Repository navigation
fix(types,console): retire the page kind jsx from PageNodeSchema.kind; the console sample moves to html (objectui#12464) - #12485
Conversation
… and move the console sample to html (objectui#12464) @objectstack/spec 18 refuses the page kind jsx (objectstack-ai/objectstack#23638). PageNodeSchema.kind drops 'jsx'; the console's sdui-jsx-preview sample authors kind 'html'. The page renderer keeps its 'jsx' arm for stored rows until the resolved spec carries the retirement; it reads kind as a widened wire value so that arm still compiles against the narrowed type. Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB Co-authored-by: Claude <noreply@anthropic.com>
…ind jsx too (objectui#12464) The zod mirror took `kind` from the spec's PageSchema by reference, so on the pinned 18.0.0-next.1 it still admitted 'jsx' and was wider than the narrowed TS face (zod-mirror-parity WiderLedger TS2322). It now picks its enum out of the spec's by reference with `.extract`, through the stripImportedDefaults boundary, identical to the spec's enum once the resolved spec carries the retirement. Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB Co-authored-by: Claude <noreply@anthropic.com>
…#12464) Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Inputs read: card #12464 (body, triage ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #12464
Clause-②: yes — the published
@object-ui/typesPageNodeSchema.kindnarrows (drops'jsx'), levelledminor(objectui levels a breaking changeminor, nevermajor)The objectui layer of objectstack-ai/objectstack#23543 family F5-jsx, which landed in
@objectstack/specas objectstack-ai/objectstack#23638 (c5dd7fce30): spec 18 refuses the page kindjsxand nameshtml.What changed
@object-ui/types, TS face.PageNodeSchema.kindis'full' | 'slotted' | 'html' | 'react'; its docblock no longer callsjsxan accepted alias. The@ts-expect-errorcomment inauthoring-nodes-11364.test.tslists the four kinds.@object-ui/types, zod face (premise correction). The card measured "no'jsx'page kind inpackages/types/src/zod/". That holds for the literal text, but the zodPageNodeSchematakeskindfrom the spec'sPageSchemaby reference, so on the pinned18.0.0-next.1it still admittedjsx. With the TS face narrowed, the zod face was wider than the TS face, andzod-mirror-parity.test.tsfailedtypestype-check with two TS2322 ("layout.zod.ts#PageNodeSchema"and"kind"not assignable tonever, fromWiderLedgerMismatchandWiderLedgerKeyDrift). The zod face now picks its enum out of the spec's by reference,stripImportedDefaults(SpecPageSchema).shape.kind.unwrap().extract(['full', 'slotted', 'html', 'react']), the wayPAGE_KIND_NODE_TYPEalready does fortype. Against specmainthis is the spec's own enum. Againstnext.1it refusesjsxatkind. A kind the spec drops fails to compile here. A ledger entry was not used because it cannot be correct on both spec versions: it would be stale on specmain.apps/console/src/sdui-jsx-preview.tsxauthorskind: 'html'; its header comment names the html tier. The extraction pin insdui-preview-page-source-query-params.test.tsreadssdui-jsx-preview.tsx:command_center:html.@object-ui/componentspage renderer: the'jsx'arm stays (half 2 deferred, below). Narrowing the type made the arm a compile error:TS2367: This comparison appears to be unintentional because the types '"full" | "slotted" | undefined' and '"jsx"' have no overlap(the components declaration build). The renderer now readskindas the stored wire value,const kind: string | undefined = schema.kind;. That is a widening annotation, not a cast. Its comment says why: a server on a spec built before the retirement can serve a storedjsxrow. Nojsxtohtmlmapping is added anywhere. Rendering is unchanged.content/docs/guide/react-pages.mdno longer says"jsx""is still accepted"; it says the alias was retired in spec 18 and to author"html"..changeset/12464-retire-page-kind-jsx.md:@object-ui/types: minor,@object-ui/console: patch(the console is published: noprivatefield).@object-ui/componentsgets no entry because its behaviour does not change.Half 2 (the renderer's
'jsx'arm): deferredThe pin reading on this tree:
packages/typesandpackages/componentsboth resolve@objectstack/spec18.0.0-next.1from the lockfile and the installed store. Itsdist/ui/index.mjsdeclareskind: z.enum(["full", "slotted", "html", "react", "jsx"])andCOMPILED_PAGE_KINDS = ["html", "jsx"].npm view @objectstack/spec@next versionanswers18.0.0-next.1(dist-tagsnext: 18.0.0-next.1,latest: 17.7.0). The published manifest carries nogitHead.The resolved spec therefore does not carry
c5dd7fce30, and the arm stays as the triage requires. The PM splits it into its own card. Pin window: until anextbuilt fromc5dd7fce30or a descendant is resolved, a storedjsxpage served by anext.1runtime still renders ashtmlthrough that arm.Verification (head
4cc23c7f7)turbo run build --filter='@object-ui/console^...' --concurrency=2: 34/34 tasks.type-checkfor@object-ui/types,@object-ui/components,@object-ui/app-shelland@object-ui/console: exit 0 each.packages/types/: 383 files, 10335 tests passed.public-contract, the app-shellpageRequiresStampdouble): 220 tests passed.packages/types/src/__tests__/page-kind-jsx-retired-12464.test.ts:Equalon the wholekindunion, a@ts-expect-erroronkind: 'jsx', and a zodsafeParserefused at pathkindwithhtmlas the control.'jsx'was re-added to the TS union and to the.extractlist. Thentsc -p tsconfig.test.jsonreportedTS2344(theEqualpin) andTS2578(the unused@ts-expect-error), and vitest reported1 failed | 1 passed(the zod pin). Restore proof:git diff HEADwas empty, and both files' hashes matched their HEAD blobs.no-explicit-anyandexhaustive-depson untouched lines). The population is the config's**/*.{ts,tsx}block, and the file count comes from--format json. The config enables no type-aware linting (noprojectServiceorproject), so these edits cannot change the verdict on any untouched file.check:phantom-deps,self-import,unreferenced-sources,doc-example-readers,handler-key-reads,side-effects-array,element-data-source-declaration,spec-symbols,action-forward-parity,designer-field-key-parity,icon-record-names,i18n-keys,i18n-drift,i18n-designer-parity,control-bytesandnew-line-citations. Also exit 0:check-doc-snippet-types.mjs(792 of 792 blocks judged, after its scoped build),check-changeset-fixed.mjsandcheck-changeset-presence.mjs. The guardcheck-governed-queue-guard.mjs --testreports NOT GOVERNED.main, which was not built in this container. The check runs on this PR. By construction, on specmainthe TSkindequals the spec's four-value enum, so the TS2430 atPageNodeSchemano longer applies, and the zod.extractis the identity there.check:spec-floors. It exits 1 withno-artifactbecause it needs a whole-workspace build, and it is the known red onmain.Acceptance notes (noted, not filed)
packages/app-shell/src/views/metadata-admin/ResourceEditPage.pageRequiresStamp-11357.test.tsx: the server double'scompiledRequiresreadsbody.kind !== 'html' && body.kind !== 'jsx', mirroringnext.1'sCOMPILED_PAGE_KINDS. It is test-only and outside this card's file surface. Carrier: the half-2 card.packages/types/src/zod/layout.zod.ts: the comment on the re-attached spec checks names anhtml/react/jsxpage, andhtml/jsxforcheckPageRequiresKind. That describesnext.1's checks. Carrier: the half-2 card.packages/components/src/renderers/layout/page.tsx: the comment abovegetJsxManifeststill reads "akind:'jsx'page carries a constrained JSXsource". Carrier: the half-2 card.sdui-jsx-preview.tsx(withsdui-jsx-preview.html, and the names in two console tests) and itspage as any. A rename touches files outside this card's surface. Carrier: none.Generated by Claude Code