• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1const PackageJson = require('@npmcli/package-json')
2const BaseCommand = require('../base-command.js')
3const Queryable = require('../utils/queryable.js')
4
5class Pkg extends BaseCommand {
6  static description = 'Manages your package.json'
7  static name = 'pkg'
8  static usage = [
9    'set <key>=<value> [<key>=<value> ...]',
10    'get [<key> [<key> ...]]',
11    'delete <key> [<key> ...]',
12    'set [<array>[<index>].<key>=<value> ...]',
13    'set [<array>[].<key>=<value> ...]',
14    'fix',
15  ]
16
17  static params = [
18    'force',
19    'json',
20    'workspace',
21    'workspaces',
22  ]
23
24  static workspaces = true
25  static ignoreImplicitWorkspace = false
26
27  async exec (args, { prefix } = {}) {
28    if (!prefix) {
29      this.prefix = this.npm.localPrefix
30    } else {
31      this.prefix = prefix
32    }
33
34    if (this.npm.global) {
35      throw Object.assign(
36        new Error(`There's no package.json file to manage on global mode`),
37        { code: 'EPKGGLOBAL' }
38      )
39    }
40
41    const [cmd, ..._args] = args
42    switch (cmd) {
43      case 'get':
44        return this.get(_args)
45      case 'set':
46        return this.set(_args)
47      case 'delete':
48        return this.delete(_args)
49      case 'fix':
50        return this.fix(_args)
51      default:
52        throw this.usageError()
53    }
54  }
55
56  async execWorkspaces (args) {
57    await this.setWorkspaces()
58    const result = {}
59    for (const [workspaceName, workspacePath] of this.workspaces.entries()) {
60      this.prefix = workspacePath
61      result[workspaceName] = await this.exec(args, { prefix: workspacePath })
62    }
63    // when running in workspaces names, make sure to key by workspace
64    // name the results of each value retrieved in each ws
65    this.npm.output(JSON.stringify(result, null, 2))
66  }
67
68  async get (args) {
69    const pkgJson = await PackageJson.load(this.prefix)
70
71    const { content } = pkgJson
72    let result = !args.length && content
73
74    if (!result) {
75      const q = new Queryable(content)
76      result = q.query(args)
77
78      // in case there's only a single result from the query
79      // just prints that one element to stdout
80      if (Object.keys(result).length === 1) {
81        result = result[args]
82      }
83    }
84
85    // only outputs if not running with workspaces config,
86    // in case you're retrieving info for workspaces the pkgWorkspaces
87    // will handle the output to make sure it get keyed by ws name
88    if (!this.npm.config.get('workspaces')) {
89      this.npm.output(JSON.stringify(result, null, 2))
90    }
91
92    return result
93  }
94
95  async set (args) {
96    const setError = () =>
97      this.usageError('npm pkg set expects a key=value pair of args.')
98
99    if (!args.length) {
100      throw setError()
101    }
102
103    const force = this.npm.config.get('force')
104    const json = this.npm.config.get('json')
105    const pkgJson = await PackageJson.load(this.prefix)
106    const q = new Queryable(pkgJson.content)
107    for (const arg of args) {
108      const [key, ...rest] = arg.split('=')
109      const value = rest.join('=')
110      if (!key || !value) {
111        throw setError()
112      }
113
114      q.set(key, json ? JSON.parse(value) : value, { force })
115    }
116
117    pkgJson.update(q.toJSON())
118    await pkgJson.save()
119  }
120
121  async delete (args) {
122    const setError = () =>
123      this.usageError('npm pkg delete expects key args.')
124
125    if (!args.length) {
126      throw setError()
127    }
128
129    const pkgJson = await PackageJson.load(this.prefix)
130    const q = new Queryable(pkgJson.content)
131    for (const key of args) {
132      if (!key) {
133        throw setError()
134      }
135
136      q.delete(key)
137    }
138
139    pkgJson.update(q.toJSON())
140    await pkgJson.save()
141  }
142
143  async fix () {
144    const pkgJson = await PackageJson.fix(this.prefix)
145    await pkgJson.save()
146  }
147}
148
149module.exports = Pkg
150