@qlover/scripts-context 2.2.0 → 2.3.3

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/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { UserConfig } from '@commitlint/types';
2
+ import { LoggerInterface, FormatterInterface, LogEvent } from '@qlover/logger';
2
3
  import { Env } from '@qlover/env-loader';
3
4
  import { ExecutorContextImpl, LifecyclePluginInterface, ExecutorContextInterface, ExecutorError } from '@qlover/fe-corekit';
4
5
 
@@ -41,1853 +42,9 @@ interface FeConfig {
41
42
  */
42
43
  commitlint?: UserConfig;
43
44
  /**
44
- * config of CI release
45
- *
46
- * scripts release
47
- */
48
- release?: FeReleaseConfig;
49
- /**
50
- * @default ['.env.local', '.env']
51
- */
52
- envOrder?: string[];
53
- /**
54
- * Allow additional custom properties for script-specific configurations
55
- *
56
- * This enables users to add custom configuration properties for their
57
- * specific scripts without modifying the core FeConfig type definition.
58
- *
59
- * @example
60
- * ```typescript
61
- * const config: FeConfig = {
62
- * protectedBranches: ['main'],
63
- * 'my-script': {
64
- * customOption: 'value'
65
- * }
66
- * };
67
- * ```
68
- */
69
- [key: string]: unknown;
70
- }
71
- /**
72
- * Configuration interface for automated release process management
73
- *
74
- * Core concept:
75
- * Defines comprehensive configuration options for automated release
76
- * processes, including PR management, package publishing, and
77
- * release workflow customization.
78
- *
79
- * Main features:
80
- * - PR management: Automated pull request creation and management
81
- * - Dynamic branch naming with template variables
82
- * - Customizable PR titles and descriptions
83
- * - Automatic PR labeling and categorization
84
- * - Configurable auto-merge behavior and strategies
85
- *
86
- * - Package publishing: Flexible package distribution configuration
87
- * - Custom publish paths for different environments
88
- * - Multi-package directory support for monorepos
89
- * - Package-specific labeling and tracking
90
- * - Environment-aware publishing strategies
91
- *
92
- * - Release workflow: Comprehensive release process control
93
- * - Template-based content generation
94
- * - Environment-specific configurations
95
- * - Integration with CI/CD pipelines
96
- * - Automated changelog and version management
97
- *
98
- * Design considerations:
99
- * - All properties are optional for maximum flexibility
100
- * - Template variables support dynamic content generation
101
- * - Environment-aware configuration for different deployment stages
102
- * - Integration with GitHub and other Git hosting platforms
103
- * - Support for both single-package and monorepo scenarios
104
- *
105
- * Template variables:
106
- * - `${pkgName}`: Package name from package.json
107
- * - `${tagName}`: Release version tag
108
- * - `${env}`: Release environment (development, staging, production)
109
- * - `${branch}`: Source branch name
110
- * - `${name}`: Package name for labeling
111
- * - `${changelog}`: Generated changelog content
112
- *
113
- * @example Basic release configuration
114
- * ```typescript
115
- * const releaseConfig: FeReleaseConfig = {
116
- * autoMergeReleasePR: true,
117
- * autoMergeType: 'squash',
118
- * branchName: 'release-${pkgName}-${tagName}'
119
- * };
120
- * ```
121
- *
122
- * @example Advanced configuration with custom templates
123
- * ```typescript
124
- * const releaseConfig: FeReleaseConfig = {
125
- * publishPath: './dist',
126
- * autoMergeReleasePR: false,
127
- * branchName: 'feat/release-${pkgName}-v${tagName}',
128
- * PRTitle: '🚀 Release ${pkgName} v${tagName}',
129
- * PRBody: '## Release ${pkgName} v${tagName}\n\n${changelog}',
130
- * label: {
131
- * name: 'release',
132
- * color: '1A7F37',
133
- * description: 'Automated release'
134
- * }
135
- * };
136
- * ```
137
- *
138
- * @example Monorepo configuration
139
- * ```typescript
140
- * const releaseConfig: FeReleaseConfig = {
141
- * packagesDirectories: ['packages/*', 'apps/*'],
142
- * changePackagesLabel: 'changes:${name}',
143
- * autoMergeReleasePR: true
144
- * };
145
- * ```
146
- */
147
- interface FeReleaseConfig {
148
- /**
149
- * The path to publish the package
150
- *
151
- * Core concept:
152
- * Specifies the directory path where the package should be
153
- * published, allowing for custom distribution locations
154
- * and environment-specific publishing strategies.
155
- *
156
- * Publishing behavior:
157
- * - Overrides default package.json publishConfig
158
- * - Supports both relative and absolute paths
159
- * - Used by npm publish and other distribution tools
160
- * - Enables environment-specific publishing locations
161
- * - Supports custom registry and distribution strategies
162
- *
163
- * Use cases:
164
- * - Custom npm registry publishing
165
- * - Environment-specific package distribution
166
- * - Private package repository publishing
167
- * - Alternative distribution platforms
168
- * - Testing and staging package distribution
169
- *
170
- * @optional
171
- * @default `''`
172
- * @example Basic publish path
173
- * ```typescript
174
- * const config: FeReleaseConfig = {
175
- * publishPath: './dist'
176
- * };
177
- * ```
178
- *
179
- * @example Custom registry
180
- * ```typescript
181
- * const config: FeReleaseConfig = {
182
- * publishPath: '@myorg/registry'
183
- * };
184
- * ```
185
- */
186
- publishPath?: string;
187
- /**
188
- * Whether to automatically merge PR when creating and publishing
189
- *
190
- * Core concept:
191
- * Controls whether release pull requests should be automatically
192
- * merged after successful validation, enabling fully automated
193
- * release workflows.
194
- *
195
- * Auto-merge behavior:
196
- * - Merges PR after all checks pass
197
- * - Uses specified auto-merge type (merge/squash/rebase)
198
- * - Triggers post-merge release actions
199
- * - Enables continuous deployment workflows
200
- * - Reduces manual intervention in release process
201
- *
202
- * Workflow integration:
203
- * - Integrates with GitHub auto-merge features
204
- * - Supports CI/CD pipeline automation
205
- * - Enables fully automated release processes
206
- * - Reduces release cycle time
207
- * - Maintains release quality through automated checks
208
- *
209
- * @optional
210
- * @default `false`
211
- * @example Enable auto-merge
212
- * ```typescript
213
- * const config: FeReleaseConfig = {
214
- * autoMergeReleasePR: true,
215
- * autoMergeType: 'squash'
216
- * };
217
- * ```
218
- *
219
- * @example Manual review required
220
- * ```typescript
221
- * const config: FeReleaseConfig = {
222
- * autoMergeReleasePR: false
223
- * };
224
- * ```
225
- */
226
- autoMergeReleasePR?: boolean;
227
- /**
228
- * PR auto-merge strategy for release pull requests
229
- *
230
- * Core concept:
231
- * Defines the merge strategy used when automatically merging
232
- * release pull requests, affecting commit history and
233
- * repository structure.
234
- *
235
- * Merge strategies:
236
- * - merge: Creates merge commit with branch history
237
- * - squash: Combines all commits into single commit
238
- * - rebase: Replays commits on target branch
239
- *
240
- * Strategy considerations:
241
- * - merge: Preserves complete branch history
242
- * - squash: Creates clean, linear history
243
- * - rebase: Maintains chronological order
244
- * - Affects commit message and history structure
245
- * - Influences repository maintenance and debugging
246
- *
247
- * @optional
248
- * @default `'squash'`
249
- * @example Squash merge
250
- * ```typescript
251
- * const config: FeReleaseConfig = {
252
- * autoMergeType: 'squash'
253
- * };
254
- * ```
255
- *
256
- * @example Preserve history
257
- * ```typescript
258
- * const config: FeReleaseConfig = {
259
- * autoMergeType: 'merge'
260
- * };
261
- * ```
262
- */
263
- autoMergeType?: 'merge' | 'squash' | 'rebase';
264
- /**
265
- * Template for creating release branch names
266
- *
267
- * Core concept:
268
- * Defines the naming pattern for release branches using
269
- * template variables, enabling consistent and descriptive
270
- * branch naming across different packages and environments.
271
- *
272
- * Template variables:
273
- * - `${pkgName}`: Package name from package.json
274
- * - `${tagName}`: Release version tag
275
- * - `${env}`: Release environment
276
- * - `${branch}`: Source branch name
277
- *
278
- * Branch naming patterns:
279
- * - Descriptive names for easy identification
280
- * - Consistent format across all releases
281
- * - Environment and package-specific naming
282
- * - Supports Git branch naming conventions
283
- * - Enables automated branch management
284
- *
285
- * @optional
286
- * @default `'release-${pkgName}-${tagName}'`
287
- * @example Basic branch naming
288
- * ```typescript
289
- * const config: FeReleaseConfig = {
290
- * branchName: 'release-${pkgName}-${tagName}'
291
- * };
292
- * ```
293
- *
294
- * @example Environment-aware naming
295
- * ```typescript
296
- * const config: FeReleaseConfig = {
297
- * branchName: 'release/${env}/${pkgName}-${tagName}'
298
- * };
299
- * ```
300
- */
301
- branchName?: string;
302
- /**
303
- * Template for release pull request titles
304
- *
305
- * Core concept:
306
- * Defines the title format for release pull requests using
307
- * template variables, providing clear and informative
308
- * PR titles for release management.
309
- *
310
- * Title components:
311
- * - Package name for identification
312
- * - Release version for version tracking
313
- * - Environment for deployment context
314
- * - Source branch for change tracking
315
- * - Consistent formatting for automation
316
- *
317
- * Template variables:
318
- * - `${pkgName}`: Package name from package.json
319
- * - `${tagName}`: Release version tag
320
- * - `${env}`: Release environment
321
- * - `${branch}`: Source branch name
322
- *
323
- * @optional
324
- * @default `'[${pkgName} Release] Branch:${branch}, Tag:${tagName}, Env:${env}'`
325
- * @example Basic PR title
326
- * ```typescript
327
- * const config: FeReleaseConfig = {
328
- * PRTitle: '[${pkgName} Release] v${tagName}'
329
- * };
330
- * ```
331
- *
332
- * @example Detailed PR title
333
- * ```typescript
334
- * const config: FeReleaseConfig = {
335
- * PRTitle: '🚀 Release ${pkgName} v${tagName} (${env})'
336
- * };
337
- * ```
338
- */
339
- PRTitle?: string;
340
- /**
341
- * Template for release pull request body content
342
- *
343
- * Core concept:
344
- * Defines the content template for release pull request
345
- * descriptions, providing comprehensive release information
346
- * and automated content generation.
347
- *
348
- * Content sections:
349
- * - Release details and metadata
350
- * - Generated changelog content
351
- * - Review checklist and notes
352
- * - Environment and version information
353
- * - Automated process notifications
354
- *
355
- * Template variables:
356
- * - `${tagName}`: Release version tag
357
- * - `${branch}`: Source branch name
358
- * - `${env}`: Release environment
359
- * - `${changelog}`: Generated changelog content
360
- * - `${pkgName}`: Package name
361
- *
362
- * @optional
363
- * @default Comprehensive PR body template with changelog
364
- * @example Simple PR body
365
- * ```typescript
366
- * const config: FeReleaseConfig = {
367
- * PRBody: 'Release ${pkgName} v${tagName}\n\n${changelog}'
368
- * };
369
- * ```
370
- *
371
- * @example Detailed PR body
372
- * ```typescript
373
- * const config: FeReleaseConfig = {
374
- * PRBody: `
375
- * ## Release ${pkgName} v${tagName}
376
- *
377
- * **Environment:** ${env}
378
- * **Branch:** ${branch}
379
- *
380
- * ### Changes
381
- * ${changelog}
382
- *
383
- * ### Checklist
384
- * - [ ] Version number is correct
385
- * - [ ] All tests pass
386
- * - [ ] Documentation updated
387
- * `
388
- * };
389
- * ```
390
- */
391
- PRBody?: string;
392
- /**
393
- * Configuration for release pull request labels
394
- *
395
- * Core concept:
396
- * Defines the label configuration for release pull requests,
397
- * enabling automated categorization and visual identification
398
- * of release-related PRs.
399
- *
400
- * Label features:
401
- * - Automated label application
402
- * - Customizable label appearance
403
- * - Consistent release identification
404
- * - Integration with GitHub labeling system
405
- * - Support for custom label descriptions
406
- *
407
- * Label properties:
408
- * - name: Label identifier and display name
409
- * - color: Hexadecimal color code for visual distinction
410
- * - description: Label description for documentation
411
- *
412
- * @optional
413
- * @example Basic label configuration
414
- * ```typescript
415
- * const config: FeReleaseConfig = {
416
- * label: {
417
- * name: 'release',
418
- * color: '1A7F37',
419
- * description: 'Automated release PR'
420
- * }
421
- * };
422
- * ```
423
- *
424
- * @example Custom label
425
- * ```typescript
426
- * const config: FeReleaseConfig = {
427
- * label: {
428
- * name: 'CI-Release',
429
- * color: '0366D6',
430
- * description: 'Release created by CI/CD'
431
- * }
432
- * };
433
- * ```
434
- */
435
- label?: {
436
- /**
437
- * Hexadecimal color code for label appearance
438
- *
439
- * Color format: 6-character hex string without '#'
440
- * Used for visual distinction in GitHub interface
441
- * Supports standard web color codes
442
- *
443
- * @optional
444
- * @default `'1A7F37'`
445
- * @example Green color
446
- * ```typescript
447
- * color: '1A7F37'
448
- * ```
449
- *
450
- * @example Blue color
451
- * ```typescript
452
- * color: '0366D6'
453
- * ```
454
- */
455
- color?: string;
456
- /**
457
- * Descriptive text for label documentation
458
- *
459
- * Provides context about the label's purpose
460
- * Used in GitHub label management interface
461
- * Helps team members understand label usage
462
- *
463
- * @optional
464
- * @default `'Release PR'`
465
- * @example
466
- * ```typescript
467
- * description: 'Automated release pull request'
468
- * ```
469
- */
470
- description?: string;
471
- /**
472
- * Label name for identification and display
473
- *
474
- * Used as the primary identifier for the label
475
- * Displayed in GitHub PR interface
476
- * Should be descriptive and consistent
477
- *
478
- * @optional
479
- * @default `'CI-Release'`
480
- * @example
481
- * ```typescript
482
- * name: 'release'
483
- * ```
484
- */
485
- name?: string;
486
- };
487
- /**
488
- * Template for package change labels in monorepos
489
- *
490
- * Core concept:
491
- * Defines the naming pattern for labels that identify
492
- * which packages have changed in monorepo releases,
493
- * enabling targeted review and deployment.
494
- *
495
- * Label usage:
496
- * - Applied to PRs when specific packages change
497
- * - Enables package-specific review processes
498
- * - Supports selective deployment strategies
499
- * - Improves monorepo change tracking
500
- * - Facilitates team collaboration and review
501
- *
502
- * Template variables:
503
- * - `${name}`: Package name for label identification
504
- *
505
- * @optional
506
- * @default `'changes:${name}'`
507
- * @example Basic change label
508
- * ```typescript
509
- * const config: FeReleaseConfig = {
510
- * changePackagesLabel: 'changes:${name}'
511
- * };
512
- * ```
513
- *
514
- * @example Custom change label
515
- * ```typescript
516
- * const config: FeReleaseConfig = {
517
- * changePackagesLabel: 'package:${name}'
518
- * };
519
- * ```
520
- */
521
- changePackagesLabel?: string;
522
- /**
523
- * Directories containing packages for monorepo releases
524
- *
525
- * Core concept:
526
- * Specifies the directories that contain packages for
527
- * monorepo release management, enabling selective
528
- * package discovery and release coordination.
529
- *
530
- * Directory patterns:
531
- * - Supports glob patterns for flexible matching
532
- * - Enables selective package inclusion
533
- * - Supports nested directory structures
534
- * - Facilitates monorepo organization
535
- * - Enables workspace-specific configurations
536
- *
537
- * Use cases:
538
- * - Monorepo package discovery
539
- * - Selective package releases
540
- * - Workspace-specific configurations
541
- * - Multi-package coordination
542
- * - Dependency-aware releases
543
- *
544
- * @optional
545
- * @default `[]`
546
- * @example Basic package directories
547
- * ```typescript
548
- * const config: FeReleaseConfig = {
549
- * packagesDirectories: ['packages/*']
550
- * };
551
- * ```
552
- *
553
- * @example Multiple package directories
554
- * ```typescript
555
- * const config: FeReleaseConfig = {
556
- * packagesDirectories: ['packages/*', 'apps/*', 'libs/*']
557
- * };
558
- * ```
559
- */
560
- packagesDirectories?: string[];
561
- }
562
-
563
- /**
564
- * Represents a log event in the logging system
565
- *
566
- * This class encapsulates all information about a single log event,
567
- * including the log level, message arguments, timestamp, logger name,
568
- * and optional typed context data.
569
- *
570
- * Core features:
571
- * - Automatic timestamp generation
572
- * - Type-safe context support
573
- * - Flexible argument handling
574
- * - Logger identification
575
- *
576
- * @typeParam Ctx - Type of the context value, defaults to unknown
577
- *
578
- * @example Basic usage
579
- * ```typescript
580
- * const event = new LogEvent(
581
- * 'info',
582
- * ['Application started'],
583
- * 'app'
584
- * );
585
- * // event.timestamp is automatically set
586
- * console.log(event);
587
- * ```
588
- *
589
- * @example With context
590
- * ```typescript
591
- * interface RequestContext {
592
- * requestId: string;
593
- * userId: string;
594
- * path: string;
595
- * }
596
- *
597
- * const event = new LogEvent<RequestContext>(
598
- * 'info',
599
- * ['Request processed', { duration: 150 }],
600
- * 'http',
601
- * new LogContext({
602
- * requestId: 'req-123',
603
- * userId: 'user-456',
604
- * path: '/api/users'
605
- * })
606
- * );
607
- * ```
608
- *
609
- * @example Error event
610
- * ```typescript
611
- * const error = new Error('Database connection failed');
612
- * const event = new LogEvent(
613
- * 'error',
614
- * [
615
- * 'Failed to connect to database',
616
- * {
617
- * error: error.message,
618
- * stack: error.stack,
619
- * code: 'DB_CONN_ERROR'
620
- * }
621
- * ],
622
- * 'database'
623
- * );
624
- * ```
625
- *
626
- * @example Performance monitoring
627
- * ```typescript
628
- * interface PerformanceContext {
629
- * operation: string;
630
- * startTime: number;
631
- * endTime: number;
632
- * metadata: Record<string, unknown>;
633
- * }
634
- *
635
- * const event = new LogEvent<PerformanceContext>(
636
- * 'debug',
637
- * ['Operation completed'],
638
- * 'performance',
639
- * new LogContext({
640
- * operation: 'data-processing',
641
- * startTime: 1679395845000,
642
- * endTime: 1679395846000,
643
- * metadata: {
644
- * itemsProcessed: 1000,
645
- * batchSize: 100,
646
- * cacheHits: 850
647
- * }
648
- * })
649
- * );
650
- * ```
651
- */
652
- declare class LogEvent<Ctx = unknown> {
653
- /**
654
- * Log level indicating the severity or importance
655
- *
656
- * Common values:
657
- * - 'fatal': System is unusable
658
- * - 'error': Error conditions
659
- * - 'warn': Warning conditions
660
- * - 'info': Informational messages
661
- * - 'debug': Debug-level messages
662
- * - 'trace': Trace-level messages
663
- *
664
- * @example
665
- * ```typescript
666
- * new LogEvent('error', ['Database connection failed'], 'db');
667
- * ```
668
- */
669
- level: string;
670
- /**
671
- * Array of log message arguments
672
- *
673
- * The first argument is typically the main message string,
674
- * followed by optional data objects, error instances, or
675
- * other relevant information.
676
- *
677
- * @example
678
- * ```typescript
679
- * // Simple message
680
- * new LogEvent('info', ['User logged in'], 'auth');
681
- *
682
- * // Message with data
683
- * new LogEvent('info', [
684
- * 'User logged in',
685
- * { userId: 123, role: 'admin' }
686
- * ], 'auth');
687
- *
688
- * // Error with details
689
- * new LogEvent('error', [
690
- * 'Operation failed',
691
- * new Error('Invalid input'),
692
- * { operation: 'validate', input: data }
693
- * ], 'validator');
694
- * ```
695
- */
696
- args: unknown[];
697
- /**
698
- * Name of the logger that created this event
699
- *
700
- * Used to identify the source or category of the log event.
701
- * This can be a module name, service name, or any other
702
- * identifier that helps categorize log events.
703
- *
704
- * @example
705
- * ```typescript
706
- * // Module-based names
707
- * new LogEvent('info', ['Starting'], 'auth.service');
708
- * new LogEvent('debug', ['Cache miss'], 'data.cache');
709
- *
710
- * // Component-based names
711
- * new LogEvent('info', ['Render complete'], 'ui.dashboard');
712
- * new LogEvent('error', ['API error'], 'api.users');
713
- * ```
714
- */
715
- loggerName: string;
716
- /**
717
- * Optional typed context data for the log event
718
- *
719
- * Provides additional structured data that can be used by
720
- * formatters and handlers. The context type is controlled
721
- * by the Ctx type parameter.
722
- *
723
- * @example
724
- * ```typescript
725
- * // Request context
726
- * interface RequestContext {
727
- * requestId: string;
728
- * path: string;
729
- * method: string;
730
- * }
731
- *
732
- * new LogEvent<RequestContext>(
733
- * 'info',
734
- * ['Request received'],
735
- * 'http',
736
- * new LogContext({
737
- * requestId: 'req-123',
738
- * path: '/api/users',
739
- * method: 'GET'
740
- * })
741
- * );
742
- *
743
- * // Performance context
744
- * interface PerfContext {
745
- * duration: number;
746
- * memoryUsage: number;
747
- * }
748
- *
749
- * new LogEvent<PerfContext>(
750
- * 'debug',
751
- * ['Operation completed'],
752
- * 'perf',
753
- * new LogContext({
754
- * duration: 150,
755
- * memoryUsage: process.memoryUsage().heapUsed
756
- * })
757
- * );
758
- * ```
759
- */
760
- context?: Ctx | undefined;
761
- /**
762
- * Timestamp when the log event was created
763
- *
764
- * Automatically set to the current time in milliseconds since the Unix epoch
765
- * when the event is constructed. This ensures accurate timing information
766
- * for each log entry.
767
- *
768
- * @example
769
- * ```typescript
770
- * const event = new LogEvent('info', ['message'], 'app');
771
- * console.log(new Date(event.timestamp).toISOString());
772
- * // Output: "2024-03-21T14:30:45.123Z"
773
- * ```
774
- */
775
- timestamp: number;
776
- constructor(
777
- /**
778
- * Log level indicating the severity or importance
779
- *
780
- * Common values:
781
- * - 'fatal': System is unusable
782
- * - 'error': Error conditions
783
- * - 'warn': Warning conditions
784
- * - 'info': Informational messages
785
- * - 'debug': Debug-level messages
786
- * - 'trace': Trace-level messages
787
- *
788
- * @example
789
- * ```typescript
790
- * new LogEvent('error', ['Database connection failed'], 'db');
791
- * ```
792
- */
793
- level: string,
794
- /**
795
- * Array of log message arguments
796
- *
797
- * The first argument is typically the main message string,
798
- * followed by optional data objects, error instances, or
799
- * other relevant information.
800
- *
801
- * @example
802
- * ```typescript
803
- * // Simple message
804
- * new LogEvent('info', ['User logged in'], 'auth');
805
- *
806
- * // Message with data
807
- * new LogEvent('info', [
808
- * 'User logged in',
809
- * { userId: 123, role: 'admin' }
810
- * ], 'auth');
811
- *
812
- * // Error with details
813
- * new LogEvent('error', [
814
- * 'Operation failed',
815
- * new Error('Invalid input'),
816
- * { operation: 'validate', input: data }
817
- * ], 'validator');
818
- * ```
819
- */
820
- args: unknown[],
821
- /**
822
- * Name of the logger that created this event
823
- *
824
- * Used to identify the source or category of the log event.
825
- * This can be a module name, service name, or any other
826
- * identifier that helps categorize log events.
827
- *
828
- * @example
829
- * ```typescript
830
- * // Module-based names
831
- * new LogEvent('info', ['Starting'], 'auth.service');
832
- * new LogEvent('debug', ['Cache miss'], 'data.cache');
833
- *
834
- * // Component-based names
835
- * new LogEvent('info', ['Render complete'], 'ui.dashboard');
836
- * new LogEvent('error', ['API error'], 'api.users');
837
- * ```
838
- */
839
- loggerName: string,
840
- /**
841
- * Optional typed context data for the log event
842
- *
843
- * Provides additional structured data that can be used by
844
- * formatters and handlers. The context type is controlled
845
- * by the Ctx type parameter.
846
- *
847
- * @example
848
- * ```typescript
849
- * // Request context
850
- * interface RequestContext {
851
- * requestId: string;
852
- * path: string;
853
- * method: string;
854
- * }
855
- *
856
- * new LogEvent<RequestContext>(
857
- * 'info',
858
- * ['Request received'],
859
- * 'http',
860
- * new LogContext({
861
- * requestId: 'req-123',
862
- * path: '/api/users',
863
- * method: 'GET'
864
- * })
865
- * );
866
- *
867
- * // Performance context
868
- * interface PerfContext {
869
- * duration: number;
870
- * memoryUsage: number;
871
- * }
872
- *
873
- * new LogEvent<PerfContext>(
874
- * 'debug',
875
- * ['Operation completed'],
876
- * 'perf',
877
- * new LogContext({
878
- * duration: 150,
879
- * memoryUsage: process.memoryUsage().heapUsed
880
- * })
881
- * );
882
- * ```
883
- */
884
- context?: Ctx | undefined);
885
- }
886
-
887
- /**
888
- * Interface for log event formatters
889
- *
890
- * Formatters are responsible for converting log events into specific output
891
- * formats. They can transform the event data into strings, objects, or arrays
892
- * suitable for the target output medium.
893
- *
894
- * Core responsibilities:
895
- * - Format log events into desired output format
896
- * - Support type-safe context handling
897
- * - Maintain consistent formatting across log entries
898
- * - Handle different log levels appropriately
899
- *
900
- * @typeParam Ctx - Type of the context value, defaults to unknown
901
- *
902
- * @example Basic string formatter
903
- * ```typescript
904
- * class SimpleFormatter implements FormatterInterface {
905
- * format(event: LogEvent): string[] {
906
- * const timestamp = new Date(event.timestamp).toISOString();
907
- * const level = event.level.toUpperCase();
908
- * const message = event.args.join(' ');
909
- *
910
- * return [`[${timestamp}] ${level}: ${message}`];
911
- * }
912
- * }
913
- * ```
914
- *
915
- * @example JSON formatter
916
- * ```typescript
917
- * class JSONFormatter implements FormatterInterface {
918
- * format(event: LogEvent): string {
919
- * return JSON.stringify({
920
- * timestamp: event.timestamp,
921
- * level: event.level,
922
- * message: event.args[0],
923
- * data: event.args.slice(1),
924
- * context: event.context?.value
925
- * });
926
- * }
927
- * }
928
- * ```
929
- *
930
- * @example Type-safe context formatter
931
- * ```typescript
932
- * interface RequestContext {
933
- * requestId: string;
934
- * userId?: string;
935
- * path: string;
936
- * method: string;
937
- * }
938
- *
939
- * class RequestFormatter implements FormatterInterface<RequestContext> {
940
- * format(event: LogEvent<RequestContext>): string[] {
941
- * const ctx = event.context?.value;
942
- * const prefix = ctx
943
- * ? `[${ctx.method} ${ctx.path}] [${ctx.requestId}]`
944
- * : '';
945
- *
946
- * return [
947
- * prefix,
948
- * event.level.toUpperCase(),
949
- * ...event.args
950
- * ];
951
- * }
952
- * }
953
- * ```
954
- *
955
- * @example Colored console formatter
956
- * ```typescript
957
- * class ColoredFormatter implements FormatterInterface {
958
- * private colors = {
959
- * error: '\x1b[31m', // Red
960
- * warn: '\x1b[33m', // Yellow
961
- * info: '\x1b[36m', // Cyan
962
- * debug: '\x1b[90m', // Gray
963
- * reset: '\x1b[0m' // Reset
964
- * };
965
- *
966
- * format(event: LogEvent): unknown[] {
967
- * const color = this.colors[event.level] || this.colors.reset;
968
- * const timestamp = new Date(event.timestamp).toISOString();
969
- *
970
- * return [
971
- * `${color}[${timestamp}] ${event.level.toUpperCase()}:${this.colors.reset}`,
972
- * ...event.args
973
- * ];
974
- * }
975
- * }
976
- * ```
977
- */
978
- interface FormatterInterface<Ctx = unknown> {
979
- /**
980
- * Formats a log event into the desired output format
981
- *
982
- * This method transforms a log event into a format suitable for output.
983
- * The return value can be:
984
- * - A single value (string, object, etc.)
985
- * - An array of values (for handlers that support multiple arguments)
986
- *
987
- * Implementation considerations:
988
- * - Handle all log levels consistently
989
- * - Process context data appropriately
990
- * - Maintain type safety with generic context
991
- * - Consider performance for high-volume logging
992
- *
993
- * @param event - The log event to format
994
- * @returns Formatted output as a single value or array of values
995
- *
996
- * @example String output
997
- * ```typescript
998
- * format(event: LogEvent): string {
999
- * const { timestamp, level, args } = event;
1000
- * return `[${new Date(timestamp).toISOString()}] ${
1001
- * level.toUpperCase()
1002
- * }: ${args.join(' ')}`;
1003
- * }
1004
- * ```
1005
- *
1006
- * @example Array output for console
1007
- * ```typescript
1008
- * format(event: LogEvent): unknown[] {
1009
- * const prefix = `[${event.level.toUpperCase()}]`;
1010
- * return [prefix, ...event.args];
1011
- * }
1012
- * ```
1013
- *
1014
- * @example Structured output
1015
- * ```typescript
1016
- * format(event: LogEvent): object {
1017
- * return {
1018
- * '@timestamp': event.timestamp,
1019
- * level: event.level,
1020
- * message: event.args[0],
1021
- * metadata: {
1022
- * args: event.args.slice(1),
1023
- * context: event.context?.value
1024
- * }
1025
- * };
1026
- * }
1027
- * ```
1028
- *
1029
- * @example Type-safe context handling
1030
- * ```typescript
1031
- * interface UserContext {
1032
- * userId: string;
1033
- * sessionId: string;
1034
- * }
1035
- *
1036
- * format(event: LogEvent<UserContext>): object {
1037
- * const ctx = event.context?.value;
1038
- * return {
1039
- * timestamp: event.timestamp,
1040
- * level: event.level,
1041
- * message: event.args[0],
1042
- * user: ctx ? {
1043
- * id: ctx.userId,
1044
- * session: ctx.sessionId
1045
- * } : undefined
1046
- * };
1047
- * }
1048
- * ```
1049
- */
1050
- format(event: LogEvent<Ctx>): unknown | unknown[];
1051
- }
1052
-
1053
- /**
1054
- * Interface for log event handlers (appenders)
1055
- *
1056
- * Handlers are responsible for processing and outputting log events to
1057
- * various destinations (console, file, network, etc.). They can optionally
1058
- * use formatters to customize the output format.
1059
- *
1060
- * Core responsibilities:
1061
- * - Process log events
1062
- * - Output logs to specific destinations
1063
- * - Support optional formatting
1064
- * - Handle different log levels
1065
- *
1066
- * @example Basic console handler
1067
- * ```typescript
1068
- * class ConsoleHandler implements HandlerInterface {
1069
- * private formatter: FormatterInterface | null = null;
1070
- *
1071
- * append(event: LogEvent): void {
1072
- * const args = this.formatter
1073
- * ? this.formatter.format(event)
1074
- * : event.args;
1075
- *
1076
- * console.log(...args);
1077
- * }
1078
- *
1079
- * setFormatter(formatter: FormatterInterface): void {
1080
- * this.formatter = formatter;
1081
- * }
1082
- * }
1083
- * ```
1084
- *
1085
- * @example File handler with rotation
1086
- * ```typescript
1087
- * class RotatingFileHandler implements HandlerInterface {
1088
- * constructor(
1089
- * private filename: string,
1090
- * private maxSize: number = 10 * 1024 * 1024
1091
- * ) {}
1092
- *
1093
- * append(event: LogEvent): void {
1094
- * const message = this.formatter
1095
- * ? this.formatter.format(event)
1096
- * : event.args.join(' ');
1097
- *
1098
- * if (this.shouldRotate()) {
1099
- * this.rotate();
1100
- * }
1101
- * fs.appendFileSync(this.filename, message + '\n');
1102
- * }
1103
- *
1104
- * setFormatter(formatter: FormatterInterface): void {
1105
- * this.formatter = formatter;
1106
- * }
1107
- *
1108
- * private shouldRotate(): boolean {
1109
- * return fs.statSync(this.filename).size > this.maxSize;
1110
- * }
1111
- *
1112
- * private rotate(): void {
1113
- * const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
1114
- * fs.renameSync(
1115
- * this.filename,
1116
- * `${this.filename}.${timestamp}.backup`
1117
- * );
1118
- * }
1119
- * }
1120
- * ```
1121
- *
1122
- * @example Network handler with buffering
1123
- * ```typescript
1124
- * class NetworkHandler implements HandlerInterface {
1125
- * private buffer: LogEvent[] = [];
1126
- * private timer: NodeJS.Timer | null = null;
1127
- *
1128
- * constructor(
1129
- * private endpoint: string,
1130
- * private batchSize: number = 100,
1131
- * private flushInterval: number = 5000
1132
- * ) {
1133
- * this.startTimer();
1134
- * }
1135
- *
1136
- * append(event: LogEvent): void {
1137
- * this.buffer.push(event);
1138
- * if (this.buffer.length >= this.batchSize) {
1139
- * this.flush();
1140
- * }
1141
- * }
1142
- *
1143
- * setFormatter(formatter: FormatterInterface): void {
1144
- * this.formatter = formatter;
1145
- * }
1146
- *
1147
- * private async flush(): Promise<void> {
1148
- * if (this.buffer.length === 0) return;
1149
- *
1150
- * const events = this.buffer.map(event => ({
1151
- * level: event.level,
1152
- * message: this.formatter
1153
- * ? this.formatter.format(event)
1154
- * : event.args.join(' '),
1155
- * timestamp: event.timestamp
1156
- * }));
1157
- *
1158
- * try {
1159
- * await fetch(this.endpoint, {
1160
- * method: 'POST',
1161
- * body: JSON.stringify(events)
1162
- * });
1163
- * this.buffer = [];
1164
- * } catch (error) {
1165
- * console.error('Failed to send logs:', error);
1166
- * }
1167
- * }
1168
- *
1169
- * private startTimer(): void {
1170
- * this.timer = setInterval(() => this.flush(), this.flushInterval);
1171
- * }
1172
- * }
1173
- * ```
1174
- */
1175
- interface HandlerInterface<Ctx = unknown> {
1176
- /**
1177
- * Processes and outputs a log event
1178
- *
1179
- * This method is called by the logger for each log event that needs
1180
- * to be processed. The handler can format the event using its formatter
1181
- * (if set) and output it to its destination.
1182
- *
1183
- * Implementation considerations:
1184
- * - Handle all log levels appropriately
1185
- * - Apply formatting if a formatter is set
1186
- * - Handle errors gracefully
1187
- * - Consider performance implications
1188
- *
1189
- * @param event - The log event to process and output
1190
- *
1191
- * @example Basic implementation
1192
- * ```typescript
1193
- * append(event: LogEvent): void {
1194
- * const output = this.formatter
1195
- * ? this.formatter.format(event)
1196
- * : event.args;
1197
- *
1198
- * console.log(...output);
1199
- * }
1200
- * ```
1201
- *
1202
- * @example Advanced implementation with error handling
1203
- * ```typescript
1204
- * append(event: LogEvent): void {
1205
- * try {
1206
- * // Format the event
1207
- * const formatted = this.formatter
1208
- * ? this.formatter.format(event)
1209
- * : event.args;
1210
- *
1211
- * // Add timestamp and level
1212
- * const output = [
1213
- * new Date(event.timestamp).toISOString(),
1214
- * event.level.toUpperCase(),
1215
- * ...formatted
1216
- * ];
1217
- *
1218
- * // Write to file
1219
- * fs.appendFileSync(this.filename, output.join(' ') + '\n');
1220
- * } catch (error) {
1221
- * console.error('Failed to append log:', error);
1222
- * // Optionally write to fallback location
1223
- * fs.appendFileSync(
1224
- * 'error.log',
1225
- * `Failed to write log: ${error.message}\n`
1226
- * );
1227
- * }
1228
- * }
1229
- * ```
1230
- *
1231
- * @example Asynchronous implementation
1232
- * ```typescript
1233
- * async append(event: LogEvent): Promise<void> {
1234
- * // Format the event
1235
- * const message = this.formatter
1236
- * ? this.formatter.format(event)
1237
- * : event.args.join(' ');
1238
- *
1239
- * // Prepare log entry
1240
- * const entry = {
1241
- * timestamp: event.timestamp,
1242
- * level: event.level,
1243
- * message,
1244
- * metadata: event.context?.value
1245
- * };
1246
- *
1247
- * try {
1248
- * // Send to logging service
1249
- * await fetch('https://logging.example.com/ingest', {
1250
- * method: 'POST',
1251
- * headers: { 'Content-Type': 'application/json' },
1252
- * body: JSON.stringify(entry)
1253
- * });
1254
- * } catch (error) {
1255
- * // Handle failure
1256
- * console.error('Failed to send log:', error);
1257
- * // Add to retry queue
1258
- * this.retryQueue.push(entry);
1259
- * }
1260
- * }
1261
- * ```
1262
- */
1263
- append(event: LogEvent<Ctx>): void;
1264
- /**
1265
- * Sets or updates the formatter for this handler
1266
- *
1267
- * The formatter is responsible for converting log events into
1268
- * the desired output format. This method allows changing the
1269
- * formatter at runtime.
1270
- *
1271
- * Implementation considerations:
1272
- * - Handle null formatters gracefully
1273
- * - Consider thread safety in async environments
1274
- * - Clean up old formatter resources if necessary
1275
- *
1276
- * @param formatter - The formatter instance to use
1277
- *
1278
- * @example Basic implementation
1279
- * ```typescript
1280
- * setFormatter(formatter: FormatterInterface): void {
1281
- * this.formatter = formatter;
1282
- * }
1283
- * ```
1284
- *
1285
- * @example Implementation with cleanup
1286
- * ```typescript
1287
- * setFormatter(formatter: FormatterInterface): void {
1288
- * if (this.formatter && 'dispose' in this.formatter) {
1289
- * // Clean up old formatter resources
1290
- * this.formatter.dispose();
1291
- * }
1292
- * this.formatter = formatter;
1293
- * }
1294
- * ```
1295
- *
1296
- * @example Thread-safe implementation
1297
- * ```typescript
1298
- * setFormatter(formatter: FormatterInterface): void {
1299
- * // Ensure atomic formatter update
1300
- * this.lock.acquire();
1301
- * try {
1302
- * const oldFormatter = this.formatter;
1303
- * this.formatter = formatter;
1304
- *
1305
- * // Flush any pending logs with old formatter
1306
- * if (oldFormatter) {
1307
- * this.flushBuffer(oldFormatter);
1308
- * }
1309
- * } finally {
1310
- * this.lock.release();
1311
- * }
1312
- * }
1313
- * ```
1314
- */
1315
- setFormatter(formatter: FormatterInterface): void;
1316
- }
1317
-
1318
- /**
1319
- * Type-safe container for log event context data
1320
- *
1321
- * This class provides a generic wrapper for additional context data
1322
- * that can be attached to log events. It ensures type safety through
1323
- * its generic type parameter and provides a consistent structure for
1324
- * context handling.
1325
- *
1326
- * Core features:
1327
- * - Generic type support
1328
- * - Optional value handling
1329
- * - Immutable context data
1330
- * - Type-safe access
1331
- *
1332
- * @typeParam Value - Type of the context value
1333
- *
1334
- * @example Basic usage
1335
- * ```typescript
1336
- * // Simple context
1337
- * const context = new LogContext({ userId: 123 });
1338
- * logger.info('User action', context);
1339
- * ```
1340
- *
1341
- * @example Type-safe context
1342
- * ```typescript
1343
- * interface RequestContext {
1344
- * requestId: string;
1345
- * path: string;
1346
- * method: string;
1347
- * userId?: string;
1348
- * }
1349
- *
1350
- * const context = new LogContext<RequestContext>({
1351
- * requestId: 'req-123',
1352
- * path: '/api/users',
1353
- * method: 'GET'
1354
- * });
1355
- *
1356
- * logger.info('Request received', context);
1357
- * ```
1358
- *
1359
- * @example Optional context
1360
- * ```typescript
1361
- * // Empty context
1362
- * const emptyContext = new LogContext();
1363
- *
1364
- * // Context with undefined value
1365
- * const context = new LogContext<string | undefined>(undefined);
1366
- *
1367
- * // Context with null value
1368
- * const nullContext = new LogContext<string | null>(null);
1369
- * ```
1370
- *
1371
- * @example Complex context
1372
- * ```typescript
1373
- * interface PerformanceContext {
1374
- * operation: string;
1375
- * metrics: {
1376
- * duration: number;
1377
- * memory: {
1378
- * before: number;
1379
- * after: number;
1380
- * };
1381
- * cpu: {
1382
- * user: number;
1383
- * system: number;
1384
- * };
1385
- * };
1386
- * metadata: Record<string, unknown>;
1387
- * }
1388
- *
1389
- * const context = new LogContext<PerformanceContext>({
1390
- * operation: 'data-processing',
1391
- * metrics: {
1392
- * duration: 1500,
1393
- * memory: {
1394
- * before: 100000,
1395
- * after: 150000
1396
- * },
1397
- * cpu: {
1398
- * user: 80,
1399
- * system: 20
1400
- * }
1401
- * },
1402
- * metadata: {
1403
- * batchSize: 1000,
1404
- * compression: true,
1405
- * priority: 'high'
1406
- * }
1407
- * });
1408
- *
1409
- * logger.debug('Operation metrics', context);
1410
- * ```
1411
- *
1412
- * @example Context in formatters
1413
- * ```typescript
1414
- * class DetailedFormatter implements FormatterInterface<RequestContext> {
1415
- * format(event: LogEvent<RequestContext>): string[] {
1416
- * const ctx = event.context?.value;
1417
- * if (ctx) {
1418
- * return [
1419
- * `[${ctx.method} ${ctx.path}]`,
1420
- * `[${ctx.requestId}]`,
1421
- * ...event.args
1422
- * ];
1423
- * }
1424
- * return event.args;
1425
- * }
1426
- * }
1427
- * ```
1428
- */
1429
- declare class LogContext<Value> {
1430
- /**
1431
- * The context value that will be attached to log events
1432
- *
1433
- * This value is typed according to the Value type parameter
1434
- * and can be accessed safely through optional chaining.
1435
- */
1436
- value?: Value | undefined;
1437
- /**
1438
- * Creates a new LogContext instance
1439
- *
1440
- * @param value - Optional context value of type Value
1441
- *
1442
- * The value parameter is marked as optional to support:
1443
- * - Empty contexts (no value provided)
1444
- * - Explicitly undefined values
1445
- * - Nullable types (Value | null)
1446
- *
1447
- * The value is stored as a public property to allow:
1448
- * - Direct access in formatters and handlers
1449
- * - Type-safe value extraction
1450
- * - Optional chaining support
1451
- *
1452
- * @example Basic construction
1453
- * ```typescript
1454
- * // With value
1455
- * const context = new LogContext({ userId: 123 });
1456
- * console.log(context.value?.userId); // 123
1457
- *
1458
- * // Empty context
1459
- * const empty = new LogContext();
1460
- * console.log(empty.value); // undefined
1461
- * ```
1462
- *
1463
- * @example Type-safe construction
1464
- * ```typescript
1465
- * interface UserContext {
1466
- * id: number;
1467
- * name: string;
1468
- * role?: string;
1469
- * }
1470
- *
1471
- * const context = new LogContext<UserContext>({
1472
- * id: 123,
1473
- * name: 'John',
1474
- * role: 'admin' // Optional property
1475
- * });
1476
- *
1477
- * // Type-safe access
1478
- * const userId = context.value?.id; // number | undefined
1479
- * const role = context.value?.role; // string | undefined
1480
- * ```
1481
- *
1482
- * @example Nullable context
1483
- * ```typescript
1484
- * type NullableContext = {
1485
- * sessionId: string;
1486
- * } | null;
1487
- *
1488
- * // With value
1489
- * const active = new LogContext<NullableContext>({
1490
- * sessionId: 'sess-123'
1491
- * });
1492
- *
1493
- * // With null
1494
- * const inactive = new LogContext<NullableContext>(null);
1495
- *
1496
- * // Type-safe null handling
1497
- * console.log(active.value?.sessionId); // 'sess-123'
1498
- * console.log(inactive.value?.sessionId); // undefined
1499
- * ```
1500
- *
1501
- * @example Context in logging
1502
- * ```typescript
1503
- * interface RequestContext {
1504
- * path: string;
1505
- * method: string;
1506
- * duration: number;
1507
- * }
1508
- *
1509
- * const context = new LogContext<RequestContext>({
1510
- * path: '/api/users',
1511
- * method: 'GET',
1512
- * duration: 150
1513
- * });
1514
- *
1515
- * // Using context in log messages
1516
- * logger.info('Request completed', context);
1517
- *
1518
- * // Accessing context in formatters
1519
- * class RequestFormatter implements FormatterInterface<RequestContext> {
1520
- * format(event: LogEvent<RequestContext>): string[] {
1521
- * const ctx = event.context?.value;
1522
- * return [
1523
- * ctx ? `${ctx.method} ${ctx.path} (${ctx.duration}ms)` : 'Unknown',
1524
- * ...event.args
1525
- * ];
1526
- * }
1527
- * }
1528
- * ```
1529
- */
1530
- constructor(
1531
- /**
1532
- * The context value that will be attached to log events
1533
- *
1534
- * This value is typed according to the Value type parameter
1535
- * and can be accessed safely through optional chaining.
1536
- */
1537
- value?: Value | undefined);
1538
- }
1539
-
1540
- /**
1541
- * Core interface for logger implementations
1542
- *
1543
- * This interface defines the standard contract for logger implementations,
1544
- * providing methods for different log levels, handler management, and
1545
- * context creation.
1546
- *
1547
- * Core functionality:
1548
- * - Standard log level methods (fatal, error, warn, info, debug, trace)
1549
- * - Handler (appender) management
1550
- * - Context creation for structured logging
1551
- * - Type-safe logging with generic context support
1552
- *
1553
- * @example Basic usage
1554
- * ```typescript
1555
- * class MyLogger implements LoggerInterface {
1556
- * info(...args: unknown[]): void {
1557
- * console.log('[INFO]', ...args);
1558
- * }
1559
- * // ... implement other methods
1560
- * }
1561
- *
1562
- * const logger = new MyLogger();
1563
- * logger.info('Application started');
1564
- * ```
1565
- *
1566
- * @example With handlers and context
1567
- * ```typescript
1568
- * class AdvancedLogger implements LoggerInterface {
1569
- * private handlers: HandlerInterface[] = [];
1570
- *
1571
- * addAppender(handler: HandlerInterface): void {
1572
- * this.handlers.push(handler);
1573
- * }
1574
- *
1575
- * info(...args: unknown[]): void {
1576
- * const event = {
1577
- * level: 'info',
1578
- * args,
1579
- * timestamp: Date.now()
1580
- * };
1581
- *
1582
- * this.handlers.forEach(handler => handler.append(event));
1583
- * }
1584
- *
1585
- * context<T>(value?: T): LogContext<T> {
1586
- * return new LogContext(value);
1587
- * }
1588
- * // ... implement other methods
1589
- * }
1590
- *
1591
- * const logger = new AdvancedLogger();
1592
- * logger.addAppender(new ConsoleHandler());
1593
- * logger.info('User logged in', logger.context({ userId: 123 }));
1594
- * ```
1595
- *
1596
- * @example Type-safe context usage
1597
- * ```typescript
1598
- * interface UserContext {
1599
- * userId: number;
1600
- * username: string;
1601
- * role: string;
1602
- * }
1603
- *
1604
- * const logger: LoggerInterface = new Logger();
1605
- *
1606
- * // Type-safe context
1607
- * logger.info('User action', logger.context<UserContext>({
1608
- * userId: 123,
1609
- * username: 'john_doe',
1610
- * role: 'admin'
1611
- * }));
1612
- * ```
1613
- */
1614
- interface LoggerInterface<Ctx = unknown> {
1615
- /**
1616
- * General purpose logging method (alias for info)
1617
- *
1618
- * @param args - Message content followed by optional context
1619
- *
1620
- * @example
1621
- * ```typescript
1622
- * logger.log('Application started');
1623
- * logger.log('User action', { userId: 123 });
1624
- * logger.log('Process completed', logger.context({ duration: 1500 }));
1625
- * ```
1626
- */
1627
- log(...args: unknown[]): void;
1628
- /**
1629
- * Logs a critical error that causes application termination
1630
- *
1631
- * Use for severe errors that:
1632
- * - Cause immediate application shutdown
1633
- * - Require immediate administrator attention
1634
- * - Indicate system is unusable
1635
- *
1636
- * @param args - Message content followed by optional context
1637
- *
1638
- * @example
1639
- * ```typescript
1640
- * logger.fatal('Database connection permanently lost');
1641
- * logger.fatal('Out of memory', { memoryUsage: process.memoryUsage() });
1642
- * logger.fatal('System crash', logger.context({
1643
- * error: new Error('Unrecoverable error'),
1644
- * state: 'corrupted'
1645
- * }));
1646
- * ```
1647
- */
1648
- fatal(...args: unknown[]): void;
1649
- /**
1650
- * Logs an error condition that doesn't cause termination
1651
- *
1652
- * Use for errors that:
1653
- * - Prevent normal operation but allow recovery
1654
- * - Require administrator attention
1655
- * - Need to be tracked for troubleshooting
1656
- *
1657
- * @param args - Message content followed by optional context
1658
- *
1659
- * @example
1660
- * ```typescript
1661
- * logger.error('Failed to process payment');
1662
- * logger.error('API request failed', { status: 500, path: '/api/users' });
1663
- * logger.error('Database query error', logger.context({
1664
- * query: 'SELECT * FROM users',
1665
- * error: new Error('Connection timeout')
1666
- * }));
1667
- * ```
1668
- */
1669
- error(...args: unknown[]): void;
1670
- /**
1671
- * Logs a warning condition that might cause issues
1672
- *
1673
- * Use for situations that:
1674
- * - Are unusual but not errors
1675
- * - Might cause problems in the future
1676
- * - Indicate deprecated feature usage
1677
- *
1678
- * @param args - Message content followed by optional context
1679
- *
1680
- * @example
1681
- * ```typescript
1682
- * logger.warn('High memory usage detected');
1683
- * logger.warn('Deprecated API used', { api: 'oldMethod', alternative: 'newMethod' });
1684
- * logger.warn('Cache miss rate high', logger.context({
1685
- * rate: '85%',
1686
- * threshold: '75%'
1687
- * }));
1688
- * ```
1689
- */
1690
- warn(...args: unknown[]): void;
1691
- /**
1692
- * Logs normal but significant events
1693
- *
1694
- * Use for events that:
1695
- * - Mark major application state changes
1696
- * - Track business process completion
1697
- * - Record user actions
1698
- *
1699
- * @param args - Message content followed by optional context
1700
- *
1701
- * @example
1702
- * ```typescript
1703
- * logger.info('Application started on port 3000');
1704
- * logger.info('User logged in', { userId: 123, role: 'admin' });
1705
- * logger.info('Order processed', logger.context({
1706
- * orderId: 'ORD-123',
1707
- * amount: 99.99,
1708
- * currency: 'USD'
1709
- * }));
1710
- * ```
1711
- */
1712
- info(...args: unknown[]): void;
1713
- /**
1714
- * Logs detailed information for debugging
1715
- *
1716
- * Use for information that:
1717
- * - Helps diagnose problems
1718
- * - Shows detailed flow of execution
1719
- * - Exposes internal state
1720
- *
1721
- * @param args - Message content followed by optional context
1722
- *
1723
- * @example
1724
- * ```typescript
1725
- * logger.debug('Processing request payload');
1726
- * logger.debug('Cache state', { size: 1024, entries: 50 });
1727
- * logger.debug('Query execution plan', logger.context({
1728
- * sql: 'SELECT * FROM users WHERE role = ?',
1729
- * params: ['admin'],
1730
- * executionTime: 150
1731
- * }));
1732
- * ```
1733
- */
1734
- debug(...args: unknown[]): void;
1735
- /**
1736
- * Logs the most detailed level of information
1737
- *
1738
- * Use for information that:
1739
- * - Shows step-by-step execution flow
1740
- * - Includes method entry/exit points
1741
- * - Contains variable state changes
1742
- *
1743
- * @param args - Message content followed by optional context
1744
- *
1745
- * @example
1746
- * ```typescript
1747
- * logger.trace('Entering method processUser');
1748
- * logger.trace('Variable state', { counter: 5, buffer: [1,2,3] });
1749
- * logger.trace('Method execution', logger.context({
1750
- * method: 'processUser',
1751
- * args: { id: 123 },
1752
- * stack: new Error().stack
1753
- * }));
1754
- * ```
1755
- */
1756
- trace(...args: unknown[]): void;
1757
- /**
1758
- * Adds a new handler (appender) to the logger
1759
- *
1760
- * Handlers are responsible for processing and outputting log events.
1761
- * Multiple handlers can be added to send logs to different destinations
1762
- * or format them differently.
1763
- *
1764
- * @param appender - The handler instance to add
1765
- *
1766
- * @example Basic console handler
1767
- * ```typescript
1768
- * const logger = new Logger();
1769
- * logger.addAppender(new ConsoleHandler());
1770
- * ```
1771
- *
1772
- * @example Multiple handlers
1773
- * ```typescript
1774
- * const logger = new Logger();
1775
- *
1776
- * // Console output for development
1777
- * logger.addAppender(new ConsoleHandler(
1778
- * new TimestampFormatter({ locale: 'en-US' })
1779
- * ));
1780
- *
1781
- * // File output for errors
1782
- * logger.addAppender(new FileHandler('./logs/errors.log', {
1783
- * level: 'error',
1784
- * formatter: new JSONFormatter()
1785
- * }));
1786
- *
1787
- * // Metrics collection
1788
- * logger.addAppender(new MetricsHandler({
1789
- * service: 'user-api',
1790
- * endpoint: 'https://metrics.example.com'
1791
- * }));
1792
- * ```
1793
- *
1794
- * @example Conditional handlers
1795
- * ```typescript
1796
- * const logger = new Logger();
1797
- *
1798
- * // Development handlers
1799
- * if (process.env.NODE_ENV === 'development') {
1800
- * logger.addAppender(new ConsoleHandler(
1801
- * new PrettyFormatter({ colors: true })
1802
- * ));
1803
- * logger.addAppender(new FileHandler('./logs/dev.log'));
1804
- * }
1805
- *
1806
- * // Production handlers
1807
- * if (process.env.NODE_ENV === 'production') {
1808
- * logger.addAppender(new CloudWatchHandler({
1809
- * region: 'us-east-1',
1810
- * logGroupName: '/aws/api'
1811
- * }));
1812
- * logger.addAppender(new AlertHandler({
1813
- * level: 'error',
1814
- * webhook: 'https://alerts.example.com'
1815
- * }));
1816
- * }
1817
- * ```
1818
- */
1819
- addAppender(appender: HandlerInterface<Ctx>): void;
1820
- /**
1821
- * Creates a new LogContext instance for structured logging
1822
- *
1823
- * Context objects allow adding structured data to log messages
1824
- * in a type-safe way. They can be used to add metadata,
1825
- * performance metrics, error details, or any other relevant
1826
- * information to log entries.
1827
- *
1828
- * @since 0.1.0
1829
- * @param value - Optional value to be stored in the context
1830
- * @returns A new LogContext instance with the provided value
1831
- *
1832
- * @example Basic context usage
1833
- * ```typescript
1834
- * logger.info('User logged in', logger.context({
1835
- * userId: 123,
1836
- * role: 'admin',
1837
- * loginTime: new Date()
1838
- * }));
1839
- * ```
1840
- *
1841
- * @example Type-safe context
1842
- * ```typescript
1843
- * interface RequestContext {
1844
- * method: string;
1845
- * path: string;
1846
- * duration: number;
1847
- * statusCode: number;
1848
- * }
1849
- *
1850
- * logger.info('Request completed', logger.context<RequestContext>({
1851
- * method: 'GET',
1852
- * path: '/api/users',
1853
- * duration: 150,
1854
- * statusCode: 200
1855
- * }));
1856
- * ```
1857
- *
1858
- * @example Error context
1859
- * ```typescript
1860
- * try {
1861
- * await processOrder(orderId);
1862
- * } catch (error) {
1863
- * logger.error('Order processing failed', logger.context({
1864
- * orderId,
1865
- * error: error instanceof Error ? error.message : String(error),
1866
- * stack: error instanceof Error ? error.stack : undefined
1867
- * }));
1868
- * }
1869
- * ```
1870
- *
1871
- * @example Performance monitoring
1872
- * ```typescript
1873
- * const startTime = Date.now();
1874
- * try {
1875
- * const result = await heavyOperation();
1876
- * logger.info('Operation completed', logger.context({
1877
- * duration: Date.now() - startTime,
1878
- * resultSize: result.length,
1879
- * memoryUsage: process.memoryUsage()
1880
- * }));
1881
- * } catch (error) {
1882
- * logger.error('Operation failed', logger.context({
1883
- * duration: Date.now() - startTime,
1884
- * error,
1885
- * memoryUsage: process.memoryUsage()
1886
- * }));
1887
- * }
1888
- * ```
45
+ * @default ['.env.local', '.env']
1889
46
  */
1890
- context<Value>(value?: Value): LogContext<Value>;
47
+ envOrder?: string[];
1891
48
  }
