@simplysm/core-common 13.0.100 → 14.0.4

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 (184) hide show
  1. package/README.md +86 -92
  2. package/dist/common.types.d.ts +14 -14
  3. package/dist/common.types.js +2 -1
  4. package/dist/common.types.js.map +1 -6
  5. package/dist/env.d.ts +8 -1
  6. package/dist/env.d.ts.map +1 -1
  7. package/dist/env.js +13 -9
  8. package/dist/env.js.map +1 -6
  9. package/dist/errors/argument-error.d.ts +10 -10
  10. package/dist/errors/argument-error.d.ts.map +1 -1
  11. package/dist/errors/argument-error.js +31 -14
  12. package/dist/errors/argument-error.js.map +1 -6
  13. package/dist/errors/not-implemented-error.d.ts +8 -8
  14. package/dist/errors/not-implemented-error.js +30 -12
  15. package/dist/errors/not-implemented-error.js.map +1 -6
  16. package/dist/errors/sd-error.d.ts +10 -10
  17. package/dist/errors/sd-error.d.ts.map +1 -1
  18. package/dist/errors/sd-error.js +45 -24
  19. package/dist/errors/sd-error.js.map +1 -6
  20. package/dist/errors/timeout-error.d.ts +10 -10
  21. package/dist/errors/timeout-error.js +34 -15
  22. package/dist/errors/timeout-error.js.map +1 -6
  23. package/dist/extensions/arr-ext.d.ts +2 -2
  24. package/dist/extensions/arr-ext.helpers.d.ts +10 -10
  25. package/dist/extensions/arr-ext.helpers.js +112 -89
  26. package/dist/extensions/arr-ext.helpers.js.map +1 -6
  27. package/dist/extensions/arr-ext.js +458 -422
  28. package/dist/extensions/arr-ext.js.map +1 -6
  29. package/dist/extensions/arr-ext.types.d.ts +57 -57
  30. package/dist/extensions/arr-ext.types.d.ts.map +1 -1
  31. package/dist/extensions/arr-ext.types.js +6 -1
  32. package/dist/extensions/arr-ext.types.js.map +1 -6
  33. package/dist/extensions/map-ext.d.ts +16 -16
  34. package/dist/extensions/map-ext.js +27 -22
  35. package/dist/extensions/map-ext.js.map +1 -6
  36. package/dist/extensions/set-ext.d.ts +11 -11
  37. package/dist/extensions/set-ext.js +32 -25
  38. package/dist/extensions/set-ext.js.map +1 -6
  39. package/dist/features/debounce-queue.d.ts +17 -17
  40. package/dist/features/debounce-queue.js +98 -70
  41. package/dist/features/debounce-queue.js.map +1 -6
  42. package/dist/features/event-emitter.d.ts +20 -20
  43. package/dist/features/event-emitter.js +101 -78
  44. package/dist/features/event-emitter.js.map +1 -6
  45. package/dist/features/serial-queue.d.ts +11 -11
  46. package/dist/features/serial-queue.js +78 -57
  47. package/dist/features/serial-queue.js.map +1 -6
  48. package/dist/globals.d.ts +4 -4
  49. package/dist/globals.js +9 -1
  50. package/dist/globals.js.map +1 -6
  51. package/dist/index.js +28 -27
  52. package/dist/index.js.map +1 -6
  53. package/dist/types/date-only.d.ts +64 -64
  54. package/dist/types/date-only.d.ts.map +1 -1
  55. package/dist/types/date-only.js +263 -252
  56. package/dist/types/date-only.js.map +1 -6
  57. package/dist/types/date-time.d.ts +36 -36
  58. package/dist/types/date-time.d.ts.map +1 -1
  59. package/dist/types/date-time.js +196 -288
  60. package/dist/types/date-time.js.map +1 -6
  61. package/dist/types/lazy-gc-map.d.ts +26 -26
  62. package/dist/types/lazy-gc-map.d.ts.map +1 -1
  63. package/dist/types/lazy-gc-map.js +202 -159
  64. package/dist/types/lazy-gc-map.js.map +1 -6
  65. package/dist/types/time.d.ts +23 -23
  66. package/dist/types/time.d.ts.map +1 -1
  67. package/dist/types/time.js +169 -158
  68. package/dist/types/time.js.map +1 -6
  69. package/dist/types/uuid.d.ts +11 -11
  70. package/dist/types/uuid.d.ts.map +1 -1
  71. package/dist/types/uuid.js +95 -70
  72. package/dist/types/uuid.js.map +1 -6
  73. package/dist/utils/bytes.d.ts +17 -17
  74. package/dist/utils/bytes.js +137 -81
  75. package/dist/utils/bytes.js.map +1 -6
  76. package/dist/utils/date-format.d.ts +40 -40
  77. package/dist/utils/date-format.js +187 -101
  78. package/dist/utils/date-format.js.map +1 -6
  79. package/dist/utils/error.d.ts +4 -4
  80. package/dist/utils/error.js +11 -6
  81. package/dist/utils/error.js.map +1 -6
  82. package/dist/utils/json.d.ts +19 -19
  83. package/dist/utils/json.js +187 -135
  84. package/dist/utils/json.js.map +1 -6
  85. package/dist/utils/num.d.ts +20 -20
  86. package/dist/utils/num.js +76 -34
  87. package/dist/utils/num.js.map +1 -6
  88. package/dist/utils/obj.d.ts +111 -111
  89. package/dist/utils/obj.d.ts.map +1 -1
  90. package/dist/utils/obj.js +706 -496
  91. package/dist/utils/obj.js.map +1 -6
  92. package/dist/utils/path.d.ts +10 -10
  93. package/dist/utils/path.js +35 -18
  94. package/dist/utils/path.js.map +1 -6
  95. package/dist/utils/primitive.d.ts +5 -5
  96. package/dist/utils/primitive.js +34 -14
  97. package/dist/utils/primitive.js.map +1 -6
  98. package/dist/utils/str.d.ts +38 -38
  99. package/dist/utils/str.js +217 -113
  100. package/dist/utils/str.js.map +1 -6
  101. package/dist/utils/template-strings.d.ts +26 -26
  102. package/dist/utils/template-strings.js +113 -40
  103. package/dist/utils/template-strings.js.map +1 -6
  104. package/dist/utils/transferable.d.ts +18 -18
  105. package/dist/utils/transferable.js +218 -151
  106. package/dist/utils/transferable.js.map +1 -6
  107. package/dist/utils/wait.d.ts +9 -9
  108. package/dist/utils/wait.js +30 -15
  109. package/dist/utils/wait.js.map +1 -6
  110. package/dist/utils/xml.d.ts +13 -13
  111. package/dist/utils/xml.js +84 -46
  112. package/dist/utils/xml.js.map +1 -6
  113. package/dist/utils/zip.d.ts +22 -22
  114. package/dist/utils/zip.js +172 -148
  115. package/dist/utils/zip.js.map +1 -6
  116. package/docs/array-extensions.md +430 -0
  117. package/docs/env.md +52 -0
  118. package/docs/errors.md +41 -56
  119. package/docs/features.md +82 -97
  120. package/docs/type-utilities.md +91 -0
  121. package/docs/types.md +221 -201
  122. package/docs/utils.md +319 -435
  123. package/package.json +7 -5
  124. package/src/common.types.ts +14 -14
  125. package/src/env.ts +12 -3
  126. package/src/errors/argument-error.ts +15 -15
  127. package/src/errors/not-implemented-error.ts +9 -9
  128. package/src/errors/sd-error.ts +12 -12
  129. package/src/errors/timeout-error.ts +12 -12
  130. package/src/extensions/arr-ext.helpers.ts +16 -16
  131. package/src/extensions/arr-ext.ts +35 -35
  132. package/src/extensions/arr-ext.types.ts +57 -57
  133. package/src/extensions/map-ext.ts +16 -16
  134. package/src/extensions/set-ext.ts +11 -11
  135. package/src/features/debounce-queue.ts +23 -23
  136. package/src/features/event-emitter.ts +25 -25
  137. package/src/features/serial-queue.ts +13 -13
  138. package/src/globals.ts +4 -4
  139. package/src/index.ts +5 -5
  140. package/src/types/date-only.ts +84 -83
  141. package/src/types/date-time.ts +43 -42
  142. package/src/types/lazy-gc-map.ts +44 -44
  143. package/src/types/time.ts +29 -29
  144. package/src/types/uuid.ts +15 -15
  145. package/src/utils/bytes.ts +35 -35
  146. package/src/utils/date-format.ts +59 -59
  147. package/src/utils/error.ts +4 -4
  148. package/src/utils/json.ts +41 -41
  149. package/src/utils/num.ts +20 -20
  150. package/src/utils/obj.ts +138 -138
  151. package/src/utils/path.ts +10 -10
  152. package/src/utils/primitive.ts +6 -6
  153. package/src/utils/str.ts +48 -48
  154. package/src/utils/template-strings.ts +29 -29
  155. package/src/utils/transferable.ts +38 -38
  156. package/src/utils/wait.ts +10 -10
  157. package/src/utils/xml.ts +19 -19
  158. package/src/utils/zip.ts +25 -25
  159. package/docs/extensions.md +0 -387
  160. package/tests/errors/errors.spec.ts +0 -80
  161. package/tests/extensions/array-extension.spec.ts +0 -654
  162. package/tests/extensions/map-extension.spec.ts +0 -117
  163. package/tests/extensions/set-extension.spec.ts +0 -67
  164. package/tests/types/date-only.spec.ts +0 -533
  165. package/tests/types/date-time.spec.ts +0 -246
  166. package/tests/types/lazy-gc-map.spec.ts +0 -606
  167. package/tests/types/time.spec.ts +0 -428
  168. package/tests/types/uuid.spec.ts +0 -74
  169. package/tests/utils/bytes-utils.spec.ts +0 -197
  170. package/tests/utils/date-format.spec.ts +0 -350
  171. package/tests/utils/debounce-queue.spec.ts +0 -226
  172. package/tests/utils/json.spec.ts +0 -400
  173. package/tests/utils/number.spec.ts +0 -136
  174. package/tests/utils/object.spec.ts +0 -810
  175. package/tests/utils/path.spec.ts +0 -70
  176. package/tests/utils/primitive.spec.ts +0 -43
  177. package/tests/utils/sd-event-emitter.spec.ts +0 -189
  178. package/tests/utils/serial-queue.spec.ts +0 -305
  179. package/tests/utils/string.spec.ts +0 -265
  180. package/tests/utils/template-strings.spec.ts +0 -48
  181. package/tests/utils/transferable.spec.ts +0 -639
  182. package/tests/utils/wait.spec.ts +0 -123
  183. package/tests/utils/xml.spec.ts +0 -146
  184. package/tests/utils/zip.spec.ts +0 -221
