Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
44cc4d3
initial step of refactoring builder API to be created by a factory + …
seefeldb Jun 6, 2025
8c4f7fa
deno.lock change, not sure this is right
seefeldb Jun 6, 2025
2a712d9
let's just go back to `any` here, this is wonky
seefeldb Jun 6, 2025
2ac3fe2
builder/interface.ts and builder/schema-to-ts.ts are now together ent…
seefeldb Jun 6, 2025
27de921
lots of types fixes for previous change
seefeldb Jun 6, 2025
d8837ba
more type fixes
seefeldb Jun 6, 2025
14b319b
remove this syntax for now
seefeldb Jun 6, 2025
82ca353
remove extraneous parameter for createBuilder
seefeldb Jun 6, 2025
9c614de
add back ability to set schema with cell/opaqueRef
seefeldb Jun 7, 2025
f2fe26a
fix more tests
seefeldb Jun 7, 2025
79ef937
export opaqueRef directly still, for internal use outside of recipes
seefeldb Jun 7, 2025
6074063
partially fix test
seefeldb Jun 7, 2025
c630bc1
import type with `type` annotation
seefeldb Jun 9, 2025
6f97b4d
interface is now truly just the public interface. users should only i…
seefeldb Jun 9, 2025
d6398e3
separated imports in other places
seefeldb Jun 9, 2025
4d9e789
fix misaligned exports
seefeldb Jun 9, 2025
f11897e
removed Mutable from interface
seefeldb Jun 9, 2025
255a1cb
change all recipes to import from /interface.
seefeldb Jun 9, 2025
70139fe
redo use of SchemaWithoutCell in the right places, this fixed the tests
seefeldb Jun 9, 2025
0206774
need Mutable<> after all, so duplicating here to keep interface.ts an…
seefeldb Jun 9, 2025
fe6edc7
recipe also needs SchemaWithoutCell
seefeldb Jun 9, 2025
65c14ca
and recipe needs that also for the recipe function!
seefeldb Jun 9, 2025
1300446
fix recipes
seefeldb Jun 9, 2025
2a226d6
move getRecipeEnvironment to public environment
seefeldb Jun 9, 2025
5c4f4b7
revert to original deno.lock
seefeldb Jun 9, 2025
2bb1e50
also exports constants via builder!
seefeldb Jun 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
builder/interface.ts and builder/schema-to-ts.ts are now together ent…
…irely self contained!
  • Loading branch information
seefeldb committed Jun 9, 2025
commit 2ac3fe231ddd0c103340ae14342d5063590fefa1
23 changes: 0 additions & 23 deletions packages/builder/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,6 @@
// Re-export all public API from interface for backward compatibility
export * from "./interface.ts";

