EN /HU | Belépés

WarpEngine Client

A WarpEngine Client egy WarpEngine-áruház asztali alkalmazása: a katalógus kártyarácsként, egy kattintás telepít egy címet az alkalmazásmenüdbe, egy elindítja, egy eltávolítja. Linux, macOS és Windows. A jelenlegi kiadás a 3.1.0, amely már ismeri a WarpEngine 1.0-t.

A WarpEngine Client ablaka: balra az áruház és a szűrőtengelyek, jobbra a katalógus játékkártyák rácsaként

Az áruházmotor az alkalmazás része. A katalógus beolvasása, a géphez illő kiadás kiválasztása, a kicsomagolás, a menübejegyzés kiírása és annak nyilvántartása, hogy mi hova került, mind a folyamaton belül történik. Nincs értelmező, amit meg kellene keresni, és nincs gyerekfolyamat, amit értelmezni kellene: az alkalmazásnak egyetlen futásidejű függősége sincs, még zip-könyvtára sem. Ami a lemezre kerül, az viszont nem változott: a config.json és a state.json megtartja azt az alakot, amit a shell-áruház írt, így a CLI-vel telepített könyvtárat változtatás nélkül felismeri.

Az, hogy melyik áruházból telepít, nincs belefordítva: a kliens megkérdez egy nyilvántartást (GET /api/stores az oldalon), és egy ottani rekord egy név és egy katalógus, semmi több. A viselkedés a kliens saját dolga, a játékmappa pedig a katalógushoszt slugja, így két áruház egy gépen soha nem nyúl egymás fájljaihoz.

Mire van szüksége

Semmire. Nincs értelmező, nincs csomagkezelő, nincs rendszergazdai jog: az alkalmazás a saját futtatókörnyezetét viszi, az áruház pedig a saját felhasználói fiókod alá települ. A fejlesztéséhez Node 22 vagy újabb kell, az eszközláncot a make setup telepíti.

Telepítés

Vedd le a gépedhez való csomagot a kiadások közül, és nyisd meg. Az első indításkor, ha nincs áruház a gépen, az ablak felajánlja, amit a nyilvántartás publikál, vagy elfogad egy beírt katalóguscímet. Ennyi az egész beállítás.

Megnyitás macOS-en

A build ad hoc alá van írva, de nincs notarizálva, ezért a macOS rákérdez, mielőtt egy böngészőből érkezett példányt futtatna:

SH
xattr -dr com.apple.quarantine "/Applications/WarpEngine Client.app"

A Rendszerbeállítások ▸ Adatvédelem és biztonság alatti Megnyitás mindenképp is működik, egy blokkolt próbálkozás után. Ezt a lépést csak a notarizálás szünteti meg, ahhoz pedig fizetős Apple Developer ID kell. Az áruház által később letöltött fájlokat ez nem érinti: az alkalmazás a saját HTTP-kliensével tölti le őket, amely nem állítja be a karanténjelzőt.

A v1.0.0-t egyáltalán nem lehetett megnyitni — azt jelentette, hogy „is damaged". A csomag soha nem lett aláírva; csak a fő futtatható állományán volt rajta a linker ad hoc aláírása, tehát nem volt erőforrás-pecsét, és a Gatekeeper kérdés helyett elutasította. A scripts/after-pack.js most build közben aláírja a csomagot, az eredmény pedig valid on disk státusszal ellenőrizhető.

Belépés, és a pénzbe kerülő címek

Ebben a kliensben semmi nem tud semmit egyetlen konkrét áruházról sem. Az ár, hogy kell-e fiók, hol lehet megvenni, hol lehet belépni — mindez a katalógus szerverétől jön: a WarpEngine 0.5 a GET /api/service végponton megmondja, mit kínál, és minden bejegyzésre rátesz egy access blokkot. Ezért szolgál ki egyetlen build bármilyen boltot. A végpontok és alakok, amiket a kliens olvas, a WECP — WarpEngine Catalog Protocol, saját oldalán leírva.

