@sitecore-jss/sitecore-jss 0.1.0-beta.2

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 (143) hide show
  1. package/LICENSE.txt +202 -0
  2. package/README.md +7 -0
  3. package/dist/cjs/cache-client.js +54 -0
  4. package/dist/cjs/constants.js +12 -0
  5. package/dist/cjs/debug.js +43 -0
  6. package/dist/cjs/graphql/app-root-query.js +73 -0
  7. package/dist/cjs/graphql/graphql-edge-proxy.js +12 -0
  8. package/dist/cjs/graphql/index.js +11 -0
  9. package/dist/cjs/graphql/search-service.js +60 -0
  10. package/dist/cjs/graphql-request-client.js +106 -0
  11. package/dist/cjs/i18n/dictionary-service.js +45 -0
  12. package/dist/cjs/i18n/graphql-dictionary-service.js +125 -0
  13. package/dist/cjs/i18n/index.js +7 -0
  14. package/dist/cjs/index.js +36 -0
  15. package/dist/cjs/layout/content-styles.js +73 -0
  16. package/dist/cjs/layout/graphql-layout-service.js +84 -0
  17. package/dist/cjs/layout/index.js +18 -0
  18. package/dist/cjs/layout/layout-service.js +9 -0
  19. package/dist/cjs/layout/models.js +27 -0
  20. package/dist/cjs/layout/themes.js +79 -0
  21. package/dist/cjs/layout/utils.js +44 -0
  22. package/dist/cjs/media/index.js +24 -0
  23. package/dist/cjs/media/media-api.js +128 -0
  24. package/dist/cjs/models.js +2 -0
  25. package/dist/cjs/native-fetcher.js +183 -0
  26. package/dist/cjs/personalize/graphql-personalize-service.js +114 -0
  27. package/dist/cjs/personalize/index.js +12 -0
  28. package/dist/cjs/personalize/layout-personalizer.js +75 -0
  29. package/dist/cjs/personalize/utils.js +92 -0
  30. package/dist/cjs/site/graphql-error-pages-service.js +86 -0
  31. package/dist/cjs/site/graphql-redirects-service.js +103 -0
  32. package/dist/cjs/site/graphql-robots-service.js +81 -0
  33. package/dist/cjs/site/graphql-siteinfo-service.js +128 -0
  34. package/dist/cjs/site/graphql-sitemap-service.js +91 -0
  35. package/dist/cjs/site/index.js +22 -0
  36. package/dist/cjs/site/site-resolver.js +79 -0
  37. package/dist/cjs/site/utils.js +43 -0
  38. package/dist/cjs/utils/edit-frame.js +138 -0
  39. package/dist/cjs/utils/editing.js +122 -0
  40. package/dist/cjs/utils/env.js +26 -0
  41. package/dist/cjs/utils/index.js +25 -0
  42. package/dist/cjs/utils/is-server.js +10 -0
  43. package/dist/cjs/utils/timeout-promise.js +31 -0
  44. package/dist/cjs/utils/utils.js +70 -0
  45. package/dist/esm/cache-client.js +50 -0
  46. package/dist/esm/constants.js +9 -0
  47. package/dist/esm/debug.js +36 -0
  48. package/dist/esm/graphql/app-root-query.js +69 -0
  49. package/dist/esm/graphql/graphql-edge-proxy.js +8 -0
  50. package/dist/esm/graphql/index.js +4 -0
  51. package/dist/esm/graphql/search-service.js +56 -0
  52. package/dist/esm/graphql-request-client.js +99 -0
  53. package/dist/esm/i18n/dictionary-service.js +41 -0
  54. package/dist/esm/i18n/graphql-dictionary-service.js +118 -0
  55. package/dist/esm/i18n/index.js +2 -0
  56. package/dist/esm/index.js +7 -0
  57. package/dist/esm/layout/content-styles.js +65 -0
  58. package/dist/esm/layout/graphql-layout-service.js +77 -0
  59. package/dist/esm/layout/index.js +6 -0
  60. package/dist/esm/layout/layout-service.js +5 -0
  61. package/dist/esm/layout/models.js +24 -0
  62. package/dist/esm/layout/themes.js +74 -0
  63. package/dist/esm/layout/utils.js +39 -0
  64. package/dist/esm/media/index.js +2 -0
  65. package/dist/esm/media/media-api.js +117 -0
  66. package/dist/esm/models.js +1 -0
  67. package/dist/esm/native-fetcher.js +176 -0
  68. package/dist/esm/personalize/graphql-personalize-service.js +107 -0
  69. package/dist/esm/personalize/index.js +3 -0
  70. package/dist/esm/personalize/layout-personalizer.js +69 -0
  71. package/dist/esm/personalize/utils.js +85 -0
  72. package/dist/esm/site/graphql-error-pages-service.js +79 -0
  73. package/dist/esm/site/graphql-redirects-service.js +96 -0
  74. package/dist/esm/site/graphql-robots-service.js +74 -0
  75. package/dist/esm/site/graphql-siteinfo-service.js +121 -0
  76. package/dist/esm/site/graphql-sitemap-service.js +84 -0
  77. package/dist/esm/site/index.js +7 -0
  78. package/dist/esm/site/site-resolver.js +75 -0
  79. package/dist/esm/site/utils.js +37 -0
  80. package/dist/esm/utils/edit-frame.js +133 -0
  81. package/dist/esm/utils/editing.js +111 -0
  82. package/dist/esm/utils/env.js +22 -0
  83. package/dist/esm/utils/index.js +5 -0
  84. package/dist/esm/utils/is-server.js +8 -0
  85. package/dist/esm/utils/timeout-promise.js +28 -0
  86. package/dist/esm/utils/utils.js +61 -0
  87. package/graphql.d.ts +1 -0
  88. package/graphql.js +1 -0
  89. package/i18n.d.ts +1 -0
  90. package/i18n.js +1 -0
  91. package/layout.d.ts +1 -0
  92. package/layout.js +1 -0
  93. package/media.d.ts +1 -0
  94. package/media.js +1 -0
  95. package/package.json +71 -0
  96. package/personalize.d.ts +1 -0
  97. package/personalize.js +1 -0
  98. package/site.d.ts +1 -0
  99. package/site.js +1 -0
  100. package/types/cache-client.d.ts +64 -0
  101. package/types/constants.d.ts +6 -0
  102. package/types/debug.d.ts +26 -0
  103. package/types/graphql/app-root-query.d.ts +32 -0
  104. package/types/graphql/graphql-edge-proxy.d.ts +7 -0
  105. package/types/graphql/index.d.ts +4 -0
  106. package/types/graphql/search-service.d.ts +92 -0
  107. package/types/graphql-request-client.d.ts +88 -0
  108. package/types/i18n/dictionary-service.d.ts +56 -0
  109. package/types/i18n/graphql-dictionary-service.d.ts +65 -0
  110. package/types/i18n/index.d.ts +2 -0
  111. package/types/index.d.ts +6 -0
  112. package/types/layout/content-styles.d.ts +18 -0
  113. package/types/layout/graphql-layout-service.d.ts +59 -0
  114. package/types/layout/index.d.ts +6 -0
  115. package/types/layout/layout-service.d.ts +20 -0
  116. package/types/layout/models.d.ts +140 -0
  117. package/types/layout/themes.d.ts +11 -0
  118. package/types/layout/utils.d.ts +17 -0
  119. package/types/media/index.d.ts +2 -0
  120. package/types/media/media-api.d.ts +69 -0
  121. package/types/models.d.ts +6 -0
  122. package/types/native-fetcher.d.ts +92 -0
  123. package/types/personalize/graphql-personalize-service.d.ts +77 -0
  124. package/types/personalize/index.d.ts +3 -0
  125. package/types/personalize/layout-personalizer.d.ts +25 -0
  126. package/types/personalize/utils.d.ts +53 -0
  127. package/types/site/graphql-error-pages-service.d.ts +55 -0
  128. package/types/site/graphql-redirects-service.d.ts +66 -0
  129. package/types/site/graphql-robots-service.d.ts +47 -0
  130. package/types/site/graphql-siteinfo-service.d.ts +69 -0
  131. package/types/site/graphql-sitemap-service.d.ts +53 -0
  132. package/types/site/index.d.ts +7 -0
  133. package/types/site/site-resolver.d.ts +27 -0
  134. package/types/site/utils.d.ts +24 -0
  135. package/types/utils/edit-frame.d.ts +76 -0
  136. package/types/utils/editing.d.ts +58 -0
  137. package/types/utils/env.d.ts +7 -0
  138. package/types/utils/index.d.ts +5 -0
  139. package/types/utils/is-server.d.ts +6 -0
  140. package/types/utils/timeout-promise.d.ts +18 -0
  141. package/types/utils/utils.d.ts +18 -0
  142. package/utils.d.ts +1 -0
  143. package/utils.js +1 -0
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __rest = (this && this.__rest) || function (s, e) {
12
+ var t = {};
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
+ t[p] = s[p];
15
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
+ t[p[i]] = s[p[i]];
19
+ }
20
+ return t;
21
+ };
22
+ var __importDefault = (this && this.__importDefault) || function (mod) {
23
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.NativeDataFetcher = void 0;
27
+ const debug_1 = __importDefault(require("./debug"));
28
+ const timeout_promise_1 = __importDefault(require("./utils/timeout-promise"));
29
+ class NativeDataFetcher {
30
+ constructor(config = {}) {
31
+ this.config = config;
32
+ }
33
+ /**
34
+ * Implements a data fetcher.
35
+ * @param {string} url The URL to request (may include query string)
36
+ * @param {RequestInit} [options] Optional fetch options
37
+ * @returns {Promise<NativeDataFetcherResponse<T>>} response
38
+ */
39
+ fetch(url, options = {}) {
40
+ var _a;
41
+ return __awaiter(this, void 0, void 0, function* () {
42
+ const _b = this.config, { debugger: debugOverride, fetch: fetchOverride } = _b, init = __rest(_b, ["debugger", "fetch"]);
43
+ const startTimestamp = Date.now();
44
+ const fetchImpl = fetchOverride || fetch;
45
+ const debug = debugOverride || debug_1.default.http;
46
+ // merge options from fetcher config and fetch call
47
+ const requestInit = this.getRequestInit(Object.assign(Object.assign({}, init), options));
48
+ const fetchWithOptionalTimeout = [fetchImpl(url, requestInit)];
49
+ if (init.timeout) {
50
+ this.abortTimeout = new timeout_promise_1.default(init.timeout);
51
+ fetchWithOptionalTimeout.push(this.abortTimeout.start);
52
+ }
53
+ // Note a goal here is to provide consistent debug logging and error handling
54
+ // as we do in GraphQLRequestClient
55
+ const { headers: reqHeaders } = requestInit, rest = __rest(requestInit, ["headers"]);
56
+ debug('request: %o', Object.assign({ url, headers: this.extractDebugHeaders(reqHeaders) }, rest));
57
+ const response = yield Promise.race(fetchWithOptionalTimeout)
58
+ .then((res) => {
59
+ var _a;
60
+ (_a = this.abortTimeout) === null || _a === void 0 ? void 0 : _a.clear();
61
+ return res;
62
+ })
63
+ .catch((error) => {
64
+ var _a;
65
+ (_a = this.abortTimeout) === null || _a === void 0 ? void 0 : _a.clear();
66
+ debug('request error: %o', error);
67
+ throw error;
68
+ });
69
+ // Note even an error status may send useful json data in response (which we want for logging)
70
+ let respData = undefined;
71
+ const isJson = (_a = response.headers.get('Content-Type')) === null || _a === void 0 ? void 0 : _a.includes('application/json');
72
+ if (isJson) {
73
+ respData = yield response.json().catch((error) => {
74
+ debug('response.json() error: %o', error);
75
+ });
76
+ }
77
+ else {
78
+ // if not JSON, just read the response as text
79
+ respData = yield response.text().catch((error) => {
80
+ debug('response.text() error: %o', error);
81
+ });
82
+ }
83
+ const debugResponse = {
84
+ status: response.status,
85
+ statusText: response.statusText,
86
+ headers: this.extractDebugHeaders(response.headers),
87
+ url: response.url,
88
+ redirected: response.redirected,
89
+ data: respData,
90
+ };
91
+ if (!response.ok) {
92
+ debug('response error: %o', debugResponse);
93
+ throw new Error(`HTTP ${response.status} ${response.statusText}`);
94
+ }
95
+ debug('response in %dms: %o', Date.now() - startTimestamp, debugResponse);
96
+ return Object.assign(Object.assign({}, response), { data: respData });
97
+ });
98
+ }
99
+ /**
100
+ * Perform a GET request
101
+ * @param {string} url The URL to request (may include query string)
102
+ * @param {RequestInit} [options] Fetch options
103
+ * @returns {Promise<NativeDataFetcherResponse<T>>} response
104
+ */
105
+ get(url, options = {}) {
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ return this.fetch(url, Object.assign({ method: 'GET' }, options));
108
+ });
109
+ }
110
+ /**
111
+ * Perform a POST request
112
+ * @param {string} url The URL to request (may include query string)
113
+ * @param {unknown} body The data to send with the request
114
+ * @param {RequestInit} [options] Fetch options
115
+ * @returns {Promise<NativeDataFetcherResponse<T>>} response
116
+ */
117
+ post(url, body, options = {}) {
118
+ return __awaiter(this, void 0, void 0, function* () {
119
+ return this.fetch(url, Object.assign({ method: 'POST', body: JSON.stringify(body) }, options));
120
+ });
121
+ }
122
+ /**
123
+ * Perform a DELETE request
124
+ * @param {string} url The URL to request (may include query string)
125
+ * @param {RequestInit} [options] Fetch options
126
+ * @returns {Promise<NativeDataFetcherResponse<T>>} response
127
+ */
128
+ delete(url, options = {}) {
129
+ return __awaiter(this, void 0, void 0, function* () {
130
+ return this.fetch(url, Object.assign({ method: 'DELETE' }, options));
131
+ });
132
+ }
133
+ /**
134
+ * Perform a PUT request
135
+ * @param {string} url The URL to request (may include query string)
136
+ * @param {unknown} body The data to send with the request
137
+ * @param {RequestInit} [options] Fetch options
138
+ * @returns {Promise<NativeDataFetcherResponse<T>>} response
139
+ */
140
+ put(url, body, options = {}) {
141
+ return __awaiter(this, void 0, void 0, function* () {
142
+ return this.fetch(url, Object.assign({ method: 'PUT', body: JSON.stringify(body) }, options));
143
+ });
144
+ }
145
+ /**
146
+ * Perform a HEAD request
147
+ * @param {string} url The URL to request (may include query string)
148
+ * @param {RequestInit} [options] Fetch options
149
+ * @returns {Promise<NativeDataFetcherResponse<T>>} response
150
+ */
151
+ head(url, options = {}) {
152
+ return this.fetch(url, Object.assign({ method: 'HEAD' }, options));
153
+ }
154
+ /**
155
+ * Determines settings for the request
156
+ * @param {RequestInit} init Custom settings for request
157
+ * @returns {RequestInit} The final request settings
158
+ */
159
+ getRequestInit(init = {}) {
160
+ const headers = new Headers(init.headers);
161
+ if (!init.method) {
162
+ init.method = init.body ? 'POST' : 'GET';
163
+ }
164
+ headers.set('Content-Type', 'application/json');
165
+ init.headers = headers;
166
+ return init;
167
+ }
168
+ /**
169
+ * Safely extract all headers for debug logging
170
+ * @param {HeadersInit} incomingHeaders Incoming headers
171
+ * @returns Object with headers as key/value pairs
172
+ */
173
+ extractDebugHeaders(incomingHeaders = {}) {
174
+ const headers = {};
175
+ if (typeof (incomingHeaders === null || incomingHeaders === void 0 ? void 0 : incomingHeaders.forEach) !== 'string' && incomingHeaders.forEach) {
176
+ incomingHeaders === null || incomingHeaders === void 0 ? void 0 : incomingHeaders.forEach((value, key) => {
177
+ headers[key] = value;
178
+ });
179
+ }
180
+ return headers;
181
+ }
182
+ }
183
+ exports.NativeDataFetcher = NativeDataFetcher;
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.GraphQLPersonalizeService = void 0;
16
+ const debug_1 = __importDefault(require("../debug"));
17
+ const utils_1 = require("../utils");
18
+ const utils_2 = require("./utils");
19
+ const cache_client_1 = require("../cache-client");
20
+ class GraphQLPersonalizeService {
21
+ /**
22
+ * Fetch personalize data using the Sitecore GraphQL endpoint.
23
+ * @param {GraphQLPersonalizeServiceConfig} config
24
+ */
25
+ constructor(config) {
26
+ this.config = config;
27
+ this.config.timeout = config.timeout || 400;
28
+ this.graphQLClient = this.getGraphQLClient();
29
+ this.cache = this.getCacheClient();
30
+ }
31
+ get query() {
32
+ return /* GraphQL */ `
33
+ query($siteName: String!, $language: String!, $itemPath: String!) {
34
+ layout(site: $siteName, routePath: $itemPath, language: $language) {
35
+ item {
36
+ id
37
+ version
38
+ personalization {
39
+ variantIds
40
+ }
41
+ }
42
+ }
43
+ }
44
+ `;
45
+ }
46
+ /**
47
+ * Get personalize information for a route
48
+ * @param {string} itemPath page route
49
+ * @param {string} language language
50
+ * @param {string} siteName site name
51
+ * @returns {Promise<PersonalizeInfo | undefined>} the personalize information or undefined (if itemPath / language not found)
52
+ */
53
+ getPersonalizeInfo(itemPath, language, siteName) {
54
+ var _a;
55
+ return __awaiter(this, void 0, void 0, function* () {
56
+ debug_1.default.personalize('fetching personalize info for %s %s %s', siteName, itemPath, language);
57
+ const cacheKey = this.getCacheKey(itemPath, language, siteName);
58
+ let data = this.cache.getCacheValue(cacheKey);
59
+ if (!data) {
60
+ try {
61
+ data = yield this.graphQLClient.request(this.query, {
62
+ siteName,
63
+ itemPath,
64
+ language,
65
+ });
66
+ this.cache.setCacheValue(cacheKey, data);
67
+ }
68
+ catch (error) {
69
+ if (utils_1.isTimeoutError(error)) {
70
+ return undefined;
71
+ }
72
+ throw error;
73
+ }
74
+ }
75
+ return ((_a = data === null || data === void 0 ? void 0 : data.layout) === null || _a === void 0 ? void 0 : _a.item)
76
+ ? {
77
+ // CDP expects content id format `embedded_[<scope>_]<id>_<lang>` (lowercase)
78
+ contentId: utils_2.CdpHelper.getContentId(data.layout.item.id, language, this.config.scope),
79
+ variantIds: data.layout.item.personalization.variantIds,
80
+ }
81
+ : undefined;
82
+ });
83
+ }
84
+ /**
85
+ * Gets cache client implementation
86
+ * Override this method if custom cache needs to be used
87
+ * @returns CacheClient instance
88
+ */
89
+ getCacheClient() {
90
+ var _a, _b;
91
+ return new cache_client_1.MemoryCacheClient({
92
+ cacheEnabled: (_a = this.config.cacheEnabled) !== null && _a !== void 0 ? _a : true,
93
+ cacheTimeout: (_b = this.config.cacheTimeout) !== null && _b !== void 0 ? _b : 10,
94
+ });
95
+ }
96
+ getCacheKey(itemPath, language, siteName) {
97
+ return `${siteName}-${itemPath}-${language}`;
98
+ }
99
+ /**
100
+ * Gets a GraphQL client that can make requests to the API.
101
+ * @returns {GraphQLClient} implementation
102
+ */
103
+ getGraphQLClient() {
104
+ if (!this.config.clientFactory) {
105
+ throw new Error('You should provide a clientFactory.');
106
+ }
107
+ return this.config.clientFactory({
108
+ debugger: debug_1.default.personalize,
109
+ fetch: this.config.fetch,
110
+ timeout: this.config.timeout,
111
+ });
112
+ }
113
+ }
114
+ exports.GraphQLPersonalizeService = GraphQLPersonalizeService;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CdpHelper = exports.normalizePersonalizedRewrite = exports.getPersonalizedRewriteData = exports.getPersonalizedRewrite = exports.GraphQLPersonalizeService = exports.personalizeLayout = void 0;
4
+ var layout_personalizer_1 = require("./layout-personalizer");
5
+ Object.defineProperty(exports, "personalizeLayout", { enumerable: true, get: function () { return layout_personalizer_1.personalizeLayout; } });
6
+ var graphql_personalize_service_1 = require("./graphql-personalize-service");
7
+ Object.defineProperty(exports, "GraphQLPersonalizeService", { enumerable: true, get: function () { return graphql_personalize_service_1.GraphQLPersonalizeService; } });
8
+ var utils_1 = require("./utils");
9
+ Object.defineProperty(exports, "getPersonalizedRewrite", { enumerable: true, get: function () { return utils_1.getPersonalizedRewrite; } });
10
+ Object.defineProperty(exports, "getPersonalizedRewriteData", { enumerable: true, get: function () { return utils_1.getPersonalizedRewriteData; } });
11
+ Object.defineProperty(exports, "normalizePersonalizedRewrite", { enumerable: true, get: function () { return utils_1.normalizePersonalizedRewrite; } });
12
+ Object.defineProperty(exports, "CdpHelper", { enumerable: true, get: function () { return utils_1.CdpHelper; } });
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.personalizeComponent = exports.personalizePlaceholder = exports.personalizeLayout = void 0;
4
+ /**
5
+ * Apply personalization to layout data. This will recursively go through all placeholders/components, check experiences nodes and replace default with object from specific experience.
6
+ * @param {LayoutServiceData} layout Layout data
7
+ * @param {string} variantId variant id
8
+ */
9
+ function personalizeLayout(layout, variantId) {
10
+ var _a;
11
+ // Add 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 !== null && placeholders !== void 0 ? placeholders : {}).length === 0) {
15
+ return;
16
+ }
17
+ if (placeholders) {
18
+ Object.keys(placeholders).forEach((placeholder) => {
19
+ placeholders[placeholder] = personalizePlaceholder(placeholders[placeholder], variantId);
20
+ });
21
+ }
22
+ }
23
+ exports.personalizeLayout = personalizeLayout;
24
+ /**
25
+
26
+ * @param {Array} components components within placeholder
27
+ * @param {string} variantId variant id
28
+ * @returns {Array<ComponentRendering | HtmlElementRendering>} components with personalization applied
29
+ */
30
+ function personalizePlaceholder(components, variantId) {
31
+ return components
32
+ .map((component) => {
33
+ const rendering = component;
34
+ if (rendering.experiences !== undefined) {
35
+ return personalizeComponent(rendering, variantId);
36
+ }
37
+ else if (rendering.placeholders) {
38
+ const placeholders = rendering.placeholders;
39
+ Object.keys(placeholders).forEach((placeholder) => {
40
+ placeholders[placeholder] = personalizePlaceholder(placeholders[placeholder], variantId);
41
+ });
42
+ }
43
+ return component;
44
+ })
45
+ .filter(Boolean);
46
+ }
47
+ exports.personalizePlaceholder = personalizePlaceholder;
48
+ /**
49
+ * @param {ComponentRenderingWithExperiences} component component with experiences
50
+ * @param {string} variantId variant id
51
+ * @returns {ComponentRendering | null} component with personalization applied or null if hidden
52
+ */
53
+ function personalizeComponent(component, variantId) {
54
+ const variant = component.experiences[variantId];
55
+ if (variant === undefined && component.componentName === undefined) {
56
+ // DEFAULT IS HIDDEN
57
+ return null;
58
+ }
59
+ else if (variant && variant.componentName === null && variant.dataSource === null) {
60
+ // HIDDEN
61
+ return null;
62
+ }
63
+ else if (variant) {
64
+ component = variant;
65
+ }
66
+ if (!component.placeholders)
67
+ return component;
68
+ Object.keys(component === null || component === void 0 ? void 0 : component.placeholders).forEach((placeholder) => {
69
+ if (component.placeholders) {
70
+ component.placeholders[placeholder] = personalizePlaceholder(component.placeholders[placeholder], variantId);
71
+ }
72
+ });
73
+ return component;
74
+ }
75
+ exports.personalizeComponent = personalizeComponent;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CdpHelper = exports.normalizePersonalizedRewrite = exports.getPersonalizedRewriteData = exports.getPersonalizedRewrite = exports.VARIANT_PREFIX = exports.DEFAULT_VARIANT = void 0;
4
+ exports.DEFAULT_VARIANT = '_default';
5
+ exports.VARIANT_PREFIX = '_variantId_';
6
+ /**
7
+ * Get a personalized rewrite path for given pathname
8
+ * @param {string} pathname the pathname
9
+ * @param {PersonalizedRewriteData} data the personalize data to include in the rewrite
10
+ * @returns {string} the rewrite path
11
+ */
12
+ function getPersonalizedRewrite(pathname, data) {
13
+ const path = pathname.startsWith('/') ? pathname : '/' + pathname;
14
+ return `/${exports.VARIANT_PREFIX}${data.variantId}${path}`;
15
+ }
16
+ exports.getPersonalizedRewrite = getPersonalizedRewrite;
17
+ /**
18
+ * Get personalize data from the rewrite path
19
+ * @param {string} pathname the pathname
20
+ * @returns {PersonalizedRewriteData} the personalize data from the rewrite
21
+ */
22
+ function getPersonalizedRewriteData(pathname) {
23
+ const data = {
24
+ variantId: exports.DEFAULT_VARIANT,
25
+ };
26
+ const path = pathname.endsWith('/') ? pathname : pathname + '/';
27
+ const result = path.match(`${exports.VARIANT_PREFIX}(.*?)\\/`);
28
+ if (result) {
29
+ data.variantId = result[1];
30
+ }
31
+ return data;
32
+ }
33
+ exports.getPersonalizedRewriteData = getPersonalizedRewriteData;
34
+ /**
35
+ * Normalize a personalized rewrite path (remove personalize data)
36
+ * @param {string} pathname the pathname
37
+ * @returns {string} the pathname with personalize data removed
38
+ */
39
+ function normalizePersonalizedRewrite(pathname) {
40
+ if (!pathname.includes(exports.VARIANT_PREFIX)) {
41
+ return pathname;
42
+ }
43
+ const result = pathname.match(`${exports.VARIANT_PREFIX}.*?(?:\\/|$)`);
44
+ return result === null ? pathname : pathname.replace(result[0], '');
45
+ }
46
+ exports.normalizePersonalizedRewrite = normalizePersonalizedRewrite;
47
+ /**
48
+ * Static utility class for Sitecore CDP
49
+ */
50
+ class CdpHelper {
51
+ /**
52
+ * Gets the page variant id for CDP in the required format
53
+ * @param {string} pageId the page id
54
+ * @param {string} language the language
55
+ * @param {string} variantId the variant id
56
+ * @param {string} [scope] the scope value
57
+ * @returns {string} the formatted page variant id
58
+ */
59
+ static getPageVariantId(pageId, language, variantId, scope) {
60
+ const formattedPageId = pageId.replace(/[{}-]/g, '');
61
+ const formattedLanguage = language.replace('-', '_');
62
+ const scopeId = scope ? `${this.normalizeScope(scope)}_` : '';
63
+ let formattedVariantId = variantId;
64
+ if (!variantId || variantId === exports.DEFAULT_VARIANT) {
65
+ formattedVariantId = 'default';
66
+ }
67
+ return `${scopeId}${formattedPageId}_${formattedLanguage}_${formattedVariantId}`.toLowerCase();
68
+ }
69
+ /**
70
+ * Gets the content id for CDP in the required format `embedded_[<scope>_]<id>_<lang>`
71
+ * @param {string} pageId the page id
72
+ * @param {string} language the language
73
+ * @param {string} [scope] the scope value
74
+ * @returns {string} the content id
75
+ */
76
+ static getContentId(pageId, language, scope) {
77
+ const formattedPageId = pageId.replace(/[{}-]/g, '');
78
+ const formattedLanguage = language.replace('-', '_');
79
+ const scopeId = scope ? `${this.normalizeScope(scope)}_` : '';
80
+ return `embedded_${scopeId}${formattedPageId}_${formattedLanguage}`.toLowerCase();
81
+ }
82
+ /**
83
+ * Normalizes the scope from the given string value
84
+ * Removes all non-alphanumeric characters
85
+ * @param {string} [scope] the scope value
86
+ * @returns {string} normalized scope value
87
+ */
88
+ static normalizeScope(scope) {
89
+ return (scope === null || scope === void 0 ? void 0 : scope.replace(/[^a-zA-Z0-9]+/g, '')) || '';
90
+ }
91
+ }
92
+ exports.CdpHelper = CdpHelper;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.GraphQLErrorPagesService = void 0;
16
+ const constants_1 = require("../constants");
17
+ const debug_1 = __importDefault(require("../debug"));
18
+ // The default query for request error handling
19
+ const defaultQuery = /* GraphQL */ `
20
+ query ErrorPagesQuery($siteName: String!, $language: String!) {
21
+ site {
22
+ siteInfo(site: $siteName) {
23
+ errorHandling(language: $language) {
24
+ notFoundPage {
25
+ rendered
26
+ }
27
+ notFoundPagePath
28
+ serverErrorPage {
29
+ rendered
30
+ }
31
+ serverErrorPagePath
32
+ }
33
+ }
34
+ }
35
+ }
36
+ `;
37
+ /**
38
+ * Service that fetch the error pages data using Sitecore's GraphQL API.
39
+ */
40
+ class GraphQLErrorPagesService {
41
+ /**
42
+ * Creates an instance of graphQL error pages service with the provided options
43
+ * @param {GraphQLErrorPagesServiceConfig} options instance
44
+ */
45
+ constructor(options) {
46
+ this.options = options;
47
+ this.graphQLClient = this.getGraphQLClient();
48
+ }
49
+ get query() {
50
+ return defaultQuery;
51
+ }
52
+ /**
53
+ * Fetch list of error pages for the site
54
+ * @returns {ErrorPages} list of url's error pages
55
+ * @throws {Error} if the siteName is empty.
56
+ */
57
+ fetchErrorPages() {
58
+ return __awaiter(this, void 0, void 0, function* () {
59
+ const siteName = this.options.siteName;
60
+ const language = this.options.language;
61
+ if (!siteName) {
62
+ throw new Error(constants_1.siteNameError);
63
+ }
64
+ return this.graphQLClient.request(this.query, {
65
+ siteName,
66
+ language,
67
+ })
68
+ .then((result) => result.site.siteInfo ? result.site.siteInfo.errorHandling : null)
69
+ .catch((e) => Promise.reject(e));
70
+ });
71
+ }
72
+ /**
73
+ * Gets a GraphQL client that can make requests to the API.
74
+ * @returns {GraphQLClient} implementation
75
+ */
76
+ getGraphQLClient() {
77
+ if (!this.options.clientFactory) {
78
+ throw new Error('You should provide a clientFactory.');
79
+ }
80
+ return this.options.clientFactory({
81
+ debugger: debug_1.default.errorpages,
82
+ retries: this.options.retries,
83
+ });
84
+ }
85
+ }
86
+ exports.GraphQLErrorPagesService = GraphQLErrorPagesService;
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.GraphQLRedirectsService = exports.REDIRECT_TYPE_SERVER_TRANSFER = exports.REDIRECT_TYPE_302 = exports.REDIRECT_TYPE_301 = void 0;
16
+ const constants_1 = require("../constants");
17
+ const debug_1 = __importDefault(require("../debug"));
18
+ const cache_client_1 = require("../cache-client");
19
+ exports.REDIRECT_TYPE_301 = 'REDIRECT_301';
20
+ exports.REDIRECT_TYPE_302 = 'REDIRECT_302';
21
+ exports.REDIRECT_TYPE_SERVER_TRANSFER = 'SERVER_TRANSFER';
22
+ // The default query for request redirects of site
23
+ const defaultQuery = /* GraphQL */ `
24
+ query RedirectsQuery($siteName: String!) {
25
+ site {
26
+ siteInfo(site: $siteName) {
27
+ redirects {
28
+ pattern
29
+ target
30
+ redirectType
31
+ isQueryStringPreserved
32
+ locale
33
+ }
34
+ }
35
+ }
36
+ }
37
+ `;
38
+ /**
39
+ * The GraphQLRedirectsService class is used to query the JSS redirects using Graphql endpoint
40
+ */
41
+ class GraphQLRedirectsService {
42
+ /**
43
+ * Creates an instance of graphQL redirects service with the provided options
44
+ * @param {GraphQLRedirectsServiceConfig} options instance
45
+ */
46
+ constructor(options) {
47
+ this.options = options;
48
+ this.graphQLClient = this.getGraphQLClient();
49
+ this.cache = this.getCacheClient();
50
+ }
51
+ get query() {
52
+ return defaultQuery;
53
+ }
54
+ /**
55
+ * Fetch an array of redirects from API
56
+ * @param {string} siteName site name
57
+ * @returns Promise<RedirectInfo[]>
58
+ * @throws {Error} if the siteName is empty.
59
+ */
60
+ fetchRedirects(siteName) {
61
+ var _a, _b;
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ if (!siteName) {
64
+ throw new Error(constants_1.siteNameError);
65
+ }
66
+ const cacheKey = `redirects-${siteName}`;
67
+ let data = this.cache.getCacheValue(cacheKey);
68
+ if (!data) {
69
+ data = yield this.graphQLClient.request(this.query, {
70
+ siteName,
71
+ });
72
+ this.cache.setCacheValue(cacheKey, data);
73
+ }
74
+ 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) || [];
75
+ });
76
+ }
77
+ /**
78
+ * Gets a GraphQL client that can make requests to the API.
79
+ * @returns {GraphQLClient} implementation
80
+ */
81
+ getGraphQLClient() {
82
+ if (!this.options.clientFactory) {
83
+ throw new Error('You should provide a clientFactory.');
84
+ }
85
+ return this.options.clientFactory({
86
+ debugger: debug_1.default.redirects,
87
+ fetch: this.options.fetch,
88
+ });
89
+ }
90
+ /**
91
+ * Gets cache client implementation
92
+ * Override this method if custom cache needs to be used
93
+ * @returns CacheClient instance
94
+ */
95
+ getCacheClient() {
96
+ var _a, _b;
97
+ return new cache_client_1.MemoryCacheClient({
98
+ cacheEnabled: (_a = this.options.cacheEnabled) !== null && _a !== void 0 ? _a : true,
99
+ cacheTimeout: (_b = this.options.cacheTimeout) !== null && _b !== void 0 ? _b : 10,
100
+ });
101
+ }
102
+ }
103
+ exports.GraphQLRedirectsService = GraphQLRedirectsService;