@nymphjs/nymph 1.0.0-beta.1 → 1.0.0-beta.100

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 +535 -0
  2. package/README.md +14 -22
  3. package/dist/Entity.d.ts +293 -10
  4. package/dist/Entity.js +571 -149
  5. package/dist/Entity.js.map +1 -1
  6. package/dist/Entity.test.js +67 -26
  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 +497 -13
  11. package/dist/Nymph.js +761 -188
  12. package/dist/Nymph.js.map +1 -1
  13. package/dist/Nymph.types.d.ts +95 -26
  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 +181 -43
  25. package/dist/driver/NymphDriver.js +532 -285
  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 +939 -219
  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 +19 -6
  65. package/dist/testArtifacts.js +32 -37
  66. package/dist/testArtifacts.js.map +1 -1
  67. package/dist/testMocks.d.ts +28 -11
  68. package/dist/testMocks.js +44 -28
  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 +24 -20
  75. package/src/Entity.test.ts +63 -13
  76. package/src/Entity.ts +498 -156
  77. package/src/Entity.types.ts +72 -74
  78. package/src/Nymph.ts +904 -336
  79. package/src/Nymph.types.ts +179 -44
  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 +650 -460
  84. package/src/driver/index.ts +2 -2
  85. package/src/driver/testArtifacts.ts +966 -196
  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 +20 -20
  92. package/src/testMocks.ts +85 -37
  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
@@ -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,105 +9,228 @@ 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>
27
- ) => void;
39
+ result: Promise<boolean>,
40
+ ) => Promise<void>;
28
41
  export type NymphDisconnectCallback = (
29
42
  nymph: Nymph,
30
- result: Promise<boolean>
31
- ) => void;
32
- /** The NymphQueryCallback will be called on both top level and qref queries. */
43
+ result: Promise<boolean>,
44
+ ) => Promise<void>;
45
+ /**
46
+ * The NymphQueryCallback will be called on both top level and qref queries.
47
+ *
48
+ * This is the only callback that is not asynchronous.
49
+ *
50
+ * This also isn't necessarily run on every "query". It is run before a database
51
+ * query for an entity, but it is not run during PubSub entity change
52
+ * propagation. Therefore, it shouldn't do anything _entity_ specific, instead
53
+ * it should be _query_ specific. For example, throw an error if the user is not
54
+ * permitted to run the query at all.
55
+ */
33
56
  export type NymphQueryCallback = (
34
57
  nymph: Nymph,
35
58
  options: Options,
36
- selectors: FormattedSelector[]
59
+ selectors: FormattedSelector[],
37
60
  ) => void;
