@nymphjs/nymph 1.0.0-beta.12 → 1.0.0-beta.121

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 (103) hide show
  1. package/CHANGELOG.md +588 -0
  2. package/README.md +23 -21
  3. package/dist/Entity.d.ts +295 -12
  4. package/dist/Entity.js +560 -148
  5. package/dist/Entity.js.map +1 -1
  6. package/dist/Entity.test.js +52 -13
  7. package/dist/Entity.test.js.map +1 -1
  8. package/dist/Entity.types.d.ts +256 -23
  9. package/dist/Entity.types.js +1 -2
  10. package/dist/Nymph.d.ts +590 -13
  11. package/dist/Nymph.js +846 -180
  12. package/dist/Nymph.js.map +1 -1
  13. package/dist/Nymph.types.d.ts +131 -8
  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/driver/NymphDriver.d.ts +205 -40
  23. package/dist/driver/NymphDriver.js +712 -238
  24. package/dist/driver/NymphDriver.js.map +1 -1
  25. package/dist/driver/index.d.ts +1 -2
  26. package/dist/driver/index.js +2 -23
  27. package/dist/driver/index.js.map +1 -1
  28. package/dist/driver/testArtifacts.d.ts +4 -4
  29. package/dist/driver/testArtifacts.js +1920 -1086
  30. package/dist/driver/testArtifacts.js.map +1 -1
  31. package/dist/errors/ClassNotAvailableError.js +1 -5
  32. package/dist/errors/ClassNotAvailableError.js.map +1 -1
  33. package/dist/errors/EntityConflictError.js +1 -5
  34. package/dist/errors/EntityConflictError.js.map +1 -1
  35. package/dist/errors/EntityInvalidDataError.d.ts +6 -0
  36. package/dist/errors/EntityInvalidDataError.js +8 -6
  37. package/dist/errors/EntityInvalidDataError.js.map +1 -1
  38. package/dist/errors/EntityIsSleepingReferenceError.js +1 -5
  39. package/dist/errors/EntityIsSleepingReferenceError.js.map +1 -1
  40. package/dist/errors/EntityUniqueConstraintError.d.ts +3 -0
  41. package/dist/errors/EntityUniqueConstraintError.js +7 -0
  42. package/dist/errors/EntityUniqueConstraintError.js.map +1 -0
  43. package/dist/errors/HttpError.d.ts +5 -0
  44. package/dist/errors/HttpError.js +11 -0
  45. package/dist/errors/HttpError.js.map +1 -0
  46. package/dist/errors/InvalidParametersError.js +1 -5
  47. package/dist/errors/InvalidParametersError.js.map +1 -1
  48. package/dist/errors/InvalidStateError.d.ts +3 -0
  49. package/dist/errors/InvalidStateError.js +7 -0
  50. package/dist/errors/InvalidStateError.js.map +1 -0
  51. package/dist/errors/NotConfiguredError.js +1 -5
  52. package/dist/errors/NotConfiguredError.js.map +1 -1
  53. package/dist/errors/QueryFailedError.d.ts +2 -1
  54. package/dist/errors/QueryFailedError.js +5 -6
  55. package/dist/errors/QueryFailedError.js.map +1 -1
  56. package/dist/errors/UnableToConnectError.js +1 -5
  57. package/dist/errors/UnableToConnectError.js.map +1 -1
  58. package/dist/errors/index.d.ts +11 -8
  59. package/dist/errors/index.js +11 -24
  60. package/dist/errors/index.js.map +1 -1
  61. package/dist/index.d.ts +11 -11
  62. package/dist/index.js +14 -34
  63. package/dist/index.js.map +1 -1
  64. package/dist/nymphJoiProps.d.ts +1 -1
  65. package/dist/nymphJoiProps.js +10 -15
  66. package/dist/nymphJoiProps.js.map +1 -1
  67. package/dist/testArtifacts.d.ts +19 -6
  68. package/dist/testArtifacts.js +32 -37
  69. package/dist/testArtifacts.js.map +1 -1
  70. package/dist/testMocks.d.ts +27 -12
  71. package/dist/testMocks.js +40 -29
  72. package/dist/testMocks.js.map +1 -1
  73. package/dist/utils.d.ts +4 -4
  74. package/dist/utils.js +40 -29
  75. package/dist/utils.js.map +1 -1
  76. package/jest.config.js +31 -5
  77. package/package.json +33 -23
  78. package/src/Entity.test.ts +50 -7
  79. package/src/Entity.ts +489 -150
  80. package/src/Entity.types.ts +72 -74
  81. package/src/Nymph.ts +991 -324
  82. package/src/Nymph.types.ts +201 -27
  83. package/src/conf/defaults.ts +34 -1
  84. package/src/conf/index.ts +50 -2
  85. package/src/driver/NymphDriver.ts +898 -413
  86. package/src/driver/index.ts +1 -3
  87. package/src/driver/testArtifacts.ts +2557 -1629
  88. package/src/errors/EntityUniqueConstraintError.ts +6 -0
  89. package/src/errors/HttpError.ts +12 -0
  90. package/src/errors/InvalidStateError.ts +6 -0
  91. package/src/errors/QueryFailedError.ts +3 -1
  92. package/src/errors/index.ts +14 -8
  93. package/src/index.ts +11 -11
  94. package/src/nymphJoiProps.ts +2 -2
  95. package/src/testArtifacts.ts +20 -20
  96. package/src/testMocks.ts +76 -35
  97. package/src/utils.ts +39 -18
  98. package/tsconfig.json +6 -3
  99. package/typedoc.json +4 -0
  100. package/dist/conf/d.d.ts +0 -6
  101. package/dist/conf/d.js +0 -3
  102. package/dist/conf/d.js.map +0 -1
  103. package/src/conf/d.ts +0 -24
