extension-from-store 0.1.1 → 0.2.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/README.md +27 -0
- package/bin.cjs +7 -10
- package/bin.js +7 -10
- package/dist/browser.cjs +355 -0
- package/dist/browser.d.ts +44 -0
- package/dist/browser.js +321 -0
- package/dist/core.cjs +301 -0
- package/dist/core.d.ts +10 -0
- package/dist/core.js +222 -0
- package/dist/crx.d.ts +1 -0
- package/dist/extract.d.ts +1 -1
- package/dist/index.cjs +141 -101
- package/dist/index.js +131 -91
- package/dist/manifest.d.ts +7 -0
- package/dist/meta.d.ts +1 -4
- package/dist/node-platform.d.ts +2 -0
- package/dist/platform.d.ts +8 -0
- package/dist/resolve.d.ts +21 -0
- package/dist/stores/chrome.d.ts +2 -1
- package/dist/stores/firefox.d.ts +5 -0
- package/package.json +14 -2
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__ from "node:fs/promises";
|
|
2
|
-
import * as __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__ from "node:path";
|
|
3
2
|
import * as __WEBPACK_EXTERNAL_MODULE_node_os_74b4b876__ from "node:os";
|
|
3
|
+
import * as __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__ from "node:path";
|
|
4
|
+
import * as __WEBPACK_EXTERNAL_MODULE_extract_zip_c4acec5a__ from "extract-zip";
|
|
4
5
|
import * as __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__ from "node:fs";
|
|
5
6
|
import * as __WEBPACK_EXTERNAL_MODULE_node_http_2dc67212__ from "node:http";
|
|
6
7
|
import * as __WEBPACK_EXTERNAL_MODULE_node_https_626f33a7__ from "node:https";
|
|
7
8
|
import * as __WEBPACK_EXTERNAL_MODULE_node_stream_promises_5adae1f2__ from "node:stream/promises";
|
|
8
9
|
import * as __WEBPACK_EXTERNAL_MODULE_node_url_e96de089__ from "node:url";
|
|
9
|
-
import * as __WEBPACK_EXTERNAL_MODULE_extract_zip_c4acec5a__ from "extract-zip";
|
|
10
10
|
function _define_property(obj, key, value) {
|
|
11
11
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
12
12
|
value: value,
|
|
@@ -24,6 +24,48 @@ class errors_extensionFromStoreError extends Error {
|
|
|
24
24
|
this.cause = cause;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
+
function readUInt32LE(bytes, offset) {
|
|
28
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset + offset, Uint32Array.BYTES_PER_ELEMENT);
|
|
29
|
+
return view.getUint32(0, true);
|
|
30
|
+
}
|
|
31
|
+
function readMagic(bytes) {
|
|
32
|
+
let out = '';
|
|
33
|
+
const slice = bytes.subarray(0, 4);
|
|
34
|
+
for(let index = 0; index < slice.length; index += 1)out += String.fromCharCode(slice[index]);
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
function stripCrxHeader(buffer) {
|
|
38
|
+
if (buffer.length < 16) throw new errors_extensionFromStoreError('ExtractionFailed', 'CRX file too small');
|
|
39
|
+
const magic = readMagic(buffer);
|
|
40
|
+
if ('Cr24' !== magic) throw new errors_extensionFromStoreError('ExtractionFailed', 'Invalid CRX header');
|
|
41
|
+
const version = readUInt32LE(buffer, 4);
|
|
42
|
+
if (2 === version) {
|
|
43
|
+
const publicKeyLength = readUInt32LE(buffer, 8);
|
|
44
|
+
const signatureLength = readUInt32LE(buffer, 12);
|
|
45
|
+
const headerSize = 16 + publicKeyLength + signatureLength;
|
|
46
|
+
return buffer.subarray(headerSize);
|
|
47
|
+
}
|
|
48
|
+
if (3 === version) {
|
|
49
|
+
const headerSize = readUInt32LE(buffer, 8);
|
|
50
|
+
return buffer.subarray(12 + headerSize);
|
|
51
|
+
}
|
|
52
|
+
throw new errors_extensionFromStoreError('ExtractionFailed', `Unsupported CRX version ${version}`);
|
|
53
|
+
}
|
|
54
|
+
async function extractCrx(crxPath, extractDir, workDir) {
|
|
55
|
+
const crxBuffer = await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].readFile(crxPath);
|
|
56
|
+
const zipBuffer = Buffer.from(stripCrxHeader(crxBuffer));
|
|
57
|
+
const zipPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(workDir, 'payload.zip');
|
|
58
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].writeFile(zipPath, zipBuffer);
|
|
59
|
+
await (0, __WEBPACK_EXTERNAL_MODULE_extract_zip_c4acec5a__["default"])(zipPath, {
|
|
60
|
+
dir: extractDir
|
|
61
|
+
});
|
|
62
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].unlink(zipPath).catch(()=>void 0);
|
|
63
|
+
}
|
|
64
|
+
async function extractZipArchive(zipPath, extractDir) {
|
|
65
|
+
await (0, __WEBPACK_EXTERNAL_MODULE_extract_zip_c4acec5a__["default"])(zipPath, {
|
|
66
|
+
dir: extractDir
|
|
67
|
+
});
|
|
68
|
+
}
|
|
27
69
|
function createLogger(logger) {
|
|
28
70
|
return {
|
|
29
71
|
info: (message)=>{
|
|
@@ -54,7 +96,8 @@ function request(url, options) {
|
|
|
54
96
|
hostname: target.hostname,
|
|
55
97
|
port: target.port,
|
|
56
98
|
path: `${target.pathname}${target.search}`,
|
|
57
|
-
headers
|
|
99
|
+
headers,
|
|
100
|
+
agent: false
|
|
58
101
|
}, (res)=>{
|
|
59
102
|
resolve({
|
|
60
103
|
statusCode: res.statusCode || 0,
|
|
@@ -105,75 +148,59 @@ async function requestJson(url, options, maxRedirects = 5) {
|
|
|
105
148
|
throw new errors_extensionFromStoreError('StoreIncompatibility', `Invalid JSON response from ${url}`, error);
|
|
106
149
|
}
|
|
107
150
|
}
|
|
108
|
-
function
|
|
109
|
-
if (buffer.length < 16) throw new errors_extensionFromStoreError('ExtractionFailed', 'CRX file too small');
|
|
110
|
-
const magic = buffer.subarray(0, 4).toString('ascii');
|
|
111
|
-
if ('Cr24' !== magic) throw new errors_extensionFromStoreError('ExtractionFailed', 'Invalid CRX header');
|
|
112
|
-
const version = buffer.readUInt32LE(4);
|
|
113
|
-
if (2 === version) {
|
|
114
|
-
const publicKeyLength = buffer.readUInt32LE(8);
|
|
115
|
-
const signatureLength = buffer.readUInt32LE(12);
|
|
116
|
-
const headerSize = 16 + publicKeyLength + signatureLength;
|
|
117
|
-
return buffer.subarray(headerSize);
|
|
118
|
-
}
|
|
119
|
-
if (3 === version) {
|
|
120
|
-
const headerSize = buffer.readUInt32LE(8);
|
|
121
|
-
const offset = 12 + headerSize;
|
|
122
|
-
return buffer.subarray(offset);
|
|
123
|
-
}
|
|
124
|
-
throw new errors_extensionFromStoreError('ExtractionFailed', `Unsupported CRX version ${version}`);
|
|
125
|
-
}
|
|
126
|
-
async function extractCrx(crxPath, extractDir, workDir) {
|
|
127
|
-
const crxBuffer = await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].readFile(crxPath);
|
|
128
|
-
const zipBuffer = stripCrxHeader(crxBuffer);
|
|
129
|
-
const zipPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(workDir, 'payload.zip');
|
|
130
|
-
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].writeFile(zipPath, zipBuffer);
|
|
131
|
-
await (0, __WEBPACK_EXTERNAL_MODULE_extract_zip_c4acec5a__["default"])(zipPath, {
|
|
132
|
-
dir: extractDir
|
|
133
|
-
});
|
|
134
|
-
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].unlink(zipPath).catch(()=>void 0);
|
|
135
|
-
}
|
|
136
|
-
async function extractZipArchive(zipPath, extractDir) {
|
|
137
|
-
await (0, __WEBPACK_EXTERNAL_MODULE_extract_zip_c4acec5a__["default"])(zipPath, {
|
|
138
|
-
dir: extractDir
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
async function readManifestInfo(manifestPath) {
|
|
142
|
-
let raw = '';
|
|
143
|
-
try {
|
|
144
|
-
raw = await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].readFile(manifestPath, 'utf8');
|
|
145
|
-
} catch (error) {
|
|
146
|
-
throw new errors_extensionFromStoreError('ExtractionFailed', 'manifest.json was not found after extraction', error);
|
|
147
|
-
}
|
|
151
|
+
function parseManifestInfo(raw) {
|
|
148
152
|
let parsed;
|
|
149
153
|
try {
|
|
150
154
|
parsed = JSON.parse(raw);
|
|
151
155
|
} catch (error) {
|
|
152
156
|
throw new errors_extensionFromStoreError('ExtractionFailed', 'manifest.json is not valid JSON', error);
|
|
153
157
|
}
|
|
154
|
-
|
|
155
|
-
const
|
|
158
|
+
if (!parsed || 'object' != typeof parsed || Array.isArray(parsed)) throw new errors_extensionFromStoreError('ExtractionFailed', 'manifest.json must contain an object');
|
|
159
|
+
const manifest = parsed;
|
|
160
|
+
const manifestVersion = manifest.manifest_version;
|
|
161
|
+
const extensionVersion = manifest.version;
|
|
156
162
|
if (2 !== manifestVersion && 3 !== manifestVersion) throw new errors_extensionFromStoreError('ExtractionFailed', 'manifest_version must be 2 or 3');
|
|
157
163
|
if (!extensionVersion || 'string' != typeof extensionVersion) throw new errors_extensionFromStoreError('ExtractionFailed', 'manifest.json is missing a version');
|
|
158
164
|
return {
|
|
165
|
+
manifest,
|
|
159
166
|
manifestVersion,
|
|
160
167
|
extensionVersion
|
|
161
168
|
};
|
|
162
169
|
}
|
|
163
|
-
function
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
170
|
+
async function readManifestInfo(manifestPath) {
|
|
171
|
+
let raw = '';
|
|
172
|
+
try {
|
|
173
|
+
raw = await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].readFile(manifestPath, 'utf8');
|
|
174
|
+
} catch (error) {
|
|
175
|
+
throw new errors_extensionFromStoreError('ExtractionFailed', 'manifest.json was not found after extraction', error);
|
|
176
|
+
}
|
|
177
|
+
return parseManifestInfo(raw);
|
|
178
|
+
}
|
|
179
|
+
function getNodeArch() {
|
|
180
|
+
if ('arm64' === process.arch) return 'arm64';
|
|
181
|
+
if ('ia32' === process.arch) return 'x86';
|
|
182
|
+
return 'x64';
|
|
183
|
+
}
|
|
184
|
+
function getNodeChromePlatformInfo() {
|
|
168
185
|
return {
|
|
169
|
-
os,
|
|
170
|
-
arch:
|
|
171
|
-
naclArch: archName
|
|
186
|
+
os: 'darwin' === process.platform ? 'mac' : 'win32' === process.platform ? 'win' : 'linux',
|
|
187
|
+
arch: getNodeArch()
|
|
172
188
|
};
|
|
173
189
|
}
|
|
174
|
-
function
|
|
190
|
+
function normalizeChromePlatformInfo(platform) {
|
|
191
|
+
return {
|
|
192
|
+
os: platform.os,
|
|
193
|
+
arch: platform.arch,
|
|
194
|
+
naclArch: platform.naclArch || platform.arch
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
const DEFAULT_CHROME_PLATFORM = {
|
|
198
|
+
os: 'linux',
|
|
199
|
+
arch: 'x64'
|
|
200
|
+
};
|
|
201
|
+
function getChromeDownloadUrl(id, platformInfo = DEFAULT_CHROME_PLATFORM) {
|
|
175
202
|
const encoded = encodeURIComponent(id);
|
|
176
|
-
const platform =
|
|
203
|
+
const platform = normalizeChromePlatformInfo(platformInfo);
|
|
177
204
|
const productId = 'chromiumcrx';
|
|
178
205
|
const productChannel = 'unknown';
|
|
179
206
|
const productVersion = '9999.0.9999.0';
|
|
@@ -203,12 +230,12 @@ function getEdgeDownloadUrl(id) {
|
|
|
203
230
|
async function resolveFirefoxDownload(idOrSlug, versionHint, options) {
|
|
204
231
|
var _addon_current_version_file, _addon_current_version, _addon_current_version1;
|
|
205
232
|
const baseUrl = `https://addons.mozilla.org/api/v5/addons/addon/${encodeURIComponent(idOrSlug)}/`;
|
|
206
|
-
const addon = await requestJson(baseUrl, options);
|
|
233
|
+
const addon = await options.requestJson(baseUrl, options);
|
|
207
234
|
const slugOrId = addon.slug || idOrSlug;
|
|
208
235
|
if (versionHint) {
|
|
209
236
|
var _version_file;
|
|
210
237
|
const versionUrl = `${baseUrl}versions/${encodeURIComponent(versionHint)}/`;
|
|
211
|
-
const version = await requestJson(versionUrl, options);
|
|
238
|
+
const version = await options.requestJson(versionUrl, options);
|
|
212
239
|
const downloadUrl = null == (_version_file = version.file) ? void 0 : _version_file.url;
|
|
213
240
|
if (!downloadUrl) throw new errors_extensionFromStoreError('NotPublic', `Version ${versionHint} is not publicly downloadable`);
|
|
214
241
|
return {
|
|
@@ -253,48 +280,20 @@ function extractFirefoxSlugFromUrl(url) {
|
|
|
253
280
|
function validateInput(url) {
|
|
254
281
|
if (!url || 'string' != typeof url) throw new errors_extensionFromStoreError('InvalidInput', 'URL is required');
|
|
255
282
|
}
|
|
256
|
-
function defaultOutputDir() {
|
|
257
|
-
return __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].resolve(process.cwd(), 'extensions');
|
|
258
|
-
}
|
|
259
283
|
function sanitizeSegment(value, label) {
|
|
260
284
|
const sanitized = value.replace(/[\\/]/g, '-').trim();
|
|
261
285
|
if (!sanitized) throw new errors_extensionFromStoreError('InvalidInput', `${label} is not a valid path segment`);
|
|
262
286
|
return sanitized;
|
|
263
287
|
}
|
|
264
|
-
async function
|
|
265
|
-
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].mkdir(dir, {
|
|
266
|
-
recursive: true
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
async function pathExists(target) {
|
|
270
|
-
try {
|
|
271
|
-
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].access(target);
|
|
272
|
-
return true;
|
|
273
|
-
} catch {
|
|
274
|
-
return false;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
async function moveDir(source, destination) {
|
|
278
|
-
try {
|
|
279
|
-
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].rename(source, destination);
|
|
280
|
-
} catch {
|
|
281
|
-
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].cp(source, destination, {
|
|
282
|
-
recursive: true
|
|
283
|
-
});
|
|
284
|
-
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].rm(source, {
|
|
285
|
-
recursive: true,
|
|
286
|
-
force: true
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
async function resolveDownload(url, version, options) {
|
|
288
|
+
async function resolveDownload(url, options) {
|
|
291
289
|
const store = detectStoreFromUrl(url);
|
|
292
290
|
if (!store) throw new errors_extensionFromStoreError('UnsupportedStore', 'URL does not match a supported store');
|
|
293
291
|
if ('chrome' === store) {
|
|
294
292
|
const downloadId = extractChromeIdFromUrl(url);
|
|
295
293
|
if (!downloadId) throw new errors_extensionFromStoreError('NotFound', 'Chrome extension id not found in URL');
|
|
296
294
|
return {
|
|
297
|
-
|
|
295
|
+
store,
|
|
296
|
+
downloadUrl: getChromeDownloadUrl(downloadId, options.platform),
|
|
298
297
|
archiveType: 'crx',
|
|
299
298
|
downloadId,
|
|
300
299
|
slugOrId: downloadId
|
|
@@ -304,6 +303,7 @@ async function resolveDownload(url, version, options) {
|
|
|
304
303
|
const downloadId = extractEdgeIdFromUrl(url);
|
|
305
304
|
if (!downloadId) throw new errors_extensionFromStoreError('NotFound', 'Edge extension id not found in URL');
|
|
306
305
|
return {
|
|
306
|
+
store,
|
|
307
307
|
downloadUrl: getEdgeDownloadUrl(downloadId),
|
|
308
308
|
archiveType: 'crx',
|
|
309
309
|
downloadId,
|
|
@@ -312,14 +312,48 @@ async function resolveDownload(url, version, options) {
|
|
|
312
312
|
}
|
|
313
313
|
const slug = extractFirefoxSlugFromUrl(url);
|
|
314
314
|
if (!slug) throw new errors_extensionFromStoreError('NotFound', 'Firefox extension slug not found in URL');
|
|
315
|
-
const firefox = await resolveFirefoxDownload(slug, version,
|
|
315
|
+
const firefox = await resolveFirefoxDownload(slug, options.version, {
|
|
316
|
+
userAgent: options.userAgent,
|
|
317
|
+
logger: options.logger,
|
|
318
|
+
requestJson: options.requestJson
|
|
319
|
+
});
|
|
316
320
|
return {
|
|
321
|
+
store,
|
|
317
322
|
downloadUrl: firefox.downloadUrl,
|
|
318
323
|
archiveType: 'xpi',
|
|
319
324
|
versionHint: firefox.version,
|
|
320
325
|
slugOrId: firefox.slugOrId
|
|
321
326
|
};
|
|
322
327
|
}
|
|
328
|
+
function defaultOutputDir() {
|
|
329
|
+
return __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].resolve(process.cwd(), 'extensions');
|
|
330
|
+
}
|
|
331
|
+
async function ensureDirExists(dir) {
|
|
332
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].mkdir(dir, {
|
|
333
|
+
recursive: true
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
async function pathExists(target) {
|
|
337
|
+
try {
|
|
338
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].access(target);
|
|
339
|
+
return true;
|
|
340
|
+
} catch {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
async function moveDir(source, destination) {
|
|
345
|
+
try {
|
|
346
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].rename(source, destination);
|
|
347
|
+
} catch {
|
|
348
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].cp(source, destination, {
|
|
349
|
+
recursive: true
|
|
350
|
+
});
|
|
351
|
+
await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].rm(source, {
|
|
352
|
+
recursive: true,
|
|
353
|
+
force: true
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
}
|
|
323
357
|
function errorWithCode(code, message, cause) {
|
|
324
358
|
return new errors_extensionFromStoreError(code, message, cause);
|
|
325
359
|
}
|
|
@@ -328,7 +362,13 @@ async function fetchExtensionFromStore(url, options = {}) {
|
|
|
328
362
|
const log = createLogger(options.logger);
|
|
329
363
|
const outDir = options.outDir ? __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].resolve(options.outDir) : defaultOutputDir();
|
|
330
364
|
await ensureDirExists(outDir);
|
|
331
|
-
const resolved = await resolveDownload(url,
|
|
365
|
+
const resolved = await resolveDownload(url, {
|
|
366
|
+
version: options.version,
|
|
367
|
+
userAgent: options.userAgent,
|
|
368
|
+
logger: options.logger,
|
|
369
|
+
platform: getNodeChromePlatformInfo(),
|
|
370
|
+
requestJson: requestJson
|
|
371
|
+
});
|
|
332
372
|
if (options.version && !url.includes('addons.mozilla.org')) log.warn('Version hints are best-effort and only supported on Firefox at the moment.');
|
|
333
373
|
const workDir = await __WEBPACK_EXTERNAL_MODULE_node_fs_promises_153e37e0__["default"].mkdtemp(__WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(__WEBPACK_EXTERNAL_MODULE_node_os_74b4b876__["default"].tmpdir(), 'extension-from-store-'));
|
|
334
374
|
const archivePath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(workDir, `archive.${resolved.archiveType}`);
|
|
@@ -363,7 +403,7 @@ async function fetchExtensionFromStore(url, options = {}) {
|
|
|
363
403
|
await moveDir(extractDir, finalDir);
|
|
364
404
|
const metaPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(finalDir, 'extension.meta.json');
|
|
365
405
|
const meta = {
|
|
366
|
-
store:
|
|
406
|
+
store: resolved.store,
|
|
367
407
|
identifier: resolved.slugOrId,
|
|
368
408
|
version: resolvedVersion,
|
|
369
409
|
manifestVersion: manifestInfo.manifestVersion
|
package/dist/meta.d.ts
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type ChromePlatformOs = 'mac' | 'win' | 'linux';
|
|
2
|
+
export type ChromePlatformArch = 'x64' | 'arm64' | 'x86';
|
|
3
|
+
export type ChromePlatformInfo = {
|
|
4
|
+
os: ChromePlatformOs;
|
|
5
|
+
arch: ChromePlatformArch;
|
|
6
|
+
naclArch?: ChromePlatformArch;
|
|
7
|
+
};
|
|
8
|
+
export declare function normalizeChromePlatformInfo(platform: ChromePlatformInfo): Required<ChromePlatformInfo>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Logger } from './logger';
|
|
2
|
+
import type { ChromePlatformInfo } from './platform';
|
|
3
|
+
import { type JsonRequester } from './stores/firefox';
|
|
4
|
+
export type ResolvedDownload = {
|
|
5
|
+
store: 'chrome' | 'edge' | 'firefox';
|
|
6
|
+
downloadUrl: string;
|
|
7
|
+
archiveType: 'crx' | 'xpi';
|
|
8
|
+
versionHint?: string;
|
|
9
|
+
downloadId?: string;
|
|
10
|
+
slugOrId: string;
|
|
11
|
+
};
|
|
12
|
+
export type ResolveDownloadOptions = {
|
|
13
|
+
version?: string;
|
|
14
|
+
userAgent?: string;
|
|
15
|
+
logger?: Logger;
|
|
16
|
+
platform?: ChromePlatformInfo;
|
|
17
|
+
requestJson: JsonRequester;
|
|
18
|
+
};
|
|
19
|
+
export declare function validateInput(url: string): void;
|
|
20
|
+
export declare function sanitizeSegment(value: string, label: string): string;
|
|
21
|
+
export declare function resolveDownload(url: string, options: ResolveDownloadOptions): Promise<ResolvedDownload>;
|
package/dist/stores/chrome.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { type ChromePlatformInfo } from '../platform';
|
|
2
|
+
export declare function getChromeDownloadUrl(id: string, platformInfo?: ChromePlatformInfo): string;
|
package/dist/stores/firefox.d.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import type { Logger } from '../logger';
|
|
2
|
+
export type JsonRequester = <T>(url: string, options: {
|
|
3
|
+
userAgent?: string;
|
|
4
|
+
logger?: Logger;
|
|
5
|
+
}) => Promise<T>;
|
|
2
6
|
export declare function resolveFirefoxDownload(idOrSlug: string, versionHint: string | undefined, options: {
|
|
3
7
|
userAgent?: string;
|
|
4
8
|
logger?: Logger;
|
|
9
|
+
requestJson: JsonRequester;
|
|
5
10
|
}): Promise<{
|
|
6
11
|
downloadUrl: string;
|
|
7
12
|
version: string;
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"engineStrict": false,
|
|
11
11
|
"name": "extension-from-store",
|
|
12
|
-
"version": "0.
|
|
12
|
+
"version": "0.2.0",
|
|
13
13
|
"description": "Download public browser extensions from official stores",
|
|
14
14
|
"homepage": "https://www.npmjs.com/package/extension-from-store",
|
|
15
15
|
"type": "module",
|
|
@@ -18,6 +18,16 @@
|
|
|
18
18
|
"types": "./dist/index.d.ts",
|
|
19
19
|
"import": "./dist/index.js",
|
|
20
20
|
"require": "./dist/index.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./browser": {
|
|
23
|
+
"types": "./dist/browser.d.ts",
|
|
24
|
+
"import": "./dist/browser.js",
|
|
25
|
+
"require": "./dist/browser.cjs"
|
|
26
|
+
},
|
|
27
|
+
"./core": {
|
|
28
|
+
"types": "./dist/core.d.ts",
|
|
29
|
+
"import": "./dist/core.js",
|
|
30
|
+
"require": "./dist/core.cjs"
|
|
21
31
|
}
|
|
22
32
|
},
|
|
23
33
|
"main": "./dist/index.cjs",
|
|
@@ -32,6 +42,7 @@
|
|
|
32
42
|
},
|
|
33
43
|
"scripts": {
|
|
34
44
|
"build": "rslib build",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
35
46
|
"check": "pnpm dlx @biomejs/biome@1.9.4 check --write",
|
|
36
47
|
"dev": "rslib build --watch",
|
|
37
48
|
"format": "pnpm dlx @biomejs/biome@1.9.4 format --write",
|
|
@@ -69,7 +80,8 @@
|
|
|
69
80
|
"extension-download"
|
|
70
81
|
],
|
|
71
82
|
"dependencies": {
|
|
72
|
-
"extract-zip": "^2.0.1"
|
|
83
|
+
"extract-zip": "^2.0.1",
|
|
84
|
+
"fflate": "^0.8.2"
|
|
73
85
|
},
|
|
74
86
|
"devDependencies": {
|
|
75
87
|
"@biomejs/biome": "^1.9.4",
|