@10stars/config 15.1.1 → 15.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@10stars/config",
3
- "version": "15.1.1",
3
+ "version": "15.1.2",
4
4
  "private": false,
5
5
  "bin": {
6
6
  "10config": "./src/index.ts"
package/src/index.ts CHANGED
@@ -145,7 +145,7 @@ Examples:
145
145
  commands.push({ label, command })
146
146
  i += 3
147
147
  } else {
148
- commands.push({ label: `cmd${commands.length + 1}`, command: arg! })
148
+ commands.push({ command: arg! })
149
149
  i++
150
150
  }
151
151
  }
package/src/runner.ts CHANGED
@@ -2,7 +2,7 @@ import { colors, getNextColor, type ColorName } from "./colors"
2
2
 
3
3
  export interface CommandConfig {
4
4
  /** Label shown as prefix in output */
5
- label: string
5
+ label?: string
6
6
  /** Command to run (string will be split by spaces, array used as-is) */
7
7
  command: string | string[]
8
8
  /** Color for the label (auto-assigned if not provided) */
@@ -10,7 +10,7 @@ export interface CommandConfig {
10
10
  }
11
11
 
12
12
  interface RunningProcess {
13
- label: string
13
+ label?: string
14
14
  proc: ReturnType<typeof Bun.spawn>
15
15
  prefix: string
16
16
  }
@@ -24,7 +24,11 @@ async function pipeOutput(
24
24
  const text = decoder.decode(chunk).trimEnd()
25
25
  if (text) {
26
26
  for (const line of text.split("\n")) {
27
- console.log(`${prefix} ${line}`)
27
+ if (prefix) {
28
+ console.log(`${prefix} ${line}`)
29
+ } else {
30
+ console.log(line)
31
+ }
28
32
  }
29
33
  }
30
34
  }
@@ -40,9 +44,13 @@ export async function runConcurrently(commands: CommandConfig[]): Promise<void>
40
44
  const processes: RunningProcess[] = []
41
45
 
42
46
  for (const config of commands) {
43
- const colorName = config.color ?? getNextColor()
44
- const colorFn = colors[colorName]
45
- const prefix = `[${colorFn(config.label)}]`
47
+ let prefix = ""
48
+ if (config.label) {
49
+ const colorName = config.color ?? getNextColor()
50
+ const colorFn = colors[colorName]
51
+ prefix = `[${colorFn(config.label)}]`
52
+ }
53
+
46
54
  const args = parseCommand(config.command)
47
55
 
48
56
  const proc = Bun.spawn(args, {
@@ -61,30 +69,40 @@ export async function runConcurrently(commands: CommandConfig[]): Promise<void>
61
69
  pipeOutput(proc.stderr, prefix)
62
70
  }
63
71
 
64
- // Handle SIGINT to kill all child processes
65
- const cleanup = () => {
72
+ // Kill all processes and exit
73
+ const killAll = (exitCode: number) => {
66
74
  for (const { proc } of processes) {
67
- proc.kill()
75
+ try {
76
+ proc.kill()
77
+ } catch {
78
+ // Process may already be dead
79
+ }
68
80
  }
69
- process.exit(0)
81
+ process.exit(exitCode)
70
82
  }
71
- process.on("SIGINT", cleanup)
72
- process.on("SIGTERM", cleanup)
73
83
 
74
- // Wait for all processes to complete
75
- const results = await Promise.all(
76
- processes.map(async ({ label, proc, prefix }) => {
77
- const exitCode = await proc.exited
78
- if (exitCode !== 0) {
79
- console.log(`${prefix} exited with code ${exitCode}`)
80
- }
81
- return { label, exitCode }
82
- }),
83
- )
84
+ // Handle SIGINT/SIGTERM to kill all child processes
85
+ process.on("SIGINT", () => killAll(0))
86
+ process.on("SIGTERM", () => killAll(0))
87
+
88
+ // Create a promise for each process that resolves on completion or rejects on failure
89
+ const processPromises = processes.map(async ({ label, proc, prefix }) => {
90
+ const exitCode = await proc.exited
91
+ if (exitCode !== 0) {
92
+ const labelText = label ? ` (${label})` : ""
93
+ console.error(
94
+ `\n${prefix} Process${labelText} exited with code ${exitCode}. Stopping all processes...`,
95
+ )
96
+ throw new Error(`Process failed with exit code ${exitCode}`)
97
+ }
98
+ return { label, exitCode }
99
+ })
84
100
 
85
- // Exit with non-zero if any process failed
86
- const failed = results.filter((r) => r.exitCode !== 0)
87
- if (failed.length > 0) {
88
- process.exit(1)
101
+ try {
102
+ // Wait for all to succeed - if any fails, it will throw and we catch it
103
+ await Promise.all(processPromises)
104
+ } catch {
105
+ // One process failed - kill all others and exit
106
+ killAll(1)
89
107
  }
90
108
  }