@platforma-sdk/model 1.61.1 → 1.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/block_model.cjs +17 -10
  2. package/dist/block_model.cjs.map +1 -1
  3. package/dist/block_model.d.ts +22 -5
  4. package/dist/block_model.js +16 -10
  5. package/dist/block_model.js.map +1 -1
  6. package/dist/columns/column_collection_builder.cjs +26 -14
  7. package/dist/columns/column_collection_builder.cjs.map +1 -1
  8. package/dist/columns/column_collection_builder.d.ts +9 -8
  9. package/dist/columns/column_collection_builder.js +26 -14
  10. package/dist/columns/column_collection_builder.js.map +1 -1
  11. package/dist/columns/ctx_column_sources.cjs.map +1 -1
  12. package/dist/columns/ctx_column_sources.d.ts +1 -1
  13. package/dist/columns/ctx_column_sources.js.map +1 -1
  14. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +93 -89
  15. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
  16. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +2 -2
  17. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +93 -89
  18. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
  19. package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
  20. package/dist/components/PlDataTable/createPlDataTable/index.d.ts +2 -1
  21. package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
  22. package/dist/components/PlMultiSequenceAlignment.cjs +1 -1
  23. package/dist/components/PlMultiSequenceAlignment.cjs.map +1 -1
  24. package/dist/components/PlMultiSequenceAlignment.js +2 -2
  25. package/dist/components/PlMultiSequenceAlignment.js.map +1 -1
  26. package/dist/components/PlSelectionModel.cjs.map +1 -1
  27. package/dist/components/PlSelectionModel.d.ts +1 -1
  28. package/dist/components/PlSelectionModel.js.map +1 -1
  29. package/dist/index.cjs +7 -0
  30. package/dist/index.d.ts +6 -2
  31. package/dist/index.js +4 -1
  32. package/dist/package.cjs +1 -1
  33. package/dist/package.js +1 -1
  34. package/dist/pframe_utils/index.cjs +2 -5
  35. package/dist/pframe_utils/index.cjs.map +1 -1
  36. package/dist/pframe_utils/index.js +2 -5
  37. package/dist/pframe_utils/index.js.map +1 -1
  38. package/dist/platforma.d.ts +8 -4
  39. package/dist/plugin_handle.cjs.map +1 -1
  40. package/dist/plugin_handle.d.ts +13 -7
  41. package/dist/plugin_handle.js.map +1 -1
  42. package/dist/plugin_model.cjs +37 -11
  43. package/dist/plugin_model.cjs.map +1 -1
  44. package/dist/plugin_model.d.ts +80 -39
  45. package/dist/plugin_model.js +37 -11
  46. package/dist/plugin_model.js.map +1 -1
  47. package/dist/render/api.cjs +13 -24
  48. package/dist/render/api.cjs.map +1 -1
  49. package/dist/render/api.d.ts +11 -14
  50. package/dist/render/api.js +13 -24
  51. package/dist/render/api.js.map +1 -1
  52. package/dist/render/internal.cjs.map +1 -1
  53. package/dist/render/internal.d.ts +3 -14
  54. package/dist/render/internal.js.map +1 -1
  55. package/dist/services/block_services.cjs +18 -0
  56. package/dist/services/block_services.cjs.map +1 -0
  57. package/dist/services/block_services.d.ts +18 -0
  58. package/dist/services/block_services.js +16 -0
  59. package/dist/services/block_services.js.map +1 -0
  60. package/dist/services/index.cjs +2 -0
  61. package/dist/services/index.d.ts +3 -0
  62. package/dist/services/index.js +2 -0
  63. package/dist/services/service_bridge.cjs +35 -0
  64. package/dist/services/service_bridge.cjs.map +1 -0
  65. package/dist/services/service_bridge.d.ts +18 -0
  66. package/dist/services/service_bridge.js +33 -0
  67. package/dist/services/service_bridge.js.map +1 -0
  68. package/dist/services/service_resolve.d.ts +13 -0
  69. package/package.json +9 -9
  70. package/src/block_model.ts +47 -14
  71. package/src/columns/column_collection_builder.test.ts +23 -2
  72. package/src/columns/column_collection_builder.ts +38 -30
  73. package/src/columns/ctx_column_sources.ts +2 -2
  74. package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +159 -153
  75. package/src/components/PlDataTable/createPlDataTable/index.ts +5 -4
  76. package/src/components/PlMultiSequenceAlignment.ts +1 -2
  77. package/src/components/PlSelectionModel.ts +1 -1
  78. package/src/index.ts +1 -0
  79. package/src/pframe_utils/index.ts +2 -6
  80. package/src/platforma.ts +14 -2
  81. package/src/plugin_handle.ts +24 -6
  82. package/src/plugin_model.ts +252 -84
  83. package/src/render/api.ts +50 -51
  84. package/src/render/internal.ts +3 -38
  85. package/src/services/block_services.ts +17 -0
  86. package/src/services/index.ts +3 -0
  87. package/src/services/service_bridge.ts +71 -0
  88. package/src/services/service_resolve.ts +71 -0
