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

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 +650 -0
  2. package/README.md +34 -24
  3. package/dist/Entity.d.ts +306 -15
  4. package/dist/Entity.js +688 -226
  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 +646 -252
  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
package/dist/Nymph.d.ts CHANGED
@@ -1,14 +1,42 @@
1
- import { Config } from './conf';
2
- import { NymphDriver } from './driver';
3
- import Entity from './Entity';
4
- import { EntityConstructor, EntityInterface } from './Entity.types';
5
- import type { Selector, Options, NymphConnectCallback, NymphDisconnectCallback, NymphBeforeGetEntityCallback, NymphBeforeGetEntitiesCallback, NymphBeforeSaveEntityCallback, NymphAfterSaveEntityCallback, NymphFailedSaveEntityCallback, NymphBeforeDeleteEntityCallback, NymphAfterDeleteEntityCallback, NymphFailedDeleteEntityCallback, NymphBeforeDeleteEntityByIDCallback, NymphAfterDeleteEntityByIDCallback, NymphFailedDeleteEntityByIDCallback, NymphBeforeNewUIDCallback, NymphAfterNewUIDCallback, NymphFailedNewUIDCallback, NymphBeforeSetUIDCallback, NymphAfterSetUIDCallback, NymphFailedSetUIDCallback, NymphBeforeRenameUIDCallback, NymphAfterRenameUIDCallback, NymphFailedRenameUIDCallback, NymphBeforeDeleteUIDCallback, NymphAfterDeleteUIDCallback, NymphFailedDeleteUIDCallback, NymphBeforeStartTransactionCallback, NymphAfterStartTransactionCallback, NymphBeforeCommitTransactionCallback, NymphAfterCommitTransactionCallback, NymphBeforeRollbackTransactionCallback, NymphAfterRollbackTransactionCallback, NymphEventType, NymphQueryCallback, FormattedSelector, TilmeldInterface } from './Nymph.types';
1
+ import { Config } from './conf/index.js';
2
+ import type { NymphDriver } from './driver/index.js';
3
+ import Entity, { type EntityInstanceType, type EntityObjectType } from './Entity.js';
4
+ import type { EntityConstructor, EntityInterface, SerializedEntityData } from './Entity.types.js';
5
+ import type { Selector, Options, NymphConnectCallback, NymphDisconnectCallback, NymphBeforeGetEntityCallback, NymphBeforeGetEntitiesCallback, NymphBeforeSaveEntityCallback, NymphAfterSaveEntityCallback, NymphFailedSaveEntityCallback, NymphBeforeDeleteEntityCallback, NymphAfterDeleteEntityCallback, NymphFailedDeleteEntityCallback, NymphBeforeDeleteEntityByIDCallback, NymphAfterDeleteEntityByIDCallback, NymphFailedDeleteEntityByIDCallback, NymphBeforeNewUIDCallback, NymphAfterNewUIDCallback, NymphFailedNewUIDCallback, NymphBeforeSetUIDCallback, NymphAfterSetUIDCallback, NymphFailedSetUIDCallback, NymphBeforeRenameUIDCallback, NymphAfterRenameUIDCallback, NymphFailedRenameUIDCallback, NymphBeforeDeleteUIDCallback, NymphAfterDeleteUIDCallback, NymphFailedDeleteUIDCallback, NymphBeforeStartTransactionCallback, NymphAfterStartTransactionCallback, NymphBeforeCommitTransactionCallback, NymphAfterCommitTransactionCallback, NymphBeforeRollbackTransactionCallback, NymphAfterRollbackTransactionCallback, NymphEventType, NymphQueryCallback, FormattedSelector, TilmeldInterface } from './Nymph.types.js';
6
+ /**
7
+ * An object relational mapper for Node.js.
8
+ *
9
+ * Written by Hunter Perrin for SciActive.
10
+ *
11
+ * @author Hunter Perrin <hperrin@port87.com>
12
+ * @copyright SciActive Inc
13
+ * @see http://nymph.io/
14
+ */
6
15
  export default class Nymph {
16
+ /**
17
+ * The Nymph config.
18
+ */
7
19
  config: Config;
20
+ /**
21
+ * The Nymph instance that this one was cloned from, or null if it's not a
22
+ * clone.
23
+ */
8
24
  parent: Nymph | null;
25
+ /**
26
+ * The Nymph database driver.
27
+ */
9
28
  driver: NymphDriver;
29
+ /**
30
+ * An optional Tilmeld user/group manager instance.
31
+ */
10
32
  tilmeld?: TilmeldInterface;
33
+ /**
34
+ * A simple map of names to Entity classes.
35
+ */
11
36
  private entityClasses;
37
+ /**
38
+ * The entity class for this instance of Nymph.
39
+ */
12
40
  Entity: typeof Entity;
13
41
  private connectCallbacks;
14
42
  private disconnectCallbacks;
@@ -42,46 +70,582 @@ export default class Nymph {
42
70
  private afterCommitTransactionCallbacks;
43
71
  private beforeRollbackTransactionCallbacks;
44
72
  private afterRollbackTransactionCallbacks;
45
- constructor(config: Partial<Config>, driver: NymphDriver, tilmeld?: TilmeldInterface);
46
- addEntityClass<T extends EntityConstructor>(entityClass: T): T;
73
+ /**
74
+ * Initialize Nymph.
75
+ *
76
+ * @param config The Nymph configuration.
77
+ * @param driver The Nymph database driver.
78
+ * @param tilmeld The Tilmeld user/group manager instance, if you want to use it.
79
+ * @param parent Used internally by Nymph. Don't set this.
80
+ */
81
+ constructor(config: Partial<Config>, driver: NymphDriver, tilmeld?: TilmeldInterface, parent?: Nymph);
82
+ /**
83
+ * Add your class to this instance.
84
+ *
85
+ * This will create a class that extends your class within this instance of
86
+ * Nymph and return it. You can then use this class's constructor and methods,
87
+ * which will use this instance of Nymph.
88
+ *
89
+ * Because this creates a subclass, don't use the class
90
+ * returned from `getEntityClass` to check with `instanceof`.
91
+ */
92
+ addEntityClass<T extends EntityConstructor>(EntityClass: T): T;
93
+ /**
94
+ * Get the class that uses the specified class name.
95
+ */
47
96
  getEntityClass(className: string): EntityConstructor;
97
+ getEntityClass<T extends EntityConstructor>(className: T): T;
98
+ /**
99
+ * Get the class that uses the specified etype.
100
+ *
101
+ * Note that it is fine, though unusual, for two classes to use the same
102
+ * etype. However, this can lead to very hard to diagnose bugs, so is
103
+ * generally discouraged.
104
+ */
105
+ getEntityClassByEtype(etype: string): EntityConstructor;
106
+ /**
107
+ * Get a clone of this instance with cloned classes and event listeners.
108
+ *
109
+ * @returns A clone of this instance.
110
+ */
48
111
  clone(): Nymph;
112
+ /**
113
+ * Connect to the database.
114
+ *
115
+ * @returns Whether the instance is connected to the database.
116
+ */
49
117
  connect(): Promise<boolean>;
118
+ /**
119
+ * Disconnect from the database.
120
+ *
121
+ * @returns Whether the instance is connected to the database.
122
+ */
50
123
  disconnect(): Promise<boolean>;
124
+ /**
125
+ * Run all the query callbacks on a query.
126
+ */
51
127
  runQueryCallbacks(options: Options, selectors: FormattedSelector[]): void;
128
+ /**
129
+ * Start an atomic transaction and returns a new instance of Nymph.
130
+ *
131
+ * All proceeding changes using this new instance will wait to be written to
132
+ * the database's permanent storage until commit() is called. You can also
133
+ * undo all the changes since this function ran with rollback().
134
+ *
135
+ * Transactions will nest as long as every name is unique. Internally, Nymph
136
+ * uses names prefixed with "nymph-".
137
+ *
138
+ * @returns A new instance of Nymph that should be used for the transaction.
139
+ */
52
140
  startTransaction(name: string): Promise<Nymph>;
141
+ /**
142
+ * Commit the named transaction.
143
+ *
144
+ * After this is called, the transaction instance should be discarded.
145
+ *
146
+ * @returns True on success, false on failure.
147
+ */
53
148
  commit(name: string): Promise<boolean>;
149
+ /**
150
+ * Rollback the named transaction.
151
+ *
152
+ * After this is called, the transaction instance should be discarded.
153
+ *
154
+ * @returns True on success, false on failure.
155
+ */
54
156
  rollback(name: string): Promise<boolean>;
157
+ /**
158
+ * Check if there is any open transaction.
159
+ *
160
+ * @returns True if there is a transaction.
161
+ */
55
162
  inTransaction(): Promise<boolean>;
163
+ /**
164
+ * Increment or create a unique ID and return the new value.
165
+ *
166
+ * Unique IDs, or UIDs are similar to GUIDs, but numeric and sequential.
167
+ *
168
+ * A UID can be used to identify an object when the GUID doesn't suffice. On
169
+ * a system where a new entity is created many times per second, referring
170
+ * to something by its GUID may be unintuitive. However, the component
171
+ * designer is responsible for assigning UIDs to the component's entities.
172
+ * Beware that if a UID is incremented for an entity, and the entity cannot
173
+ * be saved, there is no safe, and therefore, no recommended way to
174
+ * decrement the UID back to its previous value.
175
+ *
176
+ * If newUID() is passed the name of a UID which does not exist yet, one
177
+ * will be created with that name, and assigned the value 1. If the UID
178
+ * already exists, its value will be incremented. The new value will be
179
+ * returned.
180
+ *
181
+ * @param name The UID's name.
182
+ * @returns The UID's new value, or null on failure.
183
+ */
56
184
  newUID(name: string): Promise<number | null>;
185
+ /**
186
+ * Get the current value of a unique ID.
187
+ * @param name The UID's name.
188
+ * @returns The UID's value, or null on failure and if it doesn't exist.
189
+ */
57
190
  getUID(name: string): Promise<number | null>;
191
+ /**
192
+ * Set the value of a UID.
193
+ *
194
+ * @param name The UID's name.
195
+ * @param value The value.
196
+ * @returns True on success, false on failure.
197
+ */
58
198
  setUID(name: string, value: number): Promise<boolean>;
199
+ /**
200
+ * Delete a unique ID.
201
+ *
202
+ * @param name The UID's name.
203
+ * @returns True on success, false on failure.
204
+ */
59
205
  deleteUID(name: string): Promise<boolean>;
206
+ /**
207
+ * Rename a unique ID.
208
+ *
209
+ * @param oldName The old name.
210
+ * @param newName The new name.
211
+ * @returns True on success, false on failure.
212
+ */
60
213
  renameUID(oldName: string, newName: string): Promise<boolean>;
214
+ /**
215
+ * Save an entity to the database.
216
+ *
217
+ * If the entity has never been saved (has no GUID), a variable "cdate"
218
+ * is set on it with the current Unix timestamp.
219
+ *
220
+ * The variable "mdate" is set to the current Unix timestamp.
221
+ *
222
+ * @param entity The entity.
223
+ * @returns True on success, false on failure.
224
+ */
61
225
  saveEntity(entity: EntityInterface): Promise<boolean>;
226
+ /**
227
+ * Get an array of entities.
228
+ *
229
+ * `options` is an object, which contains any of the following settings:
230
+ *
231
+ * - class - The class to create each entity with.
232
+ * - limit - The limit of entities to be returned.
233
+ * - offset - The offset from the oldest matching entity to start retrieving.
234
+ * - reverse - If true, entities will be retrieved from newest to oldest.
235
+ * Therefore, offset will be from the newest entity.
236
+ * - sort - How to sort the entities. Accepts "cdate", "mdate", the name of a
237
+ * top-level property, or null for no particular order. The method of
238
+ * sorting properties other than cdate and mdate is driver dependent. The
239
+ * only hard rule is that numbers should be sorted numerically (2 before
240
+ * 10). Defaults to "cdate".
241
+ * - return - What to return. "entity", "object", "guid", or "count". Defaults
242
+ * to "entity".
243
+ * - source - Will be 'client' if the query came from a REST call.
244
+ * - skipCache - If true, Nymph will skip the cache and retrieve the entity
245
+ * from the DB.
246
+ * - skipAc - If true, Tilmeld will not filter returned entities according to
247
+ * access controls. (If Tilmeld is installed.) (This is *always* set to
248
+ * false by the REST server.)
249
+ *
250
+ * If a class is specified, it must have a factory() static method that
251
+ * returns a new instance.
252
+ *
253
+ * Selectors are objects. Any amount of selectors can be provided. Empty
254
+ * selectors will be ignored. The `type` property of a selector is required
255
+ * and can be one of the following strings:
256
+ *
257
+ * - & - (and) All values in the selector must be true.
258
+ * - | - (or) At least one value in the selector must be true.
259
+ * - !& - (not and) All values in the selector must be false.
260
+ * - !| - (not or) At least one value in the selector must be false.
261
+ *
262
+ * The rest of the properties in the selectors are called selector clauses,
263
+ * which can be any of the following (in the form selector.name = value, or
264
+ * selector.name = [value1, value2,...]):
265
+ *
266
+ * - guid - A GUID. True if the entity's GUID is equal.
267
+ * - tag - A tag. True if the entity has the tag.
268
+ * - defined - A name. True if the named property exists.
269
+ * - truthy - A name. True if the named property is defined and truthy.
270
+ * - equal - An array with a name, then value. True if the named property is
271
+ * defined and equal (their JSON strings are identical).
272
+ * - contain - An array with a name, then value. True if the named property
273
+ * contains the value (its JSON string is found within the property's JSON
274
+ * string).
275
+ * - search - An array with a name, then search query. True if the named
276
+ * property matches the query. Use single quotes to find sequential terms.
277
+ * Use double quotes to find exact terms. Use "or" as the or operator. Use
278
+ * "-" before a term as the negation operator. Stop words and punctuation
279
+ * are stripped. Case insensitive.
280
+ * - match - An array with a name, then regular expression. True if the
281
+ * named property matches. Uses POSIX RegExp. Case sensitive. Must *not* be
282
+ * surrounded by any delimiters.
283
+ * - imatch - An array with a name, then regular expression. True if the
284
+ * named property matches. Uses POSIX RegExp. Case insensitive. Must *not*
285
+ * be surrounded by any delimiters.
286
+ * - like - An array with a name, then pattern. True if the named property
287
+ * matches. Uses % for variable length wildcard and _ for single character
288
+ * wildcard. Case sensitive.
289
+ * - ilike - An array with a name, then pattern. True if the named property
290
+ * matches. Uses % for variable length wildcard and _ for single character
291
+ * wildcard. Case insensitive.
292
+ * - gt - An array with a name, then value. True if the named property is
293
+ * greater than the value.
294
+ * - gte - An array with a name, then value. True if the named property is
295
+ * greater than or equal to the value.
296
+ * - lt - An array with a name, then value. True if the named property is
297
+ * less than the value.
298
+ * - lte - An array with a name, then value. True if the named property is
299
+ * less than or equal to the value.
300
+ * - ref - An array with a name, then either an entity, or a GUID. True if
301
+ * the named property is the entity or contains the entity.
302
+ * - qref - An array with a name, then a full query (including options) in an
303
+ * array. True if the named property is an entity that matches the query or
304
+ * contains an entity that matches the query.
305
+ * - selector - A selector. (Keep in mind, you can also use an array of these,
306
+ * just like any other clause.)
307
+ *
308
+ * These clauses can all be negated, by prefixing them with an exclamation
309
+ * point, such as "!truthy" to mean falsy (or undefined).
310
+ *
311
+ * Any clause that accepts an array of name and value can also accept a third
312
+ * element. If value is null and the third element is a string, the third
313
+ * element will be used with Locutus' strtotime function to set value to a
314
+ * relative timestamp. For example, the following selector will look for all
315
+ * entities that were created in the last day:
316
+ *
317
+ * ```
318
+ * {
319
+ * type: '&',
320
+ * gte: ['cdate', null, '-1 day']
321
+ * }
322
+ * ```
323
+ *
324
+ * Locutus' implementation: https://locutus.io/php/datetime/strtotime/
325
+ * PHP's documentation: https://www.php.net/manual/en/function.strtotime.php
326
+ *
327
+ * This example will retrieve the last two entities where:
328
+ *
329
+ * - It has 'person' tag.
330
+ * - spouse is defined.
331
+ * - gender is male and lname is Smith.
332
+ * - warnings is not an integer 0.
333
+ * - It has 'level1' and 'level2' tags, or it has 'access1' and 'access2'
334
+ * tags.
335
+ * - It has either 'employee' or 'manager' tag.
336
+ * - name is either Clark, James, Chris, Christopher, Jake, or Jacob.
337
+ * - If age is 22 or more, then pay is not greater than 8.
338
+ *
339
+ * ```
340
+ * const entities = Nymph.getEntities(
341
+ * { class: Entity, reverse: true, limit: 2 },
342
+ * {
343
+ * type: '&', // all must be true
344
+ * tag: 'person',
345
+ * defined: 'spouse',
346
+ * equal: [
347
+ * ['gender', 'male'],
348
+ * ['lname', 'Smith']
349
+ * ],
350
+ * '!equal': ['warnings', 0]
351
+ * },
352
+ * {
353
+ * type: '|', // at least one of the selectors in this must match
354
+ * selector: [
355
+ * {
356
+ * type: '&',
357
+ * tag: ['level1', 'level2']
358
+ * },
359
+ * {
360
+ * type: '&',
361
+ * tag: ['access1', 'access2']
362
+ * }
363
+ * ]
364
+ * },
365
+ * {
366
+ * type: '|', // at least one must be true
367
+ * tag: ['employee', 'manager']
368
+ * },
369
+ * {
370
+ * type: '|',
371
+ * equal: [
372
+ * ['name', 'Clark'],
373
+ * ['name', 'James']
374
+ * ],
375
+ * match: [
376
+ * ['name', 'Chris(topher)?'],
377
+ * ['name', 'Ja(ke|cob)']
378
+ * ]
379
+ * },
380
+ * {
381
+ * type: '!|', // at least one must be false
382
+ * gte: ['age', 22],
383
+ * gt: ['pay', 8]
384
+ * }
385
+ * );
386
+ * ```
387
+ *
388
+ * @param options The options.
389
+ * @param selectors Unlimited optional selectors to search for. If none are given, all entities are retrieved for the given options.
390
+ * @returns An array of entities or guids, or a count.
391
+ * @todo Use an asterisk to specify any variable.
392
+ */
62
393
  getEntities<T extends EntityConstructor = EntityConstructor>(options: Options<T> & {
63
394
  return: 'count';
64
395
  }, ...selectors: Selector[]): Promise<number>;
65
396
  getEntities<T extends EntityConstructor = EntityConstructor>(options: Options<T> & {
66
397
  return: 'guid';
67
398
  }, ...selectors: Selector[]): Promise<string[]>;
68
- getEntities<T extends EntityConstructor = EntityConstructor>(options?: Options<T>, ...selectors: Selector[]): Promise<ReturnType<T['factorySync']>[]>;
399
+ getEntities<T extends EntityConstructor = EntityConstructor>(options: Options<T> & {
400
+ return: 'object';
401
+ }, ...selectors: Selector[]): Promise<EntityObjectType<T>[]>;
402
+ getEntities<T extends EntityConstructor = EntityConstructor>(options?: Options<T>, ...selectors: Selector[]): Promise<EntityInstanceType<T>[]>;
403
+ /**
404
+ * Get the first entity to match all options/selectors.
405
+ *
406
+ * options and selectors are the same as in getEntities().
407
+ *
408
+ * This function is equivalent to setting options.limit to 1 for
409
+ * getEntities(), except that it will return null if no entity is found.
410
+ * getEntities() would return an empty array.
411
+ *
412
+ * @param options The options.
413
+ * @param selectors Unlimited optional selectors to search for, or a single GUID. If none are given, all entities are searched for the given options.
414
+ * @returns An entity or guid, or null on failure or nothing found, or a number.
415
+ */
69
416
  getEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T> & {
70
417
  return: 'count';
71
418
  }, ...selectors: Selector[]): Promise<number>;
72
419
  getEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T> & {
73
420
  return: 'guid';
74
421
  }, ...selectors: Selector[]): Promise<string | null>;
