eip-cloud-services 1.0.21 → 1.1.1

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 CHANGED
@@ -1,12 +1,37 @@
1
+
1
2
  # Changelog
2
3
 
3
4
  All notable changes to this project will be documented in this file.
4
5
 
5
- ## [1.0.21] - 2023-06-21
6
+ ## [1.1.0] - 2023-11-18
7
+
8
+ ### Changed
9
+ - **Redis Module Major Overhaul:**
10
+ - Transitioned from using the node redis package to the ioredis package.
11
+ - Updated the `getClient` method to support Redis clusters, including handling of client connections in subscriber mode.
12
+ - Implemented a dictionary of connected clients for efficient client management in Redis.
13
+ - Added new functionalities to the Redis module, including handling for various Redis commands and pub/sub features.
14
+ - Enriched the module with JSDoc comments for better clarity and documentation.
15
+ - Created a comprehensive README for the Redis module, detailing its features and usage.
6
16
 
7
17
  ### Added
8
- - New feature X.
9
- - Improved performance in Y.
18
+ - **AWS S3 Module Developments:**
19
+ - Reviewed and discussed functionalities of the AWS S3 module.
20
+ - Created a README file for the AWS S3 module, detailing usage and configuration.
21
+ - **CDN Module Improvements:**
22
+ - Analyzed functionalities of the CDN module.
23
+ - Generated a README for the CDN module, including instructions on usage and examples.
24
+ - **MySQL Module Update:**
25
+ - Discussed the MySQL module's features and capabilities.
26
+ - Compiled a README for the MySQL module, outlining key functionalities and configuration.
27
+ - **AWS Lambda Module Revision:**
28
+ - Explored the AWS Lambda module's functionalities.
29
+ - Prepared a README for the AWS Lambda module, providing usage examples and details.
30
+ - **Overall Module Documentation:**
31
+ - Combined individual READMEs into a single comprehensive README file.
32
+ - Added a summary, installation and import guide, and example configuration to the combined README.
33
+
34
+ ## [1.0.21] - 2023-06-21
10
35
 
11
36
  ### Fixed
12
37
  - Bug where ACL's were not copied across when moving S3 objects.