package/docs/utils.md CHANGED
@@ -1,264 +1,201 @@
1
- # Utilities
1
+ # Utils
2
2
 
3
- Utility namespaces and directly exported functions.
3
+ Namespace-exported utility functions and standalone exports. Import as `import { obj, str, num, ... } from "@simplysm/core-common"`.
4
4
 
5
- Source: `src/utils/*.ts`
5
+ ## `obj` -- Object Utilities
6
6
 
7
- ---
7
+ ### `obj.clone<T>(source: T): T`
8
8
 
9
- ## Namespace: `obj`
9
+ Deep clone with support for circular references and custom types (DateTime, DateOnly, Time, Uuid, Uint8Array, Date, RegExp, Map, Set, Error). Preserves prototype chain. Functions and Symbols are kept as references.
10
10
 
11
- Object manipulation utilities. Source: `src/utils/obj.ts`
11
+ ```typescript
12
+ const cloned = obj.clone({ a: 1, b: new DateTime() });
13
+ ```
12
14
 
13
- ### `obj.clone`
15
+ ### `obj.equal(source, target, options?): boolean`
14
16
 
15
- Deep clone. Supports circular references and custom types (DateTime, DateOnly, Time, Uuid, Uint8Array, Error, Map, Set, RegExp). Functions and Symbols maintain references. Prototype chain is maintained.
17
+ Deep equality comparison.
16
18
 
17
19
  ```typescript
18
- export function clone<TObj>(source: TObj): TObj;
20
+ function equal(source: unknown, target: unknown, options?: EqualOptions): boolean;
19
21
  ```
20
22
 
21
- ### `obj.equal`
23
+ **`EqualOptions`:**
22
24
 
23
- Deep equality comparison. Supports DateTime, DateOnly, Time, Uuid, Date, RegExp, Map, Set, Array, and plain objects.
25
+ | Field | Type | Description |
26
+ |-------|------|-------------|
27
+ | `topLevelIncludes` | `string[]` | Only compare these top-level keys |
28
+ | `topLevelExcludes` | `string[]` | Exclude these top-level keys from comparison |
29
+ | `ignoreArrayIndex` | `boolean` | Ignore array order (O(n^2)) |
30
+ | `shallow` | `boolean` | Compare only one level deep (reference equality for nested) |
24
31
 
25
- ```typescript
26
- export function equal(source: unknown, target: unknown, options?: EqualOptions): boolean;
32
+ Supports: Date, DateTime, DateOnly, Time, Uuid, RegExp, Array, Map, Set, plain objects.
27
33
 
28
- export interface EqualOptions {
29
- /** List of keys to compare (applies only to top level) */
30
- topLevelIncludes?: string[];
31
- /** List of keys to exclude from comparison (applies only to top level) */
32
- topLevelExcludes?: string[];
33
- /** Whether to ignore array order. O(n^2) complexity when true */
34
- ignoreArrayIndex?: boolean;
35
- /** Whether to do shallow comparison. Only compare 1 level (reference comparison) when true */
36
- shallow?: boolean;
37
- }
38
- ```
39
-
40
- ### `obj.merge`
34
+ ### `obj.merge<S, T>(source: S, target: T, opt?): S & T`
41
35
 
42
- Deep merge (merge target into source as base). Returns a new object without modifying originals.
36
+ Deep merge. Returns a new object (immutable).
43
37
 
