@nymphjs/nymph 1.0.0-beta.13 → 1.0.0-beta.130

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 (123) hide show
  1. package/CHANGELOG.md +644 -0
  2. package/README.md +34 -24
  3. package/dist/Entity.d.ts +304 -15
  4. package/dist/Entity.js +609 -154
  5. package/dist/Entity.js.map +1 -1
  6. package/dist/Entity.test.js +75 -29
  7. package/dist/Entity.test.js.map +1 -1
  8. package/dist/Entity.types.d.ts +275 -28
  9. package/dist/Entity.types.js +1 -2
  10. package/dist/Nymph.d.ts +575 -11
  11. package/dist/Nymph.js +825 -288
  12. package/dist/Nymph.js.map +1 -1
  13. package/dist/Nymph.types.d.ts +117 -7
  14. package/dist/Nymph.types.js +47 -5
  15. package/dist/Nymph.types.js.map +1 -1
  16. package/dist/conf/defaults.d.ts +1 -1
  17. package/dist/conf/defaults.js +26 -3
  18. package/dist/conf/defaults.js.map +1 -1
  19. package/dist/conf/index.d.ts +50 -2
  20. package/dist/conf/index.js +2 -8
  21. package/dist/conf/index.js.map +1 -1
  22. package/dist/decorators/index.d.ts +1 -0
  23. package/dist/decorators/index.js +2 -0
  24. package/dist/decorators/index.js.map +1 -0
  25. package/dist/decorators/transactional.d.ts +12 -0
  26. package/dist/decorators/transactional.js +45 -0
  27. package/dist/decorators/transactional.js.map +1 -0
  28. package/dist/driver/NymphDriver.d.ts +209 -41
  29. package/dist/driver/NymphDriver.js +737 -242
  30. package/dist/driver/NymphDriver.js.map +1 -1
  31. package/dist/driver/index.d.ts +1 -2
  32. package/dist/driver/index.js +2 -23
  33. package/dist/driver/index.js.map +1 -1
  34. package/dist/driver/testArtifacts.d.ts +4 -4
  35. package/dist/driver/testArtifacts.js +2016 -1086
  36. package/dist/driver/testArtifacts.js.map +1 -1
  37. package/dist/errors/ClassNotAvailableError.js +1 -5
  38. package/dist/errors/ClassNotAvailableError.js.map +1 -1
  39. package/dist/errors/EntityConflictError.js +1 -5
  40. package/dist/errors/EntityConflictError.js.map +1 -1
  41. package/dist/errors/EntityInvalidDataError.d.ts +6 -0
  42. package/dist/errors/EntityInvalidDataError.js +8 -6
  43. package/dist/errors/EntityInvalidDataError.js.map +1 -1
  44. package/dist/errors/EntityIsSleepingReferenceError.js +1 -5
  45. package/dist/errors/EntityIsSleepingReferenceError.js.map +1 -1
  46. package/dist/errors/EntityUniqueConstraintError.d.ts +3 -0
  47. package/dist/errors/EntityUniqueConstraintError.js +7 -0
  48. package/dist/errors/EntityUniqueConstraintError.js.map +1 -0
  49. package/dist/errors/HttpError.d.ts +5 -0
  50. package/dist/errors/HttpError.js +11 -0
  51. package/dist/errors/HttpError.js.map +1 -0
  52. package/dist/errors/InvalidParametersError.js +1 -5
  53. package/dist/errors/InvalidParametersError.js.map +1 -1
  54. package/dist/errors/InvalidStateError.d.ts +3 -0
  55. package/dist/errors/InvalidStateError.js +7 -0
  56. package/dist/errors/InvalidStateError.js.map +1 -0
  57. package/dist/errors/MethodFailedError.d.ts +3 -0
  58. package/dist/errors/MethodFailedError.js +7 -0
  59. package/dist/errors/MethodFailedError.js.map +1 -0
  60. package/dist/errors/NotConfiguredError.js +1 -5
  61. package/dist/errors/NotConfiguredError.js.map +1 -1
  62. package/dist/errors/QueryFailedError.d.ts +2 -1
  63. package/dist/errors/QueryFailedError.js +5 -6
  64. package/dist/errors/QueryFailedError.js.map +1 -1
  65. package/dist/errors/UnableToConnectError.js +1 -5
  66. package/dist/errors/UnableToConnectError.js.map +1 -1
  67. package/dist/errors/index.d.ts +12 -8
  68. package/dist/errors/index.js +12 -24
  69. package/dist/errors/index.js.map +1 -1
  70. package/dist/helpers/index.d.ts +1 -0
  71. package/dist/helpers/index.js +2 -0
  72. package/dist/helpers/index.js.map +1 -0
  73. package/dist/helpers/transaction.d.ts +15 -0
  74. package/dist/helpers/transaction.js +47 -0
  75. package/dist/helpers/transaction.js.map +1 -0
  76. package/dist/index.d.ts +13 -11
  77. package/dist/index.js +16 -34
  78. package/dist/index.js.map +1 -1
  79. package/dist/nymphJoiProps.d.ts +1 -1
  80. package/dist/nymphJoiProps.js +10 -15
  81. package/dist/nymphJoiProps.js.map +1 -1
  82. package/dist/testArtifacts.d.ts +21 -6
  83. package/dist/testArtifacts.js +124 -50
  84. package/dist/testArtifacts.js.map +1 -1
  85. package/dist/testMocks.d.ts +27 -12
  86. package/dist/testMocks.js +44 -33
  87. package/dist/testMocks.js.map +1 -1
  88. package/dist/utils.d.ts +5 -5
  89. package/dist/utils.js +106 -68
  90. package/dist/utils.js.map +1 -1
  91. package/jest.config.js +31 -5
  92. package/package.json +43 -24
  93. package/src/Entity.test.ts +73 -23
  94. package/src/Entity.ts +555 -169
  95. package/src/Entity.types.ts +102 -90
  96. package/src/Nymph.ts +930 -517
  97. package/src/Nymph.types.ts +145 -39
  98. package/src/conf/defaults.ts +34 -1
  99. package/src/conf/index.ts +50 -2
  100. package/src/decorators/index.ts +1 -0
  101. package/src/decorators/transactional.ts +63 -0
  102. package/src/driver/NymphDriver.ts +987 -417
  103. package/src/driver/index.ts +1 -3
  104. package/src/driver/testArtifacts.ts +2699 -1628
  105. package/src/errors/EntityUniqueConstraintError.ts +6 -0
  106. package/src/errors/HttpError.ts +12 -0
  107. package/src/errors/InvalidStateError.ts +6 -0
  108. package/src/errors/MethodFailedError.ts +6 -0
  109. package/src/errors/QueryFailedError.ts +3 -1
  110. package/src/errors/index.ts +16 -8
  111. package/src/helpers/index.ts +1 -0
  112. package/src/helpers/transaction.ts +65 -0
  113. package/src/index.ts +13 -11
  114. package/src/nymphJoiProps.ts +2 -2
  115. package/src/testArtifacts.ts +69 -20
  116. package/src/testMocks.ts +107 -41
  117. package/src/utils.ts +102 -67
  118. package/tsconfig.json +6 -3
  119. package/typedoc.json +4 -0
  120. package/dist/conf/d.d.ts +0 -6
  121. package/dist/conf/d.js +0 -3
  122. package/dist/conf/d.js.map +0 -1
  123. package/src/conf/d.ts +0 -24
@@ -1,1662 +1,2331 @@
1
- import fs from 'fs';
2
- import strtotime from 'locutus/php/datetime/strtotime';
1
+ import { dirname } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import fs from 'node:fs';
4
+ import { strtotime } from 'locutus/php/datetime/index';
3
5
  import { guid } from '@nymphjs/guid';
4
6
 
5
- import type Nymph from '../Nymph';
7
+ import type Nymph from '../Nymph.js';
8
+ import {
9
+ EntityUniqueConstraintError,
10
+ EntityInvalidDataError,
11
+ } from '../errors/index.js';
6
12
  import {
7
13
  TestBModel as TestBModelClass,
8
14
  TestModel as TestModelClass,
9
15
  TestModelData,
10
- } from '../testArtifacts';
16
+ TestEmptyModel as TestEmptyModelClass,
17
+ } from '../testArtifacts.js';
18
+ import {
19
+ entitiesToReferences,
20
+ entityConstructorsToClassNames,
21
+ } from '../utils.js';
11
22
 
