@businessdash/sdk 0.9.60
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/LICENSE +21 -0
- package/README.md +899 -0
- package/dist/adapters-revalidate.d.ts +44 -0
- package/dist/adapters-revalidate.d.ts.map +1 -0
- package/dist/adapters-revalidate.js +68 -0
- package/dist/adapters-revalidate.js.map +1 -0
- package/dist/alpha.d.ts +21 -0
- package/dist/alpha.d.ts.map +1 -0
- package/dist/alpha.js +21 -0
- package/dist/alpha.js.map +1 -0
- package/dist/analytics-core.d.ts +34 -0
- package/dist/analytics-core.d.ts.map +1 -0
- package/dist/analytics-core.js +138 -0
- package/dist/analytics-core.js.map +1 -0
- package/dist/analytics-server.d.ts +54 -0
- package/dist/analytics-server.d.ts.map +1 -0
- package/dist/analytics-server.js +78 -0
- package/dist/analytics-server.js.map +1 -0
- package/dist/attribution-logo.d.ts +2 -0
- package/dist/attribution-logo.d.ts.map +1 -0
- package/dist/attribution-logo.js +5 -0
- package/dist/attribution-logo.js.map +1 -0
- package/dist/auth-handler.d.ts +92 -0
- package/dist/auth-handler.d.ts.map +1 -0
- package/dist/auth-handler.js +277 -0
- package/dist/auth-handler.js.map +1 -0
- package/dist/biab-forms.css +484 -0
- package/dist/cli.d.ts +46 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1824 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +1681 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +2845 -0
- package/dist/client.js.map +1 -0
- package/dist/collections.d.ts +13 -0
- package/dist/collections.d.ts.map +1 -0
- package/dist/collections.js +13 -0
- package/dist/collections.js.map +1 -0
- package/dist/contracts.d.ts +14609 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +2428 -0
- package/dist/contracts.js.map +1 -0
- package/dist/data-model-schema.d.ts +962 -0
- package/dist/data-model-schema.d.ts.map +1 -0
- package/dist/data-model-schema.js +2295 -0
- package/dist/data-model-schema.js.map +1 -0
- package/dist/distribution.d.ts +38 -0
- package/dist/distribution.d.ts.map +1 -0
- package/dist/distribution.js +61 -0
- package/dist/distribution.js.map +1 -0
- package/dist/element.d.ts +121 -0
- package/dist/element.d.ts.map +1 -0
- package/dist/element.js +276 -0
- package/dist/element.js.map +1 -0
- package/dist/enums.d.ts +25 -0
- package/dist/enums.d.ts.map +1 -0
- package/dist/enums.js +38 -0
- package/dist/enums.js.map +1 -0
- package/dist/errors.d.ts +195 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +188 -0
- package/dist/errors.js.map +1 -0
- package/dist/forms-core/autocomplete.d.ts +37 -0
- package/dist/forms-core/autocomplete.d.ts.map +1 -0
- package/dist/forms-core/autocomplete.js +82 -0
- package/dist/forms-core/autocomplete.js.map +1 -0
- package/dist/forms-core/business-function.d.ts +61 -0
- package/dist/forms-core/business-function.d.ts.map +1 -0
- package/dist/forms-core/business-function.js +149 -0
- package/dist/forms-core/business-function.js.map +1 -0
- package/dist/forms-core/calculation.d.ts +72 -0
- package/dist/forms-core/calculation.d.ts.map +1 -0
- package/dist/forms-core/calculation.js +103 -0
- package/dist/forms-core/calculation.js.map +1 -0
- package/dist/forms-core/controller.d.ts +249 -0
- package/dist/forms-core/controller.d.ts.map +1 -0
- package/dist/forms-core/controller.js +590 -0
- package/dist/forms-core/controller.js.map +1 -0
- package/dist/forms-core/elements.d.ts +44 -0
- package/dist/forms-core/elements.d.ts.map +1 -0
- package/dist/forms-core/elements.js +68 -0
- package/dist/forms-core/elements.js.map +1 -0
- package/dist/forms-core/email-domains.d.ts +10 -0
- package/dist/forms-core/email-domains.d.ts.map +1 -0
- package/dist/forms-core/email-domains.js +69 -0
- package/dist/forms-core/email-domains.js.map +1 -0
- package/dist/forms-core/file-rules.d.ts +51 -0
- package/dist/forms-core/file-rules.d.ts.map +1 -0
- package/dist/forms-core/file-rules.js +105 -0
- package/dist/forms-core/file-rules.js.map +1 -0
- package/dist/forms-core/formula.d.ts +114 -0
- package/dist/forms-core/formula.d.ts.map +1 -0
- package/dist/forms-core/formula.js +1170 -0
- package/dist/forms-core/formula.js.map +1 -0
- package/dist/forms-core/index.d.ts +24 -0
- package/dist/forms-core/index.d.ts.map +1 -0
- package/dist/forms-core/index.js +28 -0
- package/dist/forms-core/index.js.map +1 -0
- package/dist/forms-core/units.d.ts +49 -0
- package/dist/forms-core/units.d.ts.map +1 -0
- package/dist/forms-core/units.js +255 -0
- package/dist/forms-core/units.js.map +1 -0
- package/dist/forms-core/us-states.d.ts +14 -0
- package/dist/forms-core/us-states.d.ts.map +1 -0
- package/dist/forms-core/us-states.js +66 -0
- package/dist/forms-core/us-states.js.map +1 -0
- package/dist/forms-core/validation.d.ts +266 -0
- package/dist/forms-core/validation.d.ts.map +1 -0
- package/dist/forms-core/validation.js +850 -0
- package/dist/forms-core/validation.js.map +1 -0
- package/dist/forms.d.ts +19 -0
- package/dist/forms.d.ts.map +1 -0
- package/dist/forms.js +29 -0
- package/dist/forms.js.map +1 -0
- package/dist/gallery-types.d.ts +32 -0
- package/dist/gallery-types.d.ts.map +1 -0
- package/dist/gallery-types.js +2 -0
- package/dist/gallery-types.js.map +1 -0
- package/dist/graphql.d.ts +97 -0
- package/dist/graphql.d.ts.map +1 -0
- package/dist/graphql.js +212 -0
- package/dist/graphql.js.map +1 -0
- package/dist/index.cjs +19448 -0
- package/dist/index.d.cts +19 -0
- package/dist/index.d.mts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/marketing-schema.d.ts +216 -0
- package/dist/marketing-schema.d.ts.map +1 -0
- package/dist/marketing-schema.js +200 -0
- package/dist/marketing-schema.js.map +1 -0
- package/dist/mcp.d.ts +42 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +87 -0
- package/dist/mcp.js.map +1 -0
- package/dist/native.d.ts +45 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +43 -0
- package/dist/native.js.map +1 -0
- package/dist/next-revalidate.d.ts +43 -0
- package/dist/next-revalidate.d.ts.map +1 -0
- package/dist/next-revalidate.js +84 -0
- package/dist/next-revalidate.js.map +1 -0
- package/dist/parallel-pages.d.ts +102 -0
- package/dist/parallel-pages.d.ts.map +1 -0
- package/dist/parallel-pages.js +108 -0
- package/dist/parallel-pages.js.map +1 -0
- package/dist/payment-icons.d.ts +66 -0
- package/dist/payment-icons.d.ts.map +1 -0
- package/dist/payment-icons.js +160 -0
- package/dist/payment-icons.js.map +1 -0
- package/dist/proxy.d.ts +67 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +97 -0
- package/dist/proxy.js.map +1 -0
- package/dist/react-analytics.d.ts +39 -0
- package/dist/react-analytics.d.ts.map +1 -0
- package/dist/react-analytics.js +59 -0
- package/dist/react-analytics.js.map +1 -0
- package/dist/react-attribution.d.ts +99 -0
- package/dist/react-attribution.d.ts.map +1 -0
- package/dist/react-attribution.js +52 -0
- package/dist/react-attribution.js.map +1 -0
- package/dist/react-marketing.d.ts +181 -0
- package/dist/react-marketing.d.ts.map +1 -0
- package/dist/react-marketing.js +215 -0
- package/dist/react-marketing.js.map +1 -0
- package/dist/react.d.ts +727 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +2418 -0
- package/dist/react.js.map +1 -0
- package/dist/reserved-paths.d.ts +24 -0
- package/dist/reserved-paths.d.ts.map +1 -0
- package/dist/reserved-paths.js +60 -0
- package/dist/reserved-paths.js.map +1 -0
- package/dist/revalidate-verify.d.ts +30 -0
- package/dist/revalidate-verify.d.ts.map +1 -0
- package/dist/revalidate-verify.js +74 -0
- package/dist/revalidate-verify.js.map +1 -0
- package/dist/sdk.d.ts +678 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +801 -0
- package/dist/sdk.js.map +1 -0
- package/dist/seo.d.ts +218 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +309 -0
- package/dist/seo.js.map +1 -0
- package/dist/socials.d.ts +47 -0
- package/dist/socials.d.ts.map +1 -0
- package/dist/socials.js +172 -0
- package/dist/socials.js.map +1 -0
- package/dist/static.d.ts +14 -0
- package/dist/static.d.ts.map +1 -0
- package/dist/static.js +14 -0
- package/dist/static.js.map +1 -0
- package/dist/url-pattern.d.ts +47 -0
- package/dist/url-pattern.d.ts.map +1 -0
- package/dist/url-pattern.js +124 -0
- package/dist/url-pattern.js.map +1 -0
- package/dist/vanilla.d.ts +77 -0
- package/dist/vanilla.d.ts.map +1 -0
- package/dist/vanilla.js +903 -0
- package/dist/vanilla.js.map +1 -0
- package/openapi.json +13779 -0
- package/package.json +204 -0
- package/src/adapters-revalidate.ts +88 -0
- package/src/alpha.ts +89 -0
- package/src/analytics-core.ts +175 -0
- package/src/analytics-server.ts +99 -0
- package/src/angular/biab-form.component.ts +1443 -0
- package/src/angular/index.ts +26 -0
- package/src/attribution-logo.ts +5 -0
- package/src/auth-handler.ts +352 -0
- package/src/cli.ts +2517 -0
- package/src/client.ts +3578 -0
- package/src/collections.ts +101 -0
- package/src/contracts.ts +3390 -0
- package/src/data-model-schema.ts +4042 -0
- package/src/distribution.ts +73 -0
- package/src/element.ts +321 -0
- package/src/enums.ts +65 -0
- package/src/errors.ts +338 -0
- package/src/forms-core/autocomplete.ts +97 -0
- package/src/forms-core/business-function.ts +209 -0
- package/src/forms-core/calculation.ts +167 -0
- package/src/forms-core/controller.ts +922 -0
- package/src/forms-core/elements.ts +86 -0
- package/src/forms-core/email-domains.ts +68 -0
- package/src/forms-core/file-rules.ts +123 -0
- package/src/forms-core/formula.ts +1339 -0
- package/src/forms-core/index.ts +122 -0
- package/src/forms-core/units.ts +308 -0
- package/src/forms-core/us-states.ts +68 -0
- package/src/forms-core/validation.ts +1037 -0
- package/src/forms.ts +63 -0
- package/src/gallery-types.ts +31 -0
- package/src/graphql.ts +295 -0
- package/src/index.ts +505 -0
- package/src/marketing-schema.ts +395 -0
- package/src/mcp.ts +108 -0
- package/src/native.ts +73 -0
- package/src/next-revalidate.ts +124 -0
- package/src/parallel-pages.ts +192 -0
- package/src/payment-icons.ts +205 -0
- package/src/proxy.ts +173 -0
- package/src/qwik.tsx +1234 -0
- package/src/react-analytics.tsx +76 -0
- package/src/react-attribution.tsx +192 -0
- package/src/react-marketing.tsx +338 -0
- package/src/react.tsx +5495 -0
- package/src/reserved-paths.ts +65 -0
- package/src/revalidate-verify.ts +98 -0
- package/src/sdk.ts +1671 -0
- package/src/seo.ts +488 -0
- package/src/socials.ts +230 -0
- package/src/solid.tsx +1466 -0
- package/src/static.ts +21 -0
- package/src/styles/biab-forms.css +484 -0
- package/src/svelte/BiabForm.svelte +1069 -0
- package/src/svelte/context.ts +57 -0
- package/src/svelte/index.ts +79 -0
- package/src/url-pattern.ts +153 -0
- package/src/vanilla.ts +1290 -0
- package/src/vue/BiabForm.vue +1538 -0
- package/src/vue/index.ts +119 -0
package/dist/mcp.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serve your business's MCP connector from YOUR domain.
|
|
3
|
+
*
|
|
4
|
+
* The platform's host-resolved `/api/mcp` only exists on sites the platform
|
|
5
|
+
* serves. If you host your own app with the SDK, mount these two handlers
|
|
6
|
+
* and your domain gains the same connector surface — so the URL an org
|
|
7
|
+
* hands to Claude / ChatGPT / Gemini is their own site, exactly like the
|
|
8
|
+
* docs promise:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* // app/api/mcp/route.ts
|
|
12
|
+
* import { mcpHandler } from '@businessdash/sdk/mcp'
|
|
13
|
+
* export const { POST, GET } = mcpHandler({
|
|
14
|
+
* siteId: process.env.BIAB_SITE_ID!,
|
|
15
|
+
* baseUrl: process.env.NEXT_PUBLIC_BIAB_APP_URL!, // https://www.biab.app
|
|
16
|
+
* })
|
|
17
|
+
*
|
|
18
|
+
* // app/.well-known/mcp.json/route.ts
|
|
19
|
+
* import { mcpManifestHandler } from '@businessdash/sdk/mcp'
|
|
20
|
+
* export const GET = mcpManifestHandler({
|
|
21
|
+
* siteId: process.env.BIAB_SITE_ID!,
|
|
22
|
+
* baseUrl: process.env.NEXT_PUBLIC_BIAB_APP_URL!,
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Thin by design: the body is forwarded verbatim and the platform still
|
|
27
|
+
* enforces the org's MCP opt-in and per-tool write gates — a proxy can't
|
|
28
|
+
* widen anything.
|
|
29
|
+
*/
|
|
30
|
+
export type McpProxyOptions = {
|
|
31
|
+
siteId: string;
|
|
32
|
+
/** Platform origin, e.g. "https://www.biab.app". */
|
|
33
|
+
baseUrl: string;
|
|
34
|
+
};
|
|
35
|
+
/** POST proxies JSON-RPC to the platform; GET mirrors the spec's 405. */
|
|
36
|
+
export declare function mcpHandler(options: McpProxyOptions): {
|
|
37
|
+
POST: (request: Request) => Promise<Response>;
|
|
38
|
+
GET: () => Promise<Response>;
|
|
39
|
+
};
|
|
40
|
+
/** Serves `.well-known/mcp.json` with the endpoint URL pointing at YOUR domain. */
|
|
41
|
+
export declare function mcpManifestHandler(options: McpProxyOptions): (request: Request) => Promise<Response>;
|
|
42
|
+
//# sourceMappingURL=mcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,MAAM,eAAe,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;CAChB,CAAC;AAQF,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG;IACrD,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,GAAG,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC7B,CAoCA;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,eAAe,GACtB,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAoBzC"}
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serve your business's MCP connector from YOUR domain.
|
|
3
|
+
*
|
|
4
|
+
* The platform's host-resolved `/api/mcp` only exists on sites the platform
|
|
5
|
+
* serves. If you host your own app with the SDK, mount these two handlers
|
|
6
|
+
* and your domain gains the same connector surface — so the URL an org
|
|
7
|
+
* hands to Claude / ChatGPT / Gemini is their own site, exactly like the
|
|
8
|
+
* docs promise:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* // app/api/mcp/route.ts
|
|
12
|
+
* import { mcpHandler } from '@businessdash/sdk/mcp'
|
|
13
|
+
* export const { POST, GET } = mcpHandler({
|
|
14
|
+
* siteId: process.env.BIAB_SITE_ID!,
|
|
15
|
+
* baseUrl: process.env.NEXT_PUBLIC_BIAB_APP_URL!, // https://www.biab.app
|
|
16
|
+
* })
|
|
17
|
+
*
|
|
18
|
+
* // app/.well-known/mcp.json/route.ts
|
|
19
|
+
* import { mcpManifestHandler } from '@businessdash/sdk/mcp'
|
|
20
|
+
* export const GET = mcpManifestHandler({
|
|
21
|
+
* siteId: process.env.BIAB_SITE_ID!,
|
|
22
|
+
* baseUrl: process.env.NEXT_PUBLIC_BIAB_APP_URL!,
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Thin by design: the body is forwarded verbatim and the platform still
|
|
27
|
+
* enforces the org's MCP opt-in and per-tool write gates — a proxy can't
|
|
28
|
+
* widen anything.
|
|
29
|
+
*/
|
|
30
|
+
function upstream(options) {
|
|
31
|
+
return `${options.baseUrl.replace(/\/$/, "")}/api/public/mcp/${encodeURIComponent(options.siteId)}`;
|
|
32
|
+
}
|
|
33
|
+
/** POST proxies JSON-RPC to the platform; GET mirrors the spec's 405. */
|
|
34
|
+
export function mcpHandler(options) {
|
|
35
|
+
const target = upstream(options);
|
|
36
|
+
return {
|
|
37
|
+
POST: async (request) => {
|
|
38
|
+
try {
|
|
39
|
+
const res = await fetch(target, {
|
|
40
|
+
method: "POST",
|
|
41
|
+
headers: {
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
Accept: request.headers.get("accept") ?? "application/json",
|
|
44
|
+
},
|
|
45
|
+
body: await request.text(),
|
|
46
|
+
});
|
|
47
|
+
const text = await res.text();
|
|
48
|
+
return new Response(text.length > 0 ? text : null, {
|
|
49
|
+
status: res.status,
|
|
50
|
+
headers: {
|
|
51
|
+
"Content-Type": res.headers.get("content-type") ?? "application/json",
|
|
52
|
+
"Cache-Control": "no-store",
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return Response.json({
|
|
58
|
+
jsonrpc: "2.0",
|
|
59
|
+
id: null,
|
|
60
|
+
error: { code: -32603, message: "Upstream unavailable" },
|
|
61
|
+
}, { status: 502 });
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
GET: async () => new Response(null, { status: 405, headers: { Allow: "POST" } }),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Serves `.well-known/mcp.json` with the endpoint URL pointing at YOUR domain. */
|
|
68
|
+
export function mcpManifestHandler(options) {
|
|
69
|
+
const target = `${upstream(options)}/manifest`;
|
|
70
|
+
return async (request) => {
|
|
71
|
+
try {
|
|
72
|
+
const origin = new URL(request.url).origin;
|
|
73
|
+
const res = await fetch(`${target}?origin=${encodeURIComponent(origin)}`, { next: { revalidate: 300 } });
|
|
74
|
+
return new Response(await res.text(), {
|
|
75
|
+
status: res.status,
|
|
76
|
+
headers: {
|
|
77
|
+
"Content-Type": "application/json",
|
|
78
|
+
"Cache-Control": "public, max-age=300",
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return Response.json({ error: "upstream_unavailable" }, { status: 502 });
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=mcp.js.map
|
package/dist/mcp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAQH,SAAS,QAAQ,CAAC,OAAwB;IACzC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,kBAAkB,CAChF,OAAO,CAAC,MAAM,CACd,EAAE,CAAC;AACL,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,UAAU,CAAC,OAAwB;IAIlD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO;QACN,IAAI,EAAE,KAAK,EAAE,OAAgB,EAAE,EAAE;YAChC,IAAI,CAAC;gBACJ,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;oBAC/B,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE;wBACR,cAAc,EAAE,kBAAkB;wBAClC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,kBAAkB;qBAC3D;oBACD,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,EAAE;iBAC1B,CAAC,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBAC9B,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;oBAClD,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,OAAO,EAAE;wBACR,cAAc,EACb,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,kBAAkB;wBACtD,eAAe,EAAE,UAAU;qBAC3B;iBACD,CAAC,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACR,OAAO,QAAQ,CAAC,IAAI,CACnB;oBACC,OAAO,EAAE,KAAK;oBACd,EAAE,EAAE,IAAI;oBACR,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,sBAAsB,EAAE;iBACxD,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CACf,CAAC;YACH,CAAC;QACF,CAAC;QACD,GAAG,EAAE,KAAK,IAAI,EAAE,CACf,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;KAChE,CAAC;AACH,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,kBAAkB,CACjC,OAAwB;IAExB,MAAM,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC;IAC/C,OAAO,KAAK,EAAE,OAAgB,EAAE,EAAE;QACjC,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;YAC3C,MAAM,GAAG,GAAG,MAAM,KAAK,CACtB,GAAG,MAAM,WAAW,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAChD,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,EAAiB,CAC5C,CAAC;YACF,OAAO,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE;gBACrC,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,OAAO,EAAE;oBACR,cAAc,EAAE,kBAAkB;oBAClC,eAAe,EAAE,qBAAqB;iBACtC;aACD,CAAC,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1E,CAAC;IACF,CAAC,CAAC;AACH,CAAC"}
|
package/dist/native.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@businessdash/sdk/native` — the entry point for React Native / Expo.
|
|
3
|
+
*
|
|
4
|
+
* ## Why this exists
|
|
5
|
+
*
|
|
6
|
+
* The root export (`.`) re-exports `createAuthHandler` and `getTenantSession`
|
|
7
|
+
* from `auth-handler.ts`, which calls `Buffer.from(state, "base64url")`.
|
|
8
|
+
* `Buffer` is a Node global that React Native does not provide, and Metro does
|
|
9
|
+
* not polyfill it. The call sits inside a function rather than at module
|
|
10
|
+
* scope, so importing the root *appears* to work — right up until a sign-in
|
|
11
|
+
* callback is decoded and it throws `ReferenceError: Buffer is not defined` in
|
|
12
|
+
* production.
|
|
13
|
+
*
|
|
14
|
+
* That whole module is server-side by design anyway: an auth handler is a
|
|
15
|
+
* thing a tenant's SERVER mounts to receive an OAuth callback and set a
|
|
16
|
+
* cookie. An app has neither. Same for `proxy.ts` (a same-origin proxy route)
|
|
17
|
+
* and `revalidate-verify.ts` (`node:crypto`).
|
|
18
|
+
*
|
|
19
|
+
* So this entry is the data layer with the server-only surface removed. It is
|
|
20
|
+
* additive — nothing here changes what `.` exports.
|
|
21
|
+
*
|
|
22
|
+
* ## What a native app does instead
|
|
23
|
+
*
|
|
24
|
+
* - **Auth** — drive the hosted flow directly: `POST auth/start`, open the URL
|
|
25
|
+
* in a web-auth session, then `POST auth/exchange` with the `code` and
|
|
26
|
+
* `state` from your deep-link callback. `client.auth` has all three.
|
|
27
|
+
* - **Forms** — `<biab-form>` is a DOM custom element with no native
|
|
28
|
+
* counterpart. Read the schema and render it with your own components.
|
|
29
|
+
* - **Revalidation** — irrelevant. The webhook targets a server that holds a
|
|
30
|
+
* cache; an app just re-fetches.
|
|
31
|
+
*
|
|
32
|
+
* ## Metro
|
|
33
|
+
*
|
|
34
|
+
* Subpath exports (`@businessdash/sdk/native`) need Metro's package-exports
|
|
35
|
+
* support. Expo SDK 51+ enables it by default; on bare React Native set
|
|
36
|
+
* `unstable_enablePackageExports = true` in `metro.config.js`. Without it the
|
|
37
|
+
* import fails to resolve at all, with an error that looks like a missing
|
|
38
|
+
* dependency.
|
|
39
|
+
*/
|
|
40
|
+
export type { BiabDevClientOptions, FetchLike } from "./client.js";
|
|
41
|
+
export { BiabDevClient, createBiabDevClient, } from "./client.js";
|
|
42
|
+
export { accessRejectionFromBody, BiabAccessRejectedError, BiabApiError, BiabFeatureNotEntitledError, BiabPaymentLapsedError, type BiabPlanGateBody, BiabServiceSuspendedError, isBiabPlanGateBody, type UnwrappedAccess, type UnwrappedEntitlement, } from "./errors.js";
|
|
43
|
+
export type { BiabClient, CreateBiabClientOptions, FormFieldDef, FormRenderSettings, FormSchema, FormSubmissionData, FormSubmitResult, FormValidationIssue, GalleryResource, SchedulingBookingResult, SchedulingEventType, SchedulingResource, SchedulingSlot, } from "./sdk.js";
|
|
44
|
+
export { createBiabClient } from "./sdk.js";
|
|
45
|
+
//# sourceMappingURL=native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,YAAY,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EACN,aAAa,EACb,mBAAmB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,YAAY,EACZ,2BAA2B,EAC3B,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,oBAAoB,GACzB,MAAM,aAAa,CAAC;AACrB,YAAY,EACX,UAAU,EACV,uBAAuB,EACvB,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,GACd,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/native.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@businessdash/sdk/native` — the entry point for React Native / Expo.
|
|
3
|
+
*
|
|
4
|
+
* ## Why this exists
|
|
5
|
+
*
|
|
6
|
+
* The root export (`.`) re-exports `createAuthHandler` and `getTenantSession`
|
|
7
|
+
* from `auth-handler.ts`, which calls `Buffer.from(state, "base64url")`.
|
|
8
|
+
* `Buffer` is a Node global that React Native does not provide, and Metro does
|
|
9
|
+
* not polyfill it. The call sits inside a function rather than at module
|
|
10
|
+
* scope, so importing the root *appears* to work — right up until a sign-in
|
|
11
|
+
* callback is decoded and it throws `ReferenceError: Buffer is not defined` in
|
|
12
|
+
* production.
|
|
13
|
+
*
|
|
14
|
+
* That whole module is server-side by design anyway: an auth handler is a
|
|
15
|
+
* thing a tenant's SERVER mounts to receive an OAuth callback and set a
|
|
16
|
+
* cookie. An app has neither. Same for `proxy.ts` (a same-origin proxy route)
|
|
17
|
+
* and `revalidate-verify.ts` (`node:crypto`).
|
|
18
|
+
*
|
|
19
|
+
* So this entry is the data layer with the server-only surface removed. It is
|
|
20
|
+
* additive — nothing here changes what `.` exports.
|
|
21
|
+
*
|
|
22
|
+
* ## What a native app does instead
|
|
23
|
+
*
|
|
24
|
+
* - **Auth** — drive the hosted flow directly: `POST auth/start`, open the URL
|
|
25
|
+
* in a web-auth session, then `POST auth/exchange` with the `code` and
|
|
26
|
+
* `state` from your deep-link callback. `client.auth` has all three.
|
|
27
|
+
* - **Forms** — `<biab-form>` is a DOM custom element with no native
|
|
28
|
+
* counterpart. Read the schema and render it with your own components.
|
|
29
|
+
* - **Revalidation** — irrelevant. The webhook targets a server that holds a
|
|
30
|
+
* cache; an app just re-fetches.
|
|
31
|
+
*
|
|
32
|
+
* ## Metro
|
|
33
|
+
*
|
|
34
|
+
* Subpath exports (`@businessdash/sdk/native`) need Metro's package-exports
|
|
35
|
+
* support. Expo SDK 51+ enables it by default; on bare React Native set
|
|
36
|
+
* `unstable_enablePackageExports = true` in `metro.config.js`. Without it the
|
|
37
|
+
* import fails to resolve at all, with an error that looks like a missing
|
|
38
|
+
* dependency.
|
|
39
|
+
*/
|
|
40
|
+
export { BiabDevClient, createBiabDevClient, } from "./client.js";
|
|
41
|
+
export { accessRejectionFromBody, BiabAccessRejectedError, BiabApiError, BiabFeatureNotEntitledError, BiabPaymentLapsedError, BiabServiceSuspendedError, isBiabPlanGateBody, } from "./errors.js";
|
|
42
|
+
export { createBiabClient } from "./sdk.js";
|
|
43
|
+
//# sourceMappingURL=native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.js","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,OAAO,EACN,aAAa,EACb,mBAAmB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,YAAY,EACZ,2BAA2B,EAC3B,sBAAsB,EAEtB,yBAAyB,EACzB,kBAAkB,GAGlB,MAAM,aAAa,CAAC;AAgBrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drop-in Next.js route handler for BIAB revalidation webhooks.
|
|
3
|
+
*
|
|
4
|
+
* Consumer mounts this with literally one line:
|
|
5
|
+
*
|
|
6
|
+
* // app/api/biab/revalidate/route.ts
|
|
7
|
+
* export { POST } from "@businessdash/sdk/next/revalidate";
|
|
8
|
+
*
|
|
9
|
+
* That's it. The handler:
|
|
10
|
+
*
|
|
11
|
+
* 1. Reads the shared secret from `BIAB_REVALIDATION_SECRET`
|
|
12
|
+
* (override via `createRevalidateHandler({ secret })` if env
|
|
13
|
+
* isn't available — see below).
|
|
14
|
+
* 2. Verifies the `X-Biab-Signature: t=<unix>,v1=<hex>` header.
|
|
15
|
+
* Constant-time hash compare, ±5 minute replay window.
|
|
16
|
+
* 3. Calls `revalidateTag(tag, { expire: 0 })` for each tag in
|
|
17
|
+
* the payload.
|
|
18
|
+
* 4. Returns `{ ok: true, revalidated: string[] }`.
|
|
19
|
+
*
|
|
20
|
+
* For non-Next consumers, import `verifyAndExtractTags` directly
|
|
21
|
+
* from `@businessdash/sdk/adapters/revalidate` and call your framework's
|
|
22
|
+
* invalidation primitive (CDN purge, KV delete, static rebuild
|
|
23
|
+
* trigger). The verification logic is framework-agnostic and lives
|
|
24
|
+
* in a separate file so non-Next bundlers don't transitively pick
|
|
25
|
+
* up `next/cache`.
|
|
26
|
+
*/
|
|
27
|
+
import { type BiabPublishPayload, type VerifyOptions, type VerifyResult, verifyAndExtractTags } from "./revalidate-verify.js";
|
|
28
|
+
export { type BiabPublishPayload, type VerifyOptions, type VerifyResult, verifyAndExtractTags, };
|
|
29
|
+
export interface CreateRevalidateHandlerOptions {
|
|
30
|
+
/**
|
|
31
|
+
* Override the secret instead of reading from
|
|
32
|
+
* `BIAB_REVALIDATION_SECRET`. Useful in tests or when the
|
|
33
|
+
* consumer manages secrets in a non-standard place.
|
|
34
|
+
*/
|
|
35
|
+
secret?: string;
|
|
36
|
+
}
|
|
37
|
+
export declare function createRevalidateHandler(opts?: CreateRevalidateHandlerOptions): (request: Request) => Promise<Response>;
|
|
38
|
+
/**
|
|
39
|
+
* Default `POST` handler the consumer re-exports. Reads the secret
|
|
40
|
+
* from `BIAB_REVALIDATION_SECRET` env automatically.
|
|
41
|
+
*/
|
|
42
|
+
export declare const POST: (request: Request) => Promise<Response>;
|
|
43
|
+
//# sourceMappingURL=next-revalidate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next-revalidate.d.ts","sourceRoot":"","sources":["../src/next-revalidate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,oBAAoB,EACpB,MAAM,wBAAwB,CAAC;AAIhC,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,oBAAoB,GACpB,CAAC;AAMF,MAAM,WAAW,8BAA8B;IAC9C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAgCD,wBAAgB,uBAAuB,CACtC,IAAI,GAAE,8BAAmC,IAEd,SAAS,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CA4B/D;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,YAlCoB,OAAO,KAAG,OAAO,CAAC,QAAQ,CAkClB,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drop-in Next.js route handler for BIAB revalidation webhooks.
|
|
3
|
+
*
|
|
4
|
+
* Consumer mounts this with literally one line:
|
|
5
|
+
*
|
|
6
|
+
* // app/api/biab/revalidate/route.ts
|
|
7
|
+
* export { POST } from "@businessdash/sdk/next/revalidate";
|
|
8
|
+
*
|
|
9
|
+
* That's it. The handler:
|
|
10
|
+
*
|
|
11
|
+
* 1. Reads the shared secret from `BIAB_REVALIDATION_SECRET`
|
|
12
|
+
* (override via `createRevalidateHandler({ secret })` if env
|
|
13
|
+
* isn't available — see below).
|
|
14
|
+
* 2. Verifies the `X-Biab-Signature: t=<unix>,v1=<hex>` header.
|
|
15
|
+
* Constant-time hash compare, ±5 minute replay window.
|
|
16
|
+
* 3. Calls `revalidateTag(tag, { expire: 0 })` for each tag in
|
|
17
|
+
* the payload.
|
|
18
|
+
* 4. Returns `{ ok: true, revalidated: string[] }`.
|
|
19
|
+
*
|
|
20
|
+
* For non-Next consumers, import `verifyAndExtractTags` directly
|
|
21
|
+
* from `@businessdash/sdk/adapters/revalidate` and call your framework's
|
|
22
|
+
* invalidation primitive (CDN purge, KV delete, static rebuild
|
|
23
|
+
* trigger). The verification logic is framework-agnostic and lives
|
|
24
|
+
* in a separate file so non-Next bundlers don't transitively pick
|
|
25
|
+
* up `next/cache`.
|
|
26
|
+
*/
|
|
27
|
+
import { verifyAndExtractTags, } from "./revalidate-verify.js";
|
|
28
|
+
// Re-export for backwards compatibility — callers that previously
|
|
29
|
+
// imported these from `@businessdash/sdk/next/revalidate` still work.
|
|
30
|
+
export { verifyAndExtractTags, };
|
|
31
|
+
async function callRevalidateTag(tags) {
|
|
32
|
+
// Lazy-import so the SDK is usable outside Next without dragging
|
|
33
|
+
// `next/cache` into the bundle. The module name lives in a variable
|
|
34
|
+
// so TypeScript doesn't try to type-check the missing dep at build
|
|
35
|
+
// time — the import is purely runtime.
|
|
36
|
+
const modName = "next/cache";
|
|
37
|
+
const mod = await import(
|
|
38
|
+
/* @vite-ignore */ /* webpackIgnore: true */ modName).catch(() => null);
|
|
39
|
+
if (!mod || typeof mod.revalidateTag !== "function") {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
const fn = mod.revalidateTag;
|
|
43
|
+
const revalidated = [];
|
|
44
|
+
for (const tag of tags) {
|
|
45
|
+
try {
|
|
46
|
+
fn(tag, { expire: 0 });
|
|
47
|
+
revalidated.push(tag);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
/* outside a Next request scope — caller may retry */
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return revalidated;
|
|
54
|
+
}
|
|
55
|
+
export function createRevalidateHandler(opts = {}) {
|
|
56
|
+
return async function POST(request) {
|
|
57
|
+
const secret = opts.secret ?? process.env["BIAB_REVALIDATION_SECRET"];
|
|
58
|
+
if (!secret) {
|
|
59
|
+
return Response.json({ ok: false, reason: "missing_revalidation_secret_env" }, { status: 500 });
|
|
60
|
+
}
|
|
61
|
+
const rawBody = await request.text();
|
|
62
|
+
const sig = request.headers.get("x-biab-signature");
|
|
63
|
+
const verified = verifyAndExtractTags({
|
|
64
|
+
secret,
|
|
65
|
+
rawBody,
|
|
66
|
+
signatureHeader: sig,
|
|
67
|
+
});
|
|
68
|
+
if (!verified.ok || !verified.payload) {
|
|
69
|
+
return Response.json({ ok: false, reason: verified.reason ?? "verify_failed" }, { status: 401 });
|
|
70
|
+
}
|
|
71
|
+
const revalidated = await callRevalidateTag(verified.payload.tags);
|
|
72
|
+
return Response.json({
|
|
73
|
+
ok: true,
|
|
74
|
+
revalidated,
|
|
75
|
+
orgId: verified.payload.orgId,
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Default `POST` handler the consumer re-exports. Reads the secret
|
|
81
|
+
* from `BIAB_REVALIDATION_SECRET` env automatically.
|
|
82
|
+
*/
|
|
83
|
+
export const POST = createRevalidateHandler();
|
|
84
|
+
//# sourceMappingURL=next-revalidate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next-revalidate.js","sourceRoot":"","sources":["../src/next-revalidate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAIN,oBAAoB,GACpB,MAAM,wBAAwB,CAAC;AAEhC,kEAAkE;AAClE,sEAAsE;AACtE,OAAO,EAIN,oBAAoB,GACpB,CAAC;AAoBF,KAAK,UAAU,iBAAiB,CAAC,IAAc;IAC9C,iEAAiE;IACjE,oEAAoE;IACpE,mEAAmE;IACnE,uCAAuC;IACvC,MAAM,OAAO,GAAG,YAAY,CAAC;IAC7B,MAAM,GAAG,GAAmD,MAAM,MAAM;IACvE,kBAAkB,CAAC,yBAAyB,CAAC,OAAO,CACpD,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACpB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,aAAa,KAAK,UAAU,EAAE,CAAC;QACrD,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,EAAE,GAAG,GAAG,CAAC,aAAa,CAAC;IAC7B,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC;YACJ,EAAE,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YACvB,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACR,qDAAqD;QACtD,CAAC;IACF,CAAC;IACD,OAAO,WAAW,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,uBAAuB,CACtC,OAAuC,EAAE;IAEzC,OAAO,KAAK,UAAU,IAAI,CAAC,OAAgB;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QACtE,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,OAAO,QAAQ,CAAC,IAAI,CACnB,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAiC,EAAE,EACxD,EAAE,MAAM,EAAE,GAAG,EAAE,CACf,CAAC;QACH,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,oBAAoB,CAAC;YACrC,MAAM;YACN,OAAO;YACP,eAAe,EAAE,GAAG;SACpB,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACvC,OAAO,QAAQ,CAAC,IAAI,CACnB,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,eAAe,EAAE,EACzD,EAAE,MAAM,EAAE,GAAG,EAAE,CACf,CAAC;QACH,CAAC;QACD,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnE,OAAO,QAAQ,CAAC,IAAI,CAAC;YACpB,EAAE,EAAE,IAAI;YACR,WAAW;YACX,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK;SAC7B,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code-first declaration of a programmatic-SEO ("parallel") page.
|
|
3
|
+
* The consumer writes:
|
|
4
|
+
*
|
|
5
|
+
* import { defineParallelPage } from "@businessdash/sdk";
|
|
6
|
+
*
|
|
7
|
+
* const repairAreaPage = defineParallelPage({
|
|
8
|
+
* key: "repair-area",
|
|
9
|
+
* routePattern: "/repair/[service]/[area]",
|
|
10
|
+
* variables: {
|
|
11
|
+
* service: {
|
|
12
|
+
* source: { section: "repairTypesCatalog" },
|
|
13
|
+
* slugField: "type",
|
|
14
|
+
* tokenFields: ["type", "description"],
|
|
15
|
+
* },
|
|
16
|
+
* area: {
|
|
17
|
+
* source: { section: "serviceAreas", path: "areas" },
|
|
18
|
+
* slugField: "slug",
|
|
19
|
+
* tokenFields: ["name", "state", "slug"],
|
|
20
|
+
* },
|
|
21
|
+
* },
|
|
22
|
+
* meta: {
|
|
23
|
+
* title: "{service.type} in {area.name} | {company.shortName}",
|
|
24
|
+
* description:
|
|
25
|
+
* "Professional {service.type} in {area.name}, {area.state}. Call {company.phone}.",
|
|
26
|
+
* },
|
|
27
|
+
* templateRef: "repairAreaTemplate",
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* `defineParallelPage` is a pure builder — no DB writes, no HTTP. It
|
|
31
|
+
* returns a frozen, type-checked artifact. Push to the BIAB server
|
|
32
|
+
* later via `biab-dev sync-parallel-pages` (or the SDK's
|
|
33
|
+
* `client.parallelPages.upsertDefinition()` when wired).
|
|
34
|
+
*/
|
|
35
|
+
export type ParallelPageVariableInput = {
|
|
36
|
+
source: {
|
|
37
|
+
section: string;
|
|
38
|
+
path?: string;
|
|
39
|
+
};
|
|
40
|
+
slugField: string;
|
|
41
|
+
tokenFields?: ReadonlyArray<string>;
|
|
42
|
+
};
|
|
43
|
+
export type ParallelPageMetaInput = {
|
|
44
|
+
title: string;
|
|
45
|
+
description: string;
|
|
46
|
+
canonical?: string;
|
|
47
|
+
ogImage?: string;
|
|
48
|
+
};
|
|
49
|
+
export type ParallelPageInput<V extends Record<string, ParallelPageVariableInput>> = {
|
|
50
|
+
key: string;
|
|
51
|
+
routePattern: string;
|
|
52
|
+
variables: V;
|
|
53
|
+
meta: ParallelPageMetaInput;
|
|
54
|
+
/**
|
|
55
|
+
* For SDK-defined pages, a schema section key naming the body
|
|
56
|
+
* template. The dashboard renders the matching section's content
|
|
57
|
+
* for the parallel-page body. Site-builder pages use a different
|
|
58
|
+
* pointer scheme (`cms:<contentId>`) — set transparently by the
|
|
59
|
+
* dashboard.
|
|
60
|
+
*/
|
|
61
|
+
templateRef: string;
|
|
62
|
+
/**
|
|
63
|
+
* Per-page robots directive. Defaults to `inherit` (defer to the
|
|
64
|
+
* site-wide robots config). Set `noindex` for variants that
|
|
65
|
+
* shouldn't appear in search (e.g. dynamic catch-alls used as
|
|
66
|
+
* fallbacks).
|
|
67
|
+
*/
|
|
68
|
+
crawlRule?: "inherit" | "index" | "noindex";
|
|
69
|
+
};
|
|
70
|
+
export type ParallelPageDefinition<V extends Record<string, ParallelPageVariableInput>> = {
|
|
71
|
+
readonly $kind: "biab.parallelPage";
|
|
72
|
+
readonly key: string;
|
|
73
|
+
readonly routePattern: string;
|
|
74
|
+
readonly variables: ReadonlyArray<{
|
|
75
|
+
readonly name: keyof V & string;
|
|
76
|
+
readonly source: {
|
|
77
|
+
readonly section: string;
|
|
78
|
+
readonly path?: string;
|
|
79
|
+
};
|
|
80
|
+
readonly slugField: string;
|
|
81
|
+
readonly tokenFields: ReadonlyArray<string>;
|
|
82
|
+
}>;
|
|
83
|
+
readonly meta: Readonly<ParallelPageMetaInput>;
|
|
84
|
+
readonly templateRef: string;
|
|
85
|
+
readonly crawlRule: "inherit" | "index" | "noindex";
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Validate + freeze a parallel-page declaration. Throws on:
|
|
89
|
+
* - Empty / malformed `routePattern`
|
|
90
|
+
* - `[variable]` segments in the pattern that aren't in `variables`
|
|
91
|
+
* - `variables` keys that don't appear in the pattern
|
|
92
|
+
* - Duplicate variable names
|
|
93
|
+
* - Missing `slugField` on any binding
|
|
94
|
+
*/
|
|
95
|
+
export declare function defineParallelPage<V extends Record<string, ParallelPageVariableInput>>(input: ParallelPageInput<V>): ParallelPageDefinition<V>;
|
|
96
|
+
/**
|
|
97
|
+
* Type guard for the artifact `defineParallelPage` returns. Useful
|
|
98
|
+
* when consumers export a mixed array of marketing + parallel-page
|
|
99
|
+
* declarations from one `biab.config.ts`.
|
|
100
|
+
*/
|
|
101
|
+
export declare function isParallelPageDefinition(value: unknown): value is ParallelPageDefinition<Record<string, ParallelPageVariableInput>>;
|
|
102
|
+
//# sourceMappingURL=parallel-pages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel-pages.d.ts","sourceRoot":"","sources":["../src/parallel-pages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAIH,MAAM,MAAM,yBAAyB,GAAG;IACvC,MAAM,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAC5B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,IAChD;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,CAAC,CAAC;IACb,IAAI,EAAE,qBAAqB,CAAC;IAC5B;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,sBAAsB,CACjC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,IAChD;IACH,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;QACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC;QAChC,QAAQ,CAAC,MAAM,EAAE;YAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACtE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;KAC5C,CAAC,CAAC;IACH,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,qBAAqB,CAAC,CAAC;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;CACpD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CACjC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,EAClD,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAwExD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACvC,KAAK,EAAE,OAAO,GACZ,KAAK,IAAI,sBAAsB,CAAC,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAM5E"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code-first declaration of a programmatic-SEO ("parallel") page.
|
|
3
|
+
* The consumer writes:
|
|
4
|
+
*
|
|
5
|
+
* import { defineParallelPage } from "@businessdash/sdk";
|
|
6
|
+
*
|
|
7
|
+
* const repairAreaPage = defineParallelPage({
|
|
8
|
+
* key: "repair-area",
|
|
9
|
+
* routePattern: "/repair/[service]/[area]",
|
|
10
|
+
* variables: {
|
|
11
|
+
* service: {
|
|
12
|
+
* source: { section: "repairTypesCatalog" },
|
|
13
|
+
* slugField: "type",
|
|
14
|
+
* tokenFields: ["type", "description"],
|
|
15
|
+
* },
|
|
16
|
+
* area: {
|
|
17
|
+
* source: { section: "serviceAreas", path: "areas" },
|
|
18
|
+
* slugField: "slug",
|
|
19
|
+
* tokenFields: ["name", "state", "slug"],
|
|
20
|
+
* },
|
|
21
|
+
* },
|
|
22
|
+
* meta: {
|
|
23
|
+
* title: "{service.type} in {area.name} | {company.shortName}",
|
|
24
|
+
* description:
|
|
25
|
+
* "Professional {service.type} in {area.name}, {area.state}. Call {company.phone}.",
|
|
26
|
+
* },
|
|
27
|
+
* templateRef: "repairAreaTemplate",
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* `defineParallelPage` is a pure builder — no DB writes, no HTTP. It
|
|
31
|
+
* returns a frozen, type-checked artifact. Push to the BIAB server
|
|
32
|
+
* later via `biab-dev sync-parallel-pages` (or the SDK's
|
|
33
|
+
* `client.parallelPages.upsertDefinition()` when wired).
|
|
34
|
+
*/
|
|
35
|
+
import { parseParallelPagePattern } from "./url-pattern.js";
|
|
36
|
+
/**
|
|
37
|
+
* Validate + freeze a parallel-page declaration. Throws on:
|
|
38
|
+
* - Empty / malformed `routePattern`
|
|
39
|
+
* - `[variable]` segments in the pattern that aren't in `variables`
|
|
40
|
+
* - `variables` keys that don't appear in the pattern
|
|
41
|
+
* - Duplicate variable names
|
|
42
|
+
* - Missing `slugField` on any binding
|
|
43
|
+
*/
|
|
44
|
+
export function defineParallelPage(input) {
|
|
45
|
+
if (!input.key || typeof input.key !== "string") {
|
|
46
|
+
throw new Error("defineParallelPage: `key` is required.");
|
|
47
|
+
}
|
|
48
|
+
if (!/^[a-z][a-z0-9-]*$/.test(input.key)) {
|
|
49
|
+
throw new Error(`defineParallelPage: \`key\` must be kebab-case (got "${input.key}").`);
|
|
50
|
+
}
|
|
51
|
+
const parsed = parseParallelPagePattern(input.routePattern);
|
|
52
|
+
const inputNames = new Set(Object.keys(input.variables));
|
|
53
|
+
const patternNames = new Set(parsed.variableNames);
|
|
54
|
+
for (const patternName of patternNames) {
|
|
55
|
+
if (!inputNames.has(patternName)) {
|
|
56
|
+
throw new Error(`defineParallelPage("${input.key}"): pattern uses "[${patternName}]" ` +
|
|
57
|
+
`but \`variables\` has no binding for "${patternName}".`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
for (const inputName of inputNames) {
|
|
61
|
+
if (!patternNames.has(inputName)) {
|
|
62
|
+
throw new Error(`defineParallelPage("${input.key}"): \`variables\` declares "${inputName}" ` +
|
|
63
|
+
`but the pattern "${input.routePattern}" has no "[${inputName}]" segment.`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const variables = parsed.variableNames.map((name) => {
|
|
67
|
+
const raw = input.variables[name];
|
|
68
|
+
if (!raw.source?.section) {
|
|
69
|
+
throw new Error(`defineParallelPage("${input.key}"): variable "${name}" is missing \`source.section\`.`);
|
|
70
|
+
}
|
|
71
|
+
if (!raw.slugField) {
|
|
72
|
+
throw new Error(`defineParallelPage("${input.key}"): variable "${name}" is missing \`slugField\`.`);
|
|
73
|
+
}
|
|
74
|
+
const tokenFields = raw.tokenFields ?? [raw.slugField];
|
|
75
|
+
return Object.freeze({
|
|
76
|
+
name: name,
|
|
77
|
+
source: Object.freeze({
|
|
78
|
+
section: raw.source.section,
|
|
79
|
+
...(raw.source.path !== undefined ? { path: raw.source.path } : {}),
|
|
80
|
+
}),
|
|
81
|
+
slugField: raw.slugField,
|
|
82
|
+
tokenFields: Object.freeze([...tokenFields]),
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
if (!input.meta?.title || !input.meta?.description) {
|
|
86
|
+
throw new Error(`defineParallelPage("${input.key}"): \`meta.title\` and \`meta.description\` are required.`);
|
|
87
|
+
}
|
|
88
|
+
return Object.freeze({
|
|
89
|
+
$kind: "biab.parallelPage",
|
|
90
|
+
key: input.key,
|
|
91
|
+
routePattern: input.routePattern,
|
|
92
|
+
variables: Object.freeze(variables),
|
|
93
|
+
meta: Object.freeze({ ...input.meta }),
|
|
94
|
+
templateRef: input.templateRef,
|
|
95
|
+
crawlRule: input.crawlRule ?? "inherit",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Type guard for the artifact `defineParallelPage` returns. Useful
|
|
100
|
+
* when consumers export a mixed array of marketing + parallel-page
|
|
101
|
+
* declarations from one `biab.config.ts`.
|
|
102
|
+
*/
|
|
103
|
+
export function isParallelPageDefinition(value) {
|
|
104
|
+
return (!!value &&
|
|
105
|
+
typeof value === "object" &&
|
|
106
|
+
value.$kind === "biab.parallelPage");
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=parallel-pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel-pages.js","sourceRoot":"","sources":["../src/parallel-pages.ts"],"names":[],"mappings":"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"}
|