@travetto/model 6.0.0-rc.0 → 6.0.0-rc.2

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 (38) hide show
  1. package/README.md +23 -21
  2. package/__index__.ts +23 -15
  3. package/package.json +7 -7
  4. package/src/error/invalid-index.ts +2 -2
  5. package/src/registry/decorator.ts +3 -3
  6. package/src/registry/model.ts +5 -6
  7. package/src/registry/types.ts +1 -1
  8. package/src/{service → types}/basic.ts +8 -3
  9. package/src/{service → types}/blob.ts +1 -1
  10. package/src/{service → types}/bulk.ts +3 -3
  11. package/src/{service → types}/crud.ts +3 -8
  12. package/src/{service → types}/expiry.ts +3 -4
  13. package/src/{service → types}/indexed.ts +3 -4
  14. package/src/types/model.ts +1 -0
  15. package/src/{service → types}/storage.ts +6 -2
  16. package/src/{internal/service → util}/blob.ts +8 -6
  17. package/src/{internal/service → util}/bulk.ts +10 -4
  18. package/src/{internal/service → util}/crud.ts +13 -7
  19. package/src/{internal/service → util}/expiry.ts +9 -4
  20. package/src/{internal/service → util}/indexed.ts +13 -8
  21. package/src/{internal/service → util}/storage.ts +10 -4
  22. package/support/base-command.ts +2 -2
  23. package/support/bin/candidate.ts +7 -8
  24. package/support/bin/export.ts +1 -2
  25. package/support/bin/install.ts +1 -2
  26. package/support/cli.model_export.ts +3 -3
  27. package/support/cli.model_install.ts +3 -3
  28. package/support/doc.support.tsx +23 -11
  29. package/support/test/base.ts +9 -8
  30. package/support/test/basic.ts +1 -1
  31. package/support/test/blob.ts +7 -6
  32. package/support/test/bulk.ts +15 -15
  33. package/support/test/crud.ts +9 -9
  34. package/support/test/expiry.ts +19 -19
  35. package/support/test/indexed.ts +5 -5
  36. package/support/test/polymorphism.ts +9 -9
  37. package/support/test/suite.ts +9 -8
  38. package/src/internal/service/common.ts +0 -51
