feat: add selected-step binding client
This commit is contained in:
@@ -69,6 +69,8 @@ const authoringClient: DraftAuthoringClient = {
|
||||
createFromCapability: vi.fn(),
|
||||
addCapabilityStep: vi.fn(),
|
||||
updateCapabilityStep: vi.fn(),
|
||||
setStepInputBindings: vi.fn(),
|
||||
setStepOutputBindings: vi.fn(),
|
||||
setRoute: vi.fn(),
|
||||
validate: vi.fn(),
|
||||
};
|
||||
|
||||
@@ -55,6 +55,8 @@ const createEmpty = vi.fn<DraftAuthoringClient["createEmpty"]>();
|
||||
const createFromCapability = vi.fn<DraftAuthoringClient["createFromCapability"]>();
|
||||
const addCapabilityStep = vi.fn<DraftAuthoringClient["addCapabilityStep"]>();
|
||||
const updateCapabilityStep = vi.fn<DraftAuthoringClient["updateCapabilityStep"]>();
|
||||
const setStepInputBindings = vi.fn<DraftAuthoringClient["setStepInputBindings"]>();
|
||||
const setStepOutputBindings = vi.fn<DraftAuthoringClient["setStepOutputBindings"]>();
|
||||
const setRoute = vi.fn<DraftAuthoringClient["setRoute"]>();
|
||||
const validate = vi.fn<DraftAuthoringClient["validate"]>();
|
||||
const list = vi.fn<DraftWorkspaceClient["list"]>();
|
||||
@@ -64,6 +66,8 @@ const authoringClient = {
|
||||
createFromCapability,
|
||||
addCapabilityStep,
|
||||
updateCapabilityStep,
|
||||
setStepInputBindings,
|
||||
setStepOutputBindings,
|
||||
setRoute,
|
||||
validate,
|
||||
} satisfies DraftAuthoringClient;
|
||||
|
||||
@@ -9,6 +9,8 @@ import {
|
||||
type InputPathBinding,
|
||||
type InputValueBinding,
|
||||
type SetDraftRouteInput,
|
||||
type SetStepInputBindingsInput,
|
||||
type SetStepOutputBindingsInput,
|
||||
type UpdateCapabilityStepInput,
|
||||
} from "./draft-workspace-models.js";
|
||||
import { createDraftAuthoringClient } from "./draft-authoring-client.js";
|
||||
@@ -258,4 +260,135 @@ describe("DraftAuthoringClient", () => {
|
||||
/DraftWorkspace is malformed/,
|
||||
);
|
||||
});
|
||||
|
||||
it("sets input bindings with canonical structural paths and preserves null values", async () => {
|
||||
const { executor: writeExecutor, run } = createExecutor();
|
||||
const client = createDraftAuthoringClient(writeExecutor);
|
||||
const bindings = [
|
||||
{
|
||||
path: { root: "context", parts: ["request", "text"] },
|
||||
target: { root: "local", parts: ["text"] },
|
||||
},
|
||||
{
|
||||
target: { root: "local", parts: ["optional"] },
|
||||
value: null,
|
||||
},
|
||||
] satisfies SetStepInputBindingsInput["bindings"];
|
||||
const input = {
|
||||
workspaceId: " report ",
|
||||
revision: 7,
|
||||
stepId: " render ",
|
||||
bindings,
|
||||
} satisfies SetStepInputBindingsInput;
|
||||
|
||||
await expect(client.setStepInputBindings(input)).resolves.toEqual(canonicalWorkspace);
|
||||
|
||||
expect(run).toHaveBeenCalledWith(
|
||||
"workflow.draft_workspaces.set_step_input_bindings",
|
||||
{
|
||||
workspace_id: "report",
|
||||
revision: 7,
|
||||
step_id: "render",
|
||||
bindings,
|
||||
},
|
||||
decodeDraftWorkspace,
|
||||
);
|
||||
bindings.splice(0, bindings.length);
|
||||
expect(run).toHaveBeenCalledWith(
|
||||
"workflow.draft_workspaces.set_step_input_bindings",
|
||||
{
|
||||
workspace_id: "report",
|
||||
revision: 7,
|
||||
step_id: "render",
|
||||
bindings: [
|
||||
{
|
||||
path: { root: "context", parts: ["request", "text"] },
|
||||
target: { root: "local", parts: ["text"] },
|
||||
},
|
||||
{
|
||||
target: { root: "local", parts: ["optional"] },
|
||||
value: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
decodeDraftWorkspace,
|
||||
);
|
||||
});
|
||||
|
||||
it("sets output bindings with an exact ordered copy, including empty lists", async () => {
|
||||
const { executor: writeExecutor, run } = createExecutor();
|
||||
const client = createDraftAuthoringClient(writeExecutor);
|
||||
const bindings = [
|
||||
{ source: "text", target: "state.report" },
|
||||
{ source: "text", target: "state.audit.latest" },
|
||||
] satisfies SetStepOutputBindingsInput["bindings"];
|
||||
const input = {
|
||||
workspaceId: "report",
|
||||
revision: 7,
|
||||
stepId: "render",
|
||||
bindings,
|
||||
} satisfies SetStepOutputBindingsInput;
|
||||
|
||||
await client.setStepOutputBindings(input);
|
||||
expect(run).toHaveBeenCalledWith(
|
||||
"workflow.draft_workspaces.set_step_output_bindings",
|
||||
{
|
||||
workspace_id: "report",
|
||||
revision: 7,
|
||||
step_id: "render",
|
||||
bindings: [
|
||||
{ source: "text", target: "state.report" },
|
||||
{ source: "text", target: "state.audit.latest" },
|
||||
],
|
||||
},
|
||||
decodeDraftWorkspace,
|
||||
);
|
||||
bindings.splice(0, bindings.length);
|
||||
expect(run).toHaveBeenCalledWith(
|
||||
"workflow.draft_workspaces.set_step_output_bindings",
|
||||
{
|
||||
workspace_id: "report",
|
||||
revision: 7,
|
||||
step_id: "render",
|
||||
bindings: [
|
||||
{ source: "text", target: "state.report" },
|
||||
{ source: "text", target: "state.audit.latest" },
|
||||
],
|
||||
},
|
||||
decodeDraftWorkspace,
|
||||
);
|
||||
|
||||
await client.setStepOutputBindings({ ...input, bindings: [] });
|
||||
expect(run).toHaveBeenLastCalledWith(
|
||||
"workflow.draft_workspaces.set_step_output_bindings",
|
||||
{
|
||||
workspace_id: "report",
|
||||
revision: 7,
|
||||
step_id: "render",
|
||||
bindings: [],
|
||||
},
|
||||
decodeDraftWorkspace,
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects blank identifiers for focused binding methods before transport", async () => {
|
||||
const { executor: writeExecutor, run } = createExecutor();
|
||||
const client = createDraftAuthoringClient(writeExecutor);
|
||||
const input = {
|
||||
workspaceId: "report",
|
||||
revision: 7,
|
||||
stepId: "render",
|
||||
bindings: [],
|
||||
} satisfies SetStepOutputBindingsInput;
|
||||
|
||||
await expect(client.setStepInputBindings({ ...input, workspaceId: " " })).rejects.toMatchObject({
|
||||
kind: "operation",
|
||||
operation: "workflow.draft_workspaces.set_step_input_bindings",
|
||||
});
|
||||
await expect(client.setStepOutputBindings({ ...input, stepId: "\t" })).rejects.toMatchObject({
|
||||
kind: "operation",
|
||||
operation: "workflow.draft_workspaces.set_step_output_bindings",
|
||||
});
|
||||
expect(run).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,7 +6,10 @@ import {
|
||||
type CreateFromCapabilityInput,
|
||||
type DraftWorkspace,
|
||||
type InputBinding,
|
||||
type OutputBinding,
|
||||
type SetDraftRouteInput,
|
||||
type SetStepInputBindingsInput,
|
||||
type SetStepOutputBindingsInput,
|
||||
type UpdateCapabilityStepInput,
|
||||
} from "./draft-workspace-models.js";
|
||||
import { ConsoleClientError } from "./errors.js";
|
||||
@@ -17,6 +20,8 @@ export interface DraftAuthoringClient {
|
||||
createFromCapability(input: CreateFromCapabilityInput): Promise<DraftWorkspace>;
|
||||
addCapabilityStep(input: AddCapabilityStepInput): Promise<DraftWorkspace>;
|
||||
updateCapabilityStep(input: UpdateCapabilityStepInput): Promise<DraftWorkspace>;
|
||||
setStepInputBindings(input: SetStepInputBindingsInput): Promise<DraftWorkspace>;
|
||||
setStepOutputBindings(input: SetStepOutputBindingsInput): Promise<DraftWorkspace>;
|
||||
setRoute(input: SetDraftRouteInput): Promise<DraftWorkspace>;
|
||||
validate(workspaceId: string): Promise<DraftWorkspace>;
|
||||
}
|
||||
@@ -51,9 +56,9 @@ const ifDefined = <T>(
|
||||
if (value !== undefined) target[key] = value;
|
||||
};
|
||||
|
||||
const copyBindings = (
|
||||
bindings: ReadonlyArray<InputBinding> | null | undefined,
|
||||
): InputBinding[] | null | undefined =>
|
||||
const copyBindings = <T>(
|
||||
bindings: ReadonlyArray<T> | null | undefined,
|
||||
): T[] | null | undefined =>
|
||||
bindings === undefined || bindings === null ? bindings : [...bindings];
|
||||
|
||||
export const createDraftAuthoringClient = (
|
||||
@@ -147,6 +152,34 @@ export const createDraftAuthoringClient = (
|
||||
);
|
||||
},
|
||||
|
||||
setStepInputBindings: async (input) => {
|
||||
const operation = "workflow.draft_workspaces.set_step_input_bindings";
|
||||
return executor.run(
|
||||
operation,
|
||||
{
|
||||
workspace_id: requireIdentifier(operation, input.workspaceId, "workspace id"),
|
||||
revision: input.revision,
|
||||
step_id: requireIdentifier(operation, input.stepId, "step id"),
|
||||
bindings: copyBindings<InputBinding>(input.bindings),
|
||||
},
|
||||
decodeDraftWorkspace,
|
||||
);
|
||||
},
|
||||
|
||||
setStepOutputBindings: async (input) => {
|
||||
const operation = "workflow.draft_workspaces.set_step_output_bindings";
|
||||
return executor.run(
|
||||
operation,
|
||||
{
|
||||
workspace_id: requireIdentifier(operation, input.workspaceId, "workspace id"),
|
||||
revision: input.revision,
|
||||
step_id: requireIdentifier(operation, input.stepId, "step id"),
|
||||
bindings: copyBindings<OutputBinding>(input.bindings),
|
||||
},
|
||||
decodeDraftWorkspace,
|
||||
);
|
||||
},
|
||||
|
||||
setRoute: async (input) => {
|
||||
const operation = "workflow.draft_workspaces.set_route";
|
||||
return executor.run(
|
||||
|
||||
@@ -95,6 +95,8 @@ const authoringClient: DraftAuthoringClient = {
|
||||
createFromCapability: vi.fn(),
|
||||
addCapabilityStep: vi.fn(),
|
||||
updateCapabilityStep: vi.fn(),
|
||||
setStepInputBindings: vi.fn(),
|
||||
setStepOutputBindings: vi.fn(),
|
||||
setRoute: vi.fn(),
|
||||
validate: vi.fn(),
|
||||
};
|
||||
|
||||
@@ -67,6 +67,8 @@ const authoringClient: DraftAuthoringClient = {
|
||||
createFromCapability: vi.fn(),
|
||||
addCapabilityStep: vi.fn(),
|
||||
updateCapabilityStep: vi.fn(),
|
||||
setStepInputBindings: vi.fn(),
|
||||
setStepOutputBindings: vi.fn(),
|
||||
setRoute: vi.fn(),
|
||||
validate: vi.fn(),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user