@farthershore/farthershore-js 0.9.0 → 0.11.0
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/CHANGELOG.md +56 -0
- package/README.md +280 -187
- package/dist/bootstrap.js +3 -3
- package/dist/bootstrap.js.map +1 -1
- package/dist/client.d.ts +79 -69
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +31 -79
- package/dist/client.js.map +1 -1
- package/dist/components/app.d.ts +7 -6
- package/dist/components/app.d.ts.map +1 -1
- package/dist/components/app.js +22 -9
- package/dist/components/app.js.map +1 -1
- package/dist/components/auth-guard.d.ts +44 -12
- package/dist/components/auth-guard.d.ts.map +1 -1
- package/dist/components/auth-guard.js +28 -12
- package/dist/components/auth-guard.js.map +1 -1
- package/dist/components/auth.d.ts +18 -0
- package/dist/components/auth.d.ts.map +1 -1
- package/dist/components/auth.js +167 -8
- package/dist/components/auth.js.map +1 -1
- package/dist/components/bill-estimator.js +1 -1
- package/dist/components/bill-estimator.js.map +1 -1
- package/dist/components/billing.d.ts +9 -1
- package/dist/components/billing.d.ts.map +1 -1
- package/dist/components/billing.js +3 -3
- package/dist/components/billing.js.map +1 -1
- package/dist/components/cancel-subscription.js +2 -2
- package/dist/components/cancel-subscription.js.map +1 -1
- package/dist/components/capability-usage-card.js +2 -2
- package/dist/components/capability-usage-card.js.map +1 -1
- package/dist/components/chrome.d.ts +3 -2
- package/dist/components/chrome.d.ts.map +1 -1
- package/dist/components/chrome.js +7 -3
- package/dist/components/chrome.js.map +1 -1
- package/dist/components/credit.js +2 -2
- package/dist/components/credit.js.map +1 -1
- package/dist/components/docs.css +7 -3
- package/dist/components/index.d.ts +3 -3
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +6 -2
- package/dist/components/index.js.map +1 -1
- package/dist/components/keys.js +2 -2
- package/dist/components/keys.js.map +1 -1
- package/dist/components/limit-boundary.d.ts +1 -1
- package/dist/components/limit-boundary.d.ts.map +1 -1
- package/dist/components/limit-boundary.js +1 -1
- package/dist/components/limit-boundary.js.map +1 -1
- package/dist/components/limit-notice.js +1 -1
- package/dist/components/limit-notice.js.map +1 -1
- package/dist/components/onboarding-view.js +5 -5
- package/dist/components/onboarding-view.js.map +1 -1
- package/dist/components/org-switcher.js +1 -1
- package/dist/components/org-switcher.js.map +1 -1
- package/dist/components/plans-table.d.ts +11 -1
- package/dist/components/plans-table.d.ts.map +1 -1
- package/dist/components/plans-table.js +14 -5
- package/dist/components/plans-table.js.map +1 -1
- package/dist/components/product-docs/fetch-product-docs.js +1 -1
- package/dist/components/product-docs/fetch-product-docs.js.map +1 -1
- package/dist/components/product-docs/product-docs.js +1 -1
- package/dist/components/product-docs/product-docs.js.map +1 -1
- package/dist/components/resources-panel.js +3 -3
- package/dist/components/resources-panel.js.map +1 -1
- package/dist/components/root.d.ts +43 -6
- package/dist/components/root.d.ts.map +1 -1
- package/dist/components/root.js +54 -15
- package/dist/components/root.js.map +1 -1
- package/dist/components/spend-cap-control.js +2 -2
- package/dist/components/spend-cap-control.js.map +1 -1
- package/dist/components/styles.css +11 -5
- package/dist/components/team-panel.js +2 -2
- package/dist/components/team-panel.js.map +1 -1
- package/dist/components/theme.d.ts +5 -2
- package/dist/components/theme.d.ts.map +1 -1
- package/dist/components/theme.js +7 -1
- package/dist/components/theme.js.map +1 -1
- package/dist/components/top-up-prompt.d.ts +1 -1
- package/dist/components/top-up-prompt.d.ts.map +1 -1
- package/dist/components/upgrade-prompt.d.ts +1 -1
- package/dist/components/upgrade-prompt.d.ts.map +1 -1
- package/dist/components/upgrade-prompt.js +1 -1
- package/dist/components/upgrade-prompt.js.map +1 -1
- package/dist/components/usage.d.ts +5 -1
- package/dist/components/usage.d.ts.map +1 -1
- package/dist/components/usage.js +20 -4
- package/dist/components/usage.js.map +1 -1
- package/dist/config.d.ts +49 -11
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +48 -13
- package/dist/config.js.map +1 -1
- package/dist/deny-codes.js +2 -2
- package/dist/deny-codes.js.map +1 -1
- package/dist/{errors.d.ts → errors/index.d.ts} +36 -3
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/{errors.js → errors/index.js} +51 -3
- package/dist/errors/index.js.map +1 -0
- package/dist/fetch.d.ts +62 -0
- package/dist/fetch.d.ts.map +1 -0
- package/dist/fetch.js +195 -0
- package/dist/fetch.js.map +1 -0
- package/dist/format/index.d.ts +2 -0
- package/dist/format/index.d.ts.map +1 -0
- package/dist/format/index.js +19 -0
- package/dist/format/index.js.map +1 -0
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.d.ts.map +1 -1
- package/dist/generated/version.js +2 -2
- package/dist/generated/version.js.map +1 -1
- package/dist/http.js +8 -8
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +21 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -14
- package/dist/index.js.map +1 -1
- package/dist/permissions.d.ts +16 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +29 -0
- package/dist/permissions.js.map +1 -0
- package/dist/react/hooks.d.ts +5 -1
- package/dist/react/hooks.d.ts.map +1 -1
- package/dist/react/hooks.js +81 -69
- package/dist/react/hooks.js.map +1 -1
- package/dist/react/index.d.ts +7 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +13 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/organization-context.js +1 -1
- package/dist/react/organization-context.js.map +1 -1
- package/dist/react/query-adapter.d.ts +63 -0
- package/dist/react/query-adapter.d.ts.map +1 -0
- package/dist/react/query-adapter.js +117 -0
- package/dist/react/query-adapter.js.map +1 -0
- package/dist/react/scope.d.ts +41 -0
- package/dist/react/scope.d.ts.map +1 -0
- package/dist/react/scope.js +35 -0
- package/dist/react/scope.js.map +1 -0
- package/dist/react/use-async.d.ts +30 -7
- package/dist/react/use-async.d.ts.map +1 -1
- package/dist/react/use-async.js +23 -10
- package/dist/react/use-async.js.map +1 -1
- package/dist/react/use-limit-status.d.ts +1 -1
- package/dist/react/use-limit-status.d.ts.map +1 -1
- package/dist/react/use-limits.d.ts +1 -1
- package/dist/react/use-limits.d.ts.map +1 -1
- package/dist/react/use-limits.js +2 -2
- package/dist/react/use-limits.js.map +1 -1
- package/dist/react/use-upgrade.d.ts +1 -1
- package/dist/react/use-upgrade.d.ts.map +1 -1
- package/dist/react/use-upgrade.js +1 -1
- package/dist/react/use-upgrade.js.map +1 -1
- package/dist/resources/_shared.d.ts +2 -2
- package/dist/resources/_shared.d.ts.map +1 -1
- package/dist/resources/_shared.js +7 -7
- package/dist/resources/_shared.js.map +1 -1
- package/dist/resources/account.d.ts +64 -1
- package/dist/resources/account.d.ts.map +1 -1
- package/dist/resources/account.js +113 -18
- package/dist/resources/account.js.map +1 -1
- package/dist/resources/api.js +1 -1
- package/dist/resources/api.js.map +1 -1
- package/dist/resources/auth.js +4 -4
- package/dist/resources/auth.js.map +1 -1
- package/dist/resources/billing.d.ts.map +1 -1
- package/dist/resources/billing.js +22 -21
- package/dist/resources/billing.js.map +1 -1
- package/dist/resources/entitlements.js +5 -5
- package/dist/resources/entitlements.js.map +1 -1
- package/dist/resources/keys.js +10 -10
- package/dist/resources/keys.js.map +1 -1
- package/dist/resources/plans.d.ts +1 -1
- package/dist/resources/plans.d.ts.map +1 -1
- package/dist/resources/plans.js +19 -7
- package/dist/resources/plans.js.map +1 -1
- package/dist/resources/resources.d.ts.map +1 -1
- package/dist/resources/resources.js +4 -4
- package/dist/resources/resources.js.map +1 -1
- package/dist/resources/usage.js +4 -4
- package/dist/resources/usage.js.map +1 -1
- package/dist/retry-throttle.d.ts +1 -1
- package/dist/retry-throttle.d.ts.map +1 -1
- package/dist/retry-throttle.js +1 -1
- package/dist/retry-throttle.js.map +1 -1
- package/dist/test-utils/error-builders.d.ts +29 -0
- package/dist/test-utils/error-builders.d.ts.map +1 -0
- package/dist/test-utils/error-builders.js +36 -0
- package/dist/test-utils/error-builders.js.map +1 -0
- package/dist/test-utils/index.d.ts +4 -0
- package/dist/test-utils/index.d.ts.map +1 -0
- package/dist/test-utils/index.js +15 -0
- package/dist/test-utils/index.js.map +1 -0
- package/dist/test-utils/mock-client.d.ts +37 -0
- package/dist/test-utils/mock-client.d.ts.map +1 -0
- package/dist/test-utils/mock-client.js +366 -0
- package/dist/test-utils/mock-client.js.map +1 -0
- package/dist/test-utils/test-provider.d.ts +25 -0
- package/dist/test-utils/test-provider.d.ts.map +1 -0
- package/dist/test-utils/test-provider.js +22 -0
- package/dist/test-utils/test-provider.js.map +1 -0
- package/dist/top-up.js +1 -1
- package/dist/top-up.js.map +1 -1
- package/dist/types.d.ts +53 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/use-fetch.d.ts +18 -0
- package/dist/use-fetch.d.ts.map +1 -0
- package/dist/use-fetch.js +51 -0
- package/dist/use-fetch.js.map +1 -0
- package/dist/variables-registry.d.ts +56 -0
- package/dist/variables-registry.d.ts.map +1 -0
- package/dist/variables-registry.js +172 -0
- package/dist/variables-registry.js.map +1 -0
- package/dist/vars.d.ts +9 -0
- package/dist/vars.d.ts.map +1 -0
- package/dist/vars.js +29 -0
- package/dist/vars.js.map +1 -0
- package/package.json +12 -2
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,62 @@
|
|
|
3
3
|
All notable changes to `@farthershore/farthershore-js` are documented here.
|
|
4
4
|
This project adheres to Semantic Versioning (pre-1.0: minors may break).
|
|
5
5
|
|
|
6
|
+
## [0.10.0] - 2026-07-02
|
|
7
|
+
|
|
8
|
+
Frontend SDK ergonomics redesign — the headless client + hooks are now the
|
|
9
|
+
default surface and the styled portal is an opt-in layer.
|
|
10
|
+
|
|
11
|
+
### Changed (BREAKING)
|
|
12
|
+
|
|
13
|
+
- **`productId` → `businessId`** across the public surface (config,
|
|
14
|
+
`ClientContext`, resources, hooks, params). No `productId` remains in the
|
|
15
|
+
public API.
|
|
16
|
+
- **Ecosystem hook shape:** every data hook returns
|
|
17
|
+
`{ data, error, isLoading, isError, isSuccess, refetch, queryKey }`. The bare
|
|
18
|
+
`loading` field and `refresh` alias are removed (use `isLoading` / `refetch`).
|
|
19
|
+
- **`/errors` subpath:** the full error taxonomy + parse/predicate helpers moved
|
|
20
|
+
to `@farthershore/farthershore-js/errors`. The root re-exports only
|
|
21
|
+
`FartherShoreError`, `FartherShoreApiError`, `LimitExceededError`,
|
|
22
|
+
`FartherShoreRateLimitedError`, and `FartherShoreConfigError`.
|
|
23
|
+
- **`format` namespace:** the catalog display/derivation helpers are grouped
|
|
24
|
+
under `format` (`import { format } from "@farthershore/farthershore-js"`);
|
|
25
|
+
they are no longer flat root exports.
|
|
26
|
+
- Removed the SSR/`createServerClient` surface (platform is browser-only).
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **Zero-config client:** `createFartherShoreClient()` with no args on-platform
|
|
31
|
+
(lazy `window.__FS_CONFIG__`, `businessId` discovered from the portal host);
|
|
32
|
+
manual `{ coreUrl, portalHost, businessId, getToken }` is a documented
|
|
33
|
+
dev/test escape hatch.
|
|
34
|
+
- **`fs.fetch(url, opts)`** drop-in secure fetch with a client-side variable
|
|
35
|
+
registry + `PROVIDER_CATALOG` host inference.
|
|
36
|
+
- **`/react`:** prop-free `<FartherShoreProvider>`; `useReadScope()`;
|
|
37
|
+
`useFetch()`; a TanStack-Query / SWR adapter (`fsQueryOptions`,
|
|
38
|
+
`createFsFetcher`) with no runtime dependency on either library.
|
|
39
|
+
- **Composable components:** data components render under a bare
|
|
40
|
+
`<FartherShoreProvider>` (no forced `FartherShoreRoot`);
|
|
41
|
+
`PlansTable`/`UsageCard` gain `renderRow`, `BillingSummary` gains
|
|
42
|
+
`slots.actions`; themeable z-index via `--fs-*-z` CSS variables.
|
|
43
|
+
- **`FartherShoreRoot`** is now a composition of `FsBootGate` /
|
|
44
|
+
`FsAuthProvider` / `FsThemeProvider` with `skipAuth` / `skipTheme` /
|
|
45
|
+
`skipBootGate` flags.
|
|
46
|
+
- **`/test-utils` subpath:** `createMockFartherShoreClient`,
|
|
47
|
+
`<FartherShoreTestProvider>`, and typed error builders
|
|
48
|
+
(`mockLimitExceeded` / `mockRateLimited` / `mockApiError`).
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- `<OrgSwitcher>` read a non-existent `organizationName` field and showed raw
|
|
53
|
+
organization ids; it now reads the `name` field the platform actually sends.
|
|
54
|
+
- `fs.fetch` variable resolution no longer silently hands a lone host-less
|
|
55
|
+
variable to a call targeting a _different_ recognized provider host (e.g. a
|
|
56
|
+
sole `STRIPE_SECRET_KEY` against `api.openai.com`) — it throws
|
|
57
|
+
`FartherShoreConfigError` on that ambiguity, as documented.
|
|
58
|
+
- `sideEffects` now allowlists `*.css` (was `false`), so webpack-based
|
|
59
|
+
consumers no longer tree-shake away the `./components/styles.css` /
|
|
60
|
+
`./components/docs.css` side-effect imports in production builds.
|
|
61
|
+
|
|
6
62
|
## [0.9.0] - 2026-06-29
|
|
7
63
|
|
|
8
64
|
### Changed (BREAKING)
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
The **Farther Shore Frontend SDK** — the browser + React integration layer for
|
|
4
4
|
your product's subscriber portal.
|
|
5
5
|
|
|
6
|
-
> **Status: `0.
|
|
6
|
+
> **Status: `0.10.0`.** Pre-1.0 (`0.x`): a minor bump (e.g. `0.9.x` → `0.10.0`)
|
|
7
7
|
> may include breaking changes, so a caret range is unsafe — **pin this package
|
|
8
8
|
> exactly** (`0.9.0`) or use a patch-only tilde (`~0.9.0`). Changes are recorded
|
|
9
9
|
> in [`CHANGELOG.md`](./CHANGELOG.md).
|
|
@@ -26,143 +26,28 @@ goes (Core for platform concerns like auth, plans, usage, and billing; the
|
|
|
26
26
|
Gateway for your product's own features), **how** it's authenticated, and which
|
|
27
27
|
host/environment scoping headers to attach.
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
This guide walks through the five on-ramps for integrating the SDK into a real
|
|
30
|
+
app: the zero-config happy path, bringing your own auth, bringing your own
|
|
31
|
+
design system, bringing your own data layer, and writing org-scoped custom
|
|
32
|
+
hooks.
|
|
32
33
|
|
|
33
|
-
##
|
|
34
|
+
## 1. Zero-config happy path
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// field — `portalHost` defaults to `window.location.host`.
|
|
40
|
-
const fs = createFartherShoreClient({
|
|
41
|
-
coreUrl: "https://core.farthershore.com",
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// 2. Discover the business / environment / plans for this host
|
|
45
|
-
// (memoized; safe to re-call).
|
|
46
|
-
const { business, plans } = await fs.bootstrap();
|
|
47
|
-
|
|
48
|
-
// 3. Authenticate. In a preview/test environment, exchange a persona access key
|
|
49
|
-
// for a session. (Clerk environments instead pass `getToken` in the config,
|
|
50
|
-
// or call `fs.auth.setToken(token)`.)
|
|
51
|
-
await fs.auth.signIn({ apiKey: "fsk_test_…" });
|
|
52
|
-
|
|
53
|
-
// 4. Read platform state through the typed resources (→ Core).
|
|
54
|
-
const keys = await fs.keys.list(); // ApiKey[]
|
|
55
|
-
const usage = await fs.usage.snapshot(); // { summary, events, billingBasis }
|
|
56
|
-
|
|
57
|
-
// 5. Call one of YOUR product features (→ Gateway). Set the consumer API key
|
|
58
|
-
// once, then express intent by feature name + path — no Gateway URL in app
|
|
59
|
-
// code.
|
|
60
|
-
fs.setApiKey("fsk_live_…");
|
|
61
|
-
const forecast = await fs.feature("weather").json("/forecast?city=NYC");
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Surface
|
|
65
|
-
|
|
66
|
-
| Namespace | Routes to | Methods |
|
|
67
|
-
| --------------------------------------------------------- | --------------------- | ----------------------------------------------------------------------- |
|
|
68
|
-
| `fs.bootstrap()` | Core (public resolve) | discover business / environment / plans / branding |
|
|
69
|
-
| `fs.business` | (bootstrap) | `get()` |
|
|
70
|
-
| `fs.auth` | Core | `getSession()`, `signIn({apiKey})` (persona), `signOut()`, `setToken()` |
|
|
71
|
-
| `fs.keys` | Core | `list()`, `create()`, `revoke()`, `rotate()` |
|
|
72
|
-
| `fs.usage` | Core | `summary()`, `events()`, `snapshot()` |
|
|
73
|
-
| `fs.billing` | Core | `subscription()`, `openBillingPortal()`, `creditBalance()` |
|
|
74
|
-
| `fs.plans` | Core / (bootstrap) | `list()`, `subscribe()` |
|
|
75
|
-
| `fs.entitlements` / `fs.features` | Core | plan entitlements + capability/feature gating |
|
|
76
|
-
| `fs.me` / `fs.organizations` / `fs.team` / `fs.auditLogs` | Core | subscriber, org, team, and audit-log reads |
|
|
77
|
-
| `fs.feature(name)` / `fs.invoke(path)` | **Gateway** | `fetch(path)`, `json(path)` |
|
|
78
|
-
|
|
79
|
-
The package also ships typed domain models (`Business`, `Plan`, `Subscription`,
|
|
80
|
-
`UsageSnapshot`, `ApiKey`, …), the gateway error/deny taxonomy
|
|
81
|
-
(`FartherShoreApiError`, `LimitExceededError`, `FS_DENY_CODES`,
|
|
82
|
-
`retryWhileThrottled`, …), and pure display helpers (`formatPlanPrice`,
|
|
83
|
-
`estimateBill`, `usageToCsv`, …) so every frontend renders the catalog and usage
|
|
84
|
-
identically.
|
|
85
|
-
|
|
86
|
-
## Auth
|
|
87
|
-
|
|
88
|
-
- **Core** calls use the subscriber's **session token** as
|
|
89
|
-
`Authorization: Bearer`. The host app owns the session:
|
|
90
|
-
- _Clerk environments:_ pass `getToken` (from the Clerk browser SDK) in the
|
|
91
|
-
config, or call `fs.auth.setToken(token)`.
|
|
92
|
-
- _Persona / preview environments:_
|
|
93
|
-
`fs.auth.signIn({ apiKey: "fsk_test_…" })` — the SDK exchanges the key for a
|
|
94
|
-
session and manages the token itself.
|
|
95
|
-
- **Gateway** (feature) calls use the consumer **API key** (`fsk_…`):
|
|
96
|
-
`fs.setApiKey(key)` (or `fs.feature(name).fetch(path, { apiKey })`). The
|
|
97
|
-
gateway host is discovered at bootstrap (the business's `gatewayHost`).
|
|
98
|
-
|
|
99
|
-
## Configuration
|
|
36
|
+
On a portal served by the Farther Shore edge, the client needs **no
|
|
37
|
+
arguments at all**. It reads `window.__FS_CONFIG__` (injected by the edge)
|
|
38
|
+
lazily — the first time a request actually needs it — and discovers the
|
|
39
|
+
`businessId` from the portal host.
|
|
100
40
|
|
|
101
41
|
```ts
|
|
102
|
-
createFartherShoreClient
|
|
103
|
-
coreUrl, // platform Core base URL — optional on platform-served portals
|
|
104
|
-
portalHost, // defaults to window.location.host
|
|
105
|
-
productId, // optional — bootstrap() discovers it
|
|
106
|
-
environmentId, // ephemeral/preview env scoping
|
|
107
|
-
organizationId, // org-owned subscriptions
|
|
108
|
-
gatewayUrl, // override (else derived from the business gatewayHost)
|
|
109
|
-
apiKey, // consumer key for Gateway calls
|
|
110
|
-
getToken, // () => session bearer (Clerk) | null
|
|
111
|
-
fetch, // injectable (tests / SSR)
|
|
112
|
-
});
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Portals served through the Farther Shore edge need **no config at all** —
|
|
116
|
-
`createFartherShoreClient()` works on its own: the edge injects
|
|
117
|
-
`window.__FS_CONFIG__` (the environment's `coreUrl` plus the Clerk connection)
|
|
118
|
-
into the served HTML, and the SDK falls back to it. Explicit config always wins,
|
|
119
|
-
and everywhere else (local dev, SSR, self-hosting) `coreUrl` is required.
|
|
120
|
-
|
|
121
|
-
On Clerk **satellite** portals (the portal is on a different domain than the
|
|
122
|
-
platform's sign-in domain), the managed auth layer also owns the cross-domain
|
|
123
|
-
session handshake: public visits never redirect, and a `#fs-sso` URL fragment
|
|
124
|
-
(appended by trusted surfaces like the dashboard's "Open portal" links) triggers
|
|
125
|
-
an immediate redirect through the primary domain that lands back signed in.
|
|
126
|
-
|
|
127
|
-
### SSR / server usage
|
|
128
|
-
|
|
129
|
-
On a server there is no `window`/`location` to infer the portal host from and no
|
|
130
|
-
ambient browser session — so use `createServerClient`, an explicit alias for
|
|
131
|
-
`createFartherShoreClient`. Pass `portalHost` and `fetch` instead of relying on
|
|
132
|
-
globals, and resolve the per-request session via `getToken`.
|
|
133
|
-
|
|
134
|
-
```ts
|
|
135
|
-
import { createServerClient } from "@farthershore/farthershore-js";
|
|
136
|
-
|
|
137
|
-
const fs = createServerClient({
|
|
138
|
-
coreUrl: process.env.FS_CORE_URL!,
|
|
139
|
-
portalHost: "weather.farthershore.com", // no window.location on the server
|
|
140
|
-
getToken: () => sessionTokenForThisRequest, // per-request bearer
|
|
141
|
-
fetch, // Node global, or an injected impl
|
|
142
|
-
});
|
|
42
|
+
import { createFartherShoreClient } from "@farthershore/farthershore-js";
|
|
143
43
|
|
|
144
|
-
const
|
|
44
|
+
const fs = createFartherShoreClient();
|
|
145
45
|
```
|
|
146
46
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
The hooks live in a **subpath** of the same package — `react` is an _optional_
|
|
150
|
-
peer dependency, so the core stays framework-agnostic and only React apps pull it
|
|
151
|
-
in (no second package to version).
|
|
47
|
+
Wrap your tree in the provider:
|
|
152
48
|
|
|
153
49
|
```tsx
|
|
154
|
-
import {
|
|
155
|
-
import {
|
|
156
|
-
FartherShoreProvider,
|
|
157
|
-
useBusiness,
|
|
158
|
-
useApiKeys,
|
|
159
|
-
useUsage,
|
|
160
|
-
useBilling,
|
|
161
|
-
useSession,
|
|
162
|
-
useFeature,
|
|
163
|
-
} from "@farthershore/farthershore-js/react";
|
|
164
|
-
|
|
165
|
-
const fs = createFartherShoreClient({ coreUrl: import.meta.env.VITE_CORE_URL });
|
|
50
|
+
import { FartherShoreProvider } from "@farthershore/farthershore-js/react";
|
|
166
51
|
|
|
167
52
|
function App() {
|
|
168
53
|
return (
|
|
@@ -171,25 +56,32 @@ function App() {
|
|
|
171
56
|
</FartherShoreProvider>
|
|
172
57
|
);
|
|
173
58
|
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Then read platform state through the hooks. Every read hook returns the same
|
|
62
|
+
ecosystem shape — `{ data, error, isLoading, isError, isSuccess, refetch,
|
|
63
|
+
queryKey }` — plus its mutations:
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { useApiKeys } from "@farthershore/farthershore-js/react";
|
|
174
67
|
|
|
175
68
|
function ApiKeys() {
|
|
176
|
-
const { data,
|
|
177
|
-
|
|
69
|
+
const { data, isLoading, isError, error, refetch } = useApiKeys();
|
|
70
|
+
if (isLoading) return <p>Loading…</p>;
|
|
71
|
+
if (isError) return <p>Failed to load keys: {error?.message}</p>;
|
|
72
|
+
return (
|
|
73
|
+
<ul>
|
|
74
|
+
{data?.map((k) => (
|
|
75
|
+
<li key={k.id}>{k.label}</li>
|
|
76
|
+
))}
|
|
77
|
+
</ul>
|
|
78
|
+
);
|
|
178
79
|
}
|
|
179
80
|
```
|
|
180
81
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
`openBillingPortal`), `usePlans`, `useEntitlements`, `useFeature(name)`, plus
|
|
185
|
-
team/org/audit/limit hooks and `useFartherShore()` for the raw client.
|
|
186
|
-
|
|
187
|
-
## Managed components
|
|
188
|
-
|
|
189
|
-
Every product ships with a generic managed portal by default. The component kit
|
|
190
|
-
is the same set of building blocks that portal is made of, available à la carte —
|
|
191
|
-
every component works with **zero props** under `<FartherShoreRoot>` (it reads
|
|
192
|
-
its data through the SDK; props are optional overrides).
|
|
82
|
+
Want a whole portal with almost no code? `<FartherShoreRoot>` is one wrapper —
|
|
83
|
+
provider + bootstrap gate + theme + managed auth — and the managed component
|
|
84
|
+
kit is self-fed under it:
|
|
193
85
|
|
|
194
86
|
```tsx
|
|
195
87
|
import {
|
|
@@ -209,59 +101,260 @@ import "@farthershore/farthershore-js/components/styles.css";
|
|
|
209
101
|
</FartherShoreRoot>;
|
|
210
102
|
```
|
|
211
103
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
104
|
+
**Escape hatch (dev/test only):** everywhere there's no injected
|
|
105
|
+
`window.__FS_CONFIG__` — local dev, self-hosting, tests — pass config
|
|
106
|
+
explicitly:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
const fs = createFartherShoreClient({
|
|
110
|
+
coreUrl: "http://localhost:4000", // dev/self-host only; injected on-platform
|
|
111
|
+
portalHost: "croncloud.example.com", // defaults to window.location.host
|
|
112
|
+
businessId: "biz_123", // usually omitted — bootstrap() discovers it
|
|
113
|
+
getToken: () => myAuthProvider.getToken(), // see "BYO auth" below
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Explicit config always wins over the injected channel. A request attempted
|
|
118
|
+
with no resolvable `coreUrl` throws an actionable `FartherShoreConfigError`.
|
|
119
|
+
|
|
120
|
+
## 2. BYO auth
|
|
121
|
+
|
|
122
|
+
Feed the client your own session token instead of the managed Clerk/persona
|
|
123
|
+
layer, in one of two ways:
|
|
124
|
+
|
|
125
|
+
- **At construction**, via `getToken` in the config:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
const fs = createFartherShoreClient({
|
|
129
|
+
getToken: () => myAuthProvider.getToken(), // () => string | null | Promise<...>
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
- **After construction**, via the client method (useful when the token
|
|
134
|
+
provider isn't ready yet at client-build time):
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
fs.setTokenProvider(() => myAuthProvider.getToken());
|
|
138
|
+
```
|
|
217
139
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
serves it instead of the default. Your product's _contract_ (plans, pricing,
|
|
221
|
-
routes, meters) lives in `business/` and is managed as code; the UI lives in
|
|
222
|
-
`frontend/`.
|
|
140
|
+
If you're using `<FartherShoreRoot>` but want to bring your own auth provider
|
|
141
|
+
entirely (skip the managed Clerk-satellite/persona layer), pass `skipAuth`:
|
|
223
142
|
|
|
224
|
-
|
|
143
|
+
```tsx
|
|
144
|
+
<FartherShoreRoot client={fs} skipAuth>
|
|
145
|
+
<MyOwnAuthProvider>
|
|
146
|
+
<Portal />
|
|
147
|
+
</MyOwnAuthProvider>
|
|
148
|
+
</FartherShoreRoot>
|
|
149
|
+
```
|
|
225
150
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
`<BusinessApiReference/>` renders an OpenAPI 3.x document as a docs-styled API
|
|
231
|
-
reference. `<CodeGroup>` is the multi-language fenced-code block used inside docs
|
|
232
|
-
pages.
|
|
151
|
+
## 3. BYO design system
|
|
152
|
+
|
|
153
|
+
The managed components work standalone under a **bare** `<FartherShoreProvider>`
|
|
154
|
+
— you don't need `<FartherShoreRoot>` to use them:
|
|
233
155
|
|
|
234
156
|
```tsx
|
|
157
|
+
import { FartherShoreProvider } from "@farthershore/farthershore-js/react";
|
|
235
158
|
import {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
159
|
+
PlansTable,
|
|
160
|
+
ApiKeysPanel,
|
|
161
|
+
UsageCard,
|
|
162
|
+
BillingSummary,
|
|
163
|
+
CreditBalance,
|
|
164
|
+
TeamPanel,
|
|
165
|
+
AuditLogTable,
|
|
166
|
+
RateLimitDisplay,
|
|
167
|
+
BillEstimator,
|
|
168
|
+
CapabilityUsageCard,
|
|
169
|
+
UpgradePrompt,
|
|
170
|
+
TopUpPrompt,
|
|
171
|
+
DocsLegal,
|
|
172
|
+
ResourcesPanel,
|
|
173
|
+
FeaturePanel,
|
|
239
174
|
} from "@farthershore/farthershore-js/components";
|
|
240
|
-
import "@farthershore/farthershore-js/components/
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
175
|
+
import "@farthershore/farthershore-js/components/styles.css";
|
|
176
|
+
|
|
177
|
+
<FartherShoreProvider client={fs}>
|
|
178
|
+
<PlansTable />
|
|
179
|
+
<ApiKeysPanel />
|
|
180
|
+
</FartherShoreProvider>;
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Recompose without forking. `PlansTable` takes `renderRow` for a fully custom
|
|
184
|
+
card, with context for the featured/pending/subscribe state:
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
<PlansTable
|
|
188
|
+
renderRow={(plan, { featured, pending, onSubscribe, index }) => (
|
|
189
|
+
<MyPlanCard
|
|
190
|
+
key={plan.id}
|
|
191
|
+
plan={plan}
|
|
192
|
+
highlighted={featured}
|
|
193
|
+
busy={pending}
|
|
194
|
+
onClick={onSubscribe}
|
|
195
|
+
rank={index}
|
|
196
|
+
/>
|
|
197
|
+
)}
|
|
198
|
+
/>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
`UsageCard` takes `renderRow` per metered dimension:
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
<UsageCard
|
|
205
|
+
renderRow={(row, index) => (
|
|
206
|
+
<MyUsageRow key={row.key} row={row} index={index} />
|
|
207
|
+
)}
|
|
208
|
+
/>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
`BillingSummary` takes named `slots` (e.g. to replace the actions area):
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
<BillingSummary slots={{ actions: <MyBillingActions /> }} />
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Every component also accepts a plain `className` on its root for CSS-based
|
|
218
|
+
restyling.
|
|
219
|
+
|
|
220
|
+
To bring your own theming under `<FartherShoreRoot>` instead of the managed
|
|
221
|
+
theme root, pass `skipTheme`:
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
<FartherShoreRoot client={fs} skipTheme>
|
|
225
|
+
<MyThemeProvider>
|
|
226
|
+
<Portal />
|
|
227
|
+
</MyThemeProvider>
|
|
228
|
+
</FartherShoreRoot>
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## 4. BYO data layer
|
|
232
|
+
|
|
233
|
+
Already run TanStack Query or SWR? The `/react` subpath ships a structural
|
|
234
|
+
adapter — no runtime dependency on either library, so it costs nothing unless
|
|
235
|
+
you import it.
|
|
236
|
+
|
|
237
|
+
**TanStack Query:**
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
import { useQuery } from "@tanstack/react-query";
|
|
241
|
+
import { fsQueryOptions } from "@farthershore/farthershore-js/react";
|
|
242
|
+
|
|
243
|
+
const q = fsQueryOptions(fs);
|
|
244
|
+
const { data } = useQuery(q.keys.list());
|
|
245
|
+
const { data: usage } = useQuery(q.usage.snapshot());
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**SWR:**
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
import useSWR from "swr";
|
|
252
|
+
import { createFsFetcher } from "@farthershore/farthershore-js/react";
|
|
253
|
+
|
|
254
|
+
const fetcher = createFsFetcher(fs);
|
|
255
|
+
const { data } = useSWR("https://api.example.com/v1/x", fetcher);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
`fsQueryOptions` covers the common reads (`keys`, `usage`, `billing`, `plans`,
|
|
259
|
+
`me`, `business`). For a product-declared resource beyond those, use the
|
|
260
|
+
generic escape hatch — both return a ready-to-use `{ queryKey, queryFn }`
|
|
261
|
+
object:
|
|
262
|
+
|
|
263
|
+
```tsx
|
|
264
|
+
const { data: widgets } = useQuery(q.resource("widgets"));
|
|
265
|
+
const { data: widget } = useQuery(q.resourceItem("widgets", widgetId));
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## 5. Org-scope custom hooks
|
|
269
|
+
|
|
270
|
+
Writing your own hook that reads org-scoped data (a product-declared resource,
|
|
271
|
+
say)? Use `useReadScope()` instead of `useFartherShore()` alone — it composes
|
|
272
|
+
the client with the **reactive** active-org id, so folding it into your query
|
|
273
|
+
key/dep array makes an org switch auto-refetch:
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
import { useReadScope } from "@farthershore/farthershore-js/react";
|
|
277
|
+
import { useAsync } from "@farthershore/farthershore-js/react";
|
|
278
|
+
|
|
279
|
+
function useMyResource() {
|
|
280
|
+
const { fs, businessId, organizationId } = useReadScope();
|
|
281
|
+
return useAsync(
|
|
282
|
+
(signal) => fs.resources("widgets").list({ signal }),
|
|
283
|
+
[fs, businessId, organizationId],
|
|
284
|
+
["widgets", businessId, organizationId],
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
`fs` alone is a stable reference and never reacts to an org switch on its
|
|
290
|
+
own — `businessId`/`organizationId` are what make the dep array and query key
|
|
291
|
+
scope-correct.
|
|
292
|
+
|
|
293
|
+
## Errors
|
|
294
|
+
|
|
295
|
+
Reads and mutations throw typed errors you can `catch` and branch on. The root
|
|
296
|
+
package keeps the five most-caught classes:
|
|
297
|
+
|
|
298
|
+
```ts
|
|
299
|
+
import {
|
|
300
|
+
FartherShoreError,
|
|
301
|
+
FartherShoreApiError,
|
|
302
|
+
LimitExceededError,
|
|
303
|
+
FartherShoreRateLimitedError,
|
|
304
|
+
FartherShoreConfigError,
|
|
305
|
+
} from "@farthershore/farthershore-js";
|
|
306
|
+
|
|
307
|
+
try {
|
|
308
|
+
await fs.keys.list();
|
|
309
|
+
} catch (err) {
|
|
310
|
+
if (err instanceof LimitExceededError) showUpgrade(err);
|
|
311
|
+
else if (err instanceof FartherShoreApiError && err.status === 401) {
|
|
312
|
+
// session expired — prompt re-auth
|
|
313
|
+
} else throw err;
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The full taxonomy — throttle subclasses (`ConcurrencyLimitError`,
|
|
318
|
+
`AdaptiveThrottleError`), deny-envelope parsers, `makeApiError`, secure-fetch
|
|
319
|
+
codes, and more — lives at the `@farthershore/farthershore-js/errors` subpath.
|
|
320
|
+
|
|
321
|
+
## Display helpers
|
|
322
|
+
|
|
323
|
+
Pure catalog/pricing/usage formatting helpers are grouped under the `format`
|
|
324
|
+
namespace, so every frontend renders money, dates, and quotas identically:
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
import { format } from "@farthershore/farthershore-js";
|
|
328
|
+
|
|
329
|
+
format.formatCents(1234); // "$12.34"
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Testing
|
|
333
|
+
|
|
334
|
+
`@farthershore/farthershore-js/test-utils` gives you a fully-typed mock client,
|
|
335
|
+
a provider wrapper, and typed-error builders — no network, no server:
|
|
336
|
+
|
|
337
|
+
```tsx
|
|
338
|
+
import {
|
|
339
|
+
createMockFartherShoreClient,
|
|
340
|
+
FartherShoreTestProvider,
|
|
341
|
+
mockLimitExceeded,
|
|
342
|
+
} from "@farthershore/farthershore-js/test-utils";
|
|
343
|
+
|
|
344
|
+
const client = createMockFartherShoreClient({
|
|
345
|
+
keys: { list: async () => [{ id: "key_1", label: "Test key" }] },
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
render(
|
|
349
|
+
<FartherShoreTestProvider client={client}>
|
|
350
|
+
<ApiKeys />
|
|
351
|
+
</FartherShoreTestProvider>,
|
|
352
|
+
);
|
|
259
353
|
```
|
|
260
354
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
ships separately as `@farthershore/farthershore-js/components/docs.css`.
|
|
355
|
+
`mockLimitExceeded`, `mockRateLimited`, and `mockApiError` build the typed
|
|
356
|
+
errors above for asserting your error-handling paths without a real deny from
|
|
357
|
+
Core or the Gateway.
|
|
265
358
|
|
|
266
359
|
## Learn more
|
|
267
360
|
|
package/dist/bootstrap.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Capability discovery. `bootstrap()` resolves the business the frontend is
|
|
2
2
|
// running for from the portal host — the SAME public endpoint the portal renders
|
|
3
|
-
// from — and caches
|
|
3
|
+
// from — and caches businessId / environmentId / gateway origin on the client so
|
|
4
4
|
// every later call knows where to go.
|
|
5
5
|
//
|
|
6
6
|
// The resolve DTO carries the business's full catalog: the plan list (the rich
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// subscribe flow — not just an account dashboard.
|
|
12
12
|
import { coreFetch } from "./http.js";
|
|
13
13
|
import { consumePrimedResolve } from "./boot-primer.js";
|
|
14
|
-
import { FartherShoreNotReadyError } from "./errors.js";
|
|
14
|
+
import { FartherShoreNotReadyError } from "./errors/index.js";
|
|
15
15
|
// ── Mappers ───────────────────────────────────────────────────────────────
|
|
16
16
|
function mapMeter(m) {
|
|
17
17
|
const key = m.key ?? m.dimension;
|
|
@@ -186,7 +186,7 @@ export async function resolveBootstrap(ctx) {
|
|
|
186
186
|
const environment = raw.environment ? mapEnv(raw.environment) : null;
|
|
187
187
|
const plans = (raw.plans ?? []).map(mapPlan);
|
|
188
188
|
// Cache routing facts for subsequent calls (config values still win).
|
|
189
|
-
ctx.
|
|
189
|
+
ctx.businessId = ctx.businessId ?? business.id;
|
|
190
190
|
if (environment)
|
|
191
191
|
ctx.environmentId = ctx.environmentId ?? environment.id;
|
|
192
192
|
ctx.gatewayUrl = ctx.gatewayUrl ?? `https://${business.gatewayHost}`;
|
package/dist/bootstrap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,iFAAiF;AACjF,
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"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"}
|