@nymphjs/nymph 1.0.0-beta.8 → 1.0.0-beta.81

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/CHANGELOG.md +382 -0
  2. package/README.md +9 -19
  3. package/dist/Entity.d.ts +269 -7
  4. package/dist/Entity.js +491 -105
  5. package/dist/Entity.js.map +1 -1
  6. package/dist/Entity.test.js +25 -3
  7. package/dist/Entity.test.js.map +1 -1
  8. package/dist/Entity.types.d.ts +225 -19
  9. package/dist/Nymph.d.ts +430 -11
  10. package/dist/Nymph.js +686 -168
  11. package/dist/Nymph.js.map +1 -1
  12. package/dist/Nymph.types.d.ts +65 -7
  13. package/dist/Nymph.types.js +2 -1
  14. package/dist/Nymph.types.js.map +1 -1
  15. package/dist/conf/d.d.ts +30 -0
  16. package/dist/conf/defaults.js +27 -0
  17. package/dist/conf/defaults.js.map +1 -1
  18. package/dist/driver/NymphDriver.d.ts +136 -38
  19. package/dist/driver/NymphDriver.js +264 -131
  20. package/dist/driver/NymphDriver.js.map +1 -1
  21. package/dist/driver/testArtifacts.d.ts +1 -1
  22. package/dist/driver/testArtifacts.js +499 -51
  23. package/dist/driver/testArtifacts.js.map +1 -1
  24. package/dist/errors/EntityInvalidDataError.d.ts +6 -0
  25. package/dist/errors/EntityInvalidDataError.js +7 -1
  26. package/dist/errors/EntityInvalidDataError.js.map +1 -1
  27. package/dist/errors/EntityUniqueConstraintError.d.ts +3 -0
  28. package/dist/errors/EntityUniqueConstraintError.js +11 -0
  29. package/dist/errors/EntityUniqueConstraintError.js.map +1 -0
  30. package/dist/errors/InvalidStateError.d.ts +3 -0
  31. package/dist/errors/InvalidStateError.js +11 -0
  32. package/dist/errors/InvalidStateError.js.map +1 -0
  33. package/dist/errors/QueryFailedError.js +1 -0
  34. package/dist/errors/QueryFailedError.js.map +1 -1
  35. package/dist/errors/index.d.ts +2 -0
  36. package/dist/errors/index.js +2 -0
  37. package/dist/errors/index.js.map +1 -1
  38. package/dist/testArtifacts.d.ts +17 -5
  39. package/dist/testArtifacts.js +31 -27
  40. package/dist/testArtifacts.js.map +1 -1
  41. package/dist/testMocks.d.ts +13 -10
  42. package/dist/testMocks.js +32 -13
  43. package/dist/testMocks.js.map +1 -1
  44. package/dist/utils.d.ts +1 -1
  45. package/dist/utils.js +21 -5
  46. package/dist/utils.js.map +1 -1
  47. package/package.json +16 -14
  48. package/src/Entity.test.ts +22 -5
  49. package/src/Entity.ts +423 -134
  50. package/src/Entity.types.ts +32 -66
  51. package/src/Nymph.ts +609 -176
  52. package/src/Nymph.types.ts +131 -26
  53. package/src/conf/d.ts +12 -0
  54. package/src/conf/defaults.ts +31 -0
  55. package/src/driver/NymphDriver.ts +289 -311
  56. package/src/driver/testArtifacts.ts +572 -181
  57. package/src/errors/EntityUniqueConstraintError.ts +6 -0
  58. package/src/errors/InvalidStateError.ts +6 -0
  59. package/src/errors/index.ts +4 -0
  60. package/src/nymphJoiProps.ts +2 -2
  61. package/src/testArtifacts.ts +18 -19
  62. package/src/testMocks.ts +55 -30
  63. package/src/utils.ts +22 -8
  64. package/tsconfig.json +3 -3
  65. package/typedoc.json +4 -0
@@ -3,18 +3,21 @@ import strtotime from 'locutus/php/datetime/strtotime';
3
3
  import { guid } from '@nymphjs/guid';
4
4
 
5
5
  import type Nymph from '../Nymph';
6
+ import { EntityUniqueConstraintError } from '../errors';
6
7
  import {
7
8
  TestBModel as TestBModelClass,
8
9
  TestModel as TestModelClass,
9
10
  TestModelData,
11
+ TestEmptyModel as TestEmptyModelClass,
10
12
  } from '../testArtifacts';
11
13
 
12
- export function QueriesTest(
14
+ export function EntitiesTest(
13
15
  nymph: Nymph,
14
- it: (name: string, fn: () => void) => void
16
+ it: (name: string, fn: () => void) => void,
15
17
  ) {
16
18
  const TestModel = nymph.addEntityClass(TestModelClass);
17
19
  const TestBModel = nymph.addEntityClass(TestBModelClass);
20
+ const TestEmptyModel = nymph.addEntityClass(TestEmptyModelClass);
18
21
 
19
22
  let testEntity: TestModelClass & TestModelData;
20
23
  let testGuid: string;
@@ -34,12 +37,15 @@ export function QueriesTest(
34
37
  testEntity.name = 'Entity Test ' + new Date().toLocaleString();
35
38
  testEntity.null = null;
36
39
  testEntity.string = 'test';
37
- testEntity.array = ['full', 'of', 'values', 500];
38
- testEntity.match = `Hello, my name is Edward McCheese. It is a pleasure to meet you. As you can see, I have several hats of the most pleasant nature.
39
-
40
- This one's email address is nice_hat-wednesday+newyork@im-a-hat.hat.
41
- This one's phone number is (555) 555-1818.
42
- This one's zip code is 92064.`;
40
+ testEntity.array = [
41
+ 'full',
42
+ 'of',
43
+ 'values',
44
+ 500,
45
+ { test: true },
46
+ { nullbyte: '\\\x00\u0000 \x00' },
47
+ ];
48
+ testEntity.match = matchValue;
43
49
  testEntity.number = 30;
44
50
  testEntity.numberString = '30';
45
51
  testEntity.timestamp = Date.now();
@@ -59,18 +65,10 @@ This one's zip code is 92064.`;
59
65
  entityReferenceTest.test = 'good';
60
66
  expect(await entityReferenceTest.$save()).toEqual(true);
61
67
 
62
- // Test synchronous getEntity.
63
- testEntity = nymph.driver.getEntitySync(
64
- { class: TestModel },
65
- testGuid
66
- ) as TestModelClass & TestModelData;
67
- expect(testEntity).toBeInstanceOf(TestModel);
68
- expect(testEntity.guid).toEqual(testGuid);
69
-
70
68
  // Test asynchronous getEntity.
71
69
  testEntity = (await nymph.getEntity(
72
70
  { class: TestModel },
73
- testGuid
71
+ testGuid,
74
72
  )) as TestModelClass & TestModelData;
75
73
  expect(testEntity).toBeInstanceOf(TestModel);
76
74
  expect(testEntity.guid).toEqual(testGuid);
@@ -84,6 +82,8 @@ This one's zip code is 92064.`;
84
82
  for (let i = 0; i < 100; i++) {
85
83
  const testEntity = await TestModel.factory();
86
84
  testEntity.name = `Multi Test ${i}`;
85
+ // Reverse the number for sort testing.
86
+ testEntity.number = 100 - i;
87
87
  testEntity.$removeTag('test');
88
88
  testEntity.$addTag('multiTest');
89
89
  expect(await testEntity.$save()).toEqual(true);
@@ -94,20 +94,36 @@ This one's zip code is 92064.`;
94
94
  }
95
95
 
96
96
  it('delete old test data', async () => {
97
- let all = await nymph.getEntities({ class: TestModel });
98
- expect(Array.isArray(all)).toEqual(true);
99
- for (const cur of all) {
97
+ let amodels = await nymph.getEntities({ class: TestModel });
98
+ expect(Array.isArray(amodels)).toEqual(true);
99
+ for (const cur of amodels) {
100
100
  expect(await cur.$delete()).toEqual(true);
101
101
  }
102
102
 
103
- all = await nymph.getEntities({ class: TestModel });
104
- expect(all.length).toEqual(0);
103
+ amodels = await nymph.getEntities({ class: TestModel });
104
+ expect(amodels.length).toEqual(0);
105
+
106
+ let bmodels = await nymph.getEntities({ class: TestBModel });
107
+ expect(Array.isArray(bmodels)).toEqual(true);
108
+ for (const cur of bmodels) {
109
+ expect(await cur.$delete()).toEqual(true);
110
+ }
111
+
112
+ bmodels = await nymph.getEntities({ class: TestBModel });
113
+ expect(bmodels.length).toEqual(0);
105
114
  });
106
115
 
107
116
  it('create entity', async () => {
108
117
  await createTestEntities();
109
118
  });
110
119
 
120
+ it("doesn't create empty entity", async () => {
121
+ const testEntity = await TestEmptyModel.factory();
122
+
123
+ expect(await testEntity.$save()).toBeFalsy();
124
+ expect(testEntity.guid).toBeNull();
125
+ });
126
+
111
127
  it('update mdate on save', async () => {
112
128
  await createTestEntities();
113
129
 
@@ -150,7 +166,7 @@ This one's zip code is 92064.`;
150
166
 
151
167
  if (!(await transaction.inTransaction())) {
152
168
  console.log(
153
- 'This Nymph driver or database seems to not support transactions. Skipping transaction tests.'
169
+ 'This Nymph driver or database seems to not support transactions. Skipping transaction tests.',
154
170
  );
155
171
  await transaction.rollback('test');
156
172
  return;
@@ -181,7 +197,7 @@ This one's zip code is 92064.`;
181
197
  expect(await testEntity.$delete()).toEqual(true);
182
198
  const resultEntity = await transaction.getEntity(
183
199
  { class: TestModel },
184
- testGuid
200
+ testGuid,
185
201
  );
186
202
  expect(resultEntity).toBeNull();
187
203
 
@@ -194,13 +210,13 @@ This one's zip code is 92064.`;
194
210
  // Verify it's back.
195
211
  testEntity = (await transaction.getEntity(
196
212
  { class: TestModel },
197
- testGuid
213
+ testGuid,
198
214
  )) as TestModelClass & TestModelData;
199
215
 
200
216
  expect(testEntity.guid).toEqual(testGuid);
201
217
 
202
- // Start a new transaction.
203
- transaction = await nymph.startTransaction('test');
218
+ // Start a new transaction with a dot in the name.
219
+ transaction = await nymph.startTransaction('test.1');
204
220
  testEntity.$nymph = transaction;
205
221
 
206
222
  // Verify in a transaction.
@@ -211,7 +227,7 @@ This one's zip code is 92064.`;
211
227
  expect(await testEntity.$save()).toEqual(true);
212
228
 
213
229
  // Commit the transaction.
214
- await transaction.commit('test');
230
+ await transaction.commit('test.1');
215
231
  testEntity.$nymph = nymph;
216
232
 
217
233
  // Verify not in a transaction.
@@ -240,7 +256,7 @@ This one's zip code is 92064.`;
240
256
  limit: 1,
241
257
  sort: 'cdate',
242
258
  },
243
- { type: '&', tag: 'test' }
259
+ { type: '&', tag: 'test' },
244
260
  );
245
261
  expect(resultEntities.length).toEqual(1);
246
262
  expect(testEntity.$is(resultEntities[0])).toEqual(true);
@@ -252,7 +268,7 @@ This one's zip code is 92064.`;
252
268
  // Retrieving entity by GUID and tags...
253
269
  const resultEntity = await nymph.getEntity(
254
270
  { class: TestModel },
255
- { type: '&', guid: testGuid, tag: 'test' }
271
+ { type: '&', guid: testGuid, tag: 'test' },
256
272
  );
257
273
  expect(testEntity.$is(resultEntity)).toEqual(true);
258
274
  });
@@ -263,7 +279,7 @@ This one's zip code is 92064.`;
263
279
  // Retrieving entity by GUID and tags...
264
280
  const resultEntity = await nymph.getEntity(
265
281
  { class: TestModel },
266
- { type: '|', guid: [testGuid, guid()] }
282
+ { type: '|', guid: [testGuid, guid()] },
267
283
  );
268
284
  expect(testEntity.$is(resultEntity)).toEqual(true);
269
285
  });
@@ -274,7 +290,7 @@ This one's zip code is 92064.`;
274
290
  // Retrieving entity by GUID and tags...
275
291
  const resultEntity = await nymph.getEntity(
276
292
  { class: TestModel },
277
- { type: '|', guid: [guid(), guid()] }
293
+ { type: '|', guid: [guid(), guid()] },
278
294
  );
279
295
  expect(testEntity.$is(resultEntity)).toEqual(false);
280
296
  });
