メインコンテンツまでスキップ

Prisma スキーマを利用したローカル開発

GASsma は clasp+esbuild 等を利用し TypeScript を使ってローカルで GAS を開発する際に、Prisma 形式のスキーマファイルから型安全なクライアントコードを自動生成する機能を提供しています。

この機能を利用すると、リレーション定義や defaults・map 等の設定がスキーマから自動生成されるため、GASsma 独自のコンストラクタオプション(relationsdefaultsupdatedAtignoremap など)を手動で記述する必要がなくなります。Prisma のスキーマ構文さえ知っていれば、Prisma と同じ感覚で開発を始められます。

CLI なし(手動設定):

import { Gassma } from "gassma";

const gassma = new Gassma.GassmaClient({
id: "SPREAD_SHEET_ID",
relations: {
User: {
posts: { type: "oneToMany", to: "Post", field: "id", reference: "authorId", onDelete: "Cascade" },
},
Post: {
author: { type: "manyToOne", to: "User", field: "authorId", reference: "id" },
},
},
defaults: { User: { role: "USER" } },
updatedAt: { Post: "updatedAt" },
map: { User: { firstName: "名前" } },
});

CLI あり(スキーマから自動生成):

import { GassmaClient } from "./generated/gassma/schemaClient";

// リレーション・defaults・updatedAt・map 等すべて自動注入済み
const gassma = new GassmaClient();

前提

以下のコマンドで GASsma の CLI ツールをインストールしてください。

$ npm i gassma

スキーマファイルの作成

プロジェクト内に .prisma ファイルを作成します。デフォルトでは ./gassma ディレクトリ配下が探索されます。

my-project/
├── gassma/
│ └── schema.prisma ← ここにスキーマを記述
├── package.json
└── ...

基本的な書き方

Prisma の文法でモデルを定義します。generator ブロックの output で出力先を指定してください。

generator client {
provider = "prisma-client-js"
output = "./generated/gassma"
}

model User {
id Int @id
name String
email String?
age Int
}

型マッピング

Prisma の型は以下の TypeScript 型に変換されます。

Prisma 型TypeScript 型
Intnumber
Floatnumber
Decimalnumber
BigIntnumber
Stringstring
Booleanboolean
DateTimeDate
Jsonstring
Bytesstring

? を付けるとオプショナルフィールドになります(null が許容されます)。

リレーション定義

Prisma の @relation 属性を使うと、リレーション情報が自動的に抽出され、生成されたクライアントに注入されます。

generator client {
provider = "prisma-client-js"
output = "./generated/gassma"
}

model User {
id Int @id
name String
posts Post[]
}

model Post {
id Int @id
title String
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
authorId Int
}

上記の定義から以下のリレーション設定が自動生成されます。

  • User.posts: oneToMany(User → Post)
  • Post.author: manyToOne(Post → User、onDelete: Cascade)

暗黙的 Many-to-Many

双方向の配列参照がある場合、暗黙的な Many-to-Many リレーションが自動検出されます。

model Post {
id Int @id
tags Tag[]
}

model Tag {
id Int @id
name String
posts Post[]
}

生成されるクライアントでは、中間テーブル名が _PostToTag(アルファベット順)として自動的に解決されます。

注記

中間テーブル(シート)自体は自動作成されません。スプレッドシート側に _PostToTag という名前のシートを手動で用意する必要があります。 中間テーブル名を変更したい場合は、生成された Client.js 内のリレーション定義を直接編集してください。

enum

Prisma の enum 定義からリテラルユニオン型が自動生成されます。

enum Role {
ADMIN
USER
MODERATOR
}

model User {
id Int @id
role Role
}

生成される型:

"role": "ADMIN" | "USER" | "MODERATOR"

enum の @map

enum メンバーに @map を付けると、コード上の名前とスプレッドシート上の値をマッピングできます。

enum Role {
admin @map("ADMIN")
user @map("USER")
moderator @map("MODERATOR")
}

生成される定数:

const Role = {
admin: "ADMIN",
user: "USER",
moderator: "MODERATOR",
} as const;

型定義には @map の値が使用されます:

"role": "ADMIN" | "USER" | "MODERATOR"

@gassma.addType

