Conversation
These imports in app.ts were skipping a level in the package dependency graph. ember-power-select and ember-power-calendar are not dependencies of host, they're dependencies of boxel-ui. Trying to import from your dep's deps is unreliable and makes the vite depscan complain. I pushed them down into the boxel-ui components that actually pull the corresponding ember-power-* components into the project.
Under vite, we don't use an AMD loader so we won't conflict with the one in monaco.
Preview deployments |
Contributor
Author
|
The leading edge of this work that I'm investigating is why postcss is now broken in our builds. I have created a minimal reproduction that's ready to be debugged further. The presence of the embroider resolver inside rolldown breaks the behavior of how postcss sees its stubbed-for-the-browser dependencies. If you take that one line out of the vite config, postcss works. |
Contributor
Author
|
related upstream issues:
|
The embroider resolver that @embroider/vite pushes into
optimizeDeps.rolldownOptions.plugins doesn't do extension resolution
for relative requires, so postcss's `require('./terminal-highlight')`
fails during dep optimization. Handle that one case in a pre-embroider
rolldown plugin instead of patching postcss.
Upstream: embroider-build/embroider#2703
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Rolldown's chunk splitting can extract modules with module-scope logger() calls into separate shared chunks that evaluate before the host app's entry body runs setup-globals. The previous throw assumed source-order import evaluation, which the new bundler violates. Loosen logger() to no-op when _logDefinitions isn't installed yet, and add reapplyLogLevels() so setup-globals can retroactively set levels on loggers created during the early chunk phase. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
# Conflicts: # packages/host/package.json # packages/runtime-common/virtual-network.ts # pnpm-lock.yaml
Rolldown evaluates CommonJS `require()` calls through a runtime wrapper
that throws if `require` isn't present, so any Node built-in that's
reachable from a static import chain crashes the browser at module load.
Several runtime-common entry points were pulling in `source-map-js`,
`util`, and `fs` transitively:
- realm.ts: defer `transpile` (→ glimmer-scoped-css/ast-transform →
postcss → source-map-js) behind a dynamic import; only the realm
server ever calls transpileJS.
- scoped-css.ts: inline `isScopedCSSRequest` and
`decodeScopedCSSRequest` so nothing in runtime-common imports from
glimmer-scoped-css.
- index-query-engine.ts, realm-index-query-engine.ts: use the new local
scoped-css helpers.
- worker.ts: change the `stream` import to `import type` and lazy-load
`Readable` inside the Node-only nodeStream branch. stream-browserify's
module body calls `require('util')`, which fails in the browser.
Host-side consumers that previously imported `isScopedCSSRequest`
directly from glimmer-scoped-css now use the runtime-common re-export.
vite.config.mjs: alias `fs` to a tiny stub (lib/empty-fs.js) and add a
matching rolldown resolver plugin to optimizeDeps. recast's main.js
eagerly `require`s fs for a CLI helper we never invoke, and its
`"browser": { "fs": false }` field isn't honored by rolldown. The
optimizeDeps resolver is needed because resolve.alias doesn't apply
during dep pre-bundling.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Node's ESM resolver (called from dynamic import() at runtime) does not
do TypeScript extension resolution, so `await import('./transpile')`
throws ERR_MODULE_NOT_FOUND on the realm server. Static imports were
fine because ts-node transforms them at compile time, but the dynamic
import I added in 6694960 bypasses that path.
Use `./transpile.ts` explicitly — matches the existing convention in
realm-server/tests/module-syntax-test.ts and is compatible with
allowImportingTsExtensions in tsconfig. Vite's dev server and Rolldown
both handle .ts extensions in dynamic imports.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces the dynamic-import hack in realm.ts with the package.json "imports" pattern already used for #fetch and #lint-task. The browser entry is a stub that throws; the node entry is the real transpile module. This keeps glimmer-scoped-css/ast-transform + postcss out of the browser graph without crossing the ts-node CJS/ESM boundary that broke dynamic import() at runtime on the realm server. Supersedes the approaches in 6694960 and 08952f1. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Only ci-host.yaml's 20-shard host suite should run on PR #4019 while the vite migration is in progress. Revert before merging to main. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Same rationale as ci.yaml — only ci-host.yaml should run on PR #4019 during the vite migration. Revert before merging to main. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Host tests execute .gts transpilation in-browser via TestRealmAdapter, so transpile.ts (and its postcss/glimmer-scoped-css transitive deps) must bundle cleanly in the browser — earlier stub just pushed the error elsewhere. - Revert realm.ts back to a plain `./transpile` import; drop the #transpile conditional and transpile-browser.ts stub. - Resolve bare `source-map-js` to postcss's own install (pnpm keeps it nested, so the host root can't find it). - Stub Node's `url` module (alongside `fs`) with empty-fs.js; postcss guards pathToFileURL/fileURLToPath with truthy checks, so an empty module is safe. Supersedes 6694960, 08952f1, c4ea349 (approach, not each individual diff). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The vite branch's 9cd7b02 deleted packages/host/tests/serve.json and switched serve:dist to `vite preview --port 4200`. A later main→vite merge brought in Buck's Traefik wrapper (86301ac), which reintroduced a `serve --config ../tests/serve.json` invocation inside scripts/serve-dist.js. CI's start:host-dist has been failing with ENOENT on the deleted serve.json ever since. Rewrite the Traefik-aware wrapper to spawn `vite preview` instead, and move the CORS + Cache-Control: no-store headers that serve.json provided into vite.config.mjs under `preview`.
Boxel's card runtime relies on `Class.name` for user-visible text —
validation errors ("references unknown path X on Person"),
displayName fallbacks, query-field-schema diagnostics. esbuild's
minifier was mangling those to `e`/`i`/`r`, which produced garbled
errors in production and broke several integration/unit tests that
assert on the class name inside the error string:
Unit | query field schema: referencing a missing field...
Unit | query field schema: referencing nested fields...
Integration | realm: 500 error for POST polymorphic incompatible type
Integration | realm: 500 error for PATCH polymorphic incompatible type
Setting esbuild.keepNames globally applies to both the dev transform
and the build-time minifier.
Babel's internal path.resolve uses process.cwd() to convert a relative
filename into an absolute moduleName on compiled templates. In the
ember-cli/embroider browser build process.cwd() returned "/", so
`path.resolve('.', 'dir/person.gts')` yielded "/dir/person.gts". Under
vite the browser process shim differs and the leading slash was lost,
which broke the two realm-test assertions that check the moduleName
field in the compiled template.
Prepend a leading slash before calling transpileJS so the moduleName is
deterministic across node and browser. Update the realm-server card
source endpoints test to match the new convention ("/person.gts")
instead of the workspace-absolute filesystem path it happened to
receive before.
esbuild.keepNames only preserves identifiers that esbuild touches (dep
optimizer, JSX transform, etc.). Vite 8's production minifier is
oxc-minifier, invoked by Rolldown, which mangles classes declared
inside function bodies — breaking runtime Class.name introspection for
test fixtures like `class TestField1 extends FieldDef {}`.
Set build.rolldownOptions.output.keepNames so oxc-minifier emits the
__name helper that restores .name at runtime, matching the behavior
ember-cli/webpack provided before.
…tled Every other skill-menu click in commands-test.gts waits for [data-room-settled] after opening the assistant. This one didn't, so the skill menu pill wasn't rendered when the click fired. The ember-cli build happened to settle in time; vite's timing surfaces the race.
…lds) @embroider/core@4's exports map only exposes `./virtual`, not `./types/virtual` — the old subpath was valid under v3. Updating tsconfig types to the supported spelling so ember-tsc can resolve it. Also remove two duplicate fields in app/config/environment.ts that a recent main merge introduced: `publishedRealmDomainOverrides` and `defaultSystemCardId`. The optional form of defaultSystemCardId is kept because consumers (room.gts, matrix-service) already guard it as possibly undefined. These were hidden behind the TS2688 early-exit from the missing type def; resolving the subpath re-surfaces them.
…nsform
esbuild:keepNames routes .ts files through esbuild before rollup's babel
plugin, and esbuild converts class fields (x = foo()) into constructor
__publicField(this, "x", foo()) calls. That breaks ember-concurrency's
async-arrow-task-transform, which only matches ClassProperty nodes -- the
CallExpression ends up parented by AssignmentExpression after esbuild.
Name preservation is still handled by rolldownOptions.output.keepNames
through Vite 8's oxc-minifier. Letting babel do all TypeScript handling
keeps class fields intact through the async-arrow transform.
Verified: rebuilt host dist now emits
loginTask = b(() => ({ context: this, generator: f... }))
instead of the untransformed
loginTask = i(async () => { ... })
commit f53c665 normalized the debugFilename passed to transpileJS to start with a leading slash so babel's internal path.resolve produces a consistent moduleName across node and browser. But the same filename is forwarded to content-tag's Preprocessor and shows up in user-facing "Parse Error at ..." messages, where the leading slash looks wrong (users don't expect absolute paths there). Strip the leading slash just for content-tag. Babel still gets the absolute path so moduleName resolution stays deterministic. Fixes three prerender/error tests: shards 16, 18, and 20 all expected "Parse Error at broken.gts:..." but were getting "Parse Error at /broken.gts:...".
Under ember-cli-babel, an uninitialized class field like
static [primitive]: number;
would be emitted as an empty class field (equivalent to
`static [primitive] = undefined`), so `primitive in NewField` was true
at runtime. The ai-function-generation "skips over fields that can't be
recognised" test relied on that: it needs the primitive symbol to be a
runtime property so the skip path in generateJsonSchemaForContainsFields
kicks in.
Under the vite build's babel config (onlyRemoveTypeImports + decorator
transforms), the uninitialized field is stripped from the emitted class,
so `primitive in NewField` is false, the non-primitive branch runs, and
an extra `skipField: { type: "object", properties: {} }` leaks into the
schema.
Use an explicit `undefined` initializer so the class property exists at
runtime regardless of which babel pipeline compiled it.
Previously testem stringified the thrown object as `[object Object]`, hiding the underlying error. Concatenate stack/message into the log line so the actual failure is visible in CI output.
Under Vite's ESM build, `import * as QUnit from 'qunit'` yields a frozen module namespace, so assigning `QUnit.module = ...` throws "Cannot set property module of #<Object> which has only a getter". Track newly registered modules by diffing `QUnit.config.modules` around each `runTests()` call instead.
Host suite is green on the vite branch (run 24704642390 after rerunning one Monaco dynamic-import flake). Re-enable the full CI suites on PRs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
tests/serve.json was removed when host moved to vite, but the software-factory harness still spawned `npx serve --config tests/serve.json` and crashed with ENOENT in CI. Invoke `vite preview` (the same tool scripts/serve-dist.js uses) on a chosen free port instead. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ember-source's defaultId hashes template source via node's crypto module, reached through `module.require` or `globalThis.require`. The vite branch switched transpile.ts to import the ESM source entry (`ember-source/ember-template-compiler/index.js`) where neither handle exists, so defaultId falls back to `() => null`. The emitted template JSON then contains the literal `"id": null` (unquoted), which breaks realm-server card-source-endpoints-test.ts assertion 8 — the test's `/"id":\s"[^"]+"/` normalization regex only matches quoted id strings. Wrap compiler.precompile so we always pass an `id` option backed by super-fast-md5. md5 is already a runtime-common dep, works identically in node and the browser, and produces a stable 8-char token that the test regex replaces with `"<id>"` before comparing against the compiled-card fixture.
…nder patches
The vite host build has no window.requirejs.entries / _eak_seen module
registry to walk, so the page-side lookups silently failed: the render
route patch threw "render route module not found for injection" and the
RealmServerService bypass patch returned early, leaving
assertOwnRealmServer intact so cross-origin query-fallback searches never
dispatched `_federated-search` and RuntimeRealm.search was never invoked.
Reach the classes through the Ember ApplicationInstance that the
export-application-global instance-initializer exposes on
window['@cardstack/host'] and call factoryFor('service:realm-server') /
factoryFor('route:render') instead.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.