Skip to content

Servis Spec'i (spec.yaml) ​

Bir servis tek bir YAML dosyasıyla tarif edilir. Designer bu dosyayı okur ve yazar; baseforge new-service --spec <dosya> bu dosyadan servis üretir.

Eksiksiz bir örnek ​

yaml
service: blog
database: blog_db

auth:
  authority: http://host.docker.internal:8081
  audience: baseforge-api
  protect: true
  defaultAccess: authenticated
  superRoles: [SuperAdmin]

corsOrigins: [http://localhost:5173]

entities:
  Post:
    props:
      Title: { type: string, maxLength: 200 }
      Body: text
      Status: { type: enum, values: [Draft, Published], default: Draft }
      AuthorId: guid
      ViewCount: int
    counters: [ViewCount]
    ownerField: AuthorId
    access:
      list: anonymous
      getById: anonymous
      update: [Admin, owner]
      delete: [Admin]
    filterable: [Status, AuthorId]
    readFilter:
      where: { Status: Published }
      bypassRoles: [Admin]
      bypassOwner: true
    externalRefs:
      author: { target: identity/User, store: AuthorId, via: grpc }

  Comment:
    props:
      Body: text
    relations:
      post: { kind: many-to-one, target: Post }
    publishes: [created]

subscribes:
  - event: blog/CommentCreated
    handler: NotifyPostAuthorOnComment

Servis seviyesi anahtarlar ​

AnahtarTipAçıklama
servicestringServis adı — proje, namespace ve klasör buradan türetilir
databasestringPostgreSQL veritabanı adı
entitiesmapEntity adı → entity tanımı (aşağıda)
authobjectMerkezi Identity'ye JWT bağlantısı — herkese açık servis için yazma
auth.authority / auth.audiencestringIdentity adresi ve API audience'ı (varsayılan baseforge-api)
auth.protectboolController'lara [Authorize] koy (varsayılan true)
auth.defaultAccesskuralEntity'nin access'inde belirtilmeyen action'lar için erişim (varsayılan authenticated)
auth.superRoleslisteTüm rol ve sahiplik kurallarını geçen roller
multiTenantboolHer entity'ye TenantId + izolasyon ekle (detay)
corsOriginslisteİzinli tarayıcı origin'leri (Cors:AllowedOrigins)
dockerPortsobjectrest, grpc, postgres host portları (boş = varsayılan)
rabbitMqTuningobjectoutboxMaxRetries, outboxRetentionDays
subscribeslisteServisin dinlediği event'ler: event: servis/EntityKind, handler: SınıfAdı
gatewayobjectproxiedServices: [a, b] — diğer servisleri YARP ile /api/gateway/{servis} altında sun

Entity anahtarları ​

AnahtarTipAçıklama
propsmapAlan adı → tip (kısa form) veya alan objesi (zengin form)
relationsmapAynı servisteki entity'lerle ilişkiler
externalRefsmapDiğer servislerdeki entity'lere referanslar
publisheslistecreated / updated / deleted — outbox üzerinden integration event yayınla
accessmapAction başına kural: list, getById, create, update, delete
ownerFieldstringCreate'te çağıranın id'siyle damgalanan bir guid alan
anonymousActionslisteaccess: { action: anonymous } için eski kısa yazım
filterablelisteListe ucunda eşitlik filtresi olarak açılan alanlar
readFilterobjectSatır görünürlüğü: where, bypassRoles, bypassOwner
counterslisteHerkese açık POST /{id}/increment-{alan} ucu alan int alanlar
appendOnlyboolUpdate/Delete hiç üretilmez (audit/trace kayıtları)
paginated / sortable / searchableboolListe davranışı (hepsi varsayılan true)

Alan tipleri ​

Spec tipiC# tipiPostgreSQL tipi
string, textstringtext
int / long / shortint / long / shortinteger / bigint / smallint
decimaldecimalnumeric
double / floatdouble / floatdouble precision / real
boolboolboolean
datetimeDateTimeOffsettimestamptz
dateDateOnlydate
guid, uuidGuiduuid
jsonstringjsonb
enumüretilen C# enum'utext (adıyla saklanır)

Kısa ve zengin form birlikte kullanılabilir:

yaml
props:
  Title: string                                     # kısa form
  Sku: { type: string, maxLength: 32 }              # zengin form
  Discount: { type: decimal, nullable: true }
  Status: { type: enum, values: [Draft, Active], default: Draft }

Zengin form anahtarları: type, nullable, maxLength (yalnızca string/text), default, values (yalnızca enum).

İlişkiler ​

yaml
relations:
  category: { kind: many-to-one, target: Category, nullable: true }
  lines:    { kind: one-to-many, target: OrderLine }

kind değeri one-to-many, many-to-one veya one-to-one olur. many-to-one/one-to-one bu entity'ye bir foreign key ({İlişki}Id) ekler; nullable: true onu opsiyonel yapar.

Dış referanslar ​

yaml
externalRefs:
  product: { target: products/Product, store: ProductId, via: grpc }

Foreign key oluşturulmaz — yalnızca bir ID kolonu (store). via: grpc ile BaseForge tipli bir gRPC istemcisi üretir. Bu dosyanın yanında kardeş bir spec (products.yaml) bulunursa istemci hedefin gerçek alanlarını taşır; bulunamazsa yalnızca ID içeren bir stub'a düşer. identity/User her zaman kullanılabilir.

Erişim kuralları ​

Bir kural şunlardan biridir:

  • anonymous — giriş gerekmez
  • authenticated — giriş yapmış herhangi bir kullanıcı
  • bir rol listesi, ör. [Admin, Editor] — istenirse owner da içerebilir

owner, "id'si ownerField'da olan kullanıcı" demektir. Sahip olmayanlar update/delete'te 403, başkasının kaydına getById'de 404 alır, list'te ise yalnızca kendi satırlarını görür. Modelin tamamı için bkz. Mimari §6.1.

Doğrulama ​

Spec'ler herhangi bir kod yazılmadan önce doğrulanır — geçersiz kombinasyonlar (ör. int üzerinde maxLength, append-only bir entity'nin publishes'ında updated, ownerField olmadan owner kuralı) bozuk kod üretmek yerine açık bir mesajla hata verir.

MIT Lisansı ile yayınlanmıştır.