{"id":16288,"library":"a1-database","title":"A1-Database: Embedded JSON Database","description":"a1-database is an embedded, zero-dependency, zero-installation JSON database designed for simplicity and portability. As of version 1.8.0, it stores all data in a single file, making it ideal for development, local applications, or scenarios where a lightweight, persistent data store is required without external database server overhead. It operates directly on JavaScript objects, eliminating the need for an ORM, and returns query results as arrays of objects. The package provides methods that cater to both SQL-like (e.g., `insert`, `update` with `id` keys) and document-like (flexible `save` with custom filter functions for multi-key or heterogeneous data) paradigms. Each database instance is represented by a single file, facilitating easy backup and data dumping. Its primary release cadence is not explicitly stated, but ongoing development is implied by the version number, focusing on a straightforward API for common CRUD operations like `save`, `find`, and `delete`.","status":"active","version":"1.8.0","language":"javascript","source_language":"en","source_url":"https://github.com/ax1/a1-database","tags":["javascript","database","no-sql","JSON","embedded","standalone"],"install":[{"cmd":"npm install a1-database","lang":"bash","label":"npm"},{"cmd":"yarn add a1-database","lang":"bash","label":"yarn"},{"cmd":"pnpm add a1-database","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"A1-database is primarily designed for CommonJS. Direct ESM `import` might not be supported without specific Node.js configuration (e.g., 'type: module' in package.json) or transpilation.","wrong":"import database from 'a1-database'","symbol":"database","correct":"const database = require('a1-database')"}],"quickstart":{"code":"const database = require('a1-database');\nconst fs = require('fs/promises'); // For cleanup\n\nasync function runExample() {\n  const dbPath = 'users.db';\n\n  try {\n    // Ensure cleanup of previous runs for a fresh start\n    try { await fs.unlink(dbPath); } catch (e) { /* ignore if file doesn't exist */ }\n\n    const db = await database.get(dbPath);\n    console.log('Database connected to', dbPath);\n\n    // Save initial data\n    await db.save({ name: 'Juan', email: 'juan@example.com' });\n    await db.save({ name: 'Maria', email: 'maria@example.com' });\n    console.log('Initial users saved.');\n\n    // Save with an ID, demonstrating upsert behavior\n    await db.save([{ id: 100, value: 'old test data' }]);\n    console.log('Saved item with id 100 (old).');\n    await db.save([{ id: 100, value: 'new test data', timestamp: Date.now() }]); // item with id, so old items are removed\n    console.log('Saved item with id 100 (new), overwriting old data.');\n\n    // Find operations\n    const juan = await db.findOne(el => el.name === 'Juan');\n    console.log('Found Juan:', juan);\n\n    const allUsers = await db.find(el => el.name === 'Juan' || el.name === 'Maria');\n    console.log('Found all initial users:', allUsers);\n\n    // Demonstrate existence check\n    const existsJuan = await db.exists(el => el.name === 'Juan');\n    console.log('Does Juan exist?', !!existsJuan);\n\n    // Delete operation\n    const deletedCount = await db.delete(el => el.email === 'maria@example.com');\n    console.log(`Deleted ${deletedCount} user(s).`);\n\n    const remainingUsers = await db.find(el => true);\n    console.log('Remaining items after delete:', remainingUsers);\n\n    // Disconnect from the database\n    await database.disconnect(db);\n    console.log('Database disconnected.');\n\n  } catch (error) {\n    console.error('An error occurred:', error);\n  } finally {\n    // Optional: Clean up the database file after the example\n    try { await fs.unlink(dbPath); } catch (e) { /* ignore */ }\n    console.log('Cleaned up database file.');\n  }\n}\n\nrunExample().catch(console.error);","lang":"javascript","description":"Demonstrates database connection, saving data (including upsert behavior with IDs), finding records, checking existence, and deleting entries, along with proper cleanup of the database file."},"warnings":[{"fix":"Always use absolute paths or carefully manage the current working directory to ensure the database file is created and accessed in the intended location.","message":"Database file paths are resolved relative to `process.CWD()` (Current Working Directory) where the Node.js process was started, not relative to the JavaScript file where `a1-database` is instantiated. This can lead to unexpected file locations if not explicitly managed.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"When using `save`, be explicit about providing `id` for upserts, or define precise filter functions to control replacement behavior. Use `insert` for strict 'add-only' semantics.","message":"The `save` method automatically updates existing items if an `id` property is present in the item(s) being saved, acting as an upsert. For items without an `id` or when using a custom `filter` function, `save` will append new items or replace items matching the filter, requiring careful filter definition to prevent unintended duplicates or data loss.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"If an item might already exist, use `save` if overwriting is acceptable. If strict uniqueness is required for new entries, use `insert` and wrap calls in a `try...catch` block to handle potential duplicate ID errors.","message":"The `insert` method enforces uniqueness based on the `id` field. Attempting to `insert` an item with an `id` that already exists in the database will throw an error, unlike `save` which overwrites. Developers should choose `insert` for strict 'no-duplicate-ID' policies and `save` for 'upsert' behavior.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For high-throughput applications, consider batching writes or evaluating if an in-memory or server-based database is more appropriate. Monitor disk I/O metrics if performance becomes a concern.","message":"As a file-based embedded database, `a1-database` performs disk I/O for every write operation. While suitable for many use cases, high-frequency write operations or very large datasets may experience performance bottlenecks compared to in-memory or server-based databases. Automatic compaction is triggered every 10,000 consecutive save/delete operations.","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":"To fix this, either ensure that the `id` is unique before calling `db.insert()`, or use `db.save()` instead if the intention is to update/overwrite the existing item with the same `id`.","cause":"This error occurs when attempting to use `db.insert()` with an item whose `id` field matches an existing record in the database.","error":"Error: Item with ID [ID_VALUE] already exists."}],"ecosystem":"npm"}