@adobe/spacecat-shared-tokowaka-client 1.3.1 → 1.4.0

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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [@adobe/spacecat-shared-tokowaka-client-v1.4.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tokowaka-client-v1.3.2...@adobe/spacecat-shared-tokowaka-client-v1.4.0) (2025-12-11)
2
+
3
+
4
+ ### Features
5
+
6
+ * Generic mapper hast ([#1236](https://github.com/adobe/spacecat-shared/issues/1236)) ([9791ca6](https://github.com/adobe/spacecat-shared/commit/9791ca6fd2b7a5880ac0ca99897da87631bbc25a))
7
+
8
+ # [@adobe/spacecat-shared-tokowaka-client-v1.3.2](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tokowaka-client-v1.3.1...@adobe/spacecat-shared-tokowaka-client-v1.3.2) (2025-12-11)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * tokowaka url header for preview ([#1235](https://github.com/adobe/spacecat-shared/issues/1235)) ([f265db8](https://github.com/adobe/spacecat-shared/commit/f265db821a9ea54809850e7fc771fdf3554f324f))
14
+
1
15
  # [@adobe/spacecat-shared-tokowaka-client-v1.3.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tokowaka-client-v1.3.0...@adobe/spacecat-shared-tokowaka-client-v1.3.1) (2025-12-10)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-tokowaka-client",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "Tokowaka Client for SpaceCat - Edge optimization config management",
5
5
  "type": "module",
6
6
  "engines": {
@@ -57,7 +57,7 @@ export default class GenericMapper extends BaseOpportunityMapper {
57
57
  ...this.createBasePatch(suggestion, opportunityId),
58
58
  op: transformRules.action,
59
59
  selector: transformRules.selector,
60
- value: data.patchValue,
60
+ value: data.format === 'hast' ? JSON.parse(data.patchValue) : data.patchValue,
61
61
  valueFormat: data.format || 'text',
62
62
  target: TARGET_USER_AGENTS_CATEGORIES.AI_BOTS,
63
63
  };
@@ -138,14 +138,8 @@ export async function fetchHtmlWithWarmup(
138
138
 
139
139
  // Parse the URL to extract path and construct full URL
140
140
  const urlObj = new URL(url);
141
- const urlPath = urlObj.pathname + urlObj.search;
142
-
143
- // Add tokowakaPreview param for optimized HTML
141
+ const urlPath = urlObj.pathname;
144
142
  let fullUrl = `${tokowakaEdgeUrl}${urlPath}`;
145
- if (isOptimized) {
146
- const separator = urlPath.includes('?') ? '&' : '?';
147
- fullUrl = `${fullUrl}${separator}tokowakaPreview=true`;
148
- }
149
143
 
150
144
  const headers = {
151
145
  'x-forwarded-host': forwardedHost,
@@ -153,6 +147,12 @@ export async function fetchHtmlWithWarmup(
153
147
  'x-tokowaka-url': urlPath,
154
148
  };
155
149
 
150
+ if (isOptimized) {
151
+ // Add tokowakaPreview param for optimized HTML
152
+ fullUrl = `${fullUrl}?tokowakaPreview=true`;
153
+ headers['x-tokowaka-url'] = `${urlPath}?tokowakaPreview=true`;
154
+ }
155
+
156
156
  const fetchOptions = {
157
157
  method: 'GET',
158
158
  headers,
@@ -586,7 +586,6 @@ describe('GenericMapper', () => {
586
586
  selector: '#selector',
587
587
  },
588
588
  patchValue: 'Content with tag',
589
- format: 'hast',
590
589
  tag: 'div',
591
590
  url: 'https://example.com/page',
592
591
  }),
@@ -601,7 +600,7 @@ describe('GenericMapper', () => {
601
600
  op: 'insertAfter',
602
601
  selector: '#selector',
603
602
  value: 'Content with tag',
604
- valueFormat: 'hast',
603
+ valueFormat: 'text',
605
604
  tag: 'div',
606
605
  opportunityId: 'opp-tag',
607
606
  suggestionId: 'sugg-with-tag',
@@ -633,6 +632,60 @@ describe('GenericMapper', () => {
633
632
  expect(patch.valueFormat).to.equal('text');
634
633
  });
635
634
 
635
+ it('should parse JSON patchValue when format is hast', () => {
636
+ const hastValue = {
637
+ type: 'element',
638
+ tagName: 'div',
639
+ properties: { className: ['test-class'] },
640
+ children: [{ type: 'text', value: 'Test content' }],
641
+ };
642
+
643
+ const suggestion = {
644
+ getId: () => 'sugg-hast-json',
645
+ getUpdatedAt: () => '2025-01-15T10:00:00.000Z',
646
+ getData: () => ({
647
+ transformRules: {
648
+ action: 'insertAfter',
649
+ selector: '#selector',
650
+ },
651
+ patchValue: JSON.stringify(hastValue),
652
+ format: 'hast',
653
+ url: 'https://example.com/page',
654
+ }),
655
+ };
656
+
657
+ const patches = mapper.suggestionsToPatches('/page', [suggestion], 'opp-hast');
658
+
659
+ expect(patches.length).to.equal(1);
660
+ const patch = patches[0];
661
+
662
+ expect(patch.value).to.deep.equal(hastValue);
663
+ expect(patch.valueFormat).to.equal('hast');
664
+ });
665
+
666
+ it('should use raw patchValue when format is not hast', () => {
667
+ const suggestion = {
668
+ getId: () => 'sugg-text',
669
+ getUpdatedAt: () => '2025-01-15T10:00:00.000Z',
670
+ getData: () => ({
671
+ transformRules: {
672
+ action: 'insertAfter',
673
+ selector: '#selector',
674
+ },
675
+ patchValue: 'Plain text content',
676
+ url: 'https://example.com/page',
677
+ }),
678
+ };
679
+
680
+ const patches = mapper.suggestionsToPatches('/page', [suggestion], 'opp-text');
681
+
682
+ expect(patches.length).to.equal(1);
683
+ const patch = patches[0];
684
+
685
+ expect(patch.value).to.equal('Plain text content');
686
+ expect(patch.valueFormat).to.equal('text');
687
+ });
688
+
636
689
  it('should not include UI-only fields in patch', () => {
637
690
  const suggestion = {
638
691
  getId: () => 'sugg-ui',
@@ -123,7 +123,7 @@ describe('HTML Utils', () => {
123
123
  expect(fetchStub.callCount).to.equal(2); // warmup + actual
124
124
  });
125
125
 
126
- it('should handle URL with existing query parameters when fetching optimized HTML', async () => {
126
+ it('should drop query parameters from URL when fetching optimized HTML', async () => {
127
127
  fetchStub.resolves({
128
128
  ok: true,
129
129
  status: 200,
@@ -147,11 +147,11 @@ describe('HTML Utils', () => {
147
147
  expect(html).to.equal('<html>Optimized HTML</html>');
148
148
  expect(fetchStub.callCount).to.equal(2); // warmup + actual
149
149
 
150
- // Verify the URL includes & for the preview param (not ?)
150
+ // Verify original query params are dropped and only tokowakaPreview is present
151
151
  const actualUrl = fetchStub.secondCall.args[0];
152
- expect(actualUrl).to.include('param=value');
153
- expect(actualUrl).to.include('&tokowakaPreview=true');
154
- expect(actualUrl).to.not.include('?tokowakaPreview=true');
152
+ expect(actualUrl).to.not.include('param=value');
153
+ expect(actualUrl).to.include('?tokowakaPreview=true');
154
+ expect(actualUrl).to.equal('https://edge.example.com/page?tokowakaPreview=true');
155
155
  });
156
156
 
157
157
  it('should throw error when HTTP response is not ok', async () => {