@simplysm/core-common 14.0.4 → 14.0.6

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.
@@ -1,96 +1,98 @@
1
- # Array / Set / Map Extensions
1
+ # Array Extensions
2
2
 
3
- Prototype extensions added to `Array`, `Set`, and `Map` at import time. Importing `@simplysm/core-common` automatically installs these extensions.
3
+ Prototype extensions added to both `Array` and `ReadonlyArray`. Available after importing `@simplysm/core-common`.
4
4
 
5
- ## Array -- Readonly Extensions
5
+ Also exports helper functions and result types.
6
6
 
7
- These methods return new arrays/values without mutating the original.
7
+ ## ReadonlyArray Extensions
8
8
 
9
- ### `single(predicate?)`
9
+ These methods do not mutate the original array.
10
10
 
11
- Returns the single matching element, or `undefined` if none. Throws `ArgumentError` if more than one element matches.
11
+ ### `single`
12
+
13
+ Return the single element matching the predicate. Returns `undefined` if no match. Throws `ArgumentError` if more than one element matches.
12
14
 
13
15
  ```typescript
14
16
  single(predicate?: (item: T, index: number) => boolean): T | undefined;
15
17
  ```
16
18
 
17
- ### `first(predicate?)`
19
+ ### `first`
18
20
 
19
- Returns the first matching element, or `undefined` if none.
21
+ Return the first element, or the first element matching the predicate.
20
22
 
21
23
  ```typescript
22
24
  first(predicate?: (item: T, index: number) => boolean): T | undefined;
23
25
  ```
24
26
 
25
- ### `last(predicate?)`
27
+ ### `last`
26
28
 
27
- Returns the last matching element, or `undefined` if none.
29
+ Return the last element, or the last element matching the predicate.
28
30
 
29
31
  ```typescript
30
32
  last(predicate?: (item: T, index: number) => boolean): T | undefined;
31
33
  ```
32
34
 
33
- ### `filterAsync(predicate)`
35
+ ### `filterExists`
34
36
 
35
- Async sequential filter.
37
+ Remove all `null` and `undefined` elements.
36
38
 
37
39
  ```typescript
38
- filterAsync(predicate: (item: T, index: number) => Promise<boolean>): Promise<T[]>;
40
+ filterExists(): NonNullable<T>[];
39
41
  ```
40
42
 
41
- ### `filterExists()`
43
+ ### `ofType`
42
44
 
43
- Removes `null` and `undefined` elements. Returns `NonNullable<T>[]`.
45
+ Filter elements by type. Accepts a `PrimitiveTypeStr` (e.g., `"string"`, `"DateTime"`) or a constructor function.
44
46
 
45
47
  ```typescript
46
- filterExists(): NonNullable<T>[];
48
+ ofType<TKey extends PrimitiveTypeStr>(type: TKey): Extract<T, PrimitiveTypeMap[TKey]>[];
49
+ ofType<TNarrow extends T>(type: Type<TNarrow>): TNarrow[];
47
50
  ```
48
51
 
49
- ### `ofType(type)`
52
+ ### `filterAsync`
50
53
 
51
- Filters elements by type. Accepts a `PrimitiveTypeStr` (`"string"`, `"number"`, `"boolean"`, `"DateTime"`, `"DateOnly"`, `"Time"`, `"Uuid"`, `"Bytes"`) or a constructor function.
54
+ Async sequential filter. Evaluates the predicate for each element in order.
52
55
 
53
56
  ```typescript
54
- ofType<K extends PrimitiveTypeStr>(type: K): Extract<T, PrimitiveTypeMap[K]>[];
55
- ofType<N extends T>(type: Type<N>): N[];
57
+ filterAsync(predicate: (item: T, index: number) => Promise<boolean>): Promise<T[]>;
56
58
  ```
57
59
 
58
- ### `mapAsync(selector)`
60
+ ### `mapAsync`
59
61
 
60
- Async sequential map.
62
+ Async sequential map. Evaluates the selector for each element in order.
61
63
 
62
64
  ```typescript
63
65
  mapAsync<R>(selector: (item: T, index: number) => Promise<R>): Promise<R[]>;
64
66
  ```
65
67
 
66
- ### `mapMany(selector?)`
68
+ ### `mapMany`
67
69
 
68
- Maps then flattens one level. Removes `null`/`undefined` from results.
70
+ Flatten a nested array, or map then flatten. Filters out null/undefined from the result.
69
71
 
