@instantdb/core 0.22.88 → 0.22.89-experimental.drewh-fix-export.20277749804.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 (65) 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} +215 -212
  8. package/dist/commonjs/Reactor.d.ts +23 -6
  9. package/dist/commonjs/Reactor.d.ts.map +1 -1
  10. package/dist/commonjs/Reactor.js +110 -45
  11. package/dist/commonjs/Reactor.js.map +1 -1
  12. package/dist/commonjs/SyncTable.d.ts +4 -1
  13. package/dist/commonjs/SyncTable.d.ts.map +1 -1
  14. package/dist/commonjs/SyncTable.js +35 -37
  15. package/dist/commonjs/SyncTable.js.map +1 -1
  16. package/dist/commonjs/instaml.d.ts +17 -4
  17. package/dist/commonjs/instaml.d.ts.map +1 -1
  18. package/dist/commonjs/instaml.js +115 -82
  19. package/dist/commonjs/instaml.js.map +1 -1
  20. package/dist/commonjs/instaql.d.ts +4 -3
  21. package/dist/commonjs/instaql.d.ts.map +1 -1
  22. package/dist/commonjs/instaql.js +65 -63
  23. package/dist/commonjs/instaql.js.map +1 -1
  24. package/dist/commonjs/reactorTypes.d.ts +29 -0
  25. package/dist/commonjs/reactorTypes.d.ts.map +1 -0
  26. package/dist/commonjs/reactorTypes.js +3 -0
  27. package/dist/commonjs/reactorTypes.js.map +1 -0
  28. package/dist/commonjs/store.d.ts +67 -25
  29. package/dist/commonjs/store.d.ts.map +1 -1
  30. package/dist/commonjs/store.js +177 -81
  31. package/dist/commonjs/store.js.map +1 -1
  32. package/dist/esm/Reactor.d.ts +23 -6
  33. package/dist/esm/Reactor.d.ts.map +1 -1
  34. package/dist/esm/Reactor.js +111 -46
  35. package/dist/esm/Reactor.js.map +1 -1
  36. package/dist/esm/SyncTable.d.ts +4 -1
  37. package/dist/esm/SyncTable.d.ts.map +1 -1
  38. package/dist/esm/SyncTable.js +35 -37
  39. package/dist/esm/SyncTable.js.map +1 -1
  40. package/dist/esm/instaml.d.ts +17 -4
  41. package/dist/esm/instaml.d.ts.map +1 -1
  42. package/dist/esm/instaml.js +112 -77
  43. package/dist/esm/instaml.js.map +1 -1
  44. package/dist/esm/instaql.d.ts +4 -3
  45. package/dist/esm/instaql.d.ts.map +1 -1
  46. package/dist/esm/instaql.js +65 -63
  47. package/dist/esm/instaql.js.map +1 -1
  48. package/dist/esm/reactorTypes.d.ts +29 -0
  49. package/dist/esm/reactorTypes.d.ts.map +1 -0
  50. package/dist/esm/reactorTypes.js +2 -0
  51. package/dist/esm/reactorTypes.js.map +1 -0
  52. package/dist/esm/store.d.ts +67 -25
  53. package/dist/esm/store.d.ts.map +1 -1
  54. package/dist/esm/store.js +174 -81
  55. package/dist/esm/store.js.map +1 -1
  56. package/dist/standalone/index.js +1605 -1415
  57. package/dist/standalone/index.umd.cjs +3 -3
  58. package/package.json +2 -2
  59. package/src/Reactor.js +152 -75
  60. package/src/SyncTable.ts +85 -45
  61. package/src/{instaml.js → instaml.ts} +201 -96
  62. package/src/instaql.ts +88 -62
  63. package/src/reactorTypes.ts +32 -0
  64. package/src/store.ts +257 -101
  65. package/__tests__/src/instaql.bench.js +0 -29
@@ -3,11 +3,15 @@ import zenecaAttrs from './data/zeneca/attrs.json';
3
3
  import zenecaTriples from './data/zeneca/triples.json';
4
4
  import {
5
5
  createStore,
6
- transact,
7
6
  allMapValues,
8
7
  toJSON,
9
8
  fromJSON,
10
9
  transact,
10
+ AttrsStoreClass,
11
+ getAttrByFwdIdentName,
12
+ Store,
13
+ AttrsStore,
14
+ attrsStoreFromJSON,
11
15
  } from '../../src/store';
12
16
  import query from '../../src/instaql';
13
17
  import uuid from '../../src/utils/uuid';
@@ -18,14 +22,26 @@ import * as instatx from '../../src/instatx';
18
22
  import { i, id } from '../../src';
