@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,293 +1,744 @@
1
1
  /**
2
- * Capitalizes the first character of a string and lowercases the rest.
2
+ * Options for `slugify()`.
3
+ */
4
+ export type SlugifyOptions = {
5
+ /**
6
+ * Placed between words. Defaults to `"-"`.
7
+ */
8
+ separator?: string | undefined;
9
+ /**
10
+ * Lowercase the result. Defaults to `true`.
11
+ */
12
+ lower?: boolean | undefined;
13
+ /**
14
+ * Maximum length, cut on a word boundary when possible.
15
+ */
16
+ maxLength?: number | undefined;
17
+ };
18
+ /**
19
+ * Options for `truncate()`.
20
+ */
21
+ export type TruncateOptions = {
22
+ /**
23
+ * Added where the text is cut, and counted in the length. Defaults to `"…"`.
24
+ */
25
+ omission?: string | undefined;
26
+ /**
27
+ * Cut at the previous space rather than inside a word, when the end is what gets cut.
28
+ */
29
+ words?: boolean | undefined;
30
+ /**
31
+ * Where the text is cut. `"middle"` keeps both ends, which suits paths and ids. Defaults to `"end"`.
32
+ */
33
+ position?: "end" | "middle" | "start" | undefined;
34
+ };
35
+ /**
36
+ * Options for `template()`.
37
+ */
38
+ export type TemplateOptions = {
39
+ /**
40
+ * Opening delimiter. Defaults to `"{"`.
41
+ */
42
+ open?: string | undefined;
43
+ /**
44
+ * Closing delimiter. Defaults to `"}"`.
45
+ */
46
+ close?: string | undefined;
47
+ /**
48
+ * Used for missing values. Without it, their placeholders stay as they are.
49
+ */
50
+ fallback?: string | undefined;
51
+ };
52
+ /**
53
+ * Options for `wrap()`.
54
+ */
55
+ export type WrapOptions = {
56
+ /**
57
+ * Maximum visible characters per line. Defaults to `80`.
58
+ */
59
+ width?: number | undefined;
60
+ /**
61
+ * Added at the start of every line.
62
+ */
63
+ indent?: string | undefined;
64
+ /**
65
+ * Break words longer than `width` instead of letting them overflow.
66
+ */
67
+ cut?: boolean | undefined;
68
+ /**
69
+ * Line separator. Defaults to `"\n"`.
70
+ */
71
+ newline?: string | undefined;
72
+ };
73
+ /**
74
+ * Options for `mask()`.
75
+ */
76
+ export type MaskOptions = {
77
+ /**
78
+ * Characters left visible at the start. Defaults to `0`.
79
+ */
80
+ start?: number | undefined;
81
+ /**
82
+ * Characters left visible at the end. Defaults to `4`.
83
+ */
84
+ end?: number | undefined;
85
+ /**
86
+ * Mask character. Defaults to `"*"`.
87
+ */
88
+ char?: string | undefined;
89
+ /**
90
+ * Leave spaces and dashes visible, nice for card numbers.
91
+ */
92
+ keepSpaces?: boolean | undefined;
93
+ };
94
+ /**
95
+ * The word forms for `plural()`. Only `other` is required; add the others
96
+ * when your language needs them.
97
+ */
98
+ export type PluralForms = {
99
+ /**
100
+ * The general plural, like `"files"`.
101
+ */
102
+ other: string;
103
+ /**
104
+ * Used for `0` in any language, like `"no files"`.
105
+ */
106
+ zero?: string | undefined;
107
+ /**
108
+ * The singular, like `"file"`. French also uses it for 0.
109
+ */
110
+ one?: string | undefined;
111
+ /**
112
+ * Dual form (Arabic, Hebrew, Slovenian...).
113
+ */
114
+ two?: string | undefined;
115
+ /**
116
+ * "Few" form (Polish, Czech, Russian...).
117
+ */
118
+ few?: string | undefined;
119
+ /**
120
+ * "Many" form (Polish, Russian, Arabic...).
121
+ */
122
+ many?: string | undefined;
123
+ };
124
+ /**
125
+ * Options for `plural()`.
126
+ */
127
+ export type PluralOptions = {
128
+ /**
129
+ * Language whose plural rules apply. Defaults to `"en"`.
130
+ */
131
+ locale?: string | undefined;
132
+ /**
133
+ * Put the formatted count before the word. Defaults to `true`.
134
+ */
135
+ includeCount?: boolean | undefined;
136
+ /**
137
+ * Use ordinal rules (1st, 2nd, 3rd).
138
+ */
139
+ ordinal?: boolean | undefined;
140
+ };
141
+ /**
142
+ * Options for `compare()`.
143
+ */
144
+ export type CompareOptions = {
145
+ /**
146
+ * Language used for alphabetical order. Defaults to the system's.
147
+ */
148
+ locale?: string | undefined;
149
+ /**
150
+ * Sort numbers naturally, `"file2"` before `"file10"`. Defaults to `true`.
151
+ */
152
+ numeric?: boolean | undefined;
153
+ /**
154
+ * Which differences count. `"base"` ignores accents and case. Defaults to `"variant"`.
155
+ */
156
+ sensitivity?: "base" | "accent" | "case" | "variant" | undefined;
157
+ };
158
+ /**
159
+ * Options for `closest()`.
160
+ */
161
+ export type ClosestOptions = {
162
+ /**
163
+ * Minimum similarity (0 to 1) to accept a match. Defaults to `0.4`.
164
+ */
165
+ threshold?: number | undefined;
166
+ /**
167
+ * Take case into account.
168
+ */
169
+ caseSensitive?: boolean | undefined;
170
+ };
171
+ /**
172
+ * Options for `random()`.
173
+ */
174
+ export type RandomStringOptions = {
175
+ /**
176
+ * Characters to pick from. Defaults to letters and digits.
177
+ */
178
+ charset?: string | undefined;
179
+ };
180
+ /**
181
+ * Uppercases the first character and lowercases the rest.
182
+ *
183
+ * @example
184
+ * str.capitalize("hELLO wORLD"); // "Hello world"
185
+ *
186
+ * @param {unknown} input
187
+ * @returns {string}
188
+ */
189
+ export function capitalize(input: unknown): string;
190
+ /**
191
+ * Uppercases the first character and leaves the rest alone.
192
+ *
193
+ * @example
194
+ * str.upperFirst("userName"); // "UserName"
195
+ *
196
+ * @param {unknown} input
197
+ * @returns {string}
198
+ */
199
+ export function upperFirst(input: unknown): string;
200
+ /**
201
+ * Lowercases the first character and leaves the rest alone.
202
+ *
203
+ * @example
204
+ * str.lowerFirst("UserName"); // "userName"
205
+ *
206
+ * @param {unknown} input
207
+ * @returns {string}
208
+ */
209
+ export function lowerFirst(input: unknown): string;
210
+ /**
211
+ * Turns an identifier into a label people can read. Acronyms stay as they are.
212
+ *
213
+ * @example
214
+ * str.humanize("user_first_name"); // "User first name"
215
+ * str.humanize("createdAt"); // "Created at"
216
+ * str.humanize("userID"); // "User ID"
217
+ *
218
+ * @param {unknown} input
219
+ * @returns {string}
220
+ */
221
+ export function humanize(input: unknown): string;
222
+ /**
223
+ * Uppercases the first letter of each word and leaves the rest alone.
224
+ *
225
+ * @example
226
+ * str.titleCase("the quick brown fox"); // "The Quick Brown Fox"
227
+ * str.titleCase("élodie o'neil"); // "Élodie O'neil"
228
+ *
229
+ * @param {unknown} input
230
+ * @returns {string}
231
+ */
232
+ export function titleCase(input: unknown): string;
233
+ /**
234
+ * Lowercases everything, then capitalizes the start of each sentence.
235
+ *
236
+ * @example
237
+ * str.sentenceCase("hELLO WORLD. how ARE you?"); // "Hello world. How are you?"
238
+ *
239
+ * @param {unknown} input
240
+ * @returns {string}
241
+ */
242
+ export function sentenceCase(input: unknown): string;
243
+ /**
244
+ * Converts to `camelCase`.
245
+ *
246
+ * @example
247
+ * str.camelCase("user_first-name"); // "userFirstName"
248
+ * str.camelCase("XMLHttpRequest"); // "xmlHttpRequest"
249
+ *
250
+ * @param {unknown} input
251
+ * @returns {string}
252
+ */
253
+ export function camelCase(input: unknown): string;
254
+ /**
255
+ * Converts to `PascalCase`.
256
+ *
257
+ * @example
258
+ * str.pascalCase("hello world"); // "HelloWorld"
259
+ *
260
+ * @param {unknown} input
261
+ * @returns {string}
262
+ */
263
+ export function pascalCase(input: unknown): string;
264
+ /**
265
+ * Converts to `snake_case`.
266
+ *
267
+ * @example
268
+ * str.snakeCase("helloWorld"); // "hello_world"
269
+ *
270
+ * @param {unknown} input
271
+ * @returns {string}
272
+ */
273
+ export function snakeCase(input: unknown): string;
274
+ /**
275
+ * Converts to `kebab-case`.
3
276
  *
4
277
  * @example
5
- * nodeComfort.str.capitalize("hELLO"); // "Hello"
278
+ * str.kebabCase("helloWorld"); // "hello-world"
6
279
  *
7
- * @param {string} str - Input string.
8
- * @returns {string} The capitalized string.
280
+ * @param {unknown} input
281
+ * @returns {string}
9
282
  */
