@milaboratories/pl-middle-layer 1.64.37 → 1.64.38
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/_virtual/{_@oxc-project_runtime@0.123.0/helpers → _@oxc-project_runtime@0.137.0/helpers/esm}/usingCtx.cjs +2 -2
- package/dist/_virtual/{_@oxc-project_runtime@0.123.0/helpers → _@oxc-project_runtime@0.137.0/helpers/esm}/usingCtx.js +2 -2
- package/dist/block_registry/index.cjs +11 -3
- package/dist/block_registry/index.d.ts +3 -2
- package/dist/block_registry/index.js +4 -3
- package/dist/block_registry/registry-v2-provider.cjs +1 -1
- package/dist/block_registry/registry-v2-provider.cjs.map +1 -1
- package/dist/block_registry/registry-v2-provider.d.ts.map +1 -1
- package/dist/block_registry/registry-v2-provider.js +1 -0
- package/dist/block_registry/registry-v2-provider.js.map +1 -1
- package/dist/block_registry/registry.cjs +20 -3
- package/dist/block_registry/registry.cjs.map +1 -1
- package/dist/block_registry/registry.d.ts +7 -1
- package/dist/block_registry/registry.d.ts.map +1 -1
- package/dist/block_registry/registry.js +17 -1
- package/dist/block_registry/registry.js.map +1 -1
- package/dist/block_registry/watcher.cjs +21 -2
- package/dist/block_registry/watcher.cjs.map +1 -1
- package/dist/block_registry/watcher.d.ts +1 -1
- package/dist/block_registry/watcher.d.ts.map +1 -1
- package/dist/block_registry/watcher.js +21 -3
- package/dist/block_registry/watcher.js.map +1 -1
- package/dist/block_registry/well_known_registries.cjs.map +1 -1
- package/dist/block_registry/well_known_registries.d.ts.map +1 -1
- package/dist/block_registry/well_known_registries.js.map +1 -1
- package/dist/cfg_render/executor.cjs +2 -2
- package/dist/cfg_render/executor.cjs.map +1 -1
- package/dist/cfg_render/executor.js.map +1 -1
- package/dist/cfg_render/renderer.cjs +0 -1
- package/dist/cfg_render/renderer.cjs.map +1 -1
- package/dist/cfg_render/renderer.js.map +1 -1
- package/dist/cfg_render/traverse.cjs +0 -1
- package/dist/cfg_render/traverse.cjs.map +1 -1
- package/dist/cfg_render/traverse.js.map +1 -1
- package/dist/cfg_render/util.cjs.map +1 -1
- package/dist/cfg_render/util.js.map +1 -1
- package/dist/debug/index.cjs +1 -0
- package/dist/debug/index.cjs.map +1 -1
- package/dist/debug/index.js +1 -1
- package/dist/debug/index.js.map +1 -1
- package/dist/dev_env/index.cjs +9 -1
- package/dist/dev_env/index.cjs.map +1 -1
- package/dist/dev_env/index.js +1 -1
- package/dist/dev_env/index.js.map +1 -1
- package/dist/dev_env/util.cjs +1 -1
- package/dist/dev_env/util.cjs.map +1 -1
- package/dist/dev_env/util.js.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/js_render/computable_context.cjs +8 -5
- package/dist/js_render/computable_context.cjs.map +1 -1
- package/dist/js_render/computable_context.js +5 -1
- package/dist/js_render/computable_context.js.map +1 -1
- package/dist/js_render/context.cjs +4 -1
- package/dist/js_render/context.cjs.map +1 -1
- package/dist/js_render/context.js +4 -1
- package/dist/js_render/context.js.map +1 -1
- package/dist/js_render/index.cjs +0 -1
- package/dist/js_render/index.cjs.map +1 -1
- package/dist/js_render/index.js.map +1 -1
- package/dist/js_render/service_injectors.cjs +2 -3
- package/dist/js_render/service_injectors.cjs.map +1 -1
- package/dist/js_render/service_injectors.js +1 -1
- package/dist/js_render/service_injectors.js.map +1 -1
- package/dist/middle_layer/active_cfg.cjs +0 -1
- package/dist/middle_layer/active_cfg.cjs.map +1 -1
- package/dist/middle_layer/active_cfg.js.map +1 -1
- package/dist/middle_layer/block.cjs +0 -1
- package/dist/middle_layer/block.cjs.map +1 -1
- package/dist/middle_layer/block.js.map +1 -1
- package/dist/middle_layer/block_ctx.cjs +0 -1
- package/dist/middle_layer/block_ctx.cjs.map +1 -1
- package/dist/middle_layer/block_ctx.js.map +1 -1
- package/dist/middle_layer/block_ctx_unsafe.cjs.map +1 -1
- package/dist/middle_layer/block_ctx_unsafe.js.map +1 -1
- package/dist/middle_layer/driver_kit.cjs +0 -1
- package/dist/middle_layer/driver_kit.cjs.map +1 -1
- package/dist/middle_layer/driver_kit.js.map +1 -1
- package/dist/middle_layer/frontend_path.cjs +5 -1
- package/dist/middle_layer/frontend_path.cjs.map +1 -1
- package/dist/middle_layer/frontend_path.js +6 -1
- package/dist/middle_layer/frontend_path.js.map +1 -1
- package/dist/middle_layer/index.cjs +13 -5
- package/dist/middle_layer/index.d.ts +2 -1
- package/dist/middle_layer/index.js +6 -5
- package/dist/middle_layer/middle_layer.cjs +7 -1
- package/dist/middle_layer/middle_layer.cjs.map +1 -1
- package/dist/middle_layer/middle_layer.d.ts.map +1 -1
- package/dist/middle_layer/middle_layer.js +7 -0
- package/dist/middle_layer/middle_layer.js.map +1 -1
- package/dist/middle_layer/navigation_states.cjs +0 -1
- package/dist/middle_layer/navigation_states.cjs.map +1 -1
- package/dist/middle_layer/navigation_states.js.map +1 -1
- package/dist/middle_layer/ops.cjs +1 -1
- package/dist/middle_layer/ops.cjs.map +1 -1
- package/dist/middle_layer/ops.d.ts.map +1 -1
- package/dist/middle_layer/ops.js.map +1 -1
- package/dist/middle_layer/project.cjs +9 -2
- package/dist/middle_layer/project.cjs.map +1 -1
- package/dist/middle_layer/project.d.ts.map +1 -1
- package/dist/middle_layer/project.js +5 -1
- package/dist/middle_layer/project.js.map +1 -1
- package/dist/middle_layer/project_list.cjs +2 -1
- package/dist/middle_layer/project_list.cjs.map +1 -1
- package/dist/middle_layer/project_list.js +1 -1
- package/dist/middle_layer/project_list.js.map +1 -1
- package/dist/middle_layer/project_overview.cjs +0 -1
- package/dist/middle_layer/project_overview.cjs.map +1 -1
- package/dist/middle_layer/project_overview.js.map +1 -1
- package/dist/middle_layer/project_overview_light.cjs +0 -1
- package/dist/middle_layer/project_overview_light.cjs.map +1 -1
- package/dist/middle_layer/project_overview_light.js.map +1 -1
- package/dist/middle_layer/render.cjs +0 -1
- package/dist/middle_layer/render.cjs.map +1 -1
- package/dist/middle_layer/render.js.map +1 -1
- package/dist/middle_layer/types.d.ts.map +1 -1
- package/dist/middle_layer/util.cjs +0 -1
- package/dist/middle_layer/util.cjs.map +1 -1
- package/dist/middle_layer/util.js.map +1 -1
- package/dist/model/args.cjs +1 -1
- package/dist/model/args.cjs.map +1 -1
- package/dist/model/args.js +1 -1
- package/dist/model/args.js.map +1 -1
- package/dist/model/block_pack_spec.cjs +5 -0
- package/dist/model/block_pack_spec.cjs.map +1 -1
- package/dist/model/block_pack_spec.d.ts +19 -2
- package/dist/model/block_pack_spec.d.ts.map +1 -1
- package/dist/model/block_pack_spec.js +5 -1
- package/dist/model/block_pack_spec.js.map +1 -1
- package/dist/model/frontend.d.ts.map +1 -1
- package/dist/model/index.d.ts +2 -1
- package/dist/model/project_helper.cjs +2 -1
- package/dist/model/project_helper.cjs.map +1 -1
- package/dist/model/project_helper.d.ts +1 -1
- package/dist/model/project_helper.d.ts.map +1 -1
- package/dist/model/project_helper.js +2 -0
- package/dist/model/project_helper.js.map +1 -1
- package/dist/model/project_model.cjs +2 -1
- package/dist/model/project_model.cjs.map +1 -1
- package/dist/model/project_model.d.ts.map +1 -1
- package/dist/model/project_model.js +2 -2
- package/dist/model/project_model.js.map +1 -1
- package/dist/model/project_model_util.cjs +4 -3
- package/dist/model/project_model_util.cjs.map +1 -1
- package/dist/model/project_model_util.js +4 -4
- package/dist/model/project_model_util.js.map +1 -1
- package/dist/model/template_spec.d.ts.map +1 -1
- package/dist/mutator/block-pack/block_pack.cjs +41 -4
- package/dist/mutator/block-pack/block_pack.cjs.map +1 -1
- package/dist/mutator/block-pack/block_pack.d.ts.map +1 -1
- package/dist/mutator/block-pack/block_pack.js +40 -4
- package/dist/mutator/block-pack/block_pack.js.map +1 -1
- package/dist/mutator/block-pack/frontend.cjs +5 -1
- package/dist/mutator/block-pack/frontend.cjs.map +1 -1
- package/dist/mutator/block-pack/frontend.js +6 -1
- package/dist/mutator/block-pack/frontend.js.map +1 -1
- package/dist/mutator/block-pack/required_capabilities.cjs +0 -1
- package/dist/mutator/block-pack/required_capabilities.cjs.map +1 -1
- package/dist/mutator/block-pack/required_capabilities.js.map +1 -1
- package/dist/mutator/context_export.cjs +0 -1
- package/dist/mutator/context_export.cjs.map +1 -1
- package/dist/mutator/context_export.js.map +1 -1
- package/dist/mutator/migration.cjs +0 -1
- package/dist/mutator/migration.cjs.map +1 -1
- package/dist/mutator/migration.js.map +1 -1
- package/dist/mutator/project.cjs +22 -4
- package/dist/mutator/project.cjs.map +1 -1
- package/dist/mutator/project.js +21 -4
- package/dist/mutator/project.js.map +1 -1
- package/dist/mutator/template/direct_template_loader.cjs +0 -1
- package/dist/mutator/template/direct_template_loader.cjs.map +1 -1
- package/dist/mutator/template/direct_template_loader.js.map +1 -1
- package/dist/mutator/template/direct_template_loader_v3.cjs +0 -1
- package/dist/mutator/template/direct_template_loader_v3.cjs.map +1 -1
- package/dist/mutator/template/direct_template_loader_v3.js.map +1 -1
- package/dist/mutator/template/render_block.cjs +4 -1
- package/dist/mutator/template/render_block.cjs.map +1 -1
- package/dist/mutator/template/render_block.js +1 -1
- package/dist/mutator/template/render_block.js.map +1 -1
- package/dist/mutator/template/render_template.cjs +0 -1
- package/dist/mutator/template/render_template.cjs.map +1 -1
- package/dist/mutator/template/render_template.d.ts.map +1 -1
- package/dist/mutator/template/render_template.js.map +1 -1
- package/dist/mutator/template/template_cache.cjs +6 -3
- package/dist/mutator/template/template_cache.cjs.map +1 -1
- package/dist/mutator/template/template_cache.d.ts +1 -2
- package/dist/mutator/template/template_cache.d.ts.map +1 -1
- package/dist/mutator/template/template_cache.js +6 -2
- package/dist/mutator/template/template_cache.js.map +1 -1
- package/dist/mutator/template/template_loading.cjs +1 -1
- package/dist/mutator/template/template_loading.cjs.map +1 -1
- package/dist/mutator/template/template_loading.d.ts.map +1 -1
- package/dist/mutator/template/template_loading.js.map +1 -1
- package/dist/network_check/network_check.cjs +0 -1
- package/dist/network_check/network_check.cjs.map +1 -1
- package/dist/network_check/network_check.d.ts.map +1 -1
- package/dist/network_check/network_check.js.map +1 -1
- package/dist/network_check/pings.cjs +3 -1
- package/dist/network_check/pings.cjs.map +1 -1
- package/dist/network_check/pings.js +1 -1
- package/dist/network_check/pings.js.map +1 -1
- package/dist/network_check/template.cjs +10 -3
- package/dist/network_check/template.cjs.map +1 -1
- package/dist/network_check/template.js +1 -1
- package/dist/network_check/template.js.map +1 -1
- package/dist/pool/data.cjs +12 -1
- package/dist/pool/data.cjs.map +1 -1
- package/dist/pool/data.d.ts.map +1 -1
- package/dist/pool/data.js +3 -1
- package/dist/pool/data.js.map +1 -1
- package/dist/pool/driver.cjs +8 -1
- package/dist/pool/driver.cjs.map +1 -1
- package/dist/pool/driver.d.ts.map +1 -1
- package/dist/pool/driver.js +7 -0
- package/dist/pool/driver.js.map +1 -1
- package/dist/pool/index.cjs +5 -2
- package/dist/pool/index.d.ts +2 -1
- package/dist/pool/index.js +3 -2
- package/dist/pool/p_object_collection.cjs +1 -1
- package/dist/pool/p_object_collection.cjs.map +1 -1
- package/dist/pool/p_object_collection.js.map +1 -1
- package/dist/pool/result_pool.cjs +2 -1
- package/dist/pool/result_pool.cjs.map +1 -1
- package/dist/pool/result_pool.js +2 -0
- package/dist/pool/result_pool.js.map +1 -1
- package/dist/service_factories.cjs +0 -1
- package/dist/service_factories.cjs.map +1 -1
- package/dist/service_factories.js.map +1 -1
- package/dist/worker/WorkerManager.cjs +3 -2
- package/dist/worker/WorkerManager.cjs.map +1 -1
- package/dist/worker/WorkerManager.js +2 -1
- package/dist/worker/WorkerManager.js.map +1 -1
- package/dist/worker/worker.cjs +0 -1
- package/dist/worker/worker.cjs.map +1 -1
- package/dist/worker/worker.js.map +1 -1
- package/dist/worker/workerApi.cjs +0 -1
- package/dist/worker/workerApi.cjs.map +1 -1
- package/dist/worker/workerApi.js.map +1 -1
- package/package.json +13 -13
- package/src/block_registry/registry.ts +19 -0
- package/src/block_registry/watcher.ts +25 -2
- package/src/middle_layer/frontend_path.ts +22 -2
- package/src/model/block_pack_spec.ts +24 -1
- package/src/mutator/block-pack/block_pack.ts +61 -2
- package/src/mutator/block-pack/frontend.ts +20 -2
- package/src/mutator/template/template_cache.ts +10 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project_helper.cjs","names":["LRUCache","ConsoleLoggerAdapter","BLOCK_STORAGE_FACADE_VERSION","executeSingleLambda","BlockStorageFacadeCallbacks","getDebugFlags"],"sources":["../../src/model/project_helper.ts"],"sourcesContent":["import type { ResultOrError, BlockConfig, BlockStorage, PlRef } from \"@platforma-sdk/model\";\nimport type { StringifiedJson } from \"@milaboratories/pl-model-common\";\nimport {\n extractCodeWithInfo,\n ensureError,\n BlockStorageFacadeCallbacks,\n BLOCK_STORAGE_FACADE_VERSION,\n} from \"@platforma-sdk/model\";\nimport { LRUCache } from \"lru-cache\";\nimport type { QuickJSWASMModule } from \"quickjs-emscripten\";\nimport { executeSingleLambda } from \"../js_render\";\nimport type { SignedResourceId } from \"@milaboratories/pl-client\";\nimport { ConsoleLoggerAdapter, type MiLogger } from \"@milaboratories/ts-helpers\";\nimport type { StorageDebugView } from \"@milaboratories/pl-model-middle-layer\";\nimport { getDebugFlags } from \"../debug\";\n\ntype EnrichmentTargetsRequest = {\n blockConfig: () => BlockConfig;\n args: () => unknown;\n};\n\ntype EnrichmentTargetsValue = {\n value: PlRef[] | undefined;\n};\n\n/**\n * Result of VM-based storage migration.\n * Returned by migrateStorageInVM().\n *\n * - Error result: { error: string } - serious failure (no context, etc.)\n * - Success result: { newStorageJson: StringifiedJson<BlockStorage>, info: string } - migration succeeded\n */\nexport type MigrationResult =\n | { error: string }\n | { error?: undefined; newStorageJson: StringifiedJson<BlockStorage>; info: string };\n\n/**\n * Result of args derivation from storage.\n * Returned by __pl_args_derive and __pl_prerunArgs_derive VM callbacks.\n */\ntype ArgsDeriveResult = { error: string } | { error?: undefined; value: unknown };\n\nexport class ProjectHelper {\n private readonly enrichmentTargetsCache = new LRUCache<\n string,\n EnrichmentTargetsValue,\n EnrichmentTargetsRequest\n >({\n max: 256,\n memoMethod: (_key, _value, { context }) => {\n return { value: this.calculateEnrichmentTargets(context) };\n },\n });\n\n constructor(\n private readonly quickJs: QuickJSWASMModule,\n public readonly logger: MiLogger = new ConsoleLoggerAdapter(),\n ) {}\n\n // =============================================================================\n // Args Derivation from Storage (V3+)\n // =============================================================================\n\n /**\n * Derives args directly from storage JSON using VM callback.\n * The VM extracts data from storage and calls the block's args() function.\n *\n * This allows the middle layer to work only with storage JSON,\n * without needing to know the underlying data structure.\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param storageJson Storage as JSON string\n * @returns The derived args object, or error if derivation fails\n */\n public deriveArgsFromStorage(\n blockConfig: BlockConfig,\n storageJson: string,\n ): ResultOrError<unknown> {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n return {\n error: new Error(\"deriveArgsFromStorage is only supported for model API version 2\"),\n };\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.ArgsDerive],\n extractCodeWithInfo(blockConfig),\n storageJson,\n ) as ArgsDeriveResult;\n\n if (result.error !== undefined) {\n return { error: new Error(result.error) };\n }\n return { value: result.value };\n } catch (e) {\n return { error: new Error(\"Args derivation from storage failed\", { cause: ensureError(e) }) };\n }\n }\n\n /**\n * Derives prerunArgs directly from storage JSON using VM callback.\n * Falls back to args() if prerunArgs is not defined in the block model.\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param storageJson Storage as JSON string\n * @returns The derived prerunArgs, or undefined if derivation fails\n */\n public derivePrerunArgsFromStorage(blockConfig: BlockConfig, storageJson: string): unknown {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"derivePrerunArgsFromStorage is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.PrerunArgsDerive],\n extractCodeWithInfo(blockConfig),\n storageJson,\n ) as ArgsDeriveResult;\n\n if (result.error !== undefined) {\n // Return undefined if derivation fails (skip block in staging)\n return undefined;\n }\n return result.value;\n } catch {\n // Return undefined if derivation fails (skip block in staging)\n return undefined;\n }\n }\n\n private calculateEnrichmentTargets(req: EnrichmentTargetsRequest): PlRef[] | undefined {\n const blockConfig = req.blockConfig();\n if (blockConfig.enrichmentTargets === undefined) return undefined;\n const args = req.args();\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.enrichmentTargets,\n extractCodeWithInfo(blockConfig),\n args,\n ) as PlRef[];\n return result;\n }\n\n public getEnrichmentTargets(\n blockConfig: () => BlockConfig,\n args: () => unknown,\n key?: { argsRid: SignedResourceId; blockPackRid: SignedResourceId },\n ): PlRef[] | undefined {\n const req = { blockConfig, args };\n if (key === undefined) return this.calculateEnrichmentTargets(req);\n const cacheKey = `${key.argsRid}:${key.blockPackRid}`;\n return this.enrichmentTargetsCache.memo(cacheKey, { context: req }).value;\n }\n\n // =============================================================================\n // VM-based Storage Operations\n // =============================================================================\n\n /**\n * Creates initial BlockStorage for a new block using VM-based transformation.\n * This calls the '__pl_storage_initial' callback registered by DataModel which:\n * - Gets initial data from DataModel.getDefaultData()\n * - Creates BlockStorage with correct version\n *\n * @param blockConfig The block configuration (provides the model code)\n * @returns Initial storage as JSON string\n * @throws Error if storage creation fails\n */\n public getInitialStorageInVM(blockConfig: BlockConfig): string {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"getInitialStorageInVM is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageInitial],\n extractCodeWithInfo(blockConfig),\n ) as string;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.getInitialStorageInVM] Initial storage creation failed\", {\n cause: e,\n }),\n );\n throw new Error(`Block initial storage creation failed: ${e}`);\n }\n }\n\n /**\n * Applies a state update using VM-based transformation.\n * This calls the model's `__pl_storage_applyUpdate` callback which:\n * - Normalizes current storage\n * - Updates state while preserving other fields (version, plugins)\n * - Returns the updated storage as JSON string\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param currentStorageJson Current storage as JSON string (must be defined)\n * @param newState New state from developer\n * @returns Updated storage as JSON string\n * @throws Error if storage update fails\n */\n public applyStorageUpdateInVM(\n blockConfig: BlockConfig,\n currentStorageJson: string,\n payload: { operation: string; value: unknown },\n ): string {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"applyStorageUpdateInVM is only supported for model API version 2\");\n }\n\n if (getDebugFlags().logJsExecStat) {\n this.logger.info(\n `[ProjectHelper.applyStorageUpdateInVM] currentStorageJson=${currentStorageJson.length}B, payload=${JSON.stringify(payload).length}B, operation=${payload.operation}`,\n );\n }\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageApplyUpdate],\n extractCodeWithInfo(blockConfig),\n currentStorageJson,\n payload,\n ) as string;\n return result;\n } catch (e) {\n const payloadJson = JSON.stringify(payload);\n this.logger.error(\n new Error(\n `[ProjectHelper.applyStorageUpdateInVM] Storage update failed (currentStorageJson=${currentStorageJson.length}B, payload=${payloadJson.length}B, operation=${payload.operation})`,\n { cause: e },\n ),\n );\n throw new Error(`Block storage update failed: ${e}`);\n }\n }\n\n /**\n * Gets storage debug view from raw storage data by calling the VM's __pl_storage_debugView callback.\n * Returns structured debug info about the storage (e.g., dataVersion).\n *\n * @param blockConfig Block configuration\n * @param rawStorageJson Raw storage as JSON string (or undefined)\n * @returns Storage debug view as JSON string (e.g., '{\"dataVersion\": \"v1\"}')\n */\n public getStorageDebugViewInVM(\n blockConfig: BlockConfig,\n rawStorageJson: string | undefined,\n ): StringifiedJson<StorageDebugView> | undefined {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"getStorageDebugViewInVM is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageDebugView],\n extractCodeWithInfo(blockConfig),\n rawStorageJson,\n ) as StringifiedJson<StorageDebugView>;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.getStorageDebugViewInVM] Get storage debug view failed\", {\n cause: e,\n }),\n );\n return undefined;\n }\n }\n\n // =============================================================================\n // Block State Migrations\n // =============================================================================\n\n /**\n * Runs block state migrations via VM-based transformation.\n * This calls the model's `__pl_storage_migrate` callback which:\n * - Normalizes current storage to get state and version\n * - Applies DataModel upgrade to reach target version key\n * - Runs all necessary migrations sequentially\n * - Returns new storage with updated state and version\n *\n * The middle layer doesn't need to know about dataVersion or storage internals.\n * All migration logic is encapsulated in the model.\n *\n * @param blockConfig The NEW block configuration (provides the model code with migrations)\n * @param currentStorageJson Current storage as JSON string (or undefined)\n * @returns MigrationResult with new storage or skip/error info\n */\n public migrateStorageInVM(\n blockConfig: BlockConfig,\n currentStorageJson: string | undefined,\n ): MigrationResult {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n return { error: \"migrateStorageInVM is only supported for model API version 2\" };\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageMigrate],\n extractCodeWithInfo(blockConfig),\n currentStorageJson,\n ) as MigrationResult;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.migrateStorageInVM] Migration failed\", { cause: e }),\n );\n return { error: `VM execution failed: ${e}` };\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"project_helper.cjs","names":["LRUCache","ConsoleLoggerAdapter","BLOCK_STORAGE_FACADE_VERSION","executeSingleLambda","BlockStorageFacadeCallbacks","getDebugFlags"],"sources":["../../src/model/project_helper.ts"],"sourcesContent":["import type { ResultOrError, BlockConfig, BlockStorage, PlRef } from \"@platforma-sdk/model\";\nimport type { StringifiedJson } from \"@milaboratories/pl-model-common\";\nimport {\n extractCodeWithInfo,\n ensureError,\n BlockStorageFacadeCallbacks,\n BLOCK_STORAGE_FACADE_VERSION,\n} from \"@platforma-sdk/model\";\nimport { LRUCache } from \"lru-cache\";\nimport type { QuickJSWASMModule } from \"quickjs-emscripten\";\nimport { executeSingleLambda } from \"../js_render\";\nimport type { SignedResourceId } from \"@milaboratories/pl-client\";\nimport { ConsoleLoggerAdapter, type MiLogger } from \"@milaboratories/ts-helpers\";\nimport type { StorageDebugView } from \"@milaboratories/pl-model-middle-layer\";\nimport { getDebugFlags } from \"../debug\";\n\ntype EnrichmentTargetsRequest = {\n blockConfig: () => BlockConfig;\n args: () => unknown;\n};\n\ntype EnrichmentTargetsValue = {\n value: PlRef[] | undefined;\n};\n\n/**\n * Result of VM-based storage migration.\n * Returned by migrateStorageInVM().\n *\n * - Error result: { error: string } - serious failure (no context, etc.)\n * - Success result: { newStorageJson: StringifiedJson<BlockStorage>, info: string } - migration succeeded\n */\nexport type MigrationResult =\n | { error: string }\n | { error?: undefined; newStorageJson: StringifiedJson<BlockStorage>; info: string };\n\n/**\n * Result of args derivation from storage.\n * Returned by __pl_args_derive and __pl_prerunArgs_derive VM callbacks.\n */\ntype ArgsDeriveResult = { error: string } | { error?: undefined; value: unknown };\n\nexport class ProjectHelper {\n private readonly enrichmentTargetsCache = new LRUCache<\n string,\n EnrichmentTargetsValue,\n EnrichmentTargetsRequest\n >({\n max: 256,\n memoMethod: (_key, _value, { context }) => {\n return { value: this.calculateEnrichmentTargets(context) };\n },\n });\n\n constructor(\n private readonly quickJs: QuickJSWASMModule,\n public readonly logger: MiLogger = new ConsoleLoggerAdapter(),\n ) {}\n\n // =============================================================================\n // Args Derivation from Storage (V3+)\n // =============================================================================\n\n /**\n * Derives args directly from storage JSON using VM callback.\n * The VM extracts data from storage and calls the block's args() function.\n *\n * This allows the middle layer to work only with storage JSON,\n * without needing to know the underlying data structure.\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param storageJson Storage as JSON string\n * @returns The derived args object, or error if derivation fails\n */\n public deriveArgsFromStorage(\n blockConfig: BlockConfig,\n storageJson: string,\n ): ResultOrError<unknown> {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n return {\n error: new Error(\"deriveArgsFromStorage is only supported for model API version 2\"),\n };\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.ArgsDerive],\n extractCodeWithInfo(blockConfig),\n storageJson,\n ) as ArgsDeriveResult;\n\n if (result.error !== undefined) {\n return { error: new Error(result.error) };\n }\n return { value: result.value };\n } catch (e) {\n return { error: new Error(\"Args derivation from storage failed\", { cause: ensureError(e) }) };\n }\n }\n\n /**\n * Derives prerunArgs directly from storage JSON using VM callback.\n * Falls back to args() if prerunArgs is not defined in the block model.\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param storageJson Storage as JSON string\n * @returns The derived prerunArgs, or undefined if derivation fails\n */\n public derivePrerunArgsFromStorage(blockConfig: BlockConfig, storageJson: string): unknown {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"derivePrerunArgsFromStorage is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.PrerunArgsDerive],\n extractCodeWithInfo(blockConfig),\n storageJson,\n ) as ArgsDeriveResult;\n\n if (result.error !== undefined) {\n // Return undefined if derivation fails (skip block in staging)\n return undefined;\n }\n return result.value;\n } catch {\n // Return undefined if derivation fails (skip block in staging)\n return undefined;\n }\n }\n\n private calculateEnrichmentTargets(req: EnrichmentTargetsRequest): PlRef[] | undefined {\n const blockConfig = req.blockConfig();\n if (blockConfig.enrichmentTargets === undefined) return undefined;\n const args = req.args();\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.enrichmentTargets,\n extractCodeWithInfo(blockConfig),\n args,\n ) as PlRef[];\n return result;\n }\n\n public getEnrichmentTargets(\n blockConfig: () => BlockConfig,\n args: () => unknown,\n key?: { argsRid: SignedResourceId; blockPackRid: SignedResourceId },\n ): PlRef[] | undefined {\n const req = { blockConfig, args };\n if (key === undefined) return this.calculateEnrichmentTargets(req);\n const cacheKey = `${key.argsRid}:${key.blockPackRid}`;\n return this.enrichmentTargetsCache.memo(cacheKey, { context: req }).value;\n }\n\n // =============================================================================\n // VM-based Storage Operations\n // =============================================================================\n\n /**\n * Creates initial BlockStorage for a new block using VM-based transformation.\n * This calls the '__pl_storage_initial' callback registered by DataModel which:\n * - Gets initial data from DataModel.getDefaultData()\n * - Creates BlockStorage with correct version\n *\n * @param blockConfig The block configuration (provides the model code)\n * @returns Initial storage as JSON string\n * @throws Error if storage creation fails\n */\n public getInitialStorageInVM(blockConfig: BlockConfig): string {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"getInitialStorageInVM is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageInitial],\n extractCodeWithInfo(blockConfig),\n ) as string;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.getInitialStorageInVM] Initial storage creation failed\", {\n cause: e,\n }),\n );\n throw new Error(`Block initial storage creation failed: ${e}`);\n }\n }\n\n /**\n * Applies a state update using VM-based transformation.\n * This calls the model's `__pl_storage_applyUpdate` callback which:\n * - Normalizes current storage\n * - Updates state while preserving other fields (version, plugins)\n * - Returns the updated storage as JSON string\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param currentStorageJson Current storage as JSON string (must be defined)\n * @param newState New state from developer\n * @returns Updated storage as JSON string\n * @throws Error if storage update fails\n */\n public applyStorageUpdateInVM(\n blockConfig: BlockConfig,\n currentStorageJson: string,\n payload: { operation: string; value: unknown },\n ): string {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"applyStorageUpdateInVM is only supported for model API version 2\");\n }\n\n if (getDebugFlags().logJsExecStat) {\n this.logger.info(\n `[ProjectHelper.applyStorageUpdateInVM] currentStorageJson=${currentStorageJson.length}B, payload=${JSON.stringify(payload).length}B, operation=${payload.operation}`,\n );\n }\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageApplyUpdate],\n extractCodeWithInfo(blockConfig),\n currentStorageJson,\n payload,\n ) as string;\n return result;\n } catch (e) {\n const payloadJson = JSON.stringify(payload);\n this.logger.error(\n new Error(\n `[ProjectHelper.applyStorageUpdateInVM] Storage update failed (currentStorageJson=${currentStorageJson.length}B, payload=${payloadJson.length}B, operation=${payload.operation})`,\n { cause: e },\n ),\n );\n throw new Error(`Block storage update failed: ${e}`);\n }\n }\n\n /**\n * Gets storage debug view from raw storage data by calling the VM's __pl_storage_debugView callback.\n * Returns structured debug info about the storage (e.g., dataVersion).\n *\n * @param blockConfig Block configuration\n * @param rawStorageJson Raw storage as JSON string (or undefined)\n * @returns Storage debug view as JSON string (e.g., '{\"dataVersion\": \"v1\"}')\n */\n public getStorageDebugViewInVM(\n blockConfig: BlockConfig,\n rawStorageJson: string | undefined,\n ): StringifiedJson<StorageDebugView> | undefined {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"getStorageDebugViewInVM is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageDebugView],\n extractCodeWithInfo(blockConfig),\n rawStorageJson,\n ) as StringifiedJson<StorageDebugView>;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.getStorageDebugViewInVM] Get storage debug view failed\", {\n cause: e,\n }),\n );\n return undefined;\n }\n }\n\n // =============================================================================\n // Block State Migrations\n // =============================================================================\n\n /**\n * Runs block state migrations via VM-based transformation.\n * This calls the model's `__pl_storage_migrate` callback which:\n * - Normalizes current storage to get state and version\n * - Applies DataModel upgrade to reach target version key\n * - Runs all necessary migrations sequentially\n * - Returns new storage with updated state and version\n *\n * The middle layer doesn't need to know about dataVersion or storage internals.\n * All migration logic is encapsulated in the model.\n *\n * @param blockConfig The NEW block configuration (provides the model code with migrations)\n * @param currentStorageJson Current storage as JSON string (or undefined)\n * @returns MigrationResult with new storage or skip/error info\n */\n public migrateStorageInVM(\n blockConfig: BlockConfig,\n currentStorageJson: string | undefined,\n ): MigrationResult {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n return { error: \"migrateStorageInVM is only supported for model API version 2\" };\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageMigrate],\n extractCodeWithInfo(blockConfig),\n currentStorageJson,\n ) as MigrationResult;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.migrateStorageInVM] Migration failed\", { cause: e }),\n );\n return { error: `VM execution failed: ${e}` };\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -106,5 +106,5 @@ declare class ProjectHelper {
|
|
|
106
106
|
migrateStorageInVM(blockConfig: BlockConfig, currentStorageJson: string | undefined): MigrationResult;
|
|
107
107
|
}
|
|
108
108
|
//#endregion
|
|
109
|
-
export { ProjectHelper };
|
|
109
|
+
export { MigrationResult, ProjectHelper };
|
|
110
110
|
//# sourceMappingURL=project_helper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project_helper.d.ts","names":[],"sources":["../../src/model/project_helper.ts"],"mappings":";;;;;;;;;;AAgCA;;;;;KAAY,eAAA;EACN,KAAA;AAAA;EACA,KAAA;EAAmB,cAAA,EAAgB,
|
|
1
|
+
{"version":3,"file":"project_helper.d.ts","names":[],"sources":["../../src/model/project_helper.ts"],"mappings":";;;;;;;;;;AAgCA;;;;;KAAY,eAAA;EACN,KAAA;AAAA;EACA,KAAA;EAAmB,cAAA,EAAgB,eAAe,CAAC,YAAA;EAAe,IAAA;AAAA;AAAA,cAQ3D,aAAA;EAAA,iBAaQ,OAAA;EAAA,SACD,MAAA,EAAQ,QAAA;EAAA,iBAbT,sBAAA;cAYE,OAAA,EAAS,iBAAA,EACV,MAAA,GAAQ,QAAA;EAAA;;;;;;;;;;;EAkBnB,qBAAA,CACL,WAAA,EAAa,WAAA,EACb,WAAA,WACC,aAAA;EA+KA;;;;;;;;EA/II,2BAAA,CAA4B,WAAA,EAAa,WAAA,EAAa,WAAA;EAAA,QAwBrD,0BAAA;EAaD,oBAAA,CACL,WAAA,QAAmB,WAAA,EACnB,IAAA,iBACA,GAAA;IAAQ,OAAA,EAAS,gBAAA;IAAkB,YAAA,EAAc,gBAAA;EAAA,IAChD,KAAA;EA5EI;;;;;;;;;;EAiGA,qBAAA,CAAsB,WAAA,EAAa,WAAA;EAxBrB;;;;;;;;;;;;;EA2Dd,sBAAA,CACL,WAAA,EAAa,WAAA,EACb,kBAAA,UACA,OAAA;IAAW,SAAA;IAAmB,KAAA;EAAA;EAAA;;;;;;;;EAwCzB,uBAAA,CACL,WAAA,EAAa,WAAA,EACb,cAAA,uBACC,eAAA,CAAgB,gBAAA;EA2CJ;;;;;AAEG;;;;;;;;;;EAHX,kBAAA,CACL,WAAA,EAAa,WAAA,EACb,kBAAA,uBACC,eAAA;AAAA"}
|
|
@@ -5,6 +5,8 @@ import { ConsoleLoggerAdapter } from "@milaboratories/ts-helpers";
|
|
|
5
5
|
import { LRUCache } from "lru-cache";
|
|
6
6
|
//#region src/model/project_helper.ts
|
|
7
7
|
var ProjectHelper = class {
|
|
8
|
+
quickJs;
|
|
9
|
+
logger;
|
|
8
10
|
enrichmentTargetsCache = new LRUCache({
|
|
9
11
|
max: 256,
|
|
10
12
|
memoMethod: (_key, _value, { context }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project_helper.js","names":[],"sources":["../../src/model/project_helper.ts"],"sourcesContent":["import type { ResultOrError, BlockConfig, BlockStorage, PlRef } from \"@platforma-sdk/model\";\nimport type { StringifiedJson } from \"@milaboratories/pl-model-common\";\nimport {\n extractCodeWithInfo,\n ensureError,\n BlockStorageFacadeCallbacks,\n BLOCK_STORAGE_FACADE_VERSION,\n} from \"@platforma-sdk/model\";\nimport { LRUCache } from \"lru-cache\";\nimport type { QuickJSWASMModule } from \"quickjs-emscripten\";\nimport { executeSingleLambda } from \"../js_render\";\nimport type { SignedResourceId } from \"@milaboratories/pl-client\";\nimport { ConsoleLoggerAdapter, type MiLogger } from \"@milaboratories/ts-helpers\";\nimport type { StorageDebugView } from \"@milaboratories/pl-model-middle-layer\";\nimport { getDebugFlags } from \"../debug\";\n\ntype EnrichmentTargetsRequest = {\n blockConfig: () => BlockConfig;\n args: () => unknown;\n};\n\ntype EnrichmentTargetsValue = {\n value: PlRef[] | undefined;\n};\n\n/**\n * Result of VM-based storage migration.\n * Returned by migrateStorageInVM().\n *\n * - Error result: { error: string } - serious failure (no context, etc.)\n * - Success result: { newStorageJson: StringifiedJson<BlockStorage>, info: string } - migration succeeded\n */\nexport type MigrationResult =\n | { error: string }\n | { error?: undefined; newStorageJson: StringifiedJson<BlockStorage>; info: string };\n\n/**\n * Result of args derivation from storage.\n * Returned by __pl_args_derive and __pl_prerunArgs_derive VM callbacks.\n */\ntype ArgsDeriveResult = { error: string } | { error?: undefined; value: unknown };\n\nexport class ProjectHelper {\n private readonly enrichmentTargetsCache = new LRUCache<\n string,\n EnrichmentTargetsValue,\n EnrichmentTargetsRequest\n >({\n max: 256,\n memoMethod: (_key, _value, { context }) => {\n return { value: this.calculateEnrichmentTargets(context) };\n },\n });\n\n constructor(\n private readonly quickJs: QuickJSWASMModule,\n public readonly logger: MiLogger = new ConsoleLoggerAdapter(),\n ) {}\n\n // =============================================================================\n // Args Derivation from Storage (V3+)\n // =============================================================================\n\n /**\n * Derives args directly from storage JSON using VM callback.\n * The VM extracts data from storage and calls the block's args() function.\n *\n * This allows the middle layer to work only with storage JSON,\n * without needing to know the underlying data structure.\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param storageJson Storage as JSON string\n * @returns The derived args object, or error if derivation fails\n */\n public deriveArgsFromStorage(\n blockConfig: BlockConfig,\n storageJson: string,\n ): ResultOrError<unknown> {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n return {\n error: new Error(\"deriveArgsFromStorage is only supported for model API version 2\"),\n };\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.ArgsDerive],\n extractCodeWithInfo(blockConfig),\n storageJson,\n ) as ArgsDeriveResult;\n\n if (result.error !== undefined) {\n return { error: new Error(result.error) };\n }\n return { value: result.value };\n } catch (e) {\n return { error: new Error(\"Args derivation from storage failed\", { cause: ensureError(e) }) };\n }\n }\n\n /**\n * Derives prerunArgs directly from storage JSON using VM callback.\n * Falls back to args() if prerunArgs is not defined in the block model.\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param storageJson Storage as JSON string\n * @returns The derived prerunArgs, or undefined if derivation fails\n */\n public derivePrerunArgsFromStorage(blockConfig: BlockConfig, storageJson: string): unknown {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"derivePrerunArgsFromStorage is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.PrerunArgsDerive],\n extractCodeWithInfo(blockConfig),\n storageJson,\n ) as ArgsDeriveResult;\n\n if (result.error !== undefined) {\n // Return undefined if derivation fails (skip block in staging)\n return undefined;\n }\n return result.value;\n } catch {\n // Return undefined if derivation fails (skip block in staging)\n return undefined;\n }\n }\n\n private calculateEnrichmentTargets(req: EnrichmentTargetsRequest): PlRef[] | undefined {\n const blockConfig = req.blockConfig();\n if (blockConfig.enrichmentTargets === undefined) return undefined;\n const args = req.args();\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.enrichmentTargets,\n extractCodeWithInfo(blockConfig),\n args,\n ) as PlRef[];\n return result;\n }\n\n public getEnrichmentTargets(\n blockConfig: () => BlockConfig,\n args: () => unknown,\n key?: { argsRid: SignedResourceId; blockPackRid: SignedResourceId },\n ): PlRef[] | undefined {\n const req = { blockConfig, args };\n if (key === undefined) return this.calculateEnrichmentTargets(req);\n const cacheKey = `${key.argsRid}:${key.blockPackRid}`;\n return this.enrichmentTargetsCache.memo(cacheKey, { context: req }).value;\n }\n\n // =============================================================================\n // VM-based Storage Operations\n // =============================================================================\n\n /**\n * Creates initial BlockStorage for a new block using VM-based transformation.\n * This calls the '__pl_storage_initial' callback registered by DataModel which:\n * - Gets initial data from DataModel.getDefaultData()\n * - Creates BlockStorage with correct version\n *\n * @param blockConfig The block configuration (provides the model code)\n * @returns Initial storage as JSON string\n * @throws Error if storage creation fails\n */\n public getInitialStorageInVM(blockConfig: BlockConfig): string {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"getInitialStorageInVM is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageInitial],\n extractCodeWithInfo(blockConfig),\n ) as string;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.getInitialStorageInVM] Initial storage creation failed\", {\n cause: e,\n }),\n );\n throw new Error(`Block initial storage creation failed: ${e}`);\n }\n }\n\n /**\n * Applies a state update using VM-based transformation.\n * This calls the model's `__pl_storage_applyUpdate` callback which:\n * - Normalizes current storage\n * - Updates state while preserving other fields (version, plugins)\n * - Returns the updated storage as JSON string\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param currentStorageJson Current storage as JSON string (must be defined)\n * @param newState New state from developer\n * @returns Updated storage as JSON string\n * @throws Error if storage update fails\n */\n public applyStorageUpdateInVM(\n blockConfig: BlockConfig,\n currentStorageJson: string,\n payload: { operation: string; value: unknown },\n ): string {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"applyStorageUpdateInVM is only supported for model API version 2\");\n }\n\n if (getDebugFlags().logJsExecStat) {\n this.logger.info(\n `[ProjectHelper.applyStorageUpdateInVM] currentStorageJson=${currentStorageJson.length}B, payload=${JSON.stringify(payload).length}B, operation=${payload.operation}`,\n );\n }\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageApplyUpdate],\n extractCodeWithInfo(blockConfig),\n currentStorageJson,\n payload,\n ) as string;\n return result;\n } catch (e) {\n const payloadJson = JSON.stringify(payload);\n this.logger.error(\n new Error(\n `[ProjectHelper.applyStorageUpdateInVM] Storage update failed (currentStorageJson=${currentStorageJson.length}B, payload=${payloadJson.length}B, operation=${payload.operation})`,\n { cause: e },\n ),\n );\n throw new Error(`Block storage update failed: ${e}`);\n }\n }\n\n /**\n * Gets storage debug view from raw storage data by calling the VM's __pl_storage_debugView callback.\n * Returns structured debug info about the storage (e.g., dataVersion).\n *\n * @param blockConfig Block configuration\n * @param rawStorageJson Raw storage as JSON string (or undefined)\n * @returns Storage debug view as JSON string (e.g., '{\"dataVersion\": \"v1\"}')\n */\n public getStorageDebugViewInVM(\n blockConfig: BlockConfig,\n rawStorageJson: string | undefined,\n ): StringifiedJson<StorageDebugView> | undefined {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"getStorageDebugViewInVM is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageDebugView],\n extractCodeWithInfo(blockConfig),\n rawStorageJson,\n ) as StringifiedJson<StorageDebugView>;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.getStorageDebugViewInVM] Get storage debug view failed\", {\n cause: e,\n }),\n );\n return undefined;\n }\n }\n\n // =============================================================================\n // Block State Migrations\n // =============================================================================\n\n /**\n * Runs block state migrations via VM-based transformation.\n * This calls the model's `__pl_storage_migrate` callback which:\n * - Normalizes current storage to get state and version\n * - Applies DataModel upgrade to reach target version key\n * - Runs all necessary migrations sequentially\n * - Returns new storage with updated state and version\n *\n * The middle layer doesn't need to know about dataVersion or storage internals.\n * All migration logic is encapsulated in the model.\n *\n * @param blockConfig The NEW block configuration (provides the model code with migrations)\n * @param currentStorageJson Current storage as JSON string (or undefined)\n * @returns MigrationResult with new storage or skip/error info\n */\n public migrateStorageInVM(\n blockConfig: BlockConfig,\n currentStorageJson: string | undefined,\n ): MigrationResult {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n return { error: \"migrateStorageInVM is only supported for model API version 2\" };\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageMigrate],\n extractCodeWithInfo(blockConfig),\n currentStorageJson,\n ) as MigrationResult;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.migrateStorageInVM] Migration failed\", { cause: e }),\n );\n return { error: `VM execution failed: ${e}` };\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"project_helper.js","names":[],"sources":["../../src/model/project_helper.ts"],"sourcesContent":["import type { ResultOrError, BlockConfig, BlockStorage, PlRef } from \"@platforma-sdk/model\";\nimport type { StringifiedJson } from \"@milaboratories/pl-model-common\";\nimport {\n extractCodeWithInfo,\n ensureError,\n BlockStorageFacadeCallbacks,\n BLOCK_STORAGE_FACADE_VERSION,\n} from \"@platforma-sdk/model\";\nimport { LRUCache } from \"lru-cache\";\nimport type { QuickJSWASMModule } from \"quickjs-emscripten\";\nimport { executeSingleLambda } from \"../js_render\";\nimport type { SignedResourceId } from \"@milaboratories/pl-client\";\nimport { ConsoleLoggerAdapter, type MiLogger } from \"@milaboratories/ts-helpers\";\nimport type { StorageDebugView } from \"@milaboratories/pl-model-middle-layer\";\nimport { getDebugFlags } from \"../debug\";\n\ntype EnrichmentTargetsRequest = {\n blockConfig: () => BlockConfig;\n args: () => unknown;\n};\n\ntype EnrichmentTargetsValue = {\n value: PlRef[] | undefined;\n};\n\n/**\n * Result of VM-based storage migration.\n * Returned by migrateStorageInVM().\n *\n * - Error result: { error: string } - serious failure (no context, etc.)\n * - Success result: { newStorageJson: StringifiedJson<BlockStorage>, info: string } - migration succeeded\n */\nexport type MigrationResult =\n | { error: string }\n | { error?: undefined; newStorageJson: StringifiedJson<BlockStorage>; info: string };\n\n/**\n * Result of args derivation from storage.\n * Returned by __pl_args_derive and __pl_prerunArgs_derive VM callbacks.\n */\ntype ArgsDeriveResult = { error: string } | { error?: undefined; value: unknown };\n\nexport class ProjectHelper {\n private readonly enrichmentTargetsCache = new LRUCache<\n string,\n EnrichmentTargetsValue,\n EnrichmentTargetsRequest\n >({\n max: 256,\n memoMethod: (_key, _value, { context }) => {\n return { value: this.calculateEnrichmentTargets(context) };\n },\n });\n\n constructor(\n private readonly quickJs: QuickJSWASMModule,\n public readonly logger: MiLogger = new ConsoleLoggerAdapter(),\n ) {}\n\n // =============================================================================\n // Args Derivation from Storage (V3+)\n // =============================================================================\n\n /**\n * Derives args directly from storage JSON using VM callback.\n * The VM extracts data from storage and calls the block's args() function.\n *\n * This allows the middle layer to work only with storage JSON,\n * without needing to know the underlying data structure.\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param storageJson Storage as JSON string\n * @returns The derived args object, or error if derivation fails\n */\n public deriveArgsFromStorage(\n blockConfig: BlockConfig,\n storageJson: string,\n ): ResultOrError<unknown> {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n return {\n error: new Error(\"deriveArgsFromStorage is only supported for model API version 2\"),\n };\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.ArgsDerive],\n extractCodeWithInfo(blockConfig),\n storageJson,\n ) as ArgsDeriveResult;\n\n if (result.error !== undefined) {\n return { error: new Error(result.error) };\n }\n return { value: result.value };\n } catch (e) {\n return { error: new Error(\"Args derivation from storage failed\", { cause: ensureError(e) }) };\n }\n }\n\n /**\n * Derives prerunArgs directly from storage JSON using VM callback.\n * Falls back to args() if prerunArgs is not defined in the block model.\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param storageJson Storage as JSON string\n * @returns The derived prerunArgs, or undefined if derivation fails\n */\n public derivePrerunArgsFromStorage(blockConfig: BlockConfig, storageJson: string): unknown {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"derivePrerunArgsFromStorage is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.PrerunArgsDerive],\n extractCodeWithInfo(blockConfig),\n storageJson,\n ) as ArgsDeriveResult;\n\n if (result.error !== undefined) {\n // Return undefined if derivation fails (skip block in staging)\n return undefined;\n }\n return result.value;\n } catch {\n // Return undefined if derivation fails (skip block in staging)\n return undefined;\n }\n }\n\n private calculateEnrichmentTargets(req: EnrichmentTargetsRequest): PlRef[] | undefined {\n const blockConfig = req.blockConfig();\n if (blockConfig.enrichmentTargets === undefined) return undefined;\n const args = req.args();\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.enrichmentTargets,\n extractCodeWithInfo(blockConfig),\n args,\n ) as PlRef[];\n return result;\n }\n\n public getEnrichmentTargets(\n blockConfig: () => BlockConfig,\n args: () => unknown,\n key?: { argsRid: SignedResourceId; blockPackRid: SignedResourceId },\n ): PlRef[] | undefined {\n const req = { blockConfig, args };\n if (key === undefined) return this.calculateEnrichmentTargets(req);\n const cacheKey = `${key.argsRid}:${key.blockPackRid}`;\n return this.enrichmentTargetsCache.memo(cacheKey, { context: req }).value;\n }\n\n // =============================================================================\n // VM-based Storage Operations\n // =============================================================================\n\n /**\n * Creates initial BlockStorage for a new block using VM-based transformation.\n * This calls the '__pl_storage_initial' callback registered by DataModel which:\n * - Gets initial data from DataModel.getDefaultData()\n * - Creates BlockStorage with correct version\n *\n * @param blockConfig The block configuration (provides the model code)\n * @returns Initial storage as JSON string\n * @throws Error if storage creation fails\n */\n public getInitialStorageInVM(blockConfig: BlockConfig): string {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"getInitialStorageInVM is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageInitial],\n extractCodeWithInfo(blockConfig),\n ) as string;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.getInitialStorageInVM] Initial storage creation failed\", {\n cause: e,\n }),\n );\n throw new Error(`Block initial storage creation failed: ${e}`);\n }\n }\n\n /**\n * Applies a state update using VM-based transformation.\n * This calls the model's `__pl_storage_applyUpdate` callback which:\n * - Normalizes current storage\n * - Updates state while preserving other fields (version, plugins)\n * - Returns the updated storage as JSON string\n *\n * @param blockConfig The block configuration (provides the model code)\n * @param currentStorageJson Current storage as JSON string (must be defined)\n * @param newState New state from developer\n * @returns Updated storage as JSON string\n * @throws Error if storage update fails\n */\n public applyStorageUpdateInVM(\n blockConfig: BlockConfig,\n currentStorageJson: string,\n payload: { operation: string; value: unknown },\n ): string {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"applyStorageUpdateInVM is only supported for model API version 2\");\n }\n\n if (getDebugFlags().logJsExecStat) {\n this.logger.info(\n `[ProjectHelper.applyStorageUpdateInVM] currentStorageJson=${currentStorageJson.length}B, payload=${JSON.stringify(payload).length}B, operation=${payload.operation}`,\n );\n }\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageApplyUpdate],\n extractCodeWithInfo(blockConfig),\n currentStorageJson,\n payload,\n ) as string;\n return result;\n } catch (e) {\n const payloadJson = JSON.stringify(payload);\n this.logger.error(\n new Error(\n `[ProjectHelper.applyStorageUpdateInVM] Storage update failed (currentStorageJson=${currentStorageJson.length}B, payload=${payloadJson.length}B, operation=${payload.operation})`,\n { cause: e },\n ),\n );\n throw new Error(`Block storage update failed: ${e}`);\n }\n }\n\n /**\n * Gets storage debug view from raw storage data by calling the VM's __pl_storage_debugView callback.\n * Returns structured debug info about the storage (e.g., dataVersion).\n *\n * @param blockConfig Block configuration\n * @param rawStorageJson Raw storage as JSON string (or undefined)\n * @returns Storage debug view as JSON string (e.g., '{\"dataVersion\": \"v1\"}')\n */\n public getStorageDebugViewInVM(\n blockConfig: BlockConfig,\n rawStorageJson: string | undefined,\n ): StringifiedJson<StorageDebugView> | undefined {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n throw new Error(\"getStorageDebugViewInVM is only supported for model API version 2\");\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageDebugView],\n extractCodeWithInfo(blockConfig),\n rawStorageJson,\n ) as StringifiedJson<StorageDebugView>;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.getStorageDebugViewInVM] Get storage debug view failed\", {\n cause: e,\n }),\n );\n return undefined;\n }\n }\n\n // =============================================================================\n // Block State Migrations\n // =============================================================================\n\n /**\n * Runs block state migrations via VM-based transformation.\n * This calls the model's `__pl_storage_migrate` callback which:\n * - Normalizes current storage to get state and version\n * - Applies DataModel upgrade to reach target version key\n * - Runs all necessary migrations sequentially\n * - Returns new storage with updated state and version\n *\n * The middle layer doesn't need to know about dataVersion or storage internals.\n * All migration logic is encapsulated in the model.\n *\n * @param blockConfig The NEW block configuration (provides the model code with migrations)\n * @param currentStorageJson Current storage as JSON string (or undefined)\n * @returns MigrationResult with new storage or skip/error info\n */\n public migrateStorageInVM(\n blockConfig: BlockConfig,\n currentStorageJson: string | undefined,\n ): MigrationResult {\n if (blockConfig.modelAPIVersion !== BLOCK_STORAGE_FACADE_VERSION) {\n return { error: \"migrateStorageInVM is only supported for model API version 2\" };\n }\n\n try {\n const result = executeSingleLambda(\n this.quickJs,\n blockConfig.blockLifecycleCallbacks[BlockStorageFacadeCallbacks.StorageMigrate],\n extractCodeWithInfo(blockConfig),\n currentStorageJson,\n ) as MigrationResult;\n return result;\n } catch (e) {\n this.logger.error(\n new Error(\"[ProjectHelper.migrateStorageInVM] Migration failed\", { cause: e }),\n );\n return { error: `VM execution failed: ${e}` };\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -29,7 +29,7 @@ const ServiceTemplateCacheFieldPrefix = "__serviceTemplate_";
|
|
|
29
29
|
function getServiceTemplateField(hash) {
|
|
30
30
|
return `${ServiceTemplateCacheFieldPrefix}${hash}`;
|
|
31
31
|
}
|
|
32
|
-
const FieldsToDuplicate = new Set([
|
|
32
|
+
const FieldsToDuplicate = /* @__PURE__ */ new Set([
|
|
33
33
|
"blockPack",
|
|
34
34
|
"blockSettings",
|
|
35
35
|
"blockStorage",
|
|
@@ -68,6 +68,7 @@ exports.ProjectStructureAuthorKey = ProjectStructureAuthorKey;
|
|
|
68
68
|
exports.ProjectStructureKey = ProjectStructureKey;
|
|
69
69
|
exports.SchemaVersionCurrent = SchemaVersionCurrent;
|
|
70
70
|
exports.SchemaVersionKey = SchemaVersionKey;
|
|
71
|
+
exports.ServiceTemplateCacheFieldPrefix = ServiceTemplateCacheFieldPrefix;
|
|
71
72
|
exports.blockArgsAuthorKey = blockArgsAuthorKey;
|
|
72
73
|
exports.getServiceTemplateField = getServiceTemplateField;
|
|
73
74
|
exports.parseProjectField = parseProjectField;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project_model.cjs","names":[],"sources":["../../src/model/project_model.ts"],"sourcesContent":["import type { ResourceType } from \"@milaboratories/pl-client\";\nimport type { ProjectId } from \"@milaboratories/pl-model-common\";\nimport type {\n ProjectListEntry as ProjectListEntryFromModel,\n ProjectMeta,\n} from \"@milaboratories/pl-model-middle-layer\";\nimport type { BlockRenderingMode } from \"@platforma-sdk/model\";\n\nexport type { ProjectId };\n\nexport interface ProjectListEntry extends Omit<ProjectListEntryFromModel, \"id\"> {\n /** Unique project identifier in middle layer. Use to operate with given project. */\n id: ProjectId;\n}\n\n/** Entry representing a single block in block structure */\nexport interface Block {\n /** Unique block id */\n readonly id: string;\n\n /**\n * Label shown to the user\n * @deprecated\n * */\n label: string;\n\n /** How to approach block rendering */\n renderingMode: BlockRenderingMode;\n}\n\n/** Block group in block structure */\nexport interface BlockGroup {\n /** Unique group id */\n readonly id: string;\n\n /** Label shown to the user */\n label: string;\n\n /** Blocks */\n blocks: Block[];\n}\n\n/** Root of block structure value */\nexport interface ProjectStructure {\n /** The structure */\n readonly groups: BlockGroup[];\n}\n\nexport const InitialBlockStructure: ProjectStructure = {\n groups: [{ id: \"default\", label: \"Default\", blocks: [] }],\n};\n\n/** Root of project rendering state */\nexport interface ProjectRenderingState {\n /** Timestamp of last staging rendering event */\n stagingRefreshTimestamp: number;\n\n /** Blocks with detached production state, i.e. some of the dependencies of\n * such blocks were re-rendered, but their state was left \"as is\". */\n blocksInLimbo: string[];\n}\n\nexport const InitialProjectRenderingState: ProjectRenderingState = {\n stagingRefreshTimestamp: 0,\n blocksInLimbo: [],\n};\n\nexport const InitialBlockMeta: ProjectMeta = {\n label: \"New Project\",\n};\n\n//\n// Pl Model\n//\n\nexport const ProjectResourceType: ResourceType = { name: \"UserProject\", version: \"2\" };\n\nexport const SchemaVersionKey = \"SchemaVersion\";\nexport const SchemaVersionV2 = \"2\";\nexport const SchemaVersionV3 = \"3\";\nexport const SchemaVersionCurrent = \"4\";\n\nexport const ProjectCreatedTimestamp = \"ProjectCreated\";\nexport const ProjectLastModifiedTimestamp = \"ProjectLastModified\";\nexport const ProjectMetaKey = \"ProjectMeta\";\nexport const ProjectStructureKey = \"ProjectStructure\";\nexport const BlockRenderingStateKey = \"BlockRenderingState\";\n\nexport const BlockArgsAuthorKeyPrefix = \"BlockArgsAuthor/\";\nexport const BlockArgsAuthorKeyPattern = /^BlockArgsAuthor\\/(?<blockid>.*)$/;\n\nexport function blockArgsAuthorKey(blockId: string): string {\n return `${BlockArgsAuthorKeyPrefix}${blockId}`;\n}\n\nexport const ProjectStructureAuthorKey = \"ProjectStructureAuthor\";\n\nexport const ServiceTemplateCacheFieldPrefix = \"__serviceTemplate_\";\n\nexport function getServiceTemplateField(hash: string): string {\n return `${ServiceTemplateCacheFieldPrefix}${hash}`;\n}\n\nexport interface ProjectField {\n blockId: string;\n fieldName:\n | \"blockPack\"\n | \"blockSettings\"\n | \"blockStorage\" // Persistent storage for v3 blocks (state, plugins data, etc.)\n | \"prodArgs\"\n | \"currentArgs\"\n | \"currentPrerunArgs\" // Derived args for staging/prerun rendering (from prerunArgs() or args())\n | \"prodChainCtx\" // Pre-built production context chain node (accumulated prodCtx from all blocks above)\n | \"prodCtx\"\n | \"prodUiCtx\"\n | \"prodOutput\"\n | \"prodCtxPrevious\"\n | \"prodUiCtxPrevious\"\n | \"prodOutputPrevious\"\n | \"stagingCtx\"\n | \"stagingUiCtx\"\n | \"stagingOutput\"\n | \"stagingCtxPrevious\"\n | \"stagingUiCtxPrevious\"\n | \"stagingOutputPrevious\";\n}\n\nexport const FieldsToDuplicate: Set<ProjectField[\"fieldName\"]> = new Set([\n \"blockPack\",\n \"blockSettings\",\n \"blockStorage\",\n \"prodArgs\",\n \"currentArgs\",\n \"currentPrerunArgs\",\n \"prodCtx\",\n \"prodUiCtx\",\n \"prodOutput\",\n]);\n\nexport function projectFieldName(blockId: string, fieldName: ProjectField[\"fieldName\"]): string {\n return `${blockId}-${fieldName}`;\n}\n\nconst projectFieldPattern =\n /^(?<blockId>.*)-(?<fieldName>blockPack|blockSettings|blockStorage|inputsValid|prodArgs|currentArgs|currentPrerunArgs|prodChainCtx|prodCtx|prodUiCtx|prodOutput|prodCtxPrevious|prodUiCtxPrevious|prodOutputPrevious|stagingCtx|stagingUiCtx|stagingOutput|stagingCtxPrevious|stagingUiCtxPrevious|stagingOutputPrevious)$/;\n\nexport function parseProjectField(name: string): ProjectField | undefined {\n const match = name.match(projectFieldPattern);\n if (match === null) return undefined;\n const { blockId, fieldName } = match.groups!;\n return { blockId, fieldName } as ProjectField;\n}\n"],"mappings":";AAgDA,MAAa,wBAA0C,EACrD,QAAQ,CAAC;CAAE,IAAI;CAAW,OAAO;CAAW,QAAQ,
|
|
1
|
+
{"version":3,"file":"project_model.cjs","names":[],"sources":["../../src/model/project_model.ts"],"sourcesContent":["import type { ResourceType } from \"@milaboratories/pl-client\";\nimport type { ProjectId } from \"@milaboratories/pl-model-common\";\nimport type {\n ProjectListEntry as ProjectListEntryFromModel,\n ProjectMeta,\n} from \"@milaboratories/pl-model-middle-layer\";\nimport type { BlockRenderingMode } from \"@platforma-sdk/model\";\n\nexport type { ProjectId };\n\nexport interface ProjectListEntry extends Omit<ProjectListEntryFromModel, \"id\"> {\n /** Unique project identifier in middle layer. Use to operate with given project. */\n id: ProjectId;\n}\n\n/** Entry representing a single block in block structure */\nexport interface Block {\n /** Unique block id */\n readonly id: string;\n\n /**\n * Label shown to the user\n * @deprecated\n * */\n label: string;\n\n /** How to approach block rendering */\n renderingMode: BlockRenderingMode;\n}\n\n/** Block group in block structure */\nexport interface BlockGroup {\n /** Unique group id */\n readonly id: string;\n\n /** Label shown to the user */\n label: string;\n\n /** Blocks */\n blocks: Block[];\n}\n\n/** Root of block structure value */\nexport interface ProjectStructure {\n /** The structure */\n readonly groups: BlockGroup[];\n}\n\nexport const InitialBlockStructure: ProjectStructure = {\n groups: [{ id: \"default\", label: \"Default\", blocks: [] }],\n};\n\n/** Root of project rendering state */\nexport interface ProjectRenderingState {\n /** Timestamp of last staging rendering event */\n stagingRefreshTimestamp: number;\n\n /** Blocks with detached production state, i.e. some of the dependencies of\n * such blocks were re-rendered, but their state was left \"as is\". */\n blocksInLimbo: string[];\n}\n\nexport const InitialProjectRenderingState: ProjectRenderingState = {\n stagingRefreshTimestamp: 0,\n blocksInLimbo: [],\n};\n\nexport const InitialBlockMeta: ProjectMeta = {\n label: \"New Project\",\n};\n\n//\n// Pl Model\n//\n\nexport const ProjectResourceType: ResourceType = { name: \"UserProject\", version: \"2\" };\n\nexport const SchemaVersionKey = \"SchemaVersion\";\nexport const SchemaVersionV2 = \"2\";\nexport const SchemaVersionV3 = \"3\";\nexport const SchemaVersionCurrent = \"4\";\n\nexport const ProjectCreatedTimestamp = \"ProjectCreated\";\nexport const ProjectLastModifiedTimestamp = \"ProjectLastModified\";\nexport const ProjectMetaKey = \"ProjectMeta\";\nexport const ProjectStructureKey = \"ProjectStructure\";\nexport const BlockRenderingStateKey = \"BlockRenderingState\";\n\nexport const BlockArgsAuthorKeyPrefix = \"BlockArgsAuthor/\";\nexport const BlockArgsAuthorKeyPattern = /^BlockArgsAuthor\\/(?<blockid>.*)$/;\n\nexport function blockArgsAuthorKey(blockId: string): string {\n return `${BlockArgsAuthorKeyPrefix}${blockId}`;\n}\n\nexport const ProjectStructureAuthorKey = \"ProjectStructureAuthor\";\n\nexport const ServiceTemplateCacheFieldPrefix = \"__serviceTemplate_\";\n\nexport function getServiceTemplateField(hash: string): string {\n return `${ServiceTemplateCacheFieldPrefix}${hash}`;\n}\n\nexport interface ProjectField {\n blockId: string;\n fieldName:\n | \"blockPack\"\n | \"blockSettings\"\n | \"blockStorage\" // Persistent storage for v3 blocks (state, plugins data, etc.)\n | \"prodArgs\"\n | \"currentArgs\"\n | \"currentPrerunArgs\" // Derived args for staging/prerun rendering (from prerunArgs() or args())\n | \"prodChainCtx\" // Pre-built production context chain node (accumulated prodCtx from all blocks above)\n | \"prodCtx\"\n | \"prodUiCtx\"\n | \"prodOutput\"\n | \"prodCtxPrevious\"\n | \"prodUiCtxPrevious\"\n | \"prodOutputPrevious\"\n | \"stagingCtx\"\n | \"stagingUiCtx\"\n | \"stagingOutput\"\n | \"stagingCtxPrevious\"\n | \"stagingUiCtxPrevious\"\n | \"stagingOutputPrevious\";\n}\n\nexport const FieldsToDuplicate: Set<ProjectField[\"fieldName\"]> = new Set([\n \"blockPack\",\n \"blockSettings\",\n \"blockStorage\",\n \"prodArgs\",\n \"currentArgs\",\n \"currentPrerunArgs\",\n \"prodCtx\",\n \"prodUiCtx\",\n \"prodOutput\",\n]);\n\nexport function projectFieldName(blockId: string, fieldName: ProjectField[\"fieldName\"]): string {\n return `${blockId}-${fieldName}`;\n}\n\nconst projectFieldPattern =\n /^(?<blockId>.*)-(?<fieldName>blockPack|blockSettings|blockStorage|inputsValid|prodArgs|currentArgs|currentPrerunArgs|prodChainCtx|prodCtx|prodUiCtx|prodOutput|prodCtxPrevious|prodUiCtxPrevious|prodOutputPrevious|stagingCtx|stagingUiCtx|stagingOutput|stagingCtxPrevious|stagingUiCtxPrevious|stagingOutputPrevious)$/;\n\nexport function parseProjectField(name: string): ProjectField | undefined {\n const match = name.match(projectFieldPattern);\n if (match === null) return undefined;\n const { blockId, fieldName } = match.groups!;\n return { blockId, fieldName } as ProjectField;\n}\n"],"mappings":";AAgDA,MAAa,wBAA0C,EACrD,QAAQ,CAAC;CAAE,IAAI;CAAW,OAAO;CAAW,QAAQ,CAAC;AAAE,CAAC,EAC1D;AAYA,MAAa,+BAAsD;CACjE,yBAAyB;CACzB,eAAe,CAAC;AAClB;AAEA,MAAa,mBAAgC,EAC3C,OAAO,cACT;AAMA,MAAa,sBAAoC;CAAE,MAAM;CAAe,SAAS;AAAI;AAErF,MAAa,mBAAmB;AAGhC,MAAa,uBAAuB;AAEpC,MAAa,0BAA0B;AACvC,MAAa,+BAA+B;AAC5C,MAAa,iBAAiB;AAC9B,MAAa,sBAAsB;AACnC,MAAa,yBAAyB;AAEtC,MAAa,2BAA2B;AAGxC,SAAgB,mBAAmB,SAAyB;CAC1D,OAAO,GAAG,2BAA2B;AACvC;AAEA,MAAa,4BAA4B;AAEzC,MAAa,kCAAkC;AAE/C,SAAgB,wBAAwB,MAAsB;CAC5D,OAAO,GAAG,kCAAkC;AAC9C;AA0BA,MAAa,oCAAoD,IAAI,IAAI;CACvE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAgB,iBAAiB,SAAiB,WAA8C;CAC9F,OAAO,GAAG,QAAQ,GAAG;AACvB;AAEA,MAAM,sBACJ;AAEF,SAAgB,kBAAkB,MAAwC;CACxE,MAAM,QAAQ,KAAK,MAAM,mBAAmB;CAC5C,IAAI,UAAU,MAAM,OAAO,KAAA;CAC3B,MAAM,EAAE,SAAS,cAAc,MAAM;CACrC,OAAO;EAAE;EAAS;CAAU;AAC9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project_model.d.ts","names":[],"sources":["../../src/model/project_model.ts"],"mappings":";;;;;UAUiB,kBAAA,SAAyB,IAAA,CAAK,gBAAA;EAA9B;EAEf,EAAA,EAAI,SAAA;AAAA;AAAA,cA+DO,mBAAA,EAAqB,
|
|
1
|
+
{"version":3,"file":"project_model.d.ts","names":[],"sources":["../../src/model/project_model.ts"],"mappings":";;;;;UAUiB,kBAAA,SAAyB,IAAA,CAAK,gBAAA;EAA9B;EAEf,EAAA,EAAI,SAAA;AAAA;AAAA,cA+DO,mBAAA,EAAqB,YAAoD;AAAA,cAEzE,gBAAA;AAAA,cAGA,oBAAA;AAAA,cAEA,uBAAA;AAAA,cACA,4BAAA;AAAA,cACA,cAAA;AAAA,cACA,mBAAA;AAAA,cAGA,wBAAA;AAAA,cAOA,yBAAA;AAAA,UAQI,YAAA;EACf,OAAA;EACA,SAAS;AAAA"}
|
|
@@ -29,7 +29,7 @@ const ServiceTemplateCacheFieldPrefix = "__serviceTemplate_";
|
|
|
29
29
|
function getServiceTemplateField(hash) {
|
|
30
30
|
return `${ServiceTemplateCacheFieldPrefix}${hash}`;
|
|
31
31
|
}
|
|
32
|
-
const FieldsToDuplicate = new Set([
|
|
32
|
+
const FieldsToDuplicate = /* @__PURE__ */ new Set([
|
|
33
33
|
"blockPack",
|
|
34
34
|
"blockSettings",
|
|
35
35
|
"blockStorage",
|
|
@@ -54,6 +54,6 @@ function parseProjectField(name) {
|
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
56
|
//#endregion
|
|
57
|
-
export { BlockArgsAuthorKeyPrefix, BlockRenderingStateKey, FieldsToDuplicate, InitialBlockMeta, InitialBlockStructure, InitialProjectRenderingState, ProjectCreatedTimestamp, ProjectLastModifiedTimestamp, ProjectMetaKey, ProjectResourceType, ProjectStructureAuthorKey, ProjectStructureKey, SchemaVersionCurrent, SchemaVersionKey, blockArgsAuthorKey, getServiceTemplateField, parseProjectField, projectFieldName };
|
|
57
|
+
export { BlockArgsAuthorKeyPrefix, BlockRenderingStateKey, FieldsToDuplicate, InitialBlockMeta, InitialBlockStructure, InitialProjectRenderingState, ProjectCreatedTimestamp, ProjectLastModifiedTimestamp, ProjectMetaKey, ProjectResourceType, ProjectStructureAuthorKey, ProjectStructureKey, SchemaVersionCurrent, SchemaVersionKey, ServiceTemplateCacheFieldPrefix, blockArgsAuthorKey, getServiceTemplateField, parseProjectField, projectFieldName };
|
|
58
58
|
|
|
59
59
|
//# sourceMappingURL=project_model.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project_model.js","names":[],"sources":["../../src/model/project_model.ts"],"sourcesContent":["import type { ResourceType } from \"@milaboratories/pl-client\";\nimport type { ProjectId } from \"@milaboratories/pl-model-common\";\nimport type {\n ProjectListEntry as ProjectListEntryFromModel,\n ProjectMeta,\n} from \"@milaboratories/pl-model-middle-layer\";\nimport type { BlockRenderingMode } from \"@platforma-sdk/model\";\n\nexport type { ProjectId };\n\nexport interface ProjectListEntry extends Omit<ProjectListEntryFromModel, \"id\"> {\n /** Unique project identifier in middle layer. Use to operate with given project. */\n id: ProjectId;\n}\n\n/** Entry representing a single block in block structure */\nexport interface Block {\n /** Unique block id */\n readonly id: string;\n\n /**\n * Label shown to the user\n * @deprecated\n * */\n label: string;\n\n /** How to approach block rendering */\n renderingMode: BlockRenderingMode;\n}\n\n/** Block group in block structure */\nexport interface BlockGroup {\n /** Unique group id */\n readonly id: string;\n\n /** Label shown to the user */\n label: string;\n\n /** Blocks */\n blocks: Block[];\n}\n\n/** Root of block structure value */\nexport interface ProjectStructure {\n /** The structure */\n readonly groups: BlockGroup[];\n}\n\nexport const InitialBlockStructure: ProjectStructure = {\n groups: [{ id: \"default\", label: \"Default\", blocks: [] }],\n};\n\n/** Root of project rendering state */\nexport interface ProjectRenderingState {\n /** Timestamp of last staging rendering event */\n stagingRefreshTimestamp: number;\n\n /** Blocks with detached production state, i.e. some of the dependencies of\n * such blocks were re-rendered, but their state was left \"as is\". */\n blocksInLimbo: string[];\n}\n\nexport const InitialProjectRenderingState: ProjectRenderingState = {\n stagingRefreshTimestamp: 0,\n blocksInLimbo: [],\n};\n\nexport const InitialBlockMeta: ProjectMeta = {\n label: \"New Project\",\n};\n\n//\n// Pl Model\n//\n\nexport const ProjectResourceType: ResourceType = { name: \"UserProject\", version: \"2\" };\n\nexport const SchemaVersionKey = \"SchemaVersion\";\nexport const SchemaVersionV2 = \"2\";\nexport const SchemaVersionV3 = \"3\";\nexport const SchemaVersionCurrent = \"4\";\n\nexport const ProjectCreatedTimestamp = \"ProjectCreated\";\nexport const ProjectLastModifiedTimestamp = \"ProjectLastModified\";\nexport const ProjectMetaKey = \"ProjectMeta\";\nexport const ProjectStructureKey = \"ProjectStructure\";\nexport const BlockRenderingStateKey = \"BlockRenderingState\";\n\nexport const BlockArgsAuthorKeyPrefix = \"BlockArgsAuthor/\";\nexport const BlockArgsAuthorKeyPattern = /^BlockArgsAuthor\\/(?<blockid>.*)$/;\n\nexport function blockArgsAuthorKey(blockId: string): string {\n return `${BlockArgsAuthorKeyPrefix}${blockId}`;\n}\n\nexport const ProjectStructureAuthorKey = \"ProjectStructureAuthor\";\n\nexport const ServiceTemplateCacheFieldPrefix = \"__serviceTemplate_\";\n\nexport function getServiceTemplateField(hash: string): string {\n return `${ServiceTemplateCacheFieldPrefix}${hash}`;\n}\n\nexport interface ProjectField {\n blockId: string;\n fieldName:\n | \"blockPack\"\n | \"blockSettings\"\n | \"blockStorage\" // Persistent storage for v3 blocks (state, plugins data, etc.)\n | \"prodArgs\"\n | \"currentArgs\"\n | \"currentPrerunArgs\" // Derived args for staging/prerun rendering (from prerunArgs() or args())\n | \"prodChainCtx\" // Pre-built production context chain node (accumulated prodCtx from all blocks above)\n | \"prodCtx\"\n | \"prodUiCtx\"\n | \"prodOutput\"\n | \"prodCtxPrevious\"\n | \"prodUiCtxPrevious\"\n | \"prodOutputPrevious\"\n | \"stagingCtx\"\n | \"stagingUiCtx\"\n | \"stagingOutput\"\n | \"stagingCtxPrevious\"\n | \"stagingUiCtxPrevious\"\n | \"stagingOutputPrevious\";\n}\n\nexport const FieldsToDuplicate: Set<ProjectField[\"fieldName\"]> = new Set([\n \"blockPack\",\n \"blockSettings\",\n \"blockStorage\",\n \"prodArgs\",\n \"currentArgs\",\n \"currentPrerunArgs\",\n \"prodCtx\",\n \"prodUiCtx\",\n \"prodOutput\",\n]);\n\nexport function projectFieldName(blockId: string, fieldName: ProjectField[\"fieldName\"]): string {\n return `${blockId}-${fieldName}`;\n}\n\nconst projectFieldPattern =\n /^(?<blockId>.*)-(?<fieldName>blockPack|blockSettings|blockStorage|inputsValid|prodArgs|currentArgs|currentPrerunArgs|prodChainCtx|prodCtx|prodUiCtx|prodOutput|prodCtxPrevious|prodUiCtxPrevious|prodOutputPrevious|stagingCtx|stagingUiCtx|stagingOutput|stagingCtxPrevious|stagingUiCtxPrevious|stagingOutputPrevious)$/;\n\nexport function parseProjectField(name: string): ProjectField | undefined {\n const match = name.match(projectFieldPattern);\n if (match === null) return undefined;\n const { blockId, fieldName } = match.groups!;\n return { blockId, fieldName } as ProjectField;\n}\n"],"mappings":";AAgDA,MAAa,wBAA0C,EACrD,QAAQ,CAAC;CAAE,IAAI;CAAW,OAAO;CAAW,QAAQ,
|
|
1
|
+
{"version":3,"file":"project_model.js","names":[],"sources":["../../src/model/project_model.ts"],"sourcesContent":["import type { ResourceType } from \"@milaboratories/pl-client\";\nimport type { ProjectId } from \"@milaboratories/pl-model-common\";\nimport type {\n ProjectListEntry as ProjectListEntryFromModel,\n ProjectMeta,\n} from \"@milaboratories/pl-model-middle-layer\";\nimport type { BlockRenderingMode } from \"@platforma-sdk/model\";\n\nexport type { ProjectId };\n\nexport interface ProjectListEntry extends Omit<ProjectListEntryFromModel, \"id\"> {\n /** Unique project identifier in middle layer. Use to operate with given project. */\n id: ProjectId;\n}\n\n/** Entry representing a single block in block structure */\nexport interface Block {\n /** Unique block id */\n readonly id: string;\n\n /**\n * Label shown to the user\n * @deprecated\n * */\n label: string;\n\n /** How to approach block rendering */\n renderingMode: BlockRenderingMode;\n}\n\n/** Block group in block structure */\nexport interface BlockGroup {\n /** Unique group id */\n readonly id: string;\n\n /** Label shown to the user */\n label: string;\n\n /** Blocks */\n blocks: Block[];\n}\n\n/** Root of block structure value */\nexport interface ProjectStructure {\n /** The structure */\n readonly groups: BlockGroup[];\n}\n\nexport const InitialBlockStructure: ProjectStructure = {\n groups: [{ id: \"default\", label: \"Default\", blocks: [] }],\n};\n\n/** Root of project rendering state */\nexport interface ProjectRenderingState {\n /** Timestamp of last staging rendering event */\n stagingRefreshTimestamp: number;\n\n /** Blocks with detached production state, i.e. some of the dependencies of\n * such blocks were re-rendered, but their state was left \"as is\". */\n blocksInLimbo: string[];\n}\n\nexport const InitialProjectRenderingState: ProjectRenderingState = {\n stagingRefreshTimestamp: 0,\n blocksInLimbo: [],\n};\n\nexport const InitialBlockMeta: ProjectMeta = {\n label: \"New Project\",\n};\n\n//\n// Pl Model\n//\n\nexport const ProjectResourceType: ResourceType = { name: \"UserProject\", version: \"2\" };\n\nexport const SchemaVersionKey = \"SchemaVersion\";\nexport const SchemaVersionV2 = \"2\";\nexport const SchemaVersionV3 = \"3\";\nexport const SchemaVersionCurrent = \"4\";\n\nexport const ProjectCreatedTimestamp = \"ProjectCreated\";\nexport const ProjectLastModifiedTimestamp = \"ProjectLastModified\";\nexport const ProjectMetaKey = \"ProjectMeta\";\nexport const ProjectStructureKey = \"ProjectStructure\";\nexport const BlockRenderingStateKey = \"BlockRenderingState\";\n\nexport const BlockArgsAuthorKeyPrefix = \"BlockArgsAuthor/\";\nexport const BlockArgsAuthorKeyPattern = /^BlockArgsAuthor\\/(?<blockid>.*)$/;\n\nexport function blockArgsAuthorKey(blockId: string): string {\n return `${BlockArgsAuthorKeyPrefix}${blockId}`;\n}\n\nexport const ProjectStructureAuthorKey = \"ProjectStructureAuthor\";\n\nexport const ServiceTemplateCacheFieldPrefix = \"__serviceTemplate_\";\n\nexport function getServiceTemplateField(hash: string): string {\n return `${ServiceTemplateCacheFieldPrefix}${hash}`;\n}\n\nexport interface ProjectField {\n blockId: string;\n fieldName:\n | \"blockPack\"\n | \"blockSettings\"\n | \"blockStorage\" // Persistent storage for v3 blocks (state, plugins data, etc.)\n | \"prodArgs\"\n | \"currentArgs\"\n | \"currentPrerunArgs\" // Derived args for staging/prerun rendering (from prerunArgs() or args())\n | \"prodChainCtx\" // Pre-built production context chain node (accumulated prodCtx from all blocks above)\n | \"prodCtx\"\n | \"prodUiCtx\"\n | \"prodOutput\"\n | \"prodCtxPrevious\"\n | \"prodUiCtxPrevious\"\n | \"prodOutputPrevious\"\n | \"stagingCtx\"\n | \"stagingUiCtx\"\n | \"stagingOutput\"\n | \"stagingCtxPrevious\"\n | \"stagingUiCtxPrevious\"\n | \"stagingOutputPrevious\";\n}\n\nexport const FieldsToDuplicate: Set<ProjectField[\"fieldName\"]> = new Set([\n \"blockPack\",\n \"blockSettings\",\n \"blockStorage\",\n \"prodArgs\",\n \"currentArgs\",\n \"currentPrerunArgs\",\n \"prodCtx\",\n \"prodUiCtx\",\n \"prodOutput\",\n]);\n\nexport function projectFieldName(blockId: string, fieldName: ProjectField[\"fieldName\"]): string {\n return `${blockId}-${fieldName}`;\n}\n\nconst projectFieldPattern =\n /^(?<blockId>.*)-(?<fieldName>blockPack|blockSettings|blockStorage|inputsValid|prodArgs|currentArgs|currentPrerunArgs|prodChainCtx|prodCtx|prodUiCtx|prodOutput|prodCtxPrevious|prodUiCtxPrevious|prodOutputPrevious|stagingCtx|stagingUiCtx|stagingOutput|stagingCtxPrevious|stagingUiCtxPrevious|stagingOutputPrevious)$/;\n\nexport function parseProjectField(name: string): ProjectField | undefined {\n const match = name.match(projectFieldPattern);\n if (match === null) return undefined;\n const { blockId, fieldName } = match.groups!;\n return { blockId, fieldName } as ProjectField;\n}\n"],"mappings":";AAgDA,MAAa,wBAA0C,EACrD,QAAQ,CAAC;CAAE,IAAI;CAAW,OAAO;CAAW,QAAQ,CAAC;AAAE,CAAC,EAC1D;AAYA,MAAa,+BAAsD;CACjE,yBAAyB;CACzB,eAAe,CAAC;AAClB;AAEA,MAAa,mBAAgC,EAC3C,OAAO,cACT;AAMA,MAAa,sBAAoC;CAAE,MAAM;CAAe,SAAS;AAAI;AAErF,MAAa,mBAAmB;AAGhC,MAAa,uBAAuB;AAEpC,MAAa,0BAA0B;AACvC,MAAa,+BAA+B;AAC5C,MAAa,iBAAiB;AAC9B,MAAa,sBAAsB;AACnC,MAAa,yBAAyB;AAEtC,MAAa,2BAA2B;AAGxC,SAAgB,mBAAmB,SAAyB;CAC1D,OAAO,GAAG,2BAA2B;AACvC;AAEA,MAAa,4BAA4B;AAEzC,MAAa,kCAAkC;AAE/C,SAAgB,wBAAwB,MAAsB;CAC5D,OAAO,GAAG,kCAAkC;AAC9C;AA0BA,MAAa,oCAAoD,IAAI,IAAI;CACvE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAgB,iBAAiB,SAAiB,WAA8C;CAC9F,OAAO,GAAG,QAAQ,GAAG;AACvB;AAEA,MAAM,sBACJ;AAEF,SAAgB,kBAAkB,MAAwC;CACxE,MAAM,QAAQ,KAAK,MAAM,mBAAmB;CAC5C,IAAI,UAAU,MAAM,OAAO,KAAA;CAC3B,MAAM,EAAE,SAAS,cAAc,MAAM;CACrC,OAAO;EAAE;EAAS;CAAU;AAC9B"}
|
|
@@ -53,8 +53,8 @@ function stagingGraph(structure) {
|
|
|
53
53
|
current.directUpstream = current.upstream = /* @__PURE__ */ new Set();
|
|
54
54
|
current.enrichments = current.enrichmentTargets = /* @__PURE__ */ new Set();
|
|
55
55
|
} else {
|
|
56
|
-
current.directUpstream = current.upstream = new Set([previous.id]);
|
|
57
|
-
previous.directDownstream = previous.downstream = new Set([current.id]);
|
|
56
|
+
current.directUpstream = current.upstream = /* @__PURE__ */ new Set([previous.id]);
|
|
57
|
+
previous.directDownstream = previous.downstream = /* @__PURE__ */ new Set([current.id]);
|
|
58
58
|
previous.enrichments = previous.enrichmentTargets = /* @__PURE__ */ new Set();
|
|
59
59
|
}
|
|
60
60
|
previous = current;
|
|
@@ -70,7 +70,7 @@ function productionGraph(structure, infoProvider) {
|
|
|
70
70
|
const info = infoProvider(id);
|
|
71
71
|
if (info === void 0) continue;
|
|
72
72
|
const references = require_args.inferAllReferencedBlocks(info.args, allAbove);
|
|
73
|
-
const potentialUpstreams = new Set([...references.upstreams, ...resultGraph.traverseIds("enrichments", ...references.upstreamsRequiringEnrichments)]);
|
|
73
|
+
const potentialUpstreams = /* @__PURE__ */ new Set([...references.upstreams, ...resultGraph.traverseIds("enrichments", ...references.upstreamsRequiringEnrichments)]);
|
|
74
74
|
const upstreams = /* @__PURE__ */ new Set();
|
|
75
75
|
for (const { id: pId } of allBlocks(structure)) {
|
|
76
76
|
if (pId === id) break;
|
|
@@ -128,6 +128,7 @@ function graphDiff(a, b) {
|
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
130
|
//#endregion
|
|
131
|
+
exports.BlockGraph = BlockGraph;
|
|
131
132
|
exports.allBlocks = allBlocks;
|
|
132
133
|
exports.graphDiff = graphDiff;
|
|
133
134
|
exports.productionGraph = productionGraph;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project_model_util.cjs","names":["inferAllReferencedBlocks"],"sources":["../../src/model/project_model_util.ts"],"sourcesContent":["import type { Block, ProjectStructure } from \"./project_model\";\nimport type { Optional, Writable } from \"utility-types\";\nimport { inferAllReferencedBlocks } from \"./args\";\nimport type { PlRef } from \"@milaboratories/pl-model-common\";\n\nexport function allBlocks(structure: ProjectStructure): Iterable<Block> {\n return {\n *[Symbol.iterator]() {\n for (const g of structure.groups) for (const b of g.blocks) yield b;\n },\n };\n}\n\nexport interface BlockGraphNode {\n readonly id: string;\n readonly missingReferences: boolean;\n /** Upstreams, calculated accounting for potential indirect block dependencies */\n readonly upstream: Set<string>;\n /** Direct upstream, listed in block args */\n readonly directUpstream: Set<string>;\n /** Downstreams, calculated accounting for potential indirect block dependencies */\n readonly downstream: Set<string>;\n /** Downstream blocks enriching current block's outputs */\n readonly enrichments: Set<string>;\n /** Direct downstreams listing our block in it's args */\n readonly directDownstream: Set<string>;\n /** Upstream blocks that current block may enrich with its exports */\n readonly enrichmentTargets: Set<string>;\n}\n\nexport type BlockGraphDirection =\n | \"upstream\"\n | \"downstream\"\n | \"directUpstream\"\n | \"directDownstream\"\n | \"enrichments\"\n | \"enrichmentTargets\";\n\nexport class BlockGraph {\n /** Nodes are stored in the map in topological order */\n public readonly nodes: Map<string, BlockGraphNode>;\n\n constructor(nodes: Map<string, BlockGraphNode>) {\n this.nodes = nodes;\n }\n\n public traverseIds(direction: BlockGraphDirection, ...rootBlockIds: string[]): Set<string> {\n const all = new Set<string>();\n this.traverse(direction, rootBlockIds, (node) => all.add(node.id));\n return all;\n }\n\n public traverseIdsExcludingRoots(\n direction: BlockGraphDirection,\n ...rootBlockIds: string[]\n ): Set<string> {\n const result = this.traverseIds(direction, ...rootBlockIds);\n for (const r of rootBlockIds) result.delete(r);\n return result;\n }\n\n public traverse(\n direction: BlockGraphDirection,\n rootBlockIds: string[],\n cb: (node: BlockGraphNode) => void,\n ): void {\n let unprocessed = [...rootBlockIds];\n // used to deduplicate possible downstream / upstream blocks and process them only once\n const queued = new Set<string>(unprocessed);\n while (unprocessed.length > 0) {\n const nextUnprocessed: string[] = [];\n for (const blockId of unprocessed) {\n const info = this.nodes.get(blockId)!;\n cb(info);\n info[direction].forEach((v) => {\n if (!queued.has(v)) {\n queued.add(v);\n nextUnprocessed.push(v);\n }\n });\n }\n unprocessed = nextUnprocessed;\n }\n }\n}\n\nexport function stagingGraph(structure: ProjectStructure) {\n type WNode = Optional<Writable<BlockGraphNode>, BlockGraphDirection>;\n const result = new Map<string, WNode>();\n\n // Simple dependency graph from previous to next\n //\n // more complicated patterns to be implemented later\n // (i.e. groups with specific behaviours for total outputs and inputs)\n //\n let previous: WNode | undefined = undefined;\n for (const { id } of allBlocks(structure)) {\n const current: WNode = {\n id: id,\n missingReferences: false,\n };\n result.set(id, current);\n if (previous === undefined) {\n current.directUpstream = current.upstream = new Set<string>();\n current.enrichments = current.enrichmentTargets = new Set<string>();\n } else {\n current.directUpstream = current.upstream = new Set<string>([previous.id]);\n previous.directDownstream = previous.downstream = new Set<string>([current.id]);\n previous.enrichments = previous.enrichmentTargets = new Set<string>();\n }\n\n previous = current;\n }\n if (previous !== undefined) previous.directDownstream = previous.downstream = new Set<string>();\n\n return new BlockGraph(result as Map<string, BlockGraphNode>);\n}\n\nexport type ProductionGraphBlockInfo = {\n args: unknown;\n enrichmentTargets: PlRef[] | undefined;\n};\n\nexport function productionGraph(\n structure: ProjectStructure,\n infoProvider: (blockId: string) => ProductionGraphBlockInfo | undefined,\n): BlockGraph {\n const resultMap = new Map<string, BlockGraphNode>();\n // result graph is constructed to be able to perform traversal on incomplete graph\n // to calculate potentialUpstreams\n const resultGraph = new BlockGraph(resultMap);\n\n // traversing blocks in topological order defined by the project structure\n // and keeping possibleUpstreams set on each step, to consider only\n // those dependencies that are possible under current topology\n const allAbove = new Set<string>();\n for (const { id } of allBlocks(structure)) {\n const info = infoProvider(id);\n\n // skipping those blocks for which we don't have args\n if (info === undefined) continue;\n\n const references = inferAllReferencedBlocks(info.args, allAbove);\n\n // The algorithm here adds all downstream blocks of direct upstreams as potential upstreams.\n // They may produce additional columns, anchored in our direct upstream, those columns might be needed by the workflow.\n const potentialUpstreams = new Set([\n ...references.upstreams,\n ...resultGraph.traverseIds(\"enrichments\", ...references.upstreamsRequiringEnrichments),\n ]);\n\n // To minimize complexity of the graph, we leave only the closest upstreams, removing all their transitive dependencies,\n // relying on the traversal mechanisms in BContexts and on UI level to connect our block with all upstreams\n const upstreams = new Set<string>();\n for (const { id: pId } of allBlocks(structure)) {\n if (pId === id) break; // stopping on current block\n if (potentialUpstreams.has(pId)) {\n upstreams.add(pId);\n for (const transitiveUpstream of resultGraph.traverseIdsExcludingRoots(\"upstream\", pId))\n upstreams.delete(transitiveUpstream);\n }\n }\n\n // default assumption is that all direct upstreams are enrichment targets\n const enrichmentTargets =\n info.enrichmentTargets === undefined\n ? new Set(references.upstreams)\n : new Set(info.enrichmentTargets.map((t) => t.blockId));\n\n const node: BlockGraphNode = {\n id,\n missingReferences: references.missingReferences,\n upstream: upstreams,\n directUpstream: references.upstreams,\n enrichmentTargets,\n downstream: new Set<string>(), // will be populated from downstream blocks\n directDownstream: new Set<string>(), // will be populated from downstream blocks\n enrichments: new Set<string>(), // will be populated from downstream blocks\n };\n resultMap.set(id, node);\n references.upstreams.forEach((dep) => resultMap.get(dep)!.directDownstream.add(id));\n upstreams.forEach((dep) => resultMap.get(dep)!.downstream.add(id));\n enrichmentTargets.forEach((dep) => resultMap.get(dep)?.enrichments.add(id));\n allAbove.add(id);\n }\n\n return resultGraph;\n}\n\nfunction setsEqual<T>(a: Set<T>, b: Set<T>): boolean {\n if (a.size !== b.size) return false;\n for (const e of a) if (!b.has(e)) return false;\n return true;\n}\n\nfunction intersects<T>(a: Set<T>, b: Set<T>): boolean {\n if (a.size > b.size) return intersects(b, a);\n for (const e of a) if (b.has(e)) return true;\n return false;\n}\n\nexport interface GraphDiff {\n onlyInA: Set<string>;\n /** Nodes that changed the list of their upstreams,\n * and all their downstreams */\n different: Set<string>;\n onlyInB: Set<string>;\n}\n\nexport function graphDiff(a: BlockGraph, b: BlockGraph): GraphDiff {\n const onlyInA = new Set<string>();\n const onlyInB = new Set<string>();\n const different = new Set<string>();\n a.nodes.forEach((fromA) => {\n const fromB = b.nodes.get(fromA.id);\n if (fromB === undefined) onlyInA.add(fromA.id);\n else if (!setsEqual(fromA.upstream, fromB.upstream) || intersects(fromA.upstream, different))\n different.add(fromA.id);\n });\n\n b.nodes.forEach((fromB) => {\n if (!a.nodes.has(fromB.id)) onlyInB.add(fromB.id);\n else if (intersects(fromB.upstream, different)) different.add(fromB.id);\n });\n\n return { onlyInA, onlyInB, different };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"project_model_util.cjs","names":["inferAllReferencedBlocks"],"sources":["../../src/model/project_model_util.ts"],"sourcesContent":["import type { Block, ProjectStructure } from \"./project_model\";\nimport type { Optional, Writable } from \"utility-types\";\nimport { inferAllReferencedBlocks } from \"./args\";\nimport type { PlRef } from \"@milaboratories/pl-model-common\";\n\nexport function allBlocks(structure: ProjectStructure): Iterable<Block> {\n return {\n *[Symbol.iterator]() {\n for (const g of structure.groups) for (const b of g.blocks) yield b;\n },\n };\n}\n\nexport interface BlockGraphNode {\n readonly id: string;\n readonly missingReferences: boolean;\n /** Upstreams, calculated accounting for potential indirect block dependencies */\n readonly upstream: Set<string>;\n /** Direct upstream, listed in block args */\n readonly directUpstream: Set<string>;\n /** Downstreams, calculated accounting for potential indirect block dependencies */\n readonly downstream: Set<string>;\n /** Downstream blocks enriching current block's outputs */\n readonly enrichments: Set<string>;\n /** Direct downstreams listing our block in it's args */\n readonly directDownstream: Set<string>;\n /** Upstream blocks that current block may enrich with its exports */\n readonly enrichmentTargets: Set<string>;\n}\n\nexport type BlockGraphDirection =\n | \"upstream\"\n | \"downstream\"\n | \"directUpstream\"\n | \"directDownstream\"\n | \"enrichments\"\n | \"enrichmentTargets\";\n\nexport class BlockGraph {\n /** Nodes are stored in the map in topological order */\n public readonly nodes: Map<string, BlockGraphNode>;\n\n constructor(nodes: Map<string, BlockGraphNode>) {\n this.nodes = nodes;\n }\n\n public traverseIds(direction: BlockGraphDirection, ...rootBlockIds: string[]): Set<string> {\n const all = new Set<string>();\n this.traverse(direction, rootBlockIds, (node) => all.add(node.id));\n return all;\n }\n\n public traverseIdsExcludingRoots(\n direction: BlockGraphDirection,\n ...rootBlockIds: string[]\n ): Set<string> {\n const result = this.traverseIds(direction, ...rootBlockIds);\n for (const r of rootBlockIds) result.delete(r);\n return result;\n }\n\n public traverse(\n direction: BlockGraphDirection,\n rootBlockIds: string[],\n cb: (node: BlockGraphNode) => void,\n ): void {\n let unprocessed = [...rootBlockIds];\n // used to deduplicate possible downstream / upstream blocks and process them only once\n const queued = new Set<string>(unprocessed);\n while (unprocessed.length > 0) {\n const nextUnprocessed: string[] = [];\n for (const blockId of unprocessed) {\n const info = this.nodes.get(blockId)!;\n cb(info);\n info[direction].forEach((v) => {\n if (!queued.has(v)) {\n queued.add(v);\n nextUnprocessed.push(v);\n }\n });\n }\n unprocessed = nextUnprocessed;\n }\n }\n}\n\nexport function stagingGraph(structure: ProjectStructure) {\n type WNode = Optional<Writable<BlockGraphNode>, BlockGraphDirection>;\n const result = new Map<string, WNode>();\n\n // Simple dependency graph from previous to next\n //\n // more complicated patterns to be implemented later\n // (i.e. groups with specific behaviours for total outputs and inputs)\n //\n let previous: WNode | undefined = undefined;\n for (const { id } of allBlocks(structure)) {\n const current: WNode = {\n id: id,\n missingReferences: false,\n };\n result.set(id, current);\n if (previous === undefined) {\n current.directUpstream = current.upstream = new Set<string>();\n current.enrichments = current.enrichmentTargets = new Set<string>();\n } else {\n current.directUpstream = current.upstream = new Set<string>([previous.id]);\n previous.directDownstream = previous.downstream = new Set<string>([current.id]);\n previous.enrichments = previous.enrichmentTargets = new Set<string>();\n }\n\n previous = current;\n }\n if (previous !== undefined) previous.directDownstream = previous.downstream = new Set<string>();\n\n return new BlockGraph(result as Map<string, BlockGraphNode>);\n}\n\nexport type ProductionGraphBlockInfo = {\n args: unknown;\n enrichmentTargets: PlRef[] | undefined;\n};\n\nexport function productionGraph(\n structure: ProjectStructure,\n infoProvider: (blockId: string) => ProductionGraphBlockInfo | undefined,\n): BlockGraph {\n const resultMap = new Map<string, BlockGraphNode>();\n // result graph is constructed to be able to perform traversal on incomplete graph\n // to calculate potentialUpstreams\n const resultGraph = new BlockGraph(resultMap);\n\n // traversing blocks in topological order defined by the project structure\n // and keeping possibleUpstreams set on each step, to consider only\n // those dependencies that are possible under current topology\n const allAbove = new Set<string>();\n for (const { id } of allBlocks(structure)) {\n const info = infoProvider(id);\n\n // skipping those blocks for which we don't have args\n if (info === undefined) continue;\n\n const references = inferAllReferencedBlocks(info.args, allAbove);\n\n // The algorithm here adds all downstream blocks of direct upstreams as potential upstreams.\n // They may produce additional columns, anchored in our direct upstream, those columns might be needed by the workflow.\n const potentialUpstreams = new Set([\n ...references.upstreams,\n ...resultGraph.traverseIds(\"enrichments\", ...references.upstreamsRequiringEnrichments),\n ]);\n\n // To minimize complexity of the graph, we leave only the closest upstreams, removing all their transitive dependencies,\n // relying on the traversal mechanisms in BContexts and on UI level to connect our block with all upstreams\n const upstreams = new Set<string>();\n for (const { id: pId } of allBlocks(structure)) {\n if (pId === id) break; // stopping on current block\n if (potentialUpstreams.has(pId)) {\n upstreams.add(pId);\n for (const transitiveUpstream of resultGraph.traverseIdsExcludingRoots(\"upstream\", pId))\n upstreams.delete(transitiveUpstream);\n }\n }\n\n // default assumption is that all direct upstreams are enrichment targets\n const enrichmentTargets =\n info.enrichmentTargets === undefined\n ? new Set(references.upstreams)\n : new Set(info.enrichmentTargets.map((t) => t.blockId));\n\n const node: BlockGraphNode = {\n id,\n missingReferences: references.missingReferences,\n upstream: upstreams,\n directUpstream: references.upstreams,\n enrichmentTargets,\n downstream: new Set<string>(), // will be populated from downstream blocks\n directDownstream: new Set<string>(), // will be populated from downstream blocks\n enrichments: new Set<string>(), // will be populated from downstream blocks\n };\n resultMap.set(id, node);\n references.upstreams.forEach((dep) => resultMap.get(dep)!.directDownstream.add(id));\n upstreams.forEach((dep) => resultMap.get(dep)!.downstream.add(id));\n enrichmentTargets.forEach((dep) => resultMap.get(dep)?.enrichments.add(id));\n allAbove.add(id);\n }\n\n return resultGraph;\n}\n\nfunction setsEqual<T>(a: Set<T>, b: Set<T>): boolean {\n if (a.size !== b.size) return false;\n for (const e of a) if (!b.has(e)) return false;\n return true;\n}\n\nfunction intersects<T>(a: Set<T>, b: Set<T>): boolean {\n if (a.size > b.size) return intersects(b, a);\n for (const e of a) if (b.has(e)) return true;\n return false;\n}\n\nexport interface GraphDiff {\n onlyInA: Set<string>;\n /** Nodes that changed the list of their upstreams,\n * and all their downstreams */\n different: Set<string>;\n onlyInB: Set<string>;\n}\n\nexport function graphDiff(a: BlockGraph, b: BlockGraph): GraphDiff {\n const onlyInA = new Set<string>();\n const onlyInB = new Set<string>();\n const different = new Set<string>();\n a.nodes.forEach((fromA) => {\n const fromB = b.nodes.get(fromA.id);\n if (fromB === undefined) onlyInA.add(fromA.id);\n else if (!setsEqual(fromA.upstream, fromB.upstream) || intersects(fromA.upstream, different))\n different.add(fromA.id);\n });\n\n b.nodes.forEach((fromB) => {\n if (!a.nodes.has(fromB.id)) onlyInB.add(fromB.id);\n else if (intersects(fromB.upstream, different)) different.add(fromB.id);\n });\n\n return { onlyInA, onlyInB, different };\n}\n"],"mappings":";;AAKA,SAAgB,UAAU,WAA8C;CACtE,OAAO,EACL,EAAE,OAAO,YAAY;EACnB,KAAK,MAAM,KAAK,UAAU,QAAQ,KAAK,MAAM,KAAK,EAAE,QAAQ,MAAM;CACpE,EACF;AACF;AA2BA,IAAa,aAAb,MAAwB;;CAEtB;CAEA,YAAY,OAAoC;EAC9C,KAAK,QAAQ;CACf;CAEA,YAAmB,WAAgC,GAAG,cAAqC;EACzF,MAAM,sBAAM,IAAI,IAAY;EAC5B,KAAK,SAAS,WAAW,eAAe,SAAS,IAAI,IAAI,KAAK,EAAE,CAAC;EACjE,OAAO;CACT;CAEA,0BACE,WACA,GAAG,cACU;EACb,MAAM,SAAS,KAAK,YAAY,WAAW,GAAG,YAAY;EAC1D,KAAK,MAAM,KAAK,cAAc,OAAO,OAAO,CAAC;EAC7C,OAAO;CACT;CAEA,SACE,WACA,cACA,IACM;EACN,IAAI,cAAc,CAAC,GAAG,YAAY;EAElC,MAAM,SAAS,IAAI,IAAY,WAAW;EAC1C,OAAO,YAAY,SAAS,GAAG;GAC7B,MAAM,kBAA4B,CAAC;GACnC,KAAK,MAAM,WAAW,aAAa;IACjC,MAAM,OAAO,KAAK,MAAM,IAAI,OAAO;IACnC,GAAG,IAAI;IACP,KAAK,UAAU,CAAC,SAAS,MAAM;KAC7B,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG;MAClB,OAAO,IAAI,CAAC;MACZ,gBAAgB,KAAK,CAAC;KACxB;IACF,CAAC;GACH;GACA,cAAc;EAChB;CACF;AACF;AAEA,SAAgB,aAAa,WAA6B;CAExD,MAAM,yBAAS,IAAI,IAAmB;CAOtC,IAAI,WAA8B,KAAA;CAClC,KAAK,MAAM,EAAE,QAAQ,UAAU,SAAS,GAAG;EACzC,MAAM,UAAiB;GACjB;GACJ,mBAAmB;EACrB;EACA,OAAO,IAAI,IAAI,OAAO;EACtB,IAAI,aAAa,KAAA,GAAW;GAC1B,QAAQ,iBAAiB,QAAQ,2BAAW,IAAI,IAAY;GAC5D,QAAQ,cAAc,QAAQ,oCAAoB,IAAI,IAAY;EACpE,OAAO;GACL,QAAQ,iBAAiB,QAAQ,2BAAW,IAAI,IAAY,CAAC,SAAS,EAAE,CAAC;GACzE,SAAS,mBAAmB,SAAS,6BAAa,IAAI,IAAY,CAAC,QAAQ,EAAE,CAAC;GAC9E,SAAS,cAAc,SAAS,oCAAoB,IAAI,IAAY;EACtE;EAEA,WAAW;CACb;CACA,IAAI,aAAa,KAAA,GAAW,SAAS,mBAAmB,SAAS,6BAAa,IAAI,IAAY;CAE9F,OAAO,IAAI,WAAW,MAAqC;AAC7D;AAOA,SAAgB,gBACd,WACA,cACY;CACZ,MAAM,4BAAY,IAAI,IAA4B;CAGlD,MAAM,cAAc,IAAI,WAAW,SAAS;CAK5C,MAAM,2BAAW,IAAI,IAAY;CACjC,KAAK,MAAM,EAAE,QAAQ,UAAU,SAAS,GAAG;EACzC,MAAM,OAAO,aAAa,EAAE;EAG5B,IAAI,SAAS,KAAA,GAAW;EAExB,MAAM,aAAaA,aAAAA,yBAAyB,KAAK,MAAM,QAAQ;EAI/D,MAAM,qCAAqB,IAAI,IAAI,CACjC,GAAG,WAAW,WACd,GAAG,YAAY,YAAY,eAAe,GAAG,WAAW,6BAA6B,CACvF,CAAC;EAID,MAAM,4BAAY,IAAI,IAAY;EAClC,KAAK,MAAM,EAAE,IAAI,SAAS,UAAU,SAAS,GAAG;GAC9C,IAAI,QAAQ,IAAI;GAChB,IAAI,mBAAmB,IAAI,GAAG,GAAG;IAC/B,UAAU,IAAI,GAAG;IACjB,KAAK,MAAM,sBAAsB,YAAY,0BAA0B,YAAY,GAAG,GACpF,UAAU,OAAO,kBAAkB;GACvC;EACF;EAGA,MAAM,oBACJ,KAAK,sBAAsB,KAAA,IACvB,IAAI,IAAI,WAAW,SAAS,IAC5B,IAAI,IAAI,KAAK,kBAAkB,KAAK,MAAM,EAAE,OAAO,CAAC;EAE1D,MAAM,OAAuB;GAC3B;GACA,mBAAmB,WAAW;GAC9B,UAAU;GACV,gBAAgB,WAAW;GAC3B;GACA,4BAAY,IAAI,IAAY;GAC5B,kCAAkB,IAAI,IAAY;GAClC,6BAAa,IAAI,IAAY;EAC/B;EACA,UAAU,IAAI,IAAI,IAAI;EACtB,WAAW,UAAU,SAAS,QAAQ,UAAU,IAAI,GAAG,CAAC,CAAE,iBAAiB,IAAI,EAAE,CAAC;EAClF,UAAU,SAAS,QAAQ,UAAU,IAAI,GAAG,CAAC,CAAE,WAAW,IAAI,EAAE,CAAC;EACjE,kBAAkB,SAAS,QAAQ,UAAU,IAAI,GAAG,CAAC,EAAE,YAAY,IAAI,EAAE,CAAC;EAC1E,SAAS,IAAI,EAAE;CACjB;CAEA,OAAO;AACT;AAEA,SAAS,UAAa,GAAW,GAAoB;CACnD,IAAI,EAAE,SAAS,EAAE,MAAM,OAAO;CAC9B,KAAK,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,OAAO;CACzC,OAAO;AACT;AAEA,SAAS,WAAc,GAAW,GAAoB;CACpD,IAAI,EAAE,OAAO,EAAE,MAAM,OAAO,WAAW,GAAG,CAAC;CAC3C,KAAK,MAAM,KAAK,GAAG,IAAI,EAAE,IAAI,CAAC,GAAG,OAAO;CACxC,OAAO;AACT;AAUA,SAAgB,UAAU,GAAe,GAA0B;CACjE,MAAM,0BAAU,IAAI,IAAY;CAChC,MAAM,0BAAU,IAAI,IAAY;CAChC,MAAM,4BAAY,IAAI,IAAY;CAClC,EAAE,MAAM,SAAS,UAAU;EACzB,MAAM,QAAQ,EAAE,MAAM,IAAI,MAAM,EAAE;EAClC,IAAI,UAAU,KAAA,GAAW,QAAQ,IAAI,MAAM,EAAE;OACxC,IAAI,CAAC,UAAU,MAAM,UAAU,MAAM,QAAQ,KAAK,WAAW,MAAM,UAAU,SAAS,GACzF,UAAU,IAAI,MAAM,EAAE;CAC1B,CAAC;CAED,EAAE,MAAM,SAAS,UAAU;EACzB,IAAI,CAAC,EAAE,MAAM,IAAI,MAAM,EAAE,GAAG,QAAQ,IAAI,MAAM,EAAE;OAC3C,IAAI,WAAW,MAAM,UAAU,SAAS,GAAG,UAAU,IAAI,MAAM,EAAE;CACxE,CAAC;CAED,OAAO;EAAE;EAAS;EAAS;CAAU;AACvC"}
|
|
@@ -53,8 +53,8 @@ function stagingGraph(structure) {
|
|
|
53
53
|
current.directUpstream = current.upstream = /* @__PURE__ */ new Set();
|
|
54
54
|
current.enrichments = current.enrichmentTargets = /* @__PURE__ */ new Set();
|
|
55
55
|
} else {
|
|
56
|
-
current.directUpstream = current.upstream = new Set([previous.id]);
|
|
57
|
-
previous.directDownstream = previous.downstream = new Set([current.id]);
|
|
56
|
+
current.directUpstream = current.upstream = /* @__PURE__ */ new Set([previous.id]);
|
|
57
|
+
previous.directDownstream = previous.downstream = /* @__PURE__ */ new Set([current.id]);
|
|
58
58
|
previous.enrichments = previous.enrichmentTargets = /* @__PURE__ */ new Set();
|
|
59
59
|
}
|
|
60
60
|
previous = current;
|
|
@@ -70,7 +70,7 @@ function productionGraph(structure, infoProvider) {
|
|
|
70
70
|
const info = infoProvider(id);
|
|
71
71
|
if (info === void 0) continue;
|
|
72
72
|
const references = inferAllReferencedBlocks(info.args, allAbove);
|
|
73
|
-
const potentialUpstreams = new Set([...references.upstreams, ...resultGraph.traverseIds("enrichments", ...references.upstreamsRequiringEnrichments)]);
|
|
73
|
+
const potentialUpstreams = /* @__PURE__ */ new Set([...references.upstreams, ...resultGraph.traverseIds("enrichments", ...references.upstreamsRequiringEnrichments)]);
|
|
74
74
|
const upstreams = /* @__PURE__ */ new Set();
|
|
75
75
|
for (const { id: pId } of allBlocks(structure)) {
|
|
76
76
|
if (pId === id) break;
|
|
@@ -128,6 +128,6 @@ function graphDiff(a, b) {
|
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
130
|
//#endregion
|
|
131
|
-
export { allBlocks, graphDiff, productionGraph, stagingGraph };
|
|
131
|
+
export { BlockGraph, allBlocks, graphDiff, productionGraph, stagingGraph };
|
|
132
132
|
|
|
133
133
|
//# sourceMappingURL=project_model_util.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project_model_util.js","names":[],"sources":["../../src/model/project_model_util.ts"],"sourcesContent":["import type { Block, ProjectStructure } from \"./project_model\";\nimport type { Optional, Writable } from \"utility-types\";\nimport { inferAllReferencedBlocks } from \"./args\";\nimport type { PlRef } from \"@milaboratories/pl-model-common\";\n\nexport function allBlocks(structure: ProjectStructure): Iterable<Block> {\n return {\n *[Symbol.iterator]() {\n for (const g of structure.groups) for (const b of g.blocks) yield b;\n },\n };\n}\n\nexport interface BlockGraphNode {\n readonly id: string;\n readonly missingReferences: boolean;\n /** Upstreams, calculated accounting for potential indirect block dependencies */\n readonly upstream: Set<string>;\n /** Direct upstream, listed in block args */\n readonly directUpstream: Set<string>;\n /** Downstreams, calculated accounting for potential indirect block dependencies */\n readonly downstream: Set<string>;\n /** Downstream blocks enriching current block's outputs */\n readonly enrichments: Set<string>;\n /** Direct downstreams listing our block in it's args */\n readonly directDownstream: Set<string>;\n /** Upstream blocks that current block may enrich with its exports */\n readonly enrichmentTargets: Set<string>;\n}\n\nexport type BlockGraphDirection =\n | \"upstream\"\n | \"downstream\"\n | \"directUpstream\"\n | \"directDownstream\"\n | \"enrichments\"\n | \"enrichmentTargets\";\n\nexport class BlockGraph {\n /** Nodes are stored in the map in topological order */\n public readonly nodes: Map<string, BlockGraphNode>;\n\n constructor(nodes: Map<string, BlockGraphNode>) {\n this.nodes = nodes;\n }\n\n public traverseIds(direction: BlockGraphDirection, ...rootBlockIds: string[]): Set<string> {\n const all = new Set<string>();\n this.traverse(direction, rootBlockIds, (node) => all.add(node.id));\n return all;\n }\n\n public traverseIdsExcludingRoots(\n direction: BlockGraphDirection,\n ...rootBlockIds: string[]\n ): Set<string> {\n const result = this.traverseIds(direction, ...rootBlockIds);\n for (const r of rootBlockIds) result.delete(r);\n return result;\n }\n\n public traverse(\n direction: BlockGraphDirection,\n rootBlockIds: string[],\n cb: (node: BlockGraphNode) => void,\n ): void {\n let unprocessed = [...rootBlockIds];\n // used to deduplicate possible downstream / upstream blocks and process them only once\n const queued = new Set<string>(unprocessed);\n while (unprocessed.length > 0) {\n const nextUnprocessed: string[] = [];\n for (const blockId of unprocessed) {\n const info = this.nodes.get(blockId)!;\n cb(info);\n info[direction].forEach((v) => {\n if (!queued.has(v)) {\n queued.add(v);\n nextUnprocessed.push(v);\n }\n });\n }\n unprocessed = nextUnprocessed;\n }\n }\n}\n\nexport function stagingGraph(structure: ProjectStructure) {\n type WNode = Optional<Writable<BlockGraphNode>, BlockGraphDirection>;\n const result = new Map<string, WNode>();\n\n // Simple dependency graph from previous to next\n //\n // more complicated patterns to be implemented later\n // (i.e. groups with specific behaviours for total outputs and inputs)\n //\n let previous: WNode | undefined = undefined;\n for (const { id } of allBlocks(structure)) {\n const current: WNode = {\n id: id,\n missingReferences: false,\n };\n result.set(id, current);\n if (previous === undefined) {\n current.directUpstream = current.upstream = new Set<string>();\n current.enrichments = current.enrichmentTargets = new Set<string>();\n } else {\n current.directUpstream = current.upstream = new Set<string>([previous.id]);\n previous.directDownstream = previous.downstream = new Set<string>([current.id]);\n previous.enrichments = previous.enrichmentTargets = new Set<string>();\n }\n\n previous = current;\n }\n if (previous !== undefined) previous.directDownstream = previous.downstream = new Set<string>();\n\n return new BlockGraph(result as Map<string, BlockGraphNode>);\n}\n\nexport type ProductionGraphBlockInfo = {\n args: unknown;\n enrichmentTargets: PlRef[] | undefined;\n};\n\nexport function productionGraph(\n structure: ProjectStructure,\n infoProvider: (blockId: string) => ProductionGraphBlockInfo | undefined,\n): BlockGraph {\n const resultMap = new Map<string, BlockGraphNode>();\n // result graph is constructed to be able to perform traversal on incomplete graph\n // to calculate potentialUpstreams\n const resultGraph = new BlockGraph(resultMap);\n\n // traversing blocks in topological order defined by the project structure\n // and keeping possibleUpstreams set on each step, to consider only\n // those dependencies that are possible under current topology\n const allAbove = new Set<string>();\n for (const { id } of allBlocks(structure)) {\n const info = infoProvider(id);\n\n // skipping those blocks for which we don't have args\n if (info === undefined) continue;\n\n const references = inferAllReferencedBlocks(info.args, allAbove);\n\n // The algorithm here adds all downstream blocks of direct upstreams as potential upstreams.\n // They may produce additional columns, anchored in our direct upstream, those columns might be needed by the workflow.\n const potentialUpstreams = new Set([\n ...references.upstreams,\n ...resultGraph.traverseIds(\"enrichments\", ...references.upstreamsRequiringEnrichments),\n ]);\n\n // To minimize complexity of the graph, we leave only the closest upstreams, removing all their transitive dependencies,\n // relying on the traversal mechanisms in BContexts and on UI level to connect our block with all upstreams\n const upstreams = new Set<string>();\n for (const { id: pId } of allBlocks(structure)) {\n if (pId === id) break; // stopping on current block\n if (potentialUpstreams.has(pId)) {\n upstreams.add(pId);\n for (const transitiveUpstream of resultGraph.traverseIdsExcludingRoots(\"upstream\", pId))\n upstreams.delete(transitiveUpstream);\n }\n }\n\n // default assumption is that all direct upstreams are enrichment targets\n const enrichmentTargets =\n info.enrichmentTargets === undefined\n ? new Set(references.upstreams)\n : new Set(info.enrichmentTargets.map((t) => t.blockId));\n\n const node: BlockGraphNode = {\n id,\n missingReferences: references.missingReferences,\n upstream: upstreams,\n directUpstream: references.upstreams,\n enrichmentTargets,\n downstream: new Set<string>(), // will be populated from downstream blocks\n directDownstream: new Set<string>(), // will be populated from downstream blocks\n enrichments: new Set<string>(), // will be populated from downstream blocks\n };\n resultMap.set(id, node);\n references.upstreams.forEach((dep) => resultMap.get(dep)!.directDownstream.add(id));\n upstreams.forEach((dep) => resultMap.get(dep)!.downstream.add(id));\n enrichmentTargets.forEach((dep) => resultMap.get(dep)?.enrichments.add(id));\n allAbove.add(id);\n }\n\n return resultGraph;\n}\n\nfunction setsEqual<T>(a: Set<T>, b: Set<T>): boolean {\n if (a.size !== b.size) return false;\n for (const e of a) if (!b.has(e)) return false;\n return true;\n}\n\nfunction intersects<T>(a: Set<T>, b: Set<T>): boolean {\n if (a.size > b.size) return intersects(b, a);\n for (const e of a) if (b.has(e)) return true;\n return false;\n}\n\nexport interface GraphDiff {\n onlyInA: Set<string>;\n /** Nodes that changed the list of their upstreams,\n * and all their downstreams */\n different: Set<string>;\n onlyInB: Set<string>;\n}\n\nexport function graphDiff(a: BlockGraph, b: BlockGraph): GraphDiff {\n const onlyInA = new Set<string>();\n const onlyInB = new Set<string>();\n const different = new Set<string>();\n a.nodes.forEach((fromA) => {\n const fromB = b.nodes.get(fromA.id);\n if (fromB === undefined) onlyInA.add(fromA.id);\n else if (!setsEqual(fromA.upstream, fromB.upstream) || intersects(fromA.upstream, different))\n different.add(fromA.id);\n });\n\n b.nodes.forEach((fromB) => {\n if (!a.nodes.has(fromB.id)) onlyInB.add(fromB.id);\n else if (intersects(fromB.upstream, different)) different.add(fromB.id);\n });\n\n return { onlyInA, onlyInB, different };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"project_model_util.js","names":[],"sources":["../../src/model/project_model_util.ts"],"sourcesContent":["import type { Block, ProjectStructure } from \"./project_model\";\nimport type { Optional, Writable } from \"utility-types\";\nimport { inferAllReferencedBlocks } from \"./args\";\nimport type { PlRef } from \"@milaboratories/pl-model-common\";\n\nexport function allBlocks(structure: ProjectStructure): Iterable<Block> {\n return {\n *[Symbol.iterator]() {\n for (const g of structure.groups) for (const b of g.blocks) yield b;\n },\n };\n}\n\nexport interface BlockGraphNode {\n readonly id: string;\n readonly missingReferences: boolean;\n /** Upstreams, calculated accounting for potential indirect block dependencies */\n readonly upstream: Set<string>;\n /** Direct upstream, listed in block args */\n readonly directUpstream: Set<string>;\n /** Downstreams, calculated accounting for potential indirect block dependencies */\n readonly downstream: Set<string>;\n /** Downstream blocks enriching current block's outputs */\n readonly enrichments: Set<string>;\n /** Direct downstreams listing our block in it's args */\n readonly directDownstream: Set<string>;\n /** Upstream blocks that current block may enrich with its exports */\n readonly enrichmentTargets: Set<string>;\n}\n\nexport type BlockGraphDirection =\n | \"upstream\"\n | \"downstream\"\n | \"directUpstream\"\n | \"directDownstream\"\n | \"enrichments\"\n | \"enrichmentTargets\";\n\nexport class BlockGraph {\n /** Nodes are stored in the map in topological order */\n public readonly nodes: Map<string, BlockGraphNode>;\n\n constructor(nodes: Map<string, BlockGraphNode>) {\n this.nodes = nodes;\n }\n\n public traverseIds(direction: BlockGraphDirection, ...rootBlockIds: string[]): Set<string> {\n const all = new Set<string>();\n this.traverse(direction, rootBlockIds, (node) => all.add(node.id));\n return all;\n }\n\n public traverseIdsExcludingRoots(\n direction: BlockGraphDirection,\n ...rootBlockIds: string[]\n ): Set<string> {\n const result = this.traverseIds(direction, ...rootBlockIds);\n for (const r of rootBlockIds) result.delete(r);\n return result;\n }\n\n public traverse(\n direction: BlockGraphDirection,\n rootBlockIds: string[],\n cb: (node: BlockGraphNode) => void,\n ): void {\n let unprocessed = [...rootBlockIds];\n // used to deduplicate possible downstream / upstream blocks and process them only once\n const queued = new Set<string>(unprocessed);\n while (unprocessed.length > 0) {\n const nextUnprocessed: string[] = [];\n for (const blockId of unprocessed) {\n const info = this.nodes.get(blockId)!;\n cb(info);\n info[direction].forEach((v) => {\n if (!queued.has(v)) {\n queued.add(v);\n nextUnprocessed.push(v);\n }\n });\n }\n unprocessed = nextUnprocessed;\n }\n }\n}\n\nexport function stagingGraph(structure: ProjectStructure) {\n type WNode = Optional<Writable<BlockGraphNode>, BlockGraphDirection>;\n const result = new Map<string, WNode>();\n\n // Simple dependency graph from previous to next\n //\n // more complicated patterns to be implemented later\n // (i.e. groups with specific behaviours for total outputs and inputs)\n //\n let previous: WNode | undefined = undefined;\n for (const { id } of allBlocks(structure)) {\n const current: WNode = {\n id: id,\n missingReferences: false,\n };\n result.set(id, current);\n if (previous === undefined) {\n current.directUpstream = current.upstream = new Set<string>();\n current.enrichments = current.enrichmentTargets = new Set<string>();\n } else {\n current.directUpstream = current.upstream = new Set<string>([previous.id]);\n previous.directDownstream = previous.downstream = new Set<string>([current.id]);\n previous.enrichments = previous.enrichmentTargets = new Set<string>();\n }\n\n previous = current;\n }\n if (previous !== undefined) previous.directDownstream = previous.downstream = new Set<string>();\n\n return new BlockGraph(result as Map<string, BlockGraphNode>);\n}\n\nexport type ProductionGraphBlockInfo = {\n args: unknown;\n enrichmentTargets: PlRef[] | undefined;\n};\n\nexport function productionGraph(\n structure: ProjectStructure,\n infoProvider: (blockId: string) => ProductionGraphBlockInfo | undefined,\n): BlockGraph {\n const resultMap = new Map<string, BlockGraphNode>();\n // result graph is constructed to be able to perform traversal on incomplete graph\n // to calculate potentialUpstreams\n const resultGraph = new BlockGraph(resultMap);\n\n // traversing blocks in topological order defined by the project structure\n // and keeping possibleUpstreams set on each step, to consider only\n // those dependencies that are possible under current topology\n const allAbove = new Set<string>();\n for (const { id } of allBlocks(structure)) {\n const info = infoProvider(id);\n\n // skipping those blocks for which we don't have args\n if (info === undefined) continue;\n\n const references = inferAllReferencedBlocks(info.args, allAbove);\n\n // The algorithm here adds all downstream blocks of direct upstreams as potential upstreams.\n // They may produce additional columns, anchored in our direct upstream, those columns might be needed by the workflow.\n const potentialUpstreams = new Set([\n ...references.upstreams,\n ...resultGraph.traverseIds(\"enrichments\", ...references.upstreamsRequiringEnrichments),\n ]);\n\n // To minimize complexity of the graph, we leave only the closest upstreams, removing all their transitive dependencies,\n // relying on the traversal mechanisms in BContexts and on UI level to connect our block with all upstreams\n const upstreams = new Set<string>();\n for (const { id: pId } of allBlocks(structure)) {\n if (pId === id) break; // stopping on current block\n if (potentialUpstreams.has(pId)) {\n upstreams.add(pId);\n for (const transitiveUpstream of resultGraph.traverseIdsExcludingRoots(\"upstream\", pId))\n upstreams.delete(transitiveUpstream);\n }\n }\n\n // default assumption is that all direct upstreams are enrichment targets\n const enrichmentTargets =\n info.enrichmentTargets === undefined\n ? new Set(references.upstreams)\n : new Set(info.enrichmentTargets.map((t) => t.blockId));\n\n const node: BlockGraphNode = {\n id,\n missingReferences: references.missingReferences,\n upstream: upstreams,\n directUpstream: references.upstreams,\n enrichmentTargets,\n downstream: new Set<string>(), // will be populated from downstream blocks\n directDownstream: new Set<string>(), // will be populated from downstream blocks\n enrichments: new Set<string>(), // will be populated from downstream blocks\n };\n resultMap.set(id, node);\n references.upstreams.forEach((dep) => resultMap.get(dep)!.directDownstream.add(id));\n upstreams.forEach((dep) => resultMap.get(dep)!.downstream.add(id));\n enrichmentTargets.forEach((dep) => resultMap.get(dep)?.enrichments.add(id));\n allAbove.add(id);\n }\n\n return resultGraph;\n}\n\nfunction setsEqual<T>(a: Set<T>, b: Set<T>): boolean {\n if (a.size !== b.size) return false;\n for (const e of a) if (!b.has(e)) return false;\n return true;\n}\n\nfunction intersects<T>(a: Set<T>, b: Set<T>): boolean {\n if (a.size > b.size) return intersects(b, a);\n for (const e of a) if (b.has(e)) return true;\n return false;\n}\n\nexport interface GraphDiff {\n onlyInA: Set<string>;\n /** Nodes that changed the list of their upstreams,\n * and all their downstreams */\n different: Set<string>;\n onlyInB: Set<string>;\n}\n\nexport function graphDiff(a: BlockGraph, b: BlockGraph): GraphDiff {\n const onlyInA = new Set<string>();\n const onlyInB = new Set<string>();\n const different = new Set<string>();\n a.nodes.forEach((fromA) => {\n const fromB = b.nodes.get(fromA.id);\n if (fromB === undefined) onlyInA.add(fromA.id);\n else if (!setsEqual(fromA.upstream, fromB.upstream) || intersects(fromA.upstream, different))\n different.add(fromA.id);\n });\n\n b.nodes.forEach((fromB) => {\n if (!a.nodes.has(fromB.id)) onlyInB.add(fromB.id);\n else if (intersects(fromB.upstream, different)) different.add(fromB.id);\n });\n\n return { onlyInA, onlyInB, different };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template_spec.d.ts","names":[],"sources":["../../src/model/template_spec.ts"],"mappings":";;;;UAGiB,oBAAA;EAAA,SACN,IAAA;EACT,QAAA;EACA,IAAA;AAAA;AAAA,UAGe,gBAAA;EAAA,SACN,IAAA;EACT,OAAA,EAAS,
|
|
1
|
+
{"version":3,"file":"template_spec.d.ts","names":[],"sources":["../../src/model/template_spec.ts"],"mappings":";;;;UAGiB,oBAAA;EAAA,SACN,IAAA;EACT,QAAA;EACA,IAAA;AAAA;AAAA,UAGe,gBAAA;EAAA,SACN,IAAA;EACT,OAAA,EAAS,UAAU;AAAA;AAAA,UAGJ,gBAAA;EAAA,SACN,IAAA;EACT,IAAA,EAAM,YAAA,GAAe,kBAAkB;AAAA;AAAA,UAGxB,cAAA;EAAA,SACN,IAAA;EAAA,SACA,UAAA,EAAY,gBAAgB;AAAA;AAAA,UAGtB,gBAAA;EAAA,SACN,IAAA;EACT,IAAI;AAAA;AAAA,KAGM,oBAAA,GACR,oBAAA,GACA,gBAAA,GACA,gBAAA,GACA,cAAA;AAAA,KACQ,eAAA,GAAkB,oBAAA,GAAuB,gBAAgB"}
|
|
@@ -6,17 +6,18 @@ require("../../block_registry/index.cjs");
|
|
|
6
6
|
const require_template_loading = require("../template/template_loading.cjs");
|
|
7
7
|
const require_frontend = require("./frontend.cjs");
|
|
8
8
|
const require_WorkerManager = require("../../worker/WorkerManager.cjs");
|
|
9
|
-
const require_usingCtx = require("../../_virtual/_@oxc-project_runtime@0.
|
|
9
|
+
const require_usingCtx = require("../../_virtual/_@oxc-project_runtime@0.137.0/helpers/esm/usingCtx.cjs");
|
|
10
10
|
let _platforma_sdk_model = require("@platforma-sdk/model");
|
|
11
11
|
let undici = require("undici");
|
|
12
12
|
let _platforma_sdk_block_tools = require("@platforma-sdk/block-tools");
|
|
13
13
|
let node_fs = require("node:fs");
|
|
14
|
-
node_fs = require_runtime.__toESM(node_fs);
|
|
14
|
+
node_fs = require_runtime.__toESM(node_fs, 1);
|
|
15
15
|
let _milaboratories_ts_helpers = require("@milaboratories/ts-helpers");
|
|
16
16
|
let _milaboratories_pl_client = require("@milaboratories/pl-client");
|
|
17
17
|
let lru_cache = require("lru-cache");
|
|
18
|
+
let node_url = require("node:url");
|
|
18
19
|
let canonicalize = require("canonicalize");
|
|
19
|
-
canonicalize = require_runtime.__toESM(canonicalize);
|
|
20
|
+
canonicalize = require_runtime.__toESM(canonicalize, 1);
|
|
20
21
|
let zod = require("zod");
|
|
21
22
|
//#region src/mutator/block-pack/block_pack.ts
|
|
22
23
|
const BlockPackCustomType = {
|
|
@@ -40,6 +41,9 @@ function parseBufferConfig(buffer) {
|
|
|
40
41
|
return parseStringConfig(Buffer.from(buffer).toString("utf8"));
|
|
41
42
|
}
|
|
42
43
|
var BlockPackPreparer = class {
|
|
44
|
+
v2RegistryProvider;
|
|
45
|
+
signer;
|
|
46
|
+
http;
|
|
43
47
|
constructor(v2RegistryProvider, signer, http) {
|
|
44
48
|
this.v2RegistryProvider = v2RegistryProvider;
|
|
45
49
|
this.signer = signer;
|
|
@@ -68,6 +72,10 @@ var BlockPackPreparer = class {
|
|
|
68
72
|
const description = await (0, _platforma_sdk_block_tools.loadPackDescription)(spec.folder);
|
|
69
73
|
return parseStringConfig(await node_fs.default.promises.readFile(description.components.model.file, { encoding: "utf-8" }));
|
|
70
74
|
}
|
|
75
|
+
case "from-pack-v2": {
|
|
76
|
+
const description = await (0, _platforma_sdk_block_tools.loadPackDescriptionFromManifest)((0, node_url.fileURLToPath)(spec.packUrl));
|
|
77
|
+
return parseStringConfig(await node_fs.default.promises.readFile(description.components.model.file, { encoding: "utf-8" }));
|
|
78
|
+
}
|
|
71
79
|
case "from-registry-v1": {
|
|
72
80
|
const urlPrefix = `${tSlash(spec.registryUrl)}${_platforma_sdk_block_tools.RegistryV1.packageContentPrefix({
|
|
73
81
|
organization: spec.id.organization,
|
|
@@ -94,7 +102,7 @@ var BlockPackPreparer = class {
|
|
|
94
102
|
}
|
|
95
103
|
async prepare(spec) {
|
|
96
104
|
try {
|
|
97
|
-
var _usingCtx$1 = require_usingCtx.
|
|
105
|
+
var _usingCtx$1 = require_usingCtx.default();
|
|
98
106
|
if (spec.type === "prepared") return spec;
|
|
99
107
|
const key = this.specKey(spec);
|
|
100
108
|
if (key) {
|
|
@@ -165,6 +173,34 @@ var BlockPackPreparer = class {
|
|
|
165
173
|
source
|
|
166
174
|
};
|
|
167
175
|
}
|
|
176
|
+
case "from-pack-v2": {
|
|
177
|
+
const packDir = (0, node_url.fileURLToPath)(spec.packUrl);
|
|
178
|
+
const description = await (0, _platforma_sdk_block_tools.loadPackDescriptionFromManifest)(packDir);
|
|
179
|
+
const config = parseStringConfig(await node_fs.default.promises.readFile(description.components.model.file, { encoding: "utf-8" }));
|
|
180
|
+
const workflowContent = await node_fs.default.promises.readFile(description.components.workflow.main.file);
|
|
181
|
+
const uiTgzPath = description.components.ui.folder;
|
|
182
|
+
const source = { ...spec };
|
|
183
|
+
let mtime = spec.mtime;
|
|
184
|
+
if (mtime === void 0) {
|
|
185
|
+
mtime = await require_registry.getFromPackV2Mtime(packDir, uiTgzPath);
|
|
186
|
+
source.mtime = mtime;
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
type: "explicit",
|
|
190
|
+
template: {
|
|
191
|
+
type: "explicit",
|
|
192
|
+
content: workflowContent
|
|
193
|
+
},
|
|
194
|
+
config,
|
|
195
|
+
frontend: {
|
|
196
|
+
type: "local-tgz",
|
|
197
|
+
path: uiTgzPath,
|
|
198
|
+
mtime,
|
|
199
|
+
signature: this.signer.sign(`${uiTgzPath}:${mtime}`)
|
|
200
|
+
},
|
|
201
|
+
source
|
|
202
|
+
};
|
|
203
|
+
}
|
|
168
204
|
case "from-registry-v1": {
|
|
169
205
|
const urlPrefix = `${tSlash(spec.registryUrl)}${_platforma_sdk_block_tools.RegistryV1.packageContentPrefix({
|
|
170
206
|
organization: spec.id.organization,
|
|
@@ -231,6 +267,7 @@ function createBlockPack(tx, spec) {
|
|
|
231
267
|
}
|
|
232
268
|
}
|
|
233
269
|
//#endregion
|
|
270
|
+
exports.BlockPackCustomType = BlockPackCustomType;
|
|
234
271
|
exports.BlockPackFrontendField = BlockPackFrontendField;
|
|
235
272
|
exports.BlockPackPreparer = BlockPackPreparer;
|
|
236
273
|
exports.BlockPackTemplateField = BlockPackTemplateField;
|