@maykonpaulo/maestro-provider-cassandra
v1.0.3
Published
Apache Cassandra provider for @maykonpaulo/maestro-core (ADR 0007) — real CRUD via CQL, catalog-based introspection (system_schema), and missing-table creation. The wide-column family provider.
Readme
@maykonpaulo/maestro-provider-cassandra
📖 Guia completo — criar o admin de qualquer sistema: está no README do pacote
@maykonpaulo/maestro-serverno npm → https://www.npmjs.com/package/@maykonpaulo/maestro-server
An Apache Cassandra provider for @maykonpaulo/maestro-core — the wide-column-family provider (ADR 0007).
IntrospectionProvider— reads real, catalog-sourced structure fromsystem_schema.tables/system_schema.columns— Cassandra enforces a schema (including a mandatory primary key) at the CQL level, so this is not sampling like the document/key-value providers in this family.DatasourceProvider— real CRUD via CQL (cassandra-driver).findById/update/deletequery by primary key directly and efficiently;list/countscan the whole table and filter/sort/paginate in-process, since CQL'sWHERE/ORDER BYonly work over the declared partition/clustering key, not arbitrary fields.SchemaWriteProvider—ensureEntitycreates the table with aPRIMARY KEY— requiresentity.fieldsto include exactly one field withisPrimaryKey: true, since CQL mandates a primary key atCREATE TABLEtime.
Installation
npm install @maykonpaulo/maestro-provider-cassandra @maykonpaulo/maestro-core@maykonpaulo/maestro-core and cassandra-driver are peer dependencies.
Usage
import { createCassandraProvider } from '@maykonpaulo/maestro-provider-cassandra';
const provider = createCassandraProvider({
contactPoints: ['127.0.0.1'],
localDataCenter: 'datacenter1',
keyspace: 'app', // must already exist — this provider creates tables, not keyspaces
});
await provider.ensureEntity({
entity: { table: 'users', fields: [{ name: 'id', nativeType: '', type: 'uuid', nullable: false, isPrimaryKey: true }] },
});
const created = await provider.create({ table: 'users', primaryKey: 'id', data: { name: 'Ada' } });Configuration
export interface CassandraProviderOptions {
contactPoints?: string[];
localDataCenter?: string;
keyspace: string; // required — must already exist
credentials?: { username: string; password: string };
client?: Client; // an already-connected cassandra-driver Client — for tests/embedding
}Exactly one of client or contactPoints/localDataCenter must be provided; keyspace is always required. Call await provider.close() when done with a provider that opened its own client.
Type round-tripping
The driver represents uuid/timeuuid columns as Uuid/TimeUuid wrapper objects and bigint/decimal/varint as Long/BigDecimal/Integer wrapper objects, not plain JS strings/numbers — every value this provider reads is normalized (.toString()) so it round-trips identically through create() → findById()/list(). ensureEntity's own type mapping avoids bigint for this reason (uses CQL int for the integer FieldType, which the driver already returns as a plain number); the normalization above still protects reads against a table created outside this provider with bigint/decimal columns.
Known limitations
- Keyspace must already exist: this provider creates tables, never keyspaces (replication strategy/factor is an operational decision this provider does not make on the caller's behalf).
list/countscan the whole table and filter/sort/paginate client-side — correct, but Cassandra's efficient, indexedWHERE/ORDER BY(over the partition/clustering key) is not used, since the core's generic filter set doesn't map onto "query only by the declared key" the way CQL expects.- No relations: CQL has no foreign-key constraint (denormalization is the idiomatic Cassandra data-modeling pattern instead).
- Composite (partition + clustering) keys:
ensureEntityonly ever creates a single-columnPRIMARY KEY; a table needing a compound key must be created outside this provider.
Testing
Tests run against a real, ephemeral Cassandra node, started per test run via
testcontainers (cassandra:4.1). See
tests/cassandra-integration.test.ts.
Turnkey admin (point at your database, get a UI)
This provider plugs straight into the Maestro turnkey layer: install
@maykonpaulo/maestro-server and
@maykonpaulo/maestro-admin, point them at your database and get a
full governed admin (list/CRUD/RBAC/audit + a metadata-driven UI) with no
per-entity code.
import { createCassandraProvider } from '@maykonpaulo/maestro-provider-cassandra';
import { createMaestroServer, createIntrospectedEngine } from '@maykonpaulo/maestro-server';
const provider = createCassandraProvider({ contactPoints: ['127.0.0.1'], localDataCenter: 'datacenter1', keyspace: 'app' });
const engine = await createIntrospectedEngine({ provider, access: 'full' });
await createMaestroServer({ engine }).listen(3000);See the Turnkey admin guide.
