@ix-xs/node-comfort 1.2.0 → 2.1.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 (78) hide show
  1. package/CHANGELOG.md +340 -0
  2. package/README.md +137 -548
  3. package/index.js +80 -35
  4. package/package.json +161 -33
  5. package/src/Arr.js +1050 -418
  6. package/src/Async.js +817 -0
  7. package/src/Cache.js +433 -0
  8. package/src/Checker.js +1202 -539
  9. package/src/Cli.js +1293 -0
  10. package/src/Color.js +556 -0
  11. package/src/Crypto.js +1082 -0
  12. package/src/Emitter.js +356 -0
  13. package/src/Env.js +689 -0
  14. package/src/FS.js +1626 -894
  15. package/src/Func.js +823 -356
  16. package/src/Http.js +700 -0
  17. package/src/Id.js +568 -200
  18. package/src/Logger.js +963 -378
  19. package/src/Num.js +965 -360
  20. package/src/Obj.js +1077 -379
  21. package/src/SQLite.js +1629 -1005
  22. package/src/Schema.js +2101 -0
  23. package/src/Str.js +1209 -432
  24. package/src/Sys.js +654 -0
  25. package/src/Time.js +1533 -440
  26. package/src/Utils.js +342 -325
  27. package/src/errors.js +335 -0
  28. package/src/internal/shared.js +415 -0
  29. package/types/index.d.ts +735 -526
  30. package/types/src/Arr.d.ts +533 -145
  31. package/types/src/Arr.d.ts.map +1 -1
  32. package/types/src/Async.d.ts +372 -0
  33. package/types/src/Async.d.ts.map +1 -0
  34. package/types/src/Cache.d.ts +221 -0
  35. package/types/src/Cache.d.ts.map +1 -0
  36. package/types/src/Checker.d.ts +651 -232
  37. package/types/src/Checker.d.ts.map +1 -1
  38. package/types/src/Cli.d.ts +664 -0
  39. package/types/src/Cli.d.ts.map +1 -0
  40. package/types/src/Color.d.ts +300 -0
  41. package/types/src/Color.d.ts.map +1 -0
  42. package/types/src/Crypto.d.ts +620 -0
  43. package/types/src/Crypto.d.ts.map +1 -0
  44. package/types/src/Emitter.d.ts +189 -0
  45. package/types/src/Emitter.d.ts.map +1 -0
  46. package/types/src/Env.d.ts +412 -0
  47. package/types/src/Env.d.ts.map +1 -0
  48. package/types/src/FS.d.ts +717 -238
  49. package/types/src/FS.d.ts.map +1 -1
  50. package/types/src/Func.d.ts +508 -135
  51. package/types/src/Func.d.ts.map +1 -1
  52. package/types/src/Http.d.ts +444 -0
  53. package/types/src/Http.d.ts.map +1 -0
  54. package/types/src/Id.d.ts +199 -66
  55. package/types/src/Id.d.ts.map +1 -1
  56. package/types/src/Logger.d.ts +414 -46
  57. package/types/src/Logger.d.ts.map +1 -1
  58. package/types/src/Num.d.ts +514 -137
  59. package/types/src/Num.d.ts.map +1 -1
  60. package/types/src/Obj.d.ts +453 -104
  61. package/types/src/Obj.d.ts.map +1 -1
  62. package/types/src/SQLite.d.ts +754 -308
  63. package/types/src/SQLite.d.ts.map +1 -1
  64. package/types/src/Schema.d.ts +1189 -0
  65. package/types/src/Schema.d.ts.map +1 -0
  66. package/types/src/Str.d.ts +617 -166
  67. package/types/src/Str.d.ts.map +1 -1
  68. package/types/src/Sys.d.ts +314 -0
  69. package/types/src/Sys.d.ts.map +1 -0
  70. package/types/src/Time.d.ts +759 -204
  71. package/types/src/Time.d.ts.map +1 -1
  72. package/types/src/Utils.d.ts +158 -102
  73. package/types/src/Utils.d.ts.map +1 -1
  74. package/types/src/errors.d.ts +316 -0
  75. package/types/src/errors.d.ts.map +1 -0
  76. package/types/src/internal/shared.d.ts +123 -0
  77. package/types/src/internal/shared.d.ts.map +1 -0
  78. package/types/index.d.ts.map +0 -1