70
72
  ```typescript
71
73
  mapMany(): T extends readonly (infer U)[] ? U[] : T;
72
74
  mapMany<R>(selector: (item: T, index: number) => R[]): R[];
73
75
  ```
74
76
 
75
- ### `mapManyAsync(selector?)`
77
+ ### `mapManyAsync`
76
78
 
77
- Async version of `mapMany`.
79
+ Async map then flatten.
78
80
 
79
81
  ```typescript
80
82
  mapManyAsync<R>(selector: (item: T, index: number) => Promise<R[]>): Promise<R[]>;
81
83
  ```
82
84
 
83
- ### `parallelAsync(fn)`
85
+ ### `parallelAsync`
84
86
 
85
- Runs `fn` for all items in parallel via `Promise.all`. If any rejects, the entire result rejects.
87
+ Parallel async map using `Promise.all`. All promises run concurrently.
86
88
 
87
89
  ```typescript
88
90
  parallelAsync<R>(fn: (item: T, index: number) => Promise<R>): Promise<R[]>;
89
91
  ```
90
92
 
91
- ### `groupBy(keySelector, valueSelector?)`
93
+ ### `groupBy`
92
94
 
93
- Groups items by key. Supports both primitive keys (O(n) via Map) and object keys (O(n^2) via deep equality).
95
+ Group elements by a key selector. Supports object keys via deep comparison (O(n^2)). Primitive keys use Map-based O(n) lookup.
94
96
 
95
97
  ```typescript
96
98
  groupBy<K>(keySelector: (item: T, index: number) => K): { key: K; values: T[] }[];
@@ -100,9 +102,9 @@ groupBy<K, V>(
100
102
  ): { key: K; values: V[] }[];
101
103
  ```
102
104
 
103
- ### `toMap(keySelector, valueSelector?)`
105
+ ### `toMap`
104
106
 
105
- Converts array to `Map`. Throws `ArgumentError` on duplicate keys.
107
+ Convert to a `Map`. Throws `ArgumentError` on duplicate keys.
106
108
 
107
109
  ```typescript
108
110
  toMap<K>(keySelector: (item: T, index: number) => K): Map<K, T>;
@@ -112,7 +114,7 @@ toMap<K, V>(
112
114
  ): Map<K, V>;
113
115
  ```
114
116
 
115
- ### `toMapAsync(keySelector, valueSelector?)`
117
+ ### `toMapAsync`
116
118
 
117
119
  Async version of `toMap`.
118
120
 
@@ -124,9 +126,9 @@ toMapAsync<K, V>(
124
126
  ): Promise<Map<K, V>>;
125
127
  ```
126
128
 
127
- ### `toArrayMap(keySelector, valueSelector?)`
129
+ ### `toArrayMap`
128
130
 
129
- Converts array to `Map<K, V[]>` (groups values into arrays per key).
131
+ Convert to a `Map<K, V[]>`. Multiple items with the same key are grouped into an array.
130
132
 
131
133
  ```typescript
132
134
  toArrayMap<K>(keySelector: (item: T, index: number) => K): Map<K, T[]>;
@@ -136,9 +138,9 @@ toArrayMap<K, V>(
136
138
  ): Map<K, V[]>;
137
139
  ```
138
140
 
139
- ### `toSetMap(keySelector, valueSelector?)`
141
+ ### `toSetMap`
140
142
 
141
- Converts array to `Map<K, Set<V>>`.
143
+ Convert to a `Map<K, Set<V>>`.
142
144
 
143
145
  ```typescript
144
146
  toSetMap<K>(keySelector: (item: T, index: number) => K): Map<K, Set<T>>;
@@ -148,9 +150,9 @@ toSetMap<K, V>(
148
150
  ): Map<K, Set<V>>;
149
151
  ```
150
152
 
151
- ### `toMapValues(keySelector, valueSelector)`
153
+ ### `toMapValues`
152
154
 
153
- Groups by key, then applies `valueSelector` to the group array to produce the final value.
155
+ Group by key, then aggregate each group's items using a value selector.
154
156
 
155
157
  ```typescript
