From 26a92b3078760a481d58af6a4d31bf5de3b72345 Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Mon, 4 May 2026 22:22:49 +0200 Subject: [PATCH] feat(apps/app): add plugins/3.axios-bindings.ts to wire stores into axios MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supplies the runtime closures that the registerInterceptors seam needs. The plugin imports the four stores (`useOrganisationStore`, `useNotificationStore`, `useAuthStore`, `useImpersonationStore`) — allowed by the boundaries matrix (`plugins → stores`) — and passes them as lazy callbacks so the store factories only resolve when an HTTP call actually fires. Numeric prefix `3.` runs after `2.pinia.ts` (auto-loaded by `@core/utils/plugins.ts` in alphabetical-path order), so Pinia is guaranteed active before the bindings register. No change to `main.ts` is required — the file is picked up by the existing `import.meta.glob('./plugins/*.{ts,js}')` glob. Two redirects previously inside axios.ts now live where they belong: - `window.location.href = '/platform'` on impersonation revocation, in the `onImpersonationRevoked` closure. - `handleUnauthorized()` (which itself redirects to `/login`) on 401, gated by `isInitialized` inside the `onAuthFail` closure — preserves the race-condition fix from sessie 1b-iii. With this commit the two Vite mixed-import warnings (useAuthStore + useImpersonationStore being both statically and dynamically imported) disappear from `pnpm build`. Lint stays at 0 problems, typecheck clean, 49/49 tests pass. Refs TECH-AXIOS-STORE-COUPLING. Co-Authored-By: Claude --- apps/app/src/plugins/3.axios-bindings.ts | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 apps/app/src/plugins/3.axios-bindings.ts diff --git a/apps/app/src/plugins/3.axios-bindings.ts b/apps/app/src/plugins/3.axios-bindings.ts new file mode 100644 index 00000000..599a1793 --- /dev/null +++ b/apps/app/src/plugins/3.axios-bindings.ts @@ -0,0 +1,26 @@ +import type { App } from 'vue' +import { apiClient, registerInterceptors } from '@/lib/axios' +import { useAuthStore } from '@/stores/useAuthStore' +import { useImpersonationStore } from '@/stores/useImpersonationStore' +import { useNotificationStore } from '@/stores/useNotificationStore' +import { useOrganisationStore } from '@/stores/useOrganisationStore' + +// Numeric prefix `3.` runs after `2.pinia.ts`, so Pinia is active by +// the time these store factories resolve. Stores are looked up lazily +// inside each callback (not eagerly at plugin-init), which keeps the +// seam tolerant of any future plugin-ordering changes. +export default function (_: App): void { + registerInterceptors(apiClient, { + getActiveOrgId: () => useOrganisationStore().activeOrganisationId, + notify: (message, level) => useNotificationStore().show(message, level), + onAuthFail: () => { + const authStore = useAuthStore() + if (authStore.isInitialized) + authStore.handleUnauthorized() + }, + onImpersonationRevoked: () => { + useImpersonationStore().clearState() + window.location.href = '/platform' + }, + }) +}