@businessdash/sdk 0.9.60 → 0.9.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +991 -295
- package/assets/biab-sw.js +92 -0
- package/dist/account-core/index.d.ts +126 -0
- package/dist/account-core/index.d.ts.map +1 -0
- package/dist/account-core/index.js +191 -0
- package/dist/account-core/index.js.map +1 -0
- package/dist/account.d.ts +11 -0
- package/dist/account.d.ts.map +1 -0
- package/dist/account.js +11 -0
- package/dist/account.js.map +1 -0
- package/dist/auth-handler.d.ts +1 -1
- package/dist/auth-links.d.ts +33 -0
- package/dist/auth-links.d.ts.map +1 -0
- package/dist/auth-links.js +64 -0
- package/dist/auth-links.js.map +1 -0
- package/dist/blog-core/index.d.ts +112 -0
- package/dist/blog-core/index.d.ts.map +1 -0
- package/dist/blog-core/index.js +330 -0
- package/dist/blog-core/index.js.map +1 -0
- package/dist/blog.d.ts +11 -0
- package/dist/blog.d.ts.map +1 -0
- package/dist/blog.js +11 -0
- package/dist/blog.js.map +1 -0
- package/dist/chat-core/index.d.ts +97 -0
- package/dist/chat-core/index.d.ts.map +1 -0
- package/dist/chat-core/index.js +237 -0
- package/dist/chat-core/index.js.map +1 -0
- package/dist/chat.d.ts +11 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +11 -0
- package/dist/chat.js.map +1 -0
- package/dist/checkout-core/index.d.ts +65 -0
- package/dist/checkout-core/index.d.ts.map +1 -0
- package/dist/checkout-core/index.js +159 -0
- package/dist/checkout-core/index.js.map +1 -0
- package/dist/checkout.d.ts +10 -0
- package/dist/checkout.d.ts.map +1 -0
- package/dist/checkout.js +10 -0
- package/dist/checkout.js.map +1 -0
- package/dist/cli.js +133 -25
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +622 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +888 -1
- package/dist/client.js.map +1 -1
- package/dist/consent-core/index.cjs +107 -0
- package/dist/consent-core/index.d.ts +103 -0
- package/dist/consent-core/index.d.ts.map +1 -0
- package/dist/consent-core/index.js +157 -0
- package/dist/consent-core/index.js.map +1 -0
- package/dist/contracts.d.ts +3526 -767
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +571 -4
- package/dist/contracts.js.map +1 -1
- package/dist/data-model-schema.d.ts +1 -1
- package/dist/data-model-schema.d.ts.map +1 -1
- package/dist/element.d.ts +30 -0
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +56 -0
- package/dist/element.js.map +1 -1
- package/dist/embed-protocol.d.ts +86 -0
- package/dist/embed-protocol.d.ts.map +1 -0
- package/dist/embed-protocol.js +60 -0
- package/dist/embed-protocol.js.map +1 -0
- package/dist/framework-support.d.ts +122 -0
- package/dist/framework-support.d.ts.map +1 -0
- package/dist/framework-support.js +323 -0
- package/dist/framework-support.js.map +1 -0
- package/dist/index.cjs +1355 -24
- package/dist/legal-core/index.cjs +115 -0
- package/dist/legal-core/index.d.ts +160 -0
- package/dist/legal-core/index.d.ts.map +1 -0
- package/dist/legal-core/index.js +220 -0
- package/dist/legal-core/index.js.map +1 -0
- package/dist/marketing-core/index.d.ts +66 -0
- package/dist/marketing-core/index.d.ts.map +1 -0
- package/dist/marketing-core/index.js +154 -0
- package/dist/marketing-core/index.js.map +1 -0
- package/dist/marketing.d.ts +7 -0
- package/dist/marketing.d.ts.map +1 -0
- package/dist/marketing.js +7 -0
- package/dist/marketing.js.map +1 -0
- package/dist/mcp-adapters/index.d.ts +135 -0
- package/dist/mcp-adapters/index.d.ts.map +1 -0
- package/dist/mcp-adapters/index.js +187 -0
- package/dist/mcp-adapters/index.js.map +1 -0
- package/dist/mcp-adapters.d.ts +7 -0
- package/dist/mcp-adapters.d.ts.map +1 -0
- package/dist/mcp-adapters.js +7 -0
- package/dist/mcp-adapters.js.map +1 -0
- package/dist/model3d-core/index.cjs +95 -0
- package/dist/model3d-core/index.d.ts +167 -0
- package/dist/model3d-core/index.d.ts.map +1 -0
- package/dist/model3d-core/index.js +158 -0
- package/dist/model3d-core/index.js.map +1 -0
- package/dist/notifications-core/index.cjs +315 -0
- package/dist/notifications-core/index.d.ts +229 -0
- package/dist/notifications-core/index.d.ts.map +1 -0
- package/dist/notifications-core/index.js +445 -0
- package/dist/notifications-core/index.js.map +1 -0
- package/dist/portal-core/index.d.ts +451 -0
- package/dist/portal-core/index.d.ts.map +1 -0
- package/dist/portal-core/index.js +819 -0
- package/dist/portal-core/index.js.map +1 -0
- package/dist/portal.d.ts +7 -0
- package/dist/portal.d.ts.map +1 -0
- package/dist/portal.js +7 -0
- package/dist/portal.js.map +1 -0
- package/dist/push-core/index.cjs +171 -0
- package/dist/push-core/index.d.ts +149 -0
- package/dist/push-core/index.d.ts.map +1 -0
- package/dist/push-core/index.js +231 -0
- package/dist/push-core/index.js.map +1 -0
- package/dist/react-marketing.d.ts +1 -17
- package/dist/react-marketing.d.ts.map +1 -1
- package/dist/react-marketing.js +4 -0
- package/dist/react-marketing.js.map +1 -1
- package/dist/react.d.ts +294 -101
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +302 -246
- package/dist/react.js.map +1 -1
- package/dist/seed-core/index.d.ts +354 -0
- package/dist/seed-core/index.d.ts.map +1 -0
- package/dist/seed-core/index.js +420 -0
- package/dist/seed-core/index.js.map +1 -0
- package/dist/seed.d.ts +7 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +7 -0
- package/dist/seed.js.map +1 -0
- package/dist/seo-core/blog.d.ts +94 -0
- package/dist/seo-core/blog.d.ts.map +1 -0
- package/dist/seo-core/blog.js +149 -0
- package/dist/seo-core/blog.js.map +1 -0
- package/dist/seo-core/commerce.d.ts +64 -0
- package/dist/seo-core/commerce.d.ts.map +1 -0
- package/dist/seo-core/commerce.js +87 -0
- package/dist/seo-core/commerce.js.map +1 -0
- package/dist/seo-core/index.cjs +751 -0
- package/dist/seo-core/index.d.ts +226 -0
- package/dist/seo-core/index.d.ts.map +1 -0
- package/dist/seo-core/index.js +455 -0
- package/dist/seo-core/index.js.map +1 -0
- package/dist/seo-core/local.d.ts +181 -0
- package/dist/seo-core/local.d.ts.map +1 -0
- package/dist/seo-core/local.js +193 -0
- package/dist/seo-core/local.js.map +1 -0
- package/dist/sitemap-core/index.cjs +167 -0
- package/dist/sitemap-core/index.d.ts +155 -0
- package/dist/sitemap-core/index.d.ts.map +1 -0
- package/dist/sitemap-core/index.js +195 -0
- package/dist/sitemap-core/index.js.map +1 -0
- package/dist/social-core/index.d.ts +74 -0
- package/dist/social-core/index.d.ts.map +1 -0
- package/dist/social-core/index.js +72 -0
- package/dist/social-core/index.js.map +1 -0
- package/dist/social.d.ts +7 -0
- package/dist/social.d.ts.map +1 -0
- package/dist/social.js +7 -0
- package/dist/social.js.map +1 -0
- package/dist/solid-compat.d.ts +204 -0
- package/dist/solid-compat.d.ts.map +1 -0
- package/dist/solid-compat.js +221 -0
- package/dist/solid-compat.js.map +1 -0
- package/dist/store-core/index.d.ts +141 -0
- package/dist/store-core/index.d.ts.map +1 -0
- package/dist/store-core/index.js +277 -0
- package/dist/store-core/index.js.map +1 -0
- package/dist/store.d.ts +12 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +12 -0
- package/dist/store.js.map +1 -0
- package/dist/vanilla.d.ts +111 -0
- package/dist/vanilla.d.ts.map +1 -1
- package/dist/vanilla.js +206 -0
- package/dist/vanilla.js.map +1 -1
- package/dist/verify-core/index.d.ts +98 -0
- package/dist/verify-core/index.d.ts.map +1 -0
- package/dist/verify-core/index.js +186 -0
- package/dist/verify-core/index.js.map +1 -0
- package/dist/verify.d.ts +8 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +8 -0
- package/dist/verify.js.map +1 -0
- package/openapi.json +4516 -1311
- package/package.json +128 -11
- package/src/account-core/index.ts +309 -0
- package/src/account.ts +11 -0
- package/src/angular/headless.ts +519 -0
- package/src/angular/index.ts +3 -0
- package/src/auth-links.ts +76 -0
- package/src/blog-core/index.ts +423 -0
- package/src/blog.ts +11 -0
- package/src/chat-core/index.ts +335 -0
- package/src/chat.ts +11 -0
- package/src/checkout-core/index.ts +225 -0
- package/src/checkout.ts +10 -0
- package/src/cli.ts +184 -28
- package/src/client.ts +1097 -0
- package/src/consent-core/index.ts +213 -0
- package/src/contracts.ts +768 -11
- package/src/data-model-schema.ts +1 -1
- package/src/element.ts +102 -0
- package/src/embed-protocol.ts +100 -0
- package/src/framework-support.ts +440 -0
- package/src/legal-core/index.ts +276 -0
- package/src/marketing-core/index.ts +209 -0
- package/src/marketing.ts +7 -0
- package/src/mcp-adapters/index.ts +264 -0
- package/src/mcp-adapters.ts +7 -0
- package/src/model3d-core/index.ts +248 -0
- package/src/notifications-core/index.ts +650 -0
- package/src/portal-core/index.ts +1564 -0
- package/src/portal.ts +7 -0
- package/src/push-core/index.ts +335 -0
- package/src/qwik.tsx +602 -2
- package/src/react-marketing.tsx +5 -0
- package/src/react.tsx +434 -319
- package/src/seed-core/index.ts +735 -0
- package/src/seed.ts +7 -0
- package/src/seo-core/blog.ts +216 -0
- package/src/seo-core/commerce.ts +138 -0
- package/src/seo-core/index.ts +605 -0
- package/src/seo-core/local.ts +333 -0
- package/src/sitemap-core/index.ts +296 -0
- package/src/social-core/index.ts +103 -0
- package/src/social.ts +7 -0
- package/src/solid-compat.tsx +347 -0
- package/src/solid-surfaces.tsx +1311 -0
- package/src/solid.tsx +82 -60
- package/src/store-core/index.ts +426 -0
- package/src/store.ts +12 -0
- package/src/svelte/SocialLinks.svelte +84 -0
- package/src/svelte/headless.ts +435 -0
- package/src/svelte/index.ts +9 -0
- package/src/vanilla.ts +367 -0
- package/src/verify-core/index.ts +288 -0
- package/src/verify.ts +8 -0
- package/src/vue/headless.ts +527 -0
- package/src/vue/index.ts +3 -0
package/package.json
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@businessdash/sdk",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.80",
|
|
4
4
|
"description": "BusinessDash developer SDK \u2014 the data layer that lets you build customer-facing surfaces on your own domain while BusinessDash handles the operations stack behind the scenes. 0.9.x ships a comprehensive programmatic surface: storefront (products, categories, cart, checkout via Stripe Connect with Link payment), customer portal (work feed, per-item detail, quote accept/reject, job activity, comment threads, reviews, notification preferences), blog (posts, categories, threaded comments, reactions, paywalls, Mux video), Front Desk chat (sessions, AI bot, live human handoff, queue + place-in-line), coupons (validation against synced Stripe Promotion Codes \u2014 BOGO/BXGY/free-shipping kinds), shipping (multi-carrier rates + tracking via Shippo), address validation (Google Places, platform-proxied), customer notification preferences across in-app/email/SMS/webhook, subscriptions admin + Stripe sync, and followers/subscribers. Also: tenant sign-in/up/out via the auth handler, schema-driven marketing pages with restore semantics, typed JSON-LD SEO builders (LocalBusiness/Service/FAQ/Article/Breadcrumb/Review), and a CLI (`biab-dev sync-schema`) for the schema flow. The consumer renders the UI in their own design system on their own domain; BusinessDash supplies the data, the business logic, and the Stripe/Mux/Google/Shippo plumbing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
9
|
"openapi.json",
|
|
10
|
-
"src"
|
|
10
|
+
"src",
|
|
11
|
+
"assets"
|
|
11
12
|
],
|
|
12
13
|
"main": "./dist/index.js",
|
|
13
14
|
"module": "./dist/index.js",
|
|
14
15
|
"types": "./dist/index.d.ts",
|
|
15
16
|
"bin": {
|
|
16
|
-
"biab-dev": "
|
|
17
|
-
"businessdash": "
|
|
17
|
+
"biab-dev": "dist/cli.js",
|
|
18
|
+
"businessdash": "dist/cli.js"
|
|
18
19
|
},
|
|
19
20
|
"exports": {
|
|
20
21
|
".": {
|
|
@@ -31,6 +32,10 @@
|
|
|
31
32
|
"types": "./dist/contracts.d.ts",
|
|
32
33
|
"import": "./dist/contracts.js"
|
|
33
34
|
},
|
|
35
|
+
"./framework-support": {
|
|
36
|
+
"types": "./dist/framework-support.d.ts",
|
|
37
|
+
"import": "./dist/framework-support.js"
|
|
38
|
+
},
|
|
34
39
|
"./native": {
|
|
35
40
|
"types": "./dist/native.d.ts",
|
|
36
41
|
"import": "./dist/native.js"
|
|
@@ -51,6 +56,46 @@
|
|
|
51
56
|
"types": "./dist/forms.d.ts",
|
|
52
57
|
"import": "./dist/forms.js"
|
|
53
58
|
},
|
|
59
|
+
"./store": {
|
|
60
|
+
"types": "./dist/store.d.ts",
|
|
61
|
+
"import": "./dist/store.js"
|
|
62
|
+
},
|
|
63
|
+
"./chat": {
|
|
64
|
+
"types": "./dist/chat.d.ts",
|
|
65
|
+
"import": "./dist/chat.js"
|
|
66
|
+
},
|
|
67
|
+
"./blog": {
|
|
68
|
+
"types": "./dist/blog.d.ts",
|
|
69
|
+
"import": "./dist/blog.js"
|
|
70
|
+
},
|
|
71
|
+
"./checkout": {
|
|
72
|
+
"types": "./dist/checkout.d.ts",
|
|
73
|
+
"import": "./dist/checkout.js"
|
|
74
|
+
},
|
|
75
|
+
"./account": {
|
|
76
|
+
"types": "./dist/account.d.ts",
|
|
77
|
+
"import": "./dist/account.js"
|
|
78
|
+
},
|
|
79
|
+
"./marketing": {
|
|
80
|
+
"types": "./dist/marketing.d.ts",
|
|
81
|
+
"import": "./dist/marketing.js"
|
|
82
|
+
},
|
|
83
|
+
"./verify": {
|
|
84
|
+
"types": "./dist/verify.d.ts",
|
|
85
|
+
"import": "./dist/verify.js"
|
|
86
|
+
},
|
|
87
|
+
"./portal": {
|
|
88
|
+
"types": "./dist/portal.d.ts",
|
|
89
|
+
"import": "./dist/portal.js"
|
|
90
|
+
},
|
|
91
|
+
"./social": {
|
|
92
|
+
"types": "./dist/social.d.ts",
|
|
93
|
+
"import": "./dist/social.js"
|
|
94
|
+
},
|
|
95
|
+
"./seed": {
|
|
96
|
+
"types": "./dist/seed.d.ts",
|
|
97
|
+
"import": "./dist/seed.js"
|
|
98
|
+
},
|
|
54
99
|
"./collections": {
|
|
55
100
|
"types": "./dist/collections.d.ts",
|
|
56
101
|
"import": "./dist/collections.js"
|
|
@@ -113,6 +158,10 @@
|
|
|
113
158
|
"types": "./dist/mcp.d.ts",
|
|
114
159
|
"import": "./dist/mcp.js"
|
|
115
160
|
},
|
|
161
|
+
"./mcp-adapters": {
|
|
162
|
+
"types": "./dist/mcp-adapters.d.ts",
|
|
163
|
+
"import": "./dist/mcp-adapters.js"
|
|
164
|
+
},
|
|
116
165
|
"./proxy": {
|
|
117
166
|
"types": "./dist/proxy.d.ts",
|
|
118
167
|
"import": "./dist/proxy.js"
|
|
@@ -141,7 +190,43 @@
|
|
|
141
190
|
"types": "./dist/adapters-revalidate.d.ts",
|
|
142
191
|
"import": "./dist/adapters-revalidate.js"
|
|
143
192
|
},
|
|
144
|
-
"./biab-forms.css": "./dist/biab-forms.css"
|
|
193
|
+
"./biab-forms.css": "./dist/biab-forms.css",
|
|
194
|
+
"./seo-core": {
|
|
195
|
+
"types": "./dist/seo-core/index.d.ts",
|
|
196
|
+
"import": "./dist/seo-core/index.js",
|
|
197
|
+
"require": "./dist/seo-core/index.cjs"
|
|
198
|
+
},
|
|
199
|
+
"./push-core": {
|
|
200
|
+
"types": "./dist/push-core/index.d.ts",
|
|
201
|
+
"import": "./dist/push-core/index.js",
|
|
202
|
+
"require": "./dist/push-core/index.cjs"
|
|
203
|
+
},
|
|
204
|
+
"./notifications": {
|
|
205
|
+
"types": "./dist/notifications-core/index.d.ts",
|
|
206
|
+
"import": "./dist/notifications-core/index.js",
|
|
207
|
+
"require": "./dist/notifications-core/index.cjs"
|
|
208
|
+
},
|
|
209
|
+
"./legal": {
|
|
210
|
+
"types": "./dist/legal-core/index.d.ts",
|
|
211
|
+
"import": "./dist/legal-core/index.js",
|
|
212
|
+
"require": "./dist/legal-core/index.cjs"
|
|
213
|
+
},
|
|
214
|
+
"./sitemap": {
|
|
215
|
+
"types": "./dist/sitemap-core/index.d.ts",
|
|
216
|
+
"import": "./dist/sitemap-core/index.js",
|
|
217
|
+
"require": "./dist/sitemap-core/index.cjs"
|
|
218
|
+
},
|
|
219
|
+
"./model3d": {
|
|
220
|
+
"types": "./dist/model3d-core/index.d.ts",
|
|
221
|
+
"import": "./dist/model3d-core/index.js",
|
|
222
|
+
"require": "./dist/model3d-core/index.cjs"
|
|
223
|
+
},
|
|
224
|
+
"./consent": {
|
|
225
|
+
"types": "./dist/consent-core/index.d.ts",
|
|
226
|
+
"import": "./dist/consent-core/index.js",
|
|
227
|
+
"require": "./dist/consent-core/index.cjs"
|
|
228
|
+
},
|
|
229
|
+
"./biab-sw.js": "./assets/biab-sw.js"
|
|
145
230
|
},
|
|
146
231
|
"scripts": {
|
|
147
232
|
"clean": "node -e \"const fs=require('node:fs');fs.rmSync('dist',{recursive:true,force:true})\"",
|
|
@@ -149,19 +234,25 @@
|
|
|
149
234
|
"openapi": "tsx scripts/openapi.ts",
|
|
150
235
|
"openapi:check": "tsx scripts/openapi.ts --check",
|
|
151
236
|
"postbuild": "node scripts/publish-types.js",
|
|
152
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
237
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.solid.json --noEmit && tsc -p tsconfig.qwik.json --noEmit && tsc -p tsconfig.headless.json --noEmit",
|
|
153
238
|
"test:types": "tsc -p tsconfig.type-tests.json --noEmit",
|
|
154
239
|
"test": "tsx --test test/*.test.ts test/*.test.tsx",
|
|
155
240
|
"lint": "biome check .",
|
|
156
241
|
"lint:fix": "biome check --write .",
|
|
157
|
-
"prepublishOnly": "npm run build"
|
|
242
|
+
"prepublishOnly": "npm run build",
|
|
243
|
+
"typecheck:solid": "tsc -p tsconfig.solid.json --noEmit",
|
|
244
|
+
"typecheck:headless": "tsc -p tsconfig.headless.json --noEmit",
|
|
245
|
+
"typecheck:qwik": "tsc -p tsconfig.qwik.json --noEmit",
|
|
246
|
+
"gen:socials": "tsx scripts/gen-social-tables.ts",
|
|
247
|
+
"gen:socials:check": "tsx scripts/gen-social-tables.ts --check",
|
|
248
|
+
"typecheck:solid2": "tsc -p tsconfig.solid2.json --noEmit"
|
|
158
249
|
},
|
|
159
250
|
"publishConfig": {
|
|
160
251
|
"access": "public"
|
|
161
252
|
},
|
|
162
253
|
"repository": {
|
|
163
254
|
"type": "git",
|
|
164
|
-
"url": "git+https://github.com/
|
|
255
|
+
"url": "git+https://github.com/businessdash/platform.git",
|
|
165
256
|
"directory": "biab-dev"
|
|
166
257
|
},
|
|
167
258
|
"license": "MIT",
|
|
@@ -178,8 +269,13 @@
|
|
|
178
269
|
"zod-to-json-schema": "^3.25.2"
|
|
179
270
|
},
|
|
180
271
|
"peerDependencies": {
|
|
181
|
-
"
|
|
182
|
-
"
|
|
272
|
+
"@angular/core": ">=17.0.0",
|
|
273
|
+
"@builder.io/qwik": ">=1.5.0 <2",
|
|
274
|
+
"react": ">=18.0.0 <20",
|
|
275
|
+
"react-dom": ">=18.0.0 <20",
|
|
276
|
+
"solid-js": ">=1.8.0 <3",
|
|
277
|
+
"svelte": ">=5.0.0 <6",
|
|
278
|
+
"vue": ">=3.3.0 <4"
|
|
183
279
|
},
|
|
184
280
|
"peerDependenciesMeta": {
|
|
185
281
|
"react": {
|
|
@@ -187,14 +283,35 @@
|
|
|
187
283
|
},
|
|
188
284
|
"react-dom": {
|
|
189
285
|
"optional": true
|
|
286
|
+
},
|
|
287
|
+
"solid-js": {
|
|
288
|
+
"optional": true
|
|
289
|
+
},
|
|
290
|
+
"vue": {
|
|
291
|
+
"optional": true
|
|
292
|
+
},
|
|
293
|
+
"svelte": {
|
|
294
|
+
"optional": true
|
|
295
|
+
},
|
|
296
|
+
"@builder.io/qwik": {
|
|
297
|
+
"optional": true
|
|
298
|
+
},
|
|
299
|
+
"@angular/core": {
|
|
300
|
+
"optional": true
|
|
190
301
|
}
|
|
191
302
|
},
|
|
192
303
|
"devDependencies": {
|
|
193
304
|
"@biomejs/biome": "^2.5.1",
|
|
305
|
+
"@builder.io/qwik": "^1.5.0",
|
|
306
|
+
"@solidjs/web": "2.0.0-rc.1",
|
|
194
307
|
"@types/node": "^20.19.43",
|
|
195
308
|
"@types/react": "^19.2.17",
|
|
196
309
|
"esbuild": "^0.28.1",
|
|
197
|
-
"
|
|
310
|
+
"preact": "^10.29.8",
|
|
311
|
+
"preact-render-to-string": "^6.7.0",
|
|
312
|
+
"react": "^19.2.8",
|
|
313
|
+
"react-dom": "^19.2.8",
|
|
314
|
+
"solid-js-v2": "npm:solid-js@2.0.0-rc.1",
|
|
198
315
|
"tsx": "^4.22.4",
|
|
199
316
|
"typescript": "^5.9.3"
|
|
200
317
|
},
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@businessdash/sdk/account` — headless customer session and followers.
|
|
3
|
+
*
|
|
4
|
+
* Two small controllers that were React-only (plus Solid) and had no reason to
|
|
5
|
+
* be: neither has any framework-specific logic.
|
|
6
|
+
*
|
|
7
|
+
* ## Session
|
|
8
|
+
*
|
|
9
|
+
* `createUserController` reads the auth handler's `/me` route with the session
|
|
10
|
+
* cookie. It never touches an API key — the handler the consumer mounts owns
|
|
11
|
+
* the credential, and this only asks it who is signed in.
|
|
12
|
+
*
|
|
13
|
+
* Sign-in, sign-up and sign-out are navigations, not requests, so they are
|
|
14
|
+
* plain functions over `buildAuthHref` rather than controller actions. Every
|
|
15
|
+
* one of them no-ops outside a browser instead of throwing, so an SSR render
|
|
16
|
+
* that touches them degrades rather than crashes.
|
|
17
|
+
*
|
|
18
|
+
* ## Followers
|
|
19
|
+
*
|
|
20
|
+
* `createFollowersController` wraps subscribe/unsubscribe with the local
|
|
21
|
+
* "this browser already subscribed" hint. The hint is a convenience for hiding
|
|
22
|
+
* a footer form without a round trip — it is NOT authority. `me()` is.
|
|
23
|
+
*
|
|
24
|
+
* @module
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import {
|
|
28
|
+
buildAuthHref,
|
|
29
|
+
clearLocalFollow,
|
|
30
|
+
DEFAULT_AUTH_BASE_PATH,
|
|
31
|
+
followerStoreKey,
|
|
32
|
+
type LocalFollow,
|
|
33
|
+
readLocalFollow,
|
|
34
|
+
writeLocalFollow,
|
|
35
|
+
} from "../auth-links.js";
|
|
36
|
+
import type { TenantAuthMeResponse } from "../contracts.js";
|
|
37
|
+
|
|
38
|
+
// ─── Session ─────────────────────────────────────────────────────────────────
|
|
39
|
+
|
|
40
|
+
export type UserStatus = "loading" | "signed-in" | "signed-out";
|
|
41
|
+
|
|
42
|
+
export type UserSnapshot = {
|
|
43
|
+
status: UserStatus;
|
|
44
|
+
user: TenantAuthMeResponse | null;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type UserController = {
|
|
48
|
+
snapshot(): UserSnapshot;
|
|
49
|
+
subscribe(callback: (snapshot: UserSnapshot) => void): () => void;
|
|
50
|
+
/** Read `/me`. Called once by `start()`; call again to re-check. */
|
|
51
|
+
refresh(): Promise<UserSnapshot>;
|
|
52
|
+
/** Kick off the first read. Bindings call this on mount. */
|
|
53
|
+
start(): void;
|
|
54
|
+
destroy(): void;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export type CreateUserControllerOptions = {
|
|
58
|
+
/** Where `createAuthHandler` is mounted. Defaults to `/api/biab-auth`. */
|
|
59
|
+
basePath?: string;
|
|
60
|
+
/** Injectable for tests; defaults to global `fetch`. */
|
|
61
|
+
fetchImpl?: typeof fetch;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export function createUserController(
|
|
65
|
+
options: CreateUserControllerOptions = {},
|
|
66
|
+
): UserController {
|
|
67
|
+
const basePath = (options.basePath ?? DEFAULT_AUTH_BASE_PATH).replace(
|
|
68
|
+
/\/$/,
|
|
69
|
+
"",
|
|
70
|
+
);
|
|
71
|
+
const doFetch = options.fetchImpl ?? globalThis.fetch;
|
|
72
|
+
|
|
73
|
+
let destroyed = false;
|
|
74
|
+
const subscribers = new Set<(s: UserSnapshot) => void>();
|
|
75
|
+
let state: UserSnapshot = { status: "loading", user: null };
|
|
76
|
+
|
|
77
|
+
function notify(): void {
|
|
78
|
+
if (destroyed) return;
|
|
79
|
+
for (const cb of subscribers) cb(state);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function refresh(): Promise<UserSnapshot> {
|
|
83
|
+
if (destroyed) return state;
|
|
84
|
+
try {
|
|
85
|
+
const res = await doFetch(`${basePath}/me`, { credentials: "include" });
|
|
86
|
+
const body = res.ok ? ((await res.json()) as TenantAuthMeResponse) : null;
|
|
87
|
+
if (destroyed) return state;
|
|
88
|
+
state = body
|
|
89
|
+
? { status: "signed-in", user: body }
|
|
90
|
+
: { status: "signed-out", user: null };
|
|
91
|
+
} catch {
|
|
92
|
+
// A network failure is indistinguishable from "not signed in" from the
|
|
93
|
+
// page's point of view, and treating it as an error would leave every
|
|
94
|
+
// consumer writing the same fallback.
|
|
95
|
+
if (!destroyed) state = { status: "signed-out", user: null };
|
|
96
|
+
}
|
|
97
|
+
notify();
|
|
98
|
+
return state;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
snapshot: () => state,
|
|
103
|
+
subscribe(callback) {
|
|
104
|
+
subscribers.add(callback);
|
|
105
|
+
return () => {
|
|
106
|
+
subscribers.delete(callback);
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
refresh,
|
|
110
|
+
start() {
|
|
111
|
+
void refresh();
|
|
112
|
+
},
|
|
113
|
+
destroy() {
|
|
114
|
+
destroyed = true;
|
|
115
|
+
subscribers.clear();
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export type ProgrammaticAuthOptions = {
|
|
121
|
+
/** Where to send the customer afterwards. */
|
|
122
|
+
returnTo?: string;
|
|
123
|
+
/** Pre-fill the email on the hosted page (sign-in / sign-up only). */
|
|
124
|
+
loginHint?: string;
|
|
125
|
+
/** Override the auth-handler basePath. */
|
|
126
|
+
basePath?: string;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/** Href for the auth handler's sign-in route — render it in your own link. */
|
|
130
|
+
export function signInHref(options: ProgrammaticAuthOptions = {}): string {
|
|
131
|
+
return buildAuthHref("sign-in", options);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Href for the auth handler's sign-up route. */
|
|
135
|
+
export function signUpHref(options: ProgrammaticAuthOptions = {}): string {
|
|
136
|
+
return buildAuthHref("sign-up", options);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Href for the auth handler's sign-out route. */
|
|
140
|
+
export function signOutHref(options: { basePath?: string } = {}): string {
|
|
141
|
+
return buildAuthHref("sign-out", options);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Navigate to sign-in. No-ops outside a browser. */
|
|
145
|
+
export function signIn(options: ProgrammaticAuthOptions = {}): void {
|
|
146
|
+
if (typeof window === "undefined") return;
|
|
147
|
+
window.location.assign(signInHref(options));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Navigate to sign-up. No-ops outside a browser. */
|
|
151
|
+
export function signUp(options: ProgrammaticAuthOptions = {}): void {
|
|
152
|
+
if (typeof window === "undefined") return;
|
|
153
|
+
window.location.assign(signUpHref(options));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Navigate to sign-out. No-ops outside a browser. */
|
|
157
|
+
export function signOut(options: { basePath?: string } = {}): void {
|
|
158
|
+
if (typeof window === "undefined") return;
|
|
159
|
+
window.location.assign(signOutHref(options));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ─── Followers ───────────────────────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
export type FollowersCoreClient = {
|
|
165
|
+
followers: {
|
|
166
|
+
join(input: {
|
|
167
|
+
email: string;
|
|
168
|
+
name?: string;
|
|
169
|
+
source?: string;
|
|
170
|
+
}): Promise<unknown>;
|
|
171
|
+
leave(input: { email: string }): Promise<unknown>;
|
|
172
|
+
me(input: { email: string }): Promise<unknown>;
|
|
173
|
+
edit(input: {
|
|
174
|
+
email: string;
|
|
175
|
+
patch: { name?: string; source?: string };
|
|
176
|
+
}): Promise<unknown>;
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
export type FollowersSnapshot = {
|
|
181
|
+
/** This browser already subscribed. A hint for hiding a form, not authority. */
|
|
182
|
+
subscribedLocally: boolean;
|
|
183
|
+
/** The email this browser subscribed with, or `null`. */
|
|
184
|
+
localEmail: string | null;
|
|
185
|
+
isPending: boolean;
|
|
186
|
+
error: Error | null;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export type FollowersController = {
|
|
190
|
+
snapshot(): FollowersSnapshot;
|
|
191
|
+
subscribe(callback: (snapshot: FollowersSnapshot) => void): () => void;
|
|
192
|
+
join(input: {
|
|
193
|
+
email: string;
|
|
194
|
+
name?: string;
|
|
195
|
+
source?: string;
|
|
196
|
+
}): Promise<unknown>;
|
|
197
|
+
leave(email: string): Promise<unknown>;
|
|
198
|
+
/** Authoritative status for an email — unlike `subscribedLocally`. */
|
|
199
|
+
me(email: string): Promise<unknown>;
|
|
200
|
+
edit(
|
|
201
|
+
email: string,
|
|
202
|
+
patch: { name?: string; source?: string },
|
|
203
|
+
): Promise<unknown>;
|
|
204
|
+
destroy(): void;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
export type CreateFollowersControllerOptions = {
|
|
208
|
+
client: FollowersCoreClient;
|
|
209
|
+
/** Site id — namespaces the local hint so two sites don't share it. */
|
|
210
|
+
siteId: string;
|
|
211
|
+
onError?: (error: Error) => void;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export function createFollowersController(
|
|
215
|
+
options: CreateFollowersControllerOptions,
|
|
216
|
+
): FollowersController {
|
|
217
|
+
const { client, siteId, onError } = options;
|
|
218
|
+
const storeKey = followerStoreKey(siteId);
|
|
219
|
+
|
|
220
|
+
let destroyed = false;
|
|
221
|
+
const subscribers = new Set<(s: FollowersSnapshot) => void>();
|
|
222
|
+
let local: LocalFollow | null = readLocalFollow(storeKey);
|
|
223
|
+
let isPending = false;
|
|
224
|
+
let error: Error | null = null;
|
|
225
|
+
let cached: FollowersSnapshot | null = null;
|
|
226
|
+
|
|
227
|
+
function snapshot(): FollowersSnapshot {
|
|
228
|
+
if (!cached) {
|
|
229
|
+
cached = {
|
|
230
|
+
subscribedLocally: local !== null,
|
|
231
|
+
localEmail: local?.email ?? null,
|
|
232
|
+
isPending,
|
|
233
|
+
error,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
return cached;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function notify(): void {
|
|
240
|
+
if (destroyed) return;
|
|
241
|
+
cached = null;
|
|
242
|
+
const next = snapshot();
|
|
243
|
+
for (const cb of subscribers) cb(next);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function run<T>(work: () => Promise<T>, fallback: string): Promise<T> {
|
|
247
|
+
isPending = true;
|
|
248
|
+
error = null;
|
|
249
|
+
notify();
|
|
250
|
+
try {
|
|
251
|
+
return await work();
|
|
252
|
+
} catch (cause) {
|
|
253
|
+
const err = cause instanceof Error ? cause : new Error(fallback);
|
|
254
|
+
error = err;
|
|
255
|
+
onError?.(err);
|
|
256
|
+
throw err;
|
|
257
|
+
} finally {
|
|
258
|
+
isPending = false;
|
|
259
|
+
notify();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
snapshot,
|
|
265
|
+
subscribe(callback) {
|
|
266
|
+
subscribers.add(callback);
|
|
267
|
+
return () => {
|
|
268
|
+
subscribers.delete(callback);
|
|
269
|
+
};
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
join(input) {
|
|
273
|
+
return run(async () => {
|
|
274
|
+
const res = await client.followers.join(input);
|
|
275
|
+
local = { email: input.email, at: Date.now() };
|
|
276
|
+
writeLocalFollow(storeKey, local);
|
|
277
|
+
return res;
|
|
278
|
+
}, "Could not subscribe.");
|
|
279
|
+
},
|
|
280
|
+
|
|
281
|
+
leave(email) {
|
|
282
|
+
return run(async () => {
|
|
283
|
+
const res = await client.followers.leave({ email });
|
|
284
|
+
clearLocalFollow(storeKey);
|
|
285
|
+
local = null;
|
|
286
|
+
return res;
|
|
287
|
+
}, "Could not unsubscribe.");
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
me(email) {
|
|
291
|
+
return run(
|
|
292
|
+
() => client.followers.me({ email }),
|
|
293
|
+
"Could not read status.",
|
|
294
|
+
);
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
edit(email, patch) {
|
|
298
|
+
return run(
|
|
299
|
+
() => client.followers.edit({ email, patch }),
|
|
300
|
+
"Could not update the subscription.",
|
|
301
|
+
);
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
destroy() {
|
|
305
|
+
destroyed = true;
|
|
306
|
+
subscribers.clear();
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
}
|
package/src/account.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@businessdash/sdk/account` — the framework-agnostic customer session and
|
|
3
|
+
* followers cores.
|
|
4
|
+
*
|
|
5
|
+
* Source-shipped bindings import through this public subpath, as they do for
|
|
6
|
+
* `forms`, `store`, `chat` and `blog`.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export * from "./account-core/index.js";
|