package/src/render/api.ts CHANGED
@@ -1,12 +1,8 @@
1
1
  import type {
2
2
  AnchoredPColumnSelector,
3
3
  AnyFunction,
4
- AxesId,
5
- AxesSpec,
6
4
  AxisId,
7
5
  DataInfo,
8
- DiscoverColumnsRequest,
9
- DiscoverColumnsResponse,
10
6
  Option,
11
7
  PColumn,
12
8
  PColumnLazy,
@@ -19,8 +15,6 @@ import type {
19
15
  PObjectId,
20
16
  PObjectSpec,
21
17
  PSpecPredicate,
22
- PTableColumnId,
23
- PTableColumnSpec,
24
18
  PTableDef,
25
19
  PTableDefV2,
26
20
  PTableHandle,
@@ -29,7 +23,7 @@ import type {
29
23
  PlRef,
30
24
  ResolveAnchorsOptions,
31
25
  ResultCollection,
32
- SingleAxisSelector,
26
+ ServiceName,
33
27
  SUniversalPColumnId,
34
28
  ValueOrError,
35
29
  } from "@milaboratories/pl-model-common";
@@ -61,8 +55,11 @@ import type {
61
55
  PluginHandle,
62
56
  PluginFactoryLike,
63
57
  InferFactoryData,
58
+ InferFactoryModelServices,
64
59
  InferFactoryParams,
65
60
  } from "../plugin_handle";
61
+ import type { BlockDefaultModelServices } from "../services/service_resolve";
62
+ import type { ModelServices as AllModelServices } from "@milaboratories/pl-model-common";
66
63
  import { TreeNodeAccessor, ifDef } from "./accessor";
67
64
  import type { FutureRef } from "./future";
68
65
  import type { AccessorHandle, GlobalCfgRenderCtx } from "./internal";
@@ -557,11 +554,40 @@ export class ResultPool implements ColumnProvider, AxisLabelProvider {
557
554
  }
558
555
 
559
556
  /** Main entry point to the API available within model lambdas (like outputs, sections, etc..) */
560
- export abstract class RenderCtxBase<Args = unknown, Data = unknown> {
557
+ export abstract class RenderCtxBase<
558
+ Args = unknown,
559
+ Data = unknown,
560
+ ModelServices = Partial<AllModelServices>,
561
+ > {
561
562
  protected readonly ctx: GlobalCfgRenderCtx;
563
+ private readonly requiredServiceNames: ServiceName[];
564
+ private cachedServices?: ModelServices;
562
565
 
563
- constructor() {
566
+ constructor(requiredServiceNames: ServiceName[] = []) {
564
567
  this.ctx = getCfgRenderCtx();
568
+ this.requiredServiceNames = requiredServiceNames;
569
+ }
570
+
571
+ get services(): ModelServices {
572
+ if (this.cachedServices) return this.cachedServices;
573
+ const ctx = this.ctx;
574
+ const services = Object.freeze(
575
+ Object.fromEntries(
576
+ this.requiredServiceNames.map((id) => [
577
+ id,
578
+ Object.freeze(
579
+ Object.fromEntries(
580
+ (ctx.getServiceMethods(id) as string[]).map((method) => [
581
+ method,
582
+ (...args: unknown[]) => ctx.callServiceMethod(id, method, ...args),
583
+ ]),
584
+ ),
585
+ ),
586
+ ]),
587
+ ),
588
+ ) as ModelServices;
589
+ this.cachedServices = services;
590
+ return services;
565
591
  }
566
592
 
567
593
  private dataCache?: { v: Data };
@@ -717,41 +743,6 @@ export abstract class RenderCtxBase<Args = unknown, Data = unknown> {
717
743
  return this.ctx.getBlockLabel(blockId);
718
744
  }
719
745
 
720
- //
721
- // Spec Frames
722
- //
723
-
724
- public createSpecFrame(specs: Record<string, PColumnSpec>): string {
725
- return this.ctx.createSpecFrame(specs);
726
- }
727
-
728
- public specFrameDiscoverColumns(
729
- handle: string,
730
- request: DiscoverColumnsRequest,
731
- ): DiscoverColumnsResponse {
732
- return this.ctx.specFrameDiscoverColumns(handle, request);
733
- }
734
-
735
- public disposeSpecFrame(handle: string): void {
736
- this.ctx.disposeSpecFrame(handle);
737
- }
738
-
739
- public expandAxes(spec: AxesSpec): AxesId {
740
- return this.ctx.expandAxes(spec);
741
- }
742
-
743
- public collapseAxes(ids: AxesId): AxesSpec {
744
- return this.ctx.collapseAxes(ids);
745
- }
746
-
747
- public findAxis(spec: AxesSpec, selector: SingleAxisSelector): number {
748
- return this.ctx.findAxis(spec, selector);
749
- }
750
-
751
- public findTableColumn(tableSpec: PTableColumnSpec[], selector: PTableColumnId): number {
752
- return this.ctx.findTableColumn(tableSpec, selector);
753
- }
754
-
755
746
  public getCurrentUnstableMarker(): string | undefined {
756
747
  return this.ctx.getCurrentUnstableMarker();
757
748
  }
@@ -770,7 +761,11 @@ export abstract class RenderCtxBase<Args = unknown, Data = unknown> {
770
761
  }
771
762
 
772
763
  /** Main entry point to the API available within model lambdas (like outputs, sections, etc..) for v3+ blocks */
773
- export class BlockRenderCtx<Args = unknown, Data = unknown> extends RenderCtxBase<Args, Data> {
764
+ export class BlockRenderCtx<
765
+ Args = unknown,
766
+ Data = unknown,
767
+ ModelServices = BlockDefaultModelServices,
768
+ > extends RenderCtxBase<Args, Data, ModelServices> {
774
769
  private argsCache?: { v: Args | undefined };
775
770
  public get args(): Args | undefined {
776
771
  if (this.argsCache === undefined) {
@@ -819,15 +814,19 @@ export class RenderCtxLegacy<Args = unknown, UiState = unknown> extends RenderCt
819
814
  *
820
815
  * @typeParam F - PluginFactoryLike phantom carrying data/params/outputs types
821
816
  */
822
- export class PluginRenderCtx<F extends PluginFactoryLike = PluginFactoryLike> extends RenderCtxBase<
823
- unknown,
824
- InferFactoryData<F>
825
- > {
817
+ export class PluginRenderCtx<
818
+ F extends PluginFactoryLike = PluginFactoryLike,
819
+ ModelServices = InferFactoryModelServices<F>,
820
+ > extends RenderCtxBase<unknown, InferFactoryData<F>, ModelServices> {
826
821
  private readonly handle: PluginHandle<F>;
827
822
  private readonly wrappedInputs: Record<string, () => unknown>;
828
823
 
829
- constructor(handle: PluginHandle<F>, wrappedInputs: Record<string, () => unknown>) {
830
- super();
824
+ constructor(
825
+ handle: PluginHandle<F>,
826
+ wrappedInputs: Record<string, () => unknown>,
827
+ requiredServiceNames: ServiceName[] = [],
828
+ ) {
829
+ super(requiredServiceNames);
831
830
  this.handle = handle;
832
831
  this.wrappedInputs = wrappedInputs;
833
832
  }
@@ -1,15 +1,5 @@
1
1
  import type { Optional } from "utility-types";
2
- import type {
3
- AxesId,
4
- AxesSpec,
5
- Branded,
6
- DiscoverColumnsRequest,
7
- DiscoverColumnsResponse,
8
- PTableColumnId,
9
- PTableColumnSpec,
10
- SingleAxisSelector,
11
- StringifiedJson,
12
- } from "@milaboratories/pl-model-common";
2
+ import type { Branded, StringifiedJson } from "@milaboratories/pl-model-common";
13
3
  import type { CommonFieldTraverseOps, FieldTraversalStep, ResourceType } from "./traversal_ops";
14
4
  import type {
15
5
  ArchiveFormat,
@@ -29,9 +19,9 @@ import type {
29
19
  ValueOrError,
30
20
  DataInfo,
31
21
  RangeBytes,
32
- PColumnSpec,
33
22
  } from "@milaboratories/pl-model-common";
34
23
  import type { TreeNodeAccessor } from "./accessor";
24
+ import type { ServiceDispatch } from "@milaboratories/pl-model-common";
35
25
 
36
26
  export const StagingAccessorName = "staging";
37
27
  export const MainAccessorName = "main";
@@ -168,31 +158,6 @@ export interface GlobalCfgRenderCtxMethods<AHandle = AccessorHandle, FHandle = F
168
158
  def: PTableDefV2<PColumn<AHandle | PColumnValues | DataInfo<AHandle>>>,
169
159
  ): PTableHandle;
170
160
 
171
- //
172
- // Spec Frames (synchronous WASM-based PFrame for spec-level operations)
173
- //
174
-
175
- createSpecFrame(specs: Record<string, PColumnSpec>): string;
176
-
177
- specFrameDiscoverColumns(
178
- handle: string,
179
- request: DiscoverColumnsRequest,
180
- ): DiscoverColumnsResponse;
181
-
182
- disposeSpecFrame(handle: string): void;
183
-
184
- /** Expand index-based parentAxes in AxesSpec to resolved AxisId parents in AxesId. */
185
- expandAxes(spec: AxesSpec): AxesId;
186
-
187
- /** Collapse resolved AxisId parents back to index-based parentAxes in AxesSpec. */
188
- collapseAxes(ids: AxesId): AxesSpec;
189
-
190
- /** Find the index of an axis matching the given selector. Returns -1 if not found. */
191
- findAxis(spec: AxesSpec, selector: SingleAxisSelector): number;
192
-
193
- /** Find the flat index of a table column matching the given selector. Returns -1 if not found. */
194
- findTableColumn(tableSpec: PTableColumnSpec[], selector: PTableColumnId): number;
195
-
196
161
  //
197
162
  // Computable
198
163
  //
@@ -218,7 +183,7 @@ export const GlobalCfgRenderCtxFeatureFlags = {
218
183
  pFrameInSetFilterSupport: true as const,
219
184
  };
220
185
 
221
- export interface GlobalCfgRenderCtx extends GlobalCfgRenderCtxMethods {
186
+ export interface GlobalCfgRenderCtx extends GlobalCfgRenderCtxMethods, ServiceDispatch {
222
187
  //
223
188
  // State: Args, UI State, Active Args
224
189
  //
@@ -0,0 +1,17 @@
1
+ import type { ServiceRequireFlags } from "@milaboratories/pl-model-common";
2
+ import { resolveRequiredServices } from "@milaboratories/pl-model-common";
3
+
4
+ /**
5
+ * Services required by all V3 blocks by default.
6
+ * Edit this when a new service should be available to all blocks.
7
+ *
8
+ * Standalone module to avoid circular dependencies between block_model.ts
9
+ * and service type resolution.
10
+ */
11
+ export const BLOCK_SERVICE_FLAGS = {
12
+ requiresPFrameSpec: true,
13
+ } as const satisfies Partial<ServiceRequireFlags>;
14
+
15
+ export type BlockServiceFlags = typeof BLOCK_SERVICE_FLAGS;
16
+
17
+ export const blockServiceNames = resolveRequiredServices(BLOCK_SERVICE_FLAGS);
@@ -0,0 +1,3 @@
1
+ export * from "./block_services";
2
+ export * from "./service_resolve";
3
+ export * from "./service_bridge";
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Runtime service bridge — builds lazy service objects from dispatch + registry.
3
+ * Used by the UI layer to provide typed service access.
4
+ */
5
+
6
+ import type {
7
+ ServiceTypesLike,
8
+ InferServiceUi,
9
+ ServiceName,
10
+ ServiceDispatch,
11
+ UiServices as AllUiServices,
12
+ } from "@milaboratories/pl-model-common";
13
+ import { UiServiceRegistry } from "@milaboratories/pl-model-common";
14
+
15
+ // Makes a remote node service appear local.
16
+ // Given a service ID, returns an object implementing the service's UI interface.
17
+ // Provided by the desktop app (e.g. backed by Electron IPC).
18
+ export type NodeServiceProxy = <S extends ServiceTypesLike>(
19
+ serviceId: ServiceName<S>,
20
+ ) => InferServiceUi<S>;
21
+
22
+ /**
23
+ * Builds a lazy services object from ServiceDispatch and UiServiceRegistry.
24
+ * Each service is instantiated on first access. Errors are cached to prevent
25
+ * repeated factory calls on failure.
26
+ */
27
+ export function buildServices<S extends Partial<AllUiServices> = Partial<AllUiServices>>(
28
+ dispatch: ServiceDispatch,
29
+ registry: UiServiceRegistry,
30
+ ): S {
31
+ return Object.create(
32
+ null,
33
+ Object.fromEntries(
34
+ dispatch.getServiceNames().map((id) => {
35
+ let fetched = false;
36
+ let cached: unknown;
37
+ return [
38
+ id,
39
+ {
40
+ enumerable: true,
41
+ get() {
42
+ if (!fetched) {
43
+ fetched = true;
44
+ cached = registry.get(id);
45
+ }
46
+ return cached;
47
+ },
48
+ },
49
+ ];
50
+ }),
51
+ ),
52
+ );
53
+ }
54
+
55
+ /**
56
+ * Builds a NodeServiceProxy from a ServiceDispatch.
57
+ * Each service method call is forwarded to dispatch.callServiceMethod.
58
+ */
59
+ export function createNodeServiceProxy(dispatch: ServiceDispatch): NodeServiceProxy {
60
+ return ((serviceId: ServiceName) =>
61
+ Object.freeze(
62
+ Object.fromEntries(
63
+ dispatch
64
+ .getServiceMethods(serviceId)
65
+ .map((method) => [
66
+ method,
67
+ async (...args: unknown[]) => dispatch.callServiceMethod(serviceId, method, ...args),
68
+ ]),
69
+ ),
70
+ )) as NodeServiceProxy;
71
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Type-level service resolution — auto-derives typed service maps from feature flags.
3
+ * No runtime code. No edits needed when adding a service.
4
+ */
5
+
6
+ import type {
7
+ ServiceNameLiterals,
8
+ ModelServices,
9
+ UiServices,
10
+ } from "@milaboratories/pl-model-common";
11
+ import type { BlockServiceFlags } from "./block_services";
12
+
13
+ export type { ModelServices, UiServices };
14
+
15
+ // Flag name → service name literal: "requiresPFrameSpec" → "pframeSpec"
16
+ type FlagToName<Flag extends string> = Flag extends `requires${infer K}`
17
+ ? K extends keyof ServiceNameLiterals
18
+ ? ServiceNameLiterals[K]
19
+ : never
20
+ : never;
21
+
22
+ // Extract all required service name literals from feature flags
23
+ type RequiredServiceNames<Flags> = {
24
+ [K in keyof Flags & `requires${string}`]: Flags[K] extends true ? FlagToName<K & string> : never;
25
+ }[keyof Flags & `requires${string}`];
26
+
27
+ // Resolve typed services from feature flags
28
+ // { requiresPFrameSpec: true } -> { pframeSpec: PFrameSpecDriver }
29
+ export type ResolveModelServices<Flags> = Pick<
30
+ ModelServices,
31
+ RequiredServiceNames<Flags> & keyof ModelServices
32
+ >;
33
+
34
+ export type ResolveUiServices<Flags> = Pick<
35
+ UiServices,
36
+ RequiredServiceNames<Flags> & keyof UiServices
37
+ >;
38
+
39
+ // Auto-derived from BLOCK_SERVICE_FLAGS.
40
+ export type BlockDefaultModelServices = ResolveModelServices<BlockServiceFlags>;
41
+ export type BlockDefaultUiServices = ResolveUiServices<BlockServiceFlags>;
42
+
43
+ // Compile-time type assertions — verified by tsc, not executed at runtime.
44
+ // Each @ts-expect-error proves the line below would be a type error.
45
+
46
+ // Block default services include pframeSpec
47
+ const _modelSpec: BlockDefaultModelServices["pframeSpec"] = undefined!;
48
+ const _uiSpec: BlockDefaultUiServices["pframeSpec"] = undefined!;
49
+ void _modelSpec;
50
+ void _uiSpec;
51
+
52
+ // Block default services do NOT include pframe (only plugins can request it)
53
+ // @ts-expect-error pframe is not in default block model services
54
+ const _modelPframe: BlockDefaultModelServices["pframe"] = undefined!;
55
+ // @ts-expect-error pframe is not in default block UI services
56
+ const _uiPframe: BlockDefaultUiServices["pframe"] = undefined!;
57
+ void _modelPframe;
58
+ void _uiPframe;
59
+
60
+ // ResolveModelServices with false flag resolves to empty
61
+ type _NoServices = ResolveModelServices<{ requiresPFrameSpec: false }>;
62
+ // @ts-expect-error pframeSpec is not resolved when flag is false
63
+ const _noSpec: _NoServices["pframeSpec"] = undefined!;
64
+ void _noSpec;
65
+
66
+ // ResolveModelServices with multiple flags resolves all
67
+ type _Both = ResolveModelServices<{ requiresPFrameSpec: true; requiresPFrame: true }>;
68
+ const _bothSpec: _Both["pframeSpec"] = undefined!;
69
+ const _bothPframe: _Both["pframe"] = undefined!;
70
+ void _bothSpec;
71
+ void _bothPframe;