@milaboratories/pl-middle-layer 1.64.37 → 1.64.39
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 +15 -15
- 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":"block_pack.cjs","names":["z","Code","LRUCache","resolveDevPacket","fs","RegistryV1","WorkerManager","requiredCapabilitiesFromTemplate","getDevV2PacketMtime","loadTemplate","createFrontend"],"sources":["../../../src/mutator/block-pack/block_pack.ts"],"sourcesContent":["import type { AnyResourceRef, PlTransaction, ResourceType } from \"@milaboratories/pl-client\";\nimport { field } from \"@milaboratories/pl-client\";\nimport { loadTemplate } from \"../template/template_loading\";\nimport type { BlockPackExplicit, BlockPackSpecAny, BlockPackSpecPrepared } from \"../../model\";\nimport type { Signer } from \"@milaboratories/ts-helpers\";\nimport { assertNever } from \"@milaboratories/ts-helpers\";\nimport type { Branded } from \"@milaboratories/pl-model-common\";\nimport fs from \"node:fs\";\nimport type { Dispatcher } from \"undici\";\nimport { request } from \"undici\";\nimport { createFrontend } from \"./frontend\";\nimport { requiredCapabilitiesFromTemplate } from \"./required_capabilities\";\nimport type { BlockConfigContainer } from \"@platforma-sdk/model\";\nimport { Code } from \"@platforma-sdk/model\";\nimport { loadPackDescription, RegistryV1 } from \"@platforma-sdk/block-tools\";\nimport type { BlockPackInfo } from \"../../model/block_pack\";\nimport { resolveDevPacket } from \"../../dev_env\";\nimport { getDevV2PacketMtime } from \"../../block_registry\";\nimport type { V2RegistryProvider } from \"../../block_registry/registry-v2-provider\";\nimport { LRUCache } from \"lru-cache\";\nimport canonicalize from \"canonicalize\";\nimport type { BlockPackSpec } from \"@milaboratories/pl-model-middle-layer\";\nimport { WorkerManager } from \"../../worker/WorkerManager\";\nimport { z } from \"zod\";\n\ntype PreparedCacheKey = Branded<string, \"PreparedCacheKey\">;\n\nexport const BlockPackCustomType: ResourceType = { name: \"BlockPackCustom\", version: \"1\" };\nexport const BlockPackTemplateField = \"template\";\nexport const BlockPackFrontendField = \"frontend\";\n\n/** Ensure trailing slash */\nfunction tSlash(str: string): string {\n if (str.endsWith(\"/\")) return str;\n else return `${str}/`;\n}\n\nfunction parseStringConfig(configContent: string): BlockConfigContainer {\n const res = z.record(z.string(), z.unknown()).safeParse(JSON.parse(configContent));\n\n if (!res.success) {\n throw new Error(\"Invalid config content\");\n }\n\n if (!Code.safeParse(res.data.code).success) {\n throw new Error(\"parseStringConfig:No code bundle\");\n }\n\n return res.data as BlockConfigContainer;\n}\n\nfunction parseBufferConfig(buffer: ArrayBuffer): BlockConfigContainer {\n return parseStringConfig(Buffer.from(buffer).toString(\"utf8\"));\n}\n\nexport class BlockPackPreparer {\n constructor(\n private readonly v2RegistryProvider: V2RegistryProvider,\n private readonly signer: Signer,\n private readonly http?: Dispatcher,\n ) {}\n\n private readonly remoteContentCache = new LRUCache<string, ArrayBuffer>({\n max: 500,\n maxSize: 128 * 1024 * 1024,\n fetchMethod: async (key) => {\n const httpOptions = this.http !== undefined ? { dispatcher: this.http } : {};\n return await (await request(key, httpOptions)).body.arrayBuffer();\n },\n sizeCalculation: (value) => value.byteLength,\n });\n\n /** Cache of prepared block packs for registry specs (immutable by version). */\n private readonly preparedCache = new LRUCache<PreparedCacheKey, BlockPackSpecPrepared>({\n max: 50,\n });\n\n public async getBlockConfigContainer(spec: BlockPackSpecAny): Promise<BlockConfigContainer> {\n switch (spec.type) {\n case \"explicit\":\n return spec.config;\n\n case \"prepared\":\n return spec.config;\n\n case \"dev-v1\": {\n const devPaths = await resolveDevPacket(spec.folder, false);\n const configContent = await fs.promises.readFile(devPaths.config, { encoding: \"utf-8\" });\n return JSON.parse(configContent);\n }\n\n case \"dev-v2\": {\n const description = await loadPackDescription(spec.folder);\n const configContent = await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n });\n return parseStringConfig(configContent);\n }\n\n case \"from-registry-v1\": {\n const urlPrefix = `${tSlash(spec.registryUrl)}${RegistryV1.packageContentPrefix({ organization: spec.id.organization, package: spec.id.name, version: spec.id.version })}`;\n\n const configResponse = await this.remoteContentCache.forceFetch(`${urlPrefix}/config.json`);\n return JSON.parse(Buffer.from(configResponse).toString(\"utf8\"));\n }\n\n case \"from-registry-v2\": {\n const registry = this.v2RegistryProvider.getRegistry(spec.registryUrl);\n const components = await registry.getComponents(spec.id);\n const configResponse = await this.remoteContentCache.forceFetch(components.model.url);\n return parseBufferConfig(configResponse);\n }\n\n default:\n return assertNever(spec);\n }\n }\n\n /** Returns a stable cache key for registry specs (immutable by version). Dev specs return undefined. */\n private specKey(spec: BlockPackSpecAny): PreparedCacheKey | undefined {\n switch (spec.type) {\n case \"from-registry-v1\":\n return `v1:${spec.registryUrl}:${spec.id.organization}:${spec.id.name}:${spec.id.version}` as PreparedCacheKey;\n case \"from-registry-v2\":\n return `v2:${spec.registryUrl}:${canonicalize(spec.id)}` as PreparedCacheKey;\n default:\n return undefined; // dev, explicit, prepared — not cacheable\n }\n }\n\n public async prepare(spec: BlockPackSpecAny): Promise<BlockPackSpecPrepared> {\n if (spec.type === \"prepared\") {\n return spec;\n }\n\n // Check prepare cache for registry specs\n const key = this.specKey(spec);\n if (key) {\n const cached = this.preparedCache.get(key);\n if (cached) return cached;\n }\n\n const explicit = await this.prepareWithoutUnpacking(spec);\n\n await using workerManager = new WorkerManager();\n\n const parsed = await workerManager.process(\"parseTemplate\", explicit.template.content);\n\n const result: BlockPackSpecPrepared = {\n ...explicit,\n type: \"prepared\",\n template: {\n type: \"prepared\",\n data: parsed,\n },\n requiredCapabilities: requiredCapabilitiesFromTemplate(parsed),\n };\n\n if (key) {\n this.preparedCache.set(key, result);\n }\n\n return result;\n }\n\n private async prepareWithoutUnpacking(\n spec: BlockPackExplicit | BlockPackSpec,\n ): Promise<BlockPackExplicit> {\n switch (spec.type) {\n case \"explicit\":\n return spec;\n\n case \"dev-v1\": {\n const devPaths = await resolveDevPacket(spec.folder, false);\n\n // template\n const templateContent = await fs.promises.readFile(devPaths.workflow);\n\n // config\n const config = JSON.parse(await fs.promises.readFile(devPaths.config, \"utf-8\"));\n\n // frontend\n const frontendPath = devPaths.ui;\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: templateContent,\n },\n config,\n frontend: {\n type: \"local\",\n path: frontendPath,\n signature: this.signer.sign(frontendPath),\n },\n source: spec,\n };\n }\n\n case \"dev-v2\": {\n const description = await loadPackDescription(spec.folder);\n const config = parseStringConfig(\n await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n }),\n );\n const workflowContent = await fs.promises.readFile(\n description.components.workflow.main.file,\n );\n const frontendPath = description.components.ui.folder;\n const source = { ...spec };\n if (spec.mtime === undefined)\n // if absent, calculating the mtime here, so the block will correctly show whether it can be updated\n source.mtime = await getDevV2PacketMtime(description);\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: workflowContent,\n },\n config,\n frontend: {\n type: \"local\",\n path: frontendPath,\n signature: this.signer.sign(frontendPath),\n },\n source,\n };\n }\n\n case \"from-registry-v1\": {\n const urlPrefix = `${tSlash(spec.registryUrl)}${RegistryV1.packageContentPrefix({ organization: spec.id.organization, package: spec.id.name, version: spec.id.version })}`;\n\n const templateUrl = `${urlPrefix}/template.plj.gz`;\n // template\n const templateResponse = await this.remoteContentCache.forceFetch(templateUrl);\n const templateContent = new Uint8Array(templateResponse);\n\n // config\n const configResponse = await this.remoteContentCache.forceFetch(`${urlPrefix}/config.json`);\n const config = JSON.parse(\n Buffer.from(configResponse).toString(\"utf8\"),\n ) as BlockConfigContainer;\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: templateContent,\n },\n config,\n frontend: {\n type: \"url\",\n url: `${urlPrefix}/frontend.tgz`,\n },\n source: spec,\n };\n }\n\n case \"from-registry-v2\": {\n const registry = this.v2RegistryProvider.getRegistry(spec.registryUrl);\n const components = await registry.getComponents(spec.id);\n const getModel = async () =>\n parseBufferConfig(await this.remoteContentCache.forceFetch(components.model.url));\n const getWorkflow = async () =>\n await this.remoteContentCache.forceFetch(components.workflow.main.url);\n\n const [model, workflow] = await Promise.all([getModel(), getWorkflow()]);\n const workflowContent = Buffer.from(workflow);\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: workflowContent,\n },\n config: model,\n frontend: {\n type: \"url\",\n url: components.ui.url,\n },\n source: spec,\n };\n }\n\n default:\n return assertNever(spec);\n }\n }\n}\n\nfunction createCustomBlockPack(tx: PlTransaction, spec: BlockPackSpecPrepared): AnyResourceRef {\n const blockPackInfo: BlockPackInfo = { config: spec.config, source: spec.source };\n const bp = tx.createStruct(BlockPackCustomType, JSON.stringify(blockPackInfo));\n tx.createField(field(bp, BlockPackTemplateField), \"Input\", loadTemplate(tx, spec.template));\n tx.createField(field(bp, BlockPackFrontendField), \"Input\", createFrontend(tx, spec.frontend));\n tx.lock(bp);\n\n return bp;\n}\n\nexport function createBlockPack(tx: PlTransaction, spec: BlockPackSpecPrepared): AnyResourceRef {\n switch (spec.type) {\n case \"prepared\":\n return createCustomBlockPack(tx, spec);\n default:\n return assertNever(spec.type);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"block_pack.cjs","names":["z","Code","LRUCache","resolveDevPacket","fs","RegistryV1","WorkerManager","requiredCapabilitiesFromTemplate","getDevV2PacketMtime","getFromPackV2Mtime","loadTemplate","createFrontend"],"sources":["../../../src/mutator/block-pack/block_pack.ts"],"sourcesContent":["import type { AnyResourceRef, PlTransaction, ResourceType } from \"@milaboratories/pl-client\";\nimport { field } from \"@milaboratories/pl-client\";\nimport { loadTemplate } from \"../template/template_loading\";\nimport type { BlockPackExplicit, BlockPackSpecAny, BlockPackSpecPrepared } from \"../../model\";\nimport type { Signer } from \"@milaboratories/ts-helpers\";\nimport { assertNever } from \"@milaboratories/ts-helpers\";\nimport type { Branded } from \"@milaboratories/pl-model-common\";\nimport fs from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Dispatcher } from \"undici\";\nimport { request } from \"undici\";\nimport { createFrontend } from \"./frontend\";\nimport { requiredCapabilitiesFromTemplate } from \"./required_capabilities\";\nimport type { BlockConfigContainer } from \"@platforma-sdk/model\";\nimport { Code } from \"@platforma-sdk/model\";\nimport {\n loadPackDescription,\n loadPackDescriptionFromManifest,\n RegistryV1,\n} from \"@platforma-sdk/block-tools\";\nimport type { BlockPackInfo } from \"../../model/block_pack\";\nimport { resolveDevPacket } from \"../../dev_env\";\nimport { getDevV2PacketMtime, getFromPackV2Mtime } from \"../../block_registry\";\nimport type { V2RegistryProvider } from \"../../block_registry/registry-v2-provider\";\nimport { LRUCache } from \"lru-cache\";\nimport canonicalize from \"canonicalize\";\nimport type { BlockPackSpec } from \"@milaboratories/pl-model-middle-layer\";\nimport { WorkerManager } from \"../../worker/WorkerManager\";\nimport { z } from \"zod\";\n\ntype PreparedCacheKey = Branded<string, \"PreparedCacheKey\">;\n\nexport const BlockPackCustomType: ResourceType = { name: \"BlockPackCustom\", version: \"1\" };\nexport const BlockPackTemplateField = \"template\";\nexport const BlockPackFrontendField = \"frontend\";\n\n/** Ensure trailing slash */\nfunction tSlash(str: string): string {\n if (str.endsWith(\"/\")) return str;\n else return `${str}/`;\n}\n\nfunction parseStringConfig(configContent: string): BlockConfigContainer {\n const res = z.record(z.string(), z.unknown()).safeParse(JSON.parse(configContent));\n\n if (!res.success) {\n throw new Error(\"Invalid config content\");\n }\n\n if (!Code.safeParse(res.data.code).success) {\n throw new Error(\"parseStringConfig:No code bundle\");\n }\n\n return res.data as BlockConfigContainer;\n}\n\nfunction parseBufferConfig(buffer: ArrayBuffer): BlockConfigContainer {\n return parseStringConfig(Buffer.from(buffer).toString(\"utf8\"));\n}\n\nexport class BlockPackPreparer {\n constructor(\n private readonly v2RegistryProvider: V2RegistryProvider,\n private readonly signer: Signer,\n private readonly http?: Dispatcher,\n ) {}\n\n private readonly remoteContentCache = new LRUCache<string, ArrayBuffer>({\n max: 500,\n maxSize: 128 * 1024 * 1024,\n fetchMethod: async (key) => {\n const httpOptions = this.http !== undefined ? { dispatcher: this.http } : {};\n return await (await request(key, httpOptions)).body.arrayBuffer();\n },\n sizeCalculation: (value) => value.byteLength,\n });\n\n /** Cache of prepared block packs for registry specs (immutable by version). */\n private readonly preparedCache = new LRUCache<PreparedCacheKey, BlockPackSpecPrepared>({\n max: 50,\n });\n\n public async getBlockConfigContainer(spec: BlockPackSpecAny): Promise<BlockConfigContainer> {\n switch (spec.type) {\n case \"explicit\":\n return spec.config;\n\n case \"prepared\":\n return spec.config;\n\n case \"dev-v1\": {\n const devPaths = await resolveDevPacket(spec.folder, false);\n const configContent = await fs.promises.readFile(devPaths.config, { encoding: \"utf-8\" });\n return JSON.parse(configContent);\n }\n\n case \"dev-v2\": {\n const description = await loadPackDescription(spec.folder);\n const configContent = await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n });\n return parseStringConfig(configContent);\n }\n\n case \"from-pack-v2\": {\n // packUrl is a file: URL (the facade emits URLs, not paths); convert at\n // this Node boundary before touching the filesystem.\n const packDir = fileURLToPath(spec.packUrl);\n const description = await loadPackDescriptionFromManifest(packDir);\n const configContent = await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n });\n return parseStringConfig(configContent);\n }\n\n case \"from-registry-v1\": {\n const urlPrefix = `${tSlash(spec.registryUrl)}${RegistryV1.packageContentPrefix({ organization: spec.id.organization, package: spec.id.name, version: spec.id.version })}`;\n\n const configResponse = await this.remoteContentCache.forceFetch(`${urlPrefix}/config.json`);\n return JSON.parse(Buffer.from(configResponse).toString(\"utf8\"));\n }\n\n case \"from-registry-v2\": {\n const registry = this.v2RegistryProvider.getRegistry(spec.registryUrl);\n const components = await registry.getComponents(spec.id);\n const configResponse = await this.remoteContentCache.forceFetch(components.model.url);\n return parseBufferConfig(configResponse);\n }\n\n default:\n return assertNever(spec);\n }\n }\n\n /** Returns a stable cache key for registry specs (immutable by version). Dev specs return undefined. */\n private specKey(spec: BlockPackSpecAny): PreparedCacheKey | undefined {\n switch (spec.type) {\n case \"from-registry-v1\":\n return `v1:${spec.registryUrl}:${spec.id.organization}:${spec.id.name}:${spec.id.version}` as PreparedCacheKey;\n case \"from-registry-v2\":\n return `v2:${spec.registryUrl}:${canonicalize(spec.id)}` as PreparedCacheKey;\n default:\n return undefined; // dev, explicit, prepared — not cacheable\n }\n }\n\n public async prepare(spec: BlockPackSpecAny): Promise<BlockPackSpecPrepared> {\n if (spec.type === \"prepared\") {\n return spec;\n }\n\n // Check prepare cache for registry specs\n const key = this.specKey(spec);\n if (key) {\n const cached = this.preparedCache.get(key);\n if (cached) return cached;\n }\n\n const explicit = await this.prepareWithoutUnpacking(spec);\n\n await using workerManager = new WorkerManager();\n\n const parsed = await workerManager.process(\"parseTemplate\", explicit.template.content);\n\n const result: BlockPackSpecPrepared = {\n ...explicit,\n type: \"prepared\",\n template: {\n type: \"prepared\",\n data: parsed,\n },\n requiredCapabilities: requiredCapabilitiesFromTemplate(parsed),\n };\n\n if (key) {\n this.preparedCache.set(key, result);\n }\n\n return result;\n }\n\n private async prepareWithoutUnpacking(\n spec: BlockPackExplicit | BlockPackSpec,\n ): Promise<BlockPackExplicit> {\n switch (spec.type) {\n case \"explicit\":\n return spec;\n\n case \"dev-v1\": {\n const devPaths = await resolveDevPacket(spec.folder, false);\n\n // template\n const templateContent = await fs.promises.readFile(devPaths.workflow);\n\n // config\n const config = JSON.parse(await fs.promises.readFile(devPaths.config, \"utf-8\"));\n\n // frontend\n const frontendPath = devPaths.ui;\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: templateContent,\n },\n config,\n frontend: {\n type: \"local\",\n path: frontendPath,\n signature: this.signer.sign(frontendPath),\n },\n source: spec,\n };\n }\n\n case \"dev-v2\": {\n const description = await loadPackDescription(spec.folder);\n const config = parseStringConfig(\n await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n }),\n );\n const workflowContent = await fs.promises.readFile(\n description.components.workflow.main.file,\n );\n const frontendPath = description.components.ui.folder;\n const source = { ...spec };\n if (spec.mtime === undefined)\n // if absent, calculating the mtime here, so the block will correctly show whether it can be updated\n source.mtime = await getDevV2PacketMtime(description);\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: workflowContent,\n },\n config,\n frontend: {\n type: \"local\",\n path: frontendPath,\n signature: this.signer.sign(frontendPath),\n },\n source,\n };\n }\n\n case \"from-pack-v2\": {\n // packUrl is a file: URL (the facade emits URLs, not paths); convert at\n // this Node boundary before touching the filesystem.\n const packDir = fileURLToPath(spec.packUrl);\n const description = await loadPackDescriptionFromManifest(packDir);\n const config = parseStringConfig(\n await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n }),\n );\n const workflowContent = await fs.promises.readFile(\n description.components.workflow.main.file,\n );\n // UI ships as ui.tgz inside block-pack/; its absolute path is carried\n // in the ui folder slot. The tarball is unpacked lazily at serve-time by\n // the download driver (local-tgz frontend), not eagerly here — so it\n // inherits the driver's usage-tracking and space recycling.\n const uiTgzPath = description.components.ui.folder;\n const source = { ...spec };\n let mtime = spec.mtime;\n if (mtime === undefined) {\n // No explicit mtime: derive one so the frontend cache key invalidates\n // when the block changes.\n mtime = await getFromPackV2Mtime(packDir, uiTgzPath);\n source.mtime = mtime;\n }\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: workflowContent,\n },\n config,\n frontend: {\n type: \"local-tgz\",\n path: uiTgzPath,\n mtime,\n signature: this.signer.sign(`${uiTgzPath}:${mtime}`),\n },\n source,\n };\n }\n\n case \"from-registry-v1\": {\n const urlPrefix = `${tSlash(spec.registryUrl)}${RegistryV1.packageContentPrefix({ organization: spec.id.organization, package: spec.id.name, version: spec.id.version })}`;\n\n const templateUrl = `${urlPrefix}/template.plj.gz`;\n // template\n const templateResponse = await this.remoteContentCache.forceFetch(templateUrl);\n const templateContent = new Uint8Array(templateResponse);\n\n // config\n const configResponse = await this.remoteContentCache.forceFetch(`${urlPrefix}/config.json`);\n const config = JSON.parse(\n Buffer.from(configResponse).toString(\"utf8\"),\n ) as BlockConfigContainer;\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: templateContent,\n },\n config,\n frontend: {\n type: \"url\",\n url: `${urlPrefix}/frontend.tgz`,\n },\n source: spec,\n };\n }\n\n case \"from-registry-v2\": {\n const registry = this.v2RegistryProvider.getRegistry(spec.registryUrl);\n const components = await registry.getComponents(spec.id);\n const getModel = async () =>\n parseBufferConfig(await this.remoteContentCache.forceFetch(components.model.url));\n const getWorkflow = async () =>\n await this.remoteContentCache.forceFetch(components.workflow.main.url);\n\n const [model, workflow] = await Promise.all([getModel(), getWorkflow()]);\n const workflowContent = Buffer.from(workflow);\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: workflowContent,\n },\n config: model,\n frontend: {\n type: \"url\",\n url: components.ui.url,\n },\n source: spec,\n };\n }\n\n default:\n return assertNever(spec);\n }\n }\n}\n\nfunction createCustomBlockPack(tx: PlTransaction, spec: BlockPackSpecPrepared): AnyResourceRef {\n const blockPackInfo: BlockPackInfo = { config: spec.config, source: spec.source };\n const bp = tx.createStruct(BlockPackCustomType, JSON.stringify(blockPackInfo));\n tx.createField(field(bp, BlockPackTemplateField), \"Input\", loadTemplate(tx, spec.template));\n tx.createField(field(bp, BlockPackFrontendField), \"Input\", createFrontend(tx, spec.frontend));\n tx.lock(bp);\n\n return bp;\n}\n\nexport function createBlockPack(tx: PlTransaction, spec: BlockPackSpecPrepared): AnyResourceRef {\n switch (spec.type) {\n case \"prepared\":\n return createCustomBlockPack(tx, spec);\n default:\n return assertNever(spec.type);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block_pack.d.ts","names":[],"sources":["../../../src/mutator/block-pack/block_pack.ts"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"block_pack.d.ts","names":[],"sources":["../../../src/mutator/block-pack/block_pack.ts"],"mappings":";;;;;;;;cA4Da,iBAAA;EAAA,iBAEQ,kBAAA;EAAA,iBACA,MAAA;EAAA,iBACA,IAAA;cAFA,kBAAA,EAAoB,kBAAA,EACpB,MAAA,EAAQ,MAAA,EACR,IAAA,GAAO,UAAA;EAAA,iBAGT,kBAAA;EAe0B;EAAA,iBAJ1B,aAAA;EAIJ,uBAAA,CAAwB,IAAA,EAAM,gBAAA,GAAmB,OAAA,CAAQ,oBAAA;EAgE3C;EAAA,QAXnB,OAAA;EAWK,OAAA,CAAQ,IAAA,EAAM,gBAAA,GAAmB,OAAA,CAAQ,qBAAA;EAAA,QAmCxC,uBAAA;AAAA"}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { resolveDevPacket } from "../../dev_env/index.js";
|
|
2
2
|
import { requiredCapabilitiesFromTemplate } from "./required_capabilities.js";
|
|
3
|
-
import { getDevV2PacketMtime } from "../../block_registry/registry.js";
|
|
3
|
+
import { getDevV2PacketMtime, getFromPackV2Mtime } from "../../block_registry/registry.js";
|
|
4
4
|
import "../../block_registry/index.js";
|
|
5
5
|
import { loadTemplate } from "../template/template_loading.js";
|
|
6
6
|
import { createFrontend } from "./frontend.js";
|
|
7
7
|
import { WorkerManager } from "../../worker/WorkerManager.js";
|
|
8
|
-
import
|
|
8
|
+
import _usingCtx from "../../_virtual/_@oxc-project_runtime@0.137.0/helpers/esm/usingCtx.js";
|
|
9
9
|
import { Code } from "@platforma-sdk/model";
|
|
10
10
|
import { request } from "undici";
|
|
11
|
-
import { RegistryV1, loadPackDescription } from "@platforma-sdk/block-tools";
|
|
11
|
+
import { RegistryV1, loadPackDescription, loadPackDescriptionFromManifest } from "@platforma-sdk/block-tools";
|
|
12
12
|
import fs from "node:fs";
|
|
13
13
|
import { assertNever } from "@milaboratories/ts-helpers";
|
|
14
14
|
import { field } from "@milaboratories/pl-client";
|
|
15
15
|
import { LRUCache } from "lru-cache";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
16
17
|
import canonicalize from "canonicalize";
|
|
17
18
|
import { z } from "zod";
|
|
18
19
|
//#region src/mutator/block-pack/block_pack.ts
|
|
@@ -37,6 +38,9 @@ function parseBufferConfig(buffer) {
|
|
|
37
38
|
return parseStringConfig(Buffer.from(buffer).toString("utf8"));
|
|
38
39
|
}
|
|
39
40
|
var BlockPackPreparer = class {
|
|
41
|
+
v2RegistryProvider;
|
|
42
|
+
signer;
|
|
43
|
+
http;
|
|
40
44
|
constructor(v2RegistryProvider, signer, http) {
|
|
41
45
|
this.v2RegistryProvider = v2RegistryProvider;
|
|
42
46
|
this.signer = signer;
|
|
@@ -65,6 +69,10 @@ var BlockPackPreparer = class {
|
|
|
65
69
|
const description = await loadPackDescription(spec.folder);
|
|
66
70
|
return parseStringConfig(await fs.promises.readFile(description.components.model.file, { encoding: "utf-8" }));
|
|
67
71
|
}
|
|
72
|
+
case "from-pack-v2": {
|
|
73
|
+
const description = await loadPackDescriptionFromManifest(fileURLToPath(spec.packUrl));
|
|
74
|
+
return parseStringConfig(await fs.promises.readFile(description.components.model.file, { encoding: "utf-8" }));
|
|
75
|
+
}
|
|
68
76
|
case "from-registry-v1": {
|
|
69
77
|
const urlPrefix = `${tSlash(spec.registryUrl)}${RegistryV1.packageContentPrefix({
|
|
70
78
|
organization: spec.id.organization,
|
|
@@ -162,6 +170,34 @@ var BlockPackPreparer = class {
|
|
|
162
170
|
source
|
|
163
171
|
};
|
|
164
172
|
}
|
|
173
|
+
case "from-pack-v2": {
|
|
174
|
+
const packDir = fileURLToPath(spec.packUrl);
|
|
175
|
+
const description = await loadPackDescriptionFromManifest(packDir);
|
|
176
|
+
const config = parseStringConfig(await fs.promises.readFile(description.components.model.file, { encoding: "utf-8" }));
|
|
177
|
+
const workflowContent = await fs.promises.readFile(description.components.workflow.main.file);
|
|
178
|
+
const uiTgzPath = description.components.ui.folder;
|
|
179
|
+
const source = { ...spec };
|
|
180
|
+
let mtime = spec.mtime;
|
|
181
|
+
if (mtime === void 0) {
|
|
182
|
+
mtime = await getFromPackV2Mtime(packDir, uiTgzPath);
|
|
183
|
+
source.mtime = mtime;
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
type: "explicit",
|
|
187
|
+
template: {
|
|
188
|
+
type: "explicit",
|
|
189
|
+
content: workflowContent
|
|
190
|
+
},
|
|
191
|
+
config,
|
|
192
|
+
frontend: {
|
|
193
|
+
type: "local-tgz",
|
|
194
|
+
path: uiTgzPath,
|
|
195
|
+
mtime,
|
|
196
|
+
signature: this.signer.sign(`${uiTgzPath}:${mtime}`)
|
|
197
|
+
},
|
|
198
|
+
source
|
|
199
|
+
};
|
|
200
|
+
}
|
|
165
201
|
case "from-registry-v1": {
|
|
166
202
|
const urlPrefix = `${tSlash(spec.registryUrl)}${RegistryV1.packageContentPrefix({
|
|
167
203
|
organization: spec.id.organization,
|
|
@@ -228,6 +264,6 @@ function createBlockPack(tx, spec) {
|
|
|
228
264
|
}
|
|
229
265
|
}
|
|
230
266
|
//#endregion
|
|
231
|
-
export { BlockPackFrontendField, BlockPackPreparer, BlockPackTemplateField, createBlockPack };
|
|
267
|
+
export { BlockPackCustomType, BlockPackFrontendField, BlockPackPreparer, BlockPackTemplateField, createBlockPack };
|
|
232
268
|
|
|
233
269
|
//# sourceMappingURL=block_pack.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block_pack.js","names":[],"sources":["../../../src/mutator/block-pack/block_pack.ts"],"sourcesContent":["import type { AnyResourceRef, PlTransaction, ResourceType } from \"@milaboratories/pl-client\";\nimport { field } from \"@milaboratories/pl-client\";\nimport { loadTemplate } from \"../template/template_loading\";\nimport type { BlockPackExplicit, BlockPackSpecAny, BlockPackSpecPrepared } from \"../../model\";\nimport type { Signer } from \"@milaboratories/ts-helpers\";\nimport { assertNever } from \"@milaboratories/ts-helpers\";\nimport type { Branded } from \"@milaboratories/pl-model-common\";\nimport fs from \"node:fs\";\nimport type { Dispatcher } from \"undici\";\nimport { request } from \"undici\";\nimport { createFrontend } from \"./frontend\";\nimport { requiredCapabilitiesFromTemplate } from \"./required_capabilities\";\nimport type { BlockConfigContainer } from \"@platforma-sdk/model\";\nimport { Code } from \"@platforma-sdk/model\";\nimport { loadPackDescription, RegistryV1 } from \"@platforma-sdk/block-tools\";\nimport type { BlockPackInfo } from \"../../model/block_pack\";\nimport { resolveDevPacket } from \"../../dev_env\";\nimport { getDevV2PacketMtime } from \"../../block_registry\";\nimport type { V2RegistryProvider } from \"../../block_registry/registry-v2-provider\";\nimport { LRUCache } from \"lru-cache\";\nimport canonicalize from \"canonicalize\";\nimport type { BlockPackSpec } from \"@milaboratories/pl-model-middle-layer\";\nimport { WorkerManager } from \"../../worker/WorkerManager\";\nimport { z } from \"zod\";\n\ntype PreparedCacheKey = Branded<string, \"PreparedCacheKey\">;\n\nexport const BlockPackCustomType: ResourceType = { name: \"BlockPackCustom\", version: \"1\" };\nexport const BlockPackTemplateField = \"template\";\nexport const BlockPackFrontendField = \"frontend\";\n\n/** Ensure trailing slash */\nfunction tSlash(str: string): string {\n if (str.endsWith(\"/\")) return str;\n else return `${str}/`;\n}\n\nfunction parseStringConfig(configContent: string): BlockConfigContainer {\n const res = z.record(z.string(), z.unknown()).safeParse(JSON.parse(configContent));\n\n if (!res.success) {\n throw new Error(\"Invalid config content\");\n }\n\n if (!Code.safeParse(res.data.code).success) {\n throw new Error(\"parseStringConfig:No code bundle\");\n }\n\n return res.data as BlockConfigContainer;\n}\n\nfunction parseBufferConfig(buffer: ArrayBuffer): BlockConfigContainer {\n return parseStringConfig(Buffer.from(buffer).toString(\"utf8\"));\n}\n\nexport class BlockPackPreparer {\n constructor(\n private readonly v2RegistryProvider: V2RegistryProvider,\n private readonly signer: Signer,\n private readonly http?: Dispatcher,\n ) {}\n\n private readonly remoteContentCache = new LRUCache<string, ArrayBuffer>({\n max: 500,\n maxSize: 128 * 1024 * 1024,\n fetchMethod: async (key) => {\n const httpOptions = this.http !== undefined ? { dispatcher: this.http } : {};\n return await (await request(key, httpOptions)).body.arrayBuffer();\n },\n sizeCalculation: (value) => value.byteLength,\n });\n\n /** Cache of prepared block packs for registry specs (immutable by version). */\n private readonly preparedCache = new LRUCache<PreparedCacheKey, BlockPackSpecPrepared>({\n max: 50,\n });\n\n public async getBlockConfigContainer(spec: BlockPackSpecAny): Promise<BlockConfigContainer> {\n switch (spec.type) {\n case \"explicit\":\n return spec.config;\n\n case \"prepared\":\n return spec.config;\n\n case \"dev-v1\": {\n const devPaths = await resolveDevPacket(spec.folder, false);\n const configContent = await fs.promises.readFile(devPaths.config, { encoding: \"utf-8\" });\n return JSON.parse(configContent);\n }\n\n case \"dev-v2\": {\n const description = await loadPackDescription(spec.folder);\n const configContent = await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n });\n return parseStringConfig(configContent);\n }\n\n case \"from-registry-v1\": {\n const urlPrefix = `${tSlash(spec.registryUrl)}${RegistryV1.packageContentPrefix({ organization: spec.id.organization, package: spec.id.name, version: spec.id.version })}`;\n\n const configResponse = await this.remoteContentCache.forceFetch(`${urlPrefix}/config.json`);\n return JSON.parse(Buffer.from(configResponse).toString(\"utf8\"));\n }\n\n case \"from-registry-v2\": {\n const registry = this.v2RegistryProvider.getRegistry(spec.registryUrl);\n const components = await registry.getComponents(spec.id);\n const configResponse = await this.remoteContentCache.forceFetch(components.model.url);\n return parseBufferConfig(configResponse);\n }\n\n default:\n return assertNever(spec);\n }\n }\n\n /** Returns a stable cache key for registry specs (immutable by version). Dev specs return undefined. */\n private specKey(spec: BlockPackSpecAny): PreparedCacheKey | undefined {\n switch (spec.type) {\n case \"from-registry-v1\":\n return `v1:${spec.registryUrl}:${spec.id.organization}:${spec.id.name}:${spec.id.version}` as PreparedCacheKey;\n case \"from-registry-v2\":\n return `v2:${spec.registryUrl}:${canonicalize(spec.id)}` as PreparedCacheKey;\n default:\n return undefined; // dev, explicit, prepared — not cacheable\n }\n }\n\n public async prepare(spec: BlockPackSpecAny): Promise<BlockPackSpecPrepared> {\n if (spec.type === \"prepared\") {\n return spec;\n }\n\n // Check prepare cache for registry specs\n const key = this.specKey(spec);\n if (key) {\n const cached = this.preparedCache.get(key);\n if (cached) return cached;\n }\n\n const explicit = await this.prepareWithoutUnpacking(spec);\n\n await using workerManager = new WorkerManager();\n\n const parsed = await workerManager.process(\"parseTemplate\", explicit.template.content);\n\n const result: BlockPackSpecPrepared = {\n ...explicit,\n type: \"prepared\",\n template: {\n type: \"prepared\",\n data: parsed,\n },\n requiredCapabilities: requiredCapabilitiesFromTemplate(parsed),\n };\n\n if (key) {\n this.preparedCache.set(key, result);\n }\n\n return result;\n }\n\n private async prepareWithoutUnpacking(\n spec: BlockPackExplicit | BlockPackSpec,\n ): Promise<BlockPackExplicit> {\n switch (spec.type) {\n case \"explicit\":\n return spec;\n\n case \"dev-v1\": {\n const devPaths = await resolveDevPacket(spec.folder, false);\n\n // template\n const templateContent = await fs.promises.readFile(devPaths.workflow);\n\n // config\n const config = JSON.parse(await fs.promises.readFile(devPaths.config, \"utf-8\"));\n\n // frontend\n const frontendPath = devPaths.ui;\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: templateContent,\n },\n config,\n frontend: {\n type: \"local\",\n path: frontendPath,\n signature: this.signer.sign(frontendPath),\n },\n source: spec,\n };\n }\n\n case \"dev-v2\": {\n const description = await loadPackDescription(spec.folder);\n const config = parseStringConfig(\n await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n }),\n );\n const workflowContent = await fs.promises.readFile(\n description.components.workflow.main.file,\n );\n const frontendPath = description.components.ui.folder;\n const source = { ...spec };\n if (spec.mtime === undefined)\n // if absent, calculating the mtime here, so the block will correctly show whether it can be updated\n source.mtime = await getDevV2PacketMtime(description);\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: workflowContent,\n },\n config,\n frontend: {\n type: \"local\",\n path: frontendPath,\n signature: this.signer.sign(frontendPath),\n },\n source,\n };\n }\n\n case \"from-registry-v1\": {\n const urlPrefix = `${tSlash(spec.registryUrl)}${RegistryV1.packageContentPrefix({ organization: spec.id.organization, package: spec.id.name, version: spec.id.version })}`;\n\n const templateUrl = `${urlPrefix}/template.plj.gz`;\n // template\n const templateResponse = await this.remoteContentCache.forceFetch(templateUrl);\n const templateContent = new Uint8Array(templateResponse);\n\n // config\n const configResponse = await this.remoteContentCache.forceFetch(`${urlPrefix}/config.json`);\n const config = JSON.parse(\n Buffer.from(configResponse).toString(\"utf8\"),\n ) as BlockConfigContainer;\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: templateContent,\n },\n config,\n frontend: {\n type: \"url\",\n url: `${urlPrefix}/frontend.tgz`,\n },\n source: spec,\n };\n }\n\n case \"from-registry-v2\": {\n const registry = this.v2RegistryProvider.getRegistry(spec.registryUrl);\n const components = await registry.getComponents(spec.id);\n const getModel = async () =>\n parseBufferConfig(await this.remoteContentCache.forceFetch(components.model.url));\n const getWorkflow = async () =>\n await this.remoteContentCache.forceFetch(components.workflow.main.url);\n\n const [model, workflow] = await Promise.all([getModel(), getWorkflow()]);\n const workflowContent = Buffer.from(workflow);\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: workflowContent,\n },\n config: model,\n frontend: {\n type: \"url\",\n url: components.ui.url,\n },\n source: spec,\n };\n }\n\n default:\n return assertNever(spec);\n }\n }\n}\n\nfunction createCustomBlockPack(tx: PlTransaction, spec: BlockPackSpecPrepared): AnyResourceRef {\n const blockPackInfo: BlockPackInfo = { config: spec.config, source: spec.source };\n const bp = tx.createStruct(BlockPackCustomType, JSON.stringify(blockPackInfo));\n tx.createField(field(bp, BlockPackTemplateField), \"Input\", loadTemplate(tx, spec.template));\n tx.createField(field(bp, BlockPackFrontendField), \"Input\", createFrontend(tx, spec.frontend));\n tx.lock(bp);\n\n return bp;\n}\n\nexport function createBlockPack(tx: PlTransaction, spec: BlockPackSpecPrepared): AnyResourceRef {\n switch (spec.type) {\n case \"prepared\":\n return createCustomBlockPack(tx, spec);\n default:\n return assertNever(spec.type);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"block_pack.js","names":[],"sources":["../../../src/mutator/block-pack/block_pack.ts"],"sourcesContent":["import type { AnyResourceRef, PlTransaction, ResourceType } from \"@milaboratories/pl-client\";\nimport { field } from \"@milaboratories/pl-client\";\nimport { loadTemplate } from \"../template/template_loading\";\nimport type { BlockPackExplicit, BlockPackSpecAny, BlockPackSpecPrepared } from \"../../model\";\nimport type { Signer } from \"@milaboratories/ts-helpers\";\nimport { assertNever } from \"@milaboratories/ts-helpers\";\nimport type { Branded } from \"@milaboratories/pl-model-common\";\nimport fs from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Dispatcher } from \"undici\";\nimport { request } from \"undici\";\nimport { createFrontend } from \"./frontend\";\nimport { requiredCapabilitiesFromTemplate } from \"./required_capabilities\";\nimport type { BlockConfigContainer } from \"@platforma-sdk/model\";\nimport { Code } from \"@platforma-sdk/model\";\nimport {\n loadPackDescription,\n loadPackDescriptionFromManifest,\n RegistryV1,\n} from \"@platforma-sdk/block-tools\";\nimport type { BlockPackInfo } from \"../../model/block_pack\";\nimport { resolveDevPacket } from \"../../dev_env\";\nimport { getDevV2PacketMtime, getFromPackV2Mtime } from \"../../block_registry\";\nimport type { V2RegistryProvider } from \"../../block_registry/registry-v2-provider\";\nimport { LRUCache } from \"lru-cache\";\nimport canonicalize from \"canonicalize\";\nimport type { BlockPackSpec } from \"@milaboratories/pl-model-middle-layer\";\nimport { WorkerManager } from \"../../worker/WorkerManager\";\nimport { z } from \"zod\";\n\ntype PreparedCacheKey = Branded<string, \"PreparedCacheKey\">;\n\nexport const BlockPackCustomType: ResourceType = { name: \"BlockPackCustom\", version: \"1\" };\nexport const BlockPackTemplateField = \"template\";\nexport const BlockPackFrontendField = \"frontend\";\n\n/** Ensure trailing slash */\nfunction tSlash(str: string): string {\n if (str.endsWith(\"/\")) return str;\n else return `${str}/`;\n}\n\nfunction parseStringConfig(configContent: string): BlockConfigContainer {\n const res = z.record(z.string(), z.unknown()).safeParse(JSON.parse(configContent));\n\n if (!res.success) {\n throw new Error(\"Invalid config content\");\n }\n\n if (!Code.safeParse(res.data.code).success) {\n throw new Error(\"parseStringConfig:No code bundle\");\n }\n\n return res.data as BlockConfigContainer;\n}\n\nfunction parseBufferConfig(buffer: ArrayBuffer): BlockConfigContainer {\n return parseStringConfig(Buffer.from(buffer).toString(\"utf8\"));\n}\n\nexport class BlockPackPreparer {\n constructor(\n private readonly v2RegistryProvider: V2RegistryProvider,\n private readonly signer: Signer,\n private readonly http?: Dispatcher,\n ) {}\n\n private readonly remoteContentCache = new LRUCache<string, ArrayBuffer>({\n max: 500,\n maxSize: 128 * 1024 * 1024,\n fetchMethod: async (key) => {\n const httpOptions = this.http !== undefined ? { dispatcher: this.http } : {};\n return await (await request(key, httpOptions)).body.arrayBuffer();\n },\n sizeCalculation: (value) => value.byteLength,\n });\n\n /** Cache of prepared block packs for registry specs (immutable by version). */\n private readonly preparedCache = new LRUCache<PreparedCacheKey, BlockPackSpecPrepared>({\n max: 50,\n });\n\n public async getBlockConfigContainer(spec: BlockPackSpecAny): Promise<BlockConfigContainer> {\n switch (spec.type) {\n case \"explicit\":\n return spec.config;\n\n case \"prepared\":\n return spec.config;\n\n case \"dev-v1\": {\n const devPaths = await resolveDevPacket(spec.folder, false);\n const configContent = await fs.promises.readFile(devPaths.config, { encoding: \"utf-8\" });\n return JSON.parse(configContent);\n }\n\n case \"dev-v2\": {\n const description = await loadPackDescription(spec.folder);\n const configContent = await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n });\n return parseStringConfig(configContent);\n }\n\n case \"from-pack-v2\": {\n // packUrl is a file: URL (the facade emits URLs, not paths); convert at\n // this Node boundary before touching the filesystem.\n const packDir = fileURLToPath(spec.packUrl);\n const description = await loadPackDescriptionFromManifest(packDir);\n const configContent = await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n });\n return parseStringConfig(configContent);\n }\n\n case \"from-registry-v1\": {\n const urlPrefix = `${tSlash(spec.registryUrl)}${RegistryV1.packageContentPrefix({ organization: spec.id.organization, package: spec.id.name, version: spec.id.version })}`;\n\n const configResponse = await this.remoteContentCache.forceFetch(`${urlPrefix}/config.json`);\n return JSON.parse(Buffer.from(configResponse).toString(\"utf8\"));\n }\n\n case \"from-registry-v2\": {\n const registry = this.v2RegistryProvider.getRegistry(spec.registryUrl);\n const components = await registry.getComponents(spec.id);\n const configResponse = await this.remoteContentCache.forceFetch(components.model.url);\n return parseBufferConfig(configResponse);\n }\n\n default:\n return assertNever(spec);\n }\n }\n\n /** Returns a stable cache key for registry specs (immutable by version). Dev specs return undefined. */\n private specKey(spec: BlockPackSpecAny): PreparedCacheKey | undefined {\n switch (spec.type) {\n case \"from-registry-v1\":\n return `v1:${spec.registryUrl}:${spec.id.organization}:${spec.id.name}:${spec.id.version}` as PreparedCacheKey;\n case \"from-registry-v2\":\n return `v2:${spec.registryUrl}:${canonicalize(spec.id)}` as PreparedCacheKey;\n default:\n return undefined; // dev, explicit, prepared — not cacheable\n }\n }\n\n public async prepare(spec: BlockPackSpecAny): Promise<BlockPackSpecPrepared> {\n if (spec.type === \"prepared\") {\n return spec;\n }\n\n // Check prepare cache for registry specs\n const key = this.specKey(spec);\n if (key) {\n const cached = this.preparedCache.get(key);\n if (cached) return cached;\n }\n\n const explicit = await this.prepareWithoutUnpacking(spec);\n\n await using workerManager = new WorkerManager();\n\n const parsed = await workerManager.process(\"parseTemplate\", explicit.template.content);\n\n const result: BlockPackSpecPrepared = {\n ...explicit,\n type: \"prepared\",\n template: {\n type: \"prepared\",\n data: parsed,\n },\n requiredCapabilities: requiredCapabilitiesFromTemplate(parsed),\n };\n\n if (key) {\n this.preparedCache.set(key, result);\n }\n\n return result;\n }\n\n private async prepareWithoutUnpacking(\n spec: BlockPackExplicit | BlockPackSpec,\n ): Promise<BlockPackExplicit> {\n switch (spec.type) {\n case \"explicit\":\n return spec;\n\n case \"dev-v1\": {\n const devPaths = await resolveDevPacket(spec.folder, false);\n\n // template\n const templateContent = await fs.promises.readFile(devPaths.workflow);\n\n // config\n const config = JSON.parse(await fs.promises.readFile(devPaths.config, \"utf-8\"));\n\n // frontend\n const frontendPath = devPaths.ui;\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: templateContent,\n },\n config,\n frontend: {\n type: \"local\",\n path: frontendPath,\n signature: this.signer.sign(frontendPath),\n },\n source: spec,\n };\n }\n\n case \"dev-v2\": {\n const description = await loadPackDescription(spec.folder);\n const config = parseStringConfig(\n await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n }),\n );\n const workflowContent = await fs.promises.readFile(\n description.components.workflow.main.file,\n );\n const frontendPath = description.components.ui.folder;\n const source = { ...spec };\n if (spec.mtime === undefined)\n // if absent, calculating the mtime here, so the block will correctly show whether it can be updated\n source.mtime = await getDevV2PacketMtime(description);\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: workflowContent,\n },\n config,\n frontend: {\n type: \"local\",\n path: frontendPath,\n signature: this.signer.sign(frontendPath),\n },\n source,\n };\n }\n\n case \"from-pack-v2\": {\n // packUrl is a file: URL (the facade emits URLs, not paths); convert at\n // this Node boundary before touching the filesystem.\n const packDir = fileURLToPath(spec.packUrl);\n const description = await loadPackDescriptionFromManifest(packDir);\n const config = parseStringConfig(\n await fs.promises.readFile(description.components.model.file, {\n encoding: \"utf-8\",\n }),\n );\n const workflowContent = await fs.promises.readFile(\n description.components.workflow.main.file,\n );\n // UI ships as ui.tgz inside block-pack/; its absolute path is carried\n // in the ui folder slot. The tarball is unpacked lazily at serve-time by\n // the download driver (local-tgz frontend), not eagerly here — so it\n // inherits the driver's usage-tracking and space recycling.\n const uiTgzPath = description.components.ui.folder;\n const source = { ...spec };\n let mtime = spec.mtime;\n if (mtime === undefined) {\n // No explicit mtime: derive one so the frontend cache key invalidates\n // when the block changes.\n mtime = await getFromPackV2Mtime(packDir, uiTgzPath);\n source.mtime = mtime;\n }\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: workflowContent,\n },\n config,\n frontend: {\n type: \"local-tgz\",\n path: uiTgzPath,\n mtime,\n signature: this.signer.sign(`${uiTgzPath}:${mtime}`),\n },\n source,\n };\n }\n\n case \"from-registry-v1\": {\n const urlPrefix = `${tSlash(spec.registryUrl)}${RegistryV1.packageContentPrefix({ organization: spec.id.organization, package: spec.id.name, version: spec.id.version })}`;\n\n const templateUrl = `${urlPrefix}/template.plj.gz`;\n // template\n const templateResponse = await this.remoteContentCache.forceFetch(templateUrl);\n const templateContent = new Uint8Array(templateResponse);\n\n // config\n const configResponse = await this.remoteContentCache.forceFetch(`${urlPrefix}/config.json`);\n const config = JSON.parse(\n Buffer.from(configResponse).toString(\"utf8\"),\n ) as BlockConfigContainer;\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: templateContent,\n },\n config,\n frontend: {\n type: \"url\",\n url: `${urlPrefix}/frontend.tgz`,\n },\n source: spec,\n };\n }\n\n case \"from-registry-v2\": {\n const registry = this.v2RegistryProvider.getRegistry(spec.registryUrl);\n const components = await registry.getComponents(spec.id);\n const getModel = async () =>\n parseBufferConfig(await this.remoteContentCache.forceFetch(components.model.url));\n const getWorkflow = async () =>\n await this.remoteContentCache.forceFetch(components.workflow.main.url);\n\n const [model, workflow] = await Promise.all([getModel(), getWorkflow()]);\n const workflowContent = Buffer.from(workflow);\n\n return {\n type: \"explicit\",\n template: {\n type: \"explicit\",\n content: workflowContent,\n },\n config: model,\n frontend: {\n type: \"url\",\n url: components.ui.url,\n },\n source: spec,\n };\n }\n\n default:\n return assertNever(spec);\n }\n }\n}\n\nfunction createCustomBlockPack(tx: PlTransaction, spec: BlockPackSpecPrepared): AnyResourceRef {\n const blockPackInfo: BlockPackInfo = { config: spec.config, source: spec.source };\n const bp = tx.createStruct(BlockPackCustomType, JSON.stringify(blockPackInfo));\n tx.createField(field(bp, BlockPackTemplateField), \"Input\", loadTemplate(tx, spec.template));\n tx.createField(field(bp, BlockPackFrontendField), \"Input\", createFrontend(tx, spec.frontend));\n tx.lock(bp);\n\n return bp;\n}\n\nexport function createBlockPack(tx: PlTransaction, spec: BlockPackSpecPrepared): AnyResourceRef {\n switch (spec.type) {\n case \"prepared\":\n return createCustomBlockPack(tx, spec);\n default:\n return assertNever(spec.type);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require("../../_virtual/_rolldown/runtime.cjs");
|
|
2
1
|
const require_block_pack_spec = require("../../model/block_pack_spec.cjs");
|
|
3
2
|
let _milaboratories_ts_helpers = require("@milaboratories/ts-helpers");
|
|
4
3
|
//#region src/mutator/block-pack/frontend.ts
|
|
@@ -9,6 +8,11 @@ function createFrontend(tx, spec) {
|
|
|
9
8
|
path: spec.path,
|
|
10
9
|
signature: spec.signature
|
|
11
10
|
}));
|
|
11
|
+
case "local-tgz": return tx.createValue(require_block_pack_spec.FrontendFromLocalTgzResourceType, JSON.stringify({
|
|
12
|
+
path: spec.path,
|
|
13
|
+
mtime: spec.mtime,
|
|
14
|
+
signature: spec.signature
|
|
15
|
+
}));
|
|
12
16
|
default: return (0, _milaboratories_ts_helpers.assertNever)(spec);
|
|
13
17
|
}
|
|
14
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontend.cjs","names":["FrontendFromUrlResourceType","FrontendFromFolderResourceType"],"sources":["../../../src/mutator/block-pack/frontend.ts"],"sourcesContent":["import type { AnyResourceRef, PlTransaction } from \"@milaboratories/pl-client\";\nimport type {
|
|
1
|
+
{"version":3,"file":"frontend.cjs","names":["FrontendFromUrlResourceType","FrontendFromFolderResourceType","FrontendFromLocalTgzResourceType"],"sources":["../../../src/mutator/block-pack/frontend.ts"],"sourcesContent":["import type { AnyResourceRef, PlTransaction } from \"@milaboratories/pl-client\";\nimport type {\n FrontendFromFolderData,\n FrontendFromLocalTgzData,\n FrontendFromUrlData,\n FrontendSpec,\n} from \"../../model\";\nimport {\n FrontendFromFolderResourceType,\n FrontendFromLocalTgzResourceType,\n FrontendFromUrlResourceType,\n} from \"../../model\";\nimport { assertNever } from \"@milaboratories/ts-helpers\";\n\nexport function createFrontend(tx: PlTransaction, spec: FrontendSpec): AnyResourceRef {\n switch (spec.type) {\n case \"url\":\n return tx.createValue(\n FrontendFromUrlResourceType,\n JSON.stringify({ url: spec.url } as FrontendFromUrlData),\n );\n case \"local\":\n return tx.createValue(\n FrontendFromFolderResourceType,\n JSON.stringify({\n path: spec.path,\n signature: spec.signature,\n } as FrontendFromFolderData),\n );\n case \"local-tgz\":\n return tx.createValue(\n FrontendFromLocalTgzResourceType,\n JSON.stringify({\n path: spec.path,\n mtime: spec.mtime,\n signature: spec.signature,\n } as FrontendFromLocalTgzData),\n );\n default:\n return assertNever(spec);\n }\n}\n"],"mappings":";;;AAcA,SAAgB,eAAe,IAAmB,MAAoC;CACpF,QAAQ,KAAK,MAAb;EACE,KAAK,OACH,OAAO,GAAG,YACRA,wBAAAA,6BACA,KAAK,UAAU,EAAE,KAAK,KAAK,IAAI,CAAwB,CACzD;EACF,KAAK,SACH,OAAO,GAAG,YACRC,wBAAAA,gCACA,KAAK,UAAU;GACb,MAAM,KAAK;GACX,WAAW,KAAK;EAClB,CAA2B,CAC7B;EACF,KAAK,aACH,OAAO,GAAG,YACRC,wBAAAA,kCACA,KAAK,UAAU;GACb,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,WAAW,KAAK;EAClB,CAA6B,CAC/B;EACF,SACE,QAAA,GAAA,2BAAA,YAAA,CAAmB,IAAI;CAC3B;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FrontendFromFolderResourceType, FrontendFromUrlResourceType } from "../../model/block_pack_spec.js";
|
|
1
|
+
import { FrontendFromFolderResourceType, FrontendFromLocalTgzResourceType, FrontendFromUrlResourceType } from "../../model/block_pack_spec.js";
|
|
2
2
|
import { assertNever } from "@milaboratories/ts-helpers";
|
|
3
3
|
//#region src/mutator/block-pack/frontend.ts
|
|
4
4
|
function createFrontend(tx, spec) {
|
|
@@ -8,6 +8,11 @@ function createFrontend(tx, spec) {
|
|
|
8
8
|
path: spec.path,
|
|
9
9
|
signature: spec.signature
|
|
10
10
|
}));
|
|
11
|
+
case "local-tgz": return tx.createValue(FrontendFromLocalTgzResourceType, JSON.stringify({
|
|
12
|
+
path: spec.path,
|
|
13
|
+
mtime: spec.mtime,
|
|
14
|
+
signature: spec.signature
|
|
15
|
+
}));
|
|
11
16
|
default: return assertNever(spec);
|
|
12
17
|
}
|
|
13
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontend.js","names":[],"sources":["../../../src/mutator/block-pack/frontend.ts"],"sourcesContent":["import type { AnyResourceRef, PlTransaction } from \"@milaboratories/pl-client\";\nimport type {
|
|
1
|
+
{"version":3,"file":"frontend.js","names":[],"sources":["../../../src/mutator/block-pack/frontend.ts"],"sourcesContent":["import type { AnyResourceRef, PlTransaction } from \"@milaboratories/pl-client\";\nimport type {\n FrontendFromFolderData,\n FrontendFromLocalTgzData,\n FrontendFromUrlData,\n FrontendSpec,\n} from \"../../model\";\nimport {\n FrontendFromFolderResourceType,\n FrontendFromLocalTgzResourceType,\n FrontendFromUrlResourceType,\n} from \"../../model\";\nimport { assertNever } from \"@milaboratories/ts-helpers\";\n\nexport function createFrontend(tx: PlTransaction, spec: FrontendSpec): AnyResourceRef {\n switch (spec.type) {\n case \"url\":\n return tx.createValue(\n FrontendFromUrlResourceType,\n JSON.stringify({ url: spec.url } as FrontendFromUrlData),\n );\n case \"local\":\n return tx.createValue(\n FrontendFromFolderResourceType,\n JSON.stringify({\n path: spec.path,\n signature: spec.signature,\n } as FrontendFromFolderData),\n );\n case \"local-tgz\":\n return tx.createValue(\n FrontendFromLocalTgzResourceType,\n JSON.stringify({\n path: spec.path,\n mtime: spec.mtime,\n signature: spec.signature,\n } as FrontendFromLocalTgzData),\n );\n default:\n return assertNever(spec);\n }\n}\n"],"mappings":";;;AAcA,SAAgB,eAAe,IAAmB,MAAoC;CACpF,QAAQ,KAAK,MAAb;EACE,KAAK,OACH,OAAO,GAAG,YACR,6BACA,KAAK,UAAU,EAAE,KAAK,KAAK,IAAI,CAAwB,CACzD;EACF,KAAK,SACH,OAAO,GAAG,YACR,gCACA,KAAK,UAAU;GACb,MAAM,KAAK;GACX,WAAW,KAAK;EAClB,CAA2B,CAC7B;EACF,KAAK,aACH,OAAO,GAAG,YACR,kCACA,KAAK,UAAU;GACb,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,WAAW,KAAK;EAClB,CAA6B,CAC/B;EACF,SACE,OAAO,YAAY,IAAI;CAC3B;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"required_capabilities.cjs","names":[],"sources":["../../../src/mutator/block-pack/required_capabilities.ts"],"sourcesContent":["import { gunzipSync } from \"node:zlib\";\nimport type { CompiledTemplateV3, TemplateData } from \"@milaboratories/pl-model-backend\";\n\n/**\n * Reads the capability tokens a template declares it requires via\n * `TemplateDataV3.requiredCapabilities` (populated by `tengo-builder` at\n * compile time).\n *\n * Use this on the install path: `BlockPackPreparer.prepare` parses the\n * workflow off-thread via the worker, and the parsed result feeds\n * straight into this function — no second gunzip+JSON.parse on the main\n * thread, no recursive walk to re-derive what the compiler already wrote\n * down.\n *\n * Returns `undefined` for v2 templates (no compile-time capability\n * field) and for v3 templates that declare no requirements; otherwise\n * the array as the compiler wrote it.\n */\nexport function requiredCapabilitiesFromTemplate(\n parsed: TemplateData | CompiledTemplateV3,\n): string[] | undefined {\n if (parsed.type !== \"pl.tengo-template.v3\") return undefined;\n return parsed.template.requiredCapabilities;\n}\n\n/**\n * Same lookup, starting from raw `main.plj.gz` bytes. Used only at\n * catalog-listing time for local-dev blocks where the worker pipeline\n * isn't in play (`block_registry/registry.ts`). Install paths go through\n * `requiredCapabilitiesFromTemplate` instead to avoid parsing the\n * workflow twice.\n */\nexport function deriveRequiredCapabilities(\n workflowContent: Uint8Array | Buffer,\n): string[] | undefined {\n let parsed: unknown;\n try {\n const json = gunzipSync(workflowContent).toString(\"utf-8\");\n parsed = JSON.parse(json);\n } catch {\n return undefined;\n }\n return requiredCapabilitiesFromTemplate(parsed as TemplateData | CompiledTemplateV3);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"required_capabilities.cjs","names":[],"sources":["../../../src/mutator/block-pack/required_capabilities.ts"],"sourcesContent":["import { gunzipSync } from \"node:zlib\";\nimport type { CompiledTemplateV3, TemplateData } from \"@milaboratories/pl-model-backend\";\n\n/**\n * Reads the capability tokens a template declares it requires via\n * `TemplateDataV3.requiredCapabilities` (populated by `tengo-builder` at\n * compile time).\n *\n * Use this on the install path: `BlockPackPreparer.prepare` parses the\n * workflow off-thread via the worker, and the parsed result feeds\n * straight into this function — no second gunzip+JSON.parse on the main\n * thread, no recursive walk to re-derive what the compiler already wrote\n * down.\n *\n * Returns `undefined` for v2 templates (no compile-time capability\n * field) and for v3 templates that declare no requirements; otherwise\n * the array as the compiler wrote it.\n */\nexport function requiredCapabilitiesFromTemplate(\n parsed: TemplateData | CompiledTemplateV3,\n): string[] | undefined {\n if (parsed.type !== \"pl.tengo-template.v3\") return undefined;\n return parsed.template.requiredCapabilities;\n}\n\n/**\n * Same lookup, starting from raw `main.plj.gz` bytes. Used only at\n * catalog-listing time for local-dev blocks where the worker pipeline\n * isn't in play (`block_registry/registry.ts`). Install paths go through\n * `requiredCapabilitiesFromTemplate` instead to avoid parsing the\n * workflow twice.\n */\nexport function deriveRequiredCapabilities(\n workflowContent: Uint8Array | Buffer,\n): string[] | undefined {\n let parsed: unknown;\n try {\n const json = gunzipSync(workflowContent).toString(\"utf-8\");\n parsed = JSON.parse(json);\n } catch {\n return undefined;\n }\n return requiredCapabilitiesFromTemplate(parsed as TemplateData | CompiledTemplateV3);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAkBA,SAAgB,iCACd,QACsB;CACtB,IAAI,OAAO,SAAS,wBAAwB,OAAO,KAAA;CACnD,OAAO,OAAO,SAAS;AACzB;;;;;;;;AASA,SAAgB,2BACd,iBACsB;CACtB,IAAI;CACJ,IAAI;EACF,MAAM,QAAA,GAAA,UAAA,WAAA,CAAkB,eAAe,CAAC,CAAC,SAAS,OAAO;EACzD,SAAS,KAAK,MAAM,IAAI;CAC1B,QAAQ;EACN;CACF;CACA,OAAO,iCAAiC,MAA2C;AACrF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"required_capabilities.js","names":[],"sources":["../../../src/mutator/block-pack/required_capabilities.ts"],"sourcesContent":["import { gunzipSync } from \"node:zlib\";\nimport type { CompiledTemplateV3, TemplateData } from \"@milaboratories/pl-model-backend\";\n\n/**\n * Reads the capability tokens a template declares it requires via\n * `TemplateDataV3.requiredCapabilities` (populated by `tengo-builder` at\n * compile time).\n *\n * Use this on the install path: `BlockPackPreparer.prepare` parses the\n * workflow off-thread via the worker, and the parsed result feeds\n * straight into this function — no second gunzip+JSON.parse on the main\n * thread, no recursive walk to re-derive what the compiler already wrote\n * down.\n *\n * Returns `undefined` for v2 templates (no compile-time capability\n * field) and for v3 templates that declare no requirements; otherwise\n * the array as the compiler wrote it.\n */\nexport function requiredCapabilitiesFromTemplate(\n parsed: TemplateData | CompiledTemplateV3,\n): string[] | undefined {\n if (parsed.type !== \"pl.tengo-template.v3\") return undefined;\n return parsed.template.requiredCapabilities;\n}\n\n/**\n * Same lookup, starting from raw `main.plj.gz` bytes. Used only at\n * catalog-listing time for local-dev blocks where the worker pipeline\n * isn't in play (`block_registry/registry.ts`). Install paths go through\n * `requiredCapabilitiesFromTemplate` instead to avoid parsing the\n * workflow twice.\n */\nexport function deriveRequiredCapabilities(\n workflowContent: Uint8Array | Buffer,\n): string[] | undefined {\n let parsed: unknown;\n try {\n const json = gunzipSync(workflowContent).toString(\"utf-8\");\n parsed = JSON.parse(json);\n } catch {\n return undefined;\n }\n return requiredCapabilitiesFromTemplate(parsed as TemplateData | CompiledTemplateV3);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAkBA,SAAgB,iCACd,QACsB;
|
|
1
|
+
{"version":3,"file":"required_capabilities.js","names":[],"sources":["../../../src/mutator/block-pack/required_capabilities.ts"],"sourcesContent":["import { gunzipSync } from \"node:zlib\";\nimport type { CompiledTemplateV3, TemplateData } from \"@milaboratories/pl-model-backend\";\n\n/**\n * Reads the capability tokens a template declares it requires via\n * `TemplateDataV3.requiredCapabilities` (populated by `tengo-builder` at\n * compile time).\n *\n * Use this on the install path: `BlockPackPreparer.prepare` parses the\n * workflow off-thread via the worker, and the parsed result feeds\n * straight into this function — no second gunzip+JSON.parse on the main\n * thread, no recursive walk to re-derive what the compiler already wrote\n * down.\n *\n * Returns `undefined` for v2 templates (no compile-time capability\n * field) and for v3 templates that declare no requirements; otherwise\n * the array as the compiler wrote it.\n */\nexport function requiredCapabilitiesFromTemplate(\n parsed: TemplateData | CompiledTemplateV3,\n): string[] | undefined {\n if (parsed.type !== \"pl.tengo-template.v3\") return undefined;\n return parsed.template.requiredCapabilities;\n}\n\n/**\n * Same lookup, starting from raw `main.plj.gz` bytes. Used only at\n * catalog-listing time for local-dev blocks where the worker pipeline\n * isn't in play (`block_registry/registry.ts`). Install paths go through\n * `requiredCapabilitiesFromTemplate` instead to avoid parsing the\n * workflow twice.\n */\nexport function deriveRequiredCapabilities(\n workflowContent: Uint8Array | Buffer,\n): string[] | undefined {\n let parsed: unknown;\n try {\n const json = gunzipSync(workflowContent).toString(\"utf-8\");\n parsed = JSON.parse(json);\n } catch {\n return undefined;\n }\n return requiredCapabilitiesFromTemplate(parsed as TemplateData | CompiledTemplateV3);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAkBA,SAAgB,iCACd,QACsB;CACtB,IAAI,OAAO,SAAS,wBAAwB,OAAO,KAAA;CACnD,OAAO,OAAO,SAAS;AACzB;;;;;;;;AASA,SAAgB,2BACd,iBACsB;CACtB,IAAI;CACJ,IAAI;EACF,MAAM,OAAO,WAAW,eAAe,CAAC,CAAC,SAAS,OAAO;EACzD,SAAS,KAAK,MAAM,IAAI;CAC1B,QAAQ;EACN;CACF;CACA,OAAO,iCAAiC,MAA2C;AACrF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context_export.cjs","names":["prepareTemplateSpec","SdkTemplates","createRenderTemplate"],"sources":["../../src/mutator/context_export.ts"],"sourcesContent":["import type { AnyRef, PlTransaction } from \"@milaboratories/pl-client\";\nimport { createRenderTemplate } from \"./template/render_template\";\nimport { prepareTemplateSpec } from \"./template/template_loading\";\nimport type { TemplateSpecPrepared } from \"../model/template_spec\";\nimport { createHash } from \"node:crypto\";\n\n// Workaround to prevent bundling of @platforma-sdk/workflow-tengo\n// if bundling happens import.meta.dirname will be transfered as is without transferring corresponding assets\n// Construct like new URL(…, import.meta.url) also does not work properly.\n// const require = createRequire(import.meta.url);\n// const SdkTemplates = require('@platforma-sdk/workflow-tengo').Templates;\n\nimport { Templates as SdkTemplates } from \"@platforma-sdk/workflow-tengo\";\n\nexport type TemplateEnvelop = { spec: TemplateSpecPrepared; hash: string };\n\nlet preparedTemplateEnvelop: TemplateEnvelop | undefined;\n\nexport async function getPreparedExportTemplateEnvelope(): Promise<TemplateEnvelop> {\n if (preparedTemplateEnvelop === undefined) {\n // (await import('@platforma-sdk/workflow-tengo')).Templates['pframes.export-pframe']\n const preparedTemplate = await prepareTemplateSpec(\n SdkTemplates[\"pframes.export-pframe-for-ui\"],\n );\n if (preparedTemplate.type !== \"explicit\") throw new Error(\"Unexpected prepared template type.\");\n const hash = createHash(\"sha256\").update(preparedTemplate.content).digest(\"hex\");\n preparedTemplateEnvelop = { spec: preparedTemplate, hash };\n }\n\n return preparedTemplateEnvelop;\n}\n\nexport function exportContext(tx: PlTransaction, exportTpl: AnyRef, ctx: AnyRef) {\n return createRenderTemplate(tx, exportTpl, true, { pf: ctx }, [\"result\"]).result;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"context_export.cjs","names":["prepareTemplateSpec","SdkTemplates","createRenderTemplate"],"sources":["../../src/mutator/context_export.ts"],"sourcesContent":["import type { AnyRef, PlTransaction } from \"@milaboratories/pl-client\";\nimport { createRenderTemplate } from \"./template/render_template\";\nimport { prepareTemplateSpec } from \"./template/template_loading\";\nimport type { TemplateSpecPrepared } from \"../model/template_spec\";\nimport { createHash } from \"node:crypto\";\n\n// Workaround to prevent bundling of @platforma-sdk/workflow-tengo\n// if bundling happens import.meta.dirname will be transfered as is without transferring corresponding assets\n// Construct like new URL(…, import.meta.url) also does not work properly.\n// const require = createRequire(import.meta.url);\n// const SdkTemplates = require('@platforma-sdk/workflow-tengo').Templates;\n\nimport { Templates as SdkTemplates } from \"@platforma-sdk/workflow-tengo\";\n\nexport type TemplateEnvelop = { spec: TemplateSpecPrepared; hash: string };\n\nlet preparedTemplateEnvelop: TemplateEnvelop | undefined;\n\nexport async function getPreparedExportTemplateEnvelope(): Promise<TemplateEnvelop> {\n if (preparedTemplateEnvelop === undefined) {\n // (await import('@platforma-sdk/workflow-tengo')).Templates['pframes.export-pframe']\n const preparedTemplate = await prepareTemplateSpec(\n SdkTemplates[\"pframes.export-pframe-for-ui\"],\n );\n if (preparedTemplate.type !== \"explicit\") throw new Error(\"Unexpected prepared template type.\");\n const hash = createHash(\"sha256\").update(preparedTemplate.content).digest(\"hex\");\n preparedTemplateEnvelop = { spec: preparedTemplate, hash };\n }\n\n return preparedTemplateEnvelop;\n}\n\nexport function exportContext(tx: PlTransaction, exportTpl: AnyRef, ctx: AnyRef) {\n return createRenderTemplate(tx, exportTpl, true, { pf: ctx }, [\"result\"]).result;\n}\n"],"mappings":";;;;;AAgBA,IAAI;AAEJ,eAAsB,oCAA8D;CAClF,IAAI,4BAA4B,KAAA,GAAW;EAEzC,MAAM,mBAAmB,MAAMA,yBAAAA,oBAC7BC,8BAAAA,UAAa,+BACf;EACA,IAAI,iBAAiB,SAAS,YAAY,MAAM,IAAI,MAAM,oCAAoC;EAE9F,0BAA0B;GAAE,MAAM;GAAkB,OAAA,GAAA,YAAA,WAAA,CAD5B,QAAQ,CAAC,CAAC,OAAO,iBAAiB,OAAO,CAAC,CAAC,OAAO,KACnB;EAAE;CAC3D;CAEA,OAAO;AACT;AAEA,SAAgB,cAAc,IAAmB,WAAmB,KAAa;CAC/E,OAAOC,wBAAAA,qBAAqB,IAAI,WAAW,MAAM,EAAE,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC5E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context_export.js","names":["SdkTemplates"],"sources":["../../src/mutator/context_export.ts"],"sourcesContent":["import type { AnyRef, PlTransaction } from \"@milaboratories/pl-client\";\nimport { createRenderTemplate } from \"./template/render_template\";\nimport { prepareTemplateSpec } from \"./template/template_loading\";\nimport type { TemplateSpecPrepared } from \"../model/template_spec\";\nimport { createHash } from \"node:crypto\";\n\n// Workaround to prevent bundling of @platforma-sdk/workflow-tengo\n// if bundling happens import.meta.dirname will be transfered as is without transferring corresponding assets\n// Construct like new URL(…, import.meta.url) also does not work properly.\n// const require = createRequire(import.meta.url);\n// const SdkTemplates = require('@platforma-sdk/workflow-tengo').Templates;\n\nimport { Templates as SdkTemplates } from \"@platforma-sdk/workflow-tengo\";\n\nexport type TemplateEnvelop = { spec: TemplateSpecPrepared; hash: string };\n\nlet preparedTemplateEnvelop: TemplateEnvelop | undefined;\n\nexport async function getPreparedExportTemplateEnvelope(): Promise<TemplateEnvelop> {\n if (preparedTemplateEnvelop === undefined) {\n // (await import('@platforma-sdk/workflow-tengo')).Templates['pframes.export-pframe']\n const preparedTemplate = await prepareTemplateSpec(\n SdkTemplates[\"pframes.export-pframe-for-ui\"],\n );\n if (preparedTemplate.type !== \"explicit\") throw new Error(\"Unexpected prepared template type.\");\n const hash = createHash(\"sha256\").update(preparedTemplate.content).digest(\"hex\");\n preparedTemplateEnvelop = { spec: preparedTemplate, hash };\n }\n\n return preparedTemplateEnvelop;\n}\n\nexport function exportContext(tx: PlTransaction, exportTpl: AnyRef, ctx: AnyRef) {\n return createRenderTemplate(tx, exportTpl, true, { pf: ctx }, [\"result\"]).result;\n}\n"],"mappings":";;;;;AAgBA,IAAI;AAEJ,eAAsB,oCAA8D;
|
|
1
|
+
{"version":3,"file":"context_export.js","names":["SdkTemplates"],"sources":["../../src/mutator/context_export.ts"],"sourcesContent":["import type { AnyRef, PlTransaction } from \"@milaboratories/pl-client\";\nimport { createRenderTemplate } from \"./template/render_template\";\nimport { prepareTemplateSpec } from \"./template/template_loading\";\nimport type { TemplateSpecPrepared } from \"../model/template_spec\";\nimport { createHash } from \"node:crypto\";\n\n// Workaround to prevent bundling of @platforma-sdk/workflow-tengo\n// if bundling happens import.meta.dirname will be transfered as is without transferring corresponding assets\n// Construct like new URL(…, import.meta.url) also does not work properly.\n// const require = createRequire(import.meta.url);\n// const SdkTemplates = require('@platforma-sdk/workflow-tengo').Templates;\n\nimport { Templates as SdkTemplates } from \"@platforma-sdk/workflow-tengo\";\n\nexport type TemplateEnvelop = { spec: TemplateSpecPrepared; hash: string };\n\nlet preparedTemplateEnvelop: TemplateEnvelop | undefined;\n\nexport async function getPreparedExportTemplateEnvelope(): Promise<TemplateEnvelop> {\n if (preparedTemplateEnvelop === undefined) {\n // (await import('@platforma-sdk/workflow-tengo')).Templates['pframes.export-pframe']\n const preparedTemplate = await prepareTemplateSpec(\n SdkTemplates[\"pframes.export-pframe-for-ui\"],\n );\n if (preparedTemplate.type !== \"explicit\") throw new Error(\"Unexpected prepared template type.\");\n const hash = createHash(\"sha256\").update(preparedTemplate.content).digest(\"hex\");\n preparedTemplateEnvelop = { spec: preparedTemplate, hash };\n }\n\n return preparedTemplateEnvelop;\n}\n\nexport function exportContext(tx: PlTransaction, exportTpl: AnyRef, ctx: AnyRef) {\n return createRenderTemplate(tx, exportTpl, true, { pf: ctx }, [\"result\"]).result;\n}\n"],"mappings":";;;;;AAgBA,IAAI;AAEJ,eAAsB,oCAA8D;CAClF,IAAI,4BAA4B,KAAA,GAAW;EAEzC,MAAM,mBAAmB,MAAM,oBAC7BA,UAAa,+BACf;EACA,IAAI,iBAAiB,SAAS,YAAY,MAAM,IAAI,MAAM,oCAAoC;EAE9F,0BAA0B;GAAE,MAAM;GAAkB,MADvC,WAAW,QAAQ,CAAC,CAAC,OAAO,iBAAiB,OAAO,CAAC,CAAC,OAAO,KACnB;EAAE;CAC3D;CAEA,OAAO;AACT;AAEA,SAAgB,cAAc,IAAmB,WAAmB,KAAa;CAC/E,OAAO,qBAAqB,IAAI,WAAW,MAAM,EAAE,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC5E"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
1
|
const require_project_model = require("../model/project_model.cjs");
|
|
3
2
|
const require_project_model_util = require("../model/project_model_util.cjs");
|
|
4
3
|
const require_project_model_v1 = require("../model/project_model_v1.cjs");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration.cjs","names":["SchemaVersionKey","UiError","ProjectStructureKey","allBlocks","BlockFrontendStateKeyPrefixV1","projectFieldName"],"sources":["../../src/mutator/migration.ts"],"sourcesContent":["import { UiError } from \"@milaboratories/pl-model-common\";\nimport type { PlClient, PlTransaction, SignedResourceId } from \"@milaboratories/pl-client\";\nimport type { ProjectField, ProjectStructure } from \"../model/project_model\";\nimport {\n projectFieldName,\n ProjectStructureKey,\n SchemaVersionCurrent,\n SchemaVersionKey,\n SchemaVersionV2,\n SchemaVersionV3,\n} from \"../model/project_model\";\nimport { BlockFrontendStateKeyPrefixV1, SchemaVersionV1 } from \"../model/project_model_v1\";\nimport { field, isNullSignedResourceId } from \"@milaboratories/pl-client\";\nimport { cachedDeserialize } from \"@milaboratories/ts-helpers\";\nimport { allBlocks } from \"../model/project_model_util\";\n\n/**\n * Migrates the project to the latest schema version.\n *\n * @param pl - The client to use.\n * @param rid - The resource id of the project.\n */\nexport async function applyProjectMigrations(pl: PlClient, rid: SignedResourceId) {\n await pl.withWriteTx(\"ProjectMigration\", async (tx) => {\n let schemaVersion = await tx.getKValueJson<string>(rid, SchemaVersionKey);\n if (schemaVersion === SchemaVersionCurrent) return;\n\n // Apply migrations in sequence\n if (schemaVersion === SchemaVersionV1) {\n await migrateV1ToV2(tx, rid);\n schemaVersion = SchemaVersionV2;\n }\n\n if (schemaVersion === SchemaVersionV2) {\n await migrateV2ToV3(tx, rid);\n schemaVersion = SchemaVersionV3;\n }\n\n if (schemaVersion === SchemaVersionV3) {\n // V3 → V4: production context chain + staging re-render.\n // The actual chain building and staging reset happens in fixProblemsAndMigrate()\n // (called from ProjectMutator.load). This migration step just bumps the schema\n // to prevent older clients from operating on the new project structure.\n schemaVersion = SchemaVersionCurrent;\n }\n\n if (schemaVersion !== SchemaVersionCurrent) {\n throw new UiError(\n `This project was created with a newer version of Platforma. Please update to the latest version to open it.`,\n );\n }\n\n tx.setKValue(rid, SchemaVersionKey, JSON.stringify(SchemaVersionCurrent));\n await tx.commit();\n });\n}\n\n/**\n * Migrates the project from schema version 1 to 2.\n *\n * Summary of changes:\n * - uiState is now stored in a field instead of a KV\n *\n * @param tx - The transaction to use.\n * @param rid - The resource id of the project.\n */\nasync function migrateV1ToV2(tx: PlTransaction, rid: SignedResourceId) {\n const [structure, allKV] = await Promise.all([\n tx.getKValueJson<ProjectStructure>(rid, ProjectStructureKey),\n tx.listKeyValues(rid),\n ]);\n const kvMap = new Map<string, Uint8Array>(allKV.map((kv) => [kv.key, kv.value]));\n for (const block of allBlocks(structure)) {\n const kvKey = BlockFrontendStateKeyPrefixV1 + block.id;\n const uiState = kvMap.get(kvKey);\n const valueJson = uiState ? cachedDeserialize(uiState) : {};\n const uiStateR = tx.createJsonGzValue(valueJson);\n const uiStateF = field(rid, projectFieldName(block.id, \"blockStorage\"));\n tx.createField(uiStateF, \"Dynamic\", uiStateR);\n tx.deleteKValue(rid, kvKey);\n }\n}\n\n/**\n * Migrates the project from schema version 2 to 3.\n *\n * Summary of changes:\n * - Introduces unified 'blockStorage' field containing { args, uiState }\n * - Adds 'currentPrerunArgs' field for staging/prerun rendering\n * - For each block:\n * 1. Read existing 'blockStorage' field (contains uiState in v2)\n * 2. Read existing 'currentArgs' field (contains args)\n * 3. Create unified state = { args: currentArgs, uiState: oldState }\n * 4. Write to new {blockId}-blockStorage field (overwrites)\n * 5. Initialize {blockId}-currentPrerunArgs (same as prodArgs for v1/v2 blocks)\n * - Note: currentArgs and prodArgs fields remain for compatibility layer\n *\n * @param tx - The transaction to use.\n * @param rid - The resource id of the project.\n */\nasync function migrateV2ToV3(tx: PlTransaction, rid: SignedResourceId) {\n const [structure, fullResourceState] = await Promise.all([\n tx.getKValueJson<ProjectStructure>(rid, ProjectStructureKey),\n tx.getResourceData(rid, true),\n ]);\n\n // Build a map of field name -> resource id for quick lookup\n const fieldMap = new Map<string, SignedResourceId>();\n for (const f of fullResourceState.fields) {\n if (!isNullSignedResourceId(f.value)) {\n fieldMap.set(f.name, f.value);\n }\n }\n\n for (const block of allBlocks(structure)) {\n // Read existing field values\n const uiStateFieldName = projectFieldName(block.id, \"uiState\" as ProjectField[\"fieldName\"]);\n const currentArgsFieldName = projectFieldName(block.id, \"currentArgs\");\n\n const uiStateRid = fieldMap.get(uiStateFieldName);\n const currentArgsRid = fieldMap.get(currentArgsFieldName);\n\n // Read field data in parallel where available\n const [uiStateData, currentArgsData] = await Promise.all([\n uiStateRid ? tx.getResourceData(uiStateRid, false) : Promise.resolve(undefined),\n currentArgsRid ? tx.getResourceData(currentArgsRid, false) : Promise.resolve(undefined),\n ]);\n\n // Extract values - in v2, 'blockStorage' contains raw uiState, not wrapped\n const uiState = uiStateData?.data ? cachedDeserialize(uiStateData.data) : {};\n const args = currentArgsData?.data ? cachedDeserialize(currentArgsData.data) : {};\n\n // Create unified state: { args, uiState }\n const unifiedState = {\n args,\n uiState,\n };\n\n const blockStorageFieldName = projectFieldName(block.id, \"blockStorage\");\n\n // Write new unified blockStorage field (overwrite existing)\n const stateR = tx.createJsonGzValue(unifiedState);\n const stateF = field(rid, blockStorageFieldName);\n tx.createField(stateF, \"Dynamic\", stateR);\n\n // Initialize currentPrerunArgs from currentArgs (for legacy blocks, prerunArgs = args)\n if (currentArgsRid) {\n const prerunArgsR = tx.createJsonGzValue(args);\n const prerunArgsF = field(rid, projectFieldName(block.id, \"currentPrerunArgs\"));\n tx.createField(prerunArgsF, \"Dynamic\", prerunArgsR);\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"migration.cjs","names":["SchemaVersionKey","UiError","ProjectStructureKey","allBlocks","BlockFrontendStateKeyPrefixV1","projectFieldName"],"sources":["../../src/mutator/migration.ts"],"sourcesContent":["import { UiError } from \"@milaboratories/pl-model-common\";\nimport type { PlClient, PlTransaction, SignedResourceId } from \"@milaboratories/pl-client\";\nimport type { ProjectField, ProjectStructure } from \"../model/project_model\";\nimport {\n projectFieldName,\n ProjectStructureKey,\n SchemaVersionCurrent,\n SchemaVersionKey,\n SchemaVersionV2,\n SchemaVersionV3,\n} from \"../model/project_model\";\nimport { BlockFrontendStateKeyPrefixV1, SchemaVersionV1 } from \"../model/project_model_v1\";\nimport { field, isNullSignedResourceId } from \"@milaboratories/pl-client\";\nimport { cachedDeserialize } from \"@milaboratories/ts-helpers\";\nimport { allBlocks } from \"../model/project_model_util\";\n\n/**\n * Migrates the project to the latest schema version.\n *\n * @param pl - The client to use.\n * @param rid - The resource id of the project.\n */\nexport async function applyProjectMigrations(pl: PlClient, rid: SignedResourceId) {\n await pl.withWriteTx(\"ProjectMigration\", async (tx) => {\n let schemaVersion = await tx.getKValueJson<string>(rid, SchemaVersionKey);\n if (schemaVersion === SchemaVersionCurrent) return;\n\n // Apply migrations in sequence\n if (schemaVersion === SchemaVersionV1) {\n await migrateV1ToV2(tx, rid);\n schemaVersion = SchemaVersionV2;\n }\n\n if (schemaVersion === SchemaVersionV2) {\n await migrateV2ToV3(tx, rid);\n schemaVersion = SchemaVersionV3;\n }\n\n if (schemaVersion === SchemaVersionV3) {\n // V3 → V4: production context chain + staging re-render.\n // The actual chain building and staging reset happens in fixProblemsAndMigrate()\n // (called from ProjectMutator.load). This migration step just bumps the schema\n // to prevent older clients from operating on the new project structure.\n schemaVersion = SchemaVersionCurrent;\n }\n\n if (schemaVersion !== SchemaVersionCurrent) {\n throw new UiError(\n `This project was created with a newer version of Platforma. Please update to the latest version to open it.`,\n );\n }\n\n tx.setKValue(rid, SchemaVersionKey, JSON.stringify(SchemaVersionCurrent));\n await tx.commit();\n });\n}\n\n/**\n * Migrates the project from schema version 1 to 2.\n *\n * Summary of changes:\n * - uiState is now stored in a field instead of a KV\n *\n * @param tx - The transaction to use.\n * @param rid - The resource id of the project.\n */\nasync function migrateV1ToV2(tx: PlTransaction, rid: SignedResourceId) {\n const [structure, allKV] = await Promise.all([\n tx.getKValueJson<ProjectStructure>(rid, ProjectStructureKey),\n tx.listKeyValues(rid),\n ]);\n const kvMap = new Map<string, Uint8Array>(allKV.map((kv) => [kv.key, kv.value]));\n for (const block of allBlocks(structure)) {\n const kvKey = BlockFrontendStateKeyPrefixV1 + block.id;\n const uiState = kvMap.get(kvKey);\n const valueJson = uiState ? cachedDeserialize(uiState) : {};\n const uiStateR = tx.createJsonGzValue(valueJson);\n const uiStateF = field(rid, projectFieldName(block.id, \"blockStorage\"));\n tx.createField(uiStateF, \"Dynamic\", uiStateR);\n tx.deleteKValue(rid, kvKey);\n }\n}\n\n/**\n * Migrates the project from schema version 2 to 3.\n *\n * Summary of changes:\n * - Introduces unified 'blockStorage' field containing { args, uiState }\n * - Adds 'currentPrerunArgs' field for staging/prerun rendering\n * - For each block:\n * 1. Read existing 'blockStorage' field (contains uiState in v2)\n * 2. Read existing 'currentArgs' field (contains args)\n * 3. Create unified state = { args: currentArgs, uiState: oldState }\n * 4. Write to new {blockId}-blockStorage field (overwrites)\n * 5. Initialize {blockId}-currentPrerunArgs (same as prodArgs for v1/v2 blocks)\n * - Note: currentArgs and prodArgs fields remain for compatibility layer\n *\n * @param tx - The transaction to use.\n * @param rid - The resource id of the project.\n */\nasync function migrateV2ToV3(tx: PlTransaction, rid: SignedResourceId) {\n const [structure, fullResourceState] = await Promise.all([\n tx.getKValueJson<ProjectStructure>(rid, ProjectStructureKey),\n tx.getResourceData(rid, true),\n ]);\n\n // Build a map of field name -> resource id for quick lookup\n const fieldMap = new Map<string, SignedResourceId>();\n for (const f of fullResourceState.fields) {\n if (!isNullSignedResourceId(f.value)) {\n fieldMap.set(f.name, f.value);\n }\n }\n\n for (const block of allBlocks(structure)) {\n // Read existing field values\n const uiStateFieldName = projectFieldName(block.id, \"uiState\" as ProjectField[\"fieldName\"]);\n const currentArgsFieldName = projectFieldName(block.id, \"currentArgs\");\n\n const uiStateRid = fieldMap.get(uiStateFieldName);\n const currentArgsRid = fieldMap.get(currentArgsFieldName);\n\n // Read field data in parallel where available\n const [uiStateData, currentArgsData] = await Promise.all([\n uiStateRid ? tx.getResourceData(uiStateRid, false) : Promise.resolve(undefined),\n currentArgsRid ? tx.getResourceData(currentArgsRid, false) : Promise.resolve(undefined),\n ]);\n\n // Extract values - in v2, 'blockStorage' contains raw uiState, not wrapped\n const uiState = uiStateData?.data ? cachedDeserialize(uiStateData.data) : {};\n const args = currentArgsData?.data ? cachedDeserialize(currentArgsData.data) : {};\n\n // Create unified state: { args, uiState }\n const unifiedState = {\n args,\n uiState,\n };\n\n const blockStorageFieldName = projectFieldName(block.id, \"blockStorage\");\n\n // Write new unified blockStorage field (overwrite existing)\n const stateR = tx.createJsonGzValue(unifiedState);\n const stateF = field(rid, blockStorageFieldName);\n tx.createField(stateF, \"Dynamic\", stateR);\n\n // Initialize currentPrerunArgs from currentArgs (for legacy blocks, prerunArgs = args)\n if (currentArgsRid) {\n const prerunArgsR = tx.createJsonGzValue(args);\n const prerunArgsF = field(rid, projectFieldName(block.id, \"currentPrerunArgs\"));\n tx.createField(prerunArgsF, \"Dynamic\", prerunArgsR);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration.js","names":[],"sources":["../../src/mutator/migration.ts"],"sourcesContent":["import { UiError } from \"@milaboratories/pl-model-common\";\nimport type { PlClient, PlTransaction, SignedResourceId } from \"@milaboratories/pl-client\";\nimport type { ProjectField, ProjectStructure } from \"../model/project_model\";\nimport {\n projectFieldName,\n ProjectStructureKey,\n SchemaVersionCurrent,\n SchemaVersionKey,\n SchemaVersionV2,\n SchemaVersionV3,\n} from \"../model/project_model\";\nimport { BlockFrontendStateKeyPrefixV1, SchemaVersionV1 } from \"../model/project_model_v1\";\nimport { field, isNullSignedResourceId } from \"@milaboratories/pl-client\";\nimport { cachedDeserialize } from \"@milaboratories/ts-helpers\";\nimport { allBlocks } from \"../model/project_model_util\";\n\n/**\n * Migrates the project to the latest schema version.\n *\n * @param pl - The client to use.\n * @param rid - The resource id of the project.\n */\nexport async function applyProjectMigrations(pl: PlClient, rid: SignedResourceId) {\n await pl.withWriteTx(\"ProjectMigration\", async (tx) => {\n let schemaVersion = await tx.getKValueJson<string>(rid, SchemaVersionKey);\n if (schemaVersion === SchemaVersionCurrent) return;\n\n // Apply migrations in sequence\n if (schemaVersion === SchemaVersionV1) {\n await migrateV1ToV2(tx, rid);\n schemaVersion = SchemaVersionV2;\n }\n\n if (schemaVersion === SchemaVersionV2) {\n await migrateV2ToV3(tx, rid);\n schemaVersion = SchemaVersionV3;\n }\n\n if (schemaVersion === SchemaVersionV3) {\n // V3 → V4: production context chain + staging re-render.\n // The actual chain building and staging reset happens in fixProblemsAndMigrate()\n // (called from ProjectMutator.load). This migration step just bumps the schema\n // to prevent older clients from operating on the new project structure.\n schemaVersion = SchemaVersionCurrent;\n }\n\n if (schemaVersion !== SchemaVersionCurrent) {\n throw new UiError(\n `This project was created with a newer version of Platforma. Please update to the latest version to open it.`,\n );\n }\n\n tx.setKValue(rid, SchemaVersionKey, JSON.stringify(SchemaVersionCurrent));\n await tx.commit();\n });\n}\n\n/**\n * Migrates the project from schema version 1 to 2.\n *\n * Summary of changes:\n * - uiState is now stored in a field instead of a KV\n *\n * @param tx - The transaction to use.\n * @param rid - The resource id of the project.\n */\nasync function migrateV1ToV2(tx: PlTransaction, rid: SignedResourceId) {\n const [structure, allKV] = await Promise.all([\n tx.getKValueJson<ProjectStructure>(rid, ProjectStructureKey),\n tx.listKeyValues(rid),\n ]);\n const kvMap = new Map<string, Uint8Array>(allKV.map((kv) => [kv.key, kv.value]));\n for (const block of allBlocks(structure)) {\n const kvKey = BlockFrontendStateKeyPrefixV1 + block.id;\n const uiState = kvMap.get(kvKey);\n const valueJson = uiState ? cachedDeserialize(uiState) : {};\n const uiStateR = tx.createJsonGzValue(valueJson);\n const uiStateF = field(rid, projectFieldName(block.id, \"blockStorage\"));\n tx.createField(uiStateF, \"Dynamic\", uiStateR);\n tx.deleteKValue(rid, kvKey);\n }\n}\n\n/**\n * Migrates the project from schema version 2 to 3.\n *\n * Summary of changes:\n * - Introduces unified 'blockStorage' field containing { args, uiState }\n * - Adds 'currentPrerunArgs' field for staging/prerun rendering\n * - For each block:\n * 1. Read existing 'blockStorage' field (contains uiState in v2)\n * 2. Read existing 'currentArgs' field (contains args)\n * 3. Create unified state = { args: currentArgs, uiState: oldState }\n * 4. Write to new {blockId}-blockStorage field (overwrites)\n * 5. Initialize {blockId}-currentPrerunArgs (same as prodArgs for v1/v2 blocks)\n * - Note: currentArgs and prodArgs fields remain for compatibility layer\n *\n * @param tx - The transaction to use.\n * @param rid - The resource id of the project.\n */\nasync function migrateV2ToV3(tx: PlTransaction, rid: SignedResourceId) {\n const [structure, fullResourceState] = await Promise.all([\n tx.getKValueJson<ProjectStructure>(rid, ProjectStructureKey),\n tx.getResourceData(rid, true),\n ]);\n\n // Build a map of field name -> resource id for quick lookup\n const fieldMap = new Map<string, SignedResourceId>();\n for (const f of fullResourceState.fields) {\n if (!isNullSignedResourceId(f.value)) {\n fieldMap.set(f.name, f.value);\n }\n }\n\n for (const block of allBlocks(structure)) {\n // Read existing field values\n const uiStateFieldName = projectFieldName(block.id, \"uiState\" as ProjectField[\"fieldName\"]);\n const currentArgsFieldName = projectFieldName(block.id, \"currentArgs\");\n\n const uiStateRid = fieldMap.get(uiStateFieldName);\n const currentArgsRid = fieldMap.get(currentArgsFieldName);\n\n // Read field data in parallel where available\n const [uiStateData, currentArgsData] = await Promise.all([\n uiStateRid ? tx.getResourceData(uiStateRid, false) : Promise.resolve(undefined),\n currentArgsRid ? tx.getResourceData(currentArgsRid, false) : Promise.resolve(undefined),\n ]);\n\n // Extract values - in v2, 'blockStorage' contains raw uiState, not wrapped\n const uiState = uiStateData?.data ? cachedDeserialize(uiStateData.data) : {};\n const args = currentArgsData?.data ? cachedDeserialize(currentArgsData.data) : {};\n\n // Create unified state: { args, uiState }\n const unifiedState = {\n args,\n uiState,\n };\n\n const blockStorageFieldName = projectFieldName(block.id, \"blockStorage\");\n\n // Write new unified blockStorage field (overwrite existing)\n const stateR = tx.createJsonGzValue(unifiedState);\n const stateF = field(rid, blockStorageFieldName);\n tx.createField(stateF, \"Dynamic\", stateR);\n\n // Initialize currentPrerunArgs from currentArgs (for legacy blocks, prerunArgs = args)\n if (currentArgsRid) {\n const prerunArgsR = tx.createJsonGzValue(args);\n const prerunArgsF = field(rid, projectFieldName(block.id, \"currentPrerunArgs\"));\n tx.createField(prerunArgsF, \"Dynamic\", prerunArgsR);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAsBA,eAAsB,uBAAuB,IAAc,KAAuB;
|
|
1
|
+
{"version":3,"file":"migration.js","names":[],"sources":["../../src/mutator/migration.ts"],"sourcesContent":["import { UiError } from \"@milaboratories/pl-model-common\";\nimport type { PlClient, PlTransaction, SignedResourceId } from \"@milaboratories/pl-client\";\nimport type { ProjectField, ProjectStructure } from \"../model/project_model\";\nimport {\n projectFieldName,\n ProjectStructureKey,\n SchemaVersionCurrent,\n SchemaVersionKey,\n SchemaVersionV2,\n SchemaVersionV3,\n} from \"../model/project_model\";\nimport { BlockFrontendStateKeyPrefixV1, SchemaVersionV1 } from \"../model/project_model_v1\";\nimport { field, isNullSignedResourceId } from \"@milaboratories/pl-client\";\nimport { cachedDeserialize } from \"@milaboratories/ts-helpers\";\nimport { allBlocks } from \"../model/project_model_util\";\n\n/**\n * Migrates the project to the latest schema version.\n *\n * @param pl - The client to use.\n * @param rid - The resource id of the project.\n */\nexport async function applyProjectMigrations(pl: PlClient, rid: SignedResourceId) {\n await pl.withWriteTx(\"ProjectMigration\", async (tx) => {\n let schemaVersion = await tx.getKValueJson<string>(rid, SchemaVersionKey);\n if (schemaVersion === SchemaVersionCurrent) return;\n\n // Apply migrations in sequence\n if (schemaVersion === SchemaVersionV1) {\n await migrateV1ToV2(tx, rid);\n schemaVersion = SchemaVersionV2;\n }\n\n if (schemaVersion === SchemaVersionV2) {\n await migrateV2ToV3(tx, rid);\n schemaVersion = SchemaVersionV3;\n }\n\n if (schemaVersion === SchemaVersionV3) {\n // V3 → V4: production context chain + staging re-render.\n // The actual chain building and staging reset happens in fixProblemsAndMigrate()\n // (called from ProjectMutator.load). This migration step just bumps the schema\n // to prevent older clients from operating on the new project structure.\n schemaVersion = SchemaVersionCurrent;\n }\n\n if (schemaVersion !== SchemaVersionCurrent) {\n throw new UiError(\n `This project was created with a newer version of Platforma. Please update to the latest version to open it.`,\n );\n }\n\n tx.setKValue(rid, SchemaVersionKey, JSON.stringify(SchemaVersionCurrent));\n await tx.commit();\n });\n}\n\n/**\n * Migrates the project from schema version 1 to 2.\n *\n * Summary of changes:\n * - uiState is now stored in a field instead of a KV\n *\n * @param tx - The transaction to use.\n * @param rid - The resource id of the project.\n */\nasync function migrateV1ToV2(tx: PlTransaction, rid: SignedResourceId) {\n const [structure, allKV] = await Promise.all([\n tx.getKValueJson<ProjectStructure>(rid, ProjectStructureKey),\n tx.listKeyValues(rid),\n ]);\n const kvMap = new Map<string, Uint8Array>(allKV.map((kv) => [kv.key, kv.value]));\n for (const block of allBlocks(structure)) {\n const kvKey = BlockFrontendStateKeyPrefixV1 + block.id;\n const uiState = kvMap.get(kvKey);\n const valueJson = uiState ? cachedDeserialize(uiState) : {};\n const uiStateR = tx.createJsonGzValue(valueJson);\n const uiStateF = field(rid, projectFieldName(block.id, \"blockStorage\"));\n tx.createField(uiStateF, \"Dynamic\", uiStateR);\n tx.deleteKValue(rid, kvKey);\n }\n}\n\n/**\n * Migrates the project from schema version 2 to 3.\n *\n * Summary of changes:\n * - Introduces unified 'blockStorage' field containing { args, uiState }\n * - Adds 'currentPrerunArgs' field for staging/prerun rendering\n * - For each block:\n * 1. Read existing 'blockStorage' field (contains uiState in v2)\n * 2. Read existing 'currentArgs' field (contains args)\n * 3. Create unified state = { args: currentArgs, uiState: oldState }\n * 4. Write to new {blockId}-blockStorage field (overwrites)\n * 5. Initialize {blockId}-currentPrerunArgs (same as prodArgs for v1/v2 blocks)\n * - Note: currentArgs and prodArgs fields remain for compatibility layer\n *\n * @param tx - The transaction to use.\n * @param rid - The resource id of the project.\n */\nasync function migrateV2ToV3(tx: PlTransaction, rid: SignedResourceId) {\n const [structure, fullResourceState] = await Promise.all([\n tx.getKValueJson<ProjectStructure>(rid, ProjectStructureKey),\n tx.getResourceData(rid, true),\n ]);\n\n // Build a map of field name -> resource id for quick lookup\n const fieldMap = new Map<string, SignedResourceId>();\n for (const f of fullResourceState.fields) {\n if (!isNullSignedResourceId(f.value)) {\n fieldMap.set(f.name, f.value);\n }\n }\n\n for (const block of allBlocks(structure)) {\n // Read existing field values\n const uiStateFieldName = projectFieldName(block.id, \"uiState\" as ProjectField[\"fieldName\"]);\n const currentArgsFieldName = projectFieldName(block.id, \"currentArgs\");\n\n const uiStateRid = fieldMap.get(uiStateFieldName);\n const currentArgsRid = fieldMap.get(currentArgsFieldName);\n\n // Read field data in parallel where available\n const [uiStateData, currentArgsData] = await Promise.all([\n uiStateRid ? tx.getResourceData(uiStateRid, false) : Promise.resolve(undefined),\n currentArgsRid ? tx.getResourceData(currentArgsRid, false) : Promise.resolve(undefined),\n ]);\n\n // Extract values - in v2, 'blockStorage' contains raw uiState, not wrapped\n const uiState = uiStateData?.data ? cachedDeserialize(uiStateData.data) : {};\n const args = currentArgsData?.data ? cachedDeserialize(currentArgsData.data) : {};\n\n // Create unified state: { args, uiState }\n const unifiedState = {\n args,\n uiState,\n };\n\n const blockStorageFieldName = projectFieldName(block.id, \"blockStorage\");\n\n // Write new unified blockStorage field (overwrite existing)\n const stateR = tx.createJsonGzValue(unifiedState);\n const stateF = field(rid, blockStorageFieldName);\n tx.createField(stateF, \"Dynamic\", stateR);\n\n // Initialize currentPrerunArgs from currentArgs (for legacy blocks, prerunArgs = args)\n if (currentArgsRid) {\n const prerunArgsR = tx.createJsonGzValue(args);\n const prerunArgsF = field(rid, projectFieldName(block.id, \"currentPrerunArgs\"));\n tx.createField(prerunArgsF, \"Dynamic\", prerunArgsR);\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/mutator/project.cjs
CHANGED
|
@@ -13,7 +13,7 @@ let node_zlib = require("node:zlib");
|
|
|
13
13
|
let _milaboratories_pl_client = require("@milaboratories/pl-client");
|
|
14
14
|
let _milaboratories_pl_errors = require("@milaboratories/pl-errors");
|
|
15
15
|
let denque = require("denque");
|
|
16
|
-
denque = require_runtime.__toESM(denque);
|
|
16
|
+
denque = require_runtime.__toESM(denque, 1);
|
|
17
17
|
//#region src/mutator/project.ts
|
|
18
18
|
function cached(modIdCb, valueCb) {
|
|
19
19
|
let initialized = false;
|
|
@@ -35,6 +35,11 @@ function cached(modIdCb, valueCb) {
|
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
var BlockInfo = class {
|
|
38
|
+
id;
|
|
39
|
+
fields;
|
|
40
|
+
config;
|
|
41
|
+
source;
|
|
42
|
+
logger;
|
|
38
43
|
constructor(id, fields, config, source, logger = new _milaboratories_ts_helpers.ConsoleLoggerAdapter()) {
|
|
39
44
|
this.id = id;
|
|
40
45
|
this.fields = fields;
|
|
@@ -125,6 +130,18 @@ const NoNewBlocks = (blockId) => {
|
|
|
125
130
|
throw new Error(`No new block info for ${blockId}`);
|
|
126
131
|
};
|
|
127
132
|
var ProjectMutator = class ProjectMutator {
|
|
133
|
+
rid;
|
|
134
|
+
tx;
|
|
135
|
+
author;
|
|
136
|
+
schema;
|
|
137
|
+
lastModified;
|
|
138
|
+
meta;
|
|
139
|
+
struct;
|
|
140
|
+
renderingState;
|
|
141
|
+
blocksInLimbo;
|
|
142
|
+
blockInfos;
|
|
143
|
+
ctxExportTplHolder;
|
|
144
|
+
projectHelper;
|
|
128
145
|
/** Max number of blocks to render staging for in a single background refresh pass. */
|
|
129
146
|
static STAGING_REFRESH_MAX_BATCH = 10;
|
|
130
147
|
globalModCount = 0;
|
|
@@ -579,12 +596,12 @@ var ProjectMutator = class ProjectMutator {
|
|
|
579
596
|
const diff = (setA, setB) => new Set([...setA].filter((x) => !setB.has(x)));
|
|
580
597
|
if (fields.prodOutput?.status === "Ready" && fields.prodCtx?.status === "Ready") {
|
|
581
598
|
if (this.blocksInLimbo.has(blockId)) return require_project_model.FieldsToDuplicate;
|
|
582
|
-
return diff(require_project_model.FieldsToDuplicate, new Set([
|
|
599
|
+
return diff(require_project_model.FieldsToDuplicate, /* @__PURE__ */ new Set([
|
|
583
600
|
"prodOutputPrevious",
|
|
584
601
|
"prodCtxPrevious",
|
|
585
602
|
"prodUiCtxPrevious"
|
|
586
603
|
]));
|
|
587
|
-
} else return diff(require_project_model.FieldsToDuplicate, new Set([
|
|
604
|
+
} else return diff(require_project_model.FieldsToDuplicate, /* @__PURE__ */ new Set([
|
|
588
605
|
"prodOutput",
|
|
589
606
|
"prodCtx",
|
|
590
607
|
"prodUiCtx",
|
|
@@ -1004,7 +1021,7 @@ async function duplicateProject(tx, sourceRid, options) {
|
|
|
1004
1021
|
tx.lock(newPrj);
|
|
1005
1022
|
const ts = String(Date.now());
|
|
1006
1023
|
const kvSkipPrefixes = [require_project_model.BlockArgsAuthorKeyPrefix];
|
|
1007
|
-
const kvSkipKeys = new Set([
|
|
1024
|
+
const kvSkipKeys = /* @__PURE__ */ new Set([
|
|
1008
1025
|
require_project_model.ProjectCreatedTimestamp,
|
|
1009
1026
|
require_project_model.ProjectLastModifiedTimestamp,
|
|
1010
1027
|
require_project_model.ProjectStructureAuthorKey
|
|
@@ -1051,6 +1068,7 @@ async function withProjectAuthored(projectHelper, txOrPl, rid, author, cb, ops =
|
|
|
1051
1068
|
}
|
|
1052
1069
|
}
|
|
1053
1070
|
//#endregion
|
|
1071
|
+
exports.ProjectMutator = ProjectMutator;
|
|
1054
1072
|
exports.createProject = createProject;
|
|
1055
1073
|
exports.duplicateProject = duplicateProject;
|
|
1056
1074
|
exports.withProject = withProject;
|