@platforma-sdk/model 1.81.0 → 1.82.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 (38) hide show
  1. package/dist/block_migrations.cjs +92 -8
  2. package/dist/block_migrations.cjs.map +1 -1
  3. package/dist/block_migrations.d.ts +121 -32
  4. package/dist/block_migrations.d.ts.map +1 -1
  5. package/dist/block_migrations.js +92 -8
  6. package/dist/block_migrations.js.map +1 -1
  7. package/dist/block_model.cjs +69 -15
  8. package/dist/block_model.cjs.map +1 -1
  9. package/dist/block_model.d.ts +58 -22
  10. package/dist/block_model.d.ts.map +1 -1
  11. package/dist/block_model.js +71 -17
  12. package/dist/block_model.js.map +1 -1
  13. package/dist/block_storage_callbacks.cjs +194 -13
  14. package/dist/block_storage_callbacks.cjs.map +1 -1
  15. package/dist/block_storage_callbacks.js +192 -15
  16. package/dist/block_storage_callbacks.js.map +1 -1
  17. package/dist/block_storage_facade.cjs +4 -1
  18. package/dist/block_storage_facade.cjs.map +1 -1
  19. package/dist/block_storage_facade.d.ts +102 -0
  20. package/dist/block_storage_facade.d.ts.map +1 -1
  21. package/dist/block_storage_facade.js +4 -1
  22. package/dist/block_storage_facade.js.map +1 -1
  23. package/dist/components/PlDataTable/createPlDataTable/utils.cjs +1 -1
  24. package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -1
  25. package/dist/components/PlDataTable/createPlDataTable/utils.js +1 -1
  26. package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -1
  27. package/dist/package.cjs +1 -1
  28. package/dist/package.js +1 -1
  29. package/package.json +9 -8
  30. package/src/block_migrations.ts +205 -55
  31. package/src/block_model.ts +190 -59
  32. package/src/block_storage_callbacks.ts +294 -15
  33. package/src/block_storage_facade.ts +95 -0
  34. package/src/components/PlDataTable/createPlDataTable/utils.test.ts +31 -0
  35. package/src/components/PlDataTable/createPlDataTable/utils.ts +4 -1
  36. package/src/kind_reference.test.ts +134 -0
  37. package/src/template_init.test.ts +413 -0
  38. package/src/template_params.test.ts +135 -0
@@ -1,4 +1,4 @@
1
- import { DataModel } from "./block_migrations.js";
1
+ import { BlockKind, DataModel } from "./block_migrations.js";
2
2
  import { ConfigRenderLambda, ConfigRenderLambdaFlags, InferOutputsFromLambdas } from "./bconfig/lambdas.js";
3
3
  import { DeriveHref } from "./bconfig/util.js";
4
4
  import { BlockDefaultUiServices } from "./services/service_resolve.js";
@@ -30,7 +30,7 @@ type PluginRecord<Data extends PluginData = PluginData, Params extends PluginPar
30
30
  * to call {@link done()} at the end of configuration. Value returned by this builder must be
31
31
  * exported as constant with name "platforma" from the "config" module.
32
32
  * API version is 3 (for UI) and 2 (for model) */
