@codemation/node-example 0.0.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 +23 -0
- package/dist/chunk-fLflgnQm.js +25 -0
- package/dist/index.cjs +79 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +270 -0
- package/dist/index.d.ts +270 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
- package/src/ExampleUppercaseNode.ts +25 -0
- package/src/index.ts +1 -0
- package/src/uppercase.ts +18 -0
- package/tsconfig.json +9 -0
- package/tsdown.config.ts +10 -0
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# `@codemation/node-example`
|
|
2
|
+
|
|
3
|
+
A **minimal example node package**: shows how to ship a custom node (config + implementation) that depends only on `@codemation/core`. The monorepo uses it in tests and as a template for **community or private node packages**.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @codemation/node-example@^0.0.0
|
|
9
|
+
# or
|
|
10
|
+
npm install @codemation/node-example@^0.0.0
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## When to use
|
|
14
|
+
|
|
15
|
+
Reference or copy this package when you author a new **`node-*`** package. Adding a real node package should not require changes inside `@codemation/core`.
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { ExampleUppercase, ExampleUppercaseNode } from "@codemation/node-example";
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Inspect `src/` for the uppercase sample node pattern, then replace it with your own `NodeConfigBase` and `Node` classes and export them from your package’s public entry.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { };
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
let __codemation_core = require("@codemation/core");
|
|
25
|
+
__codemation_core = __toESM(__codemation_core);
|
|
26
|
+
|
|
27
|
+
//#region \0@oxc-project+runtime@0.95.0/helpers/decorate.js
|
|
28
|
+
function __decorate(decorators, target, key, desc) {
|
|
29
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
30
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
31
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
32
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/ExampleUppercaseNode.ts
|
|
37
|
+
let ExampleUppercaseNode = class ExampleUppercaseNode$1 {
|
|
38
|
+
kind = "node";
|
|
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 };
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
ExampleUppercaseNode = __decorate([(0, __codemation_core.node)({ packageName: "@codemation/node-example" })], ExampleUppercaseNode);
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/uppercase.ts
|
|
61
|
+
var ExampleUppercase = class {
|
|
62
|
+
kind = "node";
|
|
63
|
+
type = ExampleUppercaseNode;
|
|
64
|
+
constructor(name, cfg, id) {
|
|
65
|
+
this.name = name;
|
|
66
|
+
this.cfg = cfg;
|
|
67
|
+
this.id = id;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
exports.ExampleUppercase = ExampleUppercase;
|
|
73
|
+
Object.defineProperty(exports, 'ExampleUppercaseNode', {
|
|
74
|
+
enumerable: true,
|
|
75
|
+
get: function () {
|
|
76
|
+
return ExampleUppercaseNode;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +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"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { ReadableStream } from "node:stream/web";
|
|
2
|
+
import { InjectionToken as TypeToken } from "tsyringe";
|
|
3
|
+
|
|
4
|
+
//#region ../core/src/contracts/retryPolicySpec.types.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* In-process retry policy for runnable nodes. Serialized configs use the same
|
|
8
|
+
* `kind` discriminator (`JSON.stringify` / persisted workflows).
|
|
9
|
+
*
|
|
10
|
+
* `maxAttempts` is the total number of tries including the first (e.g. 3 means up to 2 delays after failures).
|
|
11
|
+
*/
|
|
12
|
+
type RetryPolicySpec = NoneRetryPolicySpec | FixedRetryPolicySpec | ExponentialRetryPolicySpec;
|
|
13
|
+
interface NoneRetryPolicySpec {
|
|
14
|
+
readonly kind: "none";
|
|
15
|
+
}
|
|
16
|
+
interface FixedRetryPolicySpec {
|
|
17
|
+
readonly kind: "fixed";
|
|
18
|
+
/** Total attempts including the first execution. Must be >= 1. */
|
|
19
|
+
readonly maxAttempts: number;
|
|
20
|
+
readonly delayMs: number;
|
|
21
|
+
}
|
|
22
|
+
interface ExponentialRetryPolicySpec {
|
|
23
|
+
readonly kind: "exponential";
|
|
24
|
+
/** Total attempts including the first execution. Must be >= 1. */
|
|
25
|
+
readonly maxAttempts: number;
|
|
26
|
+
readonly initialDelayMs: number;
|
|
27
|
+
readonly multiplier: number;
|
|
28
|
+
readonly maxDelayMs?: number;
|
|
29
|
+
/** When true, each delay is multiplied by a random factor in [1, 1.2). */
|
|
30
|
+
readonly jitter?: boolean;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region ../core/src/contracts/runTypes.d.ts
|
|
34
|
+
|
|
35
|
+
type NodeInputsByPort = Readonly<Record<InputPortKey, Items>>;
|
|
36
|
+
type NodeExecutionStatus = "pending" | "queued" | "running" | "completed" | "failed" | "skipped";
|
|
37
|
+
interface NodeExecutionError {
|
|
38
|
+
message: string;
|
|
39
|
+
name?: string;
|
|
40
|
+
stack?: string;
|
|
41
|
+
}
|
|
42
|
+
/** Stable id for a single connection invocation row in {@link ConnectionInvocationRecord}. */
|
|
43
|
+
type ConnectionInvocationId = string;
|
|
44
|
+
/** Arguments for appending a {@link ConnectionInvocationRecord} (engine fills run/workflow ids and timestamps). */
|
|
45
|
+
type ConnectionInvocationAppendArgs = Readonly<{
|
|
46
|
+
invocationId: ConnectionInvocationId;
|
|
47
|
+
connectionNodeId: NodeId;
|
|
48
|
+
parentAgentNodeId: NodeId;
|
|
49
|
+
parentAgentActivationId: NodeActivationId;
|
|
50
|
+
status: NodeExecutionStatus;
|
|
51
|
+
managedInput?: JsonValue;
|
|
52
|
+
managedOutput?: JsonValue;
|
|
53
|
+
error?: NodeExecutionError;
|
|
54
|
+
queuedAt?: string;
|
|
55
|
+
startedAt?: string;
|
|
56
|
+
finishedAt?: string;
|
|
57
|
+
}>;
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region ../core/src/contracts/runtimeTypes.d.ts
|
|
60
|
+
interface NodeExecutionStatePublisher {
|
|
61
|
+
markQueued(args: {
|
|
62
|
+
nodeId: NodeId;
|
|
63
|
+
activationId?: NodeActivationId;
|
|
64
|
+
inputsByPort?: NodeInputsByPort;
|
|
65
|
+
}): Promise<void>;
|
|
66
|
+
markRunning(args: {
|
|
67
|
+
nodeId: NodeId;
|
|
68
|
+
activationId?: NodeActivationId;
|
|
69
|
+
inputsByPort?: NodeInputsByPort;
|
|
70
|
+
}): Promise<void>;
|
|
71
|
+
markCompleted(args: {
|
|
72
|
+
nodeId: NodeId;
|
|
73
|
+
activationId?: NodeActivationId;
|
|
74
|
+
inputsByPort?: NodeInputsByPort;
|
|
75
|
+
outputs?: NodeOutputs;
|
|
76
|
+
}): Promise<void>;
|
|
77
|
+
markFailed(args: {
|
|
78
|
+
nodeId: NodeId;
|
|
79
|
+
activationId?: NodeActivationId;
|
|
80
|
+
inputsByPort?: NodeInputsByPort;
|
|
81
|
+
error: Error;
|
|
82
|
+
}): Promise<void>;
|
|
83
|
+
appendConnectionInvocation(args: ConnectionInvocationAppendArgs): Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
type BinaryBody = ReadableStream<Uint8Array> | AsyncIterable<Uint8Array> | Uint8Array | ArrayBuffer;
|
|
86
|
+
interface BinaryStorageReadResult {
|
|
87
|
+
body: ReadableStream<Uint8Array>;
|
|
88
|
+
size?: number;
|
|
89
|
+
}
|
|
90
|
+
interface BinaryAttachmentCreateRequest {
|
|
91
|
+
name: string;
|
|
92
|
+
body: BinaryBody;
|
|
93
|
+
mimeType: string;
|
|
94
|
+
filename?: string;
|
|
95
|
+
previewKind?: BinaryAttachment["previewKind"];
|
|
96
|
+
}
|
|
97
|
+
interface NodeBinaryAttachmentService extends ExecutionBinaryService {
|
|
98
|
+
attach(args: BinaryAttachmentCreateRequest): Promise<BinaryAttachment>;
|
|
99
|
+
withAttachment<TJson>(item: Item<TJson>, name: string, attachment: BinaryAttachment): Item<TJson>;
|
|
100
|
+
}
|
|
101
|
+
interface ExecutionBinaryService {
|
|
102
|
+
forNode(args: {
|
|
103
|
+
nodeId: NodeId;
|
|
104
|
+
activationId: NodeActivationId;
|
|
105
|
+
}): NodeBinaryAttachmentService;
|
|
106
|
+
openReadStream(attachment: BinaryAttachment): Promise<BinaryStorageReadResult | undefined>;
|
|
107
|
+
}
|
|
108
|
+
interface ExecutionContext {
|
|
109
|
+
runId: RunId;
|
|
110
|
+
workflowId: WorkflowId;
|
|
111
|
+
parent?: ParentExecutionRef;
|
|
112
|
+
/** This run's subworkflow depth (0 = root). */
|
|
113
|
+
subworkflowDepth: number;
|
|
114
|
+
/** Effective activation budget cap for this run (after policy merge). */
|
|
115
|
+
engineMaxNodeActivations: number;
|
|
116
|
+
/** Effective subworkflow nesting cap for this run (after policy merge). */
|
|
117
|
+
engineMaxSubworkflowDepth: number;
|
|
118
|
+
now: () => Date;
|
|
119
|
+
data: RunDataSnapshot;
|
|
120
|
+
nodeState?: NodeExecutionStatePublisher;
|
|
121
|
+
binary: ExecutionBinaryService;
|
|
122
|
+
getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
|
|
123
|
+
}
|
|
124
|
+
interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase> extends ExecutionContext {
|
|
125
|
+
nodeId: NodeId;
|
|
126
|
+
activationId: NodeActivationId;
|
|
127
|
+
config: TConfig;
|
|
128
|
+
binary: NodeBinaryAttachmentService;
|
|
129
|
+
}
|
|
130
|
+
interface Node<TConfig extends NodeConfigBase = NodeConfigBase> {
|
|
131
|
+
kind: "node";
|
|
132
|
+
outputPorts: ReadonlyArray<OutputPortKey>;
|
|
133
|
+
execute(items: Items, ctx: NodeExecutionContext<TConfig>): Promise<NodeOutputs>;
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region ../core/src/contracts/workflowTypes.d.ts
|
|
137
|
+
type WorkflowId = string;
|
|
138
|
+
type NodeId = string;
|
|
139
|
+
type OutputPortKey = string;
|
|
140
|
+
type InputPortKey = string;
|
|
141
|
+
type NodeKind = "trigger" | "node";
|
|
142
|
+
type JsonPrimitive = string | number | boolean | null;
|
|
143
|
+
interface JsonObject {
|
|
144
|
+
readonly [key: string]: JsonValue;
|
|
145
|
+
}
|
|
146
|
+
type JsonValue = JsonPrimitive | JsonObject | JsonArray;
|
|
147
|
+
type JsonArray = ReadonlyArray<JsonValue>;
|
|
148
|
+
interface NodeConfigBase {
|
|
149
|
+
readonly kind: NodeKind;
|
|
150
|
+
readonly type: TypeToken<unknown>;
|
|
151
|
+
readonly name?: string;
|
|
152
|
+
readonly id?: NodeId;
|
|
153
|
+
readonly icon?: string;
|
|
154
|
+
readonly execution?: Readonly<{
|
|
155
|
+
hint?: "local" | "worker";
|
|
156
|
+
queue?: string;
|
|
157
|
+
}>;
|
|
158
|
+
/** In-process execute retries (runnable nodes). Triggers typically omit this. */
|
|
159
|
+
readonly retryPolicy?: RetryPolicySpec;
|
|
160
|
+
/** Recover from execute failures; return outputs to continue, or rethrow to fail the node. */
|
|
161
|
+
readonly nodeErrorHandler?: NodeErrorHandlerSpec;
|
|
162
|
+
/**
|
|
163
|
+
* When true, edges carrying zero items on an output port still schedule single-input downstream nodes.
|
|
164
|
+
* Decided from the **source** node that produced the (empty) output. Default (false/undefined): empty
|
|
165
|
+
* main batches skip downstream execution and propagate the empty path.
|
|
166
|
+
*/
|
|
167
|
+
readonly continueWhenEmptyOutput?: boolean;
|
|
168
|
+
getCredentialRequirements?(): ReadonlyArray<CredentialRequirement>;
|
|
169
|
+
}
|
|
170
|
+
declare const runnableNodeInputType: unique symbol;
|
|
171
|
+
declare const runnableNodeOutputType: unique symbol;
|
|
172
|
+
interface RunnableNodeConfig<TInputJson$1 = unknown, TOutputJson$1 = unknown> extends NodeConfigBase {
|
|
173
|
+
readonly kind: "node";
|
|
174
|
+
readonly [runnableNodeInputType]?: TInputJson$1;
|
|
175
|
+
readonly [runnableNodeOutputType]?: TOutputJson$1;
|
|
176
|
+
}
|
|
177
|
+
type PairedItemRef = Readonly<{
|
|
178
|
+
nodeId: NodeId;
|
|
179
|
+
output: OutputPortKey;
|
|
180
|
+
itemIndex: number;
|
|
181
|
+
}>;
|
|
182
|
+
type BinaryPreviewKind = "image" | "audio" | "video" | "download";
|
|
183
|
+
type BinaryAttachment = Readonly<{
|
|
184
|
+
id: string;
|
|
185
|
+
storageKey: string;
|
|
186
|
+
mimeType: string;
|
|
187
|
+
size: number;
|
|
188
|
+
storageDriver: string;
|
|
189
|
+
previewKind: BinaryPreviewKind;
|
|
190
|
+
createdAt: string;
|
|
191
|
+
runId: RunId;
|
|
192
|
+
workflowId: WorkflowId;
|
|
193
|
+
nodeId: NodeId;
|
|
194
|
+
activationId: NodeActivationId;
|
|
195
|
+
filename?: string;
|
|
196
|
+
sha256?: string;
|
|
197
|
+
}>;
|
|
198
|
+
type ItemBinary = Readonly<Record<string, BinaryAttachment>>;
|
|
199
|
+
type Item<TJson = unknown> = Readonly<{
|
|
200
|
+
json: TJson;
|
|
201
|
+
binary?: ItemBinary;
|
|
202
|
+
meta?: Readonly<Record<string, unknown>>;
|
|
203
|
+
paired?: ReadonlyArray<PairedItemRef>;
|
|
204
|
+
}>;
|
|
205
|
+
type Items<TJson = unknown> = ReadonlyArray<Item<TJson>>;
|
|
206
|
+
type NodeOutputs = Partial<Record<OutputPortKey, Items>>;
|
|
207
|
+
type RunId = string;
|
|
208
|
+
type NodeActivationId = string;
|
|
209
|
+
interface ParentExecutionRef {
|
|
210
|
+
runId: RunId;
|
|
211
|
+
workflowId: WorkflowId;
|
|
212
|
+
nodeId: NodeId;
|
|
213
|
+
/** Subworkflow depth of the **spawning** run (0 = root). Passed when starting a child run. */
|
|
214
|
+
subworkflowDepth?: number;
|
|
215
|
+
/** Effective max node activations from the parent run (propagated to child policy merge). */
|
|
216
|
+
engineMaxNodeActivations?: number;
|
|
217
|
+
/** Effective max subworkflow depth from the parent run (propagated to child policy merge). */
|
|
218
|
+
engineMaxSubworkflowDepth?: number;
|
|
219
|
+
}
|
|
220
|
+
interface RunDataSnapshot {
|
|
221
|
+
getOutputs(nodeId: NodeId): NodeOutputs | undefined;
|
|
222
|
+
getOutputItems(nodeId: NodeId, output?: OutputPortKey): Items;
|
|
223
|
+
getOutputItem(nodeId: NodeId, itemIndex: number, output?: OutputPortKey): Item | undefined;
|
|
224
|
+
}
|
|
225
|
+
interface NodeErrorHandlerArgs<TConfig extends NodeConfigBase = NodeConfigBase> {
|
|
226
|
+
readonly kind: "single" | "multi";
|
|
227
|
+
readonly items: Items;
|
|
228
|
+
readonly inputsByPort: Readonly<Record<InputPortKey, Items>> | undefined;
|
|
229
|
+
readonly ctx: NodeExecutionContext<TConfig>;
|
|
230
|
+
readonly error: Error;
|
|
231
|
+
}
|
|
232
|
+
interface NodeErrorHandler {
|
|
233
|
+
handle<TConfig extends NodeConfigBase>(args: NodeErrorHandlerArgs<TConfig>): Promise<NodeOutputs>;
|
|
234
|
+
}
|
|
235
|
+
type NodeErrorHandlerSpec = TypeToken<NodeErrorHandler> | NodeErrorHandler;
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region ../core/src/contracts/credentialTypes.d.ts
|
|
238
|
+
type CredentialTypeId = string;
|
|
239
|
+
type CredentialRequirement = Readonly<{
|
|
240
|
+
slotKey: string;
|
|
241
|
+
label: string;
|
|
242
|
+
acceptedTypes: ReadonlyArray<CredentialTypeId>;
|
|
243
|
+
optional?: true;
|
|
244
|
+
helpText?: string;
|
|
245
|
+
helpUrl?: string;
|
|
246
|
+
}>;
|
|
247
|
+
//#endregion
|
|
248
|
+
//#region src/ExampleUppercaseNode.d.ts
|
|
249
|
+
declare class ExampleUppercaseNode implements Node<ExampleUppercase<Record<string, unknown>, string>> {
|
|
250
|
+
kind: "node";
|
|
251
|
+
outputPorts: readonly ["main"];
|
|
252
|
+
execute(items: Items, ctx: NodeExecutionContext<ExampleUppercase<Record<string, unknown>, string>>): Promise<NodeOutputs>;
|
|
253
|
+
}
|
|
254
|
+
//#endregion
|
|
255
|
+
//#region src/uppercase.d.ts
|
|
256
|
+
declare class ExampleUppercase<TInputJson$1 extends Record<string, unknown> = Record<string, unknown>, TField extends keyof TInputJson$1 & string = keyof TInputJson$1 & string> implements RunnableNodeConfig<TInputJson$1, TInputJson$1> {
|
|
257
|
+
readonly name: string;
|
|
258
|
+
readonly cfg: {
|
|
259
|
+
field: TField;
|
|
260
|
+
};
|
|
261
|
+
readonly id?: string | undefined;
|
|
262
|
+
readonly kind: "node";
|
|
263
|
+
readonly type: TypeToken<unknown>;
|
|
264
|
+
constructor(name: string, cfg: {
|
|
265
|
+
field: TField;
|
|
266
|
+
}, id?: string | undefined);
|
|
267
|
+
}
|
|
268
|
+
//#endregion
|
|
269
|
+
export { ExampleUppercase, ExampleUppercaseNode };
|
|
270
|
+
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { ReadableStream } from "node:stream/web";
|
|
2
|
+
import { InjectionToken as TypeToken } from "tsyringe";
|
|
3
|
+
|
|
4
|
+
//#region ../core/src/contracts/retryPolicySpec.types.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* In-process retry policy for runnable nodes. Serialized configs use the same
|
|
8
|
+
* `kind` discriminator (`JSON.stringify` / persisted workflows).
|
|
9
|
+
*
|
|
10
|
+
* `maxAttempts` is the total number of tries including the first (e.g. 3 means up to 2 delays after failures).
|
|
11
|
+
*/
|
|
12
|
+
type RetryPolicySpec = NoneRetryPolicySpec | FixedRetryPolicySpec | ExponentialRetryPolicySpec;
|
|
13
|
+
interface NoneRetryPolicySpec {
|
|
14
|
+
readonly kind: "none";
|
|
15
|
+
}
|
|
16
|
+
interface FixedRetryPolicySpec {
|
|
17
|
+
readonly kind: "fixed";
|
|
18
|
+
/** Total attempts including the first execution. Must be >= 1. */
|
|
19
|
+
readonly maxAttempts: number;
|
|
20
|
+
readonly delayMs: number;
|
|
21
|
+
}
|
|
22
|
+
interface ExponentialRetryPolicySpec {
|
|
23
|
+
readonly kind: "exponential";
|
|
24
|
+
/** Total attempts including the first execution. Must be >= 1. */
|
|
25
|
+
readonly maxAttempts: number;
|
|
26
|
+
readonly initialDelayMs: number;
|
|
27
|
+
readonly multiplier: number;
|
|
28
|
+
readonly maxDelayMs?: number;
|
|
29
|
+
/** When true, each delay is multiplied by a random factor in [1, 1.2). */
|
|
30
|
+
readonly jitter?: boolean;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region ../core/src/contracts/runTypes.d.ts
|
|
34
|
+
|
|
35
|
+
type NodeInputsByPort = Readonly<Record<InputPortKey, Items>>;
|
|
36
|
+
type NodeExecutionStatus = "pending" | "queued" | "running" | "completed" | "failed" | "skipped";
|
|
37
|
+
interface NodeExecutionError {
|
|
38
|
+
message: string;
|
|
39
|
+
name?: string;
|
|
40
|
+
stack?: string;
|
|
41
|
+
}
|
|
42
|
+
/** Stable id for a single connection invocation row in {@link ConnectionInvocationRecord}. */
|
|
43
|
+
type ConnectionInvocationId = string;
|
|
44
|
+
/** Arguments for appending a {@link ConnectionInvocationRecord} (engine fills run/workflow ids and timestamps). */
|
|
45
|
+
type ConnectionInvocationAppendArgs = Readonly<{
|
|
46
|
+
invocationId: ConnectionInvocationId;
|
|
47
|
+
connectionNodeId: NodeId;
|
|
48
|
+
parentAgentNodeId: NodeId;
|
|
49
|
+
parentAgentActivationId: NodeActivationId;
|
|
50
|
+
status: NodeExecutionStatus;
|
|
51
|
+
managedInput?: JsonValue;
|
|
52
|
+
managedOutput?: JsonValue;
|
|
53
|
+
error?: NodeExecutionError;
|
|
54
|
+
queuedAt?: string;
|
|
55
|
+
startedAt?: string;
|
|
56
|
+
finishedAt?: string;
|
|
57
|
+
}>;
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region ../core/src/contracts/runtimeTypes.d.ts
|
|
60
|
+
interface NodeExecutionStatePublisher {
|
|
61
|
+
markQueued(args: {
|
|
62
|
+
nodeId: NodeId;
|
|
63
|
+
activationId?: NodeActivationId;
|
|
64
|
+
inputsByPort?: NodeInputsByPort;
|
|
65
|
+
}): Promise<void>;
|
|
66
|
+
markRunning(args: {
|
|
67
|
+
nodeId: NodeId;
|
|
68
|
+
activationId?: NodeActivationId;
|
|
69
|
+
inputsByPort?: NodeInputsByPort;
|
|
70
|
+
}): Promise<void>;
|
|
71
|
+
markCompleted(args: {
|
|
72
|
+
nodeId: NodeId;
|
|
73
|
+
activationId?: NodeActivationId;
|
|
74
|
+
inputsByPort?: NodeInputsByPort;
|
|
75
|
+
outputs?: NodeOutputs;
|
|
76
|
+
}): Promise<void>;
|
|
77
|
+
markFailed(args: {
|
|
78
|
+
nodeId: NodeId;
|
|
79
|
+
activationId?: NodeActivationId;
|
|
80
|
+
inputsByPort?: NodeInputsByPort;
|
|
81
|
+
error: Error;
|
|
82
|
+
}): Promise<void>;
|
|
83
|
+
appendConnectionInvocation(args: ConnectionInvocationAppendArgs): Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
type BinaryBody = ReadableStream<Uint8Array> | AsyncIterable<Uint8Array> | Uint8Array | ArrayBuffer;
|
|
86
|
+
interface BinaryStorageReadResult {
|
|
87
|
+
body: ReadableStream<Uint8Array>;
|
|
88
|
+
size?: number;
|
|
89
|
+
}
|
|
90
|
+
interface BinaryAttachmentCreateRequest {
|
|
91
|
+
name: string;
|
|
92
|
+
body: BinaryBody;
|
|
93
|
+
mimeType: string;
|
|
94
|
+
filename?: string;
|
|
95
|
+
previewKind?: BinaryAttachment["previewKind"];
|
|
96
|
+
}
|
|
97
|
+
interface NodeBinaryAttachmentService extends ExecutionBinaryService {
|
|
98
|
+
attach(args: BinaryAttachmentCreateRequest): Promise<BinaryAttachment>;
|
|
99
|
+
withAttachment<TJson>(item: Item<TJson>, name: string, attachment: BinaryAttachment): Item<TJson>;
|
|
100
|
+
}
|
|
101
|
+
interface ExecutionBinaryService {
|
|
102
|
+
forNode(args: {
|
|
103
|
+
nodeId: NodeId;
|
|
104
|
+
activationId: NodeActivationId;
|
|
105
|
+
}): NodeBinaryAttachmentService;
|
|
106
|
+
openReadStream(attachment: BinaryAttachment): Promise<BinaryStorageReadResult | undefined>;
|
|
107
|
+
}
|
|
108
|
+
interface ExecutionContext {
|
|
109
|
+
runId: RunId;
|
|
110
|
+
workflowId: WorkflowId;
|
|
111
|
+
parent?: ParentExecutionRef;
|
|
112
|
+
/** This run's subworkflow depth (0 = root). */
|
|
113
|
+
subworkflowDepth: number;
|
|
114
|
+
/** Effective activation budget cap for this run (after policy merge). */
|
|
115
|
+
engineMaxNodeActivations: number;
|
|
116
|
+
/** Effective subworkflow nesting cap for this run (after policy merge). */
|
|
117
|
+
engineMaxSubworkflowDepth: number;
|
|
118
|
+
now: () => Date;
|
|
119
|
+
data: RunDataSnapshot;
|
|
120
|
+
nodeState?: NodeExecutionStatePublisher;
|
|
121
|
+
binary: ExecutionBinaryService;
|
|
122
|
+
getCredential<TSession = unknown>(slotKey: string): Promise<TSession>;
|
|
123
|
+
}
|
|
124
|
+
interface NodeExecutionContext<TConfig extends NodeConfigBase = NodeConfigBase> extends ExecutionContext {
|
|
125
|
+
nodeId: NodeId;
|
|
126
|
+
activationId: NodeActivationId;
|
|
127
|
+
config: TConfig;
|
|
128
|
+
binary: NodeBinaryAttachmentService;
|
|
129
|
+
}
|
|
130
|
+
interface Node<TConfig extends NodeConfigBase = NodeConfigBase> {
|
|
131
|
+
kind: "node";
|
|
132
|
+
outputPorts: ReadonlyArray<OutputPortKey>;
|
|
133
|
+
execute(items: Items, ctx: NodeExecutionContext<TConfig>): Promise<NodeOutputs>;
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region ../core/src/contracts/workflowTypes.d.ts
|
|
137
|
+
type WorkflowId = string;
|
|
138
|
+
type NodeId = string;
|
|
139
|
+
type OutputPortKey = string;
|
|
140
|
+
type InputPortKey = string;
|
|
141
|
+
type NodeKind = "trigger" | "node";
|
|
142
|
+
type JsonPrimitive = string | number | boolean | null;
|
|
143
|
+
interface JsonObject {
|
|
144
|
+
readonly [key: string]: JsonValue;
|
|
145
|
+
}
|
|
146
|
+
type JsonValue = JsonPrimitive | JsonObject | JsonArray;
|
|
147
|
+
type JsonArray = ReadonlyArray<JsonValue>;
|
|
148
|
+
interface NodeConfigBase {
|
|
149
|
+
readonly kind: NodeKind;
|
|
150
|
+
readonly type: TypeToken<unknown>;
|
|
151
|
+
readonly name?: string;
|
|
152
|
+
readonly id?: NodeId;
|
|
153
|
+
readonly icon?: string;
|
|
154
|
+
readonly execution?: Readonly<{
|
|
155
|
+
hint?: "local" | "worker";
|
|
156
|
+
queue?: string;
|
|
157
|
+
}>;
|
|
158
|
+
/** In-process execute retries (runnable nodes). Triggers typically omit this. */
|
|
159
|
+
readonly retryPolicy?: RetryPolicySpec;
|
|
160
|
+
/** Recover from execute failures; return outputs to continue, or rethrow to fail the node. */
|
|
161
|
+
readonly nodeErrorHandler?: NodeErrorHandlerSpec;
|
|
162
|
+
/**
|
|
163
|
+
* When true, edges carrying zero items on an output port still schedule single-input downstream nodes.
|
|
164
|
+
* Decided from the **source** node that produced the (empty) output. Default (false/undefined): empty
|
|
165
|
+
* main batches skip downstream execution and propagate the empty path.
|
|
166
|
+
*/
|
|
167
|
+
readonly continueWhenEmptyOutput?: boolean;
|
|
168
|
+
getCredentialRequirements?(): ReadonlyArray<CredentialRequirement>;
|
|
169
|
+
}
|
|
170
|
+
declare const runnableNodeInputType: unique symbol;
|
|
171
|
+
declare const runnableNodeOutputType: unique symbol;
|
|
172
|
+
interface RunnableNodeConfig<TInputJson$1 = unknown, TOutputJson$1 = unknown> extends NodeConfigBase {
|
|
173
|
+
readonly kind: "node";
|
|
174
|
+
readonly [runnableNodeInputType]?: TInputJson$1;
|
|
175
|
+
readonly [runnableNodeOutputType]?: TOutputJson$1;
|
|
176
|
+
}
|
|
177
|
+
type PairedItemRef = Readonly<{
|
|
178
|
+
nodeId: NodeId;
|
|
179
|
+
output: OutputPortKey;
|
|
180
|
+
itemIndex: number;
|
|
181
|
+
}>;
|
|
182
|
+
type BinaryPreviewKind = "image" | "audio" | "video" | "download";
|
|
183
|
+
type BinaryAttachment = Readonly<{
|
|
184
|
+
id: string;
|
|
185
|
+
storageKey: string;
|
|
186
|
+
mimeType: string;
|
|
187
|
+
size: number;
|
|
188
|
+
storageDriver: string;
|
|
189
|
+
previewKind: BinaryPreviewKind;
|
|
190
|
+
createdAt: string;
|
|
191
|
+
runId: RunId;
|
|
192
|
+
workflowId: WorkflowId;
|
|
193
|
+
nodeId: NodeId;
|
|
194
|
+
activationId: NodeActivationId;
|
|
195
|
+
filename?: string;
|
|
196
|
+
sha256?: string;
|
|
197
|
+
}>;
|
|
198
|
+
type ItemBinary = Readonly<Record<string, BinaryAttachment>>;
|
|
199
|
+
type Item<TJson = unknown> = Readonly<{
|
|
200
|
+
json: TJson;
|
|
201
|
+
binary?: ItemBinary;
|
|
202
|
+
meta?: Readonly<Record<string, unknown>>;
|
|
203
|
+
paired?: ReadonlyArray<PairedItemRef>;
|
|
204
|
+
}>;
|
|
205
|
+
type Items<TJson = unknown> = ReadonlyArray<Item<TJson>>;
|
|
206
|
+
type NodeOutputs = Partial<Record<OutputPortKey, Items>>;
|
|
207
|
+
type RunId = string;
|
|
208
|
+
type NodeActivationId = string;
|
|
209
|
+
interface ParentExecutionRef {
|
|
210
|
+
runId: RunId;
|
|
211
|
+
workflowId: WorkflowId;
|
|
212
|
+
nodeId: NodeId;
|
|
213
|
+
/** Subworkflow depth of the **spawning** run (0 = root). Passed when starting a child run. */
|
|
214
|
+
subworkflowDepth?: number;
|
|
215
|
+
/** Effective max node activations from the parent run (propagated to child policy merge). */
|
|
216
|
+
engineMaxNodeActivations?: number;
|
|
217
|
+
/** Effective max subworkflow depth from the parent run (propagated to child policy merge). */
|
|
218
|
+
engineMaxSubworkflowDepth?: number;
|
|
219
|
+
}
|
|
220
|
+
interface RunDataSnapshot {
|
|
221
|
+
getOutputs(nodeId: NodeId): NodeOutputs | undefined;
|
|
222
|
+
getOutputItems(nodeId: NodeId, output?: OutputPortKey): Items;
|
|
223
|
+
getOutputItem(nodeId: NodeId, itemIndex: number, output?: OutputPortKey): Item | undefined;
|
|
224
|
+
}
|
|
225
|
+
interface NodeErrorHandlerArgs<TConfig extends NodeConfigBase = NodeConfigBase> {
|
|
226
|
+
readonly kind: "single" | "multi";
|
|
227
|
+
readonly items: Items;
|
|
228
|
+
readonly inputsByPort: Readonly<Record<InputPortKey, Items>> | undefined;
|
|
229
|
+
readonly ctx: NodeExecutionContext<TConfig>;
|
|
230
|
+
readonly error: Error;
|
|
231
|
+
}
|
|
232
|
+
interface NodeErrorHandler {
|
|
233
|
+
handle<TConfig extends NodeConfigBase>(args: NodeErrorHandlerArgs<TConfig>): Promise<NodeOutputs>;
|
|
234
|
+
}
|
|
235
|
+
type NodeErrorHandlerSpec = TypeToken<NodeErrorHandler> | NodeErrorHandler;
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region ../core/src/contracts/credentialTypes.d.ts
|
|
238
|
+
type CredentialTypeId = string;
|
|
239
|
+
type CredentialRequirement = Readonly<{
|
|
240
|
+
slotKey: string;
|
|
241
|
+
label: string;
|
|
242
|
+
acceptedTypes: ReadonlyArray<CredentialTypeId>;
|
|
243
|
+
optional?: true;
|
|
244
|
+
helpText?: string;
|
|
245
|
+
helpUrl?: string;
|
|
246
|
+
}>;
|
|
247
|
+
//#endregion
|
|
248
|
+
//#region src/ExampleUppercaseNode.d.ts
|
|
249
|
+
declare class ExampleUppercaseNode implements Node<ExampleUppercase<Record<string, unknown>, string>> {
|
|
250
|
+
kind: "node";
|
|
251
|
+
outputPorts: readonly ["main"];
|
|
252
|
+
execute(items: Items, ctx: NodeExecutionContext<ExampleUppercase<Record<string, unknown>, string>>): Promise<NodeOutputs>;
|
|
253
|
+
}
|
|
254
|
+
//#endregion
|
|
255
|
+
//#region src/uppercase.d.ts
|
|
256
|
+
declare class ExampleUppercase<TInputJson$1 extends Record<string, unknown> = Record<string, unknown>, TField extends keyof TInputJson$1 & string = keyof TInputJson$1 & string> implements RunnableNodeConfig<TInputJson$1, TInputJson$1> {
|
|
257
|
+
readonly name: string;
|
|
258
|
+
readonly cfg: {
|
|
259
|
+
field: TField;
|
|
260
|
+
};
|
|
261
|
+
readonly id?: string | undefined;
|
|
262
|
+
readonly kind: "node";
|
|
263
|
+
readonly type: TypeToken<unknown>;
|
|
264
|
+
constructor(name: string, cfg: {
|
|
265
|
+
field: TField;
|
|
266
|
+
}, id?: string | undefined);
|
|
267
|
+
}
|
|
268
|
+
//#endregion
|
|
269
|
+
export { ExampleUppercase, ExampleUppercaseNode };
|
|
270
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { node } from "@codemation/core";
|
|
2
|
+
|
|
3
|
+
//#region \0@oxc-project+runtime@0.95.0/helpers/decorate.js
|
|
4
|
+
function __decorate(decorators, target, key, desc) {
|
|
5
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
6
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
7
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
8
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/ExampleUppercaseNode.ts
|
|
13
|
+
let ExampleUppercaseNode = class ExampleUppercaseNode$1 {
|
|
14
|
+
kind = "node";
|
|
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 };
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
ExampleUppercaseNode = __decorate([node({ packageName: "@codemation/node-example" })], ExampleUppercaseNode);
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/uppercase.ts
|
|
37
|
+
var ExampleUppercase = class {
|
|
38
|
+
kind = "node";
|
|
39
|
+
type = ExampleUppercaseNode;
|
|
40
|
+
constructor(name, cfg, id) {
|
|
41
|
+
this.name = name;
|
|
42
|
+
this.cfg = cfg;
|
|
43
|
+
this.id = id;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
export { ExampleUppercase, ExampleUppercaseNode };
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codemation/node-example",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"author": "Made Relevant B.V.",
|
|
8
|
+
"homepage": "https://www.maderelevant.com",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "./dist/index.cjs",
|
|
11
|
+
"module": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"development": {
|
|
17
|
+
"import": "./src/index.ts",
|
|
18
|
+
"require": "./dist/index.cjs"
|
|
19
|
+
},
|
|
20
|
+
"import": "./dist/index.js",
|
|
21
|
+
"require": "./dist/index.cjs"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@codemation/core": "0.0.1"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^25.3.5",
|
|
29
|
+
"eslint": "^10.0.3",
|
|
30
|
+
"tsdown": "^0.15.5",
|
|
31
|
+
"typescript": "^5.9.3"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"dev": "tsdown --watch",
|
|
35
|
+
"build": "tsdown",
|
|
36
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
37
|
+
"lint": "eslint .",
|
|
38
|
+
"test": "echo \"(test placeholder)\""
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Item, Items, Node, NodeExecutionContext, NodeOutputs } from "@codemation/core";
|
|
2
|
+
|
|
3
|
+
import { node } from "@codemation/core";
|
|
4
|
+
|
|
5
|
+
import { ExampleUppercase } from "./uppercase";
|
|
6
|
+
|
|
7
|
+
@node({ packageName: "@codemation/node-example" })
|
|
8
|
+
export class ExampleUppercaseNode implements Node<ExampleUppercase<Record<string, unknown>, string>> {
|
|
9
|
+
kind = "node" as const;
|
|
10
|
+
outputPorts = ["main"] as const;
|
|
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 };
|
|
24
|
+
}
|
|
25
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./uppercase";
|
package/src/uppercase.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RunnableNodeConfig, TypeToken } from "@codemation/core";
|
|
2
|
+
|
|
3
|
+
import { ExampleUppercaseNode } from "./ExampleUppercaseNode";
|
|
4
|
+
|
|
5
|
+
export class ExampleUppercase<
|
|
6
|
+
TInputJson extends Record<string, unknown> = Record<string, unknown>,
|
|
7
|
+
TField extends keyof TInputJson & string = keyof TInputJson & string,
|
|
8
|
+
> implements RunnableNodeConfig<TInputJson, TInputJson> {
|
|
9
|
+
readonly kind = "node" as const;
|
|
10
|
+
readonly type: TypeToken<unknown> = ExampleUppercaseNode;
|
|
11
|
+
constructor(
|
|
12
|
+
public readonly name: string,
|
|
13
|
+
public readonly cfg: { field: TField },
|
|
14
|
+
public readonly id?: string,
|
|
15
|
+
) {}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { ExampleUppercaseNode } from "./ExampleUppercaseNode";
|
package/tsconfig.json
ADDED