Skip to content

Commit

Permalink
feat: add fix method
Browse files Browse the repository at this point in the history
  • Loading branch information
wraithgar committed Jul 5, 2023
1 parent 7ddb1d1 commit e2bc4f3
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 4 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ Convenience static that calls `load` before calling `prepare`

---

### `async PackageJson.fix()`

Like `normalize` but intended for the `npm pkg fix` command.

---

### `PackageJson.update(content)`

Updates the contents of a `package.json` with the `content` provided.
Expand Down
30 changes: 30 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,23 @@ class PackageJson {
'bin',
])

// npm pkg fix
static fixSteps = Object.freeze([
'binRefs',
'bundleDependencies',
'bundleDependenciesFalse',
'fixNameField',
'fixVersionField',
'fixRepositoryField',
'fixBinField',
'fixDependencies',
'fixScriptsField',
'devDependencies',
'scriptpath',
])

static prepareSteps = Object.freeze([
'_id',
'_attributes',
'bundledDependencies',
'bundleDependencies',
Expand Down Expand Up @@ -81,6 +97,13 @@ class PackageJson {
}
}

// npm pkg fix
static async fix (path, opts) {
const p = new PackageJson()
await p.load(path, true)
return p.fix(opts)
}

// read-package-json compatible behavior
static async prepare (path, opts) {
const p = new PackageJson()
Expand Down Expand Up @@ -244,6 +267,13 @@ class PackageJson {
await normalize(this, opts)
return this
}

async fix (opts = {}) {
// This one is not overridable
opts.steps = this.constructor.fixSteps
await normalize(this, opts)
return this
}
}

module.exports = PackageJson
63 changes: 59 additions & 4 deletions lib/normalize.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
const fs = require('fs/promises')
const { glob } = require('glob')
const normalizePackageBin = require('npm-normalize-package-bin')
const normalizePackageData = require('normalize-package-data')
const legacyFixer = require('normalize-package-data/lib/fixer.js')
const legacyMakeWarning = require('normalize-package-data/lib/make_warning.js')
const path = require('path')
const log = require('proc-log')
const git = require('@npmcli/git')

// We don't want the `changes` array in here by default because this is a hot
// path for parsing packuments during install. So the calling method passes it
// in if it wants to track changes.
const normalize = async (pkg, { strict, steps, root, changes }) => {
const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) => {
if (!pkg.content) {
throw new Error('Can not normalize without content')
}
const data = pkg.content
const scripts = data.scripts || {}
const pkgId = `${data.name ?? ''}@${data.version ?? ''}`

legacyFixer.warn = function () {
changes?.push(legacyMakeWarning.apply(null, arguments))
}

// name and version are load bearing so we have to clean them up first
if (steps.includes('fixNameField') || steps.includes('normalizeData')) {
legacyFixer.fixNameField(data, { strict, allowLegacyCase })
}

if (steps.includes('fixVersionField') || steps.includes('normalizeData')) {
legacyFixer.fixVersionField(data, strict)
}
// remove attributes that start with "_"
if (steps.includes('_attributes')) {
for (const key in data) {
Expand Down Expand Up @@ -171,6 +184,10 @@ const normalize = async (pkg, { strict, steps, root, changes }) => {
changes?.push(`"readme" was set to the contents of ${readmeFile}`)
changes?.push(`"readmeFilename" was set to ${readmeFile}`)
}
if (!data.readme) {
// this.warn('missingReadme')
data.readme = 'ERROR: No README data found!'
}
}

// expand directories.man
Expand Down Expand Up @@ -295,9 +312,47 @@ const normalize = async (pkg, { strict, steps, root, changes }) => {
}
}

// "normalizeData" from read-package-json
// "normalizeData" from "read-package-json", which was just a call through to
// "normalize-package-data". We only call the "fixer" functions because
// outside of that it was also clobbering _id (which we already conditionally
// do) and also adding the gypfile script (which we also already
// conditionally do)

// Some steps are isolated so we can do a limited subset of these in `fix`
if (steps.includes('fixRepositoryField') || steps.includes('normalizeData')) {
legacyFixer.fixRepositoryField(data)
}

if (steps.includes('fixBinField') || steps.includes('normalizeData')) {
legacyFixer.fixBinField(data)
}

if (steps.includes('fixDependencies') || steps.includes('normalizeData')) {
legacyFixer.fixDependencies(data, strict)
}

if (steps.includes('fixScriptsField') || steps.includes('normalizeData')) {
legacyFixer.fixScriptsField(data)
}

if (steps.includes('normalizeData')) {
normalizePackageData(data, strict)
const legacySteps = [
'fixDescriptionField',
'fixModulesField',
'fixFilesField',
'fixManField',
'fixBugsField',
'fixKeywordsField',
'fixBundleDependenciesField',
'fixHomepageField',
'fixReadmeField',
'fixLicenseField',
'fixPeople',
'fixTypos',
]
for (const legacyStep of legacySteps) {
legacyFixer[legacyStep](data)
}
}

// Warn if the bin references don't point to anything. This might be better
Expand Down
19 changes: 19 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,22 @@ t.test('cannot update with no content', async t => {
message: /Can not update without content/,
})
})

t.test('fix', async t => {
const path = t.testdir({
'package.json': JSON.stringify({
name: '@npmcli/test-package ',
version: 'v1.0.0',
bin: '@npmcli/test-package',
dependencies: ['lodash'],
scripts: true,
repository: 'github.com/npm/test-package',
}),
})
const { content } = await PackageJson.fix(path)
t.strictSame(content.name, '@npmcli/test-package')
t.strictSame(content.version, '1.0.0')
t.strictSame(content.bin, { 'test-package': '@npmcli/test-package' })
t.strictSame(content.dependencies, { lodash: '' })
t.strictSame(content.repository, { type: 'git', url: 'github.com/npm/test-package' })
})

0 comments on commit e2bc4f3

Please sign in to comment.