12
- export function QueriesTest(
23
+ const __dirname = dirname(fileURLToPath(import.meta.url));
24
+
25
+ export function EntitiesTest(
13
26
  nymph: Nymph,
14
- it: (name: string, fn: () => void) => void
27
+ describe: (name: string, fn: () => void) => void,
28
+ it: (name: string, fn: () => void) => void,
15
29
  ) {
16
- const TestModel = nymph.addEntityClass(TestModelClass);
17
- const TestBModel = nymph.addEntityClass(TestBModelClass);
18
-
19
- let testEntity: TestModelClass & TestModelData;
20
- let testGuid: string;
21
- let refGuid: string;
22
- let createdMultiple = false;
23
-
24
- // The entities created by this function are required by many of the tests.
25
- async function createTestEntities() {
26
- if (testGuid != null) {
27
- return;
28
- }
30
+ describe('Entity', () => {
31
+ const TestModel = nymph.addEntityClass(TestModelClass);
32
+ const TestBModel = nymph.addEntityClass(TestBModelClass);
33
+ const TestEmptyModel = nymph.addEntityClass(TestEmptyModelClass);
34
+
35
+ let testEntity: TestModelClass & TestModelData;
36
+ let testGuid: string;
37
+ let refGuid: string;
38
+ let createdMultiple = false;
39
+
40
+ // The entities created by this function are required by many of the tests.
41
+ async function createTestEntities() {
42
+ if (testGuid != null) {
43
+ return;
44
+ }
29
45
 
30
- // Creating entity...
31
- testEntity = await TestModel.factory();
46
+ // Creating entity...
47
+ testEntity = await TestModel.factory();
32
48
 
33
- // Saving entity...
34
- testEntity.name = 'Entity Test ' + new Date().toLocaleString();
35
- testEntity.null = null;
36
- 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.
49
+ // Saving entity...
50
+ testEntity.name = 'Entity Test ' + new Date().toLocaleString();
51
+ testEntity.null = null;
52
+ testEntity.string = 'test';
53
+ testEntity.array = [
54
+ 'full',
55
+ 'of',
56
+ 'values',
57
+ 500,
58
+ { test: true },
59
+ { nullbyte: '\\\x00\u0000 \x00' },
60
+ ];
61
+ testEntity.match = matchValue;
62
+ testEntity.search = searchValue;
63
+ testEntity.number = 30;
64
+ testEntity.numberString = '30';
65
+ testEntity.timestamp = Date.now();
66
+ await testEntity.$save();
67
+ expect(testEntity.guid).not.toBeNull();
68
+ testGuid = testEntity.guid as string;
69
+
70
+ const entityReferenceTest: TestModelClass & TestModelData =
71
+ new TestModel();
72
+ entityReferenceTest.string = 'ref string';
73
+ entityReferenceTest.timestamp = (strtotime('-2 days') || 0) * 1000;
74
+ await entityReferenceTest.$save();
75
+ refGuid = entityReferenceTest.guid as string;
76
+ testEntity.reference = entityReferenceTest;
77
+ testEntity.refArray = [entityReferenceTest];
78
+ await testEntity.$save();
79
+
80
+ entityReferenceTest.test = 'good';
81
+ await entityReferenceTest.$save();
82
+
83
+ // Test asynchronous getEntity.
84
+ testEntity = (await nymph.getEntity(
85
+ { class: TestModel },
86
+ testGuid,
87
+ )) as TestModelClass & TestModelData;
88
+ expect(testEntity).toBeInstanceOf(TestModel);
89
+ expect(testEntity.guid).toEqual(testGuid);
90
+ }
39
91
 
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.`;
43
- testEntity.number = 30;
44
- testEntity.numberString = '30';
45
- testEntity.timestamp = Date.now();
46
- expect(await testEntity.$save()).toEqual(true);
47
- expect(testEntity.guid).not.toBeNull();
48
- testGuid = testEntity.guid as string;
49
-
50
- const entityReferenceTest: TestModelClass & TestModelData = new TestModel();
51
- entityReferenceTest.string = 'wrong';
52
- entityReferenceTest.timestamp = strtotime('-2 days') * 1000;
53
- expect(await entityReferenceTest.$save()).toEqual(true);
54
- refGuid = entityReferenceTest.guid as string;
55
- testEntity.reference = entityReferenceTest;
56
- testEntity.refArray = [entityReferenceTest];
57
- expect(await testEntity.$save()).toEqual(true);
58
-
59
- entityReferenceTest.test = 'good';
60
- expect(await entityReferenceTest.$save()).toEqual(true);
61
-
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
- // Test asynchronous getEntity.
71
- testEntity = (await nymph.getEntity(
72
- { class: TestModel },
73
- testGuid
74
- )) as TestModelClass & TestModelData;
75
- expect(testEntity).toBeInstanceOf(TestModel);
76
- expect(testEntity.guid).toEqual(testGuid);
77
- }
78
-
79
- // The entities created by this function are required by many of the tests.
80
- async function createMultipleTestEntities() {
81
- if (!createdMultiple) {
82
- createdMultiple = true;
83
- // Creating 100 entities...
84
- for (let i = 0; i < 100; i++) {
85
- const testEntity = await TestModel.factory();
86
- testEntity.name = `Multi Test ${i}`;
87
- testEntity.$removeTag('test');
88
- testEntity.$addTag('multiTest');
89
- expect(await testEntity.$save()).toEqual(true);
90
- // Pause for a few milliseconds so the cdate and mdate can be sorted.
91
- await new Promise((res) => setTimeout(() => res(1), 5));
92
+ // The entities created by this function are required by many of the tests.
93
+ async function createMultipleTestEntities() {
94
+ if (!createdMultiple) {
95
+ createdMultiple = true;
96
+ // Creating 100 entities...
97
+ for (let i = 0; i < 100; i++) {
98
+ const testEntity = await TestModel.factory();
99
+ testEntity.name = `Multi Test ${i}`;
100
+ // Reverse the number for sort testing.
101
+ testEntity.number = 100 - i;
102
+ testEntity.$removeTag('test');
103
+ testEntity.$addTag('multiTest');
104
+ await testEntity.$save();
105
+ // Pause for a few milliseconds so the cdate and mdate can be sorted.
106
+ await new Promise((res) => setTimeout(() => res(1), 5));
107
+ }
92
108
  }
93
109
  }
94
- }
95
110
 
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) {
100
- expect(await cur.$delete()).toEqual(true);
101
- }
111
+ it('delete old test data', async () => {
112
+ let amodels = await nymph.getEntities({ class: TestModel });
113
+ expect(Array.isArray(amodels)).toEqual(true);
114
+ for (const cur of amodels) {
115
+ await cur.$delete();
116
+ }
102
117
 
103
- all = await nymph.getEntities({ class: TestModel });
104
- expect(all.length).toEqual(0);
105
- });
118
+ amodels = await nymph.getEntities({ class: TestModel });
119
+ expect(amodels.length).toEqual(0);
106
120
 
107
- it('create entity', async () => {
108
- await createTestEntities();
109
- });
121
+ let bmodels = await nymph.getEntities({ class: TestBModel });
122
+ expect(Array.isArray(bmodels)).toEqual(true);
123
+ for (const cur of bmodels) {
124
+ await cur.$delete();
125
+ }
110
126
 
111
- it('update mdate on save', async () => {
112
- await createTestEntities();
127
+ bmodels = await nymph.getEntities({ class: TestBModel });
128
+ expect(bmodels.length).toEqual(0);
129
+ });
113
130
 
114
- const oldMdate = testEntity.mdate ?? Infinity;
131
+ it('create entity', async () => {
132
+ await createTestEntities();
133
+ });
115
134
 
116
- await new Promise((resolve) => setTimeout(() => resolve(true), 100));
117
- await testEntity.$save();
135
+ it("doesn't create empty entity", async () => {
136
+ const testEntity = await TestEmptyModel.factory();
118
137
 
119
- expect(testEntity.mdate).toBeGreaterThan(oldMdate);
120
- });
138
+ try {
139
+ await testEntity.$save();
121
140
 
122
- it('create multiple entities', async () => {
123
- return createMultipleTestEntities();
124
- });
141
+ throw new Error('Should have thrown.');
142
+ } catch (e: any) {
143
+ expect(e).toBeInstanceOf(EntityInvalidDataError);
144
+ }
145
+ expect(testEntity.guid).toBeNull();
146
+ });
125
147
 
126
- it('by guid', async () => {
127
- await createTestEntities();
148
+ it('update mdate on save', async () => {
149
+ await createTestEntities();
128
150
 
129
- // Retrieving entity by GUID...
130
- let resultEntity = await nymph.getEntity({ class: TestModel }, testGuid);
131
- expect(testEntity.$is(resultEntity)).toEqual(true);
151
+ const oldMdate = testEntity.mdate ?? Infinity;
132
152
 
133
- // Using class constructor...
134
- resultEntity = await TestModel.factory(testGuid);
135
- expect(testEntity.$is(resultEntity)).toEqual(true);
153
+ await new Promise((resolve) => setTimeout(() => resolve(true), 100));
154
+ await testEntity.$save();
136
155
 
137
- // Testing wrong GUID...
138
- resultEntity = await nymph.getEntity({ class: TestModel }, guid());
139
- expect(testEntity.$is(resultEntity)).toEqual(false);
140
- });
156
+ expect(testEntity.mdate).toBeGreaterThan(oldMdate);
157
+ });
141
158
 
142
- it('transactions', async () => {
143
- await createTestEntities();
159
+ it('create multiple entities', async () => {
160
+ return createMultipleTestEntities();
161
+ });
144
162
 
145
- // Verify not in a transaction.
146
- expect(await nymph.inTransaction()).toEqual(false);
163
+ it('by guid', async () => {
164
+ await createTestEntities();
147
165
 
148
- let transaction = await nymph.startTransaction('test');
149
- testEntity.$nymph = transaction;
166
+ // Retrieving entity by GUID...
167
+ let resultEntity = await nymph.getEntity({ class: TestModel }, testGuid);
168
+ expect(testEntity.$is(resultEntity)).toEqual(true);
150
169
 
151
- if (!(await transaction.inTransaction())) {
152
- console.log(
153
- 'This Nymph driver or database seems to not support transactions. Skipping transaction tests.'
154
- );
155
- await transaction.rollback('test');
156
- return;
157
- }
170
+ // Using class constructor...
171
+ resultEntity = await TestModel.factory(testGuid);
172
+ expect(testEntity.$is(resultEntity)).toEqual(true);
158
173
 
159
- // Change a value in the test entity.
160
- testEntity.string = 'bad value';
161
- expect(await testEntity.$save()).toEqual(true);
174
+ // Testing wrong GUID...
175
+ resultEntity = await nymph.getEntity({ class: TestModel }, guid());
176
+ expect(testEntity.$is(resultEntity)).toEqual(false);
177
+ });
162
178
 
163
- // Rollback the transaction.
164
- await transaction.rollback('test');
179
+ it('guaranteed guid', async () => {
180
+ // Creating entity...
181
+ const testEntity = await TestModel.factory();
165
182
 
166
- // Verify not in a transaction.
167
- expect(await transaction.inTransaction()).toEqual(false);
183
+ // Saving entity...
184
+ testEntity.name = 'Entity Test ' + new Date().toLocaleString();
185
+ testEntity.null = null;
186
+ testEntity.string = 'test';
187
+ testEntity.array = [];
188
+ testEntity.match = matchValue;
189
+ testEntity.number = 30;
190
+ testEntity.numberString = '30';
191
+ testEntity.timestamp = Date.now();
168
192
 
169
- // Verify the value is correct.
170
- await testEntity.$refresh();
171
- expect(testEntity.string).toEqual('test');
193
+ // Get the guaranteed GUID.
194
+ const testGuid = testEntity.$getGuaranteedGUID();
172
195
 
173
- // Start a new transaction.
174
- transaction = await nymph.startTransaction('test');
175
- testEntity.$nymph = transaction;
196
+ await testEntity.$save();
197
+ expect(testEntity.guid).not.toBeNull();
198
+ expect(testEntity.guid).toEqual(testGuid);
176
199
 
177
- // Verify in a transaction.
178
- expect(await transaction.inTransaction()).toEqual(true);
200
+ // Retrieving entity by GUID...
201
+ let resultEntity = await nymph.getEntity({ class: TestModel }, testGuid);
202
+ expect(testEntity.$is(resultEntity)).toEqual(true);
179
203
 
180
- // Delete the entity.
181
- expect(await testEntity.$delete()).toEqual(true);
182
- const resultEntity = await transaction.getEntity(
183
- { class: TestModel },
184
- testGuid
185
- );
186
- expect(resultEntity).toBeNull();
204
+ // Delete the entity.
205
+ await testEntity.$delete();
206
+ });
187
207
 
188
- // Rollback the transaction.
189
- await transaction.rollback('test');
208
+ it('create, list, and delete indexes', async () => {
209
+ // Delete existing indexes.
210
+ const existingIndexes = await nymph.getIndexes(TestModel.ETYPE);
211
+ for (let index of existingIndexes) {
212
+ await nymph.deleteIndex(TestModel.ETYPE, index.scope, index.name);
213
+ }
214
+ const existingBIndexes = await nymph.getIndexes(TestBModel.ETYPE);
215
+ for (let index of existingBIndexes) {
216
+ await nymph.deleteIndex(TestBModel.ETYPE, index.scope, index.name);
217
+ }
190
218
 
191
- // Verify not in a transaction.
192
- expect(await transaction.inTransaction()).toEqual(false);
219
+ const sortByName = (arr: { name: string }[]) => {
220
+ arr.sort((a, b) => a.name.localeCompare(b.name));
221
+ return arr;
222
+ };
223
+
224
+ expect(
225
+ await nymph.addIndex(TestModel.ETYPE, {
226
+ scope: 'data',
227
+ name: 'testindex',
228
+ property: 'test',
229
+ }),
230
+ ).toEqual(true);
231
+
232
+ expect(sortByName(await nymph.getIndexes(TestModel.ETYPE))).toEqual([
233
+ { scope: 'data', name: 'testindex', property: 'test' },
234
+ ]);
235
+
236
+ expect(
237
+ await nymph.addIndex(TestModel.ETYPE, {
238
+ scope: 'data',
239
+ name: 'secondone',
240
+ property: 'match',
241
+ }),
242
+ ).toEqual(true);
243
+
244
+ expect(sortByName(await nymph.getIndexes(TestModel.ETYPE))).toEqual([
245
+ { scope: 'data', name: 'secondone', property: 'match' },
246
+ { scope: 'data', name: 'testindex', property: 'test' },
247
+ ]);
248
+
249
+ expect(
250
+ await nymph.addIndex(TestModel.ETYPE, {
251
+ scope: 'references',
252
+ name: 'refone',
253
+ property: 'reference',
254
+ }),
255
+ ).toEqual(true);
256
+
257
+ expect(sortByName(await nymph.getIndexes(TestModel.ETYPE))).toEqual([
258
+ { scope: 'references', name: 'refone', property: 'reference' },
259
+ { scope: 'data', name: 'secondone', property: 'match' },
260
+ { scope: 'data', name: 'testindex', property: 'test' },
261
+ ]);
262
+
263
+ expect(
264
+ await nymph.addIndex(TestModel.ETYPE, {
265
+ scope: 'tokens',
266
+ name: 'tokenone',
267
+ property: 'search',
268
+ }),
269
+ ).toEqual(true);
270
+
271
+ expect(sortByName(await nymph.getIndexes(TestModel.ETYPE))).toEqual([
272
+ { scope: 'references', name: 'refone', property: 'reference' },
273
+ { scope: 'data', name: 'secondone', property: 'match' },
274
+ { scope: 'data', name: 'testindex', property: 'test' },
275
+ { scope: 'tokens', name: 'tokenone', property: 'search' },
276
+ ]);
277
+
278
+ expect(
279
+ await nymph.addIndex(TestBModel.ETYPE, {
280
+ scope: 'data',
281
+ name: 'flooflab',
282
+ property: 'string',
283
+ }),
284
+ ).toEqual(true);
285
+
286
+ expect(sortByName(await nymph.getIndexes(TestBModel.ETYPE))).toEqual([
287
+ { scope: 'data', name: 'flooflab', property: 'string' },
288
+ ]);
289
+
290
+ expect(sortByName(await nymph.getIndexes(TestModel.ETYPE))).toEqual([
291
+ { scope: 'references', name: 'refone', property: 'reference' },
292
+ { scope: 'data', name: 'secondone', property: 'match' },
293
+ { scope: 'data', name: 'testindex', property: 'test' },
294
+ { scope: 'tokens', name: 'tokenone', property: 'search' },
295
+ ]);
296
+
297
+ expect(
298
+ await nymph.deleteIndex(TestBModel.ETYPE, 'data', 'flooflab'),
299
+ ).toEqual(true);
300
+
301
+ expect(await nymph.getIndexes(TestBModel.ETYPE)).toEqual([]);
302
+
303
+ expect(sortByName(await nymph.getIndexes(TestModel.ETYPE))).toEqual([
304
+ { scope: 'references', name: 'refone', property: 'reference' },
305
+ { scope: 'data', name: 'secondone', property: 'match' },
306
+ { scope: 'data', name: 'testindex', property: 'test' },
307
+ { scope: 'tokens', name: 'tokenone', property: 'search' },
308
+ ]);
309
+
310
+ expect(
311
+ await nymph.deleteIndex(TestModel.ETYPE, 'data', 'testindex'),
312
+ ).toEqual(true);
313
+
314
+ expect(sortByName(await nymph.getIndexes(TestModel.ETYPE))).toEqual([
315
+ { scope: 'references', name: 'refone', property: 'reference' },
316
+ { scope: 'data', name: 'secondone', property: 'match' },
317
+ { scope: 'tokens', name: 'tokenone', property: 'search' },
318
+ ]);
319
+ });
193
320
 
194
- // Verify it's back.
195
- testEntity = (await transaction.getEntity(
196
- { class: TestModel },
197
- testGuid
198
- )) as TestModelClass & TestModelData;
321
+ it('transactions', async () => {
322
+ await createTestEntities();
199
323
 
200
- expect(testEntity.guid).toEqual(testGuid);
324
+ // Verify not in a transaction.
325
+ expect(await nymph.inTransaction()).toEqual(false);
201
326
 
202
- // Start a new transaction.
203
- transaction = await nymph.startTransaction('test');
204
- testEntity.$nymph = transaction;
327
+ let transaction = await nymph.startTransaction('test');
328
+ testEntity.$nymph = transaction;
205
329
 
206
- // Verify in a transaction.
207
- expect(await transaction.inTransaction()).toEqual(true);
330
+ if (!(await transaction.inTransaction())) {
331
+ console.log(
332
+ 'This Nymph driver or database seems to not support transactions. Skipping transaction tests.',
333
+ );
334
+ await transaction.rollback('test');
335
+ return;
336
+ }
208
337
 
209
- // Make a change.
210
- testEntity.string = 'fish';
211
- expect(await testEntity.$save()).toEqual(true);
338
+ // Change a value in the test entity.
339
+ testEntity.string = 'bad value';
340
+ await testEntity.$save();
212
341
 
213
- // Commit the transaction.
214
- await transaction.commit('test');
215
- testEntity.$nymph = nymph;
342
+ // Rollback the transaction.
343
+ await transaction.rollback('test');
216
344
 
217
- // Verify not in a transaction.
218
- expect(await transaction.inTransaction()).toEqual(false);
345
+ // Verify not in a transaction.
346
+ expect(await transaction.inTransaction()).toEqual(false);
219
347
 
220
- // Verify the value is correct.
221
- await testEntity.$refresh();
222
- expect(testEntity.string).toEqual('fish');
348
+ // Verify the value is correct.
349
+ await testEntity.$refresh();
350
+ expect(testEntity.string).toEqual('test');
223
351
 
224
- // Finally, change it back.
225
- testEntity.string = 'test';
226
- expect(await testEntity.$save()).toEqual(true);
352
+ // Start a new transaction.
353
+ transaction = await nymph.startTransaction('test');
354
+ testEntity.$nymph = transaction;
227
355
 
228
- // TODO: nested transactions
229
- });
356
+ // Verify in a transaction.
357
+ expect(await transaction.inTransaction()).toEqual(true);
230
358
 
231
- it('options', async () => {
232
- await createTestEntities();
359
+ // Delete the entity.
360
+ await testEntity.$delete();
361
+ const resultEntity = await transaction.getEntity(
362
+ { class: TestModel },
363
+ testGuid,
364
+ );
365
+ expect(resultEntity).toBeNull();
233
366
 
234
- // Testing entity order, offset, limit...
235
- const resultEntities = await nymph.getEntities(
236
- {
237
- class: TestModel,
238
- reverse: true,
239
- offset: 1,
240
- limit: 1,
241
- sort: 'cdate',
242
- },
243
- { type: '&', tag: 'test' }
244
- );
245
- expect(resultEntities.length).toEqual(1);
246
- expect(testEntity.$is(resultEntities[0])).toEqual(true);
247
- });
367
+ // Rollback the transaction.
368
+ await transaction.rollback('test');
248
369
 
249
- it('guid and tags', async () => {
250
- await createTestEntities();
370
+ // Verify not in a transaction.
371
+ expect(await transaction.inTransaction()).toEqual(false);
251
372
 
252
- // Retrieving entity by GUID and tags...
253
- const resultEntity = await nymph.getEntity(
254
- { class: TestModel },
255
- { type: '&', guid: testGuid, tag: 'test' }
256
- );
257
- expect(testEntity.$is(resultEntity)).toEqual(true);
258
- });
373
+ // Verify it's back.
374
+ testEntity = (await transaction.getEntity(
375
+ { class: TestModel },
376
+ testGuid,
377
+ )) as TestModelClass & TestModelData;
259
378
 
260
- it('or selector', async () => {
261
- await createTestEntities();
379
+ expect(testEntity.guid).toEqual(testGuid);
262
380
 
263
- // Retrieving entity by GUID and tags...
264
- const resultEntity = await nymph.getEntity(
265
- { class: TestModel },
266
- { type: '|', guid: [testGuid, guid()] }
267
- );
268
- expect(testEntity.$is(resultEntity)).toEqual(true);
269
- });
381
+ // Start a new transaction with a dot in the name.
382
+ transaction = await nymph.startTransaction('test.1');
383
+ testEntity.$nymph = transaction;
270
384
 
271
- it('wrong or selector', async () => {
272
- await createTestEntities();
385
+ // Verify in a transaction.
386
+ expect(await transaction.inTransaction()).toEqual(true);
273
387
 
274
- // Retrieving entity by GUID and tags...
275
- const resultEntity = await nymph.getEntity(
276
- { class: TestModel },
277
- { type: '|', guid: [guid(), guid()] }
278
- );
279
- expect(testEntity.$is(resultEntity)).toEqual(false);
280
- });
388
+ // Make a change.
389
+ testEntity.string = 'fish';
390
+ await testEntity.$save();
281
391
 
282
- it('not guid', async () => {
283
- await createTestEntities();
392
+ // Commit the transaction.
393
+ await transaction.commit('test.1');
394
+ testEntity.$nymph = nymph;
284
395
 
285
- // Retrieving entity by !GUID...
286
- const resultEntity = await nymph.getEntities(
287
- { class: TestModel },
288
- { type: '&', '!guid': guid(), tag: 'test' }
289
- );
290
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
291
- });
396
+ // Verify not in a transaction.
397
+ expect(await transaction.inTransaction()).toEqual(false);
292
398
 
293
- it('not tags', async () => {
294
- await createTestEntities();
399
+ // Verify the value is correct.
400
+ await testEntity.$refresh();
401
+ expect(testEntity.string).toEqual('fish');
295
402
 
296
- // Retrieving entity by !tags...
297
- const resultEntity = await nymph.getEntities(
298
- { class: TestModel },
299
- { type: '&', guid: testGuid, '!tag': ['barbecue', 'pickles'] }
300
- );
301
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
302
- });
403
+ // Finally, change it back.
404
+ testEntity.string = 'test';
405
+ await testEntity.$save();
303
406
 
304
- it('guid and wrong tags', async () => {
305
- await createTestEntities();
407
+ // TODO: nested transactions
408
+ });
306
409
 
307
- // Testing GUID and wrong tags...
308
- const resultEntity = await nymph.getEntity(
309
- { class: TestModel },
310
- { type: '&', guid: testGuid, tag: ['pickles'] }
311
- );
312
- expect(resultEntity).toBeNull();
313
- });
410
+ it('transactional decorator', async () => {
411
+ await createTestEntities();
314
412
 
315
- it('tags', async () => {
316
- await createTestEntities();
413
+ if (testEntity.reference == null) {
414
+ throw new Error('Reference is null.');
415
+ }
416
+ await testEntity.reference.$wake();
317
417
 
318
- // Retrieving entity by tags...
319
- const resultEntity = await nymph.getEntities(
320
- { class: TestModel },
321
- { type: '&', tag: 'test' }
322
- );
323
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
324
- });
418
+ expect(testEntity.string).toEqual('test');
419
+ expect(testEntity.reference.string).toEqual('ref string');
325
420
 
326
- it('wrong tags', async () => {
327
- await createTestEntities();
421
+ try {
422
+ await testEntity.$testTransactionalDecorator(true);
328
423
 
329
- // Testing wrong tags...
330
- const resultEntity = await nymph.getEntities(
331
- { class: TestModel },
332
- { type: '&', tag: 'pickles' }
333
- );
334
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
335
- });
424
+ throw Error('Should have thrown an error.');
425
+ } catch (e: any) {
426
+ expect(e.message).toEqual('An error.');
427
+ }
336
428
 
337
- it('inclusive tags', async () => {
338
- await createTestEntities();
429
+ if (!(await testEntity.$refresh())) {
430
+ throw new Error("Entity couldn't be refreshed.");
431
+ }
432
+ await testEntity.reference.$wake();
339
433
 
340
- // Retrieving entity by tags inclusively...
341
- const resultEntity = await nymph.getEntities(
342
- { class: TestModel },
343
- { type: '|', tag: ['pickles', 'test', 'barbecue'] }
344
- );
345
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
346
- });
434
+ expect(testEntity.string).toEqual('test');
435
+ expect(testEntity.reference.string).toEqual('ref string');
347
436
 
348
- it('wrong inclusive tags', async () => {
349
- await createTestEntities();
437
+ expect(await testEntity.$testTransactionalDecorator(false)).toEqual(
438
+ 'Success.',
439
+ );
350
440
 
351
- // Testing wrong inclusive tags...
352
- const resultEntity = await nymph.getEntities(
353
- { class: TestModel },
354
- { type: '|', tag: ['pickles', 'barbecue'] }
355
- );
356
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
357
- });
441
+ if (!(await testEntity.$refresh())) {
442
+ throw new Error("Entity couldn't be refreshed.");
443
+ }
444
+ await testEntity.reference.$wake();
358
445
 
359
- it('mixed tags', async () => {
360
- await createTestEntities();
446
+ expect(testEntity.string).toEqual('this has been changed');
447
+ expect(testEntity.reference.string).toEqual('this has been changed too');
361
448
 
362
- // Retrieving entity by mixed tags...
363
- const resultEntity = await nymph.getEntities(
364
- { class: TestModel },
365
- { type: '&', tag: 'test' },
366
- { type: '|', tag: ['pickles', 'test', 'barbecue'] }
367
- );
368
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
369
- });
449
+ // Reset back to original values.
450
+ testEntity.reference.string = 'ref string';
451
+ await testEntity.reference.$save();
452
+ testEntity.string = 'test';
453
+ await testEntity.$save();
454
+ });
370
455
 
371
- it('wrong inclusive mixed tags', async () => {
372
- await createTestEntities();
456
+ it('transaction helper', async () => {
457
+ await createTestEntities();
373
458
 
374
- // Testing wrong inclusive mixed tags...
375
- const resultEntity = await nymph.getEntities(
376
- { class: TestModel },
377
- { type: '&', tag: 'test' },
378
- { type: '|', tag: ['pickles', 'barbecue'] }
379
- );
380
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
381
- });
459
+ if (testEntity.reference == null) {
460
+ throw new Error('Reference is null.');
461
+ }
462
+ await testEntity.reference.$wake();
382
463
 
383
- it('wrong exclusive mixed tags', async () => {
384
- await createTestEntities();
464
+ expect(testEntity.string).toEqual('test');
465
+ expect(testEntity.reference.string).toEqual('ref string');
385
466
 
386
- // Testing wrong exclusive mixed tags...
387
- const resultEntity = await nymph.getEntities(
388
- { class: TestModel },
389
- { type: '&', tag: 'pickles' },
390
- { type: '|', tag: ['test', 'barbecue'] }
391
- );
392
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
393
- });
467
+ try {
468
+ await testEntity.$testTransactionHelper(true);
394
469
 
395
- it('defined', async () => {
396
- await createTestEntities();
470
+ throw Error('Should have thrown an error.');
471
+ } catch (e: any) {
472
+ expect(e.message).toEqual('An error.');
473
+ }
397
474
 
398
- // Retrieving entity by defined...
399
- const resultEntity = await nymph.getEntities(
400
- { class: TestModel },
401
- { type: '&', defined: 'string' }
402
- );
403
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
404
- });
475
+ if (!(await testEntity.$refresh())) {
476
+ throw new Error("Entity couldn't be refreshed.");
477
+ }
478
+ await testEntity.reference.$wake();
405
479
 
406
- it('not defined', async () => {
407
- await createTestEntities();
480
+ expect(testEntity.string).toEqual('test');
481
+ expect(testEntity.reference.string).toEqual('ref string');
408
482
 
409
- // Retrieving entity by !defined...
410
- const resultEntity = await nymph.getEntities(
411
- { class: TestModel },
412
- { type: '&', tag: 'test', '!defined': 'pickles' }
413
- );
414
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
415
- });
483
+ expect(await testEntity.$testTransactionHelper(false)).toEqual(
484
+ 'Success.',
485
+ );
416
486
 
417
- it('defined in a not and clause', async () => {
418
- await createTestEntities();
487
+ if (!(await testEntity.$refresh())) {
488
+ throw new Error("Entity couldn't be refreshed.");
489
+ }
490
+ await testEntity.reference.$wake();
419
491
 
420
- // Retrieving entity by defined in not and clause...
421
- const resultEntity = await nymph.getEntities(
422
- { class: TestModel },
423
- { type: '!&', defined: 'pickles' },
424
- { type: '&', tag: 'test' }
425
- );
426
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
427
- });
492
+ expect(testEntity.string).toEqual('this has been changed');
493
+ expect(testEntity.reference.string).toEqual('this has been changed too');
428
494
 
429
- it('equal', async () => {
430
- await createTestEntities();
495
+ // Reset back to original values.
496
+ testEntity.reference.string = 'ref string';
497
+ await testEntity.reference.$save();
498
+ testEntity.string = 'test';
499
+ await testEntity.$save();
500
+ });
431
501
 
432
- // Retrieving entity by equal...
433
- const resultEntity = await nymph.getEntities(
434
- { class: TestModel },
435
- { type: '&', equal: ['string', 'test'] }
436
- );
437
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
438
- });
502
+ it('options', async () => {
503
+ await createTestEntities();
504
+
505
+ // Testing entity order, offset, limit...
506
+ let resultEntities = await nymph.getEntities(
507
+ {
508
+ class: TestModel,
509
+ reverse: true,
510
+ offset: 1,
511
+ limit: 1,
512
+ sort: 'cdate',
513
+ },
514
+ { type: '&', tag: 'test' },
515
+ );
516
+ expect(resultEntities.length).toEqual(1);
517
+ expect(testEntity.$is(resultEntities[0])).toEqual(true);
439
518
 
440
- it('not equal', async () => {
441
- await createTestEntities();
519
+ // Testing null sort...
520
+ resultEntities = await nymph.getEntities(
521
+ {
522
+ class: TestModel,
523
+ reverse: true,
524
+ sort: null,
525
+ },
526
+ { type: '&', tag: 'test' },
527
+ );
528
+ expect(testEntity.$inArray(resultEntities)).toEqual(true);
529
+ });
442
530
 
443
- const referenceEntity = await TestModel.factory(refGuid);
444
- expect(referenceEntity.guid).toEqual(refGuid);
531
+ it('guid and tags', async () => {
532
+ await createTestEntities();
445
533
 
446
- // Retrieving entity by !equal...
447
- const resultEntity = await nymph.getEntities(
448
- { class: TestModel },
449
- { type: '&', tag: 'test', '!equal': ['string', 'wrong'] }
450
- );
451
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
452
- expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
453
- });
534
+ // Retrieving entity by GUID and tags...
535
+ const resultEntity = await nymph.getEntity(
536
+ { class: TestModel },
537
+ { type: '&', guid: testGuid, tag: 'test' },
538
+ );
539
+ expect(testEntity.$is(resultEntity)).toEqual(true);
540
+ });
454
541
 
455
- it('like', async () => {
456
- await createTestEntities();
542
+ it('or selector', async () => {
543
+ await createTestEntities();
457
544
 
458
- // Retrieving entity by like...
459
- const resultEntity = await nymph.getEntities(
460
- { class: TestModel },
461
- { type: '&', like: ['string', 't_s%'] }
462
- );
463
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
464
- });
545
+ // Retrieving entity by GUID and tags...
546
+ const resultEntity = await nymph.getEntity(
547
+ { class: TestModel },
548
+ { type: '|', guid: [testGuid, guid()] },
549
+ );
550
+ expect(testEntity.$is(resultEntity)).toEqual(true);
551
+ });
465
552
 
466
- it('not like', async () => {
467
- await createTestEntities();
553
+ it('wrong or selector', async () => {
554
+ await createTestEntities();
468
555
 
469
- const referenceEntity = await TestModel.factory(refGuid);
470
- expect(referenceEntity.guid).toEqual(refGuid);
556
+ // Retrieving entity by GUID and tags...
557
+ const resultEntity = await nymph.getEntity(
558
+ { class: TestModel },
559
+ { type: '|', guid: [guid(), guid()] },
560
+ );
561
+ expect(testEntity.$is(resultEntity)).toEqual(false);
562
+ });
471
563
 
472
- // Retrieving entity by !like...
473
- const resultEntity = await nymph.getEntities(
474
- { class: TestModel },
475
- { type: '&', tag: 'test', '!like': ['string', 'wr_n%'] }
476
- );
477
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
478
- expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
479
- });
564
+ it('not guid', async () => {
565
+ await createTestEntities();
480
566
 
481
- it('ilike', async () => {
482
- await createTestEntities();
567
+ // Retrieving entity by !GUID...
568
+ const resultEntity = await nymph.getEntities(
569
+ { class: TestModel },
570
+ { type: '&', '!guid': guid(), tag: 'test' },
571
+ );
572
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
573
+ });
483
574
 
484
- // Retrieving entity by ilike...
485
- const resultEntity = await nymph.getEntities(
486
- { class: TestModel },
487
- { type: '&', ilike: ['string', 'T_s%'] }
488
- );
489
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
490
- });
575
+ it('not tags', async () => {
576
+ await createTestEntities();
491
577
 
492
- it('not ilike', async () => {
493
- await createTestEntities();
578
+ // Retrieving entity by !tags...
579
+ const resultEntity = await nymph.getEntities(
580
+ { class: TestModel },
581
+ { type: '&', guid: testGuid, '!tag': ['barbecue', 'pickles'] },
582
+ );
583
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
584
+ });
494
585
 
495
- const referenceEntity = await TestModel.factory(refGuid);
496
- expect(referenceEntity.guid).toEqual(refGuid);
586
+ it('guid and wrong tags', async () => {
587
+ await createTestEntities();
497
588
 
498
- // Retrieving entity by !ilike...
499
- const resultEntity = await nymph.getEntities(
500
- { class: TestModel },
501
- { type: '&', tag: 'test', '!ilike': ['string', 'wr_n%'] }
502
- );
503
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
504
- expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
505
- });
589
+ // Testing GUID and wrong tags...
590
+ const resultEntity = await nymph.getEntity(
591
+ { class: TestModel },
592
+ { type: '&', guid: testGuid, tag: ['pickles'] },
593
+ );
594
+ expect(resultEntity).toBeNull();
595
+ });
506
596
 
507
- it('like with wrong case', async () => {
508
- await createTestEntities();
597
+ it('tags', async () => {
598
+ await createTestEntities();
509
599
 
510
- // Retrieving entity by like...
511
- const resultEntity = await nymph.getEntities(
512
- { class: TestModel },
513
- { type: '&', like: ['string', 'T_s%'] }
514
- );
515
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
516
- });
600
+ // Retrieving entity by tags...
601
+ const resultEntity = await nymph.getEntities(
602
+ { class: TestModel },
603
+ { type: '&', tag: 'test' },
604
+ );
605
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
606
+ });
517
607
 
518
- it('tags and equal', async () => {
519
- await createTestEntities();
608
+ it('wrong tags', async () => {
609
+ await createTestEntities();
520
610
 
521
- // Retrieving entity by tags and equal...
522
- const resultEntity = await nymph.getEntities(
523
- { class: TestModel },
524
- { type: '&', tag: 'test', equal: ['string', 'test'] }
525
- );
526
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
527
- });
611
+ // Testing wrong tags...
612
+ const resultEntity = await nymph.getEntities(
613
+ { class: TestModel },
614
+ { type: '&', tag: 'pickles' },
615
+ );
616
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
617
+ });
528
618
 
529
- it('wrong tags right equal', async () => {
530
- await createTestEntities();
619
+ it('inclusive tags', async () => {
620
+ await createTestEntities();
531
621
 
532
- // Testing wrong tags and right equal...
533
- const resultEntity = await nymph.getEntities(
534
- { class: TestModel },
535
- { type: '&', tag: 'pickles', equal: ['string', 'test'] }
536
- );
537
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
538
- });
622
+ // Retrieving entity by tags inclusively...
623
+ const resultEntity = await nymph.getEntities(
624
+ { class: TestModel },
625
+ { type: '|', tag: ['pickles', 'test', 'barbecue'] },
626
+ );
627
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
628
+ });
539
629
 
540
- it('right tags wrong equal', async () => {
541
- await createTestEntities();
630
+ it('wrong inclusive tags', async () => {
631
+ await createTestEntities();
542
632
 
543
- // Testing right tags and wrong equal...
544
- const resultEntity = await nymph.getEntities(
545
- { class: TestModel },
546
- { type: '&', tag: 'test', equal: ['string', 'pickles'] }
547
- );
548
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
549
- });
633
+ // Testing wrong inclusive tags...
634
+ const resultEntity = await nymph.getEntities(
635
+ { class: TestModel },
636
+ { type: '|', tag: ['pickles', 'barbecue'] },
637
+ );
638
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
639
+ });
550
640
 
551
- it('wrong tags wrong equal', async () => {
552
- await createTestEntities();
641
+ it('mixed tags', async () => {
642
+ await createTestEntities();
553
643
 
554
- // Testing wrong tags and wrong equal...
555
- const resultEntity = await nymph.getEntities(
556
- { class: TestModel },
557
- { type: '&', tag: 'pickles', equal: ['string', 'pickles'] }
558
- );
559
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
560
- });
644
+ // Retrieving entity by mixed tags...
645
+ const resultEntity = await nymph.getEntities(
646
+ { class: TestModel },
647
+ { type: '&', tag: 'test' },
648
+ { type: '|', tag: ['pickles', 'test', 'barbecue'] },
649
+ );
650
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
651
+ });
561
652
 
562
- it('contain', async () => {
563
- await createTestEntities();
564
-
565
- // Retrieving entity by contain...
566
- let resultEntity = await nymph.getEntities(
567
- { class: TestModel },
568
- { type: '&', contain: ['array', 'values'] }
569
- );
570
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
571
-
572
- // Retrieving entity by contain with full match...
573
- resultEntity = await nymph.getEntities(
574
- { class: TestModel },
575
- { type: '&', contain: ['string', 'test'] }
576
- );
577
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
578
- });
653
+ it('wrong inclusive mixed tags', async () => {
654
+ await createTestEntities();
579
655
 
580
- it('not contain', async () => {
581
- await createTestEntities();
656
+ // Testing wrong inclusive mixed tags...
657
+ const resultEntity = await nymph.getEntities(
658
+ { class: TestModel },
659
+ { type: '&', tag: 'test' },
660
+ { type: '|', tag: ['pickles', 'barbecue'] },
661
+ );
662
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
663
+ });
582
664
 
583
- // Retrieving entity by !contain...
584
- const resultEntity = await nymph.getEntities(
585
- { class: TestModel },
586
- { type: '&', tag: 'test' },
587
- { type: '!&', contain: ['array', 'pickles'] }
588
- );
589
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
590
- });
665
+ it('wrong exclusive mixed tags', async () => {
666
+ await createTestEntities();
591
667
 
592
- it('wrong contain', async () => {
593
- await createTestEntities();
594
-
595
- // Testing wrong contain...
596
- let resultEntity = await nymph.getEntities(
597
- { class: TestModel },
598
- { type: '&', contain: ['array', 'pickles'] }
599
- );
600
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
601
-
602
- // Testing wrong contain...
603
- resultEntity = await nymph.getEntities(
604
- { class: TestModel },
605
- { type: '&', contain: ['string', 'pickles'] }
606
- );
607
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
608
- });
668
+ // Testing wrong exclusive mixed tags...
669
+ const resultEntity = await nymph.getEntities(
670
+ { class: TestModel },
671
+ { type: '&', tag: 'pickles' },
672
+ { type: '|', tag: ['test', 'barbecue'] },
673
+ );
674
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
675
+ });
609
676
 
610
- it('match', async () => {
611
- await createTestEntities();
612
-
613
- // Retrieving entity by regex match...
614
- let resultEntity = await nymph.getEntities(
615
- { class: TestModel },
616
- { type: '&', match: ['match', '.*'] } // anything
617
- );
618
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
619
- resultEntity = await nymph.getEntities(
620
- { class: TestModel },
621
- { type: '&', tag: 'test', match: ['match', 'Edward McCheese'] } // a substring
622
- );
623
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
624
- resultEntity = await nymph.getEntities(
625
- { class: TestModel },
626
- { type: '&', tag: 'test' },
627
- {
628
- type: '|',
629
- match: [
630
- ['string', '[0-9]'],
631
- ['match', 'Edward McCheese'],
632
- ],
633
- } // inclusive test
634
- );
635
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
636
- resultEntity = await nymph.getEntities(
637
- { class: TestModel },
638
- {
639
- type: '&',
640
- tag: 'test',
641
- match: ['match', '[-a-zA-Z0-9+_]+@[-a-zA-Z0-9_]+.[-a-zA-Z0-9_]{2,4}'],
642
- } // a simple email
643
- );
644
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
645
- resultEntity = await nymph.getEntities(
646
- { class: TestModel },
647
- {
648
- type: '&',
649
- tag: 'test',
650
- match: ['match', '\\([0-9]{3}\\) [0-9]{3}-[0-9]{4}'],
651
- } // a phone number
652
- );
653
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
654
- });
677
+ it('defined', async () => {
678
+ await createTestEntities();
655
679
 
656
- it('imatch', async () => {
657
- await createTestEntities();
680
+ // Retrieving entity by defined...
681
+ const resultEntity = await nymph.getEntities(
682
+ { class: TestModel },
683
+ { type: '&', defined: 'string' },
684
+ );
685
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
686
+ });
658
687
 
659
- // Retrieving entity by regex match...
660
- const resultEntity = await nymph.getEntities(
661
- { class: TestModel },
662
- { type: '&', tag: 'test', imatch: ['match', 'edward mccheese'] } // a substring
663
- );
664
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
665
- });
688
+ it('not defined', async () => {
689
+ await createTestEntities();
666
690
 
667
- it('wrong match', async () => {
668
- await createTestEntities();
669
-
670
- // Testing wrong regex match...
671
- let resultEntity = await nymph.getEntities(
672
- { class: TestModel },
673
- { type: '&', match: ['match', 'Q'] }
674
- );
675
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
676
- resultEntity = await nymph.getEntities(
677
- { class: TestModel },
678
- { type: '&', tag: 'pickle', match: ['match', '.*'] }
679
- );
680
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
681
- resultEntity = await nymph.getEntities(
682
- { class: TestModel },
683
- {
684
- type: '|',
685
- match: [
686
- ['string', '[0-9]'],
687
- ['match', ',,'],
688
- ],
689
- }
690
- );
691
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
692
- });
691
+ // Retrieving entity by !defined...
692
+ const resultEntity = await nymph.getEntities(
693
+ { class: TestModel },
694
+ { type: '&', tag: 'test', '!defined': 'pickles' },
695
+ );
696
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
697
+ });
693
698
 
694
- it('match wrong case', async () => {
695
- await createTestEntities();
699
+ it('defined in a not and clause', async () => {
700
+ await createTestEntities();
696
701
 
697
- // Retrieving entity by regex match...
698
- const resultEntity = await nymph.getEntities(
699
- { class: TestModel },
700
- { type: '&', tag: 'test', match: ['match', 'edward mccheese'] } // a substring
701
- );
702
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
703
- });
702
+ // Retrieving entity by defined in not and clause...
703
+ const resultEntity = await nymph.getEntities(
704
+ { class: TestModel },
705
+ { type: '!&', defined: 'pickles' },
706
+ { type: '&', tag: 'test' },
707
+ );
708
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
709
+ });
704
710
 
705
- it('match and equal inclusive', async () => {
706
- await createTestEntities();
711
+ it('equal', async () => {
712
+ await createTestEntities();
707
713
 
708
- // Retrieving entity by regex + equal inclusively...
709
- const resultEntity = await nymph.getEntities(
710
- { class: TestModel },
711
- { type: '&', tag: 'test' },
712
- { type: '|', equal: ['string', 'pickles'], match: ['string', 'test'] }
713
- );
714
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
715
- });
714
+ // Retrieving entity by equal...
715
+ let resultEntity = await nymph.getEntities(
716
+ { class: TestModel },
717
+ { type: '&', equal: ['string', 'test'] },
718
+ );
719
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
716
720
 
717
- it('greater than', async () => {
718
- await createTestEntities();
719
-
720
- // Retrieving entity by inequality...
721
- let resultEntity = await nymph.getEntities(
722
- { class: TestModel },
723
- {
724
- type: '|',
725
- gt: [
726
- ['number', 30],
727
- ['pickles', 100],
728
- ],
729
- }
730
- );
731
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
732
-
733
- // Retrieving entity by inequality...
734
- resultEntity = await nymph.getEntities(
735
- { class: TestModel },
736
- {
737
- type: '|',
738
- gt: [
739
- ['number', 31],
740
- ['pickles', 100],
741
- ],
742
- }
743
- );
744
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
745
-
746
- // Retrieving entity by inequality...
747
- resultEntity = await nymph.getEntities(
748
- { class: TestModel },
749
- {
750
- type: '|',
751
- gt: [
752
- ['number', 29],
753
- ['pickles', 100],
754
- ],
755
- }
756
- );
757
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
758
-
759
- // Retrieving entity by inequality...
760
- resultEntity = await nymph.getEntities(
761
- { class: TestModel },
762
- {
763
- type: '|',
764
- gt: [
765
- ['numberString', 30],
766
- ['pickles', 100],
767
- ],
768
- }
769
- );
770
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
771
-
772
- // Retrieving entity by inequality...
773
- resultEntity = await nymph.getEntities(
774
- { class: TestModel },
775
- {
776
- type: '|',
777
- gt: [
778
- ['numberString', 31],
779
- ['pickles', 100],
780
- ],
781
- }
782
- );
783
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
784
-
785
- // Retrieving entity by inequality...
786
- resultEntity = await nymph.getEntities(
787
- { class: TestModel },
788
- {
789
- type: '|',
790
- gt: [
791
- ['numberString', 29],
792
- ['pickles', 100],
793
- ],
794
- }
795
- );
796
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
797
- });
721
+ // Retrieving entity by equal...
722
+ resultEntity = await nymph.getEntities(
723
+ { class: TestModel },
724
+ { type: '&', equal: ['null', null] },
725
+ );
726
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
798
727
 
799
- it('greater than or equal', async () => {
800
- await createTestEntities();
801
-
802
- // Retrieving entity by inequality...
803
- let resultEntity = await nymph.getEntities(
804
- { class: TestModel },
805
- {
806
- type: '|',
807
- gte: [
808
- ['number', 30],
809
- ['pickles', 100],
810
- ],
811
- }
812
- );
813
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
814
-
815
- // Retrieving entity by inequality...
816
- resultEntity = await nymph.getEntities(
817
- { class: TestModel },
818
- {
819
- type: '|',
820
- gte: [
821
- ['number', 31],
822
- ['pickles', 100],
823
- ],
824
- }
825
- );
826
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
827
-
828
- // Retrieving entity by inequality...
829
- resultEntity = await nymph.getEntities(
830
- { class: TestModel },
831
- {
832
- type: '|',
833
- gte: [
834
- ['number', 29],
835
- ['pickles', 100],
836
- ],
837
- }
838
- );
839
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
840
-
841
- // Retrieving entity by inequality...
842
- resultEntity = await nymph.getEntities(
843
- { class: TestModel },
844
- {
845
- type: '|',
846
- gte: [
847
- ['numberString', 30],
848
- ['pickles', 100],
849
- ],
850
- }
851
- );
852
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
853
-
854
- // Retrieving entity by inequality...
855
- resultEntity = await nymph.getEntities(
856
- { class: TestModel },
857
- {
858
- type: '|',
859
- gte: [
860
- ['numberString', 31],
861
- ['pickles', 100],
862
- ],
863
- }
864
- );
865
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
866
-
867
- // Retrieving entity by inequality...
868
- resultEntity = await nymph.getEntities(
869
- { class: TestModel },
870
- {
871
- type: '|',
872
- gte: [
873
- ['numberString', 29],
874
- ['pickles', 100],
875
- ],
876
- }
877
- );
878
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
879
- });
728
+ // Retrieving entity by equal...
729
+ resultEntity = await nymph.getEntities(
730
+ { class: TestModel },
731
+ { type: '&', equal: ['boolean', true] },
732
+ );
733
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
880
734
 
881
- it('less than', async () => {
882
- await createTestEntities();
883
-
884
- // Retrieving entity by inequality...
885
- let resultEntity = await nymph.getEntities(
886
- { class: TestModel },
887
- {
888
- type: '|',
889
- lt: [
890
- ['number', 30],
891
- ['pickles', 100],
892
- ],
893
- }
894
- );
895
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
896
-
897
- // Retrieving entity by inequality...
898
- resultEntity = await nymph.getEntities(
899
- { class: TestModel },
900
- {
901
- type: '|',
902
- lt: [
903
- ['number', 31],
904
- ['pickles', 100],
905
- ],
906
- }
907
- );
908
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
909
-
910
- // Retrieving entity by inequality...
911
- resultEntity = await nymph.getEntities(
912
- { class: TestModel },
913
- {
914
- type: '|',
915
- lt: [
916
- ['number', 29],
917
- ['pickles', 100],
918
- ],
919
- }
920
- );
921
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
922
-
923
- // Retrieving entity by inequality...
924
- resultEntity = await nymph.getEntities(
925
- { class: TestModel },
926
- {
927
- type: '|',
928
- lt: [
929
- ['numberString', 30],
930
- ['pickles', 100],
931
- ],
932
- }
933
- );
934
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
935
-
936
- // Retrieving entity by inequality...
937
- resultEntity = await nymph.getEntities(
938
- { class: TestModel },
939
- {
940
- type: '|',
941
- lt: [
942
- ['numberString', 31],
943
- ['pickles', 100],
944
- ],
945
- }
946
- );
947
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
948
-
949
- // Retrieving entity by inequality...
950
- resultEntity = await nymph.getEntities(
951
- { class: TestModel },
952
- {
953
- type: '|',
954
- lt: [
955
- ['numberString', 29],
956
- ['pickles', 100],
957
- ],
958
- }
959
- );
960
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
961
- });
735
+ // Retrieving entity by equal...
736
+ resultEntity = await nymph.getEntities(
737
+ { class: TestModel },
738
+ { type: '&', equal: ['number', 30] },
739
+ );
740
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
741
+
742
+ // Retrieving entity by equal...
743
+ resultEntity = await nymph.getEntities(
744
+ { class: TestModel },
745
+ {
746
+ type: '&',
747
+ equal: [
748
+ 'array',
749
+ [
750
+ 'full',
751
+ 'of',
752
+ 'values',
753
+ 500,
754
+ { test: true },
755
+ { nullbyte: '\\\x00\u0000 \x00' },
756
+ ],
757
+ ],
758
+ },
759
+ );
760
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
761
+
762
+ // Retrieving entity by equal...
763
+ resultEntity = await nymph.getEntities(
764
+ { class: TestModel },
765
+ {
766
+ type: '&',
767
+ equal: ['match', matchValue],
768
+ },
769
+ );
770
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
771
+ });
962
772
 
963
- it('less than or equal', async () => {
964
- await createTestEntities();
965
-
966
- // Retrieving entity by inequality...
967
- let resultEntity = await nymph.getEntities(
968
- { class: TestModel },
969
- {
970
- type: '|',
971
- lte: [
972
- ['number', 30],
973
- ['pickles', 100],
974
- ],
975
- }
976
- );
977
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
978
-
979
- // Retrieving entity by inequality...
980
- resultEntity = await nymph.getEntities(
981
- { class: TestModel },
982
- {
983
- type: '|',
984
- lte: [
985
- ['number', 31],
986
- ['pickles', 100],
987
- ],
988
- }
989
- );
990
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
991
-
992
- // Retrieving entity by inequality...
993
- resultEntity = await nymph.getEntities(
994
- { class: TestModel },
995
- {
996
- type: '|',
997
- lte: [
998
- ['number', 29],
999
- ['pickles', 100],
1000
- ],
1001
- }
1002
- );
1003
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1004
-
1005
- // Retrieving entity by inequality...
1006
- resultEntity = await nymph.getEntities(
1007
- { class: TestModel },
1008
- {
1009
- type: '|',
1010
- lte: [
1011
- ['numberString', 30],
1012
- ['pickles', 100],
1013
- ],
1014
- }
1015
- );
1016
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1017
-
1018
- // Retrieving entity by inequality...
1019
- resultEntity = await nymph.getEntities(
1020
- { class: TestModel },
1021
- {
1022
- type: '|',
1023
- lte: [
1024
- ['numberString', 31],
1025
- ['pickles', 100],
1026
- ],
1027
- }
1028
- );
1029
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1030
-
1031
- // Retrieving entity by inequality...
1032
- resultEntity = await nymph.getEntities(
1033
- { class: TestModel },
1034
- {
1035
- type: '|',
1036
- lte: [
1037
- ['numberString', 29],
1038
- ['pickles', 100],
1039
- ],
1040
- }
1041
- );
1042
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1043
- });
773
+ it('not equal', async () => {
774
+ await createTestEntities();
1044
775
 
1045
- it('not inequality', async () => {
1046
- await createTestEntities();
776
+ const referenceEntity = await TestModel.factory(refGuid);
777
+ expect(referenceEntity.guid).toEqual(refGuid);
1047
778
 
1048
- // Retrieving entity by !inequality...
1049
- const resultEntity = await nymph.getEntities(
1050
- { class: TestModel },
1051
- { type: '&', tag: 'test' },
1052
- { type: '!&', gte: ['number', 60] }
1053
- );
1054
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1055
- });
779
+ // Retrieving entity by !equal...
780
+ const resultEntity = await nymph.getEntities(
781
+ { class: TestModel },
782
+ { type: '&', tag: 'test', '!equal': ['string', 'ref string'] },
783
+ );
784
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
785
+ expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
786
+ });
1056
787
 
1057
- it('wrong inequality', async () => {
1058
- await createTestEntities();
788
+ it('like', async () => {
789
+ await createTestEntities();
1059
790
 
1060
- // Testing wrong inequality...
1061
- const resultEntity = await nymph.getEntities(
1062
- { class: TestModel },
1063
- { type: '&', lte: ['number', 29.99] }
1064
- );
1065
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1066
- });
791
+ // Retrieving entity by like...
792
+ const resultEntity = await nymph.getEntities(
793
+ { class: TestModel },
794
+ { type: '&', like: ['string', 't_s%'] },
795
+ );
796
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
797
+ });
1067
798
 
1068
- it('greater than cdate', async () => {
1069
- await createTestEntities();
799
+ it('not like', async () => {
800
+ await createTestEntities();
1070
801
 
1071
- // Retrieving entity by time...
1072
- const resultEntity = await nymph.getEntities(
1073
- { class: TestModel },
1074
- { type: '&', tag: 'test', gt: ['cdate', (testEntity.cdate ?? 0) - 120] }
1075
- );
1076
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1077
- });
802
+ const referenceEntity = await TestModel.factory(refGuid);
803
+ expect(referenceEntity.guid).toEqual(refGuid);
1078
804
 
1079
- it('wrong cdate', async () => {
1080
- await createTestEntities();
805
+ // Retrieving entity by !like...
806
+ const resultEntity = await nymph.getEntities(
807
+ { class: TestModel },
808
+ { type: '&', tag: 'test', '!like': ['string', 'r_f%'] },
809
+ );
810
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
811
+ expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
812
+ });
1081
813
 
1082
- // Testing wrong time...
1083
- const resultEntity = await nymph.getEntities(
1084
- { class: TestModel },
1085
- { type: '&', tag: 'test', gte: ['cdate', (testEntity.cdate ?? 0) + 1] }
1086
- );
1087
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1088
- });
814
+ it('ilike', async () => {
815
+ await createTestEntities();
1089
816
 
1090
- it('time selector', async () => {
1091
- await createTestEntities();
1092
-
1093
- const referenceEntity = await TestModel.factory(refGuid);
1094
-
1095
- // Retrieving entity by relative time...
1096
- let resultEntity = await nymph.getEntities(
1097
- { class: TestModel },
1098
- { type: '&', gt: ['timestamp', null, '-1 day'] }
1099
- );
1100
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1101
- expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
1102
-
1103
- // Retrieving entity by relative time inclusively...
1104
- resultEntity = await nymph.getEntities(
1105
- { class: TestModel },
1106
- {
1107
- type: '|',
1108
- gt: [
1109
- ['timestamp', null, '-1 day'],
1110
- ['timestamp', null, '+5 days'],
1111
- ],
1112
- }
1113
- );
1114
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1115
- expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
1116
-
1117
- // Retrieving entity by relative time...
1118
- resultEntity = await nymph.getEntities(
1119
- { class: TestModel },
1120
- { type: '&', gt: ['timestamp', null, '-3 days'] }
1121
- );
1122
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1123
- expect(referenceEntity.$inArray(resultEntity)).toEqual(true);
1124
-
1125
- // Retrieving entity by relative time...
1126
- resultEntity = await nymph.getEntities(
1127
- { class: TestModel },
1128
- { type: '&', gt: ['cdate', null, '-1 day'] }
1129
- );
1130
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1131
- expect(referenceEntity.$inArray(resultEntity)).toEqual(true);
1132
- });
817
+ // Retrieving entity by ilike...
818
+ const resultEntity = await nymph.getEntities(
819
+ { class: TestModel },
820
+ { type: '&', ilike: ['string', 'T_s%'] },
821
+ );
822
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
823
+ });
1133
824
 
1134
- it('wrong time selector', async () => {
1135
- await createTestEntities();
1136
-
1137
- const referenceEntity = await TestModel.factory(refGuid);
1138
-
1139
- // Retrieving entity by relative time...
1140
- let resultEntity = await nymph.getEntities(
1141
- { class: TestModel },
1142
- { type: '&', tag: 'test', gt: ['timestamp', null, '+1 day'] }
1143
- );
1144
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1145
- expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
1146
-
1147
- // Retrieving entity by relative time...
1148
- resultEntity = await nymph.getEntities(
1149
- { class: TestModel },
1150
- { type: '&', tag: 'test', lt: ['timestamp', null, '-3 days'] }
1151
- );
1152
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1153
- expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
1154
-
1155
- // Retrieving entity by relative time...
1156
- resultEntity = await nymph.getEntities(
1157
- { class: TestModel },
1158
- { type: '&', tag: 'test', gt: ['cdate', null, '+1 day'] }
1159
- );
1160
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1161
- expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
1162
- });
825
+ it('not ilike', async () => {
826
+ await createTestEntities();
1163
827
 
1164
- it('references', async () => {
1165
- await createTestEntities();
828
+ const referenceEntity = await TestModel.factory(refGuid);
829
+ expect(referenceEntity.guid).toEqual(refGuid);
1166
830
 
1167
- // Testing referenced entities...
1168
- expect(testEntity.reference?.test).toEqual('good');
831
+ // Retrieving entity by !ilike...
832
+ const resultEntity = await nymph.getEntities(
833
+ { class: TestModel },
834
+ { type: '&', tag: 'test', '!ilike': ['string', 'r_f%'] },
835
+ );
836
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
837
+ expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
838
+ });
1169
839
 
1170
- // Testing referenced entity arrays...
1171
- expect(testEntity.refArray?.[0].test).toEqual('good');
1172
- });
840
+ it('like with wrong case', async () => {
841
+ await createTestEntities();
1173
842
 
1174
- it('ref', async () => {
1175
- await createTestEntities();
843
+ // Retrieving entity by like...
844
+ const resultEntity = await nymph.getEntities(
845
+ { class: TestModel },
846
+ { type: '&', like: ['string', 'T_s%'] },
847
+ );
848
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
849
+ });
1176
850
 
1177
- // Retrieving entity by reference...
1178
- const resultEntity = await nymph.getEntities(
1179
- { class: TestModel },
1180
- { type: '&', ref: ['reference', refGuid] }
1181
- );
1182
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1183
- });
851
+ it('tags and equal', async () => {
852
+ await createTestEntities();
1184
853
 
1185
- it('not ref', async () => {
1186
- await createTestEntities();
854
+ // Retrieving entity by tags and equal...
855
+ const resultEntity = await nymph.getEntities(
856
+ { class: TestModel },
857
+ { type: '&', tag: 'test', equal: ['string', 'test'] },
858
+ );
859
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
860
+ });
1187
861
 
1188
- // Retrieving entity by !reference...
1189
- const resultEntity = await nymph.getEntities(
1190
- { class: TestModel },
1191
- { type: '&', tag: 'test' },
1192
- { type: '!&', ref: ['reference', guid()] }
1193
- );
1194
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1195
- });
862
+ it('wrong tags right equal', async () => {
863
+ await createTestEntities();
1196
864
 
1197
- it('wrong ref', async () => {
1198
- await createTestEntities();
865
+ // Testing wrong tags and right equal...
866
+ const resultEntity = await nymph.getEntities(
867
+ { class: TestModel },
868
+ { type: '&', tag: 'pickles', equal: ['string', 'test'] },
869
+ );
870
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
871
+ });
1199
872
 
1200
- // Testing wrong reference...
1201
- const resultEntity = await nymph.getEntities(
1202
- { class: TestModel },
1203
- { type: '&', ref: ['reference', guid()] }
1204
- );
1205
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1206
- });
873
+ it('right tags wrong equal', async () => {
874
+ await createTestEntities();
1207
875
 
1208
- it('nonexistent ref', async () => {
1209
- await createTestEntities();
876
+ // Testing right tags and wrong equal...
877
+ const resultEntity = await nymph.getEntities(
878
+ { class: TestModel },
879
+ { type: '&', tag: 'test', equal: ['string', 'pickles'] },
880
+ );
881
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
882
+ });
1210
883
 
1211
- // Testing non-existent reference...
1212
- const resultEntity = await nymph.getEntities(
1213
- { class: TestModel },
1214
- { type: '&', ref: ['pickle', refGuid] }
1215
- );
1216
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1217
- });
884
+ it('wrong tags wrong equal', async () => {
885
+ await createTestEntities();
1218
886
 
1219
- it('inclusive ref', async () => {
1220
- await createTestEntities();
1221
-
1222
- // Retrieving entity by inclusive reference...
1223
- const resultEntity = await nymph.getEntities(
1224
- { class: TestModel },
1225
- {
1226
- type: '|',
1227
- ref: [
1228
- ['reference', refGuid],
1229
- ['reference', guid()],
1230
- ],
1231
- }
1232
- );
1233
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1234
- });
887
+ // Testing wrong tags and wrong equal...
888
+ const resultEntity = await nymph.getEntities(
889
+ { class: TestModel },
890
+ { type: '&', tag: 'pickles', equal: ['string', 'pickles'] },
891
+ );
892
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
893
+ });
1235
894
 
1236
- it('wrong inclusive ref', async () => {
1237
- await createTestEntities();
1238
-
1239
- // Testing wrong inclusive reference...
1240
- const resultEntity = await nymph.getEntities(
1241
- { class: TestModel },
1242
- {
1243
- type: '|',
1244
- ref: [
1245
- ['reference', guid()],
1246
- ['reference', guid()],
1247
- ],
1248
- }
1249
- );
1250
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1251
- });
895
+ it('contain', async () => {
896
+ await createTestEntities();
1252
897
 
1253
- it('ref in an array', async () => {
1254
- await createTestEntities();
898
+ // Retrieving entity by contain...
899
+ let resultEntity = await nymph.getEntities(
900
+ { class: TestModel },
901
+ { type: '&', contain: ['array', 'values'] },
902
+ );
903
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1255
904
 
1256
- // Retrieving entity by array reference...
1257
- const resultEntity = await nymph.getEntities(
1258
- { class: TestModel },
1259
- { type: '&', ref: ['refArray', refGuid] }
1260
- );
1261
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1262
- });
905
+ // Retrieving entity by contain...
906
+ resultEntity = await nymph.getEntities(
907
+ { class: TestModel },
908
+ { type: '&', contain: ['array', 500] },
909
+ );
910
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1263
911
 
1264
- it('wrong ref in an array', async () => {
1265
- await createTestEntities();
1266
-
1267
- // Testing wrong array reference...
1268
- const resultEntity = await nymph.getEntities(
1269
- { class: TestModel },
1270
- {
1271
- type: '&',
1272
- ref: [
1273
- ['refArray', refGuid],
1274
- ['refArray', guid()],
1275
- ],
1276
- }
1277
- );
1278
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1279
- });
912
+ // Retrieving entity by contain...
913
+ resultEntity = await nymph.getEntities(
914
+ { class: TestModel },
915
+ { type: '&', contain: ['array', { test: true }] },
916
+ );
917
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
918
+ });
1280
919
 
1281
- it('logic operations', async () => {
1282
- await createTestEntities();
1283
-
1284
- // Testing logic operations...
1285
- const resultEntity = await nymph.getEntities(
1286
- { class: TestModel },
1287
- {
1288
- type: '&',
1289
- '!ref': [
1290
- ['refArray', guid()],
1291
- ['refArray', guid()],
1292
- ],
1293
- '!lte': ['number', 29.99],
1294
- },
1295
- {
1296
- type: '|',
1297
- '!lte': [
1298
- ['number', 29.99],
1299
- ['number', 30],
1300
- ],
1301
- },
1302
- {
1303
- type: '!&',
1304
- '!equal': ['string', 'test'],
1305
- '!contain': [
1306
- ['array', 'full'],
1307
- ['array', 'of'],
1308
- ['array', 'values'],
1309
- ['array', 500],
1310
- ],
1311
- },
1312
- {
1313
- type: '!|',
1314
- '!equal': ['string', 'test'],
1315
- contain: [
1316
- ['array', 'full'],
1317
- ['array', 'of'],
1318
- ['array', 'values'],
1319
- ['array', 500],
1320
- ],
1321
- }
1322
- );
1323
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1324
- });
920
+ it('not contain', async () => {
921
+ await createTestEntities();
1325
922
 
1326
- it('count return', async () => {
1327
- await createTestEntities();
1328
-
1329
- const result = await nymph.getEntities({ class: TestModel });
1330
-
1331
- // Testing count return...
1332
- const resultCount = await nymph.getEntities({
1333
- class: TestModel,
1334
- return: 'count',
1335
- });
1336
- expect(resultCount).toBeGreaterThanOrEqual(1);
1337
- expect(resultCount).toEqual(result.length);
1338
-
1339
- const resultSelectors = await nymph.getEntities(
1340
- { class: TestModel },
1341
- { type: '&', ref: ['reference', refGuid] }
1342
- );
1343
-
1344
- // Testing count return with selectors...
1345
- const resultSelectorsCount = await nymph.getEntities(
1346
- { class: TestModel, return: 'count' },
1347
- { type: '&', ref: ['reference', refGuid] }
1348
- );
1349
- expect(resultSelectorsCount).toBeGreaterThanOrEqual(1);
1350
- expect(resultSelectorsCount).toEqual(resultSelectors.length);
1351
-
1352
- // Testing count return with limit...
1353
- const resultSelectorsLimit = await nymph.getEntities({
1354
- class: TestModel,
1355
- limit: 1,
1356
- return: 'count',
1357
- });
1358
- expect(resultSelectorsLimit).toEqual(1);
1359
-
1360
- // Testing count return with limit...
1361
- const resultSelectorsSingle = await nymph.getEntity({
1362
- class: TestModel,
1363
- return: 'count',
1364
- });
1365
- expect(resultSelectorsSingle).toEqual(1);
1366
-
1367
- // Testing empty count...
1368
- const resultSelectorsEmpty = await nymph.getEntities(
1369
- { class: TestModel, return: 'count' },
1370
- { type: '&', ref: ['reference', guid()] }
1371
- );
1372
- expect(resultSelectorsEmpty).toEqual(0);
1373
- });
923
+ // Retrieving entity by !contain...
924
+ const resultEntity = await nymph.getEntities(
925
+ { class: TestModel },
926
+ { type: '&', tag: 'test' },
927
+ { type: '!&', contain: ['array', 'pickles'] },
928
+ );
929
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
930
+ });
1374
931
 
1375
- it('guid return', async () => {
1376
- await createTestEntities();
1377
-
1378
- // Testing guid return using logic operations...
1379
- const resultGuid = await nymph.getEntities(
1380
- { class: TestModel, return: 'guid' },
1381
- {
1382
- type: '&',
1383
- '!ref': [
1384
- ['refArray', guid()],
1385
- ['refArray', guid()],
1386
- ],
1387
- '!lte': ['number', 29.99],
1388
- },
1389
- {
1390
- type: '|',
1391
- '!lte': [
1392
- ['number', 29.99],
1393
- ['number', 30],
1394
- ],
1395
- },
1396
- {
1397
- type: '!&',
1398
- '!equal': ['string', 'test'],
1399
- '!contain': [
1400
- ['array', 'full'],
1401
- ['array', 'of'],
1402
- ['array', 'values'],
1403
- ['array', 500],
1404
- ],
1405
- },
1406
- {
1407
- type: '!|',
1408
- '!equal': ['string', 'test'],
1409
- contain: [
1410
- ['array', 'full'],
1411
- ['array', 'of'],
1412
- ['array', 'values'],
1413
- ['array', 500],
1414
- ],
1415
- }
1416
- );
1417
- expect(resultGuid.indexOf(testEntity.guid ?? '')).toBeGreaterThan(-1);
1418
- });
932
+ it('wrong contain', async () => {
933
+ await createTestEntities();
1419
934
 
1420
- it('deep selector', async () => {
1421
- await createTestEntities();
1422
-
1423
- // Testing deep selectors...
1424
- const resultEntity = await nymph.getEntities(
1425
- { class: TestModel },
1426
- {
1427
- type: '&',
1428
- '!ref': [
1429
- ['refArray', guid()],
1430
- ['refArray', guid()],
1431
- ],
1432
- '!lte': ['number', 29.99],
1433
- },
1434
- {
1435
- type: '&',
1436
- selector: [
1437
- {
1438
- type: '|',
1439
- '!lte': [
1440
- ['number', 29.99],
1441
- ['number', 30],
1442
- ],
1443
- },
1444
- {
1445
- type: '!&',
1446
- '!equal': ['string', 'test'],
1447
- '!contain': [
1448
- ['array', 'full'],
1449
- ['array', 'of'],
1450
- ['array', 'values'],
1451
- ['array', 500],
1452
- ],
1453
- },
1454
- {
1455
- type: '!|',
1456
- '!equal': ['string', 'test'],
1457
- contain: [
1458
- ['array', 'full'],
1459
- ['array', 'of'],
1460
- ['array', 'values'],
1461
- ['array', 500],
1462
- ],
1463
- },
1464
- ],
1465
- }
1466
- );
1467
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1468
-
1469
- const resultEntity2 = await nymph.getEntities(
1470
- { class: TestModel },
1471
- {
1472
- type: '&',
1473
- '!ref': [
1474
- ['refArray', guid()],
1475
- ['refArray', guid()],
1476
- ],
1477
- '!lte': ['number', 29.99],
1478
- },
1479
- {
1480
- type: '|',
1481
- selector: [
1482
- {
1483
- type: '&',
1484
- '!lte': [
1485
- ['number', 29.99],
1486
- ['number', 30],
1487
- ],
1488
- },
1489
- {
1490
- type: '!&',
1491
- '!equal': ['string', 'test'],
1492
- '!contain': [
1493
- ['array', 'full'],
1494
- ['array', 'of'],
1495
- ['array', 'values'],
1496
- ['array', 500],
1497
- ],
1498
- },
1499
- {
1500
- type: '&',
1501
- '!equal': ['string', 'test'],
1502
- contain: [
1503
- ['array', 'full'],
1504
- ['array', 'of'],
1505
- ['array', 'values'],
1506
- ['array', 500],
1507
- ],
1508
- },
1509
- ],
1510
- }
1511
- );
1512
- expect(testEntity.$inArray(resultEntity2)).toEqual(true);
1513
-
1514
- const resultEntity3 = await nymph.getEntities(
1515
- { class: TestModel },
1516
- {
1517
- type: '|',
1518
- selector: [
1519
- {
1520
- type: '&',
1521
- '!ref': ['refArray', guid()],
1522
- '!lte': ['number', 29.99],
1523
- },
1524
- { type: '&', gte: ['number', 16000] },
1525
- ],
1526
- }
1527
- );
1528
- expect(testEntity.$inArray(resultEntity3)).toEqual(true);
1529
-
1530
- const resultEntity4 = await nymph.getEntities(
1531
- { class: TestModel },
1532
- {
1533
- type: '|',
1534
- selector: [
1535
- {
1536
- type: '&',
1537
- '!ref': ['refArray', guid()],
1538
- '!lte': ['number', 29.99],
1539
- },
1540
- {
1541
- type: '&',
1542
- selector: {
935
+ // Testing wrong contain...
936
+ let resultEntity = await nymph.getEntities(
937
+ { class: TestModel },
938
+ { type: '&', contain: ['array', 'pickles'] },
939
+ );
940
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
941
+
942
+ // Testing wrong contain...
943
+ resultEntity = await nymph.getEntities(
944
+ { class: TestModel },
945
+ { type: '&', contain: ['string', 'pickles'] },
946
+ );
947
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
948
+ });
949
+
950
+ it('match', async () => {
951
+ await createTestEntities();
952
+
953
+ // Retrieving entity by regex match...
954
+ let resultEntity = await nymph.getEntities(
955
+ { class: TestModel },
956
+ { type: '&', match: ['match', '.*'] }, // anything
957
+ );
958
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
959
+ resultEntity = await nymph.getEntities(
960
+ { class: TestModel },
961
+ { type: '&', tag: 'test', match: ['match', 'Edward McCheese'] }, // a substring
962
+ );
963
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
964
+ resultEntity = await nymph.getEntities(
965
+ { class: TestModel },
966
+ { type: '&', tag: 'test' },
967
+ {
968
+ type: '|',
969
+ match: [
970
+ ['string', '[0-9]'],
971
+ ['match', 'Edward McCheese'],
972
+ ],
973
+ }, // inclusive test
974
+ );
975
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
976
+ resultEntity = await nymph.getEntities(
977
+ { class: TestModel },
978
+ {
979
+ type: '&',
980
+ tag: 'test',
981
+ match: ['match', '[-a-zA-Z0-9+_]+@[-a-zA-Z0-9_]+.[-a-zA-Z0-9_]{2,4}'],
982
+ }, // a simple email
983
+ );
984
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
985
+ resultEntity = await nymph.getEntities(
986
+ { class: TestModel },
987
+ {
988
+ type: '&',
989
+ tag: 'test',
990
+ match: ['match', '\\([0-9]{3}\\) [0-9]{3}-[0-9]{4}'],
991
+ }, // a phone number
992
+ );
993
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
994
+ });
995
+
996
+ it('imatch', async () => {
997
+ await createTestEntities();
998
+
999
+ // Retrieving entity by regex match...
1000
+ const resultEntity = await nymph.getEntities(
1001
+ { class: TestModel },
1002
+ { type: '&', tag: 'test', imatch: ['match', 'edward mccheese'] }, // a substring
1003
+ );
1004
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1005
+ });
1006
+
1007
+ it('wrong match', async () => {
1008
+ await createTestEntities();
1009
+
1010
+ // Testing wrong regex match...
1011
+ let resultEntity = await nymph.getEntities(
1012
+ { class: TestModel },
1013
+ { type: '&', match: ['match', '='] },
1014
+ );
1015
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1016
+ resultEntity = await nymph.getEntities(
1017
+ { class: TestModel },
1018
+ { type: '&', tag: 'pickle', match: ['match', '.*'] },
1019
+ );
1020
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1021
+ resultEntity = await nymph.getEntities(
1022
+ { class: TestModel },
1023
+ {
1024
+ type: '|',
1025
+ match: [
1026
+ ['string', '[0-9]'],
1027
+ ['match', ',,'],
1028
+ ],
1029
+ },
1030
+ );
1031
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1032
+ });
1033
+
1034
+ it('match wrong case', async () => {
1035
+ await createTestEntities();
1036
+
1037
+ // Retrieving entity by regex match...
1038
+ const resultEntity = await nymph.getEntities(
1039
+ { class: TestModel },
1040
+ { type: '&', tag: 'test', match: ['match', 'edward mccheese'] }, // a substring
1041
+ );
1042
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1043
+ });
1044
+
1045
+ it('match and equal inclusive', async () => {
1046
+ await createTestEntities();
1047
+
1048
+ // Retrieving entity by regex + equal inclusively...
1049
+ const resultEntity = await nymph.getEntities(
1050
+ { class: TestModel },
1051
+ { type: '&', tag: 'test' },
1052
+ { type: '|', equal: ['string', 'pickles'], match: ['string', 'test'] },
1053
+ );
1054
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1055
+ });
1056
+
1057
+ it('basic search', async () => {
1058
+ await createTestEntities();
1059
+
1060
+ // Retrieving entity by full text search...
1061
+ let resultEntity = await nymph.getEntities(
1062
+ { class: TestModel },
1063
+ {
1064
+ type: '&',
1065
+ tag: 'test',
1066
+ search: [
1067
+ 'search',
1068
+ 'Declaration of the thirteen united States of America',
1069
+ ],
1070
+ }, // a substring
1071
+ );
1072
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1073
+ resultEntity = await nymph.getEntities(
1074
+ { class: TestModel },
1075
+ { type: '&', tag: 'test' },
1076
+ {
1077
+ type: '|',
1078
+ search: [
1079
+ ['string', 'pickle'],
1080
+ ['search', 'Declaration of the thirteen united States of America'],
1081
+ ],
1082
+ }, // inclusive test
1083
+ );
1084
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1085
+ resultEntity = await nymph.getEntities(
1086
+ { class: TestModel },
1087
+ {
1088
+ type: '&',
1089
+ tag: 'test',
1090
+ search: ['search', 'July 4, 1776'],
1091
+ }, // a string with a number
1092
+ );
1093
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1094
+ });
1095
+
1096
+ it('or search', async () => {
1097
+ await createTestEntities();
1098
+
1099
+ // Retrieving entity by full text search...
1100
+ let resultEntity = await nymph.getEntities(
1101
+ { class: TestModel },
1102
+ {
1103
+ type: '&',
1104
+ tag: 'test',
1105
+ search: ['search', 'Declaration or pickles'],
1106
+ }, // a string with an or
1107
+ );
1108
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1109
+ });
1110
+
1111
+ it('series search', async () => {
1112
+ await createTestEntities();
1113
+
1114
+ // Retrieving entity by full text search...
1115
+ let resultEntity = await nymph.getEntities(
1116
+ { class: TestModel },
1117
+ {
1118
+ type: '&',
1119
+ tag: 'test',
1120
+ search: ['search', '"excited domestic insurrections"'],
1121
+ }, // double quoted substring
1122
+ );
1123
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1124
+ resultEntity = await nymph.getEntities(
1125
+ { class: TestModel },
1126
+ {
1127
+ type: '&',
1128
+ tag: 'test',
1129
+ search: ['search', "'exciting domestic insurrected'"],
1130
+ }, // single quoted substring
1131
+ );
1132
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1133
+ });
1134
+
1135
+ it('negated search', async () => {
1136
+ await createTestEntities();
1137
+
1138
+ // Retrieving entity by full text search...
1139
+ let resultEntity = await nymph.getEntities(
1140
+ { class: TestModel },
1141
+ {
1142
+ type: '&',
1143
+ tag: 'test',
1144
+ search: ['search', '-pickle'],
1145
+ }, // negated term
1146
+ );
1147
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1148
+ });
1149
+
1150
+ it('combined search', async () => {
1151
+ await createTestEntities();
1152
+
1153
+ // Retrieving entity by full text search...
1154
+ let resultEntity = await nymph.getEntities(
1155
+ { class: TestModel },
1156
+ {
1157
+ type: '&',
1158
+ tag: 'test',
1159
+ search: ['search', 'Declaration -pickle'],
1160
+ }, // negated term with positive term
1161
+ );
1162
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1163
+ resultEntity = await nymph.getEntities(
1164
+ { class: TestModel },
1165
+ {
1166
+ type: '&',
1167
+ tag: 'test',
1168
+ search: ['search', 'Declaration "General Congress"'],
1169
+ }, // terms found in separate areas
1170
+ );
1171
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1172
+ });
1173
+
1174
+ it('wrong search', async () => {
1175
+ await createTestEntities();
1176
+
1177
+ // Testing wrong search...
1178
+ let resultEntity = await nymph.getEntities(
1179
+ { class: TestModel },
1180
+ { type: '&', search: ['search', 'pickles'] },
1181
+ );
1182
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1183
+ resultEntity = await nymph.getEntities(
1184
+ { class: TestModel },
1185
+ { type: '&', tag: 'pickle', search: ['search', 'Declaration'] },
1186
+ );
1187
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1188
+ resultEntity = await nymph.getEntities(
1189
+ { class: TestModel },
1190
+ {
1191
+ type: '|',
1192
+ search: [
1193
+ ['string', 'pickle'],
1194
+ ['search', 'Hawaii'],
1195
+ ],
1196
+ },
1197
+ );
1198
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1199
+ });
1200
+
1201
+ it('search with only stop words', async () => {
1202
+ await createTestEntities();
1203
+
1204
+ // Testing wrong search...
1205
+ let resultEntity = await nymph.getEntities(
1206
+ { class: TestModel },
1207
+ { type: '&', search: ['search', 'i am'] },
1208
+ );
1209
+ expect(resultEntity).toEqual([]);
1210
+ });
1211
+
1212
+ it('search must be case insensitive', async () => {
1213
+ await createTestEntities();
1214
+
1215
+ // Retrieving entity by full text search...
1216
+ const resultEntity = await nymph.getEntities(
1217
+ { class: TestModel },
1218
+ {
1219
+ type: '&',
1220
+ tag: 'test',
1221
+ search: [
1222
+ 'search',
1223
+ 'DECLARATION OF THE THIRTEEN UNITED STATES OF AMERICA',
1224
+ ],
1225
+ }, // a substring
1226
+ );
1227
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1228
+ });
1229
+
1230
+ it('search and equal inclusive', async () => {
1231
+ await createTestEntities();
1232
+
1233
+ // Retrieving entity by fts + equal inclusively...
1234
+ const resultEntity = await nymph.getEntities(
1235
+ { class: TestModel },
1236
+ { type: '&', tag: 'test' },
1237
+ { type: '|', equal: ['string', 'pickles'], search: ['string', 'test'] },
1238
+ );
1239
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1240
+ });
1241
+
1242
+ it('greater than', async () => {
1243
+ await createTestEntities();
1244
+
1245
+ // Retrieving entity by inequality...
1246
+ let resultEntity = await nymph.getEntities(
1247
+ { class: TestModel },
1248
+ {
1249
+ type: '|',
1250
+ gt: [
1251
+ ['number', 30],
1252
+ ['pickles', 100],
1253
+ ],
1254
+ },
1255
+ );
1256
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1257
+
1258
+ // Retrieving entity by inequality...
1259
+ resultEntity = await nymph.getEntities(
1260
+ { class: TestModel },
1261
+ {
1262
+ type: '|',
1263
+ gt: [
1264
+ ['number', 31],
1265
+ ['pickles', 100],
1266
+ ],
1267
+ },
1268
+ );
1269
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1270
+
1271
+ // Retrieving entity by inequality...
1272
+ resultEntity = await nymph.getEntities(
1273
+ { class: TestModel },
1274
+ {
1275
+ type: '|',
1276
+ gt: [
1277
+ ['number', 29],
1278
+ ['pickles', 100],
1279
+ ],
1280
+ },
1281
+ );
1282
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1283
+
1284
+ // Retrieving entity by inequality...
1285
+ resultEntity = await nymph.getEntities(
1286
+ { class: TestModel },
1287
+ {
1288
+ type: '|',
1289
+ gt: [
1290
+ ['numberString', 30],
1291
+ ['pickles', 100],
1292
+ ],
1293
+ },
1294
+ );
1295
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1296
+
1297
+ // Retrieving entity by inequality...
1298
+ resultEntity = await nymph.getEntities(
1299
+ { class: TestModel },
1300
+ {
1301
+ type: '|',
1302
+ gt: [
1303
+ ['numberString', 31],
1304
+ ['pickles', 100],
1305
+ ],
1306
+ },
1307
+ );
1308
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1309
+
1310
+ // Retrieving entity by inequality...
1311
+ resultEntity = await nymph.getEntities(
1312
+ { class: TestModel },
1313
+ {
1314
+ type: '|',
1315
+ gt: [
1316
+ ['numberString', 29],
1317
+ ['pickles', 100],
1318
+ ],
1319
+ },
1320
+ );
1321
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1322
+ });
1323
+
1324
+ it('greater than or equal', async () => {
1325
+ await createTestEntities();
1326
+
1327
+ // Retrieving entity by inequality...
1328
+ let resultEntity = await nymph.getEntities(
1329
+ { class: TestModel },
1330
+ {
1331
+ type: '|',
1332
+ gte: [
1333
+ ['number', 30],
1334
+ ['pickles', 100],
1335
+ ],
1336
+ },
1337
+ );
1338
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1339
+
1340
+ // Retrieving entity by inequality...
1341
+ resultEntity = await nymph.getEntities(
1342
+ { class: TestModel },
1343
+ {
1344
+ type: '|',
1345
+ gte: [
1346
+ ['number', 31],
1347
+ ['pickles', 100],
1348
+ ],
1349
+ },
1350
+ );
1351
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1352
+
1353
+ // Retrieving entity by inequality...
1354
+ resultEntity = await nymph.getEntities(
1355
+ { class: TestModel },
1356
+ {
1357
+ type: '|',
1358
+ gte: [
1359
+ ['number', 29],
1360
+ ['pickles', 100],
1361
+ ],
1362
+ },
1363
+ );
1364
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1365
+
1366
+ // Retrieving entity by inequality...
1367
+ resultEntity = await nymph.getEntities(
1368
+ { class: TestModel },
1369
+ {
1370
+ type: '|',
1371
+ gte: [
1372
+ ['numberString', 30],
1373
+ ['pickles', 100],
1374
+ ],
1375
+ },
1376
+ );
1377
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1378
+
1379
+ // Retrieving entity by inequality...
1380
+ resultEntity = await nymph.getEntities(
1381
+ { class: TestModel },
1382
+ {
1383
+ type: '|',
1384
+ gte: [
1385
+ ['numberString', 31],
1386
+ ['pickles', 100],
1387
+ ],
1388
+ },
1389
+ );
1390
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1391
+
1392
+ // Retrieving entity by inequality...
1393
+ resultEntity = await nymph.getEntities(
1394
+ { class: TestModel },
1395
+ {
1396
+ type: '|',
1397
+ gte: [
1398
+ ['numberString', 29],
1399
+ ['pickles', 100],
1400
+ ],
1401
+ },
1402
+ );
1403
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1404
+ });
1405
+
1406
+ it('less than', async () => {
1407
+ await createTestEntities();
1408
+
1409
+ // Retrieving entity by inequality...
1410
+ let resultEntity = await nymph.getEntities(
1411
+ { class: TestModel },
1412
+ {
1413
+ type: '|',
1414
+ lt: [
1415
+ ['number', 30],
1416
+ ['pickles', 100],
1417
+ ],
1418
+ },
1419
+ );
1420
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1421
+
1422
+ // Retrieving entity by inequality...
1423
+ resultEntity = await nymph.getEntities(
1424
+ { class: TestModel },
1425
+ {
1426
+ type: '|',
1427
+ lt: [
1428
+ ['number', 31],
1429
+ ['pickles', 100],
1430
+ ],
1431
+ },
1432
+ );
1433
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1434
+
1435
+ // Retrieving entity by inequality...
1436
+ resultEntity = await nymph.getEntities(
1437
+ { class: TestModel },
1438
+ {
1439
+ type: '|',
1440
+ lt: [
1441
+ ['number', 29],
1442
+ ['pickles', 100],
1443
+ ],
1444
+ },
1445
+ );
1446
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1447
+
1448
+ // Retrieving entity by inequality...
1449
+ resultEntity = await nymph.getEntities(
1450
+ { class: TestModel },
1451
+ {
1452
+ type: '|',
1453
+ lt: [
1454
+ ['numberString', 30],
1455
+ ['pickles', 100],
1456
+ ],
1457
+ },
1458
+ );
1459
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1460
+
1461
+ // Retrieving entity by inequality...
1462
+ resultEntity = await nymph.getEntities(
1463
+ { class: TestModel },
1464
+ {
1465
+ type: '|',
1466
+ lt: [
1467
+ ['numberString', 31],
1468
+ ['pickles', 100],
1469
+ ],
1470
+ },
1471
+ );
1472
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1473
+
1474
+ // Retrieving entity by inequality...
1475
+ resultEntity = await nymph.getEntities(
1476
+ { class: TestModel },
1477
+ {
1478
+ type: '|',
1479
+ lt: [
1480
+ ['numberString', 29],
1481
+ ['pickles', 100],
1482
+ ],
1483
+ },
1484
+ );
1485
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1486
+ });
1487
+
1488
+ it('less than or equal', async () => {
1489
+ await createTestEntities();
1490
+
1491
+ // Retrieving entity by inequality...
1492
+ let resultEntity = await nymph.getEntities(
1493
+ { class: TestModel },
1494
+ {
1495
+ type: '|',
1496
+ lte: [
1497
+ ['number', 30],
1498
+ ['pickles', 100],
1499
+ ],
1500
+ },
1501
+ );
1502
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1503
+
1504
+ // Retrieving entity by inequality...
1505
+ resultEntity = await nymph.getEntities(
1506
+ { class: TestModel },
1507
+ {
1508
+ type: '|',
1509
+ lte: [
1510
+ ['number', 31],
1511
+ ['pickles', 100],
1512
+ ],
1513
+ },
1514
+ );
1515
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1516
+
1517
+ // Retrieving entity by inequality...
1518
+ resultEntity = await nymph.getEntities(
1519
+ { class: TestModel },
1520
+ {
1521
+ type: '|',
1522
+ lte: [
1523
+ ['number', 29],
1524
+ ['pickles', 100],
1525
+ ],
1526
+ },
1527
+ );
1528
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1529
+
1530
+ // Retrieving entity by inequality...
1531
+ resultEntity = await nymph.getEntities(
1532
+ { class: TestModel },
1533
+ {
1534
+ type: '|',
1535
+ lte: [
1536
+ ['numberString', 30],
1537
+ ['pickles', 100],
1538
+ ],
1539
+ },
1540
+ );
1541
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1542
+
1543
+ // Retrieving entity by inequality...
1544
+ resultEntity = await nymph.getEntities(
1545
+ { class: TestModel },
1546
+ {
1547
+ type: '|',
1548
+ lte: [
1549
+ ['numberString', 31],
1550
+ ['pickles', 100],
1551
+ ],
1552
+ },
1553
+ );
1554
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1555
+
1556
+ // Retrieving entity by inequality...
1557
+ resultEntity = await nymph.getEntities(
1558
+ { class: TestModel },
1559
+ {
1560
+ type: '|',
1561
+ lte: [
1562
+ ['numberString', 29],
1563
+ ['pickles', 100],
1564
+ ],
1565
+ },
1566
+ );
1567
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1568
+ });
1569
+
1570
+ it('not inequality', async () => {
1571
+ await createTestEntities();
1572
+
1573
+ // Retrieving entity by !inequality...
1574
+ const resultEntity = await nymph.getEntities(
1575
+ { class: TestModel },
1576
+ { type: '&', tag: 'test' },
1577
+ { type: '!&', gte: ['number', 60] },
1578
+ );
1579
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1580
+ });
1581
+
1582
+ it('wrong inequality', async () => {
1583
+ await createTestEntities();
1584
+
1585
+ // Testing wrong inequality...
1586
+ const resultEntity = await nymph.getEntities(
1587
+ { class: TestModel },
1588
+ { type: '&', lte: ['number', 29.99] },
1589
+ );
1590
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1591
+ });
1592
+
1593
+ it('greater than cdate', async () => {
1594
+ await createTestEntities();
1595
+
1596
+ // Retrieving entity by time...
1597
+ const resultEntity = await nymph.getEntities(
1598
+ { class: TestModel },
1599
+ {
1600
+ type: '&',
1601
+ tag: 'test',
1602
+ gt: ['cdate', (testEntity.cdate ?? 0) - 120],
1603
+ },
1604
+ );
1605
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1606
+ });
1607
+
1608
+ it('wrong cdate', async () => {
1609
+ await createTestEntities();
1610
+
1611
+ // Testing wrong time...
1612
+ const resultEntity = await nymph.getEntities(
1613
+ { class: TestModel },
1614
+ { type: '&', tag: 'test', gte: ['cdate', (testEntity.cdate ?? 0) + 1] },
1615
+ );
1616
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1617
+ });
1618
+
1619
+ it('time selector', async () => {
1620
+ await createTestEntities();
1621
+
1622
+ const referenceEntity = await TestModel.factory(refGuid);
1623
+
1624
+ // Retrieving entity by relative time...
1625
+ let resultEntity = await nymph.getEntities(
1626
+ { class: TestModel },
1627
+ { type: '&', gt: ['timestamp', null, '-1 day'] },
1628
+ );
1629
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1630
+ expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
1631
+
1632
+ // Retrieving entity by relative time inclusively...
1633
+ resultEntity = await nymph.getEntities(
1634
+ { class: TestModel },
1635
+ {
1636
+ type: '|',
1637
+ gt: [
1638
+ ['timestamp', null, '-1 day'],
1639
+ ['timestamp', null, '+5 days'],
1640
+ ],
1641
+ },
1642
+ );
1643
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1644
+ expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
1645
+
1646
+ // Retrieving entity by relative time...
1647
+ resultEntity = await nymph.getEntities(
1648
+ { class: TestModel },
1649
+ { type: '&', gt: ['timestamp', null, '-3 days'] },
1650
+ );
1651
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1652
+ expect(referenceEntity.$inArray(resultEntity)).toEqual(true);
1653
+
1654
+ // Retrieving entity by relative time...
1655
+ resultEntity = await nymph.getEntities(
1656
+ { class: TestModel },
1657
+ { type: '&', gt: ['cdate', null, '-1 day'] },
1658
+ );
1659
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1660
+ expect(referenceEntity.$inArray(resultEntity)).toEqual(true);
1661
+ });
1662
+
1663
+ it('wrong time selector', async () => {
1664
+ await createTestEntities();
1665
+
1666
+ const referenceEntity = await TestModel.factory(refGuid);
1667
+
1668
+ // Retrieving entity by relative time...
1669
+ let resultEntity = await nymph.getEntities(
1670
+ { class: TestModel },
1671
+ { type: '&', tag: 'test', gt: ['timestamp', null, '+1 day'] },
1672
+ );
1673
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1674
+ expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
1675
+
1676
+ // Retrieving entity by relative time...
1677
+ resultEntity = await nymph.getEntities(
1678
+ { class: TestModel },
1679
+ { type: '&', tag: 'test', lt: ['timestamp', null, '-3 days'] },
1680
+ );
1681
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1682
+ expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
1683
+
1684
+ // Retrieving entity by relative time...
1685
+ resultEntity = await nymph.getEntities(
1686
+ { class: TestModel },
1687
+ { type: '&', tag: 'test', gt: ['cdate', null, '+1 day'] },
1688
+ );
1689
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1690
+ expect(referenceEntity.$inArray(resultEntity)).toEqual(false);
1691
+ });
1692
+
1693
+ it('references', async () => {
1694
+ await createTestEntities();
1695
+
1696
+ // Testing referenced entities...
1697
+ await testEntity.reference?.$wake();
1698
+ expect(testEntity.reference?.test).toEqual('good');
1699
+
1700
+ // Testing referenced entity arrays...
1701
+ await Promise.all(testEntity.refArray?.map((e) => e.$wake()) || []);
1702
+ expect(testEntity.refArray?.[0].test).toEqual('good');
1703
+ });
1704
+
1705
+ it('ref', async () => {
1706
+ await createTestEntities();
1707
+
1708
+ // Retrieving entity by reference...
1709
+ const resultEntity = await nymph.getEntities(
1710
+ { class: TestModel },
1711
+ { type: '&', ref: ['reference', refGuid] },
1712
+ );
1713
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1714
+ });
1715
+
1716
+ it('not ref', async () => {
1717
+ await createTestEntities();
1718
+
1719
+ // Retrieving entity by !reference...
1720
+ const resultEntity = await nymph.getEntities(
1721
+ { class: TestModel },
1722
+ { type: '&', tag: 'test' },
1723
+ { type: '!&', ref: ['reference', guid()] },
1724
+ );
1725
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1726
+ });
1727
+
1728
+ it('wrong ref', async () => {
1729
+ await createTestEntities();
1730
+
1731
+ // Testing wrong reference...
1732
+ const resultEntity = await nymph.getEntities(
1733
+ { class: TestModel },
1734
+ { type: '&', ref: ['reference', guid()] },
1735
+ );
1736
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1737
+ });
1738
+
1739
+ it('nonexistent ref', async () => {
1740
+ await createTestEntities();
1741
+
1742
+ // Testing non-existent reference...
1743
+ const resultEntity = await nymph.getEntities(
1744
+ { class: TestModel },
1745
+ { type: '&', ref: ['pickle', refGuid] },
1746
+ );
1747
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1748
+ });
1749
+
1750
+ it('inclusive ref', async () => {
1751
+ await createTestEntities();
1752
+
1753
+ // Retrieving entity by inclusive reference...
1754
+ const resultEntity = await nymph.getEntities(
1755
+ { class: TestModel },
1756
+ {
1757
+ type: '|',
1758
+ ref: [
1759
+ ['reference', refGuid],
1760
+ ['reference', guid()],
1761
+ ],
1762
+ },
1763
+ );
1764
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1765
+ });
1766
+
1767
+ it('wrong inclusive ref', async () => {
1768
+ await createTestEntities();
1769
+
1770
+ // Testing wrong inclusive reference...
1771
+ const resultEntity = await nymph.getEntities(
1772
+ { class: TestModel },
1773
+ {
1774
+ type: '|',
1775
+ ref: [
1776
+ ['reference', guid()],
1777
+ ['reference', guid()],
1778
+ ],
1779
+ },
1780
+ );
1781
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1782
+ });
1783
+
1784
+ it('ref in an array', async () => {
1785
+ await createTestEntities();
1786
+
1787
+ // Retrieving entity by array reference...
1788
+ const resultEntity = await nymph.getEntities(
1789
+ { class: TestModel },
1790
+ { type: '&', ref: ['refArray', refGuid] },
1791
+ );
1792
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1793
+ });
1794
+
1795
+ it('wrong ref in an array', async () => {
1796
+ await createTestEntities();
1797
+
1798
+ // Testing wrong array reference...
1799
+ const resultEntity = await nymph.getEntities(
1800
+ { class: TestModel },
1801
+ {
1802
+ type: '&',
1803
+ ref: [
1804
+ ['refArray', refGuid],
1805
+ ['refArray', guid()],
1806
+ ],
1807
+ },
1808
+ );
1809
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
1810
+ });
1811
+
1812
+ it('logic operations', async () => {
1813
+ await createTestEntities();
1814
+
1815
+ // Testing logic operations...
1816
+ const resultEntity = await nymph.getEntities(
1817
+ { class: TestModel },
1818
+ {
1819
+ type: '&',
1820
+ '!ref': [
1821
+ ['refArray', guid()],
1822
+ ['refArray', guid()],
1823
+ ],
1824
+ '!lte': ['number', 29.99],
1825
+ },
1826
+ {
1827
+ type: '|',
1828
+ '!lte': [
1829
+ ['number', 29.99],
1830
+ ['number', 30],
1831
+ ],
1832
+ },
1833
+ {
1834
+ type: '!&',
1835
+ '!equal': ['string', 'test'],
1836
+ '!contain': [
1837
+ ['array', 'full'],
1838
+ ['array', 'of'],
1839
+ ['array', 'values'],
1840
+ ['array', 500],
1841
+ ['array', { test: true }],
1842
+ ['array', { nullbyte: '\\\x00\u0000 \x00' }],
1843
+ ],
1844
+ },
1845
+ {
1846
+ type: '!|',
1847
+ '!equal': ['string', 'test'],
1848
+ contain: [
1849
+ ['array', 'full'],
1850
+ ['array', 'of'],
1851
+ ['array', 'values'],
1852
+ ['array', 500],
1853
+ ],
1854
+ },
1855
+ );
1856
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
1857
+ });
1858
+
1859
+ it('count return', async () => {
1860
+ await createTestEntities();
1861
+
1862
+ const result = await nymph.getEntities({ class: TestModel });
1863
+
1864
+ // Testing count return...
1865
+ const resultCount = await nymph.getEntities({
1866
+ class: TestModel,
1867
+ return: 'count',
1868
+ });
1869
+ expect(resultCount).toBeGreaterThanOrEqual(1);
1870
+ expect(resultCount).toEqual(result.length);
1871
+
1872
+ const resultSelectors = await nymph.getEntities(
1873
+ { class: TestModel },
1874
+ { type: '&', ref: ['reference', refGuid] },
1875
+ );
1876
+
1877
+ // Testing count return with selectors...
1878
+ const resultSelectorsCount = await nymph.getEntities(
1879
+ { class: TestModel, return: 'count' },
1880
+ { type: '&', ref: ['reference', refGuid] },
1881
+ );
1882
+ expect(resultSelectorsCount).toBeGreaterThanOrEqual(1);
1883
+ expect(resultSelectorsCount).toEqual(resultSelectors.length);
1884
+
1885
+ // Testing count return with limit...
1886
+ const resultSelectorsLimit = await nymph.getEntities({
1887
+ class: TestModel,
1888
+ limit: 1,
1889
+ return: 'count',
1890
+ });
1891
+ expect(resultSelectorsLimit).toEqual(1);
1892
+
1893
+ // Testing count return with limit...
1894
+ const resultSelectorsSingle = await nymph.getEntity({
1895
+ class: TestModel,
1896
+ return: 'count',
1897
+ });
1898
+ expect(resultSelectorsSingle).toEqual(1);
1899
+
1900
+ // Testing empty count...
1901
+ const resultSelectorsEmpty = await nymph.getEntities(
1902
+ { class: TestModel, return: 'count' },
1903
+ { type: '&', ref: ['reference', guid()] },
1904
+ );
1905
+ expect(resultSelectorsEmpty).toEqual(0);
1906
+ });
1907
+
1908
+ it('guid return', async () => {
1909
+ await createTestEntities();
1910
+
1911
+ // Testing guid return using logic operations...
1912
+ const resultGuid = await nymph.getEntities(
1913
+ { class: TestModel, return: 'guid' },
1914
+ {
1915
+ type: '&',
1916
+ '!ref': [
1917
+ ['refArray', guid()],
1918
+ ['refArray', guid()],
1919
+ ],
1920
+ '!lte': ['number', 29.99],
1921
+ },
1922
+ {
1923
+ type: '|',
1924
+ '!lte': [
1925
+ ['number', 29.99],
1926
+ ['number', 30],
1927
+ ],
1928
+ },
1929
+ {
1930
+ type: '!&',
1931
+ '!equal': ['string', 'test'],
1932
+ '!contain': [
1933
+ ['array', 'full'],
1934
+ ['array', 'of'],
1935
+ ['array', 'values'],
1936
+ ['array', 500],
1937
+ ['array', { test: true }],
1938
+ ['array', { nullbyte: '\\\x00\u0000 \x00' }],
1939
+ ],
1940
+ },
1941
+ {
1942
+ type: '!|',
1943
+ '!equal': ['string', 'test'],
1944
+ contain: [
1945
+ ['array', 'full'],
1946
+ ['array', 'of'],
1947
+ ['array', 'values'],
1948
+ ['array', 500],
1949
+ ],
1950
+ },
1951
+ );
1952
+ expect(resultGuid.indexOf(testEntity.guid ?? '')).toBeGreaterThan(-1);
1953
+ });
1954
+
1955
+ it('object return', async () => {
1956
+ await createTestEntities();
1957
+
1958
+ // Testing object return using logic operations...
1959
+ const resultObjects = await nymph.getEntities(
1960
+ { class: TestModel, return: 'object' },
1961
+ {
1962
+ type: '&',
1963
+ '!ref': [
1964
+ ['refArray', guid()],
1965
+ ['refArray', guid()],
1966
+ ],
1967
+ '!lte': ['number', 29.99],
1968
+ },
1969
+ {
1970
+ type: '|',
1971
+ '!lte': [
1972
+ ['number', 29.99],
1973
+ ['number', 30],
1974
+ ],
1975
+ },
1976
+ {
1977
+ type: '!&',
1978
+ '!equal': ['string', 'test'],
1979
+ '!contain': [
1980
+ ['array', 'full'],
1981
+ ['array', 'of'],
1982
+ ['array', 'values'],
1983
+ ['array', 500],
1984
+ ['array', { test: true }],
1985
+ ['array', { nullbyte: '\\\x00\u0000 \x00' }],
1986
+ ],
1987
+ },
1988
+ {
1989
+ type: '!|',
1990
+ '!equal': ['string', 'test'],
1991
+ contain: [
1992
+ ['array', 'full'],
1993
+ ['array', 'of'],
1994
+ ['array', 'values'],
1995
+ ['array', 500],
1996
+ ],
1997
+ },
1998
+ );
1999
+
2000
+ const resultObject = resultObjects.find(
2001
+ (entity) => entity.guid === testEntity.guid,
2002
+ );
2003
+
2004
+ expect(resultObject).toBeInstanceOf(Object);
2005
+ expect(resultObject).not.toBeInstanceOf(TestModel);
2006
+ expect(Array.isArray(resultObject?.tags)).toBeTruthy();
2007
+ expect(resultObject?.string).toEqual('test');
2008
+ });
2009
+
2010
+ it('deep selector', async () => {
2011
+ await createTestEntities();
2012
+
2013
+ // Testing deep selectors...
2014
+ const resultEntity = await nymph.getEntities(
2015
+ { class: TestModel },
2016
+ {
2017
+ type: '&',
2018
+ '!ref': [
2019
+ ['refArray', guid()],
2020
+ ['refArray', guid()],
2021
+ ],
2022
+ '!lte': ['number', 29.99],
2023
+ },
2024
+ {
2025
+ type: '&',
2026
+ selector: [
2027
+ {
2028
+ type: '|',
2029
+ '!lte': [
2030
+ ['number', 29.99],
2031
+ ['number', 30],
2032
+ ],
2033
+ },
2034
+ {
2035
+ type: '!&',
2036
+ '!equal': ['string', 'test'],
2037
+ '!contain': [
2038
+ ['array', 'full'],
2039
+ ['array', 'of'],
2040
+ ['array', 'values'],
2041
+ ['array', 500],
2042
+ ['array', { test: true }],
2043
+ ['array', { nullbyte: '\\\x00\u0000 \x00' }],
2044
+ ],
2045
+ },
2046
+ {
2047
+ type: '!|',
2048
+ '!equal': ['string', 'test'],
2049
+ contain: [
2050
+ ['array', 'full'],
2051
+ ['array', 'of'],
2052
+ ['array', 'values'],
2053
+ ['array', 500],
2054
+ ],
2055
+ },
2056
+ ],
2057
+ },
2058
+ );
2059
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
2060
+
2061
+ const resultEntity2 = await nymph.getEntities(
2062
+ { class: TestModel },
2063
+ {
2064
+ type: '&',
2065
+ '!ref': [
2066
+ ['refArray', guid()],
2067
+ ['refArray', guid()],
2068
+ ],
2069
+ '!lte': ['number', 29.99],
2070
+ },
2071
+ {
2072
+ type: '|',
2073
+ selector: [
2074
+ {
1543
2075
  type: '&',
1544
- selector: { type: '&', gte: ['number', 16000] },
2076
+ '!lte': [
2077
+ ['number', 29.99],
2078
+ ['number', 30],
2079
+ ],
1545
2080
  },
1546
- },
1547
- ],
1548
- }
1549
- );
1550
- expect(testEntity.$inArray(resultEntity4)).toEqual(true);
1551
- });
2081
+ {
2082
+ type: '!&',
2083
+ '!equal': ['string', 'test'],
2084
+ '!contain': [
2085
+ ['array', 'full'],
2086
+ ['array', 'of'],
2087
+ ['array', 'values'],
2088
+ ['array', 500],
2089
+ ['array', { test: true }],
2090
+ ['array', { nullbyte: '\\\x00\u0000 \x00' }],
2091
+ ],
2092
+ },
2093
+ {
2094
+ type: '&',
2095
+ '!equal': ['string', 'test'],
2096
+ contain: [
2097
+ ['array', 'full'],
2098
+ ['array', 'of'],
2099
+ ['array', 'values'],
2100
+ ['array', 500],
2101
+ ],
2102
+ },
2103
+ ],
2104
+ },
2105
+ );
2106
+ expect(testEntity.$inArray(resultEntity2)).toEqual(true);
2107
+
2108
+ const resultEntity3 = await nymph.getEntities(
2109
+ { class: TestModel },
2110
+ {
2111
+ type: '|',
2112
+ selector: [
2113
+ {
2114
+ type: '&',
2115
+ '!ref': ['refArray', guid()],
2116
+ '!lte': ['number', 29.99],
2117
+ },
2118
+ { type: '&', gte: ['number', 16000] },
2119
+ ],
2120
+ },
2121
+ );
2122
+ expect(testEntity.$inArray(resultEntity3)).toEqual(true);
2123
+
2124
+ const resultEntity4 = await nymph.getEntities(
2125
+ { class: TestModel },
2126
+ {
2127
+ type: '|',
2128
+ selector: [
2129
+ {
2130
+ type: '&',
2131
+ '!ref': ['refArray', guid()],
2132
+ '!lte': ['number', 29.99],
2133
+ },
2134
+ {
2135
+ type: '&',
2136
+ selector: {
2137
+ type: '&',
2138
+ selector: { type: '&', gte: ['number', 16000] },
2139
+ },
2140
+ },
2141
+ ],
2142
+ },
2143
+ );
2144
+ expect(testEntity.$inArray(resultEntity4)).toEqual(true);
2145
+ });
1552
2146
 
1553
- it('wrong deep selector', async () => {
1554
- // Testing wrong deep selectors...
1555
- const resultEntity = await nymph.getEntities(
1556
- { class: TestModel },
1557
- {
1558
- type: '&',
1559
- selector: [
1560
- {
1561
- type: '&',
1562
- '!ref': ['refArray', guid()],
1563
- '!lte': ['number', 29.99],
1564
- },
1565
- { type: '&', gte: ['number', 16000] },
1566
- ],
1567
- }
1568
- );
1569
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1570
- });
2147
+ it('wrong deep selector', async () => {
2148
+ // Testing wrong deep selectors...
2149
+ const resultEntity = await nymph.getEntities(
2150
+ { class: TestModel },
2151
+ {
2152
+ type: '&',
2153
+ selector: [
2154
+ {
2155
+ type: '&',
2156
+ '!ref': ['refArray', guid()],
2157
+ '!lte': ['number', 29.99],
2158
+ },
2159
+ { type: '&', gte: ['number', 16000] },
2160
+ ],
2161
+ },
2162
+ );
2163
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
2164
+ });
1571
2165
 
1572
- it('qref', async () => {
1573
- await createTestEntities();
1574
-
1575
- // Retrieving entity by qref...
1576
- const resultEntity = await nymph.getEntities(
1577
- { class: TestModel },
1578
- {
1579
- type: '&',
1580
- qref: [
1581
- 'reference',
1582
- [{ class: TestModel }, { type: '&', equal: ['test', 'good'] }],
1583
- ],
1584
- }
1585
- );
1586
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1587
- });
2166
+ it('qref', async () => {
2167
+ await createTestEntities();
2168
+
2169
+ // Retrieving entity by qref...
2170
+ const resultEntity = await nymph.getEntities(
2171
+ { class: TestModel },
2172
+ {
2173
+ type: '&',
2174
+ qref: [
2175
+ 'reference',
2176
+ [{ class: TestModel }, { type: '&', equal: ['test', 'good'] }],
2177
+ ],
2178
+ },
2179
+ );
2180
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
2181
+ });
1588
2182
 
1589
- it('not qref', async () => {
1590
- await createTestEntities();
1591
-
1592
- // Retrieving entity by !qref...
1593
- const resultEntity = await nymph.getEntities(
1594
- { class: TestModel },
1595
- {
1596
- type: '&',
1597
- '!qref': [
1598
- 'reference',
1599
- [{ class: TestModel }, { type: '&', equal: ['test', 'pickles'] }],
1600
- ],
1601
- }
1602
- );
1603
- expect(testEntity.$inArray(resultEntity)).toEqual(true);
1604
- });
2183
+ it('not qref', async () => {
2184
+ await createTestEntities();
2185
+
2186
+ // Retrieving entity by !qref...
2187
+ const resultEntity = await nymph.getEntities(
2188
+ { class: TestModel },
2189
+ {
2190
+ type: '&',
2191
+ '!qref': [
2192
+ 'reference',
2193
+ [{ class: TestModel }, { type: '&', equal: ['test', 'pickles'] }],
2194
+ ],
2195
+ },
2196
+ );
2197
+ expect(testEntity.$inArray(resultEntity)).toEqual(true);
2198
+ });
1605
2199
 
1606
- it('wrong qref class', async () => {
1607
- await createTestEntities();
1608
-
1609
- // Testing wrong qref...
1610
- const resultEntity = await nymph.getEntities(
1611
- { class: TestModel },
1612
- {
1613
- type: '&',
1614
- qref: [
1615
- 'reference',
1616
- [{ class: TestBModel }, { type: '&', equal: ['test', 'good'] }],
1617
- ],
1618
- }
1619
- );
1620
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1621
- });
2200
+ it('wrong qref class', async () => {
2201
+ await createTestEntities();
2202
+
2203
+ // Testing wrong qref...
2204
+ const resultEntity = await nymph.getEntities(
2205
+ { class: TestModel },
2206
+ {
2207
+ type: '&',
2208
+ qref: [
2209
+ 'reference',
2210
+ [{ class: TestBModel }, { type: '&', equal: ['test', 'good'] }],
2211
+ ],
2212
+ },
2213
+ );
2214
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
2215
+ });
2216
+
2217
+ it('wrong qref data', async () => {
2218
+ await createTestEntities();
2219
+
2220
+ // Testing wrong qref...
2221
+ const resultEntity = await nymph.getEntities(
2222
+ { class: TestModel },
2223
+ {
2224
+ type: '&',
2225
+ qref: [
2226
+ 'reference',
2227
+ [{ class: TestModel }, { type: '&', equal: ['test', 'pickles'] }],
2228
+ ],
2229
+ },
2230
+ );
2231
+ expect(testEntity.$inArray(resultEntity)).toEqual(false);
2232
+ });
1622
2233
 
1623
- it('wrong qref data', async () => {
1624
- await createTestEntities();
1625
-
1626
- // Testing wrong qref...
1627
- const resultEntity = await nymph.getEntities(
1628
- { class: TestModel },
1629
- {
1630
- type: '&',
1631
- qref: [
1632
- 'reference',
1633
- [{ class: TestModel }, { type: '&', equal: ['test', 'pickles'] }],
1634
- ],
2234
+ it('cdate and mdate sort option', async () => {
2235
+ await createMultipleTestEntities();
2236
+
2237
+ for (const sort of ['cdate', 'mdate'] as ('cdate' | 'mdate')[]) {
2238
+ // These ones might have the same dates (saved at exactly the same time)
2239
+ // so we use >= and <= instead of > and <.
2240
+ // Retrieving entities sorted...
2241
+ let resultEntities = await nymph.getEntities({
2242
+ class: TestModel,
2243
+ sort,
2244
+ });
2245
+ expect(resultEntities.length).toBeGreaterThan(100);
2246
+ expect(resultEntities[resultEntities.length - 1][sort]).toBeGreaterThan(
2247
+ resultEntities[0][sort] ?? 0,
2248
+ );
2249
+ for (let i = 0; i < resultEntities.length - 1; i++) {
2250
+ expect(resultEntities[i + 1][sort]).toBeGreaterThanOrEqual(
2251
+ resultEntities[i][sort] ?? 0,
2252
+ );
2253
+ }
2254
+
2255
+ // And test the same with guid return...
2256
+ let resultGuids = await nymph.getEntities({
2257
+ class: TestModel,
2258
+ sort,
2259
+ return: 'guid',
2260
+ });
2261
+ expect(resultGuids.length).toBeGreaterThan(100);
2262
+ for (let i = 0; i < resultGuids.length - 1; i++) {
2263
+ expect(resultGuids[i]).toEqual(resultEntities[i].guid);
2264
+ }
2265
+
2266
+ // Retrieving entities reverse sorted...
2267
+ resultEntities = await nymph.getEntities({
2268
+ class: TestModel,
2269
+ sort,
2270
+ reverse: true,
2271
+ });
2272
+ expect(resultEntities.length).toBeGreaterThan(100);
2273
+ expect(resultEntities[resultEntities.length - 1][sort]).toBeLessThan(
2274
+ resultEntities[0][sort] ?? 0,
2275
+ );
2276
+ for (let i = 0; i < resultEntities.length - 1; i++) {
2277
+ expect(resultEntities[i + 1][sort]).toBeLessThanOrEqual(
2278
+ resultEntities[i][sort] ?? 0,
2279
+ );
2280
+ }
2281
+
2282
+ // And again with other selectors.
2283
+ // These ones should have different dates every time.
2284
+ // Retrieving entities sorted...
2285
+ resultEntities = await nymph.getEntities(
2286
+ { class: TestModel, sort },
2287
+ { type: '&', match: ['name', '^Multi Test '] },
2288
+ );
2289
+ expect(resultEntities.length).toEqual(100);
2290
+ for (let i = 0; i < resultEntities.length - 1; i++) {
2291
+ expect(resultEntities[i + 1][sort]).toBeGreaterThan(
2292
+ resultEntities[i][sort] ?? 0,
2293
+ );
2294
+ }
2295
+
2296
+ // Retrieving entities reverse sorted...
2297
+ resultEntities = await nymph.getEntities(
2298
+ { class: TestModel, sort, reverse: true },
2299
+ { type: '&', match: ['name', '^Multi Test '] },
2300
+ );
2301
+ expect(resultEntities.length).toEqual(100);
2302
+ for (let i = 0; i < resultEntities.length - 1; i++) {
2303
+ expect(resultEntities[i + 1][sort]).toBeLessThan(
2304
+ resultEntities[i][sort] ?? 0,
2305
+ );
2306
+ }
1635
2307
  }
1636
- );
1637
- expect(testEntity.$inArray(resultEntity)).toEqual(false);
1638
- });
2308
+ });
1639
2309
 
1640
- it('sort option', async () => {
1641
- await createMultipleTestEntities();
2310
+ it('property sort option', async () => {
2311
+ await createMultipleTestEntities();
1642
2312
 
1643
- for (const sort of ['cdate', 'mdate']) {
1644
2313
  // Retrieving entities sorted...
1645
2314
  let resultEntities = await nymph.getEntities({
1646
2315
  class: TestModel,
1647
- sort: sort as 'cdate' | 'mdate',
2316
+ sort: 'number',
1648
2317
  });
1649
2318
  expect(resultEntities.length).toBeGreaterThan(100);
1650
2319
  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);
2320
+ expect(resultEntities[i + 1].number ?? Infinity).toBeGreaterThanOrEqual(
2321
+ resultEntities[i].number ?? 0,
2322
+ );
1654
2323
  }
1655
2324
 
1656
2325
  // And test the same with guid return...
1657
2326
  let resultGuids = await nymph.getEntities({
1658
2327
  class: TestModel,
1659
- sort: sort as 'cdate' | 'mdate',
2328
+ sort: 'number',
1660
2329
  return: 'guid',
1661
2330
  });
1662
2331
  expect(resultGuids.length).toBeGreaterThan(100);
@@ -1667,228 +2336,630 @@ This one's zip code is 92064.`;
1667
2336
  // Retrieving entities reverse sorted...
1668
2337
  resultEntities = await nymph.getEntities({
1669
2338
  class: TestModel,
1670
- sort: sort as 'cdate' | 'mdate',
2339
+ sort: 'number',
1671
2340
  reverse: true,
1672
2341
  });
1673
2342
  expect(resultEntities.length).toBeGreaterThan(100);
1674
2343
  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
2344
+ expect(resultEntities[i + 1].number ?? 0).toBeLessThanOrEqual(
2345
+ resultEntities[i].number ?? Infinity,
1677
2346
  );
1678
2347
  }
1679
2348
 
1680
2349
  // And again with other selectors.
1681
2350
  // Retrieving entities sorted...
1682
2351
  resultEntities = await nymph.getEntities(
1683
- { class: TestModel, sort: sort as 'cdate' | 'mdate' },
1684
- { type: '&', match: ['name', '^Multi Test '] }
2352
+ { class: TestModel, sort: 'number' },
2353
+ { type: '&', match: ['name', '^Multi Test '] },
1685
2354
  );
1686
2355
  expect(resultEntities.length).toEqual(100);
1687
2356
  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);
2357
+ expect(resultEntities[i + 1].number ?? Infinity).toBeGreaterThan(
2358
+ resultEntities[i].number ?? 0,
2359
+ );
2360
+ expect(resultEntities[i].name).toEqual(
2361
+ `Multi Test ${100 - (resultEntities[i].number ?? 0)}`,
2362
+ );
1691
2363
  }
1692
2364
 
1693
2365
  // Retrieving entities reverse sorted...
1694
2366
  resultEntities = await nymph.getEntities(
1695
- { class: TestModel, sort: sort as 'cdate' | 'mdate', reverse: true },
1696
- { type: '&', match: ['name', '^Multi Test '] }
2367
+ { class: TestModel, sort: 'number', reverse: true },
2368
+ { type: '&', match: ['name', '^Multi Test '] },
1697
2369
  );
1698
2370
  expect(resultEntities.length).toEqual(100);
1699
2371
  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
2372
+ expect(resultEntities[i + 1].number ?? 0).toBeLessThan(
2373
+ resultEntities[i].number ?? Infinity,
2374
+ );
2375
+ expect(resultEntities[i].name).toEqual(
2376
+ `Multi Test ${100 - (resultEntities[i].number ?? 0)}`,
1702
2377
  );
1703
2378
  }
1704
- }
1705
- });
2379
+ });
1706
2380
 