75
- getEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T>, ...selectors: Selector[]): Promise<ReturnType<T['factorySync']> | null>;
422
+ getEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T> & {
423
+ return: 'object';
424
+ }, ...selectors: Selector[]): Promise<EntityObjectType<T> | null>;
425
+ getEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T>, ...selectors: Selector[]): Promise<EntityInstanceType<T> | null>;
76
426
  getEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T> & {
77
427
  return: 'guid';
78
428
  }, guid: string): Promise<string | null>;
79
- getEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T>, guid: string): Promise<ReturnType<T['factorySync']> | null>;
429
+ getEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T> & {
430
+ return: 'object';
431
+ }, guid: string): Promise<EntityObjectType<T> | null>;
432
+ getEntity<T extends EntityConstructor = EntityConstructor>(options: Options<T>, guid: string): Promise<EntityInstanceType<T> | null>;
433
+ /**
434
+ * Delete an entity from the database.
435
+ *
436
+ * @param entity The entity.
437
+ * @returns True on success, false on failure.
438
+ */
80
439
  deleteEntity(entity: EntityInterface): Promise<boolean>;
440
+ /**
441
+ * Delete an entity from the database by its GUID.
442
+ *
443
+ * @param guid The entity's GUID.
444
+ * @param className The entity's class name.
445
+ * @returns True on success, false on failure.
446
+ */
81
447
  deleteEntityByID(guid: string, className?: string): Promise<boolean>;
