feat: browse authoring contract paths
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
import * as v from "valibot";
|
||||
|
||||
export type AuthoringPathOrigin =
|
||||
| "workflow_input"
|
||||
| "workflow_state"
|
||||
| "runtime_context"
|
||||
| "step_input"
|
||||
| "step_output"
|
||||
| "workflow_output";
|
||||
|
||||
export type AuthoringPathAvailability = "available" | "conditional";
|
||||
|
||||
export type AuthoringPathUse =
|
||||
| "step_input"
|
||||
| "step_output_source"
|
||||
| "state_target"
|
||||
| "workflow_output";
|
||||
|
||||
export type AuthoringPathOption = {
|
||||
readonly path: string;
|
||||
readonly label: string;
|
||||
readonly origin: AuthoringPathOrigin;
|
||||
readonly schema: Readonly<Record<string, unknown>>;
|
||||
readonly required: boolean;
|
||||
readonly availability: AuthoringPathAvailability;
|
||||
readonly uses: ReadonlyArray<AuthoringPathUse>;
|
||||
readonly description?: string | undefined;
|
||||
readonly reason?: string | undefined;
|
||||
};
|
||||
|
||||
export type AuthoringStepContract = {
|
||||
readonly stepId: string;
|
||||
readonly label: string;
|
||||
readonly description?: string | undefined;
|
||||
readonly inputTargets?: ReadonlyArray<AuthoringPathOption> | undefined;
|
||||
readonly outputSources?: ReadonlyArray<AuthoringPathOption> | undefined;
|
||||
readonly outcomes?: ReadonlyArray<string> | undefined;
|
||||
};
|
||||
|
||||
export type AuthoringContractInventory = {
|
||||
readonly workspaceId: string;
|
||||
readonly revision: number;
|
||||
readonly selectedStepId: string | null;
|
||||
readonly readableSources: ReadonlyArray<AuthoringPathOption>;
|
||||
readonly stepInputTargets: ReadonlyArray<AuthoringPathOption>;
|
||||
readonly stepOutputSources: ReadonlyArray<AuthoringPathOption>;
|
||||
readonly stateTargets: ReadonlyArray<AuthoringPathOption>;
|
||||
readonly workflowOutputTargets: ReadonlyArray<AuthoringPathOption>;
|
||||
readonly entrySteps: ReadonlyArray<AuthoringStepContract>;
|
||||
readonly workflowOutcomes: ReadonlyArray<string>;
|
||||
readonly warnings: ReadonlyArray<string>;
|
||||
};
|
||||
|
||||
const JsonObjectSchema = v.record(v.string(), v.unknown());
|
||||
|
||||
const AuthoringPathOriginSchema = v.union([
|
||||
v.literal("workflow_input"),
|
||||
v.literal("workflow_state"),
|
||||
v.literal("runtime_context"),
|
||||
v.literal("step_input"),
|
||||
v.literal("step_output"),
|
||||
v.literal("workflow_output"),
|
||||
]);
|
||||
|
||||
const AuthoringPathAvailabilitySchema = v.union([
|
||||
v.literal("available"),
|
||||
v.literal("conditional"),
|
||||
]);
|
||||
|
||||
const AuthoringPathUseSchema = v.union([
|
||||
v.literal("step_input"),
|
||||
v.literal("step_output_source"),
|
||||
v.literal("state_target"),
|
||||
v.literal("workflow_output"),
|
||||
]);
|
||||
|
||||
const AuthoringPathOptionWireSchema = v.object({
|
||||
path: v.string(),
|
||||
label: v.string(),
|
||||
origin: AuthoringPathOriginSchema,
|
||||
schema: JsonObjectSchema,
|
||||
required: v.boolean(),
|
||||
availability: AuthoringPathAvailabilitySchema,
|
||||
uses: v.array(AuthoringPathUseSchema),
|
||||
description: v.optional(v.string()),
|
||||
reason: v.optional(v.string()),
|
||||
});
|
||||
|
||||
const AuthoringStepContractWireSchema = v.object({
|
||||
step_id: v.string(),
|
||||
label: v.string(),
|
||||
description: v.optional(v.string()),
|
||||
input_targets: v.optional(v.array(AuthoringPathOptionWireSchema)),
|
||||
output_sources: v.optional(v.array(AuthoringPathOptionWireSchema)),
|
||||
outcomes: v.optional(v.array(v.string())),
|
||||
});
|
||||
|
||||
const AuthoringContractInventoryWireSchema = v.object({
|
||||
workspace_id: v.string(),
|
||||
revision: v.number(),
|
||||
selected_step_id: v.nullable(v.string()),
|
||||
readable_sources: v.array(AuthoringPathOptionWireSchema),
|
||||
step_input_targets: v.array(AuthoringPathOptionWireSchema),
|
||||
step_output_sources: v.array(AuthoringPathOptionWireSchema),
|
||||
state_targets: v.array(AuthoringPathOptionWireSchema),
|
||||
workflow_output_targets: v.array(AuthoringPathOptionWireSchema),
|
||||
entry_steps: v.array(AuthoringStepContractWireSchema),
|
||||
workflow_outcomes: v.array(v.string()),
|
||||
warnings: v.array(v.string()),
|
||||
});
|
||||
|
||||
const AuthoringPathOptionBrowserSchema = v.object({
|
||||
path: v.string(),
|
||||
label: v.string(),
|
||||
origin: AuthoringPathOriginSchema,
|
||||
schema: JsonObjectSchema,
|
||||
required: v.boolean(),
|
||||
availability: AuthoringPathAvailabilitySchema,
|
||||
uses: v.array(AuthoringPathUseSchema),
|
||||
description: v.optional(v.string()),
|
||||
reason: v.optional(v.string()),
|
||||
});
|
||||
|
||||
const AuthoringStepContractBrowserSchema = v.object({
|
||||
stepId: v.string(),
|
||||
label: v.string(),
|
||||
description: v.optional(v.string()),
|
||||
inputTargets: v.optional(v.array(AuthoringPathOptionBrowserSchema)),
|
||||
outputSources: v.optional(v.array(AuthoringPathOptionBrowserSchema)),
|
||||
outcomes: v.optional(v.array(v.string())),
|
||||
});
|
||||
|
||||
const AuthoringContractInventoryBrowserSchema = v.object({
|
||||
workspaceId: v.string(),
|
||||
revision: v.number(),
|
||||
selectedStepId: v.nullable(v.string()),
|
||||
readableSources: v.array(AuthoringPathOptionBrowserSchema),
|
||||
stepInputTargets: v.array(AuthoringPathOptionBrowserSchema),
|
||||
stepOutputSources: v.array(AuthoringPathOptionBrowserSchema),
|
||||
stateTargets: v.array(AuthoringPathOptionBrowserSchema),
|
||||
workflowOutputTargets: v.array(AuthoringPathOptionBrowserSchema),
|
||||
entrySteps: v.array(AuthoringStepContractBrowserSchema),
|
||||
workflowOutcomes: v.array(v.string()),
|
||||
warnings: v.array(v.string()),
|
||||
});
|
||||
|
||||
type AuthoringPathOptionWire = v.InferOutput<typeof AuthoringPathOptionWireSchema>;
|
||||
type AuthoringStepContractWire = v.InferOutput<typeof AuthoringStepContractWireSchema>;
|
||||
type AuthoringContractInventoryWire = v.InferOutput<
|
||||
typeof AuthoringContractInventoryWireSchema
|
||||
>;
|
||||
type AuthoringContractInventoryBrowser = v.InferOutput<
|
||||
typeof AuthoringContractInventoryBrowserSchema
|
||||
>;
|
||||
|
||||
const decode = <T>(
|
||||
label: string,
|
||||
schema: v.GenericSchema<unknown, T>,
|
||||
value: unknown,
|
||||
): T => {
|
||||
const result = v.safeParse(schema, value);
|
||||
if (result.success) return result.output;
|
||||
throw new Error(
|
||||
`${label} is malformed: ${result.issues[0]?.message ?? "unknown issue"}`,
|
||||
);
|
||||
};
|
||||
|
||||
const mapPathOption = (option: AuthoringPathOptionWire): AuthoringPathOption => ({
|
||||
path: option.path,
|
||||
label: option.label,
|
||||
origin: option.origin,
|
||||
schema: option.schema,
|
||||
required: option.required,
|
||||
availability: option.availability,
|
||||
uses: option.uses,
|
||||
...(option.description === undefined ? {} : { description: option.description }),
|
||||
...(option.reason === undefined ? {} : { reason: option.reason }),
|
||||
});
|
||||
|
||||
const mapStepContract = (step: AuthoringStepContractWire): AuthoringStepContract => ({
|
||||
stepId: step.step_id,
|
||||
label: step.label,
|
||||
...(step.description === undefined ? {} : { description: step.description }),
|
||||
...(step.input_targets === undefined
|
||||
? {}
|
||||
: { inputTargets: step.input_targets.map(mapPathOption) }),
|
||||
...(step.output_sources === undefined
|
||||
? {}
|
||||
: { outputSources: step.output_sources.map(mapPathOption) }),
|
||||
...(step.outcomes === undefined ? {} : { outcomes: step.outcomes }),
|
||||
});
|
||||
|
||||
const mapInventory = (
|
||||
inventory: AuthoringContractInventoryWire,
|
||||
): AuthoringContractInventory => ({
|
||||
workspaceId: inventory.workspace_id,
|
||||
revision: inventory.revision,
|
||||
selectedStepId: inventory.selected_step_id,
|
||||
readableSources: inventory.readable_sources.map(mapPathOption),
|
||||
stepInputTargets: inventory.step_input_targets.map(mapPathOption),
|
||||
stepOutputSources: inventory.step_output_sources.map(mapPathOption),
|
||||
stateTargets: inventory.state_targets.map(mapPathOption),
|
||||
workflowOutputTargets: inventory.workflow_output_targets.map(mapPathOption),
|
||||
entrySteps: inventory.entry_steps.map(mapStepContract),
|
||||
workflowOutcomes: inventory.workflow_outcomes,
|
||||
warnings: inventory.warnings,
|
||||
});
|
||||
|
||||
const mapBrowserInventory = (
|
||||
inventory: AuthoringContractInventoryBrowser,
|
||||
): AuthoringContractInventory => ({
|
||||
workspaceId: inventory.workspaceId,
|
||||
revision: inventory.revision,
|
||||
selectedStepId: inventory.selectedStepId,
|
||||
readableSources: inventory.readableSources,
|
||||
stepInputTargets: inventory.stepInputTargets,
|
||||
stepOutputSources: inventory.stepOutputSources,
|
||||
stateTargets: inventory.stateTargets,
|
||||
workflowOutputTargets: inventory.workflowOutputTargets,
|
||||
entrySteps: inventory.entrySteps,
|
||||
workflowOutcomes: inventory.workflowOutcomes,
|
||||
warnings: inventory.warnings,
|
||||
});
|
||||
|
||||
const AuthoringContractResponseSchema = v.union([
|
||||
AuthoringContractInventoryWireSchema,
|
||||
AuthoringContractInventoryBrowserSchema,
|
||||
]);
|
||||
|
||||
export const decodeAuthoringContractInventory = (
|
||||
value: unknown,
|
||||
): AuthoringContractInventory => {
|
||||
const decoded = decode(
|
||||
"AuthoringContractInventory",
|
||||
AuthoringContractResponseSchema,
|
||||
value,
|
||||
);
|
||||
return "workspace_id" in decoded ? mapInventory(decoded) : mapBrowserInventory(decoded);
|
||||
};
|
||||
Reference in New Issue
Block a user