1892
49
 
1893
50
  /**
@@ -2784,7 +941,7 @@ interface ShellConfig extends ShellExecOptions {
2784
941
  *
2785
942
  * Main features:
2786
943
  * - Template formatting: Dynamic command generation with context
2787
- * - Uses lodash template for string interpolation
944
+ * - Uses TemplateEngine for string interpolation
2788
945
  * - Supports complex template expressions
2789
946
  * - Provides error handling for template failures
2790
947
  * - Enables dynamic command construction
@@ -2833,7 +990,7 @@ interface ShellConfig extends ShellExecOptions {
2833
990
  * @example With template formatting
2834
991
  * ```typescript
2835
992
  * const shell = new Shell({ logger: myLogger });
2836
- * const output = await shell.exec('git clone <%= repo %>', {
993
+ * const output = await shell.exec('git clone ${repo}', {
2837
994
  * context: { repo: 'https://github.com/user/repo.git' }
2838
995
  * });
2839
996
  * ```
@@ -2859,6 +1016,7 @@ interface ShellConfig extends ShellExecOptions {
2859
1016
  declare class Shell implements ShellInterface {
2860
1017
  config: ShellConfig;
2861
1018
  private cache;
1019
+ private static readonly templateEngine;
2862
1020
  /**
2863
1021
  * Creates a new Shell instance with the specified configuration
2864
1022
  *
@@ -2926,59 +1084,30 @@ declare class Shell implements ShellInterface {
2926
1084
  */
