Files
dashfront/.cursor/rules/no-silent-fallbacks.mdc
2026-07-31 17:51:57 +02:00

88 lines
2.4 KiB
Plaintext

---
description: Keine Fallbacks, keine alternativen API-Felder oder Endpoints
alwaysApply: true
---
# Keine Fallbacks, keine alternativen APIs
Stille Fallbacks und parallele API-Verträge verschleiern Fehler und entwerten Tests. Fehlende oder falsche Daten müssen **sichtbar** scheitern — nicht durch Ersatzwerte kaschiert werden.
## Verboten
### Alternative Feldnamen / Response-Formen
```js
// ❌
const nodes = data?.tree ?? data?.categories ?? [];
const target = article.sku ?? article.slug ?? article.id;
const rootId = data.rootCategoryId ?? companyRootCategoryId ?? null;
// ✅
requireObject(data, 'category/tree');
const nodes = requireArray(data.tree, 'category/tree.tree');
const rootId = data.rootCategoryId ?? companyRootCategoryId;
requireDefined(rootId, 'rootCategoryId');
```
Ein Endpoint, ein Shape, ein Feldname — dokumentiert in `src/api/index.js`.
### Alternative Endpoints für denselben Zweck
```js
// ❌ Zwei Wege für dieselben Daten
category.getTree();
http('/api/article/byCategory?...');
// ✅ Nur der vereinbarte Endpoint
category.getArticles(categoryId);
```
Neue Endpoints nur nach expliziter Vereinbarung; alte nicht parallel als Fallback behalten.
### Default-Werte beim Parsen / in Selectors
```js
// ❌
selectCompanyIso639 = (s) => s.company.current?.iso639 ?? 'de';
name: raw.name ?? 'Unbenannt';
// ✅
selectCompanyIso639 = (s) => s.company.current?.iso639;
// UI zeigt leer oder Fehler, wenn null
```
### Display-Platzhalter für fehlende Daten
```js
// ❌
<TableCell>{row.cName || '—'}</TableCell>
label={`Kategorie ${id}`}
// ✅
<TableCell>{row.cName}</TableCell>
// oder gar nicht rendern
```
### Ersatz-Identifikatoren in URLs
```js
// ❌
/artikel/${sku ?? slug ?? id}
// ✅
/artikel/${sku} — nur wenn sku gesetzt, sonst disabled / kein Link
```
## Erlaubt
- **Formular-Startwerte** beim Öffnen eines leeren Dialogs (z. B. `defaultIso639()` für Neuanlage)
- **Explizite Fehlerbehandlung:** `requireObject` / `requireArray` / `requireDefined` aus `src/utils/apiShape.js` → Thunk rejected → `BackendError`
- **Optionale Vertragsfelder** nur wenn im API-Vertrag als optional dokumentiert (z. B. `sort` in Sort-Comparator)
## Bei neuem Code
1. API-Vertrag in `src/api/index.js` kommentieren
2. Antwort mit `apiShape`-Helfern validieren
3. Kein `??`-Ketten für „vielleicht heißt es anders“
4. Fehler im UI anzeigen, nicht durch Defaults überdecken