@codemation/node-example 0.0.24 → 0.0.26

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @codemation/node-example
2
2
 
3
+ ## 0.0.26
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`35b78bb`](https://github.com/MadeRelevant/codemation/commit/35b78bb4d8c7ee2998a8b8e51e5ffc3fd901e4c7), [`eb97e53`](https://github.com/MadeRelevant/codemation/commit/eb97e5376f4f620099c32c14d7797ed3039bf7bb)]:
8
+ - @codemation/core@0.4.0
9
+
10
+ ## 0.0.25
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [[`bb2b3b8`](https://github.com/MadeRelevant/codemation/commit/bb2b3b89069697c6aa36aac1de7124c5eea65c3e)]:
15
+ - @codemation/core@0.3.0
16
+
3
17
  ## 0.0.24
4
18
 
5
19
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -37,21 +37,17 @@ function __decorate(decorators, target, key, desc) {
37
37
  let ExampleUppercaseNode = class ExampleUppercaseNode$1 {
38
38
  kind = "node";
39
39
  outputPorts = ["main"];
40
- async execute(items, ctx) {
41
- const out = [];
42
- for (let i = 0; i < items.length; i++) {
43
- const item = items[i];
44
- const json = typeof item.json === "object" && item.json !== null ? item.json : {};
45
- const value = String(json[ctx.config.cfg.field] ?? "");
46
- out.push({
47
- ...item,
48
- json: {
49
- ...json,
50
- [ctx.config.cfg.field]: value.toUpperCase()
51
- }
52
- });
53
- }
54
- return { main: out };
40
+ execute(args) {
41
+ const item = args.item;
42
+ const json = typeof item.json === "object" && item.json !== null ? item.json : {};
43
+ const value = String(json[args.ctx.config.cfg.field] ?? "");
44
+ return {
45
+ ...item,
46
+ json: {
47
+ ...json,
48
+ [args.ctx.config.cfg.field]: value.toUpperCase()
49
+ }
50
+ };
55
51
  }
56
52
  };
57
53
  ExampleUppercaseNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemation/node-example" })], ExampleUppercaseNode);
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ExampleUppercaseNode","out: Item[]","name: string","cfg: { field: TField }","id?: string"],"sources":["../src/ExampleUppercaseNode.ts","../src/uppercase.ts"],"sourcesContent":["import type { Item, Items, Node, NodeExecutionContext, NodeOutputs } from \"@codemation/core\";\n\nimport { node } from \"@codemation/core\";\n\nimport { ExampleUppercase } from \"./uppercase\";\n\n@node({ packageName: \"@codemation/node-example\" })\nexport class ExampleUppercaseNode implements Node<ExampleUppercase<Record<string, unknown>, string>> {\n kind = \"node\" as const;\n outputPorts = [\"main\"] as const;\n\n async execute(\n items: Items,\n ctx: NodeExecutionContext<ExampleUppercase<Record<string, unknown>, string>>,\n ): Promise<NodeOutputs> {\n const out: Item[] = [];\n for (let i = 0; i < items.length; i++) {\n const item = items[i]!;\n const json = typeof item.json === \"object\" && item.json !== null ? (item.json as Record<string, unknown>) : {};\n const value = String(json[ctx.config.cfg.field] ?? \"\");\n out.push({ ...item, json: { ...json, [ctx.config.cfg.field]: value.toUpperCase() } });\n }\n return { main: out };\n }\n}\n","import type { RunnableNodeConfig, TypeToken } from \"@codemation/core\";\n\nimport { ExampleUppercaseNode } from \"./ExampleUppercaseNode\";\n\nexport class ExampleUppercase<\n TInputJson extends Record<string, unknown> = Record<string, unknown>,\n TField extends keyof TInputJson & string = keyof TInputJson & string,\n> implements RunnableNodeConfig<TInputJson, TInputJson> {\n readonly kind = \"node\" as const;\n readonly type: TypeToken<unknown> = ExampleUppercaseNode;\n constructor(\n public readonly name: string,\n public readonly cfg: { field: TField },\n public readonly id?: string,\n ) {}\n}\n\nexport { ExampleUppercaseNode } from \"./ExampleUppercaseNode\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOO,iCAAMA,uBAAwF;CACnG,OAAO;CACP,cAAc,CAAC,OAAO;CAEtB,MAAM,QACJ,OACA,KACsB;EACtB,MAAMC,MAAc,EAAE;AACtB,OAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;GACrC,MAAM,OAAO,MAAM;GACnB,MAAM,OAAO,OAAO,KAAK,SAAS,YAAY,KAAK,SAAS,OAAQ,KAAK,OAAmC,EAAE;GAC9G,MAAM,QAAQ,OAAO,KAAK,IAAI,OAAO,IAAI,UAAU,GAAG;AACtD,OAAI,KAAK;IAAE,GAAG;IAAM,MAAM;KAAE,GAAG;MAAO,IAAI,OAAO,IAAI,QAAQ,MAAM,aAAa;KAAE;IAAE,CAAC;;AAEvF,SAAO,EAAE,MAAM,KAAK;;;+DAhBlB,EAAE,aAAa,4BAA4B,CAAC;;;;ACFlD,IAAa,mBAAb,MAGwD;CACtD,AAAS,OAAO;CAChB,AAAS,OAA2B;CACpC,YACE,AAAgBC,MAChB,AAAgBC,KAChB,AAAgBC,IAChB;EAHgB;EACA;EACA"}
1
+ {"version":3,"file":"index.cjs","names":["ExampleUppercaseNode","name: string","cfg: { field: TField }","id?: string"],"sources":["../src/ExampleUppercaseNode.ts","../src/uppercase.ts"],"sourcesContent":["import type { Item, RunnableNode, RunnableNodeExecuteArgs } from \"@codemation/core\";\n\nimport { node } from \"@codemation/core\";\n\nimport { ExampleUppercase } from \"./uppercase\";\n\n@node({ packageName: \"@codemation/node-example\" })\nexport class ExampleUppercaseNode implements RunnableNode<ExampleUppercase<Record<string, unknown>, string>> {\n kind = \"node\" as const;\n outputPorts = [\"main\"] as const;\n\n execute(args: RunnableNodeExecuteArgs<ExampleUppercase<Record<string, unknown>, string>>): unknown {\n const item = args.item as Item;\n const json = typeof item.json === \"object\" && item.json !== null ? (item.json as Record<string, unknown>) : {};\n const value = String(json[args.ctx.config.cfg.field] ?? \"\");\n return { ...item, json: { ...json, [args.ctx.config.cfg.field]: value.toUpperCase() } };\n }\n}\n","import type { RunnableNodeConfig, TypeToken } from \"@codemation/core\";\n\nimport { ExampleUppercaseNode } from \"./ExampleUppercaseNode\";\n\nexport class ExampleUppercase<\n TInputJson extends Record<string, unknown> = Record<string, unknown>,\n TField extends keyof TInputJson & string = keyof TInputJson & string,\n> implements RunnableNodeConfig<TInputJson, TInputJson> {\n readonly kind = \"node\" as const;\n readonly type: TypeToken<unknown> = ExampleUppercaseNode;\n constructor(\n public readonly name: string,\n public readonly cfg: { field: TField },\n public readonly id?: string,\n ) {}\n}\n\nexport { ExampleUppercaseNode } from \"./ExampleUppercaseNode\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOO,iCAAMA,uBAAgG;CAC3G,OAAO;CACP,cAAc,CAAC,OAAO;CAEtB,QAAQ,MAA2F;EACjG,MAAM,OAAO,KAAK;EAClB,MAAM,OAAO,OAAO,KAAK,SAAS,YAAY,KAAK,SAAS,OAAQ,KAAK,OAAmC,EAAE;EAC9G,MAAM,QAAQ,OAAO,KAAK,KAAK,IAAI,OAAO,IAAI,UAAU,GAAG;AAC3D,SAAO;GAAE,GAAG;GAAM,MAAM;IAAE,GAAG;KAAO,KAAK,IAAI,OAAO,IAAI,QAAQ,MAAM,aAAa;IAAE;GAAE;;;+DATrF,EAAE,aAAa,4BAA4B,CAAC;;;;ACFlD,IAAa,mBAAb,MAGwD;CACtD,AAAS,OAAO;CAChB,AAAS,OAA2B;CACpC,YACE,AAAgBC,MAChB,AAAgBC,KAChB,AAAgBC,IAChB;EAHgB;EACA;EACA"}
package/dist/index.d.cts CHANGED
@@ -128,10 +128,29 @@ interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase>
128
128
  config: TConfig;
129
129
  binary: NodeBinaryAttachmentService;
130
130
  }
131
- interface Node<TConfig extends NodeConfigBase = NodeConfigBase> {
132
- kind: "node";
133
- outputPorts: ReadonlyArray<OutputPortKey>;
134
- execute(items: Items, ctx: NodeExecutionContext<TConfig>): Promise<NodeOutputs>;
131
+ /**
132
+ * Per-item runnable node: return JSON, an array to fan-out on `main`, or {@link emitPorts} for multi-port emission.
133
+ * Engine applies `inputSchema.parse(item.json)` and passes the result as `args.input` (wire `item.json` is unchanged).
134
+ */
135
+ interface RunnableNodeExecuteArgs<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown> {
136
+ readonly input: TInputJson$1;
137
+ readonly item: Item;
138
+ readonly itemIndex: number;
139
+ readonly items: Items;
140
+ readonly ctx: NodeExecutionContext<TConfig>;
141
+ }
142
+ interface RunnableNode<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown, _TOutputJson = unknown> {
143
+ readonly kind: "node";
144
+ /**
145
+ * Declared output ports (e.g. `["main"]`).
146
+ *
147
+ * Prefer describing dynamic router ports (Switch) and fixed multi-ports (If true/false)
148
+ * via {@link NodeConfigBase.declaredOutputPorts}. Engine defaults to `["main"]` when omitted.
149
+ */
150
+ readonly outputPorts?: ReadonlyArray<OutputPortKey>;
151
+ /** When omitted, engine uses {@link RunnableNodeConfig.inputSchema} or `z.unknown()`. */
152
+ readonly inputSchema?: ZodType<TInputJson$1>;
153
+ execute(args: RunnableNodeExecuteArgs<TConfig, TInputJson$1>): Promise<unknown> | unknown;
135
154
  }
136
155
  //#endregion
137
156
  //#region ../core/src/contracts/workflowTypes.d.ts
@@ -166,64 +185,41 @@ interface NodeConfigBase {
166
185
  * main batches skip downstream execution and propagate the empty path.
167
186
  */
168
187
  readonly continueWhenEmptyOutput?: boolean;
188
+ /**
189
+ * Declared I/O port names for canvas authoring (unioned with ports inferred from edges).
190
+ * Use for dynamic routers (Switch) and future error ports.
191
+ */
192
+ readonly declaredOutputPorts?: ReadonlyArray<OutputPortKey>;
193
+ readonly declaredInputPorts?: ReadonlyArray<InputPortKey>;
169
194
  getCredentialRequirements?(): ReadonlyArray<CredentialRequirement>;
170
195
  }
171
196
  declare const runnableNodeInputType: unique symbol;
172
197
  declare const runnableNodeOutputType: unique symbol;
173
- /** Phantom: JSON shape on the wire from upstream before {@link RunnableNodeConfig.mapInput}. */
174
- declare const runnableNodeWireType: unique symbol;
175
- /**
176
- * Read-only execution slice passed to {@link RunnableNodeConfig.mapInput} (aligned with the engine’s
177
- * node execution context for `runId`, `data`, etc.). Use **`ctx.data`** to read **any completed** upstream
178
- * node’s outputs in this run (e.g. `ctx.data.getOutputItems(nodeIdA, "main")` while mapping at D), not only
179
- * the immediate predecessor’s {@link ItemInputMapperArgs.item}.
180
- */
181
- interface ItemInputMapperContext {
182
- readonly runId: RunId;
183
- readonly workflowId: WorkflowId;
184
- /** Node whose activation is being prepared (the consumer of `mapInput`). */
185
- readonly nodeId: NodeId;
186
- readonly activationId: NodeActivationId;
187
- readonly parent?: ParentExecutionRef;
188
- readonly data: RunDataSnapshot;
189
- }
190
- /**
191
- * Arguments for optional per-item input mapping applied by the engine before Zod validation.
192
- */
193
- interface ItemInputMapperArgs<TWireJson$1 = unknown> {
194
- readonly item: Item<TWireJson$1>;
195
- readonly itemIndex: number;
196
- readonly items: Items<TWireJson$1>;
197
- readonly ctx: ItemInputMapperContext;
198
- }
199
- /**
200
- * Per-item mapper before Zod validation. Uses a **bivariant** method signature so concrete
201
- * `ItemInputMapper<SpecificWire, TIn>` remains assignable to `RunnableNodeConfig` fields typed as
202
- * `ItemInputMapper<unknown, unknown>` (same pattern as React-style callbacks).
203
- */
204
- type ItemInputMapper<TWireJson$1 = unknown, TInputJson$1 = unknown> = {
205
- bivarianceHack(args: ItemInputMapperArgs<TWireJson$1>): TInputJson$1 | Promise<TInputJson$1>;
206
- }["bivarianceHack"];
198
+ type LineageCarryPolicy = "emitOnly" | "carryThrough";
207
199
  /**
208
- * Runnable node: **`TInputJson`** is the payload after `mapInput` (if any) + Zod validation — what {@link ItemNode}
209
- * `executeOne` receives. **`TOutputJson`** is emitted `item.json` on outputs. **`TWireJson`** is `item.json` from
210
- * upstream **before** `mapInput`; it defaults to **`TInputJson`** when there is no mapper or wire differs from execute input.
200
+ * Runnable node: **`TInputJson`** is what **`inputSchema`** validates on **`item.json`** (the wire payload).
201
+ * **`TOutputJson`** is emitted `item.json` on outputs.
211
202
  */
212
- interface RunnableNodeConfig<TInputJson$1 = unknown, TOutputJson$1 = unknown, TWireJson$1 = TInputJson$1> extends NodeConfigBase {
203
+ interface RunnableNodeConfig<TInputJson$1 = unknown, TOutputJson$1 = unknown> extends NodeConfigBase {
213
204
  readonly kind: "node";
214
205
  readonly [runnableNodeInputType]?: TInputJson$1;
215
206
  readonly [runnableNodeOutputType]?: TOutputJson$1;
216
- readonly [runnableNodeWireType]?: TWireJson$1;
217
207
  /**
218
- * Optional Zod input contract for {@link ItemNode} when not set on the node class.
208
+ * Optional Zod input contract for {@link RunnableNode} when not set on the node class.
219
209
  * Resolution order: node instance `inputSchema`, then config `inputSchema`, then `z.unknown()`.
220
210
  */
221
211
  readonly inputSchema?: ZodType<TInputJson$1>;
222
212
  /**
223
- * Optional per-item mapper: engine applies it before validating against the node’s `inputSchema`.
224
- * When omitted, the engine validates `item.json` directly.
213
+ * Overrides default lineage propagation for `execute` outputs (binary/meta/paired).
214
+ * Routers with multiple {@link RunnableNode#outputPorts} default to **`carryThrough`**; others default to **`emitOnly`**.
215
+ */
216
+ readonly lineageCarry?: LineageCarryPolicy;
217
+ /**
218
+ * When an activation receives **zero** input items, the engine normally runs `execute` zero times.
219
+ * Set to **`runOnce`** to run `execute` once with an empty `items` batch (and a synthetic wire item for schema parsing).
220
+ * Used by batch-style callback nodes (built-in `Callback`) so `callback([], ctx)` still runs.
225
221
  */
226
- readonly mapInput?: ItemInputMapper<TWireJson$1, TInputJson$1>;
222
+ readonly emptyBatchExecution?: "skip" | "runOnce";
227
223
  }
228
224
  type PairedItemRef = Readonly<{
229
225
  nodeId: NodeId;
@@ -297,10 +293,10 @@ type CredentialRequirement = Readonly<{
297
293
  }>;
298
294
  //#endregion
299
295
  //#region src/ExampleUppercaseNode.d.ts
300
- declare class ExampleUppercaseNode implements Node<ExampleUppercase<Record<string, unknown>, string>> {
296
+ declare class ExampleUppercaseNode implements RunnableNode<ExampleUppercase<Record<string, unknown>, string>> {
301
297
  kind: "node";
302
298
  outputPorts: readonly ["main"];
303
- execute(items: Items, ctx: NodeExecutionContext<ExampleUppercase<Record<string, unknown>, string>>): Promise<NodeOutputs>;
299
+ execute(args: RunnableNodeExecuteArgs<ExampleUppercase<Record<string, unknown>, string>>): unknown;
304
300
  }
305
301
  //#endregion
306
302
  //#region src/uppercase.d.ts
package/dist/index.d.ts CHANGED
@@ -128,10 +128,29 @@ interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase>
128
128
  config: TConfig;
129
129
  binary: NodeBinaryAttachmentService;
130
130
  }
131
- interface Node<TConfig extends NodeConfigBase = NodeConfigBase> {
132
- kind: "node";
133
- outputPorts: ReadonlyArray<OutputPortKey>;
134
- execute(items: Items, ctx: NodeExecutionContext<TConfig>): Promise<NodeOutputs>;
131
+ /**
132
+ * Per-item runnable node: return JSON, an array to fan-out on `main`, or {@link emitPorts} for multi-port emission.
133
+ * Engine applies `inputSchema.parse(item.json)` and passes the result as `args.input` (wire `item.json` is unchanged).
134
+ */
135
+ interface RunnableNodeExecuteArgs<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown> {
136
+ readonly input: TInputJson$1;
137
+ readonly item: Item;
138
+ readonly itemIndex: number;
139
+ readonly items: Items;
140
+ readonly ctx: NodeExecutionContext<TConfig>;
141
+ }
142
+ interface RunnableNode<TConfig extends RunnableNodeConfig<any, any> = RunnableNodeConfig<any, any>, TInputJson$1 = unknown, _TOutputJson = unknown> {
143
+ readonly kind: "node";
144
+ /**
145
+ * Declared output ports (e.g. `["main"]`).
146
+ *
147
+ * Prefer describing dynamic router ports (Switch) and fixed multi-ports (If true/false)
148
+ * via {@link NodeConfigBase.declaredOutputPorts}. Engine defaults to `["main"]` when omitted.
149
+ */
150
+ readonly outputPorts?: ReadonlyArray<OutputPortKey>;
151
+ /** When omitted, engine uses {@link RunnableNodeConfig.inputSchema} or `z.unknown()`. */
152
+ readonly inputSchema?: ZodType<TInputJson$1>;
153
+ execute(args: RunnableNodeExecuteArgs<TConfig, TInputJson$1>): Promise<unknown> | unknown;
135
154
  }
136
155
  //#endregion
137
156
  //#region ../core/src/contracts/workflowTypes.d.ts
@@ -166,64 +185,41 @@ interface NodeConfigBase {
166
185
  * main batches skip downstream execution and propagate the empty path.
167
186
  */
168
187
  readonly continueWhenEmptyOutput?: boolean;
188
+ /**
189
+ * Declared I/O port names for canvas authoring (unioned with ports inferred from edges).
190
+ * Use for dynamic routers (Switch) and future error ports.
191
+ */
192
+ readonly declaredOutputPorts?: ReadonlyArray<OutputPortKey>;
193
+ readonly declaredInputPorts?: ReadonlyArray<InputPortKey>;
169
194
  getCredentialRequirements?(): ReadonlyArray<CredentialRequirement>;
170
195
  }
171
196
  declare const runnableNodeInputType: unique symbol;
172
197
  declare const runnableNodeOutputType: unique symbol;
173
- /** Phantom: JSON shape on the wire from upstream before {@link RunnableNodeConfig.mapInput}. */
174
- declare const runnableNodeWireType: unique symbol;
175
- /**
176
- * Read-only execution slice passed to {@link RunnableNodeConfig.mapInput} (aligned with the engine’s
177
- * node execution context for `runId`, `data`, etc.). Use **`ctx.data`** to read **any completed** upstream
178
- * node’s outputs in this run (e.g. `ctx.data.getOutputItems(nodeIdA, "main")` while mapping at D), not only
179
- * the immediate predecessor’s {@link ItemInputMapperArgs.item}.
180
- */
181
- interface ItemInputMapperContext {
182
- readonly runId: RunId;
183
- readonly workflowId: WorkflowId;
184
- /** Node whose activation is being prepared (the consumer of `mapInput`). */
185
- readonly nodeId: NodeId;
186
- readonly activationId: NodeActivationId;
187
- readonly parent?: ParentExecutionRef;
188
- readonly data: RunDataSnapshot;
189
- }
190
- /**
191
- * Arguments for optional per-item input mapping applied by the engine before Zod validation.
192
- */
193
- interface ItemInputMapperArgs<TWireJson$1 = unknown> {
194
- readonly item: Item<TWireJson$1>;
195
- readonly itemIndex: number;
196
- readonly items: Items<TWireJson$1>;
197
- readonly ctx: ItemInputMapperContext;
198
- }
199
- /**
200
- * Per-item mapper before Zod validation. Uses a **bivariant** method signature so concrete
201
- * `ItemInputMapper<SpecificWire, TIn>` remains assignable to `RunnableNodeConfig` fields typed as
202
- * `ItemInputMapper<unknown, unknown>` (same pattern as React-style callbacks).
203
- */
204
- type ItemInputMapper<TWireJson$1 = unknown, TInputJson$1 = unknown> = {
205
- bivarianceHack(args: ItemInputMapperArgs<TWireJson$1>): TInputJson$1 | Promise<TInputJson$1>;
206
- }["bivarianceHack"];
198
+ type LineageCarryPolicy = "emitOnly" | "carryThrough";
207
199
  /**
208
- * Runnable node: **`TInputJson`** is the payload after `mapInput` (if any) + Zod validation — what {@link ItemNode}
209
- * `executeOne` receives. **`TOutputJson`** is emitted `item.json` on outputs. **`TWireJson`** is `item.json` from
210
- * upstream **before** `mapInput`; it defaults to **`TInputJson`** when there is no mapper or wire differs from execute input.
200
+ * Runnable node: **`TInputJson`** is what **`inputSchema`** validates on **`item.json`** (the wire payload).
201
+ * **`TOutputJson`** is emitted `item.json` on outputs.
211
202
  */
212
- interface RunnableNodeConfig<TInputJson$1 = unknown, TOutputJson$1 = unknown, TWireJson$1 = TInputJson$1> extends NodeConfigBase {
203
+ interface RunnableNodeConfig<TInputJson$1 = unknown, TOutputJson$1 = unknown> extends NodeConfigBase {
213
204
  readonly kind: "node";
214
205
  readonly [runnableNodeInputType]?: TInputJson$1;
215
206
  readonly [runnableNodeOutputType]?: TOutputJson$1;
216
- readonly [runnableNodeWireType]?: TWireJson$1;
217
207
  /**
218
- * Optional Zod input contract for {@link ItemNode} when not set on the node class.
208
+ * Optional Zod input contract for {@link RunnableNode} when not set on the node class.
219
209
  * Resolution order: node instance `inputSchema`, then config `inputSchema`, then `z.unknown()`.
220
210
  */
221
211
  readonly inputSchema?: ZodType<TInputJson$1>;
222
212
  /**
223
- * Optional per-item mapper: engine applies it before validating against the node’s `inputSchema`.
224
- * When omitted, the engine validates `item.json` directly.
213
+ * Overrides default lineage propagation for `execute` outputs (binary/meta/paired).
214
+ * Routers with multiple {@link RunnableNode#outputPorts} default to **`carryThrough`**; others default to **`emitOnly`**.
215
+ */
216
+ readonly lineageCarry?: LineageCarryPolicy;
217
+ /**
218
+ * When an activation receives **zero** input items, the engine normally runs `execute` zero times.
219
+ * Set to **`runOnce`** to run `execute` once with an empty `items` batch (and a synthetic wire item for schema parsing).
220
+ * Used by batch-style callback nodes (built-in `Callback`) so `callback([], ctx)` still runs.
225
221
  */
226
- readonly mapInput?: ItemInputMapper<TWireJson$1, TInputJson$1>;
222
+ readonly emptyBatchExecution?: "skip" | "runOnce";
227
223
  }
228
224
  type PairedItemRef = Readonly<{
229
225
  nodeId: NodeId;
@@ -297,10 +293,10 @@ type CredentialRequirement = Readonly<{
297
293
  }>;
298
294
  //#endregion
299
295
  //#region src/ExampleUppercaseNode.d.ts
300
- declare class ExampleUppercaseNode implements Node<ExampleUppercase<Record<string, unknown>, string>> {
296
+ declare class ExampleUppercaseNode implements RunnableNode<ExampleUppercase<Record<string, unknown>, string>> {
301
297
  kind: "node";
302
298
  outputPorts: readonly ["main"];
303
- execute(items: Items, ctx: NodeExecutionContext<ExampleUppercase<Record<string, unknown>, string>>): Promise<NodeOutputs>;
299
+ execute(args: RunnableNodeExecuteArgs<ExampleUppercase<Record<string, unknown>, string>>): unknown;
304
300
  }
305
301
  //#endregion
306
302
  //#region src/uppercase.d.ts
package/dist/index.js CHANGED
@@ -13,21 +13,17 @@ function __decorate(decorators, target, key, desc) {
13
13
  let ExampleUppercaseNode = class ExampleUppercaseNode$1 {
14
14
  kind = "node";
15
15
  outputPorts = ["main"];
16
- async execute(items, ctx) {
17
- const out = [];
18
- for (let i = 0; i < items.length; i++) {
19
- const item = items[i];
20
- const json = typeof item.json === "object" && item.json !== null ? item.json : {};
21
- const value = String(json[ctx.config.cfg.field] ?? "");
22
- out.push({
23
- ...item,
24
- json: {
25
- ...json,
26
- [ctx.config.cfg.field]: value.toUpperCase()
27
- }
28
- });
29
- }
30
- return { main: out };
16
+ execute(args) {
17
+ const item = args.item;
18
+ const json = typeof item.json === "object" && item.json !== null ? item.json : {};
19
+ const value = String(json[args.ctx.config.cfg.field] ?? "");
20
+ return {
21
+ ...item,
22
+ json: {
23
+ ...json,
24
+ [args.ctx.config.cfg.field]: value.toUpperCase()
25
+ }
26
+ };
31
27
  }
32
28
  };
33
29
  ExampleUppercaseNode = __decorate([node({ packageName: "@codemation/node-example" })], ExampleUppercaseNode);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ExampleUppercaseNode","out: Item[]","name: string","cfg: { field: TField }","id?: string"],"sources":["../src/ExampleUppercaseNode.ts","../src/uppercase.ts"],"sourcesContent":["import type { Item, Items, Node, NodeExecutionContext, NodeOutputs } from \"@codemation/core\";\n\nimport { node } from \"@codemation/core\";\n\nimport { ExampleUppercase } from \"./uppercase\";\n\n@node({ packageName: \"@codemation/node-example\" })\nexport class ExampleUppercaseNode implements Node<ExampleUppercase<Record<string, unknown>, string>> {\n kind = \"node\" as const;\n outputPorts = [\"main\"] as const;\n\n async execute(\n items: Items,\n ctx: NodeExecutionContext<ExampleUppercase<Record<string, unknown>, string>>,\n ): Promise<NodeOutputs> {\n const out: Item[] = [];\n for (let i = 0; i < items.length; i++) {\n const item = items[i]!;\n const json = typeof item.json === \"object\" && item.json !== null ? (item.json as Record<string, unknown>) : {};\n const value = String(json[ctx.config.cfg.field] ?? \"\");\n out.push({ ...item, json: { ...json, [ctx.config.cfg.field]: value.toUpperCase() } });\n }\n return { main: out };\n }\n}\n","import type { RunnableNodeConfig, TypeToken } from \"@codemation/core\";\n\nimport { ExampleUppercaseNode } from \"./ExampleUppercaseNode\";\n\nexport class ExampleUppercase<\n TInputJson extends Record<string, unknown> = Record<string, unknown>,\n TField extends keyof TInputJson & string = keyof TInputJson & string,\n> implements RunnableNodeConfig<TInputJson, TInputJson> {\n readonly kind = \"node\" as const;\n readonly type: TypeToken<unknown> = ExampleUppercaseNode;\n constructor(\n public readonly name: string,\n public readonly cfg: { field: TField },\n public readonly id?: string,\n ) {}\n}\n\nexport { ExampleUppercaseNode } from \"./ExampleUppercaseNode\";\n"],"mappings":";;;;;;;;;;;;AAOO,iCAAMA,uBAAwF;CACnG,OAAO;CACP,cAAc,CAAC,OAAO;CAEtB,MAAM,QACJ,OACA,KACsB;EACtB,MAAMC,MAAc,EAAE;AACtB,OAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;GACrC,MAAM,OAAO,MAAM;GACnB,MAAM,OAAO,OAAO,KAAK,SAAS,YAAY,KAAK,SAAS,OAAQ,KAAK,OAAmC,EAAE;GAC9G,MAAM,QAAQ,OAAO,KAAK,IAAI,OAAO,IAAI,UAAU,GAAG;AACtD,OAAI,KAAK;IAAE,GAAG;IAAM,MAAM;KAAE,GAAG;MAAO,IAAI,OAAO,IAAI,QAAQ,MAAM,aAAa;KAAE;IAAE,CAAC;;AAEvF,SAAO,EAAE,MAAM,KAAK;;;mCAhBvB,KAAK,EAAE,aAAa,4BAA4B,CAAC;;;;ACFlD,IAAa,mBAAb,MAGwD;CACtD,AAAS,OAAO;CAChB,AAAS,OAA2B;CACpC,YACE,AAAgBC,MAChB,AAAgBC,KAChB,AAAgBC,IAChB;EAHgB;EACA;EACA"}
1
+ {"version":3,"file":"index.js","names":["ExampleUppercaseNode","name: string","cfg: { field: TField }","id?: string"],"sources":["../src/ExampleUppercaseNode.ts","../src/uppercase.ts"],"sourcesContent":["import type { Item, RunnableNode, RunnableNodeExecuteArgs } from \"@codemation/core\";\n\nimport { node } from \"@codemation/core\";\n\nimport { ExampleUppercase } from \"./uppercase\";\n\n@node({ packageName: \"@codemation/node-example\" })\nexport class ExampleUppercaseNode implements RunnableNode<ExampleUppercase<Record<string, unknown>, string>> {\n kind = \"node\" as const;\n outputPorts = [\"main\"] as const;\n\n execute(args: RunnableNodeExecuteArgs<ExampleUppercase<Record<string, unknown>, string>>): unknown {\n const item = args.item as Item;\n const json = typeof item.json === \"object\" && item.json !== null ? (item.json as Record<string, unknown>) : {};\n const value = String(json[args.ctx.config.cfg.field] ?? \"\");\n return { ...item, json: { ...json, [args.ctx.config.cfg.field]: value.toUpperCase() } };\n }\n}\n","import type { RunnableNodeConfig, TypeToken } from \"@codemation/core\";\n\nimport { ExampleUppercaseNode } from \"./ExampleUppercaseNode\";\n\nexport class ExampleUppercase<\n TInputJson extends Record<string, unknown> = Record<string, unknown>,\n TField extends keyof TInputJson & string = keyof TInputJson & string,\n> implements RunnableNodeConfig<TInputJson, TInputJson> {\n readonly kind = \"node\" as const;\n readonly type: TypeToken<unknown> = ExampleUppercaseNode;\n constructor(\n public readonly name: string,\n public readonly cfg: { field: TField },\n public readonly id?: string,\n ) {}\n}\n\nexport { ExampleUppercaseNode } from \"./ExampleUppercaseNode\";\n"],"mappings":";;;;;;;;;;;;AAOO,iCAAMA,uBAAgG;CAC3G,OAAO;CACP,cAAc,CAAC,OAAO;CAEtB,QAAQ,MAA2F;EACjG,MAAM,OAAO,KAAK;EAClB,MAAM,OAAO,OAAO,KAAK,SAAS,YAAY,KAAK,SAAS,OAAQ,KAAK,OAAmC,EAAE;EAC9G,MAAM,QAAQ,OAAO,KAAK,KAAK,IAAI,OAAO,IAAI,UAAU,GAAG;AAC3D,SAAO;GAAE,GAAG;GAAM,MAAM;IAAE,GAAG;KAAO,KAAK,IAAI,OAAO,IAAI,QAAQ,MAAM,aAAa;IAAE;GAAE;;;mCAT1F,KAAK,EAAE,aAAa,4BAA4B,CAAC;;;;ACFlD,IAAa,mBAAb,MAGwD;CACtD,AAAS,OAAO;CAChB,AAAS,OAA2B;CACpC,YACE,AAAgBC,MAChB,AAAgBC,KAChB,AAAgBC,IAChB;EAHgB;EACA;EACA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemation/node-example",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -28,7 +28,7 @@
28
28
  }
29
29
  },
30
30
  "dependencies": {
31
- "@codemation/core": "0.2.3"
31
+ "@codemation/core": "0.4.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/node": "^25.3.5",
@@ -37,6 +37,7 @@
37
37
  "typescript": "^5.9.3"
38
38
  },
39
39
  "scripts": {
40
+ "changeset:verify": "pnpm --workspace-root run changeset:verify",
40
41
  "dev": "tsdown --watch",
41
42
  "build": "tsdown",
42
43
  "typecheck": "tsc -p tsconfig.json --noEmit",
@@ -1,25 +1,18 @@
1
- import type { Item, Items, Node, NodeExecutionContext, NodeOutputs } from "@codemation/core";
1
+ import type { Item, RunnableNode, RunnableNodeExecuteArgs } from "@codemation/core";
2
2
 
3
3
  import { node } from "@codemation/core";
4
4
 
5
5
  import { ExampleUppercase } from "./uppercase";
6
6
 
7
7
  @node({ packageName: "@codemation/node-example" })
8
- export class ExampleUppercaseNode implements Node<ExampleUppercase<Record<string, unknown>, string>> {
8
+ export class ExampleUppercaseNode implements RunnableNode<ExampleUppercase<Record<string, unknown>, string>> {
9
9
  kind = "node" as const;
10
10
  outputPorts = ["main"] as const;
11
11
 
12
- async execute(
13
- items: Items,
14
- ctx: NodeExecutionContext<ExampleUppercase<Record<string, unknown>, string>>,
15
- ): Promise<NodeOutputs> {
16
- const out: Item[] = [];
17
- for (let i = 0; i < items.length; i++) {
18
- const item = items[i]!;
19
- const json = typeof item.json === "object" && item.json !== null ? (item.json as Record<string, unknown>) : {};
20
- const value = String(json[ctx.config.cfg.field] ?? "");
21
- out.push({ ...item, json: { ...json, [ctx.config.cfg.field]: value.toUpperCase() } });
22
- }
23
- return { main: out };
12
+ execute(args: RunnableNodeExecuteArgs<ExampleUppercase<Record<string, unknown>, string>>): unknown {
13
+ const item = args.item as Item;
14
+ const json = typeof item.json === "object" && item.json !== null ? (item.json as Record<string, unknown>) : {};
15
+ const value = String(json[args.ctx.config.cfg.field] ?? "");
16
+ return { ...item, json: { ...json, [args.ctx.config.cfg.field]: value.toUpperCase() } };
24
17
  }
25
18
  }