2927
1085
  get logger(): LoggerInterface;
2928
1086
  /**
2929
- * Formats a template string with context using lodash template
2930
- *
2931
- * Core concept:
2932
- * Provides static template formatting functionality using
2933
- * lodash template for string interpolation with context data.
2934
- *
2935
- * Template features:
2936
- * - Uses lodash template for powerful string interpolation
2937
- * - Supports complex template expressions and logic
2938
- * - Handles undefined and null context values gracefully
2939
- * - Returns formatted string with context values substituted
2940
- *
2941
- * Template syntax:
2942
- * - `<%= variable %>` for escaped output
2943
- * - `<%- variable %>` for unescaped output
2944
- * - `<% code %>` for JavaScript code execution
2945
- * - Supports nested object access and function calls
1087
+ * Formats a template string with context using {@link TemplateEngine}.
2946
1088
  *
2947
- * Context handling:
2948
- * - Accepts any object with string/number/boolean values
2949
- * - Handles undefined and null values safely
2950
- * - Supports nested object property access
2951
- * - Provides fallback for missing context values
1089
+ * Uses ES6-style `${ path }` placeholders via {@link TemplateEngine}.
2952
1090
  *
2953
1091
  * @param template - Template string with interpolation placeholders
2954
1092
  * @param context - Context object for template variable substitution
2955
1093
  * @returns Formatted string with context values substituted
2956
1094
  *
2957
- * @example Basic template formatting
1095
+ * @example Basic formatting
2958
1096
  * ```typescript
2959
- * const result = Shell.format('Hello <%= name %>!', { name: 'World' });
1097
+ * const result = Shell.format('Hello ${name}!', { name: 'World' });
2960
1098
  * // Returns: 'Hello World!'
2961
1099
  * ```
2962
1100
  *
2963
1101
  * @example Complex template with nested objects
2964
1102
  * ```typescript
2965
1103
  * const result = Shell.format(
2966
- * 'git clone <%= repo.url %> <%= repo.branch %>',
1104
+ * 'git clone ${repo.url} ${repo.branch}',
2967
1105
  * { repo: { url: 'https://github.com/user/repo.git', branch: 'main' } }
2968
1106
  * );
2969
1107
  * // Returns: 'git clone https://github.com/user/repo.git main'
2970
1108
  * ```
2971
- *
2972
- * @example Template with conditional logic
2973
- * ```typescript
2974
- * const result = Shell.format(
2975
- * 'npm install<% if (dev) { %> --save-dev<% } %>',
2976
- * { dev: true }
2977
- * );
2978
- * // Returns: 'npm install --save-dev'
2979
- * ```
2980
1109
  */