19
23
  import { createLinkIndex } from '../../src/utils/linkIndex';
20
24
 
21
- const zenecaIdToAttr = zenecaAttrs.reduce((res, x) => {
22
- res[x.id] = x;
23
- return res;
24
- }, {});
25
-
26
- const store = createStore(zenecaIdToAttr, zenecaTriples);
27
-
28
- function checkIndexIntegrity(store) {
25
+ const zenecaAttrsStore = new AttrsStoreClass(
26
+ zenecaAttrs.reduce((res, x) => {
27
+ res[x.id] = x;
28
+ return res;
29
+ }, {}),
30
+ null,
31
+ );
32
+
33
+ const store = createStore(
34
+ zenecaAttrsStore,
35
+ zenecaTriples as [string, string, any, number][],
36
+ );
37
+
38
+ function checkIndexIntegrity({
39
+ store,
40
+ attrsStore,
41
+ }: {
42
+ store: Store;
43
+ attrsStore: AttrsStore;
44
+ }) {
29
45
  const tripleSort = (a, b) => {
30
46
  const [e_a, aid_a, v_a, t_a] = a;
31
47
  const [e_b, aid_b, v_b, t_b] = b;
@@ -48,8 +64,13 @@ function checkIndexIntegrity(store) {
48
64
  const aevTriples = allMapValues(store.aev, 3).sort(tripleSort);
49
65
  const vaeTriples = allMapValues(store.vae, 3);
50
66
 
51
- // Check eav and aev have all the same values
52
- expect(eavTriples).toEqual(aevTriples);
67
+ // Check eav and aev have all the same triples
68
+ for (let i = 0; i < eavTriples.length; i++) {
69
+ const et = eavTriples[i];
70
+ const at = aevTriples[i];
71
+ expect(et).toEqual(at);
72
+ }
73
+ expect(eavTriples.length).toEqual(aevTriples.length);
53
74
 
54
75
  // Check vae doesn't have extra triples
55
76
  for (const triple of vaeTriples) {
@@ -60,7 +81,7 @@ function checkIndexIntegrity(store) {
60
81
  // Check vae has all of the triples it should have
61
82
  for (const triple of eavTriples) {
62
83
  const [e, a, v] = triple;
63
- const attr = store.attrs[a];
84
+ const attr = attrsStore.getAttr(a)!;
64
85
  if (attr['value-type'] === 'ref') {
65
86
  expect(store.vae.get(v)?.get(a)?.get(e)).toEqual(triple);
66
87
  }
@@ -70,13 +91,13 @@ function checkIndexIntegrity(store) {
70
91
  test('simple add', () => {
71
92
  const id = uuid();
72
93
  const chunk = tx.users[id].update({ handle: 'bobby' });
73
- const txSteps = instaml.transform({ attrs: store.attrs }, chunk);
74
- const newStore = transact(store, txSteps);
75
- expect(
76
- query({ store: newStore }, { users: {} }).data.users.map((x) => x.handle),
77
- ).contains('bobby');
94
+ const txSteps = instaml.transform({ attrsStore: zenecaAttrsStore }, chunk);
95
+ const newCtx = transact(store, zenecaAttrsStore, txSteps);
96
+ expect(query(newCtx, { users: {} }).data.users.map((x) => x.handle)).contains(
97
+ 'bobby',
98
+ );
78
99
 
79
- checkIndexIntegrity(newStore);
100
+ checkIndexIntegrity(newCtx);
80
101
  });
81
102
 
82
103
  test('cardinality-one add', () => {
@@ -84,17 +105,17 @@ test('cardinality-one add', () => {
84
105
  const chunk = tx.users[id]
85
106
  .update({ handle: 'bobby' })
86
107
  .update({ handle: 'bob' });
87
- const txSteps = instaml.transform({ attrs: store.attrs }, chunk);
88
- const newStore = transact(store, txSteps);
108
+ const txSteps = instaml.transform({ attrsStore: zenecaAttrsStore }, chunk);
109
+ const newCtx = transact(store, zenecaAttrsStore, txSteps);
89
110
  const ret = datalog
90
- .query(newStore, {
111
+ .query(newCtx.store, {
91
112
  find: ['?v'],
92
113
  where: [[id, '?attr', '?v']],
93
114
  })
94
115
  .flatMap((vec) => vec[0]);
95
116
  expect(ret).contains('bob');
96
117
  expect(ret).not.contains('bobby');
97
- checkIndexIntegrity(newStore);
118
+ checkIndexIntegrity(newCtx);
98
119
  });
99
120
 
100
121
  test('link/unlink', () => {
@@ -106,23 +127,20 @@ test('link/unlink', () => {
106
127
  const bookshelfChunk = tx.bookshelves[bookshelfId].update({
107
128
  name: 'my books',
108
129
  });
109
- const txSteps = instaml.transform({ attrs: store.attrs }, [
130
+ const txSteps = instaml.transform({ attrsStore: zenecaAttrsStore }, [
110
131
  userChunk,
111
132
  bookshelfChunk,
112
133
  ]);
113
- const newStore = transact(store, txSteps);
134
+ const newCtx = transact(store, zenecaAttrsStore, txSteps);
114
135
  expect(
115
- query(
116
- { store: newStore },
117
- {
118
- users: {
119
- $: { where: { handle: 'bobby' } },
120
- bookshelves: {},
121
- },
136
+ query(newCtx, {
137
+ users: {
138
+ $: { where: { handle: 'bobby' } },
139
+ bookshelves: {},
122
140
  },
123
- ).data.users.map((x) => [x.handle, x.bookshelves.map((x) => x.name)]),
141
+ }).data.users.map((x) => [x.handle, x.bookshelves.map((x) => x.name)]),
124
142
  ).toEqual([['bobby', ['my books']]]);
125
- checkIndexIntegrity(newStore);
143
+ checkIndexIntegrity(newCtx);
126
144
 
127
145
  const secondBookshelfId = uuid();
128
146
  const secondBookshelfChunk = tx.bookshelves[secondBookshelfId].update({
@@ -133,23 +151,20 @@ test('link/unlink', () => {
133
151
  bookshelves: bookshelfId,
134
152
  })
135
153
  .link({ bookshelves: secondBookshelfId });
136
- const secondTxSteps = instaml.transform({ attrs: newStore.attrs }, [
154
+ const secondTxSteps = instaml.transform({ attrsStore: newCtx.attrsStore }, [
137
155
  unlinkFirstChunk,
138
156
  secondBookshelfChunk,
139
157
  ]);
140
- const secondStore = transact(newStore, secondTxSteps);
158
+ const secondCtx = transact(newCtx.store, newCtx.attrsStore, secondTxSteps);
141
159
  expect(
142
- query(
143
- { store: secondStore },
144
- {
145
- users: {
146
- $: { where: { handle: 'bobby' } },
147
- bookshelves: {},
148
- },
160
+ query(secondCtx, {
161
+ users: {
162
+ $: { where: { handle: 'bobby' } },
163
+ bookshelves: {},
149
164
  },
150
- ).data.users.map((x) => [x.handle, x.bookshelves.map((x) => x.name)]),
165
+ }).data.users.map((x) => [x.handle, x.bookshelves.map((x) => x.name)]),
151
166
  ).toEqual([['bobby', ['my second books']]]);
152
- checkIndexIntegrity(secondStore);
167
+ checkIndexIntegrity(secondCtx);
153
168
  });
154
169
 
155
170
  test('link/unlink multi', () => {
@@ -166,25 +181,22 @@ test('link/unlink multi', () => {
166
181
  const bookshelf2Chunk = tx.bookshelves[bookshelfId2].update({
167
182
  name: 'my books 2',
168
183
  });
169
- const txSteps = instaml.transform({ attrs: store.attrs }, [
184
+ const txSteps = instaml.transform({ attrsStore: zenecaAttrsStore }, [
170
185
  userChunk,
171
186
  bookshelf1Chunk,
172
187
  bookshelf2Chunk,
173
188
  ]);
174
189
 
175
- const newStore = transact(store, txSteps);
190
+ const newCtx = transact(store, zenecaAttrsStore, txSteps);
176
191
  expect(
177
- query(
178
- { store: newStore },
179
- {
180
- users: {
181
- $: { where: { handle: 'bobby' } },
182
- bookshelves: {},
183
- },
192
+ query(newCtx, {
193
+ users: {
194
+ $: { where: { handle: 'bobby' } },
195
+ bookshelves: {},
184
196
  },
185
- ).data.users.map((x) => [x.handle, x.bookshelves.map((x) => x.name)]),
197
+ }).data.users.map((x) => [x.handle, x.bookshelves.map((x) => x.name)]),
186
198
  ).toEqual([['bobby', ['my books 1', 'my books 2']]]);
187
- checkIndexIntegrity(newStore);
199
+ checkIndexIntegrity(newCtx);
188
200
 
189
201
  const bookshelfId3 = uuid();
190
202
  const bookshelf3Chunk = tx.bookshelves[bookshelfId3].update({
@@ -195,23 +207,20 @@ test('link/unlink multi', () => {
195
207
  bookshelves: [bookshelfId1, bookshelfId2],
196
208
  })
197
209
  .link({ bookshelves: bookshelfId3 });
198
- const secondTxSteps = instaml.transform({ attrs: newStore.attrs }, [
210
+ const secondTxSteps = instaml.transform({ attrsStore: newCtx.attrsStore }, [
199
211
  unlinkChunk,
200
212
  bookshelf3Chunk,
201
213
  ]);
202
- const secondStore = transact(newStore, secondTxSteps);
214
+ const secondCtx = transact(newCtx.store, newCtx.attrsStore, secondTxSteps);
203
215
  expect(
204
- query(
205
- { store: secondStore },
206
- {
207
- users: {
208
- $: { where: { handle: 'bobby' } },
209
- bookshelves: {},
210
- },
216
+ query(secondCtx, {
217
+ users: {
218
+ $: { where: { handle: 'bobby' } },
219
+ bookshelves: {},
211
220
  },
212
- ).data.users.map((x) => [x.handle, x.bookshelves.map((x) => x.name)]),
221
+ }).data.users.map((x) => [x.handle, x.bookshelves.map((x) => x.name)]),
213
222
  ).toEqual([['bobby', ['my books 3']]]);
214
- checkIndexIntegrity(secondStore);
223
+ checkIndexIntegrity(secondCtx);
215
224
  });
216
225
 
217
226
  test('link/unlink without update', () => {
@@ -221,30 +230,28 @@ test('link/unlink without update', () => {
221
230
  const bookshelfChunk = tx.bookshelves[bookshelfId].update({
222
231
  name: 'my books',
223
232
  });
224
- const txSteps = instaml.transform({ attrs: store.attrs }, [
233
+ const txSteps = instaml.transform({ attrsStore: zenecaAttrsStore }, [
225
234
  userChunk,
226
235
  bookshelfChunk,
227
236
  ]);
228
- const store2 = transact(store, txSteps);
237
+ const ctx2 = transact(store, zenecaAttrsStore, txSteps);
229
238
 
230
239
  const linkChunk = tx.users[userId].link({ bookshelves: bookshelfId });
231
- const store3 = transact(
232
- store2,
233
- instaml.transform({ attrs: store2.attrs }, [linkChunk]),
240
+ const ctx3 = transact(
241
+ ctx2.store,
242
+ ctx2.attrsStore,
243
+ instaml.transform(ctx2, [linkChunk]),
234
244
  );
235
245
 
236
246
  expect(
237
- query(
238
- { store: store3 },
239
- {
240
- users: {
241
- $: { where: { handle: 'bobby' } },
242
- bookshelves: {},
243
- },
247
+ query(ctx3, {
248
+ users: {
249
+ $: { where: { handle: 'bobby' } },
250
+ bookshelves: {},
244
251
  },
245
- ).data.users.map((x) => [x.handle, x.bookshelves.map((x) => x.name)]),
252
+ }).data.users.map((x) => [x.handle, x.bookshelves.map((x) => x.name)]),
246
253
  ).toEqual([['bobby', ['my books']]]);
247
- checkIndexIntegrity(store3);
254
+ checkIndexIntegrity(ctx3);
248
255
  });
249
256
 
250
257
  test('delete entity', () => {
@@ -256,21 +263,21 @@ test('delete entity', () => {
256
263
  const bookshelfChunk = tx.bookshelves[bookshelfId].update({
257
264
  name: 'my books',
258
265
  });
259
- const txSteps = instaml.transform({ attrs: store.attrs }, [
266
+ const txSteps = instaml.transform({ attrsStore: zenecaAttrsStore }, [
260
267
  userChunk,
261
268
  bookshelfChunk,
262
269
  ]);
263
- const newStore = transact(store, txSteps);
264
- checkIndexIntegrity(newStore);
270
+ const newCtx = transact(store, zenecaAttrsStore, txSteps);
271
+ checkIndexIntegrity(newCtx);
265
272
 
266
273
  const retOne = datalog
267
- .query(newStore, {
274
+ .query(newCtx.store, {
268
275
  find: ['?v'],
269
276
  where: [[bookshelfId, '?attr', '?v']],
270
277
  })
271
278
  .flatMap((vec) => vec[0]);
272
279
  const retTwo = datalog
273
- .query(newStore, {
280
+ .query(newCtx.store, {
274
281
  find: ['?v'],
275
282
  where: [['?v', '?attr', bookshelfId]],
276
283
  })
@@ -279,18 +286,18 @@ test('delete entity', () => {
279
286
  expect(retTwo).contains(userId);
280
287
 
281
288
  const txStepsTwo = instaml.transform(
282
- { attrs: newStore.attrs },
289
+ newCtx,
283
290
  tx.bookshelves[bookshelfId].delete(),
284
291
  );
285
- const newStoreTwo = transact(newStore, txStepsTwo);
292
+ const newCtxTwo = transact(newCtx.store, newCtx.attrsStore, txStepsTwo);
286
293
  const retThree = datalog
287
- .query(newStoreTwo, {
294
+ .query(newCtxTwo.store, {
288
295
  find: ['?v'],
289
296
  where: [[bookshelfId, '?attr', '?v']],
290
297
  })
291
298
  .flatMap((vec) => vec[0]);
292
299
  const retFour = datalog
293
- .query(newStoreTwo, {
300
+ .query(newCtxTwo.store, {
294
301
  find: ['?v'],
295
302
  where: [['?v', '?attr', bookshelfId]],
296
303
  })
@@ -298,7 +305,7 @@ test('delete entity', () => {
298
305
 
299
306
  expect(retThree).toEqual([]);
300
307
  expect(retFour).toEqual([]);
301
- checkIndexIntegrity(newStoreTwo);
308
+ checkIndexIntegrity(newCtxTwo);
302
309
  });
303
310
 
304
311
  test('on-delete cascade', () => {
@@ -315,30 +322,25 @@ test('on-delete cascade', () => {
315
322
  const chunk3 = tx.books[book3]
316
323
  .update({ title: 'book3', description: 'series' })
317
324
  .link({ prequel: book2 });
318
- const txSteps = instaml.transform({ attrs: store.attrs }, [
325
+ const txSteps = instaml.transform({ attrsStore: zenecaAttrsStore }, [
319
326
  chunk1,
320
327
  chunk2,
321
328
  chunk3,
322
329
  ]);
323
- const newStore = transact(store, txSteps);
324
- checkIndexIntegrity(newStore);
330
+ const newCtx = transact(store, zenecaAttrsStore, txSteps);
331
+ checkIndexIntegrity(newCtx);
325
332
  expect(
326
- query(
327
- { store: newStore },
328
- { books: { $: { where: { description: 'series' } } } },
329
- ).data.books.map((x) => x.title),
333
+ query(newCtx, {
334
+ books: { $: { where: { description: 'series' } } },
335
+ }).data.books.map((x) => x.title),
330
336
  ).toEqual(['book1', 'book2', 'book3']);
331
337
 
332
- const txStepsTwo = instaml.transform(
333
- { attrs: newStore.attrs },
334
- tx.books[book1].delete(),
335
- );
336
- const newStoreTwo = transact(newStore, txStepsTwo);
338
+ const txStepsTwo = instaml.transform(newCtx, tx.books[book1].delete());
339
+ const newCtxTwo = transact(newCtx.store, newCtx.attrsStore, txStepsTwo);
337
340
  expect(
338
- query(
339
- { store: newStoreTwo },
340
- { books: { $: { where: { description: 'series' } } } },
341
- ).data.books.map((x) => x.title),
341
+ query(newCtxTwo, {
342
+ books: { $: { where: { description: 'series' } } },
343
+ }).data.books.map((x) => x.title),
342
344
  ).toEqual([]);
343
345
  });
344
346
 
@@ -361,30 +363,25 @@ test('on-delete-reverse cascade', () => {
361
363
  description: 'series',
362
364
  })
363
365
  .link({ next: [book2, book3] });
364
- const txSteps = instaml.transform({ attrs: store.attrs }, [
366
+ const txSteps = instaml.transform({ attrsStore: zenecaAttrsStore }, [
365
367
  chunk2,
366
368
  chunk3,
367
369
  chunk1,
368
370
  ]);
369
- const newStore = transact(store, txSteps);
370
- checkIndexIntegrity(newStore);
371
+ const newCtx = transact(store, zenecaAttrsStore, txSteps);
372
+ checkIndexIntegrity(newCtx);
371
373
  expect(
372
- query(
373
- { store: newStore },
374
- { books: { $: { where: { description: 'series' } } } },
375
- ).data.books.map((x) => x.title),
374
+ query(newCtx, {
375
+ books: { $: { where: { description: 'series' } } },
376
+ }).data.books.map((x) => x.title),
376
377
  ).toEqual(['book2', 'book3', 'book1']);
377
378
 
378
- const txStepsTwo = instaml.transform(
379
- { attrs: newStore.attrs },
380
- tx.books[book1].delete(),
381
- );
382
- const newStoreTwo = transact(newStore, txStepsTwo);
379
+ const txStepsTwo = instaml.transform(newCtx, tx.books[book1].delete());
380
+ const newCtxTwo = transact(newCtx.store, newCtx.attrsStore, txStepsTwo);
383
381
  expect(
384
- query(
385
- { store: newStoreTwo },
386
- { books: { $: { where: { description: 'series' } } } },
387
- ).data.books.map((x) => x.title),
382
+ query(newCtxTwo, {
383
+ books: { $: { where: { description: 'series' } } },
384
+ }).data.books.map((x) => x.title),
388
385
  ).toEqual([]);
389
386
  });
390
387
 
@@ -395,49 +392,45 @@ test('new attrs', () => {
395
392
  .update({ handle: 'bobby' })
396
393
  .link({ colors: colorId });
397
394
  const colorChunk = tx.colors[colorId].update({ name: 'red' });
398
- const txSteps = instaml.transform({ attrs: store.attrs }, [
395
+ const txSteps = instaml.transform({ attrsStore: zenecaAttrsStore }, [
399
396
  userChunk,
400
397
  colorChunk,
401
398
  ]);
402
- const newStore = transact(store, txSteps);
399
+ const newCtx = transact(store, zenecaAttrsStore, txSteps);
403
400
  expect(
404
- query(
405
- { store: newStore },
406
- {
407
- users: {
408
- $: { where: { handle: 'bobby' } },
409
- colors: {},
410
- },
401
+ query(newCtx, {
402
+ users: {
403
+ $: { where: { handle: 'bobby' } },
404
+ colors: {},
411
405
  },
412
- ).data.users.map((x) => [x.handle, x.colors.map((x) => x.name)]),
406
+ }).data.users.map((x) => [x.handle, x.colors.map((x) => x.name)]),
413
407
  ).toEqual([['bobby', ['red']]]);
414
408
 
415
- checkIndexIntegrity(newStore);
409
+ checkIndexIntegrity(newCtx);
416
410
  });
417
411
 
418
412
  test('delete attr', () => {
419
413
  expect(
420
- query({ store }, { users: {} }).data.users.map((x) => [
421
- x.handle,
422
- x.fullName,
423
- ]),
414
+ query(
415
+ { store, attrsStore: zenecaAttrsStore },
416
+ { users: {} },
417
+ ).data.users.map((x) => [x.handle, x.fullName]),
424
418
  ).toEqual([
425
419
  ['joe', 'Joe Averbukh'],
426
420
  ['alex', 'Alex'],
427
421
  ['stopa', 'Stepan Parunashvili'],
428
422
  ['nicolegf', 'Nicole'],
429
423
  ]);
430
- const fullNameAttr = instaml.getAttrByFwdIdentName(
431
- store.attrs,
424
+ const fullNameAttr = getAttrByFwdIdentName(
425
+ zenecaAttrsStore,
432
426
  'users',
433
427
  'fullName',
434
428
  );
435
- const newStore = transact(store, [['delete-attr', fullNameAttr.id]]);
429
+ const newCtx = transact(store, zenecaAttrsStore, [
430
+ ['delete-attr', fullNameAttr!.id],
431
+ ]);
436
432
  expect(
437
- query({ store: newStore }, { users: {} }).data.users.map((x) => [
438
- x.handle,
439
- x.fullName,
440
- ]),
433
+ query(newCtx, { users: {} }).data.users.map((x) => [x.handle, x.fullName]),
441
434
  ).toEqual([
442
435
  ['joe', undefined],
443
436
  ['alex', undefined],
@@ -445,41 +438,38 @@ test('delete attr', () => {
445
438
  ['nicolegf', undefined],
446
439
  ]);
447
440
 
448
- checkIndexIntegrity(newStore);
441
+ checkIndexIntegrity(newCtx);
449
442
  });
450
443
 
451
444
  test('update attr', () => {
452
445
  expect(
453
- query({ store }, { users: {} }).data.users.map((x) => [
454
- x.handle,
455
- x.fullName,
456
- ]),
446
+ query(
447
+ { store, attrsStore: zenecaAttrsStore },
448
+ { users: {} },
449
+ ).data.users.map((x) => [x.handle, x.fullName]),
457
450
  ).toEqual([
458
451
  ['joe', 'Joe Averbukh'],
459
452
  ['alex', 'Alex'],
460
453
  ['stopa', 'Stepan Parunashvili'],
461
454
  ['nicolegf', 'Nicole'],
462
455
  ]);
463
- const fullNameAttr = instaml.getAttrByFwdIdentName(
464
- store.attrs,
456
+ const fullNameAttr = getAttrByFwdIdentName(
457
+ zenecaAttrsStore,
465
458
  'users',
466
459
  'fullName',
467
460
  );
468
- const fwdIdent = fullNameAttr['forward-identity'];
469
- const newStore = transact(store, [
461
+ const fwdIdent = fullNameAttr!['forward-identity'];
462
+ const newCtx = transact(store, zenecaAttrsStore, [
470
463
  [
471
464
  'update-attr',
472
465
  {
473
- id: fullNameAttr.id,
466
+ id: fullNameAttr!.id,
474
467
  'forward-identity': [fwdIdent[0], 'users', 'fullNamez'],
475
468
  },
476
469
  ],
477
470
  ]);
478
471
  expect(
479
- query({ store: newStore }, { users: {} }).data.users.map((x) => [
480
- x.handle,
481
- x.fullNamez,
482
- ]),
472
+ query(newCtx, { users: {} }).data.users.map((x) => [x.handle, x.fullNamez]),
483
473
  ).toEqual([
484
474
  ['joe', 'Joe Averbukh'],
485
475
  ['alex', 'Alex'],
@@ -489,7 +479,7 @@ test('update attr', () => {
489
479
  });
490
480
 
491
481
  test('JSON serialization round-trips', () => {
492
- const newStore = fromJSON(toJSON(store));
482
+ const newStore = fromJSON(zenecaAttrsStore, toJSON(store));
493
483
  expect(store).toEqual(newStore);
494
484
  });
495
485
 
@@ -499,21 +489,22 @@ test('ruleParams no-ops', () => {
499
489
  .ruleParams({ guestId: 'bobby' })
500
490
  .update({ handle: 'bobby' });
501
491
 
502
- const txSteps = instaml.transform({ attrs: store.attrs }, chunk);
503
- const newStore = transact(store, txSteps);
504
- expect(
505
- query({ store: newStore }, { users: {} }).data.users.map((x) => x.handle),
506
- ).contains('bobby');
492
+ const txSteps = instaml.transform({ attrsStore: zenecaAttrsStore }, chunk);
493
+ const newCtx = transact(store, zenecaAttrsStore, txSteps);
494
+ expect(query(newCtx, { users: {} }).data.users.map((x) => x.handle)).contains(
495
+ 'bobby',
496
+ );
507
497
 
508
- checkIndexIntegrity(newStore);
498
+ checkIndexIntegrity(newCtx);
509
499
  });
510
500
 
511
501
  test('deepMerge', () => {
512
502
  const gameId = uuid();
513
- const gameStore = transact(
503
+ const gameCtx = transact(
514
504
  store,
505
+ zenecaAttrsStore,
515
506
  instaml.transform(
516
- { attrs: store.attrs },
507
+ { attrsStore: zenecaAttrsStore },
517
508
  tx.games[gameId].update({
518
509
  state: {
519
510
  score: 100,
@@ -525,10 +516,14 @@ test('deepMerge', () => {
525
516
  }),
526
517
  ),
527
518
  );
528
- const updatedStore = transact(
529
- gameStore,
519
+
520
+ checkIndexIntegrity(gameCtx);
521
+
522
+ const updatedCtx = transact(
523
+ gameCtx.store,
524
+ gameCtx.attrsStore,
530
525
  instaml.transform(
531
- { attrs: gameStore.attrs },
526
+ gameCtx,
532
527
  tx.games[gameId].merge({
533
528
  state: {
534
529
  // Objects update deeply
@@ -549,10 +544,10 @@ test('deepMerge', () => {
549
544
  }),
550
545
  ),
551
546
  );
552
- const updatedGame = query(
553
- { store: updatedStore },
554
- { games: { $: { where: { id: gameId } } } },
555
- ).data.games[0];
547
+
548
+ const updatedGame = query(updatedCtx, {
549
+ games: { $: { where: { id: gameId } } },
550
+ }).data.games[0];
556
551
  expect(updatedGame.state).toEqual({
557
552
  playerStats: {
558
553
  health: 50,
@@ -564,7 +559,7 @@ test('deepMerge', () => {
564
559
  inventory: ['shield'],
565
560
  locations: ['forest', undefined, 'castle'],
566
561
  });
567
- checkIndexIntegrity(updatedGame);
562
+ checkIndexIntegrity(updatedCtx);
568
563
  });
569
564
 
570
565
  test('recursive links w same id', () => {
@@ -612,33 +607,28 @@ test('recursive links w same id', () => {
612
607
  }),
613
608
  ];
614
609
 
615
- const steps = instaml.transform({ attrs: {}, schema }, ops);
616
- const store = createStore({}, [], true, createLinkIndex(schema), schema);
617
- const newStore = transact(store, steps);
610
+ const attrsStore = new AttrsStoreClass({}, createLinkIndex(schema));
611
+ const steps = instaml.transform({ attrsStore, schema }, ops);
612
+ const store = createStore(attrsStore, [], true, !!schema);
613
+ const newCtx = transact(store, attrsStore, steps);
618
614
 
619
- const result = query(
620
- { store: newStore, pageInfo: {}, aggregate: {} },
621
- {
622
- todos: {},
623
- fakeUsers: {},
624
- },
625
- );
615
+ const result = query(newCtx, {
616
+ todos: {},
617
+ fakeUsers: {},
618
+ });
626
619
 
627
620
  expect(result.data.todos.length).toBe(1);
628
621
  expect(result.data.fakeUsers.length).toBe(1);
629
622
 
630
623
  const removeOp = [instatx.tx.todos[sameId].delete()];
631
624
 
632
- const removeSteps = instaml.transform({ attrs: store.attrs }, removeOp);
633
- const postRemoveStore = transact(newStore, removeSteps);
625
+ const removeSteps = instaml.transform(newCtx, removeOp);
626
+ const postRemoveCtx = transact(newCtx.store, newCtx.attrsStore, removeSteps);
634
627
 
635
- const removeResult = query(
636
- { store: postRemoveStore, pageInfo: {}, aggregate: {} },
637
- {
638
- todos: {},
639
- fakeUsers: {},
640
- },
641
- );
628
+ const removeResult = query(postRemoveCtx, {
629
+ todos: {},
630
+ fakeUsers: {},
631
+ });
642
632
 
643
633
  expect(removeResult.data.todos.length).toBe(0);
644
634
  expect(removeResult.data.fakeUsers.length).toBe(1);
@@ -664,16 +654,14 @@ test('date conversion', () => {
664
654
  }),
665
655
  ];
666
656
 
667
- const steps = instaml.transform({ attrs: {}, schema }, ops);
668
- const store = createStore({}, [], true, createLinkIndex(schema), true);
669
- const newStore = transact(store, steps);
657
+ const attrsStore = new AttrsStoreClass({}, null);
658
+ const steps = instaml.transform({ attrsStore, schema }, ops);
659
+ const store = createStore(attrsStore, [], true, true);
660
+ const newCtx = transact(store, attrsStore, steps);
670
661
 
671
- const result = query(
672
- { store: newStore, pageInfo: {}, aggregate: {} },
673
- {
674
- todos: {},
675
- },
676
- );
662
+ const result = query(newCtx, {
663
+ todos: {},
664
+ });
677
665
 
678
666
  expect(result.data.todos.length).toBe(1);
679
667
  expect(result.data.todos[0].createdAt).toBeInstanceOf(Date);
@@ -698,18 +686,33 @@ test('date conversion', () => {
698
686
  }),
699
687
  ];
700
688
 
701
- const steps = instaml.transform({ attrs: {}, schema }, ops);
702
- const store = createStore({}, [], true, createLinkIndex(schema), false);
703
- const newStore = transact(store, steps);
689
+ const attrsStore = new AttrsStoreClass({}, null);
690
+ const steps = instaml.transform({ attrsStore, schema }, ops);
691
+ const store = createStore(attrsStore, [], true, false);
692
+ const newCtx = transact(store, attrsStore, steps);
704
693
 
705
- const result = query(
706
- { store: newStore, pageInfo: {}, aggregate: {} },
707
- {
708
- todos: {},
709
- },
710
- );
694
+ const result = query(newCtx, {
695
+ todos: {},
696
+ });
711
697
 
712
698
  expect(result.data.todos.length).toBe(1);
713
699
  expect(result.data.todos[0].createdAt).toBeTypeOf('number');
714
700
  }).not.toThrow();
715
701
  });
702
+
703
+ test('v0 store restores', () => {
704
+ function toJSONOld(store) {
705
+ return {
706
+ __type: store.__type,
707
+ attrs: store.attrs,
708
+ triples: allMapValues(store.eav, 3),
709
+ cardinalityInference: store.cardinalityInference,
710
+ linkIndex: store.linkIndex,
711
+ useDateObjects: store.useDateObjects,
712
+ };
713
+ }
714
+ const v0Json = toJSONOld({ ...store, attrs: zenecaAttrsStore.attrs });
715
+ const attrsStore = attrsStoreFromJSON(null, v0Json);
716
+ const restored = fromJSON(attrsStore!, v0Json);
717
+ expect(restored).toEqual(store);
718
+ });