@fsai-flow/core 0.0.5 → 0.1.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/dist/index.d.ts +17 -0
- package/dist/index.js +61 -0
- package/dist/lib/ActiveWebhooks.d.ts +59 -0
- package/dist/lib/ActiveWebhooks.js +177 -0
- package/dist/lib/ActiveWorkflows.d.ts +87 -0
- package/dist/lib/ActiveWorkflows.js +465 -0
- package/dist/lib/BinaryDataManager/FileSystem.d.ts +26 -0
- package/dist/lib/BinaryDataManager/FileSystem.js +180 -0
- package/dist/lib/BinaryDataManager/index.d.ts +21 -0
- package/dist/lib/BinaryDataManager/index.js +129 -0
- package/dist/lib/ChangeCase.d.ts +9 -0
- package/dist/lib/ChangeCase.js +43 -0
- package/dist/lib/Constants.d.ts +14 -0
- package/dist/lib/Constants.js +18 -0
- package/dist/lib/Credentials.d.ts +27 -0
- package/dist/lib/Credentials.js +88 -0
- package/dist/lib/FileSystem.d.ts +26 -0
- package/dist/lib/FileSystem.js +180 -0
- package/dist/lib/InputConnectionDataLegacy.d.ts +2 -0
- package/dist/lib/InputConnectionDataLegacy.js +72 -0
- package/dist/lib/Interfaces.d.ts +147 -0
- package/dist/lib/Interfaces.js +2 -0
- package/dist/lib/LoadNodeParameterOptions.d.ts +39 -0
- package/dist/lib/LoadNodeParameterOptions.js +152 -0
- package/dist/lib/NodeExecuteFunctions.d.ts +225 -0
- package/dist/lib/NodeExecuteFunctions.js +2467 -0
- package/dist/lib/NodesLoader/constants.d.ts +5 -0
- package/dist/lib/NodesLoader/constants.js +105 -0
- package/dist/lib/NodesLoader/custom-directory-loader.d.ts +9 -0
- package/dist/lib/NodesLoader/custom-directory-loader.js +35 -0
- package/dist/lib/NodesLoader/directory-loader.d.ts +66 -0
- package/dist/lib/NodesLoader/directory-loader.js +367 -0
- package/dist/lib/NodesLoader/index.d.ts +5 -0
- package/dist/lib/NodesLoader/index.js +11 -0
- package/dist/lib/NodesLoader/lazy-package-directory-loader.d.ts +7 -0
- package/dist/lib/NodesLoader/lazy-package-directory-loader.js +44 -0
- package/dist/lib/NodesLoader/load-class-in-isolation.d.ts +1 -0
- package/dist/lib/NodesLoader/load-class-in-isolation.js +17 -0
- package/dist/lib/NodesLoader/package-directory-loader.d.ts +17 -0
- package/dist/lib/NodesLoader/package-directory-loader.js +92 -0
- package/dist/lib/NodesLoader/types.d.ts +14 -0
- package/dist/lib/NodesLoader/types.js +2 -0
- package/dist/lib/RedisLeaderElectionManager.d.ts +53 -0
- package/dist/lib/RedisLeaderElectionManager.js +279 -0
- package/dist/lib/RequestTypes.d.ts +58 -0
- package/dist/lib/RequestTypes.js +8 -0
- package/dist/lib/UserSettings.d.ts +80 -0
- package/dist/lib/UserSettings.js +269 -0
- package/dist/lib/WorkflowExecute.d.ts +53 -0
- package/dist/lib/WorkflowExecute.js +906 -0
- package/dist/lib/index.d.ts +21 -0
- package/dist/lib/index.js +129 -0
- package/dist/utils/crypto.d.ts +1 -0
- package/dist/utils/crypto.js +7 -0
- package/package.json +52 -52
- package/dist/README.md +0 -31
- package/dist/package.json +0 -54
- package/eslint.config.js +0 -19
- package/jest.config.ts +0 -10
- package/project.json +0 -19
- package/src/index.ts +0 -28
- package/src/lib/ActiveWebhooks.ts +0 -245
- package/src/lib/ActiveWorkflows.ts +0 -575
- package/src/lib/BinaryDataManager/FileSystem.ts +0 -214
- package/src/lib/BinaryDataManager/index.ts +0 -187
- package/src/lib/ChangeCase.ts +0 -45
- package/src/lib/Constants.ts +0 -16
- package/src/lib/Credentials.ts +0 -108
- package/src/lib/FileSystem.ts +0 -214
- package/src/lib/InputConnectionDataLegacy.ts +0 -123
- package/src/lib/Interfaces.ts +0 -338
- package/src/lib/LoadNodeParameterOptions.ts +0 -235
- package/src/lib/NodeExecuteFunctions.ts +0 -3700
- package/src/lib/NodesLoader/constants.ts +0 -112
- package/src/lib/NodesLoader/custom-directory-loader.ts +0 -31
- package/src/lib/NodesLoader/directory-loader.ts +0 -458
- package/src/lib/NodesLoader/index.ts +0 -5
- package/src/lib/NodesLoader/lazy-package-directory-loader.ts +0 -55
- package/src/lib/NodesLoader/load-class-in-isolation.ts +0 -19
- package/src/lib/NodesLoader/package-directory-loader.ts +0 -107
- package/src/lib/NodesLoader/types.ts +0 -14
- package/src/lib/RedisLeaderElectionManager.ts +0 -334
- package/src/lib/UserSettings.ts +0 -292
- package/src/lib/WorkflowExecute.ts +0 -1128
- package/src/lib/index.ts +0 -187
- package/src/utils/crypto.ts +0 -5
- package/tests/Credentials.test.ts +0 -88
- package/tests/Helpers.ts +0 -808
- package/tests/WorkflowExecute.test.ts +0 -1242
- package/tsconfig.json +0 -41
- package/tsconfig.lib.json +0 -10
- package/tsconfig.spec.json +0 -14
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { INodeProperties } from "@fsai-flow/workflow";
|
|
2
|
+
export declare const CUSTOM_NODES_CATEGORY = "Custom Nodes";
|
|
3
|
+
export declare const commonPollingParameters: INodeProperties[];
|
|
4
|
+
export declare const commonCORSParameters: INodeProperties[];
|
|
5
|
+
export declare const commonDeclarativeNodeOptionParameters: INodeProperties;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.commonDeclarativeNodeOptionParameters = exports.commonCORSParameters = exports.commonPollingParameters = exports.CUSTOM_NODES_CATEGORY = void 0;
|
|
4
|
+
const workflow_1 = require("@fsai-flow/workflow");
|
|
5
|
+
exports.CUSTOM_NODES_CATEGORY = "Custom Nodes";
|
|
6
|
+
exports.commonPollingParameters = [
|
|
7
|
+
{
|
|
8
|
+
displayName: "Poll Times",
|
|
9
|
+
name: "pollTimes",
|
|
10
|
+
type: "fixedCollection",
|
|
11
|
+
typeOptions: {
|
|
12
|
+
multipleValues: true,
|
|
13
|
+
multipleValueButtonText: "Add Poll Time",
|
|
14
|
+
},
|
|
15
|
+
default: { item: [{ mode: "everyMinute" }] },
|
|
16
|
+
description: "Time at which polling should occur",
|
|
17
|
+
placeholder: "Add Poll Time",
|
|
18
|
+
options: workflow_1.cronNodeOptions,
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
exports.commonCORSParameters = [
|
|
22
|
+
{
|
|
23
|
+
displayName: "Allowed Origins (CORS)",
|
|
24
|
+
name: "allowedOrigins",
|
|
25
|
+
type: "string",
|
|
26
|
+
default: "*",
|
|
27
|
+
description: "Comma-separated list of URLs allowed for cross-origin non-preflight requests. Use * (default) to allow all origins.",
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
exports.commonDeclarativeNodeOptionParameters = {
|
|
31
|
+
displayName: "Request Options",
|
|
32
|
+
name: "requestOptions",
|
|
33
|
+
type: "collection",
|
|
34
|
+
isNodeSetting: true,
|
|
35
|
+
placeholder: "Add Option",
|
|
36
|
+
default: {},
|
|
37
|
+
options: [
|
|
38
|
+
{
|
|
39
|
+
displayName: "Batching",
|
|
40
|
+
name: "batching",
|
|
41
|
+
placeholder: "Add Batching",
|
|
42
|
+
type: "fixedCollection",
|
|
43
|
+
typeOptions: {
|
|
44
|
+
multipleValues: false,
|
|
45
|
+
},
|
|
46
|
+
default: {
|
|
47
|
+
batch: {},
|
|
48
|
+
},
|
|
49
|
+
options: [
|
|
50
|
+
{
|
|
51
|
+
displayName: "Batching",
|
|
52
|
+
name: "batch",
|
|
53
|
+
values: [
|
|
54
|
+
{
|
|
55
|
+
displayName: "Items per Batch",
|
|
56
|
+
name: "batchSize",
|
|
57
|
+
type: "number",
|
|
58
|
+
typeOptions: {
|
|
59
|
+
minValue: -1,
|
|
60
|
+
},
|
|
61
|
+
default: 50,
|
|
62
|
+
description: "Input will be split in batches to throttle requests. -1 for disabled. 0 will be treated as 1.",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
displayName: "Batch Interval (ms)",
|
|
66
|
+
name: "batchInterval",
|
|
67
|
+
type: "number",
|
|
68
|
+
typeOptions: {
|
|
69
|
+
minValue: 0,
|
|
70
|
+
},
|
|
71
|
+
default: 1000,
|
|
72
|
+
description: "Time (in milliseconds) between each batch of requests. 0 for disabled.",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
displayName: "Ignore SSL Issues (Insecure)",
|
|
80
|
+
name: "allowUnauthorizedCerts",
|
|
81
|
+
type: "boolean",
|
|
82
|
+
noDataExpression: true,
|
|
83
|
+
default: false,
|
|
84
|
+
description: "Whether to accept the response even if SSL certificate validation is not possible",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
displayName: "Proxy",
|
|
88
|
+
name: "proxy",
|
|
89
|
+
type: "string",
|
|
90
|
+
default: "",
|
|
91
|
+
placeholder: "e.g. http://myproxy:3128",
|
|
92
|
+
description: "HTTP proxy to use. If authentication is required it can be defined as follow: http://username:password@myproxy:3128",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
displayName: "Timeout",
|
|
96
|
+
name: "timeout",
|
|
97
|
+
type: "number",
|
|
98
|
+
typeOptions: {
|
|
99
|
+
minValue: 1,
|
|
100
|
+
},
|
|
101
|
+
default: 10000,
|
|
102
|
+
description: "Time in ms to wait for the server to send response headers (and start the response body) before aborting the request",
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DirectoryLoader } from "./directory-loader";
|
|
2
|
+
/**
|
|
3
|
+
* Loader for source files of nodes and credentials located in a custom dir,
|
|
4
|
+
* e.g. `~/.n8n/custom`
|
|
5
|
+
*/
|
|
6
|
+
export declare class CustomDirectoryLoader extends DirectoryLoader {
|
|
7
|
+
packageName: string;
|
|
8
|
+
loadAll(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CustomDirectoryLoader = void 0;
|
|
7
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
8
|
+
const directory_loader_1 = require("./directory-loader");
|
|
9
|
+
/**
|
|
10
|
+
* Loader for source files of nodes and credentials located in a custom dir,
|
|
11
|
+
* e.g. `~/.n8n/custom`
|
|
12
|
+
*/
|
|
13
|
+
class CustomDirectoryLoader extends directory_loader_1.DirectoryLoader {
|
|
14
|
+
constructor() {
|
|
15
|
+
super(...arguments);
|
|
16
|
+
this.packageName = "CUSTOM";
|
|
17
|
+
}
|
|
18
|
+
async loadAll() {
|
|
19
|
+
const nodes = await (0, fast_glob_1.default)("**/*.node.js", {
|
|
20
|
+
cwd: this.directory,
|
|
21
|
+
absolute: true,
|
|
22
|
+
});
|
|
23
|
+
for (const nodePath of nodes) {
|
|
24
|
+
this.loadNodeFromFile(nodePath);
|
|
25
|
+
}
|
|
26
|
+
const credentials = await (0, fast_glob_1.default)("**/*.credentials.js", {
|
|
27
|
+
cwd: this.directory,
|
|
28
|
+
absolute: true,
|
|
29
|
+
});
|
|
30
|
+
for (const credentialPath of credentials) {
|
|
31
|
+
this.loadCredentialFromFile(credentialPath);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.CustomDirectoryLoader = CustomDirectoryLoader;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ICredentialType, ICredentialTypeData, INodeCredentialDescription, INodeType, INodeTypeBaseDescription, INodeTypeData, INodeTypeNameVersion, IVersionedNodeType, KnownNodesAndCredentials } from "@fsai-flow/workflow";
|
|
2
|
+
export type Types = {
|
|
3
|
+
nodes: INodeTypeBaseDescription[];
|
|
4
|
+
credentials: ICredentialType[];
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Base class for loading n8n nodes and credentials from a directory.
|
|
8
|
+
* Handles the common functionality for resolving paths, loading classes, and managing node and credential types.
|
|
9
|
+
*/
|
|
10
|
+
export declare abstract class DirectoryLoader {
|
|
11
|
+
readonly directory: string;
|
|
12
|
+
protected excludeNodes: string[];
|
|
13
|
+
protected includeNodes: string[];
|
|
14
|
+
isLazyLoaded: boolean;
|
|
15
|
+
loadedNodes: INodeTypeNameVersion[];
|
|
16
|
+
nodeTypes: INodeTypeData;
|
|
17
|
+
credentialTypes: ICredentialTypeData;
|
|
18
|
+
known: KnownNodesAndCredentials;
|
|
19
|
+
types: Types;
|
|
20
|
+
readonly nodesByCredential: Record<string, string[]>;
|
|
21
|
+
constructor(directory: string, excludeNodes?: string[], includeNodes?: string[]);
|
|
22
|
+
abstract packageName: string;
|
|
23
|
+
abstract loadAll(): Promise<void>;
|
|
24
|
+
reset(): void;
|
|
25
|
+
protected resolvePath(file: string): string;
|
|
26
|
+
private loadClass;
|
|
27
|
+
/** Loads a nodes class from a file, fixes icons, and augments the codex */
|
|
28
|
+
loadNodeFromFile(filePath: string): void;
|
|
29
|
+
getNode(nodeType: string): {
|
|
30
|
+
type: INodeType | import("@fsai-flow/workflow").INodeVersionedType;
|
|
31
|
+
sourcePath: string;
|
|
32
|
+
};
|
|
33
|
+
/** Loads a credential class from a file, and fixes icons */
|
|
34
|
+
loadCredentialFromFile(filePath: string): void;
|
|
35
|
+
getCredential(credentialType: string): {
|
|
36
|
+
type: ICredentialType;
|
|
37
|
+
sourcePath: string;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Returns an array of credential descriptions that are supported by a node.
|
|
41
|
+
* For versioned nodes, combines and deduplicates credentials from all versions.
|
|
42
|
+
*/
|
|
43
|
+
getCredentialsForNode(object: IVersionedNodeType | INodeType): INodeCredentialDescription[];
|
|
44
|
+
/**
|
|
45
|
+
* Returns an array of all versions of a node type.
|
|
46
|
+
* For non-versioned nodes, returns an array with just that node.
|
|
47
|
+
* For versioned nodes, returns all available versions.
|
|
48
|
+
*/
|
|
49
|
+
getVersionedNodeTypeAll(object: IVersionedNodeType | INodeType): INodeType[];
|
|
50
|
+
/**
|
|
51
|
+
* Retrieves `categories`, `subcategories` and alias (if defined)
|
|
52
|
+
* from the codex data for the node at the given file path.
|
|
53
|
+
*/
|
|
54
|
+
private getCodex;
|
|
55
|
+
/**
|
|
56
|
+
* Adds a node codex `categories` and `subcategories` (if defined)
|
|
57
|
+
* to a node description `codex` property.
|
|
58
|
+
*/
|
|
59
|
+
private addCodex;
|
|
60
|
+
private addLoadOptionsMethods;
|
|
61
|
+
private applySpecialNodeParameters;
|
|
62
|
+
private getIconPath;
|
|
63
|
+
private fixIconPaths;
|
|
64
|
+
/** Augments additional `Request Options` property on declarative node-type */
|
|
65
|
+
static applyDeclarativeNodeOptionParameters(nodeType: INodeType): void;
|
|
66
|
+
}
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.DirectoryLoader = void 0;
|
|
40
|
+
const path = __importStar(require("node:path"));
|
|
41
|
+
const workflow_1 = require("@fsai-flow/workflow");
|
|
42
|
+
const uniqBy_1 = __importDefault(require("lodash/uniqBy"));
|
|
43
|
+
const constants_1 = require("./constants");
|
|
44
|
+
const load_class_in_isolation_1 = require("./load-class-in-isolation");
|
|
45
|
+
function toJSON() {
|
|
46
|
+
return {
|
|
47
|
+
...this,
|
|
48
|
+
authenticate: typeof this.authenticate === "function" ? {} : this.authenticate,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Base class for loading n8n nodes and credentials from a directory.
|
|
53
|
+
* Handles the common functionality for resolving paths, loading classes, and managing node and credential types.
|
|
54
|
+
*/
|
|
55
|
+
class DirectoryLoader {
|
|
56
|
+
constructor(directory, excludeNodes = [], includeNodes = []) {
|
|
57
|
+
this.directory = directory;
|
|
58
|
+
this.excludeNodes = excludeNodes;
|
|
59
|
+
this.includeNodes = includeNodes;
|
|
60
|
+
this.isLazyLoaded = false;
|
|
61
|
+
// Another way of keeping track of the names and versions of a node. This
|
|
62
|
+
// seems to only be used by the installedPackages repository
|
|
63
|
+
this.loadedNodes = [];
|
|
64
|
+
// Stores the loaded descriptions and sourcepaths
|
|
65
|
+
this.nodeTypes = {};
|
|
66
|
+
this.credentialTypes = {};
|
|
67
|
+
// Stores the location and classnames of the nodes and credentials that are
|
|
68
|
+
// loaded; used to actually load the files in lazy-loading scenario.
|
|
69
|
+
this.known = { nodes: {}, credentials: {} };
|
|
70
|
+
// Stores the different versions with their individual descriptions
|
|
71
|
+
this.types = { nodes: [], credentials: [] };
|
|
72
|
+
this.nodesByCredential = {};
|
|
73
|
+
}
|
|
74
|
+
reset() {
|
|
75
|
+
this.loadedNodes = [];
|
|
76
|
+
this.nodeTypes = {};
|
|
77
|
+
this.credentialTypes = {};
|
|
78
|
+
this.known = { nodes: {}, credentials: {} };
|
|
79
|
+
this.types = { nodes: [], credentials: [] };
|
|
80
|
+
}
|
|
81
|
+
resolvePath(file) {
|
|
82
|
+
return path.resolve(this.directory, file);
|
|
83
|
+
}
|
|
84
|
+
loadClass(sourcePath) {
|
|
85
|
+
const filePath = this.resolvePath(sourcePath);
|
|
86
|
+
const [className] = path.parse(sourcePath).name.split(".");
|
|
87
|
+
try {
|
|
88
|
+
return (0, load_class_in_isolation_1.loadClassInIsolation)(filePath, className);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
throw error instanceof TypeError
|
|
92
|
+
? new Error("Class could not be found. Please check if the class is named correctly.")
|
|
93
|
+
: error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Loads a nodes class from a file, fixes icons, and augments the codex */
|
|
97
|
+
loadNodeFromFile(filePath) {
|
|
98
|
+
const tempNode = this.loadClass(filePath);
|
|
99
|
+
this.addCodex(tempNode, filePath);
|
|
100
|
+
const nodeType = tempNode.description.name;
|
|
101
|
+
if (this.includeNodes.length && !this.includeNodes.includes(nodeType)) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (this.excludeNodes.includes(nodeType)) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
this.fixIconPaths(tempNode.description, filePath);
|
|
108
|
+
let nodeVersion = 1;
|
|
109
|
+
if ("nodeVersions" in tempNode) {
|
|
110
|
+
for (const versionNode of Object.values(tempNode.nodeVersions)) {
|
|
111
|
+
this.fixIconPaths(versionNode.description, filePath);
|
|
112
|
+
}
|
|
113
|
+
for (const version of Object.values(tempNode.nodeVersions)) {
|
|
114
|
+
this.addLoadOptionsMethods(version);
|
|
115
|
+
this.applySpecialNodeParameters(version);
|
|
116
|
+
}
|
|
117
|
+
const currentVersionNode = tempNode.nodeVersions[tempNode.currentVersion];
|
|
118
|
+
this.addCodex(currentVersionNode, filePath);
|
|
119
|
+
nodeVersion = tempNode.currentVersion;
|
|
120
|
+
if (Object.hasOwn(currentVersionNode, "executeSingle")) {
|
|
121
|
+
throw new Error('"executeSingle" has been removed. Please update the code of this node to use "execute" instead.');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
this.addLoadOptionsMethods(tempNode);
|
|
126
|
+
this.applySpecialNodeParameters(tempNode);
|
|
127
|
+
// Short renaming to avoid type issues
|
|
128
|
+
nodeVersion = Array.isArray(tempNode.description.version)
|
|
129
|
+
? tempNode.description.version.slice(-1)[0]
|
|
130
|
+
: tempNode.description.version;
|
|
131
|
+
}
|
|
132
|
+
this.known.nodes[nodeType] = {
|
|
133
|
+
className: tempNode.constructor.name,
|
|
134
|
+
sourcePath: filePath,
|
|
135
|
+
};
|
|
136
|
+
this.nodeTypes[nodeType] = {
|
|
137
|
+
type: tempNode,
|
|
138
|
+
sourcePath: filePath,
|
|
139
|
+
};
|
|
140
|
+
this.loadedNodes.push({
|
|
141
|
+
name: nodeType,
|
|
142
|
+
version: nodeVersion,
|
|
143
|
+
});
|
|
144
|
+
for (const { description } of this.getVersionedNodeTypeAll(tempNode)) {
|
|
145
|
+
this.types.nodes.push(description);
|
|
146
|
+
}
|
|
147
|
+
for (const credential of this.getCredentialsForNode(tempNode)) {
|
|
148
|
+
if (!this.nodesByCredential[credential.name]) {
|
|
149
|
+
this.nodesByCredential[credential.name] = [];
|
|
150
|
+
}
|
|
151
|
+
this.nodesByCredential[credential.name].push(nodeType);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
getNode(nodeType) {
|
|
155
|
+
const { nodeTypes, known: { nodes: knownNodes }, } = this;
|
|
156
|
+
if (!(nodeType in nodeTypes) && nodeType in knownNodes) {
|
|
157
|
+
const { sourcePath } = knownNodes[nodeType];
|
|
158
|
+
this.loadNodeFromFile(sourcePath);
|
|
159
|
+
}
|
|
160
|
+
if (nodeType in nodeTypes) {
|
|
161
|
+
return nodeTypes[nodeType];
|
|
162
|
+
}
|
|
163
|
+
throw new Error(`Unrecognized node type: ${nodeType}`);
|
|
164
|
+
}
|
|
165
|
+
/** Loads a credential class from a file, and fixes icons */
|
|
166
|
+
loadCredentialFromFile(filePath) {
|
|
167
|
+
const tempCredential = this.loadClass(filePath);
|
|
168
|
+
// Add serializer method "toJSON" to the class so that authenticate method (if defined)
|
|
169
|
+
// gets mapped to the authenticate attribute before it is sent to the client.
|
|
170
|
+
// The authenticate property is used by the client to decide whether or not to
|
|
171
|
+
// include the credential type in the predefined credentials (HTTP node)
|
|
172
|
+
Object.assign(tempCredential, { toJSON });
|
|
173
|
+
this.fixIconPaths(tempCredential, filePath);
|
|
174
|
+
const credentialType = tempCredential.name;
|
|
175
|
+
this.known.credentials[credentialType] = {
|
|
176
|
+
className: tempCredential.constructor.name,
|
|
177
|
+
sourcePath: filePath,
|
|
178
|
+
extends: tempCredential.extends,
|
|
179
|
+
supportedNodes: this.nodesByCredential[credentialType],
|
|
180
|
+
};
|
|
181
|
+
this.credentialTypes[credentialType] = {
|
|
182
|
+
type: tempCredential,
|
|
183
|
+
sourcePath: filePath,
|
|
184
|
+
};
|
|
185
|
+
this.types.credentials.push(tempCredential);
|
|
186
|
+
}
|
|
187
|
+
getCredential(credentialType) {
|
|
188
|
+
const { credentialTypes, known: { credentials: knownCredentials }, } = this;
|
|
189
|
+
if (!(credentialType in credentialTypes) &&
|
|
190
|
+
credentialType in knownCredentials) {
|
|
191
|
+
const { sourcePath } = knownCredentials[credentialType];
|
|
192
|
+
this.loadCredentialFromFile(sourcePath);
|
|
193
|
+
}
|
|
194
|
+
if (credentialType in credentialTypes) {
|
|
195
|
+
return credentialTypes[credentialType];
|
|
196
|
+
}
|
|
197
|
+
throw new Error(`Unrecognized credential type: ${credentialType}`);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Returns an array of credential descriptions that are supported by a node.
|
|
201
|
+
* For versioned nodes, combines and deduplicates credentials from all versions.
|
|
202
|
+
*/
|
|
203
|
+
getCredentialsForNode(object) {
|
|
204
|
+
if ("nodeVersions" in object) {
|
|
205
|
+
const credentials = Object.values(object.nodeVersions).flatMap(({ description }) => description.credentials ?? []);
|
|
206
|
+
return (0, uniqBy_1.default)(credentials, "name");
|
|
207
|
+
}
|
|
208
|
+
return object.description.credentials ?? [];
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Returns an array of all versions of a node type.
|
|
212
|
+
* For non-versioned nodes, returns an array with just that node.
|
|
213
|
+
* For versioned nodes, returns all available versions.
|
|
214
|
+
*/
|
|
215
|
+
getVersionedNodeTypeAll(object) {
|
|
216
|
+
if ("nodeVersions" in object) {
|
|
217
|
+
const nodeVersions = Object.values(object.nodeVersions).map((element) => {
|
|
218
|
+
element.description.name = object.description.name;
|
|
219
|
+
element.description.codex = object.description.codex;
|
|
220
|
+
return element;
|
|
221
|
+
});
|
|
222
|
+
return (0, uniqBy_1.default)(nodeVersions.reverse(), (node) => {
|
|
223
|
+
const { version } = node.description;
|
|
224
|
+
return Array.isArray(version) ? version.join(",") : version.toString();
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
return [object];
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Retrieves `categories`, `subcategories` and alias (if defined)
|
|
231
|
+
* from the codex data for the node at the given file path.
|
|
232
|
+
*/
|
|
233
|
+
getCodex(filePath) {
|
|
234
|
+
const codexFilePath = this.resolvePath(`${filePath}on`); // .js to .json
|
|
235
|
+
const { categories, subcategories, resources: { primaryDocumentation, credentialDocumentation }, alias, } = module.require(codexFilePath);
|
|
236
|
+
return {
|
|
237
|
+
...(categories && { categories }),
|
|
238
|
+
...(subcategories && { subcategories }),
|
|
239
|
+
...(alias && { alias }),
|
|
240
|
+
resources: {
|
|
241
|
+
primaryDocumentation,
|
|
242
|
+
credentialDocumentation,
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Adds a node codex `categories` and `subcategories` (if defined)
|
|
248
|
+
* to a node description `codex` property.
|
|
249
|
+
*/
|
|
250
|
+
addCodex(node, filePath) {
|
|
251
|
+
const isCustom = this.packageName === "CUSTOM";
|
|
252
|
+
try {
|
|
253
|
+
let codex;
|
|
254
|
+
if (!isCustom) {
|
|
255
|
+
codex = node.description.codex;
|
|
256
|
+
}
|
|
257
|
+
if (codex === undefined) {
|
|
258
|
+
codex = this.getCodex(filePath);
|
|
259
|
+
}
|
|
260
|
+
if (isCustom) {
|
|
261
|
+
codex.categories = codex.categories
|
|
262
|
+
? codex.categories.concat(constants_1.CUSTOM_NODES_CATEGORY)
|
|
263
|
+
: [constants_1.CUSTOM_NODES_CATEGORY];
|
|
264
|
+
}
|
|
265
|
+
node.description.codex = codex;
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
console.debug(`No codex available for: ${node.description.name}`);
|
|
269
|
+
if (isCustom) {
|
|
270
|
+
node.description.codex = {
|
|
271
|
+
categories: [constants_1.CUSTOM_NODES_CATEGORY],
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
addLoadOptionsMethods(node) {
|
|
277
|
+
if (node?.methods?.loadOptions) {
|
|
278
|
+
node.description.__loadOptionsMethods = Object.keys(node.methods.loadOptions);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
applySpecialNodeParameters(nodeType) {
|
|
282
|
+
const { properties, polling, supportsCORS } = nodeType.description;
|
|
283
|
+
if (polling) {
|
|
284
|
+
properties.unshift(...constants_1.commonPollingParameters);
|
|
285
|
+
}
|
|
286
|
+
if (nodeType.webhook && supportsCORS) {
|
|
287
|
+
const optionsProperty = properties.find(({ name }) => name === "options");
|
|
288
|
+
if (optionsProperty)
|
|
289
|
+
optionsProperty.options = [
|
|
290
|
+
...constants_1.commonCORSParameters,
|
|
291
|
+
...optionsProperty.options,
|
|
292
|
+
];
|
|
293
|
+
else
|
|
294
|
+
properties.push(...constants_1.commonCORSParameters);
|
|
295
|
+
}
|
|
296
|
+
DirectoryLoader.applyDeclarativeNodeOptionParameters(nodeType);
|
|
297
|
+
}
|
|
298
|
+
getIconPath(icon, filePath) {
|
|
299
|
+
const iconPath = path.join(path.dirname(filePath), icon.replace("file:", ""));
|
|
300
|
+
return `icons/${this.packageName}/${iconPath}`;
|
|
301
|
+
}
|
|
302
|
+
fixIconPaths(obj, filePath) {
|
|
303
|
+
const { icon } = obj;
|
|
304
|
+
if (!icon)
|
|
305
|
+
return;
|
|
306
|
+
if (typeof icon === "string") {
|
|
307
|
+
if (icon.startsWith("file:")) {
|
|
308
|
+
obj.iconUrl = this.getIconPath(icon, filePath);
|
|
309
|
+
obj.icon = undefined;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
else if (icon.light.startsWith("file:") &&
|
|
313
|
+
icon.dark.startsWith("file:")) {
|
|
314
|
+
obj.iconUrl = {
|
|
315
|
+
light: this.getIconPath(icon.light, filePath),
|
|
316
|
+
dark: this.getIconPath(icon.dark, filePath),
|
|
317
|
+
};
|
|
318
|
+
obj.icon = undefined;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/** Augments additional `Request Options` property on declarative node-type */
|
|
322
|
+
static applyDeclarativeNodeOptionParameters(nodeType) {
|
|
323
|
+
if (!!nodeType.execute ||
|
|
324
|
+
!!nodeType.trigger ||
|
|
325
|
+
!!nodeType.webhook ||
|
|
326
|
+
!!nodeType.description.polling ||
|
|
327
|
+
(0, workflow_1.isSubNodeType)(nodeType.description)) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const parameters = nodeType.description.properties;
|
|
331
|
+
if (!parameters) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
// Was originally under "options" instead of "requestOptions" so the chance
|
|
335
|
+
// that that existed was quite high. With this name the chance is actually
|
|
336
|
+
// very low that it already exists but lets leave it in anyway to be sure.
|
|
337
|
+
const existingRequestOptionsIndex = parameters.findIndex((parameter) => parameter.name === "requestOptions");
|
|
338
|
+
if (existingRequestOptionsIndex !== -1) {
|
|
339
|
+
parameters[existingRequestOptionsIndex] = {
|
|
340
|
+
...constants_1.commonDeclarativeNodeOptionParameters,
|
|
341
|
+
options: [
|
|
342
|
+
...(constants_1.commonDeclarativeNodeOptionParameters.options ?? []),
|
|
343
|
+
...(parameters[existingRequestOptionsIndex]?.options ?? []),
|
|
344
|
+
],
|
|
345
|
+
};
|
|
346
|
+
const options = parameters[existingRequestOptionsIndex]?.options;
|
|
347
|
+
if (options) {
|
|
348
|
+
options.sort((a, b) => {
|
|
349
|
+
if ("displayName" in a && "displayName" in b) {
|
|
350
|
+
if (a.displayName < b.displayName) {
|
|
351
|
+
return -1;
|
|
352
|
+
}
|
|
353
|
+
if (a.displayName > b.displayName) {
|
|
354
|
+
return 1;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return 0;
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
parameters.push(constants_1.commonDeclarativeNodeOptionParameters);
|
|
363
|
+
}
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
exports.DirectoryLoader = DirectoryLoader;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { CustomDirectoryLoader } from "./custom-directory-loader";
|
|
2
|
+
export { DirectoryLoader, type Types } from "./directory-loader";
|
|
3
|
+
export { LazyPackageDirectoryLoader } from "./lazy-package-directory-loader";
|
|
4
|
+
export { PackageDirectoryLoader } from "./package-directory-loader";
|
|
5
|
+
export type { n8n } from "./types";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PackageDirectoryLoader = exports.LazyPackageDirectoryLoader = exports.DirectoryLoader = exports.CustomDirectoryLoader = void 0;
|
|
4
|
+
var custom_directory_loader_1 = require("./custom-directory-loader");
|
|
5
|
+
Object.defineProperty(exports, "CustomDirectoryLoader", { enumerable: true, get: function () { return custom_directory_loader_1.CustomDirectoryLoader; } });
|
|
6
|
+
var directory_loader_1 = require("./directory-loader");
|
|
7
|
+
Object.defineProperty(exports, "DirectoryLoader", { enumerable: true, get: function () { return directory_loader_1.DirectoryLoader; } });
|
|
8
|
+
var lazy_package_directory_loader_1 = require("./lazy-package-directory-loader");
|
|
9
|
+
Object.defineProperty(exports, "LazyPackageDirectoryLoader", { enumerable: true, get: function () { return lazy_package_directory_loader_1.LazyPackageDirectoryLoader; } });
|
|
10
|
+
var package_directory_loader_1 = require("./package-directory-loader");
|
|
11
|
+
Object.defineProperty(exports, "PackageDirectoryLoader", { enumerable: true, get: function () { return package_directory_loader_1.PackageDirectoryLoader; } });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { PackageDirectoryLoader } from "./package-directory-loader";
|
|
2
|
+
/**
|
|
3
|
+
* This loader extends PackageDirectoryLoader to load node and credentials lazily, if possible
|
|
4
|
+
*/
|
|
5
|
+
export declare class LazyPackageDirectoryLoader extends PackageDirectoryLoader {
|
|
6
|
+
loadAll(): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LazyPackageDirectoryLoader = void 0;
|
|
4
|
+
const package_directory_loader_1 = require("./package-directory-loader");
|
|
5
|
+
/**
|
|
6
|
+
* This loader extends PackageDirectoryLoader to load node and credentials lazily, if possible
|
|
7
|
+
*/
|
|
8
|
+
class LazyPackageDirectoryLoader extends package_directory_loader_1.PackageDirectoryLoader {
|
|
9
|
+
async loadAll() {
|
|
10
|
+
try {
|
|
11
|
+
this.known.nodes = await this.readJSON("dist/known/nodes.json");
|
|
12
|
+
this.known.credentials = await this.readJSON("dist/known/credentials.json");
|
|
13
|
+
this.types.nodes = await this.readJSON("dist/types/nodes.json");
|
|
14
|
+
this.types.credentials = await this.readJSON("dist/types/credentials.json");
|
|
15
|
+
if (this.includeNodes.length) {
|
|
16
|
+
const allowedNodes = {};
|
|
17
|
+
for (const nodeType of this.includeNodes) {
|
|
18
|
+
if (nodeType in this.known.nodes) {
|
|
19
|
+
allowedNodes[nodeType] = this.known.nodes[nodeType];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
this.known.nodes = allowedNodes;
|
|
23
|
+
this.types.nodes = this.types.nodes.filter((nodeType) => this.includeNodes.includes(nodeType.name));
|
|
24
|
+
}
|
|
25
|
+
if (this.excludeNodes.length) {
|
|
26
|
+
for (const nodeType of this.excludeNodes) {
|
|
27
|
+
delete this.known.nodes[nodeType];
|
|
28
|
+
}
|
|
29
|
+
this.types.nodes = this.types.nodes.filter((nodeType) => !this.excludeNodes.includes(nodeType.name));
|
|
30
|
+
}
|
|
31
|
+
console.debug(`Lazy-loading nodes and credentials from ${this.packageJson.name}`, {
|
|
32
|
+
nodes: this.types.nodes?.length ?? 0,
|
|
33
|
+
credentials: this.types.credentials?.length ?? 0,
|
|
34
|
+
});
|
|
35
|
+
this.isLazyLoaded = true;
|
|
36
|
+
return; // We can load nodes and credentials lazily now
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
console.debug("Can't enable lazy-loading");
|
|
40
|
+
await super.loadAll();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.LazyPackageDirectoryLoader = LazyPackageDirectoryLoader;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const loadClassInIsolation: <T>(filePath: string, className: string) => T;
|