2981
- static format(template?: string, context?: Record<string, unknown>): string;
1110
+ static format(template?: string, context?: Record<string, any>): string;
2982
1111
  /**
2983
1112
  * Formats a template string with context and comprehensive error handling
2984
1113
  *
@@ -3012,14 +1141,14 @@ declare class Shell implements ShellInterface {
3012
1141
  *
3013
1142
  * @example Basic formatting
3014
1143
  * ```typescript
3015
- * const result = shell.format('Hello <%= name %>!', { name: 'World' });
1144
+ * const result = shell.format('Hello ${name}!', { name: 'World' });
3016
1145
  * // Returns: 'Hello World!'
3017
1146
  * ```
3018
1147
  *
3019
1148
  * @example Error handling
3020
1149
  * ```typescript
3021
1150
  * try {
3022
- * const result = shell.format('Hello <%= name %>!', {});
1151
+ * const result = shell.format('Hello ${name}!', {});
3023
1152
  * } catch (error) {
3024
1153
  * // Error is logged with template and context information
3025
1154
  * console.error('Template formatting failed:', error.message);
@@ -3061,7 +1190,7 @@ declare class Shell implements ShellInterface {
3061
1190
  *
3062
1191
  * @example String command with template
3063
1192
  * ```typescript
3064
- * const output = await shell.exec('git clone <%= repo %>', {
1193
+ * const output = await shell.exec('git clone ${repo}', {
3065
1194
  * context: { repo: 'https://github.com/user/repo.git' }
3066
1195
  * });
3067
1196
  * ```
@@ -4321,6 +2450,25 @@ declare class ScriptContext<Opt extends ScriptSharedInterface> extends ExecutorC
4321
2450
  * detailed information display.
4322
2451
  */