@@ -1,5 +1,5 @@
1
- import { EntityConstructor, EntityInterface } from './Entity.types';
2
- import Nymph from './Nymph';
1
+ import type { EntityConstructor, EntityInterface } from './Entity.types.js';
2
+ import type Nymph from './Nymph.js';
3
3
 
4
4
  export type NymphEventType =
5
5
  | 'connect'
@@ -9,25 +9,38 @@ export type NymphEventType =
9
9
  | 'beforeGetEntities'
10
10
  | 'beforeSaveEntity'
11
11
  | 'afterSaveEntity'
12
+ | 'failedSaveEntity'
12
13
  | 'beforeDeleteEntity'
13
14
  | 'afterDeleteEntity'
15
+ | 'failedDeleteEntity'
14
16
  | 'beforeDeleteEntityByID'
15
17
  | 'afterDeleteEntityByID'
18
+ | 'failedDeleteEntityByID'
16
19
  | 'beforeNewUID'
17
20
  | 'afterNewUID'
21
+ | 'failedNewUID'
18
22
  | 'beforeSetUID'
19
23
  | 'afterSetUID'
24
+ | 'failedSetUID'
20
25
  | 'beforeRenameUID'
21
26
  | 'afterRenameUID'
27
+ | 'failedRenameUID'
22
28
  | 'beforeDeleteUID'
23
- | 'afterDeleteUID';
29
+ | 'afterDeleteUID'
30
+ | 'failedDeleteUID'
31
+ | 'beforeStartTransaction'
32
+ | 'afterStartTransaction'
33
+ | 'beforeCommitTransaction'
34
+ | 'afterCommitTransaction'
35
+ | 'beforeRollbackTransaction'
36
+ | 'afterRollbackTransaction';
24
37
  export type NymphConnectCallback = (
25
38
  nymph: Nymph,
26
- result: Promise<boolean>
39
+ result: Promise<boolean>,
27
40
  ) => Promise<void>;
28
41
  export type NymphDisconnectCallback = (
29
42
  nymph: Nymph,
30
- result: Promise<boolean>
43
+ result: Promise<boolean>,
31
44
  ) => Promise<void>;