// Re-export builders with actual implementations for backward compatibility
export { opaqueRef as cell, stream } from "./opaque-ref.ts";
export {
byRef,
compute,
createNodeFactory,
derive,
handler,
lift,
render,
} from "./module.ts";
export {
recipe,
} from "./recipe.ts";
export {
type BuiltInCompileAndRunParams,
type BuiltInCompileAndRunState,
Expand Down Expand Up @@ -74,12 +60,3 @@ export {
// Export the factory function
export { createBuilder } from "./factory.ts";
export type { BuilderFunctions, BuilderRuntime } from "./interface.ts";

// Export createCell function placeholder
export function createCell(...args: any[]): any {
throw new Error(
"createCell requires a runtime context. " +
"This function should be overridden during recipe evaluation. " +
"If you're seeing this error, it means createCell is being called outside of a recipe context.",
);
}
175 changes: 139 additions & 36 deletions packages/builder/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,20 @@
* This module exports only the types and functions that are part of the public API.
*/

// Import types for use in this file
import type {
JSONSchema,
Module,
ModuleFactory,
Opaque,
OpaqueRef,
RecipeFactory,
} from "./types.ts";
import type { Mutable } from "@commontools/utils/types";

import type { Schema } from "./schema-to-ts.ts";

// Re-export core types needed by recipes
export type {
Frame,
JSONObject,
JSONSchema,
// JSON types
JSONValue,
// Module and Recipe types
Module,
// Factory types
ModuleFactory,
Mutable,
Node,
NodeFactory,
// Core data types
Opaque,
OpaqueRef,
Recipe,
RecipeFactory,
Static,
} from "./types.ts";

// Export symbols as both type and value
export { ID, NAME, TYPE, UI } from "./types.ts";
export const ID: unique symbol = Symbol("ID, unique to the context");
export const ID_FIELD: unique symbol = Symbol(
"ID_FIELD, name of sibling that contains id",
);

// Should be Symbol("UI") or so, but this makes repeat() use these when
// iterating over recipes.
export const TYPE = "$TYPE";
export const NAME = "$NAME";
export const UI = "$UI";

// Re-export Schema type
export type { Schema } from "./schema-to-ts.ts";
Expand All @@ -48,9 +25,6 @@ export type { Schema } from "./schema-to-ts.ts";
export { schema } from "./schema-to-ts.ts";
export { AuthSchema } from "./schema-lib.ts";

// Re-export spell utilities
export { $, event, select, Spell } from "./spell.ts";

// Cell type with only public methods
export interface Cell<T = any> {
// Public methods available in spell code and system
Expand All @@ -68,6 +42,135 @@ export interface Stream<T> {
send(event: T): void;
}

export type OpaqueRef<T> =
& OpaqueRefMethods<T>
& (T extends Array<infer U> ? Array<OpaqueRef<U>>
: T extends object ? { [K in keyof T]: OpaqueRef<T[K]> }
: T);

// Any OpaqueRef is also an Opaque, but can also have static values.
// Use Opaque<T> in APIs that get inputs from the developer and use OpaqueRef
// when data gets passed into what developers see (either recipe inputs or
// module outputs).
export type Opaque<T> =
| OpaqueRef<T>
| (T extends Array<infer U> ? Array<Opaque<U>>
: T extends object ? { [K in keyof T]: Opaque<T[K]> }
: T);

// OpaqueRefMethods type with only public methods
export interface OpaqueRefMethods<T> {
get(): OpaqueRef<T>;
set(value: Opaque<T> | T): void;
key<K extends keyof T>(key: K): OpaqueRef<T[K]>;
setDefault(value: Opaque<T> | T): void;
setName(name: string): void;
setSchema(schema: JSONSchema): void;
map<S>(
fn: (
element: T extends Array<infer U> ? Opaque<U> : Opaque<T>,
index: Opaque<number>,
array: T,
) => Opaque<S>,
): Opaque<S[]>;
}

// Factory types

// TODO(seefeld): Subset of internal type, just enough to make it
// differentiated. But this isn't part of the public API, so we need to find a
// different way to handle this.
export interface Recipe {
argumentSchema: JSONSchema;
resultSchema: JSONSchema;
}
export interface Module {
type: "ref" | "javascript" | "recipe" | "raw" | "isolated" | "passthrough";
}

export type toJSON = {
toJSON(): unknown;
};

export type Handler<T = any, R = any> = Module & {
with: (inputs: Opaque<T>) => OpaqueRef<R>;
};

export type NodeFactory<T, R> =
& ((inputs: Opaque<T>) => OpaqueRef<R>)
& (Module | Handler | Recipe)
& toJSON;

export type RecipeFactory<T, R> =
& ((inputs: Opaque<T>) => OpaqueRef<R>)
& Recipe
& toJSON;

export type ModuleFactory<T, R> =
& ((inputs: Opaque<T>) => OpaqueRef<R>)
& Module
& toJSON;

export type HandlerFactory<T, R> =
& ((inputs: Opaque<T>) => OpaqueRef<R>)
& Handler<T, R>
& toJSON;

// JSON types

export type JSONValue =
| null
| boolean
| number
| string
| JSONArray
| JSONObject & IDFields;

export interface JSONArray extends ArrayLike<JSONValue> {}

export interface JSONObject extends Record<string, JSONValue> {}

// Annotations when writing data that help determine the entity id. They are
// removed before sending to storage.
export interface IDFields {
[ID]?: unknown;
[ID_FIELD]?: unknown;
}

// TODO(@ubik2) When specifying a JSONSchema, you can often use a boolean
// This is particularly useful for specifying the schema of a property.
// That will require reworking some things, so for now, I'm not doing it
export type JSONSchema = {
readonly [ID]?: unknown;
readonly [ID_FIELD]?: unknown;
readonly type?:
| "object"
| "array"
| "string"
| "integer"
| "number"
| "boolean"
| "null";
readonly properties?: Readonly<Record<string, JSONSchema>>;
readonly description?: string;
readonly default?: Readonly<JSONValue>;
readonly title?: string;
readonly example?: Readonly<JSONValue>;
readonly required?: readonly string[];
readonly enum?: readonly string[];
readonly items?: Readonly<JSONSchema>;
readonly $ref?: string;
readonly $defs?: Readonly<Record<string, JSONSchema>>;
readonly asCell?: boolean;
readonly asStream?: boolean;
readonly anyOf?: readonly JSONSchema[];
readonly additionalProperties?: Readonly<JSONSchema> | boolean;
readonly ifc?: { classification?: string[]; integrity?: string[] }; // temporarily used to assign labels like "confidential"
};

export { type Mutable };
export type JSONSchemaMutable = Mutable<JSONSchema>;

// Built-in types
export interface BuiltInLLMParams {
messages?: string[];
Expand Down
3 changes: 1 addition & 2 deletions packages/builder/src/schema-to-ts.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { IDFields, JSONSchema } from "./types.ts";
import type { Cell, Stream } from "./interface.ts";
import type { Cell, IDFields, JSONSchema, Stream } from "./interface.ts";

export const schema = <T extends JSONSchema>(schema: T) => schema;

Expand Down
Loading