4323
2452
  readonly verbose: boolean;
2453
+ /**
2454
+ * 该属性只是一个 parameters 的别名
2455
+ *
2456
+ * 当你需要设置最新的参数时可以直接使用 setParameters 方法
2457
+ *
2458
+ * @override
2459
+ * @example
2460
+ * ```ts
2461
+ * context.setParameters({
2462
+ * target: 'production'
2463
+ * });
2464
+ *
2465
+ * console.log(context.options);
2466
+ * // { target: 'production' }
2467
+ * console.log(context.parameters);
2468
+ * // { target: 'production' }
2469
+ * ```
2470
+ */
2471
+ get options(): Opt;
4324
2472
  /**
4325
2473
  * Creates a new ScriptContext instance with the specified configuration
4326
2474
  *
@@ -4368,10 +2516,6 @@ declare class ScriptContext<Opt extends ScriptSharedInterface> extends ExecutorC
4368
2516
  * ```
4369
2517
  */
4370
2518
  constructor(name: string, opts?: Partial<ScriptContextInterface<Opt>>);
4371
- /**
4372
- * @override
4373
- */
4374
- get options(): Opt;
4375
2519
  /**
4376
2520
  * Environment instance for variable access and management
4377
2521
  *
@@ -4457,8 +2601,9 @@ declare class ScriptContext<Opt extends ScriptSharedInterface> extends ExecutorC
4457
2601
  * });
4458
2602
  * // Merges nested build configuration
4459
2603
  * ```
2604
+ *
4460
2605
  */
