hanzio 1.1.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.
Files changed (172) hide show
  1. package/README.md +832 -219
  2. package/dist/api-wrapper/builders.d.ts +15 -3
  3. package/dist/api-wrapper/create-client.d.ts +1 -1
  4. package/dist/api-wrapper/describe.d.ts +16 -0
  5. package/dist/api-wrapper/endpoint.d.ts +18 -0
  6. package/dist/api-wrapper/errors.d.ts +40 -2
  7. package/dist/api-wrapper/headers.d.ts +2 -1
  8. package/dist/api-wrapper/index.d.ts +5 -0
  9. package/dist/api-wrapper/otel.d.ts +44 -0
  10. package/dist/api-wrapper/paginate.d.ts +12 -0
  11. package/dist/api-wrapper/redaction.d.ts +2 -0
  12. package/dist/api-wrapper/shared.d.ts +16 -2
  13. package/dist/api-wrapper/testing.d.ts +23 -0
  14. package/dist/api-wrapper/transport.d.ts +12 -10
  15. package/dist/api-wrapper/types.d.ts +104 -18
  16. package/dist/array/index.d.ts +50 -4
  17. package/dist/cache/createCache.d.ts +31 -0
  18. package/dist/cache/index.d.ts +45 -2
  19. package/dist/color/contrast.d.ts +40 -0
  20. package/dist/color/index.d.ts +2 -0
  21. package/dist/{math → color}/metricsSeriesColors.d.ts +14 -7
  22. package/dist/cool-console-log/index.d.ts +34 -5
  23. package/dist/crypto/encoding.d.ts +18 -0
  24. package/dist/crypto/hash.d.ts +33 -0
  25. package/dist/crypto/index.d.ts +4 -0
  26. package/dist/crypto/sealer.d.ts +25 -0
  27. package/dist/crypto/webhook.d.ts +20 -0
  28. package/dist/date/index.d.ts +46 -2
  29. package/dist/emitter/index.d.ts +21 -0
  30. package/dist/error/index.d.ts +12 -0
  31. package/dist/format/index.d.ts +102 -0
  32. package/dist/function/index.d.ts +60 -0
  33. package/dist/guard/index.d.ts +20 -0
  34. package/dist/i18n/index.d.ts +37 -0
  35. package/dist/index-0zvtcbzy.js +224 -0
  36. package/dist/index-181e6vfw.js +29 -0
  37. package/dist/index-8r2vdzjg.js +87 -0
  38. package/dist/index-hy7kbb99.js +157 -0
  39. package/dist/{src/secrets/loaders.js → index-j1ybktbr.js} +608 -405
  40. package/dist/index-k9yx6bne.js +89 -0
  41. package/dist/index-kj1phgrx.js +169 -0
  42. package/dist/index-mnkcfyx8.js +78 -0
  43. package/dist/{p-queue/index.js → index-pwt0dz63.js} +7 -11
  44. package/dist/index-rp5pqghz.js +157 -0
  45. package/dist/index-srt06xd2.js +15 -0
  46. package/dist/index-wjyb9bsd.js +263 -0
  47. package/dist/index.d.ts +7 -7
  48. package/dist/jwt/index.d.ts +50 -2
  49. package/dist/math/index.d.ts +2 -2
  50. package/dist/math/linearRegressionTrend.d.ts +14 -1
  51. package/dist/math/scale.d.ts +8 -0
  52. package/dist/object/index.d.ts +19 -0
  53. package/dist/p-queue/index.d.ts +1 -1
  54. package/dist/promise/index.d.ts +97 -2
  55. package/dist/secrets/core.d.ts +47 -0
  56. package/dist/secrets/deadline.d.ts +6 -0
  57. package/dist/secrets/environment.d.ts +9 -0
  58. package/dist/secrets/errors.d.ts +11 -0
  59. package/dist/secrets/index.d.ts +13 -25
  60. package/dist/secrets/infisical-cli.d.ts +6 -0
  61. package/dist/secrets/infisical-config.d.ts +17 -0
  62. package/dist/secrets/infisical-session.d.ts +4 -0
  63. package/dist/secrets/infisical.d.ts +8 -13
  64. package/dist/secrets/loaders.d.ts +5 -12
  65. package/dist/secrets/vite.d.ts +7 -3
  66. package/dist/secrets/worker-loader.d.ts +9 -0
  67. package/dist/secrets/worker.d.ts +3 -0
  68. package/dist/sitemap/index.d.ts +48 -6
  69. package/dist/src/api-wrapper/index.js +60 -1100
  70. package/dist/src/api-wrapper/testing.js +20 -0
  71. package/dist/{cool-console-log → src/cool-console-log}/index.js +80 -33
  72. package/dist/src/crypto/index.js +195 -0
  73. package/dist/src/format/index.js +211 -0
  74. package/dist/src/i18n/index.js +36 -0
  75. package/dist/src/index.js +863 -2809
  76. package/dist/src/jwt/index.js +138 -92
  77. package/dist/src/p-queue/index.js +9 -437
  78. package/dist/src/secrets/index.js +261 -1377
  79. package/dist/src/secrets/vite.js +6 -17
  80. package/dist/src/secrets/worker.js +12 -0
  81. package/dist/src/sitemap/index.js +183 -511
  82. package/dist/src/storage/index.js +119 -0
  83. package/dist/src/zod/index.js +347 -174
  84. package/dist/state/index.d.ts +21 -0
  85. package/dist/storage/index.d.ts +58 -0
  86. package/dist/string/index.d.ts +75 -2
  87. package/dist/typedswitch/index.d.ts +37 -26
  88. package/dist/types/index.d.ts +11 -0
  89. package/dist/url/index.d.ts +50 -1
  90. package/dist/zod/index.d.ts +32 -3
  91. package/dist/zod/introspect.d.ts +19 -0
  92. package/dist/zod/jsonToZodSchemaMapper.d.ts +3 -1
  93. package/dist/zod/zodMinMaxFilter.d.ts +22 -3
  94. package/dist/zod/zodToTypeString.d.ts +8 -3
  95. package/package.json +87 -7
  96. package/src/api-wrapper/actions-impl.ts +11 -72
  97. package/src/api-wrapper/builders.ts +84 -52
  98. package/src/api-wrapper/create-client.ts +246 -96
  99. package/src/api-wrapper/describe.ts +157 -0
  100. package/src/api-wrapper/endpoint.ts +26 -0
  101. package/src/api-wrapper/error-reporting.ts +7 -1
  102. package/src/api-wrapper/errors.ts +117 -2
  103. package/src/api-wrapper/headers.ts +19 -1
  104. package/src/api-wrapper/index.ts +5 -0
  105. package/src/api-wrapper/otel.ts +139 -0
  106. package/src/api-wrapper/paginate.ts +28 -0
  107. package/src/api-wrapper/redaction.ts +43 -0
  108. package/src/api-wrapper/shared.ts +21 -2
  109. package/src/api-wrapper/testing.ts +48 -0
  110. package/src/api-wrapper/transport.ts +68 -74
  111. package/src/api-wrapper/types.ts +186 -18
  112. package/src/array/index.ts +195 -42
  113. package/src/cache/createCache.ts +157 -0
  114. package/src/cache/index.ts +235 -83
  115. package/src/color/contrast.ts +163 -0
  116. package/src/color/index.ts +22 -0
  117. package/src/{math → color}/metricsSeriesColors.ts +47 -49
  118. package/src/cool-console-log/index.ts +128 -41
  119. package/src/crypto/encoding.ts +83 -0
  120. package/src/crypto/hash.ts +170 -0
  121. package/src/crypto/index.ts +26 -0
  122. package/src/crypto/sealer.ts +168 -0
  123. package/src/crypto/webhook.ts +86 -0
  124. package/src/date/index.ts +109 -34
  125. package/src/emitter/index.ts +82 -0
  126. package/src/error/index.ts +63 -0
  127. package/src/format/index.ts +389 -0
  128. package/src/function/index.ts +201 -0
  129. package/src/guard/index.ts +80 -0
  130. package/src/i18n/index.ts +125 -0
  131. package/src/index.ts +11 -7
  132. package/src/jwt/index.ts +199 -125
  133. package/src/math/index.ts +5 -10
  134. package/src/math/linearRegressionTrend.ts +33 -8
  135. package/src/math/scale.ts +17 -0
  136. package/src/object/index.ts +99 -0
  137. package/src/p-queue/index.ts +2 -0
  138. package/src/promise/index.ts +304 -9
  139. package/src/secrets/core.ts +348 -0
  140. package/src/secrets/deadline.ts +69 -0
  141. package/src/secrets/environment.ts +69 -0
  142. package/src/secrets/errors.ts +29 -0
  143. package/src/secrets/index.ts +79 -210
  144. package/src/secrets/infisical-cli.ts +99 -0
  145. package/src/secrets/infisical-config.ts +70 -0
  146. package/src/secrets/infisical-session.ts +42 -0
  147. package/src/secrets/infisical.ts +214 -66
  148. package/src/secrets/loaders.ts +24 -48
  149. package/src/secrets/vite.ts +44 -15
  150. package/src/secrets/worker-loader.ts +56 -0
  151. package/src/secrets/worker.ts +4 -0
  152. package/src/sitemap/index.ts +293 -130
  153. package/src/state/index.ts +133 -81
  154. package/src/storage/index.ts +187 -0
  155. package/src/string/index.ts +261 -23
  156. package/src/typedswitch/index.ts +134 -103
  157. package/src/types/index.ts +14 -0
  158. package/src/url/index.ts +146 -1
  159. package/src/zod/index.ts +105 -9
  160. package/src/zod/introspect.ts +103 -0
  161. package/src/zod/jsonToZodSchemaMapper.ts +44 -21
  162. package/src/zod/zodMinMaxFilter.ts +37 -13
  163. package/src/zod/zodToTypeString.ts +184 -181
  164. package/dist/api-wrapper/index.js +0 -250
  165. package/dist/gzip/index.d.ts +0 -2
  166. package/dist/gzip/index.js +0 -16
  167. package/dist/index.js +0 -1823
  168. package/dist/jwt/index.js +0 -19
  169. package/dist/sitemap/index.js +0 -552
  170. package/dist/src/gzip/index.js +0 -16
  171. package/dist/src/secrets/infisical.js +0 -1194
  172. package/dist/zod/index.js +0 -210
