@exdst-sitecore-content-sdk/astro 0.0.16 → 0.0.19

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 (110) hide show
  1. package/README.md +3 -3
  2. package/package.json +41 -42
  3. package/src/client/index.ts +1 -1
  4. package/src/client/sitecore-astro-client.test.ts +41 -20
  5. package/src/client/sitecore-astro-client.ts +74 -57
  6. package/src/components/AstroImage.astro +2 -2
  7. package/src/components/AstroImage.astro.test.ts +542 -0
  8. package/src/components/Date.astro +5 -1
  9. package/src/components/Date.astro.test.ts +197 -0
  10. package/src/components/DefaultEmptyFieldEditingComponentImage.astro +4 -0
  11. package/src/components/DefaultEmptyFieldEditingComponentText.astro +4 -0
  12. package/src/components/EditingScripts.astro +2 -2
  13. package/src/components/EditingScripts.astro.test.ts +267 -0
  14. package/src/components/ErrorBoundary.astro +8 -9
  15. package/src/components/ErrorBoundary.astro.test.ts +252 -0
  16. package/src/components/ErrorComponent.astro +16 -0
  17. package/src/components/ErrorComponent.astro.test.ts +31 -0
  18. package/src/components/FieldMetadata.astro +1 -1
  19. package/src/components/FieldMetadata.astro.test.ts +40 -0
  20. package/src/components/File.astro +5 -1
  21. package/src/components/File.astro.test.ts +68 -0
  22. package/src/components/HiddenRendering.astro.test.ts +36 -0
  23. package/src/components/Image.astro +18 -4
  24. package/src/components/Image.astro.test.ts +438 -0
  25. package/src/components/Link.astro +13 -1
  26. package/src/components/Link.astro.test.ts +261 -0
  27. package/src/components/MissingComponent.astro.test.ts +21 -0
  28. package/src/components/Placeholder/Placeholder.astro +18 -23
  29. package/src/components/Placeholder/Placeholder.astro.test.ts +1088 -0
  30. package/src/components/Placeholder/PlaceholderMetadata.astro +24 -18
  31. package/src/components/Placeholder/PlaceholderMetadata.astro.test.ts +228 -0
  32. package/src/components/Placeholder/PlaceholderUtils.astro +21 -40
  33. package/src/components/Placeholder/PlaceholderUtils.astro.test.ts +149 -0
  34. package/src/components/Placeholder/models.ts +26 -17
  35. package/src/components/Placeholder/placeholder-utils.test.ts +153 -6
  36. package/src/components/Placeholder/placeholder-utils.ts +33 -11
  37. package/src/components/RichText.astro +9 -1
  38. package/src/components/RichText.astro.test.ts +205 -0
  39. package/src/components/Text.astro +15 -3
  40. package/src/components/Text.astro.test.ts +273 -0
  41. package/src/config/define-config.test.ts +5 -5
  42. package/src/config/define-config.ts +22 -42
  43. package/src/config-cli/define-cli-config.test.ts +5 -12
  44. package/src/config-cli/define-cli-config.ts +4 -8
  45. package/src/context.ts +42 -11
  46. package/src/debug.ts +13 -0
  47. package/src/editing/editing-config-middleware.test.ts +5 -7
  48. package/src/editing/editing-config-middleware.ts +11 -7
  49. package/src/editing/editing-render-middleware.test.ts +366 -24
  50. package/src/editing/editing-render-middleware.ts +34 -12
  51. package/src/editing/index.ts +2 -0
  52. package/src/editing/render-middleware.test.ts +1 -1
  53. package/src/editing/render-middleware.ts +1 -1
  54. package/src/editing/types.ts +39 -0
  55. package/src/editing/utils.test.ts +364 -4
  56. package/src/editing/utils.ts +82 -24
  57. package/src/enhancers/WithEmptyFieldEditingComponent.astro +1 -1
  58. package/src/enhancers/WithEmptyFieldEditingComponent.astro.test.ts +380 -0
  59. package/src/enhancers/WithFieldMetadata.astro.test.ts +113 -0
  60. package/src/index.ts +10 -7
  61. package/src/middleware/index.ts +4 -12
  62. package/src/middleware/middleware.test.ts +13 -0
  63. package/src/middleware/middleware.ts +12 -3
  64. package/src/middleware/multisite-middleware.test.ts +45 -50
  65. package/src/middleware/multisite-middleware.ts +33 -6
  66. package/src/middleware/robots-middleware.test.ts +20 -4
  67. package/src/middleware/robots-middleware.ts +10 -3
  68. package/src/middleware/sitemap-middleware.test.ts +35 -3
  69. package/src/middleware/sitemap-middleware.ts +7 -6
  70. package/src/services/component-props-service.ts +7 -6
  71. package/src/sharedTypes/component-props.ts +15 -4
  72. package/src/site/index.ts +1 -1
  73. package/src/tests/astro-helpers.ts +61 -0
  74. package/src/tests/test-components/CustomErrorComponent.astro +3 -0
  75. package/src/tests/test-components/CustomHiddenRendering.astro +10 -0
  76. package/src/tests/test-components/CustomMissingComponent.astro +9 -0
  77. package/src/tests/test-components/DownloadCallout.astro +12 -0
  78. package/src/tests/test-components/EmptyFieldEditingComponent.astro +5 -0
  79. package/src/tests/test-components/ErrorBoundaryWithError.astro +10 -0
  80. package/src/tests/test-components/Home.astro +12 -0
  81. package/src/tests/test-components/SxaRichText.astro +23 -0
  82. package/src/tests/test-components/SxaRichTextDefault.astro +7 -0
  83. package/src/tests/test-components/SxaRichTextWithTitle.astro +8 -0
  84. package/src/tests/test-components/TestComponent.astro +9 -0
  85. package/src/tests/test-components/TestComponentWithError.astro +4 -0
  86. package/src/tests/test-components/TestComponentWithField.astro +17 -0
  87. package/src/tests/test-components/TestHeader.astro +8 -0
  88. package/src/tests/test-components/TestLogo.astro +5 -0
  89. package/src/tests/test-components/TestParentWrapperComponent.astro +5 -0
  90. package/src/tests/test-components/TestWrapperComponent.astro +5 -0
  91. package/src/tests/test-data/metadata-data.ts +86 -0
  92. package/src/tests/test-data/normal-mode-data.ts +466 -0
  93. package/src/tests/vitest.setup.ts +4 -0
  94. package/src/tools/generate-map.ts +4 -3
  95. package/src/tools/index.ts +2 -4
  96. package/src/tools/templating/components.test.ts +100 -87
  97. package/src/tools/templating/components.ts +2 -1
  98. package/src/tools/templating/default-component.ts +3 -8
  99. package/src/utils/utils.ts +20 -2
  100. /package/src/{test-data → tests}/helpers.ts +0 -0
  101. /package/src/{test-data → tests}/personalizeData.ts +0 -0
  102. /package/src/{test-data/components → tests/test-components/map-components}/Bar.astro +0 -0
  103. /package/src/{test-data/components → tests/test-components/map-components}/Baz.astro +0 -0
  104. /package/src/{test-data/components → tests/test-components/map-components}/Foo.astro +0 -0
  105. /package/src/{test-data/components → tests/test-components/map-components}/Hero.variant.astro +0 -0
  106. /package/src/{test-data/components → tests/test-components/map-components}/NotComponent.bsx +0 -0
  107. /package/src/{test-data/components → tests/test-components/map-components}/Qux.astro +0 -0
  108. /package/src/{test-data/components → tests/test-components/map-components}/folded/Folded.astro +0 -0
  109. /package/src/{test-data/components → tests/test-components/map-components}/folded/random-file-2.docx +0 -0
  110. /package/src/{test-data/components → tests/test-components/map-components}/random-file.txt +0 -0
