TAS Client for Experimentation Services
The `tas-client` package, currently at version 0.3.2, provides a client-side library for querying, refetching, and caching data from an experimentation service endpoint. It is specifically designed to interact with endpoints whose results conform to a required experimentation data structure. This client library emphasizes integration via consumer-provided implementations of key interfaces, including `IExperimentationFilterProvider`, `IExperimentationTelemetry`, and `IKeyValueStorage`, allowing for flexible integration with various application environments. Its focus on managing experiment data, including features like configurable refetch intervals and treatment variable retrieval, differentiates it from generic HTTP clients by providing specialized logic for experimentation workflows. Given its `0.x` version, releases are likely feature-driven and ad-hoc rather than on a fixed schedule, indicating an active but evolving development phase.
Common errors
-
TypeError: tasClient is not a constructor
cause Attempting to use CommonJS `require` syntax (`const TASClient = require('tas-client');`) in an environment where the package is published as an ESM module, or incorrect named import.fixEnsure you are using `import { TASClient } from 'tas-client';` for ESM environments. Verify your `tsconfig.json` (for TypeScript) or `package.json` (`"type": "module"`) is configured for ESM. -
TypeError: Cannot read properties of undefined (reading 'getTreatmentVariable')
cause This typically occurs if the `TASClient` instance was not properly initialized due to missing or invalid constructor parameters, or if the underlying endpoint did not return data conforming to the expected experimentation structure, leading to an uninitialized internal state.fixDouble-check that all required properties (`filterProviders`, `telemetry`, `keyValueStorage`, `endpoint`, etc.) are correctly provided and configured in the `TASClient` constructor. Ensure your experimentation service endpoint returns data in the format the `tas-client` expects.
Warnings
- gotcha The synchronous `getTreatmentVariable()` method requires `tasClient.initializePromise` to be awaited beforehand to ensure the client is fully initialized and data is fetched. Failure to do so may result in unexpected behavior or `undefined` values.
- breaking This package explicitly requires Node.js version 22 or higher as specified in its `engines` field in `package.json`. Running it on older Node.js versions will likely lead to runtime errors or installation issues.
- gotcha The `TASClient` constructor requires implementations of `IExperimentationFilterProvider`, `IExperimentationTelemetry`, and `IKeyValueStorage`. Providing incomplete or incorrect implementations of these interfaces will cause the client to malfunction or throw errors during operation.
Install
-
npm install tas-client -
yarn add tas-client -
pnpm add tas-client
Imports
- TASClient
const TASClient = require('tas-client');import { TASClient } from 'tas-client'; - IExperimentationFilterProvider
import type { IExperimentationFilterProvider } from 'tas-client'; - IExperimentationTelemetry
import type { IExperimentationTelemetry } from 'tas-client'; - IKeyValueStorage
import type { IKeyValueStorage } from 'tas-client';
Quickstart
import { TASClient, type IExperimentationFilterProvider, type IExperimentationTelemetry, type IKeyValueStorage } from 'tas-client';
// Minimal implementation of IExperimentationFilterProvider
class MyFilterProvider implements IExperimentationFilterProvider {
getFilters(): Record<string, string> {
return { 'userSegment': 'premium' };
}
}
// Minimal implementation of IExperimentationTelemetry
class MyTelemetry implements IExperimentationTelemetry {
async postEvent(eventName: string, properties: Record<string, any>): Promise<void> {
console.log(`Telemetry event: ${eventName}`, properties);
}
}
// Minimal implementation of IKeyValueStorage
class MyKeyValueStorage implements IKeyValueStorage {
private store: Record<string, string> = {};
async get(key: string): Promise<string | undefined> {
console.log(`Getting key: ${key}`);
return this.store[key];
}
async set(key: string, value: string): Promise<void> {
console.log(`Setting key: ${key} to value: ${value}`);
this.store[key] = value;
}
}
async function runTasClient() {
const filterProvider = new MyFilterProvider();
const telemetry = new MyTelemetry();
const keyValueStorage = new MyKeyValueStorage();
const storageKey = 'myTasClientCache'; // Unique key for storage
const tasEndpoint = process.env.TAS_ENDPOINT ?? 'https://api.example.com/experimentation'; // Replace with actual endpoint
const refetchInterval = 60 * 60 * 1000; // Refetch every hour
const tasClient = new TASClient({
filterProviders: [filterProvider],
telemetry: telemetry,
storageKey: storageKey,
keyValueStorage: keyValueStorage,
assignmentContextTelemetryPropertyName: 'assignmentContext',
telemetryEventName: 'tasClientEvent',
endpoint: tasEndpoint,
refetchInterval: refetchInterval,
});
// Wait for initialization to complete before getting synchronous treatment variables
await tasClient.initializePromise;
const treatmentVariable = tasClient.getTreatmentVariable('myConfigId', 'featureFlag');
console.log(`Treatment variable for 'featureFlag': ${treatmentVariable}`);
// Alternatively, if not awaiting initializePromise:
const treatmentVariableAsync = await tasClient.getTreatmentVariableAsync('anotherConfigId', 'anotherFeature');
console.log(`Async treatment variable for 'anotherFeature': ${treatmentVariableAsync}`);
}
runTasClient().catch(console.error);