10
- export function capitalize(str: string): string;
283
+ export function kebabCase(input: unknown): string;
11
284
  /**
12
- * Uppercases the first character of each word (Title Case), leaving the rest untouched.
285
+ * Converts to `CONSTANT_CASE`.
13
286
  *
14
287
  * @example
15
- * nodeComfort.str.titleCase("the quick brown fox"); // "The Quick Brown Fox"
288
+ * str.constantCase("helloWorld"); // "HELLO_WORLD"
16
289
  *
17
- * @param {string} str - Input string.
18
- * @returns {string} The title-cased string.
290
+ * @param {unknown} input
291
+ * @returns {string}
19
292
  */
20
- export function titleCase(str: string): string;
293
+ export function constantCase(input: unknown): string;
21
294
  /**
22
- * Converts a string to `camelCase`.
295
+ * Converts to `dot.case`.
23
296
  *
24
297
  * @example
25
- * nodeComfort.str.camelCase("hello world"); // "helloWorld"
26
- * nodeComfort.str.camelCase("foo-bar_baz"); // "fooBarBaz"
298
+ * str.dotCase("userFirstName"); // "user.first.name"
27
299
  *
28
- * @param {string} str - Input string.
29
- * @returns {string} The camelCased string.
300
+ * @param {unknown} input
301
+ * @returns {string}
30
302
  */
31
- export function camelCase(str: string): string;
303
+ export function dotCase(input: unknown): string;
32
304
  /**
33
- * Converts a string to `PascalCase`.
305
+ * Splits text into words. Understands camelCase, snake_case, kebab-case,
306
+ * dots, spaces and punctuation.
34
307
  *
35
308
  * @example
36
- * nodeComfort.str.pascalCase("hello world"); // "HelloWorld"
309
+ * str.words("helloWorld-foo_bar"); // ["hello", "World", "foo", "bar"]
37
310
  *
38
- * @param {string} str - Input string.
39
- * @returns {string} The PascalCased string.
311
+ * @param {unknown} input
312
+ * @returns {string[]}
40
313
  */
41
- export function pascalCase(str: string): string;
314
+ export function words(input: unknown): string[];
42
315
  /**
43
- * Converts a string to `snake_case`.
316
+ * Removes accents (`é` becomes `e`) and spells out special Latin letters
317
+ * (`ß` becomes `ss`, `æ` becomes `ae`).
44
318
  *
45
319
  * @example
46
- * nodeComfort.str.snakeCase("helloWorld"); // "hello_world"
320
+ * str.deburr("Crème brûlée"); // "Creme brulee"
321
+ * str.deburr("Straße"); // "Strasse"
47
322
  *
48
- * @param {string} str - Input string.
49
- * @returns {string} The snake_cased string.
323
+ * @param {unknown} input
324
+ * @returns {string}
50
325
  */
51
- export function snakeCase(str: string): string;
326
+ export function deburr(input: unknown): string;
52
327
  /**
53
- * Converts a string to `kebab-case`.
328
+ * Turns text into a URL slug: no accents, lowercase, words joined by dashes.
54
329
  *
55
330
  * @example
56
- * nodeComfort.str.kebabCase("helloWorld"); // "hello-world"
331
+ * str.slugify("Héllo, World!"); // "hello-world"
332
+ * str.slugify("Crème Brûlée", { separator: "_" }); // "creme_brulee"
333
+ * str.slugify("A very long title", { maxLength: 8 }); // "a-very"
57
334
  *
58
- * @param {string} str - Input string.
59
- * @returns {string} The kebab-cased string.
335
+ * @param {unknown} input
336
+ * @param {SlugifyOptions} [options]
337
+ * @returns {string} The slug, possibly empty.
60
338
  */
61
- export function kebabCase(str: string): string;
339
+ export function slugify(input: unknown, options?: SlugifyOptions): string;
62
340
  /**
63
- * Converts a string to `CONSTANT_CASE`.
341
+ * Collapses runs of whitespace into single spaces and trims the ends.
64
342
  *
65
343
  * @example
66
- * nodeComfort.str.constantCase("helloWorld"); // "HELLO_WORLD"
344
+ * str.squish(" hello \n\t world "); // "hello world"
67
345
  *
68
- * @param {string} str - Input string.
69
- * @returns {string} The CONSTANT_CASED string.
346
+ * @param {unknown} input
347
+ * @returns {string}
70
348
  */
