Examples

This document provides examples of how to use NebulaDB in different scenarios.

Basic CRUD Operations

import { createDb } from '@nebula/core';
import { MemoryAdapter } from '@nebula/adapter-memory';

// Create a database
const db = createDb({ adapter: new MemoryAdapter() });
const users = db.collection('users');

// Create (Insert)
const alice = await users.insert({
  name: 'Alice',
  age: 30,
  email: 'alice@example.com'
});
console.log('Inserted user:', alice);

// Read (Find)
const allUsers = await users.find();
console.log('All users:', allUsers);

const user = await users.findOne({ name: 'Alice' });
console.log('Found user:', user);

// Update
await users.update(
  { id: alice.id },
  { $set: { age: 31 } }
);
const updatedUser = await users.findOne({ id: alice.id });
console.log('Updated user:', updatedUser);

// Delete
await users.delete({ id: alice.id });
const remainingUsers = await users.find();
console.log('Remaining users:', remainingUsers);

Todo List Application

import { createDb } from '@nebula/core';
import { LocalStorageAdapter } from '@nebula/adapter-localstorage';

const db = createDb({ adapter: new LocalStorageAdapter('todo-app') });
const todos = db.collection('todos');

async function addTodo(title) {
  return await todos.insert({
    title,
    completed: false,
    createdAt: new Date().toISOString()
  });
}

async function toggleTodo(id) {
  const todo = await todos.findOne({ id });
  if (todo) {
    await todos.update(
      { id },
      { $set: { completed: !todo.completed } }
    );
  }
}

async function deleteTodo(id) {
  await todos.delete({ id });
}

async function getAllTodos() { return await todos.find(); }
async function getActiveTodos() { return await todos.find({ completed: false }); }
async function getCompletedTodos() { return await todos.find({ completed: true }); }

async function clearCompletedTodos() {
  await todos.delete({ completed: true });
}

// Example usage
async function run() {
  await addTodo('Learn NebulaDB');
  await addTodo('Build a todo app');
  await addTodo('Write documentation');
  console.log('All todos:', await getAllTodos());
  const firstTodo = (await getAllTodos())[0];
  await toggleTodo(firstTodo.id);
  console.log('Active todos:', await getActiveTodos());
  console.log('Completed todos:', await getCompletedTodos());
  await clearCompletedTodos();
  console.log('Remaining todos:', await getAllTodos());
}
run();

Blog Application

import { createDb } from '@nebula/core';
import { FileSystemAdapter } from '@nebula/adapter-filesystem';
import path from 'path';

const db = createDb({
  adapter: new FileSystemAdapter(path.join(__dirname, 'blog-data.json'))
});

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

async function createUser(userData) {
  return await users.insert({ ...userData, createdAt: new Date().toISOString() });
}
async function getUserById(id) { return await users.findOne({ id }); }

async function createPost(userId, postData) {
  return await posts.insert({
    ...postData, userId,
    createdAt: new Date().toISOString(),
    updatedAt: new Date().toISOString()
  });
}
async function getPostsByUser(userId) { return await posts.find({ userId }); }
async function getAllPosts() { return await posts.find(); }

async function createComment(userId, postId, content) {
  return await comments.insert({
    userId, postId, content,
    createdAt: new Date().toISOString()
  });
}
async function getCommentsByPost(postId) { return await comments.find({ postId }); }

async function getPostWithDetails(id) {
  const post = await posts.findOne({ id });
  if (!post) return null;
  const author = await getUserById(post.userId);
  const postComments = await getCommentsByPost(id);
  const commentUserIds = [...new Set(postComments.map(c => c.userId))];
  const commentAuthors = await Promise.all(commentUserIds.map(id => getUserById(id)));
  const userMap = commentAuthors.reduce((map, user) => { map[user.id] = user; return map; }, {});
  const commentsWithAuthors = postComments.map(comment => ({
    ...comment, author: userMap[comment.userId]
  }));
  return { ...post, author, comments: commentsWithAuthors };
}

async function run() {
  const alice = await createUser({ username: 'alice', email: 'alice@example.com', name: 'Alice Johnson' });
  const bob = await createUser({ username: 'bob', email: 'bob@example.com', name: 'Bob Smith' });
  const post1 = await createPost(alice.id, { title: 'Introduction to NebulaDB', content: 'NebulaDB is a flexible embedded database...' });
  const post2 = await createPost(bob.id, { title: 'Building Apps with NebulaDB', content: 'In this tutorial, we will build a simple app...' });
  await createComment(bob.id, post1.id, 'Great introduction!');
  await createComment(alice.id, post2.id, 'Nice tutorial, very helpful.');
  const postWithDetails = await getPostWithDetails(post1.id);
  console.log(JSON.stringify(postWithDetails, null, 2));
  await db.save();
}
run();

Real-time Chat Application

import { createDb } from '@nebula/core';
import { MemoryAdapter } from '@nebula/adapter-memory';

const db = createDb({ adapter: new MemoryAdapter() });
const users = db.collection('users');
const rooms = db.collection('rooms');
const messages = db.collection('messages');

async function createUser(username) {
  return await users.insert({ username, online: true, lastSeen: new Date().toISOString() });
}
async function setUserStatus(userId, online) {
  await users.update({ id: userId }, { $set: { online, lastSeen: new Date().toISOString() } });
}

async function createRoom(name, createdBy) {
  return await rooms.insert({ name, createdBy, createdAt: new Date().toISOString(), participants: [createdBy] });
}
async function joinRoom(roomId, userId) {
  const room = await rooms.findOne({ id: roomId });
  if (!room) throw new Error('Room not found');
  if (!room.participants.includes(userId)) {
    await rooms.update({ id: roomId }, { $push: { participants: userId } });
  }
}

async function sendMessage(roomId, userId, content) {
  return await messages.insert({ roomId, userId, content, timestamp: new Date().toISOString(), read: [userId] });
}
async function getRoomMessages(roomId) { return await messages.find({ roomId }); }

function subscribeToRoomMessages(roomId, callback) {
  return messages.subscribe({ roomId }, (roomMessages) => {
    const sortedMessages = [...roomMessages].sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));
    callback(sortedMessages);
  });
}

async function run() {
  const alice = await createUser('alice');
  const bob = await createUser('bob');
  const room = await createRoom('General', alice.id);
  await joinRoom(room.id, bob.id);
  const unsubscribe = subscribeToRoomMessages(room.id, (messages) => {
    console.log('New messages:', messages);
  });
  await sendMessage(room.id, alice.id, 'Hello, Bob!');
  await sendMessage(room.id, bob.id, 'Hi Alice, how are you?');
  await sendMessage(room.id, alice.id, "I'm doing well, thanks!");
  await setUserStatus(bob.id, false);
  unsubscribe();
}
run();

E-commerce Inventory Management

import { createDb } from '@nebula/core';
import { FileSystemAdapter } from '@nebula/adapter-filesystem';
import path from 'path';

const db = createDb({ adapter: new FileSystemAdapter(path.join(__dirname, 'inventory-data.json')) });
const products = db.collection('products');
const categories = db.collection('categories');
const inventory = db.collection('inventory');
const orders = db.collection('orders');

async function createProduct(productData) {
  return await products.insert({ ...productData, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() });
}
async function getProductById(id) { return await products.findOne({ id }); }
async function getProductsByCategory(categoryId) { return await products.find({ categoryId }); }

async function createCategory(name) {
  return await categories.insert({ name, createdAt: new Date().toISOString() });
}

async function updateInventory(productId, quantity, location = 'main') {
  const item = await inventory.findOne({ productId, location });
  if (item) {
    await inventory.update({ id: item.id }, { $set: { quantity, updatedAt: new Date().toISOString() } });
    return await inventory.findOne({ id: item.id });
  } else {
    return await inventory.insert({ productId, location, quantity, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() });
  }
}
async function checkAvailability(productId, quantity, location = 'main') {
  const item = await inventory.findOne({ productId, location });
  return item && item.quantity >= quantity;
}

async function createOrder(orderData) {
  for (const item of orderData.items) {
    const available = await checkAvailability(item.productId, item.quantity);
    if (!available) throw new Error(`Product ${item.productId} is not available`);
  }
  const order = await orders.insert({ ...orderData, status: 'pending', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() });
  for (const item of orderData.items) {
    const inventoryItem = await inventory.findOne({ productId: item.productId });
    await updateInventory(item.productId, inventoryItem.quantity - item.quantity);
  }
  return order;
}
async function updateOrderStatus(id, status) {
  await orders.update({ id }, { $set: { status, updatedAt: new Date().toISOString() } });
  return await orders.findOne({ id });
}

async function run() {
  const electronics = await createCategory('Electronics');
  const clothing = await createCategory('Clothing');
  const laptop = await createProduct({ name: 'Laptop Pro', description: 'Powerful laptop for professionals', price: 1299.99, categoryId: electronics.id, sku: 'LP-2023-001' });
  const tshirt = await createProduct({ name: 'Cotton T-Shirt', description: 'Comfortable cotton t-shirt', price: 19.99, categoryId: clothing.id, sku: 'TS-2023-001' });
  await updateInventory(laptop.id, 10);
  await updateInventory(tshirt.id, 100);
  const order = await createOrder({
    customer: { name: 'John Doe', email: 'john@example.com', address: '123 Main St' },
    items: [
      { productId: laptop.id, quantity: 1, price: laptop.price },
      { productId: tshirt.id, quantity: 2, price: tshirt.price }
    ],
    total: laptop.price + (tshirt.price * 2)
  });
  console.log('Order created:', order);
  await updateOrderStatus(order.id, 'shipped');
  const shippedOrders = await orders.find({ status: 'shipped' });
  console.log('Shipped orders:', shippedOrders);
  await db.save();
}
run();