Skip to content

Commit

Permalink
deps: @npmcli/package-json@3.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
wraithgar committed May 17, 2023
1 parent f53e6ff commit 19214b5
Show file tree
Hide file tree
Showing 6 changed files with 439 additions and 40 deletions.
9 changes: 7 additions & 2 deletions DEPENDENCIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ graph LR;
npmcli-mock-registry-->npmcli-template-oss["@npmcli/template-oss"];
npmcli-mock-registry-->pacote;
npmcli-package-json-->json-parse-even-better-errors;
npmcli-package-json-->normalize-package-data;
npmcli-package-json-->npm-normalize-package-bin;
npmcli-run-script-->npmcli-node-gyp["@npmcli/node-gyp"];
npmcli-run-script-->npmcli-promise-spawn["@npmcli/promise-spawn"];
npmcli-run-script-->read-package-json-fast;
Expand Down Expand Up @@ -694,7 +696,10 @@ graph LR;
npmcli-mock-registry-->tap;
npmcli-move-file-->mkdirp;
npmcli-move-file-->rimraf;
npmcli-package-json-->glob;
npmcli-package-json-->json-parse-even-better-errors;
npmcli-package-json-->normalize-package-data;
npmcli-package-json-->npm-normalize-package-bin;
npmcli-promise-spawn-->which;
npmcli-query-->postcss-selector-parser;
npmcli-run-script-->node-gyp;
Expand Down Expand Up @@ -817,6 +822,6 @@ packages higher up the chain.
- pacote, libnpmhook, libnpmorg, libnpmsearch, libnpmteam, npm-profile
- npm-registry-fetch, libnpmversion
- @npmcli/git, make-fetch-happen, @npmcli/config, init-package-json
- @npmcli/installed-package-contents, @npmcli/map-workspaces, cacache, npm-pick-manifest, @npmcli/run-script, read-package-json, promzard
- @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
- @npmcli/installed-package-contents, @npmcli/map-workspaces, cacache, npm-pick-manifest, @npmcli/run-script, read-package-json, @npmcli/package-json, promzard
- @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
- @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
157 changes: 130 additions & 27 deletions node_modules/@npmcli/package-json/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
const fs = require('fs')
const promisify = require('util').promisify
const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)
const { readFile, writeFile } = require('fs/promises')
const { resolve } = require('path')
const updateDeps = require('./update-dependencies.js')
const updateScripts = require('./update-scripts.js')
const updateWorkspaces = require('./update-workspaces.js')
const normalize = require('./normalize.js')

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

const _filename = Symbol('filename')
const _manifest = Symbol('manifest')
const _readFileContent = Symbol('readFileContent')

// a list of handy specialized helper functions that take
// care of special cases that are handled by the npm cli
const knownSteps = new Set([
Expand All @@ -29,42 +23,111 @@ const knownKeys = new Set([
])

class PackageJson {
static normalizeSteps = Object.freeze([
'_id',
'_attributes',
'bundledDependencies',
'bundleDependencies',
'optionalDedupe',
'scripts',
'funding',
'bin',
])

static prepareSteps = Object.freeze([
'_attributes',
'bundledDependencies',
'bundleDependencies',
'gypfile',
'serverjs',
'scriptpath',
'authors',
'readme',
'mans',
'binDir',
'gitHead',
'fillTypes',
'normalizeData',
'binRefs',
])

// default behavior, just loads and parses
static async load (path) {
return await new PackageJson(path).load()
}

// read-package-json compatible behavior
static async prepare (path, opts) {
return await new PackageJson(path).prepare(opts)
}

// read-package-json-fast compatible behavior
static async normalize (path, opts) {
return await new PackageJson(path).normalize(opts)
}

#filename
#path
#manifest = {}
#readFileContent = ''
#fromIndex = false

constructor (path) {
this[_filename] = resolve(path, 'package.json')
this[_manifest] = {}
this[_readFileContent] = ''
this.#path = path
this.#filename = resolve(path, 'package.json')
}

async load () {
async load (parseIndex) {
let parseErr
try {
this[_readFileContent] =
await readFile(this[_filename], 'utf8')
this.#readFileContent =
await readFile(this.#filename, 'utf8')
} catch (err) {
throw new Error('package.json not found')
err.message = `Could not read package.json: ${err}`
if (!parseIndex) {
throw err
}
parseErr = err
}

if (parseErr) {
const indexFile = resolve(this.#path, 'index.js')
let indexFileContent
try {
indexFileContent = await readFile(indexFile, 'utf8')
} catch (err) {
throw parseErr
}
try {
this.#manifest = fromComment(indexFileContent)
} catch (err) {
throw parseErr
}
this.#fromIndex = true
return this
}

try {
this[_manifest] =
parseJSON(this[_readFileContent])
this.#manifest = parseJSON(this.#readFileContent)
} catch (err) {
throw new Error(`Invalid package.json: ${err}`)
err.message = `Invalid package.json: ${err}`
throw err
}

return this
}

get content () {
return this[_manifest]
return this.#manifest
}

get path () {
return this.#path
}

update (content) {
// validates both current manifest and content param
const invalidContent =
typeof this[_manifest] !== 'object'
typeof this.#manifest !== 'object'
|| typeof content !== 'object'
if (invalidContent) {
throw Object.assign(
Expand All @@ -74,36 +137,76 @@ class PackageJson {
}

for (const step of knownSteps) {
this[_manifest] = step({ content, originalContent: this[_manifest] })
this.#manifest = step({ content, originalContent: this.#manifest })
}

// unknown properties will just be overwitten
for (const [key, value] of Object.entries(content)) {
if (!knownKeys.has(key)) {
this[_manifest][key] = value
this.#manifest[key] = value
}
}

return this
}

async save () {
if (this.#fromIndex) {
throw new Error('No package.json to save to')
}
const {
[Symbol.for('indent')]: indent,
[Symbol.for('newline')]: newline,
} = this[_manifest]
} = this.#manifest

const format = indent === undefined ? ' ' : indent
const eol = newline === undefined ? '\n' : newline
const fileContent = `${
JSON.stringify(this[_manifest], null, format)
JSON.stringify(this.#manifest, null, format)
}\n`
.replace(/\n/g, eol)

if (fileContent.trim() !== this[_readFileContent].trim()) {
return await writeFile(this[_filename], fileContent)
if (fileContent.trim() !== this.#readFileContent.trim()) {
return await writeFile(this.#filename, fileContent)
}
}

async normalize (opts = {}) {
if (!opts.steps) {
opts.steps = this.constructor.normalizeSteps
}
await this.load()
await normalize(this, opts)
return this
}

async prepare (opts = {}) {
if (!opts.steps) {
opts.steps = this.constructor.prepareSteps
}
await this.load(true)
await normalize(this, opts)
return this
}
}

// /**package { "name": "foo", "version": "1.2.3", ... } **/
function fromComment (data) {
data = data.split(/^\/\*\*package(?:\s|$)/m)

if (data.length < 2) {
throw new Error('File has no package in comments')
}
data = data[1]
data = data.split(/\*\*\/$/m)

if (data.length < 2) {
throw new Error('File has no package in comments')
}
data = data[0]
data = data.replace(/^\s*\*/mg, '')

return parseJSON(data)
}

module.exports = PackageJson

0 comments on commit 19214b5

Please sign in to comment.