diff --git a/packages/js-runtime/test/fixtures/schema-transform/recipe-with-types.expected.tsx b/packages/js-runtime/test/fixtures/schema-transform/recipe-with-types.expected.tsx
index 46c9db9e5..e16cec786 100644
--- a/packages/js-runtime/test/fixtures/schema-transform/recipe-with-types.expected.tsx
+++ b/packages/js-runtime/test/fixtures/schema-transform/recipe-with-types.expected.tsx
@@ -1,173 +1,127 @@
///
-import { recipe, handler, h, UI, NAME, str, Cell, derive, JSONSchema } from "commontools";
-// Define types using TypeScript interfaces
-interface TodoItem {
- id: string;
- text: string;
- completed: boolean;
- createdAt: Date;
+import { recipe, h, UI, NAME, Cell, Default, handler, JSONSchema } from "commontools";
+interface Item {
+ text: Default;
}
-interface TodoInput {
- todos: Cell;
+interface InputSchemaInterface {
+ title: Default;
+ items: Default- ;
}
-interface TodoOutput extends TodoInput {
- completedCount: number;
- pendingCount: number;
+interface OutputSchemaInterface extends InputSchemaInterface {
+ items_count: number;
}
-interface AddTodoEvent {
- text: string;
-}
-interface ToggleTodoEvent {
- id: string;
-}
-// Transform to schemas at compile time
+type InputEventType = {
+ detail: {
+ message: string;
+ };
+};
const inputSchema = {
type: "object",
properties: {
- todos: {
+ title: {
+ type: "string",
+ default: "untitled"
+ },
+ items: {
type: "array",
items: {
type: "object",
properties: {
- id: {
- type: "string"
- },
text: {
- type: "string"
- },
- completed: {
- type: "boolean"
- },
- createdAt: {
type: "string",
- format: "date-time"
+ default: ""
}
},
- required: ["id", "text", "completed", "createdAt"]
+ required: ["text"]
},
- asCell: true
+ default: []
}
},
- required: ["todos"],
- default: {
- todos: []
- }
+ required: ["title", "items"]
} as const satisfies JSONSchema;
const outputSchema = {
type: "object",
properties: {
- completedCount: {
+ items_count: {
type: "number"
},
- pendingCount: {
- type: "number"
+ title: {
+ type: "string",
+ default: "untitled"
},
- todos: {
+ items: {
type: "array",
items: {
type: "object",
properties: {
- id: {
- type: "string"
- },
text: {
- type: "string"
- },
- completed: {
- type: "boolean"
- },
- createdAt: {
type: "string",
- format: "date-time"
+ default: ""
}
},
- required: ["id", "text", "completed", "createdAt"]
+ required: ["text"]
},
- asCell: true
+ default: []
}
},
- required: ["completedCount", "pendingCount", "todos"]
+ required: ["items_count", "title", "items"]
} as const satisfies JSONSchema;
-const addTodoSchema = {
+// Handler that logs the message event
+const addItem = handler({
type: "object",
properties: {
- text: {
- type: "string"
+ detail: {
+ type: "object",
+ properties: {
+ message: {
+ type: "string"
+ }
+ },
+ required: ["message"]
}
},
- required: ["text"],
- title: "Add Todo",
- description: "Add a new todo item",
- examples: [{
- text: "Buy groceries"
- }]
-} as const satisfies JSONSchema;
-const toggleTodoSchema = {
+ required: ["detail"]
+} as const satisfies JSONSchema, {
type: "object",
properties: {
- id: {
- type: "string"
+ items: {
+ type: "array",
+ items: {
+ type: "object",
+ properties: {
+ text: {
+ type: "string",
+ default: ""
+ }
+ },
+ required: ["text"]
+ },
+ asCell: true
}
},
- required: ["id"],
- title: "Toggle Todo",
- description: "Toggle the completion status of a todo"
-} as const satisfies JSONSchema;
-// Handlers with full type safety
-const addTodo = handler(addTodoSchema, inputSchema, (event: AddTodoEvent, state: TodoInput) => {
- state.todos.push({
- id: Date.now().toString(),
- text: event.text,
- completed: false,
- createdAt: new Date()
- });
+ required: ["items"]
+} as const satisfies JSONSchema, (event: InputEventType, { items }: {
+ items: Cell
- ;
+}) => {
+ items.push({ text: event.detail.message });
});
-const toggleTodo = handler(toggleTodoSchema, inputSchema, (event: ToggleTodoEvent, state: TodoInput) => {
- const todos = state.todos.get();
- const todo = todos.find((t: any) => t.id === event.id);
- if (todo) {
- todo.completed = !todo.completed;
- state.todos.set(todos);
- }
-});
-export default recipe(inputSchema, outputSchema, ({ todos }) => {
- const completedCount = derive(todos, (todos: TodoItem[]) => todos.filter((t: TodoItem) => t.completed).length);
- const pendingCount = derive(todos, (todos: TodoItem[]) => todos.filter((t: TodoItem) => !t.completed).length);
+export default recipe(inputSchema, outputSchema, ({ title, items }) => {
+ const items_count = items.length;
return {
- [NAME]: str `Todo List (${pendingCount} pending)`,
+ [NAME]: title,
[UI]: (
-
-
+
{title}
+
Basic recipe
+
Items count: {items_count}
-
-
- Completed: {completedCount} | Pending: {pendingCount}
-
+
),
- todos,
- completedCount,
- pendingCount
+ title,
+ items,
+ items_count
};
});
diff --git a/packages/js-runtime/test/fixtures/schema-transform/recipe-with-types.input.tsx b/packages/js-runtime/test/fixtures/schema-transform/recipe-with-types.input.tsx
index 148540425..9efb573a0 100644
--- a/packages/js-runtime/test/fixtures/schema-transform/recipe-with-types.input.tsx
+++ b/packages/js-runtime/test/fixtures/schema-transform/recipe-with-types.input.tsx
@@ -1,127 +1,65 @@
///
-import { recipe, handler, toSchema, h, UI, NAME, str, Cell, derive } from "commontools";
+import { recipe, h, UI, NAME, toSchema, Cell, Default, handler } from "commontools";
-// Define types using TypeScript interfaces
-interface TodoItem {
- id: string;
- text: string;
- completed: boolean;
- createdAt: Date;
+interface Item {
+ text: Default;
}
-interface TodoInput {
- todos: Cell;
+interface InputSchemaInterface {
+ title: Default;
+ items: Default- ;
}
-interface TodoOutput extends TodoInput {
- completedCount: number;
- pendingCount: number;
+interface OutputSchemaInterface extends InputSchemaInterface {
+ items_count: number;
}
-interface AddTodoEvent {
- text: string;
-}
-
-interface ToggleTodoEvent {
- id: string;
-}
-
-// Transform to schemas at compile time
-const inputSchema = toSchema({
- default: { todos: [] }
-});
-
-const outputSchema = toSchema();
-
-const addTodoSchema = toSchema({
- title: "Add Todo",
- description: "Add a new todo item",
- examples: [{ text: "Buy groceries" }]
-});
-
-const toggleTodoSchema = toSchema({
- title: "Toggle Todo",
- description: "Toggle the completion status of a todo"
-});
-
-// Handlers with full type safety
-const addTodo = handler(
- addTodoSchema,
- inputSchema,
- (event: AddTodoEvent, state: TodoInput) => {
- state.todos.push({
- id: Date.now().toString(),
- text: event.text,
- completed: false,
- createdAt: new Date()
- });
+type InputEventType = {
+ detail: {
+ message: string
}
-);
+};
+
+const inputSchema = toSchema();
+const outputSchema = toSchema();
-const toggleTodo = handler(
- toggleTodoSchema,
- inputSchema,
- (event: ToggleTodoEvent, state: TodoInput) => {
- const todos = state.todos.get();
- const todo = todos.find((t: any) => t.id === event.id);
- if (todo) {
- todo.completed = !todo.completed;
- state.todos.set(todos);
- }
+// Handler that logs the message event
+const addItem = handler
+// <
+// { detail: { message: string } },
+// { items: Item[] }
+// >
+(
+ (event: InputEventType, { items }: {items: Cell
- }) => {
+ items.push({text: event.detail.message});
}
);
-export default recipe(inputSchema, outputSchema, ({ todos }) => {
- const completedCount = derive(todos, (todos: TodoItem[]) =>
- todos.filter((t: TodoItem) => t.completed).length
- );
+export default recipe(inputSchema, outputSchema, ({ title, items }) => {
+ const items_count = items.length;
- const pendingCount = derive(todos, (todos: TodoItem[]) =>
- todos.filter((t: TodoItem) => !t.completed).length
- );
-
return {
- [NAME]: str`Todo List (${pendingCount} pending)`,
+ [NAME]: title,
[UI]: (
-
-
+
{title}
+
Basic recipe
+
Items count: {items_count}
-
-
- Completed: {completedCount} | Pending: {pendingCount}
-
+
),
- todos,
- completedCount,
- pendingCount
+ title,
+ items,
+ items_count
};
});
diff --git a/packages/js-runtime/test/fixtures/schema-transform/type-to-schema.expected.ts b/packages/js-runtime/test/fixtures/schema-transform/type-to-schema.expected.ts
index c7d813ee9..57c7ab898 100644
--- a/packages/js-runtime/test/fixtures/schema-transform/type-to-schema.expected.ts
+++ b/packages/js-runtime/test/fixtures/schema-transform/type-to-schema.expected.ts
@@ -1,5 +1,5 @@
///
-import { recipe, handler, Cell, Stream, JSONSchema } from "commontools";
+import { recipe, NAME, handler, Cell, Stream, JSONSchema } from "commontools";
// Define types using TypeScript - more compact!
interface UpdaterInput {
newValues: string[];
@@ -125,3 +125,9 @@ const userSchema = {
required: ["name", "age", "tags", "metadata"],
description: "A user in the system"
} as const satisfies JSONSchema;
+export default recipe("test", (state) => {
+ return {
+ [NAME]: "test",
+ };
+});
+
diff --git a/packages/js-runtime/test/fixtures/schema-transform/type-to-schema.input.ts b/packages/js-runtime/test/fixtures/schema-transform/type-to-schema.input.ts
index 84d22dd48..3f42ef6bf 100644
--- a/packages/js-runtime/test/fixtures/schema-transform/type-to-schema.input.ts
+++ b/packages/js-runtime/test/fixtures/schema-transform/type-to-schema.input.ts
@@ -1,5 +1,5 @@
///
-import { recipe, handler, toSchema, Cell, Stream } from "commontools";
+import { recipe, NAME, handler, toSchema, Cell, Stream } from "commontools";
// Define types using TypeScript - more compact!
interface UpdaterInput {
@@ -54,4 +54,10 @@ interface User {
const userSchema = toSchema({
description: "A user in the system",
-});
\ No newline at end of file
+});
+
+export default recipe("test", (state) => {
+ return {
+ [NAME]: "test",
+ };
+});