@wyxos/zephyr 0.9.8 → 0.9.9

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.8",
3
+ "version": "0.9.9",
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",
@@ -54,7 +54,7 @@ export function createAppContext({
54
54
  workflow: normalizedExecutionMode.workflow
55
55
  })
56
56
  const hasInteractiveTerminal = Boolean(processInstance?.stdin?.isTTY && processInstance?.stdout?.isTTY)
57
- const createSshClient = createSshClientFactory({NodeSSH: NodeSSHClass})
57
+ const createSshClient = createSshClientFactory({NodeSSH: NodeSSHClass, logWarning})
58
58
  const {runCommand, runCommandCapture} = createLocalCommandRunners({
59
59
  runCommandBase: runCommandImpl,
60
60
  runCommandCaptureBase: runCommandCaptureImpl
@@ -1,14 +1,69 @@
1
- export function createSshClientFactory({ NodeSSH }) {
1
+ const connectionErrorHandlerSymbol = Symbol('zephyrSshConnectionErrorHandler')
2
+ const connectWrapperSymbol = Symbol('zephyrSshConnectWrapper')
3
+
4
+ function getErrorMessage(error) {
5
+ if (error instanceof Error && error.message) {
6
+ return error.message
7
+ }
8
+
9
+ return String(error ?? 'Unknown SSH connection error')
10
+ }
11
+
12
+ export function attachSshConnectionErrorHandler(ssh, { logWarning } = {}) {
13
+ const connection = ssh?.connection
14
+
15
+ if (!connection || typeof connection.on !== 'function') {
16
+ return false
17
+ }
18
+
19
+ if (connection[connectionErrorHandlerSymbol]) {
20
+ return false
21
+ }
22
+
23
+ let hasLogged = false
24
+ const handler = (error) => {
25
+ if (hasLogged) {
26
+ return
27
+ }
28
+
29
+ hasLogged = true
30
+ logWarning?.(`SSH connection emitted a background error after connect: ${getErrorMessage(error)}`)
31
+ }
32
+
33
+ connection.on('error', handler)
34
+ connection[connectionErrorHandlerSymbol] = handler
35
+
36
+ return true
37
+ }
38
+
39
+ function wrapSshConnect(ssh, { logWarning } = {}) {
40
+ if (!ssh || typeof ssh.connect !== 'function' || ssh[connectWrapperSymbol]) {
41
+ return ssh
42
+ }
43
+
44
+ const originalConnect = ssh.connect
45
+
46
+ ssh.connect = async function connectWithBackgroundErrorHandler(...args) {
47
+ const result = await originalConnect.apply(this, args)
48
+ attachSshConnectionErrorHandler(this, { logWarning })
49
+
50
+ return result
51
+ }
52
+ ssh[connectWrapperSymbol] = true
53
+
54
+ return ssh
55
+ }
56
+
57
+ export function createSshClientFactory({ NodeSSH, logWarning }) {
2
58
  if (!NodeSSH) {
3
59
  throw new Error('createSshClientFactory requires NodeSSH')
4
60
  }
5
61
 
6
62
  return function createSshClient() {
7
63
  if (typeof globalThis !== 'undefined' && globalThis.__zephyrSSHFactory) {
8
- return globalThis.__zephyrSSHFactory()
64
+ return wrapSshConnect(globalThis.__zephyrSSHFactory(), { logWarning })
9
65
  }
10
66
 
11
- return new NodeSSH()
67
+ return wrapSshConnect(new NodeSSH(), { logWarning })
12
68
  }
13
69
  }
14
-
package/src/ssh/ssh.mjs CHANGED
@@ -11,7 +11,7 @@ import { createSshClientFactory } from '../runtime/ssh-client.mjs'
11
11
 
12
12
  const { logProcessing, logSuccess, logWarning, logError } = createChalkLogger(chalk)
13
13
 
14
- const createSshClient = createSshClientFactory({ NodeSSH })
14
+ const createSshClient = createSshClientFactory({ NodeSSH, logWarning })
15
15
 
16
16
  function normalizeRemotePath(value) {
17
17
  if (value == null) return value
@@ -136,4 +136,3 @@ export async function deleteRemoteFile(ssh, remotePath, remoteCwd) {
136
136
  logSuccess(`Deleted remote file: ${absoluteRemotePath}`)
137
137
  }
138
138
  }
139
-