4461
- setOptions(options: Partial<Opt>): void;
2606
+ setParameters(params: Partial<Opt>): void;
4462
2607
  /**
4463
2608
  * Retrieves environment variable with optional default value
4464
2609
  *
@@ -4558,7 +2703,7 @@ declare class ScriptContext<Opt extends ScriptSharedInterface> extends ExecutorC
4558
2703
  * // Returns the complete options object
4559
2704
  * ```
4560
2705
  */
4561
- getOptions<T = unknown>(key?: string | string[], defaultValue?: T): T;
2706
+ getParameters<T = unknown>(key?: string | string[], defaultValue?: T): T;
4562
2707
  }
4563
2708
 
4564
2709
  /**
@@ -4796,7 +2941,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
4796
2941
  * }
4797
2942
  * ```
4798
2943
  */
4799
- get options(): Props;
2944
+ get config(): Props;
4800
2945
  /**
4801
2946
  * Determines whether a lifecycle method should be executed
4802
2947
  *
@@ -4822,7 +2967,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
4822
2967
  * plugin.enabled('onExec', context); // Returns true
4823
2968
  * ```
4824
2969
  */
4825
- enabled(_name: string, _context: Context): boolean;
2970
+ enabled(name: string, _context: Context): boolean;
4826
2971
  /**
4827
2972
  * Retrieves configuration values with nested path support
4828
2973
  *
@@ -4854,7 +2999,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
4854
2999
  * const plugins = this.getConfig<string[]>('plugins', []);
4855
3000
  * ```
4856
3001
  */
