@qlover/scripts-context 2.2.0 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { UserConfig } from '@commitlint/types';
2
2
  import { Env } from '@qlover/env-loader';
3
- import { ExecutorContextImpl, LifecyclePluginInterface, ExecutorContextInterface, ExecutorError } from '@qlover/fe-corekit';
4
3
 
5
4
  declare const defaultFeConfig: FeConfig;
6
5
  interface FeConfig {
@@ -40,524 +39,10 @@ interface FeConfig {
40
39
  * @default { "extends": ["@commitlint/config-conventional"] }
41
40
  */
42
41
  commitlint?: UserConfig;
43
- /**
44
- * config of CI release
45
- *
46
- * scripts release
47
- */
48
- release?: FeReleaseConfig;
49
42
  /**
50
43
  * @default ['.env.local', '.env']
51
44
  */
52
45
  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
46
  }
562
47
 
563
48
  /**
@@ -2784,7 +2269,7 @@ interface ShellConfig extends ShellExecOptions {
2784
2269
  *
2785
2270
  * Main features:
2786
2271
  * - Template formatting: Dynamic command generation with context
2787
- * - Uses lodash template for string interpolation
2272
+ * - Uses TemplateEngine for string interpolation
2788
2273
  * - Supports complex template expressions
2789
2274
  * - Provides error handling for template failures
2790
2275
  * - Enables dynamic command construction
@@ -2833,7 +2318,7 @@ interface ShellConfig extends ShellExecOptions {
2833
2318
  * @example With template formatting
2834
2319
  * ```typescript
2835
2320
  * const shell = new Shell({ logger: myLogger });
2836
- * const output = await shell.exec('git clone <%= repo %>', {
2321
+ * const output = await shell.exec('git clone ${repo}', {
2837
2322
  * context: { repo: 'https://github.com/user/repo.git' }
2838
2323
  * });
2839
2324
  * ```
@@ -2859,6 +2344,7 @@ interface ShellConfig extends ShellExecOptions {
2859
2344
  declare class Shell implements ShellInterface {
2860
2345
  config: ShellConfig;
2861
2346
  private cache;
2347
+ private static readonly templateEngine;
2862
2348
  /**
2863
2349
  * Creates a new Shell instance with the specified configuration
2864
2350
  *
@@ -2926,59 +2412,30 @@ declare class Shell implements ShellInterface {
2926
2412
  */
2927
2413
  get logger(): LoggerInterface;
2928
2414
  /**
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
2415
+ * Formats a template string with context using {@link TemplateEngine}.
2940
2416
  *
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
2946
- *
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
2417
+ * Uses ES6-style `${ path }` placeholders via {@link TemplateEngine}.
2952
2418
  *
2953
2419
  * @param template - Template string with interpolation placeholders
2954
2420
  * @param context - Context object for template variable substitution
2955
2421
  * @returns Formatted string with context values substituted
2956
2422
  *
2957
- * @example Basic template formatting
2423
+ * @example Basic formatting
2958
2424
  * ```typescript
2959
- * const result = Shell.format('Hello <%= name %>!', { name: 'World' });
2425
+ * const result = Shell.format('Hello ${name}!', { name: 'World' });
2960
2426
  * // Returns: 'Hello World!'
2961
2427
  * ```
2962
2428
  *
2963
2429
  * @example Complex template with nested objects
2964
2430
  * ```typescript
2965
2431
  * const result = Shell.format(
2966
- * 'git clone <%= repo.url %> <%= repo.branch %>',
2432
+ * 'git clone ${repo.url} ${repo.branch}',
2967
2433
  * { repo: { url: 'https://github.com/user/repo.git', branch: 'main' } }
2968
2434
  * );
2969
2435
  * // Returns: 'git clone https://github.com/user/repo.git main'
2970
2436
  * ```
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
2437
  */
2981
- static format(template?: string, context?: Record<string, unknown>): string;
2438
+ static format(template?: string, context?: Record<string, any>): string;
2982
2439
  /**
2983
2440
  * Formats a template string with context and comprehensive error handling
2984
2441
  *
@@ -3012,14 +2469,14 @@ declare class Shell implements ShellInterface {
3012
2469
  *
3013
2470
  * @example Basic formatting
3014
2471
  * ```typescript
3015
- * const result = shell.format('Hello <%= name %>!', { name: 'World' });
2472
+ * const result = shell.format('Hello ${name}!', { name: 'World' });
3016
2473
  * // Returns: 'Hello World!'
3017
2474
  * ```
3018
2475
  *
3019
2476
  * @example Error handling
3020
2477
  * ```typescript
3021
2478
  * try {
3022
- * const result = shell.format('Hello <%= name %>!', {});
2479
+ * const result = shell.format('Hello ${name}!', {});
3023
2480
  * } catch (error) {
3024
2481
  * // Error is logged with template and context information
3025
2482
  * console.error('Template formatting failed:', error.message);
@@ -3061,7 +2518,7 @@ declare class Shell implements ShellInterface {
3061
2518
  *
3062
2519
  * @example String command with template
3063
2520
  * ```typescript
3064
- * const output = await shell.exec('git clone <%= repo %>', {
2521
+ * const output = await shell.exec('git clone ${repo}', {
3065
2522
  * context: { repo: 'https://github.com/user/repo.git' }
3066
2523
  * });
3067
2524
  * ```
@@ -4201,45 +3658,1783 @@ declare class ConfigSearch {
4201
3658
  }
4202
3659
 
4203
3660
  /**
4204
- * Enhanced script context that provides environment management and configuration utilities
3661
+ * Base error class for all executor-related errors in the system
4205
3662
  *
4206
- * Core concept:
4207
- * Provides a comprehensive script execution environment with integrated
4208
- * configuration management, environment variable handling, logging,
4209
- * and shell command execution capabilities.
3663
+ * ExecutorError provides a standardized way to handle errors throughout the executor
3664
+ * lifecycle. It wraps underlying errors while maintaining error context through an
3665
+ * error ID system, enabling precise error categorization and handling.
4210
3666
  *
4211
- * Main features:
4212
- * - Environment management: Integrated environment variable handling
4213
- * - Automatic loading of .env files with configurable order
4214
- * - Type-safe environment variable access with defaults
4215
- * - Support for environment-specific configurations
4216
- * - Integration with fe-config environment settings
3667
+ * Core features:
3668
+ * - **Error identification**: Uses unique `id` to categorize different error types without relying on error messages
3669
+ * - **Error wrapping**: Preserves original error information through `cause` property, supporting error chaining
3670
+ * - **Stack trace independence**: Each error maintains its own stack trace, original error stack accessible via `cause.stack`
3671
+ * - **Type safety**: Provides type-safe error handling with TypeScript, enabling compile-time error checking
3672
+ * - **Subclass support**: Designed to be extended by specific error types (RequestError, AbortError, etc.)
4217
3673
  *
4218
- * - Configuration management: Unified configuration access and merging
4219
- * - Script-specific configuration sections
4220
- * - Deep merging with default values
4221
- * - Type-safe option access with nested path support
4222
- * - Configuration validation and fallback handling
3674
+ * Design considerations:
3675
+ * - The `id` field enables error categorization without relying on error messages, which may be localized or changed
3676
+ * - The `cause` field supports error chaining (similar to Java's exception chaining), preserving the original error context
3677
+ * - When `cause` is an Error, its message is inherited but stack trace remains independent, and the Error object is stored in `cause`
3678
+ * - When `cause` is a string, it's used directly as the error message, but not stored in `cause` property (to avoid duplication)
3679
+ * - When `cause` is undefined or other types, the error message falls back to `id` value
3680
+ * - Each ExecutorError has its own stack trace showing where it was created, not where the original error occurred
3681
+ * - Original error's stack trace is preserved in `cause.stack` for complete error chain debugging
3682
+ * - Stack trace is automatically captured in V8 environments (Node.js, Chrome) for better debugging
3683
+ * - For subclasses, `name` is set to `constructor.name`, which may be affected by bundling/minification (see TODO comment in constructor)
3684
+ *
3685
+ * Error handling strategy:
3686
+ * - Use specific error IDs for different failure scenarios to enable precise error handling
3687
+ * - Always wrap lower-level errors with ExecutorError to maintain consistent error interface
3688
+ * - Preserve original error information through the `cause` property for debugging
3689
+ * - Use `instanceof` checks for error type detection, and `id` for specific error scenario handling
3690
+ *
3691
+ * @example Basic usage with error ID only
3692
+ * ```typescript
3693
+ * throw new ExecutorError('VALIDATION_ERROR');
3694
+ * // Error message will be 'VALIDATION_ERROR' (falls back to id)
3695
+ * ```
4223
3696
  *
4224
- * - Logging system: Structured logging with timestamp formatting
4225
- * - Configurable verbosity levels
4226
- * - Timestamp formatting with timezone support
4227
- * - Logger name identification for multi-script environments
4228
- * - Console output with structured formatting
3697
+ * @example Wrapping an existing error
3698
+ * ```typescript
3699
+ * try {
3700
+ * await riskyOperation();
3701
+ * } catch (error) {
3702
+ * throw new ExecutorError('OPERATION_FAILED', error);
3703
+ * }
3704
+ * ```
4229
3705
  *
4230
- * - Shell integration: Command execution with dry run support
4231
- * - Safe command execution with error handling
4232
- * - Dry run mode for testing and validation
4233
- * - Integrated logging for command output
4234
- * - Support for custom execution functions
3706
+ * @example With custom string message
3707
+ * ```typescript
3708
+ * throw new ExecutorError(
3709
+ * 'CUSTOM_ERROR',
3710
+ * 'Invalid configuration: timeout must be positive'
3711
+ * );
3712
+ * ```
4235
3713
  *
4236
- * Design considerations:
4237
- * - Uses lodash merge for deep configuration merging
4238
- * - Supports environment file loading with configurable order
4239
- * - Provides type-safe option access with fallback values
4240
- * - Implements proper error handling for missing configurations
4241
- * - Maintains backward compatibility with existing interfaces
4242
- * - Supports both development and production environments
3714
+ * @example Error identification and handling
3715
+ * ```typescript
3716
+ * try {
3717
+ * await executor.exec(task);
3718
+ * } catch (error) {
3719
+ * if (error instanceof ExecutorError) {
3720
+ * switch (error.id) {
3721
+ * case 'VALIDATION_ERROR':
3722
+ * // Handle validation errors
3723
+ * console.error('Validation failed:', error.message);
3724
+ * break;
3725
+ * case 'TIMEOUT_ERROR':
3726
+ * // Handle timeout errors
3727
+ * console.error('Operation timed out:', error.message);
3728
+ * break;
3729
+ * default:
3730
+ * // Handle other executor errors
3731
+ * console.error('Unknown executor error:', error.id);
3732
+ * }
3733
+ * }
3734
+ * }
3735
+ * ```
3736
+ *
3737
+ * @see RequestError - Extends ExecutorError for request-specific errors
3738
+ * @see AbortError - Extends ExecutorError for abort-specific errors
3739
+ */
3740
+ declare class ExecutorError extends Error {
3741
+ /**
3742
+ * Unique identifier for categorizing the error type
3743
+ *
3744
+ * This ID enables programmatic error handling without relying on error messages,
3745
+ * which may change or be localized. It serves as a stable contract for error types
3746
+ * across the entire executor system.
3747
+ *
3748
+ * Best practices:
3749
+ * - Use UPPER_SNAKE_CASE for consistency
3750
+ * - Make IDs descriptive and specific to the error scenario
3751
+ * - Document common error IDs in the class-level documentation
3752
+ * - Avoid changing existing IDs to maintain backward compatibility
3753
+ *
3754
+ * @example `'VALIDATION_ERROR'`
3755
+ * @example `'EXECUTOR_ASYNC_ERROR'`
3756
+ * @example `'REQUEST_TIMEOUT'`
3757
+ */
3758
+ readonly id: string;
3759
+ /**
3760
+ * Creates a new ExecutorError instance
3761
+ *
3762
+ * The constructor intelligently handles different types of `cause` values:
3763
+ * - If `cause` is an Error: Inherits its message but maintains independent stack trace
3764
+ * - If `cause` is a string: Uses it as the error message directly
3765
+ * - If `cause` is undefined or other types: Uses the `id` as the error message
3766
+ *
3767
+ * Implementation details:
3768
+ * - Uses `super()` to initialize the parent Error class first
3769
+ * - Sets the error name based on whether this is the base class or a subclass
3770
+ * - For base ExecutorError, uses the constant `EXECUTOR_ERROR_NAME`
3771
+ * - For subclasses, uses `this.constructor.name` (note: may be affected by bundling/minification)
3772
+ * - Each ExecutorError gets its own stack trace (captured by V8 automatically)
3773
+ * - Original error's stack trace is preserved in `cause.stack` for debugging the error chain
3774
+ * - The `cause` property is only set when `this.message !== cause` to avoid redundancy
3775
+ *
3776
+ * Message resolution logic:
3777
+ * 1. If `cause` is an Error: `message = cause.message`
3778
+ * 2. Else if `cause` is a string: `message = cause`
3779
+ * 3. Else: `message = id` (fallback to error ID)
3780
+ *
3781
+ * Cause property logic:
3782
+ * - Set `this.cause = cause` only when `this.message !== cause`
3783
+ * - This means: Error objects always set `cause`, strings don't (to avoid duplication), undefined sets `cause` to undefined
3784
+ *
3785
+ * @param id - Unique identifier for the error type
3786
+ *
3787
+ * Used to categorize and identify specific error scenarios. Common IDs include:
3788
+ * - `'UNKNOWN_ASYNC_ERROR'` (EXECUTOR_ASYNC_ERROR) - Async execution failures in executor lifecycle
3789
+ * - `'UNKNOWN_SYNC_ERROR'` (EXECUTOR_SYNC_ERROR) - Sync execution failures in executor lifecycle
3790
+ * - `'VALIDATION_ERROR'` - Input validation failures
3791
+ * - `'TIMEOUT_ERROR'` - Operation timeout
3792
+ * - `'ABORT_ERROR'` - Operation aborted by user or system
3793
+ * - `'PLUGIN_ERROR'` - Plugin execution failures
3794
+ * - `'CONTEXT_ERROR'` - Context-related errors
3795
+ *
3796
+ * @param cause - Optional underlying cause of the error
3797
+ *
3798
+ * Can be:
3799
+ * - An Error object: Original error to wrap, inheriting its message. The Error object will be stored in `cause` property (access original stack via `cause.stack`).
3800
+ * - A string: Custom error message describing the failure. The string will be used as `message`, but won't be stored in `cause` (to avoid duplication).
3801
+ * - Undefined: Error message will be set to `id`. The `cause` property will be set to `undefined`.
3802
+ * - Any other value: Error message will be set to `id`. The value will be stored in `cause` property.
3803
+ *
3804
+ * @example Create error with ID only
3805
+ * ```typescript
3806
+ * const error = new ExecutorError('UNKNOWN_ERROR');
3807
+ * console.log(error.id); // 'UNKNOWN_ERROR'
3808
+ * console.log(error.message); // 'UNKNOWN_ERROR' (falls back to id)
3809
+ * console.log(error.cause); // undefined
3810
+ * console.log(error.name); // 'ExecutorError'
3811
+ * ```
3812
+ *
3813
+ * @example Wrap an existing error
3814
+ * ```typescript
3815
+ * try {
3816
+ * JSON.parse(invalidJson);
3817
+ * } catch (err) {
3818
+ * const error = new ExecutorError('PARSE_ERROR', err);
3819
+ * console.log(error.id); // 'PARSE_ERROR'
3820
+ * console.log(error.message); // 'Unexpected token...' (from err.message)
3821
+ * console.log(error.cause); // Original SyntaxError (stored in cause)
3822
+ * console.log(error.stack); // Stack trace showing where ExecutorError was created
3823
+ * console.log(error.cause.stack); // Original SyntaxError stack trace
3824
+ * }
3825
+ * ```
3826
+ *
3827
+ * @example Create error with custom message
3828
+ * ```typescript
3829
+ * const error = new ExecutorError(
3830
+ * 'CONFIG_ERROR',
3831
+ * 'Timeout must be a positive number'
3832
+ * );
3833
+ * console.log(error.id); // 'CONFIG_ERROR'
3834
+ * console.log(error.message); // 'Timeout must be a positive number'
3835
+ * console.log(error.cause); // undefined (not stored to avoid duplication)
3836
+ * ```
3837
+ *
3838
+ * @example Subclass usage
3839
+ * ```typescript
3840
+ * class RequestError extends ExecutorError {
3841
+ * constructor(cause?: unknown) {
3842
+ * super('REQUEST_ERROR', cause);
3843
+ * // Note: constructor.name may be mangled during bundling
3844
+ * // Consider explicitly setting this.name if needed
3845
+ * }
3846
+ * }
3847
+ * const error = new RequestError('Network failure');
3848
+ * console.log(error.name); // 'RequestError' (from constructor.name)
3849
+ * console.log(error.id); // 'REQUEST_ERROR'
3850
+ * console.log(error.message); // 'Network failure'
3851
+ * ```
3852
+ */
3853
+ constructor(
3854
+ /**
3855
+ * Unique identifier for categorizing the error type
3856
+ *
3857
+ * This ID enables programmatic error handling without relying on error messages,
3858
+ * which may change or be localized. It serves as a stable contract for error types
3859
+ * across the entire executor system.
3860
+ *
3861
+ * Best practices:
3862
+ * - Use UPPER_SNAKE_CASE for consistency
3863
+ * - Make IDs descriptive and specific to the error scenario
3864
+ * - Document common error IDs in the class-level documentation
3865
+ * - Avoid changing existing IDs to maintain backward compatibility
3866
+ *
3867
+ * @example `'VALIDATION_ERROR'`
3868
+ * @example `'EXECUTOR_ASYNC_ERROR'`
3869
+ * @example `'REQUEST_TIMEOUT'`
3870
+ */
3871
+ id: string,
3872
+ /**
3873
+ * Optional underlying cause of the error
3874
+ *
3875
+ * Supports error chaining by preserving the original error or message.
3876
+ * The behavior differs based on the type:
3877
+ *
3878
+ * - **Error object**: Its message is inherited, and the Error object is stored in `cause` property (original stack accessible via `cause.stack`)
3879
+ * - **String**: Used as the error message directly, but not stored in `cause` property (to avoid duplication)
3880
+ * - **Undefined**: Error message falls back to `id`, and `cause` is set to `undefined`
3881
+ * - **Other types**: Error message falls back to `id`, and the value is stored in `cause` property
3882
+ *
3883
+ * Use cases:
3884
+ * - Wrapping lower-level errors (network errors, parse errors, etc.) - use Error object
3885
+ * - Providing custom error messages for specific scenarios - use string
3886
+ * - Storing additional error context (objects, metadata, etc.) - use any other type
3887
+ *
3888
+ * @optional
3889
+ * @example Error object: `new Error('Connection failed')` - message and stack inherited, Error stored in cause
3890
+ * @example String message: `'Invalid input format'` - used as message, not stored in cause
3891
+ * @example Other values: `{ code: 500, details: '...' }` - message falls back to id, value stored in cause
3892
+ */
3893
+ cause?: unknown);
3894
+ }
3895
+
3896
+ /**
3897
+ * Asynchronous task function type
3898
+ *
3899
+ * Represents a task that returns a Promise. Used for async operations
3900
+ * like API calls, file I/O, or any asynchronous work.
3901
+ *
3902
+ * @template R - Return type of the task
3903
+ * @template P - Parameter type for the context
3904
+ *
3905
+ * @example
3906
+ * ```typescript
3907
+ * const asyncTask: ExecutorAsyncTask<User, UserId> = async (ctx) => {
3908
+ * const response = await fetch(`/api/users/${ctx.parameters.id}`);
3909
+ * return response.json();
3910
+ * };
3911
+ * ```
3912
+ */
3913
+ type ExecutorAsyncTask<R, P> = (ctx: ExecutorContextInterface<P, R>) => Promise<R>;
3914
+ /**
3915
+ * Synchronous task function type
3916
+ *
3917
+ * Represents a task that returns immediately. Used for synchronous
3918
+ * operations like data transformation, validation, or computation.
3919
+ *
3920
+ * @template R - Return type of the task
3921
+ * @template P - Parameter type for the context
3922
+ *
3923
+ * @example
3924
+ * ```typescript
3925
+ * const syncTask: ExecutorSyncTask<string, string> = (ctx) => {
3926
+ * return ctx.parameters.toUpperCase();
3927
+ * };
3928
+ * ```
3929
+ */
3930
+ type ExecutorSyncTask<R, P> = (ctx: ExecutorContextInterface<P, R>) => R;
3931
+ /**
3932
+ * Union type for both sync and async tasks
3933
+ *
3934
+ * Allows a single type to represent either synchronous or asynchronous tasks.
3935
+ * The executor will automatically detect the return type and handle accordingly.
3936
+ *
3937
+ * @template R - Return type of the task
3938
+ * @template P - Parameter type for the context
3939
+ */
3940
+ type ExecutorTask<R, P> = ExecutorAsyncTask<R, P> | ExecutorSyncTask<R, P>;
3941
+ /**
3942
+ * Plugin hook name type
3943
+ *
3944
+ * Currently supports string names. Symbol support is planned for future versions
3945
+ * to allow for more advanced plugin identification and namespacing.
3946
+ *
3947
+ * @todo Add symbol support | symbol;
3948
+ */
3949
+ type ExecutorPluginNameType = string;
3950
+ /**
3951
+ * Base plugin interface for executor plugins
3952
+ *
3953
+ * ## Purpose
3954
+ * Defines the minimum contract that all executor plugins must implement.
3955
+ * Provides plugin identification, enablement checking, and basic metadata.
3956
+ *
3957
+ * Key Features:
3958
+ *
3959
+ * Plugin Identification:
3960
+ * - pluginName: Optional name for plugin identification
3961
+ * - onlyOne: Flag to ensure only one instance of this plugin type
3962
+ *
3963
+ * Enablement Checking:
3964
+ * - enabled: Method to check if plugin should execute for a given hook
3965
+ * - Context-Aware: Can check context state to determine enablement
3966
+ * - Hook-Specific: Can enable/disable per hook name
3967
+ *
3968
+ * Usage:
3969
+ * This is the base interface. Most plugins should extend `LifecyclePluginInterface`
3970
+ * which adds lifecycle hooks (onBefore, onExec, onSuccess, onError).
3971
+ *
3972
+ * @template Ctx - Type of executor context interface
3973
+ *
3974
+ * @example Basic plugin
3975
+ * ```typescript
3976
+ * const plugin: ExecutorPluginInterface<ExecutorContextInterface<unknown, unknown>> = {
3977
+ * pluginName: 'myPlugin',
3978
+ * onlyOne: true,
3979
+ * enabled: (name, context) => {
3980
+ * return name === 'onBefore' && context.parameters.shouldRun;
3981
+ * }
3982
+ * };
3983
+ * ```
3984
+ *
3985
+ * @see LifecyclePluginInterface - Extended interface with lifecycle hooks
3986
+ * @see LifecycleExecutor - Executor that uses plugins
3987
+ */
3988
+ interface ExecutorPluginInterface<Ctx extends ExecutorContextInterface<unknown, unknown>> {
3989
+ /** Optional plugin name for identification */
3990
+ readonly pluginName: ExecutorPluginNameType;
3991
+ /** If true, ensures only one instance of this plugin type */
3992
+ readonly onlyOne?: boolean;
3993
+ /**
3994
+ * Check if plugin should be enabled for a given hook
3995
+ * @param name - Hook name to check
3996
+ * @param context - Optional execution context
3997
+ * @returns true if plugin should execute, false otherwise
3998
+ */
3999
+ enabled?(name: ExecutorPluginNameType, context?: Ctx): boolean;
4000
+ }
4001
+
4002
+ /**
4003
+ * Runtime information interface for hook execution tracking
4004
+ *
4005
+ * Core concept:
4006
+ * Provides detailed runtime metadata for individual hook execution,
4007
+ * enabling performance monitoring, flow control, and execution state tracking
4008
+ *
4009
+ * Main features:
4010
+ * - Execution tracking: Monitors hook execution state and performance
4011
+ * - Flow control: Provides mechanisms to control execution pipeline flow
4012
+ * - Performance metrics: Tracks execution times and performance data
4013
+ * - State preservation: Maintains execution state throughout the pipeline
4014
+ * - Extensibility: Supports additional custom properties for specific use cases
4015
+ *
4016
+ * Flow control mechanisms:
4017
+ * - breakChain: Immediately stops execution pipeline
4018
+ * - returnBreakChain: Stops pipeline when return value is present
4019
+ * - times: Tracks execution frequency for optimization
4020
+ *
4021
+ * @since 3.0.0
4022
+ * @example Basic runtime information
4023
+ * ```typescript
4024
+ * const runtime: HookRuntimes = {
4025
+ * hookName: 'onBefore',
4026
+ * returnValue: { validated: true },
4027
+ * times: 1,
4028
+ * breakChain: false,
4029
+ * returnBreakChain: false
4030
+ * };
4031
+ * ```
4032
+ *
4033
+ * @example Runtime with custom properties
4034
+ * ```typescript
4035
+ * const runtime: HookRuntimes = {
4036
+ * hookName: 'customHook',
4037
+ * returnValue: { processed: true },
4038
+ * times: 3,
4039
+ * breakChain: false,
4040
+ * returnBreakChain: true,
4041
+ * customMetric: 'performance_data',
4042
+ * executionTime: 150
4043
+ * };
4044
+ * ```
4045
+ */
4046
+ interface HookRuntimes {
4047
+ /**
4048
+ * Name of the current plugin being executed
4049
+ *
4050
+ * Core concept:
4051
+ * Identifies which plugin is currently executing, enabling plugin-specific
4052
+ * debugging and tracking
4053
+ *
4054
+ * @optional
4055
+ * @example `'ValidationPlugin'`
4056
+ * @example `'CachePlugin'`
4057
+ */
4058
+ pluginName?: string;
4059
+ /**
4060
+ * Index of the current plugin in the plugins array
4061
+ *
4062
+ * Core concept:
4063
+ * Tracks the position of the current plugin in the execution chain,
4064
+ * useful for debugging execution order
4065
+ *
4066
+ * @optional
4067
+ * @example `0` // First plugin
4068
+ * @example `2` // Third plugin
4069
+ */
4070
+ pluginIndex?: number;
4071
+ /**
4072
+ * Name of the current hook being executed
4073
+ *
4074
+ * Core concept:
4075
+ * Identifies the specific hook that is currently being executed,
4076
+ * enabling targeted debugging and monitoring of hook performance
4077
+ *
4078
+ * Main features:
4079
+ * - Hook identification: Clearly identifies which hook is executing
4080
+ * - Debugging support: Enables targeted debugging of specific hooks
4081
+ * - Performance monitoring: Allows tracking of individual hook performance
4082
+ * - Pipeline visibility: Provides visibility into execution pipeline state
4083
+ *
4084
+ * @optional
4085
+ * @example `'onBefore'`
4086
+ * @example `'onExec'`
4087
+ * @example `'onAfter'`
4088
+ * @example `'customValidationHook'`
4089
+ */
4090
+ hookName?: string;
4091
+ /**
4092
+ * Return value from the current hook execution
4093
+ *
4094
+ * Core concept:
4095
+ * Captures the return value from the current hook execution,
4096
+ * enabling result tracking and flow control based on hook output
4097
+ *
4098
+ * Main features:
4099
+ * - Result tracking: Monitors what each hook returns
4100
+ * - Flow control: Enables conditional execution based on return values
4101
+ * - Debugging support: Provides visibility into hook output
4102
+ * - Pipeline integration: Results can influence downstream execution
4103
+ *
4104
+ * @readonly
4105
+ * @optional
4106
+ * @example `{ validated: true, data: 'processed' }`
4107
+ * @example `'hook_result'`
4108
+ * @example `{ error: 'validation_failed' }`
4109
+ */
4110
+ returnValue?: unknown;
4111
+ /**
4112
+ * Number of times the current hook has been executed
4113
+ *
4114
+ * Core concept:
4115
+ * Tracks how many plugins have executed the current hook (e.g., onBefore).
4116
+ * This counter increments for each plugin that successfully executes the hook.
4117
+ *
4118
+ * Important:
4119
+ * - This is per-hook, not global
4120
+ * - Reset when switching to a different hook
4121
+ * - Represents "which plugin is executing this hook" (1st, 2nd, 3rd, etc.)
4122
+ *
4123
+ * Main features:
4124
+ * - Execution counting: Monitors how many plugins executed this hook
4125
+ * - Performance analysis: Identifies frequently executed hooks
4126
+ * - Loop detection: Helps identify potential infinite loops
4127
+ * - Optimization insights: Provides data for performance optimization
4128
+ *
4129
+ * Usage scenarios:
4130
+ * - Know if any plugin executed the hook (times > 0)
4131
+ * - Track which plugin number is executing (useful for debugging)
4132
+ * - Detect if hook was skipped by all plugins (times === 0)
4133
+ *
4134
+ * @optional
4135
+ * @example `0` // No plugin has executed this hook yet
4136
+ * @example `1` // First plugin executed this hook
4137
+ * @example `3` // Third plugin is executing this hook
4138
+ */
4139
+ times?: number;
4140
+ /**
4141
+ * Flag to immediately break the execution chain
4142
+ *
4143
+ * Core concept:
4144
+ * Provides a mechanism to immediately stop the execution pipeline,
4145
+ * enabling early termination when certain conditions are met
4146
+ *
4147
+ * Main features:
4148
+ * - Immediate termination: Stops execution pipeline immediately
4149
+ * - Conditional control: Enables conditional execution flow
4150
+ * - Error handling: Allows early termination on critical errors
4151
+ * - Performance optimization: Avoids unnecessary processing
4152
+ *
4153
+ * Use cases:
4154
+ * - Error conditions: Stop execution when critical errors occur
4155
+ * - Validation failures: Terminate when validation fails
4156
+ * - Early success: Stop when desired result is achieved early
4157
+ * - Resource constraints: Terminate when resources are exhausted
4158
+ *
4159
+ * @optional
4160
+ * @example `true` // Break execution chain immediately
4161
+ * @example `false` // Continue normal execution
4162
+ */
4163
+ breakChain?: boolean;
4164
+ /**
4165
+ * Flag to break chain when return value exists
4166
+ *
4167
+ * Core concept:
4168
+ * Enables conditional chain breaking based on the presence of a return value,
4169
+ * commonly used in error handling and early termination scenarios
4170
+ *
4171
+ * Main features:
4172
+ * - Conditional termination: Breaks chain only when return value exists
4173
+ * - Error handling: Commonly used in `onError` lifecycle hooks
4174
+ * - Result-based control: Enables flow control based on hook results
4175
+ * - Flexible termination: Provides more nuanced control than `breakChain`
4176
+ *
4177
+ * Common usage:
4178
+ * - Error handlers: Break chain when error is handled and result is returned
4179
+ * - Validation: Stop processing when validation result is returned
4180
+ * - Caching: Terminate when cached result is found
4181
+ * - Early success: Stop when desired result is achieved
4182
+ *
4183
+ * @optional
4184
+ * @example `true` // Break chain if returnValue exists
4185
+ * @example `false` // Continue regardless of returnValue
4186
+ */
4187
+ returnBreakChain?: boolean;
4188
+ /**
4189
+ * Flag to continue execution on error
4190
+ *
4191
+ * Core concept:
4192
+ * Provides a mechanism to continue executing subsequent plugins even when
4193
+ * a plugin hook throws an error, enabling resilient execution pipelines
4194
+ *
4195
+ * Main features:
4196
+ * - Error resilience: Continues execution despite individual plugin failures
4197
+ * - Fault tolerance: Enables graceful degradation in plugin chains
4198
+ * - Cleanup guarantees: Ensures all cleanup hooks execute even if some fail
4199
+ * - Flexible error handling: Allows selective error suppression
4200
+ *
4201
+ * Use cases:
4202
+ * - Finally hooks: Ensure all cleanup operations execute even if one fails
4203
+ * - Logging hooks: Continue logging even if one logger fails
4204
+ * - Monitoring hooks: Collect metrics from all plugins despite failures
4205
+ * - Non-critical operations: Continue execution for non-critical hooks
4206
+ *
4207
+ * @optional
4208
+ * @example `true` // Continue to next plugin even if current plugin throws error
4209
+ * @example `false` // Stop execution and throw error (default behavior)
4210
+ */
4211
+ continueOnError?: boolean;
4212
+ /**
4213
+ * Additional custom properties for extensibility
4214
+ *
4215
+ * Core concept:
4216
+ * Provides a flexible mechanism to add custom properties to runtime
4217
+ * information, enabling plugin-specific metadata and custom tracking
4218
+ *
4219
+ * Main features:
4220
+ * - Extensibility: Allows plugins to add custom runtime data
4221
+ * - Custom metrics: Enables plugin-specific performance tracking
4222
+ * - Metadata storage: Provides space for custom execution metadata
4223
+ * - Plugin integration: Enables rich plugin-to-plugin communication
4224
+ *
4225
+ * Common custom properties:
4226
+ * - executionTime: Hook execution time in milliseconds
4227
+ * - memoryUsage: Memory consumption during hook execution
4228
+ * - customMetrics: Plugin-specific performance metrics
4229
+ * - debugInfo: Additional debugging information
4230
+ *
4231
+ * @example
4232
+ * ```typescript
4233
+ * {
4234
+ * executionTime: 150,
4235
+ * memoryUsage: '2.5MB',
4236
+ * customMetric: 'validation_score',
4237
+ * debugInfo: { step: 'validation', level: 'info' }
4238
+ * }
4239
+ * ```
4240
+ */
4241
+ [key: string]: unknown;
4242
+ }
4243
+ /**
4244
+ * Interface for runtime tracking of executor hooks
4245
+ *
4246
+ * Core concept:
4247
+ * Generic interface that allows extending HookRuntimes with custom properties.
4248
+ * This enables plugins to add their own runtime tracking data.
4249
+ *
4250
+ * @template RuntimesType - Type of hook runtimes (extends HookRuntimes)
4251
+ *
4252
+ * @example Basic usage (default HookRuntimes)
4253
+ * ```typescript
4254
+ * class MyContext implements ExecutorHookRuntimesInterface {
4255
+ * // Uses default HookRuntimes
4256
+ * }
4257
+ * ```
4258
+ *
4259
+ * @example Extended runtimes with custom properties
4260
+ * ```typescript
4261
+ * interface CustomRuntimes extends HookRuntimes {
4262
+ * executionTime?: number;
4263
+ * memoryUsage?: number;
4264
+ * customMetric?: string;
4265
+ * }
4266
+ *
4267
+ * class MyContext implements ExecutorHookRuntimesInterface<CustomRuntimes> {
4268
+ * get hooksRuntimes(): Readonly<CustomRuntimes> {
4269
+ * // Return extended runtime data
4270
+ * }
4271
+ * }
4272
+ * ```
4273
+ *
4274
+ * @since 2.6.0
4275
+ */
4276
+ interface ExecutorHookRuntimesInterface<RuntimesType extends HookRuntimes = HookRuntimes> {
4277
+ /**
4278
+ * Reset hooks runtime state to initial values
4279
+ *
4280
+ * If hookName is provided, only reset the runtime state for that hook.
4281
+ *
4282
+ * Core concept:
4283
+ * Clears all runtime tracking information for fresh execution
4284
+ */
4285
+ resetHooksRuntimes(hookName?: string): void;
4286
+ /**
4287
+ * Reset entire context to initial state
4288
+ */
4289
+ reset(): void;
4290
+ /**
4291
+ * Check if a plugin hook should be skipped
4292
+ * @param plugin - The plugin to check
4293
+ * @param hookName - The name of the hook to validate
4294
+ * @returns True if the hook should be skipped, false otherwise
4295
+ */
4296
+ shouldSkipPluginHook<Ctx extends ExecutorContextInterface<unknown, unknown>>(plugin: ExecutorPluginInterface<Ctx>, hookName: string): boolean;
4297
+ /**
4298
+ * Get read-only snapshot of hooks runtime information
4299
+ *
4300
+ * Core concept:
4301
+ * Provides safe read-only access to runtime tracking information.
4302
+ * Returns a frozen copy to prevent accidental modifications.
4303
+ *
4304
+ * Generic support:
4305
+ * - Can return extended HookRuntimes with custom properties
4306
+ * - Type-safe access to custom runtime data
4307
+ * - Maintains immutability through Readonly
4308
+ *
4309
+ * @returns Frozen snapshot of hook runtime state (can include custom properties)
4310
+ *
4311
+ * @example Access standard properties
4312
+ * ```typescript
4313
+ * const runtimes = context.hooksRuntimes;
4314
+ * console.log(runtimes.hookName, runtimes.times);
4315
+ * ```
4316
+ *
4317
+ * @example Access custom properties (with extended type)
4318
+ * ```typescript
4319
+ * interface CustomRuntimes extends HookRuntimes {
4320
+ * executionTime: number;
4321
+ * }
4322
+ * const context: ExecutorHookRuntimesInterface<CustomRuntimes>;
4323
+ * const runtimes = context.hooksRuntimes;
4324
+ * console.log(runtimes.executionTime); // Type-safe!
4325
+ * ```
4326
+ */
4327
+ get hooksRuntimes(): Readonly<RuntimesType>;
4328
+ /**
4329
+ * Update runtime tracking information for plugin execution
4330
+ *
4331
+ * Core concept:
4332
+ * Controlled way to update runtime state through partial updates.
4333
+ * This is the only safe way to modify runtime state.
4334
+ *
4335
+ * Generic support:
4336
+ * - Can update custom properties in extended HookRuntimes
4337
+ * - Type-safe updates with partial type checking
4338
+ * - Maintains immutability through object replacement
4339
+ *
4340
+ * @param runtimes - Partial runtime updates to apply (can include custom properties)
4341
+ *
4342
+ * @example Update standard properties
4343
+ * ```typescript
4344
+ * context.runtimes({
4345
+ * pluginName: 'ValidationPlugin',
4346
+ * hookName: 'onBefore',
4347
+ * pluginIndex: 0,
4348
+ * times: 1
4349
+ * });
4350
+ * ```
4351
+ *
4352
+ * @example Update custom properties (with extended type)
4353
+ * ```typescript
4354
+ * interface CustomRuntimes extends HookRuntimes {
4355
+ * executionTime: number;
4356
+ * }
4357
+ * const context: ExecutorHookRuntimesInterface<CustomRuntimes>;
4358
+ * context.runtimes({
4359
+ * executionTime: 150,
4360
+ * customMetric: 'performance'
4361
+ * });
4362
+ * ```
4363
+ */
4364
+ runtimes(runtimes: Partial<RuntimesType>): void;
4365
+ /**
4366
+ * Set return value in context runtime tracking
4367
+ * @param returnValue - The value to set as return value
4368
+ */
4369
+ runtimeReturnValue(returnValue: unknown): void;
4370
+ /**
4371
+ * Check if the execution chain should be broken
4372
+ * @returns True if the chain should be broken, false otherwise
4373
+ */
4374
+ shouldBreakChain(): boolean;
4375
+ /**
4376
+ * Check if the execution chain should be broken due to return value
4377
+ * @returns True if the chain should be broken due to return value, false otherwise
4378
+ */
4379
+ shouldBreakChainOnReturn(): boolean;
4380
+ /**
4381
+ * Check if execution should continue on error
4382
+ *
4383
+ * Core concept:
4384
+ * Determines whether to continue executing subsequent plugins when a plugin hook
4385
+ * throws an error, enabling resilient execution pipelines
4386
+ *
4387
+ * Main features:
4388
+ * - Error resilience: Allows execution to continue despite individual failures
4389
+ * - Fault tolerance: Enables graceful degradation in plugin chains
4390
+ * - Cleanup guarantees: Ensures all cleanup hooks execute even if some fail
4391
+ *
4392
+ * Use cases:
4393
+ * - Finally hooks: Ensure all cleanup operations execute even if one fails
4394
+ * - Logging hooks: Continue logging even if one logger fails
4395
+ * - Monitoring hooks: Collect metrics from all plugins despite failures
4396
+ *
4397
+ * @returns True if execution should continue on error, false otherwise
4398
+ *
4399
+ * @example
4400
+ * ```typescript
4401
+ * // Enable continue on error for finally hooks
4402
+ * context.runtimes({ continueOnError: true });
4403
+ * await runPluginsHookAsync(plugins, 'onFinally', context);
4404
+ * ```
4405
+ */
4406
+ shouldContinueOnError(): boolean;
4407
+ }
4408
+
4409
+ /**
4410
+ * Executor context interface with generic runtime support
4411
+ *
4412
+ * Core concept:
4413
+ * Provides a shared context for task execution, allowing plugins to access
4414
+ * and modify parameters, track execution state, and share data across the
4415
+ * execution lifecycle. The context acts as a communication bridge between
4416
+ * the executor, plugins, and the task being executed.
4417
+ *
4418
+ * Main features:
4419
+ * - Parameter management: Read and update execution parameters
4420
+ * - Type-safe parameter access through generic type `T`
4421
+ * - Immutable read access via `parameters` property
4422
+ * - Safe updates via `setParameters()` with internal cloning
4423
+ * - Prevents accidental parameter mutation
4424
+ *
4425
+ * - Error tracking: Store and retrieve error state
4426
+ * - Captures errors from task execution
4427
+ * - Accessible to error handling plugins
4428
+ * - Supports any error type (Error, string, object, etc.)
4429
+ * - Automatically converts to ExecutorError
4430
+ *
4431
+ * - Return value handling: Access task return values
4432
+ * - Type-safe return value through generic type `R`
4433
+ * - Available to afterHooks for result transformation
4434
+ * - Undefined until task completes successfully
4435
+ *
4436
+ * - Runtime metadata: Track execution timing and state
4437
+ * - Extensible runtime information via `RuntimesType`
4438
+ * - Hook execution tracking
4439
+ * - Performance monitoring support
4440
+ * - Custom metadata storage
4441
+ *
4442
+ * Design considerations:
4443
+ * - Immutable core properties: `parameters`, `error`, `returnValue` are read-only
4444
+ * - Safe mutation methods: `setParameters()`, `setError()`, `setReturnValue()`
4445
+ * - Generic type safety: Full type inference for parameters and return values
4446
+ * - Extensible runtimes: Custom runtime metadata via `RuntimesType` generic
4447
+ *
4448
+ * @since `3.0.0`
4449
+ * @template T - Type of execution parameters
4450
+ * @template R - Type of return value (required for type safety)
4451
+ * @template RuntimesType - Type of hook runtimes (extends `HookRuntimes`, defaults to `HookRuntimes`)
4452
+ *
4453
+ * @example Basic usage
4454
+ * ```typescript
4455
+ * interface UserParams {
4456
+ * userId: number;
4457
+ * action: string;
4458
+ * }
4459
+ *
4460
+ * interface UserResult {
4461
+ * success: boolean;
4462
+ * data: User;
4463
+ * }
4464
+ *
4465
+ * const context: ExecutorContextInterface<UserParams, UserResult> =
4466
+ * new ExecutorContextImpl({ userId: 123, action: 'fetch' });
4467
+ *
4468
+ * console.log(context.parameters.userId); // 123
4469
+ * ```
4470
+ *
4471
+ * @example In plugin hooks
4472
+ * ```typescript
4473
+ * const plugin: LifecyclePluginInterface<ExecutorContextInterface<UserParams, UserResult>> = {
4474
+ * pluginName: 'logger',
4475
+ *
4476
+ * onBefore: async (ctx) => {
4477
+ * console.log('Starting with:', ctx.parameters);
4478
+ * // Add timestamp to parameters
4479
+ * ctx.setParameters({
4480
+ * ...ctx.parameters,
4481
+ * timestamp: Date.now()
4482
+ * });
4483
+ * },
4484
+ *
4485
+ * onAfter: async (ctx, result) => {
4486
+ * console.log('Completed with:', ctx.returnValue);
4487
+ * return result;
4488
+ * },
4489
+ *
4490
+ * onError: async (ctx, error) => {
4491
+ * console.error('Failed with:', ctx.error);
4492
+ * throw error;
4493
+ * }
4494
+ * };
4495
+ * ```
4496
+ *
4497
+ * @example Parameter transformation
4498
+ * ```typescript
4499
+ * const executor = new LifecycleExecutor();
4500
+ *
4501
+ * executor.use({
4502
+ * pluginName: 'validator',
4503
+ * onBefore: async (ctx) => {
4504
+ * // Validate and transform parameters
4505
+ * const validated = validateParams(ctx.parameters);
4506
+ * ctx.setParameters(validated);
4507
+ * }
4508
+ * });
4509
+ *
4510
+ * const result = await executor.exec(
4511
+ * { userId: '123' }, // String input
4512
+ * async (ctx) => {
4513
+ * // ctx.parameters.userId is now validated and transformed
4514
+ * return await fetchUser(ctx.parameters.userId);
4515
+ * }
4516
+ * );
4517
+ * ```
4518
+ *
4519
+ * @example Error handling
4520
+ * ```typescript
4521
+ * executor.use({
4522
+ * pluginName: 'errorHandler',
4523
+ * onError: async (ctx, error) => {
4524
+ * // Access error from context
4525
+ * console.error('Task failed:', ctx.error);
4526
+ *
4527
+ * // Transform error
4528
+ * if (ctx.error instanceof NetworkError) {
4529
+ * throw new UserFriendlyError('Network connection failed');
4530
+ * }
4531
+ * throw error;
4532
+ * }
4533
+ * });
4534
+ * ```
4535
+ *
4536
+ * @example With unknown return type
4537
+ * ```typescript
4538
+ * // When return type is not known in advance
4539
+ * const context: ExecutorContextInterface<UserParams, unknown> =
4540
+ * new ExecutorContextImpl(params);
4541
+ * ```
4542
+ *
4543
+ * @example Extended runtimes
4544
+ * ```typescript
4545
+ * interface CustomRuntimes extends HookRuntimes {
4546
+ * executionTime: number;
4547
+ * memoryUsage: number;
4548
+ * cacheHits: number;
4549
+ * }
4550
+ *
4551
+ * const context: ExecutorContextInterface<UserParams, UserResult, CustomRuntimes> =
4552
+ * new ExecutorContextImpl(params);
4553
+ *
4554
+ * // Access custom runtime metadata
4555
+ * console.log(context.runtimes.executionTime);
4556
+ * ```
4557
+ *
4558
+ * @see {@link ExecutorHookRuntimesInterface} for runtime metadata interface
4559
+ * @see {@link ExecutorContextImpl} for default implementation
4560
+ */
4561
+ interface ExecutorContextInterface<T, R = unknown, RuntimesType extends HookRuntimes = HookRuntimes> extends ExecutorHookRuntimesInterface<RuntimesType> {
4562
+ /**
4563
+ * Read-only access to execution parameters
4564
+ *
4565
+ * Provides immutable access to the current parameters. To modify parameters,
4566
+ * use `setParameters()` method which ensures safe cloning.
4567
+ *
4568
+ * @example
4569
+ * ```typescript
4570
+ * console.log(ctx.parameters.userId);
4571
+ * console.log(ctx.parameters.action);
4572
+ * ```
4573
+ */
4574
+ readonly parameters: T;
4575
+ /**
4576
+ * Current error state, if any
4577
+ *
4578
+ * Contains the error that occurred during task execution. Only populated
4579
+ * when an error is thrown. Accessible in error handling hooks.
4580
+ *
4581
+ * @example
4582
+ * ```typescript
4583
+ * onError: (ctx, error) => {
4584
+ * if (ctx.error instanceof NetworkError) {
4585
+ * console.log('Network error occurred');
4586
+ * }
4587
+ * }
4588
+ * ```
4589
+ */
4590
+ readonly error: unknown;
4591
+ /**
4592
+ * Task return value
4593
+ *
4594
+ * Contains the value returned by the task after successful execution.
4595
+ * Undefined until the task completes. Accessible in afterHooks for
4596
+ * result transformation.
4597
+ *
4598
+ * @example
4599
+ * ```typescript
4600
+ * onAfter: (ctx, result) => {
4601
+ * console.log('Task returned:', ctx.returnValue);
4602
+ * // Transform result
4603
+ * return { ...result, timestamp: Date.now() };
4604
+ * }
4605
+ * ```
4606
+ */
4607
+ readonly returnValue: R | undefined;
4608
+ /**
4609
+ * Set the error state
4610
+ *
4611
+ * Stores an error in the context for access by error handling plugins.
4612
+ * Accepts any type of error value and converts it to `ExecutorError`.
4613
+ * This matches the behavior of JavaScript's catch clause which can catch any type.
4614
+ *
4615
+ * @param error - Error to set (can be any type: Error, string, object, etc.)
4616
+ *
4617
+ * @example
4618
+ * ```typescript
4619
+ * try {
4620
+ * await riskyOperation();
4621
+ * } catch (error) {
4622
+ * ctx.setError(error);
4623
+ * }
4624
+ * ```
4625
+ */
4626
+ setError(error: unknown): void;
4627
+ /**
4628
+ * Set the return value
4629
+ *
4630
+ * Stores the task's return value in the context. Typically called by
4631
+ * the executor after task completion, but can be used by plugins to
4632
+ * override the return value.
4633
+ *
4634
+ * @param value - Return value to set
4635
+ *
4636
+ * @example
4637
+ * ```typescript
4638
+ * onAfter: (ctx, result) => {
4639
+ * // Override return value
4640
+ * ctx.setReturnValue({ ...result, enhanced: true });
4641
+ * return ctx.returnValue;
4642
+ * }
4643
+ * ```
4644
+ */
4645
+ setReturnValue(value: unknown): void;
4646
+ /**
4647
+ * Update parameters (clones internally for safety)
4648
+ *
4649
+ * Updates the execution parameters with a new value. The parameters are
4650
+ * cloned internally to prevent accidental mutation. This ensures that
4651
+ * plugins cannot inadvertently affect each other's parameter views.
4652
+ *
4653
+ * @param params - New parameters to set
4654
+ *
4655
+ * @example
4656
+ * ```typescript
4657
+ * onBefore: (ctx) => {
4658
+ * // Add authentication token
4659
+ * ctx.setParameters({
4660
+ * ...ctx.parameters,
4661
+ * authToken: getAuthToken()
4662
+ * });
4663
+ * }
4664
+ * ```
4665
+ *
4666
+ * @example Parameter validation
4667
+ * ```typescript
4668
+ * onBefore: (ctx) => {
4669
+ * const validated = validateAndTransform(ctx.parameters);
4670
+ * ctx.setParameters(validated);
4671
+ * }
4672
+ * ```
4673
+ */
4674
+ setParameters(params: T): void;
4675
+ }
4676
+
4677
+ type LifecycleErrorResult = ExecutorError | Error | void;
4678
+ type LifecycleExecResult<R, Param> = R | ExecutorTask<R, Param> | void;
4679
+ /**
4680
+ * Lifecycle plugin interface for executor plugins
4681
+ *
4682
+ * Purpose:
4683
+ * This interface extends ExecutorPluginInterface and adds standardized lifecycle hook methods
4684
+ * that plugins can implement to participate in the executor's execution pipeline.
4685
+ * It serves as the default plugin type for LifecycleExecutor.
4686
+ *
4687
+ * Key Lifecycle Hooks:
4688
+ *
4689
+ * - onBefore: Pre-execution hook that can modify parameters
4690
+ * - Can return new parameters to update context
4691
+ * - Supports both sync and async return values
4692
+ * - More flexible than direct parameter modification
4693
+ *
4694
+ * - onSuccess: Post-execution hook for result processing
4695
+ * - Executed after successful task completion
4696
+ * - Can transform or log results
4697
+ * - Supports both sync and async execution
4698
+ *
4699
+ * - onError: Error handling hook
4700
+ * - Executed when errors occur
4701
+ * - Can handle, transform, or log errors
4702
+ * - Supports both sync and async execution
4703
+ *
4704
+ * - onExec: Task modification hook
4705
+ * - Can modify or wrap the task
4706
+ * - Supports both sync and async task modifications
4707
+ *
4708
+ * - onFinally: Cleanup hook
4709
+ * - Always executed after task completion
4710
+ * - Guaranteed to run regardless of success or failure
4711
+ * - Supports both sync and async execution
4712
+ *
4713
+ * Enhanced onBefore Hook:
4714
+ * - Return Value Support: Can return new parameters to update context
4715
+ * ```typescript
4716
+ * onBefore: (ctx) => {
4717
+ * // Return new parameters - automatically updates context
4718
+ * return { ...ctx.parameters, newField: 'value' };
4719
+ * }
4720
+ * ```
4721
+ *
4722
+ * - Type Safety: Return type inferred from context parameter type
4723
+ * - TypeScript automatically infers correct return type
4724
+ * - Compile-time type checking
4725
+ * - Better IDE support
4726
+ *
4727
+ * Default Plugin Type for LifecycleExecutor:
4728
+ * - Type Constraint: LifecycleExecutor defaults to this interface
4729
+ * - Ensures plugins implement lifecycle hooks
4730
+ * - Better type safety
4731
+ * - Clearer plugin contract
4732
+ *
4733
+ * - Backward Compatibility: Extends ExecutorPluginInterface
4734
+ * - Compatible with existing plugin implementations
4735
+ * - Can be used with other executor types
4736
+ * - Gradual migration path
4737
+ *
4738
+ * Usage with LifecycleExecutor:
4739
+ *
4740
+ * Default Usage (Recommended):
4741
+ * ```typescript
4742
+ * const executor = new LifecycleExecutor();
4743
+ * // Plugin type defaults to LifecyclePluginInterface
4744
+ * executor.use({
4745
+ * pluginName: 'myPlugin',
4746
+ * enabled: () => true,
4747
+ * onBefore: (ctx) => {
4748
+ * return { ...ctx.parameters, timestamp: Date.now() };
4749
+ * }
4750
+ * });
4751
+ * ```
4752
+ *
4753
+ * Explicit Type Usage:
4754
+ * ```typescript
4755
+ * interface MyPlugin extends LifecyclePluginInterface<ExecutorContextInterface<MyParams, MyResult>> {
4756
+ * customMethod(): void;
4757
+ * }
4758
+ *
4759
+ * const executor = new LifecycleExecutor<
4760
+ * ExecutorContextInterface<MyParams, MyResult>,
4761
+ * MyPlugin
4762
+ * >();
4763
+ * ```
4764
+ *
4765
+ * Benefits:
4766
+ * - Type Safety: Stronger type constraints than generic ExecutorPluginInterface
4767
+ * - Clear Contract: Explicit lifecycle hook definitions
4768
+ * - Better IDE Support: Improved autocomplete and type checking
4769
+ * - Parameter Safety: Supports safe parameter updates via return values
4770
+ * - Unified API: Consistent interface across all lifecycle hooks
4771
+ *
4772
+ * @since 3.0.0
4773
+ * @template Ctx - Type of executor context interface
4774
+ *
4775
+ * @example Basic lifecycle plugin
4776
+ * ```typescript
4777
+ * const plugin: LifecyclePluginInterface<ExecutorContextInterface<UserParams, UserResult>> = {
4778
+ * pluginName: 'userPlugin',
4779
+ * enabled: () => true,
4780
+ * onBefore: (ctx) => {
4781
+ * // Modify parameters via return value
4782
+ * return { ...ctx.parameters, timestamp: Date.now() };
4783
+ * },
4784
+ * onSuccess: (ctx) => {
4785
+ * console.log('Task completed:', ctx.returnValue);
4786
+ * },
4787
+ * onError: (ctx) => {
4788
+ * console.error('Error occurred:', ctx.error);
4789
+ * }
4790
+ * };
4791
+ * ```
4792
+ *
4793
+ * @example onBefore returning new parameters (async)
4794
+ * ```typescript
4795
+ * const plugin: LifecyclePluginInterface<ExecutorContextInterface<ApiParams, ApiResult>> = {
4796
+ * onBefore: async (ctx) => {
4797
+ * const apiKey = await fetchApiKey();
4798
+ * // Return new parameters - automatically updates context
4799
+ * return { ...ctx.parameters, apiKey };
4800
+ * }
4801
+ * };
4802
+ * ```
4803
+ *
4804
+ * @see LifecycleExecutor - Executor that uses this as default plugin type
4805
+ * @see ExecutorPluginInterface - Base plugin interface
4806
+ * @see ExecutorContextInterface - Context interface used by plugins
4807
+ *
4808
+ * @category Plugin
4809
+ */
4810
+ interface LifecyclePluginInterface<Ctx extends ExecutorContextInterface<unknown, unknown>, Result = Ctx['returnValue'], Param = Ctx['parameters']> extends ExecutorPluginInterface<Ctx> {
4811
+ /**
4812
+ * Hook executed before the main task
4813
+ * Can modify the input data before it reaches the task
4814
+ *
4815
+ * Return value behavior:
4816
+ * - If returns a value (non-void), it will be used to update context parameters
4817
+ * - If returns void or undefined, parameters remain unchanged
4818
+ * - Supports both sync and async return values
4819
+ *
4820
+ * @param ctx - Execution context
4821
+ * @returns Modified parameters (will update context parameters), void, or Promise of either
4822
+ */
4823
+ onBefore?(ctx: Ctx): Param | Promise<Param> | void | Promise<void>;
4824
+ /**
4825
+ * Hook executed after successful task completion
4826
+ * Can transform the task result
4827
+ *
4828
+ * @param ctx - Execution context
4829
+ * @returns void or Promise<void>
4830
+ */
4831
+ onSuccess?(ctx: Ctx): void | Promise<void>;
4832
+ /**
4833
+ * Error handling hook
4834
+ * - For `exec`: returning a value or throwing will break the chain
4835
+ * - For `execNoError`: returning a value or throwing will return the error
4836
+ *
4837
+ * Because `onError` can break the chain, best practice is each plugin only handle plugin related error
4838
+ *
4839
+ * @param ctx - Execution context containing error information
4840
+ * @returns ExecutorError, Error, void, or Promise of either
4841
+ */
4842
+ onError?(ctx: Ctx): LifecycleErrorResult | Promise<LifecycleErrorResult>;
4843
+ /**
4844
+ * Custom execution logic hook
4845
+ *
4846
+ * Purpose:
4847
+ * Allows plugins to intercept, wrap, or replace the task execution.
4848
+ * Plugins can return a value directly, return a new task function, or execute
4849
+ * the task within the hook.
4850
+ *
4851
+ * Return value behavior:
4852
+ * - If returns a function (ExecutorTask): The function will be executed as the new task
4853
+ * - If returns any other value: The value will be used as the task result (skips task execution)
4854
+ * - Supports both sync and async return values
4855
+ *
4856
+ * Type inference:
4857
+ * - The return type `R` is automatically inferred from the task parameter
4858
+ * - Return values are type-safe and match the task's return type
4859
+ * - TypeScript can infer types from return statements without explicit annotations
4860
+ *
4861
+ * Use cases:
4862
+ * - Return a wrapped task function to add middleware behavior
4863
+ * - Return a direct value to bypass task execution
4864
+ * - Execute the task with custom logic and return the result
4865
+ *
4866
+ * @template R - Return type of the task (automatically inferred from task parameter)
4867
+ * @param ctx - Execution context
4868
+ * @param task - Original task to be executed
4869
+ * @returns Task result (type R), modified task function, or Promise of either
4870
+ *
4871
+ * @example Return a direct value (bypass task) - type automatically inferred
4872
+ * ```typescript
4873
+ * onExec: async () => {
4874
+ * return 'intercepted-result'; // Type inferred as Promise<string>
4875
+ * }
4876
+ * ```
4877
+ *
4878
+ * @example Return a wrapped task function
4879
+ * ```typescript
4880
+ * onExec: (ctx, task) => {
4881
+ * // Return a new task function that wraps the original
4882
+ * return async (wrappedCtx) => {
4883
+ * console.log('Before task execution');
4884
+ * const result = await task(wrappedCtx);
4885
+ * console.log('After task execution');
4886
+ * return result;
4887
+ * };
4888
+ * }
4889
+ * ```
4890
+ *
4891
+ * @example Return a direct value (bypass task)
4892
+ * ```typescript
4893
+ * onExec: (ctx, task) => {
4894
+ * // Return cached result, skip task execution
4895
+ * if (cache.has(ctx.parameters.id)) {
4896
+ * return cache.get(ctx.parameters.id);
4897
+ * }
4898
+ * // Or execute task and return result
4899
+ * return task(ctx);
4900
+ * }
4901
+ * ```
4902
+ *
4903
+ * 如果需要手动覆盖返回类型,可以使用提供的 R 泛型手动推断类型,但是这样不够安全,
4904
+ * 未来可能会加入接口类型的泛型
4905
+ *
4906
+ * @example 使用手动推断类型
4907
+ * ```typescript
4908
+ * interface TestResult {
4909
+ * data: string;
4910
+ * processed?: boolean;
4911
+ * }
4912
+ *
4913
+ * type TestContext = ExecutorContextInterface<TestParams>;
4914
+ *
4915
+ * const plugin: LifecyclePluginInterface<TestContext> = {
4916
+ * pluginName: 'plugin',
4917
+ * onExec: async <R>(ctx, task) => {
4918
+ * const result = await task(ctx);
4919
+ * return `wrapped: ${result}` as R;
4920
+ * }
4921
+ * };
4922
+ * ```
4923
+ */
4924
+ onExec?: (ctx: Ctx, task: ExecutorTask<Result, Param>) => LifecycleExecResult<Result, Param> | Promise<LifecycleExecResult<Result, Param>>;
4925
+ /**
4926
+ * Hook executed in finally block after task execution
4927
+ *
4928
+ * Purpose:
4929
+ * Allows plugins to perform cleanup operations that must run regardless
4930
+ * of whether the task succeeded or failed. Supports both sync and async execution.
4931
+ *
4932
+ * Execution Guarantees:
4933
+ * - Always executed after task completion (success or error)
4934
+ * - Executed in finally block, ensuring cleanup even if errors occur
4935
+ * - Runs after onSuccess or onError hooks
4936
+ * - Cannot prevent error propagation
4937
+ *
4938
+ * Use Cases:
4939
+ * - Resource cleanup
4940
+ * - Logging completion status
4941
+ * - Resetting state
4942
+ * - Closing connections
4943
+ * - Finalizing transactions
4944
+ *
4945
+ * @param ctx - Execution context (may contain error if task failed)
4946
+ * @returns void or Promise<void>
4947
+ *
4948
+ * @example Resource cleanup
4949
+ * ```typescript
4950
+ * onFinally: async (ctx) => {
4951
+ * if (ctx.parameters.connection) {
4952
+ * await ctx.parameters.connection.close();
4953
+ * }
4954
+ * }
4955
+ * ```
4956
+ *
4957
+ * @example Logging completion
4958
+ * ```typescript
4959
+ * onFinally: (ctx) => {
4960
+ * const status = ctx.error ? 'failed' : 'succeeded';
4961
+ * console.log(`Task ${status}`);
4962
+ * }
4963
+ * ```
4964
+ */
4965
+ onFinally?(ctx: Ctx): void | Promise<void>;
4966
+ }
4967
+
4968
+ /**
4969
+ * Base implementation of ExecutorContextInterface that integrates ContextHandler functionality
4970
+ *
4971
+ * ## Core Concept
4972
+ * Provides a complete implementation of the executor context interface, integrating
4973
+ * all context management functionality that was previously handled by ContextHandler.
4974
+ * This eliminates the need for a separate ContextHandler class and centralizes
4975
+ * all context-related operations in a single class.
4976
+ *
4977
+ * Key Differences from Original Implementation:
4978
+ *
4979
+ * No Separate ContextHandler:
4980
+ * - Integrated Functionality: All ContextHandler methods integrated into context
4981
+ * - Original: Separate ContextHandler class managed context state
4982
+ * - New: All functionality in ExecutorContextImpl
4983
+ * - Benefits: Simpler API, fewer dependencies, clearer ownership
4984
+ *
4985
+ * - Direct Method Access: All methods available directly on context
4986
+ * - No need to pass context to handler methods
4987
+ * - More intuitive API
4988
+ * - Better encapsulation
4989
+ *
4990
+ * Parameter Handling (Reference-Based):
4991
+ * - **No Cloning**: Parameters are stored by reference, not cloned
4992
+ * - Original: Parameters were cloned automatically
4993
+ * - New: Parameters are used directly (zero overhead)
4994
+ * - Benefits: Better performance, user control, predictable behavior
4995
+ *
4996
+ * - **User Responsibility**: Users must clone parameters if isolation is needed
4997
+ * - If you need isolation: `new ExecutorContextImpl({ ...params })`
4998
+ * - If you don't need isolation: `new ExecutorContextImpl(params)`
4999
+ * - Trade-off: More control vs. more responsibility
5000
+ *
5001
+ * - **Performance**: Zero cloning overhead
5002
+ * - No Object.assign or spread operations
5003
+ * - No memory allocation for parameter copies
5004
+ * - Ideal for high-performance scenarios
5005
+ *
5006
+ * Enhanced Runtime Tracking:
5007
+ * - Integrated Tracking: All runtime tracking in context
5008
+ * - Plugin execution metadata
5009
+ * - Hook execution tracking
5010
+ * - Chain breaking state
5011
+ * - Return value tracking
5012
+ *
5013
+ * - Better Debugging: Comprehensive runtime information
5014
+ * - Track which plugins executed
5015
+ * - Track execution order
5016
+ * - Track return values
5017
+ * - Track chain breaking conditions
5018
+ *
5019
+ * Improved API Design:
5020
+ * - Consistent Naming: All methods follow consistent naming conventions
5021
+ * - Type Safety: Strong typing throughout
5022
+ * - Clear Responsibilities: Each method has a single, clear purpose
5023
+ * - Better Documentation: Comprehensive JSDoc comments
5024
+ *
5025
+ * Main Features:
5026
+ * - Context state management: Manages parameters, error, and return value
5027
+ * - Plugin runtime tracking: Tracks plugin execution metadata
5028
+ * - Chain control: Manages execution chain breaking conditions
5029
+ * - Error handling: Context error state management
5030
+ * - Hook validation: Checks plugin hook availability and enablement
5031
+ * - Reference-based parameters: No automatic cloning (user control)
5032
+ * - High performance: Zero overhead parameter handling
5033
+ *
5034
+ * Parameter Handling (Important):
5035
+ *
5036
+ * **No Automatic Cloning**:
5037
+ * - Parameters are stored by reference
5038
+ * - Modifications affect the original object
5039
+ * - Users must clone parameters themselves if isolation is needed
5040
+ *
5041
+ * **Usage Examples**:
5042
+ * ```typescript
5043
+ * // Without isolation (parameters will be modified)
5044
+ * const params = { userId: 123, data: 'test' };
5045
+ * const context = new ExecutorContextImpl(params);
5046
+ * context.setParameters({ userId: 456 });
5047
+ * console.log(params.userId); // 456 - original modified
5048
+ *
5049
+ * // With isolation (clone parameters first)
5050
+ * const params = { userId: 123, data: 'test' };
5051
+ * const context = new ExecutorContextImpl({ ...params }); // shallow clone
5052
+ * context.setParameters({ userId: 456 });
5053
+ * console.log(params.userId); // 123 - original unchanged
5054
+ * ```
5055
+ *
5056
+ * **Performance**:
5057
+ * - Constructor: Zero overhead (no cloning)
5058
+ * - Getter: Direct return (zero overhead)
5059
+ * - setParameters: Zero overhead (no cloning)
5060
+ *
5061
+ * Design Considerations:
5062
+ * - Integrates ContextHandler functionality directly into the context
5063
+ * - Provides all methods needed for executor plugin lifecycle management
5064
+ * - Maintains backward compatibility with existing ExecutorContext interface
5065
+ * - Eliminates the need for separate ContextHandler instance
5066
+ * - Delegates parameter isolation responsibility to users
5067
+ * - Optimized for maximum performance with zero-overhead parameter handling
5068
+ *
5069
+ * @since 3.0.0
5070
+ * @template T - Type of context parameters
5071
+ *
5072
+ * @example Basic usage
5073
+ * ```typescript
5074
+ * const context = new ExecutorContextImpl({ userId: 123, data: 'test' });
5075
+ *
5076
+ * // Use context methods directly
5077
+ * context.setReturnValue('result');
5078
+ * context.runtimes(plugin, 'onBefore', 0);
5079
+ * if (context.shouldBreakChain()) {
5080
+ * // Handle chain breaking
5081
+ * }
5082
+ * ```
5083
+ *
5084
+ * @example Parameter isolation
5085
+ * ```typescript
5086
+ * const originalParams = { value: 'original' };
5087
+ * const context = new ExecutorContextImpl(originalParams);
5088
+ *
5089
+ * // Parameters are cloned - modifications don't affect original
5090
+ * const params = context.parameters;
5091
+ * params.value = 'modified';
5092
+ * expect(originalParams.value).toBe('original'); // Original unchanged
5093
+ * ```
5094
+ *
5095
+ * @example With error handling
5096
+ * ```typescript
5097
+ * const context = new ExecutorContextImpl(data);
5098
+ *
5099
+ * try {
5100
+ * // Execute some operation
5101
+ * } catch (error) {
5102
+ * context.setError(new ExecutorError('ERROR_CODE', error));
5103
+ * }
5104
+ *
5105
+ * if (context.error) {
5106
+ * // Handle error
5107
+ * }
5108
+ * ```
5109
+ *
5110
+ * @see ExecutorContextInterface - Interface that this class implements
5111
+ * @see LifecycleExecutor - Executor that uses this context implementation
5112
+ *
5113
+ * @category ExecutorContextImpl
5114
+ */
5115
+ declare class ExecutorContextImpl<T, R = unknown, RuntimesType extends HookRuntimes = HookRuntimes> implements ExecutorContextInterface<T, R, RuntimesType> {
5116
+ private _parameters;
5117
+ private _error;
5118
+ private _returnValue?;
5119
+ /**
5120
+ * Creates a new ExecutorContextImpl instance
5121
+ *
5122
+ * **Important**: Parameters are stored by reference, not cloned.
5123
+ * If you need parameter isolation, clone them before passing to the constructor.
5124
+ *
5125
+ * @param parameters - The initial parameters for the context
5126
+ *
5127
+ * @example Without isolation (parameters will be modified)
5128
+ * ```typescript
5129
+ * const params = { value: 1 };
5130
+ * const context = new ExecutorContextImpl(params);
5131
+ * context.setParameters({ value: 2 });
5132
+ * console.log(params.value); // 2 - original object is modified
5133
+ * ```
5134
+ *
5135
+ * @example With isolation (clone parameters first)
5136
+ * ```typescript
5137
+ * const params = { value: 1 };
5138
+ * const context = new ExecutorContextImpl({ ...params }); // shallow clone
5139
+ * context.setParameters({ value: 2 });
5140
+ * console.log(params.value); // 1 - original object is unchanged
5141
+ * ```
5142
+ */
5143
+ constructor(parameters: T);
5144
+ /**
5145
+ * Get the context parameters
5146
+ *
5147
+ * **Important**: Returns the parameters by reference.
5148
+ * Modifications to the returned object will affect the context's internal state.
5149
+ *
5150
+ * @override
5151
+ * @returns The parameters object (by reference)
5152
+ */
5153
+ get parameters(): T;
5154
+ /**
5155
+ * Get the error, if any
5156
+ *
5157
+ * @override
5158
+ * @returns The error, if any
5159
+ */
5160
+ get error(): unknown;
5161
+ /**
5162
+ * Get the return value, if any
5163
+ *
5164
+ * @override
5165
+ * @returns The return value, if any
5166
+ */
5167
+ get returnValue(): R | undefined;
5168
+ /**
5169
+ * Get read-only snapshot of hooks runtime information
5170
+ *
5171
+ * Core concept:
5172
+ * Provides safe read-only access to runtime tracking information.
5173
+ * Returns a frozen shallow copy to prevent accidental modifications.
5174
+ *
5175
+ * Security features:
5176
+ * - Stored in WeakMap, truly private (cannot access via ._hooksRuntimes)
5177
+ * - Returns a new frozen object (not the internal reference)
5178
+ * - Object is frozen to prevent modifications
5179
+ * - Setter throws error to prevent assignment
5180
+ *
5181
+ * Why WeakMap?
5182
+ * - TypeScript's `private` is only compile-time protection
5183
+ * - JavaScript runtime can still access `._hooksRuntimes`
5184
+ * - WeakMap provides true runtime privacy
5185
+ * - No way to access the internal state from outside
5186
+ *
5187
+ * @override
5188
+ * @returns Frozen shallow copy of hook runtime state
5189
+ *
5190
+ * @example Safe read access
5191
+ * ```typescript
5192
+ * const runtimes = context.hooksRuntimes;
5193
+ * console.log(`Hook ${runtimes.hookName} executed ${runtimes.times} times`);
5194
+ * ```
5195
+ *
5196
+ * @example Modification attempts fail
5197
+ * ```typescript
5198
+ * const runtimes = context.hooksRuntimes;
5199
+ * runtimes.times = 10; // Error: Cannot assign to read only property
5200
+ * context.hooksRuntimes = {}; // Error: hooksRuntimes is read-only
5201
+ * context._hooksRuntimes; // undefined - truly private!
5202
+ * ```
5203
+ */
5204
+ get hooksRuntimes(): Readonly<RuntimesType>;
5205
+ /**
5206
+ * Set error in context
5207
+ *
5208
+ * Automatically converts standard Error objects to ExecutorError for consistency.
5209
+ * If the error is already an ExecutorError, it is stored as-is.
5210
+ * If the error is a standard Error, it is wrapped in an ExecutorError with id 'EXECUTOR_ERROR'.
5211
+ *
5212
+ * @override
5213
+ * @param error - The error to set in context (ExecutorError or standard Error)
5214
+ *
5215
+ * @example With ExecutorError
5216
+ * ```typescript
5217
+ * context.setError(new ExecutorError('VALIDATION_ERROR', 'Invalid input'));
5218
+ * console.log(context.error.id); // 'VALIDATION_ERROR'
5219
+ * ```
5220
+ *
5221
+ * @example With standard Error (auto-converted)
5222
+ * ```typescript
5223
+ * try {
5224
+ * JSON.parse('invalid');
5225
+ * } catch (error) {
5226
+ * context.setError(error); // Auto-converted to ExecutorError
5227
+ * console.log(context.error.id); // 'EXECUTOR_ERROR'
5228
+ * console.log(context.error.cause); // Original SyntaxError
5229
+ * }
5230
+ * ```
5231
+ */
5232
+ setError(error: unknown): void;
5233
+ /**
5234
+ * Set return value in context
5235
+ *
5236
+ * @override
5237
+ * @param value - The value to set as return value
5238
+ */
5239
+ setReturnValue(value: R): void;
5240
+ /**
5241
+ * Set parameters in context
5242
+ *
5243
+ * **Important**: Parameters are stored by reference, not cloned.
5244
+ * The provided parameters object will be used directly.
5245
+ *
5246
+ * @override
5247
+ * @param params - The parameters to set (stored by reference)
5248
+ *
5249
+ * @example
5250
+ * ```typescript
5251
+ * const newParams = { value: 2 };
5252
+ * context.setParameters(newParams);
5253
+ * // context.parameters === newParams (same reference)
5254
+ * ```
5255
+ */
5256
+ setParameters(params: T): void;
5257
+ /**
5258
+ * Reset hooks runtime state to initial values
5259
+ *
5260
+ * Core concept:
5261
+ * Clears all runtime tracking information for fresh execution
5262
+ *
5263
+ * Reset operations:
5264
+ * - Clears plugin name and hook name
5265
+ * - Resets return value and chain breaking flags
5266
+ * - Resets execution counter and index
5267
+ *
5268
+ * @override
5269
+ */
5270
+ resetHooksRuntimes(hookName?: string): void;
5271
+ /**
5272
+ * Reset entire context to initial state
5273
+ *
5274
+ * Core concept:
5275
+ * Complete context cleanup for new execution cycle
5276
+ *
5277
+ * Reset operations:
5278
+ * - Resets hooks runtime state
5279
+ * - Clears return value
5280
+ * - Clears error state
5281
+ *
5282
+ * @override
5283
+ */
5284
+ reset(): void;
5285
+ /**
5286
+ * Check if a plugin hook should be skipped
5287
+ * Returns true if the hook should be skipped (invalid or disabled)
5288
+ *
5289
+ * Core concept:
5290
+ * Plugin hook validation and enablement checking
5291
+ *
5292
+ * Validation criteria:
5293
+ * - Hook method exists and is callable
5294
+ * - Plugin is enabled for the specific hook
5295
+ * - Plugin enablement function returns true
5296
+ *
5297
+ * @override
5298
+ * @template Ctx - Type of task context
5299
+ * @param plugin - The plugin to check
5300
+ * @param hookName - The name of the hook to validate
5301
+ * @returns True if the hook should be skipped, false otherwise
5302
+ */
5303
+ shouldSkipPluginHook<Ctx extends ExecutorContextInterface<unknown, unknown>>(plugin: ExecutorPluginInterface<Ctx>, hookName: string): boolean;
5304
+ /**
5305
+ * Update runtime tracking information for plugin execution
5306
+ *
5307
+ * Core concept:
5308
+ * Track plugin execution metadata for debugging and flow control.
5309
+ * Creates a new runtime object with merged updates to ensure immutability.
5310
+ *
5311
+ * Security:
5312
+ * - Always creates a new object (immutable updates)
5313
+ * - Stored in WeakMap (truly private)
5314
+ * - Cannot be accessed or modified from outside
5315
+ *
5316
+ * Tracking information:
5317
+ * - Current plugin name
5318
+ * - Current hook name
5319
+ * - Execution counter (times)
5320
+ * - Plugin index in execution chain
5321
+ *
5322
+ * @override
5323
+ * @param updates - Partial runtime updates to merge
5324
+ * @example
5325
+ * ```typescript
5326
+ * context.runtimes({
5327
+ * pluginName: 'testPlugin',
5328
+ * hookName: 'onBefore',
5329
+ * times: 1,
5330
+ * pluginIndex: 0
5331
+ * });
5332
+ * ```
5333
+ */
5334
+ runtimes(updates: Partial<HookRuntimes>): void;
5335
+ /**
5336
+ * Set return value in context runtime tracking
5337
+ *
5338
+ * Core concept:
5339
+ * Store plugin hook return value for chain control and debugging.
5340
+ * Creates a new runtime object with updated return value.
5341
+ *
5342
+ * Security:
5343
+ * - Creates new object (immutable update)
5344
+ * - Stored in WeakMap (truly private)
5345
+ *
5346
+ * Usage scenarios:
5347
+ * - Track plugin hook return values
5348
+ * - Enable chain breaking based on return values
5349
+ * - Debug plugin execution flow
5350
+ *
5351
+ * @override
5352
+ * @param returnValue - The value to set as return value
5353
+ */
5354
+ runtimeReturnValue(returnValue: unknown): void;
5355
+ /**
5356
+ * Check if the execution chain should be broken
5357
+ *
5358
+ * Core concept:
5359
+ * Chain breaking control for plugin execution flow
5360
+ *
5361
+ * Chain breaking scenarios:
5362
+ * - Plugin explicitly sets breakChain flag
5363
+ * - Error conditions requiring immediate termination
5364
+ * - Business logic requiring early exit
5365
+ *
5366
+ * @override
5367
+ * @returns True if the chain should be broken, false otherwise
5368
+ */
5369
+ shouldBreakChain(): boolean;
5370
+ /**
5371
+ * Check if the execution chain should be broken due to return value
5372
+ *
5373
+ * Core concept:
5374
+ * Return value-based chain breaking control
5375
+ *
5376
+ * Usage scenarios:
5377
+ * - Plugin returns a value that should terminate execution
5378
+ * - Error handling hooks return error objects
5379
+ * - Business logic requires return value-based flow control
5380
+ *
5381
+ * @override
5382
+ * @returns True if the chain should be broken due to return value, false otherwise
5383
+ */
5384
+ shouldBreakChainOnReturn(): boolean;
5385
+ /**
5386
+ * Check if execution should continue on error
5387
+ *
5388
+ * Core concept:
5389
+ * Determines whether to continue executing subsequent plugins when a plugin hook
5390
+ * throws an error, enabling resilient execution pipelines
5391
+ *
5392
+ * @override
5393
+ * @returns True if execution should continue on error, false otherwise
5394
+ */
5395
+ shouldContinueOnError(): boolean;
5396
+ }
5397
+
5398
+ /**
5399
+ * Enhanced script context that provides environment management and configuration utilities
5400
+ *
5401
+ * Core concept:
5402
+ * Provides a comprehensive script execution environment with integrated
5403
+ * configuration management, environment variable handling, logging,
5404
+ * and shell command execution capabilities.
5405
+ *
5406
+ * Main features:
5407
+ * - Environment management: Integrated environment variable handling
5408
+ * - Automatic loading of .env files with configurable order
5409
+ * - Type-safe environment variable access with defaults
5410
+ * - Support for environment-specific configurations
5411
+ * - Integration with fe-config environment settings
5412
+ *
5413
+ * - Configuration management: Unified configuration access and merging
5414
+ * - Script-specific configuration sections
5415
+ * - Deep merging with default values
5416
+ * - Type-safe option access with nested path support
5417
+ * - Configuration validation and fallback handling
5418
+ *
5419
+ * - Logging system: Structured logging with timestamp formatting
5420
+ * - Configurable verbosity levels
5421
+ * - Timestamp formatting with timezone support
5422
+ * - Logger name identification for multi-script environments
5423
+ * - Console output with structured formatting
5424
+ *
5425
+ * - Shell integration: Command execution with dry run support
5426
+ * - Safe command execution with error handling
5427
+ * - Dry run mode for testing and validation
5428
+ * - Integrated logging for command output
5429
+ * - Support for custom execution functions
5430
+ *
5431
+ * Design considerations:
5432
+ * - Uses lodash merge for deep configuration merging
5433
+ * - Supports environment file loading with configurable order
5434
+ * - Provides type-safe option access with fallback values
5435
+ * - Implements proper error handling for missing configurations
5436
+ * - Maintains backward compatibility with existing interfaces
5437
+ * - Supports both development and production environments
4243
5438
  *
4244
5439
  * Performance optimizations:
4245
5440
  * - Lazy environment initialization
@@ -4321,6 +5516,25 @@ declare class ScriptContext<Opt extends ScriptSharedInterface> extends ExecutorC
4321
5516
  * detailed information display.
4322
5517
  */
4323
5518
  readonly verbose: boolean;
5519
+ /**
5520
+ * 该属性只是一个 parameters 的别名
5521
+ *
5522
+ * 当你需要设置最新的参数时可以直接使用 setParameters 方法
5523
+ *
5524
+ * @override
5525
+ * @example
5526
+ * ```ts
5527
+ * context.setParameters({
5528
+ * target: 'production'
5529
+ * });
5530
+ *
5531
+ * console.log(context.options);
5532
+ * // { target: 'production' }
5533
+ * console.log(context.parameters);
5534
+ * // { target: 'production' }
5535
+ * ```
5536
+ */
5537
+ get options(): Opt;
4324
5538
  /**
4325
5539
  * Creates a new ScriptContext instance with the specified configuration
4326
5540
  *
@@ -4368,10 +5582,6 @@ declare class ScriptContext<Opt extends ScriptSharedInterface> extends ExecutorC
4368
5582
  * ```
4369
5583
  */
4370
5584
  constructor(name: string, opts?: Partial<ScriptContextInterface<Opt>>);
4371
- /**
4372
- * @override
4373
- */
4374
- get options(): Opt;
4375
5585
  /**
4376
5586
  * Environment instance for variable access and management
4377
5587
  *
@@ -4457,8 +5667,9 @@ declare class ScriptContext<Opt extends ScriptSharedInterface> extends ExecutorC
4457
5667
  * });
4458
5668
  * // Merges nested build configuration
4459
5669
  * ```
5670
+ *
4460
5671
  */
4461
- setOptions(options: Partial<Opt>): void;
5672
+ setParameters(params: Partial<Opt>): void;
4462
5673
  /**
4463
5674
  * Retrieves environment variable with optional default value
4464
5675
  *
@@ -4558,7 +5769,7 @@ declare class ScriptContext<Opt extends ScriptSharedInterface> extends ExecutorC
4558
5769
  * // Returns the complete options object
4559
5770
  * ```
4560
5771
  */
4561
- getOptions<T = unknown>(key?: string | string[], defaultValue?: T): T;
5772
+ getParameters<T = unknown>(key?: string | string[], defaultValue?: T): T;
4562
5773
  }
