pw-sanitizer 0.1.0

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 (86) hide show
  1. package/README.md +415 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +113 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/config/loader.d.ts +30 -0
  7. package/dist/config/loader.d.ts.map +1 -0
  8. package/dist/config/loader.js +173 -0
  9. package/dist/config/loader.js.map +1 -0
  10. package/dist/config/types.d.ts +432 -0
  11. package/dist/config/types.d.ts.map +1 -0
  12. package/dist/config/types.js +6 -0
  13. package/dist/config/types.js.map +1 -0
  14. package/dist/config/validator.d.ts +34 -0
  15. package/dist/config/validator.d.ts.map +1 -0
  16. package/dist/config/validator.js +95 -0
  17. package/dist/config/validator.js.map +1 -0
  18. package/dist/index.d.ts +74 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +190 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/logger.d.ts +82 -0
  23. package/dist/logger.d.ts.map +1 -0
  24. package/dist/logger.js +122 -0
  25. package/dist/logger.js.map +1 -0
  26. package/dist/processors/html-report.d.ts +27 -0
  27. package/dist/processors/html-report.d.ts.map +1 -0
  28. package/dist/processors/html-report.js +220 -0
  29. package/dist/processors/html-report.js.map +1 -0
  30. package/dist/processors/screenshot.d.ts +37 -0
  31. package/dist/processors/screenshot.d.ts.map +1 -0
  32. package/dist/processors/screenshot.js +52 -0
  33. package/dist/processors/screenshot.js.map +1 -0
  34. package/dist/processors/trace-file.d.ts +29 -0
  35. package/dist/processors/trace-file.d.ts.map +1 -0
  36. package/dist/processors/trace-file.js +250 -0
  37. package/dist/processors/trace-file.js.map +1 -0
  38. package/dist/redact/json-walker.d.ts +28 -0
  39. package/dist/redact/json-walker.d.ts.map +1 -0
  40. package/dist/redact/json-walker.js +164 -0
  41. package/dist/redact/json-walker.js.map +1 -0
  42. package/dist/redact/matcher.d.ts +25 -0
  43. package/dist/redact/matcher.d.ts.map +1 -0
  44. package/dist/redact/matcher.js +130 -0
  45. package/dist/redact/matcher.js.map +1 -0
  46. package/dist/redact/pattern-loader.d.ts +25 -0
  47. package/dist/redact/pattern-loader.d.ts.map +1 -0
  48. package/dist/redact/pattern-loader.js +111 -0
  49. package/dist/redact/pattern-loader.js.map +1 -0
  50. package/dist/redact/pattern-registry.d.ts +17 -0
  51. package/dist/redact/pattern-registry.d.ts.map +1 -0
  52. package/dist/redact/pattern-registry.js +58 -0
  53. package/dist/redact/pattern-registry.js.map +1 -0
  54. package/dist/remove/detector.d.ts +22 -0
  55. package/dist/remove/detector.d.ts.map +1 -0
  56. package/dist/remove/detector.js +152 -0
  57. package/dist/remove/detector.js.map +1 -0
  58. package/dist/remove/remover.d.ts +18 -0
  59. package/dist/remove/remover.d.ts.map +1 -0
  60. package/dist/remove/remover.js +72 -0
  61. package/dist/remove/remover.js.map +1 -0
  62. package/dist/remove/rule-loader.d.ts +25 -0
  63. package/dist/remove/rule-loader.d.ts.map +1 -0
  64. package/dist/remove/rule-loader.js +110 -0
  65. package/dist/remove/rule-loader.js.map +1 -0
  66. package/dist/remove/rule-registry.d.ts +17 -0
  67. package/dist/remove/rule-registry.d.ts.map +1 -0
  68. package/dist/remove/rule-registry.js +58 -0
  69. package/dist/remove/rule-registry.js.map +1 -0
  70. package/dist/remove/timestamp-repair.d.ts +28 -0
  71. package/dist/remove/timestamp-repair.d.ts.map +1 -0
  72. package/dist/remove/timestamp-repair.js +157 -0
  73. package/dist/remove/timestamp-repair.js.map +1 -0
  74. package/dist/reporter.d.ts +44 -0
  75. package/dist/reporter.d.ts.map +1 -0
  76. package/dist/reporter.js +180 -0
  77. package/dist/reporter.js.map +1 -0
  78. package/dist/teardown.d.ts +27 -0
  79. package/dist/teardown.d.ts.map +1 -0
  80. package/dist/teardown.js +42 -0
  81. package/dist/teardown.js.map +1 -0
  82. package/dist/utils.d.ts +36 -0
  83. package/dist/utils.d.ts.map +1 -0
  84. package/dist/utils.js +112 -0
  85. package/dist/utils.js.map +1 -0
  86. package/package.json +71 -0
