diff --git a/.vscode/settings.json b/.vscode/settings.json index d3d7b2b1..c08b234d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,6 @@ "editor.wordWrapColumn": 100, "[markdown]": { "editor.wordWrap": "off" - } + }, + "typescript.experimental.useTsgo": true } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ea1cfc39..19ce6450 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,6 +40,8 @@ Each codemod resides in its own directory under `recipes/` and should include: **`src/workflow.ts` example:** ```ts import type { SgRoot, Edit } from "@codemod.com/jssg-types/main"; +import type JS from "@codemod.com/jssg-types/langs/javascript"; + /** * Transform function that converts deprecated api.fn calls * to the new api.fn syntax. @@ -49,12 +51,15 @@ import type { SgRoot, Edit } from "@codemod.com/jssg-types/main"; * 2. api.fn(, { recursive: true }) * ... */ -export default function transform(root: SgRoot): string | null { +export default function transform(root: SgRoot): string | null { const rootNode = root.root(); - let hasChanges = false; const edits: Edit[] = []; + // do some transformation - if (!hasChanges) return null; + edits.push(...); + + if (edits.length === 0) return null; + return rootNode.commitEdits(edits); } ``` diff --git a/package-lock.json b/package-lock.json index 8f01d490..df0d2833 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,9 @@ "utils" ], "devDependencies": { - "@biomejs/biome": "2.2.4", - "@types/node": "^24.5.0", - "typescript": "^5.9.2" + "@biomejs/biome": "2.1.4", + "@types/node": "^24.2.1", + "@typescript/native-preview": "^7.0.0-dev.20250916.1" } }, "node_modules/@ampproject/remapping": { @@ -878,9 +878,9 @@ } }, "node_modules/@biomejs/biome": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.2.4.tgz", - "integrity": "sha512-TBHU5bUy/Ok6m8c0y3pZiuO/BZoY/OcGxoLlrfQof5s8ISVwbVBdFINPQZyFfKwil8XibYWb7JMwnT8wT4WVPg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.1.4.tgz", + "integrity": "sha512-QWlrqyxsU0FCebuMnkvBIkxvPqH89afiJzjMl+z67ybutse590jgeaFdDurE9XYtzpjRGTI1tlUZPGWmbKsElA==", "dev": true, "license": "MIT OR Apache-2.0", "bin": { @@ -894,20 +894,20 @@ "url": "https://opencollective.com/biome" }, "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "2.2.4", - "@biomejs/cli-darwin-x64": "2.2.4", - "@biomejs/cli-linux-arm64": "2.2.4", - "@biomejs/cli-linux-arm64-musl": "2.2.4", - "@biomejs/cli-linux-x64": "2.2.4", - "@biomejs/cli-linux-x64-musl": "2.2.4", - "@biomejs/cli-win32-arm64": "2.2.4", - "@biomejs/cli-win32-x64": "2.2.4" + "@biomejs/cli-darwin-arm64": "2.1.4", + "@biomejs/cli-darwin-x64": "2.1.4", + "@biomejs/cli-linux-arm64": "2.1.4", + "@biomejs/cli-linux-arm64-musl": "2.1.4", + "@biomejs/cli-linux-x64": "2.1.4", + "@biomejs/cli-linux-x64-musl": "2.1.4", + "@biomejs/cli-win32-arm64": "2.1.4", + "@biomejs/cli-win32-x64": "2.1.4" } }, "node_modules/@biomejs/cli-darwin-arm64": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.2.4.tgz", - "integrity": "sha512-RJe2uiyaloN4hne4d2+qVj3d3gFJFbmrr5PYtkkjei1O9c+BjGXgpUPVbi8Pl8syumhzJjFsSIYkcLt2VlVLMA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.1.4.tgz", + "integrity": "sha512-sCrNENE74I9MV090Wq/9Dg7EhPudx3+5OiSoQOkIe3DLPzFARuL1dOwCWhKCpA3I5RHmbrsbNSRfZwCabwd8Qg==", "cpu": [ "arm64" ], @@ -922,9 +922,9 @@ } }, "node_modules/@biomejs/cli-darwin-x64": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.2.4.tgz", - "integrity": "sha512-cFsdB4ePanVWfTnPVaUX+yr8qV8ifxjBKMkZwN7gKb20qXPxd/PmwqUH8mY5wnM9+U0QwM76CxFyBRJhC9tQwg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.1.4.tgz", + "integrity": "sha512-gOEICJbTCy6iruBywBDcG4X5rHMbqCPs3clh3UQ+hRKlgvJTk4NHWQAyHOXvaLe+AxD1/TNX1jbZeffBJzcrOw==", "cpu": [ "x64" ], @@ -939,9 +939,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.2.4.tgz", - "integrity": "sha512-M/Iz48p4NAzMXOuH+tsn5BvG/Jb07KOMTdSVwJpicmhN309BeEyRyQX+n1XDF0JVSlu28+hiTQ2L4rZPvu7nMw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.1.4.tgz", + "integrity": "sha512-juhEkdkKR4nbUi5k/KRp1ocGPNWLgFRD4NrHZSveYrD6i98pyvuzmS9yFYgOZa5JhaVqo0HPnci0+YuzSwT2fw==", "cpu": [ "arm64" ], @@ -956,9 +956,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.4.tgz", - "integrity": "sha512-7TNPkMQEWfjvJDaZRSkDCPT/2r5ESFPKx+TEev+I2BXDGIjfCZk2+b88FOhnJNHtksbOZv8ZWnxrA5gyTYhSsQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.1.4.tgz", + "integrity": "sha512-nYr7H0CyAJPaLupFE2cH16KZmRC5Z9PEftiA2vWxk+CsFkPZQ6dBRdcC6RuS+zJlPc/JOd8xw3uCCt9Pv41WvQ==", "cpu": [ "arm64" ], @@ -973,9 +973,9 @@ } }, "node_modules/@biomejs/cli-linux-x64": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.2.4.tgz", - "integrity": "sha512-orr3nnf2Dpb2ssl6aihQtvcKtLySLta4E2UcXdp7+RTa7mfJjBgIsbS0B9GC8gVu0hjOu021aU8b3/I1tn+pVQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.1.4.tgz", + "integrity": "sha512-Eoy9ycbhpJVYuR+LskV9s3uyaIkp89+qqgqhGQsWnp/I02Uqg2fXFblHJOpGZR8AxdB9ADy87oFVxn9MpFKUrw==", "cpu": [ "x64" ], @@ -990,9 +990,9 @@ } }, "node_modules/@biomejs/cli-linux-x64-musl": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.4.tgz", - "integrity": "sha512-m41nFDS0ksXK2gwXL6W6yZTYPMH0LughqbsxInSKetoH6morVj43szqKx79Iudkp8WRT5SxSh7qVb8KCUiewGg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.1.4.tgz", + "integrity": "sha512-lvwvb2SQQHctHUKvBKptR6PLFCM7JfRjpCCrDaTmvB7EeZ5/dQJPhTYBf36BE/B4CRWR2ZiBLRYhK7hhXBCZAg==", "cpu": [ "x64" ], @@ -1007,9 +1007,9 @@ } }, "node_modules/@biomejs/cli-win32-arm64": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.2.4.tgz", - "integrity": "sha512-NXnfTeKHDFUWfxAefa57DiGmu9VyKi0cDqFpdI+1hJWQjGJhJutHPX0b5m+eXvTKOaf+brU+P0JrQAZMb5yYaQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.1.4.tgz", + "integrity": "sha512-3WRYte7orvyi6TRfIZkDN9Jzoogbv+gSvR+b9VOXUg1We1XrjBg6WljADeVEaKTvOcpVdH0a90TwyOQ6ue4fGw==", "cpu": [ "arm64" ], @@ -1024,9 +1024,9 @@ } }, "node_modules/@biomejs/cli-win32-x64": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.2.4.tgz", - "integrity": "sha512-3Y4V4zVRarVh/B/eSHczR4LYoSVyv3Dfuvm3cWs5w/HScccS0+Wt/lHOcDTRYeHjQmMYVC3rIRWqyN2EI52+zg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.1.4.tgz", + "integrity": "sha512-tBc+W7anBPSFXGAoQW+f/+svkpt8/uXfRwDzN1DvnatkRMt16KIYpEi/iw8u9GahJlFv98kgHcIrSsZHZTR0sw==", "cpu": [ "x64" ], @@ -1663,9 +1663,9 @@ } }, "node_modules/@types/node": { - "version": "24.5.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.0.tgz", - "integrity": "sha512-y1dMvuvJspJiPSDZUQ+WMBvF7dpnEqN4x9DDC9ie5Fs/HUZJA3wFp7EhHoVaKX/iI0cRoECV8X2jL8zi0xrHCg==", + "version": "24.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.1.tgz", + "integrity": "sha512-/SQdmUP2xa+1rdx7VwB9yPq8PaKej8TD5cQ+XfKDPWWC+VDJU4rvVVagXqKUzhKjtFoNA8rXDJAkCxQPAe00+Q==", "license": "MIT", "dependencies": { "undici-types": "~7.12.0" @@ -1681,6 +1681,123 @@ "form-data": "^4.0.0" } }, + "node_modules/@typescript/native-preview": { + "version": "7.0.0-dev.20250916.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview/-/native-preview-7.0.0-dev.20250916.1.tgz", + "integrity": "sha512-i9FKJWV1SMpc9YtTYimB23ERduB/udyijD2XAeOjOCV+5gzBWPc2A6lQrfhRDGHDV2NEMKRr4bTSuQ8Ptnh2EQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsgo": "bin/tsgo.js" + }, + "optionalDependencies": { + "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20250916.1", + "@typescript/native-preview-darwin-x64": "7.0.0-dev.20250916.1", + "@typescript/native-preview-linux-arm": "7.0.0-dev.20250916.1", + "@typescript/native-preview-linux-arm64": "7.0.0-dev.20250916.1", + "@typescript/native-preview-linux-x64": "7.0.0-dev.20250916.1", + "@typescript/native-preview-win32-arm64": "7.0.0-dev.20250916.1", + "@typescript/native-preview-win32-x64": "7.0.0-dev.20250916.1" + } + }, + "node_modules/@typescript/native-preview-darwin-arm64": { + "version": "7.0.0-dev.20250916.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-arm64/-/native-preview-darwin-arm64-7.0.0-dev.20250916.1.tgz", + "integrity": "sha512-h0OMrJItE0KH0jXsrFcLSFpbLGUxkQ09oXrcvX9h93G2T1zxKVCl1i56ukDq4NT68qOBHwMIVqflttbTWRxN2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@typescript/native-preview-darwin-x64": { + "version": "7.0.0-dev.20250916.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-x64/-/native-preview-darwin-x64-7.0.0-dev.20250916.1.tgz", + "integrity": "sha512-6Bxu3jvisyW/TiWKk2p3lbqVI/WzMcK5wIjzzfInketZRtS9ENQpkZ9Yw5Yx4JuOw7m/j69YCM9YPEQzqVh5Yw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@typescript/native-preview-linux-arm": { + "version": "7.0.0-dev.20250916.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm/-/native-preview-linux-arm-7.0.0-dev.20250916.1.tgz", + "integrity": "sha512-f2kxgRQe2FIAUQVmJT7/r4RJfxyj3mjfV747OkWqH/sIJNOj4JnVl4RIsY+JL8r99zlJidm/FuiBUeDcyp7qyA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@typescript/native-preview-linux-arm64": { + "version": "7.0.0-dev.20250916.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm64/-/native-preview-linux-arm64-7.0.0-dev.20250916.1.tgz", + "integrity": "sha512-tEON0Hn5CTyB3GbMLxzlzl3gyIHO4Qj4gyfj327q27lCyZxQrANZRJidhUP57RBxejAQdTj/bLQMm30/py7SDw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@typescript/native-preview-linux-x64": { + "version": "7.0.0-dev.20250916.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-x64/-/native-preview-linux-x64-7.0.0-dev.20250916.1.tgz", + "integrity": "sha512-xIN1NNZhnp8CywGbjv2sMy/Y9yqiUrLPhaa1oK3aL8GFFDc56i2a9kHspy6sL60VZmqUizDMS4qsofavL63nbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@typescript/native-preview-win32-arm64": { + "version": "7.0.0-dev.20250916.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-arm64/-/native-preview-win32-arm64-7.0.0-dev.20250916.1.tgz", + "integrity": "sha512-lt4OgcGId11iDXghb3+sAP0U6BWtaJeKyAIs7d0BMBzF/wdR5isjnSDD1zLR/tqLom7WoupIkKMAoaVNO5GTmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@typescript/native-preview-win32-x64": { + "version": "7.0.0-dev.20250916.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-x64/-/native-preview-win32-x64-7.0.0-dev.20250916.1.tgz", + "integrity": "sha512-xL2kkfgxljnNIQHuL5ENNF2K8weUJi5gY/BEdCwe5kpfeVljc+rq4V39X1LjEnj4NAU39h6O9zFImRdcghFnkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -3869,20 +3986,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/undici-types": { "version": "7.12.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", diff --git a/package.json b/package.json index 92045d5e..6fe00eb3 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "pre-commit": "node --run lint:fix; node --run type-check; node --run test", "test": "npm run test --workspaces --if-present", "test-legacy": "npm run test-legacy --workspaces --if-present", - "type-check": "tsc" + "type-check": "tsgo --noEmit" }, "repository": { "type": "git", @@ -27,9 +27,9 @@ }, "homepage": "https://nodejs.org/learn/userland-migrations", "devDependencies": { - "@biomejs/biome": "2.2.4", - "@types/node": "^24.5.0", - "typescript": "^5.9.2" + "@biomejs/biome": "2.1.4", + "@types/node": "^24.2.1", + "@typescript/native-preview": "^7.0.0-dev.20250916.1" }, "workspaces": [ "./recipes/*", diff --git a/recipes/create-require-from-path/src/workflow.ts b/recipes/create-require-from-path/src/workflow.ts index e8672590..30401693 100644 --- a/recipes/create-require-from-path/src/workflow.ts +++ b/recipes/create-require-from-path/src/workflow.ts @@ -1,6 +1,7 @@ import { getNodeImportStatements } from "@nodejs/codemod-utils/ast-grep/import-statement"; import { getNodeRequireCalls } from "@nodejs/codemod-utils/ast-grep/require-call"; import type { SgRoot, Edit } from "@codemod.com/jssg-types/main"; +import type JS from "@codemod.com/jssg-types/langs/javascript"; /** * Transform function that updates code to replace deprecated `createRequireFromPath` usage @@ -20,7 +21,7 @@ import type { SgRoot, Edit } from "@codemod.com/jssg-types/main"; * * 3. Preserves original variable names and declaration types. */ -export default function transform(root: SgRoot): string | null { +export default function transform(root: SgRoot): string | null { const rootNode = root.root(); const edits: Edit[] = []; let hasChanges = false; diff --git a/recipes/fs-access-mode-constants/src/workflow.ts b/recipes/fs-access-mode-constants/src/workflow.ts index 79c77dee..8e320ca7 100644 --- a/recipes/fs-access-mode-constants/src/workflow.ts +++ b/recipes/fs-access-mode-constants/src/workflow.ts @@ -8,7 +8,6 @@ export default function tranform(root: SgRoot): string | null { const edits: Edit[] = []; const patterns = ['F_OK', 'R_OK', 'W_OK', 'X_OK']; - // @ts-expect-error - ast-grep types are not fully compatible with JSSG types const requireStatements = getNodeRequireCalls(root, 'fs'); for (const statement of requireStatements) { @@ -30,7 +29,6 @@ export default function tranform(root: SgRoot): string | null { } } - // @ts-expect-error - ast-grep types are not fully compatible with JSSG types const importStatements = getNodeImportStatements(root, 'fs'); let promisesImportName = ''; diff --git a/recipes/http-classes-with-new/src/workflow.ts b/recipes/http-classes-with-new/src/workflow.ts index 67af8c76..5976267e 100644 --- a/recipes/http-classes-with-new/src/workflow.ts +++ b/recipes/http-classes-with-new/src/workflow.ts @@ -2,6 +2,7 @@ import { getNodeImportStatements } from '@nodejs/codemod-utils/ast-grep/import-s import { getNodeRequireCalls } from '@nodejs/codemod-utils/ast-grep/require-call'; import { resolveBindingPath } from '@nodejs/codemod-utils/ast-grep/resolve-binding-path'; import type { SgRoot, Edit, SgNode } from '@codemod.com/jssg-types/main'; +import type JS from "@codemod.com/jssg-types/langs/javascript"; /** * Classes of the http module @@ -26,7 +27,7 @@ const CLASS_NAMES = [ * 5. `http.Server()` → `new http.Server()` * 6. `http.ServerResponse() → `new http.ServerResponse()` */ -export default function transform(root: SgRoot): string | null { +export default function transform(root: SgRoot): string | null { const rootNode = root.root(); const edits: Edit[] = []; @@ -59,7 +60,7 @@ export default function transform(root: SgRoot): string | null { * @param statements - The import & require statements to search for the http classes * @returns The base path of the http classes */ -function* getHttpClassBasePaths(statements: SgNode[]) { +function* getHttpClassBasePaths(statements: SgNode[]) { for (const cls of CLASS_NAMES) { for (const stmt of statements) { const resolvedPath = resolveBindingPath(stmt, `$.${cls}`); diff --git a/recipes/import-assertions-to-attributes/src/workflow.ts b/recipes/import-assertions-to-attributes/src/workflow.ts index eb9a5f7d..03a2514e 100644 --- a/recipes/import-assertions-to-attributes/src/workflow.ts +++ b/recipes/import-assertions-to-attributes/src/workflow.ts @@ -1,4 +1,5 @@ import type { SgRoot, Edit } from '@codemod.com/jssg-types/main'; +import type JS from "@codemod.com/jssg-types/langs/javascript"; /** * Transform function that converts import assertions to import attributes @@ -11,7 +12,7 @@ import type { SgRoot, Edit } from '@codemod.com/jssg-types/main'; * 1. import { something } from './module.json' with { type: 'json' }; * 2. import('./module.json', { with: { type: 'json' } }) */ -export default async function transform(root: SgRoot): Promise { +export default async function transform(root: SgRoot): Promise { const rootNode = root.root(); const edits: Edit[] = []; diff --git a/recipes/import-assertions-to-attributes/tsconfig.json b/recipes/import-assertions-to-attributes/tsconfig.json deleted file mode 100644 index dbad0f78..00000000 --- a/recipes/import-assertions-to-attributes/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "allowImportingTsExtensions": true, - "allowJs": true, - "alwaysStrict": true, - "baseUrl": "./", - "declaration": true, - "declarationMap": true, - "emitDeclarationOnly": true, - "lib": ["ESNext", "DOM"], - "module": "NodeNext", - "moduleResolution": "NodeNext", - "noImplicitThis": true, - "removeComments": true, - "strict": true, - "stripInternal": true, - "target": "esnext" - }, - "include": ["./"], - "exclude": [ - "node_modules", - "./node_modules", - "tests/expected/**", - "tests/input/**" - ] -} diff --git a/recipes/process-main-module/src/workflow.ts b/recipes/process-main-module/src/workflow.ts index b53a14b7..2b0c86ee 100644 --- a/recipes/process-main-module/src/workflow.ts +++ b/recipes/process-main-module/src/workflow.ts @@ -1,7 +1,8 @@ -import type { Edit, SgRoot, Range } from "@codemod.com/jssg-types/main"; import { getNodeRequireCalls } from "@nodejs/codemod-utils/ast-grep/require-call"; import { removeLines } from "@nodejs/codemod-utils/ast-grep/remove-lines"; import { removeBinding } from "@nodejs/codemod-utils/ast-grep/remove-binding"; +import type { Edit, SgRoot, Range } from "@codemod.com/jssg-types/main"; +import type Js from "@codemod.com/jssg-types/langs/javascript"; /** * Transforms `process.mainModule` usage to `require.main`. Handles direct global access @@ -19,7 +20,7 @@ import { removeBinding } from "@nodejs/codemod-utils/ast-grep/remove-binding"; * - Change 'mainModule' → 'require.main' * - Change 'process.mainModule' → 'require.main' */ -export default function transform(root: SgRoot): string | null { +export default function transform(root: SgRoot): string | null { const rootNode = root.root(); const edits: Edit[] = []; const linesToRemove: Range[] = []; diff --git a/recipes/rmdir/src/workflow.ts b/recipes/rmdir/src/workflow.ts index d989c044..6d583d2d 100644 --- a/recipes/rmdir/src/workflow.ts +++ b/recipes/rmdir/src/workflow.ts @@ -2,6 +2,7 @@ import { getNodeImportStatements } from "@nodejs/codemod-utils/ast-grep/import-s import { getNodeRequireCalls } from "@nodejs/codemod-utils/ast-grep/require-call"; import { resolveBindingPath } from "@nodejs/codemod-utils/ast-grep/resolve-binding-path"; import type { SgRoot, Edit } from "@codemod.com/jssg-types/main"; +import type Js from "@codemod.com/jssg-types/langs/javascript"; /** * Transform function that converts deprecated fs.rmdir calls @@ -13,7 +14,7 @@ import type { SgRoot, Edit } from "@codemod.com/jssg-types/main"; * 3. fs.rmdirSync(path, { recursive: true }) -> fs.rmSync(path, { recursive: true, force: true }) * 4. fs.promises.rmdir(path, { recursive: true }) -> fs.promises.rm(path, { recursive: true, force: true }) */ -export default function transform(root: SgRoot): string | null { +export default function transform(root: SgRoot): string | null { const rootNode = root.root(); let hasChanges = false; const edits: Edit[] = []; diff --git a/recipes/rmdir/tsconfig.json b/recipes/rmdir/tsconfig.json deleted file mode 100644 index 92c12497..00000000 --- a/recipes/rmdir/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "allowImportingTsExtensions": true, - "allowJs": true, - "alwaysStrict": true, - "baseUrl": "./", - "declaration": true, - "declarationMap": true, - "emitDeclarationOnly": true, - "lib": ["ESNext", "DOM"], - "module": "NodeNext", - "moduleResolution": "NodeNext", - "noImplicitThis": true, - "removeComments": true, - "strict": true, - "stripInternal": true, - "target": "esnext" - }, - "include": ["./"], - "exclude": [ - "tests/**" - ] -} diff --git a/recipes/tmpdir-to-tmpdir/src/workflow.ts b/recipes/tmpdir-to-tmpdir/src/workflow.ts index 7fe80386..f366af7e 100644 --- a/recipes/tmpdir-to-tmpdir/src/workflow.ts +++ b/recipes/tmpdir-to-tmpdir/src/workflow.ts @@ -1,6 +1,7 @@ import { getNodeImportStatements } from "@nodejs/codemod-utils/ast-grep/import-statement"; import { getNodeRequireCalls } from "@nodejs/codemod-utils/ast-grep/require-call"; import type { SgRoot, Edit } from "@codemod.com/jssg-types/main"; +import type Js from "@codemod.com/jssg-types/langs/javascript"; /** * Transform function that updates code to replace deprecated `tmpDir` usage @@ -20,7 +21,7 @@ import type { SgRoot, Edit } from "@codemod.com/jssg-types/main"; * * 3. Preserves original variable names and declaration types. */ -export default function transform(root: SgRoot): string | null { +export default function transform(root: SgRoot): string | null { const rootNode = root.root(); const edits: Edit[] = []; let hasChanges = false; diff --git a/recipes/types-is-native-error/src/workflow.ts b/recipes/types-is-native-error/src/workflow.ts index e3437a8e..a6f1bd16 100644 --- a/recipes/types-is-native-error/src/workflow.ts +++ b/recipes/types-is-native-error/src/workflow.ts @@ -4,13 +4,14 @@ import { getNodeImportStatements } from "@nodejs/codemod-utils/ast-grep/import-s import { resolveBindingPath } from "@nodejs/codemod-utils/ast-grep/resolve-binding-path"; import { removeLines } from "@nodejs/codemod-utils/ast-grep/remove-lines"; import { removeBinding } from "@nodejs/codemod-utils/ast-grep/remove-binding"; +import type JS from "@codemod.com/jssg-types/langs/javascript"; type Binding = { path: string; lastPropertyAccess?: string; propertyAccess?: string; depth: number; - node: SgNode; + node: SgNode; }; /** @@ -72,7 +73,7 @@ function createPropBinding( * isNativeError have been replaced * */ -export default function transform(root: SgRoot): string | null { +export default function transform(root: SgRoot): string | null { const rootNode = root.root(); const bindings: Binding[] = []; const edits: Edit[] = []; diff --git a/recipes/util-log-to-console-log/src/workflow.ts b/recipes/util-log-to-console-log/src/workflow.ts index 2221f4f4..1c8dc719 100644 --- a/recipes/util-log-to-console-log/src/workflow.ts +++ b/recipes/util-log-to-console-log/src/workflow.ts @@ -1,21 +1,20 @@ +import { getNodeRequireCalls } from "@nodejs/codemod-utils/ast-grep/require-call"; +import { getNodeImportStatements } from "@nodejs/codemod-utils/ast-grep/import-statement"; +import { resolveBindingPath } from "@nodejs/codemod-utils/ast-grep/resolve-binding-path"; +import { removeBinding } from "@nodejs/codemod-utils/ast-grep/remove-binding"; +import { removeLines } from "@nodejs/codemod-utils/ast-grep/remove-lines"; import type { Edit, - Kinds, Range, Rule, SgNode, SgRoot, - TypesMap, } from "@codemod.com/jssg-types/main"; -import { getNodeRequireCalls } from "@nodejs/codemod-utils/ast-grep/require-call"; -import { getNodeImportStatements } from "@nodejs/codemod-utils/ast-grep/import-statement"; -import { resolveBindingPath } from "@nodejs/codemod-utils/ast-grep/resolve-binding-path"; -import { removeBinding } from "@nodejs/codemod-utils/ast-grep/remove-binding"; -import { removeLines } from "@nodejs/codemod-utils/ast-grep/remove-lines"; +import type Js from "@codemod.com/jssg-types/langs/javascript"; type BindingToReplace = { - rule: Rule; - node: SgNode>; + rule: Rule; + node: SgNode; binding: string; }; @@ -31,7 +30,7 @@ type BindingToReplace = { * * Apply all changes, removing or updating the import line as needed. */ -export default function transform(root: SgRoot): string | null { +export default function transform(root: SgRoot): string | null { const rootNode = root.root(); const edits: Edit[] = []; const linesToRemove: Range[] = []; diff --git a/recipes/util-print-to-console-log/src/workflow.ts b/recipes/util-print-to-console-log/src/workflow.ts index b0ccd038..8d7ca4fc 100644 --- a/recipes/util-print-to-console-log/src/workflow.ts +++ b/recipes/util-print-to-console-log/src/workflow.ts @@ -1,21 +1,20 @@ +import { getNodeRequireCalls } from "@nodejs/codemod-utils/ast-grep/require-call"; +import { getNodeImportStatements } from "@nodejs/codemod-utils/ast-grep/import-statement"; +import { resolveBindingPath } from "@nodejs/codemod-utils/ast-grep/resolve-binding-path"; +import { removeBinding } from "@nodejs/codemod-utils/ast-grep/remove-binding"; +import { removeLines } from "@nodejs/codemod-utils/ast-grep/remove-lines"; import type { Edit, - Kinds, Range, Rule, SgNode, SgRoot, - TypesMap, } from "@codemod.com/jssg-types/main"; -import { getNodeRequireCalls } from "@nodejs/codemod-utils/ast-grep/require-call"; -import { getNodeImportStatements } from "@nodejs/codemod-utils/ast-grep/import-statement"; -import { resolveBindingPath } from "@nodejs/codemod-utils/ast-grep/resolve-binding-path"; -import { removeBinding } from "@nodejs/codemod-utils/ast-grep/remove-binding"; -import { removeLines } from "@nodejs/codemod-utils/ast-grep/remove-lines"; +import type Js from "@codemod.com/jssg-types/langs/javascript"; type BindingToReplace = { - rule: Rule; - node: SgNode>; + rule: Rule; + node: SgNode; binding: string; replaceFn: (arg: string) => string; }; @@ -54,7 +53,7 @@ const updates = [ * * Apply all changes, removing or updating the import line as needed. */ -export default function transform(root: SgRoot): string | null { +export default function transform(root: SgRoot): string | null { const rootNode = root.root(); const edits: Edit[] = []; const linesToRemove: Range[] = []; diff --git a/tsconfig.json b/tsconfig.json index 583490d9..35384337 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "baseUrl": "./", "rootDir": "./", "target": "ESNext", @@ -44,27 +43,9 @@ "./utils" ], "exclude": [ - "node_modules", - "**/build/**", - "**/fixtures/**", - "**/expected/**", "**/tests/**", - "**/*.fixture.mjs", - "**/*.fixture.mts", - "**/*.fixture.js", - "**/*.fixture.ts", - "**/*.mock.mjs", - "**/*.e2e.mjs", - "**/*.e2e.mts", - "**/*.e2e.js", - "**/*.e2e.ts", - "**/*.spec.mjs", - "**/*.spec.mts", - "**/*.spec.js", - "**/*.spec.ts", - "**/*.test.mjs", - "**/*.test.mts", - "**/*.test.js", + // For correct-ts-specifiers "**/*.test.ts", + "**/fixtures/**" ], } diff --git a/utils/src/ast-grep/import-statement.ts b/utils/src/ast-grep/import-statement.ts index 364a11b9..552abf56 100644 --- a/utils/src/ast-grep/import-statement.ts +++ b/utils/src/ast-grep/import-statement.ts @@ -1,18 +1,19 @@ -import type { SgRoot, SgNode } from '@codemod.com/jssg-types/main'; +import type { SgNode, SgRoot } from '@codemod.com/jssg-types/main'; +import type Js from "@codemod.com/jssg-types/langs/javascript"; -export const getNodeImportStatements = (rootNode: SgRoot, nodeModuleName: string): SgNode[] => +export const getNodeImportStatements = (rootNode: SgRoot, nodeModuleName: string): SgNode[] => rootNode - .root() - .findAll({ - rule: { - kind: "import_statement", - has: { - field: "source", - kind: "string", - regex: `^['"](node:)?${nodeModuleName}['"]$` - } + .root() + .findAll({ + rule: { + kind: "import_statement", + has: { + field: "source", + kind: "string", + regex: `^['"](node:)?${nodeModuleName}['"]$` } - }); + } + }); /** * We just catch `variable_declarator` nodes that use `import` to import a module @@ -22,8 +23,8 @@ export const getNodeImportStatements = (rootNode: SgRoot, nodeModuleName: string * We also don't catch pending promises, like `const pending = import("node:module");` * because it's will became to complex to handle in codemod context. (storing var name, checking is method is used, etc.) */ -export const getNodeImportCalls = (rootNode: SgRoot, nodeModuleName: string): SgNode[] => - rootNode +export const getNodeImportCalls = (node: SgRoot, nodeModuleName: string): SgNode[] => + node .root() .findAll({ rule: { diff --git a/utils/src/ast-grep/remove-binding.ts b/utils/src/ast-grep/remove-binding.ts index 1b612e9c..7e479a1f 100644 --- a/utils/src/ast-grep/remove-binding.ts +++ b/utils/src/ast-grep/remove-binding.ts @@ -1,4 +1,5 @@ -import type { SgNode, Edit, Range, Kinds, TypesMap } from "@codemod.com/jssg-types/main"; +import type { SgNode, Edit, Range } from "@codemod.com/jssg-types/main"; +import type Js from "@codemod.com/jssg-types/langs/javascript"; const requireKinds = ["lexical_declaration", "variable_declarator"]; const importKinds = ["import_statement", "import_clause"]; @@ -41,7 +42,7 @@ type RemoveBindingReturnType = { * ``` */ export function removeBinding( - node: SgNode>, + node: SgNode, binding: string, ): RemoveBindingReturnType | undefined { const nodeKind = node.kind().toString(); @@ -81,7 +82,7 @@ export function removeBinding( } function handleNamedImportBindings( - node: SgNode>, + node: SgNode, binding: string, ): RemoveBindingReturnType | undefined { const namespaceImport = node.find({ @@ -171,7 +172,7 @@ function handleNamedImportBindings( } function handleNamedRequireBindings( - node: SgNode>, + node: SgNode, binding: string, ): RemoveBindingReturnType | undefined { const objectPattern = node.find({ diff --git a/utils/src/ast-grep/require-call.ts b/utils/src/ast-grep/require-call.ts index 9a8a273f..609de9f6 100644 --- a/utils/src/ast-grep/require-call.ts +++ b/utils/src/ast-grep/require-call.ts @@ -1,4 +1,5 @@ -import type { SgRoot, SgNode } from '@codemod.com/jssg-types/main'; +import type { SgNode, SgRoot } from '@codemod.com/jssg-types/main'; +import type Js from "@codemod.com/jssg-types/langs/javascript"; /** * We just catch `variable_declarator` nodes that use `require` to import a module @@ -6,82 +7,82 @@ import type { SgRoot, SgNode } from '@codemod.com/jssg-types/main'; * catch those. * We also catch `require` calls that are not assigned to a variable, like `const fs = require('fs');` */ -export const getNodeRequireCalls = (rootNode: SgRoot, nodeModuleName: string): SgNode[] => +export const getNodeRequireCalls = (rootNode: SgRoot, nodeModuleName: string): SgNode[] => rootNode - .root() - .findAll({ - rule: { - kind: "variable_declarator", - all: [ - { - has: { - field: "name", - any: [ - { kind: "object_pattern" }, - { kind: "identifier" } - ] - } - }, - { - has: { - field: "value", - any: [ - { - kind: "call_expression", - all: [ - { + .root() + .findAll({ + rule: { + kind: "variable_declarator", + all: [ + { + has: { + field: "name", + any: [ + { kind: "object_pattern" }, + { kind: "identifier" } + ] + } + }, + { + has: { + field: "value", + any: [ + { + kind: "call_expression", + all: [ + { + has: { + field: "function", + kind: "identifier", + regex: "^require$" + } + }, + { + has: { + field: "arguments", + kind: "arguments", has: { - field: "function", - kind: "identifier", - regex: "^require$" + kind: "string", + regex: `^['"](node:)?${nodeModuleName}['"]$` } - }, - { - has: { - field: "arguments", - kind: "arguments", + } + } + ] + }, + { + kind: "member_expression", + all: [ + { + has: { + field: "object", + kind: "call_expression", + all: [ + { has: { - kind: "string", - regex: `^['"](node:)?${nodeModuleName}['"]$` + field: "function", + kind: "identifier", + regex: "^require$" } - } - } - ] - }, - { - kind: "member_expression", - all: [ - { - has: { - field: "object", - kind: "call_expression", - all: [ - { - has: { - field: "function", - kind: "identifier", - regex: "^require$" - } - }, - { + }, + { + has: { + field: "arguments", + kind: "arguments", has: { - field: "arguments", - kind: "arguments", - has: { - kind: "string", - regex: `^['"](node:)?${nodeModuleName}['"]$` - } + kind: "string", + regex: `^['"](node:)?${nodeModuleName}['"]$` } } - ] } + ] } - ] - } - ] - } + } + ] + } + ] } - ] - } - }); + } + ] + } + }); diff --git a/utils/src/ast-grep/resolve-binding-path.ts b/utils/src/ast-grep/resolve-binding-path.ts index 4974b4fd..55d9c4a4 100644 --- a/utils/src/ast-grep/resolve-binding-path.ts +++ b/utils/src/ast-grep/resolve-binding-path.ts @@ -1,4 +1,5 @@ -import type { SgNode, Kinds, TypesMap } from "@codemod.com/jssg-types/main"; +import type { SgNode } from "@codemod.com/jssg-types/main"; +import type Js from "@codemod.com/jssg-types/langs/javascript"; const requireKinds = ["lexical_declaration", "variable_declarator"]; const importKinds = ["import_statement", "import_clause"]; @@ -35,7 +36,7 @@ const supportedKinds = [...requireKinds, ...importKinds]; * // Returns: "utilTypes.isNativeError" * ``` */ -export function resolveBindingPath(node: SgNode>, path: string) { +export function resolveBindingPath(node: SgNode, path: string) { const activeNode = node; const rootKind = activeNode.kind().toString(); @@ -54,7 +55,7 @@ export function resolveBindingPath(node: SgNode>, path } } -function resolveBindingPathRequire(node: SgNode>, path: string) { +function resolveBindingPathRequire(node: SgNode, path: string) { const pathArr = path.split("."); let activeNode = node; const rootKind = node.kind(); @@ -125,7 +126,7 @@ function resolveBindingPathRequire(node: SgNode>, path } } -function resolveBindingPathImport(node: SgNode>, path: string) { +function resolveBindingPathImport(node: SgNode, path: string) { const pathArr = path.split("."); let activeNode = node; const rootKind = node.kind();