@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
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,42 +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
|
-
|
|
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,
|
|
44
46
|
} from "./client.js";
|
|
45
47
|
import {
|
|
46
48
|
getEmailDomain,
|
|
@@ -54,7 +56,7 @@ import type { BundleGalleryItem } from "./gallery-types.js";
|
|
|
54
56
|
const DEFAULT_BASE_URL = "https://biab.app/api/package/v1";
|
|
55
57
|
const DEFAULT_REVALIDATE_SECONDS = 60 * 60 * 24; // 24h backstop
|
|
56
58
|
|
|
57
|
-
export interface
|
|
59
|
+
export interface CreateBdClientOptions {
|
|
58
60
|
apiKey: string;
|
|
59
61
|
siteId: string;
|
|
60
62
|
baseUrl?: string;
|
|
@@ -111,7 +113,7 @@ async function jsonGet<T>(
|
|
|
111
113
|
if (!res.ok) {
|
|
112
114
|
const text = await res.text().catch(() => "");
|
|
113
115
|
throw new Error(
|
|
114
|
-
`
|
|
116
|
+
`BD SDK ${res.status} ${res.statusText} on ${pathWithQuery}: ${text.slice(0, 200)}`,
|
|
115
117
|
);
|
|
116
118
|
}
|
|
117
119
|
return (await res.json()) as T;
|
|
@@ -150,7 +152,7 @@ function createGalleryResource(state: InternalState): GalleryResource {
|
|
|
150
152
|
}
|
|
151
153
|
const qs = query.toString();
|
|
152
154
|
const path = `sites/${encodeURIComponent(state.siteId)}/gallery${qs ? `?${qs}` : ""}`;
|
|
153
|
-
const tags = ["
|
|
155
|
+
const tags = ["bd:gallery", `bd:site:${state.siteId}`];
|
|
154
156
|
// The server projects to exactly the requested `fields`, so the row
|
|
155
157
|
// shape is `GalleryItemFor<F>` — a fact only the wire can vouch for.
|
|
156
158
|
// Stating it as the fetch's type argument confines the assumption to
|
|
@@ -327,14 +329,14 @@ function createSchedulingResource(state: InternalState): SchedulingResource {
|
|
|
327
329
|
if (!res.ok) {
|
|
328
330
|
const text = await res.text().catch(() => "");
|
|
329
331
|
throw new Error(
|
|
330
|
-
`
|
|
332
|
+
`BD SDK ${res.status} ${res.statusText} on ${path}: ${text.slice(0, 200)}`,
|
|
331
333
|
);
|
|
332
334
|
}
|
|
333
335
|
return (await res.json()) as T;
|
|
334
336
|
}
|
|
335
337
|
return {
|
|
336
338
|
async listEventTypes() {
|
|
337
|
-
const tags = ["
|
|
339
|
+
const tags = ["bd:scheduling", `bd:site:${state.siteId}`];
|
|
338
340
|
const result = await jsonGet<{ items: SchedulingEventType[] }>(
|
|
339
341
|
state,
|
|
340
342
|
`${sitePath}/event-types`,
|
|
@@ -344,9 +346,9 @@ function createSchedulingResource(state: InternalState): SchedulingResource {
|
|
|
344
346
|
},
|
|
345
347
|
async getEventType(slug) {
|
|
346
348
|
const tags = [
|
|
347
|
-
"
|
|
348
|
-
`
|
|
349
|
-
`
|
|
349
|
+
"bd:scheduling",
|
|
350
|
+
`bd:scheduling:event:${slug}`,
|
|
351
|
+
`bd:site:${state.siteId}`,
|
|
350
352
|
];
|
|
351
353
|
return await jsonGet(
|
|
352
354
|
state,
|
|
@@ -373,7 +375,7 @@ function createSchedulingResource(state: InternalState): SchedulingResource {
|
|
|
373
375
|
if (!res.ok) {
|
|
374
376
|
const text = await res.text().catch(() => "");
|
|
375
377
|
throw new Error(
|
|
376
|
-
`
|
|
378
|
+
`BD SDK ${res.status} ${res.statusText} on ${path}: ${text.slice(0, 200)}`,
|
|
377
379
|
);
|
|
378
380
|
}
|
|
379
381
|
const data = (await res.json()) as { slots: SchedulingSlot[] };
|
|
@@ -405,7 +407,7 @@ function createSchedulingResource(state: InternalState): SchedulingResource {
|
|
|
405
407
|
if (!res.ok) {
|
|
406
408
|
const text = await res.text().catch(() => "");
|
|
407
409
|
throw new Error(
|
|
408
|
-
`
|
|
410
|
+
`BD SDK ${res.status} ${res.statusText}: ${text.slice(0, 200)}`,
|
|
409
411
|
);
|
|
410
412
|
}
|
|
411
413
|
return (await res.json()) as SchedulingBookingView;
|
|
@@ -439,7 +441,7 @@ function createSchedulingResource(state: InternalState): SchedulingResource {
|
|
|
439
441
|
// ---------------------------------------------------------------------------
|
|
440
442
|
|
|
441
443
|
/**
|
|
442
|
-
* Public-facing description of one form field. Mirrors
|
|
444
|
+
* Public-facing description of one form field. Mirrors BD's
|
|
443
445
|
* `FormField` type so the consumer can type their submission payload
|
|
444
446
|
* against the schema fetched at runtime.
|
|
445
447
|
*/
|
|
@@ -608,7 +610,7 @@ export interface FormFieldDef {
|
|
|
608
610
|
sensitive?: boolean;
|
|
609
611
|
};
|
|
610
612
|
/**
|
|
611
|
-
* `credit_card` element — collect a card via Stripe Elements (`<
|
|
613
|
+
* `credit_card` element — collect a card via Stripe Elements (`<BdForm/>`
|
|
612
614
|
* only). `card_on_file` saves the card (SetupIntent); `deposit` charges
|
|
613
615
|
* `amountCents` now (PaymentIntent). The card is created on the org's Stripe
|
|
614
616
|
* connected account via `forms.paymentIntent(slug, fieldId)`; the submission
|
|
@@ -624,7 +626,7 @@ export interface FormFieldDef {
|
|
|
624
626
|
/**
|
|
625
627
|
* `schedule` element (availability v1). The visitor states when they're free;
|
|
626
628
|
* the submitted value is `{ asap?, days?: string[], times?: string[], notes? }`.
|
|
627
|
-
* `<
|
|
629
|
+
* `<BdForm/>` renders day + time-window chips, an ASAP toggle, and notes.
|
|
628
630
|
* Added in 0.9.9.
|
|
629
631
|
*/
|
|
630
632
|
scheduleConfig?: {
|
|
@@ -657,7 +659,7 @@ export interface FormRenderSettings {
|
|
|
657
659
|
showProgress?: boolean;
|
|
658
660
|
progressStyle?: "bar" | "steps";
|
|
659
661
|
/**
|
|
660
|
-
* Warn before the visitor abandons a dirty, unsubmitted form. `<
|
|
662
|
+
* Warn before the visitor abandons a dirty, unsubmitted form. `<BdForm/>`
|
|
661
663
|
* attaches a `beforeunload` guard when `enabled` (the browser shows a generic
|
|
662
664
|
* prompt); `message` is provided so you can show it in your own modal too.
|
|
663
665
|
*/
|
|
@@ -696,7 +698,7 @@ export interface FormActionPreview {
|
|
|
696
698
|
} | null;
|
|
697
699
|
/**
|
|
698
700
|
* `grant_coupon` only: the display-safe coupon notice to show before submit
|
|
699
|
-
* (e.g. "{code} will be applied to this inquiry"). `<
|
|
701
|
+
* (e.g. "{code} will be applied to this inquiry"). `<BdForm/>` renders it
|
|
700
702
|
* above the submit button. The coupon id / field mapping never leave the
|
|
701
703
|
* server. Added in 0.9.9.
|
|
702
704
|
*/
|
|
@@ -771,18 +773,18 @@ export interface FormValidationResult {
|
|
|
771
773
|
* Runtime validate a submission against the fetched form schema.
|
|
772
774
|
* Returns `ok: true` only when every required field is present and
|
|
773
775
|
* every supplied value passes its type / min / max / regex /
|
|
774
|
-
* options check. Designed to mirror what
|
|
776
|
+
* options check. Designed to mirror what BD's server enforces so
|
|
775
777
|
* the consumer can show inline errors before round-tripping.
|
|
776
778
|
*
|
|
777
|
-
* For build-time type safety, the future `
|
|
779
|
+
* For build-time type safety, the future `bd codegen forms`
|
|
778
780
|
* CLI emits a `.d.ts` per form so TypeScript can also enforce
|
|
779
781
|
* shape at compile time. Until that ships, this runtime check is
|
|
780
782
|
* the safety net.
|
|
781
783
|
*/
|
|
782
784
|
|
|
783
785
|
/**
|
|
784
|
-
* Narrow check for the shape `
|
|
785
|
-
* mirrors what the
|
|
786
|
+
* Narrow check for the shape `bd.forms.uploadFile` returns —
|
|
787
|
+
* mirrors what the BD hiring mirror reads (storageId, url, name,
|
|
786
788
|
* mimeType, size). Used by both `validateFormSubmission` and any
|
|
787
789
|
* caller that wants to assert "this value is a successful upload."
|
|
788
790
|
*/
|
|
@@ -1059,7 +1061,7 @@ export function validateFormSubmission(
|
|
|
1059
1061
|
fieldId: field.id,
|
|
1060
1062
|
label: field.label,
|
|
1061
1063
|
reason: "type",
|
|
1062
|
-
message: `${field.label} must be uploaded via
|
|
1064
|
+
message: `${field.label} must be uploaded via bd.forms.uploadFile().`,
|
|
1063
1065
|
});
|
|
1064
1066
|
}
|
|
1065
1067
|
if (
|
|
@@ -1162,14 +1164,14 @@ export function validateFormSubmission(
|
|
|
1162
1164
|
* - `forbidden` — the key lacks the scope/permission, or the request origin
|
|
1163
1165
|
* isn't on the key's allowed-host list (403).
|
|
1164
1166
|
* - `plan_required` — the org's plan doesn't include forms (entitlement gate).
|
|
1165
|
-
* - `payment_required` — the org's
|
|
1166
|
-
* - `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.
|
|
1167
1169
|
* - `rate_limited` — too many submissions too fast (429).
|
|
1168
1170
|
* - `not_found` — the form doesn't exist, is inactive, or isn't accepting
|
|
1169
1171
|
* external submissions (404).
|
|
1170
1172
|
* - `invalid_request` — the request body was malformed (400).
|
|
1171
|
-
* - `server_error` —
|
|
1172
|
-
* - `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, …).
|
|
1173
1175
|
*/
|
|
1174
1176
|
export type FormSubmitFailureReason =
|
|
1175
1177
|
| "client_validation_failed"
|
|
@@ -1200,12 +1202,12 @@ export type FormSubmitResult =
|
|
|
1200
1202
|
slug?: string;
|
|
1201
1203
|
/** True when this was a `dryRun` — validated but not stored. */
|
|
1202
1204
|
dryRun?: boolean;
|
|
1203
|
-
/** Any additional fields
|
|
1205
|
+
/** Any additional fields BD returned (forward-compat). */
|
|
1204
1206
|
[key: string]: unknown;
|
|
1205
1207
|
}
|
|
1206
1208
|
| {
|
|
1207
1209
|
ok: false;
|
|
1208
|
-
/** HTTP status, or 0 when the request never reached
|
|
1210
|
+
/** HTTP status, or 0 when the request never reached BD. */
|
|
1209
1211
|
status: number;
|
|
1210
1212
|
reason: FormSubmitFailureReason;
|
|
1211
1213
|
/** Human-readable summary, safe to surface to the consumer. */
|
|
@@ -1216,14 +1218,14 @@ export type FormSubmitResult =
|
|
|
1216
1218
|
|
|
1217
1219
|
export interface FormsResource {
|
|
1218
1220
|
/**
|
|
1219
|
-
* Fetch the form's field definitions. Cached via `
|
|
1220
|
-
* + `
|
|
1221
|
+
* Fetch the form's field definitions. Cached via `bd:forms`
|
|
1222
|
+
* + `bd:forms:<slug>` tags so admin edits invalidate via the
|
|
1221
1223
|
* webhook layer.
|
|
1222
1224
|
*/
|
|
1223
1225
|
schema(slug: string): Promise<FormSchema>;
|
|
1224
1226
|
/**
|
|
1225
1227
|
* Submit a form. Validates against the schema client-side (via
|
|
1226
|
-
* `validateFormSubmission`) before round-tripping, then posts to
|
|
1228
|
+
* `validateFormSubmission`) before round-tripping, then posts to BD.
|
|
1227
1229
|
*
|
|
1228
1230
|
* Always resolves to a {@link FormSubmitResult} — it does NOT throw for an
|
|
1229
1231
|
* expected failure. Check `result.ok`; on failure, `result.reason` says what
|
|
@@ -1253,10 +1255,10 @@ export interface FormsResource {
|
|
|
1253
1255
|
/**
|
|
1254
1256
|
* Upload a single file for a file-type field on the form.
|
|
1255
1257
|
*
|
|
1256
|
-
* 1. Calls the
|
|
1258
|
+
* 1. Calls the BD upload-url endpoint to get a presigned PUT
|
|
1257
1259
|
* URL + storageId (the server validates the form, field,
|
|
1258
1260
|
* MIME type, and size cap against the org's plan).
|
|
1259
|
-
* 2. PUTs the file bytes directly to R2 —
|
|
1261
|
+
* 2. PUTs the file bytes directly to R2 — BD never sees the
|
|
1260
1262
|
* bytes, only the metadata.
|
|
1261
1263
|
* 3. Returns a `FormFileValue` to drop into the form's `data`
|
|
1262
1264
|
* payload when calling `submit`.
|
|
@@ -1271,17 +1273,17 @@ export interface FormsResource {
|
|
|
1271
1273
|
opts?: { filename?: string },
|
|
1272
1274
|
): Promise<FormFileValue>;
|
|
1273
1275
|
/**
|
|
1274
|
-
* Mint a Stripe intent for a `credit_card` field so `<
|
|
1276
|
+
* Mint a Stripe intent for a `credit_card` field so `<BdForm/>` can mount
|
|
1275
1277
|
* Stripe Elements. `card_on_file` → a SetupIntent; `deposit` → a PaymentIntent
|
|
1276
1278
|
* for the configured amount. The intent is created on the org's connected
|
|
1277
1279
|
* account; initialize Stripe with `{ stripeAccount: connectedAccountId }` and
|
|
1278
1280
|
* the returned `publishableKey`, then confirm with `clientSecret`. The card
|
|
1279
|
-
* never touches
|
|
1281
|
+
* never touches BD — only the opaque intent id flows back in the submission.
|
|
1280
1282
|
*/
|
|
1281
1283
|
paymentIntent(slug: string, fieldId: string): Promise<FormPaymentIntent>;
|
|
1282
1284
|
/**
|
|
1283
1285
|
* Open booking slots for an auto-mode `schedule` field — the form's assigned
|
|
1284
|
-
* staff's combined real availability over [from, to]. `<
|
|
1286
|
+
* staff's combined real availability over [from, to]. `<BdForm/>` renders
|
|
1285
1287
|
* the instant-booking picker from these; the visitor picks one and the
|
|
1286
1288
|
* meeting books on submit. Returns absolute UTC instants (`startAt`); host
|
|
1287
1289
|
* identities stay server-side. Empty when the org lacks the scheduling
|
|
@@ -1373,7 +1375,7 @@ function mapSubmitResponse(
|
|
|
1373
1375
|
function mapSubmitThrow(err: unknown): FormSubmitResult {
|
|
1374
1376
|
if (err instanceof Error) {
|
|
1375
1377
|
// `jsonGet` embeds the HTTP status in its message — recover it if present.
|
|
1376
|
-
const m = err.message.match(/
|
|
1378
|
+
const m = err.message.match(/BD SDK (\d{3})/);
|
|
1377
1379
|
if (m) return mapSubmitResponse(Number(m[1]), null);
|
|
1378
1380
|
return {
|
|
1379
1381
|
ok: false,
|
|
@@ -1396,11 +1398,7 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1396
1398
|
// Non-chatbot form read: a form is reachable here when it is **Live**
|
|
1397
1399
|
// (`isActive`) — independent of `chatbotAccess`. Embedding a form on
|
|
1398
1400
|
// your own page no longer requires opting it into the AI chatbot.
|
|
1399
|
-
const tags = [
|
|
1400
|
-
"biab:forms",
|
|
1401
|
-
`biab:forms:${slug}`,
|
|
1402
|
-
`biab:site:${state.siteId}`,
|
|
1403
|
-
];
|
|
1401
|
+
const tags = ["bd:forms", `bd:forms:${slug}`, `bd:site:${state.siteId}`];
|
|
1404
1402
|
const path = `forms/${encodeURIComponent(slug)}`;
|
|
1405
1403
|
const result = await jsonGet<{
|
|
1406
1404
|
id: string;
|
|
@@ -1469,8 +1467,8 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1469
1467
|
reason: "network_error",
|
|
1470
1468
|
message:
|
|
1471
1469
|
err instanceof Error
|
|
1472
|
-
? `Could not reach
|
|
1473
|
-
: "Could not reach
|
|
1470
|
+
? `Could not reach BD: ${err.message}`
|
|
1471
|
+
: "Could not reach BD.",
|
|
1474
1472
|
};
|
|
1475
1473
|
}
|
|
1476
1474
|
|
|
@@ -1516,11 +1514,11 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1516
1514
|
const text = await presignRes.text().catch(() => "");
|
|
1517
1515
|
if (presignRes.status === 403 || presignRes.status === 402) {
|
|
1518
1516
|
throw new Error(
|
|
1519
|
-
`
|
|
1517
|
+
`BD SDK: file upload requires the "forms.file_uploads" entitlement on this org. ${text.slice(0, 200)}`,
|
|
1520
1518
|
);
|
|
1521
1519
|
}
|
|
1522
1520
|
throw new Error(
|
|
1523
|
-
`
|
|
1521
|
+
`BD SDK ${presignRes.status} ${presignRes.statusText} on upload-url: ${text.slice(0, 200)}`,
|
|
1524
1522
|
);
|
|
1525
1523
|
}
|
|
1526
1524
|
const presign = (await presignRes.json()) as {
|
|
@@ -1539,7 +1537,7 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1539
1537
|
if (!putRes.ok) {
|
|
1540
1538
|
const text = await putRes.text().catch(() => "");
|
|
1541
1539
|
throw new Error(
|
|
1542
|
-
`
|
|
1540
|
+
`BD SDK upload to R2 failed: ${putRes.status} ${putRes.statusText}: ${text.slice(0, 200)}`,
|
|
1543
1541
|
);
|
|
1544
1542
|
}
|
|
1545
1543
|
|
|
@@ -1566,7 +1564,7 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1566
1564
|
if (!res.ok) {
|
|
1567
1565
|
const text = await res.text().catch(() => "");
|
|
1568
1566
|
throw new Error(
|
|
1569
|
-
`
|
|
1567
|
+
`BD SDK ${res.status} ${res.statusText} on payment-intent: ${text.slice(0, 200)}`,
|
|
1570
1568
|
);
|
|
1571
1569
|
}
|
|
1572
1570
|
return (await res.json()) as FormPaymentIntent;
|
|
@@ -1586,7 +1584,7 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1586
1584
|
if (!res.ok) {
|
|
1587
1585
|
const text = await res.text().catch(() => "");
|
|
1588
1586
|
throw new Error(
|
|
1589
|
-
`
|
|
1587
|
+
`BD SDK ${res.status} ${res.statusText} on schedule-slots: ${text.slice(0, 200)}`,
|
|
1590
1588
|
);
|
|
1591
1589
|
}
|
|
1592
1590
|
return (await res.json()) as { slots: Array<{ startAt: string }> };
|
|
@@ -1598,7 +1596,7 @@ function createFormsResource(state: InternalState): FormsResource {
|
|
|
1598
1596
|
// Top-level client
|
|
1599
1597
|
// ---------------------------------------------------------------------------
|
|
1600
1598
|
|
|
1601
|
-
export interface
|
|
1599
|
+
export interface BdClient {
|
|
1602
1600
|
gallery: GalleryResource;
|
|
1603
1601
|
scheduling: SchedulingResource;
|
|
1604
1602
|
forms: FormsResource;
|
|
@@ -1607,29 +1605,39 @@ export interface BiabClient {
|
|
|
1607
1605
|
// long-form transport for its surface; the consumer pattern is
|
|
1608
1606
|
// `client.<resource>.<method>(...)`. Field selection / typed
|
|
1609
1607
|
// narrowing lands here surface-by-surface (gallery shipped first).
|
|
1610
|
-
blog:
|
|
1611
|
-
reviews:
|
|
1612
|
-
storefront:
|
|
1613
|
-
cart:
|
|
1614
|
-
checkout:
|
|
1615
|
-
coupons:
|
|
1616
|
-
subscriptions:
|
|
1617
|
-
shipping:
|
|
1618
|
-
address:
|
|
1619
|
-
customerPortal:
|
|
1620
|
-
notifications:
|
|
1621
|
-
followers:
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
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;
|
|
1620
|
+
// The org's published legal pages — what `@businessdash/sdk/legal`'s
|
|
1621
|
+
// resolver expects a client to carry, so the starters' catch-all
|
|
1622
|
+
// route works on THIS facade, not only on the raw BdApiClient.
|
|
1623
|
+
legal: BdLegalClient;
|
|
1624
|
+
// Site-scoped surfaces (collections, rows, data model, analytics,
|
|
1625
|
+
// scheduling, …). A METHOD mirroring `BdApiClient.site(siteId)` —
|
|
1626
|
+
// `@businessdash/sdk/sitemap`'s collector calls
|
|
1627
|
+
// `client.site(siteId).sitemapEntries()`, so the starters' sitemap
|
|
1628
|
+
// route needs the same shape on this facade.
|
|
1629
|
+
site(siteId: string): BdSiteClient;
|
|
1630
|
+
marketing: BdMarketingClient;
|
|
1631
|
+
marketingPages: BdMarketingPagesClient;
|
|
1632
|
+
parallelPages: BdParallelPagesClient;
|
|
1625
1633
|
}
|
|
1626
1634
|
|
|
1627
|
-
export function
|
|
1635
|
+
export function createBdClient(opts: CreateBdClientOptions): BdClient {
|
|
1628
1636
|
if (!opts.apiKey) {
|
|
1629
|
-
throw new Error("
|
|
1637
|
+
throw new Error("createBdClient: apiKey is required.");
|
|
1630
1638
|
}
|
|
1631
1639
|
if (!opts.siteId) {
|
|
1632
|
-
throw new Error("
|
|
1640
|
+
throw new Error("createBdClient: siteId is required.");
|
|
1633
1641
|
}
|
|
1634
1642
|
const state: InternalState = {
|
|
1635
1643
|
apiKey: opts.apiKey,
|
|
@@ -1639,7 +1647,7 @@ export function createBiabClient(opts: CreateBiabClientOptions): BiabClient {
|
|
|
1639
1647
|
fetch: opts.fetch ?? globalThis.fetch.bind(globalThis),
|
|
1640
1648
|
siteOrigin: opts.siteOrigin,
|
|
1641
1649
|
};
|
|
1642
|
-
const transport = new
|
|
1650
|
+
const transport = new BdApiClient({
|
|
1643
1651
|
baseUrl: state.baseUrl,
|
|
1644
1652
|
apiKey: state.apiKey,
|
|
1645
1653
|
...(opts.fetch ? { fetch: opts.fetch } : {}),
|
|
@@ -1649,23 +1657,45 @@ export function createBiabClient(opts: CreateBiabClientOptions): BiabClient {
|
|
|
1649
1657
|
gallery: createGalleryResource(state),
|
|
1650
1658
|
scheduling: createSchedulingResource(state),
|
|
1651
1659
|
forms: createFormsResource(state),
|
|
1652
|
-
blog: new
|
|
1653
|
-
reviews: new
|
|
1654
|
-
storefront: new
|
|
1655
|
-
cart: new
|
|
1656
|
-
checkout: new
|
|
1657
|
-
coupons: new
|
|
1658
|
-
subscriptions: new
|
|
1659
|
-
shipping: new
|
|
1660
|
-
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),
|
|
1661
1669
|
// CustomerPortal needs an org id binding; when the consumer's API
|
|
1662
1670
|
// key already binds an org, pass `null` here (server resolves via
|
|
1663
1671
|
// the key). For multi-tenant proxies, override after construction.
|
|
1664
|
-
customerPortal: new
|
|
1665
|
-
notifications: new
|
|
1666
|
-
followers: new
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
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),
|
|
1676
|
+
site: (siteId: string) => transport.site(siteId),
|
|
1677
|
+
marketing: new BdMarketingClient(transport, state.siteId),
|
|
1678
|
+
marketingPages: new BdMarketingPagesClient(transport, state.siteId),
|
|
1679
|
+
parallelPages: new BdParallelPagesClient(transport, state.siteId),
|
|
1670
1680
|
};
|
|
1671
1681
|
}
|
|
1682
|
+
|
|
1683
|
+
/* ── Facade ↔ helper-module contracts ──────────────────────────────────
|
|
1684
|
+
* The standalone helpers (`/legal`, `/sitemap`) accept "any client that
|
|
1685
|
+
* carries the right surface", and every file-routed starter hands them
|
|
1686
|
+
* THIS facade. 0.9.80 shipped without `legal` and `site`, and three
|
|
1687
|
+
* starters stopped typechecking against the published package — a drift
|
|
1688
|
+
* only the template fleet could see. These aliases move that failure
|
|
1689
|
+
* into `pnpm typecheck`: drop a required surface and the build breaks
|
|
1690
|
+
* here, before a release. Type-only; erased from the emitted JS. */
|
|
1691
|
+
type MustBeTrue<T extends true> = T;
|
|
1692
|
+
export type FacadeServesLegalRoutes = MustBeTrue<
|
|
1693
|
+
BdClient extends import("./legal-core/index.js").LegalClientLike
|
|
1694
|
+
? true
|
|
1695
|
+
: false
|
|
1696
|
+
>;
|
|
1697
|
+
export type FacadeServesSitemapRoutes = MustBeTrue<
|
|
1698
|
+
BdClient extends import("./sitemap-core/index.js").SitemapClientLike
|
|
1699
|
+
? true
|
|
1700
|
+
: false
|
|
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();
|