Skip to content

Instantly share code, notes, and snippets.

@itsrifat
Last active August 31, 2020 05:58
Show Gist options
  • Save itsrifat/5035d92e7403164be9b1ae5f1349d21b to your computer and use it in GitHub Desktop.
Save itsrifat/5035d92e7403164be9b1ae5f1349d21b to your computer and use it in GitHub Desktop.
jscodeshift script to replace an import with another. should be called like `find $1 -iname '*.tsx' -print | xargs ./node_modules/.bin/jscodeshift -t import-replacer.ts -fromModule react-apollo -fromImport graphql -toModule @apollo/client -toImport graphql`
/* tslint:disable */
// @ts-nocheck
/*
* This codemod can replace imports
* for exmalple it can change
* import {compose} from 'react-apollo'
* into
* import {flowRight as compose} from 'lodash'
*
Should be called like:
find $1 -iname '*.tsx' -print | xargs ./node_modules/.bin/jscodeshift -t import-replacer.ts -fromModule react-apollo -fromImport graphql -toModule @apollo/client -toImport graphql
* */
import { Transform } from "jscodeshift";
import { ImportDeclaration, JSCodeshift } from "jscodeshift";
import { ImportDeclarationBuilder } from "ast-types/gen/builders";
const codeContainsImport = (
j: JSCodeshift,
source: string,
options: { [key: string]: string }
) => {
return (
j(source)
.find<ImportDeclaration>(j.ImportDeclaration)
.filter(imp => {
const importLine = imp.node;
return importLine.source.value === options.fromModule;
})
.filter(imp => {
return imp.node.specifiers.some(
s => s.imported && s.imported.name === options.fromImport
);
}).length > 0
);
};
const containsReplacer = (
j: JSCodeshift,
source: string,
options: { [key: string]: string }
) => {
return (
j(source)
.find<ImportDeclaration>(j.ImportDeclaration)
.filter(imp => {
const importLine = imp.node;
return importLine.source.value === options.toModule;
}).length > 0
);
};
const transform: Transform = (fileInfo, api, options) => {
const { fromModule, fromImport, toModule, toImport } = options;
if (![fromModule, fromImport, toModule, toImport].every(i => i)) {
throw new Error(
"Didn't receive all the arguments: fromModule, fromImport, toModule, toImport"
);
}
const j = api.jscodeshift;
const importDeclaration: ImportDeclarationBuilder = j.importDeclaration as any;
// does the current file contains a reference to import of compose from react-apollo?
const hasFromImport = codeContainsImport(j, fileInfo.source, options);
if (!hasFromImport) {
return;
}
// remove instances of compose from react-apollo import
const sourceAfterRemovingSourceImport = j(fileInfo.source)
.find<ImportDeclaration>(j.ImportDeclaration)
.filter(imp => {
const importLine = imp.node;
return importLine.source.value === options.fromModule;
})
.replaceWith(p => {
const specifiers = p.node.specifiers.filter(
s =>
s.type === "ImportDefaultSpecifier" ||
(s.imported && s.imported.name !== options.fromImport)
);
if (!specifiers.length) return;
return importDeclaration(specifiers, {
value: options.fromModule,
type: "Literal"
});
})
.toSource();
const replacerSpecifier = {
imported: {
name: options.toImport,
type: "Identifier"
},
type: "ImportSpecifier"
};
const importFromReplacer = importDeclaration([replacerSpecifier], {
value: options.toModule,
type: "Literal"
});
const hasReplacer = containsReplacer(j, sourceAfterRemovingSourceImport, options);
// do we already have an import from microscopekit in this file? them add a new import statement for microscopekit
if (!hasReplacer) {
const decl = j(sourceAfterRemovingSourceImport)
.find<ImportDeclaration>(j.ImportDeclaration)
.at(0)
.insertAfter(importFromReplacer);
return decl.toSource();
}
// otherwise amend a compose to the existing one
const decl = j(sourceAfterRemovingSourceImport)
.find<ImportDeclaration>(j.ImportDeclaration, node => {
return node.source.value === options.toModule;
})
.at(0)
.replaceWith(p => {
return importDeclaration(
[...(p.node.specifiers as any), replacerSpecifier],
{
value: options.toModule,
type: "Literal"
}
);
});
return decl.toSource();
};
export const parser = "tsx";
export default transform;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment