1.0.0 • Published 3 years ago

@dodiameer/json-database v1.0.0

Weekly downloads
-
License
ISC
Repository
-
Last release
3 years ago

Proof of concept - JSON-Based database

This codebase is a mess, but it works.

A database written in Node that uses JSON for data storage, it follows the concept of adapters to allow you to store your data anywhere, e.g. AWS S3, DigitalOcean Droplets, etc. (even another database, but like why?)

Usage

//=========== database.ts ===========//
import { Database } from "@dodiameer/json-database/db";
import { FileAdapter } from "@dodiameer/json-database/adapters/file";
import * as path from "path";
// There are currently no other adapters. If you want to make one look at the section for it in README.md

export const db = new Database({
  adapter: new FileAdapter(path.join(__dirname, "<location of data relative to current file>")),
});

//=========== app.ts ===========//
import { db } from "./database.ts"
import * as crypto from "crypto";

const all = await db.list("<name>.json")
const one = await db.get({
  name: "<name>.json",
  lookupKey: "id", // any unique, randomly generated field
  lookupValue: "some-id"
})

const oneMetadata = await db.get({
  name: "<name>.json",
  lookupKey: "id",
  lookupValue: "some-id",
  // Dot-separated path to any property in the object, null if it doesn't exist
  path: "info.extra.metadata" 
}) 

// Let's create something new!
const new = await db.create("<name>.json", { id: crypto.randomUUID(), key: "vale" }) 

// Oops, wrong value!
const update = await db.update({
  name: "<name>.json",
  lookupKey: "id",
  lookupValue: new.id,
  value: {id: new.id, key: "value"} // Completely overrides the object, be careful!
})

// Scratch that, delete the whole object
const deleted = await db.delete({ 
  name: "<name>.json", 
  lookupKey: "id", 
  lookupValue: update.id 
})

Adapters

An adapter has to be implemented like this: (The below is psuedo-code)

//=========== adapter.ts ===========//
import { GetParams, UpdateParams, DeleteParams } from "@dodiameer/json-database";
import { getPath } from "@dodiameer/json-database"; // Helper function
export class S3Adapter {
  constructor(apiKey) {
    // You can also implement caching and anything you want here
    this.client = new S3Client(apiKey)
  }

  // Implement any helper functions as private 
  private async loadFileFromS3(name) {
    return JSON.parse(await this.client.get(name)) 
  }

  // Helper function, unrelated
  private async writeFileToS3(name, content) {
    // (null, 2) will pretty-print with 2 tab width, recommended 
    const stringified = JSON.stringify(content, null, 2)
    await this.client.write(name, stringified)
  }

  // Anything under this has to be implemented
  async list(name) {
    return await this.loadFileFromS3(name)
  }

  async get({ name, lookupKey, lookupValue, path }: GetParams) {
    const file = await this.loadFileFromS3(name)
    const object = await file.find(o => o[lookupKey] === lookupValue) ?? {}
    return getPath(object, path ?? null) // Will return object if path is null 
  }

  async create(name, value) {
    // Some logic here to insert value into array
    await this.writeFileToS3(name, value)
    return value
  }

  async update({ name, lookupKey, lookupValue }: UpdateParams) {
    // Some logic to find existing object and update it
    await this.writeFileToS3(name, newFileContent)
    return updatedObject
  }

  async delete({ name, lookupKey, lookupValue }: DeleteParams) {
    // Some logic to find existing object and delete it
    await this.writeFileToS3(name, newFileContent)
    return deletedObject // You can return something else but this is prefered
  }
}