Skip to content

AxionCompany/ominipg

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

51 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Ominipg Logo

Ominipg

The flexible, all-in-one toolkit for PostgreSQL in Deno and Node.js

JSR License: MIT

Ominipg is a flexible PostgreSQL toolkit for Deno and Node.js that combines the power of PGlite (PostgreSQL in WASM) with a modern, developer-friendly API. Build local-first applications, use powerful CRUD operations with MongoDB-style filters, or integrate with your favorite ORMβ€”all with full TypeScript type safety.


✨ Features

  • πŸ¦• Deno Native, Node Ready: Deno-first source with npm output for Node.js 22+
  • πŸš€ Multiple Modes: In-memory, persistent, or direct PostgreSQL connections
  • πŸ”„ Local-First Sync: Automatic synchronization between local and remote databases
  • πŸ“ Powerful CRUD API: MongoDB-style filters with full type inference
  • 🎯 ORM Integration: Works seamlessly with Drizzle ORM
  • πŸ”Œ Standalone or Integrated: Use CRUD module with any PostgreSQL database library
  • ⚑ Worker Isolation: Run database operations in a Web Worker
  • πŸ”§ PostgreSQL Extensions: Support for uuid_ossp, vector, and more
  • πŸ“˜ TypeScript First: Complete type safety and inference
  • πŸͺΆ Lightweight Core: PGlite and PostgreSQL drivers are optional providers

πŸ“¦ Installation

Deno

The built-in Deno providers load compatible npm engine versions lazily. No engine import-map entries are required for the default providers.

// Full library
import { Ominipg } from "jsr:@oxian/ominipg";
import { autoConfigure } from "jsr:@oxian/ominipg/auto";
import { createPgProvider } from "jsr:@oxian/ominipg/pg";
import { createPGliteProvider } from "jsr:@oxian/ominipg/pglite";

// CRUD module only (use with any database library)
import { createCrudApi, defineSchema } from "jsr:@oxian/ominipg/crud";

Node.js

Ominipg publishes an ESM-only npm package for Node.js 22+.

npm install @oxian/ominipg
// Full library
import { Ominipg } from "@oxian/ominipg";
import { autoConfigure } from "@oxian/ominipg/auto";
import { createPgProvider } from "@oxian/ominipg/pg";
import { createPGliteProvider } from "@oxian/ominipg/pglite";

// CRUD module only (use with any database library)
import { createCrudApi, defineSchema } from "@oxian/ominipg/crud";

PGlite and node-postgres are optional peer dependencies. Install only the engines you use:

npm install @electric-sql/pglite
npm install pg pg-logical-replication

πŸš€ Quick Start

Auto-Configured Providers

Use autoConfigure() when your app already has url and optional syncUrl strings and you want Ominipg to inject the right optional providers.

import { Ominipg } from "jsr:@oxian/ominipg";
import { autoConfigure } from "jsr:@oxian/ominipg/auto";

const db = await Ominipg.connect(autoConfigure({
  url: dbUrl, // ":memory:", "file://...", or "postgresql://..."
  syncUrl: dbSyncUrl, // optional PostgreSQL sync target
}));

In-Memory Database with Raw SQL

import { Ominipg } from "jsr:@oxian/ominipg";
import { autoConfigure } from "jsr:@oxian/ominipg/auto";

// Create an in-memory database
const db = await Ominipg.connect(autoConfigure({
  url: ":memory:",
  schemaSQL: [`
    CREATE TABLE users (
      id SERIAL PRIMARY KEY,
      name TEXT NOT NULL,
      email TEXT UNIQUE
    )
  `],
}));

// Execute queries
await db.query("INSERT INTO users (name, email) VALUES ($1, $2)", [
  "Alice",
  "alice@example.com",
]);

const result = await db.query("SELECT * FROM users");
console.log(result.rows);

await db.close();

CRUD API with Type Safety

import { defineSchema, Ominipg } from "jsr:@oxian/ominipg";
import { createPGliteProvider } from "jsr:@oxian/ominipg/pglite";

// Define schema with full type inference
const schemas = defineSchema({
  users: {
    schema: {
      type: "object",
      properties: {
        id: { type: "string" },
        name: { type: "string" },
        email: { type: "string" },
        age: { type: "number" },
      },
      required: ["id", "name", "email"],
    },
    keys: [{ property: "id" }],
    timestamps: true, // Automatic createdAt/updatedAt
  },
});

const db = await Ominipg.connect({
  url: ":memory:",
  pgliteProvider: createPGliteProvider(),
  schemas,
});

// Type-safe CRUD operations
const user = await db.crud.users.create({
  id: "1",
  name: "Alice",
  email: "alice@example.com",
  age: 30,
});

// MongoDB-style filters
const adults = await db.crud.users.find({
  age: { $gte: 18 },
  email: { $like: "%@example.com" },
});

