@travetto/model 5.0.0-rc.1 → 5.0.0-rc.10

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 (39) hide show
  1. package/README.md +1 -2
  2. package/package.json +7 -7
  3. package/src/error/exists.ts +1 -1
  4. package/src/error/invalid-index.ts +1 -1
  5. package/src/error/invalid-sub-type.ts +1 -1
  6. package/src/error/not-found.ts +1 -1
  7. package/src/internal/service/bulk.ts +1 -1
  8. package/src/internal/service/common.ts +16 -22
  9. package/src/internal/service/crud.ts +15 -21
  10. package/src/internal/service/expiry.ts +2 -5
  11. package/src/internal/service/indexed.ts +13 -25
  12. package/src/internal/service/storage.ts +3 -7
  13. package/src/internal/service/stream.ts +1 -1
  14. package/src/provider/file.ts +3 -5
  15. package/src/provider/memory.ts +4 -6
  16. package/src/registry/decorator.ts +7 -13
  17. package/src/registry/model.ts +13 -8
  18. package/src/registry/types.ts +1 -2
  19. package/src/service/basic.ts +1 -1
  20. package/src/service/bulk.ts +1 -1
  21. package/src/service/crud.ts +1 -1
  22. package/src/service/expiry.ts +1 -1
  23. package/src/service/indexed.ts +2 -2
  24. package/src/service/storage.ts +1 -1
  25. package/src/service/stream.ts +2 -2
  26. package/support/base-command.ts +1 -1
  27. package/support/bin/candidate.ts +2 -3
  28. package/support/bin/export.ts +1 -1
  29. package/support/bin/install.ts +1 -1
  30. package/support/cli.model_export.ts +1 -1
  31. package/support/cli.model_install.ts +1 -1
  32. package/support/doc.support.tsx +4 -10
  33. package/support/test/base.ts +3 -3
  34. package/support/test/crud.ts +5 -4
  35. package/support/test/expiry.ts +1 -1
  36. package/support/test/indexed.ts +1 -1
  37. package/support/test/polymorphism.ts +7 -6
  38. package/support/test/stream.ts +14 -11
  39. package/support/test/suite.ts +1 -1