Ahol a szerver nem kínál belépést (minden 0.5 előtti WarpEngine, és minden olyan áruház, amely nem árul semmit), ott az ablak sem mutat ilyet. Ahol igen:

  • az oldalmenü kap egy Fiók blokkot: Belépés…, majd Kilépés;
  • a belépés egy rövid kódot mutat. A böngésző megnyitja az áruház oldalát, a kódot oda kell beírni, és a jóváhagyás belépteti ezt az eszközt. Jelszó soha nem jut el a klienshez — pont ez a kerülőút értelme.
  • a token az operációs rendszer kulcstartójában él (Keychain, libsecret, DPAPI) az Electron safeStorage API-ján keresztül, áruházanként egy. Ha nincs kulcstartó, akkor egyáltalán nem tárolja el, nem pedig nyíltan kiírja; ennek az ára az, hogy a következő indításnál újra be kell lépni.

Egy kártyán az, hogy egy ember mit tehet, elválik attól, hogy a gép mit tud futtatni:

Állapot Mit kínál a kártya
birtokolt, vagy ingyenes Telepítés
nem birtokolt az ár, és a Megveszem, amely böngészőben nyitja meg az áruházi oldalt
kijelentkezve, a katalógus kapuzza Belépés a telepítéshez — a katalógus addig nem tudja megmondani, kié, amíg nem tudja, ki kérdez

A vásárlás a böngészőben történik: egy itt újraépített pénztár csak egy második hely lenne, ahol el lehet rontani a kártyakezelést. A Frissítés utána Telepítéssé alakítja a kártyát.

Ezzel jön két állapotszűrő is — Birtokolt és Megveendő —, mert a birtoklás nem ugyanaz, mint a telepítettség.

Egy meg nem vett cím nincs kiszürkítve. A kiszürkítés azt jelenti, hogy a gép nem tudja futtatni; a géppel semmi baj, ha egy cím egyszerűen pénzbe kerül.

Bearer token soha nem megy el olyan hosztra, amely nem adta ki. Egy kapuzott letöltés aláírt tárolóra irányít át — gyakran valaki más szerverére —, és egyes objektumtárolók visszautasítják azt a kérést, amely Authorization fejlécet és aláírást is visz.

Melyik áruházból telepít

Az első indításkor a kliens lekéri a nyilvántartást. Egy áruház esetén nincs mit eldönteni; több esetén a beállítóképernyő választót mutat.

JSON
[
  { "name": "Teletype Games", "catalogUrl": "https://teletypegames.org" },
  { "name": "Some Other Store", "catalogUrl": "https://games.example.org" }
]

Egy név és egy katalógus a teljes rekord. A kliens már tudja a hoszt–asset leképezést, a telepítési módokat, a platformokat és a viselkedést. Amit nem tudhat, az az identitás, és egy nyilvántartás csak az identitást mondja meg. Egy rekordból ezeket származtatja:

  • az áruházazonosító — a katalógushoszt slugja (teletypegames.org → teletypegames), vagy a megjelenített névé, ha az nem megy. Ez adja az áruház könyvtárának és a játékmappának a nevét. Két rekord, amely ugyanarra a katalógusra mutat, ugyanaz az áruház, és ugyanoda kerül, így az újratelepítés soha nem hagy árvát.
  • a játékmappa — ez a slug az operációs rendszer szokásos helyén a telepített programoknak. Ez egyben az egyetlen részfa, ahonnan ez az áruház valaha töröl.
  • mely címek jelennek meg — a kiadott, az archivált és a demó. Az a katalógus, amely demót publikál, azt szánja is játszásra.

Egy katalógusnak egyáltalán nem kell a nyilvántartásban lennie: a beállításokból bármilyen WarpEngine-katalóguscím hozzáadható. Egy csupasz hosztnév is elég (a https alapértelmezett), a nevet pedig belőle veszi.

A nyilvántartás címe az utolsó oldalspecifikus dolog a kliensben, három helyen dönthető el, a legspecifikusabbal kezdve: egy futásidejű STORES_API, az a cím, amellyel a csomag épült, majd a miénk.

