首頁 web前端 js教程 基斯利·卡內爾 (Kisley Kanel):完美二人組

基斯利·卡內爾 (Kisley Kanel):完美二人組

Jan 03, 2025 pm 09:05 PM

自從我開始開發我的第一個專案(我的 OT Pokémon 和 Habbo 的第一個網站)以來,我一直選擇 Raw SQL。老實說,我仍然非常喜歡編寫自己的查詢並更精確地控制這個「低級」層。 ORM 並不讓我完全放心,因為我已經花了幾天時間分析日誌來識別和優化低效查詢。

但是,在我使用 Raw SQL 的許多程式碼庫中,絕大多數沒有遷移控制,而且資料庫也沒有受到監控。一切都在即興創作的基礎上進行:「您需要一個新字段嗎?運行ALTER TABLE 並添加一個新列。」這種方法在所有場景下都是極其有害的,出現了幾個問題,例如:“我們應該在生產環境中上哪些列?”,“創建了哪些新實體?”,“環境是否同步?” - 以及許多其他類似的問題。

我的問題的解決方案

面對所有這些問題,我決定採用新的工具來讓我和與我一起工作的團隊的日常工作變得更健康。我不想放棄我所擁有的靈活性,但我也想更好地控制應用程式的自由度。經過大量研究,我發現了一個我認為最完整的解決這些問題的工具:Kysely,它是TypeScript 的查詢構建器,除了實用之外,還是完全類型安全的—對我來說非常重要的一點。這個函式庫引起了我的注意,以至於我開始直接和間接地積極為社群做出貢獻,為與 Kysely 整合的其他開源函式庫創建插件。

然而,使用 Kysely 時最大的困難之一是,與 ORM 不同,它沒有實體或自動產生類型/介面。所有這些工作都需要手動完成,這可能有點累人。在研究解決方案的過程中,我發現了一個最終在所有涉及 PostgreSQL 的專案中採用的工具:Kanel。 Kanel 自動產生資料庫類型,完美補充了 Kysely。

此外,Kanel 還有一個可以直接與 Kysely 一起使用的附加功能:Kanel-Kysely。我一直在積極為這個儲存庫做出貢獻,幫助開發新功能,例如遷移表的類型過濾器以及 Zod 物件到駝峰命名法的轉換。

配置 Kysely

我將使用 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 migrate make create_user_table。它將負責創建我們的第一個遷移。接下來,我們將建立一個新的使用者表,完成後,我們將使用命令 npx kysely migratelatest.
在資料庫中執行此遷移

// 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 {}
登入後複製

配置 Kanel

讓我們從安裝依賴項開始。

npm i kanel kanel-kysely --save-dev
登入後複製

接下來,讓我們為 Kanel 建立設定檔以開始工作。請注意,我將使用一些插件,例如camelCaseHook(將我們的介面轉換為camelCase)和kyselyTypeFilter(以排除Kysely的遷移表),我很高興能夠貢獻這些功能之一,並使我們的工作甚至更容易。

// .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.tsUser.ts 。您的 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 產生的類型運作正常,因為我們的程式碼編輯器將準確建​​議我們在第一次遷移中建立的欄位。

Kysely   Kanel: a dupla perfeita

最後的考慮因素

這是我非常喜歡在我的個人專案甚至工作中使用的組合(當我有自由這樣做時)。對於喜歡原始 SQL 提供的靈活性但也選擇「更安全」路徑的每個人來說,查詢產生器都是必不可少的工具。 Kanel 還為我節省了許多時間的調試和創建新類型的時間。我強烈建議你用這兩個創建一個項目,你絕對不會後悔的。

儲存庫連結: Frankenstein-nodejs

以上是基斯利·卡內爾 (Kisley Kanel):完美二人組的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

前端熱敏紙小票打印遇到亂碼問題怎麼辦? 前端熱敏紙小票打印遇到亂碼問題怎麼辦? Apr 04, 2025 pm 02:42 PM

前端熱敏紙小票打印的常見問題與解決方案在前端開發中,小票打印是一個常見的需求。然而,很多開發者在實...

神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

誰得到更多的Python或JavaScript? 誰得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

如何實現視差滾動和元素動畫效果,像資生堂官網那樣?
或者:
怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? 如何實現視差滾動和元素動畫效果,像資生堂官網那樣? 或者: 怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? Apr 04, 2025 pm 05:36 PM

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript難以學習嗎? JavaScript難以學習嗎? Apr 03, 2025 am 12:20 AM

學習JavaScript不難,但有挑戰。 1)理解基礎概念如變量、數據類型、函數等。 2)掌握異步編程,通過事件循環實現。 3)使用DOM操作和Promise處理異步請求。 4)避免常見錯誤,使用調試技巧。 5)優化性能,遵循最佳實踐。

JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? 如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

前端開發中如何實現類似 VSCode 的面板拖拽調整功能? 前端開發中如何實現類似 VSCode 的面板拖拽調整功能? Apr 04, 2025 pm 02:06 PM

探索前端中類似VSCode的面板拖拽調整功能的實現在前端開發中,如何實現類似於VSCode...

See all articles