@platforma-sdk/model 1.65.9 → 1.66.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/dist/block_model.cjs +8 -11
  2. package/dist/block_model.cjs.map +1 -1
  3. package/dist/block_model.d.ts.map +1 -1
  4. package/dist/block_model.js +8 -10
  5. package/dist/block_model.js.map +1 -1
  6. package/dist/columns/column_collection_builder.cjs +61 -74
  7. package/dist/columns/column_collection_builder.cjs.map +1 -1
  8. package/dist/columns/column_collection_builder.d.ts +16 -22
  9. package/dist/columns/column_collection_builder.d.ts.map +1 -1
  10. package/dist/columns/column_collection_builder.js +62 -75
  11. package/dist/columns/column_collection_builder.js.map +1 -1
  12. package/dist/columns/column_selector.cjs.map +1 -1
  13. package/dist/columns/column_selector.d.ts +1 -1
  14. package/dist/columns/column_selector.js.map +1 -1
  15. package/dist/columns/column_snapshot.cjs.map +1 -1
  16. package/dist/columns/column_snapshot.d.ts +4 -4
  17. package/dist/columns/column_snapshot.d.ts.map +1 -1
  18. package/dist/columns/column_snapshot.js.map +1 -1
  19. package/dist/columns/ctx_column_sources.cjs.map +1 -1
  20. package/dist/columns/ctx_column_sources.d.ts +1 -1
  21. package/dist/columns/ctx_column_sources.d.ts.map +1 -1
  22. package/dist/columns/ctx_column_sources.js.map +1 -1
  23. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs +2 -2
  24. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs.map +1 -1
  25. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js +2 -2
  26. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js.map +1 -1
  27. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs +17 -18
  28. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs.map +1 -1
  29. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js +17 -18
  30. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js.map +1 -1
  31. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +99 -91
  32. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
  33. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +16 -16
  34. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts.map +1 -1
  35. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +102 -94
  36. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
  37. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs +32 -23
  38. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs.map +1 -1
  39. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts +5 -5
  40. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts.map +1 -1
  41. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js +33 -24
  42. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js.map +1 -1
  43. package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
  44. package/dist/components/PlDataTable/createPlDataTable/index.d.ts +2 -3
  45. package/dist/components/PlDataTable/createPlDataTable/index.d.ts.map +1 -1
  46. package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
  47. package/dist/components/PlDataTable/createPlDataTable/utils.cjs +133 -16
  48. package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -1
  49. package/dist/components/PlDataTable/createPlDataTable/utils.d.ts +8 -6
  50. package/dist/components/PlDataTable/createPlDataTable/utils.d.ts.map +1 -1
  51. package/dist/components/PlDataTable/createPlDataTable/utils.js +130 -17
  52. package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -1
  53. package/dist/components/PlDataTable/labels.cjs +1 -2
  54. package/dist/components/PlDataTable/labels.cjs.map +1 -1
  55. package/dist/components/PlDataTable/labels.js +1 -2
  56. package/dist/components/PlDataTable/labels.js.map +1 -1
  57. package/dist/filters/distill.cjs +73 -30
  58. package/dist/filters/distill.cjs.map +1 -1
  59. package/dist/filters/distill.d.ts.map +1 -1
  60. package/dist/filters/distill.js +73 -30
  61. package/dist/filters/distill.js.map +1 -1
  62. package/dist/index.cjs +19 -15
  63. package/dist/index.d.ts +4 -2
  64. package/dist/index.js +6 -4
  65. package/dist/labels/derive_distinct_tooltips.cjs +85 -0
  66. package/dist/labels/derive_distinct_tooltips.cjs.map +1 -0
  67. package/dist/labels/derive_distinct_tooltips.d.ts +17 -0
  68. package/dist/labels/derive_distinct_tooltips.d.ts.map +1 -0
  69. package/dist/labels/derive_distinct_tooltips.js +84 -0
  70. package/dist/labels/derive_distinct_tooltips.js.map +1 -0
  71. package/dist/labels/index.cjs +1 -0
  72. package/dist/labels/index.d.ts +2 -1
  73. package/dist/labels/index.js +1 -0
  74. package/dist/package.cjs +1 -1
  75. package/dist/package.js +1 -1
  76. package/dist/render/api.cjs +8 -13
  77. package/dist/render/api.cjs.map +1 -1
  78. package/dist/render/api.d.ts +8 -11
  79. package/dist/render/api.d.ts.map +1 -1
  80. package/dist/render/api.js +8 -13
  81. package/dist/render/api.js.map +1 -1
  82. package/dist/services/get_services.cjs +19 -0
  83. package/dist/services/get_services.cjs.map +1 -0
  84. package/dist/services/get_services.d.ts +7 -0
  85. package/dist/services/get_services.d.ts.map +1 -0
  86. package/dist/services/get_services.js +19 -0
  87. package/dist/services/get_services.js.map +1 -0
  88. package/dist/services/index.cjs +1 -0
  89. package/dist/services/index.d.ts +2 -1
  90. package/dist/services/index.js +1 -0
  91. package/dist/services/service_bridge.cjs +4 -4
  92. package/dist/services/service_bridge.cjs.map +1 -1
  93. package/dist/services/service_bridge.d.ts +4 -4
  94. package/dist/services/service_bridge.d.ts.map +1 -1
  95. package/dist/services/service_bridge.js +4 -4
  96. package/dist/services/service_bridge.js.map +1 -1
  97. package/package.json +6 -6
  98. package/src/block_model.ts +8 -11
  99. package/src/columns/column_collection_builder.test.ts +75 -30
  100. package/src/columns/column_collection_builder.ts +96 -133
  101. package/src/columns/column_selector.ts +1 -1
  102. package/src/columns/column_snapshot.ts +7 -4
  103. package/src/columns/ctx_column_sources.ts +1 -3
  104. package/src/components/PFrameForGraphs.test.ts +4 -4
  105. package/src/components/PlDataTable/createPlDataTable/createPTableDefV2.ts +2 -2
  106. package/src/components/PlDataTable/createPlDataTable/createPTableDefV3.ts +44 -21
  107. package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +202 -218
  108. package/src/components/PlDataTable/createPlDataTable/discoverColumns.ts +69 -56
  109. package/src/components/PlDataTable/createPlDataTable/index.ts +6 -7
  110. package/src/components/PlDataTable/createPlDataTable/utils.test.ts +97 -1
  111. package/src/components/PlDataTable/createPlDataTable/utils.ts +190 -35
  112. package/src/components/PlDataTable/labels.ts +3 -7
  113. package/src/filters/distill.test.ts +91 -0
  114. package/src/filters/distill.ts +102 -46
  115. package/src/labels/derive_distinct_tooltips.test.ts +233 -0
  116. package/src/labels/derive_distinct_tooltips.ts +130 -0
  117. package/src/labels/index.ts +1 -0
  118. package/src/render/api.ts +15 -50
  119. package/src/services/get_services.ts +28 -0
  120. package/src/services/index.ts +1 -0
  121. package/src/services/service_bridge.ts +5 -5
