@milaboratories/pl-model-common 1.46.4 → 1.47.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.
Files changed (178) hide show
  1. package/dist/columns/accessor_traversal.cjs +119 -0
  2. package/dist/columns/accessor_traversal.cjs.map +1 -0
  3. package/dist/columns/accessor_traversal.d.ts +52 -0
  4. package/dist/columns/accessor_traversal.d.ts.map +1 -0
  5. package/dist/columns/accessor_traversal.js +114 -0
  6. package/dist/columns/accessor_traversal.js.map +1 -0
  7. package/dist/columns/column_registry.cjs +40 -0
  8. package/dist/columns/column_registry.cjs.map +1 -0
  9. package/dist/columns/column_registry.d.ts +31 -0
  10. package/dist/columns/column_registry.d.ts.map +1 -0
  11. package/dist/columns/column_registry.js +40 -0
  12. package/dist/columns/column_registry.js.map +1 -0
  13. package/dist/columns/column_selector.cjs +49 -0
  14. package/dist/columns/column_selector.cjs.map +1 -0
  15. package/dist/columns/column_selector.d.ts +33 -0
  16. package/dist/columns/column_selector.d.ts.map +1 -0
  17. package/dist/columns/column_selector.js +47 -0
  18. package/dist/columns/column_selector.js.map +1 -0
  19. package/dist/columns/dedup.cjs +47 -0
  20. package/dist/columns/dedup.cjs.map +1 -0
  21. package/dist/columns/dedup.d.ts +27 -0
  22. package/dist/columns/dedup.d.ts.map +1 -0
  23. package/dist/columns/dedup.js +47 -0
  24. package/dist/columns/dedup.js.map +1 -0
  25. package/dist/columns/index.cjs +18 -0
  26. package/dist/columns/index.d.ts +8 -0
  27. package/dist/columns/index.js +6 -0
  28. package/dist/columns/providers.cjs +62 -0
  29. package/dist/columns/providers.cjs.map +1 -0
  30. package/dist/columns/providers.d.ts +39 -0
  31. package/dist/columns/providers.d.ts.map +1 -0
  32. package/dist/columns/providers.js +61 -0
  33. package/dist/columns/providers.js.map +1 -0
  34. package/dist/columns/types.d.ts +108 -0
  35. package/dist/columns/types.d.ts.map +1 -0
  36. package/dist/driver_kit.d.ts +1 -2
  37. package/dist/driver_kit.d.ts.map +1 -1
  38. package/dist/drivers/columns/columns_collection_driver.d.ts +124 -0
  39. package/dist/drivers/columns/columns_collection_driver.d.ts.map +1 -0
  40. package/dist/drivers/columns/discover_columns_options.cjs +28 -0
  41. package/dist/drivers/columns/discover_columns_options.cjs.map +1 -0
  42. package/dist/drivers/columns/discover_columns_options.d.ts +64 -0
  43. package/dist/drivers/columns/discover_columns_options.d.ts.map +1 -0
  44. package/dist/drivers/columns/discover_columns_options.js +28 -0
  45. package/dist/drivers/columns/discover_columns_options.js.map +1 -0
  46. package/dist/drivers/columns/index.d.ts +3 -0
  47. package/dist/drivers/index.cjs +32 -7
  48. package/dist/drivers/index.d.ts +12 -9
  49. package/dist/drivers/index.js +6 -4
  50. package/dist/drivers/pframe/driver.d.ts +1 -2
  51. package/dist/drivers/pframe/driver.d.ts.map +1 -1
  52. package/dist/drivers/pframe/index.cjs +30 -7
  53. package/dist/drivers/pframe/index.d.ts +9 -8
  54. package/dist/drivers/pframe/index.js +5 -4
  55. package/dist/drivers/pframe/query/index.d.ts +2 -2
  56. package/dist/drivers/pframe/query/query_common.d.ts +24 -1
  57. package/dist/drivers/pframe/query/query_common.d.ts.map +1 -1
  58. package/dist/drivers/pframe/query/query_spec.d.ts +25 -24
  59. package/dist/drivers/pframe/query/query_spec.d.ts.map +1 -1
  60. package/dist/drivers/pframe/query/utils.cjs +18 -8
  61. package/dist/drivers/pframe/query/utils.cjs.map +1 -1
  62. package/dist/drivers/pframe/query/utils.d.ts +5 -1
  63. package/dist/drivers/pframe/query/utils.d.ts.map +1 -1
  64. package/dist/drivers/pframe/query/utils.js +18 -8
  65. package/dist/drivers/pframe/query/utils.js.map +1 -1
  66. package/dist/drivers/pframe/spec/anchored.d.ts +2 -2
  67. package/dist/drivers/pframe/spec/discovered_column.cjs +31 -15
  68. package/dist/drivers/pframe/spec/discovered_column.cjs.map +1 -1
  69. package/dist/drivers/pframe/spec/discovered_column.d.ts +23 -13
  70. package/dist/drivers/pframe/spec/discovered_column.d.ts.map +1 -1
  71. package/dist/drivers/pframe/spec/discovered_column.js +26 -12
  72. package/dist/drivers/pframe/spec/discovered_column.js.map +1 -1
  73. package/dist/drivers/pframe/spec/filtered_column.cjs +46 -0
  74. package/dist/drivers/pframe/spec/filtered_column.cjs.map +1 -1
  75. package/dist/drivers/pframe/spec/filtered_column.d.ts +39 -1
  76. package/dist/drivers/pframe/spec/filtered_column.d.ts.map +1 -1
  77. package/dist/drivers/pframe/spec/filtered_column.js +41 -1
  78. package/dist/drivers/pframe/spec/filtered_column.js.map +1 -1
  79. package/dist/drivers/pframe/spec/ids.cjs +62 -10
  80. package/dist/drivers/pframe/spec/ids.cjs.map +1 -1
  81. package/dist/drivers/pframe/spec/ids.d.ts +48 -15
  82. package/dist/drivers/pframe/spec/ids.d.ts.map +1 -1
  83. package/dist/drivers/pframe/spec/ids.js +60 -9
  84. package/dist/drivers/pframe/spec/ids.js.map +1 -1
  85. package/dist/drivers/pframe/spec/index.cjs +30 -7
  86. package/dist/drivers/pframe/spec/index.d.ts +6 -5
  87. package/dist/drivers/pframe/spec/index.js +5 -4
  88. package/dist/drivers/pframe/spec/native_id.cjs +1 -0
  89. package/dist/drivers/pframe/spec/native_id.cjs.map +1 -1
  90. package/dist/drivers/pframe/spec/native_id.js +1 -0
  91. package/dist/drivers/pframe/spec/native_id.js.map +1 -1
  92. package/dist/drivers/pframe/spec/overridden.cjs +212 -0
  93. package/dist/drivers/pframe/spec/overridden.cjs.map +1 -0
  94. package/dist/drivers/pframe/spec/overridden.d.ts +67 -0
  95. package/dist/drivers/pframe/spec/overridden.d.ts.map +1 -0
  96. package/dist/drivers/pframe/spec/overridden.js +202 -0
  97. package/dist/drivers/pframe/spec/overridden.js.map +1 -0
  98. package/dist/drivers/pframe/spec/selectors.cjs +1 -0
  99. package/dist/drivers/pframe/spec/selectors.cjs.map +1 -1
  100. package/dist/drivers/pframe/spec/selectors.d.ts +3 -0
  101. package/dist/drivers/pframe/spec/selectors.d.ts.map +1 -1
  102. package/dist/drivers/pframe/spec/selectors.js +1 -0
  103. package/dist/drivers/pframe/spec/selectors.js.map +1 -1
  104. package/dist/drivers/pframe/spec/spec.cjs.map +1 -1
  105. package/dist/drivers/pframe/spec/spec.d.ts +2 -3
  106. package/dist/drivers/pframe/spec/spec.d.ts.map +1 -1
  107. package/dist/drivers/pframe/spec/spec.js.map +1 -1
  108. package/dist/drivers/pframe/spec_driver.d.ts +2 -2
  109. package/dist/drivers/pframe/spec_driver.d.ts.map +1 -1
  110. package/dist/drivers/pframe/table_calculate.cjs +2 -2
  111. package/dist/drivers/pframe/table_calculate.cjs.map +1 -1
  112. package/dist/drivers/pframe/table_calculate.d.ts +6 -2
  113. package/dist/drivers/pframe/table_calculate.d.ts.map +1 -1
  114. package/dist/drivers/pframe/table_calculate.js +2 -2
  115. package/dist/drivers/pframe/table_calculate.js.map +1 -1
  116. package/dist/drivers/pframe/table_common.cjs.map +1 -1
  117. package/dist/drivers/pframe/table_common.d.ts +11 -4
  118. package/dist/drivers/pframe/table_common.d.ts.map +1 -1
  119. package/dist/drivers/pframe/table_common.js.map +1 -1
  120. package/dist/index.cjs +63 -10
  121. package/dist/index.d.ts +20 -11
  122. package/dist/index.js +15 -6
  123. package/dist/pool/index.cjs +18 -0
  124. package/dist/pool/index.d.ts +2 -2
  125. package/dist/pool/index.js +3 -0
  126. package/dist/pool/spec.cjs +59 -11
  127. package/dist/pool/spec.cjs.map +1 -1
  128. package/dist/pool/spec.d.ts +24 -9
  129. package/dist/pool/spec.d.ts.map +1 -1
  130. package/dist/pool/spec.js +50 -10
  131. package/dist/pool/spec.js.map +1 -1
  132. package/dist/services/index.d.ts +2 -2
  133. package/dist/services/service_declarations.cjs +22 -0
  134. package/dist/services/service_declarations.cjs.map +1 -1
  135. package/dist/services/service_declarations.d.ts +5 -3
  136. package/dist/services/service_declarations.d.ts.map +1 -1
  137. package/dist/services/service_declarations.js +22 -0
  138. package/dist/services/service_declarations.js.map +1 -1
  139. package/dist/services/service_registry.cjs.map +1 -1
  140. package/dist/services/service_registry.d.ts +3 -3
  141. package/dist/services/service_registry.d.ts.map +1 -1
  142. package/dist/services/service_registry.js.map +1 -1
  143. package/dist/services/service_types.cjs.map +1 -1
  144. package/dist/services/service_types.d.ts +25 -9
  145. package/dist/services/service_types.d.ts.map +1 -1
  146. package/dist/services/service_types.js.map +1 -1
  147. package/package.json +5 -4
  148. package/src/columns/accessor_traversal.ts +139 -0
  149. package/src/columns/column_registry.ts +41 -0
  150. package/src/columns/column_selector.ts +100 -0
  151. package/src/columns/dedup.ts +49 -0
  152. package/src/columns/index.ts +6 -0
  153. package/src/columns/providers.ts +74 -0
  154. package/src/columns/types.ts +116 -0
  155. package/src/drivers/columns/columns_collection_driver.ts +146 -0
  156. package/src/drivers/columns/discover_columns_options.ts +91 -0
  157. package/src/drivers/columns/index.ts +2 -0
  158. package/src/drivers/index.ts +1 -0
  159. package/src/drivers/pframe/index.ts +0 -1
  160. package/src/drivers/pframe/query/query_common.ts +24 -0
  161. package/src/drivers/pframe/query/query_spec.ts +38 -25
  162. package/src/drivers/pframe/query/utils.test.ts +6 -6
  163. package/src/drivers/pframe/query/utils.ts +27 -7
  164. package/src/drivers/pframe/spec/discovered_column.ts +43 -28
  165. package/src/drivers/pframe/spec/filtered_column.ts +66 -0
  166. package/src/drivers/pframe/spec/ids.ts +142 -17
  167. package/src/drivers/pframe/spec/index.ts +1 -0
  168. package/src/drivers/pframe/spec/overridden.ts +285 -0
  169. package/src/drivers/pframe/spec/selectors.ts +3 -0
  170. package/src/drivers/pframe/spec/spec.ts +7 -3
  171. package/src/drivers/pframe/spec_driver.ts +3 -3
  172. package/src/drivers/pframe/table_calculate.ts +13 -3
  173. package/src/drivers/pframe/table_common.ts +10 -3
  174. package/src/index.ts +1 -0
  175. package/src/pool/spec.ts +69 -23
  176. package/src/services/service_declarations.ts +31 -0
  177. package/src/services/service_registry.ts +8 -4
  178. package/src/services/service_types.ts +35 -9
