From 68ecc1643a672e72fd34ea9e224e30a917aa840b Mon Sep 17 00:00:00 2001
From: mshanemc <shane.mclaughlin@salesforce.com>
Date: Wed, 23 Feb 2022 08:30:43 -0600
Subject: [PATCH] feat: migrate force command from toolbelt

---
 package.json           |  1 +
 src/commands/force.ts  | 84 ++++++++++++++++++++++++++++++++++++++++++
 test/nuts/blank.nut.ts |  6 ---
 test/nuts/force.nut.ts | 36 ++++++++++++++++++
 tsconfig.json          |  6 ++-
 yarn.lock              | 17 +++++++++
 6 files changed, 143 insertions(+), 7 deletions(-)
 create mode 100644 src/commands/force.ts
 delete mode 100644 test/nuts/blank.nut.ts
 create mode 100644 test/nuts/force.nut.ts

diff --git a/package.json b/package.json
index 0332aa19..511267f4 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
   "bugs": "https://github.com/forcedotcom/cli/issues",
   "dependencies": {
     "@oclif/config": "^1",
+    "@oclif/plugin-help": "^3.3.1",
     "@salesforce/command": "^4.1.5",
     "@salesforce/core": "^2.29.0",
     "@salesforce/kit": "^1.5.17",
diff --git a/src/commands/force.ts b/src/commands/force.ts
new file mode 100644
index 00000000..1634de0a
--- /dev/null
+++ b/src/commands/force.ts
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2020, salesforce.com, inc.
+ * All rights reserved.
+ * Licensed under the BSD 3-Clause license.
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
+ */
+
+// This is a doc command
+/* istanbul ignore file */
+
+import { SfdxCommand } from '@salesforce/command';
+import got from 'got';
+import { Help } from '@oclif/plugin-help';
+import * as ProxyAgent from 'proxy-agent';
+import { getProxyForUrl } from 'proxy-from-env';
+
+const getAsciiSignature = (apiVersion: string): string => `
+                 DX DX DX
+             DX DX DX DX DX DX          DX DX DX
+          DX DX DX      DX DX DX    DX DX DX DX DX DX
+        DX DX              DX DX DX DX DX     DX DX DX
+       DX DX                 DX DX DX             DX DX    DX DX DX
+      DX DX                    DX DX                DX DX DX DX DX DX DX
+     DX DX                                          DX DX DX       DX DX DX
+     DX DX                                            DX             DX DX DX
+      DX DX                                                              DX DX
+      DX DX                                                               DX DX
+       DX DX                                                              DX DX
+     DX DX                                                                 DX DX
+   DX DX                                                                   DX DX
+ DX DX                                                                     DX DX
+DX DX                                                                     DX DX
+DX DX                                                                    DX DX
+DX DX                                                                   DX DX
+ DX DX                                                    DX          DX DX
+ DX DX                                                  DX DX DX DX DX DX
+  DX DX                                                 DX DX DX DX DX
+    DX DX DX   DX DX                     DX           DX DX
+       DX DX DX DX DX                   DX DX DX DX DX DX
+          DX DX  DX DX                  DX DX DX DX DX
+                  DX DX              DX DX
+                    DX DX DX     DX DX DX
+                      DX DX DX DX DX DX                     v${apiVersion}
+                          DX DX DX
+
+* Salesforce CLI Release Notes: https://github.com/forcedotcom/cli/tree/main/releasenotes
+* Salesforce DX Setup Guide: https://sfdc.co/sfdx_setup_guide
+* Salesforce DX Developer Guide: https://sfdc.co/sfdx_dev_guide
+* Salesforce CLI Command Reference: https://sfdc.co/sfdx_cli_reference
+* Salesforce Extensions for VS Code: https://marketplace.visualstudio.com/items?itemName=salesforce.salesforcedx-vscode
+`;
+
+const getCurrentApiVersion = async (): Promise<string> => {
+  const url = 'https://mdcoverage.secure.force.com/services/apexrest/report';
+  return `${(
+    JSON.parse(
+      (
+        await got(url, {
+          agent: { https: ProxyAgent(getProxyForUrl(url)) },
+        })
+      ).body
+    ) as {
+      versions: { selected: number };
+    }
+  ).versions.selected.toString()}.0`;
+};
+
+export class ForceCommand extends SfdxCommand {
+  public static readonly hidden = true;
+
+  public async run(): Promise<{ apiVersion: string }> {
+    const apiVersion = await getCurrentApiVersion();
+    this.ux.log(getAsciiSignature(apiVersion));
+    return { apiVersion };
+  }
+
+  // overrides the help so that it shows the help for the `force` topic and not "help" for this command
+  protected _help(): never {
+    const help = new Help(this.config);
+    // We need to include force in the args for topics to be shown
+    help.showHelp(process.argv.slice(2));
+    return this.exit(0);
+  }
+}
diff --git a/test/nuts/blank.nut.ts b/test/nuts/blank.nut.ts
deleted file mode 100644
index 5db313f9..00000000
--- a/test/nuts/blank.nut.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
- * Copyright (c) 2021, salesforce.com, inc.
- * All rights reserved.
- * Licensed under the BSD 3-Clause license.
- * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
- */
diff --git a/test/nuts/force.nut.ts b/test/nuts/force.nut.ts
new file mode 100644
index 00000000..bdadf96c
--- /dev/null
+++ b/test/nuts/force.nut.ts
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, salesforce.com, inc.
+ * All rights reserved.
+ * Licensed under the BSD 3-Clause license.
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
+ */
+
+import { expect } from 'chai';
+
+import { TestSession, execCmd } from '@salesforce/cli-plugins-testkit';
+
+describe('force command', () => {
+  let session: TestSession;
+
+  before(async () => {
+    session = await TestSession.create({
+      project: {
+        name: 'forceNut',
+      },
+    });
+  });
+  it('returns an apiVersion in JSON', () => {
+    const result = execCmd<{ apiVersion: string }>('force --json', { ensureExitCode: 0 }).jsonOutput.result;
+    expect(result).to.be.an('object').that.has.all.keys('apiVersion');
+    expect(result.apiVersion).to.match(/^\d{2,}\.0$/);
+    expect(parseInt(result.apiVersion, 10)).to.be.greaterThan(53);
+  });
+  it('executes the cloud/links without JSON', () => {
+    const result = execCmd('force', { ensureExitCode: 0 }).shellOutput as string;
+    expect(result).to.include('Salesforce CLI Release Notes');
+  });
+
+  after(async () => {
+    await session.clean();
+  });
+});
diff --git a/tsconfig.json b/tsconfig.json
index c789e2e6..fcf4409a 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,7 +3,11 @@
   "compilerOptions": {
     "outDir": "lib",
     "rootDir": "src",
-    "allowSyntheticDefaultImports": true
+    "allowSyntheticDefaultImports": true,
+    "baseUrl": ".",
+    "paths": {
+      "@oclif/config": ["node_modules/@oclif/config"]
+    }
   },
   "include": ["./src/**/*.ts"]
 }
