Add ability to generate package.json deps from root pkg

This commit is contained in:
Jerko Steiner 2019-10-01 10:02:09 +07:00
parent 0c49e52f21
commit 64d9778a33
4 changed files with 476 additions and 589 deletions

930
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -54,22 +54,31 @@
"@typescript-eslint/eslint-plugin": "^2.2.0",
"@typescript-eslint/parser": "^2.2.0",
"axios": "^0.19.0",
"bcrypt": "^3.0.6",
"bloomer": "^0.6.5",
"body-parser": "^1.19.0",
"browser-unpack": "^1.4.2",
"browserify": "^16.2.3",
"browserify-hmr": "^0.4.0",
"buildfile": "^1.2.22",
"bulma": "^0.7.4",
"cls-hooked": "^4.2.2",
"common-shakeify": "^0.6.0",
"cookie-parser": "^1.4.4",
"csurf": "^1.10.0",
"deep-object-diff": "^1.1.0",
"email-validator": "^2.0.4",
"eslint": "^6.4.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-react": "^7.14.3",
"esmify": "git+https://github.com/jeremija/esmify.git",
"express": "^4.17.1",
"express-session": "^1.16.2",
"formik": "^1.5.8",
"history": "^4.9.0",
"http-errors": "^1.7.3",
"jest": "^24.5.0",
"js-yaml": "^3.13.1",
"lerna": "^3.16.4",
"loose-envify": "^1.4.0",
"marked": "^0.7.0",
@ -79,16 +88,21 @@
"nodemon": "^1.18.9",
"npm-run-all": "^4.1.5",
"open-graph-scraper": "^3.6.2",
"passport": "^0.4.0",
"passport-local": "^1.0.0",
"pkg": "^4.4.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-icons": "^3.5.0",
"react-redux": "^7.1.1",
"react-router": "^5.0.1",
"react-router-dom": "^5.0.1",
"react-ssr-prepass": "^1.0.5",
"redux": "^4.0.1",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.0",
"sanitize-html": "^1.20.0",
"shortid": "^2.2.15",
"sourceify": "git+https://github.com/jeremija/sourceify.git#sources-content",
"std-mocks": "^1.0.1",
"styled-components": "^4.4.0",

View File

@ -2,16 +2,34 @@ import * as ts from 'typescript'
import {argparse, arg} from '@rondo.dev/argparse'
import {info, error} from '../log'
import { getFolders } from '../getFolders'
import {readFileSync} from 'fs'
import {join} from 'path'
export function imports(...argv: string[]): string[] {
interface Package {
name: string
version: string
dependencies: Record<string, string>
devDependencies: Record<string, string>
}
interface Dependencies {
dependencies: string[]
devDependencies: string[]
}
export function imports(...argv: string[]) {
const args = argparse({
packages: arg('string', {default: 'packages/', positional: true}),
root: arg('string', {default: 'package.json'}),
root: arg('string', {default: './package.json'}),
dryRun: arg('boolean'),
testFileRegex: arg('string', {default: '\\.test\\.(t|j)sx?$'}),
debug: arg('boolean'),
help: arg('boolean', {alias: 'h'}),
output: arg('string', {alias: 'o', default: '-'}),
}).parse(argv)
const testFileRegex = new RegExp(args.testFileRegex)
function debug(m: string, ...meta: Array<unknown>) {
if (args.debug) {
info(m, ...meta)
@ -22,7 +40,7 @@ export function imports(...argv: string[]): string[] {
function collectImports(
projectDir: string,
tsconfigFileName: string,
): string[] {
): Dependencies {
// Build a program using the set of root file names in fileNames
// const program = ts.createProgram(fileNames, options)
const configPath = ts.findConfigFile(
@ -52,7 +70,8 @@ export function imports(...argv: string[]): string[] {
parsedCommandLine.options,
)
const modules = new Set<string>()
// key is dependency name, list contains source files
const filenamesByRequiredModule: Record<string, string[]> = {}
// Get the checker, we will use it to find more about classes
// const checker = program.getTypeChecker()
@ -82,11 +101,9 @@ export function imports(...argv: string[]): string[] {
return
}
if (!modules.has(name)) {
debug(name)
modules.add(name)
}
const filenames = filenamesByRequiredModule[name] =
filenamesByRequiredModule[name] || []
filenames.push(sourceFile.fileName)
}
ts.forEachChild(node, visit.bind(null, sourceFile))
@ -99,22 +116,85 @@ export function imports(...argv: string[]): string[] {
}
}
return Array.from(modules)
const result: Dependencies = {
dependencies: [],
devDependencies: [],
}
Object.keys(filenamesByRequiredModule).forEach(moduleName => {
const filenames = filenamesByRequiredModule[moduleName]
if (filenames.every(filename => testFileRegex.test(filename))) {
result.devDependencies.push(moduleName)
} else {
result.dependencies.push(moduleName)
}
})
return result
}
getFolders(args.packages)
.forEach(pkgDir => {
function readPackage(path: string): Package {
return JSON.parse(readFileSync(path, 'utf8'))
}
// eslint-disable-next-line
const rootPackage = readPackage(args.root)
function resolveModule(name: string, version?: string) {
if (!version) {
throw new Error(`Module "${name}" not found in root package.json`)
}
if (version.startsWith('file:')) {
const pkg = readPackage(join(version.slice(5), 'package.json'))
if (!pkg.version) {
throw new Error(`Package.json of referenced module "${name}" ` +
'does not have version field')
}
return {name, version: pkg.version}
}
name = name.split('/')[0]
return {name: name, version}
}
function resolveModuleName(name: string) {
const folders = name.split('/')
if (folders[0].startsWith('@')) {
return folders.slice(0, 2).join('/')
}
return folders[0]
}
function resolveDependencies(dependencies: string[]) {
return dependencies
.map(resolveModuleName)
.reduce((obj, mod) => {
const versionString =
rootPackage.dependencies[mod] ||
rootPackage.devDependencies[mod]
const resolvedModule = resolveModule(mod, versionString)
obj[resolvedModule.name] = resolvedModule.version
return obj
}, {} as Record<string, string>)
}
const result = getFolders(args.packages)
.map(pkgDir => {
error('Entering: %s', pkgDir)
const modules = collectImports(pkgDir, 'tsconfig.json')
const imports = collectImports(pkgDir, 'tsconfig.json')
const packageFile = join(pkgDir, 'package.json')
const targetPackage = readPackage(packageFile)
targetPackage.dependencies = resolveDependencies(imports.dependencies)
targetPackage.devDependencies = resolveDependencies(imports.devDependencies)
debug('dependencies: %o', targetPackage.dependencies)
debug('devDependencies: %o', targetPackage.devDependencies)
return {filename: packageFile, json: targetPackage}
})
.forEach(pkg => {
// TODO write package.json
// const value = JSON.stringify(pkg.json, null, ' ')
// fs.writeFileSync(pkg.filename, value)
})
if (args.output === '-') {
// info(value)
} else {
// fs.writeFileSync(args.output, value)
}
return []
return result
}
imports.help = 'Find used module in a package, use root package.json to ' +
'find dependency versions and update local package.json. Useful when using ' +

View File

@ -1,5 +1,6 @@
{
"name": "@rondo.dev/package",
"version": "0.0.1",
"private": true,
"scripts": {
"test": "jest",