@foir/sdk 0.19.0 → 0.20.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 +279 -0
- package/dist/app/client.d.ts +109 -21
- package/dist/app/contract/proto/apps/v1/apps_pb.d.ts +223 -211
- package/dist/app/errors.d.ts +2 -2
- package/dist/app/index.d.ts +4 -4
- package/dist/app/manifest.d.ts +1 -1
- package/dist/app/vocabulary.generated.d.ts +13 -10
- package/dist/app-contract.js +27 -31
- package/dist/app.js +80 -23
- package/dist/auth/access.d.ts +106 -0
- package/dist/auth/grant-table.generated.d.ts +13 -0
- package/dist/auth/grants.d.ts +38 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/operations.d.ts +6 -1
- package/dist/auth/ops.d.ts +1 -0
- package/dist/auth.js +269 -1
- package/dist/data/builtins.d.ts +59 -3
- package/dist/data/index.d.ts +1 -1
- package/dist/data/transport.d.ts +2 -2
- package/dist/next.js +3 -0
- package/dist/placement/index.d.ts +40 -8
- package/dist/placement.js +224 -2
- package/dist/push.js +3 -0
- package/dist/react/FoirProvider.d.ts +40 -1
- package/dist/react/feedback-notes.d.ts +1 -1
- package/dist/react/index.d.ts +5 -4
- package/dist/react.js +347 -3
- package/dist/server/events-client.d.ts +5 -5
- package/dist/server/index.d.ts +1 -1
- package/dist/server/older-claims.generated.d.ts +8 -0
- package/dist/server/require-scoped-token.d.ts +1 -1
- package/dist/server/verify-scoped-token.d.ts +36 -17
- package/dist/server.js +267 -5
- package/package.json +6 -5
package/dist/placement.js
CHANGED
|
@@ -1,3 +1,197 @@
|
|
|
1
|
+
// src/auth/grant-table.generated.ts
|
|
2
|
+
var GRANT_TABLE = [
|
|
3
|
+
["records:read", true, ["own", "named", "all"], []],
|
|
4
|
+
["records:create", true, [], []],
|
|
5
|
+
["records:write", true, ["own", "named", "all"], []],
|
|
6
|
+
["records:delete", true, ["own", "named", "all"], []],
|
|
7
|
+
["records:publish", true, ["own", "all"], []],
|
|
8
|
+
["records:attribute", true, [], []],
|
|
9
|
+
["search:read", true, [], []],
|
|
10
|
+
["embeddings:read", false, [], []],
|
|
11
|
+
["embeddings:write", false, [], []],
|
|
12
|
+
["schemas:read", false, [], []],
|
|
13
|
+
["drafts:read", false, [], []],
|
|
14
|
+
["files:read", false, ["own", "all"], []],
|
|
15
|
+
["files:write", false, ["own", "all"], []],
|
|
16
|
+
["files:delete", false, ["own", "all"], []],
|
|
17
|
+
["notifications:read", false, ["own", "all"], []],
|
|
18
|
+
["notifications:write", false, ["own", "named", "all"], []],
|
|
19
|
+
["notifications:consent", false, [], []],
|
|
20
|
+
["pushcredentials:read", false, [], []],
|
|
21
|
+
["pushcredentials:write", false, [], []],
|
|
22
|
+
["notes:read", false, [], []],
|
|
23
|
+
["notes:write", false, [], []],
|
|
24
|
+
["notes:create", false, [], []],
|
|
25
|
+
["approvals:read", false, [], []],
|
|
26
|
+
["approvals:write", false, [], []],
|
|
27
|
+
["rooms:read", true, [], []],
|
|
28
|
+
["rooms:write", true, [], []],
|
|
29
|
+
["presence:read", true, [], []],
|
|
30
|
+
["operations:read", false, [], []],
|
|
31
|
+
["operations:execute", true, [], []],
|
|
32
|
+
["operations:write", false, [], []],
|
|
33
|
+
["operations:complete", false, [], []],
|
|
34
|
+
["status:write", false, [], []],
|
|
35
|
+
["appconfig:read", false, [], []],
|
|
36
|
+
["schedules:read", false, [], []],
|
|
37
|
+
["schedules:write", false, [], []],
|
|
38
|
+
["hooks:read", false, [], []],
|
|
39
|
+
["hooks:write", false, [], []],
|
|
40
|
+
["relyingparties:read", false, [], []],
|
|
41
|
+
["relyingparties:write", false, [], []],
|
|
42
|
+
["domains:read", false, [], []],
|
|
43
|
+
["domains:write", false, [], []],
|
|
44
|
+
["secrets:read", false, [], []],
|
|
45
|
+
["secrets:list", false, [], []],
|
|
46
|
+
["secrets:put", false, [], []],
|
|
47
|
+
["secrets:delete", false, [], []],
|
|
48
|
+
["appsecrets:read", false, [], []],
|
|
49
|
+
["appsecrets:list", false, [], []],
|
|
50
|
+
["appsecrets:put", false, [], []],
|
|
51
|
+
["appsecrets:delete", false, [], []],
|
|
52
|
+
["opsecrets:read", false, [], []],
|
|
53
|
+
["opsecrets:write", false, [], []],
|
|
54
|
+
["settings:read", false, [], []],
|
|
55
|
+
["settings:write", false, [], []],
|
|
56
|
+
["designtokens:read", false, [], []],
|
|
57
|
+
["designtokens:write", false, [], []],
|
|
58
|
+
["models:read", false, [], []],
|
|
59
|
+
["models:write", false, [], []],
|
|
60
|
+
["configs:read", false, [], []],
|
|
61
|
+
["configs:write", false, [], []],
|
|
62
|
+
["apps:read", false, [], []],
|
|
63
|
+
["apps:write", false, [], []],
|
|
64
|
+
["events:read", false, [], []],
|
|
65
|
+
["targeting:debug", false, [], []],
|
|
66
|
+
["visitors:forward", false, [], []],
|
|
67
|
+
["apikeys:read", false, [], []],
|
|
68
|
+
["apikeys:write", false, [], []],
|
|
69
|
+
["organizations:read", false, [], []],
|
|
70
|
+
["organizations:write", false, [], []],
|
|
71
|
+
["organizations:create", false, [], []],
|
|
72
|
+
["organizations:delete", false, [], []],
|
|
73
|
+
["organizations:reach", false, [], []],
|
|
74
|
+
["members:read", false, [], []],
|
|
75
|
+
["members:write", false, [], []],
|
|
76
|
+
["roles:read", false, [], []],
|
|
77
|
+
["roles:write", false, [], []],
|
|
78
|
+
["projects:read", false, [], []],
|
|
79
|
+
["projects:write", false, [], []],
|
|
80
|
+
["project:manage", false, [], ["records:read.all", "records:create", "records:write.all", "records:delete.all", "records:publish.all", "records:attribute", "search:read", "embeddings:read", "embeddings:write", "schemas:read", "drafts:read", "files:read.all", "files:write.all", "files:delete.all", "users:read.all", "identities:read", "users:create", "identities:delete", "users:write.all", "users:delete.all", "notifications:read.all", "notifications:write.all", "notifications:consent", "pushcredentials:read", "pushcredentials:write", "notes:read", "notes:write", "notes:create", "approvals:read", "approvals:write", "rooms:read", "rooms:write", "presence:read", "operations:read", "operations:execute", "operations:write", "appconfig:read", "schedules:read", "schedules:write", "hooks:read", "hooks:write", "auth:login_with_foir", "relyingparties:read", "relyingparties:write", "domains:read", "domains:write", "secrets:read", "secrets:list", "secrets:put", "secrets:delete", "appsecrets:read", "appsecrets:list", "appsecrets:put", "appsecrets:delete", "usersecrets:read", "usersecrets:list", "usersecrets:put", "usersecrets:delete", "opsecrets:read", "opsecrets:write", "settings:read", "settings:write", "designtokens:read", "designtokens:write", "models:read", "models:write", "configs:read", "configs:write", "signinproviders:read", "signinproviders:write", "apps:read", "apps:write", "events:read", "targeting:debug", "visitors:forward", "apikeys:read", "apikeys:write", "organizations:read", "organizations:create", "organizations:delete", "organizations:write", "organizations:reach", "members:read", "members:write", "roles:read", "roles:write", "projects:read", "projects:write"]],
|
|
81
|
+
["projects:create", false, [], []],
|
|
82
|
+
["projects:delete", false, [], []],
|
|
83
|
+
["tenants:read", false, [], []],
|
|
84
|
+
["tenants:write", false, [], []],
|
|
85
|
+
["tenants:delete", false, [], []],
|
|
86
|
+
["audit:read", false, [], []],
|
|
87
|
+
["export:run", false, [], []],
|
|
88
|
+
["billing:read", false, [], []],
|
|
89
|
+
["billing:manage", false, [], []],
|
|
90
|
+
["usage:read", false, [], []],
|
|
91
|
+
["controlkeys:read", false, [], []],
|
|
92
|
+
["controlkeys:write", false, [], []],
|
|
93
|
+
["tenanthooks:read", false, [], []],
|
|
94
|
+
["tenanthooks:write", false, [], []],
|
|
95
|
+
["apps:install", false, [], []],
|
|
96
|
+
["tenant:manage", false, [], ["project:manage", "projects:create", "projects:delete", "tenants:read", "tenants:write", "tenants:delete", "audit:read", "export:run", "billing:read", "billing:manage", "usage:read", "controlkeys:read", "controlkeys:write", "tenanthooks:read", "tenanthooks:write", "apps:install"]],
|
|
97
|
+
["platform:read", false, [], []],
|
|
98
|
+
["platform:manage", false, [], ["tenant:manage", "platform:read", "platform:create_workspace", "users:setup"]],
|
|
99
|
+
["platform:create_workspace", false, [], []],
|
|
100
|
+
["users:read", false, ["own", "named", "all"], []],
|
|
101
|
+
["users:write", false, ["own", "all"], []],
|
|
102
|
+
["users:setup", false, [], []],
|
|
103
|
+
["users:delete", false, ["own", "all"], []],
|
|
104
|
+
["users:create", false, [], []],
|
|
105
|
+
["identities:read", false, [], []],
|
|
106
|
+
["identities:delete", false, [], []],
|
|
107
|
+
["usersecrets:read", false, [], []],
|
|
108
|
+
["usersecrets:list", false, [], []],
|
|
109
|
+
["usersecrets:put", false, [], []],
|
|
110
|
+
["usersecrets:delete", false, [], []],
|
|
111
|
+
["auth:login_with_foir", false, [], []],
|
|
112
|
+
["signinproviders:read", false, [], []],
|
|
113
|
+
["signinproviders:write", false, [], []]
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
// src/auth/grants.ts
|
|
117
|
+
var WILDCARD = "*";
|
|
118
|
+
var RESOURCE_WILDCARD = ":*";
|
|
119
|
+
var index;
|
|
120
|
+
function catalogue() {
|
|
121
|
+
if (!index) {
|
|
122
|
+
const byName = new Map(GRANT_TABLE.map((row) => [row[0], row]));
|
|
123
|
+
const longestFirst = [...byName.keys()].sort(
|
|
124
|
+
(a, b) => a.length !== b.length ? b.length - a.length : a < b ? -1 : 1
|
|
125
|
+
);
|
|
126
|
+
index = { byName, longestFirst };
|
|
127
|
+
}
|
|
128
|
+
return index;
|
|
129
|
+
}
|
|
130
|
+
var reachRank = { own: 1, named: 2, all: 3 };
|
|
131
|
+
function hasReach(permission, reach) {
|
|
132
|
+
const reaches = permission[2];
|
|
133
|
+
return reaches.length === 0 ? reach === "own" : reaches.includes(reach);
|
|
134
|
+
}
|
|
135
|
+
function resourceOf(name) {
|
|
136
|
+
const i = name.indexOf(":");
|
|
137
|
+
return i < 0 ? name : name.slice(0, i);
|
|
138
|
+
}
|
|
139
|
+
function parseGrant(s) {
|
|
140
|
+
const { byName, longestFirst } = catalogue();
|
|
141
|
+
for (const name of longestFirst) {
|
|
142
|
+
if (!s.startsWith(name)) continue;
|
|
143
|
+
let rest = s.slice(name.length);
|
|
144
|
+
if (rest !== "" && rest[0] !== "." && rest[0] !== ":") continue;
|
|
145
|
+
const permission = byName.get(name);
|
|
146
|
+
let reach = "own";
|
|
147
|
+
if (rest.startsWith(".")) {
|
|
148
|
+
const after = rest.slice(1);
|
|
149
|
+
const colon = after.indexOf(":");
|
|
150
|
+
const word = colon < 0 ? after : after.slice(0, colon);
|
|
151
|
+
if (word !== "named" && word !== "all") return null;
|
|
152
|
+
if (!hasReach(permission, word)) return null;
|
|
153
|
+
reach = word;
|
|
154
|
+
rest = after.slice(word.length);
|
|
155
|
+
}
|
|
156
|
+
let target = "";
|
|
157
|
+
if (rest.startsWith(":")) {
|
|
158
|
+
target = rest.slice(1);
|
|
159
|
+
if (!permission[1]) return null;
|
|
160
|
+
if (target === "" || /[: \t\n*]/.test(target)) return null;
|
|
161
|
+
}
|
|
162
|
+
return { permission, reach, target };
|
|
163
|
+
}
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
function covers(held, required) {
|
|
167
|
+
return held.permission === required.permission && reachRank[held.reach] >= reachRank[required.reach] && (held.target === "" || held.target === required.target);
|
|
168
|
+
}
|
|
169
|
+
function resourceWildcard(held) {
|
|
170
|
+
if (!held.endsWith(RESOURCE_WILDCARD)) return null;
|
|
171
|
+
const resource = held.slice(0, -RESOURCE_WILDCARD.length);
|
|
172
|
+
return resource.includes(":") ? null : resource;
|
|
173
|
+
}
|
|
174
|
+
function holdsAt(held, required, depth) {
|
|
175
|
+
for (const h of held) {
|
|
176
|
+
if (h === WILDCARD) return true;
|
|
177
|
+
const resource = resourceWildcard(h);
|
|
178
|
+
if (resource !== null) {
|
|
179
|
+
if (resource === resourceOf(required.permission[0])) return true;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
const grant = parseGrant(h);
|
|
183
|
+
if (grant === null) continue;
|
|
184
|
+
if (covers(grant, required)) return true;
|
|
185
|
+
const implies = grant.permission[3];
|
|
186
|
+
if (depth < 4 && implies.length > 0 && holdsAt(implies, required, depth + 1)) return true;
|
|
187
|
+
}
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
function holds(held, required) {
|
|
191
|
+
const grant = parseGrant(required);
|
|
192
|
+
return grant !== null && holdsAt(held, grant, 0);
|
|
193
|
+
}
|
|
194
|
+
|
|
1
195
|
// src/placement/index.ts
|
|
2
196
|
var PLACEMENT_MESSAGE = {
|
|
3
197
|
/** Page to console: the page is listening and wants a token. */
|
|
@@ -13,6 +207,32 @@ var PLACEMENT_MESSAGE = {
|
|
|
13
207
|
/** Console to page: how the console looks, now and whenever it changes. */
|
|
14
208
|
appearance: "foir:placement:appearance"
|
|
15
209
|
};
|
|
210
|
+
function strings(value) {
|
|
211
|
+
return Array.isArray(value) ? value.filter((v) => typeof v === "string") : null;
|
|
212
|
+
}
|
|
213
|
+
function reasons(value, key) {
|
|
214
|
+
if (!Array.isArray(value)) return null;
|
|
215
|
+
const out = [];
|
|
216
|
+
for (const entry of value) {
|
|
217
|
+
const e = entry;
|
|
218
|
+
if (typeof e?.[key] === "string") out.push({ name: e[key], reason: typeof e.reason === "string" ? e.reason : "" });
|
|
219
|
+
}
|
|
220
|
+
return out;
|
|
221
|
+
}
|
|
222
|
+
function grantFrom(sent) {
|
|
223
|
+
const grants = strings(sent.grants) ?? strings(sent.grantedScopes) ?? [];
|
|
224
|
+
const withheld = reasons(sent.withheldGrants, "grant") ?? reasons(sent.withheld, "scope") ?? [];
|
|
225
|
+
const before = reasons(sent.withheld, "scope") ?? withheld;
|
|
226
|
+
return {
|
|
227
|
+
accessToken: sent.accessToken,
|
|
228
|
+
expiresAt: sent.expiresAt,
|
|
229
|
+
orgId: sent.orgId,
|
|
230
|
+
grants,
|
|
231
|
+
withheldGrants: withheld.map((w) => ({ grant: w.name, reason: w.reason })),
|
|
232
|
+
grantedScopes: strings(sent.grantedScopes) ?? grants,
|
|
233
|
+
withheld: before.map((w) => ({ scope: w.name, reason: w.reason }))
|
|
234
|
+
};
|
|
235
|
+
}
|
|
16
236
|
var FOIR_CONSOLE_ORIGINS = {
|
|
17
237
|
production: ["https://app.foir.io"],
|
|
18
238
|
dev: ["https://app-dev.foir.io"]
|
|
@@ -87,7 +307,9 @@ function connectPlacement(options) {
|
|
|
87
307
|
get appearance() {
|
|
88
308
|
return appearance;
|
|
89
309
|
},
|
|
90
|
-
|
|
310
|
+
// As written, for a list a console of the release before sent in the
|
|
311
|
+
// names a placement declared then; and by what the list covers.
|
|
312
|
+
can: (asked) => grant ? grant.grants.includes(asked) || holds(grant.grants, asked) : false,
|
|
91
313
|
async request(document, variables) {
|
|
92
314
|
if (!grant) throw new PlacementRefused("the operator has signed out");
|
|
93
315
|
const res = await doFetch(`${apiUrl}/graphql`, {
|
|
@@ -113,7 +335,7 @@ function connectPlacement(options) {
|
|
|
113
335
|
const msg = event.data;
|
|
114
336
|
switch (msg.type) {
|
|
115
337
|
case PLACEMENT_MESSAGE.token:
|
|
116
|
-
grant = msg.grant;
|
|
338
|
+
grant = grantFrom(msg.grant);
|
|
117
339
|
scheduleRefresh();
|
|
118
340
|
if (!settled) {
|
|
119
341
|
settled = true;
|
package/dist/push.js
CHANGED
|
@@ -1034,6 +1034,9 @@ var AUTH_OPS = {
|
|
|
1034
1034
|
// Post-credential self reads.
|
|
1035
1035
|
currentUser: "currentUser",
|
|
1036
1036
|
myProviderToken: "myProviderToken",
|
|
1037
|
+
// What the calling credential may do, and for a signed-in customer the roles
|
|
1038
|
+
// they hold. `./access` reads it.
|
|
1039
|
+
whoami: "whoami",
|
|
1037
1040
|
// Methods.
|
|
1038
1041
|
customerLogin: "customerLogin",
|
|
1039
1042
|
customerRegister: "customerRegister",
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type { AuthProviderPublic, FoirCustomer, FoirSessionConfig, SessionAdapter } from '../auth';
|
|
2
|
+
import type { AuthProviderPublic, FoirAccess, FoirCustomer, FoirSessionConfig, SessionAdapter } from '../auth';
|
|
3
3
|
import type { ProviderCallbackInput, ProviderLoginInput } from '../auth';
|
|
4
4
|
import type { FoirEnv } from '../graphql/foir-request';
|
|
5
5
|
/** Where the session hydration stands. */
|
|
6
6
|
export type FoirStatus = 'loading' | 'authenticated' | 'unauthenticated';
|
|
7
|
+
/**
|
|
8
|
+
* Where reading the signed-in customer's access stands. `idle` until something
|
|
9
|
+
* asks for it; `unavailable` when the platform could not be asked.
|
|
10
|
+
*/
|
|
11
|
+
export type FoirAccessStatus = 'idle' | 'loading' | 'ready' | 'unavailable';
|
|
7
12
|
/** The full context value. Read it through the hooks below, not directly. */
|
|
8
13
|
export interface FoirContextValue {
|
|
9
14
|
status: FoirStatus;
|
|
10
15
|
customer: FoirCustomer | null;
|
|
16
|
+
/** The signed-in customer's access, once read. See {@link useFoirAccess}. */
|
|
17
|
+
access: FoirAccess | null;
|
|
18
|
+
accessStatus: FoirAccessStatus;
|
|
19
|
+
/** Ask the platform for the signed-in customer's access, again if it was read before. */
|
|
20
|
+
loadAccess(): Promise<void>;
|
|
21
|
+
/** The same, unless a read is already under way: then that one is awaited. */
|
|
22
|
+
ensureAccess(): Promise<void>;
|
|
11
23
|
/** The API config; exposed so advanced consumers can call `@foir/sdk/auth` directly. */
|
|
12
24
|
env: FoirEnv;
|
|
13
25
|
/** The session store backing this provider. */
|
|
@@ -89,6 +101,33 @@ export interface FoirSession {
|
|
|
89
101
|
export declare function useFoirSession(): FoirSession;
|
|
90
102
|
/** The signed-in customer (`{ id, email }`), or null. */
|
|
91
103
|
export declare function useFoirUser(): FoirCustomer | null;
|
|
104
|
+
/** What {@link useFoirAccess} returns. */
|
|
105
|
+
export interface FoirAccessState {
|
|
106
|
+
/**
|
|
107
|
+
* `loading` until the platform has answered for this session, `ready` once it
|
|
108
|
+
* has (and at once when nobody is signed in), `unavailable` when it could not
|
|
109
|
+
* be asked.
|
|
110
|
+
*/
|
|
111
|
+
status: 'loading' | 'ready' | 'unavailable';
|
|
112
|
+
isLoading: boolean;
|
|
113
|
+
/** The signed-in customer's access, or null: signed out, loading or unavailable. */
|
|
114
|
+
access: FoirAccess | null;
|
|
115
|
+
/** Whether the customer holds the role with this key. False until known. */
|
|
116
|
+
hasRole(key: string): boolean;
|
|
117
|
+
/** Whether the customer's scopes cover this one. False until known. */
|
|
118
|
+
hasScope(scope: string): boolean;
|
|
119
|
+
/** Ask the platform again, for a role given or taken away since. */
|
|
120
|
+
reload(): Promise<void>;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The roles the signed-in customer holds and the scopes they resolve to, as the
|
|
124
|
+
* platform resolved them. Read on first use, again when the session refreshes,
|
|
125
|
+
* and whenever `reload` is called.
|
|
126
|
+
*
|
|
127
|
+
* Use it to decide what to show. It protects nothing: the platform checks every
|
|
128
|
+
* request whatever the page offers.
|
|
129
|
+
*/
|
|
130
|
+
export declare function useFoirAccess(): FoirAccessState;
|
|
92
131
|
/** The sign-in / sign-out actions. */
|
|
93
132
|
export declare function useFoirAuth(): {
|
|
94
133
|
signIn: (vars: {
|
|
@@ -45,7 +45,7 @@ export interface FoirFeedbackClient {
|
|
|
45
45
|
*
|
|
46
46
|
* The distinction earns its place because the three have different audiences.
|
|
47
47
|
* `signIn` is the visitor's to fix. `scope` is the OPERATOR's — a role that does
|
|
48
|
-
* not grant `notes:
|
|
48
|
+
* not grant `notes:create` produces `missing required scope: notes:create`, which
|
|
49
49
|
* reads like a bad API key and is not one; the key is fine and the customer's
|
|
50
50
|
* role is short a capability. `other` is everything the widget will not pretend
|
|
51
51
|
* to understand.
|
package/dist/react/index.d.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* `@foir/sdk/react` — drop-in React components for Foir customers.
|
|
3
3
|
*
|
|
4
4
|
* Wrap your app in `<FoirProvider>`, then read the session with
|
|
5
|
-
* `useFoirSession` / `useFoirUser
|
|
5
|
+
* `useFoirSession` / `useFoirUser`, ask what the customer may see with
|
|
6
|
+
* `useFoirAccess`, and drive it with `useFoirAuth` — or drop in
|
|
6
7
|
* the `<SignIn>`, `<OAuthButtons>`, and `<UserButton>` components. Built entirely
|
|
7
8
|
* on `@foir/sdk/auth`; `react` is the only peer dependency.
|
|
8
9
|
*
|
|
@@ -10,8 +11,8 @@
|
|
|
10
11
|
* RECORD the page was rendered from rather than to its URL. It takes the data
|
|
11
12
|
* client from `@foir/sdk/data` and the subject registry you built for it.
|
|
12
13
|
*/
|
|
13
|
-
export { FoirProvider, useFoirSession, useFoirUser, useFoirAuth, } from './FoirProvider';
|
|
14
|
-
export type { FoirProviderProps, FoirContextValue, FoirSession, FoirStatus, } from './FoirProvider';
|
|
14
|
+
export { FoirProvider, useFoirSession, useFoirUser, useFoirAuth, useFoirAccess, } from './FoirProvider';
|
|
15
|
+
export type { FoirProviderProps, FoirContextValue, FoirSession, FoirStatus, FoirAccessState, FoirAccessStatus, } from './FoirProvider';
|
|
15
16
|
export { SignIn } from './SignIn';
|
|
16
17
|
export type { SignInProps } from './SignIn';
|
|
17
18
|
export { OAuthButtons } from './OAuthButtons';
|
|
@@ -21,5 +22,5 @@ export type { UserButtonProps } from './UserButton';
|
|
|
21
22
|
export { FoirFeedback } from './FoirFeedback';
|
|
22
23
|
export type { FoirFeedbackProps, FoirFeedbackClient } from './FoirFeedback';
|
|
23
24
|
export { createLocalStorageAdapter } from './localStorageAdapter';
|
|
24
|
-
export type { FoirCustomer, SessionAdapter, AuthProviderPublic } from '../auth';
|
|
25
|
+
export type { FoirAccess, FoirCustomer, SessionAdapter, AuthProviderPublic } from '../auth';
|
|
25
26
|
export type { FoirEnv } from '../graphql/foir-request';
|