@homedev/framework 1.0.0 → 1.0.2
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/README.md +673 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.js +10 -8
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
# homedev framework
|
|
2
|
+
|
|
3
|
+
Set of classes and utilities for extending Node.js with common patterns and helpers.
|
|
4
|
+
|
|
5
|
+
## Logger
|
|
6
|
+
|
|
7
|
+
### constructor(options?)
|
|
8
|
+
Creates a logger with optional overrides for level, timestamp, and output function.
|
|
9
|
+
|
|
10
|
+
Arguments:
|
|
11
|
+
- options: partial logger configuration.
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
```ts
|
|
15
|
+
const log = new Logger({ level: 'WARN', timeStamp: true })
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### write(level, ...args)
|
|
19
|
+
Writes a log message at the given level when allowed by current threshold.
|
|
20
|
+
|
|
21
|
+
Arguments:
|
|
22
|
+
- level: log level name, for example INFO or ERROR.
|
|
23
|
+
- args: message parts to log.
|
|
24
|
+
|
|
25
|
+
Usage:
|
|
26
|
+
```ts
|
|
27
|
+
log.write('ERROR', 'Something failed', err)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### info(...args), warn(...args), error(...args), debug(...args), verbose(...args)
|
|
31
|
+
Convenience methods for common log levels.
|
|
32
|
+
|
|
33
|
+
Arguments:
|
|
34
|
+
- args: message parts to log.
|
|
35
|
+
|
|
36
|
+
Usage:
|
|
37
|
+
```ts
|
|
38
|
+
log.info('Server started')
|
|
39
|
+
log.warn('Retrying request')
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## StringBuilder
|
|
43
|
+
|
|
44
|
+
### constructor(initial?, options?)
|
|
45
|
+
Builds strings efficiently with optional formatting behavior.
|
|
46
|
+
|
|
47
|
+
Arguments:
|
|
48
|
+
- initial: initial content as string, list of strings, or another builder.
|
|
49
|
+
- options: indentation and line formatting options.
|
|
50
|
+
|
|
51
|
+
Usage:
|
|
52
|
+
```ts
|
|
53
|
+
const sb = new StringBuilder('hello', { indentSize: 2 })
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### setOptions(options)
|
|
57
|
+
Replaces current formatting options.
|
|
58
|
+
|
|
59
|
+
Arguments:
|
|
60
|
+
- options: new StringBuilder options.
|
|
61
|
+
|
|
62
|
+
Usage:
|
|
63
|
+
```ts
|
|
64
|
+
sb.setOptions({ lineSeparator: '\n', trim: true })
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### clear(), isEmpty(), toString()
|
|
68
|
+
Core buffer controls.
|
|
69
|
+
|
|
70
|
+
Arguments:
|
|
71
|
+
- clear: none.
|
|
72
|
+
- isEmpty: none.
|
|
73
|
+
- toString: none.
|
|
74
|
+
|
|
75
|
+
Usage:
|
|
76
|
+
```ts
|
|
77
|
+
sb.clear()
|
|
78
|
+
sb.isEmpty()
|
|
79
|
+
sb.toString()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### indent(), dedent(), getCurrentIndent()
|
|
83
|
+
Controls current indentation level used by formatted line writes.
|
|
84
|
+
|
|
85
|
+
Arguments:
|
|
86
|
+
- indent: none.
|
|
87
|
+
- dedent: none.
|
|
88
|
+
- getCurrentIndent: none.
|
|
89
|
+
|
|
90
|
+
Usage:
|
|
91
|
+
```ts
|
|
92
|
+
sb.indent().writeLine('child').dedent()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### getLines(), formatLine(line?)
|
|
96
|
+
Reads content as lines or formats a single line according to options.
|
|
97
|
+
|
|
98
|
+
Arguments:
|
|
99
|
+
- line: optional source line.
|
|
100
|
+
|
|
101
|
+
Usage:
|
|
102
|
+
```ts
|
|
103
|
+
const line = sb.formatLine('hello')
|
|
104
|
+
const lines = sb.getLines()
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### write(...args), writeLine(...args), writeMap(items, fn)
|
|
108
|
+
Main writing helpers.
|
|
109
|
+
|
|
110
|
+
Arguments:
|
|
111
|
+
- write: any values to append.
|
|
112
|
+
- writeLine: values to append as formatted lines.
|
|
113
|
+
- writeMap: items list and callback `(item, index, builder)`.
|
|
114
|
+
|
|
115
|
+
Usage:
|
|
116
|
+
```ts
|
|
117
|
+
sb.write('A', 'B').writeLine('C')
|
|
118
|
+
sb.writeMap([1, 2], n => `${n}\n`)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Markdown
|
|
122
|
+
|
|
123
|
+
### header(text, level?)
|
|
124
|
+
Writes a markdown heading and an empty line after it.
|
|
125
|
+
|
|
126
|
+
Arguments:
|
|
127
|
+
- text: heading content.
|
|
128
|
+
- level: heading level, normalized to 1..6.
|
|
129
|
+
|
|
130
|
+
Usage:
|
|
131
|
+
```ts
|
|
132
|
+
md.header('Overview', 2)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### codeBlock(code?, language?), endCodeBlock()
|
|
136
|
+
Writes fenced code blocks. Fences are adjusted if code already contains backticks.
|
|
137
|
+
|
|
138
|
+
Arguments:
|
|
139
|
+
- code: optional code text.
|
|
140
|
+
- language: optional language id.
|
|
141
|
+
|
|
142
|
+
Usage:
|
|
143
|
+
```ts
|
|
144
|
+
md.codeBlock('const x = 1', 'ts')
|
|
145
|
+
md.codeBlock().writeLine('manual').endCodeBlock()
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### link(text, url, title?)
|
|
149
|
+
Writes an inline markdown link.
|
|
150
|
+
|
|
151
|
+
Arguments:
|
|
152
|
+
- text: visible link text.
|
|
153
|
+
- url: link target.
|
|
154
|
+
- title: optional title attribute.
|
|
155
|
+
|
|
156
|
+
Usage:
|
|
157
|
+
```ts
|
|
158
|
+
md.link('Docs', '/docs', 'Open docs')
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### table(headers, rows)
|
|
162
|
+
Writes a markdown table with automatic column padding.
|
|
163
|
+
|
|
164
|
+
Arguments:
|
|
165
|
+
- headers: column headers (must not be empty).
|
|
166
|
+
- rows: table rows as arrays.
|
|
167
|
+
|
|
168
|
+
Usage:
|
|
169
|
+
```ts
|
|
170
|
+
md.table(['Name', 'Age'], [['Alice', '30'], ['Bob', '25']])
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### blockquote(text)
|
|
174
|
+
Writes one blockquote line per input line.
|
|
175
|
+
|
|
176
|
+
Arguments:
|
|
177
|
+
- text: quote text, can be multiline.
|
|
178
|
+
|
|
179
|
+
Usage:
|
|
180
|
+
```ts
|
|
181
|
+
md.blockquote('Line 1\nLine 2')
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### bold(text), italic(text), code(text)
|
|
185
|
+
Inline text style helpers.
|
|
186
|
+
|
|
187
|
+
Arguments:
|
|
188
|
+
- text: value to wrap in markdown markers.
|
|
189
|
+
|
|
190
|
+
Usage:
|
|
191
|
+
```ts
|
|
192
|
+
md.bold('Important').write(' ').italic('note').write(' ').code('x')
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### item(text), items(values), orderedList(items, start?)
|
|
196
|
+
List helpers for bullets and numbered lists.
|
|
197
|
+
|
|
198
|
+
Arguments:
|
|
199
|
+
- item: single bullet text.
|
|
200
|
+
- items: array of values or object map.
|
|
201
|
+
- orderedList: list items and optional start index.
|
|
202
|
+
|
|
203
|
+
Usage:
|
|
204
|
+
```ts
|
|
205
|
+
md.item('One')
|
|
206
|
+
md.items(['A', 'B'])
|
|
207
|
+
md.orderedList(['First', 'Second'], 3)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### horizontalRule(), image(alt, url)
|
|
211
|
+
Writes separators and images.
|
|
212
|
+
|
|
213
|
+
Arguments:
|
|
214
|
+
- horizontalRule: none.
|
|
215
|
+
- image: alt text and image URL.
|
|
216
|
+
|
|
217
|
+
Usage:
|
|
218
|
+
```ts
|
|
219
|
+
md.horizontalRule()
|
|
220
|
+
md.image('logo', '/img/logo.png')
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### strikethrough(text), highlight(text), subscript(text), superscript(text)
|
|
224
|
+
Additional inline formatting helpers.
|
|
225
|
+
|
|
226
|
+
Arguments:
|
|
227
|
+
- text: content to format.
|
|
228
|
+
|
|
229
|
+
Usage:
|
|
230
|
+
```ts
|
|
231
|
+
md.strikethrough('old').write(' ').highlight('new')
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### taskList(items)
|
|
235
|
+
Writes GitHub-style task checklist entries.
|
|
236
|
+
|
|
237
|
+
Arguments:
|
|
238
|
+
- items: list of `{ text, checked }`.
|
|
239
|
+
|
|
240
|
+
Usage:
|
|
241
|
+
```ts
|
|
242
|
+
md.taskList([{ text: 'Ship release', checked: false }])
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### section(text, level?), endSection(), setSectionLevel(level)
|
|
246
|
+
Nested section heading workflow.
|
|
247
|
+
|
|
248
|
+
Arguments:
|
|
249
|
+
- section: heading text and optional explicit level.
|
|
250
|
+
- endSection: none.
|
|
251
|
+
- setSectionLevel: explicit current section depth.
|
|
252
|
+
|
|
253
|
+
Usage:
|
|
254
|
+
```ts
|
|
255
|
+
md.section('Chapter')
|
|
256
|
+
md.section('Details')
|
|
257
|
+
md.endSection()
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Array functions
|
|
261
|
+
|
|
262
|
+
### mapAsync(callback), forEachAsync(callback)
|
|
263
|
+
Async iteration helpers.
|
|
264
|
+
|
|
265
|
+
Arguments:
|
|
266
|
+
- callback: async callback `(item, index, array)`.
|
|
267
|
+
|
|
268
|
+
Usage:
|
|
269
|
+
```ts
|
|
270
|
+
const names = await users.mapAsync(async u => u.name)
|
|
271
|
+
await users.forEachAsync(async u => save(u))
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### sortBy(selector, ascending?)
|
|
275
|
+
Returns a sorted copy using selector value comparison.
|
|
276
|
+
|
|
277
|
+
Arguments:
|
|
278
|
+
- selector: function extracting sort value.
|
|
279
|
+
- ascending: sort direction, default true.
|
|
280
|
+
|
|
281
|
+
Usage:
|
|
282
|
+
```ts
|
|
283
|
+
const ordered = users.sortBy(u => u.age)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### unique(), uniqueBy(selector), groupBy(selector)
|
|
287
|
+
Deduplication and grouping helpers.
|
|
288
|
+
|
|
289
|
+
Arguments:
|
|
290
|
+
- unique: none.
|
|
291
|
+
- uniqueBy: key selector.
|
|
292
|
+
- groupBy: key selector.
|
|
293
|
+
|
|
294
|
+
Usage:
|
|
295
|
+
```ts
|
|
296
|
+
ids.unique()
|
|
297
|
+
users.uniqueBy(u => u.id)
|
|
298
|
+
users.groupBy(u => u.role)
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### toObject(keySelector, valueSelector?), toObjectWithKey(key)
|
|
302
|
+
Converts arrays into object maps.
|
|
303
|
+
|
|
304
|
+
Arguments:
|
|
305
|
+
- keySelector: key function.
|
|
306
|
+
- valueSelector: optional value function.
|
|
307
|
+
- key: property name used as key.
|
|
308
|
+
|
|
309
|
+
Usage:
|
|
310
|
+
```ts
|
|
311
|
+
users.toObject(u => u.id)
|
|
312
|
+
users.toObjectWithKey('id')
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### nonNullMap(callback), nonNullMapAsync(callback)
|
|
316
|
+
Maps and removes nullish callback outputs.
|
|
317
|
+
|
|
318
|
+
Arguments:
|
|
319
|
+
- callback: mapping callback.
|
|
320
|
+
|
|
321
|
+
Usage:
|
|
322
|
+
```ts
|
|
323
|
+
const values = items.nonNullMap(i => i.optional)
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### findOrFail(predicate, message?, thisArg?)
|
|
327
|
+
Finds first match or throws an error.
|
|
328
|
+
|
|
329
|
+
Arguments:
|
|
330
|
+
- predicate: match function.
|
|
331
|
+
- message: optional error message.
|
|
332
|
+
- thisArg: optional predicate context.
|
|
333
|
+
|
|
334
|
+
Usage:
|
|
335
|
+
```ts
|
|
336
|
+
const admin = users.findOrFail(u => u.role === 'admin', 'Admin not found')
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### selectFor(predicate, selector, message?, thisArg?)
|
|
340
|
+
Finds an item then returns selected projection.
|
|
341
|
+
|
|
342
|
+
Arguments:
|
|
343
|
+
- predicate: match function.
|
|
344
|
+
- selector: projection function.
|
|
345
|
+
- message: optional error message.
|
|
346
|
+
- thisArg: optional predicate context.
|
|
347
|
+
|
|
348
|
+
Usage:
|
|
349
|
+
```ts
|
|
350
|
+
const email = users.selectFor(u => u.id === 1, u => u.email)
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### createInstances(Target, ...args)
|
|
354
|
+
Creates class instances from array values.
|
|
355
|
+
|
|
356
|
+
Arguments:
|
|
357
|
+
- Target: constructor function.
|
|
358
|
+
- args: shared constructor args.
|
|
359
|
+
|
|
360
|
+
Usage:
|
|
361
|
+
```ts
|
|
362
|
+
const models = rows.createInstances(UserModel, commonConfig)
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### mergeAll(options?)
|
|
366
|
+
Merges all array objects into one output object.
|
|
367
|
+
|
|
368
|
+
Arguments:
|
|
369
|
+
- options: merge conflict behavior options.
|
|
370
|
+
|
|
371
|
+
Usage:
|
|
372
|
+
```ts
|
|
373
|
+
const config = [{ a: 1 }, { b: 2 }].mergeAll()
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Array.flat(value)
|
|
377
|
+
Static helper that flattens array input or wraps non-array values.
|
|
378
|
+
|
|
379
|
+
Arguments:
|
|
380
|
+
- value: value or array.
|
|
381
|
+
|
|
382
|
+
Usage:
|
|
383
|
+
```ts
|
|
384
|
+
const result = Array.flat([1, [2, 3]])
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
## Object functions
|
|
388
|
+
|
|
389
|
+
### mapEntries(obj, callback)
|
|
390
|
+
Transforms object entries into a new object.
|
|
391
|
+
|
|
392
|
+
Arguments:
|
|
393
|
+
- obj: source object.
|
|
394
|
+
- callback: returns `[newKey, newValue]`.
|
|
395
|
+
|
|
396
|
+
Usage:
|
|
397
|
+
```ts
|
|
398
|
+
const mapped = Object.mapEntries({ a: 1 }, ([k, v]) => [k.toUpperCase(), v * 2])
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### toList(obj, keyName)
|
|
402
|
+
Converts object map into array items and adds key field.
|
|
403
|
+
|
|
404
|
+
Arguments:
|
|
405
|
+
- obj: source object.
|
|
406
|
+
- keyName: property name for map key.
|
|
407
|
+
|
|
408
|
+
Usage:
|
|
409
|
+
```ts
|
|
410
|
+
const rows = Object.toList({ x: { n: 1 } }, 'id')
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### deepClone(obj)
|
|
414
|
+
Performs deep clone using structuredClone or JSON fallback.
|
|
415
|
+
|
|
416
|
+
Arguments:
|
|
417
|
+
- obj: value to clone.
|
|
418
|
+
|
|
419
|
+
Usage:
|
|
420
|
+
```ts
|
|
421
|
+
const copy = Object.deepClone(original)
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### merge(source, target, options?)
|
|
425
|
+
Deep-merges source values into target object.
|
|
426
|
+
|
|
427
|
+
Arguments:
|
|
428
|
+
- source: source object.
|
|
429
|
+
- target: target object, modified in place.
|
|
430
|
+
- options: conflict and strategy handlers.
|
|
431
|
+
|
|
432
|
+
Usage:
|
|
433
|
+
```ts
|
|
434
|
+
Object.merge(sourceConfig, targetConfig)
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### navigate(obj, callback)
|
|
438
|
+
Walks object tree and allows replace/delete/update while traversing.
|
|
439
|
+
|
|
440
|
+
Arguments:
|
|
441
|
+
- obj: root object.
|
|
442
|
+
- callback: visitor callback with path context.
|
|
443
|
+
|
|
444
|
+
Usage:
|
|
445
|
+
```ts
|
|
446
|
+
Object.navigate(data, ({ value }) => value)
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### find(from, predicate)
|
|
450
|
+
Returns nested values matching predicate.
|
|
451
|
+
|
|
452
|
+
Arguments:
|
|
453
|
+
- from: root object.
|
|
454
|
+
- predicate: match function.
|
|
455
|
+
|
|
456
|
+
Usage:
|
|
457
|
+
```ts
|
|
458
|
+
const ids = Object.find(data, ({ key }) => key === 'id')
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### select(from, path, options?)
|
|
462
|
+
Selects nested values with path expressions and options.
|
|
463
|
+
|
|
464
|
+
Arguments:
|
|
465
|
+
- from: root object.
|
|
466
|
+
- path: selection path.
|
|
467
|
+
- options: set/default/optional behavior.
|
|
468
|
+
|
|
469
|
+
Usage:
|
|
470
|
+
```ts
|
|
471
|
+
const city = Object.select(user, 'address.city')
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
## String functions
|
|
475
|
+
|
|
476
|
+
### toPascal(), capitalize(), toCamel(), toSnake(), toKebab(), changeCase(to)
|
|
477
|
+
Case conversion helpers.
|
|
478
|
+
|
|
479
|
+
Arguments:
|
|
480
|
+
- changeCase: `to` target format.
|
|
481
|
+
|
|
482
|
+
Usage:
|
|
483
|
+
```ts
|
|
484
|
+
'hello world'.toCamel()
|
|
485
|
+
'hello_world'.toPascal()
|
|
486
|
+
'sample'.changeCase('upper')
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### splitWithQuotes(separator?), splitNested(separator, open, close)
|
|
490
|
+
Split helpers that respect quoted or nested segments.
|
|
491
|
+
|
|
492
|
+
Arguments:
|
|
493
|
+
- splitWithQuotes: optional separator, default comma.
|
|
494
|
+
- splitNested: separator plus opening/closing delimiters.
|
|
495
|
+
|
|
496
|
+
Usage:
|
|
497
|
+
```ts
|
|
498
|
+
'a, "b, c", d'.splitWithQuotes(',')
|
|
499
|
+
'a(b,c),d'.splitNested(',', '(', ')')
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### toStringBuilder()
|
|
503
|
+
Converts string into StringBuilder initialized by lines.
|
|
504
|
+
|
|
505
|
+
Arguments:
|
|
506
|
+
- none.
|
|
507
|
+
|
|
508
|
+
Usage:
|
|
509
|
+
```ts
|
|
510
|
+
const sb = 'line1\nline2'.toStringBuilder()
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### toHtmlLink(path?), toRgb(), toArgb()
|
|
514
|
+
Formatting helpers for links and colors.
|
|
515
|
+
|
|
516
|
+
Arguments:
|
|
517
|
+
- path: optional URL for anchor.
|
|
518
|
+
- toRgb: none, expects hex color string.
|
|
519
|
+
- toArgb: none, expects ARGB hex color string.
|
|
520
|
+
|
|
521
|
+
Usage:
|
|
522
|
+
```ts
|
|
523
|
+
'Docs'.toHtmlLink('/docs')
|
|
524
|
+
'#ff0080'.toRgb()
|
|
525
|
+
'80ff0080'.toArgb()
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### single(char), remove(char), toAlphanum(), toAlpha()
|
|
529
|
+
String cleanup helpers.
|
|
530
|
+
|
|
531
|
+
Arguments:
|
|
532
|
+
- char: character or regex fragment to collapse/remove.
|
|
533
|
+
|
|
534
|
+
Usage:
|
|
535
|
+
```ts
|
|
536
|
+
'a---b'.single('-')
|
|
537
|
+
'a-b-c'.remove('-')
|
|
538
|
+
'a!1b'.toAlphanum()
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### padBlock(indent, separator?, padder?), tokenize(values, tokenizer?), stripIndent()
|
|
542
|
+
Text block and templating helpers.
|
|
543
|
+
|
|
544
|
+
Arguments:
|
|
545
|
+
- padBlock: indent size, optional separator and pad char.
|
|
546
|
+
- tokenize: value map and optional token regex.
|
|
547
|
+
- stripIndent: none.
|
|
548
|
+
|
|
549
|
+
Usage:
|
|
550
|
+
```ts
|
|
551
|
+
'first\nsecond'.padBlock(2)
|
|
552
|
+
'Hello ${name}'.tokenize({ name: 'Ada' })
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
## File functions
|
|
556
|
+
|
|
557
|
+
### exists(fileName)
|
|
558
|
+
Checks whether a file is readable.
|
|
559
|
+
|
|
560
|
+
Arguments:
|
|
561
|
+
- fileName: file path.
|
|
562
|
+
|
|
563
|
+
Usage:
|
|
564
|
+
```ts
|
|
565
|
+
const ok = await exists('config.json')
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### locate(fileName, dirs?)
|
|
569
|
+
Resolves a file path by searching optional directories.
|
|
570
|
+
|
|
571
|
+
Arguments:
|
|
572
|
+
- fileName: relative or absolute file name.
|
|
573
|
+
- dirs: optional directories to check.
|
|
574
|
+
|
|
575
|
+
Usage:
|
|
576
|
+
```ts
|
|
577
|
+
const fullPath = await locate('settings.json', ['.', 'config'])
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### loadFormat(fileName, options?)
|
|
581
|
+
Reads and parses file content by format or extension matching.
|
|
582
|
+
|
|
583
|
+
Arguments:
|
|
584
|
+
- fileName: file to load.
|
|
585
|
+
- options: parser map, lookup dirs, or forced format.
|
|
586
|
+
|
|
587
|
+
Usage:
|
|
588
|
+
```ts
|
|
589
|
+
const data = await loadFormat('data.json')
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
### writeFormat(filePath, content, options?)
|
|
593
|
+
Encodes and writes content using selected encoder.
|
|
594
|
+
|
|
595
|
+
Arguments:
|
|
596
|
+
- filePath: destination path.
|
|
597
|
+
- content: value to write.
|
|
598
|
+
- options: encoder map and format.
|
|
599
|
+
|
|
600
|
+
Usage:
|
|
601
|
+
```ts
|
|
602
|
+
await writeFormat('out.json', { ok: true }, { format: 'json' })
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### globMap(pattern, options)
|
|
606
|
+
Runs async mapping over files that match glob pattern(s).
|
|
607
|
+
|
|
608
|
+
Arguments:
|
|
609
|
+
- pattern: glob pattern or direct file path.
|
|
610
|
+
- options: cwd, optional filter, and async mapper.
|
|
611
|
+
|
|
612
|
+
Usage:
|
|
613
|
+
```ts
|
|
614
|
+
const files = await globMap('**/*.ts', { cwd: '.', map: async f => f })
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### writeOutputs(outputs, options?), writeOutput(output, options?)
|
|
618
|
+
Writes one or many typed outputs with filtering support.
|
|
619
|
+
|
|
620
|
+
Arguments:
|
|
621
|
+
- outputs/output: output definition(s) with name/value/type/class.
|
|
622
|
+
- options: target dir, class filtering, and pre-write hook.
|
|
623
|
+
|
|
624
|
+
Usage:
|
|
625
|
+
```ts
|
|
626
|
+
await writeOutputs([{ name: 'a.json', type: 'json', value: { a: 1 } }], { targetDirectory: 'dist' })
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
### importList(modules, options?), importGlob(patterns, options?)
|
|
630
|
+
Dynamically imports modules from explicit list or glob patterns.
|
|
631
|
+
|
|
632
|
+
Arguments:
|
|
633
|
+
- modules/patterns: module list or glob list.
|
|
634
|
+
- options: cwd, default-resolution mode, filters, fail strategy, mapper.
|
|
635
|
+
|
|
636
|
+
Usage:
|
|
637
|
+
```ts
|
|
638
|
+
const mods = await importList(['./tool.ts'])
|
|
639
|
+
const many = await importGlob(['**/*.ts'], { cwd: 'plugins' })
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
### getCwd(cwd?)
|
|
643
|
+
Resolves effective working directory.
|
|
644
|
+
|
|
645
|
+
Arguments:
|
|
646
|
+
- cwd: optional absolute or relative directory.
|
|
647
|
+
|
|
648
|
+
Usage:
|
|
649
|
+
```ts
|
|
650
|
+
const base = getCwd('config')
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
## Global helpers
|
|
654
|
+
|
|
655
|
+
### AsyncFunction
|
|
656
|
+
Runtime alias to async function constructor.
|
|
657
|
+
|
|
658
|
+
Usage:
|
|
659
|
+
```ts
|
|
660
|
+
const fn = new AsyncFunction('x', 'return x * 2')
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
### defined(value, msg?)
|
|
664
|
+
Returns value when not null/undefined; throws otherwise.
|
|
665
|
+
|
|
666
|
+
Arguments:
|
|
667
|
+
- value: value to validate.
|
|
668
|
+
- msg: optional error message.
|
|
669
|
+
|
|
670
|
+
Usage:
|
|
671
|
+
```ts
|
|
672
|
+
const safe = defined(input, 'Input is required')
|
|
673
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses and queries command-line arguments.
|
|
3
|
+
*
|
|
4
|
+
* Accepts argv-like arrays and parses only the provided tokens.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export declare class CommandLineArgs {
|
|
9
|
+
#private;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a parser for the provided command-line tokens.
|
|
12
|
+
*
|
|
13
|
+
* @param args - Argument tokens to parse.
|
|
14
|
+
* @param definitions - Known argument definitions used by usage output.
|
|
15
|
+
*/
|
|
16
|
+
constructor(args: string[], definitions?: CommandLineArgumentDefinition[]);
|
|
17
|
+
/**
|
|
18
|
+
* Returns normalized parsed argument tokens.
|
|
19
|
+
*/
|
|
20
|
+
get args(): string[];
|
|
21
|
+
/**
|
|
22
|
+
* Returns non-option positional values.
|
|
23
|
+
*/
|
|
24
|
+
get positionals(): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Returns true if a flag was provided.
|
|
27
|
+
*
|
|
28
|
+
* @param flag - Option name with or without `-`/`--` prefix.
|
|
29
|
+
*/
|
|
30
|
+
has(flag: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Returns values for a flag.
|
|
33
|
+
*
|
|
34
|
+
* @param flag - Option name with or without `-`/`--` prefix.
|
|
35
|
+
*/
|
|
36
|
+
getArgs(flag: string): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Returns true for boolean flags, first value for valued flags, or undefined.
|
|
39
|
+
*
|
|
40
|
+
* @param flag - Option name with or without `-`/`--` prefix.
|
|
41
|
+
*/
|
|
42
|
+
get(flag: string): string | true | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Returns all options as a plain object.
|
|
45
|
+
*/
|
|
46
|
+
toObject(): Record<string, string[] | true>;
|
|
47
|
+
/**
|
|
48
|
+
* Builds usage output from provided argument definitions.
|
|
49
|
+
*
|
|
50
|
+
* @param command - Command name shown in usage output.
|
|
51
|
+
*/
|
|
52
|
+
usage(command?: string): string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Defines an argument for usage output.
|
|
57
|
+
*
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
export declare interface CommandLineArgumentDefinition {
|
|
61
|
+
name: string;
|
|
62
|
+
alias?: string;
|
|
63
|
+
description?: string;
|
|
64
|
+
takesValue?: boolean;
|
|
65
|
+
multiple?: boolean;
|
|
66
|
+
valueName?: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Parsed representation of a single CLI option.
|
|
71
|
+
*
|
|
72
|
+
* @public
|
|
73
|
+
*/
|
|
74
|
+
export declare interface CommandLineOption {
|
|
75
|
+
values: string[];
|
|
76
|
+
sawEqualsStyle: boolean;
|
|
77
|
+
}
|
|
78
|
+
|
|
1
79
|
/**
|
|
2
80
|
* Checks whether a file is readable.
|
|
3
81
|
*
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
Array.prototype.findOrFail=function(T,x
|
|
2
|
-
`))};String.prototype.padBlock=function(T,
|
|
3
|
-
`,
|
|
4
|
-
`)};String.prototype.toHtmlLink=function(T){return`<a href="${T??this.toString()}">${this.toString()}</a>`};String.prototype.toRgb=function(){let T=this.toString().replace("#","");if(T.length!==6)throw Error("Invalid hex color");let
|
|
1
|
+
Array.prototype.findOrFail=function(T,U,x){let b=this.find(T,x);if(b===void 0)throw Error(U??"Element not found");return b};Array.flat=function(T){if(Array.isArray(T))return T.flat(2);else return[T]};Array.prototype.forEachAsync=async function(T){for(let U=0;U<this.length;U++)await T(this[U],U,this)};Array.prototype.groupBy=function(T){return this.reduce((U,x)=>{let b=T(x);if(!U[b])U[b]=[];return U[b].push(x),U},{})};Array.prototype.createInstances=function(T,...U){return this.map((x,b)=>new T(...U,x,b))};Array.prototype.mapAsync=async function(T){return Promise.all(this.map(T))};Array.prototype.nonNullMap=function(T){let U=[];for(let x=0;x<this.length;x++){let b=T(this[x],x,this);if(b!=null)U.push(b)}return U};Array.prototype.nonNullMapAsync=async function(T){let U=[];for(let x=0;x<this.length;x++){let b=await T(this[x],x,this);if(b!=null)U.push(b)}return U};Array.prototype.mergeAll=function(T){let U={};for(let x of this.slice().reverse())Object.merge(x,U,T);return U};Array.prototype.toObject=function(T,U){return Object.fromEntries(this.map((x)=>{let b=T(x),O=U?U(x):x;return[b,O]}))};Array.prototype.toObjectWithKey=function(T){return Object.fromEntries(this.map((U)=>[String(U[T]),U]))};Array.prototype.selectFor=function(T,U,x,b){let O=this.find(T,b);if(O===void 0)throw Error(x??"Element not found");return U(O)};Array.prototype.sortBy=function(T,U=!0){return this.slice().sort((x,b)=>{let O=T(x),A=T(b);if(O<A)return U?-1:1;if(O>A)return U?1:-1;return 0})};Array.prototype.unique=function(){return Array.from(new Set(this))};Array.prototype.uniqueBy=function(T){let U=new Set;return this.filter((x)=>{let b=T(x);if(U.has(b))return!1;else return U.add(b),!0})};var w;((E)=>{E[E.Explore=0]="Explore";E[E.SkipSiblings=1]="SkipSiblings";E[E.NoExplore=2]="NoExplore";E[E.ReplaceParent=3]="ReplaceParent";E[E.DeleteParent=4]="DeleteParent";E[E.MergeParent=5]="MergeParent";E[E.ReplaceItem=6]="ReplaceItem";E[E.DeleteItem=7]="DeleteItem"})(w||={});class X{action;by;skipSiblings;reexplore;constructor(T,U,x,b){this.action=T;this.by=U;this.skipSiblings=x;this.reexplore=b}static _explore=new X(0);static _noExplore=new X(2);static _skipSiblings=new X(1);static _deleteParent=new X(4);static ReplaceParent(T,U){return new X(3,T,void 0,U)}static SkipSiblings(){return X._skipSiblings}static Explore(){return X._explore}static NoExplore(){return X._noExplore}static DeleteParent(){return X._deleteParent}static MergeParent(T){return new X(5,T)}static ReplaceItem(T,U){return new X(6,T,U)}static DeleteItem(T){return new X(7,void 0,T)}}Object.navigate=async(T,U)=>{let x=new WeakSet,b=[],O=[],A=async(F,E,j)=>{let B=F===null,Y=B?X.Explore():await U({key:F,value:E,path:b,parent:j,parents:O});if(E&&typeof E==="object"&&Y.action===0){if(x.has(E))return Y;if(x.add(E),!B)b.push(F),O.push(j);let f=E;while(await K(f,F,j))f=j[F];if(!B)O.pop(),b.pop()}return Y},K=async(F,E,j)=>{let B=Object.keys(F),$=B.length;for(let Y=0;Y<$;Y++){let Z=B[Y],Q=F[Z],f=await A(Z,Q,F),G=f.action;if(G===0||G===2)continue;if(G===6){if(F[Z]=f.by,f.skipSiblings)return;continue}if(G===7){if(delete F[Z],f.skipSiblings)return;continue}if(G===1)return;if(G===3){if(E===null)throw Error("Cannot replace root object");if(j[E]=f.by,f.reexplore)return!0;return}if(G===4){if(E===null)throw Error("Cannot delete root object");delete j[E];return}if(G===5)delete F[Z],Object.assign(F,f.by)}};await A(null,T,null)};Object.find=async function(T,U){let x=[];return await Object.navigate(T,(b)=>{if(U([...b.path,b.key].join("."),b.value))x.push(b.value);return X.Explore()}),x};Object.merge=(T,U,x)=>{for(let b of Object.keys(U)){if(T[b]===void 0)continue;let O=U[b],A=T[b];if(typeof A!==typeof O||Array.isArray(A)!==Array.isArray(O)){let F=x?.mismatch?.(b,A,O,T,U);if(F!==void 0){U[b]=F;continue}throw Error(`Type mismatch: ${b}`)}let K=x?.mode?.(b,A,O,T,U)??U[".merge"]??"merge";switch(K){case"source":U[b]=A;continue;case"target":continue;case"skip":delete U[b],delete T[b];continue;case"merge":break;default:throw Error(`Unknown merge mode: ${K}`)}if(typeof A==="object")if(Array.isArray(A))O.push(...A);else{if(x?.navigate?.(b,A,O,T,U)===!1)continue;Object.merge(A,O,x)}else{if(A===O)continue;let F=x?.conflict?.(b,A,O,T,U);U[b]=F===void 0?O:F}}for(let b of Object.keys(T))if(U[b]===void 0)U[b]=T[b]};var L=/^\[([^=\]]*)([=]*)([^\]]*)\]$/,V=/^([^[\]]*)\[([^\]]*)]$/,m=(T,U,x,b)=>{if(T.startsWith("{")&&T.endsWith("}")){let O=T.substring(1,T.length-1);return Object.select(U,O,x)?.toString()}return b?T:void 0},P=(T,U,x,b)=>{let O=m(U,x,b);if(O)return Object.select(T,O,b);let A=L.exec(U);if(A){let[,F,E,j]=A,B=m(F.trim(),x,b,!0),$=m(j.trim(),x,b,!0);if(Array.isArray(T)&&(E==="="||E==="==")&&B)return T.find((Y)=>Y?.[B]==$)}let K=V.exec(U);if(K){let[,F,E]=K;return T?.[F]?.[E]}return T?.[U]};Object.select=(T,U,x)=>{let b=void 0,O=void 0,A=U??"",K=($)=>{if(!$)return[$,!1];return $.endsWith("?")?[$.substring(0,$.length-1),!0]:[$,!1]},F=($,Y)=>{let[Z,Q]=K(Y.pop());if(!Z){if(x?.set!==void 0&&O!==void 0&&b!==void 0)b[O]=x.set;return $}let f=P($,Z,T,x);if(f===void 0){if(Q||x?.optional||x?.defaultValue!==void 0)return;throw Error(`Unknown path element: "${Z}" in "${A}"`)}return b=$,O=Z,F(f,Y)},E=A.splitNested(x?.separator??".","{","}"),j=void 0;if(E.length>0&&E[E.length-1].startsWith("?="))j=E.pop()?.substring(2);E.reverse();let B=F(T,E);if(B===void 0)return j??x?.defaultValue;return B};Object.deepClone=function(T){if(typeof structuredClone<"u")try{return structuredClone(T)}catch{}return JSON.parse(JSON.stringify(T))};Object.toList=function(T,U){return Object.entries(T).map(([x,b])=>({[U]:x,...b}))};Object.mapEntries=function(T,U){let b=Object.entries(T).map(([O,A])=>U(O,A));return Object.fromEntries(b)};global.AsyncFunction=Object.getPrototypeOf(async function(){}).constructor;global.defined=(T,U="Value is undefined")=>{if(T===void 0||T===null)throw Error(U);return T};String.prototype.tokenize=function(T,U=/\${([^}]+)}/g){return this.replace(U,(x,b)=>{let O=T[b];if(O===null||O===void 0)return"";if(typeof O==="string")return O;if(typeof O==="number"||typeof O==="boolean")return String(O);return String(O)})};String.prototype.toPascal=function(){return this.replace(/((?:[_ ]+)\w|^\w)/g,(T,U)=>U.toUpperCase()).replace(/[^a-zA-Z0-9 ]/g,"").replace(/[_ ]/g,"")};String.prototype.capitalize=function(){return this.replace(/((?:[ ]+)\w|^\w)/g,(T,U)=>U.toUpperCase())};String.prototype.toCamel=function(){return this.toPascal().replace(/((?:[ ]+\w)|^\w)/g,(T,U)=>U.toLowerCase())};String.prototype.toSnake=function(){return this.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/\s+/g,"_")};String.prototype.toKebab=function(){return this.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/\s+/g,"-")};String.prototype.changeCase=function(T){switch(T){case"upper":return this.toUpperCase();case"lower":return this.toLowerCase();case"pascal":return this.toPascal();case"camel":return this.toCamel();case"snake":return this.toSnake();case"kebab":return this.toKebab();default:throw Error(`Unsupported case type: ${T}`)}};String.prototype.splitWithQuotes=function(T=","){let U=[],x=this.length,b=T.length,O=0,A=(K)=>{if(K+b>x)return!1;for(let F=0;F<b;F++)if(this[K+F]!==T[F])return!1;return!0};while(O<x){while(O<x&&this[O]===" ")O++;if(O>=x)break;let K="",F=this[O]==='"'||this[O]==="'";if(F){let E=this[O++];while(O<x&&this[O]!==E)K+=this[O++];if(O<x)O++}else{while(O<x&&!A(O)){let E=this[O];if(E==='"'||E==="'"){K+=E,O++;while(O<x&&this[O]!==E)K+=this[O++];if(O<x)K+=this[O++]}else K+=this[O++]}K=K.trim()}if(K)U.push({value:K,quoted:F});if(A(O))O+=b}return U};String.prototype.splitNested=function(T,U,x){let b=0,O="",A=[];for(let K of this){if(O+=K,K===U)b++;if(K===x)b--;if(b===0&&K===T)A.push(O.slice(0,-1)),O=""}if(O)A.push(O);return A};String.prototype.toStringBuilder=function(){return new J(this.split(`
|
|
2
|
+
`))};String.prototype.padBlock=function(T,U=`
|
|
3
|
+
`,x=" "){let b=x.repeat(T);return this.split(U).map((O)=>b+O).join(U)};String.prototype.stripIndent=function(){let T=this.split(/\r?\n/),U=T.filter((b)=>b.trim().length>0).map((b)=>/^[ \t]*/.exec(b)?.[0].length??0),x=U.length>0?Math.min(...U):0;if(x===0)return this;return T.map((b)=>b.slice(x)).join(`
|
|
4
|
+
`)};String.prototype.toHtmlLink=function(T){return`<a href="${T??this.toString()}">${this.toString()}</a>`};String.prototype.toRgb=function(){let T=this.toString().replace("#","");if(T.length!==6)throw Error("Invalid hex color");let U=parseInt(T.substring(0,2),16),x=parseInt(T.substring(2,4),16),b=parseInt(T.substring(4,6),16);return`rgb(${U.toString()}, ${x.toString()}, ${b.toString()})`};String.prototype.toArgb=function(){let T=this.toString().replace("#","");if(T.length!==8)throw Error("Invalid hex color");let U=parseInt(T.substring(0,2),16),x=parseInt(T.substring(2,4),16),b=parseInt(T.substring(4,6),16),O=parseInt(T.substring(6,8),16);return`argb(${U.toString()}, ${x.toString()}, ${b.toString()}, ${O.toString()})`};String.prototype.single=function(T){return this.replaceAll(new RegExp(`(${T})+`,"g"),"$1")};String.prototype.remove=function(T){return this.replaceAll(new RegExp(T,"g"),"")};String.prototype.toAlphanum=function(){return this.replace(/[^a-z0-9]/gi,"")};String.prototype.toAlpha=function(){return this.replace(/[^a-z]/gi,"")};class R{options;constructor(T){this.options={level:"INFO",showClass:!1,levels:["DEBUG","VERBOSE","INFO","WARN","ERROR"],timeStamp:!1,timeOptions:{second:"2-digit",minute:"2-digit",hour:"2-digit",day:"2-digit",month:"2-digit",year:"2-digit"},logFunction:(U,...x)=>{switch(U){case"ERROR":console.error(...x);break;case"WARN":console.warn(...x);break;case"DEBUG":console.debug(...x);break;case"VERBOSE":console.log(...x);break;default:console.log(...x)}},...T}}write(T,...U){if(this.options.level){let O=this.options.levels.indexOf(this.options.level),A=this.options.levels.indexOf(T);if(O===-1)throw Error(`Unknown configured log level: ${this.options.level}`);if(A===-1)throw Error(`Unknown log level: ${T}`);if(A<O)return}let x=[],b=[];if(this.options.timeStamp)b.push(new Date().toLocaleString(this.options.timeLocale,this.options.timeOptions));if(this.options.showClass)b.push(T);if(b.length>0)x.push(`[${b.join(" ")}]`);x.push(...U),this.options.logFunction(T,...x)}info(...T){this.write("INFO",...T)}error(...T){this.write("ERROR",...T)}warn(...T){this.write("WARN",...T)}debug(...T){this.write("DEBUG",...T)}verbose(...T){this.write("VERBOSE",...T)}}class J{#T=[];#U=0;options;constructor(T,U){if(T instanceof J)this.options={...T.options,...U},this.#T.push(...T.#T);else if(this.options=U??{},T)if(Array.isArray(T))this.#T.push(...T);else this.#T.push(T)}setOptions(T){return this.options=T,this}clear(){return this.#T.length=0,this}isEmpty(){return this.#T.length===0}toString(){return this.#T.join("")}indent(){return this.#U+=1,this}dedent(){if(this.#U>0)this.#U-=1;return this}getCurrentIndent(){return this.#U}getLines(){return this.toString().split(`
|
|
5
5
|
`)}formatLine(T){T??=`
|
|
6
|
-
`;let
|
|
7
|
-
`)}write(...T){return this.#T.push(...T.flatMap((
|
|
8
|
-
`)}writeMap(T,
|
|
9
|
-
`).forEach((
|
|
6
|
+
`;let U=(this.options.indentChar??" ").repeat(this.#U*(this.options.indentSize??2));if(this.options.trim)T=T.trim();return U+(this.options.linePrefix??"")+T+(this.options.lineSuffix??"")+(this.options.lineSeparator??`
|
|
7
|
+
`)}write(...T){return this.#T.push(...T.flatMap((U)=>{if(U!==void 0){if(typeof U==="string")return U;if(Array.isArray(U))return U.flat();if(U instanceof J)return U.toString();if(typeof U==="function")return U(this);return String(U)}}).filter((U)=>U!==void 0)),this}writeLine(...T){return this.write(T.length>0?T.map((U)=>this.formatLine(U)):`
|
|
8
|
+
`)}writeMap(T,U){return T.forEach((x,b)=>U(x,b,this)),this}}class S extends J{#T=0;#U="```";#x(T){return Math.min(6,Math.max(1,Math.floor(T)))}#b(T){if(T===void 0)return"```";let U=0;for(let x of T.matchAll(/`+/g))U=Math.max(U,x[0].length);return"`".repeat(Math.max(3,U+1))}header(T,U=1){let x=this.#x(U);return this.writeLine(`${"#".repeat(x)} ${T}`,"")}codeBlock(T,U){let x=this.#b(T);if(this.#U=x,U??="",this.writeLine(x+U),T!==void 0)this.writeLine(T).endCodeBlock();return this}endCodeBlock(){let T=this.#U;return this.#U="```",this.writeLine(T)}link(T,U,x){if(x)return this.write(`[${T}](${U} "${x}")`);return this.write(`[${T}](${U})`)}table(T,U){if(T.length===0)throw Error("Table requires at least one header");let x=T.map((A,K)=>{let F=A.length;return U.forEach((E)=>{if(E[K])F=Math.max(F,E[K].length)}),F}),b=T.map((A,K)=>A.padEnd(x[K]));this.writeLine("| "+b.join(" | ")+" |");let O=x.map((A)=>"-".repeat(A));return this.writeLine("| "+O.join(" | ")+" |"),U.forEach((A)=>{let K=T.map((F,E)=>(A[E]??"").padEnd(x[E]));this.writeLine("| "+K.join(" | ")+" |")}),this}blockquote(T){return T.split(`
|
|
9
|
+
`).forEach((x)=>this.writeLine("> "+x)),this}bold(T){return this.write(`**${T}**`)}italic(T){return this.write(`*${T}*`)}item(T){return this.writeLine(`- ${T}`)}items(T){if(Array.isArray(T))T.forEach((U)=>this.item(U));else Object.entries(T).forEach(([U,x])=>x!==void 0&&this.item(`${U}: ${x!==void 0?String(x):""}`));return this}orderedList(T,U=1){return T.forEach((x,b)=>this.writeLine(`${(b+U).toString()}. ${x}`)),this}code(T){return this.write(`\`${T}\``)}horizontalRule(){return this.writeLine("---")}image(T,U){return this.writeLine(``)}strikethrough(T){return this.write(`~~${T}~~`)}highlight(T){return this.write(`==${T}==`)}subscript(T){return this.write(`~${T}~`)}superscript(T){return this.write(`^${T}^`)}taskList(T){return T.forEach((U)=>this.writeLine(`- [${U.checked?"x":" "}] ${U.text}`)),this}section(T,U){if(U!==void 0)this.#T=this.#x(U);else this.#T=Math.min(6,this.#T+1);return this.header(T,this.#T)}endSection(){if(this.#T>0)this.#T--;return this}setSectionLevel(T){return this.#T=Math.min(6,Math.max(0,Math.floor(T))),this}}class k{#T;#U;#x=new Map;#b=[];constructor(T,U=[]){this.#T=[...T],this.#U=[...U],this.#E()}get args(){return[...this.#T]}get positionals(){return[...this.#b]}has(T){return this.#x.has(this.#O(T))}getArgs(T){return[...this.#x.get(this.#O(T))?.values??[]]}get(T){let U=this.#x.get(this.#O(T))?.values;if(!U)return;if(U.length===0)return!0;return U[0]}toObject(){let T={};for(let[U,x]of this.#x.entries())T[U]=x.values.length>0?[...x.values]:!0;return T}usage(T="command"){let U=[`Usage: ${T} [options]`];if(this.#b.length>0)U[0]+=" [values]";if(this.#U.length===0)return U.join(`
|
|
10
|
+
`);U.push("","Options:");for(let x of this.#U){let b=`--${x.name}`,O=x.alias?`-${x.alias}`:void 0,A=x.valueName??"value",K=x.takesValue?x.multiple?` <${A}...>`:` <${A}>`:"",F=O?`${O}, ${b}`:b,E=x.description?` ${x.description}`:"";U.push(` ${F}${K}${E}`)}return U.join(`
|
|
11
|
+
`)}#E(){for(let T=0;T<this.#T.length;T++){let U=this.#T[T];if(!U.startsWith("-")||U==="-"){this.#b.push(U);continue}if(U.startsWith("--")&&U.includes("=")){let O=U.indexOf("="),A=this.#O(U.slice(0,O)),K=U.slice(O+1);this.#A(A,K.length>0?[K]:[""],!0);continue}let x=this.#O(U),b=[];while(T+1<this.#T.length){let O=this.#T[T+1];if(O.startsWith("-")&&O!=="-")break;b.push(O),T++}this.#A(x,b,!1)}}#A(T,U,x){let b=this.#x.get(T);if(!b){this.#x.set(T,{values:[...U],sawEqualsStyle:x});return}b.values.push(...U),b.sawEqualsStyle=b.sawEqualsStyle||x}#O(T){return T.replace(/^-+/,"").trim()}}import M from"fs/promises";var q=async(T)=>{try{return await M.access(T,M.constants.R_OK),!0}catch{return!1}};import C from"path";var D=async(T,U)=>{let x=!C.isAbsolute(T)&&U?["",...U]:[""];for(let b of x){let O=C.join(b,T);if(await q(O))return C.resolve(O)}throw Error(`File not found: "${T}"`)};import N from"fs/promises";import d from"path";var h=(T,U)=>U?.some((x)=>new RegExp(x).test(T))===!0,vT=async(T,U)=>{let x=await D(T,U?.dirs),b=await N.readFile(x,"utf-8"),O=d.dirname(x),A={text:{fn:(E)=>E,matching:["\\.txt$","\\.text$"]},json:{fn:JSON.parse,matching:["\\.json$"]},...U?.parsers},K=U?.format?A[U.format]:Object.values(A).find((E)=>h(T,E.matching));if(!K)throw Error(`Unsupported format for file "${T}" and no matching parser found`);return{content:await K.fn(b),fullPath:x,folderPath:O}};import r from"fs/promises";var g=(T,U)=>U?.some((x)=>new RegExp(x).test(T))===!0,I=async(T,U,x)=>{let b={text:{fn:(A)=>A,matching:["\\.txt$","\\.text$"]},json:{fn:JSON.stringify,matching:["\\.json$"]},...x?.encoders},O=x?.format?b[x.format]:Object.values(b).find((A)=>g(T,A.matching));if(!O)throw Error(`Unsupported format for file "${T}" and no matching encoder found`);await r.writeFile(T,await O.fn(U))};import v from"fs/promises";var nT=async(T,U)=>{if(typeof T==="string"&&!T.includes("*"))return await U.map(T,0,[]);let x=await Array.fromAsync(v.glob(T,{cwd:U.cwd})),b=U.filter?x.filter(U.filter):x;return await Promise.all(b.map(U.map))};import z from"fs/promises";import W from"path";var aT=async(T,U)=>{if(U?.targetDirectory&&U?.removeFirst)try{await z.rm(U?.targetDirectory,{recursive:!0,force:!0})}catch(x){throw Error(`Failed to clean the output directory: ${x.message}`,{cause:x})}for(let x of T)await c(x,U)},c=async(T,U)=>{let x=W.join(U?.targetDirectory??".",T.name),b=W.dirname(x);if(U?.classes){if(T.class!==void 0&&!U.classes.includes(T.class))return;if(U.classRequired&&T.class===void 0)throw Error(`Output "${T.name}" is missing class field`)}if(U?.writing?.(T)===!1)return;try{await z.mkdir(b,{recursive:!0})}catch(O){throw Error(`Failed to create target directory "${b}" for output "${x}": ${O.message}`,{cause:O})}try{await I(x,T.value,{format:T.type??"text"})}catch(O){throw Error(`Failed to write output "${x}": ${O.message}`,{cause:O})}};import p from"fs/promises";import H from"path";import y from"path";var _=(T)=>T?y.isAbsolute(T)?T:y.join(process.cwd(),T):process.cwd();var u=async(T,U)=>{let x=[];for(let b of T)try{let O=!H.isAbsolute(b)?H.join(_(U?.cwd),b):b;if(U?.filter?.(O)===!1)continue;let A=await import(O);if(U?.resolveDefault==="only"&&!A.default)throw Error(`Module ${b} does not have a default export`);let K=U?.resolveDefault?A.default??A:A,F=U?.map?await U.map(K,b):K;if(F!==void 0)x.push(F)}catch(O){if(U?.fail?.(b,O)===!1)continue;throw Error(`Failed to import module ${b}: ${O.message??O}`,{cause:O})}return x},AU=async(T,U)=>{let x=[],b=_(U?.cwd);for(let O of T){let A=(await Array.fromAsync(p.glob(O,{cwd:b}))).map((K)=>H.join(b,K));x.push(...await u(A,U))}return x};export{aT as writeOutputs,c as writeOutput,I as writeFormat,D as locate,vT as loadFormat,u as importList,AU as importGlob,nT as globMap,_ as getCwd,q as exists,J as StringBuilder,X as NavigateResult,w as NavigateAction,S as Markdown,R as Logger,k as CommandLineArgs};
|