heroku 11.8.1 → 11.9.0-beta.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/commands/addons/open.js +1 -1
  3. package/dist/commands/autocomplete/create.js +1 -1
  4. package/dist/commands/pg/copy.js +5 -3
  5. package/dist/commands/pipelines/promote.js +1 -0
  6. package/dist/hooks/init/configure-git-credential-manager.d.ts +3 -0
  7. package/dist/hooks/init/configure-git-credential-manager.js +38 -0
  8. package/dist/lib/config/quote.js +2 -2
  9. package/dist/lib/git/git.js +12 -6
  10. package/dist/lib/local/foreman/colors.cjs +41 -0
  11. package/dist/lib/local/foreman/colors.d.cts +2 -0
  12. package/dist/lib/local/foreman/console.cjs +103 -0
  13. package/dist/lib/local/foreman/console.d.cts +22 -0
  14. package/dist/lib/local/foreman/envs.cjs +103 -0
  15. package/dist/lib/local/foreman/envs.d.cts +4 -0
  16. package/dist/lib/local/foreman/forward.cjs +27 -0
  17. package/dist/lib/local/foreman/forward.d.cts +1 -0
  18. package/dist/lib/local/foreman/proc.cjs +115 -0
  19. package/dist/lib/local/foreman/proc.d.cts +3 -0
  20. package/dist/lib/local/foreman/procfile.cjs +46 -0
  21. package/dist/lib/local/foreman/procfile.d.cts +2 -0
  22. package/dist/lib/local/foreman/proxy.cjs +97 -0
  23. package/dist/lib/local/foreman/proxy.d.cts +1 -0
  24. package/dist/lib/local/foreman/requirements.cjs +47 -0
  25. package/dist/lib/local/foreman/requirements.d.cts +2 -0
  26. package/dist/lib/local/run-foreman.cjs +13 -130
  27. package/dist/lib/pg/backups.d.ts +1 -1
  28. package/dist/lib/pg/backups.js +1 -1
  29. package/dist/lib/pg/download.js +4 -1
  30. package/dist/lib/pipelines/setup/get-repo.js +4 -2
  31. package/oclif.manifest.json +1576 -1576
  32. package/package.json +3 -3
  33. package/npm-shrinkwrap.json +0 -22863
package/CHANGELOG.md CHANGED
@@ -4,6 +4,26 @@ All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
6
 
