@qlover/scripts-context 1.0.0 → 1.1.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.
Files changed (2) hide show
  1. package/dist/index.js +354 -6
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -2818,9 +2818,116 @@ var LogEvent = class {
2818
2818
  this.context = context;
2819
2819
  this.timestamp = Date.now();
2820
2820
  }
2821
+ /**
2822
+ * Timestamp when the log event was created
2823
+ *
2824
+ * Automatically set to the current time in milliseconds since the Unix epoch
2825
+ * when the event is constructed. This ensures accurate timing information
2826
+ * for each log entry.
2827
+ *
2828
+ * @example
2829
+ * ```typescript
2830
+ * const event = new LogEvent('info', ['message'], 'app');
2831
+ * console.log(new Date(event.timestamp).toISOString());
2832
+ * // Output: "2024-03-21T14:30:45.123Z"
2833
+ * ```
2834
+ */
2821
2835
  timestamp;
2822
2836
  };
2823
2837
  var LogContext = class {
2838
+ /**
2839
+ * Creates a new LogContext instance
2840
+ *
2841
+ * @param value - Optional context value of type Value
2842
+ *
2843
+ * The value parameter is marked as optional to support:
2844
+ * - Empty contexts (no value provided)
2845
+ * - Explicitly undefined values
2846
+ * - Nullable types (Value | null)
2847
+ *
2848
+ * The value is stored as a public property to allow:
2849
+ * - Direct access in formatters and handlers
2850
+ * - Type-safe value extraction
2851
+ * - Optional chaining support
2852
+ *
2853
+ * @example Basic construction
2854
+ * ```typescript
2855
+ * // With value
2856
+ * const context = new LogContext({ userId: 123 });
2857
+ * console.log(context.value?.userId); // 123
2858
+ *
2859
+ * // Empty context
2860
+ * const empty = new LogContext();
2861
+ * console.log(empty.value); // undefined
2862
+ * ```
2863
+ *
2864
+ * @example Type-safe construction
2865
+ * ```typescript
2866
+ * interface UserContext {
2867
+ * id: number;
2868
+ * name: string;
2869
+ * role?: string;
2870
+ * }
2871
+ *
2872
+ * const context = new LogContext<UserContext>({
2873
+ * id: 123,
2874
+ * name: 'John',
2875
+ * role: 'admin' // Optional property
2876
+ * });
2877
+ *
2878
+ * // Type-safe access
2879
+ * const userId = context.value?.id; // number | undefined
2880
+ * const role = context.value?.role; // string | undefined
2881
+ * ```
2882
+ *
2883
+ * @example Nullable context
2884
+ * ```typescript
2885
+ * type NullableContext = {
2886
+ * sessionId: string;
2887
+ * } | null;
2888
+ *
2889
+ * // With value
2890
+ * const active = new LogContext<NullableContext>({
2891
+ * sessionId: 'sess-123'
2892
+ * });
2893
+ *
2894
+ * // With null
2895
+ * const inactive = new LogContext<NullableContext>(null);
2896
+ *
2897
+ * // Type-safe null handling
2898
+ * console.log(active.value?.sessionId); // 'sess-123'
2899
+ * console.log(inactive.value?.sessionId); // undefined
2900
+ * ```
2901
+ *
2902
+ * @example Context in logging
2903
+ * ```typescript
2904
+ * interface RequestContext {
2905
+ * path: string;
2906
+ * method: string;
2907
+ * duration: number;
2908
+ * }
2909
+ *
2910
+ * const context = new LogContext<RequestContext>({
2911
+ * path: '/api/users',
2912
+ * method: 'GET',
2913
+ * duration: 150
2914
+ * });
2915
+ *
2916
+ * // Using context in log messages
2917
+ * logger.info('Request completed', context);
2918
+ *
2919
+ * // Accessing context in formatters
2920
+ * class RequestFormatter implements FormatterInterface<RequestContext> {
2921
+ * format(event: LogEvent<RequestContext>): string[] {
2922
+ * const ctx = event.context?.value;
2923
+ * return [
2924
+ * ctx ? `${ctx.method} ${ctx.path} (${ctx.duration}ms)` : 'Unknown',
2925
+ * ...event.args
2926
+ * ];
2927
+ * }
2928
+ * }
2929
+ * ```
2930
+ */
2824
2931
  constructor(value) {
2825
2932
  this.value = value;
2826
2933
  }
@@ -3113,23 +3220,189 @@ var Logger = class {
3113
3220
  }
3114
3221
  };
