@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.
Files changed (65) hide show
  1. package/CHANGELOG.md +135 -1
  2. package/README.md +9 -9
  3. package/dist/app/client.d.ts +90 -84
  4. package/dist/app/contract/proto/apps/v1/apps_pb.d.ts +14 -13
  5. package/dist/app/dispatch.d.ts +5 -5
  6. package/dist/app/errors.d.ts +11 -11
  7. package/dist/app/index.d.ts +4 -4
  8. package/dist/app/naming.d.ts +1 -1
  9. package/dist/app/ticket.d.ts +2 -2
  10. package/dist/app/vocabulary.generated.d.ts +2 -2
  11. package/dist/app-contract.js +3 -3
  12. package/dist/app.js +92 -90
  13. package/dist/auth/access.d.ts +19 -19
  14. package/dist/auth/auth.d.ts +216 -114
  15. package/dist/auth/hosted.d.ts +14 -14
  16. package/dist/auth/index.d.ts +7 -7
  17. package/dist/auth/operations.d.ts +128 -32
  18. package/dist/auth/ops.d.ts +39 -21
  19. package/dist/auth/session-client.d.ts +3 -3
  20. package/dist/auth-session.js +3 -3
  21. package/dist/auth.js +291 -146
  22. package/dist/client/platform-client.d.ts +1 -1
  23. package/dist/client.js +32 -5
  24. package/dist/codegen/index.js +1 -1
  25. package/dist/data/builtins.d.ts +41 -82
  26. package/dist/data/client.d.ts +2 -2
  27. package/dist/data/decimal.d.ts +1 -1
  28. package/dist/data/document.d.ts +14 -0
  29. package/dist/data/index.d.ts +2 -2
  30. package/dist/data/manifest.d.ts +1 -1
  31. package/dist/data/schema.d.ts +1 -1
  32. package/dist/data/transport.d.ts +33 -26
  33. package/dist/data/ws-transport.d.ts +1 -1
  34. package/dist/data.js +97 -19
  35. package/dist/graphql/content-client.d.ts +13 -13
  36. package/dist/index.js +24 -0
  37. package/dist/live/drift.d.ts +1 -1
  38. package/dist/media/screen-capture.d.ts +1 -1
  39. package/dist/next/index.d.ts +2 -2
  40. package/dist/next/session.d.ts +10 -10
  41. package/dist/next.js +121 -61
  42. package/dist/placement/index.d.ts +15 -32
  43. package/dist/placement.js +18 -20
  44. package/dist/push.js +113 -46
  45. package/dist/react/FoirFeedback.d.ts +2 -2
  46. package/dist/react/FoirProvider.d.ts +23 -23
  47. package/dist/react/SignIn.d.ts +4 -4
  48. package/dist/react/UserButton.d.ts +1 -1
  49. package/dist/react/feedback-notes.d.ts +4 -4
  50. package/dist/react/index.d.ts +3 -3
  51. package/dist/react.js +168 -105
  52. package/dist/realtime/index.d.ts +1 -1
  53. package/dist/server/callback-client.d.ts +4 -4
  54. package/dist/server/events-client.d.ts +18 -18
  55. package/dist/server/operation-types.d.ts +8 -8
  56. package/dist/server/require-scoped-token.d.ts +3 -3
  57. package/dist/server/server-client.d.ts +1 -1
  58. package/dist/server/types.d.ts +1 -1
  59. package/dist/server/verify-scoped-token.d.ts +4 -28
  60. package/dist/server.js +67 -112
  61. package/dist/transport/foir-http.d.ts +57 -18
  62. package/dist/transport/key-kind.d.ts +40 -0
  63. package/dist/types/index.d.ts +2 -2
  64. package/package.json +3 -3
  65. package/dist/server/older-claims.generated.d.ts +0 -8
package/dist/data.js CHANGED
@@ -98,6 +98,28 @@ function refuseCredentialHeaders(extra) {
98
98
  }
99
99
  }
100
100
  var FOIR_VISITOR_IP_HEADER = "X-Foir-Visitor-IP";