@@ -1,2 +1,3 @@
1
1
  import "./block_services.js";
2
2
  import "./service_bridge.js";
3
+ import "./get_services.js";
@@ -21,14 +21,14 @@ function buildServices(dispatch, registry) {
21
21
  })));
22
22
  }
23
23
  /**
24
- * Builds a NodeServiceProxy from a ServiceDispatch.
24
+ * Builds a ServiceProxy from a ServiceDispatch.
25
25
  * Each service method call is forwarded to dispatch.callServiceMethod.
26
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)]))));
27
+ function createServiceProxy(dispatch) {
28
+ return ((serviceId) => Object.freeze(Object.fromEntries(dispatch.getServiceMethods(serviceId).map((method) => [method, (...args) => dispatch.callServiceMethod(serviceId, method, ...args)]))));
29
29
  }
30
30
  //#endregion
31
31
  exports.buildServices = buildServices;
32
- exports.createNodeServiceProxy = createNodeServiceProxy;
32
+ exports.createServiceProxy = createServiceProxy;
33
33
 
34
34
  //# sourceMappingURL=service_bridge.cjs.map
@@ -1 +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"}
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 ServiceProxy = <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 ServiceProxy from a ServiceDispatch.\n * Each service method call is forwarded to dispatch.callServiceMethod.\n */\nexport function createServiceProxy(dispatch: ServiceDispatch): ServiceProxy {\n return ((serviceId: ServiceName) =>\n Object.freeze(\n Object.fromEntries(\n dispatch\n .getServiceMethods(serviceId)\n .map((method) => [\n method,\n (...args: unknown[]) => dispatch.callServiceMethod(serviceId, method, ...args),\n ]),\n ),\n )) as ServiceProxy;\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,mBAAmB,UAAyC;AAC1E,UAAS,cACP,OAAO,OACL,OAAO,YACL,SACG,kBAAkB,UAAU,CAC5B,KAAK,WAAW,CACf,SACC,GAAG,SAAoB,SAAS,kBAAkB,WAAW,QAAQ,GAAG,KAAK,CAC/E,CAAC,CACL,CACF"}
@@ -1,7 +1,7 @@
1
1
  import { InferServiceUi, ServiceDispatch, ServiceName, ServiceTypesLike, UiServiceRegistry, UiServices } from "@milaboratories/pl-model-common";
2
2
 
3
3
  //#region src/services/service_bridge.d.ts
4
- type NodeServiceProxy = <S extends ServiceTypesLike>(serviceId: ServiceName<S>) => InferServiceUi<S>;
4
+ type ServiceProxy = <S extends ServiceTypesLike>(serviceId: ServiceName<S>) => InferServiceUi<S>;
5
5
  /**
6
6
  * Builds a lazy services object from ServiceDispatch and UiServiceRegistry.
7
7
  * Each service is instantiated on first access. Errors are cached to prevent
@@ -9,10 +9,10 @@ type NodeServiceProxy = <S extends ServiceTypesLike>(serviceId: ServiceName<S>)
9
9
  */
10
10
  declare function buildServices<S extends Partial<UiServices> = Partial<UiServices>>(dispatch: ServiceDispatch, registry: UiServiceRegistry): S;
11
11
  /**
12
- * Builds a NodeServiceProxy from a ServiceDispatch.
12
+ * Builds a ServiceProxy from a ServiceDispatch.
13
13
  * Each service method call is forwarded to dispatch.callServiceMethod.
14
14
  */
15
- declare function createNodeServiceProxy(dispatch: ServiceDispatch): NodeServiceProxy;
15
+ declare function createServiceProxy(dispatch: ServiceDispatch): ServiceProxy;
16
16
  //#endregion
17
- export { NodeServiceProxy, buildServices, createNodeServiceProxy };
17
+ export { ServiceProxy, buildServices, createServiceProxy };
18
18
  //# sourceMappingURL=service_bridge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service_bridge.d.ts","names":[],"sources":["../../src/services/service_bridge.ts"],"mappings":";;;KAiBY,gBAAA,cAA8B,gBAAA,EACxC,SAAA,EAAW,WAAA,CAAY,CAAA,MACpB,cAAA,CAAe,CAAA;;;;;;iBAOJ,aAAA,WAAwB,OAAA,CAAQ,UAAA,IAAiB,OAAA,CAAQ,UAAA,EAAA,CACvE,QAAA,EAAU,eAAA,EACV,QAAA,EAAU,iBAAA,GACT,CAAA;;;;;iBA6Ba,sBAAA,CAAuB,QAAA,EAAU,eAAA,GAAkB,gBAAA"}
1
+ {"version":3,"file":"service_bridge.d.ts","names":[],"sources":["../../src/services/service_bridge.ts"],"mappings":";;;KAiBY,YAAA,cAA0B,gBAAA,EACpC,SAAA,EAAW,WAAA,CAAY,CAAA,MACpB,cAAA,CAAe,CAAA;;;;;;iBAOJ,aAAA,WAAwB,OAAA,CAAQ,UAAA,IAAiB,OAAA,CAAQ,UAAA,EAAA,CACvE,QAAA,EAAU,eAAA,EACV,QAAA,EAAU,iBAAA,GACT,CAAA;;;;;iBA6Ba,kBAAA,CAAmB,QAAA,EAAU,eAAA,GAAkB,YAAA"}
@@ -21,13 +21,13 @@ function buildServices(dispatch, registry) {
21
21
  })));
