KabaLang örnekleri: konsol, masaüstü ve web için dokuz proje
Konsol: fraktal (paralel şeritli 24-bit Mandelbrot/Julia + yakınlaşma), sudoku (geri izlemeli, canlı animasyon), fatura (JSON → terminal tablosu, PDF ve Excel). Masaüstü: hesap makinesi (işlem önceliği, canlı bağlama), odak (Pomodoro), parola atölyesi (entropi ölçer, SHA-256). Web: pano (Kanban REST API + SQLite), kisalt (302 yönlendirme, SVG istatistik), anket (adres başına tek oy, sunucuda çizilen grafik). Hepsi `kabalang calistir` ile derlenip çalışır; web uygulamaları yalnız 127.0.0.1'i dinler, SQL parametre bağlamalı, HTML çıktısı kaçırılır.
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ PANO — KabaLang ile Kanban görev panosu ║
|
||||
# ║ ║
|
||||
# ║ · JSON REST API: GET · POST · PUT · DELETE /api/gorevler ║
|
||||
# ║ · Kalıcı kayıt: SQLite, her sorgu PARAMETRE BAĞLAMALI ║
|
||||
# ║ · Ön yüz: arayuz.html (tek sayfa, dış bağımlılık yok) ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
#
|
||||
# Çalıştır: cd web/pano && kabalang calistir pano.kbl
|
||||
# Aç: http://127.0.0.1:8471
|
||||
|
||||
kullan kaba.web
|
||||
kullan kaba.json
|
||||
kullan kaba.veritabani
|
||||
kullan kaba.sistem
|
||||
|
||||
# Panoda yalnız bu üç sütun vardır. Kapalı küme → istemciden gelen
|
||||
# sütun adı bu listede değilse istek reddedilir.
|
||||
SUTUNLAR = ["yapilacak", "suruyor", "bitti"]
|
||||
ONCELIKLER = ["dusuk", "orta", "yuksek"]
|
||||
|
||||
db = cevre.al("PANO_DB")
|
||||
eger db == "":
|
||||
db = "pano.db"
|
||||
|
||||
# ── Veritabanı ──────────────────────────────────────────────────────
|
||||
|
||||
fonksiyon hazirla(db):
|
||||
veritabani.sqlite(db, "CREATE TABLE IF NOT EXISTS gorev(id INTEGER PRIMARY KEY AUTOINCREMENT, baslik TEXT NOT NULL, aciklama TEXT DEFAULT '', sutun TEXT NOT NULL, oncelik TEXT DEFAULT 'orta', olusturma TEXT);")
|
||||
|
||||
# İlk açılışta pano boş görünmesin: birkaç örnek kart.
|
||||
eger veritabani.sqlite(db, "SELECT count(*) FROM gorev") == "0":
|
||||
ornekler = [
|
||||
["Giriş ekranını tasarla", "Koyu tema, mobil öncelikli", "bitti", "yuksek"],
|
||||
["REST API taslağı", "GET · POST · PUT · DELETE uçları", "bitti", "orta"],
|
||||
["SQLite şeması", "Parametre bağlamalı sorgular", "suruyor", "yuksek"],
|
||||
["Sürükle-bırak kartlar", "Sütunlar arası taşıma", "suruyor", "orta"],
|
||||
["Bildirim e-postaları", "Görev atanınca haber ver", "yapilacak", "dusuk"],
|
||||
["Karanlık/aydınlık tema", "Sistem tercihine uy", "yapilacak", "orta"],
|
||||
["Yük testi", "1000 eşzamanlı istek", "yapilacak", "yuksek"]
|
||||
]
|
||||
dongu o icinde ornekler:
|
||||
veritabani.sqlite(db, "INSERT INTO gorev(baslik, aciklama, sutun, oncelik, olusturma) VALUES (?, ?, ?, ?, ?)", [o[0], o[1], o[2], o[3], zaman.simdi()])
|
||||
|
||||
# Bütün görevleri JSON dizi olarak verir. JSON'u SQLite'ın kendi
|
||||
# json_object/json_group_array işlevleri kurar → elle kaçış yazmayız.
|
||||
fonksiyon gorevler_json(db):
|
||||
sonuc = veritabani.sqlite(db, "SELECT json_group_array(json_object('id', id, 'baslik', baslik, 'aciklama', aciklama, 'sutun', sutun, 'oncelik', oncelik, 'olusturma', olusturma)) FROM (SELECT * FROM gorev ORDER BY id)")
|
||||
eger sonuc == "":
|
||||
don "[]"
|
||||
don sonuc
|
||||
|
||||
fonksiyon gorev_json(db, kimlik):
|
||||
don veritabani.sqlite(db, "SELECT json_object('id', id, 'baslik', baslik, 'aciklama', aciklama, 'sutun', sutun, 'oncelik', oncelik, 'olusturma', olusturma) FROM gorev WHERE id = ?", [kimlik])
|
||||
|
||||
# ── Doğrulama ───────────────────────────────────────────────────────
|
||||
|
||||
fonksiyon hata_json(ileti, durum):
|
||||
don web.json(json.uret({"hata": ileti}), durum)
|
||||
|
||||
# Kimlik yalnız rakamlardan oluşmalı; "1 OR 1=1" gibi bir değer
|
||||
# zaten parametre olarak bağlanır, ama anlamsız istek erkenden döner.
|
||||
fonksiyon kimlik_gecerli(k):
|
||||
eger k.uzunluk() == 0 veya k.uzunluk() > 9:
|
||||
don yanlis
|
||||
dongu i icinde 0..k.uzunluk() - 1:
|
||||
eger degil "0123456789".icerir(k.dilim(i, 1)):
|
||||
don yanlis
|
||||
don dogru
|
||||
|
||||
# ── Uçlar ───────────────────────────────────────────────────────────
|
||||
|
||||
hazirla(db)
|
||||
|
||||
arayuz = dosya.oku("arayuz.html")
|
||||
eger arayuz == "":
|
||||
yazdir("⚠ arayuz.html bulunamadı — programı web/pano klasöründen çalıştırın.")
|
||||
|
||||
fonksiyon ana_sayfa(_istek):
|
||||
don web.html(arayuz)
|
||||
|
||||
fonksiyon listele(_istek):
|
||||
don web.json(gorevler_json(db))
|
||||
|
||||
fonksiyon olustur(istek):
|
||||
govde = istek.govde()
|
||||
eger degil json.gecerli_mi(govde):
|
||||
don hata_json("gövde geçerli JSON değil", 400)
|
||||
baslik = json.al(govde, "baslik").kirp()
|
||||
aciklama = json.al(govde, "aciklama").kirp()
|
||||
sutun = json.al(govde, "sutun")
|
||||
oncelik = json.al(govde, "oncelik")
|
||||
eger baslik == "":
|
||||
don hata_json("başlık boş olamaz", 422)
|
||||
eger baslik.uzunluk() > 120:
|
||||
don hata_json("başlık en çok 120 karakter", 422)
|
||||
eger sutun == "":
|
||||
sutun = "yapilacak"
|
||||
eger oncelik == "":
|
||||
oncelik = "orta"
|
||||
eger degil SUTUNLAR.icerir(sutun):
|
||||
don hata_json("bilinmeyen sütun: " + sutun, 422)
|
||||
eger degil ONCELIKLER.icerir(oncelik):
|
||||
don hata_json("bilinmeyen öncelik: " + oncelik, 422)
|
||||
|
||||
veritabani.sqlite(db, "INSERT INTO gorev(baslik, aciklama, sutun, oncelik, olusturma) VALUES (?, ?, ?, ?, ?)", [baslik, aciklama, sutun, oncelik, zaman.simdi()])
|
||||
yeni = veritabani.sqlite(db, "SELECT max(id) FROM gorev")
|
||||
don web.json(gorev_json(db, yeni), 201)
|
||||
|
||||
fonksiyon guncelle(istek):
|
||||
kimlik = istek.parametre("id")
|
||||
eger degil kimlik_gecerli(kimlik):
|
||||
don hata_json("geçersiz kimlik", 400)
|
||||
eger veritabani.sqlite(db, "SELECT count(*) FROM gorev WHERE id = ?", [kimlik]) == "0":
|
||||
don hata_json("görev bulunamadı", 404)
|
||||
govde = istek.govde()
|
||||
eger degil json.gecerli_mi(govde):
|
||||
don hata_json("gövde geçerli JSON değil", 400)
|
||||
|
||||
# Yalnız gönderilen alanlar güncellenir.
|
||||
sutun = json.al(govde, "sutun")
|
||||
eger sutun != "":
|
||||
eger degil SUTUNLAR.icerir(sutun):
|
||||
don hata_json("bilinmeyen sütun: " + sutun, 422)
|
||||
veritabani.sqlite(db, "UPDATE gorev SET sutun = ? WHERE id = ?", [sutun, kimlik])
|
||||
baslik = json.al(govde, "baslik").kirp()
|
||||
eger baslik != "":
|
||||
veritabani.sqlite(db, "UPDATE gorev SET baslik = ? WHERE id = ?", [baslik, kimlik])
|
||||
oncelik = json.al(govde, "oncelik")
|
||||
eger oncelik != "":
|
||||
eger degil ONCELIKLER.icerir(oncelik):
|
||||
don hata_json("bilinmeyen öncelik: " + oncelik, 422)
|
||||
veritabani.sqlite(db, "UPDATE gorev SET oncelik = ? WHERE id = ?", [oncelik, kimlik])
|
||||
don web.json(gorev_json(db, kimlik))
|
||||
|
||||
fonksiyon kaldir(istek):
|
||||
kimlik = istek.parametre("id")
|
||||
eger degil kimlik_gecerli(kimlik):
|
||||
don hata_json("geçersiz kimlik", 400)
|
||||
eger veritabani.sqlite(db, "SELECT count(*) FROM gorev WHERE id = ?", [kimlik]) == "0":
|
||||
don hata_json("görev bulunamadı", 404)
|
||||
veritabani.sqlite(db, "DELETE FROM gorev WHERE id = ?", [kimlik])
|
||||
don web.yanit("", 204)
|
||||
|
||||
# Tek iş parçacığı: SQLite'a yazan işleyiciler sırayla koşar.
|
||||
sunucu = web.sunucu(8471, "127.0.0.1", 1)
|
||||
sunucu.hatalar_json()
|
||||
sunucu.govde_siniri(16384)
|
||||
|
||||
sunucu.al("/", ana_sayfa)
|
||||
sunucu.al("/api/gorevler", listele)
|
||||
sunucu.gonder("/api/gorevler", olustur)
|
||||
sunucu.guncelle("/api/gorevler/{id}", guncelle)
|
||||
# DELETE yöntemi `sunucu.kaldir` ile bağlanır
|
||||
sunucu.kaldir("/api/gorevler/{id}", kaldir)
|
||||
|
||||
yazdir("📋 Pano hazır — http://127.0.0.1:8471")
|
||||
sunucu.basla()
|
||||
Reference in New Issue
Block a user