32
45
  /**
33
46
  * The NymphQueryCallback will be called on both top level and qref queries.
@@ -43,87 +56,192 @@ export type NymphDisconnectCallback = (
43
56
  export type NymphQueryCallback = (
44
57
  nymph: Nymph,
45
58
  options: Options,
46
- selectors: FormattedSelector[]
59
+ selectors: FormattedSelector[],
47
60
  ) => void;
48
61
  export type NymphBeforeGetEntityCallback = (
49
62
  nymph: Nymph,
50
63
  options: Options,
51
- selectors: Selector[]
64
+ selectors: Selector[],
52
65
  ) => Promise<void>;
53
66
  export type NymphBeforeGetEntitiesCallback = (
54
67
  nymph: Nymph,
55
68
  options: Options,
56
- selectors: Selector[]
69
+ selectors: Selector[],
57
70
  ) => Promise<void>;
58
71
  export type NymphBeforeSaveEntityCallback = (
59
72
  nymph: Nymph,
60
- entity: EntityInterface
73
+ entity: EntityInterface,
61
74
  ) => Promise<void>;
62
75
  export type NymphAfterSaveEntityCallback = (
63
76
  nymph: Nymph,
64
- result: Promise<boolean>
77
+ result: Promise<boolean>,
78
+ ) => Promise<void>;
79
+ export type NymphFailedSaveEntityCallback = (
80
+ nymph: Nymph,
81
+ error: any,
65
82
  ) => Promise<void>;
66
83
  export type NymphBeforeDeleteEntityCallback = (
67
84
  nymph: Nymph,
68
- entity: EntityInterface
85
+ entity: EntityInterface,
69
86
  ) => Promise<void>;
70
87
  export type NymphAfterDeleteEntityCallback = (
71
88
  nymph: Nymph,
72
- result: Promise<boolean>
89
+ result: Promise<boolean>,
90
+ ) => Promise<void>;
91
+ export type NymphFailedDeleteEntityCallback = (
92
+ nymph: Nymph,
93
+ error: any,
73
94
  ) => Promise<void>;
74
95
  export type NymphBeforeDeleteEntityByIDCallback = (
75
96
  nymph: Nymph,
76
97
  guid: string,
77
- className?: string
98
+ className?: string,
78
99
  ) => Promise<void>;
79
100
  export type NymphAfterDeleteEntityByIDCallback = (
80
101
  nymph: Nymph,
81
- result: Promise<boolean>
102
+ result: Promise<boolean>,
103
+ ) => Promise<void>;
104
+ export type NymphFailedDeleteEntityByIDCallback = (
105
+ nymph: Nymph,
106
+ error: any,
82
107
  ) => Promise<void>;
83
108
  export type NymphBeforeNewUIDCallback = (
84
109
  nymph: Nymph,
85
- name: string
110
+ name: string,
86
111
  ) => Promise<void>;
87
112
  export type NymphAfterNewUIDCallback = (
88
113
  nymph: Nymph,
89
- result: Promise<number | null>
114
+ result: Promise<number | null>,
115
+ ) => Promise<void>;
116
+ export type NymphFailedNewUIDCallback = (
117
+ nymph: Nymph,
118
+ error: any,
90
119
  ) => Promise<void>;
91
120
  export type NymphBeforeSetUIDCallback = (
92
121
  nymph: Nymph,
93
122
  name: string,
94
- value: number
123
+ value: number,
95
124
  ) => Promise<void>;
96
125
  export type NymphAfterSetUIDCallback = (
97
126
  nymph: Nymph,
98
- result: Promise<boolean>
127
+ result: Promise<boolean>,
128
+ ) => Promise<void>;
129
+ export type NymphFailedSetUIDCallback = (
130
+ nymph: Nymph,
131
+ error: any,
99
132
  ) => Promise<void>;
100
133
  export type NymphBeforeRenameUIDCallback = (
101
134
  nymph: Nymph,
102
135
  oldName: string,
103
- newName: string
136
+ newName: string,
104
137
  ) => Promise<void>;
105
138
  export type NymphAfterRenameUIDCallback = (
106
139
  nymph: Nymph,
107
- result: Promise<boolean>
140
+ result: Promise<boolean>,
141
+ ) => Promise<void>;
142
+ export type NymphFailedRenameUIDCallback = (
143
+ nymph: Nymph,
144
+ error: any,
108
145
  ) => Promise<void>;
109
146
  export type NymphBeforeDeleteUIDCallback = (
110
147
  nymph: Nymph,
111
- name: string
148
+ name: string,
112
149
  ) => Promise<void>;
113
150
  export type NymphAfterDeleteUIDCallback = (
114
151
  nymph: Nymph,
115
- result: Promise<boolean>
152
+ result: Promise<boolean>,
153
+ ) => Promise<void>;
154
+ export type NymphFailedDeleteUIDCallback = (
155
+ nymph: Nymph,
156
+ error: any,
157
+ ) => Promise<void>;
158
+ export type NymphBeforeStartTransactionCallback = (
159
+ nymph: Nymph,
160
+ name: string,
161
+ ) => Promise<void>;
162
+ export type NymphAfterStartTransactionCallback = (
163
+ nymph: Nymph,
164
+ name: string,
165
+ result: Nymph,
166
+ ) => Promise<void>;
167
+ export type NymphBeforeCommitTransactionCallback = (
168
+ nymph: Nymph,
169
+ name: string,
170
+ ) => Promise<void>;
171
+ export type NymphAfterCommitTransactionCallback = (
172
+ nymph: Nymph,
173
+ name: string,
174
+ result: boolean,
175
+ ) => Promise<void>;
176
+ export type NymphBeforeRollbackTransactionCallback = (
177
+ nymph: Nymph,
178
+ name: string,
179
+ ) => Promise<void>;
180
+ export type NymphAfterRollbackTransactionCallback = (
181
+ nymph: Nymph,
182
+ name: string,
183
+ result: boolean,
116
184
  ) => Promise<void>;
117
185
 
118
186
  export type Options<T extends EntityConstructor = EntityConstructor> = {
187
+ /**
188
+ * The Entity class to query.
189
+ */
119
190
  class?: T;
