@milaboratories/pl-model-common 1.35.0 → 1.36.1
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/dialog/index.d.ts +34 -0
- package/dist/dialog/index.d.ts.map +1 -0
- package/dist/drivers/index.d.ts +1 -1
- package/dist/drivers/pframe/data_types.cjs +1 -0
- package/dist/drivers/pframe/data_types.cjs.map +1 -1
- package/dist/drivers/pframe/data_types.d.ts +27 -1
- package/dist/drivers/pframe/data_types.d.ts.map +1 -1
- package/dist/drivers/pframe/data_types.js +1 -1
- package/dist/drivers/pframe/data_types.js.map +1 -1
- package/dist/drivers/pframe/driver.cjs.map +1 -1
- package/dist/drivers/pframe/driver.d.ts +6 -1
- package/dist/drivers/pframe/driver.d.ts.map +1 -1
- package/dist/drivers/pframe/driver.js.map +1 -1
- package/dist/drivers/pframe/index.d.ts +1 -1
- package/dist/drivers/pframe/query/query_common.d.ts +14 -28
- package/dist/drivers/pframe/query/query_common.d.ts.map +1 -1
- package/dist/drivers/pframe/query/query_data.d.ts +3 -3
- package/dist/drivers/pframe/query/query_data.d.ts.map +1 -1
- package/dist/drivers/pframe/query/query_spec.d.ts +9 -25
- package/dist/drivers/pframe/query/query_spec.d.ts.map +1 -1
- package/dist/drivers/pframe/query/utils.cjs +19 -14
- package/dist/drivers/pframe/query/utils.cjs.map +1 -1
- package/dist/drivers/pframe/query/utils.js +19 -14
- package/dist/drivers/pframe/query/utils.js.map +1 -1
- package/dist/index.cjs +10 -3
- package/dist/index.d.ts +6 -5
- package/dist/index.js +5 -5
- package/dist/services/index.cjs +1 -1
- package/dist/services/index.d.ts +3 -3
- package/dist/services/index.js +1 -1
- package/dist/services/{service_injector_factory.js → node_service_handlers.cjs} +6 -5
- package/dist/services/node_service_handlers.cjs.map +1 -0
- package/dist/services/node_service_handlers.d.ts +8 -0
- package/dist/services/node_service_handlers.d.ts.map +1 -0
- package/dist/services/{service_injector_factory.cjs → node_service_handlers.js} +6 -5
- package/dist/services/node_service_handlers.js.map +1 -0
- package/dist/services/service_declarations.cjs +48 -2
- package/dist/services/service_declarations.cjs.map +1 -1
- package/dist/services/service_declarations.d.ts +2 -0
- package/dist/services/service_declarations.d.ts.map +1 -1
- package/dist/services/service_declarations.js +48 -2
- package/dist/services/service_declarations.js.map +1 -1
- package/dist/services/service_injectors.cjs +29 -25
- package/dist/services/service_injectors.cjs.map +1 -1
- package/dist/services/service_injectors.d.ts +21 -10
- package/dist/services/service_injectors.d.ts.map +1 -1
- package/dist/services/service_injectors.js +29 -26
- package/dist/services/service_injectors.js.map +1 -1
- package/dist/services/service_types.cjs +26 -2
- package/dist/services/service_types.cjs.map +1 -1
- package/dist/services/service_types.d.ts +6 -4
- package/dist/services/service_types.d.ts.map +1 -1
- package/dist/services/service_types.js +22 -3
- package/dist/services/service_types.js.map +1 -1
- package/package.json +3 -3
- package/src/dialog/index.ts +33 -0
- package/src/drivers/pframe/data_types.ts +30 -1
- package/src/drivers/pframe/driver.ts +17 -2
- package/src/drivers/pframe/query/query_common.ts +13 -5
- package/src/drivers/pframe/query/query_data.ts +2 -3
- package/src/drivers/pframe/query/query_spec.ts +9 -33
- package/src/drivers/pframe/query/utils.ts +26 -16
- package/src/index.ts +1 -0
- package/src/services/{service_injector_factory.ts → node_service_handlers.ts} +13 -6
- package/src/services/service_declarations.ts +60 -3
- package/src/services/service_injectors.ts +50 -34
- package/src/services/service_types.ts +38 -4
- package/dist/services/service_injector_factory.cjs.map +0 -1
- package/dist/services/service_injector_factory.d.ts +0 -8
- package/dist/services/service_injector_factory.d.ts.map +0 -1
- package/dist/services/service_injector_factory.js.map +0 -1
|
@@ -3,11 +3,57 @@ import { service } from "./service_types.js";
|
|
|
3
3
|
const Services = {
|
|
4
4
|
PFrameSpec: service()({
|
|
5
5
|
type: "wasm",
|
|
6
|
-
name: "pframeSpec"
|
|
6
|
+
name: "pframeSpec",
|
|
7
|
+
modelMethods: [
|
|
8
|
+
"createSpecFrame",
|
|
9
|
+
"listColumns",
|
|
10
|
+
"discoverColumns",
|
|
11
|
+
"deleteColumn",
|
|
12
|
+
"evaluateQuery",
|
|
13
|
+
"buildQuery",
|
|
14
|
+
"expandAxes",
|
|
15
|
+
"collapseAxes",
|
|
16
|
+
"findAxis",
|
|
17
|
+
"findTableColumn"
|
|
18
|
+
],
|
|
19
|
+
uiMethods: [
|
|
20
|
+
"createSpecFrame",
|
|
21
|
+
"listColumns",
|
|
22
|
+
"discoverColumns",
|
|
23
|
+
"deleteColumn",
|
|
24
|
+
"evaluateQuery",
|
|
25
|
+
"buildQuery",
|
|
26
|
+
"expandAxes",
|
|
27
|
+
"collapseAxes",
|
|
28
|
+
"findAxis",
|
|
29
|
+
"findTableColumn"
|
|
30
|
+
]
|
|
7
31
|
}),
|
|
8
32
|
PFrame: service()({
|
|
9
33
|
type: "node",
|
|
10
|
-
name: "pframe"
|
|
34
|
+
name: "pframe",
|
|
35
|
+
modelMethods: [
|
|
36
|
+
"createPFrame",
|
|
37
|
+
"createPTable",
|
|
38
|
+
"createPTableV2"
|
|
39
|
+
],
|
|
40
|
+
uiMethods: [
|
|
41
|
+
"findColumns",
|
|
42
|
+
"getColumnSpec",
|
|
43
|
+
"listColumns",
|
|
44
|
+
"calculateTableData",
|
|
45
|
+
"getUniqueValues",
|
|
46
|
+
"getShape",
|
|
47
|
+
"getSpec",
|
|
48
|
+
"getData",
|
|
49
|
+
"writePTableToFs"
|
|
50
|
+
]
|
|
51
|
+
}),
|
|
52
|
+
Dialog: service()({
|
|
53
|
+
type: "main",
|
|
54
|
+
name: "dialog",
|
|
55
|
+
modelMethods: [],
|
|
56
|
+
uiMethods: ["showSaveDialog"]
|
|
11
57
|
})
|
|
12
58
|
};
|
|
13
59
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service_declarations.js","names":[],"sources":["../../src/services/service_declarations.ts"],"sourcesContent":["/**\n * Service declarations — add new services here.\n *\n * After adding a service, fix type errors in these files:\n *\n * Model side:\n * - lib/node/pl-middle-layer/src/js_render/service_injectors.ts — VM bridge for workflow scripts\n * - lib/node/pl-middle-layer/src/middle_layer/middle_layer.ts — ModelServiceRegistry factory\n *\n * UI side:\n * - lib/model/common/src/services/
|
|
1
|
+
{"version":3,"file":"service_declarations.js","names":[],"sources":["../../src/services/service_declarations.ts"],"sourcesContent":["/**\n * Service declarations — add new services here.\n *\n * `modelMethods` / `uiMethods` lists are the single source of truth for\n * method names exposed on each side. They drive SERVICE_METHOD_MAP (UI\n * ServiceProxy forwarders) and MODEL_SERVICE_METHOD_MAP (workflow VM\n * bridge), so node/main/wasm split no longer needs introspection stubs.\n *\n * After adding a service, fix type errors in these files:\n *\n * Model side:\n * - lib/node/pl-middle-layer/src/js_render/service_injectors.ts — VM bridge for workflow scripts\n * - lib/node/pl-middle-layer/src/middle_layer/middle_layer.ts — ModelServiceRegistry factory\n *\n * UI side:\n * - lib/model/common/src/services/node_service_handlers.ts — driver method wrappers (node services only)\n * - sdk/ui-vue/src/internal/createAppV3.ts — UiServiceRegistry factory\n *\n * Electron main side (only for `main` services):\n * - platforma-desktop-app/packages/main/src/services/mainServices.ts — main-process dispatcher\n *\n * Optional:\n * - sdk/model/src/services/block_service_flags.ts — only if default-required by all blocks\n */\n\nimport type { DialogService } from \"../dialog\";\nimport type { PFrameDriver, PFrameModelDriver } from \"../drivers/pframe/driver\";\nimport type { PFrameSpecDriver } from \"../drivers/pframe/spec_driver\";\nimport { service } from \"./service_types\";\n\nexport const Services = {\n PFrameSpec: service<PFrameSpecDriver, PFrameSpecDriver>()({\n type: \"wasm\",\n name: \"pframeSpec\",\n modelMethods: [\n \"createSpecFrame\",\n \"listColumns\",\n \"discoverColumns\",\n \"deleteColumn\",\n \"evaluateQuery\",\n \"buildQuery\",\n \"expandAxes\",\n \"collapseAxes\",\n \"findAxis\",\n \"findTableColumn\",\n ] as const,\n uiMethods: [\n \"createSpecFrame\",\n \"listColumns\",\n \"discoverColumns\",\n \"deleteColumn\",\n \"evaluateQuery\",\n \"buildQuery\",\n \"expandAxes\",\n \"collapseAxes\",\n \"findAxis\",\n \"findTableColumn\",\n ] as const,\n }),\n PFrame: service<PFrameModelDriver, PFrameDriver>()({\n type: \"node\",\n name: \"pframe\",\n modelMethods: [\"createPFrame\", \"createPTable\", \"createPTableV2\"] as const,\n uiMethods: [\n \"findColumns\",\n \"getColumnSpec\",\n \"listColumns\",\n \"calculateTableData\",\n \"getUniqueValues\",\n \"getShape\",\n \"getSpec\",\n \"getData\",\n \"writePTableToFs\",\n ] as const,\n }),\n Dialog: service<Record<string, never>, DialogService>()({\n type: \"main\",\n name: \"dialog\",\n modelMethods: [] as const,\n uiMethods: [\"showSaveDialog\"] as const,\n }),\n};\n"],"mappings":";;AA8BA,MAAa,WAAW;CACtB,YAAY,SAA6C,CAAC;EACxD,MAAM;EACN,MAAM;EACN,cAAc;GACZ;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;EACD,WAAW;GACT;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;EACF,CAAC;CACF,QAAQ,SAA0C,CAAC;EACjD,MAAM;EACN,MAAM;EACN,cAAc;GAAC;GAAgB;GAAgB;GAAiB;EAChE,WAAW;GACT;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;EACF,CAAC;CACF,QAAQ,SAA+C,CAAC;EACtD,MAAM;EACN,MAAM;EACN,cAAc,EAAE;EAChB,WAAW,CAAC,iBAAiB;EAC9B,CAAC;CACH"}
|
|
@@ -1,47 +1,51 @@
|
|
|
1
|
+
const require_service_types = require("./service_types.cjs");
|
|
1
2
|
const require_service_declarations = require("./service_declarations.cjs");
|
|
2
3
|
const require_service_capabilities = require("./service_capabilities.cjs");
|
|
3
|
-
const
|
|
4
|
+
const require_node_service_handlers = require("./node_service_handlers.cjs");
|
|
4
5
|
//#region src/services/service_injectors.ts
|
|
5
6
|
let cachedKit;
|
|
6
|
-
let
|
|
7
|
-
function
|
|
8
|
-
if (!
|
|
7
|
+
let cachedHandlers;
|
|
8
|
+
function getOrCreateHandlers(driverKit) {
|
|
9
|
+
if (!cachedHandlers || cachedKit !== driverKit) {
|
|
9
10
|
cachedKit = driverKit;
|
|
10
|
-
|
|
11
|
+
cachedHandlers = require_node_service_handlers.createNodeServiceHandlers(driverKit);
|
|
11
12
|
}
|
|
12
|
-
return
|
|
13
|
+
return cachedHandlers;
|
|
13
14
|
}
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the worker-side handler object for a given service ID. Caches
|
|
17
|
+
* per DriverKit reference. Called from the worker's IPC dispatch path.
|
|
18
|
+
*/
|
|
19
|
+
function resolveNodeServiceHandler(driverKit, serviceId) {
|
|
20
|
+
const handlers = getOrCreateHandlers(driverKit);
|
|
17
21
|
const key = Object.keys(require_service_declarations.Services).find((k) => require_service_declarations.Services[k] === serviceId);
|
|
18
22
|
if (!key) return null;
|
|
19
|
-
return
|
|
23
|
+
return handlers[key];
|
|
20
24
|
}
|
|
21
|
-
|
|
22
|
-
* Static map of ServiceName → method names, auto-derived from the injector shape.
|
|
23
|
-
* Computed once at module load. The stub DriverKit is never called — it only
|
|
24
|
-
* provides a target so the closures in createUiServiceInjectors have own-property
|
|
25
|
-
* keys that getMethodNames can introspect.
|
|
26
|
-
*/
|
|
27
|
-
const SERVICE_METHOD_MAP = (() => {
|
|
28
|
-
const injectors = require_service_injector_factory.createUiServiceInjectors(new Proxy({}, { get: () => new Proxy({}, { get: () => () => {} }) }));
|
|
25
|
+
function buildMethodMap(pick) {
|
|
29
26
|
const result = {};
|
|
30
|
-
for (const
|
|
31
|
-
const serviceId = require_service_declarations.Services[key];
|
|
32
|
-
const injector = injectors[key];
|
|
33
|
-
result[serviceId] = injector ? require_service_capabilities.getMethodNames(injector) : [];
|
|
34
|
-
}
|
|
27
|
+
for (const id of Object.values(require_service_declarations.Services)) result[id] = [...pick(id)];
|
|
35
28
|
return result;
|
|
36
|
-
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* UI-side method names per service. Drives ServiceProxy forwarder
|
|
32
|
+
* construction in the renderer.
|
|
33
|
+
*/
|
|
34
|
+
const SERVICE_METHOD_MAP = buildMethodMap(require_service_types.getServiceUiMethods);
|
|
35
|
+
/**
|
|
36
|
+
* Model-side method names per service. Drives the workflow VM bridge
|
|
37
|
+
* (see pl-middle-layer js_render).
|
|
38
|
+
*/
|
|
39
|
+
const MODEL_SERVICE_METHOD_MAP = buildMethodMap(require_service_types.getServiceModelMethods);
|
|
37
40
|
/** Build service info for a block from its feature flags. */
|
|
38
41
|
function buildServiceInfo(featureFlags) {
|
|
39
42
|
const serviceIds = require_service_capabilities.resolveRequiredServices(featureFlags);
|
|
40
43
|
return Object.fromEntries(serviceIds.map((id) => [id, SERVICE_METHOD_MAP[id] ?? []]));
|
|
41
44
|
}
|
|
42
45
|
//#endregion
|
|
46
|
+
exports.MODEL_SERVICE_METHOD_MAP = MODEL_SERVICE_METHOD_MAP;
|
|
43
47
|
exports.SERVICE_METHOD_MAP = SERVICE_METHOD_MAP;
|
|
44
48
|
exports.buildServiceInfo = buildServiceInfo;
|
|
45
|
-
exports.
|
|
49
|
+
exports.resolveNodeServiceHandler = resolveNodeServiceHandler;
|
|
46
50
|
|
|
47
51
|
//# sourceMappingURL=service_injectors.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service_injectors.cjs","names":["
|
|
1
|
+
{"version":3,"file":"service_injectors.cjs","names":["createNodeServiceHandlers","Services","getServiceUiMethods","getServiceModelMethods","resolveRequiredServices"],"sources":["../../src/services/service_injectors.ts"],"sourcesContent":["/**\n * Service dispatch glue — auto-derived types, method maps, and service info builder.\n *\n * The worker-side handler factory (createNodeServiceHandlers) lives in\n * node_service_handlers.ts — that's the only file to edit when adding a\n * new node service. Method-name registries for UI and model sides are\n * derived directly from the `uiMethods` / `modelMethods` declarations in\n * service_declarations.ts — no factory introspection, no stubs.\n */\n\nimport type { InferServiceKind, InferServiceUi, ServiceBrand, ServiceName } from \"./service_types\";\nimport type { DriverKit } from \"../driver_kit\";\nimport { Services } from \"./service_declarations\";\nimport { getServiceModelMethods, getServiceUiMethods } from \"./service_types\";\nimport { resolveRequiredServices } from \"./service_capabilities\";\nimport { createNodeServiceHandlers } from \"./node_service_handlers\";\n\nexport { createNodeServiceHandlers } from \"./node_service_handlers\";\n\ntype NodeServiceKeys = {\n [K in keyof typeof Services]: InferServiceKind<ServiceBrand<(typeof Services)[K]>> extends \"node\"\n ? K\n : never;\n}[keyof typeof Services];\n\n/**\n * Auto-derived map of node service keys to their UI-facing interfaces.\n * Fulfilled by real driver wrappers in the worker. Main services are\n * dispatched by the Electron main-process router and never reach this\n * map; wasm services are instantiated locally on each consumer.\n */\nexport type NodeServiceHandlerMap = {\n [K in NodeServiceKeys]: InferServiceUi<ServiceBrand<(typeof Services)[K]>>;\n};\n\nlet cachedKit: DriverKit | undefined;\nlet cachedHandlers: NodeServiceHandlerMap | undefined;\n\nfunction getOrCreateHandlers(driverKit: DriverKit): NodeServiceHandlerMap {\n if (!cachedHandlers || cachedKit !== driverKit) {\n cachedKit = driverKit;\n cachedHandlers = createNodeServiceHandlers(driverKit);\n }\n return cachedHandlers;\n}\n\n/**\n * Resolve the worker-side handler object for a given service ID. Caches\n * per DriverKit reference. Called from the worker's IPC dispatch path.\n */\nexport function resolveNodeServiceHandler(\n driverKit: DriverKit,\n serviceId: ServiceName,\n): NodeServiceHandlerMap[keyof NodeServiceHandlerMap] | null {\n const handlers = getOrCreateHandlers(driverKit);\n const key = Object.keys(Services).find(\n (k) => Services[k as keyof typeof Services] === serviceId,\n ) as NodeServiceKeys | undefined;\n if (!key) return null;\n return handlers[key];\n}\n\nfunction buildMethodMap(\n pick: (id: ServiceName) => readonly string[],\n): Readonly<Record<string, string[]>> {\n const result: Record<string, string[]> = {};\n for (const id of Object.values(Services)) {\n result[id as string] = [...pick(id)];\n }\n return result;\n}\n\n/**\n * UI-side method names per service. Drives ServiceProxy forwarder\n * construction in the renderer.\n */\nexport const SERVICE_METHOD_MAP: Readonly<Record<string, string[]>> =\n buildMethodMap(getServiceUiMethods);\n\n/**\n * Model-side method names per service. Drives the workflow VM bridge\n * (see pl-middle-layer js_render).\n */\nexport const MODEL_SERVICE_METHOD_MAP: Readonly<Record<string, string[]>> =\n buildMethodMap(getServiceModelMethods);\n\n/** Build service info for a block from its feature flags. */\nexport function buildServiceInfo(\n featureFlags: Record<string, unknown>,\n): Record<ServiceName, string[]> {\n const serviceIds = resolveRequiredServices(featureFlags);\n return Object.fromEntries(\n serviceIds.map((id) => [id, SERVICE_METHOD_MAP[id as string] ?? []]),\n ) as Record<ServiceName, string[]>;\n}\n"],"mappings":";;;;;AAmCA,IAAI;AACJ,IAAI;AAEJ,SAAS,oBAAoB,WAA6C;AACxE,KAAI,CAAC,kBAAkB,cAAc,WAAW;AAC9C,cAAY;AACZ,mBAAiBA,8BAAAA,0BAA0B,UAAU;;AAEvD,QAAO;;;;;;AAOT,SAAgB,0BACd,WACA,WAC2D;CAC3D,MAAM,WAAW,oBAAoB,UAAU;CAC/C,MAAM,MAAM,OAAO,KAAKC,6BAAAA,SAAS,CAAC,MAC/B,MAAMA,6BAAAA,SAAS,OAAgC,UACjD;AACD,KAAI,CAAC,IAAK,QAAO;AACjB,QAAO,SAAS;;AAGlB,SAAS,eACP,MACoC;CACpC,MAAM,SAAmC,EAAE;AAC3C,MAAK,MAAM,MAAM,OAAO,OAAOA,6BAAAA,SAAS,CACtC,QAAO,MAAgB,CAAC,GAAG,KAAK,GAAG,CAAC;AAEtC,QAAO;;;;;;AAOT,MAAa,qBACX,eAAeC,sBAAAA,oBAAoB;;;;;AAMrC,MAAa,2BACX,eAAeC,sBAAAA,uBAAuB;;AAGxC,SAAgB,iBACd,cAC+B;CAC/B,MAAM,aAAaC,6BAAAA,wBAAwB,aAAa;AACxD,QAAO,OAAO,YACZ,WAAW,KAAK,OAAO,CAAC,IAAI,mBAAmB,OAAiB,EAAE,CAAC,CAAC,CACrE"}
|
|
@@ -1,23 +1,34 @@
|
|
|
1
1
|
import { Services } from "./service_declarations.js";
|
|
2
2
|
import { InferServiceKind, InferServiceUi, ServiceBrand, ServiceName } from "./service_types.js";
|
|
3
3
|
import { DriverKit } from "../driver_kit.js";
|
|
4
|
-
import {
|
|
4
|
+
import { createNodeServiceHandlers } from "./node_service_handlers.js";
|
|
5
5
|
|
|
6
6
|
//#region src/services/service_injectors.d.ts
|
|
7
7
|
type NodeServiceKeys = { [K in keyof typeof Services]: InferServiceKind<ServiceBrand<(typeof Services)[K]>> extends "node" ? K : never }[keyof typeof Services];
|
|
8
|
-
/** Auto-derived map of node service keys to their UI-side driver interfaces. */
|
|
9
|
-
type UiServiceInjectorMap = { [K in NodeServiceKeys]: InferServiceUi<ServiceBrand<(typeof Services)[K]>> };
|
|
10
|
-
/** Resolve the injector for a given service ID. Caches injectors per DriverKit reference. */
|
|
11
|
-
declare function resolveUiInjector(driverKit: DriverKit, serviceId: ServiceName): UiServiceInjectorMap[keyof UiServiceInjectorMap] | null;
|
|
12
8
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
9
|
+
* Auto-derived map of node service keys to their UI-facing interfaces.
|
|
10
|
+
* Fulfilled by real driver wrappers in the worker. Main services are
|
|
11
|
+
* dispatched by the Electron main-process router and never reach this
|
|
12
|
+
* map; wasm services are instantiated locally on each consumer.
|
|
13
|
+
*/
|
|
14
|
+
type NodeServiceHandlerMap = { [K in NodeServiceKeys]: InferServiceUi<ServiceBrand<(typeof Services)[K]>> };
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the worker-side handler object for a given service ID. Caches
|
|
17
|
+
* per DriverKit reference. Called from the worker's IPC dispatch path.
|
|
18
|
+
*/
|
|
19
|
+
declare function resolveNodeServiceHandler(driverKit: DriverKit, serviceId: ServiceName): NodeServiceHandlerMap[keyof NodeServiceHandlerMap] | null;
|
|
20
|
+
/**
|
|
21
|
+
* UI-side method names per service. Drives ServiceProxy forwarder
|
|
22
|
+
* construction in the renderer.
|
|
17
23
|
*/
|
|
18
24
|
declare const SERVICE_METHOD_MAP: Readonly<Record<string, string[]>>;
|
|
25
|
+
/**
|
|
26
|
+
* Model-side method names per service. Drives the workflow VM bridge
|
|
27
|
+
* (see pl-middle-layer js_render).
|
|
28
|
+
*/
|
|
29
|
+
declare const MODEL_SERVICE_METHOD_MAP: Readonly<Record<string, string[]>>;
|
|
19
30
|
/** Build service info for a block from its feature flags. */
|
|
20
31
|
declare function buildServiceInfo(featureFlags: Record<string, unknown>): Record<ServiceName, string[]>;
|
|
21
32
|
//#endregion
|
|
22
|
-
export {
|
|
33
|
+
export { MODEL_SERVICE_METHOD_MAP, NodeServiceHandlerMap, SERVICE_METHOD_MAP, buildServiceInfo, resolveNodeServiceHandler };
|
|
23
34
|
//# sourceMappingURL=service_injectors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service_injectors.d.ts","names":[],"sources":["../../src/services/service_injectors.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"service_injectors.d.ts","names":[],"sources":["../../src/services/service_injectors.ts"],"mappings":";;;;;;KAmBK,eAAA,wBACgB,QAAA,GAAW,gBAAA,CAAiB,YAAA,SAAqB,QAAA,EAAU,CAAA,qBAC1E,CAAA,wBAES,QAAA;;;;;;;KAQH,qBAAA,WACJ,eAAA,GAAkB,cAAA,CAAe,YAAA,SAAqB,QAAA,EAAU,CAAA;;;;AADxE;iBAmBgB,yBAAA,CACd,SAAA,EAAW,SAAA,EACX,SAAA,EAAW,WAAA,GACV,qBAAA,OAA4B,qBAAA;;;;;cAuBlB,kBAAA,EAAoB,QAAA,CAAS,MAAA;;;;;cAO7B,wBAAA,EAA0B,QAAA,CAAS,MAAA;;iBAIhC,gBAAA,CACd,YAAA,EAAc,MAAA,oBACb,MAAA,CAAO,WAAA"}
|
|
@@ -1,45 +1,48 @@
|
|
|
1
|
+
import { getServiceModelMethods, getServiceUiMethods } from "./service_types.js";
|
|
1
2
|
import { Services } from "./service_declarations.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
3
|
+
import { resolveRequiredServices } from "./service_capabilities.js";
|
|
4
|
+
import { createNodeServiceHandlers } from "./node_service_handlers.js";
|
|
4
5
|
//#region src/services/service_injectors.ts
|
|
5
6
|
let cachedKit;
|
|
6
|
-
let
|
|
7
|
-
function
|
|
8
|
-
if (!
|
|
7
|
+
let cachedHandlers;
|
|
8
|
+
function getOrCreateHandlers(driverKit) {
|
|
9
|
+
if (!cachedHandlers || cachedKit !== driverKit) {
|
|
9
10
|
cachedKit = driverKit;
|
|
10
|
-
|
|
11
|
+
cachedHandlers = createNodeServiceHandlers(driverKit);
|
|
11
12
|
}
|
|
12
|
-
return
|
|
13
|
+
return cachedHandlers;
|
|
13
14
|
}
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the worker-side handler object for a given service ID. Caches
|
|
17
|
+
* per DriverKit reference. Called from the worker's IPC dispatch path.
|
|
18
|
+
*/
|
|
19
|
+
function resolveNodeServiceHandler(driverKit, serviceId) {
|
|
20
|
+
const handlers = getOrCreateHandlers(driverKit);
|
|
17
21
|
const key = Object.keys(Services).find((k) => Services[k] === serviceId);
|
|
18
22
|
if (!key) return null;
|
|
19
|
-
return
|
|
23
|
+
return handlers[key];
|
|
20
24
|
}
|
|
21
|
-
|
|
22
|
-
* Static map of ServiceName → method names, auto-derived from the injector shape.
|
|
23
|
-
* Computed once at module load. The stub DriverKit is never called — it only
|
|
24
|
-
* provides a target so the closures in createUiServiceInjectors have own-property
|
|
25
|
-
* keys that getMethodNames can introspect.
|
|
26
|
-
*/
|
|
27
|
-
const SERVICE_METHOD_MAP = (() => {
|
|
28
|
-
const injectors = createUiServiceInjectors(new Proxy({}, { get: () => new Proxy({}, { get: () => () => {} }) }));
|
|
25
|
+
function buildMethodMap(pick) {
|
|
29
26
|
const result = {};
|
|
30
|
-
for (const
|
|
31
|
-
const serviceId = Services[key];
|
|
32
|
-
const injector = injectors[key];
|
|
33
|
-
result[serviceId] = injector ? getMethodNames(injector) : [];
|
|
34
|
-
}
|
|
27
|
+
for (const id of Object.values(Services)) result[id] = [...pick(id)];
|
|
35
28
|
return result;
|
|
36
|
-
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* UI-side method names per service. Drives ServiceProxy forwarder
|
|
32
|
+
* construction in the renderer.
|
|
33
|
+
*/
|
|
34
|
+
const SERVICE_METHOD_MAP = buildMethodMap(getServiceUiMethods);
|
|
35
|
+
/**
|
|
36
|
+
* Model-side method names per service. Drives the workflow VM bridge
|
|
37
|
+
* (see pl-middle-layer js_render).
|
|
38
|
+
*/
|
|
39
|
+
const MODEL_SERVICE_METHOD_MAP = buildMethodMap(getServiceModelMethods);
|
|
37
40
|
/** Build service info for a block from its feature flags. */
|
|
38
41
|
function buildServiceInfo(featureFlags) {
|
|
39
42
|
const serviceIds = resolveRequiredServices(featureFlags);
|
|
40
43
|
return Object.fromEntries(serviceIds.map((id) => [id, SERVICE_METHOD_MAP[id] ?? []]));
|
|
41
44
|
}
|
|
42
45
|
//#endregion
|
|
43
|
-
export { SERVICE_METHOD_MAP, buildServiceInfo,
|
|
46
|
+
export { MODEL_SERVICE_METHOD_MAP, SERVICE_METHOD_MAP, buildServiceInfo, resolveNodeServiceHandler };
|
|
44
47
|
|
|
45
48
|
//# sourceMappingURL=service_injectors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service_injectors.js","names":[],"sources":["../../src/services/service_injectors.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"file":"service_injectors.js","names":[],"sources":["../../src/services/service_injectors.ts"],"sourcesContent":["/**\n * Service dispatch glue — auto-derived types, method maps, and service info builder.\n *\n * The worker-side handler factory (createNodeServiceHandlers) lives in\n * node_service_handlers.ts — that's the only file to edit when adding a\n * new node service. Method-name registries for UI and model sides are\n * derived directly from the `uiMethods` / `modelMethods` declarations in\n * service_declarations.ts — no factory introspection, no stubs.\n */\n\nimport type { InferServiceKind, InferServiceUi, ServiceBrand, ServiceName } from \"./service_types\";\nimport type { DriverKit } from \"../driver_kit\";\nimport { Services } from \"./service_declarations\";\nimport { getServiceModelMethods, getServiceUiMethods } from \"./service_types\";\nimport { resolveRequiredServices } from \"./service_capabilities\";\nimport { createNodeServiceHandlers } from \"./node_service_handlers\";\n\nexport { createNodeServiceHandlers } from \"./node_service_handlers\";\n\ntype NodeServiceKeys = {\n [K in keyof typeof Services]: InferServiceKind<ServiceBrand<(typeof Services)[K]>> extends \"node\"\n ? K\n : never;\n}[keyof typeof Services];\n\n/**\n * Auto-derived map of node service keys to their UI-facing interfaces.\n * Fulfilled by real driver wrappers in the worker. Main services are\n * dispatched by the Electron main-process router and never reach this\n * map; wasm services are instantiated locally on each consumer.\n */\nexport type NodeServiceHandlerMap = {\n [K in NodeServiceKeys]: InferServiceUi<ServiceBrand<(typeof Services)[K]>>;\n};\n\nlet cachedKit: DriverKit | undefined;\nlet cachedHandlers: NodeServiceHandlerMap | undefined;\n\nfunction getOrCreateHandlers(driverKit: DriverKit): NodeServiceHandlerMap {\n if (!cachedHandlers || cachedKit !== driverKit) {\n cachedKit = driverKit;\n cachedHandlers = createNodeServiceHandlers(driverKit);\n }\n return cachedHandlers;\n}\n\n/**\n * Resolve the worker-side handler object for a given service ID. Caches\n * per DriverKit reference. Called from the worker's IPC dispatch path.\n */\nexport function resolveNodeServiceHandler(\n driverKit: DriverKit,\n serviceId: ServiceName,\n): NodeServiceHandlerMap[keyof NodeServiceHandlerMap] | null {\n const handlers = getOrCreateHandlers(driverKit);\n const key = Object.keys(Services).find(\n (k) => Services[k as keyof typeof Services] === serviceId,\n ) as NodeServiceKeys | undefined;\n if (!key) return null;\n return handlers[key];\n}\n\nfunction buildMethodMap(\n pick: (id: ServiceName) => readonly string[],\n): Readonly<Record<string, string[]>> {\n const result: Record<string, string[]> = {};\n for (const id of Object.values(Services)) {\n result[id as string] = [...pick(id)];\n }\n return result;\n}\n\n/**\n * UI-side method names per service. Drives ServiceProxy forwarder\n * construction in the renderer.\n */\nexport const SERVICE_METHOD_MAP: Readonly<Record<string, string[]>> =\n buildMethodMap(getServiceUiMethods);\n\n/**\n * Model-side method names per service. Drives the workflow VM bridge\n * (see pl-middle-layer js_render).\n */\nexport const MODEL_SERVICE_METHOD_MAP: Readonly<Record<string, string[]>> =\n buildMethodMap(getServiceModelMethods);\n\n/** Build service info for a block from its feature flags. */\nexport function buildServiceInfo(\n featureFlags: Record<string, unknown>,\n): Record<ServiceName, string[]> {\n const serviceIds = resolveRequiredServices(featureFlags);\n return Object.fromEntries(\n serviceIds.map((id) => [id, SERVICE_METHOD_MAP[id as string] ?? []]),\n ) as Record<ServiceName, string[]>;\n}\n"],"mappings":";;;;;AAmCA,IAAI;AACJ,IAAI;AAEJ,SAAS,oBAAoB,WAA6C;AACxE,KAAI,CAAC,kBAAkB,cAAc,WAAW;AAC9C,cAAY;AACZ,mBAAiB,0BAA0B,UAAU;;AAEvD,QAAO;;;;;;AAOT,SAAgB,0BACd,WACA,WAC2D;CAC3D,MAAM,WAAW,oBAAoB,UAAU;CAC/C,MAAM,MAAM,OAAO,KAAK,SAAS,CAAC,MAC/B,MAAM,SAAS,OAAgC,UACjD;AACD,KAAI,CAAC,IAAK,QAAO;AACjB,QAAO,SAAS;;AAGlB,SAAS,eACP,MACoC;CACpC,MAAM,SAAmC,EAAE;AAC3C,MAAK,MAAM,MAAM,OAAO,OAAO,SAAS,CACtC,QAAO,MAAgB,CAAC,GAAG,KAAK,GAAG,CAAC;AAEtC,QAAO;;;;;;AAOT,MAAa,qBACX,eAAe,oBAAoB;;;;;AAMrC,MAAa,2BACX,eAAe,uBAAuB;;AAGxC,SAAgB,iBACd,cAC+B;CAC/B,MAAM,aAAa,wBAAwB,aAAa;AACxD,QAAO,OAAO,YACZ,WAAW,KAAK,OAAO,CAAC,IAAI,mBAAmB,OAAiB,EAAE,CAAC,CAAC,CACrE"}
|
|
@@ -1,20 +1,39 @@
|
|
|
1
1
|
const require_errors = require("../errors.cjs");
|
|
2
2
|
//#region src/services/service_types.ts
|
|
3
3
|
const SERVICE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;
|
|
4
|
-
const { service, isNodeService } = (() => {
|
|
4
|
+
const { service, isNodeService, isWasmService, isMainService, getServiceKind, getServiceModelMethods, getServiceUiMethods } = (() => {
|
|
5
5
|
const typeMap = /* @__PURE__ */ new Map();
|
|
6
|
+
const modelMethodsMap = /* @__PURE__ */ new Map();
|
|
7
|
+
const uiMethodsMap = /* @__PURE__ */ new Map();
|
|
6
8
|
return {
|
|
7
9
|
service() {
|
|
8
10
|
return (options) => {
|
|
9
|
-
const { name, type } = options;
|
|
11
|
+
const { name, type, modelMethods, uiMethods } = options;
|
|
10
12
|
if (!SERVICE_ID_PATTERN.test(name)) throw new require_errors.ServiceInvalidIdError(`Invalid service ID "${name}": must match ${SERVICE_ID_PATTERN}`);
|
|
11
13
|
if (typeMap.has(name)) throw new require_errors.ServiceAlreadyRegisteredError(`Service "${name}" already registered`);
|
|
12
14
|
typeMap.set(name, type);
|
|
15
|
+
modelMethodsMap.set(name, modelMethods);
|
|
16
|
+
uiMethodsMap.set(name, uiMethods);
|
|
13
17
|
return name;
|
|
14
18
|
};
|
|
15
19
|
},
|
|
16
20
|
isNodeService(id) {
|
|
17
21
|
return typeMap.get(id) === "node";
|
|
22
|
+
},
|
|
23
|
+
isWasmService(id) {
|
|
24
|
+
return typeMap.get(id) === "wasm";
|
|
25
|
+
},
|
|
26
|
+
isMainService(id) {
|
|
27
|
+
return typeMap.get(id) === "main";
|
|
28
|
+
},
|
|
29
|
+
getServiceKind(id) {
|
|
30
|
+
return typeMap.get(id);
|
|
31
|
+
},
|
|
32
|
+
getServiceModelMethods(id) {
|
|
33
|
+
return modelMethodsMap.get(id) ?? [];
|
|
34
|
+
},
|
|
35
|
+
getServiceUiMethods(id) {
|
|
36
|
+
return uiMethodsMap.get(id) ?? [];
|
|
18
37
|
}
|
|
19
38
|
};
|
|
20
39
|
})();
|
|
@@ -22,7 +41,12 @@ function serviceFnKey(serviceId, method = "") {
|
|
|
22
41
|
return `service:${serviceId}:${method}`;
|
|
23
42
|
}
|
|
24
43
|
//#endregion
|
|
44
|
+
exports.getServiceKind = getServiceKind;
|
|
45
|
+
exports.getServiceModelMethods = getServiceModelMethods;
|
|
46
|
+
exports.getServiceUiMethods = getServiceUiMethods;
|
|
47
|
+
exports.isMainService = isMainService;
|
|
25
48
|
exports.isNodeService = isNodeService;
|
|
49
|
+
exports.isWasmService = isWasmService;
|
|
26
50
|
exports.service = service;
|
|
27
51
|
exports.serviceFnKey = serviceFnKey;
|
|
28
52
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service_types.cjs","names":["ServiceInvalidIdError","ServiceAlreadyRegisteredError"],"sources":["../../src/services/service_types.ts"],"sourcesContent":["import { UnionToIntersection } from \"@milaboratories/helpers\";\nimport type { Branded } from \"../branding\";\nimport { ServiceAlreadyRegisteredError, ServiceInvalidIdError } from \"../errors\";\nimport type { Services } from \"./service_declarations\";\n\nexport type ServiceTypesLike<\n Model = unknown,\n Ui = unknown,\n Kind extends ServiceType = ServiceType,\n> = {\n readonly __types?: { model: Model; ui: Ui; kind: Kind };\n};\n\nexport type InferServiceModel<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<infer M, unknown, ServiceType> ? M : unknown;\n\nexport type InferServiceUi<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, infer U, ServiceType> ? U : unknown;\n\nexport type InferServiceKind<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, unknown, infer K> ? K : ServiceType;\n\nexport type ServiceName<S extends ServiceTypesLike = ServiceTypesLike> = Branded<string, S>;\n\nexport type ServiceType = \"node\" | \"wasm\";\n\nconst SERVICE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;\n\nexport const {
|
|
1
|
+
{"version":3,"file":"service_types.cjs","names":["ServiceInvalidIdError","ServiceAlreadyRegisteredError"],"sources":["../../src/services/service_types.ts"],"sourcesContent":["import { UnionToIntersection } from \"@milaboratories/helpers\";\nimport type { Branded } from \"../branding\";\nimport { ServiceAlreadyRegisteredError, ServiceInvalidIdError } from \"../errors\";\nimport type { Services } from \"./service_declarations\";\n\nexport type ServiceTypesLike<\n Model = unknown,\n Ui = unknown,\n Kind extends ServiceType = ServiceType,\n> = {\n readonly __types?: { model: Model; ui: Ui; kind: Kind };\n};\n\nexport type InferServiceModel<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<infer M, unknown, ServiceType> ? M : unknown;\n\nexport type InferServiceUi<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, infer U, ServiceType> ? U : unknown;\n\nexport type InferServiceKind<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, unknown, infer K> ? K : ServiceType;\n\nexport type ServiceName<S extends ServiceTypesLike = ServiceTypesLike> = Branded<string, S>;\n\nexport type ServiceType = \"node\" | \"wasm\" | \"main\";\n\nconst SERVICE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;\n\nexport const {\n service,\n isNodeService,\n isWasmService,\n isMainService,\n getServiceKind,\n getServiceModelMethods,\n getServiceUiMethods,\n} = (() => {\n const typeMap = new Map<string, ServiceType>();\n const modelMethodsMap = new Map<string, readonly string[]>();\n const uiMethodsMap = new Map<string, readonly string[]>();\n return {\n service<Model, Ui>() {\n return <\n K extends ServiceType,\n N extends string,\n MM extends readonly (keyof Model & string)[],\n UM extends readonly (keyof Ui & string)[],\n >(options: {\n readonly type: K;\n readonly name: N;\n readonly modelMethods: MM;\n readonly uiMethods: UM;\n }): Branded<N, ServiceTypesLike<Model, Ui, K>> => {\n const { name, type, modelMethods, uiMethods } = options;\n if (!SERVICE_ID_PATTERN.test(name)) {\n throw new ServiceInvalidIdError(\n `Invalid service ID \"${name}\": must match ${SERVICE_ID_PATTERN}`,\n );\n }\n if (typeMap.has(name)) {\n throw new ServiceAlreadyRegisteredError(`Service \"${name}\" already registered`);\n }\n typeMap.set(name, type);\n modelMethodsMap.set(name, modelMethods);\n uiMethodsMap.set(name, uiMethods);\n return name as Branded<N, ServiceTypesLike<Model, Ui, K>>;\n };\n },\n isNodeService(id: ServiceName): boolean {\n return typeMap.get(id) === \"node\";\n },\n isWasmService(id: ServiceName): boolean {\n return typeMap.get(id) === \"wasm\";\n },\n isMainService(id: ServiceName): boolean {\n return typeMap.get(id) === \"main\";\n },\n getServiceKind(id: ServiceName): ServiceType | undefined {\n return typeMap.get(id);\n },\n getServiceModelMethods(id: ServiceName): readonly string[] {\n return modelMethodsMap.get(id) ?? [];\n },\n getServiceUiMethods(id: ServiceName): readonly string[] {\n return uiMethodsMap.get(id) ?? [];\n },\n };\n})();\n\nexport function serviceFnKey(serviceId: string, method = \"\"): string {\n return `service:${serviceId}:${method}`;\n}\n\nexport type ServiceBrand<T> =\n T extends Branded<string, infer S extends ServiceTypesLike> ? S : never;\n\nexport type ModelServiceFactoryMap<SMap extends Record<string, ServiceName>> = {\n [K in keyof SMap]: (() => InferServiceModel<ServiceBrand<SMap[K]>>) | null;\n};\n\nexport type UiServiceFactoryMap<SMap extends Record<string, ServiceName>> = {\n [K in keyof SMap]: (() => InferServiceUi<ServiceBrand<SMap[K]>>) | null;\n};\n\n/** Contract between any service provider and any service consumer. */\nexport interface ServiceDispatch {\n getServiceNames(): ServiceName[];\n getServiceMethods(serviceId: ServiceName): string[];\n callServiceMethod(serviceId: ServiceName, method: string, ...args: unknown[]): unknown;\n}\n\n// Auto-derived types from the Services const in service_declarations.ts.\n// Adding a service to Services automatically updates all of these.\n\ntype TServices = typeof Services;\n\ntype ExtractServiceName<T> = T extends Branded<infer N extends string, any> ? N : never;\n\n/** Model-side service interfaces keyed by service name literal. */\nexport type ModelServices = {\n [K in keyof TServices as ExtractServiceName<TServices[K]>]: InferServiceModel<\n ServiceBrand<TServices[K]>\n >;\n};\n\n/** UI-side service interfaces keyed by service name literal. */\nexport type UiServices = {\n [K in keyof TServices as ExtractServiceName<TServices[K]>]: InferServiceUi<\n ServiceBrand<TServices[K]>\n >;\n};\n\n/** Map from Services keys to their unbranded string name literals. */\nexport type ServiceNameLiterals = {\n [K in keyof TServices]: ExtractServiceName<TServices[K]>;\n};\n\n/** Auto-derived requires* feature flags from Services keys. */\nexport type ServiceRequireFlags = {\n [K in keyof TServices as `requires${K & string}`]?: boolean;\n};\n\nexport type RequireServices<T extends ServiceName> = UnionToIntersection<\n T extends Branded<infer N extends string, infer S extends ServiceTypesLike>\n ? Record<N, InferServiceModel<S>>\n : never\n>;\n"],"mappings":";;AA0BA,MAAM,qBAAqB;AAE3B,MAAa,EACX,SACA,eACA,eACA,eACA,gBACA,wBACA,+BACS;CACT,MAAM,0BAAU,IAAI,KAA0B;CAC9C,MAAM,kCAAkB,IAAI,KAAgC;CAC5D,MAAM,+BAAe,IAAI,KAAgC;AACzD,QAAO;EACL,UAAqB;AACnB,WAKE,YAKgD;IAChD,MAAM,EAAE,MAAM,MAAM,cAAc,cAAc;AAChD,QAAI,CAAC,mBAAmB,KAAK,KAAK,CAChC,OAAM,IAAIA,eAAAA,sBACR,uBAAuB,KAAK,gBAAgB,qBAC7C;AAEH,QAAI,QAAQ,IAAI,KAAK,CACnB,OAAM,IAAIC,eAAAA,8BAA8B,YAAY,KAAK,sBAAsB;AAEjF,YAAQ,IAAI,MAAM,KAAK;AACvB,oBAAgB,IAAI,MAAM,aAAa;AACvC,iBAAa,IAAI,MAAM,UAAU;AACjC,WAAO;;;EAGX,cAAc,IAA0B;AACtC,UAAO,QAAQ,IAAI,GAAG,KAAK;;EAE7B,cAAc,IAA0B;AACtC,UAAO,QAAQ,IAAI,GAAG,KAAK;;EAE7B,cAAc,IAA0B;AACtC,UAAO,QAAQ,IAAI,GAAG,KAAK;;EAE7B,eAAe,IAA0C;AACvD,UAAO,QAAQ,IAAI,GAAG;;EAExB,uBAAuB,IAAoC;AACzD,UAAO,gBAAgB,IAAI,GAAG,IAAI,EAAE;;EAEtC,oBAAoB,IAAoC;AACtD,UAAO,aAAa,IAAI,GAAG,IAAI,EAAE;;EAEpC;IACC;AAEJ,SAAgB,aAAa,WAAmB,SAAS,IAAY;AACnE,QAAO,WAAW,UAAU,GAAG"}
|
|
@@ -14,11 +14,13 @@ type InferServiceModel<S extends ServiceTypesLike> = S extends ServiceTypesLike<
|
|
|
14
14
|
type InferServiceUi<S extends ServiceTypesLike> = S extends ServiceTypesLike<unknown, infer U, ServiceType> ? U : unknown;
|
|
15
15
|
type InferServiceKind<S extends ServiceTypesLike> = S extends ServiceTypesLike<unknown, unknown, infer K> ? K : ServiceType;
|
|
16
16
|
type ServiceName<S extends ServiceTypesLike = ServiceTypesLike> = Branded$1<string, S>;
|
|
17
|
-
type ServiceType = "node" | "wasm";
|
|
18
|
-
declare const service: <Model, Ui>() => <K extends ServiceType, N extends string>(options: {
|
|
17
|
+
type ServiceType = "node" | "wasm" | "main";
|
|
18
|
+
declare const service: <Model, Ui>() => <K extends ServiceType, N extends string, MM extends readonly (keyof Model & string)[], UM extends readonly (keyof Ui & string)[]>(options: {
|
|
19
19
|
readonly type: K;
|
|
20
20
|
readonly name: N;
|
|
21
|
-
|
|
21
|
+
readonly modelMethods: MM;
|
|
22
|
+
readonly uiMethods: UM;
|
|
23
|
+
}) => Branded$1<N, ServiceTypesLike<Model, Ui, K>>, isNodeService: (id: ServiceName) => boolean, isWasmService: (id: ServiceName) => boolean, isMainService: (id: ServiceName) => boolean, getServiceKind: (id: ServiceName) => ServiceType | undefined, getServiceModelMethods: (id: ServiceName) => readonly string[], getServiceUiMethods: (id: ServiceName) => readonly string[];
|
|
22
24
|
declare function serviceFnKey(serviceId: string, method?: string): string;
|
|
23
25
|
type ServiceBrand<T> = T extends Branded$1<string, infer S extends ServiceTypesLike> ? S : never;
|
|
24
26
|
type ModelServiceFactoryMap<SMap extends Record<string, ServiceName>> = { [K in keyof SMap]: (() => InferServiceModel<ServiceBrand<SMap[K]>>) | null };
|
|
@@ -41,5 +43,5 @@ type ServiceNameLiterals = { [K in keyof TServices]: ExtractServiceName<TService
|
|
|
41
43
|
type ServiceRequireFlags = { [K in keyof TServices as `requires${K & string}`]?: boolean };
|
|
42
44
|
type RequireServices<T extends ServiceName> = UnionToIntersection<T extends Branded$1<infer N extends string, infer S extends ServiceTypesLike> ? Record<N, InferServiceModel<S>> : never>;
|
|
43
45
|
//#endregion
|
|
44
|
-
export { InferServiceKind, InferServiceModel, InferServiceUi, ModelServiceFactoryMap, ModelServices, RequireServices, ServiceBrand, ServiceDispatch, ServiceName, ServiceNameLiterals, ServiceRequireFlags, ServiceType, ServiceTypesLike, UiServiceFactoryMap, UiServices, isNodeService, service, serviceFnKey };
|
|
46
|
+
export { InferServiceKind, InferServiceModel, InferServiceUi, ModelServiceFactoryMap, ModelServices, RequireServices, ServiceBrand, ServiceDispatch, ServiceName, ServiceNameLiterals, ServiceRequireFlags, ServiceType, ServiceTypesLike, UiServiceFactoryMap, UiServices, getServiceKind, getServiceModelMethods, getServiceUiMethods, isMainService, isNodeService, isWasmService, service, serviceFnKey };
|
|
45
47
|
//# sourceMappingURL=service_types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service_types.d.ts","names":[],"sources":["../../src/services/service_types.ts"],"mappings":";;;;;KAKY,gBAAA,6CAGG,WAAA,GAAc,WAAA;EAAA,SAElB,OAAA;IAAY,KAAA,EAAO,KAAA;IAAO,EAAA,EAAI,EAAA;IAAI,IAAA,EAAM,IAAA;EAAA;AAAA;AAAA,KAGvC,iBAAA,WAA4B,gBAAA,IACtC,CAAA,SAAU,gBAAA,mBAAmC,WAAA,IAAe,CAAA;AAAA,KAElD,cAAA,WAAyB,gBAAA,IACnC,CAAA,SAAU,gBAAA,mBAAmC,WAAA,IAAe,CAAA;AAAA,KAElD,gBAAA,WAA2B,gBAAA,IACrC,CAAA,SAAU,gBAAA,8BAA8C,CAAA,GAAI,WAAA;AAAA,KAElD,WAAA,WAAsB,gBAAA,GAAmB,gBAAA,IAAoB,SAAA,SAAgB,CAAA;AAAA,KAE7E,WAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"service_types.d.ts","names":[],"sources":["../../src/services/service_types.ts"],"mappings":";;;;;KAKY,gBAAA,6CAGG,WAAA,GAAc,WAAA;EAAA,SAElB,OAAA;IAAY,KAAA,EAAO,KAAA;IAAO,EAAA,EAAI,EAAA;IAAI,IAAA,EAAM,IAAA;EAAA;AAAA;AAAA,KAGvC,iBAAA,WAA4B,gBAAA,IACtC,CAAA,SAAU,gBAAA,mBAAmC,WAAA,IAAe,CAAA;AAAA,KAElD,cAAA,WAAyB,gBAAA,IACnC,CAAA,SAAU,gBAAA,mBAAmC,WAAA,IAAe,CAAA;AAAA,KAElD,gBAAA,WAA2B,gBAAA,IACrC,CAAA,SAAU,gBAAA,8BAA8C,CAAA,GAAI,WAAA;AAAA,KAElD,WAAA,WAAsB,gBAAA,GAAmB,gBAAA,IAAoB,SAAA,SAAgB,CAAA;AAAA,KAE7E,WAAA;AAAA,cAKV,OAAA,8BAcgB,WAAA,+CAEiB,KAAA,yCACA,EAAA,cAAc,OAAA;IAAA,SAEhC,IAAA,EAAM,CAAA;IAAA,SACN,IAAA,EAAM,CAAA;IAAA,SACN,YAAA,EAAc,EAAA;IAAA,SACd,SAAA,EAAW,EAAA;EAAA,MAClB,SAAA,CAAQ,CAAA,EAAG,gBAAA,CAAiB,KAAA,EAAO,EAAA,EAAI,CAAA,IAAA,aAAA,GAtBlC,EAAA,EAsCO,WAAA,cAAA,aAAA,GArCP,EAAA,EAwCO,WAAA,cAAA,aAAA,GAvCP,EAAA,EA0CO,WAAA,cAAA,cAAA,GAzCN,EAAA,EA4CO,WAAA,KAAc,WAAA,cAAA,sBAAA,GA3Cb,EAAA,EA8CO,WAAA,wBAAA,mBAAA,GA7CV,EAAA,EAgDO,WAAA;AAAA,iBAMZ,YAAA,CAAa,SAAA,UAAmB,MAAA;AAAA,KAIpC,YAAA,MACV,CAAA,SAAU,SAAA,yBAAgC,gBAAA,IAAoB,CAAA;AAAA,KAEpD,sBAAA,cAAoC,MAAA,SAAe,WAAA,mBACjD,IAAA,UAAc,iBAAA,CAAkB,YAAA,CAAa,IAAA,CAAK,CAAA;AAAA,KAGpD,mBAAA,cAAiC,MAAA,SAAe,WAAA,mBAC9C,IAAA,UAAc,cAAA,CAAe,YAAA,CAAa,IAAA,CAAK,CAAA;AAxF7D;AAAA,UA4FiB,eAAA;EACf,eAAA,IAAmB,WAAA;EACnB,iBAAA,CAAkB,SAAA,EAAW,WAAA;EAC7B,iBAAA,CAAkB,SAAA,EAAW,WAAA,EAAa,MAAA,aAAmB,IAAA;AAAA;AAAA,KAM1D,SAAA,UAAmB,QAAA;AAAA,KAEnB,kBAAA,MAAwB,CAAA,SAAU,SAAA,gCAAuC,CAAA;;KAGlE,aAAA,iBACE,SAAA,IAAa,kBAAA,CAAmB,SAAA,CAAU,CAAA,KAAM,iBAAA,CAC1D,YAAA,CAAa,SAAA,CAAU,CAAA;;KAKf,UAAA,iBACE,SAAA,IAAa,kBAAA,CAAmB,SAAA,CAAU,CAAA,KAAM,cAAA,CAC1D,YAAA,CAAa,SAAA,CAAU,CAAA;;KAKf,mBAAA,iBACE,SAAA,GAAY,kBAAA,CAAmB,SAAA,CAAU,CAAA;;KAI3C,mBAAA,iBACE,SAAA,eAAwB,CAAA;AAAA,KAG1B,eAAA,WAA0B,WAAA,IAAe,mBAAA,CACnD,CAAA,SAAU,SAAA,yCAAgD,gBAAA,IACtD,MAAA,CAAO,CAAA,EAAG,iBAAA,CAAkB,CAAA"}
|
|
@@ -1,20 +1,39 @@
|
|
|
1
1
|
import { ServiceAlreadyRegisteredError, ServiceInvalidIdError } from "../errors.js";
|
|
2
2
|
//#region src/services/service_types.ts
|
|
3
3
|
const SERVICE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;
|
|
4
|
-
const { service, isNodeService } = (() => {
|
|
4
|
+
const { service, isNodeService, isWasmService, isMainService, getServiceKind, getServiceModelMethods, getServiceUiMethods } = (() => {
|
|
5
5
|
const typeMap = /* @__PURE__ */ new Map();
|
|
6
|
+
const modelMethodsMap = /* @__PURE__ */ new Map();
|
|
7
|
+
const uiMethodsMap = /* @__PURE__ */ new Map();
|
|
6
8
|
return {
|
|
7
9
|
service() {
|
|
8
10
|
return (options) => {
|
|
9
|
-
const { name, type } = options;
|
|
11
|
+
const { name, type, modelMethods, uiMethods } = options;
|
|
10
12
|
if (!SERVICE_ID_PATTERN.test(name)) throw new ServiceInvalidIdError(`Invalid service ID "${name}": must match ${SERVICE_ID_PATTERN}`);
|
|
11
13
|
if (typeMap.has(name)) throw new ServiceAlreadyRegisteredError(`Service "${name}" already registered`);
|
|
12
14
|
typeMap.set(name, type);
|
|
15
|
+
modelMethodsMap.set(name, modelMethods);
|
|
16
|
+
uiMethodsMap.set(name, uiMethods);
|
|
13
17
|
return name;
|
|
14
18
|
};
|
|
15
19
|
},
|
|
16
20
|
isNodeService(id) {
|
|
17
21
|
return typeMap.get(id) === "node";
|
|
22
|
+
},
|
|
23
|
+
isWasmService(id) {
|
|
24
|
+
return typeMap.get(id) === "wasm";
|
|
25
|
+
},
|
|
26
|
+
isMainService(id) {
|
|
27
|
+
return typeMap.get(id) === "main";
|
|
28
|
+
},
|
|
29
|
+
getServiceKind(id) {
|
|
30
|
+
return typeMap.get(id);
|
|
31
|
+
},
|
|
32
|
+
getServiceModelMethods(id) {
|
|
33
|
+
return modelMethodsMap.get(id) ?? [];
|
|
34
|
+
},
|
|
35
|
+
getServiceUiMethods(id) {
|
|
36
|
+
return uiMethodsMap.get(id) ?? [];
|
|
18
37
|
}
|
|
19
38
|
};
|
|
20
39
|
})();
|
|
@@ -22,6 +41,6 @@ function serviceFnKey(serviceId, method = "") {
|
|
|
22
41
|
return `service:${serviceId}:${method}`;
|
|
23
42
|
}
|
|
24
43
|
//#endregion
|
|
25
|
-
export { isNodeService, service, serviceFnKey };
|
|
44
|
+
export { getServiceKind, getServiceModelMethods, getServiceUiMethods, isMainService, isNodeService, isWasmService, service, serviceFnKey };
|
|
26
45
|
|
|
27
46
|
//# sourceMappingURL=service_types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service_types.js","names":[],"sources":["../../src/services/service_types.ts"],"sourcesContent":["import { UnionToIntersection } from \"@milaboratories/helpers\";\nimport type { Branded } from \"../branding\";\nimport { ServiceAlreadyRegisteredError, ServiceInvalidIdError } from \"../errors\";\nimport type { Services } from \"./service_declarations\";\n\nexport type ServiceTypesLike<\n Model = unknown,\n Ui = unknown,\n Kind extends ServiceType = ServiceType,\n> = {\n readonly __types?: { model: Model; ui: Ui; kind: Kind };\n};\n\nexport type InferServiceModel<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<infer M, unknown, ServiceType> ? M : unknown;\n\nexport type InferServiceUi<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, infer U, ServiceType> ? U : unknown;\n\nexport type InferServiceKind<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, unknown, infer K> ? K : ServiceType;\n\nexport type ServiceName<S extends ServiceTypesLike = ServiceTypesLike> = Branded<string, S>;\n\nexport type ServiceType = \"node\" | \"wasm\";\n\nconst SERVICE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;\n\nexport const {
|
|
1
|
+
{"version":3,"file":"service_types.js","names":[],"sources":["../../src/services/service_types.ts"],"sourcesContent":["import { UnionToIntersection } from \"@milaboratories/helpers\";\nimport type { Branded } from \"../branding\";\nimport { ServiceAlreadyRegisteredError, ServiceInvalidIdError } from \"../errors\";\nimport type { Services } from \"./service_declarations\";\n\nexport type ServiceTypesLike<\n Model = unknown,\n Ui = unknown,\n Kind extends ServiceType = ServiceType,\n> = {\n readonly __types?: { model: Model; ui: Ui; kind: Kind };\n};\n\nexport type InferServiceModel<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<infer M, unknown, ServiceType> ? M : unknown;\n\nexport type InferServiceUi<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, infer U, ServiceType> ? U : unknown;\n\nexport type InferServiceKind<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, unknown, infer K> ? K : ServiceType;\n\nexport type ServiceName<S extends ServiceTypesLike = ServiceTypesLike> = Branded<string, S>;\n\nexport type ServiceType = \"node\" | \"wasm\" | \"main\";\n\nconst SERVICE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;\n\nexport const {\n service,\n isNodeService,\n isWasmService,\n isMainService,\n getServiceKind,\n getServiceModelMethods,\n getServiceUiMethods,\n} = (() => {\n const typeMap = new Map<string, ServiceType>();\n const modelMethodsMap = new Map<string, readonly string[]>();\n const uiMethodsMap = new Map<string, readonly string[]>();\n return {\n service<Model, Ui>() {\n return <\n K extends ServiceType,\n N extends string,\n MM extends readonly (keyof Model & string)[],\n UM extends readonly (keyof Ui & string)[],\n >(options: {\n readonly type: K;\n readonly name: N;\n readonly modelMethods: MM;\n readonly uiMethods: UM;\n }): Branded<N, ServiceTypesLike<Model, Ui, K>> => {\n const { name, type, modelMethods, uiMethods } = options;\n if (!SERVICE_ID_PATTERN.test(name)) {\n throw new ServiceInvalidIdError(\n `Invalid service ID \"${name}\": must match ${SERVICE_ID_PATTERN}`,\n );\n }\n if (typeMap.has(name)) {\n throw new ServiceAlreadyRegisteredError(`Service \"${name}\" already registered`);\n }\n typeMap.set(name, type);\n modelMethodsMap.set(name, modelMethods);\n uiMethodsMap.set(name, uiMethods);\n return name as Branded<N, ServiceTypesLike<Model, Ui, K>>;\n };\n },\n isNodeService(id: ServiceName): boolean {\n return typeMap.get(id) === \"node\";\n },\n isWasmService(id: ServiceName): boolean {\n return typeMap.get(id) === \"wasm\";\n },\n isMainService(id: ServiceName): boolean {\n return typeMap.get(id) === \"main\";\n },\n getServiceKind(id: ServiceName): ServiceType | undefined {\n return typeMap.get(id);\n },\n getServiceModelMethods(id: ServiceName): readonly string[] {\n return modelMethodsMap.get(id) ?? [];\n },\n getServiceUiMethods(id: ServiceName): readonly string[] {\n return uiMethodsMap.get(id) ?? [];\n },\n };\n})();\n\nexport function serviceFnKey(serviceId: string, method = \"\"): string {\n return `service:${serviceId}:${method}`;\n}\n\nexport type ServiceBrand<T> =\n T extends Branded<string, infer S extends ServiceTypesLike> ? S : never;\n\nexport type ModelServiceFactoryMap<SMap extends Record<string, ServiceName>> = {\n [K in keyof SMap]: (() => InferServiceModel<ServiceBrand<SMap[K]>>) | null;\n};\n\nexport type UiServiceFactoryMap<SMap extends Record<string, ServiceName>> = {\n [K in keyof SMap]: (() => InferServiceUi<ServiceBrand<SMap[K]>>) | null;\n};\n\n/** Contract between any service provider and any service consumer. */\nexport interface ServiceDispatch {\n getServiceNames(): ServiceName[];\n getServiceMethods(serviceId: ServiceName): string[];\n callServiceMethod(serviceId: ServiceName, method: string, ...args: unknown[]): unknown;\n}\n\n// Auto-derived types from the Services const in service_declarations.ts.\n// Adding a service to Services automatically updates all of these.\n\ntype TServices = typeof Services;\n\ntype ExtractServiceName<T> = T extends Branded<infer N extends string, any> ? N : never;\n\n/** Model-side service interfaces keyed by service name literal. */\nexport type ModelServices = {\n [K in keyof TServices as ExtractServiceName<TServices[K]>]: InferServiceModel<\n ServiceBrand<TServices[K]>\n >;\n};\n\n/** UI-side service interfaces keyed by service name literal. */\nexport type UiServices = {\n [K in keyof TServices as ExtractServiceName<TServices[K]>]: InferServiceUi<\n ServiceBrand<TServices[K]>\n >;\n};\n\n/** Map from Services keys to their unbranded string name literals. */\nexport type ServiceNameLiterals = {\n [K in keyof TServices]: ExtractServiceName<TServices[K]>;\n};\n\n/** Auto-derived requires* feature flags from Services keys. */\nexport type ServiceRequireFlags = {\n [K in keyof TServices as `requires${K & string}`]?: boolean;\n};\n\nexport type RequireServices<T extends ServiceName> = UnionToIntersection<\n T extends Branded<infer N extends string, infer S extends ServiceTypesLike>\n ? Record<N, InferServiceModel<S>>\n : never\n>;\n"],"mappings":";;AA0BA,MAAM,qBAAqB;AAE3B,MAAa,EACX,SACA,eACA,eACA,eACA,gBACA,wBACA,+BACS;CACT,MAAM,0BAAU,IAAI,KAA0B;CAC9C,MAAM,kCAAkB,IAAI,KAAgC;CAC5D,MAAM,+BAAe,IAAI,KAAgC;AACzD,QAAO;EACL,UAAqB;AACnB,WAKE,YAKgD;IAChD,MAAM,EAAE,MAAM,MAAM,cAAc,cAAc;AAChD,QAAI,CAAC,mBAAmB,KAAK,KAAK,CAChC,OAAM,IAAI,sBACR,uBAAuB,KAAK,gBAAgB,qBAC7C;AAEH,QAAI,QAAQ,IAAI,KAAK,CACnB,OAAM,IAAI,8BAA8B,YAAY,KAAK,sBAAsB;AAEjF,YAAQ,IAAI,MAAM,KAAK;AACvB,oBAAgB,IAAI,MAAM,aAAa;AACvC,iBAAa,IAAI,MAAM,UAAU;AACjC,WAAO;;;EAGX,cAAc,IAA0B;AACtC,UAAO,QAAQ,IAAI,GAAG,KAAK;;EAE7B,cAAc,IAA0B;AACtC,UAAO,QAAQ,IAAI,GAAG,KAAK;;EAE7B,cAAc,IAA0B;AACtC,UAAO,QAAQ,IAAI,GAAG,KAAK;;EAE7B,eAAe,IAA0C;AACvD,UAAO,QAAQ,IAAI,GAAG;;EAExB,uBAAuB,IAAoC;AACzD,UAAO,gBAAgB,IAAI,GAAG,IAAI,EAAE;;EAEtC,oBAAoB,IAAoC;AACtD,UAAO,aAAa,IAAI,GAAG,IAAI,EAAE;;EAEpC;IACC;AAEJ,SAAgB,aAAa,WAAmB,SAAS,IAAY;AACnE,QAAO,WAAW,UAAU,GAAG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/pl-model-common",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.36.1",
|
|
4
4
|
"description": "Platforma SDK Model",
|
|
5
5
|
"files": [
|
|
6
6
|
"./dist/**/*",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"typescript": "~5.9.3",
|
|
28
28
|
"vitest": "^4.1.3",
|
|
29
29
|
"@milaboratories/build-configs": "2.0.0",
|
|
30
|
-
"@milaboratories/ts-
|
|
31
|
-
"@milaboratories/ts-
|
|
30
|
+
"@milaboratories/ts-configs": "1.2.3",
|
|
31
|
+
"@milaboratories/ts-builder": "1.3.2"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "ts-builder build --target node",
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File filter passed to the native save dialog. Matches Electron's
|
|
3
|
+
* `FileFilter` shape so desktop runtimes can forward it verbatim.
|
|
4
|
+
*/
|
|
5
|
+
export interface FileFilter {
|
|
6
|
+
name: string;
|
|
7
|
+
extensions: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Options accepted by `Dialog.showSaveDialog`. The UI supplies only a
|
|
12
|
+
* default file name; the main-process handler decides the default
|
|
13
|
+
* directory (e.g. `~/Downloads`).
|
|
14
|
+
*/
|
|
15
|
+
export interface ShowSaveDialogOptions {
|
|
16
|
+
defaultFileName?: string;
|
|
17
|
+
filters?: FileFilter[];
|
|
18
|
+
title?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Result of `Dialog.showSaveDialog`. */
|
|
22
|
+
export interface ShowSaveDialogResult {
|
|
23
|
+
canceled: boolean;
|
|
24
|
+
path?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* UI-facing save-dialog service. Implemented by desktop runtimes that
|
|
29
|
+
* can open a native file picker; absent in web/preview environments.
|
|
30
|
+
*/
|
|
31
|
+
export interface DialogService {
|
|
32
|
+
showSaveDialog(options: ShowSaveDialogOptions): Promise<ShowSaveDialogResult>;
|
|
33
|
+
}
|