22
22
  }
23
23
  /**
24
- * Builds a NodeServiceProxy from a ServiceDispatch.
24
+ * Builds a ServiceProxy from a ServiceDispatch.
25
25
  * Each service method call is forwarded to dispatch.callServiceMethod.
26
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)]))));
27
+ function createServiceProxy(dispatch) {
28
+ return ((serviceId) => Object.freeze(Object.fromEntries(dispatch.getServiceMethods(serviceId).map((method) => [method, (...args) => dispatch.callServiceMethod(serviceId, method, ...args)]))));
29
29
  }
30
30
  //#endregion
31
- export { buildServices, createNodeServiceProxy };
31
+ export { buildServices, createServiceProxy };
32
32
 
33
33
  //# sourceMappingURL=service_bridge.js.map
@@ -1 +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"}
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 ServiceProxy = <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 ServiceProxy from a ServiceDispatch.\n * Each service method call is forwarded to dispatch.callServiceMethod.\n */\nexport function createServiceProxy(dispatch: ServiceDispatch): ServiceProxy {\n return ((serviceId: ServiceName) =>\n Object.freeze(\n Object.fromEntries(\n dispatch\n .getServiceMethods(serviceId)\n .map((method) => [\n method,\n (...args: unknown[]) => dispatch.callServiceMethod(serviceId, method, ...args),\n ]),\n ),\n )) as ServiceProxy;\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,mBAAmB,UAAyC;AAC1E,UAAS,cACP,OAAO,OACL,OAAO,YACL,SACG,kBAAkB,UAAU,CAC5B,KAAK,WAAW,CACf,SACC,GAAG,SAAoB,SAAS,kBAAkB,WAAW,QAAQ,GAAG,KAAK,CAC/E,CAAC,CACL,CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/model",
3
- "version": "1.65.9",
3
+ "version": "1.66.2",
4
4
  "description": "Platforma.bio SDK / Block Model",
5
5
  "files": [
6
6
  "./dist/**/*",
@@ -30,20 +30,20 @@
30
30
  "fast-json-patch": "^3.1.1",
31
31
  "utility-types": "^3.11.0",
32
32
  "zod": "~3.25.76",
33
- "@milaboratories/pl-model-common": "1.33.0",
34
- "@milaboratories/pl-model-middle-layer": "1.18.1",
35
33
  "@milaboratories/pl-error-like": "1.12.9",
36
34
  "@milaboratories/helpers": "1.14.1",
37
- "@milaboratories/ptabler-expression-js": "1.2.11"
35
+ "@milaboratories/pl-model-common": "1.34.1",
36
+ "@milaboratories/pl-model-middle-layer": "1.18.3",
37
+ "@milaboratories/ptabler-expression-js": "1.2.13"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@vitest/coverage-istanbul": "^4.1.3",
41
41
  "fast-json-patch": "^3.1.1",
42
42
  "typescript": "~5.9.3",
43
43
  "vitest": "^4.1.3",
44
- "@milaboratories/pf-driver": "1.3.8",
44
+ "@milaboratories/pf-driver": "1.3.10",
45
45
  "@milaboratories/build-configs": "2.0.0",
46
- "@milaboratories/pf-spec-driver": "1.3.0",
46
+ "@milaboratories/pf-spec-driver": "1.3.2",
47
47
  "@milaboratories/ts-builder": "1.3.2",
48
48
  "@milaboratories/ts-configs": "1.2.3"
49
49
  },
@@ -6,12 +6,11 @@ import type {
6
6
  BlockCodeKnownFeatureFlags,
7
7
  BlockConfigContainer,
8
8
  } from "@milaboratories/pl-model-common";
9
- import { resolveRequiredServices } from "@milaboratories/pl-model-common";
10
9
  import { getPlatformaInstance, isInUI, createAndRegisterRenderLambda } from "./internal";
11
10
  import type { DataModel } from "./block_migrations";
12
11
  import type { PlatformaV3 } from "./platforma";
13
12
  import type { BlockDefaultUiServices } from "./services/service_resolve";
14
- import { blockServiceNames, BLOCK_SERVICE_FLAGS } from "./services/block_services";
13
+ import { BLOCK_SERVICE_FLAGS } from "./services/block_services";
15
14
  import type { InferRenderFunctionReturn, RenderFunction } from "./render";
16
15
  import { BlockRenderCtx, PluginRenderCtx } from "./render";
17
16
  import type { PluginData, PluginModel, PluginOutputs, PluginParams } from "./plugin_model";
@@ -237,7 +236,7 @@ export class BlockModelV3<
237
236
  ...this.config.outputs,
238
237
  [key]: createAndRegisterRenderLambda({
239
238
  handle: `block-output#${key}`,
240
- lambda: () => cfgOrRf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
239
+ lambda: () => cfgOrRf(new BlockRenderCtx<Args, Data>()),
241
240
  ...flags,
242
241
  }),
243
242
  },
