@teleporthq/teleport-plugin-next-workflows 0.43.61 → 0.43.63

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 (93) hide show
  1. package/__tests__/browser-speech-recognition.test.ts +625 -0
  2. package/__tests__/custom-event-component-scope.test.ts +143 -0
  3. package/__tests__/data-update-item-runtime.test.ts +39 -0
  4. package/__tests__/page-revalidate-node.test.ts +276 -0
  5. package/__tests__/payment-refund.test.ts +135 -0
  6. package/dist/cjs/api-route-generator.d.ts.map +1 -1
  7. package/dist/cjs/api-route-generator.js +1 -0
  8. package/dist/cjs/api-route-generator.js.map +1 -1
  9. package/dist/cjs/nodes/analytics/commerce-tracking.d.ts +46 -0
  10. package/dist/cjs/nodes/analytics/commerce-tracking.d.ts.map +1 -0
  11. package/dist/cjs/nodes/analytics/commerce-tracking.js +94 -0
  12. package/dist/cjs/nodes/analytics/commerce-tracking.js.map +1 -0
  13. package/dist/cjs/nodes/browser/browser-speech-recognition.d.ts +3 -0
  14. package/dist/cjs/nodes/browser/browser-speech-recognition.d.ts.map +1 -0
  15. package/dist/cjs/nodes/browser/browser-speech-recognition.js +448 -0
  16. package/dist/cjs/nodes/browser/browser-speech-recognition.js.map +1 -0
  17. package/dist/cjs/nodes/cache/page-revalidate.d.ts +3 -0
  18. package/dist/cjs/nodes/cache/page-revalidate.d.ts.map +1 -0
  19. package/dist/cjs/nodes/cache/page-revalidate.js +125 -0
  20. package/dist/cjs/nodes/cache/page-revalidate.js.map +1 -0
  21. package/dist/cjs/nodes/cart/cart-add-item.d.ts.map +1 -1
  22. package/dist/cjs/nodes/cart/cart-add-item.js +22 -1
  23. package/dist/cjs/nodes/cart/cart-add-item.js.map +1 -1
  24. package/dist/cjs/nodes/cart/cart-remove-item.d.ts.map +1 -1
  25. package/dist/cjs/nodes/cart/cart-remove-item.js +23 -1
  26. package/dist/cjs/nodes/cart/cart-remove-item.js.map +1 -1
  27. package/dist/cjs/nodes/data/data-create-item.d.ts.map +1 -1
  28. package/dist/cjs/nodes/data/data-create-item.js +42 -1
  29. package/dist/cjs/nodes/data/data-create-item.js.map +1 -1
  30. package/dist/cjs/nodes/data/data-update-item.d.ts.map +1 -1
  31. package/dist/cjs/nodes/data/data-update-item.js +38 -3
  32. package/dist/cjs/nodes/data/data-update-item.js.map +1 -1
  33. package/dist/cjs/nodes/index.d.ts.map +1 -1
  34. package/dist/cjs/nodes/index.js +4 -1
  35. package/dist/cjs/nodes/index.js.map +1 -1
  36. package/dist/cjs/nodes/payment/payment-refund.d.ts +3 -0
  37. package/dist/cjs/nodes/payment/payment-refund.d.ts.map +1 -0
  38. package/dist/cjs/nodes/payment/payment-refund.js +446 -0
  39. package/dist/cjs/nodes/payment/payment-refund.js.map +1 -0
  40. package/dist/cjs/secret-collector.d.ts.map +1 -1
  41. package/dist/cjs/secret-collector.js +3 -0
  42. package/dist/cjs/secret-collector.js.map +1 -1
  43. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  44. package/dist/esm/api-route-generator.d.ts.map +1 -1
  45. package/dist/esm/api-route-generator.js +1 -0
  46. package/dist/esm/api-route-generator.js.map +1 -1
  47. package/dist/esm/nodes/analytics/commerce-tracking.d.ts +46 -0
  48. package/dist/esm/nodes/analytics/commerce-tracking.d.ts.map +1 -0
  49. package/dist/esm/nodes/analytics/commerce-tracking.js +90 -0
  50. package/dist/esm/nodes/analytics/commerce-tracking.js.map +1 -0
  51. package/dist/esm/nodes/browser/browser-speech-recognition.d.ts +3 -0
  52. package/dist/esm/nodes/browser/browser-speech-recognition.d.ts.map +1 -0
  53. package/dist/esm/nodes/browser/browser-speech-recognition.js +445 -0
  54. package/dist/esm/nodes/browser/browser-speech-recognition.js.map +1 -0
  55. package/dist/esm/nodes/cache/page-revalidate.d.ts +3 -0
  56. package/dist/esm/nodes/cache/page-revalidate.d.ts.map +1 -0
  57. package/dist/esm/nodes/cache/page-revalidate.js +122 -0
  58. package/dist/esm/nodes/cache/page-revalidate.js.map +1 -0
  59. package/dist/esm/nodes/cart/cart-add-item.d.ts.map +1 -1
  60. package/dist/esm/nodes/cart/cart-add-item.js +22 -1
  61. package/dist/esm/nodes/cart/cart-add-item.js.map +1 -1
  62. package/dist/esm/nodes/cart/cart-remove-item.d.ts.map +1 -1
  63. package/dist/esm/nodes/cart/cart-remove-item.js +23 -1
  64. package/dist/esm/nodes/cart/cart-remove-item.js.map +1 -1
  65. package/dist/esm/nodes/data/data-create-item.d.ts.map +1 -1
  66. package/dist/esm/nodes/data/data-create-item.js +42 -1
  67. package/dist/esm/nodes/data/data-create-item.js.map +1 -1
  68. package/dist/esm/nodes/data/data-update-item.d.ts.map +1 -1
  69. package/dist/esm/nodes/data/data-update-item.js +38 -3
  70. package/dist/esm/nodes/data/data-update-item.js.map +1 -1
  71. package/dist/esm/nodes/index.d.ts.map +1 -1
  72. package/dist/esm/nodes/index.js +4 -1
  73. package/dist/esm/nodes/index.js.map +1 -1
  74. package/dist/esm/nodes/payment/payment-refund.d.ts +3 -0
  75. package/dist/esm/nodes/payment/payment-refund.d.ts.map +1 -0
  76. package/dist/esm/nodes/payment/payment-refund.js +443 -0
  77. package/dist/esm/nodes/payment/payment-refund.js.map +1 -0
  78. package/dist/esm/secret-collector.d.ts.map +1 -1
  79. package/dist/esm/secret-collector.js +3 -0
  80. package/dist/esm/secret-collector.js.map +1 -1
  81. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  82. package/package.json +4 -4
  83. package/src/api-route-generator.ts +1 -0
  84. package/src/nodes/analytics/commerce-tracking.ts +93 -0
  85. package/src/nodes/browser/browser-speech-recognition.ts +474 -0
  86. package/src/nodes/cache/page-revalidate.ts +140 -0
  87. package/src/nodes/cart/cart-add-item.ts +35 -1
  88. package/src/nodes/cart/cart-remove-item.ts +36 -1
  89. package/src/nodes/data/data-create-item.ts +44 -1
  90. package/src/nodes/data/data-update-item.ts +39 -3
  91. package/src/nodes/index.ts +6 -0
  92. package/src/nodes/payment/payment-refund.ts +512 -0
  93. package/src/secret-collector.ts +3 -0
