@lovalingo/lovalingo 0.5.21 → 0.5.23
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/dist/utils/api.js +48 -1
- package/package.json +1 -1
package/dist/utils/api.js
CHANGED
|
@@ -1,9 +1,48 @@
|
|
|
1
1
|
import { warnDebug, errorDebug } from './logger';
|
|
2
|
+
const OK_HTTP_STATUSES = new Set([200, 201]);
|
|
3
|
+
function getNavigationResponseStatus() {
|
|
4
|
+
if (typeof performance === "undefined" || typeof performance.getEntriesByType !== "function")
|
|
5
|
+
return null;
|
|
6
|
+
const entries = performance.getEntriesByType("navigation");
|
|
7
|
+
if (!entries || entries.length === 0)
|
|
8
|
+
return null;
|
|
9
|
+
const entry = entries[0];
|
|
10
|
+
const rawStatus = entry?.responseStatus;
|
|
11
|
+
const status = typeof rawStatus === "number" ? Math.floor(rawStatus) : NaN;
|
|
12
|
+
if (!Number.isFinite(status) || status <= 0)
|
|
13
|
+
return null;
|
|
14
|
+
return status;
|
|
15
|
+
}
|
|
16
|
+
// Why: avoid tracking misses/pageviews for non-OK responses (404/5xx) so bad routes don't pollute discovery.
|
|
17
|
+
function isOkHttpStatus(status) {
|
|
18
|
+
if (typeof status !== "number")
|
|
19
|
+
return true;
|
|
20
|
+
return OK_HTTP_STATUSES.has(status);
|
|
21
|
+
}
|
|
22
|
+
function normalizeApiBase(raw) {
|
|
23
|
+
const input = (raw || "").toString().trim();
|
|
24
|
+
if (!input)
|
|
25
|
+
return "https://cdn.lovalingo.com";
|
|
26
|
+
let base = input.replace(/\/functions\/v1\/?$/i, "").replace(/\/$/, "");
|
|
27
|
+
try {
|
|
28
|
+
const parsed = new URL(base);
|
|
29
|
+
const host = parsed.hostname.toLowerCase();
|
|
30
|
+
// Why: runtime endpoints moved off Supabase Edge Functions; fall back to CDN if a Supabase host is supplied.
|
|
31
|
+
if (host.endsWith(".supabase.co")) {
|
|
32
|
+
warnDebug("LovalingoAPI", `apiBase points to Supabase (${host}); falling back to https://cdn.lovalingo.com`);
|
|
33
|
+
return "https://cdn.lovalingo.com";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// Ignore parse errors and keep the raw base.
|
|
38
|
+
}
|
|
39
|
+
return base;
|
|
40
|
+
}
|
|
2
41
|
export class LovalingoAPI {
|
|
3
42
|
constructor(apiKey, apiBase, pathConfig, editKey) {
|
|
4
43
|
this.entitlements = null;
|
|
5
44
|
this.apiKey = apiKey;
|
|
6
|
-
this.apiBase = apiBase;
|
|
45
|
+
this.apiBase = normalizeApiBase(apiBase);
|
|
7
46
|
this.pathConfig = pathConfig;
|
|
8
47
|
this.editKey = editKey;
|
|
9
48
|
}
|
|
@@ -126,6 +165,9 @@ export class LovalingoAPI {
|
|
|
126
165
|
try {
|
|
127
166
|
if (!this.hasApiKey())
|
|
128
167
|
return;
|
|
168
|
+
const status = getNavigationResponseStatus();
|
|
169
|
+
if (!isOkHttpStatus(status))
|
|
170
|
+
return;
|
|
129
171
|
const params = new URLSearchParams();
|
|
130
172
|
params.set("key", this.apiKey);
|
|
131
173
|
params.set("path", pathOrUrl);
|
|
@@ -154,6 +196,10 @@ export class LovalingoAPI {
|
|
|
154
196
|
return null;
|
|
155
197
|
if (!Array.isArray(misses) || misses.length === 0)
|
|
156
198
|
return null;
|
|
199
|
+
const status = getNavigationResponseStatus();
|
|
200
|
+
if (!isOkHttpStatus(status)) {
|
|
201
|
+
return { ignored: true, reason: "http_status" };
|
|
202
|
+
}
|
|
157
203
|
const pathParam = this.buildPathParam(opts?.pathOrUrl);
|
|
158
204
|
const response = await fetch(`${this.apiBase}/functions/v1/misses`, {
|
|
159
205
|
method: "POST",
|
|
@@ -164,6 +210,7 @@ export class LovalingoAPI {
|
|
|
164
210
|
path: pathParam,
|
|
165
211
|
source_locale: opts?.sourceLocale,
|
|
166
212
|
locales: Array.isArray(opts?.locales) ? opts?.locales : undefined,
|
|
213
|
+
page_status: typeof status === "number" ? status : undefined,
|
|
167
214
|
misses,
|
|
168
215
|
}),
|
|
169
216
|
});
|
package/package.json
CHANGED