@@ -285,7 +301,7 @@ This one's zip code is 92064.`;
285
301
  // Retrieving entity by !GUID...
286
302
  const resultEntity = await nymph.getEntities(
287
303
  { class: TestModel },
288
- { type: '&', '!guid': guid(), tag: 'test' }
304
+ { type: '&', '!guid': guid(), tag: 'test' },
289
305
  );
290
306
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
291
307
  });
@@ -296,7 +312,7 @@ This one's zip code is 92064.`;
296
312
  // Retrieving entity by !tags...
297
313
  const resultEntity = await nymph.getEntities(
298
314
  { class: TestModel },
299
- { type: '&', guid: testGuid, '!tag': ['barbecue', 'pickles'] }
315
+ { type: '&', guid: testGuid, '!tag': ['barbecue', 'pickles'] },
300
316
  );
301
317
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
302
318
  });
@@ -307,7 +323,7 @@ This one's zip code is 92064.`;
307
323
  // Testing GUID and wrong tags...
308
324
  const resultEntity = await nymph.getEntity(
309
325
  { class: TestModel },
310
- { type: '&', guid: testGuid, tag: ['pickles'] }
326
+ { type: '&', guid: testGuid, tag: ['pickles'] },
311
327
  );
312
328
  expect(resultEntity).toBeNull();
313
329
  });
@@ -318,7 +334,7 @@ This one's zip code is 92064.`;
318
334
  // Retrieving entity by tags...
319
335
  const resultEntity = await nymph.getEntities(
320
336
  { class: TestModel },
321
- { type: '&', tag: 'test' }
337
+ { type: '&', tag: 'test' },
322
338
  );
323
339
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
324
340
  });
@@ -329,7 +345,7 @@ This one's zip code is 92064.`;
329
345
  // Testing wrong tags...
330
346
  const resultEntity = await nymph.getEntities(
331
347
  { class: TestModel },
332
- { type: '&', tag: 'pickles' }
348
+ { type: '&', tag: 'pickles' },
333
349
  );
334
350
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
335
351
  });
@@ -340,7 +356,7 @@ This one's zip code is 92064.`;
340
356
  // Retrieving entity by tags inclusively...
341
357
  const resultEntity = await nymph.getEntities(
342
358
  { class: TestModel },
343
- { type: '|', tag: ['pickles', 'test', 'barbecue'] }
359
+ { type: '|', tag: ['pickles', 'test', 'barbecue'] },
344
360
  );
345
361
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
346
362
  });
@@ -351,7 +367,7 @@ This one's zip code is 92064.`;
351
367
  // Testing wrong inclusive tags...
352
368
  const resultEntity = await nymph.getEntities(
353
369
  { class: TestModel },
354
- { type: '|', tag: ['pickles', 'barbecue'] }
370
+ { type: '|', tag: ['pickles', 'barbecue'] },
355
371
  );
356
372
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
357
373
  });
@@ -363,7 +379,7 @@ This one's zip code is 92064.`;
363
379
  const resultEntity = await nymph.getEntities(
364
380
  { class: TestModel },
365
381
  { type: '&', tag: 'test' },
366
- { type: '|', tag: ['pickles', 'test', 'barbecue'] }
382
+ { type: '|', tag: ['pickles', 'test', 'barbecue'] },
367
383
  );
368
384
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
369
385
  });
@@ -375,7 +391,7 @@ This one's zip code is 92064.`;
375
391
  const resultEntity = await nymph.getEntities(
376
392
  { class: TestModel },
377
393
  { type: '&', tag: 'test' },
378
- { type: '|', tag: ['pickles', 'barbecue'] }
394
+ { type: '|', tag: ['pickles', 'barbecue'] },
379
395
  );
380
396
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
381
397
  });
@@ -387,7 +403,7 @@ This one's zip code is 92064.`;
387
403
  const resultEntity = await nymph.getEntities(
388
404
  { class: TestModel },
389
405
  { type: '&', tag: 'pickles' },
390
- { type: '|', tag: ['test', 'barbecue'] }
406
+ { type: '|', tag: ['test', 'barbecue'] },
391
407
  );
392
408
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
393
409
  });
@@ -398,7 +414,7 @@ This one's zip code is 92064.`;
398
414
  // Retrieving entity by defined...
399
415
  const resultEntity = await nymph.getEntities(
400
416
  { class: TestModel },
401
- { type: '&', defined: 'string' }
417
+ { type: '&', defined: 'string' },
402
418
  );
403
419
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
404
420
  });
@@ -409,7 +425,7 @@ This one's zip code is 92064.`;
409
425
  // Retrieving entity by !defined...
410
426
  const resultEntity = await nymph.getEntities(
411
427
  { class: TestModel },
412
- { type: '&', tag: 'test', '!defined': 'pickles' }
428
+ { type: '&', tag: 'test', '!defined': 'pickles' },
413
429
  );
414
430
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
415
431
  });
@@ -421,7 +437,7 @@ This one's zip code is 92064.`;
421
437
  const resultEntity = await nymph.getEntities(
422
438
  { class: TestModel },
423
439
  { type: '!&', defined: 'pickles' },
424
- { type: '&', tag: 'test' }
440
+ { type: '&', tag: 'test' },
425
441
  );
426
442
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
427
443
  });
@@ -430,9 +446,60 @@ This one's zip code is 92064.`;
430
446
  await createTestEntities();
431
447
 
432
448
  // Retrieving entity by equal...
433
- const resultEntity = await nymph.getEntities(
449
+ let resultEntity = await nymph.getEntities(
450
+ { class: TestModel },
451
+ { type: '&', equal: ['string', 'test'] },
452
+ );
453
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
454
+
455
+ // Retrieving entity by equal...
456
+ resultEntity = await nymph.getEntities(
457
+ { class: TestModel },
458
+ { type: '&', equal: ['null', null] },
459
+ );
460
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
461
+
462
+ // Retrieving entity by equal...
463
+ resultEntity = await nymph.getEntities(
464
+ { class: TestModel },
465
+ { type: '&', equal: ['boolean', true] },
466
+ );
467
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
468
+
469
+ // Retrieving entity by equal...
470
+ resultEntity = await nymph.getEntities(
471
+ { class: TestModel },
472
+ { type: '&', equal: ['number', 30] },
473
+ );
474
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
475
+
476
+ // Retrieving entity by equal...
477
+ resultEntity = await nymph.getEntities(
478
+ { class: TestModel },
479
+ {
480
+ type: '&',
481
+ equal: [
482
+ 'array',
483
+ [
484
+ 'full',
485
+ 'of',
486
+ 'values',
487
+ 500,
488
+ { test: true },
489
+ { nullbyte: '\\\x00\u0000 \x00' },
490
+ ],
491
+ ],
492
+ },
493
+ );
494
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
495
+
496
+ // Retrieving entity by equal...
497
+ resultEntity = await nymph.getEntities(
434
498
  { class: TestModel },
435
- { type: '&', equal: ['string', 'test'] }
499
+ {
500
+ type: '&',
501
+ equal: ['match', matchValue],
502
+ },
436
503
  );
437
504
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
438
505
  });
@@ -446,7 +513,7 @@ This one's zip code is 92064.`;
446
513
  // Retrieving entity by !equal...
447
514
  const resultEntity = await nymph.getEntities(
448
515
  { class: TestModel },
449
- { type: '&', tag: 'test', '!equal': ['string', 'wrong'] }
516
+ { type: '&', tag: 'test', '!equal': ['string', 'wrong'] },
450
517
  );
451
518
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
452
519
  expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
@@ -458,7 +525,7 @@ This one's zip code is 92064.`;
458
525
  // Retrieving entity by like...
459
526
  const resultEntity = await nymph.getEntities(
460
527
  { class: TestModel },
461
- { type: '&', like: ['string', 't_s%'] }
528
+ { type: '&', like: ['string', 't_s%'] },
462
529
  );
463
530
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
464
531
  });
@@ -472,7 +539,7 @@ This one's zip code is 92064.`;
472
539
  // Retrieving entity by !like...
473
540
  const resultEntity = await nymph.getEntities(
474
541
  { class: TestModel },
475
- { type: '&', tag: 'test', '!like': ['string', 'wr_n%'] }
542
+ { type: '&', tag: 'test', '!like': ['string', 'wr_n%'] },
476
543
  );
477
544
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
478
545
  expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
@@ -484,7 +551,7 @@ This one's zip code is 92064.`;
484
551
  // Retrieving entity by ilike...
485
552
  const resultEntity = await nymph.getEntities(
486
553
  { class: TestModel },
487
- { type: '&', ilike: ['string', 'T_s%'] }
554
+ { type: '&', ilike: ['string', 'T_s%'] },
488
555
  );
489
556
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
490
557
  });
@@ -498,7 +565,7 @@ This one's zip code is 92064.`;
498
565
  // Retrieving entity by !ilike...
499
566
  const resultEntity = await nymph.getEntities(
500
567
  { class: TestModel },
501
- { type: '&', tag: 'test', '!ilike': ['string', 'wr_n%'] }
568
+ { type: '&', tag: 'test', '!ilike': ['string', 'wr_n%'] },
502
569
  );
503
570
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
504
571
  expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
@@ -510,7 +577,7 @@ This one's zip code is 92064.`;
510
577
  // Retrieving entity by like...
511
578
  const resultEntity = await nymph.getEntities(
512
579
  { class: TestModel },
513
- { type: '&', like: ['string', 'T_s%'] }
580
+ { type: '&', like: ['string', 'T_s%'] },
514
581
  );
515
582
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
516
583
  });
@@ -521,7 +588,7 @@ This one's zip code is 92064.`;
521
588
  // Retrieving entity by tags and equal...
522
589
  const resultEntity = await nymph.getEntities(
523
590
  { class: TestModel },
524
- { type: '&', tag: 'test', equal: ['string', 'test'] }
591
+ { type: '&', tag: 'test', equal: ['string', 'test'] },
525
592
  );
526
593
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
527
594
  });
@@ -532,7 +599,7 @@ This one's zip code is 92064.`;
532
599
  // Testing wrong tags and right equal...
533
600
  const resultEntity = await nymph.getEntities(
534
601
  { class: TestModel },
535
- { type: '&', tag: 'pickles', equal: ['string', 'test'] }
602
+ { type: '&', tag: 'pickles', equal: ['string', 'test'] },
536
603
  );
537
604
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
538
605
  });
@@ -543,7 +610,7 @@ This one's zip code is 92064.`;
543
610
  // Testing right tags and wrong equal...
544
611
  const resultEntity = await nymph.getEntities(
545
612
  { class: TestModel },
546
- { type: '&', tag: 'test', equal: ['string', 'pickles'] }
613
+ { type: '&', tag: 'test', equal: ['string', 'pickles'] },
547
614
  );
548
615
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
549
616
  });
@@ -554,7 +621,7 @@ This one's zip code is 92064.`;
554
621
  // Testing wrong tags and wrong equal...
555
622
  const resultEntity = await nymph.getEntities(
556
623
  { class: TestModel },
557
- { type: '&', tag: 'pickles', equal: ['string', 'pickles'] }
624
+ { type: '&', tag: 'pickles', equal: ['string', 'pickles'] },
558
625
  );
559
626
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
560
627
  });
@@ -565,14 +632,21 @@ This one's zip code is 92064.`;
565
632
  // Retrieving entity by contain...
566
633
  let resultEntity = await nymph.getEntities(
567
634
  { class: TestModel },
568
- { type: '&', contain: ['array', 'values'] }
635
+ { type: '&', contain: ['array', 'values'] },
569
636
  );
570
637
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
571
638
 
572
- // Retrieving entity by contain with full match...
639
+ // Retrieving entity by contain...
573
640
  resultEntity = await nymph.getEntities(
574
641
  { class: TestModel },
575
- { type: '&', contain: ['string', 'test'] }
642
+ { type: '&', contain: ['array', 500] },
643
+ );
644
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
645
+
646
+ // Retrieving entity by contain...
647
+ resultEntity = await nymph.getEntities(
648
+ { class: TestModel },
649
+ { type: '&', contain: ['array', { test: true }] },
576
650
  );
