@wyxos/zephyr 0.2.1 → 0.2.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": "@wyxos/zephyr",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
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",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "scripts": {
11
11
  "test": "vitest",
12
- "release": "node publish.mjs"
12
+ "release": "node bin/zephyr.mjs --type=node"
13
13
  },
14
14
  "keywords": [
15
15
  "deployment",
@@ -4,43 +4,40 @@ import { dirname, join } from 'node:path'
4
4
  import { readFile } from 'node:fs/promises'
5
5
  import fs from 'node:fs'
6
6
  import path from 'node:path'
7
- import chalk from 'chalk'
8
7
  import process from 'node:process'
9
8
 
9
+ const STEP_PREFIX = '→'
10
+ const OK_PREFIX = '✔'
11
+ const WARN_PREFIX = '⚠'
12
+
10
13
  const IS_WINDOWS = process.platform === 'win32'
11
14
 
12
15
  function logStep(message) {
13
- console.log(chalk.yellow(`→ ${message}`))
16
+ console.log(`${STEP_PREFIX} ${message}`)
14
17
  }
15
18
 
16
19
  function logSuccess(message) {
17
- console.log(chalk.green(`✔ ${message}`))
20
+ console.log(`${OK_PREFIX} ${message}`)
18
21
  }
19
22
 
20
23
  function logWarning(message) {
21
- console.warn(chalk.yellow(`⚠ ${message}`))
22
- }
23
-
24
- function logError(message) {
25
- console.error(chalk.red(`✗ ${message}`))
24
+ console.warn(`${WARN_PREFIX} ${message}`)
26
25
  }
27
26
 
28
- function runCommand(command, args, { cwd = process.cwd(), capture = false, silent = false } = {}) {
27
+ function runCommand(command, args, { cwd = process.cwd(), capture = false, useShell = false } = {}) {
29
28
  return new Promise((resolve, reject) => {
29
+ // On Windows, npm-related commands need shell: true to resolve npx.cmd
30
+ // Git commands work fine without shell, so we only use it when explicitly requested
30
31
  const spawnOptions = {
31
32
  cwd,
32
- stdio: capture ? ['ignore', 'pipe', 'pipe'] : (silent ? ['ignore', 'ignore', 'pipe'] : 'inherit'),
33
- shell: IS_WINDOWS
33
+ stdio: capture ? ['ignore', 'pipe', 'pipe'] : 'inherit'
34
34
  }
35
35
 
36
- const escapedArgs = IS_WINDOWS ? args.map(arg => {
37
- if (arg.includes(' ') || arg.includes('\n') || arg.includes('"')) {
38
- return `"${arg.replace(/"/g, '\\"')}"`
39
- }
40
- return arg
41
- }) : args
36
+ if (useShell || (IS_WINDOWS && (command === 'npm' || command === 'npx'))) {
37
+ spawnOptions.shell = true
38
+ }
42
39
 
43
- const child = spawn(command, escapedArgs, spawnOptions)
40
+ const child = spawn(command, args, spawnOptions)
44
41
  let stdout = ''
45
42
  let stderr = ''
46
43
 
@@ -55,21 +52,10 @@ function runCommand(command, args, { cwd = process.cwd(), capture = false, silen
55
52
  }
56
53
 
57
54
  child.on('error', reject)
58
-
59
- let errorOutput = ''
60
- if (silent && !capture) {
61
- child.stderr.on('data', (chunk) => {
62
- errorOutput += chunk.toString()
63
- })
64
- }
65
-
66
55
  child.on('close', (code) => {
67
56
  if (code === 0) {
68
57
  resolve(capture ? { stdout: stdout.trim(), stderr: stderr.trim() } : undefined)
69
58
  } else {
70
- if (silent && errorOutput) {
71
- console.error(chalk.red(errorOutput))
72
- }
73
59
  const error = new Error(`Command failed (${code}): ${command} ${args.join(' ')}`)
74
60
  if (capture) {
75
61
  error.stdout = stdout
@@ -217,7 +203,7 @@ async function runLint(skipLint, pkg, rootDir = process.cwd()) {
217
203
  }
218
204
 
219
205
  logStep('Running lint...')
220
- await runCommand('npm', ['run', 'lint'], { silent: true, cwd: rootDir })
206
+ await runCommand('npm', ['run', 'lint'], { cwd: rootDir })
221
207
  logSuccess('Lint passed.')
222
208
  }
223
209
 
@@ -234,15 +220,15 @@ async function runTests(skipTests, pkg, rootDir = process.cwd()) {
234
220
  }
235
221
 
236
222
  logStep('Running test suite...')
237
-
223
+
238
224
  // Prefer test:run if available, otherwise use test with --run flag
239
225
  if (hasScript(pkg, 'test:run')) {
240
- await runCommand('npm', ['run', 'test:run'], { silent: true, cwd: rootDir })
226
+ await runCommand('npm', ['run', 'test:run'], { cwd: rootDir })
241
227
  } else {
242
228
  // For test script, try to pass --run flag (works with vitest)
243
- await runCommand('npm', ['test', '--', '--run'], { silent: true, cwd: rootDir })
229
+ await runCommand('npm', ['test', '--', '--run'], { cwd: rootDir })
244
230
  }
245
-
231
+
246
232
  logSuccess('Tests passed.')
247
233
  }
248
234
 
@@ -258,7 +244,7 @@ async function runBuild(skipBuild, pkg, rootDir = process.cwd()) {
258
244
  }
259
245
 
260
246
  logStep('Building project...')
261
- await runCommand('npm', ['run', 'build'], { silent: true, cwd: rootDir })
247
+ await runCommand('npm', ['run', 'build'], { cwd: rootDir })
262
248
  logSuccess('Build completed.')
263
249
  }
264
250
 
@@ -274,7 +260,7 @@ async function runLibBuild(skipBuild, pkg, rootDir = process.cwd()) {
274
260
  }
275
261
 
276
262
  logStep('Building library...')
277
- await runCommand('npm', ['run', 'build:lib'], { silent: true, cwd: rootDir })
263
+ await runCommand('npm', ['run', 'build:lib'], { cwd: rootDir })
278
264
  logSuccess('Library built.')
279
265
 
280
266
  // Check for lib changes and commit them if any
@@ -286,8 +272,8 @@ async function runLibBuild(skipBuild, pkg, rootDir = process.cwd()) {
286
272
 
287
273
  if (hasLibChanges) {
288
274
  logStep('Committing lib build artifacts...')
289
- await runCommand('git', ['add', 'lib/'], { silent: true, cwd: rootDir })
290
- await runCommand('git', ['commit', '-m', 'chore: build lib artifacts'], { silent: true, cwd: rootDir })
275
+ await runCommand('git', ['add', 'lib/'], { cwd: rootDir })
276
+ await runCommand('git', ['commit', '-m', 'chore: build lib artifacts'], { cwd: rootDir })
291
277
  logSuccess('Lib build artifacts committed.')
292
278
  }
293
279
 
@@ -296,7 +282,7 @@ async function runLibBuild(skipBuild, pkg, rootDir = process.cwd()) {
296
282
 
297
283
  async function ensureNpmAuth(rootDir = process.cwd()) {
298
284
  logStep('Confirming npm authentication...')
299
- await runCommand('npm', ['whoami'], { silent: true, cwd: rootDir })
285
+ await runCommand('npm', ['whoami'], { cwd: rootDir })
300
286
  logSuccess('npm authenticated.')
301
287
  }
302
288
 
@@ -312,32 +298,38 @@ async function bumpVersion(releaseType, rootDir = process.cwd()) {
312
298
 
313
299
  if (hasLibChanges) {
314
300
  logStep('Stashing lib build artifacts...')
315
- await runCommand('git', ['stash', 'push', '-u', '-m', 'temp: lib build artifacts', 'lib/'], { silent: true, cwd: rootDir })
301
+ await runCommand('git', ['stash', 'push', '-u', '-m', 'temp: lib build artifacts', 'lib/'], { cwd: rootDir })
316
302
  }
317
303
 
318
304
  try {
319
- await runCommand('npm', ['version', releaseType, '--message', 'chore: release %s'], { silent: true, cwd: rootDir })
305
+ // npm version will update package.json and create a commit with default message
306
+ await runCommand('npm', ['version', releaseType], { cwd: rootDir })
320
307
  } finally {
321
308
  // Restore lib changes and ensure they're in the commit
322
309
  if (hasLibChanges) {
323
310
  logStep('Restoring lib build artifacts...')
324
- await runCommand('git', ['stash', 'pop'], { silent: true, cwd: rootDir })
325
- await runCommand('git', ['add', 'lib/'], { silent: true, cwd: rootDir })
311
+ await runCommand('git', ['stash', 'pop'], { cwd: rootDir })
312
+ await runCommand('git', ['add', 'lib/'], { cwd: rootDir })
326
313
  const { stdout: statusAfter } = await runCommand('git', ['status', '--porcelain'], { capture: true, cwd: rootDir })
327
314
  if (statusAfter.includes('lib/')) {
328
- await runCommand('git', ['commit', '--amend', '--no-edit'], { silent: true, cwd: rootDir })
315
+ await runCommand('git', ['commit', '--amend', '--no-edit'], { cwd: rootDir })
329
316
  }
330
317
  }
331
318
  }
332
319
 
333
320
  const pkg = await readPackage(rootDir)
321
+ const commitMessage = `chore: release ${pkg.version}`
322
+
323
+ // Amend the commit message to use our custom format
324
+ await runCommand('git', ['commit', '--amend', '-m', commitMessage], { cwd: rootDir })
325
+
334
326
  logSuccess(`Version updated to ${pkg.version}.`)
335
327
  return pkg
336
328
  }
337
329
 
338
330
  async function pushChanges(rootDir = process.cwd()) {
339
331
  logStep('Pushing commits and tags to origin...')
340
- await runCommand('git', ['push', '--follow-tags'], { silent: true, cwd: rootDir })
332
+ await runCommand('git', ['push', '--follow-tags'], { cwd: rootDir })
341
333
  logSuccess('Git push completed.')
342
334
  }
343
335
 
@@ -349,7 +341,7 @@ async function publishPackage(pkg, rootDir = process.cwd()) {
349
341
  }
350
342
 
351
343
  logStep(`Publishing ${pkg.name}@${pkg.version} to npm...`)
352
- await runCommand('npm', publishArgs, { silent: true, cwd: rootDir })
344
+ await runCommand('npm', publishArgs, { cwd: rootDir })
353
345
  logSuccess('npm publish completed.')
354
346
  }
355
347
 
@@ -390,7 +382,7 @@ async function deployGHPages(skipDeploy, pkg, rootDir = process.cwd()) {
390
382
 
391
383
  // Write CNAME file to dist if homepage is set
392
384
  const cnamePath = path.join(distPath, 'CNAME')
393
-
385
+
394
386
  if (pkg.homepage) {
395
387
  const domain = extractDomainFromHomepage(pkg.homepage)
396
388
  if (domain) {
@@ -406,17 +398,17 @@ async function deployGHPages(skipDeploy, pkg, rootDir = process.cwd()) {
406
398
  const worktreeDir = path.resolve(rootDir, '.gh-pages')
407
399
 
408
400
  try {
409
- await runCommand('git', ['worktree', 'remove', worktreeDir, '-f'], { silent: true, cwd: rootDir })
401
+ await runCommand('git', ['worktree', 'remove', worktreeDir, '-f'], { cwd: rootDir })
410
402
  } catch { }
411
403
 
412
404
  try {
413
- await runCommand('git', ['worktree', 'add', worktreeDir, 'gh-pages'], { silent: true, cwd: rootDir })
405
+ await runCommand('git', ['worktree', 'add', worktreeDir, 'gh-pages'], { cwd: rootDir })
414
406
  } catch {
415
- await runCommand('git', ['worktree', 'add', worktreeDir, '-b', 'gh-pages'], { silent: true, cwd: rootDir })
407
+ await runCommand('git', ['worktree', 'add', worktreeDir, '-b', 'gh-pages'], { cwd: rootDir })
416
408
  }
417
409
 
418
- await runCommand('git', ['-C', worktreeDir, 'config', 'user.name', 'wyxos'], { silent: true })
419
- await runCommand('git', ['-C', worktreeDir, 'config', 'user.email', 'github@wyxos.com'], { silent: true })
410
+ await runCommand('git', ['-C', worktreeDir, 'config', 'user.name', 'wyxos'])
411
+ await runCommand('git', ['-C', worktreeDir, 'config', 'user.email', 'github@wyxos.com'])
420
412
 
421
413
  // Clear worktree directory
422
414
  for (const entry of fs.readdirSync(worktreeDir)) {
@@ -428,9 +420,9 @@ async function deployGHPages(skipDeploy, pkg, rootDir = process.cwd()) {
428
420
  // Copy dist to worktree
429
421
  fs.cpSync(distPath, worktreeDir, { recursive: true })
430
422
 
431
- await runCommand('git', ['-C', worktreeDir, 'add', '-A'], { silent: true })
432
- await runCommand('git', ['-C', worktreeDir, 'commit', '-m', `deploy: demo ${new Date().toISOString()}`, '--allow-empty'], { silent: true })
433
- await runCommand('git', ['-C', worktreeDir, 'push', '-f', 'origin', 'gh-pages'], { silent: true })
423
+ await runCommand('git', ['-C', worktreeDir, 'add', '-A'])
424
+ await runCommand('git', ['-C', worktreeDir, 'commit', '-m', `deploy: demo ${new Date().toISOString()}`, '--allow-empty'])
425
+ await runCommand('git', ['-C', worktreeDir, 'push', '-f', 'origin', 'gh-pages'])
434
426
 
435
427
  logSuccess('GitHub Pages deployment completed.')
436
428
  }