@travetto/model 3.1.0-rc.6 → 3.1.0-rc.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/README.md CHANGED
@@ -60,10 +60,9 @@ The [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/servi
60
60
  export interface ModelCrudSupport extends ModelBasicSupport {
61
61
 
62
62
  /**
63
- * Generate a uuid
64
- * @param value The optional value to generate a uuid around. Passing the same value multiple times produces the same output.
63
+ * Uuid Generator
65
64
  */
66
- uuid(): string;
65
+ uuid: UuidGenerator;
67
66
 
68
67
  /**
69
68
  * Update an item
@@ -234,8 +233,8 @@ All fields are optional, but the `id` and `type` are important as those field ty
234
233
  |[Redis Model Support](https://github.com/travetto/travetto/tree/main/module/model-redis#readme "Redis backing for the travetto model module.")|X|X|X|X| ||
235
234
  |[S3 Model Support](https://github.com/travetto/travetto/tree/main/module/model-s3#readme "S3 backing for the travetto model module.")|X|X| |X|X| |
236
235
  |[SQL Model Service](https://github.com/travetto/travetto/tree/main/module/model-sql#readme "SQL backing for the travetto model module, with real-time modeling support for SQL schemas.")|X|X|X|X| |X|
237
- |[MemoryModelService](https://github.com/travetto/travetto/tree/main/module/model/src/provider/memory.ts#L54)|X|X|X|X|X|X|
238
- |[FileModelService](https://github.com/travetto/travetto/tree/main/module/model/src/provider/file.ts#L51)|X|X| |X|X|X|
236
+ |[MemoryModelService](https://github.com/travetto/travetto/tree/main/module/model/src/provider/memory.ts#L53)|X|X|X|X|X|X|
237
+ |[FileModelService](https://github.com/travetto/travetto/tree/main/module/model/src/provider/file.ts#L50)|X|X| |X|X|X|
239
238
 
240
239
  ## Custom Model Service
241
240
  In addition to the provided contracts, the module also provides common utilities and shared test suites. The common utilities are useful for repetitive functionality, that is unable to be shared due to not relying upon inheritance (this was an intentional design decision). This allows for all the [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations.") implementations to completely own the functionality and also to be able to provide additional/unique functionality that goes beyond the interface.
@@ -262,7 +261,6 @@ import { ModelIndexedUtil } from '../internal/service/indexed';
262
261
  import { ModelStorageUtil } from '../internal/service/storage';
263
262
  import { StreamModel, STREAMS } from '../internal/service/stream';
264
263
  import { IndexConfig } from '../registry/types';
265
- import { ModelUtil } from '../internal/util';
266
264
  const STREAM_META = `${STREAMS}_meta`;
267
265
  type StoreType = Map<string, Buffer>;
268
266
  @Config('model.memory')
@@ -291,11 +289,11 @@ export class MemoryModelService implements ModelCrudSupport, ModelStreamSupport,
291
289
  sorted: new Map<string, Map<string, Map<string, number>>>(),
292
290
  unsorted: new Map<string, Map<string, Set<string>>>()
293
291
  };
292
+ uuid = ModelCrudUtil.uuidGenerator();
294
293
  get client(): Map<string, StoreType>;
295
294
  constructor(public readonly config: MemoryModelConfig) { }
296
295
  async postConstruct(): Promise<void>;
297
296
  // CRUD Support
298
- uuid(): string;
299
297
  async get<T extends ModelType>(cls: Class<T>, id: string): Promise<T>;
300
298
  async create<T extends ModelType>(cls: Class<T>, item: OptionalId<T>): Promise<T>;
301
299
  async update<T extends ModelType>(cls: Class<T>, item: T): Promise<T>;
package/__index__.ts CHANGED
@@ -9,6 +9,7 @@ export * from './src/service/indexed';
9
9
  export * from './src/service/expiry';
10
10
  export * from './src/service/storage';
11
11
  export * from './src/service/stream';
12
+ export * from './src/service/types';
12
13
 
13
14
  export * from './src/provider/file';
14
15
  export * from './src/provider/memory';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/model",
3
- "version": "3.1.0-rc.6",
3
+ "version": "3.1.0-rc.7",
4
4
  "description": "Datastore abstraction for core operations.",
5
5
  "keywords": [
6
6
  "datastore",
@@ -32,7 +32,7 @@
32
32
  "@travetto/schema": "^3.1.0-rc.5"
33
33
  },
34
34
  "peerDependencies": {
35
- "@travetto/cli": "^3.1.0-rc.6",
35
+ "@travetto/cli": "^3.1.0-rc.8",
36
36
  "@travetto/test": "^3.1.0-rc.4"
37
37
  },
38
38
  "peerDependenciesMeta": {
@@ -1,6 +1,7 @@
1
1
  import { Class } from '@travetto/base';
2
2
 
3
3
  import { BulkOp } from '../../service/bulk';
4
+ import { ModelUuidGenerator } from '../../service/types';
4
5
  import { ModelType } from '../../types/model';
5
6
  import { ModelCrudUtil } from './crud';
6
7
 
@@ -19,7 +20,7 @@ export class ModelBulkUtil {
19
20
  * @param operations
20
21
  * @param idSource
21
22
  */
22
- static async preStore<T extends ModelType>(cls: Class<T>, operations: BulkOp<T>[], idSource: { uuid(): string }): Promise<BulkPreStore<T>> {
23
+ static async preStore<T extends ModelType>(cls: Class<T>, operations: BulkOp<T>[], idSource: { uuid: ModelUuidGenerator }): Promise<BulkPreStore<T>> {
23
24
  const insertedIds = new Map<number, string>();
24
25
  const upsertedIds = new Map<number, string>();
25
26
  const updatedIds = new Map<number, string>();
@@ -1,19 +1,38 @@
1
1
  import crypto from 'crypto';
2
2
 
3
- import { Class, ObjectUtil } from '@travetto/base';
4
- import { SchemaRegistry, SchemaValidator } from '@travetto/schema';
3
+ import { Class, ObjectUtil, Util } from '@travetto/base';
4
+ import { SchemaRegistry, SchemaValidator, ValidationError, ValidationResultError } from '@travetto/schema';
5
5
 
6
6
  import { ModelRegistry } from '../../registry/model';
7
7
  import { ModelType, OptionalId } from '../../types/model';
8
8
  import { NotFoundError } from '../../error/not-found';
9
9
  import { ExistsError } from '../../error/exists';
10
10
  import { SubTypeNotSupportedError } from '../../error/invalid-sub-type';
11
+ import { ModelUuidGenerator } from '../../service/types';
11
12
 
12
13
  /**
13
14
  * Crud utilities
14
15
  */
15
16
  export class ModelCrudUtil {
16
17
 
18
+ /**
19
+ * Build a uuid generator
20
+ */
21
+ static uuidGenerator(create: () => string, valid: (id: string) => boolean): ModelUuidGenerator;
22
+ static uuidGenerator(len?: number): ModelUuidGenerator;
23
+ static uuidGenerator(lenOrCreate: (() => string) | number = 32, valid?: (id: string) => boolean): ModelUuidGenerator {
24
+ if (typeof lenOrCreate === 'number') {
25
+ const len = lenOrCreate;
26
+ const create = (): string => Util.uuid(len);
27
+ create.valid = (id: string): boolean => id.length === len && /^[0-9a-f]+$/i.test(id);
28
+ return create;
29
+ } else {
30
+ const create = (): string => lenOrCreate();
31
+ create.valid = valid!;
32
+ return create;
33
+ }
34
+ }
35
+
17
36
  /**
18
37
  * Provide hash value
19
38
  * @param value Input value
@@ -61,7 +80,7 @@ export class ModelCrudUtil {
61
80
  * @param cls Type to store for
62
81
  * @param item Item to store
63
82
  */
64
- static async preStore<T extends ModelType>(cls: Class<T>, item: Partial<OptionalId<T>>, idSource: { uuid(): string }): Promise<T> {
83
+ static async preStore<T extends ModelType>(cls: Class<T>, item: Partial<OptionalId<T>>, idSource: { uuid: ModelUuidGenerator }): Promise<T> {
65
84
  if (!item.id) {
66
85
  item.id = idSource.uuid();
67
86
  }
@@ -77,7 +96,22 @@ export class ModelCrudUtil {
77
96
  SchemaRegistry.ensureInstanceTypeField(cls, item);
78
97
  }
79
98
 
80
- await SchemaValidator.validate(cls, item);
99
+ let errors: ValidationError[] = [];
100
+ try {
101
+ await SchemaValidator.validate(cls, item);
102
+ } catch (err) {
103
+ if (err instanceof ValidationResultError) {
104
+ errors = err.errors;
105
+ }
106
+ }
107
+
108
+ if (!idSource.uuid.valid(item.id!)) {
109
+ errors.push({ kind: 'invalid', path: 'id', value: item.id!, type: 'string', message: `${item.id!} is an invalid value for \`id\`` });
110
+ }
111
+
112
+ if (errors.length) {
113
+ throw new ValidationResultError(errors);
114
+ }
81
115
 
82
116
  if (item.prePersist) {
83
117
  await item.prePersist();
@@ -22,7 +22,6 @@ import { ModelExpiryUtil } from '../internal/service/expiry';
22
22
  import { NotFoundError } from '../error/not-found';
23
23
  import { ExistsError } from '../error/exists';
24
24
  import { StreamModel, STREAMS } from '../internal/service/stream';
25
- import { ModelUtil } from '../internal/util';
26
25
 
27
26
  type Suffix = '.bin' | '.meta' | '.json' | '.expires';
28
27
 
@@ -60,6 +59,8 @@ export class FileModelService implements ModelCrudSupport, ModelStreamSupport, M
60
59
  }
61
60
  }
62
61
 
62
+ uuid = ModelCrudUtil.uuidGenerator();
63
+
63
64
  get client(): string {
64
65
  return this.config.folder;
65
66
  }
@@ -105,10 +106,6 @@ export class FileModelService implements ModelCrudSupport, ModelStreamSupport, M
105
106
  return item;
106
107
  }
107
108
 
108
- uuid(): string {
109
- return ModelUtil.uuid(32);
110
- }
111
-
112
109
  async get<T extends ModelType>(cls: Class<T>, id: string): Promise<T> {
113
110
  await this.#find(cls, '.json', id);
114
111
 
@@ -20,7 +20,6 @@ import { ModelIndexedUtil } from '../internal/service/indexed';
20
20
  import { ModelStorageUtil } from '../internal/service/storage';
21
21
  import { StreamModel, STREAMS } from '../internal/service/stream';
22
22
  import { IndexConfig } from '../registry/types';
23
- import { ModelUtil } from '../internal/util';
24
23
 
25
24
  const STREAM_META = `${STREAMS}_meta`;
26
25
 
@@ -58,6 +57,8 @@ export class MemoryModelService implements ModelCrudSupport, ModelStreamSupport,
58
57
  sorted: new Map<string, Map<string, Map<string, number>>>(),
59
58
  unsorted: new Map<string, Map<string, Set<string>>>()
60
59
  };
60
+
61
+ uuid = ModelCrudUtil.uuidGenerator();
61
62
  get client(): Map<string, StoreType> { return this.#store; }
62
63
 
63
64
  constructor(public readonly config: MemoryModelConfig) { }
@@ -168,10 +169,6 @@ export class MemoryModelService implements ModelCrudSupport, ModelStreamSupport,
168
169
  }
169
170
 
170
171
  // CRUD Support
171
- uuid(): string {
172
- return ModelUtil.uuid(32);
173
- }
174
-
175
172
  async get<T extends ModelType>(cls: Class<T>, id: string): Promise<T> {
176
173
  const store = this.#getStore(cls);
177
174
  if (store.has(id)) {
@@ -2,19 +2,18 @@ import { Class } from '@travetto/base';
2
2
 
3
3
  import { ModelType, OptionalId } from '../types/model';
4
4
  import { ModelBasicSupport } from './basic';
5
+ import { UuidGenerator } from './types';
5
6
 
6
7
  /**
7
8
  * Interface for simple CRUD
8
- *
9
9
  * @concrete ../internal/service/common:ModelCrudSupportTarget
10
10
  */
11
11
  export interface ModelCrudSupport extends ModelBasicSupport {
12
12
 
13
13
  /**
14
- * Generate a uuid
15
- * @param value The optional value to generate a uuid around. Passing the same value multiple times produces the same output.
14
+ * Uuid Generator
16
15
  */
17
- uuid(): string;
16
+ uuid: UuidGenerator;
18
17
 
19
18
  /**
20
19
  * Update an item
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Model UUID Generator
3
+ */
4
+ export type ModelUuidGenerator = (() => string) & { valid: (id: string) => boolean };
@@ -1,7 +0,0 @@
1
- import { Util } from '@travetto/base';
2
-
3
- export class ModelUtil {
4
- static uuid(len: number = 32): string {
5
- return Util.uuid(len);
6
- }
7
- }