38
61
  export type NymphBeforeGetEntityCallback = (
39
62
  nymph: Nymph,
40
63
  options: Options,
41
- selectors: Selector[]
42
- ) => void;
64
+ selectors: Selector[],
65
+ ) => Promise<void>;
43
66
  export type NymphBeforeGetEntitiesCallback = (
44
67
  nymph: Nymph,
45
68
  options: Options,
46
- selectors: Selector[]
47
- ) => void;
69
+ selectors: Selector[],
70
+ ) => Promise<void>;
48
71
  export type NymphBeforeSaveEntityCallback = (
49
72
  nymph: Nymph,
50
- entity: EntityInterface
51
- ) => void;
73
+ entity: EntityInterface,
74
+ ) => Promise<void>;
52
75
  export type NymphAfterSaveEntityCallback = (
53
76
  nymph: Nymph,
54
- result: Promise<boolean>
55
- ) => void;
77
+ result: Promise<boolean>,
78
+ ) => Promise<void>;
79
+ export type NymphFailedSaveEntityCallback = (
80
+ nymph: Nymph,
81
+ error: any,
82
+ ) => Promise<void>;
56
83
  export type NymphBeforeDeleteEntityCallback = (
57
84
  nymph: Nymph,
58
- entity: EntityInterface
59
- ) => void;
85
+ entity: EntityInterface,
86
+ ) => Promise<void>;
60
87
  export type NymphAfterDeleteEntityCallback = (
61
88
  nymph: Nymph,
62
- result: Promise<boolean>
63
- ) => void;
89
+ result: Promise<boolean>,
90
+ ) => Promise<void>;
91
+ export type NymphFailedDeleteEntityCallback = (
92
+ nymph: Nymph,
93
+ error: any,
94
+ ) => Promise<void>;
64
95
  export type NymphBeforeDeleteEntityByIDCallback = (
65
96
  nymph: Nymph,
66
97
  guid: string,
67
- className?: string
68
- ) => void;
98
+ className?: string,
99
+ ) => Promise<void>;
69
100
  export type NymphAfterDeleteEntityByIDCallback = (
70
101
  nymph: Nymph,
71
- result: Promise<boolean>
72
- ) => void;
73
- export type NymphBeforeNewUIDCallback = (nymph: Nymph, name: string) => void;
102
+ result: Promise<boolean>,
103
+ ) => Promise<void>;
104
+ export type NymphFailedDeleteEntityByIDCallback = (
105
+ nymph: Nymph,
106
+ error: any,
107
+ ) => Promise<void>;
108
+ export type NymphBeforeNewUIDCallback = (
109
+ nymph: Nymph,
110
+ name: string,
111
+ ) => Promise<void>;
74
112
  export type NymphAfterNewUIDCallback = (
75
113
  nymph: Nymph,
76
- result: Promise<number | null>
77
- ) => void;
114
+ result: Promise<number | null>,
115
+ ) => Promise<void>;
116
+ export type NymphFailedNewUIDCallback = (
117
+ nymph: Nymph,
118
+ error: any,
119
+ ) => Promise<void>;
78
120
  export type NymphBeforeSetUIDCallback = (
79
121
  nymph: Nymph,
80
122
  name: string,
81
- value: number
82
- ) => void;
123
+ value: number,
124
+ ) => Promise<void>;
83
125
  export type NymphAfterSetUIDCallback = (
84
126
  nymph: Nymph,
85
- result: Promise<boolean>
86
- ) => void;
127
+ result: Promise<boolean>,
128
+ ) => Promise<void>;
129
+ export type NymphFailedSetUIDCallback = (
130
+ nymph: Nymph,
131
+ error: any,
132
+ ) => Promise<void>;
87
133
  export type NymphBeforeRenameUIDCallback = (
88
134
  nymph: Nymph,
89
135
  oldName: string,
90
- newName: string
91
- ) => void;
136
+ newName: string,
137
+ ) => Promise<void>;
92
138
  export type NymphAfterRenameUIDCallback = (
93
139
  nymph: Nymph,
94
- result: Promise<boolean>
95
- ) => void;
96
- export type NymphBeforeDeleteUIDCallback = (nymph: Nymph, name: string) => void;
140
+ result: Promise<boolean>,
141
+ ) => Promise<void>;
142
+ export type NymphFailedRenameUIDCallback = (
143
+ nymph: Nymph,
144
+ error: any,
145
+ ) => Promise<void>;
146
+ export type NymphBeforeDeleteUIDCallback = (
147
+ nymph: Nymph,
148
+ name: string,
149
+ ) => Promise<void>;
97
150
  export type NymphAfterDeleteUIDCallback = (
98
151
  nymph: Nymph,
99
- result: Promise<boolean>
100
- ) => void;
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,
184
+ ) => Promise<void>;
101
185
 
