@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.cjs +3 -18
- package/dist/index.d.ts +197 -1899
- package/dist/index.js +753 -243
- package/package.json +4 -4
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
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
|
1095
|
+
* @example Basic formatting
|
|
2958
1096
|
* ```typescript
|
|
2959
|
-
* const result = Shell.format('Hello
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
|
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?(
|
|
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?(
|
|
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?(
|
|
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
|
|
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 };
|