feat: Typen aus der Schema-Migration erzeugen statt aus einer Instanz
npm run generate-pocketbase-types liest das Collections-Array jetzt direkt aus backend/pb_migrations/ (scripts/schema-to-json.mjs) und speist es über pocketbase-typegen --json ein. Keine laufende Instanz, kein Token, kein Netzwerkzugriff mehr nötig. Damit stammen Schema und Typen aus derselben versionierten Quelle und können nicht auseinanderlaufen. Vorher zeigten sie auf eine Remote-Instanz, deren Stand niemand garantieren konnte — nach dem Neu-Deployment lieferte sie prompt Typen ohne die fachlichen Collections. frontend/.env enthält dadurch nur noch PUBLIC_PB_URL. PB_TYPEGEN_URL und PB_TYPEGEN_TOKEN entfallen (letztere wurde ohnehin nirgends gelesen), PB_SUPERUSER_TOKEN wird nicht mehr gebraucht. Die Datei enthält damit kein Geheimnis mehr. Verifiziert: ohne .env, ohne Token und ohne laufende Instanz entstehen alle sechs Collections, svelte-check meldet 0 Fehler und 0 Warnungen. Die System-Collections (_superusers, _mfas, ...) fehlen in den Typen, weil sie bewusst nicht in der Migration stehen. Die Anwendung verwendet sie nicht. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
132ce04e0c
commit
2540666e1a
8 changed files with 127 additions and 137 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -22,6 +22,9 @@ Thumbs.db
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
|
|
||||||
|
# Zwischendatei der Typgenerierung
|
||||||
|
.schema.tmp.json
|
||||||
|
|
||||||
# PocketBase-Laufzeitdaten
|
# PocketBase-Laufzeitdaten
|
||||||
backend/pb_data/
|
backend/pb_data/
|
||||||
*.db
|
*.db
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,8 @@ npm run check
|
||||||
# Type-check with watch mode
|
# Type-check with watch mode
|
||||||
npm run check:watch
|
npm run check:watch
|
||||||
|
|
||||||
# Generate TypeScript types from PocketBase schema
|
# Generate TypeScript types from the schema migration in backend/pb_migrations
|
||||||
|
# (no running instance, no token, no network access needed)
|
||||||
npm run generate-pocketbase-types
|
npm run generate-pocketbase-types
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -99,7 +100,7 @@ The app uses Svelte 5 runes for state management with a custom store pattern:
|
||||||
- `$derived()` for computed values
|
- `$derived()` for computed values
|
||||||
- `{@render children?.()}` for slot content
|
- `{@render children?.()}` for slot content
|
||||||
|
|
||||||
**Type Generation**: After modifying PocketBase schema, run `npm run generate-pocketbase-types` to update TypeScript types.
|
**Type Generation**: After modifying the schema migration in `backend/pb_migrations/`, run `npm run generate-pocketbase-types` to update `frontend/src/lib/types.d.ts`. The script reads the collections array straight out of the migration (`frontend/scripts/schema-to-json.mjs`) — schema and types come from the same versioned source and cannot drift apart. Commit the regenerated file.
|
||||||
|
|
||||||
**Async Data Loading**: Root layout (`src/routes/+layout.svelte`) shows pattern:
|
**Async Data Loading**: Root layout (`src/routes/+layout.svelte`) shows pattern:
|
||||||
```svelte
|
```svelte
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,11 @@
|
||||||
# Vorlage für die lokale .env — kopieren und ausfüllen:
|
# Vorlage für die lokale .env — kopieren und ausfüllen:
|
||||||
# cp .env.example .env
|
# cp .env.example .env
|
||||||
#
|
|
||||||
# Die echte .env steht in .gitignore und darf nicht committet werden,
|
|
||||||
# sie enthält den Superuser-Token.
|
|
||||||
|
|
||||||
# Basis-URL der PocketBase-Instanz, die das Frontend anspricht.
|
# Basis-URL der PocketBase-Instanz, die das Frontend anspricht.
|
||||||
# Produktiv: https://api.stammtisch-hersbruck.de
|
# Produktiv: https://api.stammtisch-hersbruck.de
|
||||||
# Lokales Backend aus ../backend: http://127.0.0.1:8090
|
# Lokales Backend aus ../backend: http://127.0.0.1:8090
|
||||||
|
#
|
||||||
|
# Die Variable wird zur Buildzeit eingesetzt ($env/static/public). Ein Wechsel
|
||||||
|
# der Instanz erfordert deshalb einen Neustart des Dev-Servers bzw. einen
|
||||||
|
# neuen Build.
|
||||||
PUBLIC_PB_URL=https://api.stammtisch-hersbruck.de
|
PUBLIC_PB_URL=https://api.stammtisch-hersbruck.de
|
||||||
|
|
||||||
# Ziel für die Typgenerierung (npm run generate-pocketbase-types) und die
|
|
||||||
# Scripts unter scripts/. Zeigt üblicherweise auf dieselbe Instanz wie oben.
|
|
||||||
PB_TYPEGEN_URL=https://api.stammtisch-hersbruck.de/
|
|
||||||
|
|
||||||
# Superuser-Token für Schema-Zugriffe. Im PocketBase-Admin-UI erzeugen.
|
|
||||||
# Niemals committen.
|
|
||||||
PB_SUPERUSER_TOKEN=
|
|
||||||
PB_TYPEGEN_TOKEN=
|
|
||||||
|
|
|
||||||
|
|
@ -35,15 +35,27 @@ Die App läuft dann auf http://stammtisch-hersbruck.de.localhost:31337
|
||||||
|
|
||||||
Die Variable wird von SvelteKit zur **Buildzeit** eingesetzt
|
Die Variable wird von SvelteKit zur **Buildzeit** eingesetzt
|
||||||
(`$env/static/public`). Ein Wechsel der Instanz erfordert deshalb einen
|
(`$env/static/public`). Ein Wechsel der Instanz erfordert deshalb einen
|
||||||
Neustart des Dev-Servers bzw. einen neuen Build — ein blosser Neustart des
|
Neustart des Dev-Servers bzw. einen neuen Build — ein bloßer Neustart des
|
||||||
Containers genügt nicht.
|
Containers genügt nicht.
|
||||||
|
|
||||||
`PB_TYPEGEN_URL` und `PB_SUPERUSER_TOKEN` gelten getrennt davon für
|
Es ist die einzige Variable in `.env`; ein Token wird nicht mehr gebraucht.
|
||||||
`npm run generate-pocketbase-types`.
|
|
||||||
|
|
||||||
## Schema
|
## Typen
|
||||||
|
|
||||||
Das maßgebliche Schema liegt als Migration in `../backend/pb_migrations/`.
|
Das maßgebliche Schema liegt als Migration in `../backend/pb_migrations/`.
|
||||||
Nach einer Schema-Änderung `npm run generate-pocketbase-types` ausführen — das
|
Daraus entstehen auch die TypeScript-Typen:
|
||||||
aktualisiert `src/lib/types.d.ts`, aus dem der PocketBase-Client seine Typen
|
|
||||||
bezieht.
|
npm run generate-pocketbase-types
|
||||||
|
|
||||||
|
Das Script liest das Collections-Array aus der Migration
|
||||||
|
(`scripts/schema-to-json.mjs`) und erzeugt daraus `src/lib/types.d.ts`. Es
|
||||||
|
braucht **keine laufende Instanz, keinen Token und keinen Netzwerkzugriff** —
|
||||||
|
Schema und Typen kommen aus derselben versionierten Quelle und können deshalb
|
||||||
|
nicht auseinanderlaufen.
|
||||||
|
|
||||||
|
Nach jeder Schema-Änderung in `../backend/pb_migrations/` einmal ausführen und
|
||||||
|
die aktualisierte `types.d.ts` mitcommitten.
|
||||||
|
|
||||||
|
> Die System-Collections (`_superusers`, `_mfas`, …) stehen bewusst nicht in
|
||||||
|
> der Migration und fehlen deshalb in den Typen. Die Anwendung verwendet sie
|
||||||
|
> nicht.
|
||||||
|
|
|
||||||
86
frontend/package-lock.json
generated
86
frontend/package-lock.json
generated
|
|
@ -1586,9 +1586,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.12",
|
"version": "1.1.18",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
|
||||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
|
@ -1697,6 +1697,7 @@
|
||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||||
|
"deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
|
@ -2107,9 +2108,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/es-object-atoms": {
|
"node_modules/es-object-atoms": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
|
||||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
"integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -2228,17 +2229,17 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/form-data": {
|
"node_modules/form-data": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
|
||||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
"integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
"es-set-tostringtag": "^2.1.0",
|
"es-set-tostringtag": "^2.1.0",
|
||||||
"hasown": "^2.0.2",
|
"hasown": "^2.0.4",
|
||||||
"mime-types": "^2.1.12"
|
"mime-types": "^2.1.35"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
|
|
@ -2389,7 +2390,7 @@
|
||||||
"version": "7.2.3",
|
"version": "7.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||||
"deprecated": "Glob versions prior to v9 are no longer supported",
|
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
|
@ -2466,9 +2467,9 @@
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
|
||||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -2627,9 +2628,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/ip-address": {
|
"node_modules/ip-address": {
|
||||||
"version": "10.0.1",
|
"version": "10.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz",
|
||||||
"integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==",
|
"integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
|
@ -3096,9 +3097,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
|
@ -3222,11 +3223,11 @@
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/minipass-flush": {
|
"node_modules/minipass-flush": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz",
|
||||||
"integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
|
"integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "BlueOak-1.0.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minipass": "^3.0.0"
|
"minipass": "^3.0.0"
|
||||||
|
|
@ -3490,9 +3491,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/node-abi": {
|
"node_modules/node-abi": {
|
||||||
"version": "3.78.0",
|
"version": "3.94.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.78.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz",
|
||||||
"integrity": "sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ==",
|
"integrity": "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -3611,6 +3612,7 @@
|
||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||||
|
"deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
|
@ -3798,6 +3800,7 @@
|
||||||
"version": "7.1.3",
|
"version": "7.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
|
||||||
"integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
|
"integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
|
||||||
|
"deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -3845,9 +3848,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pump": {
|
"node_modules/pump": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
|
||||||
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
|
"integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -4039,9 +4042,9 @@
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.7.3",
|
"version": "7.8.5",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
|
||||||
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -4149,14 +4152,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/socks": {
|
"node_modules/socks": {
|
||||||
"version": "2.8.7",
|
"version": "2.8.9",
|
||||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
|
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz",
|
||||||
"integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
|
"integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ip-address": "^10.0.1",
|
"ip-address": "^10.1.1",
|
||||||
"smart-buffer": "^4.2.0"
|
"smart-buffer": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -4273,6 +4276,7 @@
|
||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||||
|
"deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -4536,9 +4540,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tar-fs": {
|
"node_modules/tar-fs": {
|
||||||
"version": "2.1.4",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz",
|
||||||
"integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
|
"integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
"prepare": "svelte-kit sync || echo ''",
|
"prepare": "svelte-kit sync || echo ''",
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
"generate-pocketbase-types": "set -a && . ./.env && set +a && pocketbase-typegen --url \"$PB_TYPEGEN_URL\" --token \"$PB_SUPERUSER_TOKEN\" --out ./src/lib/types.d.ts"
|
"generate-pocketbase-types": "node scripts/schema-to-json.mjs > .schema.tmp.json && pocketbase-typegen --json .schema.tmp.json --out ./src/lib/types.d.ts && rm -f .schema.tmp.json"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@internationalized/date": "^3.12.1",
|
"@internationalized/date": "^3.12.1",
|
||||||
|
|
|
||||||
52
frontend/scripts/schema-to-json.mjs
Normal file
52
frontend/scripts/schema-to-json.mjs
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* Extrahiert das Collections-Array aus der PocketBase-Migration und schreibt es
|
||||||
|
* als JSON auf stdout — in der Form, die `pocketbase-typegen --json` erwartet.
|
||||||
|
*
|
||||||
|
* Damit entstehen die TypeScript-Typen aus dem versionierten Schema im Repo,
|
||||||
|
* ohne laufende Instanz, ohne Token und ohne Netzwerkzugriff.
|
||||||
|
*
|
||||||
|
* Aufruf über npm run generate-pocketbase-types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { readFileSync, readdirSync } from 'node:fs'
|
||||||
|
import { join } from 'node:path'
|
||||||
|
|
||||||
|
const MIGRATIONS_DIR = new URL('../../backend/pb_migrations/', import.meta.url).pathname
|
||||||
|
|
||||||
|
// Die Snapshot-Migration ist die einzige, die ein vollständiges
|
||||||
|
// `const collections = [...]` enthält. Bei mehreren Dateien gewinnt die
|
||||||
|
// jüngste — Migrationen sind nach Zeitstempel benannt.
|
||||||
|
const candidates = readdirSync(MIGRATIONS_DIR)
|
||||||
|
.filter((f) => f.endsWith('.js'))
|
||||||
|
.sort()
|
||||||
|
.reverse()
|
||||||
|
|
||||||
|
const MARKER = 'const collections = '
|
||||||
|
|
||||||
|
for (const file of candidates) {
|
||||||
|
const source = readFileSync(join(MIGRATIONS_DIR, file), 'utf8')
|
||||||
|
const start = source.indexOf(MARKER)
|
||||||
|
if (start === -1) continue
|
||||||
|
|
||||||
|
// Vom öffnenden [ bis zur zugehörigen schließenden Klammer zählen —
|
||||||
|
// ein Regex käme an den verschachtelten Arrays der Feldoptionen nicht vorbei.
|
||||||
|
const from = start + MARKER.length
|
||||||
|
let depth = 0
|
||||||
|
|
||||||
|
for (let i = from; i < source.length; i++) {
|
||||||
|
if (source[i] === '[') depth++
|
||||||
|
else if (source[i] === ']') {
|
||||||
|
depth--
|
||||||
|
if (depth === 0) {
|
||||||
|
process.stdout.write(source.slice(from, i + 1))
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(
|
||||||
|
`Keine Migration mit "${MARKER.trim()}" in ${MIGRATIONS_DIR} gefunden.\n` +
|
||||||
|
`Ohne sie lassen sich die Typen nicht aus dem Repo erzeugen.`
|
||||||
|
)
|
||||||
|
process.exit(1)
|
||||||
74
frontend/src/lib/types.d.ts
vendored
74
frontend/src/lib/types.d.ts
vendored
|
|
@ -6,11 +6,6 @@ import type PocketBase from 'pocketbase'
|
||||||
import type { RecordService } from 'pocketbase'
|
import type { RecordService } from 'pocketbase'
|
||||||
|
|
||||||
export enum Collections {
|
export enum Collections {
|
||||||
Authorigins = "_authOrigins",
|
|
||||||
Externalauths = "_externalAuths",
|
|
||||||
Mfas = "_mfas",
|
|
||||||
Otps = "_otps",
|
|
||||||
Superusers = "_superusers",
|
|
||||||
Events = "events",
|
Events = "events",
|
||||||
Riders = "riders",
|
Riders = "riders",
|
||||||
Runs = "runs",
|
Runs = "runs",
|
||||||
|
|
@ -46,55 +41,6 @@ export type AuthSystemFields<T = unknown> = {
|
||||||
|
|
||||||
// Record types for each collection
|
// Record types for each collection
|
||||||
|
|
||||||
export type AuthoriginsRecord = {
|
|
||||||
collectionRef: string
|
|
||||||
created?: IsoDateString
|
|
||||||
fingerprint: string
|
|
||||||
id: string
|
|
||||||
recordRef: string
|
|
||||||
updated?: IsoDateString
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ExternalauthsRecord = {
|
|
||||||
collectionRef: string
|
|
||||||
created?: IsoDateString
|
|
||||||
id: string
|
|
||||||
provider: string
|
|
||||||
providerId: string
|
|
||||||
recordRef: string
|
|
||||||
updated?: IsoDateString
|
|
||||||
}
|
|
||||||
|
|
||||||
export type MfasRecord = {
|
|
||||||
collectionRef: string
|
|
||||||
created?: IsoDateString
|
|
||||||
id: string
|
|
||||||
method: string
|
|
||||||
recordRef: string
|
|
||||||
updated?: IsoDateString
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OtpsRecord = {
|
|
||||||
collectionRef: string
|
|
||||||
created?: IsoDateString
|
|
||||||
id: string
|
|
||||||
password: string
|
|
||||||
recordRef: string
|
|
||||||
sentTo?: string
|
|
||||||
updated?: IsoDateString
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SuperusersRecord = {
|
|
||||||
created?: IsoDateString
|
|
||||||
email: string
|
|
||||||
emailVisibility?: boolean
|
|
||||||
id: string
|
|
||||||
password: string
|
|
||||||
tokenKey: string
|
|
||||||
updated?: IsoDateString
|
|
||||||
verified?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum EventsStatusOptions {
|
export enum EventsStatusOptions {
|
||||||
"draft" = "draft",
|
"draft" = "draft",
|
||||||
"active" = "active",
|
"active" = "active",
|
||||||
|
|
@ -182,11 +128,6 @@ export type UsersRecord = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response types include system fields and match responses from the PocketBase API
|
// Response types include system fields and match responses from the PocketBase API
|
||||||
export type AuthoriginsResponse<Texpand = unknown> = Required<AuthoriginsRecord> & BaseSystemFields<Texpand>
|
|
||||||
export type ExternalauthsResponse<Texpand = unknown> = Required<ExternalauthsRecord> & BaseSystemFields<Texpand>
|
|
||||||
export type MfasResponse<Texpand = unknown> = Required<MfasRecord> & BaseSystemFields<Texpand>
|
|
||||||
export type OtpsResponse<Texpand = unknown> = Required<OtpsRecord> & BaseSystemFields<Texpand>
|
|
||||||
export type SuperusersResponse<Texpand = unknown> = Required<SuperusersRecord> & AuthSystemFields<Texpand>
|
|
||||||
export type EventsResponse<Texpand = unknown> = Required<EventsRecord> & BaseSystemFields<Texpand>
|
export type EventsResponse<Texpand = unknown> = Required<EventsRecord> & BaseSystemFields<Texpand>
|
||||||
export type RidersResponse<Texpand = unknown> = Required<RidersRecord> & BaseSystemFields<Texpand>
|
export type RidersResponse<Texpand = unknown> = Required<RidersRecord> & BaseSystemFields<Texpand>
|
||||||
export type RunsResponse<Texpand = unknown> = Required<RunsRecord> & BaseSystemFields<Texpand>
|
export type RunsResponse<Texpand = unknown> = Required<RunsRecord> & BaseSystemFields<Texpand>
|
||||||
|
|
@ -197,11 +138,6 @@ export type UsersResponse<Texpand = unknown> = Required<UsersRecord> & AuthSyste
|
||||||
// Types containing all Records and Responses, useful for creating typing helper functions
|
// Types containing all Records and Responses, useful for creating typing helper functions
|
||||||
|
|
||||||
export type CollectionRecords = {
|
export type CollectionRecords = {
|
||||||
_authOrigins: AuthoriginsRecord
|
|
||||||
_externalAuths: ExternalauthsRecord
|
|
||||||
_mfas: MfasRecord
|
|
||||||
_otps: OtpsRecord
|
|
||||||
_superusers: SuperusersRecord
|
|
||||||
events: EventsRecord
|
events: EventsRecord
|
||||||
riders: RidersRecord
|
riders: RidersRecord
|
||||||
runs: RunsRecord
|
runs: RunsRecord
|
||||||
|
|
@ -211,11 +147,6 @@ export type CollectionRecords = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CollectionResponses = {
|
export type CollectionResponses = {
|
||||||
_authOrigins: AuthoriginsResponse
|
|
||||||
_externalAuths: ExternalauthsResponse
|
|
||||||
_mfas: MfasResponse
|
|
||||||
_otps: OtpsResponse
|
|
||||||
_superusers: SuperusersResponse
|
|
||||||
events: EventsResponse
|
events: EventsResponse
|
||||||
riders: RidersResponse
|
riders: RidersResponse
|
||||||
runs: RunsResponse
|
runs: RunsResponse
|
||||||
|
|
@ -228,11 +159,6 @@ export type CollectionResponses = {
|
||||||
// https://github.com/pocketbase/js-sdk#specify-typescript-definitions
|
// https://github.com/pocketbase/js-sdk#specify-typescript-definitions
|
||||||
|
|
||||||
export type TypedPocketBase = PocketBase & {
|
export type TypedPocketBase = PocketBase & {
|
||||||
collection(idOrName: '_authOrigins'): RecordService<AuthoriginsResponse>
|
|
||||||
collection(idOrName: '_externalAuths'): RecordService<ExternalauthsResponse>
|
|
||||||
collection(idOrName: '_mfas'): RecordService<MfasResponse>
|
|
||||||
collection(idOrName: '_otps'): RecordService<OtpsResponse>
|
|
||||||
collection(idOrName: '_superusers'): RecordService<SuperusersResponse>
|
|
||||||
collection(idOrName: 'events'): RecordService<EventsResponse>
|
collection(idOrName: 'events'): RecordService<EventsResponse>
|
||||||
collection(idOrName: 'riders'): RecordService<RidersResponse>
|
collection(idOrName: 'riders'): RecordService<RidersResponse>
|
||||||
collection(idOrName: 'runs'): RecordService<RunsResponse>
|
collection(idOrName: 'runs'): RecordService<RunsResponse>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue