Skip to content

Commit

Permalink
update method optimized for optimal reliablity
Browse files Browse the repository at this point in the history
  • Loading branch information
NazmusSayad committed Sep 27, 2024
1 parent bac0cb6 commit 2ac3eed
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 142 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "npmize",
"version": "1.1.7",
"version": "1.1.8",
"description": "Let's create an npm package without worrying about anything.",
"bin": "./dist/index.js",
"scripts": {
"dev": "tsc -w",
"build": "node ./build.cjs",
"tsc": "tsc --noEmit --watch",
"lab": "run ./src/__lab__/index.ts",
"lab-js": "node --watch ./dist/__lab__/index.js"
"lab-js": "node --watch --watch ./dist/__lab__/index.js"
},
"dependencies": {
"@babel/parser": "^7.25.6",
Expand Down
2 changes: 1 addition & 1 deletion src/__lab__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import '../main'

// app.start(['init', TEST_TARGET])
// app.start(['dev', TEST_TARGET, '--node'])
app.start(['build', TEST_TARGET])
app.start(['build', TEST_TARGET, '--node'])
// app.start(['build', TEST_TARGET, '--worker'])
19 changes: 6 additions & 13 deletions src/scripts/generateOutput.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import path from 'path'
import getNodeCode from './getNodeCode'
import updateImports from '../updateImports'
import { MakeOutputOptions } from './makeOutputFile'
Expand All @@ -8,7 +7,7 @@ export default async function (
fileContent: string,
options: MakeOutputOptions
) {
const [tempFilePath, newFileContent] = await updateImports(
const updatedContent = await updateImports(
options.tempOutDir,
filePath,
fileContent,
Expand All @@ -17,15 +16,9 @@ export default async function (
options.tsConfig?.paths
)

const newFilePath = path.join(
options.finalOutDir,
path.relative(options.tempOutDir, tempFilePath)
)

const output =
options.pushNodeCode && options.moduleType === 'cjs'
? getNodeCode(newFilePath, newFileContent) + newFileContent
: newFileContent

return [newFilePath, output] as const
return options.pushNodeCode &&
options.moduleType === 'mjs' &&
filePath.endsWith('.js')
? getNodeCode(updatedContent) + updatedContent
: updatedContent
}
4 changes: 1 addition & 3 deletions src/scripts/getNodeCode.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
const varName =
'_____VGhpcyBuYW1lIGlzIHVzZWQgdG8gZW5hYmxlIF9fZGlybmFtZSBhbmQgX19maWxlbmFtZSDwn5iK_____'

export default (filePath: string, fileContent: string) => {
if (filePath.endsWith('ts')) return ''

export default function (fileContent: string) {
const isFilenameExist = fileContent.includes('__filename')
const isDirnameExist = fileContent.includes('__dirname')
if (!isFilenameExist && !isDirnameExist) return ''
Expand Down
11 changes: 7 additions & 4 deletions src/scripts/makeOutputFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import path from 'path'
import { Worker } from 'worker_threads'
import { autoCreateDir } from '../utils/fs'
import generateOutput from './generateOutput'
import { getNewFilePath } from './utils'

export type MakeOutputOptions = {
useWorker: boolean
Expand All @@ -19,10 +20,12 @@ export type MakeOutputOptions = {
export default async function (filePath: string, options: MakeOutputOptions) {
const fileContent = fs.readFileSync(filePath, 'utf-8')
const generator = options.useWorker ? generateOutputWorker : generateOutput
const [newFilePath, newFileContent] = await generator(
filePath,
fileContent,
options
const newFileContent = await generator(filePath, fileContent, options)

const relativeFilePath = path.relative(options.tempOutDir, filePath)
const newFilePath = getNewFilePath(
path.join(options.finalOutDir, relativeFilePath),
options.moduleType
)

autoCreateDir(path.dirname(newFilePath))
Expand Down
7 changes: 7 additions & 0 deletions src/scripts/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function getNewFilePath(filePath: string, type: 'cjs' | 'mjs') {
const prefix = type[0]

return filePath.replace(/\.(js|ts)$/, (match) => {
return match.replace(/(js|ts)/i, (type) => prefix + type)
})
}
33 changes: 33 additions & 0 deletions src/updateImports/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as fs from 'fs'
import { NodeType } from './types.t'

export function getUpdatedData(fileData: any, found: NodeType[], cb: any) {
const newEntries: NodeType[] = [
{ start: 0, end: 0, value: '', filename: '' },
...found.sort((a, b) => a.start - b.start),
]

const chunks = newEntries.map((node, i, arr) => {
const nextNode = arr[i + 1]
const nodeEnd = node.end
const nextNodeEnd = nextNode ? nextNode.start : Infinity
const str = fileData.slice(nodeEnd, nextNodeEnd)

if (!nextNode) return str
return [str, `"${cb(nextNode) ?? nextNode.value}"`]
})

return chunks.flat().join('')
}

export function resolveJsFilePath(target: string) {
function isExists(target: string) {
if (fs.existsSync(target) && fs.statSync(target).isFile()) return target
}

return (
isExists(target) ||
isExists(target + '.js') ||
isExists(target + '/index.js')
)
}
59 changes: 20 additions & 39 deletions src/updateImports/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import path from 'path'
import * as utils from './utils'
import { NodeType } from './types.t'
import * as babel from '@babel/parser'
import { Worker } from 'worker_threads'
import { Statement } from '@babel/types'
import { getImports, getRequires } from './node'
import { resolveImportPath } from '../scripts/tsconfig'
import { getUpdatedData, resolveJsFilePath } from './helpers'

export default async function (
cwd: string,
Expand All @@ -15,26 +13,26 @@ export default async function (
tsconfigBaseUrl: string | undefined,
tsconfigPaths: Record<string, string[]> | undefined
) {
const ext = '.' + moduleType
const fileDirPath = path.dirname(filePath)

const newExt = '.' + moduleType
const isModuleJs = filePath.endsWith('.ts') || moduleType === 'mjs'
const parsedBody = babel.parse(compiledText, {
sourceType: 'module',
plugins: ['typescript'],
sourceFilename: filePath,
}).program.body

const isModuleJs = filePath.endsWith('.ts') || moduleType === 'mjs'
const foundImportPaths = isModuleJs
? getImports(parsedBody)
: getRequires(parsedBody)

function updateRelativeImports(node: NodeType) {
const shortPath = node.value.replace(/\.js$/i, '')
const fullPath = path.join(fileDirPath, node.value)
const fileDir = path.dirname(filePath)
const resolvedPath = resolveJsFilePath(path.join(fileDir, node.value))
if (!resolvedPath) return

const isExists = utils.isFileExists(fullPath)
return isExists ? shortPath + ext : shortPath + '/index' + ext
const noExtPath = resolvedPath.replace(/\.\w+$/i, newExt)
const relativePath = path.relative(fileDir, noExtPath).replace(/\\/g, '/')
return relativePath.startsWith('.') ? relativePath : './' + relativePath
}

function updateResolvedPath(baseUrl: string, resolvedPath: string) {
Expand All @@ -49,7 +47,7 @@ export default async function (
)

const shortestPathWithExt =
path.dirname(shortPath) + '/' + path.parse(shortPath).name + ext
path.dirname(shortPath) + '/' + path.parse(shortPath).name + newExt

const posixSortPathWithExt = path
.normalize(shortestPathWithExt)
Expand All @@ -59,35 +57,18 @@ export default async function (
return './' + posixSortPathWithExt
}

const updatedData = utils.getUpdatedData(
compiledText,
foundImportPaths,
(node: NodeType) => {
if (node.value.startsWith('.')) {
return updateRelativeImports(node)
}

if (!tsconfigBaseUrl || !tsconfigPaths) return
const resolvedPath = resolveImportPath(
tsconfigBaseUrl,
node.value,
tsconfigPaths
)

return resolvedPath && updateResolvedPath(tsconfigBaseUrl, resolvedPath)
return getUpdatedData(compiledText, foundImportPaths, (node: NodeType) => {
if (node.value.startsWith('.')) {
return updateRelativeImports(node)
}
)

const newFilePath = utils.getNewFilePath(filePath, moduleType)
return [newFilePath, updatedData] as const
}
if (!tsconfigBaseUrl || !tsconfigPaths) return
const resolvedPath = resolveImportPath(
tsconfigBaseUrl,
node.value,
tsconfigPaths
)

function getRequiredStatements(type: 'import' | 'require', body: Statement[]) {
return new Promise<NodeType[]>((resolve) => {
const worker = new Worker(path.join(__dirname, './nodeWorker.js'))
worker.postMessage({ type, body })
worker.on('message', (message) => {
resolve(message)
})
return resolvedPath && updateResolvedPath(tsconfigBaseUrl, resolvedPath)
})
}
51 changes: 37 additions & 14 deletions src/updateImports/node.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,51 @@
import { NodeType } from './types.t'
import { Statement } from '@babel/types'
import { findNestedItems, isOkString, parseString } from './utils'

const TSImportType = (parsed: Statement[]) => {
return findNestedItems(parsed, 'type', 'TSImportType')
function parseString(str: any): NodeType {
return {
start: str.start,
end: str.end,
value: str.value,
filename: str.loc.filename,
}
}

const isOkString = (node: any) => {
return node && node.type === 'StringLiteral'
}

function findNestedItems(entireObj: Statement[], valToFind: unknown) {
const foundObj: any[] = []
JSON.stringify(entireObj, (_, nestedValue) => {
const found = nestedValue && nestedValue.type === valToFind
found && foundObj.push(nestedValue)
return nestedValue
})
return foundObj
}

function TSImportType(parsed: Statement[]) {
return findNestedItems(parsed, 'TSImportType')
.filter((node) => isOkString(node.argument))
.map((node) => parseString(node.argument))
}

const ImportDeclaration_ExportNamedDeclaration_ExportAllDeclaration = (
function ImportDeclaration_ExportNamedDeclaration_ExportAllDeclaration(
parsed: Statement[]
) => {
) {
return [
findNestedItems(parsed, 'type', 'ImportDeclaration'),
findNestedItems(parsed, 'type', 'ExportDeclaration'),
findNestedItems(parsed, 'type', 'ExportNamedDeclaration'),
findNestedItems(parsed, 'type', 'ExportAllDeclaration'),
findNestedItems(parsed, 'ImportDeclaration'),
findNestedItems(parsed, 'ExportDeclaration'),
findNestedItems(parsed, 'ExportNamedDeclaration'),
findNestedItems(parsed, 'ExportAllDeclaration'),
]
.flat()
.filter((node) => isOkString(node.source))
.map((node) => parseString(node.source))
}

const CallExpressionImport = (parsed: Statement[]) => {
return findNestedItems(parsed, 'type', 'CallExpression')
function CallExpressionImport(parsed: Statement[]) {
return findNestedItems(parsed, 'CallExpression')
.filter(
(node) =>
node &&
Expand All @@ -33,8 +56,8 @@ const CallExpressionImport = (parsed: Statement[]) => {
.map((node) => parseString(node.arguments[0]))
}

const CallExpressionRequire = (parsed: Statement[]) => {
return findNestedItems(parsed, 'type', 'CallExpression')
function CallExpressionRequire(parsed: Statement[]) {
return findNestedItems(parsed, 'CallExpression')
.filter(
(node) =>
node &&
Expand All @@ -48,8 +71,8 @@ const CallExpressionRequire = (parsed: Statement[]) => {

export function getImports(parsed: Statement[]) {
return [
...CallExpressionImport(parsed),
...TSImportType(parsed),
...CallExpressionImport(parsed),
...ImportDeclaration_ExportNamedDeclaration_ExportAllDeclaration(parsed),
]
}
Expand Down
1 change: 0 additions & 1 deletion src/updateImports/types.t.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ export type NodeType = {
start: number
end: number
value: string
rawValue: string
filename: string
}
Loading

0 comments on commit 2ac3eed

Please sign in to comment.