@camaradesuk/git-worktree-tools 1.10.0 → 1.12.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.
- package/README.md +4 -4
- package/dist/lib/config.d.ts +2 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +11 -0
- package/dist/lib/config.js.map +1 -1
- package/package.json +12 -3
- package/schemas/worktreerc.schema.json +1 -1
- package/dist/api/list.test.d.ts +0 -5
- package/dist/api/list.test.d.ts.map +0 -1
- package/dist/api/list.test.js +0 -390
- package/dist/api/list.test.js.map +0 -1
- package/dist/cli/cleanpr.test.d.ts +0 -2
- package/dist/cli/cleanpr.test.d.ts.map +0 -1
- package/dist/cli/cleanpr.test.js +0 -954
- package/dist/cli/cleanpr.test.js.map +0 -1
- package/dist/cli/lswt.test.d.ts +0 -2
- package/dist/cli/lswt.test.d.ts.map +0 -1
- package/dist/cli/lswt.test.js +0 -376
- package/dist/cli/lswt.test.js.map +0 -1
- package/dist/cli/newpr.test.d.ts +0 -2
- package/dist/cli/newpr.test.d.ts.map +0 -1
- package/dist/cli/newpr.test.js +0 -1182
- package/dist/cli/newpr.test.js.map +0 -1
- package/dist/cli/prs.test.d.ts +0 -8
- package/dist/cli/prs.test.d.ts.map +0 -1
- package/dist/cli/prs.test.js +0 -463
- package/dist/cli/prs.test.js.map +0 -1
- package/dist/cli/wt/clean.test.d.ts +0 -8
- package/dist/cli/wt/clean.test.d.ts.map +0 -1
- package/dist/cli/wt/clean.test.js +0 -624
- package/dist/cli/wt/clean.test.js.map +0 -1
- package/dist/cli/wt/completion.test.d.ts +0 -5
- package/dist/cli/wt/completion.test.d.ts.map +0 -1
- package/dist/cli/wt/completion.test.js +0 -275
- package/dist/cli/wt/completion.test.js.map +0 -1
- package/dist/cli/wt/config.test.d.ts +0 -7
- package/dist/cli/wt/config.test.d.ts.map +0 -1
- package/dist/cli/wt/config.test.js +0 -440
- package/dist/cli/wt/config.test.js.map +0 -1
- package/dist/cli/wt/entry.test.d.ts +0 -8
- package/dist/cli/wt/entry.test.d.ts.map +0 -1
- package/dist/cli/wt/entry.test.js +0 -201
- package/dist/cli/wt/entry.test.js.map +0 -1
- package/dist/cli/wt/init.test.d.ts +0 -5
- package/dist/cli/wt/init.test.d.ts.map +0 -1
- package/dist/cli/wt/init.test.js +0 -165
- package/dist/cli/wt/init.test.js.map +0 -1
- package/dist/cli/wt/init.unit.test.d.ts +0 -5
- package/dist/cli/wt/init.unit.test.d.ts.map +0 -1
- package/dist/cli/wt/init.unit.test.js +0 -432
- package/dist/cli/wt/init.unit.test.js.map +0 -1
- package/dist/cli/wt/interactive-menu.test.d.ts +0 -12
- package/dist/cli/wt/interactive-menu.test.d.ts.map +0 -1
- package/dist/cli/wt/interactive-menu.test.js +0 -796
- package/dist/cli/wt/interactive-menu.test.js.map +0 -1
- package/dist/cli/wt/list.test.d.ts +0 -10
- package/dist/cli/wt/list.test.d.ts.map +0 -1
- package/dist/cli/wt/list.test.js +0 -157
- package/dist/cli/wt/list.test.js.map +0 -1
- package/dist/cli/wt/prs.test.d.ts +0 -5
- package/dist/cli/wt/prs.test.d.ts.map +0 -1
- package/dist/cli/wt/prs.test.js +0 -410
- package/dist/cli/wt/prs.test.js.map +0 -1
- package/dist/cli/wt/run-command.test.d.ts +0 -5
- package/dist/cli/wt/run-command.test.d.ts.map +0 -1
- package/dist/cli/wt/run-command.test.js +0 -88
- package/dist/cli/wt/run-command.test.js.map +0 -1
- package/dist/cli/wt/state.test.d.ts +0 -9
- package/dist/cli/wt/state.test.d.ts.map +0 -1
- package/dist/cli/wt/state.test.js +0 -127
- package/dist/cli/wt/state.test.js.map +0 -1
- package/dist/cli/wt/wt.test.d.ts +0 -8
- package/dist/cli/wt/wt.test.d.ts.map +0 -1
- package/dist/cli/wt/wt.test.js +0 -739
- package/dist/cli/wt/wt.test.js.map +0 -1
- package/dist/cli/wt.unit.test.d.ts +0 -7
- package/dist/cli/wt.unit.test.d.ts.map +0 -1
- package/dist/cli/wt.unit.test.js +0 -160
- package/dist/cli/wt.unit.test.js.map +0 -1
- package/dist/cli/wtconfig.test.d.ts +0 -5
- package/dist/cli/wtconfig.test.d.ts.map +0 -1
- package/dist/cli/wtconfig.test.js +0 -1289
- package/dist/cli/wtconfig.test.js.map +0 -1
- package/dist/cli/wtlink.test.d.ts +0 -2
- package/dist/cli/wtlink.test.d.ts.map +0 -1
- package/dist/cli/wtlink.test.js +0 -249
- package/dist/cli/wtlink.test.js.map +0 -1
- package/dist/cli/wtstate.test.d.ts +0 -5
- package/dist/cli/wtstate.test.d.ts.map +0 -1
- package/dist/cli/wtstate.test.js +0 -193
- package/dist/cli/wtstate.test.js.map +0 -1
- package/dist/e2e/cleanpr/cleanpr.e2e.test.d.ts +0 -2
- package/dist/e2e/cleanpr/cleanpr.e2e.test.d.ts.map +0 -1
- package/dist/e2e/cleanpr/cleanpr.e2e.test.js +0 -326
- package/dist/e2e/cleanpr/cleanpr.e2e.test.js.map +0 -1
- package/dist/e2e/cli.e2e.test.d.ts +0 -2
- package/dist/e2e/cli.e2e.test.d.ts.map +0 -1
- package/dist/e2e/cli.e2e.test.js +0 -417
- package/dist/e2e/cli.e2e.test.js.map +0 -1
- package/dist/e2e/lswt/lswt.e2e.test.d.ts +0 -2
- package/dist/e2e/lswt/lswt.e2e.test.d.ts.map +0 -1
- package/dist/e2e/lswt/lswt.e2e.test.js +0 -361
- package/dist/e2e/lswt/lswt.e2e.test.js.map +0 -1
- package/dist/e2e/newpr/newpr.e2e.test.d.ts +0 -2
- package/dist/e2e/newpr/newpr.e2e.test.d.ts.map +0 -1
- package/dist/e2e/newpr/newpr.e2e.test.js +0 -286
- package/dist/e2e/newpr/newpr.e2e.test.js.map +0 -1
- package/dist/e2e/newpr/scenarios.e2e.test.d.ts +0 -2
- package/dist/e2e/newpr/scenarios.e2e.test.d.ts.map +0 -1
- package/dist/e2e/newpr/scenarios.e2e.test.js +0 -426
- package/dist/e2e/newpr/scenarios.e2e.test.js.map +0 -1
- package/dist/e2e/newpr-full-flow.e2e.test.d.ts +0 -2
- package/dist/e2e/newpr-full-flow.e2e.test.d.ts.map +0 -1
- package/dist/e2e/newpr-full-flow.e2e.test.js +0 -280
- package/dist/e2e/newpr-full-flow.e2e.test.js.map +0 -1
- package/dist/e2e/prs/prs.e2e.test.d.ts +0 -7
- package/dist/e2e/prs/prs.e2e.test.d.ts.map +0 -1
- package/dist/e2e/prs/prs.e2e.test.js +0 -606
- package/dist/e2e/prs/prs.e2e.test.js.map +0 -1
- package/dist/e2e/workflows/pr-lifecycle.e2e.test.d.ts +0 -2
- package/dist/e2e/workflows/pr-lifecycle.e2e.test.d.ts.map +0 -1
- package/dist/e2e/workflows/pr-lifecycle.e2e.test.js +0 -298
- package/dist/e2e/workflows/pr-lifecycle.e2e.test.js.map +0 -1
- package/dist/e2e/wt/interactive-menu.e2e.test.d.ts +0 -8
- package/dist/e2e/wt/interactive-menu.e2e.test.d.ts.map +0 -1
- package/dist/e2e/wt/interactive-menu.e2e.test.js +0 -583
- package/dist/e2e/wt/interactive-menu.e2e.test.js.map +0 -1
- package/dist/e2e/wt/wt.e2e.test.d.ts +0 -9
- package/dist/e2e/wt/wt.e2e.test.d.ts.map +0 -1
- package/dist/e2e/wt/wt.e2e.test.js +0 -597
- package/dist/e2e/wt/wt.e2e.test.js.map +0 -1
- package/dist/e2e/wtlink/wtlink.e2e.test.d.ts +0 -2
- package/dist/e2e/wtlink/wtlink.e2e.test.d.ts.map +0 -1
- package/dist/e2e/wtlink/wtlink.e2e.test.js +0 -416
- package/dist/e2e/wtlink/wtlink.e2e.test.js.map +0 -1
- package/dist/integration/git.integration.test.d.ts +0 -2
- package/dist/integration/git.integration.test.d.ts.map +0 -1
- package/dist/integration/git.integration.test.js +0 -336
- package/dist/integration/git.integration.test.js.map +0 -1
- package/dist/integration/lswt-remote-pr.integration.test.d.ts +0 -2
- package/dist/integration/lswt-remote-pr.integration.test.d.ts.map +0 -1
- package/dist/integration/lswt-remote-pr.integration.test.js +0 -222
- package/dist/integration/lswt-remote-pr.integration.test.js.map +0 -1
- package/dist/integration/newpr-branchfrom-head.integration.test.d.ts +0 -2
- package/dist/integration/newpr-branchfrom-head.integration.test.d.ts.map +0 -1
- package/dist/integration/newpr-branchfrom-head.integration.test.js +0 -498
- package/dist/integration/newpr-branchfrom-head.integration.test.js.map +0 -1
- package/dist/integration/newpr.integration.test.d.ts +0 -2
- package/dist/integration/newpr.integration.test.d.ts.map +0 -1
- package/dist/integration/newpr.integration.test.js +0 -460
- package/dist/integration/newpr.integration.test.js.map +0 -1
- package/dist/integration/prs.integration.test.d.ts +0 -8
- package/dist/integration/prs.integration.test.d.ts.map +0 -1
- package/dist/integration/prs.integration.test.js +0 -478
- package/dist/integration/prs.integration.test.js.map +0 -1
- package/dist/lib/ai/base-provider.test.d.ts +0 -7
- package/dist/lib/ai/base-provider.test.d.ts.map +0 -1
- package/dist/lib/ai/base-provider.test.js +0 -319
- package/dist/lib/ai/base-provider.test.js.map +0 -1
- package/dist/lib/ai/cli-provider.test.d.ts +0 -5
- package/dist/lib/ai/cli-provider.test.d.ts.map +0 -1
- package/dist/lib/ai/cli-provider.test.js +0 -460
- package/dist/lib/ai/cli-provider.test.js.map +0 -1
- package/dist/lib/ai/fallback-provider.test.d.ts +0 -7
- package/dist/lib/ai/fallback-provider.test.d.ts.map +0 -1
- package/dist/lib/ai/fallback-provider.test.js +0 -165
- package/dist/lib/ai/fallback-provider.test.js.map +0 -1
- package/dist/lib/ai/generation-service.test.d.ts +0 -7
- package/dist/lib/ai/generation-service.test.d.ts.map +0 -1
- package/dist/lib/ai/generation-service.test.js +0 -213
- package/dist/lib/ai/generation-service.test.js.map +0 -1
- package/dist/lib/ai/provider-manager.test.d.ts +0 -5
- package/dist/lib/ai/provider-manager.test.d.ts.map +0 -1
- package/dist/lib/ai/provider-manager.test.js +0 -312
- package/dist/lib/ai/provider-manager.test.js.map +0 -1
- package/dist/lib/ai/repo-docs.test.d.ts +0 -5
- package/dist/lib/ai/repo-docs.test.d.ts.map +0 -1
- package/dist/lib/ai/repo-docs.test.js +0 -357
- package/dist/lib/ai/repo-docs.test.js.map +0 -1
- package/dist/lib/cleanpr/args.test.d.ts +0 -2
- package/dist/lib/cleanpr/args.test.d.ts.map +0 -1
- package/dist/lib/cleanpr/args.test.js +0 -269
- package/dist/lib/cleanpr/args.test.js.map +0 -1
- package/dist/lib/cleanpr/cleanup.test.d.ts +0 -2
- package/dist/lib/cleanpr/cleanup.test.d.ts.map +0 -1
- package/dist/lib/cleanpr/cleanup.test.js +0 -296
- package/dist/lib/cleanpr/cleanup.test.js.map +0 -1
- package/dist/lib/cleanpr/worktree-info.test.d.ts +0 -2
- package/dist/lib/cleanpr/worktree-info.test.d.ts.map +0 -1
- package/dist/lib/cleanpr/worktree-info.test.js +0 -228
- package/dist/lib/cleanpr/worktree-info.test.js.map +0 -1
- package/dist/lib/colors.test.d.ts +0 -2
- package/dist/lib/colors.test.d.ts.map +0 -1
- package/dist/lib/colors.test.js +0 -142
- package/dist/lib/colors.test.js.map +0 -1
- package/dist/lib/config-editor.test.d.ts +0 -11
- package/dist/lib/config-editor.test.d.ts.map +0 -1
- package/dist/lib/config-editor.test.js +0 -526
- package/dist/lib/config-editor.test.js.map +0 -1
- package/dist/lib/config-migration/detector.test.d.ts +0 -5
- package/dist/lib/config-migration/detector.test.d.ts.map +0 -1
- package/dist/lib/config-migration/detector.test.js +0 -201
- package/dist/lib/config-migration/detector.test.js.map +0 -1
- package/dist/lib/config-migration/reporter.test.d.ts +0 -5
- package/dist/lib/config-migration/reporter.test.d.ts.map +0 -1
- package/dist/lib/config-migration/reporter.test.js +0 -305
- package/dist/lib/config-migration/reporter.test.js.map +0 -1
- package/dist/lib/config-migration/runner.test.d.ts +0 -5
- package/dist/lib/config-migration/runner.test.d.ts.map +0 -1
- package/dist/lib/config-migration/runner.test.js +0 -235
- package/dist/lib/config-migration/runner.test.js.map +0 -1
- package/dist/lib/config-validation.test.d.ts +0 -5
- package/dist/lib/config-validation.test.d.ts.map +0 -1
- package/dist/lib/config-validation.test.js +0 -423
- package/dist/lib/config-validation.test.js.map +0 -1
- package/dist/lib/config.test.d.ts +0 -2
- package/dist/lib/config.test.d.ts.map +0 -1
- package/dist/lib/config.test.js +0 -554
- package/dist/lib/config.test.js.map +0 -1
- package/dist/lib/constants.test.d.ts +0 -5
- package/dist/lib/constants.test.d.ts.map +0 -1
- package/dist/lib/constants.test.js +0 -180
- package/dist/lib/constants.test.js.map +0 -1
- package/dist/lib/deprecation.test.d.ts +0 -2
- package/dist/lib/deprecation.test.d.ts.map +0 -1
- package/dist/lib/deprecation.test.js +0 -71
- package/dist/lib/deprecation.test.js.map +0 -1
- package/dist/lib/errors.test.d.ts +0 -2
- package/dist/lib/errors.test.d.ts.map +0 -1
- package/dist/lib/errors.test.js +0 -117
- package/dist/lib/errors.test.js.map +0 -1
- package/dist/lib/git.test.d.ts +0 -2
- package/dist/lib/git.test.d.ts.map +0 -1
- package/dist/lib/git.test.js +0 -608
- package/dist/lib/git.test.js.map +0 -1
- package/dist/lib/github.test.d.ts +0 -2
- package/dist/lib/github.test.d.ts.map +0 -1
- package/dist/lib/github.test.js +0 -441
- package/dist/lib/github.test.js.map +0 -1
- package/dist/lib/global-check.test.d.ts +0 -5
- package/dist/lib/global-check.test.d.ts.map +0 -1
- package/dist/lib/global-check.test.js +0 -150
- package/dist/lib/global-check.test.js.map +0 -1
- package/dist/lib/global-config.test.d.ts +0 -5
- package/dist/lib/global-config.test.d.ts.map +0 -1
- package/dist/lib/global-config.test.js +0 -282
- package/dist/lib/global-config.test.js.map +0 -1
- package/dist/lib/hooks/confirmation.test.d.ts +0 -7
- package/dist/lib/hooks/confirmation.test.d.ts.map +0 -1
- package/dist/lib/hooks/confirmation.test.js +0 -300
- package/dist/lib/hooks/confirmation.test.js.map +0 -1
- package/dist/lib/hooks/executor.test.d.ts +0 -5
- package/dist/lib/hooks/executor.test.d.ts.map +0 -1
- package/dist/lib/hooks/executor.test.js +0 -648
- package/dist/lib/hooks/executor.test.js.map +0 -1
- package/dist/lib/hooks/templates.test.d.ts +0 -5
- package/dist/lib/hooks/templates.test.d.ts.map +0 -1
- package/dist/lib/hooks/templates.test.js +0 -163
- package/dist/lib/hooks/templates.test.js.map +0 -1
- package/dist/lib/hooks/types.test.d.ts +0 -5
- package/dist/lib/hooks/types.test.d.ts.map +0 -1
- package/dist/lib/hooks/types.test.js +0 -132
- package/dist/lib/hooks/types.test.js.map +0 -1
- package/dist/lib/json-output.test.d.ts +0 -5
- package/dist/lib/json-output.test.d.ts.map +0 -1
- package/dist/lib/json-output.test.js +0 -261
- package/dist/lib/json-output.test.js.map +0 -1
- package/dist/lib/logger.test.d.ts +0 -14
- package/dist/lib/logger.test.d.ts.map +0 -1
- package/dist/lib/logger.test.js +0 -692
- package/dist/lib/logger.test.js.map +0 -1
- package/dist/lib/lswt/action-executors.test.d.ts +0 -2
- package/dist/lib/lswt/action-executors.test.d.ts.map +0 -1
- package/dist/lib/lswt/action-executors.test.js +0 -1127
- package/dist/lib/lswt/action-executors.test.js.map +0 -1
- package/dist/lib/lswt/actions.test.d.ts +0 -2
- package/dist/lib/lswt/actions.test.d.ts.map +0 -1
- package/dist/lib/lswt/actions.test.js +0 -497
- package/dist/lib/lswt/actions.test.js.map +0 -1
- package/dist/lib/lswt/args.test.d.ts +0 -2
- package/dist/lib/lswt/args.test.d.ts.map +0 -1
- package/dist/lib/lswt/args.test.js +0 -195
- package/dist/lib/lswt/args.test.js.map +0 -1
- package/dist/lib/lswt/environment.test.d.ts +0 -2
- package/dist/lib/lswt/environment.test.d.ts.map +0 -1
- package/dist/lib/lswt/environment.test.js +0 -544
- package/dist/lib/lswt/environment.test.js.map +0 -1
- package/dist/lib/lswt/formatters.test.d.ts +0 -2
- package/dist/lib/lswt/formatters.test.d.ts.map +0 -1
- package/dist/lib/lswt/formatters.test.js +0 -323
- package/dist/lib/lswt/formatters.test.js.map +0 -1
- package/dist/lib/lswt/fuzzy-search.test.d.ts +0 -5
- package/dist/lib/lswt/fuzzy-search.test.d.ts.map +0 -1
- package/dist/lib/lswt/fuzzy-search.test.js +0 -207
- package/dist/lib/lswt/fuzzy-search.test.js.map +0 -1
- package/dist/lib/lswt/interactive.test.d.ts +0 -2
- package/dist/lib/lswt/interactive.test.d.ts.map +0 -1
- package/dist/lib/lswt/interactive.test.js +0 -771
- package/dist/lib/lswt/interactive.test.js.map +0 -1
- package/dist/lib/lswt/table.test.d.ts +0 -5
- package/dist/lib/lswt/table.test.d.ts.map +0 -1
- package/dist/lib/lswt/table.test.js +0 -262
- package/dist/lib/lswt/table.test.js.map +0 -1
- package/dist/lib/lswt/worktree-info.test.d.ts +0 -2
- package/dist/lib/lswt/worktree-info.test.d.ts.map +0 -1
- package/dist/lib/lswt/worktree-info.test.js +0 -484
- package/dist/lib/lswt/worktree-info.test.js.map +0 -1
- package/dist/lib/newpr/action-deps.test.d.ts +0 -5
- package/dist/lib/newpr/action-deps.test.d.ts.map +0 -1
- package/dist/lib/newpr/action-deps.test.js +0 -111
- package/dist/lib/newpr/action-deps.test.js.map +0 -1
- package/dist/lib/newpr/actions.test.d.ts +0 -2
- package/dist/lib/newpr/actions.test.d.ts.map +0 -1
- package/dist/lib/newpr/actions.test.js +0 -254
- package/dist/lib/newpr/actions.test.js.map +0 -1
- package/dist/lib/newpr/args.test.d.ts +0 -2
- package/dist/lib/newpr/args.test.d.ts.map +0 -1
- package/dist/lib/newpr/args.test.js +0 -479
- package/dist/lib/newpr/args.test.js.map +0 -1
- package/dist/lib/newpr/hook-runner.test.d.ts +0 -7
- package/dist/lib/newpr/hook-runner.test.d.ts.map +0 -1
- package/dist/lib/newpr/hook-runner.test.js +0 -422
- package/dist/lib/newpr/hook-runner.test.js.map +0 -1
- package/dist/lib/newpr/plan-generator.test.d.ts +0 -7
- package/dist/lib/newpr/plan-generator.test.d.ts.map +0 -1
- package/dist/lib/newpr/plan-generator.test.js +0 -387
- package/dist/lib/newpr/plan-generator.test.js.map +0 -1
- package/dist/lib/newpr/scenario-handler.test.d.ts +0 -2
- package/dist/lib/newpr/scenario-handler.test.d.ts.map +0 -1
- package/dist/lib/newpr/scenario-handler.test.js +0 -256
- package/dist/lib/newpr/scenario-handler.test.js.map +0 -1
- package/dist/lib/prompts.test.d.ts +0 -2
- package/dist/lib/prompts.test.d.ts.map +0 -1
- package/dist/lib/prompts.test.js +0 -807
- package/dist/lib/prompts.test.js.map +0 -1
- package/dist/lib/prs/actions.test.d.ts +0 -5
- package/dist/lib/prs/actions.test.d.ts.map +0 -1
- package/dist/lib/prs/actions.test.js +0 -356
- package/dist/lib/prs/actions.test.js.map +0 -1
- package/dist/lib/prs/command.test.d.ts +0 -11
- package/dist/lib/prs/command.test.d.ts.map +0 -1
- package/dist/lib/prs/command.test.js +0 -409
- package/dist/lib/prs/command.test.js.map +0 -1
- package/dist/lib/prs/data.test.d.ts +0 -5
- package/dist/lib/prs/data.test.d.ts.map +0 -1
- package/dist/lib/prs/data.test.js +0 -417
- package/dist/lib/prs/data.test.js.map +0 -1
- package/dist/lib/prs/details.test.d.ts +0 -5
- package/dist/lib/prs/details.test.d.ts.map +0 -1
- package/dist/lib/prs/details.test.js +0 -325
- package/dist/lib/prs/details.test.js.map +0 -1
- package/dist/lib/prs/filters.test.d.ts +0 -5
- package/dist/lib/prs/filters.test.d.ts.map +0 -1
- package/dist/lib/prs/filters.test.js +0 -312
- package/dist/lib/prs/filters.test.js.map +0 -1
- package/dist/lib/prs/formatters.test.d.ts +0 -2
- package/dist/lib/prs/formatters.test.d.ts.map +0 -1
- package/dist/lib/prs/formatters.test.js +0 -387
- package/dist/lib/prs/formatters.test.js.map +0 -1
- package/dist/lib/prs/interactive.test.d.ts +0 -5
- package/dist/lib/prs/interactive.test.d.ts.map +0 -1
- package/dist/lib/prs/interactive.test.js +0 -517
- package/dist/lib/prs/interactive.test.js.map +0 -1
- package/dist/lib/schema.test.d.ts +0 -10
- package/dist/lib/schema.test.d.ts.map +0 -1
- package/dist/lib/schema.test.js +0 -309
- package/dist/lib/schema.test.js.map +0 -1
- package/dist/lib/state-detection.test.d.ts +0 -2
- package/dist/lib/state-detection.test.d.ts.map +0 -1
- package/dist/lib/state-detection.test.js +0 -451
- package/dist/lib/state-detection.test.js.map +0 -1
- package/dist/lib/ui/error.test.d.ts +0 -2
- package/dist/lib/ui/error.test.d.ts.map +0 -1
- package/dist/lib/ui/error.test.js +0 -143
- package/dist/lib/ui/error.test.js.map +0 -1
- package/dist/lib/ui/output.test.d.ts +0 -2
- package/dist/lib/ui/output.test.d.ts.map +0 -1
- package/dist/lib/ui/output.test.js +0 -59
- package/dist/lib/ui/output.test.js.map +0 -1
- package/dist/lib/ui/status.test.d.ts +0 -2
- package/dist/lib/ui/status.test.d.ts.map +0 -1
- package/dist/lib/ui/status.test.js +0 -158
- package/dist/lib/ui/status.test.js.map +0 -1
- package/dist/lib/ui/table.test.d.ts +0 -2
- package/dist/lib/ui/table.test.d.ts.map +0 -1
- package/dist/lib/ui/table.test.js +0 -115
- package/dist/lib/ui/table.test.js.map +0 -1
- package/dist/lib/ui/theme.test.d.ts +0 -2
- package/dist/lib/ui/theme.test.d.ts.map +0 -1
- package/dist/lib/ui/theme.test.js +0 -76
- package/dist/lib/ui/theme.test.js.map +0 -1
- package/dist/lib/wtconfig/config-manager.test.d.ts +0 -5
- package/dist/lib/wtconfig/config-manager.test.d.ts.map +0 -1
- package/dist/lib/wtconfig/config-manager.test.js +0 -501
- package/dist/lib/wtconfig/config-manager.test.js.map +0 -1
- package/dist/lib/wtconfig/environment.test.d.ts +0 -5
- package/dist/lib/wtconfig/environment.test.d.ts.map +0 -1
- package/dist/lib/wtconfig/environment.test.js +0 -285
- package/dist/lib/wtconfig/environment.test.js.map +0 -1
- package/dist/lib/wtlink/config-manifest.test.d.ts +0 -2
- package/dist/lib/wtlink/config-manifest.test.d.ts.map +0 -1
- package/dist/lib/wtlink/config-manifest.test.js +0 -486
- package/dist/lib/wtlink/config-manifest.test.js.map +0 -1
- package/dist/lib/wtlink/link-configs.test.d.ts +0 -2
- package/dist/lib/wtlink/link-configs.test.d.ts.map +0 -1
- package/dist/lib/wtlink/link-configs.test.js +0 -612
- package/dist/lib/wtlink/link-configs.test.js.map +0 -1
- package/dist/lib/wtlink/main-menu.test.d.ts +0 -5
- package/dist/lib/wtlink/main-menu.test.d.ts.map +0 -1
- package/dist/lib/wtlink/main-menu.test.js +0 -126
- package/dist/lib/wtlink/main-menu.test.js.map +0 -1
- package/dist/lib/wtlink/manage-manifest.test.d.ts +0 -2
- package/dist/lib/wtlink/manage-manifest.test.d.ts.map +0 -1
- package/dist/lib/wtlink/manage-manifest.test.js +0 -714
- package/dist/lib/wtlink/manage-manifest.test.js.map +0 -1
- package/dist/lib/wtlink/validate-manifest.test.d.ts +0 -2
- package/dist/lib/wtlink/validate-manifest.test.d.ts.map +0 -1
- package/dist/lib/wtlink/validate-manifest.test.js +0 -220
- package/dist/lib/wtlink/validate-manifest.test.js.map +0 -1
- package/dist/lib/wtstate/analyze.test.d.ts +0 -5
- package/dist/lib/wtstate/analyze.test.d.ts.map +0 -1
- package/dist/lib/wtstate/analyze.test.js +0 -282
- package/dist/lib/wtstate/analyze.test.js.map +0 -1
- package/dist/lib/wtstate/args.test.d.ts +0 -5
- package/dist/lib/wtstate/args.test.d.ts.map +0 -1
- package/dist/lib/wtstate/args.test.js +0 -120
- package/dist/lib/wtstate/args.test.js.map +0 -1
- package/dist/mcp/server.test.d.ts +0 -9
- package/dist/mcp/server.test.d.ts.map +0 -1
- package/dist/mcp/server.test.js +0 -550
- package/dist/mcp/server.test.js.map +0 -1
package/dist/lib/logger.test.js
DELETED
|
@@ -1,692 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Comprehensive tests for logger.ts (consola-based)
|
|
3
|
-
*
|
|
4
|
-
* Covers:
|
|
5
|
-
* - parseLogLevel mapping
|
|
6
|
-
* - LogLevel compatibility export
|
|
7
|
-
* - initializeLogger level resolution (flag precedence)
|
|
8
|
-
* - DEBUG=newpr deprecation path
|
|
9
|
-
* - AuditFileReporter (write, JSONL, directory creation, rotation)
|
|
10
|
-
* - ConditionalStderrReporter (verbose/non-verbose conditional output)
|
|
11
|
-
* - Process exit handler (synchronous audit summary)
|
|
12
|
-
*/
|
|
13
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
14
|
-
import fs from 'fs';
|
|
15
|
-
import path from 'path';
|
|
16
|
-
import os from 'os';
|
|
17
|
-
import { parseLogLevel, initializeLogger, logger, LogLevel, setAuditContext, _resetForTesting, } from './logger.js';
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
// Test-level helpers
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
/** Saved env vars to restore after each test */
|
|
22
|
-
let savedEnv;
|
|
23
|
-
/** Per-test temp directory */
|
|
24
|
-
let tempDir;
|
|
25
|
-
function createTempDir() {
|
|
26
|
-
return fs.mkdtempSync(path.join(os.tmpdir(), 'logger-test-'));
|
|
27
|
-
}
|
|
28
|
-
function cleanupTempDir(dir) {
|
|
29
|
-
if (dir && fs.existsSync(dir)) {
|
|
30
|
-
fs.rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Wait for an audit log file to have non-empty content.
|
|
35
|
-
* Polls every 50ms up to the given timeout (default 2s).
|
|
36
|
-
* WriteStream flush timing varies across platforms/Node versions.
|
|
37
|
-
*/
|
|
38
|
-
async function waitForAuditContent(filePath, timeoutMs = 2000) {
|
|
39
|
-
const start = Date.now();
|
|
40
|
-
while (Date.now() - start < timeoutMs) {
|
|
41
|
-
try {
|
|
42
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
43
|
-
if (content.length > 0)
|
|
44
|
-
return content;
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
// file may not exist yet
|
|
48
|
-
}
|
|
49
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
50
|
-
}
|
|
51
|
-
// Final attempt — return whatever is there (may be empty, test will fail with a clear message)
|
|
52
|
-
try {
|
|
53
|
-
return fs.readFileSync(filePath, 'utf-8');
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
return '';
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
// ---------------------------------------------------------------------------
|
|
60
|
-
// parseLogLevel
|
|
61
|
-
// ---------------------------------------------------------------------------
|
|
62
|
-
describe('parseLogLevel', () => {
|
|
63
|
-
it('parses "debug" to 4', () => {
|
|
64
|
-
expect(parseLogLevel('debug')).toBe(4);
|
|
65
|
-
});
|
|
66
|
-
it('parses "info" to 3', () => {
|
|
67
|
-
expect(parseLogLevel('info')).toBe(3);
|
|
68
|
-
});
|
|
69
|
-
it('parses "warn" to 1', () => {
|
|
70
|
-
expect(parseLogLevel('warn')).toBe(1);
|
|
71
|
-
});
|
|
72
|
-
it('parses "warning" to 1', () => {
|
|
73
|
-
expect(parseLogLevel('warning')).toBe(1);
|
|
74
|
-
});
|
|
75
|
-
it('parses "error" to 0', () => {
|
|
76
|
-
expect(parseLogLevel('error')).toBe(0);
|
|
77
|
-
});
|
|
78
|
-
it('parses "silent" to -999', () => {
|
|
79
|
-
expect(parseLogLevel('silent')).toBe(-999);
|
|
80
|
-
});
|
|
81
|
-
it('parses "trace" to 5', () => {
|
|
82
|
-
expect(parseLogLevel('trace')).toBe(5);
|
|
83
|
-
});
|
|
84
|
-
it('parses "verbose" to 4 (alias for debug)', () => {
|
|
85
|
-
expect(parseLogLevel('verbose')).toBe(4);
|
|
86
|
-
});
|
|
87
|
-
it('is case insensitive — "DEBUG" returns 4', () => {
|
|
88
|
-
expect(parseLogLevel('DEBUG')).toBe(4);
|
|
89
|
-
});
|
|
90
|
-
it('is case insensitive — mixed case "Error" returns 0', () => {
|
|
91
|
-
expect(parseLogLevel('Error')).toBe(0);
|
|
92
|
-
});
|
|
93
|
-
it('returns undefined for "unknown"', () => {
|
|
94
|
-
expect(parseLogLevel('unknown')).toBeUndefined();
|
|
95
|
-
});
|
|
96
|
-
it('returns undefined for empty string', () => {
|
|
97
|
-
expect(parseLogLevel('')).toBeUndefined();
|
|
98
|
-
});
|
|
99
|
-
it('returns undefined for numeric strings', () => {
|
|
100
|
-
expect(parseLogLevel('99')).toBeUndefined();
|
|
101
|
-
expect(parseLogLevel('3')).toBeUndefined();
|
|
102
|
-
});
|
|
103
|
-
it('trims whitespace', () => {
|
|
104
|
-
expect(parseLogLevel(' info ')).toBe(3);
|
|
105
|
-
expect(parseLogLevel('\tdebug\n')).toBe(4);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
// ---------------------------------------------------------------------------
|
|
109
|
-
// LogLevel compatibility export
|
|
110
|
-
// ---------------------------------------------------------------------------
|
|
111
|
-
describe('LogLevel compatibility export', () => {
|
|
112
|
-
it('LogLevel.SILENT exists and equals -999', () => {
|
|
113
|
-
expect(LogLevel.SILENT).toBe(-999);
|
|
114
|
-
});
|
|
115
|
-
it('LogLevel.ERROR equals 0', () => {
|
|
116
|
-
expect(LogLevel.ERROR).toBe(0);
|
|
117
|
-
});
|
|
118
|
-
it('LogLevel.WARN equals 1', () => {
|
|
119
|
-
expect(LogLevel.WARN).toBe(1);
|
|
120
|
-
});
|
|
121
|
-
it('LogLevel.INFO equals 3', () => {
|
|
122
|
-
expect(LogLevel.INFO).toBe(3);
|
|
123
|
-
});
|
|
124
|
-
it('LogLevel.DEBUG equals 4', () => {
|
|
125
|
-
expect(LogLevel.DEBUG).toBe(4);
|
|
126
|
-
});
|
|
127
|
-
it('LogLevel.TRACE equals 5', () => {
|
|
128
|
-
expect(LogLevel.TRACE).toBe(5);
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
// ---------------------------------------------------------------------------
|
|
132
|
-
// Logger singleton
|
|
133
|
-
// ---------------------------------------------------------------------------
|
|
134
|
-
describe('Logger singleton', () => {
|
|
135
|
-
beforeEach(() => {
|
|
136
|
-
_resetForTesting();
|
|
137
|
-
});
|
|
138
|
-
it('returns same instance on repeated access', () => {
|
|
139
|
-
const instance1 = logger;
|
|
140
|
-
const instance2 = logger;
|
|
141
|
-
expect(instance1).toBe(instance2);
|
|
142
|
-
});
|
|
143
|
-
it('defaults to level 3 (INFO) after reset', () => {
|
|
144
|
-
expect(logger.level).toBe(3);
|
|
145
|
-
});
|
|
146
|
-
it('has standard logging methods', () => {
|
|
147
|
-
expect(typeof logger.error).toBe('function');
|
|
148
|
-
expect(typeof logger.warn).toBe('function');
|
|
149
|
-
expect(typeof logger.info).toBe('function');
|
|
150
|
-
expect(typeof logger.debug).toBe('function');
|
|
151
|
-
expect(typeof logger.trace).toBe('function');
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
// ---------------------------------------------------------------------------
|
|
155
|
-
// initializeLogger — level resolution
|
|
156
|
-
// ---------------------------------------------------------------------------
|
|
157
|
-
describe('initializeLogger level resolution', () => {
|
|
158
|
-
beforeEach(() => {
|
|
159
|
-
_resetForTesting();
|
|
160
|
-
savedEnv = {
|
|
161
|
-
GWT_LOG_LEVEL: process.env.GWT_LOG_LEVEL,
|
|
162
|
-
DEBUG: process.env.DEBUG,
|
|
163
|
-
NO_COLOR: process.env.NO_COLOR,
|
|
164
|
-
};
|
|
165
|
-
delete process.env.GWT_LOG_LEVEL;
|
|
166
|
-
delete process.env.DEBUG;
|
|
167
|
-
});
|
|
168
|
-
afterEach(() => {
|
|
169
|
-
_resetForTesting();
|
|
170
|
-
for (const [key, value] of Object.entries(savedEnv)) {
|
|
171
|
-
if (value === undefined) {
|
|
172
|
-
delete process.env[key];
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
process.env[key] = value;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
it('quiet flag sets level to 0 (error only) regardless of env', () => {
|
|
180
|
-
process.env.GWT_LOG_LEVEL = 'debug';
|
|
181
|
-
initializeLogger({ quiet: true });
|
|
182
|
-
expect(logger.level).toBe(0);
|
|
183
|
-
});
|
|
184
|
-
it('verbose flag sets level to 4 (debug)', () => {
|
|
185
|
-
initializeLogger({ verbose: true });
|
|
186
|
-
expect(logger.level).toBe(4);
|
|
187
|
-
});
|
|
188
|
-
it('GWT_LOG_LEVEL=debug with no flags sets level to 4', () => {
|
|
189
|
-
process.env.GWT_LOG_LEVEL = 'debug';
|
|
190
|
-
initializeLogger({});
|
|
191
|
-
expect(logger.level).toBe(4);
|
|
192
|
-
});
|
|
193
|
-
it('GWT_LOG_LEVEL=warn with no flags sets level to 1', () => {
|
|
194
|
-
process.env.GWT_LOG_LEVEL = 'warn';
|
|
195
|
-
initializeLogger({});
|
|
196
|
-
expect(logger.level).toBe(1);
|
|
197
|
-
});
|
|
198
|
-
it('quiet flag overrides GWT_LOG_LEVEL=debug (CLI flag wins)', () => {
|
|
199
|
-
process.env.GWT_LOG_LEVEL = 'debug';
|
|
200
|
-
initializeLogger({ quiet: true });
|
|
201
|
-
expect(logger.level).toBe(0);
|
|
202
|
-
});
|
|
203
|
-
it('no flags and no env var defaults to level 3 (INFO)', () => {
|
|
204
|
-
initializeLogger({});
|
|
205
|
-
expect(logger.level).toBe(3);
|
|
206
|
-
});
|
|
207
|
-
it('quiet flag takes priority over verbose when both are set', () => {
|
|
208
|
-
initializeLogger({ quiet: true, verbose: true });
|
|
209
|
-
expect(logger.level).toBe(0);
|
|
210
|
-
});
|
|
211
|
-
it('GWT_LOG_LEVEL with invalid value falls back to INFO', () => {
|
|
212
|
-
process.env.GWT_LOG_LEVEL = 'bananas';
|
|
213
|
-
initializeLogger({});
|
|
214
|
-
expect(logger.level).toBe(3);
|
|
215
|
-
});
|
|
216
|
-
it('verbose flag overrides GWT_LOG_LEVEL=warn (CLI flag wins)', () => {
|
|
217
|
-
process.env.GWT_LOG_LEVEL = 'warn';
|
|
218
|
-
initializeLogger({ verbose: true });
|
|
219
|
-
expect(logger.level).toBe(4);
|
|
220
|
-
});
|
|
221
|
-
it('sets reporters when called', () => {
|
|
222
|
-
initializeLogger({});
|
|
223
|
-
expect(logger.options.reporters).toBeDefined();
|
|
224
|
-
expect(logger.options.reporters.length).toBeGreaterThan(0);
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
// ---------------------------------------------------------------------------
|
|
228
|
-
// DEBUG=newpr deprecation path
|
|
229
|
-
// ---------------------------------------------------------------------------
|
|
230
|
-
describe('DEBUG=newpr deprecation path', () => {
|
|
231
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
232
|
-
let stderrSpy;
|
|
233
|
-
beforeEach(() => {
|
|
234
|
-
_resetForTesting();
|
|
235
|
-
savedEnv = {
|
|
236
|
-
GWT_LOG_LEVEL: process.env.GWT_LOG_LEVEL,
|
|
237
|
-
DEBUG: process.env.DEBUG,
|
|
238
|
-
};
|
|
239
|
-
delete process.env.GWT_LOG_LEVEL;
|
|
240
|
-
delete process.env.DEBUG;
|
|
241
|
-
stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
242
|
-
});
|
|
243
|
-
afterEach(() => {
|
|
244
|
-
stderrSpy.mockRestore();
|
|
245
|
-
_resetForTesting();
|
|
246
|
-
for (const [key, value] of Object.entries(savedEnv)) {
|
|
247
|
-
if (value === undefined) {
|
|
248
|
-
delete process.env[key];
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
process.env[key] = value;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
it('DEBUG=newpr sets level to 4 (debug) and prints deprecation warning', () => {
|
|
256
|
-
process.env.DEBUG = 'newpr';
|
|
257
|
-
initializeLogger({});
|
|
258
|
-
expect(logger.level).toBe(4);
|
|
259
|
-
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('WARNING: DEBUG=newpr is deprecated'));
|
|
260
|
-
});
|
|
261
|
-
it('DEBUG=newpr deprecation warning fires exactly once across multiple calls', () => {
|
|
262
|
-
process.env.DEBUG = 'newpr';
|
|
263
|
-
initializeLogger({});
|
|
264
|
-
initializeLogger({});
|
|
265
|
-
const deprecationCalls = stderrSpy.mock.calls.filter((call) => typeof call[0] === 'string' && call[0].includes('deprecated'));
|
|
266
|
-
expect(deprecationCalls).toHaveLength(1);
|
|
267
|
-
});
|
|
268
|
-
it('DEBUG=* activates debug level and prints deprecation warning', () => {
|
|
269
|
-
process.env.DEBUG = '*';
|
|
270
|
-
initializeLogger({});
|
|
271
|
-
expect(logger.level).toBe(4);
|
|
272
|
-
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('deprecated'));
|
|
273
|
-
});
|
|
274
|
-
it('DEBUG=1 activates debug level and prints deprecation warning', () => {
|
|
275
|
-
process.env.DEBUG = '1';
|
|
276
|
-
initializeLogger({});
|
|
277
|
-
expect(logger.level).toBe(4);
|
|
278
|
-
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('deprecated'));
|
|
279
|
-
});
|
|
280
|
-
it('DEBUG=something_else does NOT activate debug — level stays at default', () => {
|
|
281
|
-
process.env.DEBUG = 'something_else';
|
|
282
|
-
initializeLogger({});
|
|
283
|
-
expect(logger.level).toBe(3);
|
|
284
|
-
const deprecationCalls = stderrSpy.mock.calls.filter((call) => typeof call[0] === 'string' && call[0].includes('deprecated'));
|
|
285
|
-
expect(deprecationCalls).toHaveLength(0);
|
|
286
|
-
});
|
|
287
|
-
it('GWT_LOG_LEVEL takes priority over DEBUG=newpr', () => {
|
|
288
|
-
process.env.GWT_LOG_LEVEL = 'warn';
|
|
289
|
-
process.env.DEBUG = 'newpr';
|
|
290
|
-
initializeLogger({});
|
|
291
|
-
expect(logger.level).toBe(1);
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
// ---------------------------------------------------------------------------
|
|
295
|
-
// _resetForTesting
|
|
296
|
-
// ---------------------------------------------------------------------------
|
|
297
|
-
describe('_resetForTesting', () => {
|
|
298
|
-
it('resets logger level to INFO (3)', () => {
|
|
299
|
-
logger.level = 0;
|
|
300
|
-
_resetForTesting();
|
|
301
|
-
expect(logger.level).toBe(3);
|
|
302
|
-
});
|
|
303
|
-
it('clears reporters', () => {
|
|
304
|
-
initializeLogger({ verbose: true });
|
|
305
|
-
_resetForTesting();
|
|
306
|
-
expect(logger.options.reporters).toEqual([]);
|
|
307
|
-
});
|
|
308
|
-
it('resets deprecation warning flag so it can fire again', () => {
|
|
309
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
310
|
-
const origDebug = process.env.DEBUG;
|
|
311
|
-
const origGwt = process.env.GWT_LOG_LEVEL;
|
|
312
|
-
delete process.env.GWT_LOG_LEVEL;
|
|
313
|
-
process.env.DEBUG = 'newpr';
|
|
314
|
-
initializeLogger({});
|
|
315
|
-
_resetForTesting();
|
|
316
|
-
delete process.env.GWT_LOG_LEVEL;
|
|
317
|
-
process.env.DEBUG = 'newpr';
|
|
318
|
-
initializeLogger({});
|
|
319
|
-
const deprecationCalls = stderrSpy.mock.calls.filter((call) => typeof call[0] === 'string' && call[0].includes('deprecated'));
|
|
320
|
-
expect(deprecationCalls).toHaveLength(2);
|
|
321
|
-
stderrSpy.mockRestore();
|
|
322
|
-
if (origDebug === undefined)
|
|
323
|
-
delete process.env.DEBUG;
|
|
324
|
-
else
|
|
325
|
-
process.env.DEBUG = origDebug;
|
|
326
|
-
if (origGwt === undefined)
|
|
327
|
-
delete process.env.GWT_LOG_LEVEL;
|
|
328
|
-
else
|
|
329
|
-
process.env.GWT_LOG_LEVEL = origGwt;
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
// ---------------------------------------------------------------------------
|
|
333
|
-
// AuditFileReporter
|
|
334
|
-
// ---------------------------------------------------------------------------
|
|
335
|
-
describe('AuditFileReporter', () => {
|
|
336
|
-
beforeEach(() => {
|
|
337
|
-
_resetForTesting();
|
|
338
|
-
tempDir = createTempDir();
|
|
339
|
-
savedEnv = {
|
|
340
|
-
GWT_LOG_LEVEL: process.env.GWT_LOG_LEVEL,
|
|
341
|
-
DEBUG: process.env.DEBUG,
|
|
342
|
-
};
|
|
343
|
-
delete process.env.GWT_LOG_LEVEL;
|
|
344
|
-
delete process.env.DEBUG;
|
|
345
|
-
});
|
|
346
|
-
afterEach(() => {
|
|
347
|
-
_resetForTesting();
|
|
348
|
-
cleanupTempDir(tempDir);
|
|
349
|
-
for (const [key, value] of Object.entries(savedEnv)) {
|
|
350
|
-
if (value === undefined) {
|
|
351
|
-
delete process.env[key];
|
|
352
|
-
}
|
|
353
|
-
else {
|
|
354
|
-
process.env[key] = value;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
it('writes a log entry to the audit log file', async () => {
|
|
359
|
-
const constantsMod = await import('./constants.js');
|
|
360
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue(tempDir);
|
|
361
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
362
|
-
initializeLogger({ commandName: 'test-cmd' });
|
|
363
|
-
logger.info('test audit message');
|
|
364
|
-
const auditPath = path.join(tempDir, 'audit.log');
|
|
365
|
-
const content = await waitForAuditContent(auditPath);
|
|
366
|
-
expect(content).toContain('test audit message');
|
|
367
|
-
stderrSpy.mockRestore();
|
|
368
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
369
|
-
});
|
|
370
|
-
it('audit log entries contain timestamp, level, and message', async () => {
|
|
371
|
-
const constantsMod = await import('./constants.js');
|
|
372
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue(tempDir);
|
|
373
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
374
|
-
initializeLogger({ commandName: 'test-cmd' });
|
|
375
|
-
logger.warn('something went wrong');
|
|
376
|
-
const auditPath = path.join(tempDir, 'audit.log');
|
|
377
|
-
const content = await waitForAuditContent(auditPath);
|
|
378
|
-
expect(content).toMatch(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/);
|
|
379
|
-
expect(content).toMatch(/WARN/);
|
|
380
|
-
expect(content).toContain('something went wrong');
|
|
381
|
-
stderrSpy.mockRestore();
|
|
382
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
383
|
-
});
|
|
384
|
-
it('writes JSONL entries when json mode is active', async () => {
|
|
385
|
-
const constantsMod = await import('./constants.js');
|
|
386
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue(tempDir);
|
|
387
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
388
|
-
initializeLogger({ json: true, commandName: 'test-cmd' });
|
|
389
|
-
logger.info('json test message');
|
|
390
|
-
const auditPath = path.join(tempDir, 'audit.log');
|
|
391
|
-
const content = (await waitForAuditContent(auditPath)).trim();
|
|
392
|
-
const lines = content.split('\n').filter((l) => l.trim().length > 0);
|
|
393
|
-
for (const line of lines) {
|
|
394
|
-
const parsed = JSON.parse(line);
|
|
395
|
-
expect(parsed).toHaveProperty('timestamp');
|
|
396
|
-
expect(parsed).toHaveProperty('level');
|
|
397
|
-
expect(parsed).toHaveProperty('message');
|
|
398
|
-
}
|
|
399
|
-
const hasMessage = lines.some((line) => {
|
|
400
|
-
const parsed = JSON.parse(line);
|
|
401
|
-
return parsed.message.includes('json test message');
|
|
402
|
-
});
|
|
403
|
-
expect(hasMessage).toBe(true);
|
|
404
|
-
stderrSpy.mockRestore();
|
|
405
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
406
|
-
});
|
|
407
|
-
it('creates audit directory automatically if it does not exist', async () => {
|
|
408
|
-
const nestedDir = path.join(tempDir, 'nested', 'subdir');
|
|
409
|
-
const constantsMod = await import('./constants.js');
|
|
410
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue(nestedDir);
|
|
411
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
412
|
-
expect(fs.existsSync(nestedDir)).toBe(false);
|
|
413
|
-
initializeLogger({ commandName: 'test-cmd' });
|
|
414
|
-
expect(fs.existsSync(nestedDir)).toBe(true);
|
|
415
|
-
stderrSpy.mockRestore();
|
|
416
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
417
|
-
});
|
|
418
|
-
});
|
|
419
|
-
// ---------------------------------------------------------------------------
|
|
420
|
-
// Rotation
|
|
421
|
-
// ---------------------------------------------------------------------------
|
|
422
|
-
describe('Audit log rotation', () => {
|
|
423
|
-
beforeEach(() => {
|
|
424
|
-
_resetForTesting();
|
|
425
|
-
tempDir = createTempDir();
|
|
426
|
-
savedEnv = {
|
|
427
|
-
GWT_LOG_LEVEL: process.env.GWT_LOG_LEVEL,
|
|
428
|
-
DEBUG: process.env.DEBUG,
|
|
429
|
-
};
|
|
430
|
-
delete process.env.GWT_LOG_LEVEL;
|
|
431
|
-
delete process.env.DEBUG;
|
|
432
|
-
});
|
|
433
|
-
afterEach(() => {
|
|
434
|
-
_resetForTesting();
|
|
435
|
-
cleanupTempDir(tempDir);
|
|
436
|
-
for (const [key, value] of Object.entries(savedEnv)) {
|
|
437
|
-
if (value === undefined) {
|
|
438
|
-
delete process.env[key];
|
|
439
|
-
}
|
|
440
|
-
else {
|
|
441
|
-
process.env[key] = value;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
it('rotates a file larger than 10MB to audit.log.1', async () => {
|
|
446
|
-
const constantsMod = await import('./constants.js');
|
|
447
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue(tempDir);
|
|
448
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
449
|
-
const auditPath = path.join(tempDir, 'audit.log');
|
|
450
|
-
const bigContent = 'x'.repeat(10 * 1024 * 1024 + 100);
|
|
451
|
-
fs.writeFileSync(auditPath, bigContent);
|
|
452
|
-
initializeLogger({ commandName: 'test-cmd' });
|
|
453
|
-
expect(fs.existsSync(path.join(tempDir, 'audit.log.1'))).toBe(true);
|
|
454
|
-
const rotatedContent = fs.readFileSync(path.join(tempDir, 'audit.log.1'), 'utf-8');
|
|
455
|
-
expect(rotatedContent).toBe(bigContent);
|
|
456
|
-
logger.info('post-rotation entry');
|
|
457
|
-
await waitForAuditContent(auditPath);
|
|
458
|
-
expect(fs.existsSync(auditPath)).toBe(true);
|
|
459
|
-
const newSize = fs.statSync(auditPath).size;
|
|
460
|
-
expect(newSize).toBeLessThan(10 * 1024 * 1024);
|
|
461
|
-
stderrSpy.mockRestore();
|
|
462
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
463
|
-
});
|
|
464
|
-
it('shifts existing rotated files: .1 becomes .2, original becomes .1, oldest deleted', async () => {
|
|
465
|
-
const constantsMod = await import('./constants.js');
|
|
466
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue(tempDir);
|
|
467
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
468
|
-
const auditPath = path.join(tempDir, 'audit.log');
|
|
469
|
-
const bigContent = 'x'.repeat(10 * 1024 * 1024 + 100);
|
|
470
|
-
fs.writeFileSync(auditPath, bigContent);
|
|
471
|
-
fs.writeFileSync(auditPath + '.1', 'rotated-1-content');
|
|
472
|
-
fs.writeFileSync(auditPath + '.2', 'rotated-2-content-to-be-deleted');
|
|
473
|
-
initializeLogger({ commandName: 'test-cmd' });
|
|
474
|
-
expect(fs.readFileSync(auditPath + '.2', 'utf-8')).toBe('rotated-1-content');
|
|
475
|
-
expect(fs.readFileSync(auditPath + '.1', 'utf-8')).toBe(bigContent);
|
|
476
|
-
stderrSpy.mockRestore();
|
|
477
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
478
|
-
});
|
|
479
|
-
it('rotation failure does not crash the tool', async () => {
|
|
480
|
-
const constantsMod = await import('./constants.js');
|
|
481
|
-
const badDir = path.join(tempDir, 'readonly-test');
|
|
482
|
-
fs.mkdirSync(badDir);
|
|
483
|
-
const auditPath = path.join(badDir, 'audit.log');
|
|
484
|
-
const bigContent = 'x'.repeat(10 * 1024 * 1024 + 100);
|
|
485
|
-
fs.writeFileSync(auditPath, bigContent);
|
|
486
|
-
fs.chmodSync(badDir, 0o444);
|
|
487
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue(badDir);
|
|
488
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
489
|
-
expect(() => initializeLogger({ commandName: 'test-cmd' })).not.toThrow();
|
|
490
|
-
fs.chmodSync(badDir, 0o755);
|
|
491
|
-
stderrSpy.mockRestore();
|
|
492
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
493
|
-
});
|
|
494
|
-
});
|
|
495
|
-
// ---------------------------------------------------------------------------
|
|
496
|
-
// ConditionalStderrReporter
|
|
497
|
-
// ---------------------------------------------------------------------------
|
|
498
|
-
describe('ConditionalStderrReporter', () => {
|
|
499
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
500
|
-
let stderrSpy;
|
|
501
|
-
beforeEach(() => {
|
|
502
|
-
_resetForTesting();
|
|
503
|
-
savedEnv = {
|
|
504
|
-
GWT_LOG_LEVEL: process.env.GWT_LOG_LEVEL,
|
|
505
|
-
DEBUG: process.env.DEBUG,
|
|
506
|
-
};
|
|
507
|
-
delete process.env.GWT_LOG_LEVEL;
|
|
508
|
-
delete process.env.DEBUG;
|
|
509
|
-
stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
510
|
-
});
|
|
511
|
-
afterEach(() => {
|
|
512
|
-
stderrSpy.mockRestore();
|
|
513
|
-
_resetForTesting();
|
|
514
|
-
for (const [key, value] of Object.entries(savedEnv)) {
|
|
515
|
-
if (value === undefined) {
|
|
516
|
-
delete process.env[key];
|
|
517
|
-
}
|
|
518
|
-
else {
|
|
519
|
-
process.env[key] = value;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
});
|
|
523
|
-
describe('non-verbose mode (default)', () => {
|
|
524
|
-
beforeEach(() => {
|
|
525
|
-
initializeLogger({});
|
|
526
|
-
});
|
|
527
|
-
it('error writes to stderr', () => {
|
|
528
|
-
logger.error('err-msg');
|
|
529
|
-
const errorCalls = stderrSpy.mock.calls.filter((call) => typeof call[0] === 'string' && call[0].includes('err-msg'));
|
|
530
|
-
expect(errorCalls.length).toBeGreaterThan(0);
|
|
531
|
-
});
|
|
532
|
-
it('warn writes to stderr', () => {
|
|
533
|
-
logger.warn('wrn-msg');
|
|
534
|
-
const warnCalls = stderrSpy.mock.calls.filter((call) => typeof call[0] === 'string' && call[0].includes('wrn-msg'));
|
|
535
|
-
expect(warnCalls.length).toBeGreaterThan(0);
|
|
536
|
-
});
|
|
537
|
-
it('info does NOT write to stderr', () => {
|
|
538
|
-
logger.info('inf-msg');
|
|
539
|
-
const infoCalls = stderrSpy.mock.calls.filter((call) => typeof call[0] === 'string' && call[0].includes('inf-msg'));
|
|
540
|
-
expect(infoCalls.length).toBe(0);
|
|
541
|
-
});
|
|
542
|
-
it('debug does NOT write to stderr', () => {
|
|
543
|
-
logger.debug('dbg-msg');
|
|
544
|
-
const debugCalls = stderrSpy.mock.calls.filter((call) => typeof call[0] === 'string' && call[0].includes('dbg-msg'));
|
|
545
|
-
expect(debugCalls.length).toBe(0);
|
|
546
|
-
});
|
|
547
|
-
});
|
|
548
|
-
describe('verbose mode', () => {
|
|
549
|
-
beforeEach(() => {
|
|
550
|
-
initializeLogger({ verbose: true });
|
|
551
|
-
});
|
|
552
|
-
it('error writes to stderr', () => {
|
|
553
|
-
logger.error('err-verbose');
|
|
554
|
-
const errorCalls = stderrSpy.mock.calls.filter((call) => typeof call[0] === 'string' && call[0].includes('err-verbose'));
|
|
555
|
-
expect(errorCalls.length).toBeGreaterThan(0);
|
|
556
|
-
});
|
|
557
|
-
it('warn writes to stderr', () => {
|
|
558
|
-
logger.warn('wrn-verbose');
|
|
559
|
-
const warnCalls = stderrSpy.mock.calls.filter((call) => typeof call[0] === 'string' && call[0].includes('wrn-verbose'));
|
|
560
|
-
expect(warnCalls.length).toBeGreaterThan(0);
|
|
561
|
-
});
|
|
562
|
-
it('info writes to stderr in verbose mode', () => {
|
|
563
|
-
logger.info('inf-verbose');
|
|
564
|
-
const infoCalls = stderrSpy.mock.calls.filter((call) => typeof call[0] === 'string' && call[0].includes('inf-verbose'));
|
|
565
|
-
expect(infoCalls.length).toBeGreaterThan(0);
|
|
566
|
-
});
|
|
567
|
-
it('debug writes to stderr in verbose mode', () => {
|
|
568
|
-
logger.debug('dbg-verbose');
|
|
569
|
-
const debugCalls = stderrSpy.mock.calls.filter((call) => typeof call[0] === 'string' && call[0].includes('dbg-verbose'));
|
|
570
|
-
expect(debugCalls.length).toBeGreaterThan(0);
|
|
571
|
-
});
|
|
572
|
-
});
|
|
573
|
-
});
|
|
574
|
-
// ---------------------------------------------------------------------------
|
|
575
|
-
// Process exit handler / audit session summary
|
|
576
|
-
// ---------------------------------------------------------------------------
|
|
577
|
-
describe('Process exit handler', () => {
|
|
578
|
-
beforeEach(() => {
|
|
579
|
-
_resetForTesting();
|
|
580
|
-
tempDir = createTempDir();
|
|
581
|
-
savedEnv = {
|
|
582
|
-
GWT_LOG_LEVEL: process.env.GWT_LOG_LEVEL,
|
|
583
|
-
DEBUG: process.env.DEBUG,
|
|
584
|
-
};
|
|
585
|
-
delete process.env.GWT_LOG_LEVEL;
|
|
586
|
-
delete process.env.DEBUG;
|
|
587
|
-
});
|
|
588
|
-
afterEach(() => {
|
|
589
|
-
_resetForTesting();
|
|
590
|
-
cleanupTempDir(tempDir);
|
|
591
|
-
for (const [key, value] of Object.entries(savedEnv)) {
|
|
592
|
-
if (value === undefined) {
|
|
593
|
-
delete process.env[key];
|
|
594
|
-
}
|
|
595
|
-
else {
|
|
596
|
-
process.env[key] = value;
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
});
|
|
600
|
-
it('exit handler writes audit summary via fs.appendFileSync', async () => {
|
|
601
|
-
const constantsMod = await import('./constants.js');
|
|
602
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue(tempDir);
|
|
603
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
604
|
-
const appendSpy = vi.spyOn(fs, 'appendFileSync');
|
|
605
|
-
initializeLogger({ commandName: 'test-exit' });
|
|
606
|
-
setAuditContext({ prNumber: 42 });
|
|
607
|
-
process.emit('exit', 0);
|
|
608
|
-
expect(appendSpy).toHaveBeenCalled();
|
|
609
|
-
const lastCall = appendSpy.mock.calls.find((call) => typeof call[1] === 'string' && call[1].includes('test-exit'));
|
|
610
|
-
expect(lastCall).toBeDefined();
|
|
611
|
-
const writtenContent = lastCall[1];
|
|
612
|
-
expect(writtenContent).toContain('test-exit');
|
|
613
|
-
expect(writtenContent).toContain('exit=0');
|
|
614
|
-
appendSpy.mockRestore();
|
|
615
|
-
stderrSpy.mockRestore();
|
|
616
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
617
|
-
});
|
|
618
|
-
it('exit handler includes duration as a positive number', async () => {
|
|
619
|
-
const constantsMod = await import('./constants.js');
|
|
620
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue(tempDir);
|
|
621
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
622
|
-
const appendSpy = vi.spyOn(fs, 'appendFileSync');
|
|
623
|
-
initializeLogger({ commandName: 'duration-test' });
|
|
624
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
625
|
-
process.emit('exit', 0);
|
|
626
|
-
const exitCall = appendSpy.mock.calls.find((call) => typeof call[1] === 'string' && call[1].includes('duration-test'));
|
|
627
|
-
expect(exitCall).toBeDefined();
|
|
628
|
-
const writtenContent = exitCall[1];
|
|
629
|
-
const durationMatch = writtenContent.match(/duration=(\d+)ms/);
|
|
630
|
-
expect(durationMatch).toBeTruthy();
|
|
631
|
-
const duration = parseInt(durationMatch[1], 10);
|
|
632
|
-
expect(duration).toBeGreaterThanOrEqual(0);
|
|
633
|
-
appendSpy.mockRestore();
|
|
634
|
-
stderrSpy.mockRestore();
|
|
635
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
636
|
-
});
|
|
637
|
-
it('exit handler writes JSON format when json mode is active', async () => {
|
|
638
|
-
const constantsMod = await import('./constants.js');
|
|
639
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue(tempDir);
|
|
640
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
641
|
-
const appendSpy = vi.spyOn(fs, 'appendFileSync');
|
|
642
|
-
initializeLogger({ json: true, commandName: 'json-exit-test' });
|
|
643
|
-
setAuditContext({ prNumber: 99 });
|
|
644
|
-
process.emit('exit', 1);
|
|
645
|
-
const exitCall = appendSpy.mock.calls.find((call) => typeof call[1] === 'string' && call[1].includes('json-exit-test'));
|
|
646
|
-
expect(exitCall).toBeDefined();
|
|
647
|
-
const writtenContent = exitCall[1].trim();
|
|
648
|
-
const parsed = JSON.parse(writtenContent);
|
|
649
|
-
expect(parsed.command).toBe('json-exit-test');
|
|
650
|
-
expect(parsed.exitCode).toBe(1);
|
|
651
|
-
expect(parsed.prNumber).toBe(99);
|
|
652
|
-
expect(parsed.type).toBe('session');
|
|
653
|
-
expect(parsed.durationMs).toBeGreaterThanOrEqual(0);
|
|
654
|
-
appendSpy.mockRestore();
|
|
655
|
-
stderrSpy.mockRestore();
|
|
656
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
657
|
-
});
|
|
658
|
-
it('exit handler fails silently if audit log path is inaccessible', async () => {
|
|
659
|
-
const constantsMod = await import('./constants.js');
|
|
660
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue('/nonexistent/path/deep/nest');
|
|
661
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
662
|
-
initializeLogger({ commandName: 'fail-silently-test' });
|
|
663
|
-
expect(() => process.emit('exit', 0)).not.toThrow();
|
|
664
|
-
stderrSpy.mockRestore();
|
|
665
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
666
|
-
});
|
|
667
|
-
});
|
|
668
|
-
// ---------------------------------------------------------------------------
|
|
669
|
-
// setAuditContext
|
|
670
|
-
// ---------------------------------------------------------------------------
|
|
671
|
-
describe('setAuditContext', () => {
|
|
672
|
-
beforeEach(() => {
|
|
673
|
-
_resetForTesting();
|
|
674
|
-
});
|
|
675
|
-
it('merges additional metadata into audit context', async () => {
|
|
676
|
-
const constantsMod = await import('./constants.js');
|
|
677
|
-
const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
678
|
-
tempDir = createTempDir();
|
|
679
|
-
vi.spyOn(constantsMod, 'getGlobalDataDir').mockReturnValue(tempDir);
|
|
680
|
-
const appendSpy = vi.spyOn(fs, 'appendFileSync');
|
|
681
|
-
initializeLogger({ commandName: 'context-test' });
|
|
682
|
-
setAuditContext({ worktreePath: '/tmp/worktree', prNumber: 123 });
|
|
683
|
-
process.emit('exit', 0);
|
|
684
|
-
const exitCall = appendSpy.mock.calls.find((call) => typeof call[1] === 'string' && call[1].includes('context-test'));
|
|
685
|
-
expect(exitCall).toBeDefined();
|
|
686
|
-
appendSpy.mockRestore();
|
|
687
|
-
stderrSpy.mockRestore();
|
|
688
|
-
vi.mocked(constantsMod.getGlobalDataDir).mockRestore();
|
|
689
|
-
cleanupTempDir(tempDir);
|
|
690
|
-
});
|
|
691
|
-
});
|
|
692
|
-
//# sourceMappingURL=logger.test.js.map
|