Skip to content

Commit 16c5b2e

Browse files
authored
Merge pull request #113 from Relewise/feat/allow-setting-cache-mode
feat: allow overwriting the cache mode
2 parents 308043c + 8fde5d6 commit 16c5b2e

File tree

2 files changed

+67
-12
lines changed

2 files changed

+67
-12
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,18 @@ Replace the `RELEWISE_DATASET_ID`, `RELEWISE_API_KEY` and `RELEWISE_SERVER_URL`
4040
After which you have access to various methods depending on the client you've bootstrapped.
4141

4242
***Note: serverUrl is not required and will default to https://api.relewise.com/***
43+
44+
#### Cache mode
45+
By default, clients use `cache: 'no-cache'` to ensure responses are always fresh — this prevents stale results that could break personalization.
46+
However, some service workers (often used in integrations) do not support the `no-cache` mode.
47+
48+
```ts
49+
const integrator = new Integrator(RELEWISE_DATASET_ID, RELEWISE_API_KEY, {
50+
serverUrl: RELEWISE_SERVER_URL,
51+
cache: 'default'
52+
});
53+
```
54+
4355
### Tracking
4456

4557
If you need to track e.g. Product-, Category or Content Views, track Cart Updates or Completed Orders in your solution, you need to use the `Tracker`

packages/client/src/relewise.client.ts

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { error } from 'console';
21
import version from './version';
32

43
export interface RelewiseClientOptions {
54
serverUrl?: string;
5+
cache?: RequestCache;
66
}
77

88
export interface RelewiseRequestOptions {
9-
abortSignal?: AbortSignal
9+
abortSignal?: AbortSignal;
1010
}
1111

1212
export class ProblemDetailsError extends Error {
@@ -35,6 +35,7 @@ export abstract class RelewiseClient {
3535
private readonly _serverUrl: string = 'https://api.relewise.com';
3636
private readonly _urlPath: string = 'v1';
3737
private readonly _apiKeyHeader: string;
38+
private readonly cache: RequestCache = 'no-cache';
3839

3940
constructor(protected readonly datasetId: string, protected readonly apiKey: string, options?: RelewiseClientOptions) {
4041
if (!datasetId) throw new Error('Dataset id cannot be null or empty. Please contact Relewise if you don\'t have an account already or would like a free demo license');
@@ -45,6 +46,9 @@ export abstract class RelewiseClient {
4546
if (options?.serverUrl) {
4647
this._serverUrl = options.serverUrl;
4748
}
49+
if (options?.cache) {
50+
this.cache = options.cache;
51+
}
4852
}
4953

5054
public get serverUrl(): string {
@@ -64,26 +68,26 @@ export abstract class RelewiseClient {
6468
},
6569
body: JSON.stringify(data),
6670
signal: options?.abortSignal,
67-
cache: 'no-cache',
71+
cache: this.cache,
6872
});
6973

7074
if (!response.ok) {
7175
let responseMessage: HttpProblemDetails | null = null;
72-
73-
try {
76+
77+
try {
7478
responseMessage = await response.json();
75-
} catch (_) {
79+
} catch (_) {
7680
}
77-
81+
7882
const details = responseMessage?.detail ? `Details: ${responseMessage.detail}\n` : '';
79-
83+
8084
throw new ProblemDetailsError(`Error when calling the Relewise API.\n\nTitle: ${response.statusText}\nStatus: ${response.status}\n${details}\nRead more in the details property if there is error response or look in the network tab.`, responseMessage);
8185
}
8286

8387
return await this.parseJson<TResponse>(response);
8488

8589
} catch (err) {
86-
this.handleRequestError(err);
90+
this.handleRequestError(err);
8791
}
8892
}
8993

@@ -97,11 +101,50 @@ export abstract class RelewiseClient {
97101
private handleRequestError(err: unknown): never {
98102
if (err instanceof ProblemDetailsError) throw err;
99103
if (err instanceof DOMException) throw err;
100-
101-
console.error("Network error or preflight request failed. Check API Key and Dataset ID.");
102-
throw new Error("Network error or preflight request failed. Check API Key and Dataset ID.");
104+
105+
let extraInfo = '';
106+
let possibleCause: string | null = null;
107+
108+
if (err instanceof Error) {
109+
extraInfo += `\nOriginal error: ${err.name} - ${err.message}`;
110+
if ((err as any).code) {
111+
extraInfo += `\nCode: ${(err as any).code}`;
112+
}
113+
114+
const message = err.message.toLowerCase();
115+
116+
if (message.includes('failed to fetch')) {
117+
possibleCause = 'Failed to connect to API. Possible network outage, incorrect server URL, or CORS/preflight issue.';
118+
}
119+
else if (message.includes('401') || message.includes('unauthorized')) {
120+
possibleCause = 'Unauthorized: Your API Key might be missing, expired, or incorrect.';
121+
}
122+
else if (message.includes('403') || message.includes('forbidden')) {
123+
possibleCause = 'Forbidden: Your API Key might not have access to this dataset.';
124+
}
125+
else if (message.includes('404') || message.includes('not found')) {
126+
possibleCause = 'Not Found: The Dataset ID or endpoint may be incorrect.';
127+
}
128+
}
129+
else {
130+
extraInfo += `\nNon-Error thrown: ${JSON.stringify(err)}`;
131+
}
132+
133+
const errorMessage =
134+
"Network error or preflight request failed.\n" +
135+
(possibleCause ? `Possible cause: ${possibleCause}\n` : "") +
136+
"Troubleshooting steps:\n" +
137+
"- Check your API Key is correct and active\n" +
138+
"- Verify the Dataset ID exists and is correctly spelled\n" +
139+
"- Ensure the server URL is reachable from your network\n" +
140+
"- Check browser console/network tab for blocked requests or CORS issues" +
141+
extraInfo;
142+
143+
console.error(errorMessage);
144+
throw new Error(errorMessage);
103145
}
104146

147+
105148
private async parseJson<T>(response: Response): Promise<T | undefined> {
106149
try {
107150
return await response.json();

0 commit comments

Comments
 (0)