@gusnips/react 0.9.9 → 0.9.11
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 +4 -0
- package/dist/describe-error.d.ts.map +1 -1
- package/dist/describe-error.js +5 -3
- package/dist/describe-error.js.map +1 -1
- package/dist/i18n.d.ts +1 -0
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +14 -0
- package/dist/i18n.js.map +1 -1
- package/dist/query.d.ts +4 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +2 -1
- package/dist/query.js.map +1 -1
- package/package.json +2 -1
- package/src/describe-error.test.ts +8 -0
- package/src/describe-error.ts +5 -3
- package/src/i18n.test.ts +36 -1
- package/src/i18n.ts +17 -0
- package/src/query.test.ts +10 -0
- package/src/query.ts +6 -2
package/README.md
CHANGED
|
@@ -427,6 +427,10 @@ locale. Leave it out and the detector writes it, which is right until you offer
|
|
|
427
427
|
browser": going back to that means clearing the key and detecting again, and a detector that
|
|
428
428
|
writes on every change puts the language it just detected straight back in. One writer per key.
|
|
429
429
|
|
|
430
|
+
Detection walks the browser's language list in the reader's order, exact tag first, then the base
|
|
431
|
+
subtag: `[pt-PT, en]` gets `pt-BR` when that is what you ship, and `[en-GB, pt-BR]` gets `en`.
|
|
432
|
+
`localeGateScript` uses the same rule, so the gate and the app agree about a reader.
|
|
433
|
+
|
|
430
434
|
`createAuthStore` is at `@gusnips/react/store` — a zustand store whose `isLoading` starts `false`
|
|
431
435
|
where there is no window. A session bootstrap can only be in flight in a browser, and `true`
|
|
432
436
|
during a build is a wait that never ends: it once shipped a spinner as the indexable body of a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe-error.d.ts","sourceRoot":"","sources":["../src/describe-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAkB,MAAM,gBAAgB,CAAC;AAG1D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,MAAM,YAAY;AACtB,mDAAmD;AACjD,OAAO;AACT,gEAAgE;GAC9D,QAAQ;AACV,gFAAgF;GAC9E,MAAM;AACR,iFAAiF;GAC/E,MAAM,CAAC;AAEX,+FAA+F;AAC/F,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kGAAkG;IAClG,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C,mFAAmF;IACnF,OAAO,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,SAAS,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,IAAI,CACnD,GAAG,EAAE,GAAG,EACR,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,MAAM,CAAC;AAEZ,wFAAwF;AACxF,KAAK,QAAQ,GAAG,aAAa,GAAG,aAAa,GAAG,WAAW,CAAC;AAE5D;;;;;;;;GAQG;AACH,KAAK,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,YAAY,GAAG,WAAW,CAAC;AAEvE;;;;;;;;;;GAUG;AACH,KAAK,YAAY,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;AACtE,KAAK,UAAU,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,IAAI,IAAI,YAAY,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC;AA4BzF;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,MAAM,SAAS,MAAM,EAChD,CAAC,EAAE,SAAS,CAAC,GAAG,MAAM,GAAG,QAAQ,EAAE,CAAC,EACpC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,MAAM,
|
|
1
|
+
{"version":3,"file":"describe-error.d.ts","sourceRoot":"","sources":["../src/describe-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAkB,MAAM,gBAAgB,CAAC;AAG1D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,MAAM,YAAY;AACtB,mDAAmD;AACjD,OAAO;AACT,gEAAgE;GAC9D,QAAQ;AACV,gFAAgF;GAC9E,MAAM;AACR,iFAAiF;GAC/E,MAAM,CAAC;AAEX,+FAA+F;AAC/F,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kGAAkG;IAClG,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C,mFAAmF;IACnF,OAAO,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,SAAS,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,IAAI,CACnD,GAAG,EAAE,GAAG,EACR,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,MAAM,CAAC;AAEZ,wFAAwF;AACxF,KAAK,QAAQ,GAAG,aAAa,GAAG,aAAa,GAAG,WAAW,CAAC;AAE5D;;;;;;;;GAQG;AACH,KAAK,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,YAAY,GAAG,WAAW,CAAC;AAEvE;;;;;;;;;;GAUG;AACH,KAAK,YAAY,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;AACtE,KAAK,UAAU,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,IAAI,IAAI,YAAY,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC;AA4BzF;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,MAAM,SAAS,MAAM,EAChD,CAAC,EAAE,SAAS,CAAC,GAAG,MAAM,GAAG,QAAQ,EAAE,CAAC,EACpC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,MAAM,CAMR;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,QAAQ,CAAC;IAChB,2FAA2F;IAC3F,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,sFAAsF;IACtF,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;;OAKG;IACH,OAAO,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB,CACpC,MAAM,SAAS,MAAM,EACrB,YAAY,SAAS,MAAM,EAC3B,UAAU,SAAS,MAAM;IAEzB,CAAC,EAAE,SAAS,CAAC,GAAG,MAAM,GAAG,QAAQ,EAAE,GAAG,GAAG,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAC/F,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;OAQG;IACH,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC;;;;;;;;;OASG;IACH,gBAAgB,EAAE,YAAY,CAAC;IAC/B;;;;;;;;;;;;OAYG;IACH,gBAAgB,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC9C;;;;;;;;;;;;OAYG;IACH,cAAc,CAAC,EAAE,CACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,SAAS,KAChD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACzC;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC1C;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,gGAAgG;IAChG,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,YAAY,KAAK,SAAS,CAAC;AAExD,2BAA2B;AAC3B,wBAAgB,oBAAoB,CAClC,MAAM,SAAS,MAAM,EACrB,YAAY,SAAS,MAAM,EAC3B,UAAU,SAAS,MAAM,EACzB,EACA,CAAC,EACD,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,cAAmC,EACnC,KAAU,EACV,QAAQ,EACR,iBAAsB,EACtB,gBAAgB,GACjB,EAAE,qBAAqB,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,cAAc,CAyG9F"}
|
package/dist/describe-error.js
CHANGED
|
@@ -15,11 +15,13 @@ const PLURAL_SUFFIX = /_(zero|one|two|few|many|other)$/;
|
|
|
15
15
|
* which also gets it correct plurals in languages with more than two forms, for free.
|
|
16
16
|
*/
|
|
17
17
|
export function humanizeWait(t, secs, prefix) {
|
|
18
|
+
// Up, never to the nearest: a wait is a floor, and "in 2 hours" for 2h24 sends the reader back
|
|
19
|
+
// early into the same refusal.
|
|
18
20
|
if (secs < 90)
|
|
19
|
-
return t(`${prefix}waitSeconds`, { count: Math.max(1, Math.
|
|
21
|
+
return t(`${prefix}waitSeconds`, { count: Math.max(1, Math.ceil(secs)) });
|
|
20
22
|
if (secs < 90 * 60)
|
|
21
|
-
return t(`${prefix}waitMinutes`, { count: Math.
|
|
22
|
-
return t(`${prefix}waitHours`, { count: Math.
|
|
23
|
+
return t(`${prefix}waitMinutes`, { count: Math.ceil(secs / 60) });
|
|
24
|
+
return t(`${prefix}waitHours`, { count: Math.ceil(secs / 3600) });
|
|
23
25
|
}
|
|
24
26
|
/** Build the describer. */
|
|
25
27
|
export function createErrorDescriber({ t, copyPrefix, formatWait, messageKeyPrefix, knownMessageKeys, localizeParams = (params) => params, codes = {}, fallback, durableLimitCodes = [], maxRetryWaitSecs, }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe-error.js","sourceRoot":"","sources":["../src/describe-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA2GzC,MAAM,aAAa,GAAG,iCAAiC,CAAC;AA2BxD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAC1B,CAAoC,EACpC,IAAY,EACZ,MAAc;IAEd,IAAI,IAAI,GAAG,EAAE;QAAE,OAAO,CAAC,CAAC,GAAG,MAAM,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"describe-error.js","sourceRoot":"","sources":["../src/describe-error.ts"],"names":[],"mappings":"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"}
|
package/dist/i18n.d.ts
CHANGED
|
@@ -59,6 +59,7 @@ export declare function i18nInitOptions({ fallbackLng, supportedLngs, storageKey
|
|
|
59
59
|
};
|
|
60
60
|
detection: {
|
|
61
61
|
lookupLocalStorage: string;
|
|
62
|
+
convertDetectedLanguage: (tag: string) => string;
|
|
62
63
|
lookupQuerystring?: string | undefined;
|
|
63
64
|
order: string[];
|
|
64
65
|
caches: string[];
|
package/dist/i18n.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;;;OAMG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC;CACpC;AAED,wBAAgB,eAAe,CAAC,EAC9B,WAAW,EACX,aAAa,EACb,UAAU,EACV,QAAQ,EACR,aAA0B,GAC3B,EAAE,eAAe
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;;;OAMG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC;CACpC;AAED,wBAAgB,eAAe,CAAC,EAC9B,WAAW,EACX,aAAa,EACb,UAAU,EACV,QAAQ,EACR,aAA0B,GAC3B,EAAE,eAAe;;;;;;;;;uCAOK,MAAM,KAAG,MAAM;;;;;;;;EAkCrC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAmB/E"}
|
package/dist/i18n.js
CHANGED
|
@@ -12,6 +12,19 @@
|
|
|
12
12
|
* shipped.
|
|
13
13
|
*/
|
|
14
14
|
export function i18nInitOptions({ fallbackLng, supportedLngs, storageKey, queryKey, storageWriter = "detector", }) {
|
|
15
|
+
// i18next picks the first EXACT match anywhere in the detected list before it tries a base
|
|
16
|
+
// subtag, so a reader on [pt-PT, en] got English — "en" is exact and "pt-PT" reaches our pt-BR
|
|
17
|
+
// only by its base. Settling each tag on its own, exact then base, leaves only supported tags in
|
|
18
|
+
// the list, in the reader's order. It is the locale gate's rule, written again here rather than
|
|
19
|
+
// imported because `@gusnips/locale` stays a leaf; the two must agree or the gate sends a reader
|
|
20
|
+
// to one language and the app renders another.
|
|
21
|
+
const settle = (tag) => {
|
|
22
|
+
const lower = tag.toLowerCase();
|
|
23
|
+
const base = lower.split("-")[0];
|
|
24
|
+
return (supportedLngs.find((lng) => lng.toLowerCase() === lower) ??
|
|
25
|
+
supportedLngs.find((lng) => lng.split("-")[0]?.toLowerCase() === base) ??
|
|
26
|
+
tag);
|
|
27
|
+
};
|
|
15
28
|
return {
|
|
16
29
|
fallbackLng,
|
|
17
30
|
supportedLngs: [...supportedLngs],
|
|
@@ -25,6 +38,7 @@ export function i18nInitOptions({ fallbackLng, supportedLngs, storageKey, queryK
|
|
|
25
38
|
caches: storageWriter === "detector" ? ["localStorage"] : [],
|
|
26
39
|
...(queryKey ? { lookupQuerystring: queryKey } : {}),
|
|
27
40
|
lookupLocalStorage: storageKey,
|
|
41
|
+
convertDetectedLanguage: settle,
|
|
28
42
|
},
|
|
29
43
|
react: { useSuspense: false },
|
|
30
44
|
// `nonExplicitSupportedLngs` is omitted deliberately. It breaks both shapes a catalog comes in.
|
package/dist/i18n.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA0CH,MAAM,UAAU,eAAe,CAAC,EAC9B,WAAW,EACX,aAAa,EACb,UAAU,EACV,QAAQ,EACR,aAAa,GAAG,UAAU,GACV;IAChB,OAAO;QACL,WAAW;QACX,aAAa,EAAE,CAAC,GAAG,aAAa,CAAC;QACjC,IAAI,EAAE,aAAsB;QAC5B,aAAa,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,yBAAyB;QAChE,SAAS,EAAE;YACT,KAAK,EAAE,QAAQ;gBACb,CAAC,CAAC,CAAC,aAAa,EAAE,cAAc,EAAE,WAAW,CAAC;gBAC9C,CAAC,CAAC,CAAC,cAAc,EAAE,WAAW,CAAC;YACjC,8EAA8E;YAC9E,MAAM,EAAE,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE;YAC5D,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,kBAAkB,EAAE,UAAU;
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"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"}
|
package/dist/query.d.ts
CHANGED
|
@@ -65,6 +65,9 @@ export declare function queryDefaults({ durableLimitCodes, maxRetries, maxRetryW
|
|
|
65
65
|
* an error beside data IS `isRefetchError`, and an error without data IS `isLoadingError`. It
|
|
66
66
|
* takes any query result, infinite ones included, and a test passes a plain object.
|
|
67
67
|
*
|
|
68
|
+
* A missing `error` counts as none. react-query always sends `null`, but a hook that merges two
|
|
69
|
+
* queries can send `undefined`, and a screen must not report a failed refresh for that.
|
|
70
|
+
*
|
|
68
71
|
* Which control to offer is not decided here. Hand the error to the describer: its `recover` comes
|
|
69
72
|
* from the same rule the query client retries by, so the button and the retry cannot disagree.
|
|
70
73
|
*/
|
|
@@ -80,6 +83,6 @@ export type QueryView<T, E = unknown> = {
|
|
|
80
83
|
};
|
|
81
84
|
export declare function queryView<T, E>(query: {
|
|
82
85
|
readonly data: T | undefined;
|
|
83
|
-
readonly error
|
|
86
|
+
readonly error?: E | null;
|
|
84
87
|
}): QueryView<T, E>;
|
|
85
88
|
//# sourceMappingURL=query.d.ts.map
|
package/dist/query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAoC5D,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,OAAO,EACd,iBAAiB,GAAE,SAAS,MAAM,EAAO,EACzC,gBAAgB,SAA8B,GAC7C,OAAO,CAqBT;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAKzE;AAED,wBAAgB,aAAa,CAAC,EAC5B,iBAAsB,EACtB,UAAc,EACd,gBAA8C,EAC9C,SAAyB,EACzB,MAAuB,EACvB,oBAA4B,GAC7B,GAAE,oBAAyB,GAAG,cAAc,CAe5C;AAED
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAoC5D,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,OAAO,EACd,iBAAiB,GAAE,SAAS,MAAM,EAAO,EACzC,gBAAgB,SAA8B,GAC7C,OAAO,CAqBT;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAKzE;AAED,wBAAgB,aAAa,CAAC,EAC5B,iBAAsB,EACtB,UAAc,EACd,gBAA8C,EAC9C,SAAyB,EACzB,MAAuB,EACvB,oBAA4B,GAC7B,GAAE,oBAAyB,GAAG,cAAc,CAe5C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,IAChC;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GAC7B;IAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,GAAG,IAAI,CAAA;CAAE,CAAC;AAEnF,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE;IACrC,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;CAC3B,GAAG,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAMlB"}
|
package/dist/query.js
CHANGED
|
@@ -86,7 +86,8 @@ export function queryDefaults({ durableLimitCodes = [], maxRetries = 2, maxRetry
|
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
export function queryView(query) {
|
|
89
|
-
const { data
|
|
89
|
+
const { data } = query;
|
|
90
|
+
const error = query.error ?? null;
|
|
90
91
|
if (data !== undefined)
|
|
91
92
|
return { state: "ready", data, refreshError: error };
|
|
92
93
|
if (error !== null)
|
package/dist/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,6FAA6F;AAC7F,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAEpD,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAkCvC;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,KAAc,EACd,oBAAuC,EAAE,EACzC,gBAAgB,GAAG,2BAA2B;IAE9C,wFAAwF;IACxF,wEAAwE;IACxE,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAErF,6FAA6F;IAC7F,8FAA8F;IAC9F,8FAA8F;IAC9F,4FAA4F;IAC5F,gBAAgB;IAChB,IAAI,iBAAiB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAE3C,4FAA4F;IAC5F,4FAA4F;IAC5F,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,GAAG,gBAAgB;QAAE,OAAO,KAAK,CAAC;IAE3D,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,uBAAuB,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,YAAoB,EAAE,KAAc;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,YAAY,EAAE,MAAM,CAAC,CAAC;IAC3D,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC;QAAE,OAAO,OAAO,CAAC;IACjD,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAC5B,iBAAiB,GAAG,EAAE,EACtB,UAAU,GAAG,CAAC,EACd,gBAAgB,GAAG,2BAA2B,EAC9C,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,EACzB,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EACvB,oBAAoB,GAAG,KAAK,MACJ,EAAE;IAC1B,OAAO;QACL,OAAO,EAAE;YACP,SAAS;YACT,MAAM;YACN,KAAK,EAAE,CAAC,YAAY,EAAE,KAAK,EAAE,EAAE,CAC7B,YAAY,GAAG,UAAU,IAAI,WAAW,CAAC,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,CAAC;YACtF,UAAU,EAAE,YAAY;YACxB,oBAAoB;YACpB,kBAAkB,EAAE,IAAI;SACzB;QACD,2FAA2F;QAC3F,yFAAyF;QACzF,SAAS,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;KAC5B,CAAC;AACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,6FAA6F;AAC7F,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAEpD,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAkCvC;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,KAAc,EACd,oBAAuC,EAAE,EACzC,gBAAgB,GAAG,2BAA2B;IAE9C,wFAAwF;IACxF,wEAAwE;IACxE,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAErF,6FAA6F;IAC7F,8FAA8F;IAC9F,8FAA8F;IAC9F,4FAA4F;IAC5F,gBAAgB;IAChB,IAAI,iBAAiB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAE3C,4FAA4F;IAC5F,4FAA4F;IAC5F,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,GAAG,gBAAgB;QAAE,OAAO,KAAK,CAAC;IAE3D,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,uBAAuB,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,YAAoB,EAAE,KAAc;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,YAAY,EAAE,MAAM,CAAC,CAAC;IAC3D,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC;QAAE,OAAO,OAAO,CAAC;IACjD,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAC5B,iBAAiB,GAAG,EAAE,EACtB,UAAU,GAAG,CAAC,EACd,gBAAgB,GAAG,2BAA2B,EAC9C,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,EACzB,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EACvB,oBAAoB,GAAG,KAAK,MACJ,EAAE;IAC1B,OAAO;QACL,OAAO,EAAE;YACP,SAAS;YACT,MAAM;YACN,KAAK,EAAE,CAAC,YAAY,EAAE,KAAK,EAAE,EAAE,CAC7B,YAAY,GAAG,UAAU,IAAI,WAAW,CAAC,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,CAAC;YACtF,UAAU,EAAE,YAAY;YACxB,oBAAoB;YACpB,kBAAkB,EAAE,IAAI;SACzB;QACD,2FAA2F;QAC3F,yFAAyF;QACzF,SAAS,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;KAC5B,CAAC;AACJ,CAAC;AAkCD,MAAM,UAAU,SAAS,CAAO,KAG/B;IACC,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACvB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC;IAClC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IAC7E,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACtD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAC9B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gusnips/react",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.11",
|
|
4
4
|
"description": "The headless runtime under a Vite + React SPA: typed fetch client with single-flight refresh, auth store, query defaults, route guards, error boundary, stale-tab recovery, i18n bootstrap.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -128,6 +128,7 @@
|
|
|
128
128
|
"@types/react": "^19.2.14",
|
|
129
129
|
"@types/react-dom": "^19.2.3",
|
|
130
130
|
"i18next": "^26.3.1",
|
|
131
|
+
"i18next-browser-languagedetector": "^8.2.1",
|
|
131
132
|
"react": "^19.2.4",
|
|
132
133
|
"react-dom": "^19.2.4",
|
|
133
134
|
"react-i18next": "^17.0.8",
|
|
@@ -18,6 +18,14 @@ describe("humanizeWait", () => {
|
|
|
18
18
|
expect(humanizeWait(t, 2 * 3600, "errors.")).toBe('errors.waitHours({"count":2})');
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
+
// A wait is a floor. "in 2 hours" for 2h24 sends the reader back 24 minutes early, into the
|
|
22
|
+
// same refusal; every other wait formatter in the fleet already rounds up.
|
|
23
|
+
it("rounds a wait up, never down", () => {
|
|
24
|
+
expect(humanizeWait(t, 2 * 3600 + 24 * 60, "errors.")).toBe('errors.waitHours({"count":3})');
|
|
25
|
+
expect(humanizeWait(t, 2 * 60 + 5, "errors.")).toBe('errors.waitMinutes({"count":3})');
|
|
26
|
+
expect(humanizeWait(t, 74.3, "errors.")).toBe('errors.waitSeconds({"count":75})');
|
|
27
|
+
});
|
|
28
|
+
|
|
21
29
|
it("never says 'in 0 seconds'", () => {
|
|
22
30
|
expect(humanizeWait(t, 0.2, "errors.")).toBe('errors.waitSeconds({"count":1})');
|
|
23
31
|
});
|
package/src/describe-error.ts
CHANGED
|
@@ -151,9 +151,11 @@ export function humanizeWait<Prefix extends string>(
|
|
|
151
151
|
secs: number,
|
|
152
152
|
prefix: Prefix,
|
|
153
153
|
): string {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return t(`${prefix}
|
|
154
|
+
// Up, never to the nearest: a wait is a floor, and "in 2 hours" for 2h24 sends the reader back
|
|
155
|
+
// early into the same refusal.
|
|
156
|
+
if (secs < 90) return t(`${prefix}waitSeconds`, { count: Math.max(1, Math.ceil(secs)) });
|
|
157
|
+
if (secs < 90 * 60) return t(`${prefix}waitMinutes`, { count: Math.ceil(secs / 60) });
|
|
158
|
+
return t(`${prefix}waitHours`, { count: Math.ceil(secs / 3600) });
|
|
157
159
|
}
|
|
158
160
|
|
|
159
161
|
export interface ErrorContext {
|
package/src/i18n.test.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createInstance } from "i18next";
|
|
2
|
-
import
|
|
2
|
+
import LanguageDetector from "i18next-browser-languagedetector";
|
|
3
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
4
|
import { applyBrandVars, i18nInitOptions, type I18nInitOptions } from "./i18n.ts";
|
|
4
5
|
|
|
5
6
|
describe("applyBrandVars", () => {
|
|
@@ -99,3 +100,37 @@ describe("i18nInitOptions", () => {
|
|
|
99
100
|
expect(i18nInitOptions(base).detection.caches).toEqual(["localStorage"]);
|
|
100
101
|
});
|
|
101
102
|
});
|
|
103
|
+
|
|
104
|
+
/** For a browser listing `languages`, through the real detector: the language the app settles on. */
|
|
105
|
+
async function detect(supportedLngs: string[], languages: string[]): Promise<string> {
|
|
106
|
+
vi.stubGlobal("navigator", { language: languages[0], languages });
|
|
107
|
+
const i18n = createInstance().use(LanguageDetector);
|
|
108
|
+
await i18n.init({
|
|
109
|
+
...i18nInitOptions({ fallbackLng: "en", supportedLngs, storageKey: "app.locale" }),
|
|
110
|
+
resources: Object.fromEntries(supportedLngs.map((tag) => [tag, { translation: { tag } }])),
|
|
111
|
+
});
|
|
112
|
+
return i18n.language;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
describe("language detection", () => {
|
|
116
|
+
afterEach(() => {
|
|
117
|
+
vi.unstubAllGlobals();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// i18next takes the first EXACT match anywhere in the list before it looks at a base subtag, so
|
|
121
|
+
// a reader on [pt-PT, en] got English: "en" is exact, "pt-PT" only matches our pt-BR by its base.
|
|
122
|
+
// Their list is in their order. The locale gate walks it that way, exact tag then base per tag,
|
|
123
|
+
// and the app it redirects into has to agree with it or the reader lands in one language and
|
|
124
|
+
// reads another.
|
|
125
|
+
it("walks the reader's list in their order, exact tag then base per tag", async () => {
|
|
126
|
+
const regionCoded = ["pt-BR", "en", "es"];
|
|
127
|
+
expect(await detect(regionCoded, ["pt-PT", "pt", "en-US", "en"])).toBe("pt-BR");
|
|
128
|
+
expect(await detect(regionCoded, ["en-GB", "pt-BR"])).toBe("en");
|
|
129
|
+
expect(await detect(regionCoded, ["de-DE", "es-AR", "en"])).toBe("es");
|
|
130
|
+
expect(await detect(regionCoded, ["de-DE", "fr"])).toBe("en");
|
|
131
|
+
|
|
132
|
+
const baseCodes = ["pt", "es", "en"];
|
|
133
|
+
expect(await detect(baseCodes, ["pt-BR", "en"])).toBe("pt");
|
|
134
|
+
expect(await detect(baseCodes, ["en-US", "es"])).toBe("en");
|
|
135
|
+
});
|
|
136
|
+
});
|
package/src/i18n.ts
CHANGED
|
@@ -59,6 +59,22 @@ export function i18nInitOptions({
|
|
|
59
59
|
queryKey,
|
|
60
60
|
storageWriter = "detector",
|
|
61
61
|
}: I18nInitOptions) {
|
|
62
|
+
// i18next picks the first EXACT match anywhere in the detected list before it tries a base
|
|
63
|
+
// subtag, so a reader on [pt-PT, en] got English — "en" is exact and "pt-PT" reaches our pt-BR
|
|
64
|
+
// only by its base. Settling each tag on its own, exact then base, leaves only supported tags in
|
|
65
|
+
// the list, in the reader's order. It is the locale gate's rule, written again here rather than
|
|
66
|
+
// imported because `@gusnips/locale` stays a leaf; the two must agree or the gate sends a reader
|
|
67
|
+
// to one language and the app renders another.
|
|
68
|
+
const settle = (tag: string): string => {
|
|
69
|
+
const lower = tag.toLowerCase();
|
|
70
|
+
const base = lower.split("-")[0];
|
|
71
|
+
return (
|
|
72
|
+
supportedLngs.find((lng) => lng.toLowerCase() === lower) ??
|
|
73
|
+
supportedLngs.find((lng) => lng.split("-")[0]?.toLowerCase() === base) ??
|
|
74
|
+
tag
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
62
78
|
return {
|
|
63
79
|
fallbackLng,
|
|
64
80
|
supportedLngs: [...supportedLngs],
|
|
@@ -72,6 +88,7 @@ export function i18nInitOptions({
|
|
|
72
88
|
caches: storageWriter === "detector" ? ["localStorage"] : [],
|
|
73
89
|
...(queryKey ? { lookupQuerystring: queryKey } : {}),
|
|
74
90
|
lookupLocalStorage: storageKey,
|
|
91
|
+
convertDetectedLanguage: settle,
|
|
75
92
|
},
|
|
76
93
|
react: { useSuspense: false },
|
|
77
94
|
// `nonExplicitSupportedLngs` is omitted deliberately. It breaks both shapes a catalog comes in.
|
package/src/query.test.ts
CHANGED
|
@@ -204,6 +204,16 @@ describe("queryView", () => {
|
|
|
204
204
|
unsubscribe();
|
|
205
205
|
});
|
|
206
206
|
|
|
207
|
+
it("reads a missing error as none, not as a failed refresh", () => {
|
|
208
|
+
// A hook that merges two queries can hand over `undefined`; react-query never does.
|
|
209
|
+
expect(queryView({ data: 2, error: undefined })).toStrictEqual({
|
|
210
|
+
state: "ready",
|
|
211
|
+
data: 2,
|
|
212
|
+
refreshError: null,
|
|
213
|
+
});
|
|
214
|
+
expect(queryView({ data: undefined })).toStrictEqual({ state: "waiting" });
|
|
215
|
+
});
|
|
216
|
+
|
|
207
217
|
it("treats null as an answer, not as waiting", () => {
|
|
208
218
|
expect(queryView({ data: null, error: null })).toEqual({
|
|
209
219
|
state: "ready",
|
package/src/query.ts
CHANGED
|
@@ -156,6 +156,9 @@ export function queryDefaults({
|
|
|
156
156
|
* an error beside data IS `isRefetchError`, and an error without data IS `isLoadingError`. It
|
|
157
157
|
* takes any query result, infinite ones included, and a test passes a plain object.
|
|
158
158
|
*
|
|
159
|
+
* A missing `error` counts as none. react-query always sends `null`, but a hook that merges two
|
|
160
|
+
* queries can send `undefined`, and a screen must not report a failed refresh for that.
|
|
161
|
+
*
|
|
159
162
|
* Which control to offer is not decided here. Hand the error to the describer: its `recover` comes
|
|
160
163
|
* from the same rule the query client retries by, so the button and the retry cannot disagree.
|
|
161
164
|
*/
|
|
@@ -166,9 +169,10 @@ export type QueryView<T, E = unknown> =
|
|
|
166
169
|
|
|
167
170
|
export function queryView<T, E>(query: {
|
|
168
171
|
readonly data: T | undefined;
|
|
169
|
-
readonly error
|
|
172
|
+
readonly error?: E | null;
|
|
170
173
|
}): QueryView<T, E> {
|
|
171
|
-
const { data
|
|
174
|
+
const { data } = query;
|
|
175
|
+
const error = query.error ?? null;
|
|
172
176
|
if (data !== undefined) return { state: "ready", data, refreshError: error };
|
|
173
177
|
if (error !== null) return { state: "failed", error };
|
|
174
178
|
return { state: "waiting" };
|