102
186
  export type Options<T extends EntityConstructor = EntityConstructor> = {
187
+ /**
188
+ * The Entity class to query.
189
+ */
103
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
+ */
104
195
  limit?: number;
196
+ /**
197
+ * The offset from the first matching entity, in order, to start retrieving.
198
+ */
105
199
  offset?: number;
200
+ /**
201
+ * If true, entities will be retrieved from newest to oldest/largest to
202
+ * smallest (with regard to `sort`).
203
+ */
106
204
  reverse?: boolean;
107
- sort?: 'cdate' | 'mdate';
108
- return?: 'entity' | 'guid' | 'count';
205
+ /**
206
+ * How to sort the entities. Should be "cdate", "mdate", or the name of a
207
+ * property.
208
+ */
209
+ sort?: 'cdate' | 'mdate' | string;
210
+ /**
211
+ * What to return, the entities with their data, just the entity data, just
212
+ * the GUIDs, or just a count.
213
+ *
214
+ * 'object' is only available on the server, as there are substantial security
215
+ * implications with using it. It returns the full entity data as a simple
216
+ * object. You should only use it for operations where instantiating the
217
+ * entities has an unacceptable performance cost.
218
+ */
219
+ return?: 'entity' | 'object' | 'guid' | 'count';
220
+ /**
221
+ * Will be 'client' if the query came from a REST request or the PubSub
222
+ * server. (Mainly used in Tilmeld for access control.)
223
+ */
109
224
  source?: string;
225
+ /**
226
+ * If true, Nymph will skip the cache and retrieve the entity from the DB.
227
+ */
110
228
  skipCache?: boolean;
229
+ /**
230
+ * If true, Tilmeld will not filter returned entities according to access
231
+ * controls. (If Tilmeld is installed.) (This is always set to false by the
232
+ * REST endpoint and PubSub server.)
233
+ */
111
234
  skipAc?: boolean;
112
235
  };
113
236
 
@@ -134,6 +257,9 @@ type PrimitiveSelector = {
134
257
  contain?: [string, any];
135
258
  '!contain'?: PrimitiveSelector['contain'];
136
259
 
260
+ search?: [string, string];
261
+ '!search'?: PrimitiveSelector['search'];
262
+
137
263
  match?: [string, string];
138
264
  '!match'?: PrimitiveSelector['match'];
139
265
 
@@ -189,6 +315,9 @@ export type Selector = {
189
315
  contain?: Clause<OrWithTime<PrimitiveSelector['contain']>>;
190
316
  '!contain'?: Clause<OrWithTime<PrimitiveSelector['contain']>>;
191
317
 
318
+ search?: Clause<PrimitiveSelector['search']>;
319
+ '!search'?: Clause<PrimitiveSelector['search']>;
320
+
192
321
  match?: Clause<PrimitiveSelector['match']>;
193
322
  '!match'?: Clause<PrimitiveSelector['match']>;
194
323
 
@@ -244,6 +373,9 @@ export type FormattedSelector = {
244
373
  contain?: PrimitiveSelector['contain'][];
245
374
  '!contain'?: PrimitiveSelector['contain'][];
246
375
 
376
+ search?: PrimitiveSelector['search'][];
377
+ '!search'?: PrimitiveSelector['search'][];
378
+
247
379
  match?: PrimitiveSelector['match'][];
248
380
  '!match'?: PrimitiveSelector['match'][];
249
381
 
@@ -293,9 +425,12 @@ export interface TilmeldInterface {
293
425
  init(nymph: Nymph): void;
294
426
  clone(): TilmeldInterface;
295
427
  gatekeeper(ability?: string): boolean;
296
- authenticate(): void;
428
+ authenticate(skipXsrfToken?: boolean, skipRenew?: boolean): Promise<boolean>;
297
429
  clearSession(): void;
298
430
  extractToken(token: string): Promise<any>;
299
- fillSession(user: any): void;
300
- checkClientUIDPermissions(name: string, type?: TilmeldAccessLevels): boolean;
431
+ fillSession(user: any): Promise<void>;
432
+ checkClientUIDPermissions(
433
+ name: string,
434
+ type?: TilmeldAccessLevels,
435
+ ): Promise<boolean>;
301
436
  }
package/src/conf/d.ts CHANGED
@@ -21,4 +21,29 @@ export interface Config {
21
21
  * return a 404 error.
22
22
  */
23
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;
24
49
  }
@@ -1,8 +1,41 @@
1
- import { Config } from './d';
1
+ import createDebug, { type Debugger } from 'debug';
2
+
3
+ import { Config } from './d.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,4 @@
1
- export { Config } from './d';
1
+ export { Config } from './d.js';
2
2
 
3
- import defaults from './defaults';
3
+ import defaults from './defaults.js';
4
4
  export { defaults as ConfigDefaults };