TypeScript gRPC Package Generation
This document explains the TypeScript gRPC package generation and publishing setup for Chronicle.
Overview
The Chronicle TypeScript gRPC package (@cratis/chronicle.contracts) provides strongly-typed TypeScript bindings for Chronicle's gRPC services. The package generation process consists of two main steps:
- Generate .proto files from C# gRPC service definitions (see Protobuf Extraction)
- Generate TypeScript code from proto files and publish the npm package
Components
1. TypeScript Package (Source/Clients/TypeScript)
An npm package that provides strongly-typed TypeScript bindings for the Chronicle gRPC services.
Structure:
package.json- Package configuration with @cratis/chronicle.contracts as the package nametsconfig.json- TypeScript compiler configurationrollup.config.mjs- Rollup bundler configuration for ESM and CJS buildsindex.ts- Main entry point that exports all generated servicesChronicleConnection.ts- Connection manager for Chronicle servicesChronicleServices.ts- Interface for all available servicesgenerated/- Directory containing TypeScript files generated from proto definitionsREADME.md- Package documentation
How it works:
- Uses
ts-prototo generate TypeScript files from proto definitions - Generates strongly-typed clients with full IDE support and IntelliSense
- Provides
ChronicleConnectionclass for easy connection management - Provides
ChronicleConnectionStringclass for connection string parsing - Implements OAuth 2.0 client credentials flow for authentication
- Exports all service clients and types
- Builds both ESM and CJS versions using Rollup
Key classes:
ChronicleConnection- Main connection manager with service accessChronicleConnectionString- Connection string parser supportingchronicle://URI schemeChronicleServices- Interface defining all available servicesTokenProvider- OAuth token management (client credentials and API key)
2. GitHub Workflows
Build Workflow (.github/workflows/typescript-build.yml)
Validates the TypeScript package on every PR and push to main.
Triggers:
- Push to main branch
- Pull requests to any branch
- Changes to TypeScript client, Contracts, Protobuf, or ProtoGenerator
Steps:
- Setup .NET 10 and Node.js 23
- Install protoc (Protocol Buffer Compiler)
- Build the Contracts assembly
- Run ProtoGenerator to generate .proto files
- Install TypeScript dependencies
- Generate TypeScript files from proto definitions using ts-proto
- Build TypeScript package
Publish Workflow (.github/workflows/publish.yml)
Publishes the TypeScript package to NPM alongside .NET packages during releases.
Triggers:
- Release published
Steps:
- Setup .NET 10 and Node.js 23
- Install protoc
- Build the Contracts assembly
- Run ProtoGenerator to generate .proto files
- Install TypeScript dependencies
- Generate TypeScript files using ts-proto
- Build TypeScript package
- Publish to NPM
- Commit and push updated proto and TypeScript files back to repository
Required Secrets:
NPM_TOKEN- NPM authentication token for publishing
Usage
Prerequisites
Proto files must be generated first. See Protobuf Extraction for details on generating proto files from C# contracts.
Building TypeScript Package Locally
cd Source/Clients/TypeScript
yarn install
yarn build
Using the Published Package
Install the package:
npm install @cratis/chronicle.contracts
# or
yarn add @cratis/chronicle.contracts
Use in your TypeScript code:
import { ChronicleConnection, ChronicleConnectionString } from '@cratis/chronicle.contracts';
// Using the Development connection string (includes default dev credentials)
const connection = new ChronicleConnection({
connectionString: ChronicleConnectionString.Development
});
// Or using a custom connection string
const connection = new ChronicleConnection({
connectionString: 'chronicle://my-client:my-secret@localhost:5000'
});
// Or using the legacy serverAddress (still supported)
const connection = new ChronicleConnection({
serverAddress: 'localhost:5000'
});
// Connect to Chronicle
await connection.connect();
// Use the services with full type safety and IDE completion
const eventStores = await connection.eventStores.GetEventStores({});
console.log('Event stores:', eventStores.items);
// Access other services
const namespaces = await connection.namespaces.GetNamespaces({ EventStore: 'my-store' });
// Clean up
connection.dispose();
Authentication
The package supports two authentication methods:
Client Credentials (OAuth 2.0):
// Connection string with credentials
const connStr = new ChronicleConnectionString('chronicle://client-id:client-secret@localhost:5000');
// Or using helper method
const connStr = ChronicleConnectionString.Default.withCredentials('client-id', 'client-secret');
const connection = new ChronicleConnection({ connectionString: connStr });
API Key:
// Connection string with API key query parameter
const connStr = new ChronicleConnectionString('chronicle://localhost:5000?apiKey=my-api-key');
// Or using helper method
const connStr = ChronicleConnectionString.Default.withApiKey('my-api-key');
const connection = new ChronicleConnection({ connectionString: connStr });
Custom Authority:
// If using an external OAuth server
const connection = new ChronicleConnection({
connectionString: connStr,
authority: 'https://auth.example.com' // Defaults to Chronicle server if not specified
});
Publishing a New Version
The TypeScript package is automatically published to NPM when a new GitHub release is created. The publish workflow will:
- Generate fresh proto files from C# contracts
- Generate TypeScript code from proto files
- Build the TypeScript package
- Publish to NPM with the release version tag
- Commit updated proto and TypeScript files back to the repository
Generated Files
Proto files: Source/Kernel/Protobuf/*.proto
See Protobuf Extraction for the complete list of generated proto files.
TypeScript files: Source/Clients/TypeScript/generated/*.ts
The TypeScript generation creates:
- Service client interfaces and implementations
- Request and response message types
- Enum definitions
- Type definitions for all Chronicle concepts
Maintenance
When adding new gRPC services to the C# Contracts:
- Ensure services are decorated with
[Service]attribute - Ensure methods are decorated with
[Operation]attribute - Regenerate proto files (see Protobuf Extraction)
- Run the TypeScript generation to create new TypeScript clients
- The TypeScript package will automatically include the new services with full type safety
- Publish a new version of the npm package by creating a GitHub release
Package Structure
The published npm package includes:
- ESM build (
dist/esm/) - ES modules for modern bundlers - CJS build (
dist/cjs/) - CommonJS for Node.js compatibility - Type definitions (
dist/types/) - TypeScript .d.ts files for IntelliSense - Source maps - For debugging support
- README.md - Package documentation
Dependencies
The TypeScript package has the following runtime dependencies:
@grpc/grpc-js- gRPC client for Node.js@grpc/proto-loader- Protocol buffer loading (for metadata)
Development dependencies include:
ts-proto- TypeScript code generation from proto filestypescript- TypeScript compilerrollup- Module bundler for builds- Various Rollup plugins for TypeScript and module resolution