@@ -1,5 +1,5 @@
1
1
  import { Services } from "./service_declarations.js";
2
- import { InferServiceModel, InferServiceUi, ModelServiceFactoryMap, ServiceName, ServiceTypesLike, UiServiceFactoryMap } from "./service_types.js";
2
+ import { InferServiceModelHost, InferServiceUiHost, ModelServiceFactoryMap, ServiceName, ServiceTypesLike, UiServiceFactoryMap } from "./service_types.js";
3
3
 
4
4
  //#region src/services/service_registry.d.ts
5
5
  type RegistryName = "ModelServiceRegistry" | "UiServiceRegistry";
@@ -14,11 +14,11 @@ declare class ServiceRegistryBase {
14
14
  }
15
15
  declare class ModelServiceRegistry<SMap extends Record<string, ServiceName> = typeof Services> extends ServiceRegistryBase {
16
16
  constructor(serviceMap: SMap, factories: ModelServiceFactoryMap<SMap>);
17
- get<S extends ServiceTypesLike>(id: ServiceName<S>): ([unknown] extends [InferServiceModel<S>] ? Record<string, Function> : InferServiceModel<S>) | null;
17
+ get<S extends ServiceTypesLike>(id: ServiceName<S>): ([unknown] extends [InferServiceModelHost<S>] ? Record<string, Function> : InferServiceModelHost<S>) | null;
18
18
  }
19
19
  declare class UiServiceRegistry<SMap extends Record<string, ServiceName> = typeof Services> extends ServiceRegistryBase {
20
20
  constructor(serviceMap: SMap, factories: UiServiceFactoryMap<SMap>);
21
- get<S extends ServiceTypesLike>(id: ServiceName<S>): ([unknown] extends [InferServiceUi<S>] ? Record<string, Function> : InferServiceUi<S>) | null;
21
+ get<S extends ServiceTypesLike>(id: ServiceName<S>): ([unknown] extends [InferServiceUiHost<S>] ? Record<string, Function> : InferServiceUiHost<S>) | null;
22
22
  }
23
23
  //#endregion
24
24
  export { ModelServiceRegistry, UiServiceRegistry };