71
- export function constantCase(str: string): string;
349
+ export function squish(input: unknown): string;
72
350
  /**
73
- * Converts a string into a URL-friendly slug.
351
+ * Removes HTML tags and keeps the text. This is not a sanitizer: to show
352
+ * untrusted text in HTML, use `escapeHTML()`.
74
353
  *
75
- * Accents/diacritics are stripped, non-alphanumeric runs become the separator.
354
+ * @example
355
+ * str.stripTags("<p>Hello <b>world</b></p>"); // "Hello world"
356
+ *
357
+ * @param {unknown} input
358
+ * @returns {string}
359
+ */
360
+ export function stripTags(input: unknown): string;
361
+ /**
362
+ * Escapes `& < > " '` so the text is safe inside HTML content and attributes.
76
363
  *
77
364
  * @example
78
- * nodeComfort.str.slugify("Héllo, World!"); // "hello-world"
79
- * nodeComfort.str.slugify("A B C", { separator: "_" }); // "a_b_c"
365
+ * str.escapeHTML('<a href="x">Tom & Jerry</a>');
366
+ * // "&lt;a href=&quot;x&quot;&gt;Tom &amp; Jerry&lt;/a&gt;"
80
367
  *
81
- * @param {string} str - Input string.
82
- * @param {{ separator?: string, lower?: boolean }} [options] - Slug options.
83
- * @returns {string} The slug.
368
+ * @param {unknown} input
369
+ * @returns {string}
84
370
  */
85
- export function slugify(str: string, options?: {
86
- separator?: string;
87
- lower?: boolean;
88
- }): string;
371
+ export function escapeHTML(input: unknown): string;
89
372
  /**
90
- * Truncates a string to a maximum length, appending an ellipsis if cut.
373
+ * Decodes HTML entities: named ones like `&amp;` and `&nbsp;`, and numeric
374
+ * ones like `&#233;`.
91
375
  *
92
376
  * @example
93
- * nodeComfort.str.truncate("Hello world", 8); // "Hello…"
94
- * nodeComfort.str.truncate("Hello world", 8, { omission: "..." }); // "Hello..."
377
+ * str.unescapeHTML("Tom &amp; Jerry &#x1F600;"); // "Tom & Jerry 😀"
95
378
  *
96
- * @param {string} str - Input string.
97
- * @param {number} length - Maximum length of the result (including the omission).
98
- * @param {{ omission?: string, words?: boolean }} [options] - Truncation options.
99
- * @returns {string} The truncated string.
379
+ * @param {unknown} input
380
+ * @returns {string}
100
381
  */
101
- export function truncate(str: string, length: number, options?: {
102
- omission?: string;
103
- words?: boolean;
104
- }): string;
382
+ export function unescapeHTML(input: unknown): string;
105
383
  /**
106
- * Pads a string on the left (start) to a target length.
384
+ * Escapes regex special characters so the text matches literally.
107
385
  *
108
- * @param {string} str - Input string.
109
- * @param {number} length - Target total length.
110
- * @param {string} [char=" "] - Padding character(s).
111
- * @returns {string} The padded string.
386
+ * @example
387
+ * new RegExp(str.escapeRegExp("1+1=2?")).test("1+1=2?"); // true
388
+ *
389
+ * @param {unknown} input
390
+ * @returns {string}
112
391
  */
113
- export function padStart(str: string, length: number, char?: string): string;
392
+ export function escapeRegExp(input: unknown): string;
114
393
  /**
115
- * Pads a string on the right (end) to a target length.
394
+ * Counts visible characters. Unlike `.length`, an emoji or an accented
395
+ * letter counts as one.
396
+ *
397
+ * @example
398
+ * "👨‍👩‍👧".length; // 8
399
+ * str.length("👨‍👩‍👧"); // 1
116
400
  *
117
- * @param {string} str - Input string.
118
- * @param {number} length - Target total length.
119
- * @param {string} [char=" "] - Padding character(s).
120
- * @returns {string} The padded string.
401
+ * @param {unknown} input
402
+ * @returns {number}
121
403
  */
122
- export function padEnd(str: string, length: number, char?: string): string;
404
+ export function length(input: unknown): number;
123
405
  /**
124
- * Centers a string within a target length by padding both sides.
406
+ * Size of the text in bytes once encoded, UTF-8 by default. Useful when a
407
+ * limit is in bytes, like a database column or an HTTP header.
125
408
  *
126
409
  * @example
127
- * nodeComfort.str.center("hi", 6); // " hi "
128
- * nodeComfort.str.center("hi", 6, "*"); // "**hi**"
410
+ * str.byteLength("é"); // 2
411
+ * str.byteLength("😀"); // 4
129
412
  *
130
- * @param {string} str - Input string.
131
- * @param {number} length - Target total length.
132
- * @param {string} [char=" "] - Padding character.
133
- * @returns {string} The centered string.
413
+ * @param {unknown} input
414
+ * @param {BufferEncoding} [encoding="utf8"]
415
+ * @returns {number}
134
416
  */