577
651
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
578
652
  });
@@ -584,7 +658,7 @@ This one's zip code is 92064.`;
584
658
  const resultEntity = await nymph.getEntities(
585
659
  { class: TestModel },
586
660
  { type: '&', tag: 'test' },
587
- { type: '!&', contain: ['array', 'pickles'] }
661
+ { type: '!&', contain: ['array', 'pickles'] },
588
662
  );
589
663
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
590
664
  });
@@ -595,14 +669,14 @@ This one's zip code is 92064.`;
595
669
  // Testing wrong contain...
596
670
  let resultEntity = await nymph.getEntities(
597
671
  { class: TestModel },
598
- { type: '&', contain: ['array', 'pickles'] }
672
+ { type: '&', contain: ['array', 'pickles'] },
599
673
  );
600
674
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
601
675
 
602
676
  // Testing wrong contain...
603
677
  resultEntity = await nymph.getEntities(
604
678
  { class: TestModel },
605
- { type: '&', contain: ['string', 'pickles'] }
679
+ { type: '&', contain: ['string', 'pickles'] },
606
680
  );
607
681
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
608
682
  });
@@ -613,12 +687,12 @@ This one's zip code is 92064.`;
613
687
  // Retrieving entity by regex match...
614
688
  let resultEntity = await nymph.getEntities(
615
689
  { class: TestModel },
616
- { type: '&', match: ['match', '.*'] } // anything
690
+ { type: '&', match: ['match', '.*'] }, // anything
617
691
  );
618
692
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
619
693
  resultEntity = await nymph.getEntities(
620
694
  { class: TestModel },
621
- { type: '&', tag: 'test', match: ['match', 'Edward McCheese'] } // a substring
695
+ { type: '&', tag: 'test', match: ['match', 'Edward McCheese'] }, // a substring
622
696
  );
623
697
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
624
698
  resultEntity = await nymph.getEntities(
@@ -630,7 +704,7 @@ This one's zip code is 92064.`;
630
704
  ['string', '[0-9]'],
631
705
  ['match', 'Edward McCheese'],
632
706
  ],
633
- } // inclusive test
707
+ }, // inclusive test
634
708
  );
635
709
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
636
710
  resultEntity = await nymph.getEntities(
@@ -639,7 +713,7 @@ This one's zip code is 92064.`;
639
713
  type: '&',
640
714
  tag: 'test',
641
715
  match: ['match', '[-a-zA-Z0-9+_]+@[-a-zA-Z0-9_]+.[-a-zA-Z0-9_]{2,4}'],
642
- } // a simple email
716
+ }, // a simple email
643
717
  );
644
718
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
645
719
  resultEntity = await nymph.getEntities(
@@ -648,7 +722,7 @@ This one's zip code is 92064.`;
648
722
  type: '&',
649
723
  tag: 'test',
650
724
  match: ['match', '\\([0-9]{3}\\) [0-9]{3}-[0-9]{4}'],
651
- } // a phone number
725
+ }, // a phone number
652
726
  );
653
727
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
654
728
  });
@@ -659,7 +733,7 @@ This one's zip code is 92064.`;
659
733
  // Retrieving entity by regex match...
660
734
  const resultEntity = await nymph.getEntities(
661
735
  { class: TestModel },
662
- { type: '&', tag: 'test', imatch: ['match', 'edward mccheese'] } // a substring
736
+ { type: '&', tag: 'test', imatch: ['match', 'edward mccheese'] }, // a substring
663
737
  );
664
738
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
665
739
  });
@@ -670,12 +744,12 @@ This one's zip code is 92064.`;
670
744
  // Testing wrong regex match...
671
745
  let resultEntity = await nymph.getEntities(
672
746
  { class: TestModel },
673
- { type: '&', match: ['match', 'Q'] }
747
+ { type: '&', match: ['match', '='] },
674
748
  );
675
749
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
676
750
  resultEntity = await nymph.getEntities(
677
751
  { class: TestModel },
678
- { type: '&', tag: 'pickle', match: ['match', '.*'] }
752
+ { type: '&', tag: 'pickle', match: ['match', '.*'] },
679
753
  );
680
754
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
681
755
  resultEntity = await nymph.getEntities(
@@ -686,7 +760,7 @@ This one's zip code is 92064.`;
686
760
  ['string', '[0-9]'],
687
761
  ['match', ',,'],
688
762
  ],
689
- }
763
+ },
690
764
  );
691
765
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
692
766
  });
@@ -697,7 +771,7 @@ This one's zip code is 92064.`;
697
771
  // Retrieving entity by regex match...
698
772
  const resultEntity = await nymph.getEntities(
699
773
  { class: TestModel },
700
- { type: '&', tag: 'test', match: ['match', 'edward mccheese'] } // a substring
774
+ { type: '&', tag: 'test', match: ['match', 'edward mccheese'] }, // a substring
701
775
  );
702
776
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
703
777
  });
@@ -709,7 +783,7 @@ This one's zip code is 92064.`;
709
783
  const resultEntity = await nymph.getEntities(
710
784
  { class: TestModel },
711
785
  { type: '&', tag: 'test' },
712
- { type: '|', equal: ['string', 'pickles'], match: ['string', 'test'] }
786
+ { type: '|', equal: ['string', 'pickles'], match: ['string', 'test'] },
713
787
  );
714
788
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
715
789
  });
@@ -726,7 +800,7 @@ This one's zip code is 92064.`;
726
800
  ['number', 30],
727
801
  ['pickles', 100],
728
802
  ],
729
- }
803
+ },
730
804
  );
731
805
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
732
806
 
@@ -739,7 +813,7 @@ This one's zip code is 92064.`;
739
813
  ['number', 31],
740
814
  ['pickles', 100],
741
815
  ],
742
- }
816
+ },
743
817
  );
744
818
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
745
819
 
@@ -752,7 +826,7 @@ This one's zip code is 92064.`;
752
826
  ['number', 29],
753
827
  ['pickles', 100],
754
828
  ],
755
- }
829
+ },
756
830
  );
757
831
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
758
832
 
@@ -765,7 +839,7 @@ This one's zip code is 92064.`;
765
839
  ['numberString', 30],
766
840
  ['pickles', 100],
767
841
  ],
768
- }
842
+ },
769
843
  );
770
844
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
771
845
 
@@ -778,7 +852,7 @@ This one's zip code is 92064.`;
778
852
  ['numberString', 31],
779
853
  ['pickles', 100],
780
854
  ],
781
- }
855
+ },
782
856
  );
783
857
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
784
858
 
@@ -791,7 +865,7 @@ This one's zip code is 92064.`;
791
865
  ['numberString', 29],
792
866
  ['pickles', 100],
793
867
  ],
794
- }
868
+ },
795
869
  );
796
870
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
797
871
  });
@@ -808,7 +882,7 @@ This one's zip code is 92064.`;
808
882
  ['number', 30],
809
883
  ['pickles', 100],
810
884
  ],
811
- }
885
+ },
812
886
  );
813
887
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
814
888
 
@@ -821,7 +895,7 @@ This one's zip code is 92064.`;
821
895
  ['number', 31],
822
896
  ['pickles', 100],
823
897
  ],
824
- }
898
+ },
825
899
  );
826
900
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
827
901
 
@@ -834,7 +908,7 @@ This one's zip code is 92064.`;
834
908
  ['number', 29],
835
909
  ['pickles', 100],
836
910
  ],
837
- }
911
+ },
838
912
  );
839
913
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
840
914
 
@@ -847,7 +921,7 @@ This one's zip code is 92064.`;
847
921
  ['numberString', 30],
848
922
  ['pickles', 100],
849
923
  ],
850
- }
924
+ },
851
925
  );
852
926
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
853
927
 
@@ -860,7 +934,7 @@ This one's zip code is 92064.`;
860
934
  ['numberString', 31],
861
935
  ['pickles', 100],
862
936
  ],
863
- }
937
+ },
864
938
  );
865
939
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
866
940
 
@@ -873,7 +947,7 @@ This one's zip code is 92064.`;
873
947
  ['numberString', 29],
874
948
  ['pickles', 100],
875
949
  ],
876
- }
950
+ },
877
951
  );
878
952
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
879
953
  });
@@ -890,7 +964,7 @@ This one's zip code is 92064.`;
890
964
  ['number', 30],
891
965
  ['pickles', 100],
892
966
  ],
893
- }
967
+ },
894
968
  );
895
969
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
896
970
 
@@ -903,7 +977,7 @@ This one's zip code is 92064.`;
903
977
  ['number', 31],
904
978
  ['pickles', 100],
905
979
  ],
906
- }
980
+ },
907
981
  );
908
982
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
909
983
 
@@ -916,7 +990,7 @@ This one's zip code is 92064.`;
916
990
  ['number', 29],
917
991
  ['pickles', 100],
918
992
  ],
919
- }
993
+ },
920
994
  );
921
995
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
922
996
 
@@ -929,7 +1003,7 @@ This one's zip code is 92064.`;
929
1003
  ['numberString', 30],
930
1004
  ['pickles', 100],
931
1005
  ],
932
- }
1006
+ },
933
1007
  );
934
1008
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
935
1009
 
@@ -942,7 +1016,7 @@ This one's zip code is 92064.`;
942
1016
  ['numberString', 31],
943
1017
  ['pickles', 100],
944
1018
  ],
945
- }
1019
+ },
946
1020
  );
947
1021
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
948
1022
 
@@ -955,7 +1029,7 @@ This one's zip code is 92064.`;
955
1029
  ['numberString', 29],
956
1030
  ['pickles', 100],
957
1031
  ],
958
- }
1032
+ },
959
1033
  );
960
1034
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
961
1035
  });
@@ -972,7 +1046,7 @@ This one's zip code is 92064.`;
972
1046
  ['number', 30],
973
1047
  ['pickles', 100],
974
1048
  ],
975
- }
1049
+ },
976
1050
  );
977
1051
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
978
1052
 
@@ -985,7 +1059,7 @@ This one's zip code is 92064.`;
985
1059
  ['number', 31],
986
1060
  ['pickles', 100],
987
1061
  ],
988
- }
1062
+ },
989
1063
  );
990
1064
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
991
1065
 
@@ -998,7 +1072,7 @@ This one's zip code is 92064.`;
998
1072
  ['number', 29],
999
1073
  ['pickles', 100],
1000
1074
  ],
1001
- }
1075
+ },
1002
1076
  );
1003
1077
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1004
1078
 
@@ -1011,7 +1085,7 @@ This one's zip code is 92064.`;
1011
1085
  ['numberString', 30],
1012
1086
  ['pickles', 100],
1013
1087
  ],
1014
- }
1088
+ },
1015
1089
  );
1016
1090
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1017
1091
 
@@ -1024,7 +1098,7 @@ This one's zip code is 92064.`;
1024
1098
  ['numberString', 31],
1025
1099
  ['pickles', 100],
1026
1100
  ],
1027
- }
1101
+ },
1028
1102
  );
1029
1103
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1030
1104
 
@@ -1037,7 +1111,7 @@ This one's zip code is 92064.`;
1037
1111
  ['numberString', 29],
1038
1112
  ['pickles', 100],
1039
1113
  ],
1040
- }
1114
+ },
1041
1115
  );
1042
1116
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1043
1117
  });
@@ -1049,7 +1123,7 @@ This one's zip code is 92064.`;
1049
1123
  const resultEntity = await nymph.getEntities(
1050
1124
  { class: TestModel },
1051
1125
  { type: '&', tag: 'test' },
1052
- { type: '!&', gte: ['number', 60] }
1126
+ { type: '!&', gte: ['number', 60] },
1053
1127
  );
1054
1128
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1055
1129
  });
@@ -1060,7 +1134,7 @@ This one's zip code is 92064.`;
1060
1134
  // Testing wrong inequality...
1061
1135
  const resultEntity = await nymph.getEntities(
1062
1136
  { class: TestModel },
1063
- { type: '&', lte: ['number', 29.99] }
1137
+ { type: '&', lte: ['number', 29.99] },
1064
1138
  );
1065
1139
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1066
1140
  });
@@ -1071,7 +1145,7 @@ This one's zip code is 92064.`;
1071
1145
  // Retrieving entity by time...
