@stacksjs/browser-extension 0.70.247 → 0.70.248
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/firefox-previews.d.ts +1 -1
- package/dist/firefox-previews.js +23 -12
- package/package.json +1 -1
|
@@ -17,7 +17,7 @@ export declare function imageSize(bytes: Uint8Array): { width: number, height: n
|
|
|
17
17
|
*/
|
|
18
18
|
export declare function amoToken(issuer: string, secret: string, now?: number): string;
|
|
19
19
|
/** Read the previews a listing currently shows. */
|
|
20
|
-
export declare function listFirefoxPreviews(addonId: string,
|
|
20
|
+
export declare function listFirefoxPreviews(addonId: string, auth: { issuer: string, secret: string }): Promise<FirefoxPreview[]>;
|
|
21
21
|
/**
|
|
22
22
|
* Bring the listing's screenshots in line with the config.
|
|
23
23
|
*
|
package/dist/firefox-previews.js
CHANGED
|
@@ -37,19 +37,30 @@ function resolveAuth(options) {
|
|
|
37
37
|
throw Error(`[browser-extension] missing Firefox Add-ons credentials: ${missing.join(", ")}`);
|
|
38
38
|
return { issuer, secret };
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
41
|
+
function retryAfterMs(response, body) {
|
|
42
|
+
const header = Number(response.headers.get("retry-after"));
|
|
43
|
+
if (Number.isFinite(header) && header > 0)
|
|
44
|
+
return header * 1000;
|
|
45
|
+
const stated = /available in (\d+) seconds?/i.exec(body);
|
|
46
|
+
return stated ? Number(stated[1]) * 1000 : void 0;
|
|
47
|
+
}
|
|
48
|
+
async function amo(path, auth, init = {}, attempt = 0) {
|
|
41
49
|
const response = await fetch(`${AMO_API}${path}`, {
|
|
42
50
|
...init,
|
|
43
|
-
headers: { Authorization: `JWT ${
|
|
51
|
+
headers: { Authorization: `JWT ${amoToken(auth.issuer, auth.secret)}`, ...init.headers }
|
|
44
52
|
});
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
if (response.ok || response.status === 404)
|
|
54
|
+
return response;
|
|
55
|
+
const detail = await response.text().catch(() => "");
|
|
56
|
+
if (response.status === 429 && attempt < 4) {
|
|
57
|
+
await sleep((retryAfterMs(response, detail) ?? 60000) + 1000);
|
|
58
|
+
return amo(path, auth, init, attempt + 1);
|
|
48
59
|
}
|
|
49
|
-
|
|
60
|
+
throw Error(`[browser-extension] AMO ${init.method ?? "GET"} ${path} failed (${response.status})${detail ? `: ${detail.slice(0, 300)}` : ""}`);
|
|
50
61
|
}
|
|
51
|
-
export async function listFirefoxPreviews(addonId,
|
|
52
|
-
const response = await amo(`/addons/addon/${encodeURIComponent(addonId)}/`,
|
|
62
|
+
export async function listFirefoxPreviews(addonId, auth) {
|
|
63
|
+
const response = await amo(`/addons/addon/${encodeURIComponent(addonId)}/`, auth);
|
|
53
64
|
if (response.status === 404)
|
|
54
65
|
return [];
|
|
55
66
|
return ((await response.json()).previews ?? []).map((preview, index) => ({
|
|
@@ -69,7 +80,7 @@ export async function syncFirefoxPreviews(config, options = {}) {
|
|
|
69
80
|
throw Error(`[browser-extension] Firefox screenshot not found: ${path}`);
|
|
70
81
|
})), size = imageSize(bytes);
|
|
71
82
|
return { path: file, bytes, width: size?.width ?? 0, height: size?.height ?? 0 };
|
|
72
|
-
})),
|
|
83
|
+
})), auth = resolveAuth(options), existing = await listFirefoxPreviews(config.geckoId, auth);
|
|
73
84
|
if (files.every((file) => file.width > 0 && file.height > 0) && existing.length === files.length && existing.slice().sort((a, b) => a.position - b.position).every((preview, index) => preview.size[0] === files[index].width && preview.size[1] === files[index].height))
|
|
74
85
|
return { unchanged: !0, uploaded: [], removed: [] };
|
|
75
86
|
if (options.dryRun)
|
|
@@ -79,12 +90,12 @@ export async function syncFirefoxPreviews(config, options = {}) {
|
|
|
79
90
|
const form = new FormData;
|
|
80
91
|
form.append("image", new Blob([file.bytes], { type: "image/png" }), basename(file.path));
|
|
81
92
|
form.append("position", String(index));
|
|
82
|
-
const created = await (await amo(`/addons/addon/${encodeURIComponent(config.geckoId)}/previews/`,
|
|
93
|
+
const created = await (await amo(`/addons/addon/${encodeURIComponent(config.geckoId)}/previews/`, auth, {
|
|
83
94
|
method: "POST",
|
|
84
95
|
body: form
|
|
85
96
|
})).json(), caption = store.screenshotCaptions?.[index];
|
|
86
97
|
if (caption)
|
|
87
|
-
await amo(`/addons/addon/${encodeURIComponent(config.geckoId)}/previews/${created.id}/`,
|
|
98
|
+
await amo(`/addons/addon/${encodeURIComponent(config.geckoId)}/previews/${created.id}/`, auth, {
|
|
88
99
|
method: "PATCH",
|
|
89
100
|
headers: { "Content-Type": "application/json" },
|
|
90
101
|
body: JSON.stringify({ caption: { "en-US": caption } })
|
|
@@ -93,7 +104,7 @@ export async function syncFirefoxPreviews(config, options = {}) {
|
|
|
93
104
|
}
|
|
94
105
|
const removed = [];
|
|
95
106
|
for (const preview of existing) {
|
|
96
|
-
await amo(`/addons/addon/${encodeURIComponent(config.geckoId)}/previews/${preview.id}/`,
|
|
107
|
+
await amo(`/addons/addon/${encodeURIComponent(config.geckoId)}/previews/${preview.id}/`, auth, { method: "DELETE" });
|
|
97
108
|
removed.push(preview.id);
|
|
98
109
|
}
|
|
99
110
|
return { unchanged: !1, uploaded, removed };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/browser-extension",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.70.
|
|
4
|
+
"version": "0.70.248",
|
|
5
5
|
"description": "Build MV3 browser extensions (Chrome, Firefox, Safari) the Stacks way — manifest, content/background scripts, DNR rules, packaging, Safari container app, all config-driven.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
7
|
"contributors": [
|