@businessdash/sdk 0.9.80 → 0.9.90
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 +133 -949
- package/assets/{biab-sw.js → bd-sw.js} +2 -2
- package/dist/account-core/index.d.ts +1 -1
- package/dist/account-core/index.d.ts.map +1 -1
- package/dist/adapters-revalidate.d.ts +2 -2
- package/dist/adapters-revalidate.js +2 -2
- package/dist/adapters-revalidate.js.map +1 -1
- package/dist/analytics-core.d.ts +6 -6
- package/dist/analytics-core.d.ts.map +1 -1
- package/dist/analytics-core.js +4 -4
- package/dist/analytics-core.js.map +1 -1
- package/dist/analytics-server.d.ts +6 -6
- package/dist/analytics-server.d.ts.map +1 -1
- package/dist/analytics-server.js +5 -5
- package/dist/auth-handler.d.ts +14 -14
- package/dist/auth-handler.d.ts.map +1 -1
- package/dist/auth-handler.js +16 -16
- package/dist/auth-handler.js.map +1 -1
- package/dist/auth-links.d.ts +2 -2
- package/dist/auth-links.d.ts.map +1 -1
- package/dist/auth-links.js +2 -2
- package/dist/auth-links.js.map +1 -1
- package/dist/{biab-forms.css → bd-forms.css} +158 -158
- package/dist/cli.d.ts +4 -4
- package/dist/cli.js +78 -78
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +158 -147
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +156 -137
- package/dist/client.js.map +1 -1
- package/dist/consent-core/index.cjs +2 -2
- package/dist/consent-core/index.d.ts +2 -2
- package/dist/consent-core/index.d.ts.map +1 -1
- package/dist/consent-core/index.js +10 -8
- package/dist/consent-core/index.js.map +1 -1
- package/dist/contracts.d.ts +411 -52
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +89 -15
- package/dist/contracts.js.map +1 -1
- package/dist/data-model-schema.d.ts +15 -15
- package/dist/data-model-schema.d.ts.map +1 -1
- package/dist/data-model-schema.js +19 -17
- package/dist/data-model-schema.js.map +1 -1
- package/dist/distribution.d.ts +5 -5
- package/dist/distribution.d.ts.map +1 -1
- package/dist/distribution.js +4 -4
- package/dist/element.d.ts +36 -36
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +43 -43
- package/dist/element.js.map +1 -1
- package/dist/embed-protocol.d.ts +11 -11
- package/dist/embed-protocol.d.ts.map +1 -1
- package/dist/embed-protocol.js +1 -1
- package/dist/embed-protocol.js.map +1 -1
- package/dist/errors.d.ts +15 -15
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +18 -18
- package/dist/errors.js.map +1 -1
- package/dist/forms-core/autocomplete.d.ts +3 -3
- package/dist/forms-core/autocomplete.d.ts.map +1 -1
- package/dist/forms-core/autocomplete.js +2 -2
- package/dist/forms-core/controller.d.ts +10 -10
- package/dist/forms-core/controller.d.ts.map +1 -1
- package/dist/forms-core/controller.js +4 -4
- package/dist/forms-core/controller.js.map +1 -1
- package/dist/forms-core/elements.d.ts +4 -4
- package/dist/forms-core/elements.d.ts.map +1 -1
- package/dist/forms-core/elements.js +7 -7
- package/dist/forms-core/elements.js.map +1 -1
- package/dist/forms-core/formula.d.ts +1 -1
- package/dist/forms-core/formula.js +1 -1
- package/dist/forms-core/index.d.ts +6 -6
- package/dist/forms-core/index.d.ts.map +1 -1
- package/dist/forms-core/index.js +5 -5
- package/dist/forms-core/index.js.map +1 -1
- package/dist/forms-core/units.d.ts +1 -1
- package/dist/forms-core/units.js +1 -1
- package/dist/forms-core/us-states.d.ts +1 -1
- package/dist/forms-core/us-states.js +1 -1
- package/dist/forms-core/validation.d.ts +12 -3
- package/dist/forms-core/validation.d.ts.map +1 -1
- package/dist/forms-core/validation.js +152 -17
- package/dist/forms-core/validation.js.map +1 -1
- package/dist/forms.d.ts +2 -2
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +2 -2
- package/dist/forms.js.map +1 -1
- package/dist/framework-support.js +1 -1
- package/dist/framework-support.js.map +1 -1
- package/dist/gallery-types.d.ts +1 -1
- package/dist/graphql.d.ts +3 -3
- package/dist/graphql.d.ts.map +1 -1
- package/dist/graphql.js +3 -3
- package/dist/graphql.js.map +1 -1
- package/dist/index.cjs +351 -272
- package/dist/index.d.cts +5 -5
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/legal-core/index.cjs +8 -8
- package/dist/legal-core/index.d.ts +3 -3
- package/dist/legal-core/index.d.ts.map +1 -1
- package/dist/legal-core/index.js +11 -11
- package/dist/legal-core/index.js.map +1 -1
- package/dist/marketing-core/index.d.ts +51 -1
- package/dist/marketing-core/index.d.ts.map +1 -1
- package/dist/marketing-core/index.js +35 -0
- package/dist/marketing-core/index.js.map +1 -1
- package/dist/marketing-schema.d.ts +9 -9
- package/dist/marketing-schema.d.ts.map +1 -1
- package/dist/marketing-schema.js +1 -1
- package/dist/mcp.d.ts +4 -4
- package/dist/mcp.js +4 -4
- package/dist/native.d.ts +6 -6
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +4 -4
- package/dist/native.js.map +1 -1
- package/dist/next-revalidate.d.ts +8 -8
- package/dist/next-revalidate.d.ts.map +1 -1
- package/dist/next-revalidate.js +7 -7
- package/dist/next-revalidate.js.map +1 -1
- package/dist/notifications-core/index.d.ts +1 -1
- package/dist/notifications-core/index.js +1 -1
- package/dist/parallel-pages.d.ts +4 -4
- package/dist/parallel-pages.d.ts.map +1 -1
- package/dist/parallel-pages.js +5 -5
- package/dist/parallel-pages.js.map +1 -1
- package/dist/portal-core/index.d.ts +1 -1
- package/dist/portal-core/index.js +1 -1
- package/dist/proxy.d.ts +18 -18
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +10 -10
- package/dist/proxy.js.map +1 -1
- package/dist/push-core/index.cjs +6 -2
- package/dist/push-core/index.d.ts +1 -1
- package/dist/push-core/index.d.ts.map +1 -1
- package/dist/push-core/index.js +6 -2
- package/dist/push-core/index.js.map +1 -1
- package/dist/react-analytics.d.ts +14 -14
- package/dist/react-analytics.d.ts.map +1 -1
- package/dist/react-analytics.js +15 -15
- package/dist/react-analytics.js.map +1 -1
- package/dist/react-attribution.d.ts +2 -2
- package/dist/react-attribution.d.ts.map +1 -1
- package/dist/react-attribution.js +1 -1
- package/dist/react-marketing.js +5 -5
- package/dist/react-marketing.js.map +1 -1
- package/dist/react.d.ts +38 -61
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +247 -261
- package/dist/react.js.map +1 -1
- package/dist/reserved-paths.d.ts +2 -2
- package/dist/reserved-paths.js +3 -3
- package/dist/reserved-paths.js.map +1 -1
- package/dist/revalidate-verify.d.ts +3 -3
- package/dist/revalidate-verify.d.ts.map +1 -1
- package/dist/revalidate-verify.js +1 -1
- package/dist/revalidate-verify.js.map +1 -1
- package/dist/sdk.d.ts +51 -45
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +48 -50
- package/dist/sdk.js.map +1 -1
- package/dist/seed-core/index.js +8 -8
- package/dist/seed-core/index.js.map +1 -1
- package/dist/seo-core/blog.d.ts +1 -1
- package/dist/seo-core/blog.js +1 -1
- package/dist/seo-core/blog.js.map +1 -1
- package/dist/seo-core/index.cjs +2 -2
- package/dist/seo-core/index.js +1 -1
- package/dist/seo-core/index.js.map +1 -1
- package/dist/seo.d.ts +1 -1
- package/dist/seo.d.ts.map +1 -1
- package/dist/seo.js +1 -1
- package/dist/seo.js.map +1 -1
- package/dist/sitemap-core/index.cjs +5 -5
- package/dist/sitemap-core/index.d.ts +13 -5
- package/dist/sitemap-core/index.d.ts.map +1 -1
- package/dist/sitemap-core/index.js +4 -4
- package/dist/sitemap-core/index.js.map +1 -1
- package/dist/socials.d.ts +6 -6
- package/dist/socials.d.ts.map +1 -1
- package/dist/socials.js +5 -5
- package/dist/socials.js.map +1 -1
- package/dist/solid-compat.d.ts +1 -1
- package/dist/solid-compat.js +4 -4
- package/dist/solid-compat.js.map +1 -1
- package/dist/store-core/index.d.ts +1 -1
- package/dist/vanilla.d.ts +12 -12
- package/dist/vanilla.d.ts.map +1 -1
- package/dist/vanilla.js +192 -145
- package/dist/vanilla.js.map +1 -1
- package/openapi.json +264 -1
- package/package.json +8 -8
- package/src/account-core/index.ts +1 -1
- package/src/adapters-revalidate.ts +3 -3
- package/src/analytics-core.ts +8 -8
- package/src/analytics-server.ts +6 -6
- package/src/angular/{biab-form.component.ts → bd-form.component.ts} +269 -161
- package/src/angular/headless.ts +12 -12
- package/src/angular/index.ts +9 -9
- package/src/auth-handler.ts +22 -22
- package/src/auth-links.ts +2 -2
- package/src/cli.ts +81 -81
- package/src/client.ts +218 -193
- package/src/consent-core/index.ts +10 -8
- package/src/contracts.ts +99 -15
- package/src/data-model-schema.ts +29 -26
- package/src/distribution.ts +5 -5
- package/src/element.ts +54 -54
- package/src/embed-protocol.ts +14 -14
- package/src/errors.ts +27 -27
- package/src/forms-core/autocomplete.ts +3 -3
- package/src/forms-core/controller.ts +12 -12
- package/src/forms-core/elements.ts +7 -7
- package/src/forms-core/formula.ts +1 -1
- package/src/forms-core/index.ts +8 -8
- package/src/forms-core/units.ts +1 -1
- package/src/forms-core/us-states.ts +1 -1
- package/src/forms-core/validation.ts +158 -14
- package/src/forms.ts +2 -2
- package/src/framework-support.ts +1 -1
- package/src/gallery-types.ts +1 -1
- package/src/graphql.ts +4 -4
- package/src/index.ts +38 -38
- package/src/legal-core/index.ts +12 -12
- package/src/marketing-core/index.ts +62 -0
- package/src/marketing-schema.ts +9 -9
- package/src/mcp.ts +4 -4
- package/src/native.ts +14 -14
- package/src/next-revalidate.ts +10 -10
- package/src/notifications-core/index.ts +1 -1
- package/src/parallel-pages.ts +6 -6
- package/src/portal-core/index.ts +1 -1
- package/src/proxy.ts +28 -28
- package/src/push-core/index.ts +11 -5
- package/src/qwik.tsx +262 -166
- package/src/react-analytics.tsx +17 -17
- package/src/react-attribution.tsx +2 -2
- package/src/react-marketing.tsx +5 -5
- package/src/react.tsx +541 -500
- package/src/reserved-paths.ts +3 -3
- package/src/revalidate-verify.ts +5 -5
- package/src/sdk.ts +131 -101
- package/src/seed-core/index.ts +8 -8
- package/src/seo-core/blog.ts +2 -2
- package/src/seo-core/index.ts +1 -1
- package/src/seo.ts +1 -1
- package/src/sitemap-core/index.ts +17 -9
- package/src/socials.ts +6 -6
- package/src/solid-compat.tsx +5 -5
- package/src/solid-surfaces.tsx +28 -28
- package/src/solid.tsx +264 -175
- package/src/store-core/index.ts +1 -1
- package/src/styles/{biab-forms.css → bd-forms.css} +158 -158
- package/src/svelte/{BiabForm.svelte → BdForm.svelte} +240 -173
- package/src/svelte/context.ts +16 -16
- package/src/svelte/headless.ts +10 -10
- package/src/svelte/index.ts +16 -16
- package/src/vanilla.ts +250 -169
- package/src/vue/{BiabForm.vue → BdForm.vue} +270 -157
- package/src/vue/headless.ts +11 -11
- package/src/vue/index.ts +26 -26
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
* ```ts
|
|
26
26
|
* const consent = await loadConsent({ client });
|
|
27
27
|
* if (consent.allows('analytics')) {
|
|
28
|
-
*
|
|
28
|
+
* initBdAnalytics({ siteId, baseUrl, apiKey });
|
|
29
29
|
* }
|
|
30
30
|
* if (consent.mustAsk) showYourBanner(consent);
|
|
31
31
|
* ```
|
|
32
32
|
*
|
|
33
|
-
* `
|
|
33
|
+
* `initBdAnalytics` is deliberately NOT made to call this itself. A gate that
|
|
34
34
|
* fires implicitly is one nobody can see in review, and the decision of what
|
|
35
35
|
* happens before consent — render nothing, render a placeholder, collect
|
|
36
36
|
* essential-only — belongs to the site, not to us.
|
|
@@ -73,8 +73,8 @@ export type ConsentClientLike = {
|
|
|
73
73
|
}): Promise<unknown>;
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
const VISITOR_COOKIE = "
|
|
77
|
-
const VISITOR_HEADER = "x-
|
|
76
|
+
const VISITOR_COOKIE = "bd_visitor";
|
|
77
|
+
const VISITOR_HEADER = "x-bd-visitor";
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
80
|
* The visitor's id for THIS site, minted on first need.
|
|
@@ -103,10 +103,12 @@ export function visitorKey(): string | null {
|
|
|
103
103
|
// SameSite=Lax and no Secure flag would leak on http; Secure is set unless
|
|
104
104
|
// we are plainly on localhost, where it would stop the cookie working at all.
|
|
105
105
|
const secure = location.protocol === "https:" ? "; Secure" : "";
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
//
|
|
106
|
+
// The suggested CookieStore API has no Safari or Firefox support. A consent
|
|
107
|
+
// banner has to work in every browser a visitor might arrive in — that is
|
|
108
|
+
// the entire point of it — so the universally supported API is the right
|
|
109
|
+
// one. (The directive below has to sit on the line immediately above the
|
|
110
|
+
// code; a multi-line one attaches to the next comment instead.)
|
|
111
|
+
// biome-ignore lint/suspicious/noDocumentCookie: no CookieStore in Safari or Firefox
|
|
110
112
|
document.cookie = `${VISITOR_COOKIE}=${encodeURIComponent(key)}; Path=/; Max-Age=31536000; SameSite=Lax${secure}`;
|
|
111
113
|
return key;
|
|
112
114
|
}
|
package/src/contracts.ts
CHANGED
|
@@ -455,7 +455,7 @@ export type ChatbotMessage = z.infer<typeof chatbotMessageSchema>;
|
|
|
455
455
|
/**
|
|
456
456
|
* Per-call provider override (BYO key). When set, the turn runs against the
|
|
457
457
|
* SDK consumer's own LLM account — their `apiKey`, their billing — instead
|
|
458
|
-
* of the
|
|
458
|
+
* of the BD platform's configured provider, and the platform's monthly
|
|
459
459
|
* token budget is bypassed for that call.
|
|
460
460
|
*
|
|
461
461
|
* **Server-only.** Never send this from a browser: the key would be visible
|
|
@@ -968,7 +968,7 @@ export type ListSiteMarketingPagesResponse = z.infer<
|
|
|
968
968
|
export const customerPortalOrgSchema = z.object({
|
|
969
969
|
id: z.string().uuid(),
|
|
970
970
|
name: z.string().nullable(),
|
|
971
|
-
/** @deprecated Internal auth-provider org id — use `id` (the
|
|
971
|
+
/** @deprecated Internal auth-provider org id — use `id` (the BD org id).
|
|
972
972
|
* Kept for backwards compatibility; will be removed in a future release. */
|
|
973
973
|
workosOrganizationId: z.string().nullable().optional(),
|
|
974
974
|
});
|
|
@@ -1045,7 +1045,7 @@ export const customerPortalUpdateProfileResponseSchema = z.object({
|
|
|
1045
1045
|
export const customerPortalOtherOrgSchema = z.object({
|
|
1046
1046
|
orgId: z.string().uuid(),
|
|
1047
1047
|
name: z.string().nullable(),
|
|
1048
|
-
/** @deprecated Internal auth-provider org id — use `orgId` (the
|
|
1048
|
+
/** @deprecated Internal auth-provider org id — use `orgId` (the BD org id).
|
|
1049
1049
|
* Kept for backwards compatibility; will be removed in a future release. */
|
|
1050
1050
|
workosOrganizationId: z.string().nullable().optional(),
|
|
1051
1051
|
});
|
|
@@ -1162,6 +1162,10 @@ export const customerQuoteSummarySchema = z.object({
|
|
|
1162
1162
|
totalAmount: z.number(),
|
|
1163
1163
|
validUntil: z.string(),
|
|
1164
1164
|
publicAcceptUrl: z.string().nullable(),
|
|
1165
|
+
/** True when the quote carries a narrative — a PROPOSAL rather than a
|
|
1166
|
+
* bare price. Optional so an older server that does not send it still
|
|
1167
|
+
* parses; treat a missing value as false. */
|
|
1168
|
+
isProposal: z.boolean().optional(),
|
|
1165
1169
|
});
|
|
1166
1170
|
|
|
1167
1171
|
export const customerInvoiceSummarySchema = z.object({
|
|
@@ -1243,6 +1247,59 @@ export type CustomerWorkBundle = z.infer<typeof customerWorkBundleSchema>;
|
|
|
1243
1247
|
|
|
1244
1248
|
export const customerJobDetailSchema = customerJobSummarySchema.passthrough();
|
|
1245
1249
|
|
|
1250
|
+
/** One line on a quote. Was `z.unknown()`, which left every consumer to
|
|
1251
|
+
* guess at the shape before it could render a row. */
|
|
1252
|
+
export const customerQuoteLineItemSchema = z
|
|
1253
|
+
.object({
|
|
1254
|
+
description: z.string(),
|
|
1255
|
+
quantity: z.number(),
|
|
1256
|
+
unitPrice: z.number(),
|
|
1257
|
+
total: z.number(),
|
|
1258
|
+
manufacturer: z.string().optional(),
|
|
1259
|
+
modelNo: z.string().optional(),
|
|
1260
|
+
type: z.string().optional(),
|
|
1261
|
+
category: z.string().optional(),
|
|
1262
|
+
})
|
|
1263
|
+
.passthrough();
|
|
1264
|
+
|
|
1265
|
+
/** One narrative section of a proposal. `body` is plain text; blank lines
|
|
1266
|
+
* separate paragraphs. */
|
|
1267
|
+
export const customerQuoteSectionSchema = z.object({
|
|
1268
|
+
id: z.string(),
|
|
1269
|
+
title: z.string(),
|
|
1270
|
+
body: z.string(),
|
|
1271
|
+
});
|
|
1272
|
+
|
|
1273
|
+
/**
|
|
1274
|
+
* A designed proposal, as a customer receives it.
|
|
1275
|
+
*
|
|
1276
|
+
* Distinct from `customerQuoteDetailSchema`, which is the quote itself. A
|
|
1277
|
+
* proposal is the DOCUMENT built around that quote — either a rendered PDF
|
|
1278
|
+
* or a live page — and a consumer needs to know which before deciding
|
|
1279
|
+
* whether to offer a download or an iframe.
|
|
1280
|
+
*
|
|
1281
|
+
* Deliberately carries no template, no bindings and no resolved snapshot:
|
|
1282
|
+
* those describe how the org builds proposals, and a customer's SDK has no
|
|
1283
|
+
* business reading them.
|
|
1284
|
+
*/
|
|
1285
|
+
export const customerProposalSchema = z.object({
|
|
1286
|
+
id: z.string(),
|
|
1287
|
+
quoteId: z.string(),
|
|
1288
|
+
/** `pdf` — fetch `pdfUrl`. `web` — frame `pageUrl`. */
|
|
1289
|
+
kind: openEnum("pdf", "web"),
|
|
1290
|
+
title: z.string(),
|
|
1291
|
+
/** Host-less path, like every other URL in this contract, so a storefront
|
|
1292
|
+
* on any domain can resolve it against its own origin. */
|
|
1293
|
+
pdfUrl: z.string().nullable().default(null),
|
|
1294
|
+
pageUrl: z.string().nullable().default(null),
|
|
1295
|
+
createdAt: z.string(),
|
|
1296
|
+
renderedAt: z.string().nullable().default(null),
|
|
1297
|
+
});
|
|
1298
|
+
|
|
1299
|
+
export const customerProposalListResponseSchema = z.object({
|
|
1300
|
+
items: z.array(customerProposalSchema),
|
|
1301
|
+
});
|
|
1302
|
+
|
|
1246
1303
|
export const customerQuoteDetailSchema = z
|
|
1247
1304
|
.object({
|
|
1248
1305
|
id: z.string(),
|
|
@@ -1256,7 +1313,7 @@ export const customerQuoteDetailSchema = z
|
|
|
1256
1313
|
"converted",
|
|
1257
1314
|
"expired",
|
|
1258
1315
|
),
|
|
1259
|
-
items: z.array(
|
|
1316
|
+
items: z.array(customerQuoteLineItemSchema),
|
|
1260
1317
|
subtotalAmount: z.number(),
|
|
1261
1318
|
discountAmount: z.number(),
|
|
1262
1319
|
taxRate: z.number(),
|
|
@@ -1265,6 +1322,27 @@ export const customerQuoteDetailSchema = z
|
|
|
1265
1322
|
validUntil: z.string(),
|
|
1266
1323
|
publicAcceptUrl: z.string().nullable(),
|
|
1267
1324
|
notes: z.string().nullable(),
|
|
1325
|
+
/**
|
|
1326
|
+
* The proposal narrative — cover letter, scope of work, terms. Empty
|
|
1327
|
+
* for a plain quote. This is the half that makes a quote a sales
|
|
1328
|
+
* proposal; rendering only `items` gives the customer a price list
|
|
1329
|
+
* where they were sent an argument.
|
|
1330
|
+
*/
|
|
1331
|
+
sections: z.array(customerQuoteSectionSchema).default([]),
|
|
1332
|
+
/** Derived from `sections`, so it can never disagree with them. */
|
|
1333
|
+
isProposal: z.boolean().default(false),
|
|
1334
|
+
/** Captured at send-time, so a proposal stays reproducible after the
|
|
1335
|
+
* org's billing details change. */
|
|
1336
|
+
senderName: z.string().nullable().default(null),
|
|
1337
|
+
senderEmail: z.string().nullable().default(null),
|
|
1338
|
+
sentAt: z.string().nullable().default(null),
|
|
1339
|
+
acceptedAt: z.string().nullable().default(null),
|
|
1340
|
+
rejectedAt: z.string().nullable().default(null),
|
|
1341
|
+
/** Whether `acceptQuote` would succeed right now: sent, in date, not
|
|
1342
|
+
* already decided. Do not re-derive this from `status` — expiry is a
|
|
1343
|
+
* date comparison the server has already made. */
|
|
1344
|
+
canAccept: z.boolean().default(false),
|
|
1345
|
+
expired: z.boolean().default(false),
|
|
1268
1346
|
})
|
|
1269
1347
|
.passthrough();
|
|
1270
1348
|
|
|
@@ -1343,7 +1421,7 @@ export const customerInvoiceDetailSchema = z
|
|
|
1343
1421
|
notes: z.string().nullable(),
|
|
1344
1422
|
terms: z.string().nullable(),
|
|
1345
1423
|
publicPayUrl: z.string().nullable(),
|
|
1346
|
-
// Optional so the SDK stays compatible with older
|
|
1424
|
+
// Optional so the SDK stays compatible with older BD deployments
|
|
1347
1425
|
// that don't return these yet.
|
|
1348
1426
|
/** Recorded payments/refunds, oldest first. */
|
|
1349
1427
|
payments: z.array(customerInvoicePaymentSchema).optional(),
|
|
@@ -1613,7 +1691,7 @@ export const customerOrderDetailSchema = z.object({
|
|
|
1613
1691
|
createdAt: z.string(),
|
|
1614
1692
|
items: z.array(customerOrderItemSchema),
|
|
1615
1693
|
shipments: z.array(customerShipmentSchema),
|
|
1616
|
-
// Optional for back-compat with older
|
|
1694
|
+
// Optional for back-compat with older BD deployments.
|
|
1617
1695
|
returnRequests: z.array(customerReturnRequestSchema).optional(),
|
|
1618
1696
|
});
|
|
1619
1697
|
|
|
@@ -2019,7 +2097,7 @@ export const customerProductReviewCreatedSchema = z.object({
|
|
|
2019
2097
|
export const customerDownloadSchema = z.object({
|
|
2020
2098
|
productName: z.string(),
|
|
2021
2099
|
fileName: z.string().nullable(),
|
|
2022
|
-
/** Short-lived presigned URL (
|
|
2100
|
+
/** Short-lived presigned URL (BD-hosted) or the org's external link. */
|
|
2023
2101
|
url: z.string(),
|
|
2024
2102
|
/** Seconds until `url` expires; null for a non-expiring external link. */
|
|
2025
2103
|
expiresInSeconds: z.number().nullable(),
|
|
@@ -2117,7 +2195,13 @@ export const siteBrandingSchema = z.object({
|
|
|
2117
2195
|
export type SiteBranding = z.infer<typeof siteBrandingSchema>;
|
|
2118
2196
|
|
|
2119
2197
|
export type CustomerJobDetail = z.infer<typeof customerJobDetailSchema>;
|
|
2198
|
+
export type CustomerProposal = z.infer<typeof customerProposalSchema>;
|
|
2199
|
+
export type CustomerProposalListResponse = z.infer<
|
|
2200
|
+
typeof customerProposalListResponseSchema
|
|
2201
|
+
>;
|
|
2120
2202
|
export type CustomerQuoteDetail = z.infer<typeof customerQuoteDetailSchema>;
|
|
2203
|
+
export type CustomerQuoteLineItem = z.infer<typeof customerQuoteLineItemSchema>;
|
|
2204
|
+
export type CustomerQuoteSection = z.infer<typeof customerQuoteSectionSchema>;
|
|
2121
2205
|
export type CustomerInvoiceDetail = z.infer<typeof customerInvoiceDetailSchema>;
|
|
2122
2206
|
export type CustomerInvoicePayment = z.infer<
|
|
2123
2207
|
typeof customerInvoicePaymentSchema
|
|
@@ -3063,7 +3147,7 @@ export type ShippingSettingsResponse = z.infer<
|
|
|
3063
3147
|
>;
|
|
3064
3148
|
|
|
3065
3149
|
// ── Customer notification preferences (Batch shipping, 0.9.0) ─────────
|
|
3066
|
-
// Distinct from the
|
|
3150
|
+
// Distinct from the BD-user notification prefs in this file —
|
|
3067
3151
|
// these are per-customer-per-org preferences exposed via the SDK so
|
|
3068
3152
|
// the *consumer's* site can render a preferences UI for its signed-
|
|
3069
3153
|
// in shoppers (in-app / email / SMS / outbound webhook).
|
|
@@ -3452,7 +3536,7 @@ export const siteMarketingSeoDataSchema = z.object({
|
|
|
3452
3536
|
// Bundle: brand / company / gallery / reviews surfaces
|
|
3453
3537
|
//
|
|
3454
3538
|
// Added in SDK 0.8.4. Prior versions zod-stripped these keys at the
|
|
3455
|
-
// response boundary even though the
|
|
3539
|
+
// response boundary even though the BD server already shipped them
|
|
3456
3540
|
// (the underlying `.passthrough()` in this file is on a chatbot
|
|
3457
3541
|
// schema, NOT on the bundle response). Consumers that need the
|
|
3458
3542
|
// stripped data on older SDK versions can raw-fetch
|
|
@@ -3515,7 +3599,7 @@ export const companyLocationSchema = z.object({
|
|
|
3515
3599
|
/**
|
|
3516
3600
|
* Loose-typed CompanyProfileRow. The server-side shape is fully
|
|
3517
3601
|
* typed; we keep this looser at the SDK boundary so adding a column
|
|
3518
|
-
* on the
|
|
3602
|
+
* on the BD side doesn't break older SDK consumers.
|
|
3519
3603
|
*/
|
|
3520
3604
|
const companyProfileRowSchema = z
|
|
3521
3605
|
.object({
|
|
@@ -3665,7 +3749,7 @@ export type ReviewWallListResponse = z.infer<
|
|
|
3665
3749
|
/**
|
|
3666
3750
|
* Org-owned marketing-page banner (announcement strip / marquee).
|
|
3667
3751
|
* Mirrors the platform-banner shape so consumer storefronts can
|
|
3668
|
-
* render a near-identical UI to
|
|
3752
|
+
* render a near-identical UI to BD's own marketing banner.
|
|
3669
3753
|
* `null` when the org hasn't enabled one or has no visible messages.
|
|
3670
3754
|
*/
|
|
3671
3755
|
const bundleBannerMessageSchema = z
|
|
@@ -3747,7 +3831,7 @@ export const getMarketingPageBundleResponseSchema = z
|
|
|
3747
3831
|
// New in 0.9.6:
|
|
3748
3832
|
updates: bundleUpdatesSchema.optional(),
|
|
3749
3833
|
})
|
|
3750
|
-
// `.passthrough()` at the top level so any future
|
|
3834
|
+
// `.passthrough()` at the top level so any future BD-side
|
|
3751
3835
|
// addition (e.g. bundle.events, bundle.faq, etc.) flows through
|
|
3752
3836
|
// to consumers without an SDK release — the lesson from the
|
|
3753
3837
|
// brand/company/gallery/reviews oversight on this version.
|
|
@@ -3784,7 +3868,7 @@ export const getMarketingLocalesResponseSchema = z.object({
|
|
|
3784
3868
|
});
|
|
3785
3869
|
|
|
3786
3870
|
/**
|
|
3787
|
-
* Bulk section upsert — sent by `
|
|
3871
|
+
* Bulk section upsert — sent by `bd sync-content`.
|
|
3788
3872
|
*
|
|
3789
3873
|
* One request carries up to 256 items (server-enforced). The CLI batches
|
|
3790
3874
|
* larger imports automatically. Each item is a single
|
|
@@ -3944,7 +4028,7 @@ export type ListDataModelRecordsResponse = z.infer<
|
|
|
3944
4028
|
|
|
3945
4029
|
// ── Analytics: reading visitor counts ────────────────────────────────
|
|
3946
4030
|
//
|
|
3947
|
-
// The read half of site analytics. The `<
|
|
4031
|
+
// The read half of site analytics. The `<BDAnalytics/>` tracker records
|
|
3948
4032
|
// pageviews (write-only); these read the totals back so a site can show them.
|
|
3949
4033
|
|
|
3950
4034
|
export const viewCountSchema = z.object({
|
|
@@ -4119,7 +4203,7 @@ export const jobPostingSchema = z.object({
|
|
|
4119
4203
|
salaryMax: z.number().nullable(),
|
|
4120
4204
|
currency: z.string().nullable(),
|
|
4121
4205
|
/**
|
|
4122
|
-
* Pass to `client.forms.schema()` / `<
|
|
4206
|
+
* Pass to `client.forms.schema()` / `<BdForm/>` to render the application
|
|
4123
4207
|
* form. `null` means the posting is listed but not yet accepting applications.
|
|
4124
4208
|
*/
|
|
4125
4209
|
applicationFormId: z.string().nullable(),
|
package/src/data-model-schema.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `defineDataModel` — declare an org's custom database (tables + enums) in
|
|
3
|
-
* code, push it with `
|
|
3
|
+
* code, push it with `bd sync-data-model`, promote it in the dashboard.
|
|
4
4
|
*
|
|
5
5
|
* Deliberately SEPARATE from `marketing-schema.ts`. A website's content shape
|
|
6
6
|
* and an org's database shape are different artifacts with different review
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
* config files, commands, endpoints, and API scopes. Nothing is shared but the
|
|
9
9
|
* transport conventions (canonical checksum, draft/published slots).
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* bd.config.ts → defineSiteMarketingSchema → sync-schema
|
|
12
|
+
* bd.data-model.config.ts → defineDataModel → sync-data-model
|
|
13
13
|
*
|
|
14
14
|
* Pure builders — no DB, no network, no side effects. Validation here is about
|
|
15
15
|
* catching a typo in CI before it becomes a push; the server re-validates
|
|
16
16
|
* everything it receives and is the real authority.
|
|
17
17
|
*
|
|
18
|
-
* See Resources/
|
|
18
|
+
* See Resources/BD-Data-Model-CLI-Plan.md for the full design.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
// ── Field types ──────────────────────────────────────────────────────
|
|
@@ -136,7 +136,7 @@ export interface FieldBuilder<
|
|
|
136
136
|
* This record may reference SEVERAL of `targetCollection`.
|
|
137
137
|
*
|
|
138
138
|
* That's the whole declaration — there is no join table to name, design, or
|
|
139
|
-
* maintain.
|
|
139
|
+
* maintain. BD stores every link in one universal link table, so "many"
|
|
140
140
|
* is a property of the relation rather than a second collection the author
|
|
141
141
|
* has to invent and keep in step.
|
|
142
142
|
*
|
|
@@ -149,7 +149,7 @@ export interface FieldBuilder<
|
|
|
149
149
|
belongsToMany: (
|
|
150
150
|
targetCollection: string,
|
|
151
151
|
options?: {
|
|
152
|
-
/** @deprecated Ignored —
|
|
152
|
+
/** @deprecated Ignored — BD has no per-pair join table to name. */
|
|
153
153
|
joinCollectionName?: string;
|
|
154
154
|
fields?: Record<string, AnyFieldBuilder>;
|
|
155
155
|
},
|
|
@@ -231,7 +231,7 @@ type OptionalFieldKeys<F extends Record<string, AnyFieldBuilder>> = Exclude<
|
|
|
231
231
|
|
|
232
232
|
type Simplify<T> = { [K in keyof T]: T[K] } & {};
|
|
233
233
|
|
|
234
|
-
/** Infer an object value type from a map of
|
|
234
|
+
/** Infer an object value type from a map of BD field declarations. */
|
|
235
235
|
export type InferFieldsValues<F extends Record<string, AnyFieldBuilder>> =
|
|
236
236
|
Simplify<
|
|
237
237
|
{
|
|
@@ -961,7 +961,7 @@ export function collection<F extends Record<string, AnyFieldBuilder>>(
|
|
|
961
961
|
|
|
962
962
|
const universalIdentifier =
|
|
963
963
|
options.universalIdentifier ??
|
|
964
|
-
generateUniversalIdentifier(`
|
|
964
|
+
generateUniversalIdentifier(`bd:collection:${nameSingular}`);
|
|
965
965
|
|
|
966
966
|
// Build fields with proper names and labels, collecting relation metadata
|
|
967
967
|
const fieldEntries = Object.entries(options.fields);
|
|
@@ -986,7 +986,7 @@ export function collection<F extends Record<string, AnyFieldBuilder>>(
|
|
|
986
986
|
fields.push({
|
|
987
987
|
...fieldDef,
|
|
988
988
|
universalIdentifier: generateUniversalIdentifier(
|
|
989
|
-
`
|
|
989
|
+
`bd:collection:${nameSingular}:field:${fieldName}`,
|
|
990
990
|
),
|
|
991
991
|
name: fieldName,
|
|
992
992
|
label: toLabel(fieldName),
|
|
@@ -1046,7 +1046,7 @@ export function isRelationFieldType(type: FieldType): boolean {
|
|
|
1046
1046
|
// ── Enums (SELECT options) ───────────────────────────────────────────
|
|
1047
1047
|
|
|
1048
1048
|
/**
|
|
1049
|
-
* One value in a SELECT / MULTI_SELECT field — what
|
|
1049
|
+
* One value in a SELECT / MULTI_SELECT field — what BD calls an "enum".
|
|
1050
1050
|
* Not a native Postgres enum: options are metadata, so adding or relabelling
|
|
1051
1051
|
* one costs no migration.
|
|
1052
1052
|
*/
|
|
@@ -1118,6 +1118,7 @@ export type ExtTextType =
|
|
|
1118
1118
|
|
|
1119
1119
|
export type ExtObjectType =
|
|
1120
1120
|
| "address_group"
|
|
1121
|
+
| "name_group"
|
|
1121
1122
|
| "measurement"
|
|
1122
1123
|
| "availability"
|
|
1123
1124
|
| "object"
|
|
@@ -1565,6 +1566,7 @@ const FIELD_FORM_ELEMENT_MAP: Partial<Record<FieldType, AllFormElements[]>> = {
|
|
|
1565
1566
|
RICH_TEXT: ["rich_text_input"],
|
|
1566
1567
|
RAW_JSON: [
|
|
1567
1568
|
"address_group",
|
|
1569
|
+
"name_group",
|
|
1568
1570
|
"measurement",
|
|
1569
1571
|
"availability",
|
|
1570
1572
|
"date_range",
|
|
@@ -1656,7 +1658,7 @@ export type FieldDefinition = {
|
|
|
1656
1658
|
};
|
|
1657
1659
|
|
|
1658
1660
|
/** One typed attribute carried on a many-to-many link row. Mirrors
|
|
1659
|
-
* `LinkAttributeDef` on the
|
|
1661
|
+
* `LinkAttributeDef` on the BD side (`src/shared/data-model/link-attributes.ts`). */
|
|
1660
1662
|
export type LinkAttributeDefinition = {
|
|
1661
1663
|
name: string;
|
|
1662
1664
|
label: string;
|
|
@@ -1792,7 +1794,7 @@ export const objectVisibilityValues: readonly ObjectVisibility[] = [
|
|
|
1792
1794
|
export type ObjectDefinition = {
|
|
1793
1795
|
/** Stable identity. Survives renames. */
|
|
1794
1796
|
universalIdentifier: string;
|
|
1795
|
-
/** `custom` (a new table) or `standard` (custom fields on a
|
|
1797
|
+
/** `custom` (a new table) or `standard` (custom fields on a BD entity). */
|
|
1796
1798
|
kind?: ObjectKind;
|
|
1797
1799
|
/**
|
|
1798
1800
|
* Who may read these rows from outside. Defaults to `private`.
|
|
@@ -1813,7 +1815,7 @@ export type ObjectDefinition = {
|
|
|
1813
1815
|
/** Which field is a record's headline. Must be one of `fields`. */
|
|
1814
1816
|
labelIdentifierFieldName?: string;
|
|
1815
1817
|
/**
|
|
1816
|
-
* `kind: "standard"` only — the
|
|
1818
|
+
* `kind: "standard"` only — the BD entity these fields attach to
|
|
1817
1819
|
* (e.g. "contact"). The object's own system fields stay immutable from
|
|
1818
1820
|
* the CLI; only custom fields are yours to declare.
|
|
1819
1821
|
*/
|
|
@@ -2078,7 +2080,7 @@ export interface SchemaOptions {
|
|
|
2078
2080
|
|
|
2079
2081
|
/**
|
|
2080
2082
|
* Declare the org's custom database schema. Default-export the result from
|
|
2081
|
-
* `
|
|
2083
|
+
* `bd.data-model.config.ts`.
|
|
2082
2084
|
*
|
|
2083
2085
|
* ```ts
|
|
2084
2086
|
* export default createSchema({
|
|
@@ -2121,7 +2123,7 @@ export function createSchema(
|
|
|
2121
2123
|
if (hasId) continue;
|
|
2122
2124
|
const idStrategy: PrimaryKeyType = col.idType ?? globalIdType;
|
|
2123
2125
|
const idUid = generateUniversalIdentifier(
|
|
2124
|
-
`
|
|
2126
|
+
`bd:collection:${object.nameSingular}:field:id`,
|
|
2125
2127
|
);
|
|
2126
2128
|
col.fields.unshift({
|
|
2127
2129
|
universalIdentifier: idUid,
|
|
@@ -2206,13 +2208,13 @@ export function createSchema(
|
|
|
2206
2208
|
? `target${capitalizedSource}Id`
|
|
2207
2209
|
: `${targetObj.nameSingular}Id`;
|
|
2208
2210
|
const junctionUid = generateUniversalIdentifier(
|
|
2209
|
-
`
|
|
2211
|
+
`bd:collection:${joinSingular}`,
|
|
2210
2212
|
);
|
|
2211
2213
|
const sourceUid = generateUniversalIdentifier(
|
|
2212
|
-
`
|
|
2214
|
+
`bd:collection:${joinSingular}:field:${sourceFkName}`,
|
|
2213
2215
|
);
|
|
2214
2216
|
const targetUid = generateUniversalIdentifier(
|
|
2215
|
-
`
|
|
2217
|
+
`bd:collection:${joinSingular}:field:${targetFkName}`,
|
|
2216
2218
|
);
|
|
2217
2219
|
|
|
2218
2220
|
// Resolve cascade behavior: explicit onDeleteAction, then default to CASCADE
|
|
@@ -2225,7 +2227,7 @@ export function createSchema(
|
|
|
2225
2227
|
const junctionIdType: PrimaryKeyType =
|
|
2226
2228
|
(object as CollectionDefinition).idType ?? globalIdType;
|
|
2227
2229
|
const junctionIdUid = generateUniversalIdentifier(
|
|
2228
|
-
`
|
|
2230
|
+
`bd:collection:${joinSingular}:field:id`,
|
|
2229
2231
|
);
|
|
2230
2232
|
|
|
2231
2233
|
const junctionFields: FieldDefinition[] = [
|
|
@@ -2272,7 +2274,7 @@ export function createSchema(
|
|
|
2272
2274
|
junctionFields.push({
|
|
2273
2275
|
...addDef,
|
|
2274
2276
|
universalIdentifier: generateUniversalIdentifier(
|
|
2275
|
-
`
|
|
2277
|
+
`bd:collection:${joinSingular}:field:${addName}`,
|
|
2276
2278
|
),
|
|
2277
2279
|
name: addName,
|
|
2278
2280
|
label: toLabel(addName),
|
|
@@ -2811,7 +2813,7 @@ export interface FormAndSchemaConfig<
|
|
|
2811
2813
|
|
|
2812
2814
|
/** A custom-form draft generated from one compiled collection. */
|
|
2813
2815
|
export type GeneratedFormCandidate = {
|
|
2814
|
-
/** Stable key used by
|
|
2816
|
+
/** Stable key used by BD to update this generated draft idempotently. */
|
|
2815
2817
|
sourceKey: string;
|
|
2816
2818
|
name: string;
|
|
2817
2819
|
slug: string;
|
|
@@ -2819,7 +2821,7 @@ export type GeneratedFormCandidate = {
|
|
|
2819
2821
|
fields: Array<{
|
|
2820
2822
|
id: string;
|
|
2821
2823
|
label: string;
|
|
2822
|
-
/**
|
|
2824
|
+
/** BD custom-form renderer element type. */
|
|
2823
2825
|
type: string;
|
|
2824
2826
|
required: boolean;
|
|
2825
2827
|
outputKey: string;
|
|
@@ -3150,6 +3152,7 @@ function toPersistedFormElement(element: AllFormElements): string {
|
|
|
3150
3152
|
time_picker_timeslot: "time_picker",
|
|
3151
3153
|
time_picker_datetime: "time_picker",
|
|
3152
3154
|
address_group: "address",
|
|
3155
|
+
name_group: "name",
|
|
3153
3156
|
range: "slider",
|
|
3154
3157
|
formFileValue: "file_upload",
|
|
3155
3158
|
};
|
|
@@ -3183,7 +3186,7 @@ function generateCollectionFormCandidates(
|
|
|
3183
3186
|
const type = toPersistedFormElement(declaredElement);
|
|
3184
3187
|
|
|
3185
3188
|
const id = generateUniversalIdentifier(
|
|
3186
|
-
`
|
|
3189
|
+
`bd:generated-form:${object.universalIdentifier}:field:${field.universalIdentifier}`,
|
|
3187
3190
|
);
|
|
3188
3191
|
fieldMap[field.name] = id;
|
|
3189
3192
|
const relationTarget = field.relationTarget
|
|
@@ -3280,7 +3283,7 @@ function generateCollectionFormCandidates(
|
|
|
3280
3283
|
actions: [
|
|
3281
3284
|
{
|
|
3282
3285
|
id: generateUniversalIdentifier(
|
|
3283
|
-
`
|
|
3286
|
+
`bd:generated-form:${object.universalIdentifier}:action:create-record`,
|
|
3284
3287
|
),
|
|
3285
3288
|
type: "create_records" as const,
|
|
3286
3289
|
enabled: true as const,
|
|
@@ -3342,7 +3345,7 @@ function recordIdentityField(
|
|
|
3342
3345
|
): GeneratedFormCandidate["fields"][number] {
|
|
3343
3346
|
return {
|
|
3344
3347
|
id: generateUniversalIdentifier(
|
|
3345
|
-
`
|
|
3348
|
+
`bd:generated-form:${object.universalIdentifier}:${purpose}:record`,
|
|
3346
3349
|
),
|
|
3347
3350
|
label: object.labelSingular,
|
|
3348
3351
|
type: "collection_select",
|
|
@@ -3838,7 +3841,7 @@ export function createFormSchemaOrchestrator(
|
|
|
3838
3841
|
actions: [
|
|
3839
3842
|
{
|
|
3840
3843
|
id: generateUniversalIdentifier(
|
|
3841
|
-
`
|
|
3844
|
+
`bd:generated-form:${sourceKey}:action:create-records`,
|
|
3842
3845
|
),
|
|
3843
3846
|
type: "create_records",
|
|
3844
3847
|
enabled: true,
|
package/src/distribution.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* The llms.txt convention only works at the site's own root (an AI crawler
|
|
6
6
|
* asks for https://yoursite.com/llms.txt), while the source of truth lives
|
|
7
|
-
* on
|
|
7
|
+
* on BD where the org curates it. This proxies the two together.
|
|
8
8
|
*
|
|
9
9
|
* Next.js wiring (app/llms.txt/route.ts):
|
|
10
10
|
*
|
|
@@ -12,18 +12,18 @@
|
|
|
12
12
|
* import { llmsTxtHandler } from '@businessdash/sdk/distribution'
|
|
13
13
|
*
|
|
14
14
|
* export const GET = llmsTxtHandler({
|
|
15
|
-
* siteId: process.env.
|
|
16
|
-
* baseUrl: process.env.
|
|
15
|
+
* siteId: process.env.BD_SITE_ID!,
|
|
16
|
+
* baseUrl: process.env.NEXT_PUBLIC_BD_APP_URL!, // e.g. https://www.biab.app
|
|
17
17
|
* })
|
|
18
18
|
* ```
|
|
19
19
|
*
|
|
20
|
-
* The product feed needs no proxy — you submit its
|
|
20
|
+
* The product feed needs no proxy — you submit its BD URL directly to a
|
|
21
21
|
* merchant program — but `productFeedUrl` builds it for display/submission.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
export type DistributionSourceOptions = {
|
|
25
25
|
siteId: string;
|
|
26
|
-
/**
|
|
26
|
+
/** BD app origin, e.g. "https://www.biab.app". */
|
|
27
27
|
baseUrl: string;
|
|
28
28
|
};
|
|
29
29
|
|