@verdant-web/common 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/cjs/batching.d.ts +1 -0
  2. package/dist/cjs/batching.js +3 -0
  3. package/dist/cjs/batching.js.map +1 -1
  4. package/dist/cjs/index.d.ts +1 -1
  5. package/dist/cjs/index.js +2 -1
  6. package/dist/cjs/index.js.map +1 -1
  7. package/dist/cjs/indexes.d.ts +3 -1
  8. package/dist/cjs/indexes.js +26 -3
  9. package/dist/cjs/indexes.js.map +1 -1
  10. package/dist/cjs/migration.d.ts +85 -18
  11. package/dist/cjs/migration.js +137 -13
  12. package/dist/cjs/migration.js.map +1 -1
  13. package/dist/cjs/oids.d.ts +9 -2
  14. package/dist/cjs/oids.js +38 -5
  15. package/dist/cjs/oids.js.map +1 -1
  16. package/dist/cjs/oids.test.js +4 -3
  17. package/dist/cjs/oids.test.js.map +1 -1
  18. package/dist/cjs/schema/fields.d.ts +2 -0
  19. package/dist/cjs/schema/fields.js +29 -1
  20. package/dist/cjs/schema/fields.js.map +1 -1
  21. package/dist/cjs/schema/index.d.ts +2 -2
  22. package/dist/cjs/schema/index.js +25 -2
  23. package/dist/cjs/schema/index.js.map +1 -1
  24. package/dist/cjs/schema/types/collection.d.ts +12 -40
  25. package/dist/cjs/schema/types/compounds.d.ts +6 -7
  26. package/dist/cjs/schema/types/fields.d.ts +12 -2
  27. package/dist/cjs/schema/types/shapes.d.ts +6 -6
  28. package/dist/cjs/schema/types/synthetics.d.ts +11 -2
  29. package/dist/cjs/schema/types.d.ts +4 -4
  30. package/dist/cjs/utils.js +6 -1
  31. package/dist/cjs/utils.js.map +1 -1
  32. package/dist/esm/batching.d.ts +1 -0
  33. package/dist/esm/batching.js +3 -0
  34. package/dist/esm/batching.js.map +1 -1
  35. package/dist/esm/index.d.ts +1 -1
  36. package/dist/esm/index.js +1 -1
  37. package/dist/esm/index.js.map +1 -1
  38. package/dist/esm/indexes.d.ts +3 -1
  39. package/dist/esm/indexes.js +23 -2
  40. package/dist/esm/indexes.js.map +1 -1
  41. package/dist/esm/migration.d.ts +85 -18
  42. package/dist/esm/migration.js +136 -13
  43. package/dist/esm/migration.js.map +1 -1
  44. package/dist/esm/oids.d.ts +9 -2
  45. package/dist/esm/oids.js +35 -3
  46. package/dist/esm/oids.js.map +1 -1
  47. package/dist/esm/oids.test.js +5 -4
  48. package/dist/esm/oids.test.js.map +1 -1
  49. package/dist/esm/replica.js +1 -1
  50. package/dist/esm/replica.js.map +1 -1
  51. package/dist/esm/schema/fields.d.ts +2 -0
  52. package/dist/esm/schema/fields.js +26 -0
  53. package/dist/esm/schema/fields.js.map +1 -1
  54. package/dist/esm/schema/index.d.ts +2 -2
  55. package/dist/esm/schema/index.js +25 -2
  56. package/dist/esm/schema/index.js.map +1 -1
  57. package/dist/esm/schema/types/collection.d.ts +12 -40
  58. package/dist/esm/schema/types/compounds.d.ts +6 -7
  59. package/dist/esm/schema/types/fields.d.ts +12 -2
  60. package/dist/esm/schema/types/shapes.d.ts +6 -6
  61. package/dist/esm/schema/types/synthetics.d.ts +11 -2
  62. package/dist/esm/schema/types.d.ts +4 -4
  63. package/dist/esm/utils.js +3 -1
  64. package/dist/esm/utils.js.map +1 -1
  65. package/dist/tsconfig-cjs.tsbuildinfo +1 -1
  66. package/dist/tsconfig.tsbuildinfo +1 -1
  67. package/package.json +6 -3
  68. package/src/batching.ts +4 -0
  69. package/src/index.ts +1 -0
  70. package/src/indexes.ts +51 -12
  71. package/src/migration.ts +300 -57
  72. package/src/oids.test.ts +5 -4
  73. package/src/oids.ts +39 -3
  74. package/src/schema/fields.ts +18 -0
  75. package/src/schema/index.ts +30 -3
  76. package/src/schema/types/collection.ts +14 -112
  77. package/src/schema/types/compounds.ts +29 -18
  78. package/src/schema/types/fields.ts +12 -2
  79. package/src/schema/types/shapes.ts +13 -14
  80. package/src/schema/types/synthetics.ts +31 -2
  81. package/src/schema/types.ts +4 -6
  82. package/src/utils.ts +3 -1
