@corva/chat-core
v0.1.4
Published
Platform-agnostic core of Corva Team Chat, shared by the web and mobile apps
Maintainers
Keywords
Readme
@corva/chat-core
Platform-agnostic core of Corva Team Chat, shared by corva-web-frontend and corva-react-native-app.
It holds everything that is not UI: the Revolt/Stoat API and socket client, chat stores, and the
$$CORVA:: message wire format. Each app renders its own UI on top of it.
Rules
- No platform globals. The type environment is
es2022only, with no DOM or Node types. The only globals allowed are the timers,consoleandrequestAnimationFramedeclared insrc/platform.d.tsandsrc/raf.d.ts.fetch,WebSocket, storage, notifications and app-state events are injected by the host app through adapters. - No React. Stores use
zustand/vanilla; each app wraps them in its own hooks. - No UI dependencies (
@corva/ui, MUI, React Native).
Runtime dependencies must also resolve through a main field: the mobile app runs Metro with
package exports turned off, which is why uuid stays on v11 (v12+ ship only exports).
Hosts must provide a global crypto.getRandomValues for uuid: browsers have it, and the mobile
app installs it with polyfillWebCrypto() from expo-standard-web-crypto in its root layout.
Lint and typecheck enforce these rules.
Setup
Call configureChat(host) once at app start, before touching any store, then ensureChatSession(corvaUser) to sign in:
import { configureChat, ensureChatSession } from '@corva/chat-core';
configureChat({
apiUrl, // Revolt REST, e.g. https://stoat.corva.ai/api
wsUrl, // Revolt events, e.g. wss://stoat.corva.ai/ws
platform, // ChatPlatform, see below
storage, // KeyValueStorage: localStorage on web
corvaApi, // { get, post } against corva-api with the Corva JWT
appState, // { isHidden, isInactive, subscribe, onTerminate? }
dates, // { startOfTomorrowAt(hour, now) } in the user's timezone
notifier, // optional { showIncomingMessage, onMessageSent, onLogout }
});
await ensureChatSession(corvaUser);| Host member | Web | React Native |
| ----------- | ---------------------------------------------------------- | --------------------------------------- |
| storage | localStorage | MMKV, or a hydrated in-memory map |
| corvaApi | apiCore / jsonApi (get repeats array keys) | the app's ApiClient |
| appState | visibilityState, hasFocus(), pagehide | AppState (background counts hidden) |
| dates | moment with the user's timezone default | date-fns in the device timezone |
| notifier | browser notification + sound, notification prompt, favicon | push/local notification, badge |
Stores are zustand/vanilla stores (roomStore, messageStore, …). React apps wrap them:
import { useStore } from 'zustand';
import { roomStore } from '@corva/chat-core';
export const useRoomStore = <T>(selector: (state: ReturnType<typeof roomStore.getState>) => T) =>
useStore(roomStore, selector);Platform adapter
ChatPlatform (src/platform/types.ts) is the transport part of the host, also taken directly by
createRevoltAPI and createRevoltSocket:
| Member | Web | React Native |
| ------------------------- | --------------------------------- | ------------------------------------- |
| fetch | (url, init) => fetch(url, init) | same |
| createWebSocket | url => new WebSocket(url) | same |
| createUploadBody | FormData with the File | FormData with { uri, name, type } |
| subscribeReconnectHints | online + visibilitychange | NetInfo + AppState active |
typecheck/browserPlatform.ts is a compile-only reference web adapter (platform and app state) that proves the browser APIs fit.
Development
nvm use
yarn install
yarn test # vitest, node environment
yarn lint # eslint + prettier
yarn typecheck
yarn build # tsup → dist/ (ESM + .d.ts)Trying a local build in an app
yarn build && npx yalc publish # in this repo
npx yalc add @corva/chat-core # in the consuming appPublishing
npm version patch # or minor / major
npm publish # prepublishOnly runs lint, typecheck, tests, build and package checks
git push --follow-tagsCanary build for testing a branch in an app:
npm version 0.0.0-$(git rev-parse --short HEAD) --no-git-tag-version
npm publish --tag canary && git checkout package.json