Skip to content

Commit

Permalink
feat(codemod-rewrite-module-specifiers-to-full-paths): implement proj…
Browse files Browse the repository at this point in the history
…ect (#2)
  • Loading branch information
pkerschbaum authored Sep 15, 2024
1 parent 6c11351 commit f3ea9fe
Show file tree
Hide file tree
Showing 42 changed files with 2,635 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"editor.rulers": [100],
"git.inputValidationLength": 100,
"git.inputValidationSubjectLength": null,
"typescript.tsdk": "./packages/commons-ecma/node_modules/typescript/lib",
"typescript.tsdk": "node_modules/typescript/lib",
"search.exclude": {
"**/dist": true
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const baseEslintConfig = require('@pkerschbaum/config-eslint/eslint-ecma.cjs');

module.exports = {
...baseEslintConfig,
parserOptions: {
...baseEslintConfig.parserOptions,
tsconfigRootDir: __dirname,
},
ignorePatterns: [
...(baseEslintConfig.ignorePatterns || []),
'**/codemod-inputs/**',
'**/codemod-outputs/**',
],
rules: {
...baseEslintConfig.rules,
'no-console': 'off',
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"name": "@pkerschbaum/codemod-rewrite-module-specifiers-to-full-paths",
"version": "0.0.1",
"homepage": "https://github.com/pkerschbaum/packages/tree/main/packages/codemod-rewrite-module-specifiers-to-full-paths",
"bugs": {
"url": "https://github.com/pkerschbaum/packages/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/pkerschbaum/packages",
"directory": "packages/codemod-rewrite-module-specifiers-to-full-paths"
},
"license": "MIT",
"author": "Patrick Kerschbaum <[email protected]>",
"exports": {
".": "./dist/index.js",
"./*": "./dist/*.js"
},
"typesVersions": {
"*": {
"*": [
"./dist/*"
]
}
},
"bin": "./dist/bin/codemod.js",
"files": [
"dist/**",
"!dist/**/*.d.ts.map"
],
"scripts": {
"build": "pnpm run internal:compile",
"dev": "pnpm run build --watch --preserveWatchOutput",
"internal:compile": "tsc -p ./tsconfig.build.json",
"lint": "pnpm run lint:file .",
"lint:file": "eslint --max-warnings 0",
"lint:fix": "pnpm run lint --fix",
"nuke": "pnpm run nuke:artifacts && del-cli node_modules",
"nuke:artifacts": "del-cli dist \"*.tsbuildinfo\"",
"test": "vitest run --config=\"./test/vitest.config.mts\""
},
"dependencies": {
"@commander-js/extra-typings": "^12.1.0",
"@pkerschbaum/commons-ecma": "workspace:*",
"@pkerschbaum/commons-node": "workspace:*",
"@pkerschbaum/runtime-extensions-node": "workspace:*",
"commander": "^12.1.0",
"jscodeshift": "^17.0.0",
"p-limit": "^6.1.0",
"tiny-invariant": "^1.3.3",
"typescript": "^5.5.4"
},
"devDependencies": {
"@types/jscodeshift": "^0.11.11",
"@types/node": "^20",
"@vitest/coverage-v8": "^2.0.5",
"ts-expose-internals": "^5.5.4",
"vite-tsconfig-paths": "^5.0.1",
"vitest": "^2.0.5"
},
"publishConfig": {
"access": "public"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import '@pkerschbaum/runtime-extensions-node';

import * as commander from '@commander-js/extra-typings';
import fs from 'node:fs';

import { loadTypeScriptProgram } from '#pkg/load-typescript-program';
import { rewriteModuleSpecifiersOfTypeScriptProject } from '#pkg/transform/index';

const commanderProgram = new commander.Command()
.addOption(
new commander.Option(
'--project <path-to-tsconfig-json>',
'Path to the TypeScript configuration file (e.g. "./tsconfig.json").',
).makeOptionMandatory(),
)
.addOption(
new commander.Option(
'--basepath <path>',
'A root directory to resolve relative path entries in the TypeScript config file to (e.g. option "outDir"). If omitted, the directory of the TypeScript configuration file passed with "--project" is used.',
),
);
commanderProgram.parse();
const options = commanderProgram.opts();

async function run() {
const { default: pLimit } = await import('p-limit');

const typeScriptProgram = await loadTypeScriptProgram(options);

const limit = pLimit(10);
const operations = typeScriptProgram.fileNames.map((absolutePathSourceFile) =>
limit(async () => {
const text = await fs.promises.readFile(absolutePathSourceFile, 'utf8');
const newText = rewriteModuleSpecifiersOfTypeScriptProject(
typeScriptProgram,
absolutePathSourceFile,
text,
);
await fs.promises.writeFile(absolutePathSourceFile, newText);
}),
);
await Promise.all(operations);
}

void run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import path from 'node:path';
import invariant from 'tiny-invariant';
import ts from 'typescript';

import { fsUtils } from '@pkerschbaum/commons-node/utils/fs';

export type TypeScriptProgram = {
compilerOptions: ts.CompilerOptions;
paths:
| {
absoluteBasePath: string;
patterns: ReadonlyArray<string | ts.Pattern>;
}
| undefined;
fileNames: string[];
};

export async function loadTypeScriptProgram(opts: {
project: string;
basepath?: string | undefined;
}): Promise<TypeScriptProgram> {
const projectAbsolutePath = path.resolve(opts.project);
invariant(
await fsUtils.existsPath(projectAbsolutePath),
`expected to find project, but did not! projectAbsolutePath=${projectAbsolutePath}`,
);

const basepath = opts.basepath ?? path.dirname(projectAbsolutePath);

const configFile = ts.readConfigFile(projectAbsolutePath, ts.sys.readFile.bind(ts.sys));
invariant(
configFile.config,
`expected to find config, but couldn't! projectAbsolutePath=${projectAbsolutePath}`,
);
const { options: compilerOptions, fileNames } = ts.parseJsonConfigFileContent(
configFile.config,
ts.sys,
basepath,
);

const paths = computePathsContext(compilerOptions);

return {
compilerOptions,
paths,
fileNames,
};
}

function computePathsContext(compilerOptions: ts.CompilerOptions) {
let pathsPatterns = compilerOptions.configFile?.configFileSpecs?.pathPatterns;
let absoluteBasePath = undefined;
if (!compilerOptions.paths) {
return undefined;
}

pathsPatterns = ts.tryParsePatterns(compilerOptions.paths);

invariant(compilerOptions.pathsBasePath);
absoluteBasePath = compilerOptions.baseUrl ?? compilerOptions.pathsBasePath;

return { absoluteBasePath, patterns: pathsPatterns };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '#pkg/transform/rewrite-module-specifiers-of-typescript-project';
Loading

0 comments on commit f3ea9fe

Please sign in to comment.