refactor: consolidate authoring binding copies
This commit is contained in:
@@ -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,27 +113,31 @@ 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 {
|
|
||||||
target: copyLocalInputPath(binding.target),
|
|
||||||
value: copyJsonValue(binding.value),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
target: copyLocalInputPath(binding.target),
|
target: copyLocalInputPath(binding.target),
|
||||||
expression: copyInputExpression(binding.expression),
|
value: copyJsonValue(binding.value),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const copyStepInputBinding = (
|
||||||
|
binding: StepInputBinding,
|
||||||
|
): StepInputBinding => {
|
||||||
|
if ("expression" in binding) {
|
||||||
|
return {
|
||||||
|
target: copyLocalInputPath(binding.target),
|
||||||
|
expression: copyInputExpression(binding.expression),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return copyInputBinding(binding);
|
||||||
|
};
|
||||||
|
|
||||||
const copyOutputBinding = (binding: OutputBinding): OutputBinding => ({
|
const copyOutputBinding = (binding: OutputBinding): OutputBinding => ({
|
||||||
source:
|
source:
|
||||||
typeof binding.source === "string"
|
typeof binding.source === "string"
|
||||||
|
|||||||
Reference in New Issue
Block a user