@adobe/spacecat-shared-tokowaka-client 1.6.0 → 1.6.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/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/src/index.js +4 -17
- package/src/utils/custom-html-utils.js +2 -6
- package/test/index.test.js +48 -39
- package/test/utils/html-utils.test.js +27 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [@adobe/spacecat-shared-tokowaka-client-v1.6.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tokowaka-client-v1.6.0...@adobe/spacecat-shared-tokowaka-client-v1.6.1) (2026-01-30)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* api key now optional for edge-preview ([#1299](https://github.com/adobe/spacecat-shared/issues/1299)) ([76eb046](https://github.com/adobe/spacecat-shared/commit/76eb04640dab752a83909a51827abde1e41fc57e))
|
|
7
|
+
|
|
1
8
|
# [@adobe/spacecat-shared-tokowaka-client-v1.6.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tokowaka-client-v1.5.8...@adobe/spacecat-shared-tokowaka-client-v1.6.0) (2026-01-29)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -913,26 +913,13 @@ class TokowakaClient {
|
|
|
913
913
|
}
|
|
914
914
|
|
|
915
915
|
// Fetch metaconfig to get API key
|
|
916
|
-
const metaconfig = await this.fetchMetaconfig(previewUrl);
|
|
916
|
+
const metaconfig = await this.fetchMetaconfig(previewUrl) || {};
|
|
917
917
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
+ 'A domain-level metaconfig needs to be created first before previewing suggestions.',
|
|
922
|
-
HTTP_INTERNAL_SERVER_ERROR,
|
|
923
|
-
);
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
const { apiKeys } = metaconfig;
|
|
927
|
-
if (!Array.isArray(apiKeys) || apiKeys.length === 0 || !hasText(apiKeys[0])) {
|
|
928
|
-
throw this.#createError(
|
|
929
|
-
'Metaconfig does not have valid API keys configured. '
|
|
930
|
-
+ 'Please ensure the metaconfig has at least one API key.',
|
|
931
|
-
HTTP_INTERNAL_SERVER_ERROR,
|
|
932
|
-
);
|
|
918
|
+
let apiKey;
|
|
919
|
+
if (Array.isArray(metaconfig.apiKeys) && metaconfig.apiKeys.length > 0) {
|
|
920
|
+
[apiKey] = metaconfig.apiKeys;
|
|
933
921
|
}
|
|
934
922
|
|
|
935
|
-
const apiKey = apiKeys[0];
|
|
936
923
|
const forwardedHost = calculateForwardedHost(previewUrl, this.log);
|
|
937
924
|
|
|
938
925
|
// Fetch existing deployed configuration for this URL from production S3
|
|
@@ -104,7 +104,7 @@ async function fetchWithRetry(url, options, maxRetries, retryDelayMs, log, fetch
|
|
|
104
104
|
* Fetches HTML content from edge with warmup call and retry logic
|
|
105
105
|
* Makes an initial warmup call, waits, then makes the actual call with retries
|
|
106
106
|
* @param {string} url - Full URL to fetch
|
|
107
|
-
* @param {string} apiKey - Edge Optimize API key
|
|
107
|
+
* @param {string} apiKey - Edge Optimize API key (optional)
|
|
108
108
|
* @param {string} forwardedHost - Host to forward in x-forwarded-host header
|
|
109
109
|
* @param {string} edgeUrl - Edge URL
|
|
110
110
|
* @param {boolean} isOptimized - Whether to fetch optimized HTML (with preview param)
|
|
@@ -130,10 +130,6 @@ export async function fetchHtmlWithWarmup(
|
|
|
130
130
|
throw new Error('URL is required for fetching HTML');
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
if (!hasText(apiKey)) {
|
|
134
|
-
throw new Error('Edge Optimize API key is required for fetching HTML');
|
|
135
|
-
}
|
|
136
|
-
|
|
137
133
|
if (!hasText(forwardedHost)) {
|
|
138
134
|
throw new Error('Forwarded host is required for fetching HTML');
|
|
139
135
|
}
|
|
@@ -158,7 +154,7 @@ export async function fetchHtmlWithWarmup(
|
|
|
158
154
|
|
|
159
155
|
const headers = {
|
|
160
156
|
'x-forwarded-host': forwardedHost,
|
|
161
|
-
'x-edgeoptimize-api-key': apiKey,
|
|
157
|
+
...(apiKey && { 'x-edgeoptimize-api-key': apiKey }),
|
|
162
158
|
'x-edgeoptimize-url': urlPath,
|
|
163
159
|
'Accept-Encoding': 'identity', // Disable compression to avoid content-length: 0 issue
|
|
164
160
|
};
|
package/test/index.test.js
CHANGED
|
@@ -2941,61 +2941,70 @@ describe('TokowakaClient', () => {
|
|
|
2941
2941
|
}
|
|
2942
2942
|
});
|
|
2943
2943
|
|
|
2944
|
-
it('should
|
|
2944
|
+
it('should preview suggestions successfully without metaconfig (optional)', async () => {
|
|
2945
|
+
// Override the stub from beforeEach to return null
|
|
2945
2946
|
client.fetchMetaconfig.resolves(null);
|
|
2946
2947
|
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
}
|
|
2954
|
-
});
|
|
2948
|
+
const result = await client.previewSuggestions(
|
|
2949
|
+
mockSite,
|
|
2950
|
+
mockOpportunity,
|
|
2951
|
+
mockSuggestions,
|
|
2952
|
+
{ warmupDelayMs: 0 },
|
|
2953
|
+
);
|
|
2955
2954
|
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2955
|
+
expect(result.succeededSuggestions).to.have.length(2);
|
|
2956
|
+
expect(result.failedSuggestions).to.have.length(0);
|
|
2957
|
+
expect(result.config).to.exist;
|
|
2958
|
+
expect(result.html).to.exist;
|
|
2959
|
+
expect(result.html.originalHtml).to.equal('<html><body>Test HTML</body></html>');
|
|
2960
|
+
expect(result.html.optimizedHtml).to.equal('<html><body>Test HTML</body></html>');
|
|
2961
2961
|
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
expect.fail('Should have thrown error');
|
|
2965
|
-
} catch (error) {
|
|
2966
|
-
expect(error.message).to.include('Metaconfig does not have valid API keys configured');
|
|
2967
|
-
expect(error.status).to.equal(500);
|
|
2968
|
-
}
|
|
2962
|
+
// Verify fetch was called without API key (undefined)
|
|
2963
|
+
expect(fetchStub.callCount).to.equal(4); // 2 warmup + 2 actual (original + optimized)
|
|
2969
2964
|
});
|
|
2970
2965
|
|
|
2971
|
-
it('should
|
|
2966
|
+
it('should preview suggestions successfully without apiKeys in metaconfig (optional)', async () => {
|
|
2967
|
+
// Override the stub from beforeEach
|
|
2972
2968
|
client.fetchMetaconfig.resolves({
|
|
2973
2969
|
siteId: 'site-123',
|
|
2974
|
-
apiKeys
|
|
2970
|
+
// apiKeys missing - should work without it
|
|
2975
2971
|
});
|
|
2976
2972
|
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2973
|
+
const result = await client.previewSuggestions(
|
|
2974
|
+
mockSite,
|
|
2975
|
+
mockOpportunity,
|
|
2976
|
+
mockSuggestions,
|
|
2977
|
+
{ warmupDelayMs: 0 },
|
|
2978
|
+
);
|
|
2979
|
+
|
|
2980
|
+
expect(result.succeededSuggestions).to.have.length(2);
|
|
2981
|
+
expect(result.failedSuggestions).to.have.length(0);
|
|
2982
|
+
expect(result.config).to.exist;
|
|
2983
|
+
expect(result.html).to.exist;
|
|
2984
|
+
expect(result.html.originalHtml).to.equal('<html><body>Test HTML</body></html>');
|
|
2985
|
+
expect(result.html.optimizedHtml).to.equal('<html><body>Test HTML</body></html>');
|
|
2986
|
+
expect(fetchStub.callCount).to.equal(4);
|
|
2984
2987
|
});
|
|
2985
2988
|
|
|
2986
|
-
it('should
|
|
2989
|
+
it('should preview suggestions successfully with empty apiKeys array (optional)', async () => {
|
|
2990
|
+
// Override the stub from beforeEach
|
|
2987
2991
|
client.fetchMetaconfig.resolves({
|
|
2988
2992
|
siteId: 'site-123',
|
|
2989
|
-
apiKeys: [
|
|
2993
|
+
apiKeys: [],
|
|
2990
2994
|
});
|
|
2991
2995
|
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2996
|
+
const result = await client.previewSuggestions(
|
|
2997
|
+
mockSite,
|
|
2998
|
+
mockOpportunity,
|
|
2999
|
+
mockSuggestions,
|
|
3000
|
+
{ warmupDelayMs: 0 },
|
|
3001
|
+
);
|
|
3002
|
+
|
|
3003
|
+
expect(result.succeededSuggestions).to.have.length(2);
|
|
3004
|
+
expect(result.failedSuggestions).to.have.length(0);
|
|
3005
|
+
expect(result.config).to.exist;
|
|
3006
|
+
expect(result.html).to.exist;
|
|
3007
|
+
expect(fetchStub.callCount).to.equal(4);
|
|
2999
3008
|
});
|
|
3000
3009
|
|
|
3001
3010
|
it('should throw error for unsupported opportunity type', async () => {
|
|
@@ -82,20 +82,33 @@ describe('HTML Utils', () => {
|
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
-
it('should
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
'
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
85
|
+
it('should successfully fetch HTML without apiKey (optional parameter)', async () => {
|
|
86
|
+
fetchStub.resolves({
|
|
87
|
+
ok: true,
|
|
88
|
+
status: 200,
|
|
89
|
+
statusText: 'OK',
|
|
90
|
+
headers: {
|
|
91
|
+
get: (name) => (name === 'x-edgeoptimize-cache' ? 'HIT' : null),
|
|
92
|
+
},
|
|
93
|
+
text: async () => '<html>Test HTML without API key</html>',
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const html = await fetchHtmlWithWarmup(
|
|
97
|
+
'https://example.com/page',
|
|
98
|
+
null, // apiKey is optional
|
|
99
|
+
'host',
|
|
100
|
+
'https://edge.example.com',
|
|
101
|
+
log,
|
|
102
|
+
false,
|
|
103
|
+
{ warmupDelayMs: 0 },
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
expect(html).to.equal('<html>Test HTML without API key</html>');
|
|
107
|
+
expect(fetchStub.callCount).to.equal(2); // warmup + actual
|
|
108
|
+
|
|
109
|
+
// Verify that x-edgeoptimize-api-key header is not present
|
|
110
|
+
const fetchOptions = fetchStub.firstCall.args[1];
|
|
111
|
+
expect(fetchOptions.headers).to.not.have.property('x-edgeoptimize-api-key');
|
|
99
112
|
});
|
|
100
113
|
|
|
101
114
|
it('should successfully fetch HTML with all required parameters', async () => {
|