@wyxos/zephyr 0.2.13 → 0.2.15

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.
@@ -6,6 +6,8 @@ import fs from 'node:fs'
6
6
  import path from 'node:path'
7
7
  import process from 'node:process'
8
8
  import semver from 'semver'
9
+ import inquirer from 'inquirer'
10
+ import { validateLocalDependencies } from './dependency-scanner.mjs'
9
11
 
10
12
  const STEP_PREFIX = '→'
11
13
  const OK_PREFIX = '✔'
@@ -303,7 +305,7 @@ async function runTests(skipTests, composer, rootDir = process.cwd()) {
303
305
  }, 200)
304
306
 
305
307
  if (hasArtisanFile) {
306
- await runCommand('php', ['artisan', 'test'], { capture: true, cwd: rootDir })
308
+ await runCommand('php', ['artisan', 'test', '--compact'], { capture: true, cwd: rootDir })
307
309
  } else if (hasTestScript) {
308
310
  await runCommand('composer', ['test'], { capture: true, cwd: rootDir })
309
311
  }
@@ -384,6 +386,9 @@ export async function releasePackagist() {
384
386
  throw new Error('composer.json does not have a version field. Add "version": "0.0.0" to composer.json.')
385
387
  }
386
388
 
389
+ logStep('Validating dependencies...')
390
+ await validateLocalDependencies(rootDir, (questions) => inquirer.prompt(questions))
391
+
387
392
  logStep('Checking working tree status...')
388
393
  await ensureCleanWorkingTree(rootDir)
389
394
 
@@ -0,0 +1,126 @@
1
+ import { readFile } from 'node:fs/promises'
2
+ import { fileURLToPath } from 'node:url'
3
+ import path from 'node:path'
4
+ import { spawn } from 'node:child_process'
5
+ import process from 'node:process'
6
+ import semver from 'semver'
7
+
8
+ const IS_WINDOWS = process.platform === 'win32'
9
+
10
+ async function getCurrentVersion() {
11
+ try {
12
+ // Try to get version from package.json
13
+ // When running via npx, the package.json is in the installed package directory
14
+ const packageJsonPath = path.resolve(
15
+ path.dirname(fileURLToPath(import.meta.url)),
16
+ '..',
17
+ 'package.json'
18
+ )
19
+ const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'))
20
+ return packageJson.version
21
+ } catch (error) {
22
+ // If we can't read package.json, return null
23
+ return null
24
+ }
25
+ }
26
+
27
+ async function getLatestVersion() {
28
+ try {
29
+ const response = await fetch('https://registry.npmjs.org/@wyxos/zephyr/latest')
30
+ if (!response.ok) {
31
+ return null
32
+ }
33
+ const data = await response.json()
34
+ return data.version || null
35
+ } catch (error) {
36
+ return null
37
+ }
38
+ }
39
+
40
+ function isNewerVersionAvailable(current, latest) {
41
+ if (!current || !latest) {
42
+ return false
43
+ }
44
+
45
+ // Use semver to properly compare versions
46
+ try {
47
+ return semver.gt(latest, current)
48
+ } catch (error) {
49
+ // If semver comparison fails, fall back to simple string comparison
50
+ return latest !== current
51
+ }
52
+ }
53
+
54
+ async function reExecuteWithLatest(args) {
55
+ // Re-execute with npx @wyxos/zephyr@latest
56
+ const command = IS_WINDOWS ? 'npx.cmd' : 'npx'
57
+ const npxArgs = ['@wyxos/zephyr@latest', ...args]
58
+
59
+ return new Promise((resolve, reject) => {
60
+ const child = spawn(command, npxArgs, {
61
+ stdio: 'inherit',
62
+ shell: IS_WINDOWS
63
+ })
64
+
65
+ child.on('error', reject)
66
+ child.on('close', (code) => {
67
+ if (code === 0) {
68
+ resolve()
69
+ } else {
70
+ reject(new Error(`Command exited with code ${code}`))
71
+ }
72
+ })
73
+ })
74
+ }
75
+
76
+ export async function checkAndUpdateVersion(promptFn, args) {
77
+ try {
78
+ // Skip check if already running @latest (detected via environment or process)
79
+ // When npx runs @latest, the version should already be latest
80
+ const isRunningLatest = process.env.npm_config_user_config?.includes('@latest') ||
81
+ process.argv.some(arg => arg.includes('@latest'))
82
+
83
+ if (isRunningLatest) {
84
+ return false
85
+ }
86
+
87
+ const currentVersion = await getCurrentVersion()
88
+ if (!currentVersion) {
89
+ // Can't determine current version, skip check
90
+ return false
91
+ }
92
+
93
+ const latestVersion = await getLatestVersion()
94
+ if (!latestVersion) {
95
+ // Can't fetch latest version, skip check
96
+ return false
97
+ }
98
+
99
+ if (!isNewerVersionAvailable(currentVersion, latestVersion)) {
100
+ // Already on latest or newer
101
+ return false
102
+ }
103
+
104
+ // Newer version available, prompt user
105
+ const { shouldUpdate } = await promptFn([
106
+ {
107
+ type: 'confirm',
108
+ name: 'shouldUpdate',
109
+ message: `A new version of @wyxos/zephyr is available (${latestVersion}). You are currently on ${currentVersion}. Update and continue?`,
110
+ default: true
111
+ }
112
+ ])
113
+
114
+ if (!shouldUpdate) {
115
+ return false
116
+ }
117
+
118
+ // User confirmed, re-execute with latest version
119
+ await reExecuteWithLatest(args)
120
+ return true // Indicates we've re-executed, so the current process should exit
121
+ } catch (error) {
122
+ // If version check fails, just continue with current version
123
+ // Don't block the user from using the tool
124
+ return false
125
+ }
126
+ }