Skip to content

Commit

Permalink
fix: flat node_modules is only possible in the workspace root
Browse files Browse the repository at this point in the history
close #1928
  • Loading branch information
zkochan committed Jul 28, 2019
1 parent 0e4a094 commit 76d5249
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 5 deletions.
5 changes: 4 additions & 1 deletion packages/pnpm/src/cmd/recursive/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ export async function recursive (
if (cmdFullName !== 'rebuild') {
// For a workspace with shared lockfile
if (opts.lockfileDirectory && ['install', 'uninstall', 'update'].includes(cmdFullName)) {
if (opts.shamefullyFlatten) {
logger.info({ message: 'Only the root workspace package is going to have a flat node_modules', prefix: opts.lockfileDirectory })
}
let importers = await getImporters()
const isFromWorkspace = isSubdir.bind(null, opts.lockfileDirectory)
importers = await pFilter(importers, async ({ prefix }: { prefix: string }) => isFromWorkspace(await fs.realpath(prefix)))
Expand All @@ -238,7 +241,7 @@ export async function recursive (
const { manifest, writeImporterManifest } = manifestsByPath[prefix]
const shamefullyFlatten = typeof localConfigs.shamefullyFlatten === 'boolean'
? localConfigs.shamefullyFlatten
: opts.shamefullyFlatten
: (prefix === opts.lockfileDirectory && opts.shamefullyFlatten)
let currentInput = [...input]
if (updateToLatest) {
if (!currentInput || !currentInput.length) {
Expand Down
38 changes: 37 additions & 1 deletion packages/pnpm/test/install/shamefullyFlatten.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import prepare from '@pnpm/prepare'
import prepare, { preparePackages } from '@pnpm/prepare'
import fs = require('mz/fs')
import tape = require('tape')
import promisifyTape from 'tape-promise'
import writeYamlFile = require('write-yaml-file')
import { execPnpm } from '../utils'

const test = promisifyTape(tape)
const testOnly = promisifyTape(tape.only)

test('shamefully flatten the dependency tree', async function (t) {
const project = prepare(t)
Expand All @@ -20,3 +23,36 @@ test('shamefully flatten the dependency tree', async function (t) {
await project.hasNot('debug')
await project.hasNot('cookie')
})

test('shamefully-flatten: applied only to the workspace root package when set to true in the root .npmrc file', async (t: tape.Test) => {
const projects = preparePackages(t, [
{
location: '.',
package: {
name: 'root',

dependencies: {
'pkg-with-1-dep': '100.0.0',
},
},
},
{
name: 'project',
version: '1.0.0',

dependencies: {
'foobar': '100.0.0',
},
},
])

await writeYamlFile('pnpm-workspace.yaml', { packages: ['**', '!store/**'] })
await fs.writeFile('.npmrc', 'shamefully-flatten', 'utf8')

await execPnpm('recursive', 'install')

await projects['root'].has('dep-of-pkg-with-1-dep')
await projects['root'].has('foo')
await projects['project'].hasNot('foo')
await projects['project'].has('foobar')
})
3 changes: 1 addition & 2 deletions packages/pnpm/test/monorepo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ test('recursive install with link-workspace-packages and shared-workspace-lockfi
await writeYamlFile('pnpm-workspace.yaml', { packages: ['**', '!store/**'] })
await fs.writeFile(
'is-positive/.npmrc',
'shamefully-flatten = true\nsave-exact = true',
'save-exact = true',
'utf8',
)
await fs.writeFile(
Expand All @@ -435,7 +435,6 @@ test('recursive install with link-workspace-packages and shared-workspace-lockfi
await execPnpm('recursive', 'install', '--link-workspace-packages', '--shared-workspace-lockfile=true', '--store', 'store')

t.ok(projects['is-positive'].requireModule('is-negative'))
t.ok(projects['is-positive'].requireModule('concat-stream'), 'dependencies flattened in is-positive')
t.notOk(projects['project-1'].requireModule('is-positive/package.json').author, 'local package is linked')

const sharedLockfile = await readYamlFile<Lockfile>(WANTED_LOCKFILE)
Expand Down
16 changes: 16 additions & 0 deletions packages/supi/src/install/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,17 @@ export async function install (

export type MutatedImporter = ImportersOptions & DependenciesMutation

export class ShamefullyFlattenNotInLockfileDirectoryError extends PnpmError {
public readonly shamefullyFlattenDirectory: string
public readonly lockfileDirectory: string

constructor (shamefullyFlattenDirectory: string, lockfileDirectory: string) {
super('SHAMEFULLY_FLATTEN_NOT_IN_LOCKFILE_DIR', 'Shamefully flatten can be only used in the lockfile directory')
this.shamefullyFlattenDirectory = shamefullyFlattenDirectory
this.lockfileDirectory = lockfileDirectory
}
}

export async function mutateModules (
importers: MutatedImporter[],
maybeOpts: InstallOptions & {
Expand All @@ -154,6 +165,11 @@ export async function mutateModules (
if (!opts.include.dependencies && opts.include.optionalDependencies) {
throw new PnpmError('OPTIONAL_DEPS_REQUIRE_PROD_DEPS', 'Optional dependencies cannot be installed without production dependencies')
}
for (const { prefix, shamefullyFlatten } of importers) {
if (prefix !== opts.lockfileDirectory && shamefullyFlatten) {
throw new ShamefullyFlattenNotInLockfileDirectoryError(prefix, opts.lockfileDirectory)
}
}

const ctx = await getContext(importers, opts)

Expand Down
27 changes: 26 additions & 1 deletion packages/supi/test/install/shamefullyFlatten.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import PnpmError from '@pnpm/error'
import { prepareEmpty } from '@pnpm/prepare'
import fs = require('fs')
import path = require('path')
import resolveLinkTarget = require('resolve-link-target')
import { addDependenciesToPackage, install, mutateModules } from 'supi'
import {
addDependenciesToPackage,
install,
mutateModules,
ShamefullyFlattenNotInLockfileDirectoryError,
} from 'supi'
import tape = require('tape')
import promisifyTape from 'tape-promise'
import { addDistTag, testDefaults } from '../utils'
Expand Down Expand Up @@ -252,3 +259,21 @@ test('should uninstall correctly peer dependencies', async (t) => {

t.throws(() => fs.lstatSync('node_modules/ajv-keywords'), Error, 'symlink to peer dependency is deleted')
})

test('shamefully-flatten: throw exception when executed on a project that uses an external lockfile', async (t: tape.Test) => {
prepareEmpty(t)
const lockfileDirectory = path.resolve('..')

let err!: ShamefullyFlattenNotInLockfileDirectoryError
try {
await addDependenciesToPackage({}, ['is-negative'], await testDefaults({ shamefullyFlatten: true, lockfileDirectory }))
t.fail('installation should have failed')
} catch (_err) {
err = _err
}

t.ok(err, 'error thrown')
t.equal(err.code, 'ERR_PNPM_SHAMEFULLY_FLATTEN_NOT_IN_LOCKFILE_DIR')
t.equal(err.shamefullyFlattenDirectory, process.cwd())
t.equal(err.lockfileDirectory, lockfileDirectory)
})

0 comments on commit 76d5249

Please sign in to comment.