Skip to content

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.

server/shared/bookHelper.ts
typescript
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.

server/shared/dateHelper.ts
typescript
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:

bash
pnpm silgi prepare

3. Serviste Kullanım

Tüm servis handler'larında otomatik olarak erişebilirsiniz:

server/services/book.ts
typescript
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ı

server/shared/databaseHelper.ts
typescript
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ı

server/shared/bookApiHelper.ts
typescript
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:

typescript
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

  1. Tek Sorumluluk: Her yardımcı belirli bir amaç için olmalı.
  2. Tip Tanımları: Mümkün olduğunca kesin tipler kullanın.
  3. Dokümantasyon: Fonksiyonlarınızı JSDoc ile açıklayın.
  4. Kaynak Yönetimi: Ağır kaynakları (ör. veritabanı bağlantısı) bir kez oluşturun.
  5. Temiz Hatalar: Anlamlı hata mesajları ve özel hata tipleri kullanın.
  6. 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

typescript
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

typescript
import { shareds } from './server/silgi/scan'

export async function fetchBookDetailExternal(id: string) {
  const shared = shareds()
  return shared.fetchBookDetail(id)
}

Gelişmiş Örnek: Kitap Servisi

server/services/book.ts
typescript
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ı

server/services/book.ts
typescript
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
    }
  }
})

Released under the MIT License. (dev). Documentation design is a copy of vite.dev docs.