[GAS] claspを利用した開発環境構築

## はじめに
GASを使う機会があり、折角なのでTypeScriptで開発できるようにするため  
環境構築について調査した内容をまとめました。

## 環境
- Windows 11 Pro
- Node.js v20.17.0
- NPM 9.8.0
- clasp v2.4.2 
## フォルダ構造
```
GAS-TS-PJT
├── dist
│   └── appsscript.json
├── node_modules
├── src
│   ├── App.ts
│   └── main.ts
├── .clasp.json
├── esbuild.js
├── package-lock.json
├── package.json
└── tsconfig.json
```

## GAS + TypeScriptの開発環境構築
### 1. 必要なパッケージの準備
#### プロジェクトフォルダを作成し、配下に移動する
```bash
mkdir GAS-TS-PJT
```
```bash
cd GAS-TS-PJT
```
#### package.jsonファイルの作成
```bash
npm init -y
``` 
- package.jsonが作成される
#### claspのインストール
```bash
npm install -g @google/clasp
``` 
- コマンドとして利用するにはグローバルにインストールする必要があるので注意

#### TypeScriptと必要なパッケージのインストール
```bash
npm install -D typescript @types/google-apps-script
```
- コマンド実行後に下記2種が自動生成されます
  - node_modules
  - pakage-lock.json

#### tsconfig.jsonファイルの作成
```bash
npx tsc --init
```
- コマンド実行後に下記ファイルが自動生成されます
  - tsconfig.json
#### tsconfig.jsonファイルへの追記
```json:tsconfig.json
{
    "compilerOptions": {
        "lib": ["esnext"],
        "experimentalDecorators": true
    },
    "include": ["./src"],
}
```
- 上記に関しては、[clasp公式](https://github.com/google/clasp/blob/master/docs/typescript.md)を参照

#### ビルドに利用するパッケージのインストール
```bash
npm install -D esbuild esbuild-gas-plugin
```

### 2. ビルド用スクリプト(esbuild.js)の作成

```bash
touch esbuild.js
```
  
```javascript:esbuild.js
import esbuild from "esbuild";
import { GasPlugin } from "esbuild-gas-plugin";

esbuild
    .build({
        entryPoints: ["./src/main.ts"],
        bundle: true,
        minify: true,
        outfile: "./dist/main.js",
        plugins: [GasPlugin],
    })
    .catch((error) => {
        console.log('ビルドに失敗しました')
        console.error(error);
        process.exit(1);
    });
```
 - ビルド用スクリプトは、[こちら](https://zenn.dev/funteractiveinc/articles/776b5812833475)を参考にさせていただきました

### 3. claspを用いてのGASとの連携
#### GASの有効化
[設定ページ](https://script.google.com/home/usersettings)にてAPIを有効化する

#### claspコマンドを利用し、Googleアカウントに接続する 
```bash
clasp login
```
- コマンドを実行すると、自動でブラウザが立ち上がるので表示に従い認証を行う
  1. 利用するアカウントの選択
  2. claspがログインしても良いかの確認
  3. claspがアクセスできる情報の選択
  4. 認証に成功すると、ブラウザ上に以下のワードが表示される
       - 「Logged in! You may close this page.」

#### claspコマンドを利用し、Google Accountサーバ上にプロジェクトを作成する
```bash
clasp create --type standalone --title "GAS-Project-Name"
```
- コマンドを実行すると以下の処理が走ります
  - Apps Scriptへアクセスすると、新しいプロジェクトが作成される
    - ブラウザでApps Scriptへアクセスすると確認可能
  - 以下２種のファイルがローカルに自動生成される
    - .clasp.json
    - appsscript.json

#### distフォルダの作成
```bash
mkdir dist
```

#### 「.clasp.json」の"rootDir"を編集
```json:.clasp.json
{
    "rootDir": "./dist"
}
```
- "rootDir"に対してdistフォルダを指定する

#### 「appsscript.json」をdistフォルダへ移動
```bash
mv appsscript.json ./dist/appsscript.json
```
#### 「appsscript.json」のタイムゾーン修正
```json:appsscript.json
{
    "timeZone": "Asia/Tokyo",
}
```
- デフォルトだと、"America/New_York"になっているため修正する

### 4. package.jsonの編集
#### "type"の追加
```json:package.json
{
    "type": "module",
    "main": "index.js",
}
```
- TSコード内で、import・exportを利用可能にするための設定

#### "main"の編集
```json:package.json
{
    "type": "module",
    "main": "./src/main.ts",
}
```
- デフォルトだと、"index.js"が指定されているので修正する

#### ビルドやデプロイ用コマンドの追加
```json:package.json
{
    "type": "module",
    "main": "./src/main.ts",
    "scripts": {
        "build": "node esbuild.js",
        "push": "clasp push",
        "open": "clasp open", 
        "deploy": "npm run build && npm run push"
    },
}
```
### 5. エントリーポイントの準備
#### srcフォルダの作成
```bash
mkdir src
```
#### App.tsの作成
```bash
touch ./src/App.ts
```
```typescript:./src/App.ts
export const App = () => {
    // この中にTypeScriptで処理や、関数の呼び出しを行う
    console.log("test");
};
```

#### main.tsの作成
```bash
touch ./src/main.ts
```
```typescript:.src/main.ts
import { App } from "./App";

interface Global {
    App: typeof App;
}
declare const global: Global;
// entryPoints
global.App = App;
```
- GAS上で関数Appの実行を可能にするためには  
  グローバルオブジェクトに渡す必要があるため型定義した上で記載する

### 6. ビルド方法
#### デプロイ
```
npm run deploy
```
- 最初のプッシュ時にのみ、以下のように問われるので、"y"で返答する
  - 「Manifest file has been updated. Do you want to push and overwrite?」
##### 発生する処理詳細
1. TypeScriptのコードからJavaScriptファイルをdist配下に作成
2. distフォルダ内のファイルをApps Scriptへ自動反映する

#### App Scriptの立ち上げ
```
npm run open
```
- コマンドを実行すると自動でブラウザが立ち上がり、作成したプロジェクトが表示される

## 開発中の所感
### TypeScriptでの開発が捗る！
GAS特有の型の参照が行えるため、VScodeでの開発がしやすいです。  
TypeScriptの強固な型付けの恩恵もあります。

### ファイル分けのしやすさ
関数や型を別ファイルに分けて書けるので非常に管理がしやすいです。  
#### ファイル分けの一例
```
├── src
│   ├── config
│   │   └── settings.ts
│   ├── lib
│   │   └── gasProcessMethod.ts
│   ├── types
│   │   └── types.ts
│   ├── App.ts
│   └── main.ts
```
私は開発時には、上記のようにsrcフォルダ配下でフォルダ分けして  
lib配下のファイルに記載した関数をApp.tsファイルで呼び出す形にしています。



## 参考
### 開発環境構築に関して
- TypeScript+clasp+esbuildでGASのローカル開発をもっと便利に
  - https://zenn.dev/funteractiveinc/articles/776b5812833475
- GAS + Typescript のいい感じのビルド環境を整える
  - https://zenn.dev/terass_dev/articles/a39ab8d0128eb1
- CommonJSとES Modulesについてまとめる
  - https://zenn.dev/yodaka/articles/596f441acf1cf3
### claspに関して
- clasp でコマンドライン インターフェースを使用する
  - https://developers.google.com/apps-script/guides/clasp?hl=ja
- clasp環境構築に必要なもの
  - https://qiita.com/boccham/items/5fa13488c1fd15d96f76