fix: npx emdash types crashes due to schema envelope mismatch#1458
Conversation
🦋 Changeset detectedLatest commit: 83c2622 The changes in this PR will be included in the next version bump. This PR includes changesets to release 14 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 |
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/auth-atproto
@emdash-cms/blocks
@emdash-cms/cloudflare
@emdash-cms/contentful-to-portable-text
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/plugin-cli
@emdash-cms/plugin-types
@emdash-cms/registry-client
@emdash-cms/registry-lexicons
@emdash-cms/sandbox-workerd
@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-field-kit
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
There was a problem hiding this comment.
The approach is sound: the /schema JSON endpoint was the only API route returning un-enveloped JSON, which broke EmDashClient.request()'s assumption that every successful response is shaped { data: T }. Wrapping the payload with apiSuccess() fixes the npx emdash types crash and aligns the route with its siblings. The ?format=typescript branch and X-Schema-Version header are correctly preserved.
I checked the route change, the client contract, sibling schema endpoints, and the new tests. The unit and integration tests cover the route envelope, schemaExport() returning populated data, schemaTypes() remaining raw text, and error propagation. No logic bugs or regressions were found in the implementation.
The one gap is a missing changeset for the published packages/core package. CONTRIBUTING.md and AGENTS.md require one for every published-package behavior change.
What does this PR do?
npx emdash typescrashes withCannot read properties of undefined (reading 'collections')against any instance (deployed and local dev — reproduced on 0.15.0 and 0.17.2). Root cause is an envelope inconsistency.EmDashClient.request()(packages/core/src/client/index.ts:778-782) returnsjson.datafor every response, andschemaExport()(client/index.ts:389-391) goes throughrequest. But the/_emdash/api/schemaroute (packages/core/src/astro/routes/api/schema/index.ts:92-95) returns the schema un-enveloped as{ ...schemaExport, version }with nodatawrapper. Soclient.schemaExport()returnsundefined, and the CLItypescommand (packages/core/src/cli/commands/types.ts:42-43) dereferencesschema.collections.lengthand throws. Sibling schema endpoints (e.g./schema/collections) do use the{ success, data }envelope, confirming the JSON-schema route is the outlier.Make the JSON
/schemaroute consistent with the rest of the API by wrapping its body in the standard{ success: true, data: { ...schemaExport, version } }envelope (keep the?format=typescriptbranch andX-Schema-Versionheader unchanged, sinceschemaTypes()usesrequestRawand reads text directly). This restores the contractrequest()expects soschemaExport()returns the schema object. Verify no other caller depends on the un-enveloped JSON shape; the only consumers areschemaExport()(CLI) and any directcurl, and enveloping is the documented norm. If enveloping the route risks an external contract, the fallback is to switchschemaExport()torequestRaw+ manual parse, but route-side enveloping is preferred for cross-endpoint consistency.Closes #1188
Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change)pnpm formathas been runAI-generated code disclosure
Screenshots / test output
schemaExport()returns an object with a populatedcollectionsarray against the enveloped route.versionfield is preserved in the returned schema object.schemaTypes()(?format=typescript) still returns raw TS text, unaffected by the envelope change.AI was used for assistance.