n8n-nodes-mautic-advanced 1.3.7 → 1.3.10
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.
|
@@ -3,32 +3,224 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.runtimeZod = exports.RuntimeDynamicStructuredTool = void 0;
|
|
4
4
|
// nodes/MauticAdvanced/ai-tools/runtime.ts
|
|
5
5
|
const module_1 = require("module");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Runtime resolution of `zod` and `@langchain/core`'s DynamicStructuredTool.
|
|
8
|
+
*
|
|
9
|
+
* IMPORTANT: resolution must NEVER run at module-import time. n8n's
|
|
10
|
+
* node-directory-loader requires every node file in this package (including
|
|
11
|
+
* this one) purely to register node metadata, long before any workflow
|
|
12
|
+
* executes — and it aborts loading the ENTIRE package if any one file throws
|
|
13
|
+
* while being required. Doing filesystem resolution here at import time is
|
|
14
|
+
* exactly what took down the plain, non-AI `mauticAdvanced` node and its
|
|
15
|
+
* trigger under pnpm-strict-isolated installs (issue #2). Resolution is
|
|
16
|
+
* therefore deferred to first actual use inside the Proxy traps below, which
|
|
17
|
+
* only fire when a connected AI tool is invoked at workflow-execution time.
|
|
18
|
+
*
|
|
19
|
+
* By execution time n8n's own Agent/MCP Trigger machinery has already loaded
|
|
20
|
+
* `@n8n/n8n-nodes-langchain` (and therefore zod and @langchain/core) into the
|
|
21
|
+
* process-global require.cache. We resolve the SAME module identity n8n uses —
|
|
22
|
+
* the copy its `normalizeToolSchema` runs `instanceof ZodType` / `instanceof
|
|
23
|
+
* ZodType`-style checks against — by two strategies, in order:
|
|
24
|
+
*
|
|
25
|
+
* 1. `require.main` — n8n's own entry point. For a correctly-installed
|
|
26
|
+
* (non-isolated) host this lands on n8n's top-level copies directly.
|
|
27
|
+
* Guarded for `require.main` being undefined (ESM launch, worker_threads /
|
|
28
|
+
* queue-mode workers). We do NOT fall back to `__filename`: anchoring at
|
|
29
|
+
* this file would resolve THIS package's own bundled copy, which is the
|
|
30
|
+
* wrong module identity and fails n8n's `instanceof` checks silently.
|
|
31
|
+
*
|
|
32
|
+
* 2. An n8n-owned-tree anchor — a module already resident in require.cache
|
|
33
|
+
* whose path belongs to a package only n8n owns and community nodes never
|
|
34
|
+
* bundle. We `createRequire()` the dependency FROM that module's path, so
|
|
35
|
+
* the resolved copy is tied to n8n's tree by identity — independent of
|
|
36
|
+
* cache iteration order and of pnpm virtual-store path naming.
|
|
37
|
+
*
|
|
38
|
+
* If neither strategy resolves, we FAIL CLEAN (throw a diagnostic). We do NOT
|
|
39
|
+
* scan require.cache for a bare `zod` / `@langchain/core` and guess which copy
|
|
40
|
+
* is n8n's: under pnpm strict-isolated installs the cache key is the flat
|
|
41
|
+
* virtual-store realpath (`.../.pnpm/zod@3.x.x/node_modules/zod/...`) which does
|
|
42
|
+
* not encode the dependent package, so another installed community node's
|
|
43
|
+
* bundled copy can win the scan and yield a wrong-instance `ZodType` that
|
|
44
|
+
* n8n's `instanceof` check drops silently (issue #4). Returning nothing and
|
|
45
|
+
* throwing is safer than returning a possibly-wrong copy.
|
|
46
|
+
*/
|
|
47
|
+
// n8n-owned anchor packages, in priority order. `@n8n/n8n-nodes-langchain` is
|
|
48
|
+
// always loaded at execution time and is the code that runs the instanceof
|
|
49
|
+
// checks, so resolving from it guarantees identical module identity.
|
|
50
|
+
const N8N_ANCHOR_PACKAGES = [
|
|
51
|
+
{ name: '@n8n/n8n-nodes-langchain', pattern: /[\\/]@n8n[\\/]n8n-nodes-langchain[\\/]/ },
|
|
52
|
+
{ name: '@langchain/classic', pattern: /[\\/]@langchain[\\/]classic[\\/]/ },
|
|
53
|
+
{ name: 'n8n-workflow', pattern: /[\\/]n8n-workflow[\\/]/ },
|
|
54
|
+
{ name: 'n8n-core', pattern: /[\\/]n8n-core[\\/]/ },
|
|
12
55
|
];
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
for
|
|
56
|
+
let _anchorDiagnostic = null;
|
|
57
|
+
/**
|
|
58
|
+
* Yields a createRequire() for EACH n8n-owned anchor package currently resident
|
|
59
|
+
* in Node's process-global module cache, in the priority order of
|
|
60
|
+
* N8N_ANCHOR_PACKAGES. Must be called lazily (not at module load) — n8n requires
|
|
61
|
+
* node files for registration before any workflow runs, i.e. before the anchor
|
|
62
|
+
* packages are necessarily resident in cache.
|
|
63
|
+
*
|
|
64
|
+
* IMPORTANT: this yields ALL available anchors rather than memoizing the first
|
|
65
|
+
* one found. Different anchors resolve different dependencies: `n8n-workflow` /
|
|
66
|
+
* `n8n-core` are imported by this package at registration time, so they are
|
|
67
|
+
* resident FIRST — but they can resolve `zod` and NOT `@langchain/core/tools`.
|
|
68
|
+
* Memoizing `n8n-workflow` as THE anchor would permanently starve
|
|
69
|
+
* DynamicStructuredTool resolution even after `@langchain/*` later loads. So the
|
|
70
|
+
* caller tries each anchor against the actual dependency and memoizes only at
|
|
71
|
+
* the dependency level (on success). Re-scanning the cache each unresolved call
|
|
72
|
+
* is cheap and only happens until the dependency resolves.
|
|
73
|
+
*/
|
|
74
|
+
function* iterN8nAnchorRequires() {
|
|
75
|
+
let cache;
|
|
19
76
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
77
|
+
// require.cache is the documented CommonJS alias for Module._cache, available
|
|
78
|
+
// directly in CJS module scope (this file compiles to CJS via tsc).
|
|
79
|
+
cache = require.cache;
|
|
23
80
|
}
|
|
24
|
-
catch (
|
|
25
|
-
|
|
81
|
+
catch (_e) {
|
|
82
|
+
// best-effort — require.cache introspection is not guaranteed across Node versions
|
|
83
|
+
cache = undefined;
|
|
26
84
|
}
|
|
85
|
+
if (!cache) {
|
|
86
|
+
_anchorDiagnostic = 'require.cache unavailable';
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const keys = Object.keys(cache);
|
|
90
|
+
const available = [];
|
|
91
|
+
for (const anchor of N8N_ANCHOR_PACKAGES) {
|
|
92
|
+
const key = keys.find((k) => anchor.pattern.test(k));
|
|
93
|
+
if (!key)
|
|
94
|
+
continue;
|
|
95
|
+
try {
|
|
96
|
+
const req = (0, module_1.createRequire)(key);
|
|
97
|
+
available.push(anchor.name);
|
|
98
|
+
yield { req, source: `anchor ${anchor.name}` };
|
|
99
|
+
}
|
|
100
|
+
catch (_e) {
|
|
101
|
+
// createRequire failed for this anchor — try the next
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
_anchorDiagnostic = available.length
|
|
105
|
+
? `anchors available: ${available.join(', ')}`
|
|
106
|
+
: `no n8n-owned anchor resident in require.cache (tried ${N8N_ANCHOR_PACKAGES.map((a) => a.name).join(', ')})`;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Yields candidate requires in resolution priority order: require.main first
|
|
110
|
+
* (guarded for undefined), then EACH n8n-owned-tree anchor. Symmetric for every
|
|
111
|
+
* dependency — no bare-cache scan, no self-exclusion. The caller must try the
|
|
112
|
+
* requested dependency against each yielded require and stop at the first that
|
|
113
|
+
* loads it.
|
|
114
|
+
*/
|
|
115
|
+
function* candidateRequires() {
|
|
116
|
+
if (require.main?.filename) {
|
|
117
|
+
try {
|
|
118
|
+
yield { req: (0, module_1.createRequire)(require.main.filename), source: 'require.main' };
|
|
119
|
+
}
|
|
120
|
+
catch (_e) {
|
|
121
|
+
// require.main resolution unavailable — fall through to anchors
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
yield* iterN8nAnchorRequires();
|
|
27
125
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
126
|
+
let _RuntimeDynamicStructuredTool;
|
|
127
|
+
let _runtimeZod;
|
|
128
|
+
let _langchainLoadError = null;
|
|
129
|
+
let _langchainDiagnostic = null;
|
|
130
|
+
let _zodLoadError = null;
|
|
131
|
+
let _zodDiagnostic = null;
|
|
132
|
+
function resolveDynamicStructuredTool() {
|
|
133
|
+
if (_RuntimeDynamicStructuredTool)
|
|
134
|
+
return _RuntimeDynamicStructuredTool;
|
|
135
|
+
const attempts = [];
|
|
136
|
+
for (const { req, source } of candidateRequires()) {
|
|
137
|
+
try {
|
|
138
|
+
const coreTools = req('@langchain/core/tools');
|
|
139
|
+
if (typeof coreTools?.['DynamicStructuredTool'] === 'function') {
|
|
140
|
+
_RuntimeDynamicStructuredTool = coreTools['DynamicStructuredTool'];
|
|
141
|
+
_langchainDiagnostic = `resolved DynamicStructuredTool via ${source}`;
|
|
142
|
+
_langchainLoadError = null;
|
|
143
|
+
return _RuntimeDynamicStructuredTool;
|
|
144
|
+
}
|
|
145
|
+
attempts.push(`${source}: @langchain/core/tools lacked DynamicStructuredTool`);
|
|
146
|
+
}
|
|
147
|
+
catch (e) {
|
|
148
|
+
attempts.push(`${source}: ${e.message}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
_langchainLoadError = attempts.length
|
|
152
|
+
? attempts.join('; ')
|
|
153
|
+
: 'no n8n-owned resolution source available (require.main undefined, no anchor in cache)';
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
function resolveZod() {
|
|
157
|
+
if (_runtimeZod)
|
|
158
|
+
return _runtimeZod;
|
|
159
|
+
const attempts = [];
|
|
160
|
+
for (const { req, source } of candidateRequires()) {
|
|
161
|
+
try {
|
|
162
|
+
const z = req('zod');
|
|
163
|
+
// Validate the exports look like zod via `ZodType` (the class n8n's
|
|
164
|
+
// normalizeToolSchema does `instanceof` against — the meaningful correctness
|
|
165
|
+
// signal) plus the `object` factory our schema-generator calls.
|
|
166
|
+
if (typeof z?.['ZodType'] === 'function' && typeof z?.['object'] === 'function') {
|
|
167
|
+
_runtimeZod = z;
|
|
168
|
+
_zodDiagnostic = `resolved zod via ${source}`;
|
|
169
|
+
_zodLoadError = null;
|
|
170
|
+
return _runtimeZod;
|
|
171
|
+
}
|
|
172
|
+
attempts.push(`${source}: module did not look like zod`);
|
|
173
|
+
}
|
|
174
|
+
catch (e) {
|
|
175
|
+
attempts.push(`${source}: ${e.message}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
_zodLoadError = attempts.length
|
|
179
|
+
? attempts.join('; ')
|
|
180
|
+
: 'no n8n-owned resolution source available (require.main undefined, no anchor in cache)';
|
|
181
|
+
return undefined;
|
|
31
182
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
183
|
+
// IMPORTANT: Proxy target MUST be `function () {}`, not `{}`.
|
|
184
|
+
// ECMAScript spec §10.5.13: a Proxy only has [[Construct]] if its target does.
|
|
185
|
+
// Plain objects lack [[Construct]], so `new Proxy({}, ...)` throws
|
|
186
|
+
// "is not a constructor" before the construct trap ever fires.
|
|
187
|
+
exports.RuntimeDynamicStructuredTool = new Proxy(function () { }, {
|
|
188
|
+
construct(_target, args) {
|
|
189
|
+
const ctor = resolveDynamicStructuredTool();
|
|
190
|
+
if (!ctor) {
|
|
191
|
+
throw new Error(`[MauticAdvancedAiTools] Could not resolve LangChain's DynamicStructuredTool ` +
|
|
192
|
+
`via require.main or an n8n-owned require.cache anchor. ` +
|
|
193
|
+
`Ensure @n8n/n8n-nodes-langchain is installed in n8n's node_modules.` +
|
|
194
|
+
(_anchorDiagnostic ? ` Anchor: ${_anchorDiagnostic}.` : '') +
|
|
195
|
+
(_langchainDiagnostic ? ` ${_langchainDiagnostic}.` : '') +
|
|
196
|
+
(_langchainLoadError ? ` Load error: ${_langchainLoadError}` : ''));
|
|
197
|
+
}
|
|
198
|
+
return new ctor(...args);
|
|
199
|
+
},
|
|
200
|
+
get(_target, prop) {
|
|
201
|
+
const ctor = resolveDynamicStructuredTool();
|
|
202
|
+
if (ctor) {
|
|
203
|
+
return ctor[prop];
|
|
204
|
+
}
|
|
205
|
+
return undefined;
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
exports.runtimeZod = new Proxy({}, {
|
|
209
|
+
get(_target, prop) {
|
|
210
|
+
// Guard: frameworks probe Symbol.toPrimitive, Symbol.toStringTag, .then
|
|
211
|
+
// (Promise thenable), and .constructor. Throwing on these causes
|
|
212
|
+
// misleading errors during structural inspection.
|
|
213
|
+
if (typeof prop === 'symbol' || prop === 'then' || prop === 'constructor')
|
|
214
|
+
return undefined;
|
|
215
|
+
const z = resolveZod();
|
|
216
|
+
if (!z) {
|
|
217
|
+
throw new Error(`[MauticAdvancedAiTools] Could not resolve zod (accessing .${String(prop)}) ` +
|
|
218
|
+
`via require.main or an n8n-owned require.cache anchor. ` +
|
|
219
|
+
`Ensure @n8n/n8n-nodes-langchain is installed in n8n's node_modules.` +
|
|
220
|
+
(_anchorDiagnostic ? ` Anchor: ${_anchorDiagnostic}.` : '') +
|
|
221
|
+
(_zodDiagnostic ? ` ${_zodDiagnostic}.` : '') +
|
|
222
|
+
(_zodLoadError ? ` Load error: ${_zodLoadError}` : ''));
|
|
223
|
+
}
|
|
224
|
+
return z[prop];
|
|
225
|
+
},
|
|
226
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-mautic-advanced",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.10",
|
|
4
4
|
"description": "Enhanced n8n node for Mautic with comprehensive API coverage including tags, campaigns, categories, and advanced contact management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n",
|
|
@@ -72,5 +72,13 @@
|
|
|
72
72
|
"@types/change-case": "^0.0.30",
|
|
73
73
|
"change-case": "^5.4.4",
|
|
74
74
|
"zod": "^3.22.0"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"@langchain/core": "*"
|
|
78
|
+
},
|
|
79
|
+
"peerDependenciesMeta": {
|
|
80
|
+
"@langchain/core": {
|
|
81
|
+
"optional": true
|
|
82
|
+
}
|
|
75
83
|
}
|
|
76
84
|
}
|