SIAX Technology (sax3l)

@siax/create-siax-app (0.1.2)

Published 2026-08-10 12:07:48 +00:00 by admin

Installation

@siax:registry=https://git.cloud.siax.io/api/packages/sax3l/npm/
npm install @siax/create-siax-app@0.1.2
"@siax/create-siax-app": "0.1.2"

About this package

create-siax-app

App-generatorn för SIAX K6 (M0B). Producerar ett komplett apprepo som klarar 🥉 Brons direkt vid skapandetsiax-doctor --fail-on=block ger exit 0 på det genererade repot, utan att någon rör en fil efteråt.

Zero dependencies. Körs med enbart Node 20.11+.

node index.mjs --ci --name "Gute Taxi" --bundle-id io.siax.gutetaxi \
  --capabilities location,notifications,offline --out ../

Utan --ci frågar generatorn interaktivt (bara när stdin är en terminal — den hänger aldrig i ett workflow).

Varför den finns

Alternativet är att kopiera ett befintligt apprepo. Det har provats i estatet och ger samma utfall varje gång: fem repon med fem versioner av samma CI, och en säkerhetsfix som landar i ett av dem. Generatorn är det som gör app nummer tio billig — och det som gör att en normändring kan rullas ut till alla appar samtidigt (--upgrade).

Vad som FAKTISKT är byggt

Kontroll Läge Bevis
MOB-07 — genererat repo klarar Brons direkt test/doctor.test.mjs kör den riktiga doctorn mot ett genererat repo, --fail-on=block, och kräver measuredScore: 100
MOB-08 — allt ett K6-apprepo måste ha test/generate.test.mjs verifierar 52 obligatoriska sökvägar + normkontrollerna
MOB-09 — idempotent och uppgraderingsbar test/upgrade.test.mjs: omkörning = noll ändringar, appkod skrivs aldrig över, ändrad generatorfil ger konflikt (och läker inte av sig själv)
MOB-10 — endast valda kapabiliteter genereras test/capabilities.test.mjs + test/generate.test.mjs: två kapabilitetssvar ger olika repon, behörighetstexter valideras (DIST-06)

node --test "test/**/*.test.mjs"65 tester, 65 gröna (2026-08-09).

⚠️ Använd glob-formen. node --test tooling/create-siax-app ger på Node 22+ falskt grönt: katalogen tolkas som ett testfall, rapporteras som ett passerande test, och inget körs. Samma fälla gäller node --test test.

Vad generatorn lägger i repot