// Pagination and sorting
const page1 = await db.crud.users.find(
  {},
  { limit: 10, skip: 0, sort: { createdAt: "desc" } },
);

Local-First with Sync

const db = await Ominipg.connect({
  url: ":memory:", // Local database
  syncUrl: "postgresql://user:pass@host:5432/db", // Remote sync
  pgliteProvider: createPGliteProvider(),
  pgProvider: createPgProvider(),
  schemaSQL: [`CREATE TABLE users (...)`],
});

// Work locally (instant, no network)
await db.query("INSERT INTO users ...");
await db.query("UPDATE users ...");

// Sync to remote when ready
const result = await db.sync();
console.log(`Pushed ${result.pushed} changes to remote`);

Drizzle ORM Integration

import { Ominipg, withDrizzle } from "jsr:@oxian/ominipg";
import { createPGliteProvider } from "jsr:@oxian/ominipg/pglite";
import { drizzle } from "npm:drizzle-orm/pg-proxy";
import { pgTable, serial, text } from "npm:drizzle-orm/pg-core";
import { eq } from "npm:drizzle-orm";

const users = pgTable("users", {
  id: serial("id").primaryKey(),
  name: text("name").notNull(),
});

const ominipg = await Ominipg.connect({
  url: ":memory:",
  pgliteProvider: createPGliteProvider(),
});
const db = await withDrizzle(ominipg, drizzle, { users });

// Use Drizzle's API
await db.insert(users).values({ name: "Alice" });
const allUsers = await db.select().from(users);

🎯 Use Cases

1. Local-First Applications

Build offline-capable Deno or Node.js applications with persistent storage that sync when connected:

const db = await Ominipg.connect({
  url: "file://./data/app.db", // Persistent local storage
  syncUrl: Deno.env.get("REMOTE_DB_URL"), // or process.env.REMOTE_DB_URL in Node.js
  pgliteProvider: createPGliteProvider(),
  pgProvider: createPgProvider(),
});

// App works offline
await db.crud.todos.create({ title: "Buy milk", done: false });

// Sync when online
db.on("sync:end", (result) => {
  console.log(`Synced ${result.pushed} changes`);
});
await db.sync();

2. Rapid Prototyping with Type Safety

Get a full CRUD API with validation in seconds:

const schemas = defineSchema({
  posts: {
    schema: {
      type: "object",
      properties: {
        id: { type: "string" },
        title: { type: "string" },
        content: { type: "string" },
        authorId: { type: "string" },
      },
      required: ["id", "title", "authorId"],
    },
    keys: [{ property: "id" }],
    timestamps: true,
  },
});

const db = await Ominipg.connect({
  url: ":memory:",
  pgliteProvider: createPGliteProvider(),
  schemas,
});

// Fully typed CRUD operations ready to use
await db.crud.posts.create({ ... });
const posts = await db.crud.posts.find({ authorId: "123" });

3. Testing with In-Memory Database

Perfect for unit tests with instant setup/teardown:

Deno.test("user registration", async () => {
  const db = await Ominipg.connect({
    url: ":memory:",
    pgliteProvider: createPGliteProvider(),
    schemas: userSchemas,
  });

  const user = await db.crud.users.create({
    id: "1",
    email: "test@example.com",
  });

  assertEquals(user.email, "test@example.com");

  await db.close(); // Clean up
});

4. Standalone CRUD with Existing Database

Use the CRUD module with any database library:

import { defineSchema, createCrudApi } from "jsr:@oxian/ominipg/crud";
import postgres from "npm:postgres";

const sql = postgres(DATABASE_URL);

// Create query adapter
async function queryFn(sql: string, params?: unknown[]) {
  const result = await sql.unsafe(sql, params);
  return { rows: result };
}

// Get type-safe CRUD API
const schemas = defineSchema({ users: { ... } });
const crud = createCrudApi(schemas, queryFn);

// Use with your existing database
const users = await crud.users.find({ age: { $gte: 18 } });

πŸ“š Core Concepts

Connection Modes

Mode URL Use Case
In-Memory :memory: Testing, prototyping, temporary data
Persistent file://./data.db Local storage, offline-first apps
Direct PostgreSQL postgresql://... Direct connection to PostgreSQL server
Worker Mode Any + useWorker: true Isolate DB operations in a Deno Web Worker or Node worker_threads worker

CRUD API Filters

Ominipg supports MongoDB-style query operators:

// Comparison operators
{ age: 25 }                      // Equals
{ age: { $ne: 25 } }            // Not equals
{ age: { $gt: 18, $lt: 65 } }   // Greater than, less than
{ age: { $gte: 18 } }           // Greater than or equal
{ age: { $lte: 65 } }           // Less than or equal

// Array operators
{ status: { $in: ["active", "pending"] } }
{ status: { $nin: ["deleted"] } }