4563
5774
 
4564
5775
  /**
@@ -4796,7 +6007,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
4796
6007
  * }
4797
6008
  * ```
4798
6009
  */
4799
- get options(): Props;
6010
+ get config(): Props;
4800
6011
  /**
4801
6012
  * Determines whether a lifecycle method should be executed
4802
6013
  *
@@ -4822,7 +6033,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
4822
6033
  * plugin.enabled('onExec', context); // Returns true
4823
6034
  * ```
4824
6035
  */
4825
- enabled(_name: string, _context: Context): boolean;
6036
+ enabled(name: string, _context: Context): boolean;
4826
6037
  /**
4827
6038
  * Retrieves configuration values with nested path support
4828
6039
  *
@@ -4854,7 +6065,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
4854
6065
  * const plugins = this.getConfig<string[]>('plugins', []);
4855
6066
  * ```
4856
6067
  */
4857
- getConfig<T>(keys?: string | string[], defaultValue?: T): T;
6068
+ getConfig<T>(keys?: keyof Props | (keyof Props)[], defaultValue?: T): T;
4858
6069
  /**
4859
6070
  * Updates plugin configuration with deep merging
4860
6071
  *
@@ -4950,7 +6161,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
4950
6161
  * }
4951
6162
  * ```
4952
6163
  */
