diff --git a/packages/api/index.ts b/packages/api/index.ts index dbebdd3fb..57afaf51d 100644 --- a/packages/api/index.ts +++ b/packages/api/index.ts @@ -26,6 +26,7 @@ export interface Cell { push(...value: T extends (infer U)[] ? U[] : never): void; equals(other: Cell): boolean; key(valueKey: K): Cell; + resolveAsCell(): Cell; } // Cell type with only public methods diff --git a/packages/runner/src/cell.ts b/packages/runner/src/cell.ts index d4c9b1d9c..4abd2488d 100644 --- a/packages/runner/src/cell.ts +++ b/packages/runner/src/cell.ts @@ -73,8 +73,8 @@ import { ContextualFlowControl } from "./cfc.ts"; * @returns {void} * * @method push Adds an item to the end of an array cell. - * @param {U | Cell} value - The value to add, where U is - * the array element type. + * @param {U | Cell} value - The value to add, where U is the array element + * type. * @returns {void} * * @method equals Compares two cells for equality. @@ -102,6 +102,10 @@ import { ContextualFlowControl } from "./cfc.ts"; * @method sync Syncs the cell to the storage. * @returns {Promise} * + * @method resolveAsCell Resolves the cell to a new cell with the resolved link. + * Equivalent to `cell.getAsSchema().get()` + * @returns {Cell} + * * @method getAsQueryResult Returns a query result for the cell. * @param {Path} path - The optional path to follow. * @param {ReactivityLog} log - Optional reactivity log. @@ -197,6 +201,7 @@ declare module "@commontools/api" { withTx(tx?: IExtendedStorageTransaction): Cell; sink(callback: (value: Readonly) => Cancel | undefined | void): Cancel; sync(): Promise> | Cell; + resolveAsCell(): Cell; getAsQueryResult( path?: Readonly, tx?: IExtendedStorageTransaction, @@ -646,6 +651,11 @@ export class RegularCell implements Cell { return this.runtime.storageManager.syncCell(this); } + resolveAsCell(): Cell { + const link = resolveLink(this.runtime.readTx(this.tx), this.link); + return createCell(this.runtime, link, this.tx, true, this.synced); + } + getAsQueryResult( path?: Readonly, tx?: IExtendedStorageTransaction, diff --git a/packages/runner/test/cell.test.ts b/packages/runner/test/cell.test.ts index 2477944c4..fbafcdea5 100644 --- a/packages/runner/test/cell.test.ts +++ b/packages/runner/test/cell.test.ts @@ -3642,4 +3642,33 @@ describe("Cell success callbacks", () => { expect(link0.id).not.toBe(link1.id); }); }); + + describe("resolveAsCell", () => { + it("should resolve a cell reference to the actual cell", () => { + const innerCell = runtime.getCell( + space, + "inner-cell", + { type: "number" }, + tx, + ); + innerCell.set(42); + + const outerCell = runtime.getCell<{ inner: unknown }>( + space, + "outer-cell", + { + type: "object", + properties: { + inner: { type: "number" }, + }, + }, + tx, + ); + outerCell.set({ inner: innerCell }); + + const resolvedCell = outerCell.key("inner").resolveAsCell(); + + expect(resolvedCell.equals(innerCell)).toBe(true); + }); + }); }); diff --git a/packages/static/assets/types/commontools.d.ts b/packages/static/assets/types/commontools.d.ts index 8bc1fa8ec..c78ea1b7a 100644 --- a/packages/static/assets/types/commontools.d.ts +++ b/packages/static/assets/types/commontools.d.ts @@ -17,6 +17,7 @@ export interface Cell { push(...value: T extends (infer U)[] ? U[] : never): void; equals(other: Cell): boolean; key(valueKey: K): Cell; + resolveAsCell(): Cell; } export interface Stream { send(event: T): void;