SH
STORES_API=http://127.0.0.1:8731/stores npm start            # kipróbálás
make dist STORES_API=https://games.example.org/api/stores    # kiadás

A buildváltozat a becsomagolt alkalmazás package.json fájljába kerül (warpEngine.registryUrl), így egy más katalógusra épített kliens nem igényel forrásmódosítást, és a felhasználó gépén sem kell semmit beállítani. Egy áruház hozzáadása adatbázissor az oldalon, nem ennek az alkalmazásnak a kiadása.

Brandelt build

Egy build brandet vihet: egy nevet és egy boltot. A make dist BRAND_NAME="Teletype Games Store" BRAND_STORE=https://teletypegames.org BRAND_ID=teletype-store belesüti a csomagba; a BRAND_NAME=… BRAND_STORE=… npm start kipróbálja. A név az ablak címe, a sáv fejléce és a productName (Dock, /Applications, NSIS-mappa, .desktop bejegyzés); a bolt az első indításnál nyilvántartás és választó nélkül települ, a brand nevén, ugyanabba a store home-ba, amit egy általános kliens is használna ehhez a katalógushoz. A brand alapértelmezés, nem ketrec: a gépen lévő minden bolt látszik, és a beállítások továbbra is hozzáadnak és törölnek. A BRAND_ID adja az appId-t és a csomagnevek előtagját, hogy a brandelt és az általános kliens egymás mellett élhessen; a RELEASES_API a brandelt build saját kiadásaira irányítja a Frissítések keresését. A Beállítások Általános lapja azt mondja: WarpEngine Client 3.1.0 alapon. A brand adat, amit a build ad — a forrásban semmi nem nevez meg boltot.

Használat

Minden, ami nem cím, az oldalmenüben él; a menügomb becsukja, és az állapot túléli az újraindítást.

Szakasz Mit tartalmaz
Áruházak a gépen lévő összes áruház, a nyitottat megjelölve. Egy másikra kattintva vált a rács, a szűrők és a mappák, és a kliens legközelebb ott nyílik meg. Ugyanabból a katalógusból származó, de más mappában lévő két áruház az azonosítója helyett a mappáját mutatja. Áruházat hozzáadni, átnevezni és törölni a beállításokban lehet.
Fiók Belépés… / Kilépés, csak ott, ahol a katalógus kínál belépést.
Szűrők négy, egymással kombinálható tengely: a cím állapota ezen a gépen (Minden, Telepített, Frissítések, Nincs telepítve, és ahol a katalógus kapuz valamit, Birtokolt és Megveendő), a platform, a típus (natív vagy hosztolt) és a kategória, ha a katalógus publikál ilyet — a WarpEngine 0.12 a metadata-fájl category mezőjét átviszi a katalógusba, így a tengely megjelenik, amint a címek meg vannak címkézve, a 0.13 szótára (GET /api/software/vocabulary) pedig címkét ad a chipeknek. Minden darabszám azt mondja, hány címet mutatna az adott opció a többi tengely mai állása mellett, és a Törlés megjelenik, amíg bármi szűkíti a katalógust. A tengelyek abból épülnek, amit a katalógus tartalmaz: a címek nélküli platform nem jelenik meg, az eltűnő választás pedig visszaesik a Minden értékre.
Lábsor a fogaskerék (beállítások), a verziószám, a Napló és a Frissítés. A Napló az áruház saját kimenetét nyitja meg szó szerint, plusz azt a két mappát, ahova minden kerül. A Frissítés újraolvassa a katalógust. A címek egyesével, a kártyájukról telepíthetők; nincs „telepíts mindent" gomb.

