@travetto/model 8.0.0-alpha.2 → 8.0.0-alpha.21
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 +40 -56
- package/__index__.ts +0 -2
- package/package.json +7 -7
- package/src/error/invalid-index.ts +2 -2
- package/src/registry/decorator.ts +15 -15
- package/src/registry/registry-adapter.ts +6 -3
- package/src/registry/registry-index.ts +5 -27
- package/src/registry/types.ts +23 -38
- package/src/types/basic.ts +1 -1
- package/src/types/blob.ts +4 -3
- package/src/types/bulk.ts +1 -1
- package/src/types/crud.ts +8 -3
- package/src/types/expiry.ts +1 -1
- package/src/types/model.ts +10 -1
- package/src/types/storage.ts +1 -1
- package/src/util/crud.ts +81 -8
- package/support/cli.model_export.ts +4 -1
- package/support/cli.model_install.ts +4 -1
- package/support/doc.support.tsx +0 -2
- package/support/test/base.ts +5 -5
- package/support/test/basic.ts +40 -1
- package/support/test/blob.ts +1 -1
- package/support/test/crud.ts +39 -5
- package/support/test/polymorphism.ts +6 -114
- package/src/types/indexed.ts +0 -43
- package/src/util/indexed.ts +0 -144
- package/support/test/indexed.ts +0 -190
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ 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
|
## A Simple Model
|
|
19
|
-
A model can be simply defined by usage of the [@Model](https://github.com/travetto/travetto/tree/main/module/model/src/registry/decorator.ts#L14) decorator, which opts it into the [Schema](https://github.com/travetto/travetto/tree/main/module/schema#readme "Data type registry for runtime validation, reflection and binding.") contracts, as well as making it available to the [ModelRegistryIndex](https://github.com/travetto/travetto/tree/main/module/model/src/registry/registry-index.ts#
|
|
19
|
+
A model can be simply defined by usage of the [@Model](https://github.com/travetto/travetto/tree/main/module/model/src/registry/decorator.ts#L14) decorator, which opts it into the [Schema](https://github.com/travetto/travetto/tree/main/module/schema#readme "Data type registry for runtime validation, reflection and binding.") contracts, as well as making it available to the [ModelRegistryIndex](https://github.com/travetto/travetto/tree/main/module/model/src/registry/registry-index.ts#L12).
|
|
20
20
|
|
|
21
21
|
**Code: Basic Structure**
|
|
22
22
|
```typescript
|
|
@@ -33,7 +33,7 @@ export class SampleModel {
|
|
|
33
33
|
Once the model is defined, it can be leveraged with any of the services that implement the various model storage contracts. These contracts allow for persisting and fetching of the associated model object.
|
|
34
34
|
|
|
35
35
|
## Contracts
|
|
36
|
-
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), [
|
|
36
|
+
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), [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).
|
|
37
37
|
|
|
38
38
|
### Basic
|
|
39
39
|
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.
|
|
@@ -76,7 +76,7 @@ export interface ModelBasicSupport<C = unknown> {
|
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
### CRUD
|
|
79
|
-
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
|
|
79
|
+
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 support 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 support for the Travetto framework") model extension.
|
|
80
80
|
|
|
81
81
|
**Code: Crud Contract**
|
|
82
82
|
```typescript
|
|
@@ -110,51 +110,18 @@ export interface ModelCrudSupport extends ModelBasicSupport {
|
|
|
110
110
|
updatePartial<T extends ModelType>(cls: Class<T>, item: Partial<T> & { id: string }, view?: string): Promise<T>;
|
|
111
111
|
|
|
112
112
|
/**
|
|
113
|
-
* List all items
|
|
113
|
+
* List all items of a collection, results returned in batches of items.
|
|
114
|
+
*
|
|
115
|
+
* Note: Batch size hint can be used to optimize batch size, but is not guaranteed.
|
|
116
|
+
*
|
|
117
|
+
* @param cls The class to list
|
|
118
|
+
* @param options Options for listing
|
|
114
119
|
*/
|
|
115
|
-
list<T extends ModelType>(cls: Class<T
|
|
120
|
+
list<T extends ModelType>(cls: Class<T>, options?: ModelListOptions): AsyncIterable<T[]>;
|
|
116
121
|
}
|
|
117
122
|
```
|
|
118
123
|
|
|
119
|
-
|
|
120
|
-
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.
|
|
121
|
-
|
|
122
|
-
**Code: Indexed Contract**
|
|
123
|
-
```typescript
|
|
124
|
-
export interface ModelIndexedSupport extends ModelBasicSupport {
|
|
125
|
-
/**
|
|
126
|
-
* Get entity by index as defined by fields of idx and the body fields
|
|
127
|
-
* @param cls The type to search by
|
|
128
|
-
* @param idx The index name to search against
|
|
129
|
-
* @param body The payload of fields needed to search
|
|
130
|
-
*/
|
|
131
|
-
getByIndex<T extends ModelType>(cls: Class<T>, idx: string, body: DeepPartial<T>): Promise<T>;
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Delete entity by index as defined by fields of idx and the body fields
|
|
135
|
-
* @param cls The type to search by
|
|
136
|
-
* @param idx The index name to search against
|
|
137
|
-
* @param body The payload of fields needed to search
|
|
138
|
-
*/
|
|
139
|
-
deleteByIndex<T extends ModelType>(cls: Class<T>, idx: string, body: DeepPartial<T>): Promise<void>;
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* List entity by ranged index as defined by fields of idx and the body fields
|
|
143
|
-
* @param cls The type to search by
|
|
144
|
-
* @param idx The index name to search against
|
|
145
|
-
* @param body The payload of fields needed to search
|
|
146
|
-
*/
|
|
147
|
-
listByIndex<T extends ModelType>(cls: Class<T>, idx: string, body?: DeepPartial<T>): AsyncIterable<T>;
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Upsert by index, allowing the index to act as a primary key
|
|
151
|
-
* @param cls The type to create for
|
|
152
|
-
* @param idx The index name to use
|
|
153
|
-
* @param body The document to potentially store
|
|
154
|
-
*/
|
|
155
|
-
upsertByIndex<T extends ModelType>(cls: Class<T>, idx: string, body: OptionalId<T>): Promise<T>;
|
|
156
|
-
}
|
|
157
|
-
```
|
|
124
|
+
The `list` operation returns batches of model records as an async stream. It also accepts listing options such as `limit` to cap how many records are produced, alongside other runtime controls such as abort signals and batch size hints.
|
|
158
125
|
|
|
159
126
|
### Expiry
|
|
160
127
|
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.
|
|
@@ -213,12 +180,13 @@ export interface ModelBlobSupport {
|
|
|
213
180
|
updateBlobMetadata(location: string, metadata: BinaryMetadata): Promise<void>;
|
|
214
181
|
|
|
215
182
|
/**
|
|
216
|
-
* Produces an externally usable URL for sharing limited read access to a specific resource
|
|
183
|
+
* Produces an externally usable URL for sharing limited read access to a specific resource.
|
|
184
|
+
* If expiresIn is explicitly set to false, returns a direct/public URL.
|
|
217
185
|
*
|
|
218
186
|
* @param location The asset location to read from
|
|
219
|
-
* @param expiresIn Expiry
|
|
187
|
+
* @param expiresIn Expiry or false for public/direct URL
|
|
220
188
|
*/
|
|
221
|
-
getBlobReadUrl?(location: string, expiresIn?: TimeSpan): Promise<string>;
|
|
189
|
+
getBlobReadUrl?(location: string, expiresIn?: TimeSpan | false): Promise<string>;
|
|
222
190
|
|
|
223
191
|
/**
|
|
224
192
|
* Produces an externally usable URL for sharing allowing direct write access
|
|
@@ -302,8 +270,8 @@ export abstract class BaseModelSuite<T> {
|
|
|
302
270
|
const svc = (await this.service);
|
|
303
271
|
if (ModelCrudUtil.isSupported(svc)) {
|
|
304
272
|
let i = 0;
|
|
305
|
-
for await (const
|
|
306
|
-
i +=
|
|
273
|
+
for await (const batch of svc.list(cls)) {
|
|
274
|
+
i += batch.length;
|
|
307
275
|
}
|
|
308
276
|
return i;
|
|
309
277
|
} else {
|
|
@@ -332,12 +300,12 @@ export abstract class BaseModelSuite<T> {
|
|
|
332
300
|
return DependencyRegistryIndex.getInstance(this.serviceClass);
|
|
333
301
|
}
|
|
334
302
|
|
|
335
|
-
async toArray<U>(src: AsyncIterable<U> | AsyncGenerator<U>): Promise<U[]> {
|
|
336
|
-
const out: U[] = [];
|
|
303
|
+
async toArray<U>(src: AsyncIterable<U | U[]> | AsyncGenerator<U | U[]>): Promise<U[]> {
|
|
304
|
+
const out: (U | U[])[] = [];
|
|
337
305
|
for await (const el of src) {
|
|
338
306
|
out.push(el);
|
|
339
307
|
}
|
|
340
|
-
return out;
|
|
308
|
+
return castTo(out.flat());
|
|
341
309
|
}
|
|
342
310
|
}
|
|
343
311
|
```
|
|
@@ -345,16 +313,22 @@ export abstract class BaseModelSuite<T> {
|
|
|
345
313
|
## CLI - model:export
|
|
346
314
|
The module provides the ability to generate an export of the model structure from all the various [@Model](https://github.com/travetto/travetto/tree/main/module/model/src/registry/decorator.ts#L14)s within the application. This is useful for being able to generate the appropriate files to manually create the data schemas in production.
|
|
347
315
|
|
|
348
|
-
**Terminal:
|
|
316
|
+
**Terminal: Help for model:export**
|
|
349
317
|
```bash
|
|
350
318
|
$ trv model:export --help
|
|
351
319
|
|
|
352
320
|
Usage: model:export [options] <provider:string> <models...:string>
|
|
353
321
|
|
|
322
|
+
Description:
|
|
323
|
+
Export model definitions for a selected provider and model set.
|
|
324
|
+
|
|
325
|
+
The command resolves candidate models and delegates to provider-specific
|
|
326
|
+
export logic to produce schema/install artifacts.
|
|
327
|
+
|
|
354
328
|
Options:
|
|
355
329
|
-p, --profile <string> Application profiles
|
|
356
330
|
-m, --module <module> Module to run for
|
|
357
|
-
|
|
331
|
+
--help display help for command
|
|
358
332
|
|
|
359
333
|
Providers
|
|
360
334
|
--------------------
|
|
@@ -363,21 +337,29 @@ Providers
|
|
|
363
337
|
Models
|
|
364
338
|
--------------------
|
|
365
339
|
* samplemodel
|
|
340
|
+
|
|
341
|
+
Examples:
|
|
366
342
|
```
|
|
367
343
|
|
|
368
344
|
## CLI - model:install
|
|
369
345
|
The module provides the ability to install all the various [@Model](https://github.com/travetto/travetto/tree/main/module/model/src/registry/decorator.ts#L14)s within the application given the current configuration being targeted. This is useful for being able to prepare the datastore manually.
|
|
370
346
|
|
|
371
|
-
**Terminal:
|
|
347
|
+
**Terminal: Help for model:install**
|
|
372
348
|
```bash
|
|
373
349
|
$ trv model:install --help
|
|
374
350
|
|
|
375
351
|
Usage: model:install [options] <provider:string> <models...:string>
|
|
376
352
|
|
|
353
|
+
Description:
|
|
354
|
+
Install or update model definitions for a selected provider.
|
|
355
|
+
|
|
356
|
+
The command resolves candidate models and applies provider install/upsert
|
|
357
|
+
operations so backing stores are prepared for runtime usage.
|
|
358
|
+
|
|
377
359
|
Options:
|
|
378
360
|
-p, --profile <string> Application profiles
|
|
379
361
|
-m, --module <module> Module to run for
|
|
380
|
-
|
|
362
|
+
--help display help for command
|
|
381
363
|
|
|
382
364
|
Providers
|
|
383
365
|
--------------------
|
|
@@ -386,4 +368,6 @@ Providers
|
|
|
386
368
|
Models
|
|
387
369
|
--------------------
|
|
388
370
|
* samplemodel
|
|
371
|
+
|
|
372
|
+
Examples:
|
|
389
373
|
```
|
package/__index__.ts
CHANGED
|
@@ -8,7 +8,6 @@ export * from './src/types/basic.ts';
|
|
|
8
8
|
export * from './src/types/blob.ts';
|
|
9
9
|
export * from './src/types/bulk.ts';
|
|
10
10
|
export * from './src/types/crud.ts';
|
|
11
|
-
export * from './src/types/indexed.ts';
|
|
12
11
|
export * from './src/types/expiry.ts';
|
|
13
12
|
export * from './src/types/storage.ts';
|
|
14
13
|
|
|
@@ -16,7 +15,6 @@ export * from './src/util/blob.ts';
|
|
|
16
15
|
export * from './src/util/bulk.ts';
|
|
17
16
|
export * from './src/util/crud.ts';
|
|
18
17
|
export * from './src/util/expiry.ts';
|
|
19
|
-
export * from './src/util/indexed.ts';
|
|
20
18
|
export * from './src/util/storage.ts';
|
|
21
19
|
|
|
22
20
|
export * from './src/error/exists.ts';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model",
|
|
3
|
-
"version": "8.0.0-alpha.
|
|
3
|
+
"version": "8.0.0-alpha.21",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Datastore abstraction for core operations.",
|
|
6
6
|
"keywords": [
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"directory": "module/model"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@travetto/config": "^8.0.0-alpha.
|
|
31
|
-
"@travetto/di": "^8.0.0-alpha.
|
|
32
|
-
"@travetto/registry": "^8.0.0-alpha.
|
|
33
|
-
"@travetto/schema": "^8.0.0-alpha.
|
|
30
|
+
"@travetto/config": "^8.0.0-alpha.20",
|
|
31
|
+
"@travetto/di": "^8.0.0-alpha.19",
|
|
32
|
+
"@travetto/registry": "^8.0.0-alpha.19",
|
|
33
|
+
"@travetto/schema": "^8.0.0-alpha.20"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@travetto/cli": "^8.0.0-alpha.
|
|
37
|
-
"@travetto/test": "^8.0.0-alpha.
|
|
36
|
+
"@travetto/cli": "^8.0.0-alpha.26",
|
|
37
|
+
"@travetto/test": "^8.0.0-alpha.19"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
40
40
|
"@travetto/cli": {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { type Class, RuntimeError } from '@travetto/runtime';
|
|
2
2
|
|
|
3
|
-
import type { IndexConfig } from '../registry/types.ts';
|
|
4
3
|
import type { ModelType } from '../types/model.ts';
|
|
4
|
+
import type { IndexConfig } from '../registry/types.ts';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Represents when an index is invalid
|
|
8
8
|
*/
|
|
9
9
|
export class IndexNotSupported<T extends ModelType> extends RuntimeError {
|
|
10
|
-
constructor(cls: Class<T>, idx: IndexConfig
|
|
10
|
+
constructor(cls: Class<T>, idx: IndexConfig, message: string = '') {
|
|
11
11
|
super(`${typeof cls === 'string' ? cls : cls.name} and index ${idx.name} of type ${idx.type} is not supported. ${message}`.trim(), { category: 'data' });
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { castTo, type Class, getClass } from '@travetto/runtime';
|
|
2
2
|
import { SchemaRegistryIndex } from '@travetto/schema';
|
|
3
3
|
|
|
4
4
|
import type { ModelType } from '../types/model.ts';
|
|
5
|
-
import type { DataHandler,
|
|
5
|
+
import type { DataHandler, ModelConfig, PrePersistScope } from './types.ts';
|
|
6
6
|
import { ModelRegistryIndex } from './registry-index.ts';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -24,19 +24,6 @@ export function Model(config: Partial<ModelConfig<ModelType>> | string = {}) {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
/**
|
|
28
|
-
* Defines an index on a model
|
|
29
|
-
* @kind decorator
|
|
30
|
-
*/
|
|
31
|
-
export function Index<T extends ModelType>(...indices: IndexConfig<T>[]) {
|
|
32
|
-
if (indices.some(config => config.fields.some(field => field === 'id'))) {
|
|
33
|
-
throw new RuntimeError('Cannot create an index with the id field');
|
|
34
|
-
}
|
|
35
|
-
return function (cls: Class<T>): void {
|
|
36
|
-
ModelRegistryIndex.getForRegister(cls).register({ indices });
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
27
|
/**
|
|
41
28
|
* Model field decorator for denoting expiry date/time
|
|
42
29
|
* @augments `@travetto/schema:Field`
|
|
@@ -102,6 +89,19 @@ export function Transient<T>() {
|
|
|
102
89
|
};
|
|
103
90
|
}
|
|
104
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Prevent a field from being persisted
|
|
94
|
+
* @augments `@travetto/schema:Field`
|
|
95
|
+
* @kind decorator
|
|
96
|
+
*/
|
|
97
|
+
export function TransientField() {
|
|
98
|
+
return function <K extends string, C extends Partial<Record<K, unknown>>>(instance: C, property: K): void {
|
|
99
|
+
ModelRegistryIndex.getForRegister(getClass(instance)).register({
|
|
100
|
+
transientFields: [property]
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
105
|
/**
|
|
106
106
|
* Model class decorator for post-load behavior
|
|
107
107
|
* @augments `@travetto/schema:Schema`
|
|
@@ -7,9 +7,10 @@ import type { ModelConfig } from './types.ts';
|
|
|
7
7
|
function combineClasses(target: ModelConfig, sources: Partial<ModelConfig>[]): ModelConfig {
|
|
8
8
|
for (const source of sources) {
|
|
9
9
|
Object.assign(target, source, {
|
|
10
|
-
indices:
|
|
10
|
+
indices: { ...(target.indices || {}), ...(source.indices || {}) },
|
|
11
11
|
postLoad: [...(target.postLoad || []), ...(source.postLoad || [])],
|
|
12
12
|
prePersist: [...(target.prePersist || []), ...(source.prePersist || [])],
|
|
13
|
+
transientFields: [...(target.transientFields || []), ...(source.transientFields || [])],
|
|
13
14
|
});
|
|
14
15
|
}
|
|
15
16
|
if (target.store) {
|
|
@@ -29,11 +30,12 @@ export class ModelRegistryAdapter implements RegistryAdapter<ModelConfig> {
|
|
|
29
30
|
register(...data: Partial<ModelConfig>[]): ModelConfig {
|
|
30
31
|
const config = this.#config ??= {
|
|
31
32
|
class: this.#cls,
|
|
32
|
-
indices:
|
|
33
|
+
indices: {},
|
|
33
34
|
autoCreate: 'development',
|
|
34
35
|
store: this.#cls.name,
|
|
35
36
|
postLoad: [],
|
|
36
|
-
prePersist: []
|
|
37
|
+
prePersist: [],
|
|
38
|
+
transientFields: []
|
|
37
39
|
};
|
|
38
40
|
combineClasses(config, data);
|
|
39
41
|
return config;
|
|
@@ -50,6 +52,7 @@ export class ModelRegistryAdapter implements RegistryAdapter<ModelConfig> {
|
|
|
50
52
|
|
|
51
53
|
config.postLoad = [...parent.postLoad ?? [], ...config.postLoad ?? []];
|
|
52
54
|
config.prePersist = [...parent.prePersist ?? [], ...config.prePersist ?? []];
|
|
55
|
+
config.transientFields = [...parent.transientFields ?? [], ...config.transientFields ?? []];
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
|
|
@@ -2,13 +2,9 @@ import { type RegistryIndex, RegistryIndexStore, Registry } from '@travetto/regi
|
|
|
2
2
|
import { RuntimeError, castTo, type Class } from '@travetto/runtime';
|
|
3
3
|
import { SchemaRegistryIndex } from '@travetto/schema';
|
|
4
4
|
|
|
5
|
-
import type { IndexConfig,
|
|
5
|
+
import type { IndexConfig, ModelConfig } from './types.ts';
|
|
6
6
|
import type { ModelType } from '../types/model.ts';
|
|
7
7
|
import { ModelRegistryAdapter } from './registry-adapter.ts';
|
|
8
|
-
import { IndexNotSupported } from '../error/invalid-index.ts';
|
|
9
|
-
import { NotFoundError } from '../error/not-found.ts';
|
|
10
|
-
|
|
11
|
-
type IndexResult<T extends ModelType, K extends IndexType[]> = IndexConfig<T> & { type: K[number] };
|
|
12
8
|
|
|
13
9
|
/**
|
|
14
10
|
* Model registry index for managing model configurations across classes
|
|
@@ -33,12 +29,8 @@ export class ModelRegistryIndex implements RegistryIndex {
|
|
|
33
29
|
return this.#instance.getStoreName(cls);
|
|
34
30
|
}
|
|
35
31
|
|
|
36
|
-
static getIndices<T extends ModelType
|
|
37
|
-
return this.#instance.getIndices(cls
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
static getIndex<T extends ModelType, K extends IndexType[]>(cls: Class<T>, name: string, supportedTypes?: K): IndexResult<T, K> {
|
|
41
|
-
return this.#instance.getIndex(cls, name, supportedTypes);
|
|
32
|
+
static getIndices<T extends ModelType>(cls: Class<T>): IndexConfig[] {
|
|
33
|
+
return this.#instance.getIndices(cls);
|
|
42
34
|
}
|
|
43
35
|
|
|
44
36
|
static getExpiryFieldName<T extends ModelType>(cls: Class<T>): keyof T {
|
|
@@ -94,25 +86,11 @@ export class ModelRegistryIndex implements RegistryIndex {
|
|
|
94
86
|
return this.store.get(cls).get().store;
|
|
95
87
|
}
|
|
96
88
|
|
|
97
|
-
/**
|
|
98
|
-
* Get Index
|
|
99
|
-
*/
|
|
100
|
-
getIndex<T extends ModelType, K extends IndexType[]>(cls: Class<T>, name: string, supportedTypes?: K): IndexResult<T, K> {
|
|
101
|
-
const config = this.getConfig(cls).indices?.find((idx): idx is IndexConfig<T> => idx.name === name);
|
|
102
|
-
if (!config) {
|
|
103
|
-
throw new NotFoundError(`${cls.name} Index`, `${name}`);
|
|
104
|
-
}
|
|
105
|
-
if (supportedTypes && !supportedTypes.includes(config.type)) {
|
|
106
|
-
throw new IndexNotSupported(cls, config, `${config.type} indices are not supported.`);
|
|
107
|
-
}
|
|
108
|
-
return config;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
89
|
/**
|
|
112
90
|
* Get Indices
|
|
113
91
|
*/
|
|
114
|
-
getIndices<T extends ModelType
|
|
115
|
-
return (this.getConfig(cls).indices ?? [])
|
|
92
|
+
getIndices<T extends ModelType>(cls: Class<T>): IndexConfig[] {
|
|
93
|
+
return Object.values(this.getConfig(cls).indices ?? []);
|
|
116
94
|
}
|
|
117
95
|
|
|
118
96
|
/**
|
package/src/registry/types.ts
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
|
-
import type { Class
|
|
1
|
+
import type { Class } from '@travetto/runtime';
|
|
2
2
|
|
|
3
3
|
import type { ModelType } from '../types/model.ts';
|
|
4
4
|
|
|
5
|
-
type RetainPrimitiveFields<T> = Pick<T, ValidFields<T, Primitive | Date>>;
|
|
6
|
-
|
|
7
|
-
export type SortClauseRaw<T> = {
|
|
8
|
-
[P in keyof T]?:
|
|
9
|
-
T[P] extends object ? SortClauseRaw<RetainPrimitiveFields<T[P]>> : 1 | -1;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
type IndexClauseRaw<T> = {
|
|
13
|
-
[P in keyof T]?:
|
|
14
|
-
T[P] extends object ? IndexClauseRaw<RetainPrimitiveFields<T[P]>> : 1 | -1 | true;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
5
|
export type DataHandler<T = unknown> = (inst: T) => (Promise<T | void> | T | void);
|
|
18
6
|
|
|
19
7
|
export type PrePersistScope = 'full' | 'partial' | 'all';
|
|
20
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Index options
|
|
11
|
+
*/
|
|
12
|
+
export type IndexConfig<V extends string = string> = {
|
|
13
|
+
/**
|
|
14
|
+
* Index name
|
|
15
|
+
*/
|
|
16
|
+
name: string;
|
|
17
|
+
/**
|
|
18
|
+
* Type
|
|
19
|
+
*/
|
|
20
|
+
type: V;
|
|
21
|
+
/**
|
|
22
|
+
* Class the index belongs to
|
|
23
|
+
*/
|
|
24
|
+
class: Class<ModelType>;
|
|
25
|
+
};
|
|
26
|
+
|
|
21
27
|
/**
|
|
22
28
|
* Model config
|
|
23
29
|
*/
|
|
@@ -33,7 +39,7 @@ export class ModelConfig<T extends ModelType = ModelType> {
|
|
|
33
39
|
/**
|
|
34
40
|
* Indices
|
|
35
41
|
*/
|
|
36
|
-
indices?: IndexConfig
|
|
42
|
+
indices?: Record<string, IndexConfig>;
|
|
37
43
|
/**
|
|
38
44
|
* Vendor specific extras
|
|
39
45
|
*/
|
|
@@ -54,29 +60,8 @@ export class ModelConfig<T extends ModelType = ModelType> {
|
|
|
54
60
|
* Post-load handlers
|
|
55
61
|
*/
|
|
56
62
|
postLoad?: DataHandler<unknown>[];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Supported index types
|
|
61
|
-
*/
|
|
62
|
-
export type IndexType = 'unique' | 'unsorted' | 'sorted';
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Index options
|
|
66
|
-
*/
|
|
67
|
-
export type IndexConfig<T extends ModelType> = {
|
|
68
63
|
/**
|
|
69
|
-
*
|
|
64
|
+
* Fields to ignore during persistence
|
|
70
65
|
*/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
* Fields and sort order
|
|
74
|
-
*/
|
|
75
|
-
fields: IndexClauseRaw<RetainPrimitiveFields<T>>[];
|
|
76
|
-
/**
|
|
77
|
-
* Type
|
|
78
|
-
*/
|
|
79
|
-
type: IndexType;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export type IndexField<T extends ModelType> = IndexClauseRaw<RetainPrimitiveFields<T>>;
|
|
66
|
+
transientFields?: string[];
|
|
67
|
+
}
|
package/src/types/basic.ts
CHANGED
package/src/types/blob.ts
CHANGED
|
@@ -42,12 +42,13 @@ export interface ModelBlobSupport {
|
|
|
42
42
|
updateBlobMetadata(location: string, metadata: BinaryMetadata): Promise<void>;
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
|
-
* Produces an externally usable URL for sharing limited read access to a specific resource
|
|
45
|
+
* Produces an externally usable URL for sharing limited read access to a specific resource.
|
|
46
|
+
* If expiresIn is explicitly set to false, returns a direct/public URL.
|
|
46
47
|
*
|
|
47
48
|
* @param location The asset location to read from
|
|
48
|
-
* @param expiresIn Expiry
|
|
49
|
+
* @param expiresIn Expiry or false for public/direct URL
|
|
49
50
|
*/
|
|
50
|
-
getBlobReadUrl?(location: string, expiresIn?: TimeSpan): Promise<string>;
|
|
51
|
+
getBlobReadUrl?(location: string, expiresIn?: TimeSpan | false): Promise<string>;
|
|
51
52
|
|
|
52
53
|
/**
|
|
53
54
|
* Produces an externally usable URL for sharing allowing direct write access
|
package/src/types/bulk.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type Class, RuntimeError } from '@travetto/runtime';
|
|
|
2
2
|
import type { ValidationError, ValidationResultError } from '@travetto/schema';
|
|
3
3
|
|
|
4
4
|
import type { ModelCrudSupport } from './crud.ts';
|
|
5
|
-
import type { ModelType, OptionalId } from '
|
|
5
|
+
import type { ModelType, OptionalId } from './model.ts';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Bulk operation. Each operation has a single action and payload
|
package/src/types/crud.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Class } from '@travetto/runtime';
|
|
2
2
|
|
|
3
|
-
import type { ModelType, OptionalId } from '
|
|
3
|
+
import type { ModelListOptions, ModelType, OptionalId } from './model.ts';
|
|
4
4
|
|
|
5
5
|
import type { ModelBasicSupport } from './basic.ts';
|
|
6
6
|
|
|
@@ -38,7 +38,12 @@ export interface ModelCrudSupport extends ModelBasicSupport {
|
|
|
38
38
|
updatePartial<T extends ModelType>(cls: Class<T>, item: Partial<T> & { id: string }, view?: string): Promise<T>;
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* List all items
|
|
41
|
+
* List all items of a collection, results returned in batches of items.
|
|
42
|
+
*
|
|
43
|
+
* Note: Batch size hint can be used to optimize batch size, but is not guaranteed.
|
|
44
|
+
*
|
|
45
|
+
* @param cls The class to list
|
|
46
|
+
* @param options Options for listing
|
|
42
47
|
*/
|
|
43
|
-
list<T extends ModelType>(cls: Class<T
|
|
48
|
+
list<T extends ModelType>(cls: Class<T>, options?: ModelListOptions): AsyncIterable<T[]>;
|
|
44
49
|
}
|
package/src/types/expiry.ts
CHANGED
package/src/types/model.ts
CHANGED
|
@@ -16,4 +16,13 @@ export interface ModelType {
|
|
|
16
16
|
id: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export type OptionalId<T extends ModelType> = Omit<T, 'id'> & { id?: string };
|
|
19
|
+
export type OptionalId<T extends ModelType> = Omit<T, 'id'> & { id?: string };
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Options for listing items
|
|
23
|
+
*/
|
|
24
|
+
export interface ModelListOptions {
|
|
25
|
+
abort?: AbortSignal;
|
|
26
|
+
limit?: number;
|
|
27
|
+
batchSizeHint?: number;
|
|
28
|
+
}
|