@@ -1,189 +1,538 @@
1
+ declare namespace _exports {
2
+ export { PathLeaf, Paths, NullishToUndefined, PathValue, PathStep, PathInput, DeepReadonly, Change, MergeOptions, SortKeysOptions, CompactOptions };
3
+ }
4
+ declare namespace _exports {
5
+ export { clone };
6
+ export { merge };
7
+ export { mergeWith };
8
+ export { defaults };
9
+ export { equal };
10
+ export { diff };
11
+ export { get };
12
+ export { set };
13
+ export { update };
14
+ export { unset };
15
+ export { has };
16
+ export { pick };
17
+ export { omit };
18
+ export { filter };
19
+ export { mapValues };
20
+ export { mapKeys };
21
+ export { renameKeys };
22
+ export { invert };
23
+ export { compact };
24
+ export { flatten };
25
+ export { unflatten };
26
+ export { paths };
27
+ export { sortKeys };
28
+ export { keys };
29
+ export { entries };
30
+ export { fromEntries };
31
+ export { size };
32
+ export { isEmpty };
33
+ export { deepFreeze };
34
+ }
35
+ export = _exports;
1
36
  /**
2
- * Deeply clones a value.
37
+ * Values that end a path: dates, regexes, maps, sets, functions and arrays.
38
+ */
39
+ type PathLeaf = Date | RegExp | Map<any, any> | Set<any> | ((...args: any[]) => any) | readonly any[];
40
+ /**
41
+ * Every dotted path of an object type, up to 6 levels. This is what powers
42
+ * path completion in `obj.get()` and friends.
43
+ */
44
+ type Paths<T, Depth extends unknown[] = []> = Depth["length"] extends 6 ? never : T extends PathLeaf ? never : T extends object ? { [K in keyof T & (string | number)]: NonNullable<T[K]> extends PathLeaf ? `${K}` : NonNullable<T[K]> extends object ? `${K}` | `${K}.${Paths<NonNullable<T[K]>, [...Depth, 0]>}` : `${K}`; }[keyof T & (string | number)] : never;
45
+ type NullishToUndefined<T> = [Extract<T, null | undefined>] extends [never] ? never : undefined;
46
+ /**
47
+ * The type found at a dotted path of `T`, or `any` for an unknown path.
48
+ */
49
+ type PathValue<T, P extends string> = P extends `${infer Head}.${infer Rest}` ? PathStep<T, Head> extends infer Next ? ([Next] extends [typeof _NOT_FOUND] ? any : PathValue<Next, Rest> | NullishToUndefined<T>) : any : PathStep<T, P> extends infer Next ? ([Next] extends [typeof _NOT_FOUND] ? any : Next | NullishToUndefined<T>) : any;
50
+ type PathStep<T, K extends string> = K extends keyof NonNullable<T> ? NonNullable<T>[K] : NonNullable<T> extends readonly (infer E)[] ? (K extends `${number}` ? E | undefined : typeof _NOT_FOUND) : typeof _NOT_FOUND;
51
+ /**
52
+ * A path: a known dotted path (completed by your editor), any other string
53
+ * like `"items[0].name"`, or an array of keys.
54
+ */
55
+ type PathInput<T> = Paths<T> | (string & {}) | ReadonlyArray<string | number>;
56
+ /**
57
+ * `T`, read-only all the way down.
58
+ */
59
+ type DeepReadonly<T> = T extends (...args: any[]) => any ? T : T extends object ? { readonly [K in keyof T]: DeepReadonly<T[K]>; } : T;
60
+ /**
61
+ * One difference reported by `diff()`.
62
+ */
63
+ type Change = {
64
+ /**
65
+ * Where it changed, like `["address", "city"]`.
66
+ */
67
+ path: Array<string | number>;
68
+ type: "added" | "removed" | "changed";
69
+ /**
70
+ * The old value.
71
+ */
72
+ from?: unknown;
73
+ /**
74
+ * The new value.
75
+ */
76
+ to?: unknown;
77
+ };
78
+ /**
79
+ * Options for `mergeWith()`.
80
+ */
81
+ type MergeOptions = {
82
+ /**
83
+ * When both sides have an array: keep the last, join them, or join without duplicates. Defaults to `"replace"`.
84
+ */
85
+ arrays?: "concat" | "replace" | "unique" | undefined;
86
+ /**
87
+ * Don't let `undefined` overwrite an existing value.
88
+ */
89
+ skipUndefined?: boolean | undefined;
90
+ };
91
+ /**
92
+ * Options for `sortKeys()`.
93
+ */
94
+ type SortKeysOptions = {
95
+ /**
96
+ * Sort nested objects too, arrays included. Defaults to `true`. With `false`, only the first level is copied and sorted: what it holds is shared with the original.
97
+ */
98
+ deep?: boolean | undefined;
99
+ /**
100
+ * How to order two keys. Defaults to code-unit order, which is stable across machines.
101
+ */
102
+ compare?: ((a: string, b: string) => number) | undefined;
103
+ };
104
+ /**
105
+ * Options for `compact()`.
106
+ */
107
+ type CompactOptions = {
108
+ /**
109
+ * Clean nested objects and arrays too.
110
+ */
111
+ deep?: boolean | undefined;
112
+ /**
113
+ * Also remove `""`, `[]` and `{}`.
114
+ */
115
+ removeEmpty?: boolean | undefined;
116
+ };
117
+ /**
118
+ * Deep copy. Unlike `structuredClone`, it keeps functions and class
119
+ * instances (with their prototype), and it's faster on plain data. Shared
120
+ * references and cycles are preserved.
3
121
  *
4
- * Uses the native `structuredClone` when the value supports it (plain data,
5
- * Dates, Maps, Sets, typed arrays, ...), and falls back to a manual deep copy
6
- * otherwise. Functions are copied by reference.
122
+ * @example
123
+ * const copy = obj.clone({ a: { b: [1, 2] }, when: new Date() });
124
+ * copy.a.b.push(3); // the original is untouched
125
+ *
126
+ * @template T
127
+ * @param {T} value
128
+ * @returns {T}
129
+ */
130
+ declare function clone<T>(value: T): T;
131
+ /**
132
+ * Deep-merges objects into a new one. Later objects win, nested objects are
133
+ * merged, arrays are replaced. See `mergeWith()` to join arrays instead.
7
134
  *
8
135
  * @example
9
- * const copy = nodeComfort.obj.clone({ a: { b: 1 } });
136
+ * obj.merge({ db: { host: "localhost", port: 5432 } }, { db: { port: 6543 } });
137
+ * // { db: { host: "localhost", port: 6543 } }
138
+ *
139
+ * @template {object} A
140
+ * @overload
141
+ * @param {A} a
142
+ * @returns {A}
143
+ */
144
+ declare function merge<A extends object>(a: A): A;
145
+ /**
146
+ * Deep-merges `b` into a copy of `a`.
147
+ *
148
+ * @template {object} A
149
+ * @template {object} B
150
+ * @overload
151
+ * @param {A} a
152
+ * @param {B} b
153
+ * @returns {A & B}
154
+ */
155
+ declare function merge<A extends object, B extends object>(a: A, b: B): A & B;
156
+ /**
157
+ * Deep-merges three objects; the last one wins.
158
+ *
159
+ * @template {object} A
160
+ * @template {object} B
161
+ * @template {object} C
162
+ * @overload
163
+ * @param {A} a
164
+ * @param {B} b
165
+ * @param {C} c
166
+ * @returns {A & B & C}
167
+ */
168
+ declare function merge<A extends object, B extends object, C extends object>(a: A, b: B, c: C): A & B & C;
169
+ /**
170
+ * Deep-merges any number of objects; the last one wins.
171
+ *
172
+ * @overload
173
+ * @param {...object} sources
174
+ * @returns {Record<string, any>}
175
+ */
176
+ declare function merge(...sources: object[]): Record<string, any>;
177
+ /**
178
+ * Like `merge()`, with a choice of what happens to arrays and `undefined`.
179
+ *
180
+ * @example
181
+ * obj.mergeWith({ arrays: "unique" }, { tags: ["a", "b"] }, { tags: ["b", "c"] });
182
+ * // { tags: ["a", "b", "c"] }
183
+ * obj.mergeWith({ skipUndefined: true }, { port: 80 }, { port: undefined });
184
+ * // { port: 80 }
185
+ *
186
+ * @param {MergeOptions} options
187
+ * @param {...object} sources
188
+ * @returns {Record<string, any>}
189
+ */
190
+ declare function mergeWith(options: MergeOptions, ...sources: object[]): Record<string, any>;
191
+ /**
192
+ * Fills in missing properties from defaults, deeply. Values that are set,
193
+ * even `null` or `0`, are kept.
194
+ *
195
+ * @example
196
+ * obj.defaults({ port: 8080, db: { user: "me" } }, { port: 80, db: { user: "root", pass: "" } });
197
+ * // { port: 8080, db: { user: "me", pass: "" } }
198
+ *
199
+ * @template {object} T
200
+ * @template {object} D
201
+ * @param {T} target
202
+ * @param {...D} sources The first one has the highest priority.
203
+ * @returns {T & D}
204
+ */
205
+ declare function defaults<T extends object, D extends object>(target: T, ...sources: D[]): T & D;
206
+ /**
207
+ * Deep equality. Knows about arrays, dates, regexes, maps, sets, typed
208
+ * arrays, `NaN` and circular references.
209
+ *
210
+ * @example
211
+ * obj.equal({ a: [1, { b: 2 }] }, { a: [1, { b: 2 }] }); // true
212
+ * obj.equal(new Set([1, 2]), new Set([2, 1])); // true
213
+ * obj.equal({ a: 1 }, { a: 1, b: undefined }); // false
214
+ *
215
+ * @param {unknown} a
216
+ * @param {unknown} b
217
+ * @returns {boolean}
218
+ */
219
+ declare function equal(a: unknown, b: unknown): boolean;
220
+ /**
221
+ * Lists what changed between two values, deeply. Handy for audit logs and
222
+ * partial updates.
223
+ *
224
+ * @example
225
+ * obj.diff({ name: "Ada", tags: ["a"] }, { name: "Ada L.", tags: ["a", "b"] });
226
+ * // [
227
+ * // { path: ["name"], type: "changed", from: "Ada", to: "Ada L." },
228
+ * // { path: ["tags", 1], type: "added", to: "b" },
229
+ * // ]
230
+ *
231
+ * @param {unknown} before
232
+ * @param {unknown} after
233
+ * @returns {Change[]} Empty when nothing changed.
234
+ */
235
+ declare function diff(before: unknown, after: unknown): Change[];
236
+ /**
237
+ * Reads a nested value from a dotted path. Your editor completes the paths
238
+ * and knows the type of the result.
239
+ *
240
+ * @example
241
+ * obj.get(config, "db.pool.max"); // number | undefined
242
+ * obj.get(config, "db.pool.max", 10); // number
243
+ * obj.get(data, "users[0].name");
244
+ * obj.get(data, ["users", 0, "name"]);
245
+ *
246
+ * @template T
247
+ * @template {string} P
248
+ * @overload
249
+ * @param {T} object
250
+ * @param {P | Paths<T> | ReadonlyArray<string | number>} path Like `"a.b.c"`, `"a[0].b"` or `["a", 0, "b"]`.
251
+ * @returns {PathValue<T, P>}
252
+ */
253
+ declare function get<T, P extends string>(object: T, path: P | Paths<T> | ReadonlyArray<string | number>): PathValue<T, P>;
254
+ /**
255
+ * Reads a nested value from a dotted path, or returns `fallback` if there's
256
+ * nothing there.
10
257
  *
11
258
  * @template T
12
- * @param {T} value - Value to clone.
13
- * @returns {T} A deep copy.
259
+ * @template {string} P
260
+ * @template F
261
+ * @overload
262
+ * @param {T} object
263
+ * @param {P | Paths<T> | ReadonlyArray<string | number>} path Like `"a.b.c"`, `"a[0].b"` or `["a", 0, "b"]`.
264
+ * @param {F} fallback
265
+ * @returns {Exclude<PathValue<T, P>, undefined> | F}
14
266
  */
