@foir/sdk 0.5.0 → 0.8.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 +1126 -0
- package/README.md +94 -0
- package/dist/auth/auth.d.ts +243 -0
- package/dist/auth/hosted.d.ts +40 -0
- package/dist/auth/index.d.ts +21 -0
- package/dist/auth/operations.d.ts +144 -0
- package/dist/auth/ops.d.ts +99 -0
- package/dist/auth/session-client.d.ts +76 -0
- package/dist/auth-session.js +137 -0
- package/dist/auth.js +973 -92
- package/dist/chunk-IGNLWT3H.js +35 -0
- package/dist/chunk-OHYVKTGB.js +45 -0
- package/dist/chunk-TAL5H6VA.js +39 -0
- package/dist/client/platform-client.d.ts +29 -0
- package/dist/client.js +275 -37
- package/dist/codegen/block-registry.d.ts +13 -23
- package/dist/codegen/block-registry.js +3 -31
- package/dist/codegen/block-scaffold.d.ts +12 -25
- package/dist/codegen/block-scaffold.js +3 -41
- package/dist/codegen/index.d.ts +12 -61
- package/dist/codegen/index.js +7 -11
- package/dist/codegen/item-registry.d.ts +28 -0
- package/dist/codegen/item-registry.js +7 -0
- package/dist/codegen/item-scaffold.d.ts +29 -0
- package/dist/codegen/item-scaffold.js +7 -0
- package/dist/codegen/preset.d.ts +67 -0
- package/dist/codegen/shared.d.ts +36 -0
- package/dist/components/EditorProvider.d.ts +36 -0
- package/dist/content/content-renderer.d.ts +113 -0
- package/dist/content/index.d.ts +18 -0
- package/dist/content/richtext.d.ts +118 -0
- package/dist/content.js +227 -80
- package/dist/data/builtins.d.ts +506 -0
- package/dist/data/client.d.ts +166 -0
- package/dist/data/document.d.ts +251 -0
- package/dist/data/index.d.ts +73 -0
- package/dist/data/manifest.d.ts +424 -0
- package/dist/data/schema.d.ts +313 -0
- package/dist/data/selection.d.ts +524 -0
- package/dist/data/subjects.d.ts +221 -0
- package/dist/data/subscription-document.d.ts +75 -0
- package/dist/data/subscriptions.d.ts +181 -0
- package/dist/data/transport.d.ts +325 -0
- package/dist/data/ws-transport.d.ts +197 -0
- package/dist/data.js +1683 -0
- package/dist/graphql/cdn-route.d.ts +26 -0
- package/dist/graphql/client.d.ts +30 -0
- package/dist/graphql/content-client.d.ts +66 -0
- package/dist/graphql/foir-request.d.ts +47 -0
- package/dist/hooks/useAutoResize.d.ts +22 -0
- package/dist/hooks/useEditor.d.ts +16 -0
- package/dist/index.d.ts +10 -394
- package/dist/media/BlurhashCanvas.d.ts +10 -0
- package/dist/media/ProgressiveMedia.d.ts +56 -0
- package/dist/media/index.d.ts +18 -0
- package/dist/media/media.d.ts +139 -0
- package/dist/media/screen-capture.d.ts +81 -0
- package/dist/media/useProgressiveLoad.d.ts +23 -0
- package/dist/media.js +102 -0
- package/dist/next/cookieAdapter.d.ts +26 -0
- package/dist/next/index.d.ts +15 -0
- package/dist/next/middleware.d.ts +49 -0
- package/dist/next/session.d.ts +53 -0
- package/dist/next.js +763 -78
- package/dist/protocol/constants.d.ts +6 -0
- package/dist/protocol/messages.d.ts +155 -0
- package/dist/protocol/validation.d.ts +8 -0
- package/dist/push/index.d.ts +14 -0
- package/dist/push/operations.d.ts +22 -0
- package/dist/push/web-push.d.ts +39 -0
- package/dist/push.js +892 -78
- package/dist/react/FoirFeedback.d.ts +62 -0
- package/dist/react/FoirProvider.d.ts +116 -0
- package/dist/react/OAuthButtons.d.ts +20 -0
- package/dist/react/SignIn.d.ts +22 -0
- package/dist/react/UserButton.d.ts +13 -0
- package/dist/react/feedback-notes.d.ts +101 -0
- package/dist/react/index.d.ts +25 -0
- package/dist/react/localStorageAdapter.d.ts +10 -0
- package/dist/react.js +1373 -91
- package/dist/{realtime.d.ts → realtime/index.d.ts} +35 -16
- package/dist/realtime.js +1 -1
- package/dist/server/callback-client.d.ts +92 -0
- package/dist/server/events-client.d.ts +279 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/operation-types.d.ts +134 -0
- package/dist/server/require-scoped-token.d.ts +76 -0
- package/dist/server/server-client.d.ts +34 -0
- package/dist/server/types.d.ts +54 -0
- package/dist/server/verify-scoped-token.d.ts +100 -0
- package/dist/server/webhook-helpers.d.ts +36 -0
- package/dist/server.js +298 -0
- package/dist/transport/foir-http.d.ts +234 -0
- package/dist/transport/persisted-query.d.ts +68 -0
- package/dist/transport/retry.d.ts +61 -0
- package/dist/types/index.d.ts +124 -0
- package/package.json +35 -13
- package/dist/auth.d.ts +0 -382
- package/dist/chunk-ADO5FJNM.js +0 -30
- package/dist/client.d.ts +0 -135
- package/dist/content.d.ts +0 -96
- package/dist/media.d.ts +0 -234
- package/dist/next.d.ts +0 -178
- package/dist/push.d.ts +0 -109
- package/dist/react.d.ts +0 -319
- package/dist/server.d.ts +0 -534
- package/dist/shared-DkWlEd2Z.d.ts +0 -18
package/dist/auth.d.ts
DELETED
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
import { TypedDocumentNode } from '@graphql-typed-document-node/core';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Foir GraphQL client — a single typed fetch wrapper for SSR/edge loaders.
|
|
5
|
-
*
|
|
6
|
-
* No GraphQL client (Apollo/urql) required: the Foir public API is a plain
|
|
7
|
-
* `POST` with an `x-api-key` header, and the dominant consumers (Hydrogen on
|
|
8
|
-
* Oxygen, React Router loaders, TanStack Start on CF Workers) fetch in
|
|
9
|
-
* server-only loaders and render — so Apollo's `InMemoryCache`/`useQuery`
|
|
10
|
-
* reactivity is dead weight, and a shared cache on a stateless multi-tenant
|
|
11
|
-
* edge worker is a cross-tenant hazard. This helper carries only the
|
|
12
|
-
* Foir-specific transport concerns (auth header, preview schema channel,
|
|
13
|
-
* error shape). Consumers on a GraphQL client (Apollo / urql / react-query /
|
|
14
|
-
* graphql-request) use the generated `TypedDocumentNode`s directly with their
|
|
15
|
-
* own client and replicate the two Foir-specific headers below — the
|
|
16
|
-
* `x-api-key` and, in preview, `X-Foir-Schema-Channel: draft`.
|
|
17
|
-
*
|
|
18
|
-
* Deduplicates the hand-copied `lib/foir/client.ts` that shipped identically
|
|
19
|
-
* across the Foir storefronts.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
interface FoirEnv {
|
|
23
|
-
PLATFORM_API_URL?: string;
|
|
24
|
-
PLATFORM_API_KEY?: string;
|
|
25
|
-
PLATFORM_PREVIEW_API_KEY?: string;
|
|
26
|
-
FOIR_PREVIEW?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Foir customer-auth GraphQL operations + result types.
|
|
31
|
-
*
|
|
32
|
-
* These are PLATFORM-STABLE primitives — `customerLogin`/`customerRegister`/
|
|
33
|
-
* `customerRefreshToken`/OTP/provider login are fixed-shape operations served
|
|
34
|
-
* by api-public for every project (gated per-project by the password/OTP/
|
|
35
|
-
* provider flags, but identical in shape when present). Unlike per-project
|
|
36
|
-
* model types, they don't vary by configured models, so the SDK owns the
|
|
37
|
-
* documents directly rather than relying on the consumer's codegen.
|
|
38
|
-
*
|
|
39
|
-
* The project-specific customer PROFILE (e.g. `myProfile.isAdmin`) is NOT here
|
|
40
|
-
* — that shape varies per project, so it stays consumer-injected (see
|
|
41
|
-
* `requireAuth`'s `resolveUser`).
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
/** The common auth result every login/register/refresh mutation returns. */
|
|
45
|
-
interface CustomerAuthResult {
|
|
46
|
-
token: string;
|
|
47
|
-
refreshToken: string;
|
|
48
|
-
customerId: string;
|
|
49
|
-
email: string;
|
|
50
|
-
}
|
|
51
|
-
/** Result of initiating a provider login — a redirect URL or an inline token. */
|
|
52
|
-
interface ProviderLoginResult {
|
|
53
|
-
/** OAuth/OIDC authorization URL to redirect the user to (redirect flows). */
|
|
54
|
-
redirectUrl: string | null;
|
|
55
|
-
/** Inline access token (non-redirect provider flows). */
|
|
56
|
-
token: string | null;
|
|
57
|
-
}
|
|
58
|
-
/** A configured auth provider, as exposed to unauthenticated callers. */
|
|
59
|
-
interface AuthProviderPublic {
|
|
60
|
-
key: string;
|
|
61
|
-
name: string;
|
|
62
|
-
/** OAUTH2 | TOKEN_SSO | SAML | OIDC | EXTERNAL */
|
|
63
|
-
type: string;
|
|
64
|
-
isDefault: boolean | null;
|
|
65
|
-
}
|
|
66
|
-
interface ProviderLoginInput {
|
|
67
|
-
providerKey: string;
|
|
68
|
-
email?: string;
|
|
69
|
-
returnTo?: string;
|
|
70
|
-
/** Override the provider's default redirect_uri (must be allow-listed). */
|
|
71
|
-
redirectUri?: string;
|
|
72
|
-
}
|
|
73
|
-
interface ProviderCallbackInput {
|
|
74
|
-
providerKey: string;
|
|
75
|
-
code?: string;
|
|
76
|
-
state?: string;
|
|
77
|
-
email?: string;
|
|
78
|
-
idToken?: string;
|
|
79
|
-
}
|
|
80
|
-
interface ProviderOTPVerifyInput {
|
|
81
|
-
providerKey: string;
|
|
82
|
-
email: string;
|
|
83
|
-
otp: string;
|
|
84
|
-
}
|
|
85
|
-
declare const CustomerLoginDocument: TypedDocumentNode<{
|
|
86
|
-
customerLogin: CustomerAuthResult;
|
|
87
|
-
}, {
|
|
88
|
-
email: string;
|
|
89
|
-
password: string;
|
|
90
|
-
}>;
|
|
91
|
-
declare const CustomerRegisterDocument: TypedDocumentNode<{
|
|
92
|
-
customerRegister: CustomerAuthResult;
|
|
93
|
-
}, {
|
|
94
|
-
email: string;
|
|
95
|
-
password: string;
|
|
96
|
-
}>;
|
|
97
|
-
declare const CustomerRefreshTokenDocument: TypedDocumentNode<{
|
|
98
|
-
customerRefreshToken: CustomerAuthResult;
|
|
99
|
-
}, {
|
|
100
|
-
refreshToken: string;
|
|
101
|
-
}>;
|
|
102
|
-
declare const CustomerRequestOTPDocument: TypedDocumentNode<{
|
|
103
|
-
customerRequestOTP: boolean;
|
|
104
|
-
}, {
|
|
105
|
-
email: string;
|
|
106
|
-
}>;
|
|
107
|
-
declare const CustomerLoginOTPDocument: TypedDocumentNode<{
|
|
108
|
-
customerLoginOTP: CustomerAuthResult;
|
|
109
|
-
}, {
|
|
110
|
-
email: string;
|
|
111
|
-
otp: string;
|
|
112
|
-
}>;
|
|
113
|
-
declare const CustomerLoginWithProviderDocument: TypedDocumentNode<{
|
|
114
|
-
customerLoginWithProvider: ProviderLoginResult;
|
|
115
|
-
}, {
|
|
116
|
-
input: ProviderLoginInput;
|
|
117
|
-
}>;
|
|
118
|
-
declare const CustomerProviderCallbackDocument: TypedDocumentNode<{
|
|
119
|
-
customerProviderCallback: CustomerAuthResult;
|
|
120
|
-
}, {
|
|
121
|
-
input: ProviderCallbackInput;
|
|
122
|
-
}>;
|
|
123
|
-
declare const CustomerProviderVerifyOTPDocument: TypedDocumentNode<{
|
|
124
|
-
customerProviderVerifyOTP: CustomerAuthResult;
|
|
125
|
-
}, {
|
|
126
|
-
input: ProviderOTPVerifyInput;
|
|
127
|
-
}>;
|
|
128
|
-
declare const AuthProvidersDocument: TypedDocumentNode<{
|
|
129
|
-
authProviders: AuthProviderPublic[];
|
|
130
|
-
}, Record<string, never>>;
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Foir customer auth — framework-agnostic flows, token lifecycle, and guards.
|
|
134
|
-
*
|
|
135
|
-
* Session I/O is injected via {@link SessionAdapter} (no Hydrogen/React-Router
|
|
136
|
-
* coupling). Pre-login flows authenticate with the project `x-api-key`;
|
|
137
|
-
* post-login reads add the customer bearer. The project-specific profile (e.g.
|
|
138
|
-
* `isAdmin`) is resolved by a consumer-supplied `resolveUser` — the SDK never
|
|
139
|
-
* hardcodes the per-project customer profile shape.
|
|
140
|
-
*/
|
|
141
|
-
|
|
142
|
-
/** An access token + its rotating refresh token. */
|
|
143
|
-
interface FoirAuthTokens {
|
|
144
|
-
token: string;
|
|
145
|
-
refreshToken: string;
|
|
146
|
-
}
|
|
147
|
-
/** The customer identity carried by an auth result. */
|
|
148
|
-
interface FoirCustomer {
|
|
149
|
-
id: string;
|
|
150
|
-
email: string;
|
|
151
|
-
}
|
|
152
|
-
/** The resolved customer for a guarded surface. */
|
|
153
|
-
interface FoirUser {
|
|
154
|
-
id: string;
|
|
155
|
-
email: string;
|
|
156
|
-
isAdmin: boolean;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Injected session store. Methods may be sync or async so consumers can plug
|
|
160
|
-
* in a cookie session (Hydrogen/Remix), a KV store, etc.
|
|
161
|
-
*/
|
|
162
|
-
interface SessionAdapter {
|
|
163
|
-
get(key: string): string | null | undefined | Promise<string | null | undefined>;
|
|
164
|
-
set(key: string, value: string): void | Promise<void>;
|
|
165
|
-
unset(key: string): void | Promise<void>;
|
|
166
|
-
}
|
|
167
|
-
/** Login with email + password. Requires the project to have passwords enabled. */
|
|
168
|
-
declare function customerLogin(env: FoirEnv, vars: {
|
|
169
|
-
email: string;
|
|
170
|
-
password: string;
|
|
171
|
-
}): Promise<CustomerAuthResult>;
|
|
172
|
-
/** Register a new customer with email + password. */
|
|
173
|
-
declare function customerRegister(env: FoirEnv, vars: {
|
|
174
|
-
email: string;
|
|
175
|
-
password: string;
|
|
176
|
-
}): Promise<CustomerAuthResult>;
|
|
177
|
-
/** Request a one-time password be emailed to the customer. */
|
|
178
|
-
declare function customerRequestOTP(env: FoirEnv, email: string): Promise<boolean>;
|
|
179
|
-
/** Complete an OTP login. */
|
|
180
|
-
declare function customerLoginOTP(env: FoirEnv, vars: {
|
|
181
|
-
email: string;
|
|
182
|
-
otp: string;
|
|
183
|
-
}): Promise<CustomerAuthResult>;
|
|
184
|
-
/** Rotate an access token using a refresh token. */
|
|
185
|
-
declare function customerRefreshToken(env: FoirEnv, refreshToken: string): Promise<CustomerAuthResult>;
|
|
186
|
-
/**
|
|
187
|
-
* Initiate provider (OAuth/OIDC) login — returns a `redirectUrl` to send the
|
|
188
|
-
* user to, or an inline `token` for non-redirect providers.
|
|
189
|
-
*/
|
|
190
|
-
declare function customerLoginWithProvider(env: FoirEnv, input: ProviderLoginInput): Promise<ProviderLoginResult>;
|
|
191
|
-
/** Complete a provider login from the OAuth callback (`code`/`state`). */
|
|
192
|
-
declare function customerProviderCallback(env: FoirEnv, input: ProviderCallbackInput): Promise<CustomerAuthResult>;
|
|
193
|
-
/** Verify an OTP issued by an external provider. */
|
|
194
|
-
declare function customerProviderVerifyOTP(env: FoirEnv, input: ProviderOTPVerifyInput): Promise<CustomerAuthResult>;
|
|
195
|
-
/** List the project's configured auth providers (for a login UI). */
|
|
196
|
-
declare function getAuthProviders(env: FoirEnv): Promise<AuthProviderPublic[]>;
|
|
197
|
-
/** Persist an auth result to the session; returns the customer identity. */
|
|
198
|
-
declare function saveSession(adapter: SessionAdapter, result: CustomerAuthResult): Promise<FoirCustomer>;
|
|
199
|
-
/** Clear all Foir auth keys from the session. */
|
|
200
|
-
declare function clearSession(adapter: SessionAdapter): Promise<void>;
|
|
201
|
-
/** Read the stored access token (null when signed out). */
|
|
202
|
-
declare function getSessionToken(adapter: SessionAdapter): Promise<string | null>;
|
|
203
|
-
/** Read the stored customer identity (null when signed out). */
|
|
204
|
-
declare function getSessionCustomer(adapter: SessionAdapter): Promise<FoirCustomer | null>;
|
|
205
|
-
/** Login with email + password and persist the session. */
|
|
206
|
-
declare function loginWithPassword(adapter: SessionAdapter, env: FoirEnv, vars: {
|
|
207
|
-
email: string;
|
|
208
|
-
password: string;
|
|
209
|
-
}): Promise<FoirCustomer>;
|
|
210
|
-
/** Register with email + password and persist the session. */
|
|
211
|
-
declare function registerWithPassword(adapter: SessionAdapter, env: FoirEnv, vars: {
|
|
212
|
-
email: string;
|
|
213
|
-
password: string;
|
|
214
|
-
}): Promise<FoirCustomer>;
|
|
215
|
-
/** Complete an OTP login and persist the session. */
|
|
216
|
-
declare function loginWithOTP(adapter: SessionAdapter, env: FoirEnv, vars: {
|
|
217
|
-
email: string;
|
|
218
|
-
otp: string;
|
|
219
|
-
}): Promise<FoirCustomer>;
|
|
220
|
-
/**
|
|
221
|
-
* Refresh the access token from the stored refresh token, persisting the
|
|
222
|
-
* rotated pair. Returns the new tokens, or null when there's no refresh token
|
|
223
|
-
* or the refresh fails (the session is cleared in that case).
|
|
224
|
-
*/
|
|
225
|
-
declare function refreshSession(adapter: SessionAdapter, env: FoirEnv): Promise<FoirAuthTokens | null>;
|
|
226
|
-
/**
|
|
227
|
-
* Run a bearer-authed GraphQL operation with refresh-with-retry: uses the
|
|
228
|
-
* stored access token, and on a 401-shaped failure (rejected/expired bearer)
|
|
229
|
-
* attempts a single token refresh and retries once. Any other error — network
|
|
230
|
-
* blips, server errors, validation — propagates without a retry so transient
|
|
231
|
-
* mutation failures can't be duplicated. Throws the original error if there's
|
|
232
|
-
* no refresh path.
|
|
233
|
-
*/
|
|
234
|
-
declare function authedRequest<TData, TVariables>(adapter: SessionAdapter, env: FoirEnv, document: TypedDocumentNode<TData, TVariables>, variables?: TVariables): Promise<TData>;
|
|
235
|
-
interface RequireAuthOptions {
|
|
236
|
-
/**
|
|
237
|
-
* Resolve the full {@link FoirUser} (including the project-specific
|
|
238
|
-
* `isAdmin`) from the session identity. Typically runs the project's
|
|
239
|
-
* `myProfile` query via {@link authedRequest}. Defaults to `isAdmin: false`.
|
|
240
|
-
*/
|
|
241
|
-
resolveUser?: (ctx: {
|
|
242
|
-
token: string;
|
|
243
|
-
customer: FoirCustomer;
|
|
244
|
-
}) => FoirUser | Promise<FoirUser>;
|
|
245
|
-
/**
|
|
246
|
-
* Called when there's no valid session — throw your framework's redirect
|
|
247
|
-
* (e.g. `throw redirect(loginUrl)`). Must not return.
|
|
248
|
-
*/
|
|
249
|
-
onUnauthenticated: () => never | Promise<never>;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Require a signed-in customer. Resolves the {@link FoirUser} via
|
|
253
|
-
* `resolveUser` (or a minimal identity), or invokes `onUnauthenticated` when
|
|
254
|
-
* there's no session.
|
|
255
|
-
*/
|
|
256
|
-
declare function requireAuth(adapter: SessionAdapter, options: RequireAuthOptions): Promise<FoirUser>;
|
|
257
|
-
interface RequireAdminOptions extends RequireAuthOptions {
|
|
258
|
-
/** Called when the user is authenticated but not an admin. Must not return. */
|
|
259
|
-
onForbidden: () => never | Promise<never>;
|
|
260
|
-
}
|
|
261
|
-
/** Require a signed-in customer who is also an admin. */
|
|
262
|
-
declare function requireAdmin(adapter: SessionAdapter, options: RequireAdminOptions): Promise<FoirUser>;
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Hosted-login bridge — for storefronts that delegate sign-in to a Foir
|
|
266
|
-
* white-label front door (the `customerLoginWithFoir` flow) instead of
|
|
267
|
-
* rendering their own login UI.
|
|
268
|
-
*
|
|
269
|
-
* The front door sets a first-party session cookie on the registrable domain;
|
|
270
|
-
* because that domain is shared, the cookie reaches the storefront, which
|
|
271
|
-
* exchanges it server-side for a short-lived customer bearer + identity. The
|
|
272
|
-
* cookie is the durable credential (re-exchanged on bearer expiry) — there's
|
|
273
|
-
* no separate refresh token in this flow.
|
|
274
|
-
*
|
|
275
|
-
* Every URL/cookie/path is CONFIG, not a constant, so a domain restructure
|
|
276
|
-
* is a config change, not a code change.
|
|
277
|
-
*/
|
|
278
|
-
interface HostedLoginConfig {
|
|
279
|
-
/** White-label front-door origin, e.g. `https://login.example.com`. */
|
|
280
|
-
loginOrigin: string;
|
|
281
|
-
/** Session cookie name set on the registrable domain. Default `foir_customer_session`. */
|
|
282
|
-
cookieName?: string;
|
|
283
|
-
/** Session-exchange path on the front door. Default `/session/token`. */
|
|
284
|
-
sessionPath?: string;
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* Build the redirect URL to the hosted front door, forwarding a best-effort
|
|
288
|
-
* absolute `returnTo` (honoured if the front door supports it).
|
|
289
|
-
*/
|
|
290
|
-
declare function hostedLoginUrl(config: HostedLoginConfig, returnTo?: string): string;
|
|
291
|
-
/** The identity + bearer returned by a successful hosted-session exchange. */
|
|
292
|
-
interface HostedSession {
|
|
293
|
-
token: string;
|
|
294
|
-
customerId: string;
|
|
295
|
-
email: string;
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* Exchange the hosted-login cookie on an incoming request for a customer
|
|
299
|
-
* bearer + identity (server-to-server: forwards the cookie to the front
|
|
300
|
-
* door's session endpoint with the CSRF header). Returns null when there's no
|
|
301
|
-
* cookie or it's expired/revoked.
|
|
302
|
-
*/
|
|
303
|
-
declare function fetchHostedSession(request: Request, config: HostedLoginConfig): Promise<HostedSession | null>;
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Foir-hosted first-party sessions, from the browser — the model for a
|
|
307
|
-
* backend-less SPA (Vite, CRA, a static site) that wants no tokens in JS.
|
|
308
|
-
*
|
|
309
|
-
* The sibling `fetchHostedSession` in ./hosted does the same exchange from a
|
|
310
|
-
* SERVER: it reads the cookie off an incoming request and forwards it by hand.
|
|
311
|
-
* A browser cannot set a `Cookie` header, so that function is unusable from an
|
|
312
|
-
* SPA by construction. This one lets the browser send the cookie the only way it
|
|
313
|
-
* can — `credentials: 'include'` — and keeps the resulting bearer in memory.
|
|
314
|
-
*
|
|
315
|
-
* How the pieces divide:
|
|
316
|
-
*
|
|
317
|
-
* cookie — long-lived (30d), HttpOnly, first-party on your registrable
|
|
318
|
-
* domain, set by Foir when hosted login finalizes. JS cannot read
|
|
319
|
-
* it, so XSS cannot exfiltrate it.
|
|
320
|
-
* bearer — 15 minutes, held in a closure here. Never written to
|
|
321
|
-
* localStorage/sessionStorage/IndexedDB, never in a cookie of ours.
|
|
322
|
-
*
|
|
323
|
-
* There is no refresh token in this flow. Re-exchanging the cookie IS the
|
|
324
|
-
* refresh, which is why nothing here needs rotation or reuse-detection: the
|
|
325
|
-
* durable credential is an opaque server-side session handle, revocable at any
|
|
326
|
-
* time from the admin panel or `signOut()`.
|
|
327
|
-
*
|
|
328
|
-
* REQUIRES a verified custom login domain that shares a registrable domain with
|
|
329
|
-
* your app (app.acme.com + login.acme.com). That is what makes the cookie
|
|
330
|
-
* first-party and lets `SameSite=Lax` send it. The same endpoints exist on
|
|
331
|
-
* api.foir.dev but a browser cannot reach them there — the cookie would be
|
|
332
|
-
* cross-site, and that CORS surface deliberately refuses credentials.
|
|
333
|
-
*/
|
|
334
|
-
interface FoirSessionConfig {
|
|
335
|
-
/**
|
|
336
|
-
* Your verified custom login domain, e.g. `https://login.acme.com`. Must share
|
|
337
|
-
* a registrable domain with the app calling it.
|
|
338
|
-
*/
|
|
339
|
-
loginOrigin: string;
|
|
340
|
-
/** Session-exchange path. Default `/session/token`. */
|
|
341
|
-
sessionPath?: string;
|
|
342
|
-
/** Logout path. Default `/session/logout`. */
|
|
343
|
-
logoutPath?: string;
|
|
344
|
-
/** Seconds before expiry to re-exchange. Default 60. */
|
|
345
|
-
refreshSkewSeconds?: number;
|
|
346
|
-
/**
|
|
347
|
-
* Called when the session goes away — the cookie expired, was revoked, or
|
|
348
|
-
* `signOut()` ran. Use it to redirect to `signInUrl()`.
|
|
349
|
-
*/
|
|
350
|
-
onSignOut?: () => void;
|
|
351
|
-
}
|
|
352
|
-
/** The identity behind the current session. */
|
|
353
|
-
interface FoirSessionUser {
|
|
354
|
-
customerId: string;
|
|
355
|
-
email: string;
|
|
356
|
-
}
|
|
357
|
-
interface FoirSessionClient {
|
|
358
|
-
/**
|
|
359
|
-
* The current access token, exchanging or re-exchanging the cookie as needed.
|
|
360
|
-
* Null when there is no session. Concurrent callers share one in-flight
|
|
361
|
-
* exchange. Call this before each API request — do not cache the result.
|
|
362
|
-
*/
|
|
363
|
-
getToken(): Promise<string | null>;
|
|
364
|
-
/** The signed-in customer, or null. Exchanges if the session isn't loaded yet. */
|
|
365
|
-
getUser(): Promise<FoirSessionUser | null>;
|
|
366
|
-
/** Revoke the session server-side and clear the cookie. Idempotent. */
|
|
367
|
-
signOut(): Promise<void>;
|
|
368
|
-
/** Where to send the browser to sign in. */
|
|
369
|
-
signInUrl(returnTo?: string): string;
|
|
370
|
-
/** Observe session changes. Returns an unsubscribe function. */
|
|
371
|
-
subscribe(listener: (user: FoirSessionUser | null) => void): () => void;
|
|
372
|
-
/** Cancel the refresh timer. Call on unmount. */
|
|
373
|
-
destroy(): void;
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Create a session client. Safe to call during SSR — it does nothing until a
|
|
377
|
-
* method is invoked, and `getToken()` on the server returns null rather than
|
|
378
|
-
* throwing (there is no cookie jar to draw on).
|
|
379
|
-
*/
|
|
380
|
-
declare function createFoirSessionClient(config: FoirSessionConfig): FoirSessionClient;
|
|
381
|
-
|
|
382
|
-
export { type AuthProviderPublic, AuthProvidersDocument, type CustomerAuthResult, CustomerLoginDocument, CustomerLoginOTPDocument, CustomerLoginWithProviderDocument, CustomerProviderCallbackDocument, CustomerProviderVerifyOTPDocument, CustomerRefreshTokenDocument, CustomerRegisterDocument, CustomerRequestOTPDocument, type FoirAuthTokens, type FoirCustomer, type FoirSessionClient, type FoirSessionConfig, type FoirSessionUser, type FoirUser, type HostedLoginConfig, type HostedSession, type ProviderCallbackInput, type ProviderLoginInput, type ProviderLoginResult, type ProviderOTPVerifyInput, type RequireAdminOptions, type RequireAuthOptions, type SessionAdapter, authedRequest, clearSession, createFoirSessionClient, customerLogin, customerLoginOTP, customerLoginWithProvider, customerProviderCallback, customerProviderVerifyOTP, customerRefreshToken, customerRegister, customerRequestOTP, fetchHostedSession, getAuthProviders, getSessionCustomer, getSessionToken, hostedLoginUrl, loginWithOTP, loginWithPassword, refreshSession, registerWithPassword, requireAdmin, requireAuth, saveSession };
|
package/dist/chunk-ADO5FJNM.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// src/codegen/shared.ts
|
|
2
|
-
import { isUnionType } from "graphql";
|
|
3
|
-
var DEFAULT_UNIONS = ["Block"];
|
|
4
|
-
var DEFAULT_GRAPHQL_IMPORT = "./graphql";
|
|
5
|
-
var DEFAULT_SDK_IMPORT = "@foir/sdk/content";
|
|
6
|
-
function collectBlockMembers(schema, unionNames) {
|
|
7
|
-
const members = /* @__PURE__ */ new Set();
|
|
8
|
-
const missing = [];
|
|
9
|
-
for (const name of unionNames) {
|
|
10
|
-
const type = schema.getType(name);
|
|
11
|
-
if (!type || !isUnionType(type)) {
|
|
12
|
-
missing.push(name);
|
|
13
|
-
continue;
|
|
14
|
-
}
|
|
15
|
-
for (const member of type.getTypes()) members.add(member.name);
|
|
16
|
-
}
|
|
17
|
-
if (members.size === 0) {
|
|
18
|
-
throw new Error(
|
|
19
|
-
`[foir codegen] no union members found. Looked for union(s): ${unionNames.join(", ")}` + (missing.length ? ` (not found or not a union: ${missing.join(", ")})` : "") + `. Run \`foir push\` and confirm the block union name.`
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
return [...members].sort();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export {
|
|
26
|
-
DEFAULT_UNIONS,
|
|
27
|
-
DEFAULT_GRAPHQL_IMPORT,
|
|
28
|
-
DEFAULT_SDK_IMPORT,
|
|
29
|
-
collectBlockMembers
|
|
30
|
-
};
|
package/dist/client.d.ts
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { TypedDocumentNode } from '@graphql-typed-document-node/core';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Foir GraphQL client — a single typed fetch wrapper for SSR/edge loaders.
|
|
5
|
-
*
|
|
6
|
-
* No GraphQL client (Apollo/urql) required: the Foir public API is a plain
|
|
7
|
-
* `POST` with an `x-api-key` header, and the dominant consumers (Hydrogen on
|
|
8
|
-
* Oxygen, React Router loaders, TanStack Start on CF Workers) fetch in
|
|
9
|
-
* server-only loaders and render — so Apollo's `InMemoryCache`/`useQuery`
|
|
10
|
-
* reactivity is dead weight, and a shared cache on a stateless multi-tenant
|
|
11
|
-
* edge worker is a cross-tenant hazard. This helper carries only the
|
|
12
|
-
* Foir-specific transport concerns (auth header, preview schema channel,
|
|
13
|
-
* error shape). Consumers on a GraphQL client (Apollo / urql / react-query /
|
|
14
|
-
* graphql-request) use the generated `TypedDocumentNode`s directly with their
|
|
15
|
-
* own client and replicate the two Foir-specific headers below — the
|
|
16
|
-
* `x-api-key` and, in preview, `X-Foir-Schema-Channel: draft`.
|
|
17
|
-
*
|
|
18
|
-
* Deduplicates the hand-copied `lib/foir/client.ts` that shipped identically
|
|
19
|
-
* across the Foir storefronts.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
interface FoirEnv {
|
|
23
|
-
PLATFORM_API_URL?: string;
|
|
24
|
-
PLATFORM_API_KEY?: string;
|
|
25
|
-
PLATFORM_PREVIEW_API_KEY?: string;
|
|
26
|
-
FOIR_PREVIEW?: string;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Returns true when `FOIR_PREVIEW=true` is set in the environment.
|
|
30
|
-
*
|
|
31
|
-
* Preview is selected at the environment level, not per-request: load a
|
|
32
|
-
* preview env file that sets `FOIR_PREVIEW=true` + a `sk_…`
|
|
33
|
-
* `PLATFORM_PREVIEW_API_KEY` with `drafts:read` instead of the default env.
|
|
34
|
-
* The site-wide mode keeps draft semantics consistent — every loader sees
|
|
35
|
-
* the same preview/published view of the world. Intended for non-production
|
|
36
|
-
* surfaces only.
|
|
37
|
-
*/
|
|
38
|
-
declare function isFoirPreview(env: FoirEnv): boolean;
|
|
39
|
-
/** Default Foir CDN origin used to absolutise relative media URLs. */
|
|
40
|
-
declare const FOIR_CDN_BASE = "https://cdn.foir.dev/";
|
|
41
|
-
/**
|
|
42
|
-
* Foir returns `hlsManifestUrl` as a relative path while every other media
|
|
43
|
-
* URL is absolute. Prefix relative paths with the CDN host so the browser
|
|
44
|
-
* doesn't request them from the consumer's own origin. Already-absolute URLs
|
|
45
|
-
* pass through untouched. `cdnBase` is overridable for non-default CDN hosts.
|
|
46
|
-
*/
|
|
47
|
-
declare function absolutiseFoirMediaUrl(url: string | null | undefined, cdnBase?: string): string | undefined;
|
|
48
|
-
interface FoirGraphQLErrorItem {
|
|
49
|
-
message: string;
|
|
50
|
-
path?: Array<string | number>;
|
|
51
|
-
}
|
|
52
|
-
declare class FoirRequestError extends Error {
|
|
53
|
-
/** HTTP status code, when the request failed at the HTTP layer. */
|
|
54
|
-
readonly status?: number;
|
|
55
|
-
/** GraphQL errors, when the request failed with a no-data error envelope. */
|
|
56
|
-
readonly graphQLErrors?: ReadonlyArray<FoirGraphQLErrorItem>;
|
|
57
|
-
readonly cause?: unknown;
|
|
58
|
-
constructor(message: string, options?: {
|
|
59
|
-
cause?: unknown;
|
|
60
|
-
status?: number;
|
|
61
|
-
graphQLErrors?: ReadonlyArray<FoirGraphQLErrorItem>;
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Execute a typed GraphQL document against the Foir platform.
|
|
66
|
-
*
|
|
67
|
-
* Throws `FoirRequestError` on HTTP failure or GraphQL errors so the caller
|
|
68
|
-
* can decide whether to rethrow or fall back to local defaults. GraphQL can
|
|
69
|
-
* return partial data alongside errors; when data is present the errors are
|
|
70
|
-
* logged and the data returned (callers handle nulls), and we only throw when
|
|
71
|
-
* there's no data at all.
|
|
72
|
-
*/
|
|
73
|
-
interface FoirRequestOptions {
|
|
74
|
-
/**
|
|
75
|
-
* Customer bearer token. api-public still needs the `x-api-key` to resolve
|
|
76
|
-
* the project; the bearer adds the customer identity for self-scoped reads
|
|
77
|
-
* (e.g. `myProfile`). Used by `@foir/sdk/auth`'s post-login profile fetch.
|
|
78
|
-
*/
|
|
79
|
-
bearerToken?: string;
|
|
80
|
-
}
|
|
81
|
-
declare function foirRequest<TData, TVariables>(env: FoirEnv, document: TypedDocumentNode<TData, TVariables>, variables?: TVariables, options?: FoirRequestOptions): Promise<TData>;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Session-bound content client — forwards the customer bearer on every read
|
|
85
|
-
* when one is available, so auth/segment-targeted variants and customer-scoped
|
|
86
|
-
* records resolve out of the box, with no per-query wiring to forget.
|
|
87
|
-
*
|
|
88
|
-
* Resolution keys off the request's principal (see the platform's two-gate
|
|
89
|
-
* model): the `x-api-key` alone resolves the *anonymous baseline*
|
|
90
|
-
* (`context.authStatus = ""`); adding the customer bearer resolves the request
|
|
91
|
-
* as that customer (`context.authStatus = "authenticated"`, `customer_id` set).
|
|
92
|
-
*
|
|
93
|
-
* Caching: an api-key-only read is identical for every anonymous visitor and is
|
|
94
|
-
* shared-cacheable; a bearer-bearing read resolves per-customer and is not.
|
|
95
|
-
* Because the bearer only exists once a customer signs in, anonymous traffic
|
|
96
|
-
* keeps hitting the shared-cacheable baseline — only signed-in reads become
|
|
97
|
-
* per-customer. Bind this client wherever content is personalized (for most
|
|
98
|
-
* apps, everywhere the customer may be signed in) and use plain `foirRequest`
|
|
99
|
-
* for reads that must stay anonymous regardless of session.
|
|
100
|
-
*/
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Supplies the current customer bearer. Sync or async so consumers can read a
|
|
104
|
-
* cookie session (Hydrogen/Remix), a KV store, an in-memory value, etc. Returns
|
|
105
|
-
* the token when signed in, or `null`/`undefined` when signed out.
|
|
106
|
-
*/
|
|
107
|
-
type FoirTokenProvider = () => string | null | undefined | Promise<string | null | undefined>;
|
|
108
|
-
interface FoirContentClientConfig {
|
|
109
|
-
env: FoirEnv;
|
|
110
|
-
/**
|
|
111
|
-
* Resolves the current customer bearer before every request. When it yields a
|
|
112
|
-
* token the token is forwarded, so `authStatus`/segment targeting and
|
|
113
|
-
* customer-scoped records resolve as that customer; when it yields
|
|
114
|
-
* null/undefined the read hits the anonymous baseline. Omit for a client that
|
|
115
|
-
* is always anonymous (equivalent to calling `foirRequest` directly).
|
|
116
|
-
*/
|
|
117
|
-
getToken?: FoirTokenProvider;
|
|
118
|
-
}
|
|
119
|
-
interface FoirContentClient {
|
|
120
|
-
/**
|
|
121
|
-
* Run a typed document, forwarding the bound customer bearer when available.
|
|
122
|
-
* An explicit `options.bearerToken` still wins, so a single call can override
|
|
123
|
-
* the bound token (or force anonymous by passing `undefined` — the bound
|
|
124
|
-
* token only fills in when `options.bearerToken` is not supplied).
|
|
125
|
-
*/
|
|
126
|
-
request<TData, TVariables>(document: TypedDocumentNode<TData, TVariables>, variables?: TVariables, options?: FoirRequestOptions): Promise<TData>;
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Create a {@link FoirContentClient} bound to an env + token source. Every
|
|
130
|
-
* `request` forwards the customer bearer when `getToken` yields one, upgrading
|
|
131
|
-
* that read from the anonymous baseline to the signed-in customer.
|
|
132
|
-
*/
|
|
133
|
-
declare function createFoirContentClient(config: FoirContentClientConfig): FoirContentClient;
|
|
134
|
-
|
|
135
|
-
export { FOIR_CDN_BASE, type FoirContentClient, type FoirContentClientConfig, type FoirEnv, FoirRequestError, type FoirRequestOptions, type FoirTokenProvider, absolutiseFoirMediaUrl, createFoirContentClient, foirRequest, isFoirPreview };
|
package/dist/content.d.ts
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { ReactNode, JSX } from 'react';
|
|
2
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* createContentRenderer — the generic content-dispatch primitive.
|
|
6
|
-
*
|
|
7
|
-
* It does NOT know any concrete block types. Given a registry that maps each
|
|
8
|
-
* block `__typename` to a component, it renders a `flexible` field's block
|
|
9
|
-
* array: looks each block up by `__typename`, renders unknown types as null,
|
|
10
|
-
* keys by the block `_id`, assigns LCP `priority` to the first block that
|
|
11
|
-
* actually renders, and threads a consumer-defined `Ctx` to every component.
|
|
12
|
-
*
|
|
13
|
-
* The "switch" is a typed object lookup. Exhaustiveness is enforced where the
|
|
14
|
-
* registry is BUILT — against the exhaustive `BlockRegistry` type the codegen
|
|
15
|
-
* plugin (EID-92) generates per project, so omitting a block type is a compile
|
|
16
|
-
* error there, not a runtime surprise here. The consumer can supply different
|
|
17
|
-
* registries per surface (e.g. web vs email).
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/** Minimal shape every block in a `flexible` field carries. */
|
|
21
|
-
interface BlockLike {
|
|
22
|
-
__typename: string;
|
|
23
|
-
_id?: string | null;
|
|
24
|
-
}
|
|
25
|
-
/** Props a block component receives from the content renderer. */
|
|
26
|
-
interface BlockComponentProps<TBlock, TCtx = unknown> {
|
|
27
|
-
block: TBlock;
|
|
28
|
-
/** Consumer-defined render context (host product, locale, etc.). */
|
|
29
|
-
ctx: TCtx;
|
|
30
|
-
/** True only for the first block that renders — the LCP candidate. */
|
|
31
|
-
priority: boolean;
|
|
32
|
-
}
|
|
33
|
-
/** A component that renders one block type. */
|
|
34
|
-
type BlockComponent<TBlock, TCtx = unknown> = (props: BlockComponentProps<TBlock, TCtx>) => ReactNode;
|
|
35
|
-
/**
|
|
36
|
-
* A registry mapping `__typename` → block component. In practice this is the
|
|
37
|
-
* exhaustive `BlockRegistry` type the codegen plugin emits for the project;
|
|
38
|
-
* here it's the structural lower bound the renderer needs.
|
|
39
|
-
*/
|
|
40
|
-
type BlockRegistry<TCtx = unknown> = Record<string, BlockComponent<any, TCtx>>;
|
|
41
|
-
interface ContentRendererProps<TCtx> {
|
|
42
|
-
blocks: readonly BlockLike[] | null | undefined;
|
|
43
|
-
/** Consumer-defined context passed to every block component. */
|
|
44
|
-
ctx: TCtx;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Build a `<ContentRenderer>` bound to a block registry. Returns a component
|
|
48
|
-
* that takes the `flexible` field's `blocks` array plus a `ctx`.
|
|
49
|
-
*/
|
|
50
|
-
declare function createContentRenderer<TCtx = unknown>(registry: BlockRegistry<TCtx>): (props: ContentRendererProps<TCtx>) => ReactNode;
|
|
51
|
-
|
|
52
|
-
/** A resolved typography token from the project's design tokens. */
|
|
53
|
-
interface TypographyToken {
|
|
54
|
-
/** Token key referenced by a Lexical node's `style`. */
|
|
55
|
-
name: string;
|
|
56
|
-
/** Rendered HTML element (paragraph / h1–h6 / blockquote). */
|
|
57
|
-
tag?: string;
|
|
58
|
-
value: {
|
|
59
|
-
fontFamily: string[];
|
|
60
|
-
fontSize: string | number;
|
|
61
|
-
fontWeight: string | number;
|
|
62
|
-
lineHeight: string | number;
|
|
63
|
-
letterSpacing: string | number;
|
|
64
|
-
textTransform?: string;
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Provide the project's resolved typography tokens to every nested
|
|
69
|
-
* `<RichTextRenderer>` so callers don't thread them through each usage. A
|
|
70
|
-
* `tokens` prop on the renderer still takes precedence.
|
|
71
|
-
*/
|
|
72
|
-
declare function RichTextTypographyProvider({ tokens, children, }: {
|
|
73
|
-
tokens: TypographyToken[];
|
|
74
|
-
children: ReactNode;
|
|
75
|
-
}): react_jsx_runtime.JSX.Element;
|
|
76
|
-
/** Read the injected typography tokens (null when no provider is mounted). */
|
|
77
|
-
declare function useRichTextTypography(): TypographyToken[] | null;
|
|
78
|
-
interface RichtextValueLike {
|
|
79
|
-
html?: string | null;
|
|
80
|
-
json?: unknown;
|
|
81
|
-
}
|
|
82
|
-
interface RichTextRendererProps {
|
|
83
|
-
value: RichtextValueLike | null | undefined;
|
|
84
|
-
className?: string;
|
|
85
|
-
/**
|
|
86
|
-
* Resolved typography tokens. Overrides any provided via
|
|
87
|
-
* `<RichTextTypographyProvider>`. When neither is set, paragraphs render
|
|
88
|
-
* with `fallbackTag` and no inline typography.
|
|
89
|
-
*/
|
|
90
|
-
tokens?: TypographyToken[];
|
|
91
|
-
/** Tag used for any paragraph with no token style and no Lexical tag. */
|
|
92
|
-
fallbackTag?: keyof JSX.IntrinsicElements;
|
|
93
|
-
}
|
|
94
|
-
declare function RichTextRenderer({ value, className, tokens, fallbackTag, }: RichTextRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
95
|
-
|
|
96
|
-
export { type BlockComponent, type BlockComponentProps, type BlockLike, type BlockRegistry, type ContentRendererProps, RichTextRenderer, type RichTextRendererProps, RichTextTypographyProvider, type TypographyToken, createContentRenderer, useRichTextTypography };
|