Cassandra Codegen
Cassandra Codegen is a utility that generates TypeScript type definitions and type-safe mappers directly from a Cassandra or ScyllaDB database schema. Its current stable version is 0.0.11. The package releases updates on an irregular but active cadence, primarily addressing bug fixes, adding support for new Cassandra types, and enhancing generated type safety. A key differentiator is its ability to produce mappers that extend the functionality of `cassandra-driver`, offering improved type annotations for partition keys, clustering columns, and query operators. It automatically maps Cassandra types like `map` to TypeScript's `Record` and handles optionality/nullability for non-primary key columns in generated insert/retrieve types, aligning with typical driver behavior. The project draws inspiration from `kysely-codegen` for its schema-to-type generation approach.
Common errors
-
ReferenceError: Cannot access 'cyclistCategoryMapper' before initialization
cause The `initMappers` function was not called with a connected Cassandra client before attempting to use a generated mapper.fixCall `await initMappers(yourConnectedCassandraClient);` once at application startup. -
Error: All contact points failed to connect
cause The Cassandra host, port, datacenter, or credentials provided to the `cassandra-codegen` CLI or the `cassandra-driver` client are incorrect, or the Cassandra instance is not running/accessible.fixVerify the `--host`, `--port`, `--datacenter`, `--username`, and `--password` arguments when running `cassandra-codegen`, and check your `cassandra-driver` client configuration. Ensure the Cassandra database is running and reachable from your application's environment. -
Property 'mapColumn' does not exist on type 'CyclistCategoryRow'
cause This error can occur if your Cassandra table uses a `map` type column and you are using `cassandra-codegen` version older than 0.0.10/0.0.11, or the generated types are incorrect.fixUpgrade `cassandra-codegen` to version 0.0.11 or newer. Re-run the code generation CLI tool to regenerate the types, ensuring the `map` type is correctly mapped to `Record<K, V>` in TypeScript.
Warnings
- breaking The type used for unknown Cassandra types changed from `any` to `unknown`. This requires consumers of generated types to explicitly handle `unknown` where previously `any` might have been implicitly accepted, potentially leading to compilation errors.
- breaking Non-primary key properties in generated row types (for insert/retrieve contexts) are now marked as optional (`?`) and nullable (`| null`). This aligns with `cassandra-driver`'s behavior but changes the shape of generated interfaces.
- gotcha Executing the `cassandra-codegen` CLI directly might fail with 'command not found' if your npm configuration doesn't automatically add `node_modules/.bin` to your PATH.
- gotcha The `initMappers` function must be called exactly once with a connected `cassandra-driver` client instance before any generated mappers can be used. Failure to do so will result in runtime errors.
- gotcha Prior to v0.0.11, there was a bug in the regex responsible for parsing the `map` type, potentially leading to incorrect type generation or errors when encountering Cassandra `map` types. Support for `map` type to TypeScript's `Record` was also limited before v0.0.10 unless `--use-js-map` was used.
Install
-
npm install cassandra-codegen -
yarn add cassandra-codegen -
pnpm add cassandra-codegen
Imports
- initMappers
const { initMappers } = require('cassandra-codegen');import { initMappers } from 'cassandra-codegen'; - cyclistCategoryMapper
import cyclistCategoryMapper from 'cassandra-codegen';
import { cyclistCategoryMapper } from 'cassandra-codegen'; - queryOperator
import * as queryOperator from 'cassandra-codegen/queryOperator';
import { queryOperator } from 'cassandra-codegen';
Quickstart
import { initMappers, queryOperator } from 'cassandra-codegen';
import type { CyclistCategoryRow } from './generated/mykeyspace'; // Adjust path to your generated types
import { Client } from 'cassandra-driver';
// 1. Configure and connect your cassandra-driver client
const cassandraClient = new Client({
contactPoints: ['127.0.0.1'], // Your Cassandra host
localDataCenter: 'datacenter1', // Your datacenter
credentials: { username: 'user', password: 'password' }, // Your credentials
keyspace: 'mykeyspace', // The keyspace you generated types for
});
async function main() {
await cassandraClient.connect();
console.log('Cassandra client connected.');
// 2. Initialize the generated mappers with the connected client
await initMappers(cassandraClient);
console.log('Mappers initialized.');
// 3. Import and use a generated mapper (e.g., 'cyclistCategoryMapper')
// Assuming 'cyclistCategoryMapper' and 'CyclistCategoryRow' are exported from './generated/mykeyspace.ts'
// You must run the `cassandra-codegen` CLI tool first to generate these files.
const cyclistCategoryMapper: {
get: (criteria: { category: string; points: number }) => Promise<CyclistCategoryRow | null>;
find: (criteria: { category?: string; points?: number | { $gte?: number; $lte?: number } }) => Promise<CyclistCategoryRow[]>;
// ... other generated methods like insert, update, remove
} = {} as any; // Placeholder for actual generated mapper
console.log('\n--- Fetching a specific cyclist category ---');
const specificCyclist = await cyclistCategoryMapper.get({
category: 'GC',
points: 100,
});
console.log('Retrieved:', specificCyclist);
console.log('\n--- Finding cyclists using a query operator ---');
const filteredCyclists = await cyclistCategoryMapper.find({
category: 'GC',
points: queryOperator.gte(42), // Using a type-safe query operator
});
console.log('Filtered results:', filteredCyclists);
await cassandraClient.shutdown();
console.log('Cassandra client disconnected.');
}
main().catch(console.error);
/*
To run this example:
1. Ensure Cassandra is running and your keyspace/table exists.
2. Install dependencies: `npm install cassandra-codegen cassandra-driver @types/cassandra-driver`
3. Generate types/mappers: `npm exec cassandra-codegen -- --host 127.0.0.1 --port 9042 --datacenter datacenter1 --username user --password password --keyspace mykeyspace --generate-ts-file --output-dir ./generated`
4. Adjust the import path for `CyclistCategoryRow` and the mocked `cyclistCategoryMapper` to point to your generated file (e.g., `./generated/mykeyspace`).
5. Run with `ts-node your-file.ts` (if `ts-node` is installed) or compile and run `tsc your-file.ts && node your-file.js`.
*/