@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.
- package/LICENSE.txt +202 -0
- package/README.md +11 -0
- package/dist/cjs/cache-client.js +54 -0
- package/dist/cjs/constants.js +13 -0
- package/dist/cjs/data-fetcher.js +33 -0
- package/dist/cjs/debug.js +43 -0
- package/dist/cjs/editing/component-library.js +104 -0
- package/dist/cjs/editing/graphql-editing-service.js +186 -0
- package/dist/cjs/editing/index.js +23 -0
- package/dist/cjs/editing/models.js +23 -0
- package/dist/cjs/editing/rest-component-layout-service.js +76 -0
- package/dist/cjs/editing/utils.js +86 -0
- package/dist/cjs/graphql/app-root-query.js +73 -0
- package/dist/cjs/graphql/graphql-edge-proxy.js +21 -0
- package/dist/cjs/graphql/index.js +13 -0
- package/dist/cjs/graphql/search-service.js +61 -0
- package/dist/cjs/graphql-request-client.js +152 -0
- package/dist/cjs/i18n/dictionary-service.js +45 -0
- package/dist/cjs/i18n/graphql-dictionary-service.js +136 -0
- package/dist/cjs/i18n/index.js +7 -0
- package/dist/cjs/index.js +55 -0
- package/dist/cjs/layout/content-styles.js +70 -0
- package/dist/cjs/layout/graphql-layout-service.js +86 -0
- package/dist/cjs/layout/index.js +24 -0
- package/dist/cjs/layout/layout-service.js +9 -0
- package/dist/cjs/layout/models.js +35 -0
- package/dist/cjs/layout/themes.js +74 -0
- package/dist/cjs/layout/utils.js +110 -0
- package/dist/cjs/media/index.js +38 -0
- package/dist/cjs/media/media-api.js +96 -0
- package/dist/cjs/models.js +2 -0
- package/dist/cjs/native-fetcher.js +200 -0
- package/dist/cjs/personalize/graphql-personalize-service.js +114 -0
- package/dist/cjs/personalize/index.js +14 -0
- package/dist/cjs/personalize/layout-personalizer.js +97 -0
- package/dist/cjs/personalize/utils.js +136 -0
- package/dist/cjs/site/graphql-error-pages-service.js +89 -0
- package/dist/cjs/site/graphql-redirects-service.js +105 -0
- package/dist/cjs/site/graphql-robots-service.js +83 -0
- package/dist/cjs/site/graphql-siteinfo-service.js +107 -0
- package/dist/cjs/site/graphql-sitemap-service.js +93 -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/env.js +26 -0
- package/dist/cjs/utils/index.js +20 -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 +222 -0
- package/dist/esm/cache-client.js +50 -0
- package/dist/esm/constants.js +10 -0
- package/dist/esm/data-fetcher.js +28 -0
- package/dist/esm/debug.js +36 -0
- package/dist/esm/editing/component-library.js +98 -0
- package/dist/esm/editing/graphql-editing-service.js +179 -0
- package/dist/esm/editing/index.js +5 -0
- package/dist/esm/editing/models.js +20 -0
- package/dist/esm/editing/rest-component-layout-service.js +72 -0
- package/dist/esm/editing/utils.js +76 -0
- package/dist/esm/graphql/app-root-query.js +69 -0
- package/dist/esm/graphql/graphql-edge-proxy.js +16 -0
- package/dist/esm/graphql/index.js +4 -0
- package/dist/esm/graphql/search-service.js +57 -0
- package/dist/esm/graphql-request-client.js +144 -0
- package/dist/esm/i18n/dictionary-service.js +41 -0
- package/dist/esm/i18n/graphql-dictionary-service.js +129 -0
- package/dist/esm/i18n/index.js +2 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/layout/content-styles.js +62 -0
- package/dist/esm/layout/graphql-layout-service.js +79 -0
- package/dist/esm/layout/index.js +6 -0
- package/dist/esm/layout/layout-service.js +5 -0
- package/dist/esm/layout/models.js +32 -0
- package/dist/esm/layout/themes.js +69 -0
- package/dist/esm/layout/utils.js +102 -0
- package/dist/esm/media/index.js +2 -0
- package/dist/esm/media/media-api.js +86 -0
- package/dist/esm/models.js +1 -0
- package/dist/esm/native-fetcher.js +193 -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 +92 -0
- package/dist/esm/personalize/utils.js +128 -0
- package/dist/esm/site/graphql-error-pages-service.js +82 -0
- package/dist/esm/site/graphql-redirects-service.js +98 -0
- package/dist/esm/site/graphql-robots-service.js +76 -0
- package/dist/esm/site/graphql-siteinfo-service.js +100 -0
- package/dist/esm/site/graphql-sitemap-service.js +86 -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/env.js +22 -0
- package/dist/esm/utils/index.js +3 -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 +207 -0
- package/editing.d.ts +1 -0
- package/editing.js +1 -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 +76 -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 +7 -0
- package/types/data-fetcher.d.ts +34 -0
- package/types/debug.d.ts +26 -0
- package/types/editing/component-library.d.ts +48 -0
- package/types/editing/graphql-editing-service.d.ts +90 -0
- package/types/editing/index.d.ts +6 -0
- package/types/editing/models.d.ts +52 -0
- package/types/editing/rest-component-layout-service.d.ts +100 -0
- package/types/editing/utils.d.ts +70 -0
- package/types/graphql/app-root-query.d.ts +32 -0
- package/types/graphql/graphql-edge-proxy.d.ts +15 -0
- package/types/graphql/index.d.ts +4 -0
- package/types/graphql/search-service.d.ts +95 -0
- package/types/graphql-request-client.d.ts +159 -0
- package/types/i18n/dictionary-service.d.ts +56 -0
- package/types/i18n/graphql-dictionary-service.d.ts +94 -0
- package/types/i18n/index.d.ts +2 -0
- package/types/index.d.ts +8 -0
- package/types/layout/content-styles.d.ts +18 -0
- package/types/layout/graphql-layout-service.d.ts +58 -0
- package/types/layout/index.d.ts +6 -0
- package/types/layout/layout-service.d.ts +19 -0
- package/types/layout/models.d.ts +145 -0
- package/types/layout/themes.d.ts +11 -0
- package/types/layout/utils.d.ts +40 -0
- package/types/media/index.d.ts +2 -0
- package/types/media/media-api.d.ts +55 -0
- package/types/models.d.ts +6 -0
- package/types/native-fetcher.d.ts +121 -0
- package/types/personalize/graphql-personalize-service.d.ts +80 -0
- package/types/personalize/index.d.ts +3 -0
- package/types/personalize/layout-personalizer.d.ts +27 -0
- package/types/personalize/utils.d.ts +69 -0
- package/types/site/graphql-error-pages-service.d.ts +57 -0
- package/types/site/graphql-redirects-service.d.ts +68 -0
- package/types/site/graphql-robots-service.d.ts +49 -0
- package/types/site/graphql-siteinfo-service.d.ts +70 -0
- package/types/site/graphql-sitemap-service.d.ts +55 -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/env.d.ts +7 -0
- package/types/utils/index.d.ts +3 -0
- package/types/utils/is-server.d.ts +6 -0
- package/types/utils/timeout-promise.d.ts +17 -0
- package/types/utils/utils.d.ts +71 -0
- package/utils.d.ts +1 -0
- package/utils.js +1 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Determines whether the current execution context is server-side
|
|
5
|
+
* @returns true if executing server-side
|
|
6
|
+
*/
|
|
7
|
+
function isServer() {
|
|
8
|
+
return !(typeof window !== 'undefined' && window.document);
|
|
9
|
+
}
|
|
10
|
+
exports.default = isServer;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* A helper to assign timeouts to fetch or other promises
|
|
5
|
+
* Useful in nextjs middleware until fetch.signal is fully supported by Vercel edge functions
|
|
6
|
+
*/
|
|
7
|
+
class TimeoutPromise {
|
|
8
|
+
constructor(timeout) {
|
|
9
|
+
this.timeout = timeout;
|
|
10
|
+
this.timeoutId = undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a timeout promise
|
|
14
|
+
*/
|
|
15
|
+
get start() {
|
|
16
|
+
return new Promise((_, reject) => {
|
|
17
|
+
this.timeoutId = setTimeout(() => {
|
|
18
|
+
const abortError = new Error(`Request timed out, timeout of ${this.timeout}ms is exceeded`);
|
|
19
|
+
abortError.name = 'AbortError';
|
|
20
|
+
reject(abortError);
|
|
21
|
+
}, this.timeout);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Clears the timeout from timeout promise
|
|
26
|
+
*/
|
|
27
|
+
clear() {
|
|
28
|
+
this.timeoutId && clearTimeout(this.timeoutId);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.default = TimeoutPromise;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.mergeURLSearchParams = exports.escapeNonSpecialQuestionMarks = exports.areURLSearchParamsEqual = exports.isRegexOrUrl = exports.enforceCors = exports.getAllowedOriginsFromEnv = exports.isTimeoutError = exports.isAbsoluteUrl = void 0;
|
|
7
|
+
exports.resolveUrl = resolveUrl;
|
|
8
|
+
const is_server_1 = __importDefault(require("./is-server"));
|
|
9
|
+
/**
|
|
10
|
+
* note: encodeURIComponent is available via browser (window) or natively in node.js
|
|
11
|
+
* if you use another js engine for server-side rendering you may not have native encodeURIComponent
|
|
12
|
+
* and would then need to install a package for that functionality
|
|
13
|
+
* @param {ParsedUrlQueryInput} params query string parameters
|
|
14
|
+
* @returns {string} query string
|
|
15
|
+
*/
|
|
16
|
+
function getQueryString(params) {
|
|
17
|
+
return Object.keys(params)
|
|
18
|
+
.map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(String(params[k]))}`)
|
|
19
|
+
.join('&');
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resolves a base URL that may contain query string parameters and an additional set of query
|
|
23
|
+
* string parameters into a unified string representation.
|
|
24
|
+
* @param {string} urlBase the base URL that may contain query string parameters
|
|
25
|
+
* @param {ParsedUrlQueryInput} params query string parameters
|
|
26
|
+
* @returns a URL string
|
|
27
|
+
* @throws {RangeError} if the provided url is an empty string
|
|
28
|
+
*/
|
|
29
|
+
function resolveUrl(urlBase, params = {}) {
|
|
30
|
+
if (!urlBase) {
|
|
31
|
+
throw new RangeError('url must be a non-empty string');
|
|
32
|
+
}
|
|
33
|
+
// This is a better way to work with URLs since it handles different user input
|
|
34
|
+
// edge cases. This works in Node and all browser except IE11.
|
|
35
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/URL
|
|
36
|
+
// TODO: Verify our browser support requirements.
|
|
37
|
+
if ((0, is_server_1.default)()) {
|
|
38
|
+
const url = new URL(urlBase);
|
|
39
|
+
for (const key in params) {
|
|
40
|
+
if ({}.hasOwnProperty.call(params, key)) {
|
|
41
|
+
url.searchParams.append(key, String(params[key]));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const result = url.toString();
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
const qs = getQueryString(params);
|
|
48
|
+
const result = urlBase.indexOf('?') !== -1 ? `${urlBase}&${qs}` : `${urlBase}?${qs}`;
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
const isAbsoluteUrl = (url) => {
|
|
52
|
+
if (!url) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (typeof url !== 'string') {
|
|
56
|
+
throw new TypeError('Expected a string');
|
|
57
|
+
}
|
|
58
|
+
return /^[a-z][a-z0-9+.-]*:/.test(url);
|
|
59
|
+
};
|
|
60
|
+
exports.isAbsoluteUrl = isAbsoluteUrl;
|
|
61
|
+
/**
|
|
62
|
+
* Indicates whether the error is a timeout error
|
|
63
|
+
* @param {unknown} error error
|
|
64
|
+
* @returns {boolean} is timeout error
|
|
65
|
+
*/
|
|
66
|
+
const isTimeoutError = (error) => {
|
|
67
|
+
var _a;
|
|
68
|
+
return ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 408 || error.name === 'AbortError';
|
|
69
|
+
};
|
|
70
|
+
exports.isTimeoutError = isTimeoutError;
|
|
71
|
+
/**
|
|
72
|
+
* Converts a string value in a regex pattern allowing wildcard matching
|
|
73
|
+
* @param {string} pattern input with wildcards i.e. site.*.com
|
|
74
|
+
* @returns {string} modified string that can be used as regexp input
|
|
75
|
+
*/
|
|
76
|
+
const convertToWildcardRegex = (pattern) => {
|
|
77
|
+
return ('^' +
|
|
78
|
+
pattern
|
|
79
|
+
.replace(/\//g, '\\/')
|
|
80
|
+
.replace(/\./g, '\\.')
|
|
81
|
+
.replace(/\*/g, '.*') +
|
|
82
|
+
'$');
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Gets allowed origins from JSS_ALLOWED_ORIGINS env variable
|
|
86
|
+
* @returns {string[]} list of allowed origins from JSS_ALLOWED_ORIGINS env variable
|
|
87
|
+
*/
|
|
88
|
+
const getAllowedOriginsFromEnv = () => process.env.JSS_ALLOWED_ORIGINS
|
|
89
|
+
? process.env.JSS_ALLOWED_ORIGINS.replace(' ', '').split(',')
|
|
90
|
+
: [];
|
|
91
|
+
exports.getAllowedOriginsFromEnv = getAllowedOriginsFromEnv;
|
|
92
|
+
/**
|
|
93
|
+
* Tests origin from incoming request against allowed origins list that can be
|
|
94
|
+
* set in JSS's JSS_ALLOWED_ORIGINS env variable, passed via allowedOrigins param and/or
|
|
95
|
+
* be already set in Access-Control-Allow-Origin by other logic.
|
|
96
|
+
* Applies Access-Control-Allow-Origin and Access-Control-Allow-Methods on match
|
|
97
|
+
* Also applies Access-Control-Allow-Headers for preflight requests
|
|
98
|
+
* @param {IncomingMessage} req incoming request
|
|
99
|
+
* @param {OutgoingMessage} res response to set CORS headers for
|
|
100
|
+
* @param {string[]} [allowedOrigins] additional list of origins to test against
|
|
101
|
+
* @returns true if incoming origin matches the allowed lists, false when it does not
|
|
102
|
+
*/
|
|
103
|
+
const enforceCors = (req, res, allowedOrigins) => {
|
|
104
|
+
// origin in not present for non-CORS requests (e.g. server-side) - so we skip the checks
|
|
105
|
+
if (!req.headers.origin) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
// 3 sources of allowed origins are considered:
|
|
109
|
+
// the env value
|
|
110
|
+
const defaultAllowedOrigins = (0, exports.getAllowedOriginsFromEnv)();
|
|
111
|
+
// the allowedOrigins prop
|
|
112
|
+
allowedOrigins = defaultAllowedOrigins.concat(allowedOrigins || []);
|
|
113
|
+
// and the existing CORS header, if present (i.e. set by nextjs config)
|
|
114
|
+
const presetCors = res.getHeader('Access-Control-Allow-Origin');
|
|
115
|
+
if (presetCors) {
|
|
116
|
+
allowedOrigins.push(presetCors);
|
|
117
|
+
}
|
|
118
|
+
const origin = req.headers.origin;
|
|
119
|
+
if (origin &&
|
|
120
|
+
allowedOrigins.some((allowedOrigin) => origin === allowedOrigin || new RegExp(convertToWildcardRegex(allowedOrigin)).test(origin))) {
|
|
121
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
122
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE, PUT, PATCH');
|
|
123
|
+
// set the allowed headers for preflight requests
|
|
124
|
+
if (req.method === 'OPTIONS') {
|
|
125
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
126
|
+
}
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
return false;
|
|
130
|
+
};
|
|
131
|
+
exports.enforceCors = enforceCors;
|
|
132
|
+
/**
|
|
133
|
+
* Determines whether the given input is a regular expression or resembles a URL.
|
|
134
|
+
* @param {string} input - The input string to evaluate.
|
|
135
|
+
* @returns {'regex' | 'url'} - Returns 'url' if the input looks like a URL, otherwise 'regex'.
|
|
136
|
+
*/
|
|
137
|
+
const isRegexOrUrl = (input) => {
|
|
138
|
+
// Remove the trailing slash.
|
|
139
|
+
input = input.slice(0, -1);
|
|
140
|
+
// Check if the string resembles a URL.
|
|
141
|
+
const isUrlLike = /^\/[a-zA-Z0-9\-\/]+(\?([a-zA-Z0-9\-_]+=[a-zA-Z0-9\-_]+)(&[a-zA-Z0-9\-_]+=[a-zA-Z0-9\-_]+)*)?$/.test(input);
|
|
142
|
+
if (isUrlLike) {
|
|
143
|
+
return 'url';
|
|
144
|
+
}
|
|
145
|
+
// If it doesn't resemble a URL, it's likely a regular expression.
|
|
146
|
+
return 'regex';
|
|
147
|
+
};
|
|
148
|
+
exports.isRegexOrUrl = isRegexOrUrl;
|
|
149
|
+
/**
|
|
150
|
+
* Compares two URLSearchParams objects to determine if they are equal.
|
|
151
|
+
* @param {URLSearchParams} params1 - The first set of URL search parameters.
|
|
152
|
+
* @param {URLSearchParams} params2 - The second set of URL search parameters.
|
|
153
|
+
* @returns {boolean} - Returns true if the parameters are equal, otherwise false.
|
|
154
|
+
*/
|
|
155
|
+
const areURLSearchParamsEqual = (params1, params2) => {
|
|
156
|
+
// Generates a sorted string representation of URL search parameters.
|
|
157
|
+
const getSortedParamsString = (params) => {
|
|
158
|
+
return [...params.entries()]
|
|
159
|
+
.sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
|
|
160
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
161
|
+
.join('&');
|
|
162
|
+
};
|
|
163
|
+
// Compare the sorted strings of both parameter sets.
|
|
164
|
+
return getSortedParamsString(params1) === getSortedParamsString(params2);
|
|
165
|
+
};
|
|
166
|
+
exports.areURLSearchParamsEqual = areURLSearchParamsEqual;
|
|
167
|
+
/**
|
|
168
|
+
* Escapes non-special "?" characters in a string or regex.
|
|
169
|
+
* - For regular strings, it escapes all unescaped "?" characters by adding a backslash (`\`).
|
|
170
|
+
* - For regex patterns (strings enclosed in `/.../`), it analyzes each "?" to determine if it has special meaning
|
|
171
|
+
* (e.g., `?` in `(abc)?`, `.*?`, `(?!...)`) or is just a literal character. Only literal "?" characters are escaped.
|
|
172
|
+
* @param {string} input - The input string or regex pattern.
|
|
173
|
+
* @returns {string} - The modified string or regex with non-special "?" characters escaped.
|
|
174
|
+
*/
|
|
175
|
+
const escapeNonSpecialQuestionMarks = (input) => {
|
|
176
|
+
const regexPattern = /(?<!\\)\?/g; // Match unescaped "?" characters
|
|
177
|
+
const negativeLookaheadPattern = /\(\?!$/; // Detect the start of a Negative Lookahead pattern
|
|
178
|
+
const specialRegexSymbols = /[.*+)\[\]|\(]$/; // Check for special regex symbols before "?"
|
|
179
|
+
let result = '';
|
|
180
|
+
let lastIndex = 0;
|
|
181
|
+
let match;
|
|
182
|
+
while ((match = regexPattern.exec(input)) !== null) {
|
|
183
|
+
const index = match.index; // Position of the "?" in the string
|
|
184
|
+
const before = input.slice(lastIndex, index); // Context before the "?"
|
|
185
|
+
// Check if "?" is part of a Negative Lookahead
|
|
186
|
+
const isNegativeLookahead = negativeLookaheadPattern.test(before.slice(-3));
|
|
187
|
+
// Check if "?" follows a special regex symbol
|
|
188
|
+
const isSpecialRegexSymbol = specialRegexSymbols.test(before.slice(-1));
|
|
189
|
+
if (isNegativeLookahead || isSpecialRegexSymbol) {
|
|
190
|
+
// If it's a special case, keep the "?" as is
|
|
191
|
+
result += input.slice(lastIndex, index + 1);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
// Otherwise, escape the "?"
|
|
195
|
+
result += input.slice(lastIndex, index) + '\\?';
|
|
196
|
+
}
|
|
197
|
+
lastIndex = index + 1; // Move to the next part of the string
|
|
198
|
+
}
|
|
199
|
+
// Append the remaining part of the string
|
|
200
|
+
result += input.slice(lastIndex);
|
|
201
|
+
return result;
|
|
202
|
+
};
|
|
203
|
+
exports.escapeNonSpecialQuestionMarks = escapeNonSpecialQuestionMarks;
|
|
204
|
+
/**
|
|
205
|
+
* Merges two URLSearchParams objects. If both objects contain the same key, the value from the second object overrides the first.
|
|
206
|
+
* @param {URLSearchParams} params1 - The first set of URL search parameters.
|
|
207
|
+
* @param {URLSearchParams} params2 - The second set of URL search parameters.
|
|
208
|
+
* @returns {string} - A string representation of the merged URL search parameters.
|
|
209
|
+
*/
|
|
210
|
+
const mergeURLSearchParams = (params1, params2) => {
|
|
211
|
+
const merged = new URLSearchParams();
|
|
212
|
+
// Add all keys and values from the first object.
|
|
213
|
+
for (const [key, value] of params1.entries()) {
|
|
214
|
+
merged.set(key, value);
|
|
215
|
+
}
|
|
216
|
+
// Add all keys and values from the second object, replacing existing ones.
|
|
217
|
+
for (const [key, value] of params2.entries()) {
|
|
218
|
+
merged.set(key, value);
|
|
219
|
+
}
|
|
220
|
+
return merged.toString();
|
|
221
|
+
};
|
|
222
|
+
exports.mergeURLSearchParams = mergeURLSearchParams;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Cache } from 'memory-cache';
|
|
2
|
+
/**
|
|
3
|
+
* Default cache configuration
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULTS = Object.freeze({
|
|
6
|
+
cacheTimeout: 60,
|
|
7
|
+
cacheEnabled: true,
|
|
8
|
+
});
|
|
9
|
+
/**
|
|
10
|
+
* A cache client that uses the 'memory-cache' library (https://github.com/ptarjan/node-cache).
|
|
11
|
+
* This class is meant to be extended or used as a mixin; it's not meant to be used directly.
|
|
12
|
+
* @template T The type of data being cached.
|
|
13
|
+
* @mixin
|
|
14
|
+
*/
|
|
15
|
+
export class MemoryCacheClient {
|
|
16
|
+
/**
|
|
17
|
+
* Initializes a new instance of @see MemoryCacheClient using the provided @see CacheOptions
|
|
18
|
+
* @param {CacheOptions} options Configuration options
|
|
19
|
+
*/
|
|
20
|
+
constructor(options) {
|
|
21
|
+
var _a;
|
|
22
|
+
this.options = options;
|
|
23
|
+
this.cache = new Cache();
|
|
24
|
+
this.options.cacheTimeout = ((_a = this.options.cacheTimeout) !== null && _a !== void 0 ? _a : DEFAULTS.cacheTimeout) * 1000;
|
|
25
|
+
if (this.options.cacheEnabled === undefined) {
|
|
26
|
+
this.options.cacheEnabled = DEFAULTS.cacheEnabled;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Retrieves a value from the cache.
|
|
31
|
+
* @template T The type of data being cached.
|
|
32
|
+
* @param {string} key The cache key.
|
|
33
|
+
* @returns The cache value as {T}, or null if the specified key is not found in the cache.
|
|
34
|
+
*/
|
|
35
|
+
getCacheValue(key) {
|
|
36
|
+
return this.options.cacheEnabled ? this.cache.get(key) : null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Adds a value to the cache for the specified cache key.
|
|
40
|
+
* @template T The type of data being cached.
|
|
41
|
+
* @param {string} key The cache key.
|
|
42
|
+
* @param {T} value The value to cache.
|
|
43
|
+
* @returns The value added to the cache.
|
|
44
|
+
*/
|
|
45
|
+
setCacheValue(key, value) {
|
|
46
|
+
return this.options.cacheEnabled
|
|
47
|
+
? this.cache.put(key, value, this.options.cacheTimeout)
|
|
48
|
+
: value;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export var SitecoreTemplateId;
|
|
2
|
+
(function (SitecoreTemplateId) {
|
|
3
|
+
// /sitecore/templates/Foundation/JavaScript Services/App
|
|
4
|
+
SitecoreTemplateId["JssApp"] = "061cba1554744b918a0617903b102b82";
|
|
5
|
+
// /sitecore/templates/System/Dictionary/Dictionary entry
|
|
6
|
+
SitecoreTemplateId["DictionaryEntry"] = "6d1cd89719364a3aa511289a94c2a7b1";
|
|
7
|
+
})(SitecoreTemplateId || (SitecoreTemplateId = {}));
|
|
8
|
+
export const siteNameError = 'The siteName cannot be empty';
|
|
9
|
+
export const SITECORE_EDGE_URL_DEFAULT = 'https://edge-platform.sitecorecloud.io';
|
|
10
|
+
export const HIDDEN_RENDERING_NAME = 'Hidden Rendering';
|
|
@@ -0,0 +1,28 @@
|
|
|
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 { resolveUrl } from './utils/utils';
|
|
11
|
+
export class ResponseError extends Error {
|
|
12
|
+
constructor(message, response) {
|
|
13
|
+
super(message);
|
|
14
|
+
Object.setPrototypeOf(this, ResponseError.prototype);
|
|
15
|
+
this.response = response;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* @param {string} url the URL to request; may include query string
|
|
20
|
+
* @param {HttpDataFetcher<T> | NativeDataFetcherFunction<T>} fetcher the fetcher to use to perform the request
|
|
21
|
+
* @param {ParsedUrlQueryInput} params the query string parameters to send with the request
|
|
22
|
+
*/
|
|
23
|
+
export function fetchData(url_1, fetcher_1) {
|
|
24
|
+
return __awaiter(this, arguments, void 0, function* (url, fetcher, params = {}) {
|
|
25
|
+
const response = yield fetcher(resolveUrl(url, params));
|
|
26
|
+
return response.data;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
var _a;
|
|
2
|
+
import debug from 'debug';
|
|
3
|
+
import isServer from './utils/is-server';
|
|
4
|
+
const rootNamespace = 'core';
|
|
5
|
+
// On server/node side, allow switching from the built-in
|
|
6
|
+
// `%o` (pretty-print single line) and `%O` (pretty-print multiple line)
|
|
7
|
+
// with a `DEBUG_MULTILINE` environment variable.
|
|
8
|
+
if (isServer() &&
|
|
9
|
+
((_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a.DEBUG_MULTILINE) === 'true' &&
|
|
10
|
+
debug.formatters.o &&
|
|
11
|
+
debug.formatters.O) {
|
|
12
|
+
debug.formatters.o = debug.formatters.O;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Enable debug logging dynamically
|
|
16
|
+
* @param {string} namespaces space-separated list of namespaces to enable
|
|
17
|
+
*/
|
|
18
|
+
export const enableDebug = (namespaces) => debug.enable(namespaces);
|
|
19
|
+
/**
|
|
20
|
+
* Default Sitecore JSS 'debug' module debuggers. Uses namespace prefix 'core:'.
|
|
21
|
+
* See {@link https://www.npmjs.com/package/debug} for details.
|
|
22
|
+
*/
|
|
23
|
+
export default {
|
|
24
|
+
common: debug(`${rootNamespace}:common`),
|
|
25
|
+
http: debug(`${rootNamespace}:http`),
|
|
26
|
+
layout: debug(`${rootNamespace}:layout`),
|
|
27
|
+
dictionary: debug(`${rootNamespace}:dictionary`),
|
|
28
|
+
editing: debug(`${rootNamespace}:editing`),
|
|
29
|
+
sitemap: debug(`${rootNamespace}:sitemap`),
|
|
30
|
+
multisite: debug(`${rootNamespace}:multisite`),
|
|
31
|
+
robots: debug(`${rootNamespace}:robots`),
|
|
32
|
+
redirects: debug(`${rootNamespace}:redirects`),
|
|
33
|
+
personalize: debug(`${rootNamespace}:personalize`),
|
|
34
|
+
errorpages: debug(`${rootNamespace}:errorpages`),
|
|
35
|
+
proxy: debug(`${rootNamespace}:proxy`),
|
|
36
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event to be sent when report status to component library
|
|
3
|
+
*/
|
|
4
|
+
export const COMPONENT_LIBRARY_STATUS_EVENT_NAME = 'component:status';
|
|
5
|
+
/**
|
|
6
|
+
* Enumeration of statuses for the component library.
|
|
7
|
+
*/
|
|
8
|
+
export var ComponentLibraryStatus;
|
|
9
|
+
(function (ComponentLibraryStatus) {
|
|
10
|
+
ComponentLibraryStatus["READY"] = "ready";
|
|
11
|
+
ComponentLibraryStatus["RENDERED"] = "rendered";
|
|
12
|
+
})(ComponentLibraryStatus || (ComponentLibraryStatus = {}));
|
|
13
|
+
/**
|
|
14
|
+
* Adds the browser-side event handler for 'component:update' message used in Component Library
|
|
15
|
+
* The event should update a component on page by uid, with fields and params from event args
|
|
16
|
+
* @param {ComponentRendering} rootComponent root component displayed for Component Library page
|
|
17
|
+
* @param {Function} successCallback callback to be called after successful component update
|
|
18
|
+
*/
|
|
19
|
+
export const addComponentUpdateHandler = (rootComponent, successCallback) => {
|
|
20
|
+
if (!window)
|
|
21
|
+
return;
|
|
22
|
+
const handler = (e) => updateComponentHandler(e, rootComponent, successCallback);
|
|
23
|
+
window.addEventListener('message', handler);
|
|
24
|
+
// the power to remove handler outside of this function, if needed
|
|
25
|
+
const unsubscribe = () => {
|
|
26
|
+
window.removeEventListener('message', handler);
|
|
27
|
+
};
|
|
28
|
+
return unsubscribe;
|
|
29
|
+
};
|
|
30
|
+
const validateOrigin = (event) => {
|
|
31
|
+
// TODO: use `EDITING_ALLOWED_ORIGINS.concat(getAllowedOriginsFromEnv())` later
|
|
32
|
+
// nextjs's JSS_ALLOWED_ORIGINS is not available on the client, need to use NEXT_PUBLIC_ variable, but it's a breaking change for Deploy
|
|
33
|
+
const allowedOrigins = ['*'];
|
|
34
|
+
return allowedOrigins.some((origin) => origin === event.origin ||
|
|
35
|
+
new RegExp('^' + origin.replace('.', '\\.').replace(/\*/g, '.*') + '$').test(event.origin));
|
|
36
|
+
};
|
|
37
|
+
export const updateComponentHandler = (e, rootComponent, successCallback) => {
|
|
38
|
+
var _a;
|
|
39
|
+
const eventArgs = e.data;
|
|
40
|
+
if (!e.origin || !eventArgs || eventArgs.name !== 'component:update') {
|
|
41
|
+
// avoid extra noise in logs
|
|
42
|
+
if (!validateOrigin(e)) {
|
|
43
|
+
console.debug('Component Library: event skipped: message %s from origin %s', eventArgs.name, e.origin);
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (!((_a = eventArgs.details) === null || _a === void 0 ? void 0 : _a.uid)) {
|
|
48
|
+
console.debug('Received component:update event without uid, aborting event handler...');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const findComponent = (root) => {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
if (((_a = root.uid) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === ((_b = eventArgs.details) === null || _b === void 0 ? void 0 : _b.uid.toLowerCase()))
|
|
54
|
+
return root;
|
|
55
|
+
if (root.placeholders) {
|
|
56
|
+
for (const plhName of Object.keys(root.placeholders)) {
|
|
57
|
+
for (const rendering of root.placeholders[plhName]) {
|
|
58
|
+
const result = findComponent(rendering);
|
|
59
|
+
if (result)
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
};
|
|
66
|
+
const updateComponent = findComponent(rootComponent);
|
|
67
|
+
if (updateComponent) {
|
|
68
|
+
console.debug('Found component with uid %s to update. Update fields: %o. Update params: %o.', eventArgs.details.uid, eventArgs.details.fields, eventArgs.details.params);
|
|
69
|
+
if (eventArgs.details.fields) {
|
|
70
|
+
updateComponent.fields = Object.assign(Object.assign({}, updateComponent.fields), eventArgs.details.fields);
|
|
71
|
+
}
|
|
72
|
+
if (eventArgs.details.params) {
|
|
73
|
+
updateComponent.params = Object.assign(Object.assign({}, updateComponent.params), eventArgs.details.params);
|
|
74
|
+
}
|
|
75
|
+
if (successCallback)
|
|
76
|
+
successCallback(rootComponent);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
console.debug('Rendering with uid %s not found', eventArgs.details.uid);
|
|
80
|
+
}
|
|
81
|
+
// strictly for testing
|
|
82
|
+
return rootComponent;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Generates a ComponentLibraryStatusEvent with the given status and uid.
|
|
86
|
+
* @param {ComponentLibraryStatus} status - The status of rendering.
|
|
87
|
+
* @param {string} uid - The unique identifier for the event.
|
|
88
|
+
* @returns An object representing the ComponentLibraryStatusEvent.
|
|
89
|
+
*/
|
|
90
|
+
export function getComponentLibraryStatusEvent(status, uid) {
|
|
91
|
+
return {
|
|
92
|
+
name: COMPONENT_LIBRARY_STATUS_EVENT_NAME,
|
|
93
|
+
message: {
|
|
94
|
+
status,
|
|
95
|
+
uid,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
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 { LayoutKind } from './models';
|
|
12
|
+
/**
|
|
13
|
+
* The dictionary query default page size.
|
|
14
|
+
*/
|
|
15
|
+
const PAGE_SIZE = 1000;
|
|
16
|
+
/**
|
|
17
|
+
* GraphQL query for fetching editing data.
|
|
18
|
+
*/
|
|
19
|
+
export const query = /* GraphQL */ `
|
|
20
|
+
query EditingQuery(
|
|
21
|
+
$siteName: String!
|
|
22
|
+
$itemId: String!
|
|
23
|
+
$language: String!
|
|
24
|
+
$version: String
|
|
25
|
+
$after: String
|
|
26
|
+
$pageSize: Int = ${PAGE_SIZE}
|
|
27
|
+
) {
|
|
28
|
+
item(path: $itemId, language: $language, version: $version) {
|
|
29
|
+
rendered
|
|
30
|
+
}
|
|
31
|
+
site {
|
|
32
|
+
siteInfo(site: $siteName) {
|
|
33
|
+
dictionary(language: $language, first: $pageSize, after: $after) {
|
|
34
|
+
results {
|
|
35
|
+
key
|
|
36
|
+
value
|
|
37
|
+
}
|
|
38
|
+
pageInfo {
|
|
39
|
+
endCursor
|
|
40
|
+
hasNext
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
/**
|
|
48
|
+
* GraphQL query for fetching dictionary data.
|
|
49
|
+
* This query is used when the dictionary data is paginated.
|
|
50
|
+
*/
|
|
51
|
+
export const dictionaryQuery = /* GraphQL */ `
|
|
52
|
+
query EditingDictionaryQuery(
|
|
53
|
+
$siteName: String!
|
|
54
|
+
$language: String!
|
|
55
|
+
$after: String
|
|
56
|
+
$pageSize: Int = ${PAGE_SIZE}
|
|
57
|
+
) {
|
|
58
|
+
site {
|
|
59
|
+
siteInfo(site: $siteName) {
|
|
60
|
+
dictionary(language: $language, first: $pageSize, after: $after) {
|
|
61
|
+
results {
|
|
62
|
+
key
|
|
63
|
+
value
|
|
64
|
+
}
|
|
65
|
+
pageInfo {
|
|
66
|
+
endCursor
|
|
67
|
+
hasNext
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
74
|
+
/**
|
|
75
|
+
* Service for fetching editing data from Sitecore using the Sitecore's GraphQL API.
|
|
76
|
+
* Expected to be used in XMCloud Pages preview (editing) Metadata Edit Mode.
|
|
77
|
+
*/
|
|
78
|
+
export class GraphQLEditingService {
|
|
79
|
+
/**
|
|
80
|
+
* Fetch layout data using the Sitecore GraphQL endpoint.
|
|
81
|
+
* @param {GraphQLLayoutServiceConfig} serviceConfig configuration
|
|
82
|
+
*/
|
|
83
|
+
constructor(serviceConfig) {
|
|
84
|
+
this.serviceConfig = serviceConfig;
|
|
85
|
+
this.graphQLClient = this.getGraphQLClient();
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Fetches editing data. Provides the layout data and dictionary phrases
|
|
89
|
+
* @param {object} variables - The parameters for fetching editing data.
|
|
90
|
+
* @param {string} variables.siteName - The site name.
|
|
91
|
+
* @param {string} variables.itemId - The item id (path) to fetch layout data for.
|
|
92
|
+
* @param {string} variables.language - The language to fetch layout data for.
|
|
93
|
+
* @param {string} [variables.version] - The version of the item (optional).
|
|
94
|
+
* @param {LayoutKind} [variables.layoutKind] - The final or shared layout variant.
|
|
95
|
+
* @returns {Promise} The layout data and dictionary phrases.
|
|
96
|
+
*/
|
|
97
|
+
fetchEditingData(_a) {
|
|
98
|
+
return __awaiter(this, arguments, void 0, function* ({ siteName, itemId, language, version, layoutKind = LayoutKind.Final, }) {
|
|
99
|
+
var _b, _c, _d;
|
|
100
|
+
debug.editing('fetching editing data for %s %s %s %s', siteName, itemId, language, version, layoutKind);
|
|
101
|
+
if (!siteName) {
|
|
102
|
+
throw new RangeError('The site name must be a non-empty string');
|
|
103
|
+
}
|
|
104
|
+
if (!language) {
|
|
105
|
+
throw new RangeError('The language must be a non-empty string');
|
|
106
|
+
}
|
|
107
|
+
let dictionaryResults = [];
|
|
108
|
+
let hasNext = true;
|
|
109
|
+
let after = '';
|
|
110
|
+
const editingData = yield this.graphQLClient.request(query, {
|
|
111
|
+
siteName,
|
|
112
|
+
itemId,
|
|
113
|
+
version,
|
|
114
|
+
language,
|
|
115
|
+
}, {
|
|
116
|
+
headers: {
|
|
117
|
+
sc_layoutKind: layoutKind,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
if ((_c = (_b = editingData === null || editingData === void 0 ? void 0 : editingData.site) === null || _b === void 0 ? void 0 : _b.siteInfo) === null || _c === void 0 ? void 0 : _c.dictionary) {
|
|
121
|
+
dictionaryResults = editingData.site.siteInfo.dictionary.results;
|
|
122
|
+
hasNext = editingData.site.siteInfo.dictionary.pageInfo.hasNext;
|
|
123
|
+
after = editingData.site.siteInfo.dictionary.pageInfo.endCursor;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
hasNext = false;
|
|
127
|
+
}
|
|
128
|
+
const dictionary = yield this.fetchDictionaryData({ siteName, language }, dictionaryResults, hasNext, after);
|
|
129
|
+
return {
|
|
130
|
+
layoutData: ((_d = editingData === null || editingData === void 0 ? void 0 : editingData.item) === null || _d === void 0 ? void 0 : _d.rendered) || {
|
|
131
|
+
sitecore: {
|
|
132
|
+
context: { pageEditing: true, language },
|
|
133
|
+
route: null,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
dictionary,
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
fetchDictionaryData(_a) {
|
|
141
|
+
return __awaiter(this, arguments, void 0, function* ({ siteName, language, }, initDictionary = [], hasNext = true, after) {
|
|
142
|
+
var _b, _c;
|
|
143
|
+
let dictionaryResults = initDictionary;
|
|
144
|
+
const dictionary = {};
|
|
145
|
+
while (hasNext) {
|
|
146
|
+
const data = yield this.graphQLClient.request(dictionaryQuery, {
|
|
147
|
+
siteName,
|
|
148
|
+
language,
|
|
149
|
+
after,
|
|
150
|
+
});
|
|
151
|
+
if ((_c = (_b = data === null || data === void 0 ? void 0 : data.site) === null || _b === void 0 ? void 0 : _b.siteInfo) === null || _c === void 0 ? void 0 : _c.dictionary) {
|
|
152
|
+
dictionaryResults = dictionaryResults.concat(data.site.siteInfo.dictionary.results);
|
|
153
|
+
hasNext = data.site.siteInfo.dictionary.pageInfo.hasNext;
|
|
154
|
+
after = data.site.siteInfo.dictionary.pageInfo.endCursor;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
hasNext = false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
dictionaryResults.forEach((item) => (dictionary[item.key] = item.value));
|
|
161
|
+
return dictionary;
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Gets a GraphQL client that can make requests to the API.
|
|
166
|
+
* @returns {GraphQLClient} implementation
|
|
167
|
+
*/
|
|
168
|
+
getGraphQLClient() {
|
|
169
|
+
if (!this.serviceConfig.clientFactory) {
|
|
170
|
+
throw new Error('clientFactory needs to be provided when initializing GraphQL client.');
|
|
171
|
+
}
|
|
172
|
+
return this.serviceConfig.clientFactory({
|
|
173
|
+
debugger: debug.editing,
|
|
174
|
+
headers: {
|
|
175
|
+
sc_editMode: 'true',
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { GraphQLEditingService } from './graphql-editing-service';
|
|
2
|
+
export { DEFAULT_PLACEHOLDER_UID, PagesEditor, isEditorActive, resetEditorChromes, getJssPagesClientData, EDITING_ALLOWED_ORIGINS, QUERY_PARAM_EDITING_SECRET, PAGES_EDITING_MARKER, } from './utils';
|
|
3
|
+
export { RestComponentLayoutService, } from './rest-component-layout-service';
|
|
4
|
+
export { LayoutKind, MetadataKind } from './models';
|
|
5
|
+
export { addComponentUpdateHandler, ComponentLibraryStatus, getComponentLibraryStatusEvent, } from './component-library';
|