ホームページ >ウェブフロントエンド >jsチュートリアル >キスリー・カネル:完璧なデュオ
私は、最初のプロジェクト (OT ポケモンと Habbo の最初の Web サイト) の開発を始めて以来、常に Raw SQL を選択してきました。正直に言うと、私は今でも独自のクエリを作成し、この「低レベル」レイヤーをより正確に制御することをとても楽しんでいます。非効率なクエリを特定して最適化するためにログを分析するのにすでに何日も費やしているため、ORM を使用しても完全に快適とは言えません。
しかし、私が Raw SQL を使用して作業した多くのコードベースでは、大部分に移行制御がなく、データベースも監視されていませんでした。すべてが即興で機能しました。「新しいフィールドが必要ですか?ALTER TABLE を実行して、新しい列を追加してください。」このアプローチはすべてのシナリオにおいて非常に有害であり、「運用環境ではどの列を上に移動する必要があるか?」、「どのような新しいエンティティが作成されたか?」、「環境は同期されているか?」など、いくつかの疑問が生じました。 — および他の多くの同様の問題。
これらすべての問題に直面して、私は自分のルーティンと、一緒に働いているチームのルーティンをより健全なものにするために、新しいツールを導入することにしました。持っていた柔軟性を放棄したくはありませんでしたが、アプリケーションの自由度をより適切に制御したいとも考えていました。多くの調査を行った結果、これらの問題を解決するために最も完全であると考えられるツールを見つけました。Kysely は、実用的であることに加えて、完全にタイプセーフである TypeScript 用のクエリ ビルダーです。私にとって超重要なポイント。このライブラリに非常に興味を惹かれたので、Kysely と統合された他のオープン ソース ライブラリ用のプラグインを作成して、直接的および間接的にコミュニティに積極的に貢献し始めました。
ただし、Kysely を使用する場合の最大の困難の 1 つは、ORM とは異なり、エンティティや型/インターフェイスの自動生成がないことです。この作業はすべて手動で行う必要があり、少し疲れるかもしれません。ソリューションを調査中に、最終的に PostgreSQL に関連するすべてのプロジェクトで採用することになったツール、Kanel を見つけました。 Kanel はデータベース タイピングを自動的に生成し、Kysely を完全に補完します。
さらに、Kanel には、Kysely と直接使用するための追加機能があります: Kanel-Kysely。私はこのリポジトリに積極的に貢献し、移行テーブルの型フィルターや Zod オブジェクトのキャメルケースへの変換などの新機能の開発を支援してきました。
NestJS を使用して次の例を説明します。したがって、コード内の構文や何かが理解できない場合は、NestJS のドキュメントを読むことをお勧めします。私の意見では、特に JavaScript を「エスケープ」したい場合には、これが最高の JavaScript フレームワークです。しかし、それは私の別の投稿のトピックです。
例を忠実に実行したい場合は、事前に NestJS が初期化されたリポジトリを用意しておく必要があります。ただし、独自のコードを開発することもできます。
最初に、Kysely 自体、その CLI、および Node.js 用の PostgreSQL モジュールをインストールする必要があります。
npm i kysely pg && npm i kysely-ctl --save-dev
次に、Kysely のプロジェクトのルートに構成ファイルを作成する必要があります。移行ファイルとシード ファイルにも Knex プレフィックスを使用します。
// kysely.config.ts import "dotenv/config"; import { defineConfig, getKnexTimestampPrefix } from "kysely-ctl"; import { Pool } from "pg"; export default defineConfig({ dialect: "pg", dialectConfig: { pool: new Pool({ connectionString: process.env.DATABASE_URL }), }, migrations: { migrationFolder: "src/database/migrations", getMigrationPrefix: getKnexTimestampPrefix, }, seeds: { seedFolder: "src/database/seeds", getSeedPrefix: getKnexTimestampPrefix, }, });
次に、ターミナルでコマンド npx kysely merge make create_user_table を実行します。これは、最初の移行の作成を担当します。次に、新しいユーザー テーブルを作成し、完了したら、コマンド npx kysely merge last を使用してデータベースでこの移行を実行します。
// 20241225222128_create_user_table.ts import { sql, type Kysely } from 'kysely' export async function up(db: Kysely<any>): Promise<void> { await db.schema .createTable("user") .addColumn("id", "serial", (col) => col.primaryKey()) .addColumn("name", "text", (col) => col.notNull()) .addColumn("email", "text", (col) => col.unique().notNull()) .addColumn("password", "text", (col) => col.notNull()) .addColumn("created_at", "timestamp", (col) => col.defaultTo(sql`now()`).notNull(), ) .execute(); } export async function down(db: Kysely<any>): Promise<void> { await db.schema.dropTable("user").execute(); }
これらの手順がすべて完了したら、データベースのモジュールを作成しましょう。また、列をキャメルケースに変換するために Kysely プラグインを使用していることにも注目してください。
// src/database/database.module.ts import { EnvService } from "@/env/env.service"; import { Global, Logger, Module } from "@nestjs/common"; import { CamelCasePlugin, Kysely, PostgresDialect } from "kysely"; import { Pool } from "pg"; export const DATABASE_CONNECTION = "DATABASE_CONNECTION"; @Global() @Module({ providers: [ { provide: DATABASE_CONNECTION, useFactory: async (envService: EnvService) => { const dialect = new PostgresDialect({ pool: new Pool({ connectionString: envService.get("DATABASE_URL"), }), }); const nodeEnv = envService.get("NODE_ENV"); const db = new Kysely({ dialect, plugins: [new CamelCasePlugin()], log: nodeEnv === "dev" ? ["query", "error"] : ["error"], }); const logger = new Logger("DatabaseModule"); logger.log("Successfully connected to database"); return db; }, inject: [EnvService], }, ], exports: [DATABASE_CONNECTION], }) export class DatabaseModule {}
依存関係をインストールすることから始めましょう。
npm i kanel kanel-kysely --save-dev
次に、Kanel が動作を開始するための設定ファイルを作成しましょう。 CamelCaseHook (インターフェイスを CamelCase に変換するため) や kyselyTypeFilter (Kysely の移行テーブルを除外するため) などのいくつかのプラグインを使用することに注意してください。これらの機能の 1 つは、私が貢献してこれまでの作業を均一にすることができてうれしかったです。簡単です。
// .kanelrc.js require("dotenv/config"); const { kyselyCamelCaseHook, makeKyselyHook, kyselyTypeFilter } = require("kanel-kysely"); /** @type {import('kanel').Config} */ module.exports = { connection: { connectionString: process.env.DATABASE_URL, }, typeFilter: kyselyTypeFilter, preDeleteOutputFolder: true, outputPath: "./src/database/schema", preRenderHooks: [makeKyselyHook(), kyselyCamelCaseHook], };
ファイルが作成されたら、ターミナルでコマンド npx kanel を実行します。設定ファイルで指定したパスにディレクトリが作成されたことに注意してください。このディレクトリはスキーマの名前 (この場合は Public) に対応し、その中には PublicSchema.ts と User.ts という 2 つの新しいファイルがあります。 。あなたの User.ts はおそらく次のようになります:
// @generated // This file is automatically generated by Kanel. Do not modify manually. import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely'; /** Identifier type for public.user */ export type UserId = number & { __brand: 'UserId' }; /** Represents the table public.user */ export default interface UserTable { id: ColumnType<UserId, UserId | undefined, UserId>; name: ColumnType<string, string, string>; email: ColumnType<string, string, string>; password: ColumnType<string, string, string>; createdAt: ColumnType<Date, Date | string | undefined, Date | string>; } export type User = Selectable<UserTable>; export type NewUser = Insertable<UserTable>; export type UserUpdate = Updateable<UserTable>;
ただし、最も重要なのは、このディレクトリ Public の外にあるファイル Database.ts です。これは、Kysely が理解できるように渡すためのものです。データベースの全体構造。ファイル app.service.ts 内に、DatabaseModule プロバイダーを挿入し、型 Database.
を Kysely に渡します。
npm i kysely pg && npm i kysely-ctl --save-dev
コード エディターは最初の移行で作成した列を正確に提案するため、Kanel が生成した型指定が正しく機能していることに注目してください。
これは、私が個人的なプロジェクトや仕事でも (自由に使えるときは) 使用するのが大好きなデュオです。クエリ ビルダーは、Raw SQL が提供する柔軟性を好むと同時に、「より安全な」パスを選択するすべての人にとって不可欠なツールです。また、Kanel のおかげで、デバッグや新しい型付けの作成に費やす何時間も節約できました。この 2 つを使ってプロジェクトを作成することを強くお勧めします。絶対に後悔しないでしょう。
リポジトリ リンク: Frankenstein-nodejs
以上がキスリー・カネル:完璧なデュオの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。