@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,122 @@
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.handleEditorAnchors = exports.resetEditorChromes = exports.isEditorActive = exports.HorizonEditor = exports.ChromeRediscoveryGlobalFunctionName = exports.ExperienceEditor = void 0;
7
+ const is_server_1 = __importDefault(require("./is-server"));
8
+ /**
9
+ * Static utility class for Sitecore Experience Editor
10
+ */
11
+ class ExperienceEditor {
12
+ /**
13
+ * Determines whether the current execution context is within a Experience Editor.
14
+ * Experience Editor environment can be identified only in the browser
15
+ * @returns true if executing within a Experience Editor
16
+ */
17
+ static isActive() {
18
+ if (is_server_1.default()) {
19
+ return false;
20
+ }
21
+ // eslint-disable-next-line
22
+ const sc = window.Sitecore;
23
+ return Boolean(sc && sc.PageModes && sc.PageModes.ChromeManager);
24
+ }
25
+ static resetChromes() {
26
+ if (is_server_1.default()) {
27
+ return;
28
+ }
29
+ window.Sitecore.PageModes.ChromeManager.resetChromes();
30
+ }
31
+ }
32
+ exports.ExperienceEditor = ExperienceEditor;
33
+ /**
34
+ * Copy of chrome rediscovery contract from Horizon (chrome-rediscovery.contract.ts)
35
+ */
36
+ exports.ChromeRediscoveryGlobalFunctionName = {
37
+ name: 'Sitecore.Horizon.ResetChromes',
38
+ };
39
+ /**
40
+ * Static utility class for Sitecore Horizon Editor
41
+ */
42
+ class HorizonEditor {
43
+ /**
44
+ * Determines whether the current execution context is within a Horizon Editor.
45
+ * Horizon Editor environment can be identified only in the browser
46
+ * @returns true if executing within a Horizon Editor
47
+ */
48
+ static isActive() {
49
+ if (is_server_1.default()) {
50
+ return false;
51
+ }
52
+ // Horizon will add "sc_horizon=editor" query string parameter for the editor and "sc_horizon=simulator" for the preview
53
+ return window.location.search.indexOf('sc_horizon=editor') > -1;
54
+ }
55
+ static resetChromes() {
56
+ if (is_server_1.default()) {
57
+ return;
58
+ }
59
+ // Reset chromes in Horizon
60
+ window[exports.ChromeRediscoveryGlobalFunctionName.name] &&
61
+ window[exports.ChromeRediscoveryGlobalFunctionName.name]();
62
+ }
63
+ }
64
+ exports.HorizonEditor = HorizonEditor;
65
+ /**
66
+ * Determines whether the current execution context is within a Sitecore editor.
67
+ * Sitecore Editor environment can be identified only in the browser
68
+ * @returns true if executing within a Sitecore editor
69
+ */
70
+ const isEditorActive = () => {
71
+ return ExperienceEditor.isActive() || HorizonEditor.isActive();
72
+ };
73
+ exports.isEditorActive = isEditorActive;
74
+ /**
75
+ * Resets Sitecore editor "chromes"
76
+ */
77
+ const resetEditorChromes = () => {
78
+ if (ExperienceEditor.isActive()) {
79
+ ExperienceEditor.resetChromes();
80
+ }
81
+ else if (HorizonEditor.isActive()) {
82
+ HorizonEditor.resetChromes();
83
+ }
84
+ };
85
+ exports.resetEditorChromes = resetEditorChromes;
86
+ /**
87
+ * @description in Experience Editor, anchor tags
88
+ * with both onclick and href attributes will use the href, blocking the onclick from firing.
89
+ * This function makes it so the anchor tags function as intended in the sample when using Experience Editor
90
+ *
91
+ * The Mutation Observer API is used to observe changes to the body, then select all elements with href="#" and an onclick,
92
+ * and replaces the # value with javascript:void(0); which prevents the anchor tag from blocking the onclick event handler.
93
+ * @see Mutation Observer API: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/MutationObserver
94
+ */
95
+ const handleEditorAnchors = () => {
96
+ // The sample gives the href attribute priority over the onclick attribute if both are present, so we must replace
97
+ // the href attribute to avoid overriding the onclick in Experience Editor
98
+ if (!window || !ExperienceEditor.isActive()) {
99
+ return;
100
+ }
101
+ const targetNode = document.querySelector('body');
102
+ const callback = (mutationList) => {
103
+ mutationList.forEach((mutation) => {
104
+ const btns = document.querySelectorAll('.scChromeDropDown > a[href="#"], .scChromeDropDown > a[href="#!"], a[onclick]');
105
+ if (mutation.type === 'childList') {
106
+ btns.forEach((link) => {
107
+ link.href = 'javascript:void(0);';
108
+ });
109
+ }
110
+ return;
111
+ });
112
+ };
113
+ const observer = new MutationObserver(callback);
114
+ const observerOptions = {
115
+ childList: true,
116
+ subtree: true,
117
+ };
118
+ if (targetNode) {
119
+ observer.observe(targetNode, observerOptions);
120
+ }
121
+ };
122
+ exports.handleEditorAnchors = handleEditorAnchors;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tryParseEnvValue = void 0;
4
+ /**
5
+ * Method to parse JSON-formatted environment variables
6
+ * @param {string} envValue - can be undefined when providing values via process.env
7
+ * @param {T} defaultValue - default value
8
+ * @returns {T | string} parsed value
9
+ */
10
+ const tryParseEnvValue = (envValue, defaultValue) => {
11
+ if (!envValue) {
12
+ return defaultValue;
13
+ }
14
+ if (envValue.startsWith('{') && envValue.endsWith('}')) {
15
+ try {
16
+ return JSON.parse(envValue);
17
+ }
18
+ catch (error) {
19
+ console.warn('Parsing of env variable failed');
20
+ console.warn(`Attempted to parse ${envValue}`);
21
+ return defaultValue;
22
+ }
23
+ }
24
+ return defaultValue;
25
+ };
26
+ exports.tryParseEnvValue = tryParseEnvValue;
@@ -0,0 +1,25 @@
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.mapButtonToCommand = exports.DefaultEditFrameButtonIds = exports.DefaultEditFrameButtons = exports.DefaultEditFrameButton = exports.handleEditorAnchors = exports.resetEditorChromes = exports.isEditorActive = exports.HorizonEditor = exports.ExperienceEditor = exports.tryParseEnvValue = exports.isTimeoutError = exports.isAbsoluteUrl = exports.resolveUrl = exports.isServer = void 0;
7
+ var is_server_1 = require("./is-server");
8
+ Object.defineProperty(exports, "isServer", { enumerable: true, get: function () { return __importDefault(is_server_1).default; } });
9
+ var utils_1 = require("./utils");
10
+ Object.defineProperty(exports, "resolveUrl", { enumerable: true, get: function () { return utils_1.resolveUrl; } });
11
+ Object.defineProperty(exports, "isAbsoluteUrl", { enumerable: true, get: function () { return utils_1.isAbsoluteUrl; } });
12
+ Object.defineProperty(exports, "isTimeoutError", { enumerable: true, get: function () { return utils_1.isTimeoutError; } });
13
+ var env_1 = require("./env");
14
+ Object.defineProperty(exports, "tryParseEnvValue", { enumerable: true, get: function () { return env_1.tryParseEnvValue; } });
15
+ var editing_1 = require("./editing");
16
+ Object.defineProperty(exports, "ExperienceEditor", { enumerable: true, get: function () { return editing_1.ExperienceEditor; } });
17
+ Object.defineProperty(exports, "HorizonEditor", { enumerable: true, get: function () { return editing_1.HorizonEditor; } });
18
+ Object.defineProperty(exports, "isEditorActive", { enumerable: true, get: function () { return editing_1.isEditorActive; } });
19
+ Object.defineProperty(exports, "resetEditorChromes", { enumerable: true, get: function () { return editing_1.resetEditorChromes; } });
20
+ Object.defineProperty(exports, "handleEditorAnchors", { enumerable: true, get: function () { return editing_1.handleEditorAnchors; } });
21
+ var edit_frame_1 = require("./edit-frame");
22
+ Object.defineProperty(exports, "DefaultEditFrameButton", { enumerable: true, get: function () { return edit_frame_1.DefaultEditFrameButton; } });
23
+ Object.defineProperty(exports, "DefaultEditFrameButtons", { enumerable: true, get: function () { return edit_frame_1.DefaultEditFrameButtons; } });
24
+ Object.defineProperty(exports, "DefaultEditFrameButtonIds", { enumerable: true, get: function () { return edit_frame_1.DefaultEditFrameButtonIds; } });
25
+ Object.defineProperty(exports, "mapButtonToCommand", { enumerable: true, get: function () { return edit_frame_1.mapButtonToCommand; } });
@@ -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,70 @@
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.isTimeoutError = exports.isAbsoluteUrl = exports.resolveUrl = void 0;
7
+ const is_server_1 = __importDefault(require("./is-server"));
8
+ /**
9
+ * note: encodeURIComponent is available via browser (window) or natively in node.js
10
+ * if you use another js engine for server-side rendering you may not have native encodeURIComponent
11
+ * and would then need to install a package for that functionality
12
+ * @param {ParsedUrlQueryInput} params query string parameters
13
+ * @returns {string} query string
14
+ */
15
+ function getQueryString(params) {
16
+ return Object.keys(params)
17
+ .map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(String(params[k]))}`)
18
+ .join('&');
19
+ }
20
+ /**
21
+ * Resolves a base URL that may contain query string parameters and an additional set of query
22
+ * string parameters into a unified string representation.
23
+ * @param {string} urlBase the base URL that may contain query string parameters
24
+ * @param {ParsedUrlQueryInput} params query string parameters
25
+ * @returns a URL string
26
+ * @throws {RangeError} if the provided url is an empty string
27
+ */
28
+ function resolveUrl(urlBase, params = {}) {
29
+ if (!urlBase) {
30
+ throw new RangeError('url must be a non-empty string');
31
+ }
32
+ // This is a better way to work with URLs since it handles different user input
33
+ // edge cases. This works in Node and all browser except IE11.
34
+ // https://developer.mozilla.org/en-US/docs/Web/API/URL
35
+ // TODO: Verify our browser support requirements.
36
+ if (is_server_1.default()) {
37
+ const url = new URL(urlBase);
38
+ for (const key in params) {
39
+ if ({}.hasOwnProperty.call(params, key)) {
40
+ url.searchParams.append(key, String(params[key]));
41
+ }
42
+ }
43
+ const result = url.toString();
44
+ return result;
45
+ }
46
+ const qs = getQueryString(params);
47
+ const result = urlBase.indexOf('?') !== -1 ? `${urlBase}&${qs}` : `${urlBase}?${qs}`;
48
+ return result;
49
+ }
50
+ exports.resolveUrl = resolveUrl;
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;
@@ -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,9 @@
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';
@@ -0,0 +1,36 @@
1
+ var _a;
2
+ import debug from 'debug';
3
+ import isServer from './utils/is-server';
4
+ const rootNamespace = 'sitecore-jss';
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 'sitecore-jss:'.
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
+ revalidate: debug(`${rootNamespace}:revalidate`),
36
+ };
@@ -0,0 +1,69 @@
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 { SitecoreTemplateId } from '../constants';
11
+ /** @private */
12
+ export const siteNameError = 'The site name must be a non-empty string';
13
+ /** @private */
14
+ export const languageError = 'The language must be a non-empty string';
15
+ /*
16
+ * GraphQL query that returns the ID of the root item of the specified site and language
17
+ */
18
+ const appRootQuery = /* GraphQL */ `
19
+ query AppRootQuery($jssAppTemplateId: String!, $siteName: String!, $language: String!) {
20
+ layout(site: $siteName, routePath: "/", language: $language) {
21
+ homePage: item {
22
+ rootItem: ancestors(includeTemplateIDs: [$jssAppTemplateId]) {
23
+ id
24
+ }
25
+ }
26
+ }
27
+ }
28
+ `;
29
+ /**
30
+ * Gets the ID of the JSS App root item for the specified site and language.
31
+ * @param {GraphQLClient} client that fetches data from a GraphQL endpoint.
32
+ * @param {string} siteName the name of the Sitecore site.
33
+ * @param {string} language the item language version.
34
+ * @param {string} [jssAppTemplateId] optional template ID of the app root item. If not
35
+ * specified, the ID of the "/sitecore/templates/Foundation/JavaScript Services/App"
36
+ * item is used.
37
+ * @returns the root item ID of the JSS App in Sitecore. Returns null if the app root item is not found.
38
+ * @throws {RangeError} if a valid site name value is not provided.
39
+ * @throws {RangeError} if a valid language value is not provided.
40
+ * @summary This function intentionally avoids throwing an error if a root item is not found,
41
+ * leaving that decision up to implementations.
42
+ */
43
+ export function getAppRootId(client, siteName, language, jssAppTemplateId) {
44
+ var _a, _b, _c, _d, _e, _f;
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ if (!siteName) {
47
+ throw new RangeError(siteNameError);
48
+ }
49
+ if (!language) {
50
+ throw new RangeError(languageError);
51
+ }
52
+ let fetchResponse = yield client.request(appRootQuery, {
53
+ jssAppTemplateId: jssAppTemplateId || SitecoreTemplateId.JssApp,
54
+ siteName,
55
+ language,
56
+ });
57
+ if (!((_c = (_b = (_a = fetchResponse === null || fetchResponse === void 0 ? void 0 : fetchResponse.layout) === null || _a === void 0 ? void 0 : _a.homePage) === null || _b === void 0 ? void 0 : _b.rootItem) === null || _c === void 0 ? void 0 : _c.length) && language !== 'en') {
58
+ fetchResponse = yield client.request(appRootQuery, {
59
+ jssAppTemplateId: jssAppTemplateId || SitecoreTemplateId.JssApp,
60
+ siteName,
61
+ language: 'en',
62
+ });
63
+ }
64
+ if (!((_f = (_e = (_d = fetchResponse === null || fetchResponse === void 0 ? void 0 : fetchResponse.layout) === null || _d === void 0 ? void 0 : _d.homePage) === null || _e === void 0 ? void 0 : _e.rootItem) === null || _f === void 0 ? void 0 : _f.length)) {
65
+ return null;
66
+ }
67
+ return fetchResponse.layout.homePage.rootItem[0].id;
68
+ });
69
+ }
@@ -0,0 +1,8 @@
1
+ import { SITECORE_EDGE_URL_DEFAULT } from '../constants';
2
+ /**
3
+ * Generates a URL for accessing Sitecore Edge Platform Content using the provided endpoint and context ID.
4
+ * @param {string} sitecoreEdgeContextId - The unique context id.
5
+ * @param {string} [sitecoreEdgeUrl] - The base endpoint URL for the Edge Platform. Default is https://edge-platform.sitecorecloud.io
6
+ * @returns {string} The complete URL for accessing content through the Edge Platform.
7
+ */
8
+ export const getEdgeProxyContentUrl = (sitecoreEdgeContextId, sitecoreEdgeUrl = SITECORE_EDGE_URL_DEFAULT) => `${sitecoreEdgeUrl}/v1/content/api/graphql/v1?sitecoreContextId=${sitecoreEdgeContextId}`;
@@ -0,0 +1,4 @@
1
+ export { getAppRootId } from './app-root-query';
2
+ export { GraphQLRequestClient, } from './../graphql-request-client';
3
+ export { SearchQueryService, } from './search-service';
4
+ export { getEdgeProxyContentUrl } from './graphql-edge-proxy';
@@ -0,0 +1,56 @@
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
+ /**
11
+ * Provides functionality for performing GraphQL 'search' operations, including handling pagination.
12
+ * This class is meant to be extended or used as a mixin; it's not meant to be used directly.
13
+ * @template T The type of objects being requested.
14
+ * @mixin
15
+ */
16
+ export class SearchQueryService {
17
+ /**
18
+ * Creates an instance of search query service.
19
+ * @param {GraphQLClient} client that fetches data from a GraphQL endpoint.
20
+ */
21
+ constructor(client) {
22
+ this.client = client;
23
+ }
24
+ /**
25
+ * 1. Validates mandatory search query arguments
26
+ * 2. Executes search query with pagination
27
+ * 3. Aggregates pagination results into a single result-set.
28
+ * @template T The type of objects being requested.
29
+ * @param {string | DocumentNode} query the search query.
30
+ * @param {SearchQueryVariables} args search query arguments.
31
+ * @returns {T[]} array of result objects.
32
+ * @throws {RangeError} if a valid root item ID is not provided.
33
+ * @throws {RangeError} if the provided language(s) is(are) not valid.
34
+ */
35
+ fetch(query, args) {
36
+ var _a;
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ if (!args.rootItemId) {
39
+ throw new RangeError('"rootItemId" and "language" must be non-empty strings');
40
+ }
41
+ if (!args.language) {
42
+ throw new RangeError('"rootItemId" and "language" must be non-empty strings');
43
+ }
44
+ let results = [];
45
+ let hasNext = true;
46
+ let after = '';
47
+ while (hasNext) {
48
+ const fetchResponse = yield this.client.request(query, Object.assign(Object.assign({}, args), { after }));
49
+ results = results.concat((_a = fetchResponse === null || fetchResponse === void 0 ? void 0 : fetchResponse.search) === null || _a === void 0 ? void 0 : _a.results);
50
+ hasNext = fetchResponse.search.pageInfo.hasNext;
51
+ after = fetchResponse.search.pageInfo.endCursor;
52
+ }
53
+ return results;
54
+ });
55
+ }
56
+ }
@@ -0,0 +1,99 @@
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 { GraphQLClient as Client } from 'graphql-request';
11
+ import parse from 'url-parse';
12
+ import debuggers from './debug';
13
+ import TimeoutPromise from './utils/timeout-promise';
14
+ /**
15
+ * A GraphQL client for Sitecore APIs that uses the 'graphql-request' library.
16
+ * https://github.com/prisma-labs/graphql-request
17
+ */
18
+ export class GraphQLRequestClient {
19
+ /**
20
+ * Provides ability to execute graphql query using given `endpoint`
21
+ * @param {string} endpoint The Graphql endpoint
22
+ * @param {GraphQLRequestClientConfig} [clientConfig] GraphQL request client configuration.
23
+ */
24
+ constructor(endpoint, clientConfig = {}) {
25
+ this.endpoint = endpoint;
26
+ this.headers = {};
27
+ if (clientConfig.apiKey) {
28
+ this.headers.sc_apikey = clientConfig.apiKey;
29
+ }
30
+ if (!endpoint || !parse(endpoint).hostname) {
31
+ throw new Error(`Invalid GraphQL endpoint '${endpoint}'. Verify that 'layoutServiceHost' property in 'scjssconfig.json' file or appropriate environment variable is set`);
32
+ }
33
+ this.timeout = clientConfig.timeout;
34
+ this.retries = clientConfig.retries || 0;
35
+ this.client = new Client(endpoint, {
36
+ headers: this.headers,
37
+ fetch: clientConfig.fetch,
38
+ });
39
+ this.debug = clientConfig.debugger || debuggers.http;
40
+ }
41
+ /**
42
+ * Factory method for creating a GraphQLRequestClientFactory.
43
+ * @param {Object} config - client configuration options.
44
+ * @param {string} config.endpoint - endpoint
45
+ * @param {string} [config.apiKey] - apikey
46
+ */
47
+ static createClientFactory({ endpoint, apiKey, }) {
48
+ return (config = {}) => new GraphQLRequestClient(endpoint, Object.assign(Object.assign({}, config), { apiKey }));
49
+ }
50
+ /**
51
+ * Execute graphql request
52
+ * @param {string | DocumentNode} query graphql query
53
+ * @param {Object} variables graphql variables
54
+ */
55
+ request(query, variables) {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ let retriesLeft = this.retries;
58
+ const retryer = () => __awaiter(this, void 0, void 0, function* () {
59
+ // Note we don't have access to raw request/response with graphql-request
60
+ // but we should log whatever we have.
61
+ this.debug('request: %o', {
62
+ url: this.endpoint,
63
+ headers: this.headers,
64
+ query,
65
+ variables,
66
+ });
67
+ const startTimestamp = Date.now();
68
+ const fetchWithOptionalTimeout = [this.client.request(query, variables)];
69
+ if (this.timeout) {
70
+ this.abortTimeout = new TimeoutPromise(this.timeout);
71
+ fetchWithOptionalTimeout.push(this.abortTimeout.start);
72
+ }
73
+ return Promise.race(fetchWithOptionalTimeout).then((data) => {
74
+ var _a;
75
+ (_a = this.abortTimeout) === null || _a === void 0 ? void 0 : _a.clear();
76
+ this.debug('response in %dms: %o', Date.now() - startTimestamp, data);
77
+ return Promise.resolve(data);
78
+ }, (error) => {
79
+ var _a, _b, _c, _d;
80
+ (_a = this.abortTimeout) === null || _a === void 0 ? void 0 : _a.clear();
81
+ this.debug('response error: %o', error.response || error.message || error);
82
+ if (((_b = error.response) === null || _b === void 0 ? void 0 : _b.status) === 429 && retriesLeft > 0) {
83
+ const rawHeaders = (_d = (_c = error) === null || _c === void 0 ? void 0 : _c.response) === null || _d === void 0 ? void 0 : _d.headers;
84
+ const delaySeconds = rawHeaders && rawHeaders.get('Retry-After')
85
+ ? Number.parseInt(rawHeaders.get('Retry-After'), 10)
86
+ : 1;
87
+ this.debug('Error: Rate limit reached for GraphQL endpoint. Retrying in %ds. Retries left: %d', delaySeconds, retriesLeft);
88
+ retriesLeft--;
89
+ return new Promise((resolve) => setTimeout(resolve, delaySeconds * 1000)).then(retryer);
90
+ }
91
+ else {
92
+ return Promise.reject(error);
93
+ }
94
+ });
95
+ });
96
+ return retryer();
97
+ });
98
+ }
99
+ }