@businessdash/sdk 0.9.60 → 0.9.80
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 +991 -295
- package/assets/biab-sw.js +92 -0
- package/dist/account-core/index.d.ts +126 -0
- package/dist/account-core/index.d.ts.map +1 -0
- package/dist/account-core/index.js +191 -0
- package/dist/account-core/index.js.map +1 -0
- package/dist/account.d.ts +11 -0
- package/dist/account.d.ts.map +1 -0
- package/dist/account.js +11 -0
- package/dist/account.js.map +1 -0
- package/dist/auth-handler.d.ts +1 -1
- package/dist/auth-links.d.ts +33 -0
- package/dist/auth-links.d.ts.map +1 -0
- package/dist/auth-links.js +64 -0
- package/dist/auth-links.js.map +1 -0
- package/dist/blog-core/index.d.ts +112 -0
- package/dist/blog-core/index.d.ts.map +1 -0
- package/dist/blog-core/index.js +330 -0
- package/dist/blog-core/index.js.map +1 -0
- package/dist/blog.d.ts +11 -0
- package/dist/blog.d.ts.map +1 -0
- package/dist/blog.js +11 -0
- package/dist/blog.js.map +1 -0
- package/dist/chat-core/index.d.ts +97 -0
- package/dist/chat-core/index.d.ts.map +1 -0
- package/dist/chat-core/index.js +237 -0
- package/dist/chat-core/index.js.map +1 -0
- package/dist/chat.d.ts +11 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +11 -0
- package/dist/chat.js.map +1 -0
- package/dist/checkout-core/index.d.ts +65 -0
- package/dist/checkout-core/index.d.ts.map +1 -0
- package/dist/checkout-core/index.js +159 -0
- package/dist/checkout-core/index.js.map +1 -0
- package/dist/checkout.d.ts +10 -0
- package/dist/checkout.d.ts.map +1 -0
- package/dist/checkout.js +10 -0
- package/dist/checkout.js.map +1 -0
- package/dist/cli.js +133 -25
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +622 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +888 -1
- package/dist/client.js.map +1 -1
- package/dist/consent-core/index.cjs +107 -0
- package/dist/consent-core/index.d.ts +103 -0
- package/dist/consent-core/index.d.ts.map +1 -0
- package/dist/consent-core/index.js +157 -0
- package/dist/consent-core/index.js.map +1 -0
- package/dist/contracts.d.ts +3526 -767
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +571 -4
- package/dist/contracts.js.map +1 -1
- package/dist/data-model-schema.d.ts +1 -1
- package/dist/data-model-schema.d.ts.map +1 -1
- package/dist/element.d.ts +30 -0
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +56 -0
- package/dist/element.js.map +1 -1
- package/dist/embed-protocol.d.ts +86 -0
- package/dist/embed-protocol.d.ts.map +1 -0
- package/dist/embed-protocol.js +60 -0
- package/dist/embed-protocol.js.map +1 -0
- package/dist/framework-support.d.ts +122 -0
- package/dist/framework-support.d.ts.map +1 -0
- package/dist/framework-support.js +323 -0
- package/dist/framework-support.js.map +1 -0
- package/dist/index.cjs +1355 -24
- package/dist/legal-core/index.cjs +115 -0
- package/dist/legal-core/index.d.ts +160 -0
- package/dist/legal-core/index.d.ts.map +1 -0
- package/dist/legal-core/index.js +220 -0
- package/dist/legal-core/index.js.map +1 -0
- package/dist/marketing-core/index.d.ts +66 -0
- package/dist/marketing-core/index.d.ts.map +1 -0
- package/dist/marketing-core/index.js +154 -0
- package/dist/marketing-core/index.js.map +1 -0
- package/dist/marketing.d.ts +7 -0
- package/dist/marketing.d.ts.map +1 -0
- package/dist/marketing.js +7 -0
- package/dist/marketing.js.map +1 -0
- package/dist/mcp-adapters/index.d.ts +135 -0
- package/dist/mcp-adapters/index.d.ts.map +1 -0
- package/dist/mcp-adapters/index.js +187 -0
- package/dist/mcp-adapters/index.js.map +1 -0
- package/dist/mcp-adapters.d.ts +7 -0
- package/dist/mcp-adapters.d.ts.map +1 -0
- package/dist/mcp-adapters.js +7 -0
- package/dist/mcp-adapters.js.map +1 -0
- package/dist/model3d-core/index.cjs +95 -0
- package/dist/model3d-core/index.d.ts +167 -0
- package/dist/model3d-core/index.d.ts.map +1 -0
- package/dist/model3d-core/index.js +158 -0
- package/dist/model3d-core/index.js.map +1 -0
- package/dist/notifications-core/index.cjs +315 -0
- package/dist/notifications-core/index.d.ts +229 -0
- package/dist/notifications-core/index.d.ts.map +1 -0
- package/dist/notifications-core/index.js +445 -0
- package/dist/notifications-core/index.js.map +1 -0
- package/dist/portal-core/index.d.ts +451 -0
- package/dist/portal-core/index.d.ts.map +1 -0
- package/dist/portal-core/index.js +819 -0
- package/dist/portal-core/index.js.map +1 -0
- package/dist/portal.d.ts +7 -0
- package/dist/portal.d.ts.map +1 -0
- package/dist/portal.js +7 -0
- package/dist/portal.js.map +1 -0
- package/dist/push-core/index.cjs +171 -0
- package/dist/push-core/index.d.ts +149 -0
- package/dist/push-core/index.d.ts.map +1 -0
- package/dist/push-core/index.js +231 -0
- package/dist/push-core/index.js.map +1 -0
- package/dist/react-marketing.d.ts +1 -17
- package/dist/react-marketing.d.ts.map +1 -1
- package/dist/react-marketing.js +4 -0
- package/dist/react-marketing.js.map +1 -1
- package/dist/react.d.ts +294 -101
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +302 -246
- package/dist/react.js.map +1 -1
- package/dist/seed-core/index.d.ts +354 -0
- package/dist/seed-core/index.d.ts.map +1 -0
- package/dist/seed-core/index.js +420 -0
- package/dist/seed-core/index.js.map +1 -0
- package/dist/seed.d.ts +7 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +7 -0
- package/dist/seed.js.map +1 -0
- package/dist/seo-core/blog.d.ts +94 -0
- package/dist/seo-core/blog.d.ts.map +1 -0
- package/dist/seo-core/blog.js +149 -0
- package/dist/seo-core/blog.js.map +1 -0
- package/dist/seo-core/commerce.d.ts +64 -0
- package/dist/seo-core/commerce.d.ts.map +1 -0
- package/dist/seo-core/commerce.js +87 -0
- package/dist/seo-core/commerce.js.map +1 -0
- package/dist/seo-core/index.cjs +751 -0
- package/dist/seo-core/index.d.ts +226 -0
- package/dist/seo-core/index.d.ts.map +1 -0
- package/dist/seo-core/index.js +455 -0
- package/dist/seo-core/index.js.map +1 -0
- package/dist/seo-core/local.d.ts +181 -0
- package/dist/seo-core/local.d.ts.map +1 -0
- package/dist/seo-core/local.js +193 -0
- package/dist/seo-core/local.js.map +1 -0
- package/dist/sitemap-core/index.cjs +167 -0
- package/dist/sitemap-core/index.d.ts +155 -0
- package/dist/sitemap-core/index.d.ts.map +1 -0
- package/dist/sitemap-core/index.js +195 -0
- package/dist/sitemap-core/index.js.map +1 -0
- package/dist/social-core/index.d.ts +74 -0
- package/dist/social-core/index.d.ts.map +1 -0
- package/dist/social-core/index.js +72 -0
- package/dist/social-core/index.js.map +1 -0
- package/dist/social.d.ts +7 -0
- package/dist/social.d.ts.map +1 -0
- package/dist/social.js +7 -0
- package/dist/social.js.map +1 -0
- package/dist/solid-compat.d.ts +204 -0
- package/dist/solid-compat.d.ts.map +1 -0
- package/dist/solid-compat.js +221 -0
- package/dist/solid-compat.js.map +1 -0
- package/dist/store-core/index.d.ts +141 -0
- package/dist/store-core/index.d.ts.map +1 -0
- package/dist/store-core/index.js +277 -0
- package/dist/store-core/index.js.map +1 -0
- package/dist/store.d.ts +12 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +12 -0
- package/dist/store.js.map +1 -0
- package/dist/vanilla.d.ts +111 -0
- package/dist/vanilla.d.ts.map +1 -1
- package/dist/vanilla.js +206 -0
- package/dist/vanilla.js.map +1 -1
- package/dist/verify-core/index.d.ts +98 -0
- package/dist/verify-core/index.d.ts.map +1 -0
- package/dist/verify-core/index.js +186 -0
- package/dist/verify-core/index.js.map +1 -0
- package/dist/verify.d.ts +8 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +8 -0
- package/dist/verify.js.map +1 -0
- package/openapi.json +4516 -1311
- package/package.json +128 -11
- package/src/account-core/index.ts +309 -0
- package/src/account.ts +11 -0
- package/src/angular/headless.ts +519 -0
- package/src/angular/index.ts +3 -0
- package/src/auth-links.ts +76 -0
- package/src/blog-core/index.ts +423 -0
- package/src/blog.ts +11 -0
- package/src/chat-core/index.ts +335 -0
- package/src/chat.ts +11 -0
- package/src/checkout-core/index.ts +225 -0
- package/src/checkout.ts +10 -0
- package/src/cli.ts +184 -28
- package/src/client.ts +1097 -0
- package/src/consent-core/index.ts +213 -0
- package/src/contracts.ts +768 -11
- package/src/data-model-schema.ts +1 -1
- package/src/element.ts +102 -0
- package/src/embed-protocol.ts +100 -0
- package/src/framework-support.ts +440 -0
- package/src/legal-core/index.ts +276 -0
- package/src/marketing-core/index.ts +209 -0
- package/src/marketing.ts +7 -0
- package/src/mcp-adapters/index.ts +264 -0
- package/src/mcp-adapters.ts +7 -0
- package/src/model3d-core/index.ts +248 -0
- package/src/notifications-core/index.ts +650 -0
- package/src/portal-core/index.ts +1564 -0
- package/src/portal.ts +7 -0
- package/src/push-core/index.ts +335 -0
- package/src/qwik.tsx +602 -2
- package/src/react-marketing.tsx +5 -0
- package/src/react.tsx +434 -319
- package/src/seed-core/index.ts +735 -0
- package/src/seed.ts +7 -0
- package/src/seo-core/blog.ts +216 -0
- package/src/seo-core/commerce.ts +138 -0
- package/src/seo-core/index.ts +605 -0
- package/src/seo-core/local.ts +333 -0
- package/src/sitemap-core/index.ts +296 -0
- package/src/social-core/index.ts +103 -0
- package/src/social.ts +7 -0
- package/src/solid-compat.tsx +347 -0
- package/src/solid-surfaces.tsx +1311 -0
- package/src/solid.tsx +82 -60
- package/src/store-core/index.ts +426 -0
- package/src/store.ts +12 -0
- package/src/svelte/SocialLinks.svelte +84 -0
- package/src/svelte/headless.ts +435 -0
- package/src/svelte/index.ts +9 -0
- package/src/vanilla.ts +367 -0
- package/src/verify-core/index.ts +288 -0
- package/src/verify.ts +8 -0
- package/src/vue/headless.ts +527 -0
- package/src/vue/index.ts +3 -0
package/dist/index.cjs
CHANGED
|
@@ -9724,12 +9724,31 @@ var chatbotFormDefinitionSchema = external_exports.object({
|
|
|
9724
9724
|
description: external_exports.string(),
|
|
9725
9725
|
fields: external_exports.array(chatbotFormFieldSchema),
|
|
9726
9726
|
addsInquiry: external_exports.boolean(),
|
|
9727
|
-
addsLead: external_exports.boolean()
|
|
9728
|
-
|
|
9727
|
+
addsLead: external_exports.boolean(),
|
|
9728
|
+
/**
|
|
9729
|
+
* The RENDER contract — animation, multi-step + progress style, exit
|
|
9730
|
+
* confirmation, URL safety. The server has always sent this; the schema
|
|
9731
|
+
* dropped it, so anyone building a form UI on the typed client got a
|
|
9732
|
+
* bare field list and none of the behaviour the dashboard configured.
|
|
9733
|
+
*/
|
|
9734
|
+
settings: external_exports.record(external_exports.unknown()).nullish(),
|
|
9735
|
+
/** Org avatar for the form header, when the form opts in. */
|
|
9736
|
+
orgIcon: external_exports.string().nullish(),
|
|
9737
|
+
/** Public action previews ("submitting adds you to the list"). */
|
|
9738
|
+
actions: external_exports.array(external_exports.record(external_exports.unknown())).nullish(),
|
|
9739
|
+
/** Non-sensitive business functions so `calculation` fields compute. */
|
|
9740
|
+
businessFunctions: external_exports.array(external_exports.record(external_exports.unknown())).nullish()
|
|
9741
|
+
}).passthrough();
|
|
9729
9742
|
var chatbotFormSubmitInputSchema = external_exports.object({
|
|
9730
9743
|
data: external_exports.record(external_exports.unknown()),
|
|
9731
9744
|
submitterEmail: external_exports.string().email().optional(),
|
|
9732
9745
|
submitterName: external_exports.string().optional(),
|
|
9746
|
+
/** Validate and run the full pipeline WITHOUT persisting. */
|
|
9747
|
+
dryRun: external_exports.boolean().optional(),
|
|
9748
|
+
/** Provenance the route accepts and this schema previously omitted. */
|
|
9749
|
+
source: external_exports.string().max(200).optional(),
|
|
9750
|
+
referrer: external_exports.string().max(500).optional(),
|
|
9751
|
+
metadata: external_exports.record(external_exports.unknown()).optional(),
|
|
9733
9752
|
priorChat: external_exports.array(
|
|
9734
9753
|
external_exports.object({
|
|
9735
9754
|
role: external_exports.string().min(1).max(40),
|
|
@@ -9740,8 +9759,14 @@ var chatbotFormSubmitInputSchema = external_exports.object({
|
|
|
9740
9759
|
});
|
|
9741
9760
|
var chatbotFormSubmitResponseSchema = external_exports.object({
|
|
9742
9761
|
success: external_exports.literal(true),
|
|
9743
|
-
|
|
9744
|
-
|
|
9762
|
+
/**
|
|
9763
|
+
* NULL on a dry run — the submission validated but was deliberately not
|
|
9764
|
+
* persisted. Requiring a string here made every test submit throw.
|
|
9765
|
+
*/
|
|
9766
|
+
submissionId: external_exports.string().nullable(),
|
|
9767
|
+
slug: external_exports.string(),
|
|
9768
|
+
/** True when nothing was written. Pairs with a null `submissionId`. */
|
|
9769
|
+
dryRun: external_exports.boolean().optional()
|
|
9745
9770
|
});
|
|
9746
9771
|
var chatbotPersistedSessionInputSchema = external_exports.object({
|
|
9747
9772
|
visitorToken: external_exports.string().min(8).max(200),
|
|
@@ -9958,6 +9983,29 @@ var customerPortalProfileSchema = external_exports.object({
|
|
|
9958
9983
|
lastSeenAt: timestampSchema.nullable(),
|
|
9959
9984
|
joinedAt: timestampSchema.nullable()
|
|
9960
9985
|
}).nullable();
|
|
9986
|
+
var customerPortalQuizResultSchema = external_exports.object({
|
|
9987
|
+
invitationId: external_exports.string(),
|
|
9988
|
+
quizName: external_exports.string(),
|
|
9989
|
+
competency: external_exports.string().nullable(),
|
|
9990
|
+
status: external_exports.string(),
|
|
9991
|
+
completedAt: external_exports.string().nullable(),
|
|
9992
|
+
scoreWithheld: external_exports.boolean(),
|
|
9993
|
+
result: external_exports.object({
|
|
9994
|
+
status: external_exports.string(),
|
|
9995
|
+
scorePercent: external_exports.number().nullable(),
|
|
9996
|
+
provisionalScorePercent: external_exports.number().nullable(),
|
|
9997
|
+
passed: external_exports.boolean().nullable(),
|
|
9998
|
+
pointsEarned: external_exports.number().nullable(),
|
|
9999
|
+
pointsPossible: external_exports.number().nullable(),
|
|
10000
|
+
passingScore: external_exports.number(),
|
|
10001
|
+
results: external_exports.array(external_exports.record(external_exports.unknown())),
|
|
10002
|
+
submittedAt: external_exports.string().nullable(),
|
|
10003
|
+
durationSeconds: external_exports.number().nullable()
|
|
10004
|
+
}).nullable()
|
|
10005
|
+
});
|
|
10006
|
+
var customerPortalQuizResultsResponseSchema = external_exports.object({
|
|
10007
|
+
items: external_exports.array(customerPortalQuizResultSchema)
|
|
10008
|
+
});
|
|
9961
10009
|
var customerPortalUpdateProfileInputSchema = external_exports.object({
|
|
9962
10010
|
displayName: external_exports.string().min(1).max(120).optional(),
|
|
9963
10011
|
profile: external_exports.record(external_exports.unknown()).optional()
|
|
@@ -10342,6 +10390,16 @@ var customerReturnRequestSchema = external_exports.object({
|
|
|
10342
10390
|
* are separate enums and each is spelled as the database spells it.
|
|
10343
10391
|
*/
|
|
10344
10392
|
status: openEnum("requested", "approved", "denied", "refunded", "cancelled"),
|
|
10393
|
+
/**
|
|
10394
|
+
* What was asked for: money back, or a replacement. Mirrors
|
|
10395
|
+
* `order_return_request_kind`. Rows created before this existed read
|
|
10396
|
+
* `refund`, which is what they were.
|
|
10397
|
+
*/
|
|
10398
|
+
kind: openEnum("refund", "exchange"),
|
|
10399
|
+
/** On an exchange: the variant wanted instead, when one was chosen. */
|
|
10400
|
+
exchangeForVariantId: external_exports.string().nullable(),
|
|
10401
|
+
/** Set once a replacement ships — track it like any other shipment. */
|
|
10402
|
+
exchangeShipmentId: external_exports.string().nullable(),
|
|
10345
10403
|
reason: external_exports.string().nullable(),
|
|
10346
10404
|
items: external_exports.array(
|
|
10347
10405
|
external_exports.object({
|
|
@@ -10383,6 +10441,16 @@ var customerOrderDetailSchema = external_exports.object({
|
|
|
10383
10441
|
returnRequests: external_exports.array(customerReturnRequestSchema).optional()
|
|
10384
10442
|
});
|
|
10385
10443
|
var customerReturnRequestInputSchema = external_exports.object({
|
|
10444
|
+
/**
|
|
10445
|
+
* `refund` returns the money; `exchange` asks for a replacement. Defaults
|
|
10446
|
+
* to `refund`, so an omitted field means what it always meant.
|
|
10447
|
+
*/
|
|
10448
|
+
kind: external_exports.enum(["refund", "exchange"]).optional(),
|
|
10449
|
+
/**
|
|
10450
|
+
* On an exchange, the variant wanted instead. Optional even then — "a
|
|
10451
|
+
* different size" is a real request that needs a conversation first.
|
|
10452
|
+
*/
|
|
10453
|
+
exchangeForVariantId: external_exports.string().uuid().optional(),
|
|
10386
10454
|
reason: external_exports.string().max(120).optional(),
|
|
10387
10455
|
customerNote: external_exports.string().max(2e3).optional(),
|
|
10388
10456
|
items: external_exports.array(
|
|
@@ -10396,6 +10464,262 @@ var customerReturnRequestCreatedSchema = external_exports.object({
|
|
|
10396
10464
|
id: external_exports.string().nullable(),
|
|
10397
10465
|
/** Mirrors the `order_return_request_status` pg enum. */
|
|
10398
10466
|
status: openEnum("requested", "approved", "denied", "refunded", "cancelled"),
|
|
10467
|
+
/** Echoes back what was opened, so a UI need not assume. */
|
|
10468
|
+
kind: openEnum("refund", "exchange"),
|
|
10469
|
+
createdAt: external_exports.string().nullable()
|
|
10470
|
+
});
|
|
10471
|
+
var customerNotReceivedResultSchema = external_exports.object({
|
|
10472
|
+
id: external_exports.string(),
|
|
10473
|
+
/** True when a claim was already open; the original report is unchanged. */
|
|
10474
|
+
alreadyOpen: external_exports.boolean(),
|
|
10475
|
+
reportedAt: external_exports.string(),
|
|
10476
|
+
carrierStatus: openEnum(
|
|
10477
|
+
"pending",
|
|
10478
|
+
"label_created",
|
|
10479
|
+
"in_transit",
|
|
10480
|
+
"delivered",
|
|
10481
|
+
"returned"
|
|
10482
|
+
),
|
|
10483
|
+
carrierDeliveredAt: external_exports.string().nullable(),
|
|
10484
|
+
contested: external_exports.boolean().optional()
|
|
10485
|
+
});
|
|
10486
|
+
var legalPresentationSchema = external_exports.object({
|
|
10487
|
+
/** Already resolved against the company logo — render as given. */
|
|
10488
|
+
logoUrl: external_exports.string().nullable(),
|
|
10489
|
+
showLogoInHeader: external_exports.boolean(),
|
|
10490
|
+
showLogoInFooter: external_exports.boolean(),
|
|
10491
|
+
headerHtml: external_exports.string().nullable(),
|
|
10492
|
+
footerHtml: external_exports.string().nullable()
|
|
10493
|
+
});
|
|
10494
|
+
var legalDocumentSummarySchema = external_exports.object({
|
|
10495
|
+
/** The URL path, without a leading slash: `privacy`, `terms`, … */
|
|
10496
|
+
slug: external_exports.string(),
|
|
10497
|
+
title: external_exports.string(),
|
|
10498
|
+
version: external_exports.number(),
|
|
10499
|
+
/** ISO 8601. Render as "Last updated". */
|
|
10500
|
+
effectiveDate: external_exports.string().nullable(),
|
|
10501
|
+
showInFooter: external_exports.boolean(),
|
|
10502
|
+
updatedAt: external_exports.string()
|
|
10503
|
+
});
|
|
10504
|
+
var legalListResponseSchema = external_exports.object({
|
|
10505
|
+
items: external_exports.array(legalDocumentSummarySchema),
|
|
10506
|
+
presentation: legalPresentationSchema
|
|
10507
|
+
});
|
|
10508
|
+
var legalDocumentSchema = legalDocumentSummarySchema.extend({
|
|
10509
|
+
/** Sanitised server-side on write, so this is safe to render as HTML. */
|
|
10510
|
+
contentHtml: external_exports.string(),
|
|
10511
|
+
presentation: legalPresentationSchema
|
|
10512
|
+
});
|
|
10513
|
+
var customerPushDeviceSchema = external_exports.object({
|
|
10514
|
+
id: external_exports.string(),
|
|
10515
|
+
endpoint: external_exports.string(),
|
|
10516
|
+
userAgent: external_exports.string().nullable(),
|
|
10517
|
+
label: external_exports.string().nullable(),
|
|
10518
|
+
/** Null = every category. `[]` = none, but the device stays registered. */
|
|
10519
|
+
categories: external_exports.array(external_exports.string()).nullable(),
|
|
10520
|
+
lastSeenAt: external_exports.string().nullable(),
|
|
10521
|
+
createdAt: external_exports.string()
|
|
10522
|
+
});
|
|
10523
|
+
var customerPushConfigSchema = external_exports.object({
|
|
10524
|
+
vapidPublicKey: external_exports.string().nullable(),
|
|
10525
|
+
enabled: external_exports.boolean(),
|
|
10526
|
+
devices: external_exports.array(customerPushDeviceSchema)
|
|
10527
|
+
});
|
|
10528
|
+
var customerInviteResendResponseSchema = external_exports.object({
|
|
10529
|
+
id: external_exports.string(),
|
|
10530
|
+
/** The NEW link. The previous one no longer works. */
|
|
10531
|
+
url: external_exports.string(),
|
|
10532
|
+
expiresAt: external_exports.string().nullable(),
|
|
10533
|
+
/** Includes this send, so a list can show "sent 3 times". */
|
|
10534
|
+
sendCount: external_exports.number()
|
|
10535
|
+
});
|
|
10536
|
+
var schedulingEventTypeSchema = external_exports.object({
|
|
10537
|
+
id: external_exports.string(),
|
|
10538
|
+
name: external_exports.string(),
|
|
10539
|
+
slug: external_exports.string(),
|
|
10540
|
+
description: external_exports.string().nullable(),
|
|
10541
|
+
durationMinutes: external_exports.number(),
|
|
10542
|
+
locationType: external_exports.string(),
|
|
10543
|
+
/** google_meet | zoom | teams | null when the meeting is in person. */
|
|
10544
|
+
meetingProvider: external_exports.string().nullable(),
|
|
10545
|
+
color: external_exports.string().nullable(),
|
|
10546
|
+
/** When true a booking lands `pending`, not `confirmed`. */
|
|
10547
|
+
requiresApproval: external_exports.boolean()
|
|
10548
|
+
});
|
|
10549
|
+
var schedulingQuestionSchema = external_exports.object({
|
|
10550
|
+
id: external_exports.string(),
|
|
10551
|
+
label: external_exports.string()
|
|
10552
|
+
}).passthrough();
|
|
10553
|
+
var schedulingEventTypeListSchema = external_exports.object({
|
|
10554
|
+
eventTypes: external_exports.array(schedulingEventTypeSchema)
|
|
10555
|
+
});
|
|
10556
|
+
var schedulingEventTypeDetailSchema = external_exports.object({
|
|
10557
|
+
eventType: schedulingEventTypeSchema,
|
|
10558
|
+
questions: external_exports.array(schedulingQuestionSchema)
|
|
10559
|
+
});
|
|
10560
|
+
var schedulingSlotSchema = external_exports.object({
|
|
10561
|
+
startAt: external_exports.string(),
|
|
10562
|
+
endAt: external_exports.string()
|
|
10563
|
+
});
|
|
10564
|
+
var schedulingSlotsResponseSchema = external_exports.object({
|
|
10565
|
+
slots: external_exports.array(schedulingSlotSchema)
|
|
10566
|
+
});
|
|
10567
|
+
var schedulingBookingStatusSchema = openEnum(
|
|
10568
|
+
"pending",
|
|
10569
|
+
"confirmed",
|
|
10570
|
+
"canceled",
|
|
10571
|
+
"rescheduled"
|
|
10572
|
+
);
|
|
10573
|
+
var schedulingBookingViewSchema = external_exports.object({
|
|
10574
|
+
booking: external_exports.object({
|
|
10575
|
+
id: external_exports.string(),
|
|
10576
|
+
startAt: external_exports.string(),
|
|
10577
|
+
endAt: external_exports.string(),
|
|
10578
|
+
status: schedulingBookingStatusSchema,
|
|
10579
|
+
title: external_exports.string(),
|
|
10580
|
+
notes: external_exports.string().nullable(),
|
|
10581
|
+
/** The conference URL, once there is one. */
|
|
10582
|
+
conferenceLink: external_exports.string().nullable()
|
|
10583
|
+
}),
|
|
10584
|
+
invitee: external_exports.object({ name: external_exports.string(), email: external_exports.string(), timezone: external_exports.string() }).nullable()
|
|
10585
|
+
});
|
|
10586
|
+
var schedulingBookingResultSchema = external_exports.object({
|
|
10587
|
+
bookingId: external_exports.string(),
|
|
10588
|
+
status: schedulingBookingStatusSchema,
|
|
10589
|
+
/**
|
|
10590
|
+
* Three separate signed tokens, deliberately.
|
|
10591
|
+
*
|
|
10592
|
+
* A cancel link in an email must not also be able to reschedule, and
|
|
10593
|
+
* neither should read the whole booking. Handing out one token for all
|
|
10594
|
+
* three would make every emailed link as powerful as the strongest
|
|
10595
|
+
* action it enables.
|
|
10596
|
+
*/
|
|
10597
|
+
manageToken: external_exports.string(),
|
|
10598
|
+
rescheduleToken: external_exports.string(),
|
|
10599
|
+
cancelToken: external_exports.string()
|
|
10600
|
+
}).passthrough();
|
|
10601
|
+
var schedulingRescheduleResultSchema = external_exports.object({
|
|
10602
|
+
bookingId: external_exports.string(),
|
|
10603
|
+
startAt: external_exports.string(),
|
|
10604
|
+
endAt: external_exports.string(),
|
|
10605
|
+
/** Re-minted on reschedule — read it back rather than reusing the old one. */
|
|
10606
|
+
conferenceLink: external_exports.string().nullable().optional()
|
|
10607
|
+
}).passthrough();
|
|
10608
|
+
var schedulingCancelResultSchema = external_exports.object({ ok: external_exports.boolean() }).passthrough();
|
|
10609
|
+
var customerSubscriptionOfferingSchema = external_exports.object({
|
|
10610
|
+
id: external_exports.string(),
|
|
10611
|
+
name: external_exports.string(),
|
|
10612
|
+
description: external_exports.string().nullable(),
|
|
10613
|
+
imageUrl: external_exports.string().nullable(),
|
|
10614
|
+
amountCents: external_exports.number(),
|
|
10615
|
+
interval: external_exports.string()
|
|
10616
|
+
});
|
|
10617
|
+
var customerSubscriptionSchema = external_exports.object({
|
|
10618
|
+
/** active | expired | cancelled | pending | failed */
|
|
10619
|
+
status: openEnum("active", "expired", "cancelled", "pending", "failed"),
|
|
10620
|
+
/** trial | monthly_subscribed | annual_subscribed | lifetime */
|
|
10621
|
+
type: openEnum(
|
|
10622
|
+
"trial",
|
|
10623
|
+
"monthly_subscribed",
|
|
10624
|
+
"annual_subscribed",
|
|
10625
|
+
"lifetime"
|
|
10626
|
+
).nullable(),
|
|
10627
|
+
/**
|
|
10628
|
+
* The entitlement decision, computed server-side by the same function the
|
|
10629
|
+
* content gates use.
|
|
10630
|
+
*
|
|
10631
|
+
* **Render from this, not from `status`.** Two cases break a naive
|
|
10632
|
+
* `status === "active"` check: a lifetime purchase has no period to expire,
|
|
10633
|
+
* and a cancelled subscription keeps access until the period already paid
|
|
10634
|
+
* for runs out.
|
|
10635
|
+
*/
|
|
10636
|
+
hasAccess: external_exports.boolean(),
|
|
10637
|
+
/**
|
|
10638
|
+
* Cancelled, but the paid period has not ended. The honest label is
|
|
10639
|
+
* "active until {expiresAt}" — not "cancelled".
|
|
10640
|
+
*/
|
|
10641
|
+
cancelledButActive: external_exports.boolean(),
|
|
10642
|
+
startedAt: external_exports.string().nullable(),
|
|
10643
|
+
/** End of the paid period. Null for lifetime. */
|
|
10644
|
+
expiresAt: external_exports.string().nullable(),
|
|
10645
|
+
cancelledAt: external_exports.string().nullable(),
|
|
10646
|
+
renewedAt: external_exports.string().nullable(),
|
|
10647
|
+
trialEndsAt: external_exports.string().nullable(),
|
|
10648
|
+
trialUsed: external_exports.boolean(),
|
|
10649
|
+
provider: external_exports.string().nullable(),
|
|
10650
|
+
/** The offering they are on, when it still exists. */
|
|
10651
|
+
plan: customerSubscriptionOfferingSchema.nullable(),
|
|
10652
|
+
/** Null means the plan includes no service calls at all. */
|
|
10653
|
+
includedServiceCallsPerPeriod: external_exports.number().nullable(),
|
|
10654
|
+
serviceCallsUsedInPeriod: external_exports.number(),
|
|
10655
|
+
periodStartedAt: external_exports.string().nullable()
|
|
10656
|
+
});
|
|
10657
|
+
var customerSubscriptionResponseSchema = external_exports.object({
|
|
10658
|
+
/** Null when this customer has never subscribed to this org. */
|
|
10659
|
+
subscription: customerSubscriptionSchema.nullable(),
|
|
10660
|
+
/** The org's live offerings, cheapest first. */
|
|
10661
|
+
offerings: external_exports.array(customerSubscriptionOfferingSchema)
|
|
10662
|
+
});
|
|
10663
|
+
var customerSubscriptionCancelResponseSchema = external_exports.object({
|
|
10664
|
+
/** True when a cancellation is now pending at the end of the period. */
|
|
10665
|
+
cancelAtPeriodEnd: external_exports.boolean(),
|
|
10666
|
+
resumed: external_exports.boolean(),
|
|
10667
|
+
/**
|
|
10668
|
+
* Access continues until this moment. Say "active until {this}", because
|
|
10669
|
+
* that is what is true — cancelling ends the renewal, not the access.
|
|
10670
|
+
*/
|
|
10671
|
+
accessUntil: external_exports.string().nullable(),
|
|
10672
|
+
/**
|
|
10673
|
+
* The stored status still reads its old value until the provider's webhook
|
|
10674
|
+
* lands. Render from `cancelAtPeriodEnd`, not from a re-read.
|
|
10675
|
+
*/
|
|
10676
|
+
statusPending: external_exports.boolean()
|
|
10677
|
+
});
|
|
10678
|
+
var customerSubscriberContentItemSchema = external_exports.object({
|
|
10679
|
+
id: external_exports.string(),
|
|
10680
|
+
slug: external_exports.string(),
|
|
10681
|
+
title: external_exports.string(),
|
|
10682
|
+
/** The pitch. Travels even when locked — the BODY never does. */
|
|
10683
|
+
excerpt: external_exports.string().nullable(),
|
|
10684
|
+
featuredImageUrl: external_exports.string().nullable(),
|
|
10685
|
+
publishedAt: external_exports.string().nullable(),
|
|
10686
|
+
tags: external_exports.array(external_exports.string()),
|
|
10687
|
+
accessLevel: external_exports.string(),
|
|
10688
|
+
downloadAccessLevel: external_exports.string(),
|
|
10689
|
+
/** False when the post is readable but its downloads are not. */
|
|
10690
|
+
downloadsAvailable: external_exports.boolean()
|
|
10691
|
+
});
|
|
10692
|
+
var customerSubscriberContentResponseSchema = external_exports.object({
|
|
10693
|
+
items: external_exports.array(customerSubscriberContentItemSchema),
|
|
10694
|
+
/**
|
|
10695
|
+
* False means these are LOCKED previews, not an empty entitlement. Show
|
|
10696
|
+
* them with the offer — an empty list would hide the pitch at exactly the
|
|
10697
|
+
* moment it is most relevant.
|
|
10698
|
+
*/
|
|
10699
|
+
entitled: external_exports.boolean()
|
|
10700
|
+
});
|
|
10701
|
+
var customerProductReviewSchema = external_exports.object({
|
|
10702
|
+
id: external_exports.string(),
|
|
10703
|
+
productId: external_exports.string(),
|
|
10704
|
+
productName: external_exports.string(),
|
|
10705
|
+
rating: external_exports.number(),
|
|
10706
|
+
content: external_exports.string(),
|
|
10707
|
+
/**
|
|
10708
|
+
* False means QUEUED for the org to approve, not rejected. Surface it as
|
|
10709
|
+
* "awaiting review" — a customer who thinks their review vanished writes it
|
|
10710
|
+
* again, or writes to support.
|
|
10711
|
+
*/
|
|
10712
|
+
isApproved: external_exports.boolean(),
|
|
10713
|
+
createdAt: external_exports.string()
|
|
10714
|
+
});
|
|
10715
|
+
var customerProductReviewListSchema = external_exports.object({
|
|
10716
|
+
items: external_exports.array(customerProductReviewSchema)
|
|
10717
|
+
});
|
|
10718
|
+
var customerProductReviewCreatedSchema = external_exports.object({
|
|
10719
|
+
id: external_exports.string().nullable(),
|
|
10720
|
+
isApproved: external_exports.boolean(),
|
|
10721
|
+
/** The inverse of `isApproved`, named for what the UI should say. */
|
|
10722
|
+
awaitingModeration: external_exports.boolean(),
|
|
10399
10723
|
createdAt: external_exports.string().nullable()
|
|
10400
10724
|
});
|
|
10401
10725
|
var customerDownloadSchema = external_exports.object({
|
|
@@ -10439,6 +10763,75 @@ var siteBrandingSchema = external_exports.object({
|
|
|
10439
10763
|
orgName: external_exports.string().nullable(),
|
|
10440
10764
|
orgIcon: external_exports.string().nullable()
|
|
10441
10765
|
});
|
|
10766
|
+
var customerInvoiceListResponseSchema = external_exports.object({
|
|
10767
|
+
items: external_exports.array(customerInvoiceSummarySchema)
|
|
10768
|
+
});
|
|
10769
|
+
var customerQuoteListResponseSchema = external_exports.object({
|
|
10770
|
+
items: external_exports.array(customerQuoteSummarySchema)
|
|
10771
|
+
});
|
|
10772
|
+
var customerContractListResponseSchema = external_exports.object({
|
|
10773
|
+
items: external_exports.array(customerContractSummarySchema)
|
|
10774
|
+
});
|
|
10775
|
+
var customerShipmentSummarySchema = external_exports.object({
|
|
10776
|
+
id: external_exports.string(),
|
|
10777
|
+
orderId: external_exports.string(),
|
|
10778
|
+
orderNumber: external_exports.string().nullable(),
|
|
10779
|
+
carrier: external_exports.string().nullable(),
|
|
10780
|
+
trackingNumber: external_exports.string().nullable(),
|
|
10781
|
+
trackingUrl: external_exports.string().nullable(),
|
|
10782
|
+
serviceName: external_exports.string().nullable(),
|
|
10783
|
+
status: external_exports.string(),
|
|
10784
|
+
/** A date STRING, not a timestamp — the column is text. */
|
|
10785
|
+
estimatedDelivery: external_exports.string().nullable(),
|
|
10786
|
+
shippedAt: external_exports.string().nullable(),
|
|
10787
|
+
deliveredAt: external_exports.string().nullable()
|
|
10788
|
+
});
|
|
10789
|
+
var customerShipmentListResponseSchema = external_exports.object({
|
|
10790
|
+
items: external_exports.array(customerShipmentSummarySchema)
|
|
10791
|
+
});
|
|
10792
|
+
var customerPortalMessageSchema = external_exports.object({
|
|
10793
|
+
id: external_exports.string(),
|
|
10794
|
+
/** `inbound` = the customer wrote it; `outbound` = staff did. */
|
|
10795
|
+
direction: openEnum("inbound", "outbound"),
|
|
10796
|
+
channel: openEnum("portal", "email", "sms"),
|
|
10797
|
+
authorName: external_exports.string().nullable(),
|
|
10798
|
+
body: external_exports.string(),
|
|
10799
|
+
attachment: external_exports.object({
|
|
10800
|
+
url: external_exports.string(),
|
|
10801
|
+
name: external_exports.string(),
|
|
10802
|
+
mimeType: external_exports.string(),
|
|
10803
|
+
sizeBytes: external_exports.number()
|
|
10804
|
+
}).nullable(),
|
|
10805
|
+
jobId: external_exports.string().nullable(),
|
|
10806
|
+
readByCustomerAt: external_exports.string().nullable(),
|
|
10807
|
+
createdAt: external_exports.string()
|
|
10808
|
+
});
|
|
10809
|
+
var customerPortalMessageListResponseSchema = external_exports.object({
|
|
10810
|
+
items: external_exports.array(customerPortalMessageSchema)
|
|
10811
|
+
});
|
|
10812
|
+
var customerPortalMessagePostInputSchema = external_exports.object({
|
|
10813
|
+
body: external_exports.string().min(1).max(4e3),
|
|
10814
|
+
/** Thread the message under a specific job. */
|
|
10815
|
+
jobId: external_exports.string().uuid().optional()
|
|
10816
|
+
});
|
|
10817
|
+
var customerPortalMessagesMarkReadResponseSchema = external_exports.object({
|
|
10818
|
+
marked: external_exports.number()
|
|
10819
|
+
});
|
|
10820
|
+
var customerReturnRequestStatusSchema = external_exports.object({
|
|
10821
|
+
id: external_exports.string(),
|
|
10822
|
+
/** Mirrors the `order_return_request_status` pg enum. */
|
|
10823
|
+
status: openEnum("requested", "approved", "denied", "refunded", "cancelled"),
|
|
10824
|
+
reason: external_exports.string().nullable(),
|
|
10825
|
+
customerNote: external_exports.string().nullable(),
|
|
10826
|
+
/** Staff's answer. The whole point when a return is denied. */
|
|
10827
|
+
resolutionNote: external_exports.string().nullable(),
|
|
10828
|
+
items: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown())).nullable(),
|
|
10829
|
+
resolvedAt: external_exports.string().nullable(),
|
|
10830
|
+
createdAt: external_exports.string()
|
|
10831
|
+
});
|
|
10832
|
+
var customerReturnRequestListResponseSchema = external_exports.object({
|
|
10833
|
+
items: external_exports.array(customerReturnRequestStatusSchema)
|
|
10834
|
+
});
|
|
10442
10835
|
var customerReviewSummarySchema = external_exports.object({
|
|
10443
10836
|
id: external_exports.string(),
|
|
10444
10837
|
rating: external_exports.number().int(),
|
|
@@ -10489,7 +10882,19 @@ var customerContactCompanyResponseSchema = external_exports.object({
|
|
|
10489
10882
|
var customerJobEtaAssignmentSchema = external_exports.object({
|
|
10490
10883
|
displayName: external_exports.string(),
|
|
10491
10884
|
role: external_exports.string().nullable(),
|
|
10492
|
-
|
|
10885
|
+
/**
|
|
10886
|
+
* This technician's own stage. `openEnum` because the column is TEXT and
|
|
10887
|
+
* an org's board can grow a value before the SDK knows about it — an
|
|
10888
|
+
* unknown status should render as itself, not break the response.
|
|
10889
|
+
*/
|
|
10890
|
+
dispatchStatus: openEnum(
|
|
10891
|
+
"pending",
|
|
10892
|
+
"en_route",
|
|
10893
|
+
"on_site",
|
|
10894
|
+
"in_progress",
|
|
10895
|
+
"completed",
|
|
10896
|
+
"declined"
|
|
10897
|
+
),
|
|
10493
10898
|
lastKnownLocation: external_exports.object({
|
|
10494
10899
|
lat: external_exports.number(),
|
|
10495
10900
|
lng: external_exports.number(),
|
|
@@ -10497,6 +10902,35 @@ var customerJobEtaAssignmentSchema = external_exports.object({
|
|
|
10497
10902
|
}).nullable()
|
|
10498
10903
|
});
|
|
10499
10904
|
var customerJobEtaResponseSchema = external_exports.object({
|
|
10905
|
+
/**
|
|
10906
|
+
* Where the JOB is — promoted from the assignees by the dispatch board,
|
|
10907
|
+
* NOT the same as any one technician's status.
|
|
10908
|
+
*
|
|
10909
|
+
* The promotion rules are why this is returned rather than left to the
|
|
10910
|
+
* consumer: `en_route`/`arrived`/`started` land on the FIRST assignee to
|
|
10911
|
+
* reach them, while `completed` waits for the LAST. Aggregating that
|
|
10912
|
+
* client-side gets it wrong in the direction that tells a customer the work
|
|
10913
|
+
* is finished when one of three techs has packed up.
|
|
10914
|
+
*/
|
|
10915
|
+
dispatchStatus: openEnum(
|
|
10916
|
+
"unscheduled",
|
|
10917
|
+
"scheduled",
|
|
10918
|
+
"en_route",
|
|
10919
|
+
"arrived",
|
|
10920
|
+
"started",
|
|
10921
|
+
"completed"
|
|
10922
|
+
),
|
|
10923
|
+
/**
|
|
10924
|
+
* When each stage happened. A customer reading "en route" wants to know
|
|
10925
|
+
* since when — a status with no timestamp is why people phone to ask.
|
|
10926
|
+
*/
|
|
10927
|
+
timeline: external_exports.object({
|
|
10928
|
+
scheduledStartAt: external_exports.string().nullable(),
|
|
10929
|
+
enRouteAt: external_exports.string().nullable(),
|
|
10930
|
+
arrivedAt: external_exports.string().nullable(),
|
|
10931
|
+
startedAt: external_exports.string().nullable(),
|
|
10932
|
+
completedAt: external_exports.string().nullable()
|
|
10933
|
+
}),
|
|
10500
10934
|
assignments: external_exports.array(customerJobEtaAssignmentSchema),
|
|
10501
10935
|
eta: external_exports.object({
|
|
10502
10936
|
seconds: external_exports.number().nullable(),
|
|
@@ -10636,12 +11070,83 @@ var storefrontProductRowSchema = external_exports.object({
|
|
|
10636
11070
|
/** Resolved category (name/description), when the product is categorized. */
|
|
10637
11071
|
category: storefrontProductCategorySchema.nullable().optional(),
|
|
10638
11072
|
images: external_exports.array(external_exports.string()).nullable().optional(),
|
|
11073
|
+
/**
|
|
11074
|
+
* Web-renderable 3D model — `.glb`, `.gltf`, `.obj` or `.stl`.
|
|
11075
|
+
*
|
|
11076
|
+
* All four fields below are ABSENT (not null) unless the org has the
|
|
11077
|
+
* `ecommerce.product_3d` add-on. Absence is the normal case: most
|
|
11078
|
+
* businesses do not sell anything with a model. Use
|
|
11079
|
+
* `@businessdash/sdk/model3d` to turn these into something renderable.
|
|
11080
|
+
*/
|
|
11081
|
+
model3dUrl: external_exports.string().nullable().optional(),
|
|
11082
|
+
/** Apple AR Quick Look companion, `.usdz`. iOS/iPadOS/visionOS Safari. */
|
|
11083
|
+
model3dUsdzUrl: external_exports.string().nullable().optional(),
|
|
11084
|
+
/**
|
|
11085
|
+
* True when the org attached a CAD file (`.step`/`.iges`/native).
|
|
11086
|
+
*
|
|
11087
|
+
* The URL itself is deliberately NOT here. CAD files are the largest
|
|
11088
|
+
* thing the platform serves and are the org's intellectual property, so
|
|
11089
|
+
* they are issued by `GET storefront/products/{id}/cad`, which requires
|
|
11090
|
+
* cookies, rate-limits the caller and re-checks the entitlement.
|
|
11091
|
+
* Publishing the raw URL in a payload any visitor can fetch would route
|
|
11092
|
+
* around all three.
|
|
11093
|
+
*/
|
|
11094
|
+
model3dCadAvailable: external_exports.boolean().optional(),
|
|
11095
|
+
/** Filename for the download link — "bracket-v3.step". */
|
|
11096
|
+
model3dCadName: external_exports.string().nullable().optional(),
|
|
10639
11097
|
createdAt: external_exports.string()
|
|
10640
11098
|
}).passthrough();
|
|
10641
11099
|
var storefrontListProductsResponseSchema = external_exports.object({
|
|
10642
11100
|
items: external_exports.array(storefrontProductRowSchema),
|
|
10643
11101
|
nextCursor: external_exports.number().nullable()
|
|
10644
11102
|
});
|
|
11103
|
+
var couponSchema = external_exports.object({
|
|
11104
|
+
id: external_exports.string(),
|
|
11105
|
+
code: external_exports.string(),
|
|
11106
|
+
discountType: external_exports.string(),
|
|
11107
|
+
value: external_exports.number(),
|
|
11108
|
+
isActive: external_exports.boolean(),
|
|
11109
|
+
maxUses: external_exports.number().nullable(),
|
|
11110
|
+
usedCount: external_exports.number(),
|
|
11111
|
+
validUntil: external_exports.string().nullable(),
|
|
11112
|
+
stripeCouponId: external_exports.string().nullable(),
|
|
11113
|
+
stripePromotionCodeId: external_exports.string().nullable()
|
|
11114
|
+
});
|
|
11115
|
+
var couponCreateInputSchema = external_exports.object({
|
|
11116
|
+
code: external_exports.string().min(3).max(64),
|
|
11117
|
+
discountType: external_exports.enum(["percent", "amount"]),
|
|
11118
|
+
value: external_exports.number().positive(),
|
|
11119
|
+
validFrom: external_exports.coerce.date().optional(),
|
|
11120
|
+
validUntil: external_exports.coerce.date().nullish(),
|
|
11121
|
+
maxUses: external_exports.number().int().positive().nullish(),
|
|
11122
|
+
isActive: external_exports.boolean().optional(),
|
|
11123
|
+
duration: external_exports.enum(["once", "forever", "repeating"]).optional(),
|
|
11124
|
+
durationInMonths: external_exports.number().int().positive().nullish(),
|
|
11125
|
+
appliesTo: external_exports.enum(["order", "shipping", "both"]).optional()
|
|
11126
|
+
});
|
|
11127
|
+
var couponCreateResponseSchema = external_exports.object({
|
|
11128
|
+
coupon: couponSchema,
|
|
11129
|
+
stripeSynced: external_exports.boolean(),
|
|
11130
|
+
stripeError: external_exports.string().nullable()
|
|
11131
|
+
});
|
|
11132
|
+
var couponListResponseSchema = external_exports.object({
|
|
11133
|
+
coupons: external_exports.array(couponSchema)
|
|
11134
|
+
});
|
|
11135
|
+
var storefrontSyncToStripeResponseSchema = external_exports.object({
|
|
11136
|
+
synced: external_exports.array(
|
|
11137
|
+
external_exports.object({
|
|
11138
|
+
productId: external_exports.string(),
|
|
11139
|
+
stripeProductId: external_exports.string(),
|
|
11140
|
+
/** Variant combinations that got a Stripe Price. */
|
|
11141
|
+
combinationsSynced: external_exports.number()
|
|
11142
|
+
})
|
|
11143
|
+
),
|
|
11144
|
+
failed: external_exports.array(external_exports.object({ productId: external_exports.string(), error: external_exports.string() })),
|
|
11145
|
+
/** Products still unsynced after this call — keep calling until 0. */
|
|
11146
|
+
remaining: external_exports.number(),
|
|
11147
|
+
/** Connected account written to; null means the platform account. */
|
|
11148
|
+
connectedAccountId: external_exports.string().nullable()
|
|
11149
|
+
});
|
|
10645
11150
|
var storefrontProductDetailSchema = storefrontProductRowSchema.and(
|
|
10646
11151
|
external_exports.object({
|
|
10647
11152
|
variants: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown())),
|
|
@@ -11163,6 +11668,8 @@ var bundleCompanySchema = external_exports.object({
|
|
|
11163
11668
|
});
|
|
11164
11669
|
var bundleGalleryItemSchema = external_exports.object({
|
|
11165
11670
|
id: external_exports.string(),
|
|
11671
|
+
/** Sent by the server on every item and dropped here until now. */
|
|
11672
|
+
description: external_exports.string().nullish(),
|
|
11166
11673
|
type: external_exports.enum(["image", "video"]),
|
|
11167
11674
|
src: external_exports.string(),
|
|
11168
11675
|
width: external_exports.number().nullable(),
|
|
@@ -11778,6 +12285,10 @@ var BiabDevClient = class {
|
|
|
11778
12285
|
get shipping() {
|
|
11779
12286
|
return new BiabDevShippingClient(this);
|
|
11780
12287
|
}
|
|
12288
|
+
/** Customer-portal invitations — currently resend. */
|
|
12289
|
+
get customerInvites() {
|
|
12290
|
+
return new BiabDevCustomerInvitesClient(this);
|
|
12291
|
+
}
|
|
11781
12292
|
get notifications() {
|
|
11782
12293
|
return new BiabDevNotificationsClient(this);
|
|
11783
12294
|
}
|
|
@@ -11790,10 +12301,29 @@ var BiabDevClient = class {
|
|
|
11790
12301
|
get reviews() {
|
|
11791
12302
|
return new BiabDevReviewsClient(this);
|
|
11792
12303
|
}
|
|
12304
|
+
/**
|
|
12305
|
+
* Tracking consent for this org's site.
|
|
12306
|
+
*
|
|
12307
|
+
* Pair with `@businessdash/sdk/consent`, which handles the visitor cookie
|
|
12308
|
+
* and gives you a gate to check before starting analytics.
|
|
12309
|
+
*/
|
|
12310
|
+
get consent() {
|
|
12311
|
+
return new BiabDevConsentClient(this);
|
|
12312
|
+
}
|
|
11793
12313
|
/** Public job postings — build a careers page on your own domain. */
|
|
11794
12314
|
get hiring() {
|
|
11795
12315
|
return new BiabDevHiringClient(this);
|
|
11796
12316
|
}
|
|
12317
|
+
/**
|
|
12318
|
+
* The org's published legal pages — privacy, terms, refund policy, whatever
|
|
12319
|
+
* they authored in the dashboard.
|
|
12320
|
+
*
|
|
12321
|
+
* Pair with `@businessdash/sdk/legal` to render them without writing a page
|
|
12322
|
+
* per document.
|
|
12323
|
+
*/
|
|
12324
|
+
get legal() {
|
|
12325
|
+
return new BiabDevLegalClient(this);
|
|
12326
|
+
}
|
|
11797
12327
|
get chatbot() {
|
|
11798
12328
|
return new BiabDevChatbotClient(this);
|
|
11799
12329
|
}
|
|
@@ -11861,6 +12391,7 @@ var BiabDevSiteClient = class {
|
|
|
11861
12391
|
this.client = client;
|
|
11862
12392
|
this.siteId = siteId;
|
|
11863
12393
|
this.collections = new BiabDevCollectionsClient(client, siteId);
|
|
12394
|
+
this.scheduling = new BiabDevSchedulingClient(client, siteId);
|
|
11864
12395
|
this.rows = new BiabDevRowsClient(client, siteId);
|
|
11865
12396
|
this.dataModel = new BiabDevDataModelClient(client, siteId);
|
|
11866
12397
|
this.analytics = new BiabDevAnalyticsClient(client, siteId);
|
|
@@ -11905,6 +12436,14 @@ var BiabDevSiteClient = class {
|
|
|
11905
12436
|
*/
|
|
11906
12437
|
marketing;
|
|
11907
12438
|
parallelPages;
|
|
12439
|
+
/**
|
|
12440
|
+
* Booking and conference calls.
|
|
12441
|
+
*
|
|
12442
|
+
* Previously reachable only through `sdk.ts`'s separate scheduling
|
|
12443
|
+
* resource, which is why the OpenAPI generator — which reads this file —
|
|
12444
|
+
* never saw it, and why no non-JS starter had scheduling at all.
|
|
12445
|
+
*/
|
|
12446
|
+
scheduling;
|
|
11908
12447
|
/**
|
|
11909
12448
|
* The org's storefront branding — logo + favicon (site static media) plus
|
|
11910
12449
|
* the org name + icon. Render the masthead/favicon/og without the org
|
|
@@ -11916,6 +12455,27 @@ var BiabDevSiteClient = class {
|
|
|
11916
12455
|
* <img src={b.logoUrl ?? b.orgIcon ?? ""} alt={b.orgName ?? ""} />
|
|
11917
12456
|
* ```
|
|
11918
12457
|
*/
|
|
12458
|
+
/**
|
|
12459
|
+
* Every URL the PLATFORM owns the shape of, as JSON.
|
|
12460
|
+
*
|
|
12461
|
+
* Published site-builder pages, published legal documents, and every
|
|
12462
|
+
* materialised programmatic-page URL. Blog posts and products are not here
|
|
12463
|
+
* — the platform does not know where your site renders them. Merge those in
|
|
12464
|
+
* with `@businessdash/sdk/sitemap`, which handles the whole job.
|
|
12465
|
+
*
|
|
12466
|
+
* Paths are relative, so you join them against your own origin rather than
|
|
12467
|
+
* the org's primary verified domain.
|
|
12468
|
+
*/
|
|
12469
|
+
async sitemapEntries() {
|
|
12470
|
+
return this.client.request({
|
|
12471
|
+
path: `sites/${encodeURIComponent(this.siteId)}/sitemap-entries`,
|
|
12472
|
+
responseSchema: external_exports.object({
|
|
12473
|
+
entries: external_exports.array(
|
|
12474
|
+
external_exports.object({ loc: external_exports.string(), lastmod: external_exports.string().optional() })
|
|
12475
|
+
)
|
|
12476
|
+
})
|
|
12477
|
+
});
|
|
12478
|
+
}
|
|
11919
12479
|
async branding() {
|
|
11920
12480
|
return this.client.request({
|
|
11921
12481
|
path: `sites/${encodeURIComponent(this.siteId)}/branding`,
|
|
@@ -12548,6 +13108,42 @@ var BiabDevStorefrontClient = class {
|
|
|
12548
13108
|
responseSchema: storefrontSessionResponseSchema
|
|
12549
13109
|
});
|
|
12550
13110
|
}
|
|
13111
|
+
/**
|
|
13112
|
+
* Push your catalog into YOUR OWN Stripe account.
|
|
13113
|
+
*
|
|
13114
|
+
* Products and their variant combinations become Stripe Products and
|
|
13115
|
+
* Prices on the Stripe account connected to your workspace, so you can
|
|
13116
|
+
* manage the catalog here and let Stripe be the system of record for
|
|
13117
|
+
* money. Safe to re-run: an unchanged product is left alone, and a new
|
|
13118
|
+
* Price is minted only when the amount actually changed (Stripe Prices
|
|
13119
|
+
* are immutable on amount).
|
|
13120
|
+
*
|
|
13121
|
+
* Requires a SECRET key holding `storefront:write` — never a publishable
|
|
13122
|
+
* token, because this spends against Stripe on your behalf.
|
|
13123
|
+
*
|
|
13124
|
+
* Pass `productId` to sync one product. Omit it to sync everything not yet
|
|
13125
|
+
* pushed, in bounded batches: check `remaining` and call again until it
|
|
13126
|
+
* reaches 0.
|
|
13127
|
+
*
|
|
13128
|
+
* ```ts
|
|
13129
|
+
* let remaining = 1;
|
|
13130
|
+
* while (remaining > 0) {
|
|
13131
|
+
* const res = await biab.storefront.syncToStripe();
|
|
13132
|
+
* remaining = res.remaining;
|
|
13133
|
+
* }
|
|
13134
|
+
* ```
|
|
13135
|
+
*
|
|
13136
|
+
* Per-product failures are returned in `failed` rather than throwing, so
|
|
13137
|
+
* one bad product doesn't abandon the batch.
|
|
13138
|
+
*/
|
|
13139
|
+
async syncToStripe(input) {
|
|
13140
|
+
return this.client.request({
|
|
13141
|
+
method: "POST",
|
|
13142
|
+
path: "storefront/products/sync-to-stripe",
|
|
13143
|
+
body: input?.productId ? { productId: input.productId } : {},
|
|
13144
|
+
responseSchema: storefrontSyncToStripeResponseSchema
|
|
13145
|
+
});
|
|
13146
|
+
}
|
|
12551
13147
|
/**
|
|
12552
13148
|
* Paginated list of live products for the calling org's storefront.
|
|
12553
13149
|
* Cursor is an opaque integer offset — pass back the response's
|
|
@@ -12602,6 +13198,38 @@ var BiabDevStorefrontClient = class {
|
|
|
12602
13198
|
* via `BiabApiError` if the product isn't live or doesn't belong
|
|
12603
13199
|
* to the org bound to the API key.
|
|
12604
13200
|
*/
|
|
13201
|
+
/**
|
|
13202
|
+
* The CAD file for a product — STEP, IGES, or a native part file.
|
|
13203
|
+
*
|
|
13204
|
+
* ## Call this from YOUR server, then proxy it
|
|
13205
|
+
*
|
|
13206
|
+
* The API key is a server secret, so a browser cannot reach this directly.
|
|
13207
|
+
* Expose your own route (`/api/products/:id/cad`), call this behind it, and
|
|
13208
|
+
* redirect the visitor to the URL it returns.
|
|
13209
|
+
*
|
|
13210
|
+
* The platform withholds the raw URL from every product payload on purpose:
|
|
13211
|
+
* CAD files are the largest thing it serves and are the org's intellectual
|
|
13212
|
+
* property, so a catalog of naked URLs is a design library published to
|
|
13213
|
+
* anyone willing to write a loop. This endpoint requires a `biab_cad` cookie
|
|
13214
|
+
* on the incoming request, rate-limits per IP, and re-checks the
|
|
13215
|
+
* `ecommerce.product_3d` entitlement before answering.
|
|
13216
|
+
*
|
|
13217
|
+
* `cacheSeconds` is what to put on your own response — CAD at a content URL
|
|
13218
|
+
* does not change, so caching hard is where the bandwidth saving comes from.
|
|
13219
|
+
*
|
|
13220
|
+
* Rejects 404 when the product is a draft, has no CAD file, or the org lacks
|
|
13221
|
+
* the add-on. Those are deliberately one answer.
|
|
13222
|
+
*/
|
|
13223
|
+
async getCadDownload(productId) {
|
|
13224
|
+
return this.client.request({
|
|
13225
|
+
path: `storefront/products/${encodeURIComponent(productId)}/cad`,
|
|
13226
|
+
responseSchema: external_exports.object({
|
|
13227
|
+
url: external_exports.string(),
|
|
13228
|
+
fileName: external_exports.string().nullable(),
|
|
13229
|
+
cacheSeconds: external_exports.number()
|
|
13230
|
+
})
|
|
13231
|
+
});
|
|
13232
|
+
}
|
|
12605
13233
|
async getProduct(productId) {
|
|
12606
13234
|
return this.client.request({
|
|
12607
13235
|
path: `storefront/products/${encodeURIComponent(productId)}`,
|
|
@@ -12942,6 +13570,47 @@ var BiabDevCouponsClient = class {
|
|
|
12942
13570
|
* else toast.error(result.message);
|
|
12943
13571
|
* ```
|
|
12944
13572
|
*/
|
|
13573
|
+
/**
|
|
13574
|
+
* Create a coupon and make it live in YOUR OWN Stripe account in one call —
|
|
13575
|
+
* a Stripe Coupon plus a Promotion Code, so the same string works on your
|
|
13576
|
+
* storefront and on Stripe-hosted Checkout.
|
|
13577
|
+
*
|
|
13578
|
+
* Creation and the Stripe sync are one operation deliberately: a coupon
|
|
13579
|
+
* that exists locally but not in Stripe is the failure worth designing out,
|
|
13580
|
+
* where a customer types a code your storefront accepts and Stripe rejects.
|
|
13581
|
+
* If the sync fails the coupon is still created and `stripeSynced` comes
|
|
13582
|
+
* back `false` with the reason, rather than pretending it is live.
|
|
13583
|
+
*
|
|
13584
|
+
* Requires a SECRET key holding `storefront:write`.
|
|
13585
|
+
*
|
|
13586
|
+
* ```ts
|
|
13587
|
+
* const { coupon, stripeSynced } = await biab.coupons.create({
|
|
13588
|
+
* code: 'WELCOME10',
|
|
13589
|
+
* discountType: 'percent',
|
|
13590
|
+
* value: 10,
|
|
13591
|
+
* })
|
|
13592
|
+
* ```
|
|
13593
|
+
*
|
|
13594
|
+
* Buy-X-get-Y and bundle-gift coupons aren't available here — Stripe has no
|
|
13595
|
+
* native BXGY, so those run through our own cart math and need the offer
|
|
13596
|
+
* rows the dashboard collects.
|
|
13597
|
+
*/
|
|
13598
|
+
async create(input) {
|
|
13599
|
+
const body = couponCreateInputSchema.parse(input);
|
|
13600
|
+
return this.client.request({
|
|
13601
|
+
method: "POST",
|
|
13602
|
+
path: "coupons",
|
|
13603
|
+
body,
|
|
13604
|
+
responseSchema: couponCreateResponseSchema
|
|
13605
|
+
});
|
|
13606
|
+
}
|
|
13607
|
+
/** Every coupon on the workspace, newest first. Requires `storefront:write`. */
|
|
13608
|
+
async list() {
|
|
13609
|
+
return this.client.request({
|
|
13610
|
+
path: "coupons",
|
|
13611
|
+
responseSchema: couponListResponseSchema
|
|
13612
|
+
});
|
|
13613
|
+
}
|
|
12945
13614
|
async validate(code) {
|
|
12946
13615
|
const body = couponValidateInputSchema.parse({ code });
|
|
12947
13616
|
return this.client.request({
|
|
@@ -13288,35 +13957,110 @@ var BiabDevHiringClient = class {
|
|
|
13288
13957
|
});
|
|
13289
13958
|
}
|
|
13290
13959
|
};
|
|
13291
|
-
var
|
|
13960
|
+
var BiabDevLegalClient = class {
|
|
13292
13961
|
constructor(client) {
|
|
13293
13962
|
this.client = client;
|
|
13294
13963
|
}
|
|
13295
13964
|
client;
|
|
13296
|
-
/**
|
|
13297
|
-
|
|
13298
|
-
|
|
13299
|
-
|
|
13300
|
-
|
|
13301
|
-
|
|
13302
|
-
|
|
13303
|
-
|
|
13304
|
-
/** Reads the org's persisted chatbot config (system prompt, KB, model). */
|
|
13305
|
-
async getConfig() {
|
|
13965
|
+
/**
|
|
13966
|
+
* Every published document, plus the header/footer presentation.
|
|
13967
|
+
*
|
|
13968
|
+
* Both in one response because the common use — a footer link list — needs
|
|
13969
|
+
* the titles and the presentation together, and a second round trip for the
|
|
13970
|
+
* latter is one a site either makes on every page or skips entirely.
|
|
13971
|
+
*/
|
|
13972
|
+
async list() {
|
|
13306
13973
|
return this.client.request({
|
|
13307
|
-
|
|
13308
|
-
|
|
13309
|
-
responseSchema: chatbotConfigSchema
|
|
13974
|
+
path: "legal",
|
|
13975
|
+
responseSchema: legalListResponseSchema
|
|
13310
13976
|
});
|
|
13311
13977
|
}
|
|
13312
13978
|
/**
|
|
13313
|
-
*
|
|
13314
|
-
*
|
|
13979
|
+
* One document by slug, body included.
|
|
13980
|
+
*
|
|
13981
|
+
* Rejects with a 404 when the slug is unpublished or absent — the two are
|
|
13982
|
+
* deliberately indistinguishable, since "exists but hidden" would leak that
|
|
13983
|
+
* an org is drafting a policy and is not something a caller can act on.
|
|
13315
13984
|
*/
|
|
13316
|
-
async
|
|
13317
|
-
const body = chatbotConfigUpdateInputSchema.parse(input);
|
|
13985
|
+
async get(slug) {
|
|
13318
13986
|
return this.client.request({
|
|
13319
|
-
|
|
13987
|
+
path: `legal/${encodeURIComponent(slug)}`,
|
|
13988
|
+
responseSchema: legalDocumentSchema
|
|
13989
|
+
});
|
|
13990
|
+
}
|
|
13991
|
+
};
|
|
13992
|
+
var consentStateSchema = external_exports.object({
|
|
13993
|
+
/** Categories this org uses at all — one banner row each. */
|
|
13994
|
+
categories: external_exports.array(external_exports.string()),
|
|
13995
|
+
noticeText: external_exports.string().nullable(),
|
|
13996
|
+
noticeVersion: external_exports.number(),
|
|
13997
|
+
/** What may be used right now. */
|
|
13998
|
+
allowed: external_exports.array(external_exports.string()),
|
|
13999
|
+
mustAsk: external_exports.boolean(),
|
|
14000
|
+
reason: external_exports.string()
|
|
14001
|
+
});
|
|
14002
|
+
var BiabDevConsentClient = class {
|
|
14003
|
+
constructor(client) {
|
|
14004
|
+
this.client = client;
|
|
14005
|
+
}
|
|
14006
|
+
client;
|
|
14007
|
+
/** The notice to show, and what this visitor currently allows. */
|
|
14008
|
+
async get(visitorKey) {
|
|
14009
|
+
return this.client.request({
|
|
14010
|
+
path: "consent",
|
|
14011
|
+
responseSchema: consentStateSchema,
|
|
14012
|
+
...visitorKey ? { headers: { "x-biab-visitor": visitorKey } } : {}
|
|
14013
|
+
});
|
|
14014
|
+
}
|
|
14015
|
+
/**
|
|
14016
|
+
* Record the visitor's answer.
|
|
14017
|
+
*
|
|
14018
|
+
* `granted: []` is a real answer — "asked, refused everything" — and is
|
|
14019
|
+
* stored as one, so the banner does not reappear on the next page.
|
|
14020
|
+
*/
|
|
14021
|
+
async record(input) {
|
|
14022
|
+
return this.client.request({
|
|
14023
|
+
method: "POST",
|
|
14024
|
+
path: "consent",
|
|
14025
|
+
body: {
|
|
14026
|
+
granted: input.granted,
|
|
14027
|
+
noticeVersion: input.noticeVersion,
|
|
14028
|
+
source: input.source ?? "banner"
|
|
14029
|
+
},
|
|
14030
|
+
headers: { "x-biab-visitor": input.visitorKey },
|
|
14031
|
+
responseSchema: external_exports.object({ ok: external_exports.boolean() })
|
|
14032
|
+
});
|
|
14033
|
+
}
|
|
14034
|
+
};
|
|
14035
|
+
var BiabDevChatbotClient = class {
|
|
14036
|
+
constructor(client) {
|
|
14037
|
+
this.client = client;
|
|
14038
|
+
}
|
|
14039
|
+
client;
|
|
14040
|
+
/** Returns the iframe URL for `<Chatbot/>`. */
|
|
14041
|
+
async createSession() {
|
|
14042
|
+
return this.client.request({
|
|
14043
|
+
method: "POST",
|
|
14044
|
+
path: "chatbot/session",
|
|
14045
|
+
responseSchema: chatbotSessionResponseSchema
|
|
14046
|
+
});
|
|
14047
|
+
}
|
|
14048
|
+
/** Reads the org's persisted chatbot config (system prompt, KB, model). */
|
|
14049
|
+
async getConfig() {
|
|
14050
|
+
return this.client.request({
|
|
14051
|
+
method: "GET",
|
|
14052
|
+
path: "chatbot/config",
|
|
14053
|
+
responseSchema: chatbotConfigSchema
|
|
14054
|
+
});
|
|
14055
|
+
}
|
|
14056
|
+
/**
|
|
14057
|
+
* Persists the org's chatbot config. Requires `chatbot:write` scope on the
|
|
14058
|
+
* API key — typically only used by admin tools, not embedded widgets.
|
|
14059
|
+
*/
|
|
14060
|
+
async updateConfig(input) {
|
|
14061
|
+
const body = chatbotConfigUpdateInputSchema.parse(input);
|
|
14062
|
+
return this.client.request({
|
|
14063
|
+
method: "PATCH",
|
|
13320
14064
|
path: "chatbot/config",
|
|
13321
14065
|
body,
|
|
13322
14066
|
responseSchema: chatbotConfigSchema
|
|
@@ -13582,6 +14326,23 @@ var BiabDevCustomerPortalClient = class _BiabDevCustomerPortalClient {
|
|
|
13582
14326
|
headers: this.headers()
|
|
13583
14327
|
});
|
|
13584
14328
|
}
|
|
14329
|
+
/**
|
|
14330
|
+
* The signed-in customer's quiz results at this org — the SDK side of
|
|
14331
|
+
* the account-gated reveal: an invitation completed with "create an
|
|
14332
|
+
* account to see how you did" surfaces its result here (and only to
|
|
14333
|
+
* the invited email). Interview-mode quizzes come back with
|
|
14334
|
+
* `scoreWithheld: true` and no verdict, by the org's own setting.
|
|
14335
|
+
*/
|
|
14336
|
+
async myQuizResults(options) {
|
|
14337
|
+
const params = new URLSearchParams();
|
|
14338
|
+
if (options?.token) params.set("token", options.token);
|
|
14339
|
+
const qs = params.toString();
|
|
14340
|
+
return this.client.request({
|
|
14341
|
+
path: `customer-portal/quiz-results${qs ? `?${qs}` : ""}`,
|
|
14342
|
+
responseSchema: customerPortalQuizResultsResponseSchema,
|
|
14343
|
+
headers: this.headers()
|
|
14344
|
+
});
|
|
14345
|
+
}
|
|
13585
14346
|
async updateProfile(input) {
|
|
13586
14347
|
const body = customerPortalUpdateProfileInputSchema.parse(input);
|
|
13587
14348
|
return this.client.request({
|
|
@@ -13854,6 +14615,129 @@ var BiabDevCustomerPortalClient = class _BiabDevCustomerPortalClient {
|
|
|
13854
14615
|
headers: this.headers()
|
|
13855
14616
|
});
|
|
13856
14617
|
}
|
|
14618
|
+
/**
|
|
14619
|
+
* The return requests on one order, newest first.
|
|
14620
|
+
*
|
|
14621
|
+
* `resolutionNote` carries staff's answer — when a return is denied that IS
|
|
14622
|
+
* the answer, and hiding it just moves the question to email.
|
|
14623
|
+
*/
|
|
14624
|
+
async listReturnRequests(orderId) {
|
|
14625
|
+
return this.client.request({
|
|
14626
|
+
path: `customer-portal/orders/${encodeURIComponent(orderId)}/return-request`,
|
|
14627
|
+
responseSchema: customerReturnRequestListResponseSchema,
|
|
14628
|
+
headers: this.headers()
|
|
14629
|
+
});
|
|
14630
|
+
}
|
|
14631
|
+
/**
|
|
14632
|
+
* The customer's message thread with the org's staff, newest first.
|
|
14633
|
+
*
|
|
14634
|
+
* Automated rows — the review-ask and similar — are excluded server-side, so
|
|
14635
|
+
* this is only what a person wrote.
|
|
14636
|
+
*/
|
|
14637
|
+
async listMessages(opts) {
|
|
14638
|
+
const params = new URLSearchParams();
|
|
14639
|
+
if (typeof opts?.limit === "number")
|
|
14640
|
+
params.set("limit", String(opts.limit));
|
|
14641
|
+
if (opts?.jobId) params.set("jobId", opts.jobId);
|
|
14642
|
+
const qs = params.toString();
|
|
14643
|
+
return this.client.request({
|
|
14644
|
+
path: `customer-portal/messages${qs ? `?${qs}` : ""}`,
|
|
14645
|
+
responseSchema: customerPortalMessageListResponseSchema,
|
|
14646
|
+
headers: this.headers()
|
|
14647
|
+
});
|
|
14648
|
+
}
|
|
14649
|
+
/** Send a message to the org's staff. Lands in the CRM timeline. */
|
|
14650
|
+
async postMessage(input) {
|
|
14651
|
+
return this.client.request({
|
|
14652
|
+
path: "customer-portal/messages",
|
|
14653
|
+
method: "POST",
|
|
14654
|
+
body: input,
|
|
14655
|
+
responseSchema: customerPortalMessageSchema,
|
|
14656
|
+
headers: this.headers()
|
|
14657
|
+
});
|
|
14658
|
+
}
|
|
14659
|
+
/**
|
|
14660
|
+
* Mark the staff messages read up to now.
|
|
14661
|
+
*
|
|
14662
|
+
* One-way: it never clears a stamp. A portal that could un-read a message
|
|
14663
|
+
* would let a customer hide from staff that they had seen something.
|
|
14664
|
+
*/
|
|
14665
|
+
async markMessagesRead() {
|
|
14666
|
+
return this.client.request({
|
|
14667
|
+
path: "customer-portal/messages",
|
|
14668
|
+
method: "PATCH",
|
|
14669
|
+
responseSchema: customerPortalMessagesMarkReadResponseSchema,
|
|
14670
|
+
headers: this.headers()
|
|
14671
|
+
});
|
|
14672
|
+
}
|
|
14673
|
+
/**
|
|
14674
|
+
* The customer's invoices, newest first.
|
|
14675
|
+
*
|
|
14676
|
+
* `unpaid: true` filters on the computed BALANCE rather than on the status
|
|
14677
|
+
* string, because a partially-paid invoice still owes money whatever it is
|
|
14678
|
+
* called. This is the call behind "show me everything I owe" — which had no
|
|
14679
|
+
* endpoint at all before 0.9.61.
|
|
14680
|
+
*/
|
|
14681
|
+
async listInvoices(opts) {
|
|
14682
|
+
const params = new URLSearchParams();
|
|
14683
|
+
if (typeof opts?.limit === "number")
|
|
14684
|
+
params.set("limit", String(opts.limit));
|
|
14685
|
+
if (opts?.status) params.set("status", opts.status);
|
|
14686
|
+
if (opts?.unpaid) params.set("unpaid", "1");
|
|
14687
|
+
const qs = params.toString();
|
|
14688
|
+
return this.client.request({
|
|
14689
|
+
path: `customer-portal/invoices${qs ? `?${qs}` : ""}`,
|
|
14690
|
+
responseSchema: customerInvoiceListResponseSchema,
|
|
14691
|
+
headers: this.headers()
|
|
14692
|
+
});
|
|
14693
|
+
}
|
|
14694
|
+
/** The customer's quotes. `status: "sent"` is the set still awaiting them. */
|
|
14695
|
+
async listQuotes(opts) {
|
|
14696
|
+
const params = new URLSearchParams();
|
|
14697
|
+
if (typeof opts?.limit === "number")
|
|
14698
|
+
params.set("limit", String(opts.limit));
|
|
14699
|
+
if (opts?.status) params.set("status", opts.status);
|
|
14700
|
+
const qs = params.toString();
|
|
14701
|
+
return this.client.request({
|
|
14702
|
+
path: `customer-portal/quotes${qs ? `?${qs}` : ""}`,
|
|
14703
|
+
responseSchema: customerQuoteListResponseSchema,
|
|
14704
|
+
headers: this.headers()
|
|
14705
|
+
});
|
|
14706
|
+
}
|
|
14707
|
+
/** The customer's contracts. `status: "sent"` still awaits a signature. */
|
|
14708
|
+
async listContracts(opts) {
|
|
14709
|
+
const params = new URLSearchParams();
|
|
14710
|
+
if (typeof opts?.limit === "number")
|
|
14711
|
+
params.set("limit", String(opts.limit));
|
|
14712
|
+
if (opts?.status) params.set("status", opts.status);
|
|
14713
|
+
const qs = params.toString();
|
|
14714
|
+
return this.client.request({
|
|
14715
|
+
path: `customer-portal/contracts${qs ? `?${qs}` : ""}`,
|
|
14716
|
+
responseSchema: customerContractListResponseSchema,
|
|
14717
|
+
headers: this.headers()
|
|
14718
|
+
});
|
|
14719
|
+
}
|
|
14720
|
+
/**
|
|
14721
|
+
* Every shipment across the customer's orders. `active: true` narrows to
|
|
14722
|
+
* parcels still moving.
|
|
14723
|
+
*
|
|
14724
|
+
* STORED status only — no live carrier poll. `trackShipment(id)` spends a
|
|
14725
|
+
* Shippo request because it is one parcel the customer opened; doing that
|
|
14726
|
+
* per row here would mean a carrier call for every parcel in their history
|
|
14727
|
+
* on every page load.
|
|
14728
|
+
*/
|
|
14729
|
+
async listShipments(opts) {
|
|
14730
|
+
const params = new URLSearchParams();
|
|
14731
|
+
if (typeof opts?.limit === "number")
|
|
14732
|
+
params.set("limit", String(opts.limit));
|
|
14733
|
+
if (opts?.active) params.set("active", "1");
|
|
14734
|
+
const qs = params.toString();
|
|
14735
|
+
return this.client.request({
|
|
14736
|
+
path: `customer-portal/shipments${qs ? `?${qs}` : ""}`,
|
|
14737
|
+
responseSchema: customerShipmentListResponseSchema,
|
|
14738
|
+
headers: this.headers()
|
|
14739
|
+
});
|
|
14740
|
+
}
|
|
13857
14741
|
/**
|
|
13858
14742
|
* The signed-in customer's orders (newest first), each with a shipment
|
|
13859
14743
|
* roll-up (`overallStatus`, `anyInTransit`, `latestEstimatedDelivery`) for
|
|
@@ -13932,6 +14816,243 @@ var BiabDevCustomerPortalClient = class _BiabDevCustomerPortalClient {
|
|
|
13932
14816
|
headers: this.headers()
|
|
13933
14817
|
});
|
|
13934
14818
|
}
|
|
14819
|
+
/**
|
|
14820
|
+
* Ask for a replacement instead of a refund.
|
|
14821
|
+
*
|
|
14822
|
+
* Sugar over `submitReturnRequest` with `kind: "exchange"`, because an
|
|
14823
|
+
* exchange reads as its own action to the person writing the UI, and burying
|
|
14824
|
+
* it in an options bag is how it stays undiscovered. `variantId` is the one
|
|
14825
|
+
* they want instead — omit it when that still needs a conversation.
|
|
14826
|
+
*
|
|
14827
|
+
* @example
|
|
14828
|
+
* ```ts
|
|
14829
|
+
* await portal.submitExchangeRequest(orderId, {
|
|
14830
|
+
* exchangeForVariantId: largeVariantId,
|
|
14831
|
+
* reason: "wrong size",
|
|
14832
|
+
* });
|
|
14833
|
+
* ```
|
|
14834
|
+
*/
|
|
14835
|
+
async submitExchangeRequest(orderId, input) {
|
|
14836
|
+
return this.submitReturnRequest(orderId, {
|
|
14837
|
+
...input ?? {},
|
|
14838
|
+
kind: "exchange"
|
|
14839
|
+
});
|
|
14840
|
+
}
|
|
14841
|
+
/**
|
|
14842
|
+
* Report that a parcel never arrived.
|
|
14843
|
+
*
|
|
14844
|
+
* This does NOT change the shipment's carrier status, and deliberately so:
|
|
14845
|
+
* when the carrier says delivered and the customer says otherwise, both
|
|
14846
|
+
* facts matter — the carrier's scan is what the org files a claim against.
|
|
14847
|
+
* The result carries `carrierStatus` alongside the report so a UI can show
|
|
14848
|
+
* both: *"Carrier says delivered Aug 14 · You reported not received Aug 16."*
|
|
14849
|
+
*
|
|
14850
|
+
* `contested: true` means exactly that disagreement. Re-reporting an open
|
|
14851
|
+
* claim returns it with `alreadyOpen: true` rather than erroring — a
|
|
14852
|
+
* customer tapping twice is anxious, not hostile.
|
|
14853
|
+
*
|
|
14854
|
+
* @example
|
|
14855
|
+
* ```ts
|
|
14856
|
+
* const r = await portal.reportNotReceived(shipmentId, {
|
|
14857
|
+
* note: "Nothing on the porch, checked with neighbours.",
|
|
14858
|
+
* });
|
|
14859
|
+
* if (r.contested) showCarrierDisputeHelp();
|
|
14860
|
+
* ```
|
|
14861
|
+
*/
|
|
14862
|
+
async reportNotReceived(shipmentId, input) {
|
|
14863
|
+
const body = input?.note ? { note: input.note } : {};
|
|
14864
|
+
return this.client.request({
|
|
14865
|
+
method: "POST",
|
|
14866
|
+
path: `customer-portal/shipments/${encodeURIComponent(shipmentId)}/not-received`,
|
|
14867
|
+
body,
|
|
14868
|
+
responseSchema: customerNotReceivedResultSchema,
|
|
14869
|
+
headers: this.headers()
|
|
14870
|
+
});
|
|
14871
|
+
}
|
|
14872
|
+
/**
|
|
14873
|
+
* The product reviews this customer has written for this org.
|
|
14874
|
+
*
|
|
14875
|
+
* Distinct from `listReviews()`, which is reviews of the ORG. Both exist
|
|
14876
|
+
* because "are these people good to deal with" and "is this thing any good"
|
|
14877
|
+
* are different questions, stored in different tables, and shown in
|
|
14878
|
+
* different places.
|
|
14879
|
+
*
|
|
14880
|
+
* `isApproved: false` means QUEUED, not rejected — render it as "awaiting
|
|
14881
|
+
* review" or the customer will assume it was lost and write it again.
|
|
14882
|
+
*/
|
|
14883
|
+
/**
|
|
14884
|
+
* The customer's subscription with this org, and what the org offers.
|
|
14885
|
+
*
|
|
14886
|
+
* One subscription per org — `user_subscriptions` is unique on
|
|
14887
|
+
* (user, org) — so there is no id to pass. The org's live offerings come
|
|
14888
|
+
* back alongside, because a portal that reports "not subscribed" and
|
|
14889
|
+
* nothing else is a dead end.
|
|
14890
|
+
*
|
|
14891
|
+
* **Render entitlement from `subscription.hasAccess`, not from `status`.**
|
|
14892
|
+
* A lifetime purchase has no period to expire and a cancelled subscription
|
|
14893
|
+
* keeps access until the period already paid for ends; `hasAccess` is
|
|
14894
|
+
* computed by the same function the content gates use, so the portal and
|
|
14895
|
+
* the gate cannot disagree.
|
|
14896
|
+
*/
|
|
14897
|
+
async getSubscription() {
|
|
14898
|
+
return this.client.request({
|
|
14899
|
+
path: "customer-portal/subscription",
|
|
14900
|
+
responseSchema: customerSubscriptionResponseSchema,
|
|
14901
|
+
headers: this.headers()
|
|
14902
|
+
});
|
|
14903
|
+
}
|
|
14904
|
+
/**
|
|
14905
|
+
* Cancel the subscription at the end of the paid period.
|
|
14906
|
+
*
|
|
14907
|
+
* Cancelling ends the RENEWAL, not the access: the customer has paid for
|
|
14908
|
+
* the period they are in and keeps everything until `accessUntil`. Ending
|
|
14909
|
+
* access on the click would take back something they already bought, which
|
|
14910
|
+
* is the most common way a subscription flow feels like a trap.
|
|
14911
|
+
*
|
|
14912
|
+
* Read `accessUntil` back to them — "active until 14 March" is the true
|
|
14913
|
+
* statement, not "cancelled".
|
|
14914
|
+
*/
|
|
14915
|
+
async cancelSubscription() {
|
|
14916
|
+
return this.client.request({
|
|
14917
|
+
method: "POST",
|
|
14918
|
+
path: "customer-portal/subscription/cancel",
|
|
14919
|
+
body: { resume: false },
|
|
14920
|
+
responseSchema: customerSubscriptionCancelResponseSchema,
|
|
14921
|
+
headers: this.headers()
|
|
14922
|
+
});
|
|
14923
|
+
}
|
|
14924
|
+
/**
|
|
14925
|
+
* Clear a pending cancellation.
|
|
14926
|
+
*
|
|
14927
|
+
* Between cancelling and the period ending nothing has actually been lost,
|
|
14928
|
+
* so changing your mind should cost one call rather than a re-purchase.
|
|
14929
|
+
* After the period ends there is nothing to resume and they subscribe again
|
|
14930
|
+
* like anyone else.
|
|
14931
|
+
*/
|
|
14932
|
+
async resumeSubscription() {
|
|
14933
|
+
return this.client.request({
|
|
14934
|
+
method: "POST",
|
|
14935
|
+
path: "customer-portal/subscription/cancel",
|
|
14936
|
+
body: { resume: true },
|
|
14937
|
+
responseSchema: customerSubscriptionCancelResponseSchema,
|
|
14938
|
+
headers: this.headers()
|
|
14939
|
+
});
|
|
14940
|
+
}
|
|
14941
|
+
/**
|
|
14942
|
+
* The content this subscription entitles them to — the answer to "what am
|
|
14943
|
+
* I actually getting for this?", which is the question asked right before
|
|
14944
|
+
* someone cancels.
|
|
14945
|
+
*
|
|
14946
|
+
* When `entitled` is false these are LOCKED previews, not an empty
|
|
14947
|
+
* entitlement: titles, excerpts and images, no bodies. Show them beside the
|
|
14948
|
+
* offer. Rendering an empty list would hide the pitch at exactly the moment
|
|
14949
|
+
* it is most relevant.
|
|
14950
|
+
*/
|
|
14951
|
+
async getSubscriberContent(opts) {
|
|
14952
|
+
const params = new URLSearchParams();
|
|
14953
|
+
if (typeof opts?.limit === "number")
|
|
14954
|
+
params.set("limit", String(opts.limit));
|
|
14955
|
+
const qs = params.toString();
|
|
14956
|
+
return this.client.request({
|
|
14957
|
+
path: `customer-portal/subscription/content${qs ? `?${qs}` : ""}`,
|
|
14958
|
+
responseSchema: customerSubscriberContentResponseSchema,
|
|
14959
|
+
headers: this.headers()
|
|
14960
|
+
});
|
|
14961
|
+
}
|
|
14962
|
+
/**
|
|
14963
|
+
* Push config and the browsers this customer has registered.
|
|
14964
|
+
*
|
|
14965
|
+
* Returns `vapidPublicKey` too, because a page cannot subscribe without it.
|
|
14966
|
+
*/
|
|
14967
|
+
async getPushConfig() {
|
|
14968
|
+
return this.client.request({
|
|
14969
|
+
path: "customer-portal/push",
|
|
14970
|
+
responseSchema: customerPushConfigSchema,
|
|
14971
|
+
headers: this.headers()
|
|
14972
|
+
});
|
|
14973
|
+
}
|
|
14974
|
+
/**
|
|
14975
|
+
* Register this browser.
|
|
14976
|
+
*
|
|
14977
|
+
* Pair with `subscribeToPush()` from `@businessdash/sdk/push-core`, which
|
|
14978
|
+
* handles the service worker, the permission prompt and the key encoding
|
|
14979
|
+
* and hands back exactly this payload.
|
|
14980
|
+
*
|
|
14981
|
+
* Upserted on the endpoint, so re-subscribing from the same browser
|
|
14982
|
+
* refreshes the row rather than creating a second one.
|
|
14983
|
+
*/
|
|
14984
|
+
async subscribePush(input) {
|
|
14985
|
+
return this.client.request({
|
|
14986
|
+
method: "POST",
|
|
14987
|
+
path: "customer-portal/push",
|
|
14988
|
+
body: input,
|
|
14989
|
+
responseSchema: external_exports.object({ id: external_exports.string(), created: external_exports.boolean() }),
|
|
14990
|
+
headers: this.headers()
|
|
14991
|
+
});
|
|
14992
|
+
}
|
|
14993
|
+
/**
|
|
14994
|
+
* Rename a device, or narrow what it receives.
|
|
14995
|
+
*
|
|
14996
|
+
* `categories: []` means "nothing for now" and keeps the subscription
|
|
14997
|
+
* warm — browsers make re-granting a revoked permission deliberately
|
|
14998
|
+
* awkward, so an "off" that discards the subscription is hard to undo.
|
|
14999
|
+
*/
|
|
15000
|
+
async updatePushDevice(input) {
|
|
15001
|
+
return this.client.request({
|
|
15002
|
+
method: "PATCH",
|
|
15003
|
+
path: "customer-portal/push",
|
|
15004
|
+
body: input,
|
|
15005
|
+
responseSchema: external_exports.object({ ok: external_exports.boolean() }),
|
|
15006
|
+
headers: this.headers()
|
|
15007
|
+
});
|
|
15008
|
+
}
|
|
15009
|
+
/**
|
|
15010
|
+
* Forget a device. Takes an id or the endpoint.
|
|
15011
|
+
*
|
|
15012
|
+
* A browser tearing its own subscription down knows its endpoint, not our
|
|
15013
|
+
* row id — so pass what `unsubscribeFromPush()` returns.
|
|
15014
|
+
*/
|
|
15015
|
+
async unsubscribePush(input) {
|
|
15016
|
+
return this.client.request({
|
|
15017
|
+
method: "DELETE",
|
|
15018
|
+
path: "customer-portal/push",
|
|
15019
|
+
body: input,
|
|
15020
|
+
responseSchema: external_exports.object({
|
|
15021
|
+
ok: external_exports.boolean(),
|
|
15022
|
+
deletedId: external_exports.string().nullable()
|
|
15023
|
+
}),
|
|
15024
|
+
headers: this.headers()
|
|
15025
|
+
});
|
|
15026
|
+
}
|
|
15027
|
+
async listProductReviews() {
|
|
15028
|
+
return this.client.request({
|
|
15029
|
+
path: "customer-portal/product-reviews",
|
|
15030
|
+
responseSchema: customerProductReviewListSchema,
|
|
15031
|
+
headers: this.headers()
|
|
15032
|
+
});
|
|
15033
|
+
}
|
|
15034
|
+
/**
|
|
15035
|
+
* Review a product this customer BOUGHT.
|
|
15036
|
+
*
|
|
15037
|
+
* The portal requires a matching order — it is standing inside the
|
|
15038
|
+
* customer's purchase history, which is the one thing the public storefront
|
|
15039
|
+
* does not know. That makes these verified-buyer reviews, and it stops a
|
|
15040
|
+
* competitor one-starring a catalogue they never bought.
|
|
15041
|
+
*
|
|
15042
|
+
* Rejects with `not_purchased` (403) when no order matches, and
|
|
15043
|
+
* `already_reviewed` (409) on a second review of the same product.
|
|
15044
|
+
* Moderation follows the ORG's policy, so the result may be
|
|
15045
|
+
* `awaitingModeration`.
|
|
15046
|
+
*/
|
|
15047
|
+
async submitProductReview(input) {
|
|
15048
|
+
return this.client.request({
|
|
15049
|
+
method: "POST",
|
|
15050
|
+
path: "customer-portal/product-reviews",
|
|
15051
|
+
body: input,
|
|
15052
|
+
responseSchema: customerProductReviewCreatedSchema,
|
|
15053
|
+
headers: this.headers()
|
|
15054
|
+
});
|
|
15055
|
+
}
|
|
13935
15056
|
/**
|
|
13936
15057
|
* List the digital downloads the customer is entitled to for a paid order
|
|
13937
15058
|
* (P10d). Each item is a ready-to-use URL — a short-lived presigned link for
|
|
@@ -14027,6 +15148,22 @@ var BiabDevCustomerPortalClient = class _BiabDevCustomerPortalClient {
|
|
|
14027
15148
|
* dispatch travel-time recompute layer ships, at which point the
|
|
14028
15149
|
* `eta` field switches sources without breaking this shape.
|
|
14029
15150
|
*/
|
|
15151
|
+
/**
|
|
15152
|
+
* Where the job and its technicians are in the dispatch lifecycle.
|
|
15153
|
+
*
|
|
15154
|
+
* Named for ETA historically; it is the DISPATCH STATUS surface, which is
|
|
15155
|
+
* why `getDispatchStatus` below is the same call under the name people
|
|
15156
|
+
* look for.
|
|
15157
|
+
*
|
|
15158
|
+
* Read `dispatchStatus` (job-level) for "is anyone on the way" and
|
|
15159
|
+
* `assignments[].dispatchStatus` for per-technician detail. They differ on
|
|
15160
|
+
* purpose: the job is `completed` only once the LAST assignee finishes.
|
|
15161
|
+
*
|
|
15162
|
+
* Nothing about the dispatch CASCADE is exposed — who was offered the job,
|
|
15163
|
+
* who declined, how many people were asked before someone accepted. That
|
|
15164
|
+
* is staff-internal, and a customer learning they were the fourth choice
|
|
15165
|
+
* helps nobody.
|
|
15166
|
+
*/
|
|
14030
15167
|
async getJobEta(jobId) {
|
|
14031
15168
|
return this.client.request({
|
|
14032
15169
|
path: `customer-portal/jobs/${encodeURIComponent(jobId)}/eta`,
|
|
@@ -14034,6 +15171,16 @@ var BiabDevCustomerPortalClient = class _BiabDevCustomerPortalClient {
|
|
|
14034
15171
|
headers: this.headers()
|
|
14035
15172
|
});
|
|
14036
15173
|
}
|
|
15174
|
+
/**
|
|
15175
|
+
* Dispatch status for a job — the same call as `getJobEta`, under the name
|
|
15176
|
+
* developers actually search for.
|
|
15177
|
+
*
|
|
15178
|
+
* An alias rather than a second route: two endpoints returning the same
|
|
15179
|
+
* thing is how they drift.
|
|
15180
|
+
*/
|
|
15181
|
+
async getDispatchStatus(jobId) {
|
|
15182
|
+
return this.getJobEta(jobId);
|
|
15183
|
+
}
|
|
14037
15184
|
/**
|
|
14038
15185
|
* Unified job activity feed: structured events (status changes,
|
|
14039
15186
|
* dispatch lifecycle, media uploads, quote/contract/invoice
|
|
@@ -14139,6 +15286,190 @@ var BiabDevAuthClient = class {
|
|
|
14139
15286
|
});
|
|
14140
15287
|
}
|
|
14141
15288
|
};
|
|
15289
|
+
var BiabDevCustomerInvitesClient = class {
|
|
15290
|
+
constructor(client) {
|
|
15291
|
+
this.client = client;
|
|
15292
|
+
}
|
|
15293
|
+
client;
|
|
15294
|
+
/**
|
|
15295
|
+
* Hand an invite link out again.
|
|
15296
|
+
*
|
|
15297
|
+
* **Rotates the token** — the previous link stops working. That is the
|
|
15298
|
+
* point rather than a side effect: if the reason for resending was "it went
|
|
15299
|
+
* to the wrong address", rotating IS the fix, and reusing the token would
|
|
15300
|
+
* leave the wrong recipient holding a working invitation. The cost is that
|
|
15301
|
+
* someone who finds the original email later gets a dead link, which is a
|
|
15302
|
+
* support message rather than an account.
|
|
15303
|
+
*
|
|
15304
|
+
* Rate limited to one send a minute per invitation, answering **429** with
|
|
15305
|
+
* a retry hint. Resend mails an address the caller chose, so an unbounded
|
|
15306
|
+
* one is a mail-bombing tool. Staff clicking the button in the dashboard
|
|
15307
|
+
* skip the wait; an API key does not, because an API key is the automated
|
|
15308
|
+
* caller the limit exists for.
|
|
15309
|
+
*
|
|
15310
|
+
* Refuses a **revoked** invitation (resending would quietly un-revoke it)
|
|
15311
|
+
* and a **fully-redeemed** one (it did its job; a new invitation should be
|
|
15312
|
+
* created as one, so the list keeps showing what happened).
|
|
15313
|
+
*/
|
|
15314
|
+
async resend(inviteId, opts) {
|
|
15315
|
+
return this.client.request({
|
|
15316
|
+
method: "POST",
|
|
15317
|
+
path: `customer-invites/${encodeURIComponent(inviteId)}/resend`,
|
|
15318
|
+
body: opts?.expiresInDays === void 0 ? {} : { expiresInDays: opts.expiresInDays },
|
|
15319
|
+
responseSchema: customerInviteResendResponseSchema
|
|
15320
|
+
});
|
|
15321
|
+
}
|
|
15322
|
+
};
|
|
15323
|
+
var BiabDevSchedulingClient = class {
|
|
15324
|
+
constructor(client, siteId) {
|
|
15325
|
+
this.client = client;
|
|
15326
|
+
this.siteId = siteId;
|
|
15327
|
+
}
|
|
15328
|
+
client;
|
|
15329
|
+
siteId;
|
|
15330
|
+
path(suffix) {
|
|
15331
|
+
return `sites/${encodeURIComponent(this.siteId)}/scheduling/${suffix}`;
|
|
15332
|
+
}
|
|
15333
|
+
/** What the org offers to book. */
|
|
15334
|
+
async listEventTypes() {
|
|
15335
|
+
return this.client.request({
|
|
15336
|
+
path: this.path("event-types"),
|
|
15337
|
+
responseSchema: schedulingEventTypeListSchema
|
|
15338
|
+
});
|
|
15339
|
+
}
|
|
15340
|
+
/** One event type, plus the questions asked when booking it. */
|
|
15341
|
+
async getEventType(slug) {
|
|
15342
|
+
return this.client.request({
|
|
15343
|
+
path: this.path(`event-types/${encodeURIComponent(slug)}`),
|
|
15344
|
+
responseSchema: schedulingEventTypeDetailSchema
|
|
15345
|
+
});
|
|
15346
|
+
}
|
|
15347
|
+
/**
|
|
15348
|
+
* Free slots in a window.
|
|
15349
|
+
*
|
|
15350
|
+
* Ask for the window you are about to render, not the whole month: slot
|
|
15351
|
+
* computation walks every host's calendar and busy times, so a wide range
|
|
15352
|
+
* is a slow one.
|
|
15353
|
+
*/
|
|
15354
|
+
async getAvailableSlots(slug, params) {
|
|
15355
|
+
const query = new URLSearchParams({
|
|
15356
|
+
from: typeof params.from === "string" ? params.from : params.from.toISOString(),
|
|
15357
|
+
to: typeof params.to === "string" ? params.to : params.to.toISOString()
|
|
15358
|
+
});
|
|
15359
|
+
return this.client.request({
|
|
15360
|
+
path: this.path(
|
|
15361
|
+
`event-types/${encodeURIComponent(slug)}/slots?${query.toString()}`
|
|
15362
|
+
),
|
|
15363
|
+
responseSchema: schedulingSlotsResponseSchema
|
|
15364
|
+
});
|
|
15365
|
+
}
|
|
15366
|
+
/**
|
|
15367
|
+
* Book a slot.
|
|
15368
|
+
*
|
|
15369
|
+
* Returns `pending` rather than `confirmed` when the event type requires
|
|
15370
|
+
* approval — say "requested" in the UI for that case, because telling
|
|
15371
|
+
* someone their meeting is booked when staff still have to accept it is the
|
|
15372
|
+
* kind of thing they plan a day around.
|
|
15373
|
+
*/
|
|
15374
|
+
async confirmBooking(input) {
|
|
15375
|
+
const body = {
|
|
15376
|
+
...input,
|
|
15377
|
+
startAt: typeof input.startAt === "string" ? input.startAt : input.startAt.toISOString()
|
|
15378
|
+
};
|
|
15379
|
+
return this.client.request({
|
|
15380
|
+
method: "POST",
|
|
15381
|
+
path: this.path("bookings"),
|
|
15382
|
+
body,
|
|
15383
|
+
responseSchema: schedulingBookingResultSchema
|
|
15384
|
+
});
|
|
15385
|
+
}
|
|
15386
|
+
/**
|
|
15387
|
+
* Read a booking with one of its signed tokens.
|
|
15388
|
+
*
|
|
15389
|
+
* `type` must match the token you hold — a cancel token will not open the
|
|
15390
|
+
* manage view. That is the point of issuing three.
|
|
15391
|
+
*/
|
|
15392
|
+
async getBooking(token, type = "manage") {
|
|
15393
|
+
return this.client.request({
|
|
15394
|
+
path: this.path(
|
|
15395
|
+
`bookings/by-token/${encodeURIComponent(token)}?type=${encodeURIComponent(type)}`
|
|
15396
|
+
),
|
|
15397
|
+
responseSchema: schedulingBookingViewSchema
|
|
15398
|
+
});
|
|
15399
|
+
}
|
|
15400
|
+
/**
|
|
15401
|
+
* Move a booking — the INVITEE side, with their reschedule token.
|
|
15402
|
+
*
|
|
15403
|
+
* Notifies the invitee and every host, and cancels the reminder jobs queued
|
|
15404
|
+
* against the old time so nobody gets "your meeting starts in 15 minutes"
|
|
15405
|
+
* for a slot that moved.
|
|
15406
|
+
*/
|
|
15407
|
+
async rescheduleBooking(input) {
|
|
15408
|
+
return this.client.request({
|
|
15409
|
+
method: "POST",
|
|
15410
|
+
path: this.path(`bookings/by-token/${encodeURIComponent(input.token)}`),
|
|
15411
|
+
body: {
|
|
15412
|
+
action: "reschedule",
|
|
15413
|
+
newStartAt: typeof input.newStartAt === "string" ? input.newStartAt : input.newStartAt.toISOString(),
|
|
15414
|
+
...input.reason ? { reason: input.reason } : {}
|
|
15415
|
+
},
|
|
15416
|
+
responseSchema: schedulingRescheduleResultSchema
|
|
15417
|
+
});
|
|
15418
|
+
}
|
|
15419
|
+
/**
|
|
15420
|
+
* Move a booking as STAFF, with the API key rather than an invitee token.
|
|
15421
|
+
*
|
|
15422
|
+
* Same service as the token path, so the invitee AND every host are
|
|
15423
|
+
* notified either way, and the reminder jobs for the old time are
|
|
15424
|
+
* cancelled either way. `actorUserId` records WHO moved it, which is what
|
|
15425
|
+
* lets a customer's history say "they rescheduled" rather than leaving an
|
|
15426
|
+
* unexplained change.
|
|
15427
|
+
*/
|
|
15428
|
+
async rescheduleBookingAsStaff(input) {
|
|
15429
|
+
return this.client.request({
|
|
15430
|
+
method: "POST",
|
|
15431
|
+
path: this.path(`bookings/${encodeURIComponent(input.bookingId)}/manage`),
|
|
15432
|
+
body: {
|
|
15433
|
+
action: "reschedule",
|
|
15434
|
+
newStartAt: typeof input.newStartAt === "string" ? input.newStartAt : input.newStartAt.toISOString(),
|
|
15435
|
+
...input.reason ? { reason: input.reason } : {},
|
|
15436
|
+
...input.actorUserId ? { actorUserId: input.actorUserId } : {}
|
|
15437
|
+
},
|
|
15438
|
+
responseSchema: schedulingRescheduleResultSchema
|
|
15439
|
+
});
|
|
15440
|
+
}
|
|
15441
|
+
/** Cancel a booking as STAFF. Notifies the invitee and every host. */
|
|
15442
|
+
async cancelBookingAsStaff(input) {
|
|
15443
|
+
return this.client.request({
|
|
15444
|
+
method: "POST",
|
|
15445
|
+
path: this.path(`bookings/${encodeURIComponent(input.bookingId)}/manage`),
|
|
15446
|
+
body: {
|
|
15447
|
+
action: "cancel",
|
|
15448
|
+
...input.reason ? { reason: input.reason } : {},
|
|
15449
|
+
...input.actorUserId ? { actorUserId: input.actorUserId } : {}
|
|
15450
|
+
},
|
|
15451
|
+
responseSchema: schedulingCancelResultSchema
|
|
15452
|
+
});
|
|
15453
|
+
}
|
|
15454
|
+
/**
|
|
15455
|
+
* Cancel a booking — the INVITEE side, with their cancel token.
|
|
15456
|
+
*
|
|
15457
|
+
* `reason` is passed to the hosts. Worth collecting: "something came up" and
|
|
15458
|
+
* "I booked the wrong service" lead to different follow-ups, and the second
|
|
15459
|
+
* is recoverable revenue.
|
|
15460
|
+
*/
|
|
15461
|
+
async cancelBooking(input) {
|
|
15462
|
+
return this.client.request({
|
|
15463
|
+
method: "POST",
|
|
15464
|
+
path: this.path(`bookings/by-token/${encodeURIComponent(input.token)}`),
|
|
15465
|
+
body: {
|
|
15466
|
+
action: "cancel",
|
|
15467
|
+
...input.reason ? { reason: input.reason } : {}
|
|
15468
|
+
},
|
|
15469
|
+
responseSchema: schedulingCancelResultSchema
|
|
15470
|
+
});
|
|
15471
|
+
}
|
|
15472
|
+
};
|
|
14142
15473
|
|
|
14143
15474
|
// src/auth-handler.ts
|
|
14144
15475
|
var DEFAULT_AUTH_COOKIE_NAME = "biab_session";
|