Skip to main content

TypeScript SDK

The TypeScript SDK provides the analytics runtime for web, Node.js, and React Native applications.

Packages

Packagenpm scopePurpose
@dejanradmanovic/event-spec-apiCore runtimeClient, Provider interface, Hook system, context
@dejanradmanovic/event-spec-provider-amplitudeAmplitude providerAmplitude HTTP API adapter

Installation

Add a .npmrc pointing the @dejanradmanovic scope to GitHub Packages:

.npmrc
@dejanradmanovic:registry=https://npm.pkg.github.com

Then install:

npm install @dejanradmanovic/event-spec-api @dejanradmanovic/event-spec-provider-amplitude

Setup

import { Client } from '@dejanradmanovic/event-spec-api';
import { AmplitudeProvider } from '@dejanradmanovic/event-spec-provider-amplitude';

const amp = new AmplitudeProvider({
apiKey: process.env.AMPLITUDE_API_KEY!,
});

const client = new Client({
providers: [amp],
});

Tracking events

await client.track('Product Viewed', {
product_id: 'SKU-123',
category: 'electronics',
});

Identify

await client.identify('user-123', {
email: 'alice@example.com',
plan: 'pro',
});

Group

await client.group('user-123', 'org-456', {
name: 'Acme Corp',
plan: 'enterprise',
});

Using generated wrappers

import { productViewed, ProductViewedCategory } from './analytics/generated';
import { client } from './analytics/client';

await productViewed(client, {
category: ProductViewedCategory.Electronics,
productId: 'SKU-123',
});

Context propagation

import { setGlobalContext } from '@dejanradmanovic/event-spec-api';

// Set at startup
setGlobalContext({
attributes: {
locale: navigator.language,
app: { name: 'web-app', version: APP_VERSION },
},
});

// Per-request (server-side)
const reqClient = client.withTransaction({
userId: req.user.id,
anonymousId: req.session.id,
});

Multiple providers

const client = new Client({
providers: [amplitudeProvider, posthogProvider],
});
// Both receive every event.

Hooks

import { SamplingHook, SamplingStrategy, ValidationHook } from '@dejanradmanovic/event-spec-api';

const client = new Client({
providers: [amp],
hooks: [
new SamplingHook({ strategy: SamplingStrategy.UserIdHash, rate: 0.1 }),
new ValidationHook({ lookup: async (name) => registry.getEvent(name) }),
],
});

Event queue

The TypeScript client batches events and flushes them:

  • Automatically every flushInterval (default: 10 seconds)
  • Manually via await client.flush()
  • On shutdown via await client.shutdown()

Always call shutdown() in serverless environments (Vercel edge functions, Cloudflare Workers) to flush before the process exits:

process.on('SIGTERM', async () => {
await client.shutdown();
process.exit(0);
});

TypeScript types

All provider and hook interfaces are fully typed. Import types directly:

import type {
Provider,
Hook,
HookContext,
EventEnvelope,
TrackMessage,
IdentifyMessage,
AnalyticsContext,
} from '@dejanradmanovic/event-spec-api';