hanzio 1.2.0 → 2.0.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 +786 -239
- package/dist/api-wrapper/builders.d.ts +4 -3
- package/dist/api-wrapper/create-client.d.ts +1 -1
- package/dist/api-wrapper/describe.d.ts +16 -0
- package/dist/api-wrapper/endpoint.d.ts +18 -0
- package/dist/api-wrapper/errors.d.ts +39 -2
- package/dist/api-wrapper/index.d.ts +5 -0
- package/dist/api-wrapper/otel.d.ts +44 -0
- package/dist/api-wrapper/paginate.d.ts +12 -0
- package/dist/api-wrapper/redaction.d.ts +2 -0
- package/dist/api-wrapper/shared.d.ts +16 -2
- package/dist/api-wrapper/testing.d.ts +23 -0
- package/dist/api-wrapper/transport.d.ts +4 -5
- package/dist/api-wrapper/types.d.ts +103 -18
- package/dist/array/index.d.ts +50 -4
- package/dist/cache/createCache.d.ts +31 -0
- package/dist/cache/index.d.ts +19 -2
- package/dist/color/contrast.d.ts +40 -0
- package/dist/color/index.d.ts +2 -0
- package/dist/{math → color}/metricsSeriesColors.d.ts +14 -7
- package/dist/cool-console-log/index.d.ts +34 -5
- package/dist/crypto/encoding.d.ts +18 -0
- package/dist/crypto/hash.d.ts +33 -0
- package/dist/crypto/index.d.ts +4 -0
- package/dist/crypto/sealer.d.ts +25 -0
- package/dist/crypto/webhook.d.ts +20 -0
- package/dist/date/index.d.ts +46 -2
- package/dist/emitter/index.d.ts +21 -0
- package/dist/error/index.d.ts +12 -0
- package/dist/format/index.d.ts +102 -0
- package/dist/function/index.d.ts +60 -0
- package/dist/guard/index.d.ts +20 -0
- package/dist/i18n/index.d.ts +37 -0
- package/dist/index-0zvtcbzy.js +224 -0
- package/dist/index-181e6vfw.js +29 -0
- package/dist/index-8r2vdzjg.js +87 -0
- package/dist/index-hy7kbb99.js +157 -0
- package/dist/{src/secrets/infisical.js → index-j1ybktbr.js} +500 -538
- package/dist/index-k9yx6bne.js +89 -0
- package/dist/index-kj1phgrx.js +169 -0
- package/dist/index-mnkcfyx8.js +78 -0
- package/dist/{p-queue/index.js → index-pwt0dz63.js} +7 -11
- package/dist/index-rp5pqghz.js +157 -0
- package/dist/index-srt06xd2.js +15 -0
- package/dist/index-wjyb9bsd.js +263 -0
- package/dist/index.d.ts +7 -7
- package/dist/jwt/index.d.ts +50 -2
- package/dist/math/index.d.ts +2 -2
- package/dist/math/linearRegressionTrend.d.ts +14 -1
- package/dist/math/scale.d.ts +8 -0
- package/dist/object/index.d.ts +19 -0
- package/dist/p-queue/index.d.ts +1 -1
- package/dist/promise/index.d.ts +97 -2
- package/dist/sitemap/index.d.ts +48 -6
- package/dist/src/api-wrapper/index.js +60 -1130
- package/dist/src/api-wrapper/testing.js +20 -0
- package/dist/{cool-console-log → src/cool-console-log}/index.js +80 -33
- package/dist/src/crypto/index.js +195 -0
- package/dist/src/format/index.js +211 -0
- package/dist/src/i18n/index.js +36 -0
- package/dist/src/index.js +739 -3145
- package/dist/src/jwt/index.js +138 -92
- package/dist/src/p-queue/index.js +9 -437
- package/dist/src/secrets/index.js +44 -1428
- package/dist/src/secrets/vite.js +6 -39
- package/dist/src/secrets/worker.js +10 -273
- package/dist/src/sitemap/index.js +183 -511
- package/dist/src/storage/index.js +119 -0
- package/dist/src/zod/index.js +340 -167
- package/dist/state/index.d.ts +21 -0
- package/dist/storage/index.d.ts +58 -0
- package/dist/string/index.d.ts +75 -2
- package/dist/typedswitch/index.d.ts +31 -24
- package/dist/types/index.d.ts +11 -0
- package/dist/url/index.d.ts +50 -1
- package/dist/zod/index.d.ts +32 -3
- package/dist/zod/introspect.d.ts +19 -0
- package/dist/zod/jsonToZodSchemaMapper.d.ts +3 -1
- package/dist/zod/zodMinMaxFilter.d.ts +22 -3
- package/dist/zod/zodToTypeString.d.ts +8 -3
- package/package.json +78 -7
- package/src/api-wrapper/actions-impl.ts +11 -72
- package/src/api-wrapper/builders.ts +32 -25
- package/src/api-wrapper/create-client.ts +171 -41
- package/src/api-wrapper/describe.ts +157 -0
- package/src/api-wrapper/endpoint.ts +26 -0
- package/src/api-wrapper/error-reporting.ts +7 -1
- package/src/api-wrapper/errors.ts +107 -2
- package/src/api-wrapper/headers.ts +11 -6
- package/src/api-wrapper/index.ts +5 -0
- package/src/api-wrapper/otel.ts +139 -0
- package/src/api-wrapper/paginate.ts +28 -0
- package/src/api-wrapper/redaction.ts +42 -0
- package/src/api-wrapper/shared.ts +21 -2
- package/src/api-wrapper/testing.ts +48 -0
- package/src/api-wrapper/transport.ts +41 -43
- package/src/api-wrapper/types.ts +185 -18
- package/src/array/index.ts +195 -42
- package/src/cache/createCache.ts +157 -0
- package/src/cache/index.ts +132 -147
- package/src/color/contrast.ts +163 -0
- package/src/color/index.ts +22 -0
- package/src/{math → color}/metricsSeriesColors.ts +47 -49
- package/src/cool-console-log/index.ts +128 -41
- package/src/crypto/encoding.ts +83 -0
- package/src/crypto/hash.ts +170 -0
- package/src/crypto/index.ts +26 -0
- package/src/crypto/sealer.ts +168 -0
- package/src/crypto/webhook.ts +86 -0
- package/src/date/index.ts +109 -34
- package/src/emitter/index.ts +82 -0
- package/src/error/index.ts +63 -0
- package/src/format/index.ts +389 -0
- package/src/function/index.ts +201 -0
- package/src/guard/index.ts +80 -0
- package/src/i18n/index.ts +125 -0
- package/src/index.ts +11 -7
- package/src/jwt/index.ts +199 -125
- package/src/math/index.ts +5 -10
- package/src/math/linearRegressionTrend.ts +33 -8
- package/src/math/scale.ts +17 -0
- package/src/object/index.ts +99 -0
- package/src/p-queue/index.ts +2 -0
- package/src/promise/index.ts +304 -9
- package/src/sitemap/index.ts +293 -130
- package/src/state/index.ts +133 -81
- package/src/storage/index.ts +187 -0
- package/src/string/index.ts +261 -23
- package/src/typedswitch/index.ts +58 -38
- package/src/types/index.ts +14 -0
- package/src/url/index.ts +146 -1
- package/src/zod/index.ts +105 -9
- package/src/zod/introspect.ts +103 -0
- package/src/zod/jsonToZodSchemaMapper.ts +44 -21
- package/src/zod/zodMinMaxFilter.ts +37 -13
- package/src/zod/zodToTypeString.ts +184 -181
- package/dist/api-wrapper/index.js +0 -250
- package/dist/gzip/index.d.ts +0 -2
- package/dist/gzip/index.js +0 -16
- package/dist/index.js +0 -1823
- package/dist/jwt/index.js +0 -19
- package/dist/sitemap/index.js +0 -552
- package/dist/src/gzip/index.js +0 -16
- package/dist/src/secrets/loaders.js +0 -1529
- package/dist/zod/index.js +0 -210
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** The part of the Web `Storage` API (`localStorage`, `sessionStorage`) used here. */
|
|
2
|
+
export interface SyncStorageLike {
|
|
3
|
+
getItem(key: string): string | null;
|
|
4
|
+
setItem(key: string, value: string): void;
|
|
5
|
+
removeItem(key: string): void;
|
|
6
|
+
}
|
|
7
|
+
/** An async key-value store such as React Native's `AsyncStorage`. */
|
|
8
|
+
export interface AsyncStorageLike {
|
|
9
|
+
getItem(key: string): Promise<string | null>;
|
|
10
|
+
setItem(key: string, value: string): Promise<void>;
|
|
11
|
+
removeItem(key: string): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export interface StorageItemOptions<T> {
|
|
14
|
+
key: string;
|
|
15
|
+
/** Returned when nothing is stored or the stored value can't be read. */
|
|
16
|
+
fallback: T;
|
|
17
|
+
/** Validates the deserialized value, e.g. `schema.parse`. Throwing means `fallback`. */
|
|
18
|
+
parse?: (raw: unknown) => T;
|
|
19
|
+
/** Defaults to `JSON.stringify`. */
|
|
20
|
+
serialize?: (value: T) => string;
|
|
21
|
+
/** Defaults to `JSON.parse`. */
|
|
22
|
+
deserialize?: (raw: string) => unknown;
|
|
23
|
+
}
|
|
24
|
+
export interface StorageItem<T> {
|
|
25
|
+
readonly key: string;
|
|
26
|
+
get(): T;
|
|
27
|
+
set(value: T): void;
|
|
28
|
+
remove(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Calls `listener` when another tab changes this key (the `storage` event).
|
|
31
|
+
* A no-op outside browsers. Returns an unsubscribe function.
|
|
32
|
+
*/
|
|
33
|
+
subscribe(listener: (value: T) => void): () => void;
|
|
34
|
+
}
|
|
35
|
+
export interface AsyncStorageItem<T> {
|
|
36
|
+
readonly key: string;
|
|
37
|
+
get(): Promise<T>;
|
|
38
|
+
set(value: T): Promise<void>;
|
|
39
|
+
remove(): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
/** A `Map`-backed `SyncStorageLike`, for tests, SSR, or as a stand-in. */
|
|
42
|
+
export declare function createMemoryStorage(): SyncStorageLike;
|
|
43
|
+
/**
|
|
44
|
+
* A typed value persisted in `localStorage` (or any `SyncStorageLike`). Never
|
|
45
|
+
* throws: missing, corrupt or invalid data reads as `fallback`, and when the
|
|
46
|
+
* storage throws (quota, Safari private mode, sandboxed iframes) the latest
|
|
47
|
+
* value is kept in memory for this item, so reads stay consistent this session.
|
|
48
|
+
*/
|
|
49
|
+
export declare function createStorageItem<T>(options: StorageItemOptions<T> & {
|
|
50
|
+
storage?: SyncStorageLike;
|
|
51
|
+
}): StorageItem<T>;
|
|
52
|
+
/**
|
|
53
|
+
* `createStorageItem` for async stores such as React Native's `AsyncStorage`.
|
|
54
|
+
* Never rejects; same fallback and in-memory mirror behavior.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createAsyncStorageItem<T>(options: StorageItemOptions<T> & {
|
|
57
|
+
storage: AsyncStorageLike;
|
|
58
|
+
}): AsyncStorageItem<T>;
|
package/dist/string/index.d.ts
CHANGED
|
@@ -1,8 +1,81 @@
|
|
|
1
|
+
import type { Result } from '../promise';
|
|
1
2
|
export type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
|
|
2
3
|
export type JsonObject = {
|
|
3
4
|
[key: string]: JsonValue | undefined;
|
|
4
5
|
};
|
|
5
6
|
export type JsonArray = Array<JsonValue | undefined>;
|
|
6
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Parses the first number-like token in a string. Only a `-` directly before
|
|
9
|
+
* the digits is a sign, so `'2024-01-05'` gives `2024`. Whitespace and the
|
|
10
|
+
* separator that isn't `decimalSeparator` are treated as thousands separators:
|
|
11
|
+
* `'1,234.56'` gives `1234.56`, and `'1.234,56'` with `decimalSeparator: ','`
|
|
12
|
+
* gives `1234.56`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractNumber(value: string | null | undefined, options?: {
|
|
15
|
+
decimalSeparator?: '.' | ',';
|
|
16
|
+
}): number | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* A stable, short, non-cryptographic hash key (32-bit, 8 hex chars) for
|
|
19
|
+
* JSON-like input. Object key order and query-string parameter order don't
|
|
20
|
+
* matter. Collisions become likely above ~10k distinct inputs; use `sha256Id`
|
|
21
|
+
* where that matters.
|
|
22
|
+
*/
|
|
7
23
|
export declare function generateId(input: JsonValue | undefined): string;
|
|
8
|
-
|
|
24
|
+
/** Like `generateId`, but a SHA-256 hex digest truncated to `length` chars. */
|
|
25
|
+
export declare function sha256Id(input: JsonValue | undefined, length?: number): Promise<string>;
|
|
26
|
+
export type SlugifyOptions = {
|
|
27
|
+
/** Placed between words (default `'-'`). */
|
|
28
|
+
separator?: string;
|
|
29
|
+
/** Default `true`. */
|
|
30
|
+
lowercase?: boolean;
|
|
31
|
+
/** Cuts the slug to at most this many characters, without a trailing separator. */
|
|
32
|
+
maxLength?: number;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Turns text into a URL slug: strips accents, turns `&` into `and`, splits
|
|
36
|
+
* words on whitespace and `-_/,:;·`, and drops every other non-ASCII-alphanumeric
|
|
37
|
+
* character.
|
|
38
|
+
*/
|
|
39
|
+
export declare function slugify(value: string, options?: SlugifyOptions): string;
|
|
40
|
+
/**
|
|
41
|
+
* JSON.stringify with sorted object keys, so `{ a, b }` and `{ b, a }` produce
|
|
42
|
+
* the same string. Also encodes values JSON drops or rejects: `bigint`,
|
|
43
|
+
* `Map` and `Set`. Use it for cache and dedupe keys.
|
|
44
|
+
*/
|
|
45
|
+
export declare function stableStringify(value: unknown): string;
|
|
46
|
+
/**
|
|
47
|
+
* Cuts text to at most `maxLength` user-visible characters, ellipsis included.
|
|
48
|
+
* Never splits an emoji or accented letter, and drops whitespace before the
|
|
49
|
+
* ellipsis. With `wordBoundary`, cuts at the last space unless that would leave
|
|
50
|
+
* nothing.
|
|
51
|
+
*/
|
|
52
|
+
export declare function truncate(text: string, maxLength: number, options?: {
|
|
53
|
+
ellipsis?: string;
|
|
54
|
+
wordBoundary?: boolean;
|
|
55
|
+
}): string;
|
|
56
|
+
/** Collapses every whitespace run (NBSP and newlines included) to one space and trims. */
|
|
57
|
+
export declare function normalizeWhitespace(text: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Escapes text for literal use in a `RegExp`. `-` becomes `\x2d` so the result
|
|
60
|
+
* is also valid with the `u` and `v` flags.
|
|
61
|
+
*/
|
|
62
|
+
export declare function escapeRegExp(text: string): string;
|
|
63
|
+
/** Lowercases and strips accents, so `'Ærø Café'` becomes `'aero cafe'`. */
|
|
64
|
+
export declare function foldForSearch(text: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* True when every whitespace-separated query term appears in at least one
|
|
67
|
+
* field, ignoring case and accents. An empty query matches everything.
|
|
68
|
+
*/
|
|
69
|
+
export declare function matchesSearch(query: string, ...fields: (string | null | undefined)[]): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Up to `max` (default 2) uppercase letters for an avatar, or `''` when the
|
|
72
|
+
* value has no letters (phone numbers, `'—'`). One word gives its first
|
|
73
|
+
* letters (`'Ada'` → `'AD'`), several give first and last (`'Hans Kristoffer
|
|
74
|
+
* Hansen'` → `'HH'`). An email is read as its local part without the `+tag`:
|
|
75
|
+
* `'ada.lovelace+news@x.com'` → `'AL'`.
|
|
76
|
+
*/
|
|
77
|
+
export declare function initials(name: string | null | undefined, options?: {
|
|
78
|
+
max?: number;
|
|
79
|
+
}): string;
|
|
80
|
+
/** `JSON.parse` that returns a `Result` instead of throwing. */
|
|
81
|
+
export declare function safeJsonParse<T = unknown>(text: string): Result<T, SyntaxError>;
|
|
@@ -81,26 +81,28 @@ export type StringSwitchCases<T extends string, R> = {
|
|
|
81
81
|
export type PartialStringSwitchCases<T extends string, R> = {
|
|
82
82
|
[K in T]?: (value: K) => R | Promise<R>;
|
|
83
83
|
};
|
|
84
|
+
/** Discriminant values supported in object mode. Cases are keyed by `${value}`. */
|
|
85
|
+
type Discriminant = string | number | boolean;
|
|
86
|
+
/** Discriminant values of `V` whose case key (`${value}`) is in `Keys` */
|
|
87
|
+
type ValuesForKeys<V, Keys> = V extends Discriminant ? `${V}` extends `${Keys & (string | number)}` ? V : never : never;
|
|
88
|
+
type ObjectCases<T, K extends keyof T, R> = {
|
|
89
|
+
[V in Extract<T[K], Discriminant> as `${V}`]: (value: Extract<T, Record<K, V>>) => R;
|
|
90
|
+
};
|
|
91
|
+
type PartialObjectCases<T, K extends keyof T, R> = {
|
|
92
|
+
[V in Extract<T[K], Discriminant> as `${V}`]?: (value: Extract<T, Record<K, V>>) => R;
|
|
93
|
+
};
|
|
84
94
|
/** Cases for object input with custom key - all cases required */
|
|
85
|
-
export type ObjectSwitchCases<T, K extends keyof T, R> = T[K] extends
|
|
86
|
-
[V in T[K]]: (value: Extract<T, Record<K, V>>) => R | Promise<R>;
|
|
87
|
-
} : never;
|
|
95
|
+
export type ObjectSwitchCases<T, K extends keyof T, R> = T[K] extends Discriminant ? ObjectCases<T, K, R | Promise<R>> : never;
|
|
88
96
|
/** Partial cases for object input with custom key (when default is provided) */
|
|
89
|
-
export type PartialObjectSwitchCases<T, K extends keyof T, R> = T[K] extends
|
|
90
|
-
[V in T[K]]?: (value: Extract<T, Record<K, V>>) => R | Promise<R>;
|
|
91
|
-
} : never;
|
|
97
|
+
export type PartialObjectSwitchCases<T, K extends keyof T, R> = T[K] extends Discriminant ? PartialObjectCases<T, K, R | Promise<R>> : never;
|
|
92
98
|
export declare function typedSwitch<T extends string, Cases extends {
|
|
93
99
|
[K in T]: (value: K) => unknown;
|
|
94
100
|
}>(value: T, cases: Cases): RawCasesReturnType<Cases>;
|
|
95
101
|
export declare function typedSwitch<T extends string, Cases extends {
|
|
96
102
|
[K in T]?: (value: K) => unknown;
|
|
97
103
|
}, DefaultCase extends (value: Exclude<T, HandledCaseKeys<Cases>>) => unknown>(value: T, cases: Cases, defaultCase: DefaultCase): RawCasesReturnType<Cases> | RawHandlerReturnType<DefaultCase>;
|
|
98
|
-
export declare function typedSwitch<T extends object, K extends keyof T,
|
|
99
|
-
|
|
100
|
-
}>(value: T, key: K, cases: Cases): RawCasesReturnType<Cases>;
|
|
101
|
-
export declare function typedSwitch<T extends object, K extends keyof T, TKey extends T[K] & string, Cases extends {
|
|
102
|
-
[V in TKey]?: (value: Extract<T, Record<K, V>>) => unknown;
|
|
103
|
-
}, DefaultCase extends (value: Exclude<T, Record<K, HandledCaseKeys<Cases> & string>>) => unknown>(value: T, key: K, cases: Cases, defaultCase: DefaultCase): RawCasesReturnType<Cases> | RawHandlerReturnType<DefaultCase>;
|
|
104
|
+
export declare function typedSwitch<T extends object, K extends keyof T, Cases extends ObjectCases<T, K, unknown>>(value: T, key: K, cases: Cases): RawCasesReturnType<Cases>;
|
|
105
|
+
export declare function typedSwitch<T extends object, K extends keyof T, Cases extends PartialObjectCases<T, K, unknown>, DefaultCase extends (value: Exclude<T, Record<K, ValuesForKeys<T[K], HandledCaseKeys<Cases>>>>) => unknown>(value: T, key: K, cases: Cases, defaultCase: DefaultCase): RawCasesReturnType<Cases> | RawHandlerReturnType<DefaultCase>;
|
|
104
106
|
export declare function typedSwitch<Constraint, T extends string = string>(value: T, cases: {
|
|
105
107
|
[K in T]: (value: K) => Constraint;
|
|
106
108
|
}): Constraint;
|
|
@@ -113,16 +115,21 @@ export declare function typedSwitch<Constraint, T extends string = string>(value
|
|
|
113
115
|
export declare function typedSwitch<Constraint, T extends string = string>(value: T, cases: {
|
|
114
116
|
[K in T]?: (value: K) => Constraint | Promise<Constraint>;
|
|
115
117
|
}, defaultCase: (value: T) => Constraint | Promise<Constraint>): Constraint | Promise<Constraint>;
|
|
116
|
-
export declare function typedSwitch<Constraint, T extends Record<string, unknown> = Record<string, unknown>, K extends keyof T = keyof T>(value: T, key: K, cases:
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
export declare function typedSwitch<Constraint, T extends Record<string, unknown> = Record<string, unknown>, K extends keyof T = keyof T>(value: T, key: K, cases:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
118
|
+
export declare function typedSwitch<Constraint, T extends Record<string, unknown> = Record<string, unknown>, K extends keyof T = keyof T>(value: T, key: K, cases: ObjectCases<T, K, Constraint>): Constraint;
|
|
119
|
+
export declare function typedSwitch<Constraint, T extends Record<string, unknown> = Record<string, unknown>, K extends keyof T = keyof T>(value: T, key: K, cases: ObjectCases<T, K, Constraint | Promise<Constraint>>): Constraint | Promise<Constraint>;
|
|
120
|
+
export declare function typedSwitch<Constraint, T extends Record<string, unknown> = Record<string, unknown>, K extends keyof T = keyof T>(value: T, key: K, cases: PartialObjectCases<T, K, Constraint>, defaultCase: (value: T) => Constraint): Constraint;
|
|
121
|
+
export declare function typedSwitch<Constraint, T extends Record<string, unknown> = Record<string, unknown>, K extends keyof T = keyof T>(value: T, key: K, cases: PartialObjectCases<T, K, Constraint | Promise<Constraint>>, defaultCase: (value: T) => Constraint | Promise<Constraint>): Constraint | Promise<Constraint>;
|
|
122
|
+
/**
|
|
123
|
+
* Exhaustiveness helper for regular `switch` statements. Place it in the
|
|
124
|
+
* `default` branch: it only type-checks when every case has been handled, and
|
|
125
|
+
* throws if an unexpected value reaches it at runtime.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* switch (status) {
|
|
129
|
+
* case 'success': return 1
|
|
130
|
+
* case 'error': return 0
|
|
131
|
+
* default: return assertNever(status)
|
|
132
|
+
* }
|
|
133
|
+
*/
|
|
134
|
+
export declare function assertNever(value: never, message?: string): never;
|
|
128
135
|
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type MaybePromise<T> = T | Promise<T>;
|
|
2
|
+
/** Union of an object type's values. */
|
|
3
|
+
export type ValueOf<T> = T[keyof T];
|
|
4
|
+
/** Union of an array or tuple's element types. */
|
|
5
|
+
export type ElementOf<T extends readonly unknown[]> = T[number];
|
|
6
|
+
export type NonEmptyArray<T> = [T, ...T[]];
|
|
7
|
+
/** Flattens intersections into one object type so hovers stay readable. */
|
|
8
|
+
export type Simplify<T> = {
|
|
9
|
+
[K in keyof T]: T[K];
|
|
10
|
+
} & {};
|
|
11
|
+
export type Nullable<T> = T | null | undefined;
|
package/dist/url/index.d.ts
CHANGED
|
@@ -1 +1,50 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type UrlQueryValue = string | number | boolean | null | undefined;
|
|
2
|
+
export type UrlQueryParams = Record<string, UrlQueryValue | readonly UrlQueryValue[]>;
|
|
3
|
+
/**
|
|
4
|
+
* Serializes query params. Arrays repeat the key (`a=1&a=2`); `null` and
|
|
5
|
+
* `undefined` are skipped. Returns the string without a leading `?`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildQueryString(params: UrlQueryParams, options?: {
|
|
8
|
+
encode?: boolean;
|
|
9
|
+
}): string;
|
|
10
|
+
/**
|
|
11
|
+
* Replaces `:name` placeholders with encoded values. Throws when a placeholder
|
|
12
|
+
* has no value. Only `:` followed by a letter or `_` counts, so ports like
|
|
13
|
+
* `:8080` are left alone.
|
|
14
|
+
*/
|
|
15
|
+
export declare function replacePathParams(path: string, params?: Record<string, string | number | boolean | undefined>): string;
|
|
16
|
+
/** Joins base and path with exactly one `/`, fills `:params`, appends query. */
|
|
17
|
+
export declare function buildUrl(base: string, path?: string, options?: {
|
|
18
|
+
params?: Record<string, string | number | boolean | undefined>;
|
|
19
|
+
query?: UrlQueryParams;
|
|
20
|
+
}): string;
|
|
21
|
+
/**
|
|
22
|
+
* Normalizes a domain or URL to its origin: adds `https://` when no scheme is
|
|
23
|
+
* given and strips any path, query or trailing slash.
|
|
24
|
+
*/
|
|
25
|
+
export declare function normalizeDomain(input: string): string;
|
|
26
|
+
/** Accepts a bare domain (`example.com`) or a full URL. */
|
|
27
|
+
export declare function getDomainFaviconUrl(domainOrUrl: string, size?: number): string;
|
|
28
|
+
/** Removes trailing slashes: `'https://x.com/a/'` → `'https://x.com/a'`. */
|
|
29
|
+
export declare function trimTrailingSlash(url: string): string;
|
|
30
|
+
/** Prefixes `/` unless the path already starts with one. */
|
|
31
|
+
export declare function ensureLeadingSlash(path: string): string;
|
|
32
|
+
type MailtoRecipients = string | readonly string[];
|
|
33
|
+
/**
|
|
34
|
+
* Builds a `mailto:` link. Spaces become `%20` (not `+`, which mail clients
|
|
35
|
+
* show literally) and body line breaks become `%0D%0A`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function buildMailto(options: {
|
|
38
|
+
to?: MailtoRecipients;
|
|
39
|
+
cc?: MailtoRecipients;
|
|
40
|
+
bcc?: MailtoRecipients;
|
|
41
|
+
subject?: string;
|
|
42
|
+
body?: string;
|
|
43
|
+
}): string;
|
|
44
|
+
/**
|
|
45
|
+
* Milliseconds to wait from a `Retry-After` header: delta-seconds (fractions
|
|
46
|
+
* allowed) or an HTTP date relative to `now`. Past dates and negative values
|
|
47
|
+
* give `0`; a missing or invalid value gives `undefined`.
|
|
48
|
+
*/
|
|
49
|
+
export declare function parseRetryAfter(value: string | null | undefined, now?: number): number | undefined;
|
|
50
|
+
export {};
|
package/dist/zod/index.d.ts
CHANGED
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { toArray } from '../array';
|
|
3
|
+
import { type Result } from '../promise';
|
|
4
|
+
import type { JsonObject, JsonValue } from '../string';
|
|
5
|
+
export { getEnumValues, getObjectShape, unwrapSchema, zodDefaults } from './introspect';
|
|
2
6
|
export { jsonToZodSchemaMapper } from './jsonToZodSchemaMapper';
|
|
3
|
-
export { toGteLteFilter, type ZodMinMaxFilter, zodMinMaxFilter } from './zodMinMaxFilter';
|
|
7
|
+
export { createMinMaxFilter, type MinMaxFilter, toGteLteFilter, toGtLtFilter, type ZodMinMaxFilter, zodMinMaxFilter } from './zodMinMaxFilter';
|
|
4
8
|
export { zodToExample, zodToTypeString } from './zodToTypeString';
|
|
5
9
|
export type GenericId<TypeName extends string> = string & z.$brand<TypeName>;
|
|
6
|
-
export declare function createZId<TypeName extends string>(typeName: TypeName
|
|
10
|
+
export declare function createZId<TypeName extends string>(typeName: TypeName, { prefix }?: {
|
|
11
|
+
prefix?: string;
|
|
12
|
+
}): PropertyKey extends TypeName ? z.ZodString : z.core.$ZodBranded<z.ZodString, TypeName, "out">;
|
|
13
|
+
/** Branded string id: `Id<'User'>` is not assignable to `Id<'Organization'>`. */
|
|
14
|
+
export type Id<TypeName extends string> = GenericId<TypeName>;
|
|
15
|
+
/** Brands a string without checking it (fixtures, trusted sources). */
|
|
16
|
+
export declare function asId<TypeName extends string>(value: string): Id<TypeName>;
|
|
17
|
+
/** Validates a non-empty string and brands it; throws a `ZodError` otherwise. */
|
|
18
|
+
export declare function parseId<TypeName extends string>(typeName: TypeName, value: unknown): Id<TypeName>;
|
|
19
|
+
export declare function safeParseId<TypeName extends string>(typeName: TypeName, value: unknown): Result<Id<TypeName>, z.ZodError>;
|
|
20
|
+
/**
|
|
21
|
+
* Binds the id helpers to a project's union of entity names once:
|
|
22
|
+
* `export const { zId, asId, parseId, safeParseId } = createIdHelpers<'User' | 'Organization'>()`
|
|
23
|
+
*/
|
|
24
|
+
export declare function createIdHelpers<TypeNames extends string>(): {
|
|
25
|
+
zId: <T extends TypeNames>(typeName: T) => PropertyKey extends T ? z.ZodString : z.core.$ZodBranded<z.ZodString, T, "out">;
|
|
26
|
+
asId: <T extends TypeNames>(value: string) => Id<T>;
|
|
27
|
+
parseId: <T extends TypeNames>(typeName: T, value: unknown) => Id<T>;
|
|
28
|
+
safeParseId: <T extends TypeNames>(typeName: T, value: unknown) => Result<Id<T>, z.ZodError<unknown>>;
|
|
29
|
+
};
|
|
30
|
+
/** Any JSON value (no `undefined`, `NaN` or `Infinity`). */
|
|
31
|
+
export declare const zJsonValue: z.ZodType<JsonValue>;
|
|
32
|
+
export declare const zJsonObject: z.ZodType<JsonObject>;
|
|
33
|
+
/** `JSON.parse` + `schema.safeParse` without throwing. */
|
|
34
|
+
export declare function parseJson<S extends z.ZodType>(text: string, schema: S): Result<z.output<S>, SyntaxError | z.ZodError>;
|
|
7
35
|
export declare function zSingleOrArray<T extends z.ZodType>(schema: T): z.ZodUnion<readonly [z.ZodArray<T>, T]>;
|
|
8
|
-
|
|
36
|
+
/** @deprecated Use `toArray` from `hanzio`. */
|
|
37
|
+
export declare const normalizeSingleOrArray: typeof toArray;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import { type Schema } from './zodToTypeString';
|
|
3
|
+
/**
|
|
4
|
+
* Strips optional/nullable/default/prefault/nonoptional/catch/readonly/lazy
|
|
5
|
+
* wrappers and pipes (input side) until the schema that carries the shape.
|
|
6
|
+
*/
|
|
7
|
+
export declare function unwrapSchema(schema: Schema): Schema;
|
|
8
|
+
/** Values of a (possibly wrapped) `z.enum`, stringified; `undefined` for other schemas. */
|
|
9
|
+
export declare function getEnumValues(schema: Schema): string[] | undefined;
|
|
10
|
+
/** Shape of a (possibly wrapped) `z.object`; `undefined` for other schemas. */
|
|
11
|
+
export declare function getObjectShape(schema: Schema): Readonly<Record<string, Schema>> | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Initial form state for a schema: `.default()` values, `undefined` for
|
|
14
|
+
* optional, `null` for nullable, first enum/literal/union option, `''`, `0`,
|
|
15
|
+
* `false`, `[]`, and objects filled per key. Other types give `undefined`.
|
|
16
|
+
* The result is typed as the schema output but is NOT validated (`''` fails
|
|
17
|
+
* `.min(1)`, dates stay `undefined`).
|
|
18
|
+
*/
|
|
19
|
+
export declare function zodDefaults<S extends Schema>(schema: S): z.output<S>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
type ObjectConfig<V> = V extends Record<string, unknown> ? PropertyConfig<V, Record<string, any>> : never;
|
|
3
|
+
type NestedConfig<V> = V extends readonly (infer E)[] ? ObjectConfig<E> : ObjectConfig<V>;
|
|
2
4
|
type PropertyConfig<T, U> = {
|
|
3
|
-
[K in keyof T]?: (jsonObject: U) => T[K]
|
|
5
|
+
[K in keyof T]?: ((jsonObject: U) => T[K]) | NestedConfig<NonNullable<T[K]>>;
|
|
4
6
|
};
|
|
5
7
|
export declare function jsonToZodSchemaMapper<T extends z.ZodType, U extends Record<string, any>>(jsonObject: U, zodSchema: T, config: PropertyConfig<z.infer<T>, U>): z.infer<T>;
|
|
6
8
|
export {};
|
|
@@ -1,14 +1,33 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a `{ min?, max? }` filter schema for any comparable value schema,
|
|
4
|
+
* e.g. `createMinMaxFilter(z.coerce.date())`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createMinMaxFilter<T extends z.ZodType>(schema: T): z.ZodObject<{
|
|
7
|
+
min: z.ZodOptional<T>;
|
|
8
|
+
max: z.ZodOptional<T>;
|
|
9
|
+
}, z.core.$strip>;
|
|
2
10
|
export declare const zodMinMaxFilter: z.ZodObject<{
|
|
3
11
|
min: z.ZodOptional<z.ZodNumber>;
|
|
4
12
|
max: z.ZodOptional<z.ZodNumber>;
|
|
5
13
|
}, z.core.$strip>;
|
|
6
14
|
export type ZodMinMaxFilter = z.infer<typeof zodMinMaxFilter>;
|
|
15
|
+
export type MinMaxFilter<T> = {
|
|
16
|
+
min?: T;
|
|
17
|
+
max?: T;
|
|
18
|
+
};
|
|
7
19
|
/**
|
|
8
20
|
* Maps a min/max filter to a generic `gte`/`lte` range object (e.g. ORM-friendly).
|
|
9
21
|
* Returns `undefined` if both bounds are undefined.
|
|
10
22
|
*/
|
|
11
|
-
export declare function toGteLteFilter(filter:
|
|
12
|
-
gte?:
|
|
13
|
-
lte?:
|
|
23
|
+
export declare function toGteLteFilter<T>(filter: MinMaxFilter<T> | undefined): {
|
|
24
|
+
gte?: T;
|
|
25
|
+
lte?: T;
|
|
26
|
+
} | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Exclusive variant of `toGteLteFilter`, mapping min/max to `gt`/`lt`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function toGtLtFilter<T>(filter: MinMaxFilter<T> | undefined): {
|
|
31
|
+
gt?: T;
|
|
32
|
+
lt?: T;
|
|
14
33
|
} | undefined;
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import type { z } from 'zod';
|
|
2
|
+
export type Schema = z.core.$ZodType;
|
|
3
|
+
export type Def = z.core.$ZodTypes['_zod']['def'];
|
|
4
|
+
export declare function walk<T>(schema: Schema, onCycle: T, fn: (def: Def) => T): T;
|
|
5
|
+
export declare function defOf(schema: Schema): Def;
|
|
2
6
|
/**
|
|
3
7
|
* Convert a Zod schema to a human-readable TypeScript-like interface string
|
|
4
8
|
*/
|
|
5
|
-
export declare function zodToTypeString(schema:
|
|
9
|
+
export declare function zodToTypeString(schema: Schema, indent?: number): string;
|
|
6
10
|
/**
|
|
7
|
-
* Generate example JSON from a Zod schema
|
|
11
|
+
* Generate example JSON from a Zod schema. Values are JSON-safe: dates become ISO
|
|
12
|
+
* strings, bigints numbers, sets arrays and maps/records empty objects.
|
|
8
13
|
*/
|
|
9
|
-
export declare function zodToExample(schema:
|
|
14
|
+
export declare function zodToExample(schema: Schema): unknown;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hanzio",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A lightweight set of utility functions for TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./dist/src/index.js",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"dist",
|
|
29
29
|
"!src/**/*.test.ts"
|
|
30
30
|
],
|
|
31
|
+
"sideEffects": false,
|
|
31
32
|
"exports": {
|
|
32
33
|
".": {
|
|
33
34
|
"types": "./dist/index.d.ts",
|
|
@@ -35,6 +36,72 @@
|
|
|
35
36
|
"import": "./dist/src/index.js",
|
|
36
37
|
"default": "./dist/src/index.js"
|
|
37
38
|
},
|
|
39
|
+
"./zod": {
|
|
40
|
+
"types": "./dist/zod/index.d.ts",
|
|
41
|
+
"bun": "./src/zod/index.ts",
|
|
42
|
+
"import": "./dist/src/zod/index.js",
|
|
43
|
+
"default": "./dist/src/zod/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./api-wrapper": {
|
|
46
|
+
"types": "./dist/api-wrapper/index.d.ts",
|
|
47
|
+
"bun": "./src/api-wrapper/index.ts",
|
|
48
|
+
"import": "./dist/src/api-wrapper/index.js",
|
|
49
|
+
"default": "./dist/src/api-wrapper/index.js"
|
|
50
|
+
},
|
|
51
|
+
"./api-wrapper/testing": {
|
|
52
|
+
"types": "./dist/api-wrapper/testing.d.ts",
|
|
53
|
+
"bun": "./src/api-wrapper/testing.ts",
|
|
54
|
+
"import": "./dist/src/api-wrapper/testing.js",
|
|
55
|
+
"default": "./dist/src/api-wrapper/testing.js"
|
|
56
|
+
},
|
|
57
|
+
"./jwt": {
|
|
58
|
+
"types": "./dist/jwt/index.d.ts",
|
|
59
|
+
"bun": "./src/jwt/index.ts",
|
|
60
|
+
"import": "./dist/src/jwt/index.js",
|
|
61
|
+
"default": "./dist/src/jwt/index.js"
|
|
62
|
+
},
|
|
63
|
+
"./sitemap": {
|
|
64
|
+
"types": "./dist/sitemap/index.d.ts",
|
|
65
|
+
"bun": "./src/sitemap/index.ts",
|
|
66
|
+
"import": "./dist/src/sitemap/index.js",
|
|
67
|
+
"default": "./dist/src/sitemap/index.js"
|
|
68
|
+
},
|
|
69
|
+
"./p-queue": {
|
|
70
|
+
"types": "./dist/p-queue/index.d.ts",
|
|
71
|
+
"bun": "./src/p-queue/index.ts",
|
|
72
|
+
"import": "./dist/src/p-queue/index.js",
|
|
73
|
+
"default": "./dist/src/p-queue/index.js"
|
|
74
|
+
},
|
|
75
|
+
"./cool-console-log": {
|
|
76
|
+
"types": "./dist/cool-console-log/index.d.ts",
|
|
77
|
+
"bun": "./src/cool-console-log/index.ts",
|
|
78
|
+
"import": "./dist/src/cool-console-log/index.js",
|
|
79
|
+
"default": "./dist/src/cool-console-log/index.js"
|
|
80
|
+
},
|
|
81
|
+
"./format": {
|
|
82
|
+
"types": "./dist/format/index.d.ts",
|
|
83
|
+
"bun": "./src/format/index.ts",
|
|
84
|
+
"import": "./dist/src/format/index.js",
|
|
85
|
+
"default": "./dist/src/format/index.js"
|
|
86
|
+
},
|
|
87
|
+
"./crypto": {
|
|
88
|
+
"types": "./dist/crypto/index.d.ts",
|
|
89
|
+
"bun": "./src/crypto/index.ts",
|
|
90
|
+
"import": "./dist/src/crypto/index.js",
|
|
91
|
+
"default": "./dist/src/crypto/index.js"
|
|
92
|
+
},
|
|
93
|
+
"./storage": {
|
|
94
|
+
"types": "./dist/storage/index.d.ts",
|
|
95
|
+
"bun": "./src/storage/index.ts",
|
|
96
|
+
"import": "./dist/src/storage/index.js",
|
|
97
|
+
"default": "./dist/src/storage/index.js"
|
|
98
|
+
},
|
|
99
|
+
"./i18n": {
|
|
100
|
+
"types": "./dist/i18n/index.d.ts",
|
|
101
|
+
"bun": "./src/i18n/index.ts",
|
|
102
|
+
"import": "./dist/src/i18n/index.js",
|
|
103
|
+
"default": "./dist/src/i18n/index.js"
|
|
104
|
+
},
|
|
38
105
|
"./secrets": {
|
|
39
106
|
"types": "./dist/secrets/index.d.ts",
|
|
40
107
|
"bun": "./src/secrets/index.ts",
|
|
@@ -55,22 +122,21 @@
|
|
|
55
122
|
}
|
|
56
123
|
},
|
|
57
124
|
"scripts": {
|
|
58
|
-
"build": "bun run build:js && bun run build:types",
|
|
59
|
-
"build:js": "bun build ./src/index.ts ./src/zod/index.ts ./src/api-wrapper/index.ts ./src/jwt/index.ts ./src/sitemap/index.ts ./src/p-queue/index.ts ./src/
|
|
125
|
+
"build": "rm -rf dist && bun run build:js && bun run build:types",
|
|
126
|
+
"build:js": "bun build ./src/index.ts ./src/zod/index.ts ./src/api-wrapper/index.ts ./src/api-wrapper/testing.ts ./src/jwt/index.ts ./src/sitemap/index.ts ./src/p-queue/index.ts ./src/cool-console-log/index.ts ./src/format/index.ts ./src/crypto/index.ts ./src/storage/index.ts ./src/i18n/index.ts ./src/secrets/index.ts ./src/secrets/vite.ts ./src/secrets/worker.ts --outdir ./dist --target node --packages external --splitting",
|
|
60
127
|
"build:types": "tsgo -p tsconfig.build.json",
|
|
61
128
|
"prepublishOnly": "bun run build",
|
|
62
|
-
"publish:patch": "npm version patch && npm publish",
|
|
63
|
-
"publish:minor": "npm version minor && npm publish",
|
|
64
|
-
"publish:major": "npm version major && npm publish",
|
|
65
129
|
"test": "bun test",
|
|
66
130
|
"lint": "bun run typecheck && bun biome check",
|
|
67
131
|
"lint:write": "bun run typecheck && bun biome check --write",
|
|
68
132
|
"typecheck": "tsgo --noEmit",
|
|
69
133
|
"prepare": "husky",
|
|
70
|
-
"test:secrets:runtime": "bun run build && node scripts/verify-secrets.mjs"
|
|
134
|
+
"test:secrets:runtime": "bun run build && node scripts/verify-secrets.mjs",
|
|
135
|
+
"test:exports": "bun run build && node scripts/verify-exports.mjs"
|
|
71
136
|
},
|
|
72
137
|
"devDependencies": {
|
|
73
138
|
"@biomejs/biome": "^2.4.6",
|
|
139
|
+
"@opentelemetry/api": "^1.9.1",
|
|
74
140
|
"@types/bun": "latest",
|
|
75
141
|
"@typescript/native-preview": "^7.0.0-dev.20260306.1",
|
|
76
142
|
"husky": "^9.1.7",
|
|
@@ -81,5 +147,10 @@
|
|
|
81
147
|
},
|
|
82
148
|
"peerDependencies": {
|
|
83
149
|
"zod": "^4.3.6"
|
|
150
|
+
},
|
|
151
|
+
"peerDependenciesMeta": {
|
|
152
|
+
"zod": {
|
|
153
|
+
"optional": true
|
|
154
|
+
}
|
|
84
155
|
}
|
|
85
156
|
}
|
|
@@ -1,80 +1,18 @@
|
|
|
1
|
+
import { createCache } from '../cache/createCache'
|
|
1
2
|
import type { ActionCache, DefineAction } from './types'
|
|
2
3
|
|
|
3
|
-
type CacheEntry = {
|
|
4
|
-
value?: unknown
|
|
5
|
-
hasValue: boolean
|
|
6
|
-
expiresAt?: number
|
|
7
|
-
inflight?: Promise<unknown>
|
|
8
|
-
}
|
|
9
|
-
|
|
10
4
|
export function createActionCache(): ActionCache {
|
|
11
|
-
const store =
|
|
12
|
-
|
|
13
|
-
const isExpired = (entry: CacheEntry) =>
|
|
14
|
-
entry.expiresAt !== undefined && entry.expiresAt <= Date.now()
|
|
15
|
-
|
|
16
|
-
const cache = (async <T>(
|
|
5
|
+
const store = createCache()
|
|
6
|
+
const cache = (<T>(
|
|
17
7
|
key: string,
|
|
18
8
|
fn: () => Promise<T> | T,
|
|
19
9
|
options?: { ttlMs?: number }
|
|
20
|
-
): Promise<T> =>
|
|
21
|
-
const existing = store.get(key)
|
|
22
|
-
if (existing && !isExpired(existing)) {
|
|
23
|
-
if (existing.inflight) return existing.inflight as Promise<T>
|
|
24
|
-
if (existing.hasValue) return existing.value as T
|
|
25
|
-
}
|
|
10
|
+
): Promise<T> => store.getOrSet(key, fn, options)) as ActionCache
|
|
26
11
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
expiresAt:
|
|
32
|
-
options?.ttlMs !== undefined ? Date.now() + options.ttlMs : undefined
|
|
33
|
-
}
|
|
34
|
-
store.set(key, entry)
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
const value = await promise
|
|
38
|
-
entry.value = value
|
|
39
|
-
entry.hasValue = true
|
|
40
|
-
entry.inflight = undefined
|
|
41
|
-
return value
|
|
42
|
-
} catch (error) {
|
|
43
|
-
store.delete(key)
|
|
44
|
-
throw error
|
|
45
|
-
}
|
|
46
|
-
}) as ActionCache
|
|
47
|
-
|
|
48
|
-
cache.get = <T>(key: string): T | undefined => {
|
|
49
|
-
const entry = store.get(key)
|
|
50
|
-
if (!entry || !entry.hasValue) return undefined
|
|
51
|
-
if (isExpired(entry)) {
|
|
52
|
-
store.delete(key)
|
|
53
|
-
return undefined
|
|
54
|
-
}
|
|
55
|
-
return entry.value as T
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
cache.set = <T>(
|
|
59
|
-
key: string,
|
|
60
|
-
value: T,
|
|
61
|
-
options?: { ttlMs?: number }
|
|
62
|
-
): void => {
|
|
63
|
-
store.set(key, {
|
|
64
|
-
value,
|
|
65
|
-
hasValue: true,
|
|
66
|
-
expiresAt:
|
|
67
|
-
options?.ttlMs !== undefined ? Date.now() + options.ttlMs : undefined
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
cache.invalidate = (key: string): void => {
|
|
72
|
-
store.delete(key)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
cache.clear = (): void => {
|
|
76
|
-
store.clear()
|
|
77
|
-
}
|
|
12
|
+
cache.get = (key) => store.get(key)
|
|
13
|
+
cache.set = (key, value, options) => store.set(key, value, options)
|
|
14
|
+
cache.invalidate = (key) => store.delete(key)
|
|
15
|
+
cache.clear = () => store.clear()
|
|
78
16
|
|
|
79
17
|
return cache
|
|
80
18
|
}
|
|
@@ -87,10 +25,11 @@ export function makeDefineAction<TApi>(): DefineAction<TApi> {
|
|
|
87
25
|
noRuntimeInput: false as const
|
|
88
26
|
})
|
|
89
27
|
}
|
|
90
|
-
const def = args[0] as { handler: unknown }
|
|
28
|
+
const def = args[0] as { handler: unknown; input?: unknown }
|
|
91
29
|
return {
|
|
92
30
|
...def,
|
|
93
|
-
|
|
31
|
+
// A schema-validated action takes input; a bare handler doesn't.
|
|
32
|
+
noRuntimeInput: def.input === undefined
|
|
94
33
|
}
|
|
95
34
|
}
|
|
96
35
|
return defineAction as DefineAction<TApi>
|