Skip to content

Commit e40454c

Browse files
authored
fix(view): dont unwrap arrays in json mode (#7506)
1 parent 6f64148 commit e40454c

File tree

4 files changed

+72
-12
lines changed

4 files changed

+72
-12
lines changed

lib/commands/view.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ class View extends BaseCommand {
175175
}
176176

177177
async getData (pkg, args) {
178+
const json = this.npm.config.get('json')
178179
const opts = {
179180
...this.npm.flatOptions,
180181
preferOnline: true,
@@ -228,7 +229,12 @@ class View extends BaseCommand {
228229
delete versions[v].readme
229230
}
230231

231-
data.push(showFields(pckmnt, versions[v], arg))
232+
data.push(showFields({
233+
data: pckmnt,
234+
version: versions[v],
235+
fields: arg,
236+
json,
237+
}))
232238
})
233239
}
234240
})
@@ -242,11 +248,7 @@ class View extends BaseCommand {
242248
throw er
243249
}
244250

245-
if (
246-
!this.npm.config.get('json') &&
247-
args.length === 1 &&
248-
args[0] === ''
249-
) {
251+
if (!json && args.length === 1 && args[0] === '') {
250252
pckmnt.version = version
251253
}
252254

@@ -432,7 +434,7 @@ function reducer (acc, cur) {
432434
}
433435

434436
// return whatever was printed
435-
function showFields (data, version, fields) {
437+
function showFields ({ data, version, fields, json }) {
436438
const o = {}
437439
;[data, version].forEach((s) => {
438440
Object.keys(s).forEach((k) => {
@@ -441,7 +443,7 @@ function showFields (data, version, fields) {
441443
})
442444

443445
const queryable = new Queryable(o)
444-
const s = queryable.query(fields)
446+
const s = queryable.query(fields, { unwrapSingleItemArrays: !json })
445447
const res = { [version.version]: s }
446448

447449
if (s) {

lib/utils/queryable.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ const parseKeys = key => {
8383
return res
8484
}
8585

86-
const getter = ({ data, key }) => {
86+
const getter = ({ data, key }, { unwrapSingleItemArrays = true } = {}) => {
8787
// keys are a list in which each entry represents the name of
8888
// a property that should be walked through the object in order to
8989
// return the final found value
@@ -122,7 +122,7 @@ const getter = ({ data, key }) => {
122122

123123
// these are some legacy expectations from
124124
// the old API consumed by lib/view.js
125-
if (Array.isArray(_data) && _data.length <= 1) {
125+
if (unwrapSingleItemArrays && Array.isArray(_data) && _data.length <= 1) {
126126
_data = _data[0]
127127
}
128128

@@ -243,7 +243,7 @@ class Queryable {
243243
this.#data = obj
244244
}
245245

246-
query (queries) {
246+
query (queries, opts) {
247247
// this ugly interface here is meant to be a compatibility layer
248248
// with the legacy API lib/view.js is consuming, if at some point
249249
// we refactor that command then we can revisit making this nicer
@@ -255,7 +255,7 @@ class Queryable {
255255
getter({
256256
data: this.#data,
257257
key: query,
258-
})
258+
}, opts)
259259

260260
if (Array.isArray(queries)) {
261261
let res = {}

tap-snapshots/test/lib/commands/view.js.test.cjs

+19
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,25 @@ dist-tags:
300300
published over a year from now
301301
`
302302

303+
exports[`test/lib/commands/view.js TAP package with single version full json > must match snapshot 1`] = `
304+
{
305+
"_id": "single-version",
306+
"name": "single-version",
307+
"dist-tags": {
308+
"latest": "1.0.0"
309+
},
310+
"versions": [
311+
"1.0.0"
312+
],
313+
"version": "1.0.0",
314+
"dist": {
315+
"shasum": "123",
316+
"tarball": "http://hm.single-version.com/1.0.0.tgz",
317+
"fileCount": 1
318+
}
319+
}
320+
`
321+
303322
exports[`test/lib/commands/view.js TAP specific field names array field - 1 element > must match snapshot 1`] = `
304323
claudia
305324
`

test/lib/commands/view.js

+39
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,24 @@ const packument = (nv, opts) => {
252252
},
253253
},
254254
},
255+
'single-version': {
256+
_id: 'single-version',
257+
name: 'single-version',
258+
'dist-tags': {
259+
latest: '1.0.0',
260+
},
261+
versions: {
262+
'1.0.0': {
263+
name: 'single-version',
264+
version: '1.0.0',
265+
dist: {
266+
shasum: '123',
267+
tarball: 'http://hm.single-version.com/1.0.0.tgz',
268+
fileCount: 1,
269+
},
270+
},
271+
},
272+
},
255273
}
256274
if (nv.type === 'git') {
257275
return mocks[nv.hosted.project]
@@ -357,6 +375,27 @@ t.test('package with --json and no versions', async t => {
357375
t.equal(joinedOutput(), '', 'no info to display')
358376
})
359377

378+
t.test('package with single version', async t => {
379+
t.test('full json', async t => {
380+
const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } })
381+
await view.exec(['single-version'])
382+
t.matchSnapshot(joinedOutput())
383+
})
384+
385+
t.test('json and versions arg', async t => {
386+
const { view, joinedOutput } = await loadMockNpm(t, { config: { json: true } })
387+
await view.exec(['single-version', 'versions'])
388+
const parsed = JSON.parse(joinedOutput())
389+
t.strictSame(parsed, ['1.0.0'], 'does not unwrap single item arrays in json')
390+
})
391+
392+
t.test('no json and versions arg', async t => {
393+
const { view, joinedOutput } = await loadMockNpm(t, { config: { json: false } })
394+
await view.exec(['single-version', 'versions'])
395+
t.strictSame(joinedOutput(), '1.0.0', 'unwraps single item arrays in basic mode')
396+
})
397+
})
398+
360399
t.test('package in cwd', async t => {
361400
const prefixDir = {
362401
'package.json': JSON.stringify({

0 commit comments

Comments
 (0)