Veri modeli ve kayıt işlemleri
Uygulamanız kayıt tutuyorsa (talepler, rezervasyonlar, envanter, anket cevapları vb.) tabloyu, tipleri ve kayıt uçlarını elle yazmanız gerekmez. Kayıtların neye benzediğini one.data.json dosyasında tanımlarsınız; Devoplus One gerisini üretir:
- veritabanı tablosunu kuran şema değişikliği dosyası (migration;
one data generate), - TypeScript tipleri (
src/data/types.ts), - hazır kayıt uçları: listeleme, süzme, sıralama, sayfalama, ekleme, güncelleme, silme, Excel/CSV dışa aktarma ve yazdırma sayfası (SDK
createCrudHandler).
Sunucu tarafı doğrulama, Türkçe hata iletileri, "kim ekledi / kim değiştirdi" alanları ve yumuşak silme bu yolda hazırdır. Elle SQL yalnız bu modelin karşılamadığı özel bir sorgu gerektiğinde yazılır.
Ne zaman kullanılır
| İhtiyacınız | Yapılacak |
|---|---|
| "Talepleri kaydedip listeleyelim", "bir form doldurulsun, ben de göreyim" | Bir varlık (ör. talepler) + alanları |
| "Herkes yalnız kendi kaydını görsün" | createCrudHandler({ records: 'own' }) |
| "Yalnız yöneticiler onaylasın / düzenlesin" | Uygulama izni (permissions) + canWrite: 'One.<Uygulama>.<Eylem>' |
| "Durumu açık / kapalı / beklemede olsun" | choice alanı (sonradan seçenek eklenebilir ama çıkarılamaz; aşağıdaki sınıra bakın) |
| "Tutar girilsin" | money alanı (kuruş hassasiyetinde; yuvarlama yok) |
| "Sorumlu kişi seçilsin" | person alanı (kullanıcı kimliği) |
| "Ek dosya yüklensin" | file alanı + dosya deposu (services.files, OneFiles) |
Adımlar
Kayıtları planlayın: her kayıt türü için hangi bilgiler tutulacak, hangisi zorunlu, hangisi tekrar edemez (ör. talep numarası), seçimli alanların bütün seçenekleri, kim neyi görecek. Alan adlarını yapay zeka aracınız koyabilir; sizin kararınız işin kendisidir.
one.data.jsonyazın (uygulamanın kök dizini):json{ "version": 1, "entities": { "talepler": { "title": { "tr": "Talepler", "en": "Requests" }, "fields": { "baslik": { "type": "text", "title": { "tr": "Başlık", "en": "Title" }, "required": true, "maxLength": 120 }, "aciklama": { "type": "longText", "title": { "tr": "Açıklama", "en": "Description" } }, "tutar": { "type": "money", "title": { "tr": "Tutar", "en": "Amount" }, "min": 0 }, "durum": { "type": "choice", "title": { "tr": "Durum", "en": "Status" }, "required": true, "default": "acik", "index": true, "choices": [ { "value": "acik", "title": { "tr": "Açık", "en": "Open" } }, { "value": "onaylandi", "title": { "tr": "Onaylandı", "en": "Approved" } }, { "value": "reddedildi", "title": { "tr": "Reddedildi", "en": "Rejected" } } ] }, "son_tarih": { "type": "date", "title": { "tr": "Son tarih", "en": "Due date" } }, "sorumlu": { "type": "person", "title": { "tr": "Sorumlu", "en": "Owner" } } } } } }one data generateçalıştırın. Yeni şema değişikliği dosyası (migrations/NNNN_one_data.sql), tipler vemigrations/.one-data-snapshot.jsonyazılır. Üçünü de depoya ekleyin; anlık görüntü dosyası elle düzenlenmez.Uçları bağlayın (
src/index.ts):tsimport { createCrudHandler, problemResponse, readContext } from '@devoplus/one-sdk' import { dataModel } from './data/types.ts' const talepler = createCrudHandler({ model: dataModel, entity: 'talepler', records: 'shared', canWrite: 'One.Talep.Write' }) // fetch(request, env) içinde, kendi uçlarınızdan önce: const res = await talepler.handle(request, env.DB) if (res) return resone migrateile yerel veritabanını kurun,one devile deneyin. Yayında şema değişikliğini platform uygular.
Alan türleri
| Tür | Kullanıcının gördüğü | Not |
|---|---|---|
text | Kısa metin (tek satır) | maxLength varsayılan 200, en çok 1.000 |
longText | Uzun metin, açıklama | varsayılan 10.000, en çok 50.000; tekil ve dizinli olamaz |
number | Sayı | min / max |
money | Tutar | API'de "1250.50" metni; üçüncü ondalık ve binlik ayırıcı reddedilir |
date | Tarih | YYYY-AA-GG |
datetime | Tarih ve saat | gönderirken saat dilimi zorunlu (2026-10-18T09:00:00+03:00) |
boolean | Evet / hayır | |
choice | Listeden seçim | value kod (küçük harf, rakam, _, -), title görünen ad |
person | Kişi | kullanıcı kimliği; ad ve departman için organizasyon şeması okunur |
file | Dosya | dosya deposundaki anahtar |
Her alanda required, unique, index, default kullanılabilir. Adlar küçük harf, rakam ve alt çizgidir (son_tarih); order, group, not gibi veritabanı sözcükleri ve otomatik alan adları (id, created_at, created_by, updated_at, updated_by, deleted_at) kullanılamaz; komut hangi adın neden reddedildiğini söyler.
Uçlar
| Yöntem | Yol | Ne yapar |
|---|---|---|
| GET | /api/talepler?_page=1&_size=50&_sort=-created_at | sayfalı liste { items, page, pageSize, total } |
| GET | /api/talepler?durum=acik&baslik.contains=araç&tutar.from=100&son_tarih.to=2026-12-31 | süzme (eşitlik, içerir, aralık) |
| POST | /api/talepler | kayıt ekler |
| GET / PATCH / DELETE | /api/talepler/<id> | okur / gönderilen alanları günceller / siler (yumuşak) |
| GET | /api/talepler/export.xlsx, export.csv, report.html | aynı süzgeçlerle dışa aktarma (Rapor ve dışa aktarma) |
Hazır liste bileşeni bu uçlara doğrudan bağlanır: <one-table src="/api/talepler" paging="page" export="xlsx csv">. Uçlar bileşenin gönderdiği limit, page, cursor, sort + order, q (metin alanlarının herhangi birinde arama), <alan>From / <alan>To ve format=xlsx|csv parametrelerini de anlar; ayrıca bir çeviri yazmayın.
Hata yanıtı errors: [{ field, message }] taşır; iletiler Türkçedir ve formda alanın yanında olduğu gibi gösterilebilir. created_by ve updated_by oturumdan yazılır, gövdeyle gönderilemez.
Kurallar ve sınırlar
- Silme yumuşaktır. Her kayıt türü varsayılan olarak yumuşak silinir (
deleted_at). Kalıcı silme yalnız"softDelete": falseile birlikte en az 10 karakterlik"hardDeleteReason"gerekçesiyle seçilir; gerekçe yoksaone data generateve yayın durur. ModelcreateCrudHandler'a koddan verilirse gerekçesiz model kayıt uçlarında yapılandırma hatası (500) verir. - Model yalnız büyür. Yeni kayıt türü, yeni alan ve yeni dizin eklenebilir. Alan silmek, adını ya da türünü değiştirmek, isteğe bağlı bir alanı zorunlu yapmak (ya da tersi), tekilliği değiştirmek ve bir seçim alanından seçenek çıkarmak otomatik yapılmaz; komut hiçbir dosya yazmadan durur. Seçim alanına yeni seçenek eklemek serbesttir (şema değişikliği gerekmez;
one data generatetipleri yeniler). Seçeneklerin görünen adları ve başlıklar serbestçe değişir. - Var olan bir kayıt türüne zorunlu alan eklerken
defaultverin (eski kayıtlar o değeri alır). - Üretilmiş bir şema değişikliği dosyası, yayımlandıktan sonra değiştirilmez; değişiklik her zaman yeni bir dosyadır.
- En çok 30 kayıt türü, kayıt türü başına 60 alan (ve tabloda arama kolonları dahil en çok 100 kolon); liste sayfası en çok 200 kayıt, dışa aktarma varsayılan en çok 10.000 kayıt.
- Arama ("içerir" ve
q) büyük/küçük harfe ve Türkçe harflere duyarsızdır: "istanbul" "İSTANBUL"u, "cay" "Çay"ı bulur. Her metin alanının<alan>_foldadlı bir arama kolonu vardır (alan adı_foldile bitemez). Bir metin alanını elle yazdığınız SQL ile güncelliyorsanız arama kolonunu dafoldSearchText(değer)ile yazın ya daNULLyapın. - Vekalet ya da Yerine Görüntüle oturumunda kayıtlar varsayılan olarak yalnız görüntülenir; yazma gerekiyorsa manifest'te
actingSessions: "write"vecreateCrudHandler'daactingSessions: 'write'birlikte verilir. recordsseçeneği zorunludur: kayıtları kimin göreceğine siz karar verirsiniz (sharedherkes,ownyalnız ekleyen kişi). Rol gerekiyorsa e-posta listesi yazılmaz; uygulama izni istenir (erişim talebi).