ssh2-sftp-client 9.1.0 → 10.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 +149 -140
- package/README.org +69 -20
- package/package.json +10 -10
- package/src/index.js +167 -139
- package/src/utils.js +58 -53
package/src/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
1
|
+
const fs = require('node:fs');
|
|
2
|
+
const path = require('node:path');
|
|
3
3
|
const { errorCode } = require('./constants');
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -40,29 +40,21 @@ function globalListener(client, evt) {
|
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
function endListener(client, name
|
|
43
|
+
function endListener(client, name) {
|
|
44
44
|
const fn = function () {
|
|
45
45
|
client.sftp = undefined;
|
|
46
46
|
if (client.endCalled || client.endHandled || client.errorHandled) {
|
|
47
47
|
// end event already handled - ignore
|
|
48
|
-
client.debugMsg(`${name} endListener -
|
|
48
|
+
client.debugMsg(`${name} endListener - handled end event`);
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
client.endHandled = true;
|
|
52
|
-
client.debugMsg(`${name} Unexpected end event
|
|
53
|
-
// Don't reject/throw error, just log it and move on
|
|
54
|
-
// after invalidating the connection
|
|
55
|
-
// const err = new Error(`${name} Unexpected end event raised`);
|
|
56
|
-
// if (reject) {
|
|
57
|
-
// reject(err);
|
|
58
|
-
// } else {
|
|
59
|
-
// throw err;
|
|
60
|
-
// }
|
|
52
|
+
client.debugMsg(`${name} Unexpected end event`);
|
|
61
53
|
};
|
|
62
54
|
return fn;
|
|
63
55
|
}
|
|
64
56
|
|
|
65
|
-
function closeListener(client, name
|
|
57
|
+
function closeListener(client, name) {
|
|
66
58
|
const fn = function () {
|
|
67
59
|
client.sftp = undefined;
|
|
68
60
|
if (
|
|
@@ -72,27 +64,19 @@ function closeListener(client, name, reject) {
|
|
|
72
64
|
client.endHandled
|
|
73
65
|
) {
|
|
74
66
|
// handled or expected close event - ignore
|
|
75
|
-
client.debugMsg(`${name} closeListener -
|
|
67
|
+
client.debugMsg(`${name} closeListener - handled close event`);
|
|
76
68
|
return;
|
|
77
69
|
}
|
|
78
70
|
client.closeHandled = true;
|
|
79
|
-
client.debugMsg(`${name} Unexpected close event
|
|
80
|
-
// Don't throw/reject on close events. Just invalidate the connection
|
|
81
|
-
// and move on.
|
|
82
|
-
// const err = new Error(`${name}: Unexpected close event raised`);
|
|
83
|
-
// if (reject) {
|
|
84
|
-
// reject(err);
|
|
85
|
-
// } else {
|
|
86
|
-
// throw err;
|
|
87
|
-
// }
|
|
71
|
+
client.debugMsg(`${name} Unexpected close event`);
|
|
88
72
|
};
|
|
89
73
|
return fn;
|
|
90
74
|
}
|
|
91
75
|
|
|
92
76
|
function addTempListeners(client, name, reject) {
|
|
93
77
|
const listeners = {
|
|
94
|
-
end: endListener(client, name
|
|
95
|
-
close: closeListener(client, name
|
|
78
|
+
end: endListener(client, name),
|
|
79
|
+
close: closeListener(client, name),
|
|
96
80
|
error: errorListener(client, name, reject),
|
|
97
81
|
};
|
|
98
82
|
client.on('end', listeners.end);
|
|
@@ -170,32 +154,36 @@ function haveLocalAccess(filePath, mode = 'r') {
|
|
|
170
154
|
};
|
|
171
155
|
} catch (err) {
|
|
172
156
|
switch (err.errno) {
|
|
173
|
-
case -2:
|
|
157
|
+
case -2: {
|
|
174
158
|
return {
|
|
175
159
|
status: false,
|
|
176
160
|
type: null,
|
|
177
161
|
details: 'not exist',
|
|
178
162
|
code: -2,
|
|
179
163
|
};
|
|
180
|
-
|
|
164
|
+
}
|
|
165
|
+
case -13: {
|
|
181
166
|
return {
|
|
182
167
|
status: false,
|
|
183
168
|
type: localExists(filePath),
|
|
184
169
|
details: 'permission denied',
|
|
185
170
|
code: -13,
|
|
186
171
|
};
|
|
187
|
-
|
|
172
|
+
}
|
|
173
|
+
case -20: {
|
|
188
174
|
return {
|
|
189
175
|
status: false,
|
|
190
176
|
type: null,
|
|
191
177
|
details: 'parent not a directory',
|
|
192
178
|
};
|
|
193
|
-
|
|
179
|
+
}
|
|
180
|
+
default: {
|
|
194
181
|
return {
|
|
195
182
|
status: false,
|
|
196
183
|
type: null,
|
|
197
184
|
details: err.message,
|
|
198
185
|
};
|
|
186
|
+
}
|
|
199
187
|
}
|
|
200
188
|
}
|
|
201
189
|
}
|
|
@@ -211,38 +199,41 @@ function haveLocalAccess(filePath, mode = 'r') {
|
|
|
211
199
|
*/
|
|
212
200
|
function haveLocalCreate(filePath) {
|
|
213
201
|
const { status, details, type } = haveLocalAccess(filePath, 'w');
|
|
214
|
-
if (!status
|
|
215
|
-
//
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
details,
|
|
219
|
-
type,
|
|
220
|
-
};
|
|
221
|
-
} else if (!status) {
|
|
222
|
-
const dirPath = path.dirname(filePath);
|
|
223
|
-
const localCheck = haveLocalAccess(dirPath, 'w');
|
|
224
|
-
if (localCheck.status && localCheck.type !== 'd') {
|
|
225
|
-
//throw new Error(`Bad path: ${dirPath}: not a directory`);
|
|
202
|
+
if (!status) {
|
|
203
|
+
// filePath does not exist. Can we create it?
|
|
204
|
+
if (details === 'permission denied') {
|
|
205
|
+
// don't have permission
|
|
226
206
|
return {
|
|
227
|
-
status
|
|
228
|
-
details
|
|
229
|
-
type
|
|
207
|
+
status,
|
|
208
|
+
details,
|
|
209
|
+
type,
|
|
230
210
|
};
|
|
231
|
-
}
|
|
232
|
-
|
|
211
|
+
}
|
|
212
|
+
// to create it, parent must be directory and writeable
|
|
213
|
+
const dirPath = path.dirname(filePath);
|
|
214
|
+
const localCheck = haveLocalAccess(dirPath, 'w');
|
|
215
|
+
if (!localCheck.status) {
|
|
216
|
+
// no access to parent directory
|
|
233
217
|
return {
|
|
234
218
|
status: localCheck.status,
|
|
235
219
|
details: `${dirPath}: ${localCheck.details}`,
|
|
236
220
|
type: null,
|
|
237
221
|
};
|
|
238
|
-
}
|
|
222
|
+
}
|
|
223
|
+
// exists, is it a directory?
|
|
224
|
+
if (localCheck.type !== 'd') {
|
|
239
225
|
return {
|
|
240
|
-
status:
|
|
241
|
-
details:
|
|
226
|
+
status: false,
|
|
227
|
+
details: `${dirPath}: not a directory`,
|
|
242
228
|
type: null,
|
|
243
|
-
code: 0,
|
|
244
229
|
};
|
|
245
230
|
}
|
|
231
|
+
return {
|
|
232
|
+
status: true,
|
|
233
|
+
details: 'access OK',
|
|
234
|
+
type: null,
|
|
235
|
+
code: 0,
|
|
236
|
+
};
|
|
246
237
|
}
|
|
247
238
|
return { status, details, type };
|
|
248
239
|
}
|
|
@@ -289,8 +280,8 @@ function haveConnection(client, name, reject) {
|
|
|
289
280
|
function sleep(ms) {
|
|
290
281
|
return new Promise((resolve, reject) => {
|
|
291
282
|
try {
|
|
292
|
-
if (isNaN(ms) || ms < 0) {
|
|
293
|
-
reject('Argument must be
|
|
283
|
+
if (Number.isNaN(Number.parseInt(ms)) || ms < 0) {
|
|
284
|
+
reject('Argument must be a number >= 0');
|
|
294
285
|
} else {
|
|
295
286
|
setTimeout(() => {
|
|
296
287
|
resolve(true);
|
|
@@ -302,6 +293,19 @@ function sleep(ms) {
|
|
|
302
293
|
});
|
|
303
294
|
}
|
|
304
295
|
|
|
296
|
+
function partition(input, size) {
|
|
297
|
+
let output = [];
|
|
298
|
+
|
|
299
|
+
if (size < 1) {
|
|
300
|
+
throw new Error('Partition size must be greater than zero');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
for (let i = 0; i < input.length; i += size) {
|
|
304
|
+
output[output.length] = input.slice(i, i + size);
|
|
305
|
+
}
|
|
306
|
+
return output;
|
|
307
|
+
}
|
|
308
|
+
|
|
305
309
|
module.exports = {
|
|
306
310
|
globalListener,
|
|
307
311
|
errorListener,
|
|
@@ -315,4 +319,5 @@ module.exports = {
|
|
|
315
319
|
localExists,
|
|
316
320
|
haveConnection,
|
|
317
321
|
sleep,
|
|
322
|
+
partition,
|
|
318
323
|
};
|