@ix-xs/node-comfort 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +190 -0
  2. package/README.md +136 -549
  3. package/index.js +80 -35
  4. package/package.json +160 -33
  5. package/src/Arr.js +887 -419
  6. package/src/Async.js +585 -0
  7. package/src/Cache.js +329 -0
  8. package/src/Checker.js +971 -539
  9. package/src/Cli.js +1034 -0
  10. package/src/Color.js +415 -0
  11. package/src/Crypto.js +707 -0
  12. package/src/Emitter.js +289 -0
  13. package/src/Env.js +555 -0
  14. package/src/FS.js +1483 -894
  15. package/src/Func.js +670 -353
  16. package/src/Http.js +538 -0
  17. package/src/Id.js +384 -201
  18. package/src/Logger.js +739 -378
  19. package/src/Num.js +844 -361
  20. package/src/Obj.js +855 -372
  21. package/src/SQLite.js +1308 -1005
  22. package/src/Schema.js +1586 -0
  23. package/src/Str.js +983 -436
  24. package/src/Sys.js +511 -0
  25. package/src/Time.js +1260 -422
  26. package/src/Utils.js +321 -325
  27. package/src/errors.js +292 -0
  28. package/types/index.d.ts +693 -526
  29. package/types/src/Arr.d.ts +455 -145
  30. package/types/src/Arr.d.ts.map +1 -1
  31. package/types/src/Async.d.ts +321 -0
  32. package/types/src/Async.d.ts.map +1 -0
  33. package/types/src/Cache.d.ts +195 -0
  34. package/types/src/Cache.d.ts.map +1 -0
  35. package/types/src/Checker.d.ts +501 -235
  36. package/types/src/Checker.d.ts.map +1 -1
  37. package/types/src/Cli.d.ts +582 -0
  38. package/types/src/Cli.d.ts.map +1 -0
  39. package/types/src/Color.d.ts +294 -0
  40. package/types/src/Color.d.ts.map +1 -0
  41. package/types/src/Crypto.d.ts +534 -0
  42. package/types/src/Crypto.d.ts.map +1 -0
  43. package/types/src/Emitter.d.ts +170 -0
  44. package/types/src/Emitter.d.ts.map +1 -0
  45. package/types/src/Env.d.ts +382 -0
  46. package/types/src/Env.d.ts.map +1 -0
  47. package/types/src/FS.d.ts +686 -238
  48. package/types/src/FS.d.ts.map +1 -1
  49. package/types/src/Func.d.ts +380 -135
  50. package/types/src/Func.d.ts.map +1 -1
  51. package/types/src/Http.d.ts +374 -0
  52. package/types/src/Http.d.ts.map +1 -0
  53. package/types/src/Id.d.ts +149 -68
  54. package/types/src/Id.d.ts.map +1 -1
  55. package/types/src/Logger.d.ts +363 -46
  56. package/types/src/Logger.d.ts.map +1 -1
  57. package/types/src/Num.d.ts +473 -137
  58. package/types/src/Num.d.ts.map +1 -1
  59. package/types/src/Obj.d.ts +390 -104
  60. package/types/src/Obj.d.ts.map +1 -1
  61. package/types/src/SQLite.d.ts +646 -309
  62. package/types/src/SQLite.d.ts.map +1 -1
  63. package/types/src/Schema.d.ts +940 -0
  64. package/types/src/Schema.d.ts.map +1 -0
  65. package/types/src/Str.d.ts +569 -166
  66. package/types/src/Str.d.ts.map +1 -1
  67. package/types/src/Sys.d.ts +269 -0
  68. package/types/src/Sys.d.ts.map +1 -0
  69. package/types/src/Time.d.ts +663 -204
  70. package/types/src/Time.d.ts.map +1 -1
  71. package/types/src/Utils.d.ts +154 -102
  72. package/types/src/Utils.d.ts.map +1 -1
  73. package/types/src/errors.d.ts +292 -0
  74. package/types/src/errors.d.ts.map +1 -0
  75. package/types/index.d.ts.map +0 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,190 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
