@wyxos/zephyr 0.9.12 → 0.9.13

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": "@wyxos/zephyr",
3
- "version": "0.9.12",
3
+ "version": "0.9.13",
4
4
  "description": "A streamlined deployment tool for web applications with intelligent Laravel project detection",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",
@@ -1,6 +1,6 @@
1
1
  import * as localRepo from '../../deploy/local-repo.mjs'
2
2
  import * as preflight from '../../deploy/preflight.mjs'
3
- import {commandExists} from '../../utils/command.mjs'
3
+ import {commandExists, formatCommandError} from '../../utils/command.mjs'
4
4
 
5
5
  async function getGitStatus(rootDir, {runCommandCapture} = {}) {
6
6
  return await localRepo.getGitStatus(rootDir, {runCommandCapture})
@@ -98,7 +98,7 @@ async function runLocalLaravelBuild(rootDir, {runCommand, logProcessing, logSucc
98
98
  )
99
99
  }
100
100
 
101
- throw new Error(`Local frontend build failed. Fix build failures before deploying.\n${error.message}`)
101
+ throw new Error(`Local frontend build failed. Fix build failures before deploying.\n${formatCommandError(error)}`)
102
102
  }
103
103
  }
104
104
 
@@ -106,7 +106,7 @@ async function runLocalLaravelTests(rootDir, {runCommand, logProcessing, logSucc
106
106
  logProcessing?.('Running Laravel tests locally...')
107
107
 
108
108
  try {
109
- await runCommand(testCommand.command, testCommand.args, {cwd: rootDir})
109
+ await runCommand(testCommand.command, testCommand.args, {cwd: rootDir, capture: true})
110
110
  logSuccess?.('Local tests passed.')
111
111
  } catch (error) {
112
112
  if (error.code === 'ENOENT') {
@@ -116,7 +116,7 @@ async function runLocalLaravelTests(rootDir, {runCommand, logProcessing, logSucc
116
116
  )
117
117
  }
118
118
 
119
- throw new Error(`Local tests failed. Fix test failures before deploying.\n${error.message}`)
119
+ throw new Error(`Local tests failed. Fix test failures before deploying.\n${formatCommandError(error)}`)
120
120
  }
121
121
  }
122
122
 
@@ -1,6 +1,7 @@
1
1
  import { getCurrentBranch as getCurrentBranchImpl, getUpstreamRef as getUpstreamRefImpl } from '../utils/git.mjs'
2
2
  import {hasPrePushHook} from './preflight.mjs'
3
3
  import {gitCommitArgs, gitPushArgs} from '../utils/git-hooks.mjs'
4
+ import {formatCommandError} from '../utils/command.mjs'
4
5
  import {
5
6
  formatWorkingTreePreview,
6
7
  parseWorkingTreeEntries,
@@ -207,6 +208,13 @@ async function commitAndPushPendingChanges(targetBranch, rootDir, {
207
208
  await runCommand(command, args, { cwd })
208
209
  return undefined
209
210
  }
211
+ const runCapturedCommand = async (command, args) => {
212
+ try {
213
+ await runCommand(command, args, {cwd: rootDir, capture: true})
214
+ } catch (error) {
215
+ throw new Error(formatCommandError(error))
216
+ }
217
+ }
210
218
 
211
219
  const suggestedCommitMessage = await suggestCommitMessage(rootDir, {
212
220
  runCommand: captureAwareRunCommand,
@@ -244,10 +252,10 @@ async function commitAndPushPendingChanges(targetBranch, rootDir, {
244
252
  }
245
253
 
246
254
  logProcessing?.('Staging all pending changes before deployment...')
247
- await runCommand('git', ['add', '-A'], { cwd: rootDir })
255
+ await runCapturedCommand('git', ['add', '-A'])
248
256
 
249
257
  logProcessing?.('Committing pending changes before deployment...')
250
- await runCommand('git', gitCommitArgs(['-m', message], {skipGitHooks}), { cwd: rootDir })
258
+ await runCapturedCommand('git', gitCommitArgs(['-m', message], {skipGitHooks}))
251
259
 
252
260
  const prePushHookPresent = await hasPrePushHook(rootDir)
253
261
  if (prePushHookPresent) {
@@ -259,10 +267,10 @@ async function commitAndPushPendingChanges(targetBranch, rootDir, {
259
267
  }
260
268
 
261
269
  try {
262
- await runCommand('git', gitPushArgs(['origin', targetBranch], {skipGitHooks}), { cwd: rootDir })
270
+ await runCapturedCommand('git', gitPushArgs(['origin', targetBranch], {skipGitHooks}))
263
271
  } catch (error) {
264
272
  if (prePushHookPresent) {
265
- throw new Error(`Git push failed while the pre-push hook was running. See hook output above.\n${error.message}`)
273
+ throw new Error(`Git push failed while the pre-push hook was running.\n${error.message}`)
266
274
  }
267
275
 
268
276
  throw error
@@ -2,6 +2,7 @@ import fs from 'node:fs/promises'
2
2
  import path from 'node:path'
3
3
 
4
4
  import {gitCommitArgs} from '../utils/git-hooks.mjs'
5
+ import {formatCommandError} from '../utils/command.mjs'
5
6
 
6
7
  export async function hasPrePushHook(rootDir) {
7
8
  const hookPaths = [
@@ -137,14 +138,22 @@ export async function runLinting(rootDir, {
137
138
 
138
139
  if (selectedLintCommand.type === 'npm') {
139
140
  logProcessing?.('Running npm lint...')
140
- await runCommand(selectedLintCommand.command, selectedLintCommand.args, { cwd: rootDir })
141
+ try {
142
+ await runCommand(selectedLintCommand.command, selectedLintCommand.args, {cwd: rootDir, capture: true})
143
+ } catch (error) {
144
+ throw new Error(`Linting failed. Fix lint failures before deploying.\n${formatCommandError(error)}`)
145
+ }
141
146
  logSuccess?.('Linting completed.')
142
147
  return true
143
148
  }
144
149
 
145
150
  if (selectedLintCommand.type === 'pint') {
146
151
  logProcessing?.('Running Laravel Pint...')
147
- await runCommand(selectedLintCommand.command, selectedLintCommand.args, { cwd: rootDir })
152
+ try {
153
+ await runCommand(selectedLintCommand.command, selectedLintCommand.args, {cwd: rootDir, capture: true})
154
+ } catch (error) {
155
+ throw new Error(`Laravel Pint failed. Fix formatting failures before deploying.\n${formatCommandError(error)}`)
156
+ }
148
157
  logSuccess?.('Linting completed.')
149
158
  return true
150
159
  }
@@ -166,7 +175,7 @@ export async function runBuild(rootDir, {
166
175
  }
167
176
 
168
177
  logProcessing?.('Running local frontend build...')
169
- await runCommand(selectedBuildCommand.command, selectedBuildCommand.args, {cwd: rootDir})
178
+ await runCommand(selectedBuildCommand.command, selectedBuildCommand.args, {cwd: rootDir, capture: true})
170
179
  logSuccess?.('Local frontend build completed.')
171
180
  return true
172
181
  }
@@ -12,12 +12,11 @@ export function commandExists(command) {
12
12
  const resolvedCommand = resolveCommandForPlatform(command)
13
13
 
14
14
  // On Windows, use 'where', on Unix use 'which'
15
- const checker = DEFAULT_IS_WINDOWS ? 'where' : 'which'
15
+ const checker = DEFAULT_IS_WINDOWS ? 'where.exe' : 'which'
16
16
 
17
17
  try {
18
18
  const result = spawnSync(checker, [resolvedCommand], {
19
- stdio: ['ignore', 'pipe', 'ignore'],
20
- shell: DEFAULT_IS_WINDOWS
19
+ stdio: ['ignore', 'pipe', 'ignore']
21
20
  })
22
21
  return result.status === 0
23
22
  } catch {
@@ -67,7 +66,11 @@ function quoteForCmd(arg) {
67
66
  return value
68
67
  }
69
68
 
70
- export async function runCommand(command, args, { cwd = process.cwd(), stdio = 'inherit' } = {}) {
69
+ export async function runCommand(command, args, { cwd = process.cwd(), stdio = 'inherit', capture = false } = {}) {
70
+ if (capture) {
71
+ return runCommandCapture(command, args, {cwd})
72
+ }
73
+
71
74
  const resolvedCommand = resolveCommandForPlatform(command)
72
75
  const useShell = isWindowsShellShim(resolvedCommand) || shouldUseShellOnWindows(command)
73
76
 
@@ -152,3 +155,23 @@ export async function runCommandCapture(command, args, { cwd = process.cwd() } =
152
155
  })
153
156
  }
154
157
 
158
+ export function formatCapturedCommandOutput(error) {
159
+ const sections = [
160
+ ['stdout', error?.stdout],
161
+ ['stderr', error?.stderr]
162
+ ]
163
+ .map(([label, value]) => {
164
+ const text = typeof value === 'string' ? value.trim() : ''
165
+ return text ? `[${label}]\n${text}` : null
166
+ })
167
+ .filter(Boolean)
168
+
169
+ return sections.join('\n')
170
+ }
171
+
172
+ export function formatCommandError(error) {
173
+ const message = error?.message ?? String(error)
174
+ const output = formatCapturedCommandOutput(error)
175
+
176
+ return output ? `${message}\n${output}` : message
177
+ }