4953
- onExec?(_context: Context): void | Promise<void>;
6164
+ onExec?(context: Context): void | Promise<void>;
4954
6165
  /**
4955
6166
  * Lifecycle method called after successful script execution
4956
6167
  *
@@ -4981,7 +6192,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
4981
6192
  * }
4982
6193
  * ```
4983
6194
  */
4984
- onSuccess?(_context: Context): void | Promise<void>;
6195
+ onSuccess?(context: Context): void | Promise<void>;
4985
6196
  /**
4986
6197
  * Lifecycle method called when script execution fails
4987
6198
  *
@@ -5014,7 +6225,7 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
5014
6225
  * }
5015
6226
  * ```
5016
6227
  */
5017
- onError?(_context: Context): Promise<ExecutorError | void> | ExecutorError | Error | void;
6228
+ onError?(context: Context): Promise<ExecutorError | void> | ExecutorError | Error | void;
5018
6229
  /**
5019
6230
  * Lifecycle method called after script execution
5020
6231
  *
@@ -5096,6 +6307,159 @@ declare abstract class ScriptPlugin<Context extends ScriptContext<any>, Props ex
5096
6307
  * ```
5097
6308
  */
5098
6309
  step<T>(options: StepOption<T>): Promise<T>;
6310
+ /**
6311
+ * Builds the shared step log prefix (plugin context + dry-run)
6312
+ */
6313
+ protected createStepLabel(label: string): string;
6314
+ }
6315
+
6316
+ /**
6317
+ * @module TemplateEngine
6318
+ * @description Lightweight, safe template engine for variable interpolation.
6319
+ *
6320
+ * Supports path-based value lookup (e.g. `user.name`, `items[0].id`) without
6321
+ * executing arbitrary JavaScript. Designed as a drop-in replacement for
6322
+ * simple `lodash.template` use cases in scripts and configuration formatting.
6323
+ *
6324
+ * Default syntax: ES6 template-literal `${ path }`.
6325
+ *
6326
+ * @example Basic usage
6327
+ * ```typescript
6328
+ * const engine = new TemplateEngine();
6329
+ * engine.render('Hello ${user.name}!', { user: { name: 'Alice' } });
6330
+ * // => 'Hello Alice!'
6331
+ * ```
6332
+ *
6333
+ * @example Reusable compiled renderer
6334
+ * ```typescript
6335
+ * const render = engine.compile('git clone ${repo.url}');
6336
+ * render({ repo: { url: 'https://github.com/user/repo.git' } });
6337
+ * ```
6338
+ */
6339
+ /**
6340
+ * Template engine configuration options.
6341
+ */
6342
+ interface TemplateOptions {
6343
+ /**
6344
+ * Interpolation regex with exactly one capture group for the variable path.
6345
+ * Defaults to {@link interpolatePreset.ES6}.
6346
+ */
6347
+ interpolate?: RegExp;
6348
+ /**
6349
+ * Required path prefix in templates (lodash `variable` option semantics).
6350
+ * e.g. `variable: 'data'` → use `${data.user.name}` with `{ user: { name } }`.
6351
+ */
6352
+ variable?: string;
6353
+ /** Default when value is missing (undefined/null) or path is invalid. */
6354
+ defaultValue?: unknown | ((path: string, data: Record<string, unknown>) => unknown);
6355
+ /** Escape HTML entities in output. Default false. */
6356
+ escapeHtml?: boolean;
6357
+ /** Serialize objects via JSON.stringify. Default true. */
6358
+ stringifyObject?: boolean;
6359
+ /** Keep original placeholder when value is missing. Default false. */
6360
+ keepUnmatched?: boolean;
6361
+ /** Block prototype keys and only read own properties. Default true. */
6362
+ safePrototype?: boolean;
6363
+ }
6364
+ /** Compiled render function returned by {@link TemplateEngine.compile}. */
6365
+ type RenderFn = (data: Record<string, unknown>) => string;
6366
+ /**
6367
+ * Built-in interpolation regex presets.
6368
+ *
6369
+ * Pass one of these to `new TemplateEngine({ interpolate })` when you need
6370
+ * a syntax other than the default ES6-style delimiters.
6371
+ *
6372
+ * @example ES6 (default — no extra config needed)
6373
+ * ```typescript
6374
+ * new TemplateEngine().render('Hello ${name}!', { name: 'World' });
6375
+ * ```
6376
+ *
6377
+ * @example Lodash / EJS style
6378
+ * ```typescript
6379
+ * new TemplateEngine({ interpolate: interpolatePreset.LODASH })
6380
+ * .render('Hello <%= name %>!', { name: 'World' });
6381
+ * ```
6382
+ *
6383
+ * @example Mustache style
6384
+ * ```typescript
6385
+ * new TemplateEngine({ interpolate: interpolatePreset.MUSTACHE })
6386
+ * .render('Hello {{ name }}!', { name: 'World' });
6387
+ * ```
6388
+ */
6389
+ declare const interpolatePreset: {
6390
+ /**
6391
+ * ES6 template-literal style: `${ variable }`
6392
+ *
6393
+ * This is the default for {@link TemplateEngine}.
6394
+ *
6395
+ * @example
6396
+ * ```typescript
6397
+ * engine.render('${user.name}', { user: { name: 'Bob' } });
6398
+ * ```
6399
+ */
6400
+ readonly ES6: RegExp;
6401
+ /**
6402
+ * Lodash / EJS style: `<%= variable %>`
6403
+ *
6404
+ * Useful when migrating existing lodash templates.
6405
+ *
6406
+ * @example
6407
+ * ```typescript
6408
+ * new TemplateEngine({ interpolate: interpolatePreset.LODASH })
6409
+ * .render('<%= repo.url %>', { repo: { url: 'https://example.com' } });
6410
+ * ```
6411
+ */
6412
+ readonly LODASH: RegExp;
6413
+ /**
6414
+ * Mustache / Handlebars style: `{{ variable }}`
6415
+ *
6416
+ * @example
6417
+ * ```typescript
6418
+ * new TemplateEngine({ interpolate: interpolatePreset.MUSTACHE })
6419
+ * .render('{{ user.name }}', { user: { name: 'Alice' } });
6420
+ * ```
6421
+ */
6422
+ readonly MUSTACHE: RegExp;
6423
+ };
6424
+ /**
6425
+ * Lightweight template engine for safe variable interpolation.
6426
+ *
6427
+ * Features:
6428
+ * - ES6 `${ path }` syntax by default
6429
+ * - Nested path access and numeric array indices
6430
+ * - Prototype pollution protection (`safePrototype`, enabled by default)
6431
+ * - Compile-once, render-many for performance
6432
+ *
6433
+ * Does NOT execute `<% code %>` logic blocks or arbitrary JavaScript.
6434
+ */
6435
+ declare class TemplateEngine {
6436
+ private readonly options;
6437
+ /**
6438
+ * @param options - Engine configuration. All fields are optional;
6439
+ * defaults to ES6 `${}` interpolation with safe prototype access.
6440
+ */
6441
+ constructor(options?: TemplateOptions);
6442
+ /**
6443
+ * Compile a template into a reusable render function.
6444
+ *
6445
+ * Path parsing and validation happen once at compile time; subsequent
6446
+ * renders only perform value lookup and string assembly.
6447
+ *
6448
+ * @param template - Template string containing placeholders
6449
+ * @returns Render function bound to the compiled template
6450
+ * @throws {TypeError} When template is not a string
6451
+ */
6452
+ compile(template: string): RenderFn;
6453
+ /**
6454
+ * Render a template in one shot.
6455
+ *
6456
+ * Convenience wrapper around `compile(template)(data)`.
6457
+ * Prefer {@link compile} when the same template is rendered multiple times.
6458
+ *
6459
+ * @param template - Template string containing placeholders
6460
+ * @param data - Context object for variable substitution
6461
+ */
6462
+ render(template: string, data: Record<string, any>): string;
5099
6463
  }
5100
6464
 
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 };
6465
+ 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 };