2017.05.23

Salesforceに接続するVisual Studio Code拡張機能の作成

Visual Studio CodeはMicrosoftによるオープンソース・クロスラットフォームのエディターです。
2016 JavaScript Rising Stars によると2016年にgithub上で最もスターを獲得したIDEとなっており最近勢いのあるエディターです。

今回はSalesforceに接続するVisual Studio Code拡張機能の作成方法についてご紹介します。
拡張機能を作成することで、多くのプロジェクトで使いまわしするような処理をVisual Studio Code自体に取り込むことができます。

まずはひな型の導入方法のご紹介と公式のHelloWorldのコード解説、
次に実践的な内容として「Visual Studio Code上でフォルダーを右クリックすることでSalesforce上の静的リソースへアップロード」という機能を作ってみます。
(完成したソースはここに置きました)

ひな型の導入

公式からYeomanを使ったVisual Studio code 拡張機能のひな型ジェネレーターが提供されていますのでそれを使いましょう。
まずYeoman とVS Code Extension generator をインストールします。

npm install -g yo generator-code

インストールが終わったら以下のコマンドを実行します。

yo code

次のような画面が表示されます。
yo

いくつかの質問に答えていくことでひな型が作成されます。

? What type of extension do you want to create?
作成する拡張機能の種類をカーソル上下で選択します。
今回は New Extension (TypeScript)を使用するのでそのままEnterを押します。

? What's the name of your extension?
今回はHelloWorldと入力しEnterを押します。

? What's the identifier of your extension? helloworld
拡張機能を公開する際のIDです。今回は公開しないのでそのままEnterを押します。
また、ここで指定した名前でディレクトリが作成されます。

? What's the description of your extension?
説明です。今回はそのままEnterを押します。

? What's your publisher name?
発行者の名前です。今回は公開しないのでそのままEnterを押します。

? Initialize a git repository? Yes
gitのリポジトリを作成するかどうかです。どちらでもいいですが今回はそのままEnterを押します

以上でひな型の作成が始まります。
ひな型の作成が終了すると
yoResult

と表示されますので

cd helloworld
code .

を実行すると、ひな型が作成されたディレクトリが開かれた状態でVisual Studio Codeが起動します。

なお現時点で以下のような構成になっています。
directoryTree

拡張機能を動かしてみる

作成されたひな型にはHello Worldを表示する拡張機能のサンプルが入っています。
まずはpackage.jsonを見てみましょう。

package.json

  "activationEvents": [
    "onCommand:extension.sayHello"
  ],

activationEventsというのは拡張機能が読み込まれるタイミングです。
Visual Studio Code起動時に自動的に全ての拡張機能が読み込まれるわけではありません。
ここでonCommandを指定すると、コマンドが実行された際に初めて拡張機能が読み込まれます。

    "contributes": {
        "commands": [{
            "command": "extension.sayHello",
            "title": "Hello World"
        }]
    },

contributesのcommandsにHello Worldというタイトルでextension.sayHelloというコマンドが記述されています。
ここに記述したコマンドはコマンドパレット(Visual Studio Code上でF1またはCtrl+Shift+Pで表示)に表示されます。

extension.sayHelloの実装はextensino.tsにあります。
extensino.tsを見てみましょう(コメントは除去してあります)。

src/extensino.ts

export function activate(context: vscode.ExtensionContext) {

    console.log('Congratulations, your extension "ve" is now active!');

    let disposable = vscode.commands.registerCommand('extension.sayHello', () => {
        vscode.window.showInformationMessage('Hello World!');
    });

    context.subscriptions.push(disposable);
}

ログを出力後、'Hello World!'というメッセージを表示する'extension.sayHello'というコマンドを登録しています。

最後の
context.subscriptions.push(disposable);
ですが、context.subscriptionsに追加された要素は拡張機能解放時に自動的にdisposeされます。

vscode.commands.registerCommandの第二引数がコマンド実行時に実際に行われる処理になります。

では実行してみましょう。
F5を押すとTypeScriptのコンパイルが走り、拡張機能開発モードで新規にVS Codeが起動します。

新しく立ち上がった方のVisual Studio CodeでF1を押しコマンドパレットを開き、一覧からHello Worldを選択しEnterを押すとコマンドが実行され

絞り込み

Hello World! と表示されます。

Hello World!

Salesforceに接続してみる

拡張機能からSalesforceに接続できるようにしてみましょう。
まずはJavaScriptからSalesforceのAPIを実行するためのライブラリJSforceをインストールします。

npm install jsforce;

なお「表示 => 統合ターミナル」を選択するかショートカット(WindowsであればCTRL+@)を押すとVisual Studio Code上でターミナルを開くことができます
terminal2

次にextension.tsを以下のように修正します。

src/extension.ts

'use strict';
import * as vscode from 'vscode';
import * as jsforce from 'jsforce';

export function activate(context: vscode.ExtensionContext) {
    let disposable = vscode.commands.registerCommand('extension.sayHello', async () => {

        //実際のユーザー名とパスワードを記述してください
        let loginResult = await new jsforce.Connection().login("ユーザー名", "パスワード");

        vscode.window.showInformationMessage(loginResult.organizationId);
    });

    context.subscriptions.push(disposable);
}

export function deactivate() {
}

salesforce組織にログインして取得した組織IDを表示しています。
ひな型としてTypeScriptを選択するとこのように非同期処理がasync/awaitですっきり書けます。

再びF5を押し新しく立ち上がった方のVisual Studio CodeでF1を押しコマンドパレットを開き、一覧からHello Worldを選択してみてください。
今度は"Hello World!"ではなくloginにより取得された組織IDが表示されるようになりました。

