@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/README.md
CHANGED
|
@@ -24,6 +24,7 @@ pnpm add yjs y-websocket # for @foir/sdk/realtime
|
|
|
24
24
|
| --- | --- | --- |
|
|
25
25
|
| `@foir/sdk` | Editor iframe client — `EditorProvider`, `useEditor`, `useAutoResize`, `createPlatformClient`, host↔editor message protocol | `react` |
|
|
26
26
|
| `@foir/sdk/client` | Client-agnostic GraphQL transport for SSR/edge loaders — `foirRequest`, `isFoirPreview`, `absolutiseFoirMediaUrl` | `graphql` |
|
|
27
|
+
| `@foir/sdk/data` | Typed data client over `/graphql` — `createFoirClient`, per-key-shaped ops, `include`/`omit`, `fetchFoirManifest`; prints the document for you, so still no `graphql` | **none** |
|
|
27
28
|
| `@foir/sdk/auth` | Framework-agnostic customer auth — login/register/OTP/provider flows, token lifecycle (`SessionAdapter`), `createFoirSessionClient` (Foir-hosted cookie sessions), `authedRequest`, guards | `graphql` |
|
|
28
29
|
| `@foir/sdk/react` | Drop-in React auth — `<FoirProvider>` (token or `hostedSession` mode), `useFoirSession`/`useFoirUser`/`useFoirAuth`, `<SignIn>`, `<OAuthButtons>`, `<UserButton>` | `react`, `graphql` |
|
|
29
30
|
| `@foir/sdk/next` | Next.js App Router BFF auth — `createFoirCookieAdapter`, `getFoirSession`, `foirSignIn*`, `completeFoirProviderLogin`, `createFoirMiddleware` | `graphql` |
|
|
@@ -35,6 +36,99 @@ pnpm add yjs y-websocket # for @foir/sdk/realtime
|
|
|
35
36
|
|
|
36
37
|
## Usage
|
|
37
38
|
|
|
39
|
+
### Typed data client (no GraphQL, no codegen step)
|
|
40
|
+
|
|
41
|
+
`@foir/sdk/data` executes over the same `/graphql` endpoint every other consumer
|
|
42
|
+
uses — one execution surface, one executor, one set of scope checks, one response
|
|
43
|
+
cache. What you skip is writing the documents: the client loads the selection
|
|
44
|
+
tree `GET /v1/manifest` publishes for that op, applies your `include`/`omit`, and
|
|
45
|
+
prints one.
|
|
46
|
+
|
|
47
|
+
Printing a pre-resolved tree is string building, so the package still needs **no
|
|
48
|
+
`graphql` dependency at all** — no `graphql`, no
|
|
49
|
+
`@graphql-typed-document-node/core`, no `@graphql-codegen/*`, and no new peer.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { createFoirClient } from '@foir/sdk/data';
|
|
53
|
+
// generated by `foir types` from GET /v1/manifest
|
|
54
|
+
import * as generated from './foir.generated';
|
|
55
|
+
|
|
56
|
+
const foir = createFoirClient({
|
|
57
|
+
apiUrl: process.env.PLATFORM_API_URL!, // a bare origin or the /graphql URL
|
|
58
|
+
apiKey: process.env.PLATFORM_API_KEY!,
|
|
59
|
+
generated, // the whole module: types, trees, version
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const post = await foir.post.findUnique({
|
|
63
|
+
naturalKey: 'hello',
|
|
64
|
+
include: { author: true }, // relations opt in
|
|
65
|
+
omit: ['bodyRichtext'], // drop the heavy field
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const posts = await foir.post.findMany({ first: 10 }); // a Relay connection
|
|
69
|
+
const hits = await foir.ns.search.searchRecords({ query: 'shoes' });
|
|
70
|
+
const other = await foir.raw('{ designTokens { colors } }'); // any document, any root field
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**One import, no type parameter.** `generated` carries both halves of what
|
|
74
|
+
`foir types` writes — the `FoirSchema` type and the runtime selection trees the
|
|
75
|
+
documents are printed from — so `FoirSchema` is inferred rather than restated,
|
|
76
|
+
and an artifact added to the generator later costs your call site nothing. A
|
|
77
|
+
module missing one of those exports is a compile error naming it, not a quiet
|
|
78
|
+
degrade: pass it whole, or do not pass it.
|
|
79
|
+
|
|
80
|
+
The four fields it replaces (`schemaVersion`, `selections`,
|
|
81
|
+
`namespaceSelections`, `selectionUnions`) still work and still win where both
|
|
82
|
+
are given, so an existing client keeps compiling and behaving exactly as it did.
|
|
83
|
+
|
|
84
|
+
**Scalars are always complete**, so `post.title` is typed present and *is*
|
|
85
|
+
present — there is no partial-`select` footgun. `include` adds a relation key,
|
|
86
|
+
`omit` removes a scalar, and polymorphic fields are discriminated unions on
|
|
87
|
+
`__typename` that narrow under an exhaustive `switch` with no casts.
|
|
88
|
+
|
|
89
|
+
**The client is shaped by your credential.** The generated `FoirSchema` contains
|
|
90
|
+
only what that key's manifest lists, so a read-only `pk_` key has no `create` to
|
|
91
|
+
call:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
foir.post.create({ data }); // ✗ compile error under a pk_ key — not in its manifest
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`generated` is optional. Without it — and without `selections` — the client
|
|
98
|
+
fetches `GET /v1/manifest` once at first use and reads the same trees off it. A
|
|
99
|
+
fallback, so a zero-codegen start works, at the cost of a round trip in front of
|
|
100
|
+
the first query on every cold invocation. It says so, once, when it is built
|
|
101
|
+
that way; silence it with `announceManifestFallback: false`.
|
|
102
|
+
|
|
103
|
+
Reads that can be shared are sent to `GET /cdn/graphql` with only the
|
|
104
|
+
persisted-query hash in the URL, so a CDN in front of you can serve the next
|
|
105
|
+
visitor without reaching origin. That is a query, on a `pk_` key, with no
|
|
106
|
+
customer bearer, on the published channel; everything else is a `POST /graphql`.
|
|
107
|
+
|
|
108
|
+
`foir.raw()` is the escape hatch, and it takes a **GraphQL document** — it
|
|
109
|
+
reaches anything the credential can, including root fields no model or namespace
|
|
110
|
+
claims. It returns the whole `data` object.
|
|
111
|
+
|
|
112
|
+
Namespaces (`search`, `customers`, `notifications`) live under `foir.ns` because
|
|
113
|
+
the client carries no runtime schema to tell a namespace from a model. `ns` and
|
|
114
|
+
`raw` are the only reserved names.
|
|
115
|
+
|
|
116
|
+
Session-bound reads take a `bearerToken`, as a string or a function resolved per
|
|
117
|
+
request:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
const foir = createFoirClient({
|
|
121
|
+
apiUrl,
|
|
122
|
+
apiKey,
|
|
123
|
+
generated,
|
|
124
|
+
bearerToken: () => session.get('foir_access_token'),
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Already have `PLATFORM_API_URL` / `PLATFORM_API_KEY` / `FOIR_PREVIEW` wired for
|
|
129
|
+
the GraphQL path? `createFoirClientFromEnv(env, { generated })` reuses them,
|
|
130
|
+
including the preview `sk_` key and the draft schema channel.
|
|
131
|
+
|
|
38
132
|
### Typed GraphQL from a server loader
|
|
39
133
|
|
|
40
134
|
`foirRequest` is a typed `fetch` wrapper, not a GraphQL client: it carries the
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Foir customer auth — framework-agnostic flows, token lifecycle, and guards.
|
|
3
|
+
*
|
|
4
|
+
* Session I/O is injected via {@link SessionAdapter} (no Hydrogen/React-Router
|
|
5
|
+
* coupling). Pre-login flows authenticate with the project `x-api-key`;
|
|
6
|
+
* post-login reads add the customer bearer. The project-specific profile (e.g.
|
|
7
|
+
* `isAdmin`) is resolved by a consumer-supplied `resolveUser` — the SDK never
|
|
8
|
+
* hardcodes the per-project customer profile shape.
|
|
9
|
+
*
|
|
10
|
+
* TRANSPORT. Every flow below addresses the server's generated `auth` namespace
|
|
11
|
+
* through `./ops`, which is `@foir/sdk/data`'s op transport. This module holds
|
|
12
|
+
* no GraphQL documents and issues no requests of its own. What it does hold is
|
|
13
|
+
* the part a generated namespace does not give you and never could: where the
|
|
14
|
+
* tokens live, when they rotate, what a 401 means, and what to clear when a
|
|
15
|
+
* session ends.
|
|
16
|
+
*/
|
|
17
|
+
import { type FoirEnv } from '../graphql/foir-request';
|
|
18
|
+
import { type AuthOpName, type AuthOpOptions } from './ops';
|
|
19
|
+
import { type AuthConfig, type AuthProviderPublic, type CurrentUser, type CustomerAuthResult, type DefaultAuthProvider, type DeleteAccountResult, type ProviderCallbackInput, type ProviderLoginInput, type ProviderLoginResult, type ProviderOTPVerifyInput, type ProviderToken, type SignupContext, type WaitlistJoinResult } from './operations';
|
|
20
|
+
import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
|
|
21
|
+
/** An access token + its rotating refresh token. */
|
|
22
|
+
export interface FoirAuthTokens {
|
|
23
|
+
token: string;
|
|
24
|
+
refreshToken: string;
|
|
25
|
+
}
|
|
26
|
+
/** The customer identity carried by an auth result. */
|
|
27
|
+
export interface FoirCustomer {
|
|
28
|
+
id: string;
|
|
29
|
+
email: string;
|
|
30
|
+
}
|
|
31
|
+
/** The resolved customer for a guarded surface. */
|
|
32
|
+
export interface FoirUser {
|
|
33
|
+
id: string;
|
|
34
|
+
email: string;
|
|
35
|
+
isAdmin: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Injected session store. Methods may be sync or async so consumers can plug
|
|
39
|
+
* in a cookie session (Hydrogen/Remix), a KV store, etc.
|
|
40
|
+
*/
|
|
41
|
+
export interface SessionAdapter {
|
|
42
|
+
get(key: string): string | null | undefined | Promise<string | null | undefined>;
|
|
43
|
+
set(key: string, value: string): void | Promise<void>;
|
|
44
|
+
unset(key: string): void | Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
/** Login with email + password. Requires the project to have passwords enabled. */
|
|
47
|
+
export declare function customerLogin(env: FoirEnv, vars: {
|
|
48
|
+
email: string;
|
|
49
|
+
password: string;
|
|
50
|
+
}): Promise<CustomerAuthResult>;
|
|
51
|
+
/** Register a new customer with email + password. */
|
|
52
|
+
export declare function customerRegister(env: FoirEnv, vars: {
|
|
53
|
+
email: string;
|
|
54
|
+
password: string;
|
|
55
|
+
}): Promise<CustomerAuthResult>;
|
|
56
|
+
/** Request a one-time password be emailed to the customer. */
|
|
57
|
+
export declare function customerRequestOTP(env: FoirEnv, email: string): Promise<boolean>;
|
|
58
|
+
/** Complete an OTP login. */
|
|
59
|
+
export declare function customerLoginOTP(env: FoirEnv, vars: {
|
|
60
|
+
email: string;
|
|
61
|
+
otp: string;
|
|
62
|
+
}): Promise<CustomerAuthResult>;
|
|
63
|
+
/** Rotate an access token using a refresh token. */
|
|
64
|
+
export declare function customerRefreshToken(env: FoirEnv, refreshToken: string): Promise<CustomerAuthResult>;
|
|
65
|
+
/**
|
|
66
|
+
* Initiate provider (OAuth/OIDC) login — returns a `redirectUrl` to send the
|
|
67
|
+
* user to, or an inline `token` for non-redirect providers.
|
|
68
|
+
*/
|
|
69
|
+
export declare function customerLoginWithProvider(env: FoirEnv, input: ProviderLoginInput): Promise<ProviderLoginResult>;
|
|
70
|
+
/** Complete a provider login from the OAuth callback (`code`/`state`). */
|
|
71
|
+
export declare function customerProviderCallback(env: FoirEnv, input: ProviderCallbackInput): Promise<CustomerAuthResult>;
|
|
72
|
+
/** Verify an OTP issued by an external provider. */
|
|
73
|
+
export declare function customerProviderVerifyOTP(env: FoirEnv, input: ProviderOTPVerifyInput): Promise<CustomerAuthResult>;
|
|
74
|
+
/** List the project's configured auth providers (for a login UI). */
|
|
75
|
+
export declare function getAuthProviders(env: FoirEnv): Promise<AuthProviderPublic[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Read the project's public auth configuration — which built-in methods are
|
|
78
|
+
* enabled and which external providers to offer. This is what a login screen
|
|
79
|
+
* renders itself from, before any customer token exists.
|
|
80
|
+
*/
|
|
81
|
+
export declare function getAuthConfig(env: FoirEnv): Promise<AuthConfig>;
|
|
82
|
+
/**
|
|
83
|
+
* The provider a login screen should default to, or `null` when the project has
|
|
84
|
+
* configured none.
|
|
85
|
+
*/
|
|
86
|
+
export declare function getDefaultAuthProvider(env: FoirEnv): Promise<DefaultAuthProvider | null>;
|
|
87
|
+
/**
|
|
88
|
+
* Read the project's customer signup mode (public/restricted/waitlist/closed)
|
|
89
|
+
* so a self-hosted frontend can render the right signup surface proactively.
|
|
90
|
+
*/
|
|
91
|
+
export declare function customerSignupContext(env: FoirEnv): Promise<SignupContext>;
|
|
92
|
+
/** Join the project's signup waitlist. The project must be in waitlist mode. */
|
|
93
|
+
export declare function customerJoinWaitlist(env: FoirEnv, email: string): Promise<WaitlistJoinResult>;
|
|
94
|
+
/**
|
|
95
|
+
* Send a password-reset email. Resolves `true` whether or not the address has
|
|
96
|
+
* an account: the server answers identically either way, on purpose, so this
|
|
97
|
+
* endpoint cannot be used to test whether someone has signed up.
|
|
98
|
+
*/
|
|
99
|
+
export declare function customerRequestPasswordReset(env: FoirEnv, email: string): Promise<boolean>;
|
|
100
|
+
/**
|
|
101
|
+
* Redeem an emailed reset token and set a new password. Returns a fresh session
|
|
102
|
+
* — resetting a password signs the customer in — so pair it with
|
|
103
|
+
* {@link saveSession}, or use {@link resetPasswordAndSignIn} which does both.
|
|
104
|
+
*/
|
|
105
|
+
export declare function customerResetPassword(env: FoirEnv, vars: {
|
|
106
|
+
token: string;
|
|
107
|
+
newPassword: string;
|
|
108
|
+
}): Promise<CustomerAuthResult>;
|
|
109
|
+
/** Redeem an emailed verification token. */
|
|
110
|
+
export declare function customerVerifyEmail(env: FoirEnv, token: string): Promise<boolean>;
|
|
111
|
+
/**
|
|
112
|
+
* Change the calling customer's password. Requires the current password as well
|
|
113
|
+
* as the bearer, so a stolen token alone cannot take the account over.
|
|
114
|
+
*/
|
|
115
|
+
export declare function customerUpdatePassword(env: FoirEnv, vars: {
|
|
116
|
+
currentPassword: string;
|
|
117
|
+
newPassword: string;
|
|
118
|
+
}, options?: AuthOpOptions): Promise<boolean>;
|
|
119
|
+
/**
|
|
120
|
+
* The calling customer, or `null` when the request carried no customer token.
|
|
121
|
+
* An absent session is an answer rather than a failure, so this does not throw.
|
|
122
|
+
*/
|
|
123
|
+
export declare function currentUser(env: FoirEnv, options?: AuthOpOptions): Promise<CurrentUser | null>;
|
|
124
|
+
/**
|
|
125
|
+
* The stored upstream provider token for the calling customer, refreshed
|
|
126
|
+
* transparently by the server when it has expired. `null` when there is no
|
|
127
|
+
* customer token on the request or none stored for that provider.
|
|
128
|
+
*/
|
|
129
|
+
export declare function myProviderToken(env: FoirEnv, providerKey: string, options?: AuthOpOptions): Promise<ProviderToken | null>;
|
|
130
|
+
/**
|
|
131
|
+
* End the session server-side, revoking stored provider tokens. This does NOT
|
|
132
|
+
* clear local session state — {@link signOut} is the pairing that does both.
|
|
133
|
+
*/
|
|
134
|
+
export declare function customerLogout(env: FoirEnv, options?: AuthOpOptions): Promise<boolean>;
|
|
135
|
+
/**
|
|
136
|
+
* Delete the calling customer's account and their owned records and files.
|
|
137
|
+
* Irreversible. `password` is required for password accounts and omitted for
|
|
138
|
+
* provider-only ones; the server enforces the actual re-auth gate and fails
|
|
139
|
+
* closed, so omitting it is refused rather than allowed.
|
|
140
|
+
*/
|
|
141
|
+
export declare function deleteMyAccount(env: FoirEnv, vars: {
|
|
142
|
+
confirm: boolean;
|
|
143
|
+
password?: string;
|
|
144
|
+
}, options?: AuthOpOptions): Promise<DeleteAccountResult>;
|
|
145
|
+
/** Persist an auth result to the session; returns the customer identity. */
|
|
146
|
+
export declare function saveSession(adapter: SessionAdapter, result: CustomerAuthResult): Promise<FoirCustomer>;
|
|
147
|
+
/** Clear all Foir auth keys from the session. */
|
|
148
|
+
export declare function clearSession(adapter: SessionAdapter): Promise<void>;
|
|
149
|
+
/** Read the stored access token (null when signed out). */
|
|
150
|
+
export declare function getSessionToken(adapter: SessionAdapter): Promise<string | null>;
|
|
151
|
+
/** Read the stored customer identity (null when signed out). */
|
|
152
|
+
export declare function getSessionCustomer(adapter: SessionAdapter): Promise<FoirCustomer | null>;
|
|
153
|
+
/** Login with email + password and persist the session. */
|
|
154
|
+
export declare function loginWithPassword(adapter: SessionAdapter, env: FoirEnv, vars: {
|
|
155
|
+
email: string;
|
|
156
|
+
password: string;
|
|
157
|
+
}): Promise<FoirCustomer>;
|
|
158
|
+
/** Register with email + password and persist the session. */
|
|
159
|
+
export declare function registerWithPassword(adapter: SessionAdapter, env: FoirEnv, vars: {
|
|
160
|
+
email: string;
|
|
161
|
+
password: string;
|
|
162
|
+
}): Promise<FoirCustomer>;
|
|
163
|
+
/** Complete an OTP login and persist the session. */
|
|
164
|
+
export declare function loginWithOTP(adapter: SessionAdapter, env: FoirEnv, vars: {
|
|
165
|
+
email: string;
|
|
166
|
+
otp: string;
|
|
167
|
+
}): Promise<FoirCustomer>;
|
|
168
|
+
/**
|
|
169
|
+
* Complete a forgot-password flow: redeem the emailed token, set the new
|
|
170
|
+
* password, and persist the session the server mints. The peer of
|
|
171
|
+
* {@link loginWithPassword} for the branch where the customer cannot log in.
|
|
172
|
+
*/
|
|
173
|
+
export declare function resetPasswordAndSignIn(adapter: SessionAdapter, env: FoirEnv, vars: {
|
|
174
|
+
token: string;
|
|
175
|
+
newPassword: string;
|
|
176
|
+
}): Promise<FoirCustomer>;
|
|
177
|
+
/**
|
|
178
|
+
* End the session on both sides: revoke it server-side, then clear local state.
|
|
179
|
+
*
|
|
180
|
+
* The local clear happens even when the server call fails. A customer who
|
|
181
|
+
* pressed sign-out and got a network error must not be left holding a session
|
|
182
|
+
* on the device in front of them — the token expires on its own, and the
|
|
183
|
+
* failure mode of clearing anyway (one orphaned provider token) is strictly
|
|
184
|
+
* better than the failure mode of not (a signed-in browser the user believes is
|
|
185
|
+
* signed out).
|
|
186
|
+
*/
|
|
187
|
+
export declare function signOut(adapter: SessionAdapter, env: FoirEnv): Promise<void>;
|
|
188
|
+
/**
|
|
189
|
+
* Refresh the access token from the stored refresh token, persisting the
|
|
190
|
+
* rotated pair. Returns the new tokens, or null when there's no refresh token
|
|
191
|
+
* or the refresh fails (the session is cleared in that case).
|
|
192
|
+
*/
|
|
193
|
+
export declare function refreshSession(adapter: SessionAdapter, env: FoirEnv): Promise<FoirAuthTokens | null>;
|
|
194
|
+
/**
|
|
195
|
+
* Run a bearer-authed GraphQL operation with refresh-with-retry: uses the
|
|
196
|
+
* stored access token, and on a 401-shaped failure (rejected/expired bearer)
|
|
197
|
+
* attempts a single token refresh and retries once. Any other error — network
|
|
198
|
+
* blips, server errors, validation — propagates without a retry so transient
|
|
199
|
+
* mutation failures can't be duplicated. Throws the original error if there's
|
|
200
|
+
* no refresh path.
|
|
201
|
+
*/
|
|
202
|
+
export declare function authedRequest<TData, TVariables>(adapter: SessionAdapter, env: FoirEnv, document: TypedDocumentNode<TData, TVariables>, variables?: TVariables): Promise<TData>;
|
|
203
|
+
/**
|
|
204
|
+
* {@link authedRequest}'s twin for the generated `auth` namespace: run a
|
|
205
|
+
* post-credential auth op with the stored access token, refreshing once and
|
|
206
|
+
* retrying once on a 401-shaped failure.
|
|
207
|
+
*
|
|
208
|
+
* The two exist side by side because they serve different documents, not
|
|
209
|
+
* different transports. `authedRequest` runs the CONSUMER's document — the
|
|
210
|
+
* project's own `myProfile` and friends, whose shape the SDK cannot know — and
|
|
211
|
+
* this runs a root field the server generated. Refresh-with-retry is the same
|
|
212
|
+
* behaviour in both, and it is the reason either is worth having: it is session
|
|
213
|
+
* management, which is the half a generated namespace does not give you.
|
|
214
|
+
*/
|
|
215
|
+
export declare function authedOp<T>(adapter: SessionAdapter, env: FoirEnv, op: AuthOpName, args?: Record<string, unknown>): Promise<T>;
|
|
216
|
+
export interface RequireAuthOptions {
|
|
217
|
+
/**
|
|
218
|
+
* Resolve the full {@link FoirUser} (including the project-specific
|
|
219
|
+
* `isAdmin`) from the session identity. Typically runs the project's
|
|
220
|
+
* `myProfile` query via {@link authedRequest}. Defaults to `isAdmin: false`.
|
|
221
|
+
*/
|
|
222
|
+
resolveUser?: (ctx: {
|
|
223
|
+
token: string;
|
|
224
|
+
customer: FoirCustomer;
|
|
225
|
+
}) => FoirUser | Promise<FoirUser>;
|
|
226
|
+
/**
|
|
227
|
+
* Called when there's no valid session — throw your framework's redirect
|
|
228
|
+
* (e.g. `throw redirect(loginUrl)`). Must not return.
|
|
229
|
+
*/
|
|
230
|
+
onUnauthenticated: () => never | Promise<never>;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Require a signed-in customer. Resolves the {@link FoirUser} via
|
|
234
|
+
* `resolveUser` (or a minimal identity), or invokes `onUnauthenticated` when
|
|
235
|
+
* there's no session.
|
|
236
|
+
*/
|
|
237
|
+
export declare function requireAuth(adapter: SessionAdapter, options: RequireAuthOptions): Promise<FoirUser>;
|
|
238
|
+
export interface RequireAdminOptions extends RequireAuthOptions {
|
|
239
|
+
/** Called when the user is authenticated but not an admin. Must not return. */
|
|
240
|
+
onForbidden: () => never | Promise<never>;
|
|
241
|
+
}
|
|
242
|
+
/** Require a signed-in customer who is also an admin. */
|
|
243
|
+
export declare function requireAdmin(adapter: SessionAdapter, options: RequireAdminOptions): Promise<FoirUser>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hosted-login bridge — for storefronts that delegate sign-in to a Foir
|
|
3
|
+
* white-label front door (the `customerLoginWithFoir` flow) instead of
|
|
4
|
+
* rendering their own login UI.
|
|
5
|
+
*
|
|
6
|
+
* The front door sets a first-party session cookie on the registrable domain;
|
|
7
|
+
* because that domain is shared, the cookie reaches the storefront, which
|
|
8
|
+
* exchanges it server-side for a short-lived customer bearer + identity. The
|
|
9
|
+
* cookie is the durable credential (re-exchanged on bearer expiry) — there's
|
|
10
|
+
* no separate refresh token in this flow.
|
|
11
|
+
*
|
|
12
|
+
* Every URL/cookie/path is CONFIG, not a constant, so a domain restructure
|
|
13
|
+
* is a config change, not a code change.
|
|
14
|
+
*/
|
|
15
|
+
export interface HostedLoginConfig {
|
|
16
|
+
/** White-label front-door origin, e.g. `https://login.example.com`. */
|
|
17
|
+
loginOrigin: string;
|
|
18
|
+
/** Session cookie name set on the registrable domain. Default `foir_customer_session`. */
|
|
19
|
+
cookieName?: string;
|
|
20
|
+
/** Session-exchange path on the front door. Default `/session/token`. */
|
|
21
|
+
sessionPath?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Build the redirect URL to the hosted front door, forwarding a best-effort
|
|
25
|
+
* absolute `returnTo` (honoured if the front door supports it).
|
|
26
|
+
*/
|
|
27
|
+
export declare function hostedLoginUrl(config: HostedLoginConfig, returnTo?: string): string;
|
|
28
|
+
/** The identity + bearer returned by a successful hosted-session exchange. */
|
|
29
|
+
export interface HostedSession {
|
|
30
|
+
token: string;
|
|
31
|
+
customerId: string;
|
|
32
|
+
email: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Exchange the hosted-login cookie on an incoming request for a customer
|
|
36
|
+
* bearer + identity (server-to-server: forwards the cookie to the front
|
|
37
|
+
* door's session endpoint with the CSRF header). Returns null when there's no
|
|
38
|
+
* cookie or it's expired/revoked.
|
|
39
|
+
*/
|
|
40
|
+
export declare function fetchHostedSession(request: Request, config: HostedLoginConfig): Promise<HostedSession | null>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@foir/sdk/auth` — framework-agnostic Foir customer auth.
|
|
3
|
+
*
|
|
4
|
+
* The whole customer auth surface — login, register, OTP, external providers,
|
|
5
|
+
* refresh, password management, email verification and account deletion — over
|
|
6
|
+
* the server's generated `auth` namespace, plus token lifecycle with an
|
|
7
|
+
* injected `SessionAdapter`, guards, and the optional hosted-login bridge.
|
|
8
|
+
*
|
|
9
|
+
* There are no operation documents here any more. The flows address root fields
|
|
10
|
+
* the caller's own manifest advertises, through the same op transport
|
|
11
|
+
* `@foir/sdk/data` uses, so `graphql` is not on this module's path at all.
|
|
12
|
+
*/
|
|
13
|
+
export { customerLogin, customerRegister, customerRequestOTP, customerLoginOTP, customerRefreshToken, customerLoginWithProvider, customerProviderCallback, customerProviderVerifyOTP, getAuthProviders, getAuthConfig, getDefaultAuthProvider, customerSignupContext, customerJoinWaitlist, customerRequestPasswordReset, customerResetPassword, customerUpdatePassword, customerVerifyEmail, currentUser, myProviderToken, customerLogout, deleteMyAccount, saveSession, clearSession, getSessionToken, getSessionCustomer, loginWithPassword, registerWithPassword, loginWithOTP, resetPasswordAndSignIn, refreshSession, signOut, authedRequest, authedOp, requireAuth, requireAdmin, } from './auth';
|
|
14
|
+
export type { FoirAuthTokens, FoirCustomer, FoirUser, SessionAdapter, RequireAuthOptions, RequireAdminOptions, } from './auth';
|
|
15
|
+
export { AUTH_OPS } from './ops';
|
|
16
|
+
export type { AuthOpName, AuthOpOptions } from './ops';
|
|
17
|
+
export { hostedLoginUrl, fetchHostedSession } from './hosted';
|
|
18
|
+
export type { HostedLoginConfig, HostedSession } from './hosted';
|
|
19
|
+
export { createFoirSessionClient } from './session-client';
|
|
20
|
+
export type { FoirSessionClient, FoirSessionConfig, FoirSessionUser, } from './session-client';
|
|
21
|
+
export type { CustomerAuthResult, ProviderLoginResult, AuthProviderPublic, ProviderLoginInput, ProviderCallbackInput, ProviderOTPVerifyInput, SignupContext, SignupMode, WaitlistJoinResult, AuthConfig, AuthConfigProvider, DefaultAuthProvider, CurrentUser, ProviderToken, DeleteAccountResult, } from './operations';
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Foir customer-auth result and input types.
|
|
3
|
+
*
|
|
4
|
+
* These are PLATFORM-STABLE primitives — login / register / refresh / OTP /
|
|
5
|
+
* provider login / password management / account lifecycle are fixed-shape
|
|
6
|
+
* operations served by api-public for every project (gated per-project by the
|
|
7
|
+
* password / OTP / provider flags, but identical in shape when present). Unlike
|
|
8
|
+
* per-project model types they do not vary by configured models, so the SDK
|
|
9
|
+
* owns these declarations directly rather than relying on the consumer's
|
|
10
|
+
* codegen.
|
|
11
|
+
*
|
|
12
|
+
* WHAT USED TO BE HERE. This file also held eleven hand-written GraphQL
|
|
13
|
+
* documents, `parse()`d at module load. They are gone. Every flow in `./auth`
|
|
14
|
+
* now addresses the server's generated `auth` namespace through the same op
|
|
15
|
+
* transport `@foir/sdk/data` uses, so the SDK has one execution surface rather
|
|
16
|
+
* than a private one for auth and a shared one for everything else. Two
|
|
17
|
+
* consequences worth knowing:
|
|
18
|
+
*
|
|
19
|
+
* - the shapes below are no longer a document's selection set. They describe
|
|
20
|
+
* what the server's own payload writer selects for these fields, which is
|
|
21
|
+
* every scalar the type has. `authNamespaceOpShapes` in `./ops` is the
|
|
22
|
+
* machine-checked version of that sentence.
|
|
23
|
+
* - `graphql` is no longer imported here, or anywhere under `./auth`'s flow
|
|
24
|
+
* path. The top-level `parse()` calls were what no bundler could shake out,
|
|
25
|
+
* and they are the reason `@foir/sdk/auth/session` had to exist as a
|
|
26
|
+
* separate graphql-free door.
|
|
27
|
+
*
|
|
28
|
+
* The project-specific customer PROFILE (e.g. `myProfile.isAdmin`) is still NOT
|
|
29
|
+
* here — that shape varies per project, so it stays consumer-injected (see
|
|
30
|
+
* `requireAuth`'s `resolveUser`).
|
|
31
|
+
*/
|
|
32
|
+
/** The common auth result every login/register/refresh mutation returns. */
|
|
33
|
+
export interface CustomerAuthResult {
|
|
34
|
+
token: string;
|
|
35
|
+
refreshToken: string;
|
|
36
|
+
customerId: string;
|
|
37
|
+
email: string;
|
|
38
|
+
}
|
|
39
|
+
/** Result of initiating a provider login — a redirect URL or an inline token. */
|
|
40
|
+
export interface ProviderLoginResult {
|
|
41
|
+
/** OAuth/OIDC authorization URL to redirect the user to (redirect flows). */
|
|
42
|
+
redirectUrl: string | null;
|
|
43
|
+
/** Inline access token (non-redirect provider flows). */
|
|
44
|
+
token: string | null;
|
|
45
|
+
}
|
|
46
|
+
/** A configured auth provider, as exposed to unauthenticated callers. */
|
|
47
|
+
export interface AuthProviderPublic {
|
|
48
|
+
key: string;
|
|
49
|
+
name: string;
|
|
50
|
+
/** OAUTH2 | TOKEN_SSO | SAML | OIDC | EXTERNAL */
|
|
51
|
+
type: string;
|
|
52
|
+
isDefault: boolean | null;
|
|
53
|
+
}
|
|
54
|
+
export interface ProviderLoginInput {
|
|
55
|
+
providerKey: string;
|
|
56
|
+
email?: string;
|
|
57
|
+
returnTo?: string;
|
|
58
|
+
/** Override the provider's default redirect_uri (must be allow-listed). */
|
|
59
|
+
redirectUri?: string;
|
|
60
|
+
}
|
|
61
|
+
export interface ProviderCallbackInput {
|
|
62
|
+
providerKey: string;
|
|
63
|
+
code?: string;
|
|
64
|
+
state?: string;
|
|
65
|
+
email?: string;
|
|
66
|
+
idToken?: string;
|
|
67
|
+
}
|
|
68
|
+
export interface ProviderOTPVerifyInput {
|
|
69
|
+
providerKey: string;
|
|
70
|
+
email: string;
|
|
71
|
+
otp: string;
|
|
72
|
+
}
|
|
73
|
+
/** The project's customer signup mode. */
|
|
74
|
+
export type SignupMode = 'PUBLIC' | 'RESTRICTED' | 'WAITLIST' | 'CLOSED';
|
|
75
|
+
/** The signup surface a self-hosted frontend reads to render the right UI. */
|
|
76
|
+
export interface SignupContext {
|
|
77
|
+
signupMode: SignupMode;
|
|
78
|
+
}
|
|
79
|
+
/** The queued (or existing pending) entry a waitlist join returns. */
|
|
80
|
+
export interface WaitlistJoinResult {
|
|
81
|
+
id: string;
|
|
82
|
+
email: string;
|
|
83
|
+
/** Waitlist lifecycle status; PENDING on a fresh join. */
|
|
84
|
+
status: string;
|
|
85
|
+
}
|
|
86
|
+
/** One provider as it appears inside {@link AuthConfig}. */
|
|
87
|
+
export interface AuthConfigProvider {
|
|
88
|
+
key: string;
|
|
89
|
+
name: string;
|
|
90
|
+
/** OAUTH2 | TOKEN_SSO | SAML | OIDC | EXTERNAL */
|
|
91
|
+
type: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The project's public auth configuration: which built-in methods are on, and
|
|
95
|
+
* which external providers a login screen should offer. Readable before any
|
|
96
|
+
* customer token exists — it is what a login screen renders itself from.
|
|
97
|
+
*/
|
|
98
|
+
export interface AuthConfig {
|
|
99
|
+
passwordEnabled: boolean;
|
|
100
|
+
otpEnabled: boolean;
|
|
101
|
+
providers: AuthConfigProvider[] | null;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The provider a login screen should default to, or `null` when the project has
|
|
105
|
+
* configured none.
|
|
106
|
+
*/
|
|
107
|
+
export interface DefaultAuthProvider {
|
|
108
|
+
key: string | null;
|
|
109
|
+
name: string | null;
|
|
110
|
+
type: string | null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The calling customer, resolved from the bearer token. `null` when the request
|
|
114
|
+
* carried no customer token — an absent session is an answer, not a failure.
|
|
115
|
+
*/
|
|
116
|
+
export interface CurrentUser {
|
|
117
|
+
id: string;
|
|
118
|
+
email: string;
|
|
119
|
+
/** ACTIVE | PENDING | SUSPENDED | … */
|
|
120
|
+
status: string;
|
|
121
|
+
/** ISO-8601, or null when the address is unverified. */
|
|
122
|
+
emailVerifiedAt: string | null;
|
|
123
|
+
/** ISO-8601. */
|
|
124
|
+
createdAt: string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* A stored upstream provider token for the calling customer. `null` when there
|
|
128
|
+
* is no customer token on the request, or none stored for that provider.
|
|
129
|
+
*/
|
|
130
|
+
export interface ProviderToken {
|
|
131
|
+
providerKey: string;
|
|
132
|
+
accessToken: string;
|
|
133
|
+
refreshToken: string | null;
|
|
134
|
+
/** ISO-8601. */
|
|
135
|
+
expiresAt: string | null;
|
|
136
|
+
/** Space-separated provider scopes, as the provider issued them. */
|
|
137
|
+
scopes: string | null;
|
|
138
|
+
}
|
|
139
|
+
/** What a self-serve account deletion removed. */
|
|
140
|
+
export interface DeleteAccountResult {
|
|
141
|
+
success: boolean;
|
|
142
|
+
recordsDeleted: number;
|
|
143
|
+
filesDeleted: number;
|
|
144
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The auth client's execution path: the server's generated `auth` namespace.
|
|
3
|
+
*
|
|
4
|
+
* `@foir/sdk/auth` used to carry its own transport — eleven hand-written
|
|
5
|
+
* GraphQL documents `parse()`d at module load and posted to `/graphql`. That was
|
|
6
|
+
* a second wire protocol for one substrate inside one package, and it had the
|
|
7
|
+
* cost such things always have: the hand-written set covered nine of the
|
|
8
|
+
* surface's root fields and the other eleven — the whole of password
|
|
9
|
+
* management, email verification and account deletion — were reachable nowhere
|
|
10
|
+
* in the SDK, so "forgot password" meant dropping to hand-written GraphQL.
|
|
11
|
+
*
|
|
12
|
+
* Now every flow addresses a root field the caller's own manifest advertises,
|
|
13
|
+
* printed and executed by the same functions `@foir/sdk/data` runs every model
|
|
14
|
+
* op through. ONE transport, and the auth client's remaining job is the half
|
|
15
|
+
* that was always the hard part: token storage, refresh, redirects and the
|
|
16
|
+
* React context.
|
|
17
|
+
*
|
|
18
|
+
* WHAT THIS FILE IS NOT. It is not a schema. It names root fields and nothing
|
|
19
|
+
* else — no types, no selection sets, no argument coercion. The SHAPE of what an
|
|
20
|
+
* op selects comes from `namespaces.auth.ops.<op>.payload` in the caller's own
|
|
21
|
+
* manifest, and the argument types from `argTypes` beside it; if this file ever
|
|
22
|
+
* needed to know a field's type itself, the op vocabulary would be
|
|
23
|
+
* under-specified and the fix would belong on the server.
|
|
24
|
+
*
|
|
25
|
+
* ORDERING, and it is load-bearing: these ops resolve against the manifest the
|
|
26
|
+
* deployed api-public serves. A server that does not publish per-op payloads for
|
|
27
|
+
* the `auth` namespace answers every op below with a refusal naming the op. The
|
|
28
|
+
* server half ships first.
|
|
29
|
+
*/
|
|
30
|
+
import { type FoirEnv } from '../transport/foir-http';
|
|
31
|
+
/**
|
|
32
|
+
* The `auth` namespace's root field names, as the manifest lists them.
|
|
33
|
+
*
|
|
34
|
+
* Written out rather than derived so a typo is a compile error at the call site
|
|
35
|
+
* instead of a 400 at runtime, and so this file is the one place to read what
|
|
36
|
+
* the auth client addresses. The names are the server's, unmodified — the op
|
|
37
|
+
* vocabulary for every namespace except `operations` IS the root field name, so
|
|
38
|
+
* nothing here is constructed and nothing can drift into a different name.
|
|
39
|
+
*/
|
|
40
|
+
export declare const AUTH_OPS: {
|
|
41
|
+
readonly authConfig: "authConfig";
|
|
42
|
+
readonly authProviders: "authProviders";
|
|
43
|
+
readonly defaultAuthProvider: "defaultAuthProvider";
|
|
44
|
+
readonly customerSignupContext: "customerSignupContext";
|
|
45
|
+
readonly currentUser: "currentUser";
|
|
46
|
+
readonly myProviderToken: "myProviderToken";
|
|
47
|
+
readonly customerLogin: "customerLogin";
|
|
48
|
+
readonly customerRegister: "customerRegister";
|
|
49
|
+
readonly customerRequestOTP: "customerRequestOTP";
|
|
50
|
+
readonly customerLoginOTP: "customerLoginOTP";
|
|
51
|
+
readonly customerRefreshToken: "customerRefreshToken";
|
|
52
|
+
readonly customerLogout: "customerLogout";
|
|
53
|
+
readonly customerJoinWaitlist: "customerJoinWaitlist";
|
|
54
|
+
readonly customerRequestPasswordReset: "customerRequestPasswordReset";
|
|
55
|
+
readonly customerResetPassword: "customerResetPassword";
|
|
56
|
+
readonly customerUpdatePassword: "customerUpdatePassword";
|
|
57
|
+
readonly customerVerifyEmail: "customerVerifyEmail";
|
|
58
|
+
readonly deleteMyAccount: "deleteMyAccount";
|
|
59
|
+
readonly customerLoginWithProvider: "customerLoginWithProvider";
|
|
60
|
+
readonly customerProviderCallback: "customerProviderCallback";
|
|
61
|
+
readonly customerProviderVerifyOTP: "customerProviderVerifyOTP";
|
|
62
|
+
};
|
|
63
|
+
/** One of the auth namespace's root field names. */
|
|
64
|
+
export type AuthOpName = (typeof AUTH_OPS)[keyof typeof AUTH_OPS];
|
|
65
|
+
/** Per-call overrides for an auth op. */
|
|
66
|
+
export interface AuthOpOptions {
|
|
67
|
+
/**
|
|
68
|
+
* Customer bearer token. api-public still needs the `x-api-key` to resolve
|
|
69
|
+
* the project; the bearer adds the customer identity the post-credential ops
|
|
70
|
+
* (`currentUser`, `customerUpdatePassword`, `deleteMyAccount`, …) are
|
|
71
|
+
* authorised by. Ignored by the pre-credential ops, which mint it.
|
|
72
|
+
*/
|
|
73
|
+
bearerToken?: string;
|
|
74
|
+
/**
|
|
75
|
+
* `fetch` implementation. Defaults to `globalThis.fetch`. Injectable for
|
|
76
|
+
* tests and for runtimes that hand you a bound `fetch` (Hydrogen/Oxygen).
|
|
77
|
+
*/
|
|
78
|
+
fetch?: typeof globalThis.fetch;
|
|
79
|
+
/** Extra headers, applied last so they can override the ones above. */
|
|
80
|
+
headers?: Readonly<Record<string, string>>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Forget every memoised descriptor.
|
|
84
|
+
*
|
|
85
|
+
* For tests and for a long-lived process that has rotated a key. Not part of a
|
|
86
|
+
* normal flow — the descriptor is refetched on schema change by the drift check
|
|
87
|
+
* on the data client, and auth ops are not where that is noticed.
|
|
88
|
+
*/
|
|
89
|
+
export declare function clearAuthManifestCache(): void;
|
|
90
|
+
/**
|
|
91
|
+
* Execute one auth op and return the root field's value.
|
|
92
|
+
*
|
|
93
|
+
* Arguments are sent as GraphQL variables, typed from the op's published
|
|
94
|
+
* `argTypes`. `undefined` entries are dropped rather than sent as null: a
|
|
95
|
+
* GraphQL argument that is absent and one that is explicitly null mean different
|
|
96
|
+
* things to the resolvers below (`deleteMyAccount`'s optional `password` is the
|
|
97
|
+
* live example).
|
|
98
|
+
*/
|
|
99
|
+
export declare function authOp<T>(env: FoirEnv, op: AuthOpName, args?: Record<string, unknown>, options?: AuthOpOptions): Promise<T>;
|