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.

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.
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.
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.
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:
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ő.
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:
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.
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.
[
{ "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:
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.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.
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.
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.
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.

A fogaskerék egy párbeszédablakot nyit mindazzal, ami nem az előtted lévő katalógusról szól, három lapon:
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.
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.
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.
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.
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ó.
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
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:
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.
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.
make check-nél lefut egy ideiglenes gyökérben, és az átnevezést visszaolvassa a fájlból.teletypegames lett a katalógushosztból, és ugyanannak a rekordnak a kétszeri telepítése ugyanoda került.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.