Skip to content

Commit

Permalink
code compiles to cjs and mjs
Browse files Browse the repository at this point in the history
  • Loading branch information
NazmusSayad committed Aug 20, 2024
1 parent 1edc621 commit 22a85c9
Show file tree
Hide file tree
Showing 11 changed files with 476 additions and 66 deletions.
351 changes: 347 additions & 4 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "npmize",
"description": "Let's create an npm package without worrying about anything.",
"version": "0.0.11",
"version": "1.0.0",
"bin": "./dist/index.js",
"scripts": {
"lab": "nodemon ./src/__lab.ts",
Expand All @@ -12,11 +12,15 @@
"dependencies": {
"@babel/parser": "^7.20.7",
"ansi-colors": "^4.1.3",
"cross-spawn": "^7.0.3",
"execa": "^9.3.1",
"lskit": "^1.0.0",
"noarg": "^1.0.3",
"shelljs": "^0.8.5"
"shelljs": "^0.8.5",
"zx": "^8.1.4"
},
"devDependencies": {
"@types/cross-spawn": "^6.0.6",
"@types/node": "^18.11.9",
"@types/shelljs": "^0.8.15",
"typescript": "^5.3.3"
Expand Down
4 changes: 3 additions & 1 deletion src/__lab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ console.clear()

import app from './main'

app.run(['init', '--name', '../npmize-test'])
// app.run(['init', '--name', '../npmize-test'])
app.run(['dev', '--root', '../npmize-test', '--node'])
// app.run(['build', '--root', '../npmize-test'])
6 changes: 6 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ app.create(
.aliases('t')
.default([])
.description("TypeScript's options"),

node: t
.boolean()
.aliases('n')
.default(false)
.description('Enable __dirname and __filename in ES modules'),
},
},

Expand Down
13 changes: 10 additions & 3 deletions src/program/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ import tsc from '../scripts/tsc'
import { cleanDir, moveFiles } from '../utils'
import updateImports from '../updateImports'
import pushNodeCode from '../scripts/pushNodeCode'
import packageJSON from '../scripts/packageJSON'

export default function (basePath: string, options: Options) {
cleanDir(options.outDir)
const data = packageJSON.read(basePath)
if (data.type) {
options.module ??= data.type === 'module' ? 'mjs' : 'cjs'
}

console.log(`Build started at ${basePath}`)
console.log('')

Expand All @@ -29,15 +34,17 @@ function runBuild(

const tempDir = path.join(basePath, config.tempBuildDir)
cleanDir(tempDir)
cleanDir(options.outDir)

tsc(basePath, [
...options.tsc.map((tsc) => `--${tsc}`),
`--outDir ${tempDir}`,
`--module ${moduleType === 'cjs' ? 'commonjs' : 'esnext'}`,
])

const files = lskit.sync(tempDir)
const renamedFiles = updateImports(moduleType, files)
const movedFiles = moveFiles(tempDir, options.outDir, renamedFiles)
const updatedImports = updateImports(moduleType, files)
const movedFiles = moveFiles(tempDir, options.outDir, updatedImports)

if (moduleType === 'mjs' && options.node && movedFiles.length) {
console.log('Enabling Node.js __dirname and __filename...')
Expand Down
52 changes: 44 additions & 8 deletions src/program/dev.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,58 @@
import fs from 'fs'
import path from 'path'
import config from '../config'
import tsc from '../scripts/tsc'
import updateImports from '../updateImports'
import { cleanDir, moveFiles } from '../utils'
import packageJSON from '../scripts/packageJSON'
import { cleanDir } from '../utils'
import pushNodeCode from '../scripts/pushNodeCode'

export default function (basePath: string, options: DevOptions) {
const data = packageJSON.read(basePath)
options.module ??= data.type === 'module' ? 'mjs' : 'cjs'
if (data.type) {
options.module ??= data.type === 'module' ? 'mjs' : 'cjs'
}

const tempDir = path.join(basePath, config.tempBuildDir)
cleanDir(tempDir)
cleanDir(options.outDir)
tsc(basePath, [
...options.tsc.map((tsc) => `--${tsc}`),
'--watch',
`--outDir ${options.outDir}`,
`--module ${options.module === 'cjs' ? 'commonjs' : 'esnext'}`,
])

function makeOutFiles(filename: string, outModule: 'cjs' | 'mjs') {
const fullPath = path.join(tempDir, filename)
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
const updatedImports = updateImports(outModule, [fullPath])
const [movedFile] = moveFiles(tempDir, options.outDir, updatedImports)
if (outModule === 'mjs' && options.node) pushNodeCode(movedFile)
}
}

fs.watch(tempDir, { recursive: true }, (event, filename) => {
if (event !== 'change') return
if (!(filename.endsWith('.js') || filename.endsWith('.ts'))) return

if (options.module) {
makeOutFiles(filename, options.module)
} else {
makeOutFiles(filename, 'cjs')
makeOutFiles(filename, 'mjs')
}
})

tsc(
basePath,
[
...options.tsc.map((tsc) => `--${tsc}`),
`--outDir ${tempDir}`,
`--module ${options.module === 'cjs' ? 'commonjs' : 'esnext'}`,
'--watch',
],
true
)
}

type DevOptions = {
module?: 'cjs' | 'mjs'
node?: boolean
outDir: string
tsc: string[]
}
4 changes: 2 additions & 2 deletions src/scripts/pushNodeCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ ${urlModule}${filename}${dirname}
export default (...files: string[]) => {
files.forEach((file) => {
if (file.endsWith('ts')) return

let data: string = fs.readFileSync(file, 'utf-8')
let data = fs.readFileSync(file, 'utf-8')
if (!(data.includes('__dirname') || data.includes('__filename'))) return

if (data.startsWith('#!')) {
const dataLines = data.split('\n')
Expand Down
4 changes: 2 additions & 2 deletions src/scripts/tsc.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import shelljs from 'shelljs'

export default function (cwd: string, args: string[]) {
shelljs.cd(cwd).exec(['npx tsc', ...args].join(' '))
export default function (cwd: string, args: string[], async = false) {
shelljs.exec(['npx', 'tsc', ...args].join(' '), { cwd, async })
}
63 changes: 31 additions & 32 deletions src/updateImports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import path from 'path'
import * as babel from '@babel/parser'
import * as utils from './utils'
import * as node from './node'
import { writeFileSync } from '../utils'

const getImports = (parsed: any) => {
return [
Expand All @@ -22,35 +21,35 @@ const getRequires = (parsed: any) => {
export default (type: 'cjs' | 'mjs', files: any[]) => {
const ext = '.' + type

return files.map((filePath) => {
const dirPath = path.dirname(filePath)
const data = fs.readFileSync(filePath, 'utf-8')
const parsedBody = babel.parse(data, {
sourceType: 'module',
plugins: ['typescript'],
sourceFilename: filePath,
}).program.body

const foundFilePaths =
filePath.endsWith('.ts') || type === 'mjs'
? getImports(parsedBody)
: getRequires(parsedBody)

const updatedData = utils.getUpdatedData(
data,
foundFilePaths,
(node: any) => {
const shortPath = node.value.replace(/\.js$/i, '')
const fullPath = path.join(dirPath, node.value)

const isExists = utils.isFileExists(files, fullPath)
return isExists ? shortPath + ext : shortPath + '/index' + ext
}
)

fs.rmSync(filePath)
const newFilePath = utils.getNewFilePath(filePath, type)
writeFileSync(newFilePath, updatedData)
return newFilePath
})
return Object.fromEntries(
files.map((filePath) => {
const dirPath = path.dirname(filePath)
const data = fs.readFileSync(filePath, 'utf-8')
const parsedBody = babel.parse(data, {
sourceType: 'module',
plugins: ['typescript'],
sourceFilename: filePath,
}).program.body

const foundFilePaths =
filePath.endsWith('.ts') || type === 'mjs'
? getImports(parsedBody)
: getRequires(parsedBody)

const updatedData = utils.getUpdatedData(
data,
foundFilePaths,
(node: any) => {
const shortPath = node.value.replace(/\.js$/i, '')
const fullPath = path.join(dirPath, node.value)

const isExists = utils.isFileExists(files, fullPath)
return isExists ? shortPath + ext : shortPath + '/index' + ext
}
)

const newFilePath = utils.getNewFilePath(filePath, type)
return [newFilePath, updatedData] as const
})
)
}
7 changes: 6 additions & 1 deletion src/updateImports/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as fs from 'fs'

export const getUpdatedData = (fileData: any, found: any[], cb: any) => {
const newEntries = [
{ start: 0, end: 0, value: '', rawValue: '', filename: '' },
Expand Down Expand Up @@ -33,7 +35,10 @@ export const isFileExists = (files: string[], target: string) => {
return (
files.includes(target) ||
files.includes(target + '.js') ||
files.includes(target + '.ts')
files.includes(target + '.ts') ||
(fs.existsSync(target) && fs.statSync(target).isFile()) ||
(fs.existsSync(target + '.js') && fs.statSync(target + '.js').isFile()) ||
(fs.existsSync(target + '.ts') && fs.statSync(target + '.ts').isFile())
)
}

Expand Down
30 changes: 19 additions & 11 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,36 @@ import fs from 'fs'
import path from 'path'
import shelljs from 'shelljs'

export function cleanDir(dir: string, create = true) {
export function cleanDir(dir: string, createDir = true) {
if (fs.existsSync(dir)) {
fs.rmSync(dir, { recursive: true, force: true })
}

if (create) {
if (createDir) {
fs.mkdirSync(dir, { recursive: true })
}
}

export function moveFiles(baseDir: string, outDir: string, files: string[]) {
return files.map((filePath) => {
const relativePath = path.relative(baseDir, filePath)
const outDirFilePath = path.join(outDir, '/' + relativePath)
export function moveFiles(
baseDir: string,
outDir: string,
data: Record<string, string>
) {
const newPaths = [] as string[]

if (!fs.existsSync(outDirFilePath)) {
fs.mkdirSync(path.dirname(outDirFilePath), { recursive: true })
for (const key in data) {
const oldRelative = path.relative(baseDir, key)
const outPath = path.join(outDir, oldRelative)

if (!fs.existsSync(outPath)) {
fs.mkdirSync(path.dirname(outPath), { recursive: true })
}

fs.renameSync(filePath, outDirFilePath)
return outDirFilePath
})
fs.writeFileSync(outPath, data[key])
newPaths.push(outPath)
}

return newPaths
}

export function writeFileSync(filePath: string, data: string) {
Expand Down

0 comments on commit 22a85c9

Please sign in to comment.