135
- export function center(str: string, length: number, char?: string): string;
417
+ export function byteLength(input: unknown, encoding?: BufferEncoding): number;
136
418
  /**
137
- * Reverses a string (Unicode code-point aware, so emojis stay intact).
419
+ * Counts how many times `search` appears, without overlaps.
138
420
  *
139
421
  * @example
140
- * nodeComfort.str.reverse("abc"); // "cba"
422
+ * str.count("banana", "a"); // 3
423
+ * str.count("aaaa", "aa"); // 2
141
424
  *
142
- * @param {string} str - Input string.
143
- * @returns {string} The reversed string.
425
+ * @param {unknown} input
426
+ * @param {string} search An empty string gives `0`.
427
+ * @returns {number}
144
428
  */
145
- export function reverse(str: string): string;
429
+ export function count(input: unknown, search: string): number;
146
430
  /**
147
- * Collapses all runs of whitespace into single spaces and trims the ends.
431
+ * Shortens text to `length` visible characters, ending with `…` when cut.
148
432
  *
149
433
  * @example
150
- * nodeComfort.str.squish(" hello world \n"); // "hello world"
434
+ * str.truncate("Hello world", 8); // "Hello w…"
435
+ * str.truncate("Hello world", 8, { omission: "..." }); // "Hello..."
436
+ * str.truncate("Hello big world", 12, { words: true }); // "Hello big…"
437
+ *
438
+ * @param {unknown} input
439
+ * @param {number} length Maximum length, omission included.
440
+ * @param {TruncateOptions} [options]
441
+ * @returns {string}
442
+ */
443
+ export function truncate(input: unknown, length: number, options?: TruncateOptions): string;
444
+ /**
445
+ * Splits text into pieces of `size` visible characters. The last one can be
446
+ * shorter.
447
+ *
448
+ * @example
449
+ * str.chunk("4242424242424242", 4).join(" "); // "4242 4242 4242 4242"
151
450
  *
152
- * @param {string} str - Input string.
153
- * @returns {string} The normalized string.
451
+ * @param {unknown} input
452
+ * @param {number} size
453
+ * @returns {string[]}
154
454
  */
155
- export function squish(str: string): string;
455
+ export function chunk(input: unknown, size: number): string[];
156
456
  /**
157
- * Removes all HTML tags from a string.
457
+ * Returns the text between `start` and the next `end`, or `undefined` if a
458
+ * marker is missing.
158
459
  *
159
460
  * @example
160
- * nodeComfort.str.stripTags("<b>Hi</b> there"); // "Hi there"
461
+ * str.between("Hello [world]!", "[", "]"); // "world"
161
462
  *
162
- * @param {string} str - Input string.
163
- * @returns {string} The string with tags removed.
463
+ * @param {unknown} input
464
+ * @param {string} start
465
+ * @param {string} end
466
+ * @returns {string | undefined}
164
467
  */
165
- export function stripTags(str: string): string;
468
+ export function between(input: unknown, start: string, end: string): string | undefined;
166
469
  /**
167
- * Escapes HTML-sensitive characters (`& < > " '`).
470
+ * Splits at the first occurrence of `separator` only.
168
471
  *
169
472
  * @example
170
- * nodeComfort.str.escapeHTML('<a href="x">'); // "&lt;a href=&quot;x&quot;&gt;"
473
+ * str.splitOnce("key=value=more", "="); // ["key", "value=more"]
474
+ * str.splitOnce("novalue", "="); // ["novalue", undefined]
171
475
  *
172
- * @param {string} str - Input string.
173
- * @returns {string} The escaped string.
476
+ * @param {unknown} input
477
+ * @param {string} separator
478
+ * @returns {[string, string | undefined]}
174
479
  */
175
- export function escapeHTML(str: string): string;
480
+ export function splitOnce(input: unknown, separator: string): [string, string | undefined];
176
481
  /**
177
- * Reverses {@link escapeHTML}: turns HTML entities back into characters.
482
+ * Splits text into lines, whatever the line endings.
483
+ *
484
+ * @example
485
+ * str.lines("a\r\nb\nc"); // ["a", "b", "c"]
178
486
  *
179
- * @param {string} str - Input string.
180
- * @returns {string} The unescaped string.
487
+ * @param {unknown} input
488
+ * @returns {string[]}
181
489
  */
