@milaboratories/pl-middle-layer 1.65.8 → 1.66.0
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/js_render/column_registry.cjs +56 -0
- package/dist/js_render/column_registry.cjs.map +1 -0
- package/dist/js_render/column_registry.js +55 -0
- package/dist/js_render/column_registry.js.map +1 -0
- package/dist/js_render/computable_context.cjs +80 -12
- package/dist/js_render/computable_context.cjs.map +1 -1
- package/dist/js_render/computable_context.js +81 -13
- package/dist/js_render/computable_context.js.map +1 -1
- package/dist/js_render/service_injectors.cjs +43 -2
- package/dist/js_render/service_injectors.cjs.map +1 -1
- package/dist/js_render/service_injectors.js +43 -2
- package/dist/js_render/service_injectors.js.map +1 -1
- package/dist/js_render/spec_override_collapse.cjs +108 -0
- package/dist/js_render/spec_override_collapse.cjs.map +1 -0
- package/dist/js_render/spec_override_collapse.js +108 -0
- package/dist/js_render/spec_override_collapse.js.map +1 -0
- package/dist/middle_layer/block_ctx.cjs +2 -1
- package/dist/middle_layer/block_ctx.cjs.map +1 -1
- package/dist/middle_layer/block_ctx.js +2 -1
- package/dist/middle_layer/block_ctx.js.map +1 -1
- package/dist/mutator/template/template_cache.cjs.map +1 -1
- package/dist/mutator/template/template_cache.d.ts.map +1 -1
- package/dist/mutator/template/template_cache.js.map +1 -1
- package/dist/pool/data.cjs +2 -9
- package/dist/pool/data.cjs.map +1 -1
- package/dist/pool/data.d.ts.map +1 -1
- package/dist/pool/data.js +3 -10
- package/dist/pool/data.js.map +1 -1
- package/dist/pool/result_pool.cjs +0 -20
- package/dist/pool/result_pool.cjs.map +1 -1
- package/dist/pool/result_pool.js +1 -21
- package/dist/pool/result_pool.js.map +1 -1
- package/dist/pool/upstream_block_ctx.cjs +64 -0
- package/dist/pool/upstream_block_ctx.cjs.map +1 -0
- package/dist/pool/upstream_block_ctx.js +64 -0
- package/dist/pool/upstream_block_ctx.js.map +1 -0
- package/dist/service_factories.cjs +3 -1
- package/dist/service_factories.cjs.map +1 -1
- package/dist/service_factories.js +3 -1
- package/dist/service_factories.js.map +1 -1
- package/package.json +16 -15
- package/src/js_render/column_registry.ts +95 -0
- package/src/js_render/computable_context.ts +109 -26
- package/src/js_render/service_injectors.ts +106 -8
- package/src/js_render/spec_override_collapse.ts +211 -0
- package/src/middle_layer/block_ctx.ts +6 -1
- package/src/mutator/template/template_cache.test.ts +0 -14
- package/src/mutator/template/template_cache.ts +0 -14
- package/src/pool/data.ts +4 -3
- package/src/pool/result_pool.ts +1 -24
- package/src/pool/upstream_block_ctx.ts +85 -0
- package/src/service_factories.ts +2 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { PlTreeNodeAccessor } from "@milaboratories/pl-tree";
|
|
2
|
+
import {
|
|
3
|
+
AccessorEntriesProvider,
|
|
4
|
+
applySpecOverrides,
|
|
5
|
+
ColumnRegistry,
|
|
6
|
+
extractPObjectId,
|
|
7
|
+
PColumnValues,
|
|
8
|
+
ResultPoolEntriesProvider,
|
|
9
|
+
SpecOverrides,
|
|
10
|
+
type ColumnEntriesProvider,
|
|
11
|
+
type PColumn,
|
|
12
|
+
type PColumnSpec,
|
|
13
|
+
type PObjectId,
|
|
14
|
+
type UpstreamBlockCtx,
|
|
15
|
+
} from "@milaboratories/pl-model-common";
|
|
16
|
+
|
|
17
|
+
export interface ColumnRegistryRoots {
|
|
18
|
+
/** Main `outputs` accessor (if available) — usually `MainAccessorName`. */
|
|
19
|
+
readonly outputs?: PlTreeNodeAccessor;
|
|
20
|
+
/** Prerun `staging` accessor (if available) — usually `StagingAccessorName`. */
|
|
21
|
+
readonly prerun?: PlTreeNodeAccessor;
|
|
22
|
+
/** Upstream-block ctx accessors (as `collectUpstreamBlockCtxes` returns). */
|
|
23
|
+
readonly upstreamBlockCtxes: ReadonlyArray<UpstreamBlockCtx<PlTreeNodeAccessor>>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Build a host-side {@link ColumnRegistry} mirroring the sandbox layout:
|
|
28
|
+
* `outputs` precedes `prerun` precedes `rawResultPool`, first-wins on conflict.
|
|
29
|
+
*
|
|
30
|
+
* Uses raw {@link PlTreeNodeAccessor}s directly — both `TreeNodeAccessor`
|
|
31
|
+
* (sandbox) and `PlTreeNodeAccessor` (host) satisfy the `AccessorLike`
|
|
32
|
+
* traversal surface, so no host-side adapter is required.
|
|
33
|
+
*/
|
|
34
|
+
export function buildColumnRegistry(
|
|
35
|
+
roots: ColumnRegistryRoots,
|
|
36
|
+
): ColumnRegistry<PlTreeNodeAccessor> {
|
|
37
|
+
const providers: ColumnEntriesProvider<PlTreeNodeAccessor>[] = [];
|
|
38
|
+
|
|
39
|
+
if (roots.outputs !== undefined) {
|
|
40
|
+
providers.push(new AccessorEntriesProvider(roots.outputs, ["main"]));
|
|
41
|
+
}
|
|
42
|
+
if (roots.prerun !== undefined) {
|
|
43
|
+
providers.push(new AccessorEntriesProvider(roots.prerun, ["staging"]));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
providers.push(new ResultPoolEntriesProvider<PlTreeNodeAccessor>(roots.upstreamBlockCtxes));
|
|
47
|
+
|
|
48
|
+
return new ColumnRegistry<PlTreeNodeAccessor>(providers);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Resolve a column id to a materialised {@link PColumn} backed by the
|
|
53
|
+
* underlying {@link PlTreeNodeAccessor} for the `.data` resource. Returns the
|
|
54
|
+
* bare leaf spec (via {@link extractPObjectId}): filters / overrides encoded in
|
|
55
|
+
* a rich id are NOT reconstructed here — they are applied by the query nodes
|
|
56
|
+
* (`sliceAxes` / `specOverride`) that wrap this leaf in the def, so reconstructing
|
|
57
|
+
* would double-apply them. Only the explicit `overrides` argument is folded in.
|
|
58
|
+
*
|
|
59
|
+
* Throws when the id is not in the registry or the column has no resolved spec.
|
|
60
|
+
* A `.data` field that has not yet materialised yields an empty value list — the
|
|
61
|
+
* column refills on a later recomputation, mirroring the sandbox-side
|
|
62
|
+
* `finalizePColumnData` behaviour rather than blocking the whole PFrame.
|
|
63
|
+
*/
|
|
64
|
+
export function resolvePColumnById(
|
|
65
|
+
registry: ColumnRegistry<PlTreeNodeAccessor>,
|
|
66
|
+
id: PObjectId,
|
|
67
|
+
overrides?: SpecOverrides,
|
|
68
|
+
): PColumn<PColumnValues | PlTreeNodeAccessor> {
|
|
69
|
+
const pid = extractPObjectId(id);
|
|
70
|
+
const leaf = registry.resolve(pid);
|
|
71
|
+
if (leaf === undefined) {
|
|
72
|
+
throw new Error(`column id ${String(pid)} not found in host column registry`);
|
|
73
|
+
}
|
|
74
|
+
const specNode = leaf.accessor.traverse({
|
|
75
|
+
field: `${leaf.name}.spec`,
|
|
76
|
+
assertFieldType: "Input",
|
|
77
|
+
ignoreError: true,
|
|
78
|
+
});
|
|
79
|
+
const spec = specNode?.getDataAsJson<PColumnSpec>();
|
|
80
|
+
if (spec === undefined) {
|
|
81
|
+
throw new Error(`column ${String(pid)} has no resolved spec`);
|
|
82
|
+
}
|
|
83
|
+
const data =
|
|
84
|
+
leaf.accessor.traverse({
|
|
85
|
+
field: `${leaf.name}.data`,
|
|
86
|
+
assertFieldType: "Input",
|
|
87
|
+
ignoreError: true,
|
|
88
|
+
}) ?? [];
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
id: id as PObjectId,
|
|
92
|
+
spec: applySpecOverrides(spec, overrides),
|
|
93
|
+
data,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -7,14 +7,12 @@ import type {
|
|
|
7
7
|
CommonFieldTraverseOps as CommonFieldTraverseOpsFromSDK,
|
|
8
8
|
DataInfo,
|
|
9
9
|
FieldTraversalStep as FieldTraversalStepFromSDK,
|
|
10
|
-
Option,
|
|
11
10
|
PColumn,
|
|
12
11
|
PColumnValues,
|
|
13
12
|
PFrameDef,
|
|
14
13
|
PFrameHandle,
|
|
15
14
|
PObject,
|
|
16
15
|
PObjectSpec,
|
|
17
|
-
PSpecPredicate,
|
|
18
16
|
PTableDef,
|
|
19
17
|
PTableDefV2,
|
|
20
18
|
PTableHandle,
|
|
@@ -42,6 +40,7 @@ import type { MiddleLayerEnvironment } from "../middle_layer/middle_layer";
|
|
|
42
40
|
import type { Block } from "../model/project_model";
|
|
43
41
|
import { parseFinalPObjectCollection } from "../pool/p_object_collection";
|
|
44
42
|
import type { ResultPool } from "../pool/result_pool";
|
|
43
|
+
import { collectUpstreamBlockCtx, type UpstreamBlockCtx } from "../pool/upstream_block_ctx";
|
|
45
44
|
import type { JsExecutionContext } from "./context";
|
|
46
45
|
import type { VmFunctionImplementation } from "quickjs-emscripten";
|
|
47
46
|
import { Scope, type QuickJSHandle } from "quickjs-emscripten";
|
|
@@ -54,10 +53,10 @@ import {
|
|
|
54
53
|
ServiceMethodNotFoundError,
|
|
55
54
|
} from "@milaboratories/pl-model-common";
|
|
56
55
|
import { getServiceInjectors } from "./service_injectors";
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
56
|
+
import { MainAccessorName, StagingAccessorName } from "@platforma-sdk/model";
|
|
57
|
+
import { buildColumnRegistry, resolvePColumnById } from "./column_registry";
|
|
58
|
+
import type { ColumnRegistry, PObjectId } from "@milaboratories/pl-model-common";
|
|
59
|
+
import { collapseSpecOverrideNode } from "./spec_override_collapse";
|
|
61
60
|
|
|
62
61
|
export class ComputableContextHelper implements JsRenderInternal.GlobalCfgRenderCtxMethods<
|
|
63
62
|
string,
|
|
@@ -92,6 +91,10 @@ export class ComputableContextHelper implements JsRenderInternal.GlobalCfgRender
|
|
|
92
91
|
public resetComputableCtx() {
|
|
93
92
|
this.computableCtx = undefined;
|
|
94
93
|
this.accessors.clear();
|
|
94
|
+
this._resultPool = undefined;
|
|
95
|
+
this._upstreamBlockCtx = undefined;
|
|
96
|
+
this._rawUpstreamBlockCtx = undefined;
|
|
97
|
+
this._columnRegistry = undefined;
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
private get requireComputableCtx(): ComputableCtx {
|
|
@@ -153,6 +156,10 @@ export class ComputableContextHelper implements JsRenderInternal.GlobalCfgRender
|
|
|
153
156
|
return this.getAccessor(handle).getIsReadyOrError();
|
|
154
157
|
}
|
|
155
158
|
|
|
159
|
+
hasData(handle: string): boolean {
|
|
160
|
+
return this.getAccessor(handle).hasData();
|
|
161
|
+
}
|
|
162
|
+
|
|
156
163
|
getIsFinal(handle: string): boolean {
|
|
157
164
|
return this.getAccessor(handle).getIsFinal();
|
|
158
165
|
}
|
|
@@ -350,10 +357,6 @@ export class ComputableContextHelper implements JsRenderInternal.GlobalCfgRender
|
|
|
350
357
|
return this._resultPool;
|
|
351
358
|
}
|
|
352
359
|
|
|
353
|
-
public calculateOptions(predicate: PSpecPredicate): Option[] {
|
|
354
|
-
return this.resultPool.calculateOptions(predicate);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
360
|
public getDataFromResultPool(): ResultCollection<PObject<string>> {
|
|
358
361
|
const collection = this.resultPool.getData();
|
|
359
362
|
if (collection.instabilityMarker !== undefined)
|
|
@@ -409,28 +412,79 @@ export class ComputableContextHelper implements JsRenderInternal.GlobalCfgRender
|
|
|
409
412
|
);
|
|
410
413
|
}
|
|
411
414
|
|
|
415
|
+
/**
|
|
416
|
+
* Single source-of-truth cache of upstream-block ctx pairs as raw
|
|
417
|
+
* `PlTreeNodeAccessor`s. Both the sandbox-facing `getUpstreamBlockCtx()`
|
|
418
|
+
* (string-handle view) and the host column registry are derived from this.
|
|
419
|
+
*/
|
|
420
|
+
private _rawUpstreamBlockCtx: UpstreamBlockCtx<PlTreeNodeAccessor>[] | undefined = undefined;
|
|
421
|
+
/**
|
|
422
|
+
* Raw upstream-block ctx accessors for the current render. Public so the
|
|
423
|
+
* `ColumnsCollection` service injector (`service_injectors.ts`) can build
|
|
424
|
+
* `ColumnsCollectionDriverHost.getUpstreamBlockCtxes` bindings without
|
|
425
|
+
* round-tripping through the handle-shape view.
|
|
426
|
+
*/
|
|
427
|
+
public getRawUpstreamBlockCtx(): UpstreamBlockCtx<PlTreeNodeAccessor>[] {
|
|
428
|
+
if (this._rawUpstreamBlockCtx === undefined) {
|
|
429
|
+
const prjEntry = notEmpty(this.blockCtx.projectEntry, "projectEntry");
|
|
430
|
+
this._rawUpstreamBlockCtx = collectUpstreamBlockCtx(
|
|
431
|
+
this.requireComputableCtx,
|
|
432
|
+
prjEntry,
|
|
433
|
+
this.blockCtx.blockId,
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
return this._rawUpstreamBlockCtx;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
private _upstreamBlockCtx: UpstreamBlockCtx<string>[] | undefined = undefined;
|
|
440
|
+
public getUpstreamBlockCtx(): UpstreamBlockCtx<string>[] {
|
|
441
|
+
if (this._upstreamBlockCtx === undefined) {
|
|
442
|
+
this._upstreamBlockCtx = this.getRawUpstreamBlockCtx().map((b) => ({
|
|
443
|
+
blockId: b.blockId,
|
|
444
|
+
prodCtx: this.wrapAccessor(b.prodCtx),
|
|
445
|
+
stagingCtx: this.wrapAccessor(b.stagingCtx),
|
|
446
|
+
prodIncomplete: b.prodIncomplete,
|
|
447
|
+
stagingIncomplete: b.stagingIncomplete,
|
|
448
|
+
}));
|
|
449
|
+
}
|
|
450
|
+
return this._upstreamBlockCtx;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
//
|
|
454
|
+
// Host-side column registry — id → LeafEntry index over outputs/prerun/raw pool.
|
|
455
|
+
// Mirrors the sandbox `ColumnRegistry` so `createPFrame` / `createPTable` can
|
|
456
|
+
// accept `PObjectId` in addition to materialised `PColumn`s.
|
|
457
|
+
//
|
|
458
|
+
private _columnRegistry: ColumnRegistry<PlTreeNodeAccessor> | undefined = undefined;
|
|
459
|
+
public getColumnRegistry(): ColumnRegistry<PlTreeNodeAccessor> {
|
|
460
|
+
if (this._columnRegistry !== undefined) return this._columnRegistry;
|
|
461
|
+
return (this._columnRegistry = buildColumnRegistry({
|
|
462
|
+
outputs: this.accessors.get(MainAccessorName) ?? undefined,
|
|
463
|
+
prerun: this.accessors.get(StagingAccessorName) ?? undefined,
|
|
464
|
+
upstreamBlockCtxes: this.getRawUpstreamBlockCtx(),
|
|
465
|
+
}));
|
|
466
|
+
}
|
|
467
|
+
|
|
412
468
|
//
|
|
413
469
|
// PFrames / PTables
|
|
414
470
|
//
|
|
415
471
|
|
|
416
472
|
public createPFrame(
|
|
417
|
-
def: PFrameDef<PColumn<string | PColumnValues | DataInfo<string>>>,
|
|
473
|
+
def: PFrameDef<PObjectId | PColumn<string | PColumnValues | DataInfo<string>>>,
|
|
418
474
|
): PFrameHandle {
|
|
419
475
|
using guard = new PoolEntryGuard(
|
|
420
|
-
this.env.driverKit.pFrameDriver.createPFrame(
|
|
421
|
-
def.map((c) => mapPObjectData(c, (d) => this.transformInputPData(d))),
|
|
422
|
-
),
|
|
476
|
+
this.env.driverKit.pFrameDriver.createPFrame(def.map((c) => this.resolvePColumn(c))),
|
|
423
477
|
);
|
|
424
478
|
this.requireComputableCtx.addOnDestroy(guard.entry.unref);
|
|
425
479
|
return guard.keep().key;
|
|
426
480
|
}
|
|
427
481
|
|
|
428
482
|
public createPTable(
|
|
429
|
-
def: PTableDef<PColumn<string | PColumnValues | DataInfo<string>>>,
|
|
483
|
+
def: PTableDef<PObjectId | PColumn<string | PColumnValues | DataInfo<string>>>,
|
|
430
484
|
): PTableHandle {
|
|
431
485
|
using guard = new PoolEntryGuard(
|
|
432
486
|
this.env.driverKit.pFrameDriver.createPTable(
|
|
433
|
-
mapPTableDef(def, (c) =>
|
|
487
|
+
mapPTableDef(def, (c) => this.resolvePColumn(c)),
|
|
434
488
|
),
|
|
435
489
|
);
|
|
436
490
|
this.requireComputableCtx.addOnDestroy(guard.entry.unref);
|
|
@@ -438,17 +492,35 @@ export class ComputableContextHelper implements JsRenderInternal.GlobalCfgRender
|
|
|
438
492
|
}
|
|
439
493
|
|
|
440
494
|
public createPTableV2(
|
|
441
|
-
def: PTableDefV2<PColumn<string | PColumnValues | DataInfo<string>>>,
|
|
495
|
+
def: PTableDefV2<PObjectId | PColumn<string | PColumnValues | DataInfo<string>>>,
|
|
442
496
|
): PTableHandle {
|
|
443
497
|
using guard = new PoolEntryGuard(
|
|
444
498
|
this.env.driverKit.pFrameDriver.createPTableV2(
|
|
445
|
-
mapPTableDefV2(def,
|
|
499
|
+
mapPTableDefV2(def, {
|
|
500
|
+
column: (c) => this.resolvePColumn(c),
|
|
501
|
+
node: collapseSpecOverrideNode,
|
|
502
|
+
}),
|
|
446
503
|
),
|
|
447
504
|
);
|
|
448
505
|
this.requireComputableCtx.addOnDestroy(guard.entry.unref);
|
|
449
506
|
return guard.keep().key;
|
|
450
507
|
}
|
|
451
508
|
|
|
509
|
+
/**
|
|
510
|
+
* Normalise a def element: pass-through for materialised columns (after
|
|
511
|
+
* mapping their `data` payload via {@link transformInputPData}), or resolve
|
|
512
|
+
* a bare id through the host column registry. `resolvePColumnById` extracts
|
|
513
|
+
* the underlying {@link PObjectId} from any id encoding
|
|
514
|
+
* ({@link ColumnOverriddenId}, etc.).
|
|
515
|
+
*/
|
|
516
|
+
private resolvePColumn(
|
|
517
|
+
item: PObjectId | PColumn<string | PColumnValues | DataInfo<string>>,
|
|
518
|
+
): PColumn<PlTreeNodeAccessor | PColumnValues | DataInfo<PlTreeNodeAccessor>> {
|
|
519
|
+
return typeof item === "string"
|
|
520
|
+
? resolvePColumnById(this.getColumnRegistry(), item)
|
|
521
|
+
: mapPObjectData(item, (d) => this.transformInputPData(d));
|
|
522
|
+
}
|
|
523
|
+
|
|
452
524
|
/**
|
|
453
525
|
* Transforms input data for PFrame/PTable creation
|
|
454
526
|
* - Converts string handles to accessors
|
|
@@ -495,7 +567,13 @@ export class ComputableContextHelper implements JsRenderInternal.GlobalCfgRender
|
|
|
495
567
|
// Helpers
|
|
496
568
|
//
|
|
497
569
|
|
|
498
|
-
|
|
570
|
+
/**
|
|
571
|
+
* Resolve a sandbox-side `AccessorHandle` string back to its concrete
|
|
572
|
+
* host accessor. Used internally by every `traverse`/`getX(handle)`
|
|
573
|
+
* method and externally by the `ColumnsCollection` service injector
|
|
574
|
+
* for `SerializedColumnsSource` of kind `"accessor"`.
|
|
575
|
+
*/
|
|
576
|
+
public getAccessor(handle: string): PlTreeNodeAccessor {
|
|
499
577
|
const accessor = this.accessors.get(handle);
|
|
500
578
|
if (accessor === undefined) throw new Error("No such accessor");
|
|
501
579
|
return accessor;
|
|
@@ -649,6 +727,10 @@ export class ComputableContextHelper implements JsRenderInternal.GlobalCfgRender
|
|
|
649
727
|
return parent.exportSingleValue(this.getIsFinal(vm.getString(handle)), undefined);
|
|
650
728
|
});
|
|
651
729
|
|
|
730
|
+
exportCtxFunction("hasData", (handle) => {
|
|
731
|
+
return parent.exportSingleValue(this.hasData(vm.getString(handle)), undefined);
|
|
732
|
+
});
|
|
733
|
+
|
|
652
734
|
exportCtxFunction("getError", (handle) => {
|
|
653
735
|
return parent.exportSingleValue(this.getError(vm.getString(handle)), undefined);
|
|
654
736
|
});
|
|
@@ -816,13 +898,6 @@ export class ComputableContextHelper implements JsRenderInternal.GlobalCfgRender
|
|
|
816
898
|
return parent.exportObjectUniversal(this.getSpecsFromResultPool(), undefined);
|
|
817
899
|
});
|
|
818
900
|
|
|
819
|
-
exportCtxFunction("calculateOptions", (predicate) => {
|
|
820
|
-
return parent.exportObjectUniversal(
|
|
821
|
-
this.calculateOptions(parent.importObjectViaJson(predicate) as PSpecPredicate),
|
|
822
|
-
undefined,
|
|
823
|
-
);
|
|
824
|
-
});
|
|
825
|
-
|
|
826
901
|
exportCtxFunction("getSpecFromResultPoolByRef", (blockId, exportName) => {
|
|
827
902
|
return parent.exportObjectUniversal(
|
|
828
903
|
this.getSpecFromResultPoolByRef(vm.getString(blockId), vm.getString(exportName)),
|
|
@@ -837,6 +912,10 @@ export class ComputableContextHelper implements JsRenderInternal.GlobalCfgRender
|
|
|
837
912
|
);
|
|
838
913
|
});
|
|
839
914
|
|
|
915
|
+
exportCtxFunction("getUpstreamBlockCtx", () => {
|
|
916
|
+
return parent.exportObjectUniversal(this.getUpstreamBlockCtx(), undefined);
|
|
917
|
+
});
|
|
918
|
+
|
|
840
919
|
exportCtxFunction("createPFrame", (def) => {
|
|
841
920
|
return parent.exportSingleValue(
|
|
842
921
|
this.createPFrame(
|
|
@@ -938,3 +1017,7 @@ export class ComputableContextHelper implements JsRenderInternal.GlobalCfgRender
|
|
|
938
1017
|
});
|
|
939
1018
|
}
|
|
940
1019
|
}
|
|
1020
|
+
|
|
1021
|
+
function bytesToBase64(data: Uint8Array | undefined): string | undefined {
|
|
1022
|
+
return data !== undefined ? Buffer.from(data).toString("base64") : undefined;
|
|
1023
|
+
}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { QuickJSHandle, VmFunctionImplementation } from "quickjs-emscripten";
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
CollectionHandle,
|
|
4
|
+
ColumnsCollectionDriverHost,
|
|
5
|
+
DiscoverColumnsOptions,
|
|
6
|
+
InferServiceModel,
|
|
7
|
+
PoolEntry,
|
|
8
|
+
SerializedColumnsSource,
|
|
9
|
+
ServiceBrand,
|
|
10
|
+
} from "@milaboratories/pl-model-common";
|
|
3
11
|
import { Services, ServiceNotRegisteredError } from "@milaboratories/pl-model-common";
|
|
12
|
+
import type { PlTreeNodeAccessor } from "@milaboratories/pl-tree";
|
|
4
13
|
import type {
|
|
5
14
|
AxesId,
|
|
6
15
|
AxesSpec,
|
|
@@ -8,6 +17,7 @@ import type {
|
|
|
8
17
|
PColumn,
|
|
9
18
|
PColumnSpec,
|
|
10
19
|
PColumnValues,
|
|
20
|
+
PObjectId,
|
|
11
21
|
PTableColumnId,
|
|
12
22
|
PTableColumnSpec,
|
|
13
23
|
PTableRecordFilter,
|
|
@@ -141,16 +151,12 @@ export function getServiceInjectors(): ServiceInjectorMap {
|
|
|
141
151
|
};
|
|
142
152
|
},
|
|
143
153
|
|
|
144
|
-
// Dialog has no model-side surface — workflow scripts cannot open save dialogs.
|
|
145
|
-
// Declared as an empty injector to satisfy the exhaustive ServiceInjectorMap.
|
|
146
|
-
Dialog: () => ({}) as Record<never, VmMethod>,
|
|
147
|
-
|
|
148
154
|
PFrame: ({ host, vm }: ServiceInjectorContext) => ({
|
|
149
155
|
createPFrame: (def: QuickJSHandle) =>
|
|
150
156
|
vm.exportSingleValue(
|
|
151
157
|
host.createPFrame(
|
|
152
158
|
vm.importObjectViaJson(def) as PFrameDef<
|
|
153
|
-
PColumn<string | PColumnValues | DataInfo<string>>
|
|
159
|
+
PObjectId | PColumn<string | PColumnValues | DataInfo<string>>
|
|
154
160
|
>,
|
|
155
161
|
),
|
|
156
162
|
),
|
|
@@ -159,7 +165,7 @@ export function getServiceInjectors(): ServiceInjectorMap {
|
|
|
159
165
|
vm.exportSingleValue(
|
|
160
166
|
host.createPTable(
|
|
161
167
|
vm.importObjectViaJson(def) as PTableDef<
|
|
162
|
-
PColumn<string | PColumnValues | DataInfo<string>>
|
|
168
|
+
PObjectId | PColumn<string | PColumnValues | DataInfo<string>>
|
|
163
169
|
>,
|
|
164
170
|
),
|
|
165
171
|
),
|
|
@@ -168,10 +174,102 @@ export function getServiceInjectors(): ServiceInjectorMap {
|
|
|
168
174
|
vm.exportSingleValue(
|
|
169
175
|
host.createPTableV2(
|
|
170
176
|
vm.importObjectViaJson(def) as PTableDefV2<
|
|
171
|
-
PColumn<string | PColumnValues | DataInfo<string>>
|
|
177
|
+
PObjectId | PColumn<string | PColumnValues | DataInfo<string>>
|
|
172
178
|
>,
|
|
173
179
|
),
|
|
174
180
|
),
|
|
175
181
|
}),
|
|
182
|
+
|
|
183
|
+
// Dialog has no model-side surface — workflow scripts cannot open save dialogs.
|
|
184
|
+
// Declared as an empty injector to satisfy the exhaustive ServiceInjectorMap.
|
|
185
|
+
Dialog: () => ({}) as Record<never, VmMethod>,
|
|
186
|
+
|
|
187
|
+
ColumnsCollection: ({ host, vm }: ServiceInjectorContext) => {
|
|
188
|
+
const driver = host.serviceRegistry.get(Services.ColumnsCollection);
|
|
189
|
+
if (!driver)
|
|
190
|
+
throw new ServiceNotRegisteredError(
|
|
191
|
+
`Service "${Services.ColumnsCollection}" has no factory in ModelServiceRegistry. Provide a non-null factory.`,
|
|
192
|
+
);
|
|
193
|
+
const specDriver = host.serviceRegistry.get(Services.PFrameSpec);
|
|
194
|
+
if (!specDriver)
|
|
195
|
+
throw new ServiceNotRegisteredError(
|
|
196
|
+
`Service "${Services.PFrameSpec}" has no factory in ModelServiceRegistry. Provide a non-null factory.`,
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const bindings: ColumnsCollectionDriverHost<PlTreeNodeAccessor> = {
|
|
200
|
+
resolveAccessor: (h) => host.getAccessor(h),
|
|
201
|
+
getUpstreamBlockCtxes: () => host.getRawUpstreamBlockCtx(),
|
|
202
|
+
getSpecDriver: () => specDriver,
|
|
203
|
+
resolveSpec: (id: PObjectId) => {
|
|
204
|
+
const leaf = host.getColumnRegistry().resolve(id);
|
|
205
|
+
if (leaf === undefined) return undefined;
|
|
206
|
+
const specNode = leaf.accessor.traverse({
|
|
207
|
+
field: `${leaf.name}.spec`,
|
|
208
|
+
assertFieldType: "Input",
|
|
209
|
+
ignoreError: true,
|
|
210
|
+
});
|
|
211
|
+
return specNode?.getDataAsJson<PColumnSpec>();
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const pinHandle = (entry: PoolEntry<CollectionHandle>): CollectionHandle => {
|
|
216
|
+
using guard = new PoolEntryGuard(entry);
|
|
217
|
+
host.addOnDestroy(guard.entry.unref);
|
|
218
|
+
return guard.keep().key;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
create: (sources: QuickJSHandle) =>
|
|
223
|
+
vm.exportSingleValue(
|
|
224
|
+
pinHandle(
|
|
225
|
+
driver.create(vm.importObjectViaJson(sources) as SerializedColumnsSource[], bindings),
|
|
226
|
+
),
|
|
227
|
+
),
|
|
228
|
+
|
|
229
|
+
isEmpty: (handle: QuickJSHandle) =>
|
|
230
|
+
vm.exportSingleValue(driver.isEmpty(vm.vm.getString(handle) as CollectionHandle)),
|
|
231
|
+
|
|
232
|
+
isFinal: (handle: QuickJSHandle) =>
|
|
233
|
+
vm.exportSingleValue(driver.isFinal(vm.vm.getString(handle) as CollectionHandle)),
|
|
234
|
+
|
|
235
|
+
getColumns: (handle: QuickJSHandle) =>
|
|
236
|
+
vm.exportObjectViaJson(
|
|
237
|
+
driver.getColumns(vm.vm.getString(handle) as CollectionHandle, bindings),
|
|
238
|
+
),
|
|
239
|
+
|
|
240
|
+
addSource: (handle: QuickJSHandle, sources: QuickJSHandle) =>
|
|
241
|
+
vm.exportSingleValue(
|
|
242
|
+
pinHandle(
|
|
243
|
+
driver.addSource(
|
|
244
|
+
vm.vm.getString(handle) as CollectionHandle,
|
|
245
|
+
vm.importObjectViaJson(sources) as SerializedColumnsSource[],
|
|
246
|
+
bindings,
|
|
247
|
+
),
|
|
248
|
+
),
|
|
249
|
+
),
|
|
250
|
+
|
|
251
|
+
discover: (handle: QuickJSHandle, opts: QuickJSHandle) =>
|
|
252
|
+
vm.exportSingleValue(
|
|
253
|
+
pinHandle(
|
|
254
|
+
driver.discover(
|
|
255
|
+
vm.vm.getString(handle) as CollectionHandle,
|
|
256
|
+
vm.importObjectViaJson(opts) as DiscoverColumnsOptions,
|
|
257
|
+
bindings,
|
|
258
|
+
),
|
|
259
|
+
),
|
|
260
|
+
),
|
|
261
|
+
|
|
262
|
+
filter: (handle: QuickJSHandle, opts: QuickJSHandle) =>
|
|
263
|
+
vm.exportSingleValue(
|
|
264
|
+
pinHandle(
|
|
265
|
+
driver.filter(
|
|
266
|
+
vm.vm.getString(handle) as CollectionHandle,
|
|
267
|
+
vm.importObjectViaJson(opts) as DiscoverColumnsOptions,
|
|
268
|
+
bindings,
|
|
269
|
+
),
|
|
270
|
+
),
|
|
271
|
+
),
|
|
272
|
+
};
|
|
273
|
+
},
|
|
176
274
|
};
|
|
177
275
|
}
|