Basics In Node.js, spawn is a method provided by the child_process module it used to launch a new process and execute a command in that process spawn function returns a new ChildProcess object, which allows you to interact with the spawned process ChildProcess emits various events, such as stdout (standard output), stderr (standard error), and close (when the process exits). we can interact with the spawned process through its stdin , stdout , and stderr streams. This allows you to send input to the process and capture its output
const { spawn } = require('child_process');
const ls = spawn('ls', ['-l', '/usr']);
// Event listeners for the spawned process
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
promise version
const { red, white, grey } = require('chalk')
// const { spawn } = require('node:child_process')
const { spawn } = require('cross-spawn')
// https://nodejs.org/api/child_process.html#child_processspawncommand-args-options
const currentDir = __dirname
const runCommand = ({
command = 'echo "looks like you forgot to provide the terminal command"',
args = [],
options = {
cwd: currentDir,
shell: true,
stdio: 'inherit'
}
}) => {
return new Promise((resolve, reject) => {
const process = spawn(command, args, options)
process.on('message', (msg) => {
console.log(`🔈 ${white(msg)}`)
})
process.on('close', async (code) => {
if (code !== 0) {
console.log(grey('❌ command is failed'))
console.log(grey(JSON.stringify({ command, args, options, code }, null, 2)))
return reject(new Error(`Execution of command "${command}" failed with status ${code}. CWD: ${options.cwd}`))
}
console.log(grey('✅ command is finished'))
return resolve()
})
process.on('error', (err) => {
console.log(`😤 err: ${red(err.toString())}`)
console.log(red(JSON.stringify({ command, args, options, err }, null, 2)))
return reject(new Error(`Execution of command "${command}" failed (in ${options.cwd}): ${err.message}`))
})
process.stdout?.on('data', (data) => {
console.log(`${white('🗣️ stdout:')} ${grey(data.toString())}`)
})
process.stderr?.on('data', (data) => {
console.log(`🤬 stderr: ${red(data.toString())}`)
})
})
}
module.exports = { runCommand }
remove folders
const { underline, yellow, grey, green } = require('chalk')
const { runCommand } = require('../utils/runCommand')
const { getLambdasFromFileSystem } = require('./getLambdasFromFileSystem')
const { chooseLambdaFolderPaths } = require('../prompts')
const deleteNodeModules = async () => {
const lambdas = await getLambdasFromFileSystem()
const lambdaFolderPaths = await chooseLambdaFolderPaths({ lambdas })
await Promise.all(lambdaFolderPaths.map(async (dir) => {
console.log(`> [${yellow('~')}] 🗂️ ${dir}/node_modules: ${grey('delete')}`)
await runCommand({
command: 'rm',
args: ['-rf', 'node_modules'],
options: { cwd: dir }
})
console.log(`> [${green('+')}] 🗂️ ${dir}/node_modules: ${grey('delete')}`)
}))
}
deleteNodeModules()
module.exports = { deleteNodeModules }
npm ci
const { runCommand } = require('../utils/runCommand')
const npmCiFromRoot = async () => {
await runCommand({
command: 'npm',
args: ['ci']
})
}
npmCiFromRoot()
npm i in folders
const { runCommand } = require('../utils/runCommand')
const npmI = async ({ dirs }) => {
await Promise.all(dirs.map(async (dir) => {
await runCommand({
command: 'npm',
args: ['i'],
options: { cwd: dir }
})
}))
}
module.exports = { npmI }
run tests in folders
const { runCommand } = require('../utils/runCommand')
const test = async ({ lambdaFolderPaths }) => {
await Promise.all(lambdaFolderPaths.map(async (dir) => {
await runCommand({
command: 'npm',
args: ['run', 'test'],
options: {
cwd: dir,
stdio: 'inherit'
}
})
}))
}
module.exports = { test }
run command from node modules
const { runCommand } = require('../utils/runCommand')
const builtTemplateYaml = async () => {
await runCommand({
command: './node_modules/.bin/cfbuild',
args: ['template', '-t', 'template.yaml', '-o', 'built_template.yaml'],
options: { stdio: 'inherit' }
})
}
module.exports = { builtTemplateYaml }
create cloudformaton package
const { runCommand } = require('../utils/runCommand')
const { getAppRootDir } = require('../utils/getAppRootDir')
const { getPackageName } = require('../utils')
const packagedTemplateYaml = async () => {
const packageName = await getPackageName()
await runCommand({
command: 'aws',
args: [
'cloudformation',
'package',
'--template-file', 'built_template.yaml',
'--s3-bucket', 'heeros-cloudformation-build',
'--s3-prefix', packageName,
'--output-template-file', 'packaged_template.yaml'
],
options: {
cwd: getAppRootDir()
}
})
}
module.exports = { packagedTemplateYaml }