182
- export function unescapeHTML(str: string): string;
490
+ export function lines(input: unknown): string[];
183
491
  /**
184
- * Escapes a string for safe use inside a `RegExp`.
492
+ * Pads the start until the text is `length` characters long.
185
493
  *
186
494
  * @example
187
- * new RegExp(nodeComfort.str.escapeRegExp("a.b")); // matches literal "a.b"
495
+ * str.padStart("7", 3, "0"); // "007"
188
496
  *
189
- * @param {string} str - Input string.
190
- * @returns {string} The escaped string.
497
+ * @param {unknown} input
498
+ * @param {number} length
499
+ * @param {string} [char=" "]
500
+ * @returns {string}
191
501
  */
192
- export function escapeRegExp(str: string): string;
502
+ export function padStart(input: unknown, length: number, char?: string): string;
193
503
  /**
194
- * Counts the number of non-overlapping occurrences of a substring.
504
+ * Pads the end until the text is `length` characters long.
195
505
  *
196
506
  * @example
197
- * nodeComfort.str.count("banana", "a"); // 3
507
+ * str.padEnd("ab", 5, "."); // "ab..."
198
508
  *
199
- * @param {string} str - Input string.
200
- * @param {string} sub - Substring to count.
201
- * @returns {number} Number of occurrences.
509
+ * @param {unknown} input
510
+ * @param {number} length
511
+ * @param {string} [char=" "]
512
+ * @returns {string}
202
513
  */
203
- export function count(str: string, sub: string): number;
514
+ export function padEnd(input: unknown, length: number, char?: string): string;
204
515
  /**
205
- * Ensures a string starts with a given prefix (adds it only if missing).
516
+ * Centers text within `length` characters. An odd leftover goes to the right.
206
517
  *
207
518
  * @example
208
- * nodeComfort.str.ensurePrefix("example.com", "https://"); // "https://example.com"
519
+ * str.center("hi", 7, "*"); // "**hi***"
209
520
  *
210
- * @param {string} str - Input string.
211
- * @param {string} prefix - Prefix to ensure.
212
- * @returns {string} The string with the prefix guaranteed.
521
+ * @param {unknown} input
522
+ * @param {number} length
523
+ * @param {string} [char=" "]
524
+ * @returns {string}
213
525
  */
214
- export function ensurePrefix(str: string, prefix: string): string;
526
+ export function center(input: unknown, length: number, char?: string): string;
215
527
  /**
216
- * Ensures a string ends with a given suffix (adds it only if missing).
528
+ * Indents every non-empty line.
217
529
  *
218
530
  * @example
219
- * nodeComfort.str.ensureSuffix("path", "/"); // "path/"
531
+ * str.indent("a\nb", 2); // " a\n b"
532
+ * str.indent("a\nb", "> "); // "> a\n> b"
220
533
  *
221
- * @param {string} str - Input string.
222
- * @param {string} suffix - Suffix to ensure.
223
- * @returns {string} The string with the suffix guaranteed.
534
+ * @param {unknown} input
535
+ * @param {number | string} [prefix=2] A number of spaces, or the prefix itself.
536
+ * @returns {string}
224
537
  */
225
- export function ensureSuffix(str: string, suffix: string): string;
538
+ export function indent(input: unknown, prefix?: number | string): string;
226
539
  /**
227
- * Removes a prefix from a string if present.
540
+ * Removes the indentation shared by all lines, and blank first and last
541
+ * lines. Works as a template tag, so multi-line strings can follow your
542
+ * code's indentation.
228
543
  *
229
- * @param {string} str - Input string.
230
- * @param {string} prefix - Prefix to remove.
231
- * @returns {string} The string without the prefix.
544
+ * @example
545
+ * const sql = str.dedent`
546
+ * SELECT *
547
+ * FROM users
548
+ * WHERE id = ${id}
549
+ * `;
550
+ * // "SELECT *\n FROM users\n WHERE id = 42"
551
+ *
552
+ * @param {unknown} input
553
+ * @param {...unknown} values
554
+ * @returns {string}
232
555
  */
233
- export function removePrefix(str: string, prefix: string): string;
556
+ export function dedent(input: unknown, ...values: unknown[]): string;
234
557
  /**
235
- * Removes a suffix from a string if present.
558
+ * Wraps text so no line is longer than `width` visible characters. Existing
559
+ * line breaks are kept.
560
+ *
561
+ * @example
562
+ * str.wrap("The quick brown fox jumps over the lazy dog", 16);
563
+ * // "The quick brown\nfox jumps over\nthe lazy dog"
236
564
  *
237
- * @param {string} str - Input string.
238
- * @param {string} suffix - Suffix to remove.
239
- * @returns {string} The string without the suffix.
565
+ * @param {unknown} input
566
+ * @param {WrapOptions | number} [options] Options, or just the width.
567
+ * @returns {string}
240
568
  */
