Skip to content

Commit

Permalink
feat(pack): add workspace support
Browse files Browse the repository at this point in the history
  • Loading branch information
wraithgar committed Apr 6, 2021
1 parent dedb9c8 commit 98450d9
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 4 deletions.
23 changes: 22 additions & 1 deletion lib/pack.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const log = require('npmlog')
const pacote = require('pacote')
const libpack = require('libnpmpack')
const npa = require('npm-package-arg')
const getWorkspaces = require('./workspaces/get-workspaces.js')

const { getContents, logTar } = require('./utils/tar.js')

Expand All @@ -23,7 +24,7 @@ class Pack extends BaseCommand {

/* istanbul ignore next - see test/lib/load-all-commands.js */
static get params () {
return ['dry-run']
return ['dry-run', 'workspace', 'workspaces']
}

/* istanbul ignore next - see test/lib/load-all-commands.js */
Expand All @@ -35,6 +36,10 @@ class Pack extends BaseCommand {
this.pack(args).then(() => cb()).catch(cb)
}

execWorkspaces (args, filters, cb) {
this.packWorkspaces(args, filters).then(() => cb()).catch(cb)
}

async pack (args) {
if (args.length === 0)
args = ['.']
Expand Down Expand Up @@ -62,5 +67,21 @@ class Pack extends BaseCommand {
this.npm.output(tar.filename.replace(/^@/, '').replace(/\//, '-'))
}
}

async packWorkspaces (args, filters) {
// If they either ask for nothing, or explicitly include '.' in the args,
// we effectively translate that into each workspace requested

const useWorkspaces = args.length === 0 || args.includes('.')

if (!useWorkspaces) {
this.npm.log.warn('Ignoring workspaces for specified package(s)')
return this.pack(args)
}

const workspaces =
await getWorkspaces(filters, { path: this.npm.localPrefix })
return this.pack([...workspaces.values(), ...args.filter(a => a !== '.')])
}
}
module.exports = Pack
2 changes: 1 addition & 1 deletion lib/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class View extends BaseCommand {

const local = /^\.@/.test(pkg) || pkg === '.'
if (!local) {
this.npm.log.warn('Ignoring workspaces for remote package')
this.npm.log.warn('Ignoring workspaces for specified package(s)')
return this.view([pkg, ...args])
}
let wholePackument = false
Expand Down
2 changes: 1 addition & 1 deletion tap-snapshots/test-lib-utils-npm-usage.js-TAP.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ All commands:
npm pack [[<@scope>/]<pkg>...]
Options:
[--dry-run]
[--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
Run "npm help pack" for more info
Expand Down
2 changes: 1 addition & 1 deletion tap-snapshots/test-lib-view.js-TAP.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ dist-tags:
`

exports[`test/lib/view.js TAP workspaces remote package name > must match snapshot 1`] = `
Ignoring workspaces for remote package
Ignoring workspaces for specified package(s)
`

exports[`test/lib/view.js TAP workspaces remote package name > must match snapshot 2`] = `
Expand Down
14 changes: 14 additions & 0 deletions test/fixtures/mock-npm.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,24 @@
// npm.config You still need a separate flatOptions but this is the first step
// to eventually just using npm itself

const mockLog = {
clearProgress: () => {},
disableProgress: () => {},
enableProgress: () => {},
http: () => {},
info: () => {},
levels: [],
notice: () => {},
pause: () => {},
silly: () => {},
verbose: () => {},
warn: () => {},
}
const mockNpm = (base = {}) => {
const config = base.config || {}
const flatOptions = base.flatOptions || {}
return {
log: mockLog,
...base,
flatOptions,
config: {
Expand Down
103 changes: 103 additions & 0 deletions test/lib/pack.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const t = require('tap')
const requireInject = require('require-inject')
const mockNpm = require('../fixtures/mock-npm')
const pacote = require('pacote')

const OUTPUT = []
const output = (...msg) => OUTPUT.push(msg)
Expand All @@ -11,6 +12,16 @@ const libnpmpack = async (spec, opts) => {

return ''
}
const mockPacote = {
manifest: (spec) => {
if (spec.type === 'directory')
return pacote.manifest(spec)
return {
name: spec.name || 'test-package',
version: spec.version || '1.0.0-test',
}
},
}

t.afterEach(cb => {
OUTPUT.length = 0
Expand Down Expand Up @@ -152,3 +163,95 @@ t.test('should log pack contents', (t) => {
t.end()
})
})

t.test('workspaces', (t) => {
const testDir = t.testdir({
'package.json': JSON.stringify({
name: 'workspaces-test',
version: '1.0.0',
workspaces: ['workspace-a', 'workspace-b'],
}, null, 2),
'workspace-a': {
'package.json': JSON.stringify({
name: 'workspace-a',
version: '1.0.0',
}),
},
'workspace-b': {
'package.json': JSON.stringify({
name: 'workspace-b',
version: '1.0.0',
}),
},
})
const Pack = requireInject('../../lib/pack.js', {
libnpmpack,
pacote: mockPacote,
npmlog: {
notice: () => {},
showProgress: () => {},
clearProgress: () => {},
},
})
const npm = mockNpm({
localPrefix: testDir,
config: {
unicode: false,
json: false,
'dry-run': false,
},
output,
})
const pack = new Pack(npm)

t.test('all workspaces', (t) => {
pack.execWorkspaces([], [], er => {
if (er)
throw er

t.strictSame(OUTPUT, [
['workspace-a-1.0.0.tgz'],
['workspace-b-1.0.0.tgz'],
])
t.end()
})
})

t.test('all workspaces, `.` first arg', (t) => {
pack.execWorkspaces(['.'], [], er => {
if (er)
throw er

t.strictSame(OUTPUT, [
['workspace-a-1.0.0.tgz'],
['workspace-b-1.0.0.tgz'],
])
t.end()
})
})

t.test('one workspace', (t) => {
pack.execWorkspaces([], ['workspace-a'], er => {
if (er)
throw er

t.strictSame(OUTPUT, [
['workspace-a-1.0.0.tgz'],
])
t.end()
})
})

t.test('specific package', (t) => {
pack.execWorkspaces(['abbrev'], [], er => {
if (er)
throw er

t.strictSame(OUTPUT, [
['abbrev-1.0.0-test.tgz'],
])
t.end()
})
})
t.end()
})

0 comments on commit 98450d9

Please sign in to comment.