package/src/oids.ts CHANGED
@@ -437,11 +437,12 @@ export function getOidRoot(oid: ObjectIdentifier) {
437
437
 
438
438
  /**
439
439
  * Returns an inclusive range of OIDs that represent
440
- * a root object and all of its sub-objects.
440
+ * all of an OID's possible sub-objects.
441
441
  */
442
- export function getOidRange(oid: ObjectIdentifier) {
442
+ export function getOidSubIdRange(oid: ObjectIdentifier) {
443
443
  const root = getOidRoot(oid);
444
- return [root, `${root}${RANDOM_SEPARATOR}\uffff`];
444
+ const lastSubId = createSubOid(root, () => '\uffff');
445
+ return [`${root}${RANDOM_SEPARATOR}`, lastSubId];
445
446
  }
446
447
 
447
448
  export function getRoots(oids: ObjectIdentifier[]) {
@@ -455,3 +456,38 @@ export function getRoots(oids: ObjectIdentifier[]) {
455
456
  export function areOidsRelated(oidA: ObjectIdentifier, oidB: ObjectIdentifier) {
456
457
  return getOidRoot(oidA) === getOidRoot(oidB);
457
458
  }
459
+
460
+ /**
461
+ * Recursively rewrites any OIDs in an object which are 'foreign' -
462
+ * i.e. relate to some other object/entity - to be local to the
463
+ * current object. This is deterministic, so it can be done
464
+ * on multiple clients independently with predictable results.
465
+ */
466
+ export function fixForeignOids(obj: any) {
467
+ const oid = maybeGetOid(obj);
468
+ if (!oid) return;
469
+
470
+ if (Array.isArray(obj)) {
471
+ for (let i = 0; i < obj.length; i++) {
472
+ migrateForeignOid(oid, obj[i]);
473
+ fixForeignOids(obj[i]);
474
+ }
475
+ } else if (isObject(obj)) {
476
+ for (const key of Object.keys(obj)) {
477
+ migrateForeignOid(oid, obj[key]);
478
+ fixForeignOids(obj[key]);
479
+ }
480
+ }
481
+ }
482
+
483
+ function migrateForeignOid(parentOid: ObjectIdentifier, child: any) {
484
+ const childOid = maybeGetOid(child);
485
+ if (childOid && !areOidsRelated(parentOid, childOid)) {
486
+ const { subId, id } = decomposeOid(childOid);
487
+ // reuse existing subId. if child is a foreign root, use its id as subId
488
+ assignOid(
489
+ child,
490
+ createSubOid(parentOid, () => subId || id),
491
+ );
492
+ }
493
+ }
@@ -8,6 +8,24 @@ export function isNullable(field: StorageFieldSchema) {
8
8
  return field.nullable;
9
9
  }
10
10
 
11
+ export function hasDefault(field: StorageFieldSchema | undefined) {
12
+ if (!field) return false;
13
+ if (field.type === 'map') return true;
14
+ if (field.type === 'array') return true;
15
+ if (field.type === 'file') return false;
16
+ if (field.type === 'object') return true;
17
+ return field.default !== undefined;
18
+ }
19
+
20
+ export function isIndexed(field: StorageFieldSchema) {
21
+ if (field.type === 'map') return false;
22
+ if (field.type === 'object') return false;
23
+ if (field.type === 'array') return false;
24
+ if (field.type === 'file') return false;
25
+ if (field.type === 'any') return false;
26
+ return field.indexed;
27
+ }
28
+
11
29
  export function addFieldDefaults(
12
30
  collection: StorageCollectionSchema,
13
31
  value: any,
@@ -1,8 +1,11 @@
1
+ import { isIndexed } from './fields.js';
1
2
  import {
2
3
  CollectionCompoundIndices,
3
4
  StorageCollectionSchema,
5
+ StorageDirectSyntheticSchema,
4
6
  StorageFieldsSchema,
5
7
  StorageSchema,
8
+ StorageSyntheticIndexSchema,
6
9
  StorageSyntheticIndices,
7
10
  } from './types.js';
8
11
 
@@ -10,15 +13,39 @@ export function collection<
10
13
  Fields extends StorageFieldsSchema,
11
14
  Synthetics extends StorageSyntheticIndices<Fields>,
12
15
  Compounds extends CollectionCompoundIndices<Fields, Synthetics>,
13
- >(input: StorageCollectionSchema<Fields, Synthetics, Compounds>) {
14
- return input;
16
+ >({
17
+ synthetics,
18
+ indexes,
19
+ ...input
20
+ }: StorageCollectionSchema<
21
+ Fields,
22
+ Synthetics,
23
+ Compounds
24
+ >): StorageCollectionSchema<Fields, Synthetics, Compounds> {
25
+ // back compat - copy synthetics in with indexes
26
+ const finalIndexes = { ...synthetics, ...indexes };
27
+ // add all indexed fields into the synthetic indices (back compat)
28
+ for (const [key, field] of Object.entries(input.fields)) {
29
+ if (isIndexed(field)) {
30
+ finalIndexes[key] = {
31
+ field: key,
32
+ } as StorageDirectSyntheticSchema<Fields>;
33
+ }
34
+ }
35
+ return {
36
+ ...input,
37
+ indexes: finalIndexes as Synthetics,
38
+ };
15
39
  }
16
40
 
17
41
  export function schema<
42
+ // Fields extends StorageFieldsSchema,
43
+ // Indexes extends StorageSyntheticIndices<Fields>,
44
+ // Compounds extends CollectionCompoundIndices<Fields, Indexes>,
18
45
  Schema extends StorageSchema<{
19
46
  [key: string]: StorageCollectionSchema<any, any, any>;
20
47
  }>,
21
- >(input: Schema) {
48
+ >(input: Schema): StorageSchema {
22
49
  return input;
23
50
  }
24
51
 
@@ -1,13 +1,7 @@
1
1
  import { CollectionCompoundIndices } from './compounds.js';
2
+ import { StorageFieldsSchema } from './fields.js';
2
3
  import {
3
- NestedStorageFieldSchema,
4
- StorageFieldSchema,
5
- StorageFieldsSchema,
6
- StorageIndexableFields,
7
- } from './fields.js';
8
- import { StorageDocument } from './shapes.js';
9
- import {
10
- StorageSyntheticIndexSchema,
4
+ DirectIndexableFieldName,
11
5
  StorageSyntheticIndices,
12
6
  } from './synthetics.js';
13
7
 
@@ -16,7 +10,8 @@ import {
16
10
  */
17
11
  export type StorageCollectionSchema<
18
12
  Fields extends StorageFieldsSchema = StorageFieldsSchema,
19
- Synthetics extends StorageSyntheticIndices<Fields> = StorageSyntheticIndices<Fields>,
13
+ Synthetics extends
14
+ StorageSyntheticIndices<Fields> = StorageSyntheticIndices<Fields>,
20
15
  Compounds extends CollectionCompoundIndices<
21
16
  Fields,
22
17
  Synthetics
@@ -24,110 +19,17 @@ export type StorageCollectionSchema<
24
19
  > = {
25
20
  name: string;
26
21
  /**
27
- * Optionally provide a plural name. Useful for some code generation purposes.
22
+ * Your primary key must be a string, number, or boolean field. It must also
23
+ * not be rewritten.
28
24
  */
29
- pluralName?: string;
25
+ primaryKey: DirectIndexableFieldName<Fields>;
30
26
  fields: Fields;
31
- synthetics?: Synthetics;
27
+ indexes?: Synthetics;
32
28
  compounds?: Compounds;
33
- primaryKey: StorageIndexablePropertyName<Fields, Synthetics>;
34
- };
35
-
36
- export type NamedSchema<
37
- Schemas extends StorageCollectionSchema<any, any, any>,
38
- Name extends string,
39
- > = Schemas extends { name: Name } ? Schemas : never;
40
-
41
- export type IndexedSchemaProperties<
42
- Schema extends StorageCollectionSchema<any, any, any>,
43
- > = {
44
- [K in keyof CollectionSchemaFields<Schema> as CollectionSchemaFields<Schema>[K] extends {
45
- indexed: true;
46
- }
47
- ? K
48
- : never]: CollectionSchemaFields<Schema>[K];
49
- } & CollectionSchemaComputedIndexes<Schema> &
50
- CollectionSchemaCompoundIndexes<Schema>;
51
-
52
- export type CollectionIndexName<
53
- Collection extends StorageCollectionSchema<any, any, any>,
54
- > = Extract<keyof IndexedSchemaProperties<Collection>, string>;
55
-
56
- export type CollectionProperties<
57
- Collection extends StorageCollectionSchema<any, any, any>,
58
- > = Collection['fields'] & Collection['synthetics'];
59
-
60
- export type CollectionPropertyName<
61
- Collection extends StorageCollectionSchema<any, any, any>,
62
- > = Exclude<keyof CollectionProperties<Collection>, number | symbol>;
63
-
64
- export type CollectionEvents<
65
- Collection extends StorageCollectionSchema<any, any, any>,
66
- > = {
67
- put: (value: StorageDocument<Collection>) => void;
68
- delete: (id: string) => void;
69
- [key: `put:${string}`]: (value: StorageDocument<Collection>) => void;
70
- [key: `delete:${string}`]: () => void;
29
+ /**
30
+ * @deprecated - plural name is the key used to index this collection in the schema. this field is no longer used.
31
+ */
32
+ pluralName?: string;
33
+ /** @deprecated - use "indexes" */
34
+ synthetics?: Synthetics;
71
35
  };
72
-
73
- export type SchemaForCollection<
74
- Collection extends StorageCollectionSchema<any, any, any>,
75
- > = Collection;
76
-
77
- export type CollectionSchemaFields<
78
- Schema extends StorageCollectionSchema<any, any, any>,
79
- > = Schema extends StorageCollectionSchema<infer F, any, any> ? F : never;
80
- export type CollectionSchemaComputedIndexes<
81
- Schema extends StorageCollectionSchema<any, any, any>,
82
- > = Schema extends StorageCollectionSchema<any, infer S, any> ? S : never;
83
- export type CollectionSchemaCompoundIndexes<
84
- Schema extends StorageCollectionSchema<any, any, any>,
85
- > = Schema extends StorageCollectionSchema<any, any, infer C> ? C : never;
86
-
87
- export type StorageIndexableProperties<
88
- Schema extends StorageCollectionSchema<any, any, any>,
89
- > = {
90
- [K in keyof CollectionSchemaFields<Schema>]: CollectionSchemaFields<Schema>[K] extends {
91
- indexed: boolean;
92
- }
93
- ? CollectionSchemaFields<Schema>[K]
94
- : never;
95
- } & CollectionSchemaComputedIndexes<Schema>;
96
-
97
- export type StorageSchemaProperty<
98
- Schema extends StorageCollectionSchema<any, any, any>,
99
- > = StorageSchemaProperties<Schema>[keyof StorageSchemaProperties<Schema>];
100
-
101
- export type StorageSchemaPropertyName<
102
- Schema extends StorageCollectionSchema<any, any, any>,
103
- > = Extract<keyof StorageSchemaProperties<Schema>, string>;
104
-
105
- export type GetSchemaProperty<
106
- Schema extends StorageCollectionSchema<any, any, any>,
107
- Key extends StorageSchemaPropertyName<Schema>,
108
- > = StorageSchemaProperties<Schema>[Key];
109
-
110
- export type StoragePropertySchema<BaseFields extends StorageFieldsSchema> =
111
- | StorageFieldSchema
112
- | NestedStorageFieldSchema
113
- | StorageSyntheticIndexSchema<BaseFields>;
114
-
115
- export type StoragePropertyName<
116
- Fields extends StorageFieldsSchema,
117
- Synthetics extends StorageSyntheticIndices<Fields>,
118
- > =
119
- | Exclude<keyof Fields, number | symbol>
120
- | Exclude<keyof Synthetics, number | symbol>;
121
-
122
- export type StorageIndexablePropertyName<
123
- Fields extends StorageFieldsSchema,
124
- Synthetics extends StorageSyntheticIndices<Fields>,
125
- > =
126
- | Extract<keyof StorageIndexableFields<Fields>, string>
127
- | Extract<keyof Synthetics, string>;
128
-
129
- export type StorageSchemaProperties<
130
- Schema extends StorageCollectionSchema<any, any, any>,
131
- > = Schema extends StorageCollectionSchema<infer F, infer S, infer C>
132
- ? F & S & C
133
- : never;
@@ -1,33 +1,44 @@
1
1
  import {
2
- CollectionSchemaCompoundIndexes,
3
- StorageCollectionSchema,
4
- StoragePropertyName,
5
- } from './collection.js';
6
- import { StorageFieldsSchema, StorageObjectFieldSchema } from './fields.js';
7
- import { StorageSyntheticIndices } from './synthetics.js';
2
+ NestedStorageBooleanFieldSchema,
3
+ NestedStorageNumberFieldSchema,
4
+ NestedStorageStringFieldSchema,
5
+ StorageArrayFieldSchema,
6
+ StorageFieldsSchema,
7
+ } from './fields.js';
8
+ import {
9
+ DirectIndexableFieldName,
10
+ StorageSyntheticIndices,
11
+ } from './synthetics.js';
8
12
 
9
- type OmitObjectFields<T extends StorageFieldsSchema> = {
10
- [K in keyof T]: T[K] extends StorageObjectFieldSchema ? never : T[K];
13
+ // arrays of primitives are eligible for compound indices
14
+ type PrimitiveArrayFields<Fields extends StorageFieldsSchema> = {
15
+ [K in keyof Fields as Fields[K] extends StorageArrayFieldSchema
16
+ ? Fields[K]['items'] extends
17
+ | NestedStorageStringFieldSchema
18
+ | NestedStorageNumberFieldSchema
19
+ | NestedStorageBooleanFieldSchema
20
+ ? K
21
+ : never
22
+ : never]: Fields[K];
11
23
  };
24
+ type PrimitiveArrayFieldName<Fields extends StorageFieldsSchema> = Extract<
25
+ keyof PrimitiveArrayFields<Fields>,
26
+ string
27
+ >;
12
28
 
13
29
  export type CollectionCompoundIndex<
14
30
  Fields extends StorageFieldsSchema,
15
31
  Synthetics extends StorageSyntheticIndices<Fields>,
16
32
  > = {
17
33
  // object fields cannot be compound index inputs
18
- of: StoragePropertyName<OmitObjectFields<Fields>, Synthetics>[];
34
+ of: (
35
+ | DirectIndexableFieldName<Fields>
36
+ | PrimitiveArrayFieldName<Fields>
37
+ | Extract<keyof Synthetics, string>
38
+ )[];
19
39
  };
20
- type CompoundFieldNameTuple<Name extends string> =
21
- | [Name, Name]
22
- | [Name, Name, Name]
23
- | [Name, Name, Name, Name]
24
- | [Name, Name, Name, Name, Name];
25
40
 
26
41
  export type CollectionCompoundIndices<
27
42
  Fields extends StorageFieldsSchema,
28
43
  Synthetics extends StorageSyntheticIndices<Fields>,
29
44
  > = Record<string, CollectionCompoundIndex<Fields, Synthetics>>;
30
-
31
- export type CollectionCompoundIndexName<
32
- Collection extends StorageCollectionSchema<any, any, any>,
33
- > = Exclude<keyof CollectionSchemaCompoundIndexes<Collection>, number | symbol>;
@@ -1,11 +1,13 @@
1
1
  export type StorageStringFieldSchema = {
2
2
  type: 'string';
3
+ /** @deprecated - add an index to indexes with this field name. */
3
4
  indexed?: boolean;
4
5
  nullable?: boolean;
5
6
  default?: string | (() => string);
6
7
  };
7
8
  export type StorageNumberFieldSchema = {
8
9
  type: 'number';
10
+ /** @deprecated - add an index to indexes with this field name. */
9
11
  indexed?: boolean;
10
12
  nullable?: boolean;
11
13
  default?: number | (() => number);
@@ -14,6 +16,7 @@ export type StorageBooleanFieldSchema = {
14
16
  type: 'boolean';
15
17
  nullable?: boolean;
16
18
  default?: boolean | (() => boolean);
19
+ /** @deprecated - add an index to indexes with this field name. */
17
20
  indexed?: boolean;
18
21
  };
19
22
  export type StorageArrayFieldSchema = {
@@ -66,18 +69,25 @@ export type NestedStorageNumberFieldSchema = {
66
69
  nullable?: boolean;
67
70
  default?: number | (() => number);
68
71
  };
72
+ export type NestedStorageBooleanFieldSchema = {
73
+ type: 'boolean';
74
+ nullable?: boolean;
75
+ default: boolean | (() => boolean);
76
+ };
69
77
 
70
78
  export type NestedStorageFieldSchema =
71
79
  | NestedStorageStringFieldSchema
72
80
  | NestedStorageNumberFieldSchema
73
- | StorageBooleanFieldSchema
81
+ | NestedStorageBooleanFieldSchema
74
82
  | StorageArrayFieldSchema
75
83
  | StorageObjectFieldSchema
76
84
  | StorageAnyFieldSchema
77
85
  | StorageMapFieldSchema<any>
78
86
  | StorageFileFieldSchema;
79
87
 
80
- export type StorageFieldsSchema = Record<string, StorageFieldSchema>;
88
+ export type StorageFieldsSchema = {
89
+ [key: string]: StorageFieldSchema;
90
+ };
81
91
 
82
92
  export type NestedStorageFieldsSchema = Record<
83
93
  string,
@@ -1,25 +1,24 @@
1
- import {
2
- StorageCollectionSchema,
3
- StoragePropertySchema,
4
- } from './collection.js';
1
+ import { StorageCollectionSchema } from './collection.js';
5
2
  import {
6
3
  NestedStorageFieldsSchema,
7
4
  StorageArrayFieldSchema,
5
+ StorageFieldSchema,
8
6
  StorageFieldsSchema,
9
7
  StorageMapFieldSchema,
10
8
  StorageObjectFieldSchema,
11
9
  } from './fields.js';
12
10
 
13
- type StoragePropertyIsNullable<T extends StoragePropertySchema<any>> =
14
- T extends { nullable?: boolean }
15
- ? T['nullable'] extends boolean
16
- ? true
17
- : false
18
- : T['type'] extends 'any'
11
+ type StoragePropertyIsNullable<T extends StorageFieldSchema> = T extends {
12
+ nullable?: boolean;
13
+ }
14
+ ? T['nullable'] extends boolean
19
15
  ? true
20
- : false;
16
+ : false
17
+ : T['type'] extends 'any'
18
+ ? true
19
+ : false;
21
20
 
22
- export type BaseShapeFromProperty<T extends StoragePropertySchema<any>> =
21
+ export type BaseShapeFromProperty<T extends StorageFieldSchema> =
23
22
  T['type'] extends 'string'
24
23
  ? string
25
24
  : T['type'] extends 'number'
@@ -38,7 +37,7 @@ export type BaseShapeFromProperty<T extends StoragePropertySchema<any>> =
38
37
  ? File
39
38
  : never;
40
39
 
41
- export type ShapeFromProperty<T extends StoragePropertySchema<any>> =
40
+ export type ShapeFromProperty<T extends StorageFieldSchema> =
42
41
  StoragePropertyIsNullable<T> extends true
43
42
  ? BaseShapeFromProperty<T> | null
44
43
  : BaseShapeFromProperty<T>;
@@ -53,7 +52,7 @@ export type StorageDocument<
53
52
  Collection extends StorageCollectionSchema<any, any, any>,
54
53
  > = ShapeFromFields<Collection['fields']>;
55
54
 
56
- type StoragePropertyIsOptional<T extends StoragePropertySchema<any>> =
55
+ type StoragePropertyIsOptional<T extends StorageFieldSchema> =
57
56
  StoragePropertyIsNullable<T> extends true
58
57
  ? true
59
58
  : T extends { default?: any }
@@ -1,4 +1,10 @@
1
- import { StorageFieldsSchema } from './fields.js';
1
+ import {
2
+ StorageBooleanFieldSchema,
3
+ StorageFieldSchema,
4
+ StorageFieldsSchema,
5
+ StorageNumberFieldSchema,
6
+ StorageStringFieldSchema,
7
+ } from './fields.js';
2
8
  import { ShapeFromFields } from './shapes.js';
3
9
 
4
10
  export type StorageStringSyntheticSchema<Fields extends StorageFieldsSchema> = {
@@ -32,6 +38,23 @@ export type StorageBooleanArraySyntheticSchema<
32
38
  type: 'boolean[]';
33
39
  compute: (value: ShapeFromFields<Fields>) => boolean[];
34
40
  };
41
+ export type StorageDirectSyntheticSchema<Fields extends StorageFieldsSchema> = {
42
+ field: DirectIndexableFieldName<Fields>;
43
+ };
44
+
45
+ type DirectIndexableFields<Fields extends StorageFieldsSchema> = {
46
+ [K in keyof Fields as Fields[K] extends StorageStringFieldSchema
47
+ ? K
48
+ : Fields[K] extends StorageNumberFieldSchema
49
+ ? K
50
+ : Fields[K] extends StorageBooleanFieldSchema
51
+ ? K
52
+ : never]: any;
53
+ };
54
+ export type DirectIndexableFieldName<Fields extends StorageFieldsSchema> =
55
+ keyof DirectIndexableFields<Fields> extends never
56
+ ? string
57
+ : keyof DirectIndexableFields<Fields>;
35
58
 
36
59
  export type StorageSyntheticIndices<Fields extends StorageFieldsSchema> =
37
60
  Record<string, StorageSyntheticIndexSchema<Fields>>;
@@ -42,4 +65,10 @@ export type StorageSyntheticIndexSchema<Fields extends StorageFieldsSchema> =
42
65
  | StorageBooleanSyntheticSchema<Fields>
43
66
  | StorageStringArraySyntheticSchema<Fields>
44
67
  | StorageNumberArraySyntheticSchema<Fields>
45
- | StorageBooleanArraySyntheticSchema<Fields>;
68
+ | StorageBooleanArraySyntheticSchema<Fields>
69
+ | StorageDirectSyntheticSchema<Fields>;
70
+
71
+ export type IndexValueTag = Exclude<
72
+ StorageSyntheticIndexSchema<any>,
73
+ StorageDirectSyntheticSchema<any>
74
+ >['type'];
@@ -7,15 +7,13 @@ export * from './types/filters.js';
7
7
  export * from './types/shapes.js';
8
8
  export * from './types/synthetics.js';
9
9
 
10
- export interface StorageInit<Schemas extends StorageCollectionSchema> {
11
- collections: Record<string, Schemas>;
12
- }
13
-
14
10
  export type StorageSchema<
15
11
  Collections extends {
16
12
  [k: string]: StorageCollectionSchema;
17
- } = any,
18
- > = { version: number; collections: Collections };
13
+ } = {
14
+ [k: string]: StorageCollectionSchema;
15
+ },
16
+ > = { version: number; wip?: true; collections: Collections };
19
17
 
20
18
  export type SchemaCollectionName<Schema extends StorageSchema<any>> =
21
19
  Schema extends StorageSchema<infer Cs>
package/src/utils.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { v4 } from 'uuid';
2
2
  import { assignOid, maybeGetOid } from './oids.js';
3
+ import hash from 'object-hash';
3
4
 
4
5
  export function take<T extends object, Keys extends keyof T>(
5
6
  obj: T,
@@ -86,7 +87,8 @@ export function cloneDeep<T>(obj: T, copyOids = true): T {
86
87
 
87
88
  // TODO: better hash
88
89
  export function hashObject(obj: any) {
89
- return stableStringify(obj);
90
+ // hash the object into a unique string
91
+ return hash(obj);
90
92
  }
91
93
 
92
94
  export function isObject(obj: any) {