4857
- getConfig<T>(keys?: string | string[], defaultValue?: T): T;
3002
+ getConfig<T>(keys?: keyof Props | string | Array<keyof Props | string>, defaultValue?: T): T;
4858
3003
  /**
4859
3004
  * Updates plugin configuration with deep merging
4860
3005
  *
@@ -4950,7 +3095,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
4950
3095
  * }
4951
3096
  * ```
4952
3097
  */
4953
- onExec?(_context: Context): void | Promise<void>;
3098
+ onExec?(context: Context): void | Promise<void>;
4954
3099
  /**
4955
3100
  * Lifecycle method called after successful script execution
4956
3101
  *
@@ -4981,7 +3126,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
4981
3126
  * }
4982
3127
  * ```
4983
3128
  */
4984
- onSuccess?(_context: Context): void | Promise<void>;
3129
+ onSuccess?(context: Context): void | Promise<void>;
4985
3130
  /**
4986
3131
  * Lifecycle method called when script execution fails
4987
3132
  *
@@ -5014,7 +3159,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
5014
3159
  * }
5015
3160
  * ```
5016
3161
  */
5017
- onError?(_context: Context): Promise<ExecutorError | void> | ExecutorError | Error | void;
3162
+ onError?(context: Context): Promise<ExecutorError | void> | ExecutorError | Error | void;
5018
3163
  /**
5019
3164
  * Lifecycle method called after script execution
5020
3165
  *
@@ -5096,6 +3241,159 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
5096
3241
  * ```
5097
3242
  */
