glitchgrab 1.58.0 → 1.58.2
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/README.md +28 -0
- package/dist/index.d.mts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +744 -573
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +743 -573
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +36 -3
- package/dist/server.d.ts +36 -3
- package/dist/server.js +44 -13
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +42 -13
- package/dist/server.mjs.map +1 -1
- package/dist/{types-DfVtKZcp.d.mts → types-BpTLWJ1y.d.mts} +8 -0
- package/dist/{types-DfVtKZcp.d.ts → types-BpTLWJ1y.d.ts} +8 -0
- package/package.json +1 -1
package/dist/server.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { l as ReportType, k as ReportSeverity, j as ReportResult } from './types-
|
|
1
|
+
import { l as ReportType, k as ReportSeverity, j as ReportResult } from './types-BpTLWJ1y.mjs';
|
|
2
2
|
import 'react';
|
|
3
3
|
|
|
4
4
|
/** Who to attribute the report to. A server has no signed-in user, so this is the job or service. */
|
|
@@ -382,6 +382,20 @@ interface BookingSettings {
|
|
|
382
382
|
* and it keeps what is stored. The answers come back on {@link Booking.answers}.
|
|
383
383
|
*/
|
|
384
384
|
questions: BookingQuestion[];
|
|
385
|
+
/**
|
|
386
|
+
* Questions saved as a draft and not live yet — the dialog and the WhatsApp
|
|
387
|
+
* chat still ask {@link questions}. Preview them with
|
|
388
|
+
* `useGlitchgrab().openBookingPreview()`, make them live with
|
|
389
|
+
* {@link publishBookingQuestions}. `null` = no draft; `[]` = a draft that
|
|
390
|
+
* asks nothing.
|
|
391
|
+
*/
|
|
392
|
+
draftQuestions: BookingQuestion[] | null;
|
|
393
|
+
/**
|
|
394
|
+
* Text a code to the prospect's phone before the demo is confirmed. `false`
|
|
395
|
+
* books the slot the moment the form is sent — one step fewer, but a
|
|
396
|
+
* mistyped number still books. Defaults to `true`.
|
|
397
|
+
*/
|
|
398
|
+
requireOtp: boolean;
|
|
385
399
|
}
|
|
386
400
|
/** One question asked before a demo is booked. The prospect taps one of `options`. */
|
|
387
401
|
interface BookingQuestion {
|
|
@@ -404,8 +418,14 @@ type BookingQuestionInput = Omit<BookingQuestion, "id" | "required"> & {
|
|
|
404
418
|
required?: boolean;
|
|
405
419
|
};
|
|
406
420
|
/** What {@link updateBookingSettings} accepts — any subset of the settings. */
|
|
407
|
-
type BookingSettingsChanges = Partial<Omit<BookingSettings, "questions">> & {
|
|
421
|
+
type BookingSettingsChanges = Partial<Omit<BookingSettings, "questions" | "draftQuestions">> & {
|
|
408
422
|
questions?: BookingQuestionInput[];
|
|
423
|
+
/**
|
|
424
|
+
* With `questions`: save them as a draft instead — the live dialog and chat
|
|
425
|
+
* are unchanged until {@link publishBookingQuestions}. Left out, `questions`
|
|
426
|
+
* go live at once (and any draft is dropped), as before.
|
|
427
|
+
*/
|
|
428
|
+
draft?: boolean;
|
|
409
429
|
};
|
|
410
430
|
/** One answer a prospect gave, with the question as it was worded when they booked. */
|
|
411
431
|
interface BookingAnswer {
|
|
@@ -453,6 +473,19 @@ declare function getBookingSettings(options?: CallsOptions): Promise<BookingSett
|
|
|
453
473
|
* comes back as one.
|
|
454
474
|
*/
|
|
455
475
|
declare function updateBookingSettings(changes: BookingSettingsChanges, options?: CallsOptions): Promise<BookingSettingsResult>;
|
|
476
|
+
/**
|
|
477
|
+
* Make the draft questions live — the booking dialog and the WhatsApp chat ask
|
|
478
|
+
* them from now on. `error` when there is no draft to publish.
|
|
479
|
+
*
|
|
480
|
+
* ```ts
|
|
481
|
+
* await updateBookingSettings({ questions, draft: true }); // live dialog unchanged
|
|
482
|
+
* // …preview with useGlitchgrab().openBookingPreview() on your admin page…
|
|
483
|
+
* await publishBookingQuestions();
|
|
484
|
+
* ```
|
|
485
|
+
*/
|
|
486
|
+
declare function publishBookingQuestions(options?: CallsOptions): Promise<BookingSettingsResult>;
|
|
487
|
+
/** Throw the draft questions away; the live ones are untouched. */
|
|
488
|
+
declare function discardBookingQuestionsDraft(options?: CallsOptions): Promise<BookingSettingsResult>;
|
|
456
489
|
/** One booked demo. Times are ISO strings in UTC; `timezone` is what the prospect picked in. */
|
|
457
490
|
interface Booking {
|
|
458
491
|
id: string;
|
|
@@ -591,4 +624,4 @@ interface ListLeadsOptions extends CallsOptions {
|
|
|
591
624
|
*/
|
|
592
625
|
declare function listLeads(options?: ListLeadsOptions): Promise<Lead[]>;
|
|
593
626
|
|
|
594
|
-
export { type Booking, type BookingAnswer, type BookingClientNotice, type BookingMutationResult, type BookingNotifyRecipient, type BookingQuestion, type BookingQuestionInput, type BookingSettings, type BookingSettingsChanges, type BookingSettingsResult, type BookingSettingsState, type BookingWorkingHours, type Call, type CallAudio, type CallListItem, type CallMoment, type CallParticipant, type CallsOptions, type CaptureServerErrorsOptions, type DeleteCallResult, type GetCallOptions, type Guide, type GuideReadOptions, type GuideSummary, type Lead, type ListBookingsOptions, type ListCallsOptions, type ListLeadsOptions, ReportResult, ReportSeverity, ReportType, type ServerReportOptions, type ServerReporterConfig, type ServerReporterIdentity, type SignSessionOptions, cancelBooking, captureServerErrors, configureServerReporter, deleteCall, escapeJsonForScript, getBookingSettings, getCall, getGuide, listBookings, listCalls, listGuides, listLeads, reportServerError, rescheduleBooking, resetServerReporter, signSession, updateBookingSettings };
|
|
627
|
+
export { type Booking, type BookingAnswer, type BookingClientNotice, type BookingMutationResult, type BookingNotifyRecipient, type BookingQuestion, type BookingQuestionInput, type BookingSettings, type BookingSettingsChanges, type BookingSettingsResult, type BookingSettingsState, type BookingWorkingHours, type Call, type CallAudio, type CallListItem, type CallMoment, type CallParticipant, type CallsOptions, type CaptureServerErrorsOptions, type DeleteCallResult, type GetCallOptions, type Guide, type GuideReadOptions, type GuideSummary, type Lead, type ListBookingsOptions, type ListCallsOptions, type ListLeadsOptions, ReportResult, ReportSeverity, ReportType, type ServerReportOptions, type ServerReporterConfig, type ServerReporterIdentity, type SignSessionOptions, cancelBooking, captureServerErrors, configureServerReporter, deleteCall, discardBookingQuestionsDraft, escapeJsonForScript, getBookingSettings, getCall, getGuide, listBookings, listCalls, listGuides, listLeads, publishBookingQuestions, reportServerError, rescheduleBooking, resetServerReporter, signSession, updateBookingSettings };
|
package/dist/server.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { l as ReportType, k as ReportSeverity, j as ReportResult } from './types-
|
|
1
|
+
import { l as ReportType, k as ReportSeverity, j as ReportResult } from './types-BpTLWJ1y.js';
|
|
2
2
|
import 'react';
|
|
3
3
|
|
|
4
4
|
/** Who to attribute the report to. A server has no signed-in user, so this is the job or service. */
|
|
@@ -382,6 +382,20 @@ interface BookingSettings {
|
|
|
382
382
|
* and it keeps what is stored. The answers come back on {@link Booking.answers}.
|
|
383
383
|
*/
|
|
384
384
|
questions: BookingQuestion[];
|
|
385
|
+
/**
|
|
386
|
+
* Questions saved as a draft and not live yet — the dialog and the WhatsApp
|
|
387
|
+
* chat still ask {@link questions}. Preview them with
|
|
388
|
+
* `useGlitchgrab().openBookingPreview()`, make them live with
|
|
389
|
+
* {@link publishBookingQuestions}. `null` = no draft; `[]` = a draft that
|
|
390
|
+
* asks nothing.
|
|
391
|
+
*/
|
|
392
|
+
draftQuestions: BookingQuestion[] | null;
|
|
393
|
+
/**
|
|
394
|
+
* Text a code to the prospect's phone before the demo is confirmed. `false`
|
|
395
|
+
* books the slot the moment the form is sent — one step fewer, but a
|
|
396
|
+
* mistyped number still books. Defaults to `true`.
|
|
397
|
+
*/
|
|
398
|
+
requireOtp: boolean;
|
|
385
399
|
}
|
|
386
400
|
/** One question asked before a demo is booked. The prospect taps one of `options`. */
|
|
387
401
|
interface BookingQuestion {
|
|
@@ -404,8 +418,14 @@ type BookingQuestionInput = Omit<BookingQuestion, "id" | "required"> & {
|
|
|
404
418
|
required?: boolean;
|
|
405
419
|
};
|
|
406
420
|
/** What {@link updateBookingSettings} accepts — any subset of the settings. */
|
|
407
|
-
type BookingSettingsChanges = Partial<Omit<BookingSettings, "questions">> & {
|
|
421
|
+
type BookingSettingsChanges = Partial<Omit<BookingSettings, "questions" | "draftQuestions">> & {
|
|
408
422
|
questions?: BookingQuestionInput[];
|
|
423
|
+
/**
|
|
424
|
+
* With `questions`: save them as a draft instead — the live dialog and chat
|
|
425
|
+
* are unchanged until {@link publishBookingQuestions}. Left out, `questions`
|
|
426
|
+
* go live at once (and any draft is dropped), as before.
|
|
427
|
+
*/
|
|
428
|
+
draft?: boolean;
|
|
409
429
|
};
|
|
410
430
|
/** One answer a prospect gave, with the question as it was worded when they booked. */
|
|
411
431
|
interface BookingAnswer {
|
|
@@ -453,6 +473,19 @@ declare function getBookingSettings(options?: CallsOptions): Promise<BookingSett
|
|
|
453
473
|
* comes back as one.
|
|
454
474
|
*/
|
|
455
475
|
declare function updateBookingSettings(changes: BookingSettingsChanges, options?: CallsOptions): Promise<BookingSettingsResult>;
|
|
476
|
+
/**
|
|
477
|
+
* Make the draft questions live — the booking dialog and the WhatsApp chat ask
|
|
478
|
+
* them from now on. `error` when there is no draft to publish.
|
|
479
|
+
*
|
|
480
|
+
* ```ts
|
|
481
|
+
* await updateBookingSettings({ questions, draft: true }); // live dialog unchanged
|
|
482
|
+
* // …preview with useGlitchgrab().openBookingPreview() on your admin page…
|
|
483
|
+
* await publishBookingQuestions();
|
|
484
|
+
* ```
|
|
485
|
+
*/
|
|
486
|
+
declare function publishBookingQuestions(options?: CallsOptions): Promise<BookingSettingsResult>;
|
|
487
|
+
/** Throw the draft questions away; the live ones are untouched. */
|
|
488
|
+
declare function discardBookingQuestionsDraft(options?: CallsOptions): Promise<BookingSettingsResult>;
|
|
456
489
|
/** One booked demo. Times are ISO strings in UTC; `timezone` is what the prospect picked in. */
|
|
457
490
|
interface Booking {
|
|
458
491
|
id: string;
|
|
@@ -591,4 +624,4 @@ interface ListLeadsOptions extends CallsOptions {
|
|
|
591
624
|
*/
|
|
592
625
|
declare function listLeads(options?: ListLeadsOptions): Promise<Lead[]>;
|
|
593
626
|
|
|
594
|
-
export { type Booking, type BookingAnswer, type BookingClientNotice, type BookingMutationResult, type BookingNotifyRecipient, type BookingQuestion, type BookingQuestionInput, type BookingSettings, type BookingSettingsChanges, type BookingSettingsResult, type BookingSettingsState, type BookingWorkingHours, type Call, type CallAudio, type CallListItem, type CallMoment, type CallParticipant, type CallsOptions, type CaptureServerErrorsOptions, type DeleteCallResult, type GetCallOptions, type Guide, type GuideReadOptions, type GuideSummary, type Lead, type ListBookingsOptions, type ListCallsOptions, type ListLeadsOptions, ReportResult, ReportSeverity, ReportType, type ServerReportOptions, type ServerReporterConfig, type ServerReporterIdentity, type SignSessionOptions, cancelBooking, captureServerErrors, configureServerReporter, deleteCall, escapeJsonForScript, getBookingSettings, getCall, getGuide, listBookings, listCalls, listGuides, listLeads, reportServerError, rescheduleBooking, resetServerReporter, signSession, updateBookingSettings };
|
|
627
|
+
export { type Booking, type BookingAnswer, type BookingClientNotice, type BookingMutationResult, type BookingNotifyRecipient, type BookingQuestion, type BookingQuestionInput, type BookingSettings, type BookingSettingsChanges, type BookingSettingsResult, type BookingSettingsState, type BookingWorkingHours, type Call, type CallAudio, type CallListItem, type CallMoment, type CallParticipant, type CallsOptions, type CaptureServerErrorsOptions, type DeleteCallResult, type GetCallOptions, type Guide, type GuideReadOptions, type GuideSummary, type Lead, type ListBookingsOptions, type ListCallsOptions, type ListLeadsOptions, ReportResult, ReportSeverity, ReportType, type ServerReportOptions, type ServerReporterConfig, type ServerReporterIdentity, type SignSessionOptions, cancelBooking, captureServerErrors, configureServerReporter, deleteCall, discardBookingQuestionsDraft, escapeJsonForScript, getBookingSettings, getCall, getGuide, listBookings, listCalls, listGuides, listLeads, publishBookingQuestions, reportServerError, rescheduleBooking, resetServerReporter, signSession, updateBookingSettings };
|
package/dist/server.js
CHANGED
|
@@ -24,6 +24,7 @@ __export(server_exports, {
|
|
|
24
24
|
captureServerErrors: () => captureServerErrors,
|
|
25
25
|
configureServerReporter: () => configureServerReporter,
|
|
26
26
|
deleteCall: () => deleteCall,
|
|
27
|
+
discardBookingQuestionsDraft: () => discardBookingQuestionsDraft,
|
|
27
28
|
escapeJsonForScript: () => escapeJsonForScript,
|
|
28
29
|
getBookingSettings: () => getBookingSettings,
|
|
29
30
|
getCall: () => getCall,
|
|
@@ -32,6 +33,7 @@ __export(server_exports, {
|
|
|
32
33
|
listCalls: () => listCalls,
|
|
33
34
|
listGuides: () => listGuides,
|
|
34
35
|
listLeads: () => listLeads,
|
|
36
|
+
publishBookingQuestions: () => publishBookingQuestions,
|
|
35
37
|
reportServerError: () => reportServerError,
|
|
36
38
|
rescheduleBooking: () => rescheduleBooking,
|
|
37
39
|
resetServerReporter: () => resetServerReporter,
|
|
@@ -48,6 +50,9 @@ var pageLoadedAt = Date.now();
|
|
|
48
50
|
var DEFAULT_BASE_URL = "https://glitchgrab.dev";
|
|
49
51
|
var MAX_RETRIES = 3;
|
|
50
52
|
var RETRY_BASE_MS = 500;
|
|
53
|
+
function reportAttemptTimeoutMs(bodyLength) {
|
|
54
|
+
return 1e4 + Math.ceil(bodyLength / 1e5) * 1e3;
|
|
55
|
+
}
|
|
51
56
|
async function sendReport(payload, baseUrl) {
|
|
52
57
|
var _a;
|
|
53
58
|
try {
|
|
@@ -58,13 +63,18 @@ async function sendReport(payload, baseUrl) {
|
|
|
58
63
|
Authorization: `Bearer ${payload.token}`
|
|
59
64
|
};
|
|
60
65
|
const useKeepalive = body.length < 6e4;
|
|
66
|
+
const timeoutMs = reportAttemptTimeoutMs(body.length);
|
|
61
67
|
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
68
|
+
const isLast = attempt === MAX_RETRIES - 1;
|
|
69
|
+
const controller = !isLast && typeof AbortController === "function" ? new AbortController() : null;
|
|
70
|
+
const timer = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
62
71
|
try {
|
|
63
72
|
const response = await fetch(url, {
|
|
64
73
|
method: "POST",
|
|
65
74
|
headers,
|
|
66
75
|
body,
|
|
67
|
-
...useKeepalive ? { keepalive: true } : {}
|
|
76
|
+
...useKeepalive ? { keepalive: true } : {},
|
|
77
|
+
...controller ? { signal: controller.signal } : {}
|
|
68
78
|
});
|
|
69
79
|
if (response.ok) {
|
|
70
80
|
const envelope = await response.json();
|
|
@@ -74,6 +84,8 @@ async function sendReport(payload, baseUrl) {
|
|
|
74
84
|
return null;
|
|
75
85
|
}
|
|
76
86
|
} catch (e) {
|
|
87
|
+
} finally {
|
|
88
|
+
if (timer) clearTimeout(timer);
|
|
77
89
|
}
|
|
78
90
|
if (attempt < MAX_RETRIES - 1) {
|
|
79
91
|
await new Promise(
|
|
@@ -466,8 +478,20 @@ async function deleteCall(id, options = {}) {
|
|
|
466
478
|
}
|
|
467
479
|
}
|
|
468
480
|
var WEEKDAY = /^[1-7]$/;
|
|
481
|
+
function readQuestionList(value) {
|
|
482
|
+
if (!Array.isArray(value)) return null;
|
|
483
|
+
return value.filter(isRecord).map((row) => {
|
|
484
|
+
var _a, _b;
|
|
485
|
+
return {
|
|
486
|
+
id: (_a = stringOrNull(row.id)) != null ? _a : "",
|
|
487
|
+
label: (_b = stringOrNull(row.label)) != null ? _b : "",
|
|
488
|
+
options: Array.isArray(row.options) ? row.options.filter((option) => typeof option === "string") : [],
|
|
489
|
+
required: row.required !== false
|
|
490
|
+
};
|
|
491
|
+
}).filter((row) => row.id !== "" && row.label !== "");
|
|
492
|
+
}
|
|
469
493
|
function readBookingSettingsState(value) {
|
|
470
|
-
var _a, _b, _c, _d;
|
|
494
|
+
var _a, _b, _c, _d, _e;
|
|
471
495
|
if (!isRecord(value) || !isRecord(value.settings)) return null;
|
|
472
496
|
const s = value.settings;
|
|
473
497
|
const hours = {};
|
|
@@ -501,15 +525,11 @@ function readBookingSettingsState(value) {
|
|
|
501
525
|
phone: (_b2 = stringOrNull(row.phone)) != null ? _b2 : ""
|
|
502
526
|
};
|
|
503
527
|
}).filter((row) => row.phone !== "") : [],
|
|
504
|
-
questions:
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
options: Array.isArray(row.options) ? row.options.filter((option) => typeof option === "string") : [],
|
|
510
|
-
required: row.required !== false
|
|
511
|
-
};
|
|
512
|
-
}).filter((row) => row.id !== "" && row.label !== "") : []
|
|
528
|
+
questions: (_e = readQuestionList(s.questions)) != null ? _e : [],
|
|
529
|
+
// A server from before drafts sends no key: no draft.
|
|
530
|
+
draftQuestions: readQuestionList(s.draftQuestions),
|
|
531
|
+
// Missing means a server from before the switch, which always asked.
|
|
532
|
+
requireOtp: s.requireOtp !== false
|
|
513
533
|
},
|
|
514
534
|
saved: value.saved === true,
|
|
515
535
|
calendarConnected: value.calendarConnected === true
|
|
@@ -526,13 +546,16 @@ async function getBookingSettings(options = {}) {
|
|
|
526
546
|
return { ok: false, error: "Could not read booking settings" };
|
|
527
547
|
}
|
|
528
548
|
}
|
|
529
|
-
|
|
549
|
+
function updateBookingSettings(changes, options = {}) {
|
|
550
|
+
return putBookingSettings(changes != null ? changes : {}, options);
|
|
551
|
+
}
|
|
552
|
+
async function putBookingSettings(body, options) {
|
|
530
553
|
try {
|
|
531
554
|
const key = callsKey(options);
|
|
532
555
|
if (!key) return { ok: false, error: NO_KEY_ERROR };
|
|
533
556
|
const { data, error } = await callSdkApi("/api/v1/sdk/booking-settings", key, options, {
|
|
534
557
|
method: "PUT",
|
|
535
|
-
body
|
|
558
|
+
body,
|
|
536
559
|
cache: "no-store"
|
|
537
560
|
});
|
|
538
561
|
const state = error === null ? readBookingSettingsState(data) : null;
|
|
@@ -541,6 +564,12 @@ async function updateBookingSettings(changes, options = {}) {
|
|
|
541
564
|
return { ok: false, error: "Could not save booking settings" };
|
|
542
565
|
}
|
|
543
566
|
}
|
|
567
|
+
function publishBookingQuestions(options = {}) {
|
|
568
|
+
return putBookingSettings({ publishDraft: true }, options);
|
|
569
|
+
}
|
|
570
|
+
function discardBookingQuestionsDraft(options = {}) {
|
|
571
|
+
return putBookingSettings({ discardDraft: true }, options);
|
|
572
|
+
}
|
|
544
573
|
function readBooking(value) {
|
|
545
574
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
546
575
|
if (!isRecord(value) || typeof value.id !== "string") return null;
|
|
@@ -689,6 +718,7 @@ async function listLeads(options = {}) {
|
|
|
689
718
|
captureServerErrors,
|
|
690
719
|
configureServerReporter,
|
|
691
720
|
deleteCall,
|
|
721
|
+
discardBookingQuestionsDraft,
|
|
692
722
|
escapeJsonForScript,
|
|
693
723
|
getBookingSettings,
|
|
694
724
|
getCall,
|
|
@@ -697,6 +727,7 @@ async function listLeads(options = {}) {
|
|
|
697
727
|
listCalls,
|
|
698
728
|
listGuides,
|
|
699
729
|
listLeads,
|
|
730
|
+
publishBookingQuestions,
|
|
700
731
|
reportServerError,
|
|
701
732
|
rescheduleBooking,
|
|
702
733
|
resetServerReporter,
|