@nymphjs/nymph 1.0.0-alpha.3 → 1.0.0-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Nymph.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Config, ConfigDefaults as defaults } from './conf';
2
2
  import { NymphDriver } from './driver';
3
3
  import Entity from './Entity';
4
- import { EntityConstructor, EntityInterface } from './Entity.types';
4
+ import { EntityConstructor, EntityData, EntityInterface } from './Entity.types';
5
5
  import { ClassNotAvailableError } from './errors';
6
6
  import type {
7
7
  Selector,
@@ -58,7 +58,12 @@ export default class Nymph {
58
58
  /**
59
59
  * A simple map of names to Entity classes.
60
60
  */
61
- public entityClasses: { [k: string]: EntityConstructor } = {};
61
+ private entityClasses: { [k: string]: EntityConstructor } = {};
62
+
63
+ /**
64
+ * The entity class for this instance of Nymph.
65
+ */
66
+ public Entity: typeof Entity = Entity;
62
67
 
63
68
  private connectCallbacks: NymphConnectCallback[] = [];
64
69
  private disconnectCallbacks: NymphDisconnectCallback[] = [];
@@ -82,8 +87,8 @@ export default class Nymph {
82
87
  private beforeDeleteUIDCallbacks: NymphBeforeDeleteUIDCallback[] = [];
83
88
  private afterDeleteUIDCallbacks: NymphAfterDeleteUIDCallback[] = [];
84
89
 
85
- public setEntityClass(className: string, entityClass: EntityConstructor) {
86
- this.entityClasses[className] = entityClass;
90
+ public addEntityClass(entityClass: EntityConstructor) {
91
+ this.entityClasses[entityClass.class] = entityClass;
87
92
  entityClass.nymph = this;
88
93
  }
89
94
 
@@ -114,8 +119,10 @@ export default class Nymph {
114
119
  this.tilmeld = tilmeld;
115
120
  }
116
121
 
117
- class NymphEntity extends Entity {}
118
- this.setEntityClass(NymphEntity.class, NymphEntity);
122
+ class NymphEntity<T extends EntityData = EntityData> extends Entity<T> {}
123
+ NymphEntity.nymph = this;
124
+ this.Entity = NymphEntity;
125
+ this.addEntityClass(NymphEntity);
119
126
 
120
127
  this.driver.init(this);
121
128
  if (this.tilmeld) {
@@ -124,14 +131,17 @@ export default class Nymph {
124
131
  }
125
132
 
126
133
  /**
127
- * This is used internally by Nymph. Don't call it yourself.
134
+ * Get a clone of this instance with duplicate classes and event listeners.
135
+ *
128
136
  * @returns A clone of this instance.
129
137
  */
130
138
  public clone() {
131
139
  const nymph = new Nymph(this.config, this.driver, this.tilmeld?.clone());
132
- nymph.entityClasses = this.entityClasses;
133
- if (nymph.tilmeld) {
134
- nymph.tilmeld.init(nymph);
140
+ for (const name in this.entityClasses) {
141
+ if (name === 'Entity' || (this.entityClasses[name] as any).skipOnClone) {
142
+ continue;
143
+ }
144
+ nymph.addEntityClass(this.entityClasses[name]);
135
145
  }
136
146
 
137
147
  const events = [
@@ -161,7 +171,7 @@ export default class Nymph {
161
171
  // @ts-ignore: The callback should be the right type here.
162
172
  const callbacks = this[prop];
163
173
  for (let callback of callbacks) {
164
- if (callback.tilmeld) {
174
+ if (callback.skipOnClone) {
165
175
  continue;
166
176
  }
167
177
  nymph.on(event as NymphEventType, callback);
@@ -180,7 +190,7 @@ export default class Nymph {
180
190
  const result = this.driver.connect();
181
191
  for (let callback of this.connectCallbacks) {
182
192
  if (callback) {
183
- callback(result);
193
+ callback(this, result);
184
194
  }
185
195
  }
186
196
  return await result;
@@ -195,7 +205,7 @@ export default class Nymph {
195
205
  const result = this.driver.disconnect();
196
206
  for (let callback of this.disconnectCallbacks) {
197
207
  if (callback) {
198
- callback(result);
208
+ callback(this, result);
199
209
  }
200
210
  }
201
211
  return await result;
@@ -210,7 +220,7 @@ export default class Nymph {
210
220
  ) {
211
221
  for (let callback of this.queryCallbacks) {
212
222
  if (callback) {
213
- callback(options, selectors);
223
+ callback(this, options, selectors);
214
224
  }
215
225
  }
216
226
  }
@@ -282,13 +292,13 @@ export default class Nymph {
282
292
  public async newUID(name: string): Promise<number | null> {
283
293
  for (let callback of this.beforeNewUIDCallbacks) {
284
294
  if (callback) {
285
- callback(name);
295
+ callback(this, name);
286
296
  }
287
297
  }
288
298
  const result = this.driver.newUID(name);
289
299
  for (let callback of this.afterNewUIDCallbacks) {
290
300
  if (callback) {
291
- callback(result);
301
+ callback(this, result);
292
302
  }
293
303
  }
294
304
  return await result;
@@ -313,13 +323,13 @@ export default class Nymph {
313
323
  public async setUID(name: string, value: number): Promise<boolean> {
314
324
  for (let callback of this.beforeSetUIDCallbacks) {
315
325
  if (callback) {
316
- callback(name, value);
326
+ callback(this, name, value);
317
327
  }
318
328
  }
319
329
  const result = this.driver.setUID(name, value);
320
330
  for (let callback of this.afterSetUIDCallbacks) {
321
331
  if (callback) {
322
- callback(result);
332
+ callback(this, result);
323
333
  }
324
334
  }
325
335
  return await result;
@@ -334,13 +344,13 @@ export default class Nymph {
334
344
  public async deleteUID(name: string): Promise<boolean> {
335
345
  for (let callback of this.beforeDeleteUIDCallbacks) {
336
346
  if (callback) {
337
- callback(name);
347
+ callback(this, name);
338
348
  }
339
349
  }
340
350
  const result = this.driver.deleteUID(name);
341
351
  for (let callback of this.afterDeleteUIDCallbacks) {
342
352
  if (callback) {
343
- callback(result);
353
+ callback(this, result);
344
354
  }
345
355
  }
346
356
  return await result;
@@ -356,13 +366,13 @@ export default class Nymph {
356
366
  public async renameUID(oldName: string, newName: string): Promise<boolean> {
357
367
  for (let callback of this.beforeRenameUIDCallbacks) {
358
368
  if (callback) {
359
- callback(oldName, newName);
369
+ callback(this, oldName, newName);
360
370
  }
361
371
  }
362
372
  const result = this.driver.renameUID(oldName, newName);
363
373
  for (let callback of this.afterRenameUIDCallbacks) {
364
374
  if (callback) {
365
- callback(result);
375
+ callback(this, result);
366
376
  }
367
377
  }
368
378
  return await result;
@@ -382,13 +392,13 @@ export default class Nymph {
382
392
  public async saveEntity(entity: EntityInterface): Promise<boolean> {
383
393
  for (let callback of this.beforeSaveEntityCallbacks) {
384
394
  if (callback) {
385
- callback(entity);
395
+ callback(this, entity);
386
396
  }
387
397
  }
388
398
  const result = this.driver.saveEntity(entity);
389
399
  for (let callback of this.afterSaveEntityCallbacks) {
390
400
  if (callback) {
391
- callback(result);
401
+ callback(this, result);
392
402
  }
393
403
  }
394
404
  return await result;
@@ -477,10 +487,10 @@ export default class Nymph {
477
487
  * entities that were created in the last day:
478
488
  *
479
489
  * ```
480
- * [
481
- * '&',
482
- * 'gte' => ['cdate', null, '-1 day']
483
- * ]
490
+ * {
491
+ * type: '&',
492
+ * gte: ['cdate', null, '-1 day']
493
+ * }
484
494
  * ```
485
495
  *
486
496
  * Locutus' implementation: https://locutus.io/php/datetime/strtotime/
@@ -567,7 +577,7 @@ export default class Nymph {
567
577
  ): Promise<ReturnType<T['factorySync']>[] | string[]> {
568
578
  for (let callback of this.beforeGetEntitiesCallbacks) {
569
579
  if (callback) {
570
- callback(options, selectors);
580
+ callback(this, options, selectors);
571
581
  }
572
582
  }
573
583
  return await this.driver.getEntities(options, ...selectors);
@@ -613,7 +623,7 @@ export default class Nymph {
613
623
  options.limit = 1;
614
624
  for (let callback of this.beforeGetEntityCallbacks) {
615
625
  if (callback) {
616
- callback(options, selectors as Selector[]);
626
+ callback(this, options, selectors as Selector[]);
617
627
  }
618
628
  }
619
629
  const entities = await this.driver.getEntities(
@@ -635,13 +645,13 @@ export default class Nymph {
635
645
  public async deleteEntity(entity: EntityInterface): Promise<boolean> {
636
646
  for (let callback of this.beforeDeleteEntityCallbacks) {
637
647
  if (callback) {
638
- callback(entity);
648
+ callback(this, entity);
639
649
  }
640
650
  }
641
651
  const result = this.driver.deleteEntity(entity);
642
652
  for (let callback of this.afterDeleteEntityCallbacks) {
643
653
  if (callback) {
644
- callback(result);
654
+ callback(this, result);
645
655
  }
646
656
  }
647
657
  return await result;
@@ -660,13 +670,13 @@ export default class Nymph {
660
670
  ): Promise<boolean> {
661
671
  for (let callback of this.beforeDeleteEntityByIDCallbacks) {
662
672
  if (callback) {
663
- callback(guid, className);
673
+ callback(this, guid, className);
664
674
  }
665
675
  }
666
676
  const result = this.driver.deleteEntityByID(guid, className);
667
677
  for (let callback of this.afterDeleteEntityByIDCallbacks) {
668
678
  if (callback) {
669
- callback(result);
679
+ callback(this, result);
670
680
  }
671
681
  }
672
682
  return await result;
@@ -21,43 +21,83 @@ export type NymphEventType =
21
21
  | 'afterRenameUID'
22
22
  | 'beforeDeleteUID'
23
23
  | 'afterDeleteUID';
24
- export type NymphConnectCallback = (result: Promise<boolean>) => void;
25
- export type NymphDisconnectCallback = (result: Promise<boolean>) => void;
24
+ export type NymphConnectCallback = (
25
+ nymph: Nymph,
26
+ result: Promise<boolean>
27
+ ) => void;
28
+ export type NymphDisconnectCallback = (
29
+ nymph: Nymph,
30
+ result: Promise<boolean>
31
+ ) => void;
26
32
  /** The NymphQueryCallback will be called on both top level and qref queries. */
27
33
  export type NymphQueryCallback = (
34
+ nymph: Nymph,
28
35
  options: Options,
29
36
  selectors: FormattedSelector[]
30
37
  ) => void;
31
38
  export type NymphBeforeGetEntityCallback = (
39
+ nymph: Nymph,
32
40
  options: Options,
33
41
  selectors: Selector[]
34
42
  ) => void;
35
43
  export type NymphBeforeGetEntitiesCallback = (
44
+ nymph: Nymph,
36
45
  options: Options,
37
46
  selectors: Selector[]
38
47
  ) => void;
39
- export type NymphBeforeSaveEntityCallback = (entity: EntityInterface) => void;
40
- export type NymphAfterSaveEntityCallback = (result: Promise<boolean>) => void;
41
- export type NymphBeforeDeleteEntityCallback = (entity: EntityInterface) => void;
42
- export type NymphAfterDeleteEntityCallback = (result: Promise<boolean>) => void;
48
+ export type NymphBeforeSaveEntityCallback = (
49
+ nymph: Nymph,
50
+ entity: EntityInterface
51
+ ) => void;
52
+ export type NymphAfterSaveEntityCallback = (
53
+ nymph: Nymph,
54
+ result: Promise<boolean>
55
+ ) => void;
56
+ export type NymphBeforeDeleteEntityCallback = (
57
+ nymph: Nymph,
58
+ entity: EntityInterface
59
+ ) => void;
60
+ export type NymphAfterDeleteEntityCallback = (
61
+ nymph: Nymph,
62
+ result: Promise<boolean>
63
+ ) => void;
43
64
  export type NymphBeforeDeleteEntityByIDCallback = (
65
+ nymph: Nymph,
44
66
  guid: string,
45
67
  className?: string
46
68
  ) => void;
47
69
  export type NymphAfterDeleteEntityByIDCallback = (
70
+ nymph: Nymph,
71
+ result: Promise<boolean>
72
+ ) => void;
73
+ export type NymphBeforeNewUIDCallback = (nymph: Nymph, name: string) => void;
74
+ export type NymphAfterNewUIDCallback = (
75
+ nymph: Nymph,
76
+ result: Promise<number | null>
77
+ ) => void;
78
+ export type NymphBeforeSetUIDCallback = (
79
+ nymph: Nymph,
80
+ name: string,
81
+ value: number
82
+ ) => void;
83
+ export type NymphAfterSetUIDCallback = (
84
+ nymph: Nymph,
48
85
  result: Promise<boolean>
49
86
  ) => void;
50
- export type NymphBeforeNewUIDCallback = (name: string) => void;
51
- export type NymphAfterNewUIDCallback = (result: Promise<number | null>) => void;
52
- export type NymphBeforeSetUIDCallback = (name: string, value: number) => void;
53
- export type NymphAfterSetUIDCallback = (result: Promise<boolean>) => void;
54
87
  export type NymphBeforeRenameUIDCallback = (
88
+ nymph: Nymph,
55
89
  oldName: string,
56
90
  newName: string
57
91
  ) => void;
58
- export type NymphAfterRenameUIDCallback = (result: Promise<boolean>) => void;
59
- export type NymphBeforeDeleteUIDCallback = (name: string) => void;
60
- export type NymphAfterDeleteUIDCallback = (result: Promise<boolean>) => void;
92
+ export type NymphAfterRenameUIDCallback = (
93
+ nymph: Nymph,
94
+ result: Promise<boolean>
95
+ ) => void;
96
+ export type NymphBeforeDeleteUIDCallback = (nymph: Nymph, name: string) => void;
97
+ export type NymphAfterDeleteUIDCallback = (
98
+ nymph: Nymph,
99
+ result: Promise<boolean>
100
+ ) => void;
61
101
 
62
102
  export type Options<T extends EntityConstructor = EntityConstructor> = {
63
103
  class?: T;
@@ -238,6 +278,14 @@ export type FormattedSelector = {
238
278
  '!selector'?: FormattedSelector['selector'];
239
279
  };
240
280
 
281
+ export enum TilmeldAccessLevels {
282
+ NO_ACCESS = 0,
283
+ READ_ACCESS = 1,
284
+ WRITE_ACCESS = 2,
285
+ // Keeping 3 open in case we ever need one between write and full.
286
+ FULL_ACCESS = 4,
287
+ }
288
+
241
289
  export interface TilmeldInterface {
242
290
  nymph: Nymph;
243
291
  request: any;
@@ -249,4 +297,5 @@ export interface TilmeldInterface {
249
297
  clearSession(): void;
250
298
  extractToken(token: string): any;
251
299
  fillSession(user: any): void;
300
+ checkClientUIDPermissions(name: string, type?: TilmeldAccessLevels): boolean;
252
301
  }
@@ -9,8 +9,8 @@ export function QueriesTest(
9
9
  nymph: Nymph,
10
10
  it: (name: string, fn: () => void) => void
11
11
  ) {
12
- nymph.setEntityClass(TestModel.class, TestModel);
13
- nymph.setEntityClass(TestBModel.class, TestBModel);
12
+ nymph.addEntityClass(TestModel);
13
+ nymph.addEntityClass(TestBModel);
14
14
 
15
15
  let testEntity: TestModel & TestModelData;
16
16
  let testGuid: string;
@@ -1679,8 +1679,8 @@ export function UIDTest(
1679
1679
  nymph: Nymph,
1680
1680
  it: (name: string, fn: () => void) => void
1681
1681
  ) {
1682
- nymph.setEntityClass(TestModel.class, TestModel);
1683
- nymph.setEntityClass(TestBModel.class, TestBModel);
1682
+ nymph.addEntityClass(TestModel);
1683
+ nymph.addEntityClass(TestBModel);
1684
1684
 
1685
1685
  it('delete old test data', async () => {
1686
1686
  expect(await nymph.deleteUID('TestUID')).toEqual(true);
@@ -1723,8 +1723,8 @@ export function ExportImportTest(
1723
1723
  nymph: Nymph,
1724
1724
  it: (name: string, fn: () => void) => void
1725
1725
  ) {
1726
- nymph.setEntityClass(TestModel.class, TestModel);
1727
- nymph.setEntityClass(TestBModel.class, TestBModel);
1726
+ nymph.addEntityClass(TestModel);
1727
+ nymph.addEntityClass(TestBModel);
1728
1728
 
1729
1729
  async function deleteTestData() {
1730
1730
  let all = await nymph.getEntities({ class: TestModel });
package/src/index.ts CHANGED
@@ -17,4 +17,7 @@ export * from './Nymph';
17
17
  import Nymph from './Nymph';
18
18
  export { Nymph };
19
19
 
20
+ import nymphJoiProps from './nymphJoiProps';
21
+ export { nymphJoiProps };
22
+
20
23
  export * from './utils';
@@ -0,0 +1,26 @@
1
+ import Joi from 'joi';
2
+
3
+ export default {
4
+ guid: Joi.alternatives()
5
+ .try(
6
+ Joi.any().only().allow(null),
7
+ Joi.string().trim(false).length(24).hex()
8
+ )
9
+ .required(),
10
+ cdate: Joi.alternatives()
11
+ .try(Joi.any().only().allow(null), Joi.number())
12
+ .required(),
13
+ mdate: Joi.alternatives()
14
+ .try(Joi.any().only().allow(null), Joi.number())
15
+ .required(),
16
+ tags: Joi.array()
17
+ .items(
18
+ Joi.string()
19
+ .pattern(/[[\x01-\x1F\x7F]]/, {
20
+ name: 'control characters',
21
+ invert: true,
22
+ })
23
+ .min(1)
24
+ )
25
+ .required(),
26
+ };
package/src/testMocks.ts CHANGED
@@ -55,7 +55,7 @@ export class MockNymphDriver {
55
55
  }
56
56
 
57
57
  export class MockNymph {
58
- public entityClasses: { [k: string]: EntityConstructor } = {};
58
+ private entityClasses: { [k: string]: EntityConstructor } = {};
59
59
  public driver: MockNymphDriver;
60
60
  public Tilmeld: any = undefined;
61
61
 
@@ -63,11 +63,11 @@ export class MockNymph {
63
63
  this.driver = new MockNymphDriver(this);
64
64
 
65
65
  // class NymphEntity extends Entity {}
66
- this.setEntityClass(Entity.class, Entity);
66
+ this.addEntityClass(Entity);
67
67
  }
68
68
 
69
- public setEntityClass(className: string, entityClass: EntityConstructor) {
70
- this.entityClasses[className] = entityClass;
69
+ public addEntityClass(entityClass: EntityConstructor) {
70
+ this.entityClasses[entityClass.class] = entityClass;
71
71
  entityClass.nymph = this as unknown as Nymph;
72
72
  }
73
73