@openapi-flow/n8n 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/README.md +29 -1
  2. package/dist/nodes/inputs/compile-template-input-validators.d.ts +3 -0
  3. package/dist/nodes/inputs/compile-template-input-validators.js +26 -0
  4. package/dist/nodes/inputs/create-template-input-nodes.d.ts +4 -0
  5. package/dist/nodes/inputs/create-template-input-nodes.js +61 -0
  6. package/dist/nodes/native/arrays/create-bound-native-array-capability.d.ts +4 -0
  7. package/dist/nodes/native/arrays/create-bound-native-array-capability.js +81 -0
  8. package/dist/nodes/native/arrays/create-native-array-capability.d.ts +1 -0
  9. package/dist/nodes/native/arrays/create-native-array-capability.js +7 -59
  10. package/dist/nodes/native/arrays/native-array-definition.d.ts +2 -0
  11. package/dist/nodes/native/arrays/native-array-definition.js +27 -0
  12. package/dist/nodes/native/common/create-material-planning-capability.d.ts +4 -0
  13. package/dist/nodes/native/common/create-material-planning-capability.js +14 -0
  14. package/dist/nodes/native/common/define-material-bound-capability.d.ts +4 -0
  15. package/dist/nodes/native/common/define-material-bound-capability.js +33 -0
  16. package/dist/nodes/native/common/resolve-native-runtime-source.d.ts +3 -0
  17. package/dist/nodes/native/common/resolve-native-runtime-source.js +15 -0
  18. package/dist/nodes/native/common/response-reference-bindings.d.ts +4 -0
  19. package/dist/nodes/native/common/response-reference-bindings.js +15 -0
  20. package/dist/nodes/native/create-exclusive-branch-merge-capability.js +10 -0
  21. package/dist/nodes/native/create-json-output-capability.js +14 -4
  22. package/dist/nodes/native/create-native-capabilities.js +13 -12
  23. package/dist/nodes/native/create-pass-through-capability.js +2 -0
  24. package/dist/nodes/native/create-response-array-capability.js +13 -8
  25. package/dist/nodes/native/create-response-collection-capability.js +10 -8
  26. package/dist/nodes/native/if-capability.js +6 -2
  27. package/dist/nodes/native/inputs/native-input-runtime.bundle.js +24 -0
  28. package/dist/nodes/native/inputs/prepend-native-parameter-guard.d.ts +4 -0
  29. package/dist/nodes/native/inputs/prepend-native-parameter-guard.js +52 -0
  30. package/dist/nodes/native/item-join/create-bound-item-join-capability.d.ts +3 -0
  31. package/dist/nodes/native/item-join/create-bound-item-join-capability.js +169 -0
  32. package/dist/nodes/native/item-join/create-item-join-capability.d.ts +2 -1
  33. package/dist/nodes/native/item-join/create-item-join-capability.js +8 -151
  34. package/dist/nodes/native/item-join/item-join-definition.d.ts +2 -0
  35. package/dist/nodes/native/item-join/item-join-definition.js +33 -0
  36. package/dist/nodes/native/merge-append-capability.js +2 -0
  37. package/dist/nodes/native/registry/native-feature-definitions.d.ts +4 -0
  38. package/dist/nodes/native/registry/native-feature-definitions.js +93 -0
  39. package/dist/nodes/native/registry/native-feature-material-requirements.d.ts +3 -0
  40. package/dist/nodes/native/registry/native-feature-material-requirements.js +10 -0
  41. package/dist/nodes/native/registry/resolve-n8n-native-features.d.ts +3 -0
  42. package/dist/nodes/native/registry/resolve-n8n-native-features.js +6 -0
  43. package/dist/nodes/native/registry/resolve-n8n-native-planning-features.d.ts +3 -0
  44. package/dist/nodes/native/registry/resolve-n8n-native-planning-features.js +5 -0
  45. package/dist/nodes/native/registry/resolve-native-feature-registry.d.ts +3 -0
  46. package/dist/nodes/native/registry/resolve-native-feature-registry.js +99 -0
  47. package/dist/nodes/native/registry/validate-native-feature-context.d.ts +2 -0
  48. package/dist/nodes/native/registry/validate-native-feature-context.js +46 -0
  49. package/dist/nodes/native/response-array-definition.d.ts +2 -0
  50. package/dist/nodes/native/response-array-definition.js +27 -0
  51. package/dist/nodes/native/response-assertion-capability.js +5 -1
  52. package/dist/nodes/native/response-check-code.d.ts +1 -1
  53. package/dist/nodes/native/response-check-code.js +13 -7
  54. package/dist/nodes/native/response-checks/create-response-check-reader.d.ts +1 -1
  55. package/dist/nodes/native/response-checks/create-response-check-reader.js +2 -2
  56. package/dist/nodes/native/response-collection-definition.d.ts +2 -0
  57. package/dist/nodes/native/response-collection-definition.js +27 -0
  58. package/dist/nodes/native/stop-and-error-capability.js +28 -14
  59. package/dist/nodes/request/bindings/compile-request-validator.d.ts +1 -1
  60. package/dist/nodes/request/bindings/compile-request-validator.js +2 -2
  61. package/dist/nodes/request/bindings/create-bound-request-fragment.js +8 -3
  62. package/dist/nodes/request/bindings/create-output-item-reader-code.d.ts +2 -0
  63. package/dist/nodes/request/bindings/create-output-item-reader-code.js +7 -0
  64. package/dist/nodes/request/bindings/create-output-reader-code.d.ts +1 -1
  65. package/dist/nodes/request/bindings/create-output-reader-code.js +4 -4
  66. package/dist/nodes/request/create-http-request-node.js +23 -44
  67. package/dist/nodes/request/finalize-http-request-fragment.d.ts +3 -0
  68. package/dist/nodes/request/finalize-http-request-fragment.js +22 -0
  69. package/dist/nodes/request/resolve-http-request-node-configuration.d.ts +4 -0
  70. package/dist/nodes/request/resolve-http-request-node-configuration.js +41 -0
  71. package/dist/nodes/request/response/create-http-response-decoder.js +2 -1
  72. package/dist/nodes/request/response/http-response-node-name.d.ts +2 -0
  73. package/dist/nodes/request/response/http-response-node-name.js +4 -0
  74. package/dist/nodes/request/response/response-runtime.bundle.js +1 -1
  75. package/dist/nodes/request/runtime/materialize-http-request.d.ts +2 -1
  76. package/dist/nodes/request/runtime/materialize-http-request.js +21 -3
  77. package/dist/nodes/request/runtime/request-runtime.bundle.js +1 -1
  78. package/dist/public-api.d.ts +13 -0
  79. package/dist/public-api.js +9 -0
  80. package/dist/schemas/native-feature-registry-schema.d.ts +17 -0
  81. package/dist/schemas/native-feature-registry-schema.js +8 -0
  82. package/dist/schemas/native-runtime-input-schema.d.ts +5 -0
  83. package/dist/schemas/native-runtime-input-schema.js +5 -0
  84. package/dist/schemas/template-deployment-selection-schema.d.ts +3 -0
  85. package/dist/schemas/template-deployment-selection-schema.js +10 -0
  86. package/dist/schemas/workflow-input-value-map-schema.d.ts +5 -0
  87. package/dist/schemas/workflow-input-value-map-schema.js +5 -0
  88. package/dist/schemas/workflow-template-schema.d.ts +11 -0
  89. package/dist/schemas/workflow-template-schema.js +10 -0
  90. package/dist/types/native-capability.d.ts +10 -1
  91. package/dist/types/native-feature-registry.d.ts +70 -0
  92. package/dist/types/native-feature-registry.js +14 -0
  93. package/dist/types/native-material-binding.d.ts +56 -0
  94. package/dist/types/native-material-binding.js +1 -0
  95. package/dist/types/native-runtime-parameters.d.ts +55 -0
  96. package/dist/types/native-runtime-parameters.js +1 -0
  97. package/dist/types/output-binding-source.d.ts +5 -0
  98. package/dist/types/request-materialization.d.ts +9 -1
  99. package/dist/types/request-node-configuration.d.ts +13 -0
  100. package/dist/types/request-node-configuration.js +1 -0
  101. package/dist/types/response-check-compilation.d.ts +1 -1
  102. package/dist/types/reviewable-workflow.d.ts +2 -0
  103. package/dist/types/workflow-compilation.d.ts +3 -0
  104. package/dist/types/workflow-template.d.ts +121 -0
  105. package/dist/types/workflow-template.js +1 -0
  106. package/dist/workflow/batch/compile-batched-n8n-workflow.js +22 -4
  107. package/dist/workflow/build-n8n-workflow.js +3 -6
  108. package/dist/workflow/compile-native-material-fragments.d.ts +3 -0
  109. package/dist/workflow/compile-native-material-fragments.js +76 -0
  110. package/dist/workflow/compile-native-workflow-nodes.js +22 -23
  111. package/dist/workflow/compile-planned-n8n-workflow.js +28 -3
  112. package/dist/workflow/compile-reviewable-n8n-workflow.js +31 -3
  113. package/dist/workflow/compile-validated-workflow-fragments.js +14 -14
  114. package/dist/workflow/compile-workflow-material-fragments.d.ts +4 -0
  115. package/dist/workflow/compile-workflow-material-fragments.js +18 -0
  116. package/dist/workflow/create-n8n-native-output-sources.js +53 -12
  117. package/dist/workflow/entrypoint/manual-trigger.d.ts +4 -0
  118. package/dist/workflow/entrypoint/manual-trigger.js +16 -0
  119. package/dist/workflow/find-singleton-api-responses.d.ts +3 -0
  120. package/dist/workflow/find-singleton-api-responses.js +22 -0
  121. package/dist/workflow/inputs/compile-native-runtime-inputs.d.ts +5 -0
  122. package/dist/workflow/inputs/compile-native-runtime-inputs.js +129 -0
  123. package/dist/workflow/inputs/create-runtime-input-native-capabilities.d.ts +4 -0
  124. package/dist/workflow/inputs/create-runtime-input-native-capabilities.js +36 -0
  125. package/dist/workflow/resolve-n8n-native-materials.d.ts +2 -0
  126. package/dist/workflow/resolve-n8n-native-materials.js +16 -0
  127. package/dist/workflow/templates/compile-n8n-workflow-template.d.ts +3 -0
  128. package/dist/workflow/templates/compile-n8n-workflow-template.js +211 -0
  129. package/dist/workflow/templates/create-template-artifact-mapping.d.ts +2 -0
  130. package/dist/workflow/templates/create-template-artifact-mapping.js +58 -0
  131. package/dist/workflow/templates/create-template-gap-regions.d.ts +5 -0
  132. package/dist/workflow/templates/create-template-gap-regions.js +22 -0
  133. package/dist/workflow/templates/create-workflow-template-guide.d.ts +3 -0
  134. package/dist/workflow/templates/create-workflow-template-guide.js +44 -0
  135. package/dist/workflow/templates/prepare-template-api-fragments.d.ts +3 -0
  136. package/dist/workflow/templates/prepare-template-api-fragments.js +74 -0
  137. package/dist/workflow/templates/select-n8n-template-deployments.d.ts +3 -0
  138. package/dist/workflow/templates/select-n8n-template-deployments.js +12 -0
  139. package/dist/workflow/templates/workflow-template-identities.d.ts +5 -0
  140. package/dist/workflow/templates/workflow-template-identities.js +5 -0
  141. package/package.json +9 -4