A katalógus laponként érkezik, és a rács rajzol, ahogy jön. A WarpEngine 0.13 lapozza a GET /api/software-t; a kliens sorban olvassa a lapokat, és mindegyiket megmutatja, amint megjött, a sáv addig a címeket számolja. Ami az egészet igényli — a Frissítések csoport, a Mind frissítése, a prune — megvárja, és a cache mindig az összefűzött egészet tartja, részlegest soha. A rács ablakozott: 48 címet rajzol, és 48-at még, amikor az aljához érsz, így egy nagy katalógus annyiba kerül, amennyi a képernyőn van. Egy szűrő vagy keresés elölről kezd; egy lap megérkezése nem mozdítja el a görgetést.

A sávban van egy keresőmező: ami bele van írva, azokra a címekre szűkíti a rácsot, amelyek címe vagy neve tartalmazza, kis- és nagybetűtől és ékezettől függetlenül, így a love megtalálja a LÖVE-ot. A szűrő része — a chipek darabszámai számolnak vele, a Törlés kiüríti, és az Escape is. A sáv kapcsolója a rács és egy lista között vált; a lista a kártya borítójával, verziójával és menüjével rajzol.

Beállítások

A beállítások ablaka az Áruházak lapon: a telepített áruház az azonosítójával és a katalóguscímével, és a hozzáadás két módja

A fogaskerék egy párbeszédablakot nyit mindazzal, ami nem az előtted lévő katalógusról szól, három lapon:

  • Általános — a nyelv (a rendszert követi, átváltható: angol és magyar) és az alapértelmezett nézet, rács vagy lista, ugyanaz a beállítás, amit a sáv kapcsolója ír.
  • Áruházak — a gépen lévő összes áruház az azonosítójával és a katalóguscímével. A ceruza helyben átnevez: az Enter ment, az Escape elvet. Csak a név változhat, mert az azonosító, a mappa és a játékmappa mind a katalógusból származik, tehát egy másik katalógus másik áruház. A kuka eltávolít egy áruházat. A lista alatt az Áruház hozzáadása a listáról azt kínálja, amit a nyilvántartás publikál és ez a gép még nem tud, a Vagy egy saját katalógus pedig bármilyen katalóguscímet elfogad. A hozzáadás bezárja az ablakot, és megnyitja az új áruházat.
  • Frissítések — két blokk, szándékosan külön, mert két különböző dologról szólnak. Ez a kliens a verziót mutatja, és egy Frissítések keresése gombot, amely a kliens saját kiadáslistáját kérdezi le a forge-on, és helyben válaszol: Ez a legújabb verzió, vagy Az X verzió elérhető egy gombbal, amely böngészőben nyitja meg a kiadás oldalát. Az alkalmazás nem frissíti magát, és magától nem is kérdez; semmi nem történik, amíg nem kattintasz. Újabb verziójú címek: azok a telepített címek, amelyeknél a katalógus továbblépett, mindegyik egy Frissítés gombbal, és Mind frissítése, ha több van.

Egy áruház eltávolítása azt is eltávolítja, amit telepített. A kuka előbb rákérdez, és megmondja, hány cím megy vele. Az áruház state.json fájlja az egyetlen nyilvántartás arról, mely csomagok, ikonok és menübejegyzések tartoznak hozzá, ezért a játékok hátrahagyása olyan árvákat hagyna, amelyeket már semmi nem tudna azonosítani. A katalógus-cache, a beállítások és az esetleges belépési token is megy vele.

Kártyák

Egy kártya gombja Telepítés, Frissítés, vagy telepítés után Játék / Megnyitás. Egy telepített kártya hárompontos menüjében Frissítés (csak akkor élő, ha a katalógusban van újabb), Újratelepítés és Eltávolítás van. Az újratelepítés annak a példánynak való, amely telepítettnek látszik, de nem működik: a Frissítés és az Upgrade békén hagy egy épnek látszó telepítést, az Újratelepítés viszont előbb eltávolítja, majd újra kicsomagolja a katalógusból, ikonnal és menübejegyzéssel együtt. Minden kártya megmondja, hogy natív-e — kicsomagolva, helyben futtatva, offline is működik —, vagy hosztolt: a katalógus által kiszolgált böngészős build, amelynek a bejegyzése oldalt nyit meg, és hálózatot igényel.

