zarro 1.92.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/LICENSE +10 -0
- package/README.md +260 -0
- package/gulp-tasks/.editorconfig +8 -0
- package/gulp-tasks/.git +1 -0
- package/gulp-tasks/.gitignore +9 -0
- package/gulp-tasks/.gitmodules +0 -0
- package/gulp-tasks/LICENSE +24 -0
- package/gulp-tasks/README.md +144 -0
- package/gulp-tasks/build.js +135 -0
- package/gulp-tasks/clean.js +37 -0
- package/gulp-tasks/cover-dotnet.js +56 -0
- package/gulp-tasks/default-report-generator.js +51 -0
- package/gulp-tasks/default-tools-installer.js +33 -0
- package/gulp-tasks/default.js +17 -0
- package/gulp-tasks/dotnet-publish.js +23 -0
- package/gulp-tasks/generate-reports.js +7 -0
- package/gulp-tasks/get-local-nuget.js +16 -0
- package/gulp-tasks/git-submodules.js +83 -0
- package/gulp-tasks/increment-package-json-version.js +12 -0
- package/gulp-tasks/increment-package-json-version.ts +17 -0
- package/gulp-tasks/install-tools.js +24 -0
- package/gulp-tasks/modules/add-stream-on-any-handler.js +31 -0
- package/gulp-tasks/modules/alter-package-json-version.js +64 -0
- package/gulp-tasks/modules/alter-package-json-version.ts +113 -0
- package/gulp-tasks/modules/are-all-dotnet-core.js +96 -0
- package/gulp-tasks/modules/ask.js +31 -0
- package/gulp-tasks/modules/ask.ts +41 -0
- package/gulp-tasks/modules/collect-files.js +15 -0
- package/gulp-tasks/modules/collect-files.ts +16 -0
- package/gulp-tasks/modules/config-generator.js +10 -0
- package/gulp-tasks/modules/defaults.js +9 -0
- package/gulp-tasks/modules/download-nuget.js +104 -0
- package/gulp-tasks/modules/ensure-folder-exists.js +21 -0
- package/gulp-tasks/modules/env-helpers.js +49 -0
- package/gulp-tasks/modules/env-helpers.ts +67 -0
- package/gulp-tasks/modules/env.js +364 -0
- package/gulp-tasks/modules/exec.js +257 -0
- package/gulp-tasks/modules/exec.ts +346 -0
- package/gulp-tasks/modules/fail-after.js +30 -0
- package/gulp-tasks/modules/fail-after.ts +34 -0
- package/gulp-tasks/modules/fallback.js +6 -0
- package/gulp-tasks/modules/find-dirs.js +39 -0
- package/gulp-tasks/modules/find-local-nuget.js +42 -0
- package/gulp-tasks/modules/find-npm-base.js +42 -0
- package/gulp-tasks/modules/fs.js +79 -0
- package/gulp-tasks/modules/gather-paths.js +23 -0
- package/gulp-tasks/modules/gather-paths.ts +29 -0
- package/gulp-tasks/modules/generate-env-help-for.js +30 -0
- package/gulp-tasks/modules/get-tools-folder.js +12 -0
- package/gulp-tasks/modules/git-push-tags.js +33 -0
- package/gulp-tasks/modules/git-push-tags.ts +42 -0
- package/gulp-tasks/modules/git-push.js +51 -0
- package/gulp-tasks/modules/git-tag.js +36 -0
- package/gulp-tasks/modules/gulp-dotnetcover.js +537 -0
- package/gulp-tasks/modules/gulp-git-tag-from-csproj.js +50 -0
- package/gulp-tasks/modules/gulp-git-tag-from-csproj.ts +71 -0
- package/gulp-tasks/modules/gulp-git-tag-from-package-nuspec.js +55 -0
- package/gulp-tasks/modules/gulp-increment-nuget-package-dependency-version.js +40 -0
- package/gulp-tasks/modules/gulp-increment-nuget-package-version.js +87 -0
- package/gulp-tasks/modules/gulp-increment-nuget-package-version.ts +122 -0
- package/gulp-tasks/modules/gulp-msbuild.js +1 -0
- package/gulp-tasks/modules/gulp-npm-run.js +40 -0
- package/gulp-tasks/modules/gulp-npm-run.ts +52 -0
- package/gulp-tasks/modules/gulp-nuget-pack.js +168 -0
- package/gulp-tasks/modules/gulp-nuget-restore.js +106 -0
- package/gulp-tasks/modules/gulp-nunit-runner/.jshintrc +5 -0
- package/gulp-tasks/modules/gulp-nunit-runner/.npmignore +16 -0
- package/gulp-tasks/modules/gulp-nunit-runner/LICENSE +21 -0
- package/gulp-tasks/modules/gulp-nunit-runner/README.md +300 -0
- package/gulp-tasks/modules/gulp-nunit-runner/index.js +1 -0
- package/gulp-tasks/modules/gulp-nunit-runner/lib/index.js +205 -0
- package/gulp-tasks/modules/gulp-nunit-runner/lib/teamcity.js +86 -0
- package/gulp-tasks/modules/gulp-purge.js +88 -0
- package/gulp-tasks/modules/gulp-util.js +5 -0
- package/gulp-tasks/modules/gulp-version.js +8 -0
- package/gulp-tasks/modules/gulp-with-help.js +1 -0
- package/gulp-tasks/modules/gulp-xbuild.js +62 -0
- package/gulp-tasks/modules/gulp.js +92 -0
- package/gulp-tasks/modules/http-downloader.js +113 -0
- package/gulp-tasks/modules/import-npm-tasks.js +33 -0
- package/gulp-tasks/modules/increment-version-string.js +18 -0
- package/gulp-tasks/modules/increment-version.js +30 -0
- package/gulp-tasks/modules/increment-version.ts +41 -0
- package/gulp-tasks/modules/install-local-tools.js +122 -0
- package/gulp-tasks/modules/load-xml-file.js +12 -0
- package/gulp-tasks/modules/load-xml-file.ts +15 -0
- package/gulp-tasks/modules/log-config.js +31 -0
- package/gulp-tasks/modules/log.js +142 -0
- package/gulp-tasks/modules/longest-string-length.js +13 -0
- package/gulp-tasks/modules/looks-like-a-promise.js +11 -0
- package/gulp-tasks/modules/ls-r.js +52 -0
- package/gulp-tasks/modules/multi-split.js +29 -0
- package/gulp-tasks/modules/net-framework-test-assembly-filter.js +45 -0
- package/gulp-tasks/modules/nuget-push.js +66 -0
- package/gulp-tasks/modules/nuget-update-self.js +9 -0
- package/gulp-tasks/modules/nuget.js +8 -0
- package/gulp-tasks/modules/nuget.ts +14 -0
- package/gulp-tasks/modules/pad-left.js +4 -0
- package/gulp-tasks/modules/pad-right.js +4 -0
- package/gulp-tasks/modules/pad.js +25 -0
- package/gulp-tasks/modules/parse-xml-string.js +5 -0
- package/gulp-tasks/modules/parse-xml-string.ts +6 -0
- package/gulp-tasks/modules/parse-xml.js +14 -0
- package/gulp-tasks/modules/parse-xml.ts +15 -0
- package/gulp-tasks/modules/path-unquote.js +6 -0
- package/gulp-tasks/modules/promisify-function.js +19 -0
- package/gulp-tasks/modules/promisify-function.ts +18 -0
- package/gulp-tasks/modules/promisify-stream.js +73 -0
- package/gulp-tasks/modules/promisify.js +1 -0
- package/gulp-tasks/modules/quote-if-required.js +14 -0
- package/gulp-tasks/modules/read-all-git-branches.js +10 -0
- package/gulp-tasks/modules/read-all-git-branches.ts +13 -0
- package/gulp-tasks/modules/read-all-git-remotes.js +36 -0
- package/gulp-tasks/modules/read-all-git-remotes.ts +44 -0
- package/gulp-tasks/modules/read-csproj-package-version.js +16 -0
- package/gulp-tasks/modules/read-csproj-package-version.ts +26 -0
- package/gulp-tasks/modules/read-csproj-version.js +16 -0
- package/gulp-tasks/modules/read-csproj-version.ts +26 -0
- package/gulp-tasks/modules/read-current-git-branch.js +12 -0
- package/gulp-tasks/modules/read-current-git-branch.ts +16 -0
- package/gulp-tasks/modules/read-git-commit-delta-count.js +21 -0
- package/gulp-tasks/modules/read-git-commit-delta-count.ts +33 -0
- package/gulp-tasks/modules/read-git-info.js +28 -0
- package/gulp-tasks/modules/read-git-info.ts +31 -0
- package/gulp-tasks/modules/read-git-remote.js +17 -0
- package/gulp-tasks/modules/read-git-remote.ts +23 -0
- package/gulp-tasks/modules/read-last-fetch-time.js +21 -0
- package/gulp-tasks/modules/read-last-fetch-time.ts +17 -0
- package/gulp-tasks/modules/read-main-branch-name.js +48 -0
- package/gulp-tasks/modules/read-main-branch-name.ts +76 -0
- package/gulp-tasks/modules/read-nuspec-version.js +14 -0
- package/gulp-tasks/modules/read-nuspec-version.ts +22 -0
- package/gulp-tasks/modules/read-package-json.js +16 -0
- package/gulp-tasks/modules/read-package-json.ts +22 -0
- package/gulp-tasks/modules/read-package-version.js +8 -0
- package/gulp-tasks/modules/read-package-version.ts +10 -0
- package/gulp-tasks/modules/read-text-file.js +14 -0
- package/gulp-tasks/modules/read-text-file.ts +14 -0
- package/gulp-tasks/modules/reduce-gulp-noise.js +34 -0
- package/gulp-tasks/modules/register-environment-variables.js +526 -0
- package/gulp-tasks/modules/require-module.js +28 -0
- package/gulp-tasks/modules/resolve-git-branch.js +11 -0
- package/gulp-tasks/modules/resolve-git-branch.ts +13 -0
- package/gulp-tasks/modules/resolve-git-remote.js +11 -0
- package/gulp-tasks/modules/resolve-git-remote.ts +13 -0
- package/gulp-tasks/modules/resolve-masks.js +47 -0
- package/gulp-tasks/modules/resolve-nuget.js +135 -0
- package/gulp-tasks/modules/resolve-test-masks.js +10 -0
- package/gulp-tasks/modules/rewrite-file.js +26 -0
- package/gulp-tasks/modules/rewrite-file.ts +34 -0
- package/gulp-tasks/modules/rimraf.js +21 -0
- package/gulp-tasks/modules/rimraf.ts +31 -0
- package/gulp-tasks/modules/run-sequence.js +16 -0
- package/gulp-tasks/modules/safe-git.js +23 -0
- package/gulp-tasks/modules/safe-git.ts +23 -0
- package/gulp-tasks/modules/seed.js +12 -0
- package/gulp-tasks/modules/set-task-name.js +9 -0
- package/gulp-tasks/modules/sleep.js +5 -0
- package/gulp-tasks/modules/spawn-nuget.js +13 -0
- package/gulp-tasks/modules/spawn.js +103 -0
- package/gulp-tasks/modules/split-path.js +3 -0
- package/gulp-tasks/modules/stat.js +8 -0
- package/gulp-tasks/modules/status.js +57 -0
- package/gulp-tasks/modules/status.ts +71 -0
- package/gulp-tasks/modules/test-path.js +3 -0
- package/gulp-tasks/modules/testutil-finder.js +176 -0
- package/gulp-tasks/modules/throw-if-no-files.js +15 -0
- package/gulp-tasks/modules/uniq.js +6 -0
- package/gulp-tasks/modules/uniq.ts +5 -0
- package/gulp-tasks/modules/verify-exe.js +17 -0
- package/gulp-tasks/modules/version-reading-shared.js +12 -0
- package/gulp-tasks/modules/version-reading-shared.ts +16 -0
- package/gulp-tasks/modules/write-text-file.js +10 -0
- package/gulp-tasks/modules/zarro-error.js +6 -0
- package/gulp-tasks/nuget-restore.js +57 -0
- package/gulp-tasks/pack.js +118 -0
- package/gulp-tasks/purge.js +94 -0
- package/gulp-tasks/release-npm.js +58 -0
- package/gulp-tasks/release-npm.ts +81 -0
- package/gulp-tasks/start/_package.json +39 -0
- package/gulp-tasks/start/gulpfile.js +204 -0
- package/gulp-tasks/start/update-starter-packages.js +63 -0
- package/gulp-tasks/test-dotnet.js +195 -0
- package/gulp-tasks/update-git-submodules.js +11 -0
- package/gulp-tasks/update-git-submodules.ts +29 -0
- package/gulp-tasks/update-self.js +65 -0
- package/gulp-tasks/update-self.ts +88 -0
- package/gulp-tasks/verify-up-to-date.js +77 -0
- package/gulp-tasks/verify-up-to-date.ts +119 -0
- package/index-modules/contains-any.js +31 -0
- package/index-modules/gather-args.js +21 -0
- package/index-modules/handlers/help.js +17 -0
- package/index-modules/handlers/init.js +57 -0
- package/index-modules/handlers/invoke-gulp.js +111 -0
- package/index-modules/handlers/show-env.js +46 -0
- package/index-modules/is-dir.js +6 -0
- package/index-modules/is-file.js +6 -0
- package/index.js +53 -0
- package/package.json +96 -0
- package/tsconfig.json +66 -0
- package/types.d.ts +753 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as vinyl from "vinyl";
|
|
2
|
+
|
|
3
|
+
(function() {
|
|
4
|
+
// collects the files from a gulp stream
|
|
5
|
+
const
|
|
6
|
+
es = require("event-stream");
|
|
7
|
+
module.exports = function collectFiles(target: vinyl.BufferFile[]) {
|
|
8
|
+
const stream = es.through(function data(file: vinyl.BufferFile) {
|
|
9
|
+
target.push(file);
|
|
10
|
+
stream.emit("data", file);
|
|
11
|
+
}, function end() {
|
|
12
|
+
stream.emit("end");
|
|
13
|
+
});
|
|
14
|
+
return stream;
|
|
15
|
+
}
|
|
16
|
+
})();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var env = requireModule("env"),
|
|
2
|
+
path = require("path");
|
|
3
|
+
|
|
4
|
+
module.exports = function configGenerator() {
|
|
5
|
+
return {
|
|
6
|
+
localNuget: path.join(env.resolve("BUILD_TOOLS_FOLDER"), "nuget.exe"),
|
|
7
|
+
nugetDownloadUrl:
|
|
8
|
+
"http://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
|
|
9
|
+
};
|
|
10
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const
|
|
2
|
+
{ ZarroError } = requireModule("zarro-error"),
|
|
3
|
+
HttpDownloader = require("./http-downloader"),
|
|
4
|
+
nugetUpdateSelf = require("./nuget-update-self"),
|
|
5
|
+
logger = require("./log"),
|
|
6
|
+
path = require("path"),
|
|
7
|
+
url = 'http://dist.nuget.org/win-x86-commandline/latest/nuget.exe';
|
|
8
|
+
|
|
9
|
+
function downloadNugetTo(targetFolder) {
|
|
10
|
+
logger.debug(`Attempting to download nuget.exe to ${targetFolder}`);
|
|
11
|
+
const
|
|
12
|
+
downloader = new HttpDownloader(),
|
|
13
|
+
target = path.join(targetFolder, "nuget.exe");
|
|
14
|
+
return downloader
|
|
15
|
+
.download(url, path.join(targetFolder, "nuget.exe"))
|
|
16
|
+
.then(() => validateCanRunExe(target));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const
|
|
20
|
+
validators = {},
|
|
21
|
+
cached = {};
|
|
22
|
+
|
|
23
|
+
function validateCanRunExe(exePath) {
|
|
24
|
+
if (validators[exePath]) {
|
|
25
|
+
return validators[exePath];
|
|
26
|
+
}
|
|
27
|
+
const shouldLog = !validators[exePath];
|
|
28
|
+
if (shouldLog) {
|
|
29
|
+
logger.debug(`validating exe at: ${exePath}`);
|
|
30
|
+
}
|
|
31
|
+
return validators[exePath] = new Promise((resolve, reject) => {
|
|
32
|
+
let lastMessage = "unknown error",
|
|
33
|
+
attempts = 0;
|
|
34
|
+
setTimeout(function testExe() {
|
|
35
|
+
if (cached[exePath]) {
|
|
36
|
+
return resolve(exePath);
|
|
37
|
+
}
|
|
38
|
+
if (attempts === 10) {
|
|
39
|
+
return reject(`Unable to run executable at ${exePath}: ${lastMessage}`);
|
|
40
|
+
}
|
|
41
|
+
attempts++;
|
|
42
|
+
if (shouldLog) {
|
|
43
|
+
logger.debug(`attempt #${attempts} to run ${exePath}`);
|
|
44
|
+
}
|
|
45
|
+
const a = attempts;
|
|
46
|
+
nugetUpdateSelf(exePath).then(() => {
|
|
47
|
+
if (shouldLog) {
|
|
48
|
+
const sub = a > 1 ? ` (${a})` : "";
|
|
49
|
+
logger.info(`nuget.exe appears to be valid!${sub}`);
|
|
50
|
+
}
|
|
51
|
+
cached[exePath] = true;
|
|
52
|
+
return resolve(exePath);
|
|
53
|
+
}).catch(e => {
|
|
54
|
+
lastMessage = e.message || lastMessage;
|
|
55
|
+
if (shouldLog) {
|
|
56
|
+
logger.debug(`failed to run executable (${
|
|
57
|
+
e.message
|
|
58
|
+
}); ${
|
|
59
|
+
attempts < 9
|
|
60
|
+
? "will try again"
|
|
61
|
+
: "giving up"
|
|
62
|
+
}`);
|
|
63
|
+
}
|
|
64
|
+
setTimeout(testExe, 1000);
|
|
65
|
+
});
|
|
66
|
+
}, 1000);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function retry(fn, attempt, maxAttempts, wait) {
|
|
71
|
+
attempt = attempt || 0;
|
|
72
|
+
maxAttempts = maxAttempts || 10;
|
|
73
|
+
wait = wait || 5000;
|
|
74
|
+
if (wait < 1000) {
|
|
75
|
+
wait *= 1000;
|
|
76
|
+
}
|
|
77
|
+
return fn().catch(e => {
|
|
78
|
+
if (attempt >= maxAttempts) {
|
|
79
|
+
throw new ZarroError(`${e} (giving up after ${attempt} attempts)`);
|
|
80
|
+
} else {
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
console.warn(e);
|
|
84
|
+
console.log(`trying again in ${wait / 1000}s (${++attempt} / ${maxAttempts})`);
|
|
85
|
+
retry(fn, attempt, maxAttempts).then(function () {
|
|
86
|
+
resolve(Array.from(arguments));
|
|
87
|
+
}).catch(function () {
|
|
88
|
+
reject(Array.from(arguments));
|
|
89
|
+
});
|
|
90
|
+
}, wait);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
module.exports = function downloadNuget(targetFolder) {
|
|
97
|
+
return retry(() =>
|
|
98
|
+
downloadNugetTo(targetFolder)
|
|
99
|
+
).then(downloaded => {
|
|
100
|
+
console.log(`nuget downloaded to: ${downloaded}`);
|
|
101
|
+
return downloaded;
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const
|
|
2
|
+
fs = require("fs"),
|
|
3
|
+
debug = require("debug")("ensure-folder-exists")
|
|
4
|
+
|
|
5
|
+
module.exports = function ensureFolderExists(folder) {
|
|
6
|
+
debug(`Ensuring existence of tools folder "${folder}"`);
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
try {
|
|
9
|
+
if (!fs.existsSync(folder)) {
|
|
10
|
+
fs.mkdirSync(folder);
|
|
11
|
+
}
|
|
12
|
+
debug(`${folder} exists!`);
|
|
13
|
+
resolve();
|
|
14
|
+
} catch (e) {
|
|
15
|
+
debug(`${folder} doesn't exist and not creatable`);
|
|
16
|
+
debug(e);
|
|
17
|
+
reject(e);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(function () {
|
|
3
|
+
const { ZarroError } = requireModule("zarro-error");
|
|
4
|
+
function env(name, fallback) {
|
|
5
|
+
const value = process.env[name];
|
|
6
|
+
if (value !== undefined) {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
const argCount = Array.from(arguments).length;
|
|
10
|
+
if (argCount > 1) {
|
|
11
|
+
return fallback;
|
|
12
|
+
}
|
|
13
|
+
throw new ZarroError(`environment variable '${name}' is not defined and no fallback provided`);
|
|
14
|
+
}
|
|
15
|
+
function envNumber(name, fallback) {
|
|
16
|
+
const haveFallback = fallback !== undefined, value = haveFallback ? env(name, fallback === null || fallback === void 0 ? void 0 : fallback.toString()) : env(name), parsed = parseInt(value, 10);
|
|
17
|
+
if (!isNaN(parsed)) {
|
|
18
|
+
return parsed;
|
|
19
|
+
}
|
|
20
|
+
throw new ZarroError(`environment variable '${name}' is invalid: expected numeric value but found '${value}'`);
|
|
21
|
+
}
|
|
22
|
+
function envFlag(name, fallback) {
|
|
23
|
+
const haveFallback = fallback !== undefined, value = haveFallback ? env(name, fallback === null || fallback === void 0 ? void 0 : fallback.toString()) : env(name);
|
|
24
|
+
return parseBool(name, value);
|
|
25
|
+
}
|
|
26
|
+
const truthy = [
|
|
27
|
+
"1",
|
|
28
|
+
"yes",
|
|
29
|
+
"true"
|
|
30
|
+
], falsey = [
|
|
31
|
+
"0",
|
|
32
|
+
"no",
|
|
33
|
+
"false"
|
|
34
|
+
];
|
|
35
|
+
function parseBool(name, value) {
|
|
36
|
+
if (truthy.indexOf(value === null || value === void 0 ? void 0 : value.toString()) > -1) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
if (falsey.indexOf(value === null || value === void 0 ? void 0 : value.toString()) > -1) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
throw new ZarroError(`environment variable '${name}' is invalid: could not parse '${value}' as a boolean value`);
|
|
43
|
+
}
|
|
44
|
+
module.exports = {
|
|
45
|
+
env,
|
|
46
|
+
envNumber,
|
|
47
|
+
envFlag
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
const { ZarroError } = requireModule("zarro-error");
|
|
3
|
+
|
|
4
|
+
function env(name: string, fallback?: string): string {
|
|
5
|
+
const value = process.env[name];
|
|
6
|
+
if (value !== undefined) {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
const argCount = Array.from(arguments).length;
|
|
10
|
+
if (argCount > 1) {
|
|
11
|
+
return fallback as string;
|
|
12
|
+
}
|
|
13
|
+
throw new ZarroError(
|
|
14
|
+
`environment variable '${ name }' is not defined and no fallback provided`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function envNumber(name: string, fallback?: number): number {
|
|
19
|
+
const
|
|
20
|
+
haveFallback = fallback !== undefined,
|
|
21
|
+
value = haveFallback ? env(name, fallback?.toString()) : env(name),
|
|
22
|
+
parsed = parseInt(value, 10);
|
|
23
|
+
if (!isNaN(parsed)) {
|
|
24
|
+
return parsed;
|
|
25
|
+
}
|
|
26
|
+
throw new ZarroError(
|
|
27
|
+
`environment variable '${ name }' is invalid: expected numeric value but found '${ value }'`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function envFlag(name: string, fallback?: boolean): boolean {
|
|
32
|
+
const
|
|
33
|
+
haveFallback = fallback !== undefined,
|
|
34
|
+
value = haveFallback ? env(name, fallback?.toString()) : env(name);
|
|
35
|
+
return parseBool(name, value);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const truthy = [
|
|
39
|
+
"1",
|
|
40
|
+
"yes",
|
|
41
|
+
"true"
|
|
42
|
+
],
|
|
43
|
+
falsey = [
|
|
44
|
+
"0",
|
|
45
|
+
"no",
|
|
46
|
+
"false"
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
function parseBool(name: string, value: string): boolean {
|
|
50
|
+
if (truthy.indexOf(value?.toString()) > -1) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
if (falsey.indexOf(value?.toString()) > -1) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
throw new ZarroError(
|
|
57
|
+
`environment variable '${name}' is invalid: could not parse '${value}' as a boolean value`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = {
|
|
62
|
+
env,
|
|
63
|
+
envNumber,
|
|
64
|
+
envFlag
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
})();
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
if (!Array.prototype.flatMap) {
|
|
2
|
+
try {
|
|
3
|
+
const flatMap = require("array.prototype.flatmap");
|
|
4
|
+
flatMap.shim();
|
|
5
|
+
} catch (e) {
|
|
6
|
+
console.error(
|
|
7
|
+
"Array.prototype.flatmap is required -- either use a newer Node or install the npm package array.prototype.flatmap"
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const
|
|
12
|
+
{ ZarroError } = requireModule("zarro-error"),
|
|
13
|
+
chalk = require("ansi-colors"),
|
|
14
|
+
debug = require("debug")("env"),
|
|
15
|
+
registeredEnvironmentVariables = {},
|
|
16
|
+
longestStringLength = require("./longest-string-length"),
|
|
17
|
+
padRight = require("./pad-right"),
|
|
18
|
+
padLeft = require("./pad-left"),
|
|
19
|
+
toExport = {
|
|
20
|
+
flag,
|
|
21
|
+
fallback,
|
|
22
|
+
register,
|
|
23
|
+
printHelp,
|
|
24
|
+
taskHelp,
|
|
25
|
+
resolve,
|
|
26
|
+
associate,
|
|
27
|
+
resolveArray,
|
|
28
|
+
explode,
|
|
29
|
+
overrideDefault,
|
|
30
|
+
resolveNumber,
|
|
31
|
+
resolveFlag
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const positives = [ "1", "yes", "true" ];
|
|
35
|
+
if (process.env.POSITIVE_FLAG) {
|
|
36
|
+
positives.push(process.env.POSITIVE_FLAG);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function flag(name, defaultValue) {
|
|
40
|
+
const envVar = fallback(name, defaultValue);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
envVar === true || positives.indexOf((envVar || "").toLowerCase()) > -1
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function fallback(name, defaultValue) {
|
|
48
|
+
const envVar = process.env[name];
|
|
49
|
+
return envVar === undefined ? defaultValue : envVar;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function register(config) {
|
|
53
|
+
let { name, help, tasks, overriddenBy, when } = config;
|
|
54
|
+
if (toExport[name] !== undefined) {
|
|
55
|
+
throw new ZarroError(`env var already registered: ${name}`);
|
|
56
|
+
}
|
|
57
|
+
toExport[name] = name;
|
|
58
|
+
// 'default' seems like a more natural name, but we can't use it for a var name...
|
|
59
|
+
let fallback = config.default;
|
|
60
|
+
if (registeredEnvironmentVariables[name]) {
|
|
61
|
+
return update(name, fallback, help, tasks, overriddenBy, when);
|
|
62
|
+
}
|
|
63
|
+
tasks = normaliseArray(tasks);
|
|
64
|
+
help = trim(help);
|
|
65
|
+
fallback = trim(fallback);
|
|
66
|
+
|
|
67
|
+
registeredEnvironmentVariables[name] = {
|
|
68
|
+
help,
|
|
69
|
+
tasks,
|
|
70
|
+
default: fallback,
|
|
71
|
+
overriddenBy: overriddenBy || [],
|
|
72
|
+
when
|
|
73
|
+
};
|
|
74
|
+
if (pendingAssociations[name]) {
|
|
75
|
+
const otherTasks = pendingAssociations[name];
|
|
76
|
+
delete pendingAssociations[name];
|
|
77
|
+
tasks.push.apply(tasks, otherTasks);
|
|
78
|
+
}
|
|
79
|
+
if (pendingDefaultOverrides[name]) {
|
|
80
|
+
registeredEnvironmentVariables[name].default =
|
|
81
|
+
pendingDefaultOverrides[name];
|
|
82
|
+
delete pendingDefaultOverrides[name];
|
|
83
|
+
}
|
|
84
|
+
debug({
|
|
85
|
+
label: `register env var: ${name}`,
|
|
86
|
+
config: registeredEnvironmentVariables[name]
|
|
87
|
+
});
|
|
88
|
+
return toExport;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const pendingAssociations = {};
|
|
92
|
+
|
|
93
|
+
function associate(varName, tasks) {
|
|
94
|
+
if (Array.isArray(varName)) {
|
|
95
|
+
varName.forEach(v => associate(v, tasks));
|
|
96
|
+
return toExport;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!varName || !tasks || tasks.length === 0) {
|
|
100
|
+
return toExport;
|
|
101
|
+
}
|
|
102
|
+
if (!Array.isArray(tasks)) {
|
|
103
|
+
tasks = [ tasks ];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const target = registeredEnvironmentVariables[varName]
|
|
107
|
+
? registeredEnvironmentVariables[varName].tasks
|
|
108
|
+
: (pendingAssociations[varName] = pendingAssociations[varName] || []);
|
|
109
|
+
tasks.forEach(task => {
|
|
110
|
+
if (target.indexOf(task) > -1) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
target.push(task);
|
|
114
|
+
});
|
|
115
|
+
return toExport;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const pendingDefaultOverrides = {};
|
|
119
|
+
|
|
120
|
+
function overrideDefault(varName, newDefault) {
|
|
121
|
+
const target = registeredEnvironmentVariables[varName];
|
|
122
|
+
if (target) {
|
|
123
|
+
target.default = newDefault;
|
|
124
|
+
} else {
|
|
125
|
+
pendingDefaultOverrides[varName] = newDefault;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function normaliseArray(arr) {
|
|
130
|
+
if (!arr) {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
return Array.isArray(arr) ? arr : [ arr ];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function update(varName, fallbackValue, help, tasks, overriddenBy, when) {
|
|
137
|
+
const target = registeredEnvironmentVariables[varName];
|
|
138
|
+
if (!target.help) {
|
|
139
|
+
target.help = trim(help);
|
|
140
|
+
}
|
|
141
|
+
if (!target.default) {
|
|
142
|
+
target.default = trim(fallbackValue);
|
|
143
|
+
}
|
|
144
|
+
tasks = normaliseArray(tasks);
|
|
145
|
+
target.tasks = target.tasks.concat(tasks);
|
|
146
|
+
target.overriddenBy = target.overriddenBy.concat(overriddenBy || []);
|
|
147
|
+
// TODO: composite when? this code is first-come-first-wins
|
|
148
|
+
target.when = target.when || when;
|
|
149
|
+
debug({
|
|
150
|
+
label: `update env var: ${varName}`,
|
|
151
|
+
config: target
|
|
152
|
+
});
|
|
153
|
+
return toExport;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function trim(str) {
|
|
157
|
+
if (str === null || str === undefined) {
|
|
158
|
+
return "";
|
|
159
|
+
}
|
|
160
|
+
if (Array.isArray(str)) {
|
|
161
|
+
return str.map(s => s.trim());
|
|
162
|
+
}
|
|
163
|
+
return str.toString().trim();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function printHelp() {
|
|
167
|
+
printHelpFor(listVars());
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function printHelpFor(vars) {
|
|
171
|
+
const longest = longestStringLength(vars);
|
|
172
|
+
vars.forEach(k =>
|
|
173
|
+
createHelpFor(k, longest).forEach(line => console.log(line))
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function indent(str, howMany) {
|
|
178
|
+
if (howMany === undefined || howMany < 1) {
|
|
179
|
+
howMany = 1;
|
|
180
|
+
}
|
|
181
|
+
return padLeft(str, howMany * 2 + str.length);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const tasksPre = chalk.greenBright("tasks"),
|
|
185
|
+
defaultPre = chalk.cyanBright("default");
|
|
186
|
+
|
|
187
|
+
function createHelpFor(k, longest) {
|
|
188
|
+
if (longest === undefined) {
|
|
189
|
+
// take a guess
|
|
190
|
+
longest = 16;
|
|
191
|
+
}
|
|
192
|
+
const result = [];
|
|
193
|
+
result.push(chalk.yellow(`${padRight(k, longest)}`));
|
|
194
|
+
const target = registeredEnvironmentVariables[k];
|
|
195
|
+
if (target.help) {
|
|
196
|
+
result.push(indent(chalk.gray(target.help)));
|
|
197
|
+
}
|
|
198
|
+
if (target.default) {
|
|
199
|
+
result.push(indent(`${defaultPre}: ${target.default}`, 2));
|
|
200
|
+
}
|
|
201
|
+
if (target.tasks && target.tasks.length) {
|
|
202
|
+
result.push(
|
|
203
|
+
indent(
|
|
204
|
+
`${tasksPre}: ${target.tasks
|
|
205
|
+
.map(t => t.trim())
|
|
206
|
+
.filter(t => t)
|
|
207
|
+
.sort()
|
|
208
|
+
.join(", ")}`,
|
|
209
|
+
2
|
|
210
|
+
)
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
if (target.overriddenBy !== undefined) {
|
|
214
|
+
const overrides = Array.isArray(target.overriddenBy)
|
|
215
|
+
? target.overriddenBy.join(",")
|
|
216
|
+
: target.overriddenBy;
|
|
217
|
+
if (overrides.trim()) {
|
|
218
|
+
result.push(indent(chalk.magenta(`overridden by: ${overrides}`)));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function listVars() {
|
|
225
|
+
return Object.keys(registeredEnvironmentVariables).sort();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function taskHelp(task) {
|
|
229
|
+
const keys = listVars(),
|
|
230
|
+
matchingRequest = keys.filter(cur => {
|
|
231
|
+
return registeredEnvironmentVariables[cur].tasks.indexOf(task) > -1;
|
|
232
|
+
});
|
|
233
|
+
printHelpFor(matchingRequest);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function resolve() {
|
|
237
|
+
const names = Array.from(arguments).flatMap(a => a);
|
|
238
|
+
const result = resolveInternal(names);
|
|
239
|
+
logResolved(names, result);
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function resolveFirst(names, ignoreDefault) {
|
|
244
|
+
return names
|
|
245
|
+
.reduce((acc, cur) =>
|
|
246
|
+
acc === undefined
|
|
247
|
+
? resolveInternal(cur, ignoreDefault)
|
|
248
|
+
: acc, undefined);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function resolveInternal(name, ignoreDefault) {
|
|
252
|
+
if (Array.isArray(name)) {
|
|
253
|
+
// attempt to resolve the first defined variable
|
|
254
|
+
const firstDefined = resolveFirst(name, true);
|
|
255
|
+
// if that doesn't work, get the first default value
|
|
256
|
+
return firstDefined === undefined
|
|
257
|
+
? resolveFirst(name, false)
|
|
258
|
+
: firstDefined;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const target = registeredEnvironmentVariables[name] || {},
|
|
262
|
+
configuredOverrides = target.overriddenBy,
|
|
263
|
+
overrides = configuredOverrides
|
|
264
|
+
? Array.isArray(configuredOverrides)
|
|
265
|
+
? configuredOverrides
|
|
266
|
+
: [ configuredOverrides ]
|
|
267
|
+
: [],
|
|
268
|
+
overrideValues = overrides
|
|
269
|
+
.map(s => process.env[s])
|
|
270
|
+
.filter(s => s !== undefined),
|
|
271
|
+
initialValue =
|
|
272
|
+
(!ignoreDefault && process.env[name] === undefined) ? target.default : process.env[name];
|
|
273
|
+
if (overrideValues.length === 0) {
|
|
274
|
+
return initialValue;
|
|
275
|
+
}
|
|
276
|
+
if (target.when === undefined) {
|
|
277
|
+
if (overrideValues.length > 0) {
|
|
278
|
+
console.warn(
|
|
279
|
+
`multiple override values found for '${name}' and no strategy for discriminating set; selecting the first`
|
|
280
|
+
);
|
|
281
|
+
debug({
|
|
282
|
+
when: target.when,
|
|
283
|
+
overrides,
|
|
284
|
+
overrideValues,
|
|
285
|
+
initialValue
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return overrideValues[0];
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const result = overrideValues.reduce((acc, cur) => {
|
|
292
|
+
debug({
|
|
293
|
+
label: "invoke override discriminator",
|
|
294
|
+
when: target.when,
|
|
295
|
+
acc,
|
|
296
|
+
cur
|
|
297
|
+
});
|
|
298
|
+
return target.when(acc, cur) ? cur : acc;
|
|
299
|
+
}, initialValue);
|
|
300
|
+
|
|
301
|
+
debug({
|
|
302
|
+
when: target.when,
|
|
303
|
+
overrides,
|
|
304
|
+
overrideValues,
|
|
305
|
+
initialValue,
|
|
306
|
+
envVar: name,
|
|
307
|
+
envValue: process.env[name],
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
return result;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function logResolved(name, value) {
|
|
314
|
+
debug(`resolved: ${name} => ${quoteString(value)}`);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function quoteString(val) {
|
|
318
|
+
return typeof val === "string" ? `"${val}"` : val;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function resolveArray(name, delimiter) {
|
|
322
|
+
const value = resolveInternal(name) || "",
|
|
323
|
+
valueArray = Array.isArray(value) ? value : explode(value, delimiter);
|
|
324
|
+
logResolved(name, valueArray);
|
|
325
|
+
return valueArray;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function resolveNumber(name) {
|
|
329
|
+
const value = resolveInternal(name),
|
|
330
|
+
asNumber = parseInt(value, 10);
|
|
331
|
+
if (isNaN(asNumber)) {
|
|
332
|
+
throw new ZarroError(`${value} is not a valid numeric value for ${name}`);
|
|
333
|
+
}
|
|
334
|
+
logResolved(name, asNumber);
|
|
335
|
+
return asNumber;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const positiveFlags = [ "yes", "true", "1" ];
|
|
339
|
+
const negativeFlags = [ "no", "false", "0" ];
|
|
340
|
+
|
|
341
|
+
function resolveFlag(name) {
|
|
342
|
+
const value = (resolveInternal(name) || "").toLowerCase();
|
|
343
|
+
if (positiveFlags.indexOf(value) > -1) {
|
|
344
|
+
logResolved(name, true);
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
if (negativeFlags.indexOf(value) > -1) {
|
|
348
|
+
logResolved(name, false);
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
throw new ZarroError(`environmental flag not set and no default: ${name}`);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function explode(str, delimiter) {
|
|
355
|
+
return str
|
|
356
|
+
.split(delimiter || ",")
|
|
357
|
+
.map(p => p.trim())
|
|
358
|
+
.filter(p => !!p);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const registerEnvironmentVariables = require("./register-environment-variables");
|
|
362
|
+
registerEnvironmentVariables(toExport);
|
|
363
|
+
|
|
364
|
+
module.exports = toExport;
|