Skip to content

Commit 19214b5

Browse files
committed
deps: @npmcli/[email protected]
1 parent f53e6ff commit 19214b5

File tree

6 files changed

+439
-40
lines changed

6 files changed

+439
-40
lines changed

DEPENDENCIES.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ graph LR;
214214
npmcli-mock-registry-->npmcli-template-oss["@npmcli/template-oss"];
215215
npmcli-mock-registry-->pacote;
216216
npmcli-package-json-->json-parse-even-better-errors;
217+
npmcli-package-json-->normalize-package-data;
218+
npmcli-package-json-->npm-normalize-package-bin;
217219
npmcli-run-script-->npmcli-node-gyp["@npmcli/node-gyp"];
218220
npmcli-run-script-->npmcli-promise-spawn["@npmcli/promise-spawn"];
219221
npmcli-run-script-->read-package-json-fast;
@@ -694,7 +696,10 @@ graph LR;
694696
npmcli-mock-registry-->tap;
695697
npmcli-move-file-->mkdirp;
696698
npmcli-move-file-->rimraf;
699+
npmcli-package-json-->glob;
697700
npmcli-package-json-->json-parse-even-better-errors;
701+
npmcli-package-json-->normalize-package-data;
702+
npmcli-package-json-->npm-normalize-package-bin;
698703
npmcli-promise-spawn-->which;
699704
npmcli-query-->postcss-selector-parser;
700705
npmcli-run-script-->node-gyp;
@@ -817,6 +822,6 @@ packages higher up the chain.
817822
- pacote, libnpmhook, libnpmorg, libnpmsearch, libnpmteam, npm-profile
818823
- npm-registry-fetch, libnpmversion
819824
- @npmcli/git, make-fetch-happen, @npmcli/config, init-package-json
820-
- @npmcli/installed-package-contents, @npmcli/map-workspaces, cacache, npm-pick-manifest, @npmcli/run-script, read-package-json, promzard
821-
- @npmcli/docs, @npmcli/fs, npm-bundled, read-package-json-fast, unique-filename, npm-install-checks, npm-package-arg, npm-packlist, normalize-package-data, @npmcli/package-json, bin-links, nopt, npmlog, parse-conflict-json, read
825+
- @npmcli/installed-package-contents, @npmcli/map-workspaces, cacache, npm-pick-manifest, @npmcli/run-script, read-package-json, @npmcli/package-json, promzard
826+
- @npmcli/docs, @npmcli/fs, npm-bundled, read-package-json-fast, unique-filename, npm-install-checks, npm-package-arg, npm-packlist, normalize-package-data, bin-links, nopt, npmlog, parse-conflict-json, read
822827
- @npmcli/eslint-config, @npmcli/template-oss, ignore-walk, semver, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, are-we-there-yet, gauge, minify-registry-metadata, ini, @npmcli/disparity-colors, mute-stream, npm-audit-report, npm-user-validate
Lines changed: 130 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
1-
const fs = require('fs')
2-
const promisify = require('util').promisify
3-
const readFile = promisify(fs.readFile)
4-
const writeFile = promisify(fs.writeFile)
1+
const { readFile, writeFile } = require('fs/promises')
52
const { resolve } = require('path')
63
const updateDeps = require('./update-dependencies.js')
74
const updateScripts = require('./update-scripts.js')
85
const updateWorkspaces = require('./update-workspaces.js')
6+
const normalize = require('./normalize.js')
97

108
const parseJSON = require('json-parse-even-better-errors')
119

