{"id":16602,"library":"camadb","title":"CamaDB: TypeScript Embedded NoSQL Database","description":"CamaDB is an embedded NoSQL database written in pure TypeScript, supporting Node.js, Electron, and browser environments. Its current stable version is 2.0.0 (January 2023), and it is under active development. CamaDB provides a MongoDB-style API for querying (SiftJS), updating (Obop), and aggregation (Mingo, with some limitations), offering full TypeScript support. It differentiates itself by providing frictionless integration across runtimes, handling native JavaScript data types, and aiming for fast performance on datasets up to 1 million rows, bypassing common issues with native database bindings in environments like Electron.","status":"active","version":"2.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/elmarti/camadb","tags":["javascript","camadb","typescript","embedded database"],"install":[{"cmd":"npm install camadb","lang":"bash","label":"npm"},{"cmd":"yarn add camadb","lang":"bash","label":"yarn"},{"cmd":"pnpm add camadb","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for decorator-based type reflection, especially for column type definition and proper type inference at runtime. Must be imported once, typically at the application entry point.","package":"reflect-metadata","optional":false}],"imports":[{"note":"CamaDB is primarily an ESM-first library. While CommonJS might work with transpilation, direct require() is not the recommended approach. TypeScript types are included.","wrong":"const { Cama } = require('camadb');","symbol":"Cama","correct":"import { Cama } from 'camadb';"},{"note":"When importing only a type, it's best practice in modern TypeScript to use 'import type' to ensure it's removed during compilation and avoids potential runtime issues.","wrong":"import { CamaConfig } from 'camadb';","symbol":"CamaConfig","correct":"import type { CamaConfig } from 'camadb';"},{"note":"The `Collection` class is not directly exported for import. Instead, instances of `Collection` are created and returned by the `Cama` database instance's `initCollection` method.","wrong":"import { Collection } from 'camadb';","symbol":"Collection","correct":"const collection = await database.initCollection(...);"}],"quickstart":{"code":"import { Cama } from 'camadb';\n// Ensure reflect-metadata is imported if decorators are used, often at the top level\n// import 'reflect-metadata'; \n\ninterface User { \n  _id: string;\n  name: string;\n  email: string;\n  registrationDate: Date;\n  preferences: { \n    theme: string;\n    notifications: boolean;\n  };\n}\n\nasync function setupCamaDB() {\n  // Initialize the database instance with filesystem persistence\n  const database = new Cama({\n    path: './.cama-data',\n    persistenceAdapter: 'fs', // Use 'indexeddb' or 'localstorage' for browser environments\n    logLevel: 'info' // Can be 'debug' for more verbose logging\n  });\n\n  // Initialize a collection named 'users' with a specific date column for proper type handling\n  const usersCollection = await database.initCollection<User>('users', {\n    columns: [{\n      type: 'date',\n      title: 'registrationDate' // Essential for CamaDB to correctly store and retrieve Date objects\n    }],\n    indexes: [], // Indexes are not yet implemented but are part of the configuration API\n  });\n\n  // Insert a new user document into the collection\n  const newUser: User = {\n    _id: 'user_001',\n    name: 'Alice Wonderland',\n    email: 'alice@example.com',\n    registrationDate: new Date(),\n    preferences: {\n      theme: 'dark',\n      notifications: true\n    }\n  };\n  await usersCollection.insertOne(newUser);\n\n  console.log('User inserted successfully:', newUser._id);\n\n  // Example of finding a user by _id\n  const foundUser = await usersCollection.findMany({ _id: 'user_001' });\n  console.log('Found user:', foundUser);\n\n  // Example of updating a user's preferences\n  await usersCollection.updateMany({\n    _id: 'user_001'\n  }, {\n    $set: {\n      'preferences.theme': 'light'\n    }\n  });\n  console.log('User preferences updated.');\n}\n\nsetupCamaDB().catch(console.error);","lang":"typescript","description":"Demonstrates initializing a CamaDB instance and a collection with a type interface, then inserting a document, and performing basic find and update operations."},"warnings":[{"fix":"Review any custom logic interacting with CamaDB's internal operation queues or persistence layer if upgrading from versions prior to 2.0.0. Ensure compatibility with the new centralized system.","message":"Version 2.0.0 introduced a breaking change by centralizing the internal queuing system. This may affect applications that interacted directly with previous internal queue mechanisms or custom persistence adapters.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Optimize queries by using precise filters to reduce the dataset size that needs to be scanned. For critical performance, consider implementing application-level caching or pre-processing data.","message":"Indexes are not yet implemented, which may impact query performance on very large datasets, especially without highly selective filters. The library states it is fast even without them, but complex queries might suffer.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Integrate a third-party full-text search library (e.g., FlexSearch, Lunr.js) or develop a custom keyword-matching solution for your data.","message":"Rich text search functionality is currently missing. For full-text search capabilities, an external library or custom implementation is required.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Refactor complex aggregation queries that would typically use '$lookup' into multiple `find` operations, then join and process the results within your application code.","message":"The Mingo-powered aggregation engine in CamaDB does not support all MongoDB aggregation commands, specifically 'lookup' commands are not available.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure `import \"reflect-metadata\";` is present at the very top of your application's entry file. Additionally, `emitDecoratorMetadata` and `experimentalDecorators` must be set to `true` in your `tsconfig.json`.","message":"CamaDB uses `reflect-metadata` for type reflection. If not configured correctly (e.g., missing import, `tsconfig.json` settings), this can lead to runtime errors, particularly with features relying on decorator metadata.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Add `import \"reflect-metadata\";` at the top of your main application entry file. Also, ensure `emitDecoratorMetadata` and `experimentalDecorators` are `true` in your `tsconfig.json`.","cause":"The `reflect-metadata` polyfill was not imported or configured correctly, which CamaDB relies on for TypeScript type reflection.","error":"ReferenceError: Reflect is not defined"},{"fix":"Configure the `persistenceAdapter` option during `Cama` initialization to match your target environment: use `'fs'` for Node.js/Electron, and `'indexeddb'` or `'localstorage'` for browser-based applications.","cause":"Attempting to use a persistence adapter (e.g., 'fs') in an unsupported JavaScript runtime (e.g., browser), or conversely, trying to use a browser-specific adapter in Node.js.","error":"Error: Persistence adapter 'fs' requires a Node.js environment."},{"fix":"When initializing a collection via `database.initCollection`, ensure that any columns intended to store `Date` objects have `type: 'date'` specified in their column definition, e.g., `{ type: 'date', title: 'myDateColumn' }`.","cause":"Inserting or retrieving a `Date` object into a collection column that was not explicitly defined with `type: 'date'` in the `initCollection` options, leading to incorrect serialization/deserialization.","error":"TypeError: Cannot read properties of undefined (reading 'toISOString')"},{"fix":"Ensure `database.initCollection()` is called only once per collection name per database instance. Store the returned `Collection` instance and reuse it throughout your application.","cause":"Attempting to call `database.initCollection()` for a collection that has already been initialized on the current database instance, which is not permitted.","error":"Error: Collection 'myCollectionName' already exists."}],"ecosystem":"npm"}