@nymphjs/nymph 1.0.0-beta.61 → 1.0.0-beta.63
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.
- package/CHANGELOG.md +15 -0
- package/dist/Entity.js +133 -103
- package/dist/Entity.js.map +1 -1
- package/dist/Entity.test.js +1 -1
- package/dist/Entity.test.js.map +1 -1
- package/dist/Nymph.js +63 -48
- package/dist/Nymph.js.map +1 -1
- package/dist/driver/NymphDriver.d.ts +20 -3
- package/dist/driver/NymphDriver.js +107 -76
- package/dist/driver/NymphDriver.js.map +1 -1
- package/dist/driver/testArtifacts.js +53 -26
- package/dist/driver/testArtifacts.js.map +1 -1
- package/dist/errors/EntityInvalidDataError.js +1 -1
- package/dist/errors/EntityInvalidDataError.js.map +1 -1
- package/dist/errors/QueryFailedError.js +1 -0
- package/dist/errors/QueryFailedError.js.map +1 -1
- package/dist/testArtifacts.js +11 -11
- package/dist/testArtifacts.js.map +1 -1
- package/dist/testMocks.js +11 -10
- package/dist/testMocks.js.map +1 -1
- package/package.json +3 -3
- package/src/Entity.test.ts +2 -1
- package/src/driver/NymphDriver.ts +112 -71
- package/src/driver/testArtifacts.ts +59 -29
- package/tsconfig.json +2 -2
|
@@ -68,6 +68,7 @@ export default abstract class NymphDriver {
|
|
|
68
68
|
abstract connect(): Promise<boolean>;
|
|
69
69
|
|
|
70
70
|
abstract isConnected(): boolean;
|
|
71
|
+
protected abstract internalTransaction(name: string): Promise<any>;
|
|
71
72
|
abstract startTransaction(name: string): Promise<Nymph>;
|
|
72
73
|
abstract commit(name: string): Promise<boolean>;
|
|
73
74
|
abstract rollback(name: string): Promise<boolean>;
|
|
@@ -84,9 +85,11 @@ export default abstract class NymphDriver {
|
|
|
84
85
|
*/
|
|
85
86
|
abstract disconnect(): Promise<boolean>;
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
abstract exportDataIterator(): AsyncGenerator<
|
|
89
|
+
{ type: 'comment' | 'uid' | 'entity'; content: string },
|
|
90
|
+
void,
|
|
91
|
+
undefined | false
|
|
92
|
+
>;
|
|
90
93
|
abstract getEntities<T extends EntityConstructor = EntityConstructor>(
|
|
91
94
|
options: Options<T> & { return: 'count' },
|
|
92
95
|
...selectors: Selector[]
|
|
@@ -104,7 +107,15 @@ export default abstract class NymphDriver {
|
|
|
104
107
|
...selectors: Selector[]
|
|
105
108
|
): Promise<EntityInstanceType<T>[] | string[] | number>;
|
|
106
109
|
abstract getUID(name: string): Promise<number | null>;
|
|
107
|
-
abstract
|
|
110
|
+
abstract importEntity(entity: {
|
|
111
|
+
guid: string;
|
|
112
|
+
cdate: number;
|
|
113
|
+
mdate: number;
|
|
114
|
+
tags: string[];
|
|
115
|
+
sdata: SerializedEntityData;
|
|
116
|
+
etype: string;
|
|
117
|
+
}): Promise<void>;
|
|
118
|
+
abstract importUID(uid: { name: string; value: number }): Promise<void>;
|
|
108
119
|
abstract newUID(name: string): Promise<number | null>;
|
|
109
120
|
abstract renameUID(oldName: string, newName: string): Promise<boolean>;
|
|
110
121
|
abstract saveEntity(entity: EntityInterface): Promise<boolean>;
|
|
@@ -181,9 +192,9 @@ export default abstract class NymphDriver {
|
|
|
181
192
|
if (!fhandle) {
|
|
182
193
|
throw new InvalidParametersError('Provided filename is not writeable.');
|
|
183
194
|
}
|
|
184
|
-
await this.
|
|
185
|
-
fs.writeSync(fhandle,
|
|
186
|
-
}
|
|
195
|
+
for await (let entry of this.exportDataIterator()) {
|
|
196
|
+
fs.writeSync(fhandle, entry.content);
|
|
197
|
+
}
|
|
187
198
|
fs.closeSync(fhandle);
|
|
188
199
|
} catch (e: any) {
|
|
189
200
|
return false;
|
|
@@ -192,83 +203,113 @@ export default abstract class NymphDriver {
|
|
|
192
203
|
}
|
|
193
204
|
|
|
194
205
|
public async exportPrint() {
|
|
195
|
-
await this.
|
|
196
|
-
console.log(
|
|
197
|
-
}
|
|
206
|
+
for await (let entry of this.exportDataIterator()) {
|
|
207
|
+
console.log(entry.content);
|
|
208
|
+
}
|
|
198
209
|
return true;
|
|
199
210
|
}
|
|
200
211
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
guid: string,
|
|
205
|
-
tags: string[],
|
|
206
|
-
sdata: SerializedEntityData,
|
|
207
|
-
etype: string,
|
|
208
|
-
) => Promise<void>,
|
|
209
|
-
saveUIDCallback: (name: string, value: number) => Promise<void>,
|
|
210
|
-
startTransactionCallback: (() => Promise<void>) | null = null,
|
|
211
|
-
commitTransactionCallback: (() => Promise<void>) | null = null,
|
|
212
|
+
public async importDataIterator(
|
|
213
|
+
lines: Iterable<string>,
|
|
214
|
+
transaction?: boolean,
|
|
212
215
|
) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
throw new InvalidParametersError('Provided filename is unreadable.');
|
|
216
|
+
const first = lines[Symbol.iterator]().next();
|
|
217
|
+
|
|
218
|
+
if (first.done || first.value !== '#nex2') {
|
|
219
|
+
throw new Error('Tried to import a file that is not a NEX v2 file.');
|
|
218
220
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
let tags: string[] = [];
|
|
223
|
-
let etype = '__undefined';
|
|
224
|
-
if (startTransactionCallback) {
|
|
225
|
-
await startTransactionCallback();
|
|
221
|
+
|
|
222
|
+
if (transaction) {
|
|
223
|
+
await this.internalTransaction('nymph-import');
|
|
226
224
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
/^\s
|
|
234
|
-
|
|
235
|
-
const propMatch = text.match(/^\s*([^=]+)\s*=\s*(.*\S)\s*$/);
|
|
236
|
-
const uidMatch = text.match(/^\s*<([^>]+)>\[(\d+)\]\s*$/);
|
|
237
|
-
if (uidMatch) {
|
|
238
|
-
// Add the UID.
|
|
239
|
-
await saveUIDCallback(uidMatch[1], Number(uidMatch[2]));
|
|
240
|
-
} else if (entityMatch) {
|
|
241
|
-
// Save the current entity.
|
|
242
|
-
if (guid) {
|
|
243
|
-
await saveEntityCallback(guid, tags, sdata, etype);
|
|
244
|
-
guid = null;
|
|
245
|
-
tags = [];
|
|
246
|
-
sdata = {};
|
|
247
|
-
etype = '__undefined';
|
|
225
|
+
try {
|
|
226
|
+
let guid: string | null = null;
|
|
227
|
+
let sdata: SerializedEntityData = {};
|
|
228
|
+
let tags: string[] = [];
|
|
229
|
+
let etype = '__undefined';
|
|
230
|
+
for (let line of lines) {
|
|
231
|
+
if (line.match(/^\s*#/)) {
|
|
232
|
+
continue;
|
|
248
233
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
234
|
+
const entityMatch = line.match(
|
|
235
|
+
/^\s*{([0-9A-Fa-f]+)}<([-\w_]+)>\[([^\]]*)\]\s*$/,
|
|
236
|
+
);
|
|
237
|
+
const propMatch = line.match(/^\s*([^=]+)\s*=\s*(.*\S)\s*$/);
|
|
238
|
+
const uidMatch = line.match(/^\s*<([^>]+)>\[(\d+)\]\s*$/);
|
|
239
|
+
if (uidMatch) {
|
|
240
|
+
// Add the UID.
|
|
241
|
+
await this.importUID({
|
|
242
|
+
name: uidMatch[1],
|
|
243
|
+
value: Number(uidMatch[2]),
|
|
244
|
+
});
|
|
245
|
+
} else if (entityMatch) {
|
|
246
|
+
// Save the current entity.
|
|
247
|
+
if (guid) {
|
|
248
|
+
const cdate = Number(JSON.parse(sdata.cdate));
|
|
249
|
+
delete sdata.cdate;
|
|
250
|
+
const mdate = Number(JSON.parse(sdata.mdate));
|
|
251
|
+
delete sdata.mdate;
|
|
252
|
+
await this.importEntity({ guid, cdate, mdate, tags, sdata, etype });
|
|
253
|
+
guid = null;
|
|
254
|
+
tags = [];
|
|
255
|
+
sdata = {};
|
|
256
|
+
etype = '__undefined';
|
|
257
|
+
}
|
|
258
|
+
// Record the new entity's info.
|
|
259
|
+
guid = entityMatch[1];
|
|
260
|
+
etype = entityMatch[2];
|
|
261
|
+
tags = entityMatch[3].split(',');
|
|
262
|
+
} else if (propMatch) {
|
|
263
|
+
// Add the variable to the new entity.
|
|
264
|
+
if (guid) {
|
|
265
|
+
sdata[propMatch[1]] = propMatch[2];
|
|
266
|
+
}
|
|
257
267
|
}
|
|
268
|
+
// Clear the entity cache.
|
|
269
|
+
this.entityCache = {};
|
|
258
270
|
}
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
271
|
+
// Save the last entity.
|
|
272
|
+
if (guid) {
|
|
273
|
+
const cdate = Number(JSON.parse(sdata.cdate));
|
|
274
|
+
delete sdata.cdate;
|
|
275
|
+
const mdate = Number(JSON.parse(sdata.mdate));
|
|
276
|
+
delete sdata.mdate;
|
|
277
|
+
await this.importEntity({ guid, cdate, mdate, tags, sdata, etype });
|
|
278
|
+
}
|
|
279
|
+
if (transaction) {
|
|
280
|
+
await this.commit('nymph-import');
|
|
281
|
+
}
|
|
282
|
+
} catch (e: any) {
|
|
283
|
+
await this.rollback('nymph-import');
|
|
284
|
+
throw e;
|
|
268
285
|
}
|
|
269
286
|
return true;
|
|
270
287
|
}
|
|
271
288
|
|
|
289
|
+
public async importData(text: string, transaction?: boolean) {
|
|
290
|
+
return await this.importDataIterator(text.split('/n'), transaction);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
public async import(filename: string, transaction?: boolean) {
|
|
294
|
+
let rl: ReadLines;
|
|
295
|
+
try {
|
|
296
|
+
rl = new ReadLines(filename);
|
|
297
|
+
} catch (e: any) {
|
|
298
|
+
throw new InvalidParametersError('Provided filename is unreadable.');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const lines = {
|
|
302
|
+
*[Symbol.iterator]() {
|
|
303
|
+
let line: false | Buffer;
|
|
304
|
+
while ((line = rl.next())) {
|
|
305
|
+
yield line.toString('utf8');
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
return await this.importDataIterator(lines, transaction);
|
|
311
|
+
}
|
|
312
|
+
|
|
272
313
|
public checkData(
|
|
273
314
|
data: EntityData,
|
|
274
315
|
sdata: SerializedEntityData,
|
|
@@ -94,14 +94,23 @@ These hats are absolutely fantastic.`;
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
it('delete old test data', async () => {
|
|
97
|
-
let
|
|
98
|
-
expect(Array.isArray(
|
|
99
|
-
for (const cur of
|
|
97
|
+
let amodels = await nymph.getEntities({ class: TestModel });
|
|
98
|
+
expect(Array.isArray(amodels)).toEqual(true);
|
|
99
|
+
for (const cur of amodels) {
|
|
100
100
|
expect(await cur.$delete()).toEqual(true);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
expect(
|
|
103
|
+
amodels = await nymph.getEntities({ class: TestModel });
|
|
104
|
+
expect(amodels.length).toEqual(0);
|
|
105
|
+
|
|
106
|
+
let bmodels = await nymph.getEntities({ class: TestBModel });
|
|
107
|
+
expect(Array.isArray(bmodels)).toEqual(true);
|
|
108
|
+
for (const cur of bmodels) {
|
|
109
|
+
expect(await cur.$delete()).toEqual(true);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
bmodels = await nymph.getEntities({ class: TestBModel });
|
|
113
|
+
expect(bmodels.length).toEqual(0);
|
|
105
114
|
});
|
|
106
115
|
|
|
107
116
|
it('create entity', async () => {
|
|
@@ -1986,25 +1995,39 @@ export function ExportImportTest(
|
|
|
1986
1995
|
const bmodels = await nymph.getEntities({ class: TestBModel });
|
|
1987
1996
|
|
|
1988
1997
|
expect(models.length).toEqual(30);
|
|
1989
|
-
expect(bmodels.length).toEqual(
|
|
1990
|
-
|
|
1991
|
-
const
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
1998
|
+
expect(bmodels.length).toEqual(30);
|
|
1999
|
+
|
|
2000
|
+
for (const model of models) {
|
|
2001
|
+
expect(model.name).toMatch(/^Entity Test /);
|
|
2002
|
+
expect(model.null).toBeDefined();
|
|
2003
|
+
expect(model.null).toBeNull();
|
|
2004
|
+
expect(model.string).toEqual('test');
|
|
2005
|
+
expect(model.array).toEqual(['full', 'of', 'values', 500]);
|
|
2006
|
+
expect(model.match)
|
|
2007
|
+
.toEqual(`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.
|
|
2008
|
+
|
|
2009
|
+
This one's email address is nice_hat-wednesday+newyork@im-a-hat.hat.
|
|
2010
|
+
This one's phone number is (555) 555-1818.
|
|
2011
|
+
This one's zip code is 92064.
|
|
2012
|
+
This one's favorite emojis are 🔥❤️😊😂⭐🤔
|
|
2013
|
+
|
|
2014
|
+
These hats are absolutely fantastic.`);
|
|
2015
|
+
expect(model.number).toEqual(30);
|
|
2016
|
+
expect(model.numberString).toEqual('30');
|
|
2017
|
+
expect(model.timestamp).toBeGreaterThanOrEqual(strtotime('-2 minutes'));
|
|
2018
|
+
expect(model.index).toMatch(/^\d+a$/);
|
|
2019
|
+
|
|
2020
|
+
await model.reference?.$wake();
|
|
2021
|
+
expect(model.reference?.guid).not.toBeNull();
|
|
2022
|
+
expect(model.reference?.string).toEqual('another');
|
|
2023
|
+
expect(model.reference?.index).toMatch(/^\d+b$/);
|
|
2024
|
+
expect(model.index?.substring(0, -1)).toEqual(
|
|
2025
|
+
model.reference?.index?.substring(0, -1),
|
|
2026
|
+
);
|
|
2027
|
+
expect(model.reference?.$inArray(bmodels)).toEqual(true);
|
|
2028
|
+
await Promise.all(model.refArray?.map((e) => e.$wake()) || []);
|
|
2029
|
+
expect(model.refArray?.[0].guid).not.toBeNull();
|
|
2030
|
+
expect(model.refArray?.[0].guid).toEqual(model.reference?.guid);
|
|
2008
2031
|
}
|
|
2009
2032
|
}
|
|
2010
2033
|
|
|
@@ -2017,22 +2040,29 @@ export function ExportImportTest(
|
|
|
2017
2040
|
expect(await nymph.newUID('TestUID')).toEqual(2);
|
|
2018
2041
|
expect(await nymph.newUID('TestUID2')).toEqual(1);
|
|
2019
2042
|
|
|
2020
|
-
for (let i = 0; i <
|
|
2021
|
-
const EntityClass = i < 15 ? TestModel : TestBModel;
|
|
2022
|
-
|
|
2043
|
+
for (let i = 0; i < 30; i++) {
|
|
2023
2044
|
// Creating entity...
|
|
2024
|
-
const testEntity = await
|
|
2045
|
+
const testEntity = await TestModel.factory();
|
|
2025
2046
|
|
|
2026
2047
|
// Saving entity...
|
|
2027
2048
|
testEntity.name = 'Entity Test ' + new Date().toLocaleString();
|
|
2028
2049
|
testEntity.null = null;
|
|
2029
2050
|
testEntity.string = 'test';
|
|
2030
2051
|
testEntity.array = ['full', 'of', 'values', 500];
|
|
2052
|
+
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.
|
|
2053
|
+
|
|
2054
|
+
This one's email address is nice_hat-wednesday+newyork@im-a-hat.hat.
|
|
2055
|
+
This one's phone number is (555) 555-1818.
|
|
2056
|
+
This one's zip code is 92064.
|
|
2057
|
+
This one's favorite emojis are 🔥❤️😊😂⭐🤔
|
|
2058
|
+
|
|
2059
|
+
These hats are absolutely fantastic.`;
|
|
2031
2060
|
testEntity.number = 30;
|
|
2061
|
+
testEntity.numberString = '30';
|
|
2032
2062
|
testEntity.timestamp = Date.now();
|
|
2033
2063
|
testEntity.index = i + 'a';
|
|
2034
2064
|
|
|
2035
|
-
const entityReferenceTest = await
|
|
2065
|
+
const entityReferenceTest = await TestBModel.factory();
|
|
2036
2066
|
entityReferenceTest.string = 'another';
|
|
2037
2067
|
entityReferenceTest.index = i + 'b';
|
|
2038
2068
|
|
package/tsconfig.json
CHANGED