44
38
  ```typescript
45
- export function merge<TSource, TMergeTarget>(
46
- source: TSource,
47
- target: TMergeTarget,
48
- opt?: MergeOptions,
49
- ): TSource & TMergeTarget;
50
-
51
- export interface MergeOptions {
52
- /** Array processing method. "replace": replace with target (default), "concat": merge (deduplicate) */
53
- arrayProcess?: "replace" | "concat";
54
- /** Whether to delete the key when target is null */
55
- useDelTargetNull?: boolean;
56
- }
39
+ function merge<S, T>(source: S, target: T, opt?: MergeOptions): S & T;
57
40
  ```
58
41
 
59
- ### `obj.merge3`
42
+ **`MergeOptions`:**
43
+
44
+ | Field | Type | Default | Description |
45
+ |-------|------|---------|-------------|
46
+ | `arrayProcess` | `"replace" \| "concat"` | `"replace"` | How to handle arrays. `"concat"` deduplicates via Set |
47
+ | `useDelTargetNull` | `boolean` | `false` | If `true`, `null` target values delete the key |
60
48
 
61
- 3-way merge. Compares source, origin, and target to produce a merged result with conflict detection.
49
+ ### `obj.merge3<S, O, T>(source, origin, target, optionsObj?)`
50
+
51
+ 3-way merge. Compares source and target against a common origin.
62
52
 
63
53
  ```typescript
64
- export function merge3<
65
- S extends Record<string, unknown>,
66
- O extends Record<string, unknown>,
67
- T extends Record<string, unknown>,
68
- >(
69
- source: S,
70
- origin: O,
71
- target: T,
54
+ function merge3<S, O, T>(
55
+ source: S, origin: O, target: T,
72
56
  optionsObj?: Record<string, Merge3KeyOptions>,
73
57
  ): { conflict: boolean; result: O & S & T };
74
-
75
- export interface Merge3KeyOptions {
76
- /** List of sub-keys to compare (same as equal's topLevelIncludes) */
77
- keys?: string[];
78
- /** List of sub-keys to exclude from comparison */
79
- excludes?: string[];
80
- /** Whether to ignore array order */
81
- ignoreArrayIndex?: boolean;
82
- }
83
58
  ```
84
59
 
85
- ### `obj.omit`
60
+ **`Merge3KeyOptions`:**
86
61
 
87
- Exclude specific keys from object.
62
+ | Field | Type | Description |
63
+ |-------|------|-------------|
64
+ | `keys` | `string[]` | Sub-keys to compare |
65
+ | `excludes` | `string[]` | Sub-keys to exclude |
66
+ | `ignoreArrayIndex` | `boolean` | Ignore array order |
88
67
 
89
- ```typescript
90
- export function omit<T extends Record<string, unknown>, K extends keyof T>(item: T, omitKeys: K[]): Omit<T, K>;
91
- ```
68
+ Rules: origin -> source change wins; origin -> target change wins; both changed same way = ok; both changed differently = conflict (origin value kept).
92
69
 
93
- ### `obj.omitByFilter`
70
+ ### `obj.omit<T, K>(item, omitKeys): Omit<T, K>`
94
71
 
95
- Exclude keys matching condition.
72
+ Returns a new object excluding the specified keys.
96
73
 
97
74
  ```typescript
98
- export function omitByFilter<T extends Record<string, unknown>>(item: T, omitKeyFn: (key: keyof T) => boolean): T;
75
+ obj.omit({ a: 1, b: 2, c: 3 }, ["c"]); // { a: 1, b: 2 }
99
76
  ```
100
77
 
101
- ### `obj.pick`
78
+ ### `obj.omitByFilter<T>(item, omitKeyFn): T`
102
79
 
103
- Select specific keys from object.
80
+ Returns a new object excluding keys where the predicate returns `true`.
104
81
 
105
82
  ```typescript
106
- export function pick<T extends Record<string, unknown>, K extends keyof T>(item: T, pickKeys: K[]): Pick<T, K>;
83
+ obj.omitByFilter({ name: "a", _internal: "x" }, (k) => k.startsWith("_"));
107
84
  ```
108
85
 
109
- ### `obj.getChainValue`
86
+ ### `obj.pick<T, K>(item, pickKeys): Pick<T, K>`
110
87
 
111
- Get value by chain path (e.g., `"a.b[0].c"`).
88
+ Returns a new object with only the specified keys.
112
89
 
113
90
  ```typescript
114
- export function getChainValue(obj: unknown, chain: string): unknown;
115
- export function getChainValue(obj: unknown, chain: string, optional: true): unknown | undefined;
91
+ obj.pick({ a: 1, b: 2, c: 3 }, ["a", "b"]); // { a: 1, b: 2 }
116
92
  ```
117
93
 
118
- ### `obj.getChainValueByDepth`
94
+ ### `obj.getChainValue(obj, chain, optional?): unknown`
119
95
 
120
- Descend by the same key for depth levels.
96
+ Access a deeply nested value using a dot/bracket chain string.
121
97
 
122
98
  ```typescript
123
- export function getChainValueByDepth<TObject, TKey extends keyof TObject>(
124
- obj: TObject, key: TKey, depth: number,
125
- ): TObject[TKey];
126
- export function getChainValueByDepth<TObject, TKey extends keyof TObject>(
127
- obj: TObject, key: TKey, depth: number, optional: true,
128
- ): TObject[TKey] | undefined;
99
+ obj.getChainValue(data, "a.b[0].c");
100
+ obj.getChainValue(data, "a?.b?.c", true); // returns undefined if intermediate is missing
129
101
  ```
130
102
 
131
- ### `obj.setChainValue`
103
+ ### `obj.getChainValueByDepth<T, K>(obj, key, depth, optional?)`
132
104
 
133
- Set value by chain path.
105
+ Descend into the same key repeatedly by a given depth.
134
106
 
135
107
  ```typescript
136
- export function setChainValue(obj: unknown, chain: string, value: unknown): void;
108
+ obj.getChainValueByDepth({ parent: { parent: { name: "root" } } }, "parent", 2);
109
+ // { name: "root" }
137
110
  ```
138
111
 
139
- ### `obj.deleteChainValue`
112
+ ### `obj.setChainValue(obj, chain, value): void`
140
113
 
141
- Delete value by chain path.
114
+ Set a deeply nested value. Creates intermediate objects as needed.
142
115
 
143
116
  ```typescript
144
- export function deleteChainValue(obj: unknown, chain: string): void;
117
+ obj.setChainValue(data, "a.b[0].c", 42);
145
118
  ```
146
119
 
147
- ### `obj.clearUndefined`
120
+ ### `obj.deleteChainValue(obj, chain): void`
148
121
 
149
- Delete keys with `undefined` values from object. Mutates the original.
122
+ Delete a deeply nested value.
150
123
 
151
124
  ```typescript
152
- export function clearUndefined<T extends object>(obj: T): T;
125
+ obj.deleteChainValue(data, "a.b[0].c");
153
126
  ```
154
127
 
155
- ### `obj.clear`
128
+ ### `obj.clearUndefined<T>(obj): T`
156
129
 
157
- Delete all keys from object. Mutates the original.
130
+ Mutates: deletes keys with `undefined` values from an object.
158
131
 
159
- ```typescript
160
- export function clear<T extends Record<string, unknown>>(obj: T): Record<string, never>;
161
- ```
132
+ ### `obj.clear<T>(obj): Record<string, never>`
162
133
 