@@ -46,6 +46,10 @@ export interface StateMachineConfig<TState extends string, TAction extends strin
46
46
  stateTransitions: Record<TState, readonly TState[]>;
47
47
  validators?: Partial<Record<TState, ValidatorFn<TState, TContext, TAction>>>;
48
48
  globalValidator?: ValidatorFn<TState, TContext, TAction>;
49
+ actionValidators?: Partial<Record<TAction, ValidatorFn<TState, TContext, TAction>>>;
50
+ initialState?: TState;
51
+ onTransition?: (context: TContext, from: TState, to: TState, action: TAction) => void | Promise<void>;
52
+ applyTransition?: boolean;
49
53
  actions?: {
50
54
  [K in TAction]?: ActionHandlerFn<TContext, TActionDataMap[K], TActionResultMap[K]>;
51
55
  };
@@ -74,6 +78,12 @@ export declare class SimpleStateMachine<TState extends string, TAction extends s
74
78
  * @returns Map of target states to validation results (true if any action to that state validates)
75
79
  */
76
80
  getPossibleTransitions(): Promise<Partial<Record<TState, ValidationResult>>>;
81
+ /**
82
+ * Checks whether an action can be executed from the current state
83
+ *
84
+ * @returns true, or the reason the action is not allowed
85
+ */
86
+ canExecute(action: TAction): Promise<ValidationResult>;
77
87
  /**
78
88
  * Executes an action with additional data
79
89
  *
@@ -99,3 +109,14 @@ export declare class SimpleStateMachine<TState extends string, TAction extends s
99
109
  */
