@businessdash/sdk 0.9.81 → 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 +115 -902
- 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 +350 -273
- 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 +1 -1
- package/dist/push-core/index.d.ts +1 -1
- package/dist/push-core/index.js +1 -1
- 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 +49 -49
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +47 -51
- 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 +3 -3
- package/dist/sitemap-core/index.js +2 -2
- 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 +2 -2
- 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 +106 -110
- 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 +2 -2
- 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
package/src/reserved-paths.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Page paths reserved by the
|
|
3
|
-
*
|
|
2
|
+
* Page paths reserved by the BD platform. These routes are served by
|
|
3
|
+
* BD on every verified org hostname (`pay.acme.com/quotes/accept/<token>`,
|
|
4
4
|
* `acme.com/contracts/sign/<token>`, etc.), so a marketing page declared at
|
|
5
5
|
* one of these paths would collide and silently break customer-facing
|
|
6
6
|
* accept / sign / pay flows.
|
|
@@ -56,7 +56,7 @@ export function isReservedPagePath(input: string): boolean {
|
|
|
56
56
|
*/
|
|
57
57
|
export function reservedPagePathErrorMessage(input: string): string {
|
|
58
58
|
return [
|
|
59
|
-
`"${input}" is reserved by the
|
|
59
|
+
`"${input}" is reserved by the BD platform.`,
|
|
60
60
|
`Reserved paths: ${RESERVED_PAGE_PATHS.join(", ")}.`,
|
|
61
61
|
`These routes are served on every verified org hostname for quote / contract / invoice flows;`,
|
|
62
62
|
`shipping a marketing page at the same path would break customer-facing accept / sign / pay links.`,
|
package/src/revalidate-verify.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Framework-agnostic HMAC verification for
|
|
2
|
+
* Framework-agnostic HMAC verification for BD revalidation
|
|
3
3
|
* webhooks. Lives in its own file so adapters (Cloudflare, KV
|
|
4
4
|
* purge, static rebuild trigger, …) can pull it in without
|
|
5
5
|
* transitively bringing the Next-only `next-revalidate.ts` into
|
|
@@ -14,7 +14,7 @@ import { createHmac, timingSafeEqual } from "node:crypto";
|
|
|
14
14
|
|
|
15
15
|
const REPLAY_WINDOW_SECONDS = 5 * 60;
|
|
16
16
|
|
|
17
|
-
export interface
|
|
17
|
+
export interface BdPublishPayload {
|
|
18
18
|
event: "content.published";
|
|
19
19
|
orgId: string;
|
|
20
20
|
tags: string[];
|
|
@@ -30,7 +30,7 @@ export interface VerifyOptions {
|
|
|
30
30
|
|
|
31
31
|
export interface VerifyResult {
|
|
32
32
|
ok: boolean;
|
|
33
|
-
payload?:
|
|
33
|
+
payload?: BdPublishPayload;
|
|
34
34
|
reason?: string;
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -81,9 +81,9 @@ export function verifyAndExtractTags(opts: VerifyOptions): VerifyResult {
|
|
|
81
81
|
return { ok: false, reason: "signature_mismatch" };
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
let payload:
|
|
84
|
+
let payload: BdPublishPayload;
|
|
85
85
|
try {
|
|
86
|
-
payload = JSON.parse(opts.rawBody) as
|
|
86
|
+
payload = JSON.parse(opts.rawBody) as BdPublishPayload;
|
|
87
87
|
} catch {
|
|
88
88
|
return { ok: false, reason: "body_not_json" };
|
|
89
89
|
}
|
package/src/sdk.ts
CHANGED
|
@@ -5,44 +5,44 @@
|
|
|
5
5
|
* and that's it. Auth, caching, revalidation, tagging, retries — all
|
|
6
6
|
* handled inside this module so the consumer code reads as:
|
|
7
7
|
*
|
|
8
|
-
* const items = await
|
|
8
|
+
* const items = await bd.gallery.list({
|
|
9
9
|
* limit: 12,
|
|
10
10
|
* fields: ["src", "title", "category", "blurDataURL"],
|
|
11
11
|
* });
|
|
12
12
|
*
|
|
13
13
|
* Auto-applied per request:
|
|
14
14
|
* • `Authorization: Bearer <apiKey>`
|
|
15
|
-
* • `next: { tags: ["
|
|
15
|
+
* • `next: { tags: ["bd:<resource>", "bd:site:<orgId-when-known>"],
|
|
16
16
|
* revalidate: <longBackstop> }` — invisible on non-Next
|
|
17
17
|
* runtimes that ignore the `next` key
|
|
18
18
|
* • Field selection forwarded as `?fields=…` so the platform
|
|
19
19
|
* SELECTs only what's needed.
|
|
20
20
|
*
|
|
21
21
|
* The companion `@businessdash/sdk/next/revalidate` route export closes
|
|
22
|
-
* the loop: when
|
|
22
|
+
* the loop: when BD POSTs `content.published`, the route handler
|
|
23
23
|
* verifies the HMAC and calls `revalidateTag(...)` to bust the local
|
|
24
24
|
* Next cache. End-to-end, the consumer wrote ~5 lines.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
27
|
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
type
|
|
44
|
-
|
|
45
|
-
|
|
28
|
+
BdAddressClient,
|
|
29
|
+
BdApiClient,
|
|
30
|
+
BdBlogClient,
|
|
31
|
+
BdCartClient,
|
|
32
|
+
BdCheckoutClient,
|
|
33
|
+
BdCouponsClient,
|
|
34
|
+
BdCustomerPortalClient,
|
|
35
|
+
BdFollowersClient,
|
|
36
|
+
BdLegalClient,
|
|
37
|
+
BdMarketingClient,
|
|
38
|
+
BdMarketingPagesClient,
|
|
39
|
+
BdNotificationsClient,
|
|
40
|
+
BdParallelPagesClient,
|
|
41
|
+
BdReviewsClient,
|
|
42
|
+
BdShippingClient,
|
|
43
|
+
type BdSiteClient,
|
|
44
|
+
BdStorefrontClient,
|
|
45
|
+
BdSubscriptionsClient,
|
|
46
46
|
} from "./client.js";
|
|
47
47
|
import {
|
|
48
48
|
getEmailDomain,
|
|
@@ -56,7 +56,7 @@ import type { BundleGalleryItem } from "./gallery-types.js";
|
|
|
56
56
|
const DEFAULT_BASE_URL = "https://biab.app/api/package/v1";
|
|
57
57
|
const DEFAULT_REVALIDATE_SECONDS = 60 * 60 * 24; // 24h backstop
|
|
58
58
|
|
|
59
|
-
export interface
|
|
59
|
+
export interface CreateBdClientOptions {
|
|
60
60
|
apiKey: string;
|
|
61
61
|
siteId: string;
|
|
62
62
|
baseUrl?: string;
|
|
@@ -113,7 +113,7 @@ async function jsonGet<T>(
|
|
|
113
113
|
if (!res.ok) {
|
|
114
114
|
const text = await res.text().catch(() => "");
|
|
115
115
|
throw new Error(
|
|
116
|
-
`
|
|
116
|
+
`BD SDK ${res.status} ${res.statusText} on ${pathWithQuery}: ${text.slice(0, 200)}`,
|
|
117
117
|
);
|
|
118
118
|
}
|
|
119
119
|
return (await res.json()) as T;
|
|
@@ -152,7 +152,7 @@ function createGalleryResource(state: InternalState): GalleryResource {
|
|
|
152
152
|
}
|
|
153
153
|
const qs = query.toString();
|
|
154
154
|
const path = `sites/${encodeURIComponent(state.siteId)}/gallery${qs ? `?${qs}` : ""}`;
|
|
155
|
-
const tags = ["
|
|
155
|
+
const tags = ["bd:gallery", `bd:site:${state.siteId}`];
|
|
156
156
|
// The server projects to exactly the requested `fields`, so the row
|
|
157
157
|
// shape is `GalleryItemFor<F>` — a fact only the wire can vouch for.
|
|
158
158
|
// Stating it as the fetch's type argument confines the assumption to
|
|
@@ -329,14 +329,14 @@ function createSchedulingResource(state: InternalState): SchedulingResource {
|
|
|
329
329
|
if (!res.ok) {
|
|
330
330
|
const text = await res.text().catch(() => "");
|
|
331
331
|
throw new Error(
|
|
332
|
-
`
|
|
332
|
+
`BD SDK ${res.status} ${res.statusText} on ${path}: ${text.slice(0, 200)}`,
|
|
333
333
|
);
|
|
334
334
|
}
|
|
335
335
|
return (await res.json()) as T;
|
|
336
336
|
}
|
|
337
337
|
return {
|
|
338
338
|
async listEventTypes() {
|
|
339
|
-
const tags = ["
|
|
339
|
+
const tags = ["bd:scheduling", `bd:site:${state.siteId}`];
|
|
340
340
|
const result = await jsonGet<{ items: SchedulingEventType[] }>(
|
|
341
341
|
state,
|
|
342
342
|
`${sitePath}/event-types`,
|
|
@@ -346,9 +346,9 @@ function createSchedulingResource(state: InternalState): SchedulingResource {
|
|
|
346
346
|
},
|
|
347
347
|
async getEventType(slug) {
|
|
348
348
|
const tags = [
|
|
349
|
-
"
|
|
350
|
-
`
|
|
351
|
-
`
|
|
349
|
+
"bd:scheduling",
|
|
350
|
+
`bd:scheduling:event:${slug}`,
|
|
351
|
+
`bd:site:${state.siteId}`,
|
|
352
352
|
];
|
|
353
353
|
return await jsonGet(
|
|
354
354
|
state,
|
|
@@ -375,7 +375,7 @@ function createSchedulingResource(state: InternalState): SchedulingResource {
|
|
|
375
375
|
if (!res.ok) {
|
|
376
376
|
const text = await res.text().catch(() => "");
|
|
377
377
|
throw new Error(
|
|
378
|
-
`
|
|
378
|
+
`BD SDK ${res.status} ${res.statusText} on ${path}: ${text.slice(0, 200)}`,
|
|
379
379
|
);
|
|
380
380
|
}
|
|
381
381
|
const data = (await res.json()) as { slots: SchedulingSlot[] };
|
|
@@ -407,7 +407,7 @@ function createSchedulingResource(state: InternalState): SchedulingResource {
|
|
|
407
407
|
if (!res.ok) {
|
|
408
408
|
const text = await res.text().catch(() => "");
|
|
409
409
|
throw new Error(
|
|
410
|
-
`
|
|
410
|
+
`BD SDK ${res.status} ${res.statusText}: ${text.slice(0, 200)}`,
|
|
411
411
|
);
|
|
412
412
|
}
|
|
413
413
|
return (await res.json()) as SchedulingBookingView;
|
|
@@ -441,7 +441,7 @@ function createSchedulingResource(state: InternalState): SchedulingResource {
|
|
|
441
441
|
// ---------------------------------------------------------------------------
|
|
442
442
|
|
|
443
443
|
/**
|
|
444
|
-
* Public-facing description of one form field. Mirrors
|
|
444
|
+
* Public-facing description of one form field. Mirrors BD's
|
|
445
445
|
* `FormField` type so the consumer can type their submission payload
|
|
446
446
|
* against the schema fetched at runtime.
|
|
447
447
|
*/
|
|
@@ -610,7 +610,7 @@ export interface FormFieldDef {
|
|
|
610
610
|
sensitive?: boolean;
|
|
611
611
|
};
|
|
612
612
|
/**
|
|
613
|
-
* `credit_card` element — collect a card via Stripe Elements (`<
|
|
613
|
+
* `credit_card` element — collect a card via Stripe Elements (`<BdForm/>`
|
|
614
614
|
* only). `card_on_file` saves the card (SetupIntent); `deposit` charges
|
|
615
615
|
* `amountCents` now (PaymentIntent). The card is created on the org's Stripe
|
|
616
616
|
* connected account via `forms.paymentIntent(slug, fieldId)`; the submission
|
|
@@ -626,7 +626,7 @@ export interface FormFieldDef {
|
|
|
626
626
|
/**
|
|
627
627
|
* `schedule` element (availability v1). The visitor states when they're free;
|
|
628
628
|
* the submitted value is `{ asap?, days?: string[], times?: string[], notes? }`.
|
|
629
|
-
* `<
|
|
629
|
+
* `<BdForm/>` renders day + time-window chips, an ASAP toggle, and notes.
|
|
630
630
|
* Added in 0.9.9.
|
|
631
631
|
*/
|
|
632
632
|
scheduleConfig?: {
|
|
@@ -659,7 +659,7 @@ export interface FormRenderSettings {
|
|
|
659
659
|
showProgress?: boolean;
|
|
660
660
|
progressStyle?: "bar" | "steps";
|
|
661
661
|
/**
|
|
662
|
-
* Warn before the visitor abandons a dirty, unsubmitted form. `<
|
|
662
|
+
* Warn before the visitor abandons a dirty, unsubmitted form. `<BdForm/>`
|
|
663
663
|
* attaches a `beforeunload` guard when `enabled` (the browser shows a generic
|
|
664
664
|
* prompt); `message` is provided so you can show it in your own modal too.
|
|
665
665
|
*/
|
|
@@ -698,7 +698,7 @@ export interface FormActionPreview {
|
|
|
698
698
|
} | null;
|
|
699
699
|
/**
|
|
700
700
|
* `grant_coupon` only: the display-safe coupon notice to show before submit
|
|
701
|
-
* (e.g. "{code} will be applied to this inquiry"). `<
|
|
701
|
+
* (e.g. "{code} will be applied to this inquiry"). `<BdForm/>` renders it
|
|
702
702
|
* above the submit button. The coupon id / field mapping never leave the
|
|
703
703
|
* server. Added in 0.9.9.
|
|
704
704
|
*/
|
|
@@ -773,18 +773,18 @@ export interface FormValidationResult {
|
|
|
773
773
|
* Runtime validate a submission against the fetched form schema.
|
|
774
774
|
* Returns `ok: true` only when every required field is present and
|
|
775
775
|
* every supplied value passes its type / min / max / regex /
|
|
776
|
-
* options check. Designed to mirror what
|
|
776
|
+
* options check. Designed to mirror what BD's server enforces so
|
|
777
777
|
* the consumer can show inline errors before round-tripping.
|
|
778
778
|
*
|
|
779
|
-
* For build-time type safety, the future `
|
|
779
|
+
* For build-time type safety, the future `bd codegen forms`
|
|
780
780
|
* CLI emits a `.d.ts` per form so TypeScript can also enforce
|
|
781
781
|
* shape at compile time. Until that ships, this runtime check is
|
|
782
782
|
* the safety net.
|
|
783
783
|
*/
|
|
784
784
|
|
|
785
785
|
/**
|
|
786
|
-
* Narrow check for the shape `
|
|
787
|
-
* mirrors what the
|
|
786
|
+
* Narrow check for the shape `bd.forms.uploadFile` returns —
|
|
787
|
+
* mirrors what the BD hiring mirror reads (storageId, url, name,
|
|
788
788
|
* mimeType, size). Used by both `validateFormSubmission` and any
|
|
789
789
|
* caller that wants to assert "this value is a successful upload."
|
|
790
790
|
*/
|
|
@@ -1061,7 +1061,7 @@ export function validateFormSubmission(
|
|
|
1061
1061
|
fieldId: field.id,
|
|
1062
1062
|
label: field.label,
|
|
1063
1063
|
reason: "type",
|
|
1064
|
-
message: `${field.label} must be uploaded via
|
|
1064
|
+
message: `${field.label} must be uploaded via bd.forms.uploadFile().`,
|
|
1065
1065
|
});
|
|
1066
1066
|
}
|
|
1067
1067
|
if (
|
|
@@ -1164,14 +1164,14 @@ export function validateFormSubmission(
|
|
|
1164
1164
|
* - `forbidden` — the key lacks the scope/permission, or the request origin
|
|
1165
1165
|
* isn't on the key's allowed-host list (403).
|
|
1166
1166
|
* - `plan_required` — the org's plan doesn't include forms (entitlement gate).
|
|
1167
|
-
* - `payment_required` — the org's
|
|
1168
|
-
* - `service_suspended` — the org's
|
|
1167
|
+
* - `payment_required` — the org's BD billing is past due.
|
|
1168
|
+
* - `service_suspended` — the org's BD billing has lapsed 60+ days.
|
|
1169
1169
|
* - `rate_limited` — too many submissions too fast (429).
|
|
1170
1170
|
* - `not_found` — the form doesn't exist, is inactive, or isn't accepting
|
|
1171
1171
|
* external submissions (404).
|
|
1172
1172
|
* - `invalid_request` — the request body was malformed (400).
|
|
1173
|
-
* - `server_error` —
|
|
1174
|
-
* - `network_error` — the request never reached
|
|
1173
|
+
* - `server_error` — BD failed to process the submission (5xx).
|
|
1174
|
+
* - `network_error` — the request never reached BD (offline, DNS, CORS, …).
|
|
1175
1175
|
*/
|
|
1176
1176
|
export type FormSubmitFailureReason =
|
|
1177
1177
|
| "client_validation_failed"
|
|
@@ -1202,12 +1202,12 @@ export type FormSubmitResult =
|
|
|
1202
1202
|
slug?: string;
|
|
1203
1203
|
/** True when this was a `dryRun` — validated but not stored. */
|
|
1204
1204
|
dryRun?: boolean;
|
|
1205
|
-
/** Any additional fields
|
|
1205
|
+
/** Any additional fields BD returned (forward-compat). */
|
|
1206
1206
|
[key: string]: unknown;
|
|
1207
1207
|
}
|
|
1208
1208
|
| {
|
|
1209
1209
|
ok: false;
|
|
1210
|
-
/** HTTP status, or 0 when the request never reached
|
|
1210
|
+
/** HTTP status, or 0 when the request never reached BD. */
|
|
1211
1211
|
status: number;
|
|
1212
1212
|
reason: FormSubmitFailureReason;
|
|
1213
1213
|
/** Human-readable summary, safe to surface to the consumer. */
|
|
@@ -1218,14 +1218,14 @@ export type FormSubmitResult =
|
|
|
1218
1218
|
|
|
1219
1219
|
export interface FormsResource {
|
|
1220
1220
|
/**
|
|
1221
|
-
* Fetch the form's field definitions. Cached via `
|
|
1222
|
-
* + `
|
|
1221
|
+
* Fetch the form's field definitions. Cached via `bd:forms`
|
|
1222
|
+
* + `bd:forms:<slug>` tags so admin edits invalidate via the
|
|
1223
1223
|
* webhook layer.
|
|
1224
1224
|
*/
|
|
1225
1225
|
schema(slug: string): Promise<FormSchema>;
|
|
1226
1226
|
/**
|
|
1227
1227
|
* Submit a form. Validates against the schema client-side (via
|
|
1228
|
-
* `validateFormSubmission`) before round-tripping, then posts to
|
|
1228
|
+
* `validateFormSubmission`) before round-tripping, then posts to BD.
|
|
1229
1229
|
*
|
|
1230
1230
|
* Always resolves to a {@link FormSubmitResult} — it does NOT throw for an
|
|
1231
1231
|
* expected failure. Check `result.ok`; on failure, `result.reason` says what
|
|
@@ -1255,10 +1255,10 @@ export interface FormsResource {
|
|
|
1255
1255
|
/**
|
|
1256
1256
|
* Upload a single file for a file-type field on the form.
|
|
1257
1257
|
*
|
|
1258
|
-
* 1. Calls the
|
|
1258
|
+
* 1. Calls the BD upload-url endpoint to get a presigned PUT
|
|
1259
1259
|
* URL + storageId (the server validates the form, field,
|
|
1260
1260
|
* MIME type, and size cap against the org's plan).
|
|
1261
|
-
* 2. PUTs the file bytes directly to R2 —
|
|
1261
|
+
* 2. PUTs the file bytes directly to R2 — BD never sees the
|
|
1262
1262
|
* bytes, only the metadata.
|
|
1263
1263
|
* 3. Returns a `FormFileValue` to drop into the form's `data`
|
|
1264
1264
|
* payload when calling `submit`.
|
|
@@ -1273,17 +1273,17 @@ export interface FormsResource {
|
|
|
1273
1273
|
opts?: { filename?: string },
|
|
1274
1274
|
): Promise<FormFileValue>;
|
|
1275
1275
|
/**
|
|
1276
|
-
* Mint a Stripe intent for a `credit_card` field so `<
|
|
1276
|
+
* Mint a Stripe intent for a `credit_card` field so `<BdForm/>` can mount
|
|
1277
1277
|
* Stripe Elements. `card_on_file` → a SetupIntent; `deposit` → a PaymentIntent
|
|
1278
1278
|
* for the configured amount. The intent is created on the org's connected
|
|
1279
1279
|
* account; initialize Stripe with `{ stripeAccount: connectedAccountId }` and
|
|
1280
1280
|
* the returned `publishableKey`, then confirm with `clientSecret`. The card
|
|
1281
|
-
* never touches
|
|
1281
|
+
* never touches BD — only the opaque intent id flows back in the submission.
|
|
1282
1282
|
*/
|
|
1283
1283
|
paymentIntent(slug: string, fieldId: string): Promise<FormPaymentIntent>;
|
|
1284
1284
|
/**
|
|
1285
1285
|
* Open booking slots for an auto-mode `schedule` field — the form's assigned
|
|
1286
|
-
* staff's combined real availability over [from, to]. `<
|
|
1286
|
+
* staff's combined real availability over [from, to]. `<BdForm/>` renders
|
|
1287
1287
|
* the instant-booking picker from these; the visitor picks one and the
|
|
1288
1288
|
* meeting books on submit. Returns absolute UTC instants (`startAt`); host
|
|
1289
1289
|
* identities stay server-side. Empty when the org lacks the scheduling
|
|
@@ -1375,7 +1375,7 @@ function mapSubmitResponse(
|
|
|
1375
1375
|
function mapSubmitThrow(err: unknown): FormSubmitResult {
|
|
1376
1376
|
if (err instanceof Error) {
|
|
1377
1377
|
// `jsonGet` embeds the HTTP status in its message — recover it if present.
|
|
1378
|
-
const m = err.message.match(/
|
|
1378
|
+
const m = err.message.match(/BD SDK (\d{3})/);
|
|
1379
1379
|
if (m) return mapSubmitResponse(Number(m[1]), null);
|
|
1380
1380
|
return {
|
|
1381
1381
|
ok: false,
|
|
@@ -1398,11 +1398,7 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1398
1398
|
// Non-chatbot form read: a form is reachable here when it is **Live**
|
|
1399
1399
|
// (`isActive`) — independent of `chatbotAccess`. Embedding a form on
|
|
1400
1400
|
// your own page no longer requires opting it into the AI chatbot.
|
|
1401
|
-
const tags = [
|
|
1402
|
-
"biab:forms",
|
|
1403
|
-
`biab:forms:${slug}`,
|
|
1404
|
-
`biab:site:${state.siteId}`,
|
|
1405
|
-
];
|
|
1401
|
+
const tags = ["bd:forms", `bd:forms:${slug}`, `bd:site:${state.siteId}`];
|
|
1406
1402
|
const path = `forms/${encodeURIComponent(slug)}`;
|
|
1407
1403
|
const result = await jsonGet<{
|
|
1408
1404
|
id: string;
|
|
@@ -1471,8 +1467,8 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1471
1467
|
reason: "network_error",
|
|
1472
1468
|
message:
|
|
1473
1469
|
err instanceof Error
|
|
1474
|
-
? `Could not reach
|
|
1475
|
-
: "Could not reach
|
|
1470
|
+
? `Could not reach BD: ${err.message}`
|
|
1471
|
+
: "Could not reach BD.",
|
|
1476
1472
|
};
|
|
1477
1473
|
}
|
|
1478
1474
|
|
|
@@ -1518,11 +1514,11 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1518
1514
|
const text = await presignRes.text().catch(() => "");
|
|
1519
1515
|
if (presignRes.status === 403 || presignRes.status === 402) {
|
|
1520
1516
|
throw new Error(
|
|
1521
|
-
`
|
|
1517
|
+
`BD SDK: file upload requires the "forms.file_uploads" entitlement on this org. ${text.slice(0, 200)}`,
|
|
1522
1518
|
);
|
|
1523
1519
|
}
|
|
1524
1520
|
throw new Error(
|
|
1525
|
-
`
|
|
1521
|
+
`BD SDK ${presignRes.status} ${presignRes.statusText} on upload-url: ${text.slice(0, 200)}`,
|
|
1526
1522
|
);
|
|
1527
1523
|
}
|
|
1528
1524
|
const presign = (await presignRes.json()) as {
|
|
@@ -1541,7 +1537,7 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1541
1537
|
if (!putRes.ok) {
|
|
1542
1538
|
const text = await putRes.text().catch(() => "");
|
|
1543
1539
|
throw new Error(
|
|
1544
|
-
`
|
|
1540
|
+
`BD SDK upload to R2 failed: ${putRes.status} ${putRes.statusText}: ${text.slice(0, 200)}`,
|
|
1545
1541
|
);
|
|
1546
1542
|
}
|
|
1547
1543
|
|
|
@@ -1568,7 +1564,7 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1568
1564
|
if (!res.ok) {
|
|
1569
1565
|
const text = await res.text().catch(() => "");
|
|
1570
1566
|
throw new Error(
|
|
1571
|
-
`
|
|
1567
|
+
`BD SDK ${res.status} ${res.statusText} on payment-intent: ${text.slice(0, 200)}`,
|
|
1572
1568
|
);
|
|
1573
1569
|
}
|
|
1574
1570
|
return (await res.json()) as FormPaymentIntent;
|
|
@@ -1588,7 +1584,7 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1588
1584
|
if (!res.ok) {
|
|
1589
1585
|
const text = await res.text().catch(() => "");
|
|
1590
1586
|
throw new Error(
|
|
1591
|
-
`
|
|
1587
|
+
`BD SDK ${res.status} ${res.statusText} on schedule-slots: ${text.slice(0, 200)}`,
|
|
1592
1588
|
);
|
|
1593
1589
|
}
|
|
1594
1590
|
return (await res.json()) as { slots: Array<{ startAt: string }> };
|
|
@@ -1600,7 +1596,7 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1600
1596
|
// Top-level client
|
|
1601
1597
|
// ---------------------------------------------------------------------------
|
|
1602
1598
|
|
|
1603
|
-
export interface
|
|
1599
|
+
export interface BdClient {
|
|
1604
1600
|
gallery: GalleryResource;
|
|
1605
1601
|
scheduling: SchedulingResource;
|
|
1606
1602
|
forms: FormsResource;
|
|
@@ -1609,39 +1605,39 @@ export interface BiabClient {
|
|
|
1609
1605
|
// long-form transport for its surface; the consumer pattern is
|
|
1610
1606
|
// `client.<resource>.<method>(...)`. Field selection / typed
|
|
1611
1607
|
// narrowing lands here surface-by-surface (gallery shipped first).
|
|
1612
|
-
blog:
|
|
1613
|
-
reviews:
|
|
1614
|
-
storefront:
|
|
1615
|
-
cart:
|
|
1616
|
-
checkout:
|
|
1617
|
-
coupons:
|
|
1618
|
-
subscriptions:
|
|
1619
|
-
shipping:
|
|
1620
|
-
address:
|
|
1621
|
-
customerPortal:
|
|
1622
|
-
notifications:
|
|
1623
|
-
followers:
|
|
1608
|
+
blog: BdBlogClient;
|
|
1609
|
+
reviews: BdReviewsClient;
|
|
1610
|
+
storefront: BdStorefrontClient;
|
|
1611
|
+
cart: BdCartClient;
|
|
1612
|
+
checkout: BdCheckoutClient;
|
|
1613
|
+
coupons: BdCouponsClient;
|
|
1614
|
+
subscriptions: BdSubscriptionsClient;
|
|
1615
|
+
shipping: BdShippingClient;
|
|
1616
|
+
address: BdAddressClient;
|
|
1617
|
+
customerPortal: BdCustomerPortalClient;
|
|
1618
|
+
notifications: BdNotificationsClient;
|
|
1619
|
+
followers: BdFollowersClient;
|
|
1624
1620
|
// The org's published legal pages — what `@businessdash/sdk/legal`'s
|
|
1625
1621
|
// resolver expects a client to carry, so the starters' catch-all
|
|
1626
|
-
// route works on THIS facade, not only on the raw
|
|
1627
|
-
legal:
|
|
1622
|
+
// route works on THIS facade, not only on the raw BdApiClient.
|
|
1623
|
+
legal: BdLegalClient;
|
|
1628
1624
|
// Site-scoped surfaces (collections, rows, data model, analytics,
|
|
1629
|
-
// scheduling, …). A METHOD mirroring `
|
|
1625
|
+
// scheduling, …). A METHOD mirroring `BdApiClient.site(siteId)` —
|
|
1630
1626
|
// `@businessdash/sdk/sitemap`'s collector calls
|
|
1631
1627
|
// `client.site(siteId).sitemapEntries()`, so the starters' sitemap
|
|
1632
1628
|
// route needs the same shape on this facade.
|
|
1633
|
-
site(siteId: string):
|
|
1634
|
-
marketing:
|
|
1635
|
-
marketingPages:
|
|
1636
|
-
parallelPages:
|
|
1629
|
+
site(siteId: string): BdSiteClient;
|
|
1630
|
+
marketing: BdMarketingClient;
|
|
1631
|
+
marketingPages: BdMarketingPagesClient;
|
|
1632
|
+
parallelPages: BdParallelPagesClient;
|
|
1637
1633
|
}
|
|
1638
1634
|
|
|
1639
|
-
export function
|
|
1635
|
+
export function createBdClient(opts: CreateBdClientOptions): BdClient {
|
|
1640
1636
|
if (!opts.apiKey) {
|
|
1641
|
-
throw new Error("
|
|
1637
|
+
throw new Error("createBdClient: apiKey is required.");
|
|
1642
1638
|
}
|
|
1643
1639
|
if (!opts.siteId) {
|
|
1644
|
-
throw new Error("
|
|
1640
|
+
throw new Error("createBdClient: siteId is required.");
|
|
1645
1641
|
}
|
|
1646
1642
|
const state: InternalState = {
|
|
1647
1643
|
apiKey: opts.apiKey,
|
|
@@ -1651,7 +1647,7 @@ export function createBiabClient(opts: CreateBiabClientOptions): BiabClient {
|
|
|
1651
1647
|
fetch: opts.fetch ?? globalThis.fetch.bind(globalThis),
|
|
1652
1648
|
siteOrigin: opts.siteOrigin,
|
|
1653
1649
|
};
|
|
1654
|
-
const transport = new
|
|
1650
|
+
const transport = new BdApiClient({
|
|
1655
1651
|
baseUrl: state.baseUrl,
|
|
1656
1652
|
apiKey: state.apiKey,
|
|
1657
1653
|
...(opts.fetch ? { fetch: opts.fetch } : {}),
|
|
@@ -1661,26 +1657,26 @@ export function createBiabClient(opts: CreateBiabClientOptions): BiabClient {
|
|
|
1661
1657
|
gallery: createGalleryResource(state),
|
|
1662
1658
|
scheduling: createSchedulingResource(state),
|
|
1663
1659
|
forms: createFormsResource(state),
|
|
1664
|
-
blog: new
|
|
1665
|
-
reviews: new
|
|
1666
|
-
storefront: new
|
|
1667
|
-
cart: new
|
|
1668
|
-
checkout: new
|
|
1669
|
-
coupons: new
|
|
1670
|
-
subscriptions: new
|
|
1671
|
-
shipping: new
|
|
1672
|
-
address: new
|
|
1660
|
+
blog: new BdBlogClient(transport),
|
|
1661
|
+
reviews: new BdReviewsClient(transport),
|
|
1662
|
+
storefront: new BdStorefrontClient(transport),
|
|
1663
|
+
cart: new BdCartClient(transport, state.siteId),
|
|
1664
|
+
checkout: new BdCheckoutClient(transport, state.siteId),
|
|
1665
|
+
coupons: new BdCouponsClient(transport),
|
|
1666
|
+
subscriptions: new BdSubscriptionsClient(transport),
|
|
1667
|
+
shipping: new BdShippingClient(transport, state.siteId),
|
|
1668
|
+
address: new BdAddressClient(transport),
|
|
1673
1669
|
// CustomerPortal needs an org id binding; when the consumer's API
|
|
1674
1670
|
// key already binds an org, pass `null` here (server resolves via
|
|
1675
1671
|
// the key). For multi-tenant proxies, override after construction.
|
|
1676
|
-
customerPortal: new
|
|
1677
|
-
notifications: new
|
|
1678
|
-
followers: new
|
|
1679
|
-
legal: new
|
|
1672
|
+
customerPortal: new BdCustomerPortalClient(transport, null),
|
|
1673
|
+
notifications: new BdNotificationsClient(transport, state.siteId),
|
|
1674
|
+
followers: new BdFollowersClient(transport, state.siteId),
|
|
1675
|
+
legal: new BdLegalClient(transport),
|
|
1680
1676
|
site: (siteId: string) => transport.site(siteId),
|
|
1681
|
-
marketing: new
|
|
1682
|
-
marketingPages: new
|
|
1683
|
-
parallelPages: new
|
|
1677
|
+
marketing: new BdMarketingClient(transport, state.siteId),
|
|
1678
|
+
marketingPages: new BdMarketingPagesClient(transport, state.siteId),
|
|
1679
|
+
parallelPages: new BdParallelPagesClient(transport, state.siteId),
|
|
1684
1680
|
};
|
|
1685
1681
|
}
|
|
1686
1682
|
|
|
@@ -1694,12 +1690,12 @@ export function createBiabClient(opts: CreateBiabClientOptions): BiabClient {
|
|
|
1694
1690
|
* here, before a release. Type-only; erased from the emitted JS. */
|
|
1695
1691
|
type MustBeTrue<T extends true> = T;
|
|
1696
1692
|
export type FacadeServesLegalRoutes = MustBeTrue<
|
|
1697
|
-
|
|
1693
|
+
BdClient extends import("./legal-core/index.js").LegalClientLike
|
|
1698
1694
|
? true
|
|
1699
1695
|
: false
|
|
1700
1696
|
>;
|
|
1701
1697
|
export type FacadeServesSitemapRoutes = MustBeTrue<
|
|
1702
|
-
|
|
1698
|
+
BdClient extends import("./sitemap-core/index.js").SitemapClientLike
|
|
1703
1699
|
? true
|
|
1704
1700
|
: false
|
|
1705
1701
|
>;
|
package/src/seed-core/index.ts
CHANGED
|
@@ -694,22 +694,22 @@ export function seedTargetFromEnv(
|
|
|
694
694
|
? {}
|
|
695
695
|
: process.env,
|
|
696
696
|
): SeedTarget {
|
|
697
|
-
//
|
|
697
|
+
// BD_API_KEY first, because that is the name the CLI reads and the name
|
|
698
698
|
// every starter's .env.example sets. Reading a different name would mean a
|
|
699
699
|
// project whose CLI works fine still fails here, with an error naming a
|
|
700
700
|
// variable the consumer has never seen.
|
|
701
701
|
const apiKey =
|
|
702
|
-
env.
|
|
703
|
-
const siteId = env.
|
|
702
|
+
env.BD_API_KEY ?? env.BUSINESSDASH_API_KEY ?? env.BD_PACKAGE_API_KEY;
|
|
703
|
+
const siteId = env.BD_SITE_ID ?? env.BUSINESSDASH_SITE_ID;
|
|
704
704
|
const baseUrl =
|
|
705
|
-
env.
|
|
705
|
+
env.BD_PACKAGE_API_BASE_URL ??
|
|
706
706
|
env.BUSINESSDASH_API_BASE_URL ??
|
|
707
|
-
env.
|
|
707
|
+
env.NEXT_PUBLIC_BD_PACKAGE_API_BASE_URL;
|
|
708
708
|
|
|
709
709
|
const missing = [
|
|
710
|
-
!apiKey && "
|
|
711
|
-
!siteId && "
|
|
712
|
-
!baseUrl && "
|
|
710
|
+
!apiKey && "BD_API_KEY",
|
|
711
|
+
!siteId && "BD_SITE_ID",
|
|
712
|
+
!baseUrl && "BD_PACKAGE_API_BASE_URL",
|
|
713
713
|
].filter(Boolean);
|
|
714
714
|
|
|
715
715
|
if (missing.length > 0) {
|
package/src/seo-core/blog.ts
CHANGED
|
@@ -54,7 +54,7 @@ export type BlogPostSeoInput = {
|
|
|
54
54
|
/**
|
|
55
55
|
* CSS selector wrapping the gated body, for the paywall markup.
|
|
56
56
|
*
|
|
57
|
-
* Defaults to `.
|
|
57
|
+
* Defaults to `.bd-post-body`. It only has to match the element your
|
|
58
58
|
* template actually hides — a selector that matches nothing makes the
|
|
59
59
|
* markup a claim you are not backing up.
|
|
60
60
|
*/
|
|
@@ -108,7 +108,7 @@ export function blogPostSeo(input: BlogPostSeoInput): SeoInput {
|
|
|
108
108
|
node["hasPart"] = {
|
|
109
109
|
"@type": "WebPageElement",
|
|
110
110
|
isAccessibleForFree: false,
|
|
111
|
-
cssSelector: input.paywallSelector ?? ".
|
|
111
|
+
cssSelector: input.paywallSelector ?? ".bd-post-body",
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
114
|
|
package/src/seo-core/index.ts
CHANGED
|
@@ -557,7 +557,7 @@ export function applyToDocument(
|
|
|
557
557
|
: document,
|
|
558
558
|
): void {
|
|
559
559
|
if (!doc) return;
|
|
560
|
-
const OWNED = "data-
|
|
560
|
+
const OWNED = "data-bd-seo";
|
|
561
561
|
|
|
562
562
|
for (const existing of Array.from(doc.head.querySelectorAll(`[${OWNED}]`))) {
|
|
563
563
|
existing.remove();
|
package/src/seo.ts
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
* @module
|
|
42
42
|
*/
|
|
43
43
|
|
|
44
|
-
import {
|
|
44
|
+
import { BdAccessRejectedError } from "../errors.js";
|
|
45
45
|
import { isReservedPagePath } from "../reserved-paths.js";
|
|
46
46
|
|
|
47
47
|
/** Where a kind of platform content lives on YOUR site. */
|
|
@@ -156,7 +156,7 @@ function escapeXml(value: string): string {
|
|
|
156
156
|
* gives up on an error page.
|
|
157
157
|
*/
|
|
158
158
|
function isExpectedAbsence(cause: unknown): boolean {
|
|
159
|
-
return cause instanceof
|
|
159
|
+
return cause instanceof BdAccessRejectedError;
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
/**
|