typicode / lowdb

Simple and fast JSON database
MIT License
21.3k stars 918 forks source link

Open to adding support for deno? #563

Closed chmac closed 1 year ago

chmac commented 1 year ago

Firstly, thanks for all the work on lowdb. I love the simplicity. 🧡 🧡 🧡

Would you be open to adding support for deno? I imagine it would be quite a simple job to fork the JSONFile, JSONFileSync, TextFile and TextFileSync adapters and refactor the read / write calls to use Deno's API.

If you prefer, I could also write a simple deno adapter and then publish that separately. I wanted to open the topic here and get some feedback before I chose either path.

chmac commented 1 year ago

Hmm, I started looking into this, and I realise it's not quite as simple as I first thought. The tests are based on running in node, and so they won't work under deno. 🤔

Maybe a separate package makes more sense then?

typicode commented 1 year ago

Thanks for the nice words. Aren't deno compatible with npm modules now?

chmac commented 1 year ago

That is an excellent point! I had thought to use the Deno filesystem APIs, but you are right that all npm modules can be imported directly now. My experience is that they don't always work, but I'll try to check lowdb and report back.

tmikaeld commented 1 year ago

This used to work in Deno and Cloudflare workers, I used it when it was 1.0 and wanted to use it now, but didn't work..

Working in 1.0:

  const { default: low } = await import('lowdb');
  const {default: Memory } = await import('lowdb/adapters/Memory');
  const db = low(new Memory())

  const dbContent = await fetch('https://test.source.com/json').then((res)=>res.json());

  db.defaults(dbContent)
    .write()

  const result = db.get('posts')

Update: Still works in Deno with lowdb 1.0 though ;-)

chmac commented 1 year ago

@typicode You were absolutely correct, in my minimal test, lowdb worked in deno without any additional messing around. Here's the test case I used in case anyone else wants to test it.

import { Low } from "npm:lowdb";
import { JSONFile } from "npm:lowdb/node";

type Data = {
  posts: string[];
};

const test = async () => {
  // File path
  const file = "./data/db.json";

  // Configure lowdb to write to JSONFile
  const adapter = new JSONFile<Data>(file);
  const db = new Low(adapter);

  // Read data from JSON file, this will set db.data content
  await db.read();

  // If db.json doesn't exist, db.data will be null
  // Use the code below to set default data
  // db.data = db.data || { posts: [] } // For Node < v15.x
  db.data ||= { posts: [] }; // For Node >= 15.x

  // Create and query items using native JS API
  db.data.posts.push("hello world");
  const firstPost = db.data.posts[0];
  console.log("#7sqNUh firstPost", firstPost);

  // Alternatively, you can also use this syntax if you prefer
  const { posts } = db.data;
  posts.push("hello world");

  // Finally write db.data content to file
  await db.write();
};

// Learn more at https://deno.land/manual/examples/module_metadata#concepts
if (import.meta.main) {
  await test();
}

I'll close the issue now.

tmikaeld commented 1 year ago

@chmac While this is great, I was looking at getting it working in Cloudflare workers with the latest version. But when I tried the latest memory mapper, it doesn't allow writes at all.

Use case: retrieve data from a cloudflare KV value and write it to in-memory mapper.

typicode commented 1 year ago

Thanks @chmac good to know :) @tmikaeld, I don't know why it doesn't work. Lowdb with in-memory adapter is pure JS without any Node API. If you figure out the root cause, I'd be interested to know :)