100
110
  getInitialState(): TState | undefined;
101
111
  }
112
+ /**
113
+ * Defines a state machine config once and binds it to items on demand
114
+ *
115
+ * @example
116
+ * const orderMachine = createStateMachine<Status, Action, Order>(config)
117
+ * const machine = orderMachine.for(order, 'status')
118
+ */
119
+ export declare function createStateMachine<TState extends string, TAction extends string, TContext, TActionDataMap extends ActionDataMap<TAction> = ActionDataMap<TAction>, TActionResultMap extends ActionResultMap<TAction> = ActionResultMap<TAction>>(config: StateMachineConfig<TState, TAction, TContext, TActionDataMap, TActionResultMap>): {
120
+ config: StateMachineConfig<TState, TAction, TContext, TActionDataMap, TActionResultMap>;
121
+ for: (item: TContext, stateKey: StateKey<TContext, TState>) => SimpleStateMachine<TState, TAction, TContext, TActionDataMap, TActionResultMap>;
122
+ };
@@ -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>;
@@ -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
- export declare function extractNumber(value: string | null | undefined): number | undefined;
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
- export declare function slugify(value: string): string;
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>;
@@ -67,7 +67,11 @@
67
67
  type RawHandlerReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
68
68
  /** Get union of all raw return types from a cases object's values */
