@sitecore-content-sdk/core 0.1.0-beta.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.
Files changed (160) hide show
  1. package/LICENSE.txt +202 -0
  2. package/README.md +11 -0
  3. package/dist/cjs/cache-client.js +54 -0
  4. package/dist/cjs/constants.js +13 -0
  5. package/dist/cjs/data-fetcher.js +33 -0
  6. package/dist/cjs/debug.js +43 -0
  7. package/dist/cjs/editing/component-library.js +104 -0
  8. package/dist/cjs/editing/graphql-editing-service.js +186 -0
  9. package/dist/cjs/editing/index.js +23 -0
  10. package/dist/cjs/editing/models.js +23 -0
  11. package/dist/cjs/editing/rest-component-layout-service.js +76 -0
  12. package/dist/cjs/editing/utils.js +86 -0
  13. package/dist/cjs/graphql/app-root-query.js +73 -0
  14. package/dist/cjs/graphql/graphql-edge-proxy.js +21 -0
  15. package/dist/cjs/graphql/index.js +13 -0
  16. package/dist/cjs/graphql/search-service.js +61 -0
  17. package/dist/cjs/graphql-request-client.js +152 -0
  18. package/dist/cjs/i18n/dictionary-service.js +45 -0
  19. package/dist/cjs/i18n/graphql-dictionary-service.js +136 -0
  20. package/dist/cjs/i18n/index.js +7 -0
  21. package/dist/cjs/index.js +55 -0
  22. package/dist/cjs/layout/content-styles.js +70 -0
  23. package/dist/cjs/layout/graphql-layout-service.js +86 -0
  24. package/dist/cjs/layout/index.js +24 -0
  25. package/dist/cjs/layout/layout-service.js +9 -0
  26. package/dist/cjs/layout/models.js +35 -0
  27. package/dist/cjs/layout/themes.js +74 -0
  28. package/dist/cjs/layout/utils.js +110 -0
  29. package/dist/cjs/media/index.js +38 -0
  30. package/dist/cjs/media/media-api.js +96 -0
  31. package/dist/cjs/models.js +2 -0
  32. package/dist/cjs/native-fetcher.js +200 -0
  33. package/dist/cjs/personalize/graphql-personalize-service.js +114 -0
  34. package/dist/cjs/personalize/index.js +14 -0
  35. package/dist/cjs/personalize/layout-personalizer.js +97 -0
  36. package/dist/cjs/personalize/utils.js +136 -0
  37. package/dist/cjs/site/graphql-error-pages-service.js +89 -0
  38. package/dist/cjs/site/graphql-redirects-service.js +105 -0
  39. package/dist/cjs/site/graphql-robots-service.js +83 -0
  40. package/dist/cjs/site/graphql-siteinfo-service.js +107 -0
  41. package/dist/cjs/site/graphql-sitemap-service.js +93 -0
  42. package/dist/cjs/site/index.js +22 -0
  43. package/dist/cjs/site/site-resolver.js +79 -0
  44. package/dist/cjs/site/utils.js +43 -0
  45. package/dist/cjs/utils/env.js +26 -0
  46. package/dist/cjs/utils/index.js +20 -0
  47. package/dist/cjs/utils/is-server.js +10 -0
  48. package/dist/cjs/utils/timeout-promise.js +31 -0
  49. package/dist/cjs/utils/utils.js +222 -0
  50. package/dist/esm/cache-client.js +50 -0
  51. package/dist/esm/constants.js +10 -0
  52. package/dist/esm/data-fetcher.js +28 -0
  53. package/dist/esm/debug.js +36 -0
  54. package/dist/esm/editing/component-library.js +98 -0
  55. package/dist/esm/editing/graphql-editing-service.js +179 -0
  56. package/dist/esm/editing/index.js +5 -0
  57. package/dist/esm/editing/models.js +20 -0
  58. package/dist/esm/editing/rest-component-layout-service.js +72 -0
  59. package/dist/esm/editing/utils.js +76 -0
  60. package/dist/esm/graphql/app-root-query.js +69 -0
  61. package/dist/esm/graphql/graphql-edge-proxy.js +16 -0
  62. package/dist/esm/graphql/index.js +4 -0
  63. package/dist/esm/graphql/search-service.js +57 -0
  64. package/dist/esm/graphql-request-client.js +144 -0
  65. package/dist/esm/i18n/dictionary-service.js +41 -0
  66. package/dist/esm/i18n/graphql-dictionary-service.js +129 -0
  67. package/dist/esm/i18n/index.js +2 -0
  68. package/dist/esm/index.js +9 -0
  69. package/dist/esm/layout/content-styles.js +62 -0
  70. package/dist/esm/layout/graphql-layout-service.js +79 -0
  71. package/dist/esm/layout/index.js +6 -0
  72. package/dist/esm/layout/layout-service.js +5 -0
  73. package/dist/esm/layout/models.js +32 -0
  74. package/dist/esm/layout/themes.js +69 -0
  75. package/dist/esm/layout/utils.js +102 -0
  76. package/dist/esm/media/index.js +2 -0
  77. package/dist/esm/media/media-api.js +86 -0
  78. package/dist/esm/models.js +1 -0
  79. package/dist/esm/native-fetcher.js +193 -0
  80. package/dist/esm/personalize/graphql-personalize-service.js +107 -0
  81. package/dist/esm/personalize/index.js +3 -0
  82. package/dist/esm/personalize/layout-personalizer.js +92 -0
  83. package/dist/esm/personalize/utils.js +128 -0
  84. package/dist/esm/site/graphql-error-pages-service.js +82 -0
  85. package/dist/esm/site/graphql-redirects-service.js +98 -0
  86. package/dist/esm/site/graphql-robots-service.js +76 -0
  87. package/dist/esm/site/graphql-siteinfo-service.js +100 -0
  88. package/dist/esm/site/graphql-sitemap-service.js +86 -0
  89. package/dist/esm/site/index.js +7 -0
  90. package/dist/esm/site/site-resolver.js +75 -0
  91. package/dist/esm/site/utils.js +37 -0
  92. package/dist/esm/utils/env.js +22 -0
  93. package/dist/esm/utils/index.js +3 -0
  94. package/dist/esm/utils/is-server.js +8 -0
  95. package/dist/esm/utils/timeout-promise.js +28 -0
  96. package/dist/esm/utils/utils.js +207 -0
  97. package/editing.d.ts +1 -0
  98. package/editing.js +1 -0
  99. package/graphql.d.ts +1 -0
  100. package/graphql.js +1 -0
  101. package/i18n.d.ts +1 -0
  102. package/i18n.js +1 -0
  103. package/layout.d.ts +1 -0
  104. package/layout.js +1 -0
  105. package/media.d.ts +1 -0
  106. package/media.js +1 -0
  107. package/package.json +76 -0
  108. package/personalize.d.ts +1 -0
  109. package/personalize.js +1 -0
  110. package/site.d.ts +1 -0
  111. package/site.js +1 -0
  112. package/types/cache-client.d.ts +64 -0
  113. package/types/constants.d.ts +7 -0
  114. package/types/data-fetcher.d.ts +34 -0
  115. package/types/debug.d.ts +26 -0
  116. package/types/editing/component-library.d.ts +48 -0
  117. package/types/editing/graphql-editing-service.d.ts +90 -0
  118. package/types/editing/index.d.ts +6 -0
  119. package/types/editing/models.d.ts +52 -0
  120. package/types/editing/rest-component-layout-service.d.ts +100 -0
  121. package/types/editing/utils.d.ts +70 -0
  122. package/types/graphql/app-root-query.d.ts +32 -0
  123. package/types/graphql/graphql-edge-proxy.d.ts +15 -0
  124. package/types/graphql/index.d.ts +4 -0
  125. package/types/graphql/search-service.d.ts +95 -0
  126. package/types/graphql-request-client.d.ts +159 -0
  127. package/types/i18n/dictionary-service.d.ts +56 -0
  128. package/types/i18n/graphql-dictionary-service.d.ts +94 -0
  129. package/types/i18n/index.d.ts +2 -0
  130. package/types/index.d.ts +8 -0
  131. package/types/layout/content-styles.d.ts +18 -0
  132. package/types/layout/graphql-layout-service.d.ts +58 -0
  133. package/types/layout/index.d.ts +6 -0
  134. package/types/layout/layout-service.d.ts +19 -0
  135. package/types/layout/models.d.ts +145 -0
  136. package/types/layout/themes.d.ts +11 -0
  137. package/types/layout/utils.d.ts +40 -0
  138. package/types/media/index.d.ts +2 -0
  139. package/types/media/media-api.d.ts +55 -0
  140. package/types/models.d.ts +6 -0
  141. package/types/native-fetcher.d.ts +121 -0
  142. package/types/personalize/graphql-personalize-service.d.ts +80 -0
  143. package/types/personalize/index.d.ts +3 -0
  144. package/types/personalize/layout-personalizer.d.ts +27 -0
  145. package/types/personalize/utils.d.ts +69 -0
  146. package/types/site/graphql-error-pages-service.d.ts +57 -0
  147. package/types/site/graphql-redirects-service.d.ts +68 -0
  148. package/types/site/graphql-robots-service.d.ts +49 -0
  149. package/types/site/graphql-siteinfo-service.d.ts +70 -0
  150. package/types/site/graphql-sitemap-service.d.ts +55 -0
  151. package/types/site/index.d.ts +7 -0
  152. package/types/site/site-resolver.d.ts +27 -0
  153. package/types/site/utils.d.ts +24 -0
  154. package/types/utils/env.d.ts +7 -0
  155. package/types/utils/index.d.ts +3 -0
  156. package/types/utils/is-server.d.ts +6 -0
  157. package/types/utils/timeout-promise.d.ts +17 -0
  158. package/types/utils/utils.d.ts +71 -0
  159. package/utils.d.ts +1 -0
  160. package/utils.js +1 -0
