Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 5 additions & 3 deletions builder/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isObj } from "@commontools/utils";

export const ID: symbol = Symbol("ID, unique to the context");
export const ID_FIELD: symbol = Symbol(
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",
);

Expand Down Expand Up @@ -108,9 +108,11 @@ export type JSONValue =
| boolean
| null
| JSONValue[]
| { [key: string]: JSONValue };
| { [key: string]: JSONValue } & { [ID]?: any; [ID_FIELD]?: any };

export type JSONSchema = {
readonly [ID]?: any;
readonly [ID_FIELD]?: any;
readonly type?:
| "object"
| "array"
Expand Down
49 changes: 36 additions & 13 deletions runner/src/cell.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { isStreamAlias, TYPE } from "@commontools/builder";
import { getTopFrame, ID, type JSONSchema } from "@commontools/builder";
import {
getTopFrame,
ID,
ID_FIELD,
type JSONSchema,
} from "@commontools/builder";
import { type DeepKeyLookup, type DocImpl, getDoc, isDoc } from "./doc.ts";
import {
createQueryResultProxy,
Expand Down Expand Up @@ -103,15 +108,15 @@ import { type Schema } from "@commontools/builder";
*/
export interface Cell<T> {
get(): T;
set(value: T): void;
send(value: T): void;
update(values: Partial<T>): void;
set(value: Cellify<T> | T): void;
send(value: Cellify<T> | T): void;
update<V extends Cellify<Partial<T> | Partial<T>>>(
values: V extends object ? V : never,
): void;
push(
...value: Array<
| (T extends Array<infer U> ? U : any)
| DocImpl<T extends Array<infer U> ? U : any>
| (T extends Array<infer U> ? (Cellify<U> | U | DocImpl<U>) : any)
| CellLink
| Cell<T extends Array<infer U> ? U : any>
>
): void;
equals(other: Cell<any>): boolean;
Expand Down Expand Up @@ -164,6 +169,26 @@ export interface Cell<T> {
copyTrap: boolean;
}

/**
* Cellify is a type utility that allows any part of type T to be wrapped in
* Cell<>, and allow any part of T that is currently wrapped in Cell<> to be
* used unwrapped. This is designed for use with Cell<T> method parameters,
* allowing flexibility in how values are passed.
*/
export type Cellify<T> =
// Handle existing Cell<> types, allowing unwrapping
T extends Cell<infer U> ? Cellify<U> | Cell<Cellify<U>>
// Handle arrays
: T extends Array<infer U> ? Array<Cellify<U>> | Cell<Array<Cellify<U>>>
// Handle objects (excluding null), adding optional ID fields
: T extends object ?
| ({ [K in keyof T]: Cellify<T[K]> } & { [ID]?: any; [ID_FIELD]?: any })
| Cell<
{ [K in keyof T]: Cellify<T[K]> } & { [ID]?: any; [ID_FIELD]?: any }
>
// Handle primitives
: T | Cell<T>;

export interface Stream<T> {
send(event: T): void;
sink(callback: (event: T) => Cancel | undefined | void): Cancel;
Expand Down Expand Up @@ -359,15 +384,15 @@ function createRegularCell<T>(

const self = {
get: () => validateAndTransform(doc, path, schema, log, rootSchema),
set: (newValue: T) =>
set: (newValue: Cellify<T>) =>
diffAndUpdate(
resolveLinkToAlias(doc, path, log),
newValue,
log,
getTopFrame()?.cause,
),
send: (newValue: T) => self.set(newValue),
update: (values: Partial<T>) => {
send: (newValue: Cellify<T>) => self.set(newValue),
update: (values: Cellify<Partial<T>>) => {
if (typeof values !== "object" || values === null) {
throw new Error("Can't update with non-object value");
}
Expand All @@ -378,10 +403,8 @@ function createRegularCell<T>(
},
push: (
...values: Array<
| (T extends Array<infer U> ? U : any)
| DocImpl<T extends Array<infer U> ? U : any>
| (T extends Array<infer U> ? (Cellify<U> | U | DocImpl<U>) : any)
| CellLink
| Cell<T extends Array<infer U> ? U : any>
>
) => {
// Follow aliases and references, since we want to get to an assumed
Expand Down
36 changes: 15 additions & 21 deletions runner/test/cell.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,7 @@ import { type DocImpl, getDoc, isDoc } from "../src/doc.ts";
import { isCell, isCellLink } from "../src/cell.ts";
import { isQueryResult } from "../src/query-result-proxy.ts";
import { type ReactivityLog } from "../src/scheduler.ts";
import {
getTopFrame,
ID,
JSONSchema,
popFrame,
pushFrame,
} from "@commontools/builder";
import { ID, JSONSchema, popFrame, pushFrame } from "@commontools/builder";
import { addEventHandler, idle } from "../src/scheduler.ts";
import { addCommonIDfromObjectID } from "../src/utils.ts";

Expand Down Expand Up @@ -562,7 +556,7 @@ describe("asCell with schema", () => {
},
},
required: ["name", "age", "tags", "nested"],
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const cell = c.asCell([], undefined, schema);
const value = cell.get();
Expand Down Expand Up @@ -596,7 +590,7 @@ describe("asCell with schema", () => {
},
},
required: ["id", "metadata"],
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const value = c.asCell([], undefined, schema).get();

Expand Down Expand Up @@ -643,7 +637,7 @@ describe("asCell with schema", () => {
},
},
required: ["name", "children"],
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const value = c.asCell([], undefined, schema).get();

Expand Down Expand Up @@ -700,7 +694,7 @@ describe("asCell with schema", () => {
},
},
required: ["user"],
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const cell = c.asCell([], undefined, schema);
const userCell = cell.key("user");
Expand Down Expand Up @@ -831,7 +825,7 @@ describe("asCell with schema", () => {
},
},
required: ["id", "context"],
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const cell = c.asCell([], undefined, schema);
const value = cell.get();
Expand Down Expand Up @@ -873,7 +867,7 @@ describe("asCell with schema", () => {
},
},
required: ["context"],
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const cell = c.asCell([], undefined, schema);
const value = cell.get();
Expand Down Expand Up @@ -919,7 +913,7 @@ describe("asCell with schema", () => {
},
},
required: ["context"],
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const cell = c.asCell([], undefined, schema);
const value = cell.get();
Expand Down Expand Up @@ -965,7 +959,7 @@ describe("asCell with schema", () => {
},
},
required: ["context"],
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const cell = c.asCell([], undefined, schema);
const value = cell.get();
Expand Down Expand Up @@ -1032,7 +1026,7 @@ describe("asCell with schema", () => {
},
},
required: ["context"],
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const log = { reads: [], writes: [] } as ReactivityLog;
const cell = c.asCell([], log, schema);
Expand Down Expand Up @@ -1082,7 +1076,7 @@ describe("asCell with schema", () => {
},
},
required: ["items"],
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const cell = c.asCell([], undefined, schema);
const itemsCell = cell.key("items");
Expand Down Expand Up @@ -1115,7 +1109,7 @@ describe("asCell with schema", () => {
value: { type: "number" },
},
},
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const cell = c.asCell([], undefined, schema);

Expand Down Expand Up @@ -1149,7 +1143,7 @@ describe("asCell with schema", () => {
type: "object",
properties: { anything: { asCell: true } },
},
} satisfies JSONSchema;
} as const satisfies JSONSchema;

const cell = c.asCell([], undefined, schema);

Expand Down Expand Up @@ -1226,8 +1220,8 @@ describe("asCell with schema", () => {
const schema = {
type: "array",
items: { type: "object", properties: { value: { type: "number" } } },
default: [{ [ID]: "test", "value": 10 }, { [ID]: "test2", "value": 20 }],
} as JSONSchema;
default: [{ [ID]: "test", value: 10 }, { [ID]: "test2", value: 20 }],
} as const satisfies JSONSchema;

const c = getDoc({}, "push-to-undefined-schema-stable-id", "test");
const arrayCell = c.asCell(["items"], undefined, schema);
Expand Down