@platforma-sdk/model 1.56.0 → 1.57.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/block_model.cjs +27 -8
- package/dist/block_model.cjs.map +1 -1
- package/dist/block_model.d.ts.map +1 -1
- package/dist/block_model.js +28 -9
- package/dist/block_model.js.map +1 -1
- package/dist/block_storage.cjs +8 -5
- package/dist/block_storage.cjs.map +1 -1
- package/dist/block_storage.d.ts +6 -4
- package/dist/block_storage.d.ts.map +1 -1
- package/dist/block_storage.js +8 -5
- package/dist/block_storage.js.map +1 -1
- package/dist/components/PlDataTable/index.d.ts +1 -1
- package/dist/components/PlDataTable/index.d.ts.map +1 -1
- package/dist/components/PlDataTable/table.cjs +16 -1
- package/dist/components/PlDataTable/table.cjs.map +1 -1
- package/dist/components/PlDataTable/table.d.ts.map +1 -1
- package/dist/components/PlDataTable/table.js +16 -2
- package/dist/components/PlDataTable/table.js.map +1 -1
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/package.json.cjs +1 -1
- package/dist/package.json.js +1 -1
- package/dist/pframe_utils/columns.cjs +1 -0
- package/dist/pframe_utils/columns.cjs.map +1 -1
- package/dist/pframe_utils/columns.js +1 -0
- package/dist/pframe_utils/columns.js.map +1 -1
- package/dist/pframe_utils/index.cjs +1 -0
- package/dist/pframe_utils/index.cjs.map +1 -1
- package/dist/pframe_utils/index.js +1 -0
- package/dist/pframe_utils/index.js.map +1 -1
- package/dist/plugin_model.cjs.map +1 -1
- package/dist/plugin_model.d.ts +1 -14
- package/dist/plugin_model.d.ts.map +1 -1
- package/dist/plugin_model.js.map +1 -1
- package/dist/render/api.cjs +42 -2
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +22 -2
- package/dist/render/api.d.ts.map +1 -1
- package/dist/render/api.js +42 -3
- package/dist/render/api.js.map +1 -1
- package/package.json +6 -6
- package/src/block_model.ts +30 -9
- package/src/block_storage.test.ts +4 -2
- package/src/block_storage.ts +8 -8
- package/src/components/PlDataTable/index.ts +6 -1
- package/src/components/PlDataTable/table.ts +3 -4
- package/src/index.ts +0 -1
- package/src/plugin_model.ts +1 -19
- package/src/render/api.ts +52 -2
package/src/block_model.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { getPlatformaInstance, isInUI, createAndRegisterRenderLambda } from "./i
|
|
|
10
10
|
import type { DataModel } from "./block_migrations";
|
|
11
11
|
import type { PlatformaV3 } from "./platforma";
|
|
12
12
|
import type { InferRenderFunctionReturn, RenderFunction } from "./render";
|
|
13
|
-
import {
|
|
13
|
+
import { BlockRenderCtx, PluginRenderCtx } from "./render";
|
|
14
14
|
import type { PluginModel } from "./plugin_model";
|
|
15
15
|
import type { RenderCtxBase } from "./render";
|
|
16
16
|
import { PlatformaSDKVersion } from "./version";
|
|
@@ -192,8 +192,8 @@ export class BlockModelV3<
|
|
|
192
192
|
outputs: {
|
|
193
193
|
...this.config.outputs,
|
|
194
194
|
[key]: createAndRegisterRenderLambda({
|
|
195
|
-
handle: `output#${key}`,
|
|
196
|
-
lambda: () => cfgOrRf(new
|
|
195
|
+
handle: `block-output#${key}`,
|
|
196
|
+
lambda: () => cfgOrRf(new BlockRenderCtx<Args, Data>()),
|
|
197
197
|
...flags,
|
|
198
198
|
}),
|
|
199
199
|
},
|
|
@@ -287,7 +287,7 @@ export class BlockModelV3<
|
|
|
287
287
|
...this.config,
|
|
288
288
|
// Replace the default sections callback with the user-provided one
|
|
289
289
|
sections: createAndRegisterRenderLambda(
|
|
290
|
-
{ handle: "sections", lambda: () => rf(new
|
|
290
|
+
{ handle: "sections", lambda: () => rf(new BlockRenderCtx<Args, Data>()) },
|
|
291
291
|
true,
|
|
292
292
|
),
|
|
293
293
|
});
|
|
@@ -301,7 +301,7 @@ export class BlockModelV3<
|
|
|
301
301
|
...this.config,
|
|
302
302
|
title: createAndRegisterRenderLambda({
|
|
303
303
|
handle: "title",
|
|
304
|
-
lambda: () => rf(new
|
|
304
|
+
lambda: () => rf(new BlockRenderCtx<Args, Data>()),
|
|
305
305
|
}),
|
|
306
306
|
});
|
|
307
307
|
}
|
|
@@ -313,7 +313,7 @@ export class BlockModelV3<
|
|
|
313
313
|
...this.config,
|
|
314
314
|
subtitle: createAndRegisterRenderLambda({
|
|
315
315
|
handle: "subtitle",
|
|
316
|
-
lambda: () => rf(new
|
|
316
|
+
lambda: () => rf(new BlockRenderCtx<Args, Data>()),
|
|
317
317
|
}),
|
|
318
318
|
});
|
|
319
319
|
}
|
|
@@ -325,7 +325,7 @@ export class BlockModelV3<
|
|
|
325
325
|
...this.config,
|
|
326
326
|
tags: createAndRegisterRenderLambda({
|
|
327
327
|
handle: "tags",
|
|
328
|
-
lambda: () => rf(new
|
|
328
|
+
lambda: () => rf(new BlockRenderCtx<Args, Data>()),
|
|
329
329
|
}),
|
|
330
330
|
});
|
|
331
331
|
}
|
|
@@ -458,6 +458,27 @@ export class BlockModelV3<
|
|
|
458
458
|
derivePrerunArgsFromStorage(storageJson, argsFunction, prerunArgsFunction),
|
|
459
459
|
});
|
|
460
460
|
|
|
461
|
+
// Register plugin input and output lambdas
|
|
462
|
+
const pluginOutputs: Record<string, ConfigRenderLambda> = {};
|
|
463
|
+
for (const [pluginId, { model, inputs }] of Object.entries(plugins)) {
|
|
464
|
+
// Wrap plugin param lambdas: close over BlockRenderCtx creation
|
|
465
|
+
const wrappedInputs: Record<string, () => unknown> = {};
|
|
466
|
+
for (const [paramKey, paramFn] of Object.entries(inputs)) {
|
|
467
|
+
wrappedInputs[paramKey] = () => paramFn(new BlockRenderCtx());
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Register plugin outputs (in config pack, evaluated by middle layer)
|
|
471
|
+
const outputs = model.outputs as Record<string, (ctx: PluginRenderCtx) => unknown>;
|
|
472
|
+
for (const [outputKey, outputFn] of Object.entries(outputs)) {
|
|
473
|
+
const key = `plugin-output#${pluginId}#${outputKey}`;
|
|
474
|
+
pluginOutputs[key] = createAndRegisterRenderLambda({
|
|
475
|
+
handle: key,
|
|
476
|
+
lambda: () => outputFn(new PluginRenderCtx(pluginId, wrappedInputs)),
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
const allOutputs = { ...this.config.outputs, ...pluginOutputs };
|
|
481
|
+
|
|
461
482
|
const blockConfig: BlockConfigContainer = {
|
|
462
483
|
v4: {
|
|
463
484
|
configVersion: 4,
|
|
@@ -468,7 +489,7 @@ export class BlockModelV3<
|
|
|
468
489
|
title: this.config.title,
|
|
469
490
|
subtitle: this.config.subtitle,
|
|
470
491
|
tags: this.config.tags,
|
|
471
|
-
outputs:
|
|
492
|
+
outputs: allOutputs,
|
|
472
493
|
enrichmentTargets: this.config.enrichmentTargets,
|
|
473
494
|
featureFlags: this.config.featureFlags,
|
|
474
495
|
blockLifecycleCallbacks: { ...BlockStorageFacadeHandles },
|
|
@@ -500,7 +521,7 @@ export class BlockModelV3<
|
|
|
500
521
|
}),
|
|
501
522
|
blockModelInfo: {
|
|
502
523
|
outputs: Object.fromEntries(
|
|
503
|
-
Object.entries(
|
|
524
|
+
Object.entries(allOutputs).map(([key, value]) => [
|
|
504
525
|
key,
|
|
505
526
|
{
|
|
506
527
|
withStatus: Boolean(isConfigLambda(value) && value.withStatus),
|
|
@@ -218,8 +218,10 @@ describe("BlockStorage", () => {
|
|
|
218
218
|
expect(getPluginData(storage, "chart1")).toEqual({ type: "bar" });
|
|
219
219
|
});
|
|
220
220
|
|
|
221
|
-
it("getPluginData should
|
|
222
|
-
expect(getPluginData(baseStorage, "nonexistent")).
|
|
221
|
+
it("getPluginData should throw for missing plugin", () => {
|
|
222
|
+
expect(() => getPluginData(baseStorage, "nonexistent")).toThrow(
|
|
223
|
+
"Plugin 'nonexistent' not found in block storage",
|
|
224
|
+
);
|
|
223
225
|
});
|
|
224
226
|
|
|
225
227
|
it("should not modify original storage (immutability)", () => {
|
package/src/block_storage.ts
CHANGED
|
@@ -381,17 +381,17 @@ export function migrateBlockStorage(
|
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
/**
|
|
384
|
-
* Gets plugin-specific data from
|
|
384
|
+
* Gets plugin-specific data from block storage.
|
|
385
|
+
* Accepts raw storage (any format) and normalizes internally.
|
|
385
386
|
*
|
|
386
|
-
* @param
|
|
387
|
+
* @param rawStorage - Raw block storage (may be legacy format or BlockStorage)
|
|
387
388
|
* @param pluginId - The plugin instance id
|
|
388
|
-
* @returns The plugin data
|
|
389
|
+
* @returns The plugin data
|
|
390
|
+
* @throws If pluginId is not found in storage
|
|
389
391
|
*/
|
|
390
|
-
export function getPluginData<TData = unknown>(
|
|
391
|
-
storage
|
|
392
|
-
pluginId: string,
|
|
393
|
-
): TData | undefined {
|
|
392
|
+
export function getPluginData<TData = unknown>(rawStorage: unknown, pluginId: string): TData {
|
|
393
|
+
const storage = normalizeBlockStorage(rawStorage);
|
|
394
394
|
const pluginEntry = storage.__plugins?.[pluginId];
|
|
395
|
-
if (!pluginEntry)
|
|
395
|
+
if (!pluginEntry) throw new Error(`Plugin '${pluginId}' not found in block storage`);
|
|
396
396
|
return pluginEntry.__data as TData;
|
|
397
397
|
}
|
|
@@ -21,4 +21,9 @@ export {
|
|
|
21
21
|
createPlDataTableStateV2,
|
|
22
22
|
} from "./state-migration";
|
|
23
23
|
|
|
24
|
-
export {
|
|
24
|
+
export {
|
|
25
|
+
isColumnHidden,
|
|
26
|
+
isColumnOptional,
|
|
27
|
+
createPlDataTableV2,
|
|
28
|
+
createPlDataTableSheet,
|
|
29
|
+
} from "./table";
|
|
@@ -39,6 +39,7 @@ import type { PlDataTableStateV2 } from "./state-migration";
|
|
|
39
39
|
import type { PlDataTableSheet } from "./v5";
|
|
40
40
|
import { getAllLabelColumns, getMatchingLabelColumns } from "./labels";
|
|
41
41
|
import { collectFilterSpecColumns } from "../../filters/traverse";
|
|
42
|
+
import { isEmpty } from "es-toolkit/compat";
|
|
42
43
|
|
|
43
44
|
/** Convert a PTableColumnId to a SpecQueryExpression reference. */
|
|
44
45
|
function columnIdToExpr(col: PTableColumnId): SpecQueryExpression {
|
|
@@ -198,10 +199,8 @@ export function createPlDataTableV2<A, U>(
|
|
|
198
199
|
);
|
|
199
200
|
|
|
200
201
|
// -- Sorting validation --
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
(s) => canonicalizeJson<PTableColumnId>(s.column),
|
|
204
|
-
);
|
|
202
|
+
const userSorting = tableStateNormalized.pTableParams.sorting;
|
|
203
|
+
const sorting = (isEmpty(userSorting) ? ops?.sorting : userSorting) ?? [];
|
|
205
204
|
const firstInvalidSortingColumn = sorting.find(
|
|
206
205
|
(s) => !isValidColumnId(canonicalizeJson<PTableColumnId>(s.column)),
|
|
207
206
|
);
|
package/src/index.ts
CHANGED
|
@@ -15,7 +15,6 @@ export {
|
|
|
15
15
|
} from "./block_migrations";
|
|
16
16
|
export type { LegacyV1State } from "./block_migrations";
|
|
17
17
|
export { PluginModel } from "./plugin_model";
|
|
18
|
-
export type { PluginRenderCtx } from "./plugin_model";
|
|
19
18
|
export * from "./bconfig";
|
|
20
19
|
export * from "./components";
|
|
21
20
|
export * from "./config";
|
package/src/plugin_model.ts
CHANGED
|
@@ -9,29 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
import type { DataModel } from "./block_migrations";
|
|
11
11
|
import type { PluginName } from "./block_storage";
|
|
12
|
-
import type {
|
|
12
|
+
import type { PluginRenderCtx } from "./render";
|
|
13
13
|
|
|
14
14
|
/** Symbol for internal builder creation method */
|
|
15
15
|
const FROM_BUILDER = Symbol("fromBuilder");
|
|
16
16
|
|
|
17
|
-
// =============================================================================
|
|
18
|
-
// Plugin Render Context
|
|
19
|
-
// =============================================================================
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Context passed to plugin output functions.
|
|
23
|
-
* Provides access to plugin's persistent data, params derived from block context,
|
|
24
|
-
* and the result pool for accessing workflow outputs.
|
|
25
|
-
*/
|
|
26
|
-
export interface PluginRenderCtx<Data, Params = undefined> {
|
|
27
|
-
/** Plugin's persistent data */
|
|
28
|
-
readonly data: Data;
|
|
29
|
-
/** Params derived from block's RenderCtx */
|
|
30
|
-
readonly params: Params;
|
|
31
|
-
/** Result pool for accessing workflow outputs */
|
|
32
|
-
readonly resultPool: ResultPool;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
17
|
// =============================================================================
|
|
36
18
|
// Plugin Type
|
|
37
19
|
// =============================================================================
|
package/src/render/api.ts
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
AnchoredIdDeriver,
|
|
31
31
|
collectSpecQueryColumns,
|
|
32
32
|
ensurePColumn,
|
|
33
|
+
parseJson,
|
|
33
34
|
extractAllColumns,
|
|
34
35
|
isDataInfo,
|
|
35
36
|
isPColumn,
|
|
@@ -48,6 +49,7 @@ import {
|
|
|
48
49
|
import canonicalize from "canonicalize";
|
|
49
50
|
import type { Optional } from "utility-types";
|
|
50
51
|
import { getCfgRenderCtx } from "../internal";
|
|
52
|
+
import { getPluginData } from "../block_storage";
|
|
51
53
|
import { TreeNodeAccessor, ifDef } from "./accessor";
|
|
52
54
|
import type { FutureRef } from "./future";
|
|
53
55
|
import type { AccessorHandle, GlobalCfgRenderCtx } from "./internal";
|
|
@@ -711,7 +713,7 @@ export abstract class RenderCtxBase<Args = unknown, Data = unknown> {
|
|
|
711
713
|
}
|
|
712
714
|
|
|
713
715
|
/** Main entry point to the API available within model lambdas (like outputs, sections, etc..) for v3+ blocks */
|
|
714
|
-
export class
|
|
716
|
+
export class BlockRenderCtx<Args = unknown, Data = unknown> extends RenderCtxBase<Args, Data> {
|
|
715
717
|
private argsCache?: { v: Args | undefined };
|
|
716
718
|
public get args(): Args | undefined {
|
|
717
719
|
if (this.argsCache === undefined) {
|
|
@@ -751,8 +753,56 @@ export class RenderCtxLegacy<Args = unknown, UiState = unknown> extends RenderCt
|
|
|
751
753
|
}
|
|
752
754
|
}
|
|
753
755
|
|
|
756
|
+
/**
|
|
757
|
+
* Render context for plugin output functions.
|
|
758
|
+
* Reads plugin data from blockStorage and derives params from pre-wrapped input callbacks.
|
|
759
|
+
*/
|
|
760
|
+
export class PluginRenderCtx<Data = unknown, Params = unknown> {
|
|
761
|
+
private readonly ctx: GlobalCfgRenderCtx;
|
|
762
|
+
private readonly pluginId: string;
|
|
763
|
+
private readonly wrappedInputs: Record<string, () => unknown>;
|
|
764
|
+
|
|
765
|
+
constructor(pluginId: string, wrappedInputs: Record<string, () => unknown>) {
|
|
766
|
+
this.ctx = getCfgRenderCtx();
|
|
767
|
+
this.pluginId = pluginId;
|
|
768
|
+
this.wrappedInputs = wrappedInputs;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
private dataCache?: { v: Data };
|
|
772
|
+
|
|
773
|
+
/** Plugin's persistent data from blockStorage.__plugins.{pluginId}.__data */
|
|
774
|
+
public get data(): Data {
|
|
775
|
+
if (this.dataCache === undefined) {
|
|
776
|
+
const raw = this.ctx.blockStorage();
|
|
777
|
+
const pluginData = getPluginData<Data>(parseJson(raw), this.pluginId);
|
|
778
|
+
this.dataCache = { v: pluginData };
|
|
779
|
+
}
|
|
780
|
+
return this.dataCache.v;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
private paramsCache?: { v: Params };
|
|
784
|
+
|
|
785
|
+
/** Params derived from block context via pre-wrapped input callbacks */
|
|
786
|
+
public get params(): Params {
|
|
787
|
+
if (this.paramsCache === undefined) {
|
|
788
|
+
const result: Record<string, unknown> = {};
|
|
789
|
+
for (const [key, fn] of Object.entries(this.wrappedInputs)) {
|
|
790
|
+
result[key] = fn();
|
|
791
|
+
}
|
|
792
|
+
this.paramsCache = { v: result as Params };
|
|
793
|
+
}
|
|
794
|
+
return this.paramsCache.v;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/** Result pool — same as block, from cfgRenderCtx methods */
|
|
798
|
+
public readonly resultPool = new ResultPool();
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/** @deprecated Use BlockRenderCtx instead */
|
|
802
|
+
export type RenderCtx<Args = unknown, Data = unknown> = BlockRenderCtx<Args, Data>;
|
|
803
|
+
|
|
754
804
|
export type RenderFunction<Args = unknown, State = unknown, Ret = unknown> = (
|
|
755
|
-
rCtx:
|
|
805
|
+
rCtx: BlockRenderCtx<Args, State>,
|
|
756
806
|
) => Ret;
|
|
757
807
|
|
|
758
808
|
export type RenderFunctionLegacy<Args = unknown, State = unknown, Ret = unknown> = (
|