156
158
  toMapValues<K, V>(
@@ -159,9 +161,9 @@ toMapValues<K, V>(
159
161
  ): Map<K, V>;
160
162
  ```
161
163
 
162
- ### `toObject(keySelector, valueSelector?)`
164
+ ### `toObject`
163
165
 
164
- Converts array to a plain object. Throws `ArgumentError` on duplicate keys.
166
+ Convert to a plain object `Record<string, V>`. Throws `ArgumentError` on duplicate keys.
165
167
 
166
168
  ```typescript
167
169
  toObject(keySelector: (item: T, index: number) => string): Record<string, T>;
@@ -171,68 +173,70 @@ toObject<V>(
171
173
  ): Record<string, V>;
172
174
  ```
173
175
 
174
- ### `toTree(keyProp, parentKey)`
176
+ ### `toTree`
175
177
 
176
- Converts a flat array to a tree structure. Items where `parentKey` is `null`/`undefined` become roots. O(n) complexity.
178
+ Convert a flat array to a tree structure. Items where `parentKey` is null/undefined become root nodes. Uses O(n) Map-based indexing internally.
177
179
 
178
180
  ```typescript
179
181
  toTree<K extends keyof T, P extends keyof T>(keyProp: K, parentKey: P): TreeArray<T>[];
180
182
  ```
181
183
 
182
- ```typescript
183
- const items = [
184
- { id: 1, parentId: undefined, name: "root" },
185
- { id: 2, parentId: 1, name: "child" },
186
- ];
187
- const tree = items.toTree("id", "parentId");
188
- // [{ id: 1, name: "root", children: [{ id: 2, name: "child", children: [] }] }]
189
- ```
190
-
191
- ### `distinct(options?)`
184
+ ### `distinct`
192
185
 
193
- Returns a new array with duplicates removed.
186
+ Remove duplicates (returns a new array).
194
187
 
195
188
  ```typescript
196
- distinct(options?: boolean | {
197
- matchAddress?: boolean;
198
- keyFn?: (item: T) => string | number;
199
- }): T[];
189
+ distinct(
190
+ options?: boolean | { matchAddress?: boolean; keyFn?: (item: T) => string | number },
191
+ ): T[];
200
192
  ```
201
193
 
202
194
  | Option | Description |
203
195
  |--------|-------------|
204
- | `true` or `{ matchAddress: true }` | Use reference equality (Set-based, O(n)) |
205
- | `{ keyFn }` | Use custom key function (O(n)) |
206
- | No options | Deep equality comparison (O(n^2) for objects) |
196
+ | `true` or `{ matchAddress: true }` | Reference equality (Set-based, O(n)) |
197
+ | `{ keyFn }` | Custom key function (O(n)) |
198
+ | Default (no options) | Deep equality for objects (O(n^2)), type-based for primitives (O(n)) |
207
199
 
208
- ### `orderBy(selector?)` / `orderByDesc(selector?)`
200
+ ### `orderBy`
209
201
 
210
- Returns a sorted copy. Supports `string`, `number`, `DateTime`, `DateOnly`, `Time`.
202
+ Sort ascending (returns a new array). Supports `string`, `number`, `DateTime`, `DateOnly`, `Time`.
211
203
 
212
204
  ```typescript
213
205
  orderBy(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[];
206
+ ```
207
+
208
+ ### `orderByDesc`
209
+
210
+ Sort descending (returns a new array).
211
+
212
+ ```typescript
214
213
  orderByDesc(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[];
215
214
  ```
216
215
 
217
- ### `diffs(target, options?)`
216
+ ### `diffs`
218
217
 
219
- Compares two arrays and returns INSERT/DELETE/UPDATE diff results.
218
+ Compare this array (source) with a target array. Returns a list of insert/delete/update operations.
220
219
 
221
220
  ```typescript
222
- diffs<P>(target: P[], options?: {
223
- keys?: string[];
224
- excludes?: string[];
225
- }): ArrayDiffsResult<T, P>[];
221
+ diffs<P>(target: P[]): ArrayDiffsResult<T, P>[];
222
+ diffs<P extends Record<string, unknown>>(
223
+ target: P[],
224
+ options: { keys: string[]; excludes?: string[] },
225
+ ): ArrayDiffsResult<T, P>[];
226
+ diffs<P extends Record<string, unknown>>(
227
+ target: P[],
228
+ options: { excludes: string[] },
229
+ ): ArrayDiffsResult<T, P>[];
226
230
  ```
227
231
 
228
- Result items:
229
- - `{ source: T, target: undefined }` -- item exists only in source (DELETE)
230
- - `{ source: undefined, target: P }` -- item exists only in target (INSERT)
231
- - `{ source: T, target: P }` -- item exists in both but differs (UPDATE)
232
+ | Option | Description |
233
+ |--------|-------------|
234
+ | `keys` | Properties to use for matching source to target items |
235
+ | `excludes` | Properties to ignore in equality comparison |
232
236
 
233
- ### `oneWayDiffs(orgItems, keyPropNameOrGetValFn, options?)`
237
+ ### `oneWayDiffs`
234
238
 
235
- One-way diff: compares current array against original items.
239
+ One-way diff: compare this array against original items. Returns create/update/same results.
236
240
 
237
241
  ```typescript
238
242
  oneWayDiffs<K extends keyof T>(
@@ -242,160 +246,124 @@ oneWayDiffs<K extends keyof T>(
242
246
  ): ArrayOneWayDiffResult<T>[];
243
247
  ```
244
248
 
245
- Result types: `"create"`, `"update"`, `"same"` (only if `includeSame: true`).
249
+ ### `merge`
246
250
 
247
- ### `merge(target, options?)`
248
-
249
- Merges two arrays using deep merge on matched items and appends unmatched target items.
251
+ Merge this array with a target array. Matched items are deep-merged; unmatched target items are appended.
250
252
 
251
253
  ```typescript
252
- merge<P>(target: P[], options?: {
253
- keys?: string[];
254
- excludes?: string[];
255
- }): (T | P | (T & P))[];
254
+ merge<P>(target: P[]): (T | P | (T & P))[];
255
+ merge<P extends Record<string, unknown>>(
256
+ target: P[],
257
+ options: { keys: string[]; excludes?: string[] },
258
+ ): (T | P | (T & P))[];
259
+ merge<P extends Record<string, unknown>>(
260
+ target: P[],
261
+ options: { excludes: string[] },
262
+ ): (T | P | (T & P))[];
256
263
  ```
257
264
 
258
- ### `sum(selector?)`
265
+ ### `sum`
259
266
 
260
- Returns the sum of elements. Returns `0` for empty arrays.
267
+ Sum of elements. If no selector is provided, elements must be numbers.
261
268
 
262
269
  ```typescript
263
270
  sum(selector?: (item: T, index: number) => number): number;
264
271
  ```
265
272
 
266
- ### `min(selector?)` / `max(selector?)`
267
-
268
- Returns the minimum/maximum element. Returns `undefined` for empty arrays.
273
+ Returns `0` for empty arrays.
269
274
 
270
- ```typescript
271
- min(selector?: (item: T, index: number) => string | number): string | number | undefined;
272
- max(selector?: (item: T, index: number) => string | number): string | number | undefined;
273
- ```
275
+ ### `min`
274
276
 
275
- ### `shuffle()`
276
-
277
- Returns a new array with elements in random order (Fisher-Yates algorithm).
277
+ Minimum element or minimum selected value.
278
278
 
279
279
  ```typescript
280
- shuffle(): T[];
280
+ min(): T extends number | string ? T | undefined : never;
281
+ min<P extends number | string>(selector?: (item: T, index: number) => P): P | undefined;
281
282
  ```
282
283
 
283
- ## Array -- Mutable Extensions
284
-
285
- These methods mutate the original array in place.
284
+ ### `max`
286
285
 
287
- ### `distinctThis(options?)`
288
-
289
- Removes duplicates from the original array in place. Same options as `distinct()`.
286
+ Maximum element or maximum selected value.
290
287
 
291
288
  ```typescript
292
- distinctThis(options?: boolean | {
293
- matchAddress?: boolean;
294
- keyFn?: (item: T) => string | number;
295
- }): T[];
289
+ max(): T extends number | string ? T | undefined : never;
290
+ max<P extends number | string>(selector?: (item: T, index: number) => P): P | undefined;
296
291
  ```
297
292
 
298
- ### `orderByThis(selector?)` / `orderByDescThis(selector?)`
293
+ ### `shuffle`
299
294
 
300
- Sorts the original array in place.
295
+ Return a new array with elements in random order (Fisher-Yates algorithm).
301
296
 
302
297
  ```typescript
303
- orderByThis(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[];
304
- orderByDescThis(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[];
298
+ shuffle(): T[];
305
299
  ```
306
300
 
307
- ### `insert(index, ...items)`
301
+ ---
308
302
 
309
- Inserts items at the given index in place.
303
+ ## Mutable Array Extensions
310
304
 
311
- ```typescript
312
- insert(index: number, ...items: T[]): this;
313
- ```
305
+ These methods mutate the original array in-place.
314
306
 
315
- ### `remove(itemOrSelector)`
307
+ ### `distinctThis`
316
308
 
317
- Removes matching items in place.
309
+ Remove duplicates in-place. Same options as `distinct`.
318
310
 
319
311
  ```typescript
320
- remove(item: T): this;
321
- remove(selector: (item: T, index: number) => boolean): this;
312
+ distinctThis(
313
+ options?: boolean | { matchAddress?: boolean; keyFn?: (item: T) => string | number },
314
+ ): T[];
322
315
  ```
323
316
 
324
- ### `toggle(item)`
317
+ ### `orderByThis`
325
318
 
326
- Toggles an item: removes if present, adds if absent.
319
+ Sort ascending in-place.
327
320
 
328
321
  ```typescript
329
- toggle(item: T): this;
322
+ orderByThis(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[];
330
323
  ```
331
324
 
332
- ### `clear()`
325
+ ### `orderByDescThis`
333
326
 
334
- Removes all items from the array.
327
+ Sort descending in-place.
335
328
 
336
329
  ```typescript
337
- clear(): this;
330
+ orderByDescThis(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[];
338
331
  ```
339
332
 
340
- ## Set Extensions
333
+ ### `insert`
341
334
 
342
- ### `adds(...values)`
343
-
344
- Adds multiple values at once. Returns `this` for chaining.
335
+ Insert items at a given index. Mutates the array.
345
336
 
346
337
  ```typescript
347
- adds(...values: T[]): this;
338
+ insert(index: number, ...items: T[]): this;
348
339
  ```
349
340
 
350
- ### `toggle(value, addOrDel?)`
341
+ ### `remove`
351
342
 
352
- Toggles a value in the Set. Optionally force add or delete.
343
+ Remove items by value or predicate. Mutates the array.
353
344
 
354
345
  ```typescript
355
- toggle(value: T, addOrDel?: "add" | "del"): this;
356
- ```
357
-
358
- | Parameter | Type | Description |
359
- |-----------|------|-------------|
360
- | `value` | `T` | Value to toggle |
361
- | `addOrDel` | `"add" \| "del" \| undefined` | Force add or delete. Omit for auto-toggle |
362
-
363
- ```typescript
364
- const set = new Set([1, 2, 3]);
365
- set.toggle(2); // removes 2 -> {1, 3}
366
- set.toggle(4); // adds 4 -> {1, 3, 4}
367
- set.toggle(5, "add"); // force add -> {1, 3, 4, 5}
368
- set.toggle(5, "del"); // force del -> {1, 3, 4}
346
+ remove(item: T): this;
347
+ remove(selector: (item: T, index: number) => boolean): this;
369
348
  ```
370
349
 
371
- ## Map Extensions
350
+ ### `toggle`
372
351
 
373
- ### `getOrCreate(key, newValue)`
374
-
375
- Returns the value for `key`. If the key does not exist, creates it with `newValue` (or calls `newValue` as a factory function if it is a function).
352
+ Toggle an item: remove if present, add (push) if absent.
376
353
 
377
354
  ```typescript
378
- getOrCreate(key: K, newValue: V): V;
379
- getOrCreate(key: K, newValueFn: () => V): V;
380
- ```
381
-
382
- **Note:** If `V` is a function type, wrap it in a factory to avoid it being called:
383
- ```typescript
384
- fnMap.getOrCreate("key", () => myFunction);
355
+ toggle(item: T): this;
385
356
  ```
386
357
 
387
- ### `update(key, updateFn)`
358
+ ### `clear`
388
359
 
389
- Updates a key's value using a function. If the key does not exist, `updateFn` receives `undefined`.
360
+ Remove all items from the array.
390
361
 
391
362
  ```typescript
392
- update(key: K, updateFn: (v: V | undefined) => V): void;
363
+ clear(): this;
393
364
  ```
394
365
 
395
- ```typescript
396
- const counts = new Map<string, number>();
397
- counts.update("hits", (v) => (v ?? 0) + 1);
398
- ```
366
+ ---
399
367
 
400
368
  ## Exported Types
401
369
 
@@ -428,3 +396,42 @@ type TreeArray<TNode> = TNode & { children: TreeArray<TNode>[] };
428
396
  ```typescript
429
397
  type ComparableType = string | number | boolean | DateTime | DateOnly | Time | undefined;
430
398
  ```
399
+
400
+ ---
401
+
402
+ ## Exported Helper Functions
403
+
404
+ ### `toComparable`
405
+
406
+ Convert DateTime, DateOnly, or Time to their tick value for comparison. Primitives pass through unchanged.
407
+
408
+ ```typescript
409
+ function toComparable(value: ComparableType): string | number | boolean | undefined;
410
+ ```
411
+
412
+ ### `compareForOrder`
413
+
414
+ Comparison function for sorting. Handles null/undefined (sorted first in ascending, last in descending). Supports string (locale-aware), number, and boolean.
415
+
416
+ ```typescript
417
+ function compareForOrder(pp: ComparableType, pn: ComparableType, desc: boolean): number;
418
+ ```
419
+
420
+ | Parameter | Type | Description |
421
+ |-----------|------|-------------|
422
+ | `pp` | `ComparableType` | First value |
423
+ | `pn` | `ComparableType` | Second value |
424
+ | `desc` | `boolean` | `true` for descending order |
425
+
426
+ **Returns:** Negative if `pp` should come first, positive if `pn` should come first, `0` if equal.
427
+
428
+ ### `getDistinctIndices`
429
+
430
+ Get the set of indices to keep for deduplication. Handles all strategies: address comparison, custom key function, and deep equality.
431
+
432
+ ```typescript
433
+ function getDistinctIndices<T>(
434
+ items: readonly T[],
435
+ options?: boolean | { matchAddress?: boolean; keyFn?: (item: T) => string | number },
436
+ ): Set<number>;
437
+ ```
package/docs/env.md CHANGED
@@ -1,10 +1,8 @@
1
1
  # Environment
2
2
 
3
- Unified access to environment variables from both `import.meta.env` (Vite/browser) and `process.env` (Node.js). `process.env` takes precedence when both are available.
4
-
5
3
  ## `parseBoolEnv`
6
4
 
7
- Parses an unknown value to a boolean. Returns `true` for `"true"`, `"1"`, `"yes"`, `"on"` (case-insensitive), `false` for everything else.
5
+ Parse a value to boolean. Recognizes `"true"`, `"1"`, `"yes"`, `"on"` (case-insensitive) as `true`; everything else is `false`.
8
6
 
9
7
  ```typescript
10
8
  function parseBoolEnv(value: unknown): boolean;
@@ -12,22 +10,13 @@ function parseBoolEnv(value: unknown): boolean;
12
10
 
13
11
  | Parameter | Type | Description |
14
12
  |-----------|------|-------------|
15
- | `value` | `unknown` | The value to parse |
13
+ | `value` | `unknown` | The value to parse. Converted to string internally. |
16
14
 
17
15
  **Returns:** `boolean`
18
16
 
19
- ```typescript
20
- parseBoolEnv("true"); // true
21
- parseBoolEnv("1"); // true
22
- parseBoolEnv("yes"); // true
23
- parseBoolEnv("on"); // true
24
- parseBoolEnv("false"); // false
25
- parseBoolEnv(undefined); // false
26
- ```
27
-
28
17
  ## `env`
29
18
 
30
- A pre-built environment object that merges `import.meta.env` and `process.env`.
19
+ Unified environment variable object. Merges `import.meta.env` and `process.env` (process.env takes precedence). `DEV` is auto-parsed as boolean, `VER` is typed as optional string.
31
20
 
32
21
  ```typescript
33
22
  const env: {
@@ -37,16 +26,8 @@ const env: {
37
26
  };
38
27
  ```
39
28
 
40
- | Property | Type | Description |
41
- |----------|------|-------------|
42
- | `DEV` | `boolean` | Whether in development mode (parsed via `parseBoolEnv` from `DEV` env var) |
43
- | `VER` | `string \| undefined` | Version string from `VER` env var |
44
- | `[key]` | `unknown` | Any other environment variable |
45
-
46
- ```typescript
47
- import { env } from "@simplysm/core-common";
48
-
49
- if (env.DEV) {
50
- // development-only logic
51
- }
52
- ```
29
+ | Field | Type | Description |
30
+ |-------|------|-------------|
31
+ | `DEV` | `boolean` | Whether the app is running in development mode. Parsed from raw `DEV` env var via `parseBoolEnv`. |
32
+ | `VER` | `string \| undefined` | Application version string, if set. |
33
+ | `[key: string]` | `unknown` | Any other environment variable. |