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.
Files changed (5) hide show
  1. package/README.md +149 -140
  2. package/README.org +69 -20
  3. package/package.json +10 -10
  4. package/src/index.js +167 -139
  5. 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, reject) {
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 - ignoring handled error`);
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 - ignoring`);
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, reject) {
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 - ignoring handled error`);
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 raised - ignoring`);
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, reject),
95
- close: closeListener(client, name, reject),
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
- case -13:
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
- case -20:
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
- default:
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 && details === 'permission denied') {
215
- //throw new Error(`Bad path: ${filePath}: permission denied`);
216
- return {
217
- status,
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: false,
228
- details: `${dirPath}: not a directory`,
229
- type: null,
207
+ status,
208
+ details,
209
+ type,
230
210
  };
231
- } else if (!localCheck.status) {
232
- //throw new Error(`Bad path: ${dirPath}: ${localCheck.details}`);
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
- } else {
222
+ }
223
+ // exists, is it a directory?
224
+ if (localCheck.type !== 'd') {
239
225
  return {
240
- status: true,
241
- details: 'access OK',
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 anumber >= 0');
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
  };