@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.
- package/LICENSE.txt +202 -0
- package/README.md +7 -0
- package/dist/cjs/cache-client.js +54 -0
- package/dist/cjs/constants.js +12 -0
- package/dist/cjs/debug.js +43 -0
- package/dist/cjs/graphql/app-root-query.js +73 -0
- package/dist/cjs/graphql/graphql-edge-proxy.js +12 -0
- package/dist/cjs/graphql/index.js +11 -0
- package/dist/cjs/graphql/search-service.js +60 -0
- package/dist/cjs/graphql-request-client.js +106 -0
- package/dist/cjs/i18n/dictionary-service.js +45 -0
- package/dist/cjs/i18n/graphql-dictionary-service.js +125 -0
- package/dist/cjs/i18n/index.js +7 -0
- package/dist/cjs/index.js +36 -0
- package/dist/cjs/layout/content-styles.js +73 -0
- package/dist/cjs/layout/graphql-layout-service.js +84 -0
- package/dist/cjs/layout/index.js +18 -0
- package/dist/cjs/layout/layout-service.js +9 -0
- package/dist/cjs/layout/models.js +27 -0
- package/dist/cjs/layout/themes.js +79 -0
- package/dist/cjs/layout/utils.js +44 -0
- package/dist/cjs/media/index.js +24 -0
- package/dist/cjs/media/media-api.js +128 -0
- package/dist/cjs/models.js +2 -0
- package/dist/cjs/native-fetcher.js +183 -0
- package/dist/cjs/personalize/graphql-personalize-service.js +114 -0
- package/dist/cjs/personalize/index.js +12 -0
- package/dist/cjs/personalize/layout-personalizer.js +75 -0
- package/dist/cjs/personalize/utils.js +92 -0
- package/dist/cjs/site/graphql-error-pages-service.js +86 -0
- package/dist/cjs/site/graphql-redirects-service.js +103 -0
- package/dist/cjs/site/graphql-robots-service.js +81 -0
- package/dist/cjs/site/graphql-siteinfo-service.js +128 -0
- package/dist/cjs/site/graphql-sitemap-service.js +91 -0
- package/dist/cjs/site/index.js +22 -0
- package/dist/cjs/site/site-resolver.js +79 -0
- package/dist/cjs/site/utils.js +43 -0
- package/dist/cjs/utils/edit-frame.js +138 -0
- package/dist/cjs/utils/editing.js +122 -0
- package/dist/cjs/utils/env.js +26 -0
- package/dist/cjs/utils/index.js +25 -0
- package/dist/cjs/utils/is-server.js +10 -0
- package/dist/cjs/utils/timeout-promise.js +31 -0
- package/dist/cjs/utils/utils.js +70 -0
- package/dist/esm/cache-client.js +50 -0
- package/dist/esm/constants.js +9 -0
- package/dist/esm/debug.js +36 -0
- package/dist/esm/graphql/app-root-query.js +69 -0
- package/dist/esm/graphql/graphql-edge-proxy.js +8 -0
- package/dist/esm/graphql/index.js +4 -0
- package/dist/esm/graphql/search-service.js +56 -0
- package/dist/esm/graphql-request-client.js +99 -0
- package/dist/esm/i18n/dictionary-service.js +41 -0
- package/dist/esm/i18n/graphql-dictionary-service.js +118 -0
- package/dist/esm/i18n/index.js +2 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/layout/content-styles.js +65 -0
- package/dist/esm/layout/graphql-layout-service.js +77 -0
- package/dist/esm/layout/index.js +6 -0
- package/dist/esm/layout/layout-service.js +5 -0
- package/dist/esm/layout/models.js +24 -0
- package/dist/esm/layout/themes.js +74 -0
- package/dist/esm/layout/utils.js +39 -0
- package/dist/esm/media/index.js +2 -0
- package/dist/esm/media/media-api.js +117 -0
- package/dist/esm/models.js +1 -0
- package/dist/esm/native-fetcher.js +176 -0
- package/dist/esm/personalize/graphql-personalize-service.js +107 -0
- package/dist/esm/personalize/index.js +3 -0
- package/dist/esm/personalize/layout-personalizer.js +69 -0
- package/dist/esm/personalize/utils.js +85 -0
- package/dist/esm/site/graphql-error-pages-service.js +79 -0
- package/dist/esm/site/graphql-redirects-service.js +96 -0
- package/dist/esm/site/graphql-robots-service.js +74 -0
- package/dist/esm/site/graphql-siteinfo-service.js +121 -0
- package/dist/esm/site/graphql-sitemap-service.js +84 -0
- package/dist/esm/site/index.js +7 -0
- package/dist/esm/site/site-resolver.js +75 -0
- package/dist/esm/site/utils.js +37 -0
- package/dist/esm/utils/edit-frame.js +133 -0
- package/dist/esm/utils/editing.js +111 -0
- package/dist/esm/utils/env.js +22 -0
- package/dist/esm/utils/index.js +5 -0
- package/dist/esm/utils/is-server.js +8 -0
- package/dist/esm/utils/timeout-promise.js +28 -0
- package/dist/esm/utils/utils.js +61 -0
- package/graphql.d.ts +1 -0
- package/graphql.js +1 -0
- package/i18n.d.ts +1 -0
- package/i18n.js +1 -0
- package/layout.d.ts +1 -0
- package/layout.js +1 -0
- package/media.d.ts +1 -0
- package/media.js +1 -0
- package/package.json +71 -0
- package/personalize.d.ts +1 -0
- package/personalize.js +1 -0
- package/site.d.ts +1 -0
- package/site.js +1 -0
- package/types/cache-client.d.ts +64 -0
- package/types/constants.d.ts +6 -0
- package/types/debug.d.ts +26 -0
- package/types/graphql/app-root-query.d.ts +32 -0
- package/types/graphql/graphql-edge-proxy.d.ts +7 -0
- package/types/graphql/index.d.ts +4 -0
- package/types/graphql/search-service.d.ts +92 -0
- package/types/graphql-request-client.d.ts +88 -0
- package/types/i18n/dictionary-service.d.ts +56 -0
- package/types/i18n/graphql-dictionary-service.d.ts +65 -0
- package/types/i18n/index.d.ts +2 -0
- package/types/index.d.ts +6 -0
- package/types/layout/content-styles.d.ts +18 -0
- package/types/layout/graphql-layout-service.d.ts +59 -0
- package/types/layout/index.d.ts +6 -0
- package/types/layout/layout-service.d.ts +20 -0
- package/types/layout/models.d.ts +140 -0
- package/types/layout/themes.d.ts +11 -0
- package/types/layout/utils.d.ts +17 -0
- package/types/media/index.d.ts +2 -0
- package/types/media/media-api.d.ts +69 -0
- package/types/models.d.ts +6 -0
- package/types/native-fetcher.d.ts +92 -0
- package/types/personalize/graphql-personalize-service.d.ts +77 -0
- package/types/personalize/index.d.ts +3 -0
- package/types/personalize/layout-personalizer.d.ts +25 -0
- package/types/personalize/utils.d.ts +53 -0
- package/types/site/graphql-error-pages-service.d.ts +55 -0
- package/types/site/graphql-redirects-service.d.ts +66 -0
- package/types/site/graphql-robots-service.d.ts +47 -0
- package/types/site/graphql-siteinfo-service.d.ts +69 -0
- package/types/site/graphql-sitemap-service.d.ts +53 -0
- package/types/site/index.d.ts +7 -0
- package/types/site/site-resolver.d.ts +27 -0
- package/types/site/utils.d.ts +24 -0
- package/types/utils/edit-frame.d.ts +76 -0
- package/types/utils/editing.d.ts +58 -0
- package/types/utils/env.d.ts +7 -0
- package/types/utils/index.d.ts +5 -0
- package/types/utils/is-server.d.ts +6 -0
- package/types/utils/timeout-promise.d.ts +18 -0
- package/types/utils/utils.d.ts +18 -0
- package/utils.d.ts +1 -0
- 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;
|