1072
1146
  const resultEntity = await nymph.getEntities(
1073
1147
  { class: TestModel },
1074
- { type: '&', tag: 'test', gt: ['cdate', (testEntity.cdate ?? 0) - 120] }
1148
+ { type: '&', tag: 'test', gt: ['cdate', (testEntity.cdate ?? 0) - 120] },
1075
1149
  );
1076
1150
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1077
1151
  });
@@ -1082,7 +1156,7 @@ This one's zip code is 92064.`;
1082
1156
  // Testing wrong time...
1083
1157
  const resultEntity = await nymph.getEntities(
1084
1158
  { class: TestModel },
1085
- { type: '&', tag: 'test', gte: ['cdate', (testEntity.cdate ?? 0) + 1] }
1159
+ { type: '&', tag: 'test', gte: ['cdate', (testEntity.cdate ?? 0) + 1] },
1086
1160
  );
1087
1161
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1088
1162
  });
@@ -1095,7 +1169,7 @@ This one's zip code is 92064.`;
1095
1169
  // Retrieving entity by relative time...
1096
1170
  let resultEntity = await nymph.getEntities(
1097
1171
  { class: TestModel },
1098
- { type: '&', gt: ['timestamp', null, '-1 day'] }
1172
+ { type: '&', gt: ['timestamp', null, '-1 day'] },
1099
1173
  );
1100
1174
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1101
1175
  expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
@@ -1109,7 +1183,7 @@ This one's zip code is 92064.`;
1109
1183
  ['timestamp', null, '-1 day'],
1110
1184
  ['timestamp', null, '+5 days'],
1111
1185
  ],
1112
- }
1186
+ },
1113
1187
  );
1114
1188
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1115
1189
  expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
@@ -1117,7 +1191,7 @@ This one's zip code is 92064.`;
1117
1191
  // Retrieving entity by relative time...
1118
1192
  resultEntity = await nymph.getEntities(
1119
1193
  { class: TestModel },
1120
- { type: '&', gt: ['timestamp', null, '-3 days'] }
1194
+ { type: '&', gt: ['timestamp', null, '-3 days'] },
1121
1195
  );
1122
1196
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1123
1197
  expect(referenceEntity.$inArray(resultEntity)).toEqual(true);
@@ -1125,7 +1199,7 @@ This one's zip code is 92064.`;
1125
1199
  // Retrieving entity by relative time...
1126
1200
  resultEntity = await nymph.getEntities(
1127
1201
  { class: TestModel },
1128
- { type: '&', gt: ['cdate', null, '-1 day'] }
1202
+ { type: '&', gt: ['cdate', null, '-1 day'] },
1129
1203
  );
1130
1204
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1131
1205
  expect(referenceEntity.$inArray(resultEntity)).toEqual(true);
@@ -1139,7 +1213,7 @@ This one's zip code is 92064.`;
1139
1213
  // Retrieving entity by relative time...
1140
1214
  let resultEntity = await nymph.getEntities(
1141
1215
  { class: TestModel },
1142
- { type: '&', tag: 'test', gt: ['timestamp', null, '+1 day'] }
1216
+ { type: '&', tag: 'test', gt: ['timestamp', null, '+1 day'] },
1143
1217
  );
1144
1218
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1145
1219
  expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
@@ -1147,7 +1221,7 @@ This one's zip code is 92064.`;
1147
1221
  // Retrieving entity by relative time...
1148
1222
  resultEntity = await nymph.getEntities(
1149
1223
  { class: TestModel },
1150
- { type: '&', tag: 'test', lt: ['timestamp', null, '-3 days'] }
1224
+ { type: '&', tag: 'test', lt: ['timestamp', null, '-3 days'] },
1151
1225
  );
1152
1226
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1153
1227
  expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
@@ -1155,7 +1229,7 @@ This one's zip code is 92064.`;
1155
1229
  // Retrieving entity by relative time...
1156
1230
  resultEntity = await nymph.getEntities(
1157
1231
  { class: TestModel },
1158
- { type: '&', tag: 'test', gt: ['cdate', null, '+1 day'] }
1232
+ { type: '&', tag: 'test', gt: ['cdate', null, '+1 day'] },
1159
1233
  );
1160
1234
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1161
1235
  expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
@@ -1165,9 +1239,11 @@ This one's zip code is 92064.`;
1165
1239
  await createTestEntities();
1166
1240
 
1167
1241
  // Testing referenced entities...
1242
+ await testEntity.reference?.$wake();
1168
1243
  expect(testEntity.reference?.test).toEqual('good');
1169
1244
 
1170
1245
  // Testing referenced entity arrays...
1246
+ await Promise.all(testEntity.refArray?.map((e) => e.$wake()) || []);
1171
1247
  expect(testEntity.refArray?.[0].test).toEqual('good');
1172
1248
  });
1173
1249
 
@@ -1177,7 +1253,7 @@ This one's zip code is 92064.`;
1177
1253
  // Retrieving entity by reference...
1178
1254
  const resultEntity = await nymph.getEntities(
1179
1255
  { class: TestModel },
1180
- { type: '&', ref: ['reference', refGuid] }
1256
+ { type: '&', ref: ['reference', refGuid] },
1181
1257
  );
1182
1258
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1183
1259
  });
@@ -1189,7 +1265,7 @@ This one's zip code is 92064.`;
1189
1265
  const resultEntity = await nymph.getEntities(
1190
1266
  { class: TestModel },
1191
1267
  { type: '&', tag: 'test' },
1192
- { type: '!&', ref: ['reference', guid()] }
1268
+ { type: '!&', ref: ['reference', guid()] },
1193
1269
  );
1194
1270
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1195
1271
  });
@@ -1200,7 +1276,7 @@ This one's zip code is 92064.`;
1200
1276
  // Testing wrong reference...
1201
1277
  const resultEntity = await nymph.getEntities(
1202
1278
  { class: TestModel },
1203
- { type: '&', ref: ['reference', guid()] }
1279
+ { type: '&', ref: ['reference', guid()] },
1204
1280
  );
1205
1281
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1206
1282
  });
@@ -1211,7 +1287,7 @@ This one's zip code is 92064.`;
1211
1287
  // Testing non-existent reference...
1212
1288
  const resultEntity = await nymph.getEntities(
1213
1289
  { class: TestModel },
1214
- { type: '&', ref: ['pickle', refGuid] }
1290
+ { type: '&', ref: ['pickle', refGuid] },
1215
1291
  );
1216
1292
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1217
1293
  });
@@ -1228,7 +1304,7 @@ This one's zip code is 92064.`;
1228
1304
  ['reference', refGuid],
1229
1305
  ['reference', guid()],
1230
1306
  ],
1231
- }
1307
+ },
1232
1308
  );
1233
1309
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1234
1310
  });
@@ -1245,7 +1321,7 @@ This one's zip code is 92064.`;
1245
1321
  ['reference', guid()],
1246
1322
  ['reference', guid()],
1247
1323
  ],
1248
- }
1324
+ },
1249
1325
  );
1250
1326
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1251
1327
  });
@@ -1256,7 +1332,7 @@ This one's zip code is 92064.`;
1256
1332
  // Retrieving entity by array reference...
1257
1333
  const resultEntity = await nymph.getEntities(
1258
1334
  { class: TestModel },
1259
- { type: '&', ref: ['refArray', refGuid] }
1335
+ { type: '&', ref: ['refArray', refGuid] },
1260
1336
  );
1261
1337
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1262
1338
  });
@@ -1273,7 +1349,7 @@ This one's zip code is 92064.`;
1273
1349
  ['refArray', refGuid],
1274
1350
  ['refArray', guid()],
1275
1351
  ],
1276
- }
1352
+ },
1277
1353
  );
1278
1354
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1279
1355
  });
@@ -1307,6 +1383,8 @@ This one's zip code is 92064.`;
1307
1383
  ['array', 'of'],
1308
1384
  ['array', 'values'],
1309
1385
  ['array', 500],
1386
+ ['array', { test: true }],
1387
+ ['array', { nullbyte: '\\\x00\u0000 \x00' }],
1310
1388
  ],
1311
1389
  },
1312
1390
  {
@@ -1318,7 +1396,7 @@ This one's zip code is 92064.`;
1318
1396
  ['array', 'values'],
1319
1397
  ['array', 500],
1320
1398
  ],
1321
- }
1399
+ },
1322
1400
  );
1323
1401
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1324
1402
  });
@@ -1338,13 +1416,13 @@ This one's zip code is 92064.`;
1338
1416
 
1339
1417
  const resultSelectors = await nymph.getEntities(
1340
1418
  { class: TestModel },
1341
- { type: '&', ref: ['reference', refGuid] }
1419
+ { type: '&', ref: ['reference', refGuid] },
1342
1420
  );
1343
1421
 
1344
1422
  // Testing count return with selectors...
1345
1423
  const resultSelectorsCount = await nymph.getEntities(
1346
1424
  { class: TestModel, return: 'count' },
1347
- { type: '&', ref: ['reference', refGuid] }
1425
+ { type: '&', ref: ['reference', refGuid] },
1348
1426
  );
1349
1427
  expect(resultSelectorsCount).toBeGreaterThanOrEqual(1);
1350
1428
  expect(resultSelectorsCount).toEqual(resultSelectors.length);
@@ -1367,7 +1445,7 @@ This one's zip code is 92064.`;
1367
1445
  // Testing empty count...
1368
1446
  const resultSelectorsEmpty = await nymph.getEntities(
1369
1447
  { class: TestModel, return: 'count' },
1370
- { type: '&', ref: ['reference', guid()] }
1448
+ { type: '&', ref: ['reference', guid()] },
1371
1449
  );
1372
1450
  expect(resultSelectorsEmpty).toEqual(0);
1373
1451
  });
@@ -1401,6 +1479,8 @@ This one's zip code is 92064.`;
1401
1479
  ['array', 'of'],
1402
1480
  ['array', 'values'],
1403
1481
  ['array', 500],
1482
+ ['array', { test: true }],
1483
+ ['array', { nullbyte: '\\\x00\u0000 \x00' }],
1404
1484
  ],
1405
1485
  },
1406
1486
  {
@@ -1412,7 +1492,7 @@ This one's zip code is 92064.`;
1412
1492
  ['array', 'values'],
1413
1493
  ['array', 500],
1414
1494
  ],
1415
- }
1495
+ },
1416
1496
  );
1417
1497
  expect(resultGuid.indexOf(testEntity.guid ?? '')).toBeGreaterThan(-1);
1418
1498
  });
@@ -1449,6 +1529,8 @@ This one's zip code is 92064.`;
1449
1529
  ['array', 'of'],
1450
1530
  ['array', 'values'],
1451
1531
  ['array', 500],
1532
+ ['array', { test: true }],
1533
+ ['array', { nullbyte: '\\\x00\u0000 \x00' }],
1452
1534
  ],
1453
1535
  },
1454
1536
  {
@@ -1462,7 +1544,7 @@ This one's zip code is 92064.`;
1462
1544
  ],
1463
1545
  },
1464
1546
  ],
1465
- }
1547
+ },
1466
1548
  );
1467
1549
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1468
1550
 
@@ -1494,6 +1576,8 @@ This one's zip code is 92064.`;
1494
1576
  ['array', 'of'],
1495
1577
  ['array', 'values'],
1496
1578
  ['array', 500],
1579
+ ['array', { test: true }],
1580
+ ['array', { nullbyte: '\\\x00\u0000 \x00' }],
1497
1581
  ],
1498
1582
  },
1499
1583
  {
@@ -1507,7 +1591,7 @@ This one's zip code is 92064.`;
1507
1591
  ],
1508
1592
  },
1509
1593
  ],
1510
- }
1594
+ },
1511
1595
  );
1512
1596
  expect(testEntity.$inArray(resultEntity2)).toEqual(true);
1513
1597
 
@@ -1523,7 +1607,7 @@ This one's zip code is 92064.`;
1523
1607
  },
1524
1608
  { type: '&', gte: ['number', 16000] },
1525
1609
  ],
1526
- }
1610
+ },
1527
1611
  );
1528
1612
  expect(testEntity.$inArray(resultEntity3)).toEqual(true);
1529
1613
 
@@ -1545,7 +1629,7 @@ This one's zip code is 92064.`;
1545
1629
  },
1546
1630
  },
1547
1631
  ],
1548
- }
1632
+ },
1549
1633
  );
