Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
<!-- markdownlint-disable MD024 -->
# Spec Delta — react-ui-i18n deferred tooling
## ADDED Requirements
### Requirement: Stories ship for every i18n primitive
Every primitive added by the `react-ui-i18n` capability SHALL ship a sibling `.stories.tsx` alongside its implementation. Each story file SHALL contain a `default` export plus a `playground` and at least one variants story (the chassis-wide stories convention). Stories SHALL render inside `<TranslationProvider>` + `<RegistryProvider>` + `<ReactUiI18nBridge>` so the rendered surface matches production-runtime composition. Story-snapshot tests SHALL run as part of the package's test suite.
The covered surfaces are: `<FormattedNumber>`, `<FormattedCurrency>`, `<FormattedDate>`, `<FormattedList>`, `<FormattedRelativeTime>`, `<Plural>`, `<FormattedMessage>`, `<ReactUiI18nBridge>`, `formattedCell`, `useValidationMessageBridge`, and `<InputNumber>`.
**Verified by:** per-feature story-snapshot tests (one `*.stories.test.tsx` per primitive) plus a presence check in `scripts/check-i18n-stories.test.ts` (or equivalent).
#### Scenario: every i18n primitive has a `.stories.tsx` sibling
- GIVEN the directory `src/i18n/<primitive>/`
- WHEN the chassis `*.stories.tsx` walker runs
- THEN every public primitive listed in the capability spec has a matching `<primitive>.stories.tsx` file
### Requirement: bun run check:i18n-keys catches translation-key drift
The package SHALL ship `scripts/check-i18n-keys.ts` invoked via `bun run check:i18n-keys`. The script SHALL AST-walk every `*.{ts,tsx}` under `src/components/**` and `src/i18n/**` looking for translation-key references — `t("react-ui.…")`, `tDynamic("react-ui.…")`, `<FormattedMessage i18nKey="react-ui.…" />`, `<Trans i18nKey="react-ui.…" />` — and SHALL diff the discovered key set against `src/locales/en-GB.json`. The script SHALL exit non-zero when any key is referenced in code but absent from the bundle (`MISSING`) or present in the bundle but referenced nowhere in code (`ORPHAN`). The script SHALL be wired into `bunx turbo lint` so CI fails on drift.
**Verified by:** `scripts/check-i18n-keys.test.ts` — fixture directory exercising the missing, orphan, and clean paths.
#### Scenario: missing key in code fails the gate
- GIVEN a source file referencing `t("react-ui.foo.absent")` and `en-GB.json` lacking that key
- WHEN `bun run check:i18n-keys` runs
- THEN the script exits non-zero and prints `MISSING: react-ui.foo.absent` with the source path
#### Scenario: orphan key in bundle fails the gate
- GIVEN `en-GB.json` containing `react-ui.foo.unused` and no source reference
- WHEN `bun run check:i18n-keys` runs
- THEN the script exits non-zero and prints `ORPHAN: react-ui.foo.unused`
#### Scenario: clean source + bundle pair passes
- GIVEN every key in `en-GB.json` is referenced in code AND every code-referenced key is in the bundle
- WHEN `bun run check:i18n-keys` runs
- THEN the script exits zero with no diagnostics
### Requirement: bun run check:registry-eject verifies shadcn ejection
The package SHALL ship `scripts/check-registry-eject.ts` invoked via `bun run check:registry-eject`. For every `registry/r/<name>.json` entry the script SHALL:
1. Resolve the listed source files.
2. Apply the registry transform (rewriting `@suaveplan/react-ui` imports to local relative paths, preserving `@suaveplan/react-i18n` imports).
3. Run `tsc --noEmit` against the transformed tree using a synthesized consumer `tsconfig.json` that declares `@suaveplan/react-i18n` and React peers via `compilerOptions.paths`.
The script SHALL exit non-zero when any registry entry's transformed source fails to type-check, surfacing the underlying tsc diagnostics with the entry name as context. The script SHALL also detect missing registry entries — public components / primitives in `src/components/**` and `src/i18n/**` lacking a corresponding `registry/r/<name>.json` SHALL trigger a `MISSING REGISTRY ENTRY` diagnostic. The script SHALL be wired into `bunx turbo lint`.
**Verified by:** `scripts/check-registry-eject.test.ts` — fixture-driven happy-path + failure-path tests.
#### Scenario: ejected primitive type-checks against react-i18n
- GIVEN the registry entry `formatted-number.json`
- WHEN the transform is applied to its files and the result is type-checked
- THEN `tsc --noEmit` exits 0 and the import `import { useFormatter } from "@suaveplan/react-i18n"` resolves
#### Scenario: missing registry entry for a public primitive fails the gate
- GIVEN a public primitive at `src/i18n/<new>/<new>.tsx` with no corresponding `registry/r/<new>.json`
- WHEN `bun run check:registry-eject` runs
- THEN the script exits non-zero with `MISSING REGISTRY ENTRY: src/i18n/<new>/<new>.tsx`
#### Scenario: corrupted transform output fails the gate
- GIVEN a registry entry whose source references a symbol the transform fails to rewrite correctly
- WHEN the transformed source is type-checked
- THEN the script exits non-zero with `EJECT FAILURE: <name>` and the underlying tsc diagnostics