Skip to content

Commit 7ddb1d1

Browse files
authored
feat: add changes array to normalize functions (#41)
1 parent 4775bf3 commit 7ddb1d1

4 files changed

Lines changed: 237 additions & 16 deletions

File tree

README.md

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ it will be overwritten.
7070
Loads a `package.json` at the given path.
7171

7272
- `opts`: `Object` can contain:
73-
- `create`: `Boolean` if true, a new package.json will be created if
74-
one does not already exist. Will not clobber ane existing
75-
package.json that can not be parsed.
73+
- `create`: `Boolean` if true, a new package.json will be created if one does not already exist. Will not clobber ane existing package.json that can not be parsed.
7674

7775
### Example:
7876

@@ -84,18 +82,15 @@ const pkgJson = new PackageJson()
8482
await pkgJson.load('./')
8583
```
8684

87-
Throws an error in case a `package.json` file is missing or has invalid
88-
contents.
85+
Throws an error in case a `package.json` file is missing or has invalid contents.
8986

9087
---
9188

9289
### **static** `async PackageJson.load(path)`
9390

94-
Convenience static method that returns a new instance and loads the contents of
95-
a `package.json` file from that location.
91+
Convenience static method that returns a new instance and loads the contents of a `package.json` file from that location.
9692

97-
- `path`: `String` that points to the folder from where to read the
98-
`package.json` from
93+
- `path`: `String` that points to the folder from where to read the `package.json` from
9994

10095
### Example:
10196

@@ -110,16 +105,28 @@ const pkgJson = await PackageJson.load('./')
110105

111106
### `async PackageJson.normalize()`
112107

113-
Intended for normalizing package.json files in a node_modules tree.
114-
Some light normalization is done to ensure that it is ready for use in
115-
`@npmcli/arborist`
108+
Intended for normalizing package.json files in a node_modules tree. Some light normalization is done to ensure that it is ready for use in `@npmcli/arborist`
109+
110+
- `path`: `String` that points to the folder from where to read the `package.json` from
111+
- `opts`: `Object` can contain:
112+
- `strict`: `Boolean` enables optional strict mode when applying the `normalizeData` step
113+
- `steps`: `Array` optional normalization steps that will be applied to the `package.json` file, replacing the default steps
114+
- `root`: `Path` optional git root to provide when applying the `gitHead` step
115+
- `changes`: `Array` if provided, a message about each change that was made to the packument will be added to this array
116116

117117
---
118118

119-
### **static** `async PackageJson.normalize(path)`
119+
### **static** `async PackageJson.normalize(path, opts = {})`
120120

121121
Convenience static that calls `load` before calling `normalize`
122122

123+
- `path`: `String` that points to the folder from where to read the `package.json` from
124+
- `opts`: `Object` can contain:
125+
- `strict`: `Boolean` enables optional strict mode when applying the `normalizeData` step
126+
- `steps`: `Array` optional normalization steps that will be applied to the `package.json` file, replacing the default steps
127+
- `root`: `Path` optional git root to provide when applying the `gitHead` step
128+
- `changes`: `Array` if provided, a message about each change that was made to the packument will be added to this array
129+
123130
---
124131

125132
### `async PackageJson.prepare()`
@@ -128,10 +135,17 @@ Like `normalize` but intended for preparing package.json files for publish.
128135

129136
---
130137

131-
### **static** `async PackageJson.prepare(path)`
138+
### **static** `async PackageJson.prepare(path, opts = {})`
132139

133140
Convenience static that calls `load` before calling `prepare`
134141

142+
- `path`: `String` that points to the folder from where to read the `package.json` from
143+
- `opts`: `Object` can contain:
144+
- `strict`: `Boolean` enables optional strict mode when applying the `normalizeData` step
145+
- `steps`: `Array` optional normalization steps that will be applied to the `package.json` file, replacing the default steps
146+
- `root`: `Path` optional git root to provide when applying the `gitHead` step
147+
- `changes`: `Array` if provided, a message about each change that was made to the packument will be added to this array
148+
135149
---
136150

137151
### `PackageJson.update(content)`

lib/normalize.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ const path = require('path')
66
const log = require('proc-log')
77
const git = require('@npmcli/git')
88

9-
const normalize = async (pkg, { strict, steps, root }) => {
9+
// We don't want the `changes` array in here by default because this is a hot
10+
// path for parsing packuments during install. So the calling method passes it
11+
// in if it wants to track changes.
12+
const normalize = async (pkg, { strict, steps, root, changes }) => {
1013
if (!pkg.content) {
1114
throw new Error('Can not normalize without content')
1215
}
@@ -18,6 +21,7 @@ const normalize = async (pkg, { strict, steps, root }) => {
1821
if (steps.includes('_attributes')) {
1922
for (const key in data) {
2023
if (key.startsWith('_')) {
24+
changes?.push(`"${key}" was removed`)
2125
delete pkg.content[key]
2226
}
2327
}
@@ -26,6 +30,7 @@ const normalize = async (pkg, { strict, steps, root }) => {
2630
// build the "_id" attribute
2731
if (steps.includes('_id')) {
2832
if (data.name && data.version) {
33+
changes?.push(`"_id" was set to ${pkgId}`)
2934
data._id = pkgId
3035
}
3136
}
@@ -35,20 +40,25 @@ const normalize = async (pkg, { strict, steps, root }) => {
3540
if (data.bundleDependencies === undefined && data.bundledDependencies !== undefined) {
3641
data.bundleDependencies = data.bundledDependencies
3742
}
43+
changes?.push(`Deleted incorrect "bundledDependencies"`)
3844
delete data.bundledDependencies
3945
}
4046
// expand "bundleDependencies: true or translate from object"
4147
if (steps.includes('bundleDependencies')) {
4248
const bd = data.bundleDependencies
4349
if (bd === false && !steps.includes('bundleDependenciesDeleteFalse')) {
50+
changes?.push(`"bundleDepdencies" was changed from "false" to "[]"`)
4451
data.bundleDependencies = []
4552
} else if (bd === true) {
53+
changes?.push(`"bundleDepdencies" was auto-populated from "dependencies"`)
4654
data.bundleDependencies = Object.keys(data.dependencies || {})
4755
} else if (bd && typeof bd === 'object') {
4856
if (!Array.isArray(bd)) {
57+
changes?.push(`"bundleDependencies" was changed from an object to an array`)
4958
data.bundleDependencies = Object.keys(bd)
5059
}
5160
} else {
61+
changes?.push(`"bundleDependencies" was removed`)
5262
delete data.bundleDependencies
5363
}
5464
}
@@ -61,9 +71,11 @@ const normalize = async (pkg, { strict, steps, root }) => {
6171
if (data.dependencies &&
6272
data.optionalDependencies && typeof data.optionalDependencies === 'object') {
6373
for (const name in data.optionalDependencies) {
74+
changes?.push(`optionalDependencies entry "${name}" was removed`)
6475
delete data.dependencies[name]
6576
}
6677
if (!Object.keys(data.dependencies).length) {
78+
changes?.push(`empty "optionalDependencies" was removed`)
6779
delete data.dependencies
6880
}
6981
}
@@ -77,6 +89,8 @@ const normalize = async (pkg, { strict, steps, root }) => {
7789
scripts.install = 'node-gyp rebuild'
7890
data.scripts = scripts
7991
data.gypfile = true
92+
changes?.push(`"scripts.install" was set to "node-gyp rebuild"`)
93+
changes?.push(`"gypfile" was set to "true"`)
8094
}
8195
}
8296
}
@@ -87,6 +101,7 @@ const normalize = async (pkg, { strict, steps, root }) => {
87101
await fs.access(path.join(pkg.path, 'server.js'))
88102
scripts.start = 'node server.js'
89103
data.scripts = scripts
104+
changes?.push('"scripts.start" was set to "node server.js"')
90105
} catch {
91106
// do nothing
92107
}
@@ -99,18 +114,22 @@ const normalize = async (pkg, { strict, steps, root }) => {
99114
for (const name in data.scripts) {
100115
if (typeof data.scripts[name] !== 'string') {
101116
delete data.scripts[name]
117+
changes?.push(`invalid scripts entry "${name}" was removed`)
102118
} else if (steps.includes('scriptpath')) {
103119
data.scripts[name] = data.scripts[name].replace(spre, '')
120+
changes?.push(`scripts entry "${name}" was fixed to remove node_modules/.bin reference`)
104121
}
105122
}
106123
} else {
124+
changes?.push(`removed invalid "scripts"`)
107125
delete data.scripts
108126
}
109127
}
110128

111129
if (steps.includes('funding')) {
112130
if (data.funding && typeof data.funding === 'string') {
113131
data.funding = { url: data.funding }
132+
changes?.push(`"funding" was changed to an object with a url attribute`)
114133
}
115134
}
116135

@@ -122,6 +141,7 @@ const normalize = async (pkg, { strict, steps, root }) => {
122141
.map(line => line.replace(/^\s*#.*$/, '').trim())
123142
.filter(line => line)
124143
data.contributors = authors
144+
changes.push('"contributors" was auto-populated with the contents of the "AUTHORS" file')
125145
} catch {
126146
// do nothing
127147
}
@@ -148,6 +168,8 @@ const normalize = async (pkg, { strict, steps, root }) => {
148168
const readmeData = await fs.readFile(path.join(pkg.path, readmeFile), 'utf8')
149169
data.readme = readmeData
150170
data.readmeFilename = readmeFile
171+
changes?.push(`"readme" was set to the contents of ${readmeFile}`)
172+
changes?.push(`"readmeFilename" was set to ${readmeFile}`)
151173
}
152174
}
153175

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/* IMPORTANT
2+
* This snapshot file is auto-generated, but designed for humans.
3+
* It should be checked into source control and tracked carefully.
4+
* Re-generate by setting TAP_SNAPSHOT=1 and running tests.
5+
* Make sure to inspect the output below. Do not ignore changes!
6+
*/
7+
'use strict'
8+
exports[`test/normalize.js TAP @npmcli/package-json - with changes clean up bundleDependencies change name if bundleDependencies is not present > must match snapshot 1`] = `
9+
Array [
10+
"Deleted incorrect \\"bundledDependencies\\"",
11+
"removed invalid \\"scripts\\"",
12+
]
13+
`
14+
15+
exports[`test/normalize.js TAP @npmcli/package-json - with changes clean up bundleDependencies dont array-ify if its an array already > must match snapshot 1`] = `
16+
Array [
17+
"Deleted incorrect \\"bundledDependencies\\"",
18+
"removed invalid \\"scripts\\"",
19+
]
20+
`
21+
22+
exports[`test/normalize.js TAP @npmcli/package-json - with changes clean up bundleDependencies handle bundleDependencies object > must match snapshot 1`] = `
23+
Array [
24+
"Deleted incorrect \\"bundledDependencies\\"",
25+
"\\"bundleDependencies\\" was changed from an object to an array",
26+
"removed invalid \\"scripts\\"",
27+
]
28+
`
29+
30+
exports[`test/normalize.js TAP @npmcli/package-json - with changes clean up bundleDependencies handle bundleDependencies: false > must match snapshot 1`] = `
31+
Array [
32+
"Deleted incorrect \\"bundledDependencies\\"",
33+
"\\"bundleDepdencies\\" was changed from \\"false\\" to \\"[]\\"",
34+
"removed invalid \\"scripts\\"",
35+
]
36+
`
37+
38+
exports[`test/normalize.js TAP @npmcli/package-json - with changes clean up bundleDependencies handle bundleDependencies: true > must match snapshot 1`] = `
39+
Array [
40+
"Deleted incorrect \\"bundledDependencies\\"",
41+
"\\"bundleDepdencies\\" was auto-populated from \\"dependencies\\"",
42+
"removed invalid \\"scripts\\"",
43+
]
44+
`
45+
46+
exports[`test/normalize.js TAP @npmcli/package-json - with changes clean up bundleDependencies handle bundleDependencies: true with no deps > must match snapshot 1`] = `
47+
Array [
48+
"Deleted incorrect \\"bundledDependencies\\"",
49+
"\\"bundleDepdencies\\" was auto-populated from \\"dependencies\\"",
50+
"removed invalid \\"scripts\\"",
51+
]
52+
`
53+
54+
exports[`test/normalize.js TAP @npmcli/package-json - with changes clean up bundleDependencies handle bundledDependencies: true > must match snapshot 1`] = `
55+
Array [
56+
"Deleted incorrect \\"bundledDependencies\\"",
57+
"\\"bundleDepdencies\\" was auto-populated from \\"dependencies\\"",
58+
"removed invalid \\"scripts\\"",
59+
]
60+
`
61+
62+
exports[`test/normalize.js TAP @npmcli/package-json - with changes clean up scripts delete non-object scripts > must match snapshot 1`] = `
63+
Array [
64+
"Deleted incorrect \\"bundledDependencies\\"",
65+
"\\"bundleDependencies\\" was removed",
66+
"removed invalid \\"scripts\\"",
67+
]
68+
`
69+
70+
exports[`test/normalize.js TAP @npmcli/package-json - with changes clean up scripts delete non-string script targets > must match snapshot 1`] = `
71+
Array [
72+
"Deleted incorrect \\"bundledDependencies\\"",
73+
"\\"bundleDependencies\\" was removed",
74+
"invalid scripts entry \\"bar\\" was removed",
75+
"invalid scripts entry \\"baz\\" was removed",
76+
]
77+
`
78+
79+
exports[`test/normalize.js TAP @npmcli/package-json - with changes cleanup bins delete string bin when no name > must match snapshot 1`] = `
80+
Array [
81+
"Deleted incorrect \\"bundledDependencies\\"",
82+
"\\"bundleDependencies\\" was removed",
83+
"removed invalid \\"scripts\\"",
84+
]
85+
`
86+
87+
exports[`test/normalize.js TAP @npmcli/package-json - with changes cleanup bins handle string when a name is set > must match snapshot 1`] = `
88+
Array [
89+
"Deleted incorrect \\"bundledDependencies\\"",
90+
"\\"bundleDependencies\\" was removed",
91+
"removed invalid \\"scripts\\"",
92+
]
93+
`
94+
95+
exports[`test/normalize.js TAP @npmcli/package-json - with changes cleanup bins remove non-object bin > must match snapshot 1`] = `
96+
Array [
97+
"Deleted incorrect \\"bundledDependencies\\"",
98+
"\\"bundleDependencies\\" was removed",
99+
"removed invalid \\"scripts\\"",
100+
]
101+
`
102+
103+
exports[`test/normalize.js TAP @npmcli/package-json - with changes cleanup bins remove non-string bin values > must match snapshot 1`] = `
104+
Array [
105+
"Deleted incorrect \\"bundledDependencies\\"",
106+
"\\"bundleDependencies\\" was removed",
107+
"removed invalid \\"scripts\\"",
108+
]
109+
`
110+
111+
exports[`test/normalize.js TAP @npmcli/package-json - with changes convert funding string to object > must match snapshot 1`] = `
112+
Array [
113+
"Deleted incorrect \\"bundledDependencies\\"",
114+
"\\"bundleDependencies\\" was removed",
115+
"removed invalid \\"scripts\\"",
116+
"\\"funding\\" was changed to an object with a url attribute",
117+
]
118+
`
119+
120+
exports[`test/normalize.js TAP @npmcli/package-json - with changes dedupe optional deps out of regular deps choose optional deps in conflict, leaving populated dependencies > must match snapshot 1`] = `
121+
Array [
122+
"Deleted incorrect \\"bundledDependencies\\"",
123+
"\\"bundleDependencies\\" was removed",
124+
"optionalDependencies entry \\"whowins\\" was removed",
125+
"removed invalid \\"scripts\\"",
126+
]
127+
`
128+
129+
exports[`test/normalize.js TAP @npmcli/package-json - with changes dedupe optional deps out of regular deps choose optional deps in conflict, removing empty dependencies > must match snapshot 1`] = `
130+
Array [
131+
"Deleted incorrect \\"bundledDependencies\\"",
132+
"\\"bundleDependencies\\" was removed",
133+
"optionalDependencies entry \\"whowins\\" was removed",
134+
"empty \\"optionalDependencies\\" was removed",
135+
"removed invalid \\"scripts\\"",
136+
]
137+
`
138+
139+
exports[`test/normalize.js TAP @npmcli/package-json - with changes dedupe optional deps out of regular deps do not create regular deps if only optional specified > must match snapshot 1`] = `
140+
Array [
141+
"Deleted incorrect \\"bundledDependencies\\"",
142+
"\\"bundleDependencies\\" was removed",
143+
"removed invalid \\"scripts\\"",
144+
]
145+
`
146+
147+
exports[`test/normalize.js TAP @npmcli/package-json - with changes normalize bin > must match snapshot 1`] = `
148+
Array [
149+
"Deleted incorrect \\"bundledDependencies\\"",
150+
"\\"bundleDependencies\\" was removed",
151+
"removed invalid \\"scripts\\"",
152+
]
153+
`
154+
155+
exports[`test/normalize.js TAP @npmcli/package-json - with changes set _id if name and version set > must match snapshot 1`] = `
156+
Array [
157+
"\\"_id\\" was set to [email protected]",
158+
"Deleted incorrect \\"bundledDependencies\\"",
159+
"\\"bundleDependencies\\" was removed",
160+
"removed invalid \\"scripts\\"",
161+
]
162+
`
163+
164+
exports[`test/normalize.js TAP @npmcli/package-json - with changes skipping steps > must match snapshot 1`] = `
165+
Array []
166+
`
167+
168+
exports[`test/normalize.js TAP @npmcli/package-json - with changes strip _fields > must match snapshot 1`] = `
169+
Array [
170+
"\\"_lodash\\" was removed",
171+
"\\"_id\\" was set to [email protected]",
172+
"Deleted incorrect \\"bundledDependencies\\"",
173+
"\\"bundleDependencies\\" was removed",
174+
"removed invalid \\"scripts\\"",
175+
]
176+
`

0 commit comments

Comments
 (0)