// String operators
{ name: { $like: "A%" } }        // Starts with A
{ email: { $ilike: "%gmail%" } }  // Contains gmail (case-insensitive)

// Null checks
{ deletedAt: null }              // IS NULL
{ deletedAt: { $ne: null } }     // IS NOT NULL

// Logical operators
{ $and: [{ age: { $gte: 18 } }, { verified: true }] }
{ $or: [{ role: "admin" }, { role: "moderator" }] }
{ $not: { status: "banned" } }

Type Inference

Schemas automatically infer TypeScript types:

const schemas = defineSchema({
  users: {
    schema: {/* ... */},
    keys: [{ property: "id" }],
  },
});

// Automatic type inference - no imports needed!
type User = typeof schemas.users.$inferSelect;
type NewUser = typeof schemas.users.$inferInsert;

// Use with functions
async function getUser(id: string): Promise<User> {
  return await db.crud.users.findOne({ id });
}

πŸ”§ Configuration Options

await Ominipg.connect({
  // Database connection
  url: ":memory:",                           // Required
  syncUrl: "postgresql://...",               // Optional remote sync
  pgliteProvider: createPGliteProvider(),    // Required for PGlite URLs
  pgProvider: createPgProvider(),            // Required for PostgreSQL/sync

  // Schema and initialization
  schemas: defineSchema({ ... }),            // CRUD schemas
  schemaSQL: ["CREATE TABLE ..."],           // DDL statements

  // PGlite extensions
  pgliteExtensions: ["uuid_ossp", "vector"], // Extensions to load
  pgliteConfig: {
    initialMemory: 256 * 1024 * 1024,        // WASM memory limit
  },

  // Execution mode
  useWorker: false,                          // PGlite in-process (default without sync)
  // useWorker: true,                        // Worker / worker_threads
});

🎨 API Overview

Core Database API

// Execute raw SQL
const result = await db.query(sql, params);

// Sync with remote
const syncResult = await db.sync();
await db.syncSequences();

// Events
db.on("connected", () => console.log("Connected"));
db.on("sync:end", (result) => console.log("Synced"));
db.on("error", (error) => console.error(error));

// Diagnostic info
const info = await db.getDiagnosticInfo();

// Cleanup
await db.close();

CRUD API

// Create operations
await db.crud.users.create(data);
await db.crud.users.createMany([data1, data2]);

// Read operations
await db.crud.users.find(filter, options);
await db.crud.users.findOne(filter);

// Update operations
await db.crud.users.update(filter, updates);
await db.crud.users.update(filter, data, { upsert: true });

// Delete operations
await db.crud.users.delete(filter);

πŸ“– Documentation

Explore detailed guides and examples:

Examples

Check out the /examples directory for complete, runnable examples:


πŸ› οΈ Development

Prerequisites

  • Deno 2.x or higher
  • Node.js 22.x or higher (for npm package verification)
  • PostgreSQL (optional, for testing remote features)

Running Tests

# Run all tests
deno task test:deno

# Run specific test
deno test --allow-all --config deno.test.json test/crud.test.ts

# With watch mode
deno test --allow-all --config deno.test.json --watch

Running Examples

deno run --allow-all --config deno.test.json examples/quick-start.ts
deno run --allow-all --config deno.test.json examples/with-drizzle-simple.ts

npm Build

The npm package is generated with dnt. No extra bundler is required; the Node worker is emitted as transformed ESM files inside the package.

deno task build:npm
deno task test:npm-node

The generated package is written to ./npm and exposes:

import { Ominipg } from "@oxian/ominipg";
import { createCrudApi, defineSchema } from "@oxian/ominipg/crud";
import { createPgProvider } from "@oxian/ominipg/pg";
import { createPGliteProvider } from "@oxian/ominipg/pglite";

πŸ—ΊοΈ Roadmap

We're actively working on expanding Ominipg. See ROADMAP.md for details:

  • 🌐 More Runtime Targets - Bun and Browser compatibility
  • πŸ”„ Bi-directional Sync - Two-way synchronization with conflict resolution
  • πŸ—„οΈ Pluggable Storage - SQLite and other backend support
  • πŸ”€ Column Aliases - Map snake_case columns to camelCase in TypeScript

🀝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Areas we'd love help with:

  • πŸ› Bug fixes and edge case handling
  • πŸ“š Documentation improvements
  • βœ… Test coverage expansion
  • πŸš€ Performance optimizations
  • 🎨 Real-world examples

πŸ“„ License

MIT License - see LICENSE for details.


πŸ™ Acknowledgments

Ominipg is built on the shoulders of giants:

  • PGlite - PostgreSQL in WASM
  • pg - PostgreSQL client for Node.js
  • Drizzle ORM - TypeScript ORM integration
  • Zod - Schema validation

πŸ“ž Support


Made with ❀️ by the Ominipg Team

⭐ Star us on GitHub | πŸ“¦ View on JSR

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors