@adobe/spacecat-shared-utils 1.94.0 → 1.96.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 +14 -0
- package/package.json +1 -1
- package/src/index.d.ts +14 -0
- package/src/index.js +1 -0
- package/src/llmo-config.js +64 -0
- package/src/url-helpers.js +34 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [@adobe/spacecat-shared-utils-v1.96.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.95.0...@adobe/spacecat-shared-utils-v1.96.0) (2026-02-12)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* get llmo config v2 ([#1340](https://github.com/adobe/spacecat-shared/issues/1340)) ([6fcbd51](https://github.com/adobe/spacecat-shared/commit/6fcbd51864daca13736d3813097c485e2189cd68))
|
|
7
|
+
|
|
8
|
+
# [@adobe/spacecat-shared-utils-v1.95.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.94.0...@adobe/spacecat-shared-utils-v1.95.0) (2026-02-12)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add canonicalizeUrl utility for consistent URL comparison ([#1334](https://github.com/adobe/spacecat-shared/issues/1334)) ([eb15132](https://github.com/adobe/spacecat-shared/commit/eb1513228e5d2e1701211b6aaf36108bd1642d68))
|
|
14
|
+
|
|
1
15
|
# [@adobe/spacecat-shared-utils-v1.94.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.93.0...@adobe/spacecat-shared-utils-v1.94.0) (2026-02-11)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -133,6 +133,20 @@ export declare function stripTrailingSlash(url: string): string;
|
|
|
133
133
|
*/
|
|
134
134
|
export declare function stripWWW(url: string): string;
|
|
135
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Canonicalizes a URL by removing protocol, www prefix, and trailing slash
|
|
138
|
+
* for comparison and matching purposes.
|
|
139
|
+
* Optionally strips query parameters and fragments.
|
|
140
|
+
* @param url - URL to canonicalize
|
|
141
|
+
* @param options - Canonicalization options
|
|
142
|
+
* @param options.stripQuery - Whether to strip query parameters and fragments
|
|
143
|
+
* @returns Canonicalized URL
|
|
144
|
+
*/
|
|
145
|
+
export declare function canonicalizeUrl(
|
|
146
|
+
url: string,
|
|
147
|
+
options?: { stripQuery?: boolean }
|
|
148
|
+
): string;
|
|
149
|
+
|
|
136
150
|
/**
|
|
137
151
|
* Composes a base URL by applying a series of transformations to the given domain.
|
|
138
152
|
* @param domain - The domain to compose the base URL from.
|
package/src/index.js
CHANGED
package/src/llmo-config.js
CHANGED
|
@@ -125,3 +125,67 @@ export async function writeConfig(siteId, config, s3Client, options) {
|
|
|
125
125
|
}
|
|
126
126
|
return { version: res.VersionId };
|
|
127
127
|
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Gets the S3 path for a V2 customer configuration.
|
|
131
|
+
* @param {string} organizationId The SpaceCat organization ID.
|
|
132
|
+
* @returns {string} The S3 key path for the V2 customer config.
|
|
133
|
+
*/
|
|
134
|
+
export function customerConfigV2Path(organizationId) {
|
|
135
|
+
return `customer-config-v2/${organizationId}/config.json`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Reads the V2 customer configuration for an organization from S3.
|
|
140
|
+
* @param {string} organizationId The SpaceCat organization ID.
|
|
141
|
+
* @param {S3Client} s3Client The S3 client to use for reading the configuration.
|
|
142
|
+
* @param {object} [options]
|
|
143
|
+
* @param {string} [options.s3Bucket] Optional S3 bucket name.
|
|
144
|
+
* @returns {Promise<object|null>} The configuration object or null if not found.
|
|
145
|
+
* @throws {Error} If reading the configuration fails for reasons other than it not existing.
|
|
146
|
+
*/
|
|
147
|
+
export async function readCustomerConfigV2(organizationId, s3Client, options) {
|
|
148
|
+
const s3Bucket = options?.s3Bucket || process.env.S3_BUCKET_NAME;
|
|
149
|
+
|
|
150
|
+
const getObjectCommand = new GetObjectCommand({
|
|
151
|
+
Bucket: s3Bucket,
|
|
152
|
+
Key: customerConfigV2Path(organizationId),
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const res = await s3Client.send(getObjectCommand);
|
|
157
|
+
const body = res.Body;
|
|
158
|
+
if (!body) {
|
|
159
|
+
throw new Error('Customer config V2 body is empty');
|
|
160
|
+
}
|
|
161
|
+
const text = await body.transformToString();
|
|
162
|
+
return JSON.parse(text);
|
|
163
|
+
} catch (e) {
|
|
164
|
+
if (e.name === 'NoSuchKey' || e.name === 'NotFound') {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
throw e;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Writes the V2 customer configuration for an organization to S3.
|
|
173
|
+
* @param {string} organizationId The SpaceCat organization ID.
|
|
174
|
+
* @param {object} config The customer configuration object to write.
|
|
175
|
+
* @param {S3Client} s3Client The S3 client to use for writing the configuration.
|
|
176
|
+
* @param {object} [options]
|
|
177
|
+
* @param {string} [options.s3Bucket] Optional S3 bucket name.
|
|
178
|
+
* @returns {Promise<void>}
|
|
179
|
+
*/
|
|
180
|
+
export async function writeCustomerConfigV2(organizationId, config, s3Client, options) {
|
|
181
|
+
const s3Bucket = options?.s3Bucket || process.env.S3_BUCKET_NAME;
|
|
182
|
+
|
|
183
|
+
const putObjectCommand = new PutObjectCommand({
|
|
184
|
+
Bucket: s3Bucket,
|
|
185
|
+
Key: customerConfigV2Path(organizationId),
|
|
186
|
+
Body: JSON.stringify(config, null, 2),
|
|
187
|
+
ContentType: 'application/json',
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
await s3Client.send(putObjectCommand);
|
|
191
|
+
}
|
package/src/url-helpers.js
CHANGED
|
@@ -318,6 +318,40 @@ async function wwwUrlResolver(site, rumApiClient, log) {
|
|
|
318
318
|
return fallback;
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
+
/**
|
|
322
|
+
* Canonicalizes a URL by removing protocol, www prefix, and trailing slash
|
|
323
|
+
* for comparison and matching purposes.
|
|
324
|
+
* Optionally strips query parameters and fragments.
|
|
325
|
+
* @param {string} url - URL to canonicalize
|
|
326
|
+
* @param {object} options - Canonicalization options
|
|
327
|
+
* @param {boolean} options.stripQuery - Whether to strip query parameters and fragments
|
|
328
|
+
* @returns {string} Canonicalized URL
|
|
329
|
+
*/
|
|
330
|
+
export function canonicalizeUrl(url, { stripQuery = false } = {}) {
|
|
331
|
+
if (!url || typeof url !== 'string') {
|
|
332
|
+
return '';
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
let canonicalized = url
|
|
336
|
+
.toLowerCase() // Case insensitive
|
|
337
|
+
.trim()
|
|
338
|
+
.replace(/^https?:\/\//, '') // Remove protocol
|
|
339
|
+
.replace(/^www\d*\./, '') // Remove www, www2, www3, etc.
|
|
340
|
+
.replace(/\/$/, ''); // Remove trailing slash
|
|
341
|
+
|
|
342
|
+
// Optionally strip query parameters and fragments
|
|
343
|
+
if (stripQuery) {
|
|
344
|
+
const queryIndex = canonicalized.search(/[?#]/);
|
|
345
|
+
if (queryIndex !== -1) {
|
|
346
|
+
canonicalized = canonicalized.substring(0, queryIndex);
|
|
347
|
+
}
|
|
348
|
+
// Remove any trailing slash that may have been revealed
|
|
349
|
+
canonicalized = canonicalized.replace(/\/$/, '');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return canonicalized;
|
|
353
|
+
}
|
|
354
|
+
|
|
321
355
|
export {
|
|
322
356
|
ensureHttps,
|
|
323
357
|
getSpacecatRequestHeaders,
|