@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
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic revalidation handler builder.
|
|
3
|
+
*
|
|
4
|
+
* The Next.js drop-in at `@businessdash/sdk/next/revalidate` is the
|
|
5
|
+
* happy path for Next consumers — one-line `export { POST } from`
|
|
6
|
+
* and the handler verifies the HMAC + calls `revalidateTag`.
|
|
7
|
+
*
|
|
8
|
+
* For everything else (Cloudflare Workers, plain Node HTTP,
|
|
9
|
+
* SvelteKit, Remix, static-site rebuilds), this adapter exposes
|
|
10
|
+
* the same verification logic without the Next dependency. The
|
|
11
|
+
* consumer plugs in their own cache-invalidation callback —
|
|
12
|
+
* KV.delete, fetch(`/purge-cache`), trigger a static rebuild, etc.
|
|
13
|
+
*
|
|
14
|
+
* Usage example (Cloudflare Workers):
|
|
15
|
+
*
|
|
16
|
+
* import { createGenericRevalidateHandler } from "@businessdash/sdk/adapters/revalidate";
|
|
17
|
+
*
|
|
18
|
+
* const handler = createGenericRevalidateHandler({
|
|
19
|
+
* secret: env.BIAB_REVALIDATION_SECRET,
|
|
20
|
+
* onTagsRevalidated: async (tags) => {
|
|
21
|
+
* for (const tag of tags) {
|
|
22
|
+
* await env.PURGE_CACHE.fetch(new Request(`/?tag=${tag}`));
|
|
23
|
+
* }
|
|
24
|
+
* },
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* export default { fetch: (req) => handler(req) };
|
|
28
|
+
*
|
|
29
|
+
* The HMAC verification + replay-window logic lives in
|
|
30
|
+
* `verifyAndExtractTags` (next-revalidate.ts) and is shared.
|
|
31
|
+
*/
|
|
32
|
+
export { verifyAndExtractTags } from "./revalidate-verify.js";
|
|
33
|
+
export interface CreateGenericRevalidateHandlerOptions {
|
|
34
|
+
secret: string;
|
|
35
|
+
/**
|
|
36
|
+
* Called when the request verifies and a publish event is
|
|
37
|
+
* received. The consumer's framework-appropriate cache purge
|
|
38
|
+
* goes here. Failures should throw so the response is 500 —
|
|
39
|
+
* BIAB-side retry can re-deliver.
|
|
40
|
+
*/
|
|
41
|
+
onTagsRevalidated: (tags: string[], orgId: string) => Promise<void> | void;
|
|
42
|
+
}
|
|
43
|
+
export declare function createGenericRevalidateHandler(opts: CreateGenericRevalidateHandlerOptions): (request: Request) => Promise<Response>;
|
|
44
|
+
//# sourceMappingURL=adapters-revalidate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters-revalidate.d.ts","sourceRoot":"","sources":["../src/adapters-revalidate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAOH,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAI9D,MAAM,WAAW,qCAAqC;IACrD,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC3E;AAED,wBAAgB,8BAA8B,CAC7C,IAAI,EAAE,qCAAqC,IAKd,SAAS,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CA6BjE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic revalidation handler builder.
|
|
3
|
+
*
|
|
4
|
+
* The Next.js drop-in at `@businessdash/sdk/next/revalidate` is the
|
|
5
|
+
* happy path for Next consumers — one-line `export { POST } from`
|
|
6
|
+
* and the handler verifies the HMAC + calls `revalidateTag`.
|
|
7
|
+
*
|
|
8
|
+
* For everything else (Cloudflare Workers, plain Node HTTP,
|
|
9
|
+
* SvelteKit, Remix, static-site rebuilds), this adapter exposes
|
|
10
|
+
* the same verification logic without the Next dependency. The
|
|
11
|
+
* consumer plugs in their own cache-invalidation callback —
|
|
12
|
+
* KV.delete, fetch(`/purge-cache`), trigger a static rebuild, etc.
|
|
13
|
+
*
|
|
14
|
+
* Usage example (Cloudflare Workers):
|
|
15
|
+
*
|
|
16
|
+
* import { createGenericRevalidateHandler } from "@businessdash/sdk/adapters/revalidate";
|
|
17
|
+
*
|
|
18
|
+
* const handler = createGenericRevalidateHandler({
|
|
19
|
+
* secret: env.BIAB_REVALIDATION_SECRET,
|
|
20
|
+
* onTagsRevalidated: async (tags) => {
|
|
21
|
+
* for (const tag of tags) {
|
|
22
|
+
* await env.PURGE_CACHE.fetch(new Request(`/?tag=${tag}`));
|
|
23
|
+
* }
|
|
24
|
+
* },
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* export default { fetch: (req) => handler(req) };
|
|
28
|
+
*
|
|
29
|
+
* The HMAC verification + replay-window logic lives in
|
|
30
|
+
* `verifyAndExtractTags` (next-revalidate.ts) and is shared.
|
|
31
|
+
*/
|
|
32
|
+
// Import directly from the framework-agnostic verifier so this
|
|
33
|
+
// adapter file doesn't transitively pull in `next/cache` (which
|
|
34
|
+
// some non-Next bundlers — Nuxt's Nitro, Cloudflare's workerd —
|
|
35
|
+
// try to resolve at build time even when it's behind a runtime
|
|
36
|
+
// dynamic import).
|
|
37
|
+
export { verifyAndExtractTags } from "./revalidate-verify.js";
|
|
38
|
+
import { verifyAndExtractTags } from "./revalidate-verify.js";
|
|
39
|
+
export function createGenericRevalidateHandler(opts) {
|
|
40
|
+
if (!opts.secret) {
|
|
41
|
+
throw new Error("createGenericRevalidateHandler: secret is required.");
|
|
42
|
+
}
|
|
43
|
+
return async function handle(request) {
|
|
44
|
+
const rawBody = await request.text();
|
|
45
|
+
const sig = request.headers.get("x-biab-signature");
|
|
46
|
+
const verified = verifyAndExtractTags({
|
|
47
|
+
secret: opts.secret,
|
|
48
|
+
rawBody,
|
|
49
|
+
signatureHeader: sig,
|
|
50
|
+
});
|
|
51
|
+
if (!verified.ok || !verified.payload) {
|
|
52
|
+
return Response.json({ ok: false, reason: verified.reason ?? "verify_failed" }, { status: 401 });
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
await opts.onTagsRevalidated(verified.payload.tags, verified.payload.orgId);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
const message = err instanceof Error ? err.message : "callback_failed";
|
|
59
|
+
return Response.json({ ok: false, reason: message }, { status: 500 });
|
|
60
|
+
}
|
|
61
|
+
return Response.json({
|
|
62
|
+
ok: true,
|
|
63
|
+
revalidated: verified.payload.tags,
|
|
64
|
+
orgId: verified.payload.orgId,
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=adapters-revalidate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters-revalidate.js","sourceRoot":"","sources":["../src/adapters-revalidate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,+DAA+D;AAC/D,gEAAgE;AAChE,gEAAgE;AAChE,+DAA+D;AAC/D,mBAAmB;AACnB,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAa9D,MAAM,UAAU,8BAA8B,CAC7C,IAA2C;IAE3C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,KAAK,UAAU,MAAM,CAAC,OAAgB;QAC5C,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,EAAE,IAAI,CAAC,MAAM;YACnB,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,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,iBAAiB,CAC3B,QAAQ,CAAC,OAAO,CAAC,IAAI,EACrB,QAAQ,CAAC,OAAO,CAAC,KAAK,CACtB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC;YACvE,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,CAAC;YACpB,EAAE,EAAE,IAAI;YACR,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI;YAClC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK;SAC7B,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC"}
|
package/dist/alpha.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@businessdash/sdk/alpha` — legacy/deprecated schema API for backward compatibility.
|
|
3
|
+
*
|
|
4
|
+
* This entrypoint re-exports the original `data-model-schema` surface exactly as
|
|
5
|
+
* it was available from `@businessdash/sdk` prior to the `0.9` entrypoint split.
|
|
6
|
+
*
|
|
7
|
+
* Use it when migrating old codebases that rely on the deprecated API:
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* // old: import { defineDataModel, defineField, defineObject } from "@businessdash/sdk"
|
|
11
|
+
* // new:
|
|
12
|
+
* import { defineDataModel, defineField, defineObject } from "@businessdash/sdk/alpha"
|
|
13
|
+
*
|
|
14
|
+
* // Or for the full legacy surface:
|
|
15
|
+
* import * as Alpha from "@businessdash/sdk/alpha"
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* New projects should use `@businessdash/sdk/collections` or `@businessdash/sdk/forms` instead.
|
|
19
|
+
*/
|
|
20
|
+
export { type AddressDef, type AllFormElements, type BoundaryMetadata, bd, type ChoiceCardDef, type CollectionDefinition, type CollectionOptions, collection, computeDataModelChecksum, createSchema, type DataModelArtifact, type DataModelClientShape, type DataModelInput, type DeleteAction, type DynamicOptionsDef, defineCollection, defineDataModel, defineField, defineObject, type ElementMetadata, type EncryptionMode, type ExtArrayType, type ExtBooleanType, type ExtNumberType, type ExtObjectType, type ExtractFieldPaths, type ExtTextType, FIELD_TYPES, type FieldBuilder, type FieldDefinition, type FieldOptions, type FieldSpec, type Fields, type FieldType, type FileDef, type FindFieldTypeByPath, fields, type InferJsType, isFieldType, isRelationFieldType, type MeasurementCategory, type MeasurementDef, type ObjectDefinition, type ObjectKind, type ObjectPropertyDef, type ObjectSchemaDef, type ObjectVisibility, objectVisibilityValues, PREDEFINED_UNITS, type PrimaryKeyType, type RangeDef, RELATION_FIELD_TYPES, type RelationMetadata, type RelationOnDelete, type RequiredIfCondition, type RlsPolicyConfig, SchemaBoundary, type SchemaBoundaryNode, type SchemaOptions, type SecureEvalRule, type SelectOption, type SpecialDateValue, type StorageStrategy, UNSUPPORTED_FIELD_TYPES, type ValidationRules, validateAndResolveMeasurement, validateFieldValue, } from "./data-model-schema.js";
|
|
21
|
+
//# sourceMappingURL=alpha.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alpha.d.ts","sourceRoot":"","sources":["../src/alpha.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EACN,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,EAAE,EACF,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,UAAU,EACV,wBAAwB,EACxB,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,OAAO,EACZ,KAAK,mBAAmB,EACxB,MAAM,EACN,KAAK,WAAW,EAChB,WAAW,EACX,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,uBAAuB,EACvB,KAAK,eAAe,EACpB,6BAA6B,EAC7B,kBAAkB,GAClB,MAAM,wBAAwB,CAAC"}
|
package/dist/alpha.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@businessdash/sdk/alpha` — legacy/deprecated schema API for backward compatibility.
|
|
3
|
+
*
|
|
4
|
+
* This entrypoint re-exports the original `data-model-schema` surface exactly as
|
|
5
|
+
* it was available from `@businessdash/sdk` prior to the `0.9` entrypoint split.
|
|
6
|
+
*
|
|
7
|
+
* Use it when migrating old codebases that rely on the deprecated API:
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* // old: import { defineDataModel, defineField, defineObject } from "@businessdash/sdk"
|
|
11
|
+
* // new:
|
|
12
|
+
* import { defineDataModel, defineField, defineObject } from "@businessdash/sdk/alpha"
|
|
13
|
+
*
|
|
14
|
+
* // Or for the full legacy surface:
|
|
15
|
+
* import * as Alpha from "@businessdash/sdk/alpha"
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* New projects should use `@businessdash/sdk/collections` or `@businessdash/sdk/forms` instead.
|
|
19
|
+
*/
|
|
20
|
+
export { bd, collection, computeDataModelChecksum, createSchema, defineCollection, defineDataModel, defineField, defineObject, FIELD_TYPES, fields, isFieldType, isRelationFieldType, objectVisibilityValues, PREDEFINED_UNITS, RELATION_FIELD_TYPES, SchemaBoundary, UNSUPPORTED_FIELD_TYPES, validateAndResolveMeasurement, validateFieldValue, } from "./data-model-schema.js";
|
|
21
|
+
//# sourceMappingURL=alpha.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alpha.js","sourceRoot":"","sources":["../src/alpha.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAIN,EAAE,EAIF,UAAU,EACV,wBAAwB,EACxB,YAAY,EAMZ,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,YAAY,EASZ,WAAW,EASX,MAAM,EAEN,WAAW,EACX,mBAAmB,EAQnB,sBAAsB,EACtB,gBAAgB,EAGhB,oBAAoB,EAKpB,cAAc,EAOd,uBAAuB,EAEvB,6BAA6B,EAC7B,kBAAkB,GAClB,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic core for BIAB site analytics. The React
|
|
3
|
+
* component (`<BIABAnalytics />`) wraps this; Svelte/Qwik/Vue/
|
|
4
|
+
* vanilla-JS consumers call `initBiabAnalytics(opts)` directly
|
|
5
|
+
* from their framework's "on mount" hook and call the returned
|
|
6
|
+
* cleanup function in their "on unmount" hook.
|
|
7
|
+
*
|
|
8
|
+
* Same privacy posture as the React component:
|
|
9
|
+
* - No cookies, no localStorage, no third-party requests
|
|
10
|
+
* - Honours navigator.doNotTrack + globalPrivacyControl
|
|
11
|
+
* - Never sees the visitor's IP or UA — those are read
|
|
12
|
+
* server-side by the ingest endpoint and used only to
|
|
13
|
+
* derive country + device family + a daily-rotating
|
|
14
|
+
* anon-id hash that resets every UTC midnight.
|
|
15
|
+
*/
|
|
16
|
+
export type InitBiabAnalyticsOptions = {
|
|
17
|
+
siteId: string;
|
|
18
|
+
baseUrl: string;
|
|
19
|
+
apiKey: string;
|
|
20
|
+
/** Defaults to true. Set false only if your privacy policy
|
|
21
|
+
* already commits to honouring DNT/GPC and you want to
|
|
22
|
+
* count those visitors. */
|
|
23
|
+
respectDnt?: boolean;
|
|
24
|
+
};
|
|
25
|
+
export type BiabAnalyticsTracker = {
|
|
26
|
+
/** Tear down the listeners. Safe to call multiple times. */
|
|
27
|
+
stop: () => void;
|
|
28
|
+
/** Fire a custom event. */
|
|
29
|
+
track: (name: string, opts?: {
|
|
30
|
+
path?: string;
|
|
31
|
+
}) => void;
|
|
32
|
+
};
|
|
33
|
+
export declare function initBiabAnalytics(options: InitBiabAnalyticsOptions): BiabAnalyticsTracker;
|
|
34
|
+
//# sourceMappingURL=analytics-core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-core.d.ts","sourceRoot":"","sources":["../src/analytics-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,wBAAwB,GAAG;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf;;gCAE4B;IAC5B,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAClC,4DAA4D;IAC5D,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,2BAA2B;IAC3B,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACxD,CAAC;AAEF,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,wBAAwB,GAC/B,oBAAoB,CA+HtB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic core for BIAB site analytics. The React
|
|
3
|
+
* component (`<BIABAnalytics />`) wraps this; Svelte/Qwik/Vue/
|
|
4
|
+
* vanilla-JS consumers call `initBiabAnalytics(opts)` directly
|
|
5
|
+
* from their framework's "on mount" hook and call the returned
|
|
6
|
+
* cleanup function in their "on unmount" hook.
|
|
7
|
+
*
|
|
8
|
+
* Same privacy posture as the React component:
|
|
9
|
+
* - No cookies, no localStorage, no third-party requests
|
|
10
|
+
* - Honours navigator.doNotTrack + globalPrivacyControl
|
|
11
|
+
* - Never sees the visitor's IP or UA — those are read
|
|
12
|
+
* server-side by the ingest endpoint and used only to
|
|
13
|
+
* derive country + device family + a daily-rotating
|
|
14
|
+
* anon-id hash that resets every UTC midnight.
|
|
15
|
+
*/
|
|
16
|
+
export function initBiabAnalytics(options) {
|
|
17
|
+
if (typeof window === "undefined") {
|
|
18
|
+
return { stop: () => { }, track: () => { } };
|
|
19
|
+
}
|
|
20
|
+
const respectDnt = options.respectDnt ?? true;
|
|
21
|
+
if (respectDnt && shouldOptOut()) {
|
|
22
|
+
return { stop: () => { }, track: () => { } };
|
|
23
|
+
}
|
|
24
|
+
const endpoint = `${options.baseUrl.replace(/\/$/, "")}/sites/${encodeURIComponent(options.siteId)}/analytics/events`;
|
|
25
|
+
let lastPath = null;
|
|
26
|
+
let lastEnterAt = 0;
|
|
27
|
+
let stopped = false;
|
|
28
|
+
const send = (kind, payload = {}) => {
|
|
29
|
+
if (stopped)
|
|
30
|
+
return;
|
|
31
|
+
const body = JSON.stringify({
|
|
32
|
+
kind,
|
|
33
|
+
path: payload.path ?? window.location.pathname,
|
|
34
|
+
referer: payload.referer === undefined
|
|
35
|
+
? document.referrer || null
|
|
36
|
+
: payload.referer,
|
|
37
|
+
...(payload.durationMs != null ? { durationMs: payload.durationMs } : {}),
|
|
38
|
+
...(payload.customEventName
|
|
39
|
+
? { customEventName: payload.customEventName }
|
|
40
|
+
: {}),
|
|
41
|
+
});
|
|
42
|
+
const blob = new Blob([body], { type: "application/json" });
|
|
43
|
+
try {
|
|
44
|
+
if (typeof navigator !== "undefined" &&
|
|
45
|
+
"sendBeacon" in navigator &&
|
|
46
|
+
navigator.sendBeacon(endpoint, blob)) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
/* fallthrough */
|
|
52
|
+
}
|
|
53
|
+
fetch(endpoint, {
|
|
54
|
+
method: "POST",
|
|
55
|
+
body,
|
|
56
|
+
headers: {
|
|
57
|
+
"Content-Type": "application/json",
|
|
58
|
+
Authorization: `Bearer ${options.apiKey}`,
|
|
59
|
+
},
|
|
60
|
+
keepalive: true,
|
|
61
|
+
}).catch(() => {
|
|
62
|
+
/* drop silently — analytics shouldn't break the page */
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
const trackPageview = (nextPath) => {
|
|
66
|
+
const now = Date.now();
|
|
67
|
+
if (lastPath && lastEnterAt > 0) {
|
|
68
|
+
const dur = now - lastEnterAt;
|
|
69
|
+
send("custom", {
|
|
70
|
+
path: lastPath,
|
|
71
|
+
durationMs: Math.max(0, Math.min(dur, 24 * 60 * 60 * 1000)),
|
|
72
|
+
customEventName: "pageview_duration",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
lastPath = nextPath;
|
|
76
|
+
lastEnterAt = now;
|
|
77
|
+
send("pageview", { path: nextPath });
|
|
78
|
+
};
|
|
79
|
+
// Session start once per init.
|
|
80
|
+
send("session_start");
|
|
81
|
+
trackPageview(window.location.pathname);
|
|
82
|
+
const origPush = history.pushState;
|
|
83
|
+
const origReplace = history.replaceState;
|
|
84
|
+
history.pushState = function (...args) {
|
|
85
|
+
const ret = origPush.apply(this, args);
|
|
86
|
+
queueMicrotask(() => trackPageview(window.location.pathname));
|
|
87
|
+
return ret;
|
|
88
|
+
};
|
|
89
|
+
history.replaceState = function (...args) {
|
|
90
|
+
const ret = origReplace.apply(this, args);
|
|
91
|
+
queueMicrotask(() => trackPageview(window.location.pathname));
|
|
92
|
+
return ret;
|
|
93
|
+
};
|
|
94
|
+
const onPop = () => trackPageview(window.location.pathname);
|
|
95
|
+
window.addEventListener("popstate", onPop);
|
|
96
|
+
const onVisibility = () => {
|
|
97
|
+
if (document.visibilityState !== "hidden")
|
|
98
|
+
return;
|
|
99
|
+
if (!lastPath || lastEnterAt === 0)
|
|
100
|
+
return;
|
|
101
|
+
const dur = Date.now() - lastEnterAt;
|
|
102
|
+
send("custom", {
|
|
103
|
+
path: lastPath,
|
|
104
|
+
durationMs: Math.max(0, Math.min(dur, 24 * 60 * 60 * 1000)),
|
|
105
|
+
customEventName: "pageview_duration",
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
109
|
+
return {
|
|
110
|
+
stop: () => {
|
|
111
|
+
if (stopped)
|
|
112
|
+
return;
|
|
113
|
+
stopped = true;
|
|
114
|
+
history.pushState = origPush;
|
|
115
|
+
history.replaceState = origReplace;
|
|
116
|
+
window.removeEventListener("popstate", onPop);
|
|
117
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
118
|
+
},
|
|
119
|
+
track: (name, opts) => send("custom", {
|
|
120
|
+
...(opts?.path !== undefined ? { path: opts.path } : {}),
|
|
121
|
+
customEventName: name,
|
|
122
|
+
}),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function shouldOptOut() {
|
|
126
|
+
if (typeof navigator === "undefined")
|
|
127
|
+
return false;
|
|
128
|
+
const dnt = navigator.doNotTrack ??
|
|
129
|
+
window.doNotTrack;
|
|
130
|
+
if (dnt === "1" || dnt === "yes")
|
|
131
|
+
return true;
|
|
132
|
+
const gpc = navigator
|
|
133
|
+
.globalPrivacyControl;
|
|
134
|
+
if (gpc === true)
|
|
135
|
+
return true;
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=analytics-core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-core.js","sourceRoot":"","sources":["../src/analytics-core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side analytics reporting — the half the browser tracker can't do.
|
|
3
|
+
*
|
|
4
|
+
* AI crawlers (GPTBot, ClaudeBot, PerplexityBot, …) fetch your HTML without
|
|
5
|
+
* executing JavaScript, so `<BIABAnalytics />` never sees them. Your server
|
|
6
|
+
* does. Call `reportAiCrawlerHit` from your middleware / request handler and
|
|
7
|
+
* BIAB records which pages the answer engines actually read — first-party
|
|
8
|
+
* AEO visibility, per page, per crawler.
|
|
9
|
+
*
|
|
10
|
+
* Next.js example (middleware.ts):
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { isAiCrawlerUserAgent, reportAiCrawlerHit } from "@businessdash/sdk/analytics-server";
|
|
14
|
+
*
|
|
15
|
+
* export function middleware(request: Request) {
|
|
16
|
+
* const ua = request.headers.get("user-agent");
|
|
17
|
+
* if (isAiCrawlerUserAgent(ua)) {
|
|
18
|
+
* // Fire-and-forget — never block or fail the crawler's request.
|
|
19
|
+
* void reportAiCrawlerHit({
|
|
20
|
+
* siteId: process.env.BIAB_SITE_ID!,
|
|
21
|
+
* baseUrl: process.env.NEXT_PUBLIC_BIAB_API_URL!,
|
|
22
|
+
* apiKey: process.env.NEXT_PUBLIC_BIAB_PUBLISHABLE_KEY!,
|
|
23
|
+
* userAgent: ua,
|
|
24
|
+
* path: new URL(request.url).pathname,
|
|
25
|
+
* });
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Abuse posture: the ingest endpoint accepts a forwarded user-agent ONLY
|
|
31
|
+
* when it matches a known AI crawler — a forwarded human UA is dropped
|
|
32
|
+
* server-side, so this path can record crawler visibility but can never
|
|
33
|
+
* inflate the site's human visitor counts. If this local pattern list ever
|
|
34
|
+
* lags the platform's, the result is under-reporting, never bad data.
|
|
35
|
+
*/
|
|
36
|
+
export declare function isAiCrawlerUserAgent(userAgent: string | null | undefined): boolean;
|
|
37
|
+
export type ReportAiCrawlerHitOptions = {
|
|
38
|
+
siteId: string;
|
|
39
|
+
/** Package-API base URL, e.g. "https://www.biab.app/api/package/v1". */
|
|
40
|
+
baseUrl: string;
|
|
41
|
+
/** Publishable key — same one `<BIABAnalytics />` uses. */
|
|
42
|
+
apiKey: string;
|
|
43
|
+
/** The crawler request's user-agent, verbatim. */
|
|
44
|
+
userAgent: string;
|
|
45
|
+
/** The path the crawler fetched, e.g. "/pricing". */
|
|
46
|
+
path: string;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Report one crawler fetch. Resolves quietly on every outcome — analytics
|
|
50
|
+
* must never break page serving — and returns whether the platform accepted
|
|
51
|
+
* the event (false for non-crawler UAs, network failures, etc.).
|
|
52
|
+
*/
|
|
53
|
+
export declare function reportAiCrawlerHit(options: ReportAiCrawlerHitOptions): Promise<boolean>;
|
|
54
|
+
//# sourceMappingURL=analytics-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-server.d.ts","sourceRoot":"","sources":["../src/analytics-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAUH,wBAAgB,oBAAoB,CACnC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAClC,OAAO,CAET;AAED,MAAM,MAAM,yBAAyB,GAAG;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,yBAAyB,GAChC,OAAO,CAAC,OAAO,CAAC,CA6BlB"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side analytics reporting — the half the browser tracker can't do.
|
|
3
|
+
*
|
|
4
|
+
* AI crawlers (GPTBot, ClaudeBot, PerplexityBot, …) fetch your HTML without
|
|
5
|
+
* executing JavaScript, so `<BIABAnalytics />` never sees them. Your server
|
|
6
|
+
* does. Call `reportAiCrawlerHit` from your middleware / request handler and
|
|
7
|
+
* BIAB records which pages the answer engines actually read — first-party
|
|
8
|
+
* AEO visibility, per page, per crawler.
|
|
9
|
+
*
|
|
10
|
+
* Next.js example (middleware.ts):
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { isAiCrawlerUserAgent, reportAiCrawlerHit } from "@businessdash/sdk/analytics-server";
|
|
14
|
+
*
|
|
15
|
+
* export function middleware(request: Request) {
|
|
16
|
+
* const ua = request.headers.get("user-agent");
|
|
17
|
+
* if (isAiCrawlerUserAgent(ua)) {
|
|
18
|
+
* // Fire-and-forget — never block or fail the crawler's request.
|
|
19
|
+
* void reportAiCrawlerHit({
|
|
20
|
+
* siteId: process.env.BIAB_SITE_ID!,
|
|
21
|
+
* baseUrl: process.env.NEXT_PUBLIC_BIAB_API_URL!,
|
|
22
|
+
* apiKey: process.env.NEXT_PUBLIC_BIAB_PUBLISHABLE_KEY!,
|
|
23
|
+
* userAgent: ua,
|
|
24
|
+
* path: new URL(request.url).pathname,
|
|
25
|
+
* });
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Abuse posture: the ingest endpoint accepts a forwarded user-agent ONLY
|
|
31
|
+
* when it matches a known AI crawler — a forwarded human UA is dropped
|
|
32
|
+
* server-side, so this path can record crawler visibility but can never
|
|
33
|
+
* inflate the site's human visitor counts. If this local pattern list ever
|
|
34
|
+
* lags the platform's, the result is under-reporting, never bad data.
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Cheap prefilter mirroring the platform's AI-crawler classifier, so your
|
|
38
|
+
* middleware only spends a network call on requests that will be kept.
|
|
39
|
+
* The platform's list is authoritative — this one just saves the round trip.
|
|
40
|
+
*/
|
|
41
|
+
const AI_CRAWLER_UA_PATTERN = /GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|Claude-User|Claude-SearchBot|Claude-Web|anthropic-ai|PerplexityBot|Perplexity-User|GrokBot|xAI-Crawler|Google-CloudVertexBot|GoogleOther|Applebot-Extended|meta-externalagent|Bytespider|CCBot|Amazonbot|cohere-ai|cohere-training-data-crawler|MistralAI-User|DuckAssistBot|YouBot|AI2Bot/i;
|
|
42
|
+
export function isAiCrawlerUserAgent(userAgent) {
|
|
43
|
+
return userAgent != null && AI_CRAWLER_UA_PATTERN.test(userAgent);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Report one crawler fetch. Resolves quietly on every outcome — analytics
|
|
47
|
+
* must never break page serving — and returns whether the platform accepted
|
|
48
|
+
* the event (false for non-crawler UAs, network failures, etc.).
|
|
49
|
+
*/
|
|
50
|
+
export async function reportAiCrawlerHit(options) {
|
|
51
|
+
const endpoint = `${options.baseUrl.replace(/\/$/, "")}/sites/${encodeURIComponent(options.siteId)}/analytics/events`;
|
|
52
|
+
try {
|
|
53
|
+
const res = await fetch(endpoint, {
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: {
|
|
56
|
+
"Content-Type": "application/json",
|
|
57
|
+
Authorization: `Bearer ${options.apiKey}`,
|
|
58
|
+
},
|
|
59
|
+
body: JSON.stringify({
|
|
60
|
+
kind: "pageview",
|
|
61
|
+
path: options.path,
|
|
62
|
+
referer: null,
|
|
63
|
+
visitorUserAgent: options.userAgent,
|
|
64
|
+
}),
|
|
65
|
+
// Middleware runtimes kill slow side-requests anyway; keepalive
|
|
66
|
+
// lets the report outlive the response where supported.
|
|
67
|
+
keepalive: true,
|
|
68
|
+
});
|
|
69
|
+
if (!res.ok)
|
|
70
|
+
return false;
|
|
71
|
+
const body = (await res.json().catch(() => null));
|
|
72
|
+
return body?.accepted === true;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=analytics-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-server.js","sourceRoot":"","sources":["../src/analytics-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH;;;;GAIG;AACH,MAAM,qBAAqB,GAC1B,yUAAyU,CAAC;AAE3U,MAAM,UAAU,oBAAoB,CACnC,SAAoC;IAEpC,OAAO,SAAS,IAAI,IAAI,IAAI,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACnE,CAAC;AAcD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,OAAkC;IAElC,MAAM,QAAQ,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,kBAAkB,CACjF,OAAO,CAAC,MAAM,CACd,mBAAmB,CAAC;IACrB,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;YACjC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACR,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,OAAO,CAAC,MAAM,EAAE;aACzC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACpB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,OAAO,EAAE,IAAI;gBACb,gBAAgB,EAAE,OAAO,CAAC,SAAS;aACnC,CAAC;YACF,gEAAgE;YAChE,wDAAwD;YACxD,SAAS,EAAE,IAAI;SACf,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QAC1B,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAExC,CAAC;QACT,OAAO,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC"}
|