Fix kysely resolve in SQLite/libSQL build#861
Conversation
Add a unit test that fails when packages/core/src/db/{sqlite,libsql,postgres}.ts use a CJS require() call to load an external. Vite preserves dynamic require() calls in the bundled SSR chunks; under pnpm's strict node_modules layout, require("kysely") then fails to resolve from the user's dist/server/chunks/ directory because kysely is only a transitive dep of emdash.
Replace require() in db/sqlite.ts and db/libsql.ts with static imports, matching the existing db/postgres.ts shape. With noExternal: ["emdash"] in the Vite SSR config, these files get bundled into the user's site dist; Vite preserves literal require() calls verbatim, and Node's CJS resolver could not find kysely (a transitive dep of emdash) from the user's dist/server/chunks/ under pnpm's strict node_modules layout.
🦋 Changeset detectedLatest commit: efaf216 The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
emdash-perf-coordinator | efaf216 | Apr 30 2026, 02:42 PM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
docs | efaf216 | Apr 30 2026, 02:43 PM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
emdash-i18n | efaf216 | Apr 30 2026, 02:43 PM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
emdash-demo-cache | efaf216 | Apr 30 2026, 02:44 PM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
emdash-playground | efaf216 | Apr 30 2026, 02:44 PM |
PR template validation failedPlease fix the following issues by editing your PR description:
See CONTRIBUTING.md for the full contribution policy. |
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/blocks
@emdash-cms/cloudflare
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
There was a problem hiding this comment.
Pull request overview
Fixes a Node SSR runtime failure in pnpm installs where SQLite/libSQL sites could crash after astro build with Cannot find module 'kysely' due to preserved CJS require() calls inside dialect runtime chunks.
Changes:
- Switch SQLite and libSQL dialect runtime adapters from CJS
require()to static ESM imports so Vite can resolve/bundle dependencies correctly. - Add a regression unit test to prevent reintroducing
require()in dialect runtime modules. - Add a patch changeset documenting the fix and its root cause.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/core/src/db/sqlite.ts | Replaces runtime require() usage with static imports for better-sqlite3 and kysely’s SqliteDialect. |
| packages/core/src/db/libsql.ts | Replaces runtime require() usage with a static import of @libsql/kysely-libsql. |
| packages/core/tests/unit/db/dialect-runtime-imports.test.ts | Adds regression coverage to ensure dialect runtime adapters don’t introduce require() calls. |
| .changeset/fix-dialect-runtime-require-kysely.md | Adds release notes for the runtime resolution fix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
What does this PR do?
Fixes "Cannot find module 'kysely'" at runtime after
astro buildfollowed byastro previewornode dist/server/entry.mjson Node deployments using SQLite or libSQL. Reproduced the issue exactly indemos/simple(samedialect_DAsZyBoz.mjschunk hash as the user's stack trace), confirmed the fix resolves it.Root cause.
packages/core/src/db/sqlite.tsandpackages/core/src/db/libsql.tsused CJSrequire("kysely")/require("better-sqlite3")/require("@libsql/kysely-libsql")— ostensibly to defer loading at config time. In practice these modules are only ever loaded at runtime viavirtual:emdash/dialect, so the deferral served no purpose:astro.config.mjsonly reachesdb/adapters.ts(the descriptor factory).The Astro integration's Vite SSR config (
packages/core/src/astro/integration/vite-config.ts:417-420) setsnoExternal: ["emdash"], which pulls emdash's runtime modules into the user'sdist/server/chunks/. Vite preserves dynamicrequire()calls verbatim in the bundled output, so the user's chunk ended up with a literalrequire("kysely"). Under pnpm's strictnode_moduleslayout,kyselyis only available atnode_modules/.pnpm/emdash@x/node_modules/kysely— Node's CJS resolver walks up fromdist/server/chunks/and never finds it.The peer file
db/postgres.tsalready used static imports and worked correctly. This change brings the SQLite/libSQL adapters in line with that shape; Vite then resolves the imports at build time and either bundles them or externalizes them through the right resolution context.Closes #741
Type of change
Checklist
pnpm typecheckpassespnpm lintpasses (pnpm --silent lint:json | jq '.diagnostics | length'→ 0)pnpm testpasses (3059 tests inpackages/core)pnpm formathas been rungit stash)emdashpatch)AI-generated code disclosure
/bonk)Reproduction
In
demos/simple(withnode 22.22.2):pnpm install,pnpm build(monorepo)cd demos/simple && pnpm run build && node ./dist/server/entry.mjscurl http://localhost:4321/_emdash/adminEmDash middleware error: Error: Cannot find module 'kysely'fromdialect_DAsZyBoz.mjs:9— same path as the user's stack trace.After the fix, the same flow boots cleanly and serves the setup wizard.
Notes for reviewer
await import()inastro/middleware.ts:15andloader.ts:222forvirtual:emdash/dialect, never at config time. The original "to defer loading" comment was protecting against a load chain that doesn't exist.@emdash-cms/cloudflare/db/{d1,do,playground}) and a separate Vite SSR branch, neither of which goes through these files.better-sqlite3: each adapter is a separate Vite chunk and only the configured one is reachable from the user's graph. The libsql adapter's staticimportof@libsql/kysely-libsql(anoptionalDependenciesentry) is the same shapedb/postgres.tshas used forpgsince it was written, and is only resolved when a site actually configureslibsql().Closes #741
github run