@@ -335,7 +334,7 @@ export class BlockModelV3<
335
334
  sections: createAndRegisterRenderLambda(
336
335
  {
337
336
  handle: "sections",
338
- lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
337
+ lambda: () => rf(new BlockRenderCtx<Args, Data>()),
339
338
  },
340
339
  true,
341
340
  ),
@@ -351,7 +350,7 @@ export class BlockModelV3<
351
350
  ...this.config,
352
351
  title: createAndRegisterRenderLambda({
353
352
  handle: "title",
354
- lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
353
+ lambda: () => rf(new BlockRenderCtx<Args, Data>()),
355
354
  }),
356
355
  });
357
356
  }
@@ -363,7 +362,7 @@ export class BlockModelV3<
363
362
  ...this.config,
364
363
  subtitle: createAndRegisterRenderLambda({
365
364
  handle: "subtitle",
366
- lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
365
+ lambda: () => rf(new BlockRenderCtx<Args, Data>()),
367
366
  }),
368
367
  });
369
368
  }
@@ -375,7 +374,7 @@ export class BlockModelV3<
375
374
  ...this.config,
376
375
  tags: createAndRegisterRenderLambda({
377
376
  handle: "tags",
378
- lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
377
+ lambda: () => rf(new BlockRenderCtx<Args, Data>()),
379
378
  }),
