Skip to content

Commit 1dbb993

Browse files
fix(plugin-designer): NAV_TYPE_META has an entry for the spec's doc navigation item type (#10287) (#10315)
Fixes #10287 Clause-②: no ## What was wrong objectstack#19789 added a `doc` member to the spec's navigation item union. In `packages/plugin-designer/src/NavigationDesigner.tsx`, `NAV_TYPE_META` is a `Record` keyed by the spec-derived `NavigationItemType`, and it had nine entries and no `doc`. So `Spec Main Shape Gate`, which compiles objectui against `@objectstack/spec` built from objectstack `main`, failed with TS2741 on that map on `main` and on every PR head. The TS7016 errors in app-shell's `AppContent.tsx` were a knock-on effect of the failed `plugin-designer` build. ## What changed - `NAV_TYPE_META` gets a `doc` entry: `labelKey: 'appDesigner.navTypeDoc'`, `bg-blue-100 text-blue-700` (a colour none of the other nine use), and lucide `BookOpen`. - **It has to compile against two specs.** The pinned `@objectstack/spec` 17.4.0 has no `doc`, so a plain `doc:` key is an excess property there (TS2353). objectstack `main` has `doc`, so the gate fails without the key (TS2741). The map is now a `Record` keyed by `NavigationItemType | 'doc'`, which compiles against both. A comment in the code says the `| 'doc'` goes at the pin bump that ships `doc`. The map is still a `Record` over the spec-derived union, not `Partial` and not string-keyed. - `appDesigner.navTypeDoc` is added to the `useDesignerTranslation` English fallback table and to all ten locale packs, each in its own language. - Guard test `packages/plugin-designer/src/__tests__/NavigationDesigner.specNavTypes.test.tsx`: it reads the discriminants of the **installed** spec's `NavigationItemSchema` at runtime, renders one item of each type in the tree and the live preview, and asserts that the type badge shows a label and not a raw key. It checks that every spec type is in the map, not that the two sets are equal, because the map has `doc` before the pin does. Run against the pinned spec it covers 9 types. Run against a spec built from `main` it covers 10. - `doc` is **not** added to `QUICK_ADD_TYPES`. An empty `doc` item fails the spec's book-or-doc requirement, and authoring one belongs to objectui#10188. - Changeset: `@object-ui/plugin-designer` and `@object-ui/i18n` `patch`. ## Verification (every run below is on head `6f970da0`) **The gate's own path, reproduced locally.** objectstack `main` was `6bf7f1c0b441` when this was read. I made a sparse, blobless clone of it the way the workflow does, ran `pnpm --filter @objectstack/spec build`, ran `npm pack --ignore-scripts`, and ran `node scripts/spec-main-shape-gate.mjs inject` into a separate objectui worktree. The inject step re-pointed zod to 4.6.1, which is the gate's own behaviour. Then I ran a forced turbo `type-check --continue` in that worktree, with a private cache dir. | run | objectui tree | scope | result | |---|---|---|---| | RED | `8b1f0661` (origin/main) | `--filter=@object-ui/plugin-designer` (17 tasks) | `plugin-designer:type-check` fails at `NavigationDesigner.tsx(82,7)` with **TS2741** "Property 'doc' is missing". The gate's `report` step exits 1 and attributes the error to that file and to `6bf7f1c0b441`. | | GREEN | `6f970da0` (this branch) | `--filter=...@object-ui/plugin-designer` (40 tasks) | `Tasks: 40 successful, 40 total`, 0 `error TS`. The report step exits 0: "objectui type-checks against `@objectstack/spec` at that commit." | The GREEN scope is plugin-designer and **its dependents**: `plugin-designer`, `app-shell`, `console`, `example-console-starter` and `example-byo-backend-console` type-check, plus 33 builds, including the `plugin-designer` and `app-shell` builds that the failure had been hiding. **Nothing new surfaces once the build is unblocked.** I narrowed the scope on purpose: a package that does not depend on plugin-designer cannot be moved by this diff, and the full-graph run is this PR's own `Spec Main Shape Gate` check. **Pinned spec (17.4.0), normal path.** `pnpm --filter @object-ui/plugin-designer --filter @object-ui/i18n type-check` passes. Both `tsc --noEmit && tsc -p tsconfig.test.json` scripts echoed. `tsc -p tsconfig.test.json --listFiles` includes the new test file. **Ablation.** I committed the change first. `ablation-replace.mjs` deleted the `doc` entry line and verified it on disk (anchor count 1 to 0, blob `dc6cc9b5f055` to `a1ec0cb78efb`). It then restored the file to HEAD and proved the restore (the blob matches HEAD's and `git diff HEAD` is empty). | leg | with the `doc` entry | `doc` entry deleted | |---|---|---| | gate path (main spec): plugin-designer type-check | green | **TS2741** "Property 'doc' is missing" | | gate path (main spec): guard test | 11 passed | **1 failed**: "draws the `doc` type…", `TypeError: Cannot read properties of undefined (reading 'Icon')` | | pinned spec: plugin-designer type-check | green | **TS2741**, because the `Record` key now includes `'doc'` | | pinned spec: plugin-designer type-check with `\| 'doc'` removed from the key | — | **TS2353** "'doc' does not exist in type" (this shows the extra union member is needed) | **Suites, run from the repo root:** - `pnpm exec vitest run packages/plugin-designer/ packages/i18n/ packages/app-shell/src/__tests__/defaults-maps-mirror-en-pack.test.tsx`: `Test Files 94 passed (94)`, `Tests 1340 passed (1340)`. - The three files run by name (`all-locales-key-parity`, `defaults-maps-mirror-en-pack`, the guard test): `3 passed`, `57 tests passed`. **Gates, all exit 0:** - `check:i18n-keys`, `check:i18n-drift` (1 key added, 0 en values changed), `check:i18n-dead-keys` (report only; `navTypeDoc` lands in needs-review like its nine siblings, because the key is reached through the map and not through a literal `t()` call), `check:control-bytes`, `check:new-line-citations` (0 new); - `node scripts/check-changeset-presence.mjs`, `check:changeset-claims`, `check:pending-changeset-literals`; - `check:phantom-deps`, `check:unused-deps`, `check:icon-record-names`, `check:spec-symbols`, `check:test-path-roots`, `check:designer-field-key-parity`, `check:installed-pin-claims`, `check:published-tsconfig-exclude`, `check:published-dist`, `check:vi-mock-inherit`, `check:unreferenced-sources`. **Lint, narrowed to the files this PR touches:** 1. Population: `pnpm lint` is `turbo run lint`, which runs `eslint .` per package. `eslint --print-config` resolves a config for each of the 13 changed `.ts`/`.tsx` files, so none of them is ignored. 2. `eslint --no-inline-config --format json` on those 13 files reports 0 errors and 4 warnings. All 4 are in `NavigationDesigner.tsx`. The base version of that file, linted through stdin, gives the same 4 warnings, and none of them is on a changed line. 3. `eslint.config.js` does not turn on type-aware linting (no `parserOptions.project` or `projectService`), and no rule under `eslint-rules/` reads other files. So this diff cannot change the verdict on any file it does not touch. **NOT MEASURED:** - `check:eager-locale-catalogues`: PREREQUISITE NOT MET, it needs `apps/console/dist/eager-closure.json`. - `check:doc-examples`: prerequisite not met, it needs built `dist/` for about 20 packages. This diff touches no doc example. - Both are left to CI's build jobs. ## Acceptance notes - **Out of scope, as the triage recorded:** the product gaps around `doc` belong to objectui#10188, not this PR. They are the `NavigationRenderer` and `navSurface` `default:` fallthroughs, the `AppNavCanvas` `KIND_TONE` fallback, `AppCreationWizard` `TYPE_BADGE_COLORS`, the hand-written nine-member `NavigationItemTypeSchema` in `packages/types`, and quick-add or authoring of `doc` items. - **Wording now slightly out of date:** the doc comment on `NavigationItemType` in `packages/types/src/app.ts` still describes `NAV_TYPE_META` as keyed by exactly `NavigationItemType`. The point it makes (a new spec member breaks the compile loudly) still holds. The wording goes back to exact at the pin bump. It is outside this surface, so I left it. - **A hazard when reproducing the gate locally, for whoever runs it next:** turbo 2.10 shares one local cache across linked git worktrees ("using shared worktree cache"). Turbo's hash does not cover `node_modules`. So a gate reproduction in a linked worktree writes build outputs compiled against the injected spec into the cache that sibling worktrees read. The workflow's `TURBO_FORCE` bypasses cache reads but does not stop the writes. Pass `--cache-dir` pointing at a private directory. My first attempt did write 6 entries before I stopped it. I compared each of them with the same package built against the pinned spec, and all 6 are byte-identical, so nothing wrong is in the shared cache. Written by the `domain:ui` seat #1 dev agent, session `https://claude.ai/code/session_01BA3nKVUwKQJf8DBxrSVtNC`. --- _Generated by [Claude Code](https://claude.ai/code/session_01BA3nKVUwKQJf8DBxrSVtNC)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8b1f066 commit 1dbb993

