ブックマークに登録するJavaScriptスクリプトをTypeScriptで書き直してみた

2022.08.21

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 IoT事業部の若槻です。

以前に次のようなエントリを投稿しました。

その中でJavaScriptスクリプトを作成してGoogle Chromeのブックマークに登録して使用したのですが、JavaScriptだとメンテナンス時に型支援が無いのが厳しいのでTypeScriptを使いたくなりました。

そこで今回は、そのJavaScriptスクリプトをTypeScriptで書き直してみました。

やってみた

以前のスクリプトは下記になります。JavaScriptで記述したものをコンパイルなどせずそのままブックマークに登録しています。

script.js

javascript: (() => {
  const cookies = document.cookie;
  const cookiesArray = cookies.split(';');
  const targetCookieName = 'noflush_awsc-roleInfo';

  for (const c of cookiesArray) {
    const cArray = c.split('=');
    if (cArray[0].trim() == targetCookieName) {
      const decoded = decodeURIComponent(cArray[1]);
      const parsed = JSON.parse(decoded);
      const roleList = parsed.rl;
      if (roleList.length === 0) {
        window.alert('削除可能なスイッチロール履歴が見つかりませんでした。');
        return;
      };

      var roleListText = '';
      var selectableNumArray = [];
      roleList.forEach((role, i) => {
        roleListText = `${roleListText}\n${i + 1} ${role.d}`;
        selectableNumArray.push((i + 1).toString());
      });
      var loopFlag = true;
      var input = undefined;
      do {
        input = window.prompt(
          `削除したいロール(表示名)を番号で指定して下さい。${roleListText}`
        );
        if (selectableNumArray.includes(input)) {
          if (
            !window.confirm(
              `${input} ${roleList[Number(input) - 1].d} を削除しますか?`
            )
          ) {
            window.alert('削除を中止しました。');
            return;
          };
          loopFlag = false;
        } else if (input === null) {
          window.alert('削除を中止しました。');
          return;
        } else {
          window.alert(
            `1〜${selectableNumArray.slice(-1)[0]}の間の番号を指定して下さい。`
          );
        };
      } while (loopFlag);

      const finAlertText = `${input} ${
        roleList[Number(input) - 1].d
      } をスイッチロール履歴から削除しました。`;
      roleList.splice(Number(input) - 1, 1);
      parsed.rl = roleList;

      const stringified = JSON.stringify(parsed);
      const encoded = encodeURIComponent(stringified);
      document.cookie = `${targetCookieName}=${encoded};domain=.aws.amazon.com;path=/`;
      window.alert(finAlertText);

      return;
    };
  };

  window.alert('削除可能なスイッチロール履歴が見つかりませんでした。');
})();

ファイル名をscript.jsからscript.tsに変更します。

mv script.js script.ts

するとエラーがいくつか出るようになりました。

まず下記のdocumentのエラーを対応してみます。

Cannot find name 'document'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.

記載に従いtsconfig.jsoncompilerOptions > libdomを追加します。

tsconfig.json

{
  "compilerOptions": {
    "lib": [
      "dom"
    ]
  }
}

するとdocumentと、それに加えてwindowのエラーも抑制できました。

その他のエラーはType Errorだったのでスクリプトのコードを手直ししました。最終的なTypeScriptコードは下記となります。ハイライトが修正箇所です。(ついでにvarletの修正もしています。)

script.ts

javascript: (() => {
  interface Role {
    a: string;
    c: string;
    d: string;
    r: string;
  }

  const cookies = document.cookie;
  const cookiesArray = cookies.split(';');
  const targetCookieName = 'noflush_awsc-roleInfo';

  for (const c of cookiesArray) {
    const cArray = c.split('=');
    if (cArray[0].trim() == targetCookieName) {
      const decoded = decodeURIComponent(cArray[1]);
      const parsed = JSON.parse(decoded);
      const roleList = parsed.rl;
      if (roleList.length === 0) {
        window.alert('削除可能なスイッチロール履歴が見つかりませんでした。');
        return;
      }

      let roleListText = '';
      let selectableNumArray: string[] = [];
      roleList.forEach((role: Role, i: number) => {
        roleListText = `${roleListText}\n${i + 1} ${role.d}`;
        selectableNumArray.push((i + 1).toString());
      });
      let loopFlag = true;
      let input: string | null = null;
      do {
        input = window.prompt(
          `削除したいロール(表示名)を番号で指定して下さい。${roleListText}`
        );
        if (input !== null && selectableNumArray.includes(input)) {
          if (
            !window.confirm(
              `${input} ${roleList[Number(input) - 1].d} を削除しますか?`
            )
          ) {
            window.alert('削除を中止しました。');
            return;
          }
          loopFlag = false;
        } else if (input === null) {
          window.alert('削除を中止しました。');
          return;
        } else {
          window.alert(
            `1〜${selectableNumArray.slice(-1)[0]}の間の番号を指定して下さい。`
          );
        }
      } while (loopFlag);

      const finAlertText = `${input} ${
        roleList[Number(input) - 1].d
      } をスイッチロール履歴から削除しました。`;
      roleList.splice(Number(input) - 1, 1);
      parsed.rl = roleList;

      const stringified = JSON.stringify(parsed);
      const encoded = encodeURIComponent(stringified);
      document.cookie = `${targetCookieName}=${encoded};domain=.aws.amazon.com;path=/`;
      window.alert(finAlertText);

      return;
    }
  }

  window.alert('削除可能なスイッチロール履歴が見つかりませんでした。');
})();