package/README.md CHANGED
@@ -16,14 +16,20 @@ yarn add @travetto/model
16
16
  This module provides a set of contracts/interfaces to data model persistence, modification and retrieval. This module builds heavily upon the [Schema](https://github.com/travetto/travetto/tree/main/module/schema#readme "Data type registry for runtime validation, reflection and binding."), which is used for data model validation.
17
17
 
18
18
  ## Contracts
19
- The module is mainly composed of contracts. The contracts define the expected interface for various model patterns. The primary contracts are [Basic](https://github.com/travetto/travetto/tree/main/module/model/src/service/basic.ts#L9), [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/service/crud.ts#L11), [Indexed](https://github.com/travetto/travetto/tree/main/module/model/src/service/indexed.ts#L12), [Expiry](https://github.com/travetto/travetto/tree/main/module/model/src/service/expiry.ts#L11), [Blob](https://github.com/travetto/travetto/tree/main/module/model/src/service/blob.ts#L8) and [Bulk](https://github.com/travetto/travetto/tree/main/module/model/src/service/bulk.ts#L19).
19
+ The module is mainly composed of contracts. The contracts define the expected interface for various model patterns. The primary contracts are [Basic](https://github.com/travetto/travetto/tree/main/module/model/src/types/basic.ts#L8), [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/types/crud.ts#L11), [Indexed](https://github.com/travetto/travetto/tree/main/module/model/src/types/indexed.ts#L11), [Expiry](https://github.com/travetto/travetto/tree/main/module/model/src/types/expiry.ts#L10), [Blob](https://github.com/travetto/travetto/tree/main/module/model/src/types/blob.ts#L8) and [Bulk](https://github.com/travetto/travetto/tree/main/module/model/src/types/bulk.ts#L64).
20
20
 
21
21
  ### Basic
22
- All [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations.") implementations, must honor the [Basic](https://github.com/travetto/travetto/tree/main/module/model/src/service/basic.ts#L9) contract to be able to participate in the model ecosystem. This contract represents the bare minimum for a model service.
22
+ All [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations.") implementations, must honor the [Basic](https://github.com/travetto/travetto/tree/main/module/model/src/types/basic.ts#L8) contract to be able to participate in the model ecosystem. This contract represents the bare minimum for a model service.
23
23
 
24
24
  **Code: Basic Contract**
25
25
  ```typescript
26
26
  export interface ModelBasicSupport<C = unknown> {
27
+
28
+ /**
29
+ * Id Source
30
+ */
31
+ idSource: ModelIdSource;
32
+
27
33
  /**
28
34
  * Get underlying client
29
35
  */
@@ -53,17 +59,12 @@ export interface ModelBasicSupport<C = unknown> {
53
59
  ```
54
60
 
55
61
  ### CRUD
56
- The [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/service/crud.ts#L11) contract, builds upon the basic contract, and is built around the idea of simple data retrieval and storage, to create a foundation for other services that need only basic support. The model extension in [Authentication](https://github.com/travetto/travetto/tree/main/module/auth#readme "Authentication scaffolding for the Travetto framework"), is an example of a module that only needs create, read and delete, and so any implementation of [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations.") that honors this contract, can be used with the [Authentication](https://github.com/travetto/travetto/tree/main/module/auth#readme "Authentication scaffolding for the Travetto framework") model extension.
62
+ The [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/types/crud.ts#L11) contract, builds upon the basic contract, and is built around the idea of simple data retrieval and storage, to create a foundation for other services that need only basic support. The model extension in [Authentication](https://github.com/travetto/travetto/tree/main/module/auth#readme "Authentication scaffolding for the Travetto framework"), is an example of a module that only needs create, read and delete, and so any implementation of [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations.") that honors this contract, can be used with the [Authentication](https://github.com/travetto/travetto/tree/main/module/auth#readme "Authentication scaffolding for the Travetto framework") model extension.
57
63
 
58
64
  **Code: Crud Contract**
59
65
  ```typescript
60
66
  export interface ModelCrudSupport extends ModelBasicSupport {
61
67
 
62
- /**
63
- * Id Source
64
- */
65
- idSource: ModelIdSource;
66
-
67
68
  /**
68
69
  * Update an item
69
70
  * @param item The document to update.
@@ -99,7 +100,7 @@ export interface ModelCrudSupport extends ModelBasicSupport {
99
100
  ```
100
101
 
101
102
  ### Indexed
102
- Additionally, an implementation may support the ability for basic [Indexed](https://github.com/travetto/travetto/tree/main/module/model/src/service/indexed.ts#L12) queries. This is not the full featured query support of [Data Model Querying](https://github.com/travetto/travetto/tree/main/module/model-query#readme "Datastore abstraction for advanced query support."), but allowing for indexed lookups. This does not support listing by index, but may be added at a later date.
103
+ Additionally, an implementation may support the ability for basic [Indexed](https://github.com/travetto/travetto/tree/main/module/model/src/types/indexed.ts#L11) queries. This is not the full featured query support of [Data Model Querying](https://github.com/travetto/travetto/tree/main/module/model-query#readme "Datastore abstraction for advanced query support."), but allowing for indexed lookups. This does not support listing by index, but may be added at a later date.
103
104
 
104
105
  **Code: Indexed Contract**
105
106
  ```typescript
@@ -139,7 +140,7 @@ export interface ModelIndexedSupport extends ModelBasicSupport {
139
140
  ```
140
141
 
141
142
  ### Expiry
142
- Certain implementations will also provide support for automatic [Expiry](https://github.com/travetto/travetto/tree/main/module/model/src/service/expiry.ts#L11) of data at runtime. This is extremely useful for temporary data as, and is used in the [Caching](https://github.com/travetto/travetto/tree/main/module/cache#readme "Caching functionality with decorators for declarative use.") module for expiring data accordingly.
143
+ Certain implementations will also provide support for automatic [Expiry](https://github.com/travetto/travetto/tree/main/module/model/src/types/expiry.ts#L10) of data at runtime. This is extremely useful for temporary data as, and is used in the [Caching](https://github.com/travetto/travetto/tree/main/module/cache#readme "Caching functionality with decorators for declarative use.") module for expiring data accordingly.
143
144
 
144
145
  **Code: Expiry Contract**
145
146
  ```typescript
@@ -154,7 +155,7 @@ export interface ModelExpirySupport extends ModelCrudSupport {
154
155
  ```
155
156
 
156
157
  ### Blob
157
- Some implementations also allow for the ability to read/write binary data as [Blob](https://github.com/travetto/travetto/tree/main/module/model/src/service/blob.ts#L8). Given that all implementations can store [Base64](https://en.wikipedia.org/wiki/Base64) encoded data, the key differentiator here, is native support for streaming data, as well as being able to store binary data of significant sizes.
158
+ Some implementations also allow for the ability to read/write binary data as [Blob](https://github.com/travetto/travetto/tree/main/module/model/src/types/blob.ts#L8). Given that all implementations can store [Base64](https://en.wikipedia.org/wiki/Base64) encoded data, the key differentiator here, is native support for streaming data, as well as being able to store binary data of significant sizes.
158
159
 
159
160
  **Code: Blob Contract**
160
161
  ```typescript
@@ -213,7 +214,7 @@ export interface ModelBlobSupport {
213
214
  ```
214
215
 
215
216
  ### Bulk
216
- Finally, there is support for [Bulk](https://github.com/travetto/travetto/tree/main/module/model/src/service/bulk.ts#L19) operations. This is not to simply imply issuing many commands at in parallel, but implementation support for an atomic/bulk operation. This should allow for higher throughput on data ingest, and potentially for atomic support on transactions.
217
+ Finally, there is support for [Bulk](https://github.com/travetto/travetto/tree/main/module/model/src/types/bulk.ts#L64) operations. This is not to simply imply issuing many commands at in parallel, but implementation support for an atomic/bulk operation. This should allow for higher throughput on data ingest, and potentially for atomic support on transactions.
217
218
 
218
219
  **Code: Bulk Contract**
219
220
  ```typescript
@@ -223,7 +224,7 @@ export interface ModelBulkSupport extends ModelCrudSupport {
223
224
  ```
224
225
 
225
226
  ## Declaration
226
- Models are declared via the [@Model](https://github.com/travetto/travetto/tree/main/module/model/src/registry/decorator.ts#L13) decorator, which allows the system to know that this is a class that is compatible with the module. The only requirement for a model is the [ModelType](https://github.com/travetto/travetto/tree/main/module/model/src/types/model.ts#L9)
227
+ Models are declared via the [@Model](https://github.com/travetto/travetto/tree/main/module/model/src/registry/decorator.ts#L13) decorator, which allows the system to know that this is a class that is compatible with the module. The only requirement for a model is the [ModelType](https://github.com/travetto/travetto/tree/main/module/model/src/types/model.ts#L10)
227
228
 
228
229
  **Code: ModelType**
229
230
  ```typescript
@@ -262,9 +263,10 @@ To enforce that these contracts are honored, the module provides shared test sui
262
263
  import { DependencyRegistry } from '@travetto/di';
263
264
  import { AppError, castTo, Class, classConstruct } from '@travetto/runtime';
264
265
 
265
- import { isBulkSupported, isCrudSupported } from '../../src/internal/service/common';
266
- import { ModelType } from '../../src/types/model';
267
- import { ModelSuite } from './suite';
266
+ import { ModelBulkUtil } from '../../src/util/bulk.ts';
267
+ import { ModelCrudUtil } from '../../src/util/crud.ts';
268
+ import { ModelType } from '../../src/types/model.ts';
269
+ import { ModelSuite } from './suite.ts';
268
270
 
269
271
  type ServiceClass = { serviceClass: { new(): unknown } };
270
272
 
@@ -280,7 +282,7 @@ export abstract class BaseModelSuite<T> {
280
282
 
281
283
  async getSize<U extends ModelType>(cls: Class<U>): Promise<number> {
282
284
  const svc = (await this.service);
283
- if (isCrudSupported(svc)) {
285
+ if (ModelCrudUtil.isSupported(svc)) {
284
286
  let i = 0;
285
287
  for await (const __el of svc.list(cls)) {
286
288
  i += 1;
@@ -293,10 +295,10 @@ export abstract class BaseModelSuite<T> {
293
295
 
294
296
  async saveAll<M extends ModelType>(cls: Class<M>, items: M[]): Promise<number> {
295
297
  const svc = await this.service;
296
- if (isBulkSupported(svc)) {
297
- const res = await svc.processBulk(cls, items.map(x => ({ insert: x })));
298
- return res.counts.insert;
299
- } else if (isCrudSupported(svc)) {
298
+ if (ModelBulkUtil.isSupported(svc)) {
299
+ const result = await svc.processBulk(cls, items.map(x => ({ insert: x })));
300
+ return result.counts.insert;
301
+ } else if (ModelCrudUtil.isSupported(svc)) {
300
302
  const out: Promise<M>[] = [];
301
303
  for (const el of items) {
302
304
  out.push(svc.create(cls, el));
package/__index__.ts CHANGED
@@ -1,16 +1,24 @@
1
- export * from './src/registry/decorator';
2
- export * from './src/registry/model';
3
- export * from './src/registry/types';
4
- export * from './src/types/model';
5
- export * from './src/service/basic';
6
- export * from './src/service/blob';
7
- export * from './src/service/bulk';
8
- export * from './src/service/crud';
9
- export * from './src/service/indexed';
10
- export * from './src/service/expiry';
11
- export * from './src/service/storage';
1
+ export * from './src/registry/decorator.ts';
2
+ export * from './src/registry/model.ts';
3
+ export * from './src/registry/types.ts';
4
+ export * from './src/types/model.ts';
12
5
 
13
- export * from './src/error/exists';
14
- export * from './src/error/not-found';
15
- export * from './src/error/invalid-index';
16
- export * from './src/error/invalid-sub-type';
6
+ export * from './src/types/basic.ts';
7
+ export * from './src/types/blob.ts';
8
+ export * from './src/types/bulk.ts';
9
+ export * from './src/types/crud.ts';
10
+ export * from './src/types/indexed.ts';
11
+ export * from './src/types/expiry.ts';
12
+ export * from './src/types/storage.ts';
13
+
14
+ export * from './src/util/blob.ts';
15
+ export * from './src/util/bulk.ts';
16
+ export * from './src/util/crud.ts';
17
+ export * from './src/util/expiry.ts';
18
+ export * from './src/util/indexed.ts';
19
+ export * from './src/util/storage.ts';
20
+
21
+ export * from './src/error/exists.ts';
22
+ export * from './src/error/not-found.ts';
23
+ export * from './src/error/invalid-index.ts';
24
+ export * from './src/error/invalid-sub-type.ts';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/model",
3
- "version": "6.0.0-rc.0",
3
+ "version": "6.0.0-rc.2",
4
4
  "description": "Datastore abstraction for core operations.",
5
5
  "keywords": [
6
6
  "datastore",
@@ -26,14 +26,14 @@
26
26
  "directory": "module/model"
27
27
  },
28
28
  "dependencies": {
29
- "@travetto/config": "^6.0.0-rc.0",
30
- "@travetto/di": "^6.0.0-rc.0",
31
- "@travetto/registry": "^6.0.0-rc.0",
32
- "@travetto/schema": "^6.0.0-rc.0"
29
+ "@travetto/config": "^6.0.0-rc.2",
30
+ "@travetto/di": "^6.0.0-rc.2",
31
+ "@travetto/registry": "^6.0.0-rc.2",
32
+ "@travetto/schema": "^6.0.0-rc.2"
33
33
  },
34
34
  "peerDependencies": {
35
- "@travetto/cli": "^6.0.0-rc.0",
36
- "@travetto/test": "^6.0.0-rc.0"
35
+ "@travetto/cli": "^6.0.0-rc.2",
36
+ "@travetto/test": "^6.0.0-rc.2"
37
37
  },
38
38
  "peerDependenciesMeta": {
39
39
  "@travetto/cli": {
@@ -1,7 +1,7 @@
1
1
  import { Class, AppError } from '@travetto/runtime';
2
2
 
3
- import { IndexConfig } from '../registry/types';
4
- import { ModelType } from '../types/model';
3
+ import { IndexConfig } from '../registry/types.ts';
4
+ import { ModelType } from '../types/model.ts';
5
5
 
6
6
  /**
7
7
  * Represents when an index is invalid
@@ -1,9 +1,9 @@
1
1
  import { AppError, asConstructable, castTo, Class } from '@travetto/runtime';
2
2
  import { SchemaRegistry } from '@travetto/schema';
3
3
 
4
- import { ModelType } from '../types/model';
5
- import { ModelRegistry } from './model';
6
- import { DataHandler, IndexConfig, ModelOptions, PrePersistScope } from './types';
4
+ import { ModelType } from '../types/model.ts';
5
+ import { ModelRegistry } from './model.ts';
6
+ import { DataHandler, IndexConfig, ModelOptions, PrePersistScope } from './types.ts';
7
7
 
8
8
  /**
9
9
  * Model decorator, extends `@Schema`
@@ -2,12 +2,11 @@ import { SchemaRegistry } from '@travetto/schema';
2
2
  import { MetadataRegistry } from '@travetto/registry';
3
3
  import { DependencyRegistry } from '@travetto/di';
4
4
  import { AppError, castTo, Class, describeFunction, asFull } from '@travetto/runtime';
5
- import { AllViewSymbol } from '@travetto/schema/src/internal/types';
6
5
 
7
- import { IndexConfig, IndexType, ModelOptions } from './types';
8
- import { NotFoundError } from '../error/not-found';
9
- import { ModelType } from '../types/model';
10
- import { IndexNotSupported } from '../error/invalid-index';
6
+ import { IndexConfig, IndexType, ModelOptions } from './types.ts';
7
+ import { NotFoundError } from '../error/not-found.ts';
8
+ import { ModelType } from '../types/model.ts';
9
+ import { IndexNotSupported } from '../error/invalid-index.ts';
11
10
 
12
11
  /**
13
12
  * Registry for all models, built on the Metadata registry
@@ -74,7 +73,7 @@ class $ModelRegistry extends MetadataRegistry<ModelOptions<ModelType>> {
74
73
  const config = asFull(this.pending.get(cls.Ⲑid)!);
75
74
 
76
75
  const schema = SchemaRegistry.get(cls);
77
- const view = schema.views[AllViewSymbol].schema;
76
+ const view = schema.totalView.schema;
78
77
  delete view.id.required; // Allow ids to be optional
79
78
 
80
79
  if (schema.subTypeField in view && this.getBaseModel(cls) !== cls) {
@@ -1,6 +1,6 @@
1
1
  import type { Class, Primitive } from '@travetto/runtime';
2
2
 
3
- import { ModelType } from '../types/model';
3
+ import { ModelType } from '../types/model.ts';
4
4
 
5
5
  type ValidFieldNames<T> = {
6
6
  [K in keyof T]:
@@ -1,12 +1,17 @@
1
1
  import { Class } from '@travetto/runtime';
2
- import { ModelType, OptionalId } from '../types/model';
2
+ import { ModelIdSource, ModelType, OptionalId } from '../types/model.ts';
3
3
 
4
4
  /**
5
5
  * Interface for basic data interface
6
- *
7
- * @concrete ../internal/service/common#ModelBasicSupportTarget
6
+ * @concrete
8
7
  */
9
8
  export interface ModelBasicSupport<C = unknown> {
9
+
10
+ /**
11
+ * Id Source
12
+ */
13
+ idSource: ModelIdSource;
14
+
10
15
  /**
11
16
  * Get underlying client
12
17
  */
@@ -3,7 +3,7 @@ import { BinaryInput, BlobMeta, ByteRange, TimeSpan } from '@travetto/runtime';
3
3
  /**
4
4
  * Support for Blobs CRUD.
5
5
  *
6
- * @concrete ../internal/service/common#ModelBlobSupportTarget
6
+ * @concrete
7
7
  */
8
8
  export interface ModelBlobSupport {
9
9
 
@@ -1,8 +1,8 @@
1
1
  import { Class, AppError } from '@travetto/runtime';
2
2
  import { ValidationError, ValidationResultError } from '@travetto/schema';
3
3
 
4
- import { ModelCrudSupport } from './crud';
5
- import { ModelType, OptionalId } from '../types/model';
4
+ import { ModelCrudSupport } from './crud.ts';
5
+ import { ModelType, OptionalId } from '../types/model.ts';
6
6
 
7
7
  /**
8
8
  * Bulk operation. Each operation has a single action and payload
@@ -59,7 +59,7 @@ export class BulkProcessError extends AppError<{ errors: BulkErrorItem[] }> {
59
59
  /**
60
60
  * Determines if model allows for bulk operations
61
61
  *
62
- * @concrete ../internal/service/common#ModelBulkSupportTarget
62
+ * @concrete
63
63
  */
64
64
  export interface ModelBulkSupport extends ModelCrudSupport {
65
65
  processBulk<T extends ModelType>(cls: Class<T>, operations: BulkOp<T>[]): Promise<BulkResponse>;
@@ -1,20 +1,15 @@
1
1
  import { Class } from '@travetto/runtime';
2
2
 
3
- import { ModelType, OptionalId, ModelIdSource } from '../types/model';
3
+ import { ModelType, OptionalId } from '../types/model.ts';
4
4
 
5
- import { ModelBasicSupport } from './basic';
5
+ import { ModelBasicSupport } from './basic.ts';
6
6
 
7
7
  /**
8
8
  * Interface for simple CRUD
9
- * @concrete ../internal/service/common#ModelCrudSupportTarget
9
+ * @concrete
10
10
  */
11
11
  export interface ModelCrudSupport extends ModelBasicSupport {
12
12
 
13
- /**
14
- * Id Source
15
- */
16
- idSource: ModelIdSource;
17
-
18
13
  /**
19
14
  * Update an item
20
15
  * @param item The document to update.
@@ -1,12 +1,11 @@
1
1
  import { Class } from '@travetto/runtime';
2
2
 
3
- import { ModelType } from '../types/model';
4
- import { ModelCrudSupport } from './crud';
3
+ import { ModelType } from '../types/model.ts';
4
+ import { ModelCrudSupport } from './crud.ts';
5
5
 
6
6
  /**
7
7
  * Support for managing expiration of data
8
- *
9
- * @concrete ../internal/service/common#ModelExpirySupportTarget
8
+ * @concrete
10
9
  */
11
10
  export interface ModelExpirySupport extends ModelCrudSupport {
12
11
  /**
@@ -1,13 +1,12 @@
1
1
  import { Class, DeepPartial } from '@travetto/runtime';
2
2
 
3
- import { ModelType, OptionalId } from '../types/model';
4
- import { ModelBasicSupport } from './basic';
3
+ import { ModelType, OptionalId } from '../types/model.ts';
4
+ import { ModelBasicSupport } from './basic.ts';
5
5
 
6
6
  /**
7
7
  * Support for simple indexed activity
8
8
  *
9
- *
10
- * @concrete ../internal/service/common#ModelIndexedSupportTarget
9
+ * @concrete
11
10
  */
12
11
  export interface ModelIndexedSupport extends ModelBasicSupport {
13
12
  /**
@@ -5,6 +5,7 @@ export type ModelIdSource = { create: () => string, valid: (id: string) => boole
5
5
 
6
6
  /**
7
7
  * Simple model interface
8
+ * @concrete
8
9
  */
9
10
  export interface ModelType {
10
11
  /**
@@ -1,7 +1,7 @@
1
1
  import { Class } from '@travetto/runtime';
2
2
  import { SchemaChange } from '@travetto/schema';
3
3
 
4
- import { ModelType } from '../types/model';
4
+ import { ModelType } from '../types/model.ts';
5
5
 
6
6
  /**
7
7
  * This interface defines the behavior for dealing with the
@@ -10,7 +10,7 @@ import { ModelType } from '../types/model';
10
10
  *
11
11
  * This is intended to be used during development only for rapid prototyping.
12
12
  *
13
- * @concrete ../internal/service/common#ModelStorageSupportTarget
13
+ * @concrete
14
14
  */
15
15
  export interface ModelStorageSupport {
16
16
 
@@ -53,4 +53,8 @@ export interface ModelStorageSupport {
53
53
  * An event listener for whenever a model schema is changed
54
54
  */
55
55
  changeSchema?(cls: Class, changes: SchemaChange): Promise<void>;
56
+ /**
57
+ * Truncate blob storage data
58
+ */
59
+ truncateBlob?(): Promise<void>;
56
60
  }
@@ -1,15 +1,17 @@
1
1
  import { Readable } from 'node:stream';
2
- import { Class, AppError, BinaryInput, BinaryUtil, BlobMeta, ByteRange } from '@travetto/runtime';
3
- import { ModelType } from '../../types/model';
4
-
5
- export const ModelBlobNamespace = '__blobs';
6
- export const MODEL_BLOB: Class<ModelType> = class { id: string; };
2
+ import { AppError, BinaryInput, BinaryUtil, BlobMeta, ByteRange, hasFunction } from '@travetto/runtime';
3
+ import { ModelBlobSupport } from '../types/blob.ts';
7
4
 
8
5
  /**
9
- * Utilities for processing assets
6
+ * Utilities for processing blobs
10
7
  */
11
8
  export class ModelBlobUtil {
12
9
 
10
+ /**
11
+ * Type guard for determining if service supports blob operations
12
+ */
13
+ static isSupported = hasFunction<ModelBlobSupport>('getBlob');
14
+
13
15
  /**
14
16
  * Convert input to a Readable, and get what metadata is available
15
17
  */
@@ -1,8 +1,8 @@
1
- import { Class } from '@travetto/runtime';
1
+ import { Class, hasFunction } from '@travetto/runtime';
2
2
 
3
- import { BulkOp } from '../../service/bulk';
4
- import { ModelType } from '../../types/model';
5
- import { ModelCrudProvider, ModelCrudUtil } from './crud';
3
+ import { BulkOp, ModelBulkSupport } from '../types/bulk.ts';
4
+ import { ModelType } from '../types/model.ts';
5
+ import { ModelCrudProvider, ModelCrudUtil } from './crud.ts';
6
6
 
7
7
  export type BulkPreStore<T extends ModelType> = {
8
8
  insertedIds: Map<number, string>;
@@ -13,6 +13,12 @@ export type BulkPreStore<T extends ModelType> = {
13
13
  };
14
14
 
15
15
  export class ModelBulkUtil {
16
+
17
+ /**
18
+ * Type guard for determining if service supports bulk operation
19
+ */
20
+ static isSupported = hasFunction<ModelBulkSupport>('processBulk');
21
+
16
22
  /**
17
23
  * Prepares bulk ops for storage
18
24
  * @param cls
@@ -1,12 +1,13 @@
1
- import { castTo, Class, Util, asConstructable, AppError } from '@travetto/runtime';
1
+ import { castTo, Class, Util, asConstructable, AppError, hasFunction } from '@travetto/runtime';
2
2
  import { DataUtil, SchemaRegistry, SchemaValidator, ValidationError, ValidationResultError } from '@travetto/schema';
3
3
 
4
- import { ModelRegistry } from '../../registry/model';
5
- import { ModelIdSource, ModelType, OptionalId } from '../../types/model';
6
- import { NotFoundError } from '../../error/not-found';
7
- import { ExistsError } from '../../error/exists';
8
- import { SubTypeNotSupportedError } from '../../error/invalid-sub-type';
9
- import { DataHandler, PrePersistScope } from '../../registry/types';
4
+ import { ModelRegistry } from '../registry/model.ts';
5
+ import { ModelIdSource, ModelType, OptionalId } from '../types/model.ts';
6
+ import { NotFoundError } from '../error/not-found.ts';
7
+ import { ExistsError } from '../error/exists.ts';
8
+ import { SubTypeNotSupportedError } from '../error/invalid-sub-type.ts';
9
+ import { DataHandler, PrePersistScope } from '../registry/types.ts';
10
+ import { ModelCrudSupport } from '../types/crud.ts';
10
11
 
11
12
  export type ModelCrudProvider = {
12
13
  idSource: ModelIdSource;
@@ -17,6 +18,11 @@ export type ModelCrudProvider = {
17
18
  */
18
19
  export class ModelCrudUtil {
19
20
 
21
+ /**
22
+ * Type guard for determining if service supports crud operations
23
+ */
24
+ static isSupported = hasFunction<ModelCrudSupport>('upsert');
25
+
20
26
  /**
21
27
  * Build a uuid generator
22
28
  */
@@ -1,14 +1,19 @@
1
- import { ShutdownManager, Class, TimeSpan, TimeUtil, Util, castTo } from '@travetto/runtime';
1
+ import { ShutdownManager, Class, TimeSpan, TimeUtil, Util, castTo, hasFunction } from '@travetto/runtime';
2
2
 
3
- import { ModelRegistry } from '../../registry/model';
4
- import { ModelExpirySupport } from '../../service/expiry';
5
- import { ModelType } from '../../types/model';
3
+ import { ModelRegistry } from '../registry/model.ts';
4
+ import { ModelExpirySupport } from '../types/expiry.ts';
5
+ import { ModelType } from '../types/model.ts';
6
6
 
7
7
  /**
8
8
  * Utils for model expiry
9
9
  */
10
10
  export class ModelExpiryUtil {
11
11
 
12
+ /**
13
+ * Type guard for determining if model supports expiry
14
+ */
15
+ static isSupported = hasFunction<ModelExpirySupport>('deleteExpired');
16
+
12
17
  /**
13
18
  * Get expiry info for a given item
14
19
  */
@@ -1,12 +1,12 @@
1
- import { castTo, Class, DeepPartial, TypedObject } from '@travetto/runtime';
1
+ import { castTo, Class, DeepPartial, hasFunction, TypedObject } from '@travetto/runtime';
2
2
 
3
- import { IndexNotSupported } from '../../error/invalid-index';
4
- import { NotFoundError } from '../../error/not-found';
5
- import { ModelRegistry } from '../../registry/model';
6
- import { IndexConfig } from '../../registry/types';
7
- import { ModelCrudSupport } from '../../service/crud';
8
- import { ModelIndexedSupport } from '../../service/indexed';
9
- import { ModelType, OptionalId } from '../../types/model';
3
+ import { IndexNotSupported } from '../error/invalid-index.ts';
4
+ import { NotFoundError } from '../error/not-found.ts';
5
+ import { ModelRegistry } from '../registry/model.ts';
6
+ import type { IndexConfig } from '../registry/types.ts';
7
+ import type { ModelCrudSupport } from '../types/crud.ts';
8
+ import type { ModelIndexedSupport } from '../types/indexed.ts';
9
+ import type { ModelType, OptionalId } from '../types/model.ts';
10
10
 
11
11
  type ComputeConfig = {
12
12
  includeSortInFields?: boolean;
@@ -24,6 +24,11 @@ const DEFAULT_SEP = '\u8203';
24
24
  */
25
25
  export class ModelIndexedUtil {
26
26
 
27
+ /**
28
+ * Type guard for determining if service supports indexed operation
29
+ */
30
+ static isSupported = hasFunction<ModelIndexedSupport>('getByIndex');
31
+
27
32
  /**
28
33
  * Compute flattened field to value mappings
29
34
  * @param cls Class to get info for
@@ -1,14 +1,20 @@
1
- import { Class, Runtime } from '@travetto/runtime';
1
+ import { Class, hasFunction, Runtime } from '@travetto/runtime';
2
2
  import { SchemaChangeListener } from '@travetto/schema';
3
3
 
4
- import { ModelRegistry } from '../../registry/model';
5
- import { ModelStorageSupport } from '../../service/storage';
6
- import { ModelType } from '../../types/model';
4
+ import { ModelRegistry } from '../registry/model.ts';
5
+ import { ModelStorageSupport } from '../types/storage.ts';
6
+ import { ModelType } from '../types/model.ts';
7
7
 
8
8
  /**
9
9
  * Model storage util
10
10
  */
11
11
  export class ModelStorageUtil {
12
+
13
+ /**
14
+ * Type guard for determining if service supports storage operation
15
+ */
16
+ static isSupported = hasFunction<ModelStorageSupport>('createStorage');
17
+
12
18
  /**
13
19
  * Register change listener on startup
14
20
  */
@@ -2,9 +2,9 @@ import { Env } from '@travetto/runtime';
2
2
  import { CliValidationError, CliCommandShape, cliTpl } from '@travetto/cli';
3
3
  import { RootRegistry } from '@travetto/registry';
4
4
 
5
- import type { ModelStorageSupport } from '../src/service/storage';
5
+ import type { ModelStorageSupport } from '../src/service/storage.ts';
6
6
 
7
- import { ModelCandidateUtil } from './bin/candidate';
7
+ import { ModelCandidateUtil } from './bin/candidate.ts';
8
8
 
9
9
  /**
10
10
  * CLI Entry point for exporting model schemas
@@ -1,10 +1,9 @@
1
- import { castTo, Class } from '@travetto/runtime';
2
- import { ModelRegistry } from '@travetto/model/src/registry/model';
1
+ import { toConcrete, Class } from '@travetto/runtime';
3
2
  import { InjectableConfig, DependencyRegistry } from '@travetto/di';
4
- import { ModelStorageSupportTarget } from '@travetto/model/src/internal/service/common';
5
3
 
6
- import type { ModelStorageSupport } from '../../src/service/storage';
7
- import type { ModelType } from '../../src/types/model';
4
+ import { ModelRegistry } from '../../src/registry/model.ts';
5
+ import type { ModelStorageSupport } from '../../src/types/storage.ts';
6
+ import type { ModelType } from '../../src/types/model.ts';
8
7
 
9
8
  /**
10
9
  * Utilities for finding candidates for model operations
@@ -33,14 +32,14 @@ export class ModelCandidateUtil {
33
32
  * Get model names
34
33
  */
35
34
  static async getModelNames(): Promise<string[]> {
36
- return (await this.#getModels()).map(x => ModelRegistry.getStore(x)).sort();
35
+ return (await this.#getModels()).map(x => ModelRegistry.getStore(x)).toSorted();
37
36
  }
38
37
 
39
38
  /**
40
39
  * Get all providers that are viable candidates
41
40
  */
42
41
  static async getProviders(op?: keyof ModelStorageSupport): Promise<InjectableConfig[]> {
43
- const types = DependencyRegistry.getCandidateTypes<ModelStorageSupport>(castTo(ModelStorageSupportTarget));
42
+ const types = DependencyRegistry.getCandidateTypes(toConcrete<ModelStorageSupport>());
44
43
  return types.filter(x => !op || x.class.prototype?.[op]);
45
44
  }
46
45
 
@@ -50,7 +49,7 @@ export class ModelCandidateUtil {
50
49
  static async getProviderNames(op?: keyof ModelStorageSupport): Promise<string[]> {
51
50
  return (await this.getProviders(op))
52
51
  .map(x => x.class.name.replace(/ModelService/, ''))
53
- .sort();
52
+ .toSorted();
54
53
  }
55
54
 
56
55
  /**
@@ -1,6 +1,5 @@
1
1
  import type { Class } from '@travetto/runtime';
2
- import type { ModelStorageSupport } from '@travetto/model/src/service/storage';
3
- import type { ModelType } from '@travetto/model/src/types/model';
2
+ import type { ModelStorageSupport, ModelType } from '@travetto/model';
4
3
 
5
4
  export class ModelExportUtil {
6
5
  static async run(provider: ModelStorageSupport, models: Class<ModelType>[]): Promise<void> {
@@ -1,6 +1,5 @@
1
1
  import type { Class } from '@travetto/runtime';
2
- import type { ModelStorageSupport } from '@travetto/model/src/service/storage';
3
- import type { ModelType } from '@travetto/model/src/types/model';
2
+ import type { ModelStorageSupport, ModelType } from '@travetto/model';
4
3
 
5
4
  export class ModelInstallUtil {
6
5
  static async run(provider: ModelStorageSupport, models: Class<ModelType>[]): Promise<void> {
@@ -1,8 +1,8 @@
1
1
  import { CliCommand } from '@travetto/cli';
2
2
 
3
- import { BaseModelCommand } from './base-command';
4
- import { ModelExportUtil } from './bin/export';
5
- import { ModelCandidateUtil } from './bin/candidate';
3
+ import { BaseModelCommand } from './base-command.ts';
4
+ import { ModelExportUtil } from './bin/export.ts';
5
+ import { ModelCandidateUtil } from './bin/candidate.ts';
6
6
 
7
7
  /**
8
8
  * Exports model schemas
@@ -1,8 +1,8 @@
1
1
  import { CliCommand, cliTpl } from '@travetto/cli';
2
2
 
3
- import { BaseModelCommand } from './base-command';
4
- import { ModelInstallUtil } from './bin/install';
5
- import { ModelCandidateUtil } from './bin/candidate';
3
+ import { BaseModelCommand } from './base-command.ts';
4
+ import { ModelInstallUtil } from './bin/install.ts';
5
+ import { ModelCandidateUtil } from './bin/candidate.ts';
6
6
 
7
7
  /**
8
8
  * Installing models
@@ -1,25 +1,37 @@
1
1
  /** @jsxImportSource @travetto/doc */
2
2
  import { d, c, DocJSXElementByFn, DocJSXElement, DocFileUtil } from '@travetto/doc';
3
3
  import { Config } from '@travetto/config';
4
+ import { Runtime, toConcrete } from '@travetto/runtime';
5
+
6
+ import { ModelBasicSupport } from '../src/types/basic.ts';
7
+ import { ModelBlobSupport } from '../src/types/blob.ts';
8
+ import { ModelBulkSupport } from '../src/types/bulk.ts';
9
+ import { ModelCrudSupport } from '../src/types/crud.ts';
10
+ import { ModelExpirySupport } from '../src/types/expiry.ts';
11
+ import { ModelIndexedSupport } from '../src/types/indexed.ts';
12
+
13
+ const toLink = (title: string, target: Function): DocJSXElementByFn<'CodeLink'> =>
14
+ d.codeLink(title, Runtime.getSourceFile(target), new RegExp(`\\binterface\\s+${target.name}`));
4
15
 
5
16
  export const Links = {
6
- Basic: d.codeLink('Basic', '@travetto/model/src/service/basic.ts', /export interface/),
7
- Crud: d.codeLink('CRUD', '@travetto/model/src/service/crud.ts', /export interface/),
8
- Expiry: d.codeLink('Expiry', '@travetto/model/src/service/expiry.ts', /export interface/),
9
- Indexed: d.codeLink('Indexed', '@travetto/model/src/service/indexed.ts', /export interface/),
10
- Bulk: d.codeLink('Bulk', '@travetto/model/src/service/bulk.ts', /export interface/),
11
- Blob: d.codeLink('Blob', '@travetto/model/src/service/blob.ts', /export interface/),
17
+ Basic: toLink('Basic', toConcrete<ModelBasicSupport>()),
18
+ Crud: toLink('CRUD', toConcrete<ModelCrudSupport>()),
19
+ Expiry: toLink('Expiry', toConcrete<ModelExpirySupport>()),
20
+ Indexed: toLink('Indexed', toConcrete<ModelIndexedSupport>()),
21
+ Bulk: toLink('Bulk', toConcrete<ModelBulkSupport>()),
22
+ Blob: toLink('Blob', toConcrete<ModelBlobSupport>()),
12
23
  };
13
24
 
14
25
  export const ModelTypes = (fn: | Function): DocJSXElement[] => {
15
26
  const { content } = DocFileUtil.readSource(fn);
16
27
  const found: DocJSXElementByFn<'CodeLink'>[] = [];
17
- const seen = new Set();
18
- for (const [, key] of content.matchAll(/Model(Crud|Expiry|Indexed|Bulk|Blob)Support/g)) {
19
- if (!seen.has(key)) {
28
+ const seen = new Set<string>();
29
+ for (const [, key] of content.matchAll(/Model([A-Za-z]+)Support/g)) {
30
+ if (!seen.has(key) && key in Links) {
20
31
  seen.add(key);
21
32
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
22
- found.push(Links[key as keyof typeof Links]);
33
+ const link = Links[key as keyof typeof Links];
34
+ found.push(link);
23
35
  }
24
36
  }
25
37
  return found.map(v => <li>{v}</li>);
@@ -33,7 +45,7 @@ export const ModelCustomConfig = ({ cfg }: { cfg: Function }): DocJSXElement =>
33
45
 
34
46
  where the {cfg} is defined by:
35
47
 
36
- <c.Code title={`Structure of ${cfg.name}`} src={cfg} />
48
+ <c.Code title={`Structure of ${cfg.name}`} src={cfg} startRe={/@Config/} />
37
49
 
38
50
  Additionally, you can see that the class is registered with the {Config} annotation, and so these values can be overridden using the
39
51
  standard {d.mod('Config')}resolution paths.
@@ -1,9 +1,10 @@
1
1
  import { DependencyRegistry } from '@travetto/di';
2
2
  import { AppError, castTo, Class, classConstruct } from '@travetto/runtime';
3
3
 
4
- import { isBulkSupported, isCrudSupported } from '../../src/internal/service/common';
5
- import { ModelType } from '../../src/types/model';
6
- import { ModelSuite } from './suite';
4
+ import { ModelBulkUtil } from '../../src/util/bulk.ts';
5
+ import { ModelCrudUtil } from '../../src/util/crud.ts';
6
+ import { ModelType } from '../../src/types/model.ts';
7
+ import { ModelSuite } from './suite.ts';
7
8
 
8
9
  type ServiceClass = { serviceClass: { new(): unknown } };
9
10
 
@@ -19,7 +20,7 @@ export abstract class BaseModelSuite<T> {
19
20
 
20
21
  async getSize<U extends ModelType>(cls: Class<U>): Promise<number> {
21
22
  const svc = (await this.service);
22
- if (isCrudSupported(svc)) {
23
+ if (ModelCrudUtil.isSupported(svc)) {
23
24
  let i = 0;
24
25
  for await (const __el of svc.list(cls)) {
25
26
  i += 1;
@@ -32,10 +33,10 @@ export abstract class BaseModelSuite<T> {
32
33
 
33
34
  async saveAll<M extends ModelType>(cls: Class<M>, items: M[]): Promise<number> {
34
35
  const svc = await this.service;
35
- if (isBulkSupported(svc)) {
36
- const res = await svc.processBulk(cls, items.map(x => ({ insert: x })));
37
- return res.counts.insert;
38
- } else if (isCrudSupported(svc)) {
36
+ if (ModelBulkUtil.isSupported(svc)) {
37
+ const result = await svc.processBulk(cls, items.map(x => ({ insert: x })));
38
+ return result.counts.insert;
39
+ } else if (ModelCrudUtil.isSupported(svc)) {
39
40
  const out: Promise<M>[] = [];
40
41
  for (const el of items) {
41
42
  out.push(svc.create(cls, el));
@@ -3,7 +3,7 @@ import assert from 'node:assert';
3
3
  import { Suite, Test } from '@travetto/test';
4
4
  import { ModelCrudSupport, Model, NotFoundError } from '@travetto/model';
5
5
 
6
- import { BaseModelSuite } from './base';
6
+ import { BaseModelSuite } from './base.ts';
7
7
 
8
8
  @Model('basic_person')
9
9
  class Person {
@@ -1,11 +1,12 @@
1
1
  import assert from 'node:assert';
2
2
 
3
3
  import { Suite, Test, TestFixtures } from '@travetto/test';
4
- import { BaseModelSuite } from '@travetto/model/support/test/base';
5
4
  import { BinaryUtil, Util } from '@travetto/runtime';
6
5
 
7
- import { ModelBlobSupport } from '../../src/service/blob';
8
- import { ModelBlobUtil } from '../../src/internal/service/blob';
6
+ import { BaseModelSuite } from '@travetto/model/support/test/base.ts';
7
+
8
+ import { ModelBlobSupport } from '../../src/types/blob.ts';
9
+ import { ModelBlobUtil } from '../../src/util/blob.ts';
9
10
 
10
11
  const meta = BinaryUtil.getBlobMeta;
11
12
 
@@ -168,14 +169,14 @@ export abstract class ModelBlobSuite extends BaseModelSuite<ModelBlobSupport> {
168
169
  console.log(writable);
169
170
  assert(writable);
170
171
 
171
- const res = await fetch(writable, {
172
+ const response = await fetch(writable, {
172
173
  method: 'PUT',
173
174
  body: new File([buffer], 'gary', { type: 'image/jpeg' }),
174
175
  });
175
176
 
176
- console.error(await res.text());
177
+ console.error(await response.text());
177
178
 
178
- assert(res.ok);
179
+ assert(response.ok);
179
180
 
180
181
  await service.updateBlobMeta('largeFile/one', {
181
182
  contentType: 'image/jpeg',
@@ -2,9 +2,9 @@ import assert from 'node:assert';
2
2
 
3
3
  import { Suite, Test } from '@travetto/test';
4
4
 
5
- import { Model } from '../../src/registry/decorator';
6
- import { ModelBulkSupport } from '../../src/service/bulk';
7
- import { BaseModelSuite } from './base';
5
+ import { Model } from '../../src/registry/decorator.ts';
6
+ import { ModelBulkSupport } from '../../src/types/bulk.ts';
7
+ import { BaseModelSuite } from './base.ts';
8
8
 
9
9
  @Model('bulk-user')
10
10
  class User {
@@ -18,29 +18,29 @@ export abstract class ModelBulkSuite extends BaseModelSuite<ModelBulkSupport> {
18
18
  @Test()
19
19
  async bulkInsert() {
20
20
  const service = await this.service;
21
- const res = await service.processBulk(User, [
21
+ const result = await service.processBulk(User, [
22
22
  { insert: User.from({}) },
23
23
  { insert: User.from({}) },
24
24
  { insert: User.from({}) },
25
25
  { insert: User.from({}) }
26
26
  ]);
27
27
 
28
- assert(res.counts.insert === 4);
29
- assert(res.insertedIds.size === 4);
28
+ assert(result.counts.insert === 4);
29
+ assert(result.insertedIds.size === 4);
30
30
  }
31
31
 
32
32
  @Test()
33
33
  async bulkUpsert() {
34
34
  const service = await this.service;
35
- const res = await service.processBulk(User, [
35
+ const result = await service.processBulk(User, [
36
36
  { upsert: User.from({}) },
37
37
  { upsert: User.from({}) },
38
38
  { upsert: User.from({}) },
39
39
  { upsert: User.from({}) }
40
40
  ]);
41
41
 
42
- assert(res.counts.upsert === 4);
43
- assert(res.insertedIds.size === 4);
42
+ assert(result.counts.upsert === 4);
43
+ assert(result.insertedIds.size === 4);
44
44
  }
45
45
 
46
46
  @Test()
@@ -48,9 +48,9 @@ export abstract class ModelBulkSuite extends BaseModelSuite<ModelBulkSupport> {
48
48
  const service = await this.service;
49
49
  const users = [0, 1, 2, 4].map(x => User.from({ name: `name-${x}`, id: service.idSource.create() }));
50
50
 
51
- const res = await service.processBulk(User, users.map(u => ({ insert: u })));
52
- assert(res.counts.insert === 4);
53
- assert(res.insertedIds.size === 4);
51
+ const result = await service.processBulk(User, users.map(u => ({ insert: u })));
52
+ assert(result.counts.insert === 4);
53
+ assert(result.insertedIds.size === 4);
54
54
 
55
55
  const res2 = await service.processBulk(User, users.map(u => ({ update: u })));
56
56
  assert(res2.counts.update === 4);
@@ -62,9 +62,9 @@ export abstract class ModelBulkSuite extends BaseModelSuite<ModelBulkSupport> {
62
62
  const service = await this.service;
63
63
  const users = [0, 1, 2, 4].map(x => User.from({ name: `name-${x}`, id: service.idSource.create() }));
64
64
 
65
- const res = await service.processBulk(User, users.map(u => ({ insert: u })));
66
- assert(res.counts.insert === 4);
67
- assert(res.insertedIds.size === 4);
65
+ const result = await service.processBulk(User, users.map(u => ({ insert: u })));
66
+ assert(result.counts.insert === 4);
67
+ assert(result.insertedIds.size === 4);
68
68
 
69
69
  const res2 = await service.processBulk(User, users.map(u => ({ delete: u })));
70
70
  assert(res2.counts.delete === 4);
@@ -5,7 +5,7 @@ import { Suite, Test } from '@travetto/test';
5
5
  import { Schema, Text, Precision, Required, } from '@travetto/schema';
6
6
  import { ModelCrudSupport, Model, NotFoundError, PersistValue } from '@travetto/model';
7
7
 
8
- import { BaseModelSuite } from './base';
8
+ import { BaseModelSuite } from './base.ts';
9
9
 
10
10
  @Schema()
11
11
  class Address {
@@ -213,22 +213,22 @@ export abstract class ModelCrudSuite extends BaseModelSuite<ModelCrudSupport> {
213
213
  @Test('verify dates')
214
214
  async testDates() {
215
215
  const service = await this.service;
216
- const res = await service.create(Dated, Dated.from({ createdDate: new Date() }));
216
+ const result = await service.create(Dated, Dated.from({ createdDate: new Date() }));
217
217
 
218
- assert(res.createdDate instanceof Date);
218
+ assert(result.createdDate instanceof Date);
219
219
  }
220
220
 
221
221
  @Test('verify pre-persist on create/update')
222
222
  async testPrePersist() {
223
223
  const service = await this.service;
224
- const res = await service.create(Dated, Dated.from({}));
225
- const created = res.createdDate;
226
- assert(res.createdDate instanceof Date);
227
- assert(res.updatedDate instanceof Date);
224
+ const result = await service.create(Dated, Dated.from({}));
225
+ const created = result.createdDate;
226
+ assert(result.createdDate instanceof Date);
227
+ assert(result.updatedDate instanceof Date);
228
228
 
229
229
  await timers.setTimeout(100);
230
230
 
231
- const final = await service.updatePartial(Dated, { id: res.id, value: 'random' });
231
+ const final = await service.updatePartial(Dated, { id: result.id, value: 'random' });
232
232
  assert(final.createdDate instanceof Date);
233
233
  assert(final.createdDate.getTime() === created?.getTime());
234
234
  assert(final.updatedDate instanceof Date);
@@ -254,7 +254,7 @@ export abstract class ModelCrudSuite extends BaseModelSuite<ModelCrudSupport> {
254
254
  people.map(el => service.upsert(Person, el))
255
255
  );
256
256
 
257
- const found = (await this.toArray(service.list(Person))).sort((a, b) => a.age - b.age);
257
+ const found = (await this.toArray(service.list(Person))).toSorted((a, b) => a.age - b.age);
258
258
 
259
259
  assert(found[0].age === people[0].age);
260
260
  assert(found[1].age === people[1].age);
@@ -4,11 +4,11 @@ import timers from 'node:timers/promises';
4
4
  import { Suite, Test } from '@travetto/test';
5
5
  import { TimeSpan, TimeUnit, TimeUtil } from '@travetto/runtime';
6
6
 
7
- import { ExpiresAt, Model } from '../../src/registry/decorator';
8
- import { ModelExpirySupport } from '../../src/service/expiry';
9
- import { ModelExpiryUtil } from '../../src/internal/service/expiry';
10
- import { NotFoundError } from '../../src/error/not-found';
11
- import { BaseModelSuite } from './base';
7
+ import { ExpiresAt, Model } from '../../src/registry/decorator.ts';
8
+ import { ModelExpirySupport } from '../../src/types/expiry.ts';
9
+ import { ModelExpiryUtil } from '../../src/util/expiry.ts';
10
+ import { NotFoundError } from '../../src/error/not-found.ts';
11
+ import { BaseModelSuite } from './base.ts';
12
12
 
13
13
  @Model('expiry-user')
14
14
  export class ExpiryUser {
@@ -34,63 +34,63 @@ export abstract class ModelExpirySuite extends BaseModelSuite<ModelExpirySupport
34
34
  @Test()
35
35
  async basic() {
36
36
  const service = await this.service;
37
- const res = await service.upsert(ExpiryUser, ExpiryUser.from({
37
+ const result = await service.upsert(ExpiryUser, ExpiryUser.from({
38
38
  expiresAt: this.timeFromNow('2s')
39
39
  }));
40
- assert(res instanceof ExpiryUser);
40
+ assert(result instanceof ExpiryUser);
41
41
 
42
- const expiry = ModelExpiryUtil.getExpiryState(ExpiryUser, await service.get(ExpiryUser, res.id));
42
+ const expiry = ModelExpiryUtil.getExpiryState(ExpiryUser, await service.get(ExpiryUser, result.id));
43
43
  assert(!expiry.expired);
44
44
  }
45
45
 
46
46
  @Test()
47
47
  async aging() {
48
48
  const service = await this.service;
49
- const res = await service.upsert(ExpiryUser, ExpiryUser.from({
49
+ const result = await service.upsert(ExpiryUser, ExpiryUser.from({
50
50
  expiresAt: this.timeFromNow(100)
51
51
  }));
52
52
 
53
- assert(res instanceof ExpiryUser);
53
+ assert(result instanceof ExpiryUser);
54
54
 
55
55
  await this.wait(200);
56
56
 
57
- await assert.rejects(() => service.get(ExpiryUser, res.id), NotFoundError);
57
+ await assert.rejects(() => service.get(ExpiryUser, result.id), NotFoundError);
58
58
  }
59
59
 
60
60
  @Test()
61
61
  async updateExpired() {
62
62
  const service = await this.service;
63
- const res = await service.upsert(ExpiryUser, ExpiryUser.from({
63
+ const result = await service.upsert(ExpiryUser, ExpiryUser.from({
64
64
  expiresAt: this.timeFromNow(100)
65
65
  }));
66
66
 
67
- assert(res instanceof ExpiryUser);
67
+ assert(result instanceof ExpiryUser);
68
68
 
69
69
  await this.wait(200);
70
70
 
71
- await assert.rejects(() => service.update(ExpiryUser, ExpiryUser.from({ id: res.id })), NotFoundError);
71
+ await assert.rejects(() => service.update(ExpiryUser, ExpiryUser.from({ id: result.id })), NotFoundError);
72
72
  }
73
73
 
74
74
  @Test()
75
75
  async ageWithExtension() {
76
76
  const service = await this.service;
77
- const res = await service.upsert(ExpiryUser, ExpiryUser.from({
77
+ const result = await service.upsert(ExpiryUser, ExpiryUser.from({
78
78
  expiresAt: this.timeFromNow('2s')
79
79
  }));
80
- assert(res instanceof ExpiryUser);
80
+ assert(result instanceof ExpiryUser);
81
81
 
82
82
  await this.wait(50);
83
83
 
84
- assert(!ModelExpiryUtil.getExpiryState(ExpiryUser, (await service.get(ExpiryUser, res.id))).expired);
84
+ assert(!ModelExpiryUtil.getExpiryState(ExpiryUser, (await service.get(ExpiryUser, result.id))).expired);
85
85
 
86
86
  await service.updatePartial(ExpiryUser, {
87
- id: res.id,
87
+ id: result.id,
88
88
  expiresAt: this.timeFromNow(100)
89
89
  });
90
90
 
91
91
  await this.wait(200);
92
92
 
93
- await assert.rejects(() => service.get(ExpiryUser, res.id), NotFoundError);
93
+ await assert.rejects(() => service.get(ExpiryUser, result.id), NotFoundError);
94
94
  }
95
95
 
96
96
  @Test()
@@ -4,12 +4,12 @@ import { Suite, Test } from '@travetto/test';
4
4
  import { Schema } from '@travetto/schema';
5
5
  import { TimeUtil } from '@travetto/runtime';
6
6
 
7
- import { Index, Model } from '../../src/registry/decorator';
8
- import { ModelIndexedSupport } from '../../src/service/indexed';
9
- import { NotFoundError } from '../../src/error/not-found';
10
- import { IndexNotSupported } from '../../src/error/invalid-index';
7
+ import { Index, Model } from '../../src/registry/decorator.ts';
8
+ import { ModelIndexedSupport } from '../../src/types/indexed.ts';
9
+ import { NotFoundError } from '../../src/error/not-found.ts';
10
+ import { IndexNotSupported } from '../../src/error/invalid-index.ts';
11
11
 
12
- import { BaseModelSuite } from './base';
12
+ import { BaseModelSuite } from './base.ts';
13
13
 
14
14
  @Model('index_user')
15
15
  @Index({
@@ -9,10 +9,10 @@ import {
9
9
  NotFoundError, SubTypeNotSupportedError, PersistValue
10
10
  } from '@travetto/model';
11
11
 
12
- import { isIndexedSupported } from '../../src/internal/service/common';
13
- import { ExistsError } from '../../src/error/exists';
12
+ import { ModelIndexedUtil } from '../../src/util/indexed.ts';
13
+ import { ExistsError } from '../../src/error/exists.ts';
14
14
 
15
- import { BaseModelSuite } from './base';
15
+ import { BaseModelSuite } from './base.ts';
16
16
 
17
17
  @Model({ baseType: true })
18
18
  export class Worker {
@@ -171,11 +171,11 @@ export abstract class ModelPolymorphismSuite extends BaseModelSuite<ModelCrudSup
171
171
  await timers.setTimeout(15);
172
172
 
173
173
  try {
174
- const res = await service.upsert(Doctor, Doctor.from({
174
+ const result = await service.upsert(Doctor, Doctor.from({
175
175
  id: doc.id, name: 'gob', specialty: 'eyes'
176
176
  }));
177
177
 
178
- assert(res.updatedDate!.getTime() > update.getTime());
178
+ assert(result.updatedDate!.getTime() > update.getTime());
179
179
  } catch (err) {
180
180
  assert(err instanceof SubTypeNotSupportedError);
181
181
  }
@@ -207,7 +207,7 @@ export abstract class ModelPolymorphismSuite extends BaseModelSuite<ModelCrudSup
207
207
  );
208
208
  }
209
209
 
210
- @Test('Polymorphic index', { skip: BaseModelSuite.ifNot(isIndexedSupported) })
210
+ @Test('Polymorphic index', { skip: BaseModelSuite.ifNot(ModelIndexedUtil.isSupported) })
211
211
  async polymorphicIndexGet() {
212
212
  const service: ModelIndexedSupport = castTo(await this.service);
213
213
  const now = 30;
@@ -219,12 +219,12 @@ export abstract class ModelPolymorphismSuite extends BaseModelSuite<ModelCrudSup
219
219
 
220
220
  await this.saveAll(IndexedWorker, [doc, fire, eng]);
221
221
 
222
- const res = await service.getByIndex(IndexedWorker, 'worker-name', {
222
+ const result = await service.getByIndex(IndexedWorker, 'worker-name', {
223
223
  age: now,
224
224
  name: 'rob'
225
225
  });
226
226
 
227
- assert(res instanceof IndexedFirefighter);
227
+ assert(result instanceof IndexedFirefighter);
228
228
 
229
229
  try {
230
230
  const res2 = await service.getByIndex(IndexedFirefighter, 'worker-name', {
@@ -237,7 +237,7 @@ export abstract class ModelPolymorphismSuite extends BaseModelSuite<ModelCrudSup
237
237
  }
238
238
  }
239
239
 
240
- @Test('Polymorphic index', { skip: BaseModelSuite.ifNot(isIndexedSupported) })
240
+ @Test('Polymorphic index', { skip: BaseModelSuite.ifNot(ModelIndexedUtil.isSupported) })
241
241
  async polymorphicIndexDelete() {
242
242
  const service: ModelIndexedSupport = castTo(await this.service);
243
243
  const now = 30;
@@ -3,9 +3,9 @@ import { DependencyRegistry } from '@travetto/di';
3
3
  import { RootRegistry } from '@travetto/registry';
4
4
  import { SuiteRegistry, TestFixtures } from '@travetto/test';
5
5
 
6
- import { isBlobSupported, isStorageSupported } from '../../src/internal/service/common';
7
- import { MODEL_BLOB } from '../../src/internal/service/blob';
8
- import { ModelRegistry } from '../../src/registry/model';
6
+ import { ModelBlobUtil } from '../../src/util/blob.ts';
7
+ import { ModelStorageUtil } from '../../src/util/storage.ts';
8
+ import { ModelRegistry } from '../../src/registry/model.ts';
9
9
 
10
10
  const Loaded = Symbol();
11
11
 
@@ -35,7 +35,7 @@ export function ModelSuite<T extends { configClass: Class<{ autoCreate?: boolean
35
35
  target,
36
36
  async function (this: T) {
37
37
  const service = await DependencyRegistry.getInstance(this.serviceClass, qualifier);
38
- if (isStorageSupported(service)) {
38
+ if (ModelStorageUtil.isSupported(service)) {
39
39
  await service.createStorage();
40
40
  if (service.createModel) {
41
41
  await Promise.all(ModelRegistry.getClasses()
@@ -50,10 +50,11 @@ export function ModelSuite<T extends { configClass: Class<{ autoCreate?: boolean
50
50
  target,
51
51
  async function (this: T) {
52
52
  const service = await DependencyRegistry.getInstance(this.serviceClass, qualifier);
53
- if (isStorageSupported(service)) {
53
+ if (ModelStorageUtil.isSupported(service)) {
54
54
  const models = ModelRegistry.getClasses().filter(m => m === ModelRegistry.getBaseModel(m));
55
- if (isBlobSupported(service)) {
56
- models.push(MODEL_BLOB);
55
+
56
+ if (ModelBlobUtil.isSupported(service) && service.truncateBlob) {
57
+ await service.truncateBlob();
57
58
  }
58
59
 
59
60
  if (service.truncateModel) {
@@ -71,7 +72,7 @@ export function ModelSuite<T extends { configClass: Class<{ autoCreate?: boolean
71
72
  target,
72
73
  async function (this: T) {
73
74
  const service = await DependencyRegistry.getInstance(this.serviceClass, qualifier);
74
- if (isStorageSupported(service)) {
75
+ if (ModelStorageUtil.isSupported(service)) {
75
76
  if (service.deleteModel) {
76
77
  for (const m of ModelRegistry.getClasses()) {
77
78
  if (m === ModelRegistry.getBaseModel(m)) {
@@ -1,51 +0,0 @@
1
- import { hasFunction } from '@travetto/runtime';
2
-
3
- import type { ModelBulkSupport } from '../../service/bulk';
4
- import type { ModelCrudSupport } from '../../service/crud';
5
- import type { ModelExpirySupport } from '../../service/expiry';
6
- import type { ModelIndexedSupport } from '../../service/indexed';
7
- import type { ModelStorageSupport } from '../../service/storage';
8
- import type { ModelBlobSupport } from '../../service/blob';
9
-
10
- export class ModelBasicSupportTarget { }
11
- export class ModelCrudSupportTarget { }
12
- export class ModelBulkSupportTarget { }
13
- export class ModelStorageSupportTarget { }
14
- export class ModelBlobSupportTarget { }
15
- export class ModelExpirySupportTarget { }
16
- export class ModelIndexedSupportTarget { }
17
-
18
- /**
19
- * Type guard for determining if service supports basic operations
20
- */
21
- export const isBasicSupported = hasFunction<ModelBulkSupport>('create');
22
-
23
- /**
24
- * Type guard for determining if service supports crud operations
25
- */
26
- export const isCrudSupported = hasFunction<ModelCrudSupport>('upsert');
27
-
28
- /**
29
- * Type guard for determining if model supports expiry
30
- */
31
- export const isExpirySupported = hasFunction<ModelExpirySupport>('deleteExpired');
32
-
33
- /**
34
- * Type guard for determining if service supports blob operations
35
- */
36
- export const isBlobSupported = hasFunction<ModelBlobSupport>('getBlob');
37
-
38
- /**
39
- * Type guard for determining if service supports storage operation
40
- */
41
- export const isStorageSupported = hasFunction<ModelStorageSupport>('createStorage');
42
-
43
- /**
44
- * Type guard for determining if service supports bulk operation
45
- */
46
- export const isBulkSupported = hasFunction<ModelBulkSupport>('processBulk');
47
-
48
- /**
49
- * Type guard for determining if service supports indexed operation
50
- */
51
- export const isIndexedSupported = hasFunction<ModelIndexedSupport>('getByIndex');