15
- export function clone<T>(value: T): T;
267
+ declare function get<T, P extends string, F>(object: T, path: P | Paths<T> | ReadonlyArray<string | number>, fallback: F): Exclude<PathValue<T, P>, undefined> | F;
16
268
  /**
17
- * Deeply merges two or more plain objects into a new object.
269
+ * Returns a copy with a nested value set. Missing levels are created
270
+ * (arrays when the next key is a number).
271
+ *
272
+ * @example
273
+ * obj.set({}, "a.b.c", 1); // { a: { b: { c: 1 } } }
274
+ * obj.set(state, "user.name", "Ada"); // state is untouched
275
+ *
276
+ * @template T
277
+ * @param {T} object
278
+ * @param {PathInput<T>} path
279
+ * @param {unknown} value
280
+ * @returns {T}
281
+ */
282
+ declare function set<T>(object: T, path: PathInput<T>, value: unknown): T;
283
+ /**
284
+ * Returns a copy where the value at `path` is replaced by what `updater`
285
+ * returns for it. Handy for counters and lists.
286
+ *
287
+ * @example
288
+ * obj.update(state, "stats.visits", (n = 0) => n + 1);
289
+ * obj.update(cart, "items", (items = []) => [...items, product]);
290
+ *
291
+ * @template T
292
+ * @param {T} object
293
+ * @param {PathInput<T>} path
294
+ * @param {(value: any) => unknown} updater Gets the current value, `undefined` if there's none.
295
+ * @returns {T}
296
+ */
297
+ declare function update<T>(object: T, path: PathInput<T>, updater: (value: any) => unknown): T;
298
+ /**
299
+ * Returns a copy without the property at `path`.
300
+ *
301
+ * @example
302
+ * obj.unset({ a: { b: 1, c: 2 } }, "a.b"); // { a: { c: 2 } }
18
303
  *
19
- * Later sources win. Plain-object values are merged recursively; arrays and
20
- * other values are replaced (not concatenated). Inputs are never mutated.
304
+ * @template T
305
+ * @param {T} object
306
+ * @param {PathInput<T>} path
307
+ * @returns {T}
308
+ */
309
+ declare function unset<T>(object: T, path: PathInput<T>): T;
310
+ /**
311
+ * Does the path exist? A property set to `undefined` still counts.
21
312
  *
22
313
  * @example
23
- * nodeComfort.obj.merge({ a: { x: 1 } }, { a: { y: 2 } });
24
- * // { a: { x: 1, y: 2 } }
314
+ * obj.has({ a: { b: undefined } }, "a.b"); // true
315
+ * obj.has({ a: {} }, "a.b"); // false
25
316
  *
26
- * @param {...Record<string, any>} sources - Objects to merge.
27
- * @returns {Record<string, any>} The merged object.
317
+ * @template T
318
+ * @param {T} object
319
+ * @param {PathInput<T>} path
320
+ * @returns {boolean}
28
321
  */
