This commit is contained in:
2025-08-18 23:06:34 +08:00
parent 0bc04fb659
commit ed18af0cad
1926 changed files with 275098 additions and 0 deletions

18
package/node_modules/init-package-json/LICENSE.md generated vendored Normal file
View File

@@ -0,0 +1,18 @@
ISC License
Copyright npm, Inc.
Permission to use, copy, modify, and/or distribute this
software for any purpose with or without fee is hereby
granted, provided that the above copyright notice and this
permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@@ -0,0 +1,262 @@
/* globals config, dirname, package, basename, yes, prompt */
const fs = require('fs/promises')
const path = require('path')
const validateLicense = require('validate-npm-package-license')
const validateName = require('validate-npm-package-name')
const npa = require('npm-package-arg')
const semver = require('semver')
// more popular packages should go here, maybe?
const isTestPkg = (p) => !!p.match(/^(expresso|mocha|tap|coffee-script|coco|streamline)$/)
const invalid = (msg) => Object.assign(new Error(msg), { notValid: true })
const readDeps = (test, excluded) => async () => {
const dirs = await fs.readdir('node_modules').catch(() => null)
if (!dirs) {
return
}
const deps = {}
for (const dir of dirs) {
if (dir.match(/^\./) || test !== isTestPkg(dir) || excluded[dir]) {
continue
}
const dp = path.join(dirname, 'node_modules', dir, 'package.json')
const p = await fs.readFile(dp, 'utf8').then((d) => JSON.parse(d)).catch(() => null)
if (!p || !p.version || p?._requiredBy?.some((r) => r === '#USER')) {
continue
}
deps[dir] = config.get('save-exact') ? p.version : config.get('save-prefix') + p.version
}
return deps
}
const getConfig = (key) => {
// dots take precedence over dashes
const def = config?.defaults?.[`init.${key}`]
const val = config.get(`init.${key}`)
return (val !== def && val) ? val : config.get(`init-${key.replace(/\./g, '-')}`)
}
const getName = () => {
const rawName = package.name || basename
let name = rawName
.replace(/^node-|[.-]js$/g, '')
.replace(/\s+/g, ' ')
.replace(/ /g, '-')
.toLowerCase()
let spec
try {
spec = npa(name)
} catch {
spec = {}
}
let scope = config.get('scope')
if (scope) {
if (scope.charAt(0) !== '@') {
scope = '@' + scope
}
if (spec.scope) {
name = scope + '/' + spec.name.split('/')[1]
} else {
name = scope + '/' + name
}
}
return name
}
const name = getName()
exports.name = yes ? name : prompt('package name', name, (data) => {
const its = validateName(data)
if (its.validForNewPackages) {
return data
}
const errors = (its.errors || []).concat(its.warnings || [])
return invalid(`Sorry, ${errors.join(' and ')}.`)
})
const version = package.version || getConfig('version') || '1.0.0'
exports.version = yes ? version : prompt('version', version, (v) => {
if (semver.valid(v)) {
return v
}
return invalid(`Invalid version: "${v}"`)
})
if (!package.description) {
exports.description = yes ? '' : prompt('description')
}
if (!package.main) {
exports.main = async () => {
const files = await fs.readdir(dirname)
.then(list => list.filter((f) => f.match(/\.js$/)))
.catch(() => [])
let index
if (files.includes('index.js')) {
index = 'index.js'
} else if (files.includes('main.js')) {
index = 'main.js'
} else if (files.includes(basename + '.js')) {
index = basename + '.js'
} else {
index = files[0] || 'index.js'
}
return yes ? index : prompt('entry point', index)
}
}
if (!package.bin) {
exports.bin = async () => {
try {
const d = await fs.readdir(path.resolve(dirname, 'bin'))
// just take the first js file we find there, or nada
let r = d.find(f => f.match(/\.js$/))
if (r) {
r = `bin/${r}`
}
return r
} catch {
// no bins
}
}
}
exports.directories = async () => {
const dirs = await fs.readdir(dirname)
const res = dirs.reduce((acc, d) => {
if (/^examples?$/.test(d)) {
acc.example = d
} else if (/^tests?$/.test(d)) {
acc.test = d
} else if (/^docs?$/.test(d)) {
acc.doc = d
} else if (d === 'man') {
acc.man = d
} else if (d === 'lib') {
acc.lib = d
}
return acc
}, {})
return Object.keys(res).length === 0 ? undefined : res
}
if (!package.dependencies) {
exports.dependencies = readDeps(false, package.devDependencies || {})
}
if (!package.devDependencies) {
exports.devDependencies = readDeps(true, package.dependencies || {})
}
// MUST have a test script!
if (!package.scripts) {
const scripts = package.scripts || {}
const notest = 'echo "Error: no test specified" && exit 1'
exports.scripts = async () => {
const d = await fs.readdir(path.join(dirname, 'node_modules')).catch(() => [])
// check to see what framework is in use, if any
let command
if (!scripts.test || scripts.test === notest) {
const commands = {
tap: 'tap test/*.js',
expresso: 'expresso test',
mocha: 'mocha',
}
for (const [k, v] of Object.entries(commands)) {
if (d.includes(k)) {
command = v
}
}
}
const promptArgs = ['test command', (t) => t || notest]
if (command) {
promptArgs.splice(1, 0, command)
}
scripts.test = yes ? command || notest : prompt(...promptArgs)
return scripts
}
}
if (!package.repository) {
exports.repository = async () => {
const gconf = await fs.readFile('.git/config', 'utf8').catch(() => '')
const lines = gconf.split(/\r?\n/)
let url
const i = lines.indexOf('[remote "origin"]')
if (i !== -1) {
url = gconf[i + 1]
if (!url.match(/^\s*url =/)) {
url = gconf[i + 2]
}
if (!url.match(/^\s*url =/)) {
url = null
} else {
url = url.replace(/^\s*url = /, '')
}
}
if (url && url.match(/^git@github.com:/)) {
url = url.replace(/^git@github.com:/, 'https://github.com/')
}
return yes ? url || '' : prompt('git repository', url || undefined)
}
}
if (!package.keywords) {
exports.keywords = yes ? '' : prompt('keywords', (data) => {
if (!data) {
return
}
if (Array.isArray(data)) {
data = data.join(' ')
}
if (typeof data !== 'string') {
return data
}
return data.split(/[\s,]+/)
})
}
if (!package.author) {
const authorName = getConfig('author.name')
exports.author = authorName
? {
name: authorName,
email: getConfig('author.email'),
url: getConfig('author.url'),
}
: yes ? '' : prompt('author')
}
const license = package.license || getConfig('license') || 'ISC'
exports.license = yes ? license : prompt('license', license, (data) => {
const its = validateLicense(data)
if (its.validForNewPackages) {
return data
}
const errors = (its.errors || []).concat(its.warnings || [])
return invalid(`Sorry, ${errors.join(' and ')}.`)
})