tscでトランスパイルします。

npx tsc script.ts

トランスパイル後のコードです。javascript: (() => {...})();の記述がうまくトランスパイスできるか心配でしたが、できていますね。

script.js

javascript: (function () {
    var cookies = document.cookie;
    var cookiesArray = cookies.split(';');
    var targetCookieName = 'noflush_awsc-roleInfo';
    var _loop_1 = function (c) {
        var cArray = c.split('=');
        if (cArray[0].trim() == targetCookieName) {
            var decoded = decodeURIComponent(cArray[1]);
            var parsed = JSON.parse(decoded);
            var roleList = parsed.rl;
            if (roleList.length === 0) {
                window.alert('削除可能なスイッチロール履歴が見つかりませんでした。');
                return { value: void 0 };
            }
            var roleListText_1 = '';
            var selectableNumArray_1 = [];
            roleList.forEach(function (role, i) {
                roleListText_1 = roleListText_1 + "\n" + (i + 1) + " " + role.d;
                selectableNumArray_1.push((i + 1).toString());
            });
            var loopFlag = true;
            var input = null;
            do {
                input = window.prompt("\u524A\u9664\u3057\u305F\u3044\u30ED\u30FC\u30EB\uFF08\u8868\u793A\u540D\uFF09\u3092\u756A\u53F7\u3067\u6307\u5B9A\u3057\u3066\u4E0B\u3055\u3044\u3002" + roleListText_1);
                if (input !== null && selectableNumArray_1.includes(input)) {
                    if (!window.confirm(input + " " + roleList[Number(input) - 1].d + " \u3092\u524A\u9664\u3057\u307E\u3059\u304B\uFF1F")) {
                        window.alert('削除を中止しました。');
                        return { value: void 0 };
                    }
                    loopFlag = false;
                }
                else if (input === null) {
                    window.alert('削除を中止しました。');
                    return { value: void 0 };
                }
                else {
                    window.alert("1\u301C" + selectableNumArray_1.slice(-1)[0] + "\u306E\u9593\u306E\u756A\u53F7\u3092\u6307\u5B9A\u3057\u3066\u4E0B\u3055\u3044\u3002");
                }
            } while (loopFlag);
            var finAlertText = input + " " + roleList[Number(input) - 1].d + " \u3092\u30B9\u30A4\u30C3\u30C1\u30ED\u30FC\u30EB\u5C65\u6B74\u304B\u3089\u524A\u9664\u3057\u307E\u3057\u305F\u3002";
            roleList.splice(Number(input) - 1, 1);
            parsed.rl = roleList;
            var stringified = JSON.stringify(parsed);
            var encoded = encodeURIComponent(stringified);
            document.cookie = targetCookieName + "=" + encoded + ";domain=.aws.amazon.com;path=/";
            window.alert(finAlertText);
            return { value: void 0 };
        }
    };
    for (var _i = 0, cookiesArray_1 = cookiesArray; _i < cookiesArray_1.length; _i++) {
        var c = cookiesArray_1[_i];
        var state_1 = _loop_1(c);
        if (typeof state_1 === "object")
            return state_1.value;
    }
    window.alert('削除可能なスイッチロール履歴が見つかりませんでした。');
})();

上記スクリプトをGoogle Chromeのブックマークに登録します。

登録したブックマークをAWSマネジメントコンソールで開くと、問題なく動いています!

おわりに

ブックマークに登録するJavaScriptスクリプトをTypeScriptで書き直してみました。

今後はブックマークに登録するスクリプトのソースコードは、今回の要領でTypeScriptで記述するようにしていきたいです。

以上