update
This commit is contained in:
278
package/node_modules/@npmcli/package-json/lib/index.js
generated
vendored
Normal file
278
package/node_modules/@npmcli/package-json/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
const { readFile, writeFile } = require('node:fs/promises')
|
||||
const { resolve } = require('node:path')
|
||||
const parseJSON = require('json-parse-even-better-errors')
|
||||
|
||||
const updateDeps = require('./update-dependencies.js')
|
||||
const updateScripts = require('./update-scripts.js')
|
||||
const updateWorkspaces = require('./update-workspaces.js')
|
||||
const normalize = require('./normalize.js')
|
||||
const { read, parse } = require('./read-package.js')
|
||||
|
||||
// a list of handy specialized helper functions that take
|
||||
// care of special cases that are handled by the npm cli
|
||||
const knownSteps = new Set([
|
||||
updateDeps,
|
||||
updateScripts,
|
||||
updateWorkspaces,
|
||||
])
|
||||
|
||||
// list of all keys that are handled by "knownSteps" helpers
|
||||
const knownKeys = new Set([
|
||||
...updateDeps.knownKeys,
|
||||
'scripts',
|
||||
'workspaces',
|
||||
])
|
||||
|
||||
class PackageJson {
|
||||
static normalizeSteps = Object.freeze([
|
||||
'_id',
|
||||
'_attributes',
|
||||
'bundledDependencies',
|
||||
'bundleDependencies',
|
||||
'optionalDedupe',
|
||||
'scripts',
|
||||
'funding',
|
||||
'bin',
|
||||
])
|
||||
|
||||
// npm pkg fix
|
||||
static fixSteps = Object.freeze([
|
||||
'binRefs',
|
||||
'bundleDependencies',
|
||||
'bundleDependenciesFalse',
|
||||
'fixNameField',
|
||||
'fixVersionField',
|
||||
'fixRepositoryField',
|
||||
'fixDependencies',
|
||||
'devDependencies',
|
||||
'scriptpath',
|
||||
])
|
||||
|
||||
static prepareSteps = Object.freeze([
|
||||
'_id',
|
||||
'_attributes',
|
||||
'bundledDependencies',
|
||||
'bundleDependencies',
|
||||
'bundleDependenciesDeleteFalse',
|
||||
'gypfile',
|
||||
'serverjs',
|
||||
'scriptpath',
|
||||
'authors',
|
||||
'readme',
|
||||
'mans',
|
||||
'binDir',
|
||||
'gitHead',
|
||||
'fillTypes',
|
||||
'normalizeData',
|
||||
'binRefs',
|
||||
])
|
||||
|
||||
// create a new empty package.json, so we can save at the given path even
|
||||
// though we didn't start from a parsed file
|
||||
static async create (path, opts = {}) {
|
||||
const p = new PackageJson()
|
||||
await p.create(path)
|
||||
if (opts.data) {
|
||||
return p.update(opts.data)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Loads a package.json at given path and JSON parses
|
||||
static async load (path, opts = {}) {
|
||||
const p = new PackageJson()
|
||||
// Avoid try/catch if we aren't going to create
|
||||
if (!opts.create) {
|
||||
return p.load(path)
|
||||
}
|
||||
|
||||
try {
|
||||
return await p.load(path)
|
||||
} catch (err) {
|
||||
if (!err.message.startsWith('Could not read package.json')) {
|
||||
throw err
|
||||
}
|
||||
return await p.create(path)
|
||||
}
|
||||
}
|
||||
|
||||
// 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()
|
||||
await p.load(path, true)
|
||||
return p.prepare(opts)
|
||||
}
|
||||
|
||||
// read-package-json-fast compatible behavior
|
||||
static async normalize (path, opts) {
|
||||
const p = new PackageJson()
|
||||
await p.load(path)
|
||||
return p.normalize(opts)
|
||||
}
|
||||
|
||||
#path
|
||||
#manifest
|
||||
#readFileContent = ''
|
||||
#canSave = true
|
||||
|
||||
// Load content from given path
|
||||
async load (path, parseIndex) {
|
||||
this.#path = path
|
||||
let parseErr
|
||||
try {
|
||||
this.#readFileContent = await read(this.filename)
|
||||
} catch (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.fromComment(indexFileContent)
|
||||
} catch (err) {
|
||||
throw parseErr
|
||||
}
|
||||
// This wasn't a package.json so prevent saving
|
||||
this.#canSave = false
|
||||
return this
|
||||
}
|
||||
|
||||
return this.fromJSON(this.#readFileContent)
|
||||
}
|
||||
|
||||
// Load data from a JSON string/buffer
|
||||
fromJSON (data) {
|
||||
this.#manifest = parse(data)
|
||||
return this
|
||||
}
|
||||
|
||||
fromContent (data) {
|
||||
this.#manifest = data
|
||||
this.#canSave = false
|
||||
return this
|
||||
}
|
||||
|
||||
// Load data from a comment
|
||||
// /**package { "name": "foo", "version": "1.2.3", ... } **/
|
||||
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, '')
|
||||
|
||||
this.#manifest = parseJSON(data)
|
||||
return this
|
||||
}
|
||||
|
||||
get content () {
|
||||
return this.#manifest
|
||||
}
|
||||
|
||||
get path () {
|
||||
return this.#path
|
||||
}
|
||||
|
||||
get filename () {
|
||||
if (this.path) {
|
||||
return resolve(this.path, 'package.json')
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
create (path) {
|
||||
this.#path = path
|
||||
this.#manifest = {}
|
||||
return this
|
||||
}
|
||||
|
||||
// This should be the ONLY way to set content in the manifest
|
||||
update (content) {
|
||||
if (!this.content) {
|
||||
throw new Error('Can not update without content. Please `load` or `create`')
|
||||
}
|
||||
|
||||
for (const step of knownSteps) {
|
||||
this.#manifest = step({ content, originalContent: this.content })
|
||||
}
|
||||
|
||||
// unknown properties will just be overwitten
|
||||
for (const [key, value] of Object.entries(content)) {
|
||||
if (!knownKeys.has(key)) {
|
||||
this.content[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
async save () {
|
||||
if (!this.#canSave) {
|
||||
throw new Error('No package.json to save to')
|
||||
}
|
||||
const {
|
||||
[Symbol.for('indent')]: indent,
|
||||
[Symbol.for('newline')]: newline,
|
||||
} = this.content
|
||||
|
||||
const format = indent === undefined ? ' ' : indent
|
||||
const eol = newline === undefined ? '\n' : newline
|
||||
const fileContent = `${
|
||||
JSON.stringify(this.content, null, format)
|
||||
}\n`
|
||||
.replace(/\n/g, eol)
|
||||
|
||||
if (fileContent.trim() !== this.#readFileContent.trim()) {
|
||||
return await writeFile(this.filename, fileContent)
|
||||
}
|
||||
}
|
||||
|
||||
async normalize (opts = {}) {
|
||||
if (!opts.steps) {
|
||||
opts.steps = this.constructor.normalizeSteps
|
||||
}
|
||||
await normalize(this, opts)
|
||||
return this
|
||||
}
|
||||
|
||||
async prepare (opts = {}) {
|
||||
if (!opts.steps) {
|
||||
opts.steps = this.constructor.prepareSteps
|
||||
}
|
||||
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
|
Reference in New Issue
Block a user