Skip to content

Commit 9b8f978

Browse files
authored
feat(types)!: adopt @objectstack/spec 15.1.1; drop value-erased spec/ui …Schema re-exports (#2589)
Closes #2561. Drops the ~84 value-erased `…Schema` re-exports from @object-ui/types (decision (a)) and bumps @objectstack/spec to ^15.1.1 across all 14 workspace package.jsons — the floor that guarantees framework#3021's z.toJSONSchema/lazySchema-proxy fix. Guardrail + Page/View inspector schema tests added. Full suite 6852 passed / 0 failed.
1 parent 195a651 commit 9b8f978

21 files changed

Lines changed: 305 additions & 135 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@object-ui/types': major
3+
---
4+
5+
Adopt `@objectstack/spec` 15 across the workspace and drop the value-erased `…Schema` re-exports from `@object-ui/types` (#2561).
6+
7+
**Removed exports.** `packages/types` re-exported the `@objectstack/spec/ui` surface inside `export type { … }` blocks, and those blocks included the zod validators (`DndConfigSchema`, `SpecFormViewSchema`, `ThemeModeSchema`, … 84 names in total). Under `export type` a zod value is erased, so importing any of them as a value from `@object-ui/types` silently yielded `undefined` at runtime. Per the #2561 decision (option a) the schema names are removed from the public surface instead of being converted to value re-exports — consumers that need the runtime validators import them from `@objectstack/spec/ui` directly. The inferred types (`DndConfig`, `SpecFormView`, …) are unchanged, and the genuine value re-exports (`defineStack`, `ObjectStackSchema`, `SpecReportSchema`, …) keep working. `BreakpointColumnMapSchema` / `BreakpointOrderMapSchema` are dropped without a type replacement (the spec exports no companion inferred type). A guardrail test (`spec-ui-schema-reexports.test.ts`) pins the contract.
8+
9+
**Spec 15.** Every workspace package now depends on `@objectstack/spec` ^15.1.1. The `/ui` export-name set is identical to 14.6; the spec-level breaking change is ADR-0089 D3a — `FormFieldSchema` / `FormSectionSchema` / `PageComponentSchema` are `.strict()` and reject undeclared keys, which the workspace test suite passes under. The floor is 15.1.1 (not 15.0.0) because D3a's `.strict().transform(…)` pipes crashed `z.toJSONSchema` over spec's lazySchema proxies (`Cannot set properties of undefined (setting 'ref')`), breaking Studio's spec-derived Page/View inspector schemas; fixed upstream in framework#3021, which shipped in spec 15.1.1. New `view-schema.test.ts` pins the View-inspector derivation (previously untested — it degraded silently).

apps/console/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
"@object-ui/react": "workspace:*",
8989
"@object-ui/types": "workspace:*",
9090
"@objectstack/client": "^14.6.0",
91-
"@objectstack/spec": "^15.1.0",
91+
"@objectstack/spec": "^15.1.1",
9292
"@tailwindcss/postcss": "^4.3.2",
9393
"@tailwindcss/typography": "^0.5.20",
9494
"@testing-library/jest-dom": "^6.9.1",

apps/site/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"@object-ui/plugin-view": "workspace:*",
3232
"@object-ui/react": "workspace:*",
3333
"@object-ui/types": "workspace:*",
34-
"@objectstack/spec": "^15.1.0",
34+
"@objectstack/spec": "^15.1.1",
3535
"fumadocs-core": "16.11.3",
3636
"fumadocs-mdx": "15.0.13",
3737
"fumadocs-ui": "16.11.3",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
"devDependencies": {
6262
"@changesets/cli": "^2.31.0",
6363
"@eslint/js": "^10.0.1",
64-
"@objectstack/spec": "^15.1.0",
64+
"@objectstack/spec": "^15.1.1",
6565
"@playwright/test": "^1.61.1",
6666
"@testing-library/dom": "^10.4.1",
6767
"@testing-library/jest-dom": "^6.9.1",

packages/app-shell/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"@object-ui/types": "workspace:*",
5151
"@objectstack/formula": "^14.6.0",
5252
"@objectstack/lint": "^14.6.0",
53-
"@objectstack/spec": "^15.1.0",
53+
"@objectstack/spec": "^15.1.1",
5454
"@sentry/react": "^10.65.0",
5555
"jsonc-parser": "^3.3.1",
5656
"lucide-react": "^1.24.0",
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import { describe, it, expect } from 'vitest';
4+
import {
5+
getListVariantSchema,
6+
getFormVariantSchema,
7+
getListColumnSchema,
8+
getViewForm,
9+
} from './view-schema';
10+
11+
/**
12+
* Regression for objectui#2561: the View inspector's spec-derived JSONSchema
13+
* had no test, so when spec 15 (ADR-0089 D3a) turned FormFieldSchema into a
14+
* `.strict().transform(…)` pipe and crashed `z.toJSONSchema` over the
15+
* lazySchema proxy (fixed upstream in framework#3021), the inspector degraded
16+
* silently. Pin the derivation like page-schema.test.ts does for pages.
17+
*/
18+
describe('view-schema (spec-derived View authoring metadata)', () => {
19+
it('derives the list-variant JSONSchema from the spec ViewSchema', () => {
20+
const schema = getListVariantSchema();
21+
expect(schema).toBeTruthy();
22+
expect(JSON.stringify(schema)).toContain('kanban');
23+
});
24+
25+
it('derives the form-variant JSONSchema (recursive strict FormFieldSchema)', () => {
26+
const schema = getFormVariantSchema();
27+
expect(schema).toBeTruthy();
28+
expect(JSON.stringify(schema)).toContain('sections');
29+
});
30+
31+
it('derives the ListColumn JSONSchema', () => {
32+
expect(getListColumnSchema()).toBeTruthy();
33+
});
34+
35+
it('prunes inspector-owned fields from the authoring form', () => {
36+
const form = getViewForm();
37+
if (form) {
38+
const declared = new Set<string>();
39+
for (const s of form.sections ?? []) {
40+
for (const f of s.fields ?? []) {
41+
declared.add(typeof f === 'string' ? f : (f as any)?.field);
42+
}
43+
}
44+
for (const owned of ['columns', 'data', 'name']) {
45+
expect(declared.has(owned)).toBe(false);
46+
}
47+
}
48+
});
49+
});

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"dependencies": {
3434
"@object-ui/types": "workspace:*",
3535
"@objectstack/formula": "^14.6.0",
36-
"@objectstack/spec": "^15.1.0",
36+
"@objectstack/spec": "^15.1.1",
3737
"lodash": "^4.18.1",
3838
"zod": "^4.4.3"
3939
},

packages/plugin-detail/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
},
3333
"dependencies": {
3434
"@object-ui/i18n": "workspace:*",
35-
"@objectstack/spec": "^15.1.0",
35+
"@objectstack/spec": "^15.1.1",
3636
"lucide-react": "^1.24.0"
3737
},
3838
"peerDependencies": {

packages/plugin-form/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"@object-ui/permissions": "workspace:*",
2828
"@object-ui/react": "workspace:*",
2929
"@object-ui/types": "workspace:*",
30-
"@objectstack/spec": "^15.1.0",
30+
"@objectstack/spec": "^15.1.1",
3131
"lucide-react": "^1.24.0"
3232
},
3333
"peerDependencies": {

packages/plugin-gantt/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"@object-ui/plugin-detail": "workspace:*",
3939
"@object-ui/react": "workspace:*",
4040
"@object-ui/types": "workspace:*",
41-
"@objectstack/spec": "^15.1.0",
41+
"@objectstack/spec": "^15.1.1",
4242
"lucide-react": "^1.24.0",
4343
"qrcode": "^1.5.4",
4444
"sonner": "^2.0.7"

0 commit comments

Comments
 (0)