Files
crewli/apps/app/src/main.ts
bert.hausmans f218ac6e69 fix(primevue): switch installer to named export to stop double-registration
main.ts explicitly calls installPrimeVue(app) AFTER registerPlugins(app)
per the comment in main.ts ("so PrimeVue lives outside the Vuexy @core
machine"). The intent was a single registration site outside the
auto-discovery loop.

Bug: registerPlugins (src/@core/utils/plugins.ts) globs
plugins/*/index.{ts,js} eagerly and invokes the `default` export of
each match. plugins/primevue/index.ts was exporting installPrimeVue
as the default, so registerPlugins also picked it up and called it.
End result: PrimeVue and its three services (Toast, Confirmation,
Dialog) were each registered twice on every app boot. Visible
symptoms: duplicate Toast emissions on a single Toast.add() call,
and ConfirmationService callbacks firing twice for one user
confirmation.

Fix: convert `export default function installPrimeVue` to a NAMED
export, and update main.ts's import to `{ installPrimeVue }`. The
registerPlugins glob still picks up the module path but the
`pluginImportModule.default?.(app)` invocation becomes a no-op via
optional chaining (no default export to call). main.ts remains the
single registration site.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 13:35:59 +02:00

52 lines
1.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Iconify-Tabler runtime data — side-effect import must run before any
// component renders an Icon, so the @iconify/vue runtime resolves
// names locally instead of falling back to the api.iconify.design CDN
// (blocked by our CSP). See plugins/iconify.ts for the bootstrap.
import '@/plugins/iconify'
import { createApp } from 'vue'
import { VueQueryPlugin } from '@tanstack/vue-query'
import { queryClientConfig } from '@/lib/query-client'
import { initSentry, installContextBinding } from '@/observability'
import { router } from '@/plugins/1.router'
import App from '@/App.vue'
import { registerPlugins } from '@core/utils/plugins'
import { installPrimeVue } from '@/plugins/primevue'
// Styles
import '@styles/tailwind.css'
import '@core/scss/template/index.scss'
import '@styles/styles.scss'
// Create vue app
const app = createApp(App)
// RFC-WS-7 — Sentry init runs before plugin registration so the SDK can
// hook Vue's errorHandler before any plugin or component initialises.
// Empty DSN = SDK no-op (mirrors backend behaviour, RFC §3.3).
initSentry({
app,
router,
dsn: import.meta.env.VITE_SENTRY_DSN_FRONTEND ?? '',
release: import.meta.env.VITE_SENTRY_RELEASE ?? '',
environment: import.meta.env.MODE,
})
// Register plugins (router, pinia, vuetify, …).
registerPlugins(app)
// PrimeVue runs alongside Vuetify during the F3F6 parallel-mode window.
// Registered AFTER registerPlugins(app) so PrimeVue lives outside the
// Vuexy @core/ machine — F6 can remove @core/ without affecting PrimeVue.
installPrimeVue(app)
// Bind auth-scope tags per route navigation. Must run after pinia is set
// up by registerPlugins (the guard reads useAuthStore / useOrganisationStore).
installContextBinding(router)
app.use(VueQueryPlugin, queryClientConfig)
// Mount vue app
app.mount('#app')