@teleporthq/teleport-plugin-next-workflows 0.43.48 → 0.43.49

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.
Files changed (33) hide show
  1. package/__tests__/data-node-not-awaited.test.ts +12 -1
  2. package/__tests__/ecommerce-get-settings-client.test.ts +383 -0
  3. package/dist/cjs/executor-generator.d.ts.map +1 -1
  4. package/dist/cjs/executor-generator.js +12 -1
  5. package/dist/cjs/executor-generator.js.map +1 -1
  6. package/dist/cjs/nodes/account/account-get-current.d.ts.map +1 -1
  7. package/dist/cjs/nodes/account/account-get-current.js +27 -7
  8. package/dist/cjs/nodes/account/account-get-current.js.map +1 -1
  9. package/dist/cjs/nodes/ecommerce/ecommerce-get-settings.d.ts.map +1 -1
  10. package/dist/cjs/nodes/ecommerce/ecommerce-get-settings.js +59 -1
  11. package/dist/cjs/nodes/ecommerce/ecommerce-get-settings.js.map +1 -1
  12. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  13. package/dist/cjs/workflow-project-plugin.d.ts.map +1 -1
  14. package/dist/cjs/workflow-project-plugin.js +11 -1
  15. package/dist/cjs/workflow-project-plugin.js.map +1 -1
  16. package/dist/esm/executor-generator.d.ts.map +1 -1
  17. package/dist/esm/executor-generator.js +12 -1
  18. package/dist/esm/executor-generator.js.map +1 -1
  19. package/dist/esm/nodes/account/account-get-current.d.ts.map +1 -1
  20. package/dist/esm/nodes/account/account-get-current.js +27 -7
  21. package/dist/esm/nodes/account/account-get-current.js.map +1 -1
  22. package/dist/esm/nodes/ecommerce/ecommerce-get-settings.d.ts.map +1 -1
  23. package/dist/esm/nodes/ecommerce/ecommerce-get-settings.js +59 -1
  24. package/dist/esm/nodes/ecommerce/ecommerce-get-settings.js.map +1 -1
  25. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  26. package/dist/esm/workflow-project-plugin.d.ts.map +1 -1
  27. package/dist/esm/workflow-project-plugin.js +11 -1
  28. package/dist/esm/workflow-project-plugin.js.map +1 -1
  29. package/package.json +2 -2
  30. package/src/executor-generator.ts +12 -1
  31. package/src/nodes/account/account-get-current.ts +27 -8
  32. package/src/nodes/ecommerce/ecommerce-get-settings.ts +62 -3
  33. package/src/workflow-project-plugin.ts +11 -1
