vtlab-generic-functions 1.0.4

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.
@@ -0,0 +1,61 @@
1
+ let dot = require('dot-object');
2
+
3
+
4
+ /**
5
+ * This function will transform the incoming values received on data onto the outgoing mapped values, returning a JSON object.
6
+ * @param data Values required for transformations
7
+ * @param model Models required to say how the values need to be transformed. Property `transformation` and `originKey` is must
8
+ * @returns {{}|*}
9
+ */
10
+ const parseFields = (data = {}, model = {}) => {
11
+
12
+ //validate the parameter
13
+ if (typeof data !== 'object' || typeof model !== 'object')
14
+ return {};
15
+
16
+ // declare the mapped value to return
17
+ let mappedData = {};
18
+
19
+ //transformation function
20
+ let makeTransformations = function (data, model, parent = '') {
21
+
22
+ if (typeof model !== 'object')
23
+ return null;
24
+
25
+ //loop all the keys in the model
26
+ for (let modelKey in model) {
27
+
28
+ //return if the key is the property of the model. eg: __proto__, [[Prototype]] etc.,
29
+ if (!model.hasOwnProperty(modelKey))
30
+ continue;
31
+
32
+ //each model
33
+ let currentModel = model[modelKey];
34
+
35
+ // if the model has sub model
36
+ if (typeof currentModel === 'object' && !currentModel.transformation && !currentModel.originKey) {
37
+ makeTransformations(data, currentModel, parent + modelKey + '.');
38
+ } else {
39
+
40
+ //if model doesn't has sub model
41
+ try {
42
+ mappedData[parent + modelKey] = currentModel.transformation(data);
43
+ } catch (e) {
44
+ // set `null` if transformation doesn't exist or error during the transformation
45
+ mappedData[parent + modelKey] = null;
46
+ }
47
+ }
48
+ }
49
+
50
+ };
51
+
52
+ // call transformation. return value is doted object eg: { 'depth0.depth1.depth2':valueOfDepth2 }
53
+ makeTransformations(data, model);
54
+
55
+ //make the proper object from the doted object. result is {depth0: {depth1: depth2: 'valueOfDepth2'}}
56
+ return dot.object(mappedData); //make it nested object
57
+ };
58
+
59
+ module.exports = {
60
+ parseFields
61
+ };
@@ -0,0 +1,153 @@
1
+ const nodemailer = require("nodemailer");
2
+ const MailComposer = require("nodemailer/lib/mail-composer");
3
+ const { SESClient, SendRawEmailCommand } = require("@aws-sdk/client-ses");
4
+ const config = require("../config");
5
+
6
+ const CODES_TYPE = {
7
+ INPUT_DATA_ERROR : 'input_data_error',
8
+ SUCCESSFULL_OP :'successfull_op',
9
+ GENERIC_ERROR: 'generic_error'
10
+ }
11
+
12
+ /**
13
+ * Sends an email using a SMTP server.
14
+ *
15
+ * @param {Object} options - The email options.
16
+ * @param {string} options.host - The SMTP server host.
17
+ * @param {number} [options.port=587] - The SMTP server port.
18
+ * @param {string} options.user - The SMTP server username.
19
+ * @param {string} options.password - The SMTP server password.
20
+ * @param {string} options.from - The sender's email address.
21
+ * @param {string|string[]} options.to - The recipient's email address(es).
22
+ * @param {string} options.subject - The subject of the email.
23
+ * @param {string} [options.htmlBody] - The HTML body of the email.
24
+ * @param {string} [options.textBody] - The text body of the email.
25
+ * @returns {Promise<Object>} - A promise that resolves to the result of the email sending operation.
26
+ * @throws {Object} - An error object with detailed information if the operation fails.
27
+ */
28
+ const sendMail = async ({host, port=587, user, password, from, to, subject, htmlBody, textBody}) =>{
29
+
30
+ if(isNaN(port)){
31
+ throw {
32
+ code : CODES_TYPE.INPUT_DATA_ERROR,
33
+ message : "El parámetro 'port' no es numérico",
34
+ alternative: "Asegúese de que el 'port' es númerico. Posiblemente adoptará el valor 587 o 465",
35
+ dataError: {}
36
+ };
37
+ }
38
+
39
+ try{
40
+
41
+ port = parseInt(port);
42
+ let secure = port === 465 ? true : false;
43
+
44
+
45
+ let transporter = nodemailer.createTransport({
46
+ host: host,
47
+ port: port,
48
+ secure: secure, // true for 465, false for other ports
49
+ auth: {
50
+ user: user, // generated ethereal user
51
+ pass: password, // generated ethereal password
52
+ },
53
+ tls: {
54
+ rejectUnauthorized: false
55
+ }
56
+ });
57
+
58
+ let info = await transporter.sendMail({
59
+ from: from, //'"Fred Foo 👻" <foo@example.com>',
60
+ to: to, // "bar@example.com, baz@example.com", // list of receivers
61
+ subject: subject, //"Hello ✔", // Subject line
62
+ text: textBody ? textBody : '', //"Hello world?", // plain text body
63
+ html: htmlBody ? htmlBody : '' //"<b>Hello world?</b>", // html body
64
+ });
65
+
66
+ return {
67
+ code: CODES_TYPE.SUCCESSFULL_OP,
68
+ message: 'Mail enviado correctamente',
69
+ alternative:'',
70
+ data: info
71
+ }
72
+
73
+
74
+ }catch(err){
75
+ throw {
76
+ code: CODES_TYPE.GENERIC_ERROR,
77
+ message: 'Se ha producido un error en el envío de mail',
78
+ alternative: 'Consulte el error retornado',
79
+ dataError: err
80
+ }
81
+ }
82
+ }
83
+
84
+
85
+ /**
86
+ * Sends an email using AWS SES with optional file attachment.
87
+ *
88
+ * @param {Object} mailParameters - Parameters for the email.
89
+ * @param {Buffer|string} [mailParameters.file] - The file to attach in the email.
90
+ * @param {string} [mailParameters.subject="Default subject (subject not provided)"] - The subject of the email.
91
+ * @param {string} [mailParameters.text="Default text (text not provided)"] - The text body of the email.
92
+ * @param {string} [mailParameters.fileName=`${Date.now()}.txt`] - The name of the attached file.
93
+ * @param {string|string[]} [mailParameters.to="develop@tookane.com"] - The recipient's email address(es).
94
+ * @param {string} [mailParameters.contentType='text/plain'] - The content type of the file.
95
+ * @returns {Promise<void>} - A promise that resolves when the email is sent.
96
+ * @throws {Error} - An error if sending the email fails.
97
+ */
98
+ const sendMailWithSES = async (mailParameters) => {
99
+ const {
100
+ file,
101
+ subject = "Default subject (subject not provided)",
102
+ text = "Default text (text not provided)",
103
+ fileName = `${Date.now()}.txt`,
104
+ to = "develop@tookane.com",
105
+ contentType = 'text/plain'
106
+ } = mailParameters;
107
+
108
+ let attachments = [];
109
+ if (file) {
110
+ attachments.push({
111
+ filename: fileName,
112
+ content: typeof file === 'string' ? Buffer.from(file, 'base64') : file,
113
+ contentType
114
+ });
115
+ }
116
+
117
+ let mail = new MailComposer({
118
+ to: Array.isArray(to) ? to.join(",") : to,
119
+ subject,
120
+ text,
121
+ attachments
122
+ });
123
+
124
+ let RawMessage = await mail.compile().build();
125
+ let params = {
126
+ RawMessage: {
127
+ Data: RawMessage
128
+ },
129
+ Destinations: Array.isArray(to) ? to : [to],
130
+ Source: "develop@tookane.com", // Replace with your verified SES email
131
+ };
132
+
133
+ const awsCredentials = await config.get('awsCredentials');
134
+
135
+
136
+ const sesClient = new SESClient({
137
+ region: awsCredentials.region,
138
+ credentials: {
139
+ accessKeyId: awsCredentials.accessKeyId,
140
+ secretAccessKey: awsCredentials.secretAccessKey
141
+ }
142
+ });
143
+
144
+ const command = new SendRawEmailCommand(params);
145
+ await sesClient.send(command);
146
+ };
147
+
148
+
149
+
150
+ module.exports = {
151
+ sendMail,
152
+ sendMailWithSES
153
+ }
@@ -0,0 +1,109 @@
1
+ const promiseFTP = require("promise-ftp");
2
+ /**
3
+ *
4
+ * Internal functions
5
+ */
6
+
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
+
20
+ /**
21
+ *
22
+ * EXTERNAL FUNCTIONS
23
+ */
24
+ //downloadFromFTP
25
+ const downloadFromFTP = async (ftp, remotePathWithFile) => {
26
+ let _buf = [];
27
+ let Stream = require("stream");
28
+ const writableStream = new Stream.Writable();
29
+ writableStream._write = (chunk, encoding, next) => {
30
+ _buf.push(chunk);
31
+ next();
32
+ };
33
+ return ftp
34
+ .get(remotePathWithFile)
35
+ .then((stream) => {
36
+ return new Promise(function (resolve, reject) {
37
+ stream.once("close", resolve);
38
+ stream.once("error", reject);
39
+ stream.pipe(writableStream);
40
+ });
41
+ })
42
+ .then(() => {
43
+ return _buf;
44
+ })
45
+ .catch((err) => {
46
+ throw err;
47
+ });
48
+ };
49
+
50
+ //uploadFileToFTP
51
+ const uploadFileToFTP = async (
52
+ config,
53
+ localPathWithFile,
54
+ remotePathWithFile
55
+ ) => {
56
+ /**
57
+ * config ={
58
+ host: 'ftp.islgrupo.com',
59
+ user: 'testpelikane',
60
+ password: 'Pelikane2021+',
61
+ port: <OPtional>
62
+ }
63
+ */
64
+ let ftp = new promiseFTP();
65
+ try {
66
+ await ftp.connect(config);
67
+ await ftp.put(localPathWithFile, remotePathWithFile);
68
+ return { code: 200, message: "FTP successfull ulpload" };
69
+ } catch (err) {
70
+ throw err;
71
+ }
72
+ };
73
+
74
+ /**
75
+ * To check the file existence in the FTP
76
+ * @param ftp
77
+ * @param filePath
78
+ * @returns {Promise<boolean>}
79
+ */
80
+ const isFileExistsInFTP = async (ftp, filePath) => {
81
+ try {
82
+ let exists = await ftp.list(filePath);
83
+ return exists.length > 0;
84
+ } catch (e) {
85
+ throw e;
86
+ }
87
+ };
88
+
89
+ /**
90
+ * to delete a file
91
+ * @param ftp
92
+ * @param filePath
93
+ * @returns {Promise<void>}
94
+ */
95
+ const deleteFileFromFTP = async (ftp, filePath) => {
96
+ try {
97
+ await ftp.delete(filePath);
98
+ } catch (e) {
99
+ throw e;
100
+ }
101
+ };
102
+
103
+
104
+ module.exports = {
105
+ uploadFileToFTP,
106
+ downloadFromFTP,
107
+ isFileExistsInFTP,
108
+ deleteFileFromFTP
109
+ };
package/ftp/index.js ADDED
@@ -0,0 +1,194 @@
1
+ const Client = require('ssh2-sftp-client');
2
+ const fs = require ('fs');
3
+
4
+ // THIS FILE ONLY WORKS WITH SFTP. FOR FTP USE THE INSTALLED NODE MODULE PROMISE-FTP
5
+
6
+ const FTP_CODES = {
7
+ CONNECTION_FAILED : 'connection_failed',
8
+ DISCONNECTED_CLIENT: 'disconnected_client',
9
+ UPLOAD_FAILED: 'upload_failed',
10
+ UPLOAD_SUCCESFULLY: 'upload_succesfully',
11
+ DOWNLOAD_FAILED: 'download_failed',
12
+ DOWNLOAD_SUCCESFULLY: 'download_succesfully',
13
+ OPERATION_NOT_FOUND: 'operation_not_found',
14
+ GENERIC_ERROR:'generic_error'
15
+ }
16
+
17
+ const getFileFromFtp = async ({host, user, password, localPathWithFile, remotePathWithFile}) => {
18
+
19
+ try{
20
+ let dst = fs.createWriteStream(localPathWithFile);
21
+ //let dst = localPathWithFile;
22
+
23
+ let sftp = new Client();
24
+ await sftp.connect({
25
+ host: host,
26
+ username: user,
27
+ password: password
28
+ });
29
+
30
+ /*let listData = await sftp.list('/OUT/monto/');
31
+ sftp.end(); //BORRAR
32
+ return listData;*/
33
+
34
+ await sftp.get(remotePathWithFile,dst);
35
+
36
+ return {
37
+ code: FTP_CODES.DOWNLOAD_SUCCESFULLY,
38
+ message: 'La descarga del fichero se ha realizado correctamente',
39
+ alternative: '',
40
+ data:{}
41
+ };
42
+
43
+ }catch(err){
44
+ throw {
45
+ code: FTP_CODES.GENERIC_ERROR,
46
+ message: 'Se ha producido un error durante la descarga del fichero',
47
+ alternative: 'Consultar el detalle del error',
48
+ dataError: err
49
+ }
50
+ }finally{
51
+ try{
52
+ sftp.end();
53
+ }catch(e){
54
+
55
+ }
56
+ }
57
+
58
+ }
59
+
60
+ const uploadFileToFtp = async ({host, user, password, localPathWithFile, remotePathWithFile}) => {
61
+
62
+ try{
63
+ let sftp = new Client();
64
+ await sftp.connect({
65
+ host: host,
66
+ username: user,
67
+ password: password
68
+ });
69
+
70
+ sftp.put(localPathWithFile,remotePathWithFile);
71
+
72
+ return {
73
+ code: FTP_CODES.DOWNLOAD_SUCCESFULLY,
74
+ message: 'La subida del fichero al servidor se ha realizado correctamente',
75
+ alternative: '',
76
+ data:{}
77
+ };
78
+
79
+ }catch(err){
80
+ throw {
81
+ code: FTP_CODES.GENERIC_ERROR,
82
+ message: 'Se ha producido un error durante la descarga del fichero',
83
+ alternative: 'Consultar el detalle del error',
84
+ dataError: err
85
+ }
86
+ }finally{
87
+ try{
88
+ sftp.end();
89
+ }catch(e){
90
+
91
+ }
92
+ }
93
+
94
+ }
95
+
96
+ const uploadFileFtpWithClient = async ({client, pathFrom, pathTo}) =>{
97
+ /*if(client.closed) {
98
+ throw {
99
+ code: FTP_CODES.DISCONNECTED_CLIENT,
100
+ message: 'El cliente no está conectado',
101
+ alternative: 'Conéctese de nuevo al servidor.',
102
+ dataError: {}
103
+ }
104
+ }
105
+
106
+ try{
107
+
108
+ await client.uploadFrom(pathFrom, pathTo)
109
+ return {
110
+ code: FTP_CODES.UPLOAD_SUCCESFULLY,
111
+ message: 'Se ha subido correctamente el fichero al servidor',
112
+ alternative: 'Recuerde cerrar la conexión si no va a hacer más operaciones sobre el servidor.',
113
+ data: {}
114
+ }
115
+
116
+ }catch(err){
117
+ throw {
118
+ code: FTP_CODES.UPLOAD_FAILED,
119
+ message: 'Error en la subida del fichero al servidor',
120
+ alternative: 'Ver error generado por el servidor e intentarlo de nuevo.',
121
+ dataError: err
122
+ }
123
+ }*/
124
+ }
125
+
126
+ const downloadFileFtpWithClient = async ({client, pathFrom, pathTo}) =>{
127
+ /*if(client.closed) {
128
+ throw {
129
+ code: FTP_CODES.DISCONNECTED_CLIENT,
130
+ message: 'El cliente no está conectado',
131
+ alternative: 'Conéctese de nuevo al servidor.',
132
+ dataError: {}
133
+ }
134
+ }
135
+
136
+ try{
137
+
138
+ await client.downloadTo(pathFrom, pathTo)
139
+ return {
140
+ code: FTP_CODES.DOWNLOAD_SUCCESFULLY,
141
+ message: 'Se ha subido correctamente el fichero al servidor',
142
+ alternative: 'Recuerde cerrar la conexión si no va a hacer más operaciones sobre el servidor.',
143
+ data: {}
144
+ }
145
+
146
+ }catch(err){
147
+ throw {
148
+ code: FTP_CODES.DOWNLOAD_FAILED,
149
+ message: 'Error en la descarga del fichero al servidor',
150
+ alternative: 'Ver error generado por el servidor e intentarlo de nuevo.',
151
+ dataError: err
152
+ }
153
+ }*/
154
+ }
155
+
156
+ const uploadOrDownloadFileFtp = async ({host, user, password, secure=false, typeOp='upload', pathFrom, pathTo}) =>{
157
+ /* try{
158
+ let result ={};
159
+ let client = await getFtpClient({host, user, password, secure=false})
160
+ if(typeOp==='upload'){
161
+ let uploadRes = await uploadFileFtpWithClient ({client, pathFrom, pathTo});
162
+ result = uploadRes;
163
+ }else if( typeOp === 'download'){
164
+ let downloaddRes = await downloadFileFtpWithClient ({client, pathFrom, pathTo});
165
+ result = downloaddRes
166
+ }else{
167
+ throw {
168
+ code: FTP_CODES.OPERATION_NOT_FOUND,
169
+ message: 'La operación no está disponible',
170
+ alternative: 'Incluye sólo las operaciones disponibles',
171
+ dataError: {}
172
+ }
173
+ }
174
+ client.close()
175
+
176
+ return result;
177
+
178
+ }catch(err){
179
+ throw {
180
+ code: FTP_CODES.GENERIC_ERROR,
181
+ message: 'Error al intentar la operación FTP',
182
+ alternative: 'Revise los datos del error',
183
+ dataError: err
184
+ }
185
+ }*/
186
+ }
187
+
188
+ module.exports = {
189
+ getFileFromFtp,
190
+ uploadFileToFtp,
191
+ uploadFileFtpWithClient,
192
+ downloadFileFtpWithClient,
193
+ uploadOrDownloadFileFtp
194
+ }
@@ -0,0 +1,107 @@
1
+ const jsFtp = require("jsftp");
2
+
3
+ // create connection
4
+ const connect = (config) => {
5
+ return new jsFtp({
6
+ host: config.host,
7
+ user: config.user, // defaults to "anonymous"
8
+ pass: config.password, // defaults to "@anonymous"
9
+ });
10
+ }
11
+
12
+
13
+ //uploadFileToFTP
14
+ const uploadFileToFTP = async (
15
+ ftp,
16
+ localPathWithFile,
17
+ remotePathWithFile
18
+ ) => {
19
+ return new Promise((resolve, reject) => {
20
+ try {
21
+ if (!ftp) {
22
+ throw 'FTP not connected';
23
+ }
24
+ ftp.put(localPathWithFile, remotePathWithFile, (err) => {
25
+ if (!err) {
26
+ return { code: 200, message: "FTP successfull ulpload" };
27
+ }
28
+ reject(err);
29
+ });
30
+ } catch (err) {
31
+ throw err;
32
+ }
33
+ })
34
+ };
35
+
36
+
37
+ /**
38
+ *
39
+ * EXTERNAL FUNCTIONS
40
+ */
41
+ //downloadFromFTP
42
+ const downloadFromFTP = async (ftp, remotePathWithFile) => {
43
+ return new Promise((resolve, reject) => {
44
+ let file = [];
45
+ try {
46
+ if (!ftp) {
47
+ throw 'FTP not connected';
48
+ }
49
+ ftp.get(remotePathWithFile, (err, socket) => {
50
+ if (err) {
51
+ reject(err);
52
+ } else {
53
+ socket.on("data", d => {
54
+ file.push(d);
55
+ });
56
+
57
+ socket.on("close", err => {
58
+ if (err) {
59
+ throw err;
60
+ }
61
+ resolve(Buffer.concat(file));
62
+ });
63
+ socket.resume();
64
+ }
65
+ });
66
+ } catch (e) {
67
+ console.log(e);
68
+ reject('There was an error reading the file');
69
+ }
70
+ })
71
+ };
72
+
73
+ const listFilesFromFolder = async (ftp, folder) => {
74
+ return new Promise((resolve, reject) => {
75
+ if (!ftp) {
76
+ reject('FTP not connected');
77
+ }
78
+ ftp.ls(folder, (err, res) => {
79
+ if (err) {
80
+ reject(err);
81
+ }
82
+ resolve(res);
83
+ });
84
+ })
85
+ }
86
+
87
+ const deleteFromFTP = async (ftp, pathToFile) => {
88
+ return new Promise((resolve, reject) => {
89
+ if (!ftp) {
90
+ reject('FTP not connected');
91
+ }
92
+ ftp.raw("DELE", pathToFile, (err, res) => {
93
+ if (err) {
94
+ reject(err);
95
+ }
96
+ resolve(res);
97
+ });
98
+ })
99
+ }
100
+
101
+ module.exports = {
102
+ connect,
103
+ uploadFileToFTP,
104
+ downloadFromFTP,
105
+ listFilesFromFolder,
106
+ deleteFromFTP,
107
+ };