29
- export function merge(...sources: Record<string, any>[]): Record<string, any>;
322
+ declare function has<T>(object: T, path: PathInput<T>): boolean;
30
323
  /**
31
- * Deeply compares two values for structural equality.
324
+ * A copy with only the listed keys.
325
+ *
326
+ * @example
327
+ * obj.pick(user, ["id", "email"]);
32
328
  *
33
- * Handles plain objects, arrays, Dates, RegExps, Maps and Sets.
329
+ * @template {object} T
330
+ * @template {keyof T} K
331
+ * @param {T} object
332
+ * @param {readonly K[]} keys
333
+ * @returns {Pick<T, K>}
334
+ */
335
+ declare function pick<T extends object, K extends keyof T>(object: T, keys: readonly K[]): Pick<T, K>;
336
+ /**
337
+ * A copy without the listed keys.
34
338
  *
35
339
  * @example
36
- * nodeComfort.obj.equal({ a: [1, 2] }, { a: [1, 2] }); // true
340
+ * obj.omit(user, ["password", "token"]);
37
341
  *
38
- * @param {*} a - First value.
39
- * @param {*} b - Second value.
40
- * @returns {boolean} True if the values are deeply equal.
342
+ * @template {object} T
343
+ * @template {keyof T} K
344
+ * @param {T} object
345
+ * @param {readonly K[]} keys
346
+ * @returns {Omit<T, K>}
41
347
  */
