@ix-xs/node-comfort 2.0.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.
- package/CHANGELOG.md +150 -0
- package/README.md +32 -30
- package/index.js +3 -3
- package/package.json +8 -7
- package/src/Arr.js +222 -58
- package/src/Async.js +322 -90
- package/src/Cache.js +148 -44
- package/src/Checker.js +257 -26
- package/src/Cli.js +404 -145
- package/src/Color.js +224 -83
- package/src/Crypto.js +481 -106
- package/src/Emitter.js +104 -37
- package/src/Env.js +176 -42
- package/src/FS.js +203 -60
- package/src/Func.js +226 -76
- package/src/Http.js +311 -149
- package/src/Id.js +281 -96
- package/src/Logger.js +302 -78
- package/src/Num.js +182 -60
- package/src/Obj.js +340 -125
- package/src/SQLite.js +426 -105
- package/src/Schema.js +602 -87
- package/src/Str.js +316 -86
- package/src/Sys.js +197 -54
- package/src/Time.js +572 -317
- package/src/Utils.js +62 -41
- package/src/errors.js +54 -11
- package/src/internal/shared.js +415 -0
- package/types/index.d.ts +59 -17
- package/types/src/Arr.d.ts +78 -0
- package/types/src/Arr.d.ts.map +1 -1
- package/types/src/Async.d.ts +52 -1
- package/types/src/Async.d.ts.map +1 -1
- package/types/src/Cache.d.ts +33 -7
- package/types/src/Cache.d.ts.map +1 -1
- package/types/src/Checker.d.ts +155 -2
- package/types/src/Checker.d.ts.map +1 -1
- package/types/src/Cli.d.ts +97 -15
- package/types/src/Cli.d.ts.map +1 -1
- package/types/src/Color.d.ts +7 -1
- package/types/src/Color.d.ts.map +1 -1
- package/types/src/Crypto.d.ts +99 -13
- package/types/src/Crypto.d.ts.map +1 -1
- package/types/src/Emitter.d.ts +36 -17
- package/types/src/Emitter.d.ts.map +1 -1
- package/types/src/Env.d.ts +31 -1
- package/types/src/Env.d.ts.map +1 -1
- package/types/src/FS.d.ts +36 -5
- package/types/src/FS.d.ts.map +1 -1
- package/types/src/Func.d.ts +147 -19
- package/types/src/Func.d.ts.map +1 -1
- package/types/src/Http.d.ts +113 -43
- package/types/src/Http.d.ts.map +1 -1
- package/types/src/Id.d.ts +60 -8
- package/types/src/Id.d.ts.map +1 -1
- package/types/src/Logger.d.ts +53 -2
- package/types/src/Logger.d.ts.map +1 -1
- package/types/src/Num.d.ts +48 -7
- package/types/src/Num.d.ts.map +1 -1
- package/types/src/Obj.d.ts +67 -4
- package/types/src/Obj.d.ts.map +1 -1
- package/types/src/SQLite.d.ts +123 -14
- package/types/src/SQLite.d.ts.map +1 -1
- package/types/src/Schema.d.ts +256 -7
- package/types/src/Schema.d.ts.map +1 -1
- package/types/src/Str.d.ts +49 -1
- package/types/src/Str.d.ts.map +1 -1
- package/types/src/Sys.d.ts +51 -6
- package/types/src/Sys.d.ts.map +1 -1
- package/types/src/Time.d.ts +130 -34
- package/types/src/Time.d.ts.map +1 -1
- package/types/src/Utils.d.ts +15 -11
- package/types/src/Utils.d.ts.map +1 -1
- package/types/src/errors.d.ts +27 -3
- package/types/src/errors.d.ts.map +1 -1
- package/types/src/internal/shared.d.ts +123 -0
- package/types/src/internal/shared.d.ts.map +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,155 @@ All notable changes to this project are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [2.1.0] - 2026-10-12
|
|
8
|
+
|
|
9
|
+
Every module was read again, line by line. The result: about sixty new functions and options, a hot path
|
|
10
|
+
that is several times faster almost everywhere, a long list of edge cases fixed, and a new documentation
|
|
11
|
+
website. Nothing has to change in a project that used 2.0 the documented way. The few behaviours that
|
|
12
|
+
did change are listed under "Changed".
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **logger**: `redact` hides the keys you name in everything that is logged, `onLog` receives each entry
|
|
17
|
+
(`LogEntry`) to forward it to another service, and `DEBUG=db,http:*` chooses which scopes print their
|
|
18
|
+
debug lines.
|
|
19
|
+
- **fs**: `fs.findUp()` (also `nc.findUp()`) walks up the folders to find a file, `writeFile()` and
|
|
20
|
+
`writeJSON()` take `fsync` to wait for the disk, and watchers emit `"error"`.
|
|
21
|
+
- **checker**: `isHostname`, `isMACAddress`, `isIBAN`, `isE164`, `isObjectId`, `isULID`, `isDataURL`,
|
|
22
|
+
`isMimeType`, `isTimeZone`, `isLocale`, `isCron` and `isASCII`.
|
|
23
|
+
- **env**: `env.example()` writes a `.env.example` from your specification, and `load({ cascade })` reads
|
|
24
|
+
`.env`, `.env.local`, `.env.{mode}` and `.env.{mode}.local` in the usual order.
|
|
25
|
+
- **schema**: `pipe()`, `discriminatedUnion()`, `toJSONSchema()`, object `required()`, `merge()` and
|
|
26
|
+
`keyof()`, number `gt()`, `lt()` and `safe()`, string `date()`, `slug()`, `hex()`, `base64()`, `ulid()`,
|
|
27
|
+
`semver()` and `hostname()`. `safeParse()` gives the list of `issues` without building an error.
|
|
28
|
+
- **http**: `params` fills a path such as `"users/:id"`, `schema` validates the response and gives
|
|
29
|
+
`data` its type,
|
|
30
|
+
`cookies` lists every `Set-Cookie`, headers can be a `Headers` object or pairs, and retries take `jitter`
|
|
31
|
+
and text delays (`"2s"`).
|
|
32
|
+
- **SQLite**: filters and sorts on JSON paths (`"settings.theme"`), `paginate()`, `increment()`,
|
|
33
|
+
`onConflict` for `insert()` and `insertMany()`, `defaultExpression` for columns,
|
|
34
|
+
`transaction({ immediate })`, a `synchronous` option, and reads from views and temporary tables.
|
|
35
|
+
- **time**: `time.parse()` reads a date from text with a pattern, `isSame()`, `range()`, `fromUnix()`, the
|
|
36
|
+
`Do` and `z` tokens, and `formatDuration()` accepts text such as `"90m"`.
|
|
37
|
+
- **id**: `uuidv5()`, `objectId()` and `prefixed()`.
|
|
38
|
+
- **crypto**: `verifyHmac()` for webhook signatures, `generateKeyPair()`, and JSON Web Tokens signed with
|
|
39
|
+
RSA, ECDSA or Ed25519 keys (`RS256`, `PS256`, `ES256`, `EdDSA`...).
|
|
40
|
+
- **cli**: `cli.tree()`, `cli.spin()` runs a promise under a spinner, `args()` learns commands
|
|
41
|
+
(`commands`), `env` fallbacks, `examples` in the help and `choices` for numbers. Tables accept cells of
|
|
42
|
+
several lines. Menus understand Home, End, Page Up, Page Down and Escape.
|
|
43
|
+
- **color**: `color.truncate()` cuts colored text to a width without breaking its colors.
|
|
44
|
+
- **sys**: `shutdown()`, `freePort()` and `localIP()`.
|
|
45
|
+
- **func**: `batch()` groups calls into one, `dedupe()` shares a call that is already running, and
|
|
46
|
+
`pipeAsync()`.
|
|
47
|
+
- **async**: `parallel()`, `rateLimit()` and `abortable()`.
|
|
48
|
+
- **Cache**: `getOrSet(..., { staleWhileRevalidate })` answers with the old value while the new one loads,
|
|
49
|
+
and `resetStats()`.
|
|
50
|
+
- **Emitter**: `on()` and `once()` take `{ signal }`, and `listeners()`.
|
|
51
|
+
- **str**: `upperFirst`, `lowerFirst`, `humanize` and `chunk`. **num**: `pad`, `percentChange` and
|
|
52
|
+
`product`. **arr**: `duplicates`, `xor`, `takeWhile`, `dropWhile` and `toSentence`. **obj**: `update`,
|
|
53
|
+
`sortKeys` and `paths`.
|
|
54
|
+
- **Durations are text everywhere.** The last options that only took milliseconds (`debounce`, `throttle`,
|
|
55
|
+
`memoize`, `retry`, `timeout`, `delay`, `waitFor`...) accept `"5m"` or `"1.5s"` like the rest of the
|
|
56
|
+
package.
|
|
57
|
+
- Errors serialize with `JSON.stringify()` (name, code, message, fields and cause), and `instanceof` works
|
|
58
|
+
across two copies of the package.
|
|
59
|
+
|
|
60
|
+
### Faster
|
|
61
|
+
|
|
62
|
+
Measured on the same machine, before and after, with Node 24.
|
|
63
|
+
|
|
64
|
+
| Operation | Speedup |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| `nc.info()` | 124x |
|
|
67
|
+
| `time.parseDuration("5m")` | 68x |
|
|
68
|
+
| `str.plural()` | 57x |
|
|
69
|
+
| `time.format()` with month and day names | 39x |
|
|
70
|
+
| `id.code()` | 39x |
|
|
71
|
+
| `id.uuidv7()` | 28x |
|
|
72
|
+
| `num.format()` | 23x |
|
|
73
|
+
| `checker.isIP()` | 19x |
|
|
74
|
+
| `obj.get()` with a dot path | 14x |
|
|
75
|
+
| `emitter.emit()` | 10x |
|
|
76
|
+
| `schema.is()` on invalid data | 9x |
|
|
77
|
+
| `schema.safeParse()` on invalid data | 5x |
|
|
78
|
+
| `db.get()` and `db.getAll()` | 3x to 4x |
|
|
79
|
+
|
|
80
|
+
`sys.which("node")` went from 23 ms to 0.13 ms on Windows. What is slow in JavaScript (`Intl` objects,
|
|
81
|
+
random bytes, stack traces, prepared statements) is now created once and reused.
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
Behaviours that differ from 2.0. Each one fixes something that was wrong or unsafe.
|
|
86
|
+
|
|
87
|
+
- **logger**: `DEBUG=name` only turns on the debug lines of the scopes it names (it used to turn on all
|
|
88
|
+
of them). `DEBUG=*`, `DEBUG=1` and `LOG_LEVEL=debug` show everything.
|
|
89
|
+
- **time**: `startOf()`, `endOf()`, `add()` and `diff()` follow `setTimezone()` instead of the system zone.
|
|
90
|
+
Adding whole days or weeks keeps the time of day when the clocks change in between (it added 24 hours
|
|
91
|
+
per day); `"24h"` stays exact. `add(date, "soon")` throws a `TypeError` (unreadable text used to add
|
|
92
|
+
nothing), and so does a unit that does not exist (it was read as milliseconds).
|
|
93
|
+
- **crypto**: `decrypt()` always fails with a `NodeComfortError` whose code is `ERR_DECRYPT` (malformed
|
|
94
|
+
input used to throw a `TypeError`), and refuses shortened authentication tags. `hash()` and `hmac()`
|
|
95
|
+
throw a `TypeError` for `null`, `undefined`, plain objects and empty secrets. `safeEqual()` returns
|
|
96
|
+
`false` when a value is missing. A wrong key type for a token is a `TypeError`, and the algorithms a
|
|
97
|
+
token may use follow from the key that verifies it.
|
|
98
|
+
- **cli**: leaving a menu or a password prompt with Ctrl+C or Escape rejects with an `AbortError`.
|
|
99
|
+
`cli.table([])` returns `""`. The
|
|
100
|
+
`LineReader` type is gone from the public types.
|
|
101
|
+
- **http**: the query and headers of a call are added to those of the client instead of replacing them.
|
|
102
|
+
A request whose body is a stream is never retried. With `responseType: "stream"` the timeout stops when
|
|
103
|
+
the headers arrive. `download()` writes to a temporary file first, so a failed download never destroys
|
|
104
|
+
the file that was there.
|
|
105
|
+
- **schema**: `pick()`, `omit()`, `partial()` and `extend()` keep `strict()`. Names inherited from
|
|
106
|
+
`Object.prototype` (`toString`, `constructor`) are never read from the input.
|
|
107
|
+
- **SQLite**: a column whose default is `CURRENT_TIMESTAMP` gets the time of the insert (it used to store
|
|
108
|
+
that text), and with `dates: true` the dates SQLite writes itself are read as UTC. Columns of joins and renamed columns are converted like the others, with Node 22.16 or later.
|
|
109
|
+
- **env**: in `load()`, the first file that defines a variable wins, whatever `override` says. `override`
|
|
110
|
+
only decides whether files may replace what was already in the environment. A file you load yourself
|
|
111
|
+
wins over the `.env` loaded at startup, so `.env.local` and `cascade` work without turning anything off.
|
|
112
|
+
A reference such as `${HOST}` takes the value `HOST` really ends up with.
|
|
113
|
+
- **sys**: `run()` rejects on a timeout it cannot read (it used to mean no timeout), and on Windows a
|
|
114
|
+
timeout or an abort stops the whole process tree.
|
|
115
|
+
- **fs**: an atomic write keeps the permissions of the file it replaces.
|
|
116
|
+
- **func**: `retry()` stops as soon as the function is aborted. `memoize()` no longer confuses
|
|
117
|
+
`f(undefined)` with `f(null)`, and accepts `bigint` arguments.
|
|
118
|
+
- **num**: `min()` and `max()` return `NaN` when one value is `NaN`, like `Math.min()`. `sum([0.1, 0.2, 0.3])`
|
|
119
|
+
is `0.6`.
|
|
120
|
+
- **obj**: `isEmpty()` looks inside a `Map` and a `Set`, and is `false` for a `Date`, a `RegExp` and an
|
|
121
|
+
`Error`. `unset()` on an array index removes the item instead of leaving a hole. `clone()` keeps class
|
|
122
|
+
instances and copies buffers. `merge()` never shares a nested object with its inputs.
|
|
123
|
+
- **checker**: `isEmpty()` is `false` for a `Date`, a `RegExp` and an `Error`.
|
|
124
|
+
- **utils**: `JSONString()` never throws, and writes an error with its name, message and stack.
|
|
125
|
+
|
|
126
|
+
### Fixed
|
|
127
|
+
|
|
128
|
+
- Timers longer than 24.8 days (`wait("30d")`, cache expiry, `timeout()`) no longer fire at once.
|
|
129
|
+
- Object helpers (`pick`, `omit`, `filter`, `mapValues`, `flatten`, `groupBy`, `keyBy`, `countBy`, `props`,
|
|
130
|
+
`env.parse`...) are safe with keys named `__proto__`, `constructor` or `toString`.
|
|
131
|
+
- `safeEqual()` no longer reveals the length of the secret.
|
|
132
|
+
- `str.stripTags()` leaves `a < b and c > d` alone, `unescapeHTML()` accepts invalid code points,
|
|
133
|
+
`capitalize()` handles letters outside the basic plane, and padding counts what you see.
|
|
134
|
+
- `num.formatBytes()` and `num.abbreviate()` change unit when rounding reaches the next one (`"1 MB"`,
|
|
135
|
+
not `"1024 KB"`).
|
|
136
|
+
- `isYesterday()` and `isTomorrow()` are right on the days the clocks change.
|
|
137
|
+
- `cache.getOrSet()` respects a `delete()`, a `clear()` or a `set()` made while the value was loading.
|
|
138
|
+
- A shutdown handler that never finishes can no longer let the process end with a success code.
|
|
139
|
+
- `sys.run()` and `sys.exec()` settle after a timeout or an abort even when something the command started
|
|
140
|
+
keeps its output open. They used to wait for it.
|
|
141
|
+
- An async `onLog` hook that fails no longer stops the process.
|
|
142
|
+
- Deleting a watched folder on Windows sent events without end. The watcher now reports it once and stops.
|
|
143
|
+
- `http.download()` reports a connection cut in the middle as an `HttpError` with the code `ERR_NETWORK`.
|
|
144
|
+
- `str.truncate()` never returns more than the length asked for, even when the omission is longer.
|
|
145
|
+
- `emitter.off()` removes a listener added with `once()`.
|
|
146
|
+
- `http` keeps every `Set-Cookie` header and reads the status of an error response in all cases.
|
|
147
|
+
- Tables no longer fail on very large inputs, and progress bars print labels that contain `$`.
|
|
148
|
+
|
|
149
|
+
### Documentation
|
|
150
|
+
|
|
151
|
+
- A new website, in English and in French, with a search, a page for every namespace generated from the
|
|
152
|
+
types, and a landing page whose examples are real files, run at every build.
|
|
153
|
+
- The old addresses (`/guide/logger.html`, `/api/str.html`) redirect to the new pages.
|
|
154
|
+
- `docs/API.md` is gone: the reference lives on the website, and in your editor.
|
|
155
|
+
|
|
7
156
|
## [2.0.0] - 2026-09-12
|
|
8
157
|
|
|
9
158
|
node-comfort becomes a complete, zero-dependency standard library for Node.js: 23 namespaces and classes,
|
|
@@ -186,5 +335,6 @@ Each item explains what to change. Most projects only need the SQLite and Node.j
|
|
|
186
335
|
|
|
187
336
|
- SQLite: the folder of the database was created in one place and the file opened in another.
|
|
188
337
|
|
|
338
|
+
[2.1.0]: https://github.com/ix-xs/node-comfort/compare/v2.0.0...v2.1.0
|
|
189
339
|
[2.0.0]: https://github.com/ix-xs/node-comfort/compare/v1.2.0...v2.0.0
|
|
190
340
|
[1.2.0]: https://github.com/ix-xs/node-comfort/releases/tag/v1.2.0
|
package/README.md
CHANGED
|
@@ -15,9 +15,9 @@ One package, zero dependencies, documented right in your editor.
|
|
|
15
15
|
[](./LICENSE)
|
|
16
16
|
|
|
17
17
|
[Documentation](https://ix-xs.github.io/node-comfort/) •
|
|
18
|
-
[Getting started](https://ix-xs.github.io/node-comfort/
|
|
19
|
-
[API reference](https://ix-xs.github.io/node-comfort/
|
|
20
|
-
[Recipes](https://ix-xs.github.io/node-comfort/
|
|
18
|
+
[Getting started](https://ix-xs.github.io/node-comfort/start/getting-started/) •
|
|
19
|
+
[API reference](https://ix-xs.github.io/node-comfort/reference/) •
|
|
20
|
+
[Recipes](https://ix-xs.github.io/node-comfort/recipes/) •
|
|
21
21
|
[Changelog](./CHANGELOG.md)
|
|
22
22
|
|
|
23
23
|
</div>
|
|
@@ -57,7 +57,7 @@ Node.js 22.13 or newer. That's the first version where `node:sqlite` works witho
|
|
|
57
57
|
|
|
58
58
|
- **Zero dependencies.** Built only on Node's own modules. No install scripts, nothing else to audit or keep up to date.
|
|
59
59
|
- **Your editor already knows it.** Every function, parameter and option is typed and documented, with examples. Type `nc.` and look around. It works in plain JavaScript too.
|
|
60
|
-
- **Fast to load.** Namespaces load the first time you use them. Requiring the package takes about
|
|
60
|
+
- **Fast to load.** Namespaces load the first time you use them. Requiring the package takes about 4 ms, and a script that only logs never loads the database or the HTTP client.
|
|
61
61
|
- **Safe by default.** Prototype-pollution-proof objects, scrypt passwords, AES-256-GCM, constant-time comparisons, parameterized SQL, atomic file writes.
|
|
62
62
|
- **One way of doing things.** Durations are always `"5m"` or milliseconds, options always come last, and every error has a stable `code`.
|
|
63
63
|
- **Tested everywhere.** Linux, macOS and Windows, Node.js 22 and 24, TypeScript 5.9, 6 and 7.
|
|
@@ -66,29 +66,29 @@ Node.js 22.13 or newer. That's the first version where `node:sqlite` works witho
|
|
|
66
66
|
|
|
67
67
|
| Namespace | What it's for | Often replaces |
|
|
68
68
|
| --- | --- | --- |
|
|
69
|
-
| [Logger](https://ix-xs.github.io/node-comfort/
|
|
70
|
-
| [`fs`](https://ix-xs.github.io/node-comfort/
|
|
71
|
-
| [`checker`](https://ix-xs.github.io/node-comfort/
|
|
72
|
-
| [`env`](https://ix-xs.github.io/node-comfort/
|
|
73
|
-
| [`schema`](https://ix-xs.github.io/node-comfort/
|
|
74
|
-
| [`http`](https://ix-xs.github.io/node-comfort/
|
|
75
|
-
| [`SQLite`](https://ix-xs.github.io/node-comfort/
|
|
76
|
-
| [`time`](https://ix-xs.github.io/node-comfort/
|
|
77
|
-
| [`str`](https://ix-xs.github.io/node-comfort/
|
|
78
|
-
| [`num`](https://ix-xs.github.io/node-comfort/
|
|
79
|
-
| [`arr`](https://ix-xs.github.io/node-comfort/
|
|
80
|
-
| [`obj`](https://ix-xs.github.io/node-comfort/
|
|
81
|
-
| [`func`](https://ix-xs.github.io/node-comfort/
|
|
82
|
-
| [`async`](https://ix-xs.github.io/node-comfort/
|
|
83
|
-
| [`Cache`](https://ix-xs.github.io/node-comfort/
|
|
84
|
-
| [`Emitter`](https://ix-xs.github.io/node-comfort/
|
|
85
|
-
| [`id`](https://ix-xs.github.io/node-comfort/
|
|
86
|
-
| [`crypto`](https://ix-xs.github.io/node-comfort/
|
|
87
|
-
| [`cli`](https://ix-xs.github.io/node-comfort/
|
|
88
|
-
| [`color`](https://ix-xs.github.io/node-comfort/
|
|
89
|
-
| [`sys`](https://ix-xs.github.io/node-comfort/
|
|
90
|
-
| [`utils`](https://ix-xs.github.io/node-comfort/
|
|
91
|
-
| [`errors`](https://ix-xs.github.io/node-comfort/
|
|
69
|
+
| [Logger](https://ix-xs.github.io/node-comfort/essentials/logger/) | Colorful logs, levels, JSON output, log files with rotation | `chalk`, `pino`, `winston` |
|
|
70
|
+
| [`fs`](https://ix-xs.github.io/node-comfort/essentials/fs/) | Files and folders without try/catch, atomic writes, glob, watch | `fs-extra`, `glob`, `rimraf` |
|
|
71
|
+
| [`checker`](https://ix-xs.github.io/node-comfort/essentials/checker/) | 70+ type guards and validators, `assert` | `is`, `validator` |
|
|
72
|
+
| [`env`](https://ix-xs.github.io/node-comfort/essentials/env/) | `.env` loading, typed and validated configuration | `dotenv`, `envalid` |
|
|
73
|
+
| [`schema`](https://ix-xs.github.io/node-comfort/data/schema/) | Data validation with TypeScript inference | `zod`, `yup`, `joi` |
|
|
74
|
+
| [`http`](https://ix-xs.github.io/node-comfort/system/http/) | `fetch` with JSON, retries, timeouts, validated responses, hooks, downloads | `axios`, `got`, `ky` |
|
|
75
|
+
| [`SQLite`](https://ix-xs.github.io/node-comfort/system/sqlite/) | CRUD, filters, JSON columns, pagination, transactions, migrations | `better-sqlite3` and helpers |
|
|
76
|
+
| [`time`](https://ix-xs.github.io/node-comfort/data/time/) | Formatting in any language and time zone, durations, date math, cron | `dayjs`, `ms`, `node-cron` |
|
|
77
|
+
| [`str`](https://ix-xs.github.io/node-comfort/data/str/) | Case conversion, slugs, emoji-safe truncation, fuzzy matching, plurals | `lodash`, `slugify`, `leven` |
|
|
78
|
+
| [`num`](https://ix-xs.github.io/node-comfort/data/num/) | Exact rounding, statistics, currencies, bytes | `numeral`, `pretty-bytes` |
|
|
79
|
+
| [`arr`](https://ix-xs.github.io/node-comfort/data/arr/) | Chunk, group, multi-key sort, paginate, set operations | `lodash` |
|
|
80
|
+
| [`obj`](https://ix-xs.github.io/node-comfort/data/obj/) | Deep clone, merge, equal and diff, typed dot paths | `lodash`, `deepmerge`, `dequal` |
|
|
81
|
+
| [`func`](https://ix-xs.github.io/node-comfort/flow/func/) | Debounce, throttle, memoize, retry with backoff, timeout | `p-retry`, `p-timeout` |
|
|
82
|
+
| [`async`](https://ix-xs.github.io/node-comfort/flow/async/) | Concurrency limits, queues, mutex, polling | `p-limit`, `p-map`, `p-queue` |
|
|
83
|
+
| [`Cache`](https://ix-xs.github.io/node-comfort/flow/cache/) | LRU cache with TTL, loaders and statistics | `lru-cache` |
|
|
84
|
+
| [`Emitter`](https://ix-xs.github.io/node-comfort/flow/emitter/) | Typed events, `waitFor`, async iteration | `mitt`, `emittery` |
|
|
85
|
+
| [`id`](https://ix-xs.github.io/node-comfort/data/id/) | UUID v4, v5 and v7, ULID, nanoid, ObjectId, tokens, Snowflakes | `uuid`, `ulid`, `nanoid` |
|
|
86
|
+
| [`crypto`](https://ix-xs.github.io/node-comfort/system/crypto/) | Passwords, encryption, JWT, TOTP two-factor codes | `bcrypt`, `jsonwebtoken`, `otplib` |
|
|
87
|
+
| [`cli`](https://ix-xs.github.io/node-comfort/system/cli/) | Typed arguments and subcommands, prompts, menus, spinners, progress bars, tables, trees | `commander`, `inquirer`, `ora` |
|
|
88
|
+
| [`color`](https://ix-xs.github.io/node-comfort/system/color/) | Chainable terminal colors, truecolor, gradients, links | `chalk`, `picocolors` |
|
|
89
|
+
| [`sys`](https://ix-xs.github.io/node-comfort/system/sys/) | Run commands, `which`, graceful shutdown, platform detection | `execa`, `which` |
|
|
90
|
+
| [`utils`](https://ix-xs.github.io/node-comfort/essentials/utils/) | `wait`, safe JSON, crash guard | |
|
|
91
|
+
| [`errors`](https://ix-xs.github.io/node-comfort/essentials/errors/) | Error classes with stable codes | |
|
|
92
92
|
|
|
93
93
|
The logger, `fs`, `checker` and `utils` helpers are also available at the top level: `nc.info()`, `nc.readJSON()`, `nc.isEmail()`, `nc.wait()`.
|
|
94
94
|
|
|
@@ -104,7 +104,7 @@ import nc from "@ix-xs/node-comfort";
|
|
|
104
104
|
import { slugify } from "@ix-xs/node-comfort/str"; // loads only what it needs
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
Every namespace has its own entry point (`@ix-xs/node-comfort/http`, `/sqlite`, `/schema`...). In an ES module, importing from these keeps startup lean. See [Performance](https://ix-xs.github.io/node-comfort/
|
|
107
|
+
Every namespace has its own entry point (`@ix-xs/node-comfort/http`, `/sqlite`, `/schema`...). In an ES module, importing from these keeps startup lean. See [Performance](https://ix-xs.github.io/node-comfort/start/performance/).
|
|
108
108
|
|
|
109
109
|
TypeScript needs no setup: the types ship with the package.
|
|
110
110
|
|
|
@@ -188,7 +188,7 @@ const spinner = nc.cli.spinner(`Deploying to ${env}`).start();
|
|
|
188
188
|
spinner.succeed("Deployed");
|
|
189
189
|
```
|
|
190
190
|
|
|
191
|
-
That's a small part of it. The [guide](https://ix-xs.github.io/node-comfort/
|
|
191
|
+
That's a small part of it. The [guide](https://ix-xs.github.io/node-comfort/start/introduction/) walks through every namespace, and the [recipes](https://ix-xs.github.io/node-comfort/recipes/) show them working together: a small API server, a CLI, a scheduled job.
|
|
192
192
|
|
|
193
193
|
## Coming from 1.x
|
|
194
194
|
|
|
@@ -199,7 +199,9 @@ That's a small part of it. The [guide](https://ix-xs.github.io/node-comfort/guid
|
|
|
199
199
|
- `warn` and `error` write to stderr.
|
|
200
200
|
- Deep imports (`@ix-xs/node-comfort/src/...`) are replaced by official entry points (`@ix-xs/node-comfort/str`).
|
|
201
201
|
|
|
202
|
-
The [migration guide](https://ix-xs.github.io/node-comfort/
|
|
202
|
+
The [migration guide](https://ix-xs.github.io/node-comfort/start/migration/) lists every change with before and after examples.
|
|
203
|
+
|
|
204
|
+
Coming from 2.0, there is nothing to change: 2.1 adds functions, makes the existing ones faster and corrects edge cases. The [changelog](./CHANGELOG.md) has the details.
|
|
203
205
|
|
|
204
206
|
## Contributing
|
|
205
207
|
|
package/index.js
CHANGED
|
@@ -41,8 +41,8 @@ const modules = {
|
|
|
41
41
|
// Helpers that are also available at the top level (nc.info, nc.readJSON...).
|
|
42
42
|
const flat = {
|
|
43
43
|
logger: ["log", "trace", "debug", "info", "success", "warn", "error", "fatal", "group", "groupEnd", "timeStart", "timeEnd", "table", "box", "divider", "setLevel", "getLevel", "isLevelEnabled", "configure", "setTimestamp", "setDelimiter", "createLogger"],
|
|
44
|
-
fs: ["getEnv", "createPath", "getFolder", "getFile", "getFoldersIn", "getFilesIn", "glob", "find", "readFile", "readLines", "readJSON", "writeFile", "writeJSON", "appendFile", "createFile", "createFolder", "ensureFolder", "ensureFile", "touch", "deleteFolder", "deleteFile", "remove", "deleteFoldersIn", "deleteFilesIn", "emptyFolder", "copy", "move", "copyFoldersIn", "copyFolder", "copyFilesIn", "copyFile", "moveFoldersIn", "moveFolder", "moveFilesIn", "moveFile", "exists", "isFile", "isFolder", "stat", "fileSize", "folderSize", "hashFile", "tempFolder", "sanitizeFilename", "watch"],
|
|
45
|
-
checker: ["isArray", "isNumber", "isFinite", "isInteger", "isSafeInteger", "isFloat", "isPositive", "isNegative", "isBoolean", "isString", "isSymbol", "isBigInt", "isUndefined", "isNull", "isNil", "isDefined", "isPrimitive", "isFunction", "isAsyncFunction", "isGeneratorFunction", "isGenerator", "isClass", "isObject", "isPlainObject", "isPromise", "isRegExp", "isDate", "isValidDate", "isMap", "isSet", "isWeakMap", "isWeakSet", "isIterable", "isAsyncIterable", "isBuffer", "isTypedArray", "isError", "isEmpty", "isBlank", "isArrayOf", "isOneOf", "isEmail", "isURL", "isUUID", "isJSON", "isNumeric", "isIP", "isIPv4", "isIPv6", "isPort", "isHex", "isHexColor", "isBase64", "isSemver", "isISODate", "isSlug", "isAlpha", "isAlphanumeric", "isCreditCard", "isJWT", "assert", "assertType"],
|
|
44
|
+
fs: ["getEnv", "createPath", "getFolder", "getFile", "getFoldersIn", "getFilesIn", "glob", "find", "findUp", "readFile", "readLines", "readJSON", "writeFile", "writeJSON", "appendFile", "createFile", "createFolder", "ensureFolder", "ensureFile", "touch", "deleteFolder", "deleteFile", "remove", "deleteFoldersIn", "deleteFilesIn", "emptyFolder", "copy", "move", "copyFoldersIn", "copyFolder", "copyFilesIn", "copyFile", "moveFoldersIn", "moveFolder", "moveFilesIn", "moveFile", "exists", "isFile", "isFolder", "stat", "fileSize", "folderSize", "hashFile", "tempFolder", "sanitizeFilename", "watch"],
|
|
45
|
+
checker: ["isArray", "isNumber", "isFinite", "isInteger", "isSafeInteger", "isFloat", "isPositive", "isNegative", "isBoolean", "isString", "isSymbol", "isBigInt", "isUndefined", "isNull", "isNil", "isDefined", "isPrimitive", "isFunction", "isAsyncFunction", "isGeneratorFunction", "isGenerator", "isClass", "isObject", "isPlainObject", "isPromise", "isRegExp", "isDate", "isValidDate", "isMap", "isSet", "isWeakMap", "isWeakSet", "isIterable", "isAsyncIterable", "isBuffer", "isTypedArray", "isError", "isEmpty", "isBlank", "isArrayOf", "isOneOf", "isEmail", "isURL", "isUUID", "isJSON", "isNumeric", "isIP", "isIPv4", "isIPv6", "isPort", "isHex", "isHexColor", "isBase64", "isSemver", "isISODate", "isSlug", "isAlpha", "isAlphanumeric", "isCreditCard", "isJWT", "isHostname", "isMACAddress", "isIBAN", "isE164", "isObjectId", "isULID", "isDataURL", "isMimeType", "isTimeZone", "isLocale", "isCron", "isASCII", "assert", "assertType"],
|
|
46
46
|
utils: ["wait", "when", "dontCrash", "JSONString", "JSONParse"],
|
|
47
47
|
};
|
|
48
48
|
|
|
@@ -81,4 +81,4 @@ exports.nodeComfort = exports;
|
|
|
81
81
|
|
|
82
82
|
// Never runs. Node reads this line to know the named exports of the package
|
|
83
83
|
// when it is imported from an ES module.
|
|
84
|
-
0 && (module.exports = { log, trace, debug, info, success, warn, error, fatal, group, groupEnd, timeStart, timeEnd, table, box, divider, setLevel, getLevel, isLevelEnabled, configure, setTimestamp, setDelimiter, createLogger, getEnv, createPath, getFolder, getFile, getFoldersIn, getFilesIn, glob, find, readFile, readLines, readJSON, writeFile, writeJSON, appendFile, createFile, createFolder, ensureFolder, ensureFile, touch, deleteFolder, deleteFile, remove, deleteFoldersIn, deleteFilesIn, emptyFolder, copy, move, copyFoldersIn, copyFolder, copyFilesIn, copyFile, moveFoldersIn, moveFolder, moveFilesIn, moveFile, exists, isFile, isFolder, stat, fileSize, folderSize, hashFile, tempFolder, sanitizeFilename, watch, isArray, isNumber, isFinite, isInteger, isSafeInteger, isFloat, isPositive, isNegative, isBoolean, isString, isSymbol, isBigInt, isUndefined, isNull, isNil, isDefined, isPrimitive, isFunction, isAsyncFunction, isGeneratorFunction, isGenerator, isClass, isObject, isPlainObject, isPromise, isRegExp, isDate, isValidDate, isMap, isSet, isWeakMap, isWeakSet, isIterable, isAsyncIterable, isBuffer, isTypedArray, isError, isEmpty, isBlank, isArrayOf, isOneOf, isEmail, isURL, isUUID, isJSON, isNumeric, isIP, isIPv4, isIPv6, isPort, isHex, isHexColor, isBase64, isSemver, isISODate, isSlug, isAlpha, isAlphanumeric, isCreditCard, isJWT, assert, assertType, wait, when, dontCrash, JSONString, JSONParse, logger, fs, checker, utils, str, num, arr, obj, func, time, id, crypto, color, cli, sys, async, schema, http, env, errors, SQLite, Cache, Emitter, nc, nodeComfort });
|
|
84
|
+
0 && (module.exports = { log, trace, debug, info, success, warn, error, fatal, group, groupEnd, timeStart, timeEnd, table, box, divider, setLevel, getLevel, isLevelEnabled, configure, setTimestamp, setDelimiter, createLogger, getEnv, createPath, getFolder, getFile, getFoldersIn, getFilesIn, glob, find, findUp, readFile, readLines, readJSON, writeFile, writeJSON, appendFile, createFile, createFolder, ensureFolder, ensureFile, touch, deleteFolder, deleteFile, remove, deleteFoldersIn, deleteFilesIn, emptyFolder, copy, move, copyFoldersIn, copyFolder, copyFilesIn, copyFile, moveFoldersIn, moveFolder, moveFilesIn, moveFile, exists, isFile, isFolder, stat, fileSize, folderSize, hashFile, tempFolder, sanitizeFilename, watch, isArray, isNumber, isFinite, isInteger, isSafeInteger, isFloat, isPositive, isNegative, isBoolean, isString, isSymbol, isBigInt, isUndefined, isNull, isNil, isDefined, isPrimitive, isFunction, isAsyncFunction, isGeneratorFunction, isGenerator, isClass, isObject, isPlainObject, isPromise, isRegExp, isDate, isValidDate, isMap, isSet, isWeakMap, isWeakSet, isIterable, isAsyncIterable, isBuffer, isTypedArray, isError, isEmpty, isBlank, isArrayOf, isOneOf, isEmail, isURL, isUUID, isJSON, isNumeric, isIP, isIPv4, isIPv6, isPort, isHex, isHexColor, isBase64, isSemver, isISODate, isSlug, isAlpha, isAlphanumeric, isCreditCard, isJWT, isHostname, isMACAddress, isIBAN, isE164, isObjectId, isULID, isDataURL, isMimeType, isTimeZone, isLocale, isCron, isASCII, assert, assertType, wait, when, dontCrash, JSONString, JSONParse, logger, fs, checker, utils, str, num, arr, obj, func, time, id, crypto, color, cli, sys, async, schema, http, env, errors, SQLite, Cache, Emitter, nc, nodeComfort });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ix-xs/node-comfort",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "The zero-dependency standard library for Node.js: logger, filesystem, SQLite, schema validation, HTTP client, CLI toolkit, cache, env, async pools, colors, events, i18n dates, ids, crypto and hundreds of fully typed helpers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"utils",
|
|
@@ -184,14 +184,15 @@
|
|
|
184
184
|
"access": "public"
|
|
185
185
|
},
|
|
186
186
|
"scripts": {
|
|
187
|
-
"build": "node scripts/build-types.js && node scripts/build-
|
|
187
|
+
"build": "node scripts/build-types.js && node scripts/build-reference.js",
|
|
188
188
|
"build:types": "node scripts/build-types.js",
|
|
189
|
-
"build:
|
|
190
|
-
"
|
|
191
|
-
"site:serve": "node scripts/serve-site.js",
|
|
192
|
-
"test": "node --test \"test/**/*.test.js\"",
|
|
189
|
+
"build:reference": "node scripts/build-reference.js",
|
|
190
|
+
"test": "node --test --test-reporter=spec --test-timeout=120000 \"test/**/*.test.js\"",
|
|
193
191
|
"test:types": "node scripts/check-types.js",
|
|
194
|
-
"
|
|
192
|
+
"docs:install": "npm ci --prefix docs",
|
|
193
|
+
"docs:dev": "npm run dev --prefix docs",
|
|
194
|
+
"docs:build": "npm run build --prefix docs && npm run check-links --prefix docs && npm run check-translation --prefix docs",
|
|
195
|
+
"check": "npm run build && npm test && npm run test:types",
|
|
195
196
|
"prepublishOnly": "npm run check"
|
|
196
197
|
},
|
|
197
198
|
"devDependencies": {
|