163
- ### `obj.nullToUndefined`
134
+ Mutates: deletes all keys from an object.
164
135
 
165
- Convert `null` to `undefined` recursively. Mutates the original.
136
+ ### `obj.nullToUndefined<T>(obj): T | undefined`
166
137
 
167
- ```typescript
168
- export function nullToUndefined<TObject>(obj: TObject): TObject | undefined;
169
- ```
138
+ Mutates: recursively converts all `null` values to `undefined`.
170
139
 
171
- ### `obj.unflatten`
140
+ ### `obj.unflatten(flatObj): Record<string, unknown>`
172
141
 
173
- Convert flattened object to nested object.
142
+ Converts a flat dotted-key object to a nested object.
174
143
 
175
144
  ```typescript
176
- export function unflatten(flatObj: Record<string, unknown>): Record<string, unknown>;
177
- // Example: unflatten({ "a.b.c": 1 }) => { a: { b: { c: 1 } } }
145
+ obj.unflatten({ "a.b.c": 1 }); // { a: { b: { c: 1 } } }
178
146
  ```
179
147
 
180
- ### `obj.keys`
148
+ ### `obj.keys<T>(obj): (keyof T)[]`
181
149
 
182
150
  Type-safe `Object.keys`.
183
151
 
184
- ```typescript
185
- export function keys<T extends object>(obj: T): (keyof T)[];
186
- ```
187
-
188
- ### `obj.entries`
152
+ ### `obj.entries<T>(obj): [keyof T, T[keyof T]][]`
189
153
 
190
154
  Type-safe `Object.entries`.
191
155
 
192
- ```typescript
193
- export function entries<T extends object>(obj: T): { [K in keyof T]: [K, T[K]] }[keyof T][];
194
- ```
195
-
196
- ### `obj.fromEntries`
156
+ ### `obj.fromEntries<T>(entries): object`
197
157
 
198
158
  Type-safe `Object.fromEntries`.
199
159
 
200
- ```typescript
201
- export function fromEntries<T extends [string, unknown]>(entryPairs: T[]): { [K in T[0]]: T[1] };
202
- ```
203
-
204
- ### `obj.map`
160
+ ### `obj.map<S, K, V>(obj, fn): Record<K, V>`
205
161
 
206
- Transform each entry of object and return new object.
162
+ Transform each entry of an object. The `fn` receives `(key, value)` and returns `[newKey | null, newValue]`. If `newKey` is `null`, the original key is preserved.
207
163
 
208
164
  ```typescript
209
- export function map<TSource extends object, TNewKey extends string, TNewValue>(
210
- obj: TSource,
211
- fn: (key: keyof TSource, value: TSource[keyof TSource]) => [TNewKey | null, TNewValue],
212
- ): Record<TNewKey | Extract<keyof TSource, string>, TNewValue>;
165
+ obj.map({ a: 1, b: 2 }, (k, v) => [null, v * 10]);
166
+ // { a: 10, b: 20 }
213
167
  ```
214
168
 
215
- **Example:**
169
+ ### Type Utilities (from `obj`)
216
170
 
217
- ```typescript
218
- const colors = { primary: "255, 0, 0", secondary: "0, 255, 0" };
171
+ #### `UndefToOptional<T>`
219
172
 
220
- // Transform only values (pass null for key to keep original)
221
- obj.map(colors, (key, rgb) => [null, `rgb(${rgb})`]);
222
- // { primary: "rgb(255, 0, 0)", secondary: "rgb(0, 255, 0)" }
173
+ Converts properties that include `undefined` in their type to optional properties.
223
174
 
224
- // Transform both keys and values
225
- obj.map(colors, (key, rgb) => [`${key}Light`, `rgb(${rgb})`]);
226
- // { primaryLight: "rgb(255, 0, 0)", secondaryLight: "rgb(0, 255, 0)" }
175
+ ```typescript
176
+ type UndefToOptional<T> = { [K in ...]?: T[K] } & { [K in ...]: T[K] };
227
177
  ```
228
178
 
229
- ### Type utilities from `obj`
179
+ #### `OptionalToUndef<T>`
230
180
 
231
- ```typescript
232
- /** Convert properties with undefined to optional */
233
- export type UndefToOptional<TObject> = {
234
- [K in keyof TObject as undefined extends TObject[K] ? K : never]?: TObject[K];
235
- } & { [K in keyof TObject as undefined extends TObject[K] ? never : K]: TObject[K] };
181
+ Converts optional properties to required properties with `| undefined`.
236
182
 
237
- /** Convert optional properties to required + undefined union */
238
- export type OptionalToUndef<TObject> = {
239
- [K in keyof TObject]-?: {} extends Pick<TObject, K> ? TObject[K] | undefined : TObject[K];
240
- };
183
+ ```typescript
184
+ type OptionalToUndef<T> = { [K in keyof T]-?: ... };
241
185
  ```
242
186
 
243
- ---
187
+ ## `str` -- String Utilities
244
188
 
245
- ## Namespace: `str`
189
+ ### `str.getKoreanSuffix(text, type): string`
246
190
 
247
- String utility functions. Source: `src/utils/str.ts`
248
-
249
- ### `str.getKoreanSuffix`
250
-
251
- Return the appropriate Korean particle based on the final consonant (jongseong).
191
+ Returns the appropriate Korean suffix based on whether the last character has a final consonant.
252
192
 
253
193
  ```typescript
254
- export function getKoreanSuffix(
255
- text: string,
256
- type: "을" | "은" | "이" | "와" | "랑" | "로" | "라",
257
- ): string;
194
+ function getKoreanSuffix(text: string, type: "을" | "은" | "이" | "와" | "랑" | "로" | "라"): string;
258
195
  ```
259
196
 
260
- | Type | With final consonant | Without final consonant |
261
- |------|---------------------|------------------------|
197
+ | Type | With final consonant | Without |
198
+ |------|---------------------|---------|
262
199
  | `"을"` | 을 | 를 |
263
200
  | `"은"` | 은 | 는 |
264
201
  | `"이"` | 이 | 가 |
