今回はKintone-cliを使用してKintone-UI-Component+React+Typescript+Firebaseのアプリのカストマイズを作成したいんです。
kintone-cli
kintone-cliを使用するのでインストールします:
$ npm install -g git://github.com/kintone/kintone-cli.git
プロジェクトの初期化
kintone-cli initでプロジェクトを初期化します、対話式で下記の質問されます:
- 
Project name:プロジェクト名を決めて入力し、 - 
Version:バージョン番号を決めて入力し、 - 
Description:プロジェクトの詳細を入力し、 - 
Author:プロジェクトの作者を入力し、 - 
License:ライセンスの種類を入力し、 - 
Do you want to use @kintone/kintone-ui-component?(_kintone UI Component_を利用するかどうか:
利用したいから「Y」を入力し、 - 
Do you want to use @kintone/kintone-js-sdk?(_kintone JS SDK_を使用するかどうか):
@kintone/kintone-js-sdkは既にdeprecatedですので「n」を入力し、現在の最新のkintoneのSDKを使いたっかった後から@kintone/rest-api-clientを手動で追加すれば良いです。 
$ kintone-cli init
Welcome to kintone-cli!
Please, input below information so we can get started!
? Project name user-management
? Version 0.0.1
? Description App to manage users
? Author LETEXIER Loic
? License Copyrights Meister Guild 2020
? Do you want to use @kintone/kintone-ui-component? Yes
? Do you want to use @kintone/kintone-js-sdk? No
ここまでの手順で:
- プロジェクトを格納するフォルダを作成し、
 - その中に
package.jsonファイルを作成し、 - 
gitリポジトリの初期化しました。 
プロジェクトの作成
次は実際にプロジェクトを作成します、対話式で下記の質問されます:
- 
What type of app you want to create ?(アプリ向けのカスタマイズ開発か、プラグイン開発か):アプリ向けを選択し、今回はカスタマイズ開発がしたい、 - 
Do you want to set authentication credentials ?(認証情報をセットするかどうか): 認証を利用したいから「Y」を入力し、 - 
What is your kintone domain ?:カスタマイズを適用する先のkintoneドメイン(○○.cybozu.com)の指定し、 - 
What is your kintone username ?:当該環境にログインするためのユーザー名(私はメールアドレスと一緒にしてた)を入力し、 - 
What is your kintone password ?:当該環境にログインするためのパスワードを入力し、 - 
Do you use proxy ?(接続にプロキシを使うかどうか):「n」を入力し、 - 
Do you want to use React ?(開発フレームワークとしてReactを使うかどうか):_kintone UI Component_を使う場合はReactが必よから「Y」を入力し、 - 
Do you want to use TypeScript ?(TypeScriptを使用するかどうか):TypeScriptを使用したいから「Y」を入力し、 - 
Do you want to use webpack ?(バンドラーとしてWebpackを使うかどうか):使用したいから「Y」を入力し、 - 
What is the entry for webpack ?:Webpackを使用する際のエントリポイントとなるファイルの名前(「index.tsx」のデフォルトは良かったからそのままにした)を入力し、 - 
What is the app name ?(ローカルプレビュー時やビルド・デプロイ時にも必要なアプリのフォルダーの名前):プロジェクトと同じ名前に入力し、 - 
Do you want to use @cybozu/eslint-config for syntax checking ?(サイボウズ謹製の eslint 設定を利用するかどうか):「n」を入力したけど「Y」を入力してもよいと思います、 - 
What is the app ID ?:カスタマイズを適用するアプリの「アプリ ID」を入力し、 - 
What is the scope of customization ?(カスタマイズをアプリの利用者全員に適用するか、管理者だけにするか、適用しないか):「ALL」を選択しました。 
> cd user-management
> kintone-cli create-template
? What type of app you want to create ? Customization
? Do you want to set authentication credentials ? Yes
? What is your kintone domain ? ○○.cybozu.com
? What is your kintone username ? □□@○○.com
? What is your kintone password ? [hidden]
? Do you use proxy ? No
? Do you want to use React ? Yes
? Do you want to use TypeScript ? Yes
? Do you want to use webpack ? Yes
? What is the entry for webpack ? index.tsx
? What is the app name ? user-management
? Do you want to use @cybozu/eslint-config for syntax checking ? No
? What is the app ID ? 123
? What is the scope of customization ? ALL
@kintone/dts-gen
TypeScriptの開発ではJavaScriptで書かれたAPIを使用するためにd.tsファイル(型定義ファイル)は大事です。
@kintone/dts-genはこの型定義ファイルを作成してくれるツールです:
@kintone/dts-genはkintoneのJavaScriptカスタマイズ用の関数定義に加えて、指定したアプリからフィールド情報を取り出すコマンドラインツールが同梱されています。
TypeScriptでkintoneの開発をするなら必須なものですのでインストールします:
$ npm install --save-dev @kintone/dts-gen
使い方は:
npx kintone-dts-gen --host https://(サブドメイン).cybozu.com
                      -u (ユーザー名)
                      -p (パスワード)
                      --app-id (アプリID)
                      --namespace (名前空間プレフィクス)
                      -o (ファイル出力先)
下記のコマンドでアプリのフィールド定義情報を取得して、d.tsファイルを作成します:
$ npx kintone-dts-gen --host https://mgild.cybozu.com -u l.loic@m-gild.com -p ******** --app-id 123 --namespace userFields.types -o user-management/source/users.fields.d.ts
d.tsの型定義ファイルを作成して、エディタ上でその効果を発揮させるためプロジェクトの直下にあるtsconfig.jsonで型定義ファイルの参照を指定する必要です:
...
    "files": [
        "../node_modules/@kintone/dts-gen/kintone.d.ts",
        "./source/users.fields.d.ts"
    ],
    "exclude": [
        "node_modules",
        "dist"
    ]
...
これを TypeScript で参照可能にします。
常に、ビルドしたファイルが格納されるdistフォルダーをexcludeに追加します。
firebase
このアプリでfirebaseも利用したいのでインストールします:
$ npm install --save firebase  
CSS
CSSファイルを使用するためにentryに追加しないといけません:
...
  entry: [
    path.resolve('user-management/source/index.tsx'),
    path.resolve('user-management/source/css/user-management.css')
  ],
...
ビルド + デプロイ
ビルドします:
$ kintone-cli build --app-name user-management
デプロイします:
$ kintone-cli deploy --app-name user-management
アプリ側にはちゃんとビルドされたファイルが適用されます。
結果のファイルの一覧
プロジェクト設定完了!
プロジェクトフォルダー
package.json
{
    "name": "user-management",
    "version": "0.0.1",
    "description": "App to manage users",
    "author": "LETEXIER Loic",
    "license": "Copyrights Meister Guild 2020",
    "dependencies": {
        "@kintone/kintone-ui-component": "^0.6.0",
        "firebase": "^7.22.1",
        "react": "^16.8.6",
        "react-dom": "^16.7.0"
    },
    "devDependencies": {
        "@babel/core": "^7.3.3",
        "@babel/plugin-proposal-class-properties": "^7.3.3",
        "@babel/plugin-syntax-dynamic-import": "^7.2.0",
        "@babel/preset-env": "^7.3.1",
        "@babel/preset-react": "^7.0.0",
        "@babel/preset-typescript": "^7.3.3",
        "@kintone/customize-uploader": "^2.0.5",
        "@kintone/dts-gen": "^3.0.5",
        "@types/react": "^16.8.16",
        "@types/react-dom": "^16.8.4",
        "babel-loader": "^8.0.5",
        "core-js": "^3.2.1",
        "css-loader": "^2.1.0",
        "dotenv-webpack": "^3.0.0",
        "local-web-server": "^2.6.1",
        "regenerator-runtime": "^0.13.3",
        "style-loader": "^0.23.1",
        "typescript": "^3.6.3",
        "webpack": "^4.30.0",
        "webpack-cli": "^3.2.3"
    },
    "scripts": {
        "dev": "ws",
        "build-user-management": "webpack --config user-management/webpack.config.js"
    }
.gitignore
node_modules
user-management/auth.json
アプリフォルダー
webpack.config.js
const path = require('path');
const config = {
  entry: [
    path.resolve('user-management/source/index.tsx'),
    path.resolve('user-management/source/css/user-management.css')
  ],
  resolve: {
    extensions: ['.ts', '.tsx', '.js'],
  },
  output: {
    path: path.resolve('user-management/dist'),
    filename: 'user-management.min.js',
  },
  module: {
    rules: [
      {
        test: /.ts?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-typescript'],
          },
        },
      },
      {
        test: /.tsx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/react', '@babel/preset-typescript'],
          },
        },
      },
      {
        test: /.css$/,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
  performance: {
    maxEntrypointSize: 10000000,
    maxAssetSize: 10000000,
  },
};
module.exports = (env, argv) => {
  'use strict';
  if (argv.mode === 'development') {
    config.devtool = 'source-map';
    false;
  }
  if (argv.mode === 'production') {
    //...
  }
  return [config];
};
tsconfig.json
{
    "compilerOptions": {
        "typeRoots": [
            "../node_modules/@types",
            "./source/global.d.tsx"
        ],
        "noImplicitAny": false,
        "jsx": "react"
    },
    "include": [
        "source/**/*.ts",
        "source/**/*.tsx"
    ],
    "files": [
        "../node_modules/@kintone/dts-gen/kintone.d.ts",
        "./source/users.fields.d.ts"
    ],
    "exclude": [
        "node_modules",
        "dist"
    ]
}
config.json
{
    "appID": 123,
    "appName": "user-management",
    "type": "Customization",
    "scope": "ALL",
    "uploadConfig": {
        "desktop": {
            "js": [
                "user-management/dist/user-management.min.js"
            ],
            "css": []
        },
        "mobile": {
            "js": [
                "user-management/dist/user-management.min.js"
            ]
        }
    }
}
.babelrc
{
    "plugins": [
        "@babel/plugin-proposal-class-properties",
        "@babel/plugin-syntax-dynamic-import"
    ],
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "usage",
                "corejs": {
                    "version": 3,
                    "proposals": true
                }
            }
        ]
    ]
}
ソースフォルダー
users.fields.d.ts
declare namespace userFields.types {
  interface Fields {
    password: kintone.fieldTypes.SingleLineText;
    email_address: kintone.fieldTypes.SingleLineText;
    user_name: kintone.fieldTypes.DropDown;
    idToken: kintone.fieldTypes.SingleLineText;
  }
  interface SavedFields extends Fields {
    $id: kintone.fieldTypes.Id;
    $revision: kintone.fieldTypes.Revision;
    更新者: kintone.fieldTypes.Modifier;
    作成者: kintone.fieldTypes.Creator;
    レコード番号: kintone.fieldTypes.RecordNumber;
    更新日時: kintone.fieldTypes.UpdatedTime;
    作成日時: kintone.fieldTypes.CreatedTime;
  }
}