@metamask-previews/foundryup 1.0.1-preview-4f4c98e → 1.0.1-preview-eb263b0ee
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 +0 -4
- package/dist/cli.cjs +23 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +3 -0
- package/dist/cli.d.cts.map +1 -0
- package/dist/cli.d.mts +3 -0
- package/dist/cli.d.mts.map +1 -0
- package/dist/{cli.js → cli.mjs} +2 -2
- package/dist/cli.mjs.map +1 -0
- package/dist/download.cjs +76 -0
- package/dist/download.cjs.map +1 -0
- package/dist/{download.d.ts → download.d.cts} +9 -4
- package/dist/download.d.cts.map +1 -0
- package/dist/download.d.mts +30 -0
- package/dist/download.d.mts.map +1 -0
- package/dist/{download.js → download.mjs} +5 -5
- package/dist/download.mjs.map +1 -0
- package/dist/extract.cjs +205 -0
- package/dist/extract.cjs.map +1 -0
- package/dist/{extract.d.ts → extract.d.cts} +2 -2
- package/dist/extract.d.cts.map +1 -0
- package/dist/extract.d.mts +24 -0
- package/dist/extract.d.mts.map +1 -0
- package/dist/{extract.js → extract.mjs} +15 -15
- package/dist/extract.mjs.map +1 -0
- package/dist/index.cjs +163 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{index.d.ts → index.d.cts} +7 -4
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +56 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/{index.js → index.mjs} +12 -12
- package/dist/index.mjs.map +1 -0
- package/dist/options.cjs +157 -0
- package/dist/options.cjs.map +1 -0
- package/dist/options.d.cts +62 -0
- package/dist/options.d.cts.map +1 -0
- package/dist/options.d.mts +62 -0
- package/dist/options.d.mts.map +1 -0
- package/dist/{options.js → options.mjs} +6 -6
- package/dist/options.mjs.map +1 -0
- package/dist/types.cjs +30 -0
- package/dist/types.cjs.map +1 -0
- package/dist/{types.d.ts → types.d.cts} +10 -4
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +78 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/{types.js → types.mjs} +1 -1
- package/dist/types.mjs.map +1 -0
- package/dist/utils.cjs +110 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/{utils.d.ts → utils.d.cts} +3 -3
- package/dist/utils.d.cts.map +1 -0
- package/dist/utils.d.mts +50 -0
- package/dist/utils.d.mts.map +1 -0
- package/dist/{utils.js → utils.mjs} +4 -4
- package/dist/utils.mjs.map +1 -0
- package/package.json +9 -11
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/download.d.ts.map +0 -1
- package/dist/download.js.map +0 -1
- package/dist/extract.d.ts.map +0 -1
- package/dist/extract.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/options.d.ts +0 -71
- package/dist/options.d.ts.map +0 -1
- package/dist/options.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
### Changed
|
|
11
|
-
|
|
12
|
-
- **BREAKING:** Bump minimum Node.js version to 22 ([#9168](https://github.com/MetaMask/core/pull/9168))
|
|
13
|
-
|
|
14
10
|
## [1.0.1]
|
|
15
11
|
|
|
16
12
|
### Fixed
|
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
/**
|
|
5
|
+
* CLI entry point for Foundryup.
|
|
6
|
+
*
|
|
7
|
+
* This script downloads and installs Foundry binaries.
|
|
8
|
+
* If an error occurs, it logs the error and exits with code 1.
|
|
9
|
+
*/
|
|
10
|
+
const index_js_1 = require("./index.cjs");
|
|
11
|
+
/**
|
|
12
|
+
* Run the main installation process and handle errors.
|
|
13
|
+
*/
|
|
14
|
+
(0, index_js_1.downloadAndInstallFoundryBinaries)().catch((error) => {
|
|
15
|
+
/**
|
|
16
|
+
* Log any error that occurs during installation and exit with code 1.
|
|
17
|
+
*
|
|
18
|
+
* @param error - The error thrown during installation.
|
|
19
|
+
*/
|
|
20
|
+
console.error('Error:', error);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=cli.cjs.map
|
package/dist/cli.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.cjs","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACH,0CAA+D;AAE/D;;GAEG;AACH,IAAA,4CAAiC,GAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAClD;;;;OAIG;IACH,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n\n/**\n * CLI entry point for Foundryup.\n *\n * This script downloads and installs Foundry binaries.\n * If an error occurs, it logs the error and exits with code 1.\n */\nimport { downloadAndInstallFoundryBinaries } from './index.js';\n\n/**\n * Run the main installation process and handle errors.\n */\ndownloadAndInstallFoundryBinaries().catch((error) => {\n /**\n * Log any error that occurs during installation and exit with code 1.\n *\n * @param error - The error thrown during installation.\n */\n console.error('Error:', error);\n process.exit(1);\n});\n"]}
|
package/dist/cli.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.cts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.mts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/{cli.js → cli.mjs}
RENAMED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* This script downloads and installs Foundry binaries.
|
|
6
6
|
* If an error occurs, it logs the error and exits with code 1.
|
|
7
7
|
*/
|
|
8
|
-
import { downloadAndInstallFoundryBinaries } from
|
|
8
|
+
import { downloadAndInstallFoundryBinaries } from "./index.mjs";
|
|
9
9
|
/**
|
|
10
10
|
* Run the main installation process and handle errors.
|
|
11
11
|
*/
|
|
@@ -18,4 +18,4 @@ downloadAndInstallFoundryBinaries().catch((error) => {
|
|
|
18
18
|
console.error('Error:', error);
|
|
19
19
|
process.exit(1);
|
|
20
20
|
});
|
|
21
|
-
//# sourceMappingURL=cli.
|
|
21
|
+
//# sourceMappingURL=cli.mjs.map
|
package/dist/cli.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.mjs","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AACH,OAAO,EAAE,iCAAiC,EAAE,oBAAmB;AAE/D;;GAEG;AACH,iCAAiC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAClD;;;;OAIG;IACH,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n\n/**\n * CLI entry point for Foundryup.\n *\n * This script downloads and installs Foundry binaries.\n * If an error occurs, it logs the error and exits with code 1.\n */\nimport { downloadAndInstallFoundryBinaries } from './index.js';\n\n/**\n * Run the main installation process and handle errors.\n */\ndownloadAndInstallFoundryBinaries().catch((error) => {\n /**\n * Log any error that occurs during installation and exit with code 1.\n *\n * @param error - The error thrown during installation.\n */\n console.error('Error:', error);\n process.exit(1);\n});\n"]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startDownload = void 0;
|
|
4
|
+
const node_http_1 = require("node:http");
|
|
5
|
+
const node_https_1 = require("node:https");
|
|
6
|
+
const node_stream_1 = require("node:stream");
|
|
7
|
+
const promises_1 = require("node:stream/promises");
|
|
8
|
+
/**
|
|
9
|
+
* A PassThrough stream that emits a 'response' event when the HTTP(S) response is available.
|
|
10
|
+
*/
|
|
11
|
+
class DownloadStream extends node_stream_1.Stream.PassThrough {
|
|
12
|
+
/**
|
|
13
|
+
* Returns a promise that resolves with the HTTP(S) IncomingMessage response.
|
|
14
|
+
*
|
|
15
|
+
* @returns The HTTP(S) response stream.
|
|
16
|
+
*/
|
|
17
|
+
async response() {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
this.once('response', resolve);
|
|
20
|
+
this.once('error', reject);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Starts a download from the given URL.
|
|
26
|
+
*
|
|
27
|
+
* @param url - The URL to download from
|
|
28
|
+
* @param options - The download options
|
|
29
|
+
* @param redirects - The number of redirects that have occurred
|
|
30
|
+
* @returns A stream of the download
|
|
31
|
+
*/
|
|
32
|
+
function startDownload(url, options = {}, redirects = 0) {
|
|
33
|
+
const MAX_REDIRECTS = options.maxRedirects ?? 5;
|
|
34
|
+
const request = url.protocol === 'http:' ? node_http_1.request : node_https_1.request;
|
|
35
|
+
const stream = new DownloadStream();
|
|
36
|
+
request(url, options, (response) => {
|
|
37
|
+
stream.once('close', () => {
|
|
38
|
+
response.destroy();
|
|
39
|
+
});
|
|
40
|
+
const { statusCode, statusMessage, headers } = response;
|
|
41
|
+
// handle redirects
|
|
42
|
+
if (statusCode &&
|
|
43
|
+
statusCode >= 300 &&
|
|
44
|
+
statusCode < 400 &&
|
|
45
|
+
headers.location) {
|
|
46
|
+
if (redirects >= MAX_REDIRECTS) {
|
|
47
|
+
stream.emit('error', new Error('Too many redirects'));
|
|
48
|
+
response.destroy();
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// note: we don't emit a response until we're done redirecting, because
|
|
52
|
+
// handlers only expect it to be emitted once.
|
|
53
|
+
(0, promises_1.pipeline)(startDownload(new URL(headers.location, url), options, redirects + 1)
|
|
54
|
+
// emit the response event to the stream
|
|
55
|
+
.once('response', stream.emit.bind(stream, 'response')), stream).catch(stream.emit.bind(stream, 'error'));
|
|
56
|
+
response.destroy();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// check for HTTP errors
|
|
60
|
+
else if (!statusCode || statusCode < 200 || statusCode >= 300) {
|
|
61
|
+
stream.emit('error', new Error(`Request to ${url} failed. Status Code: ${statusCode} - ${statusMessage}`));
|
|
62
|
+
response.destroy();
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// resolve with response stream
|
|
66
|
+
stream.emit('response', response);
|
|
67
|
+
response.once('error', stream.emit.bind(stream, 'error'));
|
|
68
|
+
(0, promises_1.pipeline)(response, stream).catch(stream.emit.bind(stream, 'error'));
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
.once('error', stream.emit.bind(stream, 'error'))
|
|
72
|
+
.end();
|
|
73
|
+
return stream;
|
|
74
|
+
}
|
|
75
|
+
exports.startDownload = startDownload;
|
|
76
|
+
//# sourceMappingURL=download.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.cjs","sourceRoot":"","sources":["../src/download.ts"],"names":[],"mappings":";;;AAAA,yCAAmD;AAEnD,2CAAqD;AACrD,6CAAqC;AACrC,mDAAgD;AAIhD;;GAEG;AACH,MAAM,cAAe,SAAQ,oBAAM,CAAC,WAAW;IAC7C;;;;OAIG;IACH,KAAK,CAAC,QAAQ;QACZ,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;;;;;GAOG;AACH,SAAgB,aAAa,CAC3B,GAAQ,EACR,UAA2B,EAAE,EAC7B,YAAoB,CAAC;IAErB,MAAM,aAAa,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,mBAAW,CAAC,CAAC,CAAC,oBAAY,CAAC;IACtE,MAAM,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;IACpC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE;QACjC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;YACxB,QAAQ,CAAC,OAAO,EAAE,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;QACxD,mBAAmB;QACnB,IACE,UAAU;YACV,UAAU,IAAI,GAAG;YACjB,UAAU,GAAG,GAAG;YAChB,OAAO,CAAC,QAAQ,EAChB,CAAC;YACD,IAAI,SAAS,IAAI,aAAa,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;gBACtD,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,uEAAuE;gBACvE,8CAA8C;gBAC9C,IAAA,mBAAQ,EACN,aAAa,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,SAAS,GAAG,CAAC,CAAC;oBACnE,wCAAwC;qBACvC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EACzD,MAAM,CACP,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;gBAC3C,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,CAAC;QACH,CAAC;QAED,wBAAwB;aACnB,IAAI,CAAC,UAAU,IAAI,UAAU,GAAG,GAAG,IAAI,UAAU,IAAI,GAAG,EAAE,CAAC;YAC9D,MAAM,CAAC,IAAI,CACT,OAAO,EACP,IAAI,KAAK,CACP,cAAc,GAAG,yBAAyB,UAAU,MAAM,aAAa,EAAE,CAC1E,CACF,CAAC;YACF,QAAQ,CAAC,OAAO,EAAE,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,+BAA+B;YAC/B,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAElC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;YAC1D,IAAA,mBAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QACtE,CAAC;IACH,CAAC,CAAC;SACC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SAChD,GAAG,EAAE,CAAC;IACT,OAAO,MAAM,CAAC;AAChB,CAAC;AAzDD,sCAyDC","sourcesContent":["import { request as httpRequest } from 'node:http';\nimport type { IncomingMessage } from 'node:http';\nimport { request as httpsRequest } from 'node:https';\nimport { Stream } from 'node:stream';\nimport { pipeline } from 'node:stream/promises';\n\nimport type { DownloadOptions } from './types.js';\n\n/**\n * A PassThrough stream that emits a 'response' event when the HTTP(S) response is available.\n */\nclass DownloadStream extends Stream.PassThrough {\n /**\n * Returns a promise that resolves with the HTTP(S) IncomingMessage response.\n *\n * @returns The HTTP(S) response stream.\n */\n async response(): Promise<IncomingMessage> {\n return new Promise((resolve, reject) => {\n this.once('response', resolve);\n this.once('error', reject);\n });\n }\n}\n\n/**\n * Starts a download from the given URL.\n *\n * @param url - The URL to download from\n * @param options - The download options\n * @param redirects - The number of redirects that have occurred\n * @returns A stream of the download\n */\nexport function startDownload(\n url: URL,\n options: DownloadOptions = {},\n redirects: number = 0,\n) {\n const MAX_REDIRECTS = options.maxRedirects ?? 5;\n const request = url.protocol === 'http:' ? httpRequest : httpsRequest;\n const stream = new DownloadStream();\n request(url, options, (response) => {\n stream.once('close', () => {\n response.destroy();\n });\n\n const { statusCode, statusMessage, headers } = response;\n // handle redirects\n if (\n statusCode &&\n statusCode >= 300 &&\n statusCode < 400 &&\n headers.location\n ) {\n if (redirects >= MAX_REDIRECTS) {\n stream.emit('error', new Error('Too many redirects'));\n response.destroy();\n } else {\n // note: we don't emit a response until we're done redirecting, because\n // handlers only expect it to be emitted once.\n pipeline(\n startDownload(new URL(headers.location, url), options, redirects + 1)\n // emit the response event to the stream\n .once('response', stream.emit.bind(stream, 'response')),\n stream,\n ).catch(stream.emit.bind(stream, 'error'));\n response.destroy();\n }\n }\n\n // check for HTTP errors\n else if (!statusCode || statusCode < 200 || statusCode >= 300) {\n stream.emit(\n 'error',\n new Error(\n `Request to ${url} failed. Status Code: ${statusCode} - ${statusMessage}`,\n ),\n );\n response.destroy();\n } else {\n // resolve with response stream\n stream.emit('response', response);\n\n response.once('error', stream.emit.bind(stream, 'error'));\n pipeline(response, stream).catch(stream.emit.bind(stream, 'error'));\n }\n })\n .once('error', stream.emit.bind(stream, 'error'))\n .end();\n return stream;\n}\n"]}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node/http.js" />
|
|
3
|
+
/// <reference types="npm-which/node_modules/@types/node/http.js" />
|
|
4
|
+
/// <reference types="node/stream.js" />
|
|
5
|
+
/// <reference types="npm-which/node_modules/@types/node/stream.js" />
|
|
6
|
+
import type { IncomingMessage } from "node:http";
|
|
7
|
+
import { Stream } from "node:stream";
|
|
8
|
+
import type { DownloadOptions } from "./types.cjs";
|
|
4
9
|
/**
|
|
5
10
|
* A PassThrough stream that emits a 'response' event when the HTTP(S) response is available.
|
|
6
11
|
*/
|
|
@@ -22,4 +27,4 @@ declare class DownloadStream extends Stream.PassThrough {
|
|
|
22
27
|
*/
|
|
23
28
|
export declare function startDownload(url: URL, options?: DownloadOptions, redirects?: number): DownloadStream;
|
|
24
29
|
export {};
|
|
25
|
-
//# sourceMappingURL=download.d.
|
|
30
|
+
//# sourceMappingURL=download.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.d.cts","sourceRoot":"","sources":["../src/download.ts"],"names":[],"mappings":";;;;;AACA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB;AAEjD,OAAO,EAAE,MAAM,EAAE,oBAAoB;AAGrC,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAmB;AAElD;;GAEG;AACH,cAAM,cAAe,SAAQ,MAAM,CAAC,WAAW;IAC7C;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,eAAe,CAAC;CAM3C;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,eAAoB,EAC7B,SAAS,GAAE,MAAU,kBAsDtB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node/http.js" />
|
|
3
|
+
/// <reference types="npm-which/node_modules/@types/node/http.js" />
|
|
4
|
+
/// <reference types="node/stream.js" />
|
|
5
|
+
/// <reference types="npm-which/node_modules/@types/node/stream.js" />
|
|
6
|
+
import type { IncomingMessage } from "node:http";
|
|
7
|
+
import { Stream } from "node:stream";
|
|
8
|
+
import type { DownloadOptions } from "./types.mjs";
|
|
9
|
+
/**
|
|
10
|
+
* A PassThrough stream that emits a 'response' event when the HTTP(S) response is available.
|
|
11
|
+
*/
|
|
12
|
+
declare class DownloadStream extends Stream.PassThrough {
|
|
13
|
+
/**
|
|
14
|
+
* Returns a promise that resolves with the HTTP(S) IncomingMessage response.
|
|
15
|
+
*
|
|
16
|
+
* @returns The HTTP(S) response stream.
|
|
17
|
+
*/
|
|
18
|
+
response(): Promise<IncomingMessage>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Starts a download from the given URL.
|
|
22
|
+
*
|
|
23
|
+
* @param url - The URL to download from
|
|
24
|
+
* @param options - The download options
|
|
25
|
+
* @param redirects - The number of redirects that have occurred
|
|
26
|
+
* @returns A stream of the download
|
|
27
|
+
*/
|
|
28
|
+
export declare function startDownload(url: URL, options?: DownloadOptions, redirects?: number): DownloadStream;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=download.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.d.mts","sourceRoot":"","sources":["../src/download.ts"],"names":[],"mappings":";;;;;AACA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB;AAEjD,OAAO,EAAE,MAAM,EAAE,oBAAoB;AAGrC,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAmB;AAElD;;GAEG;AACH,cAAM,cAAe,SAAQ,MAAM,CAAC,WAAW;IAC7C;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,eAAe,CAAC;CAM3C;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,eAAoB,EAC7B,SAAS,GAAE,MAAU,kBAsDtB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { request as httpRequest } from
|
|
2
|
-
import { request as httpsRequest } from
|
|
3
|
-
import { Stream } from
|
|
4
|
-
import { pipeline } from
|
|
1
|
+
import { request as httpRequest } from "node:http";
|
|
2
|
+
import { request as httpsRequest } from "node:https";
|
|
3
|
+
import { Stream } from "node:stream";
|
|
4
|
+
import { pipeline } from "node:stream/promises";
|
|
5
5
|
/**
|
|
6
6
|
* A PassThrough stream that emits a 'response' event when the HTTP(S) response is available.
|
|
7
7
|
*/
|
|
@@ -69,4 +69,4 @@ export function startDownload(url, options = {}, redirects = 0) {
|
|
|
69
69
|
.end();
|
|
70
70
|
return stream;
|
|
71
71
|
}
|
|
72
|
-
//# sourceMappingURL=download.
|
|
72
|
+
//# sourceMappingURL=download.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.mjs","sourceRoot":"","sources":["../src/download.ts"],"names":[],"mappings":"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","sourcesContent":["import { request as httpRequest } from 'node:http';\nimport type { IncomingMessage } from 'node:http';\nimport { request as httpsRequest } from 'node:https';\nimport { Stream } from 'node:stream';\nimport { pipeline } from 'node:stream/promises';\n\nimport type { DownloadOptions } from './types.js';\n\n/**\n * A PassThrough stream that emits a 'response' event when the HTTP(S) response is available.\n */\nclass DownloadStream extends Stream.PassThrough {\n /**\n * Returns a promise that resolves with the HTTP(S) IncomingMessage response.\n *\n * @returns The HTTP(S) response stream.\n */\n async response(): Promise<IncomingMessage> {\n return new Promise((resolve, reject) => {\n this.once('response', resolve);\n this.once('error', reject);\n });\n }\n}\n\n/**\n * Starts a download from the given URL.\n *\n * @param url - The URL to download from\n * @param options - The download options\n * @param redirects - The number of redirects that have occurred\n * @returns A stream of the download\n */\nexport function startDownload(\n url: URL,\n options: DownloadOptions = {},\n redirects: number = 0,\n) {\n const MAX_REDIRECTS = options.maxRedirects ?? 5;\n const request = url.protocol === 'http:' ? httpRequest : httpsRequest;\n const stream = new DownloadStream();\n request(url, options, (response) => {\n stream.once('close', () => {\n response.destroy();\n });\n\n const { statusCode, statusMessage, headers } = response;\n // handle redirects\n if (\n statusCode &&\n statusCode >= 300 &&\n statusCode < 400 &&\n headers.location\n ) {\n if (redirects >= MAX_REDIRECTS) {\n stream.emit('error', new Error('Too many redirects'));\n response.destroy();\n } else {\n // note: we don't emit a response until we're done redirecting, because\n // handlers only expect it to be emitted once.\n pipeline(\n startDownload(new URL(headers.location, url), options, redirects + 1)\n // emit the response event to the stream\n .once('response', stream.emit.bind(stream, 'response')),\n stream,\n ).catch(stream.emit.bind(stream, 'error'));\n response.destroy();\n }\n }\n\n // check for HTTP errors\n else if (!statusCode || statusCode < 200 || statusCode >= 300) {\n stream.emit(\n 'error',\n new Error(\n `Request to ${url} failed. Status Code: ${statusCode} - ${statusMessage}`,\n ),\n );\n response.destroy();\n } else {\n // resolve with response stream\n stream.emit('response', response);\n\n response.once('error', stream.emit.bind(stream, 'error'));\n pipeline(response, stream).catch(stream.emit.bind(stream, 'error'));\n }\n })\n .once('error', stream.emit.bind(stream, 'error'))\n .end();\n return stream;\n}\n"]}
|
package/dist/extract.cjs
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractFrom = void 0;
|
|
4
|
+
const minipass_1 = require("minipass");
|
|
5
|
+
const strict_1 = require("node:assert/strict");
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const promises_1 = require("node:fs/promises");
|
|
9
|
+
const node_http_1 = require("node:http");
|
|
10
|
+
const node_https_1 = require("node:https");
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
const promises_2 = require("node:stream/promises");
|
|
13
|
+
const tar_1 = require("tar");
|
|
14
|
+
const unzipper_1 = require("unzipper");
|
|
15
|
+
const download_js_1 = require("./download.cjs");
|
|
16
|
+
const types_js_1 = require("./types.cjs");
|
|
17
|
+
const utils_js_1 = require("./utils.cjs");
|
|
18
|
+
/**
|
|
19
|
+
* Extracts the binaries from the given URL and writes them to the destination.
|
|
20
|
+
*
|
|
21
|
+
* @param url - The URL of the archive to extract the binaries from
|
|
22
|
+
* @param binaries - The list of binaries to extract
|
|
23
|
+
* @param dir - The destination directory
|
|
24
|
+
* @param checksums - The checksums to verify the binaries against
|
|
25
|
+
* @returns The list of binaries extracted
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Extracts the binaries from the given URL and writes them to the destination.
|
|
29
|
+
*
|
|
30
|
+
* @param url - The URL of the archive to extract the binaries from
|
|
31
|
+
* @param binaries - The list of binaries to extract
|
|
32
|
+
* @param dir - The destination directory
|
|
33
|
+
* @param checksums - The checksums to verify the binaries against
|
|
34
|
+
* @returns The list of binaries extracted
|
|
35
|
+
*/
|
|
36
|
+
async function extractFrom(url, binaries, dir, checksums) {
|
|
37
|
+
const extract = url.pathname.toLowerCase().endsWith(types_js_1.Extension.Tar)
|
|
38
|
+
? extractFromTar
|
|
39
|
+
: extractFromZip;
|
|
40
|
+
// write all files to a temporary directory first, then rename to the final
|
|
41
|
+
// destination to avoid accidental partial extraction. We don't use
|
|
42
|
+
// `os.tmpdir` for this because `rename` will fail if the directories are on
|
|
43
|
+
// different file systems.
|
|
44
|
+
const tempDir = `${dir}.downloading`;
|
|
45
|
+
const rmOpts = { recursive: true, maxRetries: 3, force: true };
|
|
46
|
+
try {
|
|
47
|
+
// clean up any previous in-progress downloads
|
|
48
|
+
await (0, promises_1.rm)(tempDir, rmOpts);
|
|
49
|
+
// make the temporary directory to extract the binaries to
|
|
50
|
+
await (0, promises_1.mkdir)(tempDir, { recursive: true });
|
|
51
|
+
const downloads = await extract(url, binaries, tempDir, checksums?.algorithm);
|
|
52
|
+
(0, strict_1.ok)(downloads.length === binaries.length, 'Failed to extract all binaries');
|
|
53
|
+
const paths = [];
|
|
54
|
+
for (const { path, binary, checksum } of downloads) {
|
|
55
|
+
if (checksums) {
|
|
56
|
+
(0, utils_js_1.say)(`verifying checksum for ${binary}`);
|
|
57
|
+
const expected = checksums.binaries[binary];
|
|
58
|
+
if (checksum === expected) {
|
|
59
|
+
(0, utils_js_1.say)(`checksum verified for ${binary}`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
throw new Error(`checksum mismatch for ${binary}, expected ${expected}, got ${checksum}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// add the *final* path to the list of binaries
|
|
66
|
+
paths.push((0, node_path_1.join)(dir, (0, node_path_1.relative)(tempDir, path)));
|
|
67
|
+
}
|
|
68
|
+
// this directory shouldn't exist, but if two simultaneous `yarn foundryup`
|
|
69
|
+
// processes are running, it might. Last process wins, so we remove other
|
|
70
|
+
// `dir`s just in case.
|
|
71
|
+
await (0, promises_1.rm)(dir, rmOpts);
|
|
72
|
+
// everything has been extracted; move the files to their final destination
|
|
73
|
+
await (0, promises_1.rename)(tempDir, dir);
|
|
74
|
+
// return the list of extracted binaries
|
|
75
|
+
return paths;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
// if things fail for any reason try to clean up a bit. it is very important
|
|
79
|
+
// to not leave `dir` behind, as its existence is a signal that the binaries
|
|
80
|
+
// are installed.
|
|
81
|
+
const rmErrors = (await Promise.allSettled([(0, promises_1.rm)(tempDir, rmOpts), (0, promises_1.rm)(dir, rmOpts)]))
|
|
82
|
+
.filter((r) => r.status === 'rejected')
|
|
83
|
+
.map((r) => r.reason);
|
|
84
|
+
// if we failed to clean up, create an aggregate error message
|
|
85
|
+
if (rmErrors.length) {
|
|
86
|
+
throw new AggregateError([error, ...rmErrors], 'This is a bug; you should report it.');
|
|
87
|
+
}
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.extractFrom = extractFrom;
|
|
92
|
+
/**
|
|
93
|
+
* Extracts the binaries from a tar archive.
|
|
94
|
+
*
|
|
95
|
+
* @param url - The URL of the archive to extract the binaries from
|
|
96
|
+
* @param binaries - The list of binaries to extract
|
|
97
|
+
* @param dir - The destination directory
|
|
98
|
+
* @param checksumAlgorithm - The checksum algorithm to use
|
|
99
|
+
* @returns The list of binaries extracted
|
|
100
|
+
*/
|
|
101
|
+
/**
|
|
102
|
+
* Extracts the binaries from a tar archive.
|
|
103
|
+
*
|
|
104
|
+
* @param url - The URL of the archive to extract the binaries from
|
|
105
|
+
* @param binaries - The list of binaries to extract
|
|
106
|
+
* @param dir - The destination directory
|
|
107
|
+
* @param checksumAlgorithm - The checksum algorithm to use
|
|
108
|
+
* @returns The list of binaries extracted
|
|
109
|
+
*/
|
|
110
|
+
async function extractFromTar(url, binaries, dir, checksumAlgorithm) {
|
|
111
|
+
const downloads = [];
|
|
112
|
+
await (0, promises_2.pipeline)((0, download_js_1.startDownload)(url), (0, tar_1.extract)({
|
|
113
|
+
cwd: dir,
|
|
114
|
+
// @ts-expect-error: Types here broke in `tar@7.5.12`, but it appears to
|
|
115
|
+
// work fine as-is.
|
|
116
|
+
// See: https://github.com/isaacs/node-tar/issues/459
|
|
117
|
+
transform: (entry) => {
|
|
118
|
+
const absolutePath = entry.absolute;
|
|
119
|
+
if (!absolutePath) {
|
|
120
|
+
throw new Error('Missing absolute path for entry');
|
|
121
|
+
}
|
|
122
|
+
if (checksumAlgorithm) {
|
|
123
|
+
const hash = (0, node_crypto_1.createHash)(checksumAlgorithm);
|
|
124
|
+
const passThrough = new minipass_1.Minipass({ async: true });
|
|
125
|
+
passThrough.pipe(hash);
|
|
126
|
+
passThrough.on('end', () => {
|
|
127
|
+
downloads.push({
|
|
128
|
+
path: absolutePath,
|
|
129
|
+
binary: entry.path,
|
|
130
|
+
checksum: hash.digest('hex'),
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
return passThrough;
|
|
134
|
+
}
|
|
135
|
+
// When no checksum is needed, record the entry and return undefined
|
|
136
|
+
// to use the original stream without transformation
|
|
137
|
+
downloads.push({
|
|
138
|
+
path: absolutePath,
|
|
139
|
+
binary: entry.path,
|
|
140
|
+
});
|
|
141
|
+
return undefined;
|
|
142
|
+
},
|
|
143
|
+
}, binaries));
|
|
144
|
+
return downloads;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Extracts the binaries from a zip archive.
|
|
148
|
+
*
|
|
149
|
+
* @param url - The URL of the archive to extract the binaries from
|
|
150
|
+
* @param binaries - The list of binaries to extract
|
|
151
|
+
* @param dir - The destination directory
|
|
152
|
+
* @param checksumAlgorithm - The checksum algorithm to use
|
|
153
|
+
* @returns The list of binaries extracted
|
|
154
|
+
*/
|
|
155
|
+
async function extractFromZip(url, binaries, dir, checksumAlgorithm) {
|
|
156
|
+
const agent = new (url.protocol === 'http:' ? node_http_1.Agent : node_https_1.Agent)({
|
|
157
|
+
keepAlive: true,
|
|
158
|
+
});
|
|
159
|
+
const source = {
|
|
160
|
+
async size() {
|
|
161
|
+
const download = (0, download_js_1.startDownload)(url, { agent, method: 'HEAD' });
|
|
162
|
+
const response = await download.response();
|
|
163
|
+
const contentLength = response.headers['content-length'];
|
|
164
|
+
return contentLength ? parseInt(contentLength, 10) : 0;
|
|
165
|
+
},
|
|
166
|
+
stream(offset, bytes) {
|
|
167
|
+
const options = {
|
|
168
|
+
agent,
|
|
169
|
+
headers: {
|
|
170
|
+
range: `bytes=${offset}-${bytes ? offset + bytes : ''}`,
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
return (0, download_js_1.startDownload)(url, options);
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
const { files } = await unzipper_1.Open.custom(source, {});
|
|
177
|
+
const filtered = files.filter(({ path }) => binaries.includes((0, node_path_1.basename)(path, (0, node_path_1.extname)(path))));
|
|
178
|
+
return await Promise.all(filtered.map(async ({ path, stream }) => {
|
|
179
|
+
const dest = (0, node_path_1.join)(dir, path);
|
|
180
|
+
const entry = stream();
|
|
181
|
+
const destStream = (0, node_fs_1.createWriteStream)(dest);
|
|
182
|
+
const binary = (0, node_path_1.basename)(path, (0, node_path_1.extname)(path));
|
|
183
|
+
if (checksumAlgorithm) {
|
|
184
|
+
const hash = (0, node_crypto_1.createHash)(checksumAlgorithm);
|
|
185
|
+
const hashStream = async function* (entryStream) {
|
|
186
|
+
for await (const chunk of entryStream) {
|
|
187
|
+
hash.update(chunk);
|
|
188
|
+
yield chunk;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
await (0, promises_2.pipeline)(entry, hashStream, destStream);
|
|
192
|
+
return {
|
|
193
|
+
path: dest,
|
|
194
|
+
binary,
|
|
195
|
+
checksum: hash.digest('hex'),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
await (0, promises_2.pipeline)(entry, destStream);
|
|
199
|
+
return {
|
|
200
|
+
path: dest,
|
|
201
|
+
binary,
|
|
202
|
+
};
|
|
203
|
+
}));
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=extract.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.cjs","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"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","sourcesContent":["import { Minipass } from 'minipass';\nimport { ok } from 'node:assert/strict';\nimport { createHash } from 'node:crypto';\nimport { createWriteStream } from 'node:fs';\nimport { rename, mkdir, rm } from 'node:fs/promises';\nimport { Agent as HttpAgent } from 'node:http';\nimport { Agent as HttpsAgent } from 'node:https';\nimport { join, basename, extname, relative } from 'node:path';\nimport { pipeline } from 'node:stream/promises';\nimport { extract as extractTar } from 'tar';\nimport { Open } from 'unzipper';\nimport type { Source, Entry } from 'unzipper';\n\nimport { startDownload } from './download.js';\nimport { Extension } from './types.js';\nimport type { Binary } from './types.js';\nimport { say } from './utils.js';\n\n/**\n * Extracts the binaries from the given URL and writes them to the destination.\n *\n * @param url - The URL of the archive to extract the binaries from\n * @param binaries - The list of binaries to extract\n * @param dir - The destination directory\n * @param checksums - The checksums to verify the binaries against\n * @returns The list of binaries extracted\n */\n\n/**\n * Extracts the binaries from the given URL and writes them to the destination.\n *\n * @param url - The URL of the archive to extract the binaries from\n * @param binaries - The list of binaries to extract\n * @param dir - The destination directory\n * @param checksums - The checksums to verify the binaries against\n * @returns The list of binaries extracted\n */\nexport async function extractFrom(\n url: URL,\n binaries: Binary[],\n dir: string,\n checksums: { algorithm: string; binaries: Record<Binary, string> } | null,\n) {\n const extract = url.pathname.toLowerCase().endsWith(Extension.Tar)\n ? extractFromTar\n : extractFromZip;\n // write all files to a temporary directory first, then rename to the final\n // destination to avoid accidental partial extraction. We don't use\n // `os.tmpdir` for this because `rename` will fail if the directories are on\n // different file systems.\n const tempDir = `${dir}.downloading`;\n const rmOpts = { recursive: true, maxRetries: 3, force: true };\n try {\n // clean up any previous in-progress downloads\n await rm(tempDir, rmOpts);\n // make the temporary directory to extract the binaries to\n await mkdir(tempDir, { recursive: true });\n const downloads = await extract(\n url,\n binaries,\n tempDir,\n checksums?.algorithm,\n );\n ok(downloads.length === binaries.length, 'Failed to extract all binaries');\n\n const paths: string[] = [];\n for (const { path, binary, checksum } of downloads) {\n if (checksums) {\n say(`verifying checksum for ${binary}`);\n const expected = checksums.binaries[binary];\n if (checksum === expected) {\n say(`checksum verified for ${binary}`);\n } else {\n throw new Error(\n `checksum mismatch for ${binary}, expected ${expected}, got ${checksum}`,\n );\n }\n }\n // add the *final* path to the list of binaries\n paths.push(join(dir, relative(tempDir, path)));\n }\n\n // this directory shouldn't exist, but if two simultaneous `yarn foundryup`\n // processes are running, it might. Last process wins, so we remove other\n // `dir`s just in case.\n await rm(dir, rmOpts);\n // everything has been extracted; move the files to their final destination\n await rename(tempDir, dir);\n // return the list of extracted binaries\n return paths;\n } catch (error) {\n // if things fail for any reason try to clean up a bit. it is very important\n // to not leave `dir` behind, as its existence is a signal that the binaries\n // are installed.\n const rmErrors = (\n await Promise.allSettled([rm(tempDir, rmOpts), rm(dir, rmOpts)])\n )\n .filter((r) => r.status === 'rejected')\n .map((r) => (r as PromiseRejectedResult).reason);\n\n // if we failed to clean up, create an aggregate error message\n if (rmErrors.length) {\n throw new AggregateError(\n [error, ...rmErrors],\n 'This is a bug; you should report it.',\n );\n }\n throw error;\n }\n}\n/**\n * Extracts the binaries from a tar archive.\n *\n * @param url - The URL of the archive to extract the binaries from\n * @param binaries - The list of binaries to extract\n * @param dir - The destination directory\n * @param checksumAlgorithm - The checksum algorithm to use\n * @returns The list of binaries extracted\n */\n\n/**\n * Extracts the binaries from a tar archive.\n *\n * @param url - The URL of the archive to extract the binaries from\n * @param binaries - The list of binaries to extract\n * @param dir - The destination directory\n * @param checksumAlgorithm - The checksum algorithm to use\n * @returns The list of binaries extracted\n */\nasync function extractFromTar(\n url: URL,\n binaries: Binary[],\n dir: string,\n checksumAlgorithm?: string,\n) {\n const downloads: {\n path: string;\n binary: Binary;\n checksum?: string;\n }[] = [];\n await pipeline(\n startDownload(url),\n extractTar(\n {\n cwd: dir,\n // @ts-expect-error: Types here broke in `tar@7.5.12`, but it appears to\n // work fine as-is.\n // See: https://github.com/isaacs/node-tar/issues/459\n transform: (entry) => {\n const absolutePath = entry.absolute;\n if (!absolutePath) {\n throw new Error('Missing absolute path for entry');\n }\n\n if (checksumAlgorithm) {\n const hash = createHash(checksumAlgorithm);\n const passThrough = new Minipass({ async: true });\n passThrough.pipe(hash);\n passThrough.on('end', () => {\n downloads.push({\n path: absolutePath,\n binary: entry.path as Binary,\n checksum: hash.digest('hex'),\n });\n });\n return passThrough;\n }\n\n // When no checksum is needed, record the entry and return undefined\n // to use the original stream without transformation\n downloads.push({\n path: absolutePath,\n binary: entry.path as Binary,\n });\n return undefined;\n },\n },\n binaries,\n ),\n );\n return downloads;\n}\n/**\n * Extracts the binaries from a zip archive.\n *\n * @param url - The URL of the archive to extract the binaries from\n * @param binaries - The list of binaries to extract\n * @param dir - The destination directory\n * @param checksumAlgorithm - The checksum algorithm to use\n * @returns The list of binaries extracted\n */\nasync function extractFromZip(\n url: URL,\n binaries: Binary[],\n dir: string,\n checksumAlgorithm?: string,\n) {\n const agent = new (url.protocol === 'http:' ? HttpAgent : HttpsAgent)({\n keepAlive: true,\n });\n const source: Source = {\n async size() {\n const download = startDownload(url, { agent, method: 'HEAD' });\n const response = await download.response();\n const contentLength = response.headers['content-length'];\n return contentLength ? parseInt(contentLength, 10) : 0;\n },\n stream(offset: number, bytes: number) {\n const options = {\n agent,\n headers: {\n range: `bytes=${offset}-${bytes ? offset + bytes : ''}`,\n },\n };\n return startDownload(url, options);\n },\n };\n\n const { files } = await Open.custom(source, {});\n const filtered = files.filter(({ path }) =>\n binaries.includes(basename(path, extname(path)) as Binary),\n );\n return await Promise.all(\n filtered.map(async ({ path, stream }) => {\n const dest = join(dir, path);\n const entry = stream();\n const destStream = createWriteStream(dest);\n const binary = basename(path, extname(path)) as Binary;\n if (checksumAlgorithm) {\n const hash = createHash(checksumAlgorithm);\n const hashStream = async function* (entryStream: Entry) {\n for await (const chunk of entryStream) {\n hash.update(chunk);\n yield chunk;\n }\n };\n await pipeline(entry, hashStream, destStream);\n return {\n path: dest,\n binary,\n checksum: hash.digest('hex'),\n };\n }\n await pipeline(entry, destStream);\n return {\n path: dest,\n binary,\n };\n }),\n );\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Binary } from
|
|
1
|
+
import type { Binary } from "./types.cjs";
|
|
2
2
|
/**
|
|
3
3
|
* Extracts the binaries from the given URL and writes them to the destination.
|
|
4
4
|
*
|
|
@@ -21,4 +21,4 @@ export declare function extractFrom(url: URL, binaries: Binary[], dir: string, c
|
|
|
21
21
|
algorithm: string;
|
|
22
22
|
binaries: Record<Binary, string>;
|
|
23
23
|
} | null): Promise<string[]>;
|
|
24
|
-
//# sourceMappingURL=extract.d.
|
|
24
|
+
//# sourceMappingURL=extract.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.cts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAmB;AAGzC;;;;;;;;GAQG;AAEH;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,MAAM,EAAE,EAClB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,qBAoE1E"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Binary } from "./types.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Extracts the binaries from the given URL and writes them to the destination.
|
|
4
|
+
*
|
|
5
|
+
* @param url - The URL of the archive to extract the binaries from
|
|
6
|
+
* @param binaries - The list of binaries to extract
|
|
7
|
+
* @param dir - The destination directory
|
|
8
|
+
* @param checksums - The checksums to verify the binaries against
|
|
9
|
+
* @returns The list of binaries extracted
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Extracts the binaries from the given URL and writes them to the destination.
|
|
13
|
+
*
|
|
14
|
+
* @param url - The URL of the archive to extract the binaries from
|
|
15
|
+
* @param binaries - The list of binaries to extract
|
|
16
|
+
* @param dir - The destination directory
|
|
17
|
+
* @param checksums - The checksums to verify the binaries against
|
|
18
|
+
* @returns The list of binaries extracted
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractFrom(url: URL, binaries: Binary[], dir: string, checksums: {
|
|
21
|
+
algorithm: string;
|
|
22
|
+
binaries: Record<Binary, string>;
|
|
23
|
+
} | null): Promise<string[]>;
|
|
24
|
+
//# sourceMappingURL=extract.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.mts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAmB;AAGzC;;;;;;;;GAQG;AAEH;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,MAAM,EAAE,EAClB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,qBAoE1E"}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { Minipass } from
|
|
2
|
-
import { ok } from
|
|
3
|
-
import { createHash } from
|
|
4
|
-
import { createWriteStream } from
|
|
5
|
-
import { rename, mkdir, rm } from
|
|
6
|
-
import { Agent as HttpAgent } from
|
|
7
|
-
import { Agent as HttpsAgent } from
|
|
8
|
-
import { join, basename, extname, relative } from
|
|
9
|
-
import { pipeline } from
|
|
10
|
-
import { extract as extractTar } from
|
|
11
|
-
import { Open } from
|
|
12
|
-
import { startDownload } from
|
|
13
|
-
import { Extension } from
|
|
14
|
-
import { say } from
|
|
1
|
+
import { Minipass } from "minipass";
|
|
2
|
+
import { ok } from "node:assert/strict";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { createWriteStream } from "node:fs";
|
|
5
|
+
import { rename, mkdir, rm } from "node:fs/promises";
|
|
6
|
+
import { Agent as HttpAgent } from "node:http";
|
|
7
|
+
import { Agent as HttpsAgent } from "node:https";
|
|
8
|
+
import { join, basename, extname, relative } from "node:path";
|
|
9
|
+
import { pipeline } from "node:stream/promises";
|
|
10
|
+
import { extract as extractTar } from "tar";
|
|
11
|
+
import { Open } from "unzipper";
|
|
12
|
+
import { startDownload } from "./download.mjs";
|
|
13
|
+
import { Extension } from "./types.mjs";
|
|
14
|
+
import { say } from "./utils.mjs";
|
|
15
15
|
/**
|
|
16
16
|
* Extracts the binaries from the given URL and writes them to the destination.
|
|
17
17
|
*
|
|
@@ -198,4 +198,4 @@ async function extractFromZip(url, binaries, dir, checksumAlgorithm) {
|
|
|
198
198
|
};
|
|
199
199
|
}));
|
|
200
200
|
}
|
|
201
|
-
//# sourceMappingURL=extract.
|
|
201
|
+
//# sourceMappingURL=extract.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.mjs","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"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","sourcesContent":["import { Minipass } from 'minipass';\nimport { ok } from 'node:assert/strict';\nimport { createHash } from 'node:crypto';\nimport { createWriteStream } from 'node:fs';\nimport { rename, mkdir, rm } from 'node:fs/promises';\nimport { Agent as HttpAgent } from 'node:http';\nimport { Agent as HttpsAgent } from 'node:https';\nimport { join, basename, extname, relative } from 'node:path';\nimport { pipeline } from 'node:stream/promises';\nimport { extract as extractTar } from 'tar';\nimport { Open } from 'unzipper';\nimport type { Source, Entry } from 'unzipper';\n\nimport { startDownload } from './download.js';\nimport { Extension } from './types.js';\nimport type { Binary } from './types.js';\nimport { say } from './utils.js';\n\n/**\n * Extracts the binaries from the given URL and writes them to the destination.\n *\n * @param url - The URL of the archive to extract the binaries from\n * @param binaries - The list of binaries to extract\n * @param dir - The destination directory\n * @param checksums - The checksums to verify the binaries against\n * @returns The list of binaries extracted\n */\n\n/**\n * Extracts the binaries from the given URL and writes them to the destination.\n *\n * @param url - The URL of the archive to extract the binaries from\n * @param binaries - The list of binaries to extract\n * @param dir - The destination directory\n * @param checksums - The checksums to verify the binaries against\n * @returns The list of binaries extracted\n */\nexport async function extractFrom(\n url: URL,\n binaries: Binary[],\n dir: string,\n checksums: { algorithm: string; binaries: Record<Binary, string> } | null,\n) {\n const extract = url.pathname.toLowerCase().endsWith(Extension.Tar)\n ? extractFromTar\n : extractFromZip;\n // write all files to a temporary directory first, then rename to the final\n // destination to avoid accidental partial extraction. We don't use\n // `os.tmpdir` for this because `rename` will fail if the directories are on\n // different file systems.\n const tempDir = `${dir}.downloading`;\n const rmOpts = { recursive: true, maxRetries: 3, force: true };\n try {\n // clean up any previous in-progress downloads\n await rm(tempDir, rmOpts);\n // make the temporary directory to extract the binaries to\n await mkdir(tempDir, { recursive: true });\n const downloads = await extract(\n url,\n binaries,\n tempDir,\n checksums?.algorithm,\n );\n ok(downloads.length === binaries.length, 'Failed to extract all binaries');\n\n const paths: string[] = [];\n for (const { path, binary, checksum } of downloads) {\n if (checksums) {\n say(`verifying checksum for ${binary}`);\n const expected = checksums.binaries[binary];\n if (checksum === expected) {\n say(`checksum verified for ${binary}`);\n } else {\n throw new Error(\n `checksum mismatch for ${binary}, expected ${expected}, got ${checksum}`,\n );\n }\n }\n // add the *final* path to the list of binaries\n paths.push(join(dir, relative(tempDir, path)));\n }\n\n // this directory shouldn't exist, but if two simultaneous `yarn foundryup`\n // processes are running, it might. Last process wins, so we remove other\n // `dir`s just in case.\n await rm(dir, rmOpts);\n // everything has been extracted; move the files to their final destination\n await rename(tempDir, dir);\n // return the list of extracted binaries\n return paths;\n } catch (error) {\n // if things fail for any reason try to clean up a bit. it is very important\n // to not leave `dir` behind, as its existence is a signal that the binaries\n // are installed.\n const rmErrors = (\n await Promise.allSettled([rm(tempDir, rmOpts), rm(dir, rmOpts)])\n )\n .filter((r) => r.status === 'rejected')\n .map((r) => (r as PromiseRejectedResult).reason);\n\n // if we failed to clean up, create an aggregate error message\n if (rmErrors.length) {\n throw new AggregateError(\n [error, ...rmErrors],\n 'This is a bug; you should report it.',\n );\n }\n throw error;\n }\n}\n/**\n * Extracts the binaries from a tar archive.\n *\n * @param url - The URL of the archive to extract the binaries from\n * @param binaries - The list of binaries to extract\n * @param dir - The destination directory\n * @param checksumAlgorithm - The checksum algorithm to use\n * @returns The list of binaries extracted\n */\n\n/**\n * Extracts the binaries from a tar archive.\n *\n * @param url - The URL of the archive to extract the binaries from\n * @param binaries - The list of binaries to extract\n * @param dir - The destination directory\n * @param checksumAlgorithm - The checksum algorithm to use\n * @returns The list of binaries extracted\n */\nasync function extractFromTar(\n url: URL,\n binaries: Binary[],\n dir: string,\n checksumAlgorithm?: string,\n) {\n const downloads: {\n path: string;\n binary: Binary;\n checksum?: string;\n }[] = [];\n await pipeline(\n startDownload(url),\n extractTar(\n {\n cwd: dir,\n // @ts-expect-error: Types here broke in `tar@7.5.12`, but it appears to\n // work fine as-is.\n // See: https://github.com/isaacs/node-tar/issues/459\n transform: (entry) => {\n const absolutePath = entry.absolute;\n if (!absolutePath) {\n throw new Error('Missing absolute path for entry');\n }\n\n if (checksumAlgorithm) {\n const hash = createHash(checksumAlgorithm);\n const passThrough = new Minipass({ async: true });\n passThrough.pipe(hash);\n passThrough.on('end', () => {\n downloads.push({\n path: absolutePath,\n binary: entry.path as Binary,\n checksum: hash.digest('hex'),\n });\n });\n return passThrough;\n }\n\n // When no checksum is needed, record the entry and return undefined\n // to use the original stream without transformation\n downloads.push({\n path: absolutePath,\n binary: entry.path as Binary,\n });\n return undefined;\n },\n },\n binaries,\n ),\n );\n return downloads;\n}\n/**\n * Extracts the binaries from a zip archive.\n *\n * @param url - The URL of the archive to extract the binaries from\n * @param binaries - The list of binaries to extract\n * @param dir - The destination directory\n * @param checksumAlgorithm - The checksum algorithm to use\n * @returns The list of binaries extracted\n */\nasync function extractFromZip(\n url: URL,\n binaries: Binary[],\n dir: string,\n checksumAlgorithm?: string,\n) {\n const agent = new (url.protocol === 'http:' ? HttpAgent : HttpsAgent)({\n keepAlive: true,\n });\n const source: Source = {\n async size() {\n const download = startDownload(url, { agent, method: 'HEAD' });\n const response = await download.response();\n const contentLength = response.headers['content-length'];\n return contentLength ? parseInt(contentLength, 10) : 0;\n },\n stream(offset: number, bytes: number) {\n const options = {\n agent,\n headers: {\n range: `bytes=${offset}-${bytes ? offset + bytes : ''}`,\n },\n };\n return startDownload(url, options);\n },\n };\n\n const { files } = await Open.custom(source, {});\n const filtered = files.filter(({ path }) =>\n binaries.includes(basename(path, extname(path)) as Binary),\n );\n return await Promise.all(\n filtered.map(async ({ path, stream }) => {\n const dest = join(dir, path);\n const entry = stream();\n const destStream = createWriteStream(dest);\n const binary = basename(path, extname(path)) as Binary;\n if (checksumAlgorithm) {\n const hash = createHash(checksumAlgorithm);\n const hashStream = async function* (entryStream: Entry) {\n for await (const chunk of entryStream) {\n hash.update(chunk);\n yield chunk;\n }\n };\n await pipeline(entry, hashStream, destStream);\n return {\n path: dest,\n binary,\n checksum: hash.digest('hex'),\n };\n }\n await pipeline(entry, destStream);\n return {\n path: dest,\n binary,\n };\n }),\n );\n}\n"]}
|