1707
- it('delete reference', async () => {
1708
- await createTestEntities();
2381
+ it('delete reference', async () => {
2382
+ await createTestEntities();
1709
2383
 
1710
- // Deleting referenced entities...
1711
- expect(await testEntity.reference?.$delete()).toEqual(true);
1712
- expect(testEntity.reference?.guid).toBeNull();
1713
- });
2384
+ // Deleting referenced entities...
2385
+ await testEntity.reference?.$wake();
2386
+ await testEntity.reference?.$delete();
2387
+ await Promise.all(testEntity.refArray?.map((e) => e.$wake()) || []);
2388
+ expect(testEntity.reference?.guid).toBeNull();
2389
+ });
2390
+
2391
+ it('delete', async () => {
2392
+ await createTestEntities();
2393
+
2394
+ // Deleting entity...
2395
+ await testEntity.$delete();
2396
+ expect(testEntity.guid).toBeNull();
2397
+
2398
+ const entity = await nymph.getEntity(
2399
+ { class: TestModel },
2400
+ { type: '&', guid: testGuid },
2401
+ );
2402
+
2403
+ expect(entity).toBeNull();
2404
+ });
2405
+
2406
+ it('allows non-duplicate unique strings', async () => {
2407
+ // Creating entity...
2408
+ const uniqueEntityA = await TestModel.factory();
2409
+ uniqueEntityA.name = 'Entity Test ' + new Date().toLocaleString();
2410
+ uniqueEntityA.uniques = ['test a'];
2411
+
2412
+ // Saving entity...
2413
+ await uniqueEntityA.$save();
2414
+ expect(uniqueEntityA.guid).not.toBeNull();
2415
+
2416
+ // Creating entity...
2417
+ const uniqueEntityB = await TestModel.factory();
2418
+ uniqueEntityB.name = 'Entity Test ' + new Date().toLocaleString();
2419
+ uniqueEntityB.uniques = ['test b'];
2420
+
2421
+ // Saving entity...
2422
+ await uniqueEntityB.$save();
2423
+ expect(uniqueEntityB.guid).not.toBeNull();
2424
+
2425
+ expect(uniqueEntityA.guid).not.toEqual(uniqueEntityB.guid);
2426
+
2427
+ await uniqueEntityA.$delete();
2428
+ await uniqueEntityB.$delete();
2429
+ });
2430
+
2431
+ it('throws on duplicate unique strings', async () => {
2432
+ // Creating entity...
2433
+ const uniqueEntityA = await TestModel.factory();
2434
+ uniqueEntityA.name = 'Entity Test ' + new Date().toLocaleString();
2435
+ uniqueEntityA.uniques = ['test a'];
2436
+
2437
+ // Saving entity...
2438
+ await uniqueEntityA.$save();
2439
+ expect(uniqueEntityA.guid).not.toBeNull();
2440
+
2441
+ // Creating entity...
2442
+ const uniqueEntityB = await TestModel.factory();
2443
+ uniqueEntityB.name = 'Entity Test ' + new Date().toLocaleString();
2444
+ uniqueEntityB.uniques = ['test a'];
1714
2445
 
1715
- it('delete', async () => {
1716
- await createTestEntities();
2446
+ // Saving entity...
2447
+ try {
2448
+ await uniqueEntityB.$save();
2449
+
2450
+ throw Error("Shouldn't get past the uniqueness check.");
2451
+ } catch (e: any) {
2452
+ expect(e).toBeInstanceOf(EntityUniqueConstraintError);
2453
+ }
2454
+ expect(uniqueEntityB.guid).toBeNull();
2455
+
2456
+ await uniqueEntityA.$delete();
2457
+ });
2458
+
2459
+ it('allows duplicate unique string if first transaction is rolled back', async () => {
2460
+ // Creating transaction entity...
2461
+ const tnymphA = await nymph.startTransaction('test-unique-a');
2462
+ const TestModelA = tnymphA.getEntityClass(TestModel);
2463
+ const uniqueEntityA = await TestModelA.factory();
2464
+ uniqueEntityA.name = 'Entity Test ' + new Date().toLocaleString();
2465
+ uniqueEntityA.uniques = ['test a'];
2466
+
2467
+ // Saving entity...
2468
+ await uniqueEntityA.$save();
2469
+ expect(uniqueEntityA.guid).not.toBeNull();
1717
2470
 
1718
- // Deleting entity...
1719
- expect(await testEntity.$delete()).toEqual(true);
1720
- expect(testEntity.guid).toBeNull();
2471
+ // Rolling back transaction...
2472
+ expect(await tnymphA.rollback('test-unique-a')).toEqual(true);
1721
2473
 
1722
- const entity = await nymph.getEntity(
1723
- { class: TestModel },
1724
- { type: '&', guid: testGuid }
1725
- );
2474
+ // Creating transaction entity...
2475
+ const tnymphB = await nymph.startTransaction('test-unique-b');
2476
+ const TestModelB = tnymphB.getEntityClass(TestModel);
2477
+ const uniqueEntityB = await TestModelB.factory();
2478
+ uniqueEntityB.name = 'Entity Test ' + new Date().toLocaleString();
2479
+ uniqueEntityB.uniques = ['test a'];
1726
2480
 
1727
- expect(entity).toBeNull();
2481
+ // Saving entity...
2482
+ await uniqueEntityB.$save();
2483
+ expect(uniqueEntityB.guid).not.toBeNull();
2484
+
2485
+ expect(uniqueEntityA.guid).not.toEqual(uniqueEntityB.guid);
2486
+
2487
+ expect(await tnymphB.commit('test-unique-b')).toEqual(true);
2488
+
2489
+ const uniqueEntityACheck = await nymph.getEntity(
2490
+ { class: TestModel },
2491
+ { type: '&', guid: uniqueEntityA.guid ?? '' },
2492
+ );
2493
+ expect(uniqueEntityACheck).toBeNull();
2494
+
2495
+ const uniqueEntityBCheck = await nymph.getEntity(
2496
+ { class: TestModel },
2497
+ { type: '&', guid: uniqueEntityB.guid ?? '' },
2498
+ );
2499
+ expect(uniqueEntityBCheck).not.toBeNull();
2500
+
2501
+ if (uniqueEntityBCheck != null) {
2502
+ await uniqueEntityBCheck.$delete();
2503
+ }
2504
+ });
1728
2505
  });