191
+ /**
192
+ * The limit of entities to be returned. Not needed when using `getEntity`, as
193
+ * it always returns only one.
194
+ */
120
195
  limit?: number;
196
+ /**
197
+ * The offset from the first matching entity, in order, to start retrieving.
198
+ */
121
199
  offset?: number;
200
+ /**
201
+ * If true, entities will be retrieved from newest to oldest/largest to
202
+ * smallest (with regard to `sort`).
203
+ */
122
204
  reverse?: boolean;
123
- sort?: 'cdate' | 'mdate';
124
- return?: 'entity' | 'guid' | 'count';
205
+ /**
206
+ * How to sort the entities. Should be "cdate", "mdate", or the name of a
207
+ * property.
208
+ *
209
+ * When null, the result set will not be sorted in any particular way. It's
210
+ * really up to the DB how the results are returned. In this case, limit and
211
+ * offset may work for pagination, but shouldn't be relied on.
212
+ */
213
+ sort?: 'cdate' | 'mdate' | string | null;
214
+ /**
215
+ * What to return, the entities with their data, just the entity data, just
216
+ * the GUIDs, or just a count.
217
+ *
218
+ * 'object' is only available on the server, as there are substantial security
219
+ * implications with using it. It returns the full entity data as a simple
220
+ * object. You should only use it for operations where instantiating the
221
+ * entities has an unacceptable performance cost.
222
+ */
223
+ return?: 'entity' | 'object' | 'guid' | 'count';
224
+ /**
225
+ * Will be 'client' if the query came from a REST request or the PubSub
226
+ * server. (Mainly used in Tilmeld for access control.)
227
+ */
125
228
  source?: string;
229
+ /**
230
+ * If true, Nymph will skip the cache and retrieve the entity from the DB.
231
+ */
126
232
  skipCache?: boolean;