@@ -0,0 +1,273 @@
1
+ import { describe, test, expect } from 'vitest';
2
+ import { renderAstroComponent } from '../tests/astro-helpers';
3
+ import Text, { TextField } from './Text.astro';
4
+ import EmptyFieldEditingComponent from '../tests/test-components/EmptyFieldEditingComponent.astro';
5
+
6
+ describe('<Text />', () => {
7
+ test('should render nothing with missing field', async () => {
8
+ const field: TextField = null!;
9
+ const rendered = await renderAstroComponent(Text, {
10
+ props: { field: field },
11
+ });
12
+ expect(rendered.innerHTML).to.equal('');
13
+ });
14
+
15
+ test('should render nothing with missing field', async () => {
16
+ const field = {
17
+ value: '',
18
+ };
19
+ const rendered = await renderAstroComponent(Text, {
20
+ props: { field: field },
21
+ });
22
+ expect(rendered.innerHTML).to.equal('');
23
+ });
24
+
25
+ test('should render nothing with missing value', async () => {
26
+ const field = {};
27
+ const rendered = await renderAstroComponent(Text, {
28
+ props: { field: field },
29
+ });
30
+ expect(rendered.innerHTML).to.equal('');
31
+ });
32
+
33
+ test('should render value with editing explicitly disabled', async () => {
34
+ const field = {
35
+ value: 'value',
36
+ };
37
+ const rendered = (
38
+ await renderAstroComponent(Text, {
39
+ props: { field: field, tag: 'span', editable: false },
40
+ })
41
+ ).querySelector('span');
42
+
43
+ expect(rendered?.innerHTML).to.contain('value');
44
+ });
45
+
46
+ test('should encode values with editing explicitly disabled', async () => {
47
+ const field = {
48
+ value: 'value < >',
49
+ };
50
+ const rendered = (
51
+ await renderAstroComponent(Text, {
52
+ props: { field: field, tag: 'span', editable: false },
53
+ })
54
+ ).querySelector('span');
55
+ expect(rendered?.innerHTML).to.contain('&lt; &gt;');
56
+ });
57
+
58
+ test('should render value with just a value', async () => {
59
+ const field = {
60
+ value: 'value',
61
+ };
62
+ const rendered = (
63
+ await renderAstroComponent(Text, {
64
+ props: { field: field, tag: 'span' },
65
+ })
66
+ ).querySelector('span');
67
+ expect(rendered?.innerHTML).to.contain('value');
68
+ });
69
+
70
+ test('should render value without tag', async () => {
71
+ const field = {
72
+ value: 'value',
73
+ };
74
+ const rendered = await renderAstroComponent(Text, {
75
+ props: { field: field },
76
+ });
77
+ expect(rendered.innerHTML).to.equal('value');
78
+ });
79
+
80
+ test('should render number value', async () => {
81
+ const field = {
82
+ value: 1.23,
83
+ };
84
+ const rendered = await renderAstroComponent(Text, {
85
+ props: { field: field },
86
+ });
87
+ expect(rendered.innerHTML).to.equal('1.23');
88
+ });
89
+
90
+ test('should render zero number value', async () => {
91
+ const field = {
92
+ value: 0,
93
+ };
94
+ const rendered = await renderAstroComponent(Text, {
95
+ props: { field: field },
96
+ });
97
+ expect(rendered?.innerHTML).to.equal('0');
98
+ });
99
+
100
+ test('should render negative number value', async () => {
101
+ const field = {
102
+ value: -1.23,
103
+ };
104
+ const rendered = await renderAstroComponent(Text, {
105
+ props: { field: field },
106
+ });
107
+ expect(rendered?.innerHTML).to.equal('-1.23');
108
+ });
109
+
110
+ test('should render value without tag', async () => {
111
+ const field = {
112
+ value: 'value',
113
+ };
114
+ const rendered = await renderAstroComponent(Text, {
115
+ props: { field: field },
116
+ });
117
+ expect(rendered?.innerHTML).to.contain('value');
118
+ });
119
+
120
+ test('should render value with just a value that contains line breaks', async () => {
121
+ const field = {
122
+ value: 'xxx\n\naa\nbbb\ndd',
123
+ };
124
+ const rendered = (
125
+ await renderAstroComponent(Text, {
126
+ props: { field: field, tag: 'span' },
127
+ })
128
+ ).querySelector('span');
129
+ expect(rendered?.innerHTML).to.contain('xxx<br><br>aa<br>bbb<br>dd');
130
+ });
131
+
132
+ test('should render value with just a value that contains only one line break', async () => {
133
+ const field = {
134
+ value: '\n',
135
+ };
136
+ const rendered = (
137
+ await renderAstroComponent(Text, {
138
+ props: { field: field, tag: 'span' },
139
+ })
140
+ ).querySelector('span');
141
+ expect(rendered?.outerHTML).to.contain('<span><br></span>');
142
+ });
143
+
144
+ test('should render embedded html as-is when encoding is disabled', async () => {
145
+ const field = {
146
+ value: '<input type="text">some crazy stuff<script code="whaaaat">uh oh</script>',
147
+ };
148
+ const rendered = (
149
+ await renderAstroComponent(Text, {
150
+ props: { field: field, encode: false },
151
+ })
152
+ ).querySelector('span');
153
+ expect(rendered?.innerHTML).to.contain(field.value);
154
+ });
155
+
156
+ test('should render tag with a tag provided', async () => {
157
+ const field = {
158
+ value: 'value',
159
+ };
160
+ const rendered = (
161
+ await renderAstroComponent(Text, {
162
+ props: { field: field, tag: 'h1' },
163
+ })
164
+ ).querySelector('h1');
165
+ expect(rendered?.innerHTML).to.contain('value');
166
+ });
167
+
168
+ test('should render other attributes with other props provided', async () => {
169
+ const field = {
170
+ value: 'value',
171
+ };
172
+ const rendered = (
173
+ await renderAstroComponent(Text, {
174
+ props: { field: field, tag: 'h1', class: 'cssClass', id: 'lorem' },
175
+ })
176
+ ).querySelector('h1');
177
+ expect(rendered?.outerHTML).to.contain('<h1 class="cssClass" id="lorem">');
178
+ expect(rendered?.outerHTML).to.contain('value');
179
+ });
180
+
181
+ describe('edit mode', () => {
182
+ const testMetadata = {
183
+ contextItem: {
184
+ id: '{09A07660-6834-476C-B93B-584248D3003B}',
185
+ language: 'en',
186
+ revision: 'a0b36ce0a7db49418edf90eb9621e145',
187
+ version: 1,
188
+ },
189
+ fieldId: '{414061F4-FBB1-4591-BC37-BFFA67F745EB}',
190
+ fieldType: 'single-line',
191
+ rawValue: 'Test1',
192
+ };
193
+
194
+ test('should render field metadata component when metadata property is present', async () => {
195
+ const field = {
196
+ value: 'value',
197
+ metadata: testMetadata,
198
+ };
199
+
200
+ const rendered = await renderAstroComponent(Text, {
201
+ props: { field: field },
202
+ });
203
+
204
+ expect(rendered.innerHTML).to.equal(
205
+ [
206
+ `<code type="text/sitecore" chrometype="field" class="scpm" kind="open">${JSON.stringify(
207
+ testMetadata
208
+ )}</code>`,
209
+ '<span>value</span>',
210
+ '<code type="text/sitecore" chrometype="field" class="scpm" kind="close"></code>',
211
+ ].join('')
212
+ );
213
+ });
214
+
215
+ test('should render default empty field component when field value is empty in edit mode metadata', async () => {
216
+ const field = {
217
+ value: '',
218
+ metadata: testMetadata,
219
+ };
220
+
221
+ const rendered = await renderAstroComponent(Text, {
222
+ props: { field: field },
223
+ });
224
+
225
+ expect(rendered.innerHTML).to.equal(
226
+ [
227
+ `<code type="text/sitecore" chrometype="field" class="scpm" kind="open">${JSON.stringify(
228
+ testMetadata
229
+ )}</code>`,
230
+ '<span>[No text in field]</span>',
231
+ '<code type="text/sitecore" chrometype="field" class="scpm" kind="close"></code>',
232
+ ].join('')
233
+ );
234
+ });
235
+
236
+ test('should render custom empty field component when provided, when field value is empty in edit mode metadata', async () => {
237
+ const field = {
238
+ value: '',
239
+ metadata: testMetadata,
240
+ };
241
+
242
+ const rendered = await renderAstroComponent(Text, {
243
+ props: {
244
+ field: field,
245
+ emptyFieldEditingComponent: EmptyFieldEditingComponent,
246
+ },
247
+ });
248
+
249
+ expect(rendered.innerHTML).to.equal(
250
+ [
251
+ `<code type="text/sitecore" chrometype="field" class="scpm" kind="open">${JSON.stringify(
252
+ testMetadata
253
+ )}</code>`,
254
+ '<span class="empty-field-value-placeholder">Custom Empty field value</span>',
255
+ '<code type="text/sitecore" chrometype="field" class="scpm" kind="close"></code>',
256
+ ].join('')
257
+ );
258
+ });
259
+
260
+ test('should render nothing when field value is empty, when editing is explicitly disabled in edit mode metadata ', async () => {
261
+ const field = {
262
+ value: '',
263
+ metadata: testMetadata,
264
+ };
265
+
266
+ const rendered = await renderAstroComponent(Text, {
267
+ props: { field: field, editable: false },
268
+ });
269
+
270
+ expect(rendered.innerHTML).to.equal('');
271
+ });
272
+ });
273
+ });
@@ -17,7 +17,7 @@ describe('defineConfig', () => {
17
17
  beforeEach(() => {
18
18
  defineConfigCoreStub = sandbox.stub();
19
19
  defineConfigModule = proxyquire('./define-config', {
20
- '@sitecore-content-sdk/core/config': {
20
+ '@sitecore-content-sdk/content/config': {
21
21
  defineConfig: defineConfigCoreStub,
22
22
  },
23
23
  });
@@ -150,10 +150,10 @@ describe('defineConfig', () => {
150
150
 
151
151
  describe('config.api.edge.edgeUrl', () => {
152
152
  describe('environment variable is not set', () => {
153
- it('should default to undefined', () => {
153
+ it('should default to Edge Platform URL', () => {
154
154
  defineConfigModule.defineConfig(defaultConfig());
155
155
  const resultConfig = defineConfigCoreStub.getCalls()[0].args[0];
156
- expect(resultConfig.api?.edge?.edgeUrl).to.be.undefined;
156
+ expect(resultConfig.api?.edge?.edgeUrl).to.equal('https://edge-platform.sitecorecloud.io');
157
157
  });
158
158
 
159
159
  it('should use the value from the config', () => {
@@ -167,11 +167,11 @@ describe('defineConfig', () => {
167
167
  });
168
168
  describe('environment variable is set', () => {
169
169
  before(() => {
170
- process.env.PUBLIC_SITECORE_EDGE_URL = 'next-public-sitecore-edgeUrl';
170
+ process.env.PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME = 'next-public-sitecore-edgeUrl';
171
171
  });
172
172
 
173
173
  after(() => {
174
- delete process.env.PUBLIC_SITECORE_EDGE_URL;
174
+ delete process.env.PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME;
175
175
  });
176
176
 
177
177
  it('should use the value from the config if present', () => {
@@ -3,16 +3,18 @@ import {
3
3
  DeepRequired,
4
4
  defineConfig as defineConfigCore,
5
5
  SitecoreConfigInput as SitecoreConfigInputCore,
6
- } from '@sitecore-content-sdk/core/config';
6
+ } from '@sitecore-content-sdk/content/config';
7
+ import { resolveEdgeUrl } from '@sitecore-content-sdk/core/tools';
8
+
9
+ /** Env var for Edge hostname; exposed to the browser so client code can use it. */
10
+ const PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME_ENV = 'PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME';
7
11
 
8
12
  /**
9
13
  * Provides default Astro initial values from env variables for SitecoreConfig
10
14
  * @param {SitecoreConfigInput} config optional override values to be written over default config settings
11
15
  * @returns default Astro input config
12
16
  */
13
- export const getAstroFallbackConfig = (
14
- config?: SitecoreConfigInput
15
- ): SitecoreConfigInput => {
17
+ export const getAstroFallbackConfig = (config?: SitecoreConfigInput): SitecoreConfigInput => {
16
18
  return {
17
19
  ...config,
18
20
  api: {
@@ -21,64 +23,40 @@ export const getAstroFallbackConfig = (
21
23
  ...config?.api?.edge,
22
24
  contextId: config?.api?.edge?.contextId || '',
23
25
  clientContextId:
24
- config?.api?.edge?.clientContextId ||
25
- import.meta.env?.PUBLIC_SITECORE_EDGE_CONTEXT_ID ||
26
- process.env.PUBLIC_SITECORE_EDGE_CONTEXT_ID,
27
- edgeUrl:
28
- config?.api?.edge?.edgeUrl ||
29
- import.meta.env?.PUBLIC_SITECORE_EDGE_URL ||
30
- process.env.PUBLIC_SITECORE_EDGE_URL,
26
+ config?.api?.edge?.clientContextId || process.env.PUBLIC_SITECORE_EDGE_CONTEXT_ID,
27
+ edgeUrl: resolveEdgeUrl(
28
+ config?.api?.edge?.edgeUrl ?? process.env.PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME_ENV
29
+ ),
31
30
  },
32
31
  local: {
33
32
  ...config?.api?.local,
34
- apiKey:
35
- config?.api?.local?.apiKey ||
36
- import.meta.env?.PUBLIC_SITECORE_API_KEY ||
37
- process.env.PUBLIC_SITECORE_API_KEY ||
38
- '',
39
- apiHost:
40
- config?.api?.local?.apiHost ||
41
- import.meta.env?.PUBLIC_SITECORE_API_HOST ||
42
- process.env.PUBLIC_SITECORE_API_HOST ||
43
- '',
33
+ apiKey: config?.api?.local?.apiKey || process.env.PUBLIC_SITECORE_API_KEY || '',
34
+ apiHost: config?.api?.local?.apiHost || process.env.PUBLIC_SITECORE_API_HOST || '',
44
35
  },
45
36
  },
46
- defaultSite:
47
- config?.defaultSite ||
48
- import.meta.env?.PUBLIC_DEFAULT_SITE_NAME ||
49
- process.env.PUBLIC_DEFAULT_SITE_NAME ||
50
- '',
51
- defaultLanguage:
52
- config?.defaultLanguage ||
53
- import.meta.env?.PUBLIC_DEFAULT_LANGUAGE ||
54
- process.env.PUBLIC_DEFAULT_LANGUAGE ||
55
- 'en',
37
+ defaultSite: config?.defaultSite || process.env.PUBLIC_DEFAULT_SITE_NAME || '',
38
+ defaultLanguage: config?.defaultLanguage || process.env.PUBLIC_DEFAULT_LANGUAGE || 'en',
56
39
  multisite: {
57
40
  ...config?.multisite,
58
41
  useCookieResolution:
59
- config?.multisite?.useCookieResolution ??
60
- (() => (import.meta.env?.VERCEL_ENV || process.env.VERCEL_ENV) === 'preview'),
42
+ config?.multisite?.useCookieResolution ?? (() => process.env.VERCEL_ENV === 'preview'),
61
43
  },
62
44
  personalize: {
63
45
  ...config?.personalize,
64
- scope:
65
- config?.personalize?.scope ||
66
- import.meta.env?.PUBLIC_PERSONALIZE_SCOPE ||
67
- process.env.PUBLIC_PERSONALIZE_SCOPE,
46
+ scope: config?.personalize?.scope || process.env.PUBLIC_PERSONALIZE_SCOPE,
68
47
  },
69
48
  generateStaticPaths:
70
- (import.meta.env?.GENERATE_STATIC_PATHS ?? process.env.GENERATE_STATIC_PATHS) !== undefined
71
- ? (import.meta.env?.GENERATE_STATIC_PATHS || process.env.GENERATE_STATIC_PATHS).toLowerCase() === 'true'
49
+ process.env.GENERATE_STATIC_PATHS !== undefined
50
+ ? process.env.GENERATE_STATIC_PATHS.toLowerCase() === 'true'
72
51
  : config?.generateStaticPaths ?? true,
73
52
  sitecoreInternalEditingHostUrl:
74
- config?.sitecoreInternalEditingHostUrl ||
75
- import.meta.env?.SITECORE_INTERNAL_EDITING_HOST_URL ||
76
- process.env.SITECORE_INTERNAL_EDITING_HOST_URL,
53
+ config?.sitecoreInternalEditingHostUrl || process.env.SITECORE_INTERNAL_EDITING_HOST_URL,
77
54
  };
78
55
  };
79
56
 
80
57
  /**
81
58
  * Type to be used as config input in sitecore.config
59
+ * @public
82
60
  */
83
61
  export type SitecoreConfigInput = SitecoreConfigInputCore & {
84
62
  /**
@@ -102,6 +80,7 @@ export type SitecoreConfigInput = SitecoreConfigInputCore & {
102
80
 
103
81
  /**
104
82
  * Final sitecore config type used at runtime Every property should be populated, either from sitecore.config or built-in fallback values
83
+ * @public
105
84
  */
106
85
  export type SitecoreConfig = DeepRequired<SitecoreConfigInput>;
107
86
 
@@ -109,6 +88,7 @@ export type SitecoreConfig = DeepRequired<SitecoreConfigInput>;
109
88
  * Accepts a SitecoreConfigInput object and returns full sitecore configuration
110
89
  * @param {SitecoreConfigInput} config override values to be written over default config settings
111
90
  * @returns {SitecoreConfig} full sitecore configuration to use in application
91
+ * @public
112
92
  */
113
93
  export const defineConfig = (config?: SitecoreConfigInput): SitecoreConfig => {
114
94
  return defineConfigCore(getAstroFallbackConfig(config)) as SitecoreConfig;
@@ -4,16 +4,13 @@ import {
4
4
  SitecoreCliConfigInput,
5
5
  SitecoreCliConfig,
6
6
  ComponentTemplateType,
7
- } from '@sitecore-content-sdk/core/config';
7
+ } from '@sitecore-content-sdk/content/config';
8
8
  import chalk from 'chalk';
9
9
 
10
10
  describe('defineCliConfig', () => {
11
11
  const validateDefaultTemplates = (result: SitecoreCliConfig) => {
12
- expect(result.scaffold.templates[0].name).to.equal(
13
- ComponentTemplateType.DEFAULT
14
- );
15
- const defaultTemplate =
16
- result.scaffold.templates[0].generateTemplate('ComponentName');
12
+ expect(result.scaffold.templates[0].name).to.equal(ComponentTemplateType.DEFAULT);
13
+ const defaultTemplate = result.scaffold.templates[0].generateTemplate('ComponentName');
17
14
  // expect(defaultTemplate).to.contain(
18
15
  // // eslint-disable-next-line quotes
19
16
  // `import { ComponentParams, ComponentRendering } from '@sitecore-content-sdk/nextjs';`
@@ -21,9 +18,7 @@ describe('defineCliConfig', () => {
21
18
  expect(defaultTemplate).to.contain('ComponentName');
22
19
  if (result.scaffold.templates[0].getNextSteps) {
23
20
  const componentpath = 'src/components/ComponentName.astro';
24
- expect(
25
- result.scaffold.templates[0].getNextSteps(componentpath)[0]
26
- ).to.contain(
21
+ expect(result.scaffold.templates[0].getNextSteps(componentpath)[0]).to.contain(
27
22
  `* Implement the Astro component in ${chalk.green(componentpath)}`
28
23
  );
29
24
  }
@@ -59,9 +54,7 @@ describe('defineCliConfig', () => {
59
54
  ],
60
55
  },
61
56
  scaffold: {
62
- templates: [
63
- { name: 'existing template', generateTemplate: () => 'test' },
64
- ],
57
+ templates: [{ name: 'existing template', generateTemplate: () => 'test' }],
65
58
  },
66
59
  };
67
60
 
@@ -1,8 +1,5 @@
1
- import {
2
- SitecoreCliConfigInput,
3
- SitecoreCliConfig,
4
- } from '@sitecore-content-sdk/core/config';
5
- import { defineCliConfig as defineCliConfigCore } from '@sitecore-content-sdk/core/config-cli';
1
+ import { SitecoreCliConfigInput, SitecoreCliConfig } from '@sitecore-content-sdk/content/config';
2
+ import { defineCliConfig as defineCliConfigCore } from '@sitecore-content-sdk/content/config-cli';
6
3
  // import { byocTemplate } from '../tools/templating/byoc-component';
7
4
  import { defaultTemplate } from '../tools/templating/default-component';
8
5
  import { generateMap } from '../tools/generate-map';
@@ -12,10 +9,9 @@ import { generateMap } from '../tools/generate-map';
12
9
  * updated with the required default values.
13
10
  * @param {SitecoreCliConfigInput} cliConfig the cli configuration provided by the application
14
11
  * @returns {SitecoreCliConfig} full sitecore cli configuration to use with cli
12
+ * @public
15
13
  */
16
- export const defineCliConfig = (
17
- cliConfig: SitecoreCliConfigInput
18
- ): SitecoreCliConfig => {
14
+ export const defineCliConfig = (cliConfig: SitecoreCliConfigInput): SitecoreCliConfig => {
19
15
  addDefaultScaffoldTemplates(cliConfig);
20
16
  addDefaultComponentMapGenerator(cliConfig);
21
17
  return defineCliConfigCore(cliConfig);
package/src/context.ts CHANGED
@@ -1,11 +1,19 @@
1
1
  import { map } from 'nanostores';
2
2
  import { ComponentMap } from './sharedTypes/component-props';
3
- import { Page } from '@sitecore-content-sdk/core/client';
4
- import { SitecoreConfig } from '@sitecore-content-sdk/core/config';
5
- import { DictionaryPhrases } from '@sitecore-content-sdk/core/types/i18n';
3
+ import { Page } from '@sitecore-content-sdk/content/client';
4
+ import { SitecoreConfig } from '@sitecore-content-sdk/content/config';
5
+ import { DictionaryPhrases } from '@sitecore-content-sdk/content/types/i18n';
6
6
 
7
+ /**
8
+ * Nanostore map holding Sitecore page, API config, component map, and dictionary for the current request or app scope.
9
+ * @internal
10
+ */
7
11
  export const SitecoreContext: any = map({});
8
12
 
13
+ /**
14
+ * Shape of values passed when updating {@link SitecoreContext} (page, API, and optional component map).
15
+ * @internal
16
+ */
9
17
  export interface SitecoreContextProps {
10
18
  /**
11
19
  * The API configuration defined in the `SitecoreConfig`.
@@ -21,6 +29,10 @@ export interface SitecoreContextProps {
21
29
  page: Page;
22
30
  }
23
31
 
32
+ /**
33
+ * Shape of values passed when updating dictionary phrases on {@link SitecoreContext}.
34
+ * @internal
35
+ */
24
36
  export interface SitecoreDictionarytProps {
25
37
  /**
26
38
  * The dictionary data.
@@ -28,22 +40,33 @@ export interface SitecoreDictionarytProps {
28
40
  dictionary: DictionaryPhrases;
29
41
  }
30
42
 
31
- export const updateSitecoreContext = ({
32
- page,
33
- api,
34
- componentMap,
35
- }: SitecoreContextProps) => {
43
+ /**
44
+ * Writes page data, API config, and optional component map into {@link SitecoreContext}.
45
+ * @param {Page} props.page - The page data.
46
+ * @param {SitecoreConfig['api']} props.api - The API configuration.
47
+ * @param {ComponentMap} [props.componentMap] - Component map.
48
+ * @internal
49
+ */
50
+ export const updateSitecoreContext = ({ page, api, componentMap }: SitecoreContextProps) => {
36
51
  SitecoreContext.setKey('page', page);
37
52
  SitecoreContext.setKey('api', api);
38
53
  SitecoreContext.setKey('componentMap', componentMap);
39
54
  };
40
55
 
41
- export const updateSitecoreDictionary = ({
42
- dictionary,
43
- }: SitecoreDictionarytProps) => {
56
+ /**
57
+ * Writes dictionary phrases into {@link SitecoreContext} for {@link useDictionary}.
58
+ * @param {SitecoreDictionarytProps} props
59
+ * @param {DictionaryPhrases} props.dictionary
60
+ * @internal
61
+ */
62
+ export const updateSitecoreDictionary = ({ dictionary }: SitecoreDictionarytProps) => {
44
63
  SitecoreContext.setKey('dictionary', dictionary);
45
64
  };
46
65
 
66
+ /**
67
+ * Returns the current page and API config from {@link SitecoreContext}.
68
+ * @public
69
+ */
47
70
  export const useSitecore = (): SitecoreContextProps => {
48
71
  return {
49
72
  page: SitecoreContext.get()['page'],
@@ -51,10 +74,18 @@ export const useSitecore = (): SitecoreContextProps => {
51
74
  };
52
75
  };
53
76
 
77
+ /**
78
+ * Returns the component map from {@link SitecoreContext} for resolving rendering components.
79
+ * @public
80
+ */
54
81
  export const useComponentMap = (): ComponentMap => {
55
82
  return SitecoreContext.get()['componentMap'];
56
83
  };
57
84
 
85
+ /**
86
+ * Returns a translator function `t(key)` that resolves keys against the dictionary on {@link SitecoreContext}, or returns the key if no dictionary is set.
87
+ * @public
88
+ */
58
89
  export const useDictionary = () => {
59
90
  const t = (key: string): string => {
60
91
  const dictionary = SitecoreContext.get()['dictionary'];
package/src/debug.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { debug as coreDebug } from '@sitecore-content-sdk/core';
2
+ import { debug as contentDebug } from '@sitecore-content-sdk/content';
3
+
4
+ /**
5
+ * Unified debug object containing all debug namespaces from referenced content-sdk packages.
6
+ * @public
7
+ */
8
+ const debug: Record<string, debug.Debugger> = {
9
+ ...coreDebug,
10
+ ...contentDebug,
11
+ };
12
+
13
+ export default debug;
@@ -1,9 +1,9 @@
1
1
  /* eslint-disable no-unused-expressions */
2
2
  import { expect } from 'chai';
3
3
  import { EditingConfigMiddleware } from './editing-config-middleware';
4
- import { QUERY_PARAM_EDITING_SECRET } from '@sitecore-content-sdk/core/editing';
4
+ import { QUERY_PARAM_EDITING_SECRET } from '@sitecore-content-sdk/content/editing';
5
5
  import { AstroContentSdkComponent } from '../sharedTypes/component-props';
6
- import { mockRequest as MockRequest, Query } from '../test-data/helpers';
6
+ import { mockRequest as MockRequest, Query } from '../tests/helpers';
7
7
 
8
8
  const allowedOrigin = 'https://allowed.com';
9
9
 
@@ -116,17 +116,15 @@ describe('EditingConfigMiddleware', () => {
116
116
  const res = await handler(req);
117
117
 
118
118
  expect(res.headers.has('Access-Control-Allow-Origin')).to.be.true;
119
- expect(res.headers.get('Access-Control-Allow-Origin')).to.equal(
120
- allowedOrigin
121
- );
119
+ expect(res.headers.get('Access-Control-Allow-Origin')).to.include(allowedOrigin);
122
120
 
123
121
  expect(res.headers.has('Access-Control-Allow-Methods')).to.be.true;
124
- expect(res.headers.get('Access-Control-Allow-Methods')).to.equal(
122
+ expect(res.headers.get('Access-Control-Allow-Methods')).to.include(
125
123
  'GET, POST, OPTIONS, DELETE, PUT, PATCH'
126
124
  );
127
125
 
128
126
  expect(res.headers.has('Access-Control-Allow-Headers')).to.be.true;
129
- expect(res.headers.get('Access-Control-Allow-Headers')).to.equal(
127
+ expect(res.headers.get('Access-Control-Allow-Headers')).to.include(
130
128
  'Content-Type, Authorization'
131
129
  );
132
130
 
@@ -1,14 +1,18 @@
1
1
  import {
2
2
  EDITING_ALLOWED_ORIGINS,
3
3
  QUERY_PARAM_EDITING_SECRET,
4
- } from '@sitecore-content-sdk/core/editing';
5
- import { debug } from '@sitecore-content-sdk/core';
6
- import { Metadata } from '@sitecore-content-sdk/core/editing';
7
- import { getEnforcedCorsHeaders } from '@sitecore-content-sdk/core/utils';
8
- import { EditMode } from '@sitecore-content-sdk/core/layout';
4
+ } from '@sitecore-content-sdk/content/editing';
5
+ import debug from '../debug';
6
+ import { Metadata } from '@sitecore-content-sdk/core/node-tools';
7
+ import { getEnforcedCorsHeaders } from '@sitecore-content-sdk/core/tools';
8
+ import { EditMode } from '@sitecore-content-sdk/content/layout';
9
9
  import { getEditingSecret } from '../utils';
10
10
  import { AstroContentSdkComponent, ComponentMap } from '../sharedTypes/component-props';
11
11
 
12
+ /**
13
+ * The interface for the EditingConfigMiddleware configuration.
14
+ * @public
15
+ */
12
16
  export type EditingConfigMiddlewareConfig = {
13
17
  /**
14
18
  * Components available in the application
@@ -23,6 +27,7 @@ export type EditingConfigMiddlewareConfig = {
23
27
  /**
24
28
  * Middleware / handler used in the editing config API route in xmcloud add on (e.g. '/api/editing/config')
25
29
  * provides configuration information to determine feature compatibility on Pages side.
30
+ * @public
26
31
  */
27
32
  export class EditingConfigMiddleware {
28
33
  /**
@@ -39,7 +44,7 @@ export class EditingConfigMiddleware {
39
44
  }
40
45
 
41
46
  private handler = async (_req: Request): Promise<Response> => {
42
- const url = new URL(_req.url.toLowerCase());
47
+ const url = new URL(_req.url);
43
48
  const secret = url.searchParams.get(QUERY_PARAM_EDITING_SECRET);
44
49
 
45
50
  const _res = new Response();
@@ -88,7 +93,6 @@ export class EditingConfigMiddleware {
88
93
  if (_req.method === 'OPTIONS') {
89
94
  debug.editing('preflight request');
90
95
 
91
- // CORS headers are set by enforceCors
92
96
  return new Response(null, {
93
97
  status: 204,
94
98
  headers: _res.headers,