database-js-sqlparser: SQL Parser for database-js Drivers

1.0.0 · active · verified Wed Apr 22

database-js-sqlparser (current stable version 1.0.0) provides common SQL parsing functionality for `database-js` drivers that interact with non-database backends, such as in-memory data structures, local files, or APIs. It is not a database itself; rather, it acts as an abstract base class, translating standard SQL (including CREATE/DROP TABLE, SELECT, INSERT, UPDATE, DELETE) into calls to an underlying storage mechanism. Developers must extend this class and implement several asynchronous methods (e.g., `ready`, `close`, `load`, `store`, `remove`, `create`) to provide the actual data persistence. The library supports a subset of SQL, including basic CRUD operations, inner/left/right joins, grouping, filtering, ordering, and limiting. Its release cadence is not explicitly stated, but as a foundational 1.0.0 library, it is likely stable with less frequent, more deliberate updates. A key differentiator is its focus on providing a SQL interface over arbitrary JavaScript storage, abstracting away the specifics of the backend.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to extend the `SQLParser` class to create a custom in-memory `database-js` driver. It implements the required `ready`, `close`, `load`, `store`, `remove`, `create`, and `drop` methods, simulating basic table and row management in RAM. It shows how the abstract methods translate SQL operations to direct storage interactions.

import SQLParser from 'database-js-sqlparser';

class InMemoryDriver extends SQLParser {
    constructor() {
        super();
        this.tables = {}; // Simple in-memory storage
        this.lastId = 0;
    }

    ready() {
        console.log('InMemoryDriver: Ready.');
        return Promise.resolve(true);
    }

    close() {
        console.log('InMemoryDriver: Closing...');
        this.tables = {};
        this.lastId = 0;
        return Promise.resolve(true);
    }

    async load(tableName) {
        console.log(`InMemoryDriver: Loading from table '${tableName}'`);
        return Promise.resolve(Object.values(this.tables[tableName] || {}));
    }

    async store(tableName, index, row) {
        console.log(`InMemoryDriver: Storing in table '${tableName}', index: ${index}`);
        if (!this.tables[tableName]) {
            throw new Error(`Table '${tableName}' does not exist.`);
        }

        let id = index;
        if (id === null || id === undefined) {
            this.lastId++;
            id = this.lastId;
            row.id = id; // Assuming 'id' is a common primary key column
        }

        this.tables[tableName][id] = { ...row, id };
        return Promise.resolve(id);
    }

    async remove(tableName, index) {
        console.log(`InMemoryDriver: Removing from table '${tableName}', index: ${index}`);
        if (!this.tables[tableName] || !this.tables[tableName][index]) {
            throw new Error(`Row with index '${index}' not found in table '${tableName}'.`);
        }
        delete this.tables[tableName][index];
        return Promise.resolve(index);
    }

    async create(tableName, definition) {
        console.log(`InMemoryDriver: Creating table '${tableName}' with definition:`, definition);
        if (this.tables[tableName]) {
            throw new Error(`Table '${tableName}' already exists.`);
        }
        this.tables[tableName] = {}; // Initialize with an empty object for rows
        // In a real scenario, 'definition' would be used to validate column types.
        return Promise.resolve(true);
    }

    async drop(tableName) {
        console.log(`InMemoryDriver: Dropping table '${tableName}'`);
        if (!this.tables[tableName]) {
            throw new Error(`Table '${tableName}' does not exist.`);
        }
        delete this.tables[tableName];
        return Promise.resolve(true);
    }
}

async function runExample() {
    const driver = new InMemoryDriver();
    await driver.ready();

    // Simulate SQL operations by calling internal methods (in a real scenario, database-js would do this)
    // This is for demonstration of implementing the driver methods
    await driver.create('users', [
        { name: 'id', type: 'INTEGER' },
        { name: 'name', type: 'VARCHAR(255)' },
        { name: 'age', type: 'INTEGER' }
    ]);

    let userId1 = await driver.store('users', null, { name: 'Alice', age: 30 });
    let userId2 = await driver.store('users', null, { name: 'Bob', age: 25 });

    console.log('All users after inserts:', await driver.load('users'));

    await driver.store('users', userId1, { name: 'Alicia', age: 31, id: userId1 }); // Update
    console.log('Users after update:', await driver.load('users'));

    await driver.remove('users', userId2);
    console.log('Users after delete:', await driver.load('users'));

    await driver.drop('users');
    console.log('Driver closing...');
    await driver.close();
}

runExample().catch(console.error);

view raw JSON →