@@ -27,6 +27,8 @@ import { Space } from "./space.ts";
2727 * This abstracts away the paths behind an interface that e.g. the UX code or
2828 * modules that prefer cell interfaces can use.
2929 *
30+ * These methods are available in the system and in spell code:
31+ *
3032 * @method get Returns the current value of the cell.
3133 * @returns {T }
3234 *
@@ -35,35 +37,69 @@ import { Space } from "./space.ts";
3537 * @param {T } value - The new value to set.
3638 * @returns {void }
3739 *
40+ * @method update Updates multiple properties of an object cell at once.
41+ * @param {Partial<T> } values - The properties to update.
42+ * @returns {void }
43+ *
44+ * @method push Adds an item to the end of an array cell.
45+ * @param {U | DocImpl<U> | DocLink } value - The value to add, where U is the
46+ * array element type.
47+ * @returns {void }
48+ *
49+ * @method equals Compares two cells for equality.
50+ * @param {Cell<any> } other - The cell to compare with.
51+ * @returns {boolean }
52+ *
3853 * @method key Returns a new cell for the specified key path.
3954 * @param {K } valueKey - The key to access in the cell's value.
4055 * @returns {Cell<T[K]> }
4156 *
57+ * Everything below is only available in the system, not in spell code:
58+ *
59+ * @method asSchema Creates a new cell with a specific schema.
60+ * @param {JSONSchema } schema - The schema to apply.
61+ * @returns {Cell<T> } - A cell with the specified schema.
62+ *
63+ * @method withLog Creates a new cell with a specific reactivity log.
64+ * @param {ReactivityLog } log - The log to use.
65+ * @returns {Cell<T> }
66+ *
4267 * @method sink Adds a callback that is called immediately and on cell changes.
4368 * @param {function } callback - The callback to be called when the cell changes.
4469 * @returns {function } - A function to Cleanup the callback.
4570 *
46- * @method getAsProxy Returns a value proxy for the cell.
47- * @param {Path } path - The path to follow.
71+ * @method getAsQueryResult Returns a query result for the cell.
72+ * @param {Path } path - The optional path to follow.
73+ * @param {ReactivityLog } log - Optional reactivity log.
4874 * @returns {QueryResult<DeepKeyLookup<T, Path>> }
4975 *
50- * @method getAsCellReference Returns a cell reference for the cell.
76+ * @method getAsDocLink Returns a document link for the cell.
5177 * @returns {DocLink }
5278 *
53- * @method toJSON Returns a JSON pointer to the cell (not the contents!).
54- * @returns {{"/": string} }
79+ * @method getSourceCell Returns the source cell with optional schema.
80+ * @param {JSONSchema } schema - Optional schema to apply.
81+ * @returns {Cell<T & {[TYPE]: string | undefined} & {argument: any}> }
82+ *
83+ * @method toJSON Returns a serializable doclink (not the contents) to the cell.
84+ * @returns {{cell: {"/": string} | undefined, path: PropertyKey[]} }
5585 *
5686 * @method value Returns the current value of the cell.
5787 * @returns {T }
5888 *
59- * @method entityId Returns the current entity ID of the cell.
89+ * @property docLink The document link representing this cell.
90+ * @returns {DocLink }
91+ *
92+ * @property entityId Returns the current entity ID of the cell.
6093 * @returns {EntityId | undefined }
94+ *
95+ * @property schema Optional schema for the cell.
96+ * @returns {JSONSchema | undefined }
6197 */
6298export interface Cell < T > {
6399 get ( ) : T ;
64100 set ( value : T ) : void ;
65101 send ( value : T ) : void ;
66- update ( value : Partial < T > ) : void ;
102+ update ( values : Partial < T > ) : void ;
67103 push (
68104 value :
69105 | ( T extends Array < infer U > ? U : any )
@@ -248,7 +284,6 @@ function createRegularCell<T>(
248284 const self = {
249285 get : ( ) => validateAndTransform ( doc , path , schema , log , rootSchema ) ,
250286 set : ( newValue : T ) => {
251- // TODO(seefeld): This doesn't respect aliases on write. Should it?
252287 const ref = resolvePath ( doc , path , log ) ;
253288 if (
254289 prepareForSaving (
@@ -267,21 +302,18 @@ function createRegularCell<T>(
267302 }
268303 } ,
269304 send : ( newValue : T ) => self . set ( newValue ) ,
270- update : ( value : Partial < T > ) => {
271- // TODO(seefeld): This doesn't respect aliases on write. Should it?
272- const ref = resolvePath ( doc , path , log ) ;
273- const previousValue = ref . cell . getAtPath ( ref . path ) ;
274- if ( typeof previousValue !== "object" || previousValue === null ) {
275- throw new Error ( "Can't update non-object value" ) ;
305+ update : ( values : Partial < T > ) => {
306+ if ( typeof values !== "object" || values === null ) {
307+ throw new Error ( "Can't update with non-object value" ) ;
308+ }
309+ for ( const [ key , value ] of Object . entries ( values ) ) {
310+ self . key ( key as keyof T ) . set ( value as T [ keyof T ] ) ;
276311 }
277- const newValue = {
278- ...previousValue ,
279- ...value ,
280- } ;
281- ref . cell . setAtPath ( ref . path , newValue , log ) ;
282312 } ,
283313 push : ( value : any ) => {
284- const ref = resolvePath ( doc , path , log ) ;
314+ // Follow aliases and references, since we want to get to an assumed
315+ // existing array.
316+ const ref = resolveLinkToValue ( doc , path , log ) ;
285317 const array = ref . cell . getAtPath ( ref . path ) ?? [ ] ;
286318 if ( ! Array . isArray ( array ) ) {
287319 throw new Error ( "Can't push into non-array value" ) ;
0 commit comments