42
- export function equal(a: any, b: any): boolean;
348
+ declare function omit<T extends object, K extends keyof T>(object: T, keys: readonly K[]): Omit<T, K>;
43
349
  /**
44
- * Gets a nested value from an object using a dot/bracket path.
350
+ * Keeps the entries that pass a test.
45
351
  *
46
352
  * @example
47
- * nodeComfort.obj.get({ a: { b: [{ c: 42 }] } }, "a.b[0].c"); // 42
48
- * nodeComfort.obj.get({}, "a.b.c", "default"); // "default"
353
+ * obj.filter({ a: 1, b: 2, c: 3 }, (value) => value > 1); // { b: 2, c: 3 }
49
354
  *
50
- * @param {Record<string, any>} object - Source object.
51
- * @param {string|Array<string|number>} path - Dot path or key array.
52
- * @param {*} [fallback] - Returned when the path does not resolve.
53
- * @returns {*} The value at the path, or the fallback.
355
+ * @template {object} T
356
+ * @param {T} object
357
+ * @param {(value: T[keyof T], key: keyof T & string) => unknown} predicate
358
+ * @returns {Partial<T>}
54
359
  */
55
- export function get(object: Record<string, any>, path: string | Array<string | number>, fallback?: any): any;
360
+ declare function filter<T extends object>(object: T, predicate: (value: T[keyof T], key: keyof T & string) => unknown): Partial<T>;
56
361
  /**
57
- * Sets a nested value in an object using a dot/bracket path (returns a clone).
362
+ * Transforms every value, keeping the keys.
363
+ *
364
+ * @example
365
+ * obj.mapValues({ a: 1, b: 2 }, (v) => v * 10); // { a: 10, b: 20 }
58
366
  *
59
- * Intermediate objects/arrays are created as needed. The original object is
60
- * not mutated.
367
+ * @template {object} T
368
+ * @template R
369
+ * @param {T} object
370
+ * @param {(value: T[keyof T], key: keyof T & string) => R} fn
371
+ * @returns {{ [K in keyof T]: R }}
372
+ */
373
+ declare function mapValues<T extends object, R>(object: T, fn: (value: T[keyof T], key: keyof T & string) => R): { [K in keyof T]: R; };
374
+ /**
375
+ * Transforms every key, keeping the values.
61
376
  *
62
377
  * @example
63
- * nodeComfort.obj.set({}, "a.b.c", 1); // { a: { b: { c: 1 } } }
378
+ * obj.mapKeys({ first_name: "Ada" }, (key) => nc.str.camelCase(key)); // { firstName: "Ada" }
64
379
  *
65
- * @param {Record<string, any>} object - Source object.
66
- * @param {string|Array<string|number>} path - Dot path or key array.
67
- * @param {*} value - Value to set.
68
- * @returns {Record<string, any>} A new object with the value set.
380
+ * @template {object} T
381
+ * @param {T} object
382
+ * @param {(key: keyof T & string, value: T[keyof T]) => PropertyKey} fn Returns the new key.
383
+ * @returns {Record<string, T[keyof T]>}
69
384
  */
70
- export function set(object: Record<string, any>, path: string | Array<string | number>, value: any): Record<string, any>;
385
+ declare function mapKeys<T extends object>(object: T, fn: (key: keyof T & string, value: T[keyof T]) => PropertyKey): Record<string, T[keyof T]>;
71
386
  /**
72
- * Checks whether a nested path exists in an object.
387
+ * Renames some keys and leaves the others alone.
73
388
  *
74
- * @param {Record<string, any>} object - Source object.
75
- * @param {string|Array<string|number>} path - Dot path or key array.
76
- * @returns {boolean} True if the path resolves.
389
+ * @example
390
+ * obj.renameKeys({ _id: 1, name: "Ada" }, { _id: "id" }); // { id: 1, name: "Ada" }
391
+ *
392
+ * @template {object} T
393
+ * @param {T} object
394
+ * @param {Partial<Record<keyof T, string>>} mapping Old name to new name.
395
+ * @returns {Record<string, T[keyof T]>}
77
396
  */
78
- export function has(object: Record<string, any>, path: string | Array<string | number>): boolean;
397
+ declare function renameKeys<T extends object>(object: T, mapping: Partial<Record<keyof T, string>>): Record<string, T[keyof T]>;
79
398
  /**
80
- * Returns a new object containing only the given keys.
399
+ * Swaps keys and values.
81
400
  *
82
401
  * @example
83
- * nodeComfort.obj.pick({ a: 1, b: 2, c: 3 }, ["a", "c"]); // { a: 1, c: 3 }
402
+ * obj.invert({ a: "x", b: "y" }); // { x: "a", y: "b" }
84
403
  *
85
- * @param {Record<string, any>} object - Source object.
86
- * @param {string[]} keys - Keys to keep.
87
- * @returns {Record<string, any>} The picked object.
404
+ * @param {Record<string, PropertyKey>} object
405
+ * @returns {Record<string, string>}
88
406
  */
89
- export function pick(object: Record<string, any>, keys: string[]): Record<string, any>;
407
+ declare function invert(object: Record<string, PropertyKey>): Record<string, string>;
90
408
  /**
91
- * Returns a new object without the given keys.
409
+ * Removes `null` and `undefined` values, and optionally empty ones.
92
410
  *
93
411
  * @example
94
- * nodeComfort.obj.omit({ a: 1, b: 2, c: 3 }, ["b"]); // { a: 1, c: 3 }
412
+ * obj.compact({ a: 1, b: null, c: undefined }); // { a: 1 }
413
+ * obj.compact({ a: { b: null, c: "" } }, { deep: true, removeEmpty: true }); // {}
95
414
  *
96
- * @param {Record<string, any>} object - Source object.
97
- * @param {string[]} keys - Keys to remove.
98
- * @returns {Record<string, any>} The remaining object.
415
+ * @template {object} T
416
+ * @param {T} object
417
+ * @param {CompactOptions} [options]
418
+ * @returns {Partial<T>}
99
419
  */
