eip-cloud-services 1.3.0 → 1.4.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/README.md +3 -5
- package/package.json +1 -1
- package/src/cdn.js +37 -90
package/README.md
CHANGED
|
@@ -273,7 +273,7 @@ The module is designed to handle errors gracefully, providing clear error messag
|
|
|
273
273
|
|
|
274
274
|
## Overview
|
|
275
275
|
|
|
276
|
-
This module provides
|
|
276
|
+
This module provides a shared client for CDN invalidation requests. CDN invalidation requests are sent through the shared Tools API invalidate endpoint, so callers use one centralized route while the backend implementation remains independently updateable inside the invalidation service.
|
|
277
277
|
|
|
278
278
|
## Installation
|
|
279
279
|
|
|
@@ -287,7 +287,7 @@ const cdn = require('eip-cloud-services/cdn');
|
|
|
287
287
|
|
|
288
288
|
### Create a CDN Invalidation
|
|
289
289
|
|
|
290
|
-
To invalidate cached content in a CDN, use the `createInvalidation` method. This
|
|
290
|
+
To invalidate cached content in a CDN, use the `createInvalidation` method. This sends the request to the shared Tools API invalidate endpoint, which executes the configured provider-specific invalidation in `eip-cdn-invalidator`.
|
|
291
291
|
|
|
292
292
|
#### Invalidate in Amazon CloudFront
|
|
293
293
|
|
|
@@ -317,11 +317,9 @@ The module is equipped to handle errors gracefully, including validation of inpu
|
|
|
317
317
|
|
|
318
318
|
## Advanced Features
|
|
319
319
|
|
|
320
|
-
- Supports both Amazon CloudFront and Google Cloud CDN.
|
|
321
320
|
- Validates the key argument to ensure proper formatting.
|
|
322
321
|
- Constructs invalidation paths based on the provided keys.
|
|
323
|
-
-
|
|
324
|
-
- Sends invalidation commands to the CDN client based on the type of CDN and environment.
|
|
322
|
+
- Centralizes invalidation routing through the shared Tools API endpoint.
|
|
325
323
|
|
|
326
324
|
|
|
327
325
|
# AWS S3 Module
|
package/package.json
CHANGED
package/src/cdn.js
CHANGED
|
@@ -1,114 +1,61 @@
|
|
|
1
|
-
const { CloudFrontClient, CreateInvalidationCommand } = require ( '@aws-sdk/client-cloudfront' );
|
|
2
|
-
const { GoogleAuth } = require ( 'google-auth-library' );
|
|
3
|
-
const { initialiseGoogleAuth } = require ( './gcp' );
|
|
4
1
|
const fs = require ( 'fs' );
|
|
5
2
|
let config = {};
|
|
6
3
|
const configDirPath = `${ process.cwd ()}/config`;
|
|
7
4
|
if ( fs.existsSync ( configDirPath ) && fs.statSync ( configDirPath ).isDirectory () ) {
|
|
8
5
|
config = require ( 'config' ); // require the config directory if it exists
|
|
9
6
|
}
|
|
10
|
-
const packageJson = require ( '../package.json' );
|
|
11
7
|
const { cwd } = require ( 'process' );
|
|
12
8
|
const { log } = config?.s3?.logsFunction ? require ( `${ cwd ()}/${config.s3.logsFunction}` ) : console;
|
|
13
9
|
|
|
14
|
-
const
|
|
10
|
+
const INVALIDATION_ENDPOINT = process.env.EIP_CDN_INVALIDATE_ENDPOINT || config?.cdn?.invalidateEndpoint || 'https://tools.eip.telegraph.co.uk/v1/invalidate';
|
|
11
|
+
const shouldLog = Boolean ( config?.cdn?.log || config?.cdn?.logs );
|
|
15
12
|
|
|
16
|
-
/**
|
|
17
|
-
* Create a CDN invalidation for the specified key(s) and environment.
|
|
18
|
-
*
|
|
19
|
-
* @param {string} cdn - The CDN provider to be used (e.g., 'google', 'amazon').
|
|
20
|
-
* @param {string|string[]} key - The key(s) representing the file(s) to invalidate.
|
|
21
|
-
* @param {string} environment - The environment (e.g., 'staging', 'production').
|
|
22
|
-
* @returns {Promise<void>} A promise that resolves when the invalidation is created.
|
|
23
|
-
* @description Creates a CDN invalidation for the specified key(s) in the specified environment.
|
|
24
|
-
* - The `cdn` parameter specifies the CDN provider (e.g., 'google', 'amazon').
|
|
25
|
-
* - The `key` parameter can be a single string or an array of strings representing the file(s) to invalidate.
|
|
26
|
-
* - The `environment` parameter specifies the environment (e.g., 'staging', 'production').
|
|
27
|
-
* - The function validates the `key` argument and throws an error if it is not a string or an array of strings.
|
|
28
|
-
* - The function constructs the invalidation paths based on the provided keys.
|
|
29
|
-
* - The CDN client (either Google or Amazon CloudFront) is used to send the invalidation command.
|
|
30
|
-
* - Returns a promise that resolves when the invalidation is created.
|
|
31
|
-
* - The function initializes Google Auth if Google CDN is used.
|
|
32
|
-
* - If Google CDN is used, the function makes a POST request to Google's 'invalidateCache' endpoint for each provided path.
|
|
33
|
-
* - If Amazon CloudFront is used, the function sends an invalidation command to CloudFront.
|
|
34
|
-
* - If the CDN type is not 'google' or 'amazon', the function throws an error.
|
|
35
|
-
* - The function uses the 'config' module to access the CDN settings based on the CDN provider and environment.
|
|
36
|
-
*/
|
|
37
13
|
exports.createInvalidation = async ( cdn, key, environment = 'production' ) => {
|
|
38
|
-
const
|
|
14
|
+
const invalidation = normalizeInvalidation ( cdn, key, environment );
|
|
39
15
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.filter ( item => typeof item === 'string' )
|
|
43
|
-
.map ( item => item.charAt ( 0 ) !== '/' ? '/' + item : item );
|
|
44
|
-
|
|
45
|
-
if ( paths.length === 0 ) {
|
|
46
|
-
throw new Error ( 'Invalid key argument. Expected a string or an array of strings.' );
|
|
16
|
+
if ( shouldLog ) {
|
|
17
|
+
log ( `CDN [INVALIDATE][REQUEST]: ${invalidation.cdn} (${invalidation.environment}) ${invalidation.paths.join ( ', ' )}\n` );
|
|
47
18
|
}
|
|
48
19
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
20
|
+
const response = await fetch ( INVALIDATION_ENDPOINT, {
|
|
21
|
+
method: 'POST',
|
|
22
|
+
headers: {
|
|
23
|
+
'Content-Type': 'application/json'
|
|
24
|
+
},
|
|
25
|
+
body: JSON.stringify ( {
|
|
26
|
+
cdn: invalidation.cdn,
|
|
27
|
+
key: invalidation.key,
|
|
28
|
+
environment: invalidation.environment
|
|
29
|
+
} )
|
|
30
|
+
} );
|
|
52
31
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
log ( `CDN [INVALIDATE]: Invalidation already in progress - skipping: ${paths.map ( path => `https://${cdn}${environment !== 'production' ? '-test' : ''}.eip.telegraph.co.uk${path}` ).join ( ', ' )}\n` );
|
|
56
|
-
await redis.increment(redisKey);
|
|
32
|
+
if ( !response.ok ) {
|
|
33
|
+
const responseText = await response.text ();
|
|
57
34
|
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
else{
|
|
61
|
-
await redis.set(redisKey, 1, cdnSettings.type === 'google' ? 300 : 120); // 5 minutes for google, 2 minutes for amazon
|
|
62
|
-
}
|
|
35
|
+
throw new Error ( `CDN invalidation request failed (${response.status}): ${responseText}` );
|
|
63
36
|
}
|
|
37
|
+
};
|
|
64
38
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
switch ( cdnSettings.type ) {
|
|
69
|
-
case 'google':
|
|
70
|
-
await invalidateGoogleCDN ( cdnSettings, paths );
|
|
71
|
-
break;
|
|
72
|
-
|
|
73
|
-
case 'amazon':
|
|
74
|
-
await invalidateAmazonCDN ( cdnSettings, paths );
|
|
75
|
-
break;
|
|
39
|
+
function normalizeInvalidation ( cdn, key, environment ) {
|
|
40
|
+
const cdnSettings = config?.cdn?.[ cdn ]?.[ environment ];
|
|
76
41
|
|
|
77
|
-
|
|
78
|
-
|
|
42
|
+
if ( !cdnSettings ) {
|
|
43
|
+
throw new Error ( `Missing CDN configuration for ${cdn} (${environment})` );
|
|
79
44
|
}
|
|
80
|
-
};
|
|
81
45
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const auth = new GoogleAuth ( {
|
|
86
|
-
scopes: 'https://www.googleapis.com/auth/cloud-platform'
|
|
87
|
-
} );
|
|
46
|
+
const paths = ( Array.isArray ( key ) ? key : [ key ] )
|
|
47
|
+
.filter ( item => typeof item === 'string' )
|
|
48
|
+
.map ( item => item.charAt ( 0 ) !== '/' ? '/' + item : item );
|
|
88
49
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
50
|
+
if ( paths.length === 0 ) {
|
|
51
|
+
throw new Error ( 'Invalid key argument. Expected a string or an array of strings.' );
|
|
52
|
+
}
|
|
92
53
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
54
|
+
return {
|
|
55
|
+
cdn,
|
|
56
|
+
key,
|
|
57
|
+
environment,
|
|
58
|
+
paths,
|
|
59
|
+
cdnSettings
|
|
60
|
+
};
|
|
98
61
|
}
|
|
99
|
-
|
|
100
|
-
async function invalidateAmazonCDN ( cdnSettings, paths ) {
|
|
101
|
-
const client = new CloudFrontClient ();
|
|
102
|
-
const command = new CreateInvalidationCommand ( {
|
|
103
|
-
DistributionId: cdnSettings.distributionId,
|
|
104
|
-
InvalidationBatch: {
|
|
105
|
-
CallerReference: `${packageJson.name}-${Date.now ()}`,
|
|
106
|
-
Paths: {
|
|
107
|
-
Quantity: paths.length,
|
|
108
|
-
Items: paths,
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
} );
|
|
112
|
-
|
|
113
|
-
await client.send ( command );
|
|
114
|
-
}
|