@instantdb/core 0.22.86-experimental.split-store.20178922132.1 → 0.22.86-experimental.split-store.20243647937.1

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 (45) hide show
  1. package/__tests__/src/Reactor.test.js +18 -11
  2. package/__tests__/src/{datalog.test.js → datalog.test.ts} +17 -5
  3. package/__tests__/src/{instaml.test.js → instaml.test.ts} +183 -119
  4. package/__tests__/src/instaql.bench.ts +34 -0
  5. package/__tests__/src/{instaql.test.js → instaql.test.ts} +342 -455
  6. package/__tests__/src/instaqlInference.test.js +13 -9
  7. package/__tests__/src/{store.test.js → store.test.ts} +188 -210
  8. package/dist/commonjs/Reactor.d.ts +4 -1
  9. package/dist/commonjs/Reactor.d.ts.map +1 -1
  10. package/dist/commonjs/Reactor.js +22 -12
  11. package/dist/commonjs/Reactor.js.map +1 -1
  12. package/dist/commonjs/instaml.d.ts +3 -3
  13. package/dist/commonjs/instaml.d.ts.map +1 -1
  14. package/dist/commonjs/instaml.js +2 -2
  15. package/dist/commonjs/instaml.js.map +1 -1
  16. package/dist/commonjs/instaql.d.ts +2 -2
  17. package/dist/commonjs/instaql.d.ts.map +1 -1
  18. package/dist/commonjs/instaql.js.map +1 -1
  19. package/dist/commonjs/store.d.ts +28 -9
  20. package/dist/commonjs/store.d.ts.map +1 -1
  21. package/dist/commonjs/store.js +25 -19
  22. package/dist/commonjs/store.js.map +1 -1
  23. package/dist/esm/Reactor.d.ts +4 -1
  24. package/dist/esm/Reactor.d.ts.map +1 -1
  25. package/dist/esm/Reactor.js +22 -12
  26. package/dist/esm/Reactor.js.map +1 -1
  27. package/dist/esm/instaml.d.ts +3 -3
  28. package/dist/esm/instaml.d.ts.map +1 -1
  29. package/dist/esm/instaml.js +3 -3
  30. package/dist/esm/instaml.js.map +1 -1
  31. package/dist/esm/instaql.d.ts +2 -2
  32. package/dist/esm/instaql.d.ts.map +1 -1
  33. package/dist/esm/instaql.js.map +1 -1
  34. package/dist/esm/store.d.ts +28 -9
  35. package/dist/esm/store.d.ts.map +1 -1
  36. package/dist/esm/store.js +23 -17
  37. package/dist/esm/store.js.map +1 -1
  38. package/dist/standalone/index.js +580 -564
  39. package/dist/standalone/index.umd.cjs +2 -2
  40. package/package.json +2 -2
  41. package/src/Reactor.js +44 -35
  42. package/src/instaml.ts +8 -7
  43. package/src/instaql.ts +2 -2
  44. package/src/store.ts +61 -30
  45. package/__tests__/src/instaql.bench.js +0 -29
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instantdb/core",
3
- "version": "0.22.86-experimental.split-store.20178922132.1",
3
+ "version": "0.22.86-experimental.split-store.20243647937.1",
4
4
  "description": "Instant's core local abstraction",
5
5
  "homepage": "https://github.com/instantdb/instant/tree/main/client/packages/core",