package/README.md ADDED
@@ -0,0 +1,386 @@
1
+ # EIP Cloud Services Module
2
+
3
+ ## Summary
4
+
5
+ The EIP Cloud Services Module is a comprehensive Node.js package that provides seamless integration with various cloud services, including Redis, AWS S3, CDN, AWS Lambda, and MySQL. This module is designed to simplify the complexities of interacting with these cloud services, offering a range of functionalities from data caching and storage to content delivery and serverless computing.
6
+
7
+ ## Installation and Import
8
+
9
+ To use this module, first install it in your Node.js project. Then, import the required services as follows:
10
+
11
+ ```javascript
12
+ const { redis, cdn, mysql } = require('eip-cloud-services');
13
+ ```
14
+
15
+ ## Config Example
16
+
17
+ Here is an example configuration for the EIP Cloud Services Module. Replace the placeholder values with your actual configuration details.
18
+
19
+ ```javascript
20
+ const packageJson = require('../package.json');
21
+
22
+ module.exports = {
23
+ cdn: {
24
+ ['cdnName']: { // e.g. "myCdn"
25
+ ['envName1']: { //e.g. "production"
26
+ type: 'google',
27
+ urlMapName: 'YOUR_GCP_URL_MAP_NAME',
28
+ projectId: 'YOUR_GCP_PROJECT_NAME',
29
+ },
30
+ ['envName2']: { // e.g. "staging"
31
+ type: 'amazon',
32
+ distributionId: 'YOUR_DISTRIBUTION_ID',
33
+ }
34
+ },
35
+ },
36
+ redis: { // For regular redis connections
37
+ port: 'YOUR_REDIS_PORT',
38
+ host: 'YOUR_REDIS_HOST',
39
+ prefix: 'YOUR_REDIS_PREFIX',
40
+ },
41
+ redis: { // For redis cluster instances
42
+ prefix: 'YOUR_REDIS_PREFIX',
43
+ clusterEnabled: true,
44
+ cluster: [
45
+ {
46
+ port: 'YOUR_REDIS_PORT',
47
+ host: 'YOUR_REDIS_HOST',
48
+ },
49
+ {
50
+ port: 'YOUR_REDIS_PORT_2',
51
+ host: 'YOUR_REDIS_HOST_2',
52
+ },
53
+ ...
54
+ ]
55
+ },
56
+ s3: {
57
+ Bucket: 'YOUR_S3_BUCKET',
58
+ logs: "verbose", // "verbose" or "outputs", any other value will not log. verbose will log all activity. outputs will only log when there is a file updated.
59
+ logsFunction: ( message ) => { ... } // Optional, if nothing is provided console.log will be used.
60
+ },
61
+ mysql: {
62
+ connectionLimit: 10, // Max connections
63
+ host: 'my-database.domain.com',
64
+ user: 'user',
65
+ password: 'password',
66
+ database: 'my-database', // defaults to undefined
67
+ multipleStatements: false // defaults to true if not set
68
+ }
69
+ };
70
+ ```
71
+
72
+ ## Table of Contents
73
+
74
+ 1. [Redis Module](#redis-module)
75
+ 2. [AWS S3 Module](#aws-s3-module)
76
+ 3. [CDN Module](#cdn-module)
77
+ 4. [MySQL Module](#mysql-module)
78
+ 5. [AWS Lambda Module](#aws-lambda-module)
79
+
80
+ # AWS Lambda Module
81
+
82
+ ## Overview
83
+
84
+ This module provides an interface for invoking AWS Lambda functions. It simplifies the process of triggering Lambda functions from your Node.js application, with support for both synchronous and asynchronous invocations.
85
+
86
+ ## Installation
87
+
88
+ Ensure this module is included in your Node.js project. Import the Lambda component as follows:
89
+
90
+ ```javascript
91
+ const lambda = require('eip-cloud-services/lambda');
92
+ ```
93
+
94
+ ## Usage
95
+
96
+ ### Invoking a Lambda Function
97
+
98
+ You can invoke a Lambda function by specifying the function name and the event payload. The module supports both waiting for the function execution to complete and fire-and-forget invocations.
99
+
100
+ #### Synchronous Invocation (Wait for Execution to start)
101
+
102
+ ```javascript
103
+ const response = await lambda.invokeLambda('yourFunctionName', { key: 'value' }, true);
104
+ console.log(response);
105
+ ```
106
+
107
+ #### Asynchronous Invocation (Fire-and-Forget)
108
+
109
+ ```javascript
110
+ await lambda.invokeLambda('yourFunctionName', { key: 'value' }, false);
111
+ ```
112
+
113
+ ### Parameters
114
+
115
+ - `functionName`: The name of the Lambda function to invoke.
116
+ - `eventPayload`: The payload to pass to the function. This can be any valid JSON object.
117
+ - `waitForExecution` (optional): Set to `true` to wait for the execution to start and receive a response.
118
+ - `context` (optional): The client context for the function execution.
119
+ - `invocationType` (optional): Defaults to 'Event'. Can be set to 'RequestResponse' for synchronous execution.
120
+ - `logType` (optional): The type of logging for the function.
121
+
122
+ ## Configuration
123
+
124
+ Configure the module with your AWS credentials and Lambda settings.
125
+
126
+ ## Error Handling
127
+
128
+ The module includes error handling to manage issues related to Lambda invocation, such as network errors or configuration problems.
129
+
130
+ ## Logging
131
+
132
+ Logging is provided to track the start and completion of Lambda invocations, aiding in debugging and monitoring.
133
+
134
+ # MySQL Module
135
+
136
+ ## Overview
137
+
138
+ This MySQL module provides a simple and efficient interface for interacting with MySQL databases. It includes functionalities to manage database connections, execute queries, and handle connection pooling.
139
+
140
+ ## Installation
141
+
142
+ Ensure this module is included in your Node.js project. Import the MySQL component as follows:
143
+
144
+ ```javascript
145
+ const mysql = require('eip-cloud-services/mysql');
146
+ ```
147
+
148
+ ## Usage
149
+
150
+ ### Executing Queries
151
+
152
+ You can execute queries using the `query` method. This method automatically handles connections and releases them after query execution.
153
+
154
+ ```javascript
155
+ const results = await mysql.query('SELECT * FROM your_table');
156
+ console.log(results);
157
+ ```
158
+
159
+ ### Manually Managing Database Connections
160
+
161
+ It's not required for you to get connections manually, you can use the methods directly without having to setup connections. Getting a connection should only be used if you need to parse the connection to a third party module for example.
162
+
163
+ #### Get a Connection Pool
164
+
165
+ ```javascript
166
+ const pool = mysql.getPool();
167
+ ```
168
+
169
+ #### Get a Single Connection
170
+
171
+ ```javascript
172
+ const connection = await mysql.getConnection();
173
+ ```
174
+
175
+
176
+ ### Closing the Connection Pool
177
+
178
+ To gracefully close all connections in the pool:
179
+
180
+ ```javascript
181
+ await mysql.kill();
182
+ ```
183
+
184
+ ## Configuration
185
+
186
+ Configure your MySQL connection settings (like host, user, password, etc.) in the `config` directory.
187
+
188
+ ## Error Handling
189
+
190
+ The module is designed to handle errors gracefully, providing clear error messages for database connection issues and query errors.
191
+
192
+ ## Pooling
193
+
194
+ - The module uses connection pooling for efficient database interaction.
195
+ - The pool is automatically created and managed by the module.
196
+
197
+
198
+ # CDN Module
199
+
200
+ ## Overview
201
+
202
+ This module provides functionalities to manage and interact with Content Delivery Networks (CDNs) like Amazon CloudFront and Google Cloud CDN. It includes features for creating invalidations, thereby ensuring that the latest content is served to end-users.
203
+
204
+ ## Installation
205
+
206
+ Ensure this module is included in your Node.js project. Import the CDN component as follows:
207
+
208
+ ```javascript
209
+ const cdn = require('eip-cloud-services/cdn');
210
+ ```
211
+
212
+ ## Usage
213
+
214
+ ### Create a CDN Invalidation
215
+
216
+ To invalidate cached content in a CDN, use the `createInvalidation` method. This method supports invalidating content in both Amazon CloudFront and Google Cloud CDN.
217
+
218
+ #### Invalidate in Amazon CloudFront
219
+
220
+ ```javascript
221
+ await cdn.createInvalidation('amazon', 'path/to/your/file.jpg', 'production');
222
+ ```
223
+
224
+ #### Invalidate in Google Cloud CDN
225
+
226
+ ```javascript
227
+ await cdn.createInvalidation('google', 'path/to/your/file.jpg', 'production');
228
+ ```
229
+
230
+ You can also invalidate multiple paths by passing an array of keys:
231
+
232
+ ```javascript
233
+ await cdn.createInvalidation('amazon', ['file1.jpg', 'file2.jpg'], 'staging');
234
+ ```
235
+
236
+ ## Configuration
237
+
238
+ Configure the module with your CDN settings in the `config` directory. The configuration should include details like project ID, distribution ID, and URL map names for the respective CDNs.
239
+
240
+ ## Error Handling
241
+
242
+ The module is equipped to handle errors gracefully, including validation of input parameters and handling CDN-specific errors.
243
+
244
+ ## Advanced Features
245
+
246
+ - Supports both Amazon CloudFront and Google Cloud CDN.
247
+ - Validates the key argument to ensure proper formatting.
248
+ - Constructs invalidation paths based on the provided keys.
249
+ - Initializes Google Auth if Google CDN is used.
250
+ - Sends invalidation commands to the CDN client based on the type of CDN and environment.
251
+
252
+
253
+ # AWS S3 Module
254
+
255
+ ## Overview
256
+
257
+ This module provides an interface for interacting with AWS S3, offering functionalities like object retrieval, storage, deletion, and more. It supports advanced features such as encryption and cache control directives, making it a versatile tool for managing S3 operations efficiently.
258
+
259
+ ## Installation
260
+
261
+ Ensure this module is included in your Node.js project. Import the S3 component as follows:
262
+
263
+ ```javascript
264
+ const s3 = require('eip-cloud-services/s3');
265
+ ```
266
+
267
+ ## Usage
268
+
269
+ ### Check if an Object Exists
270
+
271
+ ```javascript
272
+ const exists = await s3.exists('myObjectKey');
273
+ console.log(exists); // true if exists, false otherwise
274
+ ```
275
+
276
+ ### Retrieve an Object
277
+
278
+ ```javascript
279
+ const object = await s3.get('myObjectKey');
280
+ console.log(object);
281
+ ```
282
+
283
+ ### Store an Object
284
+
285
+ ```javascript
286
+ await s3.set('myObjectKey', 'myObjectData', { /* options */ });
287
+ ```
288
+
289
+ ### Delete an Object
290
+
291
+ ```javascript
292
+ await s3.del('myObjectKey');
293
+ ```
294
+
295
+ ### Copy an Object
296
+
297
+ ```javascript
298
+ await s3.copy('sourceObjectKey', 'destinationObjectKey');
299
+ ```
300
+
301
+ ### Move an Object
302
+
303
+ ```javascript
304
+ await s3.move('sourceObjectKey', 'destinationObjectKey');
305
+ ```
306
+
307
+ ### Managing Cache-Control and Encryption
308
+
309
+ The module provides detailed control over cache behavior and supports encryption for stored objects, allowing you to optimize performance and security.
310
+
311
+ ## Configuration
312
+
313
+ Configure the module with your AWS credentials and preferred settings in the `config` directory.
314
+
315
+ ## Error Handling
316
+
317
+ The module includes comprehensive error handling, ensuring robust interaction with AWS S3 even in complex scenarios.
318
+
319
+
320
+
321
+ # Redis Module
322
+
323
+ ## Overview
324
+
325
+ This Redis module provides a robust interface for interacting with Redis, supporting both standard Redis operations and advanced features like Redis Clusters. The module is designed to manage multiple Redis client instances efficiently, allowing seamless operation with different Redis configurations.
326
+
327
+ ## Installation
328
+
329
+ To use this Redis module, first ensure that it is included in your Node.js project. You can import the module as follows:
330
+
331
+ ```javascript
332
+ const redis = require('eip-cloud-services/redis');
333
+ ```
334
+
335
+ ## Usage
336
+
337
+ ### Standard Redis Operations
338
+
339
+ You can perform standard Redis operations like setting, getting, deleting keys, etc. Here are some examples:
340
+
341
+ #### Set a Key
342
+
343
+ ```javascript
344
+ await redis.set('myKey', 'myValue');
345
+ ```
346
+
347
+ #### Get a Key
348
+
349
+ ```javascript
350
+ const value = await redis.get('myKey');
351
+ console.log(value); // Outputs: myValue
352
+ ```
353
+
354
+ #### Delete a Key
355
+
356
+ ```javascript
357
+ await redis.del('myKey');
358
+ ```
359
+
360
+ ### Advanced Operations
361
+
362
+ #### Using Redis Cluster
363
+
364
+ If your Redis setup includes a cluster, the module automatically configures the client for cluster operations based on your configuration.
365
+
366
+ #### Subscribing to a Channel
367
+
368
+ ```javascript
369
+ redis.subscribe('myChannel', (message) => {
370
+ console.log(`Received: ${message}`);
371
+ });
372
+ ```
373
+
374
+ #### Publishing to a Channel
375
+
376
+ ```javascript
377
+ await redis.publish('myChannel', 'Hello, World!');
378
+ ```
379
+
380
+ ### Managing Redis Clients
381
+
382
+ The module internally manages multiple Redis clients for different purposes (like separate clients for pub/sub). However, this is abstracted away from the standard use of the module.
383
+
384
+ ## Error Handling
385
+
386
+ The module is designed to gracefully handle Redis errors, including connection issues and cluster errors.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eip-cloud-services",
3
- "version": "1.0.21",
3
+ "version": "1.1.1",
4
4
  "description": "Houses a collection of helpers for connecting with Cloud services.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -19,6 +19,7 @@
19
19
  "@aws-sdk/client-secrets-manager": "^3.354.0",
20
20
  "config": "^3.3.9",
21
21
  "google-auth-library": "^8.8.0",
22
+ "ioredis": "^5.3.2",
22
23
  "mysql": "^2.18.1",
23
24
  "redis": "^4.6.7"
24
25
  }
package/src/cdn.js CHANGED
@@ -1,8 +1,15 @@
1
1
  const { CloudFrontClient, CreateInvalidationCommand } = require ( '@aws-sdk/client-cloudfront' );
2
2
  const { GoogleAuth } = require ( 'google-auth-library' );
3
3
  const { initialiseGoogleAuth } = require ( './gcp' );
4
- const config = require ( 'config' );
4
+ const fs = require ( 'fs' );
5
+ let config = {};
6
+ const configDirPath = `${ process.cwd ()}/config`;
7
+ if ( fs.existsSync ( configDirPath ) && fs.statSync ( configDirPath ).isDirectory () ) {
8
+ config = require ( 'config' ); // require the config directory if it exists
9
+ }
5
10
  const packageJson = require ( '../package.json' );
11
+ const { cwd } = require ( 'process' );
12
+ const { log } = config?.s3?.logsFunction ? require ( `${ cwd ()}/${config.s3.logsFunction}` ) : console;
6
13
 
7
14
  /**
8
15
  * Create a CDN invalidation for the specified key(s) and environment.
@@ -37,6 +44,9 @@ exports.createInvalidation = async ( cdn, key, environment = 'production' ) => {
37
44
  throw new Error ( 'Invalid key argument. Expected a string or an array of strings.' );
38
45
  }
39
46
 
47
+ if ( config.cdn.log )
48
+ log ( `CDN [INVALIDATE]: ${paths.map ( path => `https://${cdn}${environment !== 'production' ? '-test' : ''}.eip.telegraph.co.uk/${path}` ).join ( ', ' )}\n` );
49
+
40
50
  switch ( cdnSettings.type ) {
41
51
  case 'google':
42
52
  await invalidateGoogleCDN ( cdnSettings, paths );
package/src/lambda.js CHANGED
@@ -1,5 +1,4 @@
1
1
  const { LambdaClient, InvokeCommand } = require ( '@aws-sdk/client-lambda' );
2
- const config = require ( 'config' );
3
2
  const packageJson = require ( '../package.json' );
4
3
 
5
4
  /**
package/src/mysql.js CHANGED
@@ -1,5 +1,10 @@
1
1
  const mysql = require ( 'mysql' );
2
- const config = require ( 'config' );
2
+ const fs = require ( 'fs' );
3
+ let config = {};
4
+ const configDirPath = `${ process.cwd ()}/config`;
5
+ if ( fs.existsSync ( configDirPath ) && fs.statSync ( configDirPath ).isDirectory () ) {
6
+ config = require ( 'config' ); // require the config directory if it exists
7
+ }
3
8
 
4
9
  let pool = null;
5
10
 
@@ -10,8 +15,8 @@ function getPool () {
10
15
  host: config.mysql.host,
11
16
  user: config.mysql.user,
12
17
  password: config.mysql.password,
13
- database: config.mysql.database,
14
- multipleStatements: true
18
+ database: config.mysql.database || undefined,
19
+ multipleStatements: config.mysql.multipleStatements || true
15
20
  } );
16
21
  }
17
22
 
@@ -32,7 +37,8 @@ const newQuery = ( connection, query ) => new Promise ( ( resolve, reject ) => {
32
37
  } );
33
38
  } );
34
39
 
35
- const getConnection = () => new Promise ( ( resolve, reject ) => {
40
+ exports.getPool = getPool;
41
+ exports.getConnection = () => new Promise ( ( resolve, reject ) => {
36
42
  getPool ().getConnection ( ( error, connection ) => {
37
43
  if ( error ) {
38
44
  console.log ( error );
@@ -49,7 +55,7 @@ exports.query = queryString => new Promise ( ( resolve, reject ) => {
49
55
  if ( !queryString.endsWith ( ';' ) ){
50
56
  queryString += ';';
51
57
  }
52
- getConnection ().then ( connection => newQuery ( connection, queryString ) ).then ( resolve ).catch ( reject );
58
+ this.getConnection ().then ( connection => newQuery ( connection, queryString ) ).then ( resolve ).catch ( reject );
53
59
  } );
54
60
 
55
61
  exports.kill = () => new Promise ( resolve => {