14 files changed

Lines changed: 137 additions & 1 deletion

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
'@object-ui/plugin-designer': patch
3+
'@object-ui/i18n': patch
4+
---
5+
6+
fix(plugin-designer): the Navigation Designer has an entry for the spec's `doc` navigation item type
7+
8+
objectstack#19789 added a `doc` member to the spec's navigation item union (an
9+
item that targets a book and/or a doc). `NAV_TYPE_META` in `NavigationDesigner`
10+
is keyed by that spec-derived union, so objectui stopped compiling against
11+
`@objectstack/spec` built from objectstack `main`, and every row reads its badge,
12+
colour and icon from that map. The map now has a `doc` entry (a `BookOpen` icon,
13+
its own colour and the `appDesigner.navTypeDoc` label key). The key has an
14+
English fallback in the designer's defaults and a translation in all ten locale
15+
packs.
16+
17+
The map is typed `Record<NavigationItemType | 'doc', ...>` so it compiles both
18+
against the pinned `@objectstack/spec`, which predates `doc`, and against
19+
objectstack `main`. The `| 'doc'` goes away at the pin bump that ships `doc`.
20+
`doc` is not added to the quick-add buttons: an empty `doc` item fails the spec's
21+
book-or-doc requirement, and authoring one is objectui#10188.

