Go to file
Fabian @ Blax Software cca10c6061 fix: call setAppReady() automatically in createFromNuxtConfig 2026-04-16 08:52:52 +02:00
.github feat: expose ws globally for console debugging 2026-04-16 08:48:19 +02:00
src fix: call setAppReady() automatically in createFromNuxtConfig 2026-04-16 08:52:52 +02:00
.gitignore chore: revert dist/ commit, add prepare script for git installs 2026-04-16 08:38:03 +02:00
README.md Init 2026-04-07 08:44:00 +02:00
package-lock.json chore: bump to 0.3.0 2026-04-16 08:31:50 +02:00
package.json chore: revert dist/ commit, add prepare script for git installs 2026-04-16 08:38:03 +02:00
tsconfig.json Init 2026-04-07 08:44:00 +02:00
tsup.config.ts Init 2026-04-07 08:44:00 +02:00

README.md

@blax-software/networking

Framework-agnostic API and WebSocket client library with optional Vue, Nuxt, and axios adapters.

Features

  • Zero required dependencies — core uses native fetch and WebSocket
  • Tree-shakeable — import only what you need
  • SSR-safe — server detection with automatic no-op stubs
  • Framework adapters — Vue ref() reactivity, Nuxt auto-config, axios compatibility
  • TypeScript-first — Full type coverage with .d.ts exports

Install

npm install @blax-software/networking

# Optional peer dependencies:
npm install vue          # for /vue and /nuxt entry points
npm install axios        # for /axios adapter

Quick Start

Vanilla / React / Any framework

import { createApiClient, createWsClient } from '@blax-software/networking'

const api = createApiClient({
  serverUrl: 'https://api.example.com',
})

const ws = createWsClient({
  url: 'wss://api.example.com/app/ws',
  getAuthToken: () => api.getBearer(),
})

// REST
const users = await api.get('users')

// WebSocket
await ws.connect()
ws.setAppReady()
const result = await ws.send('user.profile', { id: 123 })

// Listen for events — returns an unsubscribe function
const off = ws.listen('chat.message', null, (data) => {
  console.log('New message:', data)
})
// Call off() to stop listening (works with React useEffect cleanup, etc.)

Vue 3

import { useApiClient, useWsClient, useWsListener } from '@blax-software/networking/vue'

const api = useApiClient({
  serverUrl: 'https://api.example.com',
})

const ws = useWsClient({
  url: 'wss://api.example.com/app/ws',
  getAuthToken: () => api.getBearer(),
})

// ws.is_setup, ws.is_opened etc. are Vue refs
watch(ws.is_setup, (ready) => {
  if (ready) console.log('WebSocket ready')
})

// Auto-cleanup on component unmount
useWsListener(ws, 'notifications.new', null, (data) => {
  console.log('Notification:', data)
})

Nuxt 3

// plugins/networking.client.ts
import { createFromNuxtConfig } from '@blax-software/networking/nuxt'

export default defineNuxtPlugin(() => {
  const { api, ws } = createFromNuxtConfig()

  // Optional: store bearer, connect WS, etc.
  api.setBearer(localStorage.getItem('bearerToken') ?? '')
  ws.connect()
  ws.setAppReady()

  return { provide: { api, ws } }
})

Reads these keys from useRuntimeConfig().public:

Key Description
SERVER_URL REST API base URL
SERVER_URL_INTERNAL Internal URL for SSR requests
WEBS_URL WebSocket hostname
WS_PROTOCOL 'wss' or 'ws'

With axios

import { createApiClient } from '@blax-software/networking'
import { createAxiosAdapter } from '@blax-software/networking/axios'
import axios from 'axios'

const axiosInstance = axios.create({
  baseURL: 'https://api.example.com',
  withCredentials: true,
})

const api = createApiClient({
  serverUrl: 'https://api.example.com',
  http: createAxiosAdapter(axiosInstance),
})

API Reference

createApiClient(config: ApiClientConfig): ApiClient

Config Type Default Description
serverUrl string | () => string required Base URL for HTTP requests
ssrServerUrl string | () => string Alternate URL for server-side requests
http HttpAdapter fetchAdapter HTTP adapter (fetch, axios, custom)
notify NotifyFn Notification callback for errors
storage StorageAdapter browserStorage Token persistence adapter
storageKey string 'bearerToken' Storage key for the bearer token
timeout number 10000 Request timeout in ms
withCredentials boolean true Include cookies in requests
retryOn503 boolean true Auto-retry on HTTP 503
apiPrefix string 'api/' Prefix prepended to relative paths
isServer boolean | () => boolean false Whether running on the server (SSR)

ApiClient methods:

Method Returns Description
get(path, params?) Promise<HttpResponse> GET request
post(path, data?, params?) Promise<HttpResponse> POST request
put(path, data?, params?) Promise<HttpResponse> PUT request
delete(path, params?) Promise<HttpResponse> DELETE request
patch(path, data?, params?) Promise<HttpResponse> PATCH request
csrf(path?) Promise<void> Fetch CSRF cookie
setBearer(token) void Set auth token
getBearer() string | null Get current auth token
clearBearer() void Remove auth token
getServerUrl() string Resolve current server URL
parseError(error) never Extract error, notify, and re-throw
parseThen(response, msg?) any Show success notification, return data
configure(partial) void Update config at runtime

createWsClient(config: WsClientConfig, createRef?): WsClient

Config Type Default Description
url string | () => string required Full WebSocket URL
getAuthToken () => string | null Auth token getter for channel subscription
notify NotifyFn Connection state notifications
translate TranslateFn Translation function for notification text
defaultChannel string 'websocket' Default channel name
heartbeatInterval number 20000 Ping interval (ms)
reconnectDelay number 3000 Delay before reconnect attempt (ms)
autoReconnect boolean true Auto-reconnect on disconnect
isServer boolean | () => boolean false Returns safe no-op stub when true
isNativePlatform boolean | () => boolean false Suppresses browser-only notifications

WsClient methods:

Method Returns Description
connect(force?) Promise<WebSocket | void> Open socket connection
send(event, data?, channel?, progress?) Promise<T> Send event, await response
listen(event, channel, callback) () => void Listen for event, returns unsubscribe fn
listenOnce(event, channel?) Promise<any> Resolve on next occurrence
setAppReady() void Unblock gated send() calls
resetConnection() void Force channels to re-subscribe
destroy() void Close and clean up everything

Reactive state (Vue refs when using vue/nuxt adapters, plain objects otherwise):

Property Type Description
is_opened ReactiveRef<boolean> Socket is open
is_setup ReactiveRef<boolean> Default channel established
is_connecting_socket ReactiveRef<boolean> Connection in progress
is_after_lost_connection ReactiveRef<boolean> Had a connection loss

Storage Adapters

import { browserStorage, memoryStorage } from '@blax-software/networking'

// Default — uses localStorage (safe for SSR, returns null on errors)
const api1 = createApiClient({ serverUrl: '...', storage: browserStorage })

// In-memory — for SSR, tests, or environments without localStorage
const api2 = createApiClient({ serverUrl: '...', storage: memoryStorage() })

License

MIT