@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.
Files changed (268) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +899 -0
  3. package/dist/adapters-revalidate.d.ts +44 -0
  4. package/dist/adapters-revalidate.d.ts.map +1 -0
  5. package/dist/adapters-revalidate.js +68 -0
  6. package/dist/adapters-revalidate.js.map +1 -0
  7. package/dist/alpha.d.ts +21 -0
  8. package/dist/alpha.d.ts.map +1 -0
  9. package/dist/alpha.js +21 -0
  10. package/dist/alpha.js.map +1 -0
  11. package/dist/analytics-core.d.ts +34 -0
  12. package/dist/analytics-core.d.ts.map +1 -0
  13. package/dist/analytics-core.js +138 -0
  14. package/dist/analytics-core.js.map +1 -0
  15. package/dist/analytics-server.d.ts +54 -0
  16. package/dist/analytics-server.d.ts.map +1 -0
  17. package/dist/analytics-server.js +78 -0
  18. package/dist/analytics-server.js.map +1 -0
  19. package/dist/attribution-logo.d.ts +2 -0
  20. package/dist/attribution-logo.d.ts.map +1 -0
  21. package/dist/attribution-logo.js +5 -0
  22. package/dist/attribution-logo.js.map +1 -0
  23. package/dist/auth-handler.d.ts +92 -0
  24. package/dist/auth-handler.d.ts.map +1 -0
  25. package/dist/auth-handler.js +277 -0
  26. package/dist/auth-handler.js.map +1 -0
  27. package/dist/biab-forms.css +484 -0
  28. package/dist/cli.d.ts +46 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +1824 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/client.d.ts +1681 -0
  33. package/dist/client.d.ts.map +1 -0
  34. package/dist/client.js +2845 -0
  35. package/dist/client.js.map +1 -0
  36. package/dist/collections.d.ts +13 -0
  37. package/dist/collections.d.ts.map +1 -0
  38. package/dist/collections.js +13 -0
  39. package/dist/collections.js.map +1 -0
  40. package/dist/contracts.d.ts +14609 -0
  41. package/dist/contracts.d.ts.map +1 -0
  42. package/dist/contracts.js +2428 -0
  43. package/dist/contracts.js.map +1 -0
  44. package/dist/data-model-schema.d.ts +962 -0
  45. package/dist/data-model-schema.d.ts.map +1 -0
  46. package/dist/data-model-schema.js +2295 -0
  47. package/dist/data-model-schema.js.map +1 -0
  48. package/dist/distribution.d.ts +38 -0
  49. package/dist/distribution.d.ts.map +1 -0
  50. package/dist/distribution.js +61 -0
  51. package/dist/distribution.js.map +1 -0
  52. package/dist/element.d.ts +121 -0
  53. package/dist/element.d.ts.map +1 -0
  54. package/dist/element.js +276 -0
  55. package/dist/element.js.map +1 -0
  56. package/dist/enums.d.ts +25 -0
  57. package/dist/enums.d.ts.map +1 -0
  58. package/dist/enums.js +38 -0
  59. package/dist/enums.js.map +1 -0
  60. package/dist/errors.d.ts +195 -0
  61. package/dist/errors.d.ts.map +1 -0
  62. package/dist/errors.js +188 -0
  63. package/dist/errors.js.map +1 -0
  64. package/dist/forms-core/autocomplete.d.ts +37 -0
  65. package/dist/forms-core/autocomplete.d.ts.map +1 -0
  66. package/dist/forms-core/autocomplete.js +82 -0
  67. package/dist/forms-core/autocomplete.js.map +1 -0
  68. package/dist/forms-core/business-function.d.ts +61 -0
  69. package/dist/forms-core/business-function.d.ts.map +1 -0
  70. package/dist/forms-core/business-function.js +149 -0
  71. package/dist/forms-core/business-function.js.map +1 -0
  72. package/dist/forms-core/calculation.d.ts +72 -0
  73. package/dist/forms-core/calculation.d.ts.map +1 -0
  74. package/dist/forms-core/calculation.js +103 -0
  75. package/dist/forms-core/calculation.js.map +1 -0
  76. package/dist/forms-core/controller.d.ts +249 -0
  77. package/dist/forms-core/controller.d.ts.map +1 -0
  78. package/dist/forms-core/controller.js +590 -0
  79. package/dist/forms-core/controller.js.map +1 -0
  80. package/dist/forms-core/elements.d.ts +44 -0
  81. package/dist/forms-core/elements.d.ts.map +1 -0
  82. package/dist/forms-core/elements.js +68 -0
  83. package/dist/forms-core/elements.js.map +1 -0
  84. package/dist/forms-core/email-domains.d.ts +10 -0
  85. package/dist/forms-core/email-domains.d.ts.map +1 -0
  86. package/dist/forms-core/email-domains.js +69 -0
  87. package/dist/forms-core/email-domains.js.map +1 -0
  88. package/dist/forms-core/file-rules.d.ts +51 -0
  89. package/dist/forms-core/file-rules.d.ts.map +1 -0
  90. package/dist/forms-core/file-rules.js +105 -0
  91. package/dist/forms-core/file-rules.js.map +1 -0
  92. package/dist/forms-core/formula.d.ts +114 -0
  93. package/dist/forms-core/formula.d.ts.map +1 -0
  94. package/dist/forms-core/formula.js +1170 -0
  95. package/dist/forms-core/formula.js.map +1 -0
  96. package/dist/forms-core/index.d.ts +24 -0
  97. package/dist/forms-core/index.d.ts.map +1 -0
  98. package/dist/forms-core/index.js +28 -0
  99. package/dist/forms-core/index.js.map +1 -0
  100. package/dist/forms-core/units.d.ts +49 -0
  101. package/dist/forms-core/units.d.ts.map +1 -0
  102. package/dist/forms-core/units.js +255 -0
  103. package/dist/forms-core/units.js.map +1 -0
  104. package/dist/forms-core/us-states.d.ts +14 -0
  105. package/dist/forms-core/us-states.d.ts.map +1 -0
  106. package/dist/forms-core/us-states.js +66 -0
  107. package/dist/forms-core/us-states.js.map +1 -0
  108. package/dist/forms-core/validation.d.ts +266 -0
  109. package/dist/forms-core/validation.d.ts.map +1 -0
  110. package/dist/forms-core/validation.js +850 -0
  111. package/dist/forms-core/validation.js.map +1 -0
  112. package/dist/forms.d.ts +19 -0
  113. package/dist/forms.d.ts.map +1 -0
  114. package/dist/forms.js +29 -0
  115. package/dist/forms.js.map +1 -0
  116. package/dist/gallery-types.d.ts +32 -0
  117. package/dist/gallery-types.d.ts.map +1 -0
  118. package/dist/gallery-types.js +2 -0
  119. package/dist/gallery-types.js.map +1 -0
  120. package/dist/graphql.d.ts +97 -0
  121. package/dist/graphql.d.ts.map +1 -0
  122. package/dist/graphql.js +212 -0
  123. package/dist/graphql.js.map +1 -0
  124. package/dist/index.cjs +19448 -0
  125. package/dist/index.d.cts +19 -0
  126. package/dist/index.d.mts +19 -0
  127. package/dist/index.d.ts +19 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +20 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/marketing-schema.d.ts +216 -0
  132. package/dist/marketing-schema.d.ts.map +1 -0
  133. package/dist/marketing-schema.js +200 -0
  134. package/dist/marketing-schema.js.map +1 -0
  135. package/dist/mcp.d.ts +42 -0
  136. package/dist/mcp.d.ts.map +1 -0
  137. package/dist/mcp.js +87 -0
  138. package/dist/mcp.js.map +1 -0
  139. package/dist/native.d.ts +45 -0
  140. package/dist/native.d.ts.map +1 -0
  141. package/dist/native.js +43 -0
  142. package/dist/native.js.map +1 -0
  143. package/dist/next-revalidate.d.ts +43 -0
  144. package/dist/next-revalidate.d.ts.map +1 -0
  145. package/dist/next-revalidate.js +84 -0
  146. package/dist/next-revalidate.js.map +1 -0
  147. package/dist/parallel-pages.d.ts +102 -0
  148. package/dist/parallel-pages.d.ts.map +1 -0
  149. package/dist/parallel-pages.js +108 -0
  150. package/dist/parallel-pages.js.map +1 -0
  151. package/dist/payment-icons.d.ts +66 -0
  152. package/dist/payment-icons.d.ts.map +1 -0
  153. package/dist/payment-icons.js +160 -0
  154. package/dist/payment-icons.js.map +1 -0
  155. package/dist/proxy.d.ts +67 -0
  156. package/dist/proxy.d.ts.map +1 -0
  157. package/dist/proxy.js +97 -0
  158. package/dist/proxy.js.map +1 -0
  159. package/dist/react-analytics.d.ts +39 -0
  160. package/dist/react-analytics.d.ts.map +1 -0
  161. package/dist/react-analytics.js +59 -0
  162. package/dist/react-analytics.js.map +1 -0
  163. package/dist/react-attribution.d.ts +99 -0
  164. package/dist/react-attribution.d.ts.map +1 -0
  165. package/dist/react-attribution.js +52 -0
  166. package/dist/react-attribution.js.map +1 -0
  167. package/dist/react-marketing.d.ts +181 -0
  168. package/dist/react-marketing.d.ts.map +1 -0
  169. package/dist/react-marketing.js +215 -0
  170. package/dist/react-marketing.js.map +1 -0
  171. package/dist/react.d.ts +727 -0
  172. package/dist/react.d.ts.map +1 -0
  173. package/dist/react.js +2418 -0
  174. package/dist/react.js.map +1 -0
  175. package/dist/reserved-paths.d.ts +24 -0
  176. package/dist/reserved-paths.d.ts.map +1 -0
  177. package/dist/reserved-paths.js +60 -0
  178. package/dist/reserved-paths.js.map +1 -0
  179. package/dist/revalidate-verify.d.ts +30 -0
  180. package/dist/revalidate-verify.d.ts.map +1 -0
  181. package/dist/revalidate-verify.js +74 -0
  182. package/dist/revalidate-verify.js.map +1 -0
  183. package/dist/sdk.d.ts +678 -0
  184. package/dist/sdk.d.ts.map +1 -0
  185. package/dist/sdk.js +801 -0
  186. package/dist/sdk.js.map +1 -0
  187. package/dist/seo.d.ts +218 -0
  188. package/dist/seo.d.ts.map +1 -0
  189. package/dist/seo.js +309 -0
  190. package/dist/seo.js.map +1 -0
  191. package/dist/socials.d.ts +47 -0
  192. package/dist/socials.d.ts.map +1 -0
  193. package/dist/socials.js +172 -0
  194. package/dist/socials.js.map +1 -0
  195. package/dist/static.d.ts +14 -0
  196. package/dist/static.d.ts.map +1 -0
  197. package/dist/static.js +14 -0
  198. package/dist/static.js.map +1 -0
  199. package/dist/url-pattern.d.ts +47 -0
  200. package/dist/url-pattern.d.ts.map +1 -0
  201. package/dist/url-pattern.js +124 -0
  202. package/dist/url-pattern.js.map +1 -0
  203. package/dist/vanilla.d.ts +77 -0
  204. package/dist/vanilla.d.ts.map +1 -0
  205. package/dist/vanilla.js +903 -0
  206. package/dist/vanilla.js.map +1 -0
  207. package/openapi.json +13779 -0
  208. package/package.json +204 -0
  209. package/src/adapters-revalidate.ts +88 -0
  210. package/src/alpha.ts +89 -0
  211. package/src/analytics-core.ts +175 -0
  212. package/src/analytics-server.ts +99 -0
  213. package/src/angular/biab-form.component.ts +1443 -0
  214. package/src/angular/index.ts +26 -0
  215. package/src/attribution-logo.ts +5 -0
  216. package/src/auth-handler.ts +352 -0
  217. package/src/cli.ts +2517 -0
  218. package/src/client.ts +3578 -0
  219. package/src/collections.ts +101 -0
  220. package/src/contracts.ts +3390 -0
  221. package/src/data-model-schema.ts +4042 -0
  222. package/src/distribution.ts +73 -0
  223. package/src/element.ts +321 -0
  224. package/src/enums.ts +65 -0
  225. package/src/errors.ts +338 -0
  226. package/src/forms-core/autocomplete.ts +97 -0
  227. package/src/forms-core/business-function.ts +209 -0
  228. package/src/forms-core/calculation.ts +167 -0
  229. package/src/forms-core/controller.ts +922 -0
  230. package/src/forms-core/elements.ts +86 -0
  231. package/src/forms-core/email-domains.ts +68 -0
  232. package/src/forms-core/file-rules.ts +123 -0
  233. package/src/forms-core/formula.ts +1339 -0
  234. package/src/forms-core/index.ts +122 -0
  235. package/src/forms-core/units.ts +308 -0
  236. package/src/forms-core/us-states.ts +68 -0
  237. package/src/forms-core/validation.ts +1037 -0
  238. package/src/forms.ts +63 -0
  239. package/src/gallery-types.ts +31 -0
  240. package/src/graphql.ts +295 -0
  241. package/src/index.ts +505 -0
  242. package/src/marketing-schema.ts +395 -0
  243. package/src/mcp.ts +108 -0
  244. package/src/native.ts +73 -0
  245. package/src/next-revalidate.ts +124 -0
  246. package/src/parallel-pages.ts +192 -0
  247. package/src/payment-icons.ts +205 -0
  248. package/src/proxy.ts +173 -0
  249. package/src/qwik.tsx +1234 -0
  250. package/src/react-analytics.tsx +76 -0
  251. package/src/react-attribution.tsx +192 -0
  252. package/src/react-marketing.tsx +338 -0
  253. package/src/react.tsx +5495 -0
  254. package/src/reserved-paths.ts +65 -0
  255. package/src/revalidate-verify.ts +98 -0
  256. package/src/sdk.ts +1671 -0
  257. package/src/seo.ts +488 -0
  258. package/src/socials.ts +230 -0
  259. package/src/solid.tsx +1466 -0
  260. package/src/static.ts +21 -0
  261. package/src/styles/biab-forms.css +484 -0
  262. package/src/svelte/BiabForm.svelte +1069 -0
  263. package/src/svelte/context.ts +57 -0
  264. package/src/svelte/index.ts +79 -0
  265. package/src/url-pattern.ts +153 -0
  266. package/src/vanilla.ts +1290 -0
  267. package/src/vue/BiabForm.vue +1538 -0
  268. 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
@@ -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"}
@@ -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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"}