@venizia/dev-configs 0.4.7 → 0.4.8-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 +3 -3
- package/dist/checks/catalog.js.map +1 -1
- package/dist/checks/module-cycles.js.map +1 -1
- package/dist/checks/purity/manifest.js.map +1 -1
- package/dist/checks/purity/probe.js.map +1 -1
- package/dist/checks/purity/run.js.map +1 -1
- package/dist/checks/split-report.js.map +1 -1
- package/dist/checks/test-controls.js.map +1 -1
- package/dist/checks/test-dead-code.js.map +1 -1
- package/dist/checks/test-mutate.js.map +1 -1
- package/dist/checks/test-weight.js.map +1 -1
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/clean.js.map +1 -1
- package/dist/cli/codemod/async-style.d.ts +1 -1
- package/dist/cli/codemod/async-style.js +3 -3
- package/dist/cli/codemod/async-style.js.map +1 -1
- package/dist/cli/codemod/connector-imports.js.map +1 -1
- package/dist/cli/codemod/const-classes.js.map +1 -1
- package/dist/cli/codemod/drop-redundant-casts.js.map +1 -1
- package/dist/cli/codemod/files.js.map +1 -1
- package/dist/cli/codemod/index.js.map +1 -1
- package/dist/cli/codemod/namespace-functions/index.js.map +1 -1
- package/dist/cli/codemod/namespace-functions/logger-scope.js.map +1 -1
- package/dist/cli/codemod/namespace-functions/mapping.js.map +1 -1
- package/dist/cli/codemod/namespace-functions/rewriter.js.map +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/lint.js.map +1 -1
- package/dist/linters/eslint.js +7 -5
- package/dist/linters/eslint.js.map +1 -1
- package/dist/linters/house/async-rules.d.ts +10 -0
- package/dist/linters/house/async-rules.js +29 -0
- package/dist/linters/house/async-rules.js.map +1 -0
- package/dist/linters/house/await-support.d.ts +2 -0
- package/dist/linters/house/await-support.js +15 -10
- package/dist/linters/house/await-support.js.map +1 -1
- package/dist/linters/house/common.d.ts +2 -0
- package/dist/linters/house/common.js +2 -0
- package/dist/linters/house/common.js.map +1 -1
- package/dist/linters/house/configs.d.ts +3 -29
- package/dist/linters/house/configs.js +24 -51
- package/dist/linters/house/configs.js.map +1 -1
- package/dist/linters/house/const-class-values.rule.js.map +1 -1
- package/dist/linters/house/effect-cleanup-consistency.rule.js +2 -1
- package/dist/linters/house/effect-cleanup-consistency.rule.js.map +1 -1
- package/dist/linters/house/hook-support.js.map +1 -1
- package/dist/linters/house/index.d.ts +2 -1
- package/dist/linters/house/index.js +4 -1
- package/dist/linters/house/index.js.map +1 -1
- package/dist/linters/house/max-params-own.rule.js.map +1 -1
- package/dist/linters/house/no-async-hook-callback.rule.js.map +1 -1
- package/dist/linters/house/no-await-promise-chain.rule.js +2 -3
- package/dist/linters/house/no-await-promise-chain.rule.js.map +1 -1
- package/dist/linters/house/no-leaked-render.rule.js.map +1 -1
- package/dist/linters/house/no-return-await.rule.js +2 -8
- package/dist/linters/house/no-return-await.rule.js.map +1 -1
- package/dist/linters/house/no-silent-catch.rule.js +1 -1
- package/dist/linters/house/no-silent-catch.rule.js.map +1 -1
- package/dist/linters/house/no-unbraced-case.rule.d.ts +15 -0
- package/dist/linters/house/no-unbraced-case.rule.js +45 -0
- package/dist/linters/house/no-unbraced-case.rule.js.map +1 -0
- package/dist/linters/house/plugin.js +2 -0
- package/dist/linters/house/plugin.js.map +1 -1
- package/dist/linters/house/promise-chain-support.js.map +1 -1
- package/dist/linters/ignore.js.map +1 -1
- package/dist/linters/index.d.ts +1 -0
- package/dist/linters/index.js +1 -0
- package/dist/linters/index.js.map +1 -1
- package/dist/linters/padding.d.ts +8 -0
- package/dist/linters/padding.js +25 -0
- package/dist/linters/padding.js.map +1 -0
- package/dist/linters/rules/eqeqeq.rule.js.map +1 -1
- package/dist/linters/rules/index.d.ts +2 -0
- package/dist/linters/rules/index.js +2 -0
- package/dist/linters/rules/index.js.map +1 -1
- package/dist/linters/rules/lines-between-class-members.rule.d.ts +14 -0
- package/dist/linters/rules/lines-between-class-members.rule.js +17 -0
- package/dist/linters/rules/lines-between-class-members.rule.js.map +1 -0
- package/dist/linters/rules/naming-convention.rule.js.map +1 -1
- package/dist/linters/rules/no-restricted-imports.rule.js.map +1 -1
- package/dist/linters/rules/no-restricted-properties.rule.js.map +1 -1
- package/dist/linters/rules/no-unused-vars.rule.js.map +1 -1
- package/dist/linters/rules/padding-line-between-statements.rule.d.ts +16 -0
- package/dist/linters/rules/padding-line-between-statements.rule.js +25 -0
- package/dist/linters/rules/padding-line-between-statements.rule.js.map +1 -0
- package/dist/linters/rules/prefer-nullish-coalescing.rule.js.map +1 -1
- package/dist/linters/rules/switch-case-braces.rule.js.map +1 -1
- package/dist/testing/repo-tmp.js.map +1 -1
- package/package.json +3 -5
- package/dist/checks/catalog.d.ts.map +0 -1
- package/dist/checks/index.d.ts.map +0 -1
- package/dist/checks/module-cycles.d.ts.map +0 -1
- package/dist/checks/purity/manifest.d.ts.map +0 -1
- package/dist/checks/purity/probe.d.ts.map +0 -1
- package/dist/checks/purity/run.d.ts.map +0 -1
- package/dist/checks/split-report.d.ts.map +0 -1
- package/dist/checks/test-controls.d.ts.map +0 -1
- package/dist/checks/test-dead-code.d.ts.map +0 -1
- package/dist/checks/test-mutate.d.ts.map +0 -1
- package/dist/checks/test-weight.d.ts.map +0 -1
- package/dist/cli/check.d.ts.map +0 -1
- package/dist/cli/clean.d.ts.map +0 -1
- package/dist/cli/codemod/async-style.d.ts.map +0 -1
- package/dist/cli/codemod/connector-imports.d.ts.map +0 -1
- package/dist/cli/codemod/const-classes.d.ts.map +0 -1
- package/dist/cli/codemod/drop-redundant-casts.d.ts.map +0 -1
- package/dist/cli/codemod/files.d.ts.map +0 -1
- package/dist/cli/codemod/index.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/index.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/logger-scope.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/mapping.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/mappings/boot.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/mappings/connectors.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/mappings/core-server.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/mappings/core-worker.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/mappings/dev-configs.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/mappings/filter.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/mappings/helpers.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/mappings/index.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/mappings/inversion.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/mappings/kernel.d.ts.map +0 -1
- package/dist/cli/codemod/namespace-functions/rewriter.d.ts.map +0 -1
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/lint.d.ts.map +0 -1
- package/dist/compilers/bun.d.ts.map +0 -1
- package/dist/compilers/index.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/linters/browser.d.ts.map +0 -1
- package/dist/linters/eslint.d.ts.map +0 -1
- package/dist/linters/house/await-support.d.ts.map +0 -1
- package/dist/linters/house/common.d.ts.map +0 -1
- package/dist/linters/house/configs.d.ts.map +0 -1
- package/dist/linters/house/const-class-values.rule.d.ts.map +0 -1
- package/dist/linters/house/effect-cleanup-consistency.rule.d.ts.map +0 -1
- package/dist/linters/house/hook-support.d.ts.map +0 -1
- package/dist/linters/house/index.d.ts.map +0 -1
- package/dist/linters/house/max-params-own.rule.d.ts.map +0 -1
- package/dist/linters/house/no-async-hook-callback.rule.d.ts.map +0 -1
- package/dist/linters/house/no-await-promise-chain.rule.d.ts.map +0 -1
- package/dist/linters/house/no-inline-await.rule.d.ts.map +0 -1
- package/dist/linters/house/no-leaked-render.rule.d.ts.map +0 -1
- package/dist/linters/house/no-new-error.rule.d.ts.map +0 -1
- package/dist/linters/house/no-return-await.rule.d.ts.map +0 -1
- package/dist/linters/house/no-silent-catch.rule.d.ts.map +0 -1
- package/dist/linters/house/plugin.d.ts.map +0 -1
- package/dist/linters/house/promise-chain-support.d.ts.map +0 -1
- package/dist/linters/ignore.d.ts.map +0 -1
- package/dist/linters/index.d.ts.map +0 -1
- package/dist/linters/jsx-files.d.ts.map +0 -1
- package/dist/linters/oxlint-presets.d.ts.map +0 -1
- package/dist/linters/oxlint.d.ts.map +0 -1
- package/dist/linters/react-eslint.d.ts.map +0 -1
- package/dist/linters/react-oxlint.d.ts.map +0 -1
- package/dist/linters/rules/common.d.ts.map +0 -1
- package/dist/linters/rules/eqeqeq.rule.d.ts.map +0 -1
- package/dist/linters/rules/index.d.ts.map +0 -1
- package/dist/linters/rules/naming-convention.rule.d.ts.map +0 -1
- package/dist/linters/rules/no-restricted-imports.rule.d.ts.map +0 -1
- package/dist/linters/rules/no-restricted-properties.rule.d.ts.map +0 -1
- package/dist/linters/rules/no-unused-vars.rule.d.ts.map +0 -1
- package/dist/linters/rules/prefer-nullish-coalescing.rule.d.ts.map +0 -1
- package/dist/linters/rules/switch-case-braces.rule.d.ts.map +0 -1
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/rejection.helper.d.ts.map +0 -1
- package/dist/testing/repo-tmp.d.ts.map +0 -1
- package/dist/testing/spawn.helper.d.ts.map +0 -1
- package/dist/testing/tmpdir-preload.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-mutate.js","sourceRoot":"","sources":["../../src/checks/test-mutate.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from 'node:child_process';\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\n/**\n * Replays the mutation proof of the trim-tests method. A ledger line says: \"this test (the\n * candidate) is redundant because that test (the survivor) already catches the same break\". The\n * replay applies the break (the mutant) to a file, runs the survivor and the candidate, and puts the\n * file back. The survivor must go red. The candidate must go red too, unless the line says it is\n * vacuous and a second mutant leaves it green as well.\n *\n * The mutant edits the file the test really loads: the package's own `src` for a test that imports\n * through the `@/` alias, or the `dist` of the dependency for a test that reaches another package\n * through its `exports`. A rebuild is never needed.\n */\nexport interface IMutant {\n /** Repository-relative file to edit (a `src` file, or a `dist` file of a dependency). */\n file: string;\n /** Text that must occur exactly once in the file. */\n find: string;\n replace: string;\n}\n\nexport interface ILedgerLine {\n id: string;\n /** Repository-relative test file that is deleted. */\n candidate: string;\n /** Run only the cases whose name matches (`bun test -t`). Default: the whole file. */\n candidateName?: string;\n /** Repository-relative test file that stays. */\n survivor: string;\n survivorName?: string;\n /**\n * The break. An array applies every edit together: a survivor in the package that owns the code\n * loads its `src`, a candidate in another package loads that package's `dist`, so one break is two edits.\n */\n mutant: IMutant | IMutant[];\n /** The source line the mutant stands for, `path:line`; recorded, not used by the replay. */\n srcLine?: string;\n /** `red` (default): the candidate must fail. `vacuous`: it must stay green under `mutant` AND `secondMutant`. */\n expectCandidate?: 'red' | 'vacuous';\n secondMutant?: IMutant | IMutant[];\n}\n\nexport interface ILedger {\n mutants: ILedgerLine[];\n}\n\nexport interface ILedgerResult {\n id: string;\n survivorRed: boolean;\n candidateRed: boolean;\n /** Only for a `vacuous` line: whether the candidate also stayed green under the second mutant. */\n candidateGreenUnderSecond?: boolean;\n ok: boolean;\n problem?: string;\n}\n\nconst TEST_TIMEOUT_MILLISECONDS = 300_000;\n\n/** The one place this tool builds an `Error`: `getError` would make dev-configs depend on inversion, which depends on dev-configs. */\n// eslint-disable-next-line venizia/no-new-error -- getError would be a dev-configs -> inversion cycle\nconst replayError = (message: string): Error => new Error(message);\n\n/** The nearest folder at or above the test file that holds a `package.json`: where `bun test` runs. */\nconst packageDirectoryOf = (opts: { root: string; file: string }): string => {\n let current = dirname(join(opts.root, opts.file));\n\n for (;;) {\n if (existsSync(join(current, 'package.json'))) {\n return current;\n }\n\n const parent = dirname(current);\n if (parent === current || parent.length < opts.root.length) {\n return opts.root;\n }\n\n current = parent;\n }\n};\n\n/** Runs one test file (or the cases matching `name`) and reports whether it failed. */\nconst runIsRed = (opts: { root: string; file: string; name?: string }): boolean => {\n const directory = packageDirectoryOf({ root: opts.root, file: opts.file });\n const target = join(opts.root, opts.file).slice(directory.length + 1);\n const args = ['test', target, ...(opts.name ? ['-t', opts.name] : [])];\n const result = spawnSync('bun', args, {\n cwd: directory,\n encoding: 'utf8',\n timeout: TEST_TIMEOUT_MILLISECONDS,\n killSignal: 'SIGKILL',\n env: { ...process.env, NODE_ENV: 'test' },\n });\n\n if (result.error) {\n throw replayError(`[test-mutate] could not run bun test ${target}: ${result.error.message}`);\n }\n\n // A name filter that matches nothing runs no case and exits 0: that would read as \"green\" and could\n // hide a typo as a vacuous test, so a run that executed nothing is an unusable ledger line.\n const output = `${result.stdout ?? ''}${result.stderr ?? ''}`;\n const passed = Number(/^\\s*(\\d+) pass/m.exec(output)?.[1] ?? 0);\n const failed = Number(/^\\s*(\\d+) fail/m.exec(output)?.[1] ?? 0);\n\n if (passed + failed === 0) {\n throw replayError(\n `[test-mutate] bun test ${target}${opts.name ? ` -t ${opts.name}` : ''} ran no case | check the file and the name`,\n );\n }\n\n return result.status !== 0 || failed > 0;\n};\n\n/** Applies `mutant`, runs `action`, and puts the file back byte for byte, verified byte for byte. */\nconst withMutant = <T>(opts: {\n root: string;\n mutant: IMutant;\n scratch: string;\n id: string;\n action: () => T;\n}): T => {\n const path = join(opts.root, opts.mutant.file);\n const original = readFileSync(path);\n const text = original.toString('utf8');\n const occurrences = text.split(opts.mutant.find).length - 1;\n\n if (occurrences !== 1) {\n throw replayError(\n `[test-mutate][${opts.id}] \\`find\\` occurs ${occurrences} times in ${opts.mutant.file}, it must occur exactly once`,\n );\n }\n\n mkdirSync(opts.scratch, { recursive: true });\n const backup = join(opts.scratch, `test-mutate-${opts.id.replace(/[^\\w.-]/g, '_')}.orig`);\n if (existsSync(backup)) {\n throw replayError(\n `[test-mutate][${opts.id}] a backup from an interrupted run exists: ${backup} | restore ${opts.mutant.file} from it, then delete it`,\n );\n }\n\n writeFileSync(backup, original);\n\n let outcome: { value: T } | { error: unknown };\n\n try {\n writeFileSync(\n path,\n text.replace(opts.mutant.find, () => opts.mutant.replace),\n );\n outcome = { value: opts.action() };\n } catch (error) {\n outcome = { error };\n }\n\n // Restored whatever the action did, and checked, before its result or error is passed on.\n writeFileSync(path, original);\n\n if (!readFileSync(path).equals(original)) {\n throw replayError(\n `[test-mutate][${opts.id}] ${opts.mutant.file} was not restored | the backup is ${backup}`,\n );\n }\n\n rmSync(backup, { force: true });\n\n if ('error' in outcome) {\n throw outcome.error;\n }\n\n return outcome.value;\n};\n\n/** Applies every edit of `mutant`, runs `action`, and puts each file back byte for byte, verified byte for byte. */\nconst withMutants = <T>(opts: {\n root: string;\n mutant: IMutant | IMutant[];\n scratch: string;\n id: string;\n action: () => T;\n}): T => {\n const edits = Array.isArray(opts.mutant) ? opts.mutant : [opts.mutant];\n\n const apply = (index: number): T =>\n index === edits.length\n ? opts.action()\n : withMutant({\n root: opts.root,\n mutant: edits[index],\n scratch: opts.scratch,\n id: `${opts.id}-${index}`,\n action: () => apply(index + 1),\n });\n\n return apply(0);\n};\n\nexport class TestMutateCheck {\n /** Replays every line; never throws for a green survivor (that is a result), only for an unusable ledger. */\n static replayLedger(opts: { root: string; ledger: ILedger; scratch?: string }): ILedgerResult[] {\n const root = resolve(opts.root);\n const scratch = opts.scratch ?? join(root, '.agents/local/tmp');\n const results: ILedgerResult[] = [];\n\n for (const line of opts.ledger.mutants) {\n const { survivorRed, candidateRed } = withMutants({\n root,\n mutant: line.mutant,\n scratch,\n id: line.id,\n action: () => ({\n survivorRed: runIsRed({ root, file: line.survivor, name: line.survivorName }),\n candidateRed: runIsRed({ root, file: line.candidate, name: line.candidateName }),\n }),\n });\n const result: ILedgerResult = { id: line.id, survivorRed, candidateRed, ok: true };\n const expectation = line.expectCandidate ?? 'red';\n\n if (!survivorRed) {\n result.ok = false;\n result.problem =\n 'the survivor stayed green under the mutant: it does not cover the behaviour';\n } else if (expectation === 'red' && !candidateRed) {\n result.ok = false;\n result.problem =\n 'the candidate stayed green under the mutant: record it as vacuous with a second mutant, or pick a mutant it checks';\n } else if (expectation === 'vacuous') {\n if (!line.secondMutant) {\n result.ok = false;\n result.problem = 'a vacuous line needs a secondMutant';\n } else if (candidateRed) {\n result.ok = false;\n result.problem = 'the candidate went red under the mutant: it is not vacuous';\n } else {\n const greenUnderSecond = !withMutants({\n root,\n mutant: line.secondMutant,\n scratch,\n id: `${line.id}-second`,\n action: () => runIsRed({ root, file: line.candidate, name: line.candidateName }),\n });\n result.candidateGreenUnderSecond = greenUnderSecond;\n\n if (!greenUnderSecond) {\n result.ok = false;\n result.problem = 'the candidate went red under the second mutant: it is not vacuous';\n }\n }\n }\n\n results.push(result);\n }\n\n return results;\n }\n\n /** The report lines of a replay, one per ledger line and a closing tally. */\n static formatLedgerResults(opts: { results: ILedgerResult[] }): string[] {\n const { results } = opts;\n const lines = results.map(\n (result) =>\n `${result.ok ? 'ok ' : 'FAIL'} ${result.id}: survivor ${result.survivorRed ? 'red' : 'GREEN'}, candidate ${result.candidateRed ? 'red' : 'green'}${result.problem ? ` | ${result.problem}` : ''}`,\n );\n const failed = results.filter((result) => !result.ok).length;\n lines.push(\n `\\n[test-mutate] ${results.length - failed}/${results.length} ledger lines hold${failed ? `, ${failed} do not` : ''}.`,\n );\n\n return lines;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"test-mutate.js","sourceRoot":"","sources":["../../src/checks/test-mutate.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from 'node:child_process';\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\n/**\n * Replays the mutation proof of the trim-tests method. A ledger line says: \"this test (the\n * candidate) is redundant because that test (the survivor) already catches the same break\". The\n * replay applies the break (the mutant) to a file, runs the survivor and the candidate, and puts the\n * file back. The survivor must go red. The candidate must go red too, unless the line says it is\n * vacuous and a second mutant leaves it green as well.\n *\n * The mutant edits the file the test really loads: the package's own `src` for a test that imports\n * through the `@/` alias, or the `dist` of the dependency for a test that reaches another package\n * through its `exports`. A rebuild is never needed.\n */\nexport interface IMutant {\n /** Repository-relative file to edit (a `src` file, or a `dist` file of a dependency). */\n file: string;\n /** Text that must occur exactly once in the file. */\n find: string;\n replace: string;\n}\n\nexport interface ILedgerLine {\n id: string;\n /** Repository-relative test file that is deleted. */\n candidate: string;\n /** Run only the cases whose name matches (`bun test -t`). Default: the whole file. */\n candidateName?: string;\n /** Repository-relative test file that stays. */\n survivor: string;\n survivorName?: string;\n /**\n * The break. An array applies every edit together: a survivor in the package that owns the code\n * loads its `src`, a candidate in another package loads that package's `dist`, so one break is two edits.\n */\n mutant: IMutant | IMutant[];\n /** The source line the mutant stands for, `path:line`; recorded, not used by the replay. */\n srcLine?: string;\n /** `red` (default): the candidate must fail. `vacuous`: it must stay green under `mutant` AND `secondMutant`. */\n expectCandidate?: 'red' | 'vacuous';\n secondMutant?: IMutant | IMutant[];\n}\n\nexport interface ILedger {\n mutants: ILedgerLine[];\n}\n\nexport interface ILedgerResult {\n id: string;\n survivorRed: boolean;\n candidateRed: boolean;\n /** Only for a `vacuous` line: whether the candidate also stayed green under the second mutant. */\n candidateGreenUnderSecond?: boolean;\n ok: boolean;\n problem?: string;\n}\n\nconst TEST_TIMEOUT_MILLISECONDS = 300_000;\n\n/** The one place this tool builds an `Error`: `getError` would make dev-configs depend on inversion, which depends on dev-configs. */\n// eslint-disable-next-line venizia/no-new-error -- getError would be a dev-configs -> inversion cycle\nconst replayError = (message: string): Error => new Error(message);\n\n/** The nearest folder at or above the test file that holds a `package.json`: where `bun test` runs. */\nconst packageDirectoryOf = (opts: { root: string; file: string }): string => {\n let current = dirname(join(opts.root, opts.file));\n\n for (;;) {\n if (existsSync(join(current, 'package.json'))) {\n return current;\n }\n\n const parent = dirname(current);\n\n if (parent === current || parent.length < opts.root.length) {\n return opts.root;\n }\n\n current = parent;\n }\n};\n\n/** Runs one test file (or the cases matching `name`) and reports whether it failed. */\nconst runIsRed = (opts: { root: string; file: string; name?: string }): boolean => {\n const directory = packageDirectoryOf({ root: opts.root, file: opts.file });\n const target = join(opts.root, opts.file).slice(directory.length + 1);\n const args = ['test', target, ...(opts.name ? ['-t', opts.name] : [])];\n const result = spawnSync('bun', args, {\n cwd: directory,\n encoding: 'utf8',\n timeout: TEST_TIMEOUT_MILLISECONDS,\n killSignal: 'SIGKILL',\n env: { ...process.env, NODE_ENV: 'test' },\n });\n\n if (result.error) {\n throw replayError(`[test-mutate] could not run bun test ${target}: ${result.error.message}`);\n }\n\n // A name filter that matches nothing runs no case and exits 0: that would read as \"green\" and could\n // hide a typo as a vacuous test, so a run that executed nothing is an unusable ledger line.\n const output = `${result.stdout ?? ''}${result.stderr ?? ''}`;\n const passed = Number(/^\\s*(\\d+) pass/m.exec(output)?.[1] ?? 0);\n const failed = Number(/^\\s*(\\d+) fail/m.exec(output)?.[1] ?? 0);\n\n if (passed + failed === 0) {\n throw replayError(\n `[test-mutate] bun test ${target}${opts.name ? ` -t ${opts.name}` : ''} ran no case | check the file and the name`,\n );\n }\n\n return result.status !== 0 || failed > 0;\n};\n\n/** Applies `mutant`, runs `action`, and puts the file back byte for byte, verified byte for byte. */\nconst withMutant = <T>(opts: {\n root: string;\n mutant: IMutant;\n scratch: string;\n id: string;\n action: () => T;\n}): T => {\n const path = join(opts.root, opts.mutant.file);\n const original = readFileSync(path);\n const text = original.toString('utf8');\n const occurrences = text.split(opts.mutant.find).length - 1;\n\n if (occurrences !== 1) {\n throw replayError(\n `[test-mutate][${opts.id}] \\`find\\` occurs ${occurrences} times in ${opts.mutant.file}, it must occur exactly once`,\n );\n }\n\n mkdirSync(opts.scratch, { recursive: true });\n const backup = join(opts.scratch, `test-mutate-${opts.id.replace(/[^\\w.-]/g, '_')}.orig`);\n\n if (existsSync(backup)) {\n throw replayError(\n `[test-mutate][${opts.id}] a backup from an interrupted run exists: ${backup} | restore ${opts.mutant.file} from it, then delete it`,\n );\n }\n\n writeFileSync(backup, original);\n\n let outcome: { value: T } | { error: unknown };\n\n try {\n writeFileSync(\n path,\n text.replace(opts.mutant.find, () => opts.mutant.replace),\n );\n outcome = { value: opts.action() };\n } catch (error) {\n outcome = { error };\n }\n\n // Restored whatever the action did, and checked, before its result or error is passed on.\n writeFileSync(path, original);\n\n if (!readFileSync(path).equals(original)) {\n throw replayError(\n `[test-mutate][${opts.id}] ${opts.mutant.file} was not restored | the backup is ${backup}`,\n );\n }\n\n rmSync(backup, { force: true });\n\n if ('error' in outcome) {\n throw outcome.error;\n }\n\n return outcome.value;\n};\n\n/** Applies every edit of `mutant`, runs `action`, and puts each file back byte for byte, verified byte for byte. */\nconst withMutants = <T>(opts: {\n root: string;\n mutant: IMutant | IMutant[];\n scratch: string;\n id: string;\n action: () => T;\n}): T => {\n const edits = Array.isArray(opts.mutant) ? opts.mutant : [opts.mutant];\n\n const apply = (index: number): T =>\n index === edits.length\n ? opts.action()\n : withMutant({\n root: opts.root,\n mutant: edits[index],\n scratch: opts.scratch,\n id: `${opts.id}-${index}`,\n action: () => apply(index + 1),\n });\n\n return apply(0);\n};\n\nexport class TestMutateCheck {\n /** Replays every line; never throws for a green survivor (that is a result), only for an unusable ledger. */\n static replayLedger(opts: { root: string; ledger: ILedger; scratch?: string }): ILedgerResult[] {\n const root = resolve(opts.root);\n const scratch = opts.scratch ?? join(root, '.agents/local/tmp');\n const results: ILedgerResult[] = [];\n\n for (const line of opts.ledger.mutants) {\n const { survivorRed, candidateRed } = withMutants({\n root,\n mutant: line.mutant,\n scratch,\n id: line.id,\n action: () => ({\n survivorRed: runIsRed({ root, file: line.survivor, name: line.survivorName }),\n candidateRed: runIsRed({ root, file: line.candidate, name: line.candidateName }),\n }),\n });\n const result: ILedgerResult = { id: line.id, survivorRed, candidateRed, ok: true };\n const expectation = line.expectCandidate ?? 'red';\n\n if (!survivorRed) {\n result.ok = false;\n result.problem =\n 'the survivor stayed green under the mutant: it does not cover the behaviour';\n } else if (expectation === 'red' && !candidateRed) {\n result.ok = false;\n result.problem =\n 'the candidate stayed green under the mutant: record it as vacuous with a second mutant, or pick a mutant it checks';\n } else if (expectation === 'vacuous') {\n if (!line.secondMutant) {\n result.ok = false;\n result.problem = 'a vacuous line needs a secondMutant';\n } else if (candidateRed) {\n result.ok = false;\n result.problem = 'the candidate went red under the mutant: it is not vacuous';\n } else {\n const greenUnderSecond = !withMutants({\n root,\n mutant: line.secondMutant,\n scratch,\n id: `${line.id}-second`,\n action: () => runIsRed({ root, file: line.candidate, name: line.candidateName }),\n });\n result.candidateGreenUnderSecond = greenUnderSecond;\n\n if (!greenUnderSecond) {\n result.ok = false;\n result.problem = 'the candidate went red under the second mutant: it is not vacuous';\n }\n }\n }\n\n results.push(result);\n }\n\n return results;\n }\n\n /** The report lines of a replay, one per ledger line and a closing tally. */\n static formatLedgerResults(opts: { results: ILedgerResult[] }): string[] {\n const { results } = opts;\n const lines = results.map(\n (result) =>\n `${result.ok ? 'ok ' : 'FAIL'} ${result.id}: survivor ${result.survivorRed ? 'red' : 'GREEN'}, candidate ${result.candidateRed ? 'red' : 'green'}${result.problem ? ` | ${result.problem}` : ''}`,\n );\n const failed = results.filter((result) => !result.ok).length;\n lines.push(\n `\\n[test-mutate] ${results.length - failed}/${results.length} ledger lines hold${failed ? `, ${failed} do not` : ''}.`,\n );\n\n return lines;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-weight.js","sourceRoot":"","sources":["../../src/checks/test-weight.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Reads the JUnit report of `bun test --reporter=junit` and says where the test time and the test\n * count are: per file, per package, the heaviest files, duplicates by name, files that assert nothing,\n * and skips. The first step of the trim-tests method (`.agents/knowledge/process/trimming-tests.md`).\n *\n * The numbers are only as good as the run that made them: a `--parallel` run times each file under\n * contention, so a file that takes 7 s there can take 1 s alone. Re-time a suspect file alone.\n */\nexport interface ITestWeightInput {\n /** Names the report in the output: the package. */\n label: string;\n xml: string;\n}\n\nexport interface ITestFileWeight {\n label: string;\n file: string;\n milliseconds: number;\n cases: number;\n assertions: number;\n skipped: number;\n slowestCase: string;\n slowestMilliseconds: number;\n}\n\nexport interface ITestWeightReport {\n files: ITestFileWeight[];\n totalMilliseconds: number;\n totalCases: number;\n totalAssertions: number;\n totalSkipped: number;\n perLabel: Array<{ label: string; files: number; cases: number; milliseconds: number }>;\n /** Heaviest first. */\n heaviest: ITestFileWeight[];\n /** How many of the heaviest files hold 80% of the time. */\n filesFor80Percent: number;\n /** Files that take under 100 ms, and what they cost together. */\n lightFiles: { count: number; milliseconds: number };\n /** The same suite and case name in more than one file. */\n sameNameAcrossFiles: Array<{ name: string; files: string[] }>;\n zeroAssertionFiles: string[];\n skippedFiles: Array<{ file: string; skipped: number }>;\n}\n\nconst ENTITIES: Record<string, string> = {\n amp: '&',\n lt: '<',\n gt: '>',\n quot: '\"',\n apos: \"'\",\n};\n\nconst decodeEntities = (text: string): string =>\n text.replace(/&(#x[0-9a-fA-F]+|#\\d+|[a-z]+);/g, (whole, body: string) => {\n if (body.startsWith('#x')) {\n return String.fromCodePoint(Number.parseInt(body.slice(2), 16));\n }\n\n if (body.startsWith('#')) {\n return String.fromCodePoint(Number.parseInt(body.slice(1), 10));\n }\n\n return ENTITIES[body] ?? whole;\n });\n\n/** Bun writes a file as a top-level suite whose `name` equals its `file`. */\nconst FILE_SUITE =\n /<testsuite name=\"([^\"]+\\.(?:test|spec)\\.[cm]?[jt]sx?)\" file=\"[^\"]+\" tests=\"(\\d+)\" assertions=\"(\\d+)\" failures=\"\\d+\" skipped=\"(\\d+)\" time=\"([\\d.eE+-]+)\"/g;\nconst CASE = /<testcase name=\"([^\"]*)\" classname=\"([^\"]*)\" time=\"([\\d.eE+-]+)\" file=\"([^\"]+)\"/g;\n\nconst LIGHT_FILE_MILLISECONDS = 100;\nconst HEAVY_SHARE = 0.8;\n\nexport class TestWeightCheck {\n /** Reads the JUnit reports of a test run into one weight report: which files carry the time, and what looks wrong. */\n static analyseJunit(opts: { reports: ITestWeightInput[] }): ITestWeightReport {\n const files: ITestFileWeight[] = [];\n const names = new Map<string, Set<string>>();\n\n for (const { label, xml } of opts.reports) {\n const start = files.length;\n\n for (const match of xml.matchAll(FILE_SUITE)) {\n files.push({\n label,\n file: match[1],\n milliseconds: Number(match[5]) * 1000,\n cases: Number(match[2]),\n assertions: Number(match[3]),\n skipped: Number(match[4]),\n slowestCase: '',\n slowestMilliseconds: 0,\n });\n }\n\n const byFile = new Map(files.slice(start).map((entry) => [entry.file, entry]));\n for (const match of xml.matchAll(CASE)) {\n const caseName = decodeEntities(match[1]);\n const suiteName = decodeEntities(match[2]);\n const entry = byFile.get(match[4]);\n const milliseconds = Number(match[3]) * 1000;\n\n if (entry && milliseconds > entry.slowestMilliseconds) {\n entry.slowestMilliseconds = milliseconds;\n entry.slowestCase = caseName;\n }\n\n const key = `${suiteName} > ${caseName}`;\n const where = names.get(key) ?? new Set<string>();\n where.add(`${label}/${match[4]}`);\n names.set(key, where);\n }\n }\n\n const heaviest = [...files].sort((left, right) => right.milliseconds - left.milliseconds);\n const totalMilliseconds = files.reduce((sum, entry) => sum + entry.milliseconds, 0);\n\n let accumulated = 0;\n let filesFor80Percent = 0;\n for (const entry of heaviest) {\n accumulated += entry.milliseconds;\n filesFor80Percent += 1;\n\n if (accumulated >= totalMilliseconds * HEAVY_SHARE) {\n break;\n }\n }\n\n const light = files.filter((entry) => entry.milliseconds < LIGHT_FILE_MILLISECONDS);\n const labels = [...new Set(files.map((entry) => entry.label))];\n\n return {\n files,\n totalMilliseconds,\n totalCases: files.reduce((sum, entry) => sum + entry.cases, 0),\n totalAssertions: files.reduce((sum, entry) => sum + entry.assertions, 0),\n totalSkipped: files.reduce((sum, entry) => sum + entry.skipped, 0),\n perLabel: labels.map((label) => {\n const own = files.filter((entry) => entry.label === label);\n return {\n label,\n files: own.length,\n cases: own.reduce((sum, entry) => sum + entry.cases, 0),\n milliseconds: own.reduce((sum, entry) => sum + entry.milliseconds, 0),\n };\n }),\n heaviest,\n filesFor80Percent,\n lightFiles: {\n count: light.length,\n milliseconds: light.reduce((sum, entry) => sum + entry.milliseconds, 0),\n },\n sameNameAcrossFiles: [...names.entries()]\n .filter(([, where]) => where.size > 1)\n .map(([name, where]) => ({ name, files: [...where].sort() })),\n zeroAssertionFiles: files\n .filter((entry) => entry.assertions === 0)\n .map((entry) => entry.file),\n skippedFiles: files\n .filter((entry) => entry.skipped > 0)\n .map((entry) => ({ file: `${entry.label}/${entry.file}`, skipped: entry.skipped })),\n };\n }\n\n /** The report as the lines `devz check test-weight` prints. */\n static formatReport(opts: { report: ITestWeightReport; top?: number }): string[] {\n const { report, top = 25 } = opts;\n const seconds = (milliseconds: number): string => (milliseconds / 1000).toFixed(1);\n const lines: string[] = [\n `files ${report.files.length} | cases ${report.totalCases} | assertions ${report.totalAssertions} | skipped ${report.totalSkipped} | sum of file times ${seconds(report.totalMilliseconds)} s`,\n ];\n\n for (const row of report.perLabel) {\n lines.push(\n ` ${row.label.padEnd(14)} files ${String(row.files).padStart(4)} cases ${String(row.cases).padStart(5)} time ${seconds(row.milliseconds).padStart(7)} s`,\n );\n }\n\n lines.push('', `heaviest ${top} files:`);\n for (const entry of report.heaviest.slice(0, top)) {\n lines.push(\n `${entry.milliseconds.toFixed(0).padStart(8)} ms ${String(entry.cases).padStart(5)} cases slowest ${entry.slowestMilliseconds.toFixed(0).padStart(7)} ms ${entry.label}/${entry.file}`,\n );\n }\n\n lines.push(\n '',\n `80% of the time is in the ${report.filesFor80Percent} heaviest files of ${report.files.length}`,\n `files under ${LIGHT_FILE_MILLISECONDS} ms: ${report.lightFiles.count}, together ${seconds(report.lightFiles.milliseconds)} s`,\n `same suite and case name in more than one file: ${report.sameNameAcrossFiles.length}`,\n );\n for (const duplicate of report.sameNameAcrossFiles.slice(0, 10)) {\n lines.push(` ${duplicate.name.slice(0, 90)} -> ${duplicate.files.join(', ')}`);\n }\n\n lines.push(\n `files with 0 assertions: ${report.zeroAssertionFiles.length}${report.zeroAssertionFiles.length ? ` (${report.zeroAssertionFiles.slice(0, 3).join(', ')})` : ''}`,\n `files with skipped cases: ${report.skippedFiles.length} (${report.skippedFiles.reduce((sum, entry) => sum + entry.skipped, 0)} cases)`,\n );\n\n return lines;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"test-weight.js","sourceRoot":"","sources":["../../src/checks/test-weight.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Reads the JUnit report of `bun test --reporter=junit` and says where the test time and the test\n * count are: per file, per package, the heaviest files, duplicates by name, files that assert nothing,\n * and skips. The first step of the trim-tests method (`.agents/knowledge/process/trimming-tests.md`).\n *\n * The numbers are only as good as the run that made them: a `--parallel` run times each file under\n * contention, so a file that takes 7 s there can take 1 s alone. Re-time a suspect file alone.\n */\nexport interface ITestWeightInput {\n /** Names the report in the output: the package. */\n label: string;\n xml: string;\n}\n\nexport interface ITestFileWeight {\n label: string;\n file: string;\n milliseconds: number;\n cases: number;\n assertions: number;\n skipped: number;\n slowestCase: string;\n slowestMilliseconds: number;\n}\n\nexport interface ITestWeightReport {\n files: ITestFileWeight[];\n totalMilliseconds: number;\n totalCases: number;\n totalAssertions: number;\n totalSkipped: number;\n perLabel: Array<{ label: string; files: number; cases: number; milliseconds: number }>;\n /** Heaviest first. */\n heaviest: ITestFileWeight[];\n /** How many of the heaviest files hold 80% of the time. */\n filesFor80Percent: number;\n /** Files that take under 100 ms, and what they cost together. */\n lightFiles: { count: number; milliseconds: number };\n /** The same suite and case name in more than one file. */\n sameNameAcrossFiles: Array<{ name: string; files: string[] }>;\n zeroAssertionFiles: string[];\n skippedFiles: Array<{ file: string; skipped: number }>;\n}\n\nconst ENTITIES: Record<string, string> = {\n amp: '&',\n lt: '<',\n gt: '>',\n quot: '\"',\n apos: \"'\",\n};\n\nconst decodeEntities = (text: string): string =>\n text.replace(/&(#x[0-9a-fA-F]+|#\\d+|[a-z]+);/g, (whole, body: string) => {\n if (body.startsWith('#x')) {\n return String.fromCodePoint(Number.parseInt(body.slice(2), 16));\n }\n\n if (body.startsWith('#')) {\n return String.fromCodePoint(Number.parseInt(body.slice(1), 10));\n }\n\n return ENTITIES[body] ?? whole;\n });\n\n/** Bun writes a file as a top-level suite whose `name` equals its `file`. */\nconst FILE_SUITE =\n /<testsuite name=\"([^\"]+\\.(?:test|spec)\\.[cm]?[jt]sx?)\" file=\"[^\"]+\" tests=\"(\\d+)\" assertions=\"(\\d+)\" failures=\"\\d+\" skipped=\"(\\d+)\" time=\"([\\d.eE+-]+)\"/g;\nconst CASE = /<testcase name=\"([^\"]*)\" classname=\"([^\"]*)\" time=\"([\\d.eE+-]+)\" file=\"([^\"]+)\"/g;\n\nconst LIGHT_FILE_MILLISECONDS = 100;\nconst HEAVY_SHARE = 0.8;\n\nexport class TestWeightCheck {\n /** Reads the JUnit reports of a test run into one weight report: which files carry the time, and what looks wrong. */\n static analyseJunit(opts: { reports: ITestWeightInput[] }): ITestWeightReport {\n const files: ITestFileWeight[] = [];\n const names = new Map<string, Set<string>>();\n\n for (const { label, xml } of opts.reports) {\n const start = files.length;\n\n for (const match of xml.matchAll(FILE_SUITE)) {\n files.push({\n label,\n file: match[1],\n milliseconds: Number(match[5]) * 1000,\n cases: Number(match[2]),\n assertions: Number(match[3]),\n skipped: Number(match[4]),\n slowestCase: '',\n slowestMilliseconds: 0,\n });\n }\n\n const byFile = new Map(files.slice(start).map((entry) => [entry.file, entry]));\n\n for (const match of xml.matchAll(CASE)) {\n const caseName = decodeEntities(match[1]);\n const suiteName = decodeEntities(match[2]);\n const entry = byFile.get(match[4]);\n const milliseconds = Number(match[3]) * 1000;\n\n if (entry && milliseconds > entry.slowestMilliseconds) {\n entry.slowestMilliseconds = milliseconds;\n entry.slowestCase = caseName;\n }\n\n const key = `${suiteName} > ${caseName}`;\n const where = names.get(key) ?? new Set<string>();\n where.add(`${label}/${match[4]}`);\n names.set(key, where);\n }\n }\n\n const heaviest = [...files].sort((left, right) => right.milliseconds - left.milliseconds);\n const totalMilliseconds = files.reduce((sum, entry) => sum + entry.milliseconds, 0);\n\n let accumulated = 0;\n let filesFor80Percent = 0;\n\n for (const entry of heaviest) {\n accumulated += entry.milliseconds;\n filesFor80Percent += 1;\n\n if (accumulated >= totalMilliseconds * HEAVY_SHARE) {\n break;\n }\n }\n\n const light = files.filter((entry) => entry.milliseconds < LIGHT_FILE_MILLISECONDS);\n const labels = [...new Set(files.map((entry) => entry.label))];\n\n return {\n files,\n totalMilliseconds,\n totalCases: files.reduce((sum, entry) => sum + entry.cases, 0),\n totalAssertions: files.reduce((sum, entry) => sum + entry.assertions, 0),\n totalSkipped: files.reduce((sum, entry) => sum + entry.skipped, 0),\n perLabel: labels.map((label) => {\n const own = files.filter((entry) => entry.label === label);\n\n return {\n label,\n files: own.length,\n cases: own.reduce((sum, entry) => sum + entry.cases, 0),\n milliseconds: own.reduce((sum, entry) => sum + entry.milliseconds, 0),\n };\n }),\n heaviest,\n filesFor80Percent,\n lightFiles: {\n count: light.length,\n milliseconds: light.reduce((sum, entry) => sum + entry.milliseconds, 0),\n },\n sameNameAcrossFiles: [...names.entries()]\n .filter(([, where]) => where.size > 1)\n .map(([name, where]) => ({ name, files: [...where].sort() })),\n zeroAssertionFiles: files\n .filter((entry) => entry.assertions === 0)\n .map((entry) => entry.file),\n skippedFiles: files\n .filter((entry) => entry.skipped > 0)\n .map((entry) => ({ file: `${entry.label}/${entry.file}`, skipped: entry.skipped })),\n };\n }\n\n /** The report as the lines `devz check test-weight` prints. */\n static formatReport(opts: { report: ITestWeightReport; top?: number }): string[] {\n const { report, top = 25 } = opts;\n const seconds = (milliseconds: number): string => (milliseconds / 1000).toFixed(1);\n const lines: string[] = [\n `files ${report.files.length} | cases ${report.totalCases} | assertions ${report.totalAssertions} | skipped ${report.totalSkipped} | sum of file times ${seconds(report.totalMilliseconds)} s`,\n ];\n\n for (const row of report.perLabel) {\n lines.push(\n ` ${row.label.padEnd(14)} files ${String(row.files).padStart(4)} cases ${String(row.cases).padStart(5)} time ${seconds(row.milliseconds).padStart(7)} s`,\n );\n }\n\n lines.push('', `heaviest ${top} files:`);\n\n for (const entry of report.heaviest.slice(0, top)) {\n lines.push(\n `${entry.milliseconds.toFixed(0).padStart(8)} ms ${String(entry.cases).padStart(5)} cases slowest ${entry.slowestMilliseconds.toFixed(0).padStart(7)} ms ${entry.label}/${entry.file}`,\n );\n }\n\n lines.push(\n '',\n `80% of the time is in the ${report.filesFor80Percent} heaviest files of ${report.files.length}`,\n `files under ${LIGHT_FILE_MILLISECONDS} ms: ${report.lightFiles.count}, together ${seconds(report.lightFiles.milliseconds)} s`,\n `same suite and case name in more than one file: ${report.sameNameAcrossFiles.length}`,\n );\n\n for (const duplicate of report.sameNameAcrossFiles.slice(0, 10)) {\n lines.push(` ${duplicate.name.slice(0, 90)} -> ${duplicate.files.join(', ')}`);\n }\n\n lines.push(\n `files with 0 assertions: ${report.zeroAssertionFiles.length}${report.zeroAssertionFiles.length ? ` (${report.zeroAssertionFiles.slice(0, 3).join(', ')})` : ''}`,\n `files with skipped cases: ${report.skippedFiles.length} (${report.skippedFiles.reduce((sum, entry) => sum + entry.skipped, 0)} cases)`,\n );\n\n return lines;\n }\n}\n"]}
|
package/dist/cli/check.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/cli/check.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { basename, isAbsolute, relative, resolve } from 'node:path';\nimport { CatalogCheck } from '../checks/catalog';\nimport { ModuleCyclesCheck } from '../checks/module-cycles';\nimport { PurityCheck } from '../checks/purity/run';\nimport { SplitReport } from '../checks/split-report';\nimport { TestControlsCheck } from '../checks/test-controls';\nimport type { IControlEntry } from '../checks/test-controls';\nimport { DeadTestCodeCheck } from '../checks/test-dead-code';\nimport { TestMutateCheck } from '../checks/test-mutate';\nimport type { ILedger } from '../checks/test-mutate';\nimport { TestWeightCheck } from '../checks/test-weight';\nimport type { IPurityClaim, IPurityOptions } from '../checks/purity/manifest';\n\nconst USAGE = `Usage: devz check <name> [options]\n\nChecks:\n purity [package] --claims <file> [--json] probe every entry claimed browser-pure (needs a build)\n module-cycles <dir> [--max <n>] list the import cycles of a built ESM folder\n split-report [--dist <dir>] [folder...] report hub files, stray types, missing barrels, long files, cycles (never a gate)\n catalog [--glob <pattern>]... [--pinned <file>]... [--preset-prefix <prefix>]\n guard dependency ranges against the root workspaces.catalog\n test-weight [--top <n>] <junit.xml>... per-file time, cases, assertions, duplicates and skips from bun's JUnit report\n test-dead-code list support files under __tests__ that no other file refers to (candidates)\n test-mutate <ledger.json> replay a mutation ledger: the survivor must go red under each mutant\n test-controls <registry.json> fail when a registered positive-control test is gone\n\npurity\n --claims <file> a module that exports PURITY_CLAIMS (the claims) and, optionally, PURITY_OPTIONS\n [package] probe only the rows of this package; a token that matches nothing fails\n --json print the verdict as JSON (no paths of this machine, no timing) instead of the report\n\n\ntest-weight, test-dead-code, test-mutate, test-controls: the tools of the trim-tests method, see\n .agents/knowledge/process/trimming-tests.md in the IGNIS repository. Produce the JUnit files with\n bun test ./src --parallel --reporter=junit --reporter-outfile=<file>.\n\nmodule-cycles\n <dir>, or --dist <dir> the built folder (dist/esm); exits 1 when more cycles than --max, 2 on a usage error\n\nsplit-report\n --dist <dir> the built ESM folder inside a package: dist/esm, or dist where one build is published (default dist)\n [folder...] package folders to report; none scans every packages/* and examples/* that has a src/\n\ncatalog\n --glob <pattern> a manifest glob beside packages/*/package.json (repeatable)\n --pinned <file> a manifest outside the workspace: its catalogued ranges must equal the catalog's (repeatable)\n --preset-prefix <p> files under this prefix are presets: catalog: is allowed in their peerDependencies\n\n --help print this text and exit`;\n\n/** A usage error: nothing was probed. */\nconst USAGE_ERROR_CODE = 2;\n\ninterface IClaimsModule {\n PURITY_CLAIMS?: IPurityClaim[];\n PURITY_OPTIONS?: IPurityOptions;\n}\n\ninterface IPurityArguments {\n claimsFile?: string;\n filter?: string;\n json: boolean;\n}\n\nconst parsePurityArguments = (args: string[]): IPurityArguments | string => {\n const parsed: IPurityArguments = { json: false };\n\n for (let index = 0; index < args.length; index += 1) {\n const arg = args[index];\n\n if (arg === '--json') {\n parsed.json = true;\n continue;\n }\n\n if (arg === '--claims') {\n const value = args[index + 1];\n if (value === undefined || value.startsWith('--')) {\n return '--claims needs a file';\n }\n\n parsed.claimsFile = value;\n index += 1;\n continue;\n }\n\n if (arg.startsWith('--')) {\n return `unknown option \"${arg}\"`;\n }\n\n if (parsed.filter !== undefined) {\n return `unexpected argument \"${arg}\"`;\n }\n\n parsed.filter = arg;\n }\n\n return parsed;\n};\n\n/** Splits repeatable `--name value` options and positionals; `undefined` for an option that lacks its value. */\nconst parseRepeatable = (opts: {\n args: string[];\n repeatable: string[];\n single: string[];\n}): { positionals: string[]; values: Record<string, string[]> } | string => {\n const { args, repeatable, single } = opts;\n const values: Record<string, string[]> = {};\n const positionals: string[] = [];\n\n for (let index = 0; index < args.length; index += 1) {\n const arg = args[index];\n\n if (arg.startsWith('--')) {\n const name = arg.slice(2);\n if (!repeatable.includes(name) && !single.includes(name)) {\n return `unknown option \"${arg}\"`;\n }\n\n const value = args[index + 1];\n if (value === undefined || value.startsWith('--')) {\n return `${arg} needs a value`;\n }\n\n values[name] = [...(values[name] ?? []), value];\n index += 1;\n continue;\n }\n\n positionals.push(arg);\n }\n\n return { positionals, values };\n};\n\n/** `devz check <name>`: runs one of the shared repository gates in the current folder. */\nexport class CheckCommand {\n private static runTestWeight(opts: { root: string; args: string[] }): number {\n const parsed = parseRepeatable({ args: opts.args, repeatable: [], single: ['top'] });\n if (typeof parsed === 'string' || parsed.positionals.length === 0) {\n console.error(\n `devz check test-weight: ${typeof parsed === 'string' ? parsed : 'give at least one JUnit file'}\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n const reports = parsed.positionals.map((file) => {\n const path = resolve(opts.root, file);\n return {\n label: basename(file).replace(/\\.xml$/, ''),\n xml: existsSync(path) ? readFileSync(path, 'utf8') : '',\n };\n });\n const missing = parsed.positionals.filter((file) => !existsSync(resolve(opts.root, file)));\n if (missing.length > 0) {\n console.error(`devz check test-weight: not found: ${missing.join(', ')}`);\n return USAGE_ERROR_CODE;\n }\n\n const top = parsed.values.top?.[0] === undefined ? undefined : Number(parsed.values.top[0]);\n for (const line of TestWeightCheck.formatReport({\n report: TestWeightCheck.analyseJunit({ reports }),\n top,\n })) {\n console.log(line);\n }\n\n return 0;\n }\n\n private static runTestDeadCode(opts: { root: string; args: string[] }): number {\n if (opts.args.length > 0) {\n console.error(`devz check test-dead-code: unexpected argument \"${opts.args[0]}\"\\n${USAGE}`);\n return USAGE_ERROR_CODE;\n }\n\n const candidates = DeadTestCodeCheck.find({ root: opts.root });\n for (const kind of ['unreferenced', 'folder-referenced'] as const) {\n const own = candidates.filter((candidate) => candidate.kind === kind);\n console.log(`${kind}: ${own.length}`);\n for (const candidate of own) {\n console.log(` ${candidate.file}`);\n }\n }\n console.log(\n '\\nThese are candidates: delete one, run the package suite, and keep it if anything fails or loads it by a built path.',\n );\n\n return 0;\n }\n\n private static runTestMutate(opts: { root: string; args: string[] }): number {\n const [file, ...extra] = opts.args;\n if (file === undefined || extra.length > 0) {\n console.error(`devz check test-mutate: give one ledger file\\n${USAGE}`);\n return USAGE_ERROR_CODE;\n }\n\n const path = resolve(opts.root, file);\n if (!existsSync(path)) {\n console.error(`devz check test-mutate: ledger not found: ${file}`);\n return USAGE_ERROR_CODE;\n }\n\n const ledger: ILedger = JSON.parse(readFileSync(path, 'utf8'));\n if (!Array.isArray(ledger.mutants)) {\n console.error(`devz check test-mutate: ${file} has no \"mutants\" array`);\n return USAGE_ERROR_CODE;\n }\n\n const results = TestMutateCheck.replayLedger({ root: opts.root, ledger });\n for (const line of TestMutateCheck.formatLedgerResults({ results })) {\n console.log(line);\n }\n\n return results.every((result) => result.ok) ? 0 : 1;\n }\n\n private static async runTestControls(opts: { root: string; args: string[] }): Promise<number> {\n const [file, ...extra] = opts.args;\n if (file === undefined || extra.length > 0) {\n console.error(`devz check test-controls: give one registry file\\n${USAGE}`);\n return USAGE_ERROR_CODE;\n }\n\n const path = resolve(opts.root, file);\n if (!existsSync(path)) {\n console.error(`devz check test-controls: registry not found: ${file}`);\n return USAGE_ERROR_CODE;\n }\n\n const registry: { controls?: IControlEntry[] } = JSON.parse(readFileSync(path, 'utf8'));\n if (!Array.isArray(registry.controls)) {\n console.error(`devz check test-controls: ${file} has no \"controls\" array`);\n return USAGE_ERROR_CODE;\n }\n\n const report = await TestControlsCheck.run({ root: opts.root, controls: registry.controls });\n if (report.problems.length === 0) {\n console.log(`test-controls: OK - ${report.checked} registered controls found`);\n return 0;\n }\n\n console.error(\n `test-controls: ${report.problems.length} of ${report.checked} registered controls are gone:`,\n );\n for (const problem of report.problems) {\n console.error(` [${problem.entry.gate}] ${problem.message}`);\n }\n\n return 1;\n }\n\n private static runSplitReport(opts: { root: string; args: string[] }): number {\n const parsed = parseRepeatable({ args: opts.args, repeatable: [], single: ['dist'] });\n if (typeof parsed === 'string') {\n console.error(`devz check split-report: ${parsed}\\n${USAGE}`);\n return USAGE_ERROR_CODE;\n }\n\n const targets = parsed.positionals.length\n ? parsed.positionals.map((target) => resolve(opts.root, target))\n : SplitReport.defaultTargets({ root: opts.root });\n\n for (const packageDir of targets) {\n SplitReport.run({ packageDir, distDir: parsed.values.dist?.[0] });\n }\n\n return 0;\n }\n\n private static async runCatalog(opts: { root: string; args: string[] }): Promise<number> {\n const parsed = parseRepeatable({\n args: opts.args,\n repeatable: ['glob', 'pinned'],\n single: ['preset-prefix'],\n });\n if (typeof parsed === 'string' || parsed.positionals.length > 0) {\n console.error(\n `devz check catalog: ${typeof parsed === 'string' ? parsed : `unexpected argument \"${parsed.positionals[0]}\"`}\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n const report = await CatalogCheck.find({\n root: opts.root,\n globs: parsed.values.glob,\n pinned: parsed.values.pinned,\n presetPrefix: parsed.values['preset-prefix']?.[0],\n });\n\n if (report.noCatalog) {\n console.error('check-catalog: no `workspaces.catalog` in the root package.json');\n return 1;\n }\n\n if (report.problems.length === 0) {\n console.log(`check-catalog: OK - ${report.entries} entries, ${report.referenced} referenced`);\n return 0;\n }\n\n console.error(`check-catalog: ${report.problems.length} problem(s):`);\n for (const problem of report.problems) {\n console.error(` ${problem.file}: ${problem.message}`);\n }\n\n return 1;\n }\n\n static async run(opts: { root: string; args?: string[] }): Promise<number> {\n const { root, args = [] } = opts;\n const [name, ...rest] = args;\n\n if (name === undefined || name === '--help' || name === '-h') {\n console.log(USAGE);\n return name === undefined ? USAGE_ERROR_CODE : 0;\n }\n\n if (name === 'module-cycles') {\n return ModuleCyclesCheck.run({\n args: rest,\n print: (line) => console.log(line),\n printError: (line) => console.error(line),\n });\n }\n\n if (name === 'split-report') {\n return CheckCommand.runSplitReport({ root, args: rest });\n }\n\n if (name === 'catalog') {\n return CheckCommand.runCatalog({ root, args: rest });\n }\n\n if (name === 'test-weight') {\n return CheckCommand.runTestWeight({ root, args: rest });\n }\n\n if (name === 'test-dead-code') {\n return CheckCommand.runTestDeadCode({ root, args: rest });\n }\n\n if (name === 'test-mutate') {\n return CheckCommand.runTestMutate({ root, args: rest });\n }\n\n if (name === 'test-controls') {\n return CheckCommand.runTestControls({ root, args: rest });\n }\n\n if (name !== 'purity') {\n console.error(`devz check: unknown check \"${name}\"\\n${USAGE}`);\n return USAGE_ERROR_CODE;\n }\n\n if (rest.includes('--help') || rest.includes('-h')) {\n console.log(USAGE);\n return 0;\n }\n\n const parsed = parsePurityArguments(rest);\n if (typeof parsed === 'string') {\n console.error(`devz check purity: ${parsed}\\n${USAGE}`);\n return USAGE_ERROR_CODE;\n }\n\n if (parsed.claimsFile === undefined) {\n console.error(`devz check purity: --claims <file> is required\\n${USAGE}`);\n return USAGE_ERROR_CODE;\n }\n\n const claimsPath = isAbsolute(parsed.claimsFile)\n ? parsed.claimsFile\n : resolve(root, parsed.claimsFile);\n if (!existsSync(claimsPath)) {\n console.error(`devz check purity: claims file not found: ${parsed.claimsFile}`);\n return USAGE_ERROR_CODE;\n }\n\n const claimsModule: IClaimsModule = await import(claimsPath);\n if (!Array.isArray(claimsModule.PURITY_CLAIMS)) {\n console.error(`devz check purity: ${parsed.claimsFile} does not export PURITY_CLAIMS`);\n return USAGE_ERROR_CODE;\n }\n\n const lines: string[] = [];\n const report = await PurityCheck.run({\n root,\n claims: claimsModule.PURITY_CLAIMS,\n options: claimsModule.PURITY_OPTIONS,\n filter: parsed.filter,\n claimsFile: relative(root, claimsPath),\n print: (line) => (parsed.json ? lines.push(line) : console.log(line)),\n printError: (line) => console.error(line),\n });\n\n if (report === undefined) {\n return 1;\n }\n\n if (parsed.json) {\n console.log(JSON.stringify(report, null, 2));\n }\n\n return report.failed > 0 ? 1 : 0;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/cli/check.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { basename, isAbsolute, relative, resolve } from 'node:path';\nimport { CatalogCheck } from '../checks/catalog';\nimport { ModuleCyclesCheck } from '../checks/module-cycles';\nimport { PurityCheck } from '../checks/purity/run';\nimport { SplitReport } from '../checks/split-report';\nimport { TestControlsCheck } from '../checks/test-controls';\nimport type { IControlEntry } from '../checks/test-controls';\nimport { DeadTestCodeCheck } from '../checks/test-dead-code';\nimport { TestMutateCheck } from '../checks/test-mutate';\nimport type { ILedger } from '../checks/test-mutate';\nimport { TestWeightCheck } from '../checks/test-weight';\nimport type { IPurityClaim, IPurityOptions } from '../checks/purity/manifest';\n\nconst USAGE = `Usage: devz check <name> [options]\n\nChecks:\n purity [package] --claims <file> [--json] probe every entry claimed browser-pure (needs a build)\n module-cycles <dir> [--max <n>] list the import cycles of a built ESM folder\n split-report [--dist <dir>] [folder...] report hub files, stray types, missing barrels, long files, cycles (never a gate)\n catalog [--glob <pattern>]... [--pinned <file>]... [--preset-prefix <prefix>]\n guard dependency ranges against the root workspaces.catalog\n test-weight [--top <n>] <junit.xml>... per-file time, cases, assertions, duplicates and skips from bun's JUnit report\n test-dead-code list support files under __tests__ that no other file refers to (candidates)\n test-mutate <ledger.json> replay a mutation ledger: the survivor must go red under each mutant\n test-controls <registry.json> fail when a registered positive-control test is gone\n\npurity\n --claims <file> a module that exports PURITY_CLAIMS (the claims) and, optionally, PURITY_OPTIONS\n [package] probe only the rows of this package; a token that matches nothing fails\n --json print the verdict as JSON (no paths of this machine, no timing) instead of the report\n\n\ntest-weight, test-dead-code, test-mutate, test-controls: the tools of the trim-tests method, see\n .agents/knowledge/process/trimming-tests.md in the IGNIS repository. Produce the JUnit files with\n bun test ./src --parallel --reporter=junit --reporter-outfile=<file>.\n\nmodule-cycles\n <dir>, or --dist <dir> the built folder (dist/esm); exits 1 when more cycles than --max, 2 on a usage error\n\nsplit-report\n --dist <dir> the built ESM folder inside a package: dist/esm, or dist where one build is published (default dist)\n [folder...] package folders to report; none scans every packages/* and examples/* that has a src/\n\ncatalog\n --glob <pattern> a manifest glob beside packages/*/package.json (repeatable)\n --pinned <file> a manifest outside the workspace: its catalogued ranges must equal the catalog's (repeatable)\n --preset-prefix <p> files under this prefix are presets: catalog: is allowed in their peerDependencies\n\n --help print this text and exit`;\n\n/** A usage error: nothing was probed. */\nconst USAGE_ERROR_CODE = 2;\n\ninterface IClaimsModule {\n PURITY_CLAIMS?: IPurityClaim[];\n PURITY_OPTIONS?: IPurityOptions;\n}\n\ninterface IPurityArguments {\n claimsFile?: string;\n filter?: string;\n json: boolean;\n}\n\nconst parsePurityArguments = (args: string[]): IPurityArguments | string => {\n const parsed: IPurityArguments = { json: false };\n\n for (let index = 0; index < args.length; index += 1) {\n const arg = args[index];\n\n if (arg === '--json') {\n parsed.json = true;\n continue;\n }\n\n if (arg === '--claims') {\n const value = args[index + 1];\n\n if (value === undefined || value.startsWith('--')) {\n return '--claims needs a file';\n }\n\n parsed.claimsFile = value;\n index += 1;\n continue;\n }\n\n if (arg.startsWith('--')) {\n return `unknown option \"${arg}\"`;\n }\n\n if (parsed.filter !== undefined) {\n return `unexpected argument \"${arg}\"`;\n }\n\n parsed.filter = arg;\n }\n\n return parsed;\n};\n\n/** Splits repeatable `--name value` options and positionals; `undefined` for an option that lacks its value. */\nconst parseRepeatable = (opts: {\n args: string[];\n repeatable: string[];\n single: string[];\n}): { positionals: string[]; values: Record<string, string[]> } | string => {\n const { args, repeatable, single } = opts;\n const values: Record<string, string[]> = {};\n const positionals: string[] = [];\n\n for (let index = 0; index < args.length; index += 1) {\n const arg = args[index];\n\n if (arg.startsWith('--')) {\n const name = arg.slice(2);\n\n if (!repeatable.includes(name) && !single.includes(name)) {\n return `unknown option \"${arg}\"`;\n }\n\n const value = args[index + 1];\n\n if (value === undefined || value.startsWith('--')) {\n return `${arg} needs a value`;\n }\n\n values[name] = [...(values[name] ?? []), value];\n index += 1;\n continue;\n }\n\n positionals.push(arg);\n }\n\n return { positionals, values };\n};\n\n/** `devz check <name>`: runs one of the shared repository gates in the current folder. */\nexport class CheckCommand {\n private static runTestWeight(opts: { root: string; args: string[] }): number {\n const parsed = parseRepeatable({ args: opts.args, repeatable: [], single: ['top'] });\n\n if (typeof parsed === 'string' || parsed.positionals.length === 0) {\n console.error(\n `devz check test-weight: ${typeof parsed === 'string' ? parsed : 'give at least one JUnit file'}\\n${USAGE}`,\n );\n\n return USAGE_ERROR_CODE;\n }\n\n const reports = parsed.positionals.map((file) => {\n const path = resolve(opts.root, file);\n\n return {\n label: basename(file).replace(/\\.xml$/, ''),\n xml: existsSync(path) ? readFileSync(path, 'utf8') : '',\n };\n });\n const missing = parsed.positionals.filter((file) => !existsSync(resolve(opts.root, file)));\n\n if (missing.length > 0) {\n console.error(`devz check test-weight: not found: ${missing.join(', ')}`);\n\n return USAGE_ERROR_CODE;\n }\n\n const top = parsed.values.top?.[0] === undefined ? undefined : Number(parsed.values.top[0]);\n\n for (const line of TestWeightCheck.formatReport({\n report: TestWeightCheck.analyseJunit({ reports }),\n top,\n })) {\n console.log(line);\n }\n\n return 0;\n }\n\n private static runTestDeadCode(opts: { root: string; args: string[] }): number {\n if (opts.args.length > 0) {\n console.error(`devz check test-dead-code: unexpected argument \"${opts.args[0]}\"\\n${USAGE}`);\n\n return USAGE_ERROR_CODE;\n }\n\n const candidates = DeadTestCodeCheck.find({ root: opts.root });\n\n for (const kind of ['unreferenced', 'folder-referenced'] as const) {\n const own = candidates.filter((candidate) => candidate.kind === kind);\n console.log(`${kind}: ${own.length}`);\n\n for (const candidate of own) {\n console.log(` ${candidate.file}`);\n }\n }\n\n console.log(\n '\\nThese are candidates: delete one, run the package suite, and keep it if anything fails or loads it by a built path.',\n );\n\n return 0;\n }\n\n private static runTestMutate(opts: { root: string; args: string[] }): number {\n const [file, ...extra] = opts.args;\n\n if (file === undefined || extra.length > 0) {\n console.error(`devz check test-mutate: give one ledger file\\n${USAGE}`);\n\n return USAGE_ERROR_CODE;\n }\n\n const path = resolve(opts.root, file);\n\n if (!existsSync(path)) {\n console.error(`devz check test-mutate: ledger not found: ${file}`);\n\n return USAGE_ERROR_CODE;\n }\n\n const ledger: ILedger = JSON.parse(readFileSync(path, 'utf8'));\n\n if (!Array.isArray(ledger.mutants)) {\n console.error(`devz check test-mutate: ${file} has no \"mutants\" array`);\n\n return USAGE_ERROR_CODE;\n }\n\n const results = TestMutateCheck.replayLedger({ root: opts.root, ledger });\n\n for (const line of TestMutateCheck.formatLedgerResults({ results })) {\n console.log(line);\n }\n\n return results.every((result) => result.ok) ? 0 : 1;\n }\n\n private static async runTestControls(opts: { root: string; args: string[] }): Promise<number> {\n const [file, ...extra] = opts.args;\n\n if (file === undefined || extra.length > 0) {\n console.error(`devz check test-controls: give one registry file\\n${USAGE}`);\n\n return USAGE_ERROR_CODE;\n }\n\n const path = resolve(opts.root, file);\n\n if (!existsSync(path)) {\n console.error(`devz check test-controls: registry not found: ${file}`);\n\n return USAGE_ERROR_CODE;\n }\n\n const registry: { controls?: IControlEntry[] } = JSON.parse(readFileSync(path, 'utf8'));\n\n if (!Array.isArray(registry.controls)) {\n console.error(`devz check test-controls: ${file} has no \"controls\" array`);\n\n return USAGE_ERROR_CODE;\n }\n\n const report = await TestControlsCheck.run({ root: opts.root, controls: registry.controls });\n\n if (report.problems.length === 0) {\n console.log(`test-controls: OK - ${report.checked} registered controls found`);\n\n return 0;\n }\n\n console.error(\n `test-controls: ${report.problems.length} of ${report.checked} registered controls are gone:`,\n );\n\n for (const problem of report.problems) {\n console.error(` [${problem.entry.gate}] ${problem.message}`);\n }\n\n return 1;\n }\n\n private static runSplitReport(opts: { root: string; args: string[] }): number {\n const parsed = parseRepeatable({ args: opts.args, repeatable: [], single: ['dist'] });\n\n if (typeof parsed === 'string') {\n console.error(`devz check split-report: ${parsed}\\n${USAGE}`);\n\n return USAGE_ERROR_CODE;\n }\n\n const targets = parsed.positionals.length\n ? parsed.positionals.map((target) => resolve(opts.root, target))\n : SplitReport.defaultTargets({ root: opts.root });\n\n for (const packageDir of targets) {\n SplitReport.run({ packageDir, distDir: parsed.values.dist?.[0] });\n }\n\n return 0;\n }\n\n private static async runCatalog(opts: { root: string; args: string[] }): Promise<number> {\n const parsed = parseRepeatable({\n args: opts.args,\n repeatable: ['glob', 'pinned'],\n single: ['preset-prefix'],\n });\n\n if (typeof parsed === 'string' || parsed.positionals.length > 0) {\n console.error(\n `devz check catalog: ${typeof parsed === 'string' ? parsed : `unexpected argument \"${parsed.positionals[0]}\"`}\\n${USAGE}`,\n );\n\n return USAGE_ERROR_CODE;\n }\n\n const report = await CatalogCheck.find({\n root: opts.root,\n globs: parsed.values.glob,\n pinned: parsed.values.pinned,\n presetPrefix: parsed.values['preset-prefix']?.[0],\n });\n\n if (report.noCatalog) {\n console.error('check-catalog: no `workspaces.catalog` in the root package.json');\n\n return 1;\n }\n\n if (report.problems.length === 0) {\n console.log(`check-catalog: OK - ${report.entries} entries, ${report.referenced} referenced`);\n\n return 0;\n }\n\n console.error(`check-catalog: ${report.problems.length} problem(s):`);\n\n for (const problem of report.problems) {\n console.error(` ${problem.file}: ${problem.message}`);\n }\n\n return 1;\n }\n\n static async run(opts: { root: string; args?: string[] }): Promise<number> {\n const { root, args = [] } = opts;\n const [name, ...rest] = args;\n\n if (name === undefined || name === '--help' || name === '-h') {\n console.log(USAGE);\n\n return name === undefined ? USAGE_ERROR_CODE : 0;\n }\n\n if (name === 'module-cycles') {\n return ModuleCyclesCheck.run({\n args: rest,\n print: (line) => console.log(line),\n printError: (line) => console.error(line),\n });\n }\n\n if (name === 'split-report') {\n return CheckCommand.runSplitReport({ root, args: rest });\n }\n\n if (name === 'catalog') {\n return CheckCommand.runCatalog({ root, args: rest });\n }\n\n if (name === 'test-weight') {\n return CheckCommand.runTestWeight({ root, args: rest });\n }\n\n if (name === 'test-dead-code') {\n return CheckCommand.runTestDeadCode({ root, args: rest });\n }\n\n if (name === 'test-mutate') {\n return CheckCommand.runTestMutate({ root, args: rest });\n }\n\n if (name === 'test-controls') {\n return CheckCommand.runTestControls({ root, args: rest });\n }\n\n if (name !== 'purity') {\n console.error(`devz check: unknown check \"${name}\"\\n${USAGE}`);\n\n return USAGE_ERROR_CODE;\n }\n\n if (rest.includes('--help') || rest.includes('-h')) {\n console.log(USAGE);\n\n return 0;\n }\n\n const parsed = parsePurityArguments(rest);\n\n if (typeof parsed === 'string') {\n console.error(`devz check purity: ${parsed}\\n${USAGE}`);\n\n return USAGE_ERROR_CODE;\n }\n\n if (parsed.claimsFile === undefined) {\n console.error(`devz check purity: --claims <file> is required\\n${USAGE}`);\n\n return USAGE_ERROR_CODE;\n }\n\n const claimsPath = isAbsolute(parsed.claimsFile)\n ? parsed.claimsFile\n : resolve(root, parsed.claimsFile);\n\n if (!existsSync(claimsPath)) {\n console.error(`devz check purity: claims file not found: ${parsed.claimsFile}`);\n\n return USAGE_ERROR_CODE;\n }\n\n const claimsModule: IClaimsModule = await import(claimsPath);\n\n if (!Array.isArray(claimsModule.PURITY_CLAIMS)) {\n console.error(`devz check purity: ${parsed.claimsFile} does not export PURITY_CLAIMS`);\n\n return USAGE_ERROR_CODE;\n }\n\n const lines: string[] = [];\n const report = await PurityCheck.run({\n root,\n claims: claimsModule.PURITY_CLAIMS,\n options: claimsModule.PURITY_OPTIONS,\n filter: parsed.filter,\n claimsFile: relative(root, claimsPath),\n print: (line) => (parsed.json ? lines.push(line) : console.log(line)),\n printError: (line) => console.error(line),\n });\n\n if (report === undefined) {\n return 1;\n }\n\n if (parsed.json) {\n console.log(JSON.stringify(report, null, 2));\n }\n\n return report.failed > 0 ? 1 : 0;\n }\n}\n"]}
|
package/dist/cli/clean.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clean.js","sourceRoot":"","sources":["../../src/cli/clean.ts"],"names":[],"mappings":";;;AAAA,qCAA8C;AAC9C,yCAAiC;AAEjC,0EAA0E;AAC1E,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEzC,MAAM,KAAK,GAAG;;;;;sCAKwB,CAAC;AAEvC,0CAA0C;AAC1C,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B,wKAAwK;AACxK,MAAa,YAAY;IACvB,MAAM,CAAC,GAAG,CAAC,IAAuC;QAChD,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;QAE3B,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"clean.js","sourceRoot":"","sources":["../../src/cli/clean.ts"],"names":[],"mappings":";;;AAAA,qCAA8C;AAC9C,yCAAiC;AAEjC,0EAA0E;AAC1E,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEzC,MAAM,KAAK,GAAG;;;;;sCAKwB,CAAC;AAEvC,0CAA0C;AAC1C,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B,wKAAwK;AACxK,MAAa,YAAY;IACvB,MAAM,CAAC,GAAG,CAAC,IAAuC;QAChD,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;QAE3B,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAEnB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CACX,mCAAmC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CACxF,CAAC;YAEF,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;YACnC,IAAA,gBAAM,EAAC,IAAA,gBAAI,EAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,IAAA,qBAAW,EAAC,IAAI,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACpE,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBAC7D,IAAA,gBAAM,EAAC,IAAA,gBAAI,EAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,OAAO,CAAC,CAAC;IACX,CAAC;CACF;AA9BD,oCA8BC","sourcesContent":["import { readdirSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** What a build and the checks generate, relative to the project root. */\nconst GENERATED_PATHS = ['dist', 'node_modules/.cache'];\n\n/**\n * `incremental` is on in the base tsconfig, so a type-check that emits nothing leaves\n * `<tsconfig name>.tsbuildinfo` next to the tsconfig. One inside `dist` is already removed with it.\n */\nconst BUILD_INFO_SUFFIX = '.tsbuildinfo';\n\nconst USAGE = `Usage: devz clean\n\nRemoves what the build and the checks generate, in the current folder: dist, node_modules/.cache and\nthe *.tsbuildinfo files next to the tsconfig. It takes no argument.\n\n --help print this text and exit`;\n\n/** A usage error: nothing was deleted. */\nconst USAGE_ERROR_CODE = 2;\n\n/** `devz clean`: removes what the build and the checks generate, and nothing else. `--help` prints the usage; any other argument is refused, and nothing is deleted. */\nexport class CleanCommand {\n static run(opts: { root: string; args?: string[] }): number {\n const { args = [] } = opts;\n\n if (args.includes('--help') || args.includes('-h')) {\n console.log(USAGE);\n\n return 0;\n }\n\n if (args.length > 0) {\n console.error(\n `devz clean: unexpected argument ${args.map((arg) => `\"${arg}\"`).join(', ')}\\n${USAGE}`,\n );\n\n return USAGE_ERROR_CODE;\n }\n\n for (const path of GENERATED_PATHS) {\n rmSync(join(opts.root, path), { recursive: true, force: true });\n }\n\n for (const entry of readdirSync(opts.root, { withFileTypes: true })) {\n if (entry.isFile() && entry.name.endsWith(BUILD_INFO_SUFFIX)) {\n rmSync(join(opts.root, entry.name), { force: true });\n }\n }\n\n return 0;\n }\n}\n"]}
|
|
@@ -16,7 +16,7 @@ export interface IAsyncStyleResult {
|
|
|
16
16
|
}
|
|
17
17
|
/** Runs the async-style rules, and only those, over source text with ESLint's own fixer loop. */
|
|
18
18
|
export declare class AsyncStyle {
|
|
19
|
-
/** The `Linter` config: the TypeScript parser and the rules of `
|
|
19
|
+
/** The `Linter` config: the TypeScript parser and the rules of `asyncRuleConfigs`, at error. */
|
|
20
20
|
static createConfig(): Promise<Linter.Config[]>;
|
|
21
21
|
/**
|
|
22
22
|
* The self-check's config: four scope rules, run on the text before and after the fixers. A hoisted name must be
|
|
@@ -51,10 +51,10 @@ class AsyncStyleFlags {
|
|
|
51
51
|
}
|
|
52
52
|
/** Runs the async-style rules, and only those, over source text with ESLint's own fixer loop. */
|
|
53
53
|
class AsyncStyle {
|
|
54
|
-
/** The `Linter` config: the TypeScript parser and the rules of `
|
|
54
|
+
/** The `Linter` config: the TypeScript parser and the rules of `asyncRuleConfigs`, at error. */
|
|
55
55
|
static async createConfig() {
|
|
56
56
|
const { default: tseslint } = await import('typescript-eslint');
|
|
57
|
-
const {
|
|
57
|
+
const { asyncRuleConfigs } = await import('../../linters/house/async-rules.js');
|
|
58
58
|
return [
|
|
59
59
|
{
|
|
60
60
|
files: ['**/*.{ts,tsx,mts,cts}'],
|
|
@@ -63,7 +63,7 @@ class AsyncStyle {
|
|
|
63
63
|
// ESLint's fixer would delete it. A codemod never touches a directive.
|
|
64
64
|
linterOptions: { reportUnusedDisableDirectives: 'off' },
|
|
65
65
|
},
|
|
66
|
-
...
|
|
66
|
+
...asyncRuleConfigs,
|
|
67
67
|
];
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async-style.js","sourceRoot":"","sources":["../../../src/cli/codemod/async-style.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport type { Linter } from 'eslint';\nimport { CodemodFiles } from './files';\n\nconst USAGE = `Usage: devz codemod async-style [paths...] [--write | --check]\n\nApplies the fixers of three house lint rules, so a repository can sweep them without a lint pass:\n\n venizia/no-inline-await \\`expect(await f())\\` becomes \\`const result = await f(); expect(result)\\`\n venizia/no-return-await \\`return await f()\\` becomes \\`return f()\\` (\\`const result = await f(); return result;\\` in a try)\n venizia/no-await-promise-chain \\`const x = await f().catch(() => null)\\` becomes\n \\`let x; try { x = await f(); } catch (error) { x = null; }\\`\n\nIt changes only what the fixers can change safely, and lists the rest with its file, line and rule:\nan \\`await\\` inside a ternary or logical operand, a loop test, an unbraced \\`if\\` branch, or after a call\nthat may have effects; an awaited \\`.then\\` or \\`.finally\\`, a \\`.catch\\` whose handler has a block body or\ncalls something, and an awaited chain that is not the whole initializer of a \\`const\\` or \\`let\\`; and\nevery venizia/no-silent-catch finding (a handler or catch block that swallows the error), which it never\nfixes: what to log is your decision.\n\n --write write the changed files (without it, nothing is written)\n --check dry run that exits 1 when anything would change or is left unfixed (for CI)\n --all with --write and no path: rewrite every source file under the working directory (--write needs a path or --all)\n --help print this text and exit\n\nWith no flag it lists what would change and writes nothing. Inside a git repository it reads the\nfiles git knows (tracked, or untracked and not ignored), and --write refuses a file with local changes\n(changed, staged or untracked): commit or stash it first, so git can undo the codemod.`;\n\n/** A usage error: nothing was read or written. */\nconst USAGE_ERROR_CODE = 2;\n\n/** A file that can hold an `await` or a `catch`. */\nconst ASYNC_TEXT = /\\b(await|catch)\\b/;\n\nclass AsyncStyleFlags {\n static readonly WRITE = '--write';\n static readonly CHECK = '--check';\n static readonly ALL = '--all';\n static readonly HELP = '--help';\n static readonly HELP_SHORT = '-h';\n\n static readonly SCHEME_SET = new Set<string>([\n this.WRITE,\n this.CHECK,\n this.ALL,\n this.HELP,\n this.HELP_SHORT,\n ]);\n\n static isValid(value: string): boolean {\n return this.SCHEME_SET.has(value);\n }\n}\n\nexport interface IAsyncStyleReport {\n line: number;\n column: number;\n /** The rule id, or `undefined` for a file ESLint could not parse. */\n ruleId: string | null;\n message: string;\n}\n\nexport interface IAsyncStyleResult {\n output: string;\n changed: boolean;\n /** How many findings of the original source carried a fix, once the fixers changed it. */\n fixes: number;\n /** What is still reported after every pass. */\n reports: IAsyncStyleReport[];\n}\n\n/** Runs the async-style rules, and only those, over source text with ESLint's own fixer loop. */\nexport class AsyncStyle {\n /** The `Linter` config: the TypeScript parser and the rules of `asyncStyleConfigs`, at error. */\n static async createConfig(): Promise<Linter.Config[]> {\n const { default: tseslint } = await import('typescript-eslint');\n const { asyncStyleConfigs } = await import('../../linters/house/index.js');\n\n return [\n {\n files: ['**/*.{ts,tsx,mts,cts}'],\n languageOptions: { parser: tseslint.parser },\n // Only the async-style rules run here, so a `// eslint-disable-next-line` for any other rule looks unused and\n // ESLint's fixer would delete it. A codemod never touches a directive.\n linterOptions: { reportUnusedDisableDirectives: 'off' },\n },\n ...asyncStyleConfigs,\n ];\n }\n\n /**\n * The self-check's config: four scope rules, run on the text before and after the fixers. A hoisted name must be\n * declared once, shadow nothing, be used after it is declared and be used at all; when the fixers break one of these\n * the count of that rule goes up, and the file is left as it was.\n */\n static async createChecks(): Promise<Linter.Config[]> {\n const { default: tseslint } = await import('typescript-eslint');\n\n return [\n {\n files: ['**/*.{ts,tsx,mts,cts}'],\n languageOptions: { parser: tseslint.parser },\n linterOptions: { reportUnusedDisableDirectives: 'off' },\n plugins: { '@typescript-eslint': tseslint.plugin as never },\n rules: {\n '@typescript-eslint/no-redeclare': 'error',\n '@typescript-eslint/no-shadow': 'error',\n '@typescript-eslint/no-use-before-define': [\n 'error',\n { functions: false, classes: false },\n ],\n '@typescript-eslint/no-unused-vars': ['error', { args: 'none', caughtErrors: 'none' }],\n },\n },\n ];\n }\n\n /** What got worse between `source` and `output` by the self-check's rules: empty when nothing did. */\n static selfCheck(opts: {\n linter: Linter;\n checks: Linter.Config[];\n source: string;\n output: string;\n filename: string;\n }): string[] {\n const { linter, checks, source, output, filename } = opts;\n const count = (text: string): Map<string, number> => {\n const found = new Map<string, number>();\n for (const message of linter.verify(text, checks, { filename })) {\n const key = message.ruleId ?? 'parse error';\n found.set(key, (found.get(key) ?? 0) + 1);\n }\n\n return found;\n };\n const was = count(source);\n const now = count(output);\n\n return [...now]\n .filter(([rule, total]) => total > (was.get(rule) ?? 0))\n .map(([rule, total]) => `${rule}: ${was.get(rule) ?? 0} before, ${total} after`);\n }\n\n /**\n * Fixes `source` (ESLint applies up to ten passes) and returns the text and what is left. `filename` is relative to\n * the linter's `cwd`. The fixed text is checked against the original (`checks`): if it has more redeclarations,\n * shadowed names, uses before declaration or unused variables than the original, no fix is returned and the file is\n * reported as `self-check`, so a hoisted name that does not match the expression it replaced never reaches a file.\n */\n static fix(opts: {\n linter: Linter;\n config: Linter.Config[];\n checks: Linter.Config[];\n source: string;\n filename: string;\n }): IAsyncStyleResult {\n const { linter, config, checks, source, filename } = opts;\n // A fix can leave a new finding behind (the try/catch of no-await-promise-chain is a silent catch when the\n // fallback is a constant), so the count is of the fixable findings, not of the findings that went away.\n const fixable = linter\n .verify(source, config, { filename })\n .filter((message) => message.fix !== undefined).length;\n const result = linter.verifyAndFix(source, config, { filename });\n\n if (result.output !== source) {\n const broken = AsyncStyle.selfCheck({\n linter,\n checks,\n source,\n output: result.output,\n filename,\n });\n\n if (broken.length > 0) {\n return {\n output: source,\n changed: false,\n fixes: 0,\n reports: [\n {\n line: 1,\n column: 1,\n ruleId: 'self-check',\n message: `the fixers would have made this file worse (${broken.join('; ')}); it is left as it was - fix it by hand`,\n },\n ],\n };\n }\n }\n\n return {\n output: result.output,\n changed: result.output !== source,\n fixes: result.fixed ? fixable : 0,\n reports: result.messages.map((message) => ({\n line: message.line,\n column: message.column,\n ruleId: message.ruleId,\n message: message.message,\n })),\n };\n }\n}\n\n/**\n * `devz codemod async-style [paths...] [--write | --check]`: applies the fixers of `no-inline-await`,\n * `no-return-await` and `no-await-promise-chain`, and lists what is left of those and of `no-silent-catch`.\n * It is a dry run unless `--write` is given. `--check` is the same dry run, and exits 1 when anything would\n * change or is left unfixed.\n */\nexport class AsyncStyleCommand {\n static readonly USAGE = USAGE;\n\n static async run(opts: { root: string; args: string[] }): Promise<number> {\n const { root, args } = opts;\n\n if (args.includes(AsyncStyleFlags.HELP) || args.includes(AsyncStyleFlags.HELP_SHORT)) {\n console.log(USAGE);\n return 0;\n }\n\n const flags = args.filter((argument) => argument.startsWith('-'));\n const paths = args.filter((argument) => !argument.startsWith('-'));\n\n const unknown = flags.filter((flag) => !AsyncStyleFlags.isValid(flag));\n if (unknown.length > 0) {\n console.error(\n `devz codemod: unknown option ${unknown.map((flag) => `\"${flag}\"`).join(', ')}\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n const isWrite = flags.includes(AsyncStyleFlags.WRITE);\n const isCheck = flags.includes(AsyncStyleFlags.CHECK);\n\n if (isWrite && isCheck) {\n console.error(\n `devz codemod: ${AsyncStyleFlags.WRITE} and ${AsyncStyleFlags.CHECK} contradict each other\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n const refusal = CodemodFiles.refusal({\n command: 'async-style',\n isWrite,\n isAll: flags.includes(AsyncStyleFlags.ALL),\n paths,\n });\n if (refusal) {\n console.error(`${refusal}\\n${USAGE}`);\n return USAGE_ERROR_CODE;\n }\n\n let linter: Linter;\n try {\n const { Linter: EslintLinter } = await import('eslint');\n linter = new EslintLinter({ cwd: root });\n } catch {\n console.error('devz codemod: the \"eslint\" package is required to run the lint fixers');\n return 1;\n }\n\n const config = await AsyncStyle.createConfig();\n const checks = await AsyncStyle.createChecks();\n const targets = (paths.length > 0 ? paths : ['.']).map((path) => resolve(root, path));\n let changedCount = 0;\n let fixCount = 0;\n let reportCount = 0;\n let refusedCount = 0;\n\n for (const target of targets) {\n const files = CodemodFiles.collect({ target });\n const dirty = isWrite ? CodemodFiles.dirty({ target }) : undefined;\n\n if (files.length === 0 && paths.length > 0) {\n console.warn(\n `devz codemod: no source files under \"${relative(root, target) || target}\" (git ignores the path, or it holds none): nothing was read`,\n );\n }\n\n for (const file of files) {\n const source = readFileSync(file, 'utf8');\n\n if (!ASYNC_TEXT.test(source)) {\n continue;\n }\n\n const shown = relative(root, file).split('\\\\').join('/');\n const result = AsyncStyle.fix({ linter, config, checks, source, filename: shown });\n\n for (const report of result.reports) {\n reportCount += 1;\n console.warn(\n `${shown}:${report.line}:${report.column} ${report.ruleId ?? 'parse error'} ${report.message}`,\n );\n }\n\n if (!result.changed) {\n continue;\n }\n\n if (dirty?.has(file)) {\n refusedCount += 1;\n console.warn(\n `refused ${shown} has local changes (commit or stash them, then run again)`,\n );\n continue;\n }\n\n changedCount += 1;\n fixCount += result.fixes;\n console.log(`${isWrite ? 'changed' : 'would change'} ${shown} (${result.fixes} fix(es))`);\n\n if (isWrite) {\n writeFileSync(file, result.output);\n }\n }\n }\n\n console.log(\n `devz codemod async-style: ${changedCount} file(s) ${isWrite ? 'changed' : 'would change'}, ${fixCount} fix(es) ${isWrite ? 'applied' : 'would be applied'}, ${reportCount} left unfixed` +\n (refusedCount > 0 ? `, ${refusedCount} refused` : ''),\n );\n\n if (!isWrite && changedCount > 0) {\n console.log(`Nothing was written. Run again with ${AsyncStyleFlags.WRITE} to apply.`);\n }\n\n if (isWrite && refusedCount > 0) {\n return 1;\n }\n\n return isCheck && (changedCount > 0 || reportCount > 0) ? 1 : 0;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"async-style.js","sourceRoot":"","sources":["../../../src/cli/codemod/async-style.ts"],"names":[],"mappings":";;;AAAA,qCAAsD;AACtD,yCAA8C;AAE9C,mCAAuC;AAEvC,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;uFAuByE,CAAC;AAExF,kDAAkD;AAClD,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B,oDAAoD;AACpD,MAAM,UAAU,GAAG,mBAAmB,CAAC;AAEvC,MAAM,eAAe;aACH,UAAK,GAAG,SAAS,CAAC;aAClB,UAAK,GAAG,SAAS,CAAC;aAClB,QAAG,GAAG,OAAO,CAAC;aACd,SAAI,GAAG,QAAQ,CAAC;aAChB,eAAU,GAAG,IAAI,CAAC;aAElB,eAAU,GAAG,IAAI,GAAG,CAAS;QAC3C,IAAI,CAAC,KAAK;QACV,IAAI,CAAC,KAAK;QACV,IAAI,CAAC,GAAG;QACR,IAAI,CAAC,IAAI;QACT,IAAI,CAAC,UAAU;KAChB,CAAC,CAAC;IAEH,MAAM,CAAC,OAAO,CAAC,KAAa;QAC1B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;;AAoBH,iGAAiG;AACjG,MAAa,UAAU;IACrB,gGAAgG;IAChG,MAAM,CAAC,KAAK,CAAC,YAAY;QACvB,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAChE,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,oCAAoC,CAAC,CAAC;QAEhF,OAAO;YACL;gBACE,KAAK,EAAE,CAAC,uBAAuB,CAAC;gBAChC,eAAe,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE;gBAC5C,8GAA8G;gBAC9G,uEAAuE;gBACvE,aAAa,EAAE,EAAE,6BAA6B,EAAE,KAAK,EAAE;aACxD;YACD,GAAG,gBAAgB;SACpB,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,YAAY;QACvB,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAEhE,OAAO;YACL;gBACE,KAAK,EAAE,CAAC,uBAAuB,CAAC;gBAChC,eAAe,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE;gBAC5C,aAAa,EAAE,EAAE,6BAA6B,EAAE,KAAK,EAAE;gBACvD,OAAO,EAAE,EAAE,oBAAoB,EAAE,QAAQ,CAAC,MAAe,EAAE;gBAC3D,KAAK,EAAE;oBACL,iCAAiC,EAAE,OAAO;oBAC1C,8BAA8B,EAAE,OAAO;oBACvC,yCAAyC,EAAE;wBACzC,OAAO;wBACP,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE;qBACrC;oBACD,mCAAmC,EAAE,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;iBACvF;aACF;SACF,CAAC;IACJ,CAAC;IAED,sGAAsG;IACtG,MAAM,CAAC,SAAS,CAAC,IAMhB;QACC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;QAE1D,MAAM,KAAK,GAAG,CAAC,IAAY,EAAuB,EAAE;YAClD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;YAExC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;gBAChE,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC;gBAC5C,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5C,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;QAEF,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAE1B,OAAO,CAAC,GAAG,GAAG,CAAC;aACZ,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;aACvD,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC;IACrF,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,GAAG,CAAC,IAMV;QACC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;QAC1D,2GAA2G;QAC3G,wGAAwG;QACxG,MAAM,OAAO,GAAG,MAAM;aACnB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC;aACpC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEjE,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC;gBAClC,MAAM;gBACN,MAAM;gBACN,MAAM;gBACN,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,QAAQ;aACT,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO;oBACL,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,CAAC;oBACR,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,CAAC;4BACP,MAAM,EAAE,CAAC;4BACT,MAAM,EAAE,YAAY;4BACpB,OAAO,EAAE,+CAA+C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,0CAA0C;yBACpH;qBACF;iBACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,MAAM;YACjC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACjC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACzC,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;aACzB,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;CACF;AArID,gCAqIC;AAED;;;;;GAKG;AACH,MAAa,iBAAiB;aACZ,UAAK,GAAG,KAAK,CAAC;IAE9B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAsC;QACrD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;QAE5B,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC;YACrF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAEnB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAEnE,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAEvE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CACX,gCAAgC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAC1F,CAAC;YAEF,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAEtD,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CACX,iBAAiB,eAAe,CAAC,KAAK,QAAQ,eAAe,CAAC,KAAK,2BAA2B,KAAK,EAAE,CACtG,CAAC;YAEF,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QAED,MAAM,OAAO,GAAG,oBAAY,CAAC,OAAO,CAAC;YACnC,OAAO,EAAE,aAAa;YACtB,OAAO;YACP,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,GAAG,CAAC;YAC1C,KAAK;SACN,CAAC,CAAC;QAEH,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC;YAEtC,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QAED,IAAI,MAAc,CAAC;QAEnB,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;YACxD,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,KAAK,CAAC,uEAAuE,CAAC,CAAC;YAEvF,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,YAAY,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,YAAY,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,mBAAO,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACtF,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,YAAY,GAAG,CAAC,CAAC;QAErB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,oBAAY,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,oBAAY,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAEnE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3C,OAAO,CAAC,IAAI,CACV,wCAAwC,IAAA,oBAAQ,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,8DAA8D,CACvI,CAAC;YACJ,CAAC;YAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,MAAM,GAAG,IAAA,sBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAE1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC7B,SAAS;gBACX,CAAC;gBAED,MAAM,KAAK,GAAG,IAAA,oBAAQ,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACzD,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;gBAEnF,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACpC,WAAW,IAAI,CAAC,CAAC;oBACjB,OAAO,CAAC,IAAI,CACV,GAAG,KAAK,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,IAAI,aAAa,KAAK,MAAM,CAAC,OAAO,EAAE,CACjG,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBACpB,SAAS;gBACX,CAAC;gBAED,IAAI,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrB,YAAY,IAAI,CAAC,CAAC;oBAClB,OAAO,CAAC,IAAI,CACV,YAAY,KAAK,4DAA4D,CAC9E,CAAC;oBACF,SAAS;gBACX,CAAC;gBAED,YAAY,IAAI,CAAC,CAAC;gBAClB,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,KAAK,KAAK,MAAM,MAAM,CAAC,KAAK,WAAW,CAAC,CAAC;gBAE5F,IAAI,OAAO,EAAE,CAAC;oBACZ,IAAA,uBAAa,EAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CACT,6BAA6B,YAAY,YAAY,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,KAAK,QAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,KAAK,WAAW,eAAe;YACvL,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CACxD,CAAC;QAEF,IAAI,CAAC,OAAO,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,uCAAuC,eAAe,CAAC,KAAK,YAAY,CAAC,CAAC;QACxF,CAAC;QAED,IAAI,OAAO,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,CAAC;QACX,CAAC;QAED,OAAO,OAAO,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,CAAC;;AAnIH,8CAoIC","sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport type { Linter } from 'eslint';\nimport { CodemodFiles } from './files';\n\nconst USAGE = `Usage: devz codemod async-style [paths...] [--write | --check]\n\nApplies the fixers of three house lint rules, so a repository can sweep them without a lint pass:\n\n venizia/no-inline-await \\`expect(await f())\\` becomes \\`const result = await f(); expect(result)\\`\n venizia/no-return-await \\`return await f()\\` becomes \\`return f()\\` (\\`const result = await f(); return result;\\` in a try)\n venizia/no-await-promise-chain \\`const x = await f().catch(() => null)\\` becomes\n \\`let x; try { x = await f(); } catch (error) { x = null; }\\`\n\nIt changes only what the fixers can change safely, and lists the rest with its file, line and rule:\nan \\`await\\` inside a ternary or logical operand, a loop test, an unbraced \\`if\\` branch, or after a call\nthat may have effects; an awaited \\`.then\\` or \\`.finally\\`, a \\`.catch\\` whose handler has a block body or\ncalls something, and an awaited chain that is not the whole initializer of a \\`const\\` or \\`let\\`; and\nevery venizia/no-silent-catch finding (a handler or catch block that swallows the error), which it never\nfixes: what to log is your decision.\n\n --write write the changed files (without it, nothing is written)\n --check dry run that exits 1 when anything would change or is left unfixed (for CI)\n --all with --write and no path: rewrite every source file under the working directory (--write needs a path or --all)\n --help print this text and exit\n\nWith no flag it lists what would change and writes nothing. Inside a git repository it reads the\nfiles git knows (tracked, or untracked and not ignored), and --write refuses a file with local changes\n(changed, staged or untracked): commit or stash it first, so git can undo the codemod.`;\n\n/** A usage error: nothing was read or written. */\nconst USAGE_ERROR_CODE = 2;\n\n/** A file that can hold an `await` or a `catch`. */\nconst ASYNC_TEXT = /\\b(await|catch)\\b/;\n\nclass AsyncStyleFlags {\n static readonly WRITE = '--write';\n static readonly CHECK = '--check';\n static readonly ALL = '--all';\n static readonly HELP = '--help';\n static readonly HELP_SHORT = '-h';\n\n static readonly SCHEME_SET = new Set<string>([\n this.WRITE,\n this.CHECK,\n this.ALL,\n this.HELP,\n this.HELP_SHORT,\n ]);\n\n static isValid(value: string): boolean {\n return this.SCHEME_SET.has(value);\n }\n}\n\nexport interface IAsyncStyleReport {\n line: number;\n column: number;\n /** The rule id, or `undefined` for a file ESLint could not parse. */\n ruleId: string | null;\n message: string;\n}\n\nexport interface IAsyncStyleResult {\n output: string;\n changed: boolean;\n /** How many findings of the original source carried a fix, once the fixers changed it. */\n fixes: number;\n /** What is still reported after every pass. */\n reports: IAsyncStyleReport[];\n}\n\n/** Runs the async-style rules, and only those, over source text with ESLint's own fixer loop. */\nexport class AsyncStyle {\n /** The `Linter` config: the TypeScript parser and the rules of `asyncRuleConfigs`, at error. */\n static async createConfig(): Promise<Linter.Config[]> {\n const { default: tseslint } = await import('typescript-eslint');\n const { asyncRuleConfigs } = await import('../../linters/house/async-rules.js');\n\n return [\n {\n files: ['**/*.{ts,tsx,mts,cts}'],\n languageOptions: { parser: tseslint.parser },\n // Only the async-style rules run here, so a `// eslint-disable-next-line` for any other rule looks unused and\n // ESLint's fixer would delete it. A codemod never touches a directive.\n linterOptions: { reportUnusedDisableDirectives: 'off' },\n },\n ...asyncRuleConfigs,\n ];\n }\n\n /**\n * The self-check's config: four scope rules, run on the text before and after the fixers. A hoisted name must be\n * declared once, shadow nothing, be used after it is declared and be used at all; when the fixers break one of these\n * the count of that rule goes up, and the file is left as it was.\n */\n static async createChecks(): Promise<Linter.Config[]> {\n const { default: tseslint } = await import('typescript-eslint');\n\n return [\n {\n files: ['**/*.{ts,tsx,mts,cts}'],\n languageOptions: { parser: tseslint.parser },\n linterOptions: { reportUnusedDisableDirectives: 'off' },\n plugins: { '@typescript-eslint': tseslint.plugin as never },\n rules: {\n '@typescript-eslint/no-redeclare': 'error',\n '@typescript-eslint/no-shadow': 'error',\n '@typescript-eslint/no-use-before-define': [\n 'error',\n { functions: false, classes: false },\n ],\n '@typescript-eslint/no-unused-vars': ['error', { args: 'none', caughtErrors: 'none' }],\n },\n },\n ];\n }\n\n /** What got worse between `source` and `output` by the self-check's rules: empty when nothing did. */\n static selfCheck(opts: {\n linter: Linter;\n checks: Linter.Config[];\n source: string;\n output: string;\n filename: string;\n }): string[] {\n const { linter, checks, source, output, filename } = opts;\n\n const count = (text: string): Map<string, number> => {\n const found = new Map<string, number>();\n\n for (const message of linter.verify(text, checks, { filename })) {\n const key = message.ruleId ?? 'parse error';\n found.set(key, (found.get(key) ?? 0) + 1);\n }\n\n return found;\n };\n\n const was = count(source);\n const now = count(output);\n\n return [...now]\n .filter(([rule, total]) => total > (was.get(rule) ?? 0))\n .map(([rule, total]) => `${rule}: ${was.get(rule) ?? 0} before, ${total} after`);\n }\n\n /**\n * Fixes `source` (ESLint applies up to ten passes) and returns the text and what is left. `filename` is relative to\n * the linter's `cwd`. The fixed text is checked against the original (`checks`): if it has more redeclarations,\n * shadowed names, uses before declaration or unused variables than the original, no fix is returned and the file is\n * reported as `self-check`, so a hoisted name that does not match the expression it replaced never reaches a file.\n */\n static fix(opts: {\n linter: Linter;\n config: Linter.Config[];\n checks: Linter.Config[];\n source: string;\n filename: string;\n }): IAsyncStyleResult {\n const { linter, config, checks, source, filename } = opts;\n // A fix can leave a new finding behind (the try/catch of no-await-promise-chain is a silent catch when the\n // fallback is a constant), so the count is of the fixable findings, not of the findings that went away.\n const fixable = linter\n .verify(source, config, { filename })\n .filter((message) => message.fix !== undefined).length;\n const result = linter.verifyAndFix(source, config, { filename });\n\n if (result.output !== source) {\n const broken = AsyncStyle.selfCheck({\n linter,\n checks,\n source,\n output: result.output,\n filename,\n });\n\n if (broken.length > 0) {\n return {\n output: source,\n changed: false,\n fixes: 0,\n reports: [\n {\n line: 1,\n column: 1,\n ruleId: 'self-check',\n message: `the fixers would have made this file worse (${broken.join('; ')}); it is left as it was - fix it by hand`,\n },\n ],\n };\n }\n }\n\n return {\n output: result.output,\n changed: result.output !== source,\n fixes: result.fixed ? fixable : 0,\n reports: result.messages.map((message) => ({\n line: message.line,\n column: message.column,\n ruleId: message.ruleId,\n message: message.message,\n })),\n };\n }\n}\n\n/**\n * `devz codemod async-style [paths...] [--write | --check]`: applies the fixers of `no-inline-await`,\n * `no-return-await` and `no-await-promise-chain`, and lists what is left of those and of `no-silent-catch`.\n * It is a dry run unless `--write` is given. `--check` is the same dry run, and exits 1 when anything would\n * change or is left unfixed.\n */\nexport class AsyncStyleCommand {\n static readonly USAGE = USAGE;\n\n static async run(opts: { root: string; args: string[] }): Promise<number> {\n const { root, args } = opts;\n\n if (args.includes(AsyncStyleFlags.HELP) || args.includes(AsyncStyleFlags.HELP_SHORT)) {\n console.log(USAGE);\n\n return 0;\n }\n\n const flags = args.filter((argument) => argument.startsWith('-'));\n const paths = args.filter((argument) => !argument.startsWith('-'));\n\n const unknown = flags.filter((flag) => !AsyncStyleFlags.isValid(flag));\n\n if (unknown.length > 0) {\n console.error(\n `devz codemod: unknown option ${unknown.map((flag) => `\"${flag}\"`).join(', ')}\\n${USAGE}`,\n );\n\n return USAGE_ERROR_CODE;\n }\n\n const isWrite = flags.includes(AsyncStyleFlags.WRITE);\n const isCheck = flags.includes(AsyncStyleFlags.CHECK);\n\n if (isWrite && isCheck) {\n console.error(\n `devz codemod: ${AsyncStyleFlags.WRITE} and ${AsyncStyleFlags.CHECK} contradict each other\\n${USAGE}`,\n );\n\n return USAGE_ERROR_CODE;\n }\n\n const refusal = CodemodFiles.refusal({\n command: 'async-style',\n isWrite,\n isAll: flags.includes(AsyncStyleFlags.ALL),\n paths,\n });\n\n if (refusal) {\n console.error(`${refusal}\\n${USAGE}`);\n\n return USAGE_ERROR_CODE;\n }\n\n let linter: Linter;\n\n try {\n const { Linter: EslintLinter } = await import('eslint');\n linter = new EslintLinter({ cwd: root });\n } catch {\n console.error('devz codemod: the \"eslint\" package is required to run the lint fixers');\n\n return 1;\n }\n\n const config = await AsyncStyle.createConfig();\n const checks = await AsyncStyle.createChecks();\n const targets = (paths.length > 0 ? paths : ['.']).map((path) => resolve(root, path));\n let changedCount = 0;\n let fixCount = 0;\n let reportCount = 0;\n let refusedCount = 0;\n\n for (const target of targets) {\n const files = CodemodFiles.collect({ target });\n const dirty = isWrite ? CodemodFiles.dirty({ target }) : undefined;\n\n if (files.length === 0 && paths.length > 0) {\n console.warn(\n `devz codemod: no source files under \"${relative(root, target) || target}\" (git ignores the path, or it holds none): nothing was read`,\n );\n }\n\n for (const file of files) {\n const source = readFileSync(file, 'utf8');\n\n if (!ASYNC_TEXT.test(source)) {\n continue;\n }\n\n const shown = relative(root, file).split('\\\\').join('/');\n const result = AsyncStyle.fix({ linter, config, checks, source, filename: shown });\n\n for (const report of result.reports) {\n reportCount += 1;\n console.warn(\n `${shown}:${report.line}:${report.column} ${report.ruleId ?? 'parse error'} ${report.message}`,\n );\n }\n\n if (!result.changed) {\n continue;\n }\n\n if (dirty?.has(file)) {\n refusedCount += 1;\n console.warn(\n `refused ${shown} has local changes (commit or stash them, then run again)`,\n );\n continue;\n }\n\n changedCount += 1;\n fixCount += result.fixes;\n console.log(`${isWrite ? 'changed' : 'would change'} ${shown} (${result.fixes} fix(es))`);\n\n if (isWrite) {\n writeFileSync(file, result.output);\n }\n }\n }\n\n console.log(\n `devz codemod async-style: ${changedCount} file(s) ${isWrite ? 'changed' : 'would change'}, ${fixCount} fix(es) ${isWrite ? 'applied' : 'would be applied'}, ${reportCount} left unfixed` +\n (refusedCount > 0 ? `, ${refusedCount} refused` : ''),\n );\n\n if (!isWrite && changedCount > 0) {\n console.log(`Nothing was written. Run again with ${AsyncStyleFlags.WRITE} to apply.`);\n }\n\n if (isWrite && refusedCount > 0) {\n return 1;\n }\n\n return isCheck && (changedCount > 0 || reportCount > 0) ? 1 : 0;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connector-imports.js","sourceRoot":"","sources":["../../../src/cli/codemod/connector-imports.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join, relative, resolve } from 'node:path';\nimport { CodemodFiles } from './files';\n\nconst USAGE = `Usage: devz codemod connector-imports [paths...] [--write | --check]\n\nMoves the connector sub-path imports of @venizia/ignis to @venizia/ignis-connectors. The sub-paths\n@venizia/ignis/postgres, /postgres/node-postgres, /postgres/postgres-js, /postgres/pglite,\n/postgres/supabase, /relational, /sqlite, /sqlite/libsql, /search, /search/controllers, /meilisearch,\n/typesense and /typesense/controllers are removed; each one is the same name under\n@venizia/ignis-connectors, so the rewrite changes only the specifier.\n\nIt reads TypeScript files (.ts, .tsx, .mts, .cts): import and export declarations, import(\"...\"),\nrequire(\"...\"), require.resolve(\"...\") and import.meta.resolve(\"...\"), import(\"...\") types, declare module\n\"...\" and the module name of mock.module(\"...\") style calls. A .js, .cjs or .mjs file is not read: edit it by hand. Other sub-paths of @venizia/ignis (mail, static-asset,\ntesting, websocket, ...) and the root are not touched. The app must list @venizia/ignis-connectors as a\ndirect dependency: it reports each package.json that does not.\n\n --write write the changed files (without it, nothing is written)\n --check dry run that exits 1 while a file would change (for CI)\n --help print this text and exit\n\nWith no flag it lists what would change and writes nothing. Inside a git repository it reads the\nfiles git knows (tracked, or untracked and not ignored), and --write refuses a file with local changes\n(changed, staged or untracked): commit or stash it first, so git can undo the codemod.`;\n\n/** A usage error: nothing was read or written. */\nconst USAGE_ERROR_CODE = 2;\n\nconst CONNECTORS_PACKAGE = '@venizia/ignis-connectors';\nconst OLD_PREFIX = '@venizia/ignis/';\n\n/** The call names that take a module name as their first argument besides `require` and `import()`. */\nconst MODULE_NAME_CALLS = new Set([\n 'module',\n 'mock',\n 'doMock',\n 'unmock',\n 'importActual',\n 'requireActual',\n 'importMock',\n 'requireMock',\n]);\n\nclass ConnectorImportsFlags {\n static readonly WRITE = '--write';\n static readonly CHECK = '--check';\n static readonly HELP = '--help';\n static readonly HELP_SHORT = '-h';\n\n static readonly SCHEME_SET = new Set<string>([\n this.WRITE,\n this.CHECK,\n this.HELP,\n this.HELP_SHORT,\n ]);\n\n static isValid(value: string): boolean {\n return this.SCHEME_SET.has(value);\n }\n}\n\n/** The removed `@venizia/ignis/<sub-path>` specifiers and the `@venizia/ignis-connectors/<sub-path>` they became. */\nexport class ConnectorSpecifiers {\n static readonly SUBPATHS: ReadonlyArray<string> = [\n 'postgres',\n 'postgres/node-postgres',\n 'postgres/postgres-js',\n 'postgres/pglite',\n 'postgres/supabase',\n 'relational',\n 'sqlite',\n 'sqlite/libsql',\n 'search',\n 'search/controllers',\n 'meilisearch',\n 'typesense',\n 'typesense/controllers',\n ];\n\n static readonly MOVES: ReadonlyMap<string, string> = new Map(\n ConnectorSpecifiers.SUBPATHS.map((subpath) => [\n `${OLD_PREFIX}${subpath}`,\n `${CONNECTORS_PACKAGE}/${subpath}`,\n ]),\n );\n}\n\nexport interface IConnectorImportsResult {\n output: string;\n changed: boolean;\n /** How many specifiers were moved. */\n rewritten: number;\n}\n\n/** Rewrites the module specifiers of the removed connector sub-paths. */\nexport class ConnectorImports {\n static rewrite(opts: {\n typescript: typeof import('typescript');\n fileName: string;\n source: string;\n }): IConnectorImportsResult {\n const { typescript: ts, fileName, source } = opts;\n const scriptKind = fileName.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;\n const file = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true, scriptKind);\n const edits: Array<{ start: number; end: number; text: string }> = [];\n\n const consider = (literal: import('typescript').Node | undefined) => {\n if (!literal || !ts.isStringLiteralLike(literal)) {\n return;\n }\n\n const moved = ConnectorSpecifiers.MOVES.get(literal.text);\n if (moved === undefined) {\n return;\n }\n\n const start = literal.getStart(file);\n const quote = source[start];\n edits.push({ start, end: literal.getEnd(), text: `${quote}${moved}${quote}` });\n };\n\n const isModuleNameCall = (call: import('typescript').CallExpression): boolean => {\n const callee = call.expression;\n\n if (callee.kind === ts.SyntaxKind.ImportKeyword) {\n return true;\n }\n\n if (ts.isIdentifier(callee)) {\n return callee.text === 'require';\n }\n\n if (!ts.isPropertyAccessExpression(callee)) {\n return false;\n }\n\n if (callee.name.text === 'resolve') {\n return (\n (ts.isIdentifier(callee.expression) && callee.expression.text === 'require') ||\n ts.isMetaProperty(callee.expression)\n );\n }\n\n return MODULE_NAME_CALLS.has(callee.name.text);\n };\n\n const visit = (node: import('typescript').Node): void => {\n if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {\n consider(node.moduleSpecifier);\n } else if (ts.isImportEqualsDeclaration(node)) {\n if (ts.isExternalModuleReference(node.moduleReference)) {\n consider(node.moduleReference.expression);\n }\n } else if (ts.isCallExpression(node)) {\n if (isModuleNameCall(node)) {\n consider(node.arguments[0]);\n }\n } else if (ts.isModuleDeclaration(node)) {\n consider(node.name);\n } else if (ts.isImportTypeNode(node)) {\n if (ts.isLiteralTypeNode(node.argument)) {\n consider(node.argument.literal);\n }\n }\n\n ts.forEachChild(node, visit);\n };\n\n visit(file);\n\n if (edits.length === 0) {\n return { output: source, changed: false, rewritten: 0 };\n }\n\n let output = source;\n for (const edit of edits.sort((a, b) => b.start - a.start)) {\n output = output.slice(0, edit.start) + edit.text + output.slice(edit.end);\n }\n\n return { output, changed: true, rewritten: edits.length };\n }\n\n /**\n * The `package.json` nearest to `file` (not above `root`), and whether it lists the connectors package; `undefined` when\n * there is none to read.\n */\n static findManifest(opts: {\n file: string;\n root: string;\n }): { path: string; hasConnectors: boolean } | undefined {\n const { file, root } = opts;\n let directory = dirname(file);\n\n for (;;) {\n const candidate = join(directory, 'package.json');\n\n if (existsSync(candidate)) {\n let manifest: unknown;\n try {\n manifest = JSON.parse(readFileSync(candidate, 'utf8'));\n } catch (error) {\n console.warn(\n `${candidate} is not valid JSON, so its dependencies were not checked | ${error instanceof Error ? error.message : String(error)}`,\n );\n return undefined;\n }\n\n const listed =\n typeof manifest === 'object' &&\n manifest !== null &&\n ['dependencies', 'devDependencies', 'peerDependencies'].some((field) => {\n const group: unknown = Reflect.get(manifest, field);\n return typeof group === 'object' && group !== null && CONNECTORS_PACKAGE in group;\n });\n\n return { path: candidate, hasConnectors: listed };\n }\n\n if (directory === root || dirname(directory) === directory) {\n return undefined;\n }\n\n directory = dirname(directory);\n }\n }\n}\n\n/**\n * `devz codemod connector-imports [paths...] [--write | --check]`: moves the removed\n * `@venizia/ignis/<connector sub-path>` specifiers to `@venizia/ignis-connectors`. It is a dry run unless `--write`\n * is given. `--check` is the same dry run, and exits 1 while a file would change.\n */\nexport class ConnectorImportsCommand {\n static readonly USAGE = USAGE;\n\n static async run(opts: { root: string; args: string[] }): Promise<number> {\n const { root, args } = opts;\n\n if (\n args.includes(ConnectorImportsFlags.HELP) ||\n args.includes(ConnectorImportsFlags.HELP_SHORT)\n ) {\n console.log(USAGE);\n return 0;\n }\n\n const flags = args.filter((argument) => argument.startsWith('-'));\n const paths = args.filter((argument) => !argument.startsWith('-'));\n\n const unknown = flags.filter((flag) => !ConnectorImportsFlags.isValid(flag));\n if (unknown.length > 0) {\n console.error(\n `devz codemod: unknown option ${unknown.map((flag) => `\"${flag}\"`).join(', ')}\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n const isWrite = flags.includes(ConnectorImportsFlags.WRITE);\n const isCheck = flags.includes(ConnectorImportsFlags.CHECK);\n\n if (isWrite && isCheck) {\n console.error(\n `devz codemod: ${ConnectorImportsFlags.WRITE} and ${ConnectorImportsFlags.CHECK} contradict each other\\n${USAGE}`,\n );\n return USAGE_ERROR_CODE;\n }\n\n let typescript: typeof import('typescript');\n try {\n const loaded = await import('typescript');\n typescript = loaded.default;\n } catch {\n console.error('devz codemod: the \"typescript\" package is required to read your sources');\n return 1;\n }\n\n const targets = (paths.length > 0 ? paths : ['.']).map((path) => resolve(root, path));\n const missing = new Set<string>();\n let changedCount = 0;\n let specifierCount = 0;\n let refusedCount = 0;\n\n for (const target of targets) {\n const files = CodemodFiles.collect({ target });\n const dirty = isWrite ? CodemodFiles.dirty({ target }) : undefined;\n\n if (files.length === 0 && paths.length > 0) {\n console.warn(\n `devz codemod: no source files under \"${relative(root, target) || target}\" (git ignores the path, or it holds none): nothing was read`,\n );\n }\n\n for (const file of files) {\n const source = readFileSync(file, 'utf8');\n\n if (!source.includes(OLD_PREFIX)) {\n continue;\n }\n\n const result = ConnectorImports.rewrite({ typescript, fileName: file, source });\n\n if (!result.changed) {\n continue;\n }\n\n const shown = relative(root, file).split('\\\\').join('/') || file;\n\n if (dirty?.has(file)) {\n refusedCount += 1;\n console.warn(\n `refused ${shown} has local changes (commit or stash them, then run again)`,\n );\n continue;\n }\n\n changedCount += 1;\n specifierCount += result.rewritten;\n console.log(\n `${isWrite ? 'changed' : 'would change'} ${shown} (${result.rewritten} specifier(s))`,\n );\n\n const manifest = ConnectorImports.findManifest({ file, root });\n if (manifest && !manifest.hasConnectors) {\n missing.add(relative(root, manifest.path).split('\\\\').join('/') || manifest.path);\n }\n\n if (isWrite) {\n writeFileSync(file, result.output);\n }\n }\n }\n\n console.log(\n `devz codemod connector-imports: ${changedCount} file(s) ${isWrite ? 'changed' : 'would change'}, ${specifierCount} specifier(s) ${isWrite ? 'moved' : 'would be moved'}` +\n (refusedCount > 0 ? `, ${refusedCount} refused` : ''),\n );\n\n for (const manifestPath of [...missing].sort()) {\n console.warn(\n `${manifestPath} does not list ${CONNECTORS_PACKAGE}: add it as a dependency, because the imports now come from it`,\n );\n }\n\n if (!isWrite && changedCount > 0) {\n console.log(\n `Nothing was written. Run again with ${ConnectorImportsFlags.WRITE} to apply, then add the dependency and run your typecheck.`,\n );\n }\n\n if (isWrite && refusedCount > 0) {\n return 1;\n }\n\n return isCheck && changedCount > 0 ? 1 : 0;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"connector-imports.js","sourceRoot":"","sources":["../../../src/cli/codemod/connector-imports.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join, relative, resolve } from 'node:path';\nimport { CodemodFiles } from './files';\n\nconst USAGE = `Usage: devz codemod connector-imports [paths...] [--write | --check]\n\nMoves the connector sub-path imports of @venizia/ignis to @venizia/ignis-connectors. The sub-paths\n@venizia/ignis/postgres, /postgres/node-postgres, /postgres/postgres-js, /postgres/pglite,\n/postgres/supabase, /relational, /sqlite, /sqlite/libsql, /search, /search/controllers, /meilisearch,\n/typesense and /typesense/controllers are removed; each one is the same name under\n@venizia/ignis-connectors, so the rewrite changes only the specifier.\n\nIt reads TypeScript files (.ts, .tsx, .mts, .cts): import and export declarations, import(\"...\"),\nrequire(\"...\"), require.resolve(\"...\") and import.meta.resolve(\"...\"), import(\"...\") types, declare module\n\"...\" and the module name of mock.module(\"...\") style calls. A .js, .cjs or .mjs file is not read: edit it by hand. Other sub-paths of @venizia/ignis (mail, static-asset,\ntesting, websocket, ...) and the root are not touched. The app must list @venizia/ignis-connectors as a\ndirect dependency: it reports each package.json that does not.\n\n --write write the changed files (without it, nothing is written)\n --check dry run that exits 1 while a file would change (for CI)\n --help print this text and exit\n\nWith no flag it lists what would change and writes nothing. Inside a git repository it reads the\nfiles git knows (tracked, or untracked and not ignored), and --write refuses a file with local changes\n(changed, staged or untracked): commit or stash it first, so git can undo the codemod.`;\n\n/** A usage error: nothing was read or written. */\nconst USAGE_ERROR_CODE = 2;\n\nconst CONNECTORS_PACKAGE = '@venizia/ignis-connectors';\nconst OLD_PREFIX = '@venizia/ignis/';\n\n/** The call names that take a module name as their first argument besides `require` and `import()`. */\nconst MODULE_NAME_CALLS = new Set([\n 'module',\n 'mock',\n 'doMock',\n 'unmock',\n 'importActual',\n 'requireActual',\n 'importMock',\n 'requireMock',\n]);\n\nclass ConnectorImportsFlags {\n static readonly WRITE = '--write';\n static readonly CHECK = '--check';\n static readonly HELP = '--help';\n static readonly HELP_SHORT = '-h';\n\n static readonly SCHEME_SET = new Set<string>([\n this.WRITE,\n this.CHECK,\n this.HELP,\n this.HELP_SHORT,\n ]);\n\n static isValid(value: string): boolean {\n return this.SCHEME_SET.has(value);\n }\n}\n\n/** The removed `@venizia/ignis/<sub-path>` specifiers and the `@venizia/ignis-connectors/<sub-path>` they became. */\nexport class ConnectorSpecifiers {\n static readonly SUBPATHS: ReadonlyArray<string> = [\n 'postgres',\n 'postgres/node-postgres',\n 'postgres/postgres-js',\n 'postgres/pglite',\n 'postgres/supabase',\n 'relational',\n 'sqlite',\n 'sqlite/libsql',\n 'search',\n 'search/controllers',\n 'meilisearch',\n 'typesense',\n 'typesense/controllers',\n ];\n\n static readonly MOVES: ReadonlyMap<string, string> = new Map(\n ConnectorSpecifiers.SUBPATHS.map((subpath) => [\n `${OLD_PREFIX}${subpath}`,\n `${CONNECTORS_PACKAGE}/${subpath}`,\n ]),\n );\n}\n\nexport interface IConnectorImportsResult {\n output: string;\n changed: boolean;\n /** How many specifiers were moved. */\n rewritten: number;\n}\n\n/** Rewrites the module specifiers of the removed connector sub-paths. */\nexport class ConnectorImports {\n static rewrite(opts: {\n typescript: typeof import('typescript');\n fileName: string;\n source: string;\n }): IConnectorImportsResult {\n const { typescript: ts, fileName, source } = opts;\n const scriptKind = fileName.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;\n const file = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true, scriptKind);\n const edits: Array<{ start: number; end: number; text: string }> = [];\n\n const consider = (literal: import('typescript').Node | undefined) => {\n if (!literal || !ts.isStringLiteralLike(literal)) {\n return;\n }\n\n const moved = ConnectorSpecifiers.MOVES.get(literal.text);\n\n if (moved === undefined) {\n return;\n }\n\n const start = literal.getStart(file);\n const quote = source[start];\n edits.push({ start, end: literal.getEnd(), text: `${quote}${moved}${quote}` });\n };\n\n const isModuleNameCall = (call: import('typescript').CallExpression): boolean => {\n const callee = call.expression;\n\n if (callee.kind === ts.SyntaxKind.ImportKeyword) {\n return true;\n }\n\n if (ts.isIdentifier(callee)) {\n return callee.text === 'require';\n }\n\n if (!ts.isPropertyAccessExpression(callee)) {\n return false;\n }\n\n if (callee.name.text === 'resolve') {\n return (\n (ts.isIdentifier(callee.expression) && callee.expression.text === 'require') ||\n ts.isMetaProperty(callee.expression)\n );\n }\n\n return MODULE_NAME_CALLS.has(callee.name.text);\n };\n\n const visit = (node: import('typescript').Node): void => {\n if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {\n consider(node.moduleSpecifier);\n } else if (ts.isImportEqualsDeclaration(node)) {\n if (ts.isExternalModuleReference(node.moduleReference)) {\n consider(node.moduleReference.expression);\n }\n } else if (ts.isCallExpression(node)) {\n if (isModuleNameCall(node)) {\n consider(node.arguments[0]);\n }\n } else if (ts.isModuleDeclaration(node)) {\n consider(node.name);\n } else if (ts.isImportTypeNode(node)) {\n if (ts.isLiteralTypeNode(node.argument)) {\n consider(node.argument.literal);\n }\n }\n\n ts.forEachChild(node, visit);\n };\n\n visit(file);\n\n if (edits.length === 0) {\n return { output: source, changed: false, rewritten: 0 };\n }\n\n let output = source;\n\n for (const edit of edits.sort((a, b) => b.start - a.start)) {\n output = output.slice(0, edit.start) + edit.text + output.slice(edit.end);\n }\n\n return { output, changed: true, rewritten: edits.length };\n }\n\n /**\n * The `package.json` nearest to `file` (not above `root`), and whether it lists the connectors package; `undefined` when\n * there is none to read.\n */\n static findManifest(opts: {\n file: string;\n root: string;\n }): { path: string; hasConnectors: boolean } | undefined {\n const { file, root } = opts;\n let directory = dirname(file);\n\n for (;;) {\n const candidate = join(directory, 'package.json');\n\n if (existsSync(candidate)) {\n let manifest: unknown;\n\n try {\n manifest = JSON.parse(readFileSync(candidate, 'utf8'));\n } catch (error) {\n console.warn(\n `${candidate} is not valid JSON, so its dependencies were not checked | ${error instanceof Error ? error.message : String(error)}`,\n );\n\n return undefined;\n }\n\n const listed =\n typeof manifest === 'object' &&\n manifest !== null &&\n ['dependencies', 'devDependencies', 'peerDependencies'].some((field) => {\n const group: unknown = Reflect.get(manifest, field);\n\n return typeof group === 'object' && group !== null && CONNECTORS_PACKAGE in group;\n });\n\n return { path: candidate, hasConnectors: listed };\n }\n\n if (directory === root || dirname(directory) === directory) {\n return undefined;\n }\n\n directory = dirname(directory);\n }\n }\n}\n\n/**\n * `devz codemod connector-imports [paths...] [--write | --check]`: moves the removed\n * `@venizia/ignis/<connector sub-path>` specifiers to `@venizia/ignis-connectors`. It is a dry run unless `--write`\n * is given. `--check` is the same dry run, and exits 1 while a file would change.\n */\nexport class ConnectorImportsCommand {\n static readonly USAGE = USAGE;\n\n static async run(opts: { root: string; args: string[] }): Promise<number> {\n const { root, args } = opts;\n\n if (\n args.includes(ConnectorImportsFlags.HELP) ||\n args.includes(ConnectorImportsFlags.HELP_SHORT)\n ) {\n console.log(USAGE);\n\n return 0;\n }\n\n const flags = args.filter((argument) => argument.startsWith('-'));\n const paths = args.filter((argument) => !argument.startsWith('-'));\n\n const unknown = flags.filter((flag) => !ConnectorImportsFlags.isValid(flag));\n\n if (unknown.length > 0) {\n console.error(\n `devz codemod: unknown option ${unknown.map((flag) => `\"${flag}\"`).join(', ')}\\n${USAGE}`,\n );\n\n return USAGE_ERROR_CODE;\n }\n\n const isWrite = flags.includes(ConnectorImportsFlags.WRITE);\n const isCheck = flags.includes(ConnectorImportsFlags.CHECK);\n\n if (isWrite && isCheck) {\n console.error(\n `devz codemod: ${ConnectorImportsFlags.WRITE} and ${ConnectorImportsFlags.CHECK} contradict each other\\n${USAGE}`,\n );\n\n return USAGE_ERROR_CODE;\n }\n\n let typescript: typeof import('typescript');\n\n try {\n const loaded = await import('typescript');\n typescript = loaded.default;\n } catch {\n console.error('devz codemod: the \"typescript\" package is required to read your sources');\n\n return 1;\n }\n\n const targets = (paths.length > 0 ? paths : ['.']).map((path) => resolve(root, path));\n const missing = new Set<string>();\n let changedCount = 0;\n let specifierCount = 0;\n let refusedCount = 0;\n\n for (const target of targets) {\n const files = CodemodFiles.collect({ target });\n const dirty = isWrite ? CodemodFiles.dirty({ target }) : undefined;\n\n if (files.length === 0 && paths.length > 0) {\n console.warn(\n `devz codemod: no source files under \"${relative(root, target) || target}\" (git ignores the path, or it holds none): nothing was read`,\n );\n }\n\n for (const file of files) {\n const source = readFileSync(file, 'utf8');\n\n if (!source.includes(OLD_PREFIX)) {\n continue;\n }\n\n const result = ConnectorImports.rewrite({ typescript, fileName: file, source });\n\n if (!result.changed) {\n continue;\n }\n\n const shown = relative(root, file).split('\\\\').join('/') || file;\n\n if (dirty?.has(file)) {\n refusedCount += 1;\n console.warn(\n `refused ${shown} has local changes (commit or stash them, then run again)`,\n );\n continue;\n }\n\n changedCount += 1;\n specifierCount += result.rewritten;\n console.log(\n `${isWrite ? 'changed' : 'would change'} ${shown} (${result.rewritten} specifier(s))`,\n );\n\n const manifest = ConnectorImports.findManifest({ file, root });\n\n if (manifest && !manifest.hasConnectors) {\n missing.add(relative(root, manifest.path).split('\\\\').join('/') || manifest.path);\n }\n\n if (isWrite) {\n writeFileSync(file, result.output);\n }\n }\n }\n\n console.log(\n `devz codemod connector-imports: ${changedCount} file(s) ${isWrite ? 'changed' : 'would change'}, ${specifierCount} specifier(s) ${isWrite ? 'moved' : 'would be moved'}` +\n (refusedCount > 0 ? `, ${refusedCount} refused` : ''),\n );\n\n for (const manifestPath of [...missing].sort()) {\n console.warn(\n `${manifestPath} does not list ${CONNECTORS_PACKAGE}: add it as a dependency, because the imports now come from it`,\n );\n }\n\n if (!isWrite && changedCount > 0) {\n console.log(\n `Nothing was written. Run again with ${ConnectorImportsFlags.WRITE} to apply, then add the dependency and run your typecheck.`,\n );\n }\n\n if (isWrite && refusedCount > 0) {\n return 1;\n }\n\n return isCheck && changedCount > 0 ? 1 : 0;\n }\n}\n"]}
|