@lilinx/link-qwik
v0.0.3
Published
Qwik City hooks (useChannel, useCall) and /api/lilinx proxy for Lilinx
Readme
@lilinx/link-qwik
Qwik City integration — useChannel, useCall, poll/call proxy, keyed singleton transport.
Consuming the package
From npm (pre-built lib/index.qwik.mjs)
Required Vite config:
// vite.config.ts
export default defineConfig({
plugins: [qwikCity(), qwikVite()],
ssr: {
noExternal: ['@lilinx/link-qwik'],
},
});Important: read connection status as store.status, not a separate Signal:
const { store } = useChannel('jobs:demo');
return <span>{store.status}</span>; // ✅ updates after poll
// NOT: live.status.value — Signals from pre-built library chunks do not cross the Qwik library boundaryData and status both live on the useStore returned as store (store.data, store.status). Use tick when you need useComputed$ over channel state.
From monorepo source (recommended for library development)
Alias to src/index.ts so the host app's Qwik optimizer compiles hooks:
resolve: {
alias: {
'@lilinx/link-qwik': path.resolve(__dirname, '../../packages/link/link-qwik/src/index.ts'),
},
},
ssr: { noExternal: ['@lilinx/link-qwik'] },See apps/demo/demo-qwik/vite.config.ts.
Multi-backend (sync-admin)
One app, two Link servers — nested providers with distinct scope and apiProxy:
<QwikLinkProvider scope="poll:ik" url={IK_WS} apiProxy="/api/lilinx">
<IkRoutes />
</QwikLinkProvider>
<QwikLinkProvider scope="poll:bd" url={BD_WS} apiProxy="/api/lilinx/bd">
<BdRoutes />
</QwikLinkProvider>Each scope gets its own createLilinx singleton and poll proxy. Demo: /multi-backend-demo.
Transport (preferTransport)
Default: ws (WebSocket → SSE → HTTP poll). Poll fallback uses apiProxy when set.
// Provider-level (all channels under this backend)
<QwikLinkProvider
url={import.meta.env.VITE_LINK_WS_URL}
apiProxy="/api/lilinx"
preferTransport="ws"
/>
// Per-channel override
const { store } = useChannel('jobs:demo', { preferTransport: 'poll' });| Value | Behaviour |
|-------|-----------|
| 'ws' (default) | Try WebSocket first, fall back to SSE then poll |
| 'sse' | Prefer SSE stream; poll as last resort |
| 'poll' | HTTP poll only (edge/serverless) |
url and preferTransport serve different roles: url sets the backend address and hard transport limits (ws:// = WS only, poll:// = HTTP only). preferTransport chooses order within allowed transports. apiProxy is separate — same-origin Qwik route for poll + calls (CORS-safe), not a transport URL.
API
| Export | Purpose |
|--------|---------|
| QwikLinkProvider | Bootstrap (url, apiProxy, optional scope, preferTransport) |
| useChannel | Channel → store.data, store.status, tick, channel.call |
| useCall | Global router call |
| acquireLinkSingleton(factory, scope?) | Keyed transport singleton |
| wakeupLiveChannel(channel, scope?) | Scope-aware poll wakeup |
| resolveLinkScope | scope ?? key ?? apiProxy ?? url |
Full reference: docs/packages/link-qwik.md.
