@platforma-sdk/model 1.61.1 → 1.62.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/block_model.cjs +17 -10
- package/dist/block_model.cjs.map +1 -1
- package/dist/block_model.d.ts +22 -5
- package/dist/block_model.js +16 -10
- package/dist/block_model.js.map +1 -1
- package/dist/columns/column_collection_builder.cjs +26 -14
- package/dist/columns/column_collection_builder.cjs.map +1 -1
- package/dist/columns/column_collection_builder.d.ts +9 -8
- package/dist/columns/column_collection_builder.js +26 -14
- package/dist/columns/column_collection_builder.js.map +1 -1
- package/dist/columns/ctx_column_sources.cjs.map +1 -1
- package/dist/columns/ctx_column_sources.d.ts +1 -1
- package/dist/columns/ctx_column_sources.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +93 -89
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +2 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +93 -89
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.d.ts +2 -1
- package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
- package/dist/index.cjs +7 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +4 -1
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/dist/platforma.d.ts +8 -4
- package/dist/plugin_handle.cjs.map +1 -1
- package/dist/plugin_handle.d.ts +13 -7
- package/dist/plugin_handle.js.map +1 -1
- package/dist/plugin_model.cjs +37 -11
- package/dist/plugin_model.cjs.map +1 -1
- package/dist/plugin_model.d.ts +80 -39
- package/dist/plugin_model.js +37 -11
- package/dist/plugin_model.js.map +1 -1
- package/dist/render/api.cjs +13 -24
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +11 -14
- package/dist/render/api.js +13 -24
- package/dist/render/api.js.map +1 -1
- package/dist/render/internal.cjs.map +1 -1
- package/dist/render/internal.d.ts +3 -14
- package/dist/render/internal.js.map +1 -1
- package/dist/services/block_services.cjs +18 -0
- package/dist/services/block_services.cjs.map +1 -0
- package/dist/services/block_services.d.ts +18 -0
- package/dist/services/block_services.js +16 -0
- package/dist/services/block_services.js.map +1 -0
- package/dist/services/index.cjs +2 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.js +2 -0
- package/dist/services/service_bridge.cjs +35 -0
- package/dist/services/service_bridge.cjs.map +1 -0
- package/dist/services/service_bridge.d.ts +18 -0
- package/dist/services/service_bridge.js +33 -0
- package/dist/services/service_bridge.js.map +1 -0
- package/dist/services/service_resolve.d.ts +13 -0
- package/package.json +9 -9
- package/src/block_model.ts +47 -14
- package/src/columns/column_collection_builder.test.ts +23 -2
- package/src/columns/column_collection_builder.ts +38 -30
- package/src/columns/ctx_column_sources.ts +2 -2
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +159 -153
- package/src/components/PlDataTable/createPlDataTable/index.ts +5 -4
- package/src/index.ts +1 -0
- package/src/platforma.ts +14 -2
- package/src/plugin_handle.ts +24 -6
- package/src/plugin_model.ts +252 -84
- package/src/render/api.ts +50 -51
- package/src/render/internal.ts +3 -38
- package/src/services/block_services.ts +17 -0
- package/src/services/index.ts +3 -0
- package/src/services/service_bridge.ts +71 -0
- package/src/services/service_resolve.ts +71 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.js","names":[],"sources":["../../src/render/internal.ts"],"sourcesContent":["import type { Optional } from \"utility-types\";\nimport type {
|
|
1
|
+
{"version":3,"file":"internal.js","names":[],"sources":["../../src/render/internal.ts"],"sourcesContent":["import type { Optional } from \"utility-types\";\nimport type { Branded, StringifiedJson } from \"@milaboratories/pl-model-common\";\nimport type { CommonFieldTraverseOps, FieldTraversalStep, ResourceType } from \"./traversal_ops\";\nimport type {\n ArchiveFormat,\n AnyFunction,\n Option,\n PColumn,\n PColumnValues,\n PFrameDef,\n PFrameHandle,\n PObject,\n PObjectSpec,\n PSpecPredicate,\n PTableDef,\n PTableDefV2,\n PTableHandle,\n ResultCollection,\n ValueOrError,\n DataInfo,\n RangeBytes,\n} from \"@milaboratories/pl-model-common\";\nimport type { TreeNodeAccessor } from \"./accessor\";\nimport type { ServiceDispatch } from \"@milaboratories/pl-model-common\";\n\nexport const StagingAccessorName = \"staging\";\nexport const MainAccessorName = \"main\";\n\nexport type AccessorHandle = Branded<string, \"AccessorHandle\">;\nexport type FutureHandle = Branded<string, \"FutureHandle\">;\n\nexport type PColumnDataUniversal<TreeEntry = TreeNodeAccessor> =\n | TreeEntry\n | DataInfo<TreeEntry>\n | PColumnValues;\n\nexport interface GlobalCfgRenderCtxMethods<AHandle = AccessorHandle, FHandle = FutureHandle> {\n //\n // Root accessor creation\n //\n\n getAccessorHandleByName(name: string): AHandle | undefined;\n\n //\n // Basic resource accessor actions\n //\n\n resolveWithCommon(\n handle: AHandle,\n commonOptions: CommonFieldTraverseOps,\n ...steps: (FieldTraversalStep | string)[]\n ): AHandle | undefined;\n\n getResourceType(handle: AHandle): ResourceType;\n\n getInputsLocked(handle: AHandle): boolean;\n\n getOutputsLocked(handle: AHandle): boolean;\n\n getIsReadyOrError(handle: AHandle): boolean;\n\n getIsFinal(handle: AHandle): boolean;\n\n getError(handle: AHandle): AHandle | undefined;\n\n listInputFields(handle: AHandle): string[];\n\n listOutputFields(handle: AHandle): string[];\n\n listDynamicFields(handle: AHandle): string[];\n\n getKeyValueBase64(handle: AHandle, key: string): string | undefined;\n\n getKeyValueAsString(handle: AHandle, key: string): string | undefined;\n\n getDataBase64(handle: AHandle): string | undefined;\n\n getDataAsString(handle: AHandle): string | undefined;\n\n /** If not final returns undefined */\n parsePObjectCollection(\n handle: AHandle,\n errorOnUnknownField: boolean,\n prefix: string,\n ...resolvePath: string[]\n ): Record<string, PObject<AHandle>> | undefined;\n\n //\n // Blob\n //\n\n getBlobContentAsBase64(handle: AHandle, range?: RangeBytes): FHandle; // string | undefined\n\n getBlobContentAsString(handle: AHandle, range?: RangeBytes): FHandle; // string | undefined\n\n getDownloadedBlobContentHandle(handle: AHandle): FHandle; // LocalBlobHandleAndSize | undefined;\n\n getOnDemandBlobContentHandle(handle: AHandle): FHandle; // RemoteBlobHandleAndSize | undefined;\n\n //\n // Blobs to URLs\n //\n\n extractArchiveAndGetURL(handle: AHandle, format: ArchiveFormat): FHandle;\n\n //\n // Import progress\n //\n\n getImportProgress(handle: AHandle): FHandle; // ImportProgress;\n\n //\n // Logs\n //\n\n getLastLogs(handle: AHandle, nLines: number): FHandle; // string | undefined;\n\n getProgressLog(handle: AHandle, patternToSearch: string): FHandle; // string | undefined;\n\n getProgressLogWithInfo(handle: AHandle, patternToSearch: string): FHandle; // ProgressLogWithInfo | undefined;\n\n getLogHandle(handle: AHandle): FHandle; // AnyLogHandle | undefined;\n\n //\n // Blocks\n //\n\n /** @deprecated at some point will stop working and will return dummy values */\n getBlockLabel(blockId: string): string;\n\n //\n // Result Pool\n //\n\n getDataFromResultPool(): ResultCollection<PObject<AHandle>>;\n\n getDataWithErrorsFromResultPool(): ResultCollection<\n Optional<PObject<ValueOrError<AHandle, Error>>, \"id\">\n >;\n\n getSpecsFromResultPool(): ResultCollection<PObjectSpec>;\n\n getSpecFromResultPoolByRef(blockId: string, exportName: string): PObjectSpec | undefined;\n\n getDataFromResultPoolByRef(blockId: string, exportName: string): PObject<AHandle> | undefined;\n\n calculateOptions(predicate: PSpecPredicate): Option[];\n\n //\n // PFrame / PTable\n //\n\n createPFrame(def: PFrameDef<PColumn<AHandle | PColumnValues | DataInfo<AHandle>>>): PFrameHandle;\n\n createPTable(def: PTableDef<PColumn<AHandle | PColumnValues | DataInfo<AHandle>>>): PTableHandle;\n\n createPTableV2(\n def: PTableDefV2<PColumn<AHandle | PColumnValues | DataInfo<AHandle>>>,\n ): PTableHandle;\n\n //\n // Computable\n //\n\n getCurrentUnstableMarker(): string | undefined;\n\n //\n // Logging\n //\n\n logInfo(message: string): void;\n\n logWarn(message: string): void;\n\n logError(message: string): void;\n}\n\nexport const GlobalCfgRenderCtxFeatureFlags = {\n explicitColumnsSupport: true as const,\n inlineColumnsSupport: true as const,\n activeArgs: true as const,\n pTablePartitionFiltersSupport: true as const,\n pFrameInSetFilterSupport: true as const,\n};\n\nexport interface GlobalCfgRenderCtx extends GlobalCfgRenderCtxMethods, ServiceDispatch {\n //\n // State: Args, UI State, Active Args\n //\n // Old runtime injects these values as strings, new runtime injects them as functions\n // that return strings, if block declares supportsLazyState flag.\n // If function not called in lazy state API, then resulting output will not depend on these values,\n // and thus will not be recalculated on corresponding state change.\n //\n\n readonly args: string | (() => string);\n /** @deprecated Use `data` instead. Optional for backward compatibility - falls back to `data` if not injected. */\n readonly uiState?: string | (() => string);\n readonly data: string | (() => string);\n readonly activeArgs: undefined | string | (() => string | undefined);\n\n readonly blockStorage: () => StringifiedJson;\n\n // Note: strings below are used because, anyway, using strings is the only way\n // to get data inside the QuickJS context, as it is implemented now. With this\n // approach deserialization can be lazily postponed until it is actually needed.\n readonly callbackRegistry: Record<string, AnyFunction>;\n readonly featureFlags?: typeof GlobalCfgRenderCtxFeatureFlags;\n}\n\nexport type FutureAwait = {\n __awaited_futures__: FutureHandle[];\n};\n\nexport function isFutureAwait(obj: unknown): obj is FutureAwait {\n return typeof obj === \"object\" && obj !== null && \"__awaited_futures__\" in obj;\n}\n\nfunction addAllFutureAwaits(set: Set<string>, visited: Set<unknown>, node: unknown) {\n if (visited.has(node)) return;\n visited.add(node);\n\n const type = typeof node;\n if (type === \"object\") {\n if (isFutureAwait(node)) node.__awaited_futures__.forEach((a) => set.add(a));\n else if (Array.isArray(node))\n for (const nested of node) addAllFutureAwaits(set, visited, nested);\n else\n for (const [, nested] of Object.entries(node as object))\n if (nested !== node) addAllFutureAwaits(set, visited, nested);\n }\n}\n\nexport function getAllFutureAwaits(obj: unknown): Set<string> {\n const set = new Set<string>();\n addAllFutureAwaits(set, new Set(), obj);\n return set;\n}\n"],"mappings":";;;;;;;;;;AAyBA,MAAa,sBAAsB;AACnC,MAAa,mBAAmB;AAuJhC,MAAa,iCAAiC;CAC5C,wBAAwB;CACxB,sBAAsB;CACtB,YAAY;CACZ,+BAA+B;CAC/B,0BAA0B;CAC3B;AA+BD,SAAgB,cAAc,KAAkC;AAC9D,QAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,yBAAyB;;AAG7E,SAAS,mBAAmB,KAAkB,SAAuB,MAAe;AAClF,KAAI,QAAQ,IAAI,KAAK,CAAE;AACvB,SAAQ,IAAI,KAAK;AAGjB,KADa,OAAO,SACP,UACX;MAAI,cAAc,KAAK,CAAE,MAAK,oBAAoB,SAAS,MAAM,IAAI,IAAI,EAAE,CAAC;WACnE,MAAM,QAAQ,KAAK,CAC1B,MAAK,MAAM,UAAU,KAAM,oBAAmB,KAAK,SAAS,OAAO;MAEnE,MAAK,MAAM,GAAG,WAAW,OAAO,QAAQ,KAAe,CACrD,KAAI,WAAW,KAAM,oBAAmB,KAAK,SAAS,OAAO;;;AAIrE,SAAgB,mBAAmB,KAA2B;CAC5D,MAAM,sBAAM,IAAI,KAAa;AAC7B,oBAAmB,qBAAK,IAAI,KAAK,EAAE,IAAI;AACvC,QAAO"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
|
|
3
|
+
|
|
4
|
+
//#region src/services/block_services.ts
|
|
5
|
+
/**
|
|
6
|
+
* Services required by all V3 blocks by default.
|
|
7
|
+
* Edit this when a new service should be available to all blocks.
|
|
8
|
+
*
|
|
9
|
+
* Standalone module to avoid circular dependencies between block_model.ts
|
|
10
|
+
* and service type resolution.
|
|
11
|
+
*/
|
|
12
|
+
const BLOCK_SERVICE_FLAGS = { requiresPFrameSpec: true };
|
|
13
|
+
const blockServiceNames = (0, _milaboratories_pl_model_common.resolveRequiredServices)(BLOCK_SERVICE_FLAGS);
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
exports.BLOCK_SERVICE_FLAGS = BLOCK_SERVICE_FLAGS;
|
|
17
|
+
exports.blockServiceNames = blockServiceNames;
|
|
18
|
+
//# sourceMappingURL=block_services.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block_services.cjs","names":[],"sources":["../../src/services/block_services.ts"],"sourcesContent":["import type { ServiceRequireFlags } from \"@milaboratories/pl-model-common\";\nimport { resolveRequiredServices } from \"@milaboratories/pl-model-common\";\n\n/**\n * Services required by all V3 blocks by default.\n * Edit this when a new service should be available to all blocks.\n *\n * Standalone module to avoid circular dependencies between block_model.ts\n * and service type resolution.\n */\nexport const BLOCK_SERVICE_FLAGS = {\n requiresPFrameSpec: true,\n} as const satisfies Partial<ServiceRequireFlags>;\n\nexport type BlockServiceFlags = typeof BLOCK_SERVICE_FLAGS;\n\nexport const blockServiceNames = resolveRequiredServices(BLOCK_SERVICE_FLAGS);\n"],"mappings":";;;;;;;;;;;AAUA,MAAa,sBAAsB,EACjC,oBAAoB,MACrB;AAID,MAAa,iFAA4C,oBAAoB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as _milaboratories_pl_model_common0 from "@milaboratories/pl-model-common";
|
|
2
|
+
|
|
3
|
+
//#region src/services/block_services.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Services required by all V3 blocks by default.
|
|
6
|
+
* Edit this when a new service should be available to all blocks.
|
|
7
|
+
*
|
|
8
|
+
* Standalone module to avoid circular dependencies between block_model.ts
|
|
9
|
+
* and service type resolution.
|
|
10
|
+
*/
|
|
11
|
+
declare const BLOCK_SERVICE_FLAGS: {
|
|
12
|
+
readonly requiresPFrameSpec: true;
|
|
13
|
+
};
|
|
14
|
+
type BlockServiceFlags = typeof BLOCK_SERVICE_FLAGS;
|
|
15
|
+
declare const blockServiceNames: _milaboratories_pl_model_common0.ServiceName[];
|
|
16
|
+
//#endregion
|
|
17
|
+
export { BLOCK_SERVICE_FLAGS, BlockServiceFlags, blockServiceNames };
|
|
18
|
+
//# sourceMappingURL=block_services.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { resolveRequiredServices } from "@milaboratories/pl-model-common";
|
|
2
|
+
|
|
3
|
+
//#region src/services/block_services.ts
|
|
4
|
+
/**
|
|
5
|
+
* Services required by all V3 blocks by default.
|
|
6
|
+
* Edit this when a new service should be available to all blocks.
|
|
7
|
+
*
|
|
8
|
+
* Standalone module to avoid circular dependencies between block_model.ts
|
|
9
|
+
* and service type resolution.
|
|
10
|
+
*/
|
|
11
|
+
const BLOCK_SERVICE_FLAGS = { requiresPFrameSpec: true };
|
|
12
|
+
const blockServiceNames = resolveRequiredServices(BLOCK_SERVICE_FLAGS);
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { BLOCK_SERVICE_FLAGS, blockServiceNames };
|
|
16
|
+
//# sourceMappingURL=block_services.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block_services.js","names":[],"sources":["../../src/services/block_services.ts"],"sourcesContent":["import type { ServiceRequireFlags } from \"@milaboratories/pl-model-common\";\nimport { resolveRequiredServices } from \"@milaboratories/pl-model-common\";\n\n/**\n * Services required by all V3 blocks by default.\n * Edit this when a new service should be available to all blocks.\n *\n * Standalone module to avoid circular dependencies between block_model.ts\n * and service type resolution.\n */\nexport const BLOCK_SERVICE_FLAGS = {\n requiresPFrameSpec: true,\n} as const satisfies Partial<ServiceRequireFlags>;\n\nexport type BlockServiceFlags = typeof BLOCK_SERVICE_FLAGS;\n\nexport const blockServiceNames = resolveRequiredServices(BLOCK_SERVICE_FLAGS);\n"],"mappings":";;;;;;;;;;AAUA,MAAa,sBAAsB,EACjC,oBAAoB,MACrB;AAID,MAAa,oBAAoB,wBAAwB,oBAAoB"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { BLOCK_SERVICE_FLAGS, BlockServiceFlags, blockServiceNames } from "./block_services.js";
|
|
2
|
+
import { BlockDefaultModelServices, BlockDefaultUiServices, ModelServices, ResolveModelServices, ResolveUiServices, UiServices } from "./service_resolve.js";
|
|
3
|
+
import { NodeServiceProxy, buildServices, createNodeServiceProxy } from "./service_bridge.js";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/services/service_bridge.ts
|
|
3
|
+
/**
|
|
4
|
+
* Builds a lazy services object from ServiceDispatch and UiServiceRegistry.
|
|
5
|
+
* Each service is instantiated on first access. Errors are cached to prevent
|
|
6
|
+
* repeated factory calls on failure.
|
|
7
|
+
*/
|
|
8
|
+
function buildServices(dispatch, registry) {
|
|
9
|
+
return Object.create(null, Object.fromEntries(dispatch.getServiceNames().map((id) => {
|
|
10
|
+
let fetched = false;
|
|
11
|
+
let cached;
|
|
12
|
+
return [id, {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get() {
|
|
15
|
+
if (!fetched) {
|
|
16
|
+
fetched = true;
|
|
17
|
+
cached = registry.get(id);
|
|
18
|
+
}
|
|
19
|
+
return cached;
|
|
20
|
+
}
|
|
21
|
+
}];
|
|
22
|
+
})));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Builds a NodeServiceProxy from a ServiceDispatch.
|
|
26
|
+
* Each service method call is forwarded to dispatch.callServiceMethod.
|
|
27
|
+
*/
|
|
28
|
+
function createNodeServiceProxy(dispatch) {
|
|
29
|
+
return ((serviceId) => Object.freeze(Object.fromEntries(dispatch.getServiceMethods(serviceId).map((method) => [method, async (...args) => dispatch.callServiceMethod(serviceId, method, ...args)]))));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
exports.buildServices = buildServices;
|
|
34
|
+
exports.createNodeServiceProxy = createNodeServiceProxy;
|
|
35
|
+
//# sourceMappingURL=service_bridge.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service_bridge.cjs","names":[],"sources":["../../src/services/service_bridge.ts"],"sourcesContent":["/**\n * Runtime service bridge — builds lazy service objects from dispatch + registry.\n * Used by the UI layer to provide typed service access.\n */\n\nimport type {\n ServiceTypesLike,\n InferServiceUi,\n ServiceName,\n ServiceDispatch,\n UiServices as AllUiServices,\n} from \"@milaboratories/pl-model-common\";\nimport { UiServiceRegistry } from \"@milaboratories/pl-model-common\";\n\n// Makes a remote node service appear local.\n// Given a service ID, returns an object implementing the service's UI interface.\n// Provided by the desktop app (e.g. backed by Electron IPC).\nexport type NodeServiceProxy = <S extends ServiceTypesLike>(\n serviceId: ServiceName<S>,\n) => InferServiceUi<S>;\n\n/**\n * Builds a lazy services object from ServiceDispatch and UiServiceRegistry.\n * Each service is instantiated on first access. Errors are cached to prevent\n * repeated factory calls on failure.\n */\nexport function buildServices<S extends Partial<AllUiServices> = Partial<AllUiServices>>(\n dispatch: ServiceDispatch,\n registry: UiServiceRegistry,\n): S {\n return Object.create(\n null,\n Object.fromEntries(\n dispatch.getServiceNames().map((id) => {\n let fetched = false;\n let cached: unknown;\n return [\n id,\n {\n enumerable: true,\n get() {\n if (!fetched) {\n fetched = true;\n cached = registry.get(id);\n }\n return cached;\n },\n },\n ];\n }),\n ),\n );\n}\n\n/**\n * Builds a NodeServiceProxy from a ServiceDispatch.\n * Each service method call is forwarded to dispatch.callServiceMethod.\n */\nexport function createNodeServiceProxy(dispatch: ServiceDispatch): NodeServiceProxy {\n return ((serviceId: ServiceName) =>\n Object.freeze(\n Object.fromEntries(\n dispatch\n .getServiceMethods(serviceId)\n .map((method) => [\n method,\n async (...args: unknown[]) => dispatch.callServiceMethod(serviceId, method, ...args),\n ]),\n ),\n )) as NodeServiceProxy;\n}\n"],"mappings":";;;;;;;AA0BA,SAAgB,cACd,UACA,UACG;AACH,QAAO,OAAO,OACZ,MACA,OAAO,YACL,SAAS,iBAAiB,CAAC,KAAK,OAAO;EACrC,IAAI,UAAU;EACd,IAAI;AACJ,SAAO,CACL,IACA;GACE,YAAY;GACZ,MAAM;AACJ,QAAI,CAAC,SAAS;AACZ,eAAU;AACV,cAAS,SAAS,IAAI,GAAG;;AAE3B,WAAO;;GAEV,CACF;GACD,CACH,CACF;;;;;;AAOH,SAAgB,uBAAuB,UAA6C;AAClF,UAAS,cACP,OAAO,OACL,OAAO,YACL,SACG,kBAAkB,UAAU,CAC5B,KAAK,WAAW,CACf,QACA,OAAO,GAAG,SAAoB,SAAS,kBAAkB,WAAW,QAAQ,GAAG,KAAK,CACrF,CAAC,CACL,CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { InferServiceUi, ServiceDispatch, ServiceName, ServiceTypesLike, UiServiceRegistry, UiServices } from "@milaboratories/pl-model-common";
|
|
2
|
+
|
|
3
|
+
//#region src/services/service_bridge.d.ts
|
|
4
|
+
type NodeServiceProxy = <S extends ServiceTypesLike>(serviceId: ServiceName<S>) => InferServiceUi<S>;
|
|
5
|
+
/**
|
|
6
|
+
* Builds a lazy services object from ServiceDispatch and UiServiceRegistry.
|
|
7
|
+
* Each service is instantiated on first access. Errors are cached to prevent
|
|
8
|
+
* repeated factory calls on failure.
|
|
9
|
+
*/
|
|
10
|
+
declare function buildServices<S extends Partial<UiServices> = Partial<UiServices>>(dispatch: ServiceDispatch, registry: UiServiceRegistry): S;
|
|
11
|
+
/**
|
|
12
|
+
* Builds a NodeServiceProxy from a ServiceDispatch.
|
|
13
|
+
* Each service method call is forwarded to dispatch.callServiceMethod.
|
|
14
|
+
*/
|
|
15
|
+
declare function createNodeServiceProxy(dispatch: ServiceDispatch): NodeServiceProxy;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { NodeServiceProxy, buildServices, createNodeServiceProxy };
|
|
18
|
+
//# sourceMappingURL=service_bridge.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/services/service_bridge.ts
|
|
2
|
+
/**
|
|
3
|
+
* Builds a lazy services object from ServiceDispatch and UiServiceRegistry.
|
|
4
|
+
* Each service is instantiated on first access. Errors are cached to prevent
|
|
5
|
+
* repeated factory calls on failure.
|
|
6
|
+
*/
|
|
7
|
+
function buildServices(dispatch, registry) {
|
|
8
|
+
return Object.create(null, Object.fromEntries(dispatch.getServiceNames().map((id) => {
|
|
9
|
+
let fetched = false;
|
|
10
|
+
let cached;
|
|
11
|
+
return [id, {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get() {
|
|
14
|
+
if (!fetched) {
|
|
15
|
+
fetched = true;
|
|
16
|
+
cached = registry.get(id);
|
|
17
|
+
}
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
20
|
+
}];
|
|
21
|
+
})));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Builds a NodeServiceProxy from a ServiceDispatch.
|
|
25
|
+
* Each service method call is forwarded to dispatch.callServiceMethod.
|
|
26
|
+
*/
|
|
27
|
+
function createNodeServiceProxy(dispatch) {
|
|
28
|
+
return ((serviceId) => Object.freeze(Object.fromEntries(dispatch.getServiceMethods(serviceId).map((method) => [method, async (...args) => dispatch.callServiceMethod(serviceId, method, ...args)]))));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { buildServices, createNodeServiceProxy };
|
|
33
|
+
//# sourceMappingURL=service_bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service_bridge.js","names":[],"sources":["../../src/services/service_bridge.ts"],"sourcesContent":["/**\n * Runtime service bridge — builds lazy service objects from dispatch + registry.\n * Used by the UI layer to provide typed service access.\n */\n\nimport type {\n ServiceTypesLike,\n InferServiceUi,\n ServiceName,\n ServiceDispatch,\n UiServices as AllUiServices,\n} from \"@milaboratories/pl-model-common\";\nimport { UiServiceRegistry } from \"@milaboratories/pl-model-common\";\n\n// Makes a remote node service appear local.\n// Given a service ID, returns an object implementing the service's UI interface.\n// Provided by the desktop app (e.g. backed by Electron IPC).\nexport type NodeServiceProxy = <S extends ServiceTypesLike>(\n serviceId: ServiceName<S>,\n) => InferServiceUi<S>;\n\n/**\n * Builds a lazy services object from ServiceDispatch and UiServiceRegistry.\n * Each service is instantiated on first access. Errors are cached to prevent\n * repeated factory calls on failure.\n */\nexport function buildServices<S extends Partial<AllUiServices> = Partial<AllUiServices>>(\n dispatch: ServiceDispatch,\n registry: UiServiceRegistry,\n): S {\n return Object.create(\n null,\n Object.fromEntries(\n dispatch.getServiceNames().map((id) => {\n let fetched = false;\n let cached: unknown;\n return [\n id,\n {\n enumerable: true,\n get() {\n if (!fetched) {\n fetched = true;\n cached = registry.get(id);\n }\n return cached;\n },\n },\n ];\n }),\n ),\n );\n}\n\n/**\n * Builds a NodeServiceProxy from a ServiceDispatch.\n * Each service method call is forwarded to dispatch.callServiceMethod.\n */\nexport function createNodeServiceProxy(dispatch: ServiceDispatch): NodeServiceProxy {\n return ((serviceId: ServiceName) =>\n Object.freeze(\n Object.fromEntries(\n dispatch\n .getServiceMethods(serviceId)\n .map((method) => [\n method,\n async (...args: unknown[]) => dispatch.callServiceMethod(serviceId, method, ...args),\n ]),\n ),\n )) as NodeServiceProxy;\n}\n"],"mappings":";;;;;;AA0BA,SAAgB,cACd,UACA,UACG;AACH,QAAO,OAAO,OACZ,MACA,OAAO,YACL,SAAS,iBAAiB,CAAC,KAAK,OAAO;EACrC,IAAI,UAAU;EACd,IAAI;AACJ,SAAO,CACL,IACA;GACE,YAAY;GACZ,MAAM;AACJ,QAAI,CAAC,SAAS;AACZ,eAAU;AACV,cAAS,SAAS,IAAI,GAAG;;AAE3B,WAAO;;GAEV,CACF;GACD,CACH,CACF;;;;;;AAOH,SAAgB,uBAAuB,UAA6C;AAClF,UAAS,cACP,OAAO,OACL,OAAO,YACL,SACG,kBAAkB,UAAU,CAC5B,KAAK,WAAW,CACf,QACA,OAAO,GAAG,SAAoB,SAAS,kBAAkB,WAAW,QAAQ,GAAG,KAAK,CACrF,CAAC,CACL,CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BlockServiceFlags } from "./block_services.js";
|
|
2
|
+
import { ModelServices as ModelServices$1, ServiceNameLiterals, UiServices as UiServices$1 } from "@milaboratories/pl-model-common";
|
|
3
|
+
|
|
4
|
+
//#region src/services/service_resolve.d.ts
|
|
5
|
+
type FlagToName<Flag extends string> = Flag extends `requires${infer K}` ? K extends keyof ServiceNameLiterals ? ServiceNameLiterals[K] : never : never;
|
|
6
|
+
type RequiredServiceNames<Flags> = { [K in keyof Flags & `requires${string}`]: Flags[K] extends true ? FlagToName<K & string> : never }[keyof Flags & `requires${string}`];
|
|
7
|
+
type ResolveModelServices<Flags> = Pick<ModelServices$1, RequiredServiceNames<Flags> & keyof ModelServices$1>;
|
|
8
|
+
type ResolveUiServices<Flags> = Pick<UiServices$1, RequiredServiceNames<Flags> & keyof UiServices$1>;
|
|
9
|
+
type BlockDefaultModelServices = ResolveModelServices<BlockServiceFlags>;
|
|
10
|
+
type BlockDefaultUiServices = ResolveUiServices<BlockServiceFlags>;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { BlockDefaultModelServices, BlockDefaultUiServices, type ModelServices$1 as ModelServices, ResolveModelServices, ResolveUiServices, type UiServices$1 as UiServices };
|
|
13
|
+
//# sourceMappingURL=service_resolve.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-sdk/model",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.62.0",
|
|
4
4
|
"description": "Platforma.bio SDK / Block Model",
|
|
5
5
|
"files": [
|
|
6
6
|
"./dist/**/*",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"utility-types": "^3.11.0",
|
|
32
32
|
"zod": "~3.23.8",
|
|
33
33
|
"@milaboratories/helpers": "1.14.0",
|
|
34
|
-
"@milaboratories/pl-model-common": "1.
|
|
35
|
-
"@milaboratories/pl-model-middle-layer": "1.16.
|
|
36
|
-
"@milaboratories/
|
|
37
|
-
"@milaboratories/
|
|
34
|
+
"@milaboratories/pl-model-common": "1.30.0",
|
|
35
|
+
"@milaboratories/pl-model-middle-layer": "1.16.1",
|
|
36
|
+
"@milaboratories/pl-error-like": "1.12.9",
|
|
37
|
+
"@milaboratories/ptabler-expression-js": "1.2.3"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@vitest/coverage-istanbul": "^4.0.18",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"typescript": "~5.9.3",
|
|
43
43
|
"vitest": "^4.0.18",
|
|
44
44
|
"@milaboratories/build-configs": "1.5.2",
|
|
45
|
-
"@milaboratories/pf-spec-driver": "1.
|
|
46
|
-
"@milaboratories/
|
|
47
|
-
"@milaboratories/
|
|
48
|
-
"@milaboratories/ts-
|
|
45
|
+
"@milaboratories/pf-spec-driver": "1.2.0",
|
|
46
|
+
"@milaboratories/ts-builder": "1.3.0",
|
|
47
|
+
"@milaboratories/pf-driver": "1.3.0",
|
|
48
|
+
"@milaboratories/ts-configs": "1.2.2"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "ts-builder build --target node",
|
package/src/block_model.ts
CHANGED
|
@@ -6,9 +6,12 @@ import type {
|
|
|
6
6
|
BlockCodeKnownFeatureFlags,
|
|
7
7
|
BlockConfigContainer,
|
|
8
8
|
} from "@milaboratories/pl-model-common";
|
|
9
|
+
import { resolveRequiredServices } from "@milaboratories/pl-model-common";
|
|
9
10
|
import { getPlatformaInstance, isInUI, createAndRegisterRenderLambda } from "./internal";
|
|
10
11
|
import type { DataModel } from "./block_migrations";
|
|
11
12
|
import type { PlatformaV3 } from "./platforma";
|
|
13
|
+
import type { BlockDefaultUiServices } from "./services/service_resolve";
|
|
14
|
+
import { blockServiceNames, BLOCK_SERVICE_FLAGS } from "./services/block_services";
|
|
12
15
|
import type { InferRenderFunctionReturn, RenderFunction } from "./render";
|
|
13
16
|
import { BlockRenderCtx, PluginRenderCtx } from "./render";
|
|
14
17
|
import type { PluginData, PluginModel, PluginOutputs, PluginParams } from "./plugin_model";
|
|
@@ -87,8 +90,10 @@ export type PluginRecord<
|
|
|
87
90
|
Data extends PluginData = PluginData,
|
|
88
91
|
Params extends PluginParams = undefined,
|
|
89
92
|
Outputs extends PluginOutputs = PluginOutputs,
|
|
93
|
+
ModelServices = unknown,
|
|
94
|
+
UiServices = unknown,
|
|
90
95
|
> = {
|
|
91
|
-
readonly model: PluginModel<Data, Params, Outputs>;
|
|
96
|
+
readonly model: PluginModel<Data, Params, Outputs, ModelServices, UiServices>;
|
|
92
97
|
readonly inputs: ParamsInputErased;
|
|
93
98
|
};
|
|
94
99
|
|
|
@@ -128,13 +133,17 @@ export class BlockModelV3<
|
|
|
128
133
|
private readonly config: BlockModelV3Config<OutputsCfg, Data, Plugins, Transfers>,
|
|
129
134
|
) {}
|
|
130
135
|
|
|
131
|
-
public static readonly
|
|
136
|
+
public static readonly FEATURE_FLAGS = {
|
|
132
137
|
supportsLazyState: true,
|
|
133
138
|
supportsPframeQueryRanking: true,
|
|
134
139
|
requiresUIAPIVersion: 3,
|
|
135
140
|
requiresModelAPIVersion: BLOCK_STORAGE_FACADE_VERSION,
|
|
136
141
|
requiresCreatePTable: 2,
|
|
137
|
-
|
|
142
|
+
...BLOCK_SERVICE_FLAGS,
|
|
143
|
+
} satisfies BlockCodeKnownFeatureFlags;
|
|
144
|
+
|
|
145
|
+
/** @deprecated Use FEATURE_FLAGS */
|
|
146
|
+
public static readonly INITIAL_BLOCK_FEATURE_FLAGS = BlockModelV3.FEATURE_FLAGS;
|
|
138
147
|
|
|
139
148
|
/**
|
|
140
149
|
* Creates a new BlockModelV3 builder with the specified data model.
|
|
@@ -164,7 +173,7 @@ export class BlockModelV3<
|
|
|
164
173
|
subtitle: undefined,
|
|
165
174
|
tags: undefined,
|
|
166
175
|
enrichmentTargets: undefined,
|
|
167
|
-
featureFlags: { ...BlockModelV3.
|
|
176
|
+
featureFlags: { ...BlockModelV3.FEATURE_FLAGS },
|
|
168
177
|
argsFunction: undefined,
|
|
169
178
|
prerunArgsFunction: undefined,
|
|
170
179
|
plugins: {},
|
|
@@ -228,7 +237,7 @@ export class BlockModelV3<
|
|
|
228
237
|
...this.config.outputs,
|
|
229
238
|
[key]: createAndRegisterRenderLambda({
|
|
230
239
|
handle: `block-output#${key}`,
|
|
231
|
-
lambda: () => cfgOrRf(new BlockRenderCtx<Args, Data>()),
|
|
240
|
+
lambda: () => cfgOrRf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
|
|
232
241
|
...flags,
|
|
233
242
|
}),
|
|
234
243
|
},
|
|
@@ -324,7 +333,10 @@ export class BlockModelV3<
|
|
|
324
333
|
...this.config,
|
|
325
334
|
// Replace the default sections callback with the user-provided one
|
|
326
335
|
sections: createAndRegisterRenderLambda(
|
|
327
|
-
{
|
|
336
|
+
{
|
|
337
|
+
handle: "sections",
|
|
338
|
+
lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
|
|
339
|
+
},
|
|
328
340
|
true,
|
|
329
341
|
),
|
|
330
342
|
},
|
|
@@ -339,7 +351,7 @@ export class BlockModelV3<
|
|
|
339
351
|
...this.config,
|
|
340
352
|
title: createAndRegisterRenderLambda({
|
|
341
353
|
handle: "title",
|
|
342
|
-
lambda: () => rf(new BlockRenderCtx<Args, Data>()),
|
|
354
|
+
lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
|
|
343
355
|
}),
|
|
344
356
|
});
|
|
345
357
|
}
|
|
@@ -351,7 +363,7 @@ export class BlockModelV3<
|
|
|
351
363
|
...this.config,
|
|
352
364
|
subtitle: createAndRegisterRenderLambda({
|
|
353
365
|
handle: "subtitle",
|
|
354
|
-
lambda: () => rf(new BlockRenderCtx<Args, Data>()),
|
|
366
|
+
lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
|
|
355
367
|
}),
|
|
356
368
|
});
|
|
357
369
|
}
|
|
@@ -363,7 +375,7 @@ export class BlockModelV3<
|
|
|
363
375
|
...this.config,
|
|
364
376
|
tags: createAndRegisterRenderLambda({
|
|
365
377
|
handle: "tags",
|
|
366
|
-
lambda: () => rf(new BlockRenderCtx<Args, Data>()),
|
|
378
|
+
lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
|
|
367
379
|
}),
|
|
368
380
|
});
|
|
369
381
|
}
|
|
@@ -418,6 +430,8 @@ export class BlockModelV3<
|
|
|
418
430
|
PParams extends PluginParams,
|
|
419
431
|
POutputs extends PluginOutputs,
|
|
420
432
|
PTransferData,
|
|
433
|
+
PluginModelServices,
|
|
434
|
+
PluginUiServices,
|
|
421
435
|
>(
|
|
422
436
|
instance: PluginInstanceClass<
|
|
423
437
|
PluginId &
|
|
@@ -432,7 +446,9 @@ export class BlockModelV3<
|
|
|
432
446
|
PData,
|
|
433
447
|
PParams,
|
|
434
448
|
POutputs,
|
|
435
|
-
PTransferData
|
|
449
|
+
PTransferData,
|
|
450
|
+
PluginModelServices,
|
|
451
|
+
PluginUiServices
|
|
436
452
|
>,
|
|
437
453
|
params?: ParamsInput<PParams, Args, Data>,
|
|
438
454
|
): BlockModelV3<
|
|
@@ -440,7 +456,15 @@ export class BlockModelV3<
|
|
|
440
456
|
OutputsCfg,
|
|
441
457
|
Data,
|
|
442
458
|
Href,
|
|
443
|
-
Plugins & {
|
|
459
|
+
Plugins & {
|
|
460
|
+
[K in PluginId]: PluginRecord<
|
|
461
|
+
PData,
|
|
462
|
+
PParams,
|
|
463
|
+
POutputs,
|
|
464
|
+
PluginModelServices,
|
|
465
|
+
PluginUiServices
|
|
466
|
+
>;
|
|
467
|
+
},
|
|
444
468
|
Omit<Transfers, PluginId>
|
|
445
469
|
>;
|
|
446
470
|
public plugin(
|
|
@@ -489,7 +513,14 @@ export class BlockModelV3<
|
|
|
489
513
|
public done(
|
|
490
514
|
..._: keyof Transfers extends never ? [] : [never]
|
|
491
515
|
): PlatformaExtended<
|
|
492
|
-
PlatformaV3<
|
|
516
|
+
PlatformaV3<
|
|
517
|
+
Data,
|
|
518
|
+
Args,
|
|
519
|
+
InferOutputsFromLambdas<OutputsCfg>,
|
|
520
|
+
Href,
|
|
521
|
+
Plugins,
|
|
522
|
+
BlockDefaultUiServices
|
|
523
|
+
>
|
|
493
524
|
> {
|
|
494
525
|
if (this.config.argsFunction === undefined) throw new Error("Args rendering function not set.");
|
|
495
526
|
|
|
@@ -505,6 +536,8 @@ export class BlockModelV3<
|
|
|
505
536
|
|
|
506
537
|
const { dataModel, argsFunction, prerunArgsFunction } = this.config;
|
|
507
538
|
|
|
539
|
+
const mergedServiceNames = resolveRequiredServices(this.config.featureFlags);
|
|
540
|
+
|
|
508
541
|
function getPlugin(handle: PluginHandle): PluginRecord {
|
|
509
542
|
const plugin = plugins[handle];
|
|
510
543
|
if (!plugin) throw new Error(`Plugin model not found for '${handle}'`);
|
|
@@ -544,7 +577,7 @@ export class BlockModelV3<
|
|
|
544
577
|
// Wrap plugin param lambdas: close over BlockRenderCtx creation
|
|
545
578
|
const wrappedInputs: Record<string, () => unknown> = {};
|
|
546
579
|
for (const [paramKey, paramFn] of Object.entries(inputs)) {
|
|
547
|
-
wrappedInputs[paramKey] = () => paramFn(new BlockRenderCtx());
|
|
580
|
+
wrappedInputs[paramKey] = () => paramFn(new BlockRenderCtx(mergedServiceNames));
|
|
548
581
|
}
|
|
549
582
|
|
|
550
583
|
// Register plugin outputs (in config pack, evaluated by middle layer)
|
|
@@ -554,7 +587,7 @@ export class BlockModelV3<
|
|
|
554
587
|
const key = pluginOutputKey(handle, outputKey);
|
|
555
588
|
pluginOutputs[key] = createAndRegisterRenderLambda({
|
|
556
589
|
handle: key,
|
|
557
|
-
lambda: () => outputFn(new PluginRenderCtx(handle, wrappedInputs)),
|
|
590
|
+
lambda: () => outputFn(new PluginRenderCtx(handle, wrappedInputs, mergedServiceNames)),
|
|
558
591
|
withStatus: outputFlags[outputKey]?.withStatus,
|
|
559
592
|
});
|
|
560
593
|
}
|
|
@@ -20,8 +20,8 @@ function createSpecFrameCtx() {
|
|
|
20
20
|
return driver;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
afterEach(() => {
|
|
24
|
-
for (const driver of drivers) driver.dispose();
|
|
23
|
+
afterEach(async () => {
|
|
24
|
+
for (const driver of drivers) await driver.dispose();
|
|
25
25
|
drivers.length = 0;
|
|
26
26
|
});
|
|
27
27
|
|
|
@@ -166,6 +166,27 @@ describe("ColumnCollection.findColumns", () => {
|
|
|
166
166
|
expect(results).toHaveLength(1);
|
|
167
167
|
expect(results[0].spec.name).toBe("col2");
|
|
168
168
|
});
|
|
169
|
+
|
|
170
|
+
test("include filters by exact name among disjoint-axis columns", () => {
|
|
171
|
+
const vdjAxis = sampleAxis("pl7.app/vdj/clonotypeKey");
|
|
172
|
+
const itemAxis = sampleAxis("item");
|
|
173
|
+
|
|
174
|
+
const vdjColumns = Array.from({ length: 10 }, (_, i) =>
|
|
175
|
+
createSnapshot(`vdj${i}`, createSpec(`pl7.app/vdj/col${i}`, { axesSpec: [vdjAxis] })),
|
|
176
|
+
);
|
|
177
|
+
const mockScore = createSnapshot("mock", createSpec("mock_score", { axesSpec: [itemAxis] }));
|
|
178
|
+
|
|
179
|
+
const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
|
|
180
|
+
builder.addSource([...vdjColumns, mockScore]);
|
|
181
|
+
|
|
182
|
+
const collection = builder.build()!;
|
|
183
|
+
const results = collection.findColumns({
|
|
184
|
+
include: [{ name: [{ type: "exact", value: "mock_score" }] }],
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
expect(results).toHaveLength(1);
|
|
188
|
+
expect(results[0].spec.name).toBe("mock_score");
|
|
189
|
+
});
|
|
169
190
|
});
|
|
170
191
|
|
|
171
192
|
describe("dedup by native ID", () => {
|