Skip to content

feat(eslint): enforce sorted JSX props and object keys across Ankhorage repos #7

Description

@artiphishle

Ziel

Die zentrale ESLint-Konfiguration in @ankhorage/devtools soll eine konsistente Sortierung für JSX Props, Objekt-Keys und Type/Object-Member erzwingen.

Technische Basis:

Gewünschte Ordnung:

  1. Alleinige/shorthand Props zuoberst.
  2. Danach normale Props bzw. Daten-/Konfigurations-Properties.
  3. Danach Funktions-/Callback-Props bzw. Methoden.
  4. Innerhalb der Gruppen immer zuerst required, dann optional, soweit die Regel das für den jeweiligen AST-Kontext unterscheiden kann.
  5. Innerhalb jeder Gruppe deterministisch alphabetisch/natural sortieren.
  6. Prettier muss unverändert funktionieren und darf nicht durch ESLint-Hacks ersetzt werden.
  7. Alle bisherigen Regeln aus @ankhorage/devtools/eslint müssen weiter gelten.

Architekturentscheidung

Für diese Aufgabe soll ausschließlich eslint-plugin-perfectionist verwendet werden.

Keine parallelen oder konkurrierenden Sortier-Regeln aktivieren.

Insbesondere keine Mischkonfiguration mit:

  • ESLint Core sort-keys
  • anderen JSX-Prop-Sortier-Regeln

Sonst entstehen widersprüchliche Auto-Fixes.

Testing-Strategie

Die bisherigen kleinen examples/package und examples/monorepo reichen für diese Sortierregeln langfristig nicht mehr aus.

Es soll deshalb zusätzlich ein neues Root-Testprojekt entstehen:

examples/
  lint-playground/

Ziel:

  • reale JSX-Komponenten
  • reale TypeScript-Interfaces
  • reale Config-Objekte
  • reale Callback-Props
  • reale Spread-Props
  • reale Monorepo-/Boundary-Regeln
  • reale Prettier-Integration

Damit die ESLint-Regeln nicht nur syntaktisch, sondern auch praktisch gegen echte App-Strukturen getestet werden.

Das Playground-Projekt soll absichtlich unsortierte Beispiele enthalten, damit:

  • bun run lint
    Fehler erzeugt
  • bun run lint --fix
    deterministische Ergebnisse produziert
  • anschließend bun run lint
    vollständig grün wird

Das ist deutlich robuster als nur isolierte Unit-Tests auf einzelne Rule-Konfigurationen.

Playground-Anforderungen

Das Beispielprojekt soll mindestens enthalten:

  • React/React Native JSX-Komponenten
  • Interfaces mit required + optional Props
  • Objekt-Konfigurationen mit Methoden + normalen Properties
  • Callback-Props (onPress, onChange, handleSubmit, etc.)
  • shorthand Props
  • Spread Props
  • Imports/Exports
  • mindestens ein bewusst schwieriger Fall, bei dem Reihenfolge semantisch relevant sein könnte

Verifikation des Playground-Projekts

Im Beispielprojekt müssen folgende Abläufe funktionieren:

bun run lint
bun run lint --fix
bun run lint
bun run build

Optional zusätzlich:

bun run format:check

Phase 1 — devtools Dependencies und ESLint-Version prüfen

  • Prüfen, ob die aktuelle eslint/@eslint/js Version in package.json realistisch und installierbar ist.
  • Falls nötig sauber auf die aktuelle stabile ESLint-Major-Version pinnen/upgraden.
  • eslint-plugin-perfectionist als Dependency von @ankhorage/devtools hinzufügen.
  • Keine Peer-Dependency-Verwirrung erzeugen: konsumierende Repos sollen weiterhin nur @ankhorage/devtools verwenden können.
  • bun install ausführen und Lockfile aktualisieren.

Phase 2 — zentrale Config sauber erweitern

Datei: src/eslint.ts

  • perfectionist importieren und im plugins Objekt registrieren.
  • Rules logisch sortieren und kurze Kommentarsektionen einfügen, z. B.:
    • TypeScript safety
    • TypeScript style
    • Imports
    • Object/member ordering
    • Unused code
    • Formatting
    • Project boundaries
    • Runtime ergonomics
  • Bestehende Regeln unverändert beibehalten, insbesondere:
    • kein any
    • restricted imports
    • simple import sort
    • unused imports
    • Prettier rule/config
  • prettier/prettier weiterhin aktiv lassen.
  • eslint-config-prettier weiterhin als letztes Config-Element anwenden.

Phase 3 — Sortierregeln konfigurieren

JSX Props

Regel:

perfectionist/sort-jsx-props

Gewünschte Gruppierung:

groups: [
  'shorthand-prop',
  'unknown',
  'callback-prop',
]

Mit customGroups für Callback-/Handler-Props:

customGroups: [
  {
    groupName: 'callback-prop',
    elementNamePattern: '^(on|handle)[A-Z].*',
  },
]

Hinweise:

  • Shorthand Props wie disabled, compact, selected stehen oben.
  • Normale Props wie title, description, variant, tone, style, testID stehen danach.
  • Handler wie onPress, onChange, onSubmit stehen unten.
  • Spread Props können Sortierpartitionen erzeugen; Codex soll vorhandene Spreads nicht blind verschieben, wenn dadurch Semantik geändert würde.

Object expressions

Regel:

perfectionist/sort-objects

Gewünschte Gruppierung:

groups: [
  'property',
  'method',
]

Optional prüfen, ob Callback-Werte via customGroups sinnvoll separat nach unten gruppiert werden können, z. B. Properties mit Funktionswert oder Namen on[A-Z]....

Wichtig: Keine unsicheren Objekt-Reorderings bei Objekten, deren Property-Reihenfolge semantisch relevant ist. Falls nötig gezielte Overrides nur für klar begründete Fälle ergänzen.

TypeScript interfaces / object types

Regel:

perfectionist/sort-object-types

Gewünschte Gruppierung:

groups: [
  'required-property',
  'optional-property',
  'required-method',
  'optional-method',
]

Damit Props-/Config-Typen zuerst required Props, dann optionale Props und danach Methoden/Funktionen bekommen.

Phase 4 — Tests, Beispiele und README aktualisieren

  • Tests in devtools ergänzen oder vorhandene Tests anpassen, damit die neue Config exportierbar und nutzbar bleibt.
  • examples/package/eslint.config.mjs und examples/monorepo/eslint.config.mjs prüfen; keine lokalen Hacks einbauen.
  • Neues examples/lint-playground Projekt erstellen.
  • README ergänzen:
    • neue Sortierpolicy kurz erklären
    • erwähnen, dass die Regeln über @ankhorage/devtools/eslint zentral kommen
    • klarstellen, dass Prettier weiterhin Formatierung macht und ESLint nur strukturelle Ordnung/Safety erzwingt
    • erklären, wie das Playground-Projekt als Regression-Test verwendet wird
  • Changeset hinzufügen, vermutlich minor:
    • feat: enforce deterministic prop and object member ordering

Phase 5 — devtools Verifikation

Im @ankhorage/devtools Repo ausführen:

bun install
bun run build
bun run lint
bun run format:check
bun run test

Zusätzlich Playground validieren:

cd examples/lint-playground
bun run lint
bun run lint --fix
bun run lint
bun run build

Falls lint Auto-Fixes braucht:

bun run format
bun run lint --fix
bun run build
bun run lint
bun run format:check
bun run test

Phase 6 — konsumierende Repos aktualisieren

Nach Veröffentlichung oder lokalem Linking/File-Dependency-Test alle betroffenen Ankhorage-Repos aktualisieren.

Priorität:

  1. @ankhorage/zora
  2. @ankhorage/surface
  3. @ankhorage/contracts
  4. @ankhorage/templates
  5. @ankhorage/orchestrator
  6. @ankhorage/orchestrator-module-expo-localization
  7. @ankhorage/orchestrator-module-expo-google-fonts
  8. @ankhorage/paradox
  9. @ankhorage/react-native-reanimated-dnd-web falls es die zentrale Config nutzt
  10. privates Hauptrepo/ankhorage4 zuletzt, weil dort wahrscheinlich die meisten JSX-Fixes entstehen

Für jedes Repo:

  • @ankhorage/devtools Version bumpen.
  • bun install ausführen.
  • bun run lint:fix oder vorhandenes Lint-Fix-Script ausführen.
  • Manuell alle Fälle prüfen, bei denen Auto-Fix Spread Props oder semantisch relevante Objekt-Reihenfolgen berührt.
  • Keine lokalen eslint-disable, keine @ts-ignore, keine any-Casts einbauen.
  • Verifikation je Repo:
bun run build
bun run lint:fix
bun run test

Falls ein Repo kein lint:fix Script hat, vorhandene Scripts respektieren und keine neue Script-Konvention erzwingen, außer es ist sinnvoll und separat dokumentiert.

Phase 7 — Akzeptanzkriterien

  • @ankhorage/devtools published/exportiert eine saubere Flat-Config mit Perfectionist-Plugin.
  • Prettier funktioniert weiterhin unverändert.
  • Bestehende TypeScript-/Import-/Boundary-Regeln funktionieren weiterhin.
  • JSX Props werden gruppiert sortiert: shorthand zuerst, normale Props danach, callbacks/functions zuletzt.
  • Type/Object Members werden required vor optional sortiert, danach Methoden/Funktionen.
  • Das neue Playground-Projekt validiert reale Anwendungsfälle.
  • Alle aktualisierten Repos sind grün mit Build, Lint und Tests.
  • Keine lokalen Rule-Workarounds in konsumierenden Repos.
  • README und Changeset sind aktualisiert.

Wichtige Guardrails für Codex

  • Kein any, kein as any, kein unknown as any.
  • Kein @ts-ignore oder @ts-expect-error.
  • Kein eslint-disable, außer explizit im PR begründet und vorher abgestimmt.
  • Keine Prettier-Hacks.
  • Keine Schwächung von strict oder anderen TypeScript-Safety-Regeln.
  • Keine Scope-Erweiterung auf andere neue Regelpakete in diesem PR.
  • Erst devtools sauber machen, dann downstream Repos reparieren.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions