@adobe/spacecat-shared-utils 1.19.3 → 1.19.5

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,3 +1,17 @@
1
+ # [@adobe/spacecat-shared-utils-v1.19.5](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.19.4...@adobe/spacecat-shared-utils-v1.19.5) (2024-08-20)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * move metrics-store and s3 in shared utils ([#327](https://github.com/adobe/spacecat-shared/issues/327)) ([bff367c](https://github.com/adobe/spacecat-shared/commit/bff367cf05f9b7d802a7b8c24bc81abbf0e2665c))
7
+
8
+ # [@adobe/spacecat-shared-utils-v1.19.4](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.19.3...@adobe/spacecat-shared-utils-v1.19.4) (2024-08-19)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **deps:** update external fixes ([#332](https://github.com/adobe/spacecat-shared/issues/332)) ([b2bb2a4](https://github.com/adobe/spacecat-shared/commit/b2bb2a4dd1a0995c36cd2b64510b7c4e0e05436f))
14
+
1
15
  # [@adobe/spacecat-shared-utils-v1.19.3](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.19.2...@adobe/spacecat-shared-utils-v1.19.3) (2024-08-14)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-utils",
3
- "version": "1.19.3",
3
+ "version": "1.19.5",
4
4
  "description": "Shared modules of the Spacecat Services - utils",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -32,17 +32,17 @@
32
32
  "devDependencies": {
33
33
  "@adobe/helix-shared-wrap": "2.0.2",
34
34
  "@adobe/spacecat-shared-data-access": "file:../spacecat-shared-data-access",
35
- "chai": "4.5.0",
35
+ "chai": "5.1.1",
36
36
  "chai-as-promised": "8.0.0",
37
37
  "husky": "9.1.4",
38
38
  "nock": "13.5.4",
39
39
  "sinon": "18.0.0",
40
- "sinon-chai": "3.7.0"
40
+ "sinon-chai": "4.0.0"
41
41
  },
42
42
  "dependencies": {
43
43
  "@adobe/fetch": "4.1.8",
44
- "@aws-sdk/client-s3": "3.627.0",
45
- "@aws-sdk/client-sqs": "3.624.0",
44
+ "@aws-sdk/client-s3": "3.633.0",
45
+ "@aws-sdk/client-sqs": "3.632.0",
46
46
  "@json2csv/plainjs": "7.0.6"
47
47
  }
48
48
  }
package/src/functions.js CHANGED
@@ -180,7 +180,7 @@ function isValidUrl(urlString) {
180
180
  try {
181
181
  const url = new URL(urlString);
182
182
  return url.protocol === 'http:' || url.protocol === 'https:';
183
- } catch (e) {
183
+ } catch {
184
184
  return false;
185
185
  }
186
186
  }
