@homedev/framework 1.0.6 → 1.0.7

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 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
+ ```