Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 28 additions & 12 deletions lib/commands/pkg.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const { inspect } = require('node:util')
const { output } = require('proc-log')
const PackageJson = require('@npmcli/package-json')
const BaseCommand = require('../base-cmd.js')
Expand Down Expand Up @@ -56,25 +57,40 @@ class Pkg extends BaseCommand {
}

async get (args, { path, workspace }) {
this.npm.config.set('json', true)
const pkgJson = await PackageJson.load(path)
const json = this.npm.config.get('json')

let result = pkgJson.content
// filter out the newline/indent symbols from the package-json object
let result = JSON.parse(JSON.stringify(pkgJson.content))

if (args.length) {
result = new Queryable(result).query(args)
// in case there's only a single argument and a single result from the query just prints that one element to stdout.
// TODO(BREAKING_CHANGE): much like other places where we unwrap single item arrays this should go away.
// it makes the behavior unknown for users who don't already know the shape of the data.
if (Object.keys(result).length === 1 && args.length === 1) {
result = result[args]
result = new Queryable(result).query(args, { unwrapSingleItemArrays: false })
if (args.length === 1 && !json && args[0] in result) {
if (workspace) {
return output.standard(`${workspace} ${result[args[0]]}`)
}
return output.standard(result[args[0]])
}
}

// The display layer is responsible for calling JSON.stringify on the result
// TODO: https://github.com/npm/cli/issues/5508 a raw mode has been requested similar to jq -r.
// If that was added then this method should no longer set `json:true` all the time
output.buffer(workspace ? { [workspace]: result } : result)
if (json) {
output.buffer(workspace ? { [workspace]: result } : result)
} else {
for (let [f, d] of Object.entries(result)) {
d = inspect(d, {
showHidden: false,
depth: 5,
colors: this.npm.color,
maxArrayLength: null,
})

if (workspace) {
output.standard(`${workspace} ${f} = ${d}`)
} else {
output.standard(`${f} = ${d}`)
}
}
}
}

async set (args, { path }) {
Expand Down
1 change: 1 addition & 0 deletions lib/commands/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ class View extends BaseCommand {
const includeVersions = versions.length > 1

let includeFields
// TODO if we ask for two fields but only one existed we treat it as if we only asked for one field, this needs to be fixed
const res = versions.flatMap((v) => {
const fields = Object.entries(data[v])

Expand Down
36 changes: 14 additions & 22 deletions smoke-tests/tap-snapshots/test/index.js.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -344,36 +344,28 @@ exports[`test/index.js TAP basic npm pkg > should have expected pkg delete outpu
`

exports[`test/index.js TAP basic npm pkg > should have expected pkg get output 1`] = `
"ISC"
ISC
`

exports[`test/index.js TAP basic npm pkg > should have expected pkg set output 1`] = `

`

exports[`test/index.js TAP basic npm pkg > should print package.json contents 1`] = `
{
"name": "project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo /"Error: no test specified/" && exit 1",
"hello": "echo Hello"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs",
"dependencies": {
"abbrev": "^1.0.4"
},
"tap": {
"test-env": [
"LC_ALL=sk"
]
}
name = 'project'
version = '1.0.0'
description = ''
main = 'index.js'
scripts = {
test: 'echo "Error: no test specified" && exit 1',
hello: 'echo Hello'
}
keywords = []
author = ''
license = 'ISC'
type = 'commonjs'
dependencies = { abbrev: '^1.0.4' }
tap = { 'test-env': [ 'LC_ALL=sk' ] }
`

exports[`test/index.js TAP basic npm pkg set scripts > should have expected script added package.json result 1`] = `
Expand Down
220 changes: 220 additions & 0 deletions tap-snapshots/test/lib/commands/pkg.js.test.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/* IMPORTANT
* This snapshot file is auto-generated, but designed for humans.
* It should be checked into source control and tracked carefully.
* Re-generate by setting TAP_SNAPSHOT=1 and running tests.
* Make sure to inspect the output below. Do not ignore changes!
*/
'use strict'
exports[`test/lib/commands/pkg.js TAP delete delete multiple field > should delete multiple fields from package.json 1`] = `
Object {
"name": "foo",
}
`

exports[`test/lib/commands/pkg.js TAP delete delete nested field > should delete nested fields from package.json 1`] = `
Object {
"info": Object {
"foo": Object {
"bar": Array [
Object {},
],
},
},
"name": "foo",
"version": "1.0.0",
}
`

exports[`test/lib/commands/pkg.js TAP delete delete single field > should delete single field from package.json 1`] = `
Object {
"name": "foo",
}
`

exports[`test/lib/commands/pkg.js TAP fix > fixes package.json issues 1`] = `
Object {
"name": "foo",
"version": "1.1.1",
}
`

exports[`test/lib/commands/pkg.js TAP get array field > should print retrieved array field 1`] = `
[ 'index.js', 'cli.js' ]
`

exports[`test/lib/commands/pkg.js TAP get array item > should print retrieved array field 1`] = `
index.js
`

exports[`test/lib/commands/pkg.js TAP get get array nested items notation > should print json result containing matching results 1`] = `
contributors[0].name = 'Ruy'
contributors[1].name = 'Gar'
`

exports[`test/lib/commands/pkg.js TAP get json no args > should print package.json content 1`] = `
{
"name": "foo",
"version": "1.1.1"
}
`

exports[`test/lib/commands/pkg.js TAP get json with args > should print package.json content 1`] = `
{
"name": "foo"
}
`

exports[`test/lib/commands/pkg.js TAP get multiple arg > should print retrieved package.json fields 1`] = `
name = 'foo'
version = '1.1.1'
`

exports[`test/lib/commands/pkg.js TAP get multiple arg with empty value > should print retrieved package.json field regardless of empty value 1`] = `
name = 'foo'
author = ''
`

exports[`test/lib/commands/pkg.js TAP get multiple arg with only one arg existing > should print retrieved package.json field 1`] = `
name = 'foo'
`

exports[`test/lib/commands/pkg.js TAP get nested arg > node test.js 1`] = `
node test.js
`

exports[`test/lib/commands/pkg.js TAP get no args > should print package.json content 1`] = `
name = 'foo'
version = '1.1.1'
`

exports[`test/lib/commands/pkg.js TAP get non string > should print retrieved package.json field 1`] = `
{ '@npmcli/test': '*' }
`

exports[`test/lib/commands/pkg.js TAP get single arg > should print retrieved package.json field 1`] = `
1.1.1
`

exports[`test/lib/commands/pkg.js TAP set push to array syntax > should append to arrays using empty bracket syntax 1`] = `
Object {
"keywords": Array [
"foo",
"bar",
"baz",
],
"name": "foo",
"version": "1.1.1",
}
`

exports[`test/lib/commands/pkg.js TAP set set --json > should add fields to package.json 1`] = `
Object {
"description": "awesome",
"foo": Object {
"bar": Object {
"baz": "BAZ",
},
},
"name": "foo",
"private": true,
"tap": Object {
"timeout": 60,
},
"version": "1.1.1",
"workspaces": Array [
"packages/*",
],
}
`

exports[`test/lib/commands/pkg.js TAP set set = separate value > should add single field to package.json 1`] = `
Object {
"name": "foo",
"tap": Object {
"test-env": Array [
"LC_ALL=sk",
],
},
"version": "1.1.1",
}
`

exports[`test/lib/commands/pkg.js TAP set set multiple fields > should add single field to package.json 1`] = `
Object {
"bin": Object {
"foo": "foo.js",
},
"name": "foo",
"scripts": Object {
"test": "node test.js",
},
"version": "1.1.1",
}
`

exports[`test/lib/commands/pkg.js TAP set set single field > should add single field to package.json 1`] = `
Object {
"description": "Awesome stuff",
"name": "foo",
"version": "1.1.1",
}
`

exports[`test/lib/commands/pkg.js TAP single workspace multiple args > should only return info for one workspace 1`] = `
a name = 'a'
a version = '1.0.0'
`

exports[`test/lib/commands/pkg.js TAP single workspace single arg > should only return info for one workspace 1`] = `
a 1.0.0
`

exports[`test/lib/commands/pkg.js TAP workspaces get > should return expected result for configured workspaces 1`] = `
a name = 'a'
a version = '1.0.0'
b name = 'b'
b version = '1.2.3'
`

exports[`test/lib/commands/pkg.js TAP workspaces get json > should return expected json result for configured workspaces 1`] = `
{
"a": {
"name": "a",
"version": "1.0.0"
},
"b": {
"name": "b",
"version": "1.2.3"
}
}
`

exports[`test/lib/commands/pkg.js TAP workspaces set > should add field to workspace a 1`] = `
Object {
"funding": "http://example.com",
"name": "a",
"version": "1.0.0",
}
`

exports[`test/lib/commands/pkg.js TAP workspaces set > should add field to workspace b 1`] = `
Object {
"funding": "http://example.com",
"name": "b",
"version": "1.2.3",
}
`

exports[`test/lib/commands/pkg.js TAP workspaces set > should delete version field from workspace a 1`] = `
Object {
"funding": "http://example.com",
"name": "a",
}
`

exports[`test/lib/commands/pkg.js TAP workspaces set > should delete version field from workspace b 1`] = `
Object {
"funding": "http://example.com",
"name": "b",
}
`
Loading
Loading