Skip to content

Commit f9d161f

Browse files
committed
3rd attempt
1 parent 91a6104 commit f9d161f

File tree

5 files changed

+308
-284
lines changed

5 files changed

+308
-284
lines changed

lib/base-cmd.js

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ class BaseCommand {
2222
const { description, usage = [''], name, params } = this
2323

2424
if (this.definitions) {
25-
const cmdDefinitions = this.definitions
26-
this.definitions = { ...globalDefinitions, ...cmdDefinitions }
25+
this.definitions = this.definitions
2726
} else {
2827
this.definitions = globalDefinitions
2928
}
29+
30+
const definitionsPool = { ...globalDefinitions, ...this.definitions }
31+
3032
const fullUsage = [
3133
`${description}`,
3234
'',
@@ -42,14 +44,14 @@ class BaseCommand {
4244
if (seenExclusive.has(param)) {
4345
continue
4446
}
45-
const exclusive = this.definitions[param]?.exclusive
46-
let paramUsage = this.definitions[param]?.usage || ''
47+
const exclusive = definitionsPool[param]?.exclusive
48+
let paramUsage = definitionsPool[param]?.usage
4749
if (exclusive) {
4850
const exclusiveParams = [paramUsage]
4951
seenExclusive.add(param)
5052
for (const e of exclusive) {
5153
seenExclusive.add(e)
52-
exclusiveParams.push(this.definitions[e].usage)
54+
exclusiveParams.push(definitionsPool[e].usage)
5355
}
5456
paramUsage = `${exclusiveParams.join('|')}`
5557
}
@@ -97,21 +99,13 @@ class BaseCommand {
9799

98100
get config () {
99101
// Return command-specific config if it exists, otherwise use npm's config
100-
return this._config || this.npm.config
101-
}
102-
103-
set config (value) {
104-
this._config = value
102+
return this.npm.config
105103
}
106104

107105
get name () {
108106
return this.constructor.name
109107
}
110108

111-
get definitions () {
112-
return this.constructor.definitions
113-
}
114-
115109
get description () {
116110
return this.constructor.description
117111
}

lib/npm.js

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,9 @@ class Npm {
6868
this.#npmRoot = npmRoot
6969
this.#argv = argv
7070
this.#excludeNpmCwd = excludeNpmCwd
71-
this.config = this.createConfig(globalDefinitions)
72-
}
73-
74-
createConfig (definitions) {
75-
return new Config({
71+
this.config = new Config({
7672
npmPath: this.#npmRoot,
77-
definitions,
73+
definitions: globalDefinitions,
7874
flatten,
7975
nerfDarts,
8076
shorthands,
@@ -235,16 +231,12 @@ class Npm {
235231
process.env.npm_command = this.command
236232
}
237233

238-
if (Command.definitions === globalDefinitions) {
239-
this.config.warn()
234+
if (!Command.definitions || Command.definitions === globalDefinitions) {
235+
this.config.logWarnings()
240236
} else {
241-
const _config = this.config.clone({
242-
definitions: { ...globalDefinitions, ...Command.definitions },
243-
shouldSetEnvs: true,
244-
})
245-
await _config.load()
246-
_config.warn()
247-
command._config = _config
237+
this.config.loadCommand(Command.definitions)
238+
this.config.logWarnings()
239+
this.config.warn = true
248240
}
249241

250242
if (this.config.get('usage')) {

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ silly logfile done cleaning log files
134134
verbose stack Error: The developer of this package has specified the following through devEngines
135135
verbose stack Invalid devEngines.runtime
136136
verbose stack Invalid name "nondescript" does not match "node" for "runtime"
137-
verbose stack at Install.checkDevEngines ({CWD}/lib/base-cmd.js:205:27)
138-
verbose stack at MockNpm.#exec ({CWD}/lib/npm.js:267:7)
139-
verbose stack at MockNpm.exec ({CWD}/lib/npm.js:216:9)
137+
verbose stack at Install.checkDevEngines ({CWD}/lib/base-cmd.js:200:27)
138+
verbose stack at MockNpm.#exec ({CWD}/lib/npm.js:264:7)
139+
verbose stack at MockNpm.exec ({CWD}/lib/npm.js:212:9)
140140
error code EBADDEVENGINES
141141
error EBADDEVENGINES The developer of this package has specified the following through devEngines
142142
error EBADDEVENGINES Invalid devEngines.runtime
@@ -199,9 +199,9 @@ warn EBADDEVENGINES }
199199
verbose stack Error: The developer of this package has specified the following through devEngines
200200
verbose stack Invalid devEngines.runtime
201201
verbose stack Invalid name "nondescript" does not match "node" for "runtime"
202-
verbose stack at Install.checkDevEngines ({CWD}/lib/base-cmd.js:205:27)
203-
verbose stack at MockNpm.#exec ({CWD}/lib/npm.js:267:7)
204-
verbose stack at MockNpm.exec ({CWD}/lib/npm.js:216:9)
202+
verbose stack at Install.checkDevEngines ({CWD}/lib/base-cmd.js:200:27)
203+
verbose stack at MockNpm.#exec ({CWD}/lib/npm.js:264:7)
204+
verbose stack at MockNpm.exec ({CWD}/lib/npm.js:212:9)
205205
error code EBADDEVENGINES
206206
error EBADDEVENGINES The developer of this package has specified the following through devEngines
207207
error EBADDEVENGINES Invalid devEngines.runtime
@@ -225,9 +225,9 @@ silly logfile done cleaning log files
225225
verbose stack Error: The developer of this package has specified the following through devEngines
226226
verbose stack Invalid devEngines.runtime
227227
verbose stack Invalid name "nondescript" does not match "node" for "runtime"
228-
verbose stack at Install.checkDevEngines ({CWD}/lib/base-cmd.js:205:27)
229-
verbose stack at MockNpm.#exec ({CWD}/lib/npm.js:267:7)
230-
verbose stack at MockNpm.exec ({CWD}/lib/npm.js:216:9)
228+
verbose stack at Install.checkDevEngines ({CWD}/lib/base-cmd.js:200:27)
229+
verbose stack at MockNpm.#exec ({CWD}/lib/npm.js:264:7)
230+
verbose stack at MockNpm.exec ({CWD}/lib/npm.js:212:9)
231231
error code EBADDEVENGINES
232232
error EBADDEVENGINES The developer of this package has specified the following through devEngines
233233
error EBADDEVENGINES Invalid devEngines.runtime

test/lib/npm.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const { time } = require('proc-log')
55
const { load: loadMockNpm } = require('../fixtures/mock-npm.js')
66
const mockGlobals = require('@npmcli/mock-globals')
77
const { commands } = require('../../lib/utils/cmd-list.js')
8+
const BaseCommand = require('../../lib/base-cmd.js')
89

910
t.test('not yet loaded', async t => {
1011
const { npm, logs } = await loadMockNpm(t, { load: false })
@@ -567,3 +568,69 @@ t.test('print usage if non-command param provided', async t => {
567568
t.match(joinedOutput(), 'Unknown command: "tset"')
568569
t.match(joinedOutput(), 'Did you mean this?')
569570
})
571+
572+
async function testCommandDefinitions (t, { defaultValue, outputValue, type, flags }) {
573+
const path = require('node:path')
574+
575+
// Create a temporary command file
576+
const tsetPath = path.join(__dirname, '../../lib/commands/tset.js')
577+
const tsetContent = `
578+
const Definition = require('@npmcli/config/lib/definitions/definition.js')
579+
const BaseCommand = require('../base-cmd.js')
580+
const { output } = require('proc-log')
581+
const { flatten } = require('@npmcli/config/lib/definitions/index.js')
582+
583+
module.exports = class TestCommand extends BaseCommand {
584+
static description = 'A test command'
585+
static name = 'tset'
586+
static definitions = {
587+
say: new Definition('say', {
588+
default: ${defaultValue},
589+
type: ${type},
590+
description: 'say',
591+
flatten,
592+
}),
593+
}
594+
595+
async exec () {
596+
const say = this.npm.config.get('say')
597+
output.standard(say)
598+
}
599+
}
600+
`
601+
fs.writeFileSync(tsetPath, tsetContent)
602+
t.teardown(() => {
603+
try {
604+
fs.unlinkSync(tsetPath)
605+
delete require.cache[tsetPath]
606+
} catch (e) {
607+
// ignore
608+
}
609+
})
610+
611+
const mockCmdList = require('../../lib/utils/cmd-list.js')
612+
const { npm, joinedOutput } = await loadMockNpm(t, {
613+
mocks: {
614+
'{LIB}/utils/cmd-list.js': {
615+
...mockCmdList,
616+
commands: [...mockCmdList.commands, 'tset'],
617+
deref: (c) => c === 'tset' ? 'tset' : mockCmdList.deref(c),
618+
},
619+
},
620+
})
621+
622+
// Now you can execute the mocked command
623+
await npm.exec('tset', flags || [])
624+
625+
t.match(joinedOutput(), outputValue)
626+
}
627+
628+
const stack = {
629+
boolean_default: (t) => testCommandDefinitions(t, { type: 'Boolean', defaultValue: 'false', outputValue: 'false' }),
630+
string_default: (t) => testCommandDefinitions(t, { type: 'String', defaultValue: `'meow'`, outputValue: 'meow' }),
631+
string_flag: (t) => testCommandDefinitions(t, { type: 'String', defaultValue: `'meow'`, outputValue: 'woof', flags: ['--say=woof'] }),
632+
}
633+
634+
Object.entries(stack).forEach(([name, fn]) => {
635+
t.test(name, fn)
636+
})

0 commit comments

Comments
 (0)