@liminalfunctions/framework-vitamins 1.0.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.
@@ -0,0 +1,536 @@
1
+ import assert from "assert";
2
+
3
+ import { generated_collection_interface, result } from '../dist/type_generated_collection'
4
+ import { Vitamins } from '../dist/vitamins'
5
+
6
+ import { Client, Institution, Mutualism, Project, gen_institution, gen_client, gen_project, gen_mutualism } from './utils/testing_harness.js'
7
+
8
+ describe('Client Library Generation: Library Generation', function () {
9
+
10
+ function get_setup(
11
+ institution_database: Map<string, any> = new Map<string, any>(),
12
+ client_database: Map<string, any> = new Map<string, any>(),
13
+ project_database: Map<string, any> = new Map<string, any>(),
14
+ mutualsm_database: Map<string, any> = new Map<string, any>()
15
+ ) {
16
+
17
+ let collection_mutualism = new Mutualism(
18
+ ['institution', 'client', 'mutualism'],
19
+ 'mutualism',
20
+ mutualsm_database
21
+ )
22
+
23
+ let collection_project = new Project(
24
+ ['institution', 'project'],
25
+ 'project',
26
+ project_database
27
+ )
28
+
29
+ let collection_client = new Client(
30
+ ['institution', 'client'],
31
+ 'client',
32
+ client_database,
33
+ collection_mutualism
34
+ )
35
+
36
+ let collection_institution = new Institution(
37
+ ['institution'],
38
+ 'institution',
39
+ institution_database,
40
+ collection_client,
41
+ collection_project
42
+ )
43
+
44
+ let api = {
45
+ collection(collection_id: 'institution'){
46
+ switch(collection_id) {
47
+ case 'institution':
48
+ return collection_institution
49
+ }
50
+ }
51
+ }
52
+
53
+ let vue = gen_vue();
54
+
55
+ return {
56
+ collection_mutualism,
57
+ collection_project,
58
+ collection_client,
59
+ collection_institution,
60
+ api,
61
+ vue
62
+ }
63
+ }
64
+
65
+ function gen_vue() {
66
+ return {
67
+ institution: new Map<string, any>(),
68
+ client: new Map<string, any>(),
69
+ project: new Map<string, any>(),
70
+ mutualism: new Map<string, any>(),
71
+ }
72
+ }
73
+
74
+ function database(...entries: result[]){
75
+ let map = new Map<string, any>();
76
+ for(let entry of entries){
77
+ map.set(entry._id, entry);
78
+ }
79
+ return map;
80
+ }
81
+
82
+ function sleep(ms) {
83
+ return new Promise((resolve) => {
84
+ setTimeout(resolve, ms);
85
+ });
86
+ }
87
+
88
+ it(`should do a basic query`, async function () {
89
+ let institution = gen_institution('test institution')
90
+ let institution_database = database(institution);
91
+ let {
92
+ vue,
93
+ api
94
+ } = get_setup(institution_database);
95
+
96
+ //@ts-expect-error
97
+ let vitamins = new Vitamins(vue);
98
+ await vitamins.query(api.collection('institution'), {}).run()
99
+ await sleep(20);
100
+
101
+ let test_against = gen_vue();
102
+ test_against.institution.set(institution._id, structuredClone(institution));
103
+
104
+ assert.deepEqual(vue.institution.get(institution._id), institution)
105
+ assert.deepEqual(vue, test_against)
106
+ });
107
+
108
+ it(`should do a basic query that returns multiple children`, async function () {
109
+ let institution_1 = gen_institution('test institution 1')
110
+ let institution_2 = gen_institution('test institution 2')
111
+ let institution_3 = gen_institution('test institution 3')
112
+ let institution_database = database(institution_1, institution_2, institution_3);
113
+ let {
114
+ vue,
115
+ api
116
+ } = get_setup(institution_database);
117
+
118
+ //@ts-expect-error
119
+ let vitamins = new Vitamins(vue);
120
+ vitamins.query(api.collection('institution'), {}).run()
121
+ await sleep(20);
122
+
123
+ let test_against = gen_vue();
124
+ test_against.institution.set(institution_1._id, structuredClone(institution_1));
125
+ test_against.institution.set(institution_2._id, structuredClone(institution_2));
126
+ test_against.institution.set(institution_3._id, structuredClone(institution_3));
127
+
128
+ assert.deepEqual(vue.institution.get(institution_3._id), institution_3)
129
+ assert.deepEqual(vue, test_against)
130
+ });
131
+
132
+ it(`should do a basic document query`, async function () {
133
+ let institution = gen_institution('test institution')
134
+ let institution_database = database(institution);
135
+ let {
136
+ vue,
137
+ api
138
+ } = get_setup(institution_database);
139
+
140
+ //@ts-expect-error
141
+ let vitamins = new Vitamins(vue);
142
+ //@ts-expect-error
143
+ await vitamins.query(api.collection('institution')?.document(institution._id), {}).run()
144
+ await sleep(20);
145
+
146
+ let test_against = gen_vue();
147
+ test_against.institution.set(institution._id, structuredClone(institution));
148
+
149
+ assert.deepEqual(vue.institution.get(institution._id), institution)
150
+ assert.deepEqual(vue, test_against)
151
+ });
152
+
153
+ it(`should do a basic query that generates a child query`, async function () {
154
+ let institution_1 = gen_institution('test institution 1')
155
+ let client_1 = gen_client(institution_1, 'test client 1')
156
+ let institution_database = database(institution_1);
157
+ let client_database = database(client_1);
158
+ let {
159
+ vue,
160
+ api
161
+ } = get_setup(institution_database, client_database);
162
+
163
+ //@ts-expect-error
164
+ let vitamins = new Vitamins(vue);
165
+ vitamins.query(api.collection('institution'), {},
166
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('client'), {})
167
+ ).run()
168
+ await sleep(20);
169
+
170
+ let test_against = gen_vue();
171
+ test_against.institution.set(institution_1._id, structuredClone(institution_1));
172
+ test_against.client.set(client_1._id, structuredClone(client_1));
173
+
174
+ assert.deepEqual(vue.institution.get(institution_1._id), institution_1)
175
+ assert.deepEqual(vue.client.get(client_1._id), client_1)
176
+ assert.deepEqual(vue, test_against)
177
+ });
178
+
179
+ it(`should do a basic document query that generates a child query`, async function () {
180
+ let institution_1 = gen_institution('test institution 1')
181
+ let client_1 = gen_client(institution_1, 'test client 1')
182
+ let institution_database = database(institution_1);
183
+ let client_database = database(client_1);
184
+ let {
185
+ vue,
186
+ api
187
+ } = get_setup(institution_database, client_database);
188
+
189
+ //@ts-expect-error
190
+ let vitamins = new Vitamins(vue);
191
+ //@ts-expect-error
192
+ vitamins.query(api.collection('institution').document(institution_1._id), undefined,
193
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('client'), {})
194
+ ).run()
195
+ await sleep(20);
196
+
197
+ let test_against = gen_vue();
198
+ test_against.institution.set(institution_1._id, structuredClone(institution_1));
199
+ test_against.client.set(client_1._id, structuredClone(client_1));
200
+
201
+ assert.deepEqual(vue.institution.get(institution_1._id), institution_1)
202
+ assert.deepEqual(vue.client.get(client_1._id), client_1)
203
+ assert.deepEqual(vue, test_against)
204
+ });
205
+
206
+ it(`should do a basic query that generates a child query that generates a child query`, async function () {
207
+ let institution_1 = gen_institution('test institution 1')
208
+ let client_1 = gen_client(institution_1, 'test client 1')
209
+ let client_2 = gen_client(institution_1, 'test client 2')
210
+ let client_3 = gen_client(institution_1, 'test client 3')
211
+ let project_1 = gen_project(institution_1, client_1, 'test project 1')
212
+ let project_2 = gen_project(institution_1, client_1, 'test project 2')
213
+ let project_3 = gen_project(institution_1, client_2, 'test project 3')
214
+ let project_4 = gen_project(institution_1, client_2, 'test project 4')
215
+ let project_5 = gen_project(institution_1, client_3, 'test project 5')
216
+ let project_6 = gen_project(institution_1, client_3, 'test project 6')
217
+ let institution_database = database(institution_1);
218
+ let client_database = database(client_1, client_2, client_3);
219
+ let project_database = database(project_1, project_2, project_3, project_4, project_5, project_6)
220
+ let {
221
+ vue,
222
+ api
223
+ } = get_setup(institution_database, client_database, project_database);
224
+
225
+ //@ts-expect-error
226
+ let vitamins = new Vitamins(vue);
227
+ vitamins.query(api.collection('institution'), {},
228
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('project'), {client_id: client_1._id}),
229
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('project'), {client_id: client_2._id}),
230
+ ).run()
231
+ await sleep(20);
232
+
233
+ let test_against = gen_vue();
234
+ test_against.institution.set(institution_1._id, structuredClone(institution_1));
235
+ test_against.project.set(project_1._id, structuredClone(project_1));
236
+ test_against.project.set(project_2._id, structuredClone(project_2));
237
+ test_against.project.set(project_3._id, structuredClone(project_3));
238
+ test_against.project.set(project_4._id, structuredClone(project_4));
239
+
240
+ assert.deepEqual(vue.institution.get(institution_1._id), institution_1)
241
+ assert.deepEqual(vue.project.get(project_1._id), project_1)
242
+ assert.deepEqual(vue.project.get(project_2._id), project_2)
243
+ assert.deepEqual(vue.project.get(project_3._id), project_3)
244
+ assert.deepEqual(vue.project.get(project_4._id), project_4)
245
+ assert.deepEqual(vue, test_against)
246
+
247
+ // make sure that extra queries aren't happening
248
+ assert.equal(api.collection('institution')?.meta_counter.get(institution_1._id) ?? 0, 1)
249
+ assert.equal(api.collection('institution')?.document(institution_1._id).collection('project').meta_counter.get(project_1._id) ?? 0, 1)
250
+ assert.equal(api.collection('institution')?.document(institution_1._id).collection('project').meta_counter.get(project_2._id) ?? 0, 1)
251
+ assert.equal(api.collection('institution')?.document(institution_1._id).collection('project').meta_counter.get(project_3._id) ?? 0, 1)
252
+ assert.equal(api.collection('institution')?.document(institution_1._id).collection('project').meta_counter.get(project_4._id) ?? 0, 1)
253
+ assert.equal(api.collection('institution')?.document(institution_1._id).collection('project').meta_counter.get(project_5._id) ?? 0, 0)
254
+ assert.equal(api.collection('institution')?.document(institution_1._id).collection('project').meta_counter.get(project_6._id) ?? 0, 0)
255
+ });
256
+
257
+ it(`should do a basic query that generates child queries accessing the same documents`, async function () {
258
+ let institution_1 = gen_institution('test institution 1')
259
+ let institution_2 = gen_institution('test institution 2')
260
+ let institution_3 = gen_institution('test institution 3')
261
+ let client_1 = gen_client(institution_1, 'test client 1')
262
+ let institution_database = database(institution_1, institution_2, institution_3);
263
+ let client_database = database(client_1);
264
+ let {
265
+ vue,
266
+ api
267
+ } = get_setup(institution_database, client_database);
268
+
269
+ //@ts-expect-error
270
+ let vitamins = new Vitamins(vue);
271
+ vitamins.query(api.collection('institution'), {},
272
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('client'), {_id: client_1._id}),
273
+ ).run()
274
+ await sleep(20);
275
+
276
+ let test_against = gen_vue();
277
+ test_against.institution.set(institution_1._id, structuredClone(institution_1));
278
+ test_against.institution.set(institution_2._id, structuredClone(institution_2));
279
+ test_against.institution.set(institution_3._id, structuredClone(institution_3));
280
+ test_against.client.set(client_1._id, structuredClone(client_1));
281
+
282
+ assert.deepEqual(vue.client.get(client_1._id), client_1)
283
+ assert.deepEqual(vue.institution.get(institution_3._id), institution_3)
284
+ assert.deepEqual(vue, test_against)
285
+
286
+ assert.equal(api.collection('institution')?.document('*').collection('client').meta_counter.get(client_1._id), 1)
287
+ });
288
+
289
+ it(`when two identical queries with different children are generated, the query should run only once and both children should run correctly`, async function () {
290
+ let institution_1 = gen_institution('test institution 1')
291
+ let client_1 = gen_client(institution_1, 'test client 1')
292
+ let client_2 = gen_client(institution_1, 'test client 2')
293
+ let client_3 = gen_client(institution_1, 'test client 3')
294
+ let institution_database = database(institution_1);
295
+ let client_database = database(client_1, client_2, client_3);
296
+ let {
297
+ vue,
298
+ api
299
+ } = get_setup(institution_database, client_database);
300
+
301
+ //@ts-expect-error
302
+ let vitamins = new Vitamins(vue);
303
+ //@ts-expect-error
304
+ vitamins.query(api.collection('institution')?.document(institution_1._id) as Collection, undefined,
305
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('client'), {_id: client_1._id}),
306
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('client'), {_id: client_2._id}),
307
+ ).run()
308
+ //@ts-expect-error
309
+ vitamins.query(api.collection('institution')?.document(institution_1._id) as Collection, undefined,
310
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('client'), {_id: client_2._id}),
311
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('client'), {_id: client_3._id}),
312
+ ).run()
313
+ await sleep(20);
314
+
315
+ let test_against = gen_vue();
316
+ test_against.institution.set(institution_1._id, structuredClone(institution_1));
317
+ test_against.client.set(client_1._id, structuredClone(client_1));
318
+ test_against.client.set(client_2._id, structuredClone(client_2));
319
+ test_against.client.set(client_3._id, structuredClone(client_3));
320
+
321
+ assert.deepEqual(vue.client.get(client_1._id), client_1)
322
+ assert.deepEqual(vue.client.get(client_2._id), client_2)
323
+ assert.deepEqual(vue.client.get(client_3._id), client_3)
324
+ assert.deepEqual(vue, test_against)
325
+
326
+ assert.equal(api.collection('institution')?.meta_counter.get(institution_1._id), 1)
327
+ assert.equal(api.collection('institution')?.document('*').collection('client').meta_counter.get(client_1._id), 1)
328
+ assert.equal(api.collection('institution')?.document('*').collection('client').meta_counter.get(client_2._id), 1)
329
+ assert.equal(api.collection('institution')?.document('*').collection('client').meta_counter.get(client_3._id), 1)
330
+ });
331
+
332
+ it(`should switch targets when the data changes`, async function () {
333
+ let institution_1 = gen_institution('test institution 1')
334
+ let institution_2 = gen_institution('test institution 2')
335
+ let client_1 = gen_client(institution_1, 'test client 1')
336
+ let institution_database = database(institution_1, institution_2);
337
+ let client_database = database(client_1);
338
+ let {
339
+ vue,
340
+ api
341
+ } = get_setup(institution_database, client_database);
342
+
343
+ //@ts-expect-error
344
+ let vitamins = new Vitamins(vue);
345
+ //@ts-expect-error
346
+ let query = await vitamins.query(api.collection('institution')?.document('*').collection('client').document(client_1._id) as Collection, undefined,
347
+ //@ts-expect-error
348
+ (result) => vitamins.query(api.collection('institution'), {_id: result.institution_id }),
349
+ ).run()
350
+ await sleep(20);
351
+
352
+ let test_against_phase_1 = gen_vue();
353
+ test_against_phase_1.institution.set(institution_1._id, structuredClone(institution_1));
354
+ test_against_phase_1.client.set(client_1._id, structuredClone(client_1));
355
+
356
+ assert.deepEqual(vue.client.get(client_1._id), client_1)
357
+ assert.deepEqual(vue.institution.get(institution_1._id), institution_1)
358
+ assert.deepEqual(vue, test_against_phase_1)
359
+
360
+ client_1.institution_id = institution_2._id;
361
+ query.rerun();
362
+ await sleep(20);
363
+
364
+ let test_against_phase_2 = gen_vue();
365
+ test_against_phase_2.institution.set(institution_2._id, structuredClone(institution_2));
366
+ test_against_phase_2.client.set(client_1._id, structuredClone(client_1));
367
+
368
+ assert.deepEqual(vue.client.get(client_1._id), client_1);
369
+ assert.deepEqual(vue.institution.get(institution_2._id), institution_2);
370
+ assert.deepEqual(vue, test_against_phase_2);
371
+ });
372
+
373
+ it(`should switch targets when the data changes using update_document_from_external`, async function () {
374
+ let institution_1 = gen_institution('test institution 1')
375
+ let institution_2 = gen_institution('test institution 2')
376
+ let client_1 = gen_client(institution_1, 'test client 1')
377
+ let institution_database = database(institution_1, institution_2);
378
+ let client_database = database(client_1);
379
+ let {
380
+ vue,
381
+ api
382
+ } = get_setup(institution_database, client_database);
383
+
384
+ //@ts-expect-error
385
+ let vitamins = new Vitamins(vue);
386
+ //@ts-expect-error
387
+ let query = await vitamins.query(api.collection('institution')?.document('*').collection('client').document(client_1._id) as Collection, undefined,
388
+ //@ts-expect-error
389
+ (result) => vitamins.query(api.collection('institution'), {_id: result.institution_id }),
390
+ ).run()
391
+ await sleep(20);
392
+
393
+ let test_against_phase_1 = gen_vue();
394
+ test_against_phase_1.institution.set(institution_1._id, structuredClone(institution_1));
395
+ test_against_phase_1.client.set(client_1._id, structuredClone(client_1));
396
+
397
+ assert.deepEqual(vue.client.get(client_1._id), client_1)
398
+ assert.deepEqual(vue.institution.get(institution_1._id), institution_1)
399
+ assert.deepEqual(vue, test_against_phase_1)
400
+
401
+ vitamins.update_document_from_external(client_1._id, Object.assign(client_1, {institution_id: institution_2._id}))
402
+ await sleep(20);
403
+
404
+ let test_against_phase_2 = gen_vue();
405
+ test_against_phase_2.institution.set(institution_2._id, structuredClone(institution_2));
406
+ test_against_phase_2.client.set(client_1._id, structuredClone(client_1));
407
+
408
+ assert.deepEqual(vue.client.get(client_1._id), client_1);
409
+ assert.deepEqual(vue.institution.get(institution_2._id), institution_2);
410
+ assert.deepEqual(vue, test_against_phase_2);
411
+ });
412
+
413
+ it(`should handle an external deletion`, async function () {
414
+ let institution_1 = gen_institution('test institution 1')
415
+ let client_1 = gen_client(institution_1, 'test client 1')
416
+ let project_1 = gen_project(institution_1, client_1, 'test project 1')
417
+ let institution_database = database(institution_1);
418
+ let client_database = database(client_1);
419
+ let project_database = database(project_1);
420
+ let {
421
+ vue,
422
+ api
423
+ } = get_setup(institution_database, client_database, project_database);
424
+
425
+ //@ts-expect-error
426
+ let vitamins = new Vitamins(vue);
427
+ let query = await vitamins.query(api.collection('institution'), {},
428
+ (result) => vitamins.query(api.collection('institution')?.document('*').collection('client'), {institution_id: result._id },
429
+ (result) => vitamins.query(api.collection('institution')?.document('*').collection('project'), {client_id: result._id })
430
+ ),
431
+ ).run()
432
+ await sleep(20);
433
+
434
+ let test_against_phase_1 = gen_vue();
435
+ test_against_phase_1.institution.set(institution_1._id, structuredClone(institution_1));
436
+ test_against_phase_1.client.set(client_1._id, structuredClone(client_1));
437
+ test_against_phase_1.project.set(project_1._id, structuredClone(project_1));
438
+
439
+ assert.deepEqual(vue, test_against_phase_1)
440
+
441
+ vitamins.delete_document_from_external(client_1._id);
442
+ await sleep(20);
443
+
444
+ let test_against_phase_2 = gen_vue();
445
+ test_against_phase_2.institution.set(institution_1._id, structuredClone(institution_1));
446
+
447
+ assert.deepEqual(vue, test_against_phase_2)
448
+ });
449
+
450
+ it(`in a basic query, errors get bubbled up to the parent context`, async function () {
451
+ let institution = gen_institution('test institution')
452
+ let institution_database = database(institution);
453
+ let {
454
+ vue,
455
+ api,
456
+ collection_institution
457
+ } = get_setup(institution_database);
458
+
459
+ collection_institution.errors = true;
460
+
461
+ assert.rejects(async () => {
462
+ //@ts-expect-error
463
+ let vitamins = new Vitamins(vue);
464
+ await vitamins.query(api.collection('institution'), {}).run()
465
+ }, 'Error: arbitrary error');
466
+ });
467
+
468
+
469
+ it(`in a basic query that generates a child query, errors get bubbled up to the parent context`, async function () {
470
+ let institution_1 = gen_institution('test institution 1')
471
+ let client_1 = gen_client(institution_1, 'test client 1')
472
+ let institution_database = database(institution_1);
473
+ let client_database = database(client_1);
474
+ let {
475
+ vue,
476
+ api
477
+ } = get_setup(institution_database, client_database);
478
+
479
+ assert.rejects(async () => {
480
+ //@ts-expect-error
481
+ let vitamins = new Vitamins(vue);
482
+ await vitamins.query(api.collection('institution'), {},
483
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('client'), {})
484
+ ).run()
485
+ }, 'Error: arbitrary error');
486
+ });
487
+
488
+ it(`in a basic document query that generates a child query, errors get bubbled up to the parent context`, async function () {
489
+ let institution_1 = gen_institution('test institution 1')
490
+ let client_1 = gen_client(institution_1, 'test client 1')
491
+ let institution_database = database(institution_1);
492
+ let client_database = database(client_1);
493
+ let {
494
+ vue,
495
+ api
496
+ } = get_setup(institution_database, client_database);
497
+
498
+ assert.rejects(async () => {
499
+ //@ts-expect-error
500
+ let vitamins = new Vitamins(vue);
501
+ //@ts-expect-error
502
+ await vitamins.query(api.collection('institution').document(institution_1._id), undefined,
503
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('client'), {})
504
+ ).run()
505
+ }, 'Error: arbitrary error');
506
+ });
507
+
508
+ it(`in a basic query that generates a child query that generates a child query, errors get bubbled up to the parent context`, async function () {
509
+ let institution_1 = gen_institution('test institution 1')
510
+ let client_1 = gen_client(institution_1, 'test client 1')
511
+ let client_2 = gen_client(institution_1, 'test client 2')
512
+ let client_3 = gen_client(institution_1, 'test client 3')
513
+ let project_1 = gen_project(institution_1, client_1, 'test project 1')
514
+ let project_2 = gen_project(institution_1, client_1, 'test project 2')
515
+ let project_3 = gen_project(institution_1, client_2, 'test project 3')
516
+ let project_4 = gen_project(institution_1, client_2, 'test project 4')
517
+ let project_5 = gen_project(institution_1, client_3, 'test project 5')
518
+ let project_6 = gen_project(institution_1, client_3, 'test project 6')
519
+ let institution_database = database(institution_1);
520
+ let client_database = database(client_1, client_2, client_3);
521
+ let project_database = database(project_1, project_2, project_3, project_4, project_5, project_6)
522
+ let {
523
+ vue,
524
+ api
525
+ } = get_setup(institution_database, client_database, project_database);
526
+
527
+ assert.rejects(async () => {
528
+ //@ts-expect-error
529
+ let vitamins = new Vitamins(vue);
530
+ await vitamins.query(api.collection('institution'), {},
531
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('project'), {client_id: client_1._id}),
532
+ (result) => vitamins.query(api.collection('institution')?.document(result._id).collection('project'), {client_id: client_2._id}),
533
+ ).run();
534
+ }, 'Error: arbitrary error');
535
+ });
536
+ });