package/src/helpers.js CHANGED
@@ -47,7 +47,7 @@ export function resolveCustomerSecretsName(baseURL, ctx) {
47
47
  let customer;
48
48
  try {
49
49
  customer = new URL(baseURL).host.replace(/[^a-zA-Z0-9]/g, '_').toLowerCase();
50
- } catch (e) {
50
+ } catch {
51
51
  throw new Error('Invalid baseURL: must be a valid URL');
52
52
  }
53
53
  return resolveSecretsName({}, ctx, `${basePath}/${customer}`);
package/src/index.d.ts CHANGED
@@ -124,3 +124,38 @@ declare function resolveCustomerSecretsName(baseURL: string, ctx: object): strin
124
124
  * @returns {Buffer} A Buffer containing the CSV formatted data, encoded in UTF-8.
125
125
  */
126
126
  declare function generateCSVFile(data: object[]): Buffer;
127
+
128
+ /**
129
+ * Retrieves stored metrics from S3.
130
+ * @param config - Configuration object
131
+ * @param config.siteId - The site ID.
132
+ * @param config.source - The source of the metrics.
133
+ * @param config.metric - The metric name.
134
+ * @param context - Context object
135
+ * @param context.log - Logger
136
+ * @param context.s3 - S3 configuration
137
+ * @param context.s3.s3Client - S3 client
138
+ * @param context.s3.s3Bucket - S3 bucket name
139
+ * @returns {Promise<any|*[]>} - The stored metrics
140
+ */
141
+ export function getStoredMetrics(config: object, context: object):
142
+ Promise<Array<object>>;
143
+
144
+ /**
145
+ * Stores metrics in S3.
146
+ * @param content - The metrics to store
147
+ * @param config - Configuration object
148
+ * @param config.siteId - The site ID
149
+ * @param config.source - The source of the metrics
150
+ * @param config.metric - The metric name
151
+ * @param context - Context object
152
+ * @param context.log - Logger
153
+ * @param context.s3 - S3 configuration
154
+ * @param context.s3.s3Client - S3 client
155
+ * @param context.s3.s3Bucket - S3 bucket name
156
+ * @returns {Promise<string>} - The path where the metrics are stored
157
+ */
158
+ export function storeMetrics(content: object, config: object, context: object): Promise<string>;
159
+
160
+ export function s3Wrapper(fn: (request: object, context: object) => Promise<Response>):
161
+ (request: object, context: object) => Promise<Response>;
package/src/index.js CHANGED
@@ -47,3 +47,7 @@ export {
47
47
  stripTrailingSlash,
48
48
  stripWWW,
49
49
  } from './url-helpers.js';
50
+
51
+ export { getStoredMetrics, storeMetrics } from './metrics-store.js';
52
+
53
+ export { s3Wrapper } from './s3.js';
@@ -0,0 +1,82 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import { GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
13
+
14
+ function createFilePath({ siteId, source, metric }) {
15
+ if (!siteId) {
16
+ throw new Error('siteId is required to compose metrics storage path');
17
+ }
18
+
19
+ if (!source) {
20
+ throw new Error('source is required to compose metrics storage path');
21
+ }
22
+
23
+ if (!metric) {
24
+ throw new Error('metric is required to compose metrics storage path');
25
+ }
26
+
27
+ return `metrics/${siteId}/${source}/${metric}.json`;
28
+ }
29
+
30
+ export async function getStoredMetrics(config, context) {
31
+ const { log, s3 } = context;
32
+
33
+ if (!s3.s3Bucket) {
34
+ throw new Error('S3 bucket name is required to get stored metrics');
35
+ }
36
+
37
+ const filePath = createFilePath(config);
38
+
39
+ const command = new GetObjectCommand({
40
+ Bucket: s3.s3Bucket,
41
+ Key: filePath,
42
+ });
43
+
44
+ try {
45
+ const response = await s3.s3Client.send(command);
46
+ const content = await response.Body?.transformToString();
47
+ const metrics = JSON.parse(content);
48
+ log.info(`Successfully retrieved ${metrics.length} metrics from ${filePath}`);
49
+
50
+ return metrics;
51
+ } catch (e) {
52
+ log.error(`Failed to retrieve metrics from ${filePath}, error: ${e.message}`);
53
+ return [];
54
+ }
55
+ }
56
+
57
+ export async function storeMetrics(content, config, context) {
58
+ const { log, s3 } = context;
59
+
60
+ if (!s3.s3Bucket) {
61
+ throw new Error('S3 bucket name is required to store metrics');
62
+ }
63
+
64
+ const filePath = createFilePath(config);
65
+
66
+ const command = new PutObjectCommand({
67
+ Bucket: s3.s3Bucket,
68
+ Key: filePath,
69
+ Body: JSON.stringify(content, null, 2),
70
+ ContentType: 'application/json',
71
+ });
72
+
73
+ try {
74
+ const response = await s3.s3Client.send(command);
75
+ log.info(`Successfully uploaded metrics to ${filePath}, response: ${JSON.stringify(response)}`);
76
+
77
+ return filePath;
78
+ } catch (e) {
79
+ log.error(`Failed to upload metrics to ${filePath}, error: ${e.message}`);
80
+ throw new Error(`Failed to upload metrics to ${filePath}, error: ${e.message}`);
81
+ }
82
+ }
package/src/s3.js CHANGED
@@ -12,17 +12,26 @@
12
12
 
13
13
  import { S3Client } from '@aws-sdk/client-s3';
14
14
 
15
- export function s3Bucket(fn) {
16
- return async (req, context) => {
15
+ /**
16
+ * Adds an S3Client instance and bucket to the context.
17
+ *
18
+ * @param {UniversalAction} fn
19
+ * @returns {function(object, UniversalContext): Promise<Response>}
20
+ */
21
+ export function s3Wrapper(fn) {
22
+ return async (request, context) => {
17
23
  if (!context.s3) {
24
+ context.s3 = {};
25
+
18
26
  const {
19
27
  AWS_REGION: region,
20
28
  S3_BUCKET_NAME: bucket,
21
29
  } = context.env;
22
30
 
23
- context.s3 = new S3Client({ region });
24
- context.s3Bucket = bucket;
31
+ context.s3.s3Client = new S3Client({ region });
32
+ context.s3.s3Bucket = bucket;
25
33
  }
26
- return fn(req, context);
34
+
35
+ return fn(request, context);
27
36
  };
28
37
  }