@venizia/dev-configs 0.4.6-0 → 0.4.7-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/dist/checks/catalog.d.ts.map +1 -1
- package/dist/checks/catalog.js +4 -2
- package/dist/checks/catalog.js.map +1 -1
- package/dist/checks/purity/probe.d.ts.map +1 -1
- package/dist/checks/purity/probe.js +2 -1
- package/dist/checks/purity/probe.js.map +1 -1
- package/dist/checks/test-controls.d.ts.map +1 -1
- package/dist/checks/test-controls.js +2 -1
- package/dist/checks/test-controls.js.map +1 -1
- package/dist/cli/codemod/async-style.d.ts +41 -0
- package/dist/cli/codemod/async-style.d.ts.map +1 -0
- package/dist/cli/codemod/async-style.js +166 -0
- package/dist/cli/codemod/async-style.js.map +1 -0
- package/dist/cli/codemod/const-classes.d.ts.map +1 -1
- package/dist/cli/codemod/const-classes.js +2 -1
- package/dist/cli/codemod/const-classes.js.map +1 -1
- package/dist/cli/codemod/drop-redundant-casts.d.ts.map +1 -1
- package/dist/cli/codemod/drop-redundant-casts.js +2 -1
- package/dist/cli/codemod/drop-redundant-casts.js.map +1 -1
- package/dist/cli/codemod/files.d.ts +7 -0
- package/dist/cli/codemod/files.d.ts.map +1 -1
- package/dist/cli/codemod/files.js +33 -0
- package/dist/cli/codemod/files.js.map +1 -1
- package/dist/cli/codemod/index.d.ts.map +1 -1
- package/dist/cli/codemod/index.js +7 -2
- package/dist/cli/codemod/index.js.map +1 -1
- package/dist/cli/index.js +1 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/linters/house/await-support.d.ts +60 -0
- package/dist/linters/house/await-support.d.ts.map +1 -0
- package/dist/linters/house/await-support.js +209 -0
- package/dist/linters/house/await-support.js.map +1 -0
- package/dist/linters/house/common.d.ts +2 -0
- package/dist/linters/house/common.d.ts.map +1 -1
- package/dist/linters/house/common.js +2 -0
- package/dist/linters/house/common.js.map +1 -1
- package/dist/linters/house/configs.d.ts +23 -0
- package/dist/linters/house/configs.d.ts.map +1 -1
- package/dist/linters/house/configs.js +46 -1
- package/dist/linters/house/configs.js.map +1 -1
- package/dist/linters/house/effect-cleanup-consistency.rule.d.ts +17 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.d.ts.map +1 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.js +87 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.js.map +1 -0
- package/dist/linters/house/hook-support.d.ts +29 -0
- package/dist/linters/house/hook-support.d.ts.map +1 -0
- package/dist/linters/house/hook-support.js +69 -0
- package/dist/linters/house/hook-support.js.map +1 -0
- package/dist/linters/house/index.d.ts +6 -0
- package/dist/linters/house/index.d.ts.map +1 -1
- package/dist/linters/house/index.js +6 -0
- package/dist/linters/house/index.js.map +1 -1
- package/dist/linters/house/no-async-hook-callback.rule.d.ts +18 -0
- package/dist/linters/house/no-async-hook-callback.rule.d.ts.map +1 -0
- package/dist/linters/house/no-async-hook-callback.rule.js +50 -0
- package/dist/linters/house/no-async-hook-callback.rule.js.map +1 -0
- package/dist/linters/house/no-inline-await.rule.d.ts +20 -0
- package/dist/linters/house/no-inline-await.rule.d.ts.map +1 -0
- package/dist/linters/house/no-inline-await.rule.js +76 -0
- package/dist/linters/house/no-inline-await.rule.js.map +1 -0
- package/dist/linters/house/no-return-await.rule.d.ts +15 -0
- package/dist/linters/house/no-return-await.rule.d.ts.map +1 -0
- package/dist/linters/house/no-return-await.rule.js +92 -0
- package/dist/linters/house/no-return-await.rule.js.map +1 -0
- package/dist/linters/house/plugin.d.ts.map +1 -1
- package/dist/linters/house/plugin.js +8 -0
- package/dist/linters/house/plugin.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/checks/catalog.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,6GAA6G;IAC7G,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,0FAA0F;IAC1F,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAEjB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAEnB,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;CACpB;AAcD,kHAAkH;AAClH,eAAO,MAAM,mBAAmB,GAAU,OAAM,eAAoB,KAAG,OAAO,CAAC,cAAc,
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/checks/catalog.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,6GAA6G;IAC7G,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,0FAA0F;IAC1F,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAEjB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAEnB,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;CACpB;AAcD,kHAAkH;AAClH,eAAO,MAAM,mBAAmB,GAAU,OAAM,eAAoB,KAAG,OAAO,CAAC,cAAc,CAoG5F,CAAC"}
|
package/dist/checks/catalog.js
CHANGED
|
@@ -10,7 +10,8 @@ const DEFAULT_GLOB = 'packages/*/package.json';
|
|
|
10
10
|
/** Reads the root catalog and every manifest the options name, and reports everything wrong with their ranges. */
|
|
11
11
|
const findCatalogProblems = async (opts = {}) => {
|
|
12
12
|
const { root = process.cwd(), globs = [], presetPrefix, pinned = [] } = opts;
|
|
13
|
-
const
|
|
13
|
+
const result = await Bun.file((0, node_path_1.join)(root, 'package.json')).text();
|
|
14
|
+
const rootJson = JSON.parse(result);
|
|
14
15
|
const catalog = rootJson.workspaces?.catalog ?? {};
|
|
15
16
|
if (Object.keys(catalog).length === 0) {
|
|
16
17
|
return { problems: [], entries: 0, referenced: 0, noCatalog: true };
|
|
@@ -27,7 +28,8 @@ const findCatalogProblems = async (opts = {}) => {
|
|
|
27
28
|
for (const file of [...files, ...presentPinned]) {
|
|
28
29
|
let json;
|
|
29
30
|
try {
|
|
30
|
-
|
|
31
|
+
const result2 = await Bun.file((0, node_path_1.join)(root, file)).text();
|
|
32
|
+
json = JSON.parse(result2);
|
|
31
33
|
}
|
|
32
34
|
catch (error) {
|
|
33
35
|
problems.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/checks/catalog.ts"],"names":[],"mappings":";;;AAAA,6BAA2B;AAC3B,qCAAqC;AACrC,yCAAiC;AA6CjC,yHAAyH;AACzH,MAAM,iBAAiB,GAAG,CAAC,cAAc,EAAE,iBAAiB,CAAU,CAAC;AAEvE,MAAM,YAAY,GAAG,yBAAyB,CAAC;AAS/C,kHAAkH;AAC3G,MAAM,mBAAmB,GAAG,KAAK,EAAE,OAAwB,EAAE,EAA2B,EAAE;IAC/F,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;IAC7E,MAAM,
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/checks/catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import { Glob } from 'bun';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/**\n * Guards dependency versions against the root `workspaces.catalog`.\n *\n * A catalogued dep is referenced as `catalog:` and resolved at publish time by `bun publish`, which\n * substitutes the real range while packing. `npm publish` does NOT - it ships `catalog:` verbatim\n * and the manifest is unresolvable for every consumer, which is how 0.1.1-9 / -6 / -4 broke.\n */\nexport interface ICatalogProblem {\n file: string;\n message: string;\n}\n\nexport interface ICatalogOptions {\n /** The repository root: where the root `package.json` and the globs resolve. Default: the current folder. */\n root?: string;\n\n /** Manifests to check, beside `packages/*\\/package.json`. A glob relative to the root. */\n globs?: string[];\n\n /**\n * Files that are not published manifests but carry `dependencies` and `devDependencies` the\n * release resolves (a VULCAN preset): `catalog:` is allowed in their `peerDependencies`, because a\n * library preset gives one name one catalog range. A file belongs here when its path starts with\n * this prefix, for example `presets/`.\n */\n presetPrefix?: string;\n\n /**\n * Manifests outside the workspace (a wiki with its own lockfile): `catalog:` does not resolve\n * there, so a catalogued dependency must be pinned to exactly the catalog's version instead.\n */\n pinned?: string[];\n}\n\nexport interface ICatalogReport {\n problems: ICatalogProblem[];\n entries: number;\n referenced: number;\n\n /** Set when there is no `workspaces.catalog` to check against. */\n noCatalog: boolean;\n}\n\n/** `peerDependencies` are compatibility statements for consumers and stay deliberately looser than the install range. */\nconst CATALOGUED_BLOCKS = ['dependencies', 'devDependencies'] as const;\n\nconst DEFAULT_GLOB = 'packages/*/package.json';\n\ninterface IManifest {\n workspaces?: { catalog?: Record<string, string> };\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\n/** Reads the root catalog and every manifest the options name, and reports everything wrong with their ranges. */\nexport const findCatalogProblems = async (opts: ICatalogOptions = {}): Promise<ICatalogReport> => {\n const { root = process.cwd(), globs = [], presetPrefix, pinned = [] } = opts;\n const result = await Bun.file(join(root, 'package.json')).text();\n const rootJson: IManifest = JSON.parse(result);\n const catalog: Record<string, string> = rootJson.workspaces?.catalog ?? {};\n\n if (Object.keys(catalog).length === 0) {\n return { problems: [], entries: 0, referenced: 0, noCatalog: true };\n }\n\n const problems: ICatalogProblem[] = [];\n const referenced = new Set<string>();\n const presentPinned = pinned.filter((file) => existsSync(join(root, file)));\n\n const files = new Set<string>();\n for (const pattern of [DEFAULT_GLOB, ...globs]) {\n for await (const file of new Glob(pattern).scan(root)) {\n files.add(file);\n }\n }\n\n for (const file of [...files, ...presentPinned]) {\n let json: IManifest;\n\n try {\n const result2 = await Bun.file(join(root, file)).text();\n json = JSON.parse(result2);\n } catch (error) {\n problems.push({\n file,\n message: `invalid JSON - ${error instanceof Error ? error.message : error}`,\n });\n continue;\n }\n\n const isPinned = presentPinned.includes(file);\n\n for (const block of CATALOGUED_BLOCKS) {\n const entriesList = Object.entries(json[block] ?? {});\n for (const [dep, range] of entriesList) {\n if (!(dep in catalog)) {\n continue;\n }\n\n referenced.add(dep);\n\n if (isPinned) {\n if (range !== catalog[dep]) {\n problems.push({\n file,\n message: `${block}.${dep} is \"${range}\" but the catalog pins \"${catalog[dep]}\" - this project is outside the workspace, so pin exactly that`,\n });\n }\n\n continue;\n }\n\n if (range === 'catalog:') {\n continue;\n }\n\n problems.push({\n file,\n message: `${block}.${dep} is \"${range}\" but the catalog owns it - use \"catalog:\" (catalog pins ${catalog[dep]})`,\n });\n }\n }\n\n // A preset is not a published manifest: its markers are resolved by the release, and the library kind gives a\n // name one catalog range, so a lib's peer takes the same marker as its dev dependency.\n const isPreset = presetPrefix !== undefined && file.startsWith(presetPrefix);\n\n // A peer resolved from the catalog would collapse to the exact install range, losing the looseness that makes it a peer.\n const peerEntries = Object.entries(json.peerDependencies ?? {});\n for (const [dep, range] of peerEntries) {\n if (range !== 'catalog:' || isPreset) {\n continue;\n }\n\n problems.push({\n file,\n message: `peerDependencies.${dep} uses \"catalog:\" - a peer range must stay hand-authored and looser than the install range`,\n });\n }\n }\n\n // A catalog entry nobody references is dead weight that will drift out of date unnoticed.\n const catalogKeys = Object.keys(catalog);\n for (const dep of catalogKeys) {\n if (referenced.has(dep)) {\n continue;\n }\n\n problems.push({\n file: 'package.json',\n message: `catalog entry \"${dep}\" is referenced by no workspace - drop it`,\n });\n }\n\n return { problems, entries: catalogKeys.length, referenced: referenced.size, noCatalog: false };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../../src/checks/purity/probe.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,kIAAkI;AAClI,eAAO,MAAM,kBAAkB,sBAAsB,CAAC;AAStD,wFAAwF;AACxF,qBAAa,eAAe;IAC1B,MAAM,CAAC,QAAQ,CAAC,KAAK,WAAW;IAChC,MAAM,CAAC,QAAQ,CAAC,OAAO,aAAa;IAEpC,MAAM,CAAC,QAAQ,CAAC,UAAU,cAA+C;IAEzE,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,cAAc;CAGvD;AAED,MAAM,MAAM,cAAc,GAAG,OAAO,CAClC,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,EACtD,MAAM,CACP,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,cAAc,CAAC;CAC1B,CAgCA,CAAC;AAaF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GAAI,MAAM,MAAM,KAAG,MAEvD,CAAC;
|
|
1
|
+
{"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../../src/checks/purity/probe.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,kIAAkI;AAClI,eAAO,MAAM,kBAAkB,sBAAsB,CAAC;AAStD,wFAAwF;AACxF,qBAAa,eAAe;IAC1B,MAAM,CAAC,QAAQ,CAAC,KAAK,WAAW;IAChC,MAAM,CAAC,QAAQ,CAAC,OAAO,aAAa;IAEpC,MAAM,CAAC,QAAQ,CAAC,UAAU,cAA+C;IAEzE,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,cAAc;CAGvD;AAED,MAAM,MAAM,cAAc,GAAG,OAAO,CAClC,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,EACtD,MAAM,CACP,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,cAAc,CAAC;CAC1B,CAgCA,CAAC;AAaF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GAAI,MAAM,MAAM,KAAG,MAEvD,CAAC;AAsIF;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAU,MAAM;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,KAAG,OAAO,CAAC,aAAa,CA6GxB,CAAC"}
|
|
@@ -181,7 +181,8 @@ const findUnresolvedExternalSpecifiers = (opts) => {
|
|
|
181
181
|
*/
|
|
182
182
|
const readMetafile = async (path) => {
|
|
183
183
|
try {
|
|
184
|
-
|
|
184
|
+
const result = await Bun.file(path).text();
|
|
185
|
+
return JSON.parse(result);
|
|
185
186
|
}
|
|
186
187
|
catch (error) {
|
|
187
188
|
const reason = error instanceof Error ? error.message : String(error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../../../src/checks/purity/probe.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { mkdir, rm } from 'node:fs/promises';\nimport { builtinModules } from 'node:module';\nimport { join } from 'node:path';\n\nexport interface IPurityResult {\n entry: string;\n ok: boolean;\n sizeBytes: number;\n builtins: string[];\n globals: string[];\n /** Node-global reads that cannot throw in a browser. Reported, never fatal. */\n guardedGlobals: string[];\n /**\n * Specifiers this probe run excluded from its own module graph. Always echoed back, on both the\n * passing and failing path - an entry that externalises something is measuring less than an entry\n * that does not, and that must stay visible next to the result, not be a silent input.\n */\n external: string[];\n buildError?: string;\n}\n\n/** Where the probe keeps its metafile, relative to the `cwd` it is given: the repository's own scratch, never the system temp. */\nexport const PURITY_SCRATCH_DIR = '.agents/local/tmp';\n\n/**\n * A browser entry must never reach `@venizia/dev-configs`: it is the Bun-only tooling package (its\n * `./testing` entry imports `bun:test`). Matches the workspace folder (not its own test fixtures) and the installed copy.\n */\nconst DEV_CONFIGS_PATH =\n /(^|\\/)(packages\\/dev-configs\\/(?!src\\/__tests__\\/)|node_modules\\/@venizia\\/dev-configs\\/)/;\n\n/** What a matched global means: ERROR is fatal, GUARDED is reported and never fatal. */\nexport class ProbeSeverities {\n static readonly ERROR = 'error';\n static readonly GUARDED = 'guarded';\n\n static readonly SCHEME_SET = new Set<string>([this.ERROR, this.GUARDED]);\n\n static isValid(value: string): value is TProbeSeverity {\n return this.SCHEME_SET.has(value);\n }\n}\n\nexport type TProbeSeverity = Extract<\n (typeof ProbeSeverities)[keyof typeof ProbeSeverities],\n string\n>;\n\n/**\n * Node globals survive verbatim into a `target: 'browser'` bundle, so a gate reading only module\n * specifiers reports clean on `process.env.NODE_ENV`. Each pattern must be anchored: a bundle\n * legitimately contains identifiers like `processQueue`. A lookbehind that rejects a preceding dot\n * also rejects `globalThis.process`, so every access path needs its own pattern.\n *\n * `severity` separates a read that throws from one that cannot. Optional chaining is not itself the\n * difference: `process?.env` throws a ReferenceError when `process` is a free identifier, while\n * `globalThis.process?.env` is an ordinary property read on an object that always exists.\n *\n * `guarded` means \"reported, never fatal\". Bare `process?.` sits there because this probe matches\n * bundled text and has no scope information: hono's `getColorEnabled` writes\n * `const { process, Deno } = globalThis;` and then `process?.env`, which is a local binding and\n * perfectly safe, and no regex can tell that apart from a free global. Failing on it would make the\n * gate cry wolf on a dependency; the unguarded `process.` and `globalThis.process.` forms stay\n * fatal, and those are the ones that are unambiguously browser-breaking.\n *\n * Exported for `probe.test.ts` to assert against directly, alongside {@link stripBundlerPathComments}.\n */\nexport const GLOBAL_PATTERNS: Array<{\n name: string;\n pattern: RegExp;\n severity: TProbeSeverity;\n}> = [\n { name: 'process', pattern: /(?<![A-Za-z0-9_$.])process\\s*\\./, severity: 'error' },\n { name: 'process?.', pattern: /(?<![A-Za-z0-9_$.])process\\s*\\?\\./, severity: 'guarded' },\n {\n name: 'globalThis.process',\n pattern: /(?<![A-Za-z0-9_$.])globalThis\\s*\\.\\s*process\\s*\\./,\n severity: 'error',\n },\n {\n name: 'globalThis.process?.',\n pattern: /(?<![A-Za-z0-9_$.])globalThis\\s*\\.\\s*process\\s*\\?\\./,\n severity: 'guarded',\n },\n {\n name: '__dirname',\n pattern: /(?<![A-Za-z0-9_$.])__dirname(?![A-Za-z0-9_$])/,\n severity: 'error',\n },\n {\n name: '__filename',\n pattern: /(?<![A-Za-z0-9_$.])__filename(?![A-Za-z0-9_$])/,\n severity: 'error',\n },\n {\n name: 'createRequire',\n pattern: /(?<![A-Za-z0-9_$.])createRequire\\s*\\(/,\n severity: 'error',\n },\n { name: 'require(', pattern: /(?<![A-Za-z0-9_$.])require\\s*\\(/, severity: 'error' },\n // Member access only. `typeof Bun !== 'undefined'` is the legitimate runtime probe and never\n // throws; `Bun.serve(...)` in a browser does.\n { name: 'Bun', pattern: /(?<![A-Za-z0-9_$.])Bun\\s*\\./, severity: 'error' },\n];\n\n/**\n * Bun's bundler prefixes every CommonJS-wrapped module with a full-line `// <path>.js` header (this\n * whole workspace emits CJS `dist/*.js` - no package declares `\"type\": \"module\"`). A source path is\n * free-form and can legitimately contain `process` as a substring with no identifier boundary on\n * its left, e.g. this gate's own `transport/in-process.js`: the header reads\n * `// packages/core-worker/dist/transport/in-process.js`, and `process.` there is a filename\n * fragment, not a read of the global. `GLOBAL_PATTERNS` matches bundled TEXT with no scope\n * information, so it cannot tell a path comment from code - stripped before matching.\n */\nconst BUNDLER_PATH_COMMENT = /^\\/\\/ [\\w@./-]+\\.(?:c|m)?js$/gm;\n\n/**\n * Exported so `probe.test.ts` can assert against the literal collision string directly, without\n * spawning `bun build` - a fixture whose OWN entry-path comment happens to reproduce the collision\n * is not something a filename choice can be relied on to keep reproducing.\n */\nexport const stripBundlerPathComments = (text: string): string => {\n return text.replace(BUNDLER_PATH_COMMENT, '');\n};\n\ninterface IMetafileImport {\n path: string;\n original?: string;\n external?: boolean;\n}\n\ninterface IMetafileInput {\n imports: IMetafileImport[];\n}\n\ninterface IMetafile {\n inputs: Record<string, IMetafileInput>;\n}\n\n/**\n * `node:module`'s own list, not a hand-maintained one: a bare `import ... from 'fs'` bundles\n * identically to `'node:fs'` (Bun stubs both to an empty object), and the metafile records\n * whichever spelling the source used. Matching by prefix alone misses the bare form entirely.\n */\nconst BUILTIN_MODULE_NAMES = new Set(builtinModules);\n\nconst isBuiltinSpecifier = (specifier: string): boolean => {\n const bareName = specifier.startsWith('node:') ? specifier.slice('node:'.length) : specifier;\n return BUILTIN_MODULE_NAMES.has(bareName);\n};\n\n/**\n * Measured against Bun 1.3.14: `--target=browser` never fails on a `node:` import and never leaves\n * the specifier in the bundled text. An unpolyfillable builtin (`fs`, `child_process`, ...) is\n * stubbed to an empty object; a polyfillable one (`crypto`, `path`, ...) is inlined in full under a\n * `/bun-vfs$$/` virtual path. Either way `exitCode` stays 0 and the specifier never survives into\n * stdout. The `--metafile` module graph is the only place it is preserved.\n */\nconst findBuiltinSpecifiers = (metafile: IMetafile): string[] => {\n const builtins = new Set<string>();\n\n const metafileInputsEntries = Object.entries(metafile.inputs);\n for (const [inputPath, input] of metafileInputsEntries) {\n if (isBuiltinSpecifier(inputPath)) {\n builtins.add(inputPath);\n }\n\n for (const dependency of input.imports) {\n const specifier = dependency.original ?? dependency.path;\n if (isBuiltinSpecifier(specifier)) {\n builtins.add(specifier);\n }\n }\n }\n\n return [...builtins].sort();\n};\n\n/**\n * A real npm dependency bundles in full under this target (measured: `zod` produces zero\n * `external` entries) and a genuinely missing package fails the build outright (nonzero exit,\n * caught before this runs). But a package's own `browser` field can remap a dependency to `false` -\n * the standard convention for disabling a Node-only dependency in browser builds - and Bun honours\n * that remap by leaving the import external with exit 0, whether or not the remapped name is a\n * builtin. An unresolved import in a browser bundle is not safe to wave through either way -\n * UNLESS the manifest entry asked for exactly this specifier via `external`, in which case its\n * presence here is the requested exclusion working, not a leak.\n */\n/**\n * A relative specifier is the package's own file, and a truly unreachable one fails the build with a\n * nonzero exit, which is caught before this runs. Bun's METAFILE nonetheless marks a re-export of the\n * form `export { name } from './x.js'` as `external` while inlining it - measured on\n * `helpers/dist/esm/core.js`: six such specifiers reported external, `Bundled 192 modules`, and the\n * output contains `class BaseHelper` with no bare relative import left in it. Reading the metafile\n * literally there reports a leak the bundle does not have.\n */\nconst isRelativeSpecifier = (specifier: string): boolean => {\n return specifier.startsWith('./') || specifier.startsWith('../');\n};\n\nconst findUnresolvedExternalSpecifiers = (opts: {\n metafile: IMetafile;\n builtins: Set<string>;\n requestedExternal: Set<string>;\n}): string[] => {\n const { metafile, builtins, requestedExternal } = opts;\n const unresolved = new Set<string>();\n\n const isRequestedExternal = (specifier: string): boolean => {\n for (const requested of requestedExternal) {\n if (specifier === requested || specifier.startsWith(`${requested}/`)) {\n return true;\n }\n }\n return false;\n };\n\n const metafileInputsValues = Object.values(metafile.inputs);\n for (const input of metafileInputsValues) {\n for (const dependency of input.imports) {\n if (!dependency.external) {\n continue;\n }\n\n const specifier = dependency.original ?? dependency.path;\n if (\n isRelativeSpecifier(specifier) ||\n builtins.has(specifier) ||\n isRequestedExternal(specifier)\n ) {\n continue;\n }\n\n unresolved.add(specifier);\n }\n }\n\n return [...unresolved].sort();\n};\n\n/**\n * Reads and removes the metafile unconditionally. Returns `undefined` rather than throwing -\n * `probeEntry` reports on every entry it is given rather than aborting the run of the other five.\n */\nconst readMetafile = async (path: string): Promise<IMetafile | undefined> => {\n try {\n return JSON.parse(await Bun.file(path).text()) as IMetafile;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n console.error(`[purity] Failed to read the build metafile at ${path}: ${reason}`);\n return undefined;\n } finally {\n await rm(path, { force: true });\n }\n};\n\n/**\n * The CLI, not `Bun.build()`: the in-process bundler resolves this workspace's symlinked\n * dependencies to directories and dies on them.\n */\nexport const probeEntry = async (opts: {\n entry: string;\n cwd: string;\n external?: string[];\n /** Defaults to {@link PURITY_SCRATCH_DIR} under `cwd`. */\n scratchDir?: string;\n}): Promise<IPurityResult> => {\n const { entry, cwd, external = [], scratchDir = join(cwd, PURITY_SCRATCH_DIR) } = opts;\n await mkdir(scratchDir, { recursive: true });\n const metafilePath = join(scratchDir, `purity-${randomUUID()}.json`);\n\n // `--env=disable`: Bun inlines `process.env.NODE_ENV` as a compile-time string constant by\n // default, regardless of whether the read is reachable. That erases the very read this probe\n // exists to catch, and the erasure depends on the ambient `NODE_ENV` the probe happens to run\n // under - the same failure shape as the undetected leak this gate was built to prevent.\n const externalArgs = external.flatMap((specifier) => ['--external', specifier]);\n const proc = Bun.spawn(\n [\n 'bun',\n 'build',\n entry,\n '--target=browser',\n '--format=esm',\n '--env=disable',\n `--metafile=${metafilePath}`,\n ...externalArgs,\n ],\n { cwd, stdout: 'pipe', stderr: 'pipe' },\n );\n\n const [stdout, stderr, exitCode] = await Promise.all([\n new Response(proc.stdout).text(),\n new Response(proc.stderr).text(),\n proc.exited,\n ]);\n\n if (exitCode !== 0) {\n await rm(metafilePath, { force: true });\n return {\n entry,\n ok: false,\n sizeBytes: 0,\n builtins: [],\n globals: [],\n guardedGlobals: [],\n external,\n buildError: stderr.trim(),\n };\n }\n\n const metafile = await readMetafile(metafilePath);\n if (!metafile) {\n return {\n entry,\n ok: false,\n sizeBytes: stdout.length,\n builtins: [],\n globals: [],\n guardedGlobals: [],\n external,\n buildError: 'Could not read the bun build metafile - the probe result is not trustworthy',\n };\n }\n\n const builtins = findBuiltinSpecifiers(metafile);\n const reachesDevConfigs = Object.keys(metafile.inputs).some((inputPath) =>\n DEV_CONFIGS_PATH.test(inputPath),\n );\n const unresolvedExternals = findUnresolvedExternalSpecifiers({\n metafile,\n builtins: new Set(builtins),\n requestedExternal: new Set(external),\n });\n const scannableText = stripBundlerPathComments(stdout);\n const matched = GLOBAL_PATTERNS.filter((g) => g.pattern.test(scannableText));\n const globals = matched.filter((g) => g.severity === ProbeSeverities.ERROR).map((g) => g.name);\n const guardedGlobals = matched\n .filter((g) => g.severity === ProbeSeverities.GUARDED)\n .map((g) => g.name);\n\n if (builtins.length > 0 || unresolvedExternals.length > 0 || reachesDevConfigs) {\n const reasons: string[] = [];\n if (reachesDevConfigs) {\n reasons.push(\n 'reaches @venizia/dev-configs, which is Bun-only tooling and never a browser dependency',\n );\n }\n if (builtins.length > 0) {\n reasons.push(`node builtin import(s): ${builtins.join(', ')}`);\n }\n if (unresolvedExternals.length > 0) {\n reasons.push(`unresolved external import(s): ${unresolvedExternals.join(', ')}`);\n }\n\n return {\n entry,\n ok: false,\n sizeBytes: stdout.length,\n builtins,\n globals,\n guardedGlobals,\n external,\n buildError: reasons.join(' | '),\n };\n }\n\n return {\n entry,\n ok: globals.length === 0,\n sizeBytes: stdout.length,\n builtins,\n globals,\n guardedGlobals,\n external,\n };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../../../src/checks/purity/probe.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { mkdir, rm } from 'node:fs/promises';\nimport { builtinModules } from 'node:module';\nimport { join } from 'node:path';\n\nexport interface IPurityResult {\n entry: string;\n ok: boolean;\n sizeBytes: number;\n builtins: string[];\n globals: string[];\n /** Node-global reads that cannot throw in a browser. Reported, never fatal. */\n guardedGlobals: string[];\n /**\n * Specifiers this probe run excluded from its own module graph. Always echoed back, on both the\n * passing and failing path - an entry that externalises something is measuring less than an entry\n * that does not, and that must stay visible next to the result, not be a silent input.\n */\n external: string[];\n buildError?: string;\n}\n\n/** Where the probe keeps its metafile, relative to the `cwd` it is given: the repository's own scratch, never the system temp. */\nexport const PURITY_SCRATCH_DIR = '.agents/local/tmp';\n\n/**\n * A browser entry must never reach `@venizia/dev-configs`: it is the Bun-only tooling package (its\n * `./testing` entry imports `bun:test`). Matches the workspace folder (not its own test fixtures) and the installed copy.\n */\nconst DEV_CONFIGS_PATH =\n /(^|\\/)(packages\\/dev-configs\\/(?!src\\/__tests__\\/)|node_modules\\/@venizia\\/dev-configs\\/)/;\n\n/** What a matched global means: ERROR is fatal, GUARDED is reported and never fatal. */\nexport class ProbeSeverities {\n static readonly ERROR = 'error';\n static readonly GUARDED = 'guarded';\n\n static readonly SCHEME_SET = new Set<string>([this.ERROR, this.GUARDED]);\n\n static isValid(value: string): value is TProbeSeverity {\n return this.SCHEME_SET.has(value);\n }\n}\n\nexport type TProbeSeverity = Extract<\n (typeof ProbeSeverities)[keyof typeof ProbeSeverities],\n string\n>;\n\n/**\n * Node globals survive verbatim into a `target: 'browser'` bundle, so a gate reading only module\n * specifiers reports clean on `process.env.NODE_ENV`. Each pattern must be anchored: a bundle\n * legitimately contains identifiers like `processQueue`. A lookbehind that rejects a preceding dot\n * also rejects `globalThis.process`, so every access path needs its own pattern.\n *\n * `severity` separates a read that throws from one that cannot. Optional chaining is not itself the\n * difference: `process?.env` throws a ReferenceError when `process` is a free identifier, while\n * `globalThis.process?.env` is an ordinary property read on an object that always exists.\n *\n * `guarded` means \"reported, never fatal\". Bare `process?.` sits there because this probe matches\n * bundled text and has no scope information: hono's `getColorEnabled` writes\n * `const { process, Deno } = globalThis;` and then `process?.env`, which is a local binding and\n * perfectly safe, and no regex can tell that apart from a free global. Failing on it would make the\n * gate cry wolf on a dependency; the unguarded `process.` and `globalThis.process.` forms stay\n * fatal, and those are the ones that are unambiguously browser-breaking.\n *\n * Exported for `probe.test.ts` to assert against directly, alongside {@link stripBundlerPathComments}.\n */\nexport const GLOBAL_PATTERNS: Array<{\n name: string;\n pattern: RegExp;\n severity: TProbeSeverity;\n}> = [\n { name: 'process', pattern: /(?<![A-Za-z0-9_$.])process\\s*\\./, severity: 'error' },\n { name: 'process?.', pattern: /(?<![A-Za-z0-9_$.])process\\s*\\?\\./, severity: 'guarded' },\n {\n name: 'globalThis.process',\n pattern: /(?<![A-Za-z0-9_$.])globalThis\\s*\\.\\s*process\\s*\\./,\n severity: 'error',\n },\n {\n name: 'globalThis.process?.',\n pattern: /(?<![A-Za-z0-9_$.])globalThis\\s*\\.\\s*process\\s*\\?\\./,\n severity: 'guarded',\n },\n {\n name: '__dirname',\n pattern: /(?<![A-Za-z0-9_$.])__dirname(?![A-Za-z0-9_$])/,\n severity: 'error',\n },\n {\n name: '__filename',\n pattern: /(?<![A-Za-z0-9_$.])__filename(?![A-Za-z0-9_$])/,\n severity: 'error',\n },\n {\n name: 'createRequire',\n pattern: /(?<![A-Za-z0-9_$.])createRequire\\s*\\(/,\n severity: 'error',\n },\n { name: 'require(', pattern: /(?<![A-Za-z0-9_$.])require\\s*\\(/, severity: 'error' },\n // Member access only. `typeof Bun !== 'undefined'` is the legitimate runtime probe and never\n // throws; `Bun.serve(...)` in a browser does.\n { name: 'Bun', pattern: /(?<![A-Za-z0-9_$.])Bun\\s*\\./, severity: 'error' },\n];\n\n/**\n * Bun's bundler prefixes every CommonJS-wrapped module with a full-line `// <path>.js` header (this\n * whole workspace emits CJS `dist/*.js` - no package declares `\"type\": \"module\"`). A source path is\n * free-form and can legitimately contain `process` as a substring with no identifier boundary on\n * its left, e.g. this gate's own `transport/in-process.js`: the header reads\n * `// packages/core-worker/dist/transport/in-process.js`, and `process.` there is a filename\n * fragment, not a read of the global. `GLOBAL_PATTERNS` matches bundled TEXT with no scope\n * information, so it cannot tell a path comment from code - stripped before matching.\n */\nconst BUNDLER_PATH_COMMENT = /^\\/\\/ [\\w@./-]+\\.(?:c|m)?js$/gm;\n\n/**\n * Exported so `probe.test.ts` can assert against the literal collision string directly, without\n * spawning `bun build` - a fixture whose OWN entry-path comment happens to reproduce the collision\n * is not something a filename choice can be relied on to keep reproducing.\n */\nexport const stripBundlerPathComments = (text: string): string => {\n return text.replace(BUNDLER_PATH_COMMENT, '');\n};\n\ninterface IMetafileImport {\n path: string;\n original?: string;\n external?: boolean;\n}\n\ninterface IMetafileInput {\n imports: IMetafileImport[];\n}\n\ninterface IMetafile {\n inputs: Record<string, IMetafileInput>;\n}\n\n/**\n * `node:module`'s own list, not a hand-maintained one: a bare `import ... from 'fs'` bundles\n * identically to `'node:fs'` (Bun stubs both to an empty object), and the metafile records\n * whichever spelling the source used. Matching by prefix alone misses the bare form entirely.\n */\nconst BUILTIN_MODULE_NAMES = new Set(builtinModules);\n\nconst isBuiltinSpecifier = (specifier: string): boolean => {\n const bareName = specifier.startsWith('node:') ? specifier.slice('node:'.length) : specifier;\n return BUILTIN_MODULE_NAMES.has(bareName);\n};\n\n/**\n * Measured against Bun 1.3.14: `--target=browser` never fails on a `node:` import and never leaves\n * the specifier in the bundled text. An unpolyfillable builtin (`fs`, `child_process`, ...) is\n * stubbed to an empty object; a polyfillable one (`crypto`, `path`, ...) is inlined in full under a\n * `/bun-vfs$$/` virtual path. Either way `exitCode` stays 0 and the specifier never survives into\n * stdout. The `--metafile` module graph is the only place it is preserved.\n */\nconst findBuiltinSpecifiers = (metafile: IMetafile): string[] => {\n const builtins = new Set<string>();\n\n const metafileInputsEntries = Object.entries(metafile.inputs);\n for (const [inputPath, input] of metafileInputsEntries) {\n if (isBuiltinSpecifier(inputPath)) {\n builtins.add(inputPath);\n }\n\n for (const dependency of input.imports) {\n const specifier = dependency.original ?? dependency.path;\n if (isBuiltinSpecifier(specifier)) {\n builtins.add(specifier);\n }\n }\n }\n\n return [...builtins].sort();\n};\n\n/**\n * A real npm dependency bundles in full under this target (measured: `zod` produces zero\n * `external` entries) and a genuinely missing package fails the build outright (nonzero exit,\n * caught before this runs). But a package's own `browser` field can remap a dependency to `false` -\n * the standard convention for disabling a Node-only dependency in browser builds - and Bun honours\n * that remap by leaving the import external with exit 0, whether or not the remapped name is a\n * builtin. An unresolved import in a browser bundle is not safe to wave through either way -\n * UNLESS the manifest entry asked for exactly this specifier via `external`, in which case its\n * presence here is the requested exclusion working, not a leak.\n */\n/**\n * A relative specifier is the package's own file, and a truly unreachable one fails the build with a\n * nonzero exit, which is caught before this runs. Bun's METAFILE nonetheless marks a re-export of the\n * form `export { name } from './x.js'` as `external` while inlining it - measured on\n * `helpers/dist/esm/core.js`: six such specifiers reported external, `Bundled 192 modules`, and the\n * output contains `class BaseHelper` with no bare relative import left in it. Reading the metafile\n * literally there reports a leak the bundle does not have.\n */\nconst isRelativeSpecifier = (specifier: string): boolean => {\n return specifier.startsWith('./') || specifier.startsWith('../');\n};\n\nconst findUnresolvedExternalSpecifiers = (opts: {\n metafile: IMetafile;\n builtins: Set<string>;\n requestedExternal: Set<string>;\n}): string[] => {\n const { metafile, builtins, requestedExternal } = opts;\n const unresolved = new Set<string>();\n\n const isRequestedExternal = (specifier: string): boolean => {\n for (const requested of requestedExternal) {\n if (specifier === requested || specifier.startsWith(`${requested}/`)) {\n return true;\n }\n }\n return false;\n };\n\n const metafileInputsValues = Object.values(metafile.inputs);\n for (const input of metafileInputsValues) {\n for (const dependency of input.imports) {\n if (!dependency.external) {\n continue;\n }\n\n const specifier = dependency.original ?? dependency.path;\n if (\n isRelativeSpecifier(specifier) ||\n builtins.has(specifier) ||\n isRequestedExternal(specifier)\n ) {\n continue;\n }\n\n unresolved.add(specifier);\n }\n }\n\n return [...unresolved].sort();\n};\n\n/**\n * Reads and removes the metafile unconditionally. Returns `undefined` rather than throwing -\n * `probeEntry` reports on every entry it is given rather than aborting the run of the other five.\n */\nconst readMetafile = async (path: string): Promise<IMetafile | undefined> => {\n try {\n const result = await Bun.file(path).text();\n return JSON.parse(result) as IMetafile;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n console.error(`[purity] Failed to read the build metafile at ${path}: ${reason}`);\n return undefined;\n } finally {\n await rm(path, { force: true });\n }\n};\n\n/**\n * The CLI, not `Bun.build()`: the in-process bundler resolves this workspace's symlinked\n * dependencies to directories and dies on them.\n */\nexport const probeEntry = async (opts: {\n entry: string;\n cwd: string;\n external?: string[];\n /** Defaults to {@link PURITY_SCRATCH_DIR} under `cwd`. */\n scratchDir?: string;\n}): Promise<IPurityResult> => {\n const { entry, cwd, external = [], scratchDir = join(cwd, PURITY_SCRATCH_DIR) } = opts;\n await mkdir(scratchDir, { recursive: true });\n const metafilePath = join(scratchDir, `purity-${randomUUID()}.json`);\n\n // `--env=disable`: Bun inlines `process.env.NODE_ENV` as a compile-time string constant by\n // default, regardless of whether the read is reachable. That erases the very read this probe\n // exists to catch, and the erasure depends on the ambient `NODE_ENV` the probe happens to run\n // under - the same failure shape as the undetected leak this gate was built to prevent.\n const externalArgs = external.flatMap((specifier) => ['--external', specifier]);\n const proc = Bun.spawn(\n [\n 'bun',\n 'build',\n entry,\n '--target=browser',\n '--format=esm',\n '--env=disable',\n `--metafile=${metafilePath}`,\n ...externalArgs,\n ],\n { cwd, stdout: 'pipe', stderr: 'pipe' },\n );\n\n const [stdout, stderr, exitCode] = await Promise.all([\n new Response(proc.stdout).text(),\n new Response(proc.stderr).text(),\n proc.exited,\n ]);\n\n if (exitCode !== 0) {\n await rm(metafilePath, { force: true });\n return {\n entry,\n ok: false,\n sizeBytes: 0,\n builtins: [],\n globals: [],\n guardedGlobals: [],\n external,\n buildError: stderr.trim(),\n };\n }\n\n const metafile = await readMetafile(metafilePath);\n if (!metafile) {\n return {\n entry,\n ok: false,\n sizeBytes: stdout.length,\n builtins: [],\n globals: [],\n guardedGlobals: [],\n external,\n buildError: 'Could not read the bun build metafile - the probe result is not trustworthy',\n };\n }\n\n const builtins = findBuiltinSpecifiers(metafile);\n const reachesDevConfigs = Object.keys(metafile.inputs).some((inputPath) =>\n DEV_CONFIGS_PATH.test(inputPath),\n );\n const unresolvedExternals = findUnresolvedExternalSpecifiers({\n metafile,\n builtins: new Set(builtins),\n requestedExternal: new Set(external),\n });\n const scannableText = stripBundlerPathComments(stdout);\n const matched = GLOBAL_PATTERNS.filter((g) => g.pattern.test(scannableText));\n const globals = matched.filter((g) => g.severity === ProbeSeverities.ERROR).map((g) => g.name);\n const guardedGlobals = matched\n .filter((g) => g.severity === ProbeSeverities.GUARDED)\n .map((g) => g.name);\n\n if (builtins.length > 0 || unresolvedExternals.length > 0 || reachesDevConfigs) {\n const reasons: string[] = [];\n if (reachesDevConfigs) {\n reasons.push(\n 'reaches @venizia/dev-configs, which is Bun-only tooling and never a browser dependency',\n );\n }\n if (builtins.length > 0) {\n reasons.push(`node builtin import(s): ${builtins.join(', ')}`);\n }\n if (unresolvedExternals.length > 0) {\n reasons.push(`unresolved external import(s): ${unresolvedExternals.join(', ')}`);\n }\n\n return {\n entry,\n ok: false,\n sizeBytes: stdout.length,\n builtins,\n globals,\n guardedGlobals,\n external,\n buildError: reasons.join(' | '),\n };\n }\n\n return {\n entry,\n ok: globals.length === 0,\n sizeBytes: stdout.length,\n builtins,\n globals,\n guardedGlobals,\n external,\n };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-controls.d.ts","sourceRoot":"","sources":["../../src/checks/test-controls.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,iHAAiH;IACjH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAU,MAAM;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,KAAG,OAAO,CAAC,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"test-controls.d.ts","sourceRoot":"","sources":["../../src/checks/test-controls.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,iHAAiH;IACjH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAU,MAAM;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,KAAG,OAAO,CAAC,MAAM,EAAE,CAiDnB,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,aAAa,GAAU,MAAM;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B,KAAG,OAAO,CAAC,eAAe,CAkC1B,CAAC"}
|
|
@@ -10,7 +10,8 @@ const node_path_1 = require("node:path");
|
|
|
10
10
|
* expressions, so the expansion does not matter.
|
|
11
11
|
*/
|
|
12
12
|
const listTestTitles = async (opts) => {
|
|
13
|
-
const
|
|
13
|
+
const result = await import('typescript');
|
|
14
|
+
const typescript = result.default;
|
|
14
15
|
const file = typescript.createSourceFile(opts.fileName ?? 'file.test.ts', opts.source, typescript.ScriptTarget.Latest, true);
|
|
15
16
|
const titles = [];
|
|
16
17
|
const RUNNERS = new Set(['test', 'it', 'describe']);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-controls.js","sourceRoot":"","sources":["../../src/checks/test-controls.ts"],"names":[],"mappings":";;;AAAA,qCAAmD;AACnD,yCAAiC;AAoCjC;;;;;GAKG;AACI,MAAM,cAAc,GAAG,KAAK,EAAE,IAGpC,EAAqB,EAAE;IACtB,MAAM,
|
|
1
|
+
{"version":3,"file":"test-controls.js","sourceRoot":"","sources":["../../src/checks/test-controls.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type ts from 'typescript';\n\n/**\n * A positive control is a test that proves a gate can fail: a fixture that must be refused, a broken\n * subject the check must catch. Deleting one makes the gate pass for the wrong reason, so the trim-tests\n * method keeps a committed registry of them and fails when one disappears.\n */\nexport interface IControlEntry {\n /** The gate the control belongs to; reported with a failure. */\n gate: string;\n /** Repository-relative path of the test file. */\n file: string;\n /**\n * `test` (default): `file` is a test file and `titlePattern` is matched against its titles.\n * `file`: `file` is a NEGATIVE FIXTURE, a file a test needs to be absent from the result (a class the\n * scanner must ignore). It only has to exist: without it the test's \"not found\" assertion passes for the\n * wrong reason.\n */\n kind?: 'test' | 'file';\n /** A regular expression matched against the TITLES (suite and case) in that file. Not used by `file` entries. */\n titlePattern?: string;\n /** At least this many titles must match. Default 1. */\n min?: number;\n}\n\nexport interface IControlProblem {\n entry: IControlEntry;\n message: string;\n}\n\nexport interface IControlsReport {\n checked: number;\n problems: IControlProblem[];\n}\n\n/**\n * The titles in a test file: the first string argument of `test`, `it`, `describe` and of the\n * second call of `test.each(rows)('title', ...)`, with their `.only`/`.skip`/`.if(...)` forms.\n * A `test.each` title is returned as written (`%s` and all): the registry patterns are regular\n * expressions, so the expansion does not matter.\n */\nexport const listTestTitles = async (opts: {\n source: string;\n fileName?: string;\n}): Promise<string[]> => {\n const result = await import('typescript');\n const typescript: typeof ts = result.default;\n const file = typescript.createSourceFile(\n opts.fileName ?? 'file.test.ts',\n opts.source,\n typescript.ScriptTarget.Latest,\n true,\n );\n const titles: string[] = [];\n const RUNNERS = new Set(['test', 'it', 'describe']);\n\n const rootName = (expression: ts.Expression): string | undefined => {\n if (typescript.isIdentifier(expression)) {\n return expression.text;\n }\n\n if (typescript.isPropertyAccessExpression(expression)) {\n return rootName(expression.expression);\n }\n\n if (typescript.isCallExpression(expression)) {\n return rootName(expression.expression);\n }\n\n return undefined;\n };\n\n const visit = (node: ts.Node): void => {\n if (typescript.isCallExpression(node)) {\n const first = node.arguments[0];\n const root = rootName(node.expression);\n\n if (\n root !== undefined &&\n RUNNERS.has(root) &&\n first &&\n (typescript.isStringLiteral(first) || typescript.isNoSubstitutionTemplateLiteral(first))\n ) {\n titles.push(first.text);\n }\n }\n\n typescript.forEachChild(node, visit);\n };\n\n visit(file);\n\n return titles;\n};\n\n/** Checks every entry of the registry against the test files it names. */\nexport const checkControls = async (opts: {\n root: string;\n controls: IControlEntry[];\n}): Promise<IControlsReport> => {\n const problems: IControlProblem[] = [];\n\n for (const entry of opts.controls) {\n const path = join(opts.root, entry.file);\n if (!existsSync(path)) {\n problems.push({\n entry,\n message: `the ${entry.kind === 'file' ? 'negative fixture' : 'test file'} ${entry.file} does not exist`,\n });\n continue;\n }\n\n if (entry.kind === 'file') {\n continue;\n }\n\n const titles = await listTestTitles({\n source: readFileSync(path, 'utf8'),\n fileName: entry.file,\n });\n const pattern = new RegExp(entry.titlePattern ?? '');\n const matched = titles.filter((title) => pattern.test(title)).length;\n const min = entry.min ?? 1;\n\n if (matched < min) {\n problems.push({\n entry,\n message: `${matched} title(s) match /${entry.titlePattern ?? ''}/ in ${entry.file}, ${min} required | the control of gate '${entry.gate}' is gone or renamed`,\n });\n }\n }\n\n return { checked: opts.controls.length, problems };\n};\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
export interface IAsyncStyleReport {
|
|
3
|
+
line: number;
|
|
4
|
+
column: number;
|
|
5
|
+
/** The rule id, or `undefined` for a file ESLint could not parse. */
|
|
6
|
+
ruleId: string | null;
|
|
7
|
+
message: string;
|
|
8
|
+
}
|
|
9
|
+
export interface IAsyncStyleResult {
|
|
10
|
+
output: string;
|
|
11
|
+
changed: boolean;
|
|
12
|
+
/** How many findings the fixers removed. */
|
|
13
|
+
fixes: number;
|
|
14
|
+
/** What is still reported after every pass. */
|
|
15
|
+
reports: IAsyncStyleReport[];
|
|
16
|
+
}
|
|
17
|
+
/** Runs the two async-style rules, and only those, over source text with ESLint's own fixer loop. */
|
|
18
|
+
export declare class AsyncStyle {
|
|
19
|
+
/** The `Linter` config: the TypeScript parser and the two rules at error, from `asyncStyleConfigs`. */
|
|
20
|
+
static createConfig(): Promise<Linter.Config[]>;
|
|
21
|
+
/** Fixes `source` (ESLint applies up to ten passes) and returns the text and what is left. `filename` is relative to the linter's `cwd`. */
|
|
22
|
+
static fix(opts: {
|
|
23
|
+
linter: Linter;
|
|
24
|
+
config: Linter.Config[];
|
|
25
|
+
source: string;
|
|
26
|
+
filename: string;
|
|
27
|
+
}): IAsyncStyleResult;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* `devz codemod async-style [paths...] [--write | --check]`: applies the fixers of `no-inline-await`
|
|
31
|
+
* and `no-return-await`. It is a dry run unless `--write` is given. `--check` is the same dry run, and
|
|
32
|
+
* exits 1 when anything would change or is left unfixed.
|
|
33
|
+
*/
|
|
34
|
+
export declare class AsyncStyleCommand {
|
|
35
|
+
static readonly USAGE = "Usage: devz codemod async-style [paths...] [--write | --check]\n\nApplies the fixers of two 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\nIt changes only what the fixers can change safely. An `await` inside a ternary or logical operand, a loop\ntest, an unbraced `if` branch, or after a call that may have effects is listed with its file, line and\nrule, and left for you.\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 --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.";
|
|
36
|
+
static run(opts: {
|
|
37
|
+
root: string;
|
|
38
|
+
args: string[];
|
|
39
|
+
}): Promise<number>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=async-style.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-style.d.ts","sourceRoot":"","sources":["../../../src/cli/codemod/async-style.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AA8CrC,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,qGAAqG;AACrG,qBAAa,UAAU;IACrB,uGAAuG;WAC1F,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IAgBrD,4IAA4I;IAC5I,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE;QACf,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,iBAAiB;CAiBtB;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,MAAM,CAAC,QAAQ,CAAC,KAAK,omCAAS;WAEjB,GAAG,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CA6G1E"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AsyncStyleCommand = exports.AsyncStyle = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const files_1 = require("./files");
|
|
7
|
+
const USAGE = `Usage: devz codemod async-style [paths...] [--write | --check]
|
|
8
|
+
|
|
9
|
+
Applies the fixers of two house lint rules, so a repository can sweep them without a lint pass:
|
|
10
|
+
|
|
11
|
+
venizia/no-inline-await \`expect(await f())\` becomes \`const result = await f(); expect(result)\`
|
|
12
|
+
venizia/no-return-await \`return await f()\` becomes \`return f()\` (\`const result = await f(); return result;\` in a try)
|
|
13
|
+
|
|
14
|
+
It changes only what the fixers can change safely. An \`await\` inside a ternary or logical operand, a loop
|
|
15
|
+
test, an unbraced \`if\` branch, or after a call that may have effects is listed with its file, line and
|
|
16
|
+
rule, and left for you.
|
|
17
|
+
|
|
18
|
+
--write write the changed files (without it, nothing is written)
|
|
19
|
+
--check dry run that exits 1 when anything would change or is left unfixed (for CI)
|
|
20
|
+
--help print this text and exit
|
|
21
|
+
|
|
22
|
+
With no flag it lists what would change and writes nothing. Inside a git repository it reads the
|
|
23
|
+
files git knows (tracked, or untracked and not ignored), and --write refuses a file with local changes
|
|
24
|
+
(changed, staged or untracked): commit or stash it first, so git can undo the codemod.`;
|
|
25
|
+
/** A usage error: nothing was read or written. */
|
|
26
|
+
const USAGE_ERROR_CODE = 2;
|
|
27
|
+
/** A file that can hold an `await`. */
|
|
28
|
+
const AWAIT_TEXT = /\bawait\b/;
|
|
29
|
+
class AsyncStyleFlags {
|
|
30
|
+
static { this.WRITE = '--write'; }
|
|
31
|
+
static { this.CHECK = '--check'; }
|
|
32
|
+
static { this.HELP = '--help'; }
|
|
33
|
+
static { this.HELP_SHORT = '-h'; }
|
|
34
|
+
static { this.SCHEME_SET = new Set([
|
|
35
|
+
this.WRITE,
|
|
36
|
+
this.CHECK,
|
|
37
|
+
this.HELP,
|
|
38
|
+
this.HELP_SHORT,
|
|
39
|
+
]); }
|
|
40
|
+
static isValid(value) {
|
|
41
|
+
return this.SCHEME_SET.has(value);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Runs the two async-style rules, and only those, over source text with ESLint's own fixer loop. */
|
|
45
|
+
class AsyncStyle {
|
|
46
|
+
/** The `Linter` config: the TypeScript parser and the two rules at error, from `asyncStyleConfigs`. */
|
|
47
|
+
static async createConfig() {
|
|
48
|
+
const { default: tseslint } = await import('typescript-eslint');
|
|
49
|
+
const { asyncStyleConfigs } = await import('../../linters/house/index.js');
|
|
50
|
+
return [
|
|
51
|
+
{
|
|
52
|
+
files: ['**/*.{ts,tsx,mts,cts}'],
|
|
53
|
+
languageOptions: { parser: tseslint.parser },
|
|
54
|
+
// Only two rules run here, so a `// eslint-disable-next-line` for any other rule looks unused and
|
|
55
|
+
// ESLint's fixer would delete it. A codemod never touches a directive.
|
|
56
|
+
linterOptions: { reportUnusedDisableDirectives: 'off' },
|
|
57
|
+
},
|
|
58
|
+
...asyncStyleConfigs,
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
/** Fixes `source` (ESLint applies up to ten passes) and returns the text and what is left. `filename` is relative to the linter's `cwd`. */
|
|
62
|
+
static fix(opts) {
|
|
63
|
+
const { linter, config, source, filename } = opts;
|
|
64
|
+
const before = linter.verify(source, config, { filename }).length;
|
|
65
|
+
const result = linter.verifyAndFix(source, config, { filename });
|
|
66
|
+
return {
|
|
67
|
+
output: result.output,
|
|
68
|
+
changed: result.output !== source,
|
|
69
|
+
fixes: result.fixed ? Math.max(0, before - result.messages.length) : 0,
|
|
70
|
+
reports: result.messages.map((message) => ({
|
|
71
|
+
line: message.line,
|
|
72
|
+
column: message.column,
|
|
73
|
+
ruleId: message.ruleId,
|
|
74
|
+
message: message.message,
|
|
75
|
+
})),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.AsyncStyle = AsyncStyle;
|
|
80
|
+
/**
|
|
81
|
+
* `devz codemod async-style [paths...] [--write | --check]`: applies the fixers of `no-inline-await`
|
|
82
|
+
* and `no-return-await`. It is a dry run unless `--write` is given. `--check` is the same dry run, and
|
|
83
|
+
* exits 1 when anything would change or is left unfixed.
|
|
84
|
+
*/
|
|
85
|
+
class AsyncStyleCommand {
|
|
86
|
+
static { this.USAGE = USAGE; }
|
|
87
|
+
static async run(opts) {
|
|
88
|
+
const { root, args } = opts;
|
|
89
|
+
if (args.includes(AsyncStyleFlags.HELP) || args.includes(AsyncStyleFlags.HELP_SHORT)) {
|
|
90
|
+
console.log(USAGE);
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
const flags = args.filter((argument) => argument.startsWith('-'));
|
|
94
|
+
const paths = args.filter((argument) => !argument.startsWith('-'));
|
|
95
|
+
const unknown = flags.filter((flag) => !AsyncStyleFlags.isValid(flag));
|
|
96
|
+
if (unknown.length > 0) {
|
|
97
|
+
console.error(`devz codemod: unknown option ${unknown.map((flag) => `"${flag}"`).join(', ')}\n${USAGE}`);
|
|
98
|
+
return USAGE_ERROR_CODE;
|
|
99
|
+
}
|
|
100
|
+
const isWrite = flags.includes(AsyncStyleFlags.WRITE);
|
|
101
|
+
const isCheck = flags.includes(AsyncStyleFlags.CHECK);
|
|
102
|
+
if (isWrite && isCheck) {
|
|
103
|
+
console.error(`devz codemod: ${AsyncStyleFlags.WRITE} and ${AsyncStyleFlags.CHECK} contradict each other\n${USAGE}`);
|
|
104
|
+
return USAGE_ERROR_CODE;
|
|
105
|
+
}
|
|
106
|
+
let linter;
|
|
107
|
+
try {
|
|
108
|
+
const { Linter: EslintLinter } = await import('eslint');
|
|
109
|
+
linter = new EslintLinter({ cwd: root });
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
console.error('devz codemod: the "eslint" package is required to run the lint fixers');
|
|
113
|
+
return 1;
|
|
114
|
+
}
|
|
115
|
+
const config = await AsyncStyle.createConfig();
|
|
116
|
+
const targets = (paths.length > 0 ? paths : ['.']).map((path) => (0, node_path_1.resolve)(root, path));
|
|
117
|
+
let changedCount = 0;
|
|
118
|
+
let fixCount = 0;
|
|
119
|
+
let reportCount = 0;
|
|
120
|
+
let refusedCount = 0;
|
|
121
|
+
for (const target of targets) {
|
|
122
|
+
const files = files_1.CodemodFiles.collect({ target });
|
|
123
|
+
const dirty = isWrite ? files_1.CodemodFiles.dirty({ target }) : undefined;
|
|
124
|
+
if (files.length === 0 && paths.length > 0) {
|
|
125
|
+
console.warn(`devz codemod: no source files under "${(0, node_path_1.relative)(root, target) || target}" (git ignores the path, or it holds none): nothing was read`);
|
|
126
|
+
}
|
|
127
|
+
for (const file of files) {
|
|
128
|
+
const source = (0, node_fs_1.readFileSync)(file, 'utf8');
|
|
129
|
+
if (!AWAIT_TEXT.test(source)) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const shown = (0, node_path_1.relative)(root, file).split('\\').join('/');
|
|
133
|
+
const result = AsyncStyle.fix({ linter, config, source, filename: shown });
|
|
134
|
+
for (const report of result.reports) {
|
|
135
|
+
reportCount += 1;
|
|
136
|
+
console.warn(`${shown}:${report.line}:${report.column} ${report.ruleId ?? 'parse error'} ${report.message}`);
|
|
137
|
+
}
|
|
138
|
+
if (!result.changed) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (dirty?.has(file)) {
|
|
142
|
+
refusedCount += 1;
|
|
143
|
+
console.warn(`refused ${shown} has local changes (commit or stash them, then run again)`);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
changedCount += 1;
|
|
147
|
+
fixCount += result.fixes;
|
|
148
|
+
console.log(`${isWrite ? 'changed' : 'would change'} ${shown} (${result.fixes} fix(es))`);
|
|
149
|
+
if (isWrite) {
|
|
150
|
+
(0, node_fs_1.writeFileSync)(file, result.output);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
console.log(`devz codemod async-style: ${changedCount} file(s) ${isWrite ? 'changed' : 'would change'}, ${fixCount} fix(es) ${isWrite ? 'applied' : 'would be applied'}, ${reportCount} left unfixed` +
|
|
155
|
+
(refusedCount > 0 ? `, ${refusedCount} refused` : ''));
|
|
156
|
+
if (!isWrite && changedCount > 0) {
|
|
157
|
+
console.log(`Nothing was written. Run again with ${AsyncStyleFlags.WRITE} to apply.`);
|
|
158
|
+
}
|
|
159
|
+
if (isWrite && refusedCount > 0) {
|
|
160
|
+
return 1;
|
|
161
|
+
}
|
|
162
|
+
return isCheck && (changedCount > 0 || reportCount > 0) ? 1 : 0;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
exports.AsyncStyleCommand = AsyncStyleCommand;
|
|
166
|
+
//# sourceMappingURL=async-style.js.map
|
|
@@ -0,0 +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 two 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\nIt changes only what the fixers can change safely. An \\`await\\` inside a ternary or logical operand, a loop\ntest, an unbraced \\`if\\` branch, or after a call that may have effects is listed with its file, line and\nrule, and left for you.\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 --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`. */\nconst AWAIT_TEXT = /\\bawait\\b/;\n\nclass AsyncStyleFlags {\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\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 the fixers removed. */\n fixes: number;\n /** What is still reported after every pass. */\n reports: IAsyncStyleReport[];\n}\n\n/** Runs the two 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 two rules at error, from `asyncStyleConfigs`. */\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 two 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 /** Fixes `source` (ESLint applies up to ten passes) and returns the text and what is left. `filename` is relative to the linter's `cwd`. */\n static fix(opts: {\n linter: Linter;\n config: Linter.Config[];\n source: string;\n filename: string;\n }): IAsyncStyleResult {\n const { linter, config, source, filename } = opts;\n const before = linter.verify(source, config, { filename }).length;\n const result = linter.verifyAndFix(source, config, { filename });\n\n return {\n output: result.output,\n changed: result.output !== source,\n fixes: result.fixed ? Math.max(0, before - result.messages.length) : 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 * and `no-return-await`. It is a dry run unless `--write` is given. `--check` is the same dry run, and\n * exits 1 when anything would 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 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 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 (!AWAIT_TEXT.test(source)) {\n continue;\n }\n\n const shown = relative(root, file).split('\\\\').join('/');\n const result = AsyncStyle.fix({ linter, config, 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":"const-classes.d.ts","sourceRoot":"","sources":["../../../src/cli/codemod/const-classes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAGjC,KAAK,WAAW,GAAG,OAAO,EAAE,CAAC;AAU7B,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,oCAAoC;IACpC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAClC,qGAAqG;IACrG,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,uDAAuD;IACvD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,SAAS,EAAE,oBAAoB,EAAE,CAAC;CACnC;AA4CD;;;;GAIG;AACH,qBAAa,YAAY;IACvB,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QACnB,UAAU,EAAE,WAAW,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,4FAA4F;QAC5F,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,cAAc,CAAC;QAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,iBAAiB;IA4KrB,OAAO,CAAC,MAAM,CAAC,WAAW;IA8C1B,yDAAyD;IACzD,OAAO,CAAC,MAAM,CAAC,aAAa;IAoD5B,OAAO,CAAC,MAAM,CAAC,UAAU;IAQzB,iIAAiI;IACjI,OAAO,CAAC,MAAM,CAAC,SAAS;IA+BxB,gFAAgF;IAChF,OAAO,CAAC,MAAM,CAAC,YAAY;IAuB3B,OAAO,CAAC,MAAM,CAAC,SAAS;IAqCxB,OAAO,CAAC,MAAM,CAAC,WAAW;IAuB1B,sHAAsH;IACtH,OAAO,CAAC,MAAM,CAAC,UAAU;IAkCzB,OAAO,CAAC,MAAM,CAAC,QAAQ;IA2BvB,wJAAwJ;IACxJ,OAAO,CAAC,MAAM,CAAC,UAAU;CAqD1B;AAyDD,mEAAmE;AACnE,qBAAa,mBAAmB;IAC9B,MAAM,CAAC,QAAQ,CAAC,KAAK,ipDAAS;WAEjB,GAAG,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"const-classes.d.ts","sourceRoot":"","sources":["../../../src/cli/codemod/const-classes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAGjC,KAAK,WAAW,GAAG,OAAO,EAAE,CAAC;AAU7B,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,oCAAoC;IACpC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAClC,qGAAqG;IACrG,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,uDAAuD;IACvD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,SAAS,EAAE,oBAAoB,EAAE,CAAC;CACnC;AA4CD;;;;GAIG;AACH,qBAAa,YAAY;IACvB,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QACnB,UAAU,EAAE,WAAW,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,4FAA4F;QAC5F,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,cAAc,CAAC;QAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,iBAAiB;IA4KrB,OAAO,CAAC,MAAM,CAAC,WAAW;IA8C1B,yDAAyD;IACzD,OAAO,CAAC,MAAM,CAAC,aAAa;IAoD5B,OAAO,CAAC,MAAM,CAAC,UAAU;IAQzB,iIAAiI;IACjI,OAAO,CAAC,MAAM,CAAC,SAAS;IA+BxB,gFAAgF;IAChF,OAAO,CAAC,MAAM,CAAC,YAAY;IAuB3B,OAAO,CAAC,MAAM,CAAC,SAAS;IAqCxB,OAAO,CAAC,MAAM,CAAC,WAAW;IAuB1B,sHAAsH;IACtH,OAAO,CAAC,MAAM,CAAC,UAAU;IAkCzB,OAAO,CAAC,MAAM,CAAC,QAAQ;IA2BvB,wJAAwJ;IACxJ,OAAO,CAAC,MAAM,CAAC,UAAU;CAqD1B;AAyDD,mEAAmE;AACnE,qBAAa,mBAAmB;IAC9B,MAAM,CAAC,QAAQ,CAAC,KAAK,ipDAAS;WAEjB,GAAG,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CA4K1E"}
|
|
@@ -531,7 +531,8 @@ class ConstClassesCommand {
|
|
|
531
531
|
}
|
|
532
532
|
let typescript;
|
|
533
533
|
try {
|
|
534
|
-
|
|
534
|
+
const result2 = await import('typescript');
|
|
535
|
+
typescript = result2.default;
|
|
535
536
|
}
|
|
536
537
|
catch {
|
|
537
538
|
console.error('devz codemod: the "typescript" package is required to read your sources');
|