右クリックでデプロイ

Salesforceに接続できるようになりましたので、もうちょっと実践的に、
・Visual Studio Code上でフォルダーを右クリックからコマンドを選択するとフォルダーをzip圧縮して静的リソースにアップロード
・Salesforceへの接続情報は設定ファイルから読み込む
という拡張機能を作ってみましょう。

デプロイ用ディレクトリ作成

まずは静的リソースへアップロードするテストデータとして、適当な場所にdeployTestというディレクトリを作成し以下を実行します

echo abc > test1.txt 
mkdir hoge\fuga 
echo def > hoge\test2.txt 
echo ghi > hoge\test3.txt 
echo jkl > hoge\fuga\test4.txt 
echo mno > hoge\fuga\test5.txt

テストデータは以下のような構成になります。
testData

ではVisual Studio Codeに戻り拡張機能を作成していきます。
まず以下のライブラリのインストールします

npm install node-zip

package.jsonのcontributesを以下のように修正します

package.json

    "contributes": {
        "menus": {
            "explorer/context": [
                {
                    "command": "extension.sayHello",
                    "when": "explorerResourceIsFolder"
                }
            ]
        },
        "commands": [
            {
                "command": "extension.sayHello",
                "title": "静的リソースへアップロード"
            }
        ]
    },

"menus"の"explorer/context"にコマンドを追加することで、「Visual Studio Code上のエクスプローラー上で右クリックしたときに表示されるコンテキストメニュー」にコマンドが追加されます。
"when"で条件を指定することができます。
explorerResourceIsFolderは「右クリック対象がフォルダーだったとき」という意味です。
titleも"Hello World"ではあんまりなので"静的リソースへアップロード"に変更します。

次にextension.tsを以下のように修正します。

src/extension.ts

'use strict';
import * as vscode from 'vscode';
import * as jsforce from 'jsforce';
import * as fs from "fs";
import * as glob from "glob";
import * as Zip from "node-zip";

export function activate(context: vscode.ExtensionContext) {
    let disposable = vscode.commands.registerCommand('extension.sayHello', (sender) => {
        if (sender) deploy(sender.path.substring(1));
    });

    context.subscriptions.push(disposable);
}

export function deactivate() {
}

async function deploy(path: string) {
    //「出力 > OUTPUT」に"deploy log"を追加し表示
    let output = vscode.window.createOutputChannel("deploy log");
    output.show();
    try {
        //sfSetting.jsonから接続情報を取得
        let settings: { userName: string, password: string, url: string } = JSON.parse(fs.readFileSync(vscode.workspace.rootPath + "/sfSetting.json", 'utf8'));
        output.append("deploy " + path + "\r\n");

        //Salesforce組織にログイン
        output.append('Login...');
        let conn = new jsforce.Connection({ loginUrl: settings.url });
        conn.metadata.pollTimeout = 2000000;
        await conn.login(settings.userName, settings.password);
        output.append('OK\r\n');

        //静的リソースにアップロード
        output.append('deploy...');
        await conn.metadata.upsert('StaticResource', createMetaData(path));
        output.append('Completed!\r\n');
    } catch (ex) {
        output.append(JSON.stringify(ex.message));
    }
}

/**
 * 指定されたpath以下のファイルをzip圧縮しbase64文字列としてcontentに設定したMetaDataを作成
 */
function createMetaData(path: string) {
    let zip = new Zip();

    glob.sync(path + "/**/*.*").forEach((file) => {
        zip.file(file.replace(path + "/", ""), fs.readFileSync(file, 'utf8'));
    });

    return {
        fullName: path.split('/').pop(),
        content: zip.generate({ base64: true, compression: 'DEFLATE' }),
        contentType: 'application/zip'
    };
}

右クリックしたフォルダー内のファイルをzip圧縮し、base64文字列としてmetadata.upsertに渡しています。

F5を押して実行し、新しく立ち上がった方のVisual Studio Codeで「ファイル => フォルダーを開く」を選択し、作成したdeployTestを開きます。
deployTest直下に以下の内容で接続用設定ファイルsflogin.jsonを作成します。
sflogin.json

{  
    "userName": "ユーザー名",
    "password": "パスワード"
}

"userName","password"は静的リソースをアップロードしたい組織のものを指定してください。
また、https://login.salesforce.com 以外のログインURLを指定したい場合は

{  
    "userName": "ユーザー名",
    "password": "パスワード",
    "url":https://test.salesforce.com
}

のようにurlを指定してください。

エクスプローラー上のhogeフォルダーを右クリックし、コンテキストメニューから 「静的リソースへアップロード」を選択します。
rightClick

以下のように出力され、指定したフォルダーがzip圧縮されsflogin.jsonで指定した組織の静的リソースへアップロードされます。
resultLog

組織を確認してみましょう。

StaticResource

無事静的リソースにアップロードされました。

拡張機能の配置および公開

デバッグ実行せず通常起動したVisual Studio Codeから拡張機能が使えるようにするには、作成した拡張機能のフォルダー(今回はhelloworldフォルダー)を以下にコピーします。

Windows %USERPROFILE%.vscode\extensions
Mac ~/.vscode/extensions
Linux ~/.vscode/extensions

また、作成した拡張機能は公式のマーケットプレイスで公開することができます。
公開方法については以下をご参照ください。
Publishing Extensions

以上、Salesforceに接続するVisual Studio Code拡張機能の作成方法についてのご紹介でした。

1 件
     
  • banner
  • banner

関連する記事