From 883a1218672e6dc51d03e2f48f6ee1b32e1c11d4 Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Thu, 4 Mar 2021 15:23:31 +0100 Subject: [PATCH] feat(cli-repl): improve argument handling MONGOSH-571 --- packages/cli-repl/src/arg-parser.spec.ts | 1198 ++++++----------- packages/cli-repl/src/arg-parser.ts | 75 +- packages/cli-repl/src/index.ts | 6 +- .../service-provider-core/src/cli-options.ts | 1 + 4 files changed, 460 insertions(+), 820 deletions(-) diff --git a/packages/cli-repl/src/arg-parser.spec.ts b/packages/cli-repl/src/arg-parser.spec.ts index a9864060f3..bb04cf301b 100644 --- a/packages/cli-repl/src/arg-parser.spec.ts +++ b/packages/cli-repl/src/arg-parser.spec.ts @@ -1,6 +1,7 @@ -import parse, { getLocale } from './arg-parser'; +import { MongoshUnimplementedError } from '@mongosh/errors'; import { expect } from 'chai'; import stripAnsi from 'strip-ansi'; +import { getLocale, parseCliArgs } from './arg-parser'; const NODE = 'node'; const MONGOSH = 'mongosh'; @@ -74,936 +75,484 @@ describe('arg-parser', () => { }); describe('.parse', () => { - context('when running from a linked bin script or executable', () => { - const baseArgv = [ NODE, MONGOSH ]; - - context('when providing only a URI', () => { - const uri = 'mongodb://domain.com:20000'; - const argv = [ ...baseArgv, uri]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - }); - - context('when providing a URI + options', () => { - const uri = 'mongodb://domain.com:20000'; - - context('when providing general options', () => { - context('when providing --ipv6', () => { - const argv = [ ...baseArgv, uri, '--ipv6' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the ipv6 value in the object', () => { - expect(parse(argv).ipv6).to.equal(true); - }); - }); - - context('when providing -h', () => { - const argv = [ ...baseArgv, uri, '-h' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the help value in the object', () => { - expect(parse(argv).help).to.equal(true); - }); - }); - - context('when providing --help', () => { - const argv = [ ...baseArgv, uri, '--help' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the help value in the object', () => { - expect(parse(argv).help).to.equal(true); - }); - }); - - context('when providing --version', () => { - const argv = [ ...baseArgv, uri, '--version' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the version value in the object', () => { - expect(parse(argv).version).to.equal(true); - }); - }); - - context('when providing --verbose', () => { - const argv = [ ...baseArgv, uri, '--verbose' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the verbose value in the object', () => { - expect(parse(argv).verbose).to.equal(true); - }); - }); - - context('when providing --shell', () => { - const argv = [ ...baseArgv, uri, '--shell' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the shell value in the object', () => { - expect(parse(argv).shell).to.equal(true); - }); - }); - - context('when providing --nodb', () => { - const argv = [ ...baseArgv, uri, '--nodb' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the nodb value in the object', () => { - expect(parse(argv).nodb).to.equal(true); - }); - }); - - context('when providing --norc', () => { - const argv = [ ...baseArgv, uri, '--norc' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the norc value in the object', () => { - expect(parse(argv).norc).to.equal(true); - }); - }); - - context('when providing --quiet', () => { - const argv = [ ...baseArgv, uri, '--quiet' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the quiet value in the object', () => { - expect(parse(argv).quiet).to.equal(true); - }); - }); - - context('when providing --eval', () => { - const argv = [ ...baseArgv, uri, '--eval', '1+1' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the eval value in the object', () => { - expect(parse(argv).eval).to.equal('1+1'); - }); - }); - - context('when providing --retryWrites', () => { - const argv = [ ...baseArgv, uri, '--retryWrites' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the retryWrites value in the object', () => { - expect(parse(argv).retryWrites).to.equal(true); - }); - }); - - context('when providing an unknown parameter', () => { - const argv = [ ...baseArgv, uri, '--what' ]; - - it('raises an error', () => { - try { - parse(argv); - } catch (err) { - return expect( - stripAnsi(err.message) - ).to.contain('Error parsing command line: unrecognized option: --what'); - } - expect.fail('parsing unknown parameter did not throw'); - }); + [ + { contextDescription: 'when running from a linked bin script or executable', baseArgv: [NODE, MONGOSH] }, + { contextDescription: 'when running via npm start', baseArgv: [ NODE, MONGOSH, START ] }, + ].forEach(({ contextDescription, baseArgv }) => { + context(contextDescription, () => { + context('when providing only a URI', () => { + const uri = 'mongodb://domain.com:20000'; + const argv = [ ...baseArgv, uri]; + + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); }); }); - context('when providing authentication options', () => { - context('when providing -u', () => { - const argv = [ ...baseArgv, uri, '-u', 'richard' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the username in the object', () => { - expect(parse(argv).username).to.equal('richard'); - }); - }); - - context('when providing --username', () => { - const argv = [ ...baseArgv, uri, '--username', 'richard' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the username in the object', () => { - expect(parse(argv).username).to.equal('richard'); - }); - }); - - context('when providing -p', () => { - const argv = [ ...baseArgv, uri, '-p', 'pw' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the password in the object', () => { - expect(parse(argv).password).to.equal('pw'); - }); - }); - - context('when providing --password', () => { - const argv = [ ...baseArgv, uri, '--password', 'pw' ]; + context('when providing a URI + options', () => { + const uri = 'mongodb://domain.com:20000'; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + context('when providing general options', () => { + context('when providing --ipv6', () => { + const argv = [ ...baseArgv, uri, '--ipv6' ]; - it('sets the password in the object', () => { - expect(parse(argv).password).to.equal('pw'); - }); - }); - - context('when providing --authenticationDatabase', () => { - const argv = [ ...baseArgv, uri, '--authenticationDatabase', 'db' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the authenticationDatabase in the object', () => { - expect(parse(argv).authenticationDatabase).to.equal('db'); - }); - }); - - context('when providing --authenticationMechanism', () => { - const argv = [ ...baseArgv, uri, '--authenticationMechanism', 'SCRAM-SHA-256' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the authenticationMechanism in the object', () => { - expect(parse(argv).authenticationMechanism).to.equal('SCRAM-SHA-256'); - }); - }); - - context('when providing --gssapiServiceName', () => { - const argv = [ ...baseArgv, uri, '--gssapiServiceName', 'mongosh' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the gssapiServiceName in the object', () => { - expect(parse(argv).gssapiServiceName).to.equal('mongosh'); - }); - }); - - context('when providing --gssapiHostName', () => { - const argv = [ ...baseArgv, uri, '--gssapiHostName', 'example.com' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the gssapiHostName in the object', () => { - expect(parse(argv).gssapiHostName).to.equal('example.com'); - }); - }); - }); - - context('when providing TLS options', () => { - context('when providing --tls', () => { - const argv = [ ...baseArgv, uri, '--tls' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the tls in the object', () => { - expect(parse(argv).tls).to.equal(true); - }); - }); - - context('when providing --tlsCertificateKeyFile', () => { - const argv = [ ...baseArgv, uri, '--tlsCertificateKeyFile', 'test' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the tlsCertificateKeyFile in the object', () => { - expect(parse(argv).tlsCertificateKeyFile).to.equal('test'); - }); - }); - - context('when providing --tlsCertificateKeyFilePassword', () => { - const argv = [ ...baseArgv, uri, '--tlsCertificateKeyFilePassword', 'test' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the tlsCertificateKeyFilePassword in the object', () => { - expect(parse(argv).tlsCertificateKeyFilePassword).to.equal('test'); - }); - }); - - context('when providing --tlsCAFile', () => { - const argv = [ ...baseArgv, uri, '--tlsCAFile', 'test' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the tlsCAFile in the object', () => { - expect(parse(argv).tlsCAFile).to.equal('test'); - }); - }); - - context('when providing --tlsCRLFile', () => { - const argv = [ ...baseArgv, uri, '--tlsCRLFile', 'test' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the tlsCRLFile in the object', () => { - expect(parse(argv).tlsCRLFile).to.equal('test'); - }); - }); - - context('when providing --tlsAllowInvalidHostnames', () => { - const argv = [ ...baseArgv, uri, '--tlsAllowInvalidHostnames' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the tlsAllowInvalidHostnames in the object', () => { - expect(parse(argv).tlsAllowInvalidHostnames).to.equal(true); - }); - }); - - context('when providing --tlsAllowInvalidCertificates', () => { - const argv = [ ...baseArgv, uri, '--tlsAllowInvalidCertificates' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the tlsAllowInvalidCertificates in the object', () => { - expect(parse(argv).tlsAllowInvalidCertificates).to.equal(true); - }); - }); - - context('when providing --tlsFIPSMode', () => { - const argv = [ ...baseArgv, uri, '--tlsFIPSMode' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the tlsFIPSMode in the object', () => { - expect(parse(argv).tlsFIPSMode).to.equal(true); - }); - }); - - context('when providing --tlsCertificateSelector', () => { - const argv = [ ...baseArgv, uri, '--tlsCertificateSelector', 'test' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the tlsCertificateSelector in the object', () => { - expect(parse(argv).tlsCertificateSelector).to.equal('test'); - }); - }); - - context('when providing --tlsDisabledProtocols', () => { - const argv = [ ...baseArgv, uri, '--tlsDisabledProtocols', 'TLS1_0,TLS2_0' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the tlsDisabledProtocols in the object', () => { - expect(parse(argv).tlsDisabledProtocols).to.equal('TLS1_0,TLS2_0'); - }); - }); - }); - - context('when providing FLE options', () => { - context('when providing --awsAccessKeyId', () => { - const argv = [ ...baseArgv, uri, '--awsAccessKeyId', 'foo' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the awsAccessKeyId in the object', () => { - expect(parse(argv).awsAccessKeyId).to.equal('foo'); - }); - }); - - context('when providing --awsSecretAccessKey', () => { - const argv = [ ...baseArgv, uri, '--awsSecretAccessKey', 'foo' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the awsSecretAccessKey in the object', () => { - expect(parse(argv).awsSecretAccessKey).to.equal('foo'); - }); - }); - - context('when providing --awsSessionToken', () => { - const argv = [ ...baseArgv, uri, '--awsSessionToken', 'foo' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the awsSessionToken in the object', () => { - expect(parse(argv).awsSessionToken).to.equal('foo'); - }); - }); - - context('when providing --keyVaultNamespace', () => { - const argv = [ ...baseArgv, uri, '--keyVaultNamespace', 'foo.bar' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the keyVaultNamespace in the object', () => { - expect(parse(argv).keyVaultNamespace).to.equal('foo.bar'); - }); - }); - - context('when providing --kmsURL', () => { - const argv = [ ...baseArgv, uri, '--kmsURL', 'example.com' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the kmsURL in the object', () => { - expect(parse(argv).kmsURL).to.equal('example.com'); - }); - }); - }); - }); - - context('when providing no URI', () => { - context('when providing a DB address', () => { - context('when only a db name is provided', () => { - const db = 'foo'; - const argv = [ ...baseArgv, db ]; - - it('sets the db in the object', () => { - expect(parse(argv)._[0]).to.equal(db); - }); - }); - - context('when a db address is provided without a scheme', () => { - const db = '192.168.0.5:9999/foo'; - const argv = [ ...baseArgv, db ]; + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the db in the object', () => { - expect(parse(argv)._[0]).to.equal(db); + it('sets the ipv6 value in the object', () => { + expect(parseCliArgs(argv).ipv6).to.equal(true); + }); }); - }); - }); - context('when providing no DB address', () => { - context('when providing a host', () => { - const argv = [ ...baseArgv, '--host', 'example.com' ]; + context('when providing -h', () => { + const argv = [ ...baseArgv, uri, '-h' ]; - it('sets the host value in the object', () => { - expect(parse(argv).host).to.equal('example.com'); - }); - }); - - context('when providing a port', () => { - const argv = [ ...baseArgv, '--port', '20000' ]; + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the port value in the object', () => { - expect(parse(argv).port).to.equal('20000'); + it('sets the help value in the object', () => { + expect(parseCliArgs(argv).help).to.equal(true); + }); }); - }); - }); - }); - }); - - context('when running via npm start', () => { - const baseArgv = [ NODE, MONGOSH, START ]; - context('when providing only a URI', () => { - const uri = 'mongodb://domain.com:20000'; - const argv = [ ...baseArgv, uri]; + context('when providing --help', () => { + const argv = [ ...baseArgv, uri, '--help' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - }); - - context('when providing a URI + options', () => { - const uri = 'mongodb://domain.com:20000'; - - context('when providing general options', () => { - context('when providing --ipv6', () => { - const argv = [ ...baseArgv, uri, '--ipv6' ]; + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); + it('sets the help value in the object', () => { + expect(parseCliArgs(argv).help).to.equal(true); + }); }); - it('sets the ipv6 value in the object', () => { - expect(parse(argv).ipv6).to.equal(true); - }); - }); + context('when providing --version', () => { + const argv = [ ...baseArgv, uri, '--version' ]; - context('when providing -h', () => { - const argv = [ ...baseArgv, uri, '-h' ]; + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); + it('sets the version value in the object', () => { + expect(parseCliArgs(argv).version).to.equal(true); + }); }); - it('sets the help value in the object', () => { - expect(parse(argv).help).to.equal(true); - }); - }); + context('when providing --verbose', () => { + const argv = [ ...baseArgv, uri, '--verbose' ]; - context('when providing --help', () => { - const argv = [ ...baseArgv, uri, '--help' ]; + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); + it('sets the verbose value in the object', () => { + expect(parseCliArgs(argv).verbose).to.equal(true); + }); }); - it('sets the help value in the object', () => { - expect(parse(argv).help).to.equal(true); - }); - }); + context('when providing --shell', () => { + const argv = [ ...baseArgv, uri, '--shell' ]; - context('when providing --version', () => { - const argv = [ ...baseArgv, uri, '--version' ]; + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); + it('sets the shell value in the object', () => { + expect(parseCliArgs(argv).shell).to.equal(true); + }); }); - it('sets the version value in the object', () => { - expect(parse(argv).version).to.equal(true); - }); - }); + context('when providing --nodb', () => { + const argv = [ ...baseArgv, uri, '--nodb' ]; - context('when providing --verbose', () => { - const argv = [ ...baseArgv, uri, '--verbose' ]; + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); + it('sets the nodb value in the object', () => { + expect(parseCliArgs(argv).nodb).to.equal(true); + }); }); - it('sets the verbose value in the object', () => { - expect(parse(argv).verbose).to.equal(true); - }); - }); + context('when providing --norc', () => { + const argv = [ ...baseArgv, uri, '--norc' ]; - context('when providing --shell', () => { - const argv = [ ...baseArgv, uri, '--shell' ]; + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); + it('sets the norc value in the object', () => { + expect(parseCliArgs(argv).norc).to.equal(true); + }); }); - it('sets the shell value in the object', () => { - expect(parse(argv).shell).to.equal(true); - }); - }); + context('when providing --quiet', () => { + const argv = [ ...baseArgv, uri, '--quiet' ]; - context('when providing --nodb', () => { - const argv = [ ...baseArgv, uri, '--nodb' ]; + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); + it('sets the quiet value in the object', () => { + expect(parseCliArgs(argv).quiet).to.equal(true); + }); }); - it('sets the nodb value in the object', () => { - expect(parse(argv).nodb).to.equal(true); - }); - }); + context('when providing --eval', () => { + const argv = [ ...baseArgv, uri, '--eval', '1+1' ]; - context('when providing --norc', () => { - const argv = [ ...baseArgv, uri, '--norc' ]; + it('throws an error since it is not yet supported', () => { + try { + parseCliArgs(argv); + } catch (e) { + expect(e).to.be.instanceOf(MongoshUnimplementedError); + expect(e.message).to.include('Argument --eval is not yet supported in mongosh'); + return; + } + expect.fail('Expected error'); + }); - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + // it('returns the URI in the object', () => { + // expect(parseCliArgs(argv)._[0]).to.equal(uri); + // }); - it('sets the norc value in the object', () => { - expect(parse(argv).norc).to.equal(true); + // it('sets the eval value in the object', () => { + // expect(parseCliArgs(argv).eval).to.equal('1+1'); + // }); }); - }); - context('when providing --quiet', () => { - const argv = [ ...baseArgv, uri, '--quiet' ]; + context('when providing --retryWrites', () => { + const argv = [ ...baseArgv, uri, '--retryWrites' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the quiet value in the object', () => { - expect(parse(argv).quiet).to.equal(true); + it('sets the retryWrites value in the object', () => { + expect(parseCliArgs(argv).retryWrites).to.equal(true); + }); }); - }); - - context('when providing --eval', () => { - const argv = [ ...baseArgv, uri, '--eval', '1+1' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + context('when providing an unknown parameter', () => { + const argv = [ ...baseArgv, uri, '--what' ]; - it('sets the eval value in the object', () => { - expect(parse(argv).eval).to.equal('1+1'); + it('raises an error', () => { + try { + parseCliArgs(argv); + } catch (err) { + return expect( + stripAnsi(err.message) + ).to.contain('Error parsing command line: unrecognized option: --what'); + } + expect.fail('parsing unknown parameter did not throw'); + }); }); }); - context('when providing --retryWrites', () => { - const argv = [ ...baseArgv, uri, '--retryWrites' ]; - - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); - - it('sets the retryWrites value in the object', () => { - expect(parse(argv).retryWrites).to.equal(true); - }); - }); + context('when providing authentication options', () => { + context('when providing -u', () => { + const argv = [ ...baseArgv, uri, '-u', 'richard' ]; - context('when providing an unknown parameter', () => { - const argv = [ ...baseArgv, uri, '--what' ]; + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('raises an error', () => { - try { - parse(argv); - } catch (err) { - return expect( - stripAnsi(err.message) - ).to.contain('Error parsing command line: unrecognized option: --what'); - } - expect.fail('parsing unknown parameter did not throw'); + it('sets the username in the object', () => { + expect(parseCliArgs(argv).username).to.equal('richard'); + }); }); - }); - }); - context('when providing authentication options', () => { - context('when providing -u', () => { - const argv = [ ...baseArgv, uri, '-u', 'richard' ]; + context('when providing --username', () => { + const argv = [ ...baseArgv, uri, '--username', 'richard' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the username in the object', () => { - expect(parse(argv).username).to.equal('richard'); + it('sets the username in the object', () => { + expect(parseCliArgs(argv).username).to.equal('richard'); + }); }); - }); - context('when providing --username', () => { - const argv = [ ...baseArgv, uri, '--username', 'richard' ]; + context('when providing -p', () => { + const argv = [ ...baseArgv, uri, '-p', 'pw' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the username in the object', () => { - expect(parse(argv).username).to.equal('richard'); + it('sets the password in the object', () => { + expect(parseCliArgs(argv).password).to.equal('pw'); + }); }); - }); - context('when providing -p', () => { - const argv = [ ...baseArgv, uri, '-p', 'pw' ]; + context('when providing --password', () => { + const argv = [ ...baseArgv, uri, '--password', 'pw' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the password in the object', () => { - expect(parse(argv).password).to.equal('pw'); + it('sets the password in the object', () => { + expect(parseCliArgs(argv).password).to.equal('pw'); + }); }); - }); - context('when providing --password', () => { - const argv = [ ...baseArgv, uri, '--password', 'pw' ]; + context('when providing --authenticationDatabase', () => { + const argv = [ ...baseArgv, uri, '--authenticationDatabase', 'db' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the password in the object', () => { - expect(parse(argv).password).to.equal('pw'); + it('sets the authenticationDatabase in the object', () => { + expect(parseCliArgs(argv).authenticationDatabase).to.equal('db'); + }); }); - }); - context('when providing --authenticationDatabase', () => { - const argv = [ ...baseArgv, uri, '--authenticationDatabase', 'db' ]; + context('when providing --authenticationMechanism', () => { + const argv = [ ...baseArgv, uri, '--authenticationMechanism', 'SCRAM-SHA-256' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the authenticationDatabase in the object', () => { - expect(parse(argv).authenticationDatabase).to.equal('db'); + it('sets the authenticationMechanism in the object', () => { + expect(parseCliArgs(argv).authenticationMechanism).to.equal('SCRAM-SHA-256'); + }); }); - }); - context('when providing --authenticationMechanism', () => { - const argv = [ ...baseArgv, uri, '--authenticationMechanism', 'SCRAM-SHA-256' ]; + context('when providing --gssapiServiceName', () => { + const argv = [ ...baseArgv, uri, '--gssapiServiceName', 'mongosh' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the authenticationMechanism in the object', () => { - expect(parse(argv).authenticationMechanism).to.equal('SCRAM-SHA-256'); + it('sets the gssapiServiceName in the object', () => { + expect(parseCliArgs(argv).gssapiServiceName).to.equal('mongosh'); + }); }); - }); - context('when providing --gssapiServiceName', () => { - const argv = [ ...baseArgv, uri, '--gssapiServiceName', 'mongosh' ]; + context('when providing --gssapiHostName', () => { + const argv = [ ...baseArgv, uri, '--gssapiHostName', 'example.com' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the gssapiServiceName in the object', () => { - expect(parse(argv).gssapiServiceName).to.equal('mongosh'); + it('sets the gssapiHostName in the object', () => { + expect(parseCliArgs(argv).gssapiHostName).to.equal('example.com'); + }); }); }); - context('when providing --gssapiHostName', () => { - const argv = [ ...baseArgv, uri, '--gssapiHostName', 'example.com' ]; + context('when providing TLS options', () => { + context('when providing --tls', () => { + const argv = [ ...baseArgv, uri, '--tls' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the gssapiHostName in the object', () => { - expect(parse(argv).gssapiHostName).to.equal('example.com'); + it('sets the tls in the object', () => { + expect(parseCliArgs(argv).tls).to.equal(true); + }); }); - }); - }); - context('when providing TLS options', () => { - context('when providing --tls', () => { - const argv = [ ...baseArgv, uri, '--tls' ]; + context('when providing --tlsCertificateKeyFile', () => { + const argv = [ ...baseArgv, uri, '--tlsCertificateKeyFile', 'test' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the tls in the object', () => { - expect(parse(argv).tls).to.equal(true); + it('sets the tlsCertificateKeyFile in the object', () => { + expect(parseCliArgs(argv).tlsCertificateKeyFile).to.equal('test'); + }); }); - }); - context('when providing --tlsCertificateKeyFile', () => { - const argv = [ ...baseArgv, uri, '--tlsCertificateKeyFile', 'test' ]; + context('when providing --tlsCertificateKeyFilePassword', () => { + const argv = [ ...baseArgv, uri, '--tlsCertificateKeyFilePassword', 'test' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the tlsCertificateKeyFile in the object', () => { - expect(parse(argv).tlsCertificateKeyFile).to.equal('test'); + it('sets the tlsCertificateKeyFilePassword in the object', () => { + expect(parseCliArgs(argv).tlsCertificateKeyFilePassword).to.equal('test'); + }); }); - }); - context('when providing --tlsCertificateKeyFilePassword', () => { - const argv = [ ...baseArgv, uri, '--tlsCertificateKeyFilePassword', 'test' ]; + context('when providing --tlsCAFile', () => { + const argv = [ ...baseArgv, uri, '--tlsCAFile', 'test' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the tlsCertificateKeyFilePassword in the object', () => { - expect(parse(argv).tlsCertificateKeyFilePassword).to.equal('test'); + it('sets the tlsCAFile in the object', () => { + expect(parseCliArgs(argv).tlsCAFile).to.equal('test'); + }); }); - }); - context('when providing --tlsCAFile', () => { - const argv = [ ...baseArgv, uri, '--tlsCAFile', 'test' ]; + context('when providing --tlsCRLFile', () => { + const argv = [ ...baseArgv, uri, '--tlsCRLFile', 'test' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the tlsCAFile in the object', () => { - expect(parse(argv).tlsCAFile).to.equal('test'); + it('sets the tlsCRLFile in the object', () => { + expect(parseCliArgs(argv).tlsCRLFile).to.equal('test'); + }); }); - }); - context('when providing --tlsCRLFile', () => { - const argv = [ ...baseArgv, uri, '--tlsCRLFile', 'test' ]; + context('when providing --tlsAllowInvalidHostnames', () => { + const argv = [ ...baseArgv, uri, '--tlsAllowInvalidHostnames' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the tlsCRLFile in the object', () => { - expect(parse(argv).tlsCRLFile).to.equal('test'); + it('sets the tlsAllowInvalidHostnames in the object', () => { + expect(parseCliArgs(argv).tlsAllowInvalidHostnames).to.equal(true); + }); }); - }); - context('when providing --tlsAllowInvalidHostnames', () => { - const argv = [ ...baseArgv, uri, '--tlsAllowInvalidHostnames' ]; + context('when providing --tlsAllowInvalidCertificates', () => { + const argv = [ ...baseArgv, uri, '--tlsAllowInvalidCertificates' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the tlsAllowInvalidHostnames in the object', () => { - expect(parse(argv).tlsAllowInvalidHostnames).to.equal(true); + it('sets the tlsAllowInvalidCertificates in the object', () => { + expect(parseCliArgs(argv).tlsAllowInvalidCertificates).to.equal(true); + }); }); - }); - - context('when providing --tlsAllowInvalidCertificates', () => { - const argv = [ ...baseArgv, uri, '--tlsAllowInvalidCertificates' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + context('when providing --tlsFIPSMode', () => { + const argv = [ ...baseArgv, uri, '--tlsFIPSMode' ]; - it('sets the tlsAllowInvalidCertificates in the object', () => { - expect(parse(argv).tlsAllowInvalidCertificates).to.equal(true); - }); - }); + it('throws an error since it is not yet supported', () => { + try { + parseCliArgs(argv); + } catch (e) { + expect(e).to.be.instanceOf(MongoshUnimplementedError); + expect(e.message).to.include('Argument --tlsFIPSMode is not yet supported in mongosh'); + return; + } + expect.fail('Expected error'); + }); - context('when providing --tlsFIPSMode', () => { - const argv = [ ...baseArgv, uri, '--tlsFIPSMode' ]; + // it('returns the URI in the object', () => { + // expect(parseCliArgs(argv)._[0]).to.equal(uri); + // }); - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); + // it('sets the tlsFIPSMode in the object', () => { + // expect(parseCliArgs(argv).tlsFIPSMode).to.equal(true); + // }); }); - it('sets the tlsFIPSMode in the object', () => { - expect(parse(argv).tlsFIPSMode).to.equal(true); - }); - }); + context('when providing --tlsCertificateSelector', () => { + const argv = [ ...baseArgv, uri, '--tlsCertificateSelector', 'test' ]; - context('when providing --tlsCertificateSelector', () => { - const argv = [ ...baseArgv, uri, '--tlsCertificateSelector', 'test' ]; + it('throws an error since it is not yet supported', () => { + try { + parseCliArgs(argv); + } catch (e) { + expect(e).to.be.instanceOf(MongoshUnimplementedError); + expect(e.message).to.include('Argument --tlsCertificateSelector is not yet supported in mongosh'); + return; + } + expect.fail('Expected error'); + }); - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + // it('returns the URI in the object', () => { + // expect(parseCliArgs(argv)._[0]).to.equal(uri); + // }); - it('sets the tlsCertificateSelector in the object', () => { - expect(parse(argv).tlsCertificateSelector).to.equal('test'); + // it('sets the tlsCertificateSelector in the object', () => { + // expect(parseCliArgs(argv).tlsCertificateSelector).to.equal('test'); + // }); }); - }); - context('when providing --tlsDisabledProtocols', () => { - const argv = [ ...baseArgv, uri, '--tlsDisabledProtocols', 'TLS1_0,TLS2_0' ]; + context('when providing --tlsDisabledProtocols', () => { + const argv = [ ...baseArgv, uri, '--tlsDisabledProtocols', 'TLS1_0,TLS2_0' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the tlsDisabledProtocols in the object', () => { - expect(parse(argv).tlsDisabledProtocols).to.equal('TLS1_0,TLS2_0'); + it('sets the tlsDisabledProtocols in the object', () => { + expect(parseCliArgs(argv).tlsDisabledProtocols).to.equal('TLS1_0,TLS2_0'); + }); }); }); - }); - context('when providing FLE options', () => { - context('when providing --awsAccessKeyId', () => { - const argv = [ ...baseArgv, uri, '--awsAccessKeyId', 'foo' ]; + context('when providing FLE options', () => { + context('when providing --awsAccessKeyId', () => { + const argv = [ ...baseArgv, uri, '--awsAccessKeyId', 'foo' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the awsAccessKeyId in the object', () => { - expect(parse(argv).awsAccessKeyId).to.equal('foo'); + it('sets the awsAccessKeyId in the object', () => { + expect(parseCliArgs(argv).awsAccessKeyId).to.equal('foo'); + }); }); - }); - context('when providing --awsSecretAccessKey', () => { - const argv = [ ...baseArgv, uri, '--awsSecretAccessKey', 'foo' ]; + context('when providing --awsSecretAccessKey', () => { + const argv = [ ...baseArgv, uri, '--awsSecretAccessKey', 'foo' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the awsSecretAccessKey in the object', () => { - expect(parse(argv).awsSecretAccessKey).to.equal('foo'); + it('sets the awsSecretAccessKey in the object', () => { + expect(parseCliArgs(argv).awsSecretAccessKey).to.equal('foo'); + }); }); - }); - context('when providing --awsSessionToken', () => { - const argv = [ ...baseArgv, uri, '--awsSessionToken', 'foo' ]; + context('when providing --awsSessionToken', () => { + const argv = [ ...baseArgv, uri, '--awsSessionToken', 'foo' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the awsSessionToken in the object', () => { - expect(parse(argv).awsSessionToken).to.equal('foo'); + it('sets the awsSessionToken in the object', () => { + expect(parseCliArgs(argv).awsSessionToken).to.equal('foo'); + }); }); - }); - context('when providing --keyVaultNamespace', () => { - const argv = [ ...baseArgv, uri, '--keyVaultNamespace', 'foo.bar' ]; + context('when providing --keyVaultNamespace', () => { + const argv = [ ...baseArgv, uri, '--keyVaultNamespace', 'foo.bar' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the keyVaultNamespace in the object', () => { - expect(parse(argv).keyVaultNamespace).to.equal('foo.bar'); + it('sets the keyVaultNamespace in the object', () => { + expect(parseCliArgs(argv).keyVaultNamespace).to.equal('foo.bar'); + }); }); - }); - context('when providing --kmsURL', () => { - const argv = [ ...baseArgv, uri, '--kmsURL', 'example.com' ]; + context('when providing --kmsURL', () => { + const argv = [ ...baseArgv, uri, '--kmsURL', 'example.com' ]; - it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); - }); + it('returns the URI in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(uri); + }); - it('sets the kmsURL in the object', () => { - expect(parse(argv).kmsURL).to.equal('example.com'); + it('sets the kmsURL in the object', () => { + expect(parseCliArgs(argv).kmsURL).to.equal('example.com'); + }); }); }); @@ -1012,53 +561,80 @@ describe('arg-parser', () => { const argv = [ ...baseArgv, uri, 'test1.js', 'test2.js' ]; it('returns the URI in the object', () => { - expect(parse(argv)._[0]).to.equal(uri); + expect(parseCliArgs(argv)._[0]).to.equal(uri); }); it('sets the filenames', () => { - expect(parse(argv)._[1]).to.equal('test1.js'); - expect(parse(argv)._[2]).to.equal('test2.js'); + expect(parseCliArgs(argv)._[1]).to.equal('test1.js'); + expect(parseCliArgs(argv)._[2]).to.equal('test2.js'); }); }); }); }); - }); - context('when providing no URI', () => { - context('when providing a DB address', () => { - context('when only a db name is provided', () => { - const db = 'foo'; - const argv = [ ...baseArgv, db ]; + context('when providing no URI', () => { + context('when providing a DB address', () => { + context('when only a db name is provided', () => { + const db = 'foo'; + const argv = [ ...baseArgv, db ]; - it('sets the db in the object', () => { - expect(parse(argv)._[0]).to.equal(db); + it('sets the db in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(db); + }); }); - }); - context('when a db address is provided without a scheme', () => { - const db = '192.168.0.5:9999/foo'; - const argv = [ ...baseArgv, db ]; + context('when a db address is provided without a scheme', () => { + const db = '192.168.0.5:9999/foo'; + const argv = [ ...baseArgv, db ]; - it('sets the db in the object', () => { - expect(parse(argv)._[0]).to.equal(db); + it('sets the db in the object', () => { + expect(parseCliArgs(argv)._[0]).to.equal(db); + }); }); }); - }); - context('when providing no DB address', () => { - context('when providing a host', () => { - const argv = [ ...baseArgv, '--host', 'example.com' ]; + context('when providing no DB address', () => { + context('when providing a host', () => { + const argv = [ ...baseArgv, '--host', 'example.com' ]; - it('sets the host value in the object', () => { - expect(parse(argv).host).to.equal('example.com'); + it('sets the host value in the object', () => { + expect(parseCliArgs(argv).host).to.equal('example.com'); + }); + }); + + context('when providing a port', () => { + const argv = [ ...baseArgv, '--port', '20000' ]; + + it('sets the port value in the object', () => { + expect(parseCliArgs(argv).port).to.equal('20000'); + }); }); }); + }); - context('when providing a port', () => { - const argv = [ ...baseArgv, '--port', '20000' ]; + context('when providing a deprecated argument', () => { + [ + { deprecated: 'ssl', replacement: 'tls' }, + { deprecated: 'sslAllowInvalidCertificates', replacement: 'tlsAllowInvalidCertificates' }, + { deprecated: 'sslAllowInvalidCertificates', replacement: 'tlsAllowInvalidCertificates' }, + { deprecated: 'sslAllowInvalidHostname', replacement: 'tlsAllowInvalidHostname' }, + // { deprecated: 'sslFIPSMode', replacement: 'tlsFIPSMode' }, <<-- FIPS is currently not supported right now + { deprecated: 'sslPEMKeyFile', replacement: 'tlsCertificateKeyFile', value: 'pemKeyFile' }, + { deprecated: 'sslPEMKeyPassword', replacement: 'tlsCertificateKeyFilePassword', value: 'pemKeyPass' }, + { deprecated: 'sslCAFile', replacement: 'tlsCAFile', value: 'caFile' }, + // { deprecated: 'sslCertificateSelector', replacement: 'tlsCertificateSelector', value: 'certSelector' }, <<-- Certificate selector not supported right now + { deprecated: 'sslCRLFile', replacement: 'tlsCRLFile', value: 'crlFile' }, + { deprecated: 'sslDisabledProtocols', replacement: 'tlsDisabledProtocols', value: 'disabledProtos' } + ].forEach(({ deprecated, replacement, value }) => { + it(`replaces --${deprecated} with --${replacement}`, () => { + const argv = [...baseArgv, `--${deprecated}`]; + if (value) { + argv.push(value); + } - it('sets the port value in the object', () => { - expect(parse(argv).port).to.equal('20000'); + const args = parseCliArgs(argv); + expect(args).to.not.have.property(deprecated); + expect(args[replacement]).to.equal(value ?? true); }); }); }); diff --git a/packages/cli-repl/src/arg-parser.ts b/packages/cli-repl/src/arg-parser.ts index 3f64f4bd93..c859419e6d 100644 --- a/packages/cli-repl/src/arg-parser.ts +++ b/packages/cli-repl/src/arg-parser.ts @@ -1,3 +1,4 @@ +import { CommonErrors, MongoshUnimplementedError } from '@mongosh/errors'; import i18n from '@mongosh/i18n'; import { CliOptions } from '@mongosh/service-provider-server'; import parser from 'yargs-parser'; @@ -22,6 +23,7 @@ const OPTIONS = { 'authenticationDatabase', 'authenticationMechanism', 'awsAccessKeyId', + 'awsIamSessionToken', 'awsSecretAccessKey', 'awsSessionToken', 'db', @@ -34,6 +36,12 @@ const OPTIONS = { 'locale', 'password', 'port', + 'sslPEMKeyFile', + 'sslPEMKeyPassword', + 'sslCAFile', + 'sslCertificateSelector', + 'sslCRLFile', + 'sslDisabledProtocols', 'tlsCAFile', 'tlsCertificateKeyFile', 'tlsCertificateKeyFilePassword', @@ -53,6 +61,10 @@ const OPTIONS = { 'retryWrites', 'shell', 'smokeTests', + 'ssl', + 'sslAllowInvalidCertificates', + 'sslAllowInvalidHostname', + 'sslFIPSMode', 'tls', 'tlsAllowInvalidCertificates', 'tlsAllowInvalidHostnames', @@ -71,6 +83,33 @@ const OPTIONS = { } }; +/** + * Maps deprecated arguments to their new counterparts. + */ +const DEPRECATED_ARGS_WITH_REPLACEMENT: Record = { + ssl: 'tls', + sslAllowInvalidCertificates: 'tlsAllowInvalidCertificates', + sslAllowInvalidHostname: 'tlsAllowInvalidHostname', + sslFIPSMode: 'tlsFIPSMode', + sslPEMKeyFile: 'tlsCertificateKeyFile', + sslPEMKeyPassword: 'tlsCertificateKeyFilePassword', + sslCAFile: 'tlsCAFile', + sslCertificateSelector: 'tlsCertificateSelector', + sslCRLFile: 'tlsCRLFile', + sslDisabledProtocols: 'tlsDisabledProtocols' +}; + +/** + * If an unsupported argument is given an error will be thrown. + */ +const UNSUPPORTED_ARGS: Readonly = [ + 'eval', + 'sslFIPSMode', + 'tlsFIPSMode', + 'sslCertificateSelector', + 'tlsCertificateSelector' +]; + /** * Determine the locale of the shell. * @@ -78,7 +117,7 @@ const OPTIONS = { * * @returns {string} The locale. */ -function getLocale(args: string[], env: any): string { +export function getLocale(args: string[], env: any): string { const localeIndex = args.indexOf('--locale'); if (localeIndex > -1) { return args[localeIndex + 1]; @@ -90,11 +129,11 @@ function getLocale(args: string[], env: any): string { /** * Parses arguments into a JS object. * - * @param {string[]} args - The args. + * @param args - The CLI arguments. * - * @returns {CliOptions} The arguments as cli options. + * @returns The arguments as cli options. */ -function parse(args: string[]): (CliOptions & { smokeTests: boolean }) { +export function parseCliArgs(args: string[]): (CliOptions & { smokeTests: boolean }) { const programArgs = args.slice(2); i18n.setLocale(getLocale(programArgs, process.env)); @@ -111,8 +150,32 @@ function parse(args: string[]): (CliOptions & { smokeTests: boolean }) { ${USAGE}` ); }); + + const messages = verifyCliArguments(parsed); + messages.forEach(m => console.warn(m)); + return parsed as unknown as (CliOptions & { smokeTests: boolean }); } -export default parse; -export { getLocale }; +export function verifyCliArguments(args: parser.Arguments): string[] { + for (const unsupported of UNSUPPORTED_ARGS) { + if (unsupported in args) { + throw new MongoshUnimplementedError( + `Argument --${unsupported} is not yet supported in mongosh`, + CommonErrors.InvalidArgument + ); + } + } + + const messages = []; + for (const deprecated in DEPRECATED_ARGS_WITH_REPLACEMENT) { + if (deprecated in args) { + const replacement = DEPRECATED_ARGS_WITH_REPLACEMENT[deprecated]; + messages.push(`WARNING: argument --${deprecated} is deprecated and will be removed. Use --${replacement} instead.`); + + args[replacement] = args[deprecated]; + delete args[deprecated]; + } + } + return messages; +} diff --git a/packages/cli-repl/src/index.ts b/packages/cli-repl/src/index.ts index 782de431bf..ffe2dc4554 100644 --- a/packages/cli-repl/src/index.ts +++ b/packages/cli-repl/src/index.ts @@ -1,9 +1,9 @@ -import CliRepl from './cli-repl'; -import parseCliArgs from './arg-parser'; import mapCliToDriver from './arg-mapper'; +import { parseCliArgs } from './arg-parser'; +import CliRepl from './cli-repl'; import clr from './clr'; -import { USAGE, TELEMETRY_GREETING_MESSAGE, MONGOSH_WIKI } from './constants'; import { getStoragePaths } from './config-directory'; +import { MONGOSH_WIKI, TELEMETRY_GREETING_MESSAGE, USAGE } from './constants'; import { getMongocryptdPath } from './mongocryptd-path'; import { runSmokeTests } from './smoke-tests'; diff --git a/packages/service-provider-core/src/cli-options.ts b/packages/service-provider-core/src/cli-options.ts index 809458b655..3883a4a9c4 100644 --- a/packages/service-provider-core/src/cli-options.ts +++ b/packages/service-provider-core/src/cli-options.ts @@ -7,6 +7,7 @@ export default interface CliOptions { authenticationDatabase?: string; authenticationMechanism?: string; awsAccessKeyId?: string; + awsIamSessionToken?: string; awsSecretAccessKey?: string; awsSessionToken?: string; db?: string;