100
- export function omit(object: Record<string, any>, keys: string[]): Record<string, any>;
420
+ declare function compact<T extends object>(object: T, options?: CompactOptions): Partial<T>;
101
421
  /**
102
- * Returns a new object keeping only the entries that pass a predicate.
422
+ * Flattens nested objects into dotted keys. Arrays stay as values.
103
423
  *
104
424
  * @example
105
- * nodeComfort.obj.filter({ a: 1, b: 2, c: 3 }, (v) => v > 1); // { b: 2, c: 3 }
425
+ * obj.flatten({ db: { host: "x", port: 5432 } }); // { "db.host": "x", "db.port": 5432 }
106
426
  *
107
- * @param {Record<string, any>} object - Source object.
108
- * @param {(value: any, key: string) => boolean} predicate - Test function.
109
- * @returns {Record<string, any>} The filtered object.
427
+ * @param {object} object
428
+ * @param {string} [prefix=""] Added in front of every key.
429
+ * @returns {Record<string, unknown>}
110
430
  */
111
- export function filter(object: Record<string, any>, predicate: (value: any, key: string) => boolean): Record<string, any>;
431
+ declare function flatten(object: object, prefix?: string): Record<string, unknown>;
112
432
  /**
113
- * Maps over an object's values, returning a new object with the same keys.
433
+ * Rebuilds nested objects from dotted keys. The opposite of `flatten()`.
114
434
  *
115
435
  * @example
116
- * nodeComfort.obj.mapValues({ a: 1, b: 2 }, (v) => v * 10); // { a: 10, b: 20 }
436
+ * obj.unflatten({ "db.host": "x", "db.port": 5432 }); // { db: { host: "x", port: 5432 } }
117
437
  *
118
- * @param {Record<string, any>} object - Source object.
119
- * @param {(value: any, key: string) => any} fn - Mapping function.
120
- * @returns {Record<string, any>} The mapped object.
438
+ * @param {Record<string, unknown>} object
439
+ * @returns {Record<string, any>}
121
440
  */
122
- export function mapValues(object: Record<string, any>, fn: (value: any, key: string) => any): Record<string, any>;
441
+ declare function unflatten(object: Record<string, unknown>): Record<string, any>;
123
442
  /**
124
- * Maps over an object's keys, returning a new object with remapped keys.
443
+ * Every leaf path of an object, in dotted form. Arrays count as leaves.
125
444
  *
126
445
  * @example
127
- * nodeComfort.obj.mapKeys({ a: 1 }, (k) => k.toUpperCase()); // { A: 1 }
446
+ * obj.paths({ db: { host: "x", port: 5432 }, tags: ["a"] }); // ["db.host", "db.port", "tags"]
128
447
  *
129
- * @param {Record<string, any>} object - Source object.
130
- * @param {(key: string, value: any) => string} fn - Key-mapping function.
131
- * @returns {Record<string, any>} The remapped object.
448
+ * @param {object} object
449
+ * @returns {string[]}
132
450
  */
133
- export function mapKeys(object: Record<string, any>, fn: (key: string, value: any) => string): Record<string, any>;
451
+ declare function paths(object: object): string[];
134
452
  /**
135
- * Swaps keys and values of an object.
453
+ * A copy with its keys in order, nested objects included. Two objects with
454
+ * the same content then give the same JSON, which makes stable hashes,
455
+ * cache keys and readable diffs.
136
456
  *
137
457
  * @example
138
- * nodeComfort.obj.invert({ a: "x", b: "y" }); // { x: "a", y: "b" }
458
+ * obj.sortKeys({ b: 1, a: { d: 1, c: 2 } }); // { a: { c: 2, d: 1 }, b: 1 }
459
+ * nc.crypto.hash(JSON.stringify(obj.sortKeys(payload)));
139
460
  *
140
- * @param {Record<string, any>} object - Source object.
141
- * @returns {Record<string, string>} The inverted object.
461
+ * @template T
462
+ * @param {T} object
463
+ * @param {SortKeysOptions} [options]
464
+ * @returns {T}
142
465
  */