package/README.md CHANGED
@@ -235,8 +235,7 @@ In addition to the provided contracts, the module also provides common utilities
235
235
  ```typescript
236
236
  import { Readable } from 'node:stream';
237
237
  import { buffer as toBuffer } from 'node:stream/consumers';
238
- import { Class, TimeSpan } from '@travetto/base';
239
- import { DeepPartial } from '@travetto/schema';
238
+ import { Class, TimeSpan, DeepPartial, castTo } from '@travetto/runtime';
240
239
  import { Injectable } from '@travetto/di';
241
240
  import { Config } from '@travetto/config';
242
241
  import { ModelCrudSupport } from '../service/crud';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/model",
3
- "version": "5.0.0-rc.1",
3
+ "version": "5.0.0-rc.10",
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": "^5.0.0-rc.1",
30
- "@travetto/di": "^5.0.0-rc.0",
31
- "@travetto/registry": "^5.0.0-rc.1",
32
- "@travetto/schema": "^5.0.0-rc.0"
29
+ "@travetto/config": "^5.0.0-rc.10",
30
+ "@travetto/di": "^5.0.0-rc.9",
31
+ "@travetto/registry": "^5.0.0-rc.9",
32
+ "@travetto/schema": "^5.0.0-rc.10"
33
33
  },
34
34
  "peerDependencies": {
35
- "@travetto/cli": "^5.0.0-rc.1",
36
- "@travetto/test": "^5.0.0-rc.1"
35
+ "@travetto/cli": "^5.0.0-rc.10",
36
+ "@travetto/test": "^5.0.0-rc.9"
37
37
  },
38
38
  "peerDependenciesMeta": {
39
39
  "@travetto/cli": {
@@ -1,4 +1,4 @@
1
- import { Class, AppError } from '@travetto/base';
1
+ import { Class, AppError } from '@travetto/runtime';
2
2
 
3
3
  /**
4
4
  * Represents when a data item already exists
@@ -1,4 +1,4 @@
1
- import { Class, AppError } from '@travetto/base';
1
+ import { Class, AppError } from '@travetto/runtime';
2
2
 
3
3
  import { IndexConfig } from '../registry/types';
4
4
  import { ModelType } from '../types/model';
@@ -1,4 +1,4 @@
1
- import { Class, AppError } from '@travetto/base';
1
+ import { Class, AppError } from '@travetto/runtime';
2
2
 
3
3
  /**
4
4
  * Represents when a model subtype class is unable to be used directly
@@ -1,4 +1,4 @@
1
- import { Class, AppError } from '@travetto/base';
1
+ import { Class, AppError } from '@travetto/runtime';
2
2
 
3
3
  /**
4
4
  * Represents when a model of cls and id cannot be found
@@ -1,4 +1,4 @@
1
- import { Class } from '@travetto/base';
1
+ import { Class } from '@travetto/runtime';
2
2
 
3
3
  import { BulkOp } from '../../service/bulk';
4
4
  import { ModelType } from '../../types/model';
@@ -1,3 +1,4 @@
1
+ import { ClassInstance } from '@travetto/runtime';
1
2
  import type { ModelBulkSupport } from '../../service/bulk';
2
3
  import { ModelCrudSupport } from '../../service/crud';
3
4
  import type { ModelExpirySupport } from '../../service/expiry';
@@ -17,62 +18,55 @@ export class ModelIndexedSupportTarget { }
17
18
  * Type guard for determining if service supports basic operations
18
19
  * @param o
19
20
  */
20
- export function isBasicSupported(o: unknown): o is ModelBulkSupport {
21
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
22
- return !!o && !!(o as Record<string, unknown>)['create'];
21
+ export function isBasicSupported(o: ClassInstance): o is ModelBulkSupport {
22
+ return !!o && 'create' in o;
23
23
  }
24
24
 
25
25
  /**
26
26
  * Type guard for determining if service supports crud operations
27
27
  * @param o
28
28
  */
29
- export function isCrudSupported(o: unknown): o is ModelCrudSupport {
30
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
31
- return !!o && !!(o as Record<string, unknown>)['upsert'];
29
+ export function isCrudSupported(o: ClassInstance): o is ModelCrudSupport {
30
+ return !!o && 'upsert' in o;
32
31
  }
33
32
 
34
33
  /**
35
- * Type guard for determining if model is expirable
34
+ * Type guard for determining if model supports expiry
36
35
  * @param o
37
36
  */
38
- export function isExpirySupported(o: unknown): o is ModelExpirySupport {
39
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
40
- return !!o && !!(o as Record<string, unknown>)['deleteExpired'];
37
+ export function isExpirySupported(o: ClassInstance): o is ModelExpirySupport {
38
+ return !!o && 'deleteExpired' in o;
41
39
  }
42
40
 
43
41
  /**
44
42
  * Type guard for determining if service supports storage operation
45
43
  * @param o
46
44
  */
47
- export function isStorageSupported(o: unknown): o is ModelStorageSupport {
48
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
49
- return !!o && !!(o as Record<string, unknown>)['createStorage'];
45
+ export function isStorageSupported(o: ClassInstance): o is ModelStorageSupport {
46
+ return !!o && 'createStorage' in o;
50
47
  }
51
48
 
52
49
  /**
53
50
  * Type guard for determining if service supports streaming operation
54
51
  * @param o
55
52
  */
56
- export function isStreamSupported(o: unknown): o is ModelStreamSupport {
57
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
58
- return !!o && !!(o as Record<string, unknown>)['getStream'];
53
+ export function isStreamSupported(o: ClassInstance): o is ModelStreamSupport {
54
+ return !!o && 'getStream' in o;
59
55
  }
60
56
 
61
57
  /**
62
58
  * Type guard for determining if service supports streaming operation
63
59
  * @param o
64
60
  */
65
- export function isBulkSupported(o: unknown): o is ModelBulkSupport {
66
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
67
- return !!o && !!(o as Record<string, unknown>)['processBulk'];
61
+ export function isBulkSupported(o: ClassInstance): o is ModelBulkSupport {
62
+ return !!o && 'processBulk' in o;
68
63
  }
69
64
 
70
65
  /**
71
66
  * Type guard for determining if service supports indexed operation
72
67
  * @param o
73
68
  */
74
- export function isIndexedSupported(o: unknown): o is ModelIndexedSupport {
75
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
76
- return !!o && !!(o as Record<string, unknown>)['getByIndex'];
69
+ export function isIndexedSupported(o: ClassInstance): o is ModelIndexedSupport {
70
+ return !!o && 'getByIndex' in o;
77
71
  }
78
72
 
@@ -1,6 +1,6 @@
1
1
  import crypto from 'node:crypto';
2
2
 
3
- import { Class, Util } from '@travetto/base';
3
+ import { castTo, Class, asFull, Util, asConstructable } from '@travetto/runtime';
4
4
  import { DataUtil, SchemaRegistry, SchemaValidator, ValidationError, ValidationResultError } from '@travetto/schema';
5
5
 
6
6
  import { ModelRegistry } from '../../registry/model';
@@ -46,14 +46,16 @@ export class ModelCrudUtil {
46
46
  * @param input Input as string or plain object
47
47
  */
48
48
  static async load<T extends ModelType>(cls: Class<T>, input: Buffer | string | object, onTypeMismatch: 'notfound' | 'exists' = 'notfound'): Promise<T> {
49
+ let resolvedInput: object;
49
50
  if (typeof input === 'string') {
50
- input = JSON.parse(input);
51
+ resolvedInput = JSON.parse(input);
51
52
  } else if (input instanceof Buffer) {
52
- input = JSON.parse(input.toString('utf8'));
53
+ resolvedInput = JSON.parse(input.toString('utf8'));
54
+ } else {
55
+ resolvedInput = input;
53
56
  }
54
57
 
55
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
56
- const result = ModelRegistry.getBaseModel(cls).from(input as object) as T;
58
+ const result = ModelRegistry.getBaseModel(cls).from(resolvedInput);
57
59
 
58
60
  if (!(result instanceof cls || result.constructor.Ⲑid === cls.Ⲑid)) {
59
61
  if (onTypeMismatch === 'notfound') {
@@ -78,12 +80,10 @@ export class ModelCrudUtil {
78
80
  }
79
81
 
80
82
  if (DataUtil.isPlainObject(item)) {
81
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
82
- item = cls.from(item as object);
83
+ item = cls.from(castTo(item));
83
84
  }
84
85
 
85
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
86
- const config = ModelRegistry.get(item.constructor as Class<T>);
86
+ const config = ModelRegistry.get(asConstructable(item).constructor);
87
87
  if (config.subType) { // Sub-typing, assign type
88
88
  SchemaRegistry.ensureInstanceTypeField(cls, item);
89
89
  }
@@ -106,8 +106,7 @@ export class ModelCrudUtil {
106
106
  if (errors.length) {
107
107
  throw new ValidationResultError(errors);
108
108
  }
109
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
110
- return item as T;
109
+ return castTo(item);
111
110
  }
112
111
 
113
112
  /**
@@ -119,12 +118,10 @@ export class ModelCrudUtil {
119
118
  */
120
119
  static async naivePartialUpdate<T extends ModelType>(cls: Class<T>, item: Partial<T>, view: undefined | string, getExisting: () => Promise<T>): Promise<T> {
121
120
  if (DataUtil.isPlainObject(item)) {
122
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
123
- item = cls.from(item as object);
121
+ item = cls.from(castTo(item));
124
122
  }
125
123
 
126
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
127
- const config = ModelRegistry.get(item.constructor as Class<T>);
124
+ const config = ModelRegistry.get(asConstructable(item).constructor);
128
125
  if (config.subType) { // Sub-typing, assign type
129
126
  SchemaRegistry.ensureInstanceTypeField(cls, item);
130
127
  }
@@ -139,8 +136,7 @@ export class ModelCrudUtil {
139
136
 
140
137
  item = await this.prePersist(cls, item, 'partial');
141
138
 
142
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
143
- return item as T;
139
+ return asFull(item);
144
140
  }
145
141
 
146
142
  /**
@@ -159,8 +155,7 @@ export class ModelCrudUtil {
159
155
  const config = ModelRegistry.get(cls);
160
156
  for (const state of (config.prePersist ?? [])) {
161
157
  if (state.scope === scope || scope === 'all' || state.scope === 'all') {
162
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
163
- const handler = state.handler as unknown as DataHandler<T>;
158
+ const handler: DataHandler<T> = castTo(state.handler);
164
159
  item = await handler(item) ?? item;
165
160
  }
166
161
  }
@@ -175,8 +170,7 @@ export class ModelCrudUtil {
175
170
  */
176
171
  static async postLoad<T>(cls: Class<T>, item: T): Promise<T> {
177
172
  const config = ModelRegistry.get(cls);
178
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
179
- for (const handler of (config.postLoad ?? []) as unknown as DataHandler<T>[]) {
173
+ for (const handler of castTo<DataHandler<T>[]>(config.postLoad ?? [])) {
180
174
  item = await handler(item) ?? item;
181
175
  }
182
176
  if (typeof item === 'object' && item && 'postLoad' in item && typeof item['postLoad'] === 'function') {
@@ -1,4 +1,4 @@
1
- import { ShutdownManager, Class, TimeSpan, TimeUtil, Util } from '@travetto/base';
1
+ import { ShutdownManager, Class, TimeSpan, TimeUtil, Util, castTo } from '@travetto/runtime';
2
2
 
3
3
  import { ModelRegistry } from '../../registry/model';
4
4
  import { ModelExpirySupport } from '../../service/expiry';
@@ -15,10 +15,7 @@ export class ModelExpiryUtil {
15
15
  */
16
16
  static getExpiryState<T extends ModelType>(cls: Class<T>, item: T): { expiresAt?: Date, expired?: boolean } {
17
17
  const expKey = ModelRegistry.getExpiry(cls);
18
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
19
- const keyAsT = expKey as keyof T;
20
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
21
- const expiresAt = item[keyAsT] ? item[keyAsT] as unknown as Date : undefined;
18
+ const expiresAt: Date = castTo(item[expKey]);
22
19
 
23
20
  return {
24
21
  expiresAt,
@@ -1,5 +1,4 @@
1
- import { Class } from '@travetto/base';
2
- import { DeepPartial } from '@travetto/schema';
1
+ import { castTo, Class, DeepPartial, TypedObject } from '@travetto/runtime';
3
2
 
4
3
  import { IndexNotSupported } from '../../error/invalid-index';
5
4
  import { NotFoundError } from '../../error/not-found';
@@ -45,38 +44,30 @@ export class ModelIndexedUtil {
45
44
  const parts = [];
46
45
 
47
46
  while (o !== undefined && o !== null) {
48
- const k = Object.keys(f)[0];
49
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
50
- o = (o[k] as Record<string, unknown>);
47
+ const k = TypedObject.keys(f)[0];
48
+ o = castTo(o[k]);
51
49
  parts.push(k);
52
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
53
- const fk = k as (keyof typeof f);
54
- if (typeof f[fk] === 'boolean' || typeof f[fk] === 'number') {
50
+ if (typeof f[k] === 'boolean' || typeof f[k] === 'number') {
55
51
  if (cfg.type === 'sorted') {
56
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
57
- sortDir = f[fk] === true ? 1 : f[fk] as number;
52
+ sortDir = f[k] === true ? 1 : f[k] === false ? 0 : f[k];
58
53
  }
59
54
  break; // At the bottom
60
55
  } else {
61
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62
- f = f[fk] as Record<string, unknown>;
56
+ f = castTo(f[k]);
63
57
  }
64
58
  }
65
59
  if (field === sortField) {
66
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
67
- sorted = { path: parts, dir: sortDir, value: o as unknown as number | Date };
60
+ sorted = { path: parts, dir: sortDir, value: castTo(o) };
68
61
  }
69
62
  if (o === undefined || o === null) {
70
63
  const empty = field === sortField ? opts.emptySortValue : opts.emptyValue;
71
64
  if (empty === undefined || empty === Error) {
72
65
  throw new IndexNotSupported(cls, cfg, `Missing field value for ${parts.join('.')}`);
73
66
  }
74
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
75
- o = empty as Record<string, unknown>;
67
+ o = castTo(empty!);
76
68
  } else {
77
69
  if (field !== sortField || (opts.includeSortInFields ?? true)) {
78
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
79
- fields.push({ path: parts, value: o as unknown as string | boolean | Date | number });
70
+ fields.push({ path: parts, value: castTo(o) });
80
71
  }
81
72
  }
82
73
  }
@@ -93,12 +84,11 @@ export class ModelIndexedUtil {
93
84
  static projectIndex<T extends ModelType>(cls: Class<T>, idx: IndexConfig<T> | string, item?: DeepPartial<T>, cfg?: ComputeConfig): Record<string, unknown> {
94
85
  const res: Record<string, unknown> = {};
95
86
  for (const { path, value } of this.computeIndexParts(cls, idx, item ?? {}, cfg).fields) {
96
- let sub = res;
87
+ let sub: Record<string, unknown> = res;
97
88
  const all = path.slice(0);
98
89
  const last = all.pop()!;
99
90
  for (const k of all) {
100
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
101
- sub = (sub[k] ??= {}) as typeof res;
91
+ sub = castTo(sub[k] ??= {});
102
92
  }
103
93
  sub[last] = value;
104
94
  }
@@ -135,11 +125,9 @@ export class ModelIndexedUtil {
135
125
  cls: Class<T>, idx: string, body: OptionalId<T>
136
126
  ): Promise<T> {
137
127
  try {
138
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
139
- const { id } = await service.getByIndex(cls, idx, body as DeepPartial<T>);
128
+ const { id } = await service.getByIndex(cls, idx, castTo(body));
140
129
  body.id = id;
141
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
142
- return await service.update(cls, body as T);
130
+ return await service.update(cls, castTo(body));
143
131
  } catch (err) {
144
132
  if (err instanceof NotFoundError) {
145
133
  return await service.create(cls, body);
@@ -1,4 +1,4 @@
1
- import { Class, Env } from '@travetto/base';
1
+ import { Class, Runtime } from '@travetto/runtime';
2
2
  import { SchemaChangeListener } from '@travetto/schema';
3
3
 
4
4
  import { ModelRegistry } from '../../registry/model';
@@ -12,15 +12,11 @@ export class ModelStorageUtil {
12
12
  /**
13
13
  * Register change listener on startup
14
14
  */
15
- static async registerModelChangeListener(storage: ModelStorageSupport, target?: Class): Promise<void> {
16
- if (!Env.dynamic || !(storage?.config?.autoCreate ?? !Env.production)) {
15
+ static async registerModelChangeListener(storage: ModelStorageSupport): Promise<void> {
16
+ if (!Runtime.dynamic || !(storage?.config?.autoCreate ?? !Runtime.production)) {
17
17
  return;
18
18
  }
19
19
 
20
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
21
- target = target ?? storage.constructor as Class<ModelStorageSupport>;
22
-
23
-
24
20
  const checkType = (cls: Class, enforceBase = true): boolean => {
25
21
  if (enforceBase && ModelRegistry.getBaseModel(cls) !== cls) {
26
22
  return false;
@@ -1,4 +1,4 @@
1
- import { AppError, Class } from '@travetto/base';
1
+ import { AppError, Class } from '@travetto/runtime';
2
2
 
3
3
  import { ModelType } from '../../types/model';
4
4
  import { StreamRange } from '../../service/stream';
@@ -5,7 +5,7 @@ import { Readable } from 'node:stream';
5
5
  import { pipeline } from 'node:stream/promises';
6
6
  import path from 'node:path';
7
7
 
8
- import { Class, TimeSpan, RuntimeContext } from '@travetto/base';
8
+ import { Class, TimeSpan, Runtime, asFull } from '@travetto/runtime';
9
9
  import { Injectable } from '@travetto/di';
10
10
  import { Config } from '@travetto/config';
11
11
  import { Required } from '@travetto/schema';
@@ -36,7 +36,7 @@ export class FileModelConfig {
36
36
  cullRate?: number | TimeSpan;
37
37
 
38
38
  async postConstruct(): Promise<void> {
39
- this.folder ??= path.resolve(os.tmpdir(), `trv_file_${RuntimeContext.main.name.replace(/[^a-z]/ig, '_')}`);
39
+ this.folder ??= path.resolve(os.tmpdir(), `trv_file_${Runtime.main.name.replace(/[^a-z]/ig, '_')}`);
40
40
  }
41
41
  }
42
42
 
@@ -153,9 +153,7 @@ export class FileModelService implements ModelCrudSupport, ModelStreamSupport, M
153
153
  item = await ModelCrudUtil.naivePartialUpdate(cls, item, view, () => this.get(cls, id));
154
154
  const file = await this.#resolveName(cls, '.json', item.id);
155
155
  await fs.writeFile(file, JSON.stringify(item), { encoding: 'utf8' });
156
-
157
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
158
- return item as T;
156
+ return asFull<T>(item);
159
157
  }
160
158
 
161
159
  async delete<T extends ModelType>(cls: Class<T>, id: string): Promise<void> {
@@ -1,8 +1,7 @@
1
1
  import { Readable } from 'node:stream';
2
2
  import { buffer as toBuffer } from 'node:stream/consumers';
3
3
 
4
- import { Class, TimeSpan } from '@travetto/base';
5
- import { DeepPartial } from '@travetto/schema';
4
+ import { Class, TimeSpan, DeepPartial, castTo } from '@travetto/runtime';
6
5
  import { Injectable } from '@travetto/di';
7
6
  import { Config } from '@travetto/config';
8
7
 
@@ -26,6 +25,7 @@ const STREAM_META = `${STREAMS}_meta`;
26
25
 
27
26
  type StoreType = Map<string, Buffer>;
28
27
 
28
+
29
29
  @Config('model.memory')
30
30
  export class MemoryModelConfig {
31
31
  autoCreate?: boolean = true;
@@ -87,8 +87,7 @@ export class MemoryModelService implements ModelCrudSupport, ModelStreamSupport,
87
87
  const item = await this.get(cls, id);
88
88
  for (const idx of ModelRegistry.getIndices(cls, ['sorted', 'unsorted'])) {
89
89
  const idxName = indexName(cls, idx);
90
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
91
- const { key } = ModelIndexedUtil.computeIndexKey(cls, idx, item as DeepPartial<T>);
90
+ const { key } = ModelIndexedUtil.computeIndexKey(cls, idx, castTo(item));
92
91
  this.#indices[idx.type].get(idxName)?.get(key)?.delete(id);
93
92
  }
94
93
  } catch (err) {
@@ -101,8 +100,7 @@ export class MemoryModelService implements ModelCrudSupport, ModelStreamSupport,
101
100
  async #writeIndices<T extends ModelType>(cls: Class<T>, item: T): Promise<void> {
102
101
  for (const idx of ModelRegistry.getIndices(cls, ['sorted', 'unsorted'])) {
103
102
  const idxName = indexName(cls, idx);
104
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
105
- const { key, sort } = ModelIndexedUtil.computeIndexKey(cls, idx, item as DeepPartial<T>);
103
+ const { key, sort } = ModelIndexedUtil.computeIndexKey(cls, idx, castTo(item));
106
104
  let index = this.#indices[idx.type].get(idxName)?.get(key);
107
105
 
108
106
  if (!index) {
@@ -1,4 +1,4 @@
1
- import { Class } from '@travetto/base';
1
+ import { asConstructable, castTo, Class } from '@travetto/runtime';
2
2
  import { SchemaRegistry } from '@travetto/schema';
3
3
 
4
4
  import { ModelType } from '../types/model';
@@ -24,8 +24,7 @@ export function Model(conf: Partial<ModelOptions<ModelType>> | string = {}) {
24
24
  /**
25
25
  * Defines an index on a model
26
26
  */
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
- export function Index<T>(...indices: IndexConfig<any>[]) {
27
+ export function Index<T extends ModelType>(...indices: IndexConfig<T>[]) {
29
28
  return function (target: Class<T>): void {
30
29
  ModelRegistry.getOrCreatePending(target).indices!.push(...indices);
31
30
  };
@@ -37,8 +36,7 @@ export function Index<T>(...indices: IndexConfig<any>[]) {
37
36
  */
38
37
  export function ExpiresAt() {
39
38
  return <K extends string, T extends Partial<Record<K, Date>>>(tgt: T, prop: K): void => {
40
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
41
- ModelRegistry.register(tgt.constructor as Class<T>, { expiresAt: prop });
39
+ ModelRegistry.register(asConstructable(tgt).constructor, { expiresAt: prop });
42
40
  };
43
41
  }
44
42
 
@@ -50,8 +48,7 @@ export function PrePersist<T>(handler: DataHandler<T>, scope: PrePersistScope =
50
48
  ModelRegistry.registerDataHandlers(tgt, {
51
49
  prePersist: [{
52
50
  scope,
53
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
54
- handler: handler as DataHandler
51
+ handler: castTo(handler)
55
52
  }]
56
53
  });
57
54
  };
@@ -62,13 +59,11 @@ export function PrePersist<T>(handler: DataHandler<T>, scope: PrePersistScope =
62
59
  */
63
60
  export function PersistValue<T>(handler: (curr: T | undefined) => T, scope: PrePersistScope = 'all') {
64
61
  return function <K extends string, C extends Partial<Record<K, T>>>(tgt: C, prop: K): void {
65
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
66
- ModelRegistry.registerDataHandlers(tgt.constructor as Class<C>, {
62
+ ModelRegistry.registerDataHandlers(asConstructable(tgt).constructor, {
67
63
  prePersist: [{
68
64
  scope,
69
65
  handler: (inst): void => {
70
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
71
- const cInst = (inst as unknown as Record<K, T>);
66
+ const cInst: Record<K, T> = castTo(inst);
72
67
  cInst[prop] = handler(cInst[prop]);
73
68
  }
74
69
  }]
@@ -82,7 +77,6 @@ export function PersistValue<T>(handler: (curr: T | undefined) => T, scope: PreP
82
77
  */
83
78
  export function PostLoad<T>(handler: DataHandler<T>) {
84
79
  return function (tgt: Class<T>): void {
85
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
86
- ModelRegistry.registerDataHandlers(tgt, { postLoad: [handler as DataHandler] });
80
+ ModelRegistry.registerDataHandlers(tgt, { postLoad: [castTo(handler)] });
87
81
  };
88
82
  }
@@ -1,8 +1,7 @@
1
- import { RuntimeIndex } from '@travetto/manifest';
2
1
  import { SchemaRegistry } from '@travetto/schema';
3
2
  import { MetadataRegistry } from '@travetto/registry';
4
3
  import { DependencyRegistry } from '@travetto/di';
5
- import { AppError, Class } from '@travetto/base';
4
+ import { AppError, castTo, Class, describeFunction, asFull } from '@travetto/runtime';
6
5
  import { AllViewⲐ } from '@travetto/schema/src/internal/types';
7
6
 
8
7
  import { IndexConfig, IndexType, ModelOptions } from './types';
@@ -52,7 +51,14 @@ class $ModelRegistry extends MetadataRegistry<ModelOptions<ModelType>> {
52
51
  }
53
52
 
54
53
  createPending(cls: Class): Partial<ModelOptions<ModelType>> {
55
- return { class: cls, indices: [], autoCreate: true, baseType: RuntimeIndex.getFunctionMetadata(cls)?.abstract, postLoad: [], prePersist: [] };
54
+ return {
55
+ class: cls,
56
+ indices: [],
57
+ autoCreate: true,
58
+ baseType: describeFunction(cls).abstract,
59
+ postLoad: [],
60
+ prePersist: []
61
+ };
56
62
  }
57
63
 
58
64
  registerDataHandlers(cls: Class, pConfig?: Partial<ModelOptions<ModelType>>): void {
@@ -65,8 +71,7 @@ class $ModelRegistry extends MetadataRegistry<ModelOptions<ModelType>> {
65
71
  }
66
72
 
67
73
  onInstallFinalize(cls: Class): ModelOptions<ModelType> {
68
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
69
- const config = this.pending.get(cls.Ⲑid)! as ModelOptions<ModelType>;
74
+ const config = asFull(this.pending.get(cls.Ⲑid)!);
70
75
 
71
76
  const schema = SchemaRegistry.get(cls);
72
77
  const view = schema.views[AllViewⲐ].schema;
@@ -97,7 +102,7 @@ class $ModelRegistry extends MetadataRegistry<ModelOptions<ModelType>> {
97
102
  /**
98
103
  * Find base class for a given model
99
104
  */
100
- getBaseModel(cls: Class): Class<ModelType> {
105
+ getBaseModel<T extends ModelType>(cls: Class<T>): Class<T> {
101
106
  if (!this.baseModels.has(cls)) {
102
107
  let conf = this.get(cls) ?? this.getOrCreatePending(cls);
103
108
  let parent = cls;
@@ -202,12 +207,12 @@ class $ModelRegistry extends MetadataRegistry<ModelOptions<ModelType>> {
202
207
  * Get expiry field
203
208
  * @param cls
204
209
  */
205
- getExpiry(cls: Class): string {
210
+ getExpiry<T extends ModelType>(cls: Class<T>): keyof T {
206
211
  const expiry = this.get(cls).expiresAt;
207
212
  if (!expiry) {
208
213
  throw new AppError(`${cls.name} is not configured with expiry support, please use @ExpiresAt to declare expiration behavior`, 'general');
209
214
  }
210
- return expiry;
215
+ return castTo(expiry);
211
216
  }
212
217
  }
213
218
 
@@ -1,5 +1,4 @@
1
- import { Class } from '@travetto/base';
2
- import { Primitive } from '@travetto/schema';
1
+ import type { Class, Primitive } from '@travetto/runtime';
3
2
 
4
3
  import { ModelType } from '../types/model';
5
4
 
@@ -1,4 +1,4 @@
1
- import { Class } from '@travetto/base';
1
+ import { Class } from '@travetto/runtime';
2
2
  import { ModelType, OptionalId } from '../types/model';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { Class, AppError } from '@travetto/base';
1
+ import { Class, AppError } from '@travetto/runtime';
2
2
  import { ValidationResultError } from '@travetto/schema';
3
3
 
4
4
  import { ModelCrudSupport } from './crud';
@@ -1,4 +1,4 @@
1
- import { Class } from '@travetto/base';
1
+ import { Class } from '@travetto/runtime';
2
2
 
3
3
  import { ModelType, OptionalId, ModelIdSource } from '../types/model';
4
4
 
@@ -1,4 +1,4 @@
1
- import { Class } from '@travetto/base';
1
+ import { Class } from '@travetto/runtime';
2
2
 
3
3
  import { ModelType } from '../types/model';
4
4
  import { ModelCrudSupport } from './crud';
@@ -1,5 +1,4 @@
1
- import { Class } from '@travetto/base';
2
- import { DeepPartial } from '@travetto/schema';
1
+ import { Class, DeepPartial } from '@travetto/runtime';
3
2
 
4
3
  import { ModelType, OptionalId } from '../types/model';
5
4
  import { ModelBasicSupport } from './basic';
@@ -7,6 +6,7 @@ import { ModelBasicSupport } from './basic';
7
6
  /**
8
7
  * Support for simple indexed activity
9
8
  *
9
+ *
10
10
  * @concrete ../internal/service/common#ModelIndexedSupportTarget
11
11
  */
12
12
  export interface ModelIndexedSupport extends ModelBasicSupport {
@@ -1,4 +1,4 @@
1
- import { Class } from '@travetto/base';
1
+ import { Class } from '@travetto/runtime';
2
2
  import { SchemaChange } from '@travetto/schema';
3
3
 
4
4
  import { ModelType } from '../types/model';
@@ -12,11 +12,11 @@ export interface StreamMeta {
12
12
  /**
13
13
  * Hash of the file contents. Different files with the same name, will have the same hash
14
14
  */
15
- hash: string;
15
+ hash?: string;
16
16
  /**
17
17
  * The original base filename of the file
18
18
  */
19
- filename: string;
19
+ filename?: string;
20
20
  /**
21
21
  * Filenames title, optional for elements like images, audio, videos
22
22
  */
@@ -1,4 +1,4 @@
1
- import { Env } from '@travetto/base';
1
+ import { Env } from '@travetto/runtime';
2
2
  import { CliValidationError, CliCommandShape, cliTpl } from '@travetto/cli';
3
3
  import { RootRegistry } from '@travetto/registry';
4
4
 
@@ -1,4 +1,4 @@
1
- import { Class } from '@travetto/base';
1
+ import { castTo, Class } from '@travetto/runtime';
2
2
  import { ModelRegistry } from '@travetto/model/src/registry/model';
3
3
  import { InjectableConfig, DependencyRegistry } from '@travetto/di';
4
4
  import { ModelStorageSupportTarget } from '@travetto/model/src/internal/service/common';
@@ -40,8 +40,7 @@ export class ModelCandidateUtil {
40
40
  * Get all providers that are viable candidates
41
41
  */
42
42
  static async getProviders(op?: keyof ModelStorageSupport): Promise<InjectableConfig[]> {
43
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
44
- const types = DependencyRegistry.getCandidateTypes<ModelStorageSupport>(ModelStorageSupportTarget as unknown as Class<ModelStorageSupport>);
43
+ const types = DependencyRegistry.getCandidateTypes<ModelStorageSupport>(castTo(ModelStorageSupportTarget));
45
44
  return types.filter(x => !op || x.class.prototype?.[op]);
46
45
  }
47
46
 
@@ -1,4 +1,4 @@
1
- import type { Class } from '@travetto/base';
1
+ import type { Class } from '@travetto/runtime';
2
2
  import type { ModelStorageSupport } from '@travetto/model/src/service/storage';
3
3
  import type { ModelType } from '@travetto/model/src/types/model';
4
4
 
@@ -1,4 +1,4 @@
1
- import type { Class } from '@travetto/base';
1
+ import type { Class } from '@travetto/runtime';
2
2
  import type { ModelStorageSupport } from '@travetto/model/src/service/storage';
3
3
  import type { ModelType } from '@travetto/model/src/types/model';
4
4
 
@@ -7,7 +7,7 @@ import { ModelCandidateUtil } from './bin/candidate';
7
7
  /**
8
8
  * Exports model schemas
9
9
  */
10
- @CliCommand({ addEnv: true, addModule: true })
10
+ @CliCommand({ with: { env: true, module: true } })
11
11
  export class ModelExportCommand extends BaseModelCommand {
12
12
 
13
13
  getOp(): 'exportModel' { return 'exportModel'; }
@@ -7,7 +7,7 @@ import { ModelCandidateUtil } from './bin/candidate';
7
7
  /**
8
8
  * Installing models
9
9
  */
10
- @CliCommand({ addEnv: true, addModule: true })
10
+ @CliCommand({ with: { env: true, module: true } })
11
11
  export class ModelInstallCommand extends BaseModelCommand {
12
12
 
13
13
  getOp(): 'createModel' { return 'createModel'; }
@@ -1,8 +1,5 @@
1
1
  /** @jsxImportSource @travetto/doc */
2
- import { readFileSync } from 'node:fs';
3
-
4
- import { RuntimeIndex } from '@travetto/manifest';
5
- import { d, c, DocJSXElementByFn, DocJSXElement } from '@travetto/doc';
2
+ import { d, c, DocJSXElementByFn, DocJSXElement, DocFileUtil } from '@travetto/doc';
6
3
  import { Config } from '@travetto/config';
7
4
 
8
5
  export const Links = {
@@ -14,14 +11,11 @@ export const Links = {
14
11
  Stream: d.codeLink('Streaming', '@travetto/model/src/service/stream.ts', /export interface/),
15
12
  };
16
13
 
17
- export const ModelTypes = (file: string | Function): DocJSXElement[] => {
18
- if (typeof file !== 'string') {
19
- file = RuntimeIndex.getFunctionMetadata(file)!.source;
20
- }
21
- const contents = readFileSync(file, 'utf8');
14
+ export const ModelTypes = (fn: | Function): DocJSXElement[] => {
15
+ const { content } = DocFileUtil.readSource(fn);
22
16
  const found: DocJSXElementByFn<'CodeLink'>[] = [];
23
17
  const seen = new Set();
24
- for (const [, key] of contents.matchAll(/Model(Crud|Expiry|Indexed|Bulk|Stream)Support/g)) {
18
+ for (const [, key] of content.matchAll(/Model(Crud|Expiry|Indexed|Bulk|Stream)Support/g)) {
25
19
  if (!seen.has(key)) {
26
20
  seen.add(key);
27
21
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
@@ -1,5 +1,5 @@
1
1
  import { DependencyRegistry } from '@travetto/di';
2
- import { AppError, Class } from '@travetto/base';
2
+ import { AppError, castTo, Class, classConstruct } from '@travetto/runtime';
3
3
 
4
4
  import { isBulkSupported, isCrudSupported } from '../../src/internal/service/common';
5
5
  import { ModelType } from '../../src/types/model';
@@ -11,7 +11,7 @@ type ServiceClass = { serviceClass: { new(): unknown } };
11
11
  export abstract class BaseModelSuite<T> {
12
12
 
13
13
  static ifNot(pred: (svc: unknown) => boolean): (x: unknown) => Promise<boolean> {
14
- return async (x: unknown) => !pred(new (x as ServiceClass).serviceClass());
14
+ return async (x: unknown) => !pred(classConstruct(castTo<ServiceClass>(x).serviceClass));
15
15
  }
16
16
 
17
17
  serviceClass: Class<T>;
@@ -36,7 +36,7 @@ export abstract class BaseModelSuite<T> {
36
36
  const res = await svc.processBulk(cls, items.map(x => ({ insert: x })));
37
37
  return res.counts.insert;
38
38
  } else if (isCrudSupported(svc)) {
39
- const out = [] as Promise<M>[];
39
+ const out: Promise<M>[] = [];
40
40
  for (const el of items) {
41
41
  out.push(svc.create(cls, el));
42
42
  }
@@ -1,4 +1,5 @@
1
1
  import assert from 'node:assert';
2
+ import timers from 'node:timers/promises';
2
3
 
3
4
  import { Suite, Test } from '@travetto/test';
4
5
  import { Schema, Text, Precision, Required, } from '@travetto/schema';
@@ -48,7 +49,7 @@ class User2 {
48
49
  name: string;
49
50
 
50
51
  prePersist() {
51
- this.name = `${this.name}-suff`;
52
+ this.name = `${this.name}-suffix`;
52
53
  }
53
54
  }
54
55
 
@@ -192,7 +193,7 @@ export abstract class ModelCrudSuite extends BaseModelSuite<ModelCrudSupport> {
192
193
  }));
193
194
 
194
195
  assert(o.address === undefined);
195
- assert(o.name === 'bob-suff');
196
+ assert(o.name === 'bob-suffix');
196
197
 
197
198
  await service.updatePartial(User2, User2.from({
198
199
  id: o.id,
@@ -216,7 +217,7 @@ export abstract class ModelCrudSuite extends BaseModelSuite<ModelCrudSupport> {
216
217
  assert(res.createdDate instanceof Date);
217
218
  }
218
219
 
219
- @Test('verify prepersist on create/update')
220
+ @Test('verify pre-persist on create/update')
220
221
  async testPrePersist() {
221
222
  const service = await this.service;
222
223
  const res = await service.create(Dated, Dated.from({}));
@@ -224,7 +225,7 @@ export abstract class ModelCrudSuite extends BaseModelSuite<ModelCrudSupport> {
224
225
  assert(res.createdDate instanceof Date);
225
226
  assert(res.updatedDate instanceof Date);
226
227
 
227
- await new Promise(r => setTimeout(r, 100));
228
+ await timers.setTimeout(100);
228
229
 
229
230
  const final = await service.updatePartial(Dated, { id: res.id });
230
231
  assert(final.createdDate instanceof Date);
@@ -2,7 +2,7 @@ import assert from 'node:assert';
2
2
  import timers from 'node:timers/promises';
3
3
 
4
4
  import { Suite, Test } from '@travetto/test';
5
- import { TimeSpan, TimeUnit, TimeUtil } from '@travetto/base';
5
+ import { TimeSpan, TimeUnit, TimeUtil } from '@travetto/runtime';
6
6
 
7
7
  import { ExpiresAt, Model } from '../../src/registry/decorator';
8
8
  import { ModelExpirySupport } from '../../src/service/expiry';
@@ -2,7 +2,7 @@ import assert from 'node:assert';
2
2
 
3
3
  import { Suite, Test } from '@travetto/test';
4
4
  import { Schema } from '@travetto/schema';
5
- import { TimeUtil } from '@travetto/base';
5
+ import { TimeUtil } from '@travetto/runtime';
6
6
 
7
7
  import { Index, Model } from '../../src/registry/decorator';
8
8
  import { ModelIndexedSupport } from '../../src/service/indexed';
@@ -12,6 +12,7 @@ import { isIndexedSupported } from '../../src/internal/service/common';
12
12
  import { ExistsError } from '../../src/error/exists';
13
13
 
14
14
  import { BaseModelSuite } from './base';
15
+ import { castTo } from '@travetto/runtime';
15
16
 
16
17
  @Model({ baseType: true })
17
18
  export class Worker {
@@ -70,7 +71,7 @@ export class IndexedEngineer extends IndexedWorker {
70
71
  }
71
72
 
72
73
  async function collect<T>(iterable: AsyncIterable<T>): Promise<T[]> {
73
- const out = [] as T[];
74
+ const out: T[] = [];
74
75
  for await (const el of iterable) {
75
76
  out.push(el);
76
77
  }
@@ -116,12 +117,12 @@ export abstract class ModelPolymorphismSuite extends BaseModelSuite<ModelCrudSup
116
117
 
117
118
  const fire3 = all.find(x => x instanceof Firefighter);
118
119
  assert(fire3 instanceof Firefighter);
119
- assert((fire3 as Firefighter).firehouse === 20);
120
+ assert(fire3.firehouse === 20);
120
121
  assert(fire3.name === 'rob');
121
122
 
122
123
  const eng3 = all.find(x => x instanceof Engineer);
123
124
  assert(eng3 instanceof Engineer);
124
- assert((eng3 as Engineer).major === 'oranges');
125
+ assert(eng3.major === 'oranges');
125
126
  assert(eng3.name === 'cob');
126
127
 
127
128
  const engineers = await collect(service.list(Engineer));
@@ -161,7 +162,7 @@ export abstract class ModelPolymorphismSuite extends BaseModelSuite<ModelCrudSup
161
162
  );
162
163
 
163
164
  await assert.rejects(
164
- () => service.update(Engineer, Doctor.from({ ...doc }) as unknown as Engineer),
165
+ () => service.update(Engineer, castTo(Doctor.from({ ...doc }))),
165
166
  (e: Error) => (e instanceof NotFoundError || e instanceof SubTypeNotSupportedError || e instanceof TypeMismatchError) ? undefined : e);
166
167
 
167
168
  await timers.setTimeout(15);
@@ -205,7 +206,7 @@ export abstract class ModelPolymorphismSuite extends BaseModelSuite<ModelCrudSup
205
206
 
206
207
  @Test('Polymorphic index', { skip: BaseModelSuite.ifNot(isIndexedSupported) })
207
208
  async polymorphicIndexGet() {
208
- const service = (await this.service) as unknown as ModelIndexedSupport;
209
+ const service: ModelIndexedSupport = castTo(await this.service);
209
210
  const now = 30;
210
211
  const [doc, fire, eng] = [
211
212
  IndexedDoctor.from({ name: 'bob', specialty: 'feet', age: now }),
@@ -235,7 +236,7 @@ export abstract class ModelPolymorphismSuite extends BaseModelSuite<ModelCrudSup
235
236
 
236
237
  @Test('Polymorphic index', { skip: BaseModelSuite.ifNot(isIndexedSupported) })
237
238
  async polymorphicIndexDelete() {
238
- const service = (await this.service) as unknown as ModelIndexedSupport;
239
+ const service: ModelIndexedSupport = castTo(await this.service);
239
240
  const now = 30;
240
241
  const [doc, fire, eng] = [
241
242
  IndexedDoctor.from({ name: 'bob', specialty: 'feet', age: now }),
@@ -3,7 +3,7 @@ import assert from 'node:assert';
3
3
  import crypto from 'node:crypto';
4
4
  import { Readable } from 'node:stream';
5
5
  import { pipeline } from 'node:stream/promises';
6
- import { buffer as toBuffer } from 'node:stream/consumers';
6
+ import { text as toText } from 'node:stream/consumers';
7
7
 
8
8
  import { Suite, Test, TestFixtures } from '@travetto/test';
9
9
 
@@ -17,9 +17,9 @@ export abstract class ModelStreamSuite extends BaseModelSuite<ModelStreamSupport
17
17
  fixture = new TestFixtures(['@travetto/model']);
18
18
 
19
19
  async getHash(stream: Readable): Promise<string> {
20
- const hasher = crypto.createHash('sha1').setEncoding('hex');
21
- await pipeline(stream, hasher);
22
- return hasher.read().toString();
20
+ const hash = crypto.createHash('sha1').setEncoding('hex');
21
+ await pipeline(stream, hash);
22
+ return hash.read().toString();
23
23
  }
24
24
 
25
25
  async getStream(resource: string): Promise<readonly [{ size: number, contentType: string, hash: string, filename: string }, Readable]> {
@@ -77,30 +77,33 @@ export abstract class ModelStreamSuite extends BaseModelSuite<ModelStreamSupport
77
77
  await service.upsertStream(meta.hash, stream, meta);
78
78
 
79
79
  const retrieved = await service.getStream(meta.hash);
80
- const content = (await toBuffer(retrieved)).toString('utf8');
80
+ const content = await toText(retrieved);
81
81
  assert(content.startsWith('abc'));
82
82
  assert(content.endsWith('xyz'));
83
83
 
84
84
  const partial = await service.getStream(meta.hash, { start: 10, end: 20 });
85
- const subContent = (await toBuffer(partial)).toString('utf8');
85
+ const subContent = await toText(partial);
86
86
  const range = await enforceRange({ start: 10, end: 20 }, meta.size);
87
87
  assert(subContent.length === (range.end - range.start) + 1);
88
- assert(subContent === 'klmnopqrstu');
88
+
89
+ const og = await this.fixture.read('/text.txt');
90
+
91
+ assert(subContent === og.substring(10, 21));
89
92
 
90
93
  const partialUnbounded = await service.getStream(meta.hash, { start: 10 });
91
- const subContent2 = (await toBuffer(partialUnbounded)).toString('utf8');
94
+ const subContent2 = await toText(partialUnbounded);
92
95
  const range2 = await enforceRange({ start: 10 }, meta.size);
93
96
  assert(subContent2.length === (range2.end - range2.start) + 1);
94
97
  assert(subContent2.startsWith('klm'));
95
98
  assert(subContent2.endsWith('xyz'));
96
99
 
97
100
  const partialSingle = await service.getStream(meta.hash, { start: 10, end: 10 });
98
- const subContent3 = (await toBuffer(partialSingle)).toString('utf8');
101
+ const subContent3 = await toText(partialSingle);
99
102
  assert(subContent3.length === 1);
100
103
  assert(subContent3 === 'k');
101
104
 
102
- const partialOverbounded = await service.getStream(meta.hash, { start: 20, end: 40 });
103
- const subContent4 = (await toBuffer(partialOverbounded)).toString('utf8');
105
+ const partialOverBounded = await service.getStream(meta.hash, { start: 20, end: 40 });
106
+ const subContent4 = await toText(partialOverBounded);
104
107
  assert(subContent4.length === 6);
105
108
  assert(subContent4.endsWith('xyz'));
106
109
 
@@ -1,4 +1,4 @@
1
- import { Class } from '@travetto/base';
1
+ import { Class } from '@travetto/runtime';
2
2
  import { DependencyRegistry } from '@travetto/di';
3
3
  import { RootRegistry } from '@travetto/registry';
4
4
  import { SuiteRegistry, TestFixtures } from '@travetto/test';