eip-cloud-services 1.0.21 → 1.1.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/CHANGELOG.md +28 -3
- package/README.md +386 -0
- package/package.json +3 -2
- package/src/cdn.js +11 -1
- package/src/lambda.js +0 -1
- package/src/mysql.js +11 -5
- package/src/redis.js +379 -132
- package/src/s3.js +145 -28
- package/src/util/log.js +3 -0
package/src/s3.js
CHANGED
|
@@ -39,20 +39,27 @@
|
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
41
|
const { S3Client, HeadObjectCommand, GetObjectCommand, PutObjectCommand, DeleteObjectCommand, CopyObjectCommand, DeleteObjectsCommand } = require ( '@aws-sdk/client-s3' );
|
|
42
|
-
const
|
|
42
|
+
const fs = require ( 'fs' );
|
|
43
|
+
let config = {};
|
|
44
|
+
const configDirPath = `${ process.cwd ()}/config`;
|
|
45
|
+
if ( fs.existsSync ( configDirPath ) && fs.statSync ( configDirPath ).isDirectory () ) {
|
|
46
|
+
config = require ( 'config' ); // require the config directory if it exists
|
|
47
|
+
}
|
|
43
48
|
const zlib = require ( 'zlib' );
|
|
44
|
-
|
|
49
|
+
const crypto = require ( 'crypto' );
|
|
50
|
+
const { cwd } = require ( 'process' );
|
|
51
|
+
const { log } = config?.s3?.logsFunction ? require ( `${ cwd ()}/${config?.s3?.logsFunction}` ) : console;
|
|
45
52
|
const S3 = new S3Client ( { region: 'eu-west-1' } );
|
|
46
53
|
|
|
47
54
|
/**
|
|
48
55
|
* Check if an object exists in S3.
|
|
49
56
|
*
|
|
50
57
|
* @param {string} key - The object key.
|
|
51
|
-
* @param {string} [bucket=config
|
|
58
|
+
* @param {string} [bucket=config?.s3?.Bucket] - The bucket name. Defaults to the configured bucket.
|
|
52
59
|
* @returns {Promise<boolean>} A promise that resolves to true if the object exists, false otherwise.
|
|
53
60
|
* @description Checks if an object with the specified key exists in S3.
|
|
54
61
|
*/
|
|
55
|
-
exports.exists = async ( key, bucket = config
|
|
62
|
+
exports.exists = async ( key, bucket = config?.s3?.Bucket ) => {
|
|
56
63
|
try {
|
|
57
64
|
const command = new HeadObjectCommand ( {
|
|
58
65
|
Bucket: bucket,
|
|
@@ -60,10 +67,16 @@ exports.exists = async ( key, bucket = config.s3.Bucket ) => {
|
|
|
60
67
|
} );
|
|
61
68
|
|
|
62
69
|
await S3.send ( command );
|
|
70
|
+
|
|
71
|
+
if ( config?.s3?.logs === 'verbose' )
|
|
72
|
+
log ( `S3 [EXISTS]: ${key} on ${bucket} - Exists` );
|
|
63
73
|
|
|
64
74
|
return true;
|
|
65
75
|
}
|
|
66
76
|
catch ( error ) {
|
|
77
|
+
if ( config?.s3?.logs === 'verbose' )
|
|
78
|
+
log ( `S3 [EXISTS]: ${key} on ${bucket} - Does not exist` );
|
|
79
|
+
|
|
67
80
|
return false;
|
|
68
81
|
}
|
|
69
82
|
};
|
|
@@ -72,26 +85,61 @@ exports.exists = async ( key, bucket = config.s3.Bucket ) => {
|
|
|
72
85
|
* Get an object from S3.
|
|
73
86
|
*
|
|
74
87
|
* @param {string} key - The object key.
|
|
88
|
+
* @param {string} [bucket=config?.s3?.Bucket] - The bucket name. Defaults to the configured bucket.
|
|
75
89
|
* @returns {Promise} A promise that resolves to the retrieved object.
|
|
76
90
|
* @description Retrieves an object from S3 based on the provided key.
|
|
77
91
|
*/
|
|
78
|
-
exports.get = async ( key ) => {
|
|
92
|
+
exports.get = async ( key, bucket = config?.s3?.Bucket ) => {
|
|
79
93
|
try {
|
|
80
94
|
const command = new GetObjectCommand ( {
|
|
81
|
-
Bucket:
|
|
95
|
+
Bucket: bucket,
|
|
82
96
|
Key: key
|
|
83
97
|
} );
|
|
84
98
|
|
|
99
|
+
if ( config?.s3?.logs === 'verbose' )
|
|
100
|
+
log ( `S3 [GET]: Getting ${bucket}/${key}.` );
|
|
101
|
+
|
|
85
102
|
const response = await S3.send ( command );
|
|
86
103
|
let data = await streamToBuffer ( response.Body );
|
|
87
104
|
|
|
88
105
|
if ( response.ContentEncoding && response.ContentEncoding === 'gzip' ) {
|
|
106
|
+
|
|
107
|
+
if ( config?.s3?.logs === 'verbose' )
|
|
108
|
+
log ( `S3 [GET]: ${key} on ${bucket} was unzipped (was gzipped).` );
|
|
109
|
+
|
|
89
110
|
data = zlib.unzipSync ( data );
|
|
90
111
|
}
|
|
91
112
|
|
|
92
|
-
if ( response.ContentType !== 'application/json' ) {
|
|
113
|
+
if ( response.ContentType !== 'application/json' && !response.Metadata[ 'tmg-json' ] ) {
|
|
114
|
+
if ( config?.s3?.logs === 'output' )
|
|
115
|
+
log ( `S3 [GET]: Returned ${response.ContentType} from ${bucket}/${key}.` );
|
|
116
|
+
|
|
93
117
|
return data.toString ( 'utf8' );
|
|
94
118
|
}
|
|
119
|
+
|
|
120
|
+
if ( ( response.ContentType === 'application/json' || response.Metadata[ 'tmg-json' ] ) && response.Metadata[ 'tmg-crypt' ] && response.Metadata[ 'tmg-crypt-vec' ] ) {
|
|
121
|
+
const key = await crypto.subtle.importKey (
|
|
122
|
+
'raw',
|
|
123
|
+
Buffer.from ( response.Metadata[ 'tmg-crypt' ], 'base64' ),
|
|
124
|
+
{ name: 'AES-CBC', length: 256 },
|
|
125
|
+
false,
|
|
126
|
+
[ 'decrypt' ]
|
|
127
|
+
);
|
|
128
|
+
const iv = Buffer.from ( response.Metadata[ 'tmg-crypt-vec' ], 'base64' );
|
|
129
|
+
const decryptedArrayBuffer = await crypto.subtle.decrypt (
|
|
130
|
+
{ name: 'AES-CBC', iv },
|
|
131
|
+
key,
|
|
132
|
+
Buffer.from ( data.toString (), 'base64' )
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
data = Buffer.from ( decryptedArrayBuffer ).toString ( 'utf8' );
|
|
136
|
+
|
|
137
|
+
if ( config?.s3?.logs === 'verbose' )
|
|
138
|
+
log ( `S3 [GET]: ${key} on ${bucket} - JSON content was decrypted.` );
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if ( config?.s3?.logs === 'output' )
|
|
142
|
+
log ( `S3 [GET]: ${bucket}/${key} - JSON content was returned.` );
|
|
95
143
|
|
|
96
144
|
return JSON.parse ( data.toString ( 'utf8' ) );
|
|
97
145
|
}
|
|
@@ -110,21 +158,52 @@ exports.get = async ( key ) => {
|
|
|
110
158
|
* @param {string} key - The object key.
|
|
111
159
|
* @param {Buffer|Uint8Array|Blob|string} body - The object body.
|
|
112
160
|
* @param {object} [options] - The optional parameters for setting the object.
|
|
113
|
-
* @param {string} [options.bucket=config
|
|
161
|
+
* @param {string} [options.bucket=config?.s3?.Bucket] - The bucket name. Defaults to the configured bucket.
|
|
114
162
|
* @param {string} [options.contentType='application/json'] - The content type of the object. Defaults to 'application/json'.
|
|
115
163
|
* @param {string} [options.acl='public-read'] - The ACL (Access Control List) of the object. Defaults to 'public-read'.
|
|
116
164
|
* @param {string} [options.cacheControl='max-age=25,s-maxage=30,must-revalidate'] - Sets cache control for the object.
|
|
165
|
+
* @param {boolean} [options.encrypt=false] - When storing JSON parsing this as true will encrypt the data with a random uuid stored in the metadata of the object.
|
|
166
|
+
* @param {object} [options.metadata={}] - Sets metadata for the object.
|
|
117
167
|
* @returns {Promise} A promise that resolves when the object is successfully set in S3.
|
|
118
168
|
* @description Sets an object in S3 with the provided key, body, and optional parameters.
|
|
119
169
|
*/
|
|
120
170
|
exports.set = async ( key, body, options = {} ) => {
|
|
121
171
|
const {
|
|
122
|
-
bucket = config
|
|
172
|
+
bucket = config?.s3?.Bucket,
|
|
123
173
|
contentType = 'application/json',
|
|
124
174
|
acl = 'public-read',
|
|
125
|
-
cacheControl = 'max-age=25,s-maxage=30,must-revalidate'
|
|
175
|
+
cacheControl = 'max-age=25,s-maxage=30,must-revalidate',
|
|
176
|
+
encrypt = false,
|
|
177
|
+
metadata = {}
|
|
126
178
|
} = options;
|
|
127
|
-
|
|
179
|
+
|
|
180
|
+
if ( encrypt && ( contentType === 'application/json' || contentType === 'text/plain' ) ) {
|
|
181
|
+
|
|
182
|
+
if ( config?.s3?.logs === 'verbose' )
|
|
183
|
+
log ( `S3 [SET]: ${bucket}/${key} - Encrypting.` );
|
|
184
|
+
|
|
185
|
+
const encoder = new TextEncoder ();
|
|
186
|
+
const data = encoder.encode ( body );
|
|
187
|
+
|
|
188
|
+
const encryptionKey = await crypto.subtle.generateKey (
|
|
189
|
+
{ name: 'AES-CBC', length: 256 },
|
|
190
|
+
true,
|
|
191
|
+
[ 'encrypt', 'decrypt' ]
|
|
192
|
+
);
|
|
193
|
+
const iv = crypto.randomBytes ( 16 );
|
|
194
|
+
const exportedKey = await crypto.subtle.exportKey ( 'raw', encryptionKey );
|
|
195
|
+
const exportedIV = iv.toString ( 'base64' );
|
|
196
|
+
metadata[ 'Tmg-Crypt' ] = Buffer.from ( exportedKey ).toString ( 'base64' );
|
|
197
|
+
metadata[ 'Tmg-Crypt-Vec' ] = exportedIV;
|
|
198
|
+
|
|
199
|
+
const encryptedData = await crypto.subtle.encrypt (
|
|
200
|
+
{ name: 'AES-CBC', iv },
|
|
201
|
+
encryptionKey,
|
|
202
|
+
data
|
|
203
|
+
);
|
|
204
|
+
body = Buffer.from ( encryptedData ).toString ( 'base64' );
|
|
205
|
+
}
|
|
206
|
+
|
|
128
207
|
try {
|
|
129
208
|
const command = new PutObjectCommand ( {
|
|
130
209
|
Bucket: bucket,
|
|
@@ -132,14 +211,20 @@ exports.set = async ( key, body, options = {} ) => {
|
|
|
132
211
|
Body: body,
|
|
133
212
|
ContentType: contentType,
|
|
134
213
|
ACL: acl,
|
|
135
|
-
CacheControl: cacheControl
|
|
214
|
+
CacheControl: cacheControl,
|
|
215
|
+
Metadata: metadata,
|
|
216
|
+
ContentLength: Buffer.byteLength ( body )
|
|
136
217
|
} );
|
|
137
218
|
|
|
138
219
|
const data = await S3.send ( command );
|
|
220
|
+
|
|
221
|
+
if ( config?.s3?.logs === 'outputs' || config?.s3?.logs === 'verbose' )
|
|
222
|
+
log ( `S3 [SET]: ${bucket}/${key} - Stored.` );
|
|
139
223
|
|
|
140
224
|
return data;
|
|
141
225
|
}
|
|
142
226
|
catch ( error ) {
|
|
227
|
+
console.log ( error );
|
|
143
228
|
throw error;
|
|
144
229
|
}
|
|
145
230
|
};
|
|
@@ -148,11 +233,11 @@ exports.set = async ( key, body, options = {} ) => {
|
|
|
148
233
|
* Delete an object from S3.
|
|
149
234
|
*
|
|
150
235
|
* @param {string} key - The object key.
|
|
151
|
-
* @param {string} [bucket=config
|
|
236
|
+
* @param {string} [bucket=config?.s3?.Bucket] - The bucket name. Defaults to the configured bucket.
|
|
152
237
|
* @returns {Promise} A promise that resolves when the object is successfully deleted from S3.
|
|
153
238
|
* @description Deletes an object from S3 based on the provided key.
|
|
154
239
|
*/
|
|
155
|
-
exports.del = async ( key, bucket = config
|
|
240
|
+
exports.del = async ( key, bucket = config?.s3?.Bucket ) => {
|
|
156
241
|
try {
|
|
157
242
|
const command = new DeleteObjectCommand ( {
|
|
158
243
|
Bucket: bucket,
|
|
@@ -161,6 +246,9 @@ exports.del = async ( key, bucket = config.s3.Bucket ) => {
|
|
|
161
246
|
|
|
162
247
|
const data = await S3.send ( command );
|
|
163
248
|
|
|
249
|
+
if ( config?.s3?.logs === 'outputs' || config?.s3?.logs === 'verbose' )
|
|
250
|
+
log ( `S3 [DELETE]: ${key} on ${bucket} - Deleted.` );
|
|
251
|
+
|
|
164
252
|
return data;
|
|
165
253
|
}
|
|
166
254
|
catch ( error ) {
|
|
@@ -169,16 +257,16 @@ exports.del = async ( key, bucket = config.s3.Bucket ) => {
|
|
|
169
257
|
};
|
|
170
258
|
|
|
171
259
|
/**
|
|
172
|
-
*
|
|
260
|
+
* Copy an object within S3 to a different location. (This keep the original like a COPY / PASTE operation)
|
|
173
261
|
*
|
|
174
262
|
* @param {string} sourceKey - The source object key.
|
|
175
263
|
* @param {string} destinationKey - The destination object key.
|
|
176
|
-
* @param {string} [sourceBucket=config
|
|
177
|
-
* @param {string} [destinationBucket=config
|
|
264
|
+
* @param {string} [sourceBucket=config?.s3?.Bucket] - The source bucket name. Defaults to the configured bucket.
|
|
265
|
+
* @param {string} [destinationBucket=config?.s3?.Bucket] - The destination bucket name. Defaults to the configured bucket.
|
|
178
266
|
* @returns {Promise} A promise that resolves when the object is successfully moved in S3.
|
|
179
267
|
* @description Moves an object from the source location to the destination location within S3.
|
|
180
268
|
*/
|
|
181
|
-
exports.
|
|
269
|
+
exports.copy = async ( sourceKey, destinationKey, sourceBucket = config?.s3?.Bucket, destinationBucket = config?.s3?.Bucket ) => {
|
|
182
270
|
try {
|
|
183
271
|
// Copy the object to the destination location
|
|
184
272
|
const copyCommand = new CopyObjectCommand ( {
|
|
@@ -190,19 +278,48 @@ exports.move = async ( sourceKey, destinationKey, sourceBucket = config.s3.Bucke
|
|
|
190
278
|
} );
|
|
191
279
|
|
|
192
280
|
await S3.send ( copyCommand );
|
|
281
|
+
|
|
282
|
+
if ( config?.s3?.logs === 'outputs' || config?.s3?.logs === 'verbose' ){
|
|
283
|
+
if ( sourceBucket === destinationBucket ){
|
|
284
|
+
log ( `S3 [COPY]: ${sourceKey} moved to ${destinationKey} on ${sourceBucket}.` );
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
log ( `S3 [COPY]: ${sourceKey} on ${sourceBucket} moved to ${destinationKey} on ${destinationBucket}.` );
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
catch ( error ) {
|
|
292
|
+
throw error;
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Move an object within S3 to a different location. (This deletes the original like a CUT / PASTE operation)
|
|
298
|
+
*
|
|
299
|
+
* @param {string} sourceKey - The source object key.
|
|
300
|
+
* @param {string} destinationKey - The destination object key.
|
|
301
|
+
* @param {string} [sourceBucket=config?.s3?.Bucket] - The source bucket name. Defaults to the configured bucket.
|
|
302
|
+
* @param {string} [destinationBucket=config?.s3?.Bucket] - The destination bucket name. Defaults to the configured bucket.
|
|
303
|
+
* @returns {Promise} A promise that resolves when the object is successfully moved in S3.
|
|
304
|
+
* @description Moves an object from the source location to the destination location within S3.
|
|
305
|
+
*/
|
|
306
|
+
exports.move = async ( sourceKey, destinationKey, sourceBucket = config?.s3?.Bucket, destinationBucket = config?.s3?.Bucket ) => {
|
|
307
|
+
try {
|
|
308
|
+
|
|
309
|
+
// Copy the object to the destination location
|
|
310
|
+
await this.copy ( sourceKey, destinationKey, sourceBucket, destinationBucket );
|
|
193
311
|
|
|
194
312
|
// Delete the object from the source location
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
],
|
|
201
|
-
Quiet: true
|
|
313
|
+
await this.del ( sourceKey, sourceBucket );
|
|
314
|
+
|
|
315
|
+
if ( config?.s3?.logs === 'outputs' || config?.s3?.logs === 'verbose' ){
|
|
316
|
+
if ( sourceBucket === destinationBucket ){
|
|
317
|
+
log ( `S3 [MOVE]: ${sourceKey} moved to ${destinationKey} on ${sourceBucket}.` );
|
|
202
318
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
319
|
+
else {
|
|
320
|
+
log ( `S3 [MOVE]: ${sourceKey} on ${sourceBucket} moved to ${destinationKey} on ${destinationBucket}.` );
|
|
321
|
+
}
|
|
322
|
+
}
|
|
206
323
|
}
|
|
207
324
|
catch ( error ) {
|
|
208
325
|
throw error;
|
package/src/util/log.js
ADDED