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

strictUndefinedChecks / Gassma.skip

Prisma の strictUndefinedChecks(Preview 機能)と Prisma.skip に相当する機能です。クエリ入力に紛れ込んだ意図しない undefined を実行時エラーとして検出し、フィールドを省略したい場合は Gassma.skip で明示的に指定できるようになります。

Gassma.skip

Gassma.skip はクエリのフィールド値として渡すと、そのフィールドを「指定しなかった」ことにするシンボルです。

const search: string | undefined = getSearchWord();

const users = gassma.Users.findMany({
where: {
// search がない場合は name の条件自体を省く
name: search ?? Gassma.skip,
},
});

Gassma.skipstrictUndefinedChecks の有効・無効に関わらず常に使用できます。where / data / create / update / select / omit / orderBy など、クエリ入力のあらゆる箇所で利用可能です。

strictUndefinedChecks の有効化

strictUndefinedChecks はオプトインの機能です。有効化する方法は 2 つあります。

previewFeatures で有効化(CLI あり)

Prisma スキーマを利用したローカル開発をしている場合は、schema.prismagenerator ブロックに previewFeatures を追加します(Prisma と同じ書き方です)。

generator client {
provider = "prisma-client-js"
output = "./generated/gassma"
previewFeatures = ["strictUndefinedChecks"]
}

npx gassma generate を実行すると、生成されるクライアントに strictUndefinedChecks: true が自動的に埋め込まれます。あわせて生成される型定義にも Gassma.skip を受け付ける型(Gassma.SkipValue)が反映されます。

コンストラクタで有効化(CLI なし)

CLI を使わない構成では、GassmaClient のコンストラクタで指定します。

const gassma = new Gassma.GassmaClient({
strictUndefinedChecks: true,
});

有効時の挙動

有効化すると、クエリ入力に明示的な undefined が含まれる場合に GassmaUndefinedValueError がスローされます。ネストした入力(Nested Write、include 内の select など)も再帰的にチェックされます。

const userName = undefined;

gassma.Users.deleteMany({
where: { name: userName },
});
// => GassmaUndefinedValueError:
// Invalid value for argument `where.name`: explicitly `undefined` values are not allowed.

無効時(デフォルト)は、後述のとおり undefined は「そのフィールドを指定しなかった」扱いになります。意図しない undefined が紛れ込むと、条件が静かに消えて対象行が広がる(上の例なら deleteMany が全件削除になる)事故につながります。有効化しておけば、こうしたバグを実行時に即座に検出できます。

フィールドを省略したい場合は、undefined の代わりに Gassma.skip を使用してください。

gassma.Users.deleteMany({
where: { name: userName ?? Gassma.skip },
});
// name の条件が省かれた状態で実行される

無効時の挙動(デフォルト)

strictUndefinedChecks が無効の場合、クエリ入力の undefined は Prisma と同じく**「そのフィールドを指定しなかった」扱い**になります。where の条件・演算子の中(equals / gt / in など)・AND / OR / NOT の中・リレーションフィルタ・orderByselect のキーなど、クエリ入力のあらゆる箇所で同様です。

// age の条件は「指定しなかった」扱いになり、全件が返る
gassma.Users.findMany({
where: { age: undefined },
});

updatedataundefined を渡した場合も同様に、そのフィールドは更新されません(セルの値は保持されます)。

gassma.Users.update({
where: { id: 1 },
data: { name: undefined, age: 21 },
});
// => name は元の値のまま、age だけが 21 に更新される
注意

where の条件が undefined(または Gassma.skip)だけで空になった場合、findMany / updateMany / deleteMany などでは全件が対象になります。単一行操作の update / delete / upsert では空の whereGassmaInvalidValueError になります(update を参照)。

exactOptionalPropertyTypes の推奨

注記

undefined の代入を型レベルでも完全に禁止するには、利用側プロジェクトの tsconfig.jsonexactOptionalPropertyTypes を有効にすることを推奨します(Prisma と同じです)。

{
"compilerOptions": {
"exactOptionalPropertyTypes": true
}
}

これにより、オプショナルなフィールドへ undefined を明示的に渡すコードがコンパイルエラーになります。

配列内では使えない

注意

配列の要素として Gassma.skip を渡すことはできません。strictUndefinedChecks の有効・無効に関わらず GassmaSkipInArrayError がスローされます。null を使うか、事前に配列から取り除いてください。

gassma.Users.findMany({
where: {
id: { in: [1, Gassma.skip, 3] },
},
});
// => GassmaSkipInArrayError:
// Invalid value for argument `where.id.in[1]`: Can not use `Gassma.skip` value
// within array. Use `null` or filter out `Gassma.skip` values.

配列の要素としての undefined も同様です。in / notIn / AND / OR / NOT / orderBy / distinct などの配列に undefined の要素が含まれる場合、strictUndefinedChecks の有効・無効に関わらず GassmaUndefinedValueError がスローされます(Prisma と同じ挙動です)。

gassma.Users.findMany({
where: {
id: { in: [1, undefined, 3] },
},
});
// => GassmaUndefinedValueError:
// Invalid value for argument `where.id.in[1]`: explicitly `undefined` values are not allowed.

バリデーション

エラー原因
GassmaUndefinedValueErrorstrictUndefinedChecks 有効時にクエリ入力へ明示的な undefined を指定。配列の要素への undefined は有効・無効に関わらず発生
GassmaSkipInArrayError配列の要素に Gassma.skip を指定(有効・無効に関わらず発生)
GassmaInvalidValueErrorundefined / Gassma.skip の除去によって update / delete / upsertwhere が空になった