241
- export function removeSuffix(str: string, suffix: string): string;
569
+ export function wrap(input: unknown, options?: WrapOptions | number): string;
242
570
  /**
243
- * Renders a template, replacing `{key}` placeholders with values from `data`.
571
+ * Reverses text without breaking emoji or accents.
244
572
  *
245
- * Missing keys are left as-is by default. Nested paths (`{user.name}`) are supported.
573
+ * @example
574
+ * str.reverse("añ👍🏽"); // "👍🏽ña"
575
+ *
576
+ * @param {unknown} input
577
+ * @returns {string}
578
+ */
579
+ export function reverse(input: unknown): string;
580
+ /**
581
+ * Hides part of a string, like a card number or a token.
582
+ *
583
+ * @example
584
+ * str.mask("4242424242424242"); // "************4242"
585
+ * str.mask("4242 4242 4242 4242", { keepSpaces: true }); // "**** **** **** 4242"
586
+ * str.mask("secret-token", { start: 2, end: 2, char: "•" }); // "se••••••••en"
587
+ *
588
+ * @param {unknown} input
589
+ * @param {MaskOptions} [options]
590
+ * @returns {string}
591
+ */
592
+ export function mask(input: unknown, options?: MaskOptions): string;
593
+ /**
594
+ * The initials of a name, in uppercase.
246
595
  *
247
596
  * @example
248
- * nodeComfort.str.template("Hi {name}, you have {count} msgs", { name: "Jo", count: 3 });
249
- * // "Hi Jo, you have 3 msgs"
597
+ * str.initials("Ada Lovelace"); // "AL"
598
+ * str.initials("jean-luc picard", 3); // "JLP"
250
599
  *
251
- * @param {string} str - Template string.
252
- * @param {Record<string, any>} data - Replacement values.
253
- * @param {{ open?: string, close?: string, fallback?: string }} [options] - Delimiters / fallback.
254
- * @returns {string} The rendered string.
600
+ * @param {unknown} input
601
+ * @param {number} [max=2] Maximum number of letters.
602
+ * @returns {string}
255
603
  */
256
- export function template(str: string, data: Record<string, any>, options?: {
257
- open?: string;
258
- close?: string;
259
- fallback?: string;
260
- }): string;
604
+ export function initials(input: unknown, max?: number): string;
261
605
  /**
262
- * Splits a string into an array of "words" (camelCase / snake / kebab aware).
606
+ * Picks the right plural for a count, following the rules of the language,
607
+ * and puts the formatted count in front.
263
608
  *
264
609
  * @example
265
- * nodeComfort.str.words("helloWorld-foo_bar"); // ["hello", "World", "foo", "bar"]
610
+ * str.plural(1, { one: "file", other: "files" }); // "1 file"
611
+ * str.plural(1234, { one: "item", other: "items" }); // "1,234 items"
612
+ * str.plural(0, { zero: "no files", one: "file", other: "files" }); // "no files"
613
+ * str.plural(0, { one: "fichier", other: "fichiers" }, { locale: "fr" }); // "0 fichier"
614
+ *
615
+ * @param {number} value
616
+ * @param {PluralForms} forms
617
+ * @param {PluralOptions} [options]
618
+ * @returns {string}
619
+ */
620
+ export function plural(value: number, forms: PluralForms, options?: PluralOptions): string;
621
+ /**
622
+ * Fills `{placeholders}` with values. Dotted paths like `{user.name}` work,
623
+ * and missing values are left alone unless you give a `fallback`.
266
624
  *
267
- * @param {string} str - Input string.
268
- * @returns {string[]} The words.
625
+ * @example
626
+ * str.template("Hi {name}, you have {count} messages", { name: "Jo", count: 3 });
627
+ * // "Hi Jo, you have 3 messages"
628
+ * str.template("Hello {{ user.name }}", { user: { name: "Ada" } }, { open: "{{", close: "}}" });
629
+ * // "Hello Ada"
630
+ *
631
+ * @param {unknown} input
632
+ * @param {Record<string, any>} data
633
+ * @param {TemplateOptions} [options]
634
+ * @returns {string}
269
635
  */
270
- export function words(str: string): string[];
636
+ export function template(input: unknown, data: Record<string, any>, options?: TemplateOptions): string;
271
637
  /**
272
- * Returns the visible length of a string in code points (emoji-safe).
638
+ * Adds `prefix` unless the text already starts with it.
273
639
  *
274
640
  * @example
275
- * "😀".length; // 2
276
- * nodeComfort.str.length("😀"); // 1
641
+ * str.ensurePrefix("example.com", "https://"); // "https://example.com"
277
642
  *
278
- * @param {string} str - Input string.
279
- * @returns {number} The number of code points.
643
+ * @param {unknown} input
644
+ * @param {string} prefix
645
+ * @returns {string}
280
646
  */