1550
1634
  expect(testEntity.$inArray(resultEntity4)).toEqual(true);
1551
1635
  });
@@ -1564,7 +1648,7 @@ This one's zip code is 92064.`;
1564
1648
  },
1565
1649
  { type: '&', gte: ['number', 16000] },
1566
1650
  ],
1567
- }
1651
+ },
1568
1652
  );
1569
1653
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1570
1654
  });
@@ -1581,7 +1665,7 @@ This one's zip code is 92064.`;
1581
1665
  'reference',
1582
1666
  [{ class: TestModel }, { type: '&', equal: ['test', 'good'] }],
1583
1667
  ],
1584
- }
1668
+ },
1585
1669
  );
1586
1670
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1587
1671
  });
@@ -1598,7 +1682,7 @@ This one's zip code is 92064.`;
1598
1682
  'reference',
1599
1683
  [{ class: TestModel }, { type: '&', equal: ['test', 'pickles'] }],
1600
1684
  ],
1601
- }
1685
+ },
1602
1686
  );
1603
1687
  expect(testEntity.$inArray(resultEntity)).toEqual(true);
1604
1688
  });
@@ -1615,7 +1699,7 @@ This one's zip code is 92064.`;
1615
1699
  'reference',
1616
1700
  [{ class: TestBModel }, { type: '&', equal: ['test', 'good'] }],
1617
1701
  ],
1618
- }
1702
+ },
1619
1703
  );
1620
1704
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1621
1705
  });
@@ -1632,31 +1716,28 @@ This one's zip code is 92064.`;
1632
1716
  'reference',
1633
1717
  [{ class: TestModel }, { type: '&', equal: ['test', 'pickles'] }],
1634
1718
  ],
1635
- }
1719
+ },
1636
1720
  );
1637
1721
  expect(testEntity.$inArray(resultEntity)).toEqual(false);
1638
1722
  });
1639
1723
 
