import { detachedManifestScope, defineComponent, withApiName, validateCustomApiName, type ComponentDefinition, } from './component'; import { Workflow, type WorkflowProps, type WorkflowNode, type WorkflowGraph } from '../workflow'; import type { WorkflowActionPayloads } from '../workflow/actions'; import type { ManifestFunction } from '../manifest-function'; export type DefineWorkflowProps = Omit & { apiName: `${string}__c`; }; /** An explicit graph reference includes its function in the manifest and keeps the wire graph unchanged. */ export function workflowFunction( definition: ManifestFunction, payload: Omit, options: Omit = {}, ): WorkflowNode { const node: ReferencedNode = { ...options, config_id: 'RunFunction', payload: { ...payload, function_id: definition.getApiName() }, processing_context: { function_context: { function_api_name: definition.getApiName() } }, }; Object.defineProperty(node, nodeFunction, { value: definition, enumerable: true }); return node; } export function defineWorkflow(props: DefineWorkflowProps): Workflow { validateCustomApiName(props.apiName); return workflowComponent.register( withApiName( new Workflow(detachedManifestScope, { ...props, definitionId: props.apiName }), props.apiName, ), props, ); } const nodeFunction = Symbol.for('@rippling/sdk/workflow-node-function/v1'); type ReferencedNode = WorkflowNode & { readonly [nodeFunction]?: ManifestFunction }; const graphFunctions = (graph: WorkflowGraph | undefined): ManifestFunction[] => Object.values(graph?.nodes ?? {}).flatMap((node: ReferencedNode) => node[nodeFunction] == null ? [] : [node[nodeFunction]], ); const workflowComponent: ComponentDefinition = defineComponent({ type: 'WORKFLOW_DEFINITION', define: defineWorkflow, references: (_definition, { function: fn, graph, functionsInferredGraph }) => () => [ ...(fn == null || typeof fn === 'string' ? [] : [fn]), ...graphFunctions(graph), ...graphFunctions(functionsInferredGraph), ], });