448
+ /**
449
+ * Export entities to a local file.
450
+ *
451
+ * This is the file format:
452
+ *
453
+ * ```
454
+ * #nex2
455
+ * # The above line must be the first thing in the file.
456
+ * # Comments begin with #
457
+ * # And can have white space before them.
458
+ * # This defines a UID.
459
+ * <name/of/uid>[5]
460
+ * <another uid>[8000]
461
+ * # For UIDs, the name is in angle brackets (<>) and the value follows
462
+ * # in square brackets ([]).
463
+ * # This starts a new entity.
464
+ * {1234abcd}<etype>[tag,list,with,commas]
465
+ * # For entities, the GUID is in curly brackets ({}), then the etype in
466
+ * # angle brackets, then the comma separated tag list follows in square
467
+ * # brackets ([]).
468
+ * # Properties are stored like this:
469
+ * # propname=JSON.stringify(value)
470
+ * abilities=["system/admin"]
471
+ * groups=[]
472
+ * inheritAbilities=false
473
+ * name="admin"
474
+ * # White space before/after "=" and at beginning/end of line is ignored.
475
+ * username = "admin"
476
+ * {2}<etype>[tag,list]
477
+ * another="This is another entity."
478
+ * newline="\n"
479
+ * ```
480
+ *
481
+ * @param filename The file to export to.
482
+ * @returns True on success, false on failure.
483
+ */
82
484
  export(filename: string): Promise<boolean>;
