@milaboratories/pl-tree 1.5.1 → 1.5.3
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/dist/accessors.d.ts +7 -3
- package/dist/accessors.d.ts.map +1 -1
- package/dist/dump.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +124 -117
- package/dist/index.mjs.map +1 -1
- package/dist/snapshot.d.ts +1 -1
- package/dist/snapshot.d.ts.map +1 -1
- package/dist/state.d.ts +1 -1
- package/dist/state.d.ts.map +1 -1
- package/dist/sync.d.ts.map +1 -1
- package/dist/synchronized_tree.d.ts.map +1 -1
- package/dist/test_utils.d.ts.map +1 -1
- package/dist/value_or_error.d.ts.map +1 -1
- package/package.json +10 -5
- package/src/accessors.ts +53 -42
- package/src/dump.ts +68 -68
- package/src/snapshot.ts +21 -20
- package/src/state.ts +39 -35
- package/src/sync.ts +10 -9
- package/src/synchronized_tree.ts +18 -13
- package/src/test_utils.ts +29 -29
- package/src/value_and_error.ts +1 -1
- package/src/value_or_error.ts +6 -6
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/pl-tree",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.3",
|
|
4
4
|
"description": "Reactive pl tree state",
|
|
5
|
+
"engines": {
|
|
6
|
+
"node": ">=20.16.0"
|
|
7
|
+
},
|
|
5
8
|
"types": "./dist/index.d.ts",
|
|
6
9
|
"main": "./dist/index.js",
|
|
7
10
|
"module": "./dist/index.mjs",
|
|
@@ -20,10 +23,11 @@
|
|
|
20
23
|
"denque": "^2.1.0",
|
|
21
24
|
"utility-types": "^3.11.0",
|
|
22
25
|
"zod": "~3.23.8",
|
|
23
|
-
"@milaboratories/
|
|
24
|
-
"@milaboratories/
|
|
25
|
-
"@milaboratories/pl-
|
|
26
|
-
"@milaboratories/ts-helpers": "^1.1.
|
|
26
|
+
"@milaboratories/pl-client": "^2.7.14",
|
|
27
|
+
"@milaboratories/computable": "^2.4.3",
|
|
28
|
+
"@milaboratories/pl-error-like": "^1.12.0",
|
|
29
|
+
"@milaboratories/ts-helpers": "^1.1.5",
|
|
30
|
+
"@milaboratories/pl-errors": "^1.0.4"
|
|
27
31
|
},
|
|
28
32
|
"devDependencies": {
|
|
29
33
|
"typescript": "~5.5.4",
|
|
@@ -37,6 +41,7 @@
|
|
|
37
41
|
"scripts": {
|
|
38
42
|
"type-check": "tsc --noEmit --composite false",
|
|
39
43
|
"build": "vite build",
|
|
44
|
+
"lint": "eslint .",
|
|
40
45
|
"test": "jest --runInBand",
|
|
41
46
|
"do-pack": "rm -f *.tgz && pnpm pack && mv *.tgz package.tgz"
|
|
42
47
|
}
|
package/src/accessors.ts
CHANGED
|
@@ -1,30 +1,38 @@
|
|
|
1
|
-
import { PlTreeResource, PlTreeState } from './state';
|
|
2
|
-
import {
|
|
1
|
+
import type { PlTreeResource, PlTreeState } from './state';
|
|
2
|
+
import type {
|
|
3
3
|
AccessorProvider,
|
|
4
4
|
ComputableCtx,
|
|
5
5
|
ComputableHooks,
|
|
6
|
-
UsageGuard
|
|
6
|
+
UsageGuard,
|
|
7
7
|
} from '@milaboratories/computable';
|
|
8
|
-
import {
|
|
8
|
+
import type {
|
|
9
9
|
ResourceId,
|
|
10
|
-
resourceIdToString,
|
|
11
10
|
ResourceType,
|
|
11
|
+
OptionalResourceId } from '@milaboratories/pl-client';
|
|
12
|
+
import {
|
|
13
|
+
resourceIdToString,
|
|
12
14
|
resourceTypesEqual,
|
|
13
15
|
resourceTypeToString,
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
14
17
|
NullResourceId,
|
|
15
|
-
OptionalResourceId,
|
|
16
|
-
stringifyWithResourceId
|
|
17
18
|
} from '@milaboratories/pl-client';
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
19
|
+
import type { ValueAndError } from './value_and_error';
|
|
20
|
+
import { mapValueAndError } from './value_and_error';
|
|
21
|
+
import type {
|
|
20
22
|
CommonFieldTraverseOps,
|
|
21
23
|
FieldTraversalStep,
|
|
22
24
|
GetFieldStep,
|
|
23
|
-
ResourceTraversalOps
|
|
25
|
+
ResourceTraversalOps,
|
|
24
26
|
} from './traversal_ops';
|
|
25
|
-
import { ValueOrError } from './value_or_error';
|
|
27
|
+
import type { ValueOrError } from './value_or_error';
|
|
26
28
|
import { parsePlError } from '@milaboratories/pl-errors';
|
|
27
29
|
import { notEmpty } from '@milaboratories/ts-helpers';
|
|
30
|
+
/** Error encountered during traversal in field or resource. */
|
|
31
|
+
export class PlError extends Error {
|
|
32
|
+
constructor(message: string) {
|
|
33
|
+
super(message);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
28
36
|
|
|
29
37
|
export type TreeAccessorData = {
|
|
30
38
|
readonly treeProvider: () => PlTreeState;
|
|
@@ -38,25 +46,25 @@ export type TreeAccessorInstanceData = {
|
|
|
38
46
|
|
|
39
47
|
export function isPlTreeEntry(obj: unknown): obj is PlTreeEntry {
|
|
40
48
|
return (
|
|
41
|
-
typeof obj === 'object'
|
|
42
|
-
obj !== null
|
|
43
|
-
(obj as any)['__pl_tree_type_marker__'] === 'PlTreeEntry'
|
|
49
|
+
typeof obj === 'object'
|
|
50
|
+
&& obj !== null
|
|
51
|
+
&& (obj as any)['__pl_tree_type_marker__'] === 'PlTreeEntry'
|
|
44
52
|
);
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
export function isPlTreeEntryAccessor(obj: unknown): obj is PlTreeEntryAccessor {
|
|
48
56
|
return (
|
|
49
|
-
typeof obj === 'object'
|
|
50
|
-
obj !== null
|
|
51
|
-
(obj as any)['__pl_tree_type_marker__'] === 'PlTreeEntryAccessor'
|
|
57
|
+
typeof obj === 'object'
|
|
58
|
+
&& obj !== null
|
|
59
|
+
&& (obj as any)['__pl_tree_type_marker__'] === 'PlTreeEntryAccessor'
|
|
52
60
|
);
|
|
53
61
|
}
|
|
54
62
|
|
|
55
63
|
export function isPlTreeNodeAccessor(obj: unknown): obj is PlTreeNodeAccessor {
|
|
56
64
|
return (
|
|
57
|
-
typeof obj === 'object'
|
|
58
|
-
obj !== null
|
|
59
|
-
(obj as any)['__pl_tree_type_marker__'] === 'PlTreeNodeAccessor'
|
|
65
|
+
typeof obj === 'object'
|
|
66
|
+
&& obj !== null
|
|
67
|
+
&& (obj as any)['__pl_tree_type_marker__'] === 'PlTreeNodeAccessor'
|
|
60
68
|
);
|
|
61
69
|
}
|
|
62
70
|
|
|
@@ -66,13 +74,13 @@ export class PlTreeEntry implements AccessorProvider<PlTreeEntryAccessor> {
|
|
|
66
74
|
|
|
67
75
|
constructor(
|
|
68
76
|
private readonly accessorData: TreeAccessorData,
|
|
69
|
-
public readonly rid: ResourceId
|
|
77
|
+
public readonly rid: ResourceId,
|
|
70
78
|
) {}
|
|
71
79
|
|
|
72
80
|
public createAccessor(ctx: ComputableCtx, guard: UsageGuard): PlTreeEntryAccessor {
|
|
73
81
|
return new PlTreeEntryAccessor(this.accessorData, this.accessorData.treeProvider(), this.rid, {
|
|
74
82
|
ctx,
|
|
75
|
-
guard
|
|
83
|
+
guard,
|
|
76
84
|
});
|
|
77
85
|
}
|
|
78
86
|
|
|
@@ -90,13 +98,13 @@ function getResourceFromTree(
|
|
|
90
98
|
tree: PlTreeState,
|
|
91
99
|
instanceData: TreeAccessorInstanceData,
|
|
92
100
|
rid: ResourceId,
|
|
93
|
-
ops: ResourceTraversalOps
|
|
101
|
+
ops: ResourceTraversalOps,
|
|
94
102
|
): PlTreeNodeAccessor {
|
|
95
103
|
const acc = new PlTreeNodeAccessor(
|
|
96
104
|
accessorData,
|
|
97
105
|
tree,
|
|
98
106
|
tree.get(instanceData.ctx.watcher, rid),
|
|
99
|
-
instanceData
|
|
107
|
+
instanceData,
|
|
100
108
|
);
|
|
101
109
|
|
|
102
110
|
if (!ops.ignoreError) {
|
|
@@ -106,13 +114,14 @@ function getResourceFromTree(
|
|
|
106
114
|
}
|
|
107
115
|
|
|
108
116
|
if (
|
|
109
|
-
ops.assertResourceType !== undefined
|
|
110
|
-
(Array.isArray(ops.assertResourceType)
|
|
117
|
+
ops.assertResourceType !== undefined
|
|
118
|
+
&& (Array.isArray(ops.assertResourceType)
|
|
111
119
|
? ops.assertResourceType.findIndex((rt) => resourceTypesEqual(rt, acc.resourceType)) === -1
|
|
112
120
|
: !resourceTypesEqual(ops.assertResourceType, acc.resourceType))
|
|
113
121
|
)
|
|
114
122
|
throw new Error(
|
|
115
|
-
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
124
|
+
`wrong resource type ${resourceTypeToString(acc.resourceType)} but expected ${ops.assertResourceType}`,
|
|
116
125
|
);
|
|
117
126
|
|
|
118
127
|
return acc;
|
|
@@ -125,7 +134,7 @@ export class PlTreeEntryAccessor {
|
|
|
125
134
|
private readonly accessorData: TreeAccessorData,
|
|
126
135
|
private readonly tree: PlTreeState,
|
|
127
136
|
private readonly rid: ResourceId,
|
|
128
|
-
private readonly instanceData: TreeAccessorInstanceData
|
|
137
|
+
private readonly instanceData: TreeAccessorInstanceData,
|
|
129
138
|
) {}
|
|
130
139
|
|
|
131
140
|
node(ops: ResourceTraversalOps = {}): PlTreeNodeAccessor {
|
|
@@ -171,7 +180,7 @@ export class PlTreeNodeAccessor {
|
|
|
171
180
|
private readonly accessorData: TreeAccessorData,
|
|
172
181
|
private readonly tree: PlTreeState,
|
|
173
182
|
private readonly resource: PlTreeResource,
|
|
174
|
-
private readonly instanceData: TreeAccessorInstanceData
|
|
183
|
+
private readonly instanceData: TreeAccessorInstanceData,
|
|
175
184
|
) {}
|
|
176
185
|
|
|
177
186
|
public get id(): ResourceId {
|
|
@@ -201,7 +210,7 @@ export class PlTreeNodeAccessor {
|
|
|
201
210
|
...steps: [
|
|
202
211
|
Omit<FieldTraversalStep, 'errorIfFieldNotSet'> & {
|
|
203
212
|
errorIfFieldNotSet: true;
|
|
204
|
-
}
|
|
213
|
+
},
|
|
205
214
|
]
|
|
206
215
|
): PlTreeNodeAccessor;
|
|
207
216
|
public traverse(...steps: (FieldTraversalStep | string)[]): PlTreeNodeAccessor | undefined;
|
|
@@ -213,15 +222,15 @@ export class PlTreeNodeAccessor {
|
|
|
213
222
|
...steps: [
|
|
214
223
|
Omit<FieldTraversalStep, 'errorIfFieldNotSet'> & {
|
|
215
224
|
errorIfFieldNotSet: true;
|
|
216
|
-
}
|
|
225
|
+
},
|
|
217
226
|
]
|
|
218
|
-
): ValueOrError<PlTreeNodeAccessor,
|
|
227
|
+
): ValueOrError<PlTreeNodeAccessor, Error>;
|
|
219
228
|
public traverseOrError(
|
|
220
229
|
...steps: (FieldTraversalStep | string)[]
|
|
221
|
-
): ValueOrError<PlTreeNodeAccessor,
|
|
230
|
+
): ValueOrError<PlTreeNodeAccessor, Error> | undefined;
|
|
222
231
|
public traverseOrError(
|
|
223
232
|
...steps: (FieldTraversalStep | string)[]
|
|
224
|
-
): ValueOrError<PlTreeNodeAccessor,
|
|
233
|
+
): ValueOrError<PlTreeNodeAccessor, Error> | undefined {
|
|
225
234
|
return this.traverseOrErrorWithCommon({}, ...steps);
|
|
226
235
|
}
|
|
227
236
|
|
|
@@ -231,6 +240,7 @@ export class PlTreeNodeAccessor {
|
|
|
231
240
|
): PlTreeNodeAccessor | undefined {
|
|
232
241
|
const result = this.traverseOrErrorWithCommon(commonOptions, ...steps);
|
|
233
242
|
if (result === undefined) return undefined;
|
|
243
|
+
|
|
234
244
|
if (!result.ok) throw result.error;
|
|
235
245
|
return result.value;
|
|
236
246
|
}
|
|
@@ -238,15 +248,16 @@ export class PlTreeNodeAccessor {
|
|
|
238
248
|
public traverseOrErrorWithCommon(
|
|
239
249
|
commonOptions: CommonFieldTraverseOps,
|
|
240
250
|
...steps: (FieldTraversalStep | string)[]
|
|
241
|
-
): ValueOrError<PlTreeNodeAccessor,
|
|
251
|
+
): ValueOrError<PlTreeNodeAccessor, Error> | undefined {
|
|
252
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
242
253
|
let current: PlTreeNodeAccessor = this;
|
|
243
254
|
|
|
244
255
|
for (const _step of steps) {
|
|
245
|
-
const step: FieldTraversalStep
|
|
246
|
-
typeof _step === 'string'
|
|
256
|
+
const step: FieldTraversalStep
|
|
257
|
+
= typeof _step === 'string'
|
|
247
258
|
? {
|
|
248
259
|
...commonOptions,
|
|
249
|
-
field: _step
|
|
260
|
+
field: _step,
|
|
250
261
|
}
|
|
251
262
|
: { ...commonOptions, ..._step };
|
|
252
263
|
|
|
@@ -262,17 +273,17 @@ export class PlTreeNodeAccessor {
|
|
|
262
273
|
ok: false,
|
|
263
274
|
|
|
264
275
|
// FIXME: in next tickets we'll allow Errors to be thrown.
|
|
265
|
-
error:
|
|
276
|
+
error: parsePlError(
|
|
266
277
|
notEmpty(next.error.getDataAsString()),
|
|
267
278
|
current.id, current.resourceType, step.field,
|
|
268
|
-
)
|
|
279
|
+
),
|
|
269
280
|
};
|
|
270
281
|
|
|
271
282
|
if (next.value === undefined) {
|
|
272
283
|
if (step.errorIfFieldNotSet)
|
|
273
284
|
return {
|
|
274
285
|
ok: false,
|
|
275
|
-
error: `field have no assigned value ${step.field} of ${resourceIdToString(current.id)}
|
|
286
|
+
error: new Error(`field have no assigned value ${step.field} of ${resourceIdToString(current.id)}`),
|
|
276
287
|
};
|
|
277
288
|
// existing but unpopulated field is unstable because it must be resolved at some point
|
|
278
289
|
this.onUnstableLambda('unpopulated_field:' + step.field);
|
|
@@ -392,7 +403,7 @@ export class PlTreeNodeAccessor {
|
|
|
392
403
|
|
|
393
404
|
public getKeyValueAsJson<T = unknown>(
|
|
394
405
|
key: string,
|
|
395
|
-
unstableIfNotFound: boolean = false
|
|
406
|
+
unstableIfNotFound: boolean = false,
|
|
396
407
|
): T | undefined {
|
|
397
408
|
const result = this.resource.getKeyValueString(this.instanceData.ctx.watcher, key);
|
|
398
409
|
if (result === undefined) {
|
package/src/dump.ts
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import { ExtendedResourceData } from
|
|
1
|
+
import type { ExtendedResourceData } from './state';
|
|
2
2
|
|
|
3
3
|
export type ResourceStats = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
4
|
+
/** Number of resources of this type */
|
|
5
|
+
count: number;
|
|
6
|
+
/** Total number of bytes in the field names of all resources of this type */
|
|
7
|
+
fieldNameBytes: number;
|
|
8
|
+
/** Total number of fields in all resources of this type */
|
|
9
|
+
fieldsCount: number;
|
|
10
|
+
/** Total number of bytes in the data of all resources of this type */
|
|
11
|
+
dataBytes: number;
|
|
12
|
+
/** Total number of key-value records in all resources of this type */
|
|
13
|
+
kvCount: number;
|
|
14
|
+
/** Total number of bytes in the key-value records of all resources of this type */
|
|
15
|
+
kvBytes: number;
|
|
16
|
+
};
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* A map of resource type statistics, keyed by the resource type name and version.
|
|
20
|
-
*
|
|
20
|
+
*
|
|
21
21
|
* @type {Record<string, ResourceStats>}
|
|
22
22
|
*/
|
|
23
23
|
export type TreeDumpStats = {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
24
|
+
total: ResourceStats;
|
|
25
|
+
byResourceType: Record<`${string}/${string}`, ResourceStats>;
|
|
26
|
+
};
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Analyzes a collection of resources and generates statistics grouped by resource type.
|
|
30
|
-
*
|
|
30
|
+
*
|
|
31
31
|
* This function processes an array of ExtendedResourceData and calculates various metrics
|
|
32
32
|
* for each unique resource type, including:
|
|
33
33
|
* - Count of resources
|
|
@@ -36,9 +36,9 @@ export type TreeDumpStats = {
|
|
|
36
36
|
* - Total bytes in resource data
|
|
37
37
|
* - Total number of key-value records
|
|
38
38
|
* - Total bytes in key-value records
|
|
39
|
-
*
|
|
39
|
+
*
|
|
40
40
|
* The statistics are organized by resource type using a key in the format "typeName/version".
|
|
41
|
-
*
|
|
41
|
+
*
|
|
42
42
|
* @param dumpStats - Array of ExtendedResourceData objects to analyze
|
|
43
43
|
* @returns A DumpStats object containing statistics for each resource type
|
|
44
44
|
* @example
|
|
@@ -59,57 +59,57 @@ export type TreeDumpStats = {
|
|
|
59
59
|
* ```
|
|
60
60
|
*/
|
|
61
61
|
export function treeDumpStats(dumpStats: ExtendedResourceData[]): TreeDumpStats {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
62
|
+
const stats: TreeDumpStats = {
|
|
63
|
+
total: {
|
|
64
|
+
count: 0,
|
|
65
|
+
fieldNameBytes: 0,
|
|
66
|
+
fieldsCount: 0,
|
|
67
|
+
dataBytes: 0,
|
|
68
|
+
kvCount: 0,
|
|
69
|
+
kvBytes: 0,
|
|
70
|
+
},
|
|
71
|
+
byResourceType: {},
|
|
72
|
+
};
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
74
|
+
for (const resource of dumpStats) {
|
|
75
|
+
const typeKey = `${resource.type.name}/${resource.type.version}` as const;
|
|
76
|
+
if (!stats.byResourceType[typeKey]) {
|
|
77
|
+
stats.byResourceType[typeKey] = {
|
|
78
|
+
count: 0,
|
|
79
|
+
fieldNameBytes: 0,
|
|
80
|
+
fieldsCount: 0,
|
|
81
|
+
dataBytes: 0,
|
|
82
|
+
kvCount: 0,
|
|
83
|
+
kvBytes: 0,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
const typeStats = stats.byResourceType[typeKey];
|
|
88
|
+
typeStats.count++;
|
|
89
|
+
stats.total.count++;
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
for (const field of resource.fields) {
|
|
92
|
+
typeStats.fieldNameBytes += field.name.length;
|
|
93
|
+
typeStats.fieldsCount++;
|
|
94
|
+
stats.total.fieldNameBytes += field.name.length;
|
|
95
|
+
stats.total.fieldsCount++;
|
|
96
|
+
}
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
98
|
+
if (resource.data) {
|
|
99
|
+
const dataLength = resource.data?.length ?? 0;
|
|
100
|
+
typeStats.dataBytes += dataLength;
|
|
101
|
+
stats.total.dataBytes += dataLength;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
typeStats.kvCount += resource.kv.length;
|
|
105
|
+
stats.total.kvCount += resource.kv.length;
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const kvLength = kv.key.length + kv.value.length;
|
|
109
|
-
typeStats.kvBytes += kvLength;
|
|
110
|
-
stats.total.kvBytes += kvLength;
|
|
111
|
-
}
|
|
107
|
+
for (const kv of resource.kv) {
|
|
108
|
+
const kvLength = kv.key.length + kv.value.length;
|
|
109
|
+
typeStats.kvBytes += kvLength;
|
|
110
|
+
stats.total.kvBytes += kvLength;
|
|
112
111
|
}
|
|
112
|
+
}
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
}
|
|
114
|
+
return stats;
|
|
115
|
+
}
|
package/src/snapshot.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { ResourceId, ResourceType } from '@milaboratories/pl-client';
|
|
2
|
-
import { Optional, Writable } from 'utility-types';
|
|
3
|
-
import { ZodType, z } from 'zod';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import type { ResourceId, ResourceType } from '@milaboratories/pl-client';
|
|
2
|
+
import type { Optional, Writable } from 'utility-types';
|
|
3
|
+
import type { ZodType, z } from 'zod';
|
|
4
|
+
import type { PlTreeNodeAccessor } from './accessors';
|
|
5
|
+
import { PlTreeEntry, PlTreeEntryAccessor } from './accessors';
|
|
6
|
+
import type { ComputableCtx } from '@milaboratories/computable';
|
|
6
7
|
import { notEmpty } from '@milaboratories/ts-helpers';
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -13,7 +14,7 @@ import { notEmpty } from '@milaboratories/ts-helpers';
|
|
|
13
14
|
export type ResourceSnapshot<
|
|
14
15
|
Data = undefined,
|
|
15
16
|
Fields extends Record<string, ResourceId | undefined> | undefined = undefined,
|
|
16
|
-
KV extends Record<string, unknown> | undefined = undefined
|
|
17
|
+
KV extends Record<string, unknown> | undefined = undefined,
|
|
17
18
|
> = {
|
|
18
19
|
readonly id: ResourceId;
|
|
19
20
|
readonly type: ResourceType;
|
|
@@ -33,7 +34,7 @@ type ResourceSnapshotGeneric = ResourceSnapshot<
|
|
|
33
34
|
export type ResourceSnapshotSchema<
|
|
34
35
|
Data extends ZodType | 'raw' | undefined = undefined,
|
|
35
36
|
Fields extends Record<string, boolean> | undefined = undefined,
|
|
36
|
-
KV extends Record<string, ZodType | 'raw'> | undefined = undefined
|
|
37
|
+
KV extends Record<string, ZodType | 'raw'> | undefined = undefined,
|
|
37
38
|
> = {
|
|
38
39
|
readonly data: Data;
|
|
39
40
|
readonly fields: Fields;
|
|
@@ -44,9 +45,9 @@ export type ResourceSnapshotSchema<
|
|
|
44
45
|
export function rsSchema<
|
|
45
46
|
const Data extends ZodType | 'raw' | undefined = undefined,
|
|
46
47
|
const Fields extends Record<string, boolean> | undefined = undefined,
|
|
47
|
-
const KV extends Record<string, ZodType | 'raw'> | undefined = undefined
|
|
48
|
+
const KV extends Record<string, ZodType | 'raw'> | undefined = undefined,
|
|
48
49
|
>(
|
|
49
|
-
schema: Optional<ResourceSnapshotSchema<Data, Fields, KV
|
|
50
|
+
schema: Optional<ResourceSnapshotSchema<Data, Fields, KV>>,
|
|
50
51
|
): ResourceSnapshotSchema<Data, Fields, KV> {
|
|
51
52
|
return schema as any;
|
|
52
53
|
}
|
|
@@ -114,10 +115,10 @@ export function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneri
|
|
|
114
115
|
export function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneric>(
|
|
115
116
|
res: PlTreeEntry | PlTreeEntryAccessor | PlTreeNodeAccessor,
|
|
116
117
|
schema: Schema,
|
|
117
|
-
ctx?: ComputableCtx
|
|
118
|
+
ctx?: ComputableCtx,
|
|
118
119
|
): InferSnapshot<Schema> {
|
|
119
|
-
const node
|
|
120
|
-
res instanceof PlTreeEntry
|
|
120
|
+
const node
|
|
121
|
+
= res instanceof PlTreeEntry
|
|
121
122
|
? notEmpty(ctx).accessor(res).node()
|
|
122
123
|
: res instanceof PlTreeEntryAccessor
|
|
123
124
|
? res.node()
|
|
@@ -138,7 +139,7 @@ export function makeResourceSnapshot<Schema extends ResourceSnapshotSchemaGeneri
|
|
|
138
139
|
fields[fieldName] = node.traverse({
|
|
139
140
|
field: fieldName,
|
|
140
141
|
errorIfFieldNotSet: required,
|
|
141
|
-
stableIfNotFound: !required
|
|
142
|
+
stableIfNotFound: !required,
|
|
142
143
|
})?.id;
|
|
143
144
|
result.fields = fields;
|
|
144
145
|
}
|
|
@@ -174,21 +175,21 @@ export type ResourceWithData = {
|
|
|
174
175
|
export function treeEntryToResourceWithData(
|
|
175
176
|
res: PlTreeEntry | ResourceWithData,
|
|
176
177
|
fields: string[],
|
|
177
|
-
ctx: ComputableCtx
|
|
178
|
+
ctx: ComputableCtx,
|
|
178
179
|
): ResourceWithData {
|
|
179
180
|
if (res instanceof PlTreeEntry) {
|
|
180
|
-
const node = ctx.accessor(res
|
|
181
|
+
const node = ctx.accessor(res).node();
|
|
181
182
|
const info = node.resourceInfo;
|
|
182
183
|
|
|
183
184
|
const fValues: [string, ResourceId | undefined][] = fields.map((name) => [
|
|
184
185
|
name,
|
|
185
|
-
node.getField(name)?.value?.id
|
|
186
|
+
node.getField(name)?.value?.id,
|
|
186
187
|
]);
|
|
187
188
|
|
|
188
189
|
return {
|
|
189
190
|
...info,
|
|
190
191
|
fields: new Map(fValues),
|
|
191
|
-
data: node.getData() ?? new Uint8Array()
|
|
192
|
+
data: node.getData() ?? new Uint8Array(),
|
|
192
193
|
};
|
|
193
194
|
}
|
|
194
195
|
|
|
@@ -206,16 +207,16 @@ export type ResourceWithMetadata = {
|
|
|
206
207
|
export function treeEntryToResourceWithMetadata(
|
|
207
208
|
res: PlTreeEntry | ResourceWithMetadata,
|
|
208
209
|
mdKeys: string[],
|
|
209
|
-
ctx: ComputableCtx
|
|
210
|
+
ctx: ComputableCtx,
|
|
210
211
|
): ResourceWithMetadata {
|
|
211
212
|
if (!(res instanceof PlTreeEntry)) return res;
|
|
212
213
|
|
|
213
|
-
const node = ctx.accessor(res
|
|
214
|
+
const node = ctx.accessor(res).node();
|
|
214
215
|
const info = node.resourceInfo;
|
|
215
216
|
const mdEntries: [string, any][] = mdKeys.map((k) => [k, node.getKeyValue(k)]);
|
|
216
217
|
|
|
217
218
|
return {
|
|
218
219
|
...info,
|
|
219
|
-
metadata: Object.fromEntries(mdEntries)
|
|
220
|
+
metadata: Object.fromEntries(mdEntries),
|
|
220
221
|
};
|
|
221
222
|
}
|