From 14b81bf3ebf7f372882830a9a69c01428e8dbe7d Mon Sep 17 00:00:00 2001 From: Padreug Date: Sat, 2 May 2026 14:53:40 +0200 Subject: [PATCH] fix(vite): @/app.config alias must precede @ (first-match-wins) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @rollup/plugin-alias (which Vite uses) iterates alias entries in definition order and uses the first match. Listing the broad '@' → ./src alias before the specific '@/app.config' → per-app override means '@/app.config' is matched by '@' first and resolves to ./src/app.config — i.e. the hub config, not the standalone's. For market this surfaced as: TypeError: Cannot read properties of undefined (reading 'config') at new NostrmarketAPI (nostrmarketAPI.ts:170:45) (nostrmarketAPI reads appConfig.modules.market.config; the hub config has only base.) The same bug affected castle (ExpensesAPI reads modules.expenses.config) and wallet (WalletWebSocketService reads modules.wallet.config.websocket) — both would crash on first use even though their dev servers started fine. Castle and wallet silently haven't been exercised yet in this session, so the bug only surfaced from market. Fix: put '@/app.config' first in the alias object in all 6 standalone vite configs (castle, market, wallet, chat, forum, tasks). Comment added at each call site explaining the constraint. The hub's vite.config.ts doesn't need the override — its '@/app.config' resolves to ./src/app.config naturally, which IS the hub config. Activities (sortir) doesn't need the override either — its app.ts imports from './app.config' (relative), and no module file under src/modules/activities reads from '@/app.config'. Co-Authored-By: Claude Opus 4.7 (1M context) --- vite.castle.config.ts | 9 ++++++--- vite.chat.config.ts | 3 ++- vite.forum.config.ts | 3 ++- vite.market.config.ts | 3 ++- vite.tasks.config.ts | 3 ++- vite.wallet.config.ts | 3 ++- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/vite.castle.config.ts b/vite.castle.config.ts index 272009c..d8d2797 100644 --- a/vite.castle.config.ts +++ b/vite.castle.config.ts @@ -105,10 +105,13 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - '@': fileURLToPath(new URL('./src', import.meta.url)), - // CRITICAL: Remap @/app.config to the castle app's config - // ExpensesAPI and other modules import from @/app.config directly + // ORDER MATTERS — @rollup/plugin-alias is first-match-wins. + // The more specific @/app.config remap must precede the @ prefix + // alias, otherwise '@/app.config' matches '@' first and resolves + // to ./src/app.config (the hub config). ExpensesAPI etc. import + // from @/app.config and need the per-app config. '@/app.config': fileURLToPath(new URL('./src/accounting-app/app.config.ts', import.meta.url)), + '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, build: { diff --git a/vite.chat.config.ts b/vite.chat.config.ts index d49a067..c5b00ac 100644 --- a/vite.chat.config.ts +++ b/vite.chat.config.ts @@ -98,8 +98,9 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - '@': fileURLToPath(new URL('./src', import.meta.url)), + // ORDER MATTERS — @/app.config must precede @ (first-match-wins). '@/app.config': fileURLToPath(new URL('./src/chat-app/app.config.ts', import.meta.url)), + '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, build: { diff --git a/vite.forum.config.ts b/vite.forum.config.ts index fca9d11..feeea35 100644 --- a/vite.forum.config.ts +++ b/vite.forum.config.ts @@ -98,8 +98,9 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - '@': fileURLToPath(new URL('./src', import.meta.url)), + // ORDER MATTERS — @/app.config must precede @ (first-match-wins). '@/app.config': fileURLToPath(new URL('./src/forum-app/app.config.ts', import.meta.url)), + '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, build: { diff --git a/vite.market.config.ts b/vite.market.config.ts index c8e5f8d..5a1a5fe 100644 --- a/vite.market.config.ts +++ b/vite.market.config.ts @@ -98,8 +98,9 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - '@': fileURLToPath(new URL('./src', import.meta.url)), + // ORDER MATTERS — @/app.config must precede @ (first-match-wins). '@/app.config': fileURLToPath(new URL('./src/market-app/app.config.ts', import.meta.url)), + '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, build: { diff --git a/vite.tasks.config.ts b/vite.tasks.config.ts index 6fa6cd2..c939772 100644 --- a/vite.tasks.config.ts +++ b/vite.tasks.config.ts @@ -98,8 +98,9 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - '@': fileURLToPath(new URL('./src', import.meta.url)), + // ORDER MATTERS — @/app.config must precede @ (first-match-wins). '@/app.config': fileURLToPath(new URL('./src/tasks-app/app.config.ts', import.meta.url)), + '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, build: { diff --git a/vite.wallet.config.ts b/vite.wallet.config.ts index 153e4b9..31b2a1d 100644 --- a/vite.wallet.config.ts +++ b/vite.wallet.config.ts @@ -104,8 +104,9 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - '@': fileURLToPath(new URL('./src', import.meta.url)), + // ORDER MATTERS — @/app.config must precede @ (first-match-wins). '@/app.config': fileURLToPath(new URL('./src/wallet-app/app.config.ts', import.meta.url)), + '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, build: {