diff --git a/package.json b/package.json index 7555a607efc..b026e66f3ad 100644 --- a/package.json +++ b/package.json @@ -46,9 +46,11 @@ "@embroider/compat": "patches/@embroider__compat.patch", "ember-eslint-parser": "patches/ember-eslint-parser.patch", "openai": "patches/openai.patch", + "postcss@8.5.6": "patches/postcss@8.5.6.patch", "matrix-js-sdk@38.3.0": "patches/matrix-js-sdk@38.3.0.patch", "@embroider/webpack": "patches/@embroider__webpack.patch", - "ember-source": "patches/ember-source.patch" + "ember-source": "patches/ember-source.patch", + "object-inspect": "patches/object-inspect.patch" }, "onlyBuiltDependencies": [ "@percy/core", diff --git a/packages/boxel-ui/addon/src/components/date-range-picker/index.gts b/packages/boxel-ui/addon/src/components/date-range-picker/index.gts index 5a5698f94e7..10b859d2b1d 100644 --- a/packages/boxel-ui/addon/src/components/date-range-picker/index.gts +++ b/packages/boxel-ui/addon/src/components/date-range-picker/index.gts @@ -1,4 +1,5 @@ import 'ember-power-calendar/styles'; +import 'ember-power-calendar/styles'; import { fn } from '@ember/helper'; import { on } from '@ember/modifier'; diff --git a/packages/boxel-ui/addon/src/components/multi-select/index.gts b/packages/boxel-ui/addon/src/components/multi-select/index.gts index b0d498851fb..f80f2071219 100644 --- a/packages/boxel-ui/addon/src/components/multi-select/index.gts +++ b/packages/boxel-ui/addon/src/components/multi-select/index.gts @@ -1,4 +1,5 @@ import 'ember-power-select/styles'; +import 'ember-power-select/styles'; import Component from '@glimmer/component'; import type { ComponentLike } from '@glint/template'; diff --git a/packages/boxel-ui/addon/src/components/select/index.gts b/packages/boxel-ui/addon/src/components/select/index.gts index 66fca3404fa..59cd9c075bf 100644 --- a/packages/boxel-ui/addon/src/components/select/index.gts +++ b/packages/boxel-ui/addon/src/components/select/index.gts @@ -1,4 +1,5 @@ import 'ember-power-select/styles'; +import 'ember-power-select/styles'; import Check from '@cardstack/boxel-icons/check'; import { eq } from '@cardstack/boxel-ui/helpers'; diff --git a/packages/host/.eslintrc.js b/packages/host/.eslintrc.js index c939f49028c..9f728330756 100644 --- a/packages/host/.eslintrc.js +++ b/packages/host/.eslintrc.js @@ -113,6 +113,7 @@ module.exports = { './config/**/*.js', './lib/**/*.js', './server/**/*.js', + './babel.config.cjs', './scripts/**/*.js', ], parserOptions: { diff --git a/packages/host/.gitignore b/packages/host/.gitignore index 71ad79d02ea..b17ee3146ff 100644 --- a/packages/host/.gitignore +++ b/packages/host/.gitignore @@ -1,3 +1,5 @@ +/tmp/ + # compiled output /dist/ /declarations/ diff --git a/packages/host/app/app.ts b/packages/host/app/app.ts index b638ea11e27..d67e7fa9f0d 100644 --- a/packages/host/app/app.ts +++ b/packages/host/app/app.ts @@ -5,16 +5,17 @@ import './deprecation-workflow'; import Application from '@ember/application'; import Resolver from 'ember-resolver'; import loadInitializers from 'ember-load-initializers'; -import config from '@cardstack/host/config/environment'; -import './lib/glint-embroider-workaround'; +import config from './config/environment'; import '@cardstack/boxel-ui/styles/global.css'; import '@cardstack/boxel-ui/styles/fonts.css'; import '@cardstack/boxel-ui/styles/variables.css'; +import compatModules from '@embroider/virtual/compat-modules'; + export default class App extends Application { modulePrefix = config.modulePrefix; podModulePrefix = config.podModulePrefix; - Resolver = Resolver; + Resolver = Resolver.withModules(compatModules); } -loadInitializers(App, config.modulePrefix); +loadInitializers(App, config.modulePrefix, compatModules); diff --git a/packages/host/app/config/environment.d.ts b/packages/host/app/config/environment.ts similarity index 57% rename from packages/host/app/config/environment.d.ts rename to packages/host/app/config/environment.ts index 858d85a5f14..e173f9ac82b 100644 --- a/packages/host/app/config/environment.d.ts +++ b/packages/host/app/config/environment.ts @@ -1,10 +1,30 @@ -export default config; +import { assert } from '@ember/debug'; +import loadConfigFromMeta from '@embroider/config-meta-loader'; -/** - * Type declarations for - * import config from 'my-app/config/environment' - */ -declare const config: { +const config = loadConfigFromMeta('@cardstack/host') as unknown; + +assert( + 'config is not an object', + typeof config === 'object' && config !== null, +); +assert( + 'modulePrefix was not detected on your config', + 'modulePrefix' in config && typeof config.modulePrefix === 'string', +); +assert( + 'locationType was not detected on your config', + 'locationType' in config && typeof config.locationType === 'string', +); +assert( + 'rootURL was not detected on your config', + 'rootURL' in config && typeof config.rootURL === 'string', +); +assert( + 'APP was not detected on your config', + 'APP' in config && typeof config.APP === 'object', +); + +export default config as { environment: string; modulePrefix: string; podModulePrefix: string; @@ -38,10 +58,12 @@ declare const config: { SHOW_ASK_AI?: boolean; AI_PATCHING_CORRECTNESS_CHECKS?: boolean; }; + publishedRealmDomainOverrides: string; publishedRealmBoxelSpaceDomain: string; publishedRealmBoxelSiteDomain: string; publishedRealmDomainOverrides: string; defaultSystemCardId?: string; cardSizeLimitBytes: number; fileSizeLimitBytes: number; -}; + defaultSystemCardId: string; +} & Record; diff --git a/packages/host/app/lib/glint-embroider-workaround.js b/packages/host/app/lib/glint-embroider-workaround.js deleted file mode 100644 index c635cc12836..00000000000 --- a/packages/host/app/lib/glint-embroider-workaround.js +++ /dev/null @@ -1,12 +0,0 @@ -// Glint wraps these packages but tries to use window.require to access the -// originals, which won't work under embroider with staticAddonTrees enabled. - -import * as GlimmerComponent from '@glimmer/component'; -window.define('@glimmer/component', function () { - return GlimmerComponent; -}); - -import * as Modifier from 'ember-modifier'; -window.define('ember-modifier', function () { - return Modifier; -}); diff --git a/packages/host/app/lib/public-path.ts b/packages/host/app/lib/public-path.ts index 3dbf4c838d1..4f40a032cf0 100644 --- a/packages/host/app/lib/public-path.ts +++ b/packages/host/app/lib/public-path.ts @@ -1,7 +1 @@ -import config from '@cardstack/host/config/environment'; - (globalThis as any).__bootStart = performance.now(); -const { hostsOwnAssets, assetsURL } = config; - -// @ts-expect-error this is consumed by webpack to set the public asset path at runtime -__webpack_public_path__ = hostsOwnAssets ? '/' : assetsURL; diff --git a/packages/host/app/modifiers/monaco.ts b/packages/host/app/modifiers/monaco.ts index c8b431eddcf..9c609016a57 100644 --- a/packages/host/app/modifiers/monaco.ts +++ b/packages/host/app/modifiers/monaco.ts @@ -10,7 +10,6 @@ import * as MonacoSDK from 'monaco-editor'; import config from '@cardstack/host/config/environment'; import type MonacoService from '@cardstack/host/services/monaco-service'; import { createMonacoWaiterManager } from '@cardstack/host/utils/editor/monaco-test-waiter'; -import '@cardstack/requirejs-monaco-ember-polyfill'; interface Signature { Args: { diff --git a/packages/host/app/services/monaco-service.ts b/packages/host/app/services/monaco-service.ts index 47d3cdd374b..d228206669d 100644 --- a/packages/host/app/services/monaco-service.ts +++ b/packages/host/app/services/monaco-service.ts @@ -9,6 +9,14 @@ import { task } from 'ember-concurrency'; import merge from 'lodash/merge'; +// The worker suffix here is a vite feature that builds them into standalone +// worker scripts, which will be outside the main bundle in prod. +import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker'; +import CSSWorker from 'monaco-editor/esm/vs/language/css/css.worker.js?worker'; +import HTMLWorker from 'monaco-editor/esm/vs/language/html/html.worker.js?worker'; +import JSONWorker from 'monaco-editor/esm/vs/language/json/json.worker.js?worker'; +import TSWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker.js?worker'; + import type { SingleCardDocument } from '@cardstack/runtime-common'; import config from '@cardstack/host/config/environment'; @@ -28,6 +36,28 @@ export type MonacoSDK = typeof _MonacoSDK; export type IStandaloneCodeEditor = _MonacoSDK.editor.IStandaloneCodeEditor; const { serverEchoDebounceMs } = config; +( + globalThis as unknown as { MonacoEnvironment: _MonacoSDK.Environment } +).MonacoEnvironment = { + getWorker: function (_workerId, label) { + switch (label) { + case 'json': + return new JSONWorker(); + case 'css': + case 'scss': + case 'less': + return new CSSWorker(); + case 'typescript': + case 'javascript': + return new TSWorker(); + case 'html': + case 'handlebars': + return new HTMLWorker(); + default: + return new EditorWorker(); + } + }, +}; export default class MonacoService extends Service { #ready: Promise; @@ -60,9 +90,15 @@ export default class MonacoService extends Service { } private loadMonacoSDK = task(async () => { - // @ts-expect-error: dynamic import without types - await import('@cardstack/requirejs-monaco-ember-polyfill'); const monaco = await import('monaco-editor'); + + // There are tests that rely on this. In older Ember versions, Monaco + // installed itself as a global automatically because it does that when it + // detects the presence of an AMD in the environment. Newer Ember versions + // (with Vite) don't use AMD anymore, so Monaco stopped putting itself on + // this global. + (globalThis as any).monaco = monaco; + monaco.languages.typescript.javascriptDefaults.setCompilerOptions( this.defaultCompilerOptions(monaco), ); diff --git a/packages/host/babel.config.cjs b/packages/host/babel.config.cjs new file mode 100644 index 00000000000..62743b404b5 --- /dev/null +++ b/packages/host/babel.config.cjs @@ -0,0 +1,53 @@ +const { + babelCompatSupport, + templateCompatSupport, +} = require('@embroider/compat/babel'); + +module.exports = { + plugins: [ + [ + '@babel/plugin-transform-typescript', + { + allExtensions: true, + onlyRemoveTypeImports: true, + allowDeclareFields: true, + }, + ], + [ + 'babel-plugin-ember-template-compilation', + { + compilerPath: 'ember-source/dist/ember-template-compiler.js', + enableLegacyModules: [ + 'ember-cli-htmlbars', + 'ember-cli-htmlbars-inline-precompile', + 'htmlbars-inline-precompile', + ], + transforms: [ + ...templateCompatSupport(), + 'glimmer-scoped-css/ast-transform', + ], + }, + ], + [ + 'module:decorator-transforms', + { + runtime: { + import: require.resolve('decorator-transforms/runtime-esm'), + }, + }, + ], + [ + '@babel/plugin-transform-runtime', + { + absoluteRuntime: __dirname, + useESModules: true, + regenerator: false, + }, + ], + ...babelCompatSupport(), + ], + + generatorOpts: { + compact: false, + }, +}; diff --git a/packages/host/config/targets.js b/packages/host/config/targets.js index e5e92faca20..1e48e0599f9 100644 --- a/packages/host/config/targets.js +++ b/packages/host/config/targets.js @@ -8,5 +8,4 @@ const browsers = [ module.exports = { browsers, - node: 'current', }; diff --git a/packages/host/ember-cli-build.js b/packages/host/ember-cli-build.js index 0e599e62264..69c4bcb6741 100644 --- a/packages/host/ember-cli-build.js +++ b/packages/host/ember-cli-build.js @@ -1,114 +1,23 @@ 'use strict'; - const EmberApp = require('ember-cli/lib/broccoli/ember-app'); const { compatBuild } = require('@embroider/compat'); -const { Webpack } = require('@embroider/webpack'); -const webpack = require('webpack'); -const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); -const MomentLocalesPlugin = require('moment-locales-webpack-plugin'); -const { GlimmerScopedCSSWebpackPlugin } = require('glimmer-scoped-css/webpack'); -const withSideWatch = require('./lib/with-side-watch'); -const Funnel = require('broccoli-funnel'); -const { BoxelUIChecksumPlugin } = require('./lib/build/package-dist-checksums'); -module.exports = function (defaults) { +module.exports = async function (defaults) { + const { buildOnce } = await import('@embroider/vite'); + const app = new EmberApp(defaults, { - trees: { - app: withSideWatch('app', { - watching: ['../runtime-common', '../boxel-ui/addon'], - }), - }, 'ember-cli-babel': { enableTypeScriptTransform: true, disableDecoratorTransforms: true, }, babel: { plugins: [ - [require.resolve('decorator-transforms')], require.resolve('ember-concurrency/async-arrow-task-transform'), ], }, }); - - return compatBuild(app, Webpack, { - staticAddonTrees: true, - staticAddonTestSupportTrees: true, - staticHelpers: true, - - staticComponents: true, - - staticModifiers: true, + return compatBuild(app, buildOnce, { + staticInvokables: true, staticAppPaths: ['lib'], - extraPublicTrees: [ - new Funnel('node_modules/content-tag/pkg', { - include: ['standalone.js', 'standalone/*'], - destDir: 'assets/content-tag', - }), - ], - packagerOptions: { - ...{ - webpackConfig: { - devtool: 'source-map', - module: { - rules: [ - { - test: /\.ttf$/, - type: 'asset/inline', - }, - { - test: /\.woff2$/, - type: 'asset', - }, - { - test: /\.png$/, - type: 'asset', - }, - { - test: /\.webp$/, - type: 'asset', - }, - { - test: /\.otf$/, - type: 'asset', - }, - ], - }, - plugins: [ - new GlimmerScopedCSSWebpackPlugin(), - new MonacoWebpackPlugin(), - new webpack.IgnorePlugin({ - resourceRegExp: /^https:\/\/cardstack\.com\/base/, - }), - new MomentLocalesPlugin({ - // 'en' is built into moment and cannot be removed. This strips the others. - localesToKeep: [], - }), - // boxel-ui packages dist checksum needed for the realm server to figure out if boxel-ui changed, and trigger a reindex of cards that use it (to update cards' prerendered HTML) - new BoxelUIChecksumPlugin(__dirname), - ], - externals: { - 'content-tag': 'ContentTagGlobal', - }, - resolve: { - fallback: { - fs: false, - os: false, - path: require.resolve('path-browserify'), - crypto: require.resolve('crypto-browserify'), - stream: require.resolve('stream-browserify'), - assert: require.resolve('assert/'), - }, - alias: { - // Exclude the rust-crypto module from the bundle because we don't use it - 'matrix-js-sdk$': 'matrix-js-sdk/src/browser-index.ts', - './rust-crypto/index.ts': false, - }, - }, - node: { - global: true, - }, - }, - }, - }, }); }; diff --git a/packages/host/app/index.html b/packages/host/index.html similarity index 63% rename from packages/host/app/index.html rename to packages/host/index.html index 345c7e7d75d..4eb632461da 100644 --- a/packages/host/app/index.html +++ b/packages/host/index.html @@ -2,17 +2,16 @@ + Boxel {{content-for "head"}} - - + + + +