@alxia/react-router 0.13.0 → 0.14.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 (76) hide show
  1. package/README.md +78 -0
  2. package/dist/chunks/index-0tyw54ad.js +160 -0
  3. package/dist/chunks/index-0tyw54ad.js.map +15 -0
  4. package/dist/chunks/index-c3k47yw7.js +124 -0
  5. package/dist/chunks/index-c3k47yw7.js.map +14 -0
  6. package/dist/errors/api-error.d.ts +18 -0
  7. package/dist/errors/api-error.d.ts.map +1 -1
  8. package/dist/errors/index.d.ts +1 -1
  9. package/dist/errors/index.d.ts.map +1 -1
  10. package/dist/errors/index.js +45 -110
  11. package/dist/errors/index.js.map +4 -8
  12. package/dist/errors/json-actions.d.ts.map +1 -1
  13. package/dist/errors/same-site.d.ts +25 -0
  14. package/dist/errors/same-site.d.ts.map +1 -0
  15. package/dist/session/codes.d.ts +7 -0
  16. package/dist/session/codes.d.ts.map +1 -0
  17. package/dist/session/cookies.d.ts +60 -0
  18. package/dist/session/cookies.d.ts.map +1 -0
  19. package/dist/session/flow-types.d.ts +178 -0
  20. package/dist/session/flow-types.d.ts.map +1 -0
  21. package/dist/session/guard.d.ts +10 -0
  22. package/dist/session/guard.d.ts.map +1 -0
  23. package/dist/session/index.d.ts +18 -0
  24. package/dist/session/index.d.ts.map +1 -0
  25. package/dist/session/index.js +637 -0
  26. package/dist/session/index.js.map +23 -0
  27. package/dist/session/land.d.ts +26 -0
  28. package/dist/session/land.d.ts.map +1 -0
  29. package/dist/session/link-land.d.ts +18 -0
  30. package/dist/session/link-land.d.ts.map +1 -0
  31. package/dist/session/link-token.d.ts +22 -0
  32. package/dist/session/link-token.d.ts.map +1 -0
  33. package/dist/session/link-types.d.ts +124 -0
  34. package/dist/session/link-types.d.ts.map +1 -0
  35. package/dist/session/links.d.ts +14 -0
  36. package/dist/session/links.d.ts.map +1 -0
  37. package/dist/session/model/index.d.ts +7 -0
  38. package/dist/session/model/index.d.ts.map +1 -0
  39. package/dist/session/model/index.js +25 -0
  40. package/dist/session/model/index.js.map +9 -0
  41. package/dist/session/model/paths.d.ts +24 -0
  42. package/dist/session/model/paths.d.ts.map +1 -0
  43. package/dist/session/model/safe-next.d.ts +15 -0
  44. package/dist/session/model/safe-next.d.ts.map +1 -0
  45. package/dist/session/model/second-factor.d.ts +16 -0
  46. package/dist/session/model/second-factor.d.ts.map +1 -0
  47. package/dist/session/model/site-path.d.ts +10 -0
  48. package/dist/session/model/site-path.d.ts.map +1 -0
  49. package/dist/session/model/step-up-answers.d.ts +40 -0
  50. package/dist/session/model/step-up-answers.d.ts.map +1 -0
  51. package/dist/session/model/step-up-props.d.ts +21 -0
  52. package/dist/session/model/step-up-props.d.ts.map +1 -0
  53. package/dist/session/model/step-up.d.ts +48 -0
  54. package/dist/session/model/step-up.d.ts.map +1 -0
  55. package/dist/session/second-factor.d.ts +22 -0
  56. package/dist/session/second-factor.d.ts.map +1 -0
  57. package/dist/session/serialize.d.ts +34 -0
  58. package/dist/session/serialize.d.ts.map +1 -0
  59. package/dist/session/sign-in.d.ts +17 -0
  60. package/dist/session/sign-in.d.ts.map +1 -0
  61. package/dist/session/step-up-codes.d.ts +9 -0
  62. package/dist/session/step-up-codes.d.ts.map +1 -0
  63. package/dist/session/step-up-types.d.ts +69 -0
  64. package/dist/session/step-up-types.d.ts.map +1 -0
  65. package/dist/session/step-up.d.ts +17 -0
  66. package/dist/session/step-up.d.ts.map +1 -0
  67. package/dist/session/step.d.ts +20 -0
  68. package/dist/session/step.d.ts.map +1 -0
  69. package/dist/session/viewer.d.ts +33 -0
  70. package/dist/session/viewer.d.ts.map +1 -0
  71. package/docs/README.md +1 -0
  72. package/docs/guide/errors.md +19 -0
  73. package/docs/guide/session.md +955 -0
  74. package/docs/roadmap.md +27 -0
  75. package/docs/troubleshooting.md +362 -1
  76. package/package.json +15 -2
@@ -1,22 +1,18 @@
1
- // src/errors/api-error.ts
2
- var isNamed = (error, name) => error instanceof Error && error.name === name;
3
- function isApiErrorLike(error) {
4
- return isNamed(error, "ApiError") && Array.isArray(error.errors) && typeof error.status === "number";
5
- }
6
- function waitMinutes(extensions) {
7
- const minutes = extensions?.params?.minutes ?? extensions?.minutes;
8
- if (minutes !== undefined)
9
- return Math.max(1, Number(minutes) || 1);
10
- const seconds = extensions?.params?.retryAfter ?? extensions?.retryAfter;
11
- return Math.max(1, Math.ceil(Number(seconds) / 60) || 1);
12
- }
13
- function valuesOf(extensions) {
14
- if (!extensions)
15
- return;
16
- return extensions.params ? { ...extensions, ...extensions.params } : extensions;
17
- }
18
- var isStatusError = (error) => isNamed(error, "ApiStatusError") && typeof error.status === "number";
19
- var isUnavailableError = (error) => isNamed(error, "ApiUnavailableError") && typeof error.reason === "string";
1
+ import {
2
+ isApiErrorLike2,
3
+ waitMinutes2,
4
+ attemptsLeftOf2,
5
+ valuesOf,
6
+ isStatusError,
7
+ isUnavailableError,
8
+ REQUEST_ID_HEADER2,
9
+ requestIdOf2,
10
+ routeError2,
11
+ errorRequestId2,
12
+ nextOf2,
13
+ siteCheck,
14
+ rememberSiteCheck
15
+ } from "../chunks/index-c3k47yw7.js";
20
16
  // src/errors/code-resolver.ts
21
17
  var API_CODE = /^[a-z-]+\.errors\.[a-z0-9-]+$/;