‎packages/i18n/src/locales/ar.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,6 +1405,7 @@ const ar = {
14051405
navTypeSeparator: "فاصل",
14061406
navTypeAction: "إجراء",
14071407
navTypeComponent: "مكوّن",
1408+
navTypeDoc: "مستند",
14081409
navEditIcon: "تعديل الأيقونة",
14091410
navToggleVisible: "تبديل الرؤية",
14101411
navHidden: "مخفي",

‎packages/i18n/src/locales/de.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,7 @@ const de = {
13981398
navTypeSeparator: "Trenner",
13991399
navTypeAction: "Aktion",
14001400
navTypeComponent: "Komponente",
1401+
navTypeDoc: "Dokument",
14011402
navEditIcon: "Symbol bearbeiten",
14021403
navToggleVisible: "Sichtbarkeit umschalten",
14031404
navHidden: "Ausgeblendet",

‎packages/i18n/src/locales/en.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,6 +1647,7 @@ const en = {
16471647
navTypeSeparator: 'Separator',
16481648
navTypeAction: 'Action',
16491649
navTypeComponent: 'Component',
1650+
navTypeDoc: 'Doc',
16501651
navEditIcon: 'Edit icon',
16511652
navToggleVisible: 'Toggle visibility',
16521653
navHidden: 'Hidden',

‎packages/i18n/src/locales/es.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,6 +1402,7 @@ const es = {
14021402
navTypeSeparator: "Separador",
14031403
navTypeAction: "Acción",
14041404
navTypeComponent: "Componente",
1405+
navTypeDoc: "Documento",
14051406
navEditIcon: "Editar icono",
14061407
navToggleVisible: "Alternar visibilidad",
14071408
navHidden: "Oculto",

‎packages/i18n/src/locales/fr.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,6 +1400,7 @@ const fr = {
14001400
navTypeSeparator: "Séparateur",
14011401
navTypeAction: "Action",
14021402
navTypeComponent: "Composant",
1403+
navTypeDoc: "Document",
14031404
navEditIcon: "Modifier l'icône",
14041405
navToggleVisible: "Basculer la visibilité",
14051406
navHidden: "Masqué",

‎packages/i18n/src/locales/ja.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,7 @@ const ja = {
13981398
navTypeSeparator: "区切り",
13991399
navTypeAction: "アクション",
14001400
navTypeComponent: "コンポーネント",
1401+
navTypeDoc: "ドキュメント",
14011402
navEditIcon: "アイコンを編集",
14021403
navToggleVisible: "表示を切り替え",
14031404
navHidden: "非表示",

‎packages/i18n/src/locales/ko.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,7 @@ const ko = {
13981398
navTypeSeparator: "구분선",
13991399
navTypeAction: "작업",
14001400
navTypeComponent: "컴포넌트",
1401+
navTypeDoc: "문서",
14011402
navEditIcon: "아이콘 편집",
14021403
navToggleVisible: "가시성 토글",
14031404
navHidden: "숨김",

‎packages/i18n/src/locales/pt.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,6 +1397,7 @@ const pt = {
13971397
navTypeSeparator: "Separador",
13981398
navTypeAction: "Ação",
13991399
navTypeComponent: "Componente",
1400+
navTypeDoc: "Documento",
14001401
navEditIcon: "Editar ícone",
14011402
navToggleVisible: "Alternar visibilidade",
14021403
navHidden: "Oculto",

‎packages/i18n/src/locales/ru.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,7 @@ const ru = {
14081408
navTypeSeparator: "Разделитель",
14091409
navTypeAction: "Действие",
14101410
navTypeComponent: "Компонент",
1411+
navTypeDoc: "Документ",
14111412
navEditIcon: "Редактировать значок",
14121413
navToggleVisible: "Переключить видимость",
14131414
navHidden: "Скрыто",

0 commit comments

Comments
 (0)