npm package: @layers/core-wasm
Description: Layers SDK Rust core compiled to WASM with JS glue
Author: Layers Team
Latest version: 2.2.0

# @layers/core-wasm

Rust analytics core compiled to WebAssembly with TypeScript wrappers. This is an **internal package** -- consumers should use [@layers/client](../client), [@layers/node](../node), or [@layers/react-native](../react-native).

## Architecture

```
                  +---------------------------+
                  |   Platform SDKs           |
                  |  (client / node / RN)     |
                  +------------+--------------+
                               |
                  +------------v--------------+
                  |   @layers/core-wasm       |
                  |   JS wrapper (LayersCore) |
                  +------------+--------------+
                               |
                  +------------v--------------+
                  |   Rust / WASM binary      |
                  |   (event queue, consent,  |
                  |    rate limiting, session) |
                  +---------------------------+
```

The Rust/WASM core is the single source of truth for event acceptance, building, and queuing. When WASM is loaded, `track()`/`screen()` delegate entirely to Rust. The JS layer handles HTTP networking, persistence backends, retry with circuit breaker, periodic flush timers, and event hydration from persistence.

When WASM is **not** available (e.g. environments where WASM cannot load), a pure-JS fallback builds events and manages its own queue with identical behavior.

## Entry Points

| Entry                         | Condition        | WASM loading                                                |
| ----------------------------- | ---------------- | ----------------------------------------------------------- |
| `@layers/core-wasm` (default) | Node.js          | Sync via `fs.readFileSync` -- no async init needed          |
| `@layers/core-wasm/browser`   | Browser bundlers | Async via `initWasm()` -- call before creating `LayersCore` |

Browser bundlers (webpack, vite, esbuild) automatically resolve the `"browser"` export condition, which avoids importing `node:fs`.

## API Reference

### `LayersCore.init(init: LayersCoreInit): LayersCore`

Create and initialize a new core instance.

```ts
import { FetchHttpClient, LayersCore, createDefaultPersistence } from '@layers/core-wasm';

const core = LayersCore.init({
  config: {
    apiKey: 'your-api-key',
    appId: 'your-app-id',
    environment: 'production',
    enableDebug: false,
    flushThreshold: 20, // events before auto-flush (default: 20)
    maxQueueSize: 10_000, // max queue depth (default: 10,000)
    maxBatchSize: 1_000, // max events per HTTP batch (default: 1,000)
    flushIntervalMs: 30_000 // periodic flush timer (default: 30s)
  },
  httpClient: new FetchHttpClient(),
  persistence: createDefaultPersistence('your-app-id')
});
```

### `core.track(eventName, properties?, userId?, anonymousId?)`

Record a custom analytics event. Delegates to the WASM core when available.

### `core.screen(screenName, properties?, userId?, anonymousId?)`

Record a screen view event.

### `core.identify(userId)`

Associate subsequent events with a user ID.

### `core.setUserProperties(properties)`

Set user-level properties that persist across sessions.

### `core.setConsent(consent)`

Update consent state. Pass `{ analytics: true/false, advertising: true/false }`.

### `core.flush()`

Synchronous flush -- drains the queue to persistence.

### `core.flushAsync()`

Async flush -- sends events over HTTP with retry and circuit breaker.

### `core.shutdown()`

Persist remaining events and stop the flush timer.

### `core.setDeviceContext(context)`

Set device-level fields (platform, OS version, locale, etc.).

### `core.getSessionId()`

Get the current session ID. Sessions auto-rotate after 30 minutes of inactivity.

### `core.startNewSession()`

Force-start a new session.

### `core.queueDepth()`

Return the number of queued events.

## Persistence Backends

| Backend                           | Use case                                                           |
| --------------------------------- | ------------------------------------------------------------------ |
| `LocalStoragePersistence`         | Browser environments (`window.localStorage`)                       |
| `MemoryPersistence`               | SSR, tests, Node.js                                                |
| `NullPersistence`                 | No persistence -- events only live in memory                       |
| `createDefaultPersistence(appId)` | Auto-detects: localStorage if available, otherwise NullPersistence |

Custom backends implement the `PersistenceBackend` interface:

```ts
interface PersistenceBackend {
  write(key: string, data: Uint8Array): void;
  read(key: string): Uint8Array | null;
  delete(key: string): void;
  listKeys(prefix: string): string[];
}
```

## HTTP Client

The included `FetchHttpClient` uses the Fetch API with configurable timeout (default 30s). Custom HTTP clients implement the `HttpClient` interface:

```ts
interface HttpClient {
  post(url: string, headers: [string, string][], body: Uint8Array): Promise<HttpResponse>;
  get(url: string, headers: [string, string][]): Promise<HttpResponse>;
}
```

## Error Handling

All errors are typed as `LayersError` with a `code` field:

```ts
import { LayersError } from '@layers/core-wasm';

try {
  core.track('event');
} catch (e) {
  if (e instanceof LayersError) {
    console.error(e.code, e.message); // e.g. 'INVALID_ARGUMENT', 'eventName must not be empty'
  }
}
```

Error codes: `INVALID_CONFIG`, `INVALID_ARGUMENT`, `SHUT_DOWN`, `QUEUE_FULL`, `HTTP`, `CIRCUIT_OPEN`, `NETWORK`, `SERIALIZATION`, `RATE_LIMITED`, `CONSENT_NOT_GRANTED`, `PERSISTENCE`, `REMOTE_CONFIG`, `EVENT_DENIED`, `INTERNAL`.

## License

MIT