Skip to content

Commit c3ae9f5

Browse files
authored
JSON Schema transformer rewrite (#1726)
* feat(schema-generator): add modular JSON Schema generator + plugin; integrate with js-runtime transformer; add unit/integration tests - New package packages/schema-generator: formatter chain (primitive/object/array/common-tools), robust generic handling, cycle detection, / policy, Date/any/unknown mapping, Default<T,V> default propagation, plugin surface - Switch js-runtime transformer to use createSchemaTransformerV2 - Add js-runtime tests: Cell/Array comparison, integration, nested wrappers, opaque decisions, fixture sanity - Remove debug logs; improve type utils and fixture compatibility Work-in-progress: finalize cycle / policy to match fixtures (only source-named defs; pure between them). * schema-generator: rewrite passes 20/20 schema fixtures; Stream<Cell<T>> flagging fixed; node-first inner generation; cleanup debug logging (CT-841) * schema-generator: handler-schema intersections merged; union literal tweak; all fixture groups green (CT-841) * tests: move opaque-ref-map fixture under schema-transform and align expected with OpaqueRef spread expansion * fixes for last two broken tests * plan for remaining refactor path * improvments to test harness * checkpoint on redoing fixtures approach to be more similar to the previous one and do full string comparison * updates to js-runtime fixtures to make them work with --show-transformed; add a couple of new test fixtures in schema-generator * remove unnecessary depth checking from cycle detection * fixes to fixtures for default export expectations; fixes to schema-generator to get all fixtures back to green * fix incorrect cycle detection issue on erased Default type * remove some test logs * fix lint/compile errors * streamline exports and delete unuseful test file * much cleanup and improvement to various formatters; one change/fix(?) to an old fixture * refactor common tools formatter * fix fixtures, or start to * improve fixture runner to do semantic equality check and fix one more bug with cycle detection of Default types * add date types fixture and fix test runner to import typescript lib types correctly * remove completed plans, update overall plan * refactor schema generator; also update many tests to account for new library loading pattern * undo unnecessary changes to intersection formatter * simplify some things in schema generator * further simplifications * doc explaining root ref promotion change to discuss * remove debug script * consolidate and simplify new tests * format checks * format md files * one more deno fmt fix * finally delete lots of old stuff * satisfy linter * remove old fixtures that are superseded by new ones; rename fixtures to use dashes instead of underscores * simplifications, comment on strategy * some cleanups * small refactor and a couple new tests * fix and move failing fixtures out of js-runtime * remove unnecessary definitions ordering * change oneOf to anyOf throughout; fmt correctly * comment for explaining behavior * use mutable version of core commontools jsonschema interface instead of making a separate schemadefinition one. extend commontools' jsonschema to have and properties * stop incorrectly entirely rejecting intersection types w call/construct signatures * better handling for various fallback cases; changed to thrown errors in many cases and added better in others * properly handle arrays of any and never types * attempt to update runner in light of json schema type changes * fix tests for new behaviors * fix formatting * re-compile commontools api after jsonschema changes * various simplifications and fixes for the common tools formatter and default type handling; not yet finished * finish simplifying common tools formatter * update complex defaults test in light of anyOf decisions * address robin's code review comments * fixes for robin's improvements to jsonschema to support booleans; typechecking works now * deno fmt
1 parent 32ff834 commit c3ae9f5

File tree

144 files changed

+5460
-3450
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

144 files changed

+5460
-3450
lines changed

deno.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"./packages/iframe-sandbox",
1212
"./packages/integration",
1313
"./packages/js-runtime",
14+
"./packages/schema-generator",
1415
"./packages/llm",
1516
"./packages/memory",
1617
"./packages/patterns",
@@ -85,6 +86,7 @@
8586
"packages/seeder/templates/",
8687
"packages/static/assets/",
8788
"packages/js-runtime/test/fixtures",
89+
"packages/schema-generator/test/fixtures",
8890
"packages/vendor-astral"
8991
]
9092
},

