From 89245656ad3473cbc709daa6fd9e99d76714ce29 Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Fri, 13 Oct 2023 12:27:41 -0400 Subject: [PATCH 01/14] Discern result key from overlapping value --- lib/commands/pkg.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/commands/pkg.js b/lib/commands/pkg.js index 29bd4e89cc3c1..51f8edcefa6a4 100644 --- a/lib/commands/pkg.js +++ b/lib/commands/pkg.js @@ -76,9 +76,18 @@ class Pkg extends BaseCommand { result = q.query(args) // in case there's only a single result from the query - // just prints that one element to stdout + // just prints that one element to stdout taking into + // consideration that one of the args supplied may + // have not had a returned value from the query + // + // e.g. npm pkg get name author would previously + // return undefined because + // args=['name', 'author'] and the query + // result was { name: '...' } if (Object.keys(result).length === 1) { - result = result[args] + // find the overlapping value in result and args + const argKey = Object.keys(result).find((key) => args.includes(key)) + result = result[argKey] } } From 61f7266827be787ab30ff0c677a160d8b3871b29 Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Fri, 13 Oct 2023 12:28:15 -0400 Subject: [PATCH 02/14] Add test for multiple args and empty value --- test/lib/commands/pkg.js | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/lib/commands/pkg.js b/test/lib/commands/pkg.js index e915ef942410f..f47722eb7d15a 100644 --- a/test/lib/commands/pkg.js +++ b/test/lib/commands/pkg.js @@ -83,6 +83,47 @@ t.test('get single arg', async t => { ) }) +t.test('get multiple arg', async t => { + const { pkg, OUTPUT } = await mockNpm(t, { + prefixDir: { + 'package.json': JSON.stringify({ + name: 'foo', + version: '1.1.1', + }), + }, + }) + + await pkg('get', 'name', 'version') + + t.strictSame( + JSON.parse(OUTPUT()), + { + name: 'foo', + version: '1.1.1', + }, + 'should print retrieved package.json field' + ) +}) + +t.test('get multiple arg with empty value', async t => { + const { pkg, OUTPUT } = await mockNpm(t, { + prefixDir: { + 'package.json': JSON.stringify({ + name: 'foo', + author: '', + }), + }, + }) + + await pkg('get', 'name', 'author') + + t.strictSame( + JSON.parse(OUTPUT()), + 'foo', + 'should print retrieved package.json field' + ) +}) + t.test('get nested arg', async t => { const { pkg, OUTPUT } = await mockNpm(t, { prefixDir: { From a1963b069c10518bc91aa5f606eff1a53c5a5ed8 Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Fri, 13 Oct 2023 15:53:25 -0400 Subject: [PATCH 03/14] Revert overlap check --- lib/commands/pkg.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/lib/commands/pkg.js b/lib/commands/pkg.js index 51f8edcefa6a4..29bd4e89cc3c1 100644 --- a/lib/commands/pkg.js +++ b/lib/commands/pkg.js @@ -76,18 +76,9 @@ class Pkg extends BaseCommand { result = q.query(args) // in case there's only a single result from the query - // just prints that one element to stdout taking into - // consideration that one of the args supplied may - // have not had a returned value from the query - // - // e.g. npm pkg get name author would previously - // return undefined because - // args=['name', 'author'] and the query - // result was { name: '...' } + // just prints that one element to stdout if (Object.keys(result).length === 1) { - // find the overlapping value in result and args - const argKey = Object.keys(result).find((key) => args.includes(key)) - result = result[argKey] + result = result[args] } } From 7e8639fe275993d41daedb1a167f990106c1c839 Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Fri, 13 Oct 2023 15:54:18 -0400 Subject: [PATCH 04/14] Return empty string if prop exists and undef --- lib/utils/queryable.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/utils/queryable.js b/lib/utils/queryable.js index 5ddcf636e8383..0913b1bfd74eb 100644 --- a/lib/utils/queryable.js +++ b/lib/utils/queryable.js @@ -113,12 +113,14 @@ const getter = ({ data, key }) => { } else { // if can't find any more values, it means it's just over // and there's nothing to return - if (!_data[k]) { + if (Object.hasOwn(_data, k) && !_data[k]) { + _data = '' + } else if (!_data[k]) { return undefined + } else { + // otherwise sets the next value + _data = _data[k] } - - // otherwise sets the next value - _data = _data[k] } label += k From 49e9e4466da2f0ff68f9b23b900dc13974887aa1 Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Fri, 13 Oct 2023 15:55:30 -0400 Subject: [PATCH 05/14] Modify error message for accuracy --- test/lib/commands/pkg.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/lib/commands/pkg.js b/test/lib/commands/pkg.js index f47722eb7d15a..f3401bde5226a 100644 --- a/test/lib/commands/pkg.js +++ b/test/lib/commands/pkg.js @@ -119,8 +119,11 @@ t.test('get multiple arg with empty value', async t => { t.strictSame( JSON.parse(OUTPUT()), - 'foo', - 'should print retrieved package.json field' + { + name: 'foo', + author: '', + }, + 'should print retrieved package.json field regardless of empty value' ) }) From c6544519ba55a16e26a1f61013836e4a456dc78f Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Fri, 13 Oct 2023 15:55:47 -0400 Subject: [PATCH 06/14] Add view test for empty value --- test/lib/commands/view.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/lib/commands/view.js b/test/lib/commands/view.js index ca07ef9eec2ff..bb6b4ec04fa3d 100644 --- a/test/lib/commands/view.js +++ b/test/lib/commands/view.js @@ -425,6 +425,11 @@ t.test('specific field names', async t => { await view.exec(['yellow@1.x.x', 'maintainers.name']) t.matchSnapshot(outputs.join('\n')) }) + + t.test('fields with empty values', async t => { + await view.exec(['yellow@1.x.x', 'empty']) + t.matchSnapshot(outputs.join('\n')) + }) }) t.test('throw error if global mode', async t => { From e808248e17603715d7f0cabad876514e689f8d64 Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Fri, 13 Oct 2023 15:56:07 -0400 Subject: [PATCH 07/14] Add empty property to yellow --- test/lib/commands/view.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/lib/commands/view.js b/test/lib/commands/view.js index bb6b4ec04fa3d..18c75bf24a2f1 100644 --- a/test/lib/commands/view.js +++ b/test/lib/commands/view.js @@ -101,6 +101,7 @@ const packument = (nv, opts) => { email: 'foo@yellow.com', twitter: 'foo', }, + empty: '', readme: 'a very useful readme', versions: { '1.0.0': { From 6bf0fff6a088292be9209c45928303ae2908131d Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Mon, 16 Oct 2023 10:23:17 -0400 Subject: [PATCH 08/14] Remove version tag from test --- test/lib/commands/view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/commands/view.js b/test/lib/commands/view.js index 18c75bf24a2f1..a99c8d6242212 100644 --- a/test/lib/commands/view.js +++ b/test/lib/commands/view.js @@ -428,7 +428,7 @@ t.test('specific field names', async t => { }) t.test('fields with empty values', async t => { - await view.exec(['yellow@1.x.x', 'empty']) + await view.exec(['yellow', 'empty']) t.matchSnapshot(outputs.join('\n')) }) }) From d017ecb2261b0f18f6d2ee1a807d491e76edf086 Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Mon, 16 Oct 2023 10:23:48 -0400 Subject: [PATCH 09/14] Update view snapshot --- tap-snapshots/test/lib/commands/view.js.test.cjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tap-snapshots/test/lib/commands/view.js.test.cjs b/tap-snapshots/test/lib/commands/view.js.test.cjs index d5b7a3b4a7906..5248d439afad9 100644 --- a/tap-snapshots/test/lib/commands/view.js.test.cjs +++ b/tap-snapshots/test/lib/commands/view.js.test.cjs @@ -315,6 +315,10 @@ maintainers[0].name = 'claudia' maintainers[1].name = 'isaacs' ` +exports[`test/lib/commands/view.js TAP specific field names fields with empty values > must match snapshot 1`] = ` + +` + exports[`test/lib/commands/view.js TAP specific field names maintainers with email > must match snapshot 1`] = ` maintainers = [ { name: 'claudia', email: 'c@yellow.com', twitter: 'cyellow' }, From 4ed95aa7e728cb9d7de9a6f76415209fec88d2e7 Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Mon, 16 Oct 2023 12:27:17 -0400 Subject: [PATCH 10/14] Check for explicit boolean value --- lib/utils/queryable.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/utils/queryable.js b/lib/utils/queryable.js index 0913b1bfd74eb..70e0afee54662 100644 --- a/lib/utils/queryable.js +++ b/lib/utils/queryable.js @@ -111,16 +111,14 @@ const getter = ({ data, key }) => { }, {}) return _data } else { - // if can't find any more values, it means it's just over - // and there's nothing to return - if (Object.hasOwn(_data, k) && !_data[k]) { - _data = '' - } else if (!_data[k]) { - return undefined - } else { - // otherwise sets the next value - _data = _data[k] - } + const value = _data[k] + if (typeof value === 'boolean' || (value === '' && Object.hasOwn(_data, k))) { + _data = value + } else if (value === undefined) { + return undefined + } else { + _data = _data[k] + } } label += k From 8fb8ddf23fa5792fb0a452bc53e9fe0b7a8d4d21 Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Mon, 16 Oct 2023 12:35:44 -0400 Subject: [PATCH 11/14] Return value instead of _data[k] --- lib/utils/queryable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/queryable.js b/lib/utils/queryable.js index 70e0afee54662..99ea1e887cbaf 100644 --- a/lib/utils/queryable.js +++ b/lib/utils/queryable.js @@ -117,7 +117,7 @@ const getter = ({ data, key }) => { } else if (value === undefined) { return undefined } else { - _data = _data[k] + _data = value } } From 6fdc97f85be5b849b4d96cb21eb4b45e280a9a42 Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Mon, 16 Oct 2023 12:56:53 -0400 Subject: [PATCH 12/14] Simplify check to only return undefined --- lib/utils/queryable.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/utils/queryable.js b/lib/utils/queryable.js index 99ea1e887cbaf..19fba0f7a68a3 100644 --- a/lib/utils/queryable.js +++ b/lib/utils/queryable.js @@ -111,14 +111,11 @@ const getter = ({ data, key }) => { }, {}) return _data } else { - const value = _data[k] - if (typeof value === 'boolean' || (value === '' && Object.hasOwn(_data, k))) { - _data = value - } else if (value === undefined) { - return undefined - } else { - _data = value - } + const value = _data[k] + if (value === undefined) { + return undefined + } + _data = value } label += k From 1c71e20c0595b129cfcdc32832349f7b4b56b365 Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:00:48 -0400 Subject: [PATCH 13/14] Remove temporary var value --- lib/utils/queryable.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/utils/queryable.js b/lib/utils/queryable.js index 19fba0f7a68a3..f59fbddeb9f33 100644 --- a/lib/utils/queryable.js +++ b/lib/utils/queryable.js @@ -111,11 +111,10 @@ const getter = ({ data, key }) => { }, {}) return _data } else { - const value = _data[k] - if (value === undefined) { + if (_data[k] === undefined) { return undefined } - _data = value + _data = _data[k] } label += k From b4ea6606eb649697c7841d2561fe7672d62f40be Mon Sep 17 00:00:00 2001 From: Aaron <2738518+NeonArray@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:38:03 -0400 Subject: [PATCH 14/14] Replace undefined check with hasOwn --- lib/utils/queryable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/queryable.js b/lib/utils/queryable.js index f59fbddeb9f33..69621d928e8dd 100644 --- a/lib/utils/queryable.js +++ b/lib/utils/queryable.js @@ -111,7 +111,7 @@ const getter = ({ data, key }) => { }, {}) return _data } else { - if (_data[k] === undefined) { + if (!Object.hasOwn(_data, k)) { return undefined } _data = _data[k]