初始化fy

This commit is contained in:
yziiy
2025-08-11 11:51:38 +08:00
parent 98ce20e897
commit 7e21160e13
19770 changed files with 3108698 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
#!/usr/bin/env node
const crossEnv = require('..')
crossEnv(process.argv.slice(2), {shell: true})

View File

@@ -0,0 +1,5 @@
#!/usr/bin/env node
const crossEnv = require('..')
crossEnv(process.argv.slice(2))

View File

@@ -0,0 +1,32 @@
const path = require('path')
const isWindows = require('./is-windows')
module.exports = commandConvert
/**
* Converts an environment variable usage to be appropriate for the current OS
* @param {String} command Command to convert
* @param {Object} env Map of the current environment variable names and their values
* @param {boolean} normalize If the command should be normalized using `path`
* after converting
* @returns {String} Converted command
*/
function commandConvert(command, env, normalize = false) {
if (!isWindows()) {
return command
}
const envUnixRegex = /\$(\w+)|\${(\w+)}/g // $my_var or ${my_var}
const convertedCmd = command.replace(envUnixRegex, (match, $1, $2) => {
const varName = $1 || $2
// In Windows, non-existent variables are not replaced by the shell,
// so for example "echo %FOO%" will literally print the string "%FOO%", as
// opposed to printing an empty string in UNIX. See kentcdodds/cross-env#145
// If the env variable isn't defined at runtime, just strip it from the command entirely
return env[varName] ? `%${varName}%` : ''
})
// Normalization is required for commands with relative paths
// For example, `./cmd.bat`. See kentcdodds/cross-env#127
// However, it should not be done for command arguments.
// See https://github.com/kentcdodds/cross-env/pull/130#issuecomment-319887970
return normalize === true ? path.normalize(convertedCmd) : convertedCmd
}

View File

@@ -0,0 +1,95 @@
const {spawn} = require('cross-spawn')
const commandConvert = require('./command')
const varValueConvert = require('./variable')
module.exports = crossEnv
const envSetterRegex = /(\w+)=('(.*)'|"(.*)"|(.*))/
function crossEnv(args, options = {}) {
const [envSetters, command, commandArgs] = parseCommand(args)
const env = getEnvVars(envSetters)
if (command) {
const proc = spawn(
// run `path.normalize` for command(on windows)
commandConvert(command, env, true),
// by default normalize is `false`, so not run for cmd args
commandArgs.map(arg => commandConvert(arg, env)),
{
stdio: 'inherit',
shell: options.shell,
env,
},
)
process.on('SIGTERM', () => proc.kill('SIGTERM'))
process.on('SIGINT', () => proc.kill('SIGINT'))
process.on('SIGBREAK', () => proc.kill('SIGBREAK'))
process.on('SIGHUP', () => proc.kill('SIGHUP'))
proc.on('exit', (code, signal) => {
let crossEnvExitCode = code
// exit code could be null when OS kills the process(out of memory, etc) or due to node handling it
// but if the signal is SIGINT the user exited the process so we want exit code 0
if (crossEnvExitCode === null) {
crossEnvExitCode = signal === 'SIGINT' ? 0 : 1
}
process.exit(crossEnvExitCode) //eslint-disable-line no-process-exit
})
return proc
}
return null
}
function parseCommand(args) {
const envSetters = {}
let command = null
let commandArgs = []
for (let i = 0; i < args.length; i++) {
const match = envSetterRegex.exec(args[i])
if (match) {
let value
if (typeof match[3] !== 'undefined') {
value = match[3]
} else if (typeof match[4] === 'undefined') {
value = match[5]
} else {
value = match[4]
}
envSetters[match[1]] = value
} else {
// No more env setters, the rest of the line must be the command and args
let cStart = []
cStart = args
.slice(i)
// Regex:
// match "\'" or "'"
// or match "\" if followed by [$"\] (lookahead)
.map(a => {
const re = /\\\\|(\\)?'|([\\])(?=[$"\\])/g
// Eliminate all matches except for "\'" => "'"
return a.replace(re, m => {
if (m === '\\\\') return '\\'
if (m === "\\'") return "'"
return ''
})
})
command = cStart[0]
commandArgs = cStart.slice(1)
break
}
}
return [envSetters, command, commandArgs]
}
function getEnvVars(envSetters) {
const envVars = {...process.env}
if (process.env.APPDATA) {
envVars.APPDATA = process.env.APPDATA
}
Object.keys(envSetters).forEach(varName => {
envVars[varName] = varValueConvert(envSetters[varName], varName)
})
return envVars
}

View File

@@ -0,0 +1,2 @@
module.exports = () =>
process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE)

View File

@@ -0,0 +1,69 @@
const isWindows = require('./is-windows')
const pathLikeEnvVarWhitelist = new Set(['PATH', 'NODE_PATH'])
module.exports = varValueConvert
/**
* This will transform UNIX-style list values to Windows-style.
* For example, the value of the $PATH variable "/usr/bin:/usr/local/bin:."
* will become "/usr/bin;/usr/local/bin;." on Windows.
* @param {String} varValue Original value of the env variable
* @param {String} varName Original name of the env variable
* @returns {String} Converted value
*/
function replaceListDelimiters(varValue, varName = '') {
const targetSeparator = isWindows() ? ';' : ':'
if (!pathLikeEnvVarWhitelist.has(varName)) {
return varValue
}
return varValue.replace(/(\\*):/g, (match, backslashes) => {
if (backslashes.length % 2) {
// Odd number of backslashes preceding it means it's escaped,
// remove 1 backslash and return the rest as-is
return match.substr(1)
}
return backslashes + targetSeparator
})
}
/**
* This will attempt to resolve the value of any env variables that are inside
* this string. For example, it will transform this:
* cross-env FOO=$NODE_ENV BAR=\\$NODE_ENV echo $FOO $BAR
* Into this:
* FOO=development BAR=$NODE_ENV echo $FOO
* (Or whatever value the variable NODE_ENV has)
* Note that this function is only called with the right-side portion of the
* env var assignment, so in that example, this function would transform
* the string "$NODE_ENV" into "development"
* @param {String} varValue Original value of the env variable
* @returns {String} Converted value
*/
function resolveEnvVars(varValue) {
const envUnixRegex = /(\\*)(\$(\w+)|\${(\w+)})/g // $my_var or ${my_var} or \$my_var
return varValue.replace(
envUnixRegex,
(_, escapeChars, varNameWithDollarSign, varName, altVarName) => {
// do not replace things preceded by a odd number of \
if (escapeChars.length % 2 === 1) {
return varNameWithDollarSign
}
return (
escapeChars.substr(0, escapeChars.length / 2) +
(process.env[varName || altVarName] || '')
)
},
)
}
/**
* Converts an environment variable value to be appropriate for the current OS.
* @param {String} originalValue Original value of the env variable
* @param {String} originalName Original name of the env variable
* @returns {String} Converted value
*/
function varValueConvert(originalValue, originalName) {
return resolveEnvVars(replaceListDelimiters(originalValue, originalName))
}