11import { ApplicationFailure } from "@temporalio/activity" ;
22import { parse as parseCsv } from "csv/sync" ;
3- import { XMLValidator } from "fast-xml-parser " ;
3+ import { SyntaxValidator } from "fast-xml-validator " ;
44import { BindingResolutionError , resolveBindings } from "./binding-resolver" ;
55import { renderCsv } from "./csv-renderer" ;
66import type { InputFormat } from "./input-parser" ;
@@ -20,6 +20,7 @@ const KNOWN_PARAM_KEYS = new Set([
2020 "fieldMapping" ,
2121 "xmlEnvelope" ,
2222 "requestId" ,
23+ "groupId" ,
2324] ) ;
2425
2526/**
@@ -45,6 +46,8 @@ export interface ExecuteTransformNodeParams {
4546 xmlEnvelope ?: string ;
4647 /** Optional request correlation ID (injected by the workflow runner). */
4748 requestId ?: string ;
49+ /** Tenant scope (injected by the workflow runner; not a port-binding input). */
50+ groupId ?: string | number ;
4851 /** Port-binding inputs from the workflow context (any additional keys). */
4952 [ key : string ] : unknown ;
5053}
@@ -131,21 +134,30 @@ export async function executeTransformNode(
131134
132135 // Step 4: Render the resolved mapping to the configured output format.
133136 let output : string ;
134- switch ( outputFormat ) {
135- case "json" :
136- output = renderJson ( resolvedMapping ) ;
137- break ;
138- case "xml" : {
139- const innerXml = renderXml (
140- resolvedMapping ,
141- xmlEnvelope ? null : undefined ,
142- ) ;
143- output = injectXmlEnvelope ( innerXml , xmlEnvelope ) ;
144- break ;
137+ try {
138+ switch ( outputFormat ) {
139+ case "json" :
140+ output = renderJson ( resolvedMapping ) ;
141+ break ;
142+ case "xml" : {
143+ const innerXml = renderXml (
144+ resolvedMapping ,
145+ xmlEnvelope ? null : undefined ,
146+ ) ;
147+ output = injectXmlEnvelope ( innerXml , xmlEnvelope ) ;
148+ break ;
149+ }
150+ case "csv" :
151+ output = renderCsv ( resolvedMapping ) ;
152+ break ;
145153 }
146- case "csv" :
147- output = renderCsv ( resolvedMapping ) ;
148- break ;
154+ } catch ( err ) {
155+ const detail = err instanceof Error ? err . message : String ( err ) ;
156+ throw ApplicationFailure . create ( {
157+ type : "TRANSFORM_OUTPUT_ERROR" ,
158+ message : `Rendered ${ outputFormat } output failed validation: ${ detail } ` ,
159+ nonRetryable : true ,
160+ } ) ;
149161 }
150162
151163 // Step 5: Post-render output validation.
@@ -159,9 +171,9 @@ export async function executeTransformNode(
159171 JSON . parse ( output ) ;
160172 break ;
161173 case "xml" : {
162- const result = XMLValidator . validate ( output ) ;
174+ const result = SyntaxValidator . validate ( output ) ;
163175 if ( result !== true ) {
164- throw new Error ( result . err . msg ) ;
176+ throw new Error ( ( result as { err : { msg : string } } ) . err . msg ) ;
165177 }
166178 break ;
167179 }
0 commit comments