97 lines
3.5 KiB
Markdown
97 lines
3.5 KiB
Markdown
# Frontend tooling
|
|
|
|
Type-safety and quality tooling for the Vue 3 + TypeScript SPAs.
|
|
|
|
## ts-reset
|
|
|
|
Installed in both `apps/portal/` and `apps/app/` as a dev-dependency.
|
|
Imported via `src/reset.d.ts`:
|
|
|
|
```typescript
|
|
import '@total-typescript/ts-reset'
|
|
```
|
|
|
|
Both SPAs' `tsconfig.json` include `./src/**/*`, so the `.d.ts` is
|
|
picked up automatically — no explicit `include` edit needed.
|
|
|
|
### What it changes
|
|
|
|
ts-reset patches TypeScript's loosest default types:
|
|
|
|
- `Array.filter(Boolean)` returns non-nullable `Array<T>` instead
|
|
of `Array<T | null | undefined | false | 0 | "">`
|
|
- `JSON.parse` returns `unknown` instead of `any`
|
|
- `fetch().then(r => r.json())` returns `unknown` instead of `any`
|
|
- `Array.includes()` accepts narrower types
|
|
- `Map.get()` returns `T | undefined` more strictly
|
|
- See <https://github.com/total-typescript/ts-reset> for the full list
|
|
|
|
### Why this matters
|
|
|
|
The default TypeScript types for these built-ins lose information
|
|
that real code relies on. ts-reset fixes the types to match runtime
|
|
behavior, surfacing bugs that were previously hidden.
|
|
|
|
### Adoption state
|
|
|
|
**apps/app** — 0 pre-install tsc errors in own code; install
|
|
surfaced 2 errors in `src/stores/useImpersonationStore.ts` (both
|
|
from `JSON.parse` on sessionStorage content). Both fixed inline via
|
|
`as ImpersonationState` assertions that make the existing trust-in-
|
|
sessionStorage explicit. A backlog entry (TECH-TS-IMPERSONATION)
|
|
tracks proper runtime validation of the stored shape.
|
|
|
|
**apps/portal** — 22 pre-existing tsc errors in own code (mostly
|
|
tiptap editor components — unrelated to ts-reset). ts-reset added
|
|
0 new errors in portal's own code. 4 additional errors surfaced in
|
|
tiptap's third-party `.ts` sources under `node_modules` (tiptap
|
|
ships uncompiled TypeScript and some of its internal `JSON.parse`
|
|
call sites fall under ts-reset's tightening). Not our code; left
|
|
as-is.
|
|
|
|
Neither SPA achieves `tsc --noEmit` clean today — that's a pre-
|
|
existing state unrelated to this work package. Build + vitest are
|
|
the actual CI-relevant gates and both remain green.
|
|
|
|
### Bypassing
|
|
|
|
`@ts-expect-error` with comment justification at the call site —
|
|
never blanket-disable ts-reset. If a specific reset is genuinely
|
|
wrong for the project, document it; the upstream issue is the
|
|
backstop.
|
|
|
|
## Vitest
|
|
|
|
Runs against `apps/portal/` and `apps/app/`. `apps/app/` has a
|
|
Vitest test suite (402 tests as of May 2026); run with `pnpm test`
|
|
from `apps/app/`.
|
|
|
|
## Storybook
|
|
|
|
Storybook 10.x is installed in apps/app/ as a component development
|
|
and documentation tool.
|
|
|
|
**Scripts (run from apps/app/):**
|
|
- `pnpm storybook` — dev server on http://localhost:6006
|
|
- `pnpm build-storybook` — static build to storybook-static/
|
|
|
|
**Config files:**
|
|
- apps/app/.storybook/main.ts — framework, stories glob, addons, viteFinal aliases
|
|
- apps/app/.storybook/preview.ts — PrimeVue (via installPrimeVue plugin), Tailwind
|
|
|
|
**Stories location:** co-located with components (ComponentName.stories.ts
|
|
next to ComponentName.vue). Exception: smoke-test stories live in
|
|
src/stories/.
|
|
|
|
**Addons (explicit, no addon-essentials):**
|
|
- @storybook/addon-docs — autodocs, prop tables
|
|
- @storybook/addon-a11y — axe-core accessibility checks per story
|
|
|
|
**Scope boundary:** Storybook = isolated render, autodocs, a11y.
|
|
Interaction testing (click, form submit, emit) stays in Playwright CT.
|
|
Do NOT install @storybook/addon-interactions.
|
|
|
|
**Not in Storybook:** page-level views, components with direct
|
|
useAuthStore / useOrganisationStore calls (these need to be
|
|
decoupled to props first).
|