12-
const _filename = Symbol('filename')
13-
const _manifest = Symbol('manifest')
14-
const _readFileContent = Symbol('readFileContent')
15-
1610
// a list of handy specialized helper functions that take
1711
// care of special cases that are handled by the npm cli
1812
const knownSteps = new Set([
@@ -29,42 +23,111 @@ const knownKeys = new Set([
2923
])
3024

3125
class PackageJson {
26+
static normalizeSteps = Object.freeze([
27+
'_id',
28+
'_attributes',
29+
'bundledDependencies',
30+
'bundleDependencies',
31+
'optionalDedupe',
32+
'scripts',
33+
'funding',
34+
'bin',
35+
])
36+
37+
static prepareSteps = Object.freeze([
38+
'_attributes',
39+
'bundledDependencies',
40+
'bundleDependencies',
41+
'gypfile',
42+
'serverjs',
43+
'scriptpath',
44+
'authors',
45+
'readme',
46+
'mans',
47+
'binDir',
48+
'gitHead',
49+
'fillTypes',
50+
'normalizeData',
51+
'binRefs',
52+
])
53+
54+
// default behavior, just loads and parses
3255
static async load (path) {
3356
return await new PackageJson(path).load()
3457
}
3558

59+
// read-package-json compatible behavior
60+
static async prepare (path, opts) {
61+
return await new PackageJson(path).prepare(opts)
62+
}
63+
64+
// read-package-json-fast compatible behavior
65+
static async normalize (path, opts) {
66+
return await new PackageJson(path).normalize(opts)
67+
}
68+
69+
#filename
70+
#path
71+
#manifest = {}
72+
#readFileContent = ''
73+
#fromIndex = false
74+
3675
constructor (path) {
37-
this[_filename] = resolve(path, 'package.json')
38-
this[_manifest] = {}
39-
this[_readFileContent] = ''
76+
this.#path = path
77+
this.#filename = resolve(path, 'package.json')
4078
}
4179

42-
async load () {
80+
async load (parseIndex) {
81+
let parseErr
4382
try {
44-
this[_readFileContent] =
45-
await readFile(this[_filename], 'utf8')
83+
this.#readFileContent =
84+
await readFile(this.#filename, 'utf8')
4685
} catch (err) {
47-
throw new Error('package.json not found')
86+
err.message = `Could not read package.json: ${err}`
87+
if (!parseIndex) {
88+
throw err
89+
}
90+
parseErr = err
91+
}
92+
93+
if (parseErr) {
94+
const indexFile = resolve(this.#path, 'index.js')
95+
let indexFileContent
96+
try {
97+
indexFileContent = await readFile(indexFile, 'utf8')
98+
} catch (err) {
99+
throw parseErr
100+
}
101+
try {
102+
this.#manifest = fromComment(indexFileContent)
103+
} catch (err) {
104+
throw parseErr
105+
}
106+
this.#fromIndex = true
107+
return this
48108
}
49109

50110
try {
51-
this[_manifest] =
52-
parseJSON(this[_readFileContent])
111+
this.#manifest = parseJSON(this.#readFileContent)
53112
} catch (err) {
54-
throw new Error(`Invalid package.json: ${err}`)
113+
err.message = `Invalid package.json: ${err}`
114+
throw err
55115
}
56-
57116
return this
58117
}
59118

60119
get content () {
61-
return this[_manifest]
120+
return this.#manifest
121+
}
122+
123+
get path () {
124+
return this.#path
62125
}
63126

64127
update (content) {
65128
// validates both current manifest and content param
66129
const invalidContent =
67-
typeof this[_manifest] !== 'object'
130+
typeof this.#manifest !== 'object'
68131
|| typeof content !== 'object'
69132
if (invalidContent) {
70133
throw Object.assign(
@@ -74,36 +137,76 @@ class PackageJson {
74137
}
75138

76139
for (const step of knownSteps) {
77-
this[_manifest] = step({ content, originalContent: this[_manifest] })
140+
this.#manifest = step({ content, originalContent: this.#manifest })
78141
}
79142

80143
// unknown properties will just be overwitten
81144
for (const [key, value] of Object.entries(content)) {
82145
if (!knownKeys.has(key)) {
83-
this[_manifest][key] = value
146+
this.#manifest[key] = value
84147
}
85148
}
86149

87150
return this
88151
}
89152

90153
async save () {
154+
if (this.#fromIndex) {
155+
throw new Error('No package.json to save to')
156+
}
91157
const {
92158
[Symbol.for('indent')]: indent,
93159
[Symbol.for('newline')]: newline,
94-
} = this[_manifest]
160+
} = this.#manifest
95161

96162
const format = indent === undefined ? ' ' : indent
97163
const eol = newline === undefined ? '\n' : newline
98164
const fileContent = `${
99-
JSON.stringify(this[_manifest], null, format)
165+
JSON.stringify(this.#manifest, null, format)
100166
}\n`
101167
.replace(/\n/g, eol)
102168

103-
if (fileContent.trim() !== this[_readFileContent].trim()) {
104-
return await writeFile(this[_filename], fileContent)
169+
if (fileContent.trim() !== this.#readFileContent.trim()) {
170+
return await writeFile(this.#filename, fileContent)
105171
}
106172
}
173+
174+
async normalize (opts = {}) {
175+
if (!opts.steps) {
176+
opts.steps = this.constructor.normalizeSteps
177+
}
178+
await this.load()
179+
await normalize(this, opts)
180+
return this
181+
}
182+
183+
async prepare (opts = {}) {
184+
if (!opts.steps) {
185+
opts.steps = this.constructor.prepareSteps
186+
}
187+
await this.load(true)
188+
await normalize(this, opts)
189+
return this
190+
}
191+
}
192+
193+
// /**package { "name": "foo", "version": "1.2.3", ... } **/
194+
function fromComment (data) {
195+
data = data.split(/^\/\*\*package(?:\s|$)/m)
196+
197+
if (data.length < 2) {
198+
throw new Error('File has no package in comments')
199+
}
200+
data = data[1]
201+
data = data.split(/\*\*\/$/m)
202+
203+
if (data.length < 2) {
204+
throw new Error('File has no package in comments')
205+
}
206+
data = data[0]
207+
data = data.replace(/^\s*\*/mg, '')
208+
209+
return parseJSON(data)
107210
}
108211

109212
module.exports = PackageJson

0 commit comments

Comments
 (0)