485
+ /**
486
+ * Export entities to the console.
487
+ *
488
+ * @returns True on success, false on failure.
489
+ */
83
490
  exportPrint(): Promise<boolean>;
84
- import(filename: string): Promise<boolean>;
491
+ exportEntity(etype: string, guid: string): Promise<string>;
492
+ /**
493
+ * Import entities from a file.
494
+ *
495
+ * @param filename The file to import from.
496
+ * @param options The options for the import.
497
+ * @returns True on success, false on failure.
498
+ */
499
+ import(filename: string, options?: {
500
+ ignoreUnknownETypes?: boolean;
501
+ }): Promise<boolean>;
502
+ /**
503
+ * Import a single entity.
504
+ *
505
+ * @param entity The entity data to import.
506
+ */
507
+ importEntity(entity: {
508
+ guid: string;
509
+ cdate: number;
510
+ mdate: number;
511
+ tags: string[];
512
+ sdata: SerializedEntityData;
513
+ etype: string;
514
+ }): Promise<void>;
515
+ /**
516
+ * Import a single entity's tokens.
517
+ *
518
+ * This does not update any of the actual data, only the tokens used for full
519
+ * text search.
520
+ *
521
+ * Be careful with this function, since you can overwrite existing tokens with
522
+ * data that is out of sync. The DB _should_ prevent you from inserting tokens
523
+ * for an entity that doesn't exist, but it _won't_ prevent you from inserting
524
+ * tokens for properties that don't exist on an entity.
525
+ *
526
+ * @param entity The entity data to import.
527
+ */
528
+ importEntityTokens(entity: {
529
+ guid: string;
530
+ cdate: number;
531
+ mdate: number;
532
+ tags: string[];
533
+ sdata: SerializedEntityData;
534
+ etype: string;
535
+ }): Promise<void>;
536
+ /**
537
+ * Import a single entity's Tilmeld access control properties.
538
+ *
539
+ * This does not update any of the other data, only the access control
540
+ * columns.
541
+ *
542
+ * @param entity The entity data to import.
543
+ */
544
+ importEntityTilmeldAC(entity: {
545
+ guid: string;
546
+ cdate: number;
547
+ mdate: number;
548
+ tags: string[];
549
+ sdata: SerializedEntityData;
550
+ etype: string;
551
+ }): Promise<void>;
552
+ /**
553
+ * Detect whether the database needs to be migrated.
554
+ *
555
+ * If not false (so, one of the string values), the database should be
556
+ * exported with an old version of Nymph, then imported into a fresh database
557
+ * with this version. Sometimes, a live migration can be done instead, which
558
+ * will require no downtime. You should still export the database beforehand,
559
+ * in case anything goes wrong.
560
+ *
561
+ * 'json' means the data tables are missing the JSON field, and the DB
562
+ * **must** be exported and imported to fix it.
563
+ *
564
+ * 'tokens' means the FTS token tables are missing, and you can get away with
565
+ * a live migration with `liveMigration('tokenTables')` and doing
566
+ * `importEntityTokens(entity)` for each entity.
567
+ *
568
+ * 'tilmeldColumns' means the entity columns for "user", "group", and access
569
+ * controls are missing, and you can get away with a live migration with
570
+ * `liveMigration('tilmeldColumns')` and doing
571
+ * `importEntityTilmeldAC(entity)` for each entity. DO NOT update to any
572
+ * version later than 1.0.0-beta.109 before this is done, or access controls
573
+ * WILL NOT work, and everyone will have access to every entity!
574
+ */
575
+ needsMigration(): Promise<"json" | "tilmeldColumns" | "tokens" | false>;
576
+ /**
577
+ * Perform a live migration on the DB.
578
+ *
579
+ * A 'tokenTables' migration will simply add the missing token tables. It will
580
+ * **not** fill them. You must use `importEntityTokens` on each entity after
581
+ * running this to fill the token tables and enable full text search matching
582
+ * on existing entities.
583
+ *
584
+ * A 'tilmeldColumns' migration will simply add the missing Tilmeld columns
585
+ * and indexes to each entity table. It will **not** fill them, and you must
586
+ * fill them before updating to the latest version of Nymph, or everyone will
587
+ * be able to access every entity! You must use `importEntityTilmeldAC` on
588
+ * each entity after running this.
589
+ *
590
+ * A 'tilmeldRemoveOldRows' migration will remove all of the old access
591
+ * control rows in the data tables that are no longer used as of
592
+ * 1.0.0-beta.110. MAKE SURE YOU HAVE RUN `importEntityTilmeldAC` ON ALL
593
+ * ENTITIES BEFORE RUNNING THIS, OR THE DATA WILL BE IRRETRIEVABLY LOST!
594
+ */
595
+ liveMigration(migrationType: 'tokenTables' | 'tilmeldColumns' | 'tilmeldRemoveOldRows'): Promise<void>;
596
+ /**
597
+ * Returns a list of the etypes stored in the DB.
598
+ */
599
+ getEtypes(): Promise<string[]>;
600
+ /**
601
+ * Get all the indexes defined for a specific etype.
602
+ *
603
+ * @param etype The etype to get indexes for.
604
+ */
605
+ getIndexes(etype: string): Promise<{
606
+ scope: 'data' | 'references' | 'tokens';
607
+ name: string;
608
+ property: string;
609
+ }[]>;
610
+ /**
611
+ * Add an index on a specific property to an etype.
612
+ *
613
+ * Nymph adds general indexes on etypes, but they span across all properties,
614
+ * so they can only speed up a query so much. You can add indexes that are
615
+ * specific to a property with this function, which will speed up queries for
616
+ * that property. If an etype only has one or two properties, you may not need
617
+ * a specific index, but if your etypes include many properties or properties
618
+ * that generally contain large amounts of data, adding a specific index can
619
+ * drastically improve the performance of your queries.
620
+ *
621
+ * The scope of the index will affect which queries it will speed up:
622
+ *
623
+ * - data: This will speed up comparisons and equality checks in queries.
624
+ * - references: This will speed up ref and qref clauses in queries.
625
+ * - tokens: This will speed up search clauses in queries.
626
+ *
627
+ * The name must be unique within the etype and scope or the existing index
628
+ * will be overwritten.
629
+ *
630
+ * You do not need to add reference indexes for the "user" and "group"
631
+ * properties, because these are already specifically indexed by Nymph.
632
+ *
633
+ * @param etype The etype to add the index on.
634
+ * @param definition The definition of the index.
635
+ */
636
+ addIndex(etype: string, definition: {
637
+ scope: 'data' | 'references' | 'tokens';
638
+ name: string;
639
+ property: string;
640
+ }): Promise<boolean>;
641
+ /**
642
+ * Delete an index from an etype.
643
+ *
644
+ * @param etype The etype to delete the index on.
645
+ * @param scope The scope of the index.
646
+ * @param name The name of the index to delete.
647
+ */
648
+ deleteIndex(etype: string, scope: 'data' | 'references' | 'tokens', name: string): Promise<boolean>;
85
649
  on<T extends NymphEventType>(event: T, callback: T extends 'connect' ? NymphConnectCallback : T extends 'disconnect' ? NymphDisconnectCallback : T extends 'query' ? NymphQueryCallback : T extends 'beforeGetEntity' ? NymphBeforeGetEntityCallback : T extends 'beforeGetEntities' ? NymphBeforeGetEntitiesCallback : T extends 'beforeSaveEntity' ? NymphBeforeSaveEntityCallback : T extends 'afterSaveEntity' ? NymphAfterSaveEntityCallback : T extends 'failedSaveEntity' ? NymphFailedSaveEntityCallback : T extends 'beforeDeleteEntity' ? NymphBeforeDeleteEntityCallback : T extends 'afterDeleteEntity' ? NymphAfterDeleteEntityCallback : T extends 'failedDeleteEntity' ? NymphFailedDeleteEntityCallback : T extends 'beforeDeleteEntityByID' ? NymphBeforeDeleteEntityByIDCallback : T extends 'afterDeleteEntityByID' ? NymphAfterDeleteEntityByIDCallback : T extends 'failedDeleteEntityByID' ? NymphFailedDeleteEntityByIDCallback : T extends 'beforeNewUID' ? NymphBeforeNewUIDCallback : T extends 'afterNewUID' ? NymphAfterNewUIDCallback : T extends 'failedNewUID' ? NymphFailedNewUIDCallback : T extends 'beforeSetUID' ? NymphBeforeSetUIDCallback : T extends 'afterSetUID' ? NymphAfterSetUIDCallback : T extends 'failedSetUID' ? NymphFailedSetUIDCallback : T extends 'beforeRenameUID' ? NymphBeforeRenameUIDCallback : T extends 'afterRenameUID' ? NymphAfterRenameUIDCallback : T extends 'failedRenameUID' ? NymphFailedRenameUIDCallback : T extends 'beforeDeleteUID' ? NymphBeforeDeleteUIDCallback : T extends 'afterDeleteUID' ? NymphAfterDeleteUIDCallback : T extends 'failedDeleteUID' ? NymphFailedDeleteUIDCallback : T extends 'beforeStartTransaction' ? NymphBeforeStartTransactionCallback : T extends 'afterStartTransaction' ? NymphAfterStartTransactionCallback : T extends 'beforeCommitTransaction' ? NymphBeforeCommitTransactionCallback : T extends 'afterCommitTransaction' ? NymphAfterCommitTransactionCallback : T extends 'beforeRollbackTransaction' ? NymphBeforeRollbackTransactionCallback : T extends 'afterRollbackTransaction' ? NymphAfterRollbackTransactionCallback : never): () => boolean;
