zarro 1.141.5 → 1.141.8
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.
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
(function () {
|
|
4
|
+
const fs = require("fs"), path = require("path"), { ZarroError } = requireModule("zarro-error"), ensureFolderExists = require("./ensure-folder-exists").sync, request = require("request"), debug = require("debug")("http-downloader");
|
|
5
|
+
class HttpClient {
|
|
6
|
+
constructor(infoLogFunction, debugLogFunction) {
|
|
7
|
+
this.aborted = false;
|
|
8
|
+
this._downloadSize = -1;
|
|
9
|
+
this._statusSuffix = "";
|
|
10
|
+
this._written = 0;
|
|
11
|
+
this._lastPerc = -1;
|
|
12
|
+
this._info = infoLogFunction || console.log;
|
|
13
|
+
this._debug = debugLogFunction || debug;
|
|
14
|
+
this.assumeDownloadedIfExistsAndSizeMatches = true;
|
|
15
|
+
}
|
|
16
|
+
async exists(url) {
|
|
17
|
+
return new Promise(resolve => {
|
|
18
|
+
request.get(url, (err) => {
|
|
19
|
+
return resolve(!err);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async download(url, target) {
|
|
24
|
+
if (this._alreadyDownloaded(target)) {
|
|
25
|
+
return target;
|
|
26
|
+
}
|
|
27
|
+
const partFile = `${target}.part`;
|
|
28
|
+
ensureFolderExists(path.dirname(partFile));
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
this._request = request.get(url, { timeout: 30000 })
|
|
31
|
+
.on("response", (response) => {
|
|
32
|
+
this._debug(`got response: ${JSON.stringify(response)}`);
|
|
33
|
+
this._downloadSize = parseInt(response.headers["content-length"] || "0");
|
|
34
|
+
this._statusSuffix = "% of " + this._humanSize(this._downloadSize);
|
|
35
|
+
})
|
|
36
|
+
.on("error", (e) => {
|
|
37
|
+
this._debug(`got error: ${e}`);
|
|
38
|
+
reject(e);
|
|
39
|
+
})
|
|
40
|
+
.on("data", (data) => {
|
|
41
|
+
this._debug(`got ${data.length} bytes`);
|
|
42
|
+
this._updateStatus(data);
|
|
43
|
+
})
|
|
44
|
+
.on("end", () => {
|
|
45
|
+
this._clear();
|
|
46
|
+
this._rename(resolve, reject, partFile, target);
|
|
47
|
+
}).pipe(fs.createWriteStream(partFile));
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
abort() {
|
|
51
|
+
if (this._request) {
|
|
52
|
+
this.aborted = true;
|
|
53
|
+
this._request.abort();
|
|
54
|
+
this._clear();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
_updateStatus(data) {
|
|
58
|
+
if (process.env.SUPPRESS_DOWNLOAD_PROGRESS || process.env.BUILD_NUMBER /* automatically disable at Jenkins CI */) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this._written += data.length;
|
|
62
|
+
const perc = Math.round((100 * this._written) / this._downloadSize);
|
|
63
|
+
if (perc != this._lastPerc) {
|
|
64
|
+
this._writeStatus(perc + this._statusSuffix);
|
|
65
|
+
this._lastPerc = perc;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
_writeStatus(msg) {
|
|
69
|
+
this._clearStatus();
|
|
70
|
+
process.stdout.write(msg);
|
|
71
|
+
}
|
|
72
|
+
_rename(resolve, reject, src, dst, attempts = 0) {
|
|
73
|
+
try {
|
|
74
|
+
this._debug("attempt rename of temp file");
|
|
75
|
+
fs.renameSync(src, dst);
|
|
76
|
+
this._clearStatus();
|
|
77
|
+
this._info(`-> ${dst} download complete!`);
|
|
78
|
+
resolve(dst);
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
this._debug("rename error:", e);
|
|
82
|
+
if (attempts > 99) {
|
|
83
|
+
reject(new ZarroError(["Unable to rename \"", src, "\" to \"", dst, "\": ", e].join("")));
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
setTimeout(() => {
|
|
87
|
+
this._rename(resolve, reject, src, dst, attempts++);
|
|
88
|
+
}, 100);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
_clearStatus() {
|
|
93
|
+
process.stdout.write("\r \r");
|
|
94
|
+
}
|
|
95
|
+
_humanSize(size) {
|
|
96
|
+
const suffixes = ["b", "kb", "mb", "tb", "pb"];
|
|
97
|
+
for (let i = 0; i < suffixes.length - 1; i++) {
|
|
98
|
+
if (size < 1024) {
|
|
99
|
+
return size.toFixed(2) + suffixes[i];
|
|
100
|
+
}
|
|
101
|
+
size /= 1024;
|
|
102
|
+
}
|
|
103
|
+
return size.toFixed(2) + suffixes[suffixes.length - 1];
|
|
104
|
+
}
|
|
105
|
+
_clear() {
|
|
106
|
+
this._request = undefined;
|
|
107
|
+
this._downloadSize = -1;
|
|
108
|
+
this._lastPerc = -1;
|
|
109
|
+
}
|
|
110
|
+
_alreadyDownloaded(target) {
|
|
111
|
+
if (!this.assumeDownloadedIfExistsAndSizeMatches) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
if (!fs.existsSync(target)) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
const lstat = fs.lstatSync(target);
|
|
118
|
+
return lstat.size === this._downloadSize;
|
|
119
|
+
}
|
|
120
|
+
static create(infoLogFunction, debugLogFunction) {
|
|
121
|
+
return new HttpClient(infoLogFunction, debugLogFunction);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
module.exports = HttpClient;
|
|
125
|
+
})();
|
|
@@ -1,113 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
request = require('request'),
|
|
6
|
-
debug = require('debug')('http-downloader');
|
|
7
|
-
|
|
8
|
-
function HttpDownloader(infoLogFunction, debugLogFunction) {
|
|
9
|
-
this._info = infoLogFunction || console.log;
|
|
10
|
-
this._debug = debugLogFunction || debug;
|
|
11
|
-
this.assumeDownloadedIfExistsAndSizeMatches = true;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
HttpDownloader.prototype = {
|
|
15
|
-
download: function (url, target) {
|
|
16
|
-
const partFile = `${target}.part`;
|
|
17
|
-
ensureFolderExists(path.dirname(partFile));
|
|
18
|
-
return new Promise((resolve, reject) => {
|
|
19
|
-
this._request = request.get(url, { timeout: 30000 })
|
|
20
|
-
.on("response", (response) => {
|
|
21
|
-
this._debug(`got response: ${JSON.stringify(response)}`);
|
|
22
|
-
this._downloadSize = parseInt(response.headers["content-length"]);
|
|
23
|
-
this._statusSuffix = '% of ' + this._humanSize(this._downloadSize);
|
|
24
|
-
})
|
|
25
|
-
.on("error", (e) => {
|
|
26
|
-
this._debug(`got error: ${e}`);
|
|
27
|
-
reject(e);
|
|
28
|
-
})
|
|
29
|
-
.on("data", (data) => {
|
|
30
|
-
this._debug(`got ${data.length} bytes`);
|
|
31
|
-
this._updateStatus(data);
|
|
32
|
-
})
|
|
33
|
-
.on("end", () => {
|
|
34
|
-
this._clear();
|
|
35
|
-
this._rename(resolve, reject, partFile, target);
|
|
36
|
-
}).pipe(fs.createWriteStream(partFile));
|
|
37
|
-
});
|
|
38
|
-
},
|
|
39
|
-
abort: function () {
|
|
40
|
-
if (this._request) {
|
|
41
|
-
self._errored = true;
|
|
42
|
-
this._request.abort();
|
|
43
|
-
this._clear();
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
_updateStatus: function (data) {
|
|
47
|
-
if (process.env.SUPPRESS_DOWNLOAD_PROGRESS || process.env.BUILD_NUMBER /* automatically disable at Jenkins CI */) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
this._written = this._written || 0;
|
|
51
|
-
this._written += data.length;
|
|
52
|
-
var perc = Math.round((100 * this._written) / this._downloadSize);
|
|
53
|
-
if (perc != this._lastPerc) {
|
|
54
|
-
this._writeStatus(perc + this._statusSuffix);
|
|
55
|
-
this._lastPerc = perc;
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
_writeStatus: function (msg) {
|
|
59
|
-
this._clearStatus();
|
|
60
|
-
process.stdout.write(msg);
|
|
61
|
-
},
|
|
62
|
-
_rename: function (resolve, reject, src, dst, attempts) {
|
|
63
|
-
try {
|
|
64
|
-
this._debug('attempt rename of temp file');
|
|
65
|
-
fs.renameSync(src, dst)
|
|
66
|
-
this._clearStatus();
|
|
67
|
-
this._info(`-> ${dst} download complete!`);
|
|
68
|
-
resolve(dst)
|
|
69
|
-
} catch (e) {
|
|
70
|
-
this._debug('rename error:', e);
|
|
71
|
-
if (attempts > 99) {
|
|
72
|
-
reject(['Unable to rename "', src, '" to "', ds, '": ', e].join(''));
|
|
73
|
-
} else {
|
|
74
|
-
setTimeout(()=> {
|
|
75
|
-
this._rename(resolve, reject, src, dst, attempts++);
|
|
76
|
-
}, 100);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
_clearStatus: function () {
|
|
81
|
-
process.stdout.write('\r \r');
|
|
82
|
-
},
|
|
83
|
-
_humanSize: function (size) {
|
|
84
|
-
var suffixes = ['b', 'kb', 'mb', 'tb', 'pb'];
|
|
85
|
-
for (var i = 0; i < suffixes.length - 1; i++) {
|
|
86
|
-
if (size < 1024) {
|
|
87
|
-
return size.toFixed(2) + suffixes[i];
|
|
88
|
-
}
|
|
89
|
-
size /= 1024;
|
|
90
|
-
}
|
|
91
|
-
return size.toFixed(2) + suffixes[suffixes.length - 1];
|
|
92
|
-
},
|
|
93
|
-
_clear: function () {
|
|
94
|
-
var self = this;
|
|
95
|
-
['_request', '_response', '_downloadSize', '_lastPerc',
|
|
96
|
-
'_resolveFunction', '_rejectFunction', '_lastData', '_statusSuffix'
|
|
97
|
-
].forEach(function (prop) {
|
|
98
|
-
self[prop] = undefined;
|
|
99
|
-
});
|
|
100
|
-
},
|
|
101
|
-
_alreadyDownloaded: function () {
|
|
102
|
-
if (!this.assumeDownloadedIfExistsAndSizeMatches) {
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
if (!fs.existsSync(this._target)) {
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
var lstat = fs.lstatSync(this._target);
|
|
109
|
-
return lstat.size === this._downloadSize;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
module.exports = HttpDownloader;
|
|
1
|
+
(function() {
|
|
2
|
+
console.warn("http-downloader is deprecated; this is now a shim to http-client");
|
|
3
|
+
module.exports = requireModule("http-downloader");
|
|
4
|
+
})();
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(function () {
|
|
3
|
+
// originally, I wanted to use the opn package, now renamed to
|
|
4
|
+
// open, but the author has kindly made it impossible to require
|
|
5
|
+
// from within zarro (I get an error about it being an ESM module);
|
|
6
|
+
// since my requirements are simple, I'll just roll my own.
|
|
7
|
+
const os = require("os"), { ZarroError } = requireModule("zarro-error"), spawn = requireModule("spawn");
|
|
8
|
+
async function open(url) {
|
|
9
|
+
const opener = findOpenerForPlatform();
|
|
10
|
+
await spawn(opener, [url]);
|
|
11
|
+
}
|
|
12
|
+
function findOpenerForPlatform() {
|
|
13
|
+
switch (os.platform()) {
|
|
14
|
+
case "darwin":
|
|
15
|
+
return "open";
|
|
16
|
+
case "netbsd":
|
|
17
|
+
case "freebsd":
|
|
18
|
+
case "linux":
|
|
19
|
+
case "openbsd":
|
|
20
|
+
return "xdg-open";
|
|
21
|
+
case "win32":
|
|
22
|
+
return "start";
|
|
23
|
+
case "cygwin":
|
|
24
|
+
// if we believe: https://stackoverflow.com/a/577698/1697008
|
|
25
|
+
return "cygstart";
|
|
26
|
+
case "aix":
|
|
27
|
+
case "android":
|
|
28
|
+
case "sunos":
|
|
29
|
+
default:
|
|
30
|
+
throw platformNotSupported();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function platformNotSupported() {
|
|
34
|
+
return new ZarroError(`Platform not supported for opening urls. Please open an issue at https://github.com/fluffynuts/zarro.`);
|
|
35
|
+
}
|
|
36
|
+
module.exports = {
|
|
37
|
+
open
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
@@ -46,13 +46,20 @@
|
|
|
46
46
|
if (!env.resolveFlag(env.DEV_SMTP_OPEN_INTERFACE)) {
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
49
|
-
const url = generateInterfaceUrlFor(ip, port), open =
|
|
49
|
+
const url = generateInterfaceUrlFor(ip, port), { open } = requireModule("open");
|
|
50
|
+
await waitForUrlToBecomeAvailable(url);
|
|
50
51
|
logInfo(`
|
|
51
52
|
Opening the dev smtp interface in your browser (${url})
|
|
52
|
-
To disable this
|
|
53
|
+
To disable this behavior, set env variable ${env.DEV_SMTP_OPEN_INTERFACE}=0
|
|
53
54
|
`.trim());
|
|
54
55
|
await open(url);
|
|
55
56
|
}
|
|
57
|
+
async function waitForUrlToBecomeAvailable(url) {
|
|
58
|
+
const sleep = requireModule("sleep"), HttpClient = requireModule("http-client"), httpClient = HttpClient.create();
|
|
59
|
+
do {
|
|
60
|
+
await sleep(500);
|
|
61
|
+
} while (!(await httpClient.exists(url)));
|
|
62
|
+
}
|
|
56
63
|
const ipMap = {
|
|
57
64
|
"[::]": "localhost",
|
|
58
65
|
"127.0.0.1": "localhost"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zarro",
|
|
3
|
-
"version": "1.141.
|
|
3
|
+
"version": "1.141.8",
|
|
4
4
|
"description": "Some glue to make gulp easier, perhaps even zero- or close-to-zero-conf",
|
|
5
5
|
"bin": {
|
|
6
6
|
"zarro": "./index.js"
|
|
@@ -54,7 +54,6 @@
|
|
|
54
54
|
"gulp-msbuild": "^0.10.0",
|
|
55
55
|
"mkdirp": "^1.0.4",
|
|
56
56
|
"npm-run-all": "^4.1.5",
|
|
57
|
-
"open": "^9.1.0",
|
|
58
57
|
"plugin-error": "^1.0.1",
|
|
59
58
|
"readline": "^1.3.0",
|
|
60
59
|
"request": "^2.88.2",
|
|
@@ -90,6 +89,7 @@
|
|
|
90
89
|
"@types/gulp": "^4.0.8",
|
|
91
90
|
"@types/jest": "^26.0.20",
|
|
92
91
|
"@types/node": "^13.13.40",
|
|
92
|
+
"@types/request": "^2.48.8",
|
|
93
93
|
"@types/rimraf": "^3.0.0",
|
|
94
94
|
"@types/through2": "^2.0.38",
|
|
95
95
|
"@types/xml2js": "^0.4.8",
|
package/types.d.ts
CHANGED
|
@@ -45,6 +45,18 @@ declare global {
|
|
|
45
45
|
): Transform;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
interface HttpClient {
|
|
49
|
+
download(url: string, target: string): Promise<string>;
|
|
50
|
+
exists(url: string): Promise<boolean>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface HttpClientModule {
|
|
54
|
+
create(
|
|
55
|
+
infoLogFunction?: (s: string) => void,
|
|
56
|
+
debugLogFunction?: (s: string) => void
|
|
57
|
+
): HttpClient;
|
|
58
|
+
}
|
|
59
|
+
|
|
48
60
|
interface GulpWithHelp {
|
|
49
61
|
task(name: string, callback: GulpCallback): void;
|
|
50
62
|
task(name: string, help: string, callback: GulpCallback): void;
|
|
@@ -217,6 +229,9 @@ declare global {
|
|
|
217
229
|
}
|
|
218
230
|
|
|
219
231
|
type GetToolsFolder = (overrideEnv?: Env) => string;
|
|
232
|
+
interface Open {
|
|
233
|
+
open(url: string): Promise<void>;
|
|
234
|
+
}
|
|
220
235
|
|
|
221
236
|
interface Env {
|
|
222
237
|
resolve(...names: (StringEnvVar | VersionIncrementStrategy)[]): string;
|