mirror of
https://github.com/hanzoai/cross-env.git
synced 2026-09-24 16:58:15 +00:00
NOTE: For the vast majority of users running supported versions of Node.js, this should not require any changes and you can update without issue. BREAKING CHANGE: This is a major rewrite that changes the module format from CommonJS to ESM-only. The package now requires Node.js >=20 and only exports ESM modules (not relevant in most cases). BREAKING CHANGE: The package.json exports have been updated to remove CommonJS support. Only ESM imports are now supported. BREAKING CHANGE: All source files have been converted from JavaScript to TypeScript, requiring TypeScript-aware tooling for development. - Replace Jest with Vitest for testing - Convert all source files from .js to .ts with proper TypeScript types - Use zshy for ESM-only builds (removes CJS support) - Adopt @epic-web/config for TypeScript, ESLint, and Prettier - Update to Node.js >=20 requirement - Remove kcd-scripts dependency - Add comprehensive e2e tests with GitHub Actions matrix testing - Update GitHub workflow with caching and cross-platform testing - Modernize documentation and remove outdated sections - Update all dependencies to latest versions - Add proper TypeScript declarations and exports The tool maintains its original functionality while being completely modernized with the latest tooling and best practices Co-authored-by: GitHub Action <[email protected]>
161 lines
3.7 KiB
JavaScript
161 lines
3.7 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { spawn } from 'child_process'
|
|
import { dirname, join } from 'path'
|
|
import { fileURLToPath } from 'url'
|
|
|
|
const __filename = fileURLToPath(import.meta.url)
|
|
const __dirname = dirname(__filename)
|
|
|
|
// Path to the built cross-env-shell binary
|
|
const crossEnvShellPath = join(
|
|
__dirname,
|
|
'..',
|
|
'dist',
|
|
'bin',
|
|
'cross-env-shell.js',
|
|
)
|
|
|
|
function runCommand(command, args = []) {
|
|
return new Promise((resolve, reject) => {
|
|
const child = spawn('node', [command, ...args], {
|
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
env: { ...process.env },
|
|
})
|
|
|
|
let stdout = ''
|
|
let stderr = ''
|
|
|
|
child.stdout.on('data', (data) => {
|
|
stdout += data.toString()
|
|
})
|
|
|
|
child.stderr.on('data', (data) => {
|
|
stderr += data.toString()
|
|
})
|
|
|
|
child.on('close', (code) => {
|
|
if (code === 0) {
|
|
resolve({ stdout, stderr, code })
|
|
} else {
|
|
reject(new Error(`Command failed with code ${code}: ${stderr}`))
|
|
}
|
|
})
|
|
|
|
child.on('error', (error) => {
|
|
reject(error)
|
|
})
|
|
})
|
|
}
|
|
|
|
function runShellCommand(shellCommand, envVars = {}) {
|
|
const envArgs = Object.entries(envVars).map(
|
|
([key, value]) => `${key}=${value}`,
|
|
)
|
|
return runCommand(crossEnvShellPath, [...envArgs, shellCommand])
|
|
}
|
|
|
|
async function runTests() {
|
|
console.log('๐งช Running cross-env-shell e2e tests...')
|
|
|
|
const tests = [
|
|
{
|
|
name: 'Basic shell environment variable',
|
|
test: async () => {
|
|
const result = await runShellCommand('echo $TEST_VAR', {
|
|
TEST_VAR: 'hello world',
|
|
})
|
|
if (result.stdout.trim() !== 'hello world') {
|
|
throw new Error(
|
|
`Expected 'hello world', got '${result.stdout.trim()}'`,
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: 'Multiple shell environment variables',
|
|
test: async () => {
|
|
const result = await runShellCommand('echo "$VAR1 $VAR2"', {
|
|
VAR1: 'hello',
|
|
VAR2: 'world',
|
|
})
|
|
// The shell will handle this according to its own rules
|
|
if (
|
|
!result.stdout.trim().includes('hello') ||
|
|
!result.stdout.trim().includes('world')
|
|
) {
|
|
throw new Error(
|
|
`Expected output to contain 'hello' and 'world', got '${result.stdout.trim()}'`,
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: 'Shell command with environment variable in command',
|
|
test: async () => {
|
|
const result = await runShellCommand('echo $MESSAGE', {
|
|
MESSAGE: 'hello from shell',
|
|
})
|
|
if (!result.stdout.trim().includes('hello from shell')) {
|
|
throw new Error(
|
|
`Expected output to contain 'hello from shell', got '${result.stdout.trim()}'`,
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: 'Shell command with environment variable substitution',
|
|
test: async () => {
|
|
const result = await runShellCommand('echo "Value is: $SUB_VAR"', {
|
|
SUB_VAR: 'substituted',
|
|
})
|
|
if (!result.stdout.trim().includes('substituted')) {
|
|
throw new Error(
|
|
`Expected output to contain 'substituted', got '${result.stdout.trim()}'`,
|
|
)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: 'Shell command with special characters in env var',
|
|
test: async () => {
|
|
const result = await runShellCommand('echo "$SPECIAL_VAR"', {
|
|
SPECIAL_VAR: 'test@#$%^&*()_+-=[]{}|;:,.<>?',
|
|
})
|
|
if (!result.stdout.trim().includes('test@#$%^&*()_+-=[]{}|;:,.<>?')) {
|
|
throw new Error(
|
|
`Expected output to contain special characters, got '${result.stdout.trim()}'`,
|
|
)
|
|
}
|
|
},
|
|
},
|
|
]
|
|
|
|
let passed = 0
|
|
let failed = 0
|
|
|
|
for (const test of tests) {
|
|
try {
|
|
console.log(` โ ${test.name}`)
|
|
await test.test()
|
|
passed++
|
|
} catch (error) {
|
|
console.log(` โ ${test.name}: ${error.message}`)
|
|
failed++
|
|
}
|
|
}
|
|
|
|
console.log(`\n๐ Test Results: ${passed} passed, ${failed} failed`)
|
|
|
|
if (failed > 0) {
|
|
process.exit(1)
|
|
}
|
|
|
|
console.log('โ
All cross-env-shell e2e tests passed!')
|
|
}
|
|
|
|
runTests().catch((error) => {
|
|
console.error('โ Test runner failed:', error)
|
|
process.exit(1)
|
|
})
|