86
650
  off<T extends NymphEventType>(event: T, callback: T extends 'connect' ? NymphConnectCallback : T extends 'disconnect' ? NymphDisconnectCallback : T extends 'query' ? NymphQueryCallback : T extends 'beforeGetEntity' ? NymphBeforeGetEntityCallback : T extends 'beforeGetEntities' ? NymphBeforeGetEntitiesCallback : T extends 'beforeSaveEntity' ? NymphBeforeSaveEntityCallback : T extends 'afterSaveEntity' ? NymphAfterSaveEntityCallback : T extends 'failedSaveEntity' ? NymphFailedSaveEntityCallback : T extends 'beforeDeleteEntity' ? NymphBeforeDeleteEntityCallback : T extends 'afterDeleteEntity' ? NymphAfterDeleteEntityCallback : T extends 'failedDeleteEntity' ? NymphFailedDeleteEntityCallback : T extends 'beforeDeleteEntityByID' ? NymphBeforeDeleteEntityByIDCallback : T extends 'afterDeleteEntityByID' ? NymphAfterDeleteEntityByIDCallback : T extends 'failedDeleteEntityByID' ? NymphFailedDeleteEntityByIDCallback : T extends 'beforeNewUID' ? NymphBeforeNewUIDCallback : T extends 'afterNewUID' ? NymphAfterNewUIDCallback : T extends 'failedNewUID' ? NymphFailedNewUIDCallback : T extends 'beforeSetUID' ? NymphBeforeSetUIDCallback : T extends 'afterSetUID' ? NymphAfterSetUIDCallback : T extends 'failedSetUID' ? NymphFailedSetUIDCallback : T extends 'beforeRenameUID' ? NymphBeforeRenameUIDCallback : T extends 'afterRenameUID' ? NymphAfterRenameUIDCallback : T extends 'failedRenameUID' ? NymphFailedRenameUIDCallback : T extends 'beforeDeleteUID' ? NymphBeforeDeleteUIDCallback : T extends 'afterDeleteUID' ? NymphAfterDeleteUIDCallback : T extends 'failedDeleteUID' ? NymphFailedDeleteUIDCallback : T extends 'beforeStartTransaction' ? NymphBeforeStartTransactionCallback : T extends 'afterStartTransaction' ? NymphAfterStartTransactionCallback : T extends 'beforeCommitTransaction' ? NymphBeforeCommitTransactionCallback : T extends 'afterCommitTransaction' ? NymphAfterCommitTransactionCallback : T extends 'beforeRollbackTransaction' ? NymphBeforeRollbackTransactionCallback : T extends 'afterRollbackTransaction' ? NymphAfterRollbackTransactionCallback : never): boolean;
87
651
  }