diff --git a/yarn.lock b/yarn.lock
index 02250253..ee64b468 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -586,6 +586,23 @@
     widest-line "^2.0.1"
     wrap-ansi "^4.0.0"
 
+"@oclif/plugin-help@^3.3.1":
+  version "3.3.1"
+  resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-3.3.1.tgz#36adb4e0173f741df409bb4b69036d24a53bfb24"
+  integrity sha512-QuSiseNRJygaqAdABYFWn/H1CwIZCp9zp/PLid6yXvy6VcQV7OenEFF5XuYaCvSARe2Tg9r8Jqls5+fw1A9CbQ==
+  dependencies:
+    "@oclif/command" "^1.8.15"
+    "@oclif/config" "1.18.2"
+    "@oclif/errors" "1.3.5"
+    "@oclif/help" "^1.0.1"
+    chalk "^4.1.2"
+    indent-string "^4.0.0"
+    lodash "^4.17.21"
+    string-width "^4.2.0"
+    strip-ansi "^6.0.0"
+    widest-line "^3.1.0"
+    wrap-ansi "^6.2.0"
+
 "@oclif/screen@^1.0.3", "@oclif/screen@^1.0.4":
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/@oclif/screen/-/screen-1.0.4.tgz#b740f68609dfae8aa71c3a6cab15d816407ba493"