101
+ function sentCoordinate(value) {
102
+ return Math.round(value * 100) / 100;
103
+ }
104
+ async function resolveFoirVisitor(source) {
105
+ const value = typeof source === "function" ? await source() : source;
106
+ if (value === null || value === void 0) return { place: {} };
107
+ if (typeof value === "string") {
108
+ const address2 = value.trim();
109
+ return { address: address2 || void 0, place: {} };
110
+ }
111
+ const address = value.address?.trim();
112
+ const country = value.country?.trim();
113
+ const place = {};
114
+ if (country) place.country = country;
115
+ if (Number.isFinite(value.latitude) && Number.isFinite(value.longitude)) {
116
+ place.location = {
117
+ latitude: sentCoordinate(value.latitude),
118
+ longitude: sentCoordinate(value.longitude)
119
+ };
120
+ }
121
+ return { address: address || void 0, place };
122
+ }
101
123
  function buildFoirHeaders(input) {
102
124
  const headers = {
103
125
  "Content-Type": "application/json"
@@ -144,8 +166,8 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
144
166
  downgrade;
145
167
  constructor(downgrade) {
146
168
  super(
147
- `[foir] your customer token was ${downgrade.customerToken} (${downgrade.reason}), so the request was served as ${downgrade.servedAs}`,
148
- { graphQLErrors: [{ message: "customer token rejected", extensions: { code: "AUTH_DOWNGRADED" } }] }
169
+ `[foir] your user token was ${downgrade.userToken} (${downgrade.reason}), so the request was served as ${downgrade.servedAs}`,
170
+ { graphQLErrors: [{ message: "user token rejected", extensions: { code: "AUTH_DOWNGRADED" } }] }
149
171
  );
150
172
  this.name = "FoirAuthDowngradedError";
151
173
  this.downgrade = downgrade;
@@ -153,7 +175,7 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
153
175
  };
154
176
  var FoirSessionExpiredError = class extends FoirRequestError {
155
177
  constructor(options) {
156
- super("[foir] the customer session has expired and could not be refreshed: sign in again", {
178
+ super("[foir] the user session has expired and could not be refreshed: sign in again", {
157
179
  cause: options?.cause,
158
180
  graphQLErrors: [{ message: "session expired", extensions: { code: "SESSION_EXPIRED" } }]
159
181
  });
@@ -170,7 +192,7 @@ function reportAuthDowngrade(envelope) {
170
192
  if (warnedDowngrade === downgrade.reason) return;
171
193
  warnedDowngrade = downgrade.reason;
172
194
  console.warn(
173
- `[foir] your customer token was ${downgrade.customerToken} (${downgrade.reason}) \u2014 this request was served as ${downgrade.servedAs}, so auth-targeted content resolved to its anonymous variant. ` + (downgrade.reason === "expired" ? "Re-exchange the token and retry." : "Check which credential you are sending.")
195
+ `[foir] your user token was ${downgrade.userToken} (${downgrade.reason}) \u2014 this request was served as ${downgrade.servedAs}, so auth-targeted content resolved to its anonymous variant. ` + (downgrade.reason === "expired" ? "Re-exchange the token and retry." : "Check which credential you are sending.")
174
196
  );
175
197
  }
176
198
  function refusePrunedDocument(json, options) {
@@ -214,6 +236,30 @@ function readFoirEnvelope(json, options) {
214
236
  return json.data;
215
237
  }
216
238
 
239
+ // src/transport/key-kind.ts
240
+ var KEY_PREFIXES = [
241
+ ["foir_pub_", "publishable"],
242
+ ["foir_srv_", "server"],
243
+ ["foir_adm_", "admin"],
244
+ ["pk_", "publishable"],
245
+ ["sk_", "older"],
246
+ ["tc_", "older"]
247
+ ];
248
+ var FOIR_CREDENTIALS_DOC = "https://docs.foir.dev/credentials";
249
+ function foirKeyKind(apiKey) {
250
+ if (typeof apiKey !== "string") return void 0;
251
+ for (const [prefix, kind] of KEY_PREFIXES) {
252
+ if (apiKey.startsWith(prefix)) return kind;
253
+ }
254
+ return void 0;
255
+ }
256
+ function adminKeyRefusal(client) {
257
+ return `[foir] ${client} was given an admin key. An admin key is a machine's own: nobody signs in through it, and an app never holds one. Build this client from your publishable key, or from your server key on the server that renders your pages. A machine that acts for itself uses createServerClient from @foir/sdk/server. See ${FOIR_CREDENTIALS_DOC}`;
258
+ }
259
+ function isPublishableFoirKey(apiKey) {
260
+ return foirKeyKind(apiKey) === "publishable";
261
+ }
262
+
217
263
  // src/transport/persisted-query.ts
218
264
  var FOIR_CDN_GRAPHQL_PATH = "/cdn/graphql";
219
265
  function persistedQueryExtension(hash) {
@@ -257,10 +303,7 @@ function foirDataEndpoint(apiUrl, path) {
257
303
  return foirApiEndpoint(apiUrl, path);
258
304
  }
259
305
  async function resolveVisitorAddress(config) {
260
- const source = config.visitor;
261
- const value = typeof source === "function" ? await source() : source;
262
- const address = value?.trim();
263
- return address ? address : void 0;
306
+ return (await resolveFoirVisitor(config.visitor)).address;
264
307
  }
265
308
  async function resolveBearerToken(config) {
266
309
  const source = config.bearerToken;
@@ -309,9 +352,13 @@ function assertFoirCredential(config) {
309
352
  "[foir] createFoirClient needs both apiUrl and apiKey (or, inside an operation endpoint, apiUrl and dispatch)"
310
353
  );
311
354
  }
312
- if (loose.visitor !== void 0 && !loose.apiKey.startsWith("sk_")) {
355
+ const kind = foirKeyKind(loose.apiKey);
356
+ if (kind === "admin") {
357
+ throw new FoirRequestError(adminKeyRefusal("createFoirClient"));
358
+ }
359
+ if (loose.visitor !== void 0 && kind !== "server" && kind !== "older") {
313
360
  throw new FoirRequestError(
314
- "[foir] createFoirClient: `visitor` names the visitor a server calls for, and only a secret key holding visitors:forward may send it. A public key already calls as its visitor, and cannot hold the permission. Drop `visitor`, or build this client from your server's secret key."
361
+ `[foir] createFoirClient: \`visitor\` names the visitor a server calls for, and only a server key holding visitors:forward may send it. A publishable key already calls as its visitor, and cannot hold the permission. Drop \`visitor\`, or build this client from your server key on the server that renders your pages. See ${FOIR_CREDENTIALS_DOC}`
315
362
  );
316
363
  }
317
364
  if (operation !== void 0) {
@@ -336,7 +383,7 @@ function assertFoirCredential(config) {
336
383
  ].filter((name) => loose[name] !== void 0);
337
384
  if (keySide.length > 0) {
338
385
  throw new FoirRequestError(
339
- `[foir] createFoirClient was given \`dispatch\` and ${keySide.map((n) => `\`${n}\``).join(", ")}. A dispatch token and an api key are different actors, and the dispatch token carries its own customer, organization and channel. Pass one credential: \`dispatch\` inside an operation endpoint, \`apiKey\` everywhere else.`
386
+ `[foir] createFoirClient was given \`dispatch\` and ${keySide.map((n) => `\`${n}\``).join(", ")}. A dispatch token and an api key are different actors, and the dispatch token carries its own user, organization and channel. Pass one credential: \`dispatch\` inside an operation endpoint, \`apiKey\` everywhere else.`
340
387
  );
341
388
  }
342
389
  const dispatch = loose.dispatch;
@@ -373,7 +420,7 @@ function contextOperation(context) {
373
420
  return void 0;
374
421
  }
375
422
  function foirRoute(input) {
376
- if (!input.apiKey.startsWith("pk_")) return { lane: "origin", reason: "key" };
423
+ if (!isPublishableFoirKey(input.apiKey)) return { lane: "origin", reason: "key" };
377
424
  if (input.bearerToken) return { lane: "origin", reason: "bearer" };
378
425
  if (input.orgId || input.orgUrl) return { lane: "origin", reason: "org" };
379
426
  if (input.mutation) return { lane: "origin", reason: "operation" };
@@ -894,13 +941,19 @@ function planFoirModelCall(source, call) {
894
941
  }
895
942
  return planCall(source, opDef, `${call.model}.${call.op}`, operationName(model.typeName, call.op), call);
896
943
  }
897
- var CREATING_OPS = /* @__PURE__ */ new Set(["create", "submit"]);
944
+ var CREATING_OPS = /* @__PURE__ */ new Set(["create"]);
898
945
  function withCreateIdempotencyKey(source, model, op, args) {
899
946
  if (!CREATING_OPS.has(op) || args.idempotencyKey !== void 0) return args;
900
947
  const argTypes = source.models[model]?.ops?.[op]?.argTypes;
901
948
  if (!argTypes || !("idempotencyKey" in argTypes)) return args;
902
949
  return { ...args, idempotencyKey: globalThis.crypto.randomUUID() };
903
950
  }
951
+ function withStatedVisitor(op, args, place) {
952
+ if (place.country === void 0 && place.location === void 0) return args;
953
+ if (!op?.argTypes || !("contexts" in op.argTypes)) return args;
954
+ const said = args.contexts ?? {};
955
+ return { ...args, contexts: { ...place, ...said } };
956
+ }
904
957
  function planFoirNamespaceCall(source, call) {
905
958
  const namespace = source.namespaces?.[call.namespace];
906
959
  if (!namespace) {
@@ -1358,7 +1411,7 @@ var FoirSocketTransport = class {
1358
1411
  constructor(config) {
1359
1412
  if (config.dispatch !== void 0) {
1360
1413
  throw new FoirRequestError(
1361
- "[foir] a client built from a dispatch token cannot subscribe. The subscription socket authenticates an api key, an admin token or a customer bearer, and has no path for a dispatch token. Queries and mutations made as the operation go to /graphql and work as they are."
1414
+ "[foir] a client built from a dispatch token cannot subscribe. The subscription socket authenticates an api key, a console token or a user bearer, and has no path for a dispatch token. Queries and mutations made as the operation go to /graphql and work as they are."
1362
1415
  );
1363
1416
  }
1364
1417
  this.config = config;
@@ -2260,20 +2313,43 @@ function createFoirClient(clientConfig) {
2260
2313
  detectedDrift
2261
2314
  );
2262
2315
  };
2316
+ const visitorOfThisRequest = async () => {
2317
+ if (config.dispatch !== void 0 || config.visitor === void 0) {
2318
+ return { config, place: {} };
2319
+ }
2320
+ const { address, place } = await resolveFoirVisitor(config.visitor);
2321
+ return {
2322
+ config: {
2323
+ ...config,
2324
+ visitor: {
2325
+ address,
2326
+ country: place.country,
2327
+ latitude: place.location?.latitude,
2328
+ longitude: place.location?.longitude
2329
+ }
2330
+ },
2331
+ place
2332
+ };
2333
+ };
2263
2334
  const runModel = async (model, op, query) => {
2264
2335
  assertStillServed(`${model}.${op}`, (served) => served.modelCall(model, op, query?.include));
2265
2336
  const { args, include, omit, pick, depth } = splitQuery(query);
2266
2337
  const source = await selectionSource();
2338
+ const visitor = await visitorOfThisRequest();
2267
2339
  const plan = planFoirModelCall(source, {
2268
2340
  model,
2269
2341
  op,
2270
- args: withCreateIdempotencyKey(source, model, op, args),
2342
+ args: withStatedVisitor(
2343
+ source.models[model]?.ops?.[op],
2344
+ withCreateIdempotencyKey(source, model, op, args),
2345
+ visitor.place
2346
+ ),
2271
2347
  include,
2272
2348
  omit,
2273
2349
  pick,
2274
2350
  depth
2275
2351
  });
2276
- const result = await executeFoirDocument(config, plan);
2352
+ const result = await executeFoirDocument(visitor.config, plan);
2277
2353
  recordFoirSubjects(config.subjects, plan, result);
2278
2354
  maybeCheckDrift();
2279
2355
  return result;
@@ -2284,16 +2360,18 @@ function createFoirClient(clientConfig) {
2284
2360
  (served) => served.namespaceCall(namespace, op, query?.include)
2285
2361
  );
2286
2362
  const { args, include, omit, pick, depth } = splitQuery(query);
2287
- const plan = planFoirNamespaceCall(await selectionSource(), {
2363
+ const source = await selectionSource();
2364
+ const visitor = await visitorOfThisRequest();
2365
+ const plan = planFoirNamespaceCall(source, {
2288
2366
  namespace,
2289
2367
  op,
2290
- args,
2368
+ args: withStatedVisitor(source.namespaces?.[namespace]?.ops?.[op], args, visitor.place),
2291
2369
  include,
2292
2370
  omit,
2293
2371
  pick,
2294
2372
  depth
2295
2373
  });
2296
- const result = await executeFoirDocument(config, plan);
2374
+ const result = await executeFoirDocument(visitor.config, plan);
2297
2375
  recordFoirSubjects(config.subjects, plan, result);
2298
2376
  maybeCheckDrift();
2299
2377
  return result;
@@ -1,19 +1,19 @@
1
1
  /**
2
- * Session-bound content client — forwards the customer bearer on every read
3
- * when one is available, so auth/segment-targeted variants and customer-scoped
2
+ * Session-bound content client — forwards the user bearer on every read
3
+ * when one is available, so auth/segment-targeted variants and user-scoped
4
4
  * records resolve out of the box, with no per-query wiring to forget.
5
5
  *
6
6
  * Resolution keys off the request's principal (see the platform's two-gate
7
7
  * model): the `x-api-key` alone resolves the *anonymous baseline*
8
- * (`context.authStatus = ""`); adding the customer bearer resolves the request
9
- * as that customer (`context.authStatus = "authenticated"`, `customer_id` set).
8
+ * (`context.authStatus = ""`); adding the user bearer resolves the request
9
+ * as that user (`context.authStatus = "authenticated"`, `user_id` set).
10
10
  *
11
11
  * Caching: an api-key-only read is identical for every anonymous visitor and is
12
- * shared-cacheable; a bearer-bearing read resolves per-customer and is not.
13
- * Because the bearer only exists once a customer signs in, anonymous traffic
12
+ * shared-cacheable; a bearer-bearing read resolves per-user and is not.
13
+ * Because the bearer only exists once a user signs in, anonymous traffic
14
14
  * keeps hitting the shared-cacheable baseline — only signed-in reads become
15
- * per-customer. Bind this client wherever content is personalized (for most
16
- * apps, everywhere the customer may be signed in) and use plain `foirRequest`
15
+ * per-user. Bind this client wherever content is personalized (for most
16
+ * apps, everywhere the user may be signed in) and use plain `foirRequest`
17
17
  * for reads that must stay anonymous regardless of session.
18
18
  */
19
19
  import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
@@ -25,9 +25,9 @@ import type { FoirTokenProvider } from '../transport/foir-http';
25
25
  export interface FoirContentClientConfig {
26
26
  env: FoirEnv;
27
27
  /**
28
- * Resolves the current customer bearer before every request. When it yields a
28
+ * Resolves the current user bearer before every request. When it yields a
29
29
  * token the token is forwarded, so `authStatus`/segment targeting and
30
- * customer-scoped records resolve as that customer; when it yields
30
+ * user-scoped records resolve as that user; when it yields
31
31
  * null/undefined the read hits the anonymous baseline. Omit for a client that
32
32
  * is always anonymous (equivalent to calling `foirRequest` directly).
33
33
  */
@@ -51,7 +51,7 @@ export interface FoirContentClientConfig {
51
51
  }
52
52
  export interface FoirContentClient {
53
53
  /**
54
- * Run a typed document, forwarding the bound customer bearer when available.
54
+ * Run a typed document, forwarding the bound user bearer when available.
55
55
  * An explicit `options.bearerToken` still wins, so a single call can override
56
56
  * the bound token (or force anonymous by passing `undefined` — the bound
57
57
  * token only fills in when `options.bearerToken` is not supplied).
@@ -60,7 +60,7 @@ export interface FoirContentClient {
60
60
  }
61
61
  /**
62
62
  * Create a {@link FoirContentClient} bound to an env + token source. Every
63
- * `request` forwards the customer bearer when `getToken` yields one, upgrading
64
- * that read from the anonymous baseline to the signed-in customer.
63
+ * `request` forwards the user bearer when `getToken` yields one, upgrading
64
+ * that read from the anonymous baseline to the signed-in user.
65
65
  */
66
66
  export declare function createFoirContentClient(config: FoirContentClientConfig): FoirContentClient;
package/dist/index.js CHANGED
@@ -94,6 +94,27 @@ function isValidHostMessage(data) {
94
94
  return true;
95
95
  }
96
96
 
97
+ // src/transport/key-kind.ts
98
+ var KEY_PREFIXES = [
99
+ ["foir_pub_", "publishable"],
100
+ ["foir_srv_", "server"],
101
+ ["foir_adm_", "admin"],
102
+ ["pk_", "publishable"],
103
+ ["sk_", "older"],
104
+ ["tc_", "older"]
105
+ ];
106
+ var FOIR_CREDENTIALS_DOC = "https://docs.foir.dev/credentials";
107
+ function foirKeyKind(apiKey) {
108
+ if (typeof apiKey !== "string") return void 0;
109
+ for (const [prefix, kind] of KEY_PREFIXES) {
110
+ if (apiKey.startsWith(prefix)) return kind;
111
+ }
112
+ return void 0;
113
+ }
114
+ function adminKeyRefusal(client) {
115
+ return `[foir] ${client} was given an admin key. An admin key is a machine's own: nobody signs in through it, and an app never holds one. Build this client from your publishable key, or from your server key on the server that renders your pages. A machine that acts for itself uses createServerClient from @foir/sdk/server. See ${FOIR_CREDENTIALS_DOC}`;
116
+ }
117
+
97
118
  // src/client/platform-client.ts
98
119
  var PlatformClientError = class extends Error {
99
120
  constructor(message, status, response) {
@@ -107,6 +128,9 @@ var PlatformClientError = class extends Error {
107
128
  };
108
129
  function createPlatformClient(options) {
109
130
  const { apiUrl, apiKey } = options;
131
+ if (foirKeyKind(apiKey) === "admin") {
132
+ throw new PlatformClientError(adminKeyRefusal("createPlatformClient"));
133
+ }
110
134
  return {
111
135
  async query(query, variables) {
112
136
  const res = await fetch(apiUrl, {
@@ -12,7 +12,7 @@ import type { FoirSchemaDrift } from '../data/transport';
12
12
  * Nothing else catches it. The dependency graph is about records, and no record
13
13
  * changed. `seq` is about ordering, and nothing is out of order. The entry is
14
14
  * fresh, correctly tagged, correctly stamped, and describes a schema that no
15
- * longer exists — until the tab is reloaded, which on a long-lived admin
15
+ * longer exists — until the tab is reloaded, which on a long-lived console
16
16
  * session can be days.
17
17
  *
18
18
  * The SDK already detects this: the data client compares the surface version
@@ -6,7 +6,7 @@
6
6
  * ---------------------------------------------------------------------------
7
7
  *
8
8
  * Two surfaces need the same picture: the console's own bug report, and the
9
- * feedback widget a customer's visitors use (`@foir/sdk/react`). One of those
9
+ * feedback widget a user's visitors use (`@foir/sdk/react`). One of those
10
10
  * ships to npm and the other does not, so the shared half has to sit in the
11
11
  * published package — a copy in each would be two answers to "how big is a
12
12
  * screenshot", free to drift, and the drift would only show up as an upload the
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `@foir/sdk/next` — server-side Foir customer auth for the Next.js App Router
2
+ * `@foir/sdk/next` — server-side Foir user auth for the Next.js App Router
3
3
  * (the BFF pattern): an HttpOnly-cookie session adapter, server-side session
4
4
  * helpers, a provider-callback exchange, and a route-protection middleware.
5
5
  *
@@ -18,5 +18,5 @@ export { readFoirCacheTags, foirCacheTags, createFoirTaggingFetch, foirTagsForRe
18
18
  export type { FoirHeaderSource, FoirCacheTags, FoirCacheTagsOptions, FoirTaggingReport, FoirTaggingFetchOptions, FoirRecordChange, } from './cacheTags';
19
19
  export { createFoirMiddleware } from './middleware';
20
20
  export type { FoirMiddlewareConfig, FoirMiddlewareRequest } from './middleware';
21
- export type { FoirCustomer, SessionAdapter } from '../auth';
21
+ export type { FoirUser, SessionAdapter } from '../auth';
22
22
  export type { FoirEnv } from '../graphql/foir-request';
@@ -1,4 +1,4 @@
1
- import type { FoirCustomer } from '../auth';
1
+ import type { FoirUser } from '../auth';
2
2
  import type { FoirEnv } from '../graphql/foir-request';
3
3
  import type { CookieAdapterOptions, FoirCookieStore } from './cookieAdapter';
4
4
  /**
@@ -6,14 +6,14 @@ import type { CookieAdapterOptions, FoirCookieStore } from './cookieAdapter';
6
6
  * cookie store (`await cookies()` in a route handler / server action, or the
7
7
  * read-only `cookies()` in a Server Component for reads).
8
8
  *
9
- * Note on "verification": the customer access token is opaque to your app and
9
+ * Note on "verification": the user access token is opaque to your app and
10
10
  * validated by the Foir API on use, so `getFoirSession` returns the identity
11
11
  * stored in the cookies rather than locally verifying a JWT. A rejected/expired
12
12
  * bearer surfaces when you call the API (and `@foir/sdk/auth`'s `authedRequest`
13
13
  * transparently refreshes it).
14
14
  */
15
- /** The signed-in customer from the session cookies, or null. */
16
- export declare function getFoirSession(store: FoirCookieStore): Promise<FoirCustomer | null>;
15
+ /** The signed-in user from the session cookies, or null. */
16
+ export declare function getFoirSession(store: FoirCookieStore): Promise<FoirUser | null>;
17
17
  /** The current access token from the session cookies, or null. */
18
18
  export declare function getFoirToken(store: FoirCookieStore): Promise<string | null>;
19
19
  /** Clear the session cookies (sign out). */
@@ -26,9 +26,9 @@ interface PasswordArgs {
26
26
  cookieOptions?: CookieAdapterOptions['cookieOptions'];
27
27
  }
28
28
  /** Password sign-in in a route handler; persists the session to cookies. */
29
- export declare function foirSignInWithPassword({ env, store, email, password, cookieOptions, }: PasswordArgs): Promise<FoirCustomer>;
30
- /** Register a customer in a route handler; persists the session to cookies. */
31
- export declare function foirRegisterWithPassword({ env, store, email, password, cookieOptions, }: PasswordArgs): Promise<FoirCustomer>;
29
+ export declare function foirSignInWithPassword({ env, store, email, password, cookieOptions, }: PasswordArgs): Promise<FoirUser>;
30
+ /** Register a user in a route handler; persists the session to cookies. */
31
+ export declare function foirRegisterWithPassword({ env, store, email, password, cookieOptions, }: PasswordArgs): Promise<FoirUser>;
32
32
  /** Complete an OTP sign-in in a route handler; persists the session to cookies. */
33
33
  export declare function foirSignInWithOtp({ env, store, email, otp, cookieOptions, }: {
34
34
  env: FoirEnv;
@@ -36,11 +36,11 @@ export declare function foirSignInWithOtp({ env, store, email, otp, cookieOption
36
36
  email: string;
37
37
  otp: string;
38
38
  cookieOptions?: CookieAdapterOptions['cookieOptions'];
39
- }): Promise<FoirCustomer>;
39
+ }): Promise<FoirUser>;
40
40
  /**
41
41
  * Complete a provider (OAuth/OIDC) login in your callback route handler:
42
42
  * exchange the `code` + `state` for tokens and persist them to the session
43
- * cookies. Returns the customer.
43
+ * cookies. Returns the user.
44
44
  */
45
45
  export declare function completeFoirProviderLogin(opts: {
46
46
  env: FoirEnv;
@@ -49,5 +49,5 @@ export declare function completeFoirProviderLogin(opts: {
49
49
  code?: string;
50
50
  state?: string;
51
51
  cookieOptions?: CookieAdapterOptions['cookieOptions'];
52
- }): Promise<FoirCustomer>;
52
+ }): Promise<FoirUser>;
53
53
  export {};