@teleporthq/teleport-plugin-next-workflows 0.43.38 → 0.43.39
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/__tests__/resolve-handler-entry-name.test.ts +130 -0
- package/dist/cjs/nodes/types.d.ts.map +1 -1
- package/dist/cjs/nodes/types.js +51 -7
- package/dist/cjs/nodes/types.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/nodes/types.d.ts.map +1 -1
- package/dist/esm/nodes/types.js +51 -7
- package/dist/esm/nodes/types.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/nodes/types.ts +50 -7
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { resolveHandlerEntryName } from '../src/nodes/types'
|
|
2
|
+
import { nodeRegistry } from '../src/nodes'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Regression coverage for resolveHandlerEntryName, which exists because a
|
|
6
|
+
* handler's declared name at runtime can diverge from the
|
|
7
|
+
* `nodeType.replace(/-/g, '_')` convention name: when this package is bundled
|
|
8
|
+
* and minified by a consumer (e.g. teleport-gui's browser packer worker), the
|
|
9
|
+
* minifier freely renames a `handlerToString(fn)`-embedded function's
|
|
10
|
+
* declaration, since nothing in the bundle calls it by name — only the
|
|
11
|
+
* runtime `.toString()` read does, which is invisible to the minifier.
|
|
12
|
+
*
|
|
13
|
+
* Two real handlers exposed shapes the resolver initially got wrong:
|
|
14
|
+
* - payment-charge-user.ts: entry declared FIRST, its own helpers after
|
|
15
|
+
* (`handlerToString(payment_charge_user) + '\n' + chargeWithStripe.toString() + ...`).
|
|
16
|
+
* - ai-custom-prompt.ts: shared AI-provider utils declared BEFORE the
|
|
17
|
+
* entry, each wrapped in a `wrapWithGuard`-style re-declaration guard
|
|
18
|
+
* (`var X = typeof X !== 'undefined' ? X : function Y() {...};` — a
|
|
19
|
+
* function EXPRESSION embedded in a ternary, not a statement-level
|
|
20
|
+
* declaration) — this crashed a real publish with "Could not resolve the
|
|
21
|
+
* entry function for workflow node type "ai-custom-prompt"".
|
|
22
|
+
* A naive "first" or "last" positional heuristic breaks one of these two.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
function evalEntryWrapper(source: string, entryName: string): unknown {
|
|
26
|
+
return new Function(`${source}\nreturn ${entryName};`)()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe('resolveHandlerEntryName', () => {
|
|
30
|
+
it('returns the convention name when the source declares it directly', () => {
|
|
31
|
+
const source = `async function my_node_type(config, context) { return {}; }`
|
|
32
|
+
expect(resolveHandlerEntryName(source, 'my-node-type')).toBe('my_node_type')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('falls back to the actual declared name when the entry was renamed (single function)', () => {
|
|
36
|
+
const source = `async function e(config, context) { return {}; }`
|
|
37
|
+
expect(resolveHandlerEntryName(source, 'my-node-type')).toBe('e')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('finds a renamed entry declared FIRST, before its own helpers (payment-charge-user shape)', () => {
|
|
41
|
+
const source = `
|
|
42
|
+
async function zzz(config, context) {
|
|
43
|
+
return helper_one(config) + helper_two(context);
|
|
44
|
+
}
|
|
45
|
+
async function helper_one(config) { return config.x; }
|
|
46
|
+
async function helper_two(context) { return context.y; }
|
|
47
|
+
`
|
|
48
|
+
const resolved = resolveHandlerEntryName(source, 'payment-charge-user')
|
|
49
|
+
expect(resolved).toBe('zzz')
|
|
50
|
+
expect(typeof evalEntryWrapper(source, resolved)).toBe('function')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('finds a renamed entry declared LAST, after ternary-guarded shared utils (ai-custom-prompt shape)', () => {
|
|
54
|
+
const source = `
|
|
55
|
+
var util_one = typeof util_one !== 'undefined' ? util_one : function util_one(val) { return val; };
|
|
56
|
+
var util_two = typeof util_two !== 'undefined' ? util_two : function util_two(val) { return val; };
|
|
57
|
+
|
|
58
|
+
async function zzz(config, context, streamCallback) {
|
|
59
|
+
return util_one(config) + util_two(context);
|
|
60
|
+
}
|
|
61
|
+
`
|
|
62
|
+
const resolved = resolveHandlerEntryName(source, 'ai-custom-prompt')
|
|
63
|
+
expect(resolved).toBe('zzz')
|
|
64
|
+
expect(typeof evalEntryWrapper(source, resolved)).toBe('function')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('prefers the entry-point arity (2-3 params) over a same-position helper with a different arity', () => {
|
|
68
|
+
// A helper positioned BEFORE the (renamed) entry, but with an arity that
|
|
69
|
+
// could never be a real handler entry point (1 param) — must not win.
|
|
70
|
+
const source = `
|
|
71
|
+
function one_param_helper(x) { return x; }
|
|
72
|
+
async function zzz(config, context) { return one_param_helper(config); }
|
|
73
|
+
`
|
|
74
|
+
expect(resolveHandlerEntryName(source, 'my-node-type')).toBe('zzz')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('throws a clear error when no declaration can be found at all', () => {
|
|
78
|
+
expect(() => resolveHandlerEntryName('var x = 1;', 'my-node-type')).toThrow(
|
|
79
|
+
/Could not resolve the entry function/
|
|
80
|
+
)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
// Full-registry regression: every node type's generateHandler()/
|
|
84
|
+
// generateServerHandler() output must resolve to a real, callable function
|
|
85
|
+
// both normally AND after its entry function's declared name is renamed
|
|
86
|
+
// (simulating what a minifier does) — proves the resolver's fallback logic
|
|
87
|
+
// holds for every handler shape actually registered, not just hand-picked
|
|
88
|
+
// examples.
|
|
89
|
+
describe('every registered node type', () => {
|
|
90
|
+
const nodeTypes = Object.keys(nodeRegistry)
|
|
91
|
+
|
|
92
|
+
it.each(nodeTypes)(
|
|
93
|
+
'%s: generateHandler resolves normally and after entry rename',
|
|
94
|
+
(nodeType) => {
|
|
95
|
+
const gen = nodeRegistry[nodeType]
|
|
96
|
+
const source = gen.generateHandler().trim()
|
|
97
|
+
const conventionName = nodeType.replace(/-/g, '_')
|
|
98
|
+
|
|
99
|
+
const resolvedNormal = resolveHandlerEntryName(source, nodeType)
|
|
100
|
+
expect(typeof evalEntryWrapper(source, resolvedNormal)).toBe('function')
|
|
101
|
+
|
|
102
|
+
if (source.includes(conventionName)) {
|
|
103
|
+
const renamed = source.replace(new RegExp(`\\b${conventionName}\\b`, 'g'), 'zzz_renamed')
|
|
104
|
+
const resolvedRenamed = resolveHandlerEntryName(renamed, nodeType)
|
|
105
|
+
expect(resolvedRenamed).toBe('zzz_renamed')
|
|
106
|
+
expect(typeof evalEntryWrapper(renamed, resolvedRenamed)).toBe('function')
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
it.each(nodeTypes.filter((t) => nodeRegistry[t].generateServerHandler))(
|
|
112
|
+
'%s: generateServerHandler resolves normally and after entry rename',
|
|
113
|
+
(nodeType) => {
|
|
114
|
+
const gen = nodeRegistry[nodeType]
|
|
115
|
+
const source = gen.generateServerHandler!().trim()
|
|
116
|
+
const conventionName = nodeType.replace(/-/g, '_')
|
|
117
|
+
|
|
118
|
+
const resolvedNormal = resolveHandlerEntryName(source, nodeType)
|
|
119
|
+
expect(typeof evalEntryWrapper(source, resolvedNormal)).toBe('function')
|
|
120
|
+
|
|
121
|
+
if (source.includes(conventionName)) {
|
|
122
|
+
const renamed = source.replace(new RegExp(`\\b${conventionName}\\b`, 'g'), 'zzz_renamed')
|
|
123
|
+
const resolvedRenamed = resolveHandlerEntryName(renamed, nodeType)
|
|
124
|
+
expect(resolvedRenamed).toBe('zzz_renamed')
|
|
125
|
+
expect(typeof evalEntryWrapper(renamed, resolvedRenamed)).toBe('function')
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
})
|
|
130
|
+
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/nodes/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE/F,wBAAgB,eAAe,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAErD;AAoBD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/nodes/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAE/F,wBAAgB,eAAe,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAErD;AAoBD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CA+DhF;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAA;IAC/C,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,eAAe,IAAI,MAAM,CAAA;IACzB,qBAAqB,CAAC,IAAI,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,2BAA4B,SAAQ,oBAAoB;IACvE,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB"}
|
package/dist/cjs/nodes/types.js
CHANGED
|
@@ -29,13 +29,57 @@ function resolveHandlerEntryName(source, nodeType) {
|
|
|
29
29
|
if (conventionNameUsed) {
|
|
30
30
|
return conventionName;
|
|
31
31
|
}
|
|
32
|
-
// `source` came from `handlerToString(fn)` on a real,
|
|
33
|
-
// function
|
|
34
|
-
//
|
|
35
|
-
// the
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
// `source` came from `handlerToString(fn)`/`fn.toString()` on a real,
|
|
33
|
+
// possibly-minified function, and may be concatenated with OTHER
|
|
34
|
+
// `.toString()`'d functions:
|
|
35
|
+
// - payment-charge-user.ts puts the entry FIRST, its own helpers after
|
|
36
|
+
// (`handlerToString(payment_charge_user) + '\n' + chargeWithStripe.toString() + ...`).
|
|
37
|
+
// - ai-custom-prompt.ts puts shared AI-provider utils BEFORE the entry
|
|
38
|
+
// (`generateAIProviderUtils() + '\n\n' + ai_custom_prompt.toString()`),
|
|
39
|
+
// where each util is `wrapWithGuard`-wrapped: `var X = typeof X !==
|
|
40
|
+
// 'undefined' ? X : function Y() {...};` — a function EXPRESSION
|
|
41
|
+
// embedded in a ternary, not a statement-level declaration.
|
|
42
|
+
// So the entry is not reliably first or last by position across handlers,
|
|
43
|
+
// and helper functions can outnumber (or precede) the entry. What IS
|
|
44
|
+
// reliable: every real entry point has exactly the HandlerFn signature —
|
|
45
|
+
// 2 params (config, context) or 3 (config, context, streamCallback) — by
|
|
46
|
+
// contract, while a handler's OWN internal helpers only coincidentally
|
|
47
|
+
// share that arity (e.g. general-rate-limiter's __checkRateLimit takes 3
|
|
48
|
+
// params too). So: collect every statement-level function declaration
|
|
49
|
+
// (skipping ternary-embedded expressions like wrapWithGuard's), and prefer
|
|
50
|
+
// an exactly-2-param candidate, then an exactly-3-param one, falling back
|
|
51
|
+
// to positional order only if nothing matches the entry-point arity.
|
|
52
|
+
const declPattern = /(?:async\s+)?function\s+([A-Za-z0-9_$]+)\s*\(([^)]*)\)/g;
|
|
53
|
+
const candidates = [];
|
|
54
|
+
let twoParamCandidate;
|
|
55
|
+
let threeParamCandidate;
|
|
56
|
+
let declMatch = declPattern.exec(source);
|
|
57
|
+
while (declMatch !== null) {
|
|
58
|
+
const precedingNonSpace = source.slice(0, declMatch.index).trimEnd().slice(-1);
|
|
59
|
+
if (precedingNonSpace === ':' || precedingNonSpace === '?') {
|
|
60
|
+
declMatch = declPattern.exec(source);
|
|
61
|
+
continue; // function EXPRESSION embedded in a ternary (e.g. wrapWithGuard's re-declaration guard)
|
|
62
|
+
}
|
|
63
|
+
const name = declMatch[1];
|
|
64
|
+
candidates.push(name);
|
|
65
|
+
const params = declMatch[2].trim();
|
|
66
|
+
const paramCount = params === '' ? 0 : params.split(',').length;
|
|
67
|
+
if (paramCount === 2 && twoParamCandidate === undefined) {
|
|
68
|
+
twoParamCandidate = name;
|
|
69
|
+
}
|
|
70
|
+
else if (paramCount === 3 && threeParamCandidate === undefined) {
|
|
71
|
+
threeParamCandidate = name;
|
|
72
|
+
}
|
|
73
|
+
declMatch = declPattern.exec(source);
|
|
74
|
+
}
|
|
75
|
+
if (twoParamCandidate !== undefined) {
|
|
76
|
+
return twoParamCandidate;
|
|
77
|
+
}
|
|
78
|
+
if (threeParamCandidate !== undefined) {
|
|
79
|
+
return threeParamCandidate;
|
|
80
|
+
}
|
|
81
|
+
if (candidates.length > 0) {
|
|
82
|
+
return candidates[0];
|
|
39
83
|
}
|
|
40
84
|
throw new Error(`Could not resolve the entry function for workflow node type "${nodeType}" — ` +
|
|
41
85
|
`expected a "${conventionName}" declaration or a single toString()'d function, found neither.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/nodes/types.ts"],"names":[],"mappings":";;;AAEA,SAAgB,eAAe,CAAC,EAAa;IAC3C,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAA;AACtB,CAAC;AAFD,0CAEC;AAED,4EAA4E;AAC5E,sDAAsD;AACtD,iDAAiD;AACjD,EAAE;AACF,qEAAqE;AACrE,0EAA0E;AAC1E,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,4EAA4E;AAC5E,wEAAwE;AACxE,gEAAgE;AAChE,yDAAyD;AACzD,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,2EAA2E;AAC3E,4EAA4E;AAC5E,SAAgB,uBAAuB,CAAC,MAAc,EAAE,QAAgB;IACtE,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAClD,MAAM,kBAAkB,GAAG,IAAI,MAAM,CAAC,gBAAgB,cAAc,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC3F,IAAI,kBAAkB,EAAE;QACtB,OAAO,cAAc,CAAA;KACtB;IAED,wEAAwE;IACxE,
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/nodes/types.ts"],"names":[],"mappings":"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"}
|