Anatomija celotne Orbital enote
Vsaka funkcionalnost v Orb je Orbital enota. Orbital enota ni popolna brez vseh stirih delov.
Stirje deli Orbital enote
Orbital enota je temeljna enota Orb aplikacije. Vsebovati mora:
Orbital enota = Entiteta + Lastnost(i) + Avtomat stanj + Strani
| Del | Namen | Brez njega... |
|---|---|---|
entity | Katere podatke upravljate | Ni podatkov za delo |
traits | Kako se aplikacija obnasa | Ni obnasanja ali UI |
stateMachine | Stanja, dogodki in prehodi | Ni definiranega zivljenjskega cikla |
pages | Kje se UI pojavi (poti) | Stran se nalozi prazna - nic se ne upodobi |
Strani so najpogosteje pozabljen del. Brez pages lastnost obstaja, a ni nikoli prikljucena na pot - uporabnik ne vidi nicesar.
Korak 1 - Definirajte entiteto
Entiteta je vasa podatkovna struktura. Opisuje, kaj upravljate in kako se shranjuje.
{
"name": "Task",
"persistence": "persistent",
"collection": "tasks",
"fields": [
{ "name": "id", "type": "string", "required": true },
{ "name": "title", "type": "string", "required": true },
{ "name": "status", "type": "enum", "values": ["pending", "done"], "default": "pending" }
]
}
Tipi polj: string, number, boolean, date, timestamp, enum, array, object, relation
Nacini trajnosti:
persistent- shranjeno v podatkovni bazi (Firestore, PostgreSQL)runtime- v pomnilniku, specificno za sejo (voz, stanje carovnika)singleton- en globalni primerek (konfiguracija aplikacije, trenutni uporabnik)
Korak 2 - Definirajte avtomat stanj
Avtomat stanj zivi znotraj lastnosti. Opisuje, v katerih stanjih je lahko funkcionalnost in kateri dogodki povzrocijo prehode.
Stanja
Vsak avtomat stanj potrebuje vsaj eno stanje, oznaceno z "isInitial": true. Stanja so objekti, ne nizi:
"states": [
{ "name": "Pending", "isInitial": true },
{ "name": "Done", "isTerminal": true }
]
Dogodki
Dogodki so sprozilci - uporabniska dejanja, sistemski dogodki ali zivljenjski kljuki:
"events": [
{ "key": "INIT", "name": "Initialize" },
{ "key": "COMPLETE", "name": "Complete Task" }
]
INITje obvezen. Brez prehoda INIT se stran nalozi, a ne upodobi nicesar.
Prehodi
Prehodi povezejo stanja in dogodke skupaj. Lahko nosijo pogoje (izrazi) in ucinke (dejanja):
"transitions": [
{
"from": "Pending",
"event": "INIT",
"to": "Pending",
"effects": [
["fetch", "Task"],
["render-ui", "main", {
"type": "entity-table",
"entity": "Task",
"columns": ["title", "status"],
"itemActions": [
{ "event": "COMPLETE", "label": "Complete" }
]
}]
]
},
{
"from": "Pending",
"event": "COMPLETE",
"to": "Done",
"effects": [
["persist", "update", "Task", "@entity"],
["notify", "success", "Task completed!"]
]
}
]
Korak 3 - Zgradite lastnost
Ovijte avtomat stanj v lastnost z name, linkedEntity in category:
{
"name": "TaskLifecycle",
"linkedEntity": "Task",
"category": "interaction",
"stateMachine": {
"states": [
{ "name": "Pending", "isInitial": true },
{ "name": "Done", "isTerminal": true }
],
"events": [
{ "key": "INIT", "name": "Initialize" },
{ "key": "COMPLETE", "name": "Complete Task" }
],
"transitions": [
{
"from": "Pending",
"event": "INIT",
"to": "Pending",
"effects": [
["fetch", "Task"],
["render-ui", "main", {
"type": "entity-table",
"entity": "Task",
"columns": ["title", "status"],
"itemActions": [
{ "event": "COMPLETE", "label": "Complete" }
]
}]
]
},
{
"from": "Pending",
"event": "COMPLETE",
"to": "Done",
"effects": [
["persist", "update", "Task", "@entity"],
["notify", "success", "Task completed!"]
]
}
]
}
}
category je lahko:
interaction- ima UI, oddaja ucinkerender-uiintegration- klici zalednih storitev, brez UI
Korak 4 - Dodajte strani
Strani vezejo lastnosti na URL poti. To je del, ki najpogosteje manjka.
"pages": [
{
"name": "TaskListPage",
"path": "/tasks",
"traits": [
{ "ref": "TaskLifecycle", "linkedEntity": "Task" }
]
}
]
pathje URL pot (podpira parametre:id, npr./tasks/:id)traits[].refse sklicuje na lastnost po imenu, definirano v isti Orbital enotitraits[].linkedEntitypove izvajalnemu okolju, katero entiteto naj veze
Celotna Orbital enota
Vse skupaj - popolnoma delujoce Orbital enota TaskManager:
;; app TaskManager
orbital Tasks {
entity Task [persistent: tasks] {
id : string!
title : string!
status : string
}
trait TaskLifecycle -> Task [interaction] {
initial: Pending
state Pending {
INIT -> Pending
(fetch Task)
(render-ui main { type: "entity-table", entity: "Task", fields: ["title", "status"], columns: ["title", "status"], itemActions: [{ event: "COMPLETE", label: "Complete" }] })
COMPLETE -> Done
(persist update Task @entity)
(notify success "Task completed!")
}
state Done {}
}
page "/tasks" -> TaskLifecycle
}
Pogoste napake
Manjkajoce pages
// ❌ Nepopolno - na nobeni poti se ne upodobi nic
{
"name": "Tasks",
"entity": { ... },
"traits": [ { "name": "TaskLifecycle", ... } ]
}
// ✅ Popolno - lastnost je prikljucena na /tasks
{
"name": "Tasks",
"entity": { ... },
"traits": [ { "name": "TaskLifecycle", ... } ],
"pages": [
{ "name": "TaskListPage", "path": "/tasks", "traits": [{ "ref": "TaskLifecycle", "linkedEntity": "Task" }] }
]
}
Stanja kot nizi (neveljavno)
// ❌ Napacna oblika
"states": ["Pending", "Done"]
// ✅ Stanja morajo biti objekti
"states": [
{ "name": "Pending", "isInitial": true },
{ "name": "Done", "isTerminal": true }
]
Manjkajoci prehod INIT
// ❌ Stran se odpre, a je prazna - ni zacetnega render-ui
"transitions": [
{ "from": "Pending", "event": "COMPLETE", "to": "Done", "effects": [...] }
]
// ✅ Dodajte samozanko na INIT za upodobitev zacetnega UI
"transitions": [
{
"from": "Pending", "event": "INIT", "to": "Pending",
"effects": [["fetch", "Task"], ["render-ui", "main", { "type": "entity-table", "entity": "Task" }]]
},
{ "from": "Pending", "event": "COMPLETE", "to": "Done", "effects": [...] }
]
Naslednji koraki
- Zgradite upravljalnik nalog - dodajte celoten CRUD temu vzorcu
- Vzorci UI in render-ui - razisCite vse tipe vzorcev
- Pogoji in poslovna pravila - dodajte pogoje prehodom