Repository: serverless/serverless (JavaScript) — Bug Fix

Issue:
CLI argument being converted to number and rounded up
# This is a Bug Report

## Description

Command line argument '2060451113271393738' is being converted to a number and then rounded up to 2060451113271393800 in options array.


* What went wrong?  
Calling KMS Secrets plugin, the string value '2060451113271393738' is being converted by the CLI processInput function to 2060451113271393800. The use of the minimist(inputArray) function appears to be causing the problem.

https://github.com/serverless/serverless/blob/master/lib/classes/CLI.js#L37

Here's the line in the minimist package that converts the argument to a number. https://github.com/substack/minimist/blob/master/index.js#L59

* What did you expect should have happened?
It should have treated my value as a string. 

* What stacktrace or error message from your provider did you see?


```sh
sls encrypt -n TEST_ENCRYPT -v '2060451113271393738' -s dev -r us-east-1

DEBUG Before call to minimist(inputArray);
[ 'encrypt',
  '-n',
  'TEST_ENCRYPT',
  '-v',
  '2060451113271393738',
  '-s',
  'dev',
  '-r',
  'us-east-1' ]

DEBUG After call to minimist(inputArray);
{ _: [ 'encrypt' ],
  n: 'TEST_ENCRYPT',
  v: 2060451113271393800,
  s: 'dev',
  r: 'us-east-1' }

```

## Additional Data

* ***Serverless Framework Version you're using***:
1.27.3

* ***Operating System***:
macOS Sierra




Discussion:
Hi, can I work on this? Or is anyone working on it currently?
Thanks!
Hi @RafalWilinski it is still this issue relevant?
@JmeG I play around with the code and I think that I have a workaround.
Do you still need it? Pass all tests so, I can push into my fork for your testing.

Resolving patch:
diff --git a/lib/classes/CLI.js b/lib/classes/CLI.js
index 3d7f4b5ab78..f4db3010393 100644
--- a/lib/classes/CLI.js
+++ b/lib/classes/CLI.js
@@ -34,7 +34,33 @@ class CLI {
       inputArray = process.argv.slice(2);
     }
 
-    const argv = minimist(inputArray);
+    const toBase64Helper = (value, index) => {
+      if ((index % 2) !== 0) {
+        return new Buffer(value.toString()).toString('base64');
+      }
+      return value;
+    };
+
+    const decodedArgsHelper = (arg) => {
+      if (_.isString(arg)) {
+        return new Buffer(arg, 'base64').toString();
+      }
+      return arg;
+    };
+
+    // get all the commands
+    const valuesToIgnore = _.takeWhile(inputArray, (item) => !item.startsWith('-'));
+    // get all the options
+    const valuesToConvert = _.difference(inputArray, valuesToIgnore);
+    // encode all the options values to base64
+    const valuesToB64 = _.map(valuesToConvert, toBase64Helper);
+    // concat commands with values on base64
+    const valuesToParse = _.concat(valuesToIgnore, valuesToB64);
+
+    const argvToParse = minimist(valuesToParse);
+
+    // decode all values to utf8 strings
+    const argv = _.mapValues(argvToParse, decodedArgsHelper);
 
     const commands = [].concat(argv._);
     const options = _.omit(argv, ['_']);


Test patch:
diff --git a/lib/classes/CLI.test.js b/lib/classes/CLI.test.js
index 9925a75a1ec..112b8befaba 100644
--- a/lib/classes/CLI.test.js
+++ b/lib/classes/CLI.test.js
@@ -362,6 +362,15 @@ describe('CLI', () => {
       expect(inputToBeProcessed).to.deep.equal(expectedObject);
     });
 
+    it('should only return numbers like strings when numbers are given on options', () => {
+      cli = new CLI(serverless, ['-f', 'function1', '-k', 123]);
+      const inputToBeProcessed = cli.processInput();
+
+      const expectedObject = { commands: [], options: { f: 'function1', k: '123' } };
+
+      expect(inputToBeProcessed).to.deep.equal(expectedObject);
+    });
+
     it('should return commands and options when both are given', () => {
       cli = new CLI(serverless, ['deploy', 'functions', '-f', 'function1']);
       const inputToBeProcessed = cli.processInput();