281
- export function length(str: string): number;
647
+ export function ensurePrefix(input: unknown, prefix: string): string;
282
648
  /**
283
- * Generates a random alphanumeric string of a given length.
649
+ * Adds `suffix` unless the text already ends with it.
284
650
  *
285
- * Note: uses `Math.random` and is **not** cryptographically secure.
286
- * For tokens/IDs use `nodeComfort.id.token()` instead.
651
+ * @example
652
+ * str.ensureSuffix("path/to", "/"); // "path/to/"
653
+ *
654
+ * @param {unknown} input
655
+ * @param {string} suffix
656
+ * @returns {string}
657
+ */
658
+ export function ensureSuffix(input: unknown, suffix: string): string;
659
+ /**
660
+ * Removes `prefix` if the text starts with it.
661
+ *
662
+ * @example
663
+ * str.removePrefix("https://example.com", "https://"); // "example.com"
664
+ *
665
+ * @param {unknown} input
666
+ * @param {string} prefix
667
+ * @returns {string}
668
+ */
669
+ export function removePrefix(input: unknown, prefix: string): string;
670
+ /**
671
+ * Removes `suffix` if the text ends with it.
672
+ *
673
+ * @example
674
+ * str.removeSuffix("report.pdf", ".pdf"); // "report"
675
+ *
676
+ * @param {unknown} input
677
+ * @param {string} suffix
678
+ * @returns {string}
679
+ */
680
+ export function removeSuffix(input: unknown, suffix: string): string;
681
+ /**
682
+ * Compares two strings the way people sort them: numbers in natural order
683
+ * and accents in the right place. Pass it straight to `sort()`.
684
+ *
685
+ * @example
686
+ * ["file10", "file2", "File1"].sort(str.compare); // ["File1", "file2", "file10"]
687
+ * str.compare("a", "A", { sensitivity: "base" }); // 0
688
+ *
689
+ * @param {unknown} a
690
+ * @param {unknown} b
691
+ * @param {CompareOptions} [options]
692
+ * @returns {number} Negative if `a` comes first, positive if `b` does, `0` if equal.
693
+ */
694
+ export function compare(a: unknown, b: unknown, options?: CompareOptions): number;
695
+ /**
696
+ * The number of single-character edits needed to turn `a` into `b`.
697
+ *
698
+ * @example
699
+ * str.levenshtein("kitten", "sitting"); // 3
700
+ *
701
+ * @param {unknown} a
702
+ * @param {unknown} b
703
+ * @returns {number}
704
+ */
705
+ export function levenshtein(a: unknown, b: unknown): number;
706
+ /**
707
+ * How alike two strings are, from `0` (nothing in common) to `1` (identical).
708
+ *
709
+ * @example
710
+ * str.similarity("hello", "hallo"); // 0.8
711
+ *
712
+ * @param {unknown} a
713
+ * @param {unknown} b
714
+ * @returns {number}
715
+ */
716
+ export function similarity(a: unknown, b: unknown): number;
717
+ /**
718
+ * Finds the candidate closest to `input`. Made for "Did you mean...?"
719
+ * suggestions.
720
+ *
721
+ * @example
722
+ * str.closest("instal", ["install", "uninstall", "list"]); // "install"
723
+ * str.closest("xyz", ["install", "list"]); // undefined
724
+ *
725
+ * @param {unknown} input
726
+ * @param {Iterable<string>} candidates
727
+ * @param {ClosestOptions} [options]
728
+ * @returns {string | undefined} `undefined` when nothing is close enough.
729
+ */
730
+ export function closest(input: unknown, candidates: Iterable<string>, options?: ClosestOptions): string | undefined;
731
+ /**
732
+ * A random string. It relies on `Math.random`, so don't use it for secrets:
733
+ * `nc.id.token()` and `nc.id.nano()` are made for that.
734
+ *
735
+ * @example
736
+ * str.random(); // "aZ3kP9qL0xYb7TcW"
737
+ * str.random(6, { charset: "0123456789" }); // "402917"
287
738
  *
288
- * @param {number} [length=16] - Desired length.
289
- * @param {string} [charset] - Characters to pick from.
290
- * @returns {string} The random string.
739
+ * @param {number} [size=16]
740
+ * @param {RandomStringOptions | string} [options] Options, or the charset itself.
741
+ * @returns {string}
291
742
  */
292
- export function random(length?: number, charset?: string): string;
743
+ export function random(size?: number, options?: RandomStringOptions | string): string;
293
744
  //# sourceMappingURL=Str.d.ts.map