6
6
  "repository": {
@@ -53,7 +53,7 @@
53
53
  "dependencies": {
54
54
  "mutative": "^1.0.10",
55
55
  "uuid": "^11.1.0",
56
- "@instantdb/version": "0.22.86-experimental.split-store.20178922132.1"
56
+ "@instantdb/version": "0.22.86-experimental.split-store.20243647937.1"
57
57
  },
58
58
  "scripts": {
59
59
  "test": "vitest",
package/src/Reactor.js CHANGED
@@ -661,38 +661,49 @@ export default class Reactor {
661
661
  const result = x['instaql-result'];
662
662
  const hash = weakHash(q);
663
663
  const triples = extractTriples(result);
664
+ const attrsStore = this.ensureAttrs();
664
665
  const store = sts.createStore(
665
- this.ensureAttrs(),
666
+ attrsStore,
666
667
  triples,
667
668
  enableCardinalityInference,
668
669
  this.config.useDateObjects,
669
670
  );
670
- const newStore = this._applyOptimisticUpdates(
671
- store,
672
- this.ensureAttrs(),
673
- mutations,
674
- processedTxId,
675
- );
671
+ const { store: newStore, attrsStore: newAttrsStore } =
672
+ this._applyOptimisticUpdates(
673
+ store,
674
+ attrsStore,
675
+ mutations,
676
+ processedTxId,
677
+ );
676
678
  const pageInfo = result?.[0]?.data?.['page-info'];
677
679
  const aggregate = result?.[0]?.data?.['aggregate'];
678
- return { q, hash, store: newStore, pageInfo, aggregate };
680
+ return {
681
+ q,
682
+ hash,
683
+ store: newStore,
684
+ attrsStore: newAttrsStore,
685
+ pageInfo,
686
+ aggregate,
687
+ };
679
688
  });
680
689
 
681
- updates.forEach(({ hash, q, store, pageInfo, aggregate }) => {
682
- this.querySubs.updateInPlace((prev) => {
683
- if (!prev[hash]) {
684
- this._log.error('Missing value in querySubs', { hash, q });
685
- return;
686
- }
687
- prev[hash].result = {
688
- store,
689
- attrsStore: this.ensureAttrs(),
690
- pageInfo,
691
- aggregate,
692
- processedTxId,
693
- };
694
- });
695
- });
690
+ updates.forEach(
691
+ ({ hash, q, store, attrsStore, pageInfo, aggregate }) => {
692
+ this.querySubs.updateInPlace((prev) => {
693
+ if (!prev[hash]) {
694
+ this._log.error('Missing value in querySubs', { hash, q });
695
+ return;
696
+ }
697
+ prev[hash].result = {
698
+ store,
699
+ attrsStore,
700
+ pageInfo,
701
+ aggregate,
702
+ processedTxId,
703
+ };
704
+ });
705
+ },
706
+ );
696
707
 
697
708
  this._cleanupPendingMutationsQueries();
698
709
 
@@ -919,7 +930,7 @@ export default class Reactor {
919
930
  }
920
931
 
921
932
  _setAttrs(attrs) {
922
- this.attrs = new sts.AttrsStore(
933
+ this.attrs = new sts.AttrsStoreClass(
923
934
  attrs.reduce((acc, attr) => {
924
935
  acc[attr.id] = attr;
925
936
  return acc;
@@ -1195,7 +1206,7 @@ export default class Reactor {
1195
1206
  }
1196
1207
 
1197
1208
  if (!deletedAttrIds.size && !pendingAttrs.length) {
1198
- return this.attrs || new sts.AttrsStore({}, this._linkIndex);
1209
+ return this.attrs || new sts.AttrsStoreClass({}, this._linkIndex);
1199
1210
  }
1200
1211
 
1201
1212
  const attrs = { ...(this.attrs?.attrs || {}) };
@@ -1206,7 +1217,7 @@ export default class Reactor {
1206
1217
  delete attrs[id];
1207
1218
  }
1208
1219
 
1209
- return new sts.AttrsStore(attrs, this._linkIndex);
1220
+ return new sts.AttrsStoreClass(attrs, this._linkIndex);
1210
1221
  }
1211
1222
 
1212
1223
  /** Runs instaql on a query and a store */
@@ -1239,14 +1250,10 @@ export default class Reactor {
1239
1250
  attrsStore,
1240
1251
  pendingMutations,
1241
1252
  );
1242
- const newStore = this._applyOptimisticUpdates(
1243
- store,
1244
- attrsStore,
1245
- mutations,
1246
- processedTxId,
1247
- );
1253
+ const { store: newStore, attrsStore: newAttrsStore } =
1254
+ this._applyOptimisticUpdates(store, attrsStore, mutations, processedTxId);
1248
1255
  const resp = instaql(
1249
- { store: newStore, attrsStore, pageInfo, aggregate },
1256
+ { store: newStore, attrsStore: newAttrsStore, pageInfo, aggregate },
1250
1257
  q,
1251
1258
  );
1252
1259
 
@@ -1256,10 +1263,12 @@ export default class Reactor {
1256
1263
  _applyOptimisticUpdates(store, attrsStore, mutations, processedTxId) {
1257
1264
  for (const [_, mut] of mutations) {
1258
1265
  if (!mut['tx-id'] || (processedTxId && mut['tx-id'] > processedTxId)) {
1259
- store = sts.transact(store, attrsStore, mut['tx-steps']);
1266
+ const result = sts.transact(store, attrsStore, mut['tx-steps']);
1267
+ store = result.store;
1268
+ attrsStore = result.attrsStore;
1260
1269
  }
1261
1270
  }
1262
- return store;
1271
+ return { store, attrsStore };
1263
1272
  }
1264
1273
 
1265
1274
  /** Re-run instaql and call all callbacks with new data */
package/src/instaml.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  allMapValues,
3
3
  AttrsStore,
4
+ AttrsStoreClass,
4
5
  getAttrByFwdIdentName,
5
6
  getAttrByReverseIdentName,
6
7
  Store,
@@ -205,7 +206,7 @@ function expandUnlink({ attrsStore }: Ctx, [etype, eidA, obj]) {
205
206
  }
206
207
 
207
208
  function checkEntityExists(
208
- stores: (Store | undefined)[],
209
+ stores: (Store | undefined)[] | undefined,
209
210
  attrsStore: AttrsStore,
210
211
  etype: string,
211
212
  eid: string,
@@ -241,10 +242,10 @@ function checkEntityExists(
241
242
  }
242
243
 
243
244
  type Ctx = {
244
- stores: (Store | undefined)[];
245
+ stores?: (Store | undefined)[];
245
246
  attrsStore: AttrsStore;
246
- schema: Schema;
247
- useDateObjects: boolean | null;
247
+ schema?: Schema;
248
+ useDateObjects?: boolean | null;
248
249
  };
249
250
 
250
251
  function convertOpts({ stores, attrsStore }: Ctx, [etype, eid, obj_, opts]) {
@@ -458,7 +459,7 @@ function refPropsFromSchema(schema: Schema, etype, label) {
458
459
  }
459
460
 
460
461
  function createRefAttr(
461
- schema: Schema,
462
+ schema: Schema | undefined,
462
463
  etype: string,
463
464
  label: string,
464
465
  props?: Partial<InstantDBAttr> | undefined,
@@ -593,7 +594,7 @@ function createMissingAttrs(
593
594
  identName.indexOf('.') !== -1 &&
594
595
  // attr names can have `.` in them, so use the attr we find with a `.`
595
596
  // before assuming it's a ref lookup.
596
- !attrByRevIdent(etype, identName)
597
+ !attrByFwdIdent(etype, identName)
597
598
  );
598
599
  }
599
600
 
@@ -694,7 +695,7 @@ function createMissingAttrs(
694
695
  for (const attr of localAttrs) {
695
696
  nextAttrs[attr.id] = attr;
696
697
  }
697
- return [new AttrsStore(nextAttrs, attrsStore.linkIndex), addOps];
698
+ return [new AttrsStoreClass(nextAttrs, attrsStore.linkIndex), addOps];
698
699
  }
699
700
  return [attrsStore, addOps];
700
701
  }
package/src/instaql.ts CHANGED
@@ -900,8 +900,8 @@ export default function query(
900
900
  }: {
901
901
  store: s.Store;
902
902
  attrsStore: s.AttrsStore;
903
- pageInfo: any;
904
- aggregate: any;
903
+ pageInfo?: any;
904
+ aggregate?: any;
905
905
  },
906
906
  q,
907
907
  ) {
package/src/store.ts CHANGED
@@ -18,23 +18,23 @@ export type Store = {
18
18
  eav: Map<string, Map<string, Map<any, Triple>>>;
19
19
  aev: Map<string, Map<string, Map<any, Triple>>>;
20
20
  vae: Map<any, Map<string, Map<string, Triple>>>;
21
- useDateObjects: boolean | null;
22
- cardinalityInference: boolean | null;
21
+ useDateObjects: boolean | null | undefined;
22
+ cardinalityInference: boolean | null | undefined;
23
23
  };
24
24
 
25
25
  type StoreJsonVersion0 = {
26
26
  __type: 'store';
27
27
  attrs: Attrs;
28
28
  triples: Triple[];
29
- cardinalityInference: boolean | null;
29
+ cardinalityInference: boolean | null | undefined;
30
30
  linkIndex: LinkIndex | null;
31
- useDateObjects: boolean | null;
31
+ useDateObjects: boolean | null | undefined;
32
32
  };
33
33
 
34
34
  type StoreJsonVersion1 = {
35
35
  triples: Triple[];
36
- cardinalityInference: boolean | null;
37
- useDateObjects: boolean | null;
36
+ cardinalityInference: boolean | null | undefined;
37
+ useDateObjects: boolean | null | undefined;
38
38
  version: 1;
39
39
  };
40
40
 
@@ -45,7 +45,22 @@ export type AttrsStoreJson = {
45
45
  linkIndex: LinkIndex | null;
46
46
  };
47
47
 
48
- export class AttrsStore {
48
+ export interface AttrsStore {
49
+ attrs: Attrs;
50
+ linkIndex: LinkIndex | null;
51
+ resetAttrIndexes(): void;
52
+ addAttr(attr: InstantDBAttr): void;
53
+ deleteAttr(attrId: string): void;
54
+ updateAttr(partialAttr: Partial<InstantDBAttr> & { id: string }): void;
55
+ getAttr(id: string): InstantDBAttr | undefined;
56
+ blobAttrs: Map<string, Map<string, InstantDBAttr>>;
57
+ primaryKeys: Map<string, InstantDBAttr>;
58
+ forwardIdents: Map<string, Map<string, InstantDBAttr>>;
59
+ revIdents: Map<string, Map<string, InstantDBAttr>>;
60
+ toJSON(): AttrsStoreJson;
61
+ }
62
+
63
+ export class AttrsStoreClass implements AttrsStore {
49
64
  public attrs: Attrs;
50
65
  public linkIndex: LinkIndex | null;
51
66
  private _blobAttrs: Map<string, Map<string, InstantDBAttr>> | null = null;
@@ -53,7 +68,6 @@ export class AttrsStore {
53
68
  private _forwardIdents: Map<string, Map<string, InstantDBAttr>> | null = null;
54
69
  private _revIdents: Map<string, Map<string, InstantDBAttr>> | null = null;
55
70
  constructor(attrs: Attrs, linkIndex: LinkIndex | null) {
56
- console.log('attrs init', new Error('trace'));
57
71
  this.attrs = attrs;
58
72
  this.linkIndex = linkIndex;
59
73
  }
@@ -187,19 +201,22 @@ function deleteInMap(m, path) {
187
201
  deleteInMap(m.get(head), tail);
188
202
  }
189
203
 
190
- function setInMap(m, path, value) {
191
- if (path.length === 0) throw new Error('path must have at least one element');
192
- if (path.length === 1) {
193
- m.set(path[0], value);
194
- return;
204
+ function setInMap(m: Map<any, any>, path: any[], value: any) {
205
+ let current = m;
206
+ const lastI = path.length - 1;
207
+ for (let i = 0; i < lastI; i++) {
208
+ const part = path[i];
209
+
210
+ let nextMap = current.get(part);
211
+ if (nextMap === undefined) {
212
+ nextMap = new Map();
213
+ current.set(part, nextMap);
214
+ }
215
+ current = nextMap;
195
216
  }
196
- const [head, ...tail] = path;
197
- let nextM = m.get(head);
198
- if (!nextM) {
199
- nextM = new Map();
200
- m.set(head, nextM);
217
+ if (lastI > -1) {
218
+ current.set(path[lastI], value);
201
219
  }
202
- setInMap(nextM, tail, value);
203
220
  }
204
221
 
205
222
  function isDateAttr(attr: InstantDBAttr) {
@@ -209,7 +226,7 @@ function isDateAttr(attr: InstantDBAttr) {
209
226
  function createTripleIndexes(
210
227
  attrsStore: AttrsStore,
211
228
  triples: Triple[],
212
- useDateObjects: boolean | null,
229
+ useDateObjects: boolean | null | undefined,
213
230
  ): Pick<Store, 'eav' | 'aev' | 'vae'> {
214
231
  const eav = new Map();
215
232
  const aev = new Map();
@@ -286,10 +303,10 @@ export function attrsStoreFromJSON(
286
303
  storeJSON: StoreJson | null,
287
304
  ): AttrsStore | undefined {
288
305
  if (attrsStoreJSON) {
289
- return new AttrsStore(attrsStoreJSON.attrs, attrsStoreJSON.linkIndex);
306
+ return new AttrsStoreClass(attrsStoreJSON.attrs, attrsStoreJSON.linkIndex);
290
307
  }
291
308
  if (storeJSON && '__type' in storeJSON) {
292
- return new AttrsStore(storeJSON.attrs, storeJSON.linkIndex);
309
+ return new AttrsStoreClass(storeJSON.attrs, storeJSON.linkIndex);
293
310
  }
294
311
  }
295
312
 
@@ -304,8 +321,8 @@ export function hasEntity(store: Store, e: string) {
304
321
  export function createStore(
305
322
  attrsStore: AttrsStore,
306
323
  triples: Triple[],
307
- enableCardinalityInference: boolean | null,
308
- useDateObjects: boolean | null,
324
+ enableCardinalityInference?: boolean | null,
325
+ useDateObjects?: boolean | null,
309
326
  ): Store {
310
327
  const store = createTripleIndexes(
311
328
  attrsStore,
@@ -876,7 +893,11 @@ function findTriple(
876
893
  return getInMap(store.eav, [eid, aid]);
877
894
  }
878
895
 
879
- export function transact(store: Store, attrsStore: AttrsStore, txSteps) {
896
+ export function transact(
897
+ store: Store,
898
+ attrsStore: AttrsStore,
899
+ txSteps,
900
+ ): { store: Store; attrsStore: AttrsStore } {
880
901
  const txStepsFiltered = txSteps.filter(
881
902
  ([action, eid, attrId, value, opts]) => {
882
903
  if (action !== 'add-triple' && action !== 'deep-merge-triple') {
@@ -915,9 +936,19 @@ export function transact(store: Store, attrsStore: AttrsStore, txSteps) {
915
936
  },
916
937
  );
917
938
 
918
- return create(store, (draft) => {
919
- txStepsFiltered.forEach((txStep) => {
920
- applyTxStep(draft, attrsStore, txStep);
921
- });
922
- });
939
+ return create(
940
+ { store, attrsStore },
941
+ (draft) => {
942
+ txStepsFiltered.forEach((txStep) => {
943
+ applyTxStep(draft.store, draft.attrsStore, txStep);
944
+ });
945
+ },
946
+ {
947
+ mark: (target) => {
948
+ if (target instanceof AttrsStoreClass) {
949
+ return 'immutable';
950
+ }
951
+ },
952
+ },
953
+ );
923
954
  }
@@ -1,29 +0,0 @@
1
- import { bench } from 'vitest';
2
-
3
- import zenecaAttrs from './data/zeneca/attrs.json';
4
- import zenecaTriples from './data/zeneca/triples.json';
5
- import { createStore } from '../../src/store';
6
- import query from '../../src/instaql';
7
-
8
- const zenecaIdToAttr = zenecaAttrs.reduce((res, x) => {
9
- res[x.id] = x;
10
- return res;
11
- }, {});
12
-
13
- const store = createStore(zenecaIdToAttr, zenecaTriples);
14
-
15
- bench('big query', () => {
16
- query(
17
- { store },
18
- {
19
- users: {
20
- bookshelves: {
21
- books: {},
22
- users: {
23
- bookshelves: {},
24
- },
25
- },
26
- },
27
- },
28
- );
29
- });