69
69
  type RawCasesReturnType<Cases> = {
70
- [K in keyof Cases]: Cases[K] extends undefined ? never : RawHandlerReturnType<Cases[K]>;
70
+ [K in keyof Cases]: RawHandlerReturnType<Cases[K]>;
71
+ }[keyof Cases];
72
+ /** Only required, defined handlers guarantee that a case is handled. */
73
+ type HandledCaseKeys<Cases> = {
74
+ [K in keyof Cases]-?: {} extends Pick<Cases, K> ? never : undefined extends Cases[K] ? never : K;
71
75
  }[keyof Cases];
72
76
  /** Cases for string input - all cases required */
73
77
  export type StringSwitchCases<T extends string, R> = {
@@ -77,26 +81,28 @@ export type StringSwitchCases<T extends string, R> = {
77
81
  export type PartialStringSwitchCases<T extends string, R> = {
78
82
  [K in T]?: (value: K) => R | Promise<R>;
79
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
+ };
80
94
  /** Cases for object input with custom key - all cases required */
81
- export type ObjectSwitchCases<T, K extends keyof T, R> = T[K] extends string ? {
82
- [V in T[K]]: (value: Extract<T, Record<K, V>>) => R | Promise<R>;
83
- } : never;
95
+ export type ObjectSwitchCases<T, K extends keyof T, R> = T[K] extends Discriminant ? ObjectCases<T, K, R | Promise<R>> : never;
84
96
  /** Partial cases for object input with custom key (when default is provided) */
85
- export type PartialObjectSwitchCases<T, K extends keyof T, R> = T[K] extends string ? {
86
- [V in T[K]]?: (value: Extract<T, Record<K, V>>) => R | Promise<R>;
87
- } : never;
97
+ export type PartialObjectSwitchCases<T, K extends keyof T, R> = T[K] extends Discriminant ? PartialObjectCases<T, K, R | Promise<R>> : never;
88
98
  export declare function typedSwitch<T extends string, Cases extends {
89
99
  [K in T]: (value: K) => unknown;
90
100
  }>(value: T, cases: Cases): RawCasesReturnType<Cases>;
91
101
  export declare function typedSwitch<T extends string, Cases extends {
92
102
  [K in T]?: (value: K) => unknown;
93
- }, DefaultCase extends (value: T) => unknown>(value: T, cases: Cases, defaultCase: DefaultCase): RawCasesReturnType<Cases> | RawHandlerReturnType<DefaultCase>;
94
- export declare function typedSwitch<T extends Record<string, unknown>, K extends keyof T, TKey extends T[K] & string, Cases extends {
95
- [V in TKey]: (value: Extract<T, Record<K, V>>) => unknown;
96
- }>(value: T, key: K, cases: Cases): RawCasesReturnType<Cases>;
97
- export declare function typedSwitch<T extends Record<string, unknown>, K extends keyof T, TKey extends T[K] & string, Cases extends {
98
- [V in TKey]?: (value: Extract<T, Record<K, V>>) => unknown;
99
- }, DefaultCase extends (value: T) => unknown>(value: T, key: K, cases: Cases, defaultCase: DefaultCase): RawCasesReturnType<Cases> | RawHandlerReturnType<DefaultCase>;
103
+ }, DefaultCase extends (value: Exclude<T, HandledCaseKeys<Cases>>) => unknown>(value: T, 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>;
100
106
  export declare function typedSwitch<Constraint, T extends string = string>(value: T, cases: {
101
107
  [K in T]: (value: K) => Constraint;
102
108
  }): Constraint;
@@ -109,16 +115,21 @@ export declare function typedSwitch<Constraint, T extends string = string>(value
109
115
  export declare function typedSwitch<Constraint, T extends string = string>(value: T, cases: {
110
116
  [K in T]?: (value: K) => Constraint | Promise<Constraint>;
111
117
  }, defaultCase: (value: T) => Constraint | Promise<Constraint>): Constraint | Promise<Constraint>;
112
- export declare function typedSwitch<Constraint, T extends Record<string, unknown> = Record<string, unknown>, K extends keyof T = keyof T>(value: T, key: K, cases: {
113
- [V in T[K] & string]: (value: Extract<T, Record<K, V>>) => Constraint;
114
- }): Constraint;
115
- export declare function typedSwitch<Constraint, T extends Record<string, unknown> = Record<string, unknown>, K extends keyof T = keyof T>(value: T, key: K, cases: {
116
- [V in T[K] & string]: (value: Extract<T, Record<K, V>>) => Constraint | Promise<Constraint>;
117
- }): Constraint | Promise<Constraint>;
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: {
119
- [V in T[K] & string]?: (value: Extract<T, Record<K, V>>) => Constraint;
120
- }, 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: {
122
- [V in T[K] & string]?: (value: Extract<T, Record<K, V>>) => Constraint | Promise<Constraint>;
123
- }, defaultCase: (value: T) => Constraint | Promise<Constraint>): Constraint | Promise<Constraint>;
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;
124
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;
@@ -1 +1,50 @@
1
- export declare function getDomainFaviconUrl(domain: string, size?: number): string;
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 {};
@@ -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): PropertyKey extends TypeName ? z.ZodString : z.core.$ZodBranded<z.ZodString, TypeName, "out">;
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
- export declare function normalizeSingleOrArray<T>(value: T | readonly T[] | null | undefined): T[];
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: ZodMinMaxFilter | undefined): {
12
- gte?: number;
13
- lte?: number;
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: z.ZodType, indent?: number): string;
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: z.ZodType): unknown;
14
+ export declare function zodToExample(schema: Schema): unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hanzio",
3
- "version": "1.1.0",
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",
@@ -46,31 +113,44 @@
46
113
  "bun": "./src/secrets/vite.ts",