5
+ [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [2.0.0] - 2026-09-12
8
+
9
+ node-comfort becomes a complete, zero-dependency standard library for Node.js: 23 namespaces and classes,
10
+ more than 500 documented and typed functions, and an editor experience checked on every commit.
11
+
12
+ ### Security
13
+
14
+ - **Prototype pollution fixed** in `obj.set()` and `obj.unflatten()` (1.2.0). A path such as
15
+ `"__proto__.isAdmin"` coming from user input could modify `Object.prototype`. Every object helper
16
+ (`set`, `unset`, `merge`, `mergeWith`, `defaults`, `unflatten`, `clone`, `fromEntries`...) now ignores
17
+ `__proto__`, `constructor` and `prototype` keys. **Upgrade if you pass user-controlled paths or objects
18
+ to these functions.**
19
+ - The 1.x filesystem helpers searched the whole folder tree for a file with the same name when a relative
20
+ path did not exist, which could read, overwrite or delete the wrong file. This implicit search is gone
21
+ (see `fs` below).
22
+ - `id.code()` no longer has a modulo bias (rejection sampling).
23
+
24
+ ### Breaking changes
25
+
26
+ Each item explains what to change. Most projects only need the SQLite and Node.js items.
27
+
28
+ 1. **Node.js 22.13 or newer is required** (`engines`). Node 20 reaches end of life, and 1.x already
29
+ required `node:sqlite`, which is only available without a flag since Node 22.13.
30
+ 2. **Deep imports are no longer allowed**: the package defines an `exports` map. Replace
31
+ `require("@ix-xs/node-comfort/src/Logger")` by `require("@ix-xs/node-comfort").logger`, or by the
32
+ official entry point of the namespace: `require("@ix-xs/node-comfort/logger")`.
33
+ 3. **SQLite methods throw instead of returning `{ error }`.** Failures throw a `nc.errors.SQLiteError`
34
+ (with `sql` and `sqliteCode`, for example `"SQLITE_CONSTRAINT_UNIQUE"`). Success values are unchanged.
35
+ ```js
36
+ // 1.x
37
+ const result = await db.insert("users", data);
38
+ if (result.error) console.error(result.error);
39
+ // 2.0
40
+ try {
41
+ db.insert("users", data);
42
+ } catch (error) {
43
+ if (error.sqliteCode === "SQLITE_CONSTRAINT_UNIQUE") console.error("Email already used");
44
+ }
45
+ ```
46
+ `db.transaction()` re-throws the error after rolling back (it used to return `{ error }`).
47
+ 4. **SQLite methods are synchronous.** They return values directly, like the underlying engine. `await`
48
+ keeps working, but `.then()` chains on their results must be removed. `db.transaction()` still accepts
49
+ async callbacks (it then returns a promise).
50
+ 5. **`db.getAll()` no longer limits to 50 rows and no longer sorts by default.** Pass `{ limit: 50 }` to keep
51
+ a limit, and `{ orderBy: "id", direction: "DESC" }` to keep the old order. When `orderBy` is given without
52
+ `direction`, the order is now ascending (it was descending).
53
+ 6. **SQLite tables are read from the database file.** 1.x only knew the tables created with `createTable()`
54
+ in the same process (`get()` returned `undefined` and `getAll()` returned `[]` for the others). Tables are
55
+ now found through `sqlite_master`, and an unknown table throws a `SQLiteError`.
56
+ 7. **SQLite `BOOLEAN` and `JSON` columns are converted.** Reading a `BOOLEAN` column returns `true`/`false`
57
+ (it returned `1`/`0`) and a `JSON` column returns the parsed value. Writing booleans, objects, arrays and
58
+ dates now works (1.x threw "cannot be bound"). Disable with `new nc.SQLite(path, { booleans: false, json: false })`.
59
+ 8. **`warn`, `error` and `fatal` logs are written to stderr**, like `console.warn` and `console.error`.
60
+ Colors are disabled when the output is not a terminal (files, pipes, CI logs) and with `NO_COLOR`;
61
+ use `FORCE_COLOR=1` to force them.
62
+ 9. **Logger markup: `overline` draws a real overline.** It used to strike the text through; use
63
+ `strikethrough` for that.
64
+ 10. **`func.timeout()` rejects with a `nc.errors.TimeoutError`.** It is still an `Error` with the same
65
+ message; only `error.name` (`"TimeoutError"`) and `error.code` (`"ETIMEDOUT"`) are new.
66
+ 11. **`num.round()` rounds negative halves away from zero** (`-2.5` gives `-3`, it gave `-2`), consistently
67
+ with positive numbers, and never returns `-0`. Decimal precision is fixed: `round(1.005, 2)` is `1.01`.
68
+ 12. **`str.length()`, `str.reverse()`, `str.truncate()` and `str.center()` count graphemes**, not UTF-16
69
+ code units: `str.length("👨‍👩‍👧")` is `1`, and emoji or accents are never cut in half.
70
+ 13. **The filesystem helpers no longer search the folder tree** when a relative path does not exist
71
+ (see Security). Use the new `nc.find("config.json")` to search explicitly.
72
+ 14. **`dontCrash()` only removes the listeners it added.** 1.x removed every `uncaughtException`, `exit`
73
+ and signal listener of the process, including those of other libraries. Calling it again replaces the
74
+ previous handlers, and the returned controller has `dispose()`.
75
+ 15. **Stricter or more complete validators**: `isEmail()` accepts international addresses but rejects
76
+ consecutive or trailing dots; `isUUID()` accepts versions 1 to 8 and the nil/max UUIDs (use
77
+ `{ version }` to restrict); `isURL()` accepts an options object (`protocols`, `requireTld`).
78
+ 16. **`JSONString()` converts `Map` to objects and `Set` to arrays** (they gave `{}`), and an object used
79
+ twice is serialized twice instead of being replaced by `"[Circular]"` (only real cycles are).
80
+
81
+ ### Deprecated
82
+
83
+ - `id.hash()`, `id.hmac()` and `id.safeEqual()` moved to `nc.crypto` (same signatures). The aliases keep
84
+ working and will be removed in 3.0.0.
85
+
86
+ ### Added
87
+
88
+ **Packaging and editor experience**
89
+ - Lazy loading: `require("@ix-xs/node-comfort")` takes about 3 ms, and each namespace is loaded the first
90
+ time it is used. A script that only logs never loads the database, the HTTP client or the crypto code.
91
+ - An entry point per namespace (`@ix-xs/node-comfort/str`, `/http`, `/sqlite`...), which keeps ES module
92
+ imports light and makes bundling easier.
93
+ - A documentation website at https://ix-xs.github.io/node-comfort/: guides for every namespace, the full
94
+ API reference, recipes, and search.
95
+ - Complete TypeScript declarations generated from the JSDoc: hover documentation with examples for every
96
+ function, parameter and option, completion after `nc.` and `nodeComfort.`, auto-import of `nc`,
97
+ `nodeComfort` and every flat helper, type guards, typed dot paths, schema inference, generic caches,
98
+ typed events, SQLite columns suggested in `where` filters.
99
+ - ES module named imports (`import { str, isEmail, nc } from "@ix-xs/node-comfort"`) and
100
+ `const { nc } = require(...)`.
101
+ - `docs/API.md`, a complete API reference generated from the types.
102
+ - Tests (`node --test`) and CI on Linux, macOS and Windows with Node 22, 24 and the latest release;
103
+ editor checks with TypeScript 5.9, 6 and 7.
104
+
105
+ **New namespaces and classes**
106
+ - `nc.crypto`: `hashPassword`/`verifyPassword`/`needsRehash` (scrypt), `encrypt`/`decrypt` (AES-256-GCM),
107
+ `signJWT`/`verifyJWT`/`decodeJWT` (HS256/384/512), `totp`/`verifyTOTP`/`totpSecret`/`totpURI` (2FA),
108
+ `hash`, `hmac`, `safeEqual`, `generateKey`, `randomBytes`, `randomInt`, `toBase64`, `fromBase64`.
109
+ - `nc.color`: chainable terminal colors (`color.red.bold("x")`), hex/RGB/256 colors, automatic level
110
+ detection and downgrade, `strip`, `width`, `link`, `gradient`, `create`.
111
+ - `nc.cli`: typed `args` with generated `--help`, `prompt`, `password`, `confirm`, `select`,
112
+ `multiselect`, `spinner`, `progress`, `table`, `box`, `isInteractive`, `size`, `clear`.
113
+ - `nc.sys`: `run` (no shell, Windows-safe arguments), `exec`, `which`, `open`, `onShutdown` (graceful
114
+ shutdown), `isWindows`, `isMac`, `isLinux`, `isCI`, `isDocker`, `isWSL`, `info`, `memory`.
115
+ - `nc.async`: `map`/`forEach`/`filter` with a concurrency limit, `series`, `limit`, `queue` (priorities,
116
+ timeouts), `mutex`, `deferred`, `settle`, `props`, `poll`, `sleep`.
117
+ - `nc.schema`: schema validation with TypeScript inference (`string`, `number`, `boolean`, `bigint`, `date`,
118
+ `literal`, `enum`, `array`, `object`, `union`, `tuple`, `record`, `lazy`, `instanceOf`, `custom`, `coerce`,
119
+ `refine`, `transform`, `default`, `catch`...).
120
+ - `nc.http`: HTTP client on top of `fetch` with JSON, query objects, auth, timeouts, retries with
121
+ `Retry-After`, hooks, clients (`create`/`extend`), downloads with progress.
122
+ - `nc.env`: `.env` parser and loader, typed getters (`number`, `bool`, `port`, `url`, `duration`, `list`,
123
+ `json`, `oneOf`) and `validate()` reporting every invalid variable at once. `NODE_COMFORT_DOTENV=false`
124
+ disables the automatic `.env` loading.
125
+ - `nc.errors`: `NodeComfortError`, `AssertionError`, `TimeoutError`, `AbortError`, `ValidationError`,
126
+ `HttpError`, `JWTError`, `ProcessError`, `SQLiteError`, each with a stable `code`.
127
+ - `nc.Cache`: LRU cache with TTL, `getOrSet` (concurrent loads shared), `wrap`, `prune`, `stats`.
128
+ - `nc.Emitter`: typed event emitter with `once`, `onAny`, `emitAsync`, `waitFor`, `iterate`.
129
+
130
+ **Existing modules**
131
+ - Logger: `trace`, `fatal` and `silent` levels, `LOG_LEVEL`, `LOG_FORMAT=json`, structured fields,
132
+ `createLogger` with scope, file output with rotation, `child` (its `fields` are added to the parent's,
133
+ for per-request loggers), `table`, `box`, `divider`, markup colors in
134
+ hex and RGB, `setLevel`, `configure`; every function returns the logger for chaining.
135
+ - FS: `glob` (relative patterns, or absolute ones that search where they point), `find`, `readLines`,
136
+ `writeFile` (atomic), `ensureFolder`, `ensureFile`, `touch`, `remove`,
137
+ `copy`, `move`, `isFile`, `isFolder`, `folderSize`, `tempFolder`, `sanitizeFilename`, chunked
138
+ `hashFile`, `readJSON` with comments, atomic `writeJSON`, debounced `watch`.
139
+ - Checker: about 30 new guards (`isIP`, `isPort`, `isSemver`, `isJWT`, `isHexColor`, `isBase64`,
140
+ `isCreditCard`, `isArrayOf`, `isOneOf`, `isClass`, `isBlank`...), `assert` and `assertType`.
141
+ - `str`, `num`, `arr`, `obj`, `func`, `time`, `id`: more than 120 new functions, among them `str.dedent`,
142
+ `str.wrap`, `str.plural`, `str.closest`, `str.mask`, `num.currency`, `num.percentile`, `num.parseBytes`,
143
+ `arr.paginate`, `arr.windows`, `arr.cartesian`, `obj.diff`, `obj.mergeWith`, `func.pipe`,
144
+ `time.setLocale`/`time.setTimezone` (every date function in any language and time zone),
145
+ `time.calendar`, `time.cron`, `time.every`, `time.nextRun`, `id.uuidv7`, `id.snowflake`.
146
+ - `num.setLocale()` sets the default language of `format`, `currency`, `percent`, `abbreviate`,
147
+ `ordinal` and `formatBytes`, like `time.setLocale()` does for dates.
148
+ - SQLite: rich `where` operators (`gt`, `in`, `like`, `between`, `$or`...), `insertMany`, `exists`,
149
+ `tables`, `columns`, `hasTable`, `table()` handles, `migrate()` (versioned with `user_version`),
150
+ `backup()`, `vacuum()`, `iterate()`, `fn()` (SQL functions in JavaScript), nested transactions with
151
+ savepoints, prepared statement cache, `readOnly`/`busyTimeout` options, `using` support.
152
+
153
+ ### Fixed
154
+
155
+ - `const { merge } = nc.obj` (and any destructured helper) threw because functions relied on `this`.
156
+ - `titleCase()` broke words with accented letters.
157
+ - Logger groups were not indented consistently, and logging a circular object crashed.
158
+ - `unescapeHTML()` now decodes numeric entities (`'`, `'`) and ` `.
159
+ - `memoize()` no longer keeps rejected promises: a failed call is retried next time.
160
+ - `watch()` follows the real path of what it watches, so a short (8.3) or symlinked path no longer
161
+ crashes the watcher on Windows.
162
+ - Dates, maps, sets and plain objects coming from a worker or a `vm` context are recognized by
163
+ `obj`, `schema`, `time`, `checker.isPlainObject` and `JSONString` (1.x compared prototypes, which
164
+ are not shared between realms).
165
+
166
+ ### Migration checklist
167
+
168
+ 1. Upgrade Node.js to 22.13+.
169
+ 2. Replace deep imports by the namespaces (`nc.logger`, `nc.fs`...).
170
+ 3. SQLite: replace `if (result.error)` checks by `try/catch`, add `{ limit, orderBy, direction: "DESC" }`
171
+ where you relied on the old `getAll()` defaults, and check code that compared `BOOLEAN` columns to `1`/`0`.
172
+ 4. If you parse your application's output, remember that warnings and errors now go to stderr.
173
+ 5. Replace `nc.id.hash/hmac/safeEqual` by `nc.crypto.hash/hmac/safeEqual` (optional until 3.0).
174
+
175
+ ## [1.2.0]
176
+
177
+ ### Added
178
+
179
+ - Namespaces `str`, `num`, `arr`, `obj`, `func`, `time` and `id`.
180
+ - Checker: 22 new guards (`isEmail`, `isURL`, `isUUID`, `isEmpty`, `isPlainObject`...).
181
+ - Logger: `info`, `success`, `warn`, `error` and `debug` levels.
182
+ - FS: `readJSON`, `writeJSON`, `appendFile`, `exists`, `stat`, `fileSize`, `hashFile`, `emptyFolder`.
183
+ - SQLite: `:memory:` databases.
184
+
185
+ ### Fixed
186
+
187
+ - SQLite: the folder of the database was created in one place and the file opened in another.
188
+
189
+ [2.0.0]: https://github.com/ix-xs/node-comfort/compare/v1.2.0...v2.0.0
190
+ [1.2.0]: https://github.com/ix-xs/node-comfort/releases/tag/v1.2.0