33
- declare class BlockModelV3<Args, OutputsCfg extends Record<string, ConfigRenderLambda>, Data extends Record<string, unknown> = Record<string, unknown>, Href extends `/${string}` = "/", Plugins extends Record<string, PluginRecord> = {}, Transfers extends Record<string, unknown> = {}> {
33
+ declare class BlockModelV3<Args, OutputsCfg extends Record<string, ConfigRenderLambda>, Data extends Record<string, unknown> = Record<string, unknown>, Href extends `/${string}` = "/", Plugins extends Record<string, PluginRecord> = {}, Transfers extends Record<string, unknown> = {}, Params = unknown> {
34
34
  private readonly config;
35
35
  private constructor();
36
36
  static readonly FEATURE_FLAGS: {
@@ -59,21 +59,28 @@ declare class BlockModelV3<Args, OutputsCfg extends Record<string, ConfigRenderL
59
59
  requiresPFramesVersion: number;
60
60
  };
61
61
  /**
62
- * Creates a new BlockModelV3 builder with the specified data model.
62
+ * Creates a new BlockModelV3 builder bound to a data model and a block kind.
63
+ *
64
+ * The `kind` argument is cross-checked against the kind handed to the
65
+ * builder: its `Params` type must match at compile time (via
66
+ * `BlockKind<Params>`), and its reference value must match at runtime. The
67
+ * reference is baked into the config so the published manifest can advertise
68
+ * which kind the block implements.
63
69
  *
64
70
  * @example
65
- * const dataModel = new DataModelBuilder()
71
+ * const dataModel = new DataModelBuilder({ kind })
66
72
  * .from<BlockData>("v1")
67
- * .init(() => ({ numbers: [], labels: [] }));
73
+ * .init(({ params }) => params ?? { numbers: [], labels: [] });
68
74
  *
69
- * BlockModelV3.create(dataModel)
75
+ * BlockModelV3.create({ dataModel, kind })
70
76
  * .args((data) => ({ numbers: data.numbers }))
71
77
  * .sections(() => [{ type: 'link', href: '/', label: 'Main' }])
72
78
  * .done();
73
- *
74
- * @param dataModel The data model that defines initial data and migrations
75
79
  */
76
- static create<Data extends Record<string, unknown>, Transfers extends Record<string, unknown> = {}>(dataModel: DataModel<Data, Transfers>): BlockModelV3<NoOb, {}, Data, "/", {}, Transfers>;
80
+ static create<Data extends Record<string, unknown>, Params = never, Transfers extends Record<string, unknown> = {}>(args: {
81
+ dataModel: DataModel<Data, Params, Transfers>;
82
+ kind: BlockKind<Params>;
83
+ }): BlockModelV3<NoOb, {}, Data, "/", {}, Transfers, Params>;
77
84
  /**
78
85
  * Add output cell wrapped with additional status information to the configuration
79
86
  *
@@ -86,7 +93,7 @@ declare class BlockModelV3<Args, OutputsCfg extends Record<string, ConfigRenderL
86
93
  withStatus: true;
87
94
  }): BlockModelV3<Args, OutputsCfg & { [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> & {
88
95
  withStatus: true;
89
- } }, Data, Href, Plugins, Transfers>;
96
+ } }, Data, Href, Plugins, Transfers, Params>;
90
97
  /**
91
98
  * Add output cell to the configuration
92
99
  *
@@ -95,13 +102,13 @@ declare class BlockModelV3<Args, OutputsCfg extends Record<string, ConfigRenderL
95
102
  * workflows outputs and interact with platforma drivers
96
103
  * @param flags additional flags that may alter lambda rendering procedure
97
104
  * */
98
- output<const Key extends string, const RF extends RenderFunction<Args, Data, unknown>>(key: Key, rf: RF, flags?: ConfigRenderLambdaFlags): BlockModelV3<Args, OutputsCfg & { [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> }, Data, Href, Plugins, Transfers>;
105
+ output<const Key extends string, const RF extends RenderFunction<Args, Data, unknown>>(key: Key, rf: RF, flags?: ConfigRenderLambdaFlags): BlockModelV3<Args, OutputsCfg & { [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> }, Data, Href, Plugins, Transfers, Params>;
99
106
  /** Shortcut for {@link output} with retentive flag set to true. */
100
- retentiveOutput<const Key extends string, const RF extends RenderFunction<Args, Data, unknown>>(key: Key, rf: RF): BlockModelV3<Args, OutputsCfg & { [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> }, Data, Href, Plugins, Transfers>;
107
+ retentiveOutput<const Key extends string, const RF extends RenderFunction<Args, Data, unknown>>(key: Key, rf: RF): BlockModelV3<Args, OutputsCfg & { [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> }, Data, Href, Plugins, Transfers, Params>;
101
108
  /** Shortcut for {@link output} with withStatus flag set to true. */
102
109
  outputWithStatus<const Key extends string, const RF extends RenderFunction<Args, Data, unknown>>(key: Key, rf: RF): BlockModelV3<Args, OutputsCfg & { [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> & {
103
110
  withStatus: true;
104
- } }, Data, Href, Plugins, Transfers>;
111
+ } }, Data, Href, Plugins, Transfers, Params>;
105
112
  /**
106
113
  * Sets a function to derive block args from data.
107
114
  * This is called during setData to compute the args that will be used for block execution.
@@ -115,7 +122,7 @@ declare class BlockModelV3<Args, OutputsCfg extends Record<string, ConfigRenderL
115
122
  * return { numbers: data.numbers };
116
123
  * })
117
124
  */
118
- args<A>(lambda: (data: Data) => A): BlockModelV3<A, OutputsCfg, Data, Href, Plugins, Transfers>;
125
+ args<A>(lambda: (data: Data) => A): BlockModelV3<A, OutputsCfg, Data, Href, Plugins, Transfers, Params>;
119
126
  /**
120
127
  * Sets a function to derive pre-run args from data (optional).
121
128
  * This is called during setData to compute the args that will be used for staging/pre-run phase.
@@ -136,20 +143,49 @@ declare class BlockModelV3<Args, OutputsCfg extends Record<string, ConfigRenderL
136
143
  * return { numbers: data.numbers };
137
144
  * })
138
145
  */
139
- prerunArgs(fn: (data: Data) => unknown): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>;
146
+ prerunArgs(fn: (data: Data) => unknown): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>;
147
+ /**
148
+ * Sets the function that projects block data back to this kind's params, for
149
+ * exporting the project as a template.
150
+ *
151
+ * The inverse of the data model's `init`: `init` builds data from `params`, this
152
+ * recovers the `params` that would rebuild the current data. Return only params
153
+ * — runtime and derived state is dropped, and the exporter supplies the rest of
154
+ * the entry (`id`, `kind`), which this lambda cannot set.
155
+ *
156
+ * References are returned as ordinary `PlRef`s; the SDK rewrites them into
157
+ * template-local form on the way out, so a block never deals with the file
158
+ * representation.
159
+ *
160
+ * Required: `done()` throws without it. A block whose state cannot be reduced to
161
+ * params returns `{}` and says so explicitly, rather than exporting an entry with
162
+ * no params that silently applies as a default-initialized block.
163
+ *
164
+ * The return type is the kind's `Params`, so a block whose projection drifts
165
+ * from its own init contract fails to compile. Available only on a
166
+ * kind-carrying model — `create(dataModel)` without a kind leaves `Params` as
167
+ * `unknown` and this method cannot be type-checked against anything.
168
+ *
169
+ * @example
170
+ * BlockModelV3.create({ dataModel, kind })
171
+ * .args((data) => ({ numbers: data.numbers }))
172
+ * .templateParams((data) => ({ sources: data.sources }))
173
+ * .done();
174
+ */
175
+ templateParams(fn: (data: Data) => Params): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>;
140
176
  /** Sets the lambda to generate list of sections in the left block overviews panel. */
141
- sections<const Ret extends SectionsExpectedType, const RF extends RenderFunction<Args, Data, Ret>>(rf: RF): BlockModelV3<Args, OutputsCfg, Data, DeriveHref<ReturnType<RF>>, Plugins, Transfers>;
177
+ sections<const Ret extends SectionsExpectedType, const RF extends RenderFunction<Args, Data, Ret>>(rf: RF): BlockModelV3<Args, OutputsCfg, Data, DeriveHref<ReturnType<RF>>, Plugins, Transfers, Params>;
142
178
  /** Sets a rendering function to derive block title, shown for the block in the left blocks-overview panel. */
143
- title(rf: RenderFunction<Args, Data, string>): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>;
144
- subtitle(rf: RenderFunction<Args, Data, string>): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>;
145
- tags(rf: RenderFunction<Args, Data, string[]>): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>;
179
+ title(rf: RenderFunction<Args, Data, string>): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>;
180
+ subtitle(rf: RenderFunction<Args, Data, string>): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>;
181
+ tags(rf: RenderFunction<Args, Data, string[]>): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>;
146
182
  /** Sets or overrides feature flags for the block. */
147
- withFeatureFlags(flags: Partial<BlockCodeKnownFeatureFlags>): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>;
183
+ withFeatureFlags(flags: Partial<BlockCodeKnownFeatureFlags>): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>;
148
184
  /**
149
185
  * Defines how to derive list of upstream references this block is meant to enrich with its exports from block args.
150
186
  * Influences dependency graph construction.
151
187
  */
152
- enriches(lambda: (args: Args) => PlRef[]): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>;
188
+ enriches(lambda: (args: Args) => PlRef[]): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>;
153
189
  /**
154
190
  * Registers a plugin instance with the block.
155
191
  * Consumes a transfer if one was defined for this plugin ID in the migration chain.
@@ -168,7 +204,7 @@ declare class BlockModelV3<Args, OutputsCfg extends Record<string, ConfigRenderL
168
204
  * sourceId: (ctx) => ctx.data.selectedSource,
169
205
  * })
170
206
  */
171
- plugin<const PluginId extends string, PData extends PluginData, PParams extends PluginParams, POutputs extends PluginOutputs, PPublicOutputs extends PluginPublicOutputs, PTransferData, PluginModelServices, PluginUiServices>(instance: PluginInstance<PluginId & (PluginId extends keyof Transfers ? Transfers[PluginId] extends PTransferData ? string : never : [PTransferData] extends [never] ? string : never) & (PluginId extends keyof Plugins ? never : string), PData, PParams, POutputs, PPublicOutputs, PTransferData, PluginModelServices, PluginUiServices>, params?: ParamsInput<PParams, Args, Data>): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins & { [K in PluginId]: PluginRecord<PData, PParams, POutputs, PPublicOutputs, PluginModelServices, PluginUiServices> }, Omit<Transfers, PluginId>>;
207
+ plugin<const PluginId extends string, PData extends PluginData, PParams extends PluginParams, POutputs extends PluginOutputs, PPublicOutputs extends PluginPublicOutputs, PTransferData, PluginModelServices, PluginUiServices>(instance: PluginInstance<PluginId & (PluginId extends keyof Transfers ? Transfers[PluginId] extends PTransferData ? string : never : [PTransferData] extends [never] ? string : never) & (PluginId extends keyof Plugins ? never : string), PData, PParams, POutputs, PPublicOutputs, PTransferData, PluginModelServices, PluginUiServices>, params?: ParamsInput<PParams, Args, Data>): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins & { [K in PluginId]: PluginRecord<PData, PParams, POutputs, PPublicOutputs, PluginModelServices, PluginUiServices> }, Omit<Transfers, PluginId>, Params>;
172
208
  /** Renders all provided block settings into a pre-configured platforma API
173
209
  * instance, that can be used in frontend to interact with block data, and
174
210
  * other features provided by the platforma to the block.
@@ -1 +1 @@
1
- {"version":3,"file":"block_model.d.ts","names":[],"sources":["../src/block_model.ts"],"mappings":"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"}
1
+ {"version":3,"file":"block_model.d.ts","names":[],"sources":["../src/block_model.ts"],"mappings":"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"}
@@ -9,8 +9,8 @@ import { isConfigLambda } from "./bconfig/types.js";
9
9
  import { downgradeCfgOrLambda } from "./bconfig/normalization.js";
10
10
  import "./bconfig/index.js";
11
11
  import { CREATE_PLUGIN_MODEL } from "./plugin_model.js";
12
- import { applyStorageUpdate, createInitialStorage, deriveArgsFromStorage, derivePrerunArgsFromStorage, getStorageDebugView, migrateStorage } from "./block_storage_callbacks.js";
13
- import { REQUIRES_PFRAMES_VERSION } from "@milaboratories/pl-model-common";
12
+ import { applyStorageUpdate, createInitialStorage, createInitialStorageFromParams, deriveArgsFromStorage, derivePrerunArgsFromStorage, deriveTemplateParamsFromStorage, getStorageDebugView, migrateStorage, validateTemplateParamsJson } from "./block_storage_callbacks.js";
13
+ import { REQUIRES_PFRAMES_VERSION, formatKindRef } from "@milaboratories/pl-model-common";
14
14
  //#region src/block_model.ts
15
15
  /**
16
16
  * Merges two feature flag objects with type-aware logic:
@@ -48,24 +48,33 @@ var BlockModelV3 = class BlockModelV3 {
48
48
  /** @deprecated Use FEATURE_FLAGS */
49
49
  static INITIAL_BLOCK_FEATURE_FLAGS = BlockModelV3.FEATURE_FLAGS;
50
50
  /**
51
- * Creates a new BlockModelV3 builder with the specified data model.
51
+ * Creates a new BlockModelV3 builder bound to a data model and a block kind.
52
+ *
53
+ * The `kind` argument is cross-checked against the kind handed to the
54
+ * builder: its `Params` type must match at compile time (via
55
+ * `BlockKind<Params>`), and its reference value must match at runtime. The
56
+ * reference is baked into the config so the published manifest can advertise
57
+ * which kind the block implements.
52
58
  *
53
59
  * @example
54
- * const dataModel = new DataModelBuilder()
60
+ * const dataModel = new DataModelBuilder({ kind })
55
61
  * .from<BlockData>("v1")
56
- * .init(() => ({ numbers: [], labels: [] }));
62
+ * .init(({ params }) => params ?? { numbers: [], labels: [] });
57
63
  *
58
- * BlockModelV3.create(dataModel)
64
+ * BlockModelV3.create({ dataModel, kind })
59
65
  * .args((data) => ({ numbers: data.numbers }))
60
66
  * .sections(() => [{ type: 'link', href: '/', label: 'Main' }])
61
67
  * .done();
62
- *
63
- * @param dataModel The data model that defines initial data and migrations
64
68
  */
65
- static create(dataModel) {
69
+ static create(args) {
70
+ const { dataModel, kind } = args;
71
+ const kindRef = formatKindRef(kind);
72
+ if (dataModel.kindRef && dataModel.kindRef !== kindRef) throw new Error(`Block kind mismatch: data model built for '${dataModel.kindRef}' but create() got '${kindRef}'`);
66
73
  return new BlockModelV3({
67
74
  renderingMode: "Heavy",
68
75
  dataModel,
76
+ kind: kindRef,
77
+ parseInitializationParams: kind.parseInitializationParams,
69
78
  outputs: {},
70
79
  sections: createAndRegisterRenderLambda({
71
80
  handle: "sections",
@@ -76,8 +85,9 @@ var BlockModelV3 = class BlockModelV3 {
76
85
  tags: void 0,
77
86
  enrichmentTargets: void 0,
78
87
  featureFlags: { ...BlockModelV3.FEATURE_FLAGS },
79
- argsFunction: void 0,
80
- prerunArgsFunction: void 0,
88
+ deriveArgs: void 0,
89
+ derivePrerunArgs: void 0,
90
+ deriveTemplateParams: void 0,
81
91
  plugins: {}
82
92
  });
83
93
  }
@@ -118,7 +128,7 @@ var BlockModelV3 = class BlockModelV3 {
118
128
  args(lambda) {
119
129
  return new BlockModelV3({
120
130
  ...this.config,
121
- argsFunction: lambda
131
+ deriveArgs: lambda
122
132
  });
123
133
  }
124
134
  /**
@@ -144,7 +154,41 @@ var BlockModelV3 = class BlockModelV3 {
144
154
  prerunArgs(fn) {
145
155
  return new BlockModelV3({
146
156
  ...this.config,
147
- prerunArgsFunction: fn
157
+ derivePrerunArgs: fn
158
+ });
159
+ }
160
+ /**
161
+ * Sets the function that projects block data back to this kind's params, for
162
+ * exporting the project as a template.
163
+ *
164
+ * The inverse of the data model's `init`: `init` builds data from `params`, this
165
+ * recovers the `params` that would rebuild the current data. Return only params
166
+ * — runtime and derived state is dropped, and the exporter supplies the rest of
167
+ * the entry (`id`, `kind`), which this lambda cannot set.
168
+ *
169
+ * References are returned as ordinary `PlRef`s; the SDK rewrites them into
170
+ * template-local form on the way out, so a block never deals with the file
171
+ * representation.
172
+ *
173
+ * Required: `done()` throws without it. A block whose state cannot be reduced to
174
+ * params returns `{}` and says so explicitly, rather than exporting an entry with
175
+ * no params that silently applies as a default-initialized block.
176
+ *
177
+ * The return type is the kind's `Params`, so a block whose projection drifts
178
+ * from its own init contract fails to compile. Available only on a
179
+ * kind-carrying model — `create(dataModel)` without a kind leaves `Params` as
180
+ * `unknown` and this method cannot be type-checked against anything.
181
+ *
182
+ * @example
183
+ * BlockModelV3.create({ dataModel, kind })
184
+ * .args((data) => ({ numbers: data.numbers }))
185
+ * .templateParams((data) => ({ sources: data.sources }))
186
+ * .done();
187
+ */
188
+ templateParams(fn) {
189
+ return new BlockModelV3({
190
+ ...this.config,
191
+ deriveTemplateParams: fn
148
192
  });
149
193
  }
150
194
  /** Sets the lambda to generate list of sections in the left block overviews panel. */
@@ -236,13 +280,14 @@ var BlockModelV3 = class BlockModelV3 {
236
280
  * before calling `.done()`.
237
281
  */
238
282
  done(..._) {
239
- if (this.config.argsFunction === void 0) throw new Error("Args rendering function not set.");
283
+ if (this.config.deriveArgs === void 0) throw new Error("Args rendering function not set.");
284
+ if (this.config.deriveTemplateParams === void 0) throw new Error("templateParams() not set. Every block must project its state back to its kind's params, so a project can be exported as a template and re-applied; a block whose state carries nothing worth restoring returns {}.");
240
285
  const apiVersion = 3;
241
286
  const { plugins } = this.config;
242
287
  const pluginRegistry = {};
243
288
  const pluginHandles = Object.keys(plugins);
244
289
  for (const handle of pluginHandles) pluginRegistry[handle] = plugins[handle].model.name;
245
- const { dataModel, argsFunction, prerunArgsFunction } = this.config;
290
+ const { dataModel, deriveArgs, derivePrerunArgs, deriveTemplateParams, parseInitializationParams } = this.config;
246
291
  function getPlugin(handle) {
247
292
  const plugin = plugins[handle];
248
293
  if (!plugin) throw new Error(`Plugin model not found for '${handle}'`);
@@ -265,8 +310,16 @@ var BlockModelV3 = class BlockModelV3 {
265
310
  getPluginRegistry: () => pluginRegistry,
266
311
  createPluginData: (handle) => getPlugin(handle).model.getDefaultData()
267
312
  }),
268
- [BlockStorageFacadeCallbacks.ArgsDerive]: (storageJson) => deriveArgsFromStorage(storageJson, argsFunction),
269
- [BlockStorageFacadeCallbacks.PrerunArgsDerive]: (storageJson) => derivePrerunArgsFromStorage(storageJson, argsFunction, prerunArgsFunction)
313
+ [BlockStorageFacadeCallbacks.ArgsDerive]: (storageJson) => deriveArgsFromStorage(storageJson, deriveArgs),
314
+ [BlockStorageFacadeCallbacks.PrerunArgsDerive]: (storageJson) => derivePrerunArgsFromStorage(storageJson, deriveArgs, derivePrerunArgs),
315
+ [BlockStorageFacadeCallbacks.InitializationParamsDerive]: (storageJson) => deriveTemplateParamsFromStorage(storageJson, deriveTemplateParams),
316
+ [BlockStorageFacadeCallbacks.StorageInitialFromParams]: (paramsJson, blockIdsJson) => createInitialStorageFromParams(paramsJson, blockIdsJson, {
317
+ getBlockDataFromParams: (params) => dataModel.getDataFromParams(params),
318
+ getPluginRegistry: () => pluginRegistry,
319
+ createPluginData: (handle) => getPlugin(handle).model.getDefaultData(),
320
+ parseInitializationParams
321
+ }),
322
+ [BlockStorageFacadeCallbacks.InitializationParamsValidate]: (paramsJson) => validateTemplateParamsJson(paramsJson, parseInitializationParams)
270
323
  });
271
324
  const pluginOutputs = {};
272
325
  for (const handle of pluginHandles) {
@@ -303,6 +356,7 @@ var BlockModelV3 = class BlockModelV3 {
303
356
  featureFlags: this.config.featureFlags,
304
357
  blockLifecycleCallbacks: { ...BlockStorageFacadeHandles }
305
358
  },
359
+ kind: this.config.kind,
306
360
  sdkVersion: PlatformaSDKVersion,
307
361
  renderingMode: this.config.renderingMode,
308
362
  sections: this.config.sections,
@@ -1 +1 @@
1
- {"version":3,"file":"block_model.js","names":[],"sources":["../src/block_model.ts"],"sourcesContent":["import type {\n BlockRenderingMode,\n BlockSection,\n OutputWithStatus,\n PlRef,\n BlockCodeKnownFeatureFlags,\n BlockConfigContainer,\n} from \"@milaboratories/pl-model-common\";\nimport { REQUIRES_PFRAMES_VERSION } from \"@milaboratories/pl-model-common\";\nimport { getPlatformaInstance, isInUI, createAndRegisterRenderLambda } from \"./internal\";\nimport type { DataModel } from \"./block_migrations\";\nimport type { PlatformaV3 } from \"./platforma\";\nimport type { BlockDefaultUiServices } from \"./services/service_resolve\";\nimport { BLOCK_SERVICE_FLAGS } from \"./services/block_services\";\nimport type { InferRenderFunctionReturn, RenderFunction } from \"./render\";\nimport { BlockRenderCtx, PluginRenderCtx } from \"./render\";\nimport type {\n PluginData,\n PluginModel,\n PluginOutputs,\n PluginParams,\n PluginPublicOutputs,\n} from \"./plugin_model\";\nimport { PluginInstance as PluginInstanceClass, CREATE_PLUGIN_MODEL } from \"./plugin_model\";\nimport { type PluginHandle, pluginOutputKey } from \"./plugin_handle\";\nimport type { RenderCtxBase } from \"./render\";\nimport { PlatformaSDKVersion } from \"./version\";\nimport {\n applyStorageUpdate,\n getStorageDebugView,\n migrateStorage,\n createInitialStorage,\n deriveArgsFromStorage,\n derivePrerunArgsFromStorage,\n} from \"./block_storage_callbacks\";\nimport { type PluginName } from \"./block_storage\";\nimport type {\n ConfigRenderLambda,\n DeriveHref,\n ConfigRenderLambdaFlags,\n InferOutputsFromLambdas,\n} from \"./bconfig\";\nimport { downgradeCfgOrLambda, isConfigLambda } from \"./bconfig\";\nimport type { PlatformaExtended } from \"./platforma\";\nimport {\n BLOCK_STORAGE_FACADE_VERSION,\n BlockStorageFacadeCallbacks,\n BlockStorageFacadeHandles,\n registerFacadeCallbacks,\n} from \"./block_storage_facade\";\n\ntype SectionsExpectedType = readonly BlockSection[];\n\ntype NoOb = Record<string, never>;\n\n/**\n * Per-property lambdas for deriving plugin params from block render context.\n * Each property is a function that receives the block's RenderCtxBase and returns the param value.\n */\nexport type ParamsInput<Params, BArgs = unknown, BData = unknown> = {\n [K in keyof Params]: (ctx: RenderCtxBase<BArgs, BData>) => Params[K];\n};\n\n/**\n * Type-erased version of ParamsInput for internal storage.\n */\ntype ParamsInputErased = Record<string, (ctx: RenderCtxBase) => unknown>;\n\n/**\n * Merges two feature flag objects with type-aware logic:\n * - `supports*` (boolean): OR — `true` if either side is `true`\n * - `requires*` (numeric): MAX — take the higher version requirement\n */\nfunction mergeFeatureFlags(\n base: BlockCodeKnownFeatureFlags,\n override: BlockCodeKnownFeatureFlags,\n): BlockCodeKnownFeatureFlags {\n const result: Record<string, boolean | number | undefined> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) continue;\n const existing = result[key];\n if (typeof value === \"boolean\") {\n result[key] = (typeof existing === \"boolean\" && existing) || value;\n } else if (typeof value === \"number\") {\n result[key] = Math.max(typeof existing === \"number\" ? existing : 0, value);\n }\n }\n return result as BlockCodeKnownFeatureFlags;\n}\n\n/**\n * Plugin record: model + param derivation lambdas.\n */\nexport type PluginRecord<\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n PublicOutputs extends PluginPublicOutputs = PluginPublicOutputs,\n ModelServices = unknown,\n UiServices = unknown,\n> = {\n readonly model: PluginModel<Data, Params, Outputs, PublicOutputs, ModelServices, UiServices>;\n readonly inputs: ParamsInputErased;\n};\n\ninterface BlockModelV3Config<\n OutputsCfg extends Record<string, ConfigRenderLambda>,\n Data,\n Plugins extends Record<string, PluginRecord> = {},\n Transfers extends Record<string, unknown> = {},\n> {\n renderingMode: BlockRenderingMode;\n dataModel: DataModel<Data, Transfers>;\n outputs: OutputsCfg;\n sections: ConfigRenderLambda;\n title: ConfigRenderLambda | undefined;\n subtitle: ConfigRenderLambda | undefined;\n tags: ConfigRenderLambda | undefined;\n enrichmentTargets: ConfigRenderLambda | undefined;\n featureFlags: BlockCodeKnownFeatureFlags;\n argsFunction: ((data: unknown) => unknown) | undefined;\n prerunArgsFunction: ((data: unknown) => unknown) | undefined;\n plugins: Plugins;\n}\n\n/** Main entry point that each block should use in it's \"config\" module. Don't forget\n * to call {@link done()} at the end of configuration. Value returned by this builder must be\n * exported as constant with name \"platforma\" from the \"config\" module.\n * API version is 3 (for UI) and 2 (for model) */\nexport class BlockModelV3<\n Args,\n OutputsCfg extends Record<string, ConfigRenderLambda>,\n Data extends Record<string, unknown> = Record<string, unknown>,\n Href extends `/${string}` = \"/\",\n Plugins extends Record<string, PluginRecord> = {},\n Transfers extends Record<string, unknown> = {},\n> {\n private constructor(\n private readonly config: BlockModelV3Config<OutputsCfg, Data, Plugins, Transfers>,\n ) {}\n\n public static readonly FEATURE_FLAGS = {\n supportsLazyState: true,\n supportsPframeQueryRanking: true,\n requiresUIAPIVersion: 3,\n requiresModelAPIVersion: BLOCK_STORAGE_FACADE_VERSION,\n requiresCreatePTable: 2,\n requiresPFramesVersion: REQUIRES_PFRAMES_VERSION,\n ...BLOCK_SERVICE_FLAGS,\n } satisfies BlockCodeKnownFeatureFlags;\n\n /** @deprecated Use FEATURE_FLAGS */\n public static readonly INITIAL_BLOCK_FEATURE_FLAGS = BlockModelV3.FEATURE_FLAGS;\n\n /**\n * Creates a new BlockModelV3 builder with the specified data model.\n *\n * @example\n * const dataModel = new DataModelBuilder()\n * .from<BlockData>(\"v1\")\n * .init(() => ({ numbers: [], labels: [] }));\n *\n * BlockModelV3.create(dataModel)\n * .args((data) => ({ numbers: data.numbers }))\n * .sections(() => [{ type: 'link', href: '/', label: 'Main' }])\n * .done();\n *\n * @param dataModel The data model that defines initial data and migrations\n */\n public static create<\n Data extends Record<string, unknown>,\n Transfers extends Record<string, unknown> = {},\n >(dataModel: DataModel<Data, Transfers>): BlockModelV3<NoOb, {}, Data, \"/\", {}, Transfers> {\n return new BlockModelV3<NoOb, {}, Data, \"/\", {}, Transfers>({\n renderingMode: \"Heavy\",\n dataModel,\n outputs: {},\n sections: createAndRegisterRenderLambda({ handle: \"sections\", lambda: () => [] }, true),\n title: undefined,\n subtitle: undefined,\n tags: undefined,\n enrichmentTargets: undefined,\n featureFlags: { ...BlockModelV3.FEATURE_FLAGS },\n argsFunction: undefined,\n prerunArgsFunction: undefined,\n plugins: {},\n });\n }\n\n /**\n * Add output cell wrapped with additional status information to the configuration\n *\n * @param key output cell name, that can be later used to retrieve the rendered value\n * @param rf callback calculating output value using context, that allows to access\n * workflows outputs and interact with platforma drivers\n * @param flags additional flags that may alter lambda rendering procedure\n * */\n public output<const Key extends string, const RF extends RenderFunction<Args, Data, unknown>>(\n key: Key,\n rf: RF,\n flags: ConfigRenderLambdaFlags & { withStatus: true },\n ): BlockModelV3<\n Args,\n OutputsCfg & {\n [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> & {\n withStatus: true;\n };\n },\n Data,\n Href,\n Plugins,\n Transfers\n >;\n /**\n * Add output cell to the configuration\n *\n * @param key output cell name, that can be later used to retrieve the rendered value\n * @param rf callback calculating output value using context, that allows to access\n * workflows outputs and interact with platforma drivers\n * @param flags additional flags that may alter lambda rendering procedure\n * */\n public output<const Key extends string, const RF extends RenderFunction<Args, Data, unknown>>(\n key: Key,\n rf: RF,\n flags?: ConfigRenderLambdaFlags,\n ): BlockModelV3<\n Args,\n OutputsCfg & {\n [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>>;\n },\n Data,\n Href,\n Plugins,\n Transfers\n >;\n public output(\n key: string,\n cfgOrRf: RenderFunction<Args, Data, unknown>,\n flags: ConfigRenderLambdaFlags = {},\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers> {\n return new BlockModelV3({\n ...this.config,\n outputs: {\n ...this.config.outputs,\n [key]: createAndRegisterRenderLambda({\n handle: `block-output#${key}`,\n lambda: () => cfgOrRf(new BlockRenderCtx<Args, Data>()),\n ...flags,\n }),\n },\n });\n }\n\n /** Shortcut for {@link output} with retentive flag set to true. */\n public retentiveOutput<\n const Key extends string,\n const RF extends RenderFunction<Args, Data, unknown>,\n >(\n key: Key,\n rf: RF,\n ): BlockModelV3<\n Args,\n OutputsCfg & {\n [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>>;\n },\n Data,\n Href,\n Plugins,\n Transfers\n > {\n return this.output(key, rf, { retentive: true });\n }\n\n /** Shortcut for {@link output} with withStatus flag set to true. */\n public outputWithStatus<\n const Key extends string,\n const RF extends RenderFunction<Args, Data, unknown>,\n >(key: Key, rf: RF) {\n return this.output(key, rf, { withStatus: true });\n }\n\n /**\n * Sets a function to derive block args from data.\n * This is called during setData to compute the args that will be used for block execution.\n *\n * @example\n * .args<BlockArgs>((data) => ({ numbers: data.numbers }))\n *\n * @example\n * .args<BlockArgs>((data) => {\n * if (data.numbers.length === 0) throw new Error('Numbers required'); // block not ready\n * return { numbers: data.numbers };\n * })\n */\n public args<A>(\n lambda: (data: Data) => A,\n ): BlockModelV3<A, OutputsCfg, Data, Href, Plugins, Transfers> {\n return new BlockModelV3<A, OutputsCfg, Data, Href, Plugins, Transfers>({\n ...this.config,\n argsFunction: lambda as (data: unknown) => unknown,\n });\n }\n\n /**\n * Sets a function to derive pre-run args from data (optional).\n * This is called during setData to compute the args that will be used for staging/pre-run phase.\n *\n * If not defined, defaults to using the args() function result.\n * If defined, uses its return value for the staging / prerun phase.\n *\n * The staging / prerun phase runs only if currentPrerunArgs differs from the executed\n * version of prerunArgs (same comparison logic as currentArgs vs prodArgs).\n *\n * @example\n * .prerunArgs((data) => ({ numbers: data.numbers }))\n *\n * @example\n * .prerunArgs((data) => {\n * // Return undefined to skip staging for this block\n * if (!data.isReady) return undefined;\n * return { numbers: data.numbers };\n * })\n */\n public prerunArgs(\n fn: (data: Data) => unknown,\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>({\n ...this.config,\n prerunArgsFunction: fn as (data: unknown) => unknown,\n });\n }\n\n /** Sets the lambda to generate list of sections in the left block overviews panel. */\n public sections<\n const Ret extends SectionsExpectedType,\n const RF extends RenderFunction<Args, Data, Ret>,\n >(rf: RF): BlockModelV3<Args, OutputsCfg, Data, DeriveHref<ReturnType<RF>>, Plugins, Transfers> {\n return new BlockModelV3<Args, OutputsCfg, Data, DeriveHref<ReturnType<RF>>, Plugins, Transfers>(\n {\n ...this.config,\n // Replace the default sections callback with the user-provided one\n sections: createAndRegisterRenderLambda(\n {\n handle: \"sections\",\n lambda: () => rf(new BlockRenderCtx<Args, Data>()),\n },\n true,\n ),\n },\n );\n }\n\n /** Sets a rendering function to derive block title, shown for the block in the left blocks-overview panel. */\n public title(\n rf: RenderFunction<Args, Data, string>,\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>({\n ...this.config,\n title: createAndRegisterRenderLambda({\n handle: \"title\",\n lambda: () => rf(new BlockRenderCtx<Args, Data>()),\n }),\n });\n }\n\n public subtitle(\n rf: RenderFunction<Args, Data, string>,\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>({\n ...this.config,\n subtitle: createAndRegisterRenderLambda({\n handle: \"subtitle\",\n lambda: () => rf(new BlockRenderCtx<Args, Data>()),\n }),\n });\n }\n\n public tags(\n rf: RenderFunction<Args, Data, string[]>,\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>({\n ...this.config,\n tags: createAndRegisterRenderLambda({\n handle: \"tags\",\n lambda: () => rf(new BlockRenderCtx<Args, Data>()),\n }),\n });\n }\n\n /** Sets or overrides feature flags for the block. */\n public withFeatureFlags(\n flags: Partial<BlockCodeKnownFeatureFlags>,\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>({\n ...this.config,\n featureFlags: { ...this.config.featureFlags, ...flags },\n });\n }\n\n /**\n * Defines how to derive list of upstream references this block is meant to enrich with its exports from block args.\n * Influences dependency graph construction.\n */\n public enriches(\n lambda: (args: Args) => PlRef[],\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers>({\n ...this.config,\n enrichmentTargets: createAndRegisterRenderLambda({\n handle: \"enrichmentTargets\",\n lambda: lambda,\n }),\n });\n }\n\n /**\n * Registers a plugin instance with the block.\n * Consumes a transfer if one was defined for this plugin ID in the migration chain.\n *\n * Type checks:\n * - If Transfers[Id] exists, verifies it extends PTransferData (transfer type compatibility)\n * - If no Transfers[Id], rejects plugins with transferAt set (missing .transfer() in data model)\n * - Rejects duplicate plugin IDs (Id already in keyof Plugins)\n *\n * @param instance - PluginInstance created via factory.create({ pluginId, ... })\n * @param params - Per-property lambdas deriving plugin params from block RenderCtx\n *\n * @example\n * .plugin(mainTable, {\n * columns: (ctx) => ctx.outputs?.resolve(\"data\")?.getPColumns(),\n * sourceId: (ctx) => ctx.data.selectedSource,\n * })\n */\n public plugin<\n const PluginId extends string,\n PData extends PluginData,\n PParams extends PluginParams,\n POutputs extends PluginOutputs,\n PPublicOutputs extends PluginPublicOutputs,\n PTransferData,\n PluginModelServices,\n PluginUiServices,\n >(\n instance: PluginInstanceClass<\n PluginId &\n (PluginId extends keyof Transfers\n ? Transfers[PluginId] extends PTransferData\n ? string\n : never\n : [PTransferData] extends [never]\n ? string\n : never) &\n (PluginId extends keyof Plugins ? never : string),\n PData,\n PParams,\n POutputs,\n PPublicOutputs,\n PTransferData,\n PluginModelServices,\n PluginUiServices\n >,\n params?: ParamsInput<PParams, Args, Data>,\n ): BlockModelV3<\n Args,\n OutputsCfg,\n Data,\n Href,\n Plugins & {\n [K in PluginId]: PluginRecord<\n PData,\n PParams,\n POutputs,\n PPublicOutputs,\n PluginModelServices,\n PluginUiServices\n >;\n },\n Omit<Transfers, PluginId>\n >;\n public plugin(\n instance: PluginInstanceClass,\n params?: ParamsInput<Record<string, unknown>, unknown, unknown>,\n ): BlockModelV3<\n Args,\n OutputsCfg,\n Data,\n Href,\n Record<string, PluginRecord>,\n Record<string, unknown>\n > {\n const pluginId = instance.id;\n const plugin = instance[CREATE_PLUGIN_MODEL]();\n const resolvedParams = (params ?? {}) as ParamsInputErased;\n\n if (pluginId in this.config.plugins) {\n throw new Error(`Plugin '${pluginId}' already registered`);\n }\n\n const registered: PluginRecord = {\n model: plugin,\n inputs: resolvedParams,\n };\n\n return new BlockModelV3({\n ...this.config,\n plugins: {\n ...this.config.plugins,\n [pluginId]: registered,\n },\n featureFlags: mergeFeatureFlags(this.config.featureFlags, plugin.featureFlags ?? {}),\n });\n }\n\n /** Renders all provided block settings into a pre-configured platforma API\n * instance, that can be used in frontend to interact with block data, and\n * other features provided by the platforma to the block.\n *\n * Type-level check: if there are unconsumed transfers (from `.transfer()` calls\n * in the migration chain), this method requires an impossible `never` argument,\n * producing a compile error. Register all transferred plugins via `.plugin(instance)`\n * before calling `.done()`.\n */\n public done(\n ..._: keyof Transfers extends never ? [] : [never]\n ): PlatformaExtended<\n PlatformaV3<\n Data,\n Args,\n InferOutputsFromLambdas<OutputsCfg>,\n Href,\n Plugins,\n BlockDefaultUiServices\n >\n > {\n if (this.config.argsFunction === undefined) throw new Error(\"Args rendering function not set.\");\n\n const apiVersion = 3;\n\n // Build plugin registry\n const { plugins } = this.config;\n const pluginRegistry: Record<string, PluginName> = {};\n const pluginHandles = Object.keys(plugins) as PluginHandle[];\n for (const handle of pluginHandles) {\n pluginRegistry[handle] = plugins[handle].model.name;\n }\n\n const { dataModel, argsFunction, prerunArgsFunction } = this.config;\n\n function getPlugin(handle: PluginHandle): PluginRecord {\n const plugin = plugins[handle];\n if (!plugin) throw new Error(`Plugin model not found for '${handle}'`);\n return plugin;\n }\n\n // Register ALL facade callbacks here, with dependencies captured via closures\n registerFacadeCallbacks({\n [BlockStorageFacadeCallbacks.StorageApplyUpdate]: applyStorageUpdate,\n [BlockStorageFacadeCallbacks.StorageDebugView]: getStorageDebugView,\n [BlockStorageFacadeCallbacks.StorageMigrate]: (currentStorageJson) =>\n migrateStorage(currentStorageJson, {\n migrateBlockData: (v) => dataModel.migrate(v),\n getPluginRegistry: () => pluginRegistry,\n migratePluginData: (handle, v) => getPlugin(handle).model.dataModel.migrate(v),\n createPluginData: (handle, transfer) => {\n if (transfer) return transfer;\n return getPlugin(handle).model.getDefaultData();\n },\n }),\n [BlockStorageFacadeCallbacks.StorageInitial]: () =>\n createInitialStorage({\n getDefaultBlockData: () => dataModel.getDefaultData(),\n getPluginRegistry: () => pluginRegistry,\n createPluginData: (handle) => getPlugin(handle).model.getDefaultData(),\n }),\n [BlockStorageFacadeCallbacks.ArgsDerive]: (storageJson) =>\n deriveArgsFromStorage(storageJson, argsFunction),\n [BlockStorageFacadeCallbacks.PrerunArgsDerive]: (storageJson) =>\n derivePrerunArgsFromStorage(storageJson, argsFunction, prerunArgsFunction),\n });\n\n // Register plugin input and output lambdas\n const pluginOutputs: Record<string, ConfigRenderLambda> = {};\n for (const handle of pluginHandles) {\n const { model, inputs } = plugins[handle];\n // Wrap plugin param lambdas: close over BlockRenderCtx creation\n const wrappedInputs: Record<string, () => unknown> = {};\n for (const [paramKey, paramFn] of Object.entries(inputs)) {\n wrappedInputs[paramKey] = () => paramFn(new BlockRenderCtx());\n }\n\n // Register plugin outputs (in config pack, evaluated by middle layer)\n const outputs = model.outputs as Record<string, (ctx: PluginRenderCtx) => unknown>;\n for (const [outputKey, outputFn] of Object.entries(outputs)) {\n const key = pluginOutputKey(handle, outputKey);\n pluginOutputs[key] = createAndRegisterRenderLambda({\n handle: key,\n lambda: () => outputFn(new PluginRenderCtx(handle, wrappedInputs)),\n withStatus: true,\n });\n }\n }\n const allOutputs = { ...this.config.outputs, ...pluginOutputs };\n\n globalThis.platformaApiVersion = apiVersion;\n\n if (!isInUI()) {\n const blockConfig: BlockConfigContainer = {\n v4: {\n configVersion: 4,\n modelAPIVersion: BLOCK_STORAGE_FACADE_VERSION,\n sdkVersion: PlatformaSDKVersion,\n renderingMode: this.config.renderingMode,\n sections: this.config.sections,\n title: this.config.title,\n subtitle: this.config.subtitle,\n tags: this.config.tags,\n outputs: allOutputs,\n enrichmentTargets: this.config.enrichmentTargets,\n featureFlags: this.config.featureFlags,\n blockLifecycleCallbacks: { ...BlockStorageFacadeHandles },\n },\n\n // fields below are added to allow previous desktop versions read generated configs\n sdkVersion: PlatformaSDKVersion,\n renderingMode: this.config.renderingMode,\n sections: this.config.sections,\n outputs: Object.fromEntries(\n Object.entries(this.config.outputs).map(([key, value]) => [\n key,\n downgradeCfgOrLambda(value),\n ]),\n ),\n };\n // we are in the configuration rendering routine, not in actual UI\n return { config: blockConfig } as any;\n // normal operation inside the UI\n } else {\n return {\n ...getPlatformaInstance({\n sdkVersion: PlatformaSDKVersion,\n apiVersion,\n }),\n blockModelInfo: {\n outputs: Object.fromEntries(\n Object.entries(allOutputs).map(([key, value]) => [\n key,\n {\n withStatus: Boolean(isConfigLambda(value) && value.withStatus),\n },\n ]),\n ),\n pluginIds: pluginHandles,\n featureFlags: this.config.featureFlags,\n pluginPublicOutputs: Object.fromEntries(\n pluginHandles.map((handle) => [handle, plugins[handle].model.publicOutputDef]),\n ),\n },\n } as any;\n }\n }\n}\n\n// Type tests for BlockModelV3\n\nexport type Expect<T extends true> = T;\n\nexport type Equal<X, Y> =\n (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;\n\nexport type Merge<A, B> = {\n [K in keyof A | keyof B]: K extends keyof B ? B[K] : K extends keyof A ? A[K] : never;\n};\n\n// Helper types for testing\ntype _TestArgs = { inputFile: string; threshold: number };\ntype _TestData = { selectedTab: string };\ntype _TestOutputs = {\n result: ConfigRenderLambda<string>;\n count: ConfigRenderLambda<number>;\n};\n\n// Test: Merge type works correctly\ntype _MergeTest1 = Expect<Equal<Merge<{ a: 1 }, { b: 2 }>, { a: 1; b: 2 }>>;\ntype _MergeTest2 = Expect<Equal<Merge<{ a: 1 }, { a: 2 }>, { a: 2 }>>;\ntype _MergeTest3 = Expect<Equal<Merge<{ a: 1; b: 1 }, { b: 2; c: 3 }>, { a: 1; b: 2; c: 3 }>>;\n\n// Test: create() returns a BlockModelV3 instance\n// Note: Due to function overloads, ReturnType uses the last overload signature.\n// We verify the structure is correct using a simpler assignability test.\ntype _CreateResult = ReturnType<typeof BlockModelV3.create>;\ntype _CreateIsBlockModelV3 =\n _CreateResult extends BlockModelV3<infer _A, infer _O, infer _S> ? true : false;\ntype _CreateTest = Expect<_CreateIsBlockModelV3>;\n\n// Test: BlockModelV3Config interface structure (default generics)\ntype _ConfigTest = Expect<\n Equal<\n BlockModelV3Config<_TestOutputs, _TestData>,\n {\n renderingMode: BlockRenderingMode;\n argsFunction: ((data: unknown) => unknown) | undefined;\n prerunArgsFunction: ((data: unknown) => unknown) | undefined;\n dataModel: DataModel<_TestData, {}>;\n outputs: _TestOutputs;\n sections: ConfigRenderLambda;\n title: ConfigRenderLambda | undefined;\n subtitle: ConfigRenderLambda | undefined;\n tags: ConfigRenderLambda | undefined;\n enrichmentTargets: ConfigRenderLambda | undefined;\n featureFlags: BlockCodeKnownFeatureFlags;\n plugins: {};\n }\n >\n>;\n\n// Test: Default Href is '/'\ntype _HrefDefaultTest =\n BlockModelV3<_TestArgs, {}, _TestData> extends BlockModelV3<_TestArgs, {}, _TestData, \"/\">\n ? true\n : false;\ntype _VerifyHrefDefault = Expect<_HrefDefaultTest>;\n\n// Test: Custom Href can be specified\ntype _CustomHref = \"/settings\" | \"/main\";\ntype _HrefCustomBuilder = BlockModelV3<_TestArgs, {}, _TestData, _CustomHref>;\ntype _HrefCustomTest =\n _HrefCustomBuilder extends BlockModelV3<_TestArgs, {}, _TestData, _CustomHref> ? true : false;\ntype _VerifyHrefCustom = Expect<_HrefCustomTest>;\n\n// Test: Output type accumulation with & intersection\ntype _OutputsAccumulation = { a: ConfigRenderLambda<string> } & {\n b: ConfigRenderLambda<number>;\n};\ntype _VerifyOutputsHaveKeys = Expect<Equal<keyof _OutputsAccumulation, \"a\" | \"b\">>;\n\n// Test: Builder with all type parameters specified compiles\ntype _FullBuilder = BlockModelV3<_TestArgs, _TestOutputs, _TestData, \"/main\">;\ntype _FullBuilderTest =\n _FullBuilder extends BlockModelV3<_TestArgs, _TestOutputs, _TestData, \"/main\"> ? true : false;\ntype _VerifyFullBuilder = Expect<_FullBuilderTest>;\n\n// Test: InferOutputsFromLambdas maps outputs correctly\ntype _InferOutputsTest = InferOutputsFromLambdas<{\n myOutput: ConfigRenderLambda<number>;\n}>;\ntype _VerifyInferOutputs = Expect<\n Equal<_InferOutputsTest, { myOutput: OutputWithStatus<number> & { __unwrap: true } }>\n>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"block_model.js","names":[],"sources":["../src/block_model.ts"],"sourcesContent":["import type {\n BlockRenderingMode,\n BlockSection,\n OutputWithStatus,\n PlRef,\n BlockCodeKnownFeatureFlags,\n BlockConfigContainer,\n BlockKindReference,\n} from \"@milaboratories/pl-model-common\";\nimport { REQUIRES_PFRAMES_VERSION, formatKindRef } from \"@milaboratories/pl-model-common\";\nimport { getPlatformaInstance, isInUI, createAndRegisterRenderLambda } from \"./internal\";\nimport type { BlockKind, DataModel } from \"./block_migrations\";\nimport type { PlatformaV3 } from \"./platforma\";\nimport type { BlockDefaultUiServices } from \"./services/service_resolve\";\nimport { BLOCK_SERVICE_FLAGS } from \"./services/block_services\";\nimport type { InferRenderFunctionReturn, RenderFunction } from \"./render\";\nimport { BlockRenderCtx, PluginRenderCtx } from \"./render\";\nimport type {\n PluginData,\n PluginModel,\n PluginOutputs,\n PluginParams,\n PluginPublicOutputs,\n} from \"./plugin_model\";\nimport { PluginInstance as PluginInstanceClass, CREATE_PLUGIN_MODEL } from \"./plugin_model\";\nimport { type PluginHandle, pluginOutputKey } from \"./plugin_handle\";\nimport type { RenderCtxBase } from \"./render\";\nimport { PlatformaSDKVersion } from \"./version\";\nimport {\n applyStorageUpdate,\n getStorageDebugView,\n migrateStorage,\n createInitialStorage,\n createInitialStorageFromParams,\n validateTemplateParamsJson,\n deriveArgsFromStorage,\n derivePrerunArgsFromStorage,\n deriveTemplateParamsFromStorage,\n} from \"./block_storage_callbacks\";\nimport { type PluginName } from \"./block_storage\";\nimport type {\n ConfigRenderLambda,\n DeriveHref,\n ConfigRenderLambdaFlags,\n InferOutputsFromLambdas,\n} from \"./bconfig\";\nimport { downgradeCfgOrLambda, isConfigLambda } from \"./bconfig\";\nimport type { PlatformaExtended } from \"./platforma\";\nimport {\n BLOCK_STORAGE_FACADE_VERSION,\n BlockStorageFacadeCallbacks,\n BlockStorageFacadeHandles,\n registerFacadeCallbacks,\n} from \"./block_storage_facade\";\n\ntype SectionsExpectedType = readonly BlockSection[];\n\ntype NoOb = Record<string, never>;\n\n/**\n * Per-property lambdas for deriving plugin params from block render context.\n * Each property is a function that receives the block's RenderCtxBase and returns the param value.\n */\nexport type ParamsInput<Params, BArgs = unknown, BData = unknown> = {\n [K in keyof Params]: (ctx: RenderCtxBase<BArgs, BData>) => Params[K];\n};\n\n/**\n * Type-erased version of ParamsInput for internal storage.\n */\ntype ParamsInputErased = Record<string, (ctx: RenderCtxBase) => unknown>;\n\n/**\n * Merges two feature flag objects with type-aware logic:\n * - `supports*` (boolean): OR — `true` if either side is `true`\n * - `requires*` (numeric): MAX — take the higher version requirement\n */\nfunction mergeFeatureFlags(\n base: BlockCodeKnownFeatureFlags,\n override: BlockCodeKnownFeatureFlags,\n): BlockCodeKnownFeatureFlags {\n const result: Record<string, boolean | number | undefined> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) continue;\n const existing = result[key];\n if (typeof value === \"boolean\") {\n result[key] = (typeof existing === \"boolean\" && existing) || value;\n } else if (typeof value === \"number\") {\n result[key] = Math.max(typeof existing === \"number\" ? existing : 0, value);\n }\n }\n return result as BlockCodeKnownFeatureFlags;\n}\n\n/**\n * Plugin record: model + param derivation lambdas.\n */\nexport type PluginRecord<\n Data extends PluginData = PluginData,\n Params extends PluginParams = undefined,\n Outputs extends PluginOutputs = PluginOutputs,\n PublicOutputs extends PluginPublicOutputs = PluginPublicOutputs,\n ModelServices = unknown,\n UiServices = unknown,\n> = {\n readonly model: PluginModel<Data, Params, Outputs, PublicOutputs, ModelServices, UiServices>;\n readonly inputs: ParamsInputErased;\n};\n\ninterface BlockModelV3Config<\n OutputsCfg extends Record<string, ConfigRenderLambda>,\n Data,\n Plugins extends Record<string, PluginRecord> = {},\n Transfers extends Record<string, unknown> = {},\n Params = unknown,\n> {\n renderingMode: BlockRenderingMode;\n dataModel: DataModel<Data, Params, Transfers>;\n /** Reference to the block kind this model implements, in `{name}@{version}` form. */\n // @todo: use blockKind, `kind` super comman word\n kind: BlockKindReference | undefined;\n outputs: OutputsCfg;\n sections: ConfigRenderLambda;\n title: ConfigRenderLambda | undefined;\n subtitle: ConfigRenderLambda | undefined;\n tags: ConfigRenderLambda | undefined;\n enrichmentTargets: ConfigRenderLambda | undefined;\n featureFlags: BlockCodeKnownFeatureFlags;\n deriveArgs: ((data: unknown) => unknown) | undefined;\n derivePrerunArgs: ((data: unknown) => unknown) | undefined;\n /** Projects block data back to this kind's params for template export. */\n deriveTemplateParams: ((data: Data) => Params) | undefined;\n /**\n * The kind's runtime check for params supplied by a template. Read off the compiled\n * kind rather than declared per block: the params contract belongs to the kind, and\n * two blocks implementing it must not be able to disagree about what a valid params\n * object is. Always present — a kind cannot omit it, and a block cannot omit a kind.\n */\n parseInitializationParams: (value: unknown) => unknown;\n plugins: Plugins;\n}\n\n/** Main entry point that each block should use in it's \"config\" module. Don't forget\n * to call {@link done()} at the end of configuration. Value returned by this builder must be\n * exported as constant with name \"platforma\" from the \"config\" module.\n * API version is 3 (for UI) and 2 (for model) */\nexport class BlockModelV3<\n Args,\n OutputsCfg extends Record<string, ConfigRenderLambda>,\n Data extends Record<string, unknown> = Record<string, unknown>,\n Href extends `/${string}` = \"/\",\n Plugins extends Record<string, PluginRecord> = {},\n Transfers extends Record<string, unknown> = {},\n Params = unknown,\n> {\n private constructor(\n private readonly config: BlockModelV3Config<OutputsCfg, Data, Plugins, Transfers, Params>,\n ) {}\n\n public static readonly FEATURE_FLAGS = {\n supportsLazyState: true,\n supportsPframeQueryRanking: true,\n requiresUIAPIVersion: 3,\n requiresModelAPIVersion: BLOCK_STORAGE_FACADE_VERSION,\n requiresCreatePTable: 2,\n requiresPFramesVersion: REQUIRES_PFRAMES_VERSION,\n ...BLOCK_SERVICE_FLAGS,\n } satisfies BlockCodeKnownFeatureFlags;\n\n /** @deprecated Use FEATURE_FLAGS */\n public static readonly INITIAL_BLOCK_FEATURE_FLAGS = BlockModelV3.FEATURE_FLAGS;\n\n /**\n * Creates a new BlockModelV3 builder bound to a data model and a block kind.\n *\n * The `kind` argument is cross-checked against the kind handed to the\n * builder: its `Params` type must match at compile time (via\n * `BlockKind<Params>`), and its reference value must match at runtime. The\n * reference is baked into the config so the published manifest can advertise\n * which kind the block implements.\n *\n * @example\n * const dataModel = new DataModelBuilder({ kind })\n * .from<BlockData>(\"v1\")\n * .init(({ params }) => params ?? { numbers: [], labels: [] });\n *\n * BlockModelV3.create({ dataModel, kind })\n * .args((data) => ({ numbers: data.numbers }))\n * .sections(() => [{ type: 'link', href: '/', label: 'Main' }])\n * .done();\n */\n public static create<\n Data extends Record<string, unknown>,\n Params = never,\n Transfers extends Record<string, unknown> = {},\n >(args: {\n dataModel: DataModel<Data, Params, Transfers>;\n kind: BlockKind<Params>;\n }): BlockModelV3<NoOb, {}, Data, \"/\", {}, Transfers, Params> {\n const { dataModel, kind } = args;\n // Derive the on-wire reference from the compiled kind; the kind object has\n // no reference field of its own.\n const kindRef = formatKindRef(kind);\n\n // Runtime guard: the kind handed to the builder must match the kind handed to\n // create(). Nothing ties them together at the type level — they arrive as two\n // separately-passed objects — so a mismatch is only visible here. The builder's own\n // reference is still optional, because a PLUGIN data model is built without a kind\n // and has none to compare.\n if (dataModel.kindRef && dataModel.kindRef !== kindRef) {\n throw new Error(\n `Block kind mismatch: data model built for '${dataModel.kindRef}' but create() got '${kindRef}'`,\n );\n }\n\n return new BlockModelV3<NoOb, {}, Data, \"/\", {}, Transfers, Params>({\n renderingMode: \"Heavy\",\n dataModel,\n kind: kindRef,\n // Read off the kind, which cannot omit it — not off the data model. The two\n // are cross-checked above, so there is one source, not a precedence order.\n parseInitializationParams: kind.parseInitializationParams,\n outputs: {},\n sections: createAndRegisterRenderLambda({ handle: \"sections\", lambda: () => [] }, true),\n title: undefined,\n subtitle: undefined,\n tags: undefined,\n enrichmentTargets: undefined,\n featureFlags: { ...BlockModelV3.FEATURE_FLAGS },\n deriveArgs: undefined,\n derivePrerunArgs: undefined,\n deriveTemplateParams: undefined,\n plugins: {},\n });\n }\n\n /**\n * Add output cell wrapped with additional status information to the configuration\n *\n * @param key output cell name, that can be later used to retrieve the rendered value\n * @param rf callback calculating output value using context, that allows to access\n * workflows outputs and interact with platforma drivers\n * @param flags additional flags that may alter lambda rendering procedure\n * */\n public output<const Key extends string, const RF extends RenderFunction<Args, Data, unknown>>(\n key: Key,\n rf: RF,\n flags: ConfigRenderLambdaFlags & { withStatus: true },\n ): BlockModelV3<\n Args,\n OutputsCfg & {\n [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> & {\n withStatus: true;\n };\n },\n Data,\n Href,\n Plugins,\n Transfers,\n Params\n >;\n /**\n * Add output cell to the configuration\n *\n * @param key output cell name, that can be later used to retrieve the rendered value\n * @param rf callback calculating output value using context, that allows to access\n * workflows outputs and interact with platforma drivers\n * @param flags additional flags that may alter lambda rendering procedure\n * */\n public output<const Key extends string, const RF extends RenderFunction<Args, Data, unknown>>(\n key: Key,\n rf: RF,\n flags?: ConfigRenderLambdaFlags,\n ): BlockModelV3<\n Args,\n OutputsCfg & {\n [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>>;\n },\n Data,\n Href,\n Plugins,\n Transfers,\n Params\n >;\n public output(\n key: string,\n cfgOrRf: RenderFunction<Args, Data, unknown>,\n flags: ConfigRenderLambdaFlags = {},\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params> {\n return new BlockModelV3({\n ...this.config,\n outputs: {\n ...this.config.outputs,\n [key]: createAndRegisterRenderLambda({\n handle: `block-output#${key}`,\n lambda: () => cfgOrRf(new BlockRenderCtx<Args, Data>()),\n ...flags,\n }),\n },\n });\n }\n\n /** Shortcut for {@link output} with retentive flag set to true. */\n public retentiveOutput<\n const Key extends string,\n const RF extends RenderFunction<Args, Data, unknown>,\n >(\n key: Key,\n rf: RF,\n ): BlockModelV3<\n Args,\n OutputsCfg & {\n [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>>;\n },\n Data,\n Href,\n Plugins,\n Transfers,\n Params\n > {\n return this.output(key, rf, { retentive: true });\n }\n\n /** Shortcut for {@link output} with withStatus flag set to true. */\n public outputWithStatus<\n const Key extends string,\n const RF extends RenderFunction<Args, Data, unknown>,\n >(key: Key, rf: RF) {\n return this.output(key, rf, { withStatus: true });\n }\n\n /**\n * Sets a function to derive block args from data.\n * This is called during setData to compute the args that will be used for block execution.\n *\n * @example\n * .args<BlockArgs>((data) => ({ numbers: data.numbers }))\n *\n * @example\n * .args<BlockArgs>((data) => {\n * if (data.numbers.length === 0) throw new Error('Numbers required'); // block not ready\n * return { numbers: data.numbers };\n * })\n */\n public args<A>(\n lambda: (data: Data) => A,\n ): BlockModelV3<A, OutputsCfg, Data, Href, Plugins, Transfers, Params> {\n return new BlockModelV3<A, OutputsCfg, Data, Href, Plugins, Transfers, Params>({\n ...this.config,\n deriveArgs: lambda as (data: unknown) => unknown,\n });\n }\n\n /**\n * Sets a function to derive pre-run args from data (optional).\n * This is called during setData to compute the args that will be used for staging/pre-run phase.\n *\n * If not defined, defaults to using the args() function result.\n * If defined, uses its return value for the staging / prerun phase.\n *\n * The staging / prerun phase runs only if currentPrerunArgs differs from the executed\n * version of prerunArgs (same comparison logic as currentArgs vs prodArgs).\n *\n * @example\n * .prerunArgs((data) => ({ numbers: data.numbers }))\n *\n * @example\n * .prerunArgs((data) => {\n * // Return undefined to skip staging for this block\n * if (!data.isReady) return undefined;\n * return { numbers: data.numbers };\n * })\n */\n public prerunArgs(\n fn: (data: Data) => unknown,\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>({\n ...this.config,\n derivePrerunArgs: fn as (data: unknown) => unknown,\n });\n }\n\n /**\n * Sets the function that projects block data back to this kind's params, for\n * exporting the project as a template.\n *\n * The inverse of the data model's `init`: `init` builds data from `params`, this\n * recovers the `params` that would rebuild the current data. Return only params\n * — runtime and derived state is dropped, and the exporter supplies the rest of\n * the entry (`id`, `kind`), which this lambda cannot set.\n *\n * References are returned as ordinary `PlRef`s; the SDK rewrites them into\n * template-local form on the way out, so a block never deals with the file\n * representation.\n *\n * Required: `done()` throws without it. A block whose state cannot be reduced to\n * params returns `{}` and says so explicitly, rather than exporting an entry with\n * no params that silently applies as a default-initialized block.\n *\n * The return type is the kind's `Params`, so a block whose projection drifts\n * from its own init contract fails to compile. Available only on a\n * kind-carrying model — `create(dataModel)` without a kind leaves `Params` as\n * `unknown` and this method cannot be type-checked against anything.\n *\n * @example\n * BlockModelV3.create({ dataModel, kind })\n * .args((data) => ({ numbers: data.numbers }))\n * .templateParams((data) => ({ sources: data.sources }))\n * .done();\n */\n public templateParams(\n fn: (data: Data) => Params,\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>({\n ...this.config,\n deriveTemplateParams: fn,\n });\n }\n\n /** Sets the lambda to generate list of sections in the left block overviews panel. */\n public sections<\n const Ret extends SectionsExpectedType,\n const RF extends RenderFunction<Args, Data, Ret>,\n >(\n rf: RF,\n ): BlockModelV3<Args, OutputsCfg, Data, DeriveHref<ReturnType<RF>>, Plugins, Transfers, Params> {\n return new BlockModelV3<\n Args,\n OutputsCfg,\n Data,\n DeriveHref<ReturnType<RF>>,\n Plugins,\n Transfers,\n Params\n >({\n ...this.config,\n // Replace the default sections callback with the user-provided one\n sections: createAndRegisterRenderLambda(\n {\n handle: \"sections\",\n lambda: () => rf(new BlockRenderCtx<Args, Data>()),\n },\n true,\n ),\n });\n }\n\n /** Sets a rendering function to derive block title, shown for the block in the left blocks-overview panel. */\n public title(\n rf: RenderFunction<Args, Data, string>,\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>({\n ...this.config,\n title: createAndRegisterRenderLambda({\n handle: \"title\",\n lambda: () => rf(new BlockRenderCtx<Args, Data>()),\n }),\n });\n }\n\n public subtitle(\n rf: RenderFunction<Args, Data, string>,\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>({\n ...this.config,\n subtitle: createAndRegisterRenderLambda({\n handle: \"subtitle\",\n lambda: () => rf(new BlockRenderCtx<Args, Data>()),\n }),\n });\n }\n\n public tags(\n rf: RenderFunction<Args, Data, string[]>,\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>({\n ...this.config,\n tags: createAndRegisterRenderLambda({\n handle: \"tags\",\n lambda: () => rf(new BlockRenderCtx<Args, Data>()),\n }),\n });\n }\n\n /** Sets or overrides feature flags for the block. */\n public withFeatureFlags(\n flags: Partial<BlockCodeKnownFeatureFlags>,\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>({\n ...this.config,\n featureFlags: { ...this.config.featureFlags, ...flags },\n });\n }\n\n /**\n * Defines how to derive list of upstream references this block is meant to enrich with its exports from block args.\n * Influences dependency graph construction.\n */\n public enriches(\n lambda: (args: Args) => PlRef[],\n ): BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params> {\n return new BlockModelV3<Args, OutputsCfg, Data, Href, Plugins, Transfers, Params>({\n ...this.config,\n enrichmentTargets: createAndRegisterRenderLambda({\n handle: \"enrichmentTargets\",\n lambda: lambda,\n }),\n });\n }\n\n /**\n * Registers a plugin instance with the block.\n * Consumes a transfer if one was defined for this plugin ID in the migration chain.\n *\n * Type checks:\n * - If Transfers[Id] exists, verifies it extends PTransferData (transfer type compatibility)\n * - If no Transfers[Id], rejects plugins with transferAt set (missing .transfer() in data model)\n * - Rejects duplicate plugin IDs (Id already in keyof Plugins)\n *\n * @param instance - PluginInstance created via factory.create({ pluginId, ... })\n * @param params - Per-property lambdas deriving plugin params from block RenderCtx\n *\n * @example\n * .plugin(mainTable, {\n * columns: (ctx) => ctx.outputs?.resolve(\"data\")?.getPColumns(),\n * sourceId: (ctx) => ctx.data.selectedSource,\n * })\n */\n public plugin<\n const PluginId extends string,\n PData extends PluginData,\n PParams extends PluginParams,\n POutputs extends PluginOutputs,\n PPublicOutputs extends PluginPublicOutputs,\n PTransferData,\n PluginModelServices,\n PluginUiServices,\n >(\n instance: PluginInstanceClass<\n PluginId &\n (PluginId extends keyof Transfers\n ? Transfers[PluginId] extends PTransferData\n ? string\n : never\n : [PTransferData] extends [never]\n ? string\n : never) &\n (PluginId extends keyof Plugins ? never : string),\n PData,\n PParams,\n POutputs,\n PPublicOutputs,\n PTransferData,\n PluginModelServices,\n PluginUiServices\n >,\n params?: ParamsInput<PParams, Args, Data>,\n ): BlockModelV3<\n Args,\n OutputsCfg,\n Data,\n Href,\n Plugins & {\n [K in PluginId]: PluginRecord<\n PData,\n PParams,\n POutputs,\n PPublicOutputs,\n PluginModelServices,\n PluginUiServices\n >;\n },\n Omit<Transfers, PluginId>,\n Params\n >;\n public plugin(\n instance: PluginInstanceClass,\n params?: ParamsInput<Record<string, unknown>, unknown, unknown>,\n ): BlockModelV3<\n Args,\n OutputsCfg,\n Data,\n Href,\n Record<string, PluginRecord>,\n Record<string, unknown>,\n Params\n > {\n const pluginId = instance.id;\n const plugin = instance[CREATE_PLUGIN_MODEL]();\n const resolvedParams = (params ?? {}) as ParamsInputErased;\n\n if (pluginId in this.config.plugins) {\n throw new Error(`Plugin '${pluginId}' already registered`);\n }\n\n const registered: PluginRecord = {\n model: plugin,\n inputs: resolvedParams,\n };\n\n return new BlockModelV3({\n ...this.config,\n plugins: {\n ...this.config.plugins,\n [pluginId]: registered,\n },\n featureFlags: mergeFeatureFlags(this.config.featureFlags, plugin.featureFlags ?? {}),\n });\n }\n\n /** Renders all provided block settings into a pre-configured platforma API\n * instance, that can be used in frontend to interact with block data, and\n * other features provided by the platforma to the block.\n *\n * Type-level check: if there are unconsumed transfers (from `.transfer()` calls\n * in the migration chain), this method requires an impossible `never` argument,\n * producing a compile error. Register all transferred plugins via `.plugin(instance)`\n * before calling `.done()`.\n */\n public done(\n ..._: keyof Transfers extends never ? [] : [never]\n ): PlatformaExtended<\n PlatformaV3<\n Data,\n Args,\n InferOutputsFromLambdas<OutputsCfg>,\n Href,\n Plugins,\n BlockDefaultUiServices\n >\n > {\n if (this.config.deriveArgs === undefined) throw new Error(\"Args rendering function not set.\");\n if (this.config.deriveTemplateParams === undefined)\n throw new Error(\n \"templateParams() not set. Every block must project its state back to its kind's params, \" +\n \"so a project can be exported as a template and re-applied; a block whose state carries \" +\n \"nothing worth restoring returns {}.\",\n );\n\n const apiVersion = 3;\n\n // Build plugin registry\n const { plugins } = this.config;\n const pluginRegistry: Record<string, PluginName> = {};\n const pluginHandles = Object.keys(plugins) as PluginHandle[];\n for (const handle of pluginHandles) {\n pluginRegistry[handle] = plugins[handle].model.name;\n }\n\n const {\n dataModel,\n deriveArgs,\n derivePrerunArgs,\n deriveTemplateParams,\n parseInitializationParams,\n } = this.config;\n\n function getPlugin(handle: PluginHandle): PluginRecord {\n const plugin = plugins[handle];\n if (!plugin) throw new Error(`Plugin model not found for '${handle}'`);\n return plugin;\n }\n\n // Register ALL facade callbacks here, with dependencies captured via closures\n registerFacadeCallbacks({\n [BlockStorageFacadeCallbacks.StorageApplyUpdate]: applyStorageUpdate,\n [BlockStorageFacadeCallbacks.StorageDebugView]: getStorageDebugView,\n [BlockStorageFacadeCallbacks.StorageMigrate]: (currentStorageJson) =>\n migrateStorage(currentStorageJson, {\n migrateBlockData: (v) => dataModel.migrate(v),\n getPluginRegistry: () => pluginRegistry,\n migratePluginData: (handle, v) => getPlugin(handle).model.dataModel.migrate(v),\n createPluginData: (handle, transfer) => {\n if (transfer) return transfer;\n return getPlugin(handle).model.getDefaultData();\n },\n }),\n [BlockStorageFacadeCallbacks.StorageInitial]: () =>\n createInitialStorage({\n getDefaultBlockData: () => dataModel.getDefaultData(),\n getPluginRegistry: () => pluginRegistry,\n createPluginData: (handle) => getPlugin(handle).model.getDefaultData(),\n }),\n [BlockStorageFacadeCallbacks.ArgsDerive]: (storageJson) =>\n deriveArgsFromStorage(storageJson, deriveArgs),\n [BlockStorageFacadeCallbacks.PrerunArgsDerive]: (storageJson) =>\n derivePrerunArgsFromStorage(storageJson, deriveArgs, derivePrerunArgs),\n [BlockStorageFacadeCallbacks.InitializationParamsDerive]: (storageJson) =>\n deriveTemplateParamsFromStorage(\n storageJson,\n deriveTemplateParams as (data: unknown) => unknown,\n ),\n [BlockStorageFacadeCallbacks.StorageInitialFromParams]: (paramsJson, blockIdsJson) =>\n createInitialStorageFromParams(paramsJson, blockIdsJson, {\n getBlockDataFromParams: (params) => dataModel.getDataFromParams(params),\n getPluginRegistry: () => pluginRegistry,\n createPluginData: (handle) => getPlugin(handle).model.getDefaultData(),\n parseInitializationParams,\n }),\n [BlockStorageFacadeCallbacks.InitializationParamsValidate]: (paramsJson) =>\n validateTemplateParamsJson(paramsJson, parseInitializationParams),\n });\n\n // Register plugin input and output lambdas\n const pluginOutputs: Record<string, ConfigRenderLambda> = {};\n for (const handle of pluginHandles) {\n const { model, inputs } = plugins[handle];\n // Wrap plugin param lambdas: close over BlockRenderCtx creation\n const wrappedInputs: Record<string, () => unknown> = {};\n for (const [paramKey, paramFn] of Object.entries(inputs)) {\n wrappedInputs[paramKey] = () => paramFn(new BlockRenderCtx());\n }\n\n // Register plugin outputs (in config pack, evaluated by middle layer)\n const outputs = model.outputs as Record<string, (ctx: PluginRenderCtx) => unknown>;\n for (const [outputKey, outputFn] of Object.entries(outputs)) {\n const key = pluginOutputKey(handle, outputKey);\n pluginOutputs[key] = createAndRegisterRenderLambda({\n handle: key,\n lambda: () => outputFn(new PluginRenderCtx(handle, wrappedInputs)),\n withStatus: true,\n });\n }\n }\n const allOutputs = { ...this.config.outputs, ...pluginOutputs };\n\n globalThis.platformaApiVersion = apiVersion;\n\n if (!isInUI()) {\n const blockConfig: BlockConfigContainer = {\n v4: {\n configVersion: 4,\n modelAPIVersion: BLOCK_STORAGE_FACADE_VERSION,\n sdkVersion: PlatformaSDKVersion,\n renderingMode: this.config.renderingMode,\n sections: this.config.sections,\n title: this.config.title,\n subtitle: this.config.subtitle,\n tags: this.config.tags,\n outputs: allOutputs,\n enrichmentTargets: this.config.enrichmentTargets,\n featureFlags: this.config.featureFlags,\n blockLifecycleCallbacks: { ...BlockStorageFacadeHandles },\n },\n\n // Block-kind identity, baked at the container level beside `code`\n // (orthogonal to which render envelope applies). Rides into model.json\n // via the JSON.stringify(config) in build-model.ts — no write-path change.\n kind: this.config.kind,\n\n // fields below are added to allow previous desktop versions read generated configs\n sdkVersion: PlatformaSDKVersion,\n renderingMode: this.config.renderingMode,\n sections: this.config.sections,\n outputs: Object.fromEntries(\n Object.entries(this.config.outputs).map(([key, value]) => [\n key,\n downgradeCfgOrLambda(value),\n ]),\n ),\n };\n // we are in the configuration rendering routine, not in actual UI\n return { config: blockConfig } as any;\n // normal operation inside the UI\n } else {\n return {\n ...getPlatformaInstance({\n sdkVersion: PlatformaSDKVersion,\n apiVersion,\n }),\n blockModelInfo: {\n outputs: Object.fromEntries(\n Object.entries(allOutputs).map(([key, value]) => [\n key,\n {\n withStatus: Boolean(isConfigLambda(value) && value.withStatus),\n },\n ]),\n ),\n pluginIds: pluginHandles,\n featureFlags: this.config.featureFlags,\n pluginPublicOutputs: Object.fromEntries(\n pluginHandles.map((handle) => [handle, plugins[handle].model.publicOutputDef]),\n ),\n },\n } as any;\n }\n }\n}\n\n// Type tests for BlockModelV3\n\nexport type Expect<T extends true> = T;\n\nexport type Equal<X, Y> =\n (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;\n\nexport type Merge<A, B> = {\n [K in keyof A | keyof B]: K extends keyof B ? B[K] : K extends keyof A ? A[K] : never;\n};\n\n// Helper types for testing\ntype _TestArgs = { inputFile: string; threshold: number };\ntype _TestData = { selectedTab: string };\ntype _TestOutputs = {\n result: ConfigRenderLambda<string>;\n count: ConfigRenderLambda<number>;\n};\n\n// Test: Merge type works correctly\ntype _MergeTest1 = Expect<Equal<Merge<{ a: 1 }, { b: 2 }>, { a: 1; b: 2 }>>;\ntype _MergeTest2 = Expect<Equal<Merge<{ a: 1 }, { a: 2 }>, { a: 2 }>>;\ntype _MergeTest3 = Expect<Equal<Merge<{ a: 1; b: 1 }, { b: 2; c: 3 }>, { a: 1; b: 2; c: 3 }>>;\n\n// Test: create() returns a BlockModelV3 instance\n// Note: Due to function overloads, ReturnType uses the last overload signature.\n// We verify the structure is correct using a simpler assignability test.\ntype _CreateResult = ReturnType<typeof BlockModelV3.create>;\ntype _CreateIsBlockModelV3 =\n _CreateResult extends BlockModelV3<infer _A, infer _O, infer _S> ? true : false;\ntype _CreateTest = Expect<_CreateIsBlockModelV3>;\n\n// Test: BlockModelV3Config interface structure (default generics)\ntype _ConfigTest = Expect<\n Equal<\n BlockModelV3Config<_TestOutputs, _TestData>,\n {\n renderingMode: BlockRenderingMode;\n deriveArgs: ((data: unknown) => unknown) | undefined;\n derivePrerunArgs: ((data: unknown) => unknown) | undefined;\n deriveTemplateParams: ((data: _TestData) => unknown) | undefined;\n parseInitializationParams: (value: unknown) => unknown;\n dataModel: DataModel<_TestData, unknown, {}>;\n kind: BlockKindReference | undefined;\n outputs: _TestOutputs;\n sections: ConfigRenderLambda;\n title: ConfigRenderLambda | undefined;\n subtitle: ConfigRenderLambda | undefined;\n tags: ConfigRenderLambda | undefined;\n enrichmentTargets: ConfigRenderLambda | undefined;\n featureFlags: BlockCodeKnownFeatureFlags;\n plugins: {};\n }\n >\n>;\n\n// Test: Default Href is '/'\ntype _HrefDefaultTest =\n BlockModelV3<_TestArgs, {}, _TestData> extends BlockModelV3<_TestArgs, {}, _TestData, \"/\">\n ? true\n : false;\ntype _VerifyHrefDefault = Expect<_HrefDefaultTest>;\n\n// Test: Custom Href can be specified\ntype _CustomHref = \"/settings\" | \"/main\";\ntype _HrefCustomBuilder = BlockModelV3<_TestArgs, {}, _TestData, _CustomHref>;\ntype _HrefCustomTest =\n _HrefCustomBuilder extends BlockModelV3<_TestArgs, {}, _TestData, _CustomHref> ? true : false;\ntype _VerifyHrefCustom = Expect<_HrefCustomTest>;\n\n// Test: Output type accumulation with & intersection\ntype _OutputsAccumulation = { a: ConfigRenderLambda<string> } & {\n b: ConfigRenderLambda<number>;\n};\ntype _VerifyOutputsHaveKeys = Expect<Equal<keyof _OutputsAccumulation, \"a\" | \"b\">>;\n\n// Test: Builder with all type parameters specified compiles\ntype _FullBuilder = BlockModelV3<_TestArgs, _TestOutputs, _TestData, \"/main\">;\ntype _FullBuilderTest =\n _FullBuilder extends BlockModelV3<_TestArgs, _TestOutputs, _TestData, \"/main\"> ? true : false;\ntype _VerifyFullBuilder = Expect<_FullBuilderTest>;\n\n// Test: InferOutputsFromLambdas maps outputs correctly\ntype _InferOutputsTest = InferOutputsFromLambdas<{\n myOutput: ConfigRenderLambda<number>;\n}>;\ntype _VerifyInferOutputs = Expect<\n Equal<_InferOutputsTest, { myOutput: OutputWithStatus<number> & { __unwrap: true } }>\n>;\n"],"mappings":"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"}