@@ -0,0 +1,448 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.browserSpeechRecognition = void 0;
4
+ const types_1 = require("../types");
5
+ /**
6
+ * A long-lived dictation session, as opposed to `browser-speech-to-text`, which
7
+ * awaits the FIRST phrase, resolves, and offers no way to stop.
8
+ *
9
+ * The contract this node exists for:
10
+ *
11
+ * - It RETURNS IMMEDIATELY. A workflow that awaited the transcript could not
12
+ * also run a second workflow to stop the microphone, and the node would hold
13
+ * the whole run open for as long as the visitor kept talking.
14
+ * - Transcripts leave through CUSTOM EVENTS (`resultEventName`), dispatched on
15
+ * the `workflow:custom:` channel that `event-custom-triggered` listens on. A
16
+ * workflow bound to that event writes the text into a field, so every
17
+ * app-visible effect still belongs to a workflow rather than to this handler.
18
+ * - The session registry on `window` — not a page state — is the authority on
19
+ * whether the microphone is live, so `action: "toggle"` cannot desync from
20
+ * reality no matter how the UI state was left.
21
+ *
22
+ * Every exit path ends in exactly one `endEventName` dispatch, including the
23
+ * ones that never started (unsupported browser, `start()` throwing), so the UI
24
+ * that turned "listening" on always has something to turn it off again.
25
+ *
26
+ * ⛔ NOTHING here is reported as an `error`. The runtime's `isFatalNodeResult`
27
+ * treats any non-empty `error` string as a FAILED node and aborts the rest of
28
+ * the workflow — which would skip the very state write that puts the button
29
+ * back to idle, and would fire the error branch of any workflow that has one.
30
+ * A browser without the API, or a visitor who declines the microphone, is a
31
+ * normal outcome of asking, not a failure of the workflow, so it comes back as
32
+ * `reason` and the caller decides what to say about it.
33
+ */
34
+ async function browser_speech_recognition(config, _context) {
35
+ const REGISTRY_KEY = '__teleportSpeechSessions';
36
+ const DEFAULT_MAX_DURATION_MS = 120000;
37
+ // Chrome ends a "continuous" session after a few seconds of silence, so a
38
+ // dictation of any length is really a chain of restarts. The cap is what
39
+ // stops a microphone that can never hear anything (muted device, wrong input)
40
+ // from restarting forever.
41
+ const MAX_CONSECUTIVE_RESTARTS = 60;
42
+ // A run shorter than this heard nothing at all; see `onend`.
43
+ const MIN_USEFUL_RUN_MS = 500;
44
+ const MAX_RAPID_RESTARTS = 5;
45
+ // Errors that mean "this will not work, stop trying" rather than "nothing was
46
+ // said just now". `no-speech` and `aborted` are ordinary and must NOT be here.
47
+ const FATAL_ERRORS = ['not-allowed', 'service-not-allowed', 'audio-capture', 'bad-grammar'];
48
+ // ⛔ These two strings are a CONTRACT with the builder repo, where they are
49
+ // `SPEECH_STOP_PHRASE_REASON` / `SPEECH_SUBMIT_PHRASE_REASON` and are what a
50
+ // workflow gates its follow-up branch on. The handler is emitted as a
51
+ // standalone string in a separate repo, so it cannot import them: instead
52
+ // both sides pin the literal in their own tests, and either one changing the
53
+ // spelling alone fails there.
54
+ const STOP_PHRASE_REASON = 'stop-phrase';
55
+ const SUBMIT_PHRASE_REASON = 'submit-phrase';
56
+ const win = typeof window === 'undefined' ? null : window;
57
+ if (!win) {
58
+ return {
59
+ listening: false,
60
+ supported: false,
61
+ action: 'unchanged',
62
+ sessionId: '',
63
+ reason: 'no-window',
64
+ };
65
+ }
66
+ const sessions = win[REGISTRY_KEY] || (win[REGISTRY_KEY] = {});
67
+ const sessionId = String(config.sessionId == null || config.sessionId === '' ? 'default' : config.sessionId);
68
+ const requested = config.action === 'start' || config.action === 'stop' ? config.action : 'toggle';
69
+ const resultEventName = typeof config.resultEventName === 'string' ? config.resultEventName : '';
70
+ const endEventName = typeof config.endEventName === 'string' ? config.endEventName : '';
71
+ // What the end event reports when THIS call is the thing that stops the
72
+ // session. A caller that stops for a reason of its own — a spoken "send that",
73
+ // a navigation, a closing panel — needs the end workflow to be able to tell
74
+ // that apart from the visitor clicking the microphone off, and the end event
75
+ // is the only place both arrive.
76
+ const stopReason = typeof config.stopReason === 'string' && config.stopReason ? config.stopReason : 'stopped';
77
+ const dispatch = (eventName, detail) => {
78
+ if (!eventName) {
79
+ return;
80
+ }
81
+ try {
82
+ win.dispatchEvent(new CustomEvent('workflow:custom:' + eventName, { detail }));
83
+ }
84
+ catch (e) {
85
+ /* a listener throwing must never take the session down with it */
86
+ }
87
+ };
88
+ const existing = sessions[sessionId];
89
+ const isListening = !!(existing && existing.active);
90
+ // ── stop ──────────────────────────────────────────────────────────────────
91
+ if (requested === 'stop' || (requested === 'toggle' && isListening)) {
92
+ if (!existing) {
93
+ return {
94
+ listening: false,
95
+ supported: true,
96
+ action: 'unchanged',
97
+ sessionId,
98
+ reason: '',
99
+ };
100
+ }
101
+ // Cleared BEFORE `.stop()` so the `onend` that follows finalizes instead of
102
+ // auto-restarting, and so a second click cannot stop the same session twice.
103
+ existing.active = false;
104
+ existing.reason = stopReason;
105
+ try {
106
+ existing.recognition.stop();
107
+ }
108
+ catch (e) {
109
+ // Already stopping, or never started. `onend` may therefore never fire,
110
+ // so finalize here instead of leaving the UI stuck on "listening".
111
+ if (existing.finalize) {
112
+ existing.finalize(stopReason, '');
113
+ }
114
+ }
115
+ return {
116
+ listening: false,
117
+ supported: true,
118
+ action: 'stopped',
119
+ sessionId,
120
+ reason: '',
121
+ };
122
+ }
123
+ // ── start ─────────────────────────────────────────────────────────────────
124
+ if (isListening) {
125
+ // `action: "start"` on a live session: leave it alone rather than replacing
126
+ // the recogniser, which would drop everything said so far.
127
+ return {
128
+ listening: true,
129
+ supported: true,
130
+ action: 'unchanged',
131
+ sessionId,
132
+ reason: '',
133
+ };
134
+ }
135
+ const SpeechRecognition = win.SpeechRecognition || win.webkitSpeechRecognition;
136
+ if (!SpeechRecognition) {
137
+ // Firefox, and every browser with the API behind a flag. The end event is
138
+ // still emitted so the caller's "listening" state is turned back off and it
139
+ // has a `reason` to explain the failure with.
140
+ dispatch(endEventName, {
141
+ sessionId,
142
+ text: typeof config.initialText === 'string' ? config.initialText : '',
143
+ transcript: '',
144
+ reason: 'unsupported',
145
+ error: '',
146
+ listening: false,
147
+ });
148
+ return {
149
+ listening: false,
150
+ supported: false,
151
+ action: 'unchanged',
152
+ sessionId,
153
+ reason: 'unsupported',
154
+ };
155
+ }
156
+ const baseText = typeof config.initialText === 'string' ? config.initialText : '';
157
+ const continuous = config.continuous !== false;
158
+ const interimResults = config.interimResults !== false;
159
+ const language = (typeof config.language === 'string' && config.language) ||
160
+ (win.document && win.document.documentElement && win.document.documentElement.lang) ||
161
+ 'en-US';
162
+ const autoRestart = config.autoRestart !== false && continuous;
163
+ // Spoken commands. Normalised once, longest first: "stop listening" has to
164
+ // win over "stop", or the longer spelling leaves "listening" in the field.
165
+ const toPhraseList = (value) => (Array.isArray(value) ? value : [])
166
+ .map((entry) => String(entry == null ? '' : entry)
167
+ .toLowerCase()
168
+ .trim())
169
+ .filter(function (entry) {
170
+ return entry !== '';
171
+ })
172
+ .sort(function (a, b) {
173
+ return b.length - a.length;
174
+ });
175
+ const stopPhrases = toPhraseList(config.stopPhrases);
176
+ const submitPhrases = toPhraseList(config.submitPhrases);
177
+ const maxDurationMs = typeof config.maxDurationMs === 'number' && config.maxDurationMs > 0
178
+ ? config.maxDurationMs
179
+ : DEFAULT_MAX_DURATION_MS;
180
+ const session = {
181
+ active: true,
182
+ startedAt: 0,
183
+ rapidRestarts: 0,
184
+ baseText,
185
+ // Finals from recogniser runs that have already ended. Kept apart from the
186
+ // current run's finals because a restarted recogniser reports its own
187
+ // results from index 0 again, so the two cannot share one accumulator.
188
+ committedText: '',
189
+ currentFinalText: '',
190
+ lastEmitted: null,
191
+ restarts: 0,
192
+ reason: 'ended',
193
+ matchedPhrase: '',
194
+ error: '',
195
+ finished: false,
196
+ recognition: null,
197
+ timer: null,
198
+ finalize: null,
199
+ };
200
+ sessions[sessionId] = session;
201
+ // Every seam between two pieces of text needs the same rule: without it,
202
+ // "hello" typed then "there" spoken comes back as "hellothere".
203
+ const join = (head, tail) => {
204
+ if (!head) {
205
+ return tail;
206
+ }
207
+ if (!tail) {
208
+ return head;
209
+ }
210
+ return /\s$/.test(head) ? head + tail : head + ' ' + tail;
211
+ };
212
+ /** Everything recognised so far in this session, across restarts. */
213
+ const spokenSoFar = () => join(session.committedText, session.currentFinalText);
214
+ /** What the target field should now contain. */
215
+ const compose = (spoken) => join(session.baseText, spoken);
216
+ // ── spoken commands ───────────────────────────────────────────────────────
217
+ // A command is the LAST thing said, so matching is anchored to the end of the
218
+ // text and to a word boundary — "enclose" is not "close", and "how do I
219
+ // submit a return" is not a submit. Trailing punctuation is the recogniser's,
220
+ // never the visitor's: "send it." and "send it" are one instruction.
221
+ const trimCommandTail = (value) => value.replace(/[\s.,!?;:]+$/, '');
222
+ // ⛔ The MESSAGE keeps its own punctuation. Only the separator between it and
223
+ // the command goes — the pause comma the recogniser writes for "what time do
224
+ // you open, send it". Trimming the same set would turn a dictated question
225
+ // into a statement.
226
+ const trimSeparator = (value) => value.replace(/[\s,;:]+$/, '');
227
+ const matchPhraseAtEnd = (text, phrases) => {
228
+ const trimmed = trimCommandTail(text);
229
+ const lower = trimmed.toLowerCase();
230
+ for (let i = 0; i < phrases.length; i += 1) {
231
+ const phrase = phrases[i];
232
+ if (!phrase || lower.length < phrase.length) {
233
+ continue;
234
+ }
235
+ if (lower.slice(lower.length - phrase.length) !== phrase) {
236
+ continue;
237
+ }
238
+ const head = trimmed.slice(0, trimmed.length - phrase.length);
239
+ if (head !== '' && !/\s$/.test(head)) {
240
+ continue;
241
+ }
242
+ return { phrase, rest: trimSeparator(head) };
243
+ }
244
+ return null;
245
+ };
246
+ /**
247
+ * What the field should show, and what the visitor asked for.
248
+ *
249
+ * Stripping runs on EVERY update so the command word is never visible, and is
250
+ * self-correcting: an interim that revises itself puts the word back on the
251
+ * next one. Only a settled phrase ACTS, which is what stops a half-spoken
252
+ * sentence from firing.
253
+ */
254
+ const readCommand = (text, isFinal) => {
255
+ if (stopPhrases.length === 0 && submitPhrases.length === 0) {
256
+ return { text, action: '', phrase: '' };
257
+ }
258
+ let hit = matchPhraseAtEnd(text, submitPhrases);
259
+ let action = hit ? 'submit' : '';
260
+ if (!hit) {
261
+ hit = matchPhraseAtEnd(text, stopPhrases);
262
+ action = hit ? 'stop' : '';
263
+ }
264
+ if (!hit) {
265
+ return { text, action: '', phrase: '' };
266
+ }
267
+ // Nothing left to act on is a plain stop, never an empty submission.
268
+ if (action === 'submit' && hit.rest.trim() === '') {
269
+ action = 'stop';
270
+ }
271
+ return { text: hit.rest, action: isFinal ? action : '', phrase: hit.phrase };
272
+ };
273
+ const finalize = (reason, error, matchedPhrase) => {
274
+ if (session.finished) {
275
+ return;
276
+ }
277
+ session.finished = true;
278
+ session.active = false;
279
+ if (session.timer) {
280
+ clearTimeout(session.timer);
281
+ session.timer = null;
282
+ }
283
+ // ⛔ A session that has been REPLACED must die quietly. `onend` arrives a
284
+ // task after `.stop()`, so a click landing in that gap starts a fresh
285
+ // session under the same name — and the old one's end event would then turn
286
+ // the UI off while the new microphone is live.
287
+ const isCurrent = sessions[sessionId] === session;
288
+ if (!isCurrent) {
289
+ return;
290
+ }
291
+ delete sessions[sessionId];
292
+ // The command word is cut out here too, so the end event's text is the same
293
+ // thing the field was left showing.
294
+ const spoken = readCommand(spokenSoFar(), true);
295
+ dispatch(endEventName, {
296
+ sessionId,
297
+ text: compose(spoken.text),
298
+ transcript: spoken.text,
299
+ reason,
300
+ error,
301
+ matchedPhrase: matchedPhrase || '',
302
+ listening: false,
303
+ });
304
+ };
305
+ session.finalize = finalize;
306
+ const recognition = new SpeechRecognition();
307
+ session.recognition = recognition;
308
+ recognition.lang = language;
309
+ recognition.continuous = continuous;
310
+ recognition.interimResults = interimResults;
311
+ if (typeof config.maxAlternatives === 'number' && config.maxAlternatives > 0) {
312
+ recognition.maxAlternatives = config.maxAlternatives;
313
+ }
314
+ recognition.onresult = (event) => {
315
+ // ⛔ REBUILT from the whole result list, never appended from
316
+ // `event.resultIndex`. An engine is free to re-report a result that is
317
+ // already final (Chrome does when a later phrase revises an earlier one),
318
+ // and an append would then say the same sentence twice. Rebuilding is
319
+ // idempotent whatever the engine re-sends.
320
+ let currentFinal = '';
321
+ let interim = '';
322
+ const results = event.results || [];
323
+ for (let i = 0; i < results.length; i += 1) {
324
+ const result = results[i];
325
+ const alternative = result && result[0];
326
+ const text = alternative && alternative.transcript ? String(alternative.transcript).trim() : '';
327
+ if (result && result.isFinal) {
328
+ currentFinal = join(currentFinal, text);
329
+ }
330
+ else {
331
+ interim = join(interim, text);
332
+ }
333
+ }
334
+ session.currentFinalText = currentFinal;
335
+ const isFinal = !interim;
336
+ const spoken = readCommand(join(spokenSoFar(), interim), isFinal);
337
+ const composed = compose(spoken.text);
338
+ // The API re-emits an unchanged interim result several times a second;
339
+ // without this guard each one would run the consuming workflow again.
340
+ //
341
+ // ⛔ Finality is part of the key. The last interim of a phrase almost always
342
+ // has the SAME text as the final that follows it, so keying on the text
343
+ // alone swallowed the final event entirely — and a consumer that only acts
344
+ // on settled speech (a spoken command, a submit) would then never fire.
345
+ const emissionKey = composed + '\u0000' + (isFinal ? '1' : '0');
346
+ if (emissionKey !== session.lastEmitted) {
347
+ session.lastEmitted = emissionKey;
348
+ dispatch(resultEventName, {
349
+ sessionId,
350
+ text: composed,
351
+ transcript: spoken.text,
352
+ isFinal,
353
+ listening: true,
354
+ });
355
+ }
356
+ if (!spoken.action) {
357
+ return;
358
+ }
359
+ // A spoken command ends the session itself. The result event above went out
360
+ // first and carries the text with the command already cut out, so whatever
361
+ // writes it into the field has the final value before the end event lands.
362
+ session.active = false;
363
+ session.reason = spoken.action === 'submit' ? SUBMIT_PHRASE_REASON : STOP_PHRASE_REASON;
364
+ session.matchedPhrase = spoken.phrase;
365
+ try {
366
+ recognition.stop();
367
+ }
368
+ catch (e) {
369
+ finalize(session.reason, '', spoken.phrase);
370
+ }
371
+ };
372
+ recognition.onerror = (event) => {
373
+ const code = (event && event.error) || 'unknown';
374
+ session.error = code;
375
+ if (FATAL_ERRORS.indexOf(code) >= 0) {
376
+ session.active = false;
377
+ session.reason = code;
378
+ }
379
+ };
380
+ recognition.onend = () => {
381
+ // A run that ended almost as soon as it began never listened to anything —
382
+ // no microphone, or the speech service unreachable. Restarting those as fast
383
+ // as the browser allows is a tight loop, so they get a much shorter leash
384
+ // than the ordinary silence-timeout restarts they are counted apart from.
385
+ const ranFor = Date.now() - session.startedAt;
386
+ session.rapidRestarts = ranFor < MIN_USEFUL_RUN_MS ? session.rapidRestarts + 1 : 0;
387
+ const canRestart = session.active &&
388
+ autoRestart &&
389
+ session.restarts < MAX_CONSECUTIVE_RESTARTS &&
390
+ session.rapidRestarts < MAX_RAPID_RESTARTS &&
391
+ !(win.document && win.document.hidden);
392
+ if (!canRestart) {
393
+ finalize(session.active ? 'ended' : session.reason, session.error, session.matchedPhrase);
394
+ return;
395
+ }
396
+ // Bank this run's finals before the recogniser starts numbering from 0
397
+ // again, and drop the error that ended it — `no-speech` from a pause must
398
+ // not be reported as the reason the whole session eventually stopped.
399
+ session.committedText = spokenSoFar();
400
+ session.currentFinalText = '';
401
+ session.error = '';
402
+ session.restarts += 1;
403
+ session.startedAt = Date.now();
404
+ try {
405
+ recognition.start();
406
+ }
407
+ catch (e) {
408
+ finalize('ended', session.error);
409
+ }
410
+ };
411
+ session.startedAt = Date.now();
412
+ try {
413
+ recognition.start();
414
+ }
415
+ catch (e) {
416
+ // `InvalidStateError` from a recogniser the browser still considers running.
417
+ finalize('start-failed', e.message || 'start-failed');
418
+ return {
419
+ listening: false,
420
+ supported: true,
421
+ action: 'unchanged',
422
+ sessionId,
423
+ reason: 'start-failed',
424
+ };
425
+ }
426
+ session.timer = setTimeout(() => {
427
+ if (!session.active) {
428
+ return;
429
+ }
430
+ session.active = false;
431
+ session.reason = 'timeout';
432
+ try {
433
+ recognition.stop();
434
+ }
435
+ catch (e) {
436
+ finalize('timeout', '');
437
+ }
438
+ }, maxDurationMs);
439
+ return { listening: true, supported: true, action: 'started', sessionId, reason: '' };
440
+ }
441
+ exports.browserSpeechRecognition = {
442
+ nodeType: 'browser-speech-recognition',
443
+ executionEnv: 'client',
444
+ generateHandler() {
445
+ return (0, types_1.handlerToString)(browser_speech_recognition);
446
+ },
447
+ };
448
+ //# sourceMappingURL=browser-speech-recognition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-speech-recognition.js","sourceRoot":"","sources":["../../../../src/nodes/browser/browser-speech-recognition.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { NodeHandlerGenerator } from '../types';
2
+ export declare const pageRevalidate: NodeHandlerGenerator;
3
+ //# sourceMappingURL=page-revalidate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-revalidate.d.ts","sourceRoot":"","sources":["../../../../src/nodes/cache/page-revalidate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAmB,MAAM,UAAU,CAAA;AAqIhE,eAAO,MAAM,cAAc,EAAE,oBAM5B,CAAA"}
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pageRevalidate = void 0;
4
+ const types_1 = require("../types");
5
+ /**
6
+ * Rebuilds statically generated pages on the published site.
7
+ *
8
+ * This is the OTHER cache a published project serves from. `cache-invalidate`
9
+ * clears the data-API cache; a page built by `getStaticProps` keeps serving the
10
+ * HTML it was built with regardless, until its ISR window expires. So an admin
11
+ * who creates, edits or deletes a row watches the public URL stay wrong for the
12
+ * length of that window. Calling `res.revalidate(path)` re-runs `getStaticProps`
13
+ * for that path immediately.
14
+ *
15
+ * SERVER-classified deliberately, for the same two reasons as
16
+ * `cache-invalidate`: `res.revalidate` only exists inside a server route, and
17
+ * being server-side lands it in the SAME segment as the write it follows, so
18
+ * adding it to a CRUD workflow costs no extra round trip.
19
+ *
20
+ * It reaches the rebuild through the app's own `POST /api/tq-revalidate` rather
21
+ * than by importing anything: node handlers ship as runtime source and are
22
+ * re-bundled by webpack, which rewrites `require(` — so an internal HTTP call is
23
+ * the sanctioned way for a handler to reach server-side machinery, and it is
24
+ * also the only way to get at a `res` object with `revalidate` on it.
25
+ *
26
+ * ⛔ Never mark this node fire-and-forget. Its workflows navigate or refresh a
27
+ * page immediately afterwards, and that reload routinely wins the race against
28
+ * an unawaited rebuild — leaving the visitor looking at the stale page this was
29
+ * meant to replace.
30
+ *
31
+ * ⛔ It also must NEVER return `{ success: false }` or a string `error`. The
32
+ * runtime treats both as FATAL and halts the workflow (`isFatalNodeResult`), so
33
+ * a page that could not be rebuilt would abort an admin's save AFTER the row was
34
+ * already written — no success toast, no navigation, and an error for an action
35
+ * that worked. Outcomes are reported as `revalidated` plus a `warning`, and the
36
+ * page's own ISR window remains the safety net.
37
+ */
38
+ async function page_revalidate(config, context) {
39
+ const configured = Array.isArray(config.paths)
40
+ ? config.paths
41
+ : config.paths === undefined || config.paths === null
42
+ ? []
43
+ : [config.paths];
44
+ // One level of flattening: a step that revalidates several rows at once (a
45
+ // bulk delete, say) resolves ONE reference to an array of slugs rather than
46
+ // configuring a path per row.
47
+ const flattened = [];
48
+ for (let i = 0; i < configured.length; i++) {
49
+ const entry = configured[i];
50
+ if (Array.isArray(entry)) {
51
+ for (let j = 0; j < entry.length; j++) {
52
+ flattened.push(entry[j]);
53
+ }
54
+ continue;
55
+ }
56
+ flattened.push(entry);
57
+ }
58
+ const paths = [];
59
+ for (let i = 0; i < flattened.length; i++) {
60
+ const raw = flattened[i];
61
+ if (raw === undefined || raw === null || typeof raw === 'object') {
62
+ continue;
63
+ }
64
+ const trimmed = String(raw).trim();
65
+ if (!trimmed) {
66
+ continue;
67
+ }
68
+ // `res.revalidate` only accepts a site-root-relative path, and a step whose
69
+ // path came from a database column often holds the bare slug.
70
+ const normalized = trimmed.charAt(0) === '/' ? trimmed : '/' + trimmed;
71
+ if (paths.indexOf(normalized) === -1) {
72
+ paths.push(normalized);
73
+ }
74
+ }
75
+ if (!paths.length) {
76
+ return {
77
+ revalidated: [],
78
+ warning: 'No page paths were configured on this step.',
79
+ };
80
+ }
81
+ const baseUrl = context.__baseUrl || '';
82
+ const __internalHeaders = context.__internalHeaders || {};
83
+ const __env = globalThis.process && globalThis.process.env;
84
+ const secret = __env ? __env.TQ_CACHE_SECRET : '';
85
+ if (!secret) {
86
+ // Reported rather than thrown: the write this follows already succeeded, and
87
+ // the page still refreshes on its own revalidate window.
88
+ return {
89
+ revalidated: [],
90
+ warning: 'TQ_CACHE_SECRET is not configured, so published pages will refresh on their own schedule.',
91
+ };
92
+ }
93
+ try {
94
+ const response = await fetch(baseUrl + '/api/tq-revalidate', {
95
+ method: 'POST',
96
+ headers: Object.assign({ 'Content-Type': 'application/json', 'x-tq-cache-secret': secret }, __internalHeaders),
97
+ body: JSON.stringify({ paths }),
98
+ });
99
+ const data = await response.json();
100
+ if (!response.ok || !data.ok) {
101
+ const warning = data.error || 'The published pages could not be refreshed; they will refresh on their own.';
102
+ return { revalidated: [], warning };
103
+ }
104
+ const revalidated = Array.isArray(data.revalidated) ? data.revalidated : [];
105
+ const failed = Array.isArray(data.failed) ? data.failed : [];
106
+ if (failed.length) {
107
+ return {
108
+ revalidated,
109
+ warning: 'Some pages could not be refreshed and will refresh on their own: ' + failed.join(', '),
110
+ };
111
+ }
112
+ return { revalidated };
113
+ }
114
+ catch (err) {
115
+ return { revalidated: [], warning: err.message };
116
+ }
117
+ }
118
+ exports.pageRevalidate = {
119
+ nodeType: 'page-revalidate',
120
+ executionEnv: 'server',
121
+ generateHandler() {
122
+ return (0, types_1.handlerToString)(page_revalidate);
123
+ },
124
+ };
125
+ //# sourceMappingURL=page-revalidate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-revalidate.js","sourceRoot":"","sources":["../../../../src/nodes/cache/page-revalidate.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"cart-add-item.d.ts","sourceRoot":"","sources":["../../../../src/nodes/cart/cart-add-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAmB,MAAM,UAAU,CAAA;AAsHhE,eAAO,MAAM,WAAW,EAAE,oBAMzB,CAAA"}
1
+ {"version":3,"file":"cart-add-item.d.ts","sourceRoot":"","sources":["../../../../src/nodes/cart/cart-add-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAmB,MAAM,UAAU,CAAA;AAmJhE,eAAO,MAAM,WAAW,EAAE,oBAWzB,CAAA"}