@@ -1 +1 @@
1
- {"version":3,"file":"service_registry.d.ts","names":[],"sources":["../../src/services/service_registry.ts"],"mappings":";;;;KAWK,YAAA;AAAA,cAGC,mBAAA;EAAA,iBACa,YAAA;EAAA,iBACA,aAAA;EAAA,iBACA,SAAA;EAAA,iBACA,SAAA;EAAA,UAER,WAAA,CACP,YAAA,EAAc,YAAA,EACd,UAAA,EAAY,MAAA,SAAe,WAAA,GAC3B,SAAA,EAAW,MAAA;EAYP,OAAA,IAAW,OAAA;EAAA,UAWP,OAAA,CAAQ,SAAA,EAAW,WAAA,GAAc,MAAA,SAAe,QAAA;AAAA;AAAA,cAiB/C,oBAAA,cACE,MAAA,SAAe,WAAA,WAAsB,QAAA,UAC1C,mBAAA;cACI,UAAA,EAAY,IAAA,EAAM,SAAA,EAAW,sBAAA,CAAuB,IAAA;EAIhE,GAAA,WAAc,gBAAA,EACZ,EAAA,EAAI,WAAA,CAAY,CAAA,wBAEM,iBAAA,CAAkB,CAAA,KAAM,MAAA,SAAe,QAAA,IAAY,iBAAA,CAAkB,CAAA;AAAA;AAAA,cAOlF,iBAAA,cACE,MAAA,SAAe,WAAA,WAAsB,QAAA,UAC1C,mBAAA;cACI,UAAA,EAAY,IAAA,EAAM,SAAA,EAAW,mBAAA,CAAoB,IAAA;EAI7D,GAAA,WAAc,gBAAA,EACZ,EAAA,EAAI,WAAA,CAAY,CAAA,wBACK,cAAA,CAAe,CAAA,KAAM,MAAA,SAAe,QAAA,IAAY,cAAA,CAAe,CAAA;AAAA"}
1
+ {"version":3,"file":"service_registry.d.ts","names":[],"sources":["../../src/services/service_registry.ts"],"mappings":";;;;KAWK,YAAA;AAAA,cAGC,mBAAA;EAAA,iBACa,YAAA;EAAA,iBACA,aAAA;EAAA,iBACA,SAAA;EAAA,iBACA,SAAA;EAAA,UAER,WAAA,CACP,YAAA,EAAc,YAAA,EACd,UAAA,EAAY,MAAA,SAAe,WAAA,GAC3B,SAAA,EAAW,MAAA;EAYP,OAAA,IAAW,OAAA;EAAA,UAWP,OAAA,CAAQ,SAAA,EAAW,WAAA,GAAc,MAAA,SAAe,QAAA;AAAA;AAAA,cAiB/C,oBAAA,cACE,MAAA,SAAe,WAAA,WAAsB,QAAA,UAC1C,mBAAA;cACI,UAAA,EAAY,IAAA,EAAM,SAAA,EAAW,sBAAA,CAAuB,IAAA;EAIhE,GAAA,WAAc,gBAAA,EACZ,EAAA,EAAI,WAAA,CAAY,CAAA,wBAEM,qBAAA,CAAsB,CAAA,KACtC,MAAA,SAAe,QAAA,IACf,qBAAA,CAAsB,CAAA;AAAA;AAAA,cAOnB,iBAAA,cACE,MAAA,SAAe,WAAA,WAAsB,QAAA,UAC1C,mBAAA;cACI,UAAA,EAAY,IAAA,EAAM,SAAA,EAAW,mBAAA,CAAoB,IAAA;EAI7D,GAAA,WAAc,gBAAA,EACZ,EAAA,EAAI,WAAA,CAAY,CAAA,wBAEM,kBAAA,CAAmB,CAAA,KAAM,MAAA,SAAe,QAAA,IAAY,kBAAA,CAAmB,CAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"service_registry.js","names":[],"sources":["../../src/services/service_registry.ts"],"sourcesContent":["import type {\n ServiceTypesLike,\n InferServiceModel,\n InferServiceUi,\n ServiceName,\n ModelServiceFactoryMap,\n UiServiceFactoryMap,\n} from \"./service_types\";\nimport { ServiceNotRegisteredError } from \"../errors\";\nimport type { Services } from \"./service_declarations\";\n\ntype RegistryName = \"ModelServiceRegistry\" | \"UiServiceRegistry\";\ntype ServiceFactory = () => Record<string, Function>;\n\nclass ServiceRegistryBase {\n private readonly registryName: RegistryName;\n private readonly knownServices = new Set<ServiceName>();\n private readonly factories = new Map<ServiceName, ServiceFactory>();\n private readonly instances = new Map<ServiceName, Record<string, Function>>();\n\n protected constructor(\n registryName: RegistryName,\n serviceMap: Record<string, ServiceName>,\n factories: Record<string, (() => unknown) | null>,\n ) {\n this.registryName = registryName;\n for (const [key, factory] of Object.entries(factories)) {\n const serviceId = serviceMap[key];\n this.knownServices.add(serviceId);\n if (factory !== null) {\n this.factories.set(serviceId, factory as ServiceFactory);\n }\n }\n }\n\n async dispose(): Promise<void> {\n for (const instance of this.instances.values()) {\n if (Symbol.asyncDispose in instance) {\n await (instance as AsyncDisposable)[Symbol.asyncDispose]();\n } else if (Symbol.dispose in instance) {\n (instance as Disposable)[Symbol.dispose]();\n }\n }\n this.instances.clear();\n }\n\n protected getById(serviceId: ServiceName): Record<string, Function> | null {\n if (!this.knownServices.has(serviceId)) {\n throw new ServiceNotRegisteredError(\n `Service \"${serviceId}\" is not registered in ${this.registryName}. Add it to the factory map.`,\n );\n }\n if (this.instances.has(serviceId)) return this.instances.get(serviceId)!;\n\n const factory = this.factories.get(serviceId);\n if (!factory) return null;\n\n const instance = factory();\n this.instances.set(serviceId, instance);\n return instance;\n }\n}\n\nexport class ModelServiceRegistry<\n SMap extends Record<string, ServiceName> = typeof Services,\n> extends ServiceRegistryBase {\n constructor(serviceMap: SMap, factories: ModelServiceFactoryMap<SMap>) {\n super(\"ModelServiceRegistry\", serviceMap, factories);\n }\n\n get<S extends ServiceTypesLike>(\n id: ServiceName<S>,\n ):\n | ([unknown] extends [InferServiceModel<S>] ? Record<string, Function> : InferServiceModel<S>)\n | null;\n get(id: ServiceName): Record<string, Function> | null {\n return this.getById(id);\n }\n}\n\nexport class UiServiceRegistry<\n SMap extends Record<string, ServiceName> = typeof Services,\n> extends ServiceRegistryBase {\n constructor(serviceMap: SMap, factories: UiServiceFactoryMap<SMap>) {\n super(\"UiServiceRegistry\", serviceMap, factories);\n }\n\n get<S extends ServiceTypesLike>(\n id: ServiceName<S>,\n ): ([unknown] extends [InferServiceUi<S>] ? Record<string, Function> : InferServiceUi<S>) | null;\n get(id: ServiceName): Record<string, Function> | null {\n return this.getById(id);\n }\n}\n"],"mappings":";;AAcA,IAAM,sBAAN,MAA0B;CACxB;CACA,gCAAiC,IAAI,IAAiB;CACtD,4BAA6B,IAAI,IAAiC;CAClE,4BAA6B,IAAI,IAA2C;CAE5E,YACE,cACA,YACA,WACA;EACA,KAAK,eAAe;EACpB,KAAK,MAAM,CAAC,KAAK,YAAY,OAAO,QAAQ,SAAS,GAAG;GACtD,MAAM,YAAY,WAAW;GAC7B,KAAK,cAAc,IAAI,SAAS;GAChC,IAAI,YAAY,MACd,KAAK,UAAU,IAAI,WAAW,OAAyB;EAE3D;CACF;CAEA,MAAM,UAAyB;EAC7B,KAAK,MAAM,YAAY,KAAK,UAAU,OAAO,GAC3C,IAAI,OAAO,gBAAgB,UACzB,MAAO,SAA6B,OAAO,aAAa,CAAC;OACpD,IAAI,OAAO,WAAW,UAC3B,SAAyB,OAAO,QAAQ,CAAC;EAG7C,KAAK,UAAU,MAAM;CACvB;CAEA,QAAkB,WAAyD;EACzE,IAAI,CAAC,KAAK,cAAc,IAAI,SAAS,GACnC,MAAM,IAAI,0BACR,YAAY,UAAU,yBAAyB,KAAK,aAAa,6BACnE;EAEF,IAAI,KAAK,UAAU,IAAI,SAAS,GAAG,OAAO,KAAK,UAAU,IAAI,SAAS;EAEtE,MAAM,UAAU,KAAK,UAAU,IAAI,SAAS;EAC5C,IAAI,CAAC,SAAS,OAAO;EAErB,MAAM,WAAW,QAAQ;EACzB,KAAK,UAAU,IAAI,WAAW,QAAQ;EACtC,OAAO;CACT;AACF;AAEA,IAAa,uBAAb,cAEU,oBAAoB;CAC5B,YAAY,YAAkB,WAAyC;EACrE,MAAM,wBAAwB,YAAY,SAAS;CACrD;CAOA,IAAI,IAAkD;EACpD,OAAO,KAAK,QAAQ,EAAE;CACxB;AACF;AAEA,IAAa,oBAAb,cAEU,oBAAoB;CAC5B,YAAY,YAAkB,WAAsC;EAClE,MAAM,qBAAqB,YAAY,SAAS;CAClD;CAKA,IAAI,IAAkD;EACpD,OAAO,KAAK,QAAQ,EAAE;CACxB;AACF"}
1
+ {"version":3,"file":"service_registry.js","names":[],"sources":["../../src/services/service_registry.ts"],"sourcesContent":["import type {\n ServiceTypesLike,\n InferServiceModelHost,\n InferServiceUiHost,\n ServiceName,\n ModelServiceFactoryMap,\n UiServiceFactoryMap,\n} from \"./service_types\";\nimport { ServiceNotRegisteredError } from \"../errors\";\nimport type { Services } from \"./service_declarations\";\n\ntype RegistryName = \"ModelServiceRegistry\" | \"UiServiceRegistry\";\ntype ServiceFactory = () => Record<string, Function>;\n\nclass ServiceRegistryBase {\n private readonly registryName: RegistryName;\n private readonly knownServices = new Set<ServiceName>();\n private readonly factories = new Map<ServiceName, ServiceFactory>();\n private readonly instances = new Map<ServiceName, Record<string, Function>>();\n\n protected constructor(\n registryName: RegistryName,\n serviceMap: Record<string, ServiceName>,\n factories: Record<string, (() => unknown) | null>,\n ) {\n this.registryName = registryName;\n for (const [key, factory] of Object.entries(factories)) {\n const serviceId = serviceMap[key];\n this.knownServices.add(serviceId);\n if (factory !== null) {\n this.factories.set(serviceId, factory as ServiceFactory);\n }\n }\n }\n\n async dispose(): Promise<void> {\n for (const instance of this.instances.values()) {\n if (Symbol.asyncDispose in instance) {\n await (instance as AsyncDisposable)[Symbol.asyncDispose]();\n } else if (Symbol.dispose in instance) {\n (instance as Disposable)[Symbol.dispose]();\n }\n }\n this.instances.clear();\n }\n\n protected getById(serviceId: ServiceName): Record<string, Function> | null {\n if (!this.knownServices.has(serviceId)) {\n throw new ServiceNotRegisteredError(\n `Service \"${serviceId}\" is not registered in ${this.registryName}. Add it to the factory map.`,\n );\n }\n if (this.instances.has(serviceId)) return this.instances.get(serviceId)!;\n\n const factory = this.factories.get(serviceId);\n if (!factory) return null;\n\n const instance = factory();\n this.instances.set(serviceId, instance);\n return instance;\n }\n}\n\nexport class ModelServiceRegistry<\n SMap extends Record<string, ServiceName> = typeof Services,\n> extends ServiceRegistryBase {\n constructor(serviceMap: SMap, factories: ModelServiceFactoryMap<SMap>) {\n super(\"ModelServiceRegistry\", serviceMap, factories);\n }\n\n get<S extends ServiceTypesLike>(\n id: ServiceName<S>,\n ):\n | ([unknown] extends [InferServiceModelHost<S>]\n ? Record<string, Function>\n : InferServiceModelHost<S>)\n | null;\n get(id: ServiceName): Record<string, Function> | null {\n return this.getById(id);\n }\n}\n\nexport class UiServiceRegistry<\n SMap extends Record<string, ServiceName> = typeof Services,\n> extends ServiceRegistryBase {\n constructor(serviceMap: SMap, factories: UiServiceFactoryMap<SMap>) {\n super(\"UiServiceRegistry\", serviceMap, factories);\n }\n\n get<S extends ServiceTypesLike>(\n id: ServiceName<S>,\n ):\n | ([unknown] extends [InferServiceUiHost<S>] ? Record<string, Function> : InferServiceUiHost<S>)\n | null;\n get(id: ServiceName): Record<string, Function> | null {\n return this.getById(id);\n }\n}\n"],"mappings":";;AAcA,IAAM,sBAAN,MAA0B;CACxB;CACA,gCAAiC,IAAI,IAAiB;CACtD,4BAA6B,IAAI,IAAiC;CAClE,4BAA6B,IAAI,IAA2C;CAE5E,YACE,cACA,YACA,WACA;EACA,KAAK,eAAe;EACpB,KAAK,MAAM,CAAC,KAAK,YAAY,OAAO,QAAQ,SAAS,GAAG;GACtD,MAAM,YAAY,WAAW;GAC7B,KAAK,cAAc,IAAI,SAAS;GAChC,IAAI,YAAY,MACd,KAAK,UAAU,IAAI,WAAW,OAAyB;EAE3D;CACF;CAEA,MAAM,UAAyB;EAC7B,KAAK,MAAM,YAAY,KAAK,UAAU,OAAO,GAC3C,IAAI,OAAO,gBAAgB,UACzB,MAAO,SAA6B,OAAO,aAAa,CAAC;OACpD,IAAI,OAAO,WAAW,UAC3B,SAAyB,OAAO,QAAQ,CAAC;EAG7C,KAAK,UAAU,MAAM;CACvB;CAEA,QAAkB,WAAyD;EACzE,IAAI,CAAC,KAAK,cAAc,IAAI,SAAS,GACnC,MAAM,IAAI,0BACR,YAAY,UAAU,yBAAyB,KAAK,aAAa,6BACnE;EAEF,IAAI,KAAK,UAAU,IAAI,SAAS,GAAG,OAAO,KAAK,UAAU,IAAI,SAAS;EAEtE,MAAM,UAAU,KAAK,UAAU,IAAI,SAAS;EAC5C,IAAI,CAAC,SAAS,OAAO;EAErB,MAAM,WAAW,QAAQ;EACzB,KAAK,UAAU,IAAI,WAAW,QAAQ;EACtC,OAAO;CACT;AACF;AAEA,IAAa,uBAAb,cAEU,oBAAoB;CAC5B,YAAY,YAAkB,WAAyC;EACrE,MAAM,wBAAwB,YAAY,SAAS;CACrD;CASA,IAAI,IAAkD;EACpD,OAAO,KAAK,QAAQ,EAAE;CACxB;AACF;AAEA,IAAa,oBAAb,cAEU,oBAAoB;CAC5B,YAAY,YAAkB,WAAsC;EAClE,MAAM,qBAAqB,YAAY,SAAS;CAClD;CAOA,IAAI,IAAkD;EACpD,OAAO,KAAK,QAAQ,EAAE;CACxB;AACF"}
@@ -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\" | \"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,IAAyB;CAC7C,MAAM,kCAAkB,IAAI,IAA+B;CAC3D,MAAM,+BAAe,IAAI,IAA+B;CACxD,OAAO;EACL,UAAqB;GACnB,QAKE,YAKgD;IAChD,MAAM,EAAE,MAAM,MAAM,cAAc,cAAc;IAChD,IAAI,CAAC,mBAAmB,KAAK,IAAI,GAC/B,MAAM,IAAIA,eAAAA,sBACR,uBAAuB,KAAK,gBAAgB,oBAC9C;IAEF,IAAI,QAAQ,IAAI,IAAI,GAClB,MAAM,IAAIC,eAAAA,8BAA8B,YAAY,KAAK,qBAAqB;IAEhF,QAAQ,IAAI,MAAM,IAAI;IACtB,gBAAgB,IAAI,MAAM,YAAY;IACtC,aAAa,IAAI,MAAM,SAAS;IAChC,OAAO;GACT;EACF;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,eAAe,IAA0C;GACvD,OAAO,QAAQ,IAAI,EAAE;EACvB;EACA,uBAAuB,IAAoC;GACzD,OAAO,gBAAgB,IAAI,EAAE,KAAK,CAAC;EACrC;EACA,oBAAoB,IAAoC;GACtD,OAAO,aAAa,IAAI,EAAE,KAAK,CAAC;EAClC;CACF;AACF,EAAA,CAAG;AAEH,SAAgB,aAAa,WAAmB,SAAS,IAAY;CACnE,OAAO,WAAW,UAAU,GAAG;AACjC"}
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 ModelHost = Model,\n UiHost = Ui,\n> = {\n readonly __types?: {\n model: Model;\n ui: Ui;\n kind: Kind;\n modelHost: ModelHost;\n uiHost: UiHost;\n };\n};\n\nexport type InferServiceModel<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<infer M, unknown, ServiceType, unknown, unknown> ? M : unknown;\n\nexport type InferServiceUi<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, infer U, ServiceType, unknown, unknown> ? U : unknown;\n\nexport type InferServiceKind<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, unknown, infer K, unknown, unknown> ? K : ServiceType;\n\n/**\n * Host-side shape stored in the model service registry. Differs from\n * {@link InferServiceModel} only when the registered impl carries extra\n * parameters (e.g. per-call `host` bindings) that the sandbox-view does\n * not expose. Defaults to {@link InferServiceModel}.\n */\nexport type InferServiceModelHost<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, unknown, ServiceType, infer MH, unknown> ? MH : unknown;\n\n/**\n * Host-side shape stored in the UI service registry. Differs from\n * {@link InferServiceUi} only when the registered impl carries extra\n * parameters that the UI-proxy view does not expose. Defaults to\n * {@link InferServiceUi}.\n */\nexport type InferServiceUiHost<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, unknown, ServiceType, unknown, infer UH> ? UH : unknown;\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, ModelHost = Model, UiHost = 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, ModelHost, UiHost>> => {\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, ModelHost, UiHost>>;\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]: (() => InferServiceModelHost<ServiceBrand<SMap[K]>>) | null;\n};\n\nexport type UiServiceFactoryMap<SMap extends Record<string, ServiceName>> = {\n [K in keyof SMap]: (() => InferServiceUiHost<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":";;AAoDA,MAAM,qBAAqB;AAE3B,MAAa,EACX,SACA,eACA,eACA,eACA,gBACA,wBACA,+BACS;CACT,MAAM,0BAAU,IAAI,IAAyB;CAC7C,MAAM,kCAAkB,IAAI,IAA+B;CAC3D,MAAM,+BAAe,IAAI,IAA+B;CACxD,OAAO;EACL,UAAqD;GACnD,QAKE,YAKmE;IACnE,MAAM,EAAE,MAAM,MAAM,cAAc,cAAc;IAChD,IAAI,CAAC,mBAAmB,KAAK,IAAI,GAC/B,MAAM,IAAIA,eAAAA,sBACR,uBAAuB,KAAK,gBAAgB,oBAC9C;IAEF,IAAI,QAAQ,IAAI,IAAI,GAClB,MAAM,IAAIC,eAAAA,8BAA8B,YAAY,KAAK,qBAAqB;IAEhF,QAAQ,IAAI,MAAM,IAAI;IACtB,gBAAgB,IAAI,MAAM,YAAY;IACtC,aAAa,IAAI,MAAM,SAAS;IAChC,OAAO;GACT;EACF;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,eAAe,IAA0C;GACvD,OAAO,QAAQ,IAAI,EAAE;EACvB;EACA,uBAAuB,IAAoC;GACzD,OAAO,gBAAgB,IAAI,EAAE,KAAK,CAAC;EACrC;EACA,oBAAoB,IAAoC;GACtD,OAAO,aAAa,IAAI,EAAE,KAAK,CAAC;EAClC;CACF;AACF,EAAA,CAAG;AAEH,SAAgB,aAAa,WAAmB,SAAS,IAAY;CACnE,OAAO,WAAW,UAAU,GAAG;AACjC"}
@@ -3,28 +3,44 @@ import { Services } from "./service_declarations.js";
3
3
  import { UnionToIntersection } from "@milaboratories/helpers";
4
4
 
5
5
  //#region src/services/service_types.d.ts
6
- type ServiceTypesLike<Model = unknown, Ui = unknown, Kind extends ServiceType = ServiceType> = {
6
+ type ServiceTypesLike<Model = unknown, Ui = unknown, Kind extends ServiceType = ServiceType, ModelHost = Model, UiHost = Ui> = {
7
7
  readonly __types?: {
8
8
  model: Model;
9
9
  ui: Ui;
10
10
  kind: Kind;
11
+ modelHost: ModelHost;
12
+ uiHost: UiHost;
11
13
  };
12
14
  };
13
- type InferServiceModel<S extends ServiceTypesLike> = S extends ServiceTypesLike<infer M, unknown, ServiceType> ? M : unknown;
14
- type InferServiceUi<S extends ServiceTypesLike> = S extends ServiceTypesLike<unknown, infer U, ServiceType> ? U : unknown;
15
- type InferServiceKind<S extends ServiceTypesLike> = S extends ServiceTypesLike<unknown, unknown, infer K> ? K : ServiceType;
15
+ type InferServiceModel<S extends ServiceTypesLike> = S extends ServiceTypesLike<infer M, unknown, ServiceType, unknown, unknown> ? M : unknown;
16
+ type InferServiceUi<S extends ServiceTypesLike> = S extends ServiceTypesLike<unknown, infer U, ServiceType, unknown, unknown> ? U : unknown;
17
+ type InferServiceKind<S extends ServiceTypesLike> = S extends ServiceTypesLike<unknown, unknown, infer K, unknown, unknown> ? K : ServiceType;
18
+ /**
19
+ * Host-side shape stored in the model service registry. Differs from
20
+ * {@link InferServiceModel} only when the registered impl carries extra
21
+ * parameters (e.g. per-call `host` bindings) that the sandbox-view does
22
+ * not expose. Defaults to {@link InferServiceModel}.
23
+ */
24
+ type InferServiceModelHost<S extends ServiceTypesLike> = S extends ServiceTypesLike<unknown, unknown, ServiceType, infer MH, unknown> ? MH : unknown;
25
+ /**
26
+ * Host-side shape stored in the UI service registry. Differs from
27
+ * {@link InferServiceUi} only when the registered impl carries extra
28
+ * parameters that the UI-proxy view does not expose. Defaults to
29
+ * {@link InferServiceUi}.
30
+ */
31
+ type InferServiceUiHost<S extends ServiceTypesLike> = S extends ServiceTypesLike<unknown, unknown, ServiceType, unknown, infer UH> ? UH : unknown;
16
32
  type ServiceName<S extends ServiceTypesLike = ServiceTypesLike> = Branded$1<string, S>;
17
33
  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: {
34
+ declare const service: <Model, Ui, ModelHost = Model, UiHost = Ui>() => <K extends ServiceType, N extends string, MM extends readonly (keyof Model & string)[], UM extends readonly (keyof Ui & string)[]>(options: {
19
35
  readonly type: K;
20
36
  readonly name: N;
21
37
  readonly modelMethods: MM;
22
38
  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[];
39
+ }) => Branded$1<N, ServiceTypesLike<Model, Ui, K, ModelHost, UiHost>>, 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[];
24
40
  declare function serviceFnKey(serviceId: string, method?: string): string;
25
41
  type ServiceBrand<T> = T extends Branded$1<string, infer S extends ServiceTypesLike> ? S : never;
26
- type ModelServiceFactoryMap<SMap extends Record<string, ServiceName>> = { [K in keyof SMap]: (() => InferServiceModel<ServiceBrand<SMap[K]>>) | null };
27
- type UiServiceFactoryMap<SMap extends Record<string, ServiceName>> = { [K in keyof SMap]: (() => InferServiceUi<ServiceBrand<SMap[K]>>) | null };
42
+ type ModelServiceFactoryMap<SMap extends Record<string, ServiceName>> = { [K in keyof SMap]: (() => InferServiceModelHost<ServiceBrand<SMap[K]>>) | null };
43
+ type UiServiceFactoryMap<SMap extends Record<string, ServiceName>> = { [K in keyof SMap]: (() => InferServiceUiHost<ServiceBrand<SMap[K]>>) | null };
28
44
  /** Contract between any service provider and any service consumer. */
29
45
  interface ServiceDispatch {
30
46
  getServiceNames(): ServiceName[];
@@ -43,5 +59,5 @@ type ServiceNameLiterals = { [K in keyof TServices]: ExtractServiceName<TService
43
59
  type ServiceRequireFlags = { [K in keyof TServices as `requires${K & string}`]?: boolean };
44
60
  type RequireServices<T extends ServiceName> = UnionToIntersection<T extends Branded$1<infer N extends string, infer S extends ServiceTypesLike> ? Record<N, InferServiceModel<S>> : never>;
45
61
  //#endregion
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 };
62
+ export { InferServiceKind, InferServiceModel, InferServiceModelHost, InferServiceUi, InferServiceUiHost, ModelServiceFactoryMap, ModelServices, RequireServices, ServiceBrand, ServiceDispatch, ServiceName, ServiceNameLiterals, ServiceRequireFlags, ServiceType, ServiceTypesLike, UiServiceFactoryMap, UiServices, getServiceKind, getServiceModelMethods, getServiceUiMethods, isMainService, isNodeService, isWasmService, service, serviceFnKey };
47
63
  //# 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,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,oBAtBlC,EAAA,EAsCO,WAAA,8BArCP,EAAA,EAwCO,WAAA,8BAvCP,EAAA,EA0CO,WAAA,+BAzCN,EAAA,EA4CO,WAAA,KAAc,WAAA,uCA3Cb,EAAA,EA8CO,WAAA,8CA7CV,EAAA,EAgDO,WAAA;AAAA,iBAMZ,YAAA,CAAa,SAAA,UAAmB,MAAW;AAAA,KAI/C,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,QAAQ;AAAA,KAE3B,kBAAA,MAAwB,CAAA,SAAU,SAAO,gCAAgC,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,CAAC;AAAA,KAG3B,eAAA,WAA0B,WAAA,IAAe,mBAAA,CACnD,CAAA,SAAU,SAAA,yCAAgD,gBAAA,IACtD,MAAA,CAAO,CAAA,EAAG,iBAAA,CAAkB,CAAA"}
1
+ {"version":3,"file":"service_types.d.ts","names":[],"sources":["../../src/services/service_types.ts"],"mappings":";;;;;KAKY,gBAAA,6CAGG,WAAA,GAAc,WAAA,cACf,KAAA,WACH,EAAA;EAAA,SAEA,OAAA;IACP,KAAA,EAAO,KAAA;IACP,EAAA,EAAI,EAAA;IACJ,IAAA,EAAM,IAAA;IACN,SAAA,EAAW,SAAA;IACX,MAAA,EAAQ,MAAA;EAAA;AAAA;AAAA,KAIA,iBAAA,WAA4B,gBAAA,IACtC,CAAA,SAAU,gBAAA,mBAAmC,WAAA,sBAAiC,CAAA;AAAA,KAEpE,cAAA,WAAyB,gBAAA,IACnC,CAAA,SAAU,gBAAA,mBAAmC,WAAA,sBAAiC,CAAA;AAAA,KAEpE,gBAAA,WAA2B,gBAAA,IACrC,CAAA,SAAU,gBAAA,gDAAgE,CAAA,GAAI,WAAA;;;;;;;KAQpE,qBAAA,WAAgC,gBAAA,IAC1C,CAAA,SAAU,gBAAA,mBAAmC,WAAA,uBAAkC,EAAA;;;;;;;KAQrE,kBAAA,WAA6B,gBAAA,IACvC,CAAA,SAAU,gBAAA,mBAAmC,WAAA,uBAAkC,EAAA;AAAA,KAErE,WAAA,WAAsB,gBAAA,GAAmB,gBAAA,IAAoB,SAAA,SAAgB,CAAA;AAAA,KAE7E,WAAA;AAAA,cAKV,OAAA,0BAY8B,KAAA,WAAgB,EAAA,kBAE9B,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,EAAG,SAAA,EAAW,MAAA,oBAtBhD,EAAA,EAsCO,WAAA,8BArCP,EAAA,EAwCO,WAAA,8BAvCP,EAAA,EA0CO,WAAA,+BAzCN,EAAA,EA4CO,WAAA,KAAc,WAAA,uCA3Cb,EAAA,EA8CO,WAAA,8CA7CV,EAAA,EAgDO,WAAA;AAAA,iBAMZ,YAAA,CAAa,SAAA,UAAmB,MAAW;AAAA,KAI/C,YAAA,MACV,CAAA,SAAU,SAAA,yBAAgC,gBAAA,IAAoB,CAAA;AAAA,KAEpD,sBAAA,cAAoC,MAAA,SAAe,WAAA,mBACjD,IAAA,UAAc,qBAAA,CAAsB,YAAA,CAAa,IAAA,CAAK,CAAA;AAAA,KAGxD,mBAAA,cAAiC,MAAA,SAAe,WAAA,mBAC9C,IAAA,UAAc,kBAAA,CAAmB,YAAA,CAAa,IAAA,CAAK,CAAA;;UAIhD,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,QAAQ;AAAA,KAE3B,kBAAA,MAAwB,CAAA,SAAU,SAAO,gCAAgC,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,CAAC;AAAA,KAG3B,eAAA,WAA0B,WAAA,IAAe,mBAAA,CACnD,CAAA,SAAU,SAAA,yCAAgD,gBAAA,IACtD,MAAA,CAAO,CAAA,EAAG,iBAAA,CAAkB,CAAA"}
@@ -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\" | \"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,IAAyB;CAC7C,MAAM,kCAAkB,IAAI,IAA+B;CAC3D,MAAM,+BAAe,IAAI,IAA+B;CACxD,OAAO;EACL,UAAqB;GACnB,QAKE,YAKgD;IAChD,MAAM,EAAE,MAAM,MAAM,cAAc,cAAc;IAChD,IAAI,CAAC,mBAAmB,KAAK,IAAI,GAC/B,MAAM,IAAI,sBACR,uBAAuB,KAAK,gBAAgB,oBAC9C;IAEF,IAAI,QAAQ,IAAI,IAAI,GAClB,MAAM,IAAI,8BAA8B,YAAY,KAAK,qBAAqB;IAEhF,QAAQ,IAAI,MAAM,IAAI;IACtB,gBAAgB,IAAI,MAAM,YAAY;IACtC,aAAa,IAAI,MAAM,SAAS;IAChC,OAAO;GACT;EACF;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,eAAe,IAA0C;GACvD,OAAO,QAAQ,IAAI,EAAE;EACvB;EACA,uBAAuB,IAAoC;GACzD,OAAO,gBAAgB,IAAI,EAAE,KAAK,CAAC;EACrC;EACA,oBAAoB,IAAoC;GACtD,OAAO,aAAa,IAAI,EAAE,KAAK,CAAC;EAClC;CACF;AACF,EAAA,CAAG;AAEH,SAAgB,aAAa,WAAmB,SAAS,IAAY;CACnE,OAAO,WAAW,UAAU,GAAG;AACjC"}
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 ModelHost = Model,\n UiHost = Ui,\n> = {\n readonly __types?: {\n model: Model;\n ui: Ui;\n kind: Kind;\n modelHost: ModelHost;\n uiHost: UiHost;\n };\n};\n\nexport type InferServiceModel<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<infer M, unknown, ServiceType, unknown, unknown> ? M : unknown;\n\nexport type InferServiceUi<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, infer U, ServiceType, unknown, unknown> ? U : unknown;\n\nexport type InferServiceKind<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, unknown, infer K, unknown, unknown> ? K : ServiceType;\n\n/**\n * Host-side shape stored in the model service registry. Differs from\n * {@link InferServiceModel} only when the registered impl carries extra\n * parameters (e.g. per-call `host` bindings) that the sandbox-view does\n * not expose. Defaults to {@link InferServiceModel}.\n */\nexport type InferServiceModelHost<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, unknown, ServiceType, infer MH, unknown> ? MH : unknown;\n\n/**\n * Host-side shape stored in the UI service registry. Differs from\n * {@link InferServiceUi} only when the registered impl carries extra\n * parameters that the UI-proxy view does not expose. Defaults to\n * {@link InferServiceUi}.\n */\nexport type InferServiceUiHost<S extends ServiceTypesLike> =\n S extends ServiceTypesLike<unknown, unknown, ServiceType, unknown, infer UH> ? UH : unknown;\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, ModelHost = Model, UiHost = 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, ModelHost, UiHost>> => {\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, ModelHost, UiHost>>;\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]: (() => InferServiceModelHost<ServiceBrand<SMap[K]>>) | null;\n};\n\nexport type UiServiceFactoryMap<SMap extends Record<string, ServiceName>> = {\n [K in keyof SMap]: (() => InferServiceUiHost<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":";;AAoDA,MAAM,qBAAqB;AAE3B,MAAa,EACX,SACA,eACA,eACA,eACA,gBACA,wBACA,+BACS;CACT,MAAM,0BAAU,IAAI,IAAyB;CAC7C,MAAM,kCAAkB,IAAI,IAA+B;CAC3D,MAAM,+BAAe,IAAI,IAA+B;CACxD,OAAO;EACL,UAAqD;GACnD,QAKE,YAKmE;IACnE,MAAM,EAAE,MAAM,MAAM,cAAc,cAAc;IAChD,IAAI,CAAC,mBAAmB,KAAK,IAAI,GAC/B,MAAM,IAAI,sBACR,uBAAuB,KAAK,gBAAgB,oBAC9C;IAEF,IAAI,QAAQ,IAAI,IAAI,GAClB,MAAM,IAAI,8BAA8B,YAAY,KAAK,qBAAqB;IAEhF,QAAQ,IAAI,MAAM,IAAI;IACtB,gBAAgB,IAAI,MAAM,YAAY;IACtC,aAAa,IAAI,MAAM,SAAS;IAChC,OAAO;GACT;EACF;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,cAAc,IAA0B;GACtC,OAAO,QAAQ,IAAI,EAAE,MAAM;EAC7B;EACA,eAAe,IAA0C;GACvD,OAAO,QAAQ,IAAI,EAAE;EACvB;EACA,uBAAuB,IAAoC;GACzD,OAAO,gBAAgB,IAAI,EAAE,KAAK,CAAC;EACrC;EACA,oBAAoB,IAAoC;GACtD,OAAO,aAAa,IAAI,EAAE,KAAK,CAAC;EAClC;CACF;AACF,EAAA,CAAG;AAEH,SAAgB,aAAa,WAAmB,SAAS,IAAY;CACnE,OAAO,WAAW,UAAU,GAAG;AACjC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/pl-model-common",
3
- "version": "1.46.4",
3
+ "version": "1.47.1",
4
4
  "description": "Platforma SDK Model",
5
5
  "files": [
6
6
  "./dist/**/*",
@@ -18,17 +18,18 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "canonicalize": "~2.1.0",
21
+ "es-toolkit": "^1.39.10",
21
22
  "zod": "~3.25.76",
22
- "@milaboratories/helpers": "1.14.3",
23
+ "@milaboratories/helpers": "1.14.4",
23
24
  "@milaboratories/pl-error-like": "1.12.10"
24
25
  },
25
26
  "devDependencies": {
26
27
  "@vitest/coverage-istanbul": "^4.1.3",
27
28
  "typescript": "~5.9.3",
28
29
  "vitest": "^4.1.3",
29
- "@milaboratories/ts-builder": "1.6.0",
30
30
  "@milaboratories/build-configs": "2.0.0",
31
- "@milaboratories/ts-configs": "1.3.0"
31
+ "@milaboratories/ts-configs": "1.3.0",
32
+ "@milaboratories/ts-builder": "1.6.0"
32
33
  },
33
34
  "scripts": {
34
35
  "build": "ts-builder build --target node",
@@ -0,0 +1,139 @@
1
+ import { createGlobalPObjectId, createLocalPObjectId } from "../pool";
2
+ import { ResourceTypeName } from "../resource_types";
3
+ import type { AccessorLike, LeafEntry, UpstreamBlockCtx } from "./types";
4
+
5
+ /** Resource types that hold column collections — DFS stops here and collects. */
6
+ export const COLLECT_TYPES: ReadonlyArray<string> = [ResourceTypeName.PFrame];
7
+
8
+ /** Resource types DFS descends through when looking for PFrames. */
9
+ export const DESCEND_TYPES: ReadonlyArray<string> = [
10
+ ResourceTypeName.StdMap,
11
+ ResourceTypeName.StdMapSlash,
12
+ ];
13
+
14
+ /**
15
+ * Enumerate column names backing a PFrame accessor — derived from
16
+ * `<name>.spec` field names, without resolving the spec resources.
17
+ */
18
+ export function listColumnNames<A extends AccessorLike<A>>(
19
+ accessor: A,
20
+ prefix: string = "",
21
+ ): string[] {
22
+ if (accessor.resourceType.name !== ResourceTypeName.PFrame) return [];
23
+ const out: string[] = [];
24
+ for (const field of accessor.listInputFields()) {
25
+ if (!field.endsWith(".spec")) continue;
26
+ const raw = field.slice(0, -".spec".length);
27
+ if (!raw.startsWith(prefix)) continue;
28
+ out.push(raw.slice(prefix.length));
29
+ }
30
+ return out;
31
+ }
32
+
33
+ /**
34
+ * One DFS hit — the accessor whose resource-type matched `collectTypes`, and
35
+ * the field-name path from the DFS root used to reach it.
36
+ */
37
+ type DescendantHit<A extends AccessorLike<A>> = {
38
+ readonly node: A;
39
+ readonly path: ReadonlyArray<string>;
40
+ };
41
+
42
+ /**
43
+ * DFS over the input-field subtree of `root`. Collects nodes whose resource
44
+ * type ∈ `collectTypes`. Descends only through `descendTypes`
45
+ * (default: StdMap / StdMapSlash). Collected nodes are not descended into.
46
+ *
47
+ * Threads the field-name path from `rootPath` to each hit, so callers can
48
+ * build canonical {@link createLocalPObjectId}s without relying on the
49
+ * accessor itself to remember its path.
50
+ *
51
+ * Includes `root` itself in the walk.
52
+ */
53
+ export function findDescendantsByType<A extends AccessorLike<A>>(opts: {
54
+ root: A;
55
+ rootPath: ReadonlyArray<string>;
56
+ collectTypes: ReadonlyArray<string>;
57
+ descendTypes?: ReadonlyArray<string>;
58
+ }): DescendantHit<A>[] {
59
+ const { root, rootPath, collectTypes, descendTypes = DESCEND_TYPES } = opts;
60
+ const collectSet = new Set(collectTypes);
61
+ const descendSet = new Set(descendTypes);
62
+ const result: DescendantHit<A>[] = [];
63
+
64
+ const stack: DescendantHit<A>[] = [{ node: root, path: rootPath }];
65
+ while (stack.length > 0) {
66
+ const { node, path } = stack.pop()!;
67
+ const typeName = node.resourceType.name;
68
+ if (collectSet.has(typeName)) {
69
+ result.push({ node, path });
70
+ continue;
71
+ }
72
+ if (!descendSet.has(typeName)) continue;
73
+ const fields = node.listInputFields();
74
+ for (let i = fields.length - 1; i >= 0; i--) {
75
+ const child = node.traverse({
76
+ field: fields[i],
77
+ assertFieldType: "Input",
78
+ ignoreError: true,
79
+ });
80
+ if (child !== undefined) stack.push({ node: child, path: [...path, fields[i]] });
81
+ }
82
+ }
83
+ return result;
84
+ }
85
+
86
+ /**
87
+ * Walk an accessor root and return one {@link LeafEntry} per discovered column.
88
+ * Ids are {@link createLocalPObjectId}-shaped: `{resolvePath, name}`. The
89
+ * `resolvePath` is derived from `rootPath` extended by the DFS traversal.
90
+ */
91
+ export function indexAccessorRoot<A extends AccessorLike<A>>(
92
+ root: A,
93
+ rootPath: ReadonlyArray<string>,
94
+ ): LeafEntry<A>[] {
95
+ const result: LeafEntry<A>[] = [];
96
+ for (const { node, path } of findDescendantsByType({
97
+ root,
98
+ rootPath,
99
+ collectTypes: COLLECT_TYPES,
100
+ descendTypes: DESCEND_TYPES,
101
+ })) {
102
+ for (const name of listColumnNames(node)) {
103
+ result.push({
104
+ accessor: node,
105
+ name,
106
+ id: createLocalPObjectId([...path], name),
107
+ });
108
+ }
109
+ }
110
+ return result;
111
+ }
112
+
113
+ /**
114
+ * Walk one upstream-block ctx pair (`prodCtx` then `stagingCtx`) and return one
115
+ * {@link LeafEntry} per column. First-wins dedup by name (prod precedes staging).
116
+ * Ids are {@link createGlobalPObjectId}-shaped — `resolvePath` is not involved.
117
+ */
118
+ export function indexPoolBlock<A extends AccessorLike<A>>(
119
+ block: UpstreamBlockCtx<A>,
120
+ ): LeafEntry<A>[] {
121
+ const accessors: A[] = [];
122
+ if (block.prodCtx) accessors.push(block.prodCtx);
123
+ if (block.stagingCtx) accessors.push(block.stagingCtx);
124
+
125
+ const result: LeafEntry<A>[] = [];
126
+ const seen = new Set<string>();
127
+ for (const accessor of accessors) {
128
+ for (const name of listColumnNames(accessor)) {
129
+ if (seen.has(name)) continue;
130
+ seen.add(name);
131
+ result.push({
132
+ accessor,
133
+ name,
134
+ id: createGlobalPObjectId(block.blockId, name),
135
+ });
136
+ }
137
+ }
138
+ return result;
139
+ }
@@ -0,0 +1,41 @@
1
+ import type { PObjectId } from "../pool";
2
+ import type { AccessorLike, ColumnEntriesProvider, LeafEntry } from "./types";
3
+
4
+ /**
5
+ * Id-index over a set of {@link ColumnEntriesProvider}s. Sole job:
6
+ * {@link PObjectId} → {@link LeafEntry}. Generic over the accessor flavour, so
7
+ * the same class backs both sandbox (`TreeNodeAccessor`) and host
8
+ * (`PlTreeNodeAccessor`) usage.
9
+ *
10
+ * Stateless beyond the provider list — every lookup goes through each
11
+ * provider's `getPObjectEntries()` (cached inside the provider). Instantiate
12
+ * directly at the call site that has the providers; there is no ambient
13
+ * singleton.
14
+ */
15
+ export class ColumnRegistry<A extends AccessorLike<A>> {
16
+ constructor(private readonly providers: ReadonlyArray<ColumnEntriesProvider<A>>) {}
17
+
18
+ /**
19
+ * Resolve a {@link PObjectId} to its backing {@link LeafEntry}. Returns
20
+ * `undefined` if the column is not reachable from any provider — caller
21
+ * decides whether that's `absent` or `resolving` via {@link isFinal}.
22
+ */
23
+ resolve(id: PObjectId): LeafEntry<A> | undefined {
24
+ return this.lookupById(id);
25
+ }
26
+
27
+ /** Whether every indexed source has finished enumerating its columns. */
28
+ isFinal(): boolean {
29
+ return this.providers.every((p) => p.isFinal());
30
+ }
31
+
32
+ private lookupById(id: PObjectId): LeafEntry<A> | undefined {
33
+ // First-wins across providers — caller controls precedence via the
34
+ // construction order of `providers`.
35
+ for (const p of this.providers) {
36
+ const hit = p.getPObjectEntries().get(id);
37
+ if (hit !== undefined) return hit;
38
+ }
39
+ return undefined;
40
+ }
41
+ }
@@ -0,0 +1,100 @@
1
+ import type {
2
+ AxisValueType,
3
+ ColumnValueType,
4
+ MultiAxisSelector,
5
+ MultiColumnSelector,
6
+ StringMatcher,
7
+ } from "../drivers/pframe";
8
+
9
+ export type { StringMatcher } from "../drivers/pframe";
10
+
11
+ // --- Relaxed types ---
12
+
13
+ /** Relaxed string matcher input: plain string, single matcher, or array of mixed. */
14
+ export type RelaxedStringMatchers = string | StringMatcher | (string | StringMatcher)[];
15
+
16
+ /** Relaxed record matcher: values can be plain strings or relaxed matchers. */
17
+ export type RelaxedRecord = Record<string, RelaxedStringMatchers>;
18
+
19
+ /** Relaxed axis selector — accepts plain strings where strict requires StringMatcher[]. */
20
+ export interface RelaxedAxisSelector {
21
+ name?: RelaxedStringMatchers;
22
+ type?: AxisValueType | AxisValueType[];
23
+ domain?: RelaxedRecord;
24
+ contextDomain?: RelaxedRecord;
25
+ annotations?: RelaxedRecord;
26
+ }
27
+
28
+ /** Relaxed column selector — convenient hand-written form. */
29
+ export interface RelaxedColumnSelector {
30
+ name?: RelaxedStringMatchers;
31
+ type?: ColumnValueType | ColumnValueType[];
32
+ domain?: RelaxedRecord;
33
+ contextDomain?: RelaxedRecord;
34
+ annotations?: RelaxedRecord;
35
+ axes?: RelaxedAxisSelector[];
36
+ partialAxesMatch?: boolean;
37
+ }
38
+
39
+ /** One or many relaxed column selectors; normalizes to MultiColumnSelector[]. */
40
+ export type ColumnSelector = RelaxedColumnSelector | RelaxedColumnSelector[];
41
+
42
+ // --- Normalization ---
43
+
44
+ function normalizeStringMatchers(input: RelaxedStringMatchers): StringMatcher[] {
45
+ if (typeof input === "string") return [{ type: "regex", value: input }];
46
+ if (!Array.isArray(input)) return [input];
47
+ return input.map((v) =>
48
+ typeof v === "string" ? ({ type: "regex", value: v } satisfies StringMatcher) : v,
49
+ );
50
+ }
51
+
52
+ function normalizeRecord(input: RelaxedRecord): Record<string, StringMatcher[]> {
53
+ const result: Record<string, StringMatcher[]> = {};
54
+ for (const [key, value] of Object.entries(input)) {
55
+ result[key] = normalizeStringMatchers(value);
56
+ }
57
+ return result;
58
+ }
59
+
60
+ function normalizeTypes<T>(input: T | T[]): T[] {
61
+ return Array.isArray(input) ? input : [input];
62
+ }
63
+
64
+ type Mutable<T> = { -readonly [K in keyof T]: T[K] };
65
+
66
+ export function convertRelaxedAxisSelectorToMultiAxisSelector(
67
+ input: RelaxedAxisSelector,
68
+ ): MultiAxisSelector {
69
+ const result: Mutable<MultiAxisSelector> = {};
70
+ if (input.name !== undefined) result.name = normalizeStringMatchers(input.name);
71
+ if (input.type !== undefined) result.type = normalizeTypes(input.type);
72
+ if (input.domain !== undefined) result.domain = normalizeRecord(input.domain);
73
+ if (input.contextDomain !== undefined)
74
+ result.contextDomain = normalizeRecord(input.contextDomain);
75
+ if (input.annotations !== undefined) result.annotations = normalizeRecord(input.annotations);
76
+ return result;
77
+ }
78
+
79
+ export function convertRelaxedColumnSelectorToMultiColumnSelector(
80
+ input: RelaxedColumnSelector,
81
+ ): MultiColumnSelector {
82
+ const result: Mutable<MultiColumnSelector> = {};
83
+ if (input.name !== undefined) result.name = normalizeStringMatchers(input.name);
84
+ if (input.type !== undefined) result.type = normalizeTypes(input.type);
85
+ if (input.domain !== undefined) result.domain = normalizeRecord(input.domain);
86
+ if (input.contextDomain !== undefined)
87
+ result.contextDomain = normalizeRecord(input.contextDomain);
88
+ if (input.annotations !== undefined) result.annotations = normalizeRecord(input.annotations);
89
+ if (input.axes !== undefined)
90
+ result.axes = input.axes.map(convertRelaxedAxisSelectorToMultiAxisSelector);
91
+ if (input.partialAxesMatch !== undefined) result.partialAxesMatch = input.partialAxesMatch;
92
+ return result;
93
+ }
94
+
95
+ export function convertColumnSelectorToMultiColumnSelector(
96
+ input: ColumnSelector,
97
+ ): MultiColumnSelector[] {
98
+ const arr = Array.isArray(input) ? input : [input];
99
+ return arr.map(convertRelaxedColumnSelectorToMultiColumnSelector);
100
+ }
@@ -0,0 +1,49 @@
1
+ import type { PColumnSpec } from "../drivers/pframe/spec/spec";
2
+ import type { NativePObjectId } from "../drivers/pframe/spec/native_id";
3
+ import { deriveNativeId } from "../drivers/pframe/spec/native_id";
4
+ import type { ColumnUniversalId } from "../drivers/pframe/spec/ids";
5
+ import { isPObjectId } from "../pool";
6
+
7
+ /**
8
+ * Two-track dedup over an item stream keyed by `ColumnUniversalId`:
9
+ *
10
+ * - **Raw `PObjectId`s** are deduped by `deriveNativeId(spec)`. The same
11
+ * physical column reached via outputs vs. result_pool has different
12
+ * id shapes but identical nativeId — first occurrence wins so the
13
+ * provider order (outputs before pool) decides which id is canonical.
14
+ * - **Non-`PObjectId` ids** (e.g. `SUniversalPColumnUniversalId`,
15
+ * `ColumnDiscoveredId`) keep raw-id dedup — they legitimately share
16
+ * nativeId with siblings.
17
+ *
18
+ * When `getSpec` returns `undefined` for a `PObjectId`, falls back to raw-id
19
+ * dedup (so an unresolvable id still survives instead of dropping silently).
20
+ *
21
+ * Shared by sandbox-side `extractColumns` (column_providers) and host-side
22
+ * `ColumnsCollectionDriverImpl.getColumns` — both layers need identical
23
+ * dedup semantics, but operate on different concrete item types (ColumnLazy
24
+ * vs. raw ColumnUniversalId).
25
+ */
26
+ export function dedupColumns<T>(
27
+ items: ReadonlyArray<T>,
28
+ getId: (item: T) => ColumnUniversalId,
29
+ getSpec: (item: T) => PColumnSpec | undefined,
30
+ ): T[] {
31
+ const seenNative = new Set<NativePObjectId>();
32
+ const seenId = new Set<ColumnUniversalId>();
33
+ const out: T[] = [];
34
+ for (const item of items) {
35
+ const id = getId(item);
36
+ if (seenId.has(id)) continue;
37
+ if (isPObjectId(id)) {
38
+ const spec = getSpec(item);
39
+ if (spec !== undefined) {
40
+ const nativeId = deriveNativeId(spec);
41
+ if (seenNative.has(nativeId)) continue;
42
+ seenNative.add(nativeId);
43
+ }
44
+ }
45
+ seenId.add(id);
46
+ out.push(item);
47
+ }
48
+ return out;
49
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./types";
2
+ export * from "./accessor_traversal";
3
+ export * from "./column_registry";
4
+ export * from "./column_selector";
5
+ export * from "./dedup";
6
+ export * from "./providers";
@@ -0,0 +1,74 @@
1
+ import type { PObjectId } from "../pool";
2
+ import { indexAccessorRoot, indexPoolBlock } from "./accessor_traversal";
3
+ import type { AccessorLike, ColumnEntriesProvider, LeafEntry, UpstreamBlockCtx } from "./types";
4
+
5
+ /**
6
+ * Generic entries provider over a single accessor root. Walks `<root>` once
7
+ * from the supplied `rootPath`, builds an id → {@link LeafEntry} map and
8
+ * exposes `isFinal()` via the root's `getInputsLocked()`.
9
+ *
10
+ * Used directly on the host side; sandbox extends it with `getColumns()`
11
+ * returning {@link ColumnLazy}s — see `AccessorColumnsProvider` in
12
+ * `@platforma-sdk/model`.
13
+ */
14
+ export class AccessorEntriesProvider<
15
+ A extends AccessorLike<A>,
16
+ > implements ColumnEntriesProvider<A> {
17
+ protected readonly entries: ReadonlyMap<PObjectId, LeafEntry<A>>;
18
+
19
+ constructor(
20
+ protected readonly root: A,
21
+ rootPath: ReadonlyArray<string>,
22
+ ) {
23
+ const map = new Map<PObjectId, LeafEntry<A>>();
24
+ for (const entry of indexAccessorRoot(root, rootPath)) {
25
+ if (!map.has(entry.id)) map.set(entry.id, entry);
26
+ }
27
+ this.entries = map;
28
+ }
29
+
30
+ getPObjectEntries(): ReadonlyMap<PObjectId, LeafEntry<A>> {
31
+ return this.entries;
32
+ }
33
+
34
+ isFinal(): boolean {
35
+ return this.root.getInputsLocked();
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Generic entries provider over a list of upstream-block ctx pairs.
41
+ *
42
+ * Per-block merge: iterate `prod` then `staging`, dedupe by name with
43
+ * first-wins semantics (prod takes precedence).
44
+ *
45
+ * `isFinal()` is the AND of `getInputsLocked()` over every present ctx
46
+ * accessor and `!prodIncomplete && !stagingIncomplete` over every block.
47
+ */
48
+ export class ResultPoolEntriesProvider<
49
+ A extends AccessorLike<A>,
50
+ > implements ColumnEntriesProvider<A> {
51
+ protected cachedEntries?: ReadonlyMap<PObjectId, LeafEntry<A>>;
52
+
53
+ constructor(protected readonly blocks: ReadonlyArray<UpstreamBlockCtx<A>>) {}
54
+
55
+ getPObjectEntries(): ReadonlyMap<PObjectId, LeafEntry<A>> {
56
+ if (this.cachedEntries !== undefined) return this.cachedEntries;
57
+ const map = new Map<PObjectId, LeafEntry<A>>();
58
+ for (const block of this.blocks) {
59
+ for (const entry of indexPoolBlock(block)) {
60
+ if (!map.has(entry.id)) map.set(entry.id, entry);
61
+ }
62
+ }
63
+ return (this.cachedEntries = map);
64
+ }
65
+
66
+ isFinal(): boolean {
67
+ for (const block of this.blocks) {
68
+ if (block.prodIncomplete || block.stagingIncomplete) return false;
69
+ if (block.prodCtx && !block.prodCtx.getInputsLocked()) return false;
70
+ if (block.stagingCtx && !block.stagingCtx.getInputsLocked()) return false;
71
+ }
72
+ return true;
73
+ }
74
+ }