5098
3243
  step<T>(options: StepOption<T>): Promise<T>;
3244
+ /**
3245
+ * Builds the shared step log prefix (plugin context + dry-run)
3246
+ */
3247
+ protected createStepLabel(label: string): string;
3248
+ }
3249
+
3250
+ /**
3251
+ * @module TemplateEngine
3252
+ * @description Lightweight, safe template engine for variable interpolation.
3253
+ *
3254
+ * Supports path-based value lookup (e.g. `user.name`, `items[0].id`) without
3255
+ * executing arbitrary JavaScript. Designed as a drop-in replacement for
3256
+ * simple `lodash.template` use cases in scripts and configuration formatting.
3257
+ *
3258
+ * Default syntax: ES6 template-literal `${ path }`.
3259
+ *
3260
+ * @example Basic usage
3261
+ * ```typescript
3262
+ * const engine = new TemplateEngine();
3263
+ * engine.render('Hello ${user.name}!', { user: { name: 'Alice' } });
3264
+ * // => 'Hello Alice!'
3265
+ * ```
3266
+ *
3267
+ * @example Reusable compiled renderer
3268
+ * ```typescript
3269
+ * const render = engine.compile('git clone ${repo.url}');
3270
+ * render({ repo: { url: 'https://github.com/user/repo.git' } });
3271
+ * ```
3272
+ */
3273
+ /**
3274
+ * Template engine configuration options.
3275
+ */
3276
+ interface TemplateOptions {
3277
+ /**
3278
+ * Interpolation regex with exactly one capture group for the variable path.
3279
+ * Defaults to {@link interpolatePreset.ES6}.
3280
+ */
3281
+ interpolate?: RegExp;
3282
+ /**
3283
+ * Required path prefix in templates (lodash `variable` option semantics).
3284
+ * e.g. `variable: 'data'` → use `${data.user.name}` with `{ user: { name } }`.
3285
+ */
3286
+ variable?: string;
3287
+ /** Default when value is missing (undefined/null) or path is invalid. */
3288
+ defaultValue?: unknown | ((path: string, data: Record<string, unknown>) => unknown);
3289
+ /** Escape HTML entities in output. Default false. */
3290
+ escapeHtml?: boolean;
3291
+ /** Serialize objects via JSON.stringify. Default true. */
3292
+ stringifyObject?: boolean;
3293
+ /** Keep original placeholder when value is missing. Default false. */
3294
+ keepUnmatched?: boolean;
3295
+ /** Block prototype keys and only read own properties. Default true. */
3296
+ safePrototype?: boolean;
3297
+ }
3298
+ /** Compiled render function returned by {@link TemplateEngine.compile}. */
3299
+ type RenderFn = (data: Record<string, unknown>) => string;
3300
+ /**
3301
+ * Built-in interpolation regex presets.
3302
+ *
3303
+ * Pass one of these to `new TemplateEngine({ interpolate })` when you need
3304
+ * a syntax other than the default ES6-style delimiters.
3305
+ *
3306
+ * @example ES6 (default — no extra config needed)
3307
+ * ```typescript
3308
+ * new TemplateEngine().render('Hello ${name}!', { name: 'World' });
3309
+ * ```
3310
+ *
3311
+ * @example Lodash / EJS style
3312
+ * ```typescript
3313
+ * new TemplateEngine({ interpolate: interpolatePreset.LODASH })
3314
+ * .render('Hello <%= name %>!', { name: 'World' });
3315
+ * ```
3316
+ *
3317
+ * @example Mustache style
3318
+ * ```typescript
3319
+ * new TemplateEngine({ interpolate: interpolatePreset.MUSTACHE })
3320
+ * .render('Hello {{ name }}!', { name: 'World' });
3321
+ * ```
3322
+ */
3323
+ declare const interpolatePreset: {
3324
+ /**
3325
+ * ES6 template-literal style: `${ variable }`
3326
+ *
3327
+ * This is the default for {@link TemplateEngine}.
3328
+ *
3329
+ * @example
3330
+ * ```typescript
3331
+ * engine.render('${user.name}', { user: { name: 'Bob' } });
3332
+ * ```
3333
+ */
3334
+ readonly ES6: RegExp;
3335
+ /**
3336
+ * Lodash / EJS style: `<%= variable %>`
3337
+ *
3338
+ * Useful when migrating existing lodash templates.
3339
+ *
3340
+ * @example
3341
+ * ```typescript
3342
+ * new TemplateEngine({ interpolate: interpolatePreset.LODASH })
3343
+ * .render('<%= repo.url %>', { repo: { url: 'https://example.com' } });
3344
+ * ```
3345
+ */
3346
+ readonly LODASH: RegExp;
3347
+ /**
3348
+ * Mustache / Handlebars style: `{{ variable }}`
3349
+ *
3350
+ * @example
3351
+ * ```typescript
3352
+ * new TemplateEngine({ interpolate: interpolatePreset.MUSTACHE })
3353
+ * .render('{{ user.name }}', { user: { name: 'Alice' } });
3354
+ * ```
3355
+ */
3356
+ readonly MUSTACHE: RegExp;
3357
+ };
3358
+ /**
3359
+ * Lightweight template engine for safe variable interpolation.
3360
+ *
3361
+ * Features:
3362
+ * - ES6 `${ path }` syntax by default
3363
+ * - Nested path access and numeric array indices
3364
+ * - Prototype pollution protection (`safePrototype`, enabled by default)
3365
+ * - Compile-once, render-many for performance
3366
+ *
3367
+ * Does NOT execute `<% code %>` logic blocks or arbitrary JavaScript.
3368
+ */
3369
+ declare class TemplateEngine {
3370
+ private readonly options;
3371
+ /**
3372
+ * @param options - Engine configuration. All fields are optional;
3373
+ * defaults to ES6 `${}` interpolation with safe prototype access.
3374
+ */
3375
+ constructor(options?: TemplateOptions);
3376
+ /**
3377
+ * Compile a template into a reusable render function.
3378
+ *
3379
+ * Path parsing and validation happen once at compile time; subsequent
3380
+ * renders only perform value lookup and string assembly.
3381
+ *
3382
+ * @param template - Template string containing placeholders
3383
+ * @returns Render function bound to the compiled template
3384
+ * @throws {TypeError} When template is not a string
3385
+ */
3386
+ compile(template: string): RenderFn;
3387
+ /**
3388
+ * Render a template in one shot.
3389
+ *
3390
+ * Convenience wrapper around `compile(template)(data)`.
3391
+ * Prefer {@link compile} when the same template is rendered multiple times.
3392
+ *
3393
+ * @param template - Template string containing placeholders
3394
+ * @param data - Context object for variable substitution
3395
+ */
3396
+ render(template: string, data: Record<string, any>): string;
5099
3397
  }
5100
3398
 
5101
- export { ColorFormatter, ConfigSearch, type ConfigSearchOptions, type ExecPromiseFunction, type FeConfig, type FeReleaseConfig, ScriptContext, type ScriptContextInterface, ScriptPlugin, type ScriptPluginProps, type ScriptSharedInterface, Shell, type ShellConfig, type ShellExecOptions, type ShellInterface, type StepOption, defaultFeConfig };
3399
+ export { ColorFormatter, ConfigSearch, type ConfigSearchOptions, type ExecPromiseFunction, type FeConfig, type RenderFn, ScriptContext, type ScriptContextInterface, ScriptPlugin, type ScriptPluginProps, type ScriptSharedInterface, Shell, type ShellConfig, type ShellExecOptions, type ShellInterface, type StepOption, TemplateEngine, type TemplateOptions, defaultFeConfig, interpolatePreset };