From c21553536f5693cac0861856492520c274503b10 Mon Sep 17 00:00:00 2001 From: "Fabian @ Blax Software" Date: Tue, 30 Jun 2026 11:53:40 +0200 Subject: [PATCH] =?UTF-8?q?fix(ws):=20resolve=20a=20function=20`url`=20laz?= =?UTF-8?q?ily=20=E2=80=94=20don't=20invoke=20the=20getter=20at=20construc?= =?UTF-8?q?tion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit createWsClient eagerly invoked a function-form `config.url` to print a dev-time URL-validation warning. For a module-scope singleton built with `createVueWsClient({ url: () => useRuntimeConfig().public... })`, that called useRuntimeConfig() at import time — outside any Nuxt context — and threw "A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function" (regression vs 0.2.x). Now only STRING urls are validated eagerly; a function url stays lazy and is resolved in _getUrl() at connect time (as in 0.2.x). Bump 0.3.1. --- package.json | 2 +- src/ws.ts | 36 ++++++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 533d214..c50e84c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@blax-software/networking", - "version": "0.3.0", + "version": "0.3.1", "description": "Plug-and-play API + WebSocket client. Framework-agnostic core with optional Vue, Nuxt, and React bindings.", "type": "module", "main": "./dist/index.cjs", diff --git a/src/ws.ts b/src/ws.ts index 3c33cbb..2c2f89f 100644 --- a/src/ws.ts +++ b/src/ws.ts @@ -642,20 +642,28 @@ export function createWsClient( : (config.isServer ?? false) if (isServer) return createSsrStub(createRef) - // Validate configuration and warn developers about common issues - const url = typeof config.url === 'function' ? config.url() : config.url - if (!url || url === 'wss:///app/' || url === 'ws:///app/') { - console.error( - '[blax-networking] WebSocket URL is empty or malformed: ' + JSON.stringify(url) + '\n' + - 'Ensure WEBS_URL and PUSHER_APP_KEY are configured. ' + - 'Expected format: wss://your-ws-host/app/{appKey}', - ) - } else if (url.endsWith('/app/') || url.endsWith('/app')) { - console.error( - '[blax-networking] WebSocket URL is missing the app key: ' + url + '\n' + - 'Ensure PUSHER_APP_KEY is set. The URL must end with /app/{appKey} ' + - 'where {appKey} matches the PUSHER_APP_KEY on the backend.', - ) + // Validate configuration and warn developers about common issues. + // IMPORTANT: only resolve a STRING url here. A function url is lazy by design — + // it may depend on a runtime context that does not exist yet at construction + // time (e.g. Nuxt's `useRuntimeConfig()`, which throws when called outside a + // plugin/setup/lifecycle). Calling it eagerly here crashed module-scope + // singletons built with `createVueWsClient({ url: () => useRuntimeConfig()... })`. + // Function urls are resolved lazily at connect time instead. + if (typeof config.url === 'string') { + const url = config.url + if (!url || url === 'wss:///app/' || url === 'ws:///app/') { + console.error( + '[blax-networking] WebSocket URL is empty or malformed: ' + JSON.stringify(url) + '\n' + + 'Ensure WEBS_URL and PUSHER_APP_KEY are configured. ' + + 'Expected format: wss://your-ws-host/app/{appKey}', + ) + } else if (url.endsWith('/app/') || url.endsWith('/app')) { + console.error( + '[blax-networking] WebSocket URL is missing the app key: ' + url + '\n' + + 'Ensure PUSHER_APP_KEY is set. The URL must end with /app/{appKey} ' + + 'where {appKey} matches the PUSHER_APP_KEY on the backend.', + ) + } } return new WsClientImpl(config, createRef)