1640
- it('sort option', async () => {
1724
+ it('cdate and mdate sort option', async () => {
1641
1725
  await createMultipleTestEntities();
1642
1726
 
1643
- for (const sort of ['cdate', 'mdate']) {
1727
+ for (const sort of ['cdate', 'mdate'] as ('cdate' | 'mdate')[]) {
1644
1728
  // Retrieving entities sorted...
1645
- let resultEntities = await nymph.getEntities({
1646
- class: TestModel,
1647
- sort: sort as 'cdate' | 'mdate',
1648
- });
1729
+ let resultEntities = await nymph.getEntities({ class: TestModel, sort });
1649
1730
  expect(resultEntities.length).toBeGreaterThan(100);
1650
1731
  for (let i = 0; i < resultEntities.length - 1; i++) {
1651
- expect(
1652
- resultEntities[i + 1][sort as 'cdate' | 'mdate']
1653
- ).toBeGreaterThan(resultEntities[i][sort as 'cdate' | 'mdate'] ?? 0);
1732
+ expect(resultEntities[i + 1][sort]).toBeGreaterThan(
1733
+ resultEntities[i][sort] ?? 0,
1734
+ );
1654
1735
  }
1655
1736
 
1656
1737
  // And test the same with guid return...
1657
1738
  let resultGuids = await nymph.getEntities({
1658
1739
  class: TestModel,
1659
- sort: sort as 'cdate' | 'mdate',
1740
+ sort,
1660
1741
  return: 'guid',
1661
1742
  });
1662
1743
  expect(resultGuids.length).toBeGreaterThan(100);
@@ -1667,48 +1748,121 @@ This one's zip code is 92064.`;
1667
1748
  // Retrieving entities reverse sorted...
1668
1749
  resultEntities = await nymph.getEntities({
1669
1750
  class: TestModel,
1670
- sort: sort as 'cdate' | 'mdate',
1751
+ sort,
1671
1752
  reverse: true,
1672
1753
  });
1673
1754
  expect(resultEntities.length).toBeGreaterThan(100);
1674
1755
  for (let i = 0; i < resultEntities.length - 1; i++) {
1675
- expect(resultEntities[i + 1][sort as 'cdate' | 'mdate']).toBeLessThan(
1676
- resultEntities[i][sort as 'cdate' | 'mdate'] ?? 0
1756
+ expect(resultEntities[i + 1][sort]).toBeLessThan(
1757
+ resultEntities[i][sort] ?? 0,
1677
1758
  );
1678
1759
  }
1679
1760
 
1680
1761
  // And again with other selectors.
1681
1762
  // Retrieving entities sorted...
1682
1763
  resultEntities = await nymph.getEntities(
1683
- { class: TestModel, sort: sort as 'cdate' | 'mdate' },
1684
- { type: '&', match: ['name', '^Multi Test '] }
1764
+ { class: TestModel, sort },
1765
+ { type: '&', match: ['name', '^Multi Test '] },
1685
1766
  );
1686
1767
  expect(resultEntities.length).toEqual(100);
1687
1768
  for (let i = 0; i < resultEntities.length - 1; i++) {
1688
- expect(
1689
- resultEntities[i + 1][sort as 'cdate' | 'mdate']
1690
- ).toBeGreaterThan(resultEntities[i][sort as 'cdate' | 'mdate'] ?? 0);
1769
+ expect(resultEntities[i + 1][sort]).toBeGreaterThan(
1770
+ resultEntities[i][sort] ?? 0,
1771
+ );
1691
1772
  }
1692
1773
 
1693
1774
  // Retrieving entities reverse sorted...
1694
1775
  resultEntities = await nymph.getEntities(
1695
- { class: TestModel, sort: sort as 'cdate' | 'mdate', reverse: true },
1696
- { type: '&', match: ['name', '^Multi Test '] }
1776
+ { class: TestModel, sort, reverse: true },
1777
+ { type: '&', match: ['name', '^Multi Test '] },
1697
1778
  );
1698
1779
  expect(resultEntities.length).toEqual(100);
1699
1780
  for (let i = 0; i < resultEntities.length - 1; i++) {
1700
- expect(resultEntities[i + 1][sort as 'cdate' | 'mdate']).toBeLessThan(
1701
- resultEntities[i][sort as 'cdate' | 'mdate'] ?? 0
1781
+ expect(resultEntities[i + 1][sort]).toBeLessThan(
1782
+ resultEntities[i][sort] ?? 0,
1702
1783
  );
1703
1784
  }
1704
1785
  }
1705
1786
  });
1706
1787
 
1788
+ it('property sort option', async () => {
1789
+ await createMultipleTestEntities();
1790
+
1791
+ // Retrieving entities sorted...
1792
+ let resultEntities = await nymph.getEntities({
1793
+ class: TestModel,
1794
+ sort: 'number',
1795
+ });
1796
+ expect(resultEntities.length).toBeGreaterThan(100);
1797
+ for (let i = 0; i < resultEntities.length - 1; i++) {
1798
+ expect(resultEntities[i + 1].number ?? Infinity).toBeGreaterThanOrEqual(
1799
+ resultEntities[i].number ?? 0,
1800
+ );
1801
+ }
1802
+
1803
+ // And test the same with guid return...
1804
+ let resultGuids = await nymph.getEntities({
1805
+ class: TestModel,
1806
+ sort: 'number',
1807
+ return: 'guid',
1808
+ });
1809
+ expect(resultGuids.length).toBeGreaterThan(100);
1810
+ for (let i = 0; i < resultGuids.length - 1; i++) {
1811
+ expect(resultGuids[i]).toEqual(resultEntities[i].guid);
1812
+ }
1813
+
1814
+ // Retrieving entities reverse sorted...
1815
+ resultEntities = await nymph.getEntities({
1816
+ class: TestModel,
1817
+ sort: 'number',
1818
+ reverse: true,
1819
+ });
1820
+ expect(resultEntities.length).toBeGreaterThan(100);
1821
+ for (let i = 0; i < resultEntities.length - 1; i++) {
1822
+ expect(resultEntities[i + 1].number ?? 0).toBeLessThanOrEqual(
1823
+ resultEntities[i].number ?? Infinity,
1824
+ );
1825
+ }
1826
+
1827
+ // And again with other selectors.
1828
+ // Retrieving entities sorted...
1829
+ resultEntities = await nymph.getEntities(
1830
+ { class: TestModel, sort: 'number' },
1831
+ { type: '&', match: ['name', '^Multi Test '] },
1832
+ );
1833
+ expect(resultEntities.length).toEqual(100);
1834
+ for (let i = 0; i < resultEntities.length - 1; i++) {
1835
+ expect(resultEntities[i + 1].number ?? Infinity).toBeGreaterThan(
1836
+ resultEntities[i].number ?? 0,
1837
+ );
1838
+ expect(resultEntities[i].name).toEqual(
1839
+ `Multi Test ${100 - (resultEntities[i].number ?? 0)}`,
1840
+ );
1841
+ }
1842
+
1843
+ // Retrieving entities reverse sorted...
1844
+ resultEntities = await nymph.getEntities(
1845
+ { class: TestModel, sort: 'number', reverse: true },
1846
+ { type: '&', match: ['name', '^Multi Test '] },
1847
+ );
1848
+ expect(resultEntities.length).toEqual(100);
1849
+ for (let i = 0; i < resultEntities.length - 1; i++) {
1850
+ expect(resultEntities[i + 1].number ?? 0).toBeLessThan(
1851
+ resultEntities[i].number ?? Infinity,
1852
+ );
1853
+ expect(resultEntities[i].name).toEqual(
1854
+ `Multi Test ${100 - (resultEntities[i].number ?? 0)}`,
1855
+ );
1856
+ }
1857
+ });
1858
+
1707
1859
  it('delete reference', async () => {
1708
1860
  await createTestEntities();
1709
1861
 
1710
1862
  // Deleting referenced entities...
1863
+ await testEntity.reference?.$wake();
1711
1864
  expect(await testEntity.reference?.$delete()).toEqual(true);
1865
+ await Promise.all(testEntity.refArray?.map((e) => e.$wake()) || []);
1712
1866
  expect(testEntity.reference?.guid).toBeNull();
1713
1867
  });
1714
1868
 
@@ -1721,16 +1875,116 @@ This one's zip code is 92064.`;
1721
1875
 
1722
1876
  const entity = await nymph.getEntity(
1723
1877
  { class: TestModel },
1724
- { type: '&', guid: testGuid }
1878
+ { type: '&', guid: testGuid },
1725
1879
  );
1726
1880
 
1727
1881
  expect(entity).toBeNull();
1728
1882
  });
1883
+
1884
+ it('allows non-duplicate unique strings', async () => {
1885
+ // Creating entity...
1886
+ const uniqueEntityA = await TestModel.factory();
1887
+ uniqueEntityA.name = 'Entity Test ' + new Date().toLocaleString();
1888
+ uniqueEntityA.uniques = ['test a'];
1889
+
1890
+ // Saving entity...
1891
+ expect(await uniqueEntityA.$save()).toEqual(true);
1892
+ expect(uniqueEntityA.guid).not.toBeNull();
1893
+
1894
+ // Creating entity...
1895
+ const uniqueEntityB = await TestModel.factory();
1896
+ uniqueEntityB.name = 'Entity Test ' + new Date().toLocaleString();
1897
+ uniqueEntityB.uniques = ['test b'];
1898
+
1899
+ // Saving entity...
1900
+ expect(await uniqueEntityB.$save()).toEqual(true);
1901
+ expect(uniqueEntityB.guid).not.toBeNull();
1902
+
1903
+ expect(uniqueEntityA.guid).not.toEqual(uniqueEntityB.guid);
1904
+
1905
+ expect(await uniqueEntityA.$delete()).toEqual(true);
1906
+ expect(await uniqueEntityB.$delete()).toEqual(true);
1907
+ });
1908
+
1909
+ it('throws on duplicate unique strings', async () => {
1910
+ // Creating entity...
1911
+ const uniqueEntityA = await TestModel.factory();
1912
+ uniqueEntityA.name = 'Entity Test ' + new Date().toLocaleString();
1913
+ uniqueEntityA.uniques = ['test a'];
1914
+
1915
+ // Saving entity...
1916
+ expect(await uniqueEntityA.$save()).toEqual(true);
1917
+ expect(uniqueEntityA.guid).not.toBeNull();
1918
+
1919
+ // Creating entity...
1920
+ const uniqueEntityB = await TestModel.factory();
1921
+ uniqueEntityB.name = 'Entity Test ' + new Date().toLocaleString();
1922
+ uniqueEntityB.uniques = ['test a'];
1923
+
1924
+ // Saving entity...
1925
+ try {
1926
+ await uniqueEntityB.$save();
1927
+
1928
+ throw Error("Shouldn't get past the uniqueness check.");
1929
+ } catch (e: any) {
1930
+ expect(e).toBeInstanceOf(EntityUniqueConstraintError);
1931
+ }
1932
+ expect(uniqueEntityB.guid).toBeNull();
1933
+
1934
+ expect(await uniqueEntityA.$delete()).toEqual(true);
1935
+ });
1936
+
1937
+ it('allows duplicate unique string if first transaction is rolled back', async () => {
1938
+ // Creating transaction entity...
1939
+ const tnymphA = await nymph.startTransaction('test-unique-a');
1940
+ const TestModelA = tnymphA.getEntityClass(TestModel);
1941
+ const uniqueEntityA = await TestModelA.factory();
1942
+ uniqueEntityA.name = 'Entity Test ' + new Date().toLocaleString();
1943
+ uniqueEntityA.uniques = ['test a'];
1944
+
1945
+ // Saving entity...
1946
+ expect(await uniqueEntityA.$save()).toEqual(true);
1947
+ expect(uniqueEntityA.guid).not.toBeNull();
1948
+
1949
+ // Rolling back transaction...
1950
+ expect(await tnymphA.rollback('test-unique-a')).toEqual(true);
1951
+
1952
+ // Creating transaction entity...
1953
+ const tnymphB = await nymph.startTransaction('test-unique-b');
1954
+ const TestModelB = tnymphB.getEntityClass(TestModel);
1955
+ const uniqueEntityB = await TestModelB.factory();
1956
+ uniqueEntityB.name = 'Entity Test ' + new Date().toLocaleString();
1957
+ uniqueEntityB.uniques = ['test a'];
1958
+
1959
+ // Saving entity...
1960
+ expect(await uniqueEntityB.$save()).toEqual(true);
1961
+ expect(uniqueEntityB.guid).not.toBeNull();
1962
+
1963
+ expect(uniqueEntityA.guid).not.toEqual(uniqueEntityB.guid);
1964
+
1965
+ expect(await tnymphB.commit('test-unique-b')).toEqual(true);
1966
+
1967
+ const uniqueEntityACheck = await nymph.getEntity(
1968
+ { class: TestModel },
1969
+ { type: '&', guid: uniqueEntityA.guid ?? '' },
1970
+ );
1971
+ expect(uniqueEntityACheck).toBeNull();
1972
+
1973
+ const uniqueEntityBCheck = await nymph.getEntity(
1974
+ { class: TestModel },
1975
+ { type: '&', guid: uniqueEntityB.guid ?? '' },
1976
+ );
1977
+ expect(uniqueEntityBCheck).not.toBeNull();
1978
+
1979
+ if (uniqueEntityBCheck != null) {
1980
+ expect(await uniqueEntityBCheck.$delete()).toEqual(true);
1981
+ }
1982
+ });
1729
1983
  }
1730
1984
 
1731
1985
  export function UIDTest(
1732
1986
  nymph: Nymph,
1733
- it: (name: string, fn: () => void) => void
1987
+ it: (name: string, fn: () => void) => void,
1734
1988
  ) {
1735
1989
  it('delete old test data', async () => {
1736
1990
  expect(await nymph.deleteUID('TestUID')).toEqual(true);
@@ -1771,7 +2025,7 @@ export function UIDTest(
1771
2025
 
1772
2026
  export function ExportImportTest(
1773
2027
  nymph: Nymph,
1774
- it: (name: string, fn: () => void) => void
2028
+ it: (name: string, fn: () => void) => void,
1775
2029
  ) {
1776
2030
  const TestModel = nymph.addEntityClass(TestModelClass);
1777
2031
  const TestBModel = nymph.addEntityClass(TestBModelClass);
@@ -1807,23 +2061,38 @@ export function ExportImportTest(
1807
2061
  const bmodels = await nymph.getEntities({ class: TestBModel });
1808
2062
 
1809
2063
  expect(models.length).toEqual(30);
1810
- expect(bmodels.length).toEqual(10);
1811
-
1812
- const all = [...models, ...bmodels];
1813
- for (const model of all) {
1814
- if (model.index?.match(/^\d+a$/)) {
1815
- expect(model.null).toBeNull();
1816
- expect(model.string).toEqual('test');
1817
- expect(model.array).toEqual(['full', 'of', 'values', 500]);
1818
- expect(model.number).toEqual(30);
1819
- expect(model.timestamp).toBeGreaterThanOrEqual(strtotime('-2 minutes'));
1820
-
1821
- expect(model.reference?.guid).not.toBeNull();
1822
- expect(model.reference?.string).toEqual('another');
1823
- expect(model.reference?.index?.match(/^\d+b$/)).toBeTruthy();
1824
- expect(model.refArray?.[0].guid).not.toBeNull();
1825
- expect(model.refArray?.[0].guid).toEqual(model.reference?.guid);
1826
- }
2064
+ expect(bmodels.length).toEqual(30);
2065
+
2066
+ for (const model of models) {
2067
+ expect(model.name).toMatch(/^Entity Test /);
2068
+ expect(model.null).toBeDefined();
2069
+ expect(model.null).toBeNull();
2070
+ expect(model.string).toEqual('test');
2071
+ expect(model.array).toEqual([
2072
+ 'full',
2073
+ 'of',
2074
+ 'values',
2075
+ 500,
2076
+ { test: true },
2077
+ { nullbyte: '\\\x00\u0000 \x00' },
2078
+ ]);
2079
+ expect(model.match).toEqual(matchValue);
2080
+ expect(model.number).toEqual(30);
2081
+ expect(model.numberString).toEqual('30');
2082
+ expect(model.timestamp).toBeGreaterThanOrEqual(strtotime('-2 minutes'));
2083
+ expect(model.index).toMatch(/^\d+a$/);
2084
+
2085
+ await model.reference?.$wake();
2086
+ expect(model.reference?.guid).not.toBeNull();
2087
+ expect(model.reference?.string).toEqual('another');
2088
+ expect(model.reference?.index).toMatch(/^\d+b$/);
2089
+ expect(model.index?.substring(0, -1)).toEqual(
2090
+ model.reference?.index?.substring(0, -1),
2091
+ );
2092
+ expect(model.reference?.$inArray(bmodels)).toEqual(true);
2093
+ await Promise.all(model.refArray?.map((e) => e.$wake()) || []);
2094
+ expect(model.refArray?.[0].guid).not.toBeNull();
2095
+ expect(model.refArray?.[0].guid).toEqual(model.reference?.guid);
1827
2096
  }
1828
2097
  }
1829
2098
 
@@ -1836,22 +2105,29 @@ export function ExportImportTest(
1836
2105
  expect(await nymph.newUID('TestUID')).toEqual(2);
1837
2106
  expect(await nymph.newUID('TestUID2')).toEqual(1);
1838
2107
 
1839
- for (let i = 0; i < 20; i++) {
1840
- const EntityClass = i < 15 ? TestModel : TestBModel;
1841
-
2108
+ for (let i = 0; i < 30; i++) {
1842
2109
  // Creating entity...
1843
- const testEntity = await EntityClass.factory();
2110
+ const testEntity = await TestModel.factory();
1844
2111
 
1845
2112
  // Saving entity...
1846
2113
  testEntity.name = 'Entity Test ' + new Date().toLocaleString();
1847
2114
  testEntity.null = null;
1848
2115
  testEntity.string = 'test';
1849
- testEntity.array = ['full', 'of', 'values', 500];
2116
+ testEntity.array = [
2117
+ 'full',
2118
+ 'of',
2119
+ 'values',
2120
+ 500,
2121
+ { test: true },
2122
+ { nullbyte: '\\\x00\u0000 \x00' },
2123
+ ];
2124
+ testEntity.match = matchValue;
1850
2125
  testEntity.number = 30;
2126
+ testEntity.numberString = '30';
1851
2127
  testEntity.timestamp = Date.now();
1852
2128
  testEntity.index = i + 'a';
1853
2129
 
1854
- const entityReferenceTest = await EntityClass.factory();
2130
+ const entityReferenceTest = await TestBModel.factory();
1855
2131
  entityReferenceTest.string = 'another';
1856
2132
  entityReferenceTest.index = i + 'b';
1857
2133
 
@@ -1865,9 +2141,13 @@ export function ExportImportTest(
1865
2141
  await checkEntityDataAndCount();
1866
2142
  });
1867
2143
 
2144
+ it('needs migration', async () => {
2145
+ expect(await nymph.needsMigration()).toEqual(false);
2146
+ });
2147
+
1868
2148
  it('export data', async () => {
1869
2149
  expect(await nymph.export(__dirname + '/testentityexport.nex')).toEqual(
1870
- true
2150
+ true,
1871
2151
  );
1872
2152
  });
1873
2153
 
@@ -1884,7 +2164,7 @@ export function ExportImportTest(
1884
2164
  expect(bmodels.length).toEqual(0);
1885
2165
 
1886
2166
  expect(await nymph.import(__dirname + '/testentityexport.nex')).toEqual(
1887
- true
2167
+ true,
1888
2168
  );
1889
2169
 
1890
2170
  await checkEntityDataAndCount();
@@ -1892,3 +2172,114 @@ export function ExportImportTest(
1892
2172
  fs.unlinkSync(__dirname + '/testentityexport.nex');
1893
2173
  });
1894
2174
  }
2175
+
2176
+ const matchValue = `Hello, my name is Edward McCheese. It is a pleasure to meet you. As you can see, I have several hats of the most pleasant nature.
2177
+
2178
+ This one's email address is nice_hat-wednesday+newyork@im-a-hat.hat.
2179
+ This one's phone number is (555) 555-1818.
2180
+ This one's zip code is 92064.
2181
+ This one's favorite emojis are 🔥❤️😊😂⭐🤔
2182
+
2183
+ These hats are absolutely fantastic.
2184
+
2185
+ \x00\x00\x00
2186
+
2187
+ Lorem ipsum odor amet, consectetuer adipiscing elit. Metus ad mattis sit pretium per, dignissim imperdiet luctus. Congue rhoncus turpis etiam aenean ultricies dapibus justo nunc. Netus non primis quis habitasse lacus. Nascetur dapibus sociosqu ridiculus primis; elementum netus consectetur ridiculus litora. Tristique facilisis erat ex class nulla cursus amet. Metus vitae tempor euismod vel; ullamcorper ac quisque vestibulum. Mauris libero pulvinar facilisi eros natoque massa.
2188
+
2189
+ Nunc vel hac nec tristique vivamus. Leo volutpat convallis eget integer tellus cubilia tincidunt malesuada? Consequat elit nisi tristique vehicula cubilia maecenas metus facilisi malesuada. In mattis euismod ad magnis fusce. Nisi congue sociosqu rhoncus lobortis fringilla sollicitudin at platea. Iaculis ut et varius metus eleifend laoreet hac odio libero. Non ridiculus tempus ultricies nullam curabitur.
2190
+
2191
+ Amet pellentesque aliquam placerat; vestibulum blandit platea porttitor pulvinar. Tellus tristique ad morbi in ac placerat luctus. Ante efficitur inceptos commodo lacus sodales sit varius nunc consequat. Senectus non vel est convallis mauris. Venenatis feugiat massa nostra, purus class primis sodales odio. Risus nulla integer feugiat ridiculus porta nascetur. Rutrum tincidunt enim parturient libero nisl ante sagittis nisi. Cubilia massa non vehicula vehicula amet parturient pellentesque. Habitant dapibus fames lectus pretium rhoncus.
2192
+
2193
+ Ridiculus nascetur mauris iaculis hendrerit ridiculus gravida auctor in. Class suscipit augue finibus semper vulputate nec. Tristique mi eu praesent commodo fermentum inceptos penatibus lobortis. Libero enim orci ultricies egestas ut pellentesque. Laoreet massa ad curabitur tellus libero laoreet habitasse enim nascetur. Iaculis euismod a euismod conubia purus. Commodo condimentum ultrices lorem ligula aenean; netus mattis sem non.
2194
+
2195
+ Curabitur duis imperdiet mus integer vel bibendum; fusce malesuada. Dignissim duis himenaeos primis odio, congue pharetra? Egestas mus sit eget proin quis. Neque dapibus dapibus nam sociosqu; maecenas viverra himenaeos. Himenaeos faucibus himenaeos faucibus ex litora eros faucibus cras. Maximus scelerisque nullam nunc congue fringilla. Nisi eu magna erat morbi cras enim amet litora. Nostra primis vitae arcu, accumsan sollicitudin curabitur. Potenti sit vel vehicula metus leo id. Etiam blandit quisque nam orci; neque lacinia rutrum.
2196
+
2197
+ Aliquam mollis varius hendrerit sem eleifend fermentum. Sapien rutrum condimentum inceptos ex feugiat consectetur mollis magna diam. Natoque enim nisi, ex risus finibus lacinia conubia vivamus suscipit. Habitasse interdum lorem ante, bibendum posuere dis. Lacus porttitor sapien proin; consequat velit ipsum venenatis. Vivamus porta mattis morbi nunc torquent neque. Senectus vehicula tincidunt parturient fringilla id amet urna libero pharetra.
2198
+
2199
+ Faucibus netus tincidunt et viverra augue ligula est quis. Ipsum tempus vehicula tortor dis tortor ad. Ex tincidunt torquent eleifend aenean urna commodo. Quam nullam imperdiet volutpat vel condimentum cubilia sociosqu. Etiam tempor sapien mattis, venenatis aptent id risus. Efficitur luctus vel; nam ut commodo sociosqu hendrerit. Quisque placerat gravida rhoncus blandit vitae. Himenaeos id risus est mollis aliquet nam curabitur.
2200
+
2201
+ Habitasse sed est fames quis lobortis leo mattis. Nisl cursus tincidunt cursus felis porttitor. Ante integer turpis non class lobortis suscipit. Condimentum velit vulputate quis sapien, lacus magna adipiscing nec primis. Blandit consequat ipsum nostra dignissim; tincidunt torquent fames. Ac faucibus elit iaculis duis lobortis. Euismod facilisi massa turpis mus neque. Class vulputate quisque elementum suscipit nostra tempus adipiscing. Malesuada himenaeos finibus ad inceptos volutpat scelerisque inceptos.
2202
+
2203
+ Natoque platea at feugiat cras tellus facilisi suspendisse lacinia maximus. Duis vestibulum eget molestie turpis risus dapibus dignissim torquent? Nulla nibh aptent fringilla scelerisque euismod mauris ornare. Orci finibus taciti habitasse fringilla laoreet convallis. Class sed fringilla eget quisque sit auctor. Id cursus mauris praesent maecenas iaculis. Ullamcorper luctus habitant ultrices pharetra etiam mattis morbi fringilla lorem.
2204
+
2205
+ Pharetra porta orci ridiculus inceptos eleifend sem ante quis. Molestie velit penatibus libero per sem litora congue. Porta quis egestas vivamus vitae potenti ornare. Elit molestie nullam vitae quam viverra. Nisl fringilla massa ridiculus donec ridiculus sed magnis. Cursus ad enim consequat ultricies tortor rhoncus pellentesque augue. Netus facilisis tempor elementum interdum at sagittis habitasse. Pretium imperdiet duis diam ullamcorper donec at suscipit. Id per inceptos ac luctus massa imperdiet tempor. Parturient libero suscipit non tempor ligula ullamcorper placerat varius.
2206
+
2207
+ Libero duis suspendisse cubilia rhoncus scelerisque faucibus mattis. Leo fusce urna at per inceptos vel lobortis. Quisque ex duis euismod dictum hac nibh eros. Penatibus eleifend tellus donec elit primis phasellus habitant dictum. Imperdiet consequat facilisi massa, lacus gravida sodales id sapien. Ornare sapien sit convallis suscipit nunc enim. Tempus at vitae class sollicitudin proin. Dolor aenean felis netus consectetur mattis phasellus vestibulum. Orci fringilla sodales montes sed himenaeos ex massa natoque porttitor.
2208
+
2209
+ Mus condimentum dui mollis dolor accumsan ligula pretium? Est phasellus platea iaculis vehicula et eros vel rutrum placerat. Nulla laoreet faucibus; congue netus magna senectus lectus dictum. Sodales aliquam eget himenaeos adipiscing, tempor feugiat. Lorem pellentesque iaculis fames lectus cubilia ornare sagittis rhoncus? Bibendum viverra tellus libero congue dignissim metus tellus aenean ultrices. Sollicitudin cras sollicitudin mattis lacus facilisis fermentum scelerisque porttitor rutrum.
2210
+
2211
+ Sapien aptent fames curae, consectetur dapibus mauris sollicitudin tellus. Laoreet etiam dignissim, suscipit platea libero vitae taciti eu nec. Donec lobortis metus nisi; est enim himenaeos molestie tellus sapien. Sapien tellus rhoncus blandit fusce hendrerit feugiat. Maximus sit hendrerit tincidunt nec imperdiet hendrerit semper suscipit. Quam augue proin netus rutrum et sem. Neque penatibus cubilia nec metus porta. Ornare pulvinar quam auctor, elit curae ad donec dis. Egestas aptent non tortor potenti morbi mauris.
2212
+
2213
+ Montes dui in pharetra primis consequat ante integer. Vulputate libero gravida rutrum tortor suscipit massa! Netus rhoncus platea torquent dapibus consectetur suspendisse etiam sociosqu. Quis placerat mauris et quam nascetur. Dictumst mi rutrum justo vitae ultricies feugiat nulla faucibus morbi. Consectetur nec condimentum euismod sodales nisi purus; finibus elementum facilisi.
2214
+
2215
+ Senectus mus faucibus ut morbi eu maximus. Turpis tincidunt sodales sociosqu lorem amet pulvinar laoreet faucibus. Mus bibendum vulputate hendrerit sollicitudin eu ridiculus posuere augue leo? Cubilia nostra consequat; fusce egestas himenaeos class ornare nec. Est montes tortor vivamus congue inceptos erat mi eget pellentesque. Amet vulputate fringilla aliquet fames tristique. Rutrum malesuada dapibus vehicula risus nunc torquent habitant turpis habitant. Ipsum proin viverra adipiscing cras et augue hendrerit. Efficitur euismod aliquam habitant; sit nisl potenti.
2216
+
2217
+ Conubia dignissim metus phasellus tristique augue, nullam quam finibus. Dignissim vel enim mattis praesent penatibus. Sapien pharetra curae torquent turpis fermentum feugiat facilisis nisi. Lacinia justo ante mauris finibus vitae ante efficitur dis. Urna gravida conubia amet rhoncus felis ut lorem placerat. Quisque fermentum suscipit aenean nisi suscipit ac? Quis ornare faucibus amet conubia justo maximus hendrerit phasellus aenean. Ex vivamus vulputate in mollis mauris praesent vehicula erat neque.
2218
+
2219
+ Orci nullam commodo habitant volutpat per tincidunt mus sit. Nisi cubilia fringilla viverra at orci magnis massa nam orci. Duis iaculis sapien nulla nascetur elit porta fermentum. Amus libero vivamus vel finibus magnis placerat himenaeos. Integer posuere suscipit non vulputate enim. Conubia id lobortis habitasse luctus odio maecenas enim conubia non. Mus egestas massa platea nullam sociosqu, magnis cras. Quam placerat nisi dui gravida ultricies, facilisis eu pharetra vivamus.
2220
+
2221
+ Fusce maecenas dis finibus senectus nascetur tortor. Nec rhoncus pretium vivamus donec vel ligula curabitur. Velit dis laoreet aenean, fusce metus blandit erat. Ligula purus natoque, arcu finibus tincidunt efficitur dolor curabitur. Ac risus et ipsum; consequat integer phasellus diam. Praesent ipsum gravida placerat porta volutpat tincidunt maximus sapien. Phasellus gravida orci enim velit condimentum.
2222
+
2223
+ Dui id laoreet penatibus orci sit a. Iaculis dis porttitor luctus; lacus dignissim quam commodo lorem. Nullam dictum quisque accumsan porttitor tortor fusce aenean. Aliquet quisque ultricies malesuada auctor facilisi tristique. Dolor nulla conubia ultricies odio ad. Nunc consectetur venenatis consequat nisi habitant. Praesent accumsan scelerisque morbi aliquam sociosqu auctor, nostra aenean.
2224
+
2225
+ Mauris amet conubia egestas eu posuere nullam. Est neque dictum in, lacus aliquam ultrices vestibulum. Dapibus dis habitasse cras conubia felis nibh. Egestas nisl iaculis nostra neque enim, ridiculus praesent. Consectetur eleifend eu mus; elit sed pellentesque fringilla. Ullamcorper hendrerit nibh aptent per congue libero ultrices eget. Mollis velit ad tortor lobortis ipsum.
2226
+
2227
+ Tristique neque justo potenti himenaeos; pellentesque nam vehicula. Maximus etiam ut nullam semper; fames curabitur quam ad morbi. Interdum curabitur platea augue porttitor a gravida. Leo imperdiet id aenean sit; habitasse quam tempus pellentesque? Nostra leo aenean amet lectus ultricies ridiculus nascetur ullamcorper. Taciti in iaculis quam nascetur proin varius eget vehicula.
2228
+
2229
+ Mattis hendrerit tempus interdum diam elementum primis augue phasellus sociosqu. Imperdiet pulvinar imperdiet lacinia posuere class magnis. Montes viverra scelerisque laoreet sociosqu proin lacus. Nam id justo praesent curabitur nam accumsan imperdiet commodo. Sociosqu netus sapien proin interdum ac. Dapibus tempor et sodales, natoque consequat torquent.
2230
+
2231
+ Lectus ultricies amet bibendum blandit finibus erat pellentesque. Nam quis ultrices curae; lorem gravida malesuada velit taciti enim. Facilisis fermentum suspendisse leo tristique litora dapibus rhoncus convallis. Netus iaculis eleifend viverra urna, vulputate ac convallis. Faucibus torquent dictum, nisl sed parturient libero. Ornare class habitant per consequat adipiscing rhoncus feugiat.
2232
+
2233
+ Proin molestie nullam eros parturient parturient curabitur aliquet. Rhoncus mus aenean sem aliquet sem finibus neque rutrum commodo. Efficitur litora lobortis nascetur adipiscing curae faucibus? Bibendum leo velit augue; potenti primis malesuada lacus ipsum. Facilisi potenti facilisis nam tempor consequat. Magnis suspendisse primis duis quam; suscipit quis fermentum phasellus. Massa ridiculus habitasse ipsum arcu sit maecenas gravida nisi? Dolor egestas lacinia lacinia libero nam curae suspendisse purus. Tristique inceptos curae netus scelerisque magna hendrerit commodo quis parturient. Eget accumsan erat sociosqu vestibulum platea turpis habitasse.
2234
+
2235
+ Maximus dignissim sed conubia a ipsum nullam condimentum dictumst. Suspendisse congue phasellus congue lacus sollicitudin senectus curae. Consequat sagittis in fringilla suscipit scelerisque suscipit. Rhoncus pharetra sodales malesuada sollicitudin lectus. Est primis pretium finibus felis pharetra nulla sapien lacinia. Nunc lorem aptent tristique quisque etiam posuere non ullamcorper. Potenti mus sed mus; non id eleifend pellentesque magnis.
2236
+
2237
+ Iaculis morbi mattis; ornare tincidunt neque mus egestas consectetur ultrices. Porta dapibus pretium, vulputate dis amet neque. Posuere auctor lacinia maecenas ridiculus ullamcorper tempus egestas cubilia nec. Cursus nulla lacinia mi facilisi, nisl tempor. Tempus elementum laoreet magnis neque morbi felis per. Suspendisse lectus vitae nunc amet himenaeos euismod aliquam. Quisque integer dictum aenean fermentum dictumst torquent.
2238
+
2239
+ Sociosqu per suspendisse augue phasellus velit dapibus parturient. At sit eu finibus posuere tincidunt. Phasellus duis scelerisque scelerisque taciti est venenatis. Arcu habitant augue amet eget maximus torquent. Eget gravida ut quisque ligula vel mus. Erat quis himenaeos; velit eget varius viverra interdum. Neque dapibus malesuada est a gravida libero integer aptent. Semper eleifend per at magnis, laoreet nibh orci vel ligula.
2240
+
2241
+ Odio purus finibus inceptos malesuada duis. Neque magnis est laoreet nibh gravida sagittis ullamcorper sodales. Parturient ultricies mattis lacus risus laoreet praesent. Tincidunt eleifend quis sagittis id nascetur. Nam scelerisque varius feugiat phasellus enim mauris nam. Tortor iaculis et cras; blandit sollicitudin pellentesque justo. Nam lacinia volutpat fusce nibh mollis; himenaeos iaculis. Vulputate dictum mattis sollicitudin accumsan at hendrerit.
2242
+
2243
+ Ipsum augue faucibus senectus porta dapibus metus. Netus sem amet nullam fermentum in dolor bibendum. Lacus quis enim vivamus enim risus elit suspendisse arcu. Penatibus proin pellentesque consequat nibh turpis fusce. Potenti sociosqu nunc tempor amet torquent. Aliquet porttitor adipiscing parturient curabitur hac? Condimentum morbi netus erat class hendrerit aptent. Placerat viverra molestie at eget donec quisque. Varius sem erat dolor, urna nunc ac duis inceptos maximus.
2244
+
2245
+ Nostra adipiscing dapibus eros vivamus accumsan elementum curae dignissim dignissim. Iaculis quisque fusce at conubia est habitant ipsum. Porttitor libero lobortis lobortis habitasse quis quisque nunc euismod aenean. Bibendum nullam volutpat quam vitae felis sit. Mauris bibendum nulla litora nec id, elit lacinia. Orci odio nunc est ante commodo dis quis diam convallis? Mattis a per cras amet egestas ex pellentesque nascetur augue. Egestas per massa per non metus hendrerit feugiat eu?
2246
+
2247
+ Praesent habitasse est elementum mattis potenti. Fermentum interdum enim orci dui faucibus sodales nisi mus. Tortor facilisi nunc potenti; dignissim magna varius! Risus cursus ornare tincidunt a feugiat massa cubilia. Sociosqu quis pharetra efficitur lorem ornare sapien arcu euismod. Elementum donec maecenas praesent scelerisque viverra mi natoque. Lacinia nibh eu commodo ut class blandit magnis.
2248
+
2249
+ Ullamcorper himenaeos mollis nostra placerat quam pellentesque nibh. Curae posuere cras dis senectus fringilla congue ipsum sit. Eros maecenas duis morbi consequat himenaeos ridiculus purus erat. Nascetur maximus massa eros class phasellus integer sed gravida. Vel donec lacinia donec curabitur penatibus integer ornare. Varius quam lectus magna per a mauris.
2250
+
2251
+ Imperdiet tempus malesuada ultrices egestas taciti nibh elit lacus. Nunc tempus tellus vitae duis rhoncus leo facilisis. Sapien nec mi lacus mi aliquet. Diam convallis fringilla libero duis integer integer dictum vel. Dolor montes nibh sapien dapibus ultrices praesent. Aeuismod phasellus taciti elit vehicula sit sociosqu. Lobortis neque urna dignissim penatibus felis vulputate. Primis magnis placerat, ligula massa facilisis nec.
2252
+
2253
+ Duis interdum himenaeos dis nisl et tortor condimentum accumsan. Laoreet amet fusce dis malesuada iaculis maximus fringilla. Conubia mus nibh felis vestibulum ad convallis mollis. Metus vivamus lobortis habitasse id nam. Egestas pretium eu penatibus consectetur malesuada congue tempus fusce. Rutrum neque pulvinar duis ligula fermentum malesuada. Tincidunt mollis molestie imperdiet ridiculus pharetra maximus sodales curabitur.
2254
+
2255
+ Sem nec integer fusce neque sagittis. Rutrum ipsum ante; urna enim primis consectetur nulla. Arcu ligula lectus varius magna ipsum, et dictum. Pharetra dignissim inceptos tristique natoque tempor volutpat. Luctus tristique himenaeos duis orci maecenas vel morbi. Habitasse a lacinia dignissim commodo elementum maecenas eu mollis. Fermentum tellus sem condimentum mattis elit lectus. Platea fusce arcu cras varius natoque? Volutpat tincidunt ridiculus mus massa ante dis sem ornare magna. Bibendum ornare ultrices proin efficitur; nascetur risus arcu.
2256
+
2257
+ Orci erat orci amet mollis venenatis. Feugiat torquent ex mattis, inceptos etiam integer. Class senectus aptent vivamus, semper dolor nisi at pretium volutpat. Natoque semper enim enim primis ultricies, pharetra pulvinar. Natoque litora tortor accumsan ridiculus lacinia integer; aliquet penatibus ridiculus. Placerat vestibulum justo tristique sapien senectus, et interdum et ridiculus. Urna aenean vel himenaeos; finibus a est efficitur donec. Dictum egestas quis fusce arcu; sapien himenaeos pretium congue. Semper et sapien nisi nascetur venenatis eros integer blandit.
2258
+
2259
+ Arcu per phasellus vehicula ad molestie? Eget arcu eget inceptos, eu ullamcorper diam. Gravida placerat elit ut hendrerit odio. Est lobortis imperdiet venenatis primis a. Facilisis integer maecenas adipiscing metus, rutrum curabitur. Dolor adipiscing himenaeos senectus tempus faucibus cras.
2260
+
2261
+ Massa torquent torquent ullamcorper erat nisl parturient primis eu pulvinar! Ridiculus sollicitudin dis eu, laoreet praesent hendrerit platea euismod. Lacinia dignissim suspendisse sagittis eu rutrum himenaeos curae massa diam. Platea ornare ridiculus consequat curabitur augue vestibulum ridiculus. Vel consectetur vivamus accumsan risus elementum? Imperdiet nascetur efficitur aliquam habitasse nascetur. Hendrerit quisque magnis in lacinia quis mauris.
2262
+
2263
+ Molestie fermentum blandit, viverra condimentum purus himenaeos. Fermentum congue a suspendisse ornare semper laoreet. Pharetra lacus non, iaculis ad taciti varius. Etiam nam risus vestibulum curabitur facilisis mattis, lorem hac id. Dignissim nibh tempor quam porta lectus nunc tincidunt aliquet. Tortor maximus maximus natoque nam magna torquent nec lectus mus. Vel fermentum semper vulputate penatibus vel purus.
2264
+
2265
+ Fermentum tincidunt penatibus platea himenaeos etiam sodales ad erat posuere. Vehicula vulputate sem blandit nullam sem. Condimentum eget lacus ad malesuada augue dui justo. Lobortis quis mauris pellentesque quam interdum sagittis. Nulla ullamcorper aptent hendrerit fusce hendrerit, cras cras magna. Ex quam torquent, congue dis est vulputate lacinia. Dignissim proin lacinia platea tortor elementum nullam. Purus natoque scelerisque habitant vestibulum; metus dui neque ipsum. Pellentesque augue montes fringilla et, maecenas habitant a.
2266
+
2267
+ Quam sapien eu scelerisque tristique, integer in rutrum gravida. Egestas lacinia nisi praesent turpis lacus maximus mus gravida. Dolor eget ultrices rhoncus velit; mollis id. Mi vulputate sed blandit nullam parturient venenatis. Neque vulputate iaculis nascetur felis fames ipsum adipiscing nullam? Vitae faucibus elit congue himenaeos orci volutpat nam. Magna tempus convallis vivamus eu semper. Egestas curabitur integer quis habitasse id taciti hac sociosqu morbi. Duis felis cursus potenti blandit cras dolor pharetra.
2268
+
2269
+ Ultricies vel primis nec mus malesuada congue? Habitasse semper mus ultricies; fermentum himenaeos placerat sodales. Platea sapien malesuada dignissim suscipit dis cras. Etiam odio pharetra metus donec odio natoque. Cras diam curae dapibus accumsan tortor mi laoreet. Ex mollis massa inceptos inceptos adipiscing. Cras rhoncus natoque accumsan augue enim. Parturient porttitor habitant semper platea elementum dictum ornare? Sociosqu blandit nullam vivamus elementum semper himenaeos.
2270
+
2271
+ Orci elit aliquam luctus habitant interdum. Tellus sollicitudin aliquam donec potenti praesent augue magnis auctor. Mattis faucibus iaculis etiam imperdiet lectus ad habitasse sollicitudin ac. Consequat maecenas quam dis adipiscing neque sociosqu. Ullamcorper in praesent himenaeos purus blandit nibh. Dignissim platea amet urna laoreet sociosqu lacinia accumsan consectetur risus. Adipiscing nullam arcu lobortis mi scelerisque feugiat non. Accumsan lacinia urna sit urna tincidunt nam pulvinar urna. Tellus cursus ac himenaeos sed aptent phasellus.
2272
+
2273
+ Scelerisque curabitur eget morbi leo phasellus morbi magnis. Elit nunc non vulputate eget at. Viverra efficitur dignissim fames ut condimentum tincidunt elementum lacus egestas. Dictum phasellus leo auctor dui diam. Sollicitudin placerat elit vehicula vulputate et at eleifend ullamcorper. Primis diam hac class leo justo etiam magnis. Justo maximus venenatis facilisis egestas hendrerit aptent arcu tortor consectetur. Consequat mus curabitur nisl; blandit enim at bibendum tempor bibendum. Ad nam arcu vehicula himenaeos sociosqu eu faucibus accumsan.
2274
+
2275
+ Maximus malesuada faucibus phasellus donec ligula. Rutrum pellentesque ultricies nullam; aenean scelerisque elementum. Porta luctus consectetur pharetra consequat varius. Ut dapibus senectus venenatis scelerisque fames ligula congue. Magna hendrerit faucibus ultricies tincidunt phasellus pellentesque, maecenas consequat! Malesuada senectus praesent sed condimentum aenean mi. Interdum sollicitudin mattis, purus vitae netus gravida. Nullam magna risus leo sit urna aenean.
2276
+
2277
+ Ut lacinia potenti vel varius habitant mus nullam adipiscing. Commodo potenti conubia hendrerit enim massa ad blandit. Nisl a massa nunc risus, condimentum enim. Hac aenean massa lacinia lobortis ad dolor sem. Nisl ex interdum blandit pulvinar pellentesque lorem. Sapien proin malesuada netus parturient pulvinar nec. Ex semper amet sem maximus blandit cras felis. Donec tellus auctor eleifend placerat natoque. Rutrum maecenas sollicitudin nisl consectetur in nulla rhoncus. Id rhoncus nec mi non lacinia leo efficitur nisi.
2278
+
2279
+ Dolor non phasellus id nascetur id nisi litora cubilia interdum. Lectus dolor sodales eu nulla porttitor placerat vulputate. Praesent ullamcorper consequat nulla torquent facilisis nunc. Rhoncus augue eleifend mauris erat duis varius felis. Dignissim nunc pulvinar vehicula dignissim maximus elit metus senectus. Venenatis conubia pulvinar commodo dui montes cubilia.
2280
+
2281
+ Cursus velit lacus aenean elit conubia. Velit in inceptos enim, elit lobortis est facilisis. Suscipit cursus dictum enim libero neque dolor himenaeos eu. Porta in integer praesent quisque quis sit. Primis velit tempus sit curae vehicula porttitor. Scelerisque nisi diam vehicula mi fusce dictum. Tincidunt mus eleifend commodo ridiculus adipiscing.
2282
+
2283
+ Pellentesque quis dignissim euismod in fermentum quam lobortis porta. Dis euismod ultricies montes odio sapien condimentum integer per. Torquent nascetur ante ante; diam ultrices nec habitant. Augue congue a conubia commodo ultricies tortor. Quis ridiculus netus vivamus dictumst efficitur parturient hendrerit. Facilisis ultrices suspendisse elit sodales eleifend maecenas tempor. Habitasse platea congue ac, pretium augue odio interdum netus. Mattis odio mi leo integer nisi diam phasellus elementum. Tortor himenaeos curabitur enim sit ac mi dictumst faucibus sociosqu.
2284
+
2285
+ Duis ex viverra auctor praesent elit ac. Sit ex at cubilia aenean scelerisque finibus ridiculus. Hendrerit imperdiet potenti erat risus commodo. Sit donec ullamcorper facilisi neque varius, suscipit malesuada hac. Nulla lacinia pulvinar non volutpat pellentesque lobortis ultrices dis. Faucibus luctus fusce, aliquam magnis pharetra sed dui nulla viverra. Lectus hendrerit eu pellentesque nostra mauris suspendisse himenaeos. Lectus bibendum inceptos commodo nulla magnis proin.`;