@nymphjs/nymph 1.0.0-beta.9 → 1.0.0-beta.90

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 (96) hide show
  1. package/CHANGELOG.md +432 -0
  2. package/README.md +10 -20
  3. package/dist/Entity.d.ts +277 -10
  4. package/dist/Entity.js +543 -148
  5. package/dist/Entity.js.map +1 -1
  6. package/dist/Entity.test.js +53 -13
  7. package/dist/Entity.test.js.map +1 -1
  8. package/dist/Entity.types.d.ts +249 -23
  9. package/dist/Entity.types.js +1 -2
  10. package/dist/Nymph.d.ts +431 -12
  11. package/dist/Nymph.js +692 -180
  12. package/dist/Nymph.js.map +1 -1
  13. package/dist/Nymph.types.d.ts +65 -7
  14. package/dist/Nymph.types.js +3 -5
  15. package/dist/Nymph.types.js.map +1 -1
  16. package/dist/conf/d.d.ts +43 -0
  17. package/dist/conf/d.js +1 -2
  18. package/dist/conf/defaults.d.ts +1 -1
  19. package/dist/conf/defaults.js +26 -3
  20. package/dist/conf/defaults.js.map +1 -1
  21. package/dist/conf/index.d.ts +2 -2
  22. package/dist/conf/index.js +2 -8
  23. package/dist/conf/index.js.map +1 -1
  24. package/dist/driver/NymphDriver.d.ts +137 -39
  25. package/dist/driver/NymphDriver.js +344 -194
  26. package/dist/driver/NymphDriver.js.map +1 -1
  27. package/dist/driver/index.d.ts +2 -2
  28. package/dist/driver/index.js +3 -23
  29. package/dist/driver/index.js.map +1 -1
  30. package/dist/driver/testArtifacts.d.ts +2 -2
  31. package/dist/driver/testArtifacts.js +557 -92
  32. package/dist/driver/testArtifacts.js.map +1 -1
  33. package/dist/errors/ClassNotAvailableError.js +1 -5
  34. package/dist/errors/ClassNotAvailableError.js.map +1 -1
  35. package/dist/errors/EntityConflictError.js +1 -5
  36. package/dist/errors/EntityConflictError.js.map +1 -1
  37. package/dist/errors/EntityInvalidDataError.d.ts +6 -0
  38. package/dist/errors/EntityInvalidDataError.js +8 -6
  39. package/dist/errors/EntityInvalidDataError.js.map +1 -1
  40. package/dist/errors/EntityIsSleepingReferenceError.js +1 -5
  41. package/dist/errors/EntityIsSleepingReferenceError.js.map +1 -1
  42. package/dist/errors/EntityUniqueConstraintError.d.ts +3 -0
  43. package/dist/errors/EntityUniqueConstraintError.js +7 -0
  44. package/dist/errors/EntityUniqueConstraintError.js.map +1 -0
  45. package/dist/errors/InvalidParametersError.js +1 -5
  46. package/dist/errors/InvalidParametersError.js.map +1 -1
  47. package/dist/errors/InvalidStateError.d.ts +3 -0
  48. package/dist/errors/InvalidStateError.js +7 -0
  49. package/dist/errors/InvalidStateError.js.map +1 -0
  50. package/dist/errors/NotConfiguredError.js +1 -5
  51. package/dist/errors/NotConfiguredError.js.map +1 -1
  52. package/dist/errors/QueryFailedError.js +2 -5
  53. package/dist/errors/QueryFailedError.js.map +1 -1
  54. package/dist/errors/UnableToConnectError.js +1 -5
  55. package/dist/errors/UnableToConnectError.js.map +1 -1
  56. package/dist/errors/index.d.ts +10 -8
  57. package/dist/errors/index.js +10 -24
  58. package/dist/errors/index.js.map +1 -1
  59. package/dist/index.d.ts +11 -11
  60. package/dist/index.js +14 -34
  61. package/dist/index.js.map +1 -1
  62. package/dist/nymphJoiProps.js +10 -15
  63. package/dist/nymphJoiProps.js.map +1 -1
  64. package/dist/testArtifacts.d.ts +18 -6
  65. package/dist/testArtifacts.js +32 -37
  66. package/dist/testArtifacts.js.map +1 -1
  67. package/dist/testMocks.d.ts +15 -12
  68. package/dist/testMocks.js +40 -29
  69. package/dist/testMocks.js.map +1 -1
  70. package/dist/utils.d.ts +4 -4
  71. package/dist/utils.js +40 -29
  72. package/dist/utils.js.map +1 -1
  73. package/jest.config.js +11 -2
  74. package/package.json +22 -19
  75. package/src/Entity.test.ts +52 -7
  76. package/src/Entity.ts +458 -147
  77. package/src/Entity.types.ts +64 -74
  78. package/src/Nymph.ts +754 -321
  79. package/src/Nymph.types.ts +131 -26
  80. package/src/conf/d.ts +25 -0
  81. package/src/conf/defaults.ts +34 -1
  82. package/src/conf/index.ts +2 -2
  83. package/src/driver/NymphDriver.ts +362 -359
  84. package/src/driver/index.ts +2 -2
  85. package/src/driver/testArtifacts.ts +609 -185
  86. package/src/errors/EntityUniqueConstraintError.ts +6 -0
  87. package/src/errors/InvalidStateError.ts +6 -0
  88. package/src/errors/index.ts +12 -8
  89. package/src/index.ts +11 -11
  90. package/src/nymphJoiProps.ts +2 -2
  91. package/src/testArtifacts.ts +19 -20
  92. package/src/testMocks.ts +60 -35
  93. package/src/type/locutus.d.ts +3 -0
  94. package/src/utils.ts +39 -18
  95. package/tsconfig.json +5 -3
  96. package/typedoc.json +4 -0
package/src/Nymph.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { Config, ConfigDefaults as defaults } from './conf';
2
- import { NymphDriver } from './driver';
3
- import Entity from './Entity';
4
- import { EntityConstructor, EntityInterface } from './Entity.types';
5
- import { ClassNotAvailableError } from './errors';
1
+ import { Config, ConfigDefaults as defaults } from './conf/index.js';
2
+ import type { NymphDriver } from './driver/index.js';
3
+ import Entity, { type EntityInstanceType } from './Entity.js';
4
+ import type { EntityConstructor, EntityInterface } from './Entity.types.js';
5
+ import { ClassNotAvailableError } from './errors/index.js';
6
6
  import type {
7
7
  Selector,
8
8
  Options,
@@ -12,23 +12,36 @@ import type {
12
12
  NymphBeforeGetEntitiesCallback,
13
13
  NymphBeforeSaveEntityCallback,
14
14
  NymphAfterSaveEntityCallback,
15
+ NymphFailedSaveEntityCallback,
15
16
  NymphBeforeDeleteEntityCallback,
16
17
  NymphAfterDeleteEntityCallback,
18
+ NymphFailedDeleteEntityCallback,
17
19
  NymphBeforeDeleteEntityByIDCallback,
18
20
  NymphAfterDeleteEntityByIDCallback,
21
+ NymphFailedDeleteEntityByIDCallback,
19
22
  NymphBeforeNewUIDCallback,
20
23
  NymphAfterNewUIDCallback,
24
+ NymphFailedNewUIDCallback,
21
25
  NymphBeforeSetUIDCallback,
22
26
  NymphAfterSetUIDCallback,
27
+ NymphFailedSetUIDCallback,
23
28
  NymphBeforeRenameUIDCallback,
24
29
  NymphAfterRenameUIDCallback,
30
+ NymphFailedRenameUIDCallback,
25
31
  NymphBeforeDeleteUIDCallback,
26
32
  NymphAfterDeleteUIDCallback,
33
+ NymphFailedDeleteUIDCallback,
34
+ NymphBeforeStartTransactionCallback,
35
+ NymphAfterStartTransactionCallback,
36
+ NymphBeforeCommitTransactionCallback,
37
+ NymphAfterCommitTransactionCallback,
38
+ NymphBeforeRollbackTransactionCallback,
39
+ NymphAfterRollbackTransactionCallback,
27
40
  NymphEventType,
28
41
  NymphQueryCallback,
29
42
  FormattedSelector,
30
43
  TilmeldInterface,
31
- } from './Nymph.types';
44
+ } from './Nymph.types.js';
32
45
 