@@ -1,15 +1,10 @@
1
- import { validateApiArguments } from '@openapi-flow/core';
2
- import { mapHttpOperationContract } from '@openapi-flow/core/internal';
3
- import { originFrom } from '../../legacy/workflow/request/base-url.js';
1
+ import { validateApiArguments, inspectApiArgumentRequirements, } from '@openapi-flow/core';
4
2
  import { resolveCredentialBinding } from '../../legacy/workflow/request/credential-binding.js';
5
- import { absoluteOperationPath } from '../../legacy/workflow/request/request-url.js';
6
3
  import { createBoundRequestFragment } from './bindings/create-bound-request-fragment.js';
7
4
  import { serializeHttpRequest } from './serialization/serialize-http-request.js';
8
5
  import { createSerializedHttpRequestNode } from './serialization/create-serialized-http-request-node.js';
9
- import { resolveHttpRequestDeployment } from './deployment/resolve-http-request-deployment.js';
10
- import { createRequestDeploymentNotes } from './deployment/create-request-deployment-notes.js';
11
- import { resolveHttpRequestAuthentication } from './authentication/resolve-http-request-authentication.js';
12
- import { createHttpResponseDecoder } from './response/create-http-response-decoder.js';
6
+ import { resolveHttpRequestNodeConfiguration } from './resolve-http-request-node-configuration.js';
7
+ import { finalizeHttpRequestFragment } from './finalize-http-request-fragment.js';
13
8
  export function createHttpRequestNode(input) {
14
9
  const { operation: contract, arguments: args } = input;
15
10
  if (input.itemMode !== undefined && input.itemMode !== 'linked')
@@ -28,30 +23,25 @@ export function createHttpRequestNode(input) {
28
23
  });
29
24
  if (!validation.valid)
30
25
  throw new Error(`arguments[${args.callId}] is missing ${validation.missingInputs.join(', ')}`);