@@ -0,0 +1,107 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import debug from '../debug';
11
+ import { isTimeoutError } from '../utils';
12
+ import { MemoryCacheClient } from '../cache-client';
13
+ export class GraphQLPersonalizeService {
14
+ /**
15
+ * Fetch personalize data using the Sitecore GraphQL endpoint.
16
+ * @param {GraphQLPersonalizeServiceConfig} config
17
+ */
18
+ constructor(config) {
19
+ this.config = config;
20
+ this.config.timeout = config.timeout || 400;
21
+ this.graphQLClient = this.getGraphQLClient();
22
+ this.cache = this.getCacheClient();
23
+ }
24
+ get query() {
25
+ return /* GraphQL */ `
26
+ query($siteName: String!, $language: String!, $itemPath: String!) {
27
+ layout(site: $siteName, routePath: $itemPath, language: $language) {
28
+ item {
29
+ id
30
+ version
31
+ personalization {
32
+ variantIds
33
+ }
34
+ }
35
+ }
36
+ }
37
+ `;
38
+ }
39
+ /**
40
+ * Get personalize information for a route
41
+ * @param {string} itemPath page route
42
+ * @param {string} language language
43
+ * @param {string} siteName site name
44
+ * @returns {Promise<PersonalizeInfo | undefined>} the personalize information or undefined (if itemPath / language not found)
45
+ */
46
+ getPersonalizeInfo(itemPath, language, siteName) {
47
+ return __awaiter(this, void 0, void 0, function* () {
48
+ var _a;
49
+ debug.personalize('fetching personalize info for %s %s %s', siteName, itemPath, language);
50
+ const cacheKey = this.getCacheKey(itemPath, language, siteName);
51
+ let data = this.cache.getCacheValue(cacheKey);
52
+ if (!data) {
53
+ try {
54
+ data = yield this.graphQLClient.request(this.query, {
55
+ siteName,
56
+ itemPath,
57
+ language,
58
+ });
59
+ this.cache.setCacheValue(cacheKey, data);
60
+ }
61
+ catch (error) {
62
+ if (isTimeoutError(error)) {
63
+ return undefined;
64
+ }
65
+ throw error;
66
+ }
67
+ }
68
+ return ((_a = data === null || data === void 0 ? void 0 : data.layout) === null || _a === void 0 ? void 0 : _a.item)
69
+ ? {
70
+ pageId: data.layout.item.id,
71
+ variantIds: data.layout.item.personalization.variantIds,
72
+ }
73
+ : undefined;
74
+ });
75
+ }
76
+ /**
77
+ * Gets cache client implementation
78
+ * Override this method if custom cache needs to be used
79
+ * @returns CacheClient instance
80
+ */
81
+ getCacheClient() {
82
+ var _a, _b;
83
+ return new MemoryCacheClient({
84
+ cacheEnabled: (_a = this.config.cacheEnabled) !== null && _a !== void 0 ? _a : true,
85
+ cacheTimeout: (_b = this.config.cacheTimeout) !== null && _b !== void 0 ? _b : 10,
86
+ });
87
+ }
88
+ getCacheKey(itemPath, language, siteName) {
89
+ return `${siteName}-${itemPath}-${language}`;
90
+ }
91
+ /**
92
+ * Gets a GraphQL client that can make requests to the API. Uses graphql-request as the default
93
+ * library for fetching graphql data (@see GraphQLRequestClient). Override this method if you
94
+ * want to use something else.
95
+ * @returns {GraphQLClient} implementation
96
+ */
97
+ getGraphQLClient() {
98
+ if (!this.config.clientFactory) {
99
+ throw new Error('clientFactory needs to be provided when initializing GraphQL client.');
100
+ }
101
+ return this.config.clientFactory({
102
+ debugger: debug.personalize,
103
+ fetch: this.config.fetch,
104
+ timeout: this.config.timeout,
105
+ });
106
+ }
107
+ }
@@ -0,0 +1,3 @@
1
+ export { personalizeLayout } from './layout-personalizer';
2
+ export { GraphQLPersonalizeService, } from './graphql-personalize-service';
3
+ export { getPersonalizedRewrite, getPersonalizedRewriteData, getGroomedVariantIds, normalizePersonalizedRewrite, CdpHelper, DEFAULT_VARIANT, } from './utils';
@@ -0,0 +1,92 @@
1
+ import { HIDDEN_RENDERING_NAME } from '../constants';
2
+ const transformToHiddenRenderingVariant = (component) => (Object.assign(Object.assign({}, component), { componentName: HIDDEN_RENDERING_NAME, experiences: {} }));
3
+ /**
4
+ * Apply personalization to layout data. This will recursively go through all placeholders/components, check experiences nodes and replace default with object from specific experience.
5
+ * @param {LayoutServiceData} layout Layout data
6
+ * @param {string} variantId variant id
7
+ * @param {string[]} [componentVariantIds] component variant ids
8
+ */
9
+ export function personalizeLayout(layout, variantId, componentVariantIds) {
10
+ var _a;
11
+ // Add (page-level) variantId to Sitecore context so that it is accessible here
12
+ layout.sitecore.context.variantId = variantId;
13
+ const placeholders = ((_a = layout.sitecore.route) === null || _a === void 0 ? void 0 : _a.placeholders) || {};
14
+ if (Object.keys(placeholders).length === 0) {
15
+ return undefined;
16
+ }
17
+ const isEditing = layout.sitecore.context.pageEditing;
18
+ if (placeholders) {
19
+ Object.keys(placeholders).forEach((placeholder) => {
20
+ placeholders[placeholder] = personalizePlaceholder(placeholders[placeholder], [variantId, ...(componentVariantIds || [])], isEditing);
21
+ });
22
+ }
23
+ return placeholders;
24
+ }
25
+ /**
26
+ * @param {Array} components components within placeholder
27
+ * @param {string[]} variantIds variant ids
28
+ * @param {boolean} isEditing indicates if page is rendered in metadata edit mode
29
+ * @returns {ComponentRendering[]} components with personalization applied
30
+ */
31
+ export function personalizePlaceholder(components, variantIds, isEditing) {
32
+ return components
33
+ .map((component) => {
34
+ const rendering = component;
35
+ if (rendering.experiences !== undefined) {
36
+ return personalizeComponent(rendering, variantIds, isEditing);
37
+ }
38
+ else if (rendering.placeholders) {
39
+ const placeholders = rendering.placeholders;
40
+ Object.keys(placeholders).forEach((placeholder) => {
41
+ placeholders[placeholder] = personalizePlaceholder(placeholders[placeholder], variantIds, isEditing);
42
+ });
43
+ }
44
+ return component;
45
+ })
46
+ .filter(Boolean);
47
+ }
48
+ /**
49
+ * @param {ComponentRenderingWithExperiences} component component with experiences
50
+ * @param {string[]} variantIds variant ids
51
+ * @param {boolean} isEditing indicates if page is rendered in metadata edit mode
52
+ * @returns {ComponentRendering | null} component with personalization applied or null if hidden
53
+ */
54
+ export function personalizeComponent(component, variantIds, isEditing) {
55
+ // Check if we have a page/component experience matching any of the variants (there should be at most 1)
56
+ const match = Object.keys(component.experiences).find((variantId) => variantIds.includes(variantId));
57
+ const variant = match && component.experiences[match];
58
+ // variant and componentName can be undefined or null
59
+ if (!variant && !component.componentName) {
60
+ // DEFAULT IS HIDDEN
61
+ if (isEditing) {
62
+ component = transformToHiddenRenderingVariant(component);
63
+ }
64
+ else {
65
+ return null;
66
+ }
67
+ }
68
+ else if (variant && variant.componentName === null && variant.dataSource === null) {
69
+ // VARIANT IS HIDDEN
70
+ if (isEditing) {
71
+ component = transformToHiddenRenderingVariant(component);
72
+ }
73
+ else {
74
+ return null;
75
+ }
76
+ }
77
+ else if (variant) {
78
+ component = variant;
79
+ }
80
+ // remove unused experiences from layout data
81
+ if (component.experiences) {
82
+ component.experiences = {};
83
+ }
84
+ if (!component.placeholders)
85
+ return component;
86
+ Object.keys(component === null || component === void 0 ? void 0 : component.placeholders).forEach((placeholder) => {
87
+ if (component.placeholders) {
88
+ component.placeholders[placeholder] = personalizePlaceholder(component.placeholders[placeholder], variantIds);
89
+ }
90
+ });
91
+ return component;
92
+ }
@@ -0,0 +1,128 @@
1
+ export const DEFAULT_VARIANT = '_default';
2
+ export const VARIANT_PREFIX = '_variantId_';
3
+ /**
4
+ * Get a personalized rewrite path for given pathname
5
+ * @param {string} pathname the pathname
6
+ * @param {string[]} variantIds the variantIds to include in the rewrite
7
+ * @returns {string} the rewrite path
8
+ */
9
+ export function getPersonalizedRewrite(pathname, variantIds) {
10
+ const path = pathname.startsWith('/') ? pathname : '/' + pathname;
11
+ return `${variantIds.map((variantId) => `/${VARIANT_PREFIX}${variantId}`).join('')}${path}`;
12
+ }
13
+ /**
14
+ * Get personalize data from the rewrite path
15
+ * @param {string} pathname the pathname
16
+ * @returns {PersonalizedRewriteData} the personalize data from the rewrite
17
+ */
18
+ export function getPersonalizedRewriteData(pathname) {
19
+ const segments = pathname.split('/');
20
+ const variantIds = [];
21
+ segments.forEach((segment) => {
22
+ const result = segment.match(`${VARIANT_PREFIX}(.*$)`);
23
+ if (result) {
24
+ variantIds.push(result[1]);
25
+ }
26
+ });
27
+ return getGroomedVariantIds(variantIds);
28
+ }
29
+ /**
30
+ * Parses a list of variantIds and divides into layout and component variants
31
+ * @param {string[]} variantIds the list of variant IDs for a page
32
+ * @returns {PersonalizedRewriteData} object with variant IDs sorted
33
+ */
34
+ export function getGroomedVariantIds(variantIds) {
35
+ const data = {
36
+ variantId: DEFAULT_VARIANT,
37
+ componentVariantIds: [],
38
+ };
39
+ variantIds.forEach((variantId) => {
40
+ var _a;
41
+ if (variantId.includes('_')) {
42
+ // Component-level personalization in format "<ComponentID>_<VariantID>"
43
+ // There can be multiple
44
+ (_a = data.componentVariantIds) === null || _a === void 0 ? void 0 : _a.push(variantId);
45
+ }
46
+ else {
47
+ // Embedded (page-level) personalization in format "<VariantID>"
48
+ // There should be only one
49
+ data.variantId = variantId;
50
+ }
51
+ });
52
+ return data;
53
+ }
54
+ /**
55
+ * Normalize a personalized rewrite path (remove personalize data)
56
+ * @param {string} pathname the pathname
57
+ * @returns {string} the pathname with personalize data removed
58
+ */
59
+ export function normalizePersonalizedRewrite(pathname) {
60
+ if (!pathname.includes(VARIANT_PREFIX)) {
61
+ return pathname;
62
+ }
63
+ let segments = pathname.split('/');
64
+ segments = segments.filter((segment) => !segment.includes(VARIANT_PREFIX));
65
+ const result = segments.join('/');
66
+ // return root path if all segments were personalize data
67
+ return result ? result : '/';
68
+ }
69
+ /**
70
+ * Static utility class for Sitecore CDP
71
+ */
72
+ export class CdpHelper {
73
+ /**
74
+ * Gets the page variant id for CDP in the required format
75
+ * @param {string} pageId the page id
76
+ * @param {string} language the language
77
+ * @param {string} variantId the variant id
78
+ * @param {string} [scope] the scope value
79
+ * @returns {string} the formatted page variant id
80
+ */
81
+ static getPageVariantId(pageId, language, variantId, scope) {
82
+ const formattedPageId = pageId.replace(/[{}-]/g, '');
83
+ const formattedLanguage = language.replace('-', '_');
84
+ const scopeId = scope ? `${this.normalizeScope(scope)}_` : '';
85
+ let formattedVariantId = variantId;
86
+ if (!variantId || variantId === DEFAULT_VARIANT) {
87
+ formattedVariantId = 'default';
88
+ }
89
+ return `${scopeId}${formattedPageId}_${formattedLanguage}_${formattedVariantId}`.toLowerCase();
90
+ }
91
+ /**
92
+ * Gets the friendly id for (page-level) Embedded Personalization in the required format `embedded_[<scope>_]<id>_<lang>`
93
+ * @param {string} pageId the page id
94
+ * @param {string} language the language
95
+ * @param {string} [scope] the scope value
96
+ * @returns {string} the friendly id
97
+ */
98
+ static getPageFriendlyId(pageId, language, scope) {
99
+ const formattedPageId = pageId.replace(/[{}-]/g, '');
100
+ const formattedLanguage = language.replace('-', '_');
101
+ const scopeId = scope ? `${this.normalizeScope(scope)}_` : '';
102
+ return `embedded_${scopeId}${formattedPageId}_${formattedLanguage}`.toLowerCase();
103
+ }
104
+ /**
105
+ * Gets the friendly id for Component A/B Testing in the required format `component_[<scope>_]<pageId>_<componentId>_<language>*`
106
+ * @param {string} pageId the page id
107
+ * @param {string} componentId the component id
108
+ * @param {string} language the language
109
+ * @param {string} [scope] the scope value
110
+ * @returns {string} the friendly id
111
+ */
112
+ static getComponentFriendlyId(pageId, componentId, language, scope) {
113
+ const formattedPageId = pageId.replace(/[{}-]/g, '');
114
+ const formattedComponentId = componentId.replace(/[{}-]/g, '');
115
+ const formattedLanguage = language.replace('-', '_');
116
+ const scopeId = scope ? `${this.normalizeScope(scope)}_` : '';
117
+ return `component_${scopeId}${formattedPageId}_${formattedComponentId}_${formattedLanguage}*`.toLowerCase();
118
+ }
119
+ /**
120
+ * Normalizes the scope from the given string value
121
+ * Removes all non-alphanumeric characters
122
+ * @param {string} [scope] the scope value
123
+ * @returns {string} normalized scope value
124
+ */
125
+ static normalizeScope(scope) {
126
+ return (scope === null || scope === void 0 ? void 0 : scope.replace(/[^a-zA-Z0-9]+/g, '')) || '';
127
+ }
128
+ }
@@ -0,0 +1,82 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { siteNameError } from '../constants';
11
+ import debug from '../debug';
12
+ // The default query for request error handling
13
+ const defaultQuery = /* GraphQL */ `
14
+ query ErrorPagesQuery($siteName: String!, $language: String!) {
15
+ site {
16
+ siteInfo(site: $siteName) {
17
+ errorHandling(language: $language) {
18
+ notFoundPage {
19
+ rendered
20
+ }
21
+ notFoundPagePath
22
+ serverErrorPage {
23
+ rendered
24
+ }
25
+ serverErrorPagePath
26
+ }
27
+ }
28
+ }
29
+ }
30
+ `;
31
+ /**
32
+ * Service that fetch the error pages data using Sitecore's GraphQL API.
33
+ */
34
+ export class GraphQLErrorPagesService {
35
+ /**
36
+ * Creates an instance of graphQL error pages service with the provided options
37
+ * @param {GraphQLErrorPagesServiceConfig} options instance
38
+ */
39
+ constructor(options) {
40
+ this.options = options;
41
+ this.graphQLClient = this.getGraphQLClient();
42
+ }
43
+ get query() {
44
+ return defaultQuery;
45
+ }
46
+ /**
47
+ * Fetch list of error pages for the site
48
+ * @returns {ErrorPages} list of url's error pages
49
+ * @throws {Error} if the siteName is empty.
50
+ */
51
+ fetchErrorPages() {
52
+ return __awaiter(this, void 0, void 0, function* () {
53
+ const siteName = this.options.siteName;
54
+ const language = this.options.language;
55
+ if (!siteName) {
56
+ throw new Error(siteNameError);
57
+ }
58
+ return this.graphQLClient.request(this.query, {
59
+ siteName,
60
+ language,
61
+ })
62
+ .then((result) => result.site.siteInfo ? result.site.siteInfo.errorHandling : null)
63
+ .catch((e) => Promise.reject(e));
64
+ });
65
+ }
66
+ /**
67
+ * Gets a GraphQL client that can make requests to the API. Uses graphql-request as the default
68
+ * library for fetching graphql data (@see GraphQLRequestClient). Override this method if you
69
+ * want to use something else.
70
+ * @returns {GraphQLClient} implementation
71
+ */
72
+ getGraphQLClient() {
73
+ if (!this.options.clientFactory) {
74
+ throw new Error('clientFactory needs to be provided when initializing GraphQL client.');
75
+ }
76
+ return this.options.clientFactory({
77
+ debugger: debug.errorpages,
78
+ retries: this.options.retries,
79
+ retryStrategy: this.options.retryStrategy,
80
+ });
81
+ }
82
+ }
@@ -0,0 +1,98 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { siteNameError } from '../constants';
11
+ import debug from '../debug';
12
+ import { MemoryCacheClient } from '../cache-client';
13
+ export const REDIRECT_TYPE_301 = 'REDIRECT_301';
14
+ export const REDIRECT_TYPE_302 = 'REDIRECT_302';
15
+ export const REDIRECT_TYPE_SERVER_TRANSFER = 'SERVER_TRANSFER';
16
+ // The default query for request redirects of site
17
+ const defaultQuery = /* GraphQL */ `
18
+ query RedirectsQuery($siteName: String!) {
19
+ site {
20
+ siteInfo(site: $siteName) {
21
+ redirects {
22
+ pattern
23
+ target
24
+ redirectType
25
+ isQueryStringPreserved
26
+ locale
27
+ }
28
+ }
29
+ }
30
+ }
31
+ `;
32
+ /**
33
+ * The GraphQLRedirectsService class is used to query the JSS redirects using Graphql endpoint
34
+ */
35
+ export class GraphQLRedirectsService {
36
+ /**
37
+ * Creates an instance of graphQL redirects service with the provided options
38
+ * @param {GraphQLRedirectsServiceConfig} options instance
39
+ */
40
+ constructor(options) {
41
+ this.options = options;
42
+ this.graphQLClient = this.getGraphQLClient();
43
+ this.cache = this.getCacheClient();
44
+ }
45
+ get query() {
46
+ return defaultQuery;
47
+ }
48
+ /**
49
+ * Fetch an array of redirects from API
50
+ * @param {string} siteName site name
51
+ * @returns Promise<RedirectInfo[]>
52
+ * @throws {Error} if the siteName is empty.
53
+ */
54
+ fetchRedirects(siteName) {
55
+ return __awaiter(this, void 0, void 0, function* () {
56
+ var _a, _b;
57
+ if (!siteName) {
58
+ throw new Error(siteNameError);
59
+ }
60
+ const cacheKey = `redirects-${siteName}`;
61
+ let data = this.cache.getCacheValue(cacheKey);
62
+ if (!data) {
63
+ data = yield this.graphQLClient.request(this.query, {
64
+ siteName,
65
+ });
66
+ this.cache.setCacheValue(cacheKey, data);
67
+ }
68
+ return ((_b = (_a = data === null || data === void 0 ? void 0 : data.site) === null || _a === void 0 ? void 0 : _a.siteInfo) === null || _b === void 0 ? void 0 : _b.redirects) || [];
69
+ });
70
+ }
71
+ /**
72
+ * Gets a GraphQL client that can make requests to the API. Uses graphql-request as the default
73
+ * library for fetching graphql data (@see GraphQLRequestClient). Override this method if you
74
+ * want to use something else.
75
+ * @returns {GraphQLClient} implementation
76
+ */
77
+ getGraphQLClient() {
78
+ if (!this.options.clientFactory) {
79
+ throw new Error('clientFactory needs to be provided when initializing GraphQL client.');
80
+ }
81
+ return this.options.clientFactory({
82
+ debugger: debug.redirects,
83
+ fetch: this.options.fetch,
84
+ });
85
+ }
86
+ /**
87
+ * Gets cache client implementation
88
+ * Override this method if custom cache needs to be used
89
+ * @returns CacheClient instance
90
+ */
91
+ getCacheClient() {
92
+ var _a, _b;
93
+ return new MemoryCacheClient({
94
+ cacheEnabled: (_a = this.options.cacheEnabled) !== null && _a !== void 0 ? _a : true,
95
+ cacheTimeout: (_b = this.options.cacheTimeout) !== null && _b !== void 0 ? _b : 10,
96
+ });
97
+ }
98
+ }
@@ -0,0 +1,76 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { siteNameError } from '../constants';
11
+ import debug from '../debug';
12
+ // The default query for request robots.txt
13
+ const defaultQuery = /* GraphQL */ `
14
+ query RobotsQuery($siteName: String!) {
15
+ site {
16
+ siteInfo(site: $siteName) {
17
+ robots
18
+ }
19
+ }
20
+ }
21
+ `;
22
+ /**
23
+ * Service that fetch the robots.txt data using Sitecore's GraphQL API.
24
+ */
25
+ export class GraphQLRobotsService {
26
+ /**
27
+ * Creates an instance of graphQL robots.txt service with the provided options
28
+ * @param {GraphQLRobotsServiceConfig} options instance
29
+ */
30
+ constructor(options) {
31
+ this.options = options;
32
+ this.graphQLClient = this.getGraphQLClient();
33
+ }
34
+ get query() {
35
+ return defaultQuery;
36
+ }
37
+ /**
38
+ * Fetch a data of robots.txt from API
39
+ * @returns text of robots.txt
40
+ * @throws {Error} if the siteName is empty.
41
+ */
42
+ fetchRobots() {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ const siteName = this.options.siteName;
45
+ if (!siteName) {
46
+ throw new Error(siteNameError);
47
+ }
48
+ const robotsResult = this.graphQLClient.request(this.query, {
49
+ siteName,
50
+ });
51
+ try {
52
+ return robotsResult.then((result) => {
53
+ var _a, _b;
54
+ return (_b = (_a = result === null || result === void 0 ? void 0 : result.site) === null || _a === void 0 ? void 0 : _a.siteInfo) === null || _b === void 0 ? void 0 : _b.robots;
55
+ });
56
+ }
57
+ catch (e) {
58
+ return Promise.reject(e);
59
+ }
60
+ });
61
+ }
62
+ /**
63
+ * Gets a GraphQL client that can make requests to the API. Uses graphql-request as the default
64
+ * library for fetching graphql data (@see GraphQLRequestClient). Override this method if you
65
+ * want to use something else.
66
+ * @returns {GraphQLClient} implementation
67
+ */
68
+ getGraphQLClient() {
69
+ if (!this.options.clientFactory) {
70
+ throw new Error('clientFactory needs to be provided when initializing GraphQL client.');
71
+ }
72
+ return this.options.clientFactory({
73
+ debugger: debug.robots,
74
+ });
75
+ }
76
+ }