deno.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/api/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ export type JSONSchemaObj = {
214214
readonly readOnly?: boolean;
215215
readonly writeOnly?: boolean;
216216
readonly examples?: readonly Readonly<JSONValue>[];
217+
readonly $schema?: string;
218+
readonly $comment?: string;
217219

218220
// Common Tools extensions
219221
readonly [ID]?: unknown;

packages/js-runtime/test/fixtures/ast-transform/counter-recipe.expected.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ interface CounterState {
66
interface RecipeState {
77
value: Default<number, 0>;
88
}
9-
const increment = handler({
10-
type: "object",
11-
additionalProperties: true
12-
} as const satisfies JSONSchema, {
9+
const increment = handler({} as const satisfies JSONSchema, {
1310
type: "object",
1411
properties: {
1512
value: {
@@ -21,10 +18,7 @@ const increment = handler({
2118
} as const satisfies JSONSchema, (e, state) => {
2219
state.value.set(state.value.get() + 1);
2320
});
24-
const decrement = handler({
25-
type: "object",
26-
additionalProperties: true
27-
} as const satisfies JSONSchema, {
21+
const decrement = handler({} as const satisfies JSONSchema, {
2822
type: "object",
2923
properties: {
3024
value: {

packages/js-runtime/test/fixtures/ast-transform/event-handler-no-derive.expected.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ declare global {
77
}
88
}
99
}
10-
const handleClick = handler({
11-
type: "object",
12-
additionalProperties: true
13-
} as const satisfies JSONSchema, {
10+
const handleClick = handler({} as const satisfies JSONSchema, {
1411
type: "object",
1512
properties: {
1613
count: {

packages/js-runtime/test/fixtures/ast-transform/handler-object-literal.expected.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ interface State {
44
value: Cell<number>;
55
name?: Cell<string>;
66
}
7-
const myHandler = handler({
8-
type: "object",
9-
additionalProperties: true
10-
} as const satisfies JSONSchema, {
7+
const myHandler = handler({} as const satisfies JSONSchema, {
118
type: "object",
129
properties: {
1310
value: {

packages/js-runtime/test/fixtures/ast-transform/recipe-array-map.expected.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
/// <cts-enable />
22
import { Cell, derive, h, handler, NAME, recipe, str, UI, JSONSchema } from "commontools";
3-
const adder = handler({
4-
type: "object",
5-
additionalProperties: true
6-
} as const satisfies JSONSchema, {
3+
const adder = handler({} as const satisfies JSONSchema, {
74
type: "object",
85
properties: {
96
values: {

packages/js-runtime/test/fixtures/handler-schema/array-cell-remove-intersection.expected.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ interface Item {
66
interface ListState {
77
items: Cell<Item[]>;
88
}
9-
const removeItem = handler({
10-
type: "object",
11-
additionalProperties: true
12-
} as const satisfies JSONSchema, {
9+
const removeItem = handler({} as const satisfies JSONSchema, {
1310
type: "object",
1411
properties: {
1512
items: {
@@ -40,10 +37,7 @@ const removeItem = handler({
4037
type ListStateWithIndex = ListState & {
4138
index: number;
4239
};
43-
const removeItemAlias = handler({
44-
type: "object",
45-
additionalProperties: true
46-
} as const satisfies JSONSchema, {
40+
const removeItemAlias = handler({} as const satisfies JSONSchema, {
4741
type: "object",
4842
properties: {
4943
items: {

packages/js-runtime/test/fixtures/handler-schema/complex-nested-types.expected.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/// <cts-enable />
22
import { handler, Cell, recipe, JSONSchema } from "commontools";
3+
// Updated 2025-09-03: String literal unions now generate correct JSON Schema
4+
// (enum instead of array) due to schema-generator UnionFormatter improvements
35
interface UserEvent {
46
user: {
57
name: string;
@@ -36,10 +38,7 @@ const userHandler = handler({
3638
required: ["name", "email"]
3739
},
3840
action: {
39-
type: "array",
40-
items: {
41-
type: "string"
42-
}
41+
enum: ["create", "update", "delete"]
4342
}
4443
},
4544
required: ["user", "action"]

packages/js-runtime/test/fixtures/handler-schema/complex-nested-types.input.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/// <cts-enable />
22
import { handler, Cell, recipe } from "commontools";
33

4+
// Updated 2025-09-03: String literal unions now generate correct JSON Schema
5+
// (enum instead of array) due to schema-generator UnionFormatter improvements
46
interface UserEvent {
57
user: {
68
name: string;

0 commit comments

Comments
 (0)