@teleporthq/teleport-plugin-next-workflows 0.43.34 → 0.43.35
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__/global-workflows-handler-map-integrity.test.ts +85 -0
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/workflow-project-plugin.d.ts.map +1 -1
- package/dist/cjs/workflow-project-plugin.js +21 -1
- package/dist/cjs/workflow-project-plugin.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/workflow-project-plugin.d.ts.map +1 -1
- package/dist/esm/workflow-project-plugin.js +21 -1
- package/dist/esm/workflow-project-plugin.js.map +1 -1
- package/package.json +2 -2
- package/src/workflow-project-plugin.ts +21 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { NextWorkflowProjectPlugin } from '../src/workflow-project-plugin'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Regression: `generateGlobalWorkflowsHook` must never emit a `clientNodeHandlers`
|
|
5
|
+
* map entry that references a handler function it did not also define.
|
|
6
|
+
*
|
|
7
|
+
* Bug: `handlers` (the function definitions) was gated on `if (nodeRegistry[t])`,
|
|
8
|
+
* while `handlerEntries` (the map) mapped over EVERY collected client node type.
|
|
9
|
+
* A client-segment node whose type has no registry generator — e.g. a
|
|
10
|
+
* `general-comment`, or an `event-*` trigger node that got collected into the
|
|
11
|
+
* type set — therefore produced a map value `'general-comment': general_comment`
|
|
12
|
+
* with no `general_comment` defined anywhere in the file. That is a bare
|
|
13
|
+
* reference to an undefined identifier; it throws `ReferenceError: general_comment
|
|
14
|
+
* is not defined` when the module/hook is evaluated in production, crashing the
|
|
15
|
+
* Vercel build (global-workflows.js is pulled into the global client bundle for
|
|
16
|
+
* every page via `useGlobalWorkflows()`). The two lists must stay paired.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// A GLOBAL workflow (custom-triggered) whose client segment mixes a REGISTERED
|
|
20
|
+
// handler node (`state-update-local-state`) with an UNREGISTERED node type
|
|
21
|
+
// (`general-comment`, which has no entry in `nodeRegistry`). `general-comment`
|
|
22
|
+
// resolves to a client segment by default, so it lands in the handler type set.
|
|
23
|
+
const globalWorkflowWithUnregisteredNode = {
|
|
24
|
+
id: 'global-wf-unregistered',
|
|
25
|
+
trigger: { type: 'event-custom-triggered', config: { eventName: 'store-locations-loaded' } },
|
|
26
|
+
nodes: [
|
|
27
|
+
{
|
|
28
|
+
id: 'node-registered',
|
|
29
|
+
type: 'state-update-local-state',
|
|
30
|
+
config: { property: 'selectedPickupStore', value: '' },
|
|
31
|
+
stepNumber: 1,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'node-unregistered',
|
|
35
|
+
type: 'general-comment',
|
|
36
|
+
config: { text: 'a designer note that must not become a handler' },
|
|
37
|
+
stepNumber: 2,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
edges: [{ id: 'edge-1', source: 'node-registered', target: 'node-unregistered' }],
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function generateHook(): string {
|
|
44
|
+
const plugin = new NextWorkflowProjectPlugin()
|
|
45
|
+
// generateGlobalWorkflowsHook is private; call it directly for a unit test.
|
|
46
|
+
return (plugin as any).generateGlobalWorkflowsHook([globalWorkflowWithUnregisteredNode])
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
describe('generateGlobalWorkflowsHook — clientNodeHandlers map integrity', () => {
|
|
50
|
+
const code = generateHook()
|
|
51
|
+
|
|
52
|
+
it('defines a function for every identifier referenced in the handler map', () => {
|
|
53
|
+
// Match handler-map entries of the shape `'node-type': node_type` (the value
|
|
54
|
+
// identifier is the key with hyphens turned to underscores).
|
|
55
|
+
const entry = /['"]([a-z0-9]+(?:-[a-z0-9]+)+)['"]\s*:\s*([a-z0-9]+(?:_[a-z0-9]+)+)\b/g
|
|
56
|
+
const dangling: string[] = []
|
|
57
|
+
let m: RegExpExecArray | null = entry.exec(code)
|
|
58
|
+
while (m !== null) {
|
|
59
|
+
const [, key, ident] = m
|
|
60
|
+
if (key.replace(/-/g, '_') !== ident) {
|
|
61
|
+
m = entry.exec(code)
|
|
62
|
+
continue // not a handler-map entry
|
|
63
|
+
}
|
|
64
|
+
const isDefined = new RegExp(
|
|
65
|
+
`(?:async\\s+function|function|const|let|var)\\s+${ident}\\b`
|
|
66
|
+
).test(code)
|
|
67
|
+
if (!isDefined) {
|
|
68
|
+
dangling.push(ident)
|
|
69
|
+
}
|
|
70
|
+
m = entry.exec(code)
|
|
71
|
+
}
|
|
72
|
+
expect(dangling).toEqual([])
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('keeps the registered handler in the map with its definition', () => {
|
|
76
|
+
expect(code).toContain("'state-update-local-state': state_update_local_state")
|
|
77
|
+
expect(code).toMatch(/(?:async\s+)?function state_update_local_state\s*\(/)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('omits an unregistered node type (general-comment) entirely — no dangling reference', () => {
|
|
81
|
+
// Neither a definition nor a map entry for the unregistered type may appear.
|
|
82
|
+
expect(code).not.toContain('general_comment')
|
|
83
|
+
expect(code).not.toContain("'general-comment'")
|
|
84
|
+
})
|
|
85
|
+
})
|