chore: install ts-reset in both portal and app SPAs
Installs @total-typescript/ts-reset 0.6.1 as a dev-dependency in
apps/portal/ and apps/app/. Patches TypeScript's loosest default
types: Array.filter(Boolean) returns non-nullable, JSON.parse
returns unknown, fetch().json() returns unknown, Map.get() strict,
etc.
Configuration: src/reset.d.ts in each SPA imports the reset. Both
tsconfig.json files already include ./src/**/* so the .d.ts is
picked up automatically — no tsconfig edits needed.
Issues surfaced during install:
- 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 returning
unknown instead of any). Fixed inline at lines 19 + 123 via
`as ImpersonationState` casts that make the existing
trust-in-sessionStorage explicit. Backlog entry
TECH-TS-IMPERSONATION tracks proper runtime shape validation.
- apps/portal — 22 pre-existing tsc errors in own code (mostly
tiptap editor components — tracked as TECH-TS-PORTAL-TSC,
unrelated to ts-reset). Zero new errors in portal's own code.
4 additional errors surfaced in tiptap's uncompiled node_modules
.ts sources (third-party); left as-is.
Neither SPA achieves `tsc --noEmit` clean today — pre-existing
state unrelated to this work package. Build + vitest are the
actual working gates and both remain green:
- apps/portal: vitest 113/113 passing; production build succeeds
- apps/app: (no vitest setup — tracked as TECH-APP-VITEST);
production build succeeds
Documentation: /dev-docs/FRONTEND-TOOLING.md added; CLAUDE.md
quality-gates updated.
Backlog: TECH-TS-IMPERSONATION (runtime validation of stored
impersonation state), TECH-TS-PORTAL-TSC (pre-existing portal tsc
errors), TECH-APP-VITEST (Vitest coverage for apps/app).
No production behavior change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -83,6 +83,7 @@
|
||||
"@tiptap/extension-subscript": "^2.27.1",
|
||||
"@tiptap/extension-superscript": "^2.27.1",
|
||||
"@tiptap/extension-underline": "^2.27.1",
|
||||
"@total-typescript/ts-reset": "^0.6.1",
|
||||
"@types/mapbox-gl": "3.4.1",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/qrcode": "^1.5.6",
|
||||
|
||||
8
apps/app/pnpm-lock.yaml
generated
8
apps/app/pnpm-lock.yaml
generated
@@ -214,6 +214,9 @@ importers:
|
||||
'@tiptap/extension-underline':
|
||||
specifier: ^2.27.1
|
||||
version: 2.27.1(@tiptap/core@2.27.1(@tiptap/pm@2.27.1))
|
||||
'@total-typescript/ts-reset':
|
||||
specifier: ^0.6.1
|
||||
version: 0.6.1
|
||||
'@types/mapbox-gl':
|
||||
specifier: 3.4.1
|
||||
version: 3.4.1
|
||||
@@ -1383,6 +1386,9 @@ packages:
|
||||
'@tiptap/pm': ^2.7.0
|
||||
vue: ^3.0.0
|
||||
|
||||
'@total-typescript/ts-reset@0.6.1':
|
||||
resolution: {integrity: sha512-cka47fVSo6lfQDIATYqb/vO1nvFfbPw7uWLayIXIhGETj0wcOOlrlkobOMDNQOFr9QOafegUPq13V2+6vtD7yg==}
|
||||
|
||||
'@trysound/sax@0.2.0':
|
||||
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
@@ -6044,6 +6050,8 @@ snapshots:
|
||||
'@tiptap/pm': 2.27.1
|
||||
vue: 3.5.22(typescript@5.9.3)
|
||||
|
||||
'@total-typescript/ts-reset@0.6.1': {}
|
||||
|
||||
'@trysound/sax@0.2.0': {}
|
||||
|
||||
'@tybys/wasm-util@0.10.1':
|
||||
|
||||
1
apps/app/src/reset.d.ts
vendored
Normal file
1
apps/app/src/reset.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import '@total-typescript/ts-reset'
|
||||
@@ -16,7 +16,7 @@ interface ImpersonationState {
|
||||
|
||||
export const useImpersonationStore = defineStore('impersonation', () => {
|
||||
const stored = sessionStorage.getItem(SESSION_STORAGE_KEY)
|
||||
const state = ref<ImpersonationState | null>(stored ? JSON.parse(stored) : null)
|
||||
const state = ref<ImpersonationState | null>(stored ? (JSON.parse(stored) as ImpersonationState) : null)
|
||||
let broadcastChannel: BroadcastChannel | null = null
|
||||
|
||||
const isImpersonating = computed(() => !!state.value)
|
||||
@@ -120,7 +120,7 @@ export const useImpersonationStore = defineStore('impersonation', () => {
|
||||
const stored = sessionStorage.getItem(SESSION_STORAGE_KEY)
|
||||
if (stored) {
|
||||
try {
|
||||
state.value = JSON.parse(stored)
|
||||
state.value = JSON.parse(stored) as ImpersonationState
|
||||
}
|
||||
catch {
|
||||
sessionStorage.removeItem(SESSION_STORAGE_KEY)
|
||||
|
||||
Reference in New Issue
Block a user