# JavaScript ADK (ART Development Kit)

The JavaScript ADK provides the tools needed for your project to interact with the A Realtime Tech(ART) application.

This package contains only the functionality required to connect and communicate with ART services.

**Note**:
 Installing the ADK package alone is not enough to communicate with ART services — it must also be authenticated using client credentials.  
 The JavaScript ADK does not have separate development or production modes and can be used directly in production without requiring a separate build step.

## Usage
### To establish and manage connection with ART services
```js
import Adk from '@arealtimetech/adk-js';

const adk = new Adk({
    Uri: "",   // service URL
    AuthToken: "" // Passcode generated from server for authenticating user
});

// Establish connection
adk.connect();

// Handle connection open event
adk.on("open",async (event) => {
    console.log("ADK connection opened", event);
});

// Handle connection close event
adk.on("close", () => {
    console.log("ADK connection closed");
});

adk.disconnect();

```
### Subscribe into a Channel
The `subscribe()` method allows your client to join a specific channel within ART services.  
Once subscribed, the channel acts as a real-time communication stream where you can **send**, **receive**, and **listen to events or messages**, as well as track **user presence**.

```js
const sub = await adk.subscribe("YOUR_CHANNEL_NAME");
```

### User Presence in a Channel

After subscribing to a channel, you can track which users are currently active in that channel.  
The `fetchPresence()` method provides real-time presence information by returning a list of connected users.

```js
// Listen for active users in the channel
sub.fetchPresence((users) => {
    console.log("Active users:", users);
});
```

### Listen to All Events and Messages

The `listen()` method allows you to capture **all events and messages** published within the subscribed channel.  
This is a catch-all listener that delivers every incoming payload, regardless of event type.

```js
// Listen to all events and messages in the channel
sub.listen((data) => {
    console.log("Received:", data);
});
```

### Listen to a Specific Event

The `bind()` method lets you listen for a **specific event** within the subscribed channel.  
Unlike `listen()`, which captures everything, `bind()` filters messages and triggers the callback **only when the defined event occurs**.

```js
// Listen to a specific event in the channel
sub.bind("EVENT", (data) => {
    console.log("Event received:", data);
});
```

### Send Messages to Specific Users

The `push()` method is used to send an event or message into the channel asynchronously.  
Along with the event name and payload, you can optionally specify a list of **target usernames** to deliver the message only to those users.

```js
// Send an event with payload to specific users
const payload = {
    message: "Hello!"
};

sub.push("EVENT", payload, {
    to: ["username1", "username2"] // list of target users
});
```

## Shared Object Channel

A **Shared Object Channel** is a real-time, collaborative data structure. It’s backed by a **CRDT** so multiple clients can update the same JSON tree concurrently; everyone converges to a consistent state.


```js
// subscribe like any channel
const sub = await adk.subscribe("YOUR_SO_CHANNEL_NAME");
```
### Reading
#### Listen for live updates
Listen to a **path** inside the shared object. Your callback receives plain JSON when that subtree changes.

```js
// path examples: "", "user", "user.profile", "todos"
const unsubscribe = await sub.query("user.profile").listen((data) => {
  console.log("profile updated:", data);
});

// later
unsubscribe();

```
Path rules
- "" (empty) or "index" → whole document
- Use dot paths for objects (e.g., user.profile.name).
- For arrays, listen at the array path (e.g., "todos"). Item keys are internal; per-item paths aren’t stable.


### Fetch once (no subscription)
Retrieve the current state at a specific key path without subscribing to continuous updates.
```js
const profile = await sub.query("user.profile").execute();
```

### Writing
sub.state() returns a live proxy. Mutate it like normal JS; changes are batched and merged with CRDT rules. The proxy:
- Auto-creates missing parent objects/arrays on write.
- Deletes safely (deleting a missing key is a no-op).
- Emits ops optimistically (UI updates immediately) and sends a compacted batch to the server.
```js
// Get the live state proxy once and reuse it
const state = sub.state();

/* ---------- Objects ---------- */
// Create/modify nested fields
state.user.profile.name = "Jane Doe";

// Safe delete (no error if the key doesn't exist)
delete state.settings.theme;

/* ---------- Arrays ---------- */
// Arrays support push/pop/splice, numeric index get/set, and length
state.todos.push({ text: "one" }, { text: "two" });

// You can immediately update newly added items
state.todos[0].text = "ONE";

// Replace item at index 1
state.todos.splice(1, 1, { text: "two-ish" });

// Pop last item (returns the removed value)
const last = state.todos.pop();

/* ---------- Flushing ---------- */
// The client batches & compacts ops automatically.
// Call flush() to force-send the current batch now.
await sub.flush();

```

Array API (on any array path)
- push(...items) / pop() / unshift(...items)
- splice(start, deleteCount?, ...insert)
- insertAt(index, item)
- move(fromIndex, toIndex)
- Numeric index get/set (state.todos[0] = {...})
- delete state.todos[i] (remove at index)

> Notes
> - You cannot create sparse indices by assignment (e.g., todos[5] = ... when length is 1). Use insertAt/splice.
> - For newly pushed items you can mutate them immediately (optimistic local state).

## Documentation
See [docs.arealtimetech.com](https://docs.arealtimetech.com)