47
114
  "import": "./dist/src/secrets/vite.js",
48
115
  "default": "./dist/src/secrets/vite.js"
116
+ },
117
+ "./secrets/worker": {
118
+ "types": "./dist/secrets/worker.d.ts",
119
+ "bun": "./src/secrets/worker.ts",
120
+ "import": "./dist/src/secrets/worker.js",
121
+ "default": "./dist/src/secrets/worker.js"
49
122
  }
50
123
  },
51
124
  "scripts": {
52
- "build": "bun run build:js && bun run build:types",
53
- "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/secrets/index.ts ./src/secrets/infisical.ts ./src/secrets/loaders.ts ./src/secrets/vite.ts --outdir ./dist --target node --packages external",
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",
54
127
  "build:types": "tsgo -p tsconfig.build.json",
55
128
  "prepublishOnly": "bun run build",
56
- "publish:patch": "npm version patch && npm publish",
57
- "publish:minor": "npm version minor && npm publish",
58
- "publish:major": "npm version major && npm publish",
59
129
  "test": "bun test",
60
130
  "lint": "bun run typecheck && bun biome check",
61
131
  "lint:write": "bun run typecheck && bun biome check --write",
62
132
  "typecheck": "tsgo --noEmit",
63
- "prepare": "husky"
133
+ "prepare": "husky",
134
+ "test:secrets:runtime": "bun run build && node scripts/verify-secrets.mjs",
135
+ "test:exports": "bun run build && node scripts/verify-exports.mjs"
64
136
  },
65
137
  "devDependencies": {
66
138
  "@biomejs/biome": "^2.4.6",
139
+ "@opentelemetry/api": "^1.9.1",
67
140
  "@types/bun": "latest",
68
141
  "@typescript/native-preview": "^7.0.0-dev.20260306.1",
69
142
  "husky": "^9.1.7",
143
+ "miniflare": "^4.20260730.0",
70
144
  "typescript": "^5.7.0",
145
+ "vite": "^8.2.2",
71
146
  "zod": "^4.3.6"
72
147
  },
73
148
  "peerDependencies": {
74
149
  "zod": "^4.3.6"
150
+ },
151
+ "peerDependenciesMeta": {
152
+ "zod": {
153
+ "optional": true
154
+ }
75
155
  }
76
156
  }