A katalógus teljes tartalma megjelenik, azt is beleértve, amit ez a gép nem tud telepíteni. Ezek a kártyák ki vannak szürkítve, nem támogatott platform vagy ehhez a géphez nincs build jelvényt viselnek a motor magyarázatával, és nincs rajtuk mit megnyomni — mondjuk egy Raspberry Pi egy csak x86-os builddel szemben. Az az áruház, amely elrejti őket, találgatni hagyja a látogatót, hogy a katalógus kicsi-e, vagy a gépe fura. Saját állapotuk van, a Nem ehhez a géphez, és kimaradnak a natív/hosztolt darabszámokból, mert az a cím, amelyhez nincs build, nem tartozik egyik módhoz sem.

A 2.7.0-tól a Commodore 64-es és Plus/4-es címek is települnek: a WarpEngine 0.11-től a kiadásaik yapeSDL-csomagot visznek egy, a játékról elnevezett indítóval, amely beállítja a gépet és elindítja a kazettát, és a programkeresésben a játékról elnevezett program nyer. A kártyák minden platformot úgy neveznek, ahogy a katalógus — Plus/4, TIC-80, LÖVE —, a szerver build-mátrixából olvasva (GET /api/builds), így egy katalógus új kliens nélkül is felvehet platformot; a végpont nélküli motor a slugoknál marad.

Minden kártya azonos magasságú borítóképsávot visel — kép híján a cím első betűjét —, hogy a gombok soron belül egy vonalba essenek. Ez csendben el volt rontva addig, amíg le nem fényképeztük az ablakot: a sorok a tartalmuk követése helyett egyenlően osztották el az ablakmagasságot, ami összenyomta a képet és levágta a gombokat, miközben minden automatikus darabszám-ellenőrzés átment, mert a csomópontok mind ott voltak az oldalon.

Amíg az áruház dolgozik, csak azok a dolgok vannak letiltva, amelyek egy második hívást indítanának. A menü, a naplófiók és a szűrők tovább működnek, mert a képernyőt változtatják, a lemezen semmit.

Bármi, ami itt települ, normál menübejegyzés, tehát az indítódban, a Dockban vagy a Start menüben is megjelenik. A játékhoz nem kell futnia az alkalmazásnak.

Fejlesztés

A make a bejárati ajtó; az npm-szkripteket csomagolja be. A make önmagában mindent kilistáz.

Cél Mit csinál
make setup függőségek telepítése (előbb ellenőrzi a Node verzióját)
make build TypeScript fordítása, a preload és a renderer bundle-ölése
make typecheck típusellenőrzés, kimenet nélkül
make lint a szigorú szabálykészlet (a make lint-fix javítja, amit tud)
make check típusellenőrzés, lintelés és minden tesztkészlet — ez a kapu
make start futtatás a telepített áruház ellen
make icons minden ikonformátum kirenderelése a resources/icon.svg fájlból
make smoke az áruház meghajtása ablak és Electron nélkül
make storetest áruház hozzáadása, átnevezése és törlése homokozóban — az egyetlen kód, amely fát töröl
make uitest az ablak egyszeri betöltése, és jelentés arról, mi rajzolódott ki (SELFTEST_SHOT=shot.png le is fényképezi, a beállítások lapjaival együtt)
make test a három tesztkészlet
make dist csomagolás ehhez a géphez (dist-mac, dist-win, dist-linux)
make publish a dist/ alatti csomagok feltöltése a Gitea-kiadásra
make release csomagolás és publikálás egy menetben
make clean a build/ és a csomagok törlése (a distclean a node_modules mappát is elhagyja)
make version az érintett verziók, azt is beleértve, hogy megvan-e a tea

Az npm-szkriptek továbbra is működnek közvetlenül (npm start, npm run dist:mac). A Makefile a kiadási lépésen kívül nem tesz hozzá logikát, és minden alkalmazást futtató szkript előbb buildel, így nem lehet elavult bundle-t tesztelni.

