@milaboratories/pl-middle-layer 1.64.36 → 1.64.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/{_@oxc-project_runtime@0.123.0/helpers → _@oxc-project_runtime@0.137.0/helpers/esm}/usingCtx.cjs +2 -2
- package/dist/_virtual/{_@oxc-project_runtime@0.123.0/helpers → _@oxc-project_runtime@0.137.0/helpers/esm}/usingCtx.js +2 -2
- package/dist/block_registry/index.cjs +11 -3
- package/dist/block_registry/index.d.ts +3 -2
- package/dist/block_registry/index.js +4 -3
- package/dist/block_registry/registry-v2-provider.cjs +1 -1
- package/dist/block_registry/registry-v2-provider.cjs.map +1 -1
- package/dist/block_registry/registry-v2-provider.d.ts.map +1 -1
- package/dist/block_registry/registry-v2-provider.js +1 -0
- package/dist/block_registry/registry-v2-provider.js.map +1 -1
- package/dist/block_registry/registry.cjs +20 -3
- package/dist/block_registry/registry.cjs.map +1 -1
- package/dist/block_registry/registry.d.ts +7 -1
- package/dist/block_registry/registry.d.ts.map +1 -1
- package/dist/block_registry/registry.js +17 -1
- package/dist/block_registry/registry.js.map +1 -1
- package/dist/block_registry/watcher.cjs +21 -2
- package/dist/block_registry/watcher.cjs.map +1 -1
- package/dist/block_registry/watcher.d.ts +1 -1
- package/dist/block_registry/watcher.d.ts.map +1 -1
- package/dist/block_registry/watcher.js +21 -3
- package/dist/block_registry/watcher.js.map +1 -1
- package/dist/block_registry/well_known_registries.cjs.map +1 -1
- package/dist/block_registry/well_known_registries.d.ts.map +1 -1
- package/dist/block_registry/well_known_registries.js.map +1 -1
- package/dist/cfg_render/executor.cjs +2 -2
- package/dist/cfg_render/executor.cjs.map +1 -1
- package/dist/cfg_render/executor.js.map +1 -1
- package/dist/cfg_render/renderer.cjs +0 -1
- package/dist/cfg_render/renderer.cjs.map +1 -1
- package/dist/cfg_render/renderer.js.map +1 -1
- package/dist/cfg_render/traverse.cjs +0 -1
- package/dist/cfg_render/traverse.cjs.map +1 -1
- package/dist/cfg_render/traverse.js.map +1 -1
- package/dist/cfg_render/util.cjs.map +1 -1
- package/dist/cfg_render/util.js.map +1 -1
- package/dist/debug/index.cjs +1 -0
- package/dist/debug/index.cjs.map +1 -1
- package/dist/debug/index.js +1 -1
- package/dist/debug/index.js.map +1 -1
- package/dist/dev_env/index.cjs +9 -1
- package/dist/dev_env/index.cjs.map +1 -1
- package/dist/dev_env/index.js +1 -1
- package/dist/dev_env/index.js.map +1 -1
- package/dist/dev_env/util.cjs +1 -1
- package/dist/dev_env/util.cjs.map +1 -1
- package/dist/dev_env/util.js.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/js_render/computable_context.cjs +8 -5
- package/dist/js_render/computable_context.cjs.map +1 -1
- package/dist/js_render/computable_context.js +5 -1
- package/dist/js_render/computable_context.js.map +1 -1
- package/dist/js_render/context.cjs +4 -1
- package/dist/js_render/context.cjs.map +1 -1
- package/dist/js_render/context.js +4 -1
- package/dist/js_render/context.js.map +1 -1
- package/dist/js_render/index.cjs +0 -1
- package/dist/js_render/index.cjs.map +1 -1
- package/dist/js_render/index.js.map +1 -1
- package/dist/js_render/service_injectors.cjs +2 -3
- package/dist/js_render/service_injectors.cjs.map +1 -1
- package/dist/js_render/service_injectors.js +1 -1
- package/dist/js_render/service_injectors.js.map +1 -1
- package/dist/middle_layer/active_cfg.cjs +0 -1
- package/dist/middle_layer/active_cfg.cjs.map +1 -1
- package/dist/middle_layer/active_cfg.js.map +1 -1
- package/dist/middle_layer/block.cjs +0 -1
- package/dist/middle_layer/block.cjs.map +1 -1
- package/dist/middle_layer/block.js.map +1 -1
- package/dist/middle_layer/block_ctx.cjs +0 -1
- package/dist/middle_layer/block_ctx.cjs.map +1 -1
- package/dist/middle_layer/block_ctx.js.map +1 -1
- package/dist/middle_layer/block_ctx_unsafe.cjs.map +1 -1
- package/dist/middle_layer/block_ctx_unsafe.js.map +1 -1
- package/dist/middle_layer/driver_kit.cjs +0 -1
- package/dist/middle_layer/driver_kit.cjs.map +1 -1
- package/dist/middle_layer/driver_kit.js.map +1 -1
- package/dist/middle_layer/frontend_path.cjs +5 -1
- package/dist/middle_layer/frontend_path.cjs.map +1 -1
- package/dist/middle_layer/frontend_path.js +6 -1
- package/dist/middle_layer/frontend_path.js.map +1 -1
- package/dist/middle_layer/index.cjs +13 -5
- package/dist/middle_layer/index.d.ts +2 -1
- package/dist/middle_layer/index.js +6 -5
- package/dist/middle_layer/middle_layer.cjs +7 -1
- package/dist/middle_layer/middle_layer.cjs.map +1 -1
- package/dist/middle_layer/middle_layer.d.ts.map +1 -1
- package/dist/middle_layer/middle_layer.js +7 -0
- package/dist/middle_layer/middle_layer.js.map +1 -1
- package/dist/middle_layer/navigation_states.cjs +0 -1
- package/dist/middle_layer/navigation_states.cjs.map +1 -1
- package/dist/middle_layer/navigation_states.js.map +1 -1
- package/dist/middle_layer/ops.cjs +1 -1
- package/dist/middle_layer/ops.cjs.map +1 -1
- package/dist/middle_layer/ops.d.ts.map +1 -1
- package/dist/middle_layer/ops.js.map +1 -1
- package/dist/middle_layer/project.cjs +9 -2
- package/dist/middle_layer/project.cjs.map +1 -1
- package/dist/middle_layer/project.d.ts.map +1 -1
- package/dist/middle_layer/project.js +5 -1
- package/dist/middle_layer/project.js.map +1 -1
- package/dist/middle_layer/project_list.cjs +2 -1
- package/dist/middle_layer/project_list.cjs.map +1 -1
- package/dist/middle_layer/project_list.js +1 -1
- package/dist/middle_layer/project_list.js.map +1 -1
- package/dist/middle_layer/project_overview.cjs +0 -1
- package/dist/middle_layer/project_overview.cjs.map +1 -1
- package/dist/middle_layer/project_overview.js.map +1 -1
- package/dist/middle_layer/project_overview_light.cjs +0 -1
- package/dist/middle_layer/project_overview_light.cjs.map +1 -1
- package/dist/middle_layer/project_overview_light.js.map +1 -1
- package/dist/middle_layer/render.cjs +0 -1
- package/dist/middle_layer/render.cjs.map +1 -1
- package/dist/middle_layer/render.js.map +1 -1
- package/dist/middle_layer/types.d.ts.map +1 -1
- package/dist/middle_layer/util.cjs +0 -1
- package/dist/middle_layer/util.cjs.map +1 -1
- package/dist/middle_layer/util.js.map +1 -1
- package/dist/model/args.cjs +1 -1
- package/dist/model/args.cjs.map +1 -1
- package/dist/model/args.js +1 -1
- package/dist/model/args.js.map +1 -1
- package/dist/model/block_pack_spec.cjs +5 -0
- package/dist/model/block_pack_spec.cjs.map +1 -1
- package/dist/model/block_pack_spec.d.ts +19 -2
- package/dist/model/block_pack_spec.d.ts.map +1 -1
- package/dist/model/block_pack_spec.js +5 -1
- package/dist/model/block_pack_spec.js.map +1 -1
- package/dist/model/frontend.d.ts.map +1 -1
- package/dist/model/index.d.ts +2 -1
- package/dist/model/project_helper.cjs +2 -1
- package/dist/model/project_helper.cjs.map +1 -1
- package/dist/model/project_helper.d.ts +1 -1
- package/dist/model/project_helper.d.ts.map +1 -1
- package/dist/model/project_helper.js +2 -0
- package/dist/model/project_helper.js.map +1 -1
- package/dist/model/project_model.cjs +2 -1
- package/dist/model/project_model.cjs.map +1 -1
- package/dist/model/project_model.d.ts.map +1 -1
- package/dist/model/project_model.js +2 -2
- package/dist/model/project_model.js.map +1 -1
- package/dist/model/project_model_util.cjs +4 -3
- package/dist/model/project_model_util.cjs.map +1 -1
- package/dist/model/project_model_util.js +4 -4
- package/dist/model/project_model_util.js.map +1 -1
- package/dist/model/template_spec.d.ts.map +1 -1
- package/dist/mutator/block-pack/block_pack.cjs +41 -4
- package/dist/mutator/block-pack/block_pack.cjs.map +1 -1
- package/dist/mutator/block-pack/block_pack.d.ts.map +1 -1
- package/dist/mutator/block-pack/block_pack.js +40 -4
- package/dist/mutator/block-pack/block_pack.js.map +1 -1
- package/dist/mutator/block-pack/frontend.cjs +5 -1
- package/dist/mutator/block-pack/frontend.cjs.map +1 -1
- package/dist/mutator/block-pack/frontend.js +6 -1
- package/dist/mutator/block-pack/frontend.js.map +1 -1
- package/dist/mutator/block-pack/required_capabilities.cjs +0 -1
- package/dist/mutator/block-pack/required_capabilities.cjs.map +1 -1
- package/dist/mutator/block-pack/required_capabilities.js.map +1 -1
- package/dist/mutator/context_export.cjs +0 -1
- package/dist/mutator/context_export.cjs.map +1 -1
- package/dist/mutator/context_export.js.map +1 -1
- package/dist/mutator/migration.cjs +0 -1
- package/dist/mutator/migration.cjs.map +1 -1
- package/dist/mutator/migration.js.map +1 -1
- package/dist/mutator/project.cjs +22 -4
- package/dist/mutator/project.cjs.map +1 -1
- package/dist/mutator/project.js +21 -4
- package/dist/mutator/project.js.map +1 -1
- package/dist/mutator/template/direct_template_loader.cjs +0 -1
- package/dist/mutator/template/direct_template_loader.cjs.map +1 -1
- package/dist/mutator/template/direct_template_loader.js.map +1 -1
- package/dist/mutator/template/direct_template_loader_v3.cjs +0 -1
- package/dist/mutator/template/direct_template_loader_v3.cjs.map +1 -1
- package/dist/mutator/template/direct_template_loader_v3.js.map +1 -1
- package/dist/mutator/template/render_block.cjs +4 -1
- package/dist/mutator/template/render_block.cjs.map +1 -1
- package/dist/mutator/template/render_block.js +1 -1
- package/dist/mutator/template/render_block.js.map +1 -1
- package/dist/mutator/template/render_template.cjs +0 -1
- package/dist/mutator/template/render_template.cjs.map +1 -1
- package/dist/mutator/template/render_template.d.ts.map +1 -1
- package/dist/mutator/template/render_template.js.map +1 -1
- package/dist/mutator/template/template_cache.cjs +6 -3
- package/dist/mutator/template/template_cache.cjs.map +1 -1
- package/dist/mutator/template/template_cache.d.ts +1 -2
- package/dist/mutator/template/template_cache.d.ts.map +1 -1
- package/dist/mutator/template/template_cache.js +6 -2
- package/dist/mutator/template/template_cache.js.map +1 -1
- package/dist/mutator/template/template_loading.cjs +1 -1
- package/dist/mutator/template/template_loading.cjs.map +1 -1
- package/dist/mutator/template/template_loading.d.ts.map +1 -1
- package/dist/mutator/template/template_loading.js.map +1 -1
- package/dist/network_check/network_check.cjs +0 -1
- package/dist/network_check/network_check.cjs.map +1 -1
- package/dist/network_check/network_check.d.ts.map +1 -1
- package/dist/network_check/network_check.js.map +1 -1
- package/dist/network_check/pings.cjs +3 -1
- package/dist/network_check/pings.cjs.map +1 -1
- package/dist/network_check/pings.js +1 -1
- package/dist/network_check/pings.js.map +1 -1
- package/dist/network_check/template.cjs +10 -3
- package/dist/network_check/template.cjs.map +1 -1
- package/dist/network_check/template.js +1 -1
- package/dist/network_check/template.js.map +1 -1
- package/dist/pool/data.cjs +12 -1
- package/dist/pool/data.cjs.map +1 -1
- package/dist/pool/data.d.ts.map +1 -1
- package/dist/pool/data.js +3 -1
- package/dist/pool/data.js.map +1 -1
- package/dist/pool/driver.cjs +8 -1
- package/dist/pool/driver.cjs.map +1 -1
- package/dist/pool/driver.d.ts.map +1 -1
- package/dist/pool/driver.js +7 -0
- package/dist/pool/driver.js.map +1 -1
- package/dist/pool/index.cjs +5 -2
- package/dist/pool/index.d.ts +2 -1
- package/dist/pool/index.js +3 -2
- package/dist/pool/p_object_collection.cjs +1 -1
- package/dist/pool/p_object_collection.cjs.map +1 -1
- package/dist/pool/p_object_collection.js.map +1 -1
- package/dist/pool/result_pool.cjs +2 -1
- package/dist/pool/result_pool.cjs.map +1 -1
- package/dist/pool/result_pool.js +2 -0
- package/dist/pool/result_pool.js.map +1 -1
- package/dist/service_factories.cjs +0 -1
- package/dist/service_factories.cjs.map +1 -1
- package/dist/service_factories.js.map +1 -1
- package/dist/worker/WorkerManager.cjs +3 -2
- package/dist/worker/WorkerManager.cjs.map +1 -1
- package/dist/worker/WorkerManager.js +2 -1
- package/dist/worker/WorkerManager.js.map +1 -1
- package/dist/worker/worker.cjs +0 -1
- package/dist/worker/worker.cjs.map +1 -1
- package/dist/worker/worker.js.map +1 -1
- package/dist/worker/workerApi.cjs +0 -1
- package/dist/worker/workerApi.cjs.map +1 -1
- package/dist/worker/workerApi.js.map +1 -1
- package/package.json +10 -10
- 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,4 +1,3 @@
|
|
|
1
|
-
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
1
|
const require_registry_v2_provider = require("../block_registry/registry-v2-provider.cjs");
|
|
3
2
|
require("../block_registry/index.cjs");
|
|
4
3
|
const require_project_model = require("../model/project_model.cjs");
|
|
@@ -35,6 +34,13 @@ let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common")
|
|
|
35
34
|
* are required.
|
|
36
35
|
* */
|
|
37
36
|
var MiddleLayer = class MiddleLayer {
|
|
37
|
+
env;
|
|
38
|
+
driverKit;
|
|
39
|
+
signer;
|
|
40
|
+
projectListResourceId;
|
|
41
|
+
openedProjectsList;
|
|
42
|
+
projectListTree;
|
|
43
|
+
blockRegistryProvider;
|
|
38
44
|
pl;
|
|
39
45
|
/** Contains a reactive list of projects along with their meta information. */
|
|
40
46
|
projectList;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middle_layer.cjs","names":["LRUCache","createProject","withProjectAuthored","ProjectMetaKey","isNotNullSignedResourceId","duplicateProject","Project","HmacSha256Signer","DefaultMiddleLayerOpsSettings","DefaultMiddleLayerOpsPaths","getDebugFlags","ProjectsField","ProjectsResourceType","initDriverKit","RetryAgent","V2RegistryProvider","BlockPackPreparer","RuntimeCapabilities","REQUIRES_PFRAMES_VERSION","createModelServiceRegistry","BlockEventDispatcher","BlockUpdateWatcher","ProjectHelper","WatchableValue","createProjectList"],"sources":["../../src/middle_layer/middle_layer.ts"],"sourcesContent":["import type { PlClient, SignedResourceId, ResourceRef } from \"@milaboratories/pl-client\";\nimport {\n field,\n isNotNullSignedResourceId,\n isNullSignedResourceId,\n resourceIdToString,\n} from \"@milaboratories/pl-client\";\nimport { LRUCache } from \"lru-cache\";\nimport { createProjectList, ProjectsField, ProjectsResourceType } from \"./project_list\";\nimport { createProject, duplicateProject, withProjectAuthored } from \"../mutator/project\";\nimport { ProjectMetaKey } from \"../model/project_model\";\nimport type { ProjectId } from \"../model/project_model\";\nimport type { SynchronizedTreeState } from \"@milaboratories/pl-tree\";\nimport { BlockPackPreparer } from \"../mutator/block-pack/block_pack\";\nimport type { MiLogger, Signer } from \"@milaboratories/ts-helpers\";\nimport { BlockEventDispatcher } from \"@milaboratories/ts-helpers\";\nimport { HmacSha256Signer } from \"@milaboratories/ts-helpers\";\nimport type { ComputableStableDefined } from \"@milaboratories/computable\";\nimport { WatchableValue } from \"@milaboratories/computable\";\nimport { Project } from \"./project\";\nimport type { MiddleLayerOps, MiddleLayerOpsConstructor } from \"./ops\";\nimport { DefaultMiddleLayerOpsPaths, DefaultMiddleLayerOpsSettings } from \"./ops\";\nimport { randomUUID } from \"node:crypto\";\nimport type { ProjectListEntry } from \"../model\";\nimport type {\n AuthorMarker,\n ProjectMeta,\n BlockPlatform,\n} from \"@milaboratories/pl-model-middle-layer\";\nimport { BlockUpdateWatcher } from \"../block_registry/watcher\";\nimport type { QuickJSWASMModule } from \"quickjs-emscripten\";\nimport { getQuickJS } from \"quickjs-emscripten\";\nimport type { MiddleLayerDriverKit } from \"./driver_kit\";\nimport { initDriverKit } from \"./driver_kit\";\nimport type { BlockCodeFeatureFlags, DriverKit, SupportedRequirement } from \"@platforma-sdk/model\";\nimport { RuntimeCapabilities } from \"@platforma-sdk/model\";\nimport {\n type ModelServiceRegistry,\n registerServiceCapabilities,\n REQUIRES_PFRAMES_VERSION,\n} from \"@milaboratories/pl-model-common\";\nimport { createModelServiceRegistry } from \"../service_factories\";\nimport type { DownloadUrlDriver } from \"@milaboratories/pl-drivers\";\nimport { V2RegistryProvider } from \"../block_registry\";\nimport type { Dispatcher } from \"undici\";\nimport { RetryAgent } from \"undici\";\nimport { getDebugFlags } from \"../debug\";\nimport { ProjectHelper } from \"../model/project_helper\";\n\nexport interface MiddleLayerEnvironment {\n dispose(): Promise<void>;\n readonly pl: PlClient;\n readonly runtimeCapabilities: RuntimeCapabilities;\n readonly logger: MiLogger;\n readonly blockEventDispatcher: BlockEventDispatcher;\n readonly httpDispatcher: Dispatcher;\n readonly retryHttpDispatcher: Dispatcher;\n readonly signer: Signer;\n readonly ops: MiddleLayerOps;\n readonly bpPreparer: BlockPackPreparer;\n readonly frontendDownloadDriver: DownloadUrlDriver;\n readonly blockUpdateWatcher: BlockUpdateWatcher;\n readonly quickJs: QuickJSWASMModule;\n readonly driverKit: MiddleLayerDriverKit;\n readonly serviceRegistry: ModelServiceRegistry;\n readonly projectHelper: ProjectHelper;\n}\n\n/**\n * Main access object to work with pl from UI.\n *\n * It implements an abstraction layer of projects and blocks.\n *\n * As a main entry point inside the pl, this object uses a resource attached\n * via the {@link ProjectsField} to the pl client's root, this resource\n * contains project list.\n *\n * Read about alternative roots, if isolated project lists (working environments)\n * are required.\n * */\nexport class MiddleLayer {\n public readonly pl: PlClient;\n\n /** Contains a reactive list of projects along with their meta information. */\n public readonly projectList: ComputableStableDefined<ProjectListEntry[]>;\n\n private constructor(\n private readonly env: MiddleLayerEnvironment,\n public readonly driverKit: DriverKit,\n public readonly signer: Signer,\n private readonly projectListResourceId: SignedResourceId,\n private readonly openedProjectsList: WatchableValue<ProjectId[]>,\n private readonly projectListTree: SynchronizedTreeState,\n public readonly blockRegistryProvider: V2RegistryProvider,\n projectList: ComputableStableDefined<ProjectListEntry[]>,\n ) {\n this.projectList = projectList;\n this.pl = this.env.pl;\n }\n\n /**\n * Get the OS where backend is running.\n * For old backend versions returns undefined.\n */\n public get serverPlatform(): BlockPlatform | undefined {\n return this.pl.serverInfo.platform as BlockPlatform | undefined;\n }\n\n /**\n * Runtime capabilities advertised by the connected backend (tokens of\n * the form `<feature>:<version>`, e.g. \"wasm:v1\"). Empty list if the\n * backend predates the capability mechanism — that's the desired\n * fail-closed behaviour for blocks declaring any `requiredCapabilities`.\n */\n public get serverCapabilities(): string[] {\n return this.pl.serverInfo.capabilities ?? [];\n }\n\n /** Adds a runtime capability to the middle layer. */\n public addRuntimeCapability(\n requirement: SupportedRequirement,\n value: number | boolean = true,\n ): void {\n this.env.runtimeCapabilities.addSupportedRequirement(requirement, value);\n }\n\n /** Checks if the given block feature flags are compatible with the runtime capabilities. */\n public checkBlockCompatibility(featureFlags: BlockCodeFeatureFlags | undefined): boolean {\n return this.env.runtimeCapabilities.checkCompatibility(featureFlags);\n }\n\n /** Returns extended API driver kit used internally by middle layer. */\n public get internalDriverKit(): MiddleLayerDriverKit {\n return this.env.driverKit;\n }\n\n /** Returns the service registry for service introspection. */\n public get serviceRegistry(): ModelServiceRegistry {\n return this.env.serviceRegistry;\n }\n\n //\n // ProjectId ↔ SignedResourceId resolution\n //\n\n private readonly projectIdCache = new LRUCache<ProjectId, SignedResourceId>({ max: 1024 });\n\n /** Resolves a ProjectId to a signed SignedResourceId.\n * Uses LRU cache with TX-scan fallback. */\n private async resolveProjectId(projectId: ProjectId): Promise<SignedResourceId> {\n const cached = this.projectIdCache.get(projectId);\n if (cached !== undefined) return cached;\n\n // Cache miss — scan project list fields to find the matching resource\n const rid = await this.pl.withReadTx(\"ResolveProjectId\", async (tx) => {\n const data = await tx.getResourceData(this.projectListResourceId, true);\n for (const f of data.fields) {\n if (isNullSignedResourceId(f.value)) continue;\n if (resourceIdToString(f.value) === (projectId as string)) return f.value;\n }\n throw new Error(`Project ${projectId} not found in project list.`);\n });\n\n this.projectIdCache.set(projectId, rid);\n return rid;\n }\n\n //\n // Project List Manipulation\n //\n\n /** Creates a project with initial state and adds it to project list. */\n public async createProject(meta: ProjectMeta): Promise<ProjectId> {\n let prj: ResourceRef;\n await this.pl.withWriteTx(\"MLCreateProject\", async (tx) => {\n prj = await createProject(tx, meta);\n tx.createField(field(this.projectListResourceId, randomUUID()), \"Dynamic\", prj);\n await tx.commit();\n });\n await this.projectListTree.refreshState();\n\n const signedRid = await prj!.globalId;\n const projectId = resourceIdToString(signedRid) as ProjectId;\n this.projectIdCache.set(projectId, signedRid);\n return projectId;\n }\n\n /** Updates project metadata */\n public async setProjectMeta(\n id: ProjectId,\n meta: ProjectMeta,\n author?: AuthorMarker,\n ): Promise<void> {\n const rid = await this.resolveProjectId(id);\n await withProjectAuthored(\n this.env.projectHelper,\n this.pl,\n rid,\n author,\n (prj) => {\n prj.setMeta(meta);\n },\n { name: \"setProjectMeta\" },\n );\n await this.projectListTree.refreshState();\n }\n\n /** Permanently deletes project from the project list, this will result in\n * destruction of all attached objects, like files, analysis results etc. */\n public async deleteProject(id: ProjectId): Promise<void> {\n await this.pl.withWriteTx(\"MLRemoveProject\", async (tx) => {\n const data = await tx.getResourceData(this.projectListResourceId, true);\n let fieldName: string | undefined;\n for (const f of data.fields) {\n if (isNullSignedResourceId(f.value)) continue;\n if (resourceIdToString(f.value) === (id as string)) {\n fieldName = f.name;\n break;\n }\n }\n if (fieldName === undefined) throw new Error(`Project ${id} not found in project list.`);\n tx.removeField(field(this.projectListResourceId, fieldName));\n await tx.commit();\n });\n this.projectIdCache.delete(id);\n await this.projectListTree.refreshState();\n }\n\n /**\n * Duplicates an existing project and adds the copy to this user's project list.\n *\n * @param srcProjectId - project id of the project to duplicate\n * @param rename - optional function that receives the source label and all existing\n * project labels (read within the same transaction), and returns the label for the copy\n */\n public async duplicateProject(\n srcProjectId: ProjectId,\n rename?: (previousLabel: string, existingLabels: string[]) => string,\n ): Promise<ProjectId> {\n const sourceRid = await this.resolveProjectId(srcProjectId);\n\n const newPrj: ResourceRef = await this.pl.withWriteTx(\"MLDuplicateProject\", async (tx) => {\n // Read source project meta\n const sourceMeta = await tx.getKValueJson<ProjectMeta>(sourceRid, ProjectMetaKey);\n\n // Read all existing project labels from the project list (parallel reads)\n const projectListData = await tx.getResourceData(this.projectListResourceId, true);\n const projectRids = projectListData.fields\n .map((f) => f.value)\n .filter(isNotNullSignedResourceId);\n const existingLabels = (\n await Promise.all(\n projectRids.map((rid) => tx.getKValueJson<ProjectMeta>(rid, ProjectMetaKey)),\n )\n ).map((m) => m.label);\n\n // Compute new label\n const newLabel = rename ? rename(sourceMeta.label, existingLabels) : sourceMeta.label;\n\n // Create the duplicate\n const newPrj = await duplicateProject(tx, sourceRid, { label: newLabel });\n\n // Attach to project list with a random UUID field name\n tx.createField(field(this.projectListResourceId, randomUUID()), \"Dynamic\", newPrj);\n await tx.commit();\n\n return newPrj;\n });\n\n await this.projectListTree.refreshState();\n\n const signedRid = await newPrj.globalId;\n const newProjectId = resourceIdToString(signedRid) as ProjectId;\n this.projectIdCache.set(newProjectId, signedRid);\n return newProjectId;\n }\n\n //\n // Projects\n //\n\n private readonly openedProjects = new Map<ProjectId, Project>();\n\n /** Opens a project, and starts corresponding project maintenance loop. */\n public async openProject(id: ProjectId): Promise<void> {\n if (this.openedProjects.has(id)) throw new Error(`Project ${id} already opened`);\n const rid = await this.resolveProjectId(id);\n this.openedProjects.set(id, await Project.init(this.env, id, rid));\n this.openedProjectsList.setValue([...this.openedProjects.keys()]);\n }\n\n /** Closes the project, and deallocate all corresponding resources. */\n public async closeProject(id: ProjectId): Promise<void> {\n const prj = this.openedProjects.get(id);\n if (prj === undefined) throw new Error(`Project ${id} not found among opened projects`);\n this.openedProjects.delete(id);\n await prj.destroy();\n this.openedProjectsList.setValue([...this.openedProjects.keys()]);\n }\n\n /** Returns a project access object for an opened project. */\n public getOpenedProject(id: ProjectId): Project {\n const prj = this.openedProjects.get(id);\n if (prj === undefined) throw new Error(`Project ${id} not found among opened projects`);\n return prj;\n }\n\n /** Returns true if project with given id is currently opened. */\n public isProjectOpened(id: ProjectId): boolean {\n return this.openedProjects.has(id);\n }\n\n /**\n * Deallocates all runtime resources consumed by this object and awaits\n * actual termination of event loops and other processes associated with\n * them.\n */\n public async close() {\n await Promise.all([...this.openedProjects.values()].map((prj) => prj.destroy()));\n // this.env.quickJs;\n await this.projectListTree.terminate();\n await this.env.dispose();\n await this.pl.close();\n }\n\n /** @deprecated */\n public async closeAndAwaitTermination() {\n await this.close();\n }\n\n /** Generates sufficiently random string to be used as local secret for the\n * middle layer */\n public static generateLocalSecret(): string {\n return HmacSha256Signer.generateSecret();\n }\n\n /** Returns a block event dispatcher, which can be used to listen to block events. */\n public get blockEventDispatcher(): BlockEventDispatcher {\n return this.env.blockEventDispatcher;\n }\n\n /** Initialize middle layer */\n public static async init(\n pl: PlClient,\n workdir: string,\n _ops: MiddleLayerOpsConstructor,\n ): Promise<MiddleLayer> {\n const ops: MiddleLayerOps = {\n ...DefaultMiddleLayerOpsSettings,\n ...DefaultMiddleLayerOpsPaths(workdir),\n ..._ops,\n };\n\n // overriding debug options from environment variables\n ops.defaultTreeOptions.logStat = getDebugFlags().logTreeStats;\n ops.debugOps.dumpInitialTreeState = getDebugFlags().dumpInitialTreeState;\n // apply MI_TREE_TRAVERSAL only when the embedder hasn't set an explicit mode\n if (\n ops.defaultTreeOptions.traversalMode === undefined &&\n getDebugFlags().treeTraversalMode !== undefined\n )\n ops.defaultTreeOptions.traversalMode = getDebugFlags().treeTraversalMode;\n\n const projects = await pl.withWriteTx(\"MLInitialization\", async (tx) => {\n const projectsField = field(tx.clientRoot, ProjectsField);\n tx.createField(projectsField, \"Dynamic\");\n const projectsFieldData = await tx.getField(projectsField);\n if (isNullSignedResourceId(projectsFieldData.value)) {\n const projects = tx.createEphemeral(ProjectsResourceType);\n tx.lock(projects);\n\n tx.setField(projectsField, projects);\n\n await tx.commit();\n\n return await projects.globalId;\n } else {\n return projectsFieldData.value;\n }\n });\n\n const logger = ops.logger;\n\n const driverKit = await initDriverKit(pl, workdir, ops.frontendDownloadPath, ops);\n\n // passed to components having no own retry logic\n const retryHttpDispatcher = new RetryAgent(pl.httpDispatcher);\n\n const v2RegistryProvider = new V2RegistryProvider(retryHttpDispatcher);\n\n const bpPreparer = new BlockPackPreparer(\n v2RegistryProvider,\n driverKit.signer,\n retryHttpDispatcher,\n );\n\n const quickJs = await getQuickJS();\n\n const runtimeCapabilities = new RuntimeCapabilities();\n // add runtime capabilities of model here\n runtimeCapabilities.addSupportedRequirement(\"requiresModelAPIVersion\", 1);\n runtimeCapabilities.addSupportedRequirement(\"requiresModelAPIVersion\", 2);\n runtimeCapabilities.addSupportedRequirement(\"requiresCreatePTable\", 2);\n runtimeCapabilities.addSupportedRequirement(\"requiresPFramesVersion\", REQUIRES_PFRAMES_VERSION);\n registerServiceCapabilities((flag, value) =>\n runtimeCapabilities.addSupportedRequirement(flag, value),\n );\n // runtime capabilities of the desktop are to be added by the desktop app / test framework\n\n const serviceRegistry = createModelServiceRegistry({ logger });\n\n const env: MiddleLayerEnvironment = {\n pl,\n blockEventDispatcher: new BlockEventDispatcher(),\n signer: driverKit.signer,\n logger,\n httpDispatcher: pl.httpDispatcher,\n retryHttpDispatcher,\n ops,\n bpPreparer,\n frontendDownloadDriver: driverKit.frontendDriver,\n driverKit,\n blockUpdateWatcher: new BlockUpdateWatcher(v2RegistryProvider, logger, {\n minDelay: ops.devBlockUpdateRecheckInterval,\n http: retryHttpDispatcher,\n preferredUpdateChannel: ops.preferredUpdateChannel,\n }),\n runtimeCapabilities,\n serviceRegistry,\n quickJs,\n projectHelper: new ProjectHelper(quickJs, logger),\n dispose: async () => {\n await serviceRegistry.dispose();\n await retryHttpDispatcher.destroy();\n await driverKit.dispose();\n },\n };\n\n const openedProjects = new WatchableValue<ProjectId[]>([]);\n const projectListTC = await createProjectList(pl, projects, openedProjects, env);\n\n return new MiddleLayer(\n env,\n driverKit,\n driverKit.signer,\n projects,\n openedProjects,\n projectListTC.tree,\n v2RegistryProvider,\n projectListTC.computable,\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"middle_layer.cjs","names":["LRUCache","createProject","withProjectAuthored","ProjectMetaKey","isNotNullSignedResourceId","duplicateProject","Project","HmacSha256Signer","DefaultMiddleLayerOpsSettings","DefaultMiddleLayerOpsPaths","getDebugFlags","ProjectsField","ProjectsResourceType","initDriverKit","RetryAgent","V2RegistryProvider","BlockPackPreparer","RuntimeCapabilities","REQUIRES_PFRAMES_VERSION","createModelServiceRegistry","BlockEventDispatcher","BlockUpdateWatcher","ProjectHelper","WatchableValue","createProjectList"],"sources":["../../src/middle_layer/middle_layer.ts"],"sourcesContent":["import type { PlClient, SignedResourceId, ResourceRef } from \"@milaboratories/pl-client\";\nimport {\n field,\n isNotNullSignedResourceId,\n isNullSignedResourceId,\n resourceIdToString,\n} from \"@milaboratories/pl-client\";\nimport { LRUCache } from \"lru-cache\";\nimport { createProjectList, ProjectsField, ProjectsResourceType } from \"./project_list\";\nimport { createProject, duplicateProject, withProjectAuthored } from \"../mutator/project\";\nimport { ProjectMetaKey } from \"../model/project_model\";\nimport type { ProjectId } from \"../model/project_model\";\nimport type { SynchronizedTreeState } from \"@milaboratories/pl-tree\";\nimport { BlockPackPreparer } from \"../mutator/block-pack/block_pack\";\nimport type { MiLogger, Signer } from \"@milaboratories/ts-helpers\";\nimport { BlockEventDispatcher } from \"@milaboratories/ts-helpers\";\nimport { HmacSha256Signer } from \"@milaboratories/ts-helpers\";\nimport type { ComputableStableDefined } from \"@milaboratories/computable\";\nimport { WatchableValue } from \"@milaboratories/computable\";\nimport { Project } from \"./project\";\nimport type { MiddleLayerOps, MiddleLayerOpsConstructor } from \"./ops\";\nimport { DefaultMiddleLayerOpsPaths, DefaultMiddleLayerOpsSettings } from \"./ops\";\nimport { randomUUID } from \"node:crypto\";\nimport type { ProjectListEntry } from \"../model\";\nimport type {\n AuthorMarker,\n ProjectMeta,\n BlockPlatform,\n} from \"@milaboratories/pl-model-middle-layer\";\nimport { BlockUpdateWatcher } from \"../block_registry/watcher\";\nimport type { QuickJSWASMModule } from \"quickjs-emscripten\";\nimport { getQuickJS } from \"quickjs-emscripten\";\nimport type { MiddleLayerDriverKit } from \"./driver_kit\";\nimport { initDriverKit } from \"./driver_kit\";\nimport type { BlockCodeFeatureFlags, DriverKit, SupportedRequirement } from \"@platforma-sdk/model\";\nimport { RuntimeCapabilities } from \"@platforma-sdk/model\";\nimport {\n type ModelServiceRegistry,\n registerServiceCapabilities,\n REQUIRES_PFRAMES_VERSION,\n} from \"@milaboratories/pl-model-common\";\nimport { createModelServiceRegistry } from \"../service_factories\";\nimport type { DownloadUrlDriver } from \"@milaboratories/pl-drivers\";\nimport { V2RegistryProvider } from \"../block_registry\";\nimport type { Dispatcher } from \"undici\";\nimport { RetryAgent } from \"undici\";\nimport { getDebugFlags } from \"../debug\";\nimport { ProjectHelper } from \"../model/project_helper\";\n\nexport interface MiddleLayerEnvironment {\n dispose(): Promise<void>;\n readonly pl: PlClient;\n readonly runtimeCapabilities: RuntimeCapabilities;\n readonly logger: MiLogger;\n readonly blockEventDispatcher: BlockEventDispatcher;\n readonly httpDispatcher: Dispatcher;\n readonly retryHttpDispatcher: Dispatcher;\n readonly signer: Signer;\n readonly ops: MiddleLayerOps;\n readonly bpPreparer: BlockPackPreparer;\n readonly frontendDownloadDriver: DownloadUrlDriver;\n readonly blockUpdateWatcher: BlockUpdateWatcher;\n readonly quickJs: QuickJSWASMModule;\n readonly driverKit: MiddleLayerDriverKit;\n readonly serviceRegistry: ModelServiceRegistry;\n readonly projectHelper: ProjectHelper;\n}\n\n/**\n * Main access object to work with pl from UI.\n *\n * It implements an abstraction layer of projects and blocks.\n *\n * As a main entry point inside the pl, this object uses a resource attached\n * via the {@link ProjectsField} to the pl client's root, this resource\n * contains project list.\n *\n * Read about alternative roots, if isolated project lists (working environments)\n * are required.\n * */\nexport class MiddleLayer {\n public readonly pl: PlClient;\n\n /** Contains a reactive list of projects along with their meta information. */\n public readonly projectList: ComputableStableDefined<ProjectListEntry[]>;\n\n private constructor(\n private readonly env: MiddleLayerEnvironment,\n public readonly driverKit: DriverKit,\n public readonly signer: Signer,\n private readonly projectListResourceId: SignedResourceId,\n private readonly openedProjectsList: WatchableValue<ProjectId[]>,\n private readonly projectListTree: SynchronizedTreeState,\n public readonly blockRegistryProvider: V2RegistryProvider,\n projectList: ComputableStableDefined<ProjectListEntry[]>,\n ) {\n this.projectList = projectList;\n this.pl = this.env.pl;\n }\n\n /**\n * Get the OS where backend is running.\n * For old backend versions returns undefined.\n */\n public get serverPlatform(): BlockPlatform | undefined {\n return this.pl.serverInfo.platform as BlockPlatform | undefined;\n }\n\n /**\n * Runtime capabilities advertised by the connected backend (tokens of\n * the form `<feature>:<version>`, e.g. \"wasm:v1\"). Empty list if the\n * backend predates the capability mechanism — that's the desired\n * fail-closed behaviour for blocks declaring any `requiredCapabilities`.\n */\n public get serverCapabilities(): string[] {\n return this.pl.serverInfo.capabilities ?? [];\n }\n\n /** Adds a runtime capability to the middle layer. */\n public addRuntimeCapability(\n requirement: SupportedRequirement,\n value: number | boolean = true,\n ): void {\n this.env.runtimeCapabilities.addSupportedRequirement(requirement, value);\n }\n\n /** Checks if the given block feature flags are compatible with the runtime capabilities. */\n public checkBlockCompatibility(featureFlags: BlockCodeFeatureFlags | undefined): boolean {\n return this.env.runtimeCapabilities.checkCompatibility(featureFlags);\n }\n\n /** Returns extended API driver kit used internally by middle layer. */\n public get internalDriverKit(): MiddleLayerDriverKit {\n return this.env.driverKit;\n }\n\n /** Returns the service registry for service introspection. */\n public get serviceRegistry(): ModelServiceRegistry {\n return this.env.serviceRegistry;\n }\n\n //\n // ProjectId ↔ SignedResourceId resolution\n //\n\n private readonly projectIdCache = new LRUCache<ProjectId, SignedResourceId>({ max: 1024 });\n\n /** Resolves a ProjectId to a signed SignedResourceId.\n * Uses LRU cache with TX-scan fallback. */\n private async resolveProjectId(projectId: ProjectId): Promise<SignedResourceId> {\n const cached = this.projectIdCache.get(projectId);\n if (cached !== undefined) return cached;\n\n // Cache miss — scan project list fields to find the matching resource\n const rid = await this.pl.withReadTx(\"ResolveProjectId\", async (tx) => {\n const data = await tx.getResourceData(this.projectListResourceId, true);\n for (const f of data.fields) {\n if (isNullSignedResourceId(f.value)) continue;\n if (resourceIdToString(f.value) === (projectId as string)) return f.value;\n }\n throw new Error(`Project ${projectId} not found in project list.`);\n });\n\n this.projectIdCache.set(projectId, rid);\n return rid;\n }\n\n //\n // Project List Manipulation\n //\n\n /** Creates a project with initial state and adds it to project list. */\n public async createProject(meta: ProjectMeta): Promise<ProjectId> {\n let prj: ResourceRef;\n await this.pl.withWriteTx(\"MLCreateProject\", async (tx) => {\n prj = await createProject(tx, meta);\n tx.createField(field(this.projectListResourceId, randomUUID()), \"Dynamic\", prj);\n await tx.commit();\n });\n await this.projectListTree.refreshState();\n\n const signedRid = await prj!.globalId;\n const projectId = resourceIdToString(signedRid) as ProjectId;\n this.projectIdCache.set(projectId, signedRid);\n return projectId;\n }\n\n /** Updates project metadata */\n public async setProjectMeta(\n id: ProjectId,\n meta: ProjectMeta,\n author?: AuthorMarker,\n ): Promise<void> {\n const rid = await this.resolveProjectId(id);\n await withProjectAuthored(\n this.env.projectHelper,\n this.pl,\n rid,\n author,\n (prj) => {\n prj.setMeta(meta);\n },\n { name: \"setProjectMeta\" },\n );\n await this.projectListTree.refreshState();\n }\n\n /** Permanently deletes project from the project list, this will result in\n * destruction of all attached objects, like files, analysis results etc. */\n public async deleteProject(id: ProjectId): Promise<void> {\n await this.pl.withWriteTx(\"MLRemoveProject\", async (tx) => {\n const data = await tx.getResourceData(this.projectListResourceId, true);\n let fieldName: string | undefined;\n for (const f of data.fields) {\n if (isNullSignedResourceId(f.value)) continue;\n if (resourceIdToString(f.value) === (id as string)) {\n fieldName = f.name;\n break;\n }\n }\n if (fieldName === undefined) throw new Error(`Project ${id} not found in project list.`);\n tx.removeField(field(this.projectListResourceId, fieldName));\n await tx.commit();\n });\n this.projectIdCache.delete(id);\n await this.projectListTree.refreshState();\n }\n\n /**\n * Duplicates an existing project and adds the copy to this user's project list.\n *\n * @param srcProjectId - project id of the project to duplicate\n * @param rename - optional function that receives the source label and all existing\n * project labels (read within the same transaction), and returns the label for the copy\n */\n public async duplicateProject(\n srcProjectId: ProjectId,\n rename?: (previousLabel: string, existingLabels: string[]) => string,\n ): Promise<ProjectId> {\n const sourceRid = await this.resolveProjectId(srcProjectId);\n\n const newPrj: ResourceRef = await this.pl.withWriteTx(\"MLDuplicateProject\", async (tx) => {\n // Read source project meta\n const sourceMeta = await tx.getKValueJson<ProjectMeta>(sourceRid, ProjectMetaKey);\n\n // Read all existing project labels from the project list (parallel reads)\n const projectListData = await tx.getResourceData(this.projectListResourceId, true);\n const projectRids = projectListData.fields\n .map((f) => f.value)\n .filter(isNotNullSignedResourceId);\n const existingLabels = (\n await Promise.all(\n projectRids.map((rid) => tx.getKValueJson<ProjectMeta>(rid, ProjectMetaKey)),\n )\n ).map((m) => m.label);\n\n // Compute new label\n const newLabel = rename ? rename(sourceMeta.label, existingLabels) : sourceMeta.label;\n\n // Create the duplicate\n const newPrj = await duplicateProject(tx, sourceRid, { label: newLabel });\n\n // Attach to project list with a random UUID field name\n tx.createField(field(this.projectListResourceId, randomUUID()), \"Dynamic\", newPrj);\n await tx.commit();\n\n return newPrj;\n });\n\n await this.projectListTree.refreshState();\n\n const signedRid = await newPrj.globalId;\n const newProjectId = resourceIdToString(signedRid) as ProjectId;\n this.projectIdCache.set(newProjectId, signedRid);\n return newProjectId;\n }\n\n //\n // Projects\n //\n\n private readonly openedProjects = new Map<ProjectId, Project>();\n\n /** Opens a project, and starts corresponding project maintenance loop. */\n public async openProject(id: ProjectId): Promise<void> {\n if (this.openedProjects.has(id)) throw new Error(`Project ${id} already opened`);\n const rid = await this.resolveProjectId(id);\n this.openedProjects.set(id, await Project.init(this.env, id, rid));\n this.openedProjectsList.setValue([...this.openedProjects.keys()]);\n }\n\n /** Closes the project, and deallocate all corresponding resources. */\n public async closeProject(id: ProjectId): Promise<void> {\n const prj = this.openedProjects.get(id);\n if (prj === undefined) throw new Error(`Project ${id} not found among opened projects`);\n this.openedProjects.delete(id);\n await prj.destroy();\n this.openedProjectsList.setValue([...this.openedProjects.keys()]);\n }\n\n /** Returns a project access object for an opened project. */\n public getOpenedProject(id: ProjectId): Project {\n const prj = this.openedProjects.get(id);\n if (prj === undefined) throw new Error(`Project ${id} not found among opened projects`);\n return prj;\n }\n\n /** Returns true if project with given id is currently opened. */\n public isProjectOpened(id: ProjectId): boolean {\n return this.openedProjects.has(id);\n }\n\n /**\n * Deallocates all runtime resources consumed by this object and awaits\n * actual termination of event loops and other processes associated with\n * them.\n */\n public async close() {\n await Promise.all([...this.openedProjects.values()].map((prj) => prj.destroy()));\n // this.env.quickJs;\n await this.projectListTree.terminate();\n await this.env.dispose();\n await this.pl.close();\n }\n\n /** @deprecated */\n public async closeAndAwaitTermination() {\n await this.close();\n }\n\n /** Generates sufficiently random string to be used as local secret for the\n * middle layer */\n public static generateLocalSecret(): string {\n return HmacSha256Signer.generateSecret();\n }\n\n /** Returns a block event dispatcher, which can be used to listen to block events. */\n public get blockEventDispatcher(): BlockEventDispatcher {\n return this.env.blockEventDispatcher;\n }\n\n /** Initialize middle layer */\n public static async init(\n pl: PlClient,\n workdir: string,\n _ops: MiddleLayerOpsConstructor,\n ): Promise<MiddleLayer> {\n const ops: MiddleLayerOps = {\n ...DefaultMiddleLayerOpsSettings,\n ...DefaultMiddleLayerOpsPaths(workdir),\n ..._ops,\n };\n\n // overriding debug options from environment variables\n ops.defaultTreeOptions.logStat = getDebugFlags().logTreeStats;\n ops.debugOps.dumpInitialTreeState = getDebugFlags().dumpInitialTreeState;\n // apply MI_TREE_TRAVERSAL only when the embedder hasn't set an explicit mode\n if (\n ops.defaultTreeOptions.traversalMode === undefined &&\n getDebugFlags().treeTraversalMode !== undefined\n )\n ops.defaultTreeOptions.traversalMode = getDebugFlags().treeTraversalMode;\n\n const projects = await pl.withWriteTx(\"MLInitialization\", async (tx) => {\n const projectsField = field(tx.clientRoot, ProjectsField);\n tx.createField(projectsField, \"Dynamic\");\n const projectsFieldData = await tx.getField(projectsField);\n if (isNullSignedResourceId(projectsFieldData.value)) {\n const projects = tx.createEphemeral(ProjectsResourceType);\n tx.lock(projects);\n\n tx.setField(projectsField, projects);\n\n await tx.commit();\n\n return await projects.globalId;\n } else {\n return projectsFieldData.value;\n }\n });\n\n const logger = ops.logger;\n\n const driverKit = await initDriverKit(pl, workdir, ops.frontendDownloadPath, ops);\n\n // passed to components having no own retry logic\n const retryHttpDispatcher = new RetryAgent(pl.httpDispatcher);\n\n const v2RegistryProvider = new V2RegistryProvider(retryHttpDispatcher);\n\n const bpPreparer = new BlockPackPreparer(\n v2RegistryProvider,\n driverKit.signer,\n retryHttpDispatcher,\n );\n\n const quickJs = await getQuickJS();\n\n const runtimeCapabilities = new RuntimeCapabilities();\n // add runtime capabilities of model here\n runtimeCapabilities.addSupportedRequirement(\"requiresModelAPIVersion\", 1);\n runtimeCapabilities.addSupportedRequirement(\"requiresModelAPIVersion\", 2);\n runtimeCapabilities.addSupportedRequirement(\"requiresCreatePTable\", 2);\n runtimeCapabilities.addSupportedRequirement(\"requiresPFramesVersion\", REQUIRES_PFRAMES_VERSION);\n registerServiceCapabilities((flag, value) =>\n runtimeCapabilities.addSupportedRequirement(flag, value),\n );\n // runtime capabilities of the desktop are to be added by the desktop app / test framework\n\n const serviceRegistry = createModelServiceRegistry({ logger });\n\n const env: MiddleLayerEnvironment = {\n pl,\n blockEventDispatcher: new BlockEventDispatcher(),\n signer: driverKit.signer,\n logger,\n httpDispatcher: pl.httpDispatcher,\n retryHttpDispatcher,\n ops,\n bpPreparer,\n frontendDownloadDriver: driverKit.frontendDriver,\n driverKit,\n blockUpdateWatcher: new BlockUpdateWatcher(v2RegistryProvider, logger, {\n minDelay: ops.devBlockUpdateRecheckInterval,\n http: retryHttpDispatcher,\n preferredUpdateChannel: ops.preferredUpdateChannel,\n }),\n runtimeCapabilities,\n serviceRegistry,\n quickJs,\n projectHelper: new ProjectHelper(quickJs, logger),\n dispose: async () => {\n await serviceRegistry.dispose();\n await retryHttpDispatcher.destroy();\n await driverKit.dispose();\n },\n };\n\n const openedProjects = new WatchableValue<ProjectId[]>([]);\n const projectListTC = await createProjectList(pl, projects, openedProjects, env);\n\n return new MiddleLayer(\n env,\n driverKit,\n driverKit.signer,\n projects,\n openedProjects,\n projectListTC.tree,\n v2RegistryProvider,\n projectListTC.computable,\n );\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middle_layer.d.ts","names":[],"sources":["../../src/middle_layer/middle_layer.ts"],"mappings":";;;;;;;;;;;;;;;;;;;UAiDiB,sBAAA;EACf,OAAA,IAAW,OAAA;EAAA,SACF,EAAA,EAAI,QAAA;EAAA,SACJ,mBAAA,EAAqB,mBAAA;EAAA,SACrB,MAAA,EAAQ,QAAA;EAAA,SACR,oBAAA,EAAsB,oBAAA;EAAA,SACtB,cAAA,EAAgB,UAAA;EAAA,SAChB,mBAAA,EAAqB,UAAA;EAAA,SACrB,MAAA,EAAQ,MAAA;EAAA,SACR,GAAA,EAAK,cAAA;EAAA,SACL,UAAA,EAAY,iBAAA;EAAA,SACZ,sBAAA,EAAwB,iBAAA;EAAA,SACxB,kBAAA,EAAoB,kBAAA;EAAA,SACpB,OAAA,EAAS,iBAAA;EAAA,SACT,SAAA,EAAW,oBAAA;EAAA,SACX,eAAA,EAAiB,oBAAA;EAAA,SACjB,aAAA,EAAe,aAAA;AAAA;;;;;;;;;;;;;cAeb,WAAA;EAAA,iBAOQ,GAAA;EAAA,SACD,SAAA,EAAW,SAAA;EAAA,SACX,MAAA,EAAQ,MAAA;EAAA,iBACP,qBAAA;EAAA,iBACA,kBAAA;EAAA,iBACA,eAAA;EAAA,SACD,qBAAA,EAAuB,kBAAA;EAAA,SAZzB,EAAA,EAAI,QAAA;EAvBN;EAAA,SA0BE,WAAA,EAAa,uBAAA,CAAwB,kBAAA;EAAA,QAE9C,WAAA
|
|
1
|
+
{"version":3,"file":"middle_layer.d.ts","names":[],"sources":["../../src/middle_layer/middle_layer.ts"],"mappings":";;;;;;;;;;;;;;;;;;;UAiDiB,sBAAA;EACf,OAAA,IAAW,OAAA;EAAA,SACF,EAAA,EAAI,QAAA;EAAA,SACJ,mBAAA,EAAqB,mBAAA;EAAA,SACrB,MAAA,EAAQ,QAAA;EAAA,SACR,oBAAA,EAAsB,oBAAA;EAAA,SACtB,cAAA,EAAgB,UAAA;EAAA,SAChB,mBAAA,EAAqB,UAAA;EAAA,SACrB,MAAA,EAAQ,MAAA;EAAA,SACR,GAAA,EAAK,cAAA;EAAA,SACL,UAAA,EAAY,iBAAA;EAAA,SACZ,sBAAA,EAAwB,iBAAA;EAAA,SACxB,kBAAA,EAAoB,kBAAA;EAAA,SACpB,OAAA,EAAS,iBAAA;EAAA,SACT,SAAA,EAAW,oBAAA;EAAA,SACX,eAAA,EAAiB,oBAAA;EAAA,SACjB,aAAA,EAAe,aAAA;AAAA;;;;;;;;;;;;;cAeb,WAAA;EAAA,iBAOQ,GAAA;EAAA,SACD,SAAA,EAAW,SAAA;EAAA,SACX,MAAA,EAAQ,MAAA;EAAA,iBACP,qBAAA;EAAA,iBACA,kBAAA;EAAA,iBACA,eAAA;EAAA,SACD,qBAAA,EAAuB,kBAAA;EAAA,SAZzB,EAAA,EAAI,QAAA;EAvBN;EAAA,SA0BE,WAAA,EAAa,uBAAA,CAAwB,kBAAA;EAAA,QAE9C,WAAA;EA1BE;;;;EAAA,IA4CE,cAAA,IAAkB,aAAA;EA1CX;;;;;;EAAA,IAoDP,kBAAA;EAjD0B;EAsD9B,oBAAA,CACL,WAAA,EAAa,oBAAA,EACb,KAAA;EAzCS;EA+CJ,uBAAA,CAAwB,YAAA,EAAc,qBAAA;;MAKlC,iBAAA,IAAqB,oBAAA;EA3CN;EAAA,IAgDf,eAAA,IAAmB,oBAAA;EAAA,iBAQb,cAAA;EA7DoC;;EAAA,QAiEvC,gBAAA;EA7BC;EAoDF,aAAA,CAAc,IAAA,EAAM,WAAA,GAAc,OAAA,CAAQ,SAAA;EAxCvB;EAwDnB,cAAA,CACX,EAAA,EAAI,SAAA,EACJ,IAAA,EAAM,WAAA,EACN,MAAA,GAAS,YAAA,GACR,OAAA;EApB8B;;EAqCpB,aAAA,CAAc,EAAA,EAAI,SAAA,GAAY,OAAA;EApBrC;;;;;;;EA8CO,gBAAA,CACX,YAAA,EAAc,SAAA,EACd,MAAA,IAAU,aAAA,UAAuB,cAAA,wBAChC,OAAA,CAAQ,SAAA;EAAA,iBA2CM,cAAA;EAGY;EAAhB,WAAA,CAAY,EAAA,EAAI,SAAA,GAAY,OAAA;EAQX;EAAjB,YAAA,CAAa,EAAA,EAAI,SAAA,GAAY,OAAA;EASd;EAArB,gBAAA,CAAiB,EAAA,EAAI,SAAA,GAAY,OAAA;EAOb;EAApB,eAAA,CAAgB,EAAA,EAAI,SAAA;EAkBU;;;;;EATxB,KAAA,IAAK,OAAA;EA6BR;EApBG,wBAAA,IAAwB,OAAA;EA/OlB;;EAAA,OAqPL,mBAAA;EAnPI;EAAA,IAwPP,oBAAA,IAAwB,oBAAA;EAvPhB;EAAA,OA4PC,IAAA,CAClB,EAAA,EAAI,QAAA,EACJ,OAAA,UACA,IAAA,EAAM,yBAAA,GACL,OAAA,CAAQ,WAAA;AAAA"}
|
|
@@ -34,6 +34,13 @@ import { REQUIRES_PFRAMES_VERSION, registerServiceCapabilities } from "@milabora
|
|
|
34
34
|
* are required.
|
|
35
35
|
* */
|
|
36
36
|
var MiddleLayer = class MiddleLayer {
|
|
37
|
+
env;
|
|
38
|
+
driverKit;
|
|
39
|
+
signer;
|
|
40
|
+
projectListResourceId;
|
|
41
|
+
openedProjectsList;
|
|
42
|
+
projectListTree;
|
|
43
|
+
blockRegistryProvider;
|
|
37
44
|
pl;
|
|
38
45
|
/** Contains a reactive list of projects along with their meta information. */
|
|
39
46
|
projectList;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middle_layer.js","names":[],"sources":["../../src/middle_layer/middle_layer.ts"],"sourcesContent":["import type { PlClient, SignedResourceId, ResourceRef } from \"@milaboratories/pl-client\";\nimport {\n field,\n isNotNullSignedResourceId,\n isNullSignedResourceId,\n resourceIdToString,\n} from \"@milaboratories/pl-client\";\nimport { LRUCache } from \"lru-cache\";\nimport { createProjectList, ProjectsField, ProjectsResourceType } from \"./project_list\";\nimport { createProject, duplicateProject, withProjectAuthored } from \"../mutator/project\";\nimport { ProjectMetaKey } from \"../model/project_model\";\nimport type { ProjectId } from \"../model/project_model\";\nimport type { SynchronizedTreeState } from \"@milaboratories/pl-tree\";\nimport { BlockPackPreparer } from \"../mutator/block-pack/block_pack\";\nimport type { MiLogger, Signer } from \"@milaboratories/ts-helpers\";\nimport { BlockEventDispatcher } from \"@milaboratories/ts-helpers\";\nimport { HmacSha256Signer } from \"@milaboratories/ts-helpers\";\nimport type { ComputableStableDefined } from \"@milaboratories/computable\";\nimport { WatchableValue } from \"@milaboratories/computable\";\nimport { Project } from \"./project\";\nimport type { MiddleLayerOps, MiddleLayerOpsConstructor } from \"./ops\";\nimport { DefaultMiddleLayerOpsPaths, DefaultMiddleLayerOpsSettings } from \"./ops\";\nimport { randomUUID } from \"node:crypto\";\nimport type { ProjectListEntry } from \"../model\";\nimport type {\n AuthorMarker,\n ProjectMeta,\n BlockPlatform,\n} from \"@milaboratories/pl-model-middle-layer\";\nimport { BlockUpdateWatcher } from \"../block_registry/watcher\";\nimport type { QuickJSWASMModule } from \"quickjs-emscripten\";\nimport { getQuickJS } from \"quickjs-emscripten\";\nimport type { MiddleLayerDriverKit } from \"./driver_kit\";\nimport { initDriverKit } from \"./driver_kit\";\nimport type { BlockCodeFeatureFlags, DriverKit, SupportedRequirement } from \"@platforma-sdk/model\";\nimport { RuntimeCapabilities } from \"@platforma-sdk/model\";\nimport {\n type ModelServiceRegistry,\n registerServiceCapabilities,\n REQUIRES_PFRAMES_VERSION,\n} from \"@milaboratories/pl-model-common\";\nimport { createModelServiceRegistry } from \"../service_factories\";\nimport type { DownloadUrlDriver } from \"@milaboratories/pl-drivers\";\nimport { V2RegistryProvider } from \"../block_registry\";\nimport type { Dispatcher } from \"undici\";\nimport { RetryAgent } from \"undici\";\nimport { getDebugFlags } from \"../debug\";\nimport { ProjectHelper } from \"../model/project_helper\";\n\nexport interface MiddleLayerEnvironment {\n dispose(): Promise<void>;\n readonly pl: PlClient;\n readonly runtimeCapabilities: RuntimeCapabilities;\n readonly logger: MiLogger;\n readonly blockEventDispatcher: BlockEventDispatcher;\n readonly httpDispatcher: Dispatcher;\n readonly retryHttpDispatcher: Dispatcher;\n readonly signer: Signer;\n readonly ops: MiddleLayerOps;\n readonly bpPreparer: BlockPackPreparer;\n readonly frontendDownloadDriver: DownloadUrlDriver;\n readonly blockUpdateWatcher: BlockUpdateWatcher;\n readonly quickJs: QuickJSWASMModule;\n readonly driverKit: MiddleLayerDriverKit;\n readonly serviceRegistry: ModelServiceRegistry;\n readonly projectHelper: ProjectHelper;\n}\n\n/**\n * Main access object to work with pl from UI.\n *\n * It implements an abstraction layer of projects and blocks.\n *\n * As a main entry point inside the pl, this object uses a resource attached\n * via the {@link ProjectsField} to the pl client's root, this resource\n * contains project list.\n *\n * Read about alternative roots, if isolated project lists (working environments)\n * are required.\n * */\nexport class MiddleLayer {\n public readonly pl: PlClient;\n\n /** Contains a reactive list of projects along with their meta information. */\n public readonly projectList: ComputableStableDefined<ProjectListEntry[]>;\n\n private constructor(\n private readonly env: MiddleLayerEnvironment,\n public readonly driverKit: DriverKit,\n public readonly signer: Signer,\n private readonly projectListResourceId: SignedResourceId,\n private readonly openedProjectsList: WatchableValue<ProjectId[]>,\n private readonly projectListTree: SynchronizedTreeState,\n public readonly blockRegistryProvider: V2RegistryProvider,\n projectList: ComputableStableDefined<ProjectListEntry[]>,\n ) {\n this.projectList = projectList;\n this.pl = this.env.pl;\n }\n\n /**\n * Get the OS where backend is running.\n * For old backend versions returns undefined.\n */\n public get serverPlatform(): BlockPlatform | undefined {\n return this.pl.serverInfo.platform as BlockPlatform | undefined;\n }\n\n /**\n * Runtime capabilities advertised by the connected backend (tokens of\n * the form `<feature>:<version>`, e.g. \"wasm:v1\"). Empty list if the\n * backend predates the capability mechanism — that's the desired\n * fail-closed behaviour for blocks declaring any `requiredCapabilities`.\n */\n public get serverCapabilities(): string[] {\n return this.pl.serverInfo.capabilities ?? [];\n }\n\n /** Adds a runtime capability to the middle layer. */\n public addRuntimeCapability(\n requirement: SupportedRequirement,\n value: number | boolean = true,\n ): void {\n this.env.runtimeCapabilities.addSupportedRequirement(requirement, value);\n }\n\n /** Checks if the given block feature flags are compatible with the runtime capabilities. */\n public checkBlockCompatibility(featureFlags: BlockCodeFeatureFlags | undefined): boolean {\n return this.env.runtimeCapabilities.checkCompatibility(featureFlags);\n }\n\n /** Returns extended API driver kit used internally by middle layer. */\n public get internalDriverKit(): MiddleLayerDriverKit {\n return this.env.driverKit;\n }\n\n /** Returns the service registry for service introspection. */\n public get serviceRegistry(): ModelServiceRegistry {\n return this.env.serviceRegistry;\n }\n\n //\n // ProjectId ↔ SignedResourceId resolution\n //\n\n private readonly projectIdCache = new LRUCache<ProjectId, SignedResourceId>({ max: 1024 });\n\n /** Resolves a ProjectId to a signed SignedResourceId.\n * Uses LRU cache with TX-scan fallback. */\n private async resolveProjectId(projectId: ProjectId): Promise<SignedResourceId> {\n const cached = this.projectIdCache.get(projectId);\n if (cached !== undefined) return cached;\n\n // Cache miss — scan project list fields to find the matching resource\n const rid = await this.pl.withReadTx(\"ResolveProjectId\", async (tx) => {\n const data = await tx.getResourceData(this.projectListResourceId, true);\n for (const f of data.fields) {\n if (isNullSignedResourceId(f.value)) continue;\n if (resourceIdToString(f.value) === (projectId as string)) return f.value;\n }\n throw new Error(`Project ${projectId} not found in project list.`);\n });\n\n this.projectIdCache.set(projectId, rid);\n return rid;\n }\n\n //\n // Project List Manipulation\n //\n\n /** Creates a project with initial state and adds it to project list. */\n public async createProject(meta: ProjectMeta): Promise<ProjectId> {\n let prj: ResourceRef;\n await this.pl.withWriteTx(\"MLCreateProject\", async (tx) => {\n prj = await createProject(tx, meta);\n tx.createField(field(this.projectListResourceId, randomUUID()), \"Dynamic\", prj);\n await tx.commit();\n });\n await this.projectListTree.refreshState();\n\n const signedRid = await prj!.globalId;\n const projectId = resourceIdToString(signedRid) as ProjectId;\n this.projectIdCache.set(projectId, signedRid);\n return projectId;\n }\n\n /** Updates project metadata */\n public async setProjectMeta(\n id: ProjectId,\n meta: ProjectMeta,\n author?: AuthorMarker,\n ): Promise<void> {\n const rid = await this.resolveProjectId(id);\n await withProjectAuthored(\n this.env.projectHelper,\n this.pl,\n rid,\n author,\n (prj) => {\n prj.setMeta(meta);\n },\n { name: \"setProjectMeta\" },\n );\n await this.projectListTree.refreshState();\n }\n\n /** Permanently deletes project from the project list, this will result in\n * destruction of all attached objects, like files, analysis results etc. */\n public async deleteProject(id: ProjectId): Promise<void> {\n await this.pl.withWriteTx(\"MLRemoveProject\", async (tx) => {\n const data = await tx.getResourceData(this.projectListResourceId, true);\n let fieldName: string | undefined;\n for (const f of data.fields) {\n if (isNullSignedResourceId(f.value)) continue;\n if (resourceIdToString(f.value) === (id as string)) {\n fieldName = f.name;\n break;\n }\n }\n if (fieldName === undefined) throw new Error(`Project ${id} not found in project list.`);\n tx.removeField(field(this.projectListResourceId, fieldName));\n await tx.commit();\n });\n this.projectIdCache.delete(id);\n await this.projectListTree.refreshState();\n }\n\n /**\n * Duplicates an existing project and adds the copy to this user's project list.\n *\n * @param srcProjectId - project id of the project to duplicate\n * @param rename - optional function that receives the source label and all existing\n * project labels (read within the same transaction), and returns the label for the copy\n */\n public async duplicateProject(\n srcProjectId: ProjectId,\n rename?: (previousLabel: string, existingLabels: string[]) => string,\n ): Promise<ProjectId> {\n const sourceRid = await this.resolveProjectId(srcProjectId);\n\n const newPrj: ResourceRef = await this.pl.withWriteTx(\"MLDuplicateProject\", async (tx) => {\n // Read source project meta\n const sourceMeta = await tx.getKValueJson<ProjectMeta>(sourceRid, ProjectMetaKey);\n\n // Read all existing project labels from the project list (parallel reads)\n const projectListData = await tx.getResourceData(this.projectListResourceId, true);\n const projectRids = projectListData.fields\n .map((f) => f.value)\n .filter(isNotNullSignedResourceId);\n const existingLabels = (\n await Promise.all(\n projectRids.map((rid) => tx.getKValueJson<ProjectMeta>(rid, ProjectMetaKey)),\n )\n ).map((m) => m.label);\n\n // Compute new label\n const newLabel = rename ? rename(sourceMeta.label, existingLabels) : sourceMeta.label;\n\n // Create the duplicate\n const newPrj = await duplicateProject(tx, sourceRid, { label: newLabel });\n\n // Attach to project list with a random UUID field name\n tx.createField(field(this.projectListResourceId, randomUUID()), \"Dynamic\", newPrj);\n await tx.commit();\n\n return newPrj;\n });\n\n await this.projectListTree.refreshState();\n\n const signedRid = await newPrj.globalId;\n const newProjectId = resourceIdToString(signedRid) as ProjectId;\n this.projectIdCache.set(newProjectId, signedRid);\n return newProjectId;\n }\n\n //\n // Projects\n //\n\n private readonly openedProjects = new Map<ProjectId, Project>();\n\n /** Opens a project, and starts corresponding project maintenance loop. */\n public async openProject(id: ProjectId): Promise<void> {\n if (this.openedProjects.has(id)) throw new Error(`Project ${id} already opened`);\n const rid = await this.resolveProjectId(id);\n this.openedProjects.set(id, await Project.init(this.env, id, rid));\n this.openedProjectsList.setValue([...this.openedProjects.keys()]);\n }\n\n /** Closes the project, and deallocate all corresponding resources. */\n public async closeProject(id: ProjectId): Promise<void> {\n const prj = this.openedProjects.get(id);\n if (prj === undefined) throw new Error(`Project ${id} not found among opened projects`);\n this.openedProjects.delete(id);\n await prj.destroy();\n this.openedProjectsList.setValue([...this.openedProjects.keys()]);\n }\n\n /** Returns a project access object for an opened project. */\n public getOpenedProject(id: ProjectId): Project {\n const prj = this.openedProjects.get(id);\n if (prj === undefined) throw new Error(`Project ${id} not found among opened projects`);\n return prj;\n }\n\n /** Returns true if project with given id is currently opened. */\n public isProjectOpened(id: ProjectId): boolean {\n return this.openedProjects.has(id);\n }\n\n /**\n * Deallocates all runtime resources consumed by this object and awaits\n * actual termination of event loops and other processes associated with\n * them.\n */\n public async close() {\n await Promise.all([...this.openedProjects.values()].map((prj) => prj.destroy()));\n // this.env.quickJs;\n await this.projectListTree.terminate();\n await this.env.dispose();\n await this.pl.close();\n }\n\n /** @deprecated */\n public async closeAndAwaitTermination() {\n await this.close();\n }\n\n /** Generates sufficiently random string to be used as local secret for the\n * middle layer */\n public static generateLocalSecret(): string {\n return HmacSha256Signer.generateSecret();\n }\n\n /** Returns a block event dispatcher, which can be used to listen to block events. */\n public get blockEventDispatcher(): BlockEventDispatcher {\n return this.env.blockEventDispatcher;\n }\n\n /** Initialize middle layer */\n public static async init(\n pl: PlClient,\n workdir: string,\n _ops: MiddleLayerOpsConstructor,\n ): Promise<MiddleLayer> {\n const ops: MiddleLayerOps = {\n ...DefaultMiddleLayerOpsSettings,\n ...DefaultMiddleLayerOpsPaths(workdir),\n ..._ops,\n };\n\n // overriding debug options from environment variables\n ops.defaultTreeOptions.logStat = getDebugFlags().logTreeStats;\n ops.debugOps.dumpInitialTreeState = getDebugFlags().dumpInitialTreeState;\n // apply MI_TREE_TRAVERSAL only when the embedder hasn't set an explicit mode\n if (\n ops.defaultTreeOptions.traversalMode === undefined &&\n getDebugFlags().treeTraversalMode !== undefined\n )\n ops.defaultTreeOptions.traversalMode = getDebugFlags().treeTraversalMode;\n\n const projects = await pl.withWriteTx(\"MLInitialization\", async (tx) => {\n const projectsField = field(tx.clientRoot, ProjectsField);\n tx.createField(projectsField, \"Dynamic\");\n const projectsFieldData = await tx.getField(projectsField);\n if (isNullSignedResourceId(projectsFieldData.value)) {\n const projects = tx.createEphemeral(ProjectsResourceType);\n tx.lock(projects);\n\n tx.setField(projectsField, projects);\n\n await tx.commit();\n\n return await projects.globalId;\n } else {\n return projectsFieldData.value;\n }\n });\n\n const logger = ops.logger;\n\n const driverKit = await initDriverKit(pl, workdir, ops.frontendDownloadPath, ops);\n\n // passed to components having no own retry logic\n const retryHttpDispatcher = new RetryAgent(pl.httpDispatcher);\n\n const v2RegistryProvider = new V2RegistryProvider(retryHttpDispatcher);\n\n const bpPreparer = new BlockPackPreparer(\n v2RegistryProvider,\n driverKit.signer,\n retryHttpDispatcher,\n );\n\n const quickJs = await getQuickJS();\n\n const runtimeCapabilities = new RuntimeCapabilities();\n // add runtime capabilities of model here\n runtimeCapabilities.addSupportedRequirement(\"requiresModelAPIVersion\", 1);\n runtimeCapabilities.addSupportedRequirement(\"requiresModelAPIVersion\", 2);\n runtimeCapabilities.addSupportedRequirement(\"requiresCreatePTable\", 2);\n runtimeCapabilities.addSupportedRequirement(\"requiresPFramesVersion\", REQUIRES_PFRAMES_VERSION);\n registerServiceCapabilities((flag, value) =>\n runtimeCapabilities.addSupportedRequirement(flag, value),\n );\n // runtime capabilities of the desktop are to be added by the desktop app / test framework\n\n const serviceRegistry = createModelServiceRegistry({ logger });\n\n const env: MiddleLayerEnvironment = {\n pl,\n blockEventDispatcher: new BlockEventDispatcher(),\n signer: driverKit.signer,\n logger,\n httpDispatcher: pl.httpDispatcher,\n retryHttpDispatcher,\n ops,\n bpPreparer,\n frontendDownloadDriver: driverKit.frontendDriver,\n driverKit,\n blockUpdateWatcher: new BlockUpdateWatcher(v2RegistryProvider, logger, {\n minDelay: ops.devBlockUpdateRecheckInterval,\n http: retryHttpDispatcher,\n preferredUpdateChannel: ops.preferredUpdateChannel,\n }),\n runtimeCapabilities,\n serviceRegistry,\n quickJs,\n projectHelper: new ProjectHelper(quickJs, logger),\n dispose: async () => {\n await serviceRegistry.dispose();\n await retryHttpDispatcher.destroy();\n await driverKit.dispose();\n },\n };\n\n const openedProjects = new WatchableValue<ProjectId[]>([]);\n const projectListTC = await createProjectList(pl, projects, openedProjects, env);\n\n return new MiddleLayer(\n env,\n driverKit,\n driverKit.signer,\n projects,\n openedProjects,\n projectListTC.tree,\n v2RegistryProvider,\n projectListTC.computable,\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"middle_layer.js","names":[],"sources":["../../src/middle_layer/middle_layer.ts"],"sourcesContent":["import type { PlClient, SignedResourceId, ResourceRef } from \"@milaboratories/pl-client\";\nimport {\n field,\n isNotNullSignedResourceId,\n isNullSignedResourceId,\n resourceIdToString,\n} from \"@milaboratories/pl-client\";\nimport { LRUCache } from \"lru-cache\";\nimport { createProjectList, ProjectsField, ProjectsResourceType } from \"./project_list\";\nimport { createProject, duplicateProject, withProjectAuthored } from \"../mutator/project\";\nimport { ProjectMetaKey } from \"../model/project_model\";\nimport type { ProjectId } from \"../model/project_model\";\nimport type { SynchronizedTreeState } from \"@milaboratories/pl-tree\";\nimport { BlockPackPreparer } from \"../mutator/block-pack/block_pack\";\nimport type { MiLogger, Signer } from \"@milaboratories/ts-helpers\";\nimport { BlockEventDispatcher } from \"@milaboratories/ts-helpers\";\nimport { HmacSha256Signer } from \"@milaboratories/ts-helpers\";\nimport type { ComputableStableDefined } from \"@milaboratories/computable\";\nimport { WatchableValue } from \"@milaboratories/computable\";\nimport { Project } from \"./project\";\nimport type { MiddleLayerOps, MiddleLayerOpsConstructor } from \"./ops\";\nimport { DefaultMiddleLayerOpsPaths, DefaultMiddleLayerOpsSettings } from \"./ops\";\nimport { randomUUID } from \"node:crypto\";\nimport type { ProjectListEntry } from \"../model\";\nimport type {\n AuthorMarker,\n ProjectMeta,\n BlockPlatform,\n} from \"@milaboratories/pl-model-middle-layer\";\nimport { BlockUpdateWatcher } from \"../block_registry/watcher\";\nimport type { QuickJSWASMModule } from \"quickjs-emscripten\";\nimport { getQuickJS } from \"quickjs-emscripten\";\nimport type { MiddleLayerDriverKit } from \"./driver_kit\";\nimport { initDriverKit } from \"./driver_kit\";\nimport type { BlockCodeFeatureFlags, DriverKit, SupportedRequirement } from \"@platforma-sdk/model\";\nimport { RuntimeCapabilities } from \"@platforma-sdk/model\";\nimport {\n type ModelServiceRegistry,\n registerServiceCapabilities,\n REQUIRES_PFRAMES_VERSION,\n} from \"@milaboratories/pl-model-common\";\nimport { createModelServiceRegistry } from \"../service_factories\";\nimport type { DownloadUrlDriver } from \"@milaboratories/pl-drivers\";\nimport { V2RegistryProvider } from \"../block_registry\";\nimport type { Dispatcher } from \"undici\";\nimport { RetryAgent } from \"undici\";\nimport { getDebugFlags } from \"../debug\";\nimport { ProjectHelper } from \"../model/project_helper\";\n\nexport interface MiddleLayerEnvironment {\n dispose(): Promise<void>;\n readonly pl: PlClient;\n readonly runtimeCapabilities: RuntimeCapabilities;\n readonly logger: MiLogger;\n readonly blockEventDispatcher: BlockEventDispatcher;\n readonly httpDispatcher: Dispatcher;\n readonly retryHttpDispatcher: Dispatcher;\n readonly signer: Signer;\n readonly ops: MiddleLayerOps;\n readonly bpPreparer: BlockPackPreparer;\n readonly frontendDownloadDriver: DownloadUrlDriver;\n readonly blockUpdateWatcher: BlockUpdateWatcher;\n readonly quickJs: QuickJSWASMModule;\n readonly driverKit: MiddleLayerDriverKit;\n readonly serviceRegistry: ModelServiceRegistry;\n readonly projectHelper: ProjectHelper;\n}\n\n/**\n * Main access object to work with pl from UI.\n *\n * It implements an abstraction layer of projects and blocks.\n *\n * As a main entry point inside the pl, this object uses a resource attached\n * via the {@link ProjectsField} to the pl client's root, this resource\n * contains project list.\n *\n * Read about alternative roots, if isolated project lists (working environments)\n * are required.\n * */\nexport class MiddleLayer {\n public readonly pl: PlClient;\n\n /** Contains a reactive list of projects along with their meta information. */\n public readonly projectList: ComputableStableDefined<ProjectListEntry[]>;\n\n private constructor(\n private readonly env: MiddleLayerEnvironment,\n public readonly driverKit: DriverKit,\n public readonly signer: Signer,\n private readonly projectListResourceId: SignedResourceId,\n private readonly openedProjectsList: WatchableValue<ProjectId[]>,\n private readonly projectListTree: SynchronizedTreeState,\n public readonly blockRegistryProvider: V2RegistryProvider,\n projectList: ComputableStableDefined<ProjectListEntry[]>,\n ) {\n this.projectList = projectList;\n this.pl = this.env.pl;\n }\n\n /**\n * Get the OS where backend is running.\n * For old backend versions returns undefined.\n */\n public get serverPlatform(): BlockPlatform | undefined {\n return this.pl.serverInfo.platform as BlockPlatform | undefined;\n }\n\n /**\n * Runtime capabilities advertised by the connected backend (tokens of\n * the form `<feature>:<version>`, e.g. \"wasm:v1\"). Empty list if the\n * backend predates the capability mechanism — that's the desired\n * fail-closed behaviour for blocks declaring any `requiredCapabilities`.\n */\n public get serverCapabilities(): string[] {\n return this.pl.serverInfo.capabilities ?? [];\n }\n\n /** Adds a runtime capability to the middle layer. */\n public addRuntimeCapability(\n requirement: SupportedRequirement,\n value: number | boolean = true,\n ): void {\n this.env.runtimeCapabilities.addSupportedRequirement(requirement, value);\n }\n\n /** Checks if the given block feature flags are compatible with the runtime capabilities. */\n public checkBlockCompatibility(featureFlags: BlockCodeFeatureFlags | undefined): boolean {\n return this.env.runtimeCapabilities.checkCompatibility(featureFlags);\n }\n\n /** Returns extended API driver kit used internally by middle layer. */\n public get internalDriverKit(): MiddleLayerDriverKit {\n return this.env.driverKit;\n }\n\n /** Returns the service registry for service introspection. */\n public get serviceRegistry(): ModelServiceRegistry {\n return this.env.serviceRegistry;\n }\n\n //\n // ProjectId ↔ SignedResourceId resolution\n //\n\n private readonly projectIdCache = new LRUCache<ProjectId, SignedResourceId>({ max: 1024 });\n\n /** Resolves a ProjectId to a signed SignedResourceId.\n * Uses LRU cache with TX-scan fallback. */\n private async resolveProjectId(projectId: ProjectId): Promise<SignedResourceId> {\n const cached = this.projectIdCache.get(projectId);\n if (cached !== undefined) return cached;\n\n // Cache miss — scan project list fields to find the matching resource\n const rid = await this.pl.withReadTx(\"ResolveProjectId\", async (tx) => {\n const data = await tx.getResourceData(this.projectListResourceId, true);\n for (const f of data.fields) {\n if (isNullSignedResourceId(f.value)) continue;\n if (resourceIdToString(f.value) === (projectId as string)) return f.value;\n }\n throw new Error(`Project ${projectId} not found in project list.`);\n });\n\n this.projectIdCache.set(projectId, rid);\n return rid;\n }\n\n //\n // Project List Manipulation\n //\n\n /** Creates a project with initial state and adds it to project list. */\n public async createProject(meta: ProjectMeta): Promise<ProjectId> {\n let prj: ResourceRef;\n await this.pl.withWriteTx(\"MLCreateProject\", async (tx) => {\n prj = await createProject(tx, meta);\n tx.createField(field(this.projectListResourceId, randomUUID()), \"Dynamic\", prj);\n await tx.commit();\n });\n await this.projectListTree.refreshState();\n\n const signedRid = await prj!.globalId;\n const projectId = resourceIdToString(signedRid) as ProjectId;\n this.projectIdCache.set(projectId, signedRid);\n return projectId;\n }\n\n /** Updates project metadata */\n public async setProjectMeta(\n id: ProjectId,\n meta: ProjectMeta,\n author?: AuthorMarker,\n ): Promise<void> {\n const rid = await this.resolveProjectId(id);\n await withProjectAuthored(\n this.env.projectHelper,\n this.pl,\n rid,\n author,\n (prj) => {\n prj.setMeta(meta);\n },\n { name: \"setProjectMeta\" },\n );\n await this.projectListTree.refreshState();\n }\n\n /** Permanently deletes project from the project list, this will result in\n * destruction of all attached objects, like files, analysis results etc. */\n public async deleteProject(id: ProjectId): Promise<void> {\n await this.pl.withWriteTx(\"MLRemoveProject\", async (tx) => {\n const data = await tx.getResourceData(this.projectListResourceId, true);\n let fieldName: string | undefined;\n for (const f of data.fields) {\n if (isNullSignedResourceId(f.value)) continue;\n if (resourceIdToString(f.value) === (id as string)) {\n fieldName = f.name;\n break;\n }\n }\n if (fieldName === undefined) throw new Error(`Project ${id} not found in project list.`);\n tx.removeField(field(this.projectListResourceId, fieldName));\n await tx.commit();\n });\n this.projectIdCache.delete(id);\n await this.projectListTree.refreshState();\n }\n\n /**\n * Duplicates an existing project and adds the copy to this user's project list.\n *\n * @param srcProjectId - project id of the project to duplicate\n * @param rename - optional function that receives the source label and all existing\n * project labels (read within the same transaction), and returns the label for the copy\n */\n public async duplicateProject(\n srcProjectId: ProjectId,\n rename?: (previousLabel: string, existingLabels: string[]) => string,\n ): Promise<ProjectId> {\n const sourceRid = await this.resolveProjectId(srcProjectId);\n\n const newPrj: ResourceRef = await this.pl.withWriteTx(\"MLDuplicateProject\", async (tx) => {\n // Read source project meta\n const sourceMeta = await tx.getKValueJson<ProjectMeta>(sourceRid, ProjectMetaKey);\n\n // Read all existing project labels from the project list (parallel reads)\n const projectListData = await tx.getResourceData(this.projectListResourceId, true);\n const projectRids = projectListData.fields\n .map((f) => f.value)\n .filter(isNotNullSignedResourceId);\n const existingLabels = (\n await Promise.all(\n projectRids.map((rid) => tx.getKValueJson<ProjectMeta>(rid, ProjectMetaKey)),\n )\n ).map((m) => m.label);\n\n // Compute new label\n const newLabel = rename ? rename(sourceMeta.label, existingLabels) : sourceMeta.label;\n\n // Create the duplicate\n const newPrj = await duplicateProject(tx, sourceRid, { label: newLabel });\n\n // Attach to project list with a random UUID field name\n tx.createField(field(this.projectListResourceId, randomUUID()), \"Dynamic\", newPrj);\n await tx.commit();\n\n return newPrj;\n });\n\n await this.projectListTree.refreshState();\n\n const signedRid = await newPrj.globalId;\n const newProjectId = resourceIdToString(signedRid) as ProjectId;\n this.projectIdCache.set(newProjectId, signedRid);\n return newProjectId;\n }\n\n //\n // Projects\n //\n\n private readonly openedProjects = new Map<ProjectId, Project>();\n\n /** Opens a project, and starts corresponding project maintenance loop. */\n public async openProject(id: ProjectId): Promise<void> {\n if (this.openedProjects.has(id)) throw new Error(`Project ${id} already opened`);\n const rid = await this.resolveProjectId(id);\n this.openedProjects.set(id, await Project.init(this.env, id, rid));\n this.openedProjectsList.setValue([...this.openedProjects.keys()]);\n }\n\n /** Closes the project, and deallocate all corresponding resources. */\n public async closeProject(id: ProjectId): Promise<void> {\n const prj = this.openedProjects.get(id);\n if (prj === undefined) throw new Error(`Project ${id} not found among opened projects`);\n this.openedProjects.delete(id);\n await prj.destroy();\n this.openedProjectsList.setValue([...this.openedProjects.keys()]);\n }\n\n /** Returns a project access object for an opened project. */\n public getOpenedProject(id: ProjectId): Project {\n const prj = this.openedProjects.get(id);\n if (prj === undefined) throw new Error(`Project ${id} not found among opened projects`);\n return prj;\n }\n\n /** Returns true if project with given id is currently opened. */\n public isProjectOpened(id: ProjectId): boolean {\n return this.openedProjects.has(id);\n }\n\n /**\n * Deallocates all runtime resources consumed by this object and awaits\n * actual termination of event loops and other processes associated with\n * them.\n */\n public async close() {\n await Promise.all([...this.openedProjects.values()].map((prj) => prj.destroy()));\n // this.env.quickJs;\n await this.projectListTree.terminate();\n await this.env.dispose();\n await this.pl.close();\n }\n\n /** @deprecated */\n public async closeAndAwaitTermination() {\n await this.close();\n }\n\n /** Generates sufficiently random string to be used as local secret for the\n * middle layer */\n public static generateLocalSecret(): string {\n return HmacSha256Signer.generateSecret();\n }\n\n /** Returns a block event dispatcher, which can be used to listen to block events. */\n public get blockEventDispatcher(): BlockEventDispatcher {\n return this.env.blockEventDispatcher;\n }\n\n /** Initialize middle layer */\n public static async init(\n pl: PlClient,\n workdir: string,\n _ops: MiddleLayerOpsConstructor,\n ): Promise<MiddleLayer> {\n const ops: MiddleLayerOps = {\n ...DefaultMiddleLayerOpsSettings,\n ...DefaultMiddleLayerOpsPaths(workdir),\n ..._ops,\n };\n\n // overriding debug options from environment variables\n ops.defaultTreeOptions.logStat = getDebugFlags().logTreeStats;\n ops.debugOps.dumpInitialTreeState = getDebugFlags().dumpInitialTreeState;\n // apply MI_TREE_TRAVERSAL only when the embedder hasn't set an explicit mode\n if (\n ops.defaultTreeOptions.traversalMode === undefined &&\n getDebugFlags().treeTraversalMode !== undefined\n )\n ops.defaultTreeOptions.traversalMode = getDebugFlags().treeTraversalMode;\n\n const projects = await pl.withWriteTx(\"MLInitialization\", async (tx) => {\n const projectsField = field(tx.clientRoot, ProjectsField);\n tx.createField(projectsField, \"Dynamic\");\n const projectsFieldData = await tx.getField(projectsField);\n if (isNullSignedResourceId(projectsFieldData.value)) {\n const projects = tx.createEphemeral(ProjectsResourceType);\n tx.lock(projects);\n\n tx.setField(projectsField, projects);\n\n await tx.commit();\n\n return await projects.globalId;\n } else {\n return projectsFieldData.value;\n }\n });\n\n const logger = ops.logger;\n\n const driverKit = await initDriverKit(pl, workdir, ops.frontendDownloadPath, ops);\n\n // passed to components having no own retry logic\n const retryHttpDispatcher = new RetryAgent(pl.httpDispatcher);\n\n const v2RegistryProvider = new V2RegistryProvider(retryHttpDispatcher);\n\n const bpPreparer = new BlockPackPreparer(\n v2RegistryProvider,\n driverKit.signer,\n retryHttpDispatcher,\n );\n\n const quickJs = await getQuickJS();\n\n const runtimeCapabilities = new RuntimeCapabilities();\n // add runtime capabilities of model here\n runtimeCapabilities.addSupportedRequirement(\"requiresModelAPIVersion\", 1);\n runtimeCapabilities.addSupportedRequirement(\"requiresModelAPIVersion\", 2);\n runtimeCapabilities.addSupportedRequirement(\"requiresCreatePTable\", 2);\n runtimeCapabilities.addSupportedRequirement(\"requiresPFramesVersion\", REQUIRES_PFRAMES_VERSION);\n registerServiceCapabilities((flag, value) =>\n runtimeCapabilities.addSupportedRequirement(flag, value),\n );\n // runtime capabilities of the desktop are to be added by the desktop app / test framework\n\n const serviceRegistry = createModelServiceRegistry({ logger });\n\n const env: MiddleLayerEnvironment = {\n pl,\n blockEventDispatcher: new BlockEventDispatcher(),\n signer: driverKit.signer,\n logger,\n httpDispatcher: pl.httpDispatcher,\n retryHttpDispatcher,\n ops,\n bpPreparer,\n frontendDownloadDriver: driverKit.frontendDriver,\n driverKit,\n blockUpdateWatcher: new BlockUpdateWatcher(v2RegistryProvider, logger, {\n minDelay: ops.devBlockUpdateRecheckInterval,\n http: retryHttpDispatcher,\n preferredUpdateChannel: ops.preferredUpdateChannel,\n }),\n runtimeCapabilities,\n serviceRegistry,\n quickJs,\n projectHelper: new ProjectHelper(quickJs, logger),\n dispose: async () => {\n await serviceRegistry.dispose();\n await retryHttpDispatcher.destroy();\n await driverKit.dispose();\n },\n };\n\n const openedProjects = new WatchableValue<ProjectId[]>([]);\n const projectListTC = await createProjectList(pl, projects, openedProjects, env);\n\n return new MiddleLayer(\n env,\n driverKit,\n driverKit.signer,\n projects,\n openedProjects,\n projectListTC.tree,\n v2RegistryProvider,\n projectListTC.computable,\n );\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation_states.cjs","names":["ChangeSource","DefaultNavigationState","Computable"],"sources":["../../src/middle_layer/navigation_states.ts"],"sourcesContent":["import type { ComputableCtx } from \"@milaboratories/computable\";\nimport { ChangeSource, Computable } from \"@milaboratories/computable\";\nimport type { NavigationState } from \"@platforma-sdk/model\";\nimport { DefaultNavigationState } from \"@platforma-sdk/model\";\n\ntype NavigationStateEntry = {\n state: NavigationState;\n readonly change: ChangeSource;\n};\n\nexport class NavigationStates {\n private readonly states = new Map<string, NavigationStateEntry>();\n\n public setState(blockId: string, state: NavigationState) {\n const entry = this.states.get(blockId);\n if (entry === undefined) {\n this.states.set(blockId, { state, change: new ChangeSource() });\n return;\n }\n entry.state = { ...state };\n entry.change.markChanged(\"navigation state changed\");\n }\n\n private readState(ctx: ComputableCtx, blockId: string): NavigationState {\n let entry = this.states.get(blockId);\n if (entry === undefined) {\n entry = { state: { ...DefaultNavigationState }, change: new ChangeSource() };\n this.states.set(blockId, entry);\n }\n entry.change.attachWatcher(ctx.watcher);\n return entry.state;\n }\n\n public getState(blockId: string): Computable<NavigationState> {\n return Computable.make(\n (ctx) => {\n return this.readState(ctx, blockId);\n },\n { key: `navigationState#${blockId}` },\n );\n }\n\n public deleteBlock(blockId: string) {\n const entry = this.states.get(blockId);\n if (entry !== undefined) {\n this.states.delete(blockId);\n entry.change.markChanged(\"block deleted\");\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"navigation_states.cjs","names":["ChangeSource","DefaultNavigationState","Computable"],"sources":["../../src/middle_layer/navigation_states.ts"],"sourcesContent":["import type { ComputableCtx } from \"@milaboratories/computable\";\nimport { ChangeSource, Computable } from \"@milaboratories/computable\";\nimport type { NavigationState } from \"@platforma-sdk/model\";\nimport { DefaultNavigationState } from \"@platforma-sdk/model\";\n\ntype NavigationStateEntry = {\n state: NavigationState;\n readonly change: ChangeSource;\n};\n\nexport class NavigationStates {\n private readonly states = new Map<string, NavigationStateEntry>();\n\n public setState(blockId: string, state: NavigationState) {\n const entry = this.states.get(blockId);\n if (entry === undefined) {\n this.states.set(blockId, { state, change: new ChangeSource() });\n return;\n }\n entry.state = { ...state };\n entry.change.markChanged(\"navigation state changed\");\n }\n\n private readState(ctx: ComputableCtx, blockId: string): NavigationState {\n let entry = this.states.get(blockId);\n if (entry === undefined) {\n entry = { state: { ...DefaultNavigationState }, change: new ChangeSource() };\n this.states.set(blockId, entry);\n }\n entry.change.attachWatcher(ctx.watcher);\n return entry.state;\n }\n\n public getState(blockId: string): Computable<NavigationState> {\n return Computable.make(\n (ctx) => {\n return this.readState(ctx, blockId);\n },\n { key: `navigationState#${blockId}` },\n );\n }\n\n public deleteBlock(blockId: string) {\n const entry = this.states.get(blockId);\n if (entry !== undefined) {\n this.states.delete(blockId);\n entry.change.markChanged(\"block deleted\");\n }\n }\n}\n"],"mappings":";;;AAUA,IAAa,mBAAb,MAA8B;CAC5B,yBAA0B,IAAI,IAAkC;CAEhE,SAAgB,SAAiB,OAAwB;EACvD,MAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;EACrC,IAAI,UAAU,KAAA,GAAW;GACvB,KAAK,OAAO,IAAI,SAAS;IAAE;IAAO,QAAQ,IAAIA,2BAAAA,aAAa;GAAE,CAAC;GAC9D;EACF;EACA,MAAM,QAAQ,EAAE,GAAG,MAAM;EACzB,MAAM,OAAO,YAAY,0BAA0B;CACrD;CAEA,UAAkB,KAAoB,SAAkC;EACtE,IAAI,QAAQ,KAAK,OAAO,IAAI,OAAO;EACnC,IAAI,UAAU,KAAA,GAAW;GACvB,QAAQ;IAAE,OAAO,EAAE,GAAGC,qBAAAA,uBAAuB;IAAG,QAAQ,IAAID,2BAAAA,aAAa;GAAE;GAC3E,KAAK,OAAO,IAAI,SAAS,KAAK;EAChC;EACA,MAAM,OAAO,cAAc,IAAI,OAAO;EACtC,OAAO,MAAM;CACf;CAEA,SAAgB,SAA8C;EAC5D,OAAOE,2BAAAA,WAAW,MACf,QAAQ;GACP,OAAO,KAAK,UAAU,KAAK,OAAO;EACpC,GACA,EAAE,KAAK,mBAAmB,UAAU,CACtC;CACF;CAEA,YAAmB,SAAiB;EAClC,MAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;EACrC,IAAI,UAAU,KAAA,GAAW;GACvB,KAAK,OAAO,OAAO,OAAO;GAC1B,MAAM,OAAO,YAAY,eAAe;EAC1C;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation_states.js","names":[],"sources":["../../src/middle_layer/navigation_states.ts"],"sourcesContent":["import type { ComputableCtx } from \"@milaboratories/computable\";\nimport { ChangeSource, Computable } from \"@milaboratories/computable\";\nimport type { NavigationState } from \"@platforma-sdk/model\";\nimport { DefaultNavigationState } from \"@platforma-sdk/model\";\n\ntype NavigationStateEntry = {\n state: NavigationState;\n readonly change: ChangeSource;\n};\n\nexport class NavigationStates {\n private readonly states = new Map<string, NavigationStateEntry>();\n\n public setState(blockId: string, state: NavigationState) {\n const entry = this.states.get(blockId);\n if (entry === undefined) {\n this.states.set(blockId, { state, change: new ChangeSource() });\n return;\n }\n entry.state = { ...state };\n entry.change.markChanged(\"navigation state changed\");\n }\n\n private readState(ctx: ComputableCtx, blockId: string): NavigationState {\n let entry = this.states.get(blockId);\n if (entry === undefined) {\n entry = { state: { ...DefaultNavigationState }, change: new ChangeSource() };\n this.states.set(blockId, entry);\n }\n entry.change.attachWatcher(ctx.watcher);\n return entry.state;\n }\n\n public getState(blockId: string): Computable<NavigationState> {\n return Computable.make(\n (ctx) => {\n return this.readState(ctx, blockId);\n },\n { key: `navigationState#${blockId}` },\n );\n }\n\n public deleteBlock(blockId: string) {\n const entry = this.states.get(blockId);\n if (entry !== undefined) {\n this.states.delete(blockId);\n entry.change.markChanged(\"block deleted\");\n }\n }\n}\n"],"mappings":";;;AAUA,IAAa,mBAAb,MAA8B;CAC5B,yBAA0B,IAAI,
|
|
1
|
+
{"version":3,"file":"navigation_states.js","names":[],"sources":["../../src/middle_layer/navigation_states.ts"],"sourcesContent":["import type { ComputableCtx } from \"@milaboratories/computable\";\nimport { ChangeSource, Computable } from \"@milaboratories/computable\";\nimport type { NavigationState } from \"@platforma-sdk/model\";\nimport { DefaultNavigationState } from \"@platforma-sdk/model\";\n\ntype NavigationStateEntry = {\n state: NavigationState;\n readonly change: ChangeSource;\n};\n\nexport class NavigationStates {\n private readonly states = new Map<string, NavigationStateEntry>();\n\n public setState(blockId: string, state: NavigationState) {\n const entry = this.states.get(blockId);\n if (entry === undefined) {\n this.states.set(blockId, { state, change: new ChangeSource() });\n return;\n }\n entry.state = { ...state };\n entry.change.markChanged(\"navigation state changed\");\n }\n\n private readState(ctx: ComputableCtx, blockId: string): NavigationState {\n let entry = this.states.get(blockId);\n if (entry === undefined) {\n entry = { state: { ...DefaultNavigationState }, change: new ChangeSource() };\n this.states.set(blockId, entry);\n }\n entry.change.attachWatcher(ctx.watcher);\n return entry.state;\n }\n\n public getState(blockId: string): Computable<NavigationState> {\n return Computable.make(\n (ctx) => {\n return this.readState(ctx, blockId);\n },\n { key: `navigationState#${blockId}` },\n );\n }\n\n public deleteBlock(blockId: string) {\n const entry = this.states.get(blockId);\n if (entry !== undefined) {\n this.states.delete(blockId);\n entry.change.markChanged(\"block deleted\");\n }\n }\n}\n"],"mappings":";;;AAUA,IAAa,mBAAb,MAA8B;CAC5B,yBAA0B,IAAI,IAAkC;CAEhE,SAAgB,SAAiB,OAAwB;EACvD,MAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;EACrC,IAAI,UAAU,KAAA,GAAW;GACvB,KAAK,OAAO,IAAI,SAAS;IAAE;IAAO,QAAQ,IAAI,aAAa;GAAE,CAAC;GAC9D;EACF;EACA,MAAM,QAAQ,EAAE,GAAG,MAAM;EACzB,MAAM,OAAO,YAAY,0BAA0B;CACrD;CAEA,UAAkB,KAAoB,SAAkC;EACtE,IAAI,QAAQ,KAAK,OAAO,IAAI,OAAO;EACnC,IAAI,UAAU,KAAA,GAAW;GACvB,QAAQ;IAAE,OAAO,EAAE,GAAG,uBAAuB;IAAG,QAAQ,IAAI,aAAa;GAAE;GAC3E,KAAK,OAAO,IAAI,SAAS,KAAK;EAChC;EACA,MAAM,OAAO,cAAc,IAAI,OAAO;EACtC,OAAO,MAAM;CACf;CAEA,SAAgB,SAA8C;EAC5D,OAAO,WAAW,MACf,QAAQ;GACP,OAAO,KAAK,UAAU,KAAK,OAAO;EACpC,GACA,EAAE,KAAK,mBAAmB,UAAU,CACtC;CACF;CAEA,YAAmB,SAAiB;EAClC,MAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;EACrC,IAAI,UAAU,KAAA,GAAW;GACvB,KAAK,OAAO,OAAO,OAAO;GAC1B,MAAM,OAAO,YAAY,eAAe;EAC1C;CACF;AACF"}
|
|
@@ -2,7 +2,7 @@ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
|
2
2
|
const require_driver = require("../pool/driver.cjs");
|
|
3
3
|
require("../pool/index.cjs");
|
|
4
4
|
let node_path = require("node:path");
|
|
5
|
-
node_path = require_runtime.__toESM(node_path);
|
|
5
|
+
node_path = require_runtime.__toESM(node_path, 1);
|
|
6
6
|
//#region src/middle_layer/ops.ts
|
|
7
7
|
/** Some defaults fot MiddleLayerOps. */
|
|
8
8
|
const DefaultDriverKitOpsSettings = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ops.cjs","names":["ConsoleLoggerAdapter","PFrameDriverOpsDefaults","path"],"sources":["../../src/middle_layer/ops.ts"],"sourcesContent":["import type { TemporalSynchronizedTreeOps } from \"./types\";\nimport type {\n DownloadBlobToURLDriverOps,\n DownloadDriverOps,\n DownloadUrlDriverOps,\n OpenFileDialogCallback,\n VirtualLocalStorageSpec,\n} from \"@milaboratories/pl-drivers\";\nimport type { UploadDriverOps } from \"@milaboratories/pl-drivers\";\nimport type { LogsStreamDriverOps } from \"@milaboratories/pl-drivers\";\nimport type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport type { LocalStorageProjection } from \"@milaboratories/pl-drivers\";\nimport path from \"node:path\";\nimport { PFrameDriverOpsDefaults, type PFrameDriverOps, type ParquetCacheOps } from \"../pool\";\n\n/** Paths part of {@link DriverKitOps}. */\nexport type DriverKitOpsPaths = {\n /** Common root where to put downloaded blobs / downloaded blob cache */\n readonly blobDownloadPath: string;\n\n /** Common root for a cache for range queries. */\n readonly blobDownloadRangesCachePath: string;\n\n /** Common root where to put downloaded blobs with */\n readonly downloadBlobToURLPath: string;\n\n /**\n * List of pl storages that have projections in local file system.\n *\n * This option affect two drivers:\n *\n * (1) LS driver generates \"index\" handles instead of \"upload\" for paths inside those locations\n *\n * (2) Download driver directly serves content retrieval requests for blobs from listed storages,\n * and don't apply any caching for such blobs (i.e. preventing duplication of files for Downloaded\n * type handles, making OnDemand and Downloaded handles equivalent)\n *\n * */\n readonly localProjections: LocalStorageProjection[];\n\n /**\n * List of virtual storages that will allow homogeneous access to local FSs through LS API.\n * If undefined, default list will be created.\n * */\n readonly virtualLocalStoragesOverride?: VirtualLocalStorageSpec[];\n\n /** Path to the directory where pframes will spill temporary files and store materialized views */\n readonly pframesSpillPath: string;\n\n /**\n * Path to the directory backing the persistent parquet blob cache. Unlike\n * {@link pframesSpillPath} this directory is NOT emptied on startup - the cache\n * (and its lifetime counters) is meant to survive restarts.\n */\n readonly parquetCachePath: string;\n};\n\n/** Options required to initialize full set of middle layer driver kit */\nexport type DriverKitOpsSettings = {\n //\n // Common\n //\n\n readonly logger: MiLogger;\n\n //\n // Signer\n //\n\n /**\n * Local secret, that is used to sign and verify different pieces of information\n * that can be used to access local data, like local paths for ongoing uploads.\n *\n * Use {@link MiddleLayer.generateLocalSecret} to generate sufficiently random string.\n * */\n readonly localSecret: string;\n\n //\n // Blob Driver\n //\n\n /**\n * Settings related to the download driver making operations with blobs. This driver is also used\n * to download logs when source process terminates and log terns into a blob\n */\n readonly blobDriverOps: DownloadDriverOps;\n\n //\n // Frontend Driver\n //\n\n /** Settings related to the frontend driver that downloads frontends. */\n readonly frontendDownloadDriverOps: DownloadUrlDriverOps;\n\n //\n // Blob To URL Driver\n //\n\n readonly downloadBlobToURLDriverOps: DownloadBlobToURLDriverOps;\n\n //\n // Upload Driver\n //\n\n /**\n * Settings related to the upload driver that actually performs upload and helps render upload\n * and indexing progresses from related pl resources.\n * */\n readonly uploadDriverOps: UploadDriverOps;\n\n //\n // Log streaming ops\n // (static logs are served via the blob driver)\n //\n\n /** Settings related to the streaming log driver */\n readonly logStreamDriverOps: LogsStreamDriverOps;\n\n //\n // LS Driver\n //\n\n /**\n * Callback to access system file open dialog, must be provided by the environment,\n * to allow for {@link showOpenSingleFileDialog} / {@link showOpenMultipleFilesDialog}\n * calls from the UI.\n */\n readonly openFileDialogCallback: OpenFileDialogCallback;\n\n //\n // PFrame Driver\n //\n\n /** Settings related to the PFrame driver */\n readonly pFrameDriverOps: PFrameDriverOps;\n\n /**\n * Tuning for the persistent parquet blob cache. Its directory is\n * {@link DriverKitOpsPaths.parquetCachePath}; this carries only the\n * size/eviction knobs.\n */\n readonly parquetCacheOps: ParquetCacheOps;\n};\n\nexport type DriverKitOps = DriverKitOpsPaths & DriverKitOpsSettings;\n\n/** Some defaults fot MiddleLayerOps. */\nexport const DefaultDriverKitOpsSettings: Pick<\n DriverKitOpsSettings,\n | \"logger\"\n | \"blobDriverOps\"\n | \"frontendDownloadDriverOps\"\n | \"downloadBlobToURLDriverOps\"\n | \"uploadDriverOps\"\n | \"logStreamDriverOps\"\n | \"pFrameDriverOps\"\n | \"parquetCacheOps\"\n> = {\n logger: new ConsoleLoggerAdapter(),\n blobDriverOps: {\n cacheSoftSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n rangesCacheMaxSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n nConcurrentDownloads: 10,\n },\n frontendDownloadDriverOps: {\n cacheSoftSizeBytes: 1 * 1024 * 1024 * 1024, // 1 GB\n withGunzip: true,\n nConcurrentDownloads: 50,\n },\n downloadBlobToURLDriverOps: {\n cacheSoftSizeBytes: 1 * 1024 * 1024 * 1024, // 1 GB\n nConcurrentDownloads: 10,\n },\n uploadDriverOps: {\n nConcurrentPartUploads: 10,\n nConcurrentGetProgresses: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000,\n },\n logStreamDriverOps: {\n nConcurrentGetLogs: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000,\n },\n pFrameDriverOps: PFrameDriverOpsDefaults,\n parquetCacheOps: {\n maxSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n admissionFraction: 0.2, // a single file may occupy at most 20% of the budget\n maxFilesTracked: 50_000, // ghost (previously-evicted) files remembered to guide readmission\n },\n};\n\nexport function DefaultDriverKitOpsPaths(\n workDir: string,\n): Pick<\n DriverKitOpsPaths,\n | \"blobDownloadPath\"\n | \"blobDownloadRangesCachePath\"\n | \"downloadBlobToURLPath\"\n | \"pframesSpillPath\"\n | \"parquetCachePath\"\n> {\n return {\n blobDownloadPath: path.join(workDir, \"download\"),\n blobDownloadRangesCachePath: path.join(workDir, \"downloadRangesCache\"),\n downloadBlobToURLPath: path.join(workDir, \"downloadToURL\"),\n pframesSpillPath: path.join(workDir, \"pframes\"),\n parquetCachePath: path.join(workDir, \"parquetCache\"),\n };\n}\n\n/** Fields with default values are marked as optional here. */\nexport type DriverKitOpsConstructor = Omit<\n DriverKitOpsSettings,\n keyof typeof DefaultDriverKitOpsSettings\n> &\n Partial<typeof DefaultDriverKitOpsSettings> &\n Omit<DriverKitOpsPaths, keyof ReturnType<typeof DefaultDriverKitOpsPaths>> &\n Partial<ReturnType<typeof DefaultDriverKitOpsPaths>>;\n\nexport type MiddleLayerOpsPaths = DriverKitOpsPaths & {\n /** Common root where to put frontend code. */\n readonly frontendDownloadPath: string;\n};\n\n/** Debug options for middle layer. */\nexport type MiddleLayerDebugOptions = {\n /** If true, will dump initial tree state to the file with root resource id as name. */\n dumpInitialTreeState: boolean;\n};\n\n/** Configuration controlling different aspects of middle layer behaviour. */\nexport type MiddleLayerOpsSettings = DriverKitOpsSettings & {\n /** Debug options. */\n readonly debugOps: MiddleLayerDebugOptions;\n\n /** Contain temporal options controlling how often should pl trees be\n * synchronized with the pl server. */\n readonly defaultTreeOptions: TemporalSynchronizedTreeOps;\n\n /** Defines interval in milliseconds for running periodic project maintenance job.\n * Project maintenance includes background staging rendering and cached outputs cleanup. */\n readonly projectRefreshInterval: number;\n\n /** How often to check for dev block updates */\n readonly devBlockUpdateRecheckInterval: number;\n\n /** Prioritize this channel if update is available in this block */\n readonly preferredUpdateChannel?: string;\n};\n\nexport type MiddleLayerOps = MiddleLayerOpsSettings & MiddleLayerOpsPaths;\n\n/** Some defaults fot MiddleLayerOps. */\nexport const DefaultMiddleLayerOpsSettings: Pick<\n MiddleLayerOps,\n | keyof typeof DefaultDriverKitOpsSettings\n | \"defaultTreeOptions\"\n | \"projectRefreshInterval\"\n | \"devBlockUpdateRecheckInterval\"\n | \"debugOps\"\n> = {\n ...DefaultDriverKitOpsSettings,\n defaultTreeOptions: {\n pollingInterval: 200,\n stopPollingDelay: 2500,\n initialTreeLoadingTimeout: 100 * 60 * 60 * 1000, // disable timeout for loading project tree (100 hours)\n },\n debugOps: {\n dumpInitialTreeState: false,\n },\n devBlockUpdateRecheckInterval: 1000,\n projectRefreshInterval: 2000,\n};\n\nexport function DefaultMiddleLayerOpsPaths(\n workDir: string,\n): Pick<\n MiddleLayerOpsPaths,\n keyof ReturnType<typeof DefaultDriverKitOpsPaths> | \"frontendDownloadPath\"\n> {\n return {\n ...DefaultDriverKitOpsPaths(workDir),\n frontendDownloadPath: path.join(workDir, \"frontend\"),\n };\n}\n\nexport type MiddleLayerOpsConstructor = Omit<\n MiddleLayerOpsSettings,\n keyof typeof DefaultMiddleLayerOpsSettings\n> &\n Partial<typeof DefaultMiddleLayerOpsSettings> &\n Omit<MiddleLayerOpsPaths, keyof Awaited<ReturnType<typeof DefaultMiddleLayerOpsPaths>>> &\n Partial<Awaited<ReturnType<typeof DefaultMiddleLayerOpsPaths>>>;\n"],"mappings":";;;;;;;AAoJA,MAAa,8BAUT;CACF,QAAQ,4CAAIA,sBAAsB;CAClC,eAAe;EACb,oBAAoB,IAAI,OAAO,OAAO;EACtC,yBAAyB,IAAI,OAAO,OAAO;EAC3C,sBAAsB;EACvB;CACD,2BAA2B;EACzB,oBAAoB,IAAI,OAAO,OAAO;EACtC,YAAY;EACZ,sBAAsB;EACvB;CACD,4BAA4B;EAC1B,oBAAoB,IAAI,OAAO,OAAO;EACtC,sBAAsB;EACvB;CACD,iBAAiB;EACf,wBAAwB;EACxB,0BAA0B;EAC1B,iBAAiB;EACjB,kBAAkB;EACnB;CACD,oBAAoB;EAClB,oBAAoB;EACpB,iBAAiB;EACjB,kBAAkB;EACnB;CACD,iBAAiBC,eAAAA;CACjB,iBAAiB;EACf,cAAc,IAAI,OAAO,OAAO;EAChC,mBAAmB;EACnB,iBAAiB;EAClB;CACF;AAED,SAAgB,yBACd,SAQA;AACA,QAAO;EACL,kBAAkBC,UAAAA,QAAK,KAAK,SAAS,WAAW;EAChD,6BAA6BA,UAAAA,QAAK,KAAK,SAAS,sBAAsB;EACtE,uBAAuBA,UAAAA,QAAK,KAAK,SAAS,gBAAgB;EAC1D,kBAAkBA,UAAAA,QAAK,KAAK,SAAS,UAAU;EAC/C,kBAAkBA,UAAAA,QAAK,KAAK,SAAS,eAAe;EACrD;;;AA8CH,MAAa,gCAOT;CACF,GAAG;CACH,oBAAoB;EAClB,iBAAiB;EACjB,kBAAkB;EAClB,2BAA2B,MAAW,KAAK;EAC5C;CACD,UAAU,EACR,sBAAsB,OACvB;CACD,+BAA+B;CAC/B,wBAAwB;CACzB;AAED,SAAgB,2BACd,SAIA;AACA,QAAO;EACL,GAAG,yBAAyB,QAAQ;EACpC,sBAAsBA,UAAAA,QAAK,KAAK,SAAS,WAAW;EACrD"}
|
|
1
|
+
{"version":3,"file":"ops.cjs","names":["ConsoleLoggerAdapter","PFrameDriverOpsDefaults","path"],"sources":["../../src/middle_layer/ops.ts"],"sourcesContent":["import type { TemporalSynchronizedTreeOps } from \"./types\";\nimport type {\n DownloadBlobToURLDriverOps,\n DownloadDriverOps,\n DownloadUrlDriverOps,\n OpenFileDialogCallback,\n VirtualLocalStorageSpec,\n} from \"@milaboratories/pl-drivers\";\nimport type { UploadDriverOps } from \"@milaboratories/pl-drivers\";\nimport type { LogsStreamDriverOps } from \"@milaboratories/pl-drivers\";\nimport type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport type { LocalStorageProjection } from \"@milaboratories/pl-drivers\";\nimport path from \"node:path\";\nimport { PFrameDriverOpsDefaults, type PFrameDriverOps, type ParquetCacheOps } from \"../pool\";\n\n/** Paths part of {@link DriverKitOps}. */\nexport type DriverKitOpsPaths = {\n /** Common root where to put downloaded blobs / downloaded blob cache */\n readonly blobDownloadPath: string;\n\n /** Common root for a cache for range queries. */\n readonly blobDownloadRangesCachePath: string;\n\n /** Common root where to put downloaded blobs with */\n readonly downloadBlobToURLPath: string;\n\n /**\n * List of pl storages that have projections in local file system.\n *\n * This option affect two drivers:\n *\n * (1) LS driver generates \"index\" handles instead of \"upload\" for paths inside those locations\n *\n * (2) Download driver directly serves content retrieval requests for blobs from listed storages,\n * and don't apply any caching for such blobs (i.e. preventing duplication of files for Downloaded\n * type handles, making OnDemand and Downloaded handles equivalent)\n *\n * */\n readonly localProjections: LocalStorageProjection[];\n\n /**\n * List of virtual storages that will allow homogeneous access to local FSs through LS API.\n * If undefined, default list will be created.\n * */\n readonly virtualLocalStoragesOverride?: VirtualLocalStorageSpec[];\n\n /** Path to the directory where pframes will spill temporary files and store materialized views */\n readonly pframesSpillPath: string;\n\n /**\n * Path to the directory backing the persistent parquet blob cache. Unlike\n * {@link pframesSpillPath} this directory is NOT emptied on startup - the cache\n * (and its lifetime counters) is meant to survive restarts.\n */\n readonly parquetCachePath: string;\n};\n\n/** Options required to initialize full set of middle layer driver kit */\nexport type DriverKitOpsSettings = {\n //\n // Common\n //\n\n readonly logger: MiLogger;\n\n //\n // Signer\n //\n\n /**\n * Local secret, that is used to sign and verify different pieces of information\n * that can be used to access local data, like local paths for ongoing uploads.\n *\n * Use {@link MiddleLayer.generateLocalSecret} to generate sufficiently random string.\n * */\n readonly localSecret: string;\n\n //\n // Blob Driver\n //\n\n /**\n * Settings related to the download driver making operations with blobs. This driver is also used\n * to download logs when source process terminates and log terns into a blob\n */\n readonly blobDriverOps: DownloadDriverOps;\n\n //\n // Frontend Driver\n //\n\n /** Settings related to the frontend driver that downloads frontends. */\n readonly frontendDownloadDriverOps: DownloadUrlDriverOps;\n\n //\n // Blob To URL Driver\n //\n\n readonly downloadBlobToURLDriverOps: DownloadBlobToURLDriverOps;\n\n //\n // Upload Driver\n //\n\n /**\n * Settings related to the upload driver that actually performs upload and helps render upload\n * and indexing progresses from related pl resources.\n * */\n readonly uploadDriverOps: UploadDriverOps;\n\n //\n // Log streaming ops\n // (static logs are served via the blob driver)\n //\n\n /** Settings related to the streaming log driver */\n readonly logStreamDriverOps: LogsStreamDriverOps;\n\n //\n // LS Driver\n //\n\n /**\n * Callback to access system file open dialog, must be provided by the environment,\n * to allow for {@link showOpenSingleFileDialog} / {@link showOpenMultipleFilesDialog}\n * calls from the UI.\n */\n readonly openFileDialogCallback: OpenFileDialogCallback;\n\n //\n // PFrame Driver\n //\n\n /** Settings related to the PFrame driver */\n readonly pFrameDriverOps: PFrameDriverOps;\n\n /**\n * Tuning for the persistent parquet blob cache. Its directory is\n * {@link DriverKitOpsPaths.parquetCachePath}; this carries only the\n * size/eviction knobs.\n */\n readonly parquetCacheOps: ParquetCacheOps;\n};\n\nexport type DriverKitOps = DriverKitOpsPaths & DriverKitOpsSettings;\n\n/** Some defaults fot MiddleLayerOps. */\nexport const DefaultDriverKitOpsSettings: Pick<\n DriverKitOpsSettings,\n | \"logger\"\n | \"blobDriverOps\"\n | \"frontendDownloadDriverOps\"\n | \"downloadBlobToURLDriverOps\"\n | \"uploadDriverOps\"\n | \"logStreamDriverOps\"\n | \"pFrameDriverOps\"\n | \"parquetCacheOps\"\n> = {\n logger: new ConsoleLoggerAdapter(),\n blobDriverOps: {\n cacheSoftSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n rangesCacheMaxSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n nConcurrentDownloads: 10,\n },\n frontendDownloadDriverOps: {\n cacheSoftSizeBytes: 1 * 1024 * 1024 * 1024, // 1 GB\n withGunzip: true,\n nConcurrentDownloads: 50,\n },\n downloadBlobToURLDriverOps: {\n cacheSoftSizeBytes: 1 * 1024 * 1024 * 1024, // 1 GB\n nConcurrentDownloads: 10,\n },\n uploadDriverOps: {\n nConcurrentPartUploads: 10,\n nConcurrentGetProgresses: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000,\n },\n logStreamDriverOps: {\n nConcurrentGetLogs: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000,\n },\n pFrameDriverOps: PFrameDriverOpsDefaults,\n parquetCacheOps: {\n maxSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n admissionFraction: 0.2, // a single file may occupy at most 20% of the budget\n maxFilesTracked: 50_000, // ghost (previously-evicted) files remembered to guide readmission\n },\n};\n\nexport function DefaultDriverKitOpsPaths(\n workDir: string,\n): Pick<\n DriverKitOpsPaths,\n | \"blobDownloadPath\"\n | \"blobDownloadRangesCachePath\"\n | \"downloadBlobToURLPath\"\n | \"pframesSpillPath\"\n | \"parquetCachePath\"\n> {\n return {\n blobDownloadPath: path.join(workDir, \"download\"),\n blobDownloadRangesCachePath: path.join(workDir, \"downloadRangesCache\"),\n downloadBlobToURLPath: path.join(workDir, \"downloadToURL\"),\n pframesSpillPath: path.join(workDir, \"pframes\"),\n parquetCachePath: path.join(workDir, \"parquetCache\"),\n };\n}\n\n/** Fields with default values are marked as optional here. */\nexport type DriverKitOpsConstructor = Omit<\n DriverKitOpsSettings,\n keyof typeof DefaultDriverKitOpsSettings\n> &\n Partial<typeof DefaultDriverKitOpsSettings> &\n Omit<DriverKitOpsPaths, keyof ReturnType<typeof DefaultDriverKitOpsPaths>> &\n Partial<ReturnType<typeof DefaultDriverKitOpsPaths>>;\n\nexport type MiddleLayerOpsPaths = DriverKitOpsPaths & {\n /** Common root where to put frontend code. */\n readonly frontendDownloadPath: string;\n};\n\n/** Debug options for middle layer. */\nexport type MiddleLayerDebugOptions = {\n /** If true, will dump initial tree state to the file with root resource id as name. */\n dumpInitialTreeState: boolean;\n};\n\n/** Configuration controlling different aspects of middle layer behaviour. */\nexport type MiddleLayerOpsSettings = DriverKitOpsSettings & {\n /** Debug options. */\n readonly debugOps: MiddleLayerDebugOptions;\n\n /** Contain temporal options controlling how often should pl trees be\n * synchronized with the pl server. */\n readonly defaultTreeOptions: TemporalSynchronizedTreeOps;\n\n /** Defines interval in milliseconds for running periodic project maintenance job.\n * Project maintenance includes background staging rendering and cached outputs cleanup. */\n readonly projectRefreshInterval: number;\n\n /** How often to check for dev block updates */\n readonly devBlockUpdateRecheckInterval: number;\n\n /** Prioritize this channel if update is available in this block */\n readonly preferredUpdateChannel?: string;\n};\n\nexport type MiddleLayerOps = MiddleLayerOpsSettings & MiddleLayerOpsPaths;\n\n/** Some defaults fot MiddleLayerOps. */\nexport const DefaultMiddleLayerOpsSettings: Pick<\n MiddleLayerOps,\n | keyof typeof DefaultDriverKitOpsSettings\n | \"defaultTreeOptions\"\n | \"projectRefreshInterval\"\n | \"devBlockUpdateRecheckInterval\"\n | \"debugOps\"\n> = {\n ...DefaultDriverKitOpsSettings,\n defaultTreeOptions: {\n pollingInterval: 200,\n stopPollingDelay: 2500,\n initialTreeLoadingTimeout: 100 * 60 * 60 * 1000, // disable timeout for loading project tree (100 hours)\n },\n debugOps: {\n dumpInitialTreeState: false,\n },\n devBlockUpdateRecheckInterval: 1000,\n projectRefreshInterval: 2000,\n};\n\nexport function DefaultMiddleLayerOpsPaths(\n workDir: string,\n): Pick<\n MiddleLayerOpsPaths,\n keyof ReturnType<typeof DefaultDriverKitOpsPaths> | \"frontendDownloadPath\"\n> {\n return {\n ...DefaultDriverKitOpsPaths(workDir),\n frontendDownloadPath: path.join(workDir, \"frontend\"),\n };\n}\n\nexport type MiddleLayerOpsConstructor = Omit<\n MiddleLayerOpsSettings,\n keyof typeof DefaultMiddleLayerOpsSettings\n> &\n Partial<typeof DefaultMiddleLayerOpsSettings> &\n Omit<MiddleLayerOpsPaths, keyof Awaited<ReturnType<typeof DefaultMiddleLayerOpsPaths>>> &\n Partial<Awaited<ReturnType<typeof DefaultMiddleLayerOpsPaths>>>;\n"],"mappings":";;;;;;;AAoJA,MAAa,8BAUT;CACF,QAAQ,yCAAIA,EAAAA,CAAAA,qBAAqB;CACjC,eAAe;EACb,oBAAoB,IAAI,OAAO,OAAO;EACtC,yBAAyB,IAAI,OAAO,OAAO;EAC3C,sBAAsB;CACxB;CACA,2BAA2B;EACzB,oBAAoB,IAAI,OAAO,OAAO;EACtC,YAAY;EACZ,sBAAsB;CACxB;CACA,4BAA4B;EAC1B,oBAAoB,IAAI,OAAO,OAAO;EACtC,sBAAsB;CACxB;CACA,iBAAiB;EACf,wBAAwB;EACxB,0BAA0B;EAC1B,iBAAiB;EACjB,kBAAkB;CACpB;CACA,oBAAoB;EAClB,oBAAoB;EACpB,iBAAiB;EACjB,kBAAkB;CACpB;CACA,iBAAiBC,eAAAA;CACjB,iBAAiB;EACf,cAAc,IAAI,OAAO,OAAO;EAChC,mBAAmB;EACnB,iBAAiB;CACnB;AACF;AAEA,SAAgB,yBACd,SAQA;CACA,OAAO;EACL,kBAAkBC,UAAAA,QAAK,KAAK,SAAS,UAAU;EAC/C,6BAA6BA,UAAAA,QAAK,KAAK,SAAS,qBAAqB;EACrE,uBAAuBA,UAAAA,QAAK,KAAK,SAAS,eAAe;EACzD,kBAAkBA,UAAAA,QAAK,KAAK,SAAS,SAAS;EAC9C,kBAAkBA,UAAAA,QAAK,KAAK,SAAS,cAAc;CACrD;AACF;;AA6CA,MAAa,gCAOT;CACF,GAAG;CACH,oBAAoB;EAClB,iBAAiB;EACjB,kBAAkB;EAClB,2BAA2B,MAAW,KAAK;CAC7C;CACA,UAAU,EACR,sBAAsB,MACxB;CACA,+BAA+B;CAC/B,wBAAwB;AAC1B;AAEA,SAAgB,2BACd,SAIA;CACA,OAAO;EACL,GAAG,yBAAyB,OAAO;EACnC,sBAAsBA,UAAAA,QAAK,KAAK,SAAS,UAAU;CACrD;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ops.d.ts","names":[],"sources":["../../src/middle_layer/ops.ts"],"mappings":";;;;;;AAiBA;AAAA,KAAY,iBAAA;mFAED,gBAAA;EAAA,SAGA,2BAAA,UAGA;EAAA,SAAA,qBAAA;EAckB
|
|
1
|
+
{"version":3,"file":"ops.d.ts","names":[],"sources":["../../src/middle_layer/ops.ts"],"mappings":";;;;;;AAiBA;AAAA,KAAY,iBAAA;mFAED,gBAAA;EAAA,SAGA,2BAAA,UAGA;EAAA,SAAA,qBAAA;EAckB;;;;;;AAgBF;AAI3B;;;;;EApB6B,SAAlB,gBAAA,EAAkB,sBAAA;EA4DU;;;;EAAA,SAtD5B,4BAAA,GAA+B,uBAAuB,IAiGrC;EAAA,SA9FjB,gBAAA;EA8FgC;;;;;EAAA,SAvFhC,gBAAA;AAAA;;KAIC,oBAAA;EAAA,SAKD,MAAA,EAAQ,QAAA;EA6CR;;;;;;EAAA,SAjCA,WAAA;EA2DiB;;;;EAAA,SAjDjB,aAAA,EAAe,iBAAA,EA2Dd;EAAA,SApDD,yBAAA,EAA2B,oBAAA;EAAA,SAM3B,0BAAA,EAA4B,0BAAA;EA8CZ;AAAwC;AAGnE;;EAH2B,SApChB,eAAA,EAAiB,eAAA,EAuCc;EAAA,SA/B/B,kBAAA,EAAoB,mBAAA;EA4Ef;;;;;EAAA,SAjEL,sBAAA,EAAwB,sBAAA,EAoEjC;EAAA,SA7DS,eAAA,EAAiB,eAAA;EA6DT;AAiBnB;;;;EAjBmB,SAtDR,eAAA,EAAiB,eAAA;AAAA;AAAA,KAGhB,YAAA,GAAe,iBAAA,GAAoB,oBAAoB;;cAGtD,2BAAA,EAA6B,IAAI,CAC5C,oBAAA;AAAA,iBA4Cc,wBAAA,CACd,OAAA,WACC,IAAI,CACL,iBAAA;;KAiBU,uBAAA,GAA0B,IAAA,CACpC,oBAAA,eACa,2BAAA,IAEb,OAAA,QAAe,2BAAA,IACf,IAAA,CAAK,iBAAA,QAAyB,UAAA,QAAkB,wBAAA,KAChD,OAAA,CAAQ,UAAA,QAAkB,wBAAA;AAAA,KAEhB,mBAAA,GAAsB,iBAAiB;EAFzC,uDAIC,oBAAoB;AAAA;;KAInB,uBAAA;EAbV,uFAeA,oBAAoB;AAAA;;KAIV,sBAAA,GAAyB,oBAAA;EAf9B,8BAiBI,QAAA,EAAU,uBAAA;EAjB6B;;EAAA,SAqBvC,kBAAA,EAAoB,2BAAA;EApBH;;EAAA,SAwBjB,sBAAA,UAtBC;EAAA,SAyBD,6BAAA;WAGA,sBAAA;AAAA;AAAA,KAGC,cAAA,GAAiB,sBAAA,GAAyB,mBAAmB;;cAG5D,6BAAA,EAA+B,IAAA,CAC1C,cAAA,eACe,2BAAA;AAAA,iBAmBD,0BAAA,CACd,OAAA,WACC,IAAA,CACD,mBAAA,QACM,UAAA,QAAkB,wBAAA;AAAA,KAQd,yBAAA,GAA4B,IAAA,CACtC,sBAAA,eACa,6BAAA,IAEb,OAAA,QAAe,6BAAA,IACf,IAAA,CAAK,mBAAA,QAA2B,OAAA,CAAQ,UAAA,QAAkB,0BAAA,MAC1D,OAAA,CAAQ,OAAA,CAAQ,UAAA,QAAkB,0BAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ops.js","names":[],"sources":["../../src/middle_layer/ops.ts"],"sourcesContent":["import type { TemporalSynchronizedTreeOps } from \"./types\";\nimport type {\n DownloadBlobToURLDriverOps,\n DownloadDriverOps,\n DownloadUrlDriverOps,\n OpenFileDialogCallback,\n VirtualLocalStorageSpec,\n} from \"@milaboratories/pl-drivers\";\nimport type { UploadDriverOps } from \"@milaboratories/pl-drivers\";\nimport type { LogsStreamDriverOps } from \"@milaboratories/pl-drivers\";\nimport type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport type { LocalStorageProjection } from \"@milaboratories/pl-drivers\";\nimport path from \"node:path\";\nimport { PFrameDriverOpsDefaults, type PFrameDriverOps, type ParquetCacheOps } from \"../pool\";\n\n/** Paths part of {@link DriverKitOps}. */\nexport type DriverKitOpsPaths = {\n /** Common root where to put downloaded blobs / downloaded blob cache */\n readonly blobDownloadPath: string;\n\n /** Common root for a cache for range queries. */\n readonly blobDownloadRangesCachePath: string;\n\n /** Common root where to put downloaded blobs with */\n readonly downloadBlobToURLPath: string;\n\n /**\n * List of pl storages that have projections in local file system.\n *\n * This option affect two drivers:\n *\n * (1) LS driver generates \"index\" handles instead of \"upload\" for paths inside those locations\n *\n * (2) Download driver directly serves content retrieval requests for blobs from listed storages,\n * and don't apply any caching for such blobs (i.e. preventing duplication of files for Downloaded\n * type handles, making OnDemand and Downloaded handles equivalent)\n *\n * */\n readonly localProjections: LocalStorageProjection[];\n\n /**\n * List of virtual storages that will allow homogeneous access to local FSs through LS API.\n * If undefined, default list will be created.\n * */\n readonly virtualLocalStoragesOverride?: VirtualLocalStorageSpec[];\n\n /** Path to the directory where pframes will spill temporary files and store materialized views */\n readonly pframesSpillPath: string;\n\n /**\n * Path to the directory backing the persistent parquet blob cache. Unlike\n * {@link pframesSpillPath} this directory is NOT emptied on startup - the cache\n * (and its lifetime counters) is meant to survive restarts.\n */\n readonly parquetCachePath: string;\n};\n\n/** Options required to initialize full set of middle layer driver kit */\nexport type DriverKitOpsSettings = {\n //\n // Common\n //\n\n readonly logger: MiLogger;\n\n //\n // Signer\n //\n\n /**\n * Local secret, that is used to sign and verify different pieces of information\n * that can be used to access local data, like local paths for ongoing uploads.\n *\n * Use {@link MiddleLayer.generateLocalSecret} to generate sufficiently random string.\n * */\n readonly localSecret: string;\n\n //\n // Blob Driver\n //\n\n /**\n * Settings related to the download driver making operations with blobs. This driver is also used\n * to download logs when source process terminates and log terns into a blob\n */\n readonly blobDriverOps: DownloadDriverOps;\n\n //\n // Frontend Driver\n //\n\n /** Settings related to the frontend driver that downloads frontends. */\n readonly frontendDownloadDriverOps: DownloadUrlDriverOps;\n\n //\n // Blob To URL Driver\n //\n\n readonly downloadBlobToURLDriverOps: DownloadBlobToURLDriverOps;\n\n //\n // Upload Driver\n //\n\n /**\n * Settings related to the upload driver that actually performs upload and helps render upload\n * and indexing progresses from related pl resources.\n * */\n readonly uploadDriverOps: UploadDriverOps;\n\n //\n // Log streaming ops\n // (static logs are served via the blob driver)\n //\n\n /** Settings related to the streaming log driver */\n readonly logStreamDriverOps: LogsStreamDriverOps;\n\n //\n // LS Driver\n //\n\n /**\n * Callback to access system file open dialog, must be provided by the environment,\n * to allow for {@link showOpenSingleFileDialog} / {@link showOpenMultipleFilesDialog}\n * calls from the UI.\n */\n readonly openFileDialogCallback: OpenFileDialogCallback;\n\n //\n // PFrame Driver\n //\n\n /** Settings related to the PFrame driver */\n readonly pFrameDriverOps: PFrameDriverOps;\n\n /**\n * Tuning for the persistent parquet blob cache. Its directory is\n * {@link DriverKitOpsPaths.parquetCachePath}; this carries only the\n * size/eviction knobs.\n */\n readonly parquetCacheOps: ParquetCacheOps;\n};\n\nexport type DriverKitOps = DriverKitOpsPaths & DriverKitOpsSettings;\n\n/** Some defaults fot MiddleLayerOps. */\nexport const DefaultDriverKitOpsSettings: Pick<\n DriverKitOpsSettings,\n | \"logger\"\n | \"blobDriverOps\"\n | \"frontendDownloadDriverOps\"\n | \"downloadBlobToURLDriverOps\"\n | \"uploadDriverOps\"\n | \"logStreamDriverOps\"\n | \"pFrameDriverOps\"\n | \"parquetCacheOps\"\n> = {\n logger: new ConsoleLoggerAdapter(),\n blobDriverOps: {\n cacheSoftSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n rangesCacheMaxSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n nConcurrentDownloads: 10,\n },\n frontendDownloadDriverOps: {\n cacheSoftSizeBytes: 1 * 1024 * 1024 * 1024, // 1 GB\n withGunzip: true,\n nConcurrentDownloads: 50,\n },\n downloadBlobToURLDriverOps: {\n cacheSoftSizeBytes: 1 * 1024 * 1024 * 1024, // 1 GB\n nConcurrentDownloads: 10,\n },\n uploadDriverOps: {\n nConcurrentPartUploads: 10,\n nConcurrentGetProgresses: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000,\n },\n logStreamDriverOps: {\n nConcurrentGetLogs: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000,\n },\n pFrameDriverOps: PFrameDriverOpsDefaults,\n parquetCacheOps: {\n maxSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n admissionFraction: 0.2, // a single file may occupy at most 20% of the budget\n maxFilesTracked: 50_000, // ghost (previously-evicted) files remembered to guide readmission\n },\n};\n\nexport function DefaultDriverKitOpsPaths(\n workDir: string,\n): Pick<\n DriverKitOpsPaths,\n | \"blobDownloadPath\"\n | \"blobDownloadRangesCachePath\"\n | \"downloadBlobToURLPath\"\n | \"pframesSpillPath\"\n | \"parquetCachePath\"\n> {\n return {\n blobDownloadPath: path.join(workDir, \"download\"),\n blobDownloadRangesCachePath: path.join(workDir, \"downloadRangesCache\"),\n downloadBlobToURLPath: path.join(workDir, \"downloadToURL\"),\n pframesSpillPath: path.join(workDir, \"pframes\"),\n parquetCachePath: path.join(workDir, \"parquetCache\"),\n };\n}\n\n/** Fields with default values are marked as optional here. */\nexport type DriverKitOpsConstructor = Omit<\n DriverKitOpsSettings,\n keyof typeof DefaultDriverKitOpsSettings\n> &\n Partial<typeof DefaultDriverKitOpsSettings> &\n Omit<DriverKitOpsPaths, keyof ReturnType<typeof DefaultDriverKitOpsPaths>> &\n Partial<ReturnType<typeof DefaultDriverKitOpsPaths>>;\n\nexport type MiddleLayerOpsPaths = DriverKitOpsPaths & {\n /** Common root where to put frontend code. */\n readonly frontendDownloadPath: string;\n};\n\n/** Debug options for middle layer. */\nexport type MiddleLayerDebugOptions = {\n /** If true, will dump initial tree state to the file with root resource id as name. */\n dumpInitialTreeState: boolean;\n};\n\n/** Configuration controlling different aspects of middle layer behaviour. */\nexport type MiddleLayerOpsSettings = DriverKitOpsSettings & {\n /** Debug options. */\n readonly debugOps: MiddleLayerDebugOptions;\n\n /** Contain temporal options controlling how often should pl trees be\n * synchronized with the pl server. */\n readonly defaultTreeOptions: TemporalSynchronizedTreeOps;\n\n /** Defines interval in milliseconds for running periodic project maintenance job.\n * Project maintenance includes background staging rendering and cached outputs cleanup. */\n readonly projectRefreshInterval: number;\n\n /** How often to check for dev block updates */\n readonly devBlockUpdateRecheckInterval: number;\n\n /** Prioritize this channel if update is available in this block */\n readonly preferredUpdateChannel?: string;\n};\n\nexport type MiddleLayerOps = MiddleLayerOpsSettings & MiddleLayerOpsPaths;\n\n/** Some defaults fot MiddleLayerOps. */\nexport const DefaultMiddleLayerOpsSettings: Pick<\n MiddleLayerOps,\n | keyof typeof DefaultDriverKitOpsSettings\n | \"defaultTreeOptions\"\n | \"projectRefreshInterval\"\n | \"devBlockUpdateRecheckInterval\"\n | \"debugOps\"\n> = {\n ...DefaultDriverKitOpsSettings,\n defaultTreeOptions: {\n pollingInterval: 200,\n stopPollingDelay: 2500,\n initialTreeLoadingTimeout: 100 * 60 * 60 * 1000, // disable timeout for loading project tree (100 hours)\n },\n debugOps: {\n dumpInitialTreeState: false,\n },\n devBlockUpdateRecheckInterval: 1000,\n projectRefreshInterval: 2000,\n};\n\nexport function DefaultMiddleLayerOpsPaths(\n workDir: string,\n): Pick<\n MiddleLayerOpsPaths,\n keyof ReturnType<typeof DefaultDriverKitOpsPaths> | \"frontendDownloadPath\"\n> {\n return {\n ...DefaultDriverKitOpsPaths(workDir),\n frontendDownloadPath: path.join(workDir, \"frontend\"),\n };\n}\n\nexport type MiddleLayerOpsConstructor = Omit<\n MiddleLayerOpsSettings,\n keyof typeof DefaultMiddleLayerOpsSettings\n> &\n Partial<typeof DefaultMiddleLayerOpsSettings> &\n Omit<MiddleLayerOpsPaths, keyof Awaited<ReturnType<typeof DefaultMiddleLayerOpsPaths>>> &\n Partial<Awaited<ReturnType<typeof DefaultMiddleLayerOpsPaths>>>;\n"],"mappings":";;;;;;AAoJA,MAAa,8BAUT;CACF,QAAQ,IAAI,sBAAsB;CAClC,eAAe;EACb,oBAAoB,IAAI,OAAO,OAAO;EACtC,yBAAyB,IAAI,OAAO,OAAO;EAC3C,sBAAsB;EACvB;CACD,2BAA2B;EACzB,oBAAoB,IAAI,OAAO,OAAO;EACtC,YAAY;EACZ,sBAAsB;EACvB;CACD,4BAA4B;EAC1B,oBAAoB,IAAI,OAAO,OAAO;EACtC,sBAAsB;EACvB;CACD,iBAAiB;EACf,wBAAwB;EACxB,0BAA0B;EAC1B,iBAAiB;EACjB,kBAAkB;EACnB;CACD,oBAAoB;EAClB,oBAAoB;EACpB,iBAAiB;EACjB,kBAAkB;EACnB;CACD,iBAAiB;CACjB,iBAAiB;EACf,cAAc,IAAI,OAAO,OAAO;EAChC,mBAAmB;EACnB,iBAAiB;EAClB;CACF;AAED,SAAgB,yBACd,SAQA;AACA,QAAO;EACL,kBAAkB,KAAK,KAAK,SAAS,WAAW;EAChD,6BAA6B,KAAK,KAAK,SAAS,sBAAsB;EACtE,uBAAuB,KAAK,KAAK,SAAS,gBAAgB;EAC1D,kBAAkB,KAAK,KAAK,SAAS,UAAU;EAC/C,kBAAkB,KAAK,KAAK,SAAS,eAAe;EACrD;;;AA8CH,MAAa,gCAOT;CACF,GAAG;CACH,oBAAoB;EAClB,iBAAiB;EACjB,kBAAkB;EAClB,2BAA2B,MAAW,KAAK;EAC5C;CACD,UAAU,EACR,sBAAsB,OACvB;CACD,+BAA+B;CAC/B,wBAAwB;CACzB;AAED,SAAgB,2BACd,SAIA;AACA,QAAO;EACL,GAAG,yBAAyB,QAAQ;EACpC,sBAAsB,KAAK,KAAK,SAAS,WAAW;EACrD"}
|
|
1
|
+
{"version":3,"file":"ops.js","names":[],"sources":["../../src/middle_layer/ops.ts"],"sourcesContent":["import type { TemporalSynchronizedTreeOps } from \"./types\";\nimport type {\n DownloadBlobToURLDriverOps,\n DownloadDriverOps,\n DownloadUrlDriverOps,\n OpenFileDialogCallback,\n VirtualLocalStorageSpec,\n} from \"@milaboratories/pl-drivers\";\nimport type { UploadDriverOps } from \"@milaboratories/pl-drivers\";\nimport type { LogsStreamDriverOps } from \"@milaboratories/pl-drivers\";\nimport type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport type { LocalStorageProjection } from \"@milaboratories/pl-drivers\";\nimport path from \"node:path\";\nimport { PFrameDriverOpsDefaults, type PFrameDriverOps, type ParquetCacheOps } from \"../pool\";\n\n/** Paths part of {@link DriverKitOps}. */\nexport type DriverKitOpsPaths = {\n /** Common root where to put downloaded blobs / downloaded blob cache */\n readonly blobDownloadPath: string;\n\n /** Common root for a cache for range queries. */\n readonly blobDownloadRangesCachePath: string;\n\n /** Common root where to put downloaded blobs with */\n readonly downloadBlobToURLPath: string;\n\n /**\n * List of pl storages that have projections in local file system.\n *\n * This option affect two drivers:\n *\n * (1) LS driver generates \"index\" handles instead of \"upload\" for paths inside those locations\n *\n * (2) Download driver directly serves content retrieval requests for blobs from listed storages,\n * and don't apply any caching for such blobs (i.e. preventing duplication of files for Downloaded\n * type handles, making OnDemand and Downloaded handles equivalent)\n *\n * */\n readonly localProjections: LocalStorageProjection[];\n\n /**\n * List of virtual storages that will allow homogeneous access to local FSs through LS API.\n * If undefined, default list will be created.\n * */\n readonly virtualLocalStoragesOverride?: VirtualLocalStorageSpec[];\n\n /** Path to the directory where pframes will spill temporary files and store materialized views */\n readonly pframesSpillPath: string;\n\n /**\n * Path to the directory backing the persistent parquet blob cache. Unlike\n * {@link pframesSpillPath} this directory is NOT emptied on startup - the cache\n * (and its lifetime counters) is meant to survive restarts.\n */\n readonly parquetCachePath: string;\n};\n\n/** Options required to initialize full set of middle layer driver kit */\nexport type DriverKitOpsSettings = {\n //\n // Common\n //\n\n readonly logger: MiLogger;\n\n //\n // Signer\n //\n\n /**\n * Local secret, that is used to sign and verify different pieces of information\n * that can be used to access local data, like local paths for ongoing uploads.\n *\n * Use {@link MiddleLayer.generateLocalSecret} to generate sufficiently random string.\n * */\n readonly localSecret: string;\n\n //\n // Blob Driver\n //\n\n /**\n * Settings related to the download driver making operations with blobs. This driver is also used\n * to download logs when source process terminates and log terns into a blob\n */\n readonly blobDriverOps: DownloadDriverOps;\n\n //\n // Frontend Driver\n //\n\n /** Settings related to the frontend driver that downloads frontends. */\n readonly frontendDownloadDriverOps: DownloadUrlDriverOps;\n\n //\n // Blob To URL Driver\n //\n\n readonly downloadBlobToURLDriverOps: DownloadBlobToURLDriverOps;\n\n //\n // Upload Driver\n //\n\n /**\n * Settings related to the upload driver that actually performs upload and helps render upload\n * and indexing progresses from related pl resources.\n * */\n readonly uploadDriverOps: UploadDriverOps;\n\n //\n // Log streaming ops\n // (static logs are served via the blob driver)\n //\n\n /** Settings related to the streaming log driver */\n readonly logStreamDriverOps: LogsStreamDriverOps;\n\n //\n // LS Driver\n //\n\n /**\n * Callback to access system file open dialog, must be provided by the environment,\n * to allow for {@link showOpenSingleFileDialog} / {@link showOpenMultipleFilesDialog}\n * calls from the UI.\n */\n readonly openFileDialogCallback: OpenFileDialogCallback;\n\n //\n // PFrame Driver\n //\n\n /** Settings related to the PFrame driver */\n readonly pFrameDriverOps: PFrameDriverOps;\n\n /**\n * Tuning for the persistent parquet blob cache. Its directory is\n * {@link DriverKitOpsPaths.parquetCachePath}; this carries only the\n * size/eviction knobs.\n */\n readonly parquetCacheOps: ParquetCacheOps;\n};\n\nexport type DriverKitOps = DriverKitOpsPaths & DriverKitOpsSettings;\n\n/** Some defaults fot MiddleLayerOps. */\nexport const DefaultDriverKitOpsSettings: Pick<\n DriverKitOpsSettings,\n | \"logger\"\n | \"blobDriverOps\"\n | \"frontendDownloadDriverOps\"\n | \"downloadBlobToURLDriverOps\"\n | \"uploadDriverOps\"\n | \"logStreamDriverOps\"\n | \"pFrameDriverOps\"\n | \"parquetCacheOps\"\n> = {\n logger: new ConsoleLoggerAdapter(),\n blobDriverOps: {\n cacheSoftSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n rangesCacheMaxSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n nConcurrentDownloads: 10,\n },\n frontendDownloadDriverOps: {\n cacheSoftSizeBytes: 1 * 1024 * 1024 * 1024, // 1 GB\n withGunzip: true,\n nConcurrentDownloads: 50,\n },\n downloadBlobToURLDriverOps: {\n cacheSoftSizeBytes: 1 * 1024 * 1024 * 1024, // 1 GB\n nConcurrentDownloads: 10,\n },\n uploadDriverOps: {\n nConcurrentPartUploads: 10,\n nConcurrentGetProgresses: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000,\n },\n logStreamDriverOps: {\n nConcurrentGetLogs: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000,\n },\n pFrameDriverOps: PFrameDriverOpsDefaults,\n parquetCacheOps: {\n maxSizeBytes: 8 * 1024 * 1024 * 1024, // 8 GB\n admissionFraction: 0.2, // a single file may occupy at most 20% of the budget\n maxFilesTracked: 50_000, // ghost (previously-evicted) files remembered to guide readmission\n },\n};\n\nexport function DefaultDriverKitOpsPaths(\n workDir: string,\n): Pick<\n DriverKitOpsPaths,\n | \"blobDownloadPath\"\n | \"blobDownloadRangesCachePath\"\n | \"downloadBlobToURLPath\"\n | \"pframesSpillPath\"\n | \"parquetCachePath\"\n> {\n return {\n blobDownloadPath: path.join(workDir, \"download\"),\n blobDownloadRangesCachePath: path.join(workDir, \"downloadRangesCache\"),\n downloadBlobToURLPath: path.join(workDir, \"downloadToURL\"),\n pframesSpillPath: path.join(workDir, \"pframes\"),\n parquetCachePath: path.join(workDir, \"parquetCache\"),\n };\n}\n\n/** Fields with default values are marked as optional here. */\nexport type DriverKitOpsConstructor = Omit<\n DriverKitOpsSettings,\n keyof typeof DefaultDriverKitOpsSettings\n> &\n Partial<typeof DefaultDriverKitOpsSettings> &\n Omit<DriverKitOpsPaths, keyof ReturnType<typeof DefaultDriverKitOpsPaths>> &\n Partial<ReturnType<typeof DefaultDriverKitOpsPaths>>;\n\nexport type MiddleLayerOpsPaths = DriverKitOpsPaths & {\n /** Common root where to put frontend code. */\n readonly frontendDownloadPath: string;\n};\n\n/** Debug options for middle layer. */\nexport type MiddleLayerDebugOptions = {\n /** If true, will dump initial tree state to the file with root resource id as name. */\n dumpInitialTreeState: boolean;\n};\n\n/** Configuration controlling different aspects of middle layer behaviour. */\nexport type MiddleLayerOpsSettings = DriverKitOpsSettings & {\n /** Debug options. */\n readonly debugOps: MiddleLayerDebugOptions;\n\n /** Contain temporal options controlling how often should pl trees be\n * synchronized with the pl server. */\n readonly defaultTreeOptions: TemporalSynchronizedTreeOps;\n\n /** Defines interval in milliseconds for running periodic project maintenance job.\n * Project maintenance includes background staging rendering and cached outputs cleanup. */\n readonly projectRefreshInterval: number;\n\n /** How often to check for dev block updates */\n readonly devBlockUpdateRecheckInterval: number;\n\n /** Prioritize this channel if update is available in this block */\n readonly preferredUpdateChannel?: string;\n};\n\nexport type MiddleLayerOps = MiddleLayerOpsSettings & MiddleLayerOpsPaths;\n\n/** Some defaults fot MiddleLayerOps. */\nexport const DefaultMiddleLayerOpsSettings: Pick<\n MiddleLayerOps,\n | keyof typeof DefaultDriverKitOpsSettings\n | \"defaultTreeOptions\"\n | \"projectRefreshInterval\"\n | \"devBlockUpdateRecheckInterval\"\n | \"debugOps\"\n> = {\n ...DefaultDriverKitOpsSettings,\n defaultTreeOptions: {\n pollingInterval: 200,\n stopPollingDelay: 2500,\n initialTreeLoadingTimeout: 100 * 60 * 60 * 1000, // disable timeout for loading project tree (100 hours)\n },\n debugOps: {\n dumpInitialTreeState: false,\n },\n devBlockUpdateRecheckInterval: 1000,\n projectRefreshInterval: 2000,\n};\n\nexport function DefaultMiddleLayerOpsPaths(\n workDir: string,\n): Pick<\n MiddleLayerOpsPaths,\n keyof ReturnType<typeof DefaultDriverKitOpsPaths> | \"frontendDownloadPath\"\n> {\n return {\n ...DefaultDriverKitOpsPaths(workDir),\n frontendDownloadPath: path.join(workDir, \"frontend\"),\n };\n}\n\nexport type MiddleLayerOpsConstructor = Omit<\n MiddleLayerOpsSettings,\n keyof typeof DefaultMiddleLayerOpsSettings\n> &\n Partial<typeof DefaultMiddleLayerOpsSettings> &\n Omit<MiddleLayerOpsPaths, keyof Awaited<ReturnType<typeof DefaultMiddleLayerOpsPaths>>> &\n Partial<Awaited<ReturnType<typeof DefaultMiddleLayerOpsPaths>>>;\n"],"mappings":";;;;;;AAoJA,MAAa,8BAUT;CACF,QAAQ,IAAI,qBAAqB;CACjC,eAAe;EACb,oBAAoB,IAAI,OAAO,OAAO;EACtC,yBAAyB,IAAI,OAAO,OAAO;EAC3C,sBAAsB;CACxB;CACA,2BAA2B;EACzB,oBAAoB,IAAI,OAAO,OAAO;EACtC,YAAY;EACZ,sBAAsB;CACxB;CACA,4BAA4B;EAC1B,oBAAoB,IAAI,OAAO,OAAO;EACtC,sBAAsB;CACxB;CACA,iBAAiB;EACf,wBAAwB;EACxB,0BAA0B;EAC1B,iBAAiB;EACjB,kBAAkB;CACpB;CACA,oBAAoB;EAClB,oBAAoB;EACpB,iBAAiB;EACjB,kBAAkB;CACpB;CACA,iBAAiB;CACjB,iBAAiB;EACf,cAAc,IAAI,OAAO,OAAO;EAChC,mBAAmB;EACnB,iBAAiB;CACnB;AACF;AAEA,SAAgB,yBACd,SAQA;CACA,OAAO;EACL,kBAAkB,KAAK,KAAK,SAAS,UAAU;EAC/C,6BAA6B,KAAK,KAAK,SAAS,qBAAqB;EACrE,uBAAuB,KAAK,KAAK,SAAS,eAAe;EACzD,kBAAkB,KAAK,KAAK,SAAS,SAAS;EAC9C,kBAAkB,KAAK,KAAK,SAAS,cAAc;CACrD;AACF;;AA6CA,MAAa,gCAOT;CACF,GAAG;CACH,oBAAoB;EAClB,iBAAiB;EACjB,kBAAkB;EAClB,2BAA2B,MAAW,KAAK;CAC7C;CACA,UAAU,EACR,sBAAsB,MACxB;CACA,+BAA+B;CAC/B,wBAAwB;AAC1B;AAEA,SAAgB,2BACd,SAIA;CACA,OAAO;EACL,GAAG,yBAAyB,OAAO;EACnC,sBAAsB,KAAK,KAAK,SAAS,UAAU;CACrD;AACF"}
|
|
@@ -12,13 +12,13 @@ const require_template_cache = require("../mutator/template/template_cache.cjs")
|
|
|
12
12
|
let _platforma_sdk_model = require("@platforma-sdk/model");
|
|
13
13
|
let _milaboratories_ts_helpers = require("@milaboratories/ts-helpers");
|
|
14
14
|
let node_fs_promises = require("node:fs/promises");
|
|
15
|
-
node_fs_promises = require_runtime.__toESM(node_fs_promises);
|
|
15
|
+
node_fs_promises = require_runtime.__toESM(node_fs_promises, 1);
|
|
16
16
|
let _milaboratories_pl_client = require("@milaboratories/pl-client");
|
|
17
17
|
let _milaboratories_pl_tree = require("@milaboratories/pl-tree");
|
|
18
18
|
let _milaboratories_computable = require("@milaboratories/computable");
|
|
19
19
|
let node_crypto = require("node:crypto");
|
|
20
20
|
let canonicalize = require("canonicalize");
|
|
21
|
-
canonicalize = require_runtime.__toESM(canonicalize);
|
|
21
|
+
canonicalize = require_runtime.__toESM(canonicalize, 1);
|
|
22
22
|
let node_timers_promises = require("node:timers/promises");
|
|
23
23
|
//#region src/middle_layer/project.ts
|
|
24
24
|
function stringifyForDump(object) {
|
|
@@ -31,6 +31,10 @@ function stringifyForDump(object) {
|
|
|
31
31
|
}
|
|
32
32
|
/** Data access object, to manipulate and read single opened (!) project data. */
|
|
33
33
|
var Project = class Project {
|
|
34
|
+
env;
|
|
35
|
+
id;
|
|
36
|
+
rid;
|
|
37
|
+
projectTree;
|
|
34
38
|
/** Data for the left panel, contain basic information about block status. */
|
|
35
39
|
overview;
|
|
36
40
|
overviewLight;
|
|
@@ -569,5 +573,8 @@ function throwIfMissingServerCapabilities(pl, requiredCapabilities) {
|
|
|
569
573
|
}
|
|
570
574
|
//#endregion
|
|
571
575
|
exports.Project = Project;
|
|
576
|
+
exports.projectTreeFieldFilter = projectTreeFieldFilter;
|
|
577
|
+
exports.projectTreePruning = projectTreePruning;
|
|
578
|
+
exports.projectTreeTraverseStopRules = projectTreeTraverseStopRules;
|
|
572
579
|
|
|
573
580
|
//# sourceMappingURL=project.cjs.map
|