createShared Kullanımı
Silgi'nin en güçlü özelliklerinden biri, servisler arasında ortak fonksiyon ve verilere erişimi sağlayan shared
sistemidir. Paylaşılan yardımcılar, kodunuzu modülerleştirir, tekrarları azaltır ve bakımı kolaylaştırır.
Neden Paylaşılan Yardımcılar Kullanılır?
- Kod Tekrarını Azaltır: Ortak işlevleri bir kez tanımlayın, tüm servislerde kullanın.
- Tutarlılık Sağlar: İş mantığını merkezileştirerek aynı davranışı garanti eder.
- Modülerlik: Karmaşık işlevleri küçük, yeniden kullanılabilir parçalara böler.
- Verimlilik: Kaynakları (ör. veritabanı bağlantısı) paylaşarak performansı artırır.
- Test Edilebilirlik: Ortak mantığı izole edip kolayca test edebilirsiniz.
- Ekip İçi İşbirliği: Kod paylaşımını kolaylaştırır.
- Modüller Arası İletişim: Veri ve işlev paylaşımını basitleştirir.
Temel Kullanım
createShared
Fonksiyonu
Paylaşılan yardımcılarınızı oluşturmak için ana fonksiyon createShared
'dir. Tüm yardımcı arayüzleriniz ExtendShared
'den türemelidir.
import type { ExtendShared } from 'silgi/types'
import { createShared } from 'silgi'
export interface BookHelper extends ExtendShared {
formatBookName: (name: string) => string
}
export const bookHelper = createShared({
formatBookName: name => `[BOOK] ${name}`,
})
ExtendShared
Arayüzü
- CLI Entegrasyonu: Silgi CLI, paylaşılan yardımcılarınızı otomatik tanır.
- Tip Genişletme: Silgi'nin tiplerini kendi yardımcı tiplerinizle genişletir.
- Tutarlılık: Tüm yardımcılar ortak bir taban tipine sahip olur.
Adım Adım Paylaşılan Yardımcı Oluşturma
1. Yardımcı Dosyasını Oluşturun
Genellikle server/shared
altında tanımlanır.
import type { ExtendShared } from 'silgi/types'
import { createShared } from 'silgi'
export interface DateHelper extends ExtendShared {
formatDate: (date: Date) => string
dateDiffInDays: (start: Date, end: Date) => number
}
export const dateHelper = createShared({
formatDate: date => date.toISOString().split('T')[0],
dateDiffInDays: (start, end) => {
const diffMs = end.getTime() - start.getTime()
return Math.floor(diffMs / (1000 * 60 * 60 * 24))
}
})
Dikkat
Paylaşılan yardımcılarınız mutlaka export const
ve export interface
ile başlamalıdır. Aksi halde CLI tarafından algılanmaz.
2. Hazırlık
Yardımcılarınızı tanımladıktan sonra CLI'nın bunları taraması için:
pnpm silgi prepare
3. Serviste Kullanım
Tüm servis handler'larında otomatik olarak erişebilirsiniz:
import { createError, createService } from 'silgi'
export const getBookByIdService = createService({
path: 'GET:/api/library/books/:id',
setup: {
handler: async (input, shared) => {
const bookId = input.parameters.path?.id
if (!bookId)
throw createError({ statusCode: 400, message: 'Book ID is required' })
// Paylaşılan yardımcı kullanımı
const name = shared.formatBookName('Sample Book')
return {
id: bookId,
name,
description: 'Sample Description',
author: { id: 'auth-1', name: 'John Doe' }
}
}
}
})
Gelişmiş Kullanım
Veritabanı Yardımcısı
import type { ExtendShared } from 'silgi/types'
import { createClient } from 'database-lib'
import { createShared } from 'silgi'
export interface DatabaseHelper extends ExtendShared {
getUser: (id: string) => Promise<any>
getOrder: (id: string) => Promise<any>
dbClient: ReturnType<typeof createClient>
}
const dbClient = createClient({ connectionString: process.env.DATABASE_URL })
export const databaseHelper = createShared({
getUser: id => dbClient.query('SELECT * FROM users WHERE id = $1', [id]),
getOrder: id => dbClient.query('SELECT * FROM orders WHERE id = $1', [id]),
dbClient,
})
Dış API Yardımcısı
import type { ExtendShared } from 'silgi/types'
import { createShared } from 'silgi'
import { localConfig } from '../silgi/configs'
import { createBookApiClient } from '../utils/bookApi'
export interface BookApiHelper extends ExtendShared {
fetchBookDetail: (id: string) => Promise<any>
searchBooks: (query: string) => Promise<any[]>
apiClient: ReturnType<typeof createBookApiClient>
}
const apiClient = createBookApiClient({
apiKey: localConfig.book.apiKey,
baseUrl: localConfig.book.baseUrl
})
export const bookApiHelper = createShared({
fetchBookDetail: id => apiClient.getBookDetail(id),
searchBooks: query => apiClient.searchBooks(query),
apiClient,
})
shared
Nesnesinin İçeriği
Bir servis handler'ında shared
parametresiyle şunlara erişebilirsiniz:
- Tüm Paylaşılan Yardımcılar: Tanımladığınız tüm yardımcılar (örn.
shared.formatBookName
,shared.fetchBookDetail
). - Storage: Key-value depolama (örn.
shared.storage('cache').setItem(...)
). - Runtime Config: Çalışma zamanı yapılandırması (örn.
shared.useRuntimeConfig()
). - Framework Context: Altyapı bağlamı.
Kullanım örneği:
handler: async (input, shared) => {
const bookId = input.parameters.path?.id
const book = await shared.getBook(bookId)
const formattedName = shared.formatBookName(book.name)
await shared.storage('cache').setItem(`book:${book.id}`, book, { ttl: 3600 })
const apiKey = shared.getBookApiKey()
return { ...book, formattedName, apiKey }
}
En İyi Uygulamalar
- Tek Sorumluluk: Her yardımcı belirli bir amaç için olmalı.
- Tip Tanımları: Mümkün olduğunca kesin tipler kullanın.
- Dokümantasyon: Fonksiyonlarınızı JSDoc ile açıklayın.
- Kaynak Yönetimi: Ağır kaynakları (ör. veritabanı bağlantısı) bir kez oluşturun.
- Temiz Hatalar: Anlamlı hata mesajları ve özel hata tipleri kullanın.
- Test Edilebilirlik: Yardımcılarınızı bağımsız ve test edilebilir tasarlayın.
Sıkça Sorulan Sorular
Farklı Ortamlar İçin Yardımcılar
export const bookDbHelper = createShared({
connect: () => {
if (process.env.NODE_ENV === 'test')
return connectToTestDb()
return connectToProdDb()
}
})
Servis Dışında Paylaşılan Yardımcıya Erişim
import { shareds } from './server/silgi/scan'
export async function fetchBookDetailExternal(id: string) {
const shared = shareds()
return shared.fetchBookDetail(id)
}
Gelişmiş Örnek: Kitap Servisi
import type { ExtendShared } from 'silgi/types'
import { createError, createService, createShared } from 'silgi'
// SHARED
export interface BookHelper extends ExtendShared {
formatBookName: (name: string) => string
}
export const bookHelper = createShared({
formatBookName: (name: string) => `[BOOK] ${name}`,
})
// SERVICE
export const getBookByIdService = createService({
path: 'GET:/api/library/books/:id',
setup: {
handler: async (input, shared) => {
const bookId = input.parameters.path?.id
const includeAuthor = input.parameters.query?.includeAuthor ?? true
const format = input.parameters.query?.format ?? 'full'
if (!bookId) {
throw createError({
statusCode: 400,
message: 'Book ID is required',
})
}
// Paylaşılan yardımcı kullanımı
const name = shared.formatBookName('Sample Book')
const book = {
id: bookId,
name,
description: format === 'full' ? 'Sample Description' : undefined,
author: includeAuthor
? { id: 'auth-1', name: 'John Doe' }
: undefined,
}
return book
}
}
})
Gelişmiş Örnek: Birden Fazla Yardımcı Kullanımı
import { createError, createService } from 'silgi'
export const listBooksService = createService({
path: 'GET:/api/library/books/list',
setup: {
handler: async (input, shared) => {
shared.logInfo('İlgili kitaplar getiriliyor')
const { category, limit, offset } = input.parameters.query || {}
const cacheKey = `books:${category}:${limit}:${offset}`
const cachedBooks = await shared.storage('cache').getItem(cacheKey)
if (cachedBooks) {
shared.logHelper.logInfo('Kitaplar önbellekten alındı')
return cachedBooks
}
const rawBooks = await shared.searchBooks({ category, limit, offset })
const books = rawBooks.map(book => ({
...book,
name: shared.formatBookName(book.name)
}))
await shared.storage('cache').setItem(cacheKey, books, { ttl: 600 })
shared.incrementCounter('books_searched')
return books
}
}
})