TecofApiClient, editörün ve alanların Tecof backend’iyle konuştuğu istemcidir. TecofProvider bir örneğini oluşturup bağlama koyar (useTecof().apiClient); sunucu tarafında doğrudan da oluşturabilirsiniz.
import { TecofApiClient } from "@tecof/theme-editor";
const client = new TecofApiClient(
process.env.NEXT_PUBLIC_BASE_URL!, // apiUrl (sondaki / temizlenir)
process.env.NEXT_PUBLIC_MERCHANT_SECRET_KEY!, // secretKey → x-secret-key
process.env.NEXT_PUBLIC_CDN_URL, // cdnUrl (verilmezse apiUrl)
undefined, // accessToken (JWT, yazma uçları için)
process.env.NEXT_PUBLIC_THEME_ID, // themeId
);
const page = await client.getPublishedPage("anasayfa", "tr");
if (page.success && page.data) console.log(page.data.title);Kimlik#
Her istek x-secret-key başlığını taşır. Vitrin anahtarı tarayıcı paketine girdiği için backend yazma uçlarında (sayfa kaydetme, yükleme, ortak bileşen, stil senkronu) ayrıca kullanıcı JWT’si ister: setAccessToken(token) ya da kurucunun 4. argümanı ile verilir ve Authorization başlığına yazılır. Editörde bu token TecofEditor’ün accessToken prop’undan gelir.
themeId verilirse sayfa okuma, kaydetme ve listeleme istekleri o temaya gider; verilmezse backend mağazanın aktif temasına düşer (çok temalı mağazada yanlış temanın sayfaları gelir).
Metotlar#
| Metot | Uç | Açıklama |
|---|---|---|
getPage(id, signal?, revisionId?) | GET /api/store/editor/:id | Editör taslağı; revisionId ile revizyon anlık görüntüsü |
savePage(id, draftData, title?, accessToken?) | PUT /api/store/editor/:id | Taslağı kaydeder ({ draftData, title?, themeId? }) |
getPublishedPage(slug, locale?) | POST /api/store/render | Yayınlanmış sayfa |
getMerchantInfo() | GET /api/store/merchant-info | Diller, varsayılan dil, ürün tipi, Powered by bandı, askı/yapım bayrakları |
uploadFile(file, folder?) | POST /api/store/upload | Çok parçalı yükleme (alan adı files) |
getUploads(page = 1, limit = 50) | GET /api/store/uploads | Medya kütüphanesi |
getPages() | GET /api/store/pages | Bağlantı seçici için sayfa listesi (_id, slug, title, status, metaTitle) |
translate(text, sourceLang, locales, isHtml = false) | POST /api/store/translate | Çoklu dil çevirisi → [{ code, value }] |
searchStockMedia(query, { provider?, page?, perPage?, orientation? }) | GET /api/store/stock-media/search | Stok görsel arama |
importStockMedia({ provider, downloadUrl, id?, alt? }) | POST /api/store/stock-media/import | Stok görseli kütüphaneye alır |
getCmsCollections() | POST /api/store/cms/collections | Koleksiyonlar |
getCmsCollectionItems(slug, { page, limit, sort, locale, filters, sortBy, sortDir }) | POST /api/store/cms/collections/:slug/items | Canlı öğeler → { items, totalData } |
getSharedComponents() · createSharedComponent(name, type, props) · updateSharedComponent(id, name, type, props) · deleteSharedComponent(id) | /api/store/shared-components | Ortak bileşenler |
previewApplyStyles(payload) · applyStylesToPages(payload) | POST /api/store/editor/apply-styles | Sayfalar arası stil (önizleme / uygulama) |
getComponentPreview(domain, componentName) | POST /api/store/component-preview | Bileşen önizleme görseli (blob URL, önbellekli) |
getEcommerceCategories(locale) · getEcommerceBrands(locale) · getEcommerceProducts(…) | GET /api/store/ecommerce/* | Vitrin e-ticaret listeleri |
getEcommerceTags · getEcommerceAttributes · getEcommerceVariantTypes · getEcommerceFlashSales · getEcommerceCampaigns · getEcommerceDiscounts | GET /api/merchant/ecommerce/* | Panel listeleri (JWT + x-merchant-id; kimlik merchant-info’dan bir kez çözülür) |
setAccessToken(token?) · getAccessToken() | — | JWT yönetimi |
setMerchantId(id?) | — | Panel uçları için mağaza kimliğini elle verir |
getRealtimeConfig() | — | Canlı katılım soketi için { url, token } |
cdnUrl | — | Medya adresleri için CDN kökü |
Hata modeli#
Metotların çoğu ağ hatasını fırlatmak yerine { success: false, message } zarfına çevirir; başarılı yanıt { success: true, data } biçimindedir:
const res = await client.savePage(pageId, draftData);
if (!res.success) {
console.error(res.message);
}İstisna: getPage iptal edilen istekleri ayırt edebilmeniz için AbortError’ı yeniden fırlatır (yeni yükleme eskisini geçersiz kıldığında eski sonucu yok saymak için):
const controller = new AbortController();
try {
const res = await client.getPage(pageId, controller.signal);
} catch (error) {
if (error instanceof DOMException && error.name === "AbortError") return; // iptal, hata değil
throw error;
}Pratik notlar#
- Yükleme isteğinde
Content-Type’ı elle vermeyin; çok parçalı sınırı tarayıcı ekler. - Backend’in
x-secret-keyveAuthorizationbaşlıklarına CORS izni verdiğinden emin olun. - CDN adresi kuran kodda dosyanın
folderalanını hesaba katın; klasörsüz${cdnUrl}/${name}kapsamlı klasördeki dosyada 404 verir.TecofPicturebunu sizin yerinize yapar.