380
379
  });
381
380
  }
@@ -536,8 +535,6 @@ export class BlockModelV3<
536
535
 
537
536
  const { dataModel, argsFunction, prerunArgsFunction } = this.config;
538
537
 
539
- const mergedServiceNames = resolveRequiredServices(this.config.featureFlags);
540
-
541
538
  function getPlugin(handle: PluginHandle): PluginRecord {
542
539
  const plugin = plugins[handle];
543
540
  if (!plugin) throw new Error(`Plugin model not found for '${handle}'`);
@@ -577,7 +574,7 @@ export class BlockModelV3<
577
574
  // Wrap plugin param lambdas: close over BlockRenderCtx creation
578
575
  const wrappedInputs: Record<string, () => unknown> = {};
579
576
  for (const [paramKey, paramFn] of Object.entries(inputs)) {
580
- wrappedInputs[paramKey] = () => paramFn(new BlockRenderCtx(mergedServiceNames));
577
+ wrappedInputs[paramKey] = () => paramFn(new BlockRenderCtx());
581
578
  }
582
579
 
583
580
  // Register plugin outputs (in config pack, evaluated by middle layer)
@@ -587,7 +584,7 @@ export class BlockModelV3<
587
584
  const key = pluginOutputKey(handle, outputKey);
588
585
  pluginOutputs[key] = createAndRegisterRenderLambda({
589
586
  handle: key,
590
- lambda: () => outputFn(new PluginRenderCtx(handle, wrappedInputs, mergedServiceNames)),
587
+ lambda: () => outputFn(new PluginRenderCtx(handle, wrappedInputs)),
591
588
  withStatus: outputFlags[outputKey]?.withStatus,
592
589
  });
593
590
  }