233
+ /**
234
+ * The level(s) of access control requested.
235
+ *
236
+ * Limiting the access control can significantly improve the performance of
237
+ * the query.
238
+ */
239
+ acRequest?: TilmeldAccessRequest;
240
+ /**
241
+ * If true, Tilmeld will not filter returned entities according to access
242
+ * controls. (If Tilmeld is installed.) (This is always set to false by the
243
+ * REST endpoint and PubSub server.)
244
+ */
127
245
  skipAc?: boolean;
128
246
  };
129
247
 
@@ -150,6 +268,9 @@ type PrimitiveSelector = {
150
268
  contain?: [string, any];
151
269
  '!contain'?: PrimitiveSelector['contain'];
152
270
 
271
+ search?: [string, string];
272
+ '!search'?: PrimitiveSelector['search'];
273
+
153
274
  match?: [string, string];
154
275
  '!match'?: PrimitiveSelector['match'];
155
276
 
@@ -205,6 +326,9 @@ export type Selector = {
205
326
  contain?: Clause<OrWithTime<PrimitiveSelector['contain']>>;
206
327
  '!contain'?: Clause<OrWithTime<PrimitiveSelector['contain']>>;
207
328
 
329
+ search?: Clause<PrimitiveSelector['search']>;
330
+ '!search'?: Clause<PrimitiveSelector['search']>;
331
+
208
332
  match?: Clause<PrimitiveSelector['match']>;
209
333
  '!match'?: Clause<PrimitiveSelector['match']>;
210
334
 
@@ -260,6 +384,9 @@ export type FormattedSelector = {
260
384
  contain?: PrimitiveSelector['contain'][];
261
385
  '!contain'?: PrimitiveSelector['contain'][];
262
386
 
387
+ search?: PrimitiveSelector['search'][];
388
+ '!search'?: PrimitiveSelector['search'][];
389
+
263
390
  match?: PrimitiveSelector['match'][];
264
391
  '!match'?: PrimitiveSelector['match'][];
265
392
 
@@ -302,6 +429,50 @@ export enum TilmeldAccessLevels {
302
429
  FULL_ACCESS = 4,
303
430
  }
304
431
 
432
+ export enum TilmeldAccessRequest {
433
+ /**
434
+ * The default level, any possible entity readable by the user.
435
+ *
436
+ * This is the same as or-ing together all of the levels listed below.
437
+ */
438
+ ALL_LEVELS = 0,
439
+ /**
440
+ * Owned by and accessible to the user.
441
+ *
442
+ * This is always enabled, so not including it has no effect. It's here to
443
+ * allow the selection of _only_ user owned entities.
444
+ */
445
+ USER_OWNED = 1,
446
+ /**
447
+ * Owned by and accessible to the user's primary group.
448
+ */
449
+ PRIMARY_GROUP_OWNED = 2,
450
+ /**
451
+ * Owned by and accessible to one of the user's secondary groups.
452
+ */
453
+ SECONDARY_GROUP_OWNED = 4,
454
+ /**
455
+ * The user is listed in an access control list.
456
+ */
457
+ USER_ACCESSIBLE = 8,
458
+ /**
459
+ * The user's primary group is listed in an access control list.
460
+ */
461
+ PRIMARY_GROUP_ACCESSIBLE = 16,
462
+ /**
463
+ * One of the user's secondary groups is listed in an access control list.
464
+ */
465
+ SECONDARY_GROUP_ACCESSIBLE = 32,
466
+ /**
467
+ * The entity is accessible to any user.
468
+ */
469
+ OTHER_ACCESSIBLE = 64,
470
+ /**
471
+ * The entity is not owned by anyone.
472
+ */
473
+ UNOWNED = 128,
474
+ }
475
+
305
476
  export interface TilmeldInterface {
306
477
  nymph: Nymph;
307
478
  request: any;
@@ -309,9 +480,12 @@ export interface TilmeldInterface {
309
480
  init(nymph: Nymph): void;
310
481
  clone(): TilmeldInterface;
311
482
  gatekeeper(ability?: string): boolean;
312
- authenticate(): void;
483
+ authenticate(skipXsrfToken?: boolean, skipRenew?: boolean): Promise<boolean>;
313
484
  clearSession(): void;
314
485
  extractToken(token: string): Promise<any>;
315
- fillSession(user: any): void;
316
- checkClientUIDPermissions(name: string, type?: TilmeldAccessLevels): boolean;
486
+ fillSession(user: any): Promise<void>;
487
+ checkClientUIDPermissions(
488
+ name: string,
489
+ type?: TilmeldAccessLevels,
490
+ ): Promise<boolean>;
317
491
  }
@@ -1,8 +1,41 @@
1
- import { Config } from './d';
1
+ import createDebug, { type Debugger } from 'debug';
2
+
3
+ import type { Config } from './index.js';
4
+
5
+ const debuggers: {
6
+ [k: string]: { info: Debugger; log: Debugger; error: Debugger };
7
+ } = {};
8
+
9
+ function getDebuggers(source: string) {
10
+ if (source in debuggers) {
11
+ return debuggers[source];
12
+ }
13
+
14
+ debuggers[source] = {
15
+ info: createDebug(`nymphjs:info:${source}`),
16
+ log: createDebug(`nymphjs:log:${source}`),
17
+ error: createDebug(`nymphjs:error:${source}`),
18
+ };
19
+
20
+ debuggers[source].info.log = console.info.bind(console);
21
+ debuggers[source].log.log = console.log.bind(console);
22
+
23
+ return debuggers[source];
24
+ }
2
25
 
3
26
  export default {
4
27
  cache: false,
5
28
  cacheThreshold: 4,
6
29
  cacheLimit: 50,
7
30
  emptyListError: false,
31
+ updateMDate: true,
32
+ debugInfo: (source, message) => {
33
+ getDebuggers(source).info(message);
34
+ },
35
+ debugLog: (source, message) => {
36
+ getDebuggers(source).log(message);
37
+ },
38
+ debugError: (source, message) => {
39
+ getDebuggers(source).error(message);
40
+ },
8
41
  } as Config;
package/src/conf/index.ts CHANGED
@@ -1,4 +1,52 @@
1
- export { Config } from './d';
1
+ /**
2
+ * Nymph Config
3
+ */
4
+ export interface Config {
5
+ /**
6
+ * Cache recently retrieved entities to speed up database queries. Uses more
7
+ * memory.
8
+ */
9
+ cache: boolean;
10
+ /**
11
+ * Cache entities after they're accessed this many times.
12
+ */
13
+ cacheThreshold: number;
14
+ /**
15
+ * The number of recently retrieved entities to cache. If you're running out
16
+ * of memory, try lowering this value. 0 means unlimited.
17
+ */
18
+ cacheLimit: number;
19
+ /**
20
+ * When querying for multiple entities with NymphREST, if the list is empty,
21
+ * return a 404 error.
22
+ */
23
+ emptyListError: boolean;
24
+ /**
25
+ * Whether to update the mdate property when saving an entity.
26
+ *
27
+ * You should probably only set this to false if you're doing migrations. Some
28
+ * things depend on having updated mdates (like conflict detection to avoid
29
+ * lost updates).
30
+ *
31
+ * If you set this to a number, that amount of milliseconds will be added to
32
+ * the mdate on any entities that are saved. This should solve the lost update
33
+ * problem when set to a small number (~1000), and keep mdates relatively
34
+ * unchanged.
35
+ */
36
+ updateMDate: boolean | number;
37
+ /**
38
+ * A function to log info messages. By default, uses the `debug` package.
39
+ */
40
+ debugInfo: (source: string, message: string) => void;
41
+ /**
42
+ * A function to log debug messages. By default, uses the `debug` package.
43
+ */
44
+ debugLog: (source: string, message: string) => void;
45
+ /**
46
+ * A function to log error messages. By default, uses the `debug` package.
47
+ */
48
+ debugError: (source: string, message: string) => void;
49
+ }
2
50
 
3
- import defaults from './defaults';
51
+ import defaults from './defaults.js';
4
52
  export { defaults as ConfigDefaults };