33
46
  /**
34
47
  * An object relational mapper for Node.js.
@@ -41,10 +54,16 @@ import type {
41
54
  */
42
55
  export default class Nymph {
43
56
  /**
44
- * The PubSub config.
57
+ * The Nymph config.
45
58
  */
46
59
  public config: Config;
47
60
 
61
+ /**
62
+ * The Nymph instance that this one was cloned from, or null if it's not a
63
+ * clone.
64
+ */
65
+ public parent: Nymph | null;
66
+
48
67
  /**
49
68
  * The Nymph database driver.
50
69
  */
@@ -72,20 +91,40 @@ export default class Nymph {
72
91
  private beforeGetEntitiesCallbacks: NymphBeforeGetEntitiesCallback[] = [];
73
92
  private beforeSaveEntityCallbacks: NymphBeforeSaveEntityCallback[] = [];
74
93
  private afterSaveEntityCallbacks: NymphAfterSaveEntityCallback[] = [];
94
+ private failedSaveEntityCallbacks: NymphFailedSaveEntityCallback[] = [];
75
95
  private beforeDeleteEntityCallbacks: NymphBeforeDeleteEntityCallback[] = [];
76
96
  private afterDeleteEntityCallbacks: NymphAfterDeleteEntityCallback[] = [];
97
+ private failedDeleteEntityCallbacks: NymphFailedDeleteEntityCallback[] = [];
77
98
  private beforeDeleteEntityByIDCallbacks: NymphBeforeDeleteEntityByIDCallback[] =
78
99
  [];
79
100
  private afterDeleteEntityByIDCallbacks: NymphAfterDeleteEntityByIDCallback[] =
80
101
  [];
102
+ private failedDeleteEntityByIDCallbacks: NymphFailedDeleteEntityByIDCallback[] =
103
+ [];
81
104
  private beforeNewUIDCallbacks: NymphBeforeNewUIDCallback[] = [];
82
105
  private afterNewUIDCallbacks: NymphAfterNewUIDCallback[] = [];
106
+ private failedNewUIDCallbacks: NymphFailedNewUIDCallback[] = [];
83
107
  private beforeSetUIDCallbacks: NymphBeforeSetUIDCallback[] = [];
84
108
  private afterSetUIDCallbacks: NymphAfterSetUIDCallback[] = [];
109
+ private failedSetUIDCallbacks: NymphFailedSetUIDCallback[] = [];
85
110
  private beforeRenameUIDCallbacks: NymphBeforeRenameUIDCallback[] = [];
86
111
  private afterRenameUIDCallbacks: NymphAfterRenameUIDCallback[] = [];
112
+ private failedRenameUIDCallbacks: NymphFailedRenameUIDCallback[] = [];
87
113
  private beforeDeleteUIDCallbacks: NymphBeforeDeleteUIDCallback[] = [];
88
114
  private afterDeleteUIDCallbacks: NymphAfterDeleteUIDCallback[] = [];
115
+ private failedDeleteUIDCallbacks: NymphFailedDeleteUIDCallback[] = [];
116
+ private beforeStartTransactionCallbacks: NymphBeforeStartTransactionCallback[] =
117
+ [];
118
+ private afterStartTransactionCallbacks: NymphAfterStartTransactionCallback[] =
119
+ [];
120
+ private beforeCommitTransactionCallbacks: NymphBeforeCommitTransactionCallback[] =
121
+ [];
122
+ private afterCommitTransactionCallbacks: NymphAfterCommitTransactionCallback[] =
123
+ [];
124
+ private beforeRollbackTransactionCallbacks: NymphBeforeRollbackTransactionCallback[] =
125
+ [];
126
+ private afterRollbackTransactionCallbacks: NymphAfterRollbackTransactionCallback[] =
127
+ [];
89
128
 
90
129
  /**
91
130
  * Initialize Nymph.
@@ -93,24 +132,90 @@ export default class Nymph {
93
132
  * @param config The Nymph configuration.
94
133
  * @param driver The Nymph database driver.
95
134
  * @param tilmeld The Tilmeld user/group manager instance, if you want to use it.
135
+ * @param parent Used internally by Nymph. Don't set this.
96
136
  */
97
137
  public constructor(
98
138
  config: Partial<Config>,
99
139
  driver: NymphDriver,
100
- tilmeld?: TilmeldInterface
140
+ tilmeld?: TilmeldInterface,
141
+ parent?: Nymph,
101
142
  ) {
102
143
  this.config = { ...defaults, ...config };
103
144
  this.driver = driver;
145
+ this.parent = parent ?? null;
104
146
 
105
147
  this.Entity = this.addEntityClass(Entity);
106
148
 
107
- if (typeof tilmeld !== 'undefined') {
149
+ if (parent) {
150
+ for (const name in parent.entityClasses) {
151
+ if (
152
+ name === 'Entity' ||
153
+ (parent.entityClasses[name] as any).skipOnClone
154
+ ) {
155
+ continue;
156
+ }
157
+ this.addEntityClass(parent.entityClasses[name]);
158
+ }
159
+
160
+ const events = [
161
+ 'connect',
162
+ 'disconnect',
163
+ 'query',
164
+ 'beforeGetEntity',
165
+ 'beforeGetEntities',
166
+ 'beforeSaveEntity',
167
+ 'afterSaveEntity',
168
+ 'failedSaveEntity',
169
+ 'beforeDeleteEntity',
170
+ 'afterDeleteEntity',
171
+ 'failedDeleteEntity',
172
+ 'beforeDeleteEntityByID',
173
+ 'afterDeleteEntityByID',
174
+ 'failedDeleteEntityByID',
175
+ 'beforeNewUID',
176
+ 'afterNewUID',
177
+ 'failedNewUID',
178
+ 'beforeSetUID',
179
+ 'afterSetUID',
180
+ 'failedSetUID',
181
+ 'beforeRenameUID',
182
+ 'afterRenameUID',
183
+ 'failedRenameUID',
184
+ 'beforeDeleteUID',
185
+ 'afterDeleteUID',
186
+ 'failedDeleteUID',
187
+ 'beforeStartTransaction',
188
+ 'afterStartTransaction',
189
+ 'beforeCommitTransaction',
190
+ 'afterCommitTransaction',
191
+ 'beforeRollbackTransaction',
192
+ 'afterRollbackTransaction',
193
+ ];
194
+
195
+ for (let event of events) {
196
+ const prop = event + 'Callbacks';
197
+ // @ts-ignore: The callback should be the right type here.
198
+ const callbacks = parent[prop];
199
+ for (let callback of callbacks) {
200
+ if (callback.skipOnClone) {
201
+ continue;
202
+ }
203
+ this.on(event as NymphEventType, callback);
204
+ }
205
+ }
206
+ }
207
+
208
+ this.config.debugInfo('nymph', 'Nymph loaded.');
209
+
210
+ if (tilmeld != null) {
108
211
  this.tilmeld = tilmeld;
109
212
  }
110
213
 
111
214
  this.driver.init(this);
215
+ this.config.debugInfo('nymph', 'Nymph driver loaded.');
112
216
  if (this.tilmeld) {
113
217
  this.tilmeld.init(this);
218
+ this.config.debugInfo('nymph', 'Tilmeld loaded.');
114
219
  }
115
220
  }
116
221
 
@@ -124,82 +229,93 @@ export default class Nymph {
124
229
  * Because this creates a subclass, don't use the class
125
230
  * returned from `getEntityClass` to check with `instanceof`.
126
231
  */
127
- public addEntityClass<T extends EntityConstructor>(entityClass: T): T {
232
+ public addEntityClass<T extends EntityConstructor>(EntityClass: T): T {
233
+ if (EntityClass.class in this.entityClasses) {
234
+ this.config.debugLog(
235
+ 'nymph',
236
+ `Adding duplicate class "${EntityClass.class}". This may be a mistake.`,
237
+ );
238
+ }
239
+
240
+ // Check that it doesn't have the same etype as any other class.
241
+ for (const ExistingClass of Object.values(this.entityClasses)) {
242
+ if (
243
+ EntityClass.ETYPE === ExistingClass.ETYPE &&
244
+ EntityClass.class !== EntityClass.class
245
+ ) {
246
+ this.config.debugLog(
247
+ 'nymph',
248
+ `Adding class "${EntityClass.class}" with same etype as existing class "${ExistingClass.class}". This may be a mistake.`,
249
+ );
250
+ }
251
+ }
252
+
128
253
  const nymph = this;
129
- class NymphEntity extends entityClass {
254
+ this.entityClasses[EntityClass.class] = class extends EntityClass {
130
255
  static nymph: Nymph = nymph;
131
256
 
132
257
  constructor(...args: any[]) {
133
258
  super(...args);
134
259
  }
135
- }
136
- this.entityClasses[entityClass.class] = NymphEntity;
137
- return NymphEntity;
260
+ };
261
+ return this.entityClasses[EntityClass.class] as T;
138
262
  }
139
263
 
140
264
  /**
141
265
  * Get the class that uses the specified class name.
142
266
  */
143
- public getEntityClass(className: string): EntityConstructor {
144
- if (className in this.entityClasses) {
145
- return this.entityClasses[className];
267
+ public getEntityClass(className: string): EntityConstructor;
268
+ public getEntityClass<T extends EntityConstructor>(className: T): T;
269
+ public getEntityClass<T extends EntityConstructor = EntityConstructor>(
270
+ className: T | string,
271
+ ): T | EntityConstructor {
272
+ let key: string | null = null;
273
+ if (typeof className === 'string') {
274
+ key = className;
275
+ } else {
276
+ key = className.class;
146
277
  }
147
- throw new ClassNotAvailableError('Tried to use class: ' + className);
278
+ if (key in this.entityClasses) {
279
+ return this.entityClasses[key];
280
+ }
281
+ this.config.debugError('nymph', `Tried to use missing class "${key}".`);
282
+ throw new ClassNotAvailableError(`Tried to use missing class "${key}".`);
148
283
  }
149
284
 
150
285
  /**
151
- * Get a clone of this instance with duplicate classes and event listeners.
286
+ * Get the class that uses the specified etype.
287
+ *
288
+ * Note that it is fine, though unusual, for two classes to use the same
289
+ * etype. However, this can lead to very hard to diagnose bugs, so is
290
+ * generally discouraged.
291
+ */
292
+ public getEntityClassByEtype(etype: string): EntityConstructor {
293
+ for (const EntityClass of Object.values(this.entityClasses)) {
294
+ if (EntityClass.ETYPE === etype) {
295
+ return EntityClass;
296
+ }
297
+ }
298
+ this.config.debugError(
299
+ 'nymph',
300
+ `Tried to use missing class by etype "${etype}".`,
301
+ );
302
+ throw new ClassNotAvailableError(
303
+ `Tried to use missing class by etype "${etype}".`,
304
+ );
305
+ }
306
+
307
+ /**
308
+ * Get a clone of this instance with cloned classes and event listeners.
152
309
  *
153
310
  * @returns A clone of this instance.
154
311
  */
155
312
  public clone() {
156
- const nymph = new Nymph(
313
+ return new Nymph(
157
314
  this.config,
158
315
  this.driver.clone(),
159
- this.tilmeld?.clone()
316
+ this.tilmeld?.clone(),
317
+ this,
160
318
  );
161
- for (const name in this.entityClasses) {
162
- if (name === 'Entity' || (this.entityClasses[name] as any).skipOnClone) {
163
- continue;
164
- }
165
- nymph.addEntityClass(this.entityClasses[name]);
166
- }
167
-
168
- const events = [
169
- 'connect',
170
- 'disconnect',
171
- 'query',
172
- 'beforeGetEntity',
173
- 'beforeGetEntities',
174
- 'beforeSaveEntity',
175
- 'afterSaveEntity',
176
- 'beforeDeleteEntity',
177
- 'afterDeleteEntity',
178
- 'beforeDeleteEntityByID',
179
- 'afterDeleteEntityByID',
180
- 'beforeNewUID',
181
- 'afterNewUID',
182
- 'beforeSetUID',
183
- 'afterSetUID',
184
- 'beforeRenameUID',
185
- 'afterRenameUID',
186
- 'beforeDeleteUID',
187
- 'afterDeleteUID',
188
- ];
189
-
190
- for (let event of events) {
191
- const prop = event + 'Callbacks';
192
- // @ts-ignore: The callback should be the right type here.
193
- const callbacks = this[prop];
194
- for (let callback of callbacks) {
195
- if (callback.skipOnClone) {
196
- continue;
197
- }
198
- nymph.on(event as NymphEventType, callback);
199
- }
200
- }
201
-
202
- return nymph;
203
319
  }
204
320
 
205
321
  /**
@@ -208,13 +324,19 @@ export default class Nymph {
208
324
  * @returns Whether the instance is connected to the database.
209
325
  */
210
326
  public async connect(): Promise<boolean> {
211
- const result = this.driver.connect();
212
- for (let callback of this.connectCallbacks) {
213
- if (callback) {
214
- await callback(this, result);
327
+ try {
328
+ const result = this.driver.connect();
329
+ for (let callback of this.connectCallbacks) {
330
+ if (callback) {
331
+ await callback(this, result);
332
+ }
215
333
  }
334
+ this.config.debugInfo('nymph', 'Driver connected.');
335
+ return await result;
336
+ } catch (e: any) {
337
+ this.config.debugError('nymph', `Failed to connect: ${e}`);
338
+ throw e;
216
339
  }
217
- return await result;
218
340
  }
219
341
 
220
342
  /**
@@ -223,13 +345,19 @@ export default class Nymph {
223
345
  * @returns Whether the instance is connected to the database.
224
346
  */
225
347
  public async disconnect(): Promise<boolean> {
226
- const result = this.driver.disconnect();
227
- for (let callback of this.disconnectCallbacks) {
228
- if (callback) {
229
- await callback(this, result);
348
+ try {
349
+ const result = this.driver.disconnect();
350
+ for (let callback of this.disconnectCallbacks) {
351
+ if (callback) {
352
+ await callback(this, result);
353
+ }
230
354
  }
355
+ this.config.debugInfo('nymph', 'Driver disconnected.');
356
+ return await result;
357
+ } catch (e: any) {
358
+ this.config.debugError('nymph', `Failed to disconnect: ${e}`);
359
+ throw e;
231
360
  }
232
- return await result;
233
361
  }
234
362
 
235
363
  /**
@@ -256,7 +384,24 @@ export default class Nymph {
256
384
  * @returns A new instance of Nymph that should be used for the transaction.
257
385
  */
258
386
  public async startTransaction(name: string): Promise<Nymph> {
259
- return await this.driver.startTransaction(name);
387
+ try {
388
+ for (let callback of this.beforeStartTransactionCallbacks) {
389
+ if (callback) {
390
+ await callback(this, name);
391
+ }
392
+ }
393
+ this.config.debugLog('nymph', `Starting transaction "${name}".`);
394
+ const result = await this.driver.startTransaction(name);
395
+ for (let callback of this.afterStartTransactionCallbacks) {
396
+ if (callback) {
397
+ await callback(this, name, result);
398
+ }
399
+ }
400
+ return result;
401
+ } catch (e: any) {
402
+ this.config.debugError('nymph', `Failed to start transaction: ${e}`);
403
+ throw e;
404
+ }
260
405
  }
261
406
 
262
407
  /**
@@ -267,7 +412,24 @@ export default class Nymph {
267
412
  * @returns True on success, false on failure.
268
413
  */
269
414
  public async commit(name: string): Promise<boolean> {
270
- return await this.driver.commit(name);
415
+ try {
416
+ for (let callback of this.beforeCommitTransactionCallbacks) {
417
+ if (callback) {
418
+ await callback(this, name);
419
+ }
420
+ }
421
+ this.config.debugLog('nymph', `Committing transaction "${name}".`);
422
+ const result = await this.driver.commit(name);
423
+ for (let callback of this.afterCommitTransactionCallbacks) {
424
+ if (callback) {
425
+ await callback(this, name, result);
426
+ }
427
+ }
428
+ return result;
429
+ } catch (e: any) {
430
+ this.config.debugError('nymph', `Failed to commit transaction: ${e}`);
431
+ throw e;
432
+ }
271
433
  }
272
434
 
273
435
  /**
@@ -278,7 +440,24 @@ export default class Nymph {
278
440
  * @returns True on success, false on failure.
279
441
  */
280
442
  public async rollback(name: string): Promise<boolean> {
281
- return await this.driver.rollback(name);
443
+ try {
444
+ for (let callback of this.beforeRollbackTransactionCallbacks) {
445
+ if (callback) {
446
+ await callback(this, name);
447
+ }
448
+ }
449
+ this.config.debugLog('nymph', `Rolling back transaction "${name}".`);
450
+ const result = await this.driver.rollback(name);
451
+ for (let callback of this.afterRollbackTransactionCallbacks) {
452
+ if (callback) {
453
+ await callback(this, name, result);
454
+ }
455
+ }
456
+ return result;
457
+ } catch (e: any) {
458
+ this.config.debugError('nymph', `Failed to roll back transaction: ${e}`);
459
+ throw e;
460
+ }
282
461
  }
283
462
 
284
463
  /**
@@ -312,18 +491,33 @@ export default class Nymph {
312
491
  * @returns The UID's new value, or null on failure.
313
492
  */
314
493
  public async newUID(name: string): Promise<number | null> {
315
- for (let callback of this.beforeNewUIDCallbacks) {
316
- if (callback) {
317
- await callback(this, name);
494
+ try {
495
+ for (let callback of this.beforeNewUIDCallbacks) {
496
+ if (callback) {
497
+ await callback(this, name);
498
+ }
318
499
  }
319
- }
320
- const result = this.driver.newUID(name);
321
- for (let callback of this.afterNewUIDCallbacks) {
322
- if (callback) {
323
- await callback(this, result);
500
+ let result: Promise<number | null>;
501
+ try {
502
+ result = this.driver.newUID(name);
503
+ } catch (e: any) {
504
+ for (let callback of this.failedNewUIDCallbacks) {
505
+ if (callback) {
506
+ await callback(this, e);
507
+ }
508
+ }
509
+ throw e;
510
+ }
511
+ for (let callback of this.afterNewUIDCallbacks) {
512
+ if (callback) {
513
+ await callback(this, result);
514
+ }
324
515
  }
516
+ return await result;
517
+ } catch (e: any) {
518
+ this.config.debugError('nymph', `Failed to create UID "${name}": ${e}`);
519
+ throw e;
325
520
  }
326
- return await result;
327
521
  }
328
522
 
329
523
  /**
@@ -332,7 +526,12 @@ export default class Nymph {
332
526
  * @returns The UID's value, or null on failure and if it doesn't exist.
333
527
  */
334
528
  public async getUID(name: string): Promise<number | null> {
335
- return await this.driver.getUID(name);
529
+ try {
530
+ return await this.driver.getUID(name);
531
+ } catch (e: any) {
532
+ this.config.debugError('nymph', `Failed to get UID "${name}": ${e}`);
533
+ throw e;
534
+ }
336
535
  }
337
536
 
338
537
  /**
@@ -343,18 +542,33 @@ export default class Nymph {
343
542
  * @returns True on success, false on failure.
344
543
  */
345
544
  public async setUID(name: string, value: number): Promise<boolean> {
346
- for (let callback of this.beforeSetUIDCallbacks) {
347
- if (callback) {
348
- await callback(this, name, value);
545
+ try {
546
+ for (let callback of this.beforeSetUIDCallbacks) {
547
+ if (callback) {
548
+ await callback(this, name, value);
549
+ }
349
550
  }
350
- }
351
- const result = this.driver.setUID(name, value);
352
- for (let callback of this.afterSetUIDCallbacks) {
353
- if (callback) {
354
- await callback(this, result);
551
+ let result: Promise<boolean>;
552
+ try {
553
+ result = this.driver.setUID(name, value);
554
+ } catch (e: any) {
555
+ for (let callback of this.failedSetUIDCallbacks) {
556
+ if (callback) {
557
+ await callback(this, e);
558
+ }
559
+ }
560
+ throw e;
355
561
  }
562
+ for (let callback of this.afterSetUIDCallbacks) {
563
+ if (callback) {
564
+ await callback(this, result);
565
+ }
566
+ }
567
+ return await result;
568
+ } catch (e: any) {
569
+ this.config.debugError('nymph', `Failed to set UID "${name}": ${e}`);
570
+ throw e;
356
571
  }
357
- return await result;
358
572
  }
359
573
 
360
574
  /**
@@ -364,18 +578,33 @@ export default class Nymph {
364
578
  * @returns True on success, false on failure.
365
579
  */
366
580
  public async deleteUID(name: string): Promise<boolean> {
367
- for (let callback of this.beforeDeleteUIDCallbacks) {
368
- if (callback) {
369
- await callback(this, name);
581
+ try {
582
+ for (let callback of this.beforeDeleteUIDCallbacks) {
583
+ if (callback) {
584
+ await callback(this, name);
585
+ }
370
586
  }
371
- }
372
- const result = this.driver.deleteUID(name);
373
- for (let callback of this.afterDeleteUIDCallbacks) {
374
- if (callback) {
375
- await callback(this, result);
587
+ let result: Promise<boolean>;
588
+ try {
589
+ result = this.driver.deleteUID(name);
590
+ } catch (e: any) {
591
+ for (let callback of this.failedDeleteUIDCallbacks) {
592
+ if (callback) {
593
+ await callback(this, e);
594
+ }
595
+ }
596
+ throw e;
597
+ }
598
+ for (let callback of this.afterDeleteUIDCallbacks) {
599
+ if (callback) {
600
+ await callback(this, result);
601
+ }
376
602
  }
603
+ return await result;
604
+ } catch (e: any) {
605
+ this.config.debugError('nymph', `Failed to delete UID "${name}": ${e}`);
606
+ throw e;
377
607
  }
378
- return await result;
379
608
  }
380
609
 
381
610
  /**
@@ -386,18 +615,36 @@ export default class Nymph {
386
615
  * @returns True on success, false on failure.
387
616
  */
388
617
  public async renameUID(oldName: string, newName: string): Promise<boolean> {
389
- for (let callback of this.beforeRenameUIDCallbacks) {
390
- if (callback) {
391
- await callback(this, oldName, newName);
618
+ try {
619
+ for (let callback of this.beforeRenameUIDCallbacks) {
620
+ if (callback) {
621
+ await callback(this, oldName, newName);
622
+ }
392
623
  }
393
- }
394
- const result = this.driver.renameUID(oldName, newName);
395
- for (let callback of this.afterRenameUIDCallbacks) {
396
- if (callback) {
397
- await callback(this, result);
624
+ let result: Promise<boolean>;
625
+ try {
626
+ result = this.driver.renameUID(oldName, newName);
627
+ } catch (e: any) {
628
+ for (let callback of this.failedRenameUIDCallbacks) {
629
+ if (callback) {
630
+ await callback(this, e);
631
+ }
632
+ }
633
+ throw e;
634
+ }
635
+ for (let callback of this.afterRenameUIDCallbacks) {
636
+ if (callback) {
637
+ await callback(this, result);
638
+ }
398
639
  }
640
+ return await result;
641
+ } catch (e: any) {
642
+ this.config.debugError(
643
+ 'nymph',
644
+ `Failed to rename UID "${oldName}" to "${newName}": ${e}`,
645
+ );
646
+ throw e;
399
647
  }
400
- return await result;
401
648
  }
402
649
 
403
650
  /**
@@ -412,18 +659,33 @@ export default class Nymph {
412
659
  * @returns True on success, false on failure.
413
660
  */
414
661
  public async saveEntity(entity: EntityInterface): Promise<boolean> {
415
- for (let callback of this.beforeSaveEntityCallbacks) {
416
- if (callback) {
417
- await callback(this, entity);
662
+ try {
663
+ for (let callback of this.beforeSaveEntityCallbacks) {
664
+ if (callback) {
665
+ await callback(this, entity);
666
+ }
418
667
  }
419
- }
420
- const result = this.driver.saveEntity(entity);
421
- for (let callback of this.afterSaveEntityCallbacks) {
422
- if (callback) {
423
- await callback(this, result);
668
+ let result: Promise<boolean>;
669
+ try {
670
+ result = this.driver.saveEntity(entity);
671
+ } catch (e: any) {
672
+ for (let callback of this.failedSaveEntityCallbacks) {
673
+ if (callback) {
674
+ await callback(this, e);
675
+ }
676
+ }
677
+ throw e;
424
678
  }
679
+ for (let callback of this.afterSaveEntityCallbacks) {
680
+ if (callback) {
681
+ await callback(this, result);
682
+ }
683
+ }
684
+ return await result;
685
+ } catch (e: any) {
686
+ this.config.debugError('nymph', `Failed to save entity: ${e}`);
687
+ throw e;
425
688
  }
426
- return await result;
427
689
  }
428
690
 
429
691
  /**
@@ -436,8 +698,10 @@ export default class Nymph {
436
698
  * - offset - The offset from the oldest matching entity to start retrieving.
437
699
  * - reverse - If true, entities will be retrieved from newest to oldest.
438
700
  * Therefore, offset will be from the newest entity.
439
- * - sort - How to sort the entities. Accepts "cdate" or "mdate". Defaults to
440
- * "cdate".
701
+ * - sort - How to sort the entities. Accepts "cdate", "mdate", or the name of
702
+ * a top-level property. The method of sorting properties other than cdate
703
+ * and mdate is driver dependent. The only hard rule is that numbers should
704
+ * be sorted numerically (2 before 10). Defaults to "cdate".
441
705
  * - return - What to return. "entity", "guid", or "count". Defaults to
442
706
  * "entity".
443
707
  * - source - Will be 'client' if the query came from a REST call.
@@ -596,17 +860,22 @@ export default class Nymph {
596
860
  public async getEntities<T extends EntityConstructor = EntityConstructor>(
597
861
  options?: Options<T>,
598
862
  ...selectors: Selector[]
599
- ): Promise<ReturnType<T['factorySync']>[]>;
863
+ ): Promise<EntityInstanceType<T>[]>;
600
864
  public async getEntities<T extends EntityConstructor = EntityConstructor>(
601
865
  options: Options<T> = {},
602
866
  ...selectors: Selector[]
603
- ): Promise<ReturnType<T['factorySync']>[] | string[] | number> {
604
- for (let callback of this.beforeGetEntitiesCallbacks) {
605
- if (callback) {
606
- await callback(this, options, selectors);
867
+ ): Promise<EntityInstanceType<T>[] | string[] | number> {
868
+ try {
869
+ for (let callback of this.beforeGetEntitiesCallbacks) {
870
+ if (callback) {
871
+ await callback(this, options, selectors);
872
+ }
607
873
  }
874
+ return await this.driver.getEntities(options, ...selectors);
875
+ } catch (e: any) {
876
+ this.config.debugError('nymph', `Failed to get entities: ${e}`);
877
+ throw e;
608
878
  }
609
- return await this.driver.getEntities(options, ...selectors);
610
879
  }
611
880
 
612
881
  /**
@@ -633,40 +902,45 @@ export default class Nymph {
633
902
  public async getEntity<T extends EntityConstructor = EntityConstructor>(
634
903
  options: Options<T>,
635
904
  ...selectors: Selector[]
636
- ): Promise<ReturnType<T['factorySync']> | null>;
905
+ ): Promise<EntityInstanceType<T> | null>;
637
906
  public async getEntity<T extends EntityConstructor = EntityConstructor>(
638
907
  options: Options<T> & { return: 'guid' },
639
- guid: string
908
+ guid: string,
640
909
  ): Promise<string | null>;
641
910
  public async getEntity<T extends EntityConstructor = EntityConstructor>(
642
911
  options: Options<T>,
643
- guid: string
644
- ): Promise<ReturnType<T['factorySync']> | null>;
912
+ guid: string,
913
+ ): Promise<EntityInstanceType<T> | null>;
645
914
  public async getEntity<T extends EntityConstructor = EntityConstructor>(
646
915
  options: Options<T> = {},
647
916
  ...selectors: Selector[] | string[]
648
- ): Promise<ReturnType<T['factorySync']> | string | number | null> {
649
- // Set up options and selectors.
650
- if (typeof selectors[0] === 'string') {
651
- selectors = [{ type: '&', guid: selectors[0] }];
652
- }
653
- options.limit = 1;
654
- for (let callback of this.beforeGetEntityCallbacks) {
655
- if (callback) {
656
- await callback(this, options, selectors as Selector[]);
917
+ ): Promise<EntityInstanceType<T> | string | number | null> {
918
+ try {
919
+ // Set up options and selectors.
920
+ if (typeof selectors[0] === 'string') {
921
+ selectors = [{ type: '&', guid: selectors[0] }];
657
922
  }
923
+ options.limit = 1;
924
+ for (let callback of this.beforeGetEntityCallbacks) {
925
+ if (callback) {
926
+ await callback(this, options, selectors as Selector[]);
927
+ }
928
+ }
929
+ const entities = await this.driver.getEntities(
930
+ options,
931
+ ...(selectors as Selector[]),
932
+ );
933
+ if (options.return === 'count') {
934
+ return entities as unknown as number;
935
+ }
936
+ if (!entities || !entities.length) {
937
+ return null;
938
+ }
939
+ return entities[0];
940
+ } catch (e: any) {
941
+ this.config.debugError('nymph', `Failed to get entity: ${e}`);
942
+ throw e;
658
943
  }
659
- const entities = await this.driver.getEntities(
660
- options,
661
- ...(selectors as Selector[])
662
- );
663
- if (options.return === 'count') {
664
- return entities as unknown as number;
665
- }
666
- if (!entities || !entities.length) {
667
- return null;
668
- }
669
- return entities[0];
670
944
  }
671
945
 
672
946
  /**
@@ -676,18 +950,33 @@ export default class Nymph {
676
950
  * @returns True on success, false on failure.
677
951
  */
678
952
  public async deleteEntity(entity: EntityInterface): Promise<boolean> {
679
- for (let callback of this.beforeDeleteEntityCallbacks) {
680
- if (callback) {
681
- await callback(this, entity);
953
+ try {
954
+ for (let callback of this.beforeDeleteEntityCallbacks) {
955
+ if (callback) {
956
+ await callback(this, entity);
957
+ }
682
958
  }
683
- }
684
- const result = this.driver.deleteEntity(entity);
685
- for (let callback of this.afterDeleteEntityCallbacks) {
686
- if (callback) {
687
- await callback(this, result);
959
+ let result: Promise<boolean>;
960
+ try {
961
+ result = this.driver.deleteEntity(entity);
962
+ } catch (e: any) {
963
+ for (let callback of this.failedDeleteEntityCallbacks) {
964
+ if (callback) {
965
+ await callback(this, e);
966
+ }
967
+ }
968
+ throw e;
688
969
  }
970
+ for (let callback of this.afterDeleteEntityCallbacks) {
971
+ if (callback) {
972
+ await callback(this, result);
973
+ }
974
+ }
975
+ return await result;
976
+ } catch (e: any) {
977
+ this.config.debugError('nymph', `Failed to delete entity: ${e}`);
978
+ throw e;
689
979
  }
690
- return await result;
691
980
  }
692
981
 
693
982
  /**
@@ -699,20 +988,35 @@ export default class Nymph {
699
988
  */
700
989
  public async deleteEntityByID(
701
990
  guid: string,
702
- className?: string
991
+ className?: string,
703
992
  ): Promise<boolean> {
704
- for (let callback of this.beforeDeleteEntityByIDCallbacks) {
705
- if (callback) {
706
- await callback(this, guid, className);
993
+ try {
994
+ for (let callback of this.beforeDeleteEntityByIDCallbacks) {
995
+ if (callback) {
996
+ await callback(this, guid, className);
997
+ }
707
998
  }
708
- }
709
- const result = this.driver.deleteEntityByID(guid, className);
710
- for (let callback of this.afterDeleteEntityByIDCallbacks) {
711
- if (callback) {
712
- await callback(this, result);
999
+ let result: Promise<boolean>;
1000
+ try {
1001
+ result = this.driver.deleteEntityByID(guid, className);
1002
+ } catch (e: any) {
1003
+ for (let callback of this.failedDeleteEntityByIDCallbacks) {
1004
+ if (callback) {
1005
+ await callback(this, e);
1006
+ }
1007
+ }
1008
+ throw e;
1009
+ }
1010
+ for (let callback of this.afterDeleteEntityByIDCallbacks) {
1011
+ if (callback) {
1012
+ await callback(this, result);
1013
+ }
713
1014
  }
1015
+ return await result;
1016
+ } catch (e: any) {
1017
+ this.config.debugError('nymph', `Failed to delete entity by ID: ${e}`);
1018
+ throw e;
714
1019
  }
715
- return await result;
716
1020
  }
717
1021
 
718
1022
  /**
@@ -737,7 +1041,7 @@ export default class Nymph {
737
1041
  * # brackets ([]).
738
1042
  * # Properties are stored like this:
739
1043
  * # propname=JSON.stringify(value)
740
- * abilities=["system/all"]
1044
+ * abilities=["system/admin"]
741
1045
  * groups=[]
742
1046
  * inheritAbilities=false
743
1047
  * name="admin"
@@ -752,7 +1056,12 @@ export default class Nymph {
752
1056
  * @returns True on success, false on failure.
753
1057
  */
754
1058
  public async export(filename: string): Promise<boolean> {
755
- return await this.driver.export(filename);
1059
+ try {
1060
+ return await this.driver.export(filename);
1061
+ } catch (e: any) {
1062
+ this.config.debugError('nymph', `Failed to export: ${e}`);
1063
+ throw e;
1064
+ }
756
1065
  }
757
1066
 
758
1067
  /**
@@ -761,7 +1070,12 @@ export default class Nymph {
761
1070
  * @returns True on success, false on failure.
762
1071
  */
763
1072
  public async exportPrint(): Promise<boolean> {
764
- return await this.driver.exportPrint();
1073
+ try {
1074
+ return await this.driver.exportPrint();
1075
+ } catch (e: any) {
1076
+ this.config.debugError('nymph', `Failed to export: ${e}`);
1077
+ throw e;
1078
+ }
765
1079
  }
766
1080
 
767
1081
  /**
@@ -771,7 +1085,22 @@ export default class Nymph {
771
1085
  * @returns True on success, false on failure.
772
1086
  */
773
1087
  public async import(filename: string): Promise<boolean> {
774
- return await this.driver.import(filename);
1088
+ try {
1089
+ return await this.driver.import(filename);
1090
+ } catch (e: any) {
1091
+ this.config.debugError('nymph', `Failed to import: ${e}`);
1092
+ throw e;
1093
+ }
1094
+ }
1095
+
1096
+ /**
1097
+ * Detect whether the database needs to be migrated.
1098
+ *
1099
+ * If true, the database should be exported with an old version of Nymph, then
1100
+ * imported into a fresh database with this version.
1101
+ */
1102
+ public async needsMigration(): Promise<boolean> {
1103
+ return await this.driver.needsMigration();
775
1104
  }
776
1105
 
777
1106
  public on<T extends NymphEventType>(
@@ -779,82 +1108,134 @@ export default class Nymph {
779
1108
  callback: T extends 'connect'
780
1109
  ? NymphConnectCallback
781
1110
  : T extends 'disconnect'
782
- ? NymphDisconnectCallback
783
- : T extends 'query'
784
- ? NymphQueryCallback
785
- : T extends 'beforeGetEntity'
786
- ? NymphBeforeGetEntityCallback
787
- : T extends 'beforeGetEntities'
788
- ? NymphBeforeGetEntitiesCallback
789
- : T extends 'beforeSaveEntity'
790
- ? NymphBeforeSaveEntityCallback
791
- : T extends 'afterSaveEntity'
792
- ? NymphAfterSaveEntityCallback
793
- : T extends 'beforeDeleteEntity'
794
- ? NymphBeforeDeleteEntityCallback
795
- : T extends 'afterDeleteEntity'
796
- ? NymphAfterDeleteEntityCallback
797
- : T extends 'beforeDeleteEntityByID'
798
- ? NymphBeforeDeleteEntityByIDCallback
799
- : T extends 'afterDeleteEntityByID'
800
- ? NymphAfterDeleteEntityByIDCallback
801
- : T extends 'beforeNewUID'
802
- ? NymphBeforeNewUIDCallback
803
- : T extends 'afterNewUID'
804
- ? NymphAfterNewUIDCallback
805
- : T extends 'beforeSetUID'
806
- ? NymphBeforeSetUIDCallback
807
- : T extends 'afterSetUID'
808
- ? NymphAfterSetUIDCallback
809
- : T extends 'beforeRenameUID'
810
- ? NymphBeforeRenameUIDCallback
811
- : T extends 'afterRenameUID'
812
- ? NymphAfterRenameUIDCallback
813
- : T extends 'beforeDeleteUID'
814
- ? NymphBeforeDeleteUIDCallback
815
- : T extends 'afterDeleteUID'
816
- ? NymphAfterDeleteUIDCallback
817
- : never
1111
+ ? NymphDisconnectCallback
1112
+ : T extends 'query'
1113
+ ? NymphQueryCallback
1114
+ : T extends 'beforeGetEntity'
1115
+ ? NymphBeforeGetEntityCallback
1116
+ : T extends 'beforeGetEntities'
1117
+ ? NymphBeforeGetEntitiesCallback
1118
+ : T extends 'beforeSaveEntity'
1119
+ ? NymphBeforeSaveEntityCallback
1120
+ : T extends 'afterSaveEntity'
1121
+ ? NymphAfterSaveEntityCallback
1122
+ : T extends 'failedSaveEntity'
1123
+ ? NymphFailedSaveEntityCallback
1124
+ : T extends 'beforeDeleteEntity'
1125
+ ? NymphBeforeDeleteEntityCallback
1126
+ : T extends 'afterDeleteEntity'
1127
+ ? NymphAfterDeleteEntityCallback
1128
+ : T extends 'failedDeleteEntity'
1129
+ ? NymphFailedDeleteEntityCallback
1130
+ : T extends 'beforeDeleteEntityByID'
1131
+ ? NymphBeforeDeleteEntityByIDCallback
1132
+ : T extends 'afterDeleteEntityByID'
1133
+ ? NymphAfterDeleteEntityByIDCallback
1134
+ : T extends 'failedDeleteEntityByID'
1135
+ ? NymphFailedDeleteEntityByIDCallback
1136
+ : T extends 'beforeNewUID'
1137
+ ? NymphBeforeNewUIDCallback
1138
+ : T extends 'afterNewUID'
1139
+ ? NymphAfterNewUIDCallback
1140
+ : T extends 'failedNewUID'
1141
+ ? NymphFailedNewUIDCallback
1142
+ : T extends 'beforeSetUID'
1143
+ ? NymphBeforeSetUIDCallback
1144
+ : T extends 'afterSetUID'
1145
+ ? NymphAfterSetUIDCallback
1146
+ : T extends 'failedSetUID'
1147
+ ? NymphFailedSetUIDCallback
1148
+ : T extends 'beforeRenameUID'
1149
+ ? NymphBeforeRenameUIDCallback
1150
+ : T extends 'afterRenameUID'
1151
+ ? NymphAfterRenameUIDCallback
1152
+ : T extends 'failedRenameUID'
1153
+ ? NymphFailedRenameUIDCallback
1154
+ : T extends 'beforeDeleteUID'
1155
+ ? NymphBeforeDeleteUIDCallback
1156
+ : T extends 'afterDeleteUID'
1157
+ ? NymphAfterDeleteUIDCallback
1158
+ : T extends 'failedDeleteUID'
1159
+ ? NymphFailedDeleteUIDCallback
1160
+ : T extends 'beforeStartTransaction'
1161
+ ? NymphBeforeStartTransactionCallback
1162
+ : T extends 'afterStartTransaction'
1163
+ ? NymphAfterStartTransactionCallback
1164
+ : T extends 'beforeCommitTransaction'
1165
+ ? NymphBeforeCommitTransactionCallback
1166
+ : T extends 'afterCommitTransaction'
1167
+ ? NymphAfterCommitTransactionCallback
1168
+ : T extends 'beforeRollbackTransaction'
1169
+ ? NymphBeforeRollbackTransactionCallback
1170
+ : T extends 'afterRollbackTransaction'
1171
+ ? NymphAfterRollbackTransactionCallback
1172
+ : never,
818
1173
  ) {
819
1174
  const prop = (event + 'Callbacks') as T extends 'connect'
820
1175
  ? 'connectCallbacks'
821
1176
  : T extends 'disconnect'
822
- ? 'disconnectCallbacks'
823
- : T extends 'query'
824
- ? 'queryCallbacks'
825
- : T extends 'beforeGetEntity'
826
- ? 'beforeGetEntityCallbacks'
827
- : T extends 'beforeGetEntities'
828
- ? 'beforeGetEntitiesCallbacks'
829
- : T extends 'beforeSaveEntity'
830
- ? 'beforeSaveEntityCallbacks'
831
- : T extends 'afterSaveEntity'
832
- ? 'afterSaveEntityCallbacks'
833
- : T extends 'beforeDeleteEntity'
834
- ? 'beforeDeleteEntityCallbacks'
835
- : T extends 'afterDeleteEntity'
836
- ? 'afterDeleteEntityCallbacks'
837
- : T extends 'beforeDeleteEntityByID'
838
- ? 'beforeDeleteEntityByIDCallbacks'
839
- : T extends 'afterDeleteEntityByID'
840
- ? 'afterDeleteEntityByIDCallbacks'
841
- : T extends 'beforeNewUID'
842
- ? 'beforeNewUIDCallbacks'
843
- : T extends 'afterNewUID'
844
- ? 'afterNewUIDCallbacks'
845
- : T extends 'beforeSetUID'
846
- ? 'beforeSetUIDCallbacks'
847
- : T extends 'afterSetUID'
848
- ? 'afterSetUIDCallbacks'
849
- : T extends 'beforeRenameUID'
850
- ? 'beforeRenameUIDCallbacks'
851
- : T extends 'afterRenameUID'
852
- ? 'afterRenameUIDCallbacks'
853
- : T extends 'beforeDeleteUID'
854
- ? 'beforeDeleteUIDCallbacks'
855
- : T extends 'afterDeleteUID'
856
- ? 'afterDeleteUIDCallbacks'
857
- : never;
1177
+ ? 'disconnectCallbacks'
1178
+ : T extends 'query'
1179
+ ? 'queryCallbacks'
1180
+ : T extends 'beforeGetEntity'
1181
+ ? 'beforeGetEntityCallbacks'
1182
+ : T extends 'beforeGetEntities'
1183
+ ? 'beforeGetEntitiesCallbacks'
1184
+ : T extends 'beforeSaveEntity'
1185
+ ? 'beforeSaveEntityCallbacks'
1186
+ : T extends 'afterSaveEntity'
1187
+ ? 'afterSaveEntityCallbacks'
1188
+ : T extends 'failedSaveEntity'
1189
+ ? 'failedSaveEntityCallbacks'
1190
+ : T extends 'beforeDeleteEntity'
1191
+ ? 'beforeDeleteEntityCallbacks'
1192
+ : T extends 'afterDeleteEntity'
1193
+ ? 'afterDeleteEntityCallbacks'
1194
+ : T extends 'failedDeleteEntity'
1195
+ ? 'failedDeleteEntityCallbacks'
1196
+ : T extends 'beforeDeleteEntityByID'
1197
+ ? 'beforeDeleteEntityByIDCallbacks'
1198
+ : T extends 'afterDeleteEntityByID'
1199
+ ? 'afterDeleteEntityByIDCallbacks'
1200
+ : T extends 'failedDeleteEntityByID'
1201
+ ? 'failedDeleteEntityByIDCallbacks'
1202
+ : T extends 'beforeNewUID'
1203
+ ? 'beforeNewUIDCallbacks'
1204
+ : T extends 'afterNewUID'
1205
+ ? 'afterNewUIDCallbacks'
1206
+ : T extends 'failedNewUID'
1207
+ ? 'failedNewUIDCallbacks'
1208
+ : T extends 'beforeSetUID'
1209
+ ? 'beforeSetUIDCallbacks'
1210
+ : T extends 'afterSetUID'
1211
+ ? 'afterSetUIDCallbacks'
1212
+ : T extends 'failedSetUID'
1213
+ ? 'failedSetUIDCallbacks'
1214
+ : T extends 'beforeRenameUID'
1215
+ ? 'beforeRenameUIDCallbacks'
1216
+ : T extends 'afterRenameUID'
1217
+ ? 'afterRenameUIDCallbacks'
1218
+ : T extends 'failedRenameUID'
1219
+ ? 'failedRenameUIDCallbacks'
1220
+ : T extends 'beforeDeleteUID'
1221
+ ? 'beforeDeleteUIDCallbacks'
1222
+ : T extends 'afterDeleteUID'
1223
+ ? 'afterDeleteUIDCallbacks'
1224
+ : T extends 'failedDeleteUID'
1225
+ ? 'failedDeleteUIDCallbacks'
1226
+ : T extends 'beforeStartTransaction'
1227
+ ? 'beforeStartTransactionCallbacks'
1228
+ : T extends 'afterStartTransaction'
1229
+ ? 'afterStartTransactionCallbacks'
1230
+ : T extends 'beforeCommitTransaction'
1231
+ ? 'beforeCommitTransactionCallbacks'
1232
+ : T extends 'afterCommitTransaction'
1233
+ ? 'afterCommitTransactionCallbacks'
1234
+ : T extends 'beforeRollbackTransaction'
1235
+ ? 'beforeRollbackTransactionCallbacks'
1236
+ : T extends 'afterRollbackTransaction'
1237
+ ? 'afterRollbackTransactionCallbacks'
1238
+ : never;
858
1239
  if (!(prop in this)) {
859
1240
  throw new Error('Invalid event type.');
860
1241
  }
@@ -868,82 +1249,134 @@ export default class Nymph {
868
1249
  callback: T extends 'connect'
869
1250
  ? NymphConnectCallback
870
1251
  : T extends 'disconnect'
871
- ? NymphDisconnectCallback
872
- : T extends 'query'
873
- ? NymphQueryCallback
874
- : T extends 'beforeGetEntity'
875
- ? NymphBeforeGetEntityCallback
876
- : T extends 'beforeGetEntities'
877
- ? NymphBeforeGetEntitiesCallback
878
- : T extends 'beforeSaveEntity'
879
- ? NymphBeforeSaveEntityCallback
880
- : T extends 'afterSaveEntity'
881
- ? NymphAfterSaveEntityCallback
882
- : T extends 'beforeDeleteEntity'
883
- ? NymphBeforeDeleteEntityCallback
884
- : T extends 'afterDeleteEntity'
885
- ? NymphAfterDeleteEntityCallback
886
- : T extends 'beforeDeleteEntityByID'
887
- ? NymphBeforeDeleteEntityByIDCallback
888
- : T extends 'afterDeleteEntityByID'
889
- ? NymphAfterDeleteEntityByIDCallback
890
- : T extends 'beforeNewUID'
891
- ? NymphBeforeNewUIDCallback
892
- : T extends 'afterNewUID'
893
- ? NymphAfterNewUIDCallback
894
- : T extends 'beforeSetUID'
895
- ? NymphBeforeSetUIDCallback
896
- : T extends 'afterSetUID'
897
- ? NymphAfterSetUIDCallback
898
- : T extends 'beforeRenameUID'
899
- ? NymphBeforeRenameUIDCallback
900
- : T extends 'afterRenameUID'
901
- ? NymphAfterRenameUIDCallback
902
- : T extends 'beforeDeleteUID'
903
- ? NymphBeforeDeleteUIDCallback
904
- : T extends 'afterDeleteUID'
905
- ? NymphAfterDeleteUIDCallback
906
- : never
1252
+ ? NymphDisconnectCallback
1253
+ : T extends 'query'
1254
+ ? NymphQueryCallback
1255
+ : T extends 'beforeGetEntity'
1256
+ ? NymphBeforeGetEntityCallback
1257
+ : T extends 'beforeGetEntities'
1258
+ ? NymphBeforeGetEntitiesCallback
1259
+ : T extends 'beforeSaveEntity'
1260
+ ? NymphBeforeSaveEntityCallback
1261
+ : T extends 'afterSaveEntity'
1262
+ ? NymphAfterSaveEntityCallback
1263
+ : T extends 'failedSaveEntity'
1264
+ ? NymphFailedSaveEntityCallback
1265
+ : T extends 'beforeDeleteEntity'
1266
+ ? NymphBeforeDeleteEntityCallback
1267
+ : T extends 'afterDeleteEntity'
1268
+ ? NymphAfterDeleteEntityCallback
1269
+ : T extends 'failedDeleteEntity'
1270
+ ? NymphFailedDeleteEntityCallback
1271
+ : T extends 'beforeDeleteEntityByID'
1272
+ ? NymphBeforeDeleteEntityByIDCallback
1273
+ : T extends 'afterDeleteEntityByID'
1274
+ ? NymphAfterDeleteEntityByIDCallback
1275
+ : T extends 'failedDeleteEntityByID'
1276
+ ? NymphFailedDeleteEntityByIDCallback
1277
+ : T extends 'beforeNewUID'
1278
+ ? NymphBeforeNewUIDCallback
1279
+ : T extends 'afterNewUID'
1280
+ ? NymphAfterNewUIDCallback
1281
+ : T extends 'failedNewUID'
1282
+ ? NymphFailedNewUIDCallback
1283
+ : T extends 'beforeSetUID'
1284
+ ? NymphBeforeSetUIDCallback
1285
+ : T extends 'afterSetUID'
1286
+ ? NymphAfterSetUIDCallback
1287
+ : T extends 'failedSetUID'
1288
+ ? NymphFailedSetUIDCallback
1289
+ : T extends 'beforeRenameUID'
1290
+ ? NymphBeforeRenameUIDCallback
1291
+ : T extends 'afterRenameUID'
1292
+ ? NymphAfterRenameUIDCallback
1293
+ : T extends 'failedRenameUID'
1294
+ ? NymphFailedRenameUIDCallback
1295
+ : T extends 'beforeDeleteUID'
1296
+ ? NymphBeforeDeleteUIDCallback
1297
+ : T extends 'afterDeleteUID'
1298
+ ? NymphAfterDeleteUIDCallback
1299
+ : T extends 'failedDeleteUID'
1300
+ ? NymphFailedDeleteUIDCallback
1301
+ : T extends 'beforeStartTransaction'
1302
+ ? NymphBeforeStartTransactionCallback
1303
+ : T extends 'afterStartTransaction'
1304
+ ? NymphAfterStartTransactionCallback
1305
+ : T extends 'beforeCommitTransaction'
1306
+ ? NymphBeforeCommitTransactionCallback
1307
+ : T extends 'afterCommitTransaction'
1308
+ ? NymphAfterCommitTransactionCallback
1309
+ : T extends 'beforeRollbackTransaction'
1310
+ ? NymphBeforeRollbackTransactionCallback
1311
+ : T extends 'afterRollbackTransaction'
1312
+ ? NymphAfterRollbackTransactionCallback
1313
+ : never,
907
1314
  ) {
908
1315
  const prop = (event + 'Callbacks') as T extends 'connect'
909
1316
  ? 'connectCallbacks'
910
1317
  : T extends 'disconnect'
911
- ? 'disconnectCallbacks'
912
- : T extends 'query'
913
- ? 'queryCallbacks'
914
- : T extends 'beforeSaveEntity'
915
- ? 'beforeSaveEntityCallbacks'
916
- : T extends 'beforeGetEntity'
917
- ? 'beforeGetEntityCallbacks'
918
- : T extends 'beforeGetEntities'
919
- ? 'beforeGetEntitiesCallbacks'
920
- : T extends 'afterSaveEntity'
921
- ? 'afterSaveEntityCallbacks'
922
- : T extends 'beforeDeleteEntity'
923
- ? 'beforeDeleteEntityCallbacks'
924
- : T extends 'afterDeleteEntity'
925
- ? 'afterDeleteEntityCallbacks'
926
- : T extends 'beforeDeleteEntityByID'
927
- ? 'beforeDeleteEntityByIDCallbacks'
928
- : T extends 'afterDeleteEntityByID'
929
- ? 'afterDeleteEntityByIDCallbacks'
930
- : T extends 'beforeNewUID'
931
- ? 'beforeNewUIDCallbacks'
932
- : T extends 'afterNewUID'
933
- ? 'afterNewUIDCallbacks'
934
- : T extends 'beforeSetUID'
935
- ? 'beforeSetUIDCallbacks'
936
- : T extends 'afterSetUID'
937
- ? 'afterSetUIDCallbacks'
938
- : T extends 'beforeRenameUID'
939
- ? 'beforeRenameUIDCallbacks'
940
- : T extends 'afterRenameUID'
941
- ? 'afterRenameUIDCallbacks'
942
- : T extends 'beforeDeleteUID'
943
- ? 'beforeDeleteUIDCallbacks'
944
- : T extends 'afterDeleteUID'
945
- ? 'afterDeleteUIDCallbacks'
946
- : never;
1318
+ ? 'disconnectCallbacks'
1319
+ : T extends 'query'
1320
+ ? 'queryCallbacks'
1321
+ : T extends 'beforeSaveEntity'
1322
+ ? 'beforeSaveEntityCallbacks'
1323
+ : T extends 'beforeGetEntity'
1324
+ ? 'beforeGetEntityCallbacks'
1325
+ : T extends 'beforeGetEntities'
1326
+ ? 'beforeGetEntitiesCallbacks'
1327
+ : T extends 'afterSaveEntity'
1328
+ ? 'afterSaveEntityCallbacks'
1329
+ : T extends 'failedSaveEntity'
1330
+ ? 'failedSaveEntityCallbacks'
1331
+ : T extends 'beforeDeleteEntity'
1332
+ ? 'beforeDeleteEntityCallbacks'
1333
+ : T extends 'afterDeleteEntity'
1334
+ ? 'afterDeleteEntityCallbacks'
1335
+ : T extends 'failedDeleteEntity'
1336
+ ? 'failedDeleteEntityCallbacks'
1337
+ : T extends 'beforeDeleteEntityByID'
1338
+ ? 'beforeDeleteEntityByIDCallbacks'
1339
+ : T extends 'afterDeleteEntityByID'
1340
+ ? 'afterDeleteEntityByIDCallbacks'
1341
+ : T extends 'failedDeleteEntityByID'
1342
+ ? 'failedDeleteEntityByIDCallbacks'
1343
+ : T extends 'beforeNewUID'
1344
+ ? 'beforeNewUIDCallbacks'
1345
+ : T extends 'afterNewUID'
1346
+ ? 'afterNewUIDCallbacks'
1347
+ : T extends 'failedNewUID'
1348
+ ? 'failedNewUIDCallbacks'
1349
+ : T extends 'beforeSetUID'
1350
+ ? 'beforeSetUIDCallbacks'
1351
+ : T extends 'afterSetUID'
1352
+ ? 'afterSetUIDCallbacks'
1353
+ : T extends 'failedSetUID'
1354
+ ? 'failedSetUIDCallbacks'
1355
+ : T extends 'beforeRenameUID'
1356
+ ? 'beforeRenameUIDCallbacks'
1357
+ : T extends 'afterRenameUID'
1358
+ ? 'afterRenameUIDCallbacks'
1359
+ : T extends 'failedRenameUID'
1360
+ ? 'failedRenameUIDCallbacks'
1361
+ : T extends 'beforeDeleteUID'
1362
+ ? 'beforeDeleteUIDCallbacks'
1363
+ : T extends 'afterDeleteUID'
1364
+ ? 'afterDeleteUIDCallbacks'
1365
+ : T extends 'failedDeleteUID'
1366
+ ? 'failedDeleteUIDCallbacks'
1367
+ : T extends 'beforeStartTransaction'
1368
+ ? 'beforeStartTransactionCallbacks'
1369
+ : T extends 'afterStartTransaction'
1370
+ ? 'afterStartTransactionCallbacks'
1371
+ : T extends 'beforeCommitTransaction'
1372
+ ? 'beforeCommitTransactionCallbacks'
1373
+ : T extends 'afterCommitTransaction'
1374
+ ? 'afterCommitTransactionCallbacks'
1375
+ : T extends 'beforeRollbackTransaction'
1376
+ ? 'beforeRollbackTransactionCallbacks'
1377
+ : T extends 'afterRollbackTransaction'
1378
+ ? 'afterRollbackTransactionCallbacks'
1379
+ : never;
947
1380
  if (!(prop in this)) {
948
1381
  return false;
949
1382
  }