@@ -476,12 +476,23 @@ describe('generated client runtime', () => {
476
476
  const client = generateClientRuntimeCode()
477
477
 
478
478
  it('dispatches an all-fire-and-forget segment without awaiting the round trip', () => {
479
- expect(client).toContain('if (seg.fireAndForget) {')
479
+ expect(client).toContain('if (segIsFireAndForget) {')
480
480
  expect(client).toContain('callServerSegment(ffUrl, context).catch(')
481
481
  // The nodes still get their null entries so downstream reads are defined.
482
482
  expect(client).toContain('context[seg.nodes[ffi].id] = null;')
483
483
  })
484
484
 
485
+ it('upgrades a mixed segment to fire-and-forget when the awaited nodes were branch-skipped', () => {
486
+ // Static flag first, then the dynamic check over the LIVE (non-skipped)
487
+ // nodes — a mixed segment whose awaited nodes sit on a branch that was
488
+ // not taken has only fire-and-forget work left to do.
489
+ expect(client).toContain(
490
+ 'var segLiveNodes = seg.nodes.filter(function(n) { return !(context.__skippedNodes && context.__skippedNodes[n.id]); });'
491
+ )
492
+ expect(client).toContain('var segIsFireAndForget = seg.fireAndForget ||')
493
+ expect(client).toContain('segLiveNodes.every(utils.isFireAndForgetNode)')
494
+ })
495
+
485
496
  it('keeps awaiting a normal server segment', () => {
486
497
  expect(client).toContain('const serverResults = await callServerSegment(url, context);')
487
498
  })
@@ -0,0 +1,383 @@
1
+ import { splitIntoSegments, generateSharedRuntimeUtilsCode } from '../src'
2
+ import { nodeRegistry } from '../src/nodes'
3
+ import { NextWorkflowProjectPlugin } from '../src/workflow-project-plugin'
4
+ import { UIDLWorkflow } from '@teleporthq/teleport-types'
5
+
6
+ // The /api/ecommerce/settings route returns a literal baked at generation time
7
+ // — within a deployment it can never say anything else. Classifying the
8
+ // `ecommerce-get-settings` node as a SERVER node therefore bought nothing and
9
+ // cost a full blocking round trip per click, PLUS it fragmented the
10
+ // surrounding workflow into extra server segments (one round trip each).
11
+ //
12
+ // The contract this file pins down:
13
+ // 1. the node is client-classified, so the segment splitter never mints a
14
+ // server segment for it;
15
+ // 2. the client handler resolves from the baked window global first, then a
16
+ // memoized fetch, then the route;
17
+ // 3. cron/webhook routes (which execute every node server-side, with no
18
+ // window) still get a real server implementation via
19
+ // generateServerHandler — never the client-only stub;
20
+ // 4. the add-to-cart / cart-increment workflow shapes collapse to exactly
21
+ // ONE server segment: the product data-select.
22
+
23
+ describe('ecommerce-get-settings node classification', () => {
24
+ const generator = nodeRegistry['ecommerce-get-settings']
25
+
26
+ it('is client-classified', () => {
27
+ expect(generator.executionEnv).toBe('client')
28
+ })
29
+
30
+ it('client handler reads the baked global, memoizes the fetch fallback', () => {
31
+ const source = generator.generateHandler()
32
+ expect(source).toContain('__teleportEcommerceSettings')
33
+ expect(source).toContain('__teleportEcommerceSettingsFetched')
34
+ expect(source).toContain('/api/ecommerce/settings')
35
+ })
36
+
37
+ it('keeps a real server implementation for cron/webhook contexts', () => {
38
+ expect(generator.generateServerHandler).toBeDefined()
39
+ const source = generator.generateServerHandler!()
40
+ expect(source).toContain('/api/ecommerce/settings')
41
+ expect(source).not.toContain('window')
42
+ })
43
+ })
44
+
45
+ describe('ecommerce-get-settings client handler behaviour', () => {
46
+ const buildHandler = () => {
47
+ const source = nodeRegistry['ecommerce-get-settings'].generateHandler()
48
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
49
+ return new Function(`return (${source})`)() as (
50
+ config: unknown,
51
+ context: Record<string, unknown>
52
+ ) => Promise<Record<string, unknown>>
53
+ }
54
+
55
+ const globalAny = global as unknown as Record<string, unknown>
56
+
57
+ afterEach(() => {
58
+ delete globalAny.window
59
+ delete globalAny.fetch
60
+ })
61
+
62
+ it('returns the baked global without fetching', async () => {
63
+ const baked = { guestCheckout: true, stockManagement: true, maxQuantityPerProduct: null }
64
+ globalAny.window = { __teleportEcommerceSettings: baked }
65
+ globalAny.fetch = jest.fn()
66
+
67
+ const result = await buildHandler()({}, {})
68
+ expect(result).toBe(baked)
69
+ expect(globalAny.fetch).not.toHaveBeenCalled()
70
+ })
71
+
72
+ it('falls back to the route and memoizes a successful response', async () => {
73
+ const payload = { guestCheckout: false, stockManagement: true }
74
+ globalAny.window = {}
75
+ const fetchMock = jest.fn().mockResolvedValue({
76
+ ok: true,
77
+ json: async () => payload,
78
+ })
79
+ globalAny.fetch = fetchMock
80
+
81
+ const handler = buildHandler()
82
+ const first = await handler({}, {})
83
+ expect(first).toEqual(payload)
84
+ expect(fetchMock).toHaveBeenCalledTimes(1)
85
+
86
+ // Second call resolves from the memo — the route is immutable within a
87
+ // deployment, so this can never serve stale data.
88
+ const second = await handler({}, {})
89
+ expect(second).toEqual(payload)
90
+ expect(fetchMock).toHaveBeenCalledTimes(1)
91
+ })
92
+
93
+ it('does not memoize a failed response', async () => {
94
+ globalAny.window = {}
95
+ const fetchMock = jest
96
+ .fn()
97
+ .mockResolvedValueOnce({ ok: false })
98
+ .mockResolvedValueOnce({ ok: true, json: async () => ({ guestCheckout: true }) })
99
+ globalAny.fetch = fetchMock
100
+
101
+ const handler = buildHandler()
102
+ const first = await handler({}, {})
103
+ expect(first).toEqual({ error: 'Failed to load e-commerce settings' })
104
+
105
+ const second = await handler({}, {})
106
+ expect(second).toEqual({ guestCheckout: true })
107
+ expect(fetchMock).toHaveBeenCalledTimes(2)
108
+ })
109
+ })
110
+
111
+ describe('segment shapes around a client settings node', () => {
112
+ const node = (id: string, type: string, config: Record<string, unknown> = {}) => ({
113
+ id,
114
+ type,
115
+ label: id,
116
+ config,
117
+ stepNumber: 0,
118
+ })
119
+ const edge = (source: string, target: string, sourceHandle?: string) => ({
120
+ id: `${source}->${target}`,
121
+ source,
122
+ target,
123
+ ...(sourceHandle ? { sourceHandle } : {}),
124
+ })
125
+
126
+ it('cart-increment shape: ONE server segment holding only the data-select', () => {
127
+ // trigger → data-select (server) → get-settings → validate (client js) → if
128
+ const workflow = {
129
+ nodes: [
130
+ node('trigger', 'event-element-clicked', { isFirstNode: true }),
131
+ node('fetch-product', 'data-select', { tableName: 'teleport_products' }),
132
+ node('get-settings', 'ecommerce-get-settings'),
133
+ node('validate', 'general-custom-js', {
134
+ code: 'function customHandler(p){}',
135
+ context: 'client',
136
+ }),
137
+ node('gate', 'general-if-statement', {}),
138
+ ],
139
+ edges: [
140
+ edge('trigger', 'fetch-product'),
141
+ edge('fetch-product', 'get-settings'),
142
+ edge('get-settings', 'validate'),
143
+ edge('validate', 'gate'),
144
+ ],
145
+ } as unknown as UIDLWorkflow
146
+
147
+ const segments = splitIntoSegments(workflow)
148
+ const serverSegments = segments.filter((s) => s.env === 'server')
149
+ expect(serverSegments).toHaveLength(1)
150
+ expect(serverSegments[0].nodes.map((n) => n.id)).toEqual(['fetch-product'])
151
+ })
152
+
153
+ it('add-to-cart shape: settings between client nodes mints NO server segment', () => {
154
+ // extract (client js) → get-settings → guest-check (client js) → if →
155
+ // [redirect | data-select] — only the data-select is a server segment.
156
+ const workflow = {
157
+ nodes: [
158
+ node('extract', 'general-custom-js', {
159
+ code: 'function customHandler(p){}',
160
+ context: 'client',
161
+ }),
162
+ node('get-settings', 'ecommerce-get-settings'),
163
+ node('guest-check', 'general-custom-js', {
164
+ code: 'function customHandler(p){}',
165
+ context: 'client',
166
+ }),
167
+ node('gate', 'general-if-statement', {}),
168
+ node('redirect', 'navigation-navigate-to-url', { url: '/sign-in' }),
169
+ node('fetch-product', 'data-select', { tableName: 'teleport_products' }),
170
+ ],
171
+ edges: [
172
+ edge('extract', 'get-settings'),
173
+ edge('get-settings', 'guest-check'),
174
+ edge('guest-check', 'gate'),
175
+ edge('gate', 'redirect', 'true'),
176
+ edge('gate', 'fetch-product', 'false'),
177
+ ],
178
+ } as unknown as UIDLWorkflow
179
+
180
+ const segments = splitIntoSegments(workflow)
181
+ const serverSegments = segments.filter((s) => s.env === 'server')
182
+ expect(serverSegments).toHaveLength(1)
183
+ expect(serverSegments[0].nodes.map((n) => n.id)).toEqual(['fetch-product'])
184
+ })
185
+ })
186
+
187
+ // ─── Dynamic fire-and-forget upgrade, end to end ─────────────────────────────
188
+ //
189
+ // Mirrors the "Resolve Current User" custom node's anonymous half: an
190
+ // if-statement routes a RETURNING guest to a fire-and-forget users-row
191
+ // re-ensure and a NEW guest to an awaited create. Both data nodes land in one
192
+ // server segment, so the segment is statically mixed (fireAndForget: false).
193
+ // When the taken branch leaves only fire-and-forget work live, the runtime
194
+ // must dispatch the segment WITHOUT awaiting; when the awaited branch is
195
+ // taken, it must still block.
196
+ describe('generated custom node — mixed segment upgrades to fire-and-forget per branch', () => {
197
+ const customNodes = {
198
+ 'cn-resolve': {
199
+ id: 'cn-resolve',
200
+ name: 'Resolve-ish',
201
+ parameters: [],
202
+ nodes: [
203
+ {
204
+ id: 'extract',
205
+ type: 'general-custom-js',
206
+ label: 'Extract',
207
+ config: {
208
+ code: 'function customHandler(p, q) { return { returning: true } }',
209
+ context: 'client',
210
+ },
211
+ executionEnv: 'client',
212
+ stepNumber: 0,
213
+ },
214
+ {
215
+ id: 'gate',
216
+ type: 'general-if-statement',
217
+ label: 'Returning Guest?',
218
+ config: {
219
+ conditionType: 'simple-comparison',
220
+ leftValue: {
221
+ type: 'workflowContext',
222
+ nodeId: 'extract',
223
+ path: ['extract', 'returning'],
224
+ },
225
+ operator: '===',
226
+ rightValue: true,
227
+ },
228
+ executionEnv: 'client',
229
+ stepNumber: 1,
230
+ },
231
+ {
232
+ id: 'ensure',
233
+ type: 'data-create-item',
234
+ label: 'Ensure Row',
235
+ config: { awaitResult: false },
236
+ executionEnv: 'server',
237
+ stepNumber: 2,
238
+ },
239
+ {
240
+ id: 'create',
241
+ type: 'data-create-item',
242
+ label: 'Create Row',
243
+ config: {},
244
+ executionEnv: 'server',
245
+ stepNumber: 2,
246
+ },
247
+ {
248
+ id: 'return-stored',
249
+ type: 'general-custom-js',
250
+ label: 'Return Stored',
251
+ config: {
252
+ code: 'function customHandler(p, q) { return { branch: "stored" } }',
253
+ context: 'client',
254
+ },
255
+ executionEnv: 'client',
256
+ stepNumber: 3,
257
+ },
258
+ {
259
+ id: 'return-new',
260
+ type: 'general-custom-js',
261
+ label: 'Return New',
262
+ config: {
263
+ code: 'function customHandler(p, q) { return { branch: "new" } }',
264
+ context: 'client',
265
+ },
266
+ executionEnv: 'client',
267
+ stepNumber: 3,
268
+ },
269
+ ],
270
+ edges: [
271
+ { id: 'e1', source: 'extract', target: 'gate' },
272
+ { id: 'e2', source: 'gate', target: 'ensure', sourceHandle: 'true' },
273
+ { id: 'e3', source: 'gate', target: 'create', sourceHandle: 'false' },
274
+ { id: 'e4', source: 'ensure', target: 'return-stored' },
275
+ { id: 'e5', source: 'create', target: 'return-new' },
276
+ ],
277
+ },
278
+ }
279
+
280
+ interface BootedCustomNode {
281
+ run: (
282
+ outerContext: Record<string, unknown>,
283
+ parameters: Record<string, unknown>,
284
+ handlers: Record<string, unknown>
285
+ ) => Promise<unknown>
286
+ segmentCalls: string[]
287
+ resolveSegment: () => void
288
+ }
289
+
290
+ const bootCustomNode = (): BootedCustomNode => {
291
+ const plugin = new NextWorkflowProjectPlugin() as unknown as {
292
+ generateCustomNodesFile: (
293
+ nodes: Record<string, unknown>,
294
+ urls: Record<string, Record<string, string>>
295
+ ) => string
296
+ }
297
+ const source = plugin.generateCustomNodesFile(customNodes, {
298
+ 'cn-resolve': { 'server-1': '/api/workflows/resolve-seg-1' },
299
+ })
300
+
301
+ const utilsModule: { exports: Record<string, unknown> } = { exports: {} }
302
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
303
+ new Function('module', 'exports', generateSharedRuntimeUtilsCode())(
304
+ utilsModule,
305
+ utilsModule.exports
306
+ )
307
+
308
+ const segmentCalls: string[] = []
309
+ let releaseSegment: () => void = () => undefined
310
+ const segmentGate = new Promise<void>((resolve) => {
311
+ releaseSegment = resolve
312
+ })
313
+ const runtimeStub = {
314
+ findStreamingAINodes: () => ({}),
315
+ mergeServerResults: () => undefined,
316
+ callStreamingServerSegment: async () => ({}),
317
+ callServerSegment: async (url: string) => {
318
+ segmentCalls.push(url)
319
+ await segmentGate
320
+ return {}
321
+ },
322
+ }
323
+
324
+ const requireStub = (id: string) =>
325
+ id === './runtime-utils' ? utilsModule.exports : id === './runtime' ? runtimeStub : {}
326
+
327
+ const moduleStub: { exports: Record<string, unknown> } = { exports: {} }
328
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
329
+ new Function('module', 'exports', 'require', source)(
330
+ moduleStub,
331
+ moduleStub.exports,
332
+ requireStub
333
+ )
334
+
335
+ const registry = moduleStub.exports as Record<string, BootedCustomNode['run']>
336
+ return { run: registry['cn-resolve'], segmentCalls, resolveSegment: releaseSegment }
337
+ }
338
+
339
+ const handlersFor = (returning: boolean) => ({
340
+ 'general-custom-js': async (config: { code?: string }) => {
341
+ const code = config && config.code ? config.code : ''
342
+ if (code.includes('returning')) {
343
+ return { returning }
344
+ }
345
+ if (code.includes('stored')) {
346
+ return { branch: 'stored' }
347
+ }
348
+ return { branch: 'new' }
349
+ },
350
+ })
351
+
352
+ it('returning-guest branch (only fire-and-forget live) does not await the segment', async () => {
353
+ const booted = bootCustomNode()
354
+
355
+ // The gate promise is never released — if the runtime awaited the segment
356
+ // this would hang and jest would time the test out.
357
+ const result = (await booted.run({}, {}, handlersFor(true))) as Record<string, unknown>
358
+
359
+ expect(booted.segmentCalls).toEqual(['/api/workflows/resolve-seg-1'])
360
+ expect(result).toEqual({ branch: 'stored' })
361
+
362
+ booted.resolveSegment()
363
+ })
364
+
365
+ it('new-guest branch (awaited create live) still blocks on the segment', async () => {
366
+ const booted = bootCustomNode()
367
+
368
+ let settled = false
369
+ const running = booted.run({}, {}, handlersFor(false)).then((value) => {
370
+ settled = true
371
+ return value
372
+ })
373
+
374
+ // Give the runtime ample turns to (incorrectly) run to completion.
375
+ await new Promise((resolve) => setTimeout(resolve, 50))
376
+ expect(booted.segmentCalls).toEqual(['/api/workflows/resolve-seg-1'])
377
+ expect(settled).toBe(false)
378
+
379
+ booted.resolveSegment()
380
+ const result = (await running) as Record<string, unknown>
381
+ expect(result).toEqual({ branch: 'new' })
382
+ })
383
+ })
@@ -1 +1 @@
1
- {"version":3,"file":"executor-generator.d.ts","sourceRoot":"","sources":["../../src/executor-generator.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,8BAA8B,QAAO,MAiuCjD,CAAA;AAED,eAAO,MAAM,yBAAyB,QAAO,MA0f5C,CAAA;AAED,eAAO,MAAM,yBAAyB,QAAO,MAK5C,CAAA"}
1
+ {"version":3,"file":"executor-generator.d.ts","sourceRoot":"","sources":["../../src/executor-generator.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,8BAA8B,QAAO,MAiuCjD,CAAA;AAED,eAAO,MAAM,yBAAyB,QAAO,MAqgB5C,CAAA;AAED,eAAO,MAAM,yBAAyB,QAAO,MAK5C,CAAA"}
@@ -1616,7 +1616,18 @@ async function executeWorkflowWithSegments(workflowConfig, triggerContext, clien
1616
1616
  // still awaits each query before it responds; we simply ignore the
1617
1617
  // response. Errors are logged, never routed to the error handler:
1618
1618
  // the workflow already moved past this point.
1619
- if (seg.fireAndForget) {
1619
+ //
1620
+ // seg.fireAndForget is computed STATICALLY (every node in the segment
1621
+ // is a fire-and-forget data node). A segment that MIXES fire-and-forget
1622
+ // and awaited nodes stays blocking statically — but when branch
1623
+ // skipping has already eliminated the awaited nodes at runtime, only
1624
+ // fire-and-forget work remains, so the same "nothing downstream can
1625
+ // read it" guarantee holds for the nodes that will actually run. The
1626
+ // dynamic check below upgrades exactly that case.
1627
+ var segLiveNodes = seg.nodes.filter(function(n) { return !(context.__skippedNodes && context.__skippedNodes[n.id]); });
1628
+ var segIsFireAndForget = seg.fireAndForget ||
1629
+ (segLiveNodes.length > 0 && segLiveNodes.every(utils.isFireAndForgetNode));
1630
+ if (segIsFireAndForget) {
1620
1631
  const ffUrl = serverSegmentUrls[seg.id];
1621
1632
  if (!ffUrl) throw new Error('No server URL for segment: ' + seg.id);
1622
1633
  utils.registerPendingNodePromise(
@@ -1 +1 @@
1
- {"version":3,"file":"executor-generator.js","sourceRoot":"","sources":["../../src/executor-generator.ts"],"names":[],"mappings":";;;AAAO,MAAM,8BAA8B,GAAG,GAAW,EAAE;IACzD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+tCR,CAAA;AACD,CAAC,CAAA;AAjuCY,QAAA,8BAA8B,kCAiuC1C;AAEM,MAAM,yBAAyB,GAAG,GAAW,EAAE;IACpD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwfR,CAAA;AACD,CAAC,CAAA;AA1fY,QAAA,yBAAyB,6BA0frC;AAEM,MAAM,yBAAyB,GAAG,GAAW,EAAE;IACpD,OAAO;;;CAGR,CAAA;AACD,CAAC,CAAA;AALY,QAAA,yBAAyB,6BAKrC"}
1
+ {"version":3,"file":"executor-generator.js","sourceRoot":"","sources":["../../src/executor-generator.ts"],"names":[],"mappings":";;;AAAO,MAAM,8BAA8B,GAAG,GAAW,EAAE;IACzD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+tCR,CAAA;AACD,CAAC,CAAA;AAjuCY,QAAA,8BAA8B,kCAiuC1C;AAEM,MAAM,yBAAyB,GAAG,GAAW,EAAE;IACpD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmgBR,CAAA;AACD,CAAC,CAAA;AArgBY,QAAA,yBAAyB,6BAqgBrC;AAEM,MAAM,yBAAyB,GAAG,GAAW,EAAE;IACpD,OAAO;;;CAGR,CAAA;AACD,CAAC,CAAA;AALY,QAAA,yBAAyB,6BAKrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"account-get-current.d.ts","sourceRoot":"","sources":["../../../../src/nodes/account/account-get-current.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAmB,MAAM,UAAU,CAAA;AAoGhE,eAAO,MAAM,iBAAiB,EAAE,oBAS/B,CAAA"}
1
+ {"version":3,"file":"account-get-current.d.ts","sourceRoot":"","sources":["../../../../src/nodes/account/account-get-current.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAmB,MAAM,UAAU,CAAA;AAuHhE,eAAO,MAAM,iBAAiB,EAAE,oBAS/B,CAAA"}
@@ -46,16 +46,36 @@ async function account_get_current(_config, context) {
46
46
  // callback re-reads the `users` row) BEFORE the workflow's own request could
47
47
  // start — for data the page had since it mounted.
48
48
  //
49
- // Only 'authenticated' short-circuits. 'loading' means the provider's first
50
- // fetch has not settled; 'unauthenticated' is also what next-auth reports when
51
- // that fetch FAILED, and treating a transient error as "signed out" would send
52
- // a signed-in visitor down the guest branch. Both fall through to the fetch —
53
- // which for a guest is the cheap case anyway, since the jwt callback returns
54
- // before touching the database when there is no token.
49
+ // Only 'authenticated' short-circuits. 'unauthenticated' is also what
50
+ // next-auth reports when the provider's fetch FAILED, and treating a
51
+ // transient error as "signed out" would send a signed-in visitor down the
52
+ // guest branch. It falls through to the fetch — which for a guest is the
53
+ // cheap case anyway, since the jwt callback returns before touching the
54
+ // database when there is no token.
55
+ //
56
+ // 'loading' means the provider's FIRST /api/auth/session fetch is still in
57
+ // flight (a click that lands within ~a second of page load). Issuing our own
58
+ // fetch at that moment duplicates the exact request already on the wire —
59
+ // including its jwt-callback user-row read. Instead, briefly poll the bridge
60
+ // snapshot until the in-flight fetch settles; the bounded deadline means a
61
+ // hung provider fetch degrades to today's behaviour (our own fetch) instead
62
+ // of stalling the workflow.
55
63
  if (typeof window !== 'undefined') {
56
64
  try {
57
65
  const bridge = window.__teleportNextAuth;
58
- const snapshot = bridge && typeof bridge.getSession === 'function' ? bridge.getSession() : null;
66
+ let snapshot = bridge && typeof bridge.getSession === 'function' ? bridge.getSession() : null;
67
+ if (snapshot && snapshot.status === 'loading') {
68
+ const deadline = Date.now() + 3000;
69
+ while (Date.now() < deadline) {
70
+ await new Promise(function (resolve) {
71
+ setTimeout(resolve, 50);
72
+ });
73
+ snapshot = bridge.getSession();
74
+ if (!snapshot || snapshot.status !== 'loading') {
75
+ break;
76
+ }
77
+ }
78
+ }
59
79
  if (snapshot && snapshot.status === 'authenticated') {
60
80
  const liveUser = snapshot.session && snapshot.session.user ? snapshot.session.user : null;
61
81
  if (liveUser) {
@@ -1 +1 @@
1
- {"version":3,"file":"account-get-current.js","sourceRoot":"","sources":["../../../../src/nodes/account/account-get-current.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"account-get-current.js","sourceRoot":"","sources":["../../../../src/nodes/account/account-get-current.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ecommerce-get-settings.d.ts","sourceRoot":"","sources":["../../../../src/nodes/ecommerce/ecommerce-get-settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAmB,MAAM,UAAU,CAAA;AAoBhE,eAAO,MAAM,oBAAoB,EAAE,oBAMlC,CAAA"}
1
+ {"version":3,"file":"ecommerce-get-settings.d.ts","sourceRoot":"","sources":["../../../../src/nodes/ecommerce/ecommerce-get-settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAmB,MAAM,UAAU,CAAA;AAyEhE,eAAO,MAAM,oBAAoB,EAAE,oBAYlC,CAAA"}
@@ -2,7 +2,59 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ecommerceGetSettings = void 0;
4
4
  const types_1 = require("../types");
5
+ // CLIENT handler. The /api/ecommerce/settings route returns a literal baked at
6
+ // generation time (see teleport-project-generator-next's
7
+ // generateEcommerceSettingsApiRoute) — within a deployment it can never return
8
+ // anything else. Paying a server round trip for it on every add-to-cart /
9
+ // cart-increment click was pure latency, and because this node was classified
10
+ // `server` it also SPLIT the surrounding workflow into extra server segments
11
+ // (one HTTP round trip each). The generated ecommerce-context module publishes
12
+ // the SAME payload on `window.__teleportEcommerceSettings` at module-eval time
13
+ // (before any click can run a workflow), so the common path is a synchronous
14
+ // read. The fetch fallback covers projects whose context file predates the
15
+ // baked global; a successful response is memoized for the page's lifetime —
16
+ // the endpoint is immutable within a deployment, so this can never go stale.
5
17
  async function ecommerce_get_settings(_config, context) {
18
+ const baseUrl = (context && context.__baseUrl) || '';
19
+ if (typeof window !== 'undefined') {
20
+ try {
21
+ const baked = window.__teleportEcommerceSettings;
22
+ if (baked && typeof baked === 'object') {
23
+ return baked;
24
+ }
25
+ const memoized = window.__teleportEcommerceSettingsFetched;
26
+ if (memoized && typeof memoized === 'object') {
27
+ return memoized;
28
+ }
29
+ }
30
+ catch (_e) { }
31
+ }
32
+ try {
33
+ const response = await fetch(baseUrl + '/api/ecommerce/settings', {
34
+ method: 'GET',
35
+ headers: { 'Content-Type': 'application/json' },
36
+ });
37
+ if (!response.ok) {
38
+ return { error: 'Failed to load e-commerce settings' };
39
+ }
40
+ const settings = await response.json();
41
+ if (typeof window !== 'undefined' && settings && typeof settings === 'object') {
42
+ try {
43
+ ;
44
+ window.__teleportEcommerceSettingsFetched = settings;
45
+ }
46
+ catch (_e) { }
47
+ }
48
+ return settings;
49
+ }
50
+ catch (err) {
51
+ return { error: err.message };
52
+ }
53
+ }
54
+ // SERVER handler — used by contexts that execute every node server-side
55
+ // (cron and webhook API routes, where no window exists). Same fetch the old
56
+ // server-classified handler performed.
57
+ async function ecommerce_settings_server_fetch(_config, context) {
6
58
  const baseUrl = (context && context.__baseUrl) || '';
7
59
  try {
8
60
  const response = await fetch(baseUrl + '/api/ecommerce/settings', {
@@ -20,9 +72,15 @@ async function ecommerce_get_settings(_config, context) {
20
72
  }
21
73
  exports.ecommerceGetSettings = {
22
74
  nodeType: 'ecommerce-get-settings',
23
- executionEnv: 'server',
75
+ // Client: the settings payload is public, baked into the deployment, and
76
+ // already shipped to the browser — keeping this node server-side only
77
+ // fragmented workflows into extra blocking round trips.
78
+ executionEnv: 'client',
24
79
  generateHandler() {
25
80
  return (0, types_1.handlerToString)(ecommerce_get_settings);
26
81
  },
82
+ generateServerHandler() {
83
+ return (0, types_1.handlerToString)(ecommerce_settings_server_fetch);
84
+ },
27
85
  };
28
86
  //# sourceMappingURL=ecommerce-get-settings.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ecommerce-get-settings.js","sourceRoot":"","sources":["../../../../src/nodes/ecommerce/ecommerce-get-settings.ts"],"names":[],"mappings":";;;AAAA,oCAAgE;AAEhE,KAAK,UAAU,sBAAsB,CAAC,OAAY,EAAE,OAAY;IAC9D,MAAM,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAA;IACpD,IAAI;QACF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,GAAG,yBAAyB,EAAE;YAChE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;SAChD,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;YAChB,OAAO,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAA;SACvD;QAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;KAC7B;IAAC,OAAO,GAAY,EAAE;QACrB,OAAO,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAA;KACzC;AACH,CAAC;AAEY,QAAA,oBAAoB,GAAyB;IACxD,QAAQ,EAAE,wBAAwB;IAClC,YAAY,EAAE,QAAQ;IACtB,eAAe;QACb,OAAO,IAAA,uBAAe,EAAC,sBAAsB,CAAC,CAAA;IAChD,CAAC;CACF,CAAA"}
1
+ {"version":3,"file":"ecommerce-get-settings.js","sourceRoot":"","sources":["../../../../src/nodes/ecommerce/ecommerce-get-settings.ts"],"names":[],"mappings":";;;AAAA,oCAAgE;AAEhE,+EAA+E;AAC/E,yDAAyD;AACzD,+EAA+E;AAC/E,0EAA0E;AAC1E,8EAA8E;AAC9E,6EAA6E;AAC7E,+EAA+E;AAC/E,+EAA+E;AAC/E,6EAA6E;AAC7E,2EAA2E;AAC3E,4EAA4E;AAC5E,6EAA6E;AAC7E,KAAK,UAAU,sBAAsB,CAAC,OAAgB,EAAE,OAAgC;IACtF,MAAM,OAAO,GAAG,CAAC,OAAO,IAAK,OAAe,CAAC,SAAS,CAAC,IAAI,EAAE,CAAA;IAE7D,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;QACjC,IAAI;YACF,MAAM,KAAK,GAAI,MAAc,CAAC,2BAA2B,CAAA;YACzD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBACtC,OAAO,KAAK,CAAA;aACb;YACD,MAAM,QAAQ,GAAI,MAAc,CAAC,kCAAkC,CAAA;YACnE,IAAI,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;gBAC5C,OAAO,QAAQ,CAAA;aAChB;SACF;QAAC,OAAO,EAAE,EAAE,GAAE;KAChB;IAED,IAAI;QACF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,GAAG,yBAAyB,EAAE;YAChE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;SAChD,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;YAChB,OAAO,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAA;SACvD;QAED,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QACtC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;YAC7E,IAAI;gBACF,CAAC;gBAAC,MAAc,CAAC,kCAAkC,GAAG,QAAQ,CAAA;aAC/D;YAAC,OAAO,EAAE,EAAE,GAAE;SAChB;QACD,OAAO,QAAQ,CAAA;KAChB;IAAC,OAAO,GAAY,EAAE;QACrB,OAAO,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAA;KACzC;AACH,CAAC;AAED,wEAAwE;AACxE,4EAA4E;AAC5E,uCAAuC;AACvC,KAAK,UAAU,+BAA+B,CAAC,OAAgB,EAAE,OAAgC;IAC/F,MAAM,OAAO,GAAG,CAAC,OAAO,IAAK,OAAe,CAAC,SAAS,CAAC,IAAI,EAAE,CAAA;IAC7D,IAAI;QACF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,GAAG,yBAAyB,EAAE;YAChE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;SAChD,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;YAChB,OAAO,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAA;SACvD;QAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;KAC7B;IAAC,OAAO,GAAY,EAAE;QACrB,OAAO,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAA;KACzC;AACH,CAAC;AAEY,QAAA,oBAAoB,GAAyB;IACxD,QAAQ,EAAE,wBAAwB;IAClC,yEAAyE;IACzE,sEAAsE;IACtE,wDAAwD;IACxD,YAAY,EAAE,QAAQ;IACtB,eAAe;QACb,OAAO,IAAA,uBAAe,EAAC,sBAAsB,CAAC,CAAA;IAChD,CAAC;IACD,qBAAqB;QACnB,OAAO,IAAA,uBAAe,EAAC,+BAA+B,CAAC,CAAA;IACzD,CAAC;CACF,CAAA"}