From b5ac181e1050819b72800c339647546defdb86ea Mon Sep 17 00:00:00 2001 From: whitecolor Date: Tue, 25 Apr 2017 10:33:00 +0500 Subject: [PATCH] move to separate files add/update --- .vscode/settings.json | 13 +-- package.json | 7 +- src/add.ts | 145 ++++++++++++++++++++++++++++++++++ src/check.ts | 1 + src/index.ts | 180 +++--------------------------------------- src/publish.ts | 1 + src/remove.ts | 26 ++++++ src/update.ts | 70 ++++++++++++++++ src/yalc.ts | 4 +- tsconfig.json | 3 +- 10 files changed, 266 insertions(+), 184 deletions(-) create mode 100644 src/add.ts create mode 100644 src/remove.ts create mode 100644 src/update.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index a6398bd..7314f9d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,12 +1,13 @@ - { "typescript.tsdk": "./node_modules/typescript/lib", - "typescript.tsserver.trace": "verbose", - "search.exclude": { - "**/out": true - }, + "typescript.tsserver.trace": "verbose", + "search.exclude": {}, + "files.exclude": { + "**/*.js": true, + "**/*.js.map": true, + "**/*.d.ts": true + }, "tslint.run": "onSave", - "editor.formatOnType": true, "editor.tabSize": 2, "editor.insertSpaces": true diff --git a/package.json b/package.json index b4d939b..13d67fc 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,14 @@ "version": "1.0.0-pre.0", "description": "Work yarn packages locally like a boss.", "bin": { - "yalc": "out/yalc.js" + "yalc": "src/yalc.js" }, + "main": "src/index.js", "scripts": { "build": "tsc", "precommit": "yalc check", - "test": "mocha out/test", - "watch": "mocha out/test --watch", + "test": "mocha test", + "watch": "mocha test --watch", "ci": "tsc && yarn test" }, "license": "MIT", diff --git a/src/add.ts b/src/add.ts new file mode 100644 index 0000000..b6892ec --- /dev/null +++ b/src/add.ts @@ -0,0 +1,145 @@ +import { execSync } from 'child_process' +import * as fs from 'fs-extra' +import { join } from 'path' +import { + PackageInstallation, InstallationsFile, + readInstallationsFile, + addInstallations, + removeInstallations, + PackageName +} from './installations' + +import { + readLockfile, + addPackageToLockfile, + LockFilePackageEntry +} from './lockfile' + +import { + getStorePackagesDir, + PackageManifest, + getPackageStoreDir, + values, + parsePackageName +} from '.' + +const ensureSymlinkSync = fs.ensureSymlinkSync as typeof fs.symlinkSync + +export interface AddPackagesOptions { + dev?: boolean, + link?: boolean, + yarn?: boolean, + safe?: boolean + workingDir: string, +} + +const getLatestPackageVersion = (packageName: string) => { + const dir = getPackageStoreDir(packageName) + const versions = fs.readdirSync(dir) + const latest = versions.map(version => ({ + version, created: fs.statSync(join(dir, version)).ctime.getTime() + })) + .sort((a, b) => b.created - a.created).map(x => x.version)[0] + return latest || '' +} + +export const addPackages = (packages: string[], options: AddPackagesOptions) => { + const packagesStoreDir = getStorePackagesDir() + const addedInstalls = packages.map((packageName) => { + const { name, version = '' } = parsePackageName(packageName) + + if (!name) { + console.log('Could not parse package name', packageName) + } + + if (!fs.existsSync(getPackageStoreDir(name))) { + console.log(`Could not find package \`${name}\` in store.`) + return null + } + const versionToInstall = version || getLatestPackageVersion(name) + + const storedPackageDir = getPackageStoreDir(name, versionToInstall) + + if (!fs.existsSync(storedPackageDir)) { + console.log(`Could not find package \`${packageName}\` ` + storedPackageDir) + return null + } + + const pkgFile = join(storedPackageDir, 'package.json') + let pkg + try { + pkg = fs.readJsonSync(join(storedPackageDir, 'package.json')) + } catch (e) { + console.log('Could not read and parse ', pkgFile) + return null + } + const destLoctedCopyDir = join(options.workingDir, + values.locedPackagesFolder, name) + const destloctedLinkDir = join(options.workingDir, 'node_modules', name) + + fs.emptyDirSync(destLoctedCopyDir) + fs.copySync(storedPackageDir, destLoctedCopyDir) + fs.removeSync(destloctedLinkDir) + + let replacedVersion = '' + if (options.link) { + ensureSymlinkSync(destLoctedCopyDir, destloctedLinkDir, 'dir') + } else { + const localAddress = 'file:' + values.locedPackagesFolder + '/' + pkg.name + fs.copySync(destLoctedCopyDir, destloctedLinkDir) + const localManifestFile = join(options.workingDir, 'package.json') + const localPkg = fs.readJsonSync(localManifestFile) as PackageManifest + + const dependencies = localPkg.dependencies || {} + const devDependencies = localPkg.devDependencies || {} + let whereToAdd = options.dev + ? devDependencies : dependencies + + if (options.dev) { + if (dependencies[pkg.name]) { + replacedVersion = dependencies[pkg.name] + delete dependencies[pkg.name] + } + } else { + if (!dependencies[pkg.name]) { + if (devDependencies[pkg.name]) { + whereToAdd = devDependencies + } + } + } + + if (whereToAdd[pkg.name] !== localAddress) { + replacedVersion = replacedVersion || whereToAdd[pkg.name] + whereToAdd[pkg.name] = localAddress + localPkg.dependencies = dependencies + localPkg.devDependencies = devDependencies + fs.writeJsonSync(localManifestFile, localPkg) + } + replacedVersion = replacedVersion == localAddress ? '' : replacedVersion + } + console.log(`${pkg.name}@${pkg.version} locted ==> ${destloctedLinkDir}`) + return { + name, + version, + replaced: replacedVersion, + path: options.workingDir + } + }).filter(_ => _) as PackageInstallation[] + + addPackageToLockfile( + addedInstalls + .map((i) => ({ + name: i!.name, + version: i!.version, + replaced: i!.replaced, + file: !options.link + })), { workingDir: options.workingDir } + ) + + addInstallations(addedInstalls) + + if (options.yarn) { + const changeDirCmd = 'cd ' + options.workingDir + ' && ' + execSync(changeDirCmd + 'yarn') + } +} diff --git a/src/check.ts b/src/check.ts index bd10f32..459c551 100644 --- a/src/check.ts +++ b/src/check.ts @@ -17,6 +17,7 @@ export type CheckOptions = { const stagedChangesCmd = 'git diff --cached --name-only' const allChangesCmd = 'git diff HEAD --name-only' const notStagedChangesCmd = 'git diff --name-only' +//git ls-files --others --exclude-standard //const filesInCommitCmd = 'git diff-tree --no-commit-id --name-only -r bd61ad98' const isPackageManifest = (fileName: string) => diff --git a/src/index.ts b/src/index.ts index 28cafe9..feabb37 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,10 +21,9 @@ const { join } = path const ensureSymlinkSync = fs.ensureSymlinkSync as typeof fs.symlinkSync -export const myNameIs = 'yalc' -export const myNameIsCapitalized = 'Yalc' - export const values = { + myNameIs: 'yalc', + myNameIsCapitalized: 'Yalc', lockfileName: 'yalc.lock', locedPackagesFolder: '.yalc', installationsFile: 'installations.json' @@ -43,11 +42,11 @@ export interface UpdatePackagesOptions { workingDir: string, } -export interface RemovePackagesOptions { - workingDir: string, -} - export { publishPackage } from './publish' +export { updatePackages } from './update' +export { checkManifest } from './check' +export { removePackages } from './remove' +export { addPackages } from './add' export interface YalcGlobal extends NodeJS.Global { yalcStoreMainDir: string @@ -59,9 +58,9 @@ export function getStoreMainDir(): string { return yalcGlobal.yalcStoreMainDir } if (process.platform === 'win32' && process.env.LOCALAPPDATA) { - return join(process.env.LOCALAPPDATA, myNameIsCapitalized); + return join(process.env.LOCALAPPDATA, values.myNameIsCapitalized); } - return join(userHome, '.' + myNameIs); + return join(userHome, '.' + values.myNameIs); } export function getStorePackagesDir(): string { @@ -91,171 +90,10 @@ export const getPackageManager = () => export const execLoudOptions = { stdio: 'inherit' } -const getLatestPackageVersion = (packageName: string) => { - const dir = getPackageStoreDir(packageName) - const versions = fs.readdirSync(dir) - const latest = versions.map(version => ({ - version, created: fs.statSync(path.join(dir, version)).ctime.getTime() - })) - .sort((a, b) => b.created - a.created).map(x => x.version)[0] - return latest || '' -} - -const parsePackageName = (packageName: string) => { +export const parsePackageName = (packageName: string) => { const match = packageName.match(/(^@[^/]+\/)?([^@]+)@?(.*)/) || [] if (!match) { return { name: '' as PackageName, version: '' } } return { name: (match[1] || '') + match[2] as PackageName, version: match[3] || '' } } - - -export const addPackages = (packages: string[], options: AddPackagesOptions) => { - const packagesStoreDir = getStorePackagesDir() - const addedInstalls = packages.map((packageName) => { - const { name, version = '' } = parsePackageName(packageName) - - if (!name) { - console.log('Could not parse package name', packageName) - } - - if (!fs.existsSync(getPackageStoreDir(name))) { - console.log(`Could not find package \`${name}\` in store.`) - return null - } - const versionToInstall = version || getLatestPackageVersion(name) - - const storedPackageDir = getPackageStoreDir(name, versionToInstall) - - if (!fs.existsSync(storedPackageDir)) { - console.log(`Could not find package \`${packageName}\` ` + storedPackageDir) - return null - } - - const pkgFile = path.join(storedPackageDir, 'package.json') - let pkg - try { - pkg = fs.readJsonSync(path.join(storedPackageDir, 'package.json')) - } catch (e) { - console.log('Could not read and parse ', pkgFile) - return null - } - const destLoctedCopyDir = path.join(options.workingDir, - values.locedPackagesFolder, name) - const destloctedLinkDir = path.join(options.workingDir, 'node_modules', name) - - fs.emptyDirSync(destLoctedCopyDir) - fs.copySync(storedPackageDir, destLoctedCopyDir) - fs.removeSync(destloctedLinkDir) - - let replacedVersion = '' - if (options.link) { - ensureSymlinkSync(destLoctedCopyDir, destloctedLinkDir, 'dir') - } else { - const localAddress = 'file:' + values.locedPackagesFolder + '/' + pkg.name - fs.copySync(destLoctedCopyDir, destloctedLinkDir) - const localManifestFile = path.join(options.workingDir, 'package.json') - const localPkg = fs.readJsonSync(localManifestFile) as PackageManifest - - const dependencies = localPkg.dependencies || {} - const devDependencies = localPkg.devDependencies || {} - let whereToAdd = options.dev - ? devDependencies : dependencies - - if (options.dev) { - if (dependencies[pkg.name]) { - replacedVersion = dependencies[pkg.name] - delete dependencies[pkg.name] - } - } else { - if (!dependencies[pkg.name]) { - if (devDependencies[pkg.name]) { - whereToAdd = devDependencies - } - } - } - - if (whereToAdd[pkg.name] !== localAddress) { - replacedVersion = replacedVersion || whereToAdd[pkg.name] - whereToAdd[pkg.name] = localAddress - localPkg.dependencies = dependencies - localPkg.devDependencies = devDependencies - fs.writeJsonSync(localManifestFile, localPkg) - } - replacedVersion = replacedVersion == localAddress ? '' : replacedVersion - } - console.log(`${pkg.name}@${pkg.version} locted ==> ${destloctedLinkDir}`) - return { - name, - version, - replaced: replacedVersion, - path: options.workingDir - } - }).filter(_ => _) as PackageInstallation[] - - addPackageToLockfile( - addedInstalls - .map((i) => ({ - name: i!.name, - version: i!.version, - replaced: i!.replaced, - file: !options.link - })), { workingDir: options.workingDir } - ) - - addInstallations(addedInstalls) - - if (options.yarn) { - const changeDirCmd = 'cd ' + options.workingDir + ' && ' - execSync(changeDirCmd + 'yarn') - } -} - -export const showInstallations = (options: { workingDir: string }) => { - -} - -export const updatePackages = (packages: string[], options: UpdatePackagesOptions) => { - const lockfile = readLockfile({ workingDir: options.workingDir }) - - let packagesToUpdate: string[] = [] - let installationsToRemove: PackageInstallation[] = [] - if (packages.length) { - packages.forEach((packageName) => { - const { name, version } = parsePackageName(packageName) - if (lockfile.packages[name]) { - if (version) { - lockfile.packages[name].version = version - } - packagesToUpdate.push(name) - } else { - installationsToRemove.push({ name, version, path: options.workingDir }) - console.log(`Did not find package ${name} in lockfile, ` + - `please use 'add' command to add it explicitly.` - ) - } - }) - } else { - packagesToUpdate = Object.keys(lockfile.packages) - } - - const lockPackages = packagesToUpdate - .map(name => ({ - name: lockfile.packages[name].version - ? name + '@' + lockfile.packages[name].version : name, - file: lockfile.packages[name].file - })) - const packagesFiles = lockPackages - .filter(p => p.file).map(p => p.name) - addPackages(packagesFiles, { workingDir: options.workingDir }) - - const packagesLinks = lockPackages - .filter(p => !p.file).map(p => p.name) - addPackages(packagesLinks, { workingDir: options.workingDir, link: true }) - - removeInstallations(installationsToRemove) -} - -export const removePackages = (packages: string[], options: RemovePackagesOptions) => { - -} diff --git a/src/publish.ts b/src/publish.ts index eb0ad6c..d4fdaef 100644 --- a/src/publish.ts +++ b/src/publish.ts @@ -9,6 +9,7 @@ import { removeInstallations, PackageName } from './installations' + import { readLockfile, addPackageToLockfile, diff --git a/src/remove.ts b/src/remove.ts new file mode 100644 index 0000000..36f53e9 --- /dev/null +++ b/src/remove.ts @@ -0,0 +1,26 @@ +import { execSync } from 'child_process' +import * as fs from 'fs-extra' +import * as path from 'path' +import { copyWithIgnorePackageToStore } from './copy' + +import { + PackageInstallation, InstallationsFile, + readInstallationsFile, + addInstallations, + removeInstallations, + PackageName +} from './installations' + +import { + readLockfile, + addPackageToLockfile, + LockFilePackageEntry +} from './lockfile' + +export interface RemovePackagesOptions { + workingDir: string, +} + +export const removePackages = (packages: string[], options: RemovePackagesOptions) => { + +} diff --git a/src/update.ts b/src/update.ts new file mode 100644 index 0000000..0dd673f --- /dev/null +++ b/src/update.ts @@ -0,0 +1,70 @@ +import { execSync } from 'child_process' +import * as fs from 'fs-extra' +import { join } from 'path' +import { + PackageInstallation, InstallationsFile, + readInstallationsFile, + addInstallations, + removeInstallations, + PackageName +} from './installations' + +import { + readLockfile, + addPackageToLockfile, + LockFilePackageEntry +} from './lockfile' + +import { + getStorePackagesDir, + PackageManifest, + getPackageStoreDir, + values, + parsePackageName, + addPackages +} from '.' + +export interface UpdatePackagesOptions { + safe?: boolean, + workingDir: string, +} +export const updatePackages = (packages: string[], options: UpdatePackagesOptions) => { + const lockfile = readLockfile({ workingDir: options.workingDir }) + + let packagesToUpdate: string[] = [] + let installationsToRemove: PackageInstallation[] = [] + if (packages.length) { + packages.forEach((packageName) => { + const { name, version } = parsePackageName(packageName) + if (lockfile.packages[name]) { + if (version) { + lockfile.packages[name].version = version + } + packagesToUpdate.push(name) + } else { + installationsToRemove.push({ name, version, path: options.workingDir }) + console.log(`Did not find package ${name} in lockfile, ` + + `please use 'add' command to add it explicitly.` + ) + } + }) + } else { + packagesToUpdate = Object.keys(lockfile.packages) + } + + const lockPackages = packagesToUpdate + .map(name => ({ + name: lockfile.packages[name].version + ? name + '@' + lockfile.packages[name].version : name, + file: lockfile.packages[name].file + })) + const packagesFiles = lockPackages + .filter(p => p.file).map(p => p.name) + addPackages(packagesFiles, { workingDir: options.workingDir }) + + const packagesLinks = lockPackages + .filter(p => !p.file).map(p => p.name) + addPackages(packagesLinks, { workingDir: options.workingDir, link: true }) + + removeInstallations(installationsToRemove) +} diff --git a/src/yalc.ts b/src/yalc.ts index 1dea289..a0f1a6e 100644 --- a/src/yalc.ts +++ b/src/yalc.ts @@ -2,7 +2,7 @@ import * as yargs from 'yargs' import { join } from 'path' import { - myNameIs, + values, publishPackage, addPackages, updatePackages, @@ -13,7 +13,7 @@ import { } from './check' -const cliCommand = myNameIs +const cliCommand = values.myNameIs console.log(`Work with npm/yarn local packages like a boss.\n`) yargs diff --git a/tsconfig.json b/tsconfig.json index c2474df..88cfd6f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,6 @@ "noImplicitAny": true, "noImplicitThis": true, "noImplicitReturns": true, - "outDir": "./out", "noFallthroughCasesInSwitch": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, @@ -19,5 +18,5 @@ "indentSize": 2, "tabSize": 2 }, - "exclude": ["**/node_modules/*", "out/*"] + "exclude": ["**/node_modules/*"] }