Skip to content

Commit

Permalink
feat(codemod): add suid-imports action
Browse files Browse the repository at this point in the history
  • Loading branch information
juanrgm committed Oct 28, 2022
1 parent cdce309 commit 76278e2
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/cyan-needles-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@suid/codemod": minor
---

Add `suid-imports` action
52 changes: 52 additions & 0 deletions packages/codemod/src/actions/suidImports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import transformSuidImports from "../transforms/transformSuidImports";
import applyTransforms from "../utils/applyTransforms.js";
import colorize from "../utils/colorize.js";
import fg from "fast-glob";
import { readFile, writeFile } from "fs/promises";
import micromatch from "micromatch";
import { normalize, relative } from "path";

export default async function suidImports(options: {
cwd: string;
filters: string[];
write: boolean;
}) {
const inputPath = normalize(options.cwd);
const inPattern = inputPath.replaceAll("\\", "/") + "/**/*";
const entries = fg.stream(inPattern, {
dot: true,
ignore: ["**/node_modules/**"],
});

let files = 0;
for await (const entry of entries) {
const path = normalize(entry.toString());
const validExt = /\.[jt]sx?$/.test(path);
if (!validExt) continue;

const rpath = relative(inputPath, path);
const matches =
!options.filters.length || !!micromatch([rpath], options.filters).length;

if (!matches) continue;

console.log(`+ ${colorize(rpath)}`);
files++;

const contents = (await readFile(path)).toString();
let imports = 0;
const newContents = applyTransforms(contents, [
async (source) => {
return await transformSuidImports(source, {
format: "named",
onImport(module) {
imports++;
console.log(`# ${colorize(module, "yellow")} `);
},
});
},
]);
if (options.write && imports) await writeFile(path, newContents);
}
if (!files) throw new Error(`No files found`);
}
12 changes: 12 additions & 0 deletions packages/codemod/src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import fixEsm from "./actions/fixEsm";
import mui2suid from "./actions/mui2suid";
import react2solid from "./actions/react2solid";
import suidImports from "./actions/suidImports";
import muiVersion from "./utils/muiVersion";
import { program } from "commander";
import { readFileSync } from "fs";
Expand Down Expand Up @@ -110,4 +111,15 @@ program
write: boolean;
}) => fixEsm(options)
);

program
.command("suid-imports")
.description("Transforms the SUID imports.")
.requiredOption("-f,--filters [glob patterns]", "Filters by glob patterns")
.option("--format [value]", "Output import format (values: named)", "named")
.option("--cwd [path]", "Current working directory path", process.cwd())
.option("-w,--write", "Overwrites the files with the transformed code")
.action((options: { cwd: string; filters: string[]; write: boolean }) =>
suidImports(options)
);
program.parse(process.argv);
63 changes: 63 additions & 0 deletions packages/codemod/src/transforms/transformSuidImports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import type { SourceFile } from "ts-morph";

function createImportsMap() {
const map: Record<string, Record<string, string>> = {};

return {
map,
add(module: string, named: string, alias: string) {
if (!map[module]) map[module] = {};
map[module][named] = alias;
},
};
}

export default async function transformSuidImports(
source: SourceFile,
options: {
format: "named";
onImport?: (moduleSpecifier: string) => false | void;
dryRun?: boolean;
}
) {
const allImports = source.getImportDeclarations();
const imports = createImportsMap();

for (const node of allImports) {
const alias = node.getDefaultImport()?.getText();
const moduleSpecifier = node.getModuleSpecifier()?.getLiteralText();
if (!alias || !moduleSpecifier) continue;
const levels = moduleSpecifier.split("/");
const [importScope, importModule, importPath] = levels;

if (importScope === "@suid" && levels.length === 3) {
if (importModule === "material") {
imports.add("@suid/material", importPath, alias);
if (options.onImport) {
if (options.onImport(moduleSpecifier) !== false) {
if (!node.getNamedImports().length) {
node.remove();
} else {
node.removeDefaultImport();
}
}
}
}
}
}

if (!options.dryRun)
for (const moduleSpecifier in imports.map) {
const importNode = source.addImportDeclaration({
moduleSpecifier,
});
const names = Object.keys(imports.map[moduleSpecifier]).sort();
for (const name of names) {
const alias = imports.map[moduleSpecifier][name];
importNode.addNamedImport({
name,
alias: name === alias ? undefined : alias,
});
}
}
}

0 comments on commit 76278e2

Please sign in to comment.