ssh2-sftp-client 10.0.3 → 11.0.0

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/src/utils.js CHANGED
@@ -1,6 +1,54 @@
1
- const fs = require('node:fs');
2
- const path = require('node:path');
3
- const { errorCode } = require('./constants');
1
+ const { statSync, constants, accessSync } = require('node:fs');
2
+ const { dirname } = require('node:path');
3
+ const { errorCode } = require('./constants.js');
4
+
5
+ function eventHandled(client) {
6
+ if (client.errorHandled || client.endHandled || client.closeHandled) {
7
+ return true;
8
+ }
9
+ return false;
10
+ }
11
+
12
+ function globalListener(client, evt, eventCallbacks) {
13
+ if (evt === 'error') {
14
+ return (err) => {
15
+ if (client.errorHandled) {
16
+ client.debugMsg(`Global error event: Ignoring handled error ${err.message}`);
17
+ return;
18
+ }
19
+ client.debugMsg(`Global error event: ${err.message}`);
20
+ client.errorHandled = true;
21
+ if (eventCallbacks?.error) {
22
+ eventCallbacks.error(err);
23
+ }
24
+ };
25
+ }
26
+ if (evt === 'end') {
27
+ return () => {
28
+ if (client.endCalled || client.endHandled) {
29
+ client.debugMsg('Global end event: Ignoring handled end event');
30
+ return;
31
+ }
32
+ client.debugMsg('Global end event: Handling end event');
33
+ client.endHandled = true;
34
+ if (eventCallbacks?.end) {
35
+ eventCallbacks.end();
36
+ }
37
+ };
38
+ }
39
+ return () => {
40
+ if (client.endCalled || client.closeHandled) {
41
+ client.debugMsg('Global close event: Ignoring handled close event');
42
+ } else {
43
+ client.debugMsg('Global close event: Handling close event');
44
+ client.closeHandled = true;
45
+ client.sftp = undefined;
46
+ if (eventCallbacks?.close) {
47
+ eventCallbacks.close();
48
+ }
49
+ }
50
+ };
51
+ }
4
52
 
5
53
  /**
6
54
  * Simple default error listener. Will reformat the error message and
@@ -10,12 +58,13 @@ const { errorCode } = require('./constants');
10
58
  * @throws {Error} Throws new error
11
59
  */
12
60
  function errorListener(client, name, reject) {
13
- const fn = (err) => {
14
- if (client.endCalled || client.errorHandled) {
61
+ const fn = function (err) {
62
+ if (eventHandled(client)) {
15
63
  // error already handled or expected - ignore
16
- client.debugMsg(`${name} errorListener - ignoring handled error`);
64
+ client.debugMsg(`${name} errorListener - ignoring handled error ${err.message}`);
17
65
  return;
18
66
  }
67
+ client.debugMsg(`${name} errorListener - handling error ${err.message}`);
19
68
  client.errorHandled = true;
20
69
  const newError = new Error(`${name}: ${err.message}`);
21
70
  newError.code = err.code;
@@ -28,55 +77,52 @@ function errorListener(client, name, reject) {
28
77
  return fn;
29
78
  }
30
79
 
31
- function globalListener(client, evt) {
32
- return () => {
33
- if (client.endCalled || client.errorHandled || client.closeHandled) {
34
- // we are processing an expected event handled elsewhere
35
- client.debugMsg(`Global ${evt} event: Ignoring expected and handled event`);
36
- } else {
37
- client.debugMsg(`Global ${evt} event: Handling unexpected event`);
38
- client.sftp = undefined;
39
- }
40
- };
41
- }
42
-
43
- function endListener(client, name) {
80
+ function endListener(client, name, reject) {
44
81
  const fn = function () {
45
82
  client.sftp = undefined;
46
- if (client.endCalled || client.endHandled || client.errorHandled) {
83
+ if (client.endCalled || eventHandled(client)) {
47
84
  // end event already handled - ignore
48
- client.debugMsg(`${name} endListener - handled end event`);
85
+ client.debugMsg(`${name} endListener - ignoring handled end event`);
49
86
  return;
50
87
  }
51
88
  client.endHandled = true;
52
- client.debugMsg(`${name} Unexpected end event`);
89
+ client.debugMsg(`${name} endListener - handling unexpected end event`);
90
+ const newError = new Error(`${name}: Unexpected end event`);
91
+ newError.code = errorCode.ERR_GENERIC_CLIENT;
92
+ if (reject) {
93
+ reject(newError);
94
+ } else {
95
+ throw newError;
96
+ }
53
97
  };
54
98
  return fn;
55
99
  }
56
100
 
57
- function closeListener(client, name) {
101
+ function closeListener(client, name, reject) {
58
102
  const fn = function () {
59
103
  client.sftp = undefined;
60
- if (
61
- client.endCalled ||
62
- client.closeHandled ||
63
- client.errorHandled ||
64
- client.endHandled
65
- ) {
104
+ if (client.endCalled || eventHandled(client)) {
66
105
  // handled or expected close event - ignore
67
- client.debugMsg(`${name} closeListener - handled close event`);
106
+ client.debugMsg(`${name} closeListener - ignoring handled close event`);
68
107
  return;
69
108
  }
70
109
  client.closeHandled = true;
71
- client.debugMsg(`${name} Unexpected close event`);
110
+ client.debugMsg(`${name} closeListener - handling unexpected close event`);
111
+ const newError = new Error(`${name}: Unexpected close event`);
112
+ newError.code = errorCode.ERR_GENERIC_CLIENT;
113
+ if (reject) {
114
+ reject(newError);
115
+ } else {
116
+ throw newError;
117
+ }
72
118
  };
73
119
  return fn;
74
120
  }
75
121
 
76
122
  function addTempListeners(client, name, reject) {
77
123
  const listeners = {
78
- end: endListener(client, name),
79
- close: closeListener(client, name),
124
+ end: endListener(client, name, reject),
125
+ close: closeListener(client, name, reject),
80
126
  error: errorListener(client, name, reject),
81
127
  };
82
128
  client.on('end', listeners.end);
@@ -109,7 +155,7 @@ function removeTempListeners(client, listeners, name) {
109
155
  * @returns {string | boolean} returns a string for object type if it exists, false otherwise
110
156
  */
111
157
  function localExists(filePath) {
112
- const stats = fs.statSync(filePath, { throwIfNoEntry: false });
158
+ const stats = statSync(filePath, { throwIfNoEntry: false });
113
159
  if (!stats) {
114
160
  return false;
115
161
  } else if (stats.isDirectory()) {
@@ -140,11 +186,10 @@ function localExists(filePath) {
140
186
  * @returns {Object} with properties status, type, details and code
141
187
  */
142
188
  function haveLocalAccess(filePath, mode = 'r') {
143
- const accessMode =
144
- fs.constants.F_OK | (mode === 'w') ? fs.constants.W_OK : fs.constants.R_OK;
189
+ const accessMode = constants.F_OK | (mode === 'w') ? constants.W_OK : constants.R_OK;
145
190
 
146
191
  try {
147
- fs.accessSync(filePath, accessMode);
192
+ accessSync(filePath, accessMode);
148
193
  const type = localExists(filePath);
149
194
  return {
150
195
  status: true,
@@ -210,7 +255,7 @@ function haveLocalCreate(filePath) {
210
255
  };
211
256
  }
212
257
  // to create it, parent must be directory and writeable
213
- const dirPath = path.dirname(filePath);
258
+ const dirPath = dirname(filePath);
214
259
  const localCheck = haveLocalAccess(dirPath, 'w');
215
260
  if (!localCheck.status) {
216
261
  // no access to parent directory