TypedChrono

API Reference

Complete reference documentation for the SchoBase TypeScript SDK. All methods are fully typed with compile-time safety.

Installation

Install SchoBase via npm, yarn, or pnpm:

npm install schobase

Client Initialization

createClient()

Initialize a SchoBase client instance.

Signature

function createClient<TSchema extends Schema>(
  config: ClientConfig<TSchema>
): SchoBaseClient<TSchema>

Parameters

NameTypeDescription
config.endpointstringSchoBase server endpoint URL
config.apiKeystringAPI authentication key
config.schemaTSchemaDatabase schema definition
config.timeout?numberRequest timeout in milliseconds (default: 30000)

Example

import { createClient, defineSchema } from 'schobase'
import { z } from 'zod'

const schema = defineSchema({
  tables: {
    sensorReadings: {
      validator: z.object({
        sensorId: z.string(),
        timestamp: z.date(),
        temperature: z.number(),
      }),
      timeIndex: 'timestamp',
    },
  },
})

const client = createClient({
  endpoint: process.env.SCHOBASE_ENDPOINT!,
  apiKey: process.env.SCHOBASE_API_KEY!,
  schema,
})

Backend Configuration

SchoBase supports multiple time series backends. Choose the one that fits your deployment needs: cloud-managed (Timestream), self-hosted (TimescaleDB), or specialized time series (InfluxDB).

TimescaleDB

Recommended

PostgreSQL extension optimized for time series data. Best for on-premise deployments and when you need SQL compatibility.

Configuration

import { createClient, defineSchema } from 'schobase'
import { z } from 'zod'

const schema = defineSchema({
  tables: {
    temperatures: {
      validator: z.object({
        sensorId: z.string(),
        timestamp: z.date(),
        temperature: z.number(),
        location: z.string(),
      }),
      timeIndex: 'timestamp',
    },
  },
})

const client = await createClient({
  backend: 'timescaledb',
  schema,
  connection: {
    type: 'timescaledb',
    host: 'localhost',
    port: 5432,
    database: 'schobase',
    user: 'postgres',
    password: process.env.DB_PASSWORD!,
  },
})

// Write data
await client.temperatures.write({
  sensorId: 'temp-01',
  timestamp: new Date(),
  temperature: 23.5,
  location: 'warehouse',
})

Connection Options

PropertyTypeDescription
type'timescaledb'Backend type identifier
hoststringDatabase host address
portnumberDatabase port (default: 5432)
databasestringDatabase name
userstringDatabase username
passwordstringDatabase password

AWS Timestream

Cloud

Fully managed time series database service by AWS. Best for cloud-native applications with serverless scaling.

Configuration

import { createClient, defineSchema } from 'schobase'
import { z } from 'zod'

const schema = defineSchema({
  tables: {
    iotMetrics: {
      validator: z.object({
        deviceId: z.string(),
        timestamp: z.date(),
        temperature: z.number(),
        humidity: z.number(),
        pressure: z.number(),
      }),
      timeIndex: 'timestamp',
    },
  },
})

const client = await createClient({
  backend: 'timestream',
  schema,
  connection: {
    type: 'timestream',
    region: 'us-east-1',
    database: 'my-timestream-db',
    credentials: {
      accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
    },
  },
})

// Write data
await client.iotMetrics.write({
  deviceId: 'device-001',
  timestamp: new Date(),
  temperature: 25.3,
  humidity: 65.2,
  pressure: 1013.25,
})

Connection Options

PropertyTypeDescription
type'timestream'Backend type identifier
regionstringAWS region (e.g., 'us-east-1')
databasestringTimestream database name
credentials?objectAWS credentials (optional, uses IAM if omitted)

InfluxDB

Coming Soon

Purpose-built time series database with high write performance. Best for IoT and real-time analytics workloads.

Configuration

import { createClient, defineSchema } from 'schobase'
import { z } from 'zod'

const schema = defineSchema({
  tables: {
    sensorData: {
      validator: z.object({
        sensorId: z.string(),
        timestamp: z.date(),
        value: z.number(),
        unit: z.string(),
      }),
      timeIndex: 'timestamp',
    },
  },
})

const client = await createClient({
  backend: 'influxdb',
  schema,
  connection: {
    type: 'influxdb',
    url: 'http://localhost:8086',
    token: process.env.INFLUXDB_TOKEN!,
    org: 'my-org',
    bucket: 'my-bucket',
  },
})

// Write data
await client.sensorData.write({
  sensorId: 'sensor-001',
  timestamp: new Date(),
  value: 42.7,
  unit: 'celsius',
})

Connection Options

PropertyTypeDescription
type'influxdb'Backend type identifier
urlstringInfluxDB server URL
tokenstringAuthentication token
orgstringOrganization name
bucketstringData bucket name

Schema Definition

defineSchema()

Define your time series database schema.

Signature

function defineSchema<T extends Record<string, TableDefinition>>(
  definition: { tables: T }
): Schema<T>

Table Definition Options

PropertyTypeDescription
validatorZodSchemaZod schema for type validation
timeIndexstringField name for time indexing
indexes?string[]Additional fields to index
retentionDays?numberData retention period in days

Example

import { defineSchema } from 'schobase'
import { z } from 'zod'