Prisma のフィールドコメント(///)に @gassma.addType を記述すると、フィールドの型にユニオン型を追加できます。

model User {
/// @gassma.addType string
id Int @id // 生成型: number | string

/// @gassma.addType string, boolean
score Int // 生成型: number | string | boolean

name String // 生成型: string(コメントなしなら通常通り)
}

@gassma.replaceType

@gassma.addType は基底型とのユニオンですが、@gassma.replaceType は基底型を置換して指定した型のみ生成します。

model User {
/// @gassma.replaceType "admin", "user", "moderator"
role String
}

生成される型:

"role": "admin" | "user" | "moderator"  // string を含まない
注記

優先順位: enum > replaceType > addType。enum がある場合は replaceType / addType は無視されます。

@default

@default() が付いたフィールドは、生成される Create 入力型でオプショナル(?)になります。

model User {
id Int @id @default(autoincrement())
name String
isActive Boolean @default(true)
createdAt DateTime @default(now())
}

生成される型:

"isActive"?: boolean   // @default(true) → オプショナル
"createdAt"?: Date // @default(now()) → オプショナル

生成されるクライアント JS には defaults 設定が自動的に埋め込まれます。

@default()生成される JS
@default(true) / @default(false)true / false
@default(0) (数値)0
@default("USER") (文字列)"USER"
@default(now())() => new Date()
@default(uuid())() => Utilities.getUuid()
@default(autoincrement())autoincrement 設定として別途生成

@updatedAt

@updatedAt が付いたフィールドは Create 入力型でオプショナルになり、生成されるクライアント JS に updatedAt 設定が埋め込まれます。

model Post {
id Int @id
title String
updatedAt DateTime @updatedAt
}

@ignore

@ignore が付いたフィールドは型定義から完全に除外され、生成されるクライアント JS に ignore 設定が埋め込まれます。

model User {
id Int @id
name String
secret String @ignore // 型定義に含まれない
}

@map

@map("name") でフィールド名のマッピングを定義できます。生成されるクライアント JS に map 設定が埋め込まれます。

model User {
id Int @id
firstName String @map("名前")
lastName String @map("名字")
}

コード上は firstName / lastName で操作し、スプレッドシート上は「名前」「名字」カラムに対応します。

@@ignore

モデルレベルの @@ignore でシート全体を除外できます。生成されるクライアント JS に ignoreSheets 設定が埋め込まれます。

model Logs {
id Int @id
message String

@@ignore
}

@@map

モデルレベルの @@map("name") でシート名をマッピングできます。

model Users {
id Int @id
name String

@@map("ユーザー一覧")
}

コード上は Users でアクセスし、スプレッドシート上は「ユーザー一覧」シートに対応します。

CLI コマンド

gassma generate

型ファイルとクライアントコードを生成します。

$ npx gassma generate

デフォルトでは ./gassma ディレクトリ内の .prisma ファイルが探索されます。--schema オプションで特定のスキーマファイルまたはディレクトリを指定できます(Prisma の prisma generate --schema に相当)。

$ npx gassma generate --schema gassma/user.prisma
$ npx gassma generate --schema ./schemas

--watch オプションでスキーマファイルの変更を監視し、自動で再生成できます。

$ npx gassma generate --watch

--schema との併用も可能です。

gassma init

プロジェクトを初期化し、スキーマファイルと設定ファイルを自動生成します。

$ npx gassma init

以下のファイルが生成されます:

  • gassma/schema.prisma — 初期スキーマ
  • gassma.config.ts — 設定ファイル
オプション説明
--output <path>生成先パスをカスタマイズ
--with-modelサンプル User モデルを含むスキーマを生成

既に schema.prisma が存在する場合はエラーで安全に停止します。

gassma validate

スキーマファイルの構文チェック・整合性チェックを行います(Prisma の prisma validate に相当)。

$ npx gassma validate
$ npx gassma validate --schema gassma/test.prisma

チェック項目:

  • 構文エラー(パーサーエラー検出)
  • generator ブロックの存在チェック
  • output フィールドの必須チェック

成功時は以下のように出力されます:

The schema at /path/to/gassma/test.prisma is valid 🚀

gassma format

.prisma ファイルを Prisma 公式と同じフォーマットで整形します(@prisma/internalsformatSchema を使用)。

$ npx gassma format
オプション説明
--schema <path>特定ファイルのみ整形
--checkフォーマット済みかチェック(CI 用、未整形時は exit 1)

gassma version

GASsma CLI のバージョンを表示します。

$ npx gassma version

--version / -V フラグでも確認できます。

生成されるファイル

スキーマファイル名をもとに以下のファイルが生成されます。例えば schema.prisma の場合:

ファイル内容
schema.d.ts型定義(モデル型、クエリ型、共通型)
schemaClient.jsクライアント実装(リレーション定義の自動注入込み)
schemaClient.d.tsクライアントの型定義

出力先は generator ブロックの output で指定したディレクトリです。

生成されたクライアントの使い方

生成されたクライアントファイルから GassmaClient をインポートしてそのまま使えます。リレーション定義は自動注入済みです。

import { GassmaClient } from "./generated/gassma/schemaClient";

const gassma = new GassmaClient();

// 型安全にシートへアクセス
const users = gassma.User.findMany({
where: { age: { gte: 20 } },
select: { name: true, email: true },
});

Prisma と同じパターンでインスタンス化できます。

// Prisma
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();

// GASsma(同じパターン)
import { GassmaClient } from "./generated/gassma/schemaClient";
const gassma = new GassmaClient();

オプション付きの初期化

// スプレッドシートID指定
const gassma = new GassmaClient("SPREAD_SHEET_ID");

// オプションオブジェクト
const gassma = new GassmaClient({
id: "SPREAD_SHEET_ID",
omit: {
User: { password: true },
},
});

設定ファイル(gassma.config.ts)

プロジェクトルートに gassma.config.ts を配置することで、CLI の設定を一元管理できます(Prisma の prisma.config.ts に相当)。

設定インターフェース

設定ファイルの記述方法は 2 つあります。

1. defineConfig ヘルパーを使用(推奨):

import { defineConfig } from "gassma/config";

export default defineConfig({
schema: "gassma/schema.prisma",
datasource: {
url: "https://docs.google.com/spreadsheets/d/XXXXX/edit",
},
});

2. satisfies 演算子を使用:

import type { GassmaConfig } from "gassma";

export default {
schema: "gassma/schema.prisma",
datasource: {
url: "https://docs.google.com/spreadsheets/d/XXXXX/edit",
},
} satisfies GassmaConfig;

GassmaConfig 型は gassma パッケージのルートから import できます。

設定オプション

オプション必須説明
schemastringいいえスキーマファイルまたはディレクトリのパス(デフォルト: ./gassma
datasource.urlstringいいえスプレッドシートの URL または ID

env() ヘルパー

env() 関数を使うと、環境変数からスプレッドシート URL を取得できます(Prisma の env() に相当)。

import "dotenv/config";
import { defineConfig, env } from "gassma/config";

export default defineConfig({
schema: "gassma",
datasource: {
url: env("SPREADSHEET_URL"),
},
});

satisfies パターンでも使用できます。

import "dotenv/config";
import type { GassmaConfig } from "gassma";
import { env } from "gassma/config";

export default {
schema: "gassma",
datasource: {
url: env("SPREADSHEET_URL"),
},
} satisfies GassmaConfig;
注記

env() は環境変数が未設定または空文字の場合にエラーをスローします。オプショナルな環境変数には process.env を直接使用してください。

datasource.url

datasource.url にスプレッドシートの URL または ID を指定すると、生成されるクライアント JS に id が自動埋め込みされます。これにより new GassmaClient() だけで対象スプレッドシートに接続できます。

フル URL とスプレッドシート ID の両方に対応しています。

// フル URL
datasource: {
url: "https://docs.google.com/spreadsheets/d/XXXXX/edit",
}

// ID 直接指定
datasource: {
url: "XXXXX",
}

スキーマ内の datasource ブロック

スキーマファイル内に datasource ブロックを記述することでも URL を指定できます。

datasource db {
provider = "google-spreadsheet"
url = "https://docs.google.com/spreadsheets/d/XXXXX/edit"
}

URL 解決の優先順位

  1. スキーマ内の datasource ブロック(最優先)
  2. gassma.config.tsdatasource.url

スキーマ解決の優先順位

  1. --schema オプション(最優先)
  2. gassma.config.tsschema 設定
  3. デフォルト ./gassma ディレクトリ

gassma init を実行すると gassma.config.ts も自動生成されます。

マルチファイルスキーマ

同じディレクトリ(およびサブディレクトリ)内に複数の .prisma ファイルを配置すると、自動的に 1 つのスキーマとして統合 されます。Prisma の Multi-file schema と同等の機能です。

gassma/
├── schema.prisma ← generator ブロックをここに記述
├── models/
│ ├── user.prisma ← User, Profile モデル
│ └── post.prisma ← Post, Comment モデル

generator ブロックはいずれか 1 ファイルに記述すれば、全ファイルで共有されます。すべてのモデルが 1 つのクライアント出力にまとめられます。

複数スキーマ(複数スプレッドシート)

異なるスプレッドシートを扱う場合は、スキーマを別々のディレクトリに分けて個別に生成します。型名にはスキーマ名のプレフィックスが付与されるため、同名モデルがあっても衝突しません。

schemas/
├── user/
│ └── schema.prisma → userClient.js, user.d.ts
└── order/
└── schema.prisma → orderClient.js, order.d.ts
import { GassmaClient as UserClient } from "./generated/user/schemaClient";
import { GassmaClient as OrderClient } from "./generated/order/schemaClient";

const userGassma = new UserClient();
const orderGassma = new OrderClient();

生成される型の概要

生成される .d.ts には以下の型が含まれます。

  • モデル型: 各フィールドの型定義(GassmaUserUse 等)
  • クエリ型: FindDataCreateDataUpdateDataDeleteDataUpsertData
  • Select / Omit 型: フィールド選択・除外の型
  • フィルタ型: WhereUseFilterConditionsFieldRef 対応含む)
  • OrderBy 型: ソート条件(リレーションソート、_count ソート、nulls 制御含む)
  • Include 型: リレーション取得の型(_count 含む)
  • Nested Write 型: リレーション先の作成・接続・更新・削除操作
  • 数値操作型: NumberOperation(increment / decrement / multiply / divide)
  • 共通型: FieldRefGassmaClientOptions、エラークラス群
  • 設定型: DefaultsConfigUpdatedAtConfigIgnoreConfigAutoincrementConfigMapConfig
  • コントローラー型: 全メソッドの引数・戻り値型