View File

@@ -0,0 +1,147 @@
const promzard = require('promzard')
const path = require('path')
const semver = require('semver')
const { read } = require('read')
const util = require('util')
const PackageJson = require('@npmcli/package-json')
const def = require.resolve('./default-input.js')
const extras = [
'bundleDependencies',
'gypfile',
'serverjs',
'scriptpath',
'readme',
'bin',
'githead',
'fillTypes',
'normalizeData',
]
const isYes = (c) => !!(c.get('yes') || c.get('y') || c.get('force') || c.get('f'))
const getConfig = (c) => {
// accept either a plain-jane object, or a config object with a "get" method.
if (typeof c.get !== 'function') {
const data = c
return {
get: (k) => data[k],
toJSON: () => data,
}
}
return c
}
// Coverage disabled because this is just walking back the fixPeople
// normalization from the normalizeData step and we don't need to re-test all
// of those paths.
/* istanbul ignore next */
const stringifyPerson = (p) => {
const { name, url, web, email, mail } = p
const u = url || web
const e = email || mail
return `${name}${e ? ` <${e}>` : ''}${u ? ` (${u})` : ''}`
}
async function init (dir,
// TODO test for non-default definitions
/* istanbul ignore next */
input = def,
c = {}) {
const config = getConfig(c)
const yes = isYes(config)
const packageFile = path.resolve(dir, 'package.json')
// read what's already there to inform our prompts
const pkg = await PackageJson.load(dir, { create: true })
await pkg.normalize()
if (!semver.valid(pkg.content.version)) {
delete pkg.content.version
}
// make sure that the input is valid. if not, use the default
const pzData = await promzard(path.resolve(input), {
yes,
config,
filename: packageFile,
dirname: dir,
basename: path.basename(dir),
package: pkg.content,
}, { backupFile: def })
for (const [k, v] of Object.entries(pzData)) {
if (v != null) {
pkg.content[k] = v
}
}
await pkg.normalize({ steps: extras })
// turn the objects back into somewhat more humane strings.
// "normalizeData" does this and there isn't a way to choose which of those steps happen
if (pkg.content.author) {
pkg.content.author = stringifyPerson(pkg.content.author)
}
// no need for the readme now.
delete pkg.content.readme
delete pkg.content.readmeFilename
// really don't want to have this lying around in the file
delete pkg.content._id
// ditto
delete pkg.content.gitHead
// if the repo is empty, remove it.
if (!pkg.content.repository) {
delete pkg.content.repository
}
// readJson filters out empty descriptions, but init-package-json
// traditionally leaves them alone
if (!pkg.content.description) {
pkg.content.description = pzData.description
}
// optionalDependencies don't need to be repeated in two places
if (pkg.content.dependencies) {
if (pkg.content.optionalDependencies) {
for (const name of Object.keys(pkg.content.optionalDependencies)) {
delete pkg.content.dependencies[name]
}
}
if (Object.keys(pkg.content.dependencies).length === 0) {
delete pkg.content.dependencies
}
}
const stringified = JSON.stringify(pkg.content, null, 2) + '\n'
const msg = util.format('%s:\n\n%s\n', packageFile, stringified)
if (yes) {
await pkg.save()
if (!config.get('silent')) {
// eslint-disable-next-line no-console
console.log(`Wrote to ${msg}`)
}
return pkg.content
}
// eslint-disable-next-line no-console
console.log(`About to write to ${msg}`)
const ok = await read({ prompt: 'Is this OK? ', default: 'yes' })
if (!ok || !ok.toLowerCase().startsWith('y')) {
// eslint-disable-next-line no-console
console.log('Aborted.')
return
}
await pkg.save()
return pkg.content
}
module.exports = init
module.exports.yes = isYes