const schema = defineSchema({
  tables: {
    metrics: {
      validator: z.object({
        metricName: z.string(),
        timestamp: z.date(),
        value: z.number(),
        tags: z.record(z.string()),
      }),
      timeIndex: 'timestamp',
      indexes: ['metricName'],
      retentionDays: 90,
    },
  },
})

Write Operations

write()

Write a single data point to the time series.

Signature

async function write<T>(data: T): Promise<WriteResult>

Example

await client.sensorReadings.write({
  sensorId: 'temp-01',
  timestamp: new Date(),
  temperature: 23.5,
})

writeBatch()

Write multiple data points in a single request.

Signature

async function writeBatch<T>(data: T[]): Promise<BatchWriteResult>

Parameters

NameTypeDescription
dataT[]Array of records to write (max 1000 per batch)

Example

const readings = Array.from({ length: 100 }, (_, i) => ({
  sensorId: 'temp-01',
  timestamp: new Date(Date.now() - i * 1000),
  temperature: 20 + Math.random() * 10,
}))

const result = await client.sensorReadings.writeBatch(readings)
console.log(`Wrote ${result.recordsIngested} records`)

Query Operations

query()

Create a query builder for type-safe queries.

Signature

function query(): QueryBuilder<T>

Query Builder Methods

where(field, operator, value) - Filter records by field value
timeRange({ start, end }) - Filter by time range
orderBy(field, direction) - Sort results
limit(n) - Limit number of results
offset(n) - Skip first n results
groupBy(interval) - Group by time interval
aggregate(functions) - Calculate aggregates
execute() - Execute the query and return results

Example

const results = await client.sensorReadings
  .query()
  .where('sensorId', '==', 'temp-01')
  .timeRange({
    start: new Date('2024-01-01'),
    end: new Date('2024-01-02'),
  })
  .orderBy('timestamp', 'desc')
  .limit(100)
  .execute()

aggregate()

Perform time-based aggregations (avg, min, max, sum, count).

Signature

function aggregate(
  functions: Record<string, AggregateFunction>
): QueryBuilder<AggregateResult>

Aggregate Functions

FunctionDescription
avgCalculate average value
minFind minimum value
maxFind maximum value
sumSum all values
countCount number of records
stddevCalculate standard deviation
percentileCalculate percentile (p50, p95, p99)

Example

const stats = await client.sensorReadings
  .query()
  .where('sensorId', '==', 'temp-01')
  .timeRange({
    start: new Date(Date.now() - 24 * 60 * 60 * 1000),
    end: new Date(),
  })
  .groupBy('1h') // 1-hour buckets
  .aggregate({
    avgTemp: { field: 'temperature', fn: 'avg' },
    maxTemp: { field: 'temperature', fn: 'max' },
    minTemp: { field: 'temperature', fn: 'min' },
    count: { fn: 'count' },
  })
  .execute()

subscribe()

Subscribe to real-time data updates.

Signature

function subscribe(): SubscriptionBuilder<T>

Example

const unsubscribe = client.sensorReadings
  .subscribe()
  .where('sensorId', '==', 'temp-01')
  .onUpdate((data) => {
    console.log('New reading:', data)
  })
  .onError((error) => {
    console.error('Subscription error:', error)
  })

// Stop subscription
unsubscribe()

Protocol Adapters

OpcUaAdapter

Connect to OPC UA servers for industrial automation data.

new OpcUaAdapter({
  endpoint: 'opc.tcp://...',
  securityMode: 'SignAndEncrypt',
  credentials: { ... }
})

ModbusAdapter

Poll Modbus TCP/RTU devices for sensor readings.

new ModbusAdapter({
  host: '192.168.1.100',
  port: 502,
  unitId: 1
})

MqttAdapter

Subscribe to MQTT topics from IoT devices.

new MqttAdapter({
  brokerUrl: 'mqtt://...',
  username: '...',
  password: '...'
})

Dnp3Adapter

Collect data from DNP3 devices (SCADA/utilities).

new Dnp3Adapter({
  host: '...',
  port: 20000,
  masterAddress: 1
})

Error Handling

SchoBase throws typed errors for validation failures, network issues, and server errors.

import { ValidationError, NetworkError, AuthError } from 'schobase'

try {
  await client.sensorReadings.write({
    sensorId: 'temp-01',
    timestamp: new Date(),
    temperature: 200, // Exceeds max of 125
  })
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Validation failed:', error.issues)
  } else if (error instanceof NetworkError) {
    console.error('Network error:', error.message)
  } else if (error instanceof AuthError) {
    console.error('Authentication failed')
  }
}

TypeScript Types

All SchoBase APIs are fully typed. TypeScript will infer types based on your schema definition.

// Types are automatically inferred from schema
type SensorReading = z.infer<typeof schema.tables.sensorReadings.validator>

// Query results are typed
const results: SensorReading[] = await client.sensorReadings
  .query()
  .execute()

// Aggregation results have computed types
const stats: Array<{
  bucket: Date
  avgTemp: number
  maxTemp: number
  count: number
}> = await client.sensorReadings
  .query()
  .groupBy('1h')
  .aggregate({ avgTemp: { ... }, maxTemp: { ... }, count: { ... } })
  .execute()

Need More Help?

Check out our examples, tutorials, or join the community for support.