22
18
  function paramsCode(issue) {
@@ -40,7 +36,7 @@ function apiCodeResolver(messages, options) {
40
36
 
41
37
  // src/errors/describe-refusal.ts
42
38
  function refusalOf(errors, error, language) {
43
- if (isApiErrorLike(error)) {
39
+ if (isApiErrorLike2(error)) {
44
40
  return {
45
41
  message: errors.apiErrorMessage(error, language),
46
42
  status: error.status
@@ -64,50 +60,11 @@ function fieldErrorsOf(errors, error, language) {
64
60
  }
65
61
 
66
62
  // src/errors/fetcher-result.ts
67
- import { data as data2 } from "react-router";
68
-
69
- // src/errors/route-error.ts
70
63
  import { data } from "react-router";
71
-
72
- // src/errors/request-id.ts
73
- var REQUEST_ID_HEADER = "x-request-id";
74
- function requestIdOf(response) {
75
- return response.headers.get(REQUEST_ID_HEADER) || undefined;
76
- }
77
-
78
- // src/errors/route-error.ts
79
- var ROUTED = new Set([401, 403, 404, 503]);
80
- function routeError(error, { statuses = ROUTED } = {}) {
81
- if (isApiErrorLike(error)) {
82
- const { requestId } = error;
83
- if (statuses.has(error.status)) {
84
- return data({ code: error.code, message: error.message, requestId }, { status: error.status });
85
- }
86
- return requestId ? data({ requestId }, { status: 500 }) : error;
87
- }
88
- if (error instanceof Response && statuses.has(error.status)) {
89
- const requestId = requestIdOf(error);
90
- if (requestId) {
91
- return data({ requestId }, { status: error.status });
92
- }
93
- }
94
- return error;
95
- }
96
- function errorRequestId(error) {
97
- if (typeof error !== "object" || error === null)
98
- return;
99
- const { data: body } = error;
100
- if (typeof body !== "object" || body === null)
101
- return;
102
- const { requestId } = body;
103
- return typeof requestId === "string" && requestId ? requestId : undefined;
104
- }
105
-
106
- // src/errors/fetcher-result.ts
107
64
  function fetcherRefusal(errors, error, language, route) {
108
- const refusal = isApiErrorLike(error) && error.status === 401 ? undefined : errors.apiRefusal(error, language);
65
+ const refusal = isApiErrorLike2(error) && error.status === 401 ? undefined : errors.apiRefusal(error, language);
109
66
  if (!refusal)
110
- throw routeError(error, route);
67
+ throw routeError2(error, route);
111
68
  return refusal;
112
69
  }
113
70
  async function fetcherResult(errors, language, about, run, route) {
@@ -115,22 +72,22 @@ async function fetcherResult(errors, language, about, run, route) {
115
72
  return { ok: true, ...about, ...await run() };
116
73
  } catch (error) {
117
74
  const { message, status } = fetcherRefusal(errors, error, language, route);
118
- return data2({ ok: false, ...about, error: message }, { status });
75
+ return data({ ok: false, ...about, error: message }, { status });
119
76
  }
120
77
  }
121
78
 
122
79
  // src/errors/submit-form.ts
123
- import { data as data3 } from "react-router";
80
+ import { data as data2 } from "react-router";
124
81
  async function submitForm(errors, language, run, fieldOf, route) {
125
82
  try {
126
83
  return { ok: true, value: await run() };
127
84
  } catch (error) {
128
- if (!isApiErrorLike(error) || error.status === 401) {
129
- throw routeError(error, route);
85
+ if (!isApiErrorLike2(error) || error.status === 401) {
86
+ throw routeError2(error, route);
130
87
  }
131
88
  const field = error.errors[0]?.extensions?.field;
132
89
  if (error.status === 404 && !(field && fieldOf(field))) {
133
- throw routeError(error, route);
90
+ throw routeError2(error, route);
134
91
  }
135
92
  const byField = {};
136
93
  const unplaced = [];
@@ -142,7 +99,7 @@ async function submitForm(errors, language, run, fieldOf, route) {
142
99
  unplaced.push(message);
143
100
  }
144
101
  const formError = Object.keys(byField).length && !unplaced.length ? undefined : [errors.apiErrorMessage(error, language), ...unplaced].join(" ");
145
- return data3({ fieldErrors: byField, formError }, { status: error.status });
102
+ return data2({ fieldErrors: byField, formError }, { status: error.status });
146
103
  }
147
104
  }
148
105
 
@@ -217,12 +174,12 @@ function apiCallFailure(error, {
217
174
  }) {
218
175
  const log = quietLog(appLog, ["warn", "error"]);
219
176
  const call = `${api}: ${operation}${requestId ? ` (request ${requestId})` : ""}`;
220
- const headers = requestId ? { [REQUEST_ID_HEADER]: requestId } : {};
177
+ const headers = requestId ? { [REQUEST_ID_HEADER2]: requestId } : {};
221
178
  const unavailable = (reason, cause) => {
222
179
  log.error(`${call} ${reason}`, cause ?? "");
223
180
  return new Response(null, { status: 503, headers });
224
181
  };
225
- if (isApiErrorLike(error)) {
182
+ if (isApiErrorLike2(error)) {
226
183
  if (requestId)
227
184
  error.requestId = requestId;
228
185
  const line = `${call} answered ${error.status}${error.code ? ` ${error.code}` : ""}`;
@@ -434,61 +391,38 @@ function createErrorCatalogue({
434
391
  };
435
392
  }
436
393
  // src/errors/json-actions.ts
437
- import { data as data4, redirect } from "react-router";
438
-
439
- // src/errors/page-path.ts
440
- function nextOf(url) {
441
- const { pathname, searchParams } = new URL(url);
442
- const trimmed = pathname.endsWith("/_.data") ? pathname.slice(0, -"_.data".length) : pathname.replace(/\.data$/, "");
443
- const path = trimmed.replace(/^\/{2,}/, "/");
444
- const params = new URLSearchParams(searchParams);
445
- params.delete("_routes");
446
- for (const value of params.getAll("index")) {
447
- if (!value)
448
- params.delete("index", value);
449
- }
450
- const search = params.toString();
451
- return search ? `${path}?${search}` : path;
452
- }
453
-
454
- // src/errors/json-actions.ts
394
+ import { data as data3, redirect } from "react-router";
455
395
  function jsonActions(options = {}) {
456
- const ownOrigin = (request) => {
457
- const { origin } = options;
458
- const set = typeof origin === "function" ? origin() : origin;
459
- return set ?? new URL(request.url).origin;
460
- };
396
+ const crossSite = siteCheck(options.origin);
461
397
  const isJson = (request) => request.headers.get("content-type")?.startsWith("application/json");
462
398
  async function readJson(request) {
463
- const origin = request.headers.get("origin");
464
- const site = request.headers.get("sec-fetch-site");
465
- if (origin && origin !== ownOrigin(request) || site && site !== "same-origin" && site !== "none") {
466
- throw data4("Cross-site request refused", { status: 403 });
467
- }
399
+ crossSite(request);
468
400
  if (!isJson(request)) {
469
- throw data4("Expected a JSON body", { status: 415 });
401
+ throw data3("Expected a JSON body", { status: 415 });
470
402
  }
471
403
  return request.json().catch(() => {
472
- throw data4("Malformed JSON body", { status: 400 });
404
+ throw data3("Malformed JSON body", { status: 400 });
473
405
  });
474
406
  }
475
- return {
407
+ const actions = {
476
408
  readJson,
477
409
  requireJsonPost(request) {
478
410
  if (!isJson(request))
479
- throw redirect(nextOf(request.url));
411
+ throw redirect(nextOf2(request.url));
480
412
  },
481
413
  async readInput(request, schema) {
482
414
  const body = await readJson(request);
483
415
  const result = await schema["~standard"].validate(body?.input);
484
416
  if (result.issues) {
485
- throw data4("The form sent an input the API would refuse", {
417
+ throw data3("The form sent an input the API would refuse", {
486
418
  status: 400
487
419
  });
488
420
  }
489
421
  return result.value;
490
422
  }
491
423
  };
424
+ rememberSiteCheck(actions, crossSite);
425
+ return actions;
492
426
  }
493
427
  // src/errors/message-values.ts
494
428
  var DAY = /^(\d{4})-(\d{2})-(\d{2})$/;
@@ -584,22 +518,23 @@ function useJsonFetcher(key, action) {
584
518
  }
585
519
  export {
586
520
  ApiMessagesProvider,
587
- REQUEST_ID_HEADER,
521
+ REQUEST_ID_HEADER2 as REQUEST_ID_HEADER,
588
522
  apiCallFailure,
589
523
  apiCodeResolver,
524
+ attemptsLeftOf2 as attemptsLeftOf,
590
525
  createApiErrors,
591
526
  createApiMessages,
592
527
  createErrorCatalogue,
593
- errorRequestId,
594
- isApiErrorLike,
528
+ errorRequestId2 as errorRequestId,
529
+ isApiErrorLike2 as isApiErrorLike,
595
530
  jsonActions,
596
- nextOf,
531
+ nextOf2 as nextOf,
597
532
  operationName,
598
- requestIdOf,
599
- routeError,
533
+ requestIdOf2 as requestIdOf,
534
+ routeError2 as routeError,
600
535
  useJsonFetcher,
601
- waitMinutes
536
+ waitMinutes2 as waitMinutes
602
537
  };
603
538
 
604
- //# debugId=10F8AF81866444B364756E2164756E21
539
+ //# debugId=0489566B0456068164756E2164756E21
605
540
  //# sourceMappingURL=index.js.map
@@ -1,13 +1,10 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/errors/api-error.ts", "../src/errors/code-resolver.ts", "../src/errors/describe-refusal.ts", "../src/errors/fetcher-result.ts", "../src/errors/route-error.ts", "../src/errors/request-id.ts", "../src/errors/submit-form.ts", "../src/errors/describe.ts", "../src/errors/api-errors.ts", "../src/errors/log.ts", "../src/errors/call-failure.ts", "../src/errors/catalogue-check.ts", "../src/errors/catalogue-read.ts", "../src/errors/catalogue.ts", "../src/errors/json-actions.ts", "../src/errors/page-path.ts", "../src/errors/message-values.ts", "../src/errors/messages.ts", "../src/errors/provider.ts", "../src/errors/use-json-fetcher.ts"],
3
+ "sources": ["../src/errors/code-resolver.ts", "../src/errors/describe-refusal.ts", "../src/errors/fetcher-result.ts", "../src/errors/submit-form.ts", "../src/errors/describe.ts", "../src/errors/api-errors.ts", "../src/errors/log.ts", "../src/errors/call-failure.ts", "../src/errors/catalogue-check.ts", "../src/errors/catalogue-read.ts", "../src/errors/catalogue.ts", "../src/errors/json-actions.ts", "../src/errors/message-values.ts", "../src/errors/messages.ts", "../src/errors/provider.ts", "../src/errors/use-json-fetcher.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * The shape of an API's refusal, as `@nxgt/graphql-client`'s `ApiError`\n * carries it, declared structurally: `/errors` never imports the client, so\n * an app needs it only if it calls the API through it. `api-error.spec.ts`\n * holds the two in step.\n */\n\n/** One refused input field: `extensions.fields` of a validation refusal. */\nexport interface ApiFieldErrorLike {\n\treadonly path: string;\n\treadonly code: string;\n\treadonly message: string;\n\t/** The values the field's message interpolates. */\n\treadonly params?: Readonly<Record<string, unknown>>;\n}\n\n/** The values a message interpolates; a throttle's wait is `minutes` or `retryAfter`. */\nexport interface ApiErrorParamsLike {\n\treadonly minutes?: unknown;\n\treadonly retryAfter?: unknown;\n\treadonly [key: string]: unknown;\n}\n\n/**\n * One GraphQL error's `extensions`. `code` is the API's own\n * `<module>.errors.<slug>`; the rest is what its messages name.\n */\nexport interface ApiErrorExtensionsLike {\n\treadonly code?: string;\n\t/** The values the message interpolates, when the API sends them. */\n\treadonly params?: ApiErrorParamsLike;\n\t/** A validation refusal: every field at fault, by input path. */\n\treadonly fields?: readonly ApiFieldErrorLike[];\n\t/** Any other refusal about one input field, by its path. */\n\treadonly field?: string;\n\t/** A throttle's wait, in minutes (`waitMinutes` coerces a string). */\n\treadonly minutes?: unknown;\n\t/** A throttle's wait, in seconds. */\n\treadonly retryAfter?: unknown;\n\treadonly [key: string]: unknown;\n}\n\n/** One error of a response's `errors`. */\nexport interface ApiErrorEntryLike {\n\treadonly message: string;\n\treadonly extensions?: ApiErrorExtensionsLike;\n}\n\n/** A refusal read from a GraphQL API: what `ApiError` has, and the request id. */\nexport interface ApiErrorLike extends Error {\n\treadonly errors: readonly ApiErrorEntryLike[];\n\t/** The first error's `extensions.code`. */\n\treadonly code: string | undefined;\n\t/** The HTTP status to answer with. */\n\treadonly status: number;\n\t/** The id the API logged the request under, when the caller kept it. */\n\treadonly requestId?: string;\n}\n\n/** Whether `error` is an `Error` of this `name`: the client's errors are told by it, never `instanceof`. */\nexport const isNamed = (error: unknown, name: string): error is Error =>\n\terror instanceof Error && error.name === name;\n\n/**\n * Whether `error` is an `ApiError` of `@nxgt/graphql-client`, by the test\n * that client's `isApiError` makes (an `Error` named `ApiError` with an\n * `errors` array), plus a numeric `status`, which `ApiErrorLike` promises.\n * It holds across two copies of the client.\n */\nexport function isApiErrorLike(error: unknown): error is ApiErrorLike {\n\treturn (\n\t\tisNamed(error, 'ApiError') &&\n\t\tArray.isArray((error as { errors?: unknown }).errors) &&\n\t\ttypeof (error as { status?: unknown }).status === 'number'\n\t);\n}\n\n/**\n * The minutes a wait lasts, as the API words it: `minutes` (at least one, in\n * `extensions.params` or beside it), else the `retryAfter` seconds rounded\n * up, else one.\n */\nexport function waitMinutes(\n\textensions: ApiErrorExtensionsLike | undefined,\n): number {\n\tconst minutes = extensions?.params?.minutes ?? extensions?.minutes;\n\tif (minutes !== undefined) return Math.max(1, Number(minutes) || 1);\n\tconst seconds = extensions?.params?.retryAfter ?? extensions?.retryAfter;\n\treturn Math.max(1, Math.ceil(Number(seconds) / 60) || 1);\n}\n\n/**\n * The values a message names: `extensions.params` over the extensions\n * themselves, where older errors and the extras of a few sit.\n */\nexport function valuesOf(\n\textensions: ApiErrorExtensionsLike | undefined,\n): Record<string, unknown> | undefined {\n\tif (!extensions) return undefined;\n\treturn extensions.params\n\t\t? { ...extensions, ...extensions.params }\n\t\t: extensions;\n}\n\n/** `@nxgt/graphql-client`'s `ApiStatusError`, as far as the failure reads it. */\nexport interface StatusErrorLike extends Error {\n\tstatus: number;\n\tstatusText?: string | undefined;\n\tbody?: unknown;\n}\n\n/** `@nxgt/graphql-client`'s `ApiUnavailableError`, as far as the failure reads it. */\nexport interface UnavailableErrorLike extends Error {\n\treason: string;\n}\n\nexport const isStatusError = (error: unknown): error is StatusErrorLike =>\n\tisNamed(error, 'ApiStatusError') &&\n\ttypeof (error as { status?: unknown }).status === 'number';\n\nexport const isUnavailableError = (\n\terror: unknown,\n): error is UnavailableErrorLike =>\n\tisNamed(error, 'ApiUnavailableError') &&\n\ttypeof (error as { reason?: unknown }).reason === 'string';\n",
6
5
  "import type { ApiMessages } from './messages';\n\n/** The part of a zod issue a code reads, by shape (`@nxgt/material-core`'s `CodeIssue`). */\nexport type CodeIssueLike = {\n\treadonly code: string;\n\t/** A custom issue's params: `.refine(…, { params: { code } })`. */\n\treadonly params?: Record<string, unknown> | undefined;\n\treadonly input?: unknown;\n\treadonly origin?: string | undefined;\n\treadonly minimum?: unknown;\n\treadonly maximum?: unknown;\n\treadonly expected?: unknown;\n\treadonly message?: string | undefined;\n};\n\n/** An API error code (`<module>.errors.<slug>`), as opposed to a GraphQL one (`BAD_USER_INPUT`). */\nexport const API_CODE = /^[a-z-]+\\.errors\\.[a-z0-9-]+$/;\n\nexport interface ApiCodeResolverOptions<L extends string> {\n\t/**\n\t * The app's translator, for every key that is not an API code. Method\n\t * syntax: the app's own `Translate<LocaleKey>` is accepted.\n\t */\n\ttranslate(\n\t\tkey: string,\n\t\tcontext?: Readonly<Record<string, unknown>>,\n\t\tlanguage?: L | (() => L),\n\t): string;\n\t/** The page's language, when a call names none. */\n\tlanguage(): L;\n\t/** Which code an issue carries; the issue's `params.code` by default. */\n\tcodeOf?(issue: CodeIssueLike): string | undefined;\n\t/** Whether a key is an API code; `<module>.errors.<slug>` by default. */\n\tisApiCode?(key: string): boolean;\n}\n\n/** What `@nxgt/material`'s `useCodeResolver(schema, resolver)` takes. */\nexport interface ApiCodeResolver<L extends string> {\n\ttranslate: (\n\t\tkey: string,\n\t\tcontext?: Readonly<Record<string, unknown>>,\n\t\tlanguage?: L | (() => L),\n\t) => string;\n\tcodeOf: (issue: CodeIssueLike) => string | undefined;\n}\n\nfunction paramsCode(issue: CodeIssueLike) {\n\tconst code = (issue.params as { code?: unknown } | undefined)?.code;\n\treturn typeof code === 'string' ? code : undefined;\n}\n\n/**\n * The words of what a form's checks ask for: a refinement carrying an API\n * code in `params.code` reads exactly as the API words it (from the\n * catalogue `messages` holds), any other key takes the app's translator, and\n * a code the catalogue lacks comes back as it is, so the form library words\n * the issue with its own locale instead. Both functions are stable: a\n * resolver is made once per schema and language, so build this once, at\n * module scope.\n */\nexport function apiCodeResolver<L extends string>(\n\tmessages: ApiMessages<L>,\n\toptions: ApiCodeResolverOptions<L>,\n): ApiCodeResolver<L> {\n\tconst isApiCode = (key: string) =>\n\t\toptions.isApiCode ? options.isApiCode(key) : API_CODE.test(key);\n\treturn {\n\t\ttranslate(key, context, provideLanguage) {\n\t\t\tif (!isApiCode(key))\n\t\t\t\treturn options.translate(key, context, provideLanguage);\n\t\t\tconst language =\n\t\t\t\ttypeof provideLanguage === 'function'\n\t\t\t\t\t? provideLanguage()\n\t\t\t\t\t: (provideLanguage ?? options.language());\n\t\t\treturn messages.apiMessage(key, context, language) ?? key;\n\t\t},\n\t\tcodeOf(issue) {\n\t\t\treturn options.codeOf ? options.codeOf(issue) : paramsCode(issue);\n\t\t},\n\t};\n}\n",
7
6
  "import { isApiErrorLike } from './api-error';\nimport type { ApiErrors } from './api-errors';\n\n/** The API's refusal of `error`, or `undefined` when it is not one. */\nexport function refusalOf<L extends string>(\n\terrors: Pick<ApiErrors<L>, 'apiErrorMessage' | 'unavailableMessage'>,\n\terror: unknown,\n\tlanguage: L,\n): ReturnType<ApiErrors<L>['apiRefusal']> {\n\tif (isApiErrorLike(error)) {\n\t\treturn {\n\t\t\tmessage: errors.apiErrorMessage(error, language),\n\t\t\tstatus: error.status,\n\t\t};\n\t}\n\tif (error instanceof Response && error.status === 503) {\n\t\treturn { message: errors.unavailableMessage(language), status: 503 };\n\t}\n\treturn undefined;\n}\n\n/** The worded message of each field an API error names, by field path. */\nexport function fieldErrorsOf<L extends string>(\n\terrors: Pick<ApiErrors<L>, 'apiErrorMessage' | 'translateCode'>,\n\terror: Parameters<ApiErrors<L>['fieldErrors']>[0],\n\tlanguage: L,\n): ReturnType<ApiErrors<L>['fieldErrors']> {\n\tconst extensions = error.errors[0]?.extensions;\n\tconst fields = Array.isArray(extensions?.fields) ? extensions.fields : [];\n\tif (!fields.length && extensions?.field) {\n\t\treturn { [extensions.field]: errors.apiErrorMessage(error, language) };\n\t}\n\treturn Object.fromEntries(\n\t\tfields.map(({ path, code, message, params }) => [\n\t\t\tpath,\n\t\t\terrors.translateCode(code, message, language, params),\n\t\t]),\n\t);\n}\n",
8
7
  "import { data } from 'react-router';\nimport { isApiErrorLike } from './api-error';\nimport type { ApiErrors, ApiRefusal } from './api-errors';\nimport { type RouteErrorOptions, routeError } from './route-error';\n\n/**\n * A fetcher's refusal: the API's (`apiRefusal`), an unreachable API's too,\n * so the page stays where it was. A 401 (the session caller redirects\n * first) or any other failure is thrown, for the error page.\n */\nexport function fetcherRefusal<L extends string>(\n\terrors: Pick<ApiErrors<L>, 'apiRefusal'>,\n\terror: unknown,\n\tlanguage: L,\n\troute?: RouteErrorOptions,\n): ApiRefusal {\n\tconst refusal =\n\t\tisApiErrorLike(error) && error.status === 401\n\t\t\t? undefined\n\t\t\t: errors.apiRefusal(error, language);\n\tif (!refusal) throw routeError(error, route);\n\treturn refusal;\n}\n\n/**\n * Runs the mutation of an action a fetcher posted to: `{ ok: true }` with\n * `about` and the mutation's value, or the refusal (`fetcherRefusal`) as a\n * worded `error`, with its HTTP status, for a toast or a form message.\n */\nexport async function fetcherResult<\n\tL extends string,\n\tAbout extends object,\n\tValue extends object = Record<never, never>,\n>(\n\terrors: Pick<ApiErrors<L>, 'apiRefusal'>,\n\tlanguage: L,\n\tabout: About,\n\trun: () => Promise<Value>,\n\troute?: RouteErrorOptions,\n) {\n\ttry {\n\t\treturn { ok: true as const, ...about, ...(await run()) };\n\t} catch (error) {\n\t\tconst { message, status } = fetcherRefusal(errors, error, language, route);\n\t\treturn data({ ok: false as const, ...about, error: message }, { status });\n\t}\n}\n",
9
- "import { data } from 'react-router';\nimport { isApiErrorLike } from './api-error';\nimport { requestIdOf } from './request-id';\n\n/** The statuses an error page words: unauthenticated, forbidden, missing, unavailable. */\nconst ROUTED: ReadonlySet<number> = new Set([401, 403, 404, 503]);\n\n/**\n * What a route error of the API carries to the error page: the API's code\n * and message when it gave a code, and the `X-Request-Id` of the call as the\n * support reference (`errorRequestId`).\n */\nexport type RouteErrorData = {\n\tcode?: string | undefined;\n\tmessage?: string | undefined;\n\trequestId?: string | undefined;\n};\n\nexport interface RouteErrorOptions {\n\t/** The statuses that become a route error of their own; 401, 403, 404 and 503 by default. */\n\tstatuses?: ReadonlySet<number>;\n}\n\n/**\n * What a loader throws for an error from the API: an `ApiError` whose\n * status is routed (401, 403, 404 or 503) becomes a route error response of\n * that status, which the root `ErrorBoundary` renders as its page, with the\n * call's request id when the API gave one. A thrown routed `Response` that\n * carries a request id becomes one too (a bare `Response` hands the browser\n * its body only). Any other `ApiError` that has a request id becomes a 500\n * with just that id, so the generic error page can show it. Anything else\n * is returned as it is.\n */\nexport function routeError(\n\terror: unknown,\n\t{ statuses = ROUTED }: RouteErrorOptions = {},\n): unknown {\n\tif (isApiErrorLike(error)) {\n\t\tconst { requestId } = error;\n\t\tif (statuses.has(error.status)) {\n\t\t\treturn data<RouteErrorData>(\n\t\t\t\t{ code: error.code, message: error.message, requestId },\n\t\t\t\t{ status: error.status },\n\t\t\t);\n\t\t}\n\t\treturn requestId\n\t\t\t? data<RouteErrorData>({ requestId }, { status: 500 })\n\t\t\t: error;\n\t}\n\tif (error instanceof Response && statuses.has(error.status)) {\n\t\tconst requestId = requestIdOf(error);\n\t\tif (requestId) {\n\t\t\treturn data<RouteErrorData>({ requestId }, { status: error.status });\n\t\t}\n\t}\n\treturn error;\n}\n\n/**\n * The support reference an error page shows: the API's `X-Request-Id` a\n * route error carries (`routeError`), if it carries one.\n */\nexport function errorRequestId(error: unknown): string | undefined {\n\tif (typeof error !== 'object' || error === null) return undefined;\n\tconst { data: body } = error as { data?: unknown };\n\tif (typeof body !== 'object' || body === null) return undefined;\n\tconst { requestId } = body as { requestId?: unknown };\n\treturn typeof requestId === 'string' && requestId ? requestId : undefined;\n}\n",
10
- "/** The header an API echoes on every response: the id its logs carry. */\nexport const REQUEST_ID_HEADER = 'x-request-id';\n\n/** The request id a response carries, if the API sent one. */\nexport function requestIdOf(response: Response): string | undefined {\n\treturn response.headers.get(REQUEST_ID_HEADER) || undefined;\n}\n",
11
8
  "import { data } from 'react-router';\nimport { isApiErrorLike } from './api-error';\nimport type { ApiErrors } from './api-errors';\nimport type { FormErrors } from './form-errors';\nimport { type RouteErrorOptions, routeError } from './route-error';\n\n/**\n * Runs a form's mutation. An `ApiError` becomes the form's errors: each\n * refused field (`extensions.fields`, or the one `extensions.field` names)\n * under the form field `fieldOf` names (else on the form), and any other\n * code as the form's message. A 404 about none of the form's fields (the\n * record itself is gone), a 401 and other failures go to the error page.\n */\nexport async function submitForm<L extends string, T>(\n\terrors: Pick<ApiErrors<L>, 'apiErrorMessage' | 'fieldErrors'>,\n\tlanguage: L,\n\trun: () => Promise<T>,\n\tfieldOf: (path: string) => string | undefined,\n\troute?: RouteErrorOptions,\n): Promise<{ ok: true; value: T } | ReturnType<typeof data<FormErrors>>> {\n\ttry {\n\t\treturn { ok: true, value: await run() };\n\t} catch (error) {\n\t\tif (!isApiErrorLike(error) || error.status === 401) {\n\t\t\tthrow routeError(error, route);\n\t\t}\n\t\tconst field = error.errors[0]?.extensions?.field;\n\t\tif (error.status === 404 && !(field && fieldOf(field))) {\n\t\t\tthrow routeError(error, route);\n\t\t}\n\t\tconst byField: Record<string, string> = {};\n\t\tconst unplaced: string[] = [];\n\t\tfor (const [path, message] of Object.entries(\n\t\t\terrors.fieldErrors(error, language),\n\t\t)) {\n\t\t\tconst field = fieldOf(path);\n\t\t\tif (field) byField[field] = message;\n\t\t\telse unplaced.push(message);\n\t\t}\n\t\tconst formError =\n\t\t\tObject.keys(byField).length && !unplaced.length\n\t\t\t\t? undefined\n\t\t\t\t: [errors.apiErrorMessage(error, language), ...unplaced].join(' ');\n\t\treturn data({ fieldErrors: byField, formError }, { status: error.status });\n\t}\n}\n",
12
9
  "import { valuesOf } from './api-error';\nimport type { ApiErrors, ApiErrorsOptions } from './api-errors';\nimport { API_CODE } from './code-resolver';\nimport { fieldErrorsOf, refusalOf } from './describe-refusal';\nimport { fetcherRefusal, fetcherResult } from './fetcher-result';\nimport { submitForm } from './submit-form';\n\nexport function describeApiErrors<L extends string>({\n\tmessages,\n\tunavailable,\n\trefused,\n\treword,\n\tbyCode = {},\n\tisApiCode = (code) => API_CODE.test(code),\n}: ApiErrorsOptions<L>): ApiErrors<L> {\n\tconst translateCode: ApiErrors<L>['translateCode'] = (\n\t\tcode,\n\t\tfallback,\n\t\tlanguage,\n\t\tvalues,\n\t) => {\n\t\tif (!code) return fallback;\n\t\treturn messages.apiMessage(code, values, language) ?? fallback;\n\t};\n\n\tconst apiErrorMessage: ApiErrors<L>['apiErrorMessage'] = (\n\t\terror,\n\t\tlanguage,\n\t) => {\n\t\tconst code = error.code;\n\t\tif (refused && (!code || !isApiCode(code))) return refused(language);\n\t\tconst own = code && Object.hasOwn(byCode, code) ? byCode[code] : undefined;\n\t\tconst values = valuesOf(error.errors[0]?.extensions);\n\t\tconst text = own\n\t\t\t? own(error, language)\n\t\t\t: translateCode(code, error.message, language, values);\n\t\tif (!reword || !code) return text;\n\t\treturn (\n\t\t\treword(text, error, { code, values: values ?? {}, language }) ?? text\n\t\t);\n\t};\n\n\tconst unavailableMessage = (language: L) => unavailable(language);\n\n\tconst apiRefusal: ApiErrors<L>['apiRefusal'] = (error, language) =>\n\t\trefusalOf({ apiErrorMessage, unavailableMessage }, error, language);\n\n\tconst fieldErrors: ApiErrors<L>['fieldErrors'] = (error, language) =>\n\t\tfieldErrorsOf({ apiErrorMessage, translateCode }, error, language);\n\n\tconst parts = { apiRefusal, apiErrorMessage, fieldErrors };\n\n\treturn {\n\t\ttranslateCode,\n\t\tapiErrorMessage,\n\t\tunavailableMessage,\n\t\tfieldErrors,\n\t\tapiRefusal,\n\t\tfetcherRefusal: (error, language, route) =>\n\t\t\tfetcherRefusal(parts, error, language, route),\n\t\tfetcherResult: (language, about, run, route) =>\n\t\t\tfetcherResult(parts, language, about, run, route),\n\t\tsubmitForm: (language, run, fieldOf, route) =>\n\t\t\tsubmitForm(parts, language, run, fieldOf, route),\n\t};\n}\n",
13
10
  "import type { data } from 'react-router';\nimport type { ApiErrorLike } from './api-error';\nimport { describeApiErrors } from './describe';\nimport type { FormErrors } from './form-errors';\nimport type { ApiMessages } from './messages';\nimport type { RouteErrorOptions } from './route-error';\n\n/** A refused call, as a page says it: the message, and the HTTP status to answer. */\nexport type ApiRefusal = { message: string; status: number };\n\nexport interface ApiErrorsOptions<L extends string> {\n\t/** The catalogue the API's codes are worded from. */\n\tmessages: ApiMessages<L>;\n\t/**\n\t * The app's own word for an API it cannot reach (a 503 `Response`): not\n\t * an API error, so never one of the catalogue's codes.\n\t */\n\tunavailable(language: L): string;\n\t/**\n\t * The app's generic refusal, said for an error with no API code (a raw\n\t * `BAD_USER_INPUT` before the API's validation layer), never the raw\n\t * message. Without it, such an error says the message the API sent.\n\t */\n\trefused?(language: L): string;\n\t/**\n\t * An app's own wording for given codes, such as the API's request limits\n\t * (depth, cost, introspection), whose params differ and name no field.\n\t * Checked after `refused`, before the catalogue.\n\t */\n\tbyCode?: Readonly<\n\t\tRecord<string, (error: ApiErrorLike, language: L) => string>\n\t>;\n\t/**\n\t * Words a whole family of codes once, after the text is worded. It runs\n\t * on the final text `apiErrorMessage` (so `apiRefusal`, `fetcherResult`,\n\t * `fetcherRefusal`, `submitForm` and a single `extensions.field`) says\n\t * for an error with a code, whichever produced it: the catalogue, the\n\t * API's own message, or `byCode`. It does not run on `refused`'s text, on\n\t * `unavailable`'s (a network failure), on `translateCode` nor on the\n\t * entries of `extensions.fields`. `values` are the merged values the\n\t * catalogue formats with (`extensions` and `extensions.params`, params\n\t * winning). Return the text to show, or `undefined` to keep `text`.\n\t */\n\treword?(\n\t\ttext: string,\n\t\terror: ApiErrorLike,\n\t\tcontext: {\n\t\t\tcode: string;\n\t\t\tvalues: Readonly<Record<string, unknown>>;\n\t\t\tlanguage: L;\n\t\t},\n\t): string | undefined;\n\t/** Whether a code is an API code; `<module>.errors.<slug>` by default. */\n\tisApiCode?(code: string): boolean;\n}\n\n/** What a page says of an API's refusals, in a language. */\nexport interface ApiErrors<L extends string> {\n\t/**\n\t * The catalogue's text of an API code in `language`, else `fallback` (the\n\t * message the API already worded). `values` are the message's arguments\n\t * (`extensions.params`).\n\t */\n\ttranslateCode(\n\t\tcode: string | undefined,\n\t\tfallback: string,\n\t\tlanguage: L,\n\t\tvalues?: Readonly<Record<string, unknown>>,\n\t): string;\n\t/**\n\t * What to show for an API error: `refused` for an error with no API code,\n\t * when given; else `byCode`'s wording of its code; else the catalogue's\n\t * text; else the message the API already worded.\n\t */\n\tapiErrorMessage(error: ApiErrorLike, language: L): string;\n\t/**\n\t * The message of each refused field, by input path, ready for a form: the\n\t * entries of `extensions.fields`, else the one field `extensions.field`\n\t * names, with the error's own message. Empty for neither.\n\t */\n\tfieldErrors(error: ApiErrorLike, language: L): Record<string, string>;\n\t/** `unavailable`, in `language`. */\n\tunavailableMessage(language: L): string;\n\t/**\n\t * What a failed call says to the user: an API refusal's message and its\n\t * status, or an API it cannot reach (a 503 `Response`: the unavailable\n\t * word). Undefined for anything else, which the caller rethrows.\n\t */\n\tapiRefusal(error: unknown, language: L): ApiRefusal | undefined;\n\t/**\n\t * A fetcher's refusal: `apiRefusal`'s, so the page stays where it was. A\n\t * 401 (the session caller redirects first) or any other failure is\n\t * thrown, through `routeError`, for the error page.\n\t */\n\tfetcherRefusal(\n\t\terror: unknown,\n\t\tlanguage: L,\n\t\troute?: RouteErrorOptions,\n\t): ApiRefusal;\n\t/**\n\t * Runs the mutation of an action a fetcher posted to: `{ ok: true }` with\n\t * `about` and the mutation's value, or `{ ok: false, error }` with `about`\n\t * and the refusal's message, answered with its HTTP status.\n\t */\n\tfetcherResult<\n\t\tAbout extends object,\n\t\tValue extends object = Record<never, never>,\n\t>(\n\t\tlanguage: L,\n\t\tabout: About,\n\t\trun: () => Promise<Value>,\n\t\troute?: RouteErrorOptions,\n\t): Promise<\n\t\t| ({ ok: true } & About & Value)\n\t\t| ReturnType<typeof data<{ ok: false; error: string } & About>>\n\t>;\n\t/**\n\t * Runs a form's mutation: `{ ok: true, value }`, or the form's errors\n\t * (`fieldErrors` under the form field `fieldOf` names an input path by,\n\t * and a `formError` for the rest) with the refusal's status. A 404 about\n\t * none of the form's fields, a 401 and other failures are thrown for the\n\t * error page, through `routeError` (with `route`).\n\t */\n\tsubmitForm<T>(\n\t\tlanguage: L,\n\t\trun: () => Promise<T>,\n\t\tfieldOf: (path: string) => string | undefined,\n\t\troute?: RouteErrorOptions,\n\t): Promise<{ ok: true; value: T } | ReturnType<typeof data<FormErrors>>>;\n}\n\n/**\n * The wording of an API's refusals for the languages `L`, from the\n * catalogue `messages` holds. Make one per app, beside its `createApiMessages`.\n */\nexport function createApiErrors<L extends string>(\n\toptions: ApiErrorsOptions<L>,\n): ApiErrors<L> {\n\treturn describeApiErrors(options);\n}\n",
@@ -16,14 +13,13 @@
16
13
  "import type { Held } from './catalogue-read';\n\n/** What the TTL check needs: the reader's state and the app's own calls. */\nexport interface CheckContext<L extends string> {\n\treader: {\n\t\theld: Map<L, Held>;\n\t\tload(language: L, now: number): Promise<void>;\n\t};\n\tversions(): Promise<Partial<Record<L, string>>>;\n\tttl(): number;\n\tretryMs: number;\n\tlog: Pick<Console, 'error'>;\n}\n\n/**\n * Asks the versions in one call and reads again the messages of each\n * language that moved. An API that cannot be reached keeps the messages\n * held (stale, still worded) and is asked again after `retryMs`.\n */\nexport async function checkVersions<L extends string>(\n\t{ reader, versions, ttl, retryMs, log }: CheckContext<L>,\n\tnow: number,\n) {\n\ttry {\n\t\tconst latest = await versions();\n\t\tfor (const [language, entry] of [...reader.held]) {\n\t\t\tif (latest[language] !== entry.version) {\n\t\t\t\tawait reader.load(language, now);\n\t\t\t} else {\n\t\t\t\tentry.checkedAt = now;\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tlog.error(\n\t\t\t'alxia-react-router: the error catalogue was not checked, keeping what is held',\n\t\t\terror,\n\t\t);\n\t\tfor (const entry of reader.held.values()) {\n\t\t\tentry.checkedAt = now - ttl() + retryMs;\n\t\t}\n\t}\n}\n\n/**\n * The TTL, whose getter is the app's: one that throws, or that is not a\n * finite number of at least 0, is logged and `fallback` is used.\n */\nexport function safeTtl(\n\tttlMs: number | (() => number),\n\tfallback: number,\n\tlog: Pick<Console, 'error'>,\n) {\n\treturn () => {\n\t\ttry {\n\t\t\tconst ttl = typeof ttlMs === 'function' ? ttlMs() : ttlMs;\n\t\t\tif (typeof ttl === 'number' && Number.isFinite(ttl) && ttl >= 0) {\n\t\t\t\treturn ttl;\n\t\t\t}\n\t\t\tlog.error('alxia-react-router: ttlMs is not a duration, using retryMs');\n\t\t} catch (error) {\n\t\t\tlog.error('alxia-react-router: ttlMs threw, using retryMs', error);\n\t\t}\n\t\treturn fallback;\n\t};\n}\n",
17
14
  "import type { ApiMessages, CatalogueMessage } from './messages';\n\n/** What the API answers for one language: its version and every message. */\nexport type CatalogueReply = {\n\tversion: string;\n\tmessages: ReadonlyArray<CatalogueMessage & { readonly code: string }>;\n};\n\n/** A language's catalogue as held, and when its version was last confirmed. */\nexport type Held = { version: string; checkedAt: number };\n\nexport interface CatalogueReaderOptions<L extends string> {\n\tmessages: ApiMessages<L>;\n\tread(language: L): Promise<CatalogueReply>;\n\tretryMs: number;\n\tfirstReadWaitMs: number;\n\tlog: Pick<Console, 'error'>;\n}\n\n/**\n * Waits for the read, until `firstReadWaitMs` after it started (not after\n * this request came: a hung API holds a request at most that long in\n * all); the read goes on either way.\n */\nasync function boundedWait(\n\tpending: { read: Promise<void>; started: number },\n\tfirstReadWaitMs: number,\n) {\n\tconst left = firstReadWaitMs - (performance.now() - pending.started);\n\tif (left <= 0) return;\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\tconst limit = new Promise<void>((resolve) => {\n\t\ttimer = setTimeout(resolve, left);\n\t});\n\tawait Promise.race([pending.read, limit]);\n\tclearTimeout(timer);\n}\n\n/**\n * The reading half of the catalogue: the first read of each language (one in\n * flight, a bounded wait, a retry delay after a failure) and the version\n * each one holds. `createErrorCatalogue` adds the TTL check on top.\n */\nexport function createCatalogueReader<L extends string>({\n\tmessages,\n\tread,\n\tretryMs,\n\tfirstReadWaitMs,\n\tlog,\n}: CatalogueReaderOptions<L>) {\n\tconst held = new Map<L, Held>();\n\tconst loading = new Map<L, { read: Promise<void>; started: number }>();\n\tconst failedAt = new Map<L, number>();\n\n\t/** Reads one language's messages and holds them. */\n\tasync function load(language: L, now: number) {\n\t\tconst reply = await read(language);\n\t\tconst entries: Record<string, CatalogueMessage> = Object.create(null);\n\t\tfor (const { code, message, params } of reply.messages) {\n\t\t\tentries[code] = { message, params };\n\t\t}\n\t\tmessages.set(language, entries);\n\t\theld.set(language, { version: reply.version, checkedAt: now });\n\t}\n\n\t/** The first read of a language, once however many pages ask at the same time. */\n\tfunction loadOnce(language: L, now: number) {\n\t\tlet pending = loading.get(language);\n\t\tif (!pending) {\n\t\t\tconst started = performance.now();\n\t\t\tconst reading = load(language, now)\n\t\t\t\t.then(() => {\n\t\t\t\t\tfailedAt.delete(language);\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\t// When it failed, not when it started: a read that hung for\n\t\t\t\t\t// the wait is not retried at once by the next request.\n\t\t\t\t\tfailedAt.set(language, now + (performance.now() - started));\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\t`alxia-react-router: the error catalogue (${language}) was not read`,\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tloading.delete(language);\n\t\t\t\t});\n\t\t\tpending = { read: reading, started };\n\t\t\tloading.set(language, pending);\n\t\t}\n\t\treturn pending;\n\t}\n\n\treturn {\n\t\theld,\n\t\tload,\n\t\t/** Reads a language that is not held yet, unless a failure is still fresh. */\n\t\tasync first(language: L, now: number) {\n\t\t\tconst failed = failedAt.get(language);\n\t\t\tif (failed === undefined || now - failed >= retryMs) {\n\t\t\t\tawait boundedWait(loadOnce(language, now), firstReadWaitMs);\n\t\t\t}\n\t\t},\n\t\treset() {\n\t\t\theld.clear();\n\t\t\tloading.clear();\n\t\t\tfailedAt.clear();\n\t\t},\n\t};\n}\n",
18
15
  "import { checkVersions, safeTtl } from './catalogue-check';\nimport { type CatalogueReply, createCatalogueReader } from './catalogue-read';\nimport { quietLog } from './log';\nimport type { ApiMessages, CatalogueMessages } from './messages';\n\nexport type { CatalogueReply } from './catalogue-read';\n\nexport interface ErrorCatalogueOptions<L extends string> {\n\t/** The store the page words refusals from (`createApiMessages`). */\n\tmessages: ApiMessages<L>;\n\t/** The languages to hold, each read once and kept fresh. */\n\tlanguages: readonly L[];\n\t/** Reads one language's catalogue from the API. */\n\tread(language: L): Promise<CatalogueReply>;\n\t/** Asks the API for the version of every language, in one call. */\n\tversions(): Promise<Partial<Record<L, string>>>;\n\t/** How long a held catalogue is served before its version is checked. */\n\tttlMs: number | (() => number);\n\t/** How soon a check or a first read that failed is tried again. Default 5000. */\n\tretryMs?: number;\n\t/**\n\t * How long a request waits for a language's first read; past it the\n\t * request goes on and the read carries on in the background. Default 1500.\n\t */\n\tfirstReadWaitMs?: number;\n\t/** The codes the browser words itself (`clientMessages`). */\n\tclientCodes: readonly string[];\n\t/** Where failures are reported. Default `console`. */\n\tlog?: Pick<Console, 'error'>;\n}\n\n/** The API's error catalogue, kept fresh for the server. */\nexport interface ErrorCatalogue<L extends string> {\n\t/**\n\t * The catalogue of `language`, ready to word a refusal. Only a language\n\t * with no catalogue yet is awaited, for at most `firstReadWaitMs`. A held\n\t * one is served as it is, and once older than the TTL its version is\n\t * checked in the background, one check at a time.\n\t */\n\tfresh(language: L, now?: number): Promise<void>;\n\t/** Every language, fresh: what the root middleware awaits. */\n\tfreshAll(now?: number): Promise<void>;\n\t/** At startup: reads every language without holding the boot back. */\n\twarm(): void;\n\t/** The messages the browser words itself, by language, for the root's loader. */\n\tclientMessages(): Record<L, CatalogueMessages>;\n\t/**\n\t * Forgets everything held and in flight. For use between tests, with\n\t * nothing in flight: a read or check still running when it is called\n\t * finishes and holds its result again.\n\t */\n\treset(): void;\n\t/** The version held for a language, if any. */\n\theldVersion(language: L): string | undefined;\n\t/** Waits for the check in flight, if any (tests). */\n\tsettled(): Promise<void>;\n}\n\n/** The messages the browser words itself, by language. */\nfunction clientMessages<L extends string>(\n\tmessages: ApiMessages<L>,\n\tlanguages: readonly L[],\n\tclientCodes: readonly string[],\n) {\n\tconst byLanguage = {} as Record<L, CatalogueMessages>;\n\tfor (const language of languages) {\n\t\tconst entries: Record<string, CatalogueMessages[string]> =\n\t\t\tObject.create(null);\n\t\tfor (const code of clientCodes) {\n\t\t\tconst entry = messages.messageOf(language, code);\n\t\t\tif (entry) entries[code] = entry;\n\t\t}\n\t\tbyLanguage[language] = entries;\n\t}\n\treturn byLanguage;\n}\n\n/**\n * Keeps the API's error catalogue in `messages`: read on first use, checked\n * against the API's versions once per TTL, and re-read only for the\n * languages whose version moved. It is an instance, not module state.\n */\nexport function createErrorCatalogue<L extends string>({\n\tmessages,\n\tlanguages,\n\tread,\n\tversions,\n\tttlMs,\n\tretryMs = 5_000,\n\tfirstReadWaitMs = 1_500,\n\tclientCodes,\n\tlog: appLog = console,\n}: ErrorCatalogueOptions<L>): ErrorCatalogue<L> {\n\tif (languages.length === 0) {\n\t\tthrow new TypeError('createErrorCatalogue(): needs at least one language.');\n\t}\n\tconst log = quietLog(appLog, ['error']);\n\tconst ttl = safeTtl(ttlMs, retryMs, log);\n\tconst reader = createCatalogueReader({\n\t\tmessages,\n\t\tread,\n\t\tretryMs,\n\t\tfirstReadWaitMs,\n\t\tlog,\n\t});\n\tconst context = { reader, versions, ttl, retryMs, log };\n\tlet checking: Promise<void> | undefined;\n\n\tasync function fresh(language: L, now: number = Date.now()) {\n\t\tconst entry = reader.held.get(language);\n\t\tif (!entry) return reader.first(language, now);\n\t\tif (now - entry.checkedAt >= ttl() && !checking) {\n\t\t\tchecking = checkVersions(context, now)\n\t\t\t\t.finally(() => {\n\t\t\t\t\tchecking = undefined;\n\t\t\t\t})\n\t\t\t\t.catch(() => {});\n\t\t}\n\t}\n\n\tconst freshAll = async (now: number = Date.now()) => {\n\t\tawait Promise.all(languages.map((language) => fresh(language, now)));\n\t};\n\n\treturn {\n\t\tfresh,\n\t\tfreshAll,\n\t\twarm() {\n\t\t\tfreshAll().catch((error) => {\n\t\t\t\tlog.error(\n\t\t\t\t\t'alxia-react-router: the error catalogue was not warmed',\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t});\n\t\t},\n\t\tclientMessages: () => clientMessages(messages, languages, clientCodes),\n\t\treset() {\n\t\t\treader.reset();\n\t\t\tchecking = undefined;\n\t\t\tmessages.clear();\n\t\t},\n\t\theldVersion: (language) => reader.held.get(language)?.version,\n\t\tsettled: () => checking ?? Promise.resolve(),\n\t};\n}\n",
19
- "import { data, redirect } from 'react-router';\nimport { nextOf } from './page-path';\nimport type { InferOutput, StandardSchemaV1 } from './standard-schema';\n\nexport interface JsonActionsOptions {\n\t/**\n\t * The origin a request must come from, such as `https://app.example.com`:\n\t * required behind a TLS-terminating proxy, where the request's own URL\n\t * says `http:`. A getter is read at each request. Else the request's own\n\t * origin.\n\t */\n\torigin?: string | (() => string | undefined);\n}\n\n/** The actions' JSON helpers, bound to one app's origin. */\nexport interface JsonActions {\n\t/**\n\t * The JSON body an action was posted, refused unless it comes from this\n\t * site: 403 for another origin or a cross-site fetch, 415 for a body that\n\t * is not `application/json`, 400 for malformed JSON.\n\t */\n\treadJson(request: Request): Promise<unknown>;\n\t/**\n\t * For the actions a form posts to: a native post (before hydration) goes\n\t * back to its page, which then posts JSON. A JSON post goes on.\n\t */\n\trequireJsonPost(request: Request): void;\n\t/**\n\t * The `input` of the JSON body `{ input }`, checked against a Standard\n\t * Schema (Zod 4, Valibot, ArkType), whose validation may be async. A\n\t * refused input is a 400.\n\t */\n\treadInput<S extends StandardSchemaV1>(\n\t\trequest: Request,\n\t\tschema: S,\n\t): Promise<InferOutput<S>>;\n}\n\n/**\n * Every action takes JSON: a cross-site page can only post a form or\n * `text/plain` without a preflight, so requiring `application/json` and a\n * same-origin `Origin` (or `Sec-Fetch-Site`) stops CSRF before the session\n * cookie's `SameSite` is even consulted.\n */\nexport function jsonActions(options: JsonActionsOptions = {}): JsonActions {\n\tconst ownOrigin = (request: Request) => {\n\t\tconst { origin } = options;\n\t\tconst set = typeof origin === 'function' ? origin() : origin;\n\t\treturn set ?? new URL(request.url).origin;\n\t};\n\tconst isJson = (request: Request) =>\n\t\trequest.headers.get('content-type')?.startsWith('application/json');\n\n\tasync function readJson(request: Request): Promise<unknown> {\n\t\tconst origin = request.headers.get('origin');\n\t\tconst site = request.headers.get('sec-fetch-site');\n\t\tif (\n\t\t\t(origin && origin !== ownOrigin(request)) ||\n\t\t\t(site && site !== 'same-origin' && site !== 'none')\n\t\t) {\n\t\t\tthrow data('Cross-site request refused', { status: 403 });\n\t\t}\n\t\tif (!isJson(request)) {\n\t\t\tthrow data('Expected a JSON body', { status: 415 });\n\t\t}\n\t\treturn request.json().catch(() => {\n\t\t\tthrow data('Malformed JSON body', { status: 400 });\n\t\t});\n\t}\n\n\treturn {\n\t\treadJson,\n\t\trequireJsonPost(request) {\n\t\t\tif (!isJson(request)) throw redirect(nextOf(request.url));\n\t\t},\n\t\tasync readInput(request, schema) {\n\t\t\tconst body = (await readJson(request)) as { input?: unknown } | null;\n\t\t\tconst result = await schema['~standard'].validate(body?.input);\n\t\t\tif (result.issues) {\n\t\t\t\tthrow data('The form sent an input the API would refuse', {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn result.value as InferOutput<typeof schema>;\n\t\t},\n\t};\n}\n",
20
- "/**\n * The page a request is for, as `next` carries it back after sign-in: its\n * path and search, without React Router's single-fetch details. A client\n * navigation's `request.url` is `/todos/demo/list.data?q=a&_routes=…`\n * (`/_.data` for `/`, `?index` for an index action), as the server\n * runtime's own `normalizeUrl` strips them.\n */\nexport function nextOf(url: string): string {\n\tconst { pathname, searchParams } = new URL(url);\n\tconst trimmed = pathname.endsWith('/_.data')\n\t\t? pathname.slice(0, -'_.data'.length)\n\t\t: pathname.replace(/\\.data$/, '');\n\t// `new URL('http://h/\\\\evil.com')` has the path `//evil.com`: never let a\n\t// `next` start with two slashes, which a redirect reads as another site.\n\tconst path = trimmed.replace(/^\\/{2,}/, '/');\n\tconst params = new URLSearchParams(searchParams);\n\tparams.delete('_routes');\n\t// An empty `index` names the index route; a valued one is the page's own.\n\tfor (const value of params.getAll('index')) {\n\t\tif (!value) params.delete('index', value);\n\t}\n\tconst search = params.toString();\n\treturn search ? `${path}?${search}` : path;\n}\n",
16
+ "import { data, redirect } from 'react-router';\nimport { nextOf } from './page-path';\nimport { rememberSiteCheck, siteCheck } from './same-site';\nimport type { InferOutput, StandardSchemaV1 } from './standard-schema';\n\nexport interface JsonActionsOptions {\n\t/**\n\t * The origin a request must come from, such as `https://app.example.com`:\n\t * required behind a TLS-terminating proxy, where the request's own URL\n\t * says `http:`. A getter is read at each request. Else the request's own\n\t * origin.\n\t */\n\torigin?: string | (() => string | undefined);\n}\n\n/** The actions' JSON helpers, bound to one app's origin. */\nexport interface JsonActions {\n\t/**\n\t * The JSON body an action was posted, refused unless it comes from this\n\t * site: 403 for another origin or a cross-site fetch, 415 for a body that\n\t * is not `application/json`, 400 for malformed JSON.\n\t */\n\treadJson(request: Request): Promise<unknown>;\n\t/**\n\t * For the actions a form posts to: a native post (before hydration) goes\n\t * back to its page, which then posts JSON. A JSON post goes on.\n\t */\n\trequireJsonPost(request: Request): void;\n\t/**\n\t * The `input` of the JSON body `{ input }`, checked against a Standard\n\t * Schema (Zod 4, Valibot, ArkType), whose validation may be async. A\n\t * refused input is a 400.\n\t */\n\treadInput<S extends StandardSchemaV1>(\n\t\trequest: Request,\n\t\tschema: S,\n\t): Promise<InferOutput<S>>;\n}\n\n/**\n * Every action takes JSON: a cross-site page can only post a form or\n * `text/plain` without a preflight, so requiring `application/json` and a\n * same-origin `Origin` (or `Sec-Fetch-Site`) stops CSRF before the session\n * cookie's `SameSite` is even consulted.\n */\nexport function jsonActions(options: JsonActionsOptions = {}): JsonActions {\n\tconst crossSite = siteCheck(options.origin);\n\tconst isJson = (request: Request) =>\n\t\trequest.headers.get('content-type')?.startsWith('application/json');\n\n\tasync function readJson(request: Request): Promise<unknown> {\n\t\tcrossSite(request);\n\t\tif (!isJson(request)) {\n\t\t\tthrow data('Expected a JSON body', { status: 415 });\n\t\t}\n\t\treturn request.json().catch(() => {\n\t\t\tthrow data('Malformed JSON body', { status: 400 });\n\t\t});\n\t}\n\n\tconst actions: JsonActions = {\n\t\treadJson,\n\t\trequireJsonPost(request) {\n\t\t\tif (!isJson(request)) throw redirect(nextOf(request.url));\n\t\t},\n\t\tasync readInput(request, schema) {\n\t\t\tconst body = (await readJson(request)) as { input?: unknown } | null;\n\t\t\tconst result = await schema['~standard'].validate(body?.input);\n\t\t\tif (result.issues) {\n\t\t\t\tthrow data('The form sent an input the API would refuse', {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn result.value as InferOutput<typeof schema>;\n\t\t},\n\t};\n\trememberSiteCheck(actions, crossSite);\n\treturn actions;\n}\n",
21
17
  "import type { CatalogueMessage } from './messages';\n\n/** The values a formatter takes: what ICU arguments can be. */\nexport type MessageValues = Readonly<\n\tRecord<string, string | number | boolean | object>\n>;\n\nconst DAY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\n/** A local `Date` built from the calendar parts of a `YYYY-MM-DD`: no time-zone shift. */\nfunction dayOf(value: string): Date | undefined {\n\tconst parts = DAY.exec(value);\n\tif (!parts) return undefined;\n\treturn new Date(Number(parts[1]), Number(parts[2]) - 1, Number(parts[3]));\n}\n\n/**\n * The values as the message formats them: a `YYYY-MM-DD` the message names\n * as a date becomes a local `Date` (by calendar parts, so the day is the\n * same in every time zone), a count or number given as a numeric string a\n * number. Everything else passes as it is.\n */\nexport function valuesFor(\n\tparams: CatalogueMessage['params'],\n\tvalues: Readonly<Record<string, unknown>>,\n): MessageValues {\n\tconst worded: Record<string, unknown> = { ...values };\n\tfor (const { name, kind } of params) {\n\t\tconst value = values[name];\n\t\tif (typeof value !== 'string') continue;\n\t\tif (kind === 'DATE') {\n\t\t\tconst day = dayOf(value);\n\t\t\tif (day) worded[name] = day;\n\t\t} else if (\n\t\t\t(kind === 'NUMBER' || kind === 'PLURAL') &&\n\t\t\tvalue.trim() !== '' &&\n\t\t\t!Number.isNaN(Number(value))\n\t\t) {\n\t\t\tworded[name] = Number(value);\n\t\t}\n\t}\n\treturn worded as MessageValues;\n}\n",
22
18
  "import { type MessageValues, valuesFor } from './message-values';\n\nexport type { MessageValues } from './message-values';\n\n/** How a message uses an argument (the API's `ErrorParamKind`). */\nexport type ParamKind = 'TEXT' | 'NUMBER' | 'DATE' | 'PLURAL' | 'SELECT';\n\n/**\n * One text of the API's error catalogue: the uninterpolated ICU message and\n * the arguments it names, which say what to supply as a date or a number\n * without parsing the message.\n */\nexport type CatalogueMessage = {\n\tmessage: string;\n\tparams: ReadonlyArray<{ name: string; kind: ParamKind }>;\n};\n\n/** A language's messages by API code (`<module>.errors.<slug>`). */\nexport type CatalogueMessages = Readonly<Record<string, CatalogueMessage>>;\n\n/**\n * Formats an ICU message for a language: plurals, numbers and dates of that\n * language. `@nxgt/material`'s `formatMessage` is one, as it is. It reports\n * a message it could not format (a missing value, a stray brace) to\n * `onError` instead of throwing.\n */\nexport type MessageFormat<L extends string> = (\n\tmessage: string,\n\tlanguage: L,\n\tvalues: MessageValues,\n\toptions: { onError(error: unknown): void },\n) => string;\n\nexport interface ApiMessagesOptions<L extends string> {\n\t/** The app's ICU formatter: the same engine as its translator, so both word alike. */\n\tformat: MessageFormat<L>;\n}\n\n/** The catalogue the page words refusals with, by language. */\nexport interface ApiMessages<L extends string> {\n\t/** Replaces a language's messages (a server's whole catalogue). */\n\tset(language: L, messages: CatalogueMessages): void;\n\t/** Adds messages to a language's (a browser's, from the root's data). */\n\tadd(language: L, messages: CatalogueMessages): void;\n\t/** Forgets every message (tests). */\n\tclear(): void;\n\t/** The message the catalogue holds for a code in a language, if any. */\n\tmessageOf(language: L, code: string): CatalogueMessage | undefined;\n\t/**\n\t * A message formatted for `language` with `values`. Undefined when it\n\t * cannot be formatted with those values (a missing argument, a day it\n\t * cannot read) or does not parse.\n\t */\n\tformat(\n\t\tentry: CatalogueMessage,\n\t\tvalues: Readonly<Record<string, unknown>> | undefined,\n\t\tlanguage: L,\n\t): string | undefined;\n\t/**\n\t * The catalogue's text of an API code in `language`, with `values`\n\t * (`extensions.params`) filled in. Undefined when the catalogue has no\n\t * such code or the message cannot be formatted, so the caller falls back\n\t * to the message the API already worded.\n\t */\n\tapiMessage(\n\t\tcode: string,\n\t\tvalues: Readonly<Record<string, unknown>> | undefined,\n\t\tlanguage: L,\n\t): string | undefined;\n}\n\n/**\n * A catalogue store for the languages `L`. It is an instance, not module\n * state: two copies of the package never split it, and a spec makes its own.\n * Make one per app, in a module of its own, and share it with\n * `apiCodeResolver` and `ApiMessagesProvider`.\n */\nexport function createApiMessages<L extends string>({\n\tformat,\n}: ApiMessagesOptions<L>): ApiMessages<L> {\n\tconst catalogues = new Map<L, Map<string, CatalogueMessage>>();\n\n\tconst messageOf = (language: L, code: string) =>\n\t\tcatalogues.get(language)?.get(code);\n\n\tfunction formatEntry(\n\t\tentry: CatalogueMessage,\n\t\tvalues: Readonly<Record<string, unknown>> | undefined,\n\t\tlanguage: L,\n\t) {\n\t\tconst worded = valuesFor(entry.params, values ?? {});\n\t\t// A message that did not format is reported here, not logged: the\n\t\t// caller falls back.\n\t\tlet failed = false;\n\t\ttry {\n\t\t\tconst text = format(entry.message, language, worded, {\n\t\t\t\tonError: () => {\n\t\t\t\t\tfailed = true;\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn failed ? undefined : text;\n\t\t} catch {\n\t\t\t// An app's formatter that throws is a message that did not format.\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\treturn {\n\t\tset(language, messages) {\n\t\t\tcatalogues.set(language, new Map(Object.entries(messages)));\n\t\t},\n\t\tadd(language, messages) {\n\t\t\tconst held = catalogues.get(language) ?? new Map();\n\t\t\tfor (const [code, message] of Object.entries(messages)) {\n\t\t\t\theld.set(code, message);\n\t\t\t}\n\t\t\tcatalogues.set(language, held);\n\t\t},\n\t\tclear() {\n\t\t\tcatalogues.clear();\n\t\t},\n\t\tmessageOf,\n\t\tformat: formatEntry,\n\t\tapiMessage(code, values, language) {\n\t\t\tconst entry = messageOf(language, code);\n\t\t\treturn entry ? formatEntry(entry, values, language) : undefined;\n\t\t},\n\t};\n}\n",
23
19
  "import type { ReactNode } from 'react';\nimport type { ApiMessages, CatalogueMessages } from './messages';\n\nexport interface ApiMessagesProviderProps<L extends string> {\n\t/** The store `apiCodeResolver` reads. */\n\tmessages: ApiMessages<L>;\n\t/** The messages the root's data carries, by language. */\n\tvalue: Readonly<Record<L, CatalogueMessages>> | undefined;\n\tchildren: ReactNode;\n}\n\n/**\n * Fills the browser's catalogue with the messages the root's data carries\n * (the few its forms word), before the children render: `apiCodeResolver`\n * reads them synchronously. A server render writes nothing: the server's\n * store holds the whole, fresher catalogue, and a render's data may be older\n * than it. It is a plain function (no JSX, no React runtime): use it as\n * `ApiMessagesProvider({ messages, value, children })` from a component, or\n * as an element's type.\n */\nexport function ApiMessagesProvider<L extends string>({\n\tmessages,\n\tvalue,\n\tchildren,\n}: ApiMessagesProviderProps<L>): ReactNode {\n\tconst inBrowser =\n\t\ttypeof (globalThis as { document?: unknown }).document !== 'undefined';\n\tif (value && inBrowser) {\n\t\tfor (const [language, held] of Object.entries<CatalogueMessages>(value)) {\n\t\t\tmessages.add(language as L, held);\n\t\t}\n\t}\n\treturn children;\n}\n",
24
20
  "import { type FetcherWithComponents, useFetcher } from 'react-router';\n\n/** What a fetcher can post as JSON. */\nexport type JsonBody = Parameters<FetcherWithComponents<unknown>['submit']>[0];\n\n/**\n * A fetcher posting JSON to its page's action (which reads it with\n * `readJson`, and answers `fetcherResult` or the like): `post` sends a\n * body, `busy` while it is in flight. `key` shares the fetcher between the\n * form that posts and the component that reads the answer; `action` posts to\n * another route's action instead (a resource route's, such as a\n * `notifications/poll`). `post` takes the target of one call as its second\n * argument (a list's rows each post to their own record's action).\n */\nexport function useJsonFetcher<Action, Body extends JsonBody = JsonBody>(\n\tkey?: string,\n\taction?: string,\n): {\n\tfetcher: ReturnType<typeof useFetcher<Action>>;\n\tpost(body: Body, to?: string): Promise<void>;\n\tbusy: boolean;\n} {\n\tconst fetcher = useFetcher<Action>(key ? { key } : undefined);\n\tconst post = (body: Body, to = action) =>\n\t\tfetcher.submit(body, {\n\t\t\tmethod: 'post',\n\t\t\tencType: 'application/json',\n\t\t\t...(to ? { action: to } : {}),\n\t\t});\n\treturn { fetcher, post, busy: fetcher.state !== 'idle' };\n}\n"
25
21
  ],
26
- "mappings": "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",
27
- "debugId": "10F8AF81866444B364756E2164756E21",
22
+ "mappings": "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",
23
+ "debugId": "0489566B0456068164756E2164756E21",
28
24
  "names": []
29
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"json-actions.d.ts","sourceRoot":"","sources":["../../src/errors/json-actions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEvE,MAAM,WAAW,kBAAkB;IAClC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;CAC7C;AAED,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxC;;;;OAIG;IACH,SAAS,CAAC,CAAC,SAAS,gBAAgB,EACnC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,CAAC,GACP,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CA0CzE"}
1
+ {"version":3,"file":"json-actions.d.ts","sourceRoot":"","sources":["../../src/errors/json-actions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEvE,MAAM,WAAW,kBAAkB;IAClC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;CAC7C;AAED,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxC;;;;OAIG;IACH,SAAS,CAAC,CAAC,SAAS,gBAAgB,EACnC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,CAAC,GACP,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAiCzE"}
@@ -0,0 +1,25 @@
1
+ /** Refuses a request from another site with a 403; reads headers only. */
2
+ export type SiteCheck = (request: Request) => void;
3
+ /**
4
+ * The same-site rule of `readJson`: an `Origin` that is not the app's own, or
5
+ * a `Sec-Fetch-Site` that is neither `same-origin` nor `none`, is a 403.
6
+ * `origin` is the app's configured origin (or a getter), else the request's.
7
+ */
8
+ export declare function siteCheck(origin?: string | (() => string | undefined) | undefined): SiteCheck;
9
+ /**
10
+ * Where a `jsonActions` instance keeps its site check: an enumerable property
11
+ * under a registered symbol, so it survives `{ ...json }` and a second copy of
12
+ * the package. Not public.
13
+ */
14
+ export declare const SITE_CHECK: unique symbol;
15
+ /** Puts the check on a `jsonActions` instance. */
16
+ export declare function rememberSiteCheck(actions: object, check: SiteCheck): void;
17
+ /** Whether `actions` carries a site check, as every `jsonActions()` instance does. */
18
+ export declare const hasSiteCheck: (actions: object) => boolean;
19
+ /**
20
+ * Refuses a cross-site request with the rule of the `jsonActions` instance
21
+ * (its configured origin, read at each request); an object without a check
22
+ * gets the request's own origin. It reads headers only, never the body.
23
+ */
24
+ export declare function refuseCrossSite(actions: object, request: Request): void;
25
+ //# sourceMappingURL=same-site.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"same-site.d.ts","sourceRoot":"","sources":["../../src/errors/same-site.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,SAAS,CACxB,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,GACtD,SAAS,CAaX;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,eAAiD,CAAC;AAEzE,kDAAkD;AAClD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAMzE;AAED,sFAAsF;AACtF,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,KAAG,OACwB,CAAC;AAExE;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAGvE"}
@@ -0,0 +1,7 @@
1
+ /** `@nxgt/janus`'s code for a wrong second-factor or step-up code. */
2
+ export declare const INVALID_CODE = "CODE_INVALID";
3
+ /** `@nxgt/janus`'s codes for a challenge that is gone: unknown, spent or expired. */
4
+ export declare const CHALLENGE_OVER: readonly ["TOKEN_UNKNOWN", "TOKEN_SPENT", "TOKEN_EXPIRED"];
5
+ /** `@nxgt/janus`'s code for a mail the API holds back: a link or a code asked for too often. */
6
+ export declare const MAIL_THROTTLED = "MAIL_THROTTLED";
7
+ //# sourceMappingURL=codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codes.d.ts","sourceRoot":"","sources":["../../src/session/codes.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C,qFAAqF;AACrF,eAAO,MAAM,cAAc,4DAIjB,CAAC;AAEX,gGAAgG;AAChG,eAAO,MAAM,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,60 @@
1
+ export interface SessionCookiesOptions {
2
+ /**
3
+ * The base name of the session cookie, e.g. `'my-app_session'`. With
4
+ * `secure`, the cookie is named `__Host-my-app_session`.
5
+ */
6
+ readonly session: string;
7
+ /**
8
+ * The base name of the second-factor challenge's cookie. With `secure`, it
9
+ * is named `__Secure-<name>`.
10
+ */
11
+ readonly challenge: string;
12
+ /**
13
+ * The app is served over HTTPS. Required, and never read from the
14
+ * environment: pass `!import.meta.env.DEV`. `false` drops `Secure` and the
15
+ * prefixes (Safari drops a `Secure` cookie over `http://localhost`).
16
+ */
17
+ readonly secure: boolean;
18
+ /** Where the browser sends the challenge. `'/sign-in'` by default. */
19
+ readonly challengePath?: string | undefined;
20
+ /** The most the challenge lives. 300, `@nxgt/janus`'s lifetime, by default. */
21
+ readonly challengeSeconds?: number | undefined;
22
+ }
23
+ /** What the session cookie holds: the token, and the expiry (ms) it was last set to. */
24
+ export interface CookieSession {
25
+ readonly token: string;
26
+ readonly expiresAt: number;
27
+ }
28
+ export interface SessionCookies {
29
+ /** The names as sent, prefixes included. */
30
+ readonly names: {
31
+ readonly session: string;
32
+ readonly challenge: string;
33
+ };
34
+ /** The session cookie of the request; `null` when absent or not `<ms>.<token>`. */
35
+ read(request: Request): CookieSession | null;
36
+ /** The session token of the request, or `null`. */
37
+ token(request: Request): string | null;
38
+ /** A `Set-Cookie` value keeping `token` until `expiresAt`. */
39
+ commit(token: string, expiresAt: string | Date, now?: number): string;
40
+ /** A `Set-Cookie` value removing the session cookie. */
41
+ destroy(): string;
42
+ /** The `Set-Cookie` header that keeps the cookie as long as the session lives; empty when the expiry did not move, or is absent or not a date. */
43
+ refreshed(session: CookieSession, expiresAt: string | Date | null): HeadersInit;
44
+ /** The challenge cookie of the request, or `null`. */
45
+ challengeOf(request: Request): string | null;
46
+ /** A `Set-Cookie` value keeping the challenge for the code page. */
47
+ commitChallenge(challenge: string, expiresAt?: string | Date | null, now?: number): string;
48
+ /** A `Set-Cookie` value removing the challenge. */
49
+ destroyChallenge(): string;
50
+ /**
51
+ * What a signed-out visit of the sign-in page sets: the challenge cleared
52
+ * blind (a client navigation fetches `/sign-in.data`, which the cookie's
53
+ * path does not match, so the request never shows it), and a dead
54
+ * session's cookie when `deadSession`.
55
+ */
56
+ signInPageHeaders(deadSession: boolean): Headers;
57
+ }
58
+ /** The cookies of a BFF's session and of its second-factor challenge. */
59
+ export declare function sessionCookies(options: SessionCookiesOptions): SessionCookies;
60
+ //# sourceMappingURL=cookies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/session/cookies.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,qBAAqB;IACrC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,+EAA+E;IAC/E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/C;AAED,wFAAwF;AACxF,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC9B,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACzE,mFAAmF;IACnF,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAAC;IAC7C,mDAAmD;IACnD,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IACvC,8DAA8D;IAC9D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtE,wDAAwD;IACxD,OAAO,IAAI,MAAM,CAAC;IAClB,kJAAkJ;IAClJ,SAAS,CACR,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAC7B,WAAW,CAAC;IACf,sDAAsD;IACtD,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IAC7C,oEAAoE;IACpE,eAAe,CACd,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,EAChC,GAAG,CAAC,EAAE,MAAM,GACV,MAAM,CAAC;IACV,mDAAmD;IACnD,gBAAgB,IAAI,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,iBAAiB,CAAC,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC;CACjD;AAiBD,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,cAAc,CA6E7E"}