66
package/node_modules/init-package-json/package.json generated vendored Normal file
View File

@@ -0,0 +1,66 @@
{
"name": "init-package-json",
"version": "6.0.3",
"main": "lib/init-package-json.js",
"scripts": {
"test": "tap",
"lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
"postlint": "template-oss-check",
"lintfix": "npm run lint -- --fix",
"snap": "tap",
"posttest": "npm run lint",
"template-oss-apply": "template-oss-apply --force"
},
"repository": {
"type": "git",
"url": "git+https://github.com/npm/init-package-json.git"
},
"author": "GitHub Inc.",
"license": "ISC",
"description": "A node module to get your node module started",
"dependencies": {
"@npmcli/package-json": "^5.0.0",
"npm-package-arg": "^11.0.0",
"promzard": "^1.0.0",
"read": "^3.0.1",
"semver": "^7.3.5",
"validate-npm-package-license": "^3.0.4",
"validate-npm-package-name": "^5.0.0"
},
"devDependencies": {
"@npmcli/config": "^8.2.0",
"@npmcli/eslint-config": "^4.0.0",
"@npmcli/template-oss": "4.22.0",
"tap": "^16.0.1"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
},
"tap": {
"test-ignore": "fixtures/",
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
],
"timeout": 300
},
"keywords": [
"init",
"package.json",
"package",
"helper",
"wizard",
"wizerd",
"prompt",
"start"
],
"files": [
"bin/",
"lib/"
],
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"version": "4.22.0",
"publish": true
}
}