n8n-nodes-workflow-ops 0.1.0

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 ADDED
@@ -0,0 +1,37 @@
1
+ # n8n-nodes-workflow-ops
2
+
3
+ Workflow Ops proof node for n8n.
4
+
5
+ This package is a small community-node proof asset for Workflow Ops Desk. It demonstrates that we can structure, test, package, and publish an n8n community node without claiming paid client history.
6
+
7
+ ## What It Does
8
+
9
+ The `Workflow Ops` node has three operations:
10
+
11
+ - `Normalize Lead`: turns common lead fields into a consistent object.
12
+ - `Score Lead`: produces a simple automation-lead score from payment, scope, and urgency signals.
13
+ - `Build Reply Draft`: drafts a short, truthful first response for a small workflow-support lead.
14
+
15
+ ## Why This Exists
16
+
17
+ Some buyers ask for proof that a contractor has shipped or packaged n8n community-node work. This repository is a transparent proof package, not a client case study. It is useful as a starting point for small n8n node work, workflow triage, and proposal demonstrations.
18
+
19
+ ## Local Checks
20
+
21
+ ```bash
22
+ npm install
23
+ npm test
24
+ npm run build
25
+ npm pack --dry-run
26
+ ```
27
+
28
+ ## Publishing Notes
29
+
30
+ n8n community nodes are npm packages. The package follows the visible community-node requirements:
31
+
32
+ - package name starts with `n8n-nodes-`,
33
+ - package keywords include `n8n-community-node-package`,
34
+ - package `n8n.nodes` points to the compiled node,
35
+ - a GitHub Actions publish workflow is included for provenance-ready publishing.
36
+
37
+ Publishing to npm requires an npm account and package publishing permissions. No paid plan is required.
@@ -0,0 +1,5 @@
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from "n8n-workflow";
2
+ export declare class WorkflowOps implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkflowOps = void 0;
4
+ class WorkflowOps {
5
+ description = {
6
+ displayName: "Workflow Ops",
7
+ name: "workflowOps",
8
+ icon: "file:workflowOps.svg",
9
+ group: ["transform"],
10
+ version: 1,
11
+ description: "Normalize automation leads, score intent, and draft concise replies.",
12
+ defaults: {
13
+ name: "Workflow Ops",
14
+ },
15
+ inputs: ["main"],
16
+ outputs: ["main"],
17
+ properties: [
18
+ {
19
+ displayName: "Operation",
20
+ name: "operation",
21
+ type: "options",
22
+ noDataExpression: true,
23
+ options: [
24
+ {
25
+ name: "Normalize Lead",
26
+ value: "normalizeLead",
27
+ description: "Create a normalized lead object from common fields",
28
+ action: "Normalize a lead",
29
+ },
30
+ {
31
+ name: "Score Lead",
32
+ value: "scoreLead",
33
+ description: "Score a lead from payment, scope, and urgency signals",
34
+ action: "Score a lead",
35
+ },
36
+ {
37
+ name: "Build Reply Draft",
38
+ value: "buildReplyDraft",
39
+ description: "Create a short, truthful proposal reply draft",
40
+ action: "Build a reply draft",
41
+ },
42
+ ],
43
+ default: "normalizeLead",
44
+ },
45
+ {
46
+ displayName: "Title",
47
+ name: "title",
48
+ type: "string",
49
+ default: "",
50
+ displayOptions: {
51
+ show: {
52
+ operation: ["normalizeLead"],
53
+ },
54
+ },
55
+ },
56
+ {
57
+ displayName: "Source",
58
+ name: "source",
59
+ type: "string",
60
+ default: "",
61
+ displayOptions: {
62
+ show: {
63
+ operation: ["normalizeLead"],
64
+ },
65
+ },
66
+ },
67
+ {
68
+ displayName: "URL",
69
+ name: "url",
70
+ type: "string",
71
+ default: "",
72
+ displayOptions: {
73
+ show: {
74
+ operation: ["normalizeLead"],
75
+ },
76
+ },
77
+ },
78
+ {
79
+ displayName: "Notes",
80
+ name: "notes",
81
+ type: "string",
82
+ typeOptions: {
83
+ rows: 4,
84
+ },
85
+ default: "",
86
+ displayOptions: {
87
+ show: {
88
+ operation: ["normalizeLead"],
89
+ },
90
+ },
91
+ },
92
+ {
93
+ displayName: "Payment Fit",
94
+ name: "paymentFit",
95
+ type: "number",
96
+ default: 0,
97
+ typeOptions: {
98
+ minValue: 0,
99
+ maxValue: 10,
100
+ },
101
+ displayOptions: {
102
+ show: {
103
+ operation: ["scoreLead"],
104
+ },
105
+ },
106
+ },
107
+ {
108
+ displayName: "Scope Fit",
109
+ name: "scopeFit",
110
+ type: "number",
111
+ default: 0,
112
+ typeOptions: {
113
+ minValue: 0,
114
+ maxValue: 10,
115
+ },
116
+ displayOptions: {
117
+ show: {
118
+ operation: ["scoreLead"],
119
+ },
120
+ },
121
+ },
122
+ {
123
+ displayName: "Urgency Fit",
124
+ name: "urgencyFit",
125
+ type: "number",
126
+ default: 0,
127
+ typeOptions: {
128
+ minValue: 0,
129
+ maxValue: 10,
130
+ },
131
+ displayOptions: {
132
+ show: {
133
+ operation: ["scoreLead"],
134
+ },
135
+ },
136
+ },
137
+ {
138
+ displayName: "Lead",
139
+ name: "lead",
140
+ type: "string",
141
+ default: "",
142
+ displayOptions: {
143
+ show: {
144
+ operation: ["buildReplyDraft"],
145
+ },
146
+ },
147
+ },
148
+ {
149
+ displayName: "Problem",
150
+ name: "problem",
151
+ type: "string",
152
+ typeOptions: {
153
+ rows: 4,
154
+ },
155
+ default: "",
156
+ displayOptions: {
157
+ show: {
158
+ operation: ["buildReplyDraft"],
159
+ },
160
+ },
161
+ },
162
+ {
163
+ displayName: "Proof Link",
164
+ name: "proofLink",
165
+ type: "string",
166
+ default: "https://github.com/ErenYeagerr/workflow-ops-desk",
167
+ displayOptions: {
168
+ show: {
169
+ operation: ["buildReplyDraft"],
170
+ },
171
+ },
172
+ },
173
+ ],
174
+ };
175
+ async execute() {
176
+ const items = this.getInputData();
177
+ const returnData = [];
178
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {
179
+ const operation = this.getNodeParameter("operation", itemIndex);
180
+ if (operation === "normalizeLead") {
181
+ returnData.push({
182
+ json: {
183
+ title: this.getNodeParameter("title", itemIndex),
184
+ source: this.getNodeParameter("source", itemIndex),
185
+ url: this.getNodeParameter("url", itemIndex),
186
+ notes: this.getNodeParameter("notes", itemIndex),
187
+ status: "new",
188
+ },
189
+ pairedItem: { item: itemIndex },
190
+ });
191
+ continue;
192
+ }
193
+ if (operation === "scoreLead") {
194
+ const paymentFit = Number(this.getNodeParameter("paymentFit", itemIndex));
195
+ const scopeFit = Number(this.getNodeParameter("scopeFit", itemIndex));
196
+ const urgencyFit = Number(this.getNodeParameter("urgencyFit", itemIndex));
197
+ const score = Math.min(100, Math.round(paymentFit * 4 + scopeFit * 4 + urgencyFit * 2));
198
+ returnData.push({
199
+ json: {
200
+ score,
201
+ recommendation: score >= 82 ? "ready" : score >= 68 ? "diagnostic_reply" : "watch",
202
+ },
203
+ pairedItem: { item: itemIndex },
204
+ });
205
+ continue;
206
+ }
207
+ const lead = this.getNodeParameter("lead", itemIndex);
208
+ const problem = this.getNodeParameter("problem", itemIndex);
209
+ const proofLink = this.getNodeParameter("proofLink", itemIndex);
210
+ returnData.push({
211
+ json: {
212
+ reply: `Hi - I can help with ${lead}. I would start by checking ${problem}, then send a small fixed-scope plan before touching production. Proof/workbench: ${proofLink}`,
213
+ },
214
+ pairedItem: { item: itemIndex },
215
+ });
216
+ }
217
+ return [returnData];
218
+ }
219
+ }
220
+ exports.WorkflowOps = WorkflowOps;
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Workflow Ops">
2
+ <rect width="64" height="64" rx="10" fill="#1f6feb"/>
3
+ <path fill="#ffffff" d="M18 20h18v8H18zm0 16h28v8H18zm27-18 7 6-7 6v-4h-6v-4h6zm-8 16 7 6-7 6v-4h-6v-4h6z"/>
4
+ </svg>
@@ -0,0 +1,231 @@
1
+ import type {
2
+ IExecuteFunctions,
3
+ INodeExecutionData,
4
+ INodeType,
5
+ INodeTypeDescription,
6
+ } from "n8n-workflow"
7
+
8
+ export class WorkflowOps implements INodeType {
9
+ description: INodeTypeDescription = {
10
+ displayName: "Workflow Ops",
11
+ name: "workflowOps",
12
+ icon: "file:workflowOps.svg",
13
+ group: ["transform"],
14
+ version: 1,
15
+ description: "Normalize automation leads, score intent, and draft concise replies.",
16
+ defaults: {
17
+ name: "Workflow Ops",
18
+ },
19
+ inputs: ["main"],
20
+ outputs: ["main"],
21
+ properties: [
22
+ {
23
+ displayName: "Operation",
24
+ name: "operation",
25
+ type: "options",
26
+ noDataExpression: true,
27
+ options: [
28
+ {
29
+ name: "Normalize Lead",
30
+ value: "normalizeLead",
31
+ description: "Create a normalized lead object from common fields",
32
+ action: "Normalize a lead",
33
+ },
34
+ {
35
+ name: "Score Lead",
36
+ value: "scoreLead",
37
+ description: "Score a lead from payment, scope, and urgency signals",
38
+ action: "Score a lead",
39
+ },
40
+ {
41
+ name: "Build Reply Draft",
42
+ value: "buildReplyDraft",
43
+ description: "Create a short, truthful proposal reply draft",
44
+ action: "Build a reply draft",
45
+ },
46
+ ],
47
+ default: "normalizeLead",
48
+ },
49
+ {
50
+ displayName: "Title",
51
+ name: "title",
52
+ type: "string",
53
+ default: "",
54
+ displayOptions: {
55
+ show: {
56
+ operation: ["normalizeLead"],
57
+ },
58
+ },
59
+ },
60
+ {
61
+ displayName: "Source",
62
+ name: "source",
63
+ type: "string",
64
+ default: "",
65
+ displayOptions: {
66
+ show: {
67
+ operation: ["normalizeLead"],
68
+ },
69
+ },
70
+ },
71
+ {
72
+ displayName: "URL",
73
+ name: "url",
74
+ type: "string",
75
+ default: "",
76
+ displayOptions: {
77
+ show: {
78
+ operation: ["normalizeLead"],
79
+ },
80
+ },
81
+ },
82
+ {
83
+ displayName: "Notes",
84
+ name: "notes",
85
+ type: "string",
86
+ typeOptions: {
87
+ rows: 4,
88
+ },
89
+ default: "",
90
+ displayOptions: {
91
+ show: {
92
+ operation: ["normalizeLead"],
93
+ },
94
+ },
95
+ },
96
+ {
97
+ displayName: "Payment Fit",
98
+ name: "paymentFit",
99
+ type: "number",
100
+ default: 0,
101
+ typeOptions: {
102
+ minValue: 0,
103
+ maxValue: 10,
104
+ },
105
+ displayOptions: {
106
+ show: {
107
+ operation: ["scoreLead"],
108
+ },
109
+ },
110
+ },
111
+ {
112
+ displayName: "Scope Fit",
113
+ name: "scopeFit",
114
+ type: "number",
115
+ default: 0,
116
+ typeOptions: {
117
+ minValue: 0,
118
+ maxValue: 10,
119
+ },
120
+ displayOptions: {
121
+ show: {
122
+ operation: ["scoreLead"],
123
+ },
124
+ },
125
+ },
126
+ {
127
+ displayName: "Urgency Fit",
128
+ name: "urgencyFit",
129
+ type: "number",
130
+ default: 0,
131
+ typeOptions: {
132
+ minValue: 0,
133
+ maxValue: 10,
134
+ },
135
+ displayOptions: {
136
+ show: {
137
+ operation: ["scoreLead"],
138
+ },
139
+ },
140
+ },
141
+ {
142
+ displayName: "Lead",
143
+ name: "lead",
144
+ type: "string",
145
+ default: "",
146
+ displayOptions: {
147
+ show: {
148
+ operation: ["buildReplyDraft"],
149
+ },
150
+ },
151
+ },
152
+ {
153
+ displayName: "Problem",
154
+ name: "problem",
155
+ type: "string",
156
+ typeOptions: {
157
+ rows: 4,
158
+ },
159
+ default: "",
160
+ displayOptions: {
161
+ show: {
162
+ operation: ["buildReplyDraft"],
163
+ },
164
+ },
165
+ },
166
+ {
167
+ displayName: "Proof Link",
168
+ name: "proofLink",
169
+ type: "string",
170
+ default: "https://github.com/ErenYeagerr/workflow-ops-desk",
171
+ displayOptions: {
172
+ show: {
173
+ operation: ["buildReplyDraft"],
174
+ },
175
+ },
176
+ },
177
+ ],
178
+ }
179
+
180
+ async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
181
+ const items = this.getInputData()
182
+ const returnData: INodeExecutionData[] = []
183
+
184
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {
185
+ const operation = this.getNodeParameter("operation", itemIndex) as string
186
+
187
+ if (operation === "normalizeLead") {
188
+ returnData.push({
189
+ json: {
190
+ title: this.getNodeParameter("title", itemIndex) as string,
191
+ source: this.getNodeParameter("source", itemIndex) as string,
192
+ url: this.getNodeParameter("url", itemIndex) as string,
193
+ notes: this.getNodeParameter("notes", itemIndex) as string,
194
+ status: "new",
195
+ },
196
+ pairedItem: { item: itemIndex },
197
+ })
198
+ continue
199
+ }
200
+
201
+ if (operation === "scoreLead") {
202
+ const paymentFit = Number(this.getNodeParameter("paymentFit", itemIndex))
203
+ const scopeFit = Number(this.getNodeParameter("scopeFit", itemIndex))
204
+ const urgencyFit = Number(this.getNodeParameter("urgencyFit", itemIndex))
205
+ const score = Math.min(100, Math.round(paymentFit * 4 + scopeFit * 4 + urgencyFit * 2))
206
+
207
+ returnData.push({
208
+ json: {
209
+ score,
210
+ recommendation: score >= 82 ? "ready" : score >= 68 ? "diagnostic_reply" : "watch",
211
+ },
212
+ pairedItem: { item: itemIndex },
213
+ })
214
+ continue
215
+ }
216
+
217
+ const lead = this.getNodeParameter("lead", itemIndex) as string
218
+ const problem = this.getNodeParameter("problem", itemIndex) as string
219
+ const proofLink = this.getNodeParameter("proofLink", itemIndex) as string
220
+
221
+ returnData.push({
222
+ json: {
223
+ reply: `Hi - I can help with ${lead}. I would start by checking ${problem}, then send a small fixed-scope plan before touching production. Proof/workbench: ${proofLink}`,
224
+ },
225
+ pairedItem: { item: itemIndex },
226
+ })
227
+ }
228
+
229
+ return [returnData]
230
+ }
231
+ }
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Workflow Ops">
2
+ <rect width="64" height="64" rx="10" fill="#1f6feb"/>
3
+ <path fill="#ffffff" d="M18 20h18v8H18zm0 16h28v8H18zm27-18 7 6-7 6v-4h-6v-4h6zm-8 16 7 6-7 6v-4h-6v-4h6z"/>
4
+ </svg>
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "n8n-nodes-workflow-ops",
3
+ "version": "0.1.0",
4
+ "description": "Workflow Ops proof node for normalizing automation leads and drafting replies in n8n.",
5
+ "license": "MIT",
6
+ "author": "Christian",
7
+ "homepage": "https://github.com/ErenYeagerr/workflow-ops-desk",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/ErenYeagerr/workflow-ops-desk.git",
11
+ "directory": "proof/n8n-nodes-workflow-ops"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/ErenYeagerr/workflow-ops-desk/issues"
15
+ },
16
+ "main": "dist/nodes/WorkflowOps/WorkflowOps.node.js",
17
+ "types": "dist/nodes/WorkflowOps/WorkflowOps.node.d.ts",
18
+ "files": [
19
+ "dist",
20
+ "nodes",
21
+ "README.md"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc -p tsconfig.json && node scripts/copy-assets.mjs",
25
+ "lint": "node --check scripts/copy-assets.mjs",
26
+ "test": "node --test test/*.test.mjs",
27
+ "pack:check": "npm pack --dry-run"
28
+ },
29
+ "keywords": [
30
+ "n8n-community-node-package",
31
+ "n8n",
32
+ "automation",
33
+ "workflow-ops"
34
+ ],
35
+ "n8n": {
36
+ "nodes": [
37
+ "dist/nodes/WorkflowOps/WorkflowOps.node.js"
38
+ ]
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^22.15.30",
42
+ "n8n-workflow": "^1.96.0",
43
+ "typescript": "^5.8.3"
44
+ }
45
+ }