3115
3222
  var ConsoleHandler = class {
3223
+ /**
3224
+ * Creates a new ConsoleHandler instance
3225
+ *
3226
+ * @param formatter - Optional formatter for customizing log message format
3227
+ * If not provided, raw log messages will be output
3228
+ *
3229
+ * @example Without formatter
3230
+ * ```typescript
3231
+ * const handler = new ConsoleHandler();
3232
+ * // Output: Raw message without formatting
3233
+ * ```
3234
+ *
3235
+ * @example With timestamp formatter
3236
+ * ```typescript
3237
+ * const handler = new ConsoleHandler(
3238
+ * new TimestampFormatter({
3239
+ * locale: 'zh-CN',
3240
+ * prefixTemplate: '[{formattedTimestamp}] {level}:'
3241
+ * })
3242
+ * );
3243
+ * // Output: [2024-03-21 14:30:45] INFO: Message
3244
+ * ```
3245
+ *
3246
+ * @example With JSON formatter
3247
+ * ```typescript
3248
+ * const handler = new ConsoleHandler(
3249
+ * new JSONFormatter({
3250
+ * pretty: true,
3251
+ * fields: ['timestamp', 'level', 'message']
3252
+ * })
3253
+ * );
3254
+ * // Output: {
3255
+ * // "timestamp": "2024-03-21T14:30:45.000Z",
3256
+ * // "level": "INFO",
3257
+ * // "message": "Application started"
3258
+ * // }
3259
+ * ```
3260
+ */
3116
3261
  constructor(formatter = null) {
3117
3262
  this.formatter = formatter;
3118
3263
  }
3119
3264
  /**
3120
- * Set formatter
3265
+ * Sets or updates the formatter for this handler
3121
3266
  *
3122
- * @override
3123
- * @param formatter
3267
+ * This method allows dynamic updating of the formatter after handler creation.
3268
+ * It's useful when you need to change the formatting style without creating
3269
+ * a new handler instance.
3270
+ *
3271
+ * @override Implementation of HandlerInterface
3272
+ * @param formatter - The formatter instance to use for formatting log messages
3273
+ *
3274
+ * @example Changing formatter at runtime
3275
+ * ```typescript
3276
+ * const handler = new ConsoleHandler();
3277
+ * const logger = new Logger({ handlers: [handler] });
3278
+ *
3279
+ * // Initially no formatting
3280
+ * logger.info('Plain message');
3281
+ * // Output: Plain message
3282
+ *
3283
+ * // Switch to timestamp formatting
3284
+ * handler.setFormatter(new TimestampFormatter());
3285
+ * logger.info('Formatted message');
3286
+ * // Output: [2024-03-21 14:30:45 INFO] Formatted message
3287
+ *
3288
+ * // Switch to JSON formatting
3289
+ * handler.setFormatter(new JSONFormatter());
3290
+ * logger.info('JSON message');
3291
+ * // Output: {"timestamp":"2024-03-21T14:30:45.000Z","level":"INFO","message":"JSON message"}
3292
+ * ```
3293
+ *
3294
+ * @example Conditional formatting
3295
+ * ```typescript
3296
+ * const handler = new ConsoleHandler();
3297
+ * const logger = new Logger({ handlers: [handler] });
3298
+ *
3299
+ * if (process.env.NODE_ENV === 'development') {
3300
+ * // Use pretty formatting in development
3301
+ * handler.setFormatter(new TimestampFormatter({
3302
+ * prefixTemplate: '[{formattedTimestamp}] {level}:'
3303
+ * }));
3304
+ * } else {
3305
+ * // Use JSON formatting in production
3306
+ * handler.setFormatter(new JSONFormatter({
3307
+ * fields: ['timestamp', 'level', 'message', 'metadata']
3308
+ * }));
3309
+ * }
3310
+ * ```
3124
3311
  */
3125
3312
  setFormatter(formatter) {
3126
3313
  this.formatter = formatter;
3127
3314
  }
3128
3315
  /**
3129
- * Append log event
3316
+ * Processes and outputs a log event to the console
3130
3317
  *
3131
- * @override
3132
- * @param event
3318
+ * This method:
3319
+ * 1. Extracts level and arguments from the event
3320
+ * 2. Applies formatting if a formatter is set
3321
+ * 3. Selects appropriate console method based on level
3322
+ * 4. Outputs the formatted message to the console
3323
+ *
3324
+ * @override Implementation of HandlerInterface
3325
+ * @param event - The log event to process and output
3326
+ *
3327
+ * @example Basic event handling
3328
+ * ```typescript
3329
+ * const handler = new ConsoleHandler();
3330
+ *
3331
+ * // Simple message
3332
+ * handler.append({
3333
+ * level: 'info',
3334
+ * args: ['Application started'],
3335
+ * timestamp: Date.now(),
3336
+ * loggerName: 'app'
3337
+ * });
3338
+ * // Console output: Application started
3339
+ *
3340
+ * // Message with context
3341
+ * handler.append({
3342
+ * level: 'error',
3343
+ * args: [
3344
+ * 'Database connection failed',
3345
+ * { host: 'localhost', port: 5432, error: 'Connection refused' }
3346
+ * ],
3347
+ * timestamp: Date.now(),
3348
+ * loggerName: 'db'
3349
+ * });
3350
+ * // Console output: Database connection failed { host: 'localhost', ... }
3351
+ * ```
3352
+ *
3353
+ * @example Formatted event handling
3354
+ * ```typescript
3355
+ * const handler = new ConsoleHandler(
3356
+ * new TimestampFormatter({
3357
+ * prefixTemplate: '[{formattedTimestamp}] {level}:'
3358
+ * })
3359
+ * );
3360
+ *
3361
+ * handler.append({
3362
+ * level: 'warn',
3363
+ * args: ['High memory usage', { usage: '85%' }],
3364
+ * timestamp: Date.now(),
3365
+ * loggerName: 'system'
3366
+ * });
3367
+ * // Console output: [2024-03-21 14:30:45] WARN: High memory usage { usage: '85%' }
3368
+ * ```
3369
+ *
3370
+ * @example Level-specific console methods
3371
+ * ```typescript
3372
+ * const handler = new ConsoleHandler();
3373
+ *
3374
+ * // Uses console.error()
3375
+ * handler.append({
3376
+ * level: 'error',
3377
+ * args: ['Critical error'],
3378
+ * timestamp: Date.now(),
3379
+ * loggerName: 'app'
3380
+ * });
3381
+ *
3382
+ * // Uses console.warn()
3383
+ * handler.append({
3384
+ * level: 'warn',
3385
+ * args: ['Deprecated feature used'],
3386
+ * timestamp: Date.now(),
3387
+ * loggerName: 'app'
3388
+ * });
3389
+ *
3390
+ * // Uses console.debug()
3391
+ * handler.append({
3392
+ * level: 'debug',
3393
+ * args: ['Processing request'],
3394
+ * timestamp: Date.now(),
3395
+ * loggerName: 'app'
3396
+ * });
3397
+ *
3398
+ * // Unknown level falls back to console.log()
3399
+ * handler.append({
3400
+ * level: 'custom',
3401
+ * args: ['Custom message'],
3402
+ * timestamp: Date.now(),
3403
+ * loggerName: 'app'
3404
+ * });
3405
+ * ```
3133
3406
  */
3134
3407
  append(event) {
3135
3408
  const { level, args } = event;
@@ -3145,12 +3418,87 @@ var defaultLocaleOptions = {
3145
3418
  timeZone: "UTC"
3146
3419
  };
3147
3420
  var TimestampFormatter = class {
3421
+ /**
3422
+ * Creates a new TimestampFormatter instance
3423
+ *
3424
+ * @param options - Configuration options for the formatter
3425
+ *
3426
+ * @example
3427
+ * ```typescript
3428
+ * const formatter = new TimestampFormatter({
3429
+ * locale: 'zh-CN',
3430
+ * prefixTemplate: '[{formattedTimestamp}] {level}:'
3431
+ * });
3432
+ * ```
3433
+ */
3148
3434
  constructor(options = {}) {
3149
3435
  this.options = options;
3150
3436
  }
3437
+ /**
3438
+ * Replaces template variables in the prefix string with actual values
3439
+ *
3440
+ * This internal method handles the variable substitution in prefix templates,
3441
+ * replacing placeholders like {timestamp} with their corresponding values.
3442
+ *
3443
+ * @param template - The template string containing variables in curly braces
3444
+ * @param vars - Object containing variable names and their values
3445
+ * @returns The template string with all variables replaced
3446
+ *
3447
+ * @example Internal usage
3448
+ * ```typescript
3449
+ * const vars = {
3450
+ * timestamp: '1679395845000',
3451
+ * level: 'INFO',
3452
+ * formattedTimestamp: '2024-03-21 14:30:45'
3453
+ * };
3454
+ *
3455
+ * // Template: "[{formattedTimestamp}] {level}"
3456
+ * // Result: "[2024-03-21 14:30:45] INFO"
3457
+ * const result = this.replacePrefix(template, vars);
3458
+ * ```
3459
+ *
3460
+ * @protected
3461
+ */
3151
3462
  replacePrefix(template, vars) {
3152
3463
  return template.replace(/\{([^{}]+)\}/g, (match, p1) => vars[p1] || match);
3153
3464
  }
3465
+ /**
3466
+ * Formats a log event by adding a timestamp prefix
3467
+ *
3468
+ * This method implements the FormatterInterface.format method. It:
3469
+ * 1. Extracts format type from context (if provided)
3470
+ * 2. Formats the timestamp according to locale and options
3471
+ * 3. Builds the prefix using the template
3472
+ * 4. Returns the formatted log entry
3473
+ *
3474
+ * @param event - The log event to format
3475
+ * @param event.timestamp - Event timestamp in milliseconds
3476
+ * @param event.level - Log level (e.g., INFO, ERROR)
3477
+ * @param event.args - Original log message arguments
3478
+ * @param event.context - Optional context with format customization
3479
+ * @param event.loggerName - Name of the logger instance
3480
+ *
3481
+ * @returns Array containing the formatted prefix followed by original arguments
3482
+ *
3483
+ * @example Internal processing
3484
+ * ```typescript
3485
+ * // Input event:
3486
+ * {
3487
+ * timestamp: 1679395845000,
3488
+ * level: 'INFO',
3489
+ * args: ['User logged in', { userId: 123 }],
3490
+ * context: { formatType: 'datetime' },
3491
+ * loggerName: 'UserService'
3492
+ * }
3493
+ *
3494
+ * // Output array:
3495
+ * [
3496
+ * '[2024-03-21 14:30:45 INFO]',
3497
+ * 'User logged in',
3498
+ * { userId: 123 }
3499
+ * ]
3500
+ * ```
3501
+ */
3154
3502
  format({ timestamp, level, args, context, loggerName }) {
3155
3503
  const {
3156
3504
  locale = "zh-CN",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@qlover/scripts-context",
3
3
  "description": "A scripts context for frontwork",
4
- "version": "1.0.0",
4
+ "version": "1.1.2",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "homepage": "https://github.com/qlover/fe-base/tree/master/packages/scripts-context#readme",
@@ -45,15 +45,15 @@
45
45
  "@types/shelljs": "^0.8.15",
46
46
  "lodash": "^4.17.21",
47
47
  "@qlover/env-loader": "0.3.0",
48
- "@qlover/logger": "0.1.1"
48
+ "@qlover/logger": "0.2.0"
49
49
  },
50
50
  "dependencies": {
51
- "@qlover/fe-corekit": "^1.4.1",
51
+ "@qlover/fe-corekit": "^2.1.0",
52
52
  "chalk": "^5.3.0",
53
53
  "cosmiconfig": "^9.0.0"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "tsup",
57
- "build:docs": "fe-code2md --removePrefix -p ./src -g ./docs --formatOutput prettier"
57
+ "build:docs": "fe-code2md -p src -g docs --formatOutput prettier --removePrefix"
58
58
  }
59
59
  }