@foir/sdk 0.22.0 → 0.23.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 +51 -0
- package/README.md +6 -6
- package/dist/app/client.d.ts +5 -4
- package/dist/app/errors.d.ts +8 -6
- package/dist/auth/auth.d.ts +41 -9
- package/dist/auth/grant-table.generated.d.ts +5 -4
- package/dist/auth/hosted.d.ts +24 -0
- package/dist/auth/index.d.ts +4 -4
- package/dist/auth/operations.d.ts +28 -4
- package/dist/auth.js +174 -123
- package/dist/client.js +1 -4
- package/dist/codegen/preset.d.ts +1 -1
- package/dist/data/client.d.ts +1 -1
- package/dist/data/schema.d.ts +1 -1
- package/dist/data/transport.d.ts +7 -6
- package/dist/data.js +2 -5
- package/dist/index.js +1 -4
- package/dist/next.js +1 -4
- package/dist/placement.js +124 -116
- package/dist/push.js +1 -4
- package/dist/react/FoirProvider.d.ts +1 -1
- package/dist/react/feedback-notes.d.ts +4 -2
- package/dist/react.js +125 -120
- package/dist/server/events-client.d.ts +7 -7
- package/dist/server/types.d.ts +1 -1
- package/dist/server.js +121 -120
- package/dist/transport/foir-http.d.ts +1 -1
- package/dist/transport/key-kind.d.ts +1 -12
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -108,6 +108,57 @@ nobody asking for `@foir/sdk` gets it early. The push that carries the commit to
|
|
|
108
108
|
|
|
109
109
|
Changes on `dev` that have not been published to npm.
|
|
110
110
|
|
|
111
|
+
## [0.23.0] — 2026-10-16
|
|
112
|
+
|
|
113
|
+
### Added
|
|
114
|
+
|
|
115
|
+
- **`signInRefusalOf(error)`** (`@foir/sdk/auth`) reads why a sign-in your app's
|
|
116
|
+
own form sent was refused, as a stable code: `password_sign_in_off` from
|
|
117
|
+
`login` or `register` where the project, or the app the sign-in came through,
|
|
118
|
+
takes no password, and `code_sign_in_off` from `requestOTP` or `loginWithOTP`
|
|
119
|
+
where it takes no code. Null for any other failure.
|
|
120
|
+
- **`hostedSignInNoticeOf` reads what the hosted login sent back** (`@foir/sdk/auth`).
|
|
121
|
+
A refused sign-in's `foir_error` code, or the provider a sign-in connected to
|
|
122
|
+
the account (`foir_connected`), each with a sentence your app can show as it
|
|
123
|
+
is. A code it has no words for reads as a general sentence, never the code.
|
|
124
|
+
- **`myProviderToken` says what it did about the token** (`@foir/sdk/auth`).
|
|
125
|
+
`refresh` is `REFRESHED`, `FAILED` (with `refreshFailure` saying where),
|
|
126
|
+
`HELD_BACK` or `NOT_ATTEMPTED`; `reauthenticate` is true when only signing in
|
|
127
|
+
with the provider again mends the connection; and `linked: false` answers a
|
|
128
|
+
signed-in user with nothing stored for the provider. Pass `forceRefresh`
|
|
129
|
+
after the provider refused the token it was given. A token whose provider
|
|
130
|
+
stated no expiry is now renewed when read, and two reads at once renew it
|
|
131
|
+
once. New type: `ProviderTokenRefresh`.
|
|
132
|
+
- **`requestPasswordReset` takes a `clientId`** (`@foir/sdk/auth`). Where the
|
|
133
|
+
project has no App base URL, the reset email links to Foir's hosted reset
|
|
134
|
+
page, and naming your app sends the user to its initiate login URL to sign in
|
|
135
|
+
once the password is changed.
|
|
136
|
+
- **`registerOrganization` takes an `appBaseUrl`** (`@foir/sdk/auth`), so an
|
|
137
|
+
organization a user founds has its address from the first request and an app
|
|
138
|
+
that finds its organization by `orgUrl` finds this one at once. The address
|
|
139
|
+
sits under the project's own app address or a domain it verified, and one
|
|
140
|
+
another organization holds is refused.
|
|
141
|
+
|
|
142
|
+
### Changed
|
|
143
|
+
|
|
144
|
+
- **Breaking: `myOrganizations` pages from an entry's `cursor`** (`@foir/sdk/auth`).
|
|
145
|
+
Each `MyOrganization` it lists carries `cursor`; pass the last one's as
|
|
146
|
+
`after` for the next page. `after` no longer takes an organization's id. A
|
|
147
|
+
user whose role holds `organizations:read` in the project is listed every
|
|
148
|
+
organization of it, suspended ones included.
|
|
149
|
+
|
|
150
|
+
- **`ProviderToken.accessToken` may be `null`**, when `linked` is false.
|
|
151
|
+
- **`holds` reads a grant that names one field** (`@foir/sdk/auth`), as
|
|
152
|
+
`records:read:<model>.<field>` or `records:write:<model>.<field>`, the way the
|
|
153
|
+
platform does. A guarded field is covered by the grant that names it and by
|
|
154
|
+
one over every owner's records of every model, and not by its model's grant,
|
|
155
|
+
so `holds(['records:read'], 'records:read:order.taxId')` is `false`.
|
|
156
|
+
- **Breaking: a key in an older format is refused.** Foir answers `401` to a
|
|
157
|
+
key that begins `pk_`, `sk_` or `tc_` and says it no longer reads that format,
|
|
158
|
+
and the SDK reads a kind only from `foir_pub_`, `foir_srv_` and `foir_adm_`.
|
|
159
|
+
Make a key of its kind in its place: see
|
|
160
|
+
[Credentials](https://docs.foir.dev/credentials).
|
|
161
|
+
|
|
111
162
|
## [0.22.0] — 2026-10-15
|
|
112
163
|
|
|
113
164
|
### Added
|
package/README.md
CHANGED
|
@@ -104,11 +104,11 @@ present — there is no partial-`select` footgun. `include` adds a relation key,
|
|
|
104
104
|
`__typename` that narrow under an exhaustive `switch` with no casts.
|
|
105
105
|
|
|
106
106
|
**The client is shaped by your credential.** The generated `FoirSchema` contains
|
|
107
|
-
only what that key's manifest lists, so a read-only
|
|
107
|
+
only what that key's manifest lists, so a read-only publishable key has no `create` to
|
|
108
108
|
call:
|
|
109
109
|
|
|
110
110
|
```ts
|
|
111
|
-
foir.post.create({ data }); // ✗ compile error under a
|
|
111
|
+
foir.post.create({ data }); // ✗ compile error under a publishable key: not in its manifest
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
`generated` is optional. Without it — and without `selections` — the client
|
|
@@ -119,7 +119,7 @@ that way; silence it with `announceManifestFallback: false`.
|
|
|
119
119
|
|
|
120
120
|
Reads that can be shared are sent to `GET /cdn/graphql` with only the
|
|
121
121
|
persisted-query hash in the URL, so a CDN in front of you can serve the next
|
|
122
|
-
visitor without reaching origin. That is a query, on a
|
|
122
|
+
visitor without reaching origin. That is a query, on a publishable key, with no
|
|
123
123
|
user bearer, on the published channel; everything else is a `POST /graphql`.
|
|
124
124
|
|
|
125
125
|
`foir.raw()` is the escape hatch, and it takes a **GraphQL document** — it
|
|
@@ -144,7 +144,7 @@ const foir = createFoirClient({
|
|
|
144
144
|
|
|
145
145
|
Already have `PLATFORM_API_URL` / `PLATFORM_API_KEY` / `FOIR_PREVIEW` wired for
|
|
146
146
|
the GraphQL path? `createFoirClientFromEnv(env, { generated })` reuses them,
|
|
147
|
-
including the preview
|
|
147
|
+
including the preview key and the draft schema channel.
|
|
148
148
|
|
|
149
149
|
A product built on organizations names the one a request acts in with `orgId`,
|
|
150
150
|
which the client sends as `X-Org-Id` on every request. This is for the PROJECT
|
|
@@ -207,7 +207,7 @@ import { FoirProvider, SignIn, UserButton, useFoirSession } from '@foir/sdk/reac
|
|
|
207
207
|
|
|
208
208
|
const env = {
|
|
209
209
|
PLATFORM_API_URL: process.env.NEXT_PUBLIC_PLATFORM_API_URL,
|
|
210
|
-
PLATFORM_API_KEY: process.env.NEXT_PUBLIC_PLATFORM_API_KEY, // a publishable
|
|
210
|
+
PLATFORM_API_KEY: process.env.NEXT_PUBLIC_PLATFORM_API_KEY, // a publishable key
|
|
211
211
|
};
|
|
212
212
|
|
|
213
213
|
export function App() {
|
|
@@ -241,7 +241,7 @@ backend.
|
|
|
241
241
|
|
|
242
242
|
```tsx
|
|
243
243
|
<FoirProvider
|
|
244
|
-
env={{ PLATFORM_API_URL: 'https://api.foir.dev/graphql', PLATFORM_API_KEY: '
|
|
244
|
+
env={{ PLATFORM_API_URL: 'https://api.foir.dev/graphql', PLATFORM_API_KEY: 'foir_pub_…' }}
|
|
245
245
|
hostedSession={{ loginOrigin: 'https://login.acme.com' }}
|
|
246
246
|
>
|
|
247
247
|
<App />
|
package/dist/app/client.d.ts
CHANGED
|
@@ -97,10 +97,11 @@ export interface AppInstallConfig {
|
|
|
97
97
|
sources: AppBinding[];
|
|
98
98
|
sinks: AppBinding[];
|
|
99
99
|
/**
|
|
100
|
-
* Why the
|
|
101
|
-
* sits at, or null when
|
|
102
|
-
*
|
|
103
|
-
* (`appUserEmailUnavailableOf`), so say so before one is.
|
|
100
|
+
* Why the app's emails to users cannot link into the app at the level this
|
|
101
|
+
* install sits at, or null when they can. While it is set, a notification
|
|
102
|
+
* whose email links into the app with `{base}` is refused
|
|
103
|
+
* (`appUserEmailUnavailableOf`), so say so before one is. Every other email
|
|
104
|
+
* is sent.
|
|
104
105
|
*/
|
|
105
106
|
userEmailUnavailable: AppUserEmailUnavailableReason | null;
|
|
106
107
|
/**
|
package/dist/app/errors.d.ts
CHANGED
|
@@ -35,18 +35,20 @@ export declare function appUserUnlinkedOf(error: unknown): {
|
|
|
35
35
|
identityProvider: string;
|
|
36
36
|
} | null;
|
|
37
37
|
/**
|
|
38
|
-
* Why a project cannot send a user an email. `NO_APP_BASE_URL`:
|
|
39
|
-
*
|
|
40
|
-
* this build does not know arrives as
|
|
38
|
+
* Why a project cannot send a user an email. `NO_APP_BASE_URL`: the email
|
|
39
|
+
* links into the app with `{base}`, and no App base URL is set for the project
|
|
40
|
+
* or for the user's organization. A reason this build does not know arrives as
|
|
41
|
+
* the platform spelled it.
|
|
41
42
|
*/
|
|
42
43
|
export type AppUserEmailUnavailableReason = 'NO_APP_BASE_URL' | (string & {});
|
|
43
44
|
/** The reason as the platform sent it, or null when it sent none. */
|
|
44
45
|
export declare function userEmailUnavailableReasonOf(value: unknown): AppUserEmailUnavailableReason | null;
|
|
45
46
|
/**
|
|
46
47
|
* A request refused because it would send a user an email the project
|
|
47
|
-
* cannot
|
|
48
|
-
* was queued.
|
|
49
|
-
*
|
|
48
|
+
* cannot build, or null for any other failure. Nothing was written and nothing
|
|
49
|
+
* was queued. A notification whose email links into the app with `{base}` is
|
|
50
|
+
* refused this way where no App base URL is set, and so is an opt-in whose
|
|
51
|
+
* confirmation email the project's copy links into the app.
|
|
50
52
|
*
|
|
51
53
|
* It is about the project, not the user: the project's team fixes it,
|
|
52
54
|
* and the same request goes once they have.
|
package/dist/auth/auth.d.ts
CHANGED
|
@@ -79,6 +79,16 @@ export declare function providerSignInRefusalOf(error: unknown): {
|
|
|
79
79
|
code: string;
|
|
80
80
|
pending?: string;
|
|
81
81
|
} | null;
|
|
82
|
+
/**
|
|
83
|
+
* Why a sign-in your app's own form sent was refused, as the platform said it:
|
|
84
|
+
* a stable code your app shows its own words for. `password_sign_in_off` from
|
|
85
|
+
* {@link login} or {@link register} where the project, or the app the sign-in
|
|
86
|
+
* came through, takes no password; `code_sign_in_off` from {@link requestOTP}
|
|
87
|
+
* or {@link loginWithOTP} where it takes no code. Null for any other failure.
|
|
88
|
+
*/
|
|
89
|
+
export declare function signInRefusalOf(error: unknown): {
|
|
90
|
+
code: string;
|
|
91
|
+
} | null;
|
|
82
92
|
/**
|
|
83
93
|
* Finish a provider sign-in that is waiting for the code sent to its address,
|
|
84
94
|
* connecting the provider to the account that holds the address. See
|
|
@@ -121,8 +131,14 @@ export declare function joinWaitlist(env: FoirEnv, email: string): Promise<Waitl
|
|
|
121
131
|
* Send a password-reset email. Resolves `true` whether or not the address has
|
|
122
132
|
* an account: the server answers identically either way, on purpose, so this
|
|
123
133
|
* endpoint cannot be used to test whether someone has signed up.
|
|
134
|
+
*
|
|
135
|
+
* `clientId` names your app. Where the email's link goes to Foir's hosted
|
|
136
|
+
* reset page (the project has no App base URL), the page then sends the user
|
|
137
|
+
* to your app's initiate login URL to sign in.
|
|
124
138
|
*/
|
|
125
|
-
export declare function requestPasswordReset(env: FoirEnv, email: string
|
|
139
|
+
export declare function requestPasswordReset(env: FoirEnv, email: string, options?: {
|
|
140
|
+
clientId?: string;
|
|
141
|
+
}): Promise<boolean>;
|
|
126
142
|
/**
|
|
127
143
|
* Redeem an emailed reset token and set a new password. Returns a fresh session
|
|
128
144
|
* (resetting a password signs the user in), so pair it with
|
|
@@ -148,11 +164,19 @@ export declare function updatePassword(env: FoirEnv, vars: {
|
|
|
148
164
|
*/
|
|
149
165
|
export declare function currentUser(env: FoirEnv, options?: AuthOpOptions): Promise<CurrentUser | null>;
|
|
150
166
|
/**
|
|
151
|
-
* The stored upstream provider token for the calling user,
|
|
152
|
-
*
|
|
153
|
-
* user token on the request
|
|
167
|
+
* The stored upstream provider token for the calling user, renewed by the
|
|
168
|
+
* server when it is due: near its stated expiry, or with no expiry stated.
|
|
169
|
+
* `null` when there is no user token on the request; `linked: false` when the
|
|
170
|
+
* user has none stored for that provider.
|
|
171
|
+
*
|
|
172
|
+
* Pass `forceRefresh` after the provider refused the token it was last given:
|
|
173
|
+
* the server renews it then, at most once a minute for one user and provider.
|
|
174
|
+
* `refresh` says what the read did, and `reauthenticate` says when only the
|
|
175
|
+
* user signing in with the provider again mends the connection.
|
|
154
176
|
*/
|
|
155
|
-
export declare function myProviderToken(env: FoirEnv, providerKey: string, options?: AuthOpOptions
|
|
177
|
+
export declare function myProviderToken(env: FoirEnv, providerKey: string, options?: AuthOpOptions & {
|
|
178
|
+
forceRefresh?: boolean;
|
|
179
|
+
}): Promise<ProviderToken | null>;
|
|
156
180
|
/**
|
|
157
181
|
* End the session server-side, revoking stored provider tokens. This does NOT
|
|
158
182
|
* clear local session state — {@link signOut} is the pairing that does both.
|
|
@@ -275,8 +299,9 @@ export declare function makeRecoveryCodes(env: FoirEnv, elevatedHandle: string,
|
|
|
275
299
|
* Answered from the calling user's own memberships: each organization they
|
|
276
300
|
* hold one in and every organization beneath it, so the list is exactly the
|
|
277
301
|
* set a request of theirs may name, and a user with no memberships sees an
|
|
278
|
-
* empty list rather than a refusal. Requires the user's bearer
|
|
279
|
-
*
|
|
302
|
+
* empty list rather than a refusal. Requires the user's bearer. A user whose
|
|
303
|
+
* role holds `organizations:read` in the project is listed every organization
|
|
304
|
+
* of it instead, suspended ones included.
|
|
280
305
|
*
|
|
281
306
|
* A MEMBERSHIP REACHES DOWNWARD. Someone who is a member of an organization may
|
|
282
307
|
* stand in any organization beneath it without holding a row of their own
|
|
@@ -295,8 +320,8 @@ export declare function myOrganizations(env: FoirEnv, vars?: {
|
|
|
295
320
|
/**
|
|
296
321
|
* Found an organization, as its first member.
|
|
297
322
|
*
|
|
298
|
-
* The caller decides the NAME and, optionally, where it hangs
|
|
299
|
-
* else. The founder is the user behind the bearer, the id is minted
|
|
323
|
+
* The caller decides the NAME and, optionally, where it hangs and where it
|
|
324
|
+
* lives — and nothing else. The founder is the user behind the bearer, the id is minted
|
|
300
325
|
* server-side the way a project's and a tenant's are, and the role they hold in
|
|
301
326
|
* the new organization is the one the PROJECT named in its settings
|
|
302
327
|
* (`organizationSignupRole`). The server creates the organization and that one
|
|
@@ -310,6 +335,12 @@ export declare function myOrganizations(env: FoirEnv, vars?: {
|
|
|
310
335
|
* not-found. Omit it to found a root, which is what every registration did
|
|
311
336
|
* before organizations nested.
|
|
312
337
|
*
|
|
338
|
+
* `appBaseUrl` is where the organization's app lives, so an app that finds its
|
|
339
|
+
* organization from the page address (`orgUrl`) finds this one at once. It is
|
|
340
|
+
* held to the rule every organization address is: under the project's own app
|
|
341
|
+
* address or a domain the project verified, and not one another organization
|
|
342
|
+
* of the project holds.
|
|
343
|
+
*
|
|
313
344
|
* Exists on the wire only while the project's `organizationSignupEnabled` setting
|
|
314
345
|
* is on; a project that never opted in has no such field, and this refuses
|
|
315
346
|
* naming it. Returns the same entry `myOrganizations` would then list, role
|
|
@@ -318,6 +349,7 @@ export declare function myOrganizations(env: FoirEnv, vars?: {
|
|
|
318
349
|
export declare function registerOrganization(env: FoirEnv, vars: {
|
|
319
350
|
name: string;
|
|
320
351
|
parentId?: string;
|
|
352
|
+
appBaseUrl?: string;
|
|
321
353
|
}, options?: AuthOpOptions): Promise<MyOrganization>;
|
|
322
354
|
/**
|
|
323
355
|
* Persist an auth result to the session; returns the signed-in user.
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
export type GrantReach = 'own' | 'named' | 'all';
|
|
2
|
+
export type GrantTarget = 'none' | 'model' | 'operation';
|
|
2
3
|
/**
|
|
3
|
-
* One permission: its name,
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* One permission: its name, what a grant of it may name, the reaches it may be
|
|
5
|
+
* granted at (none: only its bare form exists), and the grants a holder of it
|
|
6
|
+
* also holds.
|
|
6
7
|
*/
|
|
7
8
|
export type GrantTableRow = readonly [
|
|
8
9
|
name: string,
|
|
9
|
-
|
|
10
|
+
target: GrantTarget,
|
|
10
11
|
reaches: readonly GrantReach[],
|
|
11
12
|
implies: readonly string[]
|
|
12
13
|
];
|
package/dist/auth/hosted.d.ts
CHANGED
|
@@ -127,3 +127,27 @@ export type HostedSessionResult =
|
|
|
127
127
|
* returning `null` for everything that is not a success.
|
|
128
128
|
*/
|
|
129
129
|
export declare function fetchHostedSession(request: Request, config: HostedLoginConfig): Promise<HostedSessionResult>;
|
|
130
|
+
/**
|
|
131
|
+
* What the hosted login said beside the code when it sent someone back to your
|
|
132
|
+
* app. A sign-in it refused carries a stable code (`foir_error`); one that
|
|
133
|
+
* connected a provider to the person's account on the way in names the
|
|
134
|
+
* provider (`foir_connected`). Each comes with a sentence your app can show as
|
|
135
|
+
* it is, so an app that does nothing more still shows words and never a code.
|
|
136
|
+
* Show your own words for a code by switching on `code`.
|
|
137
|
+
*/
|
|
138
|
+
export type HostedSignInNotice = {
|
|
139
|
+
kind: 'refused';
|
|
140
|
+
code: string;
|
|
141
|
+
message: string;
|
|
142
|
+
} | {
|
|
143
|
+
kind: 'connected';
|
|
144
|
+
provider: string;
|
|
145
|
+
message: string;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Reads the notice off the address the hosted login sent the browser back to:
|
|
149
|
+
* your callback URL, its search string, or its parameters. `names` maps a
|
|
150
|
+
* provider's key to the name to show (from `getAuthProviders`); without it the
|
|
151
|
+
* key is shown. Null when the hosted login said nothing.
|
|
152
|
+
*/
|
|
153
|
+
export declare function hostedSignInNoticeOf(location: string | URL | URLSearchParams, names?: Record<string, string>): HostedSignInNotice | null;
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -10,15 +10,15 @@
|
|
|
10
10
|
* the caller's own manifest advertises, through the same op transport
|
|
11
11
|
* `@foir/sdk/data` uses, so `graphql` is not on this module's path at all.
|
|
12
12
|
*/
|
|
13
|
-
export { login, register, requestOTP, loginWithOTP, refreshTokens, loginWithProvider, providerCallback, providerVerifyOTP, providerSignInRefusalOf, confirmProviderLink, resendProviderLinkCode, getAuthProviders, getAuthConfig, getDefaultAuthProvider, signupContext, joinWaitlist, requestPasswordReset, resetPassword, updatePassword, verifyEmail, currentUser, myProviderToken, logout, deleteMyAccount, updateMyProfile, myAuthorizedApps, revokeAuthorizedApp, mySessions, endMySession, signOutEverywhere, createPersonalAccessToken, mySignInMethods, connectSignInMethod, disconnectSignInMethod, myFactors, beginStepUp, completeStepUp, beginFactorEnrollment, completeFactorEnrollment, removeFactor, makeRecoveryCodes, myOrganizations, registerOrganization, saveSession, clearSession, getSessionToken, getSessionUser, signInWithPassword, signUpWithPassword, signInWithOTP, resetPasswordAndSignIn, refreshSession, refreshSessionOnce, signOut, authedRequest, authedOp, requireAuth, } from './auth';
|
|
13
|
+
export { login, register, requestOTP, loginWithOTP, refreshTokens, loginWithProvider, providerCallback, providerVerifyOTP, providerSignInRefusalOf, signInRefusalOf, confirmProviderLink, resendProviderLinkCode, getAuthProviders, getAuthConfig, getDefaultAuthProvider, signupContext, joinWaitlist, requestPasswordReset, resetPassword, updatePassword, verifyEmail, currentUser, myProviderToken, logout, deleteMyAccount, updateMyProfile, myAuthorizedApps, revokeAuthorizedApp, mySessions, endMySession, signOutEverywhere, createPersonalAccessToken, mySignInMethods, connectSignInMethod, disconnectSignInMethod, myFactors, beginStepUp, completeStepUp, beginFactorEnrollment, completeFactorEnrollment, removeFactor, makeRecoveryCodes, myOrganizations, registerOrganization, saveSession, clearSession, getSessionToken, getSessionUser, signInWithPassword, signUpWithPassword, signInWithOTP, resetPasswordAndSignIn, refreshSession, refreshSessionOnce, signOut, authedRequest, authedOp, requireAuth, } from './auth';
|
|
14
14
|
export type { FoirAuthTokens, FoirUser, SessionAdapter, RequireAuthOptions, } from './auth';
|
|
15
15
|
export { userAccess, getSessionAccess, hasRole, hasScope, requireRole, requireScope, FoirAccessDeniedError, } from './access';
|
|
16
16
|
export type { FoirAccess, FoirAccessDenial } from './access';
|
|
17
17
|
export { FoirAuthDowngradedError, FoirSessionExpiredError } from '../graphql/foir-request';
|
|
18
18
|
export { AUTH_OPS } from './ops';
|
|
19
19
|
export type { AuthOpName, AuthOpOptions } from './ops';
|
|
20
|
-
export { hostedLoginUrl, hostedLogoutUrl, fetchHostedSession } from './hosted';
|
|
21
|
-
export type { HostedLoginConfig, HostedSession, HostedSessionResult } from './hosted';
|
|
20
|
+
export { hostedLoginUrl, hostedLogoutUrl, fetchHostedSession, hostedSignInNoticeOf } from './hosted';
|
|
21
|
+
export type { HostedLoginConfig, HostedSession, HostedSessionResult, HostedSignInNotice } from './hosted';
|
|
22
22
|
export { createFoirSessionClient } from './session-client';
|
|
23
23
|
export type { FoirSessionClient, FoirSessionConfig, FoirSessionUser, } from './session-client';
|
|
24
|
-
export type { AuthResult, ProviderLoginResult, AuthProviderPublic, ProviderLoginInput, ProviderCallbackInput, ProviderOTPVerifyInput, SignupContext, SignupMode, WaitlistJoinResult, AuthConfig, AuthConfigProvider, DefaultAuthProvider, CurrentUser, ProviderToken, DeleteAccountResult, MyOrganization, MyProfile, MyProfileChange, AuthorizedApp, MySession, NewPersonalAccessToken, MySignInMethod, MyFactor, StepUp, FactorEnrollment, } from './operations';
|
|
24
|
+
export type { AuthResult, ProviderLoginResult, AuthProviderPublic, ProviderLoginInput, ProviderCallbackInput, ProviderOTPVerifyInput, SignupContext, SignupMode, WaitlistJoinResult, AuthConfig, AuthConfigProvider, DefaultAuthProvider, CurrentUser, ProviderToken, ProviderTokenRefresh, DeleteAccountResult, MyOrganization, MyProfile, MyProfileChange, AuthorizedApp, MySession, NewPersonalAccessToken, MySignInMethod, MyFactor, StepUp, FactorEnrollment, } from './operations';
|
|
@@ -123,18 +123,33 @@ export interface CurrentUser {
|
|
|
123
123
|
/** ISO-8601. */
|
|
124
124
|
createdAt: string;
|
|
125
125
|
}
|
|
126
|
+
/** What a provider token read did about the token's freshness. */
|
|
127
|
+
export type ProviderTokenRefresh = 'NOT_ATTEMPTED' | 'REFRESHED' | 'FAILED' | 'HELD_BACK';
|
|
126
128
|
/**
|
|
127
|
-
* A stored upstream provider token for the calling user. `
|
|
128
|
-
* is no user token on the request,
|
|
129
|
+
* A stored upstream provider token for the calling user. `myProviderToken`
|
|
130
|
+
* answers `null` when there is no user token on the request, and
|
|
131
|
+
* `linked: false` when the user has none stored for that provider.
|
|
129
132
|
*/
|
|
130
133
|
export interface ProviderToken {
|
|
131
134
|
providerKey: string;
|
|
132
|
-
|
|
135
|
+
/** False when the user has no token for the provider; every token field is then null. */
|
|
136
|
+
linked: boolean;
|
|
137
|
+
accessToken: string | null;
|
|
133
138
|
refreshToken: string | null;
|
|
134
139
|
/** ISO-8601. */
|
|
135
140
|
expiresAt: string | null;
|
|
136
141
|
/** Space-separated provider scopes, as the provider issued them. */
|
|
137
142
|
scopes: string | null;
|
|
143
|
+
/**
|
|
144
|
+
* What the read did: `REFRESHED` renewed it, `FAILED` tried and served the
|
|
145
|
+
* stored token, `HELD_BACK` had tried within the last minute, and
|
|
146
|
+
* `NOT_ATTEMPTED` found it fresh or had nothing to renew it with.
|
|
147
|
+
*/
|
|
148
|
+
refresh: ProviderTokenRefresh | null;
|
|
149
|
+
/** Where a failed refresh failed, such as `"refresh grant"`. */
|
|
150
|
+
refreshFailure: string | null;
|
|
151
|
+
/** Only the user signing in with the provider again mends the connection. */
|
|
152
|
+
reauthenticate: boolean;
|
|
138
153
|
}
|
|
139
154
|
/** What a self-serve account deletion removed. */
|
|
140
155
|
export interface DeleteAccountResult {
|
|
@@ -205,7 +220,10 @@ export interface MyFactor {
|
|
|
205
220
|
kind: string;
|
|
206
221
|
/** What {@link removeFactor} takes. */
|
|
207
222
|
id: string;
|
|
208
|
-
/**
|
|
223
|
+
/**
|
|
224
|
+
* A security key's or passkey's name. A passkey made on the project's own
|
|
225
|
+
* login domain is named by that domain, the only one it signs in on.
|
|
226
|
+
*/
|
|
209
227
|
name: string | null;
|
|
210
228
|
/** ISO-8601. */
|
|
211
229
|
addedAt: string | null;
|
|
@@ -314,6 +332,12 @@ export interface MyOrganization {
|
|
|
314
332
|
* sees part of what the next request is allowed and not the whole of it.
|
|
315
333
|
*/
|
|
316
334
|
role: MyOrganizationRole | null;
|
|
335
|
+
/**
|
|
336
|
+
* Where the list goes on from: pass the last entry's cursor as `after` to
|
|
337
|
+
* read the next page. Null on an entry no list gave, such as the one
|
|
338
|
+
* `registerOrganization` returns.
|
|
339
|
+
*/
|
|
340
|
+
cursor: string | null;
|
|
317
341
|
}
|
|
318
342
|
/** A role as `myOrganizations` reports it: enough to match a policy and to render. */
|
|
319
343
|
export interface MyOrganizationRole {
|