Repository: oclif/core
Pull request #687 (2023-04-11 16:45:35)

fix:  jsonEnabled not handling after pass-through
@W-13012400@


Patch:
diff --git a/src/command.ts b/src/command.ts
index 9bc47d8..fc19634 100644
--- a/src/command.ts
+++ b/src/command.ts
@@ -125,6 +125,8 @@ export abstract class Command {
 
   public static hasDynamicHelp = false
 
+  protected static '_--' = false
+
   protected static _enableJsonFlag = false
 
   public static get enableJsonFlag(): boolean {
@@ -142,6 +144,18 @@ export abstract class Command {
     }
   }
 
+  public static get '--'(): boolean {
+    return Command['_--']
+  }
+
+  public static set '--'(value: boolean) {
+    Command['_--'] = value
+  }
+
+  public get passThroughEnabled(): boolean {
+    return Command['_--']
+  }
+
   /**
    * instantiate and run the command
    *
@@ -259,8 +273,22 @@ export abstract class Command {
     }
   }
 
+  /**
+   * Determine if the command is being run with the --json flag in a command that supports it.
+   *
+   * @returns {boolean} true if the command supports json and the --json flag is present
+   */
   public jsonEnabled(): boolean {
-    return this.ctor.enableJsonFlag && this.argv.includes('--json')
+    // if the command doesn't support json, return false
+    if (!this.ctor.enableJsonFlag) return false
+    // if the command parameter pass through is enabled, return true if the --json flag is before the '--' separator
+    if (this.passThroughEnabled) {
+      const ptIndex = this.argv.indexOf('--')
+      const jsonIndex = this.argv.indexOf('--json')
+      return jsonIndex > -1 && (ptIndex === -1 || jsonIndex < ptIndex)
+    }
+
+    return this.argv.includes('--json')
   }
 
   /**


Test patch:
diff --git a/test/command/command.test.ts b/test/command/command.test.ts
index 15fccf5..583456c 100644
--- a/test/command/command.test.ts
+++ b/test/command/command.test.ts
@@ -449,4 +449,123 @@ describe('command', () => {
     .do(ctx => expect(ctx.stdout).to.equal('json output: {"a":"foobar"}\n'))
     .it('test stdout EPIPE swallowed')
   })
+  describe('json enabled and pass-through tests', () => {
+    fancy
+    .stdout()
+    .do(async () => {
+      class CMD extends Command {
+        static enableJsonFlag = true
+        async run() {
+          this.log('not json output')
+        }
+      }
+      const cmd = new CMD([], {} as any)
+      expect(cmd.jsonEnabled()).to.equal(false)
+    })
+    .it('json enabled/pass through disabled/no --json flag/jsonEnabled() should be false')
+
+    fancy
+    .stdout()
+    .do(async () => {
+      class CMD extends Command {
+        static enableJsonFlag = true
+        async run() {}
+      }
+      const cmd = new CMD(['--json'], {} as any)
+      expect(cmd.jsonEnabled()).to.equal(true)
+    })
+    .it('json enabled/pass through disabled/--json flag before --/jsonEnabled() should be true')
+
+    fancy
+    .stdout()
+    .do(async () => {
+      class CMD extends Command {
+          static enableJsonFlag = true
+          static '--' = true
+          async run() {
+            const {flags} = await cmd.parse(CMD, ['--json'])
+            expect(flags.json).to.equal(true, 'json flag should be true')
+          }
+      }
+      const cmd = new CMD(['--json'], {} as any)
+      expect(cmd.jsonEnabled()).to.equal(true)
+    })
+    .it('json enabled/pass through enabled/--json flag before --/jsonEnabled() should be true')
+
+    fancy
+    .stdout()
+    .do(async () => {
+      class CMD extends Command {
+          static enableJsonFlag = true
+          static '--' = true
+          async run() {
+            const {flags} = await cmd.parse(CMD, ['--', '--json'])
+            expect(flags.json).to.equal(false, 'json flag should be false')
+            expect(this.passThroughEnabled).to.equal(true, 'pass through should be true')
+          }
+      }
+      const cmd = new CMD(['--', '--json'], {} as any)
+      expect(cmd.jsonEnabled()).to.equal(false)
+    })
+    .it('json enabled/pass through enabled/--json flag after --/jsonEnabled() should be false')
+
+    fancy
+    .stdout()
+    .do(async () => {
+      class CMD extends Command {
+          static enableJsonFlag = true
+          static '--' = true
+          async run() {
+            const {flags} = await cmd.parse(CMD, ['--foo', '--json'])
+            expect(flags.json).to.equal(true, 'json flag should be true')
+          }
+      }
+      const cmd = new CMD(['foo', '--json'], {} as any)
+      expect(cmd.jsonEnabled()).to.equal(true)
+    })
+    .it('json enabled/pass through enabled/--json flag before --/extra param/jsonEnabled() should be true')
+
+    fancy
+    .stdout()
+    .do(async () => {
+      class CMD extends Command {
+          static enableJsonFlag = true
+          static '--' = true
+          async run() {
+            const {flags} = await cmd.parse(CMD, ['--foo', '--', '--json'])
+            expect(flags.json).to.equal(false, 'json flag should be false')
+            expect(this.passThroughEnabled).to.equal(true, 'pass through should be true')
+          }
+      }
+      const cmd = new CMD(['--foo', '--', '--json'], {} as any)
+      expect(cmd.jsonEnabled()).to.equal(false)
+    })
+    .it('json enabled/pass through enabled/--json flag after --/extra param/jsonEnabled() should be false')
+
+    fancy
+    .stdout()
+    .do(async () => {
+      class CMD extends Command {
+          static enableJsonFlag = true
+          static '--' = true
+          async run() {}
+      }
+      const cmd = new CMD(['--json', '--'], {} as any)
+      expect(cmd.jsonEnabled()).to.equal(true)
+    })
+    .it('json enabled/pass through enabled/--json flag before --/jsonEnabled() should be true')
+
+    fancy
+    .stdout()
+    .do(async () => {
+      class CMD extends Command {
+          static enableJsonFlag = false
+          static '--' = true
+          async run() {}
+      }
+      const cmd = new CMD(['--json'], {} as any)
+      expect(cmd.jsonEnabled()).to.equal(false)
+    })
+    .it('json disabled/pass through enable/--json flag before --/jsonEnabled() should be false')
+  })
 })
diff --git a/test/interfaces/flags.test.ts b/test/interfaces/flags.test.ts
index 0573c25..cfd0c4e 100644
--- a/test/interfaces/flags.test.ts
+++ b/test/interfaces/flags.test.ts
@@ -126,6 +126,8 @@ class MyCommand extends BaseCommand {
     defaultArrayFlag: arrayFlag({default: ['foo', 'bar']}),
   }
 
+  public static '--' = true
+
   public flags!: MyFlags
 
   public async run(): Promise<MyFlags> {