navy 7.0.0-alpha.1 → 7.0.0-alpha.2

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.
@@ -27,6 +27,7 @@ describe('cli/program', function () {
27
27
  actionsByCommand = {};
28
28
  helpHandlersByCommand = {};
29
29
  fakeProgram = {
30
+ option: sandbox.stub().returnsThis(),
30
31
  command(spec) {
31
32
  const name = spec.split(' ')[0];
32
33
  const cmd = {
@@ -150,6 +151,10 @@ describe('cli/program', function () {
150
151
  });
151
152
  (0, _chai.expect)(consoleLogStub.called).to.equal(true);
152
153
  });
154
+ it('should register a global -e, --navy option on the root program', function () {
155
+ loadModule();
156
+ (0, _chai.expect)(fakeProgram.option.calledWith('-e, --navy [env]', _sinon.default.match.string, 'dev')).to.equal(true);
157
+ });
153
158
  });
154
159
  describe('lazyRequire wrapped action', function () {
155
160
  it('should pass through arguments to the underlying module', async function () {
@@ -332,6 +337,18 @@ describe('cli/program', function () {
332
337
  (0, _chai.expect)(navyStub.start.firstCall.args[0]).to.eql(['web', 'api']);
333
338
  (0, _chai.expect)(navyStub.ensurePluginsLoaded.calledOnce).to.equal(true);
334
339
  });
340
+ it('should merge optsWithGlobals so global navy is used when Commander passes the command', async function () {
341
+ navyStub.start = sandbox.stub().resolves();
342
+ const fakeCommand = {
343
+ optsWithGlobals: () => ({
344
+ navy: 'from-global'
345
+ })
346
+ };
347
+ await actionsByCommand.start(['web'], {
348
+ navy: 'subcommand-default'
349
+ }, fakeCommand);
350
+ (0, _chai.expect)(getNavyStub.firstCall.args[0]).to.equal('from-global');
351
+ });
335
352
  it('should pass undefined when called with an empty service list', async function () {
336
353
  navyStub.start = sandbox.stub().resolves();
337
354
  await actionsByCommand.start([], {
@@ -436,6 +453,7 @@ describe('cli/program', function () {
436
453
  function createCapturingProgram() {
437
454
  capturedActions = {};
438
455
  return {
456
+ option: sandbox.stub().returnsThis(),
439
457
  command(spec) {
440
458
  const name = spec.split(' ')[0];
441
459
  const cmd = {
@@ -11,6 +11,7 @@ var _errors = require("../errors");
11
11
  var _config = require("../config");
12
12
  var _driverLogging = require("../driver-logging");
13
13
  var _configProvider = require("../config-provider");
14
+ var _mergeActionOptions = require("./util/merge-action-options");
14
15
  const loadingLabelMap = {
15
16
  destroy: 'Destroying services...',
16
17
  start: 'Starting services...',
@@ -28,6 +29,23 @@ const loadingLabelMap = {
28
29
  function removeFirstLineFromStackTrace(stack) {
29
30
  return stack?.split('\n')?.slice(1)?.join('\n');
30
31
  }
32
+ function normaliseLazyRequireArgs(args) {
33
+ if (args.length === 0) return args;
34
+ const last = args[args.length - 1];
35
+ if (!last || typeof last.optsWithGlobals !== 'function') {
36
+ return args;
37
+ }
38
+ const command = last;
39
+ const rest = args.slice(0, -1);
40
+ if (rest.length === 0) {
41
+ return rest;
42
+ }
43
+ const lastOpt = rest[rest.length - 1];
44
+ if (lastOpt && typeof lastOpt === 'object' && !Array.isArray(lastOpt)) {
45
+ return [...rest.slice(0, -1), (0, _mergeActionOptions.mergeActionOptions)(lastOpt, command)];
46
+ }
47
+ return rest;
48
+ }
31
49
  function wrapper(res) {
32
50
  if (res.catch) {
33
51
  res.catch(ex => {
@@ -62,11 +80,21 @@ function basicCliWrapper(fnName, wrapperOpts = {}) {
62
80
  } = require('../navy');
63
81
 
64
82
  // commander v12 invokes action handlers with a trailing Command instance
65
- // appended after the parsed options. Strip it so the rest of this wrapper
66
- // can continue to treat the last remaining `args` element as the options.
67
- if (args.length > 0) args = args.slice(0, -1);
68
- const opts = args.length === 0 ? maybeServices : args[args.length - 1];
83
+ // appended after the parsed options. Strip it and merge global options
84
+ // (e.g. `navy -e dev start`) into the opts object.
85
+ let command = null;
86
+ if (args.length > 0) {
87
+ const last = args[args.length - 1];
88
+ if (last && typeof last.optsWithGlobals === 'function') {
89
+ command = last;
90
+ args = args.slice(0, -1);
91
+ }
92
+ }
93
+ let opts = args.length === 0 ? maybeServices : args[args.length - 1];
69
94
  const otherArgs = args.slice(0, args.length - 1);
95
+ if (command && opts && typeof opts === 'object' && !Array.isArray(opts)) {
96
+ opts = (0, _mergeActionOptions.mergeActionOptions)(opts, command);
97
+ }
70
98
  const envName = opts.navy;
71
99
  if (wrapperOpts.serviceBasedAlias && maybeServices.length) {
72
100
  console.log(`This command should not be called with a list of services. calling '${wrapperOpts.serviceBasedAlias}' instead`);
@@ -102,10 +130,12 @@ function basicCliWrapper(fnName, wrapperOpts = {}) {
102
130
  function lazyRequire(path) {
103
131
  return function (...args) {
104
132
  const mod = require(path);
105
- return wrapper((mod.default || mod)(...args));
133
+ const normalised = normaliseLazyRequireArgs(args);
134
+ return wrapper((mod.default || mod)(...normalised));
106
135
  };
107
136
  }
108
137
  const defaultNavy = process.env.NAVY_NAME || (0, _config.getConfig)().defaultNavy;
138
+ _commander.program.option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy);
109
139
  const importCommand = _commander.program.command('import').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Imports docker compose configuration from the current working directory and initialises a new navy').action(lazyRequire('./import'));
110
140
  (0, _configProvider.getImportCommandLineOptions)().forEach(opt => importCommand.option(...opt));
111
141
  _commander.program.command('launch [services...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Launches the given services in a navy').action(lazyRequire('./launch')).on('--help', () => console.log(`
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _chai = require("chai");
5
+ var _sinon = _interopRequireDefault(require("sinon"));
6
+ var _mergeActionOptions = require("../merge-action-options");
7
+ /* eslint-env mocha */
8
+
9
+ describe('cli/util/merge-action-options', function () {
10
+ it('should return parsed opts when command is missing', function () {
11
+ const opts = {
12
+ navy: 'dev'
13
+ };
14
+ (0, _chai.expect)((0, _mergeActionOptions.mergeActionOptions)(opts, null)).to.equal(opts);
15
+ });
16
+ it('should return parsed opts when optsWithGlobals is missing', function () {
17
+ const opts = {
18
+ navy: 'dev'
19
+ };
20
+ (0, _chai.expect)((0, _mergeActionOptions.mergeActionOptions)(opts, {})).to.equal(opts);
21
+ });
22
+ it('should merge optsWithGlobals so global navy wins over subcommand defaults', function () {
23
+ const command = {
24
+ optsWithGlobals: () => ({
25
+ navy: 'dev',
26
+ json: true
27
+ })
28
+ };
29
+ const merged = (0, _mergeActionOptions.mergeActionOptions)({
30
+ navy: 'default',
31
+ json: false
32
+ }, command);
33
+ (0, _chai.expect)(merged.navy).to.equal('dev');
34
+ (0, _chai.expect)(merged.json).to.equal(true);
35
+ });
36
+ it('should call optsWithGlobals on the command', function () {
37
+ const spy = _sinon.default.stub().returns({
38
+ navy: 'x'
39
+ });
40
+ (0, _mergeActionOptions.mergeActionOptions)({
41
+ navy: 'y'
42
+ }, {
43
+ optsWithGlobals: spy
44
+ });
45
+ (0, _chai.expect)(spy.calledOnce).to.equal(true);
46
+ });
47
+ });
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.mergeActionOptions = mergeActionOptions;
7
+ /**
8
+ * Merge Commander's per-command opts with inherited globals (e.g. `navy -e dev ps`).
9
+ * `optsWithGlobals()` is the combined view; spread it after local opts so globals
10
+ * override stale option defaults on the subcommand.
11
+ */
12
+ function mergeActionOptions(parsedOpts, command) {
13
+ if (!command || typeof command.optsWithGlobals !== 'function') {
14
+ return parsedOpts;
15
+ }
16
+ return {
17
+ ...parsedOpts,
18
+ ...command.optsWithGlobals()
19
+ };
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "navy",
3
- "version": "7.0.0-alpha.1",
3
+ "version": "7.0.0-alpha.2",
4
4
  "description": "Quick and powerful development environments using Docker and Docker Compose",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -49,6 +49,5 @@
49
49
  "resolve": "^1.20.0",
50
50
  "strip-ansi": "^6.0.1",
51
51
  "www-authenticate": "^0.6.3"
52
- },
53
- "gitHead": "c977d36ee1e962134aee34d5fa20071cd863a619"
52
+ }
54
53
  }