@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.
- package/README.md +29 -1
- package/dist/nodes/inputs/compile-template-input-validators.d.ts +3 -0
- package/dist/nodes/inputs/compile-template-input-validators.js +26 -0
- package/dist/nodes/inputs/create-template-input-nodes.d.ts +4 -0
- package/dist/nodes/inputs/create-template-input-nodes.js +61 -0
- package/dist/nodes/native/arrays/create-bound-native-array-capability.d.ts +4 -0
- package/dist/nodes/native/arrays/create-bound-native-array-capability.js +81 -0
- package/dist/nodes/native/arrays/create-native-array-capability.d.ts +1 -0
- package/dist/nodes/native/arrays/create-native-array-capability.js +7 -59
- package/dist/nodes/native/arrays/native-array-definition.d.ts +2 -0
- package/dist/nodes/native/arrays/native-array-definition.js +27 -0
- package/dist/nodes/native/common/create-material-planning-capability.d.ts +4 -0
- package/dist/nodes/native/common/create-material-planning-capability.js +14 -0
- package/dist/nodes/native/common/define-material-bound-capability.d.ts +4 -0
- package/dist/nodes/native/common/define-material-bound-capability.js +33 -0
- package/dist/nodes/native/common/resolve-native-runtime-source.d.ts +3 -0
- package/dist/nodes/native/common/resolve-native-runtime-source.js +15 -0
- package/dist/nodes/native/common/response-reference-bindings.d.ts +4 -0
- package/dist/nodes/native/common/response-reference-bindings.js +15 -0
- package/dist/nodes/native/create-exclusive-branch-merge-capability.js +10 -0
- package/dist/nodes/native/create-json-output-capability.js +14 -4
- package/dist/nodes/native/create-native-capabilities.js +13 -12
- package/dist/nodes/native/create-pass-through-capability.js +2 -0
- package/dist/nodes/native/create-response-array-capability.js +13 -8
- package/dist/nodes/native/create-response-collection-capability.js +10 -8
- package/dist/nodes/native/if-capability.js +6 -2
- package/dist/nodes/native/inputs/native-input-runtime.bundle.js +24 -0
- package/dist/nodes/native/inputs/prepend-native-parameter-guard.d.ts +4 -0
- package/dist/nodes/native/inputs/prepend-native-parameter-guard.js +52 -0
- package/dist/nodes/native/item-join/create-bound-item-join-capability.d.ts +3 -0
- package/dist/nodes/native/item-join/create-bound-item-join-capability.js +169 -0
- package/dist/nodes/native/item-join/create-item-join-capability.d.ts +2 -1
- package/dist/nodes/native/item-join/create-item-join-capability.js +8 -151
- package/dist/nodes/native/item-join/item-join-definition.d.ts +2 -0
- package/dist/nodes/native/item-join/item-join-definition.js +33 -0
- package/dist/nodes/native/merge-append-capability.js +2 -0
- package/dist/nodes/native/registry/native-feature-definitions.d.ts +4 -0
- package/dist/nodes/native/registry/native-feature-definitions.js +93 -0
- package/dist/nodes/native/registry/native-feature-material-requirements.d.ts +3 -0
- package/dist/nodes/native/registry/native-feature-material-requirements.js +10 -0
- package/dist/nodes/native/registry/resolve-n8n-native-features.d.ts +3 -0
- package/dist/nodes/native/registry/resolve-n8n-native-features.js +6 -0
- package/dist/nodes/native/registry/resolve-n8n-native-planning-features.d.ts +3 -0
- package/dist/nodes/native/registry/resolve-n8n-native-planning-features.js +5 -0
- package/dist/nodes/native/registry/resolve-native-feature-registry.d.ts +3 -0
- package/dist/nodes/native/registry/resolve-native-feature-registry.js +99 -0
- package/dist/nodes/native/registry/validate-native-feature-context.d.ts +2 -0
- package/dist/nodes/native/registry/validate-native-feature-context.js +46 -0
- package/dist/nodes/native/response-array-definition.d.ts +2 -0
- package/dist/nodes/native/response-array-definition.js +27 -0
- package/dist/nodes/native/response-assertion-capability.js +5 -1
- package/dist/nodes/native/response-check-code.d.ts +1 -1
- package/dist/nodes/native/response-check-code.js +13 -7
- package/dist/nodes/native/response-checks/create-response-check-reader.d.ts +1 -1
- package/dist/nodes/native/response-checks/create-response-check-reader.js +2 -2
- package/dist/nodes/native/response-collection-definition.d.ts +2 -0
- package/dist/nodes/native/response-collection-definition.js +27 -0
- package/dist/nodes/native/stop-and-error-capability.js +28 -14
- package/dist/nodes/request/bindings/compile-request-validator.d.ts +1 -1
- package/dist/nodes/request/bindings/compile-request-validator.js +2 -2
- package/dist/nodes/request/bindings/create-bound-request-fragment.js +8 -3
- package/dist/nodes/request/bindings/create-output-item-reader-code.d.ts +2 -0
- package/dist/nodes/request/bindings/create-output-item-reader-code.js +7 -0
- package/dist/nodes/request/bindings/create-output-reader-code.d.ts +1 -1
- package/dist/nodes/request/bindings/create-output-reader-code.js +4 -4
- package/dist/nodes/request/create-http-request-node.js +23 -44
- package/dist/nodes/request/finalize-http-request-fragment.d.ts +3 -0
- package/dist/nodes/request/finalize-http-request-fragment.js +22 -0
- package/dist/nodes/request/resolve-http-request-node-configuration.d.ts +4 -0
- package/dist/nodes/request/resolve-http-request-node-configuration.js +41 -0
- package/dist/nodes/request/response/create-http-response-decoder.js +2 -1
- package/dist/nodes/request/response/http-response-node-name.d.ts +2 -0
- package/dist/nodes/request/response/http-response-node-name.js +4 -0
- package/dist/nodes/request/response/response-runtime.bundle.js +1 -1
- package/dist/nodes/request/runtime/materialize-http-request.d.ts +2 -1
- package/dist/nodes/request/runtime/materialize-http-request.js +21 -3
- package/dist/nodes/request/runtime/request-runtime.bundle.js +1 -1
- package/dist/public-api.d.ts +13 -0
- package/dist/public-api.js +9 -0
- package/dist/schemas/native-feature-registry-schema.d.ts +17 -0
- package/dist/schemas/native-feature-registry-schema.js +8 -0
- package/dist/schemas/native-runtime-input-schema.d.ts +5 -0
- package/dist/schemas/native-runtime-input-schema.js +5 -0
- package/dist/schemas/template-deployment-selection-schema.d.ts +3 -0
- package/dist/schemas/template-deployment-selection-schema.js +10 -0
- package/dist/schemas/workflow-input-value-map-schema.d.ts +5 -0
- package/dist/schemas/workflow-input-value-map-schema.js +5 -0
- package/dist/schemas/workflow-template-schema.d.ts +11 -0
- package/dist/schemas/workflow-template-schema.js +10 -0
- package/dist/types/native-capability.d.ts +10 -1
- package/dist/types/native-feature-registry.d.ts +70 -0
- package/dist/types/native-feature-registry.js +14 -0
- package/dist/types/native-material-binding.d.ts +56 -0
- package/dist/types/native-material-binding.js +1 -0
- package/dist/types/native-runtime-parameters.d.ts +55 -0
- package/dist/types/native-runtime-parameters.js +1 -0
- package/dist/types/output-binding-source.d.ts +5 -0
- package/dist/types/request-materialization.d.ts +9 -1
- package/dist/types/request-node-configuration.d.ts +13 -0
- package/dist/types/request-node-configuration.js +1 -0
- package/dist/types/response-check-compilation.d.ts +1 -1
- package/dist/types/reviewable-workflow.d.ts +2 -0
- package/dist/types/workflow-compilation.d.ts +3 -0
- package/dist/types/workflow-template.d.ts +121 -0
- package/dist/types/workflow-template.js +1 -0
- package/dist/workflow/batch/compile-batched-n8n-workflow.js +22 -4
- package/dist/workflow/build-n8n-workflow.js +3 -6
- package/dist/workflow/compile-native-material-fragments.d.ts +3 -0
- package/dist/workflow/compile-native-material-fragments.js +76 -0
- package/dist/workflow/compile-native-workflow-nodes.js +22 -23
- package/dist/workflow/compile-planned-n8n-workflow.js +28 -3
- package/dist/workflow/compile-reviewable-n8n-workflow.js +31 -3
- package/dist/workflow/compile-validated-workflow-fragments.js +14 -14
- package/dist/workflow/compile-workflow-material-fragments.d.ts +4 -0
- package/dist/workflow/compile-workflow-material-fragments.js +18 -0
- package/dist/workflow/create-n8n-native-output-sources.js +53 -12
- package/dist/workflow/entrypoint/manual-trigger.d.ts +4 -0
- package/dist/workflow/entrypoint/manual-trigger.js +16 -0
- package/dist/workflow/find-singleton-api-responses.d.ts +3 -0
- package/dist/workflow/find-singleton-api-responses.js +22 -0
- package/dist/workflow/inputs/compile-native-runtime-inputs.d.ts +5 -0
- package/dist/workflow/inputs/compile-native-runtime-inputs.js +129 -0
- package/dist/workflow/inputs/create-runtime-input-native-capabilities.d.ts +4 -0
- package/dist/workflow/inputs/create-runtime-input-native-capabilities.js +36 -0
- package/dist/workflow/resolve-n8n-native-materials.d.ts +2 -0
- package/dist/workflow/resolve-n8n-native-materials.js +16 -0
- package/dist/workflow/templates/compile-n8n-workflow-template.d.ts +3 -0
- package/dist/workflow/templates/compile-n8n-workflow-template.js +211 -0
- package/dist/workflow/templates/create-template-artifact-mapping.d.ts +2 -0
- package/dist/workflow/templates/create-template-artifact-mapping.js +58 -0
- package/dist/workflow/templates/create-template-gap-regions.d.ts +5 -0
- package/dist/workflow/templates/create-template-gap-regions.js +22 -0
- package/dist/workflow/templates/create-workflow-template-guide.d.ts +3 -0
- package/dist/workflow/templates/create-workflow-template-guide.js +44 -0
- package/dist/workflow/templates/prepare-template-api-fragments.d.ts +3 -0
- package/dist/workflow/templates/prepare-template-api-fragments.js +74 -0
- package/dist/workflow/templates/select-n8n-template-deployments.d.ts +3 -0
- package/dist/workflow/templates/select-n8n-template-deployments.js +12 -0
- package/dist/workflow/templates/workflow-template-identities.d.ts +5 -0
- package/dist/workflow/templates/workflow-template-identities.js +5 -0
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
# @openapi-flow/n8n
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Zod `^4.6.5` is a required host peer for the public configuration schemas. It is not an independently pinned runtime dependency. The n8n SDK's internal Zod 3 remains separately owned; this does not pass a Zod 4 instance into an API requiring Zod 3.
|
|
4
|
+
|
|
5
|
+
Version **0.3.1**, with matching `@openapi-flow/core@0.3.1`. Known limitation: Ajv 8.20.0 ignores a declared `properties.__proto__`. Generated validation can reject valid data or omit that property's constraints; do not rely on it for contracts using that key. The previously accepted limitation and original failing regression remain unchanged. No field substitution or schema compatibility transform is included. See the [release record](https://github.com/carefreelife98/openapi-flow/blob/main/docs/releases/0.3.1.md).
|
|
6
|
+
|
|
7
|
+
`compileN8nWorkflowTemplate` supports canonical `gapNodes`. It preserves
|
|
8
|
+
internal control edges, reuses Korean warning regions and stop-on-execution
|
|
9
|
+
surrogates, and leaves Start detached. Full Core topology validation remains in
|
|
10
|
+
place; the strict compiler still rejects unresolved plans. See the
|
|
11
|
+
[gap contract](../../docs/workflow-draft-conversation-host.md#explicit-capability-gaps).
|
|
12
|
+
|
|
13
|
+
templates retain API `requestedInputs` metadata and report requested
|
|
14
|
+
optional values in their slots and Korean guide. Preflight and the final request
|
|
15
|
+
materializer check presence separately from the unchanged OAS, including missing
|
|
16
|
+
optional descendants of a response-bound object. Strict HTTP node creation also
|
|
17
|
+
rejects missing requested literals. See [requested inputs](../../docs/workflow-draft-api-binding-questions.md#값이-미정인-선택-입력의-요청-추적).
|
|
18
|
+
|
|
19
|
+
`resolveN8nNativePlanningFeatures` separates selectable implementation definitions from material readiness. Four source-dependent families can be selected before producers exist, then bind the original contracts through existing snapshots and SDK compilation. No guessed source schema or runtime name is used. See [planning and host integration](../../docs/native-feature-planning.md).
|
|
20
|
+
|
|
21
|
+
material-dependent array/collection/item-join compilation rebinds current data contracts and resolves runtime names from actual SDK producer exits. `createN8nNativeOutputSources` requires actual `apiResponseContracts` for referenced APIs; partial subsets can declare external native outputs explicitly. Template requests accept `itemMode: 'linked'` for ancestry-preserving item streams. No old-contract/name fallback is used; custom compiler extensions must retain a coherent material binder. See [material snapshots and runtime proof](../../docs/native-material-snapshots.md).
|
|
22
|
+
|
|
23
|
+
templates accept whole-object or explicit field-pointer runtime parameters for `createJsonOutputCapability` and StopAndError. A central editable input map, per-slot checks, full combined-object preflight and immediate native guards preserve original literals, schemas and revision. The compiler still uses official SDK Set/StopAndError nodes; structural settings are not guessed at execution time. Slots and the Korean guide identify where actual values belong. Staged planning/editing contracts are available, but older combined host factories do not automatically acquire them. See the [supported scope and checks](../../docs/native-runtime-inputs.md). These additions are not in npm 0.2.0.
|
|
24
|
+
|
|
25
|
+
Standalone strict, reviewable and finite-batch compilation also accepts explicit `nativeInputs: { revision, inputValues? }`. A runtime-owned plan requires that configuration; there is no invented revision or template draft. Results with slots include `nativeInputTemplate` with original schemas, readiness, edit locations and a Korean guide. Missing actual values remain absent and fail at preflight before external calls. Review gaps retain internal wiring and warning regions with Start detached. Omission on literal-only plans preserves their existing result shape. See the [standalone compiler protocol](../../docs/native-runtime-inputs.md#standalone-compiler-input-protocol).
|
|
26
|
+
|
|
27
|
+
`describeN8nManualTrigger()` exposes the compiler-owned start contract for requirement planning. Its description and actual SDK trigger creation share one module, so hosts can declare the existing start separately from selectable native instances. It is explicit planning metadata, not a registry default, deployment check or extra trigger node.
|
|
28
|
+
|
|
29
|
+
`resolveN8nNativeFeatures` and `N8nNativeFeature` expose one registry for eleven existing feature families. Omission inventories every family with explicit `ready`/`requires-context` status; an explicit enum list is strict and `[]` selects none. Ready capabilities retain the existing schemas, source declarations and SDK compilers. Material-dependent families require actual OAS/native contracts, not invented placeholders. The published four-feature factory keeps its original selection. See the [registration and extension contract](../../docs/native-feature-registry.md).
|
|
30
|
+
|
|
31
|
+
Deterministic OpenAPI request-node creation and explicit n8n DAG assembly with the official workflow SDK. Version `0.3.1` depends on matching core `0.3.1`.
|
|
4
32
|
|
|
5
33
|
## Installed declaration dependencies
|
|
6
34
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createWorkflowRuntimeInputsSchema } from '@openapi-flow/core';
|
|
3
|
+
import { createWorkflowInputValueMapSchema } from '../../schemas/workflow-input-value-map-schema.js';
|
|
4
|
+
import { javascriptJsonLiteral } from '../../utils/javascript-json-literal.js';
|
|
5
|
+
import { compileStandaloneValidator } from '../common/validation/compile-standalone-validator.js';
|
|
6
|
+
/** Preserve every original $id and local $ref by compiling slot roots separately. */
|
|
7
|
+
export function compileTemplateInputValidators(slots) {
|
|
8
|
+
const contract = createWorkflowRuntimeInputsSchema(slots);
|
|
9
|
+
const envelope = compileStandaloneValidator({
|
|
10
|
+
schema: z.toJSONSchema(createWorkflowInputValueMapSchema(Object.keys(contract.shape)), { io: 'input' }),
|
|
11
|
+
globalName: 'OpenApiFlowInputsValidator',
|
|
12
|
+
});
|
|
13
|
+
const values = Object.entries(contract.shape).map(([id, schema], index) => {
|
|
14
|
+
const name = `OpenApiFlowInputSlotValidator${index}`;
|
|
15
|
+
const validator = compileStandaloneValidator({
|
|
16
|
+
schema: z.toJSONSchema(schema, { io: 'input' }),
|
|
17
|
+
globalName: name,
|
|
18
|
+
});
|
|
19
|
+
const slot = slots.find((entry) => entry.id === id);
|
|
20
|
+
const presence = slot.kind === 'api-request-input' && slot.requestedInputs !== undefined
|
|
21
|
+
? `\n{const missing=OpenApiFlowRequestRuntime.listMissingRequestedApiInputs({source:${javascriptJsonLiteral('Runtime input ' + id)},rootPointer:${javascriptJsonLiteral(slot.targetPointer)},value:payload.values[${javascriptJsonLiteral(id)}],requestedInputs:${javascriptJsonLiteral(slot.requestedInputs)}});if(missing.length)throw new Error('Workflow input omits scenario-requested inputs: '+missing.join(', '));}`
|
|
22
|
+
: '';
|
|
23
|
+
return `${validator}\nif(!${name}(payload.values[${javascriptJsonLiteral(id)}]))throw new Error('Workflow inputs do not match declared slots: '+${javascriptJsonLiteral(id)}+': '+JSON.stringify(${name}.errors));${presence}`;
|
|
24
|
+
});
|
|
25
|
+
return `${envelope}\nif(!OpenApiFlowInputsValidator(payload.values))throw new Error('Workflow inputs do not match declared slots: '+JSON.stringify(OpenApiFlowInputsValidator.errors));\n${values.join('\n')}`;
|
|
26
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CreateTemplateInputNodesInput } from '../../types/workflow-template.js';
|
|
2
|
+
import type { N8nNodeFragment } from '../../types/node-fragment.js';
|
|
3
|
+
/** Compile immutable contracts; the user edits only the separate actual-value map. */
|
|
4
|
+
export declare function createTemplateInputNodes(input: CreateTemplateInputNodesInput): N8nNodeFragment[];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { node } from '@n8n/workflow-sdk';
|
|
3
|
+
import { javascriptJsonLiteral } from '../../utils/javascript-json-literal.js';
|
|
4
|
+
import { compileTemplateInputValidators } from './compile-template-input-validators.js';
|
|
5
|
+
import { compileRequestValidator } from '../request/bindings/compile-request-validator.js';
|
|
6
|
+
import { compileStandaloneValidator } from '../common/validation/compile-standalone-validator.js';
|
|
7
|
+
import { createNativeFragment } from '../native/common/create-native-fragment.js';
|
|
8
|
+
import { TEMPLATE_INPUT_ID, TEMPLATE_INPUT_NAME, TEMPLATE_PREFLIGHT_ID, TEMPLATE_PREFLIGHT_NAME, } from '../../workflow/templates/workflow-template-identities.js';
|
|
9
|
+
/** Compile immutable contracts; the user edits only the separate actual-value map. */
|
|
10
|
+
export function createTemplateInputNodes(input) {
|
|
11
|
+
const validators = compileTemplateInputValidators(input.slots);
|
|
12
|
+
const setup = node({
|
|
13
|
+
type: 'n8n-nodes-base.code',
|
|
14
|
+
version: 2,
|
|
15
|
+
config: {
|
|
16
|
+
id: TEMPLATE_INPUT_ID,
|
|
17
|
+
name: TEMPLATE_INPUT_NAME,
|
|
18
|
+
position: [220, 0],
|
|
19
|
+
notes: '실제 값은 inputValues 객체에 슬롯 ID를 키로 추가하세요. 미입력 키는 생략하세요. 타입·스키마·revision은 바꾸지 마세요. 인증 비밀값은 n8n credential에 설정하세요.',
|
|
20
|
+
notesInFlow: true,
|
|
21
|
+
parameters: {
|
|
22
|
+
mode: 'runOnceForAllItems',
|
|
23
|
+
jsCode: `// 실제 값만 입력하세요. 미입력 값에 임시 값을 넣지 마세요.\nconst inputValues=${javascriptJsonLiteral(input.inputValues)};\nreturn [{json:{revision:${input.revision},values:inputValues}}];`,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
const runtime = readFileSync(new URL('../request/runtime/request-runtime.bundle.js', import.meta.url), 'utf8');
|
|
28
|
+
const nativeRuntime = readFileSync(new URL('../native/inputs/native-input-runtime.bundle.js', import.meta.url), 'utf8');
|
|
29
|
+
// A request without runtime response dependencies can be checked completely
|
|
30
|
+
// before any branch performs an external call. Dependent requests are checked
|
|
31
|
+
// again by their materializers after the actual producers have executed.
|
|
32
|
+
const earlyChecks = input.requests
|
|
33
|
+
.filter((request) => !request.arguments.bindings.length)
|
|
34
|
+
.map((request, index) => {
|
|
35
|
+
const name = `OpenApiFlowInitialRequestValidator${index}`;
|
|
36
|
+
return `${compileRequestValidator(request, name)}\nOpenApiFlowRequestRuntime.materializeHttpRequest(${javascriptJsonLiteral(request)},Object.create(null),${name},payload.values);`;
|
|
37
|
+
});
|
|
38
|
+
const nativeChecks = input.nativeParameters.map((material, index) => {
|
|
39
|
+
const name = `OpenApiFlowInitialNativeValidator${index}`;
|
|
40
|
+
return `${compileStandaloneValidator({ schema: material.schema, globalName: name })}\n{const parameters=OpenApiFlowNativeInputRuntime.materializeNativeRuntimeParameters(${javascriptJsonLiteral(material)},payload.values);if(!${name}(parameters))throw new Error('Native runtime input violates complete original schema for '+${javascriptJsonLiteral(material.nodeId)}+': '+JSON.stringify(${name}.errors));}`;
|
|
41
|
+
});
|
|
42
|
+
const preflight = node({
|
|
43
|
+
type: 'n8n-nodes-base.code',
|
|
44
|
+
version: 2,
|
|
45
|
+
config: {
|
|
46
|
+
id: TEMPLATE_PREFLIGHT_ID,
|
|
47
|
+
name: TEMPLATE_PREFLIGHT_NAME,
|
|
48
|
+
position: [440, 0],
|
|
49
|
+
notes: '모든 초기 입력을 외부 호출 전에 검사합니다. 선행 응답을 사용하는 요청은 해당 응답을 합친 후 전송 직전에 전체 OAS를 다시 검사합니다. 부분 실행·pinning으로 검사를 건너뛰지 마세요.',
|
|
50
|
+
notesInFlow: true,
|
|
51
|
+
parameters: {
|
|
52
|
+
mode: 'runOnceForAllItems',
|
|
53
|
+
jsCode: `${runtime}\n${nativeRuntime}\nconst items=$input.all();if(items.length!==1)throw new Error('Workflow input setup requires exactly one JSON item');const payload=items[0].json;if(!payload||payload.revision!==${input.revision})throw new Error('Missing or stale workflow input revision');\n${validators}\n${nativeChecks.join('\n')}\n${earlyChecks.join('\n')}\nreturn [{json:payload,pairedItem:{item:0}}];`,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
return [
|
|
58
|
+
createNativeFragment(setup, ['main'], ['main']),
|
|
59
|
+
createNativeFragment(preflight, ['main'], ['main']),
|
|
60
|
+
];
|
|
61
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { N8nNativeCapability } from '../../../types/native-capability.js';
|
|
2
|
+
import type { BoundNativeArrayCapabilityInput } from '../../../types/native-material-binding.js';
|
|
3
|
+
/** Data-contract binding is independent of runtime SDK producer names. */
|
|
4
|
+
export declare function createBoundNativeArrayCapability(input: BoundNativeArrayCapabilityInput): N8nNativeCapability;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { defineMaterialBoundCapability } from '../common/define-material-bound-capability.js';
|
|
2
|
+
import { createNativeArrayItemSchema, validateNativeOutputContracts, } from '@openapi-flow/core';
|
|
3
|
+
import { createNativeArrayParametersSchema } from '../../../schemas/native-array-schema.js';
|
|
4
|
+
import { nativeArrayDefinition } from './native-array-definition.js';
|
|
5
|
+
import { createArrayNodeFragment } from './create-array-node-fragment.js';
|
|
6
|
+
import { resolveNativeRuntimeSource } from '../common/resolve-native-runtime-source.js';
|
|
7
|
+
/** Data-contract binding is independent of runtime SDK producer names. */
|
|
8
|
+
export function createBoundNativeArrayCapability(input) {
|
|
9
|
+
if (input.itemMode !== undefined && input.itemMode !== 'linked')
|
|
10
|
+
throw new Error('native array capability: itemMode must be linked or omitted');
|
|
11
|
+
validateNativeOutputContracts(input.sources);
|
|
12
|
+
if (!input.sources.length)
|
|
13
|
+
throw new Error('native array capability requires source contracts');
|
|
14
|
+
const contracts = input.sources.map(({ nodeId, schema }) => ({
|
|
15
|
+
nodeId,
|
|
16
|
+
schema,
|
|
17
|
+
}));
|
|
18
|
+
const sources = new Map(contracts.map((source) => [source.nodeId, source]));
|
|
19
|
+
const parametersSchema = createNativeArrayParametersSchema([
|
|
20
|
+
...sources.keys(),
|
|
21
|
+
]);
|
|
22
|
+
function source(parameters) {
|
|
23
|
+
const output = sources.get(parameters.sourceNodeId);
|
|
24
|
+
if (!output)
|
|
25
|
+
throw new Error(`native array: unknown sourceNodeId ${parameters.sourceNodeId}`);
|
|
26
|
+
createNativeArrayItemSchema(output, parameters.pointer);
|
|
27
|
+
return output;
|
|
28
|
+
}
|
|
29
|
+
return defineMaterialBoundCapability({
|
|
30
|
+
...nativeArrayDefinition,
|
|
31
|
+
parametersSchema,
|
|
32
|
+
materialSources: {
|
|
33
|
+
apiMaterials: [],
|
|
34
|
+
nativeOutputs: structuredClone(contracts),
|
|
35
|
+
},
|
|
36
|
+
bindMaterialContracts: (contracts) => createBoundNativeArrayCapability({
|
|
37
|
+
sources: contracts.nativeOutputs,
|
|
38
|
+
itemMode: input.itemMode,
|
|
39
|
+
runtime: { kind: 'compiled' },
|
|
40
|
+
}),
|
|
41
|
+
responseReferences: () => [],
|
|
42
|
+
nodeOutputReferences: (values) => {
|
|
43
|
+
const parameters = parametersSchema.parse(values);
|
|
44
|
+
source(parameters);
|
|
45
|
+
return [
|
|
46
|
+
{
|
|
47
|
+
source: 'node-output',
|
|
48
|
+
nodeId: parameters.sourceNodeId,
|
|
49
|
+
pointer: parameters.pointer,
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
},
|
|
53
|
+
outputSchema: (values) => {
|
|
54
|
+
const parameters = parametersSchema.parse(values);
|
|
55
|
+
return {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: {
|
|
58
|
+
item: createNativeArrayItemSchema(source(parameters), parameters.pointer),
|
|
59
|
+
},
|
|
60
|
+
required: ['item'],
|
|
61
|
+
additionalProperties: false,
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
compile: ({ planned, position, nativeOutputSources }) => {
|
|
65
|
+
const parameters = parametersSchema.parse(planned.parameters);
|
|
66
|
+
const runtime = resolveNativeRuntimeSource({
|
|
67
|
+
binding: input.runtime,
|
|
68
|
+
contract: source(parameters),
|
|
69
|
+
compiledSources: nativeOutputSources,
|
|
70
|
+
consumerId: planned.id,
|
|
71
|
+
});
|
|
72
|
+
return createArrayNodeFragment({
|
|
73
|
+
planned,
|
|
74
|
+
position,
|
|
75
|
+
source: { ...runtime, kind: 'native-json' },
|
|
76
|
+
parameters,
|
|
77
|
+
linked: input.itemMode === 'linked',
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { N8nNativeCapability } from '../../../types/native-capability.js';
|
|
2
2
|
import type { CreateNativeArrayCapabilityInput } from '../../../types/native-array.js';
|
|
3
|
+
/** Existing explicitly named sources remain an immutable binding. New revisions bind contracts separately. */
|
|
3
4
|
export declare function createNativeArrayCapability(input: CreateNativeArrayCapabilityInput): N8nNativeCapability;
|
|
@@ -1,64 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { createArrayNodeFragment } from './create-array-node-fragment.js';
|
|
1
|
+
import { createBoundNativeArrayCapability } from './create-bound-native-array-capability.js';
|
|
2
|
+
/** Existing explicitly named sources remain an immutable binding. New revisions bind contracts separately. */
|
|
4
3
|
export function createNativeArrayCapability(input) {
|
|
5
|
-
if (input.itemMode !== undefined && input.itemMode !== 'linked')
|
|
6
|
-
throw new Error('native array capability: itemMode must be linked or omitted');
|
|
7
|
-
validateNativeOutputContracts(input.sources);
|
|
8
4
|
if (!input.sources.length ||
|
|
9
5
|
input.sources.some((source) => typeof source.nodeName !== 'string' || !source.nodeName.trim()))
|
|
10
6
|
throw new Error('native array capability requires sources with compiled names');
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const output = sources.get(parameters.sourceNodeId);
|
|
17
|
-
if (!output)
|
|
18
|
-
throw new Error(`native array: unknown sourceNodeId ${parameters.sourceNodeId}`);
|
|
19
|
-
createNativeArrayItemSchema(output, parameters.pointer);
|
|
20
|
-
return { ...output, kind: 'native-json' };
|
|
21
|
-
}
|
|
22
|
-
return {
|
|
23
|
-
name: 'split-native-output-array',
|
|
24
|
-
description: 'Split a supplied native JSON output array into {item: unchangedElement} using official n8n Split Out. Validate the full native output schema first. Linked mode preserves parent ancestry across nested splits. Empty arrays emit no child items; never convert, flatten or fabricate values.',
|
|
25
|
-
parametersSchema,
|
|
26
|
-
inputPorts: () => ['main'],
|
|
27
|
-
outputPorts: () => ['main'],
|
|
28
|
-
responseReferences: () => [],
|
|
29
|
-
nodeOutputReferences: (values) => {
|
|
30
|
-
const parameters = parametersSchema.parse(values);
|
|
31
|
-
source(parameters);
|
|
32
|
-
return [
|
|
33
|
-
{
|
|
34
|
-
source: 'node-output',
|
|
35
|
-
nodeId: parameters.sourceNodeId,
|
|
36
|
-
pointer: parameters.pointer,
|
|
37
|
-
},
|
|
38
|
-
];
|
|
39
|
-
},
|
|
40
|
-
waitsForAllInputs: false,
|
|
41
|
-
exclusiveOutputPorts: false,
|
|
42
|
-
outputSchema: (values) => {
|
|
43
|
-
const parameters = parametersSchema.parse(values);
|
|
44
|
-
return {
|
|
45
|
-
type: 'object',
|
|
46
|
-
properties: {
|
|
47
|
-
item: createNativeArrayItemSchema(source(parameters), parameters.pointer),
|
|
48
|
-
},
|
|
49
|
-
required: ['item'],
|
|
50
|
-
additionalProperties: false,
|
|
51
|
-
};
|
|
52
|
-
},
|
|
53
|
-
compile: ({ planned, position }) => {
|
|
54
|
-
const parameters = parametersSchema.parse(planned.parameters);
|
|
55
|
-
return createArrayNodeFragment({
|
|
56
|
-
planned,
|
|
57
|
-
position,
|
|
58
|
-
source: source(parameters),
|
|
59
|
-
parameters,
|
|
60
|
-
linked: input.itemMode === 'linked',
|
|
61
|
-
});
|
|
62
|
-
},
|
|
63
|
-
};
|
|
7
|
+
return createBoundNativeArrayCapability({
|
|
8
|
+
sources: input.sources,
|
|
9
|
+
itemMode: input.itemMode,
|
|
10
|
+
runtime: { kind: 'provided', sources: input.sources },
|
|
11
|
+
});
|
|
64
12
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { nativeArrayParametersSchema } from '../../../schemas/native-array-schema.js';
|
|
2
|
+
export const nativeArrayDefinition = {
|
|
3
|
+
name: 'split-native-output-array',
|
|
4
|
+
materialRequirements: [{ field: 'nativeOutputs', minimumItems: 1 }],
|
|
5
|
+
description: 'Split a supplied native JSON output array into {item: unchangedElement} using official n8n Split Out. Validate the full native output schema first. Linked mode preserves parent ancestry across nested splits. Empty arrays emit no child items; never convert, flatten or fabricate values.',
|
|
6
|
+
parametersSchema: nativeArrayParametersSchema,
|
|
7
|
+
parameterReferenceSources: ['node-output'],
|
|
8
|
+
inputPorts: () => ['main'],
|
|
9
|
+
outputPorts: () => ['main'],
|
|
10
|
+
referenceStructureSchema: nativeArrayParametersSchema,
|
|
11
|
+
parameterReferenceBindings: (values) => {
|
|
12
|
+
const parameters = nativeArrayParametersSchema.parse(values);
|
|
13
|
+
return [
|
|
14
|
+
{
|
|
15
|
+
nodeIdPointer: '/sourceNodeId',
|
|
16
|
+
valuePointer: '/pointer',
|
|
17
|
+
reference: {
|
|
18
|
+
source: 'node-output',
|
|
19
|
+
nodeId: parameters.sourceNodeId,
|
|
20
|
+
pointer: parameters.pointer,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
},
|
|
25
|
+
waitsForAllInputs: false,
|
|
26
|
+
exclusiveOutputPorts: false,
|
|
27
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { N8nNativeCapability } from '../../../types/native-capability.js';
|
|
2
|
+
import type { NativeMaterialFeatureDefinition } from '../../../types/native-material-binding.js';
|
|
3
|
+
/** A stable implementation definition, not a ready output contract or executable node. */
|
|
4
|
+
export declare function createMaterialPlanningCapability(definition: NativeMaterialFeatureDefinition, bind: NonNullable<N8nNativeCapability['bindMaterialContracts']>): N8nNativeCapability;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineMaterialBoundCapability } from './define-material-bound-capability.js';
|
|
2
|
+
/** A stable implementation definition, not a ready output contract or executable node. */
|
|
3
|
+
export function createMaterialPlanningCapability(definition, bind) {
|
|
4
|
+
function requireBinding() {
|
|
5
|
+
throw new Error(`Native feature ${definition.name} requires actual material contract binding before value references, output or compilation`);
|
|
6
|
+
}
|
|
7
|
+
return defineMaterialBoundCapability({
|
|
8
|
+
...definition,
|
|
9
|
+
bindMaterialContracts: bind,
|
|
10
|
+
responseReferences: requireBinding,
|
|
11
|
+
outputSchema: requireBinding,
|
|
12
|
+
compile: requireBinding,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MaterialBindableN8nCapability } from '../../../types/native-material-binding.js';
|
|
2
|
+
import type { N8nNativeCapability } from '../../../types/native-capability.js';
|
|
3
|
+
/** A material binder cannot silently discard a caller's different implementation or source receipt. */
|
|
4
|
+
export declare function defineMaterialBoundCapability(definition: MaterialBindableN8nCapability): N8nNativeCapability;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
2
|
+
/** A material binder cannot silently discard a caller's different implementation or source receipt. */
|
|
3
|
+
export function defineMaterialBoundCapability(definition) {
|
|
4
|
+
if (definition.materialRequirements !== undefined)
|
|
5
|
+
definition.materialRequirements = structuredClone(definition.materialRequirements);
|
|
6
|
+
const requirements = structuredClone(definition.materialRequirements);
|
|
7
|
+
if (definition.parameterReferenceSources !== undefined)
|
|
8
|
+
definition.parameterReferenceSources = structuredClone(definition.parameterReferenceSources);
|
|
9
|
+
const referenceSources = structuredClone(definition.parameterReferenceSources);
|
|
10
|
+
const bind = definition.bindMaterialContracts;
|
|
11
|
+
const fields = new Map(Object.entries(definition).filter(([key]) => key !== 'bindMaterialContracts' && key !== 'materialSources'));
|
|
12
|
+
const receipts = structuredClone(definition.materialSources);
|
|
13
|
+
definition.bindMaterialContracts = function (sources) {
|
|
14
|
+
const changed = [...fields]
|
|
15
|
+
.filter(([key, value]) => Reflect.get(this, key) !== value)
|
|
16
|
+
.map(([key]) => key);
|
|
17
|
+
const extra = Object.keys(this).filter((key) => key !== 'bindMaterialContracts' &&
|
|
18
|
+
key !== 'materialSources' &&
|
|
19
|
+
!fields.has(key));
|
|
20
|
+
if (!isDeepStrictEqual(this.materialSources, receipts))
|
|
21
|
+
changed.push('materialSources');
|
|
22
|
+
if (!isDeepStrictEqual(this.parameterReferenceSources, referenceSources) &&
|
|
23
|
+
!changed.includes('parameterReferenceSources'))
|
|
24
|
+
changed.push('parameterReferenceSources');
|
|
25
|
+
if (!isDeepStrictEqual(this.materialRequirements, requirements) &&
|
|
26
|
+
!changed.includes('materialRequirements'))
|
|
27
|
+
changed.push('materialRequirements');
|
|
28
|
+
if (changed.length || extra.length)
|
|
29
|
+
throw new Error(`Native material definition ${definition.name} changed ${[...changed, ...extra].join(', ')} without a coherent bindMaterialContracts implementation`);
|
|
30
|
+
return bind.call(this, sources);
|
|
31
|
+
};
|
|
32
|
+
return definition;
|
|
33
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ResolveNativeRuntimeSourceInput } from '../../../types/native-material-binding.js';
|
|
2
|
+
import type { N8nNativeOutputSource } from '../../../types/output-binding-source.js';
|
|
3
|
+
export declare function resolveNativeRuntimeSource(input: ResolveNativeRuntimeSourceInput): N8nNativeOutputSource;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
2
|
+
export function resolveNativeRuntimeSource(input) {
|
|
3
|
+
if (input.binding.kind === 'compiled' &&
|
|
4
|
+
!Array.isArray(input.compiledSources))
|
|
5
|
+
throw new Error(`Native ${input.consumerId}: compile.nativeOutputSources is required for the current material revision`);
|
|
6
|
+
const sources = input.binding.kind === 'provided'
|
|
7
|
+
? input.binding.sources
|
|
8
|
+
: input.compiledSources;
|
|
9
|
+
const matches = sources.filter((source) => source.nodeId === input.contract.nodeId);
|
|
10
|
+
if (matches.length !== 1 ||
|
|
11
|
+
!matches[0].nodeName?.trim() ||
|
|
12
|
+
!isDeepStrictEqual(matches[0].schema, input.contract.schema))
|
|
13
|
+
throw new Error(`Native ${input.consumerId}: source ${input.contract.nodeId} requires exactly one matching actual compiled name/schema`);
|
|
14
|
+
return matches[0];
|
|
15
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { WorkflowNativeReferenceBinding } from '@openapi-flow/core';
|
|
2
|
+
import type { NativeCheck } from '../../../types/native-capability.js';
|
|
3
|
+
/** The comparison implementation owns these operand locations. */
|
|
4
|
+
export declare function responseReferenceBindings(checks: NativeCheck[], prefix: string): WorkflowNativeReferenceBinding[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** The comparison implementation owns these operand locations. */
|
|
2
|
+
export function responseReferenceBindings(checks, prefix) {
|
|
3
|
+
return checks.flatMap((check, index) => ['left', 'right'].flatMap((side) => {
|
|
4
|
+
const operand = check[side];
|
|
5
|
+
return operand.source === 'response'
|
|
6
|
+
? [
|
|
7
|
+
{
|
|
8
|
+
nodeIdPointer: `${prefix}/${index}/${side}/nodeId`,
|
|
9
|
+
valuePointer: `${prefix}/${index}/${side}/pointer`,
|
|
10
|
+
reference: { ...operand },
|
|
11
|
+
},
|
|
12
|
+
]
|
|
13
|
+
: [];
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
@@ -7,6 +7,16 @@ export function createExclusiveBranchMergeCapability() {
|
|
|
7
7
|
name: 'rejoin-exclusive-branches',
|
|
8
8
|
description: 'Rejoin both alternative paths of one supplied IF instance using official Merge append. input1 and input2 each cover a distinct true/false path. Preserves existing items and ancestry; never creates an empty completion item. Both paths must return, including a skip path when no business call is required.',
|
|
9
9
|
parametersSchema: exclusiveBranchMergeParametersSchema,
|
|
10
|
+
parameterReferenceSources: ['exclusive-output'],
|
|
11
|
+
parameterReferenceBindings: (parameters) => [
|
|
12
|
+
{
|
|
13
|
+
nodeIdPointer: '/sourceNodeId',
|
|
14
|
+
reference: {
|
|
15
|
+
source: 'exclusive-output',
|
|
16
|
+
nodeId: exclusiveBranchMergeParametersSchema.parse(parameters).sourceNodeId,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
],
|
|
10
20
|
inputPorts: () => ['input1', 'input2'],
|
|
11
21
|
outputPorts: () => ['main'],
|
|
12
22
|
responseReferences: () => [],
|
|
@@ -3,21 +3,28 @@ import { z } from 'zod';
|
|
|
3
3
|
import { parseNativeNodeParameters } from '@openapi-flow/core';
|
|
4
4
|
import { javascriptJsonLiteral } from '../../utils/javascript-json-literal.js';
|
|
5
5
|
import { createNativeFragment } from './common/create-native-fragment.js';
|
|
6
|
+
import { prependNativeParameterGuard } from './inputs/prepend-native-parameter-guard.js';
|
|
6
7
|
/** Explicit typed literals through Edit Fields JSON mode; no casts or mapping expressions. */
|
|
7
8
|
export function createJsonOutputCapability(input) {
|
|
8
9
|
if (!input.name.trim() || !input.description.trim())
|
|
9
10
|
throw new Error('JSON output capability requires name and description');
|
|
10
11
|
const capability = {
|
|
11
12
|
...input,
|
|
13
|
+
supportsRuntimeParameters: true,
|
|
12
14
|
inputPorts: () => ['main'],
|
|
13
15
|
outputPorts: () => ['main'],
|
|
14
16
|
responseReferences: () => [],
|
|
17
|
+
parameterReferenceSources: [],
|
|
18
|
+
parameterReferenceBindings: () => [],
|
|
15
19
|
waitsForAllInputs: false,
|
|
16
20
|
exclusiveOutputPorts: false,
|
|
17
21
|
outputSchema: () => z.toJSONSchema(input.parametersSchema, { io: 'output' }),
|
|
18
|
-
compile: (
|
|
19
|
-
const
|
|
20
|
-
|
|
22
|
+
compile: (source) => {
|
|
23
|
+
const { planned, position } = source;
|
|
24
|
+
const jsonOutput = planned.runtimeParameters !== undefined
|
|
25
|
+
? '={{ JSON.stringify($json) }}'
|
|
26
|
+
: `={{ ${javascriptJsonLiteral(parseNativeNodeParameters(planned, capability))} }}`;
|
|
27
|
+
const fragment = createNativeFragment(node({
|
|
21
28
|
type: 'n8n-nodes-base.set',
|
|
22
29
|
version: 3.4,
|
|
23
30
|
config: {
|
|
@@ -26,12 +33,15 @@ export function createJsonOutputCapability(input) {
|
|
|
26
33
|
position,
|
|
27
34
|
parameters: {
|
|
28
35
|
mode: 'raw',
|
|
29
|
-
jsonOutput
|
|
36
|
+
jsonOutput,
|
|
30
37
|
includeOtherFields: false,
|
|
31
38
|
options: { dotNotation: false },
|
|
32
39
|
},
|
|
33
40
|
},
|
|
34
41
|
}), ['main'], ['main']);
|
|
42
|
+
return planned.runtimeParameters !== undefined
|
|
43
|
+
? prependNativeParameterGuard({ input: source, capability, fragment })
|
|
44
|
+
: fragment;
|
|
35
45
|
},
|
|
36
46
|
};
|
|
37
47
|
return capability;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { createStopAndErrorCapability } from './stop-and-error-capability.js';
|
|
1
|
+
import { resolveN8nNativeFeatures } from './registry/resolve-n8n-native-features.js';
|
|
2
|
+
import { validateNativeFeatureContext } from './registry/validate-native-feature-context.js';
|
|
3
|
+
import { N8nNativeFeature } from '../../types/native-feature-registry.js';
|
|
5
4
|
export function createN8nNativeCapabilities(input = {}) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
validateNativeFeatureContext(input);
|
|
6
|
+
return resolveN8nNativeFeatures({
|
|
7
|
+
...input,
|
|
8
|
+
features: [
|
|
9
|
+
N8nNativeFeature.If,
|
|
10
|
+
N8nNativeFeature.MergeAppend,
|
|
11
|
+
N8nNativeFeature.AssertResponses,
|
|
12
|
+
N8nNativeFeature.StopAndError,
|
|
13
|
+
],
|
|
14
|
+
}).capabilities;
|
|
14
15
|
}
|
|
@@ -7,9 +7,11 @@ export function createPassThroughCapability() {
|
|
|
7
7
|
name: 'pass-through',
|
|
8
8
|
description: 'n8n No Operation: forward all input items unchanged with their original links. Main input/output, no configuration or new data. Can provide a common entry before a fan-out. This does not merge branches, collect results or replace a missing API.',
|
|
9
9
|
parametersSchema: passThroughParametersSchema,
|
|
10
|
+
parameterReferenceSources: [],
|
|
10
11
|
inputPorts: () => ['main'],
|
|
11
12
|
outputPorts: () => ['main'],
|
|
12
13
|
responseReferences: () => [],
|
|
14
|
+
parameterReferenceBindings: () => [],
|
|
13
15
|
waitsForAllInputs: false,
|
|
14
16
|
exclusiveOutputPorts: false,
|
|
15
17
|
compile: ({ planned, position }) => {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { defineMaterialBoundCapability } from './common/define-material-bound-capability.js';
|
|
1
2
|
import { createResponseArrayItemSchema } from '@openapi-flow/core';
|
|
2
3
|
import { createResponseArrayParametersSchema } from '../../schemas/response-array-schema.js';
|
|
3
4
|
import { createArrayNodeFragment } from './arrays/create-array-node-fragment.js';
|
|
5
|
+
import { responseArrayDefinition } from './response-array-definition.js';
|
|
4
6
|
export function createResponseArrayCapability(input) {
|
|
5
7
|
if (input.itemMode !== undefined && input.itemMode !== 'linked')
|
|
6
8
|
throw new Error('response array capability: itemMode must be linked or omitted');
|
|
@@ -20,12 +22,17 @@ export function createResponseArrayCapability(input) {
|
|
|
20
22
|
createResponseArrayItemSchema(material.operation, parameters.pointer);
|
|
21
23
|
return material;
|
|
22
24
|
}
|
|
23
|
-
return {
|
|
24
|
-
|
|
25
|
-
description: 'Split a declared OAS response array into one unchanged JSON item per element using n8n Split Out. Output is {item: element}. Downstream bound requests must use linked item mode. An empty array creates no downstream items.',
|
|
25
|
+
return defineMaterialBoundCapability({
|
|
26
|
+
...responseArrayDefinition,
|
|
26
27
|
parametersSchema,
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
materialSources: {
|
|
29
|
+
apiMaterials: structuredClone(input.materials),
|
|
30
|
+
nativeOutputs: [],
|
|
31
|
+
},
|
|
32
|
+
bindMaterialContracts: (sources) => createResponseArrayCapability({
|
|
33
|
+
materials: sources.apiMaterials,
|
|
34
|
+
itemMode: input.itemMode,
|
|
35
|
+
}),
|
|
29
36
|
responseReferences: (values) => {
|
|
30
37
|
const parameters = parametersSchema.parse(values);
|
|
31
38
|
source(parameters);
|
|
@@ -37,8 +44,6 @@ export function createResponseArrayCapability(input) {
|
|
|
37
44
|
},
|
|
38
45
|
];
|
|
39
46
|
},
|
|
40
|
-
waitsForAllInputs: false,
|
|
41
|
-
exclusiveOutputPorts: false,
|
|
42
47
|
outputSchema: (values) => {
|
|
43
48
|
const parameters = parametersSchema.parse(values);
|
|
44
49
|
return {
|
|
@@ -69,5 +74,5 @@ export function createResponseArrayCapability(input) {
|
|
|
69
74
|
},
|
|
70
75
|
});
|
|
71
76
|
},
|
|
72
|
-
};
|
|
77
|
+
});
|
|
73
78
|
}
|