pkg.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. const { output } = require('proc-log')
  2. const PackageJson = require('@npmcli/package-json')
  3. const BaseCommand = require('../base-cmd.js')
  4. const Queryable = require('../utils/queryable.js')
  5. class 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. static params = [
  17. 'force',
  18. 'json',
  19. 'workspace',
  20. 'workspaces',
  21. ]
  22. static workspaces = true
  23. static ignoreImplicitWorkspace = false
  24. async exec (args, { path = this.npm.localPrefix, workspace } = {}) {
  25. if (this.npm.global) {
  26. throw Object.assign(
  27. new Error(`There's no package.json file to manage on global mode`),
  28. { code: 'EPKGGLOBAL' }
  29. )
  30. }
  31. const [cmd, ..._args] = args
  32. switch (cmd) {
  33. case 'get':
  34. return this.get(_args, { path, workspace })
  35. case 'set':
  36. return this.set(_args, { path, workspace }).then(p => p.save())
  37. case 'delete':
  38. return this.delete(_args, { path, workspace }).then(p => p.save())
  39. case 'fix':
  40. return PackageJson.fix(path).then(p => p.save())
  41. default:
  42. throw this.usageError()
  43. }
  44. }
  45. async execWorkspaces (args) {
  46. await this.setWorkspaces()
  47. for (const [workspace, path] of this.workspaces.entries()) {
  48. await this.exec(args, { path, workspace })
  49. }
  50. }
  51. async get (args, { path, workspace }) {
  52. this.npm.config.set('json', true)
  53. const pkgJson = await PackageJson.load(path)
  54. let result = pkgJson.content
  55. if (args.length) {
  56. result = new Queryable(result).query(args)
  57. // in case there's only a single argument and a single result from the query just prints that one element to stdout.
  58. // TODO(BREAKING_CHANGE): much like other places where we unwrap single item arrays this should go away.
  59. // it makes the behavior unknown for users who don't already know the shape of the data.
  60. if (Object.keys(result).length === 1 && args.length === 1) {
  61. result = result[args]
  62. }
  63. }
  64. // The display layer is responsible for calling JSON.stringify on the result
  65. // TODO: https://github.com/npm/cli/issues/5508 a raw mode has been requested similar to jq -r.
  66. // If that was added then this method should no longer set `json:true` all the time
  67. output.buffer(workspace ? { [workspace]: result } : result)
  68. }
  69. async set (args, { path }) {
  70. const setError = () =>
  71. this.usageError('npm pkg set expects a key=value pair of args.')
  72. if (!args.length) {
  73. throw setError()
  74. }
  75. const force = this.npm.config.get('force')
  76. const json = this.npm.config.get('json')
  77. const pkgJson = await PackageJson.load(path)
  78. const q = new Queryable(pkgJson.content)
  79. for (const arg of args) {
  80. const [key, ...rest] = arg.split('=')
  81. const value = rest.join('=')
  82. if (!key || !value) {
  83. throw setError()
  84. }
  85. q.set(key, json ? JSON.parse(value) : value, { force })
  86. }
  87. return pkgJson.update(q.toJSON())
  88. }
  89. async delete (args, { path }) {
  90. const setError = () =>
  91. this.usageError('npm pkg delete expects key args.')
  92. if (!args.length) {
  93. throw setError()
  94. }
  95. const pkgJson = await PackageJson.load(path)
  96. const q = new Queryable(pkgJson.content)
  97. for (const key of args) {
  98. if (!key) {
  99. throw setError()
  100. }
  101. q.delete(key)
  102. }
  103. return pkgJson.update(q.toJSON())
  104. }
  105. }
  106. module.exports = Pkg