@platforma-sdk/model 1.51.9 → 1.52.3
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/bconfig/lambdas.d.ts +26 -4
- package/dist/bconfig/lambdas.d.ts.map +1 -1
- package/dist/bconfig/v3.d.ts +4 -2
- package/dist/bconfig/v3.d.ts.map +1 -1
- package/dist/block_api_v3.d.ts +32 -0
- package/dist/block_api_v3.d.ts.map +1 -0
- package/dist/block_migrations.cjs +138 -0
- package/dist/block_migrations.cjs.map +1 -0
- package/dist/block_migrations.d.ts +79 -0
- package/dist/block_migrations.d.ts.map +1 -0
- package/dist/block_migrations.js +136 -0
- package/dist/block_migrations.js.map +1 -0
- package/dist/block_model.cjs +222 -0
- package/dist/block_model.cjs.map +1 -0
- package/dist/block_model.d.ts +132 -0
- package/dist/block_model.d.ts.map +1 -0
- package/dist/block_model.js +220 -0
- package/dist/block_model.js.map +1 -0
- package/dist/block_storage.cjs +244 -0
- package/dist/block_storage.cjs.map +1 -0
- package/dist/block_storage.d.ts +208 -0
- package/dist/block_storage.d.ts.map +1 -0
- package/dist/block_storage.js +225 -0
- package/dist/block_storage.js.map +1 -0
- package/dist/block_storage_vm.cjs +264 -0
- package/dist/block_storage_vm.cjs.map +1 -0
- package/dist/block_storage_vm.d.ts +67 -0
- package/dist/block_storage_vm.d.ts.map +1 -0
- package/dist/block_storage_vm.js +260 -0
- package/dist/block_storage_vm.js.map +1 -0
- package/dist/builder.cjs +9 -6
- package/dist/builder.cjs.map +1 -1
- package/dist/builder.d.ts +15 -30
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +10 -7
- package/dist/builder.js.map +1 -1
- package/dist/components/PFrameForGraphs.cjs.map +1 -1
- package/dist/components/PFrameForGraphs.d.ts +2 -2
- package/dist/components/PFrameForGraphs.d.ts.map +1 -1
- package/dist/components/PFrameForGraphs.js.map +1 -1
- package/dist/components/PlDataTable.cjs.map +1 -1
- package/dist/components/PlDataTable.d.ts +3 -3
- package/dist/components/PlDataTable.d.ts.map +1 -1
- package/dist/components/PlDataTable.js.map +1 -1
- package/dist/index.cjs +25 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +38 -0
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.ts +21 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +36 -1
- package/dist/internal.js.map +1 -1
- package/dist/package.json.cjs +1 -1
- package/dist/package.json.js +1 -1
- package/dist/pframe_utils/columns.cjs.map +1 -1
- package/dist/pframe_utils/columns.d.ts +3 -3
- package/dist/pframe_utils/columns.d.ts.map +1 -1
- package/dist/pframe_utils/columns.js.map +1 -1
- package/dist/platforma.d.ts +18 -3
- package/dist/platforma.d.ts.map +1 -1
- package/dist/render/api.cjs +43 -16
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +19 -7
- package/dist/render/api.d.ts.map +1 -1
- package/dist/render/api.js +42 -17
- package/dist/render/api.js.map +1 -1
- package/dist/render/internal.cjs.map +1 -1
- package/dist/render/internal.d.ts +3 -1
- package/dist/render/internal.d.ts.map +1 -1
- package/dist/render/internal.js.map +1 -1
- package/package.json +7 -7
- package/src/bconfig/lambdas.ts +35 -4
- package/src/bconfig/v3.ts +12 -2
- package/src/block_api_v3.ts +49 -0
- package/src/block_migrations.ts +173 -0
- package/src/block_model.ts +440 -0
- package/src/block_storage.test.ts +258 -0
- package/src/block_storage.ts +365 -0
- package/src/block_storage_vm.ts +349 -0
- package/src/builder.ts +24 -59
- package/src/components/PFrameForGraphs.ts +2 -2
- package/src/components/PlDataTable.ts +3 -3
- package/src/index.ts +3 -0
- package/src/internal.ts +51 -0
- package/src/pframe_utils/columns.ts +3 -3
- package/src/platforma.ts +31 -5
- package/src/render/api.ts +52 -21
- package/src/render/internal.ts +3 -1
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BlockStorage VM Integration - Internal module for VM-based storage operations.
|
|
3
|
+
*
|
|
4
|
+
* This module auto-registers internal callbacks that the middle layer can invoke
|
|
5
|
+
* to perform storage transformations. Block developers never interact with these
|
|
6
|
+
* directly - they only see `state`.
|
|
7
|
+
*
|
|
8
|
+
* Registered callbacks (all prefixed with `__pl_` for internal SDK use):
|
|
9
|
+
* - `__pl_storage_normalize`: (rawStorage) => { storage, data }
|
|
10
|
+
* - `__pl_storage_applyUpdate`: (currentStorageJson, payload) => updatedStorageJson
|
|
11
|
+
* - `__pl_storage_getInfo`: (rawStorage) => JSON string with storage info
|
|
12
|
+
* - `__pl_storage_migrate`: (currentStorageJson) => MigrationResult
|
|
13
|
+
* - `__pl_args_derive`: (storageJson) => ArgsDeriveResult
|
|
14
|
+
* - `__pl_prerunArgs_derive`: (storageJson) => ArgsDeriveResult
|
|
15
|
+
*
|
|
16
|
+
* Callbacks registered by DataModel.registerCallbacks():
|
|
17
|
+
* - `__pl_data_initial`: () => initial data
|
|
18
|
+
* - `__pl_data_upgrade`: (versioned) => UpgradeResult
|
|
19
|
+
* - `__pl_storage_initial`: () => initial BlockStorage as JSON string
|
|
20
|
+
*
|
|
21
|
+
* @module block_storage_vm
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
BLOCK_STORAGE_KEY,
|
|
27
|
+
BLOCK_STORAGE_SCHEMA_VERSION,
|
|
28
|
+
type BlockStorage,
|
|
29
|
+
type MutateStoragePayload,
|
|
30
|
+
createBlockStorage,
|
|
31
|
+
getStorageData,
|
|
32
|
+
isBlockStorage,
|
|
33
|
+
updateStorageData,
|
|
34
|
+
} from './block_storage';
|
|
35
|
+
import { tryGetCfgRenderCtx, tryRegisterCallback } from './internal';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Result of storage normalization
|
|
39
|
+
*/
|
|
40
|
+
export interface NormalizeStorageResult {
|
|
41
|
+
/** The normalized BlockStorage object */
|
|
42
|
+
storage: BlockStorage;
|
|
43
|
+
/** The extracted data (what developers see) */
|
|
44
|
+
data: unknown;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Normalizes raw storage data and extracts state.
|
|
49
|
+
* Handles all formats:
|
|
50
|
+
* - New BlockStorage format (has discriminator)
|
|
51
|
+
* - Legacy V1/V2 format ({ args, uiState })
|
|
52
|
+
* - Raw V3 state (any other format)
|
|
53
|
+
*
|
|
54
|
+
* @param rawStorage - Raw data from blockStorage field (may be JSON string or object)
|
|
55
|
+
* @returns Object with normalized storage and extracted state
|
|
56
|
+
*/
|
|
57
|
+
function normalizeStorage(rawStorage: unknown): NormalizeStorageResult {
|
|
58
|
+
// Handle undefined/null
|
|
59
|
+
if (rawStorage === undefined || rawStorage === null) {
|
|
60
|
+
const storage = createBlockStorage({});
|
|
61
|
+
return { storage, data: {} };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Parse JSON string if needed
|
|
65
|
+
let parsed = rawStorage;
|
|
66
|
+
if (typeof rawStorage === 'string') {
|
|
67
|
+
try {
|
|
68
|
+
parsed = JSON.parse(rawStorage);
|
|
69
|
+
} catch {
|
|
70
|
+
// If parsing fails, treat string as the data
|
|
71
|
+
const storage = createBlockStorage(rawStorage);
|
|
72
|
+
return { storage, data: rawStorage };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Check for BlockStorage format (has discriminator)
|
|
77
|
+
if (isBlockStorage(parsed)) {
|
|
78
|
+
return { storage: parsed, data: getStorageData(parsed) };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Check for legacy V1/V2 format: { args, uiState }
|
|
82
|
+
if (isLegacyModelV1ApiFormat(parsed)) {
|
|
83
|
+
// For legacy format, the whole object IS the data
|
|
84
|
+
const storage = createBlockStorage(parsed);
|
|
85
|
+
return { storage, data: parsed };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Raw V3 data - wrap it
|
|
89
|
+
const storage = createBlockStorage(parsed);
|
|
90
|
+
return { storage, data: parsed };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Applies a state update to existing storage.
|
|
95
|
+
* Used when setData is called from the frontend.
|
|
96
|
+
*
|
|
97
|
+
* @param currentStorageJson - Current storage as JSON string (must be defined)
|
|
98
|
+
* @param newData - New data from application
|
|
99
|
+
* @returns Updated storage as JSON string
|
|
100
|
+
*/
|
|
101
|
+
function applyStorageUpdate(currentStorageJson: string, payload: MutateStoragePayload): string {
|
|
102
|
+
const { storage: currentStorage } = normalizeStorage(currentStorageJson);
|
|
103
|
+
|
|
104
|
+
// Update data while preserving other storage fields (version, plugins)
|
|
105
|
+
const updatedStorage = updateStorageData(currentStorage, payload);
|
|
106
|
+
|
|
107
|
+
return JSON.stringify(updatedStorage);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Checks if data is in legacy Model API v1 format.
|
|
112
|
+
* Legacy format has { args, uiState? } at top level without the BlockStorage discriminator.
|
|
113
|
+
*/
|
|
114
|
+
function isLegacyModelV1ApiFormat(data: unknown): data is { args?: unknown } {
|
|
115
|
+
if (data === null || typeof data !== 'object') return false;
|
|
116
|
+
if (isBlockStorage(data)) return false;
|
|
117
|
+
|
|
118
|
+
const obj = data as Record<string, unknown>;
|
|
119
|
+
return 'args' in obj;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// =============================================================================
|
|
123
|
+
// Auto-register internal callbacks when module is loaded in VM
|
|
124
|
+
// =============================================================================
|
|
125
|
+
|
|
126
|
+
// Register normalize callback
|
|
127
|
+
tryRegisterCallback('__pl_storage_normalize', (rawStorage: unknown) => {
|
|
128
|
+
return normalizeStorage(rawStorage);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Register apply update callback (requires existing storage)
|
|
132
|
+
tryRegisterCallback('__pl_storage_applyUpdate', (currentStorageJson: string, payload: MutateStoragePayload) => {
|
|
133
|
+
return applyStorageUpdate(currentStorageJson, payload);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Storage info result returned by __pl_storage_getInfo callback.
|
|
138
|
+
*/
|
|
139
|
+
export interface StorageInfo {
|
|
140
|
+
/** Current data version (1-based, starts at 1) */
|
|
141
|
+
dataVersion: number;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Gets storage info from raw storage data.
|
|
146
|
+
* Returns structured info about the storage state.
|
|
147
|
+
*
|
|
148
|
+
* @param rawStorage - Raw data from blockStorage field (may be JSON string or object)
|
|
149
|
+
* @returns JSON string with storage info
|
|
150
|
+
*/
|
|
151
|
+
function getStorageInfo(rawStorage: unknown): string {
|
|
152
|
+
const { storage } = normalizeStorage(rawStorage);
|
|
153
|
+
const info: StorageInfo = {
|
|
154
|
+
dataVersion: storage.__dataVersion,
|
|
155
|
+
};
|
|
156
|
+
return JSON.stringify(info);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Register get info callback
|
|
160
|
+
tryRegisterCallback('__pl_storage_getInfo', (rawStorage: unknown) => {
|
|
161
|
+
return getStorageInfo(rawStorage);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// =============================================================================
|
|
165
|
+
// Migration Support
|
|
166
|
+
// =============================================================================
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Result of storage migration.
|
|
170
|
+
* Returned by __pl_storage_migrate callback.
|
|
171
|
+
*
|
|
172
|
+
* - Error result: { error: string } - serious failure (no context, etc.)
|
|
173
|
+
* - Success result: { newStorageJson: string, info: string, warn?: string } - migration succeeded or reset to initial
|
|
174
|
+
*/
|
|
175
|
+
export type MigrationResult =
|
|
176
|
+
| { error: string }
|
|
177
|
+
| { error?: undefined; newStorageJson: string; info: string; warn?: string };
|
|
178
|
+
|
|
179
|
+
/** Result from Migrator.upgrade() */
|
|
180
|
+
interface UpgradeResult {
|
|
181
|
+
version: number;
|
|
182
|
+
data: unknown;
|
|
183
|
+
warning?: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Runs storage migration using the DataModel's upgrade callback.
|
|
188
|
+
* This is the main entry point for the middle layer to trigger migrations.
|
|
189
|
+
*
|
|
190
|
+
* Uses the '__pl_data_upgrade' callback registered by DataModel.registerCallbacks() which:
|
|
191
|
+
* - Handles all migration logic internally
|
|
192
|
+
* - Returns { version, data, warning? } - warning present if reset to initial data
|
|
193
|
+
*
|
|
194
|
+
* @param currentStorageJson - Current storage as JSON string (or undefined)
|
|
195
|
+
* @returns MigrationResult
|
|
196
|
+
*/
|
|
197
|
+
function migrateStorage(currentStorageJson: string | undefined): MigrationResult {
|
|
198
|
+
// Get the callback registry context
|
|
199
|
+
const ctx = tryGetCfgRenderCtx();
|
|
200
|
+
if (ctx === undefined) {
|
|
201
|
+
return { error: 'Not in config rendering context' };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Normalize storage to get current data and version
|
|
205
|
+
const { storage: currentStorage, data: currentData } = normalizeStorage(currentStorageJson);
|
|
206
|
+
const currentVersion = currentStorage.__dataVersion;
|
|
207
|
+
|
|
208
|
+
// Helper to create storage with given data and version
|
|
209
|
+
const createStorageJson = (data: unknown, version: number): string => {
|
|
210
|
+
return JSON.stringify({
|
|
211
|
+
...currentStorage,
|
|
212
|
+
__dataVersion: version,
|
|
213
|
+
__data: data,
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// Get the upgrade callback (registered by DataModel.registerCallbacks())
|
|
218
|
+
const upgradeCallback = ctx.callbackRegistry['__pl_data_upgrade'] as ((v: { version: number; data: unknown }) => UpgradeResult) | undefined;
|
|
219
|
+
if (typeof upgradeCallback !== 'function') {
|
|
220
|
+
return { error: '__pl_data_upgrade callback not found (DataModel not registered)' };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Call the migrator's upgrade function
|
|
224
|
+
let result: UpgradeResult;
|
|
225
|
+
try {
|
|
226
|
+
result = upgradeCallback({ version: currentVersion, data: currentData });
|
|
227
|
+
} catch (e) {
|
|
228
|
+
const errorMsg = e instanceof Error ? e.message : String(e);
|
|
229
|
+
return { error: `upgrade() threw: ${errorMsg}` };
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Build info message
|
|
233
|
+
const info = result.version === currentVersion
|
|
234
|
+
? `No migration needed (v${currentVersion})`
|
|
235
|
+
: result.warning
|
|
236
|
+
? `Reset to initial data (v${result.version})`
|
|
237
|
+
: `Migrated v${currentVersion}→v${result.version}`;
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
newStorageJson: createStorageJson(result.data, result.version),
|
|
241
|
+
info,
|
|
242
|
+
warn: result.warning,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Register migrate callback
|
|
247
|
+
tryRegisterCallback('__pl_storage_migrate', (currentStorageJson: string | undefined) => {
|
|
248
|
+
return migrateStorage(currentStorageJson);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// =============================================================================
|
|
252
|
+
// Args Derivation from Storage
|
|
253
|
+
// =============================================================================
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Result of args derivation from storage.
|
|
257
|
+
* Returned by __pl_args_derive and __pl_prerunArgs_derive callbacks.
|
|
258
|
+
*/
|
|
259
|
+
export type ArgsDeriveResult =
|
|
260
|
+
| { error: string }
|
|
261
|
+
| { error?: undefined; value: unknown };
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Derives args from storage using the registered 'args' callback.
|
|
265
|
+
* This extracts data from storage and passes it to the block's args() function.
|
|
266
|
+
*
|
|
267
|
+
* @param storageJson - Storage as JSON string
|
|
268
|
+
* @returns ArgsDeriveResult with derived args or error
|
|
269
|
+
*/
|
|
270
|
+
function deriveArgsFromStorage(storageJson: string): ArgsDeriveResult {
|
|
271
|
+
const ctx = tryGetCfgRenderCtx();
|
|
272
|
+
if (ctx === undefined) {
|
|
273
|
+
return { error: 'Not in config rendering context' };
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Extract data from storage
|
|
277
|
+
const { data } = normalizeStorage(storageJson);
|
|
278
|
+
|
|
279
|
+
// Get the args callback (registered by BlockModelV3.args())
|
|
280
|
+
const argsCallback = ctx.callbackRegistry['args'] as ((data: unknown) => unknown) | undefined;
|
|
281
|
+
if (typeof argsCallback !== 'function') {
|
|
282
|
+
return { error: 'args callback not found' };
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Call the args callback with extracted data
|
|
286
|
+
try {
|
|
287
|
+
const result = argsCallback(data);
|
|
288
|
+
return { value: result };
|
|
289
|
+
} catch (e) {
|
|
290
|
+
const errorMsg = e instanceof Error ? e.message : String(e);
|
|
291
|
+
return { error: `args() threw: ${errorMsg}` };
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Register args derivation callback
|
|
296
|
+
tryRegisterCallback('__pl_args_derive', (storageJson: string) => {
|
|
297
|
+
return deriveArgsFromStorage(storageJson);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Derives prerunArgs from storage using the registered 'prerunArgs' callback.
|
|
302
|
+
* Falls back to 'args' callback if 'prerunArgs' is not defined.
|
|
303
|
+
*
|
|
304
|
+
* @param storageJson - Storage as JSON string
|
|
305
|
+
* @returns ArgsDeriveResult with derived prerunArgs or error
|
|
306
|
+
*/
|
|
307
|
+
function derivePrerunArgsFromStorage(storageJson: string): ArgsDeriveResult {
|
|
308
|
+
const ctx = tryGetCfgRenderCtx();
|
|
309
|
+
if (ctx === undefined) {
|
|
310
|
+
return { error: 'Not in config rendering context' };
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Extract data from storage
|
|
314
|
+
const { data } = normalizeStorage(storageJson);
|
|
315
|
+
|
|
316
|
+
// Try prerunArgs callback first
|
|
317
|
+
const prerunArgsCallback = ctx.callbackRegistry['prerunArgs'] as ((data: unknown) => unknown) | undefined;
|
|
318
|
+
if (typeof prerunArgsCallback === 'function') {
|
|
319
|
+
try {
|
|
320
|
+
const result = prerunArgsCallback(data);
|
|
321
|
+
return { value: result };
|
|
322
|
+
} catch (e) {
|
|
323
|
+
const errorMsg = e instanceof Error ? e.message : String(e);
|
|
324
|
+
return { error: `prerunArgs() threw: ${errorMsg}` };
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Fall back to args callback
|
|
329
|
+
const argsCallback = ctx.callbackRegistry['args'] as ((data: unknown) => unknown) | undefined;
|
|
330
|
+
if (typeof argsCallback !== 'function') {
|
|
331
|
+
return { error: 'args callback not found (fallback from missing prerunArgs)' };
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
const result = argsCallback(data);
|
|
336
|
+
return { value: result };
|
|
337
|
+
} catch (e) {
|
|
338
|
+
const errorMsg = e instanceof Error ? e.message : String(e);
|
|
339
|
+
return { error: `args() threw (fallback): ${errorMsg}` };
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Register prerunArgs derivation callback
|
|
344
|
+
tryRegisterCallback('__pl_prerunArgs_derive', (storageJson: string) => {
|
|
345
|
+
return derivePrerunArgsFromStorage(storageJson);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Export discriminator key and schema version for external checks
|
|
349
|
+
export { BLOCK_STORAGE_KEY, BLOCK_STORAGE_SCHEMA_VERSION };
|
package/src/builder.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import type { BlockRenderingMode, BlockSection, AnyFunction, PlRef, BlockCodeKnownFeatureFlags, BlockConfigContainer
|
|
1
|
+
import type { BlockRenderingMode, BlockSection, AnyFunction, PlRef, BlockCodeKnownFeatureFlags, BlockConfigContainer } from '@milaboratories/pl-model-common';
|
|
2
2
|
import type { Checked, ConfigResult, TypedConfig } from './config';
|
|
3
3
|
import { getImmediate } from './config';
|
|
4
4
|
import { getPlatformaInstance, isInUI, tryRegisterCallback } from './internal';
|
|
5
5
|
import type { Platforma, PlatformaApiVersion, PlatformaV1, PlatformaV2 } from './platforma';
|
|
6
|
-
import type { InferRenderFunctionReturn,
|
|
7
|
-
import {
|
|
6
|
+
import type { InferRenderFunctionReturn, RenderFunctionLegacy } from './render';
|
|
7
|
+
import { RenderCtxLegacy } from './render';
|
|
8
8
|
import { PlatformaSDKVersion } from './version';
|
|
9
9
|
import type {
|
|
10
10
|
TypedConfigOrConfigLambda,
|
|
11
11
|
ConfigRenderLambda,
|
|
12
12
|
StdCtxArgsOnly,
|
|
13
13
|
DeriveHref,
|
|
14
|
-
ResolveCfgType,
|
|
15
|
-
ExtractFunctionHandleReturn,
|
|
16
14
|
ConfigRenderLambdaFlags,
|
|
15
|
+
InferOutputsFromConfigs,
|
|
17
16
|
} from './bconfig';
|
|
18
17
|
import {
|
|
19
18
|
downgradeCfgOrLambda,
|
|
20
19
|
isConfigLambda,
|
|
21
20
|
} from './bconfig';
|
|
21
|
+
import type { PlatformaExtended } from './platforma';
|
|
22
22
|
|
|
23
23
|
type SectionsExpectedType = readonly BlockSection[];
|
|
24
24
|
|
|
@@ -27,12 +27,6 @@ type SectionsCfgChecked<Cfg extends TypedConfig, Args, UiState> = Checked<
|
|
|
27
27
|
ConfigResult<Cfg, StdCtxArgsOnly<Args, UiState>> extends SectionsExpectedType ? true : false
|
|
28
28
|
>;
|
|
29
29
|
|
|
30
|
-
// TODO (Unused type in code)
|
|
31
|
-
// type SectionsRFChecked<RF extends Function> = Checked<
|
|
32
|
-
// RF,
|
|
33
|
-
// InferRenderFunctionReturn<RF> extends SectionsExpectedType ? true : false
|
|
34
|
-
// >;
|
|
35
|
-
|
|
36
30
|
type InputsValidExpectedType = boolean;
|
|
37
31
|
|
|
38
32
|
type InputsValidCfgChecked<Cfg extends TypedConfig, Args, UiState> = Checked<
|
|
@@ -40,12 +34,6 @@ type InputsValidCfgChecked<Cfg extends TypedConfig, Args, UiState> = Checked<
|
|
|
40
34
|
ConfigResult<Cfg, StdCtxArgsOnly<Args, UiState>> extends InputsValidExpectedType ? true : false
|
|
41
35
|
>;
|
|
42
36
|
|
|
43
|
-
// TODO (Unused type in code)
|
|
44
|
-
// type InputsValidRFChecked<RF extends Function> = Checked<
|
|
45
|
-
// RF,
|
|
46
|
-
// InferRenderFunctionReturn<RF> extends InputsValidExpectedType ? true : false
|
|
47
|
-
// >;
|
|
48
|
-
|
|
49
37
|
type NoOb = Record<string, never>;
|
|
50
38
|
|
|
51
39
|
/** Main entry point that each block should use in it's "config" module. Don't forget
|
|
@@ -126,7 +114,7 @@ export class BlockModel<
|
|
|
126
114
|
* workflows outputs and interact with platforma drivers
|
|
127
115
|
* @param flags additional flags that may alter lambda rendering procedure
|
|
128
116
|
* */
|
|
129
|
-
public output<const Key extends string, const RF extends
|
|
117
|
+
public output<const Key extends string, const RF extends RenderFunctionLegacy<Args, UiState>>(
|
|
130
118
|
key: Key,
|
|
131
119
|
rf: RF,
|
|
132
120
|
flags: ConfigRenderLambdaFlags & { withStatus: true }
|
|
@@ -144,7 +132,7 @@ export class BlockModel<
|
|
|
144
132
|
* workflows outputs and interact with platforma drivers
|
|
145
133
|
* @param flags additional flags that may alter lambda rendering procedure
|
|
146
134
|
* */
|
|
147
|
-
public output<const Key extends string, const RF extends
|
|
135
|
+
public output<const Key extends string, const RF extends RenderFunctionLegacy<Args, UiState>>(
|
|
148
136
|
key: Key,
|
|
149
137
|
rf: RF,
|
|
150
138
|
flags?: ConfigRenderLambdaFlags
|
|
@@ -161,7 +149,7 @@ export class BlockModel<
|
|
|
161
149
|
): BlockModel<Args, OutputsCfg, UiState, Href> {
|
|
162
150
|
if (typeof cfgOrRf === 'function') {
|
|
163
151
|
const handle = `output#${key}`;
|
|
164
|
-
tryRegisterCallback(handle, () => cfgOrRf(new
|
|
152
|
+
tryRegisterCallback(handle, () => cfgOrRf(new RenderCtxLegacy()));
|
|
165
153
|
return new BlockModel({
|
|
166
154
|
...this.config,
|
|
167
155
|
outputs: {
|
|
@@ -185,7 +173,7 @@ export class BlockModel<
|
|
|
185
173
|
}
|
|
186
174
|
|
|
187
175
|
/** Shortcut for {@link output} with retentive flag set to true. */
|
|
188
|
-
public retentiveOutput<const Key extends string, const RF extends
|
|
176
|
+
public retentiveOutput<const Key extends string, const RF extends RenderFunctionLegacy<Args, UiState>>(
|
|
189
177
|
key: Key,
|
|
190
178
|
rf: RF,
|
|
191
179
|
) {
|
|
@@ -193,7 +181,7 @@ export class BlockModel<
|
|
|
193
181
|
}
|
|
194
182
|
|
|
195
183
|
/** Shortcut for {@link output} with withStatus flag set to true. */
|
|
196
|
-
public outputWithStatus<const Key extends string, const RF extends
|
|
184
|
+
public outputWithStatus<const Key extends string, const RF extends RenderFunctionLegacy<Args, UiState>>(
|
|
197
185
|
key: Key,
|
|
198
186
|
rf: RF,
|
|
199
187
|
) {
|
|
@@ -201,7 +189,7 @@ export class BlockModel<
|
|
|
201
189
|
}
|
|
202
190
|
|
|
203
191
|
/** Shortcut for {@link output} with retentive and withStatus flags set to true. */
|
|
204
|
-
public retentiveOutputWithStatus<const Key extends string, const RF extends
|
|
192
|
+
public retentiveOutputWithStatus<const Key extends string, const RF extends RenderFunctionLegacy<Args, UiState>>(
|
|
205
193
|
key: Key,
|
|
206
194
|
rf: RF,
|
|
207
195
|
) {
|
|
@@ -214,14 +202,14 @@ export class BlockModel<
|
|
|
214
202
|
cfg: Cfg & InputsValidCfgChecked<Cfg, Args, UiState>
|
|
215
203
|
): BlockModel<Args, OutputsCfg, UiState, Href>;
|
|
216
204
|
/** Sets custom configuration predicate on the block args at which block can be executed */
|
|
217
|
-
public argsValid<RF extends
|
|
205
|
+
public argsValid<RF extends RenderFunctionLegacy<Args, UiState, boolean>>(
|
|
218
206
|
rf: RF
|
|
219
207
|
): BlockModel<Args, OutputsCfg, UiState, Href>;
|
|
220
208
|
public argsValid(
|
|
221
209
|
cfgOrRf: TypedConfig | AnyFunction,
|
|
222
210
|
): BlockModel<Args, OutputsCfg, UiState, `/${string}`> {
|
|
223
211
|
if (typeof cfgOrRf === 'function') {
|
|
224
|
-
tryRegisterCallback('inputsValid', () => cfgOrRf(new
|
|
212
|
+
tryRegisterCallback('inputsValid', () => cfgOrRf(new RenderCtxLegacy()));
|
|
225
213
|
return new BlockModel<Args, OutputsCfg, UiState>({
|
|
226
214
|
...this.config,
|
|
227
215
|
inputsValid: {
|
|
@@ -245,7 +233,7 @@ export class BlockModel<
|
|
|
245
233
|
/** Sets the config to generate list of section in the left block overviews panel */
|
|
246
234
|
public sections<
|
|
247
235
|
const Ret extends SectionsExpectedType,
|
|
248
|
-
const RF extends
|
|
236
|
+
const RF extends RenderFunctionLegacy<Args, UiState, Ret>,
|
|
249
237
|
>(rf: RF): BlockModel<Args, OutputsCfg, UiState, DeriveHref<ReturnType<RF>>>;
|
|
250
238
|
public sections<const Cfg extends TypedConfig>(
|
|
251
239
|
cfg: Cfg & SectionsCfgChecked<Cfg, Args, UiState>
|
|
@@ -261,7 +249,7 @@ export class BlockModel<
|
|
|
261
249
|
if (Array.isArray(arrOrCfgOrRf)) {
|
|
262
250
|
return this.sections(getImmediate(arrOrCfgOrRf));
|
|
263
251
|
} else if (typeof arrOrCfgOrRf === 'function') {
|
|
264
|
-
tryRegisterCallback('sections', () => arrOrCfgOrRf(new
|
|
252
|
+
tryRegisterCallback('sections', () => arrOrCfgOrRf(new RenderCtxLegacy()));
|
|
265
253
|
return new BlockModel<Args, OutputsCfg, UiState>({
|
|
266
254
|
...this.config,
|
|
267
255
|
sections: {
|
|
@@ -279,9 +267,9 @@ export class BlockModel<
|
|
|
279
267
|
|
|
280
268
|
/** Sets a rendering function to derive block title, shown for the block in the left blocks-overview panel. */
|
|
281
269
|
public title(
|
|
282
|
-
rf:
|
|
270
|
+
rf: RenderFunctionLegacy<Args, UiState, string>,
|
|
283
271
|
): BlockModel<Args, OutputsCfg, UiState, Href> {
|
|
284
|
-
tryRegisterCallback('title', () => rf(new
|
|
272
|
+
tryRegisterCallback('title', () => rf(new RenderCtxLegacy()));
|
|
285
273
|
return new BlockModel<Args, OutputsCfg, UiState, Href>({
|
|
286
274
|
...this.config,
|
|
287
275
|
title: {
|
|
@@ -292,9 +280,9 @@ export class BlockModel<
|
|
|
292
280
|
}
|
|
293
281
|
|
|
294
282
|
public subtitle(
|
|
295
|
-
rf:
|
|
283
|
+
rf: RenderFunctionLegacy<Args, UiState, string>,
|
|
296
284
|
): BlockModel<Args, OutputsCfg, UiState, Href> {
|
|
297
|
-
tryRegisterCallback('subtitle', () => rf(new
|
|
285
|
+
tryRegisterCallback('subtitle', () => rf(new RenderCtxLegacy()));
|
|
298
286
|
return new BlockModel<Args, OutputsCfg, UiState, Href>({
|
|
299
287
|
...this.config,
|
|
300
288
|
subtitle: {
|
|
@@ -305,9 +293,9 @@ export class BlockModel<
|
|
|
305
293
|
}
|
|
306
294
|
|
|
307
295
|
public tags(
|
|
308
|
-
rf:
|
|
296
|
+
rf: RenderFunctionLegacy<Args, UiState, string[]>,
|
|
309
297
|
): BlockModel<Args, OutputsCfg, UiState, Href> {
|
|
310
|
-
tryRegisterCallback('tags', () => rf(new
|
|
298
|
+
tryRegisterCallback('tags', () => rf(new RenderCtxLegacy()));
|
|
311
299
|
return new BlockModel<Args, OutputsCfg, UiState, Href>({
|
|
312
300
|
...this.config,
|
|
313
301
|
tags: {
|
|
@@ -407,7 +395,10 @@ export class BlockModel<
|
|
|
407
395
|
if (this.config.initialArgs === undefined) throw new Error('Initial arguments not set.');
|
|
408
396
|
|
|
409
397
|
const config: BlockConfigContainer = {
|
|
398
|
+
v4: undefined,
|
|
410
399
|
v3: {
|
|
400
|
+
configVersion: 3,
|
|
401
|
+
modelAPIVersion: 1,
|
|
411
402
|
sdkVersion: PlatformaSDKVersion,
|
|
412
403
|
renderingMode: this.config.renderingMode,
|
|
413
404
|
initialArgs: this.config.initialArgs,
|
|
@@ -452,29 +443,3 @@ export class BlockModel<
|
|
|
452
443
|
};
|
|
453
444
|
}
|
|
454
445
|
}
|
|
455
|
-
|
|
456
|
-
export type InferOutputType<CfgOrFH, Args, UiState> = CfgOrFH extends TypedConfig
|
|
457
|
-
? ResolveCfgType<CfgOrFH, Args, UiState>
|
|
458
|
-
: CfgOrFH extends ConfigRenderLambda
|
|
459
|
-
? ExtractFunctionHandleReturn<CfgOrFH>
|
|
460
|
-
: never;
|
|
461
|
-
|
|
462
|
-
type InferOutputsFromConfigs<
|
|
463
|
-
Args,
|
|
464
|
-
OutputsCfg extends Record<string, TypedConfigOrConfigLambda>,
|
|
465
|
-
UiState,
|
|
466
|
-
> = {
|
|
467
|
-
[Key in keyof OutputsCfg]:
|
|
468
|
-
& OutputWithStatus<InferOutputType<OutputsCfg[Key], Args, UiState>>
|
|
469
|
-
& { __unwrap: (OutputsCfg[Key] extends { withStatus: true } ? false : true) };
|
|
470
|
-
};
|
|
471
|
-
|
|
472
|
-
export type PlatformaExtended<Pl extends Platforma = Platforma> = Pl & {
|
|
473
|
-
blockModelInfo: BlockModelInfo;
|
|
474
|
-
};
|
|
475
|
-
|
|
476
|
-
export type BlockModelInfo = {
|
|
477
|
-
outputs: Record<string, {
|
|
478
|
-
withStatus: boolean;
|
|
479
|
-
}>;
|
|
480
|
-
};
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
readAnnotationJson,
|
|
18
18
|
stringifyJson,
|
|
19
19
|
} from '@milaboratories/pl-model-common';
|
|
20
|
-
import type { PColumnDataUniversal, PColumnEntryUniversal, PColumnEntryWithLabel,
|
|
20
|
+
import type { PColumnDataUniversal, PColumnEntryUniversal, PColumnEntryWithLabel, RenderCtxBase } from '../render';
|
|
21
21
|
import { getAllRelatedColumns, getRelatedColumns } from '../pframe_utils/columns';
|
|
22
22
|
|
|
23
23
|
/** Create id for column copy with added keys in axes domains */
|
|
@@ -179,7 +179,7 @@ function getAdditionalColumnsForColumn<T extends Omit<PColumn<PColumnDataUnivers
|
|
|
179
179
|
and modified label (with added domain values in case if more than one copy with different domains exist).
|
|
180
180
|
*/
|
|
181
181
|
export function createPFrameForGraphs<A, U>(
|
|
182
|
-
ctx:
|
|
182
|
+
ctx: RenderCtxBase<A, U>,
|
|
183
183
|
blockColumns?: PColumn<PColumnDataUniversal>[],
|
|
184
184
|
): PFrameHandle | undefined {
|
|
185
185
|
const suitableSpec = (spec: PColumnSpec) => !isHiddenFromUIColumn(spec) && !isHiddenFromGraphColumn(spec);
|
|
@@ -34,7 +34,7 @@ import type {
|
|
|
34
34
|
AxisLabelProvider,
|
|
35
35
|
ColumnProvider,
|
|
36
36
|
PColumnDataUniversal,
|
|
37
|
-
|
|
37
|
+
RenderCtxBase,
|
|
38
38
|
TreeNodeAccessor,
|
|
39
39
|
} from '../render';
|
|
40
40
|
import {
|
|
@@ -631,7 +631,7 @@ export function isColumnOptional(spec: { annotations?: Annotation }): boolean {
|
|
|
631
631
|
* @returns PlAgDataTableV2 table source
|
|
632
632
|
*/
|
|
633
633
|
export function createPlDataTableV2<A, U>(
|
|
634
|
-
ctx:
|
|
634
|
+
ctx: RenderCtxBase<A, U>,
|
|
635
635
|
columns: PColumn<PColumnDataUniversal>[],
|
|
636
636
|
tableState: PlDataTableStateV2 | undefined,
|
|
637
637
|
ops?: CreatePlDataTableOps,
|
|
@@ -765,7 +765,7 @@ export function createPlDataTableV2<A, U>(
|
|
|
765
765
|
|
|
766
766
|
/** Create sheet entries for PlDataTable */
|
|
767
767
|
export function createPlDataTableSheet<A, U>(
|
|
768
|
-
ctx:
|
|
768
|
+
ctx: RenderCtxBase<A, U>,
|
|
769
769
|
axis: AxisSpec,
|
|
770
770
|
values: (string | number)[],
|
|
771
771
|
): PlDataTableSheet {
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export * from './block_state_patch';
|
|
2
2
|
export * from './block_state_util';
|
|
3
|
+
export * from './block_storage';
|
|
3
4
|
export * from './builder';
|
|
5
|
+
export { BlockModelV3 } from './block_model';
|
|
6
|
+
export { DataModel } from './block_migrations';
|
|
4
7
|
export * from './bconfig';
|
|
5
8
|
export * from './components';
|
|
6
9
|
export * from './config';
|
package/src/internal.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { OutputWithStatus } from '@milaboratories/pl-model-common';
|
|
|
2
2
|
import { } from './global';
|
|
3
3
|
import type { Platforma, PlatformaApiVersion } from './platforma';
|
|
4
4
|
import type { FutureHandle, GlobalCfgRenderCtx } from './render/internal';
|
|
5
|
+
import type { ConfigRenderLambda, ConfigRenderLambdaFlags } from './bconfig';
|
|
5
6
|
|
|
6
7
|
/** Utility code helping to identify whether the code is running in actual UI environment */
|
|
7
8
|
export function isInUI() {
|
|
@@ -41,6 +42,56 @@ export function tryRegisterCallback(key: string, callback: (...args: any[]) => a
|
|
|
41
42
|
return true;
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Registers a callback, replacing any existing callback with the same key.
|
|
47
|
+
* Use this for callbacks that have a default value but can be overridden.
|
|
48
|
+
*
|
|
49
|
+
* @param key - The callback registry key
|
|
50
|
+
* @param callback - The callback function to register
|
|
51
|
+
* @returns true if registered, false if not in render context
|
|
52
|
+
*/
|
|
53
|
+
export function replaceCallback(key: string, callback: (...args: any[]) => any): boolean {
|
|
54
|
+
const ctx = tryGetCfgRenderCtx();
|
|
55
|
+
if (ctx === undefined) return false;
|
|
56
|
+
ctx.callbackRegistry[key] = callback;
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//
|
|
61
|
+
// ConfigRenderLambda helpers
|
|
62
|
+
//
|
|
63
|
+
|
|
64
|
+
/** Options for creating a ConfigRenderLambda descriptor */
|
|
65
|
+
export type CreateLambdaOptions = ConfigRenderLambdaFlags & {
|
|
66
|
+
/** The callback registry key */
|
|
67
|
+
handle: string;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/** Creates a ConfigRenderLambda descriptor without registering a callback. */
|
|
71
|
+
export function createRenderLambda<T = unknown>(opts: CreateLambdaOptions): ConfigRenderLambda<T> {
|
|
72
|
+
const { handle, ...flags } = opts;
|
|
73
|
+
return {
|
|
74
|
+
__renderLambda: true,
|
|
75
|
+
handle,
|
|
76
|
+
...flags,
|
|
77
|
+
} as ConfigRenderLambda<T>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Registers a callback and returns a ConfigRenderLambda descriptor. */
|
|
81
|
+
export function createAndRegisterRenderLambda<T = unknown>(opts: CreateLambdaOptions & {
|
|
82
|
+
lambda: (...args: any[]) => any;
|
|
83
|
+
}, replace?: boolean): ConfigRenderLambda<T> {
|
|
84
|
+
const { handle, lambda, ...flags } = opts;
|
|
85
|
+
|
|
86
|
+
if (replace) {
|
|
87
|
+
replaceCallback(handle, lambda);
|
|
88
|
+
} else {
|
|
89
|
+
tryRegisterCallback(handle, lambda);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return createRenderLambda<T>({ handle, ...flags });
|
|
93
|
+
}
|
|
94
|
+
|
|
44
95
|
const futureResolves = new Map<string, ((value: unknown) => void)[]>();
|
|
45
96
|
|
|
46
97
|
export function registerFutureAwait(handle: FutureHandle, onResolve: (value: unknown) => void) {
|