store-s3-aws 1.3.13 → 1.3.15

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/AwsS3Store.js +169 -167
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "store-s3-aws",
3
- "version": "1.3.13",
3
+ "version": "1.3.15",
4
4
  "description": "Lib to store files in AWS S3",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/AwsS3Store.js CHANGED
@@ -1,167 +1,169 @@
1
- const path = require('path');
2
- const fs = require('fs');
3
- const { createReadStream } = require('fs');
4
- const { S3Client, HeadObjectCommand, GetObjectCommand, DeleteObjectCommand, CopyObjectCommand } = require('@aws-sdk/client-s3');
5
- const { Upload } = require('@aws-sdk/lib-storage');
6
-
7
- class AwsS3Store {
8
-
9
- #clientS3 = null;
10
-
11
- /**
12
- * A class for storing authentication data of Whatsapp-web.js to AWS S3.
13
- * @example
14
- * For example usage see `example/index.js`.
15
- * @param {Object} options Specifies the params pattern.
16
- * @param {String} options.bucketName Specifies the S3 bucket name.
17
- * @param {String} options.remoteDataPath Specifies the remote path to save authentication files.
18
- */
19
- constructor({ bucketName, remoteDataPath, clientConfig} = {}) {
20
- if (!bucketName) throw new Error("A valid bucket name is required for AwsS3Store.");
21
- if (!remoteDataPath) throw new Error("A valid remote dir path is required for AwsS3Store.");
22
- this.bucketName = bucketName;
23
- this.remoteDataPath = remoteDataPath;
24
- this.clientConfig = clientConfig
25
- this.debugEnabled = process.env.STORE_DEBUG === 'true';
26
- }
27
-
28
- async sessionExists(options) {
29
- this.debugLog('[METHOD: sessionExists] Triggered.');
30
-
31
- const remoteFilePath = path.join(this.remoteDataPath, `${options.session}.zip`).replace(/\\/g, '/');
32
- const params = {
33
- Bucket: this.bucketName,
34
- Key: remoteFilePath
35
- };
36
- try {
37
- await this.#getClientS3().send(new HeadObjectCommand(params));
38
- this.debugLog(`[METHOD: sessionExists] File found. PATH='${remoteFilePath}'.`);
39
- return true;
40
- } catch (err) {
41
- if (err.name === 'NoSuchKey' || err.name === 'NotFound') {
42
- this.debugLog(`[METHOD: sessionExists] File not found. PATH='${remoteFilePath}'.`);
43
- return false;
44
- }
45
- this.debugLog(`[METHOD: sessionExists] Error: ${err.message}`);
46
- // throw err;
47
- return
48
- }
49
- }
50
-
51
- async save(options) {
52
- this.debugLog('[METHOD: save] Triggered.');
53
- this.debugLog(`Options: ${JSON.stringify(options, null, 2)}`);
54
-
55
- const fileName = path.basename(options.session)
56
- const remoteFilePath = path.join(this.remoteDataPath, `${fileName}.zip`).replace(/\\/g, '/');
57
- options.remoteFilePath = remoteFilePath;
58
- //await this.#deletePrevious(options);
59
-
60
- const fileStream = createReadStream(`${options.session}.zip`);
61
-
62
- const upload = new Upload({
63
- client: this.#getClientS3(),
64
- params: {
65
- Bucket: this.bucketName,
66
- Key: remoteFilePath,
67
- Body: fileStream,
68
- },
69
- leavePartsOnError: false,
70
- });
71
-
72
- await upload.done();
73
-
74
- this.debugLog(`[METHOD: save] File saved. PATH='${remoteFilePath}'.`);
75
- }
76
-
77
- async extract(options) {
78
- this.debugLog('[METHOD: extract] Triggered.');
79
-
80
- this.debugLog(`Options: ${JSON.stringify(options, null, 2)}`);
81
-
82
- const remoteFilePath = path.join(this.remoteDataPath, `${options.session}.zip`).replace(/\\/g, '/');
83
- const params = {
84
- Bucket: this.bucketName,
85
- Key: remoteFilePath
86
- };
87
- const fileStream = fs.createWriteStream(options.path);
88
- const response = await this.#getClientS3().send(new GetObjectCommand(params));
89
- await new Promise((resolve, reject) => {
90
- response.Body.pipe(fileStream)
91
- .on('error', reject)
92
- .on('finish', resolve);
93
- });
94
-
95
- this.debugLog(`[METHOD: extract] File extracted. REMOTE_PATH='${remoteFilePath}', LOCAL_PATH='${options.path}'.`);
96
-
97
- }
98
-
99
- async delete(options) {
100
- this.debugLog('[METHOD: delete] Triggered.');
101
-
102
- const remoteFilePath = path.join(this.remoteDataPath, `${options.session}.zip`).replace(/\\/g, '/');
103
- const params = {
104
- Bucket: this.bucketName,
105
- Key: remoteFilePath
106
- };
107
- try {
108
- await this.#getClientS3().send(new HeadObjectCommand(params));
109
- await this.#getClientS3().send(new DeleteObjectCommand(params));
110
- this.debugLog(`[METHOD: delete] File deleted. PATH='${remoteFilePath}'.`);
111
- } catch (err) {
112
- if (err.name === 'NoSuchKey' || err.name === 'NotFound') {
113
- this.debugLog(`[METHOD: delete] File not found. PATH='${remoteFilePath}'.`);
114
- return;
115
- }
116
- this.debugLog(`[METHOD: delete] Error: ${err.message}`);
117
- // throw err;
118
- return
119
- }
120
- }
121
-
122
- async #deletePrevious(options) {
123
- this.debugLog('[METHOD: #deletePrevious] Triggered.');
124
-
125
- const params = {
126
- Bucket: this.bucketName,
127
- Key: options.remoteFilePath
128
- };
129
- try {
130
- await this.#getClientS3().send(new HeadObjectCommand(params));
131
- const backupKey = `${options.remoteFilePath}.backup`;
132
- await this.#getClientS3().send(new CopyObjectCommand({
133
- Bucket: this.bucketName,
134
- CopySource: `${this.bucketName}/${options.remoteFilePath}`,
135
- Key: backupKey
136
- }));
137
- await this.#getClientS3().send(new DeleteObjectCommand(params));
138
- this.debugLog(`[METHOD: #deletePrevious] File deleted. PATH='${options.remoteFilePath}'.`);
139
- } catch (err) {
140
- if (err.name === 'NoSuchKey' || err.name === 'NotFound') {
141
- this.debugLog(`[METHOD: #deletePrevious] File not found. PATH='${options.remoteFilePath}'.`);
142
- return;
143
- }
144
- this.debugLog(`[METHOD: #deletePrevious] Error: ${err.message}`);
145
- // throw err;
146
- return
147
- }
148
- }
149
-
150
- #getClientS3() {
151
- if (this.#clientS3 === null) {
152
- this.#clientS3 = new S3Client({
153
- region: this.clientConfig.region
154
- });
155
- }
156
- return this.#clientS3;
157
- }
158
-
159
- debugLog(msg) {
160
- if (this.debugEnabled) {
161
- const timestamp = new Date().toISOString();
162
- console.log(`${timestamp} [STORE_DEBUG] ${msg}`);
163
- }
164
- }
165
- }
166
-
167
- module.exports = AwsS3Store;
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+ const { createReadStream } = require('fs');
4
+ const { S3Client, HeadObjectCommand, GetObjectCommand, DeleteObjectCommand, CopyObjectCommand } = require('@aws-sdk/client-s3');
5
+ const { Upload } = require('@aws-sdk/lib-storage');
6
+
7
+ class AwsS3Store {
8
+
9
+ #clientS3 = null;
10
+
11
+ /**
12
+ * A class for storing authentication data of Whatsapp-web.js to AWS S3.
13
+ * @example
14
+ * For example usage see `example/index.js`.
15
+ * @param {Object} options Specifies the params pattern.
16
+ * @param {String} options.bucketName Specifies the S3 bucket name.
17
+ * @param {String} options.remoteDataPath Specifies the remote path to save authentication files.
18
+ */
19
+ constructor({ bucketName, remoteDataPath, clientConfig} = {}) {
20
+ if (!bucketName) throw new Error("A valid bucket name is required for AwsS3Store.");
21
+ if (!remoteDataPath) throw new Error("A valid remote dir path is required for AwsS3Store.");
22
+ this.bucketName = bucketName;
23
+ this.remoteDataPath = remoteDataPath;
24
+ this.clientConfig = clientConfig
25
+ this.debugEnabled = process.env.STORE_DEBUG === 'true';
26
+ }
27
+
28
+ async sessionExists(options) {
29
+ this.debugLog('[METHOD: sessionExists] Triggered.');
30
+
31
+ const remoteFilePath = path.join(this.remoteDataPath, `${options.session}.zip`).replace(/\\/g, '/');
32
+ const params = {
33
+ Bucket: this.bucketName,
34
+ Key: remoteFilePath
35
+ };
36
+ try {
37
+ await this.#getClientS3().send(new HeadObjectCommand(params));
38
+ this.debugLog(`[METHOD: sessionExists] File found. PATH='${remoteFilePath}'.`);
39
+ return true;
40
+ } catch (err) {
41
+ if (err.name === 'NoSuchKey' || err.name === 'NotFound') {
42
+ this.debugLog(`[METHOD: sessionExists] File not found. PATH='${remoteFilePath}'.`);
43
+ return false;
44
+ }
45
+ this.debugLog(`[METHOD: sessionExists] Error: ${err.message}`);
46
+ // throw err;
47
+ return
48
+ }
49
+ }
50
+
51
+ async save(options) {
52
+ this.debugLog('[METHOD: save] Triggered.');
53
+ this.debugLog(`Options: ${JSON.stringify(options, null, 2)}`);
54
+
55
+ const fileName = path.basename(options.session)
56
+ const remoteFilePath = path.join(this.remoteDataPath, `${fileName}.zip`).replace(/\\/g, '/');
57
+ options.remoteFilePath = remoteFilePath;
58
+ //await this.#deletePrevious(options);
59
+
60
+ const fileStream = createReadStream(`./.wwebjs_auth/${options.session}.zip`);
61
+
62
+ const upload = new Upload({
63
+ client: this.#getClientS3(),
64
+ params: {
65
+ Bucket: this.bucketName,
66
+ Key: remoteFilePath,
67
+ Body: fileStream,
68
+ },
69
+ leavePartsOnError: false,
70
+ });
71
+
72
+ await upload.done();
73
+
74
+ this.debugLog(`[METHOD: save] File saved. PATH='${remoteFilePath}'.`);
75
+ }
76
+
77
+ async extract(options) {
78
+ this.debugLog('[METHOD: extract] Triggered.');
79
+
80
+ this.debugLog(`Options: ${JSON.stringify(options, null, 2)}`);
81
+
82
+ const remoteFilePath = path.join(this.remoteDataPath, `${options.session}.zip`).replace(/\\/g, '/');
83
+ const params = {
84
+ Bucket: this.bucketName,
85
+ Key: remoteFilePath
86
+ };
87
+ const dir = path.dirname(options.path);
88
+ await fs.promises.mkdir(dir, { recursive: true });
89
+ const fileStream = fs.createWriteStream(options.path);
90
+ const response = await this.#getClientS3().send(new GetObjectCommand(params));
91
+ await new Promise((resolve, reject) => {
92
+ response.Body.pipe(fileStream)
93
+ .on('error', reject)
94
+ .on('finish', resolve);
95
+ });
96
+
97
+ this.debugLog(`[METHOD: extract] File extracted. REMOTE_PATH='${remoteFilePath}', LOCAL_PATH='${options.path}'.`);
98
+
99
+ }
100
+
101
+ async delete(options) {
102
+ this.debugLog('[METHOD: delete] Triggered.');
103
+
104
+ const remoteFilePath = path.join(this.remoteDataPath, `${options.session}.zip`).replace(/\\/g, '/');
105
+ const params = {
106
+ Bucket: this.bucketName,
107
+ Key: remoteFilePath
108
+ };
109
+ try {
110
+ await this.#getClientS3().send(new HeadObjectCommand(params));
111
+ await this.#getClientS3().send(new DeleteObjectCommand(params));
112
+ this.debugLog(`[METHOD: delete] File deleted. PATH='${remoteFilePath}'.`);
113
+ } catch (err) {
114
+ if (err.name === 'NoSuchKey' || err.name === 'NotFound') {
115
+ this.debugLog(`[METHOD: delete] File not found. PATH='${remoteFilePath}'.`);
116
+ return;
117
+ }
118
+ this.debugLog(`[METHOD: delete] Error: ${err.message}`);
119
+ // throw err;
120
+ return
121
+ }
122
+ }
123
+
124
+ async #deletePrevious(options) {
125
+ this.debugLog('[METHOD: #deletePrevious] Triggered.');
126
+
127
+ const params = {
128
+ Bucket: this.bucketName,
129
+ Key: options.remoteFilePath
130
+ };
131
+ try {
132
+ await this.#getClientS3().send(new HeadObjectCommand(params));
133
+ const backupKey = `${options.remoteFilePath}.backup`;
134
+ await this.#getClientS3().send(new CopyObjectCommand({
135
+ Bucket: this.bucketName,
136
+ CopySource: `${this.bucketName}/${options.remoteFilePath}`,
137
+ Key: backupKey
138
+ }));
139
+ await this.#getClientS3().send(new DeleteObjectCommand(params));
140
+ this.debugLog(`[METHOD: #deletePrevious] File deleted. PATH='${options.remoteFilePath}'.`);
141
+ } catch (err) {
142
+ if (err.name === 'NoSuchKey' || err.name === 'NotFound') {
143
+ this.debugLog(`[METHOD: #deletePrevious] File not found. PATH='${options.remoteFilePath}'.`);
144
+ return;
145
+ }
146
+ this.debugLog(`[METHOD: #deletePrevious] Error: ${err.message}`);
147
+ // throw err;
148
+ return
149
+ }
150
+ }
151
+
152
+ #getClientS3() {
153
+ if (this.#clientS3 === null) {
154
+ this.#clientS3 = new S3Client({
155
+ region: this.clientConfig.region
156
+ });
157
+ }
158
+ return this.#clientS3;
159
+ }
160
+
161
+ debugLog(msg) {
162
+ if (this.debugEnabled) {
163
+ const timestamp = new Date().toISOString();
164
+ console.log(`${timestamp} [STORE_DEBUG] ${msg}`);
165
+ }
166
+ }
167
+ }
168
+
169
+ module.exports = AwsS3Store;