@alxia/react-router 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +370 -20
- package/dist/chunks/index-5rt6hnhn.js +42 -0
- package/dist/chunks/index-5rt6hnhn.js.map +11 -0
- package/dist/chunks/{index-mppz0806.js → index-6jf7zpxz.js} +5 -5
- package/dist/chunks/{index-mppz0806.js.map → index-6jf7zpxz.js.map} +1 -1
- package/dist/chunks/index-y6vpnjr3.js +123 -0
- package/dist/chunks/index-y6vpnjr3.js.map +14 -0
- package/dist/context.d.ts +0 -7
- package/dist/context.d.ts.map +1 -1
- package/dist/document/index.d.ts +11 -0
- package/dist/document/index.d.ts.map +1 -0
- package/dist/document/index.js +19 -0
- package/dist/document/index.js.map +9 -0
- package/dist/document/inline-script.d.ts +27 -0
- package/dist/document/inline-script.d.ts.map +1 -0
- package/dist/document/language-store.d.ts +8 -0
- package/dist/document/language-store.d.ts.map +1 -0
- package/dist/document/nonce.d.ts +34 -0
- package/dist/document/nonce.d.ts.map +1 -0
- package/dist/document/page-language.d.ts +39 -0
- package/dist/document/page-language.d.ts.map +1 -0
- package/dist/document/text-direction.d.ts +10 -0
- package/dist/document/text-direction.d.ts.map +1 -0
- package/dist/entry/abort.d.ts +21 -0
- package/dist/entry/abort.d.ts.map +1 -0
- package/dist/entry/create-entry.d.ts +32 -0
- package/dist/entry/create-entry.d.ts.map +1 -0
- package/dist/entry/index.d.ts +8 -0
- package/dist/entry/index.d.ts.map +1 -0
- package/dist/entry/index.js +128 -0
- package/dist/entry/index.js.map +12 -0
- package/dist/entry/whole-page.d.ts +10 -0
- package/dist/entry/whole-page.d.ts.map +1 -0
- package/dist/errors/api-error.d.ts +86 -0
- package/dist/errors/api-error.d.ts.map +1 -0
- package/dist/errors/api-errors.d.ts +96 -0
- package/dist/errors/api-errors.d.ts.map +1 -0
- package/dist/errors/call-failure.d.ts +45 -0
- package/dist/errors/call-failure.d.ts.map +1 -0
- package/dist/errors/catalogue-check.d.ts +24 -0
- package/dist/errors/catalogue-check.d.ts.map +1 -0
- package/dist/errors/catalogue-read.d.ts +33 -0
- package/dist/errors/catalogue-read.d.ts.map +1 -0
- package/dist/errors/catalogue.d.ts +59 -0
- package/dist/errors/catalogue.d.ts.map +1 -0
- package/dist/errors/code-resolver.d.ts +44 -0
- package/dist/errors/code-resolver.d.ts.map +1 -0
- package/dist/errors/describe-refusal.d.ts +6 -0
- package/dist/errors/describe-refusal.d.ts.map +1 -0
- package/dist/errors/describe.d.ts +3 -0
- package/dist/errors/describe.d.ts.map +1 -0
- package/dist/errors/fetcher-result.d.ts +21 -0
- package/dist/errors/fetcher-result.d.ts.map +1 -0
- package/dist/errors/form-errors.d.ts +8 -0
- package/dist/errors/form-errors.d.ts.map +1 -0
- package/dist/errors/index.d.ts +15 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +602 -0
- package/dist/errors/index.js.map +29 -0
- package/dist/errors/json-actions.d.ts +38 -0
- package/dist/errors/json-actions.d.ts.map +1 -0
- package/dist/errors/log.d.ts +8 -0
- package/dist/errors/log.d.ts.map +1 -0
- package/dist/errors/message-values.d.ts +11 -0
- package/dist/errors/message-values.d.ts.map +1 -0
- package/dist/errors/messages.d.ts +63 -0
- package/dist/errors/messages.d.ts.map +1 -0
- package/dist/errors/page-path.d.ts +9 -0
- package/dist/errors/page-path.d.ts.map +1 -0
- package/dist/errors/provider.d.ts +20 -0
- package/dist/errors/provider.d.ts.map +1 -0
- package/dist/errors/request-id.d.ts +5 -0
- package/dist/errors/request-id.d.ts.map +1 -0
- package/dist/errors/route-error.d.ts +31 -0
- package/dist/errors/route-error.d.ts.map +1 -0
- package/dist/errors/standard-schema.d.ts +34 -0
- package/dist/errors/standard-schema.d.ts.map +1 -0
- package/dist/errors/submit-form.d.ts +16 -0
- package/dist/errors/submit-form.d.ts.map +1 -0
- package/dist/errors/use-json-fetcher.d.ts +18 -0
- package/dist/errors/use-json-fetcher.d.ts.map +1 -0
- package/dist/index.js +13 -34
- package/dist/index.js.map +3 -5
- package/dist/pwa/build/index.js +1 -1
- package/dist/pwa/index.js +6 -6
- package/dist/pwa/index.js.map +1 -1
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +29 -2
- package/dist/vite/index.js.map +5 -4
- package/dist/vite/inline.d.ts +18 -0
- package/dist/vite/inline.d.ts.map +1 -0
- package/docs/README.md +3 -1
- package/docs/guide/csp-nonce.md +35 -3
- package/docs/guide/document.md +310 -0
- package/docs/guide/errors.md +838 -0
- package/docs/roadmap.md +36 -1
- package/docs/troubleshooting.md +712 -1
- package/package.json +33 -3
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shape of an API's refusal, as `@nxgt/graphql-client`'s `ApiError`
|
|
3
|
+
* carries it, declared structurally: `/errors` never imports the client, so
|
|
4
|
+
* an app needs it only if it calls the API through it. `api-error.spec.ts`
|
|
5
|
+
* holds the two in step.
|
|
6
|
+
*/
|
|
7
|
+
/** One refused input field: `extensions.fields` of a validation refusal. */
|
|
8
|
+
export interface ApiFieldErrorLike {
|
|
9
|
+
readonly path: string;
|
|
10
|
+
readonly code: string;
|
|
11
|
+
readonly message: string;
|
|
12
|
+
/** The values the field's message interpolates. */
|
|
13
|
+
readonly params?: Readonly<Record<string, unknown>>;
|
|
14
|
+
}
|
|
15
|
+
/** The values a message interpolates; a throttle's wait is `minutes` or `retryAfter`. */
|
|
16
|
+
export interface ApiErrorParamsLike {
|
|
17
|
+
readonly minutes?: unknown;
|
|
18
|
+
readonly retryAfter?: unknown;
|
|
19
|
+
readonly [key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* One GraphQL error's `extensions`. `code` is the API's own
|
|
23
|
+
* `<module>.errors.<slug>`; the rest is what its messages name.
|
|
24
|
+
*/
|
|
25
|
+
export interface ApiErrorExtensionsLike {
|
|
26
|
+
readonly code?: string;
|
|
27
|
+
/** The values the message interpolates, when the API sends them. */
|
|
28
|
+
readonly params?: ApiErrorParamsLike;
|
|
29
|
+
/** A validation refusal: every field at fault, by input path. */
|
|
30
|
+
readonly fields?: readonly ApiFieldErrorLike[];
|
|
31
|
+
/** Any other refusal about one input field, by its path. */
|
|
32
|
+
readonly field?: string;
|
|
33
|
+
/** A throttle's wait, in minutes (`waitMinutes` coerces a string). */
|
|
34
|
+
readonly minutes?: unknown;
|
|
35
|
+
/** A throttle's wait, in seconds. */
|
|
36
|
+
readonly retryAfter?: unknown;
|
|
37
|
+
readonly [key: string]: unknown;
|
|
38
|
+
}
|
|
39
|
+
/** One error of a response's `errors`. */
|
|
40
|
+
export interface ApiErrorEntryLike {
|
|
41
|
+
readonly message: string;
|
|
42
|
+
readonly extensions?: ApiErrorExtensionsLike;
|
|
43
|
+
}
|
|
44
|
+
/** A refusal read from a GraphQL API: what `ApiError` has, and the request id. */
|
|
45
|
+
export interface ApiErrorLike extends Error {
|
|
46
|
+
readonly errors: readonly ApiErrorEntryLike[];
|
|
47
|
+
/** The first error's `extensions.code`. */
|
|
48
|
+
readonly code: string | undefined;
|
|
49
|
+
/** The HTTP status to answer with. */
|
|
50
|
+
readonly status: number;
|
|
51
|
+
/** The id the API logged the request under, when the caller kept it. */
|
|
52
|
+
readonly requestId?: string;
|
|
53
|
+
}
|
|
54
|
+
/** Whether `error` is an `Error` of this `name`: the client's errors are told by it, never `instanceof`. */
|
|
55
|
+
export declare const isNamed: (error: unknown, name: string) => error is Error;
|
|
56
|
+
/**
|
|
57
|
+
* Whether `error` is an `ApiError` of `@nxgt/graphql-client`, by the test
|
|
58
|
+
* that client's `isApiError` makes (an `Error` named `ApiError` with an
|
|
59
|
+
* `errors` array), plus a numeric `status`, which `ApiErrorLike` promises.
|
|
60
|
+
* It holds across two copies of the client.
|
|
61
|
+
*/
|
|
62
|
+
export declare function isApiErrorLike(error: unknown): error is ApiErrorLike;
|
|
63
|
+
/**
|
|
64
|
+
* The minutes a wait lasts, as the API words it: `minutes` (at least one, in
|
|
65
|
+
* `extensions.params` or beside it), else the `retryAfter` seconds rounded
|
|
66
|
+
* up, else one.
|
|
67
|
+
*/
|
|
68
|
+
export declare function waitMinutes(extensions: ApiErrorExtensionsLike | undefined): number;
|
|
69
|
+
/**
|
|
70
|
+
* The values a message names: `extensions.params` over the extensions
|
|
71
|
+
* themselves, where older errors and the extras of a few sit.
|
|
72
|
+
*/
|
|
73
|
+
export declare function valuesOf(extensions: ApiErrorExtensionsLike | undefined): Record<string, unknown> | undefined;
|
|
74
|
+
/** `@nxgt/graphql-client`'s `ApiStatusError`, as far as the failure reads it. */
|
|
75
|
+
export interface StatusErrorLike extends Error {
|
|
76
|
+
status: number;
|
|
77
|
+
statusText?: string | undefined;
|
|
78
|
+
body?: unknown;
|
|
79
|
+
}
|
|
80
|
+
/** `@nxgt/graphql-client`'s `ApiUnavailableError`, as far as the failure reads it. */
|
|
81
|
+
export interface UnavailableErrorLike extends Error {
|
|
82
|
+
reason: string;
|
|
83
|
+
}
|
|
84
|
+
export declare const isStatusError: (error: unknown) => error is StatusErrorLike;
|
|
85
|
+
export declare const isUnavailableError: (error: unknown) => error is UnavailableErrorLike;
|
|
86
|
+
//# sourceMappingURL=api-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-error.d.ts","sourceRoot":"","sources":["../../src/errors/api-error.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACpD;AAED,yFAAyF;AACzF,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IACrC,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC/C,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,qCAAqC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC;AAED,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,sBAAsB,CAAC;CAC7C;AAED,kFAAkF;AAClF,MAAM,WAAW,YAAa,SAAQ,KAAK;IAC1C,QAAQ,CAAC,MAAM,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC9C,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,sCAAsC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,4GAA4G;AAC5G,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,EAAE,MAAM,MAAM,KAAG,KAAK,IAAI,KAClB,CAAC;AAE/C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAMpE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAC1B,UAAU,EAAE,sBAAsB,GAAG,SAAS,GAC5C,MAAM,CAKR;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CACvB,UAAU,EAAE,sBAAsB,GAAG,SAAS,GAC5C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAKrC;AAED,iFAAiF;AACjF,MAAM,WAAW,eAAgB,SAAQ,KAAK;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED,sFAAsF;AACtF,MAAM,WAAW,oBAAqB,SAAQ,KAAK;IAClD,MAAM,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,eAEG,CAAC;AAE5D,eAAO,MAAM,kBAAkB,GAC9B,OAAO,OAAO,KACZ,KAAK,IAAI,oBAE+C,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { data } from 'react-router';
|
|
2
|
+
import type { ApiErrorLike } from './api-error';
|
|
3
|
+
import type { FormErrors } from './form-errors';
|
|
4
|
+
import type { ApiMessages } from './messages';
|
|
5
|
+
import type { RouteErrorOptions } from './route-error';
|
|
6
|
+
/** A refused call, as a page says it: the message, and the HTTP status to answer. */
|
|
7
|
+
export type ApiRefusal = {
|
|
8
|
+
message: string;
|
|
9
|
+
status: number;
|
|
10
|
+
};
|
|
11
|
+
export interface ApiErrorsOptions<L extends string> {
|
|
12
|
+
/** The catalogue the API's codes are worded from. */
|
|
13
|
+
messages: ApiMessages<L>;
|
|
14
|
+
/**
|
|
15
|
+
* The app's own word for an API it cannot reach (a 503 `Response`): not
|
|
16
|
+
* an API error, so never one of the catalogue's codes.
|
|
17
|
+
*/
|
|
18
|
+
unavailable(language: L): string;
|
|
19
|
+
/**
|
|
20
|
+
* The app's generic refusal, said for an error with no API code (a raw
|
|
21
|
+
* `BAD_USER_INPUT` before the API's validation layer), never the raw
|
|
22
|
+
* message. Without it, such an error says the message the API sent.
|
|
23
|
+
*/
|
|
24
|
+
refused?(language: L): string;
|
|
25
|
+
/**
|
|
26
|
+
* An app's own wording for given codes, such as the API's request limits
|
|
27
|
+
* (depth, cost, introspection), whose params differ and name no field.
|
|
28
|
+
* Checked after `refused`, before the catalogue.
|
|
29
|
+
*/
|
|
30
|
+
byCode?: Readonly<Record<string, (error: ApiErrorLike, language: L) => string>>;
|
|
31
|
+
/** Whether a code is an API code; `<module>.errors.<slug>` by default. */
|
|
32
|
+
isApiCode?(code: string): boolean;
|
|
33
|
+
}
|
|
34
|
+
/** What a page says of an API's refusals, in a language. */
|
|
35
|
+
export interface ApiErrors<L extends string> {
|
|
36
|
+
/**
|
|
37
|
+
* The catalogue's text of an API code in `language`, else `fallback` (the
|
|
38
|
+
* message the API already worded). `values` are the message's arguments
|
|
39
|
+
* (`extensions.params`).
|
|
40
|
+
*/
|
|
41
|
+
translateCode(code: string | undefined, fallback: string, language: L, values?: Readonly<Record<string, unknown>>): string;
|
|
42
|
+
/**
|
|
43
|
+
* What to show for an API error: `refused` for an error with no API code,
|
|
44
|
+
* when given; else `byCode`'s wording of its code; else the catalogue's
|
|
45
|
+
* text; else the message the API already worded.
|
|
46
|
+
*/
|
|
47
|
+
apiErrorMessage(error: ApiErrorLike, language: L): string;
|
|
48
|
+
/**
|
|
49
|
+
* The message of each refused field, by input path, ready for a form: the
|
|
50
|
+
* entries of `extensions.fields`, else the one field `extensions.field`
|
|
51
|
+
* names, with the error's own message. Empty for neither.
|
|
52
|
+
*/
|
|
53
|
+
fieldErrors(error: ApiErrorLike, language: L): Record<string, string>;
|
|
54
|
+
/** `unavailable`, in `language`. */
|
|
55
|
+
unavailableMessage(language: L): string;
|
|
56
|
+
/**
|
|
57
|
+
* What a failed call says to the user: an API refusal's message and its
|
|
58
|
+
* status, or an API it cannot reach (a 503 `Response`: the unavailable
|
|
59
|
+
* word). Undefined for anything else, which the caller rethrows.
|
|
60
|
+
*/
|
|
61
|
+
apiRefusal(error: unknown, language: L): ApiRefusal | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* A fetcher's refusal: `apiRefusal`'s, so the page stays where it was. A
|
|
64
|
+
* 401 (the session caller redirects first) or any other failure is
|
|
65
|
+
* thrown, through `routeError`, for the error page.
|
|
66
|
+
*/
|
|
67
|
+
fetcherRefusal(error: unknown, language: L, route?: RouteErrorOptions): ApiRefusal;
|
|
68
|
+
/**
|
|
69
|
+
* Runs the mutation of an action a fetcher posted to: `{ ok: true }` with
|
|
70
|
+
* `about` and the mutation's value, or `{ ok: false, error }` with `about`
|
|
71
|
+
* and the refusal's message, answered with its HTTP status.
|
|
72
|
+
*/
|
|
73
|
+
fetcherResult<About extends object, Value extends object = Record<never, never>>(language: L, about: About, run: () => Promise<Value>, route?: RouteErrorOptions): Promise<({
|
|
74
|
+
ok: true;
|
|
75
|
+
} & About & Value) | ReturnType<typeof data<{
|
|
76
|
+
ok: false;
|
|
77
|
+
error: string;
|
|
78
|
+
} & About>>>;
|
|
79
|
+
/**
|
|
80
|
+
* Runs a form's mutation: `{ ok: true, value }`, or the form's errors
|
|
81
|
+
* (`fieldErrors` under the form field `fieldOf` names an input path by,
|
|
82
|
+
* and a `formError` for the rest) with the refusal's status. A 404 about
|
|
83
|
+
* none of the form's fields, a 401 and other failures are thrown for the
|
|
84
|
+
* error page, through `routeError` (with `route`).
|
|
85
|
+
*/
|
|
86
|
+
submitForm<T>(language: L, run: () => Promise<T>, fieldOf: (path: string) => string | undefined, route?: RouteErrorOptions): Promise<{
|
|
87
|
+
ok: true;
|
|
88
|
+
value: T;
|
|
89
|
+
} | ReturnType<typeof data<FormErrors>>>;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The wording of an API's refusals for the languages `L`, from the
|
|
93
|
+
* catalogue `messages` holds. Make one per app, beside its `createApiMessages`.
|
|
94
|
+
*/
|
|
95
|
+
export declare function createApiErrors<L extends string>(options: ApiErrorsOptions<L>): ApiErrors<L>;
|
|
96
|
+
//# sourceMappingURL=api-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-errors.d.ts","sourceRoot":"","sources":["../../src/errors/api-errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,qFAAqF;AACrF,MAAM,MAAM,UAAU,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM;IACjD,qDAAqD;IACrD,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACzB;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC;IACjC;;;;OAIG;IACH,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC;IAC9B;;;;OAIG;IACH,MAAM,CAAC,EAAE,QAAQ,CAChB,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,KAAK,MAAM,CAAC,CAC5D,CAAC;IACF,0EAA0E;IAC1E,SAAS,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAClC;AAED,4DAA4D;AAC5D,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,MAAM;IAC1C;;;;OAIG;IACH,aAAa,CACZ,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,CAAC,EACX,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,MAAM,CAAC;IACV;;;;OAIG;IACH,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC;IAC1D;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtE,oCAAoC;IACpC,kBAAkB,CAAC,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC;IACxC;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,UAAU,GAAG,SAAS,CAAC;IAChE;;;;OAIG;IACH,cAAc,CACb,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,CAAC,EACX,KAAK,CAAC,EAAE,iBAAiB,GACvB,UAAU,CAAC;IACd;;;;OAIG;IACH,aAAa,CACZ,KAAK,SAAS,MAAM,EACpB,KAAK,SAAS,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAE3C,QAAQ,EAAE,CAAC,EACX,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,EACzB,KAAK,CAAC,EAAE,iBAAiB,GACvB,OAAO,CACP,CAAC;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG,KAAK,GAAG,KAAK,CAAC,GAC9B,UAAU,CAAC,OAAO,IAAI,CAAC;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,KAAK,CAAC,CAAC,CAC/D,CAAC;IACF;;;;;;OAMG;IACH,UAAU,CAAC,CAAC,EACX,QAAQ,EAAE,CAAC,EACX,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACrB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAC7C,KAAK,CAAC,EAAE,iBAAiB,GACvB,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,CAAC,CAAA;KAAE,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;CACzE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAC/C,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC1B,SAAS,CAAC,CAAC,CAAC,CAEd"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export interface CallFailureOptions {
|
|
2
|
+
/** What a log line names the API by, such as `my-api https://api.example.com/graphql`. */
|
|
3
|
+
api: string;
|
|
4
|
+
/** The operation's name, for the log (`operationName(document)`). */
|
|
5
|
+
operation?: string;
|
|
6
|
+
/** The `x-request-id` the API answered, when it did (`requestIdOf(response)`). */
|
|
7
|
+
requestId?: string;
|
|
8
|
+
/** The incoming request's signal: an aborted call is answered 503. */
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
/** The statuses without a GraphQL body that become a `Response` of their own; 401, 403 and 404 by default. */
|
|
11
|
+
passedThrough?: ReadonlySet<number>;
|
|
12
|
+
/** Where the lines go; `console` by default. */
|
|
13
|
+
log?: Pick<Console, 'warn' | 'error'>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* What a call became once it failed, for a loader or an action to throw: the
|
|
17
|
+
* `ApiError` as it is (carrying `requestId`), a `Response` of the API's own
|
|
18
|
+
* status for a 401, 403 or 404 without a GraphQL body, a 503 `Response` (with no body; the reason is in the log) for an
|
|
19
|
+
* unreachable, slow, garbled or aborted API, and any other error as it is.
|
|
20
|
+
* Every case it recognises is logged with the request id, when the API gave one, and never
|
|
21
|
+
* the headers, the variables nor a token; the id rides on the `ApiError` as
|
|
22
|
+
* `requestId` and on a `Response` as `x-request-id`, where `routeError` reads
|
|
23
|
+
* it.
|
|
24
|
+
*
|
|
25
|
+
* It recognises `@nxgt/graphql-client`'s errors by their `name`, never with
|
|
26
|
+
* `instanceof`, so it needs no import of the client and holds across two
|
|
27
|
+
* copies of it.
|
|
28
|
+
*/
|
|
29
|
+
export declare function apiCallFailure(error: unknown, { api, operation, requestId, signal, passedThrough, log: appLog, }: CallFailureOptions): unknown;
|
|
30
|
+
/** A document, as far as `operationName` reads it: `graphql`'s `DocumentNode` fits. */
|
|
31
|
+
export interface DocumentLike {
|
|
32
|
+
readonly definitions: readonly {
|
|
33
|
+
readonly kind: string;
|
|
34
|
+
readonly operation?: string | undefined;
|
|
35
|
+
readonly name?: {
|
|
36
|
+
readonly value: string;
|
|
37
|
+
} | undefined;
|
|
38
|
+
}[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The name of the operation a document holds, for a log line: its name, else
|
|
42
|
+
* its kind (`query`, `mutation`, `subscription`), else `operation`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function operationName(document: DocumentLike): string;
|
|
45
|
+
//# sourceMappingURL=call-failure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-failure.d.ts","sourceRoot":"","sources":["../../src/errors/call-failure.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,kBAAkB;IAClC,0FAA0F;IAC1F,GAAG,EAAE,MAAM,CAAC;IACZ,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8GAA8G;IAC9G,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,gDAAgD;IAChD,GAAG,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;CACtC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC7B,KAAK,EAAE,OAAO,EACd,EACC,GAAG,EACH,SAAuB,EACvB,SAAS,EACT,MAAM,EACN,aAA8B,EAC9B,GAAG,EAAE,MAAgB,GACrB,EAAE,kBAAkB,GACnB,OAAO,CAyCT;AAED,uFAAuF;AACvF,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,WAAW,EAAE,SAAS;QAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACxC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;KACvD,EAAE,CAAC;CACJ;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAO5D"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Held } from './catalogue-read';
|
|
2
|
+
/** What the TTL check needs: the reader's state and the app's own calls. */
|
|
3
|
+
export interface CheckContext<L extends string> {
|
|
4
|
+
reader: {
|
|
5
|
+
held: Map<L, Held>;
|
|
6
|
+
load(language: L, now: number): Promise<void>;
|
|
7
|
+
};
|
|
8
|
+
versions(): Promise<Partial<Record<L, string>>>;
|
|
9
|
+
ttl(): number;
|
|
10
|
+
retryMs: number;
|
|
11
|
+
log: Pick<Console, 'error'>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Asks the versions in one call and reads again the messages of each
|
|
15
|
+
* language that moved. An API that cannot be reached keeps the messages
|
|
16
|
+
* held (stale, still worded) and is asked again after `retryMs`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function checkVersions<L extends string>({ reader, versions, ttl, retryMs, log }: CheckContext<L>, now: number): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* The TTL, whose getter is the app's: one that throws, or that is not a
|
|
21
|
+
* finite number of at least 0, is logged and `fallback` is used.
|
|
22
|
+
*/
|
|
23
|
+
export declare function safeTtl(ttlMs: number | (() => number), fallback: number, log: Pick<Console, 'error'>): () => number;
|
|
24
|
+
//# sourceMappingURL=catalogue-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogue-check.d.ts","sourceRoot":"","sources":["../../src/errors/catalogue-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,4EAA4E;AAC5E,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM;IAC7C,MAAM,EAAE;QACP,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACnB,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KAC9C,CAAC;IACF,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAChD,GAAG,IAAI,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,CAAC,SAAS,MAAM,EACnD,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,EACxD,GAAG,EAAE,MAAM,iBAoBX;AAED;;;GAGG;AACH,wBAAgB,OAAO,CACtB,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,EAC9B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,gBAc3B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ApiMessages, CatalogueMessage } from './messages';
|
|
2
|
+
/** What the API answers for one language: its version and every message. */
|
|
3
|
+
export type CatalogueReply = {
|
|
4
|
+
version: string;
|
|
5
|
+
messages: ReadonlyArray<CatalogueMessage & {
|
|
6
|
+
readonly code: string;
|
|
7
|
+
}>;
|
|
8
|
+
};
|
|
9
|
+
/** A language's catalogue as held, and when its version was last confirmed. */
|
|
10
|
+
export type Held = {
|
|
11
|
+
version: string;
|
|
12
|
+
checkedAt: number;
|
|
13
|
+
};
|
|
14
|
+
export interface CatalogueReaderOptions<L extends string> {
|
|
15
|
+
messages: ApiMessages<L>;
|
|
16
|
+
read(language: L): Promise<CatalogueReply>;
|
|
17
|
+
retryMs: number;
|
|
18
|
+
firstReadWaitMs: number;
|
|
19
|
+
log: Pick<Console, 'error'>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The reading half of the catalogue: the first read of each language (one in
|
|
23
|
+
* flight, a bounded wait, a retry delay after a failure) and the version
|
|
24
|
+
* each one holds. `createErrorCatalogue` adds the TTL check on top.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createCatalogueReader<L extends string>({ messages, read, retryMs, firstReadWaitMs, log, }: CatalogueReaderOptions<L>): {
|
|
27
|
+
held: Map<L, Held>;
|
|
28
|
+
load: (language: L, now: number) => Promise<void>;
|
|
29
|
+
/** Reads a language that is not held yet, unless a failure is still fresh. */
|
|
30
|
+
first(language: L, now: number): Promise<void>;
|
|
31
|
+
reset(): void;
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=catalogue-read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogue-read.d.ts","sourceRoot":"","sources":["../../src/errors/catalogue-read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhE,4EAA4E;AAC5E,MAAM,MAAM,cAAc,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC,gBAAgB,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtE,CAAC;AAEF,+EAA+E;AAC/E,MAAM,MAAM,IAAI,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,MAAM,WAAW,sBAAsB,CAAC,CAAC,SAAS,MAAM;IACvD,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;CAC5B;AAqBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,EAAE,EACvD,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,eAAe,EACf,GAAG,GACH,EAAE,sBAAsB,CAAC,CAAC,CAAC;;qBAMG,CAAC,OAAO,MAAM;IAwC3C,8EAA8E;oBACxD,CAAC,OAAO,MAAM;;EAYrC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type CatalogueReply } from './catalogue-read';
|
|
2
|
+
import type { ApiMessages, CatalogueMessages } from './messages';
|
|
3
|
+
export type { CatalogueReply } from './catalogue-read';
|
|
4
|
+
export interface ErrorCatalogueOptions<L extends string> {
|
|
5
|
+
/** The store the page words refusals from (`createApiMessages`). */
|
|
6
|
+
messages: ApiMessages<L>;
|
|
7
|
+
/** The languages to hold, each read once and kept fresh. */
|
|
8
|
+
languages: readonly L[];
|
|
9
|
+
/** Reads one language's catalogue from the API. */
|
|
10
|
+
read(language: L): Promise<CatalogueReply>;
|
|
11
|
+
/** Asks the API for the version of every language, in one call. */
|
|
12
|
+
versions(): Promise<Partial<Record<L, string>>>;
|
|
13
|
+
/** How long a held catalogue is served before its version is checked. */
|
|
14
|
+
ttlMs: number | (() => number);
|
|
15
|
+
/** How soon a check or a first read that failed is tried again. Default 5000. */
|
|
16
|
+
retryMs?: number;
|
|
17
|
+
/**
|
|
18
|
+
* How long a request waits for a language's first read; past it the
|
|
19
|
+
* request goes on and the read carries on in the background. Default 1500.
|
|
20
|
+
*/
|
|
21
|
+
firstReadWaitMs?: number;
|
|
22
|
+
/** The codes the browser words itself (`clientMessages`). */
|
|
23
|
+
clientCodes: readonly string[];
|
|
24
|
+
/** Where failures are reported. Default `console`. */
|
|
25
|
+
log?: Pick<Console, 'error'>;
|
|
26
|
+
}
|
|
27
|
+
/** The API's error catalogue, kept fresh for the server. */
|
|
28
|
+
export interface ErrorCatalogue<L extends string> {
|
|
29
|
+
/**
|
|
30
|
+
* The catalogue of `language`, ready to word a refusal. Only a language
|
|
31
|
+
* with no catalogue yet is awaited, for at most `firstReadWaitMs`. A held
|
|
32
|
+
* one is served as it is, and once older than the TTL its version is
|
|
33
|
+
* checked in the background, one check at a time.
|
|
34
|
+
*/
|
|
35
|
+
fresh(language: L, now?: number): Promise<void>;
|
|
36
|
+
/** Every language, fresh: what the root middleware awaits. */
|
|
37
|
+
freshAll(now?: number): Promise<void>;
|
|
38
|
+
/** At startup: reads every language without holding the boot back. */
|
|
39
|
+
warm(): void;
|
|
40
|
+
/** The messages the browser words itself, by language, for the root's loader. */
|
|
41
|
+
clientMessages(): Record<L, CatalogueMessages>;
|
|
42
|
+
/**
|
|
43
|
+
* Forgets everything held and in flight. For use between tests, with
|
|
44
|
+
* nothing in flight: a read or check still running when it is called
|
|
45
|
+
* finishes and holds its result again.
|
|
46
|
+
*/
|
|
47
|
+
reset(): void;
|
|
48
|
+
/** The version held for a language, if any. */
|
|
49
|
+
heldVersion(language: L): string | undefined;
|
|
50
|
+
/** Waits for the check in flight, if any (tests). */
|
|
51
|
+
settled(): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Keeps the API's error catalogue in `messages`: read on first use, checked
|
|
55
|
+
* against the API's versions once per TTL, and re-read only for the
|
|
56
|
+
* languages whose version moved. It is an instance, not module state.
|
|
57
|
+
*/
|
|
58
|
+
export declare function createErrorCatalogue<L extends string>({ messages, languages, read, versions, ttlMs, retryMs, firstReadWaitMs, clientCodes, log: appLog, }: ErrorCatalogueOptions<L>): ErrorCatalogue<L>;
|
|
59
|
+
//# sourceMappingURL=catalogue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogue.d.ts","sourceRoot":"","sources":["../../src/errors/catalogue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,cAAc,EAAyB,MAAM,kBAAkB,CAAC;AAE9E,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEjE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,MAAM;IACtD,oEAAoE;IACpE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACzB,4DAA4D;IAC5D,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;IACxB,mDAAmD;IACnD,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3C,mEAAmE;IACnE,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAChD,yEAAyE;IACzE,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IAC/B,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,sDAAsD;IACtD,GAAG,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;CAC7B;AAED,4DAA4D;AAC5D,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,MAAM;IAC/C;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,8DAA8D;IAC9D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,sEAAsE;IACtE,IAAI,IAAI,IAAI,CAAC;IACb,iFAAiF;IACjF,cAAc,IAAI,MAAM,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAC/C;;;;OAIG;IACH,KAAK,IAAI,IAAI,CAAC;IACd,+CAA+C;IAC/C,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;IAC7C,qDAAqD;IACrD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAqBD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,EAAE,EACtD,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,OAAe,EACf,eAAuB,EACvB,WAAW,EACX,GAAG,EAAE,MAAgB,GACrB,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAoD9C"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ApiMessages } from './messages';
|
|
2
|
+
/** The part of a zod issue a code reads, by shape (`@nxgt/material-core`'s `CodeIssue`). */
|
|
3
|
+
export type CodeIssueLike = {
|
|
4
|
+
readonly code: string;
|
|
5
|
+
/** A custom issue's params: `.refine(…, { params: { code } })`. */
|
|
6
|
+
readonly params?: Record<string, unknown> | undefined;
|
|
7
|
+
readonly input?: unknown;
|
|
8
|
+
readonly origin?: string | undefined;
|
|
9
|
+
readonly minimum?: unknown;
|
|
10
|
+
readonly maximum?: unknown;
|
|
11
|
+
readonly expected?: unknown;
|
|
12
|
+
readonly message?: string | undefined;
|
|
13
|
+
};
|
|
14
|
+
/** An API error code (`<module>.errors.<slug>`), as opposed to a GraphQL one (`BAD_USER_INPUT`). */
|
|
15
|
+
export declare const API_CODE: RegExp;
|
|
16
|
+
export interface ApiCodeResolverOptions<L extends string> {
|
|
17
|
+
/**
|
|
18
|
+
* The app's translator, for every key that is not an API code. Method
|
|
19
|
+
* syntax: the app's own `Translate<LocaleKey>` is accepted.
|
|
20
|
+
*/
|
|
21
|
+
translate(key: string, context?: Readonly<Record<string, unknown>>, language?: L | (() => L)): string;
|
|
22
|
+
/** The page's language, when a call names none. */
|
|
23
|
+
language(): L;
|
|
24
|
+
/** Which code an issue carries; the issue's `params.code` by default. */
|
|
25
|
+
codeOf?(issue: CodeIssueLike): string | undefined;
|
|
26
|
+
/** Whether a key is an API code; `<module>.errors.<slug>` by default. */
|
|
27
|
+
isApiCode?(key: string): boolean;
|
|
28
|
+
}
|
|
29
|
+
/** What `@nxgt/material`'s `useCodeResolver(schema, resolver)` takes. */
|
|
30
|
+
export interface ApiCodeResolver<L extends string> {
|
|
31
|
+
translate: (key: string, context?: Readonly<Record<string, unknown>>, language?: L | (() => L)) => string;
|
|
32
|
+
codeOf: (issue: CodeIssueLike) => string | undefined;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The words of what a form's checks ask for: a refinement carrying an API
|
|
36
|
+
* code in `params.code` reads exactly as the API words it (from the
|
|
37
|
+
* catalogue `messages` holds), any other key takes the app's translator, and
|
|
38
|
+
* a code the catalogue lacks comes back as it is, so the form library words
|
|
39
|
+
* the issue with its own locale instead. Both functions are stable: a
|
|
40
|
+
* resolver is made once per schema and language, so build this once, at
|
|
41
|
+
* module scope.
|
|
42
|
+
*/
|
|
43
|
+
export declare function apiCodeResolver<L extends string>(messages: ApiMessages<L>, options: ApiCodeResolverOptions<L>): ApiCodeResolver<L>;
|
|
44
|
+
//# sourceMappingURL=code-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-resolver.d.ts","sourceRoot":"","sources":["../../src/errors/code-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,4FAA4F;AAC5F,MAAM,MAAM,aAAa,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACtD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC,CAAC;AAEF,oGAAoG;AACpG,eAAO,MAAM,QAAQ,QAAkC,CAAC;AAExD,MAAM,WAAW,sBAAsB,CAAC,CAAC,SAAS,MAAM;IACvD;;;OAGG;IACH,SAAS,CACR,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC3C,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GACtB,MAAM,CAAC;IACV,mDAAmD;IACnD,QAAQ,IAAI,CAAC,CAAC;IACd,yEAAyE;IACzE,MAAM,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;IAClD,yEAAyE;IACzE,SAAS,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM;IAChD,SAAS,EAAE,CACV,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC3C,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KACpB,MAAM,CAAC;IACZ,MAAM,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,MAAM,GAAG,SAAS,CAAC;CACrD;AAOD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAC/C,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,EACxB,OAAO,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAChC,eAAe,CAAC,CAAC,CAAC,CAiBpB"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ApiErrors } from './api-errors';
|
|
2
|
+
/** The API's refusal of `error`, or `undefined` when it is not one. */
|
|
3
|
+
export declare function refusalOf<L extends string>(errors: Pick<ApiErrors<L>, 'apiErrorMessage' | 'unavailableMessage'>, error: unknown, language: L): ReturnType<ApiErrors<L>['apiRefusal']>;
|
|
4
|
+
/** The worded message of each field an API error names, by field path. */
|
|
5
|
+
export declare function fieldErrorsOf<L extends string>(errors: Pick<ApiErrors<L>, 'apiErrorMessage' | 'translateCode'>, error: Parameters<ApiErrors<L>['fieldErrors']>[0], language: L): ReturnType<ApiErrors<L>['fieldErrors']>;
|
|
6
|
+
//# sourceMappingURL=describe-refusal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe-refusal.d.ts","sourceRoot":"","sources":["../../src/errors/describe-refusal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,uEAAuE;AACvE,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EACzC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,GAAG,oBAAoB,CAAC,EACpE,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,CAAC,GACT,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAWxC;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAC7C,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,GAAG,eAAe,CAAC,EAC/D,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,EACjD,QAAQ,EAAE,CAAC,GACT,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAYzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/errors/describe.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAMhE,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAAE,EACnD,QAAQ,EACR,WAAW,EACX,OAAO,EACP,MAAW,EACX,SAAyC,GACzC,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAkDpC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ApiErrors, ApiRefusal } from './api-errors';
|
|
2
|
+
import { type RouteErrorOptions } from './route-error';
|
|
3
|
+
/**
|
|
4
|
+
* A fetcher's refusal: the API's (`apiRefusal`), an unreachable API's too,
|
|
5
|
+
* so the page stays where it was. A 401 (the session caller redirects
|
|
6
|
+
* first) or any other failure is thrown, for the error page.
|
|
7
|
+
*/
|
|
8
|
+
export declare function fetcherRefusal<L extends string>(errors: Pick<ApiErrors<L>, 'apiRefusal'>, error: unknown, language: L, route?: RouteErrorOptions): ApiRefusal;
|
|
9
|
+
/**
|
|
10
|
+
* Runs the mutation of an action a fetcher posted to: `{ ok: true }` with
|
|
11
|
+
* `about` and the mutation's value, or the refusal (`fetcherRefusal`) as a
|
|
12
|
+
* worded `error`, with its HTTP status, for a toast or a form message.
|
|
13
|
+
*/
|
|
14
|
+
export declare function fetcherResult<L extends string, About extends object, Value extends object = Record<never, never>>(errors: Pick<ApiErrors<L>, 'apiRefusal'>, language: L, about: About, run: () => Promise<Value>, route?: RouteErrorOptions): Promise<import("react-router").UNSAFE_DataWithResponseInit<{
|
|
15
|
+
ok: false;
|
|
16
|
+
} & About & {
|
|
17
|
+
error: string;
|
|
18
|
+
}> | ({
|
|
19
|
+
ok: true;
|
|
20
|
+
} & About & Awaited<Value>)>;
|
|
21
|
+
//# sourceMappingURL=fetcher-result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetcher-result.d.ts","sourceRoot":"","sources":["../../src/errors/fetcher-result.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,KAAK,iBAAiB,EAAc,MAAM,eAAe,CAAC;AAEnE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC9C,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,EACxC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,CAAC,EACX,KAAK,CAAC,EAAE,iBAAiB,GACvB,UAAU,CAOZ;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAClC,CAAC,SAAS,MAAM,EAChB,KAAK,SAAS,MAAM,EACpB,KAAK,SAAS,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAE3C,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,EACxC,QAAQ,EAAE,CAAC,EACX,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,EACzB,KAAK,CAAC,EAAE,iBAAiB;;;;;;6BAQzB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** What a form action answers when the API refused the input. */
|
|
2
|
+
export type FormErrors = {
|
|
3
|
+
/** Messages by form field, already translated. */
|
|
4
|
+
fieldErrors?: Record<string, string>;
|
|
5
|
+
/** A message for the form as a whole, already translated. */
|
|
6
|
+
formError?: string | undefined;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=form-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-errors.d.ts","sourceRoot":"","sources":["../../src/errors/form-errors.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAAG;IACxB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { type ApiErrorEntryLike, type ApiErrorExtensionsLike, type ApiErrorLike, type ApiErrorParamsLike, type ApiFieldErrorLike, isApiErrorLike, waitMinutes, } from './api-error';
|
|
2
|
+
export { type ApiErrors, type ApiErrorsOptions, type ApiRefusal, createApiErrors, } from './api-errors';
|
|
3
|
+
export { apiCallFailure, type CallFailureOptions, type DocumentLike, operationName, } from './call-failure';
|
|
4
|
+
export { type CatalogueReply, createErrorCatalogue, type ErrorCatalogue, type ErrorCatalogueOptions, } from './catalogue';
|
|
5
|
+
export { type ApiCodeResolver, type ApiCodeResolverOptions, apiCodeResolver, type CodeIssueLike, } from './code-resolver';
|
|
6
|
+
export type { FormErrors } from './form-errors';
|
|
7
|
+
export { type JsonActions, type JsonActionsOptions, jsonActions, } from './json-actions';
|
|
8
|
+
export { type ApiMessages, type ApiMessagesOptions, type CatalogueMessage, type CatalogueMessages, createApiMessages, type MessageFormat, type MessageValues, type ParamKind, } from './messages';
|
|
9
|
+
export { nextOf } from './page-path';
|
|
10
|
+
export { ApiMessagesProvider, type ApiMessagesProviderProps, } from './provider';
|
|
11
|
+
export { REQUEST_ID_HEADER, requestIdOf } from './request-id';
|
|
12
|
+
export { errorRequestId, type RouteErrorData, type RouteErrorOptions, routeError, } from './route-error';
|
|
13
|
+
export type { StandardSchemaV1 } from './standard-schema';
|
|
14
|
+
export { type JsonBody, useJsonFetcher } from './use-json-fetcher';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,cAAc,EACd,WAAW,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,eAAe,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,aAAa,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,KAAK,cAAc,EACnB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,qBAAqB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,eAAe,EACf,KAAK,aAAa,GAClB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,WAAW,GACX,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,SAAS,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EACN,mBAAmB,EACnB,KAAK,wBAAwB,GAC7B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACN,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,UAAU,GACV,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,KAAK,QAAQ,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
|