siax.repo.json          kind=app, platformRepo=M0B, sdkPackages[], bundleIds
siax.config.json        deploy-deskriptor för appens API, fyra miljöer
app.json                Expo-identitet (appens fil)
app.config.js           slår ihop app.json + config/capabilities.json + miljö
config/capabilities.json   HÄRLEDD ur kapabilitetsvalen — behörigheter, plugins
config/environments/*.json dev, test, staging, prod (endast env-NAMN)
config/ota.json         OTA-kanaler, stegvis utrullning i prod
.gitea/workflows/       ci, security, nightly, release (ALDRIG .github/)
Dockerfile              multi-stage, node:22-alpine, non-root, healthcheck
services/api/           appens eget API: health, ready, /v1/me med riktig
                        ID0-JWT-verifiering (RS256/ES256 mot JWKS, node:crypto)
services/api/migrations/0001_init.sql   tenant_id + radnivåsäkerhet
contracts/openapi.yaml  kontraktet, inklusive kapabiliteternas rutter
src/                    env, api-klient, ID0-konfig, App.tsx, kapabilitetsmoduler
store/{ios,android}/    butiksmetadata som versionerad artefakt (DIST-01)
docs/                   ARCHITECTURE, ADR, runbooks, klientstod.md, synk.md
test/                   konformitetstester som kör utan npm install
scripts/                BLD-14-kontroll och OTA-publicering
.siax-generator.json    ägarskapsmanifest (se nedan)

Ägarskapsmodellen (MOB-09)

Varje genererad fil har ett deklarerat ägarskap i .siax-generator.json, tillsammans med en sha256 av det generatorn senast skrev:

Ägarskap Betydelse Exempel
managed Generatorn äger filen. Skrivs över vid uppgradering endast om hashen på disk matchar den vi skrev sist. .gitea/workflows/*, Dockerfile, config/capabilities.json, docs/runbook/*
seed Skrivs en gång, rörs sedan aldrig. src/App.tsx, README.md, migrationer, butikstexter, docs/synk.md
merge Generatorn äger ett namnrum av nycklar, resten bevaras ordagrant. package.json

Har någon ändrat en managed-fil rapporteras det som en konflikt och filen lämnas orörd. Konflikten läker inte av sig själv: manifestet behåller den gamla hashen, så nästa körning rapporterar den igen tills den lösts. Rätt åtgärd är oftast att flytta ändringen till generatorn här i M0B; --force finns för när man verkligen menar det.

merge-regeln för package.json: generatorn äger beroenden i namnrummet @siax/*, expo, expo-*, react, react-dom, react-native, typescript, @types/react samt en fast lista scriptnamn. Allt annat bevaras. En borttagen kapabilitet får därför sitt beroende bortstädat, medan appens egna beroenden och scripts överlever.

node index.mjs --upgrade --dir <apprepo> --dry-run     # visa
node index.mjs --upgrade --dir <apprepo>               # utför
node index.mjs --upgrade --dir <apprepo> --strict      # exit 2 vid konflikt

Torrkörningen använder samma kodväg som en riktig körning (plan → apply med dryRun), inte en separat låtsasimplementation som kan divergera.

Kapabiliteter (MOB-10)

camera, location, notifications, purchases, ai, storage, offline.

Varje kapabilitet drar med sig — och bara den — sitt @siax/mobile-*-paket, sin expo-modul (pinnad till rätt SDK-linje), sina behörigheter med texter, sina env-NAMN och sina API-rutter. Registret namnger också vilken K1-kärnbusstjänst som äger funktionen, så att MOB-02 är synlig i datan och inte bara i en kommentar.

Behörighetstexterna valideras innan något skrivs (DIST-06): minst 30 tecken, ingen platshållare, och de nämner appen vid namn. Egen text sätts med --permission-text camera="…" eller med Info.plist-nyckeln direkt.

Kombinationsregler finns där de behövs — camera + storage ger NSPhotoLibraryUsageDescription, utan vilken iOS kraschar när bildväljaren öppnas.

Expo-SDK-matrisen

src/expo-sdk.mjs pinnar en hel SDK-linje åt gången (SDK 51 och 52 i dag). Generatorn gissar aldrig fram versionsnummer: begär man en linje som inte finns i matrisen vägrar den, med instruktionen att lägga till raden efter att ha läst Expos release notes. Ett repo som blandar RN- och expo-modulversioner bygger inte, och felet syns först i en runner-körning som tar tjugo minuter.

Det som medvetet INTE är gjort

  • package-lock.json är ett frö. Den har npm:s riktiga struktur (lockfileVersion: 3) och rotpaketets beroendeintervall, men inget upplöst träd — det kräver nätverk och kan inte genereras offline. npm install materialiserar den. Det står i det genererade README:t, i CI-workflowet (som varnar) och i manifestet (lockfileMaterialized: false). SUP-01 är alltså uppfylld strukturellt, inte i sak, tills någon kört npm install.
  • @siax/mobile-* är pinnade till 0.0.0 (--sdk-version för att ändra) — den version paketen har i M0B i dag. De är ännu inte publicerade till Giteas npm-registry, så npm install i ett genererat repo kan inte lösa dem förrän M2 publicerat. Endast @siax/ui och @siax/tokens (0.1.0) är publicerade.
  • Ingen ikon, ingen startskärm. En genererad platshållarikon är precis den sortens sak som glider hela vägen till en butiksinlämning. assets/README.md beskriver vad som krävs.
  • Klientens skärmar. src/App.tsx visar miljö och valda kapabiliteter. Den är seed — appen tar över direkt.
  • Kapabilitetsmodulerna anropar appens EGET API, inte SDK:t. De är skrivna mot rutter generatorn själv genererar (/v1/ai/complete m.fl.) i stället för mot @siax/mobile-*-signaturer som inte kunnat verifieras här. Det är medvetet: hellre kod som bevisligen stämmer än kod som ser rikare ut och inte kompilerar.
  • Typkontroll av det genererade repot kräver npm install (React Native levererar sina egna typer). Generatorn syntaxkontrollerar sina utdata, men tsc körs först i det genererade repots CI.
  • Ingen interaktiv frågeslinga för allt. Prompten täcker namn, bundle-id och kapabiliteter; övrigt sätts med flaggor. --ci stänger av prompten helt.

Bevis (2026-08-09)

$ node index.mjs --ci --name "Gute Taxi" --bundle-id io.siax.gutetaxi \
    --capabilities location,notifications,offline,ai --dir <tmp>/gute-taxi
nya 79 · uppdaterade 0 · ... · konflikter 0

$ node C:/siax-std/packages/doctor/src/doctor.mjs --repo <tmp>/gute-taxi --fail-on=block
Mätt poäng: 100/100 över 38 mätbara kontroller.
EXIT=0

$ cd <tmp>/gute-taxi && node --test "test/**/*.test.mjs"
tests 14 · pass 14 · fail 0        # utan npm install

$ node --test "test/**/*.test.mjs"          # generatorns egna tester
tests 65 · pass 65 · fail 0

Även varianten --operational-state running --node server11 ger 100/100 (då mäts även REPO-06, CD-01 och CD-03).

Struktur

index.mjs              bin-ingång (tunn — CLI:t är importerbart och testbart)
src/cli.mjs            argv → exitkod, injicerbar utskrift
src/args.mjs           argv-parser (repeterbara nyckel=värde-flaggor)
src/spec.mjs           AppSpec: normalisering + validering, alla fel på en gång
src/capabilities.mjs   kapabilitetsregistret + DIST-06-validering
src/expo-sdk.mjs       den verifierade SDK-matrisen
src/manifest.mjs       ägarskap, hashning, plan, tillämpning
src/generate.mjs       filkarta → plan → skrivning
src/prompt.mjs         interaktivt läge (aldrig i CI)
src/templates/*.mjs    mallarna, en modul per område
test/*.test.mjs        65 tester, node:test, zero dependencies

Mallarna är JS-funktioner, inte statiska filer med platshållare. Skälet är kapabilitetslogiken: en mallfil hade behövt villkorsspråk för att generera olika behörigheter, plugins, rutter och beroenden per val — och då är det enklare och mer läsbart att det är riktig kod från början.

Details
npm
2026-08-10 12:07:48 +00:00
1
UNLICENSED
latest
64 KiB
Assets (1)
Versions (3) View all
0.1.2 2026-08-10
0.1.1 2026-08-10
0.1.0 2026-08-10