hazo_core 1.2.0 → 1.3.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 +8 -0
- package/dist/errors/base.js +17 -3
- package/dist/errors/base.js.map +1 -1
- package/dist/http/list_params.d.ts +30 -0
- package/dist/http/list_params.d.ts.map +1 -0
- package/dist/http/list_params.js +53 -0
- package/dist/http/list_params.js.map +1 -0
- package/dist/index.client.d.ts +3 -2
- package/dist/index.client.d.ts.map +1 -1
- package/dist/index.client.js +2 -1
- package/dist/index.client.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/singleton/index.d.ts +10 -1
- package/dist/singleton/index.d.ts.map +1 -1
- package/dist/singleton/index.js +9 -2
- package/dist/singleton/index.js.map +1 -1
- package/dist/utils/debounced_saver.d.ts +52 -0
- package/dist/utils/debounced_saver.d.ts.map +1 -0
- package/dist/utils/debounced_saver.js +80 -0
- package/dist/utils/debounced_saver.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +12 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/retry.d.ts +34 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +56 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/uuid.d.ts +9 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +22 -0
- package/dist/utils/uuid.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -66,6 +66,14 @@ import { loadConfig, defineConfig, createLogger, createDebug,
|
|
|
66
66
|
fetchWithRequestId, createRequestIdMiddleware, REQUEST_ID_HEADER } from 'hazo_core';
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
+
### Utilities
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { withRetry, isUuid, parseListLimit, parseListOffset,
|
|
73
|
+
createDebouncedSaver } from 'hazo_core';
|
|
74
|
+
// all five are env-agnostic and also available from 'hazo_core/client'
|
|
75
|
+
```
|
|
76
|
+
|
|
69
77
|
### Browser-safe subset
|
|
70
78
|
|
|
71
79
|
```ts
|
package/dist/errors/base.js
CHANGED
|
@@ -147,7 +147,21 @@ export class HazoError extends Error {
|
|
|
147
147
|
value[HAZO_ERROR_SYMBOL] === true);
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
-
//
|
|
151
|
-
//
|
|
152
|
-
|
|
150
|
+
// Tag the class itself with the shared (Symbol.for) marker. Because the symbol is
|
|
151
|
+
// resolved via Symbol.for it is identical across every hazo_core evaluation, so two
|
|
152
|
+
// HazoError classes produced by separate evaluations — duplicate installed copies, or
|
|
153
|
+
// the server and client entry points loaded into one realm by a bundler (Turbopack in
|
|
154
|
+
// dev) — both carry it and can be recognised as interchangeable.
|
|
155
|
+
HazoError[HAZO_ERROR_SYMBOL] = true;
|
|
156
|
+
// Register once at module load — never again, so no repeated console.warn on each error
|
|
157
|
+
// instance. Two distinct-but-equivalent HazoError classes are a benign collision (the
|
|
158
|
+
// symbol marker makes HazoError.is() work across them regardless of which wins), so the
|
|
159
|
+
// `equivalent` predicate keeps the original silently instead of logging a spurious
|
|
160
|
+
// "already registered with a different value" warning.
|
|
161
|
+
registerSingleton('hazo_core:error_class', HazoError, {
|
|
162
|
+
equivalent: (a, b) => typeof a === 'function' &&
|
|
163
|
+
typeof b === 'function' &&
|
|
164
|
+
a[HAZO_ERROR_SYMBOL] === true &&
|
|
165
|
+
b[HAZO_ERROR_SYMBOL] === true,
|
|
166
|
+
});
|
|
153
167
|
//# sourceMappingURL=base.js.map
|
package/dist/errors/base.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/errors/base.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/errors/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a limit query-string param.
|
|
3
|
+
*
|
|
4
|
+
* @param raw The raw string from `searchParams.get('limit')` (may be null).
|
|
5
|
+
* @param opts `default` — value used when raw is absent/invalid.
|
|
6
|
+
* `max` — upper clamp applied after parsing.
|
|
7
|
+
* @returns An integer in [1, max].
|
|
8
|
+
* @example parseListLimit('50', { default: 20, max: 100 }) // 50
|
|
9
|
+
* @example parseListLimit(null, { default: 20, max: 100 }) // 20
|
|
10
|
+
* @example parseListLimit('abc', { default: 20, max: 100 }) // 20
|
|
11
|
+
* @example parseListLimit('9999', { default: 20, max: 100 }) // 100
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseListLimit(raw: string | null, opts: {
|
|
14
|
+
default: number;
|
|
15
|
+
max: number;
|
|
16
|
+
}): number;
|
|
17
|
+
/**
|
|
18
|
+
* Parse an offset query-string param.
|
|
19
|
+
*
|
|
20
|
+
* @param raw The raw string from `searchParams.get('offset')` (may be null).
|
|
21
|
+
* @param opts Optional `default` — value used when raw is absent/invalid (default 0).
|
|
22
|
+
* @returns An integer >= 0.
|
|
23
|
+
* @example parseListOffset('40', {}) // 40
|
|
24
|
+
* @example parseListOffset(null, {}) // 0
|
|
25
|
+
* @example parseListOffset('-5', {}) // 0
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseListOffset(raw: string | null, opts?: {
|
|
28
|
+
default?: number;
|
|
29
|
+
}): number;
|
|
30
|
+
//# sourceMappingURL=list_params.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_params.d.ts","sourceRoot":"","sources":["../../src/http/list_params.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACrC,MAAM,CAMR;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1B,MAAM,CAMR"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// file_description: Safe pagination parameter parsers for list API routes.
|
|
2
|
+
//
|
|
3
|
+
// `parseInt` without a radix is not safe — callers may pass garbage or omit the
|
|
4
|
+
// param entirely, which causes parseInt to return NaN. Math.min/max propagate NaN
|
|
5
|
+
// silently, resulting in e.g. `limit=NaN` being sent downstream (PostgREST, an ORM,
|
|
6
|
+
// etc). These helpers use `parseInt(raw, 10)` with an explicit radix, check for
|
|
7
|
+
// non-finite/negative results, and fall back to caller-supplied defaults.
|
|
8
|
+
//
|
|
9
|
+
// Promoted from taxclientdocs' lib/api/list-params.ts into hazo_core — pure string
|
|
10
|
+
// parsing with no app- or framework-specific behaviour. Browser-safe (no Node
|
|
11
|
+
// deps), so also exported from the client entry point.
|
|
12
|
+
/**
|
|
13
|
+
* Parse a limit query-string param.
|
|
14
|
+
*
|
|
15
|
+
* @param raw The raw string from `searchParams.get('limit')` (may be null).
|
|
16
|
+
* @param opts `default` — value used when raw is absent/invalid.
|
|
17
|
+
* `max` — upper clamp applied after parsing.
|
|
18
|
+
* @returns An integer in [1, max].
|
|
19
|
+
* @example parseListLimit('50', { default: 20, max: 100 }) // 50
|
|
20
|
+
* @example parseListLimit(null, { default: 20, max: 100 }) // 20
|
|
21
|
+
* @example parseListLimit('abc', { default: 20, max: 100 }) // 20
|
|
22
|
+
* @example parseListLimit('9999', { default: 20, max: 100 }) // 100
|
|
23
|
+
*/
|
|
24
|
+
export function parseListLimit(raw, opts) {
|
|
25
|
+
if (raw === null || raw === '')
|
|
26
|
+
return opts.default;
|
|
27
|
+
const parsed = parseInt(raw, 10);
|
|
28
|
+
if (!isFinite(parsed))
|
|
29
|
+
return opts.default;
|
|
30
|
+
if (parsed < 1)
|
|
31
|
+
return 1;
|
|
32
|
+
return Math.min(parsed, opts.max);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Parse an offset query-string param.
|
|
36
|
+
*
|
|
37
|
+
* @param raw The raw string from `searchParams.get('offset')` (may be null).
|
|
38
|
+
* @param opts Optional `default` — value used when raw is absent/invalid (default 0).
|
|
39
|
+
* @returns An integer >= 0.
|
|
40
|
+
* @example parseListOffset('40', {}) // 40
|
|
41
|
+
* @example parseListOffset(null, {}) // 0
|
|
42
|
+
* @example parseListOffset('-5', {}) // 0
|
|
43
|
+
*/
|
|
44
|
+
export function parseListOffset(raw, opts) {
|
|
45
|
+
const fallback = opts?.default ?? 0;
|
|
46
|
+
if (raw === null || raw === '')
|
|
47
|
+
return fallback;
|
|
48
|
+
const parsed = parseInt(raw, 10);
|
|
49
|
+
if (!isFinite(parsed) || parsed < 0)
|
|
50
|
+
return fallback;
|
|
51
|
+
return parsed;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=list_params.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_params.js","sourceRoot":"","sources":["../../src/http/list_params.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,gFAAgF;AAChF,kFAAkF;AAClF,oFAAoF;AACpF,gFAAgF;AAChF,0EAA0E;AAC1E,EAAE;AACF,mFAAmF;AACnF,8EAA8E;AAC9E,uDAAuD;AAEvD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAkB,EAClB,IAAsC;IAEtC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC;IACpD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACjC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC;IAC3C,IAAI,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACzB,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,GAAkB,EAClB,IAA2B;IAE3B,MAAM,QAAQ,GAAG,IAAI,EAAE,OAAO,IAAI,CAAC,CAAC;IACpC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,QAAQ,CAAC;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACjC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IACrD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/index.client.d.ts
CHANGED
|
@@ -12,10 +12,11 @@ export { HazoError, HazoValidationError, HazoAuthError, HazoNotFoundError, HazoC
|
|
|
12
12
|
export type { HazoErrorOptions, HazoValidationErrorOptions, ValidationIssue, HazoAuthErrorOptions, HazoNotFoundErrorOptions, HazoConflictErrorOptions, HazoConfigErrorOptions, HazoExternalErrorOptions, HazoRateLimitErrorOptions, HazoUnavailableErrorOptions, HazoInternalErrorOptions, } from './errors/index.js';
|
|
13
13
|
export { setBrowserCorrelationId, getContext, getCorrelationId, withContext, } from './context/client.js';
|
|
14
14
|
export type { HazoContext } from './context/types.js';
|
|
15
|
-
export { generateRequestId, generateId, optional_import, safeJsonParse, sleep, formatBytes, formatDateShort, formatDateLong, formatDateSlash, formatCurrency, formatNumber, formatBoolean, getInitials, format_date, format_date_range, DEFAULT_DATE_FORMAT, getCurrentEnv, } from './utils/index.js';
|
|
16
|
-
export type { DateFormat } from './utils/index.js';
|
|
15
|
+
export { generateRequestId, generateId, optional_import, safeJsonParse, sleep, formatBytes, formatDateShort, formatDateLong, formatDateSlash, formatCurrency, formatNumber, formatBoolean, getInitials, format_date, format_date_range, DEFAULT_DATE_FORMAT, getCurrentEnv, withRetry, isUuid, createDebouncedSaver, } from './utils/index.js';
|
|
16
|
+
export type { DateFormat, RetryOptions, DebouncedSaveContext, CreateDebouncedSaverOptions, DebouncedSaver, } from './utils/index.js';
|
|
17
17
|
export { fetchWithRequestId } from './http/fetch_with_request_id.client.js';
|
|
18
18
|
export { get_origin_url, create_redirect_url } from './http/get_origin_url.js';
|
|
19
|
+
export { parseListLimit, parseListOffset } from './http/list_params.js';
|
|
19
20
|
export { createLogger } from './logger/index.client.js';
|
|
20
21
|
export type { HazoCoreLogger } from './logger/index.js';
|
|
21
22
|
//# sourceMappingURL=index.client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../src/index.client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG3F,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGvE,OAAO,EACL,SAAS,EACT,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EACzB,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,aAAa,EACb,KAAK,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,
|
|
1
|
+
{"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../src/index.client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG3F,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGvE,OAAO,EACL,SAAS,EACT,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EACzB,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,aAAa,EACb,KAAK,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,MAAM,EACN,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,UAAU,EACV,YAAY,EACZ,oBAAoB,EACpB,2BAA2B,EAC3B,cAAc,GACf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIxE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.client.js
CHANGED
|
@@ -15,10 +15,11 @@ export { HazoError, HazoValidationError, HazoAuthError, HazoNotFoundError, HazoC
|
|
|
15
15
|
// Context (browser — mutable ref, NOT AsyncLocalStorage)
|
|
16
16
|
export { setBrowserCorrelationId, getContext, getCorrelationId, withContext, } from './context/client.js';
|
|
17
17
|
// Safe utils (no Node deps)
|
|
18
|
-
export { generateRequestId, generateId, optional_import, safeJsonParse, sleep, formatBytes, formatDateShort, formatDateLong, formatDateSlash, formatCurrency, formatNumber, formatBoolean, getInitials, format_date, format_date_range, DEFAULT_DATE_FORMAT, getCurrentEnv, } from './utils/index.js';
|
|
18
|
+
export { generateRequestId, generateId, optional_import, safeJsonParse, sleep, formatBytes, formatDateShort, formatDateLong, formatDateSlash, formatCurrency, formatNumber, formatBoolean, getInitials, format_date, format_date_range, DEFAULT_DATE_FORMAT, getCurrentEnv, withRetry, isUuid, createDebouncedSaver, } from './utils/index.js';
|
|
19
19
|
// HTTP — browser-safe variants (Fetch API, no AsyncLocalStorage)
|
|
20
20
|
export { fetchWithRequestId } from './http/fetch_with_request_id.client.js';
|
|
21
21
|
export { get_origin_url, create_redirect_url } from './http/get_origin_url.js';
|
|
22
|
+
export { parseListLimit, parseListOffset } from './http/list_params.js';
|
|
22
23
|
// Logger — client-side stub emits to the browser console (server version
|
|
23
24
|
// requires node:module + process.stderr, neither available in browsers/edge)
|
|
24
25
|
export { createLogger } from './logger/index.client.js';
|
package/dist/index.client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.client.js","sourceRoot":"","sources":["../src/index.client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,2BAA2B;AAC3B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE3F,sDAAsD;AACtD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEvE,4DAA4D;AAC5D,OAAO,EACL,SAAS,EACT,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAe3B,yDAAyD;AACzD,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAG7B,4BAA4B;AAC5B,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,aAAa,EACb,KAAK,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,
|
|
1
|
+
{"version":3,"file":"index.client.js","sourceRoot":"","sources":["../src/index.client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,2BAA2B;AAC3B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE3F,sDAAsD;AACtD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEvE,4DAA4D;AAC5D,OAAO,EACL,SAAS,EACT,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAe3B,yDAAyD;AACzD,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAG7B,4BAA4B;AAC5B,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,aAAa,EACb,KAAK,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,MAAM,EACN,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAS1B,iEAAiE;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExE,yEAAyE;AACzE,6EAA6E;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { REQUEST_ID_HEADER, HAZO_ERROR_SYMBOL, HAZO_SINGLETONS_KEY } from './constants.js';
|
|
8
8
|
export { registerSingleton, getSingleton, globalSingleton, resetGlobalSingleton } from './singleton/index.js';
|
|
9
|
-
export { getCurrentEnv, generateRequestId, generateId, optional_import, safeJsonParse, sleep, formatBytes, formatDateShort, formatDateLong, formatDateSlash, formatCurrency, formatNumber, formatBoolean, getInitials, format_date, format_date_range, DEFAULT_DATE_FORMAT, } from './utils/index.js';
|
|
10
|
-
export type { DateFormat } from './utils/index.js';
|
|
9
|
+
export { getCurrentEnv, generateRequestId, generateId, optional_import, safeJsonParse, sleep, formatBytes, formatDateShort, formatDateLong, formatDateSlash, formatCurrency, formatNumber, formatBoolean, getInitials, format_date, format_date_range, DEFAULT_DATE_FORMAT, withRetry, isUuid, createDebouncedSaver, } from './utils/index.js';
|
|
10
|
+
export type { DateFormat, RetryOptions, DebouncedSaveContext, CreateDebouncedSaverOptions, DebouncedSaver, } from './utils/index.js';
|
|
11
11
|
export { HazoError, HazoValidationError, HazoAuthError, HazoNotFoundError, HazoConflictError, HazoConfigError, HazoExternalError, HazoRateLimitError, HazoUnavailableError, HazoInternalError, fromZodValidation, fromZodConfig, } from './errors/index.js';
|
|
12
12
|
export type { HazoErrorOptions, HazoValidationErrorOptions, ValidationIssue, HazoAuthErrorOptions, HazoNotFoundErrorOptions, HazoConflictErrorOptions, HazoConfigErrorOptions, HazoExternalErrorOptions, HazoRateLimitErrorOptions, HazoUnavailableErrorOptions, HazoInternalErrorOptions, } from './errors/index.js';
|
|
13
13
|
export { withContext, getContext, getCorrelationId, } from './context/index.js';
|
|
@@ -21,4 +21,5 @@ export type { HazoCoreDebug } from './debug/index.js';
|
|
|
21
21
|
export { createRequestIdMiddleware, withRequestIdRouteHandler, } from './http/request_id_middleware.js';
|
|
22
22
|
export { fetchWithRequestId } from './http/fetch_with_request_id.js';
|
|
23
23
|
export { get_origin_url, create_redirect_url } from './http/get_origin_url.js';
|
|
24
|
+
export { parseListLimit, parseListOffset } from './http/list_params.js';
|
|
24
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG3F,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG9G,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,aAAa,EACb,KAAK,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG3F,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG9G,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,aAAa,EACb,KAAK,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,MAAM,EACN,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,UAAU,EACV,YAAY,EACZ,oBAAoB,EACpB,2BAA2B,EAC3B,cAAc,GACf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,SAAS,EACT,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EACzB,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,WAAW,EACX,UAAU,EACV,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACjH,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD,OAAO,EACL,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ export { REQUEST_ID_HEADER, HAZO_ERROR_SYMBOL, HAZO_SINGLETONS_KEY } from './con
|
|
|
9
9
|
// Singleton registry
|
|
10
10
|
export { registerSingleton, getSingleton, globalSingleton, resetGlobalSingleton } from './singleton/index.js';
|
|
11
11
|
// Utilities
|
|
12
|
-
export { getCurrentEnv, generateRequestId, generateId, optional_import, safeJsonParse, sleep, formatBytes, formatDateShort, formatDateLong, formatDateSlash, formatCurrency, formatNumber, formatBoolean, getInitials, format_date, format_date_range, DEFAULT_DATE_FORMAT, } from './utils/index.js';
|
|
12
|
+
export { getCurrentEnv, generateRequestId, generateId, optional_import, safeJsonParse, sleep, formatBytes, formatDateShort, formatDateLong, formatDateSlash, formatCurrency, formatNumber, formatBoolean, getInitials, format_date, format_date_range, DEFAULT_DATE_FORMAT, withRetry, isUuid, createDebouncedSaver, } from './utils/index.js';
|
|
13
13
|
// Errors
|
|
14
14
|
export { HazoError, HazoValidationError, HazoAuthError, HazoNotFoundError, HazoConflictError, HazoConfigError, HazoExternalError, HazoRateLimitError, HazoUnavailableError, HazoInternalError, fromZodValidation, fromZodConfig, } from './errors/index.js';
|
|
15
15
|
// Context (server — AsyncLocalStorage)
|
|
@@ -24,4 +24,5 @@ export { createDebug } from './debug/index.js';
|
|
|
24
24
|
export { createRequestIdMiddleware, withRequestIdRouteHandler, } from './http/request_id_middleware.js';
|
|
25
25
|
export { fetchWithRequestId } from './http/fetch_with_request_id.js';
|
|
26
26
|
export { get_origin_url, create_redirect_url } from './http/get_origin_url.js';
|
|
27
|
+
export { parseListLimit, parseListOffset } from './http/list_params.js';
|
|
27
28
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY;AACZ,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE3F,qBAAqB;AACrB,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE9G,YAAY;AACZ,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,aAAa,EACb,KAAK,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY;AACZ,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE3F,qBAAqB;AACrB,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE9G,YAAY;AACZ,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,aAAa,EACb,KAAK,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,MAAM,EACN,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAS1B,SAAS;AACT,OAAO,EACL,SAAS,EACT,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAe3B,uCAAuC;AACvC,OAAO,EACL,WAAW,EACX,UAAU,EACV,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAG5B,SAAS;AACT,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGjH,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,QAAQ;AACR,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO;AACP,OAAO,EACL,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -8,9 +8,18 @@
|
|
|
8
8
|
* silent. A genuine collision — a *different* value under an existing key — is warned
|
|
9
9
|
* about once per key, so it can never flood the logs.
|
|
10
10
|
*
|
|
11
|
+
* Some singletons are produced fresh by each module evaluation yet are *semantically*
|
|
12
|
+
* the same — e.g. the `HazoError` class, which is redefined when a bundler loads the
|
|
13
|
+
* server and client entry points into one realm, or when two copies of the package
|
|
14
|
+
* are installed. These differ by reference but are interchangeable. Pass
|
|
15
|
+
* `options.equivalent` to recognise that case: when it returns `true` for the existing
|
|
16
|
+
* and incoming values the original is kept silently, with no warning.
|
|
17
|
+
*
|
|
11
18
|
* @returns The registered value (either the new one or the pre-existing one)
|
|
12
19
|
*/
|
|
13
|
-
export declare function registerSingleton<T>(key: string, value: T
|
|
20
|
+
export declare function registerSingleton<T>(key: string, value: T, options?: {
|
|
21
|
+
equivalent?: (existing: unknown, value: T) => boolean;
|
|
22
|
+
}): T;
|
|
14
23
|
/**
|
|
15
24
|
* Retrieve a previously registered singleton value by key.
|
|
16
25
|
* Returns undefined if the key has never been registered.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/singleton/index.ts"],"names":[],"mappings":"AA4BA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/singleton/index.ts"],"names":[],"mappings":"AA4BA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAA;CAAE,GAClE,CAAC,CAiBH;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAM1D;AAED,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/singleton/index.js
CHANGED
|
@@ -32,13 +32,20 @@ function getWarnedKeys() {
|
|
|
32
32
|
* silent. A genuine collision — a *different* value under an existing key — is warned
|
|
33
33
|
* about once per key, so it can never flood the logs.
|
|
34
34
|
*
|
|
35
|
+
* Some singletons are produced fresh by each module evaluation yet are *semantically*
|
|
36
|
+
* the same — e.g. the `HazoError` class, which is redefined when a bundler loads the
|
|
37
|
+
* server and client entry points into one realm, or when two copies of the package
|
|
38
|
+
* are installed. These differ by reference but are interchangeable. Pass
|
|
39
|
+
* `options.equivalent` to recognise that case: when it returns `true` for the existing
|
|
40
|
+
* and incoming values the original is kept silently, with no warning.
|
|
41
|
+
*
|
|
35
42
|
* @returns The registered value (either the new one or the pre-existing one)
|
|
36
43
|
*/
|
|
37
|
-
export function registerSingleton(key, value) {
|
|
44
|
+
export function registerSingleton(key, value, options) {
|
|
38
45
|
const registry = getRegistry();
|
|
39
46
|
if (Object.prototype.hasOwnProperty.call(registry, key)) {
|
|
40
47
|
const existing = registry[key];
|
|
41
|
-
if (existing !== value) {
|
|
48
|
+
if (existing !== value && !options?.equivalent?.(existing, value)) {
|
|
42
49
|
const warned = getWarnedKeys();
|
|
43
50
|
if (!warned.has(key)) {
|
|
44
51
|
warned.add(key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/singleton/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAItD;;;GAGG;AACH,SAAS,WAAW;IAClB,MAAM,CAAC,GAAG,UAAqC,CAAC;IAChD,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC5B,CAAC,CAAC,mBAAmB,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAsB,CAAC;IACpE,CAAC;IACD,OAAO,CAAC,CAAC,mBAAmB,CAAsB,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa;IACpB,MAAM,CAAC,GAAG,UAAqC,CAAC;IAChD,MAAM,EAAE,GAAG,GAAG,mBAAmB,SAAS,CAAC;IAC3C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAAE,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,OAAO,CAAC,CAAC,EAAE,CAAgB,CAAC;AAC9B,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/singleton/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAItD;;;GAGG;AACH,SAAS,WAAW;IAClB,MAAM,CAAC,GAAG,UAAqC,CAAC;IAChD,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC5B,CAAC,CAAC,mBAAmB,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAsB,CAAC;IACpE,CAAC;IACD,OAAO,CAAC,CAAC,mBAAmB,CAAsB,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa;IACpB,MAAM,CAAC,GAAG,UAAqC,CAAC;IAChD,MAAM,EAAE,GAAG,GAAG,mBAAmB,SAAS,CAAC;IAC3C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAAE,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,OAAO,CAAC,CAAC,EAAE,CAAgB,CAAC;AAC9B,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAW,EACX,KAAQ,EACR,OAAmE;IAEnE,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;QACxD,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,QAAQ,KAAK,KAAK,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;YAClE,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAChB,OAAO,CAAC,IAAI,CACV,uCAAuC,GAAG,qEAAqE,CAChH,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,QAAa,CAAC;IACvB,CAAC;IACD,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACtB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAI,GAAW;IACzC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;QACxD,OAAO,QAAQ,CAAC,GAAG,CAAM,CAAC;IAC5B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Context passed to the `save` callback describing which path triggered it. */
|
|
2
|
+
export interface DebouncedSaveContext {
|
|
3
|
+
/**
|
|
4
|
+
* True only for the `flush()` path (unmount/navigation). Callers should issue a
|
|
5
|
+
* `keepalive` request in that case so it outlives the page; false for the normal
|
|
6
|
+
* debounced path.
|
|
7
|
+
*/
|
|
8
|
+
keepalive: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** Options for {@link createDebouncedSaver}. */
|
|
11
|
+
export interface CreateDebouncedSaverOptions<T> {
|
|
12
|
+
/** Debounce window in milliseconds. */
|
|
13
|
+
delayMs: number;
|
|
14
|
+
/** Persist the data. Called at most once per queued change. */
|
|
15
|
+
save: (data: T, ctx: DebouncedSaveContext) => void;
|
|
16
|
+
}
|
|
17
|
+
/** Handle returned by {@link createDebouncedSaver}. */
|
|
18
|
+
export interface DebouncedSaver<T> {
|
|
19
|
+
/** Queue `data` to be saved after the debounce delay, replacing any pending save. */
|
|
20
|
+
schedule(data: T): void;
|
|
21
|
+
/** Fire the pending save immediately (keepalive) and cancel the timer. No-op if nothing is pending. */
|
|
22
|
+
flush(): void;
|
|
23
|
+
/** Drop the pending save without firing it. */
|
|
24
|
+
cancel(): void;
|
|
25
|
+
/** True while a save is queued and not yet fired. */
|
|
26
|
+
hasPending(): boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create a debounced saver: `schedule()` queues a save after `delayMs` of
|
|
30
|
+
* inactivity, collapsing rapid successive calls into a single save of the latest
|
|
31
|
+
* data. `flush()` fires any pending save immediately (marked `keepalive: true`) —
|
|
32
|
+
* call it on unmount/navigation instead of just cancelling the timer, so in-flight
|
|
33
|
+
* changes are not lost.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const saver = createDebouncedSaver<FormData>({
|
|
38
|
+
* delayMs: 2000,
|
|
39
|
+
* save: (data, { keepalive }) => fetch('/api/save', {
|
|
40
|
+
* method: 'POST',
|
|
41
|
+
* body: JSON.stringify(data),
|
|
42
|
+
* keepalive,
|
|
43
|
+
* }),
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* saver.schedule(formData); // fires after 2s of inactivity
|
|
47
|
+
* // on unmount:
|
|
48
|
+
* saver.flush(); // fires immediately with keepalive: true
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function createDebouncedSaver<T>(opts: CreateDebouncedSaverOptions<T>): DebouncedSaver<T>;
|
|
52
|
+
//# sourceMappingURL=debounced_saver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debounced_saver.d.ts","sourceRoot":"","sources":["../../src/utils/debounced_saver.ts"],"names":[],"mappings":"AAmBA,gFAAgF;AAChF,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,gDAAgD;AAChD,MAAM,WAAW,2BAA2B,CAAC,CAAC;IAC5C,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,oBAAoB,KAAK,IAAI,CAAC;CACpD;AAED,uDAAuD;AACvD,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,qFAAqF;IACrF,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACxB,uGAAuG;IACvG,KAAK,IAAI,IAAI,CAAC;IACd,+CAA+C;IAC/C,MAAM,IAAI,IAAI,CAAC;IACf,qDAAqD;IACrD,UAAU,IAAI,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,IAAI,EAAE,2BAA2B,CAAC,CAAC,CAAC,GACnC,cAAc,CAAC,CAAC,CAAC,CAyCnB"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// file_description: Framework-agnostic debounced saver with an explicit `flush()`.
|
|
2
|
+
//
|
|
3
|
+
// Built to fix a lost-write bug on a client-survey autosave: the page used a bare
|
|
4
|
+
// debounce timer that was *cancelled* on unmount, so any change made within the
|
|
5
|
+
// debounce window (notably an async result landing shortly before navigation) was
|
|
6
|
+
// silently discarded when the user navigated away.
|
|
7
|
+
//
|
|
8
|
+
// The fix is `flush()`: instead of cancelling the pending timer on unmount, the
|
|
9
|
+
// caller flushes it, firing the queued save immediately. The flush path is flagged
|
|
10
|
+
// `keepalive: true` in the callback context so the caller can issue a `keepalive`
|
|
11
|
+
// fetch that survives page teardown.
|
|
12
|
+
//
|
|
13
|
+
// Pure and IO-free: the actual persistence is the injected `save` callback, so this
|
|
14
|
+
// is unit-testable in a node environment with fake timers (no DOM/fetch required).
|
|
15
|
+
// Uses only `setTimeout`/`clearTimeout`, so it is browser-safe and exported from
|
|
16
|
+
// both the server and client entry points.
|
|
17
|
+
//
|
|
18
|
+
// Promoted from taxclientdocs' lib/debounced-save.ts into hazo_core.
|
|
19
|
+
/**
|
|
20
|
+
* Create a debounced saver: `schedule()` queues a save after `delayMs` of
|
|
21
|
+
* inactivity, collapsing rapid successive calls into a single save of the latest
|
|
22
|
+
* data. `flush()` fires any pending save immediately (marked `keepalive: true`) —
|
|
23
|
+
* call it on unmount/navigation instead of just cancelling the timer, so in-flight
|
|
24
|
+
* changes are not lost.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const saver = createDebouncedSaver<FormData>({
|
|
29
|
+
* delayMs: 2000,
|
|
30
|
+
* save: (data, { keepalive }) => fetch('/api/save', {
|
|
31
|
+
* method: 'POST',
|
|
32
|
+
* body: JSON.stringify(data),
|
|
33
|
+
* keepalive,
|
|
34
|
+
* }),
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* saver.schedule(formData); // fires after 2s of inactivity
|
|
38
|
+
* // on unmount:
|
|
39
|
+
* saver.flush(); // fires immediately with keepalive: true
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export function createDebouncedSaver(opts) {
|
|
43
|
+
const { delayMs, save } = opts;
|
|
44
|
+
let timer = null;
|
|
45
|
+
let pending = null;
|
|
46
|
+
const clearTimer = () => {
|
|
47
|
+
if (timer !== null) {
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
timer = null;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
return {
|
|
53
|
+
schedule(data) {
|
|
54
|
+
pending = { data };
|
|
55
|
+
clearTimer();
|
|
56
|
+
timer = setTimeout(() => {
|
|
57
|
+
timer = null;
|
|
58
|
+
const queued = pending;
|
|
59
|
+
pending = null;
|
|
60
|
+
if (queued)
|
|
61
|
+
save(queued.data, { keepalive: false });
|
|
62
|
+
}, delayMs);
|
|
63
|
+
},
|
|
64
|
+
flush() {
|
|
65
|
+
clearTimer();
|
|
66
|
+
const queued = pending;
|
|
67
|
+
pending = null;
|
|
68
|
+
if (queued)
|
|
69
|
+
save(queued.data, { keepalive: true });
|
|
70
|
+
},
|
|
71
|
+
cancel() {
|
|
72
|
+
clearTimer();
|
|
73
|
+
pending = null;
|
|
74
|
+
},
|
|
75
|
+
hasPending() {
|
|
76
|
+
return pending !== null;
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=debounced_saver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debounced_saver.js","sourceRoot":"","sources":["../../src/utils/debounced_saver.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,EAAE;AACF,kFAAkF;AAClF,gFAAgF;AAChF,kFAAkF;AAClF,mDAAmD;AACnD,EAAE;AACF,gFAAgF;AAChF,mFAAmF;AACnF,kFAAkF;AAClF,qCAAqC;AACrC,EAAE;AACF,oFAAoF;AACpF,mFAAmF;AACnF,iFAAiF;AACjF,2CAA2C;AAC3C,EAAE;AACF,qEAAqE;AAgCrE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAoC;IAEpC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IAE/B,IAAI,KAAK,GAAyC,IAAI,CAAC;IACvD,IAAI,OAAO,GAAuB,IAAI,CAAC;IAEvC,MAAM,UAAU,GAAG,GAAS,EAAE;QAC5B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,QAAQ,CAAC,IAAO;YACd,OAAO,GAAG,EAAE,IAAI,EAAE,CAAC;YACnB,UAAU,EAAE,CAAC;YACb,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBACtB,KAAK,GAAG,IAAI,CAAC;gBACb,MAAM,MAAM,GAAG,OAAO,CAAC;gBACvB,OAAO,GAAG,IAAI,CAAC;gBACf,IAAI,MAAM;oBAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YACtD,CAAC,EAAE,OAAO,CAAC,CAAC;QACd,CAAC;QAED,KAAK;YACH,UAAU,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,OAAO,CAAC;YACvB,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,MAAM;gBAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,MAAM;YACJ,UAAU,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QAED,UAAU;YACR,OAAO,OAAO,KAAK,IAAI,CAAC;QAC1B,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -34,6 +34,11 @@ export declare function sleep(ms: number): Promise<void>;
|
|
|
34
34
|
export declare function formatBytes(bytes: number, decimals?: number): string;
|
|
35
35
|
export { format_date, format_date_range, DEFAULT_DATE_FORMAT, } from './dates.js';
|
|
36
36
|
export type { DateFormat } from './dates.js';
|
|
37
|
+
export { withRetry } from './retry.js';
|
|
38
|
+
export type { RetryOptions } from './retry.js';
|
|
39
|
+
export { isUuid } from './uuid.js';
|
|
40
|
+
export { createDebouncedSaver } from './debounced_saver.js';
|
|
41
|
+
export type { DebouncedSaveContext, CreateDebouncedSaverOptions, DebouncedSaver, } from './debounced_saver.js';
|
|
37
42
|
/**
|
|
38
43
|
* Format a date as "28 May 2026"
|
|
39
44
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAMzC;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAMD;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CASvE;AAMD;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAMjE;AAMD;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAMD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAW/D;AAMD,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAMzC;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAMD;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CASvE;AAMD;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAMjE;AAMD;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAMD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAW/D;AAMD,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM7C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAMnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,YAAY,EACV,oBAAoB,EACpB,2BAA2B,EAC3B,cAAc,GACf,MAAM,sBAAsB,CAAC;AAU9B;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAO3D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAQ1D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAM3D;AAMD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAQ,GAAG,MAAM,CAOvE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAKjE;AAMD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAElD;AAMD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOhD"}
|
package/dist/utils/index.js
CHANGED
|
@@ -88,6 +88,18 @@ export function formatBytes(bytes, decimals = 2) {
|
|
|
88
88
|
// ---------------------------------------------------------------------------
|
|
89
89
|
export { format_date, format_date_range, DEFAULT_DATE_FORMAT, } from './dates.js';
|
|
90
90
|
// ---------------------------------------------------------------------------
|
|
91
|
+
// Retry with backoff
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
export { withRetry } from './retry.js';
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// UUID validation
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
export { isUuid } from './uuid.js';
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// Debounced saver
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
export { createDebouncedSaver } from './debounced_saver.js';
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
91
103
|
// Date formatters
|
|
92
104
|
// ---------------------------------------------------------------------------
|
|
93
105
|
function toDate(date) {
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Options for {@link withRetry}. */
|
|
2
|
+
export interface RetryOptions {
|
|
3
|
+
/** Total number of attempts. Default 3. */
|
|
4
|
+
attempts?: number;
|
|
5
|
+
/** Base backoff delay in ms for the first wait. Default 500. */
|
|
6
|
+
baseDelayMs?: number;
|
|
7
|
+
/** Cap on backoff delay in ms. Default 2000. */
|
|
8
|
+
maxDelayMs?: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Run `fn` up to `attempts` times. Returns the first non-null/non-undefined result.
|
|
12
|
+
*
|
|
13
|
+
* A thrown error OR a null/undefined return is treated as a failed attempt and
|
|
14
|
+
* triggers a retry. Between attempts, waits with exponential backoff:
|
|
15
|
+
* `baseDelayMs`, `baseDelayMs * 2`, … capped at `maxDelayMs`. No wait after the
|
|
16
|
+
* final attempt. If every attempt fails (throws or returns null/undefined),
|
|
17
|
+
* resolves to `null`.
|
|
18
|
+
*
|
|
19
|
+
* @param fn Async function to execute on each attempt.
|
|
20
|
+
* @param opts Retry configuration (attempts, baseDelayMs, maxDelayMs).
|
|
21
|
+
* @param sleep Injectable sleep for tests; defaults to a setTimeout-based sleep.
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const result = await withRetry(
|
|
25
|
+
* () => fetchFlakyThing(),
|
|
26
|
+
* { attempts: 3, baseDelayMs: 500, maxDelayMs: 2000 },
|
|
27
|
+
* );
|
|
28
|
+
* if (result === null) {
|
|
29
|
+
* // every attempt failed
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function withRetry<T>(fn: () => Promise<T | null>, opts?: RetryOptions, sleep?: (ms: number) => Promise<void>): Promise<T | null>;
|
|
34
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAQA,qCAAqC;AACrC,MAAM,WAAW,YAAY;IAC3B,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,EAC3B,IAAI,CAAC,EAAE,YAAY,EACnB,KAAK,GAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAgB,GAClD,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAyBnB"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// file_description: Generic retry-with-exponential-backoff helper for transient,
|
|
2
|
+
// idempotent async calls (LLM calls, flaky external APIs, etc). Pure; no IO beyond
|
|
3
|
+
// the injectable `sleep` function, so it is unit-testable with fake timers.
|
|
4
|
+
//
|
|
5
|
+
// Promoted from taxclientdocs' lib/classification/retry.ts (withClassificationRetry)
|
|
6
|
+
// into hazo_core as a general-purpose helper — the retry/backoff shape has no
|
|
7
|
+
// classification-specific behaviour.
|
|
8
|
+
/** Default real sleep implementation. */
|
|
9
|
+
const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
|
+
/**
|
|
11
|
+
* Run `fn` up to `attempts` times. Returns the first non-null/non-undefined result.
|
|
12
|
+
*
|
|
13
|
+
* A thrown error OR a null/undefined return is treated as a failed attempt and
|
|
14
|
+
* triggers a retry. Between attempts, waits with exponential backoff:
|
|
15
|
+
* `baseDelayMs`, `baseDelayMs * 2`, … capped at `maxDelayMs`. No wait after the
|
|
16
|
+
* final attempt. If every attempt fails (throws or returns null/undefined),
|
|
17
|
+
* resolves to `null`.
|
|
18
|
+
*
|
|
19
|
+
* @param fn Async function to execute on each attempt.
|
|
20
|
+
* @param opts Retry configuration (attempts, baseDelayMs, maxDelayMs).
|
|
21
|
+
* @param sleep Injectable sleep for tests; defaults to a setTimeout-based sleep.
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const result = await withRetry(
|
|
25
|
+
* () => fetchFlakyThing(),
|
|
26
|
+
* { attempts: 3, baseDelayMs: 500, maxDelayMs: 2000 },
|
|
27
|
+
* );
|
|
28
|
+
* if (result === null) {
|
|
29
|
+
* // every attempt failed
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export async function withRetry(fn, opts, sleep = defaultSleep) {
|
|
34
|
+
const attempts = opts?.attempts ?? 3;
|
|
35
|
+
const baseDelayMs = opts?.baseDelayMs ?? 500;
|
|
36
|
+
const maxDelayMs = opts?.maxDelayMs ?? 2000;
|
|
37
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
38
|
+
let result = null;
|
|
39
|
+
try {
|
|
40
|
+
result = await fn();
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Swallow transient errors and treat as a failed attempt.
|
|
44
|
+
}
|
|
45
|
+
if (result != null) {
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
// Wait before the next attempt, but not after the last one.
|
|
49
|
+
if (attempt < attempts) {
|
|
50
|
+
const delay = Math.min(baseDelayMs * Math.pow(2, attempt - 1), maxDelayMs);
|
|
51
|
+
await sleep(delay);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,mFAAmF;AACnF,4EAA4E;AAC5E,EAAE;AACF,qFAAqF;AACrF,8EAA8E;AAC9E,qCAAqC;AAYrC,yCAAyC;AACzC,MAAM,YAAY,GAAG,CAAC,EAAU,EAAiB,EAAE,CACjD,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,EAA2B,EAC3B,IAAmB,EACnB,QAAuC,YAAY;IAEnD,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,CAAC,CAAC;IACrC,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,IAAI,GAAG,CAAC;IAC7C,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,IAAI,CAAC;IAE5C,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC;QACrD,IAAI,MAAM,GAAa,IAAI,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,0DAA0D;QAC5D,CAAC;QAED,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,4DAA4D;QAC5D,IAAI,OAAO,GAAG,QAAQ,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;YAC3E,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True iff `value` is a canonical 8-4-4-4-12 hex UUID (case-insensitive).
|
|
3
|
+
*
|
|
4
|
+
* @param value The candidate string; `null`/`undefined` return `false`.
|
|
5
|
+
* @example isUuid('f47ac10b-58cc-4372-a567-0e02b2c3d479') // true
|
|
6
|
+
* @example isUuid('f_1779965617794_qqz9a') // false
|
|
7
|
+
*/
|
|
8
|
+
export declare function isUuid(value: string | null | undefined): boolean;
|
|
9
|
+
//# sourceMappingURL=uuid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../src/utils/uuid.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEhE"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// file_description: UUID validation for API route parameters.
|
|
2
|
+
//
|
|
3
|
+
// Postgres/PostgREST-backed apps frequently accept a path/query id that must be a
|
|
4
|
+
// UUID before it's safe to send to `id=eq.<value>` — a non-UUID value (e.g. a
|
|
5
|
+
// synthetic client-generated id) causes an opaque "invalid input syntax for type
|
|
6
|
+
// uuid" 400 from PostgREST. Validating up front with `isUuid` lets routes return a
|
|
7
|
+
// clear, actionable error instead.
|
|
8
|
+
//
|
|
9
|
+
// Promoted from taxclientdocs' lib/api/uuid.ts into hazo_core — the check itself
|
|
10
|
+
// has no app-specific behaviour.
|
|
11
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
12
|
+
/**
|
|
13
|
+
* True iff `value` is a canonical 8-4-4-4-12 hex UUID (case-insensitive).
|
|
14
|
+
*
|
|
15
|
+
* @param value The candidate string; `null`/`undefined` return `false`.
|
|
16
|
+
* @example isUuid('f47ac10b-58cc-4372-a567-0e02b2c3d479') // true
|
|
17
|
+
* @example isUuid('f_1779965617794_qqz9a') // false
|
|
18
|
+
*/
|
|
19
|
+
export function isUuid(value) {
|
|
20
|
+
return typeof value === 'string' && UUID_RE.test(value);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=uuid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.js","sourceRoot":"","sources":["../../src/utils/uuid.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,kFAAkF;AAClF,8EAA8E;AAC9E,iFAAiF;AACjF,mFAAmF;AACnF,mCAAmC;AACnC,EAAE;AACF,iFAAiF;AACjF,iCAAiC;AAEjC,MAAM,OAAO,GACX,iEAAiE,CAAC;AAEpE;;;;;;GAMG;AACH,MAAM,UAAU,MAAM,CAAC,KAAgC;IACrD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hazo_core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Foundation package for all hazo_* packages — errors, correlation ID, config, logger, debug, singletons, utils",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"hazo_debug": "^3.1.1",
|
|
73
|
-
"hazo_logs": "^2.
|
|
73
|
+
"hazo_logs": "^2.1.1"
|
|
74
74
|
},
|
|
75
75
|
"peerDependenciesMeta": {
|
|
76
76
|
"hazo_logs": {
|