11import {
2+ type Alias ,
23 ID ,
34 ID_FIELD ,
45 isAlias ,
@@ -22,7 +23,7 @@ import {
2223import { type CellLink , isCell , isCellLink } from "./cell.ts" ;
2324import { type ReactivityLog } from "./scheduler.ts" ;
2425import { ContextualFlowControl } from "./index.ts" ;
25- import { isObject , isRecord } from "@commontools/utils/types" ;
26+ import { isObject , isRecord , type Mutable } from "@commontools/utils/types" ;
2627
2728/**
2829 * Extracts default values from a JSON schema object.
@@ -37,10 +38,14 @@ export function extractDefaultValues(
3738 if (
3839 schema . type === "object" && schema . properties && isObject ( schema . properties )
3940 ) {
40- const obj = deepCopy ( schema . default ?? { } ) as Record < string , JSONValue > ;
41+ // Ignore the schema.default if it's not an object, since it's not a valid
42+ // default value for an object.
43+ const obj = deepCopy ( isRecord ( schema . default ) ? schema . default : { } ) ;
4144 for ( const [ propKey , propSchema ] of Object . entries ( schema . properties ) ) {
4245 const value = extractDefaultValues ( propSchema ) ;
43- if ( value !== undefined ) obj [ propKey ] = value ;
46+ if ( value !== undefined ) {
47+ ( obj as Record < string , unknown > ) [ propKey ] = value ;
48+ }
4449 }
4550
4651 return Object . entries ( obj ) . length > 0 ? obj : undefined ;
@@ -56,12 +61,12 @@ export function extractDefaultValues(
5661 * @param objects - Objects to merge
5762 * @returns A merged object, or undefined if no objects provided
5863 */
59- export function mergeObjects < T extends Record < string , unknown > > (
60- ...objects : ( T | undefined ) [ ]
61- ) : T | undefined {
64+ export function mergeObjects < T > (
65+ ...objects : ( Partial < T > | undefined ) [ ]
66+ ) : T {
6267 objects = objects . filter ( ( obj ) => obj !== undefined ) ;
63- if ( objects . length === 0 ) return undefined ;
64- if ( objects . length === 1 ) return objects [ 0 ] ;
68+ if ( objects . length === 0 ) return { } as T ;
69+ if ( objects . length === 1 ) return objects [ 0 ] as T ;
6570
6671 const seen = new Set < PropertyKey > ( ) ;
6772 const result : Record < string , unknown > = { } ;
@@ -80,14 +85,18 @@ export function mergeObjects<T extends Record<string, unknown>>(
8085 isCell ( obj ) ||
8186 isStatic ( obj )
8287 ) {
83- return obj ;
88+ return obj as T ;
8489 }
8590
8691 // Then merge objects, only passing those on that have any values.
8792 for ( const key of Object . keys ( obj ) ) {
8893 if ( seen . has ( key ) ) continue ;
8994 seen . add ( key ) ;
90- const merged = mergeObjects ( ...objects . map ( ( obj ) => obj ?. [ key ] as T ) ) ;
95+ const merged = mergeObjects < T [ keyof T ] > (
96+ ...objects . map ( ( obj ) =>
97+ ( obj as Record < string , unknown > ) ?. [ key ] as T [ keyof T ]
98+ ) ,
99+ ) ;
91100 if ( merged !== undefined ) result [ key ] = merged ;
92101 }
93102 }
@@ -302,7 +311,7 @@ export function findAllAliasedCells<T>(
302311 const doc = ( binding . $alias . cell ?? origDoc ) as DocImpl < T > ;
303312 const path = binding . $alias . path ;
304313 if ( docs . find ( ( c ) => c . cell === doc && c . path === path ) ) return ;
305- docs . push ( { cell : doc , path } ) ;
314+ docs . push ( { cell : doc as DocImpl < unknown > , path } ) ;
306315 find ( doc . getAtPath ( path ) , doc ) ;
307316 } else if ( Array . isArray ( binding ) ) {
308317 for ( const value of binding ) find ( value , origDoc ) ;
@@ -562,21 +571,21 @@ export function maybeGetCellLink<T>(
562571
563572// Follows aliases and returns cell reference describing the last alias.
564573// Only logs interim aliases, not the first one, and not the non-alias value.
565- export function followAliases < T > (
566- alias : unknown ,
574+ export function followAliases < T = any > (
575+ alias : Alias ,
567576 doc : DocImpl < T > ,
568577 log ?: ReactivityLog ,
569578) : CellLink {
570- if ( ! isAlias ( alias ) ) {
579+ if ( isAlias ( alias ) ) {
580+ return followLinks (
581+ { cell : doc , ...alias . $alias } as CellLink ,
582+ log ,
583+ createVisits ( ) ,
584+ true ,
585+ ) ;
586+ } else {
571587 throw new Error ( `Alias expected: ${ JSON . stringify ( alias ) } ` ) ;
572588 }
573-
574- return followLinks (
575- { cell : doc , ...( alias as any ) . $alias } ,
576- log ,
577- createVisits ( ) ,
578- true ,
579- ) ;
580589}
581590
582591/**
@@ -955,14 +964,17 @@ export function containsOpaqueRef(value: unknown): boolean {
955964 return false ;
956965}
957966
958- export function deepCopy ( value : unknown ) : unknown {
967+ export function deepCopy < T = unknown > ( value : T ) : Mutable < T > {
959968 if ( isQueryResultForDereferencing ( value ) ) {
960- return deepCopy ( getCellLinkOrThrow ( value ) ) ;
969+ return deepCopy ( getCellLinkOrThrow ( value ) ) as unknown as Mutable < T > ;
961970 }
962- if ( isDoc ( value ) || isCell ( value ) ) return value ;
971+ if ( isDoc ( value ) || isCell ( value ) ) return value as Mutable < T > ;
963972 if ( isRecord ( value ) ) {
964- return Array . isArray ( value ) ? value . map ( deepCopy ) : Object . fromEntries (
965- Object . entries ( value ) . map ( ( [ key , value ] ) => [ key , deepCopy ( value ) ] ) ,
966- ) ;
967- } else return value ;
973+ return Array . isArray ( value )
974+ ? value . map ( deepCopy ) as unknown as Mutable < T >
975+ : Object . fromEntries (
976+ Object . entries ( value ) . map ( ( [ key , value ] ) => [ key , deepCopy ( value ) ] ) ,
977+ ) as unknown as Mutable < T > ;
978+ // Literal value:
979+ } else return value as Mutable < T > ;
968980}
0 commit comments