@octo-cyber/workflow 0.5.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/dist/controllers/ai-workflow-session.controller.d.ts +19 -0
- package/dist/controllers/ai-workflow-session.controller.d.ts.map +1 -0
- package/dist/controllers/ai-workflow-session.controller.js +135 -0
- package/dist/controllers/ai-workflow-session.controller.js.map +1 -0
- package/dist/controllers/credential.controller.d.ts +68 -0
- package/dist/controllers/credential.controller.d.ts.map +1 -0
- package/dist/controllers/credential.controller.js +303 -0
- package/dist/controllers/credential.controller.js.map +1 -0
- package/dist/controllers/index.d.ts +3 -0
- package/dist/controllers/index.d.ts.map +1 -0
- package/dist/controllers/index.js +8 -0
- package/dist/controllers/index.js.map +1 -0
- package/dist/controllers/workflow-ai.controller.d.ts +23 -0
- package/dist/controllers/workflow-ai.controller.d.ts.map +1 -0
- package/dist/controllers/workflow-ai.controller.js +164 -0
- package/dist/controllers/workflow-ai.controller.js.map +1 -0
- package/dist/controllers/workflow.controller.d.ts +66 -0
- package/dist/controllers/workflow.controller.d.ts.map +1 -0
- package/dist/controllers/workflow.controller.js +239 -0
- package/dist/controllers/workflow.controller.js.map +1 -0
- package/dist/core/expression-resolver.d.ts +49 -0
- package/dist/core/expression-resolver.d.ts.map +1 -0
- package/dist/core/expression-resolver.js +113 -0
- package/dist/core/expression-resolver.js.map +1 -0
- package/dist/core/node-registry.d.ts +24 -0
- package/dist/core/node-registry.d.ts.map +1 -0
- package/dist/core/node-registry.js +62 -0
- package/dist/core/node-registry.js.map +1 -0
- package/dist/core/workflow-executor.d.ts +50 -0
- package/dist/core/workflow-executor.d.ts.map +1 -0
- package/dist/core/workflow-executor.js +458 -0
- package/dist/core/workflow-executor.js.map +1 -0
- package/dist/entities/ai-workflow-session.entity.d.ts +17 -0
- package/dist/entities/ai-workflow-session.entity.d.ts.map +1 -0
- package/dist/entities/ai-workflow-session.entity.js +70 -0
- package/dist/entities/ai-workflow-session.entity.js.map +1 -0
- package/dist/entities/ai-workflow-version.entity.d.ts +18 -0
- package/dist/entities/ai-workflow-version.entity.d.ts.map +1 -0
- package/dist/entities/ai-workflow-version.entity.js +71 -0
- package/dist/entities/ai-workflow-version.entity.js.map +1 -0
- package/dist/entities/credential-definition.entity.d.ts +17 -0
- package/dist/entities/credential-definition.entity.d.ts.map +1 -0
- package/dist/entities/credential-definition.entity.js +66 -0
- package/dist/entities/credential-definition.entity.js.map +1 -0
- package/dist/entities/index.d.ts +9 -0
- package/dist/entities/index.d.ts.map +1 -0
- package/dist/entities/index.js +22 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/entities/workflow-definition.entity.d.ts +20 -0
- package/dist/entities/workflow-definition.entity.d.ts.map +1 -0
- package/dist/entities/workflow-definition.entity.js +85 -0
- package/dist/entities/workflow-definition.entity.js.map +1 -0
- package/dist/entities/workflow-execution.entity.d.ts +26 -0
- package/dist/entities/workflow-execution.entity.d.ts.map +1 -0
- package/dist/entities/workflow-execution.entity.js +99 -0
- package/dist/entities/workflow-execution.entity.js.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +96 -0
- package/dist/index.js.map +1 -0
- package/dist/n8n/cipher/cipher.d.ts +11 -0
- package/dist/n8n/cipher/cipher.d.ts.map +1 -0
- package/dist/n8n/cipher/cipher.js +54 -0
- package/dist/n8n/cipher/cipher.js.map +1 -0
- package/dist/n8n/controllers/n8n-session.controller.d.ts +20 -0
- package/dist/n8n/controllers/n8n-session.controller.d.ts.map +1 -0
- package/dist/n8n/controllers/n8n-session.controller.js +84 -0
- package/dist/n8n/controllers/n8n-session.controller.js.map +1 -0
- package/dist/n8n/index.d.ts +8 -0
- package/dist/n8n/index.d.ts.map +1 -0
- package/dist/n8n/index.js +14 -0
- package/dist/n8n/index.js.map +1 -0
- package/dist/n8n/launcher/n8n-launcher.d.ts +41 -0
- package/dist/n8n/launcher/n8n-launcher.d.ts.map +1 -0
- package/dist/n8n/launcher/n8n-launcher.js +186 -0
- package/dist/n8n/launcher/n8n-launcher.js.map +1 -0
- package/dist/n8n/nodes/OctoClaudeCliTool.node.d.ts +13 -0
- package/dist/n8n/nodes/OctoClaudeCliTool.node.d.ts.map +1 -0
- package/dist/n8n/nodes/OctoClaudeCliTool.node.js +103 -0
- package/dist/n8n/nodes/OctoClaudeCliTool.node.js.map +1 -0
- package/dist/n8n/nodes/OctoCliChatModel.node.d.ts +14 -0
- package/dist/n8n/nodes/OctoCliChatModel.node.d.ts.map +1 -0
- package/dist/n8n/nodes/OctoCliChatModel.node.js +431 -0
- package/dist/n8n/nodes/OctoCliChatModel.node.js.map +1 -0
- package/dist/n8n/nodes/OctoCodexCliTool.node.d.ts +13 -0
- package/dist/n8n/nodes/OctoCodexCliTool.node.d.ts.map +1 -0
- package/dist/n8n/nodes/OctoCodexCliTool.node.js +100 -0
- package/dist/n8n/nodes/OctoCodexCliTool.node.js.map +1 -0
- package/dist/n8n/nodes/OctoGeminiCliTool.node.d.ts +13 -0
- package/dist/n8n/nodes/OctoGeminiCliTool.node.d.ts.map +1 -0
- package/dist/n8n/nodes/OctoGeminiCliTool.node.js +91 -0
- package/dist/n8n/nodes/OctoGeminiCliTool.node.js.map +1 -0
- package/dist/n8n/nodes/OctoKnowledge.node.d.ts +6 -0
- package/dist/n8n/nodes/OctoKnowledge.node.d.ts.map +1 -0
- package/dist/n8n/nodes/OctoKnowledge.node.js +95 -0
- package/dist/n8n/nodes/OctoKnowledge.node.js.map +1 -0
- package/dist/n8n/nodes/OctoNotification.node.d.ts +6 -0
- package/dist/n8n/nodes/OctoNotification.node.d.ts.map +1 -0
- package/dist/n8n/nodes/OctoNotification.node.js +72 -0
- package/dist/n8n/nodes/OctoNotification.node.js.map +1 -0
- package/dist/n8n/nodes/OctoSyncBridge.node.d.ts +6 -0
- package/dist/n8n/nodes/OctoSyncBridge.node.d.ts.map +1 -0
- package/dist/n8n/nodes/OctoSyncBridge.node.js +60 -0
- package/dist/n8n/nodes/OctoSyncBridge.node.js.map +1 -0
- package/dist/n8n/nodes/n8n-node-types.d.ts +111 -0
- package/dist/n8n/nodes/n8n-node-types.d.ts.map +1 -0
- package/dist/n8n/nodes/n8n-node-types.js +30 -0
- package/dist/n8n/nodes/n8n-node-types.js.map +1 -0
- package/dist/n8n/nodes/octo-cli-chat-model.svg +23 -0
- package/dist/n8n/nodes/package.json +16 -0
- package/dist/n8n/proxy/css-injector.d.ts +3 -0
- package/dist/n8n/proxy/css-injector.d.ts.map +1 -0
- package/dist/n8n/proxy/css-injector.js +62 -0
- package/dist/n8n/proxy/css-injector.js.map +1 -0
- package/dist/n8n/proxy/n8n-proxy.middleware.d.ts +12 -0
- package/dist/n8n/proxy/n8n-proxy.middleware.d.ts.map +1 -0
- package/dist/n8n/proxy/n8n-proxy.middleware.js +131 -0
- package/dist/n8n/proxy/n8n-proxy.middleware.js.map +1 -0
- package/dist/n8n/proxy/n8n-theme.css +45 -0
- package/dist/n8n/sync/n8n-user-sync.service.d.ts +75 -0
- package/dist/n8n/sync/n8n-user-sync.service.d.ts.map +1 -0
- package/dist/n8n/sync/n8n-user-sync.service.js +286 -0
- package/dist/n8n/sync/n8n-user-sync.service.js.map +1 -0
- package/dist/n8n/watcher/n8n-execution-watcher.d.ts +39 -0
- package/dist/n8n/watcher/n8n-execution-watcher.d.ts.map +1 -0
- package/dist/n8n/watcher/n8n-execution-watcher.js +110 -0
- package/dist/n8n/watcher/n8n-execution-watcher.js.map +1 -0
- package/dist/nodes/code.node.d.ts +24 -0
- package/dist/nodes/code.node.d.ts.map +1 -0
- package/dist/nodes/code.node.js +150 -0
- package/dist/nodes/code.node.js.map +1 -0
- package/dist/nodes/error-trigger.node.d.ts +15 -0
- package/dist/nodes/error-trigger.node.d.ts.map +1 -0
- package/dist/nodes/error-trigger.node.js +53 -0
- package/dist/nodes/error-trigger.node.js.map +1 -0
- package/dist/nodes/execute-command.node.d.ts +9 -0
- package/dist/nodes/execute-command.node.d.ts.map +1 -0
- package/dist/nodes/execute-command.node.js +81 -0
- package/dist/nodes/execute-command.node.js.map +1 -0
- package/dist/nodes/filter.node.d.ts +10 -0
- package/dist/nodes/filter.node.d.ts.map +1 -0
- package/dist/nodes/filter.node.js +95 -0
- package/dist/nodes/filter.node.js.map +1 -0
- package/dist/nodes/http-request.node.d.ts +11 -0
- package/dist/nodes/http-request.node.d.ts.map +1 -0
- package/dist/nodes/http-request.node.js +139 -0
- package/dist/nodes/http-request.node.js.map +1 -0
- package/dist/nodes/if.node.d.ts +13 -0
- package/dist/nodes/if.node.d.ts.map +1 -0
- package/dist/nodes/if.node.js +137 -0
- package/dist/nodes/if.node.js.map +1 -0
- package/dist/nodes/index.d.ts +12 -0
- package/dist/nodes/index.d.ts.map +1 -0
- package/dist/nodes/index.js +26 -0
- package/dist/nodes/index.js.map +1 -0
- package/dist/nodes/manual-trigger.node.d.ts +10 -0
- package/dist/nodes/manual-trigger.node.d.ts.map +1 -0
- package/dist/nodes/manual-trigger.node.js +36 -0
- package/dist/nodes/manual-trigger.node.js.map +1 -0
- package/dist/nodes/merge.node.d.ts +15 -0
- package/dist/nodes/merge.node.d.ts.map +1 -0
- package/dist/nodes/merge.node.js +99 -0
- package/dist/nodes/merge.node.js.map +1 -0
- package/dist/nodes/noop.node.d.ts +12 -0
- package/dist/nodes/noop.node.d.ts.map +1 -0
- package/dist/nodes/noop.node.js +32 -0
- package/dist/nodes/noop.node.js.map +1 -0
- package/dist/nodes/placeholder.node.d.ts +10 -0
- package/dist/nodes/placeholder.node.d.ts.map +1 -0
- package/dist/nodes/placeholder.node.js +50 -0
- package/dist/nodes/placeholder.node.js.map +1 -0
- package/dist/nodes/remove-duplicates.node.d.ts +9 -0
- package/dist/nodes/remove-duplicates.node.d.ts.map +1 -0
- package/dist/nodes/remove-duplicates.node.js +68 -0
- package/dist/nodes/remove-duplicates.node.js.map +1 -0
- package/dist/nodes/respond-to-webhook.node.d.ts +14 -0
- package/dist/nodes/respond-to-webhook.node.d.ts.map +1 -0
- package/dist/nodes/respond-to-webhook.node.js +116 -0
- package/dist/nodes/respond-to-webhook.node.js.map +1 -0
- package/dist/nodes/schedule-trigger.node.d.ts +9 -0
- package/dist/nodes/schedule-trigger.node.d.ts.map +1 -0
- package/dist/nodes/schedule-trigger.node.js +67 -0
- package/dist/nodes/schedule-trigger.node.js.map +1 -0
- package/dist/nodes/set.node.d.ts +12 -0
- package/dist/nodes/set.node.d.ts.map +1 -0
- package/dist/nodes/set.node.js +81 -0
- package/dist/nodes/set.node.js.map +1 -0
- package/dist/nodes/sort.node.d.ts +9 -0
- package/dist/nodes/sort.node.d.ts.map +1 -0
- package/dist/nodes/sort.node.js +61 -0
- package/dist/nodes/sort.node.js.map +1 -0
- package/dist/nodes/split-in-batches.node.d.ts +9 -0
- package/dist/nodes/split-in-batches.node.d.ts.map +1 -0
- package/dist/nodes/split-in-batches.node.js +53 -0
- package/dist/nodes/split-in-batches.node.js.map +1 -0
- package/dist/nodes/split-out.node.d.ts +9 -0
- package/dist/nodes/split-out.node.d.ts.map +1 -0
- package/dist/nodes/split-out.node.js +76 -0
- package/dist/nodes/split-out.node.js.map +1 -0
- package/dist/nodes/switch.node.d.ts +16 -0
- package/dist/nodes/switch.node.d.ts.map +1 -0
- package/dist/nodes/switch.node.js +156 -0
- package/dist/nodes/switch.node.js.map +1 -0
- package/dist/nodes/wait.node.d.ts +12 -0
- package/dist/nodes/wait.node.d.ts.map +1 -0
- package/dist/nodes/wait.node.js +81 -0
- package/dist/nodes/wait.node.js.map +1 -0
- package/dist/nodes/webhook.node.d.ts +9 -0
- package/dist/nodes/webhook.node.d.ts.map +1 -0
- package/dist/nodes/webhook.node.js +69 -0
- package/dist/nodes/webhook.node.js.map +1 -0
- package/dist/services/ai-workflow-session.service.d.ts +31 -0
- package/dist/services/ai-workflow-session.service.d.ts.map +1 -0
- package/dist/services/ai-workflow-session.service.js +118 -0
- package/dist/services/ai-workflow-session.service.js.map +1 -0
- package/dist/services/credential.service.d.ts +57 -0
- package/dist/services/credential.service.d.ts.map +1 -0
- package/dist/services/credential.service.js +155 -0
- package/dist/services/credential.service.js.map +1 -0
- package/dist/services/index.d.ts +10 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +14 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/push.service.d.ts +60 -0
- package/dist/services/push.service.d.ts.map +1 -0
- package/dist/services/push.service.js +121 -0
- package/dist/services/push.service.js.map +1 -0
- package/dist/services/workflow-ai.service.d.ts +61 -0
- package/dist/services/workflow-ai.service.d.ts.map +1 -0
- package/dist/services/workflow-ai.service.js +219 -0
- package/dist/services/workflow-ai.service.js.map +1 -0
- package/dist/services/workflow-context.service.d.ts +32 -0
- package/dist/services/workflow-context.service.d.ts.map +1 -0
- package/dist/services/workflow-context.service.js +155 -0
- package/dist/services/workflow-context.service.js.map +1 -0
- package/dist/services/workflow-engine.service.d.ts +90 -0
- package/dist/services/workflow-engine.service.d.ts.map +1 -0
- package/dist/services/workflow-engine.service.js +305 -0
- package/dist/services/workflow-engine.service.js.map +1 -0
- package/dist/services/workflow.service.d.ts +84 -0
- package/dist/services/workflow.service.d.ts.map +1 -0
- package/dist/services/workflow.service.js +241 -0
- package/dist/services/workflow.service.js.map +1 -0
- package/dist/triggers/cron-trigger.d.ts +39 -0
- package/dist/triggers/cron-trigger.d.ts.map +1 -0
- package/dist/triggers/cron-trigger.js +137 -0
- package/dist/triggers/cron-trigger.js.map +1 -0
- package/dist/triggers/index.d.ts +3 -0
- package/dist/triggers/index.d.ts.map +1 -0
- package/dist/triggers/index.js +8 -0
- package/dist/triggers/index.js.map +1 -0
- package/dist/triggers/webhook-trigger.d.ts +51 -0
- package/dist/triggers/webhook-trigger.d.ts.map +1 -0
- package/dist/triggers/webhook-trigger.js +122 -0
- package/dist/triggers/webhook-trigger.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/node.types.d.ts +313 -0
- package/dist/types/node.types.d.ts.map +1 -0
- package/dist/types/node.types.js +23 -0
- package/dist/types/node.types.js.map +1 -0
- package/dist/types/workflow.types.d.ts +153 -0
- package/dist/types/workflow.types.d.ts.map +1 -0
- package/dist/types/workflow.types.js +44 -0
- package/dist/types/workflow.types.js.map +1 -0
- package/dist/utils/n8n-converter.d.ts +52 -0
- package/dist/utils/n8n-converter.d.ts.map +1 -0
- package/dist/utils/n8n-converter.js +107 -0
- package/dist/utils/n8n-converter.js.map +1 -0
- package/dist/utils/n8n-node-map.d.ts +6 -0
- package/dist/utils/n8n-node-map.d.ts.map +1 -0
- package/dist/utils/n8n-node-map.js +59 -0
- package/dist/utils/n8n-node-map.js.map +1 -0
- package/dist/workflow.module.d.ts +40 -0
- package/dist/workflow.module.d.ts.map +1 -0
- package/dist/workflow.module.js +240 -0
- package/dist/workflow.module.js.map +1 -0
- package/package.json +97 -0
- package/web/components/ChatPanel.tsx +344 -0
- package/web/components/N8nIframe.tsx +119 -0
- package/web/components/SessionPanel.tsx +301 -0
- package/web/components/ToolPanel.tsx +404 -0
- package/web/components/WorkflowDiff.tsx +161 -0
- package/web/components/WorkflowGraph.tsx +158 -0
- package/web/components/WorkflowPreviewPanel.tsx +186 -0
- package/web/hooks/use-n8n-session.ts +46 -0
- package/web/index.ts +29 -0
- package/web/manifest.ts +16 -0
- package/web/messages/en-US.json +94 -0
- package/web/messages/zh-CN.json +94 -0
- package/web/pages/AiDesignPage.tsx +215 -0
- package/web/pages/CredentialsPage.tsx +7 -0
- package/web/pages/ExecutionsPage.tsx +7 -0
- package/web/pages/WorkflowsPage.tsx +7 -0
- package/web/services/workflow-ai-service.ts +173 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.N8nUserSyncService = void 0;
|
|
10
|
+
const node_crypto_1 = require("node:crypto");
|
|
11
|
+
const core_1 = require("@octo/core");
|
|
12
|
+
const N8N_USER_SYNC_SECRET = process.env.N8N_USER_SYNC_SECRET || 'octo-n8n-sync-default-secret';
|
|
13
|
+
const N8N_OWNER_EMAIL = 'octo-admin@internal.local';
|
|
14
|
+
/**
|
|
15
|
+
* N8nUserSyncService — synchronises Octo users into the embedded n8n
|
|
16
|
+
* instance so that each Octo user has a corresponding n8n account.
|
|
17
|
+
*
|
|
18
|
+
* Uses n8n's internal REST API (`/rest/`) with cookie-based auth
|
|
19
|
+
* (compatible with n8n 2.x which requires API key for `/api/v1/`).
|
|
20
|
+
*/
|
|
21
|
+
let N8nUserSyncService = class N8nUserSyncService {
|
|
22
|
+
n8nApiUrl = 'http://127.0.0.1:5678';
|
|
23
|
+
ownerCookie = null;
|
|
24
|
+
ownerId = null;
|
|
25
|
+
ownerPassword = this.generateOwnerPassword();
|
|
26
|
+
logger = core_1.Container.get(core_1.LoggerService).child('N8nUserSync');
|
|
27
|
+
setApiUrl(url) {
|
|
28
|
+
this.n8nApiUrl = url;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Ensure n8n owner account exists and we have a valid auth cookie.
|
|
32
|
+
* Called once after n8n starts.
|
|
33
|
+
*
|
|
34
|
+
* Retries up to 5 times with 2s delay because n8n's REST routes
|
|
35
|
+
* may not be fully registered when /healthz first returns 200.
|
|
36
|
+
*/
|
|
37
|
+
async ensureOwnerSetup() {
|
|
38
|
+
const maxRetries = 5;
|
|
39
|
+
const retryDelay = 2000;
|
|
40
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
41
|
+
try {
|
|
42
|
+
const needsSetup = await this.checkNeedsSetup();
|
|
43
|
+
if (needsSetup) {
|
|
44
|
+
this.logger.info('Fresh n8n instance detected, setting up owner');
|
|
45
|
+
await this.setupOwner();
|
|
46
|
+
}
|
|
47
|
+
await this.loginAsOwner();
|
|
48
|
+
this.logger.info('n8n owner session established');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
const msg = err.message;
|
|
53
|
+
if (attempt < maxRetries) {
|
|
54
|
+
this.logger.warn(`Owner setup attempt ${attempt}/${maxRetries} failed: ${msg}, retrying...`);
|
|
55
|
+
await new Promise((r) => setTimeout(r, retryDelay));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
this.logger.error(`Owner setup failed after ${maxRetries} attempts: ${msg}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Ensure the Octo user exists in n8n. Creates the user if missing.
|
|
65
|
+
*/
|
|
66
|
+
async syncUser(octoUser) {
|
|
67
|
+
// Ensure we have a valid owner session
|
|
68
|
+
if (!this.ownerCookie) {
|
|
69
|
+
await this.loginAsOwner();
|
|
70
|
+
}
|
|
71
|
+
const existing = await this.findN8nUser(octoUser.email);
|
|
72
|
+
if (existing) {
|
|
73
|
+
this.logger.debug(`n8n user already exists for ${octoUser.email}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
this.logger.info(`Creating n8n user for ${octoUser.email}`);
|
|
77
|
+
const nameParts = octoUser.username.split(/[\s_-]+/);
|
|
78
|
+
const firstName = nameParts[0] || octoUser.username;
|
|
79
|
+
const lastName = nameParts.slice(1).join(' ') || 'User';
|
|
80
|
+
await this.createN8nUser({
|
|
81
|
+
email: octoUser.email,
|
|
82
|
+
firstName,
|
|
83
|
+
lastName,
|
|
84
|
+
password: this.generateInternalPassword(octoUser.id),
|
|
85
|
+
role: 'global:member',
|
|
86
|
+
});
|
|
87
|
+
this.logger.info(`n8n user created for ${octoUser.email}`);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Obtain an n8n auth cookie by logging in with the internal password.
|
|
91
|
+
*/
|
|
92
|
+
async getN8nAuthToken(octoUser) {
|
|
93
|
+
const password = this.generateInternalPassword(octoUser.id);
|
|
94
|
+
const response = await fetch(`${this.n8nApiUrl}/rest/login`, {
|
|
95
|
+
method: 'POST',
|
|
96
|
+
headers: { 'Content-Type': 'application/json' },
|
|
97
|
+
body: JSON.stringify({
|
|
98
|
+
emailOrLdapLoginId: octoUser.email,
|
|
99
|
+
password,
|
|
100
|
+
}),
|
|
101
|
+
});
|
|
102
|
+
if (!response.ok) {
|
|
103
|
+
const text = await response.text();
|
|
104
|
+
throw new Error(`n8n login failed for ${octoUser.email}: ${response.status} ${text}`);
|
|
105
|
+
}
|
|
106
|
+
// n8n 2.x returns the auth token via set-cookie header
|
|
107
|
+
const setCookie = response.headers.get('set-cookie');
|
|
108
|
+
if (setCookie) {
|
|
109
|
+
return setCookie;
|
|
110
|
+
}
|
|
111
|
+
// Fallback: some versions return token in response body
|
|
112
|
+
const body = (await response.json());
|
|
113
|
+
const data = body.data;
|
|
114
|
+
if (data?.token) {
|
|
115
|
+
return data.token;
|
|
116
|
+
}
|
|
117
|
+
throw new Error('n8n login succeeded but no auth cookie or token was returned');
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Check if n8n needs initial owner setup.
|
|
121
|
+
*/
|
|
122
|
+
async checkNeedsSetup() {
|
|
123
|
+
try {
|
|
124
|
+
const response = await fetch(`${this.n8nApiUrl}/rest/settings`);
|
|
125
|
+
if (!response.ok)
|
|
126
|
+
return true;
|
|
127
|
+
const body = (await response.json());
|
|
128
|
+
const data = body.data;
|
|
129
|
+
const userMgmt = data?.userManagement;
|
|
130
|
+
return userMgmt?.showSetupOnFirstLoad === true;
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Create the n8n owner account on a fresh instance.
|
|
138
|
+
*/
|
|
139
|
+
async setupOwner() {
|
|
140
|
+
const response = await fetch(`${this.n8nApiUrl}/rest/owner/setup`, {
|
|
141
|
+
method: 'POST',
|
|
142
|
+
headers: { 'Content-Type': 'application/json' },
|
|
143
|
+
body: JSON.stringify({
|
|
144
|
+
email: N8N_OWNER_EMAIL,
|
|
145
|
+
firstName: 'Octo',
|
|
146
|
+
lastName: 'Admin',
|
|
147
|
+
password: this.ownerPassword,
|
|
148
|
+
}),
|
|
149
|
+
});
|
|
150
|
+
if (!response.ok) {
|
|
151
|
+
const text = await response.text();
|
|
152
|
+
throw new Error(`Owner setup failed: ${response.status} ${text}`);
|
|
153
|
+
}
|
|
154
|
+
const body = (await response.json());
|
|
155
|
+
const data = body.data;
|
|
156
|
+
if (data?.id) {
|
|
157
|
+
this.ownerId = data.id;
|
|
158
|
+
}
|
|
159
|
+
this.logger.info('n8n owner account created');
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Login as the n8n owner and store the auth cookie.
|
|
163
|
+
*/
|
|
164
|
+
async loginAsOwner() {
|
|
165
|
+
const response = await fetch(`${this.n8nApiUrl}/rest/login`, {
|
|
166
|
+
method: 'POST',
|
|
167
|
+
headers: { 'Content-Type': 'application/json' },
|
|
168
|
+
body: JSON.stringify({
|
|
169
|
+
emailOrLdapLoginId: N8N_OWNER_EMAIL,
|
|
170
|
+
password: this.ownerPassword,
|
|
171
|
+
}),
|
|
172
|
+
});
|
|
173
|
+
if (!response.ok) {
|
|
174
|
+
const text = await response.text();
|
|
175
|
+
throw new Error(`Owner login failed: ${response.status} ${text}`);
|
|
176
|
+
}
|
|
177
|
+
const setCookie = response.headers.get('set-cookie');
|
|
178
|
+
if (setCookie) {
|
|
179
|
+
// Extract just the cookie name=value part
|
|
180
|
+
this.ownerCookie = setCookie.split(';')[0];
|
|
181
|
+
}
|
|
182
|
+
// Extract ownerId from response body
|
|
183
|
+
const body = (await response.json());
|
|
184
|
+
const data = body.data;
|
|
185
|
+
if (data?.id) {
|
|
186
|
+
this.ownerId = data.id;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Build headers with the owner auth cookie.
|
|
191
|
+
*/
|
|
192
|
+
ownerHeaders() {
|
|
193
|
+
const headers = {
|
|
194
|
+
'Content-Type': 'application/json',
|
|
195
|
+
};
|
|
196
|
+
if (this.ownerCookie) {
|
|
197
|
+
headers['Cookie'] = this.ownerCookie;
|
|
198
|
+
}
|
|
199
|
+
return headers;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Look up an n8n user by email address.
|
|
203
|
+
*/
|
|
204
|
+
async findN8nUser(email) {
|
|
205
|
+
try {
|
|
206
|
+
const response = await fetch(`${this.n8nApiUrl}/rest/users`, {
|
|
207
|
+
headers: this.ownerHeaders(),
|
|
208
|
+
});
|
|
209
|
+
if (!response.ok) {
|
|
210
|
+
this.logger.warn(`Failed to list n8n users: ${response.status}`);
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
const body = (await response.json());
|
|
214
|
+
const data = body.data;
|
|
215
|
+
// n8n 2.x format: { data: { count, items: [...] } }
|
|
216
|
+
const items = (data?.items ?? data ?? []);
|
|
217
|
+
return items.find((u) => u.email === email) ?? null;
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
this.logger.warn(`Error querying n8n users: ${err.message}`);
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Create a new user in n8n via the invitation flow (n8n 2.x).
|
|
226
|
+
*
|
|
227
|
+
* 1. POST /rest/invitations — owner invites user
|
|
228
|
+
* 2. POST /rest/invitations/{id}/accept — user accepts with password
|
|
229
|
+
*/
|
|
230
|
+
async createN8nUser(data) {
|
|
231
|
+
// Step 1: Create invitation
|
|
232
|
+
const inviteResponse = await fetch(`${this.n8nApiUrl}/rest/invitations`, {
|
|
233
|
+
method: 'POST',
|
|
234
|
+
headers: this.ownerHeaders(),
|
|
235
|
+
body: JSON.stringify([{ email: data.email, role: data.role }]),
|
|
236
|
+
});
|
|
237
|
+
if (!inviteResponse.ok) {
|
|
238
|
+
const text = await inviteResponse.text();
|
|
239
|
+
throw new Error(`Failed to invite n8n user (${data.email}): ${inviteResponse.status} ${text}`);
|
|
240
|
+
}
|
|
241
|
+
const inviteBody = (await inviteResponse.json());
|
|
242
|
+
const invitations = inviteBody.data;
|
|
243
|
+
if (!invitations?.[0]?.user?.id) {
|
|
244
|
+
throw new Error(`Invitation response missing user ID for ${data.email}`);
|
|
245
|
+
}
|
|
246
|
+
const inviteeId = invitations[0].user.id;
|
|
247
|
+
// Step 2: Accept invitation (sets password and activates user)
|
|
248
|
+
const acceptResponse = await fetch(`${this.n8nApiUrl}/rest/invitations/${inviteeId}/accept`, {
|
|
249
|
+
method: 'POST',
|
|
250
|
+
headers: { 'Content-Type': 'application/json' },
|
|
251
|
+
body: JSON.stringify({
|
|
252
|
+
inviterId: this.ownerId,
|
|
253
|
+
firstName: data.firstName,
|
|
254
|
+
lastName: data.lastName,
|
|
255
|
+
password: data.password,
|
|
256
|
+
}),
|
|
257
|
+
});
|
|
258
|
+
if (!acceptResponse.ok) {
|
|
259
|
+
const text = await acceptResponse.text();
|
|
260
|
+
throw new Error(`Failed to accept invitation for ${data.email}: ${acceptResponse.status} ${text}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Derive a deterministic internal password for n8n from the Octo user ID.
|
|
265
|
+
* Prefixed with "Octo@2026_" to satisfy n8n's password policy
|
|
266
|
+
* (requires uppercase letter).
|
|
267
|
+
*/
|
|
268
|
+
generateInternalPassword(userId) {
|
|
269
|
+
const hash = (0, node_crypto_1.createHmac)('sha256', N8N_USER_SYNC_SECRET)
|
|
270
|
+
.update(String(userId))
|
|
271
|
+
.digest('hex')
|
|
272
|
+
.slice(0, 32);
|
|
273
|
+
return `Octo@2026_${hash}`;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Fixed owner password for the internal n8n admin account.
|
|
277
|
+
*/
|
|
278
|
+
generateOwnerPassword() {
|
|
279
|
+
return 'Octo@2026';
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
exports.N8nUserSyncService = N8nUserSyncService;
|
|
283
|
+
exports.N8nUserSyncService = N8nUserSyncService = __decorate([
|
|
284
|
+
(0, core_1.Service)()
|
|
285
|
+
], N8nUserSyncService);
|
|
286
|
+
//# sourceMappingURL=n8n-user-sync.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"n8n-user-sync.service.js","sourceRoot":"","sources":["../../../src/n8n/sync/n8n-user-sync.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Event payload emitted when an n8n execution completes or fails. */
|
|
2
|
+
export interface N8nExecutionEvent {
|
|
3
|
+
executionId: string;
|
|
4
|
+
workflowId: string;
|
|
5
|
+
workflowName: string;
|
|
6
|
+
status: 'success' | 'error' | 'running';
|
|
7
|
+
startedAt: string;
|
|
8
|
+
stoppedAt: string | null;
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* N8nExecutionWatcher — periodically polls the n8n REST API for
|
|
13
|
+
* recently finished executions and emits EventBus events.
|
|
14
|
+
*
|
|
15
|
+
* Events emitted:
|
|
16
|
+
* - `n8n:executionFinished` — when an execution transitions to success/error
|
|
17
|
+
*/
|
|
18
|
+
export declare class N8nExecutionWatcher {
|
|
19
|
+
private readonly logger;
|
|
20
|
+
private n8nApiUrl;
|
|
21
|
+
private timer;
|
|
22
|
+
private lastCheckedAt;
|
|
23
|
+
setApiUrl(url: string): void;
|
|
24
|
+
/**
|
|
25
|
+
* Start polling for finished executions.
|
|
26
|
+
* @param intervalMs polling interval (default 15s)
|
|
27
|
+
*/
|
|
28
|
+
start(intervalMs?: number): void;
|
|
29
|
+
stop(): void;
|
|
30
|
+
private poll;
|
|
31
|
+
private fetchRecentExecutions;
|
|
32
|
+
private emitEvent;
|
|
33
|
+
/**
|
|
34
|
+
* Access the owner cookie from N8nUserSyncService via reflection.
|
|
35
|
+
* This avoids exposing internal state through a public method.
|
|
36
|
+
*/
|
|
37
|
+
private getOwnerCookie;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=n8n-execution-watcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"n8n-execution-watcher.d.ts","sourceRoot":"","sources":["../../../src/n8n/watcher/n8n-execution-watcher.ts"],"names":[],"mappings":"AAGA,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD;;;;;;GAMG;AACH,qBACa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwD;IAC/E,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,aAAa,CAAoB;IAEzC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI5B;;;OAGG;IACH,KAAK,CAAC,UAAU,SAAS,GAAG,IAAI;IAWhC,IAAI,IAAI,IAAI;YAQE,IAAI;YAiBJ,qBAAqB;IAyBnC,OAAO,CAAC,SAAS;IAkBjB;;;OAGG;IACH,OAAO,CAAC,cAAc;CAKvB"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.N8nExecutionWatcher = void 0;
|
|
10
|
+
const core_1 = require("@octo/core");
|
|
11
|
+
const n8n_user_sync_service_js_1 = require("../sync/n8n-user-sync.service.js");
|
|
12
|
+
/**
|
|
13
|
+
* N8nExecutionWatcher — periodically polls the n8n REST API for
|
|
14
|
+
* recently finished executions and emits EventBus events.
|
|
15
|
+
*
|
|
16
|
+
* Events emitted:
|
|
17
|
+
* - `n8n:executionFinished` — when an execution transitions to success/error
|
|
18
|
+
*/
|
|
19
|
+
let N8nExecutionWatcher = class N8nExecutionWatcher {
|
|
20
|
+
logger = core_1.Container.get(core_1.LoggerService).child('N8nExecWatcher');
|
|
21
|
+
n8nApiUrl = 'http://127.0.0.1:5678';
|
|
22
|
+
timer = null;
|
|
23
|
+
lastCheckedAt = new Date();
|
|
24
|
+
setApiUrl(url) {
|
|
25
|
+
this.n8nApiUrl = url;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Start polling for finished executions.
|
|
29
|
+
* @param intervalMs polling interval (default 15s)
|
|
30
|
+
*/
|
|
31
|
+
start(intervalMs = 15_000) {
|
|
32
|
+
if (this.timer)
|
|
33
|
+
return;
|
|
34
|
+
this.lastCheckedAt = new Date();
|
|
35
|
+
this.timer = setInterval(() => {
|
|
36
|
+
void this.poll();
|
|
37
|
+
}, intervalMs);
|
|
38
|
+
this.logger.info(`Polling n8n executions every ${intervalMs / 1000}s`);
|
|
39
|
+
}
|
|
40
|
+
stop() {
|
|
41
|
+
if (this.timer) {
|
|
42
|
+
clearInterval(this.timer);
|
|
43
|
+
this.timer = null;
|
|
44
|
+
this.logger.info('Stopped polling n8n executions');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async poll() {
|
|
48
|
+
try {
|
|
49
|
+
const userSync = core_1.Container.get(n8n_user_sync_service_js_1.N8nUserSyncService);
|
|
50
|
+
const cookie = this.getOwnerCookie(userSync);
|
|
51
|
+
if (!cookie)
|
|
52
|
+
return;
|
|
53
|
+
const executions = await this.fetchRecentExecutions(cookie);
|
|
54
|
+
for (const exec of executions) {
|
|
55
|
+
this.emitEvent(exec);
|
|
56
|
+
}
|
|
57
|
+
this.lastCheckedAt = new Date();
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
this.logger.debug(`Poll error: ${err.message}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async fetchRecentExecutions(cookie) {
|
|
64
|
+
// Fetch executions that finished after our last check
|
|
65
|
+
const params = new URLSearchParams({
|
|
66
|
+
status: 'finished',
|
|
67
|
+
limit: '20',
|
|
68
|
+
});
|
|
69
|
+
const response = await fetch(`${this.n8nApiUrl}/rest/executions?${params}`, { headers: { Cookie: cookie, 'Content-Type': 'application/json' } });
|
|
70
|
+
if (!response.ok)
|
|
71
|
+
return [];
|
|
72
|
+
const body = (await response.json());
|
|
73
|
+
const data = body.data;
|
|
74
|
+
const results = (data?.results ?? []);
|
|
75
|
+
// Filter to only executions that finished after our last check
|
|
76
|
+
return results.filter((exec) => {
|
|
77
|
+
if (!exec.stoppedAt)
|
|
78
|
+
return false;
|
|
79
|
+
return new Date(exec.stoppedAt) > this.lastCheckedAt;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
emitEvent(exec) {
|
|
83
|
+
const isError = exec.status === 'error' || exec.status === 'failed';
|
|
84
|
+
const event = {
|
|
85
|
+
executionId: exec.id,
|
|
86
|
+
workflowId: exec.workflowId,
|
|
87
|
+
workflowName: exec.workflowData?.name ?? `Workflow #${exec.workflowId}`,
|
|
88
|
+
status: isError ? 'error' : 'success',
|
|
89
|
+
startedAt: exec.startedAt,
|
|
90
|
+
stoppedAt: exec.stoppedAt,
|
|
91
|
+
error: exec.data?.resultData?.error?.message,
|
|
92
|
+
};
|
|
93
|
+
core_1.EventBus.emit('n8n:executionFinished', event);
|
|
94
|
+
this.logger.info(`n8n execution ${event.executionId} (${event.workflowName}): ${event.status}`);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Access the owner cookie from N8nUserSyncService via reflection.
|
|
98
|
+
* This avoids exposing internal state through a public method.
|
|
99
|
+
*/
|
|
100
|
+
getOwnerCookie(userSync) {
|
|
101
|
+
// N8nUserSyncService stores ownerCookie as a private field
|
|
102
|
+
const sync = userSync;
|
|
103
|
+
return sync.ownerCookie ?? null;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
exports.N8nExecutionWatcher = N8nExecutionWatcher;
|
|
107
|
+
exports.N8nExecutionWatcher = N8nExecutionWatcher = __decorate([
|
|
108
|
+
(0, core_1.Service)()
|
|
109
|
+
], N8nExecutionWatcher);
|
|
110
|
+
//# sourceMappingURL=n8n-execution-watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"n8n-execution-watcher.js","sourceRoot":"","sources":["../../../src/n8n/watcher/n8n-execution-watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { INodeType, INodeTypeDescription, IExecuteContext, INodeExecutionData } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Code Node — executes user-provided JavaScript code.
|
|
4
|
+
*
|
|
5
|
+
* Supports two modes:
|
|
6
|
+
* - runOnceForAllItems: code runs once with all items available
|
|
7
|
+
* - runOnceForEachItem: code runs once per input item
|
|
8
|
+
*
|
|
9
|
+
* The user code receives `$input` (items), `$json` (current item json),
|
|
10
|
+
* and must return items in the format [{ json: { ... } }].
|
|
11
|
+
*/
|
|
12
|
+
export declare class CodeNode implements INodeType {
|
|
13
|
+
description: INodeTypeDescription;
|
|
14
|
+
execute(context: IExecuteContext): Promise<INodeExecutionData[][]>;
|
|
15
|
+
private runForAllItems;
|
|
16
|
+
private runForEachItem;
|
|
17
|
+
private buildSandbox;
|
|
18
|
+
/**
|
|
19
|
+
* Normalize code output to INodeExecutionData[].
|
|
20
|
+
* Accepts: single object, array of objects, or already-formatted items.
|
|
21
|
+
*/
|
|
22
|
+
private normalizeOutput;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=code.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.node.d.ts","sourceRoot":"","sources":["../../src/nodes/code.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;GASG;AACH,qBAAa,QAAS,YAAW,SAAS;IACxC,WAAW,EAAE,oBAAoB,CA4C/B;IAEI,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;YAgB1D,cAAc;YAgBd,cAAc;IAuB5B,OAAO,CAAC,YAAY;IAuCpB;;;OAGG;IACH,OAAO,CAAC,eAAe;CA0BxB"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CodeNode = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Code Node — executes user-provided JavaScript code.
|
|
6
|
+
*
|
|
7
|
+
* Supports two modes:
|
|
8
|
+
* - runOnceForAllItems: code runs once with all items available
|
|
9
|
+
* - runOnceForEachItem: code runs once per input item
|
|
10
|
+
*
|
|
11
|
+
* The user code receives `$input` (items), `$json` (current item json),
|
|
12
|
+
* and must return items in the format [{ json: { ... } }].
|
|
13
|
+
*/
|
|
14
|
+
class CodeNode {
|
|
15
|
+
description = {
|
|
16
|
+
displayName: 'Code',
|
|
17
|
+
name: 'code',
|
|
18
|
+
group: ['transform'],
|
|
19
|
+
version: 1,
|
|
20
|
+
description: 'Execute custom JavaScript code to transform data.',
|
|
21
|
+
icon: 'code',
|
|
22
|
+
category: 'transform',
|
|
23
|
+
defaults: {
|
|
24
|
+
name: 'Code',
|
|
25
|
+
color: '#FF9922',
|
|
26
|
+
},
|
|
27
|
+
inputs: ['main'],
|
|
28
|
+
outputs: ['main'],
|
|
29
|
+
properties: [
|
|
30
|
+
{
|
|
31
|
+
displayName: 'Mode',
|
|
32
|
+
name: 'mode',
|
|
33
|
+
type: 'options',
|
|
34
|
+
default: 'runOnceForAllItems',
|
|
35
|
+
description: 'How to execute the code.',
|
|
36
|
+
options: [
|
|
37
|
+
{
|
|
38
|
+
name: 'Run Once for All Items',
|
|
39
|
+
value: 'runOnceForAllItems',
|
|
40
|
+
description: 'Code receives all items at once.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'Run Once for Each Item',
|
|
44
|
+
value: 'runOnceForEachItem',
|
|
45
|
+
description: 'Code runs separately for each input item.',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
displayName: 'JavaScript Code',
|
|
51
|
+
name: 'code',
|
|
52
|
+
type: 'string',
|
|
53
|
+
default: '// Access input items via $input.all()\n// Return items: [{ json: { key: "value" } }]\nreturn $input.all();',
|
|
54
|
+
description: 'The JavaScript code to execute. Must return an array of items with { json: { ... } } format.',
|
|
55
|
+
required: true,
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
async execute(context) {
|
|
60
|
+
const mode = context.getParam('mode');
|
|
61
|
+
const code = context.getParam('code');
|
|
62
|
+
const inputData = context.getInputData();
|
|
63
|
+
if (!code || code.trim() === '') {
|
|
64
|
+
return [inputData];
|
|
65
|
+
}
|
|
66
|
+
if (mode === 'runOnceForEachItem') {
|
|
67
|
+
return [await this.runForEachItem(code, inputData, context)];
|
|
68
|
+
}
|
|
69
|
+
return [await this.runForAllItems(code, inputData, context)];
|
|
70
|
+
}
|
|
71
|
+
async runForAllItems(code, inputData, context) {
|
|
72
|
+
const sandbox = this.buildSandbox(inputData, 0, context);
|
|
73
|
+
const fn = new Function(...Object.keys(sandbox), `"use strict";\n${code}`);
|
|
74
|
+
const result = await fn(...Object.values(sandbox));
|
|
75
|
+
return this.normalizeOutput(result);
|
|
76
|
+
}
|
|
77
|
+
async runForEachItem(code, inputData, context) {
|
|
78
|
+
const results = [];
|
|
79
|
+
for (let i = 0; i < inputData.length; i++) {
|
|
80
|
+
const sandbox = this.buildSandbox(inputData, i, context);
|
|
81
|
+
const fn = new Function(...Object.keys(sandbox), `"use strict";\n${code}`);
|
|
82
|
+
const result = await fn(...Object.values(sandbox));
|
|
83
|
+
const items = this.normalizeOutput(result);
|
|
84
|
+
results.push(...items);
|
|
85
|
+
}
|
|
86
|
+
return results;
|
|
87
|
+
}
|
|
88
|
+
buildSandbox(inputData, itemIndex, context) {
|
|
89
|
+
const currentItem = inputData[itemIndex] ?? { json: {} };
|
|
90
|
+
return {
|
|
91
|
+
$input: {
|
|
92
|
+
all: () => inputData,
|
|
93
|
+
first: () => inputData[0] ?? { json: {} },
|
|
94
|
+
last: () => inputData[inputData.length - 1] ?? { json: {} },
|
|
95
|
+
item: currentItem,
|
|
96
|
+
},
|
|
97
|
+
$json: currentItem.json,
|
|
98
|
+
$item: currentItem,
|
|
99
|
+
$itemIndex: itemIndex,
|
|
100
|
+
$now: new Date().toISOString(),
|
|
101
|
+
$today: new Date().toISOString().split('T')[0],
|
|
102
|
+
console: {
|
|
103
|
+
log: (...args) => context.logger.info(args.map(String).join(' ')),
|
|
104
|
+
warn: (...args) => context.logger.warn(args.map(String).join(' ')),
|
|
105
|
+
error: (...args) => context.logger.error(args.map(String).join(' ')),
|
|
106
|
+
},
|
|
107
|
+
JSON,
|
|
108
|
+
Math,
|
|
109
|
+
Date,
|
|
110
|
+
String,
|
|
111
|
+
Number,
|
|
112
|
+
Boolean,
|
|
113
|
+
Array,
|
|
114
|
+
Object,
|
|
115
|
+
parseInt,
|
|
116
|
+
parseFloat,
|
|
117
|
+
encodeURIComponent,
|
|
118
|
+
decodeURIComponent,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Normalize code output to INodeExecutionData[].
|
|
123
|
+
* Accepts: single object, array of objects, or already-formatted items.
|
|
124
|
+
*/
|
|
125
|
+
normalizeOutput(result) {
|
|
126
|
+
if (result === undefined || result === null) {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
// Already an array
|
|
130
|
+
if (Array.isArray(result)) {
|
|
131
|
+
return result.map((item) => {
|
|
132
|
+
if (item && typeof item === 'object' && 'json' in item) {
|
|
133
|
+
return item;
|
|
134
|
+
}
|
|
135
|
+
return { json: item };
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
// Single object
|
|
139
|
+
if (typeof result === 'object') {
|
|
140
|
+
if ('json' in result) {
|
|
141
|
+
return [result];
|
|
142
|
+
}
|
|
143
|
+
return [{ json: result }];
|
|
144
|
+
}
|
|
145
|
+
// Primitive value
|
|
146
|
+
return [{ json: { result } }];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.CodeNode = CodeNode;
|
|
150
|
+
//# sourceMappingURL=code.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.node.js","sourceRoot":"","sources":["../../src/nodes/code.node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { INodeType, INodeTypeDescription, IExecuteContext, INodeExecutionData } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* ErrorTrigger Node — triggers when a workflow execution encounters an error.
|
|
4
|
+
*
|
|
5
|
+
* This node acts as an error handler. When connected to the error output
|
|
6
|
+
* of another node, it receives the error data and can process it
|
|
7
|
+
* (e.g., send notifications, log errors, retry).
|
|
8
|
+
*
|
|
9
|
+
* Equivalent to n8n's Error Trigger node.
|
|
10
|
+
*/
|
|
11
|
+
export declare class ErrorTriggerNode implements INodeType {
|
|
12
|
+
description: INodeTypeDescription;
|
|
13
|
+
execute(context: IExecuteContext): Promise<INodeExecutionData[][]>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=error-trigger.node.d.ts.map
|