@mono-labs/cli 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # Haste CLI Tool
2
+
3
+ A fast and efficient CLI tool for building and deploying projects.
4
+
5
+ ## Installation
6
+
7
+ ### Local Development
8
+ ```bash
9
+ # Install dependencies
10
+ yarn install
11
+
12
+ # Test the CLI locally
13
+ yarn start --help
14
+ ```
15
+
16
+ ### Global Installation
17
+ ```bash
18
+ # Install globally using yarn
19
+ yarn global add .
20
+
21
+ # Or link for development
22
+ yarn link
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Build Command
28
+ ```bash
29
+ # Basic build
30
+ haste build
31
+
32
+ # Build with specific environment
33
+ haste build --env production
34
+
35
+ # Build with watch mode
36
+ haste build --watch
37
+ ```
38
+
39
+ ### Deploy Command
40
+ ```bash
41
+ # Basic deploy
42
+ haste deploy
43
+
44
+ # Deploy to specific environment
45
+ haste deploy --env staging
46
+
47
+ # Force deployment
48
+ haste deploy --force
49
+ ```
50
+
51
+ ## Available Commands
52
+
53
+ - `haste build` - Build the project
54
+ - `haste deploy` - Deploy the project
55
+ - `haste --help` - Show help information
56
+ - `haste --version` - Show version information
57
+
58
+ ## Development
59
+
60
+ ### Project Structure
61
+ ```
62
+ haste/
63
+ ├── bin/
64
+ │ └── haste.js # Main CLI entry point
65
+ ├── lib/
66
+ │ └── commands/
67
+ │ ├── build.js # Build command implementation
68
+ │ └── deploy.js # Deploy command implementation
69
+ ├── package.json
70
+ └── README.md
71
+ ```
72
+
73
+ ### Adding New Commands
74
+
75
+ 1. Create a new file in `lib/commands/`
76
+ 2. Export an `execute` function
77
+ 3. Add the command to `bin/haste.js`
78
+
79
+ ### Dependencies
80
+
81
+ - **commander** - Command-line argument parsing
82
+ - **chalk** - Terminal string styling
83
+
84
+ ## License
85
+
86
+ MIT
package/bin/haste.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../lib/index.js'
package/index.js ADDED
@@ -0,0 +1,3 @@
1
+ const haste = require('./lib/index');
2
+
3
+ module.exports = haste;
package/lib/app.js ADDED
@@ -0,0 +1,28 @@
1
+ import { Command } from 'commander'
2
+
3
+ import { STAGING_URL } from './config.js'
4
+
5
+ const version = '0.0.1'
6
+ export const program = new Command()
7
+
8
+ program.name('haste').description('CLI to manage Haste project').version(version)
9
+ const EXPO_PUBLIC_API_URL =
10
+ (process.env.EXPO_PUBLIC_API_URL && process.env.EXPO_PUBLIC_API_URL.length > 0) || STAGING_URL
11
+ const CLIENT_NAME = process.env.CLIENT_NAME || 'jawdrop'
12
+
13
+ export const generateEnvValues = (
14
+ forceProd = false,
15
+ ngrokUrl = 'localhost:3000',
16
+ useAtlas = false,
17
+ ) => {
18
+ return {
19
+ ...process.env,
20
+ EXPO_PUBLIC_API_URL,
21
+
22
+ CLIENT_NAME,
23
+ EXPO_FORCE_PROD: forceProd,
24
+ EXPO_PRIVATE_API_URL: ngrokUrl,
25
+ EXPO_UNSTABLE_ATLAS: useAtlas,
26
+ EXPO_CLIENT_NAME: CLIENT_NAME,
27
+ }
28
+ }
@@ -0,0 +1,71 @@
1
+ import { spawn } from 'child_process'
2
+
3
+ import { program } from '../../app.js'
4
+ import { generateEnvValues } from '../../app.js'
5
+ import { STAGING_URL } from '../../config.js'
6
+
7
+ const allowedPlatforms = ['ios', 'android']
8
+ function selectPlatform(platform) {
9
+ if (!allowedPlatforms.includes(platform))
10
+ throw new Error(`Invalid platform selected, must be one of ${allowedPlatforms.join(', ')}`)
11
+ return platform
12
+ }
13
+
14
+ function selectProfile(dev, preview, prod, profile) {
15
+ if (profile && (dev || preview || prod)) {
16
+ throw new Error('Conflict between profile and dev/preview/prod')
17
+ }
18
+ if (dev) return 'development'
19
+ if (preview) return 'preview'
20
+ if (prod) return 'production'
21
+ if (profile) return profile
22
+ return 'development'
23
+ }
24
+
25
+ program
26
+ .command('build')
27
+ .description('Execute eas build command')
28
+ .option('-d', 'Build to target development profile')
29
+ .option('-p', 'Build to target preview profile')
30
+ .option('--live', 'Build to target production profile')
31
+ .option('--profile <string>', 'Build profile to use')
32
+ .option('--os, --platform <string>', 'Platform to build', 'ios')
33
+ .option('-f, --force', 'Force build to target production server')
34
+ .action((str, options) => {
35
+ console.log('its me')
36
+ const platform = selectPlatform(str.platform)
37
+ const profile = selectProfile(str.d, str.p, str.live, str.profile)
38
+ const isDev = profile === 'development'
39
+ //console.log(options);
40
+ console.log(`Building ${platform} with profile ${'`'}${profile}${'`'}`)
41
+ console.log('\n\n\n')
42
+
43
+ const EXPO_FORCE_PRODUCTION = str.force || isDev ? 'false' : 'true'
44
+ console.log('EXPO_FORCE_PRODUCTION', EXPO_FORCE_PRODUCTION)
45
+
46
+ let envObj = generateEnvValues(EXPO_FORCE_PRODUCTION, '', false)
47
+ if (!isDev) {
48
+ envObj.EXPO_PUBLIC_API_URL = `${STAGING_URL}`
49
+ envObj.EXPO_FORCE_PROD = 'true'
50
+ } else {
51
+ const publicUrl = process.env.EXPO_PUBLIC_API_URL || `${STAGING_URL}`
52
+ envObj.EXPO_PUBLIC_API_URL = publicUrl
53
+ }
54
+ console.log('envObj', envObj)
55
+ envObj.EAS_BUILD_PROFILE = profile // your custom variable
56
+
57
+ const command = `w expo-app eas build --profile ${profile} --platform ${platform}`
58
+ console.log('Running command:', command)
59
+ const child = spawn('yarn', [command], {
60
+ stdio: 'inherit',
61
+ shell: true, // required if using shell-style commands or cross-platform support
62
+ env: {
63
+ ...envObj,
64
+ },
65
+ })
66
+
67
+ child.on('exit', (code) => {
68
+ console.log(`Process exited with code ${code}`)
69
+ process.exit(code ?? 0)
70
+ })
71
+ })
@@ -0,0 +1,412 @@
1
+ import { spawn } from 'child_process'
2
+ import fs from 'fs'
3
+ import { program } from '../../app.js'
4
+ import { generateEnvValues } from '../../app.js'
5
+ import { STAGING_URL } from '../../config.js'
6
+ import { getHasteConfig, getHasteFiles, getRootDirectory, getRootJson } from '../loadFromRoot.js'
7
+ import { config } from 'process'
8
+
9
+ console.log('getRootDirectory', getRootDirectory())
10
+ console.log('rootJson', getRootJson())
11
+ const files = getHasteConfig()
12
+
13
+ console.log('Haste files', files)
14
+
15
+ const fileKeys = Object.keys(files)
16
+ let dataLayer = {}
17
+
18
+ fileKeys.forEach((key) => {
19
+ const commandName = key
20
+
21
+ console.log('Haste file key', commandName, files[key])
22
+ const configObject = files[commandName] || {}
23
+ const optionsData = configObject.options || {}
24
+ const optionsList = Object.keys(optionsData)
25
+
26
+ console.log('optionsList', optionsList, optionsData)
27
+
28
+ let currentCommand = program.command(commandName).description('Execute eas build command')
29
+
30
+ if (configObject.argument) {
31
+ console.log('has argument', configObject.argument)
32
+ // .argument('<input>', 'path to input file') // required
33
+ // .argument('[output]', 'optional output file') // optional
34
+ const argumentRequired = configObject.argument.required || false
35
+ const argCommand = argumentRequired
36
+ ? `<${configObject.argument.type || 'string'}>`
37
+ : `[${configObject.argument.type || 'string'}]`
38
+ currentCommand = currentCommand.argument(argCommand, configObject.argument.description || '')
39
+ }
40
+
41
+ optionsList.forEach((optionKey) => {
42
+ const type = optionsData[optionKey].type || 'boolean'
43
+
44
+ if (type === 'string') {
45
+ if (optionsData[optionKey].shortcut) {
46
+ currentCommand = currentCommand.option(
47
+ `-${optionsData[optionKey].shortcut}, --${optionKey} <${optionKey}>`,
48
+ optionsData[optionKey].description || ''
49
+ )
50
+ console.log('optionKey', optionKey, optionsData[optionKey])
51
+ dataLayer[optionKey] = optionsData[optionKey].default || ''
52
+ } else {
53
+ currentCommand = currentCommand.option(
54
+ `--${optionKey} <${optionKey}>`,
55
+ optionsData[optionKey].description || ''
56
+ )
57
+ dataLayer[optionKey] = optionsData[optionKey].default || ''
58
+ }
59
+ } else {
60
+ if (optionsData[optionKey].shortcut) {
61
+ currentCommand = currentCommand.option(
62
+ `-${optionsData[optionKey].shortcut}, --${optionKey}`,
63
+ optionsData[optionKey].description || ''
64
+ )
65
+ console.log('optionKey', optionKey, optionsData[optionKey])
66
+ dataLayer[optionKey] = optionsData[optionKey].default || false
67
+ } else {
68
+ currentCommand = currentCommand.option(
69
+ `--${optionKey}`,
70
+ optionsData[optionKey].description || ''
71
+ )
72
+ dataLayer[optionKey] = optionsData[optionKey].default || false
73
+ }
74
+ }
75
+ })
76
+
77
+ function verifyOptionValues(optionKey, value) {
78
+ const optionInfo = optionsData[optionKey]
79
+ if (optionInfo && optionInfo.options) {
80
+ if (!optionInfo.options.includes(value)) {
81
+ throw new Error(
82
+ `Invalid value for --${optionKey}: ${value}. Valid options are: ${optionInfo.options.join(
83
+ ', '
84
+ )}`
85
+ )
86
+ }
87
+ }
88
+ return value
89
+ }
90
+
91
+ currentCommand.action(async (arg, cmd) => {
92
+ console.log('test:')
93
+ console.log('cmd', cmd)
94
+ console.log('arg', arg)
95
+ const optionVals = cmd.opts ? cmd.opts() : cmd
96
+ console.log('arg', arg)
97
+ console.log('optionVals')
98
+
99
+ const opts = optionVals
100
+ Object.keys(opts).forEach((k) => {
101
+ opts[k] = verifyOptionValues(k, opts[k])
102
+ })
103
+ const argVal = arg ? arg : configObject.argument.default
104
+ console.log('argVal', argVal)
105
+ dataLayer = { ...dataLayer, ...opts, arg: argVal }
106
+ console.log('opts', opts)
107
+ console.log('firstDataLayer', dataLayer)
108
+ await runHasteCommand(configObject, opts)
109
+
110
+ // const devConfig = configObject.environments ? configObject.environments.dev : {}
111
+ // const productionConfig = configObject.environments ? configObject.environments.production : {}
112
+ // let envObj = {}
113
+ // if (options.stage) {
114
+ // envObj = { ...devConfig }
115
+ // } else {
116
+ // envObj = { ...productionConfig }
117
+ // }
118
+
119
+ // // You can decide what happens when each flag is passed.
120
+ // // Example: run `eas build` with different profiles.
121
+ // if (options.android) {
122
+ // console.log('→ Building Android (preview profile)…')
123
+ // //run('eas', ['build', '--platform', 'android', '--profile', 'preview'])
124
+ // } else if (options.ios) {
125
+ // console.log('→ Building iOS (production profile)…')
126
+ // //run('eas', ['build', '--platform', 'ios', '--profile', 'production'])
127
+ // } else {
128
+ // // console.log('No target specified. Use --android or --ios.')
129
+ // // program.help()
130
+ // console.log('objHaste.actions', configObject)
131
+ // const preactions = configObject['preactions'] || []
132
+ // const actions = configObject.actions || []
133
+ // console.log('preactions', preactions)
134
+ // for (const item of preactions) {
135
+ // console.log(`→ Running pre-action: ${item}`)
136
+ // await run(item, [], envObj)
137
+ // }
138
+ // for (const item of actions) {
139
+ // console.log(`→ Running action: ${item}`)
140
+ // run(item, [], envObj)
141
+ // }
142
+ // }
143
+ // })
144
+ })
145
+ })
146
+
147
+ // const commandName = 'test'
148
+ // program
149
+ // .command(commandName)
150
+ // .description('Execute eas build command')
151
+ // .option('--android', 'Build to target preview profile')
152
+ // .option('--ios', 'Build to target production profile')
153
+ // .option('--stage', 'Set environment to staging')
154
+ // .action((options) => {
155
+ // const configObject = objHaste[commandName] || {}
156
+
157
+ // const devConfig = configObject.environments ? configObject.environments.dev : {}
158
+ // const productionConfig = configObject.environments ? configObject.environments.production : {}
159
+ // let envObj = {}
160
+ // if (options.stage) {
161
+ // envObj = { ...devConfig }
162
+ // } else {
163
+ // envObj = { ...productionConfig }
164
+ // }
165
+
166
+ // // You can decide what happens when each flag is passed.
167
+ // // Example: run `eas build` with different profiles.
168
+ // if (options.android) {
169
+ // console.log('→ Building Android (preview profile)…')
170
+ // //run('eas', ['build', '--platform', 'android', '--profile', 'preview'])
171
+ // } else if (options.ios) {
172
+ // console.log('→ Building iOS (production profile)…')
173
+ // //run('eas', ['build', '--platform', 'ios', '--profile', 'production'])
174
+ // } else {
175
+ // // console.log('No target specified. Use --android or --ios.')
176
+ // // program.help()
177
+ // console.log('objHaste.actions', objHaste)
178
+ // for (const item of configObject.actions) {
179
+ // console.log(`→ Running action: ${item}`)
180
+ // run(item, [], envObj)
181
+ // }
182
+ // }
183
+ // })
184
+
185
+ const totalClosedActions = 0
186
+ // Utility to spawn and pipe child output
187
+ async function run(cmd, args, envObj = {}, count = 1) {
188
+ const child = spawn(cmd, args, {
189
+ stdio: 'inherit',
190
+ shell: true,
191
+ env: {
192
+ ...process.env,
193
+ ...envObj,
194
+ },
195
+ })
196
+ const isLast = count === totalClosedActions + 1
197
+
198
+ const exitAction = () => {
199
+ totalClosedActions++
200
+ process.exit(code)
201
+ }
202
+ if (!isLast) {
203
+ child.on('exit', (code) => {
204
+ exitAction()
205
+ })
206
+ child.on('sigint', () => {
207
+ exitAction()
208
+ })
209
+ }
210
+ if (isLast) {
211
+ child.on('exit', (code) => {
212
+ if (count < totalClosedActions) exitAction()
213
+ })
214
+ child.on('sigint', () => {
215
+ if (count < totalClosedActions) {
216
+ exitAction()
217
+ process.exit(code)
218
+ }
219
+ })
220
+ }
221
+ }
222
+
223
+ // Track background processes so we can kill them on exit
224
+ const bgChildren = new Set()
225
+
226
+ /** Run a command and resolve when it exits (attach stdio so you can see output). */
227
+ function runForeground(cmd, envObj = {}, options = {}) {
228
+ return new Promise((resolve, reject) => {
229
+ let lastLine = ''
230
+ let myTextData = ''
231
+ const child = spawn(cmd, {
232
+ shell: true,
233
+ env: { ...process.env, ...envObj },
234
+ stdio: ['inherit', 'pipe', 'pipe'], // stdin pass-through, capture out/err
235
+ })
236
+
237
+ const handleData = (chunk, isErr = false) => {
238
+ const text = chunk.toString()
239
+ console.log(text.toString().trim())
240
+ console.log('text', text)
241
+ myTextData = myTextData.concat(text)
242
+ console.log('myTextData', myTextData)
243
+
244
+ // Track last line
245
+ const lines = text.trim().split(/\r?\n/)
246
+ if (lines.length) {
247
+ lastLine = lines[lines.length - 1]
248
+ }
249
+ }
250
+
251
+ child.stdout.on('data', (chunk) => handleData(chunk, false))
252
+ child.stderr.on('data', (chunk) => handleData(chunk, true))
253
+
254
+ child.on('error', reject)
255
+ child.on('exit', (code, signal) => {
256
+ myTextData.concat('\n<<< CHILD PROCESS EXITED >>>\n')
257
+ console.log('myTextData', myTextData)
258
+ //const rx = /\{out\s*:\s*(.+?)\}/gs
259
+ // ^\{out:field-name \$\{([^}]+)\}\}$
260
+ const rx = /\{out:([^\s]+) (.*)\}\n/g
261
+ //const rx = /Project ([^\r\n]*)/
262
+ console.log('myTextData', myTextData)
263
+ const match = rx.exec(myTextData)
264
+
265
+ const rx3 = /\{out:(?<field>[^\s}]+)\s+(?<value>[^\s}]+)\}/g
266
+ const results = [...myTextData.matchAll(rx3)].map((m) => {
267
+ const layerIndex = m.groups.field
268
+ const matchValue = m.groups.value
269
+ console.log('matchValue', matchValue)
270
+ dataLayer[layerIndex] = matchValue
271
+
272
+ return {
273
+ field: m.groups.field,
274
+ value: m.groups.value,
275
+ }
276
+ })
277
+ console.log(results)
278
+
279
+ console.log('match', match)
280
+
281
+ if (signal) return reject(new Error(`${cmd} exited via signal ${signal}`))
282
+ if (code === 0) return resolve(lastLine) // resolve with last line
283
+ reject(new Error(`${cmd} exited with code ${code}. Last line: ${lastLine}`))
284
+ })
285
+ })
286
+ }
287
+
288
+ function runBackground(cmd, envObj = {}, options = {}, attached = false) {
289
+ const isWin = process.platform === 'win32'
290
+ // Expand ${0}, ${1}, ... from dataLayer into env strings
291
+ const newEnv = {}
292
+ const commandClone = cmd
293
+ for (const key of Object.keys(envObj)) {
294
+ let value = envObj[key]
295
+ if (typeof value === 'string') {
296
+ console.log('dataLayer', dataLayer)
297
+ Object.keys(dataLayer).map((k) => {
298
+ value = value.replace(new RegExp(`\\$\\{${k}\\}`, 'g'), dataLayer[k])
299
+ })
300
+ }
301
+ newEnv[key] = value
302
+ }
303
+
304
+ console.log('newEnv', newEnv)
305
+
306
+ const out = commandClone.replace(/\$\{([^}]+)\}/g, (match, key) => {
307
+ // keep 0/false, only treat null/undefined as missing
308
+ const v = dataLayer[key]
309
+ return v == null ? match : String(v)
310
+ })
311
+
312
+ return new Promise((resolve, reject) => {
313
+ const child = spawn(out, {
314
+ shell: true,
315
+ stdio: attached ? 'inherit' : 'ignore', // no output in this terminal
316
+ env: { ...process.env, ...newEnv },
317
+ // On POSIX, detach so we can signal the whole group; on Windows, DON'T.
318
+ detached: !attached && !isWin,
319
+ windowsHide: !attached && !isWin, // prevent new console window on Windows
320
+ })
321
+
322
+ // Only unref on POSIX when detached; on Windows keep it referenced.
323
+ if (!attached && !isWin) child.unref()
324
+
325
+ child.once('error', (err) => {
326
+ bgChildren.delete(child)
327
+ reject(err)
328
+ })
329
+
330
+ child.once('exit', (code, signal) => {
331
+ bgChildren.delete(child)
332
+ if (signal) return reject(new Error(`${cmd} exited via signal ${signal}`))
333
+ if (code === 0) return resolve()
334
+ reject(new Error(`${cmd} exited with code ${code}`))
335
+ })
336
+ })
337
+ }
338
+
339
+ /** Kill all background children (called on SIGINT/SIGTERM or when foreground ends). */
340
+ function killAllBackground() {
341
+ for (const child of Array.from(bgChildren)) {
342
+ try {
343
+ if (process.platform === 'win32') {
344
+ spawn('taskkill', ['/PID', String(child.pid), '/T', '/F'], { shell: true, stdio: 'ignore' })
345
+ } else {
346
+ process.kill(-child.pid, 'SIGTERM') // whole group
347
+ }
348
+ } catch {}
349
+ }
350
+ bgChildren.clear()
351
+ }
352
+
353
+ process.on('SIGINT', () => {
354
+ console.log('\nSIGINT')
355
+ killAllBackground()
356
+ process.exit(130)
357
+ })
358
+ process.on('SIGTERM', () => {
359
+ killAllBackground()
360
+ process.exit(143)
361
+ })
362
+
363
+ /** In your commander .action handler */
364
+ async function runHasteCommand(configObject, options = {}) {
365
+ const environments = configObject.environments
366
+ const devConfig = configObject.environments?.dev ?? {}
367
+ const productionConfig = configObject.environments?.stage ?? {}
368
+ console.log('options', options)
369
+ const awsProfile = process.env.CDK_DEPLOY_PROFILE || 'default'
370
+ console.log('prof', awsProfile)
371
+ const envObj = options.stage ? productionConfig : devConfig
372
+ envObj['AWS_PROFILE'] = awsProfile
373
+
374
+ const preactions = configObject.preactions ?? []
375
+ const actions = configObject.actions ?? []
376
+
377
+ console.log('environments', environments)
378
+
379
+ console.log('preactions', preactions)
380
+
381
+ // 1) Run preactions SEQUENTIALLY (each waits for previous to finish)
382
+ let num = 0
383
+ console.log('envObj', envObj)
384
+ for (const cmd of preactions) {
385
+ console.log(`→ preaction: ${cmd}`)
386
+ await runForeground(cmd, envObj, options)
387
+ num++
388
+ }
389
+
390
+ // 2) Run actions: background all but the last; attach to the last
391
+ if (actions.length === 0) return
392
+
393
+ const bg = actions.slice(0, -1)
394
+ const fg = actions[actions.length - 1]
395
+
396
+ for (const cmd of bg) {
397
+ console.log(`→ background action: ${cmd}`)
398
+ runBackground(cmd, envObj, options)
399
+ }
400
+
401
+ console.log(`→ foreground action (attached): ${fg}`)
402
+ try {
403
+ console.log('envObj', envObj)
404
+ await runBackground(fg, envObj, options, true)
405
+ } finally {
406
+ // When the foreground ends, clean up background processes too (optional)
407
+ killAllBackground()
408
+ }
409
+ }
410
+
411
+ //ACTION TYPES: preaction, action
412
+ //COMMAND TYPES: sequence, parallel
@@ -0,0 +1,44 @@
1
+ import assert from 'assert'
2
+ import { spawn } from 'child_process'
3
+ import { readFileSync } from 'fs'
4
+
5
+ import { program } from '../../app.js'
6
+ import { join } from 'node:path';
7
+ const packageJSON = JSON.parse(readFileSync(join(process.cwd(), 'package.json'), 'utf8'));
8
+
9
+ console.log('Deploy command loaded')
10
+
11
+ const awsObject = packageJSON['aws'] || {}
12
+
13
+ // const awsProfile = awsObject['profile'] || 'default'
14
+ const accountId = process.env.CDK_DEPLOY_ACCOUNT
15
+ const awsProfile = process.env.CDK_DEPLOY_PROFILE || 'default'
16
+
17
+ console.log('process.env', process.env)
18
+ console.log('CDK_DEPLOY_ACCOUNT', process.env.CDK_DEPLOY_PROFILE)
19
+ program
20
+ .command('deploy2')
21
+ .description('Execute cdk deploy command')
22
+ .argument('[<string>]', 'Environment to deploy')
23
+ .option('-d, --dev', 'Deploy to dev environment')
24
+ .option('-r, --region <region>', 'Region to deploy to')
25
+ .action((str, options) => {
26
+ const owner = str || 'dev'
27
+ const region = options.region || 'us-east-2'
28
+ console.log(`Deploying to ${owner} environment`)
29
+ const command = `workspace infra deploy`
30
+ const inputs = `-c owner=${owner} -c region=${region}`
31
+ console.log(`Inputs: ${inputs}`)
32
+ const child = spawn('yarn', [`${command} ${inputs}`], {
33
+ stdio: 'inherit',
34
+ shell: true, // required if using shell-style commands or cross-platform support
35
+ env: {
36
+ AWS_PROFILE: awsProfile,
37
+ },
38
+ })
39
+
40
+ child.on('exit', (code) => {
41
+ console.log(`Process exited with code ${code}`)
42
+ process.exit(code ?? 0)
43
+ })
44
+ })
@@ -0,0 +1,27 @@
1
+ import { spawn } from 'child_process'
2
+
3
+ import { program } from '../app.js'
4
+
5
+ program
6
+ .command('destroy')
7
+ .description('Destroys the current or specified cdk construct')
8
+ .argument('[<string>]', 'Environment to deploy')
9
+ .option('-d, --dev', 'Deploy to dev environment')
10
+ .option('-r, --region <region>', 'Region to deploy to')
11
+ .action((str, options) => {
12
+ const owner = str || 'dev'
13
+ const region = options.region || 'us-east-2'
14
+ console.log(`Deploying to ${owner} environment`)
15
+ const command = `workspace infra cdk destroy`
16
+ const inputs = `-c owner=${owner} -c region=${region}`
17
+ console.log(`Inputs: ${inputs}`)
18
+ const child = spawn('yarn', [`${command} ${inputs}`], {
19
+ stdio: 'inherit',
20
+ shell: true, // required if using shell-style commands or cross-platform support
21
+ })
22
+
23
+ child.on('exit', (code) => {
24
+ console.log(`Process exited with code ${code}`)
25
+ process.exit(code ?? 0)
26
+ })
27
+ })