@@ -1,10 +1,4 @@
1
- import type {
2
- AxisSpec,
3
- PColumnSpec,
4
- PObjectId,
5
- SUniversalPColumnId,
6
- } from "@milaboratories/pl-model-common";
7
- import { AnchoredIdDeriver } from "@milaboratories/pl-model-common";
1
+ import type { AxisSpec, PColumnSpec, PObjectId } from "@milaboratories/pl-model-common";
8
2
  import { SpecDriver } from "@milaboratories/pf-spec-driver";
9
3
 
10
4
  import { afterEach, describe, expect, test } from "vitest";
@@ -122,25 +116,26 @@ describe("ColumnCollectionBuilder", () => {
122
116
  });
123
117
  });
124
118
 
125
- describe("ColumnCollection.getColumn", () => {
126
- test("returns snapshot for existing id", () => {
119
+ describe("ColumnCollection lookup by id", () => {
120
+ test("findColumns includes snapshot with existing id", () => {
127
121
  const spec = createSpec("col1");
128
122
  const snap = createSnapshot("id1", spec);
129
123
  const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
130
124
  builder.addSource([snap]);
131
125
 
132
126
  const collection = builder.build()!;
133
- const found = collection.getColumn("id1" as PObjectId);
127
+ const found = collection.findColumns().find((c) => c.id === ("id1" as PObjectId));
134
128
  expect(found).toBeDefined();
135
129
  expect(found!.spec.name).toBe("col1");
136
130
  });
137
131
 
138
- test("returns undefined for missing id", () => {
132
+ test("findColumns does not include missing id", () => {
139
133
  const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
140
134
  builder.addSource([createSnapshot("id1", createSpec("col1"))]);
141
135
 
142
136
  const collection = builder.build()!;
143
- expect(collection.getColumn("missing" as PObjectId)).toBeUndefined();
137
+ const found = collection.findColumns().find((c) => c.id === ("missing" as PObjectId));
138
+ expect(found).toBeUndefined();
144
139
  });
145
140
  });
146
141
 
@@ -232,7 +227,7 @@ describe("data status handling", () => {
232
227
  builder.addSource([snap]);
233
228
  const collection = builder.build()!;
234
229
 
235
- const found = collection.getColumn("id1" as PObjectId)!;
230
+ const found = collection.findColumns().find((c) => c.id === ("id1" as PObjectId))!;
236
231
  expect(found.dataStatus).toBe("ready");
237
232
  expect(found.data).toBeDefined();
238
233
  expect(found.data!.get()).toBe(data);
@@ -245,7 +240,7 @@ describe("data status handling", () => {
245
240
  builder.addSource([snap]);
246
241
  const collection = builder.build()!;
247
242
 
248
- const found = collection.getColumn("id1" as PObjectId)!;
243
+ const found = collection.findColumns().find((c) => c.id === ("id1" as PObjectId))!;
249
244
  expect(found.dataStatus).toBe("computing");
250
245
  expect(found.data).toBeDefined();
251
246
 
@@ -260,7 +255,7 @@ describe("data status handling", () => {
260
255
  builder.addSource([snap]);
261
256
  const collection = builder.build()!;
262
257
 
263
- const found = collection.getColumn("id1" as PObjectId)!;
258
+ const found = collection.findColumns().find((c) => c.id === ("id1" as PObjectId))!;
264
259
  expect(found.dataStatus).toBe("absent");
265
260
  expect(found.data).toBeUndefined();
266
261
  });
@@ -338,7 +333,7 @@ describe("AnchoredColumnCollection", () => {
338
333
  );
339
334
  });
340
335
 
341
- test("getColumn returns snapshot by SUniversalPColumnId", () => {
336
+ test("findColumns surfaces column by original PObjectId", () => {
342
337
  const spec = createSpec("col1", { axesSpec: [sampleAxis("sample")] });
343
338
  const snap = createSnapshot("id1", spec);
344
339
  const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
@@ -346,22 +341,22 @@ describe("AnchoredColumnCollection", () => {
346
341
 
347
342
  const collection = builder.build({ anchors: { main: anchorSpec } })!;
348
343
 
349
- const idDeriver = new AnchoredIdDeriver({ main: anchorSpec });
350
- const expectedId = idDeriver.deriveS(spec);
351
-
352
- const found = collection.getColumn(expectedId);
344
+ const matches = collection.findColumns();
345
+ const found = matches.find((m) => m.column.id === ("id1" as PObjectId));
353
346
  expect(found).toBeDefined();
354
- expect(found!.spec.name).toBe("col1");
355
- expect(found!.id).toBe(expectedId);
347
+ expect(found!.column.spec.name).toBe("col1");
356
348
  });
357
349
 
358
- test("getColumn returns undefined for unknown id", () => {
350
+ test("findColumns does not include unknown id", () => {
359
351
  const snap = createSnapshot("id1", createSpec("col1", { axesSpec: [sampleAxis("sample")] }));
360
352
  const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
361
353
  builder.addSource([snap, anchorSnap]);
362
354
 
363
355
  const collection = builder.build({ anchors: { main: anchorSpec } })!;
364
- expect(collection.getColumn("not-a-real-id" as SUniversalPColumnId)).toBeUndefined();
356
+ const found = collection
357
+ .findColumns()
358
+ .find((m) => m.column.id === ("not-a-real-id" as PObjectId));
359
+ expect(found).toBeUndefined();
365
360
  });
366
361
 
367
362
  test("getAnchors returns resolved anchor map", () => {
@@ -377,7 +372,7 @@ describe("AnchoredColumnCollection", () => {
377
372
  expect(anchors.get("main")!.spec.name).toBe("anchor-col");
378
373
  });
379
374
 
380
- test("findColumns returns ColumnMatch with originalId and variants", () => {
375
+ test("findColumns returns ColumnMatch with column id and variants", () => {
381
376
  const spec = createSpec("col1", { axesSpec: [sampleAxis("sample")] });
382
377
  const snap = createSnapshot("id1", spec);
383
378
  const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
@@ -391,10 +386,61 @@ describe("AnchoredColumnCollection", () => {
391
386
  expect(matches.length).toBeGreaterThanOrEqual(1);
392
387
  const col1Match = matches.find((m) => m.column.spec.name === "col1")!;
393
388
  expect(col1Match).toBeDefined();
394
- expect(col1Match.originalId).toBe("id1");
389
+ expect(col1Match.column.id).toBe("id1");
395
390
  expect(col1Match.variants).toBeDefined();
396
391
  });
397
392
 
393
+ test("variants carry forQueries keyed by anchor PObjectId", () => {
394
+ const spec = createSpec("col1", { axesSpec: [sampleAxis("sample")] });
395
+ const snap = createSnapshot("id1", spec);
396
+ const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
397
+ builder.addSource([snap, anchorSnap]);
398
+
399
+ const collection = builder.build({ anchors: { main: anchorSpec } })!;
400
+ const matches = collection.findColumns();
401
+ const col1Match = matches.find((m) => m.column.spec.name === "col1")!;
402
+
403
+ expect(col1Match.variants.length).toBeGreaterThan(0);
404
+ for (const v of col1Match.variants) {
405
+ expect(v.qualifications.forQueries).toBeDefined();
406
+ expect(v.qualifications.forHit).toBeDefined();
407
+ expect(v.distinctiveQualifications.forQueries).toBeDefined();
408
+ expect(v.distinctiveQualifications.forHit).toBeDefined();
409
+ // forQueries keys are a subset of anchor ids
410
+ for (const key of Object.keys(v.qualifications.forQueries)) {
411
+ expect([anchorSnap.id]).toContain(key);
412
+ }
413
+ }
414
+ });
415
+
416
+ test("anchors sharing same axes group produce forQueries entries pointing to same array", () => {
417
+ // Two anchors with identical axesSpec share an axes-group bucket in the reverse index.
418
+ const sharedAxes = [sampleAxis("sample"), sampleAxis("gene")];
419
+ const anchorA = createSpec("anchor-a", { axesSpec: sharedAxes });
420
+ const anchorB = createSpec("anchor-b", { axesSpec: sharedAxes });
421
+ const anchorASnap = createSnapshot("anchor-a-id", anchorA);
422
+ const anchorBSnap = createSnapshot("anchor-b-id", anchorB);
423
+
424
+ const colSpec = createSpec("c1", { axesSpec: [sampleAxis("sample")] });
425
+ const colSnap = createSnapshot("c1-id", colSpec);
426
+
427
+ const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
428
+ builder.addSource([colSnap, anchorASnap, anchorBSnap]);
429
+
430
+ const collection = builder.build({ anchors: { a: anchorA, b: anchorB } })!;
431
+ const matches = collection.findColumns();
432
+ const c1 = matches.find((m) => m.column.spec.name === "c1")!;
433
+ expect(c1).toBeDefined();
434
+
435
+ for (const v of c1.variants) {
436
+ const forQueries = v.qualifications.forQueries;
437
+ if (anchorASnap.id in forQueries && anchorBSnap.id in forQueries) {
438
+ // Shared axes group → equal qualifications for both anchor keys.
439
+ expect(forQueries[anchorASnap.id]).toStrictEqual(forQueries[anchorBSnap.id]);
440
+ }
441
+ }
442
+ });
443
+
398
444
  test("findColumns exclude filters out matching columns", () => {
399
445
  const snap1 = createSnapshot("id1", createSpec("col1", { axesSpec: [sampleAxis("sample")] }));
400
446
  const snap2 = createSnapshot("id2", createSpec("col2", { axesSpec: [sampleAxis("sample")] }));
@@ -437,9 +483,8 @@ describe("AnchoredColumnCollection", () => {
437
483
 
438
484
  const collection = builder.build({ anchors: { main: anchorSpec } })!;
439
485
 
440
- const idDeriver = new AnchoredIdDeriver({ main: anchorSpec });
441
- const found = collection.getColumn(idDeriver.deriveS(spec))!;
442
- expect(found.dataStatus).toBe("computing");
443
- expect(found.data!.get()).toBeUndefined();
486
+ const found = collection.findColumns().find((m) => m.column.id === ("id1" as PObjectId))!;
487
+ expect(found.column.dataStatus).toBe("computing");
488
+ expect(found.column.data!.get()).toBeUndefined();
444
489
  });
445
490
  });