npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ragestudio/scylla-odm

v0.21.0

Published

An ODM for ScyllaDB/Cassandra

Downloads

3,523

Readme

@ragestudio/scylla-odm

A lightweight ODM for ScyllaDB and Cassandra.

Warning: under active development, not production-ready.


why this exists

Most of (not existent) Node.js ODMs for ScyllaDB/Cassandra rely on the official cassandra-driver.

The official cassandra-driver ships a built-in mapper, but it has no TypeScript support or a friendly interface. You define your columns with plain strings and get plain objects back — no autocomplete, no type checking, no safety net.

This ODM is built on top of a modified cassandra-driver and adds:

  • Type-safe schemas — your column types are inferred, so find, create, and save all know the shape of your data
  • ODM Methods — easier & friendly API for interacting with your data
  • Full TypeScript support — autocomplete, type checking, and inference from schema to model to document
  • MongoDB-style query operators$gt, $in, $lte, etc., all typed

We also stripped out everything you probably never use (DataStax Insights, metrics, heavy dependencies, and other services) and applied a bunch of performance patches on top of the driver itself.

The result is a leaner driver with less overhead, fewer timers, and better memory usage.


install

npm install @ragestudio/scylla-odm

quick start

import Client, { Schema, Model, ColumnTypes } from "@ragestudio/scylla-odm";
import type { Column } from "@ragestudio/scylla-odm/types";

// 1. define a schema
const userSchema = new Schema(
  {
    table_name: "users",
    keys: ["id"], // partition key and clustering keys
  },
  {
    id: { type: ColumnTypes.Int, required: true } as Column<number>,
    name: { type: ColumnTypes.Text, required: true } as Column<string>,
    email: { type: ColumnTypes.Text, required: true } as Column<string>,
    age: { type: ColumnTypes.Int } as Column<number>,
  },
);

// 2. create a model
const User = new Model("User", userSchema);

// 3. create a client
const client = new Client({
  contactPoints: ["127.0.0.1"],
  localDataCenter: "datacenter1",
  keyspace: "myapp",
});

// 4. initialize and connect
await client.initialize();

// 4. create and save documents
const user = User.create({
  id: 1234,
  name: "Alice",
  email: "[email protected]",
  age: 30,
});

await user.save();

// 5. query
const found = await User.findOne({ id: 1234 });
console.log(found?.name); // "Alice"

// 6. shutdown
await client.shutdown();

schema

A schema describes a table: its name, primary keys, and columns.

const productSchema = new Schema(
  {
    table_name: "products",
    keys: [["category"], "id"], // compound partition key
    clustering_order: { created_at: "desc" }, // optional
  },
  {
    category: { type: ColumnTypes.Text, required: true } as Column<string>,
    id: { type: ColumnTypes.Uuid, required: true } as Column<string>,
    title: { type: ColumnTypes.Text, required: true } as Column<string>,
    price: { type: ColumnTypes.Double, required: true } as Column<number>,
    created_at: { type: ColumnTypes.Timestamp } as Column<Date>,
  },
);

model

A model wraps a schema and provides the query interface.

const Product = new Model("Product", productSchema);

methods

| method | description | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | create(data) / obj() | create a new document (not persisted yet) | | find(query, options?) | find documents matching the query, returns an array of documents | | findOne(query, options?) | find a single document, if no document is found, returns null. Due the mapper limitation, note that all partition and clustering keys must be defined in order to use this method. | | | | update(query) | update documents matching the query | | delete(query) | delete documents matching the query | | countAll() | count all documents in the table |


document

Documents are the objects you work with. They carry the data and a few helpers.

const product = Product.create({
  category: "books",
  id: uuid(),
  title: "ODM 101",
  price: 29.99,
});

await product.save(); // persist to ScyllaDB
await product.delete(); // delete from ScyllaDB
product.toRaw(); // plain object without internal fields
product.getChangedFields(original); // diff between current and original data

query operators

Use MongoDB-style operators in your queries:

// exact match
await User.find({ name: "Alice" });

// comparison operators
await Product.find({ price: { $gt: 10, $lte: 50 } });

// list matching
await User.find({ age: { $in: [25, 30, 35] } });

// sorting
await Product.find({ category: "books" }, { $orderby: { created_at: "desc" } });

// raw results (skip document wrapping)
const raw = await Product.find({ category: "books" }, { raw: true });

configuration

const client = new Client({
  modelsPath: "./db",
  contactPoints: ["127.0.0.1"],
  localDataCenter: "datacenter1",
  keyspace: "myapp",
  port: 9042,
  maxRetries: 3,
  retryDelay: 1000,
  pooling: {
    coreConnectionsPerHost: {
      local: 2,
    },
    maxRequestsPerConnection: 1024,
  },
});

You can also configure via environment variables:

| variable | default | | -------------------------- | ------------------ | | SCYLLA_CONTACT_POINTS | 127.0.0.1 | | SCYLLA_LOCAL_DATA_CENTER | datacenter1 | | SCYLLA_KEYSPACE | default_keyspace |


about the driver

This package ships a modified version of the cassandra-driver


license

This project is licensed under the MIT license.

The bundled cassandra-driver is licensed under the Apache License, Version 2.0.

Apache Cassandra NodeJS Driver
Copyright 2013 The Apache Software Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

See src/driver/LICENSE.txt and src/driver/NOTICE.txt for the full legal text.