@businessdash/sdk 0.9.60 → 0.9.70
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 +1012 -186
- 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 +567 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +807 -1
- package/dist/client.js.map +1 -1
- package/dist/contracts.d.ts +3309 -761
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +541 -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 +1244 -5
- 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 +4316 -1313
- package/package.json +121 -9
- 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 +998 -0
- package/src/contracts.ts +730 -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),
|
|
@@ -10342,6 +10367,16 @@ var customerReturnRequestSchema = external_exports.object({
|
|
|
10342
10367
|
* are separate enums and each is spelled as the database spells it.
|
|
10343
10368
|
*/
|
|
10344
10369
|
status: openEnum("requested", "approved", "denied", "refunded", "cancelled"),
|
|
10370
|
+
/**
|
|
10371
|
+
* What was asked for: money back, or a replacement. Mirrors
|
|
10372
|
+
* `order_return_request_kind`. Rows created before this existed read
|
|
10373
|
+
* `refund`, which is what they were.
|
|
10374
|
+
*/
|
|
10375
|
+
kind: openEnum("refund", "exchange"),
|
|
10376
|
+
/** On an exchange: the variant wanted instead, when one was chosen. */
|
|
10377
|
+
exchangeForVariantId: external_exports.string().nullable(),
|
|
10378
|
+
/** Set once a replacement ships — track it like any other shipment. */
|
|
10379
|
+
exchangeShipmentId: external_exports.string().nullable(),
|
|
10345
10380
|
reason: external_exports.string().nullable(),
|
|
10346
10381
|
items: external_exports.array(
|
|
10347
10382
|
external_exports.object({
|
|
@@ -10383,6 +10418,16 @@ var customerOrderDetailSchema = external_exports.object({
|
|
|
10383
10418
|
returnRequests: external_exports.array(customerReturnRequestSchema).optional()
|
|
10384
10419
|
});
|
|
10385
10420
|
var customerReturnRequestInputSchema = external_exports.object({
|
|
10421
|
+
/**
|
|
10422
|
+
* `refund` returns the money; `exchange` asks for a replacement. Defaults
|
|
10423
|
+
* to `refund`, so an omitted field means what it always meant.
|
|
10424
|
+
*/
|
|
10425
|
+
kind: external_exports.enum(["refund", "exchange"]).optional(),
|
|
10426
|
+
/**
|
|
10427
|
+
* On an exchange, the variant wanted instead. Optional even then — "a
|
|
10428
|
+
* different size" is a real request that needs a conversation first.
|
|
10429
|
+
*/
|
|
10430
|
+
exchangeForVariantId: external_exports.string().uuid().optional(),
|
|
10386
10431
|
reason: external_exports.string().max(120).optional(),
|
|
10387
10432
|
customerNote: external_exports.string().max(2e3).optional(),
|
|
10388
10433
|
items: external_exports.array(
|
|
@@ -10396,6 +10441,262 @@ var customerReturnRequestCreatedSchema = external_exports.object({
|
|
|
10396
10441
|
id: external_exports.string().nullable(),
|
|
10397
10442
|
/** Mirrors the `order_return_request_status` pg enum. */
|
|
10398
10443
|
status: openEnum("requested", "approved", "denied", "refunded", "cancelled"),
|
|
10444
|
+
/** Echoes back what was opened, so a UI need not assume. */
|
|
10445
|
+
kind: openEnum("refund", "exchange"),
|
|
10446
|
+
createdAt: external_exports.string().nullable()
|
|
10447
|
+
});
|
|
10448
|
+
var customerNotReceivedResultSchema = external_exports.object({
|
|
10449
|
+
id: external_exports.string(),
|
|
10450
|
+
/** True when a claim was already open; the original report is unchanged. */
|
|
10451
|
+
alreadyOpen: external_exports.boolean(),
|
|
10452
|
+
reportedAt: external_exports.string(),
|
|
10453
|
+
carrierStatus: openEnum(
|
|
10454
|
+
"pending",
|
|
10455
|
+
"label_created",
|
|
10456
|
+
"in_transit",
|
|
10457
|
+
"delivered",
|
|
10458
|
+
"returned"
|
|
10459
|
+
),
|
|
10460
|
+
carrierDeliveredAt: external_exports.string().nullable(),
|
|
10461
|
+
contested: external_exports.boolean().optional()
|
|
10462
|
+
});
|
|
10463
|
+
var legalPresentationSchema = external_exports.object({
|
|
10464
|
+
/** Already resolved against the company logo — render as given. */
|
|
10465
|
+
logoUrl: external_exports.string().nullable(),
|
|
10466
|
+
showLogoInHeader: external_exports.boolean(),
|
|
10467
|
+
showLogoInFooter: external_exports.boolean(),
|
|
10468
|
+
headerHtml: external_exports.string().nullable(),
|
|
10469
|
+
footerHtml: external_exports.string().nullable()
|
|
10470
|
+
});
|
|
10471
|
+
var legalDocumentSummarySchema = external_exports.object({
|
|
10472
|
+
/** The URL path, without a leading slash: `privacy`, `terms`, … */
|
|
10473
|
+
slug: external_exports.string(),
|
|
10474
|
+
title: external_exports.string(),
|
|
10475
|
+
version: external_exports.number(),
|
|
10476
|
+
/** ISO 8601. Render as "Last updated". */
|
|
10477
|
+
effectiveDate: external_exports.string().nullable(),
|
|
10478
|
+
showInFooter: external_exports.boolean(),
|
|
10479
|
+
updatedAt: external_exports.string()
|
|
10480
|
+
});
|
|
10481
|
+
var legalListResponseSchema = external_exports.object({
|
|
10482
|
+
items: external_exports.array(legalDocumentSummarySchema),
|
|
10483
|
+
presentation: legalPresentationSchema
|
|
10484
|
+
});
|
|
10485
|
+
var legalDocumentSchema = legalDocumentSummarySchema.extend({
|
|
10486
|
+
/** Sanitised server-side on write, so this is safe to render as HTML. */
|
|
10487
|
+
contentHtml: external_exports.string(),
|
|
10488
|
+
presentation: legalPresentationSchema
|
|
10489
|
+
});
|
|
10490
|
+
var customerPushDeviceSchema = external_exports.object({
|
|
10491
|
+
id: external_exports.string(),
|
|
10492
|
+
endpoint: external_exports.string(),
|
|
10493
|
+
userAgent: external_exports.string().nullable(),
|
|
10494
|
+
label: external_exports.string().nullable(),
|
|
10495
|
+
/** Null = every category. `[]` = none, but the device stays registered. */
|
|
10496
|
+
categories: external_exports.array(external_exports.string()).nullable(),
|
|
10497
|
+
lastSeenAt: external_exports.string().nullable(),
|
|
10498
|
+
createdAt: external_exports.string()
|
|
10499
|
+
});
|
|
10500
|
+
var customerPushConfigSchema = external_exports.object({
|
|
10501
|
+
vapidPublicKey: external_exports.string().nullable(),
|
|
10502
|
+
enabled: external_exports.boolean(),
|
|
10503
|
+
devices: external_exports.array(customerPushDeviceSchema)
|
|
10504
|
+
});
|
|
10505
|
+
var customerInviteResendResponseSchema = external_exports.object({
|
|
10506
|
+
id: external_exports.string(),
|
|
10507
|
+
/** The NEW link. The previous one no longer works. */
|
|
10508
|
+
url: external_exports.string(),
|
|
10509
|
+
expiresAt: external_exports.string().nullable(),
|
|
10510
|
+
/** Includes this send, so a list can show "sent 3 times". */
|
|
10511
|
+
sendCount: external_exports.number()
|
|
10512
|
+
});
|
|
10513
|
+
var schedulingEventTypeSchema = external_exports.object({
|
|
10514
|
+
id: external_exports.string(),
|
|
10515
|
+
name: external_exports.string(),
|
|
10516
|
+
slug: external_exports.string(),
|
|
10517
|
+
description: external_exports.string().nullable(),
|
|
10518
|
+
durationMinutes: external_exports.number(),
|
|
10519
|
+
locationType: external_exports.string(),
|
|
10520
|
+
/** google_meet | zoom | teams | null when the meeting is in person. */
|
|
10521
|
+
meetingProvider: external_exports.string().nullable(),
|
|
10522
|
+
color: external_exports.string().nullable(),
|
|
10523
|
+
/** When true a booking lands `pending`, not `confirmed`. */
|
|
10524
|
+
requiresApproval: external_exports.boolean()
|
|
10525
|
+
});
|
|
10526
|
+
var schedulingQuestionSchema = external_exports.object({
|
|
10527
|
+
id: external_exports.string(),
|
|
10528
|
+
label: external_exports.string()
|
|
10529
|
+
}).passthrough();
|
|
10530
|
+
var schedulingEventTypeListSchema = external_exports.object({
|
|
10531
|
+
eventTypes: external_exports.array(schedulingEventTypeSchema)
|
|
10532
|
+
});
|
|
10533
|
+
var schedulingEventTypeDetailSchema = external_exports.object({
|
|
10534
|
+
eventType: schedulingEventTypeSchema,
|
|
10535
|
+
questions: external_exports.array(schedulingQuestionSchema)
|
|
10536
|
+
});
|
|
10537
|
+
var schedulingSlotSchema = external_exports.object({
|
|
10538
|
+
startAt: external_exports.string(),
|
|
10539
|
+
endAt: external_exports.string()
|
|
10540
|
+
});
|
|
10541
|
+
var schedulingSlotsResponseSchema = external_exports.object({
|
|
10542
|
+
slots: external_exports.array(schedulingSlotSchema)
|
|
10543
|
+
});
|
|
10544
|
+
var schedulingBookingStatusSchema = openEnum(
|
|
10545
|
+
"pending",
|
|
10546
|
+
"confirmed",
|
|
10547
|
+
"canceled",
|
|
10548
|
+
"rescheduled"
|
|
10549
|
+
);
|
|
10550
|
+
var schedulingBookingViewSchema = external_exports.object({
|
|
10551
|
+
booking: external_exports.object({
|
|
10552
|
+
id: external_exports.string(),
|
|
10553
|
+
startAt: external_exports.string(),
|
|
10554
|
+
endAt: external_exports.string(),
|
|
10555
|
+
status: schedulingBookingStatusSchema,
|
|
10556
|
+
title: external_exports.string(),
|
|
10557
|
+
notes: external_exports.string().nullable(),
|
|
10558
|
+
/** The conference URL, once there is one. */
|
|
10559
|
+
conferenceLink: external_exports.string().nullable()
|
|
10560
|
+
}),
|
|
10561
|
+
invitee: external_exports.object({ name: external_exports.string(), email: external_exports.string(), timezone: external_exports.string() }).nullable()
|
|
10562
|
+
});
|
|
10563
|
+
var schedulingBookingResultSchema = external_exports.object({
|
|
10564
|
+
bookingId: external_exports.string(),
|
|
10565
|
+
status: schedulingBookingStatusSchema,
|
|
10566
|
+
/**
|
|
10567
|
+
* Three separate signed tokens, deliberately.
|
|
10568
|
+
*
|
|
10569
|
+
* A cancel link in an email must not also be able to reschedule, and
|
|
10570
|
+
* neither should read the whole booking. Handing out one token for all
|
|
10571
|
+
* three would make every emailed link as powerful as the strongest
|
|
10572
|
+
* action it enables.
|
|
10573
|
+
*/
|
|
10574
|
+
manageToken: external_exports.string(),
|
|
10575
|
+
rescheduleToken: external_exports.string(),
|
|
10576
|
+
cancelToken: external_exports.string()
|
|
10577
|
+
}).passthrough();
|
|
10578
|
+
var schedulingRescheduleResultSchema = external_exports.object({
|
|
10579
|
+
bookingId: external_exports.string(),
|
|
10580
|
+
startAt: external_exports.string(),
|
|
10581
|
+
endAt: external_exports.string(),
|
|
10582
|
+
/** Re-minted on reschedule — read it back rather than reusing the old one. */
|
|
10583
|
+
conferenceLink: external_exports.string().nullable().optional()
|
|
10584
|
+
}).passthrough();
|
|
10585
|
+
var schedulingCancelResultSchema = external_exports.object({ ok: external_exports.boolean() }).passthrough();
|
|
10586
|
+
var customerSubscriptionOfferingSchema = external_exports.object({
|
|
10587
|
+
id: external_exports.string(),
|
|
10588
|
+
name: external_exports.string(),
|
|
10589
|
+
description: external_exports.string().nullable(),
|
|
10590
|
+
imageUrl: external_exports.string().nullable(),
|
|
10591
|
+
amountCents: external_exports.number(),
|
|
10592
|
+
interval: external_exports.string()
|
|
10593
|
+
});
|
|
10594
|
+
var customerSubscriptionSchema = external_exports.object({
|
|
10595
|
+
/** active | expired | cancelled | pending | failed */
|
|
10596
|
+
status: openEnum("active", "expired", "cancelled", "pending", "failed"),
|
|
10597
|
+
/** trial | monthly_subscribed | annual_subscribed | lifetime */
|
|
10598
|
+
type: openEnum(
|
|
10599
|
+
"trial",
|
|
10600
|
+
"monthly_subscribed",
|
|
10601
|
+
"annual_subscribed",
|
|
10602
|
+
"lifetime"
|
|
10603
|
+
).nullable(),
|
|
10604
|
+
/**
|
|
10605
|
+
* The entitlement decision, computed server-side by the same function the
|
|
10606
|
+
* content gates use.
|
|
10607
|
+
*
|
|
10608
|
+
* **Render from this, not from `status`.** Two cases break a naive
|
|
10609
|
+
* `status === "active"` check: a lifetime purchase has no period to expire,
|
|
10610
|
+
* and a cancelled subscription keeps access until the period already paid
|
|
10611
|
+
* for runs out.
|
|
10612
|
+
*/
|
|
10613
|
+
hasAccess: external_exports.boolean(),
|
|
10614
|
+
/**
|
|
10615
|
+
* Cancelled, but the paid period has not ended. The honest label is
|
|
10616
|
+
* "active until {expiresAt}" — not "cancelled".
|
|
10617
|
+
*/
|
|
10618
|
+
cancelledButActive: external_exports.boolean(),
|
|
10619
|
+
startedAt: external_exports.string().nullable(),
|
|
10620
|
+
/** End of the paid period. Null for lifetime. */
|
|
10621
|
+
expiresAt: external_exports.string().nullable(),
|
|
10622
|
+
cancelledAt: external_exports.string().nullable(),
|
|
10623
|
+
renewedAt: external_exports.string().nullable(),
|
|
10624
|
+
trialEndsAt: external_exports.string().nullable(),
|
|
10625
|
+
trialUsed: external_exports.boolean(),
|
|
10626
|
+
provider: external_exports.string().nullable(),
|
|
10627
|
+
/** The offering they are on, when it still exists. */
|
|
10628
|
+
plan: customerSubscriptionOfferingSchema.nullable(),
|
|
10629
|
+
/** Null means the plan includes no service calls at all. */
|
|
10630
|
+
includedServiceCallsPerPeriod: external_exports.number().nullable(),
|
|
10631
|
+
serviceCallsUsedInPeriod: external_exports.number(),
|
|
10632
|
+
periodStartedAt: external_exports.string().nullable()
|
|
10633
|
+
});
|
|
10634
|
+
var customerSubscriptionResponseSchema = external_exports.object({
|
|
10635
|
+
/** Null when this customer has never subscribed to this org. */
|
|
10636
|
+
subscription: customerSubscriptionSchema.nullable(),
|
|
10637
|
+
/** The org's live offerings, cheapest first. */
|
|
10638
|
+
offerings: external_exports.array(customerSubscriptionOfferingSchema)
|
|
10639
|
+
});
|
|
10640
|
+
var customerSubscriptionCancelResponseSchema = external_exports.object({
|
|
10641
|
+
/** True when a cancellation is now pending at the end of the period. */
|
|
10642
|
+
cancelAtPeriodEnd: external_exports.boolean(),
|
|
10643
|
+
resumed: external_exports.boolean(),
|
|
10644
|
+
/**
|
|
10645
|
+
* Access continues until this moment. Say "active until {this}", because
|
|
10646
|
+
* that is what is true — cancelling ends the renewal, not the access.
|
|
10647
|
+
*/
|
|
10648
|
+
accessUntil: external_exports.string().nullable(),
|
|
10649
|
+
/**
|
|
10650
|
+
* The stored status still reads its old value until the provider's webhook
|
|
10651
|
+
* lands. Render from `cancelAtPeriodEnd`, not from a re-read.
|
|
10652
|
+
*/
|
|
10653
|
+
statusPending: external_exports.boolean()
|
|
10654
|
+
});
|
|
10655
|
+
var customerSubscriberContentItemSchema = external_exports.object({
|
|
10656
|
+
id: external_exports.string(),
|
|
10657
|
+
slug: external_exports.string(),
|
|
10658
|
+
title: external_exports.string(),
|
|
10659
|
+
/** The pitch. Travels even when locked — the BODY never does. */
|
|
10660
|
+
excerpt: external_exports.string().nullable(),
|
|
10661
|
+
featuredImageUrl: external_exports.string().nullable(),
|
|
10662
|
+
publishedAt: external_exports.string().nullable(),
|
|
10663
|
+
tags: external_exports.array(external_exports.string()),
|
|
10664
|
+
accessLevel: external_exports.string(),
|
|
10665
|
+
downloadAccessLevel: external_exports.string(),
|
|
10666
|
+
/** False when the post is readable but its downloads are not. */
|
|
10667
|
+
downloadsAvailable: external_exports.boolean()
|
|
10668
|
+
});
|
|
10669
|
+
var customerSubscriberContentResponseSchema = external_exports.object({
|
|
10670
|
+
items: external_exports.array(customerSubscriberContentItemSchema),
|
|
10671
|
+
/**
|
|
10672
|
+
* False means these are LOCKED previews, not an empty entitlement. Show
|
|
10673
|
+
* them with the offer — an empty list would hide the pitch at exactly the
|
|
10674
|
+
* moment it is most relevant.
|
|
10675
|
+
*/
|
|
10676
|
+
entitled: external_exports.boolean()
|
|
10677
|
+
});
|
|
10678
|
+
var customerProductReviewSchema = external_exports.object({
|
|
10679
|
+
id: external_exports.string(),
|
|
10680
|
+
productId: external_exports.string(),
|
|
10681
|
+
productName: external_exports.string(),
|
|
10682
|
+
rating: external_exports.number(),
|
|
10683
|
+
content: external_exports.string(),
|
|
10684
|
+
/**
|
|
10685
|
+
* False means QUEUED for the org to approve, not rejected. Surface it as
|
|
10686
|
+
* "awaiting review" — a customer who thinks their review vanished writes it
|
|
10687
|
+
* again, or writes to support.
|
|
10688
|
+
*/
|
|
10689
|
+
isApproved: external_exports.boolean(),
|
|
10690
|
+
createdAt: external_exports.string()
|
|
10691
|
+
});
|
|
10692
|
+
var customerProductReviewListSchema = external_exports.object({
|
|
10693
|
+
items: external_exports.array(customerProductReviewSchema)
|
|
10694
|
+
});
|
|
10695
|
+
var customerProductReviewCreatedSchema = external_exports.object({
|
|
10696
|
+
id: external_exports.string().nullable(),
|
|
10697
|
+
isApproved: external_exports.boolean(),
|
|
10698
|
+
/** The inverse of `isApproved`, named for what the UI should say. */
|
|
10699
|
+
awaitingModeration: external_exports.boolean(),
|
|
10399
10700
|
createdAt: external_exports.string().nullable()
|
|
10400
10701
|
});
|
|
10401
10702
|
var customerDownloadSchema = external_exports.object({
|
|
@@ -10439,6 +10740,75 @@ var siteBrandingSchema = external_exports.object({
|
|
|
10439
10740
|
orgName: external_exports.string().nullable(),
|
|
10440
10741
|
orgIcon: external_exports.string().nullable()
|
|
10441
10742
|
});
|
|
10743
|
+
var customerInvoiceListResponseSchema = external_exports.object({
|
|
10744
|
+
items: external_exports.array(customerInvoiceSummarySchema)
|
|
10745
|
+
});
|
|
10746
|
+
var customerQuoteListResponseSchema = external_exports.object({
|
|
10747
|
+
items: external_exports.array(customerQuoteSummarySchema)
|
|
10748
|
+
});
|
|
10749
|
+
var customerContractListResponseSchema = external_exports.object({
|
|
10750
|
+
items: external_exports.array(customerContractSummarySchema)
|
|
10751
|
+
});
|
|
10752
|
+
var customerShipmentSummarySchema = external_exports.object({
|
|
10753
|
+
id: external_exports.string(),
|
|
10754
|
+
orderId: external_exports.string(),
|
|
10755
|
+
orderNumber: external_exports.string().nullable(),
|
|
10756
|
+
carrier: external_exports.string().nullable(),
|
|
10757
|
+
trackingNumber: external_exports.string().nullable(),
|
|
10758
|
+
trackingUrl: external_exports.string().nullable(),
|
|
10759
|
+
serviceName: external_exports.string().nullable(),
|
|
10760
|
+
status: external_exports.string(),
|
|
10761
|
+
/** A date STRING, not a timestamp — the column is text. */
|
|
10762
|
+
estimatedDelivery: external_exports.string().nullable(),
|
|
10763
|
+
shippedAt: external_exports.string().nullable(),
|
|
10764
|
+
deliveredAt: external_exports.string().nullable()
|
|
10765
|
+
});
|
|
10766
|
+
var customerShipmentListResponseSchema = external_exports.object({
|
|
10767
|
+
items: external_exports.array(customerShipmentSummarySchema)
|
|
10768
|
+
});
|
|
10769
|
+
var customerPortalMessageSchema = external_exports.object({
|
|
10770
|
+
id: external_exports.string(),
|
|
10771
|
+
/** `inbound` = the customer wrote it; `outbound` = staff did. */
|
|
10772
|
+
direction: openEnum("inbound", "outbound"),
|
|
10773
|
+
channel: openEnum("portal", "email", "sms"),
|
|
10774
|
+
authorName: external_exports.string().nullable(),
|
|
10775
|
+
body: external_exports.string(),
|
|
10776
|
+
attachment: external_exports.object({
|
|
10777
|
+
url: external_exports.string(),
|
|
10778
|
+
name: external_exports.string(),
|
|
10779
|
+
mimeType: external_exports.string(),
|
|
10780
|
+
sizeBytes: external_exports.number()
|
|
10781
|
+
}).nullable(),
|
|
10782
|
+
jobId: external_exports.string().nullable(),
|
|
10783
|
+
readByCustomerAt: external_exports.string().nullable(),
|
|
10784
|
+
createdAt: external_exports.string()
|
|
10785
|
+
});
|
|
10786
|
+
var customerPortalMessageListResponseSchema = external_exports.object({
|
|
10787
|
+
items: external_exports.array(customerPortalMessageSchema)
|
|
10788
|
+
});
|
|
10789
|
+
var customerPortalMessagePostInputSchema = external_exports.object({
|
|
10790
|
+
body: external_exports.string().min(1).max(4e3),
|
|
10791
|
+
/** Thread the message under a specific job. */
|
|
10792
|
+
jobId: external_exports.string().uuid().optional()
|
|
10793
|
+
});
|
|
10794
|
+
var customerPortalMessagesMarkReadResponseSchema = external_exports.object({
|
|
10795
|
+
marked: external_exports.number()
|
|
10796
|
+
});
|
|
10797
|
+
var customerReturnRequestStatusSchema = external_exports.object({
|
|
10798
|
+
id: external_exports.string(),
|
|
10799
|
+
/** Mirrors the `order_return_request_status` pg enum. */
|
|
10800
|
+
status: openEnum("requested", "approved", "denied", "refunded", "cancelled"),
|
|
10801
|
+
reason: external_exports.string().nullable(),
|
|
10802
|
+
customerNote: external_exports.string().nullable(),
|
|
10803
|
+
/** Staff's answer. The whole point when a return is denied. */
|
|
10804
|
+
resolutionNote: external_exports.string().nullable(),
|
|
10805
|
+
items: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown())).nullable(),
|
|
10806
|
+
resolvedAt: external_exports.string().nullable(),
|
|
10807
|
+
createdAt: external_exports.string()
|
|
10808
|
+
});
|
|
10809
|
+
var customerReturnRequestListResponseSchema = external_exports.object({
|
|
10810
|
+
items: external_exports.array(customerReturnRequestStatusSchema)
|
|
10811
|
+
});
|
|
10442
10812
|
var customerReviewSummarySchema = external_exports.object({
|
|
10443
10813
|
id: external_exports.string(),
|
|
10444
10814
|
rating: external_exports.number().int(),
|
|
@@ -10489,7 +10859,19 @@ var customerContactCompanyResponseSchema = external_exports.object({
|
|
|
10489
10859
|
var customerJobEtaAssignmentSchema = external_exports.object({
|
|
10490
10860
|
displayName: external_exports.string(),
|
|
10491
10861
|
role: external_exports.string().nullable(),
|
|
10492
|
-
|
|
10862
|
+
/**
|
|
10863
|
+
* This technician's own stage. `openEnum` because the column is TEXT and
|
|
10864
|
+
* an org's board can grow a value before the SDK knows about it — an
|
|
10865
|
+
* unknown status should render as itself, not break the response.
|
|
10866
|
+
*/
|
|
10867
|
+
dispatchStatus: openEnum(
|
|
10868
|
+
"pending",
|
|
10869
|
+
"en_route",
|
|
10870
|
+
"on_site",
|
|
10871
|
+
"in_progress",
|
|
10872
|
+
"completed",
|
|
10873
|
+
"declined"
|
|
10874
|
+
),
|
|
10493
10875
|
lastKnownLocation: external_exports.object({
|
|
10494
10876
|
lat: external_exports.number(),
|
|
10495
10877
|
lng: external_exports.number(),
|
|
@@ -10497,6 +10879,35 @@ var customerJobEtaAssignmentSchema = external_exports.object({
|
|
|
10497
10879
|
}).nullable()
|
|
10498
10880
|
});
|
|
10499
10881
|
var customerJobEtaResponseSchema = external_exports.object({
|
|
10882
|
+
/**
|
|
10883
|
+
* Where the JOB is — promoted from the assignees by the dispatch board,
|
|
10884
|
+
* NOT the same as any one technician's status.
|
|
10885
|
+
*
|
|
10886
|
+
* The promotion rules are why this is returned rather than left to the
|
|
10887
|
+
* consumer: `en_route`/`arrived`/`started` land on the FIRST assignee to
|
|
10888
|
+
* reach them, while `completed` waits for the LAST. Aggregating that
|
|
10889
|
+
* client-side gets it wrong in the direction that tells a customer the work
|
|
10890
|
+
* is finished when one of three techs has packed up.
|
|
10891
|
+
*/
|
|
10892
|
+
dispatchStatus: openEnum(
|
|
10893
|
+
"unscheduled",
|
|
10894
|
+
"scheduled",
|
|
10895
|
+
"en_route",
|
|
10896
|
+
"arrived",
|
|
10897
|
+
"started",
|
|
10898
|
+
"completed"
|
|
10899
|
+
),
|
|
10900
|
+
/**
|
|
10901
|
+
* When each stage happened. A customer reading "en route" wants to know
|
|
10902
|
+
* since when — a status with no timestamp is why people phone to ask.
|
|
10903
|
+
*/
|
|
10904
|
+
timeline: external_exports.object({
|
|
10905
|
+
scheduledStartAt: external_exports.string().nullable(),
|
|
10906
|
+
enRouteAt: external_exports.string().nullable(),
|
|
10907
|
+
arrivedAt: external_exports.string().nullable(),
|
|
10908
|
+
startedAt: external_exports.string().nullable(),
|
|
10909
|
+
completedAt: external_exports.string().nullable()
|
|
10910
|
+
}),
|
|
10500
10911
|
assignments: external_exports.array(customerJobEtaAssignmentSchema),
|
|
10501
10912
|
eta: external_exports.object({
|
|
10502
10913
|
seconds: external_exports.number().nullable(),
|
|
@@ -10636,12 +11047,83 @@ var storefrontProductRowSchema = external_exports.object({
|
|
|
10636
11047
|
/** Resolved category (name/description), when the product is categorized. */
|
|
10637
11048
|
category: storefrontProductCategorySchema.nullable().optional(),
|
|
10638
11049
|
images: external_exports.array(external_exports.string()).nullable().optional(),
|
|
11050
|
+
/**
|
|
11051
|
+
* Web-renderable 3D model — `.glb`, `.gltf`, `.obj` or `.stl`.
|
|
11052
|
+
*
|
|
11053
|
+
* All four fields below are ABSENT (not null) unless the org has the
|
|
11054
|
+
* `ecommerce.product_3d` add-on. Absence is the normal case: most
|
|
11055
|
+
* businesses do not sell anything with a model. Use
|
|
11056
|
+
* `@businessdash/sdk/model3d` to turn these into something renderable.
|
|
11057
|
+
*/
|
|
11058
|
+
model3dUrl: external_exports.string().nullable().optional(),
|
|
11059
|
+
/** Apple AR Quick Look companion, `.usdz`. iOS/iPadOS/visionOS Safari. */
|
|
11060
|
+
model3dUsdzUrl: external_exports.string().nullable().optional(),
|
|
11061
|
+
/**
|
|
11062
|
+
* True when the org attached a CAD file (`.step`/`.iges`/native).
|
|
11063
|
+
*
|
|
11064
|
+
* The URL itself is deliberately NOT here. CAD files are the largest
|
|
11065
|
+
* thing the platform serves and are the org's intellectual property, so
|
|
11066
|
+
* they are issued by `GET storefront/products/{id}/cad`, which requires
|
|
11067
|
+
* cookies, rate-limits the caller and re-checks the entitlement.
|
|
11068
|
+
* Publishing the raw URL in a payload any visitor can fetch would route
|
|
11069
|
+
* around all three.
|
|
11070
|
+
*/
|
|
11071
|
+
model3dCadAvailable: external_exports.boolean().optional(),
|
|
11072
|
+
/** Filename for the download link — "bracket-v3.step". */
|
|
11073
|
+
model3dCadName: external_exports.string().nullable().optional(),
|
|
10639
11074
|
createdAt: external_exports.string()
|
|
10640
11075
|
}).passthrough();
|
|
10641
11076
|
var storefrontListProductsResponseSchema = external_exports.object({
|
|
10642
11077
|
items: external_exports.array(storefrontProductRowSchema),
|
|
10643
11078
|
nextCursor: external_exports.number().nullable()
|
|
10644
11079
|
});
|
|
11080
|
+
var couponSchema = external_exports.object({
|
|
11081
|
+
id: external_exports.string(),
|
|
11082
|
+
code: external_exports.string(),
|
|
11083
|
+
discountType: external_exports.string(),
|
|
11084
|
+
value: external_exports.number(),
|
|
11085
|
+
isActive: external_exports.boolean(),
|
|
11086
|
+
maxUses: external_exports.number().nullable(),
|
|
11087
|
+
usedCount: external_exports.number(),
|
|
11088
|
+
validUntil: external_exports.string().nullable(),
|
|
11089
|
+
stripeCouponId: external_exports.string().nullable(),
|
|
11090
|
+
stripePromotionCodeId: external_exports.string().nullable()
|
|
11091
|
+
});
|
|
11092
|
+
var couponCreateInputSchema = external_exports.object({
|
|
11093
|
+
code: external_exports.string().min(3).max(64),
|
|
11094
|
+
discountType: external_exports.enum(["percent", "amount"]),
|
|
11095
|
+
value: external_exports.number().positive(),
|
|
11096
|
+
validFrom: external_exports.coerce.date().optional(),
|
|
11097
|
+
validUntil: external_exports.coerce.date().nullish(),
|
|
11098
|
+
maxUses: external_exports.number().int().positive().nullish(),
|
|
11099
|
+
isActive: external_exports.boolean().optional(),
|
|
11100
|
+
duration: external_exports.enum(["once", "forever", "repeating"]).optional(),
|
|
11101
|
+
durationInMonths: external_exports.number().int().positive().nullish(),
|
|
11102
|
+
appliesTo: external_exports.enum(["order", "shipping", "both"]).optional()
|
|
11103
|
+
});
|
|
11104
|
+
var couponCreateResponseSchema = external_exports.object({
|
|
11105
|
+
coupon: couponSchema,
|
|
11106
|
+
stripeSynced: external_exports.boolean(),
|
|
11107
|
+
stripeError: external_exports.string().nullable()
|
|
11108
|
+
});
|
|
11109
|
+
var couponListResponseSchema = external_exports.object({
|
|
11110
|
+
coupons: external_exports.array(couponSchema)
|
|
11111
|
+
});
|
|
11112
|
+
var storefrontSyncToStripeResponseSchema = external_exports.object({
|
|
11113
|
+
synced: external_exports.array(
|
|
11114
|
+
external_exports.object({
|
|
11115
|
+
productId: external_exports.string(),
|
|
11116
|
+
stripeProductId: external_exports.string(),
|
|
11117
|
+
/** Variant combinations that got a Stripe Price. */
|
|
11118
|
+
combinationsSynced: external_exports.number()
|
|
11119
|
+
})
|
|
11120
|
+
),
|
|
11121
|
+
failed: external_exports.array(external_exports.object({ productId: external_exports.string(), error: external_exports.string() })),
|
|
11122
|
+
/** Products still unsynced after this call — keep calling until 0. */
|
|
11123
|
+
remaining: external_exports.number(),
|
|
11124
|
+
/** Connected account written to; null means the platform account. */
|
|
11125
|
+
connectedAccountId: external_exports.string().nullable()
|
|
11126
|
+
});
|
|
10645
11127
|
var storefrontProductDetailSchema = storefrontProductRowSchema.and(
|
|
10646
11128
|
external_exports.object({
|
|
10647
11129
|
variants: external_exports.array(external_exports.record(external_exports.string(), external_exports.unknown())),
|
|
@@ -11163,6 +11645,8 @@ var bundleCompanySchema = external_exports.object({
|
|
|
11163
11645
|
});
|
|
11164
11646
|
var bundleGalleryItemSchema = external_exports.object({
|
|
11165
11647
|
id: external_exports.string(),
|
|
11648
|
+
/** Sent by the server on every item and dropped here until now. */
|
|
11649
|
+
description: external_exports.string().nullish(),
|
|
11166
11650
|
type: external_exports.enum(["image", "video"]),
|
|
11167
11651
|
src: external_exports.string(),
|
|
11168
11652
|
width: external_exports.number().nullable(),
|
|
@@ -11778,6 +12262,10 @@ var BiabDevClient = class {
|
|
|
11778
12262
|
get shipping() {
|
|
11779
12263
|
return new BiabDevShippingClient(this);
|
|
11780
12264
|
}
|
|
12265
|
+
/** Customer-portal invitations — currently resend. */
|
|
12266
|
+
get customerInvites() {
|
|
12267
|
+
return new BiabDevCustomerInvitesClient(this);
|
|
12268
|
+
}
|
|
11781
12269
|
get notifications() {
|
|
11782
12270
|
return new BiabDevNotificationsClient(this);
|
|
11783
12271
|
}
|
|
@@ -11794,6 +12282,16 @@ var BiabDevClient = class {
|
|
|
11794
12282
|
get hiring() {
|
|
11795
12283
|
return new BiabDevHiringClient(this);
|
|
11796
12284
|
}
|
|
12285
|
+
/**
|
|
12286
|
+
* The org's published legal pages — privacy, terms, refund policy, whatever
|
|
12287
|
+
* they authored in the dashboard.
|
|
12288
|
+
*
|
|
12289
|
+
* Pair with `@businessdash/sdk/legal` to render them without writing a page
|
|
12290
|
+
* per document.
|
|
12291
|
+
*/
|
|
12292
|
+
get legal() {
|
|
12293
|
+
return new BiabDevLegalClient(this);
|
|
12294
|
+
}
|
|
11797
12295
|
get chatbot() {
|
|
11798
12296
|
return new BiabDevChatbotClient(this);
|
|
11799
12297
|
}
|
|
@@ -11861,6 +12359,7 @@ var BiabDevSiteClient = class {
|
|
|
11861
12359
|
this.client = client;
|
|
11862
12360
|
this.siteId = siteId;
|
|
11863
12361
|
this.collections = new BiabDevCollectionsClient(client, siteId);
|
|
12362
|
+
this.scheduling = new BiabDevSchedulingClient(client, siteId);
|
|
11864
12363
|
this.rows = new BiabDevRowsClient(client, siteId);
|
|
11865
12364
|
this.dataModel = new BiabDevDataModelClient(client, siteId);
|
|
11866
12365
|
this.analytics = new BiabDevAnalyticsClient(client, siteId);
|
|
@@ -11905,6 +12404,14 @@ var BiabDevSiteClient = class {
|
|
|
11905
12404
|
*/
|
|
11906
12405
|
marketing;
|
|
11907
12406
|
parallelPages;
|
|
12407
|
+
/**
|
|
12408
|
+
* Booking and conference calls.
|
|
12409
|
+
*
|
|
12410
|
+
* Previously reachable only through `sdk.ts`'s separate scheduling
|
|
12411
|
+
* resource, which is why the OpenAPI generator — which reads this file —
|
|
12412
|
+
* never saw it, and why no non-JS starter had scheduling at all.
|
|
12413
|
+
*/
|
|
12414
|
+
scheduling;
|
|
11908
12415
|
/**
|
|
11909
12416
|
* The org's storefront branding — logo + favicon (site static media) plus
|
|
11910
12417
|
* the org name + icon. Render the masthead/favicon/og without the org
|
|
@@ -11916,6 +12423,27 @@ var BiabDevSiteClient = class {
|
|
|
11916
12423
|
* <img src={b.logoUrl ?? b.orgIcon ?? ""} alt={b.orgName ?? ""} />
|
|
11917
12424
|
* ```
|
|
11918
12425
|
*/
|
|
12426
|
+
/**
|
|
12427
|
+
* Every URL the PLATFORM owns the shape of, as JSON.
|
|
12428
|
+
*
|
|
12429
|
+
* Published site-builder pages, published legal documents, and every
|
|
12430
|
+
* materialised programmatic-page URL. Blog posts and products are not here
|
|
12431
|
+
* — the platform does not know where your site renders them. Merge those in
|
|
12432
|
+
* with `@businessdash/sdk/sitemap`, which handles the whole job.
|
|
12433
|
+
*
|
|
12434
|
+
* Paths are relative, so you join them against your own origin rather than
|
|
12435
|
+
* the org's primary verified domain.
|
|
12436
|
+
*/
|
|
12437
|
+
async sitemapEntries() {
|
|
12438
|
+
return this.client.request({
|
|
12439
|
+
path: `sites/${encodeURIComponent(this.siteId)}/sitemap-entries`,
|
|
12440
|
+
responseSchema: external_exports.object({
|
|
12441
|
+
entries: external_exports.array(
|
|
12442
|
+
external_exports.object({ loc: external_exports.string(), lastmod: external_exports.string().optional() })
|
|
12443
|
+
)
|
|
12444
|
+
})
|
|
12445
|
+
});
|
|
12446
|
+
}
|
|
11919
12447
|
async branding() {
|
|
11920
12448
|
return this.client.request({
|
|
11921
12449
|
path: `sites/${encodeURIComponent(this.siteId)}/branding`,
|
|
@@ -12548,6 +13076,42 @@ var BiabDevStorefrontClient = class {
|
|
|
12548
13076
|
responseSchema: storefrontSessionResponseSchema
|
|
12549
13077
|
});
|
|
12550
13078
|
}
|
|
13079
|
+
/**
|
|
13080
|
+
* Push your catalog into YOUR OWN Stripe account.
|
|
13081
|
+
*
|
|
13082
|
+
* Products and their variant combinations become Stripe Products and
|
|
13083
|
+
* Prices on the Stripe account connected to your workspace, so you can
|
|
13084
|
+
* manage the catalog here and let Stripe be the system of record for
|
|
13085
|
+
* money. Safe to re-run: an unchanged product is left alone, and a new
|
|
13086
|
+
* Price is minted only when the amount actually changed (Stripe Prices
|
|
13087
|
+
* are immutable on amount).
|
|
13088
|
+
*
|
|
13089
|
+
* Requires a SECRET key holding `storefront:write` — never a publishable
|
|
13090
|
+
* token, because this spends against Stripe on your behalf.
|
|
13091
|
+
*
|
|
13092
|
+
* Pass `productId` to sync one product. Omit it to sync everything not yet
|
|
13093
|
+
* pushed, in bounded batches: check `remaining` and call again until it
|
|
13094
|
+
* reaches 0.
|
|
13095
|
+
*
|
|
13096
|
+
* ```ts
|
|
13097
|
+
* let remaining = 1;
|
|
13098
|
+
* while (remaining > 0) {
|
|
13099
|
+
* const res = await biab.storefront.syncToStripe();
|
|
13100
|
+
* remaining = res.remaining;
|
|
13101
|
+
* }
|
|
13102
|
+
* ```
|
|
13103
|
+
*
|
|
13104
|
+
* Per-product failures are returned in `failed` rather than throwing, so
|
|
13105
|
+
* one bad product doesn't abandon the batch.
|
|
13106
|
+
*/
|
|
13107
|
+
async syncToStripe(input) {
|
|
13108
|
+
return this.client.request({
|
|
13109
|
+
method: "POST",
|
|
13110
|
+
path: "storefront/products/sync-to-stripe",
|
|
13111
|
+
body: input?.productId ? { productId: input.productId } : {},
|
|
13112
|
+
responseSchema: storefrontSyncToStripeResponseSchema
|
|
13113
|
+
});
|
|
13114
|
+
}
|
|
12551
13115
|
/**
|
|
12552
13116
|
* Paginated list of live products for the calling org's storefront.
|
|
12553
13117
|
* Cursor is an opaque integer offset — pass back the response's
|
|
@@ -12602,6 +13166,38 @@ var BiabDevStorefrontClient = class {
|
|
|
12602
13166
|
* via `BiabApiError` if the product isn't live or doesn't belong
|
|
12603
13167
|
* to the org bound to the API key.
|
|
12604
13168
|
*/
|
|
13169
|
+
/**
|
|
13170
|
+
* The CAD file for a product — STEP, IGES, or a native part file.
|
|
13171
|
+
*
|
|
13172
|
+
* ## Call this from YOUR server, then proxy it
|
|
13173
|
+
*
|
|
13174
|
+
* The API key is a server secret, so a browser cannot reach this directly.
|
|
13175
|
+
* Expose your own route (`/api/products/:id/cad`), call this behind it, and
|
|
13176
|
+
* redirect the visitor to the URL it returns.
|
|
13177
|
+
*
|
|
13178
|
+
* The platform withholds the raw URL from every product payload on purpose:
|
|
13179
|
+
* CAD files are the largest thing it serves and are the org's intellectual
|
|
13180
|
+
* property, so a catalog of naked URLs is a design library published to
|
|
13181
|
+
* anyone willing to write a loop. This endpoint requires a `biab_cad` cookie
|
|
13182
|
+
* on the incoming request, rate-limits per IP, and re-checks the
|
|
13183
|
+
* `ecommerce.product_3d` entitlement before answering.
|
|
13184
|
+
*
|
|
13185
|
+
* `cacheSeconds` is what to put on your own response — CAD at a content URL
|
|
13186
|
+
* does not change, so caching hard is where the bandwidth saving comes from.
|
|
13187
|
+
*
|
|
13188
|
+
* Rejects 404 when the product is a draft, has no CAD file, or the org lacks
|
|
13189
|
+
* the add-on. Those are deliberately one answer.
|
|
13190
|
+
*/
|
|
13191
|
+
async getCadDownload(productId) {
|
|
13192
|
+
return this.client.request({
|
|
13193
|
+
path: `storefront/products/${encodeURIComponent(productId)}/cad`,
|
|
13194
|
+
responseSchema: external_exports.object({
|
|
13195
|
+
url: external_exports.string(),
|
|
13196
|
+
fileName: external_exports.string().nullable(),
|
|
13197
|
+
cacheSeconds: external_exports.number()
|
|
13198
|
+
})
|
|
13199
|
+
});
|
|
13200
|
+
}
|
|
12605
13201
|
async getProduct(productId) {
|
|
12606
13202
|
return this.client.request({
|
|
12607
13203
|
path: `storefront/products/${encodeURIComponent(productId)}`,
|
|
@@ -12942,6 +13538,47 @@ var BiabDevCouponsClient = class {
|
|
|
12942
13538
|
* else toast.error(result.message);
|
|
12943
13539
|
* ```
|
|
12944
13540
|
*/
|
|
13541
|
+
/**
|
|
13542
|
+
* Create a coupon and make it live in YOUR OWN Stripe account in one call —
|
|
13543
|
+
* a Stripe Coupon plus a Promotion Code, so the same string works on your
|
|
13544
|
+
* storefront and on Stripe-hosted Checkout.
|
|
13545
|
+
*
|
|
13546
|
+
* Creation and the Stripe sync are one operation deliberately: a coupon
|
|
13547
|
+
* that exists locally but not in Stripe is the failure worth designing out,
|
|
13548
|
+
* where a customer types a code your storefront accepts and Stripe rejects.
|
|
13549
|
+
* If the sync fails the coupon is still created and `stripeSynced` comes
|
|
13550
|
+
* back `false` with the reason, rather than pretending it is live.
|
|
13551
|
+
*
|
|
13552
|
+
* Requires a SECRET key holding `storefront:write`.
|
|
13553
|
+
*
|
|
13554
|
+
* ```ts
|
|
13555
|
+
* const { coupon, stripeSynced } = await biab.coupons.create({
|
|
13556
|
+
* code: 'WELCOME10',
|
|
13557
|
+
* discountType: 'percent',
|
|
13558
|
+
* value: 10,
|
|
13559
|
+
* })
|
|
13560
|
+
* ```
|
|
13561
|
+
*
|
|
13562
|
+
* Buy-X-get-Y and bundle-gift coupons aren't available here — Stripe has no
|
|
13563
|
+
* native BXGY, so those run through our own cart math and need the offer
|
|
13564
|
+
* rows the dashboard collects.
|
|
13565
|
+
*/
|
|
13566
|
+
async create(input) {
|
|
13567
|
+
const body = couponCreateInputSchema.parse(input);
|
|
13568
|
+
return this.client.request({
|
|
13569
|
+
method: "POST",
|
|
13570
|
+
path: "coupons",
|
|
13571
|
+
body,
|
|
13572
|
+
responseSchema: couponCreateResponseSchema
|
|
13573
|
+
});
|
|
13574
|
+
}
|
|
13575
|
+
/** Every coupon on the workspace, newest first. Requires `storefront:write`. */
|
|
13576
|
+
async list() {
|
|
13577
|
+
return this.client.request({
|
|
13578
|
+
path: "coupons",
|
|
13579
|
+
responseSchema: couponListResponseSchema
|
|
13580
|
+
});
|
|
13581
|
+
}
|
|
12945
13582
|
async validate(code) {
|
|
12946
13583
|
const body = couponValidateInputSchema.parse({ code });
|
|
12947
13584
|
return this.client.request({
|
|
@@ -13288,6 +13925,38 @@ var BiabDevHiringClient = class {
|
|
|
13288
13925
|
});
|
|
13289
13926
|
}
|
|
13290
13927
|
};
|
|
13928
|
+
var BiabDevLegalClient = class {
|
|
13929
|
+
constructor(client) {
|
|
13930
|
+
this.client = client;
|
|
13931
|
+
}
|
|
13932
|
+
client;
|
|
13933
|
+
/**
|
|
13934
|
+
* Every published document, plus the header/footer presentation.
|
|
13935
|
+
*
|
|
13936
|
+
* Both in one response because the common use — a footer link list — needs
|
|
13937
|
+
* the titles and the presentation together, and a second round trip for the
|
|
13938
|
+
* latter is one a site either makes on every page or skips entirely.
|
|
13939
|
+
*/
|
|
13940
|
+
async list() {
|
|
13941
|
+
return this.client.request({
|
|
13942
|
+
path: "legal",
|
|
13943
|
+
responseSchema: legalListResponseSchema
|
|
13944
|
+
});
|
|
13945
|
+
}
|
|
13946
|
+
/**
|
|
13947
|
+
* One document by slug, body included.
|
|
13948
|
+
*
|
|
13949
|
+
* Rejects with a 404 when the slug is unpublished or absent — the two are
|
|
13950
|
+
* deliberately indistinguishable, since "exists but hidden" would leak that
|
|
13951
|
+
* an org is drafting a policy and is not something a caller can act on.
|
|
13952
|
+
*/
|
|
13953
|
+
async get(slug) {
|
|
13954
|
+
return this.client.request({
|
|
13955
|
+
path: `legal/${encodeURIComponent(slug)}`,
|
|
13956
|
+
responseSchema: legalDocumentSchema
|
|
13957
|
+
});
|
|
13958
|
+
}
|
|
13959
|
+
};
|
|
13291
13960
|
var BiabDevChatbotClient = class {
|
|
13292
13961
|
constructor(client) {
|
|
13293
13962
|
this.client = client;
|
|
@@ -13854,6 +14523,129 @@ var BiabDevCustomerPortalClient = class _BiabDevCustomerPortalClient {
|
|
|
13854
14523
|
headers: this.headers()
|
|
13855
14524
|
});
|
|
13856
14525
|
}
|
|
14526
|
+
/**
|
|
14527
|
+
* The return requests on one order, newest first.
|
|
14528
|
+
*
|
|
14529
|
+
* `resolutionNote` carries staff's answer — when a return is denied that IS
|
|
14530
|
+
* the answer, and hiding it just moves the question to email.
|
|
14531
|
+
*/
|
|
14532
|
+
async listReturnRequests(orderId) {
|
|
14533
|
+
return this.client.request({
|
|
14534
|
+
path: `customer-portal/orders/${encodeURIComponent(orderId)}/return-request`,
|
|
14535
|
+
responseSchema: customerReturnRequestListResponseSchema,
|
|
14536
|
+
headers: this.headers()
|
|
14537
|
+
});
|
|
14538
|
+
}
|
|
14539
|
+
/**
|
|
14540
|
+
* The customer's message thread with the org's staff, newest first.
|
|
14541
|
+
*
|
|
14542
|
+
* Automated rows — the review-ask and similar — are excluded server-side, so
|
|
14543
|
+
* this is only what a person wrote.
|
|
14544
|
+
*/
|
|
14545
|
+
async listMessages(opts) {
|
|
14546
|
+
const params = new URLSearchParams();
|
|
14547
|
+
if (typeof opts?.limit === "number")
|
|
14548
|
+
params.set("limit", String(opts.limit));
|
|
14549
|
+
if (opts?.jobId) params.set("jobId", opts.jobId);
|
|
14550
|
+
const qs = params.toString();
|
|
14551
|
+
return this.client.request({
|
|
14552
|
+
path: `customer-portal/messages${qs ? `?${qs}` : ""}`,
|
|
14553
|
+
responseSchema: customerPortalMessageListResponseSchema,
|
|
14554
|
+
headers: this.headers()
|
|
14555
|
+
});
|
|
14556
|
+
}
|
|
14557
|
+
/** Send a message to the org's staff. Lands in the CRM timeline. */
|
|
14558
|
+
async postMessage(input) {
|
|
14559
|
+
return this.client.request({
|
|
14560
|
+
path: "customer-portal/messages",
|
|
14561
|
+
method: "POST",
|
|
14562
|
+
body: input,
|
|
14563
|
+
responseSchema: customerPortalMessageSchema,
|
|
14564
|
+
headers: this.headers()
|
|
14565
|
+
});
|
|
14566
|
+
}
|
|
14567
|
+
/**
|
|
14568
|
+
* Mark the staff messages read up to now.
|
|
14569
|
+
*
|
|
14570
|
+
* One-way: it never clears a stamp. A portal that could un-read a message
|
|
14571
|
+
* would let a customer hide from staff that they had seen something.
|
|
14572
|
+
*/
|
|
14573
|
+
async markMessagesRead() {
|
|
14574
|
+
return this.client.request({
|
|
14575
|
+
path: "customer-portal/messages",
|
|
14576
|
+
method: "PATCH",
|
|
14577
|
+
responseSchema: customerPortalMessagesMarkReadResponseSchema,
|
|
14578
|
+
headers: this.headers()
|
|
14579
|
+
});
|
|
14580
|
+
}
|
|
14581
|
+
/**
|
|
14582
|
+
* The customer's invoices, newest first.
|
|
14583
|
+
*
|
|
14584
|
+
* `unpaid: true` filters on the computed BALANCE rather than on the status
|
|
14585
|
+
* string, because a partially-paid invoice still owes money whatever it is
|
|
14586
|
+
* called. This is the call behind "show me everything I owe" — which had no
|
|
14587
|
+
* endpoint at all before 0.9.61.
|
|
14588
|
+
*/
|
|
14589
|
+
async listInvoices(opts) {
|
|
14590
|
+
const params = new URLSearchParams();
|
|
14591
|
+
if (typeof opts?.limit === "number")
|
|
14592
|
+
params.set("limit", String(opts.limit));
|
|
14593
|
+
if (opts?.status) params.set("status", opts.status);
|
|
14594
|
+
if (opts?.unpaid) params.set("unpaid", "1");
|
|
14595
|
+
const qs = params.toString();
|
|
14596
|
+
return this.client.request({
|
|
14597
|
+
path: `customer-portal/invoices${qs ? `?${qs}` : ""}`,
|
|
14598
|
+
responseSchema: customerInvoiceListResponseSchema,
|
|
14599
|
+
headers: this.headers()
|
|
14600
|
+
});
|
|
14601
|
+
}
|
|
14602
|
+
/** The customer's quotes. `status: "sent"` is the set still awaiting them. */
|
|
14603
|
+
async listQuotes(opts) {
|
|
14604
|
+
const params = new URLSearchParams();
|
|
14605
|
+
if (typeof opts?.limit === "number")
|
|
14606
|
+
params.set("limit", String(opts.limit));
|
|
14607
|
+
if (opts?.status) params.set("status", opts.status);
|
|
14608
|
+
const qs = params.toString();
|
|
14609
|
+
return this.client.request({
|
|
14610
|
+
path: `customer-portal/quotes${qs ? `?${qs}` : ""}`,
|
|
14611
|
+
responseSchema: customerQuoteListResponseSchema,
|
|
14612
|
+
headers: this.headers()
|
|
14613
|
+
});
|
|
14614
|
+
}
|
|
14615
|
+
/** The customer's contracts. `status: "sent"` still awaits a signature. */
|
|
14616
|
+
async listContracts(opts) {
|
|
14617
|
+
const params = new URLSearchParams();
|
|
14618
|
+
if (typeof opts?.limit === "number")
|
|
14619
|
+
params.set("limit", String(opts.limit));
|
|
14620
|
+
if (opts?.status) params.set("status", opts.status);
|
|
14621
|
+
const qs = params.toString();
|
|
14622
|
+
return this.client.request({
|
|
14623
|
+
path: `customer-portal/contracts${qs ? `?${qs}` : ""}`,
|
|
14624
|
+
responseSchema: customerContractListResponseSchema,
|
|
14625
|
+
headers: this.headers()
|
|
14626
|
+
});
|
|
14627
|
+
}
|
|
14628
|
+
/**
|
|
14629
|
+
* Every shipment across the customer's orders. `active: true` narrows to
|
|
14630
|
+
* parcels still moving.
|
|
14631
|
+
*
|
|
14632
|
+
* STORED status only — no live carrier poll. `trackShipment(id)` spends a
|
|
14633
|
+
* Shippo request because it is one parcel the customer opened; doing that
|
|
14634
|
+
* per row here would mean a carrier call for every parcel in their history
|
|
14635
|
+
* on every page load.
|
|
14636
|
+
*/
|
|
14637
|
+
async listShipments(opts) {
|
|
14638
|
+
const params = new URLSearchParams();
|
|
14639
|
+
if (typeof opts?.limit === "number")
|
|
14640
|
+
params.set("limit", String(opts.limit));
|
|
14641
|
+
if (opts?.active) params.set("active", "1");
|
|
14642
|
+
const qs = params.toString();
|
|
14643
|
+
return this.client.request({
|
|
14644
|
+
path: `customer-portal/shipments${qs ? `?${qs}` : ""}`,
|
|
14645
|
+
responseSchema: customerShipmentListResponseSchema,
|
|
14646
|
+
headers: this.headers()
|
|
14647
|
+
});
|
|
14648
|
+
}
|
|
13857
14649
|
/**
|
|
13858
14650
|
* The signed-in customer's orders (newest first), each with a shipment
|
|
13859
14651
|
* roll-up (`overallStatus`, `anyInTransit`, `latestEstimatedDelivery`) for
|
|
@@ -13932,6 +14724,243 @@ var BiabDevCustomerPortalClient = class _BiabDevCustomerPortalClient {
|
|
|
13932
14724
|
headers: this.headers()
|
|
13933
14725
|
});
|
|
13934
14726
|
}
|
|
14727
|
+
/**
|
|
14728
|
+
* Ask for a replacement instead of a refund.
|
|
14729
|
+
*
|
|
14730
|
+
* Sugar over `submitReturnRequest` with `kind: "exchange"`, because an
|
|
14731
|
+
* exchange reads as its own action to the person writing the UI, and burying
|
|
14732
|
+
* it in an options bag is how it stays undiscovered. `variantId` is the one
|
|
14733
|
+
* they want instead — omit it when that still needs a conversation.
|
|
14734
|
+
*
|
|
14735
|
+
* @example
|
|
14736
|
+
* ```ts
|
|
14737
|
+
* await portal.submitExchangeRequest(orderId, {
|
|
14738
|
+
* exchangeForVariantId: largeVariantId,
|
|
14739
|
+
* reason: "wrong size",
|
|
14740
|
+
* });
|
|
14741
|
+
* ```
|
|
14742
|
+
*/
|
|
14743
|
+
async submitExchangeRequest(orderId, input) {
|
|
14744
|
+
return this.submitReturnRequest(orderId, {
|
|
14745
|
+
...input ?? {},
|
|
14746
|
+
kind: "exchange"
|
|
14747
|
+
});
|
|
14748
|
+
}
|
|
14749
|
+
/**
|
|
14750
|
+
* Report that a parcel never arrived.
|
|
14751
|
+
*
|
|
14752
|
+
* This does NOT change the shipment's carrier status, and deliberately so:
|
|
14753
|
+
* when the carrier says delivered and the customer says otherwise, both
|
|
14754
|
+
* facts matter — the carrier's scan is what the org files a claim against.
|
|
14755
|
+
* The result carries `carrierStatus` alongside the report so a UI can show
|
|
14756
|
+
* both: *"Carrier says delivered Aug 14 · You reported not received Aug 16."*
|
|
14757
|
+
*
|
|
14758
|
+
* `contested: true` means exactly that disagreement. Re-reporting an open
|
|
14759
|
+
* claim returns it with `alreadyOpen: true` rather than erroring — a
|
|
14760
|
+
* customer tapping twice is anxious, not hostile.
|
|
14761
|
+
*
|
|
14762
|
+
* @example
|
|
14763
|
+
* ```ts
|
|
14764
|
+
* const r = await portal.reportNotReceived(shipmentId, {
|
|
14765
|
+
* note: "Nothing on the porch, checked with neighbours.",
|
|
14766
|
+
* });
|
|
14767
|
+
* if (r.contested) showCarrierDisputeHelp();
|
|
14768
|
+
* ```
|
|
14769
|
+
*/
|
|
14770
|
+
async reportNotReceived(shipmentId, input) {
|
|
14771
|
+
const body = input?.note ? { note: input.note } : {};
|
|
14772
|
+
return this.client.request({
|
|
14773
|
+
method: "POST",
|
|
14774
|
+
path: `customer-portal/shipments/${encodeURIComponent(shipmentId)}/not-received`,
|
|
14775
|
+
body,
|
|
14776
|
+
responseSchema: customerNotReceivedResultSchema,
|
|
14777
|
+
headers: this.headers()
|
|
14778
|
+
});
|
|
14779
|
+
}
|
|
14780
|
+
/**
|
|
14781
|
+
* The product reviews this customer has written for this org.
|
|
14782
|
+
*
|
|
14783
|
+
* Distinct from `listReviews()`, which is reviews of the ORG. Both exist
|
|
14784
|
+
* because "are these people good to deal with" and "is this thing any good"
|
|
14785
|
+
* are different questions, stored in different tables, and shown in
|
|
14786
|
+
* different places.
|
|
14787
|
+
*
|
|
14788
|
+
* `isApproved: false` means QUEUED, not rejected — render it as "awaiting
|
|
14789
|
+
* review" or the customer will assume it was lost and write it again.
|
|
14790
|
+
*/
|
|
14791
|
+
/**
|
|
14792
|
+
* The customer's subscription with this org, and what the org offers.
|
|
14793
|
+
*
|
|
14794
|
+
* One subscription per org — `user_subscriptions` is unique on
|
|
14795
|
+
* (user, org) — so there is no id to pass. The org's live offerings come
|
|
14796
|
+
* back alongside, because a portal that reports "not subscribed" and
|
|
14797
|
+
* nothing else is a dead end.
|
|
14798
|
+
*
|
|
14799
|
+
* **Render entitlement from `subscription.hasAccess`, not from `status`.**
|
|
14800
|
+
* A lifetime purchase has no period to expire and a cancelled subscription
|
|
14801
|
+
* keeps access until the period already paid for ends; `hasAccess` is
|
|
14802
|
+
* computed by the same function the content gates use, so the portal and
|
|
14803
|
+
* the gate cannot disagree.
|
|
14804
|
+
*/
|
|
14805
|
+
async getSubscription() {
|
|
14806
|
+
return this.client.request({
|
|
14807
|
+
path: "customer-portal/subscription",
|
|
14808
|
+
responseSchema: customerSubscriptionResponseSchema,
|
|
14809
|
+
headers: this.headers()
|
|
14810
|
+
});
|
|
14811
|
+
}
|
|
14812
|
+
/**
|
|
14813
|
+
* Cancel the subscription at the end of the paid period.
|
|
14814
|
+
*
|
|
14815
|
+
* Cancelling ends the RENEWAL, not the access: the customer has paid for
|
|
14816
|
+
* the period they are in and keeps everything until `accessUntil`. Ending
|
|
14817
|
+
* access on the click would take back something they already bought, which
|
|
14818
|
+
* is the most common way a subscription flow feels like a trap.
|
|
14819
|
+
*
|
|
14820
|
+
* Read `accessUntil` back to them — "active until 14 March" is the true
|
|
14821
|
+
* statement, not "cancelled".
|
|
14822
|
+
*/
|
|
14823
|
+
async cancelSubscription() {
|
|
14824
|
+
return this.client.request({
|
|
14825
|
+
method: "POST",
|
|
14826
|
+
path: "customer-portal/subscription/cancel",
|
|
14827
|
+
body: { resume: false },
|
|
14828
|
+
responseSchema: customerSubscriptionCancelResponseSchema,
|
|
14829
|
+
headers: this.headers()
|
|
14830
|
+
});
|
|
14831
|
+
}
|
|
14832
|
+
/**
|
|
14833
|
+
* Clear a pending cancellation.
|
|
14834
|
+
*
|
|
14835
|
+
* Between cancelling and the period ending nothing has actually been lost,
|
|
14836
|
+
* so changing your mind should cost one call rather than a re-purchase.
|
|
14837
|
+
* After the period ends there is nothing to resume and they subscribe again
|
|
14838
|
+
* like anyone else.
|
|
14839
|
+
*/
|
|
14840
|
+
async resumeSubscription() {
|
|
14841
|
+
return this.client.request({
|
|
14842
|
+
method: "POST",
|
|
14843
|
+
path: "customer-portal/subscription/cancel",
|
|
14844
|
+
body: { resume: true },
|
|
14845
|
+
responseSchema: customerSubscriptionCancelResponseSchema,
|
|
14846
|
+
headers: this.headers()
|
|
14847
|
+
});
|
|
14848
|
+
}
|
|
14849
|
+
/**
|
|
14850
|
+
* The content this subscription entitles them to — the answer to "what am
|
|
14851
|
+
* I actually getting for this?", which is the question asked right before
|
|
14852
|
+
* someone cancels.
|
|
14853
|
+
*
|
|
14854
|
+
* When `entitled` is false these are LOCKED previews, not an empty
|
|
14855
|
+
* entitlement: titles, excerpts and images, no bodies. Show them beside the
|
|
14856
|
+
* offer. Rendering an empty list would hide the pitch at exactly the moment
|
|
14857
|
+
* it is most relevant.
|
|
14858
|
+
*/
|
|
14859
|
+
async getSubscriberContent(opts) {
|
|
14860
|
+
const params = new URLSearchParams();
|
|
14861
|
+
if (typeof opts?.limit === "number")
|
|
14862
|
+
params.set("limit", String(opts.limit));
|
|
14863
|
+
const qs = params.toString();
|
|
14864
|
+
return this.client.request({
|
|
14865
|
+
path: `customer-portal/subscription/content${qs ? `?${qs}` : ""}`,
|
|
14866
|
+
responseSchema: customerSubscriberContentResponseSchema,
|
|
14867
|
+
headers: this.headers()
|
|
14868
|
+
});
|
|
14869
|
+
}
|
|
14870
|
+
/**
|
|
14871
|
+
* Push config and the browsers this customer has registered.
|
|
14872
|
+
*
|
|
14873
|
+
* Returns `vapidPublicKey` too, because a page cannot subscribe without it.
|
|
14874
|
+
*/
|
|
14875
|
+
async getPushConfig() {
|
|
14876
|
+
return this.client.request({
|
|
14877
|
+
path: "customer-portal/push",
|
|
14878
|
+
responseSchema: customerPushConfigSchema,
|
|
14879
|
+
headers: this.headers()
|
|
14880
|
+
});
|
|
14881
|
+
}
|
|
14882
|
+
/**
|
|
14883
|
+
* Register this browser.
|
|
14884
|
+
*
|
|
14885
|
+
* Pair with `subscribeToPush()` from `@businessdash/sdk/push-core`, which
|
|
14886
|
+
* handles the service worker, the permission prompt and the key encoding
|
|
14887
|
+
* and hands back exactly this payload.
|
|
14888
|
+
*
|
|
14889
|
+
* Upserted on the endpoint, so re-subscribing from the same browser
|
|
14890
|
+
* refreshes the row rather than creating a second one.
|
|
14891
|
+
*/
|
|
14892
|
+
async subscribePush(input) {
|
|
14893
|
+
return this.client.request({
|
|
14894
|
+
method: "POST",
|
|
14895
|
+
path: "customer-portal/push",
|
|
14896
|
+
body: input,
|
|
14897
|
+
responseSchema: external_exports.object({ id: external_exports.string(), created: external_exports.boolean() }),
|
|
14898
|
+
headers: this.headers()
|
|
14899
|
+
});
|
|
14900
|
+
}
|
|
14901
|
+
/**
|
|
14902
|
+
* Rename a device, or narrow what it receives.
|
|
14903
|
+
*
|
|
14904
|
+
* `categories: []` means "nothing for now" and keeps the subscription
|
|
14905
|
+
* warm — browsers make re-granting a revoked permission deliberately
|
|
14906
|
+
* awkward, so an "off" that discards the subscription is hard to undo.
|
|
14907
|
+
*/
|
|
14908
|
+
async updatePushDevice(input) {
|
|
14909
|
+
return this.client.request({
|
|
14910
|
+
method: "PATCH",
|
|
14911
|
+
path: "customer-portal/push",
|
|
14912
|
+
body: input,
|
|
14913
|
+
responseSchema: external_exports.object({ ok: external_exports.boolean() }),
|
|
14914
|
+
headers: this.headers()
|
|
14915
|
+
});
|
|
14916
|
+
}
|
|
14917
|
+
/**
|
|
14918
|
+
* Forget a device. Takes an id or the endpoint.
|
|
14919
|
+
*
|
|
14920
|
+
* A browser tearing its own subscription down knows its endpoint, not our
|
|
14921
|
+
* row id — so pass what `unsubscribeFromPush()` returns.
|
|
14922
|
+
*/
|
|
14923
|
+
async unsubscribePush(input) {
|
|
14924
|
+
return this.client.request({
|
|
14925
|
+
method: "DELETE",
|
|
14926
|
+
path: "customer-portal/push",
|
|
14927
|
+
body: input,
|
|
14928
|
+
responseSchema: external_exports.object({
|
|
14929
|
+
ok: external_exports.boolean(),
|
|
14930
|
+
deletedId: external_exports.string().nullable()
|
|
14931
|
+
}),
|
|
14932
|
+
headers: this.headers()
|
|
14933
|
+
});
|
|
14934
|
+
}
|
|
14935
|
+
async listProductReviews() {
|
|
14936
|
+
return this.client.request({
|
|
14937
|
+
path: "customer-portal/product-reviews",
|
|
14938
|
+
responseSchema: customerProductReviewListSchema,
|
|
14939
|
+
headers: this.headers()
|
|
14940
|
+
});
|
|
14941
|
+
}
|
|
14942
|
+
/**
|
|
14943
|
+
* Review a product this customer BOUGHT.
|
|
14944
|
+
*
|
|
14945
|
+
* The portal requires a matching order — it is standing inside the
|
|
14946
|
+
* customer's purchase history, which is the one thing the public storefront
|
|
14947
|
+
* does not know. That makes these verified-buyer reviews, and it stops a
|
|
14948
|
+
* competitor one-starring a catalogue they never bought.
|
|
14949
|
+
*
|
|
14950
|
+
* Rejects with `not_purchased` (403) when no order matches, and
|
|
14951
|
+
* `already_reviewed` (409) on a second review of the same product.
|
|
14952
|
+
* Moderation follows the ORG's policy, so the result may be
|
|
14953
|
+
* `awaitingModeration`.
|
|
14954
|
+
*/
|
|
14955
|
+
async submitProductReview(input) {
|
|
14956
|
+
return this.client.request({
|
|
14957
|
+
method: "POST",
|
|
14958
|
+
path: "customer-portal/product-reviews",
|
|
14959
|
+
body: input,
|
|
14960
|
+
responseSchema: customerProductReviewCreatedSchema,
|
|
14961
|
+
headers: this.headers()
|
|
14962
|
+
});
|
|
14963
|
+
}
|
|
13935
14964
|
/**
|
|
13936
14965
|
* List the digital downloads the customer is entitled to for a paid order
|
|
13937
14966
|
* (P10d). Each item is a ready-to-use URL — a short-lived presigned link for
|
|
@@ -14027,6 +15056,22 @@ var BiabDevCustomerPortalClient = class _BiabDevCustomerPortalClient {
|
|
|
14027
15056
|
* dispatch travel-time recompute layer ships, at which point the
|
|
14028
15057
|
* `eta` field switches sources without breaking this shape.
|
|
14029
15058
|
*/
|
|
15059
|
+
/**
|
|
15060
|
+
* Where the job and its technicians are in the dispatch lifecycle.
|
|
15061
|
+
*
|
|
15062
|
+
* Named for ETA historically; it is the DISPATCH STATUS surface, which is
|
|
15063
|
+
* why `getDispatchStatus` below is the same call under the name people
|
|
15064
|
+
* look for.
|
|
15065
|
+
*
|
|
15066
|
+
* Read `dispatchStatus` (job-level) for "is anyone on the way" and
|
|
15067
|
+
* `assignments[].dispatchStatus` for per-technician detail. They differ on
|
|
15068
|
+
* purpose: the job is `completed` only once the LAST assignee finishes.
|
|
15069
|
+
*
|
|
15070
|
+
* Nothing about the dispatch CASCADE is exposed — who was offered the job,
|
|
15071
|
+
* who declined, how many people were asked before someone accepted. That
|
|
15072
|
+
* is staff-internal, and a customer learning they were the fourth choice
|
|
15073
|
+
* helps nobody.
|
|
15074
|
+
*/
|
|
14030
15075
|
async getJobEta(jobId) {
|
|
14031
15076
|
return this.client.request({
|
|
14032
15077
|
path: `customer-portal/jobs/${encodeURIComponent(jobId)}/eta`,
|
|
@@ -14034,6 +15079,16 @@ var BiabDevCustomerPortalClient = class _BiabDevCustomerPortalClient {
|
|
|
14034
15079
|
headers: this.headers()
|
|
14035
15080
|
});
|
|
14036
15081
|
}
|
|
15082
|
+
/**
|
|
15083
|
+
* Dispatch status for a job — the same call as `getJobEta`, under the name
|
|
15084
|
+
* developers actually search for.
|
|
15085
|
+
*
|
|
15086
|
+
* An alias rather than a second route: two endpoints returning the same
|
|
15087
|
+
* thing is how they drift.
|
|
15088
|
+
*/
|
|
15089
|
+
async getDispatchStatus(jobId) {
|
|
15090
|
+
return this.getJobEta(jobId);
|
|
15091
|
+
}
|
|
14037
15092
|
/**
|
|
14038
15093
|
* Unified job activity feed: structured events (status changes,
|
|
14039
15094
|
* dispatch lifecycle, media uploads, quote/contract/invoice
|
|
@@ -14139,6 +15194,190 @@ var BiabDevAuthClient = class {
|
|
|
14139
15194
|
});
|
|
14140
15195
|
}
|
|
14141
15196
|
};
|
|
15197
|
+
var BiabDevCustomerInvitesClient = class {
|
|
15198
|
+
constructor(client) {
|
|
15199
|
+
this.client = client;
|
|
15200
|
+
}
|
|
15201
|
+
client;
|
|
15202
|
+
/**
|
|
15203
|
+
* Hand an invite link out again.
|
|
15204
|
+
*
|
|
15205
|
+
* **Rotates the token** — the previous link stops working. That is the
|
|
15206
|
+
* point rather than a side effect: if the reason for resending was "it went
|
|
15207
|
+
* to the wrong address", rotating IS the fix, and reusing the token would
|
|
15208
|
+
* leave the wrong recipient holding a working invitation. The cost is that
|
|
15209
|
+
* someone who finds the original email later gets a dead link, which is a
|
|
15210
|
+
* support message rather than an account.
|
|
15211
|
+
*
|
|
15212
|
+
* Rate limited to one send a minute per invitation, answering **429** with
|
|
15213
|
+
* a retry hint. Resend mails an address the caller chose, so an unbounded
|
|
15214
|
+
* one is a mail-bombing tool. Staff clicking the button in the dashboard
|
|
15215
|
+
* skip the wait; an API key does not, because an API key is the automated
|
|
15216
|
+
* caller the limit exists for.
|
|
15217
|
+
*
|
|
15218
|
+
* Refuses a **revoked** invitation (resending would quietly un-revoke it)
|
|
15219
|
+
* and a **fully-redeemed** one (it did its job; a new invitation should be
|
|
15220
|
+
* created as one, so the list keeps showing what happened).
|
|
15221
|
+
*/
|
|
15222
|
+
async resend(inviteId, opts) {
|
|
15223
|
+
return this.client.request({
|
|
15224
|
+
method: "POST",
|
|
15225
|
+
path: `customer-invites/${encodeURIComponent(inviteId)}/resend`,
|
|
15226
|
+
body: opts?.expiresInDays === void 0 ? {} : { expiresInDays: opts.expiresInDays },
|
|
15227
|
+
responseSchema: customerInviteResendResponseSchema
|
|
15228
|
+
});
|
|
15229
|
+
}
|
|
15230
|
+
};
|
|
15231
|
+
var BiabDevSchedulingClient = class {
|
|
15232
|
+
constructor(client, siteId) {
|
|
15233
|
+
this.client = client;
|
|
15234
|
+
this.siteId = siteId;
|
|
15235
|
+
}
|
|
15236
|
+
client;
|
|
15237
|
+
siteId;
|
|
15238
|
+
path(suffix) {
|
|
15239
|
+
return `sites/${encodeURIComponent(this.siteId)}/scheduling/${suffix}`;
|
|
15240
|
+
}
|
|
15241
|
+
/** What the org offers to book. */
|
|
15242
|
+
async listEventTypes() {
|
|
15243
|
+
return this.client.request({
|
|
15244
|
+
path: this.path("event-types"),
|
|
15245
|
+
responseSchema: schedulingEventTypeListSchema
|
|
15246
|
+
});
|
|
15247
|
+
}
|
|
15248
|
+
/** One event type, plus the questions asked when booking it. */
|
|
15249
|
+
async getEventType(slug) {
|
|
15250
|
+
return this.client.request({
|
|
15251
|
+
path: this.path(`event-types/${encodeURIComponent(slug)}`),
|
|
15252
|
+
responseSchema: schedulingEventTypeDetailSchema
|
|
15253
|
+
});
|
|
15254
|
+
}
|
|
15255
|
+
/**
|
|
15256
|
+
* Free slots in a window.
|
|
15257
|
+
*
|
|
15258
|
+
* Ask for the window you are about to render, not the whole month: slot
|
|
15259
|
+
* computation walks every host's calendar and busy times, so a wide range
|
|
15260
|
+
* is a slow one.
|
|
15261
|
+
*/
|
|
15262
|
+
async getAvailableSlots(slug, params) {
|
|
15263
|
+
const query = new URLSearchParams({
|
|
15264
|
+
from: typeof params.from === "string" ? params.from : params.from.toISOString(),
|
|
15265
|
+
to: typeof params.to === "string" ? params.to : params.to.toISOString()
|
|
15266
|
+
});
|
|
15267
|
+
return this.client.request({
|
|
15268
|
+
path: this.path(
|
|
15269
|
+
`event-types/${encodeURIComponent(slug)}/slots?${query.toString()}`
|
|
15270
|
+
),
|
|
15271
|
+
responseSchema: schedulingSlotsResponseSchema
|
|
15272
|
+
});
|
|
15273
|
+
}
|
|
15274
|
+
/**
|
|
15275
|
+
* Book a slot.
|
|
15276
|
+
*
|
|
15277
|
+
* Returns `pending` rather than `confirmed` when the event type requires
|
|
15278
|
+
* approval — say "requested" in the UI for that case, because telling
|
|
15279
|
+
* someone their meeting is booked when staff still have to accept it is the
|
|
15280
|
+
* kind of thing they plan a day around.
|
|
15281
|
+
*/
|
|
15282
|
+
async confirmBooking(input) {
|
|
15283
|
+
const body = {
|
|
15284
|
+
...input,
|
|
15285
|
+
startAt: typeof input.startAt === "string" ? input.startAt : input.startAt.toISOString()
|
|
15286
|
+
};
|
|
15287
|
+
return this.client.request({
|
|
15288
|
+
method: "POST",
|
|
15289
|
+
path: this.path("bookings"),
|
|
15290
|
+
body,
|
|
15291
|
+
responseSchema: schedulingBookingResultSchema
|
|
15292
|
+
});
|
|
15293
|
+
}
|
|
15294
|
+
/**
|
|
15295
|
+
* Read a booking with one of its signed tokens.
|
|
15296
|
+
*
|
|
15297
|
+
* `type` must match the token you hold — a cancel token will not open the
|
|
15298
|
+
* manage view. That is the point of issuing three.
|
|
15299
|
+
*/
|
|
15300
|
+
async getBooking(token, type = "manage") {
|
|
15301
|
+
return this.client.request({
|
|
15302
|
+
path: this.path(
|
|
15303
|
+
`bookings/by-token/${encodeURIComponent(token)}?type=${encodeURIComponent(type)}`
|
|
15304
|
+
),
|
|
15305
|
+
responseSchema: schedulingBookingViewSchema
|
|
15306
|
+
});
|
|
15307
|
+
}
|
|
15308
|
+
/**
|
|
15309
|
+
* Move a booking — the INVITEE side, with their reschedule token.
|
|
15310
|
+
*
|
|
15311
|
+
* Notifies the invitee and every host, and cancels the reminder jobs queued
|
|
15312
|
+
* against the old time so nobody gets "your meeting starts in 15 minutes"
|
|
15313
|
+
* for a slot that moved.
|
|
15314
|
+
*/
|
|
15315
|
+
async rescheduleBooking(input) {
|
|
15316
|
+
return this.client.request({
|
|
15317
|
+
method: "POST",
|
|
15318
|
+
path: this.path(`bookings/by-token/${encodeURIComponent(input.token)}`),
|
|
15319
|
+
body: {
|
|
15320
|
+
action: "reschedule",
|
|
15321
|
+
newStartAt: typeof input.newStartAt === "string" ? input.newStartAt : input.newStartAt.toISOString(),
|
|
15322
|
+
...input.reason ? { reason: input.reason } : {}
|
|
15323
|
+
},
|
|
15324
|
+
responseSchema: schedulingRescheduleResultSchema
|
|
15325
|
+
});
|
|
15326
|
+
}
|
|
15327
|
+
/**
|
|
15328
|
+
* Move a booking as STAFF, with the API key rather than an invitee token.
|
|
15329
|
+
*
|
|
15330
|
+
* Same service as the token path, so the invitee AND every host are
|
|
15331
|
+
* notified either way, and the reminder jobs for the old time are
|
|
15332
|
+
* cancelled either way. `actorUserId` records WHO moved it, which is what
|
|
15333
|
+
* lets a customer's history say "they rescheduled" rather than leaving an
|
|
15334
|
+
* unexplained change.
|
|
15335
|
+
*/
|
|
15336
|
+
async rescheduleBookingAsStaff(input) {
|
|
15337
|
+
return this.client.request({
|
|
15338
|
+
method: "POST",
|
|
15339
|
+
path: this.path(`bookings/${encodeURIComponent(input.bookingId)}/manage`),
|
|
15340
|
+
body: {
|
|
15341
|
+
action: "reschedule",
|
|
15342
|
+
newStartAt: typeof input.newStartAt === "string" ? input.newStartAt : input.newStartAt.toISOString(),
|
|
15343
|
+
...input.reason ? { reason: input.reason } : {},
|
|
15344
|
+
...input.actorUserId ? { actorUserId: input.actorUserId } : {}
|
|
15345
|
+
},
|
|
15346
|
+
responseSchema: schedulingRescheduleResultSchema
|
|
15347
|
+
});
|
|
15348
|
+
}
|
|
15349
|
+
/** Cancel a booking as STAFF. Notifies the invitee and every host. */
|
|
15350
|
+
async cancelBookingAsStaff(input) {
|
|
15351
|
+
return this.client.request({
|
|
15352
|
+
method: "POST",
|
|
15353
|
+
path: this.path(`bookings/${encodeURIComponent(input.bookingId)}/manage`),
|
|
15354
|
+
body: {
|
|
15355
|
+
action: "cancel",
|
|
15356
|
+
...input.reason ? { reason: input.reason } : {},
|
|
15357
|
+
...input.actorUserId ? { actorUserId: input.actorUserId } : {}
|
|
15358
|
+
},
|
|
15359
|
+
responseSchema: schedulingCancelResultSchema
|
|
15360
|
+
});
|
|
15361
|
+
}
|
|
15362
|
+
/**
|
|
15363
|
+
* Cancel a booking — the INVITEE side, with their cancel token.
|
|
15364
|
+
*
|
|
15365
|
+
* `reason` is passed to the hosts. Worth collecting: "something came up" and
|
|
15366
|
+
* "I booked the wrong service" lead to different follow-ups, and the second
|
|
15367
|
+
* is recoverable revenue.
|
|
15368
|
+
*/
|
|
15369
|
+
async cancelBooking(input) {
|
|
15370
|
+
return this.client.request({
|
|
15371
|
+
method: "POST",
|
|
15372
|
+
path: this.path(`bookings/by-token/${encodeURIComponent(input.token)}`),
|
|
15373
|
+
body: {
|
|
15374
|
+
action: "cancel",
|
|
15375
|
+
...input.reason ? { reason: input.reason } : {}
|
|
15376
|
+
},
|
|
15377
|
+
responseSchema: schedulingCancelResultSchema
|
|
15378
|
+
});
|
|
15379
|
+
}
|
|
15380
|
+
};
|
|
14142
15381
|
|
|
14143
15382
|
// src/auth-handler.ts
|
|
14144
15383
|
var DEFAULT_AUTH_COOKIE_NAME = "biab_session";
|