vtlab-generic-functions 1.0.23 → 1.0.25
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/ftp/ftp-promise-wrapper.js +60 -72
- package/ftp/ftpClientClass.js +214 -0
- package/lambdaClass/index.js +2 -2
- package/package.json +1 -1
- package/utils/index.js +83 -0
|
@@ -1,21 +1,5 @@
|
|
|
1
1
|
const promiseFTP = require("promise-ftp");
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
* Internal functions
|
|
5
|
-
*/
|
|
6
2
|
|
|
7
|
-
const streamToBuffer = (stream) => {
|
|
8
|
-
let _buf = [];
|
|
9
|
-
return new Promise((resolve, reject) => {
|
|
10
|
-
try {
|
|
11
|
-
stream.once("close", resolve);
|
|
12
|
-
stream.once("error", reject);
|
|
13
|
-
stream.pipe((chunk) => Buffer.concat(chunk));
|
|
14
|
-
} catch (err) {
|
|
15
|
-
reject(err);
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
};
|
|
19
3
|
|
|
20
4
|
/**
|
|
21
5
|
*
|
|
@@ -23,52 +7,53 @@ const streamToBuffer = (stream) => {
|
|
|
23
7
|
*/
|
|
24
8
|
//downloadFromFTP
|
|
25
9
|
const downloadFromFTP = async (ftp, remotePathWithFile) => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
10
|
+
let _buf = [];
|
|
11
|
+
let Stream = require("stream");
|
|
12
|
+
const writableStream = new Stream.Writable();
|
|
13
|
+
writableStream._write = (chunk, encoding, next) => {
|
|
14
|
+
_buf.push(chunk);
|
|
15
|
+
next();
|
|
16
|
+
};
|
|
17
|
+
return ftp
|
|
18
|
+
.get(remotePathWithFile)
|
|
19
|
+
.then((stream) => {
|
|
20
|
+
return new Promise(function (resolve, reject) {
|
|
21
|
+
stream.once("close", resolve);
|
|
22
|
+
stream.once("error", reject);
|
|
23
|
+
stream.pipe(writableStream);
|
|
24
|
+
});
|
|
25
|
+
})
|
|
26
|
+
.then(() => {
|
|
27
|
+
return _buf;
|
|
28
|
+
})
|
|
29
|
+
.catch((err) => {
|
|
30
|
+
throw err;
|
|
31
|
+
});
|
|
48
32
|
};
|
|
49
33
|
|
|
34
|
+
|
|
50
35
|
//uploadFileToFTP
|
|
51
36
|
const uploadFileToFTP = async (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
37
|
+
config,
|
|
38
|
+
localPathWithFile,
|
|
39
|
+
remotePathWithFile
|
|
55
40
|
) => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
41
|
+
/**
|
|
42
|
+
* config ={
|
|
43
|
+
host: 'ftp.islgrupo.com',
|
|
44
|
+
user: 'testpelikane',
|
|
45
|
+
password: 'Pelikane2021+',
|
|
46
|
+
port: <OPtional>
|
|
47
|
+
}
|
|
48
|
+
*/
|
|
49
|
+
let ftp = new promiseFTP();
|
|
50
|
+
try {
|
|
51
|
+
await ftp.connect(config);
|
|
52
|
+
await ftp.put(localPathWithFile, remotePathWithFile);
|
|
53
|
+
return { code: 200, message: "FTP successfull ulpload" };
|
|
54
|
+
} catch (err) {
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
72
57
|
};
|
|
73
58
|
|
|
74
59
|
/**
|
|
@@ -78,12 +63,12 @@ const uploadFileToFTP = async (
|
|
|
78
63
|
* @returns {Promise<boolean>}
|
|
79
64
|
*/
|
|
80
65
|
const isFileExistsInFTP = async (ftp, filePath) => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
66
|
+
try {
|
|
67
|
+
let exists = await ftp.list(filePath);
|
|
68
|
+
return exists.length > 0;
|
|
69
|
+
} catch (e) {
|
|
70
|
+
throw e;
|
|
71
|
+
}
|
|
87
72
|
};
|
|
88
73
|
|
|
89
74
|
/**
|
|
@@ -93,17 +78,20 @@ const isFileExistsInFTP = async (ftp, filePath) => {
|
|
|
93
78
|
* @returns {Promise<void>}
|
|
94
79
|
*/
|
|
95
80
|
const deleteFileFromFTP = async (ftp, filePath) => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
81
|
+
try {
|
|
82
|
+
await ftp.delete(filePath);
|
|
83
|
+
} catch (e) {
|
|
84
|
+
throw e;
|
|
85
|
+
}
|
|
101
86
|
};
|
|
102
87
|
|
|
103
88
|
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
104
92
|
module.exports = {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
93
|
+
uploadFileToFTP,
|
|
94
|
+
downloadFromFTP,
|
|
95
|
+
isFileExistsInFTP,
|
|
96
|
+
deleteFileFromFTP
|
|
109
97
|
};
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
|
|
2
|
+
const promiseFTP = require("promise-ftp");
|
|
3
|
+
const promiseSFTP = require("ssh2-sftp-client");
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents an FTP client for connecting to an FTP server and performing file operations.
|
|
8
|
+
*/
|
|
9
|
+
class FTPClientV2 {
|
|
10
|
+
/**
|
|
11
|
+
* Constructs a new FTPClientV2 instance.
|
|
12
|
+
*/
|
|
13
|
+
constructor() {
|
|
14
|
+
/**
|
|
15
|
+
* FTP server credentials.
|
|
16
|
+
* @type {Object}
|
|
17
|
+
* @private
|
|
18
|
+
*/
|
|
19
|
+
this._ftpCredentials = null;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Indicates whether the client is connected to the FTP server.
|
|
23
|
+
* @type {boolean}
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
this._isConnected = false;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The FTP client instance.
|
|
30
|
+
* @type {Object}
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
this._ftpInstance = null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Connects to the FTP server.
|
|
38
|
+
* @param {Object} config FTP server configuration.
|
|
39
|
+
* @param {string} config.host The FTP server host.
|
|
40
|
+
* @param {number} [config.port] The FTP server port.
|
|
41
|
+
* @param {string} [config.username] The FTP server username.
|
|
42
|
+
* @param {string} [config.password] The FTP server password.
|
|
43
|
+
* @param {boolean} [config.autoReconnect] Indicates whether to automatically reconnect to the server.
|
|
44
|
+
* @param {string} [config.privateKey] Buffer or string that contains a private key for either key-based or host-based user authentication
|
|
45
|
+
*
|
|
46
|
+
* @throws {Error} If FTP credentials are not provided or connection fails.
|
|
47
|
+
*/
|
|
48
|
+
async connect(config) {
|
|
49
|
+
if (!config) {
|
|
50
|
+
throw new Error("FTP credentials not provided");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// normalize username/user
|
|
54
|
+
config.username = config.username || config.user;
|
|
55
|
+
config.user = config.user || config.username;
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
switch (config.type) {
|
|
59
|
+
case "sftpWithKey":
|
|
60
|
+
this._ftpInstance = new promiseSFTP();
|
|
61
|
+
break;
|
|
62
|
+
case "ftp":
|
|
63
|
+
case "sftp":
|
|
64
|
+
default:
|
|
65
|
+
this._ftpInstance = new promiseFTP();
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
await this._ftpInstance.connect(config);
|
|
69
|
+
this._isConnected = true;
|
|
70
|
+
this._ftpCredentials = config;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
this._isConnected = false;
|
|
73
|
+
this._ftpInstance = null;
|
|
74
|
+
throw new Error(`Failed to connect to FTP server: ${error.message}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Disconnects from the FTP server.
|
|
80
|
+
* @throws {Error} If disconnection fails.
|
|
81
|
+
*/
|
|
82
|
+
async disconnect() {
|
|
83
|
+
if (this._isConnected && this._ftpInstance) {
|
|
84
|
+
try {
|
|
85
|
+
await this._ftpInstance.end();
|
|
86
|
+
this._isConnected = false;
|
|
87
|
+
this._ftpInstance = null;
|
|
88
|
+
this._ftpCredentials = null;
|
|
89
|
+
} catch (error) {
|
|
90
|
+
throw new Error(`Failed to disconnect from FTP server: ${error.message}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Downloads a file from the FTP server.
|
|
97
|
+
* @param {string} remotePathWithFile Remote path to the file.
|
|
98
|
+
* @returns {Promise<Buffer>} A Promise resolving to the downloaded file content.
|
|
99
|
+
* @throws {Error} If download fails.
|
|
100
|
+
*/
|
|
101
|
+
async downloadFile(remotePathWithFile) {
|
|
102
|
+
if (!this._isConnected) {
|
|
103
|
+
await this.connect(this._ftpCredentials);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
switch (this._ftpCredentials.type) {
|
|
107
|
+
case 'sftpWithKey':
|
|
108
|
+
let file = await this._ftpInstance.get(remotePathWithFile);
|
|
109
|
+
return [file];
|
|
110
|
+
default:
|
|
111
|
+
let Stream = require("stream");
|
|
112
|
+
return new Promise((resolve, reject) => {
|
|
113
|
+
let _buf = [];
|
|
114
|
+
const writableStream = new Stream.Writable();
|
|
115
|
+
writableStream._write = (chunk, encoding, next) => {
|
|
116
|
+
_buf.push(chunk);
|
|
117
|
+
next();
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
this._ftpInstance.get(remotePathWithFile)
|
|
121
|
+
.then((stream) => {
|
|
122
|
+
return new Promise(function (resolve, reject) {
|
|
123
|
+
stream.once("close", resolve);
|
|
124
|
+
stream.once("error", reject);
|
|
125
|
+
stream.pipe(writableStream);
|
|
126
|
+
});
|
|
127
|
+
})
|
|
128
|
+
.then(() => {
|
|
129
|
+
return resolve(_buf);
|
|
130
|
+
})
|
|
131
|
+
.catch((err) => {
|
|
132
|
+
return reject(err);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Uploads a file to the FTP server.
|
|
140
|
+
* @param {string} localPathWithFile Local path to the file.
|
|
141
|
+
* @param {string} remotePathWithFile Remote path to upload the file.
|
|
142
|
+
* @returns {Promise<Object>} A Promise resolving to an object with upload status.
|
|
143
|
+
* @throws {Error} If upload fails.
|
|
144
|
+
*/
|
|
145
|
+
async uploadFile(localPathWithFile, remotePathWithFile) {
|
|
146
|
+
try {
|
|
147
|
+
if (!this._isConnected) {
|
|
148
|
+
await this.connect(this._ftpCredentials);
|
|
149
|
+
}
|
|
150
|
+
await this._ftpInstance.put(localPathWithFile, remotePathWithFile);
|
|
151
|
+
return { code: 200, message: "FTP successful upload" };
|
|
152
|
+
} catch (error) {
|
|
153
|
+
throw new Error(`Failed to upload file to FTP server: ${error.message}`);
|
|
154
|
+
} finally {
|
|
155
|
+
await this.disconnect();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Checks if a file exists on the FTP server.
|
|
161
|
+
* @param {string} filePath Remote file path to check.
|
|
162
|
+
* @returns {Promise<boolean>} A Promise resolving to true if the file exists, false otherwise.
|
|
163
|
+
* @throws {Error} If the operation fails.
|
|
164
|
+
*/
|
|
165
|
+
async isFileExists(filePath) {
|
|
166
|
+
try {
|
|
167
|
+
if (!this._isConnected) {
|
|
168
|
+
await this.connect(this._ftpCredentials);
|
|
169
|
+
}
|
|
170
|
+
const exists = await this._ftpInstance.list(filePath);
|
|
171
|
+
return exists.length > 0;
|
|
172
|
+
} catch (error) {
|
|
173
|
+
throw new Error(`Failed to check file existence on FTP server: ${error.message}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Deletes a file from the FTP server.
|
|
179
|
+
* @param {string} filePath Remote file path to delete.
|
|
180
|
+
* @throws {Error} If deletion fails.
|
|
181
|
+
*/
|
|
182
|
+
async deleteFile(filePath) {
|
|
183
|
+
try {
|
|
184
|
+
if (!this._isConnected) {
|
|
185
|
+
await this.connect(this._ftpCredentials);
|
|
186
|
+
}
|
|
187
|
+
await this._ftpInstance.delete(filePath);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
throw new Error(`Failed to delete file from FTP server: ${error.message}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Lists files in a folder on the FTP server.
|
|
195
|
+
* @param {string} folderPath Remote folder path to list files.
|
|
196
|
+
* @returns {Promise<Array<string>>} A Pro∏”mise resolving to an array of file names in the folder.
|
|
197
|
+
* @throws {Error} If listing files fails.
|
|
198
|
+
*/
|
|
199
|
+
async listFilesInFolder(folderPath) {
|
|
200
|
+
try {
|
|
201
|
+
if (!this._isConnected) {
|
|
202
|
+
await this.connect(this._ftpCredentials);
|
|
203
|
+
}
|
|
204
|
+
const files = await this._ftpInstance.list(folderPath);
|
|
205
|
+
return files.map((file) => file.name);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
throw new Error(`Failed to list files in folder on FTP server: ${error.message}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
module.exports = {
|
|
213
|
+
FTPClientV2
|
|
214
|
+
}
|
package/lambdaClass/index.js
CHANGED
|
@@ -57,9 +57,9 @@ module.exports = class Lambda {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
s3 = {
|
|
60
|
-
upload: async (data, path) => {
|
|
60
|
+
upload: async (data, path, options = {}) => {
|
|
61
61
|
return await s3bucket.uploadToS3(path, data, {
|
|
62
|
-
ContentEncoding: "base64", ContentType: "image/png",
|
|
62
|
+
ContentEncoding: options.contentEncoding || "base64", ContentType: options.ContentType || "image/png",
|
|
63
63
|
});
|
|
64
64
|
}, download: async (path) => {
|
|
65
65
|
return await s3bucket.downloadFileFromS3(path);
|
package/package.json
CHANGED
package/utils/index.js
CHANGED
|
@@ -303,7 +303,87 @@ const getValueOrNullControl = (
|
|
|
303
303
|
throw new Error(`Failed trying to get value with path ${path}`);
|
|
304
304
|
}
|
|
305
305
|
};
|
|
306
|
+
/**
|
|
307
|
+
* Retrieves a value from a nested object structure based on a given path,
|
|
308
|
+
* with an option to fall back to a default value if the path does not yield a valid result.
|
|
309
|
+
*
|
|
310
|
+
* @param {Object} [value={}] - The object from which to retrieve the value. Defaults to an empty object if not provided.
|
|
311
|
+
* @param {Array<string>} [paths=[]] - An array of string paths, each representing a path to a nested value in the object.
|
|
312
|
+
* The function tries each path in sequence until a valid result is obtained.
|
|
313
|
+
* @param {*} [defaultFallback=null] - The default value to return if no valid value is found at any of the specified paths.
|
|
314
|
+
* Defaults to null if not provided.
|
|
315
|
+
* @returns {*} - Returns the value found at the first valid path, the default fallback value if none of the paths are valid,
|
|
316
|
+
* or throws an error if no paths are provided or if no fallback is set when a required path yields null.
|
|
317
|
+
* @throws {Error} - Throws an error if the first path is null (indicating no paths were provided), if a required value
|
|
318
|
+
* at a path is null and no more paths are left to check (without a valid defaultFallback), or if any
|
|
319
|
+
* other unexpected error occurs during execution.
|
|
320
|
+
*/
|
|
321
|
+
const getValueOrNullControlWithFallback = (
|
|
322
|
+
value = {},
|
|
323
|
+
paths = [],
|
|
324
|
+
defaultFallback = null
|
|
325
|
+
) => {
|
|
326
|
+
try {
|
|
327
|
+
const path = paths[0];
|
|
328
|
+
if(path == null) throw new Error(`Path is required`);
|
|
329
|
+
const result = getValueOrNull(value, path);
|
|
330
|
+
if(result == null && paths.length === 1 && defaultFallback != null) return defaultFallback;
|
|
331
|
+
if(result == null && paths.length === 1) throw new Error(`Value path ${path} is required`);
|
|
332
|
+
if (result) return result;
|
|
333
|
+
if(paths.length === 1) return defaultFallback;
|
|
334
|
+
return getValueOrNullControlWithFallback(value, paths.slice(1), defaultFallback);
|
|
335
|
+
} catch (e) {
|
|
336
|
+
throw e || new Error(`Failed trying to get value with paths ${paths}`);
|
|
337
|
+
}
|
|
338
|
+
};
|
|
306
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Determines the MIME type of a file encoded in base64 format based on the file's signature.
|
|
342
|
+
*
|
|
343
|
+
* @param {string} base64 - The base64 encoded string of the file.
|
|
344
|
+
* @returns {string} - The MIME type of the file. Returns 'application/octet-stream' if the type cannot be determined.
|
|
345
|
+
*/
|
|
346
|
+
const getMimeTypeFromBase64 = (base64,defaultType = 'application/pdf') => {
|
|
347
|
+
const signatures = {
|
|
348
|
+
JVBERi0: 'application/pdf',
|
|
349
|
+
R0lGOD: 'image/gif',
|
|
350
|
+
iVBOR: 'image/png',
|
|
351
|
+
'/9j/': 'image/jpg',
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
for (const sign in signatures) {
|
|
355
|
+
if (base64.includes(sign)) return signatures[sign];
|
|
356
|
+
}
|
|
357
|
+
return defaultType;
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Determines the type of freight charges based on the given INCOTERM.
|
|
363
|
+
*
|
|
364
|
+
* @param {string} incoterm - The INCOTERM code based on which the freight charge type is determined.
|
|
365
|
+
* @returns {string} - Returns "D" for direct charges or "P" for prepaid charges.
|
|
366
|
+
*/
|
|
367
|
+
const getTipoPortes = incoterm => {
|
|
368
|
+
switch (String(incoterm).toUpperCase()) {
|
|
369
|
+
case "EXW":
|
|
370
|
+
case "FAS":
|
|
371
|
+
case "FOB":
|
|
372
|
+
return "D";
|
|
373
|
+
case "FCA":
|
|
374
|
+
case "CPT":
|
|
375
|
+
case "CIP":
|
|
376
|
+
case "DPU":
|
|
377
|
+
case "DAP":
|
|
378
|
+
case "DDP":
|
|
379
|
+
case "CFR":
|
|
380
|
+
case "CIF":
|
|
381
|
+
return "P";
|
|
382
|
+
default:
|
|
383
|
+
return "P";
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
307
387
|
// use it to create safe fields for csv files writing
|
|
308
388
|
const generateCSVField = (
|
|
309
389
|
obj,
|
|
@@ -576,4 +656,7 @@ module.exports = {
|
|
|
576
656
|
generateUuid,
|
|
577
657
|
mergePDF,
|
|
578
658
|
getMessageAndCodeFromError,
|
|
659
|
+
getValueOrNullControlWithFallback,
|
|
660
|
+
getMimeTypeFromBase64,
|
|
661
|
+
getTipoPortes,
|
|
579
662
|
};
|