Fastify
TypeScript
Fastify çatısı saf JavaScript ile yazılmıştır ve bu nedenle tür tanımları kolayca sürdürülmez; ancak, 2 ve sonrasındaki versiyonlarda, bakımcılar ve katkıda bulunanlar türleri geliştirmek için büyük bir çaba sarf etmiştir.
Fastify 3. versiyonunda tür sistemi değiştirildi. Yeni tür sistemi,
genel kısıtlama ve varsayılan değerler ile birlikte, bir istek gövdesi, sorgu dizgesi ve daha fazlası gibi şema türlerini tanımlamanın yeni bir yolunu tanıtıyor! Ekip, çerçeve ve tür tanım senkronizasyonunu geliştirmeye çalışırken, bazen API'nın bazı bölümleri tanımlanmamış veya yanlış tanımlanmış olabilir. Eksiklikleri gidermek için katkıda bulunmanızı teşvik ediyoruz. Her şeyin sorunsuz gitmesini sağlamak için başlamadan önce
KATKIDA BULUNMA.md
dosyamızı okumayı unutmayın!
Bu bölümdeki belgeler Fastify 3.x türlerini kapsamaktadır.
Eklentiler türleri içerebilir veya içermeyebilir. Daha fazla bilgi için
Eklentiler
bölümüne bakın. Kullanıcıların tür desteğini geliştirmek için çekme istekleri göndermelerini teşvik ediyoruz.
@types/node
paketini yüklemeyi unutmayın
Örnekle Öğrenin
Fastify tür sistemini öğrenmenin en iyi yolu örneklerden geçmektir! Aşağıdaki dört örnek, en yaygın Fastify geliştirme durumlarını kapsamalıdır. Örneklerden sonra tür sistemi ile ilgili daha ayrıntılı belgeler mevcuttur.
Başlarken
Bu örnek, sizi Fastify ve TypeScript ile çalıştıracak. Sonuç, boş bir http Fastify sunucusu olacaktır.
Yeni bir npm projesi oluşturun, Fastify'ı yükleyin ve TypeScript & Node.js türlerini eş bağımlılıklar olarak yükleyin:
npm init -y
npm i fastify
npm i -D typescript @types/nodeAşağıdaki satırları
package.json
dosyasının"scripts"
bölümüne ekleyin:{
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "node index.js"
}
}TypeScript yapılandırma dosyasını başlatın:
npx tsc --init
veya önerilenlerden birini kullanın.
Not: tsconfig.json
dosyasında target
özelliğini es2017
veya daha büyük
bir değere ayarlayın ki FastifyDeprecation uyarısından kaçının.
Bir
index.ts
dosyası oluşturun - burası sunucu kodunu içerecek.Aşağıdaki kod bloğunu dosyanıza ekleyin:
import fastify from 'fastify'
const server = fastify()
server.get('/ping', async (request, reply) => {
return 'pong\n'
})
server.listen({ port: 8080 }, (err, address) => {
if (err) {
console.error(err)
process.exit(1)
}
console.log(`Sunucu dinliyor: ${address}`)
})npm run build
komutunu çalıştırın - bu,index.ts
dosyasınıindex.js
olarak derleyecek ve Node.js ile çalıştırılabilir hale getirecektir. Herhangi bir hata ile karşılaşırsanız lütfen fastify/help bölümünde bir sorun açın.Fastify sunucusunu çalıştırmak için
npm run start
komutunu çalıştırın.Konsolunuzda
Sunucu dinliyor: http://127.0.0.1:8080
mesajını görmelisiniz.Sunucunuzu
curl localhost:8080/ping
komutuyla test edin, bupong
döndürecektir. 🏓
🎉 Artık çalışan bir Typescript Fastify sunucunuz var! Bu örnek,
3.x sürüm tür sisteminin basitliğini gösteriyor. Varsayılan olarak, tür sistemi
bir http
sunucusu kullandığınızı varsayıyor. Sonraki örnekler daha karmaşık sunucular
oluşturma, https
ve http2
gibi, yol şemalarını belirleme ve daha fazlasını gösteriyor!
Fastify'ı TypeScript ile başlatma hakkında daha fazla örnek için (HTTP2'yi etkinleştirme gibi) ayrıntılı API bölümünü [buradan][Fastify] kontrol edin.
Generic Kullanımı
Tür sistemi, en doğru geliştirme deneyimini sağlamak için genel özelliklere dayanmaktadır. Bazıları, yükün biraz fazla olduğunu düşünebilir; ancak, değişim buna değer! Bu örnek, yönlendirme şemaları için genel türleri uygulamaya girecek ve yol düzeyindeki request
nesnesindeki dinamik özelliklere bakacaktır.
Önceki örneği tamamlamadıysanız, 1-4 adımlarını takip ederek kurulum yapın.
index.ts
dosyasının içinde üç arayüzüIQuerystring
,IHeaders
veIReply
tanımlayın:interface IQuerystring {
username: string;
password: string;
}
interface IHeaders {
'h-Custom': string;
}
interface IReply {
200: { success: boolean };
302: { url: string };
'4xx': { error: string };
}Bu üç arayüzü kullanarak yeni bir API rotası tanımlayın ve bunları genel türler olarak geçirin. Kısa yol rotası yöntemleri (yani
.get
) bir genel nesne olanRouteGenericInterface
döngüsünü kabul eder ve bu, beş adlandırılmış özellik içerir:Body
,Querystring
,Params
,Headers
veReply
.Body
,Querystring
,Params
veHeaders
arayüzleri, yol yöntemi işleyicisindekirequest
örneğine veReply
arayüzü dereply
örneğine geçilecektir.server.get<{
Querystring: IQuerystring,
Headers: IHeaders,
Reply: IReply
}>('/auth', async (request, reply) => {
const { username, password } = request.query
const customerHeader = request.headers['h-Custom']
// istek verileriyle bir şey yap
// .statusCode/.code çağrılarına .send ile zincirleme, tür daraltmasına izin verir. Örneğin:
// bu çalışır
reply.code(200).send({ success: true });
// ama bu bir tür hatası verir
reply.code(200).send('uh-oh');
// wildcards için bile çalışır
reply.code(404).send({ error: 'Bulunamadı' });
return `giriş yapıldı!`
})Sunucu kodunu
npm run build
venpm run start
komutlarıyla oluşturun ve çalıştırın.API'yi sorgulayın
curl localhost:8080/auth?username=admin&password=Password123!
Ve
giriş yapıldı!
mesajını döndürmelidir.Ama bekleyin, daha fazlası var! Genel arayüzler yönlendirme düzeyindeki kancalarda da mevcuttur. Önceki rotayı
preValidation
kancası ekleyerek değiştirin:server.get<{
Querystring: IQuerystring,
Headers: IHeaders,
Reply: IReply
}>('/auth', {
preValidation: (request, reply, done) => {
const { username, password } = request.query
done(username !== 'admin' ? new Error('Admin olmalı') : undefined) // sadece `admin` hesabını doğrula
}
}, async (request, reply) => {
const customerHeader = request.headers['h-Custom']
// istek verileriyle bir şey yap
return `giriş yapıldı!`
})Oluşturun ve çalıştırın;
username
sorgu dizesi seçeneğiniadmin
dışında bir şey olarak ayarlayın. API şimdi HTTP 500 hatasını{"statusCode":500,"error":"İç Sunucu Hatası","message":"Admin olmalı"}
döndürmelidir.
🎉 İyi iş, şimdi her rota için arayüzler tanımlayabilir ve kesin türlü istek ve cevap örneklerine sahip olabilirsiniz. Fastify tür sisteminin diğer bölümleri genel özelliklere dayanır. Daha fazlasını öğrenmek için aşağıdaki ayrıntılı tür sistemi belgelerine başvurmayı unutmayın.
JSON Şeması
İsteklerinizi ve yanıtlarınızı doğrulamak için JSON Şeması dosyalarını kullanabilirsiniz. Daha önce duymadıysanız, Fastify rotalarınız için şemalar tanımlamak, bunların verimliliğini artırabilir! Daha fazla bilgi için Doğrulama ve
Serileştirme
belgelerine göz atın.
Ayrıca, tanımlı türü işleyicilerinizde (ön doğrulama dahil) kullanma avantajına sahiptir.
Bunu başarmanın bazı yolları aşağıda verilmiştir.
Tür Sağlayıcıları
Fastify, json-schema-to-ts
ve typebox
'ı saran iki paket sunar:
Ve üçüncü taraf bir zod
sarmalayıcı: fastify-type-provider-zod
Bu paketler, şema doğrulama kurulumunu basitleştirir ve bunlar hakkında daha fazla bilgiyi Tür Sağlayıcıları
sayfasında okuyabilirsiniz.
Aşağıda, typebox
, json-schema-to-typescript
ve json-schema-to-ts
paketlerini kullanarak tür sağlayıcıları olmadan şema doğrulama ayarlamanın yolu açıklanmaktadır.
TypeBox
Tür ve şemayı aynı anda oluşturmak için yararlı bir kütüphane olan TypeBox ile başlarsınız. TypeBox ile şemanızı kod içinde tanımlarsınız ve ihtiyacınıza göre doğrudan türler veya şemalar olarak kullanırsınız.
Bir Fastify rotasında bazı yüklerin doğrulaması için kullanmak istiyorsanız, bunu şu şekilde yapabilirsiniz:
Projenize
typebox
yükleyin.npm i @sinclair/typebox
Gerekli şemayı
Type
ile tanımlayın ve ilişkili türüStatic
ile oluşturun.import { Static, Type } from '@sinclair/typebox'
export const User = Type.Object({
name: Type.String(),
mail: Type.Optional(Type.String({ format: 'email' })),
})
export type UserType = Static<typeof User>Rotanızın tanımında tanımlı türü ve şemayı kullanın.
import Fastify from 'fastify'
// ...
const fastify = Fastify()
fastify.post<{ Body: UserType, Reply: UserType }>(
'/',
{
schema: {
body: User,
response: {
200: User
},
},
},
(request, reply) => {
// `name` ve `mail` türleri otomatik olarak çıkarılır
const { name, mail } = request.body;
reply.status(200).send({ name, mail });
}
)
json-schema-to-typescript
Son örnekte, rotamız için türleri ve şemaları tanımlamak için TypeBox kullandık. Birçok kullanıcı, bu özellikleri tanımlamak için zaten JSON Şemaları kullanıyor ve şanslıyız ki mevcut JSON Şemalarını TypeScript arayüzlerine dönüştürmenin bir yolu var!
'Başlarken' örneğini tamamlamadıysanız, önce 1-4 adımlarını takip edin.
json-schema-to-typescript
modülünü yükleyin:npm i -D json-schema-to-typescript
schemas
adında yeni bir klasör oluşturun veheaders.json
vequerystring.json
adında iki dosya ekleyin. Aşağıdaki şema tanımlarını ilgili dosyalara kopyalayın ve yapıştırın:{
"title": "Başlık Şeması",
"type": "object",
"properties": {
"h-Custom": { "type": "string" }
},
"additionalProperties": false,
"required": ["h-Custom"]
}{
"title": "Sorgu Dizgesi Şeması",
"type": "object",
"properties": {
"username": { "type": "string" },
"password": { "type": "string" }
},
"additionalProperties": false,
"required": ["username", "password"]
}package.json
dosyasına bircompile-schemas
betiği ekleyin:{
"scripts": {
"compile-schemas": "json2ts -i schemas -o types"
}
}json2ts
,json-schema-to-typescript
paketinde dahil olan bir CLI aracıdır.schemas
girdi yolu vetypes
çıkış yoludur.npm run compile-schemas
komutunu çalıştırın.types
klasöründe iki yeni dosya oluşturulmuş olmalı.Aşağıdaki koda sahip
index.ts
dosyasını güncelleyin:import fastify from 'fastify'
// şemaları normal olarak içe aktarın
import QuerystringSchema from './schemas/querystring.json'
import HeadersSchema from './schemas/headers.json'
// oluşturulan arayüzleri içe aktarın
import { QuerystringSchema as QuerystringSchemaInterface } from './types/querystring'
import { HeadersSchema as HeadersSchemaInterface } from './types/headers'
const server = fastify()
server.get<{
Querystring: QuerystringSchemaInterface,
Headers: HeadersSchemaInterface
}>('/auth', {
schema: {
querystring: QuerystringSchema,
headers: HeadersSchema
},
preValidation: (request, reply, done) => {
const { username, password } = request.query
done(username !== 'admin' ? new Error('Admin olmalı') : undefined)
}
// veya asenkron kullanıyorsanız
// preValidation: async (request, reply) => {
// const { username, password } = request.query
// if (username !== "admin") throw new Error("Admin olmalı");
// }
}, async (request, reply) => {
const customerHeader = request.headers['h-Custom']
// istek verileriyle bir şey yap
return `giriş yapıldı!`
})
server.route<{
Querystring: QuerystringSchemaInterface,
Headers: HeadersSchemaInterface
}>({
method: 'GET',
url: '/auth2',
schema: {
querystring: QuerystringSchema,
headers: HeadersSchema
},
preHandler: (request, reply, done) => {
const { username, password } = request.query
const customerHeader = request.headers['h-Custom']
done()
},
handler: (request, reply) => {
const { username, password } = request.query
const customerHeader = request.headers['h-Custom']
reply.status(200).send({username});
}
})
server.listen({ port: 8080 }, (err, address) => {
if (err) {
console.error(err)
process.exit(0)
}
console.log(`Sunucu dinliyor: ${address}`)
})Bu dosyanın başındaki ithalatlara özel dikkat edin. Gereksiz görünebilir, ancak hem şema dosyalarını hem de oluşturulan arayüzleri içe aktarmanız gerekiyor.
Harika iş! Artık hem JSON Şemaları hem de TypeScript tanımlarından yararlanabilirsiniz.
json-schema-to-ts
Eğer şemalarınızdan türler oluşturmak istemiyorsanız, ancak bunları doğrudan kodunuzdan kullanmak istiyorsanız, json-schema-to-ts paketini kullanabilirsiniz.
Bunu geliştirme bağımlılığı olarak yükleyebilirsiniz.
npm i -D json-schema-to-ts
Kodunuzda, şemanızı normal bir nesne gibi tanımlayabilirsiniz. Ancak, bu modülün belgelerinde açıklandığı gibi const
yapmayı unutmayın.
const todo = {
type: 'object',
properties: {
name: { type: 'string' },
description: { type: 'string' },
done: { type: 'boolean' },
},
required: ['name'],
} as const; // const kullanmayı unutmayın!
Verilen FromSchema
tipi ile, şemanızdan bir tür oluşturabilir ve bunu işleyicinizde kullanabilirsiniz.
import { FromSchema } from "json-schema-to-ts";
fastify.post<{ Body: FromSchema<typeof todo> }>(
'/todo',
{
schema: {
body: todo,
response: {
201: {
type: 'string',
},
},
}
},
async (request, reply): Promise<void> => {
/*
request.body tipi
{
[x: string]: unknown;
description?: string;
done?: boolean;
name: string;
}
*/
request.body.name // tür hatası yok
request.body.notthere // tür hatası verir
reply.status(201).send();
},
);
Eklentiler
Fastify'ın en belirgin özelliklerinden biri, kapsamlı eklenti ekosistemidir. Eklenti türleri tamamen desteklenir ve declaration merging deseninden faydalanır. Bu örnek, bir TypeScript Fastify Eklentisi oluşturma, bir Fastify Eklentisi için tür tanımları oluşturma ve bir TypeScript Projesinde Fastify Eklentisi kullanma gibi üç parçaya bölünmüştür.
TypeScript Fastify Eklentisi Oluşturma
Yeni bir npm projesi başlatın ve gerekli bağımlılıkları yükleyin.
npm init -y
npm i fastify fastify-plugin
npm i -D typescript @types/nodepackage.json
dosyasının"scripts"
bölümüne birbuild
betiği ve"types"
bölümüne'index.d.ts'
ekleyin:{
"types": "index.d.ts",
"scripts": {
"build": "tsc -p tsconfig.json"
}
}TypeScript yapılandırma dosyasını başlatın:
npx typescript --init
Dosya oluşturulduktan sonra,
compilerOptions
nesnesinde"declaration"
seçeneğini etkinleştirin.{
"compilerOptions": {
"declaration": true
}
}Bir
index.ts
dosyası oluşturun - burası eklenti kodunu içerecek.index.ts
dosyasına aşağıdaki kodu ekleyin:import { FastifyPluginCallback, FastifyPluginAsync } from 'fastify'
import fp from 'fastify-plugin'
// declaration merging kullanarak, eklenti özelliklerinizi uygun fastify arayüzlerine ekleyin
// burada prop tipi tanımlanmışsa, değeri decorate{,Request,Reply} çağrıldığında tür kontrolüne tabi tutulacaktır
declare module 'fastify' {
interface FastifyRequest {
myPluginProp: string
}
interface FastifyReply {
myPluginProp: number
}
}
// seçenekleri tanımlayın
export interface MyPluginOptions {
myPluginOption: string
}
// geribildirim yöntemleri kullanarak eklentiyi tanımlayın
const myPluginCallback: FastifyPluginCallback<MyPluginOptions> = (fastify, options, done) => {
fastify.decorateRequest('myPluginProp', 'super_secret_value')
fastify.decorateReply('myPluginProp', options.myPluginOption)
done()
}
// promes kullanarak eklentiyi tanımlayın
const myPluginAsync: FastifyPluginAsync<MyPluginOptions> = async (fastify, options) => {
fastify.decorateRequest('myPluginProp', 'super_secret_value')
fastify.decorateReply('myPluginProp', options.myPluginOption)
}
// fastify-plugin kullanarak eklentiyi dışa aktarın
export default fp(myPluginCallback, '3.x')
// veya
// export default fp(myPluginAsync, '3.x')Eklenti kodunu derleyip hem bir JavaScript kaynak dosyası hem de bir tür tanım dosyası üretmek için
npm run build
komutunu çalıştırın.Eklenti tamamlandığında, [npm'ye yayınlayabilirsiniz] veya yerel olarak kullanabilirsiniz.
Eklentinizi npm'ye yayınlamanız gerekmez. Bunu bir Fastify projesine dahil edebilir ve kodunuzun herhangi bir parçası olarak referans verebilirsiniz! TypeScript kullanıcısı olarak, tür tanımını işlemesi için TypeScript yorumlayıcısının projede derlenmesinde bir yerde bulunmasını sağlamak önemlidir.