package/README.md ADDED
@@ -0,0 +1,415 @@
1
+ # playwright-sanitizer
2
+
3
+ Post-process Playwright HTML reports and trace files to **redact secrets** and **remove noisy steps** before sharing or archiving.
4
+
5
+ ---
6
+
7
+ ## Why
8
+
9
+ Playwright's HTML reports and `.zip` trace files can contain sensitive data — auth headers, API keys, tokens, passwords — embedded in network request logs, action parameters, and step metadata. `playwright-sanitizer` scans those files after your test run and replaces or strips the sensitive content so they are safe to store in CI artifacts, share with teammates, or upload to a dashboard.
10
+
11
+ It also lets you delete repetitive or internal steps (e.g. health-check pings, internal logging actions) that create noise in the trace viewer.
12
+
13
+ ---
14
+
15
+ ## Features
16
+
17
+ - Redact secrets in HTML reports and trace `.zip` files by key name, value pattern, or both
18
+ - Remove entire steps from traces with configurable timestamp repair
19
+ - Three output modes: `copy` (safe default), `in-place`, `side-by-side`
20
+ - Zero built-in patterns — you declare exactly what gets touched, nothing else runs
21
+ - Dry-run mode to preview changes without writing files
22
+ - Integrates as a Playwright `globalTeardown` so it runs automatically after every test run
23
+ - Programmatic API for custom pipelines
24
+ - Summary table printed to the console (and optionally written as JSON)
25
+
26
+ ---
27
+
28
+ ## Requirements
29
+
30
+ - Node.js >= 18
31
+
32
+ ---
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ npm install --save-dev playwright-sanitizer
38
+ ```
39
+
40
+ Screenshot redaction inside trace files requires the optional `sharp` dependency:
41
+
42
+ ```bash
43
+ npm install --save-dev sharp
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Quick start
49
+
50
+ ### 1. Create a config file
51
+
52
+ ```ts
53
+ // playwright-sanitizer.config.ts
54
+ import type { SanitizerConfig } from 'playwright-sanitizer';
55
+
56
+ const config: SanitizerConfig = {
57
+ redact: {
58
+ patterns: [
59
+ {
60
+ id: 'auth-header',
61
+ description: 'Authorization header value',
62
+ key: 'authorization',
63
+ severity: 'critical',
64
+ },
65
+ {
66
+ id: 'api-key',
67
+ key: /x-api-key/i,
68
+ severity: 'high',
69
+ },
70
+ ],
71
+ },
72
+ remove: {
73
+ rules: [
74
+ {
75
+ label: 'health-check pings',
76
+ url: /\/health$/,
77
+ },
78
+ ],
79
+ },
80
+ };
81
+
82
+ export default config;
83
+ ```
84
+
85
+ ### 2. Run the CLI
86
+
87
+ ```bash
88
+ npx playwright-sanitizer
89
+ ```
90
+
91
+ Sanitized files are written to `./sanitized-report` by default. Originals are untouched.
92
+
93
+ ---
94
+
95
+ ## Configuration
96
+
97
+ Config is auto-discovered in this priority order:
98
+
99
+ | Priority | Source |
100
+ |----------|--------|
101
+ | 1 | `--config <path>` CLI flag |
102
+ | 2 | `playwright-sanitizer.config.ts` |
103
+ | 3 | `playwright-sanitizer.config.js` |
104
+ | 4 | `playwright-sanitizer.config.json` |
105
+ | 5 | `sanitizer` key inside `playwright.config.ts` |
106
+
107
+ ### Full config reference
108
+
109
+ ```ts
110
+ import type { SanitizerConfig } from 'playwright-sanitizer';
111
+
112
+ const config: SanitizerConfig = {
113
+ redact: {
114
+ // Inline patterns (merged with patternFiles)
115
+ patterns: [
116
+ {
117
+ id: 'my-token', // REQUIRED — unique identifier shown in summary
118
+ description: 'API token', // optional, shown in summary output
119
+ key: 'x-api-token', // match field/header name (string = case-insensitive exact match)
120
+ valuePattern: /^ey/, // match field value (RegExp) — when set alongside key, BOTH must match
121
+ severity: 'high', // 'low' | 'medium' | 'high' | 'critical' (informational only)
122
+ },
123
+ ],
124
+
125
+ // External pattern files (.ts, .js, or .json) — merged with inline patterns
126
+ patternFiles: ['./secrets/patterns.ts'],
127
+
128
+ // Replacement string. Default: '[REDACTED]'
129
+ placeholder: '[REDACTED]',
130
+
131
+ // Partial redaction: keep first N and last N characters, mask the middle with '***'
132
+ // Example: { prefix: 4, suffix: 4 } on 'Bearer eyJhbGci...' => 'Bear***..ci'
133
+ // Takes priority over placeholder when set.
134
+ partialRedaction: { prefix: 4, suffix: 4 },
135
+ },
136
+
137
+ remove: {
138
+ // Inline rules (merged with ruleFiles)
139
+ rules: [
140
+ {
141
+ label: 'noisy health checks', // REQUIRED — shown in summary and dry-run log
142
+ stepName: /health/i, // match step name shown in the HTML report
143
+ selector: '[data-testid="spinner"]', // match CSS selector or XPath locator
144
+ url: /\/internal\//, // match network request URL
145
+ actionType: 'waitForTimeout', // match Playwright internal action type
146
+
147
+ // Safety guard: only remove if this step appears at least N times
148
+ // consecutively within a test. Logs a warning and skips removal if not met.
149
+ minConsecutiveOccurrences: 3,
150
+ },
151
+ ],
152
+
153
+ // External rule files (.ts, .js, or .json) — merged with inline rules
154
+ ruleFiles: ['./rules/remove-rules.ts'],
155
+
156
+ // How to handle time after a step is deleted.
157
+ // 'absorb-into-prev' (default): preceding step absorbs the deleted duration
158
+ // 'absorb-into-next': following step's start time shifts back
159
+ // 'gap': no adjustment; a gap appears in the timeline
160
+ timestampStrategy: 'absorb-into-prev',
161
+
162
+ // What to do with child steps when a parent is removed.
163
+ // 'remove-children' (default): children are also removed
164
+ // 'keep-shell': parent is kept as an empty container
165
+ orphanStrategy: 'remove-children',
166
+
167
+ // Preview mode — log what would be removed but don't write any files
168
+ dryRun: false,
169
+ },
170
+
171
+ output: {
172
+ reportDir: './playwright-report', // where to find HTML reports. Default: './playwright-report'
173
+ traceDir: './test-results', // where to find trace zips. Default: './test-results'
174
+
175
+ // Output mode:
176
+ // 'copy' (default): write sanitized files to dir, originals untouched
177
+ // 'in-place': overwrite original files (ensure they are version-controlled!)
178
+ // 'side-by-side': write '<name>.sanitized.<ext>' next to each original
179
+ mode: 'copy',
180
+
181
+ dir: './sanitized-report', // destination for 'copy' mode. Default: './sanitized-report'
182
+
183
+ processReports: true, // set to false to skip HTML report processing
184
+ processTraces: true, // set to false to skip trace file processing
185
+ redactScreenshots: false, // redact screenshots in traces (requires 'sharp')
186
+ },
187
+
188
+ reporting: {
189
+ summary: true, // print summary table after processing. Default: true
190
+ summaryFile: './sanitization-summary.json', // optional — write summary as JSON to this path
191
+ logLevel: 'normal', // 'silent' | 'normal' | 'verbose'
192
+ },
193
+ };
194
+
195
+ export default config;
196
+ ```
197
+
198
+ ---
199
+
200
+ ## External pattern and rule files
201
+
202
+ For large teams, keep patterns and rules in dedicated files so they can be versioned and shared across projects:
203
+
204
+ ```ts
205
+ // secrets/patterns.ts
206
+ import type { RedactPattern } from 'playwright-sanitizer';
207
+
208
+ const patterns: RedactPattern[] = [
209
+ { id: 'auth-header', key: 'authorization', severity: 'critical' },
210
+ { id: 'cookie', key: 'cookie', severity: 'high' },
211
+ { id: 'set-cookie', key: 'set-cookie', severity: 'high' },
212
+ ];
213
+
214
+ export default patterns;
215
+ ```
216
+
217
+ ```ts
218
+ // playwright-sanitizer.config.ts
219
+ export default {
220
+ redact: { patternFiles: ['./secrets/patterns.ts'] },
221
+ };
222
+ ```
223
+
224
+ JSON files are also supported. Note that RegExp is not available in JSON — strings are matched as case-insensitive exact key names:
225
+
226
+ ```json
227
+ [
228
+ { "id": "auth-header", "key": "authorization", "severity": "critical" },
229
+ { "id": "api-key", "key": "x-api-key", "severity": "high" }
230
+ ]
231
+ ```
232
+
233
+ ---
234
+
235
+ ## CLI reference
236
+
237
+ ```
238
+ Usage: playwright-sanitizer [options]
239
+
240
+ Options:
241
+ -c, --config <path> Path to config file
242
+ -r, --report <path> HTML report directory (default: "./playwright-report")
243
+ -t, --traces <path> Trace directory (default: "./test-results")
244
+ -o, --output <path> Output directory (copy mode)
245
+ --in-place Overwrite original files
246
+ --patterns <path...> One or more pattern files
247
+ --placeholder <string> Redaction placeholder (default: "[REDACTED]")
248
+ --dry-run Log changes without writing files
249
+ --no-traces Skip trace file processing
250
+ --no-reports Skip HTML report processing
251
+ --summary-output <path> Write JSON summary to file
252
+ --log-level <level> silent | normal | verbose (default: "normal")
253
+ -V, --version Display version number
254
+ -h, --help Display help
255
+ ```
256
+
257
+ ### Examples
258
+
259
+ ```bash
260
+ # Auto-discover config and run with defaults
261
+ npx playwright-sanitizer
262
+
263
+ # Use a specific config file
264
+ npx playwright-sanitizer --config ./ci/sanitizer.config.ts
265
+
266
+ # Overwrite originals (ensure files are version-controlled)
267
+ npx playwright-sanitizer --in-place
268
+
269
+ # Preview without writing any files
270
+ npx playwright-sanitizer --dry-run --log-level verbose
271
+
272
+ # Point to non-default directories
273
+ npx playwright-sanitizer --report ./reports --traces ./artifacts/traces --output ./sanitized
274
+
275
+ # Write a machine-readable summary for CI artifact ingestion
276
+ npx playwright-sanitizer --summary-output ./sanitization-summary.json
277
+ ```
278
+
279
+ ---
280
+
281
+ ## Playwright globalTeardown integration
282
+
283
+ Register the sanitizer as a Playwright `globalTeardown` and it runs automatically after every test suite:
284
+
285
+ ```ts
286
+ // playwright.config.ts
287
+ import { defineConfig } from '@playwright/test';
288
+
289
+ export default defineConfig({
290
+ globalTeardown: require.resolve('playwright-sanitizer/teardown'),
291
+ // ...rest of your config
292
+ });
293
+ ```
294
+
295
+ Config is auto-discovered as described above. Teardown failures are caught and logged — they will never mask your actual test results.
296
+
297
+ ### Embedding config in playwright.config.ts
298
+
299
+ If you prefer a single config file, add a `sanitizer` key directly to your Playwright config:
300
+
301
+ ```ts
302
+ // playwright.config.ts
303
+ import { defineConfig } from '@playwright/test';
304
+ import type { SanitizerConfig } from 'playwright-sanitizer';
305
+
306
+ export default defineConfig({
307
+ globalTeardown: require.resolve('playwright-sanitizer/teardown'),
308
+
309
+ sanitizer: {
310
+ redact: {
311
+ patterns: [
312
+ { id: 'auth', key: 'authorization', severity: 'critical' },
313
+ ],
314
+ },
315
+ output: { mode: 'in-place' },
316
+ } satisfies SanitizerConfig,
317
+ });
318
+ ```
319
+
320
+ ---
321
+
322
+ ## Programmatic API
323
+
324
+ ```ts
325
+ import { sanitize, redactReport, redactTrace } from 'playwright-sanitizer';
326
+
327
+ // Process all reports and traces using auto-discovered config
328
+ const results = await sanitize();
329
+
330
+ // Pass a config object directly (skips file discovery)
331
+ const results = await sanitize({
332
+ redact: { patterns: [{ id: 'token', key: 'x-token' }] },
333
+ output: { mode: 'copy', dir: './out' },
334
+ });
335
+
336
+ // Process a single HTML report
337
+ const result = await redactReport('./playwright-report/index.html', config);
338
+
339
+ // Process a single trace zip
340
+ const result = await redactTrace('./test-results/my-test/trace.zip', config);
341
+ ```
342
+
343
+ Each call returns a `ProcessResult` (or an array of them for `sanitize()`):
344
+
345
+ ```ts
346
+ interface ProcessResult {
347
+ file: string;
348
+ redactionsApplied: number;
349
+ stepsRemoved: number;
350
+ timestampRepairs: number;
351
+ redactionMatches: Array<{ keyPath: string; patternId: string }>;
352
+ removalMatches: Array<{ index: number; ruleLabel: string; event: TraceEvent }>;
353
+ }
354
+ ```
355
+
356
+ ---
357
+
358
+ ## Output modes
359
+
360
+ | Mode | Behaviour |
361
+ |------|-----------|
362
+ | `copy` (default) | Writes sanitized files to `output.dir` (`./sanitized-report`). Originals are never touched. |
363
+ | `in-place` | Overwrites original files. A warning is printed. Use only with version control. |
364
+ | `side-by-side` | Creates `<name>.sanitized.<ext>` next to each original file. |
365
+
366
+ ---
367
+
368
+ ## How redaction works
369
+
370
+ Redaction walks every JSON structure inside the HTML report's embedded data and the trace file's event entries. For each field encountered, the declared patterns are checked:
371
+
372
+ 1. If `key` is a **string** — matched case-insensitively as an exact field name.
373
+ 2. If `key` is a **RegExp** — tested against the field name.
374
+ 3. If `valuePattern` is provided — both `key` and `valuePattern` must match (AND logic).
375
+ 4. The matched value is replaced with `placeholder`, or a partial redaction if `partialRedaction` is configured.
376
+
377
+ No built-in patterns are ever applied. Only what you declare runs.
378
+
379
+ ---
380
+
381
+ ## How step removal works
382
+
383
+ Step removal operates on the trace event tree inside each `.zip` file:
384
+
385
+ 1. Each event is tested against your declared rules (`stepName`, `selector`, `url`, `actionType`).
386
+ 2. Matching events are collected and removed from the event list.
387
+ 3. Timestamps of surrounding events are adjusted according to `timestampStrategy` to keep the timeline coherent.
388
+ 4. Child steps of removed parents are handled according to `orphanStrategy`.
389
+
390
+ The `minConsecutiveOccurrences` safety guard prevents accidentally removing a step that only appears occasionally — if the actual consecutive count is below the threshold, the step is **not** removed and a warning is logged instead.
391
+
392
+ ---
393
+
394
+ ## CI integration example
395
+
396
+ ```yaml
397
+ # .github/workflows/test.yml
398
+ - name: Run Playwright tests
399
+ run: npx playwright test
400
+
401
+ - name: Sanitize Playwright artifacts
402
+ run: npx playwright-sanitizer --summary-output sanitization-summary.json
403
+
404
+ - name: Upload sanitized report
405
+ uses: actions/upload-artifact@v4
406
+ with:
407
+ name: playwright-report
408
+ path: sanitized-report/
409
+ ```
410
+
411
+ ---
412
+
413
+ ## License
414
+
415
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const loader_js_1 = require("./config/loader.js");
6
+ const index_js_1 = require("./index.js");
7
+ const program = new commander_1.Command();
8
+ program
9
+ .name('playwright-sanitizer')
10
+ .description('Post-process Playwright HTML reports and trace files to redact secrets and remove noisy steps')
11
+ .version('0.1.0')
12
+ .option('-c, --config <path>', 'Path to config file')
13
+ .option('-r, --report <path>', 'HTML report directory', './playwright-report')
14
+ .option('-t, --traces <path>', 'Trace directory', './test-results')
15
+ .option('-o, --output <path>', 'Output directory (for copy mode)')
16
+ .option('--in-place', 'Overwrite original files')
17
+ .option('--patterns <path...>', 'One or more pattern files (repeatable)')
18
+ .option('--placeholder <string>', 'Redaction placeholder', '[REDACTED]')
19
+ .option('--dry-run', 'Log changes without writing files')
20
+ .option('--no-traces', 'Skip trace file processing')
21
+ .option('--no-reports', 'Skip HTML report processing')
22
+ .option('--summary-output <path>', 'Write JSON summary to file')
23
+ .option('--log-level <level>', 'silent | normal | verbose', 'normal');
24
+ program.action(async (opts) => {
25
+ try {
26
+ // Load config
27
+ const config = await (0, loader_js_1.loadConfig)(opts['config']);
28
+ // Apply CLI overrides
29
+ applyCliOverrides(config, opts);
30
+ await (0, index_js_1.sanitize)(config);
31
+ process.exit(0);
32
+ }
33
+ catch (err) {
34
+ if (err instanceof Error) {
35
+ console.error(`[FATAL] ${err.message}`);
36
+ }
37
+ else {
38
+ console.error(`[FATAL] ${String(err)}`);
39
+ }
40
+ process.exit(1);
41
+ }
42
+ });
43
+ /**
44
+ * Merges parsed CLI flag values into a {@link SanitizerConfig} object.
45
+ *
46
+ * CLI flags always take the highest priority — they overwrite any values
47
+ * that were loaded from a config file. Sections are created on-demand
48
+ * (e.g. `config.output` is initialised to `{}` if not already present).
49
+ *
50
+ * Flag → config field mapping:
51
+ * - `--report` → `output.reportDir`
52
+ * - `--no-traces` → `output.processTraces = false`
53
+ * - `--no-reports` → `output.processReports = false`
54
+ * - `--output` → `output.dir` + `output.mode = 'copy'`
55
+ * - `--in-place` → `output.mode = 'in-place'`
56
+ * - `--patterns` → `redact.patternFiles`
57
+ * - `--placeholder` → `redact.placeholder`
58
+ * - `--dry-run` → `remove.dryRun = true`
59
+ * - `--log-level` → `reporting.logLevel`
60
+ * - `--summary-output` → `reporting.summaryFile`
61
+ *
62
+ * @param config - The config object to mutate (loaded from file or empty).
63
+ * @param opts - Raw parsed options from Commander.js (`program.opts()`).
64
+ */
65
+ function applyCliOverrides(config, opts) {
66
+ // Output overrides
67
+ if (!config.output)
68
+ config.output = {};
69
+ if (opts['report']) {
70
+ config.output.reportDir = opts['report'];
71
+ }
72
+ if (opts['traces'] === false) {
73
+ config.output.processTraces = false;
74
+ }
75
+ if (opts['reports'] === false) {
76
+ config.output.processReports = false;
77
+ }
78
+ if (opts['output']) {
79
+ config.output.dir = opts['output'];
80
+ config.output.mode = 'copy';
81
+ }
82
+ if (opts['inPlace']) {
83
+ config.output.mode = 'in-place';
84
+ }
85
+ // Redact overrides
86
+ if (opts['patterns']) {
87
+ if (!config.redact)
88
+ config.redact = {};
89
+ config.redact.patternFiles = opts['patterns'];
90
+ }
91
+ if (opts['placeholder']) {
92
+ if (!config.redact)
93
+ config.redact = {};
94
+ config.redact.placeholder = opts['placeholder'];
95
+ }
96
+ // Remove overrides
97
+ if (opts['dryRun']) {
98
+ if (!config.remove)
99
+ config.remove = {};
100
+ config.remove.dryRun = true;
101
+ }
102
+ // Reporting overrides
103
+ if (!config.reporting)
104
+ config.reporting = {};
105
+ if (opts['logLevel']) {
106
+ config.reporting.logLevel = opts['logLevel'];
107
+ }
108
+ if (opts['summaryOutput']) {
109
+ config.reporting.summaryFile = opts['summaryOutput'];
110
+ }
111
+ }
112
+ program.parse();
113
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { SanitizerConfig } from './types.js';
2
+ /**
3
+ * Resolves and loads the sanitizer configuration.
4
+ *
5
+ * Config discovery priority (first match wins):
6
+ * 1. Explicit `configPath` (from `--config` CLI flag or programmatic call)
7
+ * 2. `playwright-sanitizer.config.ts` in `cwd`
8
+ * 3. `playwright-sanitizer.config.js` in `cwd`
9
+ * 4. `playwright-sanitizer.config.json` in `cwd`
10
+ * 5. `sanitizer` key inside `playwright.config.ts` / `playwright.config.js`
11
+ *
12
+ * If none of the above are found, the function calls `logger.fatal` which
13
+ * throws an `Error` with an actionable message.
14
+ *
15
+ * @param configPath - Optional explicit path to a config file.
16
+ * When provided, auto-discovery is skipped entirely.
17
+ * @returns The resolved {@link SanitizerConfig}.
18
+ * @throws Calls `logger.fatal` (which throws) when no config can be found or loaded.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * // Auto-discover config in cwd
23
+ * const config = await loadConfig();
24
+ *
25
+ * // Load from an explicit path
26
+ * const config = await loadConfig('./configs/sanitizer.config.ts');
27
+ * ```
28
+ */
29
+ export declare function loadConfig(configPath?: string): Promise<SanitizerConfig>;
30
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA+FlD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA6B9E"}