143
- export function invert(object: Record<string, any>): Record<string, string>;
466
+ declare function sortKeys<T>(object: T, options?: SortKeysOptions): T;
144
467
  /**
145
- * Removes entries whose value is `null` or `undefined` (shallow).
468
+ * `Object.keys`, but typed with the object's actual keys.
146
469
  *
147
470
  * @example
148
- * nodeComfort.obj.compact({ a: 1, b: null, c: undefined }); // { a: 1 }
471
+ * for (const key of obj.keys(config)) config[key]; // no type error
472
+ *
473
+ * @template {object} T
474
+ * @param {T} object
475
+ * @returns {Array<keyof T & string>}
476
+ */
477
+ declare function keys<T extends object>(object: T): Array<keyof T & string>;
478
+ /**
479
+ * `Object.entries`, with typed keys and values.
149
480
  *
150
- * @param {Record<string, any>} object - Source object.
151
- * @returns {Record<string, any>} The compacted object.
481
+ * @template {object} T
482
+ * @param {T} object
483
+ * @returns {Array<[keyof T & string, T[keyof T]]>}
152
484
  */
153
- export function compact(object: Record<string, any>): Record<string, any>;
485
+ declare function entries<T extends object>(object: T): Array<[keyof T & string, T[keyof T]]>;
154
486
  /**
155
- * Flattens a nested object into a single-level object with dot-path keys.
487
+ * `Object.fromEntries` that accepts any iterable (a `Map` too) and skips
488
+ * unsafe keys.
156
489
  *
157
490
  * @example
158
- * nodeComfort.obj.flatten({ a: { b: { c: 1 } } }); // { "a.b.c": 1 }
491
+ * obj.fromEntries(new Map([["x", true]])); // { x: true }
159
492
  *
160
- * @param {Record<string, any>} object - Source object.
161
- * @param {string} [prefix=""] - Prefix for keys (used internally).
162
- * @returns {Record<string, any>} The flattened object.
493
+ * @template {PropertyKey} K
494
+ * @template V
495
+ * @param {Iterable<readonly [K, V]>} pairs
496
+ * @returns {Record<K, V>}
163
497
  */
164
- export function flatten(object: Record<string, any>, prefix?: string): Record<string, any>;
498
+ declare function fromEntries<K extends PropertyKey, V>(pairs: Iterable<readonly [K, V]>): Record<K, V>;
165
499
  /**
166
- * Rebuilds a nested object from a flat, dot-path keyed object.
500
+ * How many entries: own keys of an object, size of a map or set, length of
501
+ * an array or string.
167
502
  *
168
503
  * @example
169
- * nodeComfort.obj.unflatten({ "a.b.c": 1 }); // { a: { b: { c: 1 } } }
504
+ * obj.size({ a: 1, b: 2 }); // 2
170
505
  *
171
- * @param {Record<string, any>} object - Flat object.
172
- * @returns {Record<string, any>} The nested object.
506
+ * @param {unknown} value
507
+ * @returns {number}
173
508
  */
174
- export function unflatten(object: Record<string, any>): Record<string, any>;
509
+ declare function size(value: unknown): number;
175
510
  /**
176
- * Checks whether an object has no own enumerable keys.
511
+ * Is there nothing in it? No own keys for an object, no entries for a Map
512
+ * or a Set. `null` and `undefined` count as empty; a date, a regular
513
+ * expression and an error never do.
177
514
  *
178
- * @param {Record<string, any>} object - Source object.
179
- * @returns {boolean} True if the object is empty.
515
+ * @example
516
+ * obj.isEmpty({}); // true
517
+ * obj.isEmpty(new Map([["a", 1]])); // false
518
+ *
519
+ * @param {unknown} object
520
+ * @returns {boolean}
180
521
  */
181
- export function isEmpty(object: Record<string, any>): boolean;
522
+ declare function isEmpty(object: unknown): boolean;
182
523
  /**
183
- * Freezes an object deeply, making it (and all nested objects) immutable.
524
+ * Freezes an object and everything inside it. Good for configuration and
525
+ * constants.
184
526
  *
185
- * @param {Record<string, any>} object - Object to freeze.
186
- * @returns {Record<string, any>} The same, now deeply-frozen, object.
527
+ * @example
528
+ * const CONFIG = obj.deepFreeze({ db: { host: "localhost" } });
529
+ * CONFIG.db.host = "x"; // TypeScript error, and ignored at runtime
530
+ *
531
+ * @template T
532
+ * @param {T} object
533
+ * @returns {DeepReadonly<T>} The same object.
187
534
  */
188
- export function deepFreeze(object: Record<string, any>): Record<string, any>;
535
+ declare function deepFreeze<T>(object: T): DeepReadonly<T>;
536
+ /** Marks an unknown path segment in `PathStep`. */
537
+ declare const _NOT_FOUND: unique symbol;
189
538
  //# sourceMappingURL=Obj.d.ts.map