refactor: consolidate authoring binding copies

This commit is contained in:
lda
2026-08-29 21:23:50 +07:00 Verified
parent 0570ef8a78
commit f64e843c3d
4 changed files with 31 additions and 34 deletions
-3
View File
@@ -134,7 +134,6 @@ def _analyze(workflow: Workflow) -> _ContextAnalysis:
fields_by_node[node_id] = _available_fields( fields_by_node[node_id] = _available_fields(
workflow, workflow,
foreach_nodes, foreach_nodes,
node_id,
scopes, scopes,
scopes_by_node, scopes_by_node,
) )
@@ -144,11 +143,9 @@ def _analyze(workflow: Workflow) -> _ContextAnalysis:
def _available_fields( def _available_fields(
workflow: Workflow, workflow: Workflow,
foreach_nodes: Mapping[str, ForeachNode], foreach_nodes: Mapping[str, ForeachNode],
node_id: str,
scopes: set[FrameScope], scopes: set[FrameScope],
scopes_by_node: Mapping[str, set[FrameScope]], scopes_by_node: Mapping[str, set[FrameScope]],
) -> tuple[ContextFieldAvailability, ...]: ) -> tuple[ContextFieldAvailability, ...]:
del node_id
fields_by_name: dict[str, ContextFieldContract] = {} fields_by_name: dict[str, ContextFieldContract] = {}
scopes_by_field: dict[str, set[FrameScope]] = {} scopes_by_field: dict[str, set[FrameScope]] = {}
for scope in sorted(scopes, key=lambda value: value or ""): for scope in sorted(scopes, key=lambda value: value or ""):
@@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useConsoleWorkspace } from "../context.js"; import { useConsoleWorkspace } from "../context.js";
import { import {
createDraftAuthoringClient, createDraftAuthoringClient,
copyInputBinding,
copyStepInputBinding, copyStepInputBinding,
type DraftAuthoringClient, type DraftAuthoringClient,
} from "../domain/draft-authoring-client.js"; } from "../domain/draft-authoring-client.js";
@@ -193,26 +194,7 @@ const copyOutputBindings = (
const copyWorkflowOutputBindings = ( const copyWorkflowOutputBindings = (
bindings: ReadonlyArray<InputBinding>, bindings: ReadonlyArray<InputBinding>,
): ReadonlyArray<InputBinding> => bindings.map((binding) => ( ): ReadonlyArray<InputBinding> => bindings.map(copyInputBinding);
"path" in binding
? {
path:
typeof binding.path === "string"
? binding.path
: { root: binding.path.root, parts: [...binding.path.parts] },
target:
typeof binding.target === "string"
? binding.target
: { root: binding.target.root, parts: [...binding.target.parts] },
}
: {
value: copyJson(binding.value),
target:
typeof binding.target === "string"
? binding.target
: { root: binding.target.root, parts: [...binding.target.parts] },
}
));
const copyContractPatch = (patch: WorkflowContractPatch): WorkflowContractPatch => ({ const copyContractPatch = (patch: WorkflowContractPatch): WorkflowContractPatch => ({
...(patch.inputSchema !== undefined ...(patch.inputSchema !== undefined
@@ -18,7 +18,7 @@ import {
type SetWorkflowStartInput, type SetWorkflowStartInput,
type UpdateCapabilityStepInput, type UpdateCapabilityStepInput,
} from "./draft-workspace-models.js"; } from "./draft-workspace-models.js";
import { createDraftAuthoringClient } from "./draft-authoring-client.js"; import { copyInputBinding, createDraftAuthoringClient } from "./draft-authoring-client.js";
import type { ConsoleWriteExecutor } from "./write-executor.js"; import type { ConsoleWriteExecutor } from "./write-executor.js";
const canonicalWorkspace = { const canonicalWorkspace = {
@@ -65,6 +65,19 @@ const createExecutor = () => {
}; };
describe("DraftAuthoringClient", () => { describe("DraftAuthoringClient", () => {
it("copies workflow-compatible input bindings without sharing nested paths", () => {
const binding = {
path: { root: "state" as const, parts: ["report"] },
target: { root: "local" as const, parts: ["text"] },
} satisfies InputBinding;
const copied = copyInputBinding(binding);
expect(copied).not.toBe(binding);
if (!("path" in copied)) throw new Error("expected a path binding");
expect(copied.path).not.toBe(binding.path);
expect(copied.target).not.toBe(binding.target);
});
it("lowers all six authoring operations and decodes canonical workspaces", async () => { it("lowers all six authoring operations and decodes canonical workspaces", async () => {
const { executor: writeExecutor, run } = createExecutor(); const { executor: writeExecutor, run } = createExecutor();
const client = createDraftAuthoringClient(writeExecutor); const client = createDraftAuthoringClient(writeExecutor);
@@ -5,6 +5,7 @@ import {
type CreateEmptyDraftInput, type CreateEmptyDraftInput,
type CreateFromCapabilityInput, type CreateFromCapabilityInput,
type DraftWorkspace, type DraftWorkspace,
type InputBinding,
type JsonValue, type JsonValue,
type InputExpression, type InputExpression,
type InputPath, type InputPath,
@@ -112,25 +113,29 @@ export const copyInputExpression = (
} }
}; };
export const copyStepInputBinding = ( export const copyInputBinding = (binding: InputBinding): InputBinding => {
binding: StepInputBinding,
): StepInputBinding => {
if ("path" in binding) { if ("path" in binding) {
return { return {
path: copyInputPath(binding.path), path: copyInputPath(binding.path),
target: copyLocalInputPath(binding.target), target: copyLocalInputPath(binding.target),
}; };
} }
if ("value" in binding) {
return { return {
target: copyLocalInputPath(binding.target), target: copyLocalInputPath(binding.target),
value: copyJsonValue(binding.value), value: copyJsonValue(binding.value),
}; };
} };
export const copyStepInputBinding = (
binding: StepInputBinding,
): StepInputBinding => {
if ("expression" in binding) {
return { return {
target: copyLocalInputPath(binding.target), target: copyLocalInputPath(binding.target),
expression: copyInputExpression(binding.expression), expression: copyInputExpression(binding.expression),
}; };
}
return copyInputBinding(binding);
}; };
const copyOutputBinding = (binding: OutputBinding): OutputBinding => ({ const copyOutputBinding = (binding: OutputBinding): OutputBinding => ({