1729
2506
  }
1730
2507
 
1731
2508
  export function UIDTest(
1732
2509
  nymph: Nymph,
1733
- it: (name: string, fn: () => void) => void
2510
+ describe: (name: string, fn: () => void) => void,
2511
+ it: (name: string, fn: () => void) => void,
1734
2512
  ) {
1735
- it('delete old test data', async () => {
1736
- expect(await nymph.deleteUID('TestUID')).toEqual(true);
1737
- expect(await nymph.deleteUID('NewUID')).toEqual(true);
1738
- });
2513
+ describe('UID', () => {
2514
+ it('delete old test data', async () => {
2515
+ expect(await nymph.deleteUID('TestUID')).toEqual(true);
2516
+ expect(await nymph.deleteUID('NewUID')).toEqual(true);
2517
+ });
1739
2518
 
1740
- it('new UID', async () => {
1741
- expect(await nymph.newUID('TestUID')).toEqual(1);
1742
- });
2519
+ it('new UID', async () => {
2520
+ expect(await nymph.newUID('TestUID')).toEqual(1);
2521
+ });
1743
2522
 
1744
- it('increment UID', async () => {
1745
- expect(await nymph.newUID('TestUID')).toEqual(2);
1746
- });
2523
+ it('increment UID', async () => {
2524
+ expect(await nymph.newUID('TestUID')).toEqual(2);
2525
+ });
1747
2526
 
1748
- it('retrieve UID', async () => {
1749
- expect(await nymph.getUID('TestUID')).toEqual(2);
1750
- });
2527
+ it('retrieve UID', async () => {
2528
+ expect(await nymph.getUID('TestUID')).toEqual(2);
2529
+ });
1751
2530
 
1752
- it('rename UID', async () => {
1753
- expect(await nymph.renameUID('TestUID', 'NewUID')).toEqual(true);
1754
- expect(await nymph.getUID('TestUID')).toBeNull();
1755
- expect(await nymph.getUID('NewUID')).toEqual(2);
1756
- expect(await nymph.renameUID('NewUID', 'TestUID')).toEqual(true);
1757
- expect(await nymph.getUID('NewUID')).toBeNull();
1758
- expect(await nymph.getUID('TestUID')).toEqual(2);
1759
- });
2531
+ it('rename UID', async () => {
2532
+ expect(await nymph.renameUID('TestUID', 'NewUID')).toEqual(true);
2533
+ expect(await nymph.getUID('TestUID')).toBeNull();
2534
+ expect(await nymph.getUID('NewUID')).toEqual(2);
2535
+ expect(await nymph.renameUID('NewUID', 'TestUID')).toEqual(true);
2536
+ expect(await nymph.getUID('NewUID')).toBeNull();
2537
+ expect(await nymph.getUID('TestUID')).toEqual(2);
2538
+ });
1760
2539
 
1761
- it('set UID', async () => {
1762
- expect(await nymph.setUID('TestUID', 5)).toEqual(true);
1763
- expect(await nymph.getUID('TestUID')).toEqual(5);
1764
- });
2540
+ it('set UID', async () => {
2541
+ expect(await nymph.setUID('TestUID', 5)).toEqual(true);
2542
+ expect(await nymph.getUID('TestUID')).toEqual(5);
2543
+ });
1765
2544
 
1766
- it('delete UID', async () => {
1767
- expect(await nymph.deleteUID('TestUID')).toEqual(true);
1768
- expect(await nymph.getUID('TestUID')).toBeNull();
2545
+ it('delete UID', async () => {
2546
+ expect(await nymph.deleteUID('TestUID')).toEqual(true);
2547
+ expect(await nymph.getUID('TestUID')).toBeNull();
2548
+ });
1769
2549
  });
1770
2550
  }
1771
2551
 
1772
2552
  export function ExportImportTest(
1773
2553
  nymph: Nymph,
1774
- it: (name: string, fn: () => void) => void
2554
+ describe: (name: string, fn: () => void) => void,
2555
+ it: (name: string, fn: () => void) => void,
1775
2556
  ) {
1776
- const TestModel = nymph.addEntityClass(TestModelClass);
1777
- const TestBModel = nymph.addEntityClass(TestBModelClass);
1778
-
1779
- async function deleteTestData() {
1780
- let all = await nymph.getEntities({ class: TestModel });
1781
- expect(Array.isArray(all)).toEqual(true);
1782
- for (const cur of all) {
1783
- expect(await cur.$delete()).toEqual(true);
1784
- }
2557
+ describe('Export/Import', () => {
2558
+ const TestModel = nymph.addEntityClass(TestModelClass);
2559
+ const TestBModel = nymph.addEntityClass(TestBModelClass);
2560
+
2561
+ async function deleteTestData() {
2562
+ let all = await nymph.getEntities({ class: TestModel });
2563
+ expect(Array.isArray(all)).toEqual(true);
2564
+ for (const cur of all) {
2565
+ await cur.$delete();
2566
+ }
1785
2567
 
1786
- all = await nymph.getEntities({ class: TestModel });
1787
- expect(all.length).toEqual(0);
2568
+ all = await nymph.getEntities({ class: TestModel });
2569
+ expect(all.length).toEqual(0);
1788
2570
 
1789
- all = await nymph.getEntities({ class: TestBModel });
1790
- expect(Array.isArray(all)).toEqual(true);
1791
- for (const cur of all) {
1792
- expect(await cur.$delete()).toEqual(true);
1793
- }
2571
+ all = await nymph.getEntities({ class: TestBModel });
2572
+ expect(Array.isArray(all)).toEqual(true);
2573
+ for (const cur of all) {
2574
+ await cur.$delete();
2575
+ }
1794
2576
 
1795
- all = await nymph.getEntities({ class: TestBModel });
1796
- expect(all.length).toEqual(0);
2577
+ all = await nymph.getEntities({ class: TestBModel });
2578
+ expect(all.length).toEqual(0);
1797
2579
 
1798
- expect(await nymph.deleteUID('TestUID')).toEqual(true);
1799
- expect(await nymph.deleteUID('TestUID2')).toEqual(true);
1800
- }
2580
+ expect(await nymph.deleteUID('TestUID')).toEqual(true);
2581
+ expect(await nymph.deleteUID('TestUID2')).toEqual(true);
2582
+ }
1801
2583
 
1802
- async function checkEntityDataAndCount() {
1803
- expect(await nymph.getUID('TestUID')).toEqual(2);
1804
- expect(await nymph.getUID('TestUID2')).toEqual(1);
2584
+ async function checkEntityDataAndCount() {
2585
+ expect(await nymph.getUID('TestUID')).toEqual(2);
2586
+ expect(await nymph.getUID('TestUID2')).toEqual(1);
1805
2587
 
1806
- const models = await nymph.getEntities({ class: TestModel });
1807
- const bmodels = await nymph.getEntities({ class: TestBModel });
2588
+ const models = await nymph.getEntities({ class: TestModel });
2589
+ const bmodels = await nymph.getEntities({ class: TestBModel });
1808
2590
 
1809
- expect(models.length).toEqual(30);
1810
- expect(bmodels.length).toEqual(10);
2591
+ expect(models.length).toEqual(30);
2592
+ expect(bmodels.length).toEqual(30);
1811
2593
 
1812
- const all = [...models, ...bmodels];
1813
- for (const model of all) {
1814
- if (model.index?.match(/^\d+a$/)) {
2594
+ for (const model of models) {
2595
+ expect(model.name).toMatch(/^Entity Test /);
2596
+ expect(model.null).toBeDefined();
1815
2597
  expect(model.null).toBeNull();
1816
2598
  expect(model.string).toEqual('test');
1817
- expect(model.array).toEqual(['full', 'of', 'values', 500]);
2599
+ expect(model.array).toEqual([
2600
+ 'full',
2601
+ 'of',
2602
+ 'values',
2603
+ 500,
2604
+ { test: true },
2605
+ { nullbyte: '\\\x00\u0000 \x00' },
2606
+ ]);
2607
+ expect(model.match).toEqual(matchValue);
1818
2608
  expect(model.number).toEqual(30);
1819
- expect(model.timestamp).toBeGreaterThanOrEqual(strtotime('-2 minutes'));
2609
+ expect(model.numberString).toEqual('30');
2610
+ expect(model.timestamp).toBeGreaterThanOrEqual(
2611
+ strtotime('-2 minutes') || 0,
2612
+ );
2613
+ expect(model.index).toMatch(/^\d+a$/);
1820
2614
 
2615
+ await model.reference?.$wake();
1821
2616
  expect(model.reference?.guid).not.toBeNull();
1822
2617
  expect(model.reference?.string).toEqual('another');
1823
- expect(model.reference?.index?.match(/^\d+b$/)).toBeTruthy();
2618
+ expect(model.reference?.index).toMatch(/^\d+b$/);
2619
+ expect(model.index?.substring(0, -1)).toEqual(
2620
+ model.reference?.index?.substring(0, -1),
2621
+ );
2622
+ expect(model.reference?.$inArray(bmodels)).toEqual(true);
2623
+ await Promise.all(model.refArray?.map((e) => e.$wake()) || []);
1824
2624
  expect(model.refArray?.[0].guid).not.toBeNull();
1825
2625
  expect(model.refArray?.[0].guid).toEqual(model.reference?.guid);
1826
2626
  }
1827
2627
  }
1828
- }
1829
2628
 
1830
- it('delete old test data', async () => {
1831
- await deleteTestData();
1832
- });
2629
+ it('delete old test data', async () => {
2630
+ await deleteTestData();
2631
+ });
1833
2632
 
1834
- it('setup data', async () => {
1835
- expect(await nymph.newUID('TestUID')).toEqual(1);
1836
- expect(await nymph.newUID('TestUID')).toEqual(2);
1837
- expect(await nymph.newUID('TestUID2')).toEqual(1);
2633
+ it('setup data', async () => {
2634
+ expect(await nymph.newUID('TestUID')).toEqual(1);
2635
+ expect(await nymph.newUID('TestUID')).toEqual(2);
2636
+ expect(await nymph.newUID('TestUID2')).toEqual(1);
1838
2637
 
1839
- for (let i = 0; i < 20; i++) {
1840
- const EntityClass = i < 15 ? TestModel : TestBModel;
2638
+ for (let i = 0; i < 30; i++) {
2639
+ // Creating entity...
2640
+ const testEntity = await TestModel.factory();
1841
2641
 
1842
- // Creating entity...
1843
- const testEntity = await EntityClass.factory();
2642
+ // Saving entity...
2643
+ testEntity.name = 'Entity Test ' + new Date().toLocaleString();
2644
+ testEntity.null = null;
2645
+ testEntity.string = 'test';
2646
+ testEntity.array = [
2647
+ 'full',
2648
+ 'of',
2649
+ 'values',
2650
+ 500,
2651
+ { test: true },
2652
+ { nullbyte: '\\\x00\u0000 \x00' },
2653
+ ];
2654
+ testEntity.match = matchValue;
2655
+ testEntity.number = 30;
2656
+ testEntity.numberString = '30';
2657
+ testEntity.timestamp = Date.now();
2658
+ testEntity.index = i + 'a';
2659
+
2660
+ const entityReferenceTest = await TestBModel.factory();
2661
+ entityReferenceTest.string = 'another';
2662
+ entityReferenceTest.index = i + 'b';
2663
+
2664
+ await entityReferenceTest.$save();
2665
+ testEntity.reference = entityReferenceTest;
2666
+ testEntity.refArray = [entityReferenceTest];
2667
+
2668
+ await testEntity.$save();
2669
+ }
1844
2670
 
1845
- // Saving entity...
1846
- testEntity.name = 'Entity Test ' + new Date().toLocaleString();
1847
- testEntity.null = null;
1848
- testEntity.string = 'test';
1849
- testEntity.array = ['full', 'of', 'values', 500];
1850
- testEntity.number = 30;
1851
- testEntity.timestamp = Date.now();
1852
- testEntity.index = i + 'a';
2671
+ await checkEntityDataAndCount();
2672
+ });
1853
2673
 
1854
- const entityReferenceTest = await EntityClass.factory();
1855
- entityReferenceTest.string = 'another';
1856
- entityReferenceTest.index = i + 'b';
2674
+ it('needs migration', async () => {
2675
+ expect(await nymph.needsMigration()).toEqual(false);
2676
+ });
1857
2677
 
1858
- expect(await entityReferenceTest.$save()).toEqual(true);
1859
- testEntity.reference = entityReferenceTest;
1860
- testEntity.refArray = [entityReferenceTest];
2678
+ it('export one entity', async () => {
2679
+ const firstEntity = await nymph.getEntity({ class: TestModel });
1861
2680
 
1862
- expect(await testEntity.$save()).toEqual(true);
1863
- }
2681
+ expect(firstEntity).not.toBeNull();
2682
+ expect(firstEntity?.guid).not.toBeNull();
1864
2683
 
1865
- await checkEntityDataAndCount();
1866
- });
2684
+ if (firstEntity == null || firstEntity.guid == null) {
2685
+ throw new Error('Just need this for TS.');
2686
+ }
1867
2687
 
1868
- it('export data', async () => {
1869
- expect(await nymph.export(__dirname + '/testentityexport.nex')).toEqual(
1870
- true
1871
- );
1872
- });
2688
+ let expectedExport = `{${firstEntity.guid}}<${TestModel.ETYPE}>[${firstEntity?.tags.join(',')}]\n`;
2689
+ expectedExport += `\tcdate=${firstEntity.cdate}\n`;
2690
+ expectedExport += `\tmdate=${firstEntity.mdate}\n`;
2691
+ for (let [name, value] of Object.entries(firstEntity.$getData(true)).sort(
2692
+ (a, b) => a[0].localeCompare(b[0]),
2693
+ )) {
2694
+ expectedExport += `\t${name}=${JSON.stringify(value)}\n`;
2695
+ }
1873
2696
 
1874
- it('delete test data again', async () => {
1875
- await deleteTestData();
1876
- });
2697
+ const entityExport = await nymph.exportEntity(
2698
+ TestModel.ETYPE,
2699
+ firstEntity.guid,
2700
+ );
2701
+
2702
+ expect(entityExport).toEqual(expectedExport);
2703
+ });
1877
2704
 
1878
- it('import data', async () => {
1879
- expect(await nymph.getUID('TestUID')).toBeNull();
1880
- expect(await nymph.getUID('TestUID2')).toBeNull();
1881
- const models = await nymph.getEntities({ class: TestModel });
1882
- const bmodels = await nymph.getEntities({ class: TestBModel });
1883
- expect(models.length).toEqual(0);
1884
- expect(bmodels.length).toEqual(0);
2705
+ it('export data', async () => {
2706
+ expect(await nymph.export(__dirname + '/testentityexport.nex')).toEqual(
2707
+ true,
2708
+ );
2709
+ });
1885
2710
 
1886
- expect(await nymph.import(__dirname + '/testentityexport.nex')).toEqual(
1887
- true
1888
- );
2711
+ it('delete test data again', async () => {
2712
+ await deleteTestData();
2713
+ });
1889
2714
 
1890
- await checkEntityDataAndCount();
2715
+ it('import data', async () => {
2716
+ expect(await nymph.getUID('TestUID')).toBeNull();
2717
+ expect(await nymph.getUID('TestUID2')).toBeNull();
2718
+ const models = await nymph.getEntities({ class: TestModel });
2719
+ const bmodels = await nymph.getEntities({ class: TestBModel });
2720
+ expect(models.length).toEqual(0);
2721
+ expect(bmodels.length).toEqual(0);
1891
2722
 
1892
- fs.unlinkSync(__dirname + '/testentityexport.nex');
2723
+ expect(
2724
+ await nymph.import(__dirname + '/testentityexport.nex', {
2725
+ ignoreUnknownETypes: true,
2726
+ }),
2727
+ ).toEqual(true);
2728
+
2729
+ await checkEntityDataAndCount();
2730
+
2731
+ fs.unlinkSync(__dirname + '/testentityexport.nex');
2732
+ });
2733
+
2734
+ it('import tokens only', async () => {
2735
+ const model = await nymph.getEntity({ class: TestModel });
2736
+
2737
+ expect(model).not.toBeNull();
2738
+
2739
+ if (model != null) {
2740
+ const data = entityConstructorsToClassNames(
2741
+ entitiesToReferences(model.$getData(true), true),
2742
+ );
2743
+ // These should not actually be saved in the DB.
2744
+ data.number = 424242424242;
2745
+ // But this should become searchable.
2746
+ data.search = 'peanuts and pickles on a hot bun';
2747
+
2748
+ const sdata = Object.fromEntries(
2749
+ Object.entries(data).map(([name, value]) => [
2750
+ name,
2751
+ JSON.stringify(value),
2752
+ ]),
2753
+ );
2754
+
2755
+ if (model.guid == null || model.cdate == null || model.mdate == null) {
2756
+ throw new Error('Model data is wrong.');
2757
+ }
2758
+
2759
+ await nymph.importEntityTokens({
2760
+ guid: model.guid,
2761
+ // Again, these should not actually be changed in the DB.
2762
+ cdate: model.cdate + 1000,
2763
+ mdate: model.mdate + 1000,
2764
+ tags: [...model.tags, 'helicopter'],
2765
+ sdata,
2766
+ etype: TestModel.ETYPE,
2767
+ });
2768
+
2769
+ const modelCheck = await nymph.getEntity(
2770
+ { class: TestModel },
2771
+ {
2772
+ type: '&',
2773
+ search: ['search', '"peanuts and pickles on a hot bun"'],
2774
+ },
2775
+ );
2776
+
2777
+ expect(modelCheck?.guid).toEqual(model.guid);
2778
+ expect(modelCheck?.cdate).toEqual(model.cdate);
2779
+ expect(modelCheck?.mdate).toEqual(model.mdate);
2780
+ expect(modelCheck?.$hasTag('helicopter')).toEqual(false);
2781
+ expect(modelCheck?.number).not.toEqual(424242424242);
2782
+ expect(modelCheck?.search).not.toEqual(
2783
+ 'peanuts and pickles on a hot bun',
2784
+ );
2785
+ }
2786
+ });
1893
2787
  });
1894
2788
  }
2789
+
2790
+ 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.
2791
+
2792
+ This one's email address is nice_hat-wednesday+newyork@im-a-hat.hat.
2793
+ This one's phone number is (555) 555-1818.
2794
+ This one's zip code is 92064.
2795
+ This one's favorite emojis are 🔥❤️😊😂⭐🤔
2796
+
2797
+ These hats are absolutely fantastic.
2798
+
2799
+ \x00\x00\x00
2800
+
2801
+ 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.
2802
+
2803
+ 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.
2804
+
2805
+ 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.
2806
+
2807
+ 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.
2808
+
2809
+ 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.
2810
+
2811
+ 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.
2812
+
2813
+ 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.
2814
+
2815
+ 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.
2816
+
2817
+ 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.
2818
+
2819
+ 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.
2820
+
2821
+ 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.
2822
+
2823
+ 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.
2824
+
2825
+ 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.
2826
+
2827
+ 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.
2828
+
2829
+ 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.
2830
+
2831
+ 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.
2832
+
2833
+ 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.
2834
+
2835
+ 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.
2836
+
2837
+ 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.
2838
+
2839
+ 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.
2840
+
2841
+ 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.
2842
+
2843
+ 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.
2844
+
2845
+ 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.
2846
+
2847
+ 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.
2848
+
2849
+ 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.
2850
+
2851
+ 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.
2852
+
2853
+ 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.
2854
+
2855
+ 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.
2856
+
2857
+ 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.
2858
+
2859
+ 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?
2860
+
2861
+ 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.
2862
+
2863
+ 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.
2864
+
2865
+ 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.
2866
+
2867
+ 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.
2868
+
2869
+ 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.
2870
+
2871
+ 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.
2872
+
2873
+ 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.
2874
+
2875
+ 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.
2876
+
2877
+ 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.
2878
+
2879
+ 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.
2880
+
2881
+ 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.
2882
+
2883
+ 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.
2884
+
2885
+ 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.
2886
+
2887
+ 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.
2888
+
2889
+ 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.
2890
+
2891
+ 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.
2892
+
2893
+ 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.
2894
+
2895
+ 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.
2896
+
2897
+ 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.
2898
+
2899
+ 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.`;
2900
+
2901
+ const searchValue = `In Congress, July 4, 1776
2902
+
2903
+ The unanimous Declaration of the thirteen united States of America, When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.
2904
+
2905
+ We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness.--That to secure these rights, Governments are instituted among Men, deriving their just powers from the consent of the governed, --That whenever any Form of Government becomes destructive of these ends, it is the Right of the People to alter or to abolish it, and to institute new Government, laying its foundation on such principles and organizing its powers in such form, as to them shall seem most likely to effect their Safety and Happiness. Prudence, indeed, will dictate that Governments long established should not be changed for light and transient causes; and accordingly all experience hath shewn, that mankind are more disposed to suffer, while evils are sufferable, than to right themselves by abolishing the forms to which they are accustomed. But when a long train of abuses and usurpations, pursuing invariably the same Object evinces a design to reduce them under absolute Despotism, it is their right, it is their duty, to throw off such Government, and to provide new Guards for their future security.--Such has been the patient sufferance of these Colonies; and such is now the necessity which constrains them to alter their former Systems of Government. The history of the present King of Great Britain is a history of repeated injuries and usurpations, all having in direct object the establishment of an absolute Tyranny over these States. To prove this, let Facts be submitted to a candid world.
2906
+
2907
+ He has refused his Assent to Laws, the most wholesome and necessary for the public good.
2908
+
2909
+ He has forbidden his Governors to pass Laws of immediate and pressing importance, unless suspended in their operation till his Assent should be obtained; and when so suspended, he has utterly neglected to attend to them.
2910
+
2911
+ He has refused to pass other Laws for the accommodation of large districts of people, unless those people would relinquish the right of Representation in the Legislature, a right inestimable to them and formidable to tyrants only.
2912
+
2913
+ He has called together legislative bodies at places unusual, uncomfortable, and distant from the depository of their public Records, for the sole purpose of fatiguing them into compliance with his measures.
2914
+
2915
+ He has dissolved Representative Houses repeatedly, for opposing with manly firmness his invasions on the rights of the people.
2916
+
2917
+ He has refused for a long time, after such dissolutions, to cause others to be elected; whereby the Legislative powers, incapable of Annihilation, have returned to the People at large for their exercise; the State remaining in the mean time exposed to all the dangers of invasion from without, and convulsions within.
2918
+
2919
+ He has endeavoured to prevent the population of these States; for that purpose obstructing the Laws for Naturalization of Foreigners; refusing to pass others to encourage their migrations hither, and raising the conditions of new Appropriations of Lands.
2920
+
2921
+ He has obstructed the Administration of Justice, by refusing his Assent to Laws for establishing Judiciary powers.
2922
+
2923
+ He has made Judges dependent on his Will alone, for the tenure of their offices, and the amount and payment of their salaries.
2924
+
2925
+ He has erected a multitude of New Offices, and sent hither swarms of Officers to harrass our people, and eat out their substance.
2926
+
2927
+ He has kept among us, in times of peace, Standing Armies without the Consent of our legislatures.
2928
+
2929
+ He has affected to render the Military independent of and superior to the Civil power.
2930
+
2931
+ He has combined with others to subject us to a jurisdiction foreign to our constitution, and unacknowledged by our laws; giving his Assent to their Acts of pretended Legislation:
2932
+
2933
+ For Quartering large bodies of armed troops among us:
2934
+
2935
+ For protecting them, by a mock Trial, from punishment for any Murders which they should commit on the Inhabitants of these States:
2936
+
2937
+ For cutting off our Trade with all parts of the world:
2938
+
2939
+ For imposing Taxes on us without our Consent:
2940
+
2941
+ For depriving us in many cases, of the benefits of Trial by Jury:
2942
+
2943
+ For transporting us beyond Seas to be tried for pretended offences:
2944
+
2945
+ For abolishing the free System of English Laws in a neighbouring Province, establishing therein an Arbitrary government, and enlarging its Boundaries so as to render it at once an example and fit instrument for introducing the same absolute rule into these Colonies:
2946
+
2947
+ For taking away our Charters, abolishing our most valuable Laws, and altering fundamentally the Forms of our Governments:
2948
+
2949
+ For suspending our own Legislatures, and declaring themselves invested with power to legislate for us in all cases whatsoever.
2950
+
2951
+ He has abdicated Government here, by declaring us out of his Protection and waging War against us.
2952
+
2953
+ He has plundered our seas, ravaged our Coasts, burnt our towns, and destroyed the lives of our people.
2954
+
2955
+ He is at this time transporting large Armies of foreign Mercenaries to compleat the works of death, desolation and tyranny, already begun with circumstances of Cruelty & perfidy scarcely paralleled in the most barbarous ages, and totally unworthy the Head of a civilized nation.
2956
+
2957
+ He has constrained our fellow Citizens taken Captive on the high Seas to bear Arms against their Country, to become the executioners of their friends and Brethren, or to fall themselves by their Hands.
2958
+
2959
+ He has excited domestic insurrections amongst us, and has endeavoured to bring on the inhabitants of our frontiers, the merciless Indian Savages, whose known rule of warfare, is an undistinguished destruction of all ages, sexes and conditions.
2960
+
2961
+ In every stage of these Oppressions We have Petitioned for Redress in the most humble terms: Our repeated Petitions have been answered only by repeated injury. A Prince, whose character is thus marked by every act which may define a Tyrant, is unfit to be the ruler of a free people.
2962
+
2963
+ Nor have We been wanting in attentions to our Brittish brethren. We have warned them from time to time of attempts by their legislature to extend an unwarrantable jurisdiction over us. We have reminded them of the circumstances of our emigration and settlement here. We have appealed to their native justice and magnanimity, and we have conjured them by the ties of our common kindred to disavow these usurpations, which, would inevitably interrupt our connections and correspondence. They too have been deaf to the voice of justice and of consanguinity. We must, therefore, acquiesce in the necessity, which denounces our Separation, and hold them, as we hold the rest of mankind, Enemies in War, in Peace Friends.
2964
+
2965
+ We, therefore, the Representatives of the united States of America, in General Congress, Assembled, appealing to the Supreme Judge of the world for the rectitude of our intentions, do, in the Name, and by Authority of the good People of these Colonies, solemnly publish and declare, That these United Colonies are, and of Right ought to be Free and Independent States; that they are Absolved from all Allegiance to the British Crown, and that all political connection between them and the State of Great Britain, is and ought to be totally dissolved; and that as Free and Independent States, they have full Power to levy War, conclude Peace, contract Alliances, establish Commerce, and to do all other Acts and Things which Independent States may of right do. And for the support of this Declaration, with a firm reliance on the protection of divine Providence, we mutually pledge to each other our Lives, our Fortunes and our sacred Honor.`;