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/README.md +175 -135
- package/README.org +141 -28
- package/package.json +7 -7
- package/src/index.js +38 -47
- package/src/utils.js +83 -38
package/src/utils.js
CHANGED
|
@@ -1,6 +1,54 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
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
|
|
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
|
|
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
|
|
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}
|
|
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}
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
258
|
+
const dirPath = dirname(filePath);
|
|
214
259
|
const localCheck = haveLocalAccess(dirPath, 'w');
|
|
215
260
|
if (!localCheck.status) {
|
|
216
261
|
// no access to parent directory
|