7
+ ## [11.9.0-beta.0](https://github.com/heroku/cli/compare/v11.8.1...v11.9.0-beta.0) (2026-08-04)
8
+
9
+
10
+ ### Features
11
+
12
+ * add credential manager configuration to the oclif init hook ([#3786](https://github.com/heroku/cli/issues/3786)) ([8f0bb4d](https://github.com/heroku/cli/commit/8f0bb4debe2296ad201efd5730697f93756c1ffd))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * autocomplete zsh setup guards compinit to prevent double-init ([#3839](https://github.com/heroku/cli/issues/3839)) ([b3d629c](https://github.com/heroku/cli/commit/b3d629c6f9ddd4ec23249a82b0e556fd7909ab7c)), closes [#1686](https://github.com/heroku/cli/issues/1686)
18
+ * config:get --shell does not double-escape backslashes in single-quoted output ([#3833](https://github.com/heroku/cli/issues/3833)) ([bbf0d22](https://github.com/heroku/cli/commit/bbf0d2262919d8dd58aea7c2ed94daa370c21399)), closes [#1384](https://github.com/heroku/cli/issues/1384)
19
+ * pg:backups:capture -v null guard on undefined logs ([#3832](https://github.com/heroku/cli/issues/3832)) ([3c8a567](https://github.com/heroku/cli/commit/3c8a5678d18cf47657c88a23c056075e47129ad3))
20
+ * pg:backups:download respects HTTPS_PROXY env var ([#3836](https://github.com/heroku/cli/issues/3836)) ([288f302](https://github.com/heroku/cli/commit/288f302eb6e93b8fe0f2c8c130815a845a216571)), closes [#1531](https://github.com/heroku/cli/issues/1531)
21
+ * pg:copy confirmation prompt shows addon name not app name ([#3834](https://github.com/heroku/cli/issues/3834)) ([44c5786](https://github.com/heroku/cli/commit/44c5786449e9764da70c6a122ce34ae08ed14293))
22
+ * pipelines:promote exits non-zero on partial failure ([#3835](https://github.com/heroku/cli/issues/3835)) ([30842f8](https://github.com/heroku/cli/commit/30842f8f42adc208cf87a341ca681a1a3b4a2a4c)), closes [#1600](https://github.com/heroku/cli/issues/1600)
23
+ * remove GitHub org/repo in error messages ([#3808](https://github.com/heroku/cli/issues/3808)) ([1419e2a](https://github.com/heroku/cli/commit/1419e2a20edf567776c69966d3cb60e1d92bf9f4))
24
+ * replace jQuery CDN dependency in addons:open SSO template with vanilla JS ([#3837](https://github.com/heroku/cli/issues/3837)) ([1df4b3d](https://github.com/heroku/cli/commit/1df4b3df198329a145521f676dc5a2ccc514196d)), closes [#1541](https://github.com/heroku/cli/issues/1541)
25
+ * vendor node-foreman and replace util._extend with Object.assign ([#3838](https://github.com/heroku/cli/issues/3838)) ([a0b3316](https://github.com/heroku/cli/commit/a0b33160eb8c3173d5e01474b75a2221773cc503)), closes [#3736](https://github.com/heroku/cli/issues/3736) [#3736](https://github.com/heroku/cli/issues/3736) [#3736](https://github.com/heroku/cli/issues/3736) [#3736](https://github.com/heroku/cli/issues/3736) [#3736](https://github.com/heroku/cli/issues/3736)
26
+
7
27
  ## [11.8.1](https://github.com/heroku/cli/compare/v11.8.0...v11.8.1) (2026-07-08)
8
28
 
9
29
 
@@ -71,7 +71,7 @@ export default class Open extends Command {
71
71
  }
72
72
  async writeSudoTemplate(app, addon, sso) {
73
73
  const ssoPath = path.join(os.tmpdir(), 'heroku-sso.html');
74
- const html = `<!DOCTYPE HTML>\n<html lang="en">\n <head>\n <meta charset="utf-8">\n <title>Heroku Add-ons SSO</title>\n <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>\n </head>\n\n <body>\n <h3>Opening ${addon}${app ? ` on ${app}` : ''}...</h3>\n <form method="POST" action="${sso.action}">\n </form>\n\n <script>\n var params = ${JSON.stringify(sso.params)}\n var form = document.forms[0]\n $(document).ready(function() {\n $.each(params, function(key, value) {\n $('<input>').attr({ type: 'hidden', name: key, value: value })\n .appendTo(form)\n })\n form.submit()\n })\n </script>\n </body>\n</html>`;
74
+ const html = `<!DOCTYPE HTML>\n<html lang="en">\n <head>\n <meta charset="utf-8">\n <title>Heroku Add-ons SSO</title>\n </head>\n\n <body>\n <h3>Opening ${addon}${app ? ` on ${app}` : ''}...</h3>\n <form method="POST" action="${sso.action}">\n </form>\n\n <script>\n document.addEventListener('DOMContentLoaded', function() {\n var params = ${JSON.stringify(sso.params)}\n var form = document.forms[0]\n Object.keys(params).forEach(function(key) {\n var input = document.createElement('input')\n input.type = 'hidden'\n input.name = key\n input.value = params[key]\n form.appendChild(input)\n })\n form.submit()\n })\n </script>\n </body>\n</html>`;
75
75
  await fs.writeFile(ssoPath, html);
76
76
  return ssoPath;
77
77
  }
@@ -134,7 +134,7 @@ ${AC_LIB_PATH}/zsh
134
134
  $fpath
135
135
  );
136
136
  autoload -Uz compinit;
137
- compinit;
137
+ (( \${+functions[compdef]} )) || compinit;
138
138
  `;
139
139
  }
140
140
  get zshSetupScriptPath() {
@@ -20,14 +20,16 @@ const getAttachmentInfo = async function (heroku, db, app) {
20
20
  const { body: addon } = await heroku.get(`/addons/${attachment.addon.name}`);
21
21
  const { body: config } = await heroku.get(`/apps/${attachment.app.name}/config-vars`);
22
22
  const formattedConfig = Object.fromEntries(Object.entries(config).map(([k, v]) => [k.toUpperCase(), v]));
23
+ const addonName = attachment.name
24
+ .replace(/^HEROKU_POSTGRESQL_/, '')
25
+ .replace(/_URL$/, '');
23
26
  return {
24
27
  attachment: {
25
28
  ...attachment,
26
29
  addon,
27
30
  },
28
- confirm: app,
29
- name: attachment.name.replace(/^HEROKU_POSTGRESQL_/, '')
30
- .replace(/_URL$/, ''),
31
+ confirm: addonName,
32
+ name: addonName,
31
33
  url: formattedConfig[attachment.name.toUpperCase() + '_URL'],
32
34
  };
33
35
  };
@@ -93,6 +93,7 @@ export default class Promote extends Command {
93
93
  }
94
94
  else {
95
95
  ux.warn('\nPromotion to some apps failed');
96
+ process.exitCode = 1;
96
97
  }
97
98
  hux.styledObject(styledTargets);
98
99
  }
@@ -0,0 +1,3 @@
1
+ import { Hook } from '@oclif/core/hooks';
2
+ declare const hook: Hook.Init;
3
+ export default hook;
@@ -0,0 +1,38 @@
1
+ import Git from '../../lib/git/git.js';
2
+ const hook = async function () {
3
+ // Skip for --version / --help / completion-style invocations to avoid a needless git subprocess.
4
+ // Version-style invocations include `--version` plus any `oclif.additionalVersionFlags`
5
+ // (e.g. `-v`, `version`) declared in package.json — mirror version.ts, which reads the
6
+ // same config. We hard-include `-v`/`version` as a defensive fallback so this skip can
7
+ // never silently regress if config is somehow unavailable at runtime.
8
+ // Help-style invocations are skipped for the same reason: they're fast informational
9
+ // commands that shouldn't touch git. They include `--help` plus any
10
+ // `oclif.additionalHelpFlags` (e.g. `-h`) declared in package.json, and we hard-include
11
+ // `--help`/`-h`/`help` as the same kind of defensive fallback.
12
+ // Completion invocations are matched by the `autocomplete` prefix, since shell completion
13
+ // actually runs `autocomplete:options` (not the bare `autocomplete` command).
14
+ // NOTE: temporary hook until v12.
15
+ const arg = process.argv[2];
16
+ const additionalVersionFlags = this.config?.pjson?.oclif?.additionalVersionFlags ?? [];
17
+ const additionalHelpFlags = this.config?.pjson?.oclif?.additionalHelpFlags ?? [];
18
+ const skip = new Set([
19
+ '--help',
20
+ '--version',
21
+ '-h',
22
+ '-v',
23
+ 'help',
24
+ 'version',
25
+ ...additionalHelpFlags,
26
+ ...additionalVersionFlags,
27
+ ]);
28
+ if (!arg || skip.has(arg) || arg.startsWith('autocomplete'))
29
+ return;
30
+ const git = new Git();
31
+ try {
32
+ await git.configureCredentialHelper();
33
+ }
34
+ catch {
35
+ // ignore — best-effort; never block a command on git config
36
+ }
37
+ };
38
+ export default hook;
@@ -9,7 +9,7 @@ export function quote(s) {
9
9
  .replaceAll(/(["\\$`!])/g, String.raw `\$1`)
10
10
  .replaceAll('\n', String.raw `\n`)
11
11
  + '"';
12
- return "'" + s.replaceAll(/(['\\])/g, String.raw `\$1`) + "'";
12
+ return "'" + s + "'";
13
13
  }
14
14
  return s;
15
15
  }
@@ -18,7 +18,7 @@ export function parse(a) {
18
18
  a = a.replaceAll(String.raw `\n`, '\n');
19
19
  }
20
20
  else if (a.startsWith("'")) {
21
- a = a.replaceAll('\\\\', '\\');
21
+ // single-quoted strings are literal in POSIX sh — no unescaping needed
22
22
  }
23
23
  const parsed = shell.parse(a);
24
24
  if (parsed.length > 1)
@@ -13,12 +13,18 @@ export default class Git {
13
13
  */
14
14
  async configureCredentialHelper() {
15
15
  const { httpGitHost } = vars;
16
- await this.exec([
17
- 'config',
18
- '--global',
19
- `credential.https://${httpGitHost}.helper`,
20
- '!heroku git:credentials',
21
- ]);
16
+ const key = `credential.https://${httpGitHost}.helper`;
17
+ const helper = '!heroku git:credentials';
18
+ // Read the existing value first so we can skip the write when it is already
19
+ // set to our helper. `git config` rewrites the global config file (new inode)
20
+ // even when the value is byte-identical, and this runs before nearly every
21
+ // command via the init hook, so the no-op write churns the user's gitconfig.
22
+ // When the key is absent the `--get` exits non-zero and `exec` throws, so we
23
+ // treat that as an empty string.
24
+ const existing = await this.exec(['config', '--global', '--get', key]).catch(() => '');
25
+ if (existing === helper)
26
+ return;
27
+ await this.exec(['config', '--global', key, helper]);
22
28
  }
23
29
  createRemote(remote, url) {
24
30
  return this.hasGitRemote(remote)
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ // Copyright IBM Corp. 2012,2016. All Rights Reserved.
3
+ // Node module: foreman
4
+ // This file is licensed under the MIT License.
5
+ // License text available at https://opensource.org/licenses/MIT
6
+ var reset = '\x1B[0m';
7
+ var colors = {
8
+ magenta: '\x1B[35m',
9
+ blue: '\x1B[34m',
10
+ cyan: '\x1B[36m',
11
+ green: '\x1B[32m',
12
+ yellow: '\x1B[33m',
13
+ red: '\x1B[31m',
14
+ bright_magenta: '\x1B[35m',
15
+ bright_cyan: '\x1B[36m',
16
+ bright_blue: '\x1B[34m',
17
+ bright_green: '\x1B[32m',
18
+ bright_yellow: '\x1B[33m',
19
+ bright_red: '\x1B[31m',
20
+ };
21
+ function identity(self) {
22
+ return self;
23
+ }
24
+ function colorizer(color) {
25
+ if (process.stdout.isTTY) {
26
+ return function (str) {
27
+ return colors[color] + str + reset;
28
+ };
29
+ }
30
+ else {
31
+ return identity;
32
+ }
33
+ }
34
+ module.exports.colors = [];
35
+ var colorKeys = Object.keys(colors);
36
+ colorKeys.forEach(function (name) {
37
+ var colorFn = colorizer(name);
38
+ module.exports[name] = colorFn;
39
+ module.exports.colors.push(colorFn);
40
+ });
41
+ module.exports.colors_max = module.exports.colors.length;
@@ -0,0 +1,2 @@
1
+ export const colors: any[];
2
+ export { length as colors_max };
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ // Copyright IBM Corp. 2012,2016. All Rights Reserved.
3
+ // Node module: foreman
4
+ // This file is licensed under the MIT License.
5
+ // License text available at https://opensource.org/licenses/MIT
6
+ var util = require('util');
7
+ var colors = require('./colors.cjs');
8
+ function wrap(log, length, res) {
9
+ if (!res) {
10
+ res = [];
11
+ }
12
+ if (log.length <= length) {
13
+ res.push(log);
14
+ return res;
15
+ }
16
+ else {
17
+ res.push(log.substr(0, length));
18
+ return wrap(log.substr(length), length, res);
19
+ }
20
+ }
21
+ var trimEnd = '\u2026';
22
+ var ansiEscapes = /\x1b\[(\d+([A-GJKSTm]|;\d+[Hf])|6n|s|u|\?25[lh])/g;
23
+ function stripANSI(str) {
24
+ return str.replace(ansiEscapes, '');
25
+ }
26
+ function trim(line, n) {
27
+ line = line.replace(/\s+$/, '');
28
+ var stripped = stripANSI(line);
29
+ if (stripped.length <= n) {
30
+ return line;
31
+ }
32
+ else {
33
+ return stripped.substr(0, n) + trimEnd;
34
+ }
35
+ }
36
+ function Console(logger) {
37
+ logger = logger || console;
38
+ this.padding = 25;
39
+ this.trimline = 10;
40
+ this.wrapline = 500;
41
+ this.fmt = function fmt() {
42
+ return util.format.apply(null, arguments);
43
+ };
44
+ this.pad = function pad(string, n) {
45
+ var l = string.length;
46
+ var o = string;
47
+ for (var i = l; i < n; i++) {
48
+ o += " ";
49
+ }
50
+ return o;
51
+ };
52
+ this.trim = trim;
53
+ this.info = function info(key, proc, string) {
54
+ var stamp = (new Date().toLocaleTimeString()) + " " + key;
55
+ logger.log(proc.color(this.pad(stamp, this.padding)), colors.cyan(string));
56
+ };
57
+ this.error = function error(key, proc, string) {
58
+ var stamp = (new Date().toLocaleTimeString()) + " " + key;
59
+ logger.error(proc.color(this.pad(stamp, this.padding)), colors.red(string));
60
+ };
61
+ this.log = function log(key, proc, string) {
62
+ var self = this;
63
+ if (self.raw) {
64
+ logger.log(string);
65
+ return;
66
+ }
67
+ string.split(/\n/).forEach(function (line) {
68
+ if (line.trim().length === 0) {
69
+ return;
70
+ }
71
+ var stamp = (new Date().toLocaleTimeString()) + " " + key;
72
+ if (self.trimline > 0) {
73
+ line = self.trim(line, self.trimline);
74
+ }
75
+ var delimiter = " | ";
76
+ var wrapline;
77
+ if (self.wrapline === 0) {
78
+ wrapline = line.length;
79
+ }
80
+ else {
81
+ wrapline = self.wrapline;
82
+ }
83
+ wrap(line, wrapline).forEach(function (l) {
84
+ logger.log(proc.color(self.pad(stamp, self.padding) + delimiter), l);
85
+ delimiter = " | > ";
86
+ });
87
+ });
88
+ };
89
+ this.Alert = function Alert() {
90
+ logger.log(colors.green('[OKAY] ' + this.fmt.apply(null, arguments)));
91
+ };
92
+ this.Done = function Info() {
93
+ logger.log(colors.cyan('[DONE] ' + this.fmt.apply(null, arguments)));
94
+ };
95
+ this.Warn = function Warn() {
96
+ logger.warn(colors.yellow('[WARN] ' + this.fmt.apply(null, arguments)));
97
+ };
98
+ this.Error = function Error() {
99
+ logger.error(colors.bright_red('[FAIL] ' + this.fmt.apply(null, arguments)));
100
+ };
101
+ }
102
+ module.exports = Console;
103
+ Console.Console = new Console();
@@ -0,0 +1,22 @@
1
+ export = Console;
2
+ declare function Console(logger: any): void;
3
+ declare class Console {
4
+ constructor(logger: any);
5
+ padding: number;
6
+ trimline: number;
7
+ wrapline: number;
8
+ fmt: (...args: any[]) => string;
9
+ pad: (string: any, n: any) => any;
10
+ trim: typeof trim;
11
+ info: (key: any, proc: any, string: any) => void;
12
+ error: (key: any, proc: any, string: any) => void;
13
+ log: (key: any, proc: any, string: any) => void;
14
+ Alert: (...args: any[]) => void;
15
+ Done: (...args: any[]) => void;
16
+ Warn: (...args: any[]) => void;
17
+ Error: (...args: any[]) => void;
18
+ }
19
+ declare namespace Console {
20
+ let Console: Console;
21
+ }
22
+ declare function trim(line: any, n: any): any;
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ // Copyright IBM Corp. 2012,2016. All Rights Reserved.
3
+ // Node module: foreman
4
+ // This file is licensed under the MIT License.
5
+ // License text available at https://opensource.org/licenses/MIT
6
+ var fs = require('fs');
7
+ var cons = require('./console.cjs').Console;
8
+ function method(name) {
9
+ return function (o) {
10
+ return o[name].apply(o);
11
+ };
12
+ }
13
+ // Parse a Key=Value File Containing Environmental Variables
14
+ function keyValue(data) {
15
+ var env = {};
16
+ data
17
+ .toString()
18
+ .replace(/^\s*\#.*$/gm, '')
19
+ .replace(/^\s*$/gm, '')
20
+ .split(/\n/)
21
+ .map(method('trim'))
22
+ .filter(notBlank)
23
+ .forEach(capturePair);
24
+ return env;
25
+ function notBlank(str) {
26
+ return str.length > 2;
27
+ }
28
+ function capturePair(line) {
29
+ var pair = line.split('=');
30
+ var key = pair[0].trim();
31
+ var rawVal = pair.slice(1).join('=').trim();
32
+ env[key] = parseValue(rawVal);
33
+ }
34
+ function parseValue(val) {
35
+ switch (val[0]) {
36
+ case '"': return /^"([^"]*)"/.exec(val)[1];
37
+ case "'": return /^'([^']*)'/.exec(val)[1];
38
+ default: return val.replace(/\s*\#.*$/, '');
39
+ }
40
+ }
41
+ }
42
+ // Flatten nested object structure into KEY_SUBKEY=value pairs
43
+ function flattenJSON(json) {
44
+ var flattened = {};
45
+ walk(json, function (path, item) {
46
+ flattened[path.join('_').toUpperCase()] = item;
47
+ });
48
+ return flattened;
49
+ function walk(obj, visitor, path) {
50
+ var item;
51
+ path = path || [];
52
+ for (var key in obj) {
53
+ item = obj[key];
54
+ if (typeof item === 'object') {
55
+ walk(item, visitor, path.concat(key));
56
+ }
57
+ else {
58
+ visitor(path.concat(key), item);
59
+ }
60
+ }
61
+ }
62
+ }
63
+ function dumpEnv(conf) {
64
+ var output = [];
65
+ for (var key in conf) {
66
+ output.push(key + '=' + conf[key]);
67
+ }
68
+ return output.sort().join('\n') + '\n';
69
+ }
70
+ function loadEnvsFile(path) {
71
+ var env, data;
72
+ if (!fs.existsSync(path)) {
73
+ env = {};
74
+ }
75
+ else {
76
+ data = fs.readFileSync(path);
77
+ try {
78
+ var envs_json = JSON.parse(data);
79
+ env = flattenJSON(envs_json, "", {});
80
+ cons.Alert("Loaded ENV %s File as JSON Format", path);
81
+ }
82
+ catch (e) {
83
+ env = keyValue(data);
84
+ cons.Alert("Loaded ENV %s File as KEY=VALUE Format", path);
85
+ }
86
+ }
87
+ env.PATH = env.PATH || process.env.PATH;
88
+ return env;
89
+ }
90
+ function loadEnvs(path) {
91
+ var envs = path.split(',').map(loadEnvsFile).reduce(function (acc, obj) {
92
+ return Object.assign(acc, obj);
93
+ }, {});
94
+ var sorted = Object.create(null);
95
+ Object.keys(envs).sort().forEach(function (k) {
96
+ sorted[k] = envs[k];
97
+ });
98
+ return sorted;
99
+ }
100
+ module.exports.loadEnvs = loadEnvs;
101
+ module.exports.flattenJSON = flattenJSON;
102
+ module.exports.keyValue = keyValue;
103
+ module.exports.dumpEnv = dumpEnv;
@@ -0,0 +1,4 @@
1
+ export function loadEnvs(path: any): any;
2
+ export function flattenJSON(json: any): {};
3
+ export function keyValue(data: any): {};
4
+ export function dumpEnv(conf: any): string;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ // Copyright IBM Corp. 2012,2016. All Rights Reserved.
3
+ // Node module: foreman
4
+ // This file is licensed under the MIT License.
5
+ // License text available at https://opensource.org/licenses/MIT
6
+ var prog = require('child_process');
7
+ var cons = require('./console.cjs').Console;
8
+ function startForward(port, hostname, emitter) {
9
+ var proc = prog.fork(__dirname + '/../forward.js', [], {
10
+ env: {
11
+ PROXY_PORT: port,
12
+ PROXY_HOST: hostname || ' '
13
+ }
14
+ });
15
+ cons.Alert('Forward Proxy Started in Port %d', port);
16
+ if (hostname) {
17
+ cons.Alert('Intercepting requests to %s through forward proxy', hostname);
18
+ }
19
+ else {
20
+ cons.Alert('Intercepting ALL requests through forward proxy');
21
+ }
22
+ emitter.once('killall', function (signal) {
23
+ cons.Done('Killing Forward Proxy Server on Port %d', port);
24
+ proc.kill(signal);
25
+ });
26
+ }
27
+ module.exports.startForward = startForward;
@@ -0,0 +1 @@
1
+ export function startForward(port: any, hostname: any, emitter: any): void;
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ // Copyright IBM Corp. 2012,2016. All Rights Reserved.
3
+ // Node module: foreman
4
+ // This file is licensed under the MIT License.
5
+ // License text available at https://opensource.org/licenses/MIT
6
+ var prog = require('child_process');
7
+ var cons = require('./console.cjs').Console;
8
+ var _colors = require('./colors.cjs');
9
+ var colors_max = _colors.colors_max;
10
+ var colors = _colors.colors;
11
+ var os = require('os');
12
+ var platform = os.platform();
13
+ function run(key, proc, emitter) {
14
+ var file, args;
15
+ if (platform === 'win32') {
16
+ file = process.env.comspec || 'cmd.exe';
17
+ args = ['/s', '/c', proc.command];
18
+ }
19
+ else {
20
+ file = '/bin/sh';
21
+ args = ['-c', proc.command];
22
+ }
23
+ var child = prog.spawn(file, args, { env: proc.env });
24
+ var killallReceived = false;
25
+ child.stdout.on('data', function (data) {
26
+ cons.log(key, proc, data.toString());
27
+ });
28
+ child.stderr.on('data', function (data) {
29
+ cons.log(key, proc, data.toString());
30
+ });
31
+ child.on('close', function (code, signal) {
32
+ if (code === 0) {
33
+ cons.info(key, proc, "Exited Successfully");
34
+ }
35
+ else {
36
+ cons.error(key, proc, "Exited with exit code " + signal || code);
37
+ }
38
+ });
39
+ child.on('exit', function (code, signal) {
40
+ if (!killallReceived) {
41
+ emitter.emit('killall', signal || 'SIGINT');
42
+ }
43
+ });
44
+ emitter.on('killall', function (signal) {
45
+ killallReceived = true;
46
+ try {
47
+ child.kill(signal);
48
+ }
49
+ catch (err) {
50
+ if (err.code === 'EPERM') {
51
+ cons.error(key, proc, "Process has become unkillable; returns EPERM.");
52
+ }
53
+ }
54
+ });
55
+ }
56
+ function once(input, envs, callback) {
57
+ var file, args;
58
+ var proc = {
59
+ command: input,
60
+ env: merge(merge({}, process.env), envs)
61
+ };
62
+ if (platform === 'win32') {
63
+ file = process.env.comspec || 'cmd.exe';
64
+ args = ['/s', '/c', proc.command];
65
+ }
66
+ else {
67
+ file = '/bin/sh';
68
+ args = ['-c', proc.command];
69
+ }
70
+ var child = prog.spawn(file, args, { env: proc.env, stdio: 'inherit' });
71
+ child.on('close', function (code) {
72
+ callback(code);
73
+ });
74
+ }
75
+ function start(procs, requirements, envs, portarg, emitter) {
76
+ var j = 0;
77
+ var k = 0;
78
+ var port = parseInt(portarg);
79
+ if (port < 1024) {
80
+ return cons.Error('Only Proxies Can Bind to Privileged Ports - ' +
81
+ 'Try \'sudo nf start -x %s\'', port);
82
+ }
83
+ for (var key in requirements) {
84
+ var n = parseInt(requirements[key]);
85
+ for (var i = 0; i < n; i++) {
86
+ var color_val = (j + k) % colors_max;
87
+ if (!procs[key]) {
88
+ cons.Warn("Required Key '%s' Does Not Exist in Procfile Definition", key);
89
+ continue;
90
+ }
91
+ var p = {
92
+ command: procs[key],
93
+ color: colors[color_val],
94
+ env: merge(merge({}, process.env), envs)
95
+ };
96
+ p.env.PORT = port + j + k * 100;
97
+ p.env.FOREMAN_WORKER_NAME = p.env.FOREMAN_WORKER_NAME || key + "." + (i + 1);
98
+ run(key + "." + (i + 1), p, emitter);
99
+ j++;
100
+ }
101
+ j = 0;
102
+ k++;
103
+ }
104
+ }
105
+ function merge(a, b) {
106
+ if (a && b) {
107
+ for (var key in b) {
108
+ a[key] = b[key];
109
+ }
110
+ }
111
+ return a;
112
+ }
113
+ module.exports.start = start;
114
+ module.exports.run = run;
115
+ module.exports.once = once;
@@ -0,0 +1,3 @@
1
+ export function start(procs: any, requirements: any, envs: any, portarg: any, emitter: any): void;
2
+ export function run(key: any, proc: any, emitter: any): void;
3
+ export function once(input: any, envs: any, callback: any): void;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ // Copyright IBM Corp. 2012,2016. All Rights Reserved.
3
+ // Node module: foreman
4
+ // This file is licensed under the MIT License.
5
+ // License text available at https://opensource.org/licenses/MIT
6
+ var fs = require('fs');
7
+ var cons = require('./console.cjs').Console;
8
+ var path = require('path');
9
+ function procs(procdata) {
10
+ var processes = {};
11
+ procdata.toString().split(/\n/).forEach(function (line) {
12
+ if (!line || line[0] === '#') {
13
+ return;
14
+ }
15
+ var tuple = /^([A-Za-z0-9_-]+):\s*(.+)$/m.exec(line);
16
+ var prockey = tuple[1].trim();
17
+ var command = tuple[2].trim();
18
+ if (!prockey) {
19
+ throw new Error('Syntax Error in Procfile, Line %d: No Prockey Found');
20
+ }
21
+ if (!command) {
22
+ throw new Error('Syntax Error in Procfile, Line %d: No Command Found');
23
+ }
24
+ processes[prockey] = command;
25
+ });
26
+ return processes;
27
+ }
28
+ function loadProc(filename) {
29
+ try {
30
+ var data = fs.readFileSync(filename);
31
+ return procs(data);
32
+ }
33
+ catch (e) {
34
+ cons.Warn(e.message);
35
+ if (fs.existsSync('package.json')) {
36
+ cons.Alert("package.json file found - trying 'npm start'");
37
+ return procs("web: npm start");
38
+ }
39
+ else {
40
+ cons.Error("No Procfile and no package.json file found in Current Directory - See " + path.basename(process.argv[1]) + " --help");
41
+ return;
42
+ }
43
+ }
44
+ }
45
+ module.exports.loadProc = loadProc;
46
+ module.exports.procs = procs;
@@ -0,0 +1,2 @@
1
+ export function loadProc(filename: any): {} | undefined;
2
+ export function procs(procdata: any): {};