Skip to content

developwithsciencify/watermelondb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

watermelondb

watermelondb is a lightweight in-memory data SDK for Node.js and browser-adjacent runtimes. It is aimed at developers who want a structured local data layer with schema validation, transactional writes, and reactive events without bringing in a full database service.

This package is intentionally organized like an SDK rather than a demo:

  • schema parsing lives in dedicated modules
  • collections and transactions are reusable components
  • change events can be consumed by higher-level application code
  • dependencies are chosen to make the package practical in real projects

What developers get

  • zod-validated schemas
  • eventemitter3-based change subscriptions
  • nanoid-based record IDs
  • transactional write() and grouped batch() operations
  • reusable collection helpers such as upsert, findMany, first, and exists

Installation

npm install watermelondb

Package structure

watermelondb/
├── index.js
├── src/
│   ├── collection.js
│   ├── database.js
│   ├── index.js
│   ├── schema.js
│   └── utils.js
└── test.js

Good use cases

  • internal tools
  • local-first prototypes
  • test fixtures and labs
  • sync staging layers
  • small embedded stores inside larger SDKs

Quick start

const { Database, appSchema, tableSchema } = require('watermelondb');

const schema = appSchema({
  version: 1,
  tables: [
    tableSchema({
      name: 'posts',
      columns: [
        { name: 'title', type: 'string' },
        { name: 'published', type: 'boolean', default: false },
        { name: 'tags', type: 'array', default: () => [] },
      ],
    }),
    tableSchema({
      name: 'comments',
      columns: [
        { name: 'postId', type: 'string', isIndexed: true },
        { name: 'body', type: 'string' },
      ],
    }),
  ],
});

const db = new Database({ schema });

await db.write(async () => {
  const posts = db.collection('posts');
  const comments = db.collection('comments');

  const post = posts.create({
    title: 'Hello world',
    tags: ['intro'],
  });

  comments.create({
    postId: post.id,
    body: 'Great post',
  });
});

const publishedPosts = await db.read(() =>
  db.collection('posts').query({ published: true })
);

console.log(publishedPosts);

Reactive subscriptions

const unsubscribe = db.collection('posts').subscribe((event) => {
  console.log(event.type, event.record);
});

await db.write(async () => {
  db.collection('posts').create({ title: 'Realtime row' });
});

unsubscribe();

Transaction and batch behavior

Writes roll back automatically when the callback throws:

await db.write(async () => {
  db.collection('posts').create({ title: 'Temporary row' });
  throw new Error('rollback');
});

Batch operations help group related changes:

await db.batch([
  () => db.collection('posts').create({ title: 'One' }),
  () => db.collection('posts').create({ title: 'Two' }),
  () => db.collection('posts').upsert('posts_custom', { title: 'Pinned' }),
]);

Collection workflow example

const posts = db.collection('posts');

const created = posts.create({ title: 'New post' });
const updated = posts.update(created.id, { published: true });
const same = posts.find(created.id);
const many = posts.findMany([created.id]);
const firstPublished = posts.first({ published: true });
const exists = posts.exists((row) => row.title.startsWith('New'));
const total = posts.count();
const allPosts = posts.all();
const exported = posts.toJSON();

API reference

appSchema({ version, tables })

Creates and validates the database schema.

tableSchema({ name, columns })

Creates and validates a table definition.

Supported column types:

  • string
  • number
  • boolean
  • object
  • array
  • date
  • any

Column fields:

Field Description
name Column name
type Column type
isIndexed Metadata flag for higher-level tooling
default Static value or function returning a default value

new Database({ schema })

Main methods:

  • collection(name)
  • read(callback)
  • write(callback)
  • batch(operations)
  • export()

Collection

Methods:

  • create(fields)
  • upsert(id, fields)
  • find(id)
  • findMany(ids)
  • all()
  • first(predicateOrCriteria?)
  • exists(predicateOrCriteria?)
  • query(predicateOrCriteria?)
  • update(id, fields)
  • delete(id)
  • count(predicateOrCriteria?)
  • clear()
  • toJSON()
  • subscribe(listener)

predicateOrCriteria can be:

  • a predicate function such as (row) => row.published
  • a plain object such as { published: true }

Integration example

This package works well behind a higher-level project SDK:

class ProjectStore {
  constructor(db) {
    this.db = db;
  }

  saveProject(project) {
    return this.db.write(() =>
      this.db.collection('projects').upsert(project.id, project)
    );
  }

  listProjects() {
    return this.db.read(() => this.db.collection('projects').all());
  }
}

License

This package is licensed under the MIT License. See LICENSE.

About

lightweight in-memory data SDK for Node.js and browser-adjacent runtimes

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors