@ember-link/core

What is @ember-link/core?

@ember-link/core is the foundational package for all Ember Link clients. It provides the low-level primitives and protocols that power real-time communication across all supported frameworks (React, Svelte, etc).

Key Responsibilities

  • WebSocket Management Establishes and maintains a persistent connection to the Ember Link server with automatic reconnection and backoff strategies.

  • Channel Layer A lightweight publish/subscribe interface that lets you join, leave, and communicate over named channels.

  • Authentication Token-based client authentication for secure access to collaborative resources.

When to Use @ember-link/core

  • Building a custom framework integration

  • Extending or debugging low-level behavior

  • Using plain Javascript

Installation

yarn install @ember-link/core

Basic Usage

import { createClient } from '@ember-link/core';

const client = createClient({
	baseUrl: 'http://localhost:9000'
});

// 3. Join a channel (e.g., a collaborative document or room)
const { channel, leave } = client.joinChannel('test');

// 4. Listen to other user events
channel.events.subscribe('others', (others) => {
	console.log('Current users in channel: ', others);
});

// 5. Update your own presence
channel.updatePresence({ status: 'online' });

// 6. Listen to your own presence
channel.events.subscribe('presence', (presence) => {
	console.log('My Presence was updated:', presence);
});

// 7. Send any message you want
channel.sendCustomMessage({ data: 'can be any JSON serializable data' });

// 8. Listen to custom messages
channel.events.subscribe('customMessage', (message) => {
	console.log('Recieved message from peers: ', message);
});

Typescript

Defining custom presence types and custom message types

declare global {
	interface EmberLink {
		Presence: {
			status: 'online' | 'offline';
		};
		Custom: {
			data: string;
		};
	}
}

API

Client

To create a new instance of Client, you must pass a configuration object of type CreateClientOptions.

CreateClientOptions

interface CreateClientOptions {
	baseUrl: string;
	authEndpoint?: AuthEndpoint;
	multiTenant?: {
		tenantId: string;
	};
	jwtSignerPublicKey?: string;
}
NameTypeRequiredDescription
baseUrlstringThe base URL of your Ember Link backend.
authEndpointAuthEndpointConfiguration for authentication.
└ URLstringA URL for the authentication endpoint.
└ functionfunctionA function that returns a signed JWT for authentication.
multiTenantObjectConfiguration for multi-tenant setup.
└ tenantIdstringThe tenant ID used in a multi-tenant setup.
jwtSignerPublicKeystringPublic key used to verify JWTs from your auth provider.

Methods

type JoinChannel<
	P extends Record<string, unknown> = DefaultPresence,
	C extends Record<string, unknown> = DefaultCustomMessageData
> = <S extends IStorageProvider>(
	channelName: string,
	options?: ChannelConfig<S, P>['options']
) => { channel: Channel<P, C>; leave: () => void };

channelName: The name of the channel to join.

options: An optional configuration for joining the channel.

Returns a Channel object and a leave function to leave the channel

Type Arguments: In most cases you shouldn’t have to manually pass the type arguments and you should be able to define them like in the typescript example above

Connecting to a Channel

To create a new instance of a Channel, you need to call the joinChannel function on a Client

ChannelConfig

interface ChannelConfig<
	S extends IStorageProvider,
	P extends Record<string, unknown> = DefaultPresence
> {
	channelName: string;
	baseUrl: string;
	authenticate: () => Promise<AuthValue>;
	createWebSocket: (authValue: AuthValue) => WebSocket;
	options?: {
		initialPresence?: P;
		storageProvider?: S;
		autoConnect?: boolean;
	};
}
NameTypeRequiredDescription
optionsObjectOptional configuration for the channel.
└ initialPresenceType of PresenceOptional initial presence state for the channel.
└ storageProviderSOptional storage provider for syncing data.
└ autoConnectbooleanWhether to automatically connect to the channel (default: true).

Interface

type ChannelEvents<
	P extends Record<string, unknown> = DefaultPresence,
	C extends Record<string, unknown> = DefaultCustomMessageData
> = {
	presence: (self: P) => void;
	status: (status: Status) => void;
	others: (others: User<P>[]) => void;
	destroy: () => void;
	customMessage: (message: Extract<ServerMessage<P, C>, { type: 'custom' }>['data']) => void;
};

type YjsProviderEvents = {
	syncMessage: (message: StorageSyncMessage) => void;
	updateMessage: (message: StorageUpdateMessage) => void;
};

type Channel<
	P extends Record<string, unknown> = DefaultPresence,
	C extends Record<string, unknown> = DefaultCustomMessageData
> = {
	updatePresence: (state: P) => void;
	sendCustomMessage: (data: C) => void;
	hasStorage: () => boolean;
	getStorage: () => IStorage;
	getStatus: () => Status;
	getOthers: () => User<P>[];
	getName: () => string;
	getPresence: () => P | null;
	destroy: () => void;
	updateYDoc: (data: StorageUpdateMessage) => void;
	syncYDoc: (data: StorageSyncMessage) => void;
	events: Observable<ChannelEvents<P, C>> & {
		others: Observable<OtherEvents<P>>;
		yjsProvider: Observable<YjsProviderEvents>;
	};
};
NameTypeDescription
updatePresence(state: P) => voidUpdates the local users presence in the channel.
sendCustomMessage(data: C) => voidSends a message to all other users in the channel.
hasStorage() => booleanReturns true if the channel has a storage provider, false otherwise.
getStorage() => IStorageRetrieves the channel’s storage provider.
getStatus() => StatusReturns the current connection status of the channel.
getOthers() => User<P>[]Retrieves the list of other users in the channel.
getName() => stringReturns the name of the channel.
getPresence() => PReturns the presence state of the channel or null if unavailable.
destroy() => voidDestroys the channel, cleaning up resources and connections.
updateYDoc(data: StorageUpdateMessage) => voidSends an update to the Yjs document in the channel.
syncYDoc(data: StorageSyncMessage) => voidSynchronizes the Yjs document in the channel.
eventsObservable<ChannelEvents<P, C>>Event emitter for channel-specific events. Includes others and yjsProvider.