@@ -267,364 +204,305 @@ export function getKoreanSuffix(
267
204
  | `"로"` | 으로 | 로 |
268
205
  | `"라"` | 이라 | 라 |
269
206
 
270
- ### `str.replaceFullWidth`
207
+ ### `str.replaceFullWidth(str): string`
271
208
 
272
- Convert full-width characters to half-width (A-Z, a-z, 0-9, space, parentheses).
209
+ Converts full-width characters to half-width (A-Z, a-z, 0-9, space, parentheses).
273
210
 
274
211
  ```typescript
275
- export function replaceFullWidth(str: string): string;
212
+ str.replaceFullWidth("A123"); // "A123"
276
213
  ```
277
214
 
278
- ### `str.toPascalCase`
215
+ ### `str.toPascalCase(str): string`
216
+
217
+ Converts to PascalCase. Handles `-`, `_`, `.` separators.
279
218
 
280
219
  ```typescript
281
- export function toPascalCase(str: string): string;
282
- // "hello-world" -> "HelloWorld"
283
- // "hello_world" -> "HelloWorld"
284
- // "hello.world" -> "HelloWorld"
220
+ str.toPascalCase("hello-world"); // "HelloWorld"
285
221
  ```
286
222
 
287
- ### `str.toCamelCase`
223
+ ### `str.toCamelCase(str): string`
224
+
225
+ Converts to camelCase.
288
226
 
289
227
  ```typescript
290
- export function toCamelCase(str: string): string;
291
- // "hello-world" -> "helloWorld"
292
- // "hello_world" -> "helloWorld"
293
- // "HelloWorld" -> "helloWorld"
228
+ str.toCamelCase("hello-world"); // "helloWorld"
294
229
  ```
295
230
 
296
- ### `str.toKebabCase`
231
+ ### `str.toKebabCase(str): string`
232
+
233
+ Converts to kebab-case from PascalCase/camelCase.
297
234
 
298
235
  ```typescript
299
- export function toKebabCase(str: string): string;
300
- // "HelloWorld" -> "hello-world"
301
- // "helloWorld" -> "hello-world"
236
+ str.toKebabCase("HelloWorld"); // "hello-world"
302
237
  ```
303
238
 
304
- ### `str.toSnakeCase`
239
+ ### `str.toSnakeCase(str): string`
240
+
241
+ Converts to snake_case from PascalCase/camelCase.
305
242
 
306
243
  ```typescript
307
- export function toSnakeCase(str: string): string;
308
- // "HelloWorld" -> "hello_world"
309
- // "helloWorld" -> "hello_world"
244
+ str.toSnakeCase("HelloWorld"); // "hello_world"
310
245
  ```
311
246
 
312
- ### `str.isNullOrEmpty`
247
+ ### `str.isNullOrEmpty(str): str is "" | undefined`
313
248
 
314
- Check if string is `undefined`, `null`, or empty (type guard).
249
+ Type guard that returns `true` if the string is `undefined`, `null`, or `""`.
315
250
 
316
251
  ```typescript
317
- export function isNullOrEmpty(str: string | undefined): str is "" | undefined;
252
+ if (!str.isNullOrEmpty(name)) {
253
+ // name is guaranteed to be a non-empty string
254
+ }
318
255
  ```
319
256
 
320
- ### `str.insert`
257
+ ### `str.insert(str, index, insertString): string`
321
258
 
322
- Insert a string at a specific position.
259
+ Inserts a string at the given position.
323
260
 
324
261
  ```typescript
325
- export function insert(str: string, index: number, insertString: string): string;
326
- // insert("Hello World", 5, ",") => "Hello, World"
262
+ str.insert("Hello World", 5, ","); // "Hello, World"
327
263
  ```
328
264
 
329
- ---
265
+ ## `num` -- Number Utilities
330
266
 
331
- ## Namespace: `num`
267
+ ### `num.parseInt(text): number | undefined`
332
268
 
333
- Number utility functions. Source: `src/utils/num.ts`
269
+ Parses a string to integer. Strips non-numeric characters first (keeps `0-9`, `-`, `.`). Returns `undefined` if unparseable.
334
270
 
335
- ### `num.parseInt`
271
+ ### `num.parseFloat(text): number | undefined`
336
272
 
337
- Parse string to integer. Removes non-numeric characters before parsing.
273
+ Parses a string to float. Strips non-numeric characters first.
338
274
 
339
- ```typescript
340
- export function parseInt(text: unknown): number | undefined;
341
- ```
275
+ ### `num.parseRoundedInt(text): number | undefined`
342
276
 
343
- ### `num.parseRoundedInt`
277
+ Parses to float then rounds to nearest integer.
344
278
 
345
- Parse string to float, then round and return integer.
279
+ ### `num.isNullOrEmpty(val): val is 0 | undefined`
346
280
 
347
- ```typescript
348
- export function parseRoundedInt(text: unknown): number | undefined;
349
- ```
281
+ Type guard that returns `true` if the value is `undefined`, `null`, or `0`.
350
282
 
351
- ### `num.parseFloat`
283
+ ### `num.format(val, digit?): string | undefined`
352
284
 
353
- Parse string to float. Removes non-numeric characters before parsing.
285
+ Formats a number with thousands separators and optional decimal control.
354
286
 
355
287
  ```typescript
356
- export function parseFloat(text: unknown): number | undefined;
288
+ function format(val: number, digit?: { max?: number; min?: number }): string;
289
+ function format(val: number | undefined, digit?: { max?: number; min?: number }): string | undefined;
357
290
  ```
358
291
 
359
- ### `num.isNullOrEmpty`
360
-
361
- Check `undefined`, `null`, `0` (type guard).
362
-
363
292
  ```typescript
364
- export function isNullOrEmpty(val: number | undefined): val is 0 | undefined;
293
+ num.format(1234.567, { max: 2 }); // "1,234.57"
294
+ num.format(1234, { min: 2 }); // "1,234.00"
365
295
  ```
366
296
 
367
- ### `num.format`
297
+ ## `bytes` -- Uint8Array Utilities
368
298
 
369
- Format number to string with thousand separators.
299
+ ### `bytes.concat(arrays): Bytes`
370
300
 
371
- ```typescript
372
- export function format(val: number, digit?: { max?: number; min?: number }): string;
373
- export function format(val: number | undefined, digit?: { max?: number; min?: number }): string | undefined;
374
- // num.format(1234.567, { max: 2 }) => "1,234.57"
375
- // num.format(1234, { min: 2 }) => "1,234.00"
376
- ```
301
+ Concatenates multiple `Uint8Array` instances into one.
377
302
 
378
- ---
303
+ ### `bytes.toHex(bytes): string`
379
304
 
380
- ## Namespace: `bytes`
305
+ Converts to lowercase hex string.
381
306
 
382
- Uint8Array utility functions. Source: `src/utils/bytes.ts`
307
+ ### `bytes.fromHex(hex): Bytes`
383
308
 
384
- ### `bytes.concat`
309
+ Converts hex string to `Uint8Array`. Throws `ArgumentError` on invalid input.
385
310
 
386
- Concatenate multiple Uint8Arrays.
311
+ ### `bytes.toBase64(bytes): string`
387
312
 
388
- ```typescript
389
- export function concat(arrays: Bytes[]): Bytes;
390
- ```
313
+ Converts to base64 string.
391
314
 
392
- ### `bytes.toHex`
315
+ ### `bytes.fromBase64(base64): Bytes`
393
316
 
394
- Convert to lowercase hex string.
317
+ Converts base64 string to `Uint8Array`. Throws `ArgumentError` on invalid input.
395
318
 
396
319
  ```typescript
397
- export function toHex(bytes: Bytes): string;
320
+ const a = new Uint8Array([1, 2]);
321
+ const b = new Uint8Array([3, 4]);
322
+ bytes.concat([a, b]); // Uint8Array([1, 2, 3, 4])
323
+ bytes.toHex(a); // "0102"
324
+ bytes.toBase64(a); // "AQI="
325
+ bytes.fromHex("ff00"); // Uint8Array([255, 0])
326
+ bytes.fromBase64("SGVsbG8="); // Uint8Array([72, 101, 108, 108, 111])
398
327
  ```
399
328
 
400
- ### `bytes.fromHex`
329
+ ## `path` -- Path Utilities
401
330
 
402
- Convert from hex string to Uint8Array.
331
+ POSIX-style path utilities (forward slash only). Designed for browser and Capacitor environments. Does not support Windows backslash paths.
403
332
 
404
- ```typescript
405
- export function fromHex(hex: string): Bytes;
406
- ```
333
+ ### `path.join(...segments): string`
407
334
 
408
- ### `bytes.toBase64`
335
+ Joins path segments with `/`.
409
336
 
410
- Convert Bytes to base64 string.
337
+ ### `path.basename(filePath, ext?): string`
411
338
 
412
- ```typescript
413
- export function toBase64(bytes: Bytes): string;
414
- ```
339
+ Extracts the file name from a path. Optionally strips the extension.
415
340
 
416
- ### `bytes.fromBase64`
341
+ ### `path.extname(filePath): string`
417
342
 
418
- Convert base64 string to Bytes.
343
+ Extracts the file extension (including the dot). Hidden files (e.g., `.gitignore`) return `""`.
419
344
 
420
345
  ```typescript
421
- export function fromBase64(base64: string): Bytes;
346
+ path.join("a", "b", "c.txt"); // "a/b/c.txt"
347
+ path.basename("/dir/file.txt"); // "file.txt"
348
+ path.basename("/dir/file.txt", ".txt"); // "file"
349
+ path.extname("/dir/file.txt"); // ".txt"
422
350
  ```
423
351
 
424
- ---
425
-
426
- ## Namespace: `path`
427
-
428
- Path utility functions. Replacement for Node.js `path` module (supports browser environments). POSIX style paths only (slash `/`).
429
-
430
- Source: `src/utils/path.ts`
352
+ ## `json` -- JSON Utilities
431
353
 
432
- ### `path.join`
354
+ JSON stringify/parse with support for custom types: DateTime, DateOnly, Time, Uuid, Set, Map, Error, Uint8Array, Date.
433
355
 
434
- Combine paths.
356
+ ### `json.stringify(obj, options?): string`
435
357
 
436
358
  ```typescript
437
- export function join(...segments: string[]): string;
359
+ function stringify(obj: unknown, options?: {
360
+ space?: string | number;
361
+ replacer?: (key: string | undefined, value: unknown) => unknown;
362
+ redactBytes?: boolean;
363
+ }): string;
438
364
  ```
439
365
 
440
- ### `path.basename`
366
+ | Option | Description |
367
+ |--------|-------------|
368
+ | `space` | Indentation (number of spaces or string) |
369
+ | `replacer` | Custom replacer called before built-in type conversion |
370
+ | `redactBytes` | If `true`, replaces `Uint8Array` content with `"__hidden__"` (for logging) |
441
371
 
442
- Extract filename.
372
+ Custom types are serialized as `{ __type__: "TypeName", data: ... }`. Circular references throw `TypeError`.
443
373
 
444
- ```typescript
445
- export function basename(filePath: string, ext?: string): string;
446
- ```
374
+ ### `json.parse<T>(json): T`
447
375
 
448
- ### `path.extname`
449
-
450
- Extract file extension. Hidden files (e.g., `.gitignore`) return empty string.
376
+ Restores custom types from `__type__` markers. All JSON `null` values are converted to `undefined` (simplysm null-free convention).
451
377
 
452
378
  ```typescript
453
- export function extname(filePath: string): string;
379
+ const data = json.parse<MyType>(jsonString);
454
380
  ```
455
381
 
456
- ---
457
-
458
- ## Namespace: `json`
459
-
460
- JSON serialization/deserialization supporting custom types (DateTime, DateOnly, Time, Uuid, Set, Map, Error, Uint8Array).
461
-
462
- Source: `src/utils/json.ts`
463
-
464
- ### `json.stringify`
382
+ ## `xml` -- XML Utilities
465
383
 
466
- Serialize object to JSON string. Supports custom types via `__type__` markers.
384
+ Built on `fast-xml-parser`.
467
385
 
468
- ```typescript
469
- export function stringify(
470
- obj: unknown,
471
- options?: {
472
- space?: string | number;
473
- replacer?: (key: string | undefined, value: unknown) => unknown;
474
- redactBytes?: boolean;
475
- },
476
- ): string;
477
- ```
386
+ ### `xml.parse(str, options?): unknown`
478
387
 
479
- ### `json.parse`
480
-
481
- Deserialize JSON string to object. Restores custom types from `__type__` markers. All JSON `null` values are converted to `undefined`.
388
+ Parses XML string to an object. Attributes are grouped under `$`, text nodes under `_`, child elements as arrays.
482
389
 
483
390
  ```typescript
484
- export function parse<TResult = unknown>(json: string): TResult;
391
+ function parse(str: string, options?: { stripTagPrefix?: boolean }): unknown;
485
392
  ```
486
393
 
487
- ---
488
-
489
- ## Namespace: `xml`
490
-
491
- XML conversion utility using fast-xml-parser.
492
-
493
- Source: `src/utils/xml.ts`
494
-
495
- ### `xml.parse`
496
-
497
- Parse XML string into an object. Attributes grouped in `$`, text nodes in `_`, child elements as arrays.
394
+ | Option | Description |
395
+ |--------|-------------|
396
+ | `stripTagPrefix` | Remove namespace prefixes from tag names |
498
397
 
499
398
  ```typescript
500
- export function parse(str: string, options?: { stripTagPrefix?: boolean }): unknown;
399
+ xml.parse('<root id="1"><item>hello</item></root>');
400
+ // { root: { $: { id: "1" }, item: [{ _: "hello" }] } }
501
401
  ```
502
402
 
503
- ### `xml.stringify`
403
+ ### `xml.stringify(obj, options?): string`
504
404
 
505
- Serialize object to XML string.
405
+ Converts an object to XML string.
506
406
 
507
407
  ```typescript
508
- export function stringify(obj: unknown, options?: XmlBuilderOptions): string;
408
+ function stringify(obj: unknown, options?: XmlBuilderOptions): string;
509
409
  ```
510
410
 
511
- ---
512
-
513
- ## Namespace: `wait`
411
+ ## `wait` -- Wait Utilities
514
412
 
515
- Wait utility functions. Source: `src/utils/wait.ts`
413
+ ### `wait.until(forwarder, milliseconds?, maxCount?): Promise<void>`
516
414
 
517
- ### `wait.until`
518
-
519
- Wait until a condition becomes true.
415
+ Polls a condition function until it returns `true`.
520
416
 
521
417
  ```typescript
522
- export async function until(
418
+ function until(
523
419
  forwarder: () => boolean | Promise<boolean>,
524
- milliseconds?: number,
525
- maxCount?: number,
420
+ milliseconds?: number, // default: 100ms
421
+ maxCount?: number, // default: unlimited
526
422
  ): Promise<void>;
527
423
  ```
528
424
 
529
- - `milliseconds`: Check interval (default: 100ms)
530
- - `maxCount`: Maximum number of attempts (`undefined` for unlimited)
531
- - Throws `TimeoutError` when maximum number of attempts is exceeded
425
+ Throws `TimeoutError` if `maxCount` is reached.
532
426
 
533
- ### `wait.time`
427
+ ### `wait.time(millisecond): Promise<void>`
534
428
 
535
- Wait for a specified amount of time.
429
+ Delays for the specified number of milliseconds.
536
430
 
537
431
  ```typescript
538
- export async function time(millisecond: number): Promise<void>;
432
+ await wait.time(1000); // wait 1 second
539
433
  ```
540
434
 
541
- ---
542
-
543
- ## Namespace: `transfer`
435
+ ## `transfer` -- Transferable Utilities
544
436
 
545
- Transferable conversion utility for Worker data transfer. Handles custom types that `structuredClone` does not support.
437
+ Encode/decode objects for Worker `postMessage` with zero-copy `ArrayBuffer` transfer. Handles custom types that `structuredClone` does not support.
546
438
 
547
- Source: `src/utils/transferable.ts`
439
+ ### `transfer.encode(obj): { result, transferList }`
548
440
 
549
- Supported types: Date, DateTime, DateOnly, Time, Uuid, RegExp, Error (including cause, code, detail), Uint8Array, Array, Map, Set, plain objects.
550
-
551
- ### `transfer.encode`
552
-
553
- Convert objects using Simplysm types to plain objects for Worker transfer.
441
+ Encodes an object for Worker transfer. Custom types become tagged objects. `Uint8Array` buffers are added to `transferList` for zero-copy transfer.
554
442
 
555
443
  ```typescript
556
- export function encode(obj: unknown): {
444
+ function encode(obj: unknown): {
557
445
  result: unknown;
558
- transferList: Transferable[];
446
+ transferList: ArrayBuffer[];
559
447
  };
560
448
  ```
561
449
 
562
- ### `transfer.decode`
450
+ Throws `TypeError` on circular references (with path info).
451
+
452
+ Supported types: Date, DateTime, DateOnly, Time, Uuid, RegExp, Error, Uint8Array, Array, Map, Set, plain objects.
563
453
 
564
- Convert serialized objects back to Simplysm types.
454
+ ### `transfer.decode(obj): unknown`
455
+
456
+ Decodes a previously encoded object, restoring custom types.
565
457
 
566
458
  ```typescript
567
- export function decode(obj: unknown): unknown;
459
+ function decode(obj: unknown): unknown;
568
460
  ```
569
461
 
570
- **Example:**
571
-
572
462
  ```typescript
463
+ // Sending
573
464
  const { result, transferList } = transfer.encode(data);
574
465
  worker.postMessage(result, transferList);
575
466
 
576
- // In worker:
467
+ // Receiving
577
468
  const decoded = transfer.decode(event.data);
578
469
  ```
579
470
 
580
- ---
581
-
582
- ## Namespace: `err`
583
-
584
- Error utility. Source: `src/utils/error.ts`
471
+ ## `err` -- Error Utilities
585
472
 
586
- ### `err.message`
473
+ ### `err.message(err): string`
587
474
 
588
- Extract message from unknown type error. Returns `message` property for `Error` instances, otherwise `String(err)`.
475
+ Extracts a message string from an `unknown` error value.
589
476
 
590
477
  ```typescript
591
- export function message(err: unknown): string;
478
+ function message(err: unknown): string;
592
479
  ```
593
480
 
594
- ---
481
+ Returns `err.message` if `err` is an `Error`, otherwise `String(err)`.
595
482
 
596
- ## Namespace: `dt`
483
+ ## `dt` -- Date Format Utilities
597
484
 
598
- Date format utilities. Source: `src/utils/date-format.ts`
485
+ ### `dt.format(formatString, args): string`
599
486
 
600
- ### `dt.normalizeMonth`
601
-
602
- Normalize year/month/day when setting month. Adjusts year for out-of-range months, clamps day to last day of month.
487
+ Formats date/time components using C#-style format strings.
603
488
 
604
489
  ```typescript
605
- export function normalizeMonth(year: number, month: number, day: number): DtNormalizedMonth;
606
-
607
- export interface DtNormalizedMonth {
608
- year: number;
609
- month: number;
610
- day: number;
611
- }
490
+ function format(formatString: string, args: {
491
+ year?: number;
492
+ month?: number;
493
+ day?: number;
494
+ hour?: number;
495
+ minute?: number;
496
+ second?: number;
497
+ millisecond?: number;
498
+ timezoneOffsetMinutes?: number;
499
+ }): string;
612
500
  ```
613
501
 
614
- ### `dt.convert12To24`
502
+ **Format patterns:**
615
503
 
616
- Convert 12-hour format to 24-hour format.
617
-
618
- ```typescript
619
- export function convert12To24(rawHour: number, isPM: boolean): number;
620
- ```
621
-
622
- ### `dt.format`
623
-
624
- Convert date/time components to string according to format string. Supports C#-style format specifiers:
625
-
626
- | Format | Description | Example |
627
- |--------|-------------|---------|
504
+ | Pattern | Description | Example |
505
+ |---------|-------------|---------|
628
506
  | `yyyy` | 4-digit year | 2024 |
629
507
  | `yy` | 2-digit year | 24 |
630
508
  | `MM` | Zero-padded month | 01-12 |
@@ -633,125 +511,131 @@ Convert date/time components to string according to format string. Supports C#-s
633
511
  | `dd` | Zero-padded day | 01-31 |
634
512
  | `d` | Day | 1-31 |
635
513
  | `tt` | AM/PM | AM, PM |
636
- | `hh` / `h` | 12-hour (zero-padded / plain) | 01-12 / 1-12 |
637
- | `HH` / `H` | 24-hour (zero-padded / plain) | 00-23 / 0-23 |
638
- | `mm` / `m` | Minute (zero-padded / plain) | 00-59 / 0-59 |
639
- | `ss` / `s` | Second (zero-padded / plain) | 00-59 / 0-59 |
640
- | `fff` / `ff` / `f` | Milliseconds (3/2/1 digits) | 000-999 |
641
- | `zzz` / `zz` / `z` | Timezone offset | +09:00 / +09 / +9 |
514
+ | `hh` | Zero-padded 12-hour | 01-12 |
515
+ | `h` | 12-hour | 1-12 |
516
+ | `HH` | Zero-padded 24-hour | 00-23 |
517
+ | `H` | 24-hour | 0-23 |
518
+ | `mm` | Zero-padded minutes | 00-59 |
519
+ | `m` | Minutes | 0-59 |
520
+ | `ss` | Zero-padded seconds | 00-59 |
521
+ | `s` | Seconds | 0-59 |
522
+ | `fff` | Milliseconds (3 digits) | 000-999 |
523
+ | `ff` | Milliseconds (2 digits) | 00-99 |
524
+ | `f` | Milliseconds (1 digit) | 0-9 |
525
+ | `zzz` | Timezone offset | +09:00 |
526
+ | `zz` | Timezone offset (hours) | +09 |
527
+ | `z` | Timezone offset (short) | +9 |
528
+
529
+ ### `dt.normalizeMonth(year, month, day): DtNormalizedMonth`
530
+
531
+ Normalizes month overflow/underflow and adjusts day to fit the target month.
642
532
 
643
533
  ```typescript
644
- export function format(
645
- formatString: string,
646
- args: {
647
- year?: number;
648
- month?: number;
649
- day?: number;
650
- hour?: number;
651
- minute?: number;
652
- second?: number;
653
- millisecond?: number;
654
- timezoneOffsetMinutes?: number;
655
- },
656
- ): string;
534
+ dt.normalizeMonth(2025, 13, 15); // { year: 2026, month: 1, day: 15 }
535
+ dt.normalizeMonth(2025, 2, 31); // { year: 2025, month: 2, day: 28 }
657
536
  ```
658
537
 
659
- ---
538
+ ### `dt.convert12To24(rawHour, isPM): number`
539
+
540
+ Converts 12-hour format to 24-hour format.
660
541
 
661
- ## Namespace: `primitive`
542
+ ## `primitive` -- Primitive Type Utilities
662
543
 
663
- Primitive type inference. Source: `src/utils/primitive.ts`
544
+ ### `primitive.typeStr(value): PrimitiveTypeStr`
664
545
 
665
- ### `primitive.typeStr`
546
+ Returns the `PrimitiveTypeStr` for a given value at runtime.
666
547
 
667
- Infer `PrimitiveTypeStr` from a value at runtime.
548
+ ```typescript
549
+ function typeStr(value: PrimitiveTypeMap[PrimitiveTypeStr]): PrimitiveTypeStr;
550
+ ```
668
551
 
669
552
  ```typescript
670
- export function typeStr(value: PrimitiveTypeMap[PrimitiveTypeStr]): PrimitiveTypeStr;
671
- // primitive.typeStr("hello") => "string"
672
- // primitive.typeStr(new DateTime()) => "DateTime"
673
- // primitive.typeStr(new Uint8Array()) => "Bytes"
553
+ primitive.typeStr("hello"); // "string"
554
+ primitive.typeStr(123); // "number"
555
+ primitive.typeStr(true); // "boolean"
556
+ primitive.typeStr(new DateTime()); // "DateTime"
557
+ primitive.typeStr(new Uint8Array()); // "Bytes"
674
558
  ```
675
559
 
676
- ---
560
+ Throws `ArgumentError` for unsupported types.
677
561
 
678
- ## Direct Exports: Template Tag Functions
562
+ ## Template String Tags
679
563
 
680
- Template string tag functions for IDE code highlighting support. Actual behavior is string concatenation with indent normalization (leading/trailing blank lines removed, common indentation stripped).
564
+ Template tag functions for IDE syntax highlighting. All perform string interpolation + indent normalization (strips common leading whitespace).
681
565
 
682
- Source: `src/utils/template-strings.ts`
566
+ ### `js`, `ts`, `html`, `tsql`, `mysql`, `pgsql`
683
567
 
684
568
  ```typescript
685
- export function js(strings: TemplateStringsArray, ...values: unknown[]): string;
686
- export function ts(strings: TemplateStringsArray, ...values: unknown[]): string;
687
- export function html(strings: TemplateStringsArray, ...values: unknown[]): string;
688
- export function tsql(strings: TemplateStringsArray, ...values: unknown[]): string;
689
- export function mysql(strings: TemplateStringsArray, ...values: unknown[]): string;
690
- export function pgsql(strings: TemplateStringsArray, ...values: unknown[]): string;
569
+ function js(strings: TemplateStringsArray, ...values: unknown[]): string;
570
+ function ts(strings: TemplateStringsArray, ...values: unknown[]): string;
571
+ function html(strings: TemplateStringsArray, ...values: unknown[]): string;
572
+ function tsql(strings: TemplateStringsArray, ...values: unknown[]): string;
573
+ function mysql(strings: TemplateStringsArray, ...values: unknown[]): string;
574
+ function pgsql(strings: TemplateStringsArray, ...values: unknown[]): string;
691
575
  ```
692
576
 
693
- **Example:**
694
-
695
577
  ```typescript
696
- const query = tsql`
697
- SELECT TOP 10 *
698
- FROM Users
699
- WHERE Name LIKE '%${keyword}%'
578
+ const code = ts`
579
+ interface User {
580
+ name: string;
581
+ age: number;
582
+ }
700
583
  `;
584
+ // Result: "interface User {\n name: string;\n age: number;\n}"
701
585
  ```
702
586
 
703
- ---
704
-
705
- ## Direct Export: `ZipArchive`
706
-
707
- ZIP archive processing class. Handles reading, writing, compression, and decompression of ZIP files. Uses internal caching to prevent duplicate decompression. Supports `await using` (`Symbol.asyncDispose`).
587
+ ## `ZipArchive`
708
588
 
709
- Source: `src/utils/zip.ts`
589
+ ZIP file read/write/compress/extract. Supports `await using` syntax (`Symbol.asyncDispose`).
710
590
 
711
591
  ```typescript
712
- export class ZipArchive {
713
- /**
714
- * @param data ZIP data (omit to create a new archive)
715
- */
592
+ class ZipArchive {
716
593
  constructor(data?: Blob | Bytes);
717
594
 
718
- /** Extract all files with optional progress callback */
719
- async extractAll(progressCallback?: (progress: ZipArchiveProgress) => void): Promise<Map<string, Bytes | undefined>>;
720
-
721
- /** Extract specific file */
722
595
  async get(fileName: string): Promise<Bytes | undefined>;
723
-
724
- /** Check if file exists */
725
596
  async exists(fileName: string): Promise<boolean>;
726
-
727
- /** Write file (store in cache) */
728
597
  write(fileName: string, bytes: Bytes): void;
729
-
730
- /** Compress cached files to ZIP */
598
+ async extractAll(progressCallback?: (progress: ZipArchiveProgress) => void): Promise<Map<string, Bytes | undefined>>;
731
599
  async compress(): Promise<Bytes>;
732
-
733
- /** Close reader and clear cache */
734
600
  async close(): Promise<void>;
735
-
736
601
  async [Symbol.asyncDispose](): Promise<void>;
737
602
  }
603
+ ```
604
+
605
+ ### `ZipArchiveProgress`
738
606
 
739
- export interface ZipArchiveProgress {
607
+ ```typescript
608
+ interface ZipArchiveProgress {
740
609
  fileName: string;
741
610
  totalSize: number;
742
611
  extractedSize: number;
743
612
  }
744
613
  ```
745
614
 
746
- **Example:**
615
+ ### Methods
616
+
617
+ | Method | Description |
618
+ |--------|-------------|
619
+ | `get(fileName)` | Extract a single file. Cached after first extraction |
620
+ | `exists(fileName)` | Check if a file exists in the archive |
621
+ | `write(fileName, bytes)` | Write a file to the cache (for compression) |
622
+ | `extractAll(callback?)` | Extract all files with optional progress reporting |
623
+ | `compress()` | Compress all cached files into a ZIP `Uint8Array` |
624
+ | `close()` | Close the reader and clear cache |
747
625
 
748
626
  ```typescript
749
- // Read
627
+ // Reading a ZIP
750
628
  await using archive = new ZipArchive(zipBytes);
751
629
  const content = await archive.get("file.txt");
752
630
 
753
- // Create
631
+ // Creating a ZIP
754
632
  await using archive = new ZipArchive();
755
633
  archive.write("file.txt", textBytes);
634
+ archive.write("data.json", jsonBytes);
756
635
  const zipBytes = await archive.compress();
636
+
637
+ // Extracting all with progress
638
+ const files = await archive.extractAll((p) => {
639
+ console.log(`${p.fileName}: ${p.extractedSize}/${p.totalSize}`);
640
+ });
757
641
  ```