@foir/sdk 0.20.0 → 0.22.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 +135 -1
- package/README.md +9 -9
- package/dist/app/client.d.ts +90 -84
- package/dist/app/contract/proto/apps/v1/apps_pb.d.ts +14 -13
- package/dist/app/dispatch.d.ts +5 -5
- package/dist/app/errors.d.ts +11 -11
- package/dist/app/index.d.ts +4 -4
- package/dist/app/naming.d.ts +1 -1
- package/dist/app/ticket.d.ts +2 -2
- package/dist/app/vocabulary.generated.d.ts +2 -2
- package/dist/app-contract.js +3 -3
- package/dist/app.js +92 -90
- package/dist/auth/access.d.ts +19 -19
- package/dist/auth/auth.d.ts +216 -114
- package/dist/auth/hosted.d.ts +14 -14
- package/dist/auth/index.d.ts +7 -7
- package/dist/auth/operations.d.ts +128 -32
- package/dist/auth/ops.d.ts +39 -21
- package/dist/auth/session-client.d.ts +3 -3
- package/dist/auth-session.js +3 -3
- package/dist/auth.js +291 -146
- package/dist/client/platform-client.d.ts +1 -1
- package/dist/client.js +32 -5
- package/dist/codegen/index.js +1 -1
- package/dist/data/builtins.d.ts +41 -82
- package/dist/data/client.d.ts +2 -2
- package/dist/data/decimal.d.ts +1 -1
- package/dist/data/document.d.ts +14 -0
- package/dist/data/index.d.ts +2 -2
- package/dist/data/manifest.d.ts +1 -1
- package/dist/data/schema.d.ts +1 -1
- package/dist/data/transport.d.ts +33 -26
- package/dist/data/ws-transport.d.ts +1 -1
- package/dist/data.js +97 -19
- package/dist/graphql/content-client.d.ts +13 -13
- package/dist/index.js +24 -0
- package/dist/live/drift.d.ts +1 -1
- package/dist/media/screen-capture.d.ts +1 -1
- package/dist/next/index.d.ts +2 -2
- package/dist/next/session.d.ts +10 -10
- package/dist/next.js +121 -61
- package/dist/placement/index.d.ts +15 -32
- package/dist/placement.js +18 -20
- package/dist/push.js +113 -46
- package/dist/react/FoirFeedback.d.ts +2 -2
- package/dist/react/FoirProvider.d.ts +23 -23
- package/dist/react/SignIn.d.ts +4 -4
- package/dist/react/UserButton.d.ts +1 -1
- package/dist/react/feedback-notes.d.ts +4 -4
- package/dist/react/index.d.ts +3 -3
- package/dist/react.js +168 -105
- package/dist/realtime/index.d.ts +1 -1
- package/dist/server/callback-client.d.ts +4 -4
- package/dist/server/events-client.d.ts +18 -18
- package/dist/server/operation-types.d.ts +8 -8
- package/dist/server/require-scoped-token.d.ts +3 -3
- package/dist/server/server-client.d.ts +1 -1
- package/dist/server/types.d.ts +1 -1
- package/dist/server/verify-scoped-token.d.ts +4 -28
- package/dist/server.js +67 -112
- package/dist/transport/foir-http.d.ts +57 -18
- package/dist/transport/key-kind.d.ts +40 -0
- package/dist/types/index.d.ts +2 -2
- package/package.json +3 -3
- package/dist/server/older-claims.generated.d.ts +0 -8
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* The split exists so the second one is possible. The Foir-specific transport
|
|
13
13
|
* concerns — which api key is in play, the preview schema channel header, the
|
|
14
|
-
* optional
|
|
14
|
+
* optional user bearer, and the `FoirRequestError` shape — are identical on
|
|
15
15
|
* both, and duplicating them is exactly how the two surfaces would drift. So
|
|
16
16
|
* they live here once and `foir-request.ts` re-exports them unchanged; the only
|
|
17
17
|
* thing that stayed behind is the part that needs `print`.
|
|
@@ -206,8 +206,8 @@ export declare function readFoirRateLimit(headers: Headers): FoirRateLimitSnapsh
|
|
|
206
206
|
export declare function readFoirRetryAfterMs(headers: Headers): number | undefined;
|
|
207
207
|
export interface FoirRequestOptions {
|
|
208
208
|
/**
|
|
209
|
-
*
|
|
210
|
-
* the project; the bearer adds the
|
|
209
|
+
* User bearer token. api-public still needs the `x-api-key` to resolve
|
|
210
|
+
* the project; the bearer adds the user identity for self-scoped reads
|
|
211
211
|
* (e.g. `myProfile`). Used by `@foir/sdk/auth`'s post-login profile fetch.
|
|
212
212
|
*/
|
|
213
213
|
bearerToken?: string;
|
|
@@ -256,7 +256,7 @@ export interface FoirRequestOptions {
|
|
|
256
256
|
onRateLimit?: (snapshot: FoirRateLimitSnapshot | undefined) => void;
|
|
257
257
|
}
|
|
258
258
|
/**
|
|
259
|
-
* Supplies the current
|
|
259
|
+
* Supplies the current user bearer. Sync or async so consumers can read a
|
|
260
260
|
* cookie session (Hydrogen/Remix), a KV store, an in-memory value, etc. Returns
|
|
261
261
|
* the token when signed in, or `null`/`undefined` when signed out.
|
|
262
262
|
*
|
|
@@ -265,7 +265,7 @@ export interface FoirRequestOptions {
|
|
|
265
265
|
* they would end up accepting subtly different things.
|
|
266
266
|
*/
|
|
267
267
|
export type FoirTokenProvider = () => string | null | undefined | Promise<string | null | undefined>;
|
|
268
|
-
/** A request made with an api key, optionally for a signed-in
|
|
268
|
+
/** A request made with an api key, optionally for a signed-in user. */
|
|
269
269
|
export interface FoirKeyHeaderInput {
|
|
270
270
|
apiKey: string;
|
|
271
271
|
/**
|
|
@@ -273,8 +273,8 @@ export interface FoirKeyHeaderInput {
|
|
|
273
273
|
* freshly pushed model changes (new fields, new models) are visible at
|
|
274
274
|
* runtime — otherwise selections on draft-only fields are silently stripped
|
|
275
275
|
* and surface as confusing "fragment never used" errors. The header has no
|
|
276
|
-
* effect under
|
|
277
|
-
* whenever the caller is in preview.
|
|
276
|
+
* effect under an app's key without `drafts:read` (the server ignores it),
|
|
277
|
+
* so it is safe to send whenever the caller is in preview.
|
|
278
278
|
*/
|
|
279
279
|
draftChannel?: boolean;
|
|
280
280
|
bearerToken?: string;
|
|
@@ -305,7 +305,7 @@ export interface FoirKeyHeaderInput {
|
|
|
305
305
|
*
|
|
306
306
|
* The token is the whole credential. api-public takes the scoped path when
|
|
307
307
|
* `X-Foir-Token` is present and never reads `x-api-key` on it, and the
|
|
308
|
-
* organization, the
|
|
308
|
+
* organization, the user and the schema channel all come from the token's
|
|
309
309
|
* own claims, so none of the key-side inputs has anything to say here.
|
|
310
310
|
*/
|
|
311
311
|
export interface FoirDispatchHeaderInput {
|
|
@@ -337,14 +337,34 @@ export declare function refuseCredentialHeaders(extra: Readonly<Record<string, s
|
|
|
337
337
|
* authorization difference nobody would notice until it mattered.
|
|
338
338
|
*
|
|
339
339
|
* Two credentials, and a request carries exactly one: an api key (with its
|
|
340
|
-
* optional
|
|
340
|
+
* optional user bearer, organization and channel), or an operation's
|
|
341
341
|
* dispatch token. A dispatch request never writes `x-api-key`.
|
|
342
342
|
*/
|
|
343
343
|
/** The header a server names the visitor it calls for in. */
|
|
344
344
|
export declare const FOIR_VISITOR_IP_HEADER = "X-Foir-Visitor-IP";
|
|
345
345
|
/**
|
|
346
|
-
* The
|
|
347
|
-
*
|
|
346
|
+
* The visitor a server rendering pages is calling for: who they are to the
|
|
347
|
+
* per-visitor limits, and where they are to location targeting.
|
|
348
|
+
*
|
|
349
|
+
* Each part is what your host says of the visitor, and each is optional. A
|
|
350
|
+
* part left out is not said: with no address the request counts as your
|
|
351
|
+
* server's own, and with no country and no coordinates the visitor is one
|
|
352
|
+
* nobody could place. Where your server is never stands in for where the
|
|
353
|
+
* visitor is.
|
|
354
|
+
*/
|
|
355
|
+
export interface FoirVisitor {
|
|
356
|
+
/** The visitor's address, sent as `X-Foir-Visitor-IP`. */
|
|
357
|
+
address?: string | null;
|
|
358
|
+
/** The visitor's country, as an ISO 3166-1 alpha-2 code such as `GB`. */
|
|
359
|
+
country?: string | null;
|
|
360
|
+
/** The visitor's latitude, in decimal degrees. Sent with `longitude`, or not at all. */
|
|
361
|
+
latitude?: number | null;
|
|
362
|
+
/** The visitor's longitude, in decimal degrees. Sent with `latitude`, or not at all. */
|
|
363
|
+
longitude?: number | null;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* The visitor a server rendering pages is calling for, or a function that
|
|
367
|
+
* resolves them for each request. A string is the visitor's address alone.
|
|
348
368
|
*
|
|
349
369
|
* The SDK does not read it off a request, because which request header holds
|
|
350
370
|
* the visitor's real address, and whether a visitor can forge it, depends on
|
|
@@ -352,7 +372,26 @@ export declare const FOIR_VISITOR_IP_HEADER = "X-Foir-Visitor-IP";
|
|
|
352
372
|
* strips; that value, and only that, belongs here. A function that yields
|
|
353
373
|
* nothing sends nothing, and the API counts the request as your server's own.
|
|
354
374
|
*/
|
|
355
|
-
export type FoirVisitorSource = string | (() => string | null | undefined | Promise<string | null | undefined>);
|
|
375
|
+
export type FoirVisitorSource = string | FoirVisitor | (() => string | FoirVisitor | null | undefined | Promise<string | FoirVisitor | null | undefined>);
|
|
376
|
+
/** Where a stated visitor is, as a read's `contexts` carries it. */
|
|
377
|
+
export interface FoirVisitorPlace {
|
|
378
|
+
country?: string;
|
|
379
|
+
location?: {
|
|
380
|
+
latitude: number;
|
|
381
|
+
longitude: number;
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
/** One request's visitor, resolved: the address for the header, and the place for the read. */
|
|
385
|
+
export interface FoirResolvedVisitor {
|
|
386
|
+
address?: string;
|
|
387
|
+
place: FoirVisitorPlace;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Resolve a `visitor` for one request. The provider is called here, once, and
|
|
391
|
+
* what it yields is used for the header and for the read alike, so the two
|
|
392
|
+
* never describe different visitors.
|
|
393
|
+
*/
|
|
394
|
+
export declare function resolveFoirVisitor(source: FoirVisitorSource | undefined): Promise<FoirResolvedVisitor>;
|
|
356
395
|
export declare function buildFoirHeaders(input: FoirHeaderInput): Record<string, string>;
|
|
357
396
|
/**
|
|
358
397
|
* Build a `/v1/...` URL from whatever the caller put in `apiUrl`.
|
|
@@ -373,7 +412,7 @@ export declare function foirApiEndpoint(apiUrl: string, path: `/${string}`): str
|
|
|
373
412
|
/**
|
|
374
413
|
* Foir DISCARDED a credential you sent, and served the request without it.
|
|
375
414
|
*
|
|
376
|
-
* A
|
|
415
|
+
* A user JWT is optional: if it fails to verify, the read is served as an
|
|
377
416
|
* ordinary anonymous one rather than refused, because plenty of reads
|
|
378
417
|
* legitimately have nobody signed in. That is the right behaviour and it has a
|
|
379
418
|
* sharp edge — a lapsed token and a genuinely anonymous request produce the
|
|
@@ -385,9 +424,9 @@ export declare function foirApiEndpoint(apiUrl: string, path: `/${string}`): str
|
|
|
385
424
|
*/
|
|
386
425
|
export interface FoirAuthDowngrade {
|
|
387
426
|
/** Always `"rejected"`. */
|
|
388
|
-
|
|
427
|
+
userToken: string;
|
|
389
428
|
/**
|
|
390
|
-
* `expired` — re-exchange and retry. `invalid` — not a
|
|
429
|
+
* `expired` — re-exchange and retry. `invalid` — not a user token for
|
|
391
430
|
* this environment. `wrong_project` — the token and the api-key name
|
|
392
431
|
* different projects.
|
|
393
432
|
*/
|
|
@@ -396,7 +435,7 @@ export interface FoirAuthDowngrade {
|
|
|
396
435
|
servedAs: string;
|
|
397
436
|
}
|
|
398
437
|
/**
|
|
399
|
-
* A request that sent a
|
|
438
|
+
* A request that sent a user token was served without it.
|
|
400
439
|
*
|
|
401
440
|
* Thrown only to a caller that asked (`rejectDowngrade`): one that sent the
|
|
402
441
|
* token because it wants the signed-in answer, and would otherwise be handed the
|
|
@@ -409,9 +448,9 @@ export declare class FoirAuthDowngradedError extends FoirRequestError {
|
|
|
409
448
|
constructor(downgrade: FoirAuthDowngrade);
|
|
410
449
|
}
|
|
411
450
|
/**
|
|
412
|
-
* The
|
|
451
|
+
* The user's session is over: its token was rejected and could not be
|
|
413
452
|
* refreshed. It is what a signed-in request gets in place of the anonymous
|
|
414
|
-
* answer. Send the
|
|
453
|
+
* answer. Send the user to sign in again.
|
|
415
454
|
*/
|
|
416
455
|
export declare class FoirSessionExpiredError extends FoirRequestError {
|
|
417
456
|
constructor(options?: {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kind a key says it is, by its prefix.
|
|
3
|
+
*
|
|
4
|
+
* A key is one of three kinds, chosen by whoever made it. A publishable key
|
|
5
|
+
* sits in a page or an app. A server key is held by the server that renders an
|
|
6
|
+
* app's pages. An admin key is a machine's own: a sync job, a pipeline, a tool.
|
|
7
|
+
* A key says its kind in its first letters, so this is decided without a
|
|
8
|
+
* request.
|
|
9
|
+
*
|
|
10
|
+
* A key minted before a key had a kind says an older type. A `pk_` key is a
|
|
11
|
+
* publishable key. An `sk_` or a `tc_` key says only that it is not public:
|
|
12
|
+
* the platform holds it as an admin key, and it is reported here as `older`,
|
|
13
|
+
* so that a caller who refuses an admin key by name does not refuse a key
|
|
14
|
+
* whose holder has not yet been able to mint a server key in its place.
|
|
15
|
+
*/
|
|
16
|
+
export type FoirKeyKind = 'publishable' | 'server' | 'admin';
|
|
17
|
+
/** What a key's prefix says of it: its kind, or that it is an older secret. */
|
|
18
|
+
export type FoirKeyPrefixKind = FoirKeyKind | 'older';
|
|
19
|
+
/** Where each credential is for, and which key an app holds. */
|
|
20
|
+
export declare const FOIR_CREDENTIALS_DOC = "https://docs.foir.dev/credentials";
|
|
21
|
+
/**
|
|
22
|
+
* What a key says of itself by its prefix, or `undefined` for a string that
|
|
23
|
+
* is no key Fóir made.
|
|
24
|
+
*/
|
|
25
|
+
export declare function foirKeyKind(apiKey: string | null | undefined): FoirKeyPrefixKind | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* What an app's client says when it is handed an admin key, naming the client
|
|
28
|
+
* it was handed to. An admin key is a machine's own, so every client an app
|
|
29
|
+
* builds refuses one before any request, in the same words.
|
|
30
|
+
*
|
|
31
|
+
* Only a key that says it is an admin key by its prefix is refused. A key
|
|
32
|
+
* minted before a key had a kind does not say, and is let through.
|
|
33
|
+
*/
|
|
34
|
+
export declare function adminKeyRefusal(client: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Whether a key may be named in a URL. Only a publishable key may: it ships in
|
|
37
|
+
* the page and is served to every visitor, so naming it discloses nothing. Any
|
|
38
|
+
* other key would land in access logs, referrer headers and browser history.
|
|
39
|
+
*/
|
|
40
|
+
export declare function isPublishableFoirKey(apiKey: string | null | undefined): boolean;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export interface EditorInit {
|
|
|
21
21
|
apiUrl: string;
|
|
22
22
|
/** Config connection domain (e.g. my-store.myshopify.com) */
|
|
23
23
|
connectionDomain?: string;
|
|
24
|
-
/** How this editor is rendered in the
|
|
24
|
+
/** How this editor is rendered in the console. */
|
|
25
25
|
configMode?: 'editor' | 'sidebar';
|
|
26
26
|
/** Currently selected field keys (sidebar mode). */
|
|
27
27
|
selectedFieldKeys?: string[];
|
|
@@ -67,7 +67,7 @@ export interface EditorContextValue {
|
|
|
67
67
|
resize: (height: number) => void;
|
|
68
68
|
/** Report dirty state (unsaved changes). */
|
|
69
69
|
setDirty: (isDirty: boolean) => void;
|
|
70
|
-
/** Request the host to navigate to
|
|
70
|
+
/** Request the host to navigate to a console path. */
|
|
71
71
|
requestNavigate: (path: string) => void;
|
|
72
72
|
/** Request the host to execute a platform operation. Returns the result.
|
|
73
73
|
* `mode` controls whether the platform waits for the operation to complete
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foir/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Official Foir SDK — editor iframe client + server-side platform helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -177,8 +177,8 @@
|
|
|
177
177
|
"ws": "^8.18.0",
|
|
178
178
|
"y-websocket": "^3.0.0",
|
|
179
179
|
"yjs": "^13.6.30",
|
|
180
|
-
"@foir/
|
|
181
|
-
"@foir/
|
|
180
|
+
"@foir/proto-ts": "0.109.0",
|
|
181
|
+
"@foir/access-vocab": "0.0.0"
|
|
182
182
|
},
|
|
183
183
|
"engines": {
|
|
184
184
|
"node": ">=18.0.0"
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/** Stands, below, where a capability or a grant names a model. */
|
|
2
|
-
export declare const OLDER_CLAIM_TARGET = "{target}";
|
|
3
|
-
/**
|
|
4
|
-
* What each capability a token said before it said its grants was worth, as
|
|
5
|
-
* the platform reads one. A capability that was worth nothing is worth nothing
|
|
6
|
-
* here.
|
|
7
|
-
*/
|
|
8
|
-
export declare const OLDER_CAPABILITY_GRANTS: Readonly<Record<string, readonly string[]>>;
|