Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
],
"main": "dist/cli.js",
"types": "dist/cli.d.ts",
"bin": "./dist/cli.js",
"scripts": {
"transform": "ts-node-transpile-only ./src/cli.ts",
"test": "jest",
Expand All @@ -34,13 +35,15 @@
},
"dependencies": {
"camelcase": "^6.2.0",
"commander": "^8.1.0",
"css-modules-loader-core": "^1.1.0",
"lodash": "^4.17.21",
"postcss": "^8.3.6",
"postcss-nested": "^5.0.6",
"postcss-scss": "^4.0.0",
"postcss-selector-parser": "^6.0.6",
"prettier-eslint": "^13.0.0",
"signale": "^1.4.0",
"stylelint": "^13.13.1",
"ts-morph": "^11.0.3",
"ts-node": "^10.1.0",
Expand All @@ -60,6 +63,7 @@
"@types/eslint": "7.28.0",
"@types/jest": "27.0.1",
"@types/node": "16.4.1",
"@types/signale": "1.4.2",
"@types/stylelint": "13.13.2",
"eslint": "^7.32.0",
"husky": "^7.0.1",
Expand Down
50 changes: 39 additions & 11 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,47 @@
import path from 'path'

import { Command, Option } from 'commander'
import signale from 'signale'
import { Project } from 'ts-morph'

import { globalCssToCssModule } from './transforms/globalCssToCssModule/globalCssToCssModule'
import { transforms, transformNames } from './transforms'

const TARGET_FILE = path.resolve(__dirname, './transforms/globalCssToCssModule/__tests__/fixtures/Kek.tsx')
const program = new Command()

async function main(): Promise<void> {
const project = new Project()
project.addSourceFilesAtPaths(TARGET_FILE)

const result = await globalCssToCssModule({ project, shouldWriteFiles: true })
console.log(result)
interface CodemodCliOptions {
write: boolean
format: boolean
transform: keyof typeof transforms
}

main().catch(error => {
throw error
})
program
.addOption(
new Option('-t, --transform <transform>', 'Transform name').choices(transformNames).makeOptionMandatory()
)
.option('-w, --write [write]', 'Persist codemod changes to the filesystem', false)
.argument('<fileGlob>', 'File glob or globs to change files based on')
.action(async (fileGlob: string, options: CodemodCliOptions) => {
const { write: shouldWriteFiles, transform } = options
const projectGlob = path.isAbsolute(fileGlob) ? fileGlob : path.join(process.cwd(), fileGlob)

signale.start(`Starting codemod "${transform}" with project glob "${projectGlob}"`)

const project = new Project()
project.addSourceFilesAtPaths(projectGlob)

const results = await transforms[transform]({ project, shouldWriteFiles })

if (results) {
if (shouldWriteFiles) {
signale.info('Persisting codemod changes to the filesystem...')
await Promise.all(results.map(result => result.fsWritePromise))
signale.info('Persisting codemod changes completed')
} else {
console.log(results)
}

signale.success('Files are transformed!')
}
})

program.parse(process.argv)
8 changes: 1 addition & 7 deletions src/transforms/globalCssToCssModule/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,5 @@ Status: WIP
## Usage

```sh
echo "Hello world"
yarn transform -t globalCssToCssModule /client/web/src/search/home/SearchPage.tsx --write
```

## TODO

- [x] Run code formatters on the updated files
- [x] Handle @import statements in SCSS
- [ ] Add interactive CLI support
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@ describe('globalCssToCssModule', () => {
it('transforms correctly', async () => {
const project = new Project()
project.addSourceFilesAtPaths(TARGET_FILE)
const [transformResult] = await globalCssToCssModule({ project })
const codemodResults = await globalCssToCssModule({ project })

expect(transformResult.css.source).toMatchSnapshot()
expect(transformResult.ts.source).toMatchSnapshot()
expect(codemodResults).toBeTruthy()

if (codemodResults) {
const [transformResult] = codemodResults

expect(transformResult.css.source).toMatchSnapshot()
expect(transformResult.ts.source).toMatchSnapshot()
}
}, 15000) // Timeout of 15s (default is 5s). `prettier-eslint` format is slow 😬.
})
19 changes: 11 additions & 8 deletions src/transforms/globalCssToCssModule/globalCssToCssModule.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { existsSync, readFileSync, promises as fsPromises } from 'fs'
import path from 'path'

import signale from 'signale'
import { Project } from 'ts-morph'

import { formatWithPrettierEslint, formatWithStylelint, isDefined } from '../../utils'
Expand Down Expand Up @@ -41,7 +42,7 @@ interface CodemodResult {
* 7) Add `.module.scss` import to the `.tsx` file.
*
*/
export async function globalCssToCssModule(options: GlobalCssToCssModuleOptions): Promise<CodemodResult[]> {
export async function globalCssToCssModule(options: GlobalCssToCssModuleOptions): Promise<CodemodResult[] | false> {
const { project, shouldWriteFiles } = options
/**
* Find `.tsx` files with co-located `.scss` file.
Expand All @@ -66,10 +67,18 @@ export async function globalCssToCssModule(options: GlobalCssToCssModuleOptions)
})
.filter(isDefined)

if (itemsToProcess.length === 0) {
signale.warn('No files to process!')

return false
}

const codemodResultPromises = itemsToProcess.map(async ({ tsSourceFile, cssFilePath }) => {
const tsFilePath = tsSourceFile.getFilePath()
const parsedTsFilePath = path.parse(tsFilePath)

signale.info(`Processing file "${tsFilePath}"`)

const sourceCss = readFileSync(cssFilePath, 'utf8')
const exportNameMap = await getCssModuleExportNameMap(sourceCss)
const { css: cssModuleSource, filePath: cssModuleFileName } = await transformFileToCssModule({
Expand Down Expand Up @@ -119,11 +128,5 @@ export async function globalCssToCssModule(options: GlobalCssToCssModuleOptions)
}
})

const codemodResults = await Promise.all(codemodResultPromises)

if (shouldWriteFiles) {
await Promise.all(codemodResults.map(result => result.fsWritePromise))
}

return codemodResults
return Promise.all(codemodResultPromises)
}
1 change: 1 addition & 0 deletions src/transforms/globalCssToCssModule/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './globalCssToCssModule'
7 changes: 7 additions & 0 deletions src/transforms/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { globalCssToCssModule } from './globalCssToCssModule/globalCssToCssModule'

export const transforms = {
globalCssToCssModule,
} as const

export const transformNames = Object.keys(transforms)
14 changes: 13 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1933,6 +1933,13 @@
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065"
integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==

"@types/signale@1.4.2":
version "1.4.2"
resolved "https://registry.yarnpkg.com/@types/signale/-/signale-1.4.2.tgz#6fc36d038297fa4c1d9aa2b5c2ec80195d4c5d2f"
integrity sha512-cIqvDXQmLD5UNgtYhHvTt4dEyR+FXuCwoqQbz7mZaS7pGyJvpUFDAoMbgwymptqUXH3eL8vBcNU+dBiyauaA6Q==
dependencies:
"@types/node" "*"

"@types/stack-utils@^2.0.0":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
Expand Down Expand Up @@ -2911,6 +2918,11 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"

commander@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-8.1.0.tgz#db36e3e66edf24ff591d639862c6ab2c52664362"
integrity sha512-mf45ldcuHSYShkplHHGKWb4TrmwQadxOn7v4WuhDJy0ZVoY5JFajaRDKD0PNe5qXzBX0rhovjTnP6Kz9LETcuA==

comment-parser@^0.7.6:
version "0.7.6"
resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.7.6.tgz#0e743a53c8e646c899a1323db31f6cd337b10f12"
Expand Down Expand Up @@ -7523,7 +7535,7 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==

signale@^1.2.1:
signale@^1.2.1, signale@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/signale/-/signale-1.4.0.tgz#c4be58302fb0262ac00fc3d886a7c113759042f1"
integrity sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==
Expand Down