Folyamatos integráció

A .woodpecker.yaml ebben a repóban van, nem az update szerver konfigurációs kiterjesztésében: az a kiterjesztés játékplatform-pipeline-okat szolgál ki, amelyek kazettát építenek és az oldal katalógusába publikálnak, míg ez alkalmazást épít, és egy kiadásba publikál.

Lépés Image Mit csinál
check warp-engine-client-ci:node22 node_modules (lásd lent), típusellenőrzés, lintelés, füstpróba és az áruház-életciklus teszt
linux electronuserland/builder:22 AppImage és deb
windows electronuserland/builder:22-wine NSIS-telepítő és hordozható exe, Wine-on keresztül
release ci-tools (digest szerint) csak tagre: létrehozza a kiadást, és hozzácsatolja, amit épített; a curl, a jq, a zip és a git benne van az image-ben, így semmit nem telepít

A check image az electronuserland/builder:22, a repó node_modules-ával előtelepítve a /ci alatt, mellette annak a package-lock.json-nak a sha256-jával, amelyből készült. A teletypegames repó ci/warp-engine-client.Dockerfile-ja építi, és az éjszakai cron újraépíti, ha a master lockjára még nincs lock-<sha> image; a tag mozog, ezért a lépés mindig pullolja. A scripts/ci-npm.sh átmásolja ezeket a modulokat, ha a lock egyezik (egy másodperc a 15 s-os npm ci helyett), és npm ci-t futtat, ha nem.

A macOS helyi build marad — az Apple eszközlánca csak Macen létezik —, így egy kiadásnak két fele van: egy vX.Y.Z tag pusholása felépíti a Linuxot és a Windowst, és létrehozza a kiadást a RELEASE_NOTES.md törzsével, a Macen futtatott make release pedig felteszi a macOS-csomagot ugyanarra a kiadásra. Bármelyik fél mehet előbb. Az ablakteszt is helyi: kijelző és a gépen lévő áruház kell hozzá.

A publikáláshoz gitea_token repótitok kell írási joggal. A Woodpecker ad a lépéseknek forge-hitelesítő adatot, és a szkript ezt használja, ha a titok hiányzik, de nem lehet rá támaszkodni: egy kézi buildnek megvan, a tag-webhook által indítottnak nincs. Két publikáló létezik — a scripts/release.sh a tea bejelentkezést vezérli egy munkaállomáson, a scripts/ci-upload.sh pedig az API-val beszél azzal a hitelesítő adattal, ami a CI-nak van.

Mindkét buildlépés azzal zárul, hogy ellenőrzi, mit gyártott: egy 10 MB alatti csomag nem készült el. Egy félbemaradt Wine-build a valódi telepítő nevével hagy ott egy csonkot, és az ls ezzel tökéletesen elégedett. A windowsos lépést Apple Silicon Macen nem lehet elpróbálni: a Wine 4 KB-os memórialapokat feltételez, a gépnek pedig 16 KB-osak vannak.

A windowsos telepítő nincs aláírva: a Windows ismeretlen kiadóra figyelmeztet, amíg nincs kódaláíró tanúsítvány. A Linux-csomagok konvenció szerint nem visznek aláírást.

Kiadás publikálása

SH
make release
make publish TAG=v1.0.2                 # a package.json-tól eltérő tag
scripts/release.sh dist/one-file.dmg    # csak egy csomag

A tag a package.json fájlból jön, tehát az npm version patch az egyetlen hely, ahol verziót állítunk. A kiadás létrejön, ha nincs, és az a melléklet, amelynek a neve már szerepel, lecserélődik, így egy újraépítés plusz egy második make publish felkerül, nem hibázik. A kiadási jegyzetek a RELEASE_NOTES.md fájlból jönnek, ha van. A repót az origin alapján olvassa, tehát egy fork a forkba publikál. A csomagnevekben nincs szóköz (WarpEngineClient-2.3.0-arm64.dmg), mert egy kiadási melléklet szóköze minden curl-ben szóköz, ami valaha hozzáér.

Telepített és bejelentkezett tea kell hozzá — a devarea repóban van make tea. Felülbírálható: TAG, REPO, TEA_LOGIN, NOTES, DIST.

A telepítéshez Node 22+ kell, a futtatáshoz nem: az Electron telepítője csak ESM, a régebbi Node pedig nem tudja require()-elni. A becsomagolt alkalmazás a saját futtatókörnyezetét viszi.

Az npm run uitest saját felhasználóiadat-könyvtárat használ, és kihagyja az egypéldány-zárat. Különben a felhasználónál már nyitva lévő példány elnyelné a tesztfolyamatot, amely 0-val lép ki, és sikeresnek látszik.

A tesztszkriptek elfogadnak egy homokozó-áruházat, így lehet ezt a repót anélkül tesztelni, hogy egy működő telepítéshez hozzányúlnánk. A STORE_ROOT lecseréli a keresési utat, nem elé fűz: most, hogy áruházat törölni is lehet, az a homokozó, amely elér egy működő telepítést, nem homokozó.

SH
STORE_ROOT=/tmp/sandbox-root npm start
SMOKE_HOME=/tmp/sandbox-root/ttg-desktop npm run smoke
SMOKE_HOME=<dir> SMOKE_TOKEN=<bearer> npm run smoke      # belépett felhasználóként

Hogyan áll össze

TypeScript rétegekben, a függőségek befelé mutatnak. A repóban lévő STRUCTURE.md a térkép — rétegek, minden használt minta, elnevezési szabályok —, és ez az a fájl, amit el kell olvasni, mielőtt bármit hozzáadnál.

Réteg Mi él ott
src/shared/ az IPC-csatornatábla, a hídszerződés, a DTO-k, az üzenetkészletek
src/domain/ modellek, portok és hibák — se Electron, se Node
src/application/ szolgáltatások és a domain–DTO leképezők
src/infrastructure/ adapterek: az áruházmotor, a HTTP, az archívumolvasó, a fájlrendszer, az Electron
src/main/ az ablak, az IPC-kontrollerek, a kompozíciós gyökér, az önteszt
src/preload/ a híd, egyetlen fájlba bundle-ölve — egy homokozott preload nem tud modult behúzni
src/renderer/ az állapottár, a nézetek és a renderer-kontrollerek
src/scripts/ a füstpróba és az áruház-életciklus teszt: ugyanazok a szolgáltatások ablak nélkül

Két tulajdonság, amit a rétegek megvesznek:

  • a katalógus ablak és Electron nélkül is meghajtható — a füstpróba ugyanazokat a szolgáltatásokat állítja össze ugyanazokra a portokra;
  • az ablak soha nem kap fájlrendszer-útvonalat. Egy cím anélkül kel át a hídon, az indítást pedig név alapján kérjük, és a fő folyamat oldja fel az áruház saját állapotából.

Az ablak kizárólag az állapotából rajzol: a napló, a kapu, a beállítások ablaka és a szűrő egy tár mezői, minden nézetnek egyetlen render(state) metódusa van, és a bekötés csak a három kompozíciós gyökérben történik (az alkalmazás, a füstpróba, az életciklus-teszt). Ami a hídon vagy a lemezről jön, ellenőrzött olvasón megy át, soha nem castolással.

A linter szándékosan szigorú: explicit típusok minden szignatúrán, nincs any, nincs non-null assertion, kimerítő switchek. Az a fordítás, amelyből hiányzik egy kulcs, nem fordul le, és az a csatorna sem, amelyet a preload nem valósít meg.

Az áruházmotor az src/infrastructure/engine/, a StoreCatalogGateway port mögött: a katalóguskliens a cache-ével, a felmérő, amely megmondja, mely címeket tudja ez a gép telepíteni és a többit miért nem, a kiadásválasztó, a hosztfelismerő, a csomagtelepítő, a .desktop / .app / .lnk indítóírók és az állapotfájl. A port fölött semmi nem tud arról, hogy ezek léteznek. Egy RetroArch-áruház menübejegyzés helyett lejátszási listát írna, tehát az egy második gateway és egy második bejegyzés lenne a STORE_ENGINES listában, nem egy második kódút.

Zip olvasása függőség nélkül. A Node-nak nincs zip-olvasója, ezért a ZipArchive egy a node:zlib fölött: végigjárja a központi könyvtárat, kibontja a stored és deflate bejegyzéseket, visszaállítja a futtatható bitet és a szimbolikus linkeket a bejegyzések attribútumaiból — a yapeSDL .app-jában lévő SDL2 framework ilyenek fája. Visszautasítja a zip64-et, az ismeretlen tömörítési módot és a célból kiszökő útvonalat.

Melyik WarpEngine szolgálta ki a katalógust. Minden WarpEngine API-válasz visz egy WarpEngine-Version fejlécet. A SUPPORTED_WARP_ENGINE_VERSIONS felsorolja, mely verziókra írták ezt a klienst, és mindegyik arra a CatalogDialect-re képződik le, amely az adott katalógusalakot olvassa. A switch kimerítő, tehát egy új verzió felvétele megállítja a buildet, amíg valaki meg nem mondja, hogyan kell olvasni.

Mit mond a fejléc Mi történik
támogatott verzió (ma 0.2-től 1.0-ig, két dialektussal) a dialektusa olvassa a katalógust, a napló megnevezi
semmi a legrégebbi támogatott verzióként olvassa — egy 0.4.0-nál régebbi motor
régebbi bárminél, ami támogatott ugyanaz, és a napló megmondja
újabb bárminél, ami támogatott a legújabb dialektust próbálja, figyelmeztetéssel, hogy címek maradhatnak ki

contextIsolation be, nodeIntegration ki, sandbox be, és olyan CSP, amely csak az alkalmazás saját szkriptjét és stíluslapját, valamint HTTPS-en érkező képeket enged. A linkek a valódi böngészőben nyílnak; az ablak soha nem navigál.

Amit ellenőriztünk, és amit nem

Minden verziót a make check mér — nincs típushiba, nincs lint-találat, három zöld tesztkészlet —, és az ablak a SELFTEST_SHOT-tal lefényképezi magát; így találtuk meg az összenyomott rácssorokat (1.x) és a 2.6.0 üres ablakát: egy inline <svg> nem HTMLElement, ezért az elemellenőrzés az első konstruktorban dobott, és utána semmi nem futott. A fej nélküli füstpróba ezt nem láthatta; az ablakellenőrzés az első másodpercben elbukik rajta.

  • Az áruház életciklusa — hozzáadás, átnevezés, törlés — minden make check-nél lefut egy ideiglenes gyökérben, és az átnevezést visszaolvassa a fájlból.
  • Az önteszt megszámolja a kártyákat, a szűrősorokat és a kártyamenüket, megnyitja a beállításokat, összeveti az áruházsorait az oldalmenüével, és bezárja.
  • A nyilvántartási utat helyi végponton próbáltuk ki, amely az oldal payloadját szolgálta ki; a slug teletypegames lett a katalógushosztból, és ugyanannak a rekordnak a kétszeri telepítése ugyanoda került.
  • Az aláírást mértük, nem feltételeztük: karanténjelző beállítva a kiadási artifactból kicsomagolt példányon, a codesign --verify --deep --strict tiszta, a syspolicy_check pedig csak a várt „adhoc signed" figyelmeztetést jelentette.

Linuxon és Windowson nem próbáltuk ki. Az útvonalak és az indítási viselkedés meg vannak írva rájuk, és a CI megépíti a csomagokat, de a .desktop és .lnk indítók generálódtak és olvashatók, nem kattintottak rájuk. A notarizálás, a windowsos aláíró tanúsítvány és az alkalmazáson belüli frissítés mind nyitott — a kiadások mondják el, melyik verzió mit változtatott.