@adobe/spacecat-shared-content-client 1.3.40 → 1.4.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,3 +1,17 @@
1
+ # [@adobe/spacecat-shared-content-client-v1.4.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-content-client-v1.4.0...@adobe/spacecat-shared-content-client-v1.4.1) (2025-03-04)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **deps:** update adobe fixes ([#648](https://github.com/adobe/spacecat-shared/issues/648)) ([6bdd02c](https://github.com/adobe/spacecat-shared/commit/6bdd02ccaaaf89d4b3d463206ec1377c1ccecf4d))
7
+
8
+ # [@adobe/spacecat-shared-content-client-v1.4.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-content-client-v1.3.40...@adobe/spacecat-shared-content-client-v1.4.0) (2025-03-04)
9
+
10
+
11
+ ### Features
12
+
13
+ * Broken internal links autofix ([40764fb](https://github.com/adobe/spacecat-shared/commit/40764fbb88da9760ecfbb008fc4ea27cfe27e823))
14
+
1
15
  # [@adobe/spacecat-shared-content-client-v1.3.40](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-content-client-v1.3.39...@adobe/spacecat-shared-content-client-v1.3.40) (2025-03-03)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-content-client",
3
- "version": "1.3.40",
3
+ "version": "1.4.1",
4
4
  "description": "Shared modules of the Spacecat Services - Content Client",
5
5
  "type": "module",
6
6
  "engines": {
@@ -34,9 +34,9 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@adobe/helix-universal": "5.0.8",
37
+ "@adobe/helix-universal": "5.0.9",
38
38
  "@adobe/spacecat-shared-data-access": "2.0.2",
39
- "@adobe/spacecat-helix-content-sdk": "1.3.45",
39
+ "@adobe/spacecat-helix-content-sdk": "1.3.46",
40
40
  "@adobe/spacecat-shared-utils": "1.26.4",
41
41
  "graph-data-structure": "4.4.0"
42
42
  },
@@ -9,7 +9,6 @@
9
9
  * OF ANY KIND, either express or implied. See the License for the specific language
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
-
13
12
  import { createFrom as createContentSDKClient } from '@adobe/spacecat-helix-content-sdk';
14
13
  import {
15
14
  composeBaseURL, hasText, isObject, tracingFetch,
@@ -100,39 +99,45 @@ const validateMetadata = (metadata) => {
100
99
  }
101
100
  };
102
101
 
103
- const validateRedirects = (redirects) => {
104
- const pathRegex = /^\/[a-zA-Z0-9\-._~%!$&'()*+,;=:@/]*$/;
105
- if (!Array.isArray(redirects)) {
106
- throw new Error('Redirects must be an array');
102
+ const validateLinks = (links, type) => {
103
+ let pathRegex;
104
+ if (type === 'URL') {
105
+ pathRegex = /^(http:\/\/|https:\/\/)[a-zA-Z0-9\-._~%!$&'()*+,;=:@/]*$/;
106
+ } else if (type === 'Redirect') {
107
+ pathRegex = /^\/[a-zA-Z0-9\-._~%!$&'()*+,;=:@/]*$/;
108
+ }
109
+
110
+ if (!Array.isArray(links)) {
111
+ throw new Error(`${type}s must be an array`);
107
112
  }
108
113
 
109
- if (!redirects.length) {
110
- throw new Error('Redirects must not be empty');
114
+ if (!links.length) {
115
+ throw new Error(`${type}s must not be empty`);
111
116
  }
112
117
 
113
- for (const redirect of redirects) {
114
- if (!isObject(redirect)) {
115
- throw new Error('Redirect must be an object');
118
+ for (const link of links) {
119
+ if (!isObject(link)) {
120
+ throw new Error(`${type} must be an object`);
116
121
  }
117
122
 
118
- if (!hasText(redirect.from)) {
119
- throw new Error('Redirect must have a valid from path');
123
+ if (!hasText(link.from)) {
124
+ throw new Error(`${type} must have a valid from path`);
120
125
  }
121
126
 
122
- if (!hasText(redirect.to)) {
123
- throw new Error('Redirect must have a valid to path');
127
+ if (!hasText(link.to)) {
128
+ throw new Error(`${type} must have a valid to path`);
124
129
  }
125
130
 
126
- if (!pathRegex.test(redirect.from)) {
127
- throw new Error(`Invalid redirect from path: ${redirect.from}`);
131
+ if (!pathRegex.test(link.from)) {
132
+ throw new Error(`Invalid ${type} from path: ${link.from}`);
128
133
  }
129
134
 
130
- if (!pathRegex.test(redirect.to)) {
131
- throw new Error(`Invalid redirect to path: ${redirect.to}`);
135
+ if (!pathRegex.test(link.to)) {
136
+ throw new Error(`Invalid ${type} to path: ${link.to}`);
132
137
  }
133
138
 
134
- if (redirect.from === redirect.to) {
135
- throw new Error('Redirect from and to paths must be different');
139
+ if (link.from === link.to) {
140
+ throw new Error(`${type} from and to paths must be different`);
136
141
  }
137
142
  }
138
143
  };
@@ -322,7 +327,7 @@ export default class ContentClient {
322
327
  async updateRedirects(redirects) {
323
328
  const startTime = process.hrtime.bigint();
324
329
 
325
- validateRedirects(redirects);
330
+ validateLinks(redirects, 'Redirect');
326
331
 
327
332
  await this.#initClient();
328
333
 
@@ -349,4 +354,27 @@ export default class ContentClient {
349
354
 
350
355
  this.#logDuration('updateRedirects', startTime);
351
356
  }
357
+
358
+ async updateBrokenInternalLink(path, brokenLink) {
359
+ const startTime = process.hrtime.bigint();
360
+
361
+ validateLinks([brokenLink], 'URL');
362
+ validatePath(path);
363
+
364
+ await this.#initClient();
365
+
366
+ this.log.info(`Updating page link for ${this.site.getId()} and path ${path}`);
367
+
368
+ const docPath = this.#resolveDocPath(path);
369
+ const document = await this.rawClient.getDocument(docPath);
370
+
371
+ this.log.info('Updating link from', brokenLink.from, 'to', brokenLink.to);
372
+ const response = await document.updateLink(brokenLink.from, brokenLink.to);
373
+
374
+ if (response.status !== 200) {
375
+ throw new Error(`Failed to update link from ${brokenLink.from} to ${brokenLink.to} // ${brokenLink}`);
376
+ }
377
+
378
+ this.#logDuration('updateBrokenInternalLink', startTime);
379
+ }
352
380
  }
@@ -103,4 +103,18 @@ export class ContentClient {
103
103
  * is an issue updating the redirects.
104
104
  */
105
105
  updateRedirects(redirects: Array<{ from: string, to: string }>): Promise<void>
106
+
107
+ /**
108
+ * Updates the broken internal links for the given page path.
109
+ *
110
+ * @param {string} path The path to the page.
111
+ * @param {Array<{ from: string, to: string }>} brokenLinks The array of broken link objects to
112
+ * update.
113
+ * @returns {Promise<void>} A promise that resolves when the broken links have been updated.
114
+ * @throws {Error} If the path is not a string, empty or does not start with a "/"
115
+ * @throws {Error} If the brokenLinks array is not valid or if there is an issue updating the
116
+ * links.
117
+ */
118
+ updateBrokenInternalLinks(path: string, brokenLinks: Array<{ from: string, to: string }>):
119
+ Promise<void>;
106
120
  }