UNPKG

kintone-as-code

Version:

A CLI tool for managing kintone applications as code with type-safe TypeScript schemas

458 lines (357 loc) 14.6 kB
# kintone-as-code kintoneアプリの設定をコードで管理し、Effect-TSによる型安全性を実現するCLIツールです。 ## アーキテクチャ(要約) - Functional Core, Imperative Shell を採用 - Coreは純関数(`src/query/*`): 式、フィールド、ビルダー(FP)、バリデーション - Shellは副作用(`src/cli.ts`, `src/commands/*`, 生成器) - 公開APIはFPのみ。OOファサードは提供しません(メソッドチェーンの `createQuery()` は生成物 `apps/{name}.query.ts` が持つヘルパであり、パッケージの公開APIではありません) ## 特徴 - 🔒 **型安全** - kintone-effect-schemaによる完全なTypeScriptサポート - 📝 **kintoneからエクスポート** - 既存アプリからスキーマファイルを生成 - 🔧 **環境管理** - 複数のkintone環境をサポート - 🎯 **Effect-TS対応** - Effect-TSの強力なスキーマバリデーション機能 - 📋 **レコードスキーマ生成** - コピペ可能な静的レコードスキーマを自動生成 ## インストール ```bash npm install -g kintone-as-code ``` ## 必要条件 - Node.js 18以上 - APIアクセス可能なkintone環境 ## クイックスタート より丁寧な手順は `docs/getting-started.ja.md` を参照してください。以下は最小手順です。 ### 1. プロジェクトの初期化 ```bash kintone-as-code init ``` 環境設定を含む`kintone-as-code.config.js`ファイルが作成されます。 ### 2. 既存アプリのエクスポート ```bash # 基本(デフォルトで query / record-schema も生成) kintone-as-code export --app-id 123 --name customer-app # 生成を抑止 kintone-as-code export --app-id 123 --name customer-app --no-query kintone-as-code export --app-id 123 --name customer-app --no-record-schema # 関連/サブテーブルの限定公開(in/not in のみ) kintone-as-code export --app-id 123 --name customer-app \ --include-related \ --include-subtable ``` 以下のファイルが生成されます: - `apps/customer-app.schema.ts` - 完全に型付けされたフィールド定義 - `apps/customer-app.record-schema.ts` - 静的な型安全レコードスキーマ(そのままコピペで利用可能) - `apps/customer-app.query.ts` - kintone API用の型安全なクエリビルダー(デフォルトで生成) - `--include-related` 指定時は `REFERENCE_TABLE``displayFields``createTableSubField('親.子')` で最小API公開(`in/not in` のみ) - `--include-subtable` 指定時はサブテーブル子フィールドを同様に最小APIで公開 ### 3. アプリスキーマの定義 エクスポートされたスキーマは、完全な型安全性のためにkintone-effect-schemaを使用します: ```typescript import { defineAppSchema } from 'kintone-as-code'; import { APP_IDS } from './utils/app-ids'; import type { SingleLineTextFieldProperties, NumberFieldProperties, SubtableFieldProperties, } from 'kintone-effect-schema'; // 完全な型情報を持つ個別フィールド定義 export const 会社名Field: SingleLineTextFieldProperties = { type: 'SINGLE_LINE_TEXT', code: '会社名', label: '会社名', required: true, unique: true, maxLength: '100', }; export const 売上高Field: NumberFieldProperties = { type: 'NUMBER', code: '売上高', label: '年間売上高', unit: '円', unitPosition: 'AFTER', }; // ネストされたフィールドを持つサブテーブル export const 商品リストField: SubtableFieldProperties = { type: 'SUBTABLE', code: '商品リスト', fields: { 商品名: { type: 'SINGLE_LINE_TEXT', code: '商品名', label: '商品名', required: true, }, 単価: { type: 'NUMBER', code: '単価', label: '単価', unit: '円', }, }, }; // アプリフィールド設定 export const appFieldsConfig = { properties: { 会社名: 会社名Field, 売上高: 売上高Field, 商品リスト: 商品リストField, }, }; // アプリスキーマ定義 export default defineAppSchema({ // APP_IDS 方式(推奨: 生成物に合わせて一元管理) appId: APP_IDS.CUSTOMER_APP, name: '顧客管理', description: '顧客情報管理アプリ', fieldsConfig: appFieldsConfig, }); ``` ## 設定 ### アプリIDの管理 `utils/app-ids.ts` にアプリIDをまとめて管理します(`export const APP_IDS = { ... } as const;`)。`export` 実行時に自動更新されます。 ### 設定ファイル `kintone-as-code.config.js`: ```javascript export default { default: 'production', environments: { production: { auth: { baseUrl: process.env.KINTONE_BASE_URL!, username: process.env.KINTONE_USERNAME, password: process.env.KINTONE_PASSWORD, }, }, development: { auth: { baseUrl: process.env.KINTONE_BASE_URL!, username: process.env.KINTONE_USERNAME, password: process.env.KINTONE_PASSWORD, }, }, }, }; ``` ## kintone-effect-schemaとの統合 このツールは[kintone-effect-schema](https://github.com/Kensei-Kimoto/kintone-effect-schema)とシームレスに連携し、以下を提供します: - すべてのkintoneフィールドタイプの完全な型定義 - Effect-TSを使用したランタイムバリデーション - 日本語フィールドコードのサポート - 空値の自動処理 ## コマンド ### ドキュメント索引 - 概要(IaCの全体像): `docs/overview.ja.md` - 設定: `docs/config.ja.md` - 生成/レコードスキーマ: `docs/converter-and-schemas.ja.md` - Export/Apply/Create: `docs/export-apply-create.ja.md` - クエリビルダー: `docs/query-builder.ja.md` - クエリ クックブック: `docs/query-cookbook.ja.md` - アーキテクチャ: `docs/architecture.ja.md` ### init 新しいkintone-as-codeプロジェクトを初期化: ```bash kintone-as-code init [options] オプション: -f, --force 既存ファイルを強制的に上書き ``` ### export kintoneアプリ設定をTypeScriptにエクスポート: ```bash kintone-as-code export [options] オプション: --app-id <id> エクスポートするアプリID(必須) --name <name> スキーマファイル名(必須) --env <env> 環境名 --output <dir> 出力ディレクトリ(デフォルト: "apps") --with-record-schema レコードスキーマファイルを生成(デフォルト: true) --no-record-schema レコードスキーマ生成をスキップ --with-query クエリビルダーファイルを生成(デフォルト: true) --no-query クエリビルダー生成をスキップ ``` exportコマンドはデフォルトで3つのファイルを生成します: 1. **フィールドスキーマ** (`{name}.schema.ts`) - フィールド定義と設定 2. **レコードスキーマ** (`{name}.record-schema.ts`) - Effect Schemaによる型安全なレコードバリデーション 3. **クエリビルダー** (`{name}.query.ts`) - kintone REST API用の型安全なクエリビルダー ### apply スキーマを既存のkintoneアプリに適用: ```bash kintone-as-code apply [options] オプション: --app-id <id> 適用先のアプリID(省略可。指定がない場合はスキーマの appId を使用) --schema <path> スキーマファイルパス(必須) --env <env> 環境名 ``` ### create スキーマから新しいkintoneアプリを作成: ```bash kintone-as-code create [options] オプション: --schema <path> スキーマファイルパス(必須) --name <name> アプリ名(スキーマの名前を上書き) --env <env> 環境名 --space <id> スペースID(オプション) --thread <id> スレッドID(スペース内で作成する場合) ``` ## レコードスキーマの使用方法 生成されたレコードスキーマはkintoneレコードの型安全なバリデーションと自動正規化を提供します: ```typescript import { KintoneRestAPIClient } from '@kintone/rest-api-client'; import { validateRecord, type AppRecord, } from './apps/customer-app.record-schema'; // クライアントの初期化 const client = new KintoneRestAPIClient({ baseUrl: process.env.KINTONE_BASE_URL!, auth: { username: process.env.KINTONE_USERNAME!, password: process.env.KINTONE_PASSWORD!, }, }); // レコードの取得とバリデーション(自動正規化付き) const response = await client.record.getRecord({ app: 123, id: 1, }); const validatedRecord: AppRecord = validateRecord(response.record); // validatedRecord は完全に型付け&正規化されています(型アサーション不要) // 数値フィールドの空文字列 → null、undefined → '' など // 複数レコードの検証 const recordsResponse = await client.record.getRecords({ app: 123, query: 'limit 100', }); const validatedRecords = recordsResponse.records.map((record) => validateRecord(record) ); ``` ### 生成されるレコードスキーマの例(シンプル) ```ts import { Schema } from 'effect'; import { SingleLineTextFieldSchema, NumberFieldSchema, decodeKintoneRecord, } from 'kintone-effect-schema'; // 静的出力の例 export const RecordSchema = Schema.Struct({ title: SingleLineTextFieldSchema, amount: NumberFieldSchema, }); export type AppRecord = Schema.Schema.Type<typeof RecordSchema>; export const validateRecord = (record: Record<string, unknown>): AppRecord => { const normalized = decodeKintoneRecord(record); return Schema.decodeUnknownSync(RecordSchema)(normalized); }; ``` ### JavaScript API利用時(カスタマイズ) ```typescript import { validateRecord, type AppRecord, } from './apps/customer-app.record-schema'; kintone.events.on('app.record.detail.show', (event) => { // 同じ関数でJavaScript APIも処理可能 const validatedRecord: AppRecord = validateRecord(event.record); // すべての空値の不整合を自動的に処理 // 型安全にアクセス console.log(validatedRecord.会社名.value); return event; }); ``` ### ポイント - **validateRecord**: REST API・JavaScript API両方で使用可能(自動正規化あり) - **validateRecordWithCustomRules**: カスタムルール + 自動正規化 - どちらのAPIでも同じ関数で安全に処理できます! ## クエリビルダーの使用方法 生成されたクエリビルダーはIDEの自動補完を備えた型安全なクエリ構築を提供します: ```typescript import { QueryFields, createQuery } from './apps/customer-app.query'; import { and, or } from 'kintone-as-code'; // すべてのフィールド名が自動補完される const { 会社名, ステータス, 売上高, 担当者 } = QueryFields; // 型安全なクエリを構築(メソッドチェーンの例) const query = createQuery() .where( and( 会社名.like('*サイボウズ*'), 売上高.greaterThan(1000000), ステータス.in(['商談中', '受注']) ) ) .orderBy('売上高', 'desc') .limit(100) .build(); // 関数型API(純関数)での構築例 import { createQueryState, setWhere, appendOrder, withLimit, build, } from 'kintone-as-code'; const q2 = build( withLimit(100)( appendOrder( '売上高', 'desc' )( setWhere( and( 会社名.like('*サイボウズ*'), 売上高.greaterThan(1000000), ステータス.in(['商談中', '受注']) ) )(createQueryState()) ) ) ); // kintone REST APIで使用 const client = new KintoneRestAPIClient({ /* ... */ }); const records = await client.record.getRecords({ app: 123, query: query, }); ``` ### 補助メソッド - 文字列: `contains()/startsWith()/endsWith()` - 数値/日付/日時/時間: `between(min, max)` - 関数(カスタム名): `customDateFunction(name, ...args)` / `customUserFunction(name, ...args)` ### クエリビルダーの機能 - **型安全なフィールドアクセス**: すべてのフィールドがkintoneフィールドタイプに基づいて型付け - **フィールド固有の演算子**: 各フィールドタイプで有効な演算子のみ使用可能 - **kintone関数**: `TODAY()``LOGINUSER()``THIS_MONTH()` などをサポート - **複雑な条件**: `and()``or()``not()` で組み合わせ - **自動補完**: IDEがフィールドとメソッドの候補を提供 注: クエリビルダー機能は公開APIとしては提供していません。内部的にはFP APIに基づく設計であり、将来的に公開する場合もFP方針を前提とします。 ### 補足: raw() の非提供 生クエリを直接挿入する `raw()` は提供しません。代替として、 `contains/startsWith/endsWith``between(min, max)``customDateFunction/customUserFunction` を利用してください。 ### フィールドタイプ別の例 ```typescript // 文字列フィールドは like/not like をサポート 会社名.like('*株式会社*'); 会社名.notLike('*test*'); // 数値フィールドは比較演算子をサポート 売上高.greaterThan(1000000); 売上高.lessThanOrEqual(5000000); // ドロップダウンは in/not in を使用 ステータス.in(['商談中', '受注']); ステータス.notIn(['失注', 'キャンセル']); // 日付フィールドは日付関数をサポート 契約日.equals(TODAY()); 期限日.lessThan(FROM_TODAY(7, 'DAYS')); 登録日.in([THIS_MONTH()]); // ユーザーフィールドはユーザー関数をサポート 担当者.equals(LOGINUSER()); 作成者.in(['user1', 'user2']); ``` ## ベストプラクティス 1. **バージョン管理**: アプリ設定の変更を追跡するため、スキーマファイルをコミット 2. **APP_IDSの一元管理**: 複数環境対応のため、アプリIDは `utils/app-ids.ts` の `APP_IDS` で管理(export時に自動更新) 3. **型安全性**: TypeScriptの型チェックを活用して設定エラーを早期発見 4. **コードレビュー**: 開発プロセスの一環としてスキーマ変更をレビュー 5. **レコードバリデーション**: カスタマイズコードで生成されたレコードスキーマを使用して型安全なデータ処理を実現 ## ライセンス MIT