31
- const operation = mapHttpOperationContract(contract.path, contract.method, contract.key.operationRef, contract.pathItem, contract.operation);
32
- const authentication = resolveHttpRequestAuthentication({
26
+ const inspected = inspectApiArgumentRequirements({
33
27
  operation: contract,
34
- securityRequirementIndex: input.securityRequirementIndex,
35
- });
36
- const deployment = resolveHttpRequestDeployment({
37
- documentId: contract.key.documentId,
38
- authentication,
39
- baseUrl: input.baseUrl,
40
- credentialBindings: input.credentialBindings,
41
- securityRequirementIndex: input.securityRequirementIndex,
28
+ callId: args.callId,
29
+ values: args.values,
30
+ bindings: args.bindings,
31
+ requestMediaType: args.requestMediaType,
32
+ requestedInputs: args.requestedInputs,
42
33
  });
43
- const resolvedInput = { ...input, ...deployment };
34
+ if (inspected.status === 'needs-input')
35
+ throw new Error(`arguments[${args.callId}] is missing scenario-requested inputs: ${inspected.requirements.map((requirement) => requirement.targetPointer).join(', ')}`);
36
+ const prepared = resolveHttpRequestNodeConfiguration(input);
37
+ const resolvedInput = prepared.input;
38
+ const operation = prepared.config.operation;
44
39
  let fragment;
45
40
  if (args.bindings.length) {
46
- fragment = createBoundRequestFragment(resolvedInput, {
47
- contract,
48
- operation,
49
- arguments: args,
50
- templateUrl: new URL(absoluteOperationPath(originFrom(deployment.baseUrl), operation.path)).href,
51
- });
41
+ fragment = createBoundRequestFragment(resolvedInput, prepared.config);
52
42
  }
53
43
  else {
54
- const { url, body, headers } = serializeHttpRequest(operation, new URL(absoluteOperationPath(originFrom(deployment.baseUrl), operation.path)).href, args.values, args.requestMediaType);
44
+ const { url, body, headers } = serializeHttpRequest(operation, prepared.config.templateUrl, args.values, args.requestMediaType);
55
45
  const request = createSerializedHttpRequestNode({
56
46
  bodySource: 'literal',
57
47
  operation,
@@ -61,7 +51,7 @@ export function createHttpRequestNode(input) {
61
51
  url,
62
52
  body,
63
53
  headers,
64
- authentication: resolveCredentialBinding(deployment, deployment.credentialBindings),
54
+ authentication: resolveCredentialBinding(resolvedInput, resolvedInput.credentialBindings),
65
55
  shouldAssert: false,
66
56
  });
67
57
  fragment = {
@@ -74,21 +64,10 @@ export function createHttpRequestNode(input) {
74
64
  outputPorts: { main: 0 },
75
65
  };
76
66
  }
77
- fragment = createHttpResponseDecoder({ fragment, method: contract.method });
78
- if (deployment.pendingFields.length ||
79
- authentication?.credentialRequirements) {
80
- const notes = [
81
- ...(deployment.pendingFields.length
82
- ? [createRequestDeploymentNotes(contract.key.documentId, deployment)]
83
- : []),
84
- ...(authentication?.credentialRequirements
85
- ? [authentication.credentialRequirements]
86
- : []),
87
- ].join('\n');
88
- for (const requestNode of fragment.nodes) {
89
- requestNode.config.notes = notes;
90
- requestNode.config.notesInFlow = true;
91
- }
92
- }
93
- return fragment;
67
+ return finalizeHttpRequestFragment({
68
+ fragment,
69
+ method: contract.method,
70
+ documentId: contract.key.documentId,
71
+ deployment: resolvedInput,
72
+ });
94
73
  }
@@ -0,0 +1,3 @@
1
+ import type { FinalizeHttpRequestFragmentInput } from '../../types/request-node-configuration.js';
2
+ import type { N8nNodeFragment } from '../../types/node-fragment.js';
3
+ export declare function finalizeHttpRequestFragment(input: FinalizeHttpRequestFragmentInput): N8nNodeFragment;
@@ -0,0 +1,22 @@
1
+ import { createHttpResponseDecoder } from './response/create-http-response-decoder.js';
2
+ import { createRequestDeploymentNotes } from './deployment/create-request-deployment-notes.js';
3
+ export function finalizeHttpRequestFragment(input) {
4
+ const fragment = createHttpResponseDecoder(input);
5
+ const { deployment } = input;
6
+ if (deployment.pendingFields.length ||
7
+ deployment.authentication?.credentialRequirements) {
8
+ const notes = [
9
+ ...(deployment.pendingFields.length
10
+ ? [createRequestDeploymentNotes(input.documentId, deployment)]
11
+ : []),
12
+ ...(deployment.authentication?.credentialRequirements
13
+ ? [deployment.authentication.credentialRequirements]
14
+ : []),
15
+ ].join('\n');
16
+ for (const node of fragment.nodes) {
17
+ node.config.notes = notes;
18
+ node.config.notesInFlow = true;
19
+ }
20
+ }
21
+ return fragment;
22
+ }
@@ -0,0 +1,4 @@
1
+ import type { CreateHttpRequestNodeInput } from '../../types/node-fragment.js';
2
+ import type { ResolveHttpRequestNodeConfigurationResult } from '../../types/request-node-configuration.js';
3
+ /** Shared configuration ownership, after the strict or template boundary checks. */
4
+ export declare function resolveHttpRequestNodeConfiguration(input: CreateHttpRequestNodeInput): ResolveHttpRequestNodeConfigurationResult;
@@ -0,0 +1,41 @@
1
+ import { mapHttpOperationContract } from '@openapi-flow/core/internal';
2
+ import { originFrom } from '../../legacy/workflow/request/base-url.js';
3
+ import { absoluteOperationPath } from '../../legacy/workflow/request/request-url.js';
4
+ import { resolveHttpRequestAuthentication } from './authentication/resolve-http-request-authentication.js';
5
+ import { resolveHttpRequestDeployment } from './deployment/resolve-http-request-deployment.js';
6
+ /** Shared configuration ownership, after the strict or template boundary checks. */
7
+ export function resolveHttpRequestNodeConfiguration(input) {
8
+ const contract = input.operation;
9
+ const operation = mapHttpOperationContract(contract.path, contract.method, contract.key.operationRef, contract.pathItem, contract.operation);
10
+ const authentication = resolveHttpRequestAuthentication({
11
+ operation: contract,
12
+ securityRequirementIndex: input.securityRequirementIndex,
13
+ });
14
+ const deployment = resolveHttpRequestDeployment({
15
+ documentId: contract.key.documentId,
16
+ authentication,
17
+ baseUrl: input.baseUrl,
18
+ credentialBindings: input.credentialBindings,
19
+ securityRequirementIndex: input.securityRequirementIndex,
20
+ });
21
+ return {
22
+ input: { ...input, ...deployment },
23
+ config: {
24
+ contract,
25
+ operation,
26
+ arguments: {
27
+ callId: input.arguments.callId,
28
+ values: structuredClone(input.arguments.values),
29
+ bindings: structuredClone(input.arguments.bindings),
30
+ ...(input.arguments.requestedInputs === undefined
31
+ ? {}
32
+ : { requestedInputs: [...input.arguments.requestedInputs] }),
33
+ unresolvedInputs: [...input.arguments.unresolvedInputs],
34
+ ...(input.arguments.requestMediaType === undefined
35
+ ? {}
36
+ : { requestMediaType: input.arguments.requestMediaType }),
37
+ },
38
+ templateUrl: new URL(absoluteOperationPath(originFrom(deployment.baseUrl), operation.path)).href,
39
+ },
40
+ };
41
+ }
@@ -2,6 +2,7 @@ import { readFileSync } from 'node:fs';
2
2
  import { node } from '@n8n/workflow-sdk';
3
3
  import { isObject } from '@openapi-flow/core/internal';
4
4
  import { javascriptJsonLiteral } from '../../../utils/javascript-json-literal.js';
5
+ import { httpResponseNodeName } from './http-response-node-name.js';
5
6
  /** Keep transport metadata and item ancestry while exposing the decoded API exit. */
6
7
  export function createHttpResponseDecoder({ fragment, method, }) {
7
8
  const transport = fragment.exit;
@@ -35,7 +36,7 @@ export function createHttpResponseDecoder({ fragment, method, }) {
35
36
  version: 2,
36
37
  config: {
37
38
  id: fragment.nodeId,
38
- name: `Request ${fragment.nodeId}`,
39
+ name: httpResponseNodeName(fragment.nodeId),
39
40
  position: [position[0] + 220, position[1]],
40
41
  notes: 'Decode the raw HTTP response once. Preserve status, headers, body types and item ancestry. Invalid JSON fails without repair.',
41
42
  parameters: {
@@ -0,0 +1,2 @@
1
+ /** One compiler-owned exit identity, shared by producer and reference mapping. */
2
+ export declare function httpResponseNodeName(callId: string): string;
@@ -0,0 +1,4 @@
1
+ /** One compiler-owned exit identity, shared by producer and reference mapping. */
2
+ export function httpResponseNodeName(callId) {
3
+ return `Request ${callId}`;
4
+ }
@@ -21,4 +21,4 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
22
  */
23
23
  var OpenApiFlowResponseRuntime;
24
- (()=>{function a(e){if(!e||!Number.isInteger(e.statusCode))throw new Error("API response.statusCode is required");if(!e.headers||typeof e.headers!="object"||Array.isArray(e.headers))throw new Error("API response.headers is required");let t=Object.entries(e.headers).filter(([o])=>o.toLowerCase()==="content-type");if(t.length>1)throw new Error("API response.headers has ambiguous Content-Type");let n={statusCode:e.statusCode};if(t.length){if(typeof t[0][1]!="string")throw new Error("API response Content-Type must be a string");n.mediaType=t[0][1].split(";")[0].trim().toLowerCase()}return Object.hasOwn(e,"body")&&(n.body=e.body),n}var j=new Set(["application/octet-stream","application/gzip","application/zip","application/vnd.rar","application/epub+zip","application/x-bzip","application/x-bzip2","application/x-cdf","application/vnd.amazon.ebook","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-fontobject","application/vnd.oasis.opendocument.presentation","application/pdf","application/x-tar","application/vnd.visio","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/x-7z-compressed"]);function y(e){return e==="application/json"||e!==void 0&&/^[^/]+\/[^/]+\+json$/.test(e)}function h(e){return e!==void 0&&(/^(image|audio|video)\//.test(e)||j.has(e))}function m({response:e,bytes:t,method:n,sourceNodeId:o}){let i=a(e);if(Object.hasOwn(e,"body"))throw new Error(`API ${o} raw File transport must not contain body`);if(t.byteLength===0&&(n==="HEAD"||i.statusCode===204||i.statusCode===304))return{response:{...e},kind:"empty"};if(h(i.mediaType))return{response:{...e},kind:"binary"};let d=y(i.mediaType),l=Object.entries(e.headers).find(([r])=>r.toLowerCase()==="content-type")?.[1],s=typeof l=="string"?/;\s*charset\s*=\s*(?:"([^"]*)"|([^;\s]*))/i.exec(l):null,b=d||s===null?"utf-8":s[1]??s[2],c;try{c=new TextDecoder(b,{fatal:!0,ignoreBOM:!0}).decode(t)}catch(r){throw new Error(`API ${o} has invalid HTTP response encoding`,{cause:r})}if(!d)return{response:{...e,body:c},kind:"text"};try{return{response:{...e,body:JSON.parse(c)},kind:"json"}}catch(r){throw new Error(`API ${o} has an invalid JSON HTTP response`,{cause:r})}}OpenApiFlowResponseRuntime={decodeHttpResponse:m};})();
24
+ (()=>{function l(e){if(!e||!Number.isInteger(e.statusCode))throw new Error("API response.statusCode is required");if(!e.headers||typeof e.headers!="object"||Array.isArray(e.headers))throw new Error("API response.headers is required");let t=Object.entries(e.headers).filter(([r])=>r.toLowerCase()==="content-type");if(t.length>1)throw new Error("API response.headers has ambiguous Content-Type");let o={statusCode:e.statusCode};if(t.length){if(typeof t[0][1]!="string")throw new Error("API response Content-Type must be a string");o.mediaType=t[0][1].split(";")[0].trim().toLowerCase()}return Object.hasOwn(e,"body")&&(o.body=e.body),o}var x=new Set(["application/octet-stream","application/gzip","application/zip","application/vnd.rar","application/epub+zip","application/x-bzip","application/x-bzip2","application/x-cdf","application/vnd.amazon.ebook","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-fontobject","application/vnd.oasis.opendocument.presentation","application/pdf","application/x-tar","application/vnd.visio","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/x-7z-compressed"]);function h(e){return e==="application/json"||e!==void 0&&/^[^/]+\/[^/]+\+json$/.test(e)}function m(e){return e!==void 0&&(/^(image|audio|video)\//.test(e)||x.has(e))}function g({response:e,bytes:t,method:o,sourceNodeId:r}){let s=l(e);if(Object.hasOwn(e,"body"))throw new Error(`API ${r} raw File transport must not contain body`);if(t.byteLength===0&&(o==="HEAD"||s.statusCode===204||s.statusCode===304))return{response:{...e},kind:"empty"};if(m(s.mediaType))return{response:{...e},kind:"binary"};let d=h(s.mediaType),u=Object.entries(e.headers).find(([i])=>i.toLowerCase()==="content-type")?.[1],c=typeof u=="string"?/;\s*charset\s*=\s*(?:"([^"]*)"|([^;\s]*))/i.exec(u):null,w=d||c===null?"utf-8":c[1]??c[2],a;try{a=new TextDecoder(w,{fatal:!0,ignoreBOM:!0}).decode(t)}catch(i){throw new Error(`API ${r} has invalid HTTP response encoding`,{cause:i})}if(!d)return{response:{...e,body:a},kind:"text"};try{return{response:{...e,body:JSON.parse(a)},kind:"json"}}catch(i){throw new Error(`API ${r} has an invalid JSON HTTP response`,{cause:i})}}OpenApiFlowResponseRuntime={decodeHttpResponse:g};})();
@@ -1,3 +1,4 @@
1
+ import type { DeferredApiInputValues } from '@openapi-flow/core';
1
2
  import type { RequestMaterializationConfig, ResponseBodies, RuntimeHttpRequest, RuntimeRequestValidator } from '../../../types/request-materialization.js';
2
3
  /** Shared OAS validators/serializers run on the final values before HTTP sends. */
3
- export declare function materializeHttpRequest(config: RequestMaterializationConfig, responses: ResponseBodies, validate: RuntimeRequestValidator): RuntimeHttpRequest;
4
+ export declare function materializeHttpRequest(config: RequestMaterializationConfig, responses: ResponseBodies, validate: RuntimeRequestValidator, inputValues?: DeferredApiInputValues): RuntimeHttpRequest;
@@ -1,14 +1,32 @@
1
- import { materializeApiArguments } from '@openapi-flow/core/runtime';
1
+ import { materializeApiArguments, assignRequestInputValue, listMissingRequestedApiInputs, } from '@openapi-flow/core/runtime';
2
2
  import { serializeHttpRequest } from '../serialization/serialize-http-request.js';
3
3
  /** Shared OAS validators/serializers run on the final values before HTTP sends. */
4
- export function materializeHttpRequest(config, responses, validate) {
5
- const values = materializeApiArguments(config.arguments.values, config.arguments.bindings, responses, {
4
+ export function materializeHttpRequest(config, responses, validate, inputValues) {
5
+ let literals = JSON.parse(JSON.stringify(config.arguments.values));
6
+ for (const slot of config.deferredInputs?.slots ?? []) {
7
+ if (!inputValues || !Object.hasOwn(inputValues, slot.id))
8
+ throw new Error(`Missing runtime input ${slot.id} for ${slot.callId}${slot.targetPointer}`);
9
+ literals = assignRequestInputValue(literals, slot.targetPointer, inputValues[slot.id], {
10
+ callId: config.arguments.callId,
11
+ operation: config.contract,
12
+ requestMediaType: config.arguments.requestMediaType,
13
+ });
14
+ }
15
+ const values = materializeApiArguments(literals, config.arguments.bindings, responses, {
6
16
  callId: config.arguments.callId,
7
17
  operation: config.contract,
8
18
  requestMediaType: config.arguments.requestMediaType,
9
19
  });
10
20
  if (!validate(values))
11
21
  throw new Error(`Runtime request ${config.arguments.callId} does not match the OAS schema: ${JSON.stringify(validate.errors)}`);
22
+ const missing = listMissingRequestedApiInputs({
23
+ source: `Runtime request ${config.arguments.callId}`,
24
+ rootPointer: '',
25
+ value: values,
26
+ requestedInputs: config.arguments.requestedInputs,
27
+ });
28
+ if (missing.length)
29
+ throw new Error(`Runtime request ${config.arguments.callId} omits scenario-requested inputs: ${missing.join(', ')}`);
12
30
  const request = serializeHttpRequest(config.operation, config.templateUrl, values, config.arguments.requestMediaType);
13
31
  return {
14
32
  ...request,
@@ -21,4 +21,4 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
22
  */
23
23
  var OpenApiFlowRequestRuntime;
24
- (()=>{function j(e){if(e==="")return[];if(!e.startsWith("/")||/~(?![01])/u.test(e))throw new Error(`Invalid JSON Pointer: ${e}`);return e.slice(1).split("/").map(t=>t.replaceAll("~1","/").replaceAll("~0","~"))}function A(e,t){let n=e;for(let i of j(t)){if(n===null||typeof n!="object"||!Object.hasOwn(n,i))return;n=Reflect.get(n,i)}return n}function p(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function x(e){if(e.includes(!1))return!1;let t=e.filter(n=>n!==!0);return t.length?t.length===1?t[0]:{allOf:t}:!0}function C(e){if(e.includes(!0))return!0;let t=e.filter(n=>n!==!1);return t.length?t.length===1?t[0]:{anyOf:t}:!1}function $(e,t){if(typeof e=="boolean")return e;if(e.type!==void 0&&!(Array.isArray(e.type)?e.type:[e.type]).includes(t))return!1;for(let n of["allOf","anyOf","oneOf"]){if(!Array.isArray(e[n]))continue;let i=e[n].map(r=>(typeof r=="boolean"||p(r))&&$(r,t));if(n==="allOf"?!i.every(Boolean):!i.some(Boolean))return!1}return!0}function R(e,t,n){let i=new Map;function r(o,s,a=["object","array"]){if(typeof o=="boolean")return o;if(!s.length)return n?n.reference(o):o;if(n&&typeof o.$ref=="string"){let u=JSON.stringify([s,a]),l=i.get(o)??new Set;if(l.has(u))throw new Error(`Native pointer projection has a non-progressing reference cycle at ${t}`);l.add(u),i.set(o,l);let m={...o};delete m.$ref;try{return x([r(n.resolve(o),s,a),r(m,s,a)])}finally{l.delete(u)}}let[c,...d]=s,y=a.filter(u=>$(o,u)),w=[];if(y.includes("object")){let u=[];if(p(o.properties)&&Object.hasOwn(o.properties,c)){let l=o.properties[c];(typeof l=="boolean"||p(l))&&u.push(r(l,d))}if(p(o.patternProperties))for(let[l,m]of Object.entries(o.patternProperties))new RegExp(l).test(c)&&(typeof m=="boolean"||p(m))&&u.push(r(m,d));if(!u.length){let l=o.additionalProperties;u.push(l===void 0?!0:typeof l=="boolean"||p(l)?r(l,d):!1)}w.push(x(u))}if(y.includes("array")&&/^(0|[1-9][0-9]*)$/.test(c)){let u=Number(c),l=Array.isArray(o.prefixItems)?o.prefixItems:[],m=u<l.length?l[u]:o.items;w.push(typeof o.maxItems=="number"&&u>=o.maxItems?!1:m===void 0?!0:typeof m=="boolean"||p(m)?r(m,d):!1)}let k=[C(w)];for(let u of["allOf","anyOf","oneOf"]){if(!Array.isArray(o[u]))continue;let l=o[u].map(m=>typeof m=="boolean"||p(m)?r(m,s,y):!1);k.push(u==="allOf"?x(l):C(l))}return x(k)}let f=r(e,j(t));return f===!1?[]:[f]}function g(e,t){if(e===null||typeof e!="object"||Array.isArray(e))throw new Error(`${t} must be an object`);return e}function B(e,t){let n=g(e,t);if(n.$ref!==void 0)throw new Error(`${t} has an unresolved $ref`);return n}function N(e,t){if(e.operation.requestBody===void 0){if(t!==void 0)throw new Error(`${e.key.operationRef} has no requestBody for ${t}`);return}let n=g(e.operation.requestBody,`${e.key.operationRef}.requestBody`),i=g(n.content,`${e.key.operationRef}.requestBody.content`),r=Object.keys(i),f=t===void 0&&r.length===1?r[0]:t;if(f===void 0)throw new Error(`${e.key.operationRef}.requestMediaType must explicitly select one of ${r.join(", ")}`);if(!Object.hasOwn(i,f))throw new Error(`${e.key.operationRef}.requestBody.content has no ${f}`);let o=g(i[f],`${e.key.operationRef}.requestBody.content.${f}`);return o.schema===void 0?!0:typeof o.schema=="boolean"?o.schema:g(o.schema,`${f}.schema`)}function V(e,t){if(e.schema!==void 0)return typeof e.schema=="boolean"?e.schema:g(e.schema,`${t}.schema`);let n=g(e.content,`${t}.content`),i=Object.keys(n);if(i.length!==1)throw new Error(`${t}.content must have one media type`);let r=g(n[i[0]],`${t}.content.${i[0]}`);return r.schema===void 0?!0:typeof r.schema=="boolean"?r.schema:g(r.schema,`${t}.schema`)}function F(e,t){let[n,i,...r]=j(t);if(n==="body"){let a=N(e.operation,e.requestMediaType);return a===void 0?[]:R(a,t.slice(5))}let f=e.operation.effective.parameters.find(a=>a.in===n&&a.name===i);if(!f)return[];let o=V(f,t),s=r.length?"/"+r.map(a=>a.replaceAll("~","~0").replaceAll("/","~1")).join("/"):"";return R(o,s)}function J(e,t){if(["/path","/query","/header","/cookie"].includes(t))return"object";let n=new Set;for(let i of F(e,t))$(i,"object")&&n.add("object"),$(i,"array")&&n.add("array");if(n.size!==1)throw new Error(`Request ${e.callId}${t} needs an explicit literal container: OAS does not determine object versus array`);return n.has("array")?"array":"object"}function P(e,t,n,i){function r(o){if(Array.isArray(o))return o.map(r);if(o===null||typeof o!="object")return o;let s=Object.create(null);for(let[a,c]of Object.entries(o))s[a]=r(c);return s}let f=r(JSON.parse(JSON.stringify(e)));for(let o of t){if(!Object.hasOwn(n,o.sourceNodeId))throw new Error(`Missing response node ${o.sourceNodeId}`);let s=A(n[o.sourceNodeId],o.sourcePointer);if(s===void 0)throw new Error(`Missing response pointer ${o.sourceNodeId}${o.sourcePointer}`);let a=j(o.targetPointer);if(!a.length)throw new Error("binding target must identify a request field");let c=f;for(let[d,y]of a.entries())if(d===a.length-1){if(Object.hasOwn(c,y))throw new Error(`Literal conflicts with binding ${o.targetPointer}`);if(Array.isArray(c)&&!/^(0|[1-9][0-9]*)$/.test(y))throw new Error(`Binding array index is invalid ${o.targetPointer}`);Reflect.set(c,y,r(s))}else{if(!Object.hasOwn(c,y)){let k="/"+a.slice(0,d+1).map(l=>l.replaceAll("~","~0").replaceAll("/","~1")).join("/"),u=J(i,k)==="array"?[]:Object.create(null);Reflect.set(c,y,u)}let w=Reflect.get(c,y);if(!w||typeof w!="object")throw new Error(`Binding traverses non-container ${o.targetPointer}`);c=w}}return JSON.parse(JSON.stringify(f))}var h=class extends Error{operationRef;constructor(t,n){super(n),this.name="UnsupportedOperationError",this.operationRef=t}};function b(e,t,n){throw new h(t,`operationRef ${t} parameter ${e.in}.${e.name} ${n}`)}function z(e,t,n){return typeof n=="string"||typeof n=="boolean"||typeof n=="number"&&Number.isFinite(n)?n:b(e,t,"requires a scalar value")}function O(e,t){let n=encodeURIComponent(String(e)).replace(/[!'()*]/g,i=>"%"+i.charCodeAt(0).toString(16).toUpperCase());return t?n.replace(/%(3A|2F|3F|23|5B|5D|40|21|24|26|27|28|29|2A|2B|2C|3B|3D)/gi,i=>String.fromCharCode(Number.parseInt(i.slice(1),16))):n}function E(e,t,n,i){return Array.isArray(n)?n.map(r=>i(z(e,t,r))):p(n)?Object.entries(n).flatMap(([r,f])=>[i(r),i(z(e,t,f))]):[i(z(e,t,n))]}function M(e,t,n){if(e.contentMediaType!=="application/json")return b(e,t,"has no content mapping");let i=JSON.stringify(n);return i===void 0?b(e,t,"cannot be JSON serialized"):i}function H(e,t,n){if(e.contentMediaType)return O(M(e,t,n),!1);let r=E(e,t,n,o=>O(o,e.allowReserved)),f=p(n);if(e.style==="simple")return!f||!e.explode?r.join(","):r.flatMap((o,s)=>s%2===0?[o+"="+r[s+1]]:[]).join(",");if(e.style==="label")return!f||!e.explode?"."+r.join(e.explode?".":","):"."+r.flatMap((o,s)=>s%2===0?[o+"="+r[s+1]]:[]).join(".");if(e.style==="matrix"){let o=O(e.name,!1);return e.explode?f?r.flatMap((s,a)=>a%2===0?[";"+s+"="+r[a+1]]:[]).join(""):r.map(s=>";"+o+"="+s).join(""):";"+o+"="+r.join(",")}return b(e,t,`style ${e.style} is not a path style`)}function S(e,t,n){let i=O(e.name,!1);if(e.contentMediaType)return[i+"="+O(M(e,t,n),!1)];let f=E(e,t,n,s=>O(s,e.allowReserved)),o=p(n);return e.style==="deepObject"?o?f.flatMap((s,a)=>a%2===0?[i+"%5B"+s+"%5D="+f[a+1]]:[]):b(e,t,"deepObject requires an object"):e.style==="form"?e.explode?o?f.flatMap((s,a)=>a%2===0?[s+"="+f[a+1]]:[]):f.map(s=>i+"="+s):[i+"="+f.join(",")]:(e.style==="spaceDelimited"||e.style==="pipeDelimited")&&!e.explode&&(o||Array.isArray(n))?[i+"="+f.join(e.style==="spaceDelimited"?"%20":"%7C")]:b(e,t,`style ${e.style} is not mapped for query`)}function U(e,t,n){if(e.contentMediaType)return M(e,t,n);if(e.style!=="simple")return b(e,t,`style ${e.style} is not a header style`);let i=E(e,t,n,String),r=p(n)&&e.explode?i.flatMap((f,o)=>o%2===0?[f+"="+i[o+1]]:[]).join(","):i.join(",");if(/[\r\n]/.test(r))throw new Error(`plan.inputs.header.${e.name} must not contain a newline`);return r}function D(e,t,n){if(e.contentMediaType)return b(e,t,"cookie content needs a declared escaping strategy");if(e.style!=="form"&&e.style!=="cookie")return b(e,t,`style ${e.style} is not a cookie style`);let i=e.style==="cookie"?s=>String(s):s=>O(s,e.allowReserved),r=E(e,t,n,i),f=i(e.name);if(!e.explode&&(p(n)||Array.isArray(n)))return b(e,t,"explode:false produces invalid Cookie syntax");let o=p(n)?r.flatMap((s,a)=>a%2===0?[s+"="+r[a+1]]:[]):r.map(s=>f+"="+s);return o.some(s=>[...s].some(a=>{let c=a.charCodeAt(0);return c<=32||c===34||c===44||c===59||c===92||c===127}))?b(e,t,"value is not valid Cookie syntax"):o}function q(e){return encodeURIComponent(e.toWellFormed()).replace(/[!'()~]/g,t=>"%"+t.charCodeAt(0).toString(16).toUpperCase()).replaceAll("%20","+")}function G(e){let t=e.type==="array"&&p(e.items)?e.items.type:e.type;if(t==="object"||t==="array")return"application/json";if(["string","number","integer","boolean"].includes(String(t)))return"text/plain"}function X(e,t,n,i,r){if(i!=="application/json"&&i!=="text/plain")throw new h(r,`operationRef ${r}.requestBody field ${e} contentType ${i} has no form mapping`);let f=Array.isArray(t)?t:[t];if(f.length===0)return[];let o=[];for(let s of f){if(i==="text/plain"&&typeof s=="object")throw new h(r,`operationRef ${r}.requestBody field ${e} cannot use text/plain for a complex value`);i==="application/json"?o.push(q(e)+"="+q(JSON.stringify(s))):o.push(q(e)+"="+q(String(s)))}if(n.contentEncoding!==void 0)throw new h(r,`operationRef ${r}.requestBody field ${e} contentEncoding requires explicit binary serialization`);return o}function Y(e,t,n){let i=`operationRef ${e}.requestBody.schema.properties.${n}`,r=t.properties[n];if(r!==void 0){if(typeof r=="boolean")throw new h(e,`${i} does not define a form encoding type`);return B(r,i)}if(p(t.schema)&&t.schema.additionalProperties!==void 0&&typeof t.schema.additionalProperties!="boolean")return B(t.schema.additionalProperties,`operationRef ${e}.requestBody.schema.additionalProperties`);throw new h(e,`operationRef ${e}.requestBody field ${n} has no schema to determine form encoding`)}function T(e,t,n){let i=[];for(let[r,f]of Object.entries(n)){let o=Y(e,t,r),s=t.encoding?.[r],a=s===void 0?void 0:B(s,`operationRef ${e}.requestBody.encoding.${r}`);if(a?.encoding!==void 0||a?.prefixEncoding!==void 0||a?.itemEncoding!==void 0)throw new h(e,`operationRef ${e}.requestBody field ${r} needs nested encoding`);if(a?.style!==void 0||a?.explode!==void 0||a?.allowReserved!==void 0){let y=typeof a?.style=="string"?a.style:"form",w={name:r,in:"query",required:!1,schema:o,style:y,explode:typeof a?.explode=="boolean"?a.explode:y==="form",allowReserved:a?.allowReserved===!0};i.push(...S(w,e,f));continue}let d=typeof a?.contentType=="string"?a.contentType:G(o);if(d===void 0)throw new h(e,`operationRef ${e}.requestBody field ${r} has no form content mapping`);i.push(...X(r,f,o,d,e))}return i.join("&")}function I(e){if(!e||!Number.isInteger(e.statusCode))throw new Error("API response.statusCode is required");if(!e.headers||typeof e.headers!="object"||Array.isArray(e.headers))throw new Error("API response.headers is required");let t=Object.entries(e.headers).filter(([i])=>i.toLowerCase()==="content-type");if(t.length>1)throw new Error("API response.headers has ambiguous Content-Type");let n={statusCode:e.statusCode};if(t.length){if(typeof t[0][1]!="string")throw new Error("API response Content-Type must be a string");n.mediaType=t[0][1].split(";")[0].trim().toLowerCase()}return Object.hasOwn(e,"body")&&(n.body=e.body),n}function L(e){return/(token|secret|password|authorization|api.?key)/i.test(e)}function Q(e,t,n,i){let r=t,f=[],o=[],s=[];for(let d of e.parameters){let y=n[d.in]?.[d.name];if(y!==void 0)switch(d.in){case"path":r=r.replace(encodeURIComponent("{"+d.name+"}"),H(d,e.operationRef,y));break;case"query":f.push(...S(d,e.operationRef,y));break;case"header":o.push({name:d.name,value:U(d,e.operationRef,y)});break;case"cookie":s.push(...D(d,e.operationRef,y));break}}if(f.length&&(r+="?"+f.join("&")),s.length&&o.push({name:"Cookie",value:s.join("; ")}),n.body===void 0)return{url:r,headers:o};if(!e.body)throw new Error(`${e.operationRef} has no request body`);let a=Object.keys(e.body.mediaTypes),c=i??(a.length===1?a[0]:void 0);if(!c||!Object.hasOwn(e.body.mediaTypes,c))throw new Error(`${e.operationRef}: requestMediaType must select a declared body media type`);if(o.push({name:"Content-Type",value:c}),n.body!==null&&typeof n.body=="object"&&!Array.isArray(n.body)){for(let d of Object.keys(n.body))if(L(d))throw new Error(`body.${d} looks like a credential; use credentialBindings`)}if(c==="application/json")return{url:r,headers:o,body:{contentType:"json",value:JSON.stringify(n.body)}};if(c!=="application/x-www-form-urlencoded")throw new h(e.operationRef,`requestBody media type ${c} has no n8n mapping`);if(!n.body||typeof n.body!="object"||Array.isArray(n.body))throw new Error("form-urlencoded body must be an object");return{url:r,headers:o,body:{contentType:"form-urlencoded",value:T(e.operationRef,e.body.mediaTypes[c],n.body)}}}function W(e,t,n){let i=P(e.arguments.values,e.arguments.bindings,t,{callId:e.arguments.callId,operation:e.contract,requestMediaType:e.arguments.requestMediaType});if(!n(i))throw new Error(`Runtime request ${e.arguments.callId} does not match the OAS schema: ${JSON.stringify(n.errors)}`);let r=Q(e.operation,e.templateUrl,i,e.arguments.requestMediaType);return{...r,headersJson:JSON.stringify(Object.fromEntries(r.headers.map(f=>[f.name,f.value])))}}OpenApiFlowRequestRuntime={materializeHttpRequest:W,apiResponseValidationValue:I,pointerValue:A};})();
24
+ (()=>{function b(e){if(e==="")return[];if(!e.startsWith("/")||/~(?![01])/u.test(e))throw new Error(`Invalid JSON Pointer: ${e}`);return e.slice(1).split("/").map(t=>t.replaceAll("~1","/").replaceAll("~0","~"))}function A(e,t){let r=e;for(let i of b(t)){if(r===null||typeof r!="object"||!Object.hasOwn(r,i))return;r=Reflect.get(r,i)}return r}function H(e,t){return A(e,t)!==void 0}function y(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function x(e){if(e.includes(!1))return!1;let t=e.filter(r=>r!==!0);return t.length?t.length===1?t[0]:{allOf:t}:!0}function M(e){if(e.includes(!0))return!0;let t=e.filter(r=>r!==!1);return t.length?t.length===1?t[0]:{anyOf:t}:!1}function q(e,t){if(typeof e=="boolean")return e;if(e.type!==void 0&&!(Array.isArray(e.type)?e.type:[e.type]).includes(t))return!1;for(let r of["allOf","anyOf","oneOf"]){if(!Array.isArray(e[r]))continue;let i=e[r].map(o=>(typeof o=="boolean"||y(o))&&q(o,t));if(r==="allOf"?!i.every(Boolean):!i.some(Boolean))return!1}return!0}function B(e,t,r){let i=new Map;function o(n,a,s=["object","array"]){if(typeof n=="boolean")return n;if(!a.length)return r?r.reference(n):n;if(r&&typeof n.$ref=="string"){let p=JSON.stringify([a,s]),u=i.get(n)??new Set;if(u.has(p))throw new Error(`Native pointer projection has a non-progressing reference cycle at ${t}`);u.add(p),i.set(n,u);let m={...n};delete m.$ref;try{return x([o(r.resolve(n),a,s),o(m,a,s)])}finally{u.delete(p)}}let[f,...l]=a,d=s.filter(p=>q(n,p)),j=[];if(d.includes("object")){let p=[];if(y(n.properties)&&Object.hasOwn(n.properties,f)){let u=n.properties[f];(typeof u=="boolean"||y(u))&&p.push(o(u,l))}if(y(n.patternProperties))for(let[u,m]of Object.entries(n.patternProperties))new RegExp(u).test(f)&&(typeof m=="boolean"||y(m))&&p.push(o(m,l));if(!p.length){let u=n.additionalProperties;p.push(u===void 0?!0:typeof u=="boolean"||y(u)?o(u,l):!1)}j.push(x(p))}if(d.includes("array")&&/^(0|[1-9][0-9]*)$/.test(f)){let p=Number(f),u=Array.isArray(n.prefixItems)?n.prefixItems:[],m=p<u.length?u[p]:n.items;j.push(typeof n.maxItems=="number"&&p>=n.maxItems?!1:m===void 0?!0:typeof m=="boolean"||y(m)?o(m,l):!1)}let R=[M(j)];for(let p of["allOf","anyOf","oneOf"]){if(!Array.isArray(n[p]))continue;let u=n[p].map(m=>typeof m=="boolean"||y(m)?o(m,a,d):!1);R.push(p==="allOf"?x(u):M(u))}return x(R)}let c=o(e,b(t));return c===!1?[]:[c]}function w(e,t){if(e===null||typeof e!="object"||Array.isArray(e))throw new Error(`${t} must be an object`);return e}function I(e,t){let r=w(e,t);if(r.$ref!==void 0)throw new Error(`${t} has an unresolved $ref`);return r}function U(e,t){if(e.operation.requestBody===void 0){if(t!==void 0)throw new Error(`${e.key.operationRef} has no requestBody for ${t}`);return}let r=w(e.operation.requestBody,`${e.key.operationRef}.requestBody`),i=w(r.content,`${e.key.operationRef}.requestBody.content`),o=Object.keys(i),c=t===void 0&&o.length===1?o[0]:t;if(c===void 0)throw new Error(`${e.key.operationRef}.requestMediaType must explicitly select one of ${o.join(", ")}`);if(!Object.hasOwn(i,c))throw new Error(`${e.key.operationRef}.requestBody.content has no ${c}`);let n=w(i[c],`${e.key.operationRef}.requestBody.content.${c}`);return n.schema===void 0?!0:typeof n.schema=="boolean"?n.schema:w(n.schema,`${c}.schema`)}function v(e,t){if(e.schema!==void 0)return typeof e.schema=="boolean"?e.schema:w(e.schema,`${t}.schema`);let r=w(e.content,`${t}.content`),i=Object.keys(r);if(i.length!==1)throw new Error(`${t}.content must have one media type`);let o=w(r[i[0]],`${t}.content.${i[0]}`);return o.schema===void 0?!0:typeof o.schema=="boolean"?o.schema:w(o.schema,`${t}.schema`)}function D(e,t){let[r,i,...o]=b(t);if(r==="body"){let s=U(e.operation,e.requestMediaType);return s===void 0?[]:B(s,t.slice(5))}let c=e.operation.effective.parameters.find(s=>s.in===r&&s.name===i);if(!c)return[];let n=v(c,t),a=o.length?"/"+o.map(s=>s.replaceAll("~","~0").replaceAll("/","~1")).join("/"):"";return B(n,a)}function P(e,t){if(["/path","/query","/header","/cookie","/querystring"].includes(t))return"object";let r=new Set;for(let i of D(e,t))q(i,"object")&&r.add("object"),q(i,"array")&&r.add("array");if(r.size!==1)throw new Error(`Request ${e.callId}${t} needs an explicit literal container: OAS does not determine object versus array`);return r.has("array")?"array":"object"}function C(e,t,r,i){function o(n){if(Array.isArray(n))return n.map(o);if(n===null||typeof n!="object")return n;let a=Object.create(null);for(let[s,f]of Object.entries(n))a[s]=o(f);return a}let c=o(JSON.parse(JSON.stringify(e)));for(let n of t){if(!Object.hasOwn(r,n.sourceNodeId))throw new Error(`Missing response node ${n.sourceNodeId}`);let a=A(r[n.sourceNodeId],n.sourcePointer);if(a===void 0)throw new Error(`Missing response pointer ${n.sourceNodeId}${n.sourcePointer}`);let s=b(n.targetPointer);if(!s.length)throw new Error("binding target must identify a request field");let f=c;for(let[l,d]of s.entries())if(l===s.length-1){if(Object.hasOwn(f,d))throw new Error(`Literal conflicts with binding ${n.targetPointer}`);if(Array.isArray(f)&&!/^(0|[1-9][0-9]*)$/.test(d))throw new Error(`Binding array index is invalid ${n.targetPointer}`);Reflect.set(f,d,o(a))}else{if(!Object.hasOwn(f,d)){let R="/"+s.slice(0,l+1).map(u=>u.replaceAll("~","~0").replaceAll("/","~1")).join("/"),p=P(i,R)==="array"?[]:Object.create(null);Reflect.set(f,d,p)}let j=Reflect.get(f,d);if(!j||typeof j!="object")throw new Error(`Binding traverses non-container ${n.targetPointer}`);f=j}}return JSON.parse(JSON.stringify(c))}var h=class extends Error{operationRef;constructor(t,r){super(r),this.name="UnsupportedOperationError",this.operationRef=t}};function g(e,t,r){throw new h(t,`operationRef ${t} parameter ${e.in}.${e.name} ${r}`)}function z(e,t,r){return typeof r=="string"||typeof r=="boolean"||typeof r=="number"&&Number.isFinite(r)?r:g(e,t,"requires a scalar value")}function $(e,t){let r=encodeURIComponent(String(e)).replace(/[!'()*]/g,i=>"%"+i.charCodeAt(0).toString(16).toUpperCase());return t?r.replace(/%(3A|2F|3F|23|5B|5D|40|21|24|26|27|28|29|2A|2B|2C|3B|3D)/gi,i=>String.fromCharCode(Number.parseInt(i.slice(1),16))):r}function S(e,t,r,i){return Array.isArray(r)?r.map(o=>i(z(e,t,o))):y(r)?Object.entries(r).flatMap(([o,c])=>[i(o),i(z(e,t,c))]):[i(z(e,t,r))]}function J(e,t,r){if(e.contentMediaType!=="application/json")return g(e,t,"has no content mapping");let i=JSON.stringify(r);return i===void 0?g(e,t,"cannot be JSON serialized"):i}function L(e,t,r){if(e.contentMediaType)return $(J(e,t,r),!1);let o=S(e,t,r,n=>$(n,e.allowReserved)),c=y(r);if(e.style==="simple")return!c||!e.explode?o.join(","):o.flatMap((n,a)=>a%2===0?[n+"="+o[a+1]]:[]).join(",");if(e.style==="label")return!c||!e.explode?"."+o.join(e.explode?".":","):"."+o.flatMap((n,a)=>a%2===0?[n+"="+o[a+1]]:[]).join(".");if(e.style==="matrix"){let n=$(e.name,!1);return e.explode?c?o.flatMap((a,s)=>s%2===0?[";"+a+"="+o[s+1]]:[]).join(""):o.map(a=>";"+n+"="+a).join(""):";"+n+"="+o.join(",")}return g(e,t,`style ${e.style} is not a path style`)}function N(e,t,r){let i=$(e.name,!1);if(e.contentMediaType)return[i+"="+$(J(e,t,r),!1)];let c=S(e,t,r,a=>$(a,e.allowReserved)),n=y(r);return e.style==="deepObject"?n?c.flatMap((a,s)=>s%2===0?[i+"%5B"+a+"%5D="+c[s+1]]:[]):g(e,t,"deepObject requires an object"):e.style==="form"?e.explode?n?c.flatMap((a,s)=>s%2===0?[a+"="+c[s+1]]:[]):c.map(a=>i+"="+a):[i+"="+c.join(",")]:(e.style==="spaceDelimited"||e.style==="pipeDelimited")&&!e.explode&&(n||Array.isArray(r))?[i+"="+c.join(e.style==="spaceDelimited"?"%20":"%7C")]:g(e,t,`style ${e.style} is not mapped for query`)}function K(e,t,r){if(e.contentMediaType)return J(e,t,r);if(e.style!=="simple")return g(e,t,`style ${e.style} is not a header style`);let i=S(e,t,r,String),o=y(r)&&e.explode?i.flatMap((c,n)=>n%2===0?[c+"="+i[n+1]]:[]).join(","):i.join(",");if(/[\r\n]/.test(o))throw new Error(`plan.inputs.header.${e.name} must not contain a newline`);return o}function Q(e,t,r){if(e.contentMediaType)return g(e,t,"cookie content needs a declared escaping strategy");if(e.style!=="form"&&e.style!=="cookie")return g(e,t,`style ${e.style} is not a cookie style`);let i=e.style==="cookie"?a=>String(a):a=>$(a,e.allowReserved),o=S(e,t,r,i),c=i(e.name);if(!e.explode&&(y(r)||Array.isArray(r)))return g(e,t,"explode:false produces invalid Cookie syntax");let n=y(r)?o.flatMap((a,s)=>s%2===0?[a+"="+o[s+1]]:[]):o.map(a=>c+"="+a);return n.some(a=>[...a].some(s=>{let f=s.charCodeAt(0);return f<=32||f===34||f===44||f===59||f===92||f===127}))?g(e,t,"value is not valid Cookie syntax"):n}function k(e){return encodeURIComponent(e.toWellFormed()).replace(/[!'()~]/g,t=>"%"+t.charCodeAt(0).toString(16).toUpperCase()).replaceAll("%20","+")}function Y(e){let t=e.type==="array"&&y(e.items)?e.items.type:e.type;if(t==="object"||t==="array")return"application/json";if(["string","number","integer","boolean"].includes(String(t)))return"text/plain"}function Z(e,t,r,i,o){if(i!=="application/json"&&i!=="text/plain")throw new h(o,`operationRef ${o}.requestBody field ${e} contentType ${i} has no form mapping`);let c=Array.isArray(t)?t:[t];if(c.length===0)return[];let n=[];for(let a of c){if(i==="text/plain"&&typeof a=="object")throw new h(o,`operationRef ${o}.requestBody field ${e} cannot use text/plain for a complex value`);i==="application/json"?n.push(k(e)+"="+k(JSON.stringify(a))):n.push(k(e)+"="+k(String(a)))}if(r.contentEncoding!==void 0)throw new h(o,`operationRef ${o}.requestBody field ${e} contentEncoding requires explicit binary serialization`);return n}function _(e,t,r){let i=`operationRef ${e}.requestBody.schema.properties.${r}`,o=t.properties[r];if(o!==void 0){if(typeof o=="boolean")throw new h(e,`${i} does not define a form encoding type`);return I(o,i)}if(y(t.schema)&&t.schema.additionalProperties!==void 0&&typeof t.schema.additionalProperties!="boolean")return I(t.schema.additionalProperties,`operationRef ${e}.requestBody.schema.additionalProperties`);throw new h(e,`operationRef ${e}.requestBody field ${r} has no schema to determine form encoding`)}function T(e,t,r){let i=[];for(let[o,c]of Object.entries(r)){let n=_(e,t,o),a=t.encoding?.[o],s=a===void 0?void 0:I(a,`operationRef ${e}.requestBody.encoding.${o}`);if(s?.encoding!==void 0||s?.prefixEncoding!==void 0||s?.itemEncoding!==void 0)throw new h(e,`operationRef ${e}.requestBody field ${o} needs nested encoding`);if(s?.style!==void 0||s?.explode!==void 0||s?.allowReserved!==void 0){let d=typeof s?.style=="string"?s.style:"form",j={name:o,in:"query",required:!1,schema:n,style:d,explode:typeof s?.explode=="boolean"?s.explode:d==="form",allowReserved:s?.allowReserved===!0};i.push(...N(j,e,c));continue}let l=typeof s?.contentType=="string"?s.contentType:Y(n);if(l===void 0)throw new h(e,`operationRef ${e}.requestBody field ${o} has no form content mapping`);i.push(...Z(o,c,n,l,e))}return i.join("&")}function V(e){if(!e||!Number.isInteger(e.statusCode))throw new Error("API response.statusCode is required");if(!e.headers||typeof e.headers!="object"||Array.isArray(e.headers))throw new Error("API response.headers is required");let t=Object.entries(e.headers).filter(([i])=>i.toLowerCase()==="content-type");if(t.length>1)throw new Error("API response.headers has ambiguous Content-Type");let r={statusCode:e.statusCode};if(t.length){if(typeof t[0][1]!="string")throw new Error("API response Content-Type must be a string");r.mediaType=t[0][1].split(";")[0].trim().toLowerCase()}return Object.hasOwn(e,"body")&&(r.body=e.body),r}function E(e){if(b(e.rootPointer),e.requestedInputs===void 0)return[];if(!Array.isArray(e.requestedInputs))throw new Error(`${e.source}.requestedInputs must be an array`);let t=new Set;return e.requestedInputs.filter(r=>{if(typeof r!="string"||!b(r).length||t.has(r))throw new Error(`${e.source}.requestedInputs must contain distinct non-root JSON Pointers`);if(t.add(r),r!==e.rootPointer&&!r.startsWith(e.rootPointer+"/"))throw new Error(`${e.source}.requestedInputs contains ${r} outside ${e.rootPointer}`);return!H(e.value,r.slice(e.rootPointer.length))})}function O(e){if(Array.isArray(e))return e.map(O);if(e===null||typeof e!="object")return e;let t=Object.create(null);for(let[r,i]of Object.entries(e))t[r]=O(i);return t}function F(e,t,r,i){let o=b(t);if(!o.length||!["path","query","header","cookie","querystring","body"].includes(o[0]))throw new Error("confirmed input must identify a request field");let c=O(JSON.parse(JSON.stringify(e))),n=c;for(let[a,s]of o.entries()){if(Array.isArray(n)&&(!/^(0|[1-9][0-9]*)$/.test(s)||Number(s)>n.length))throw new Error(`confirmed input ${t} requires an explicit complete array prefix`);if(a===o.length-1){if(Object.hasOwn(n,s))throw new Error(`Request value conflicts with confirmed input ${t}`);Reflect.set(n,s,O(r))}else{if(!Object.hasOwn(n,s)){let l="/"+o.slice(0,a+1).map(d=>d.replaceAll("~","~0").replaceAll("/","~1")).join("/");Reflect.set(n,s,P(i,l)==="array"?[]:Object.create(null))}let f=Reflect.get(n,s);if(f===null||typeof f!="object")throw new Error(`confirmed input traverses non-container ${t}`);n=f}}return JSON.parse(JSON.stringify(c))}function W(e){return/(token|secret|password|authorization|api.?key)/i.test(e)}function G(e,t,r,i){let o=t,c=[],n=[],a=[];for(let l of e.parameters){let d=r[l.in]?.[l.name];if(d!==void 0)switch(l.in){case"path":o=o.replace(encodeURIComponent("{"+l.name+"}"),L(l,e.operationRef,d));break;case"query":c.push(...N(l,e.operationRef,d));break;case"header":n.push({name:l.name,value:K(l,e.operationRef,d)});break;case"cookie":a.push(...Q(l,e.operationRef,d));break}}if(c.length&&(o+="?"+c.join("&")),a.length&&n.push({name:"Cookie",value:a.join("; ")}),r.body===void 0)return{url:o,headers:n};if(!e.body)throw new Error(`${e.operationRef} has no request body`);let s=Object.keys(e.body.mediaTypes),f=i??(s.length===1?s[0]:void 0);if(!f||!Object.hasOwn(e.body.mediaTypes,f))throw new Error(`${e.operationRef}: requestMediaType must select a declared body media type`);if(n.push({name:"Content-Type",value:f}),r.body!==null&&typeof r.body=="object"&&!Array.isArray(r.body)){for(let l of Object.keys(r.body))if(W(l))throw new Error(`body.${l} looks like a credential; use credentialBindings`)}if(f==="application/json")return{url:o,headers:n,body:{contentType:"json",value:JSON.stringify(r.body)}};if(f!=="application/x-www-form-urlencoded")throw new h(e.operationRef,`requestBody media type ${f} has no n8n mapping`);if(!r.body||typeof r.body!="object"||Array.isArray(r.body))throw new Error("form-urlencoded body must be an object");return{url:o,headers:n,body:{contentType:"form-urlencoded",value:T(e.operationRef,e.body.mediaTypes[f],r.body)}}}function X(e,t,r,i){let o=JSON.parse(JSON.stringify(e.arguments.values));for(let s of e.deferredInputs?.slots??[]){if(!i||!Object.hasOwn(i,s.id))throw new Error(`Missing runtime input ${s.id} for ${s.callId}${s.targetPointer}`);o=F(o,s.targetPointer,i[s.id],{callId:e.arguments.callId,operation:e.contract,requestMediaType:e.arguments.requestMediaType})}let c=C(o,e.arguments.bindings,t,{callId:e.arguments.callId,operation:e.contract,requestMediaType:e.arguments.requestMediaType});if(!r(c))throw new Error(`Runtime request ${e.arguments.callId} does not match the OAS schema: ${JSON.stringify(r.errors)}`);let n=E({source:`Runtime request ${e.arguments.callId}`,rootPointer:"",value:c,requestedInputs:e.arguments.requestedInputs});if(n.length)throw new Error(`Runtime request ${e.arguments.callId} omits scenario-requested inputs: ${n.join(", ")}`);let a=G(e.operation,e.templateUrl,c,e.arguments.requestMediaType);return{...a,headersJson:JSON.stringify(Object.fromEntries(a.headers.map(s=>[s.name,s.value])))}}OpenApiFlowRequestRuntime={materializeHttpRequest:X,apiResponseValidationValue:V,pointerValue:A,listMissingRequestedApiInputs:E};})();
@@ -9,13 +9,22 @@ export type * from './types/workflow-compilation.js';
9
9
  export { compileReviewableN8nWorkflow } from './workflow/compile-reviewable-n8n-workflow.js';
10
10
  export type * from './types/reviewable-workflow.js';
11
11
  export { createN8nNativeCapabilities } from './nodes/native/create-native-capabilities.js';
12
+ export { resolveN8nNativeFeatures } from './nodes/native/registry/resolve-n8n-native-features.js';
13
+ export { resolveN8nNativePlanningFeatures } from './nodes/native/registry/resolve-n8n-native-planning-features.js';
14
+ export { N8nNativeFeature } from './types/native-feature-registry.js';
15
+ export type { N8nNativeFeatureContext, ResolveN8nNativeFeaturesInput, ReadyN8nNativeFeature, PendingN8nNativeFeature, N8nNativeFeatureRegistration, N8nNativeFeatureRegistry, N8nNativePlanningFeatureRegistry, N8nNativeFeaturePlanningDefinition, N8nNativeArrayContextRequirement, N8nNativeJsonOutputContextRequirement, N8nNativeFeatureContextRequirement, } from './types/native-feature-registry.js';
12
16
  export { createJsonOutputCapability } from './nodes/native/create-json-output-capability.js';
13
17
  export { createPassThroughCapability } from './nodes/native/create-pass-through-capability.js';
14
18
  export { createExclusiveBranchMergeCapability } from './nodes/native/create-exclusive-branch-merge-capability.js';
15
19
  export { createN8nNativeOutputSources } from './workflow/create-n8n-native-output-sources.js';
16
20
  export type * from './types/output-binding-source.js';
17
21
  export { compilePlannedN8nWorkflow } from './workflow/compile-planned-n8n-workflow.js';
22
+ export { n8nNativeInputConfigurationSchema } from './schemas/native-runtime-input-schema.js';
23
+ export { compileN8nWorkflowTemplate } from './workflow/templates/compile-n8n-workflow-template.js';
24
+ export type { CompileN8nWorkflowTemplateInput, N8nTemplateContext, N8nTemplateDeployment, N8nTemplateInputSlot, N8nTemplateNodeMapping, N8nTemplateDeploymentRequirement, N8nWorkflowTemplateResult, } from './types/workflow-template.js';
18
25
  export type * from './types/native-capability.js';
26
+ export type { N8nNativeRuntimeInput, PrependNativeParameterGuardInput, N8nNativeInputConfiguration, N8nNativeInputSlot, N8nNativeInputTemplate, } from './types/native-runtime-parameters.js';
27
+ export { prependNativeParameterGuard } from './nodes/native/inputs/prepend-native-parameter-guard.js';
19
28
  export { resolveHttpRequestAuthentication } from './nodes/request/authentication/resolve-http-request-authentication.js';
20
29
  export type * from './types/authentication.js';
21
30
  export { createResponseArrayCapability } from './nodes/native/create-response-array-capability.js';
@@ -28,3 +37,7 @@ export { createItemJoinCapability } from './nodes/native/item-join/create-item-j
28
37
  export type * from './types/item-join.js';
29
38
  export { compileBatchedN8nWorkflow } from './workflow/batch/compile-batched-n8n-workflow.js';
30
39
  export type { N8nBatchExecutionScope, CompileBatchedN8nWorkflowInput, } from './types/batch-execution.js';
40
+ export { describeN8nManualTrigger } from './workflow/entrypoint/manual-trigger.js';
41
+ export { selectN8nTemplateDeployments } from './workflow/templates/select-n8n-template-deployments.js';
42
+ export { resolveN8nNativeMaterials } from './workflow/resolve-n8n-native-materials.js';
43
+ export type { ResolveN8nNativeMaterialsInput, ResolvedN8nNativeMaterials, } from './types/native-material-binding.js';
@@ -4,14 +4,23 @@ export { assembleN8nWorkflow } from './workflow/assemble-n8n-workflow.js';
4
4
  export { httpRequestDeploymentOptionsSchema } from './schemas/request-deployment-schema.js';
5
5
  export { compileReviewableN8nWorkflow } from './workflow/compile-reviewable-n8n-workflow.js';
6
6
  export { createN8nNativeCapabilities } from './nodes/native/create-native-capabilities.js';
7
+ export { resolveN8nNativeFeatures } from './nodes/native/registry/resolve-n8n-native-features.js';
8
+ export { resolveN8nNativePlanningFeatures } from './nodes/native/registry/resolve-n8n-native-planning-features.js';
9
+ export { N8nNativeFeature } from './types/native-feature-registry.js';
7
10
  export { createJsonOutputCapability } from './nodes/native/create-json-output-capability.js';
8
11
  export { createPassThroughCapability } from './nodes/native/create-pass-through-capability.js';
9
12
  export { createExclusiveBranchMergeCapability } from './nodes/native/create-exclusive-branch-merge-capability.js';
10
13
  export { createN8nNativeOutputSources } from './workflow/create-n8n-native-output-sources.js';
11
14
  export { compilePlannedN8nWorkflow } from './workflow/compile-planned-n8n-workflow.js';
15
+ export { n8nNativeInputConfigurationSchema } from './schemas/native-runtime-input-schema.js';
16
+ export { compileN8nWorkflowTemplate } from './workflow/templates/compile-n8n-workflow-template.js';
17
+ export { prependNativeParameterGuard } from './nodes/native/inputs/prepend-native-parameter-guard.js';
12
18
  export { resolveHttpRequestAuthentication } from './nodes/request/authentication/resolve-http-request-authentication.js';
13
19
  export { createResponseArrayCapability } from './nodes/native/create-response-array-capability.js';
14
20
  export { createNativeArrayCapability } from './nodes/native/arrays/create-native-array-capability.js';
15
21
  export { createResponseCollectionCapability } from './nodes/native/create-response-collection-capability.js';
16
22
  export { createItemJoinCapability } from './nodes/native/item-join/create-item-join-capability.js';
17
23
  export { compileBatchedN8nWorkflow } from './workflow/batch/compile-batched-n8n-workflow.js';
24
+ export { describeN8nManualTrigger } from './workflow/entrypoint/manual-trigger.js';
25
+ export { selectN8nTemplateDeployments } from './workflow/templates/select-n8n-template-deployments.js';
26
+ export { resolveN8nNativeMaterials } from './workflow/resolve-n8n-native-materials.js';
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ export declare const n8nNativeFeatureSelectionSchema: z.ZodArray<z.ZodEnum<Readonly<{
3
+ readonly If: "if";
4
+ readonly MergeAppend: "merge-append";
5
+ readonly AssertResponses: "assert-responses";
6
+ readonly StopAndError: "stop-and-error";
7
+ readonly PassThrough: "pass-through";
8
+ readonly RejoinExclusiveBranches: "rejoin-exclusive-branches";
9
+ readonly JsonOutput: "json-output";
10
+ readonly SplitApiResponseArray: "split-api-response-array";
11
+ readonly CollectApiResponses: "collect-api-responses";
12
+ readonly SplitNativeOutputArray: "split-native-output-array";
13
+ readonly JoinApiItems: "join-api-items";
14
+ }>>>;
15
+ export declare const nativeItemExecutionOptionsSchema: z.ZodObject<{
16
+ itemMode: z.ZodOptional<z.ZodLiteral<"linked">>;
17
+ }, z.core.$strict>;
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ import { N8nNativeFeature } from '../types/native-feature-registry.js';
3
+ export const n8nNativeFeatureSelectionSchema = z
4
+ .array(z.enum(N8nNativeFeature))
5
+ .refine((features) => new Set(features).size === features.length, 'features must be unique');
6
+ export const nativeItemExecutionOptionsSchema = z.strictObject({
7
+ itemMode: z.literal('linked').optional(),
8
+ });
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod';
2
+ export declare const n8nNativeInputConfigurationSchema: z.ZodObject<{
3
+ revision: z.ZodNumber;
4
+ inputValues: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>;
5
+ }, z.core.$strict>;
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod';
2
+ export const n8nNativeInputConfigurationSchema = z.strictObject({
3
+ revision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
4
+ inputValues: z.record(z.string(), z.json()).optional(),
5
+ });
@@ -0,0 +1,3 @@
1
+ import { z } from 'zod';
2
+ import type { SelectN8nTemplateDeploymentsInput } from '../types/workflow-template.js';
3
+ export declare const templateDeploymentSelectionSchema: z.ZodType<SelectN8nTemplateDeploymentsInput>;
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ import { n8nTemplateDeploymentsSchema } from './workflow-template-schema.js';
3
+ const documentIds = z
4
+ .array(z.string().refine((id) => id.trim().length > 0))
5
+ .refine((ids) => new Set(ids).size === ids.length);
6
+ export const templateDeploymentSelectionSchema = z.strictObject({
7
+ deployments: n8nTemplateDeploymentsSchema,
8
+ availableDocumentIds: documentIds,
9
+ selectedDocumentIds: documentIds,
10
+ });
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod';
2
+ /** Only the map envelope; each source contract is compiled in its own resource scope. */
3
+ export declare function createWorkflowInputValueMapSchema(slotIds: string[]): z.ZodObject<{
4
+ [x: string]: z.ZodJSONSchema;
5
+ }, z.core.$strict>;
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod';
2
+ /** Only the map envelope; each source contract is compiled in its own resource scope. */
3
+ export function createWorkflowInputValueMapSchema(slotIds) {
4
+ return z.strictObject(Object.fromEntries(slotIds.map((id) => [id, z.json()])));
5
+ }
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ export declare const n8nTemplateDeploymentsSchema: z.ZodArray<z.ZodObject<{
3
+ baseUrl: z.ZodOptional<z.ZodString>;
4
+ credentialBindings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
5
+ id: z.ZodString;
6
+ name: z.ZodString;
7
+ }, z.core.$strict>>>;
8
+ securityRequirementIndex: z.ZodOptional<z.ZodNumber>;
9
+ documentId: z.ZodString;
10
+ }, z.core.$strict>>;
11
+ export declare const n8nTemplateInputValuesSchema: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ import { httpRequestDeploymentOptionsSchema } from './request-deployment-schema.js';
3
+ export const n8nTemplateDeploymentsSchema = z
4
+ .array(httpRequestDeploymentOptionsSchema.extend({
5
+ documentId: z.string().refine((value) => value.trim().length > 0),
6
+ }))
7
+ .refine((items) => new Set(items.map((item) => item.documentId)).size === items.length, {
8
+ message: 'template.deployments must contain distinct documentIds',
9
+ });
10
+ export const n8nTemplateInputValuesSchema = z.record(z.string(), z.json());
@@ -1,6 +1,8 @@
1
1
  import type { z } from 'zod';
2
- import type { PlannedNativeNode, WorkflowCapability, WorkflowGraphPlan, WorkflowApiMaterial, ApiOperationContract } from '@openapi-flow/core';
2
+ import type { PlannedNativeNode, WorkflowCapability, WorkflowGraphPlan, WorkflowApiMaterial, ApiOperationContract, WorkflowNativeMaterialSources } from '@openapi-flow/core';
3
3
  import type { N8nNodeFragment } from './node-fragment.js';
4
+ import type { N8nNativeRuntimeInput, N8nNativeInputConfiguration } from './native-runtime-parameters.js';
5
+ import type { N8nNativeOutputSource } from './output-binding-source.js';
4
6
  import type { nativeOperandSchema, nativeCheckSchema, ifParametersSchema, mergeParametersSchema, assertionParametersSchema, stopParametersSchema } from '../schemas/native-capability-schemas.js';
5
7
  export type NativeOperand = z.infer<typeof nativeOperandSchema>;
6
8
  export type NativeCheck = z.infer<typeof nativeCheckSchema>;
@@ -17,8 +19,14 @@ export interface CompileNativeNodeInput {
17
19
  position: [number, number];
18
20
  /** Original OAS contracts are required by compilers that read API responses. */
19
21
  apiResponseContracts?: Record<string, ApiOperationContract>;
22
+ /** Compiler proof from a single Manual Trigger item and item-preserving API paths. Missing/unknown proofs retain ancestry reads. */
23
+ singletonApiResponseIds?: string[];
24
+ runtimeInput?: N8nNativeRuntimeInput;
25
+ /** Names/schemas of actual already-compiled native producers, never guessed from IDs. */
26
+ nativeOutputSources?: N8nNativeOutputSource[];
20
27
  }
21
28
  export interface N8nNativeCapability extends WorkflowCapability {
29
+ bindMaterialContracts?: (sources: WorkflowNativeMaterialSources) => N8nNativeCapability;
22
30
  compile: (input: CompileNativeNodeInput) => N8nNodeFragment;
23
31
  }
24
32
  export interface CreateJsonOutputCapabilityInput {
@@ -33,5 +41,6 @@ export interface CompilePlannedN8nWorkflowInput {
33
41
  materials: WorkflowApiMaterial[];
34
42
  apiNodes: N8nNodeFragment[];
35
43
  capabilities: N8nNativeCapability[];
44
+ nativeInputs?: N8nNativeInputConfiguration;
36
45
  }
37
46
  export type CompileNativeWorkflowNodesInput = Pick<CompilePlannedN8nWorkflowInput, 'plan' | 'apiNodes' | 'capabilities' | 'materials'>;
@@ -0,0 +1,70 @@
1
+ import type { ApiBindingMaterial } from '@openapi-flow/core';
2
+ import type { CreateJsonOutputCapabilityInput, N8nNativeCapability, NativeItemExecutionOptions } from './native-capability.js';
3
+ import type { N8nNativeOutputSource } from './output-binding-source.js';
4
+ /** Supported OSS feature families, not every built-in node in n8n. */
5
+ export declare const N8nNativeFeature: Readonly<{
6
+ readonly If: "if";
7
+ readonly MergeAppend: "merge-append";
8
+ readonly AssertResponses: "assert-responses";
9
+ readonly StopAndError: "stop-and-error";
10
+ readonly PassThrough: "pass-through";
11
+ readonly RejoinExclusiveBranches: "rejoin-exclusive-branches";
12
+ readonly JsonOutput: "json-output";
13
+ readonly SplitApiResponseArray: "split-api-response-array";
14
+ readonly CollectApiResponses: "collect-api-responses";
15
+ readonly SplitNativeOutputArray: "split-native-output-array";
16
+ readonly JoinApiItems: "join-api-items";
17
+ }>;
18
+ export type N8nNativeFeature = (typeof N8nNativeFeature)[keyof typeof N8nNativeFeature];
19
+ export interface N8nNativeFeatureContext extends NativeItemExecutionOptions {
20
+ apiMaterials?: ApiBindingMaterial[];
21
+ nativeOutputSources?: N8nNativeOutputSource[];
22
+ /** The host owns the literal producer's name and original typed input contract. */
23
+ jsonOutput?: CreateJsonOutputCapabilityInput;
24
+ }
25
+ export interface ResolveN8nNativeFeaturesInput extends N8nNativeFeatureContext {
26
+ /** Omitted permits every registered family; [] permits none. */
27
+ features?: N8nNativeFeature[];
28
+ /** Explicit host implementations are retained, never inferred or replaced. */
29
+ extensions?: N8nNativeCapability[];
30
+ }
31
+ export interface ReadyN8nNativeFeature {
32
+ feature: N8nNativeFeature;
33
+ status: 'ready';
34
+ capability: N8nNativeCapability;
35
+ }
36
+ export interface PendingN8nNativeFeature {
37
+ feature: N8nNativeFeature;
38
+ status: 'requires-context';
39
+ missingContext: N8nNativeFeatureContextRequirement[];
40
+ }
41
+ export interface N8nNativeArrayContextRequirement {
42
+ field: 'apiMaterials' | 'nativeOutputSources';
43
+ minimumItems: number;
44
+ }
45
+ export interface N8nNativeJsonOutputContextRequirement {
46
+ field: 'jsonOutput';
47
+ }
48
+ export type N8nNativeFeatureContextRequirement = N8nNativeArrayContextRequirement | N8nNativeJsonOutputContextRequirement;
49
+ export type N8nNativeFeatureRegistration = ReadyN8nNativeFeature | PendingN8nNativeFeature;
50
+ export interface N8nNativeFeatureRegistry {
51
+ registrations: N8nNativeFeatureRegistration[];
52
+ /** Only ready registrations and explicitly supplied extensions. */
53
+ capabilities: N8nNativeCapability[];
54
+ }
55
+ export interface N8nNativePlanningFeatureRegistry extends N8nNativeFeatureRegistry {
56
+ /** Registered family provenance, separate from arbitrary explicit extensions. */
57
+ planningRegistrations: N8nNativeFeaturePlanningDefinition[];
58
+ /** Stable definitions are selectable, but their outputs/ports still require actual contracts. */
59
+ planningCapabilities: N8nNativeCapability[];
60
+ }
61
+ export interface N8nNativeFeaturePlanningDefinition {
62
+ feature: N8nNativeFeature;
63
+ capability: N8nNativeCapability;
64
+ }
65
+ export type N8nNativeFeatureResolutionMode = 'materials' | 'planning';
66
+ export interface N8nNativeFeatureDefinition {
67
+ requirements: N8nNativeFeatureContextRequirement[];
68
+ create: (context: N8nNativeFeatureContext) => N8nNativeCapability;
69
+ createPlanning?: (context: NativeItemExecutionOptions) => N8nNativeCapability;
70
+ }