npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@nan0web/db

v1.2.1

Published

Every data becomes a database. Agnostic document database and data manipulation utilities.

Readme

@nan0web/db

|Package name|Status|Documentation|Test coverage|Features|Npm version| |---|---|---|---|---|---| |@nan0web/db |🟢 98.8% |🧪 English 🏴󠁧󠁢󠁥󠁮󠁧󠁿Українською 🇺🇦 |🟢 93.7% |✅ d.ts 📜 system.md 🕹️ playground |1.2.0 |

Agnostic document database and data manipulation utilities. Designed to be flexible, minimal and powerful — the tool that supports any data format and nested hierarchy with reference resolution, inheritance and global variables.

Inspired by zero-is-not-a-number rule of nan0web:

Every data becomes a database.

Based on real use-cases, supports:

  • object flattening/unflattening
  • deep merging with reference handling
  • async directory listing (for fs & fetch layers)
  • stream-based progress during traversal

See how it works in playground.

Installation

How to install with npm?

npm install @nan0web/db

How to install with pnpm?

pnpm add @nan0web/db

How to install with yarn?

yarn add @nan0web/db

Quick Start

How to load JSON document?

import DB from "@nan0web/db"
const db = new DB()
const doc = await db.loadDocumentAs(".json", "doc", { key: "value" })
console.info(doc) // ← { key: "value" }

Example: Using get() with default fallback

How to get or return default?

import DB from "@nan0web/db"
const db = new DB()
const result = await db.get("missing-file.json", { defaultValue: {} })
console.info(result) // ← {}

Example: Loading known document

How to get specific document?

import DB from "@nan0web/db"
const db = new DB({ data: new Map([["file.txt", "text"]]) })
const result = await db.get("file.txt")
console.info(result) // ← "text"

Usage with Real Context

Resolving references and global vars

How to use document reference system?

import DB from "@nan0web/db"
const db = new DB({
	data: new Map([
		["_/index.json", { global: "value" }],
		["data.json", { "$ref": "_/index.json", key: "val" }]
	])
})
await db.connect()
const res = await db.fetch("data.json")
console.info(res) // ← { global: "value", key: "val" }

Playground

CLI sandbox for safe experiments:

git clone https://github.com/nan0web/db.git
cd db
npm install
npm run play

API Reference

The heart of the package includes core tools to manage hierarchical data structures.

db.get(uri, GetOpts)

Loads/returns document content from its URI.

  • Parameters

    • uri (string) – Document URI.
    • GetOpts.defaultValue (any) – fallback if doc not found
  • Returns

    • (any) – Document content or default value.

How to get document value?

import DB from "@nan0web/db"
const db = new DB({ data: new Map([["x.file", "hello"]]) })
const result = await db.get("x.file")
console.info(result) // ← "hello"

db.fetch(uri, FetchOptions)

Like get, plus advanced features: refs, vars, inherit rules processing.

Supports extension lookup, e.g. find .json even when omitted.

How to load extended data?

import DB from "@nan0web/db"
const db = new DB({ predefined: [["file.json", { value: "loaded" }]] })
await db.connect()
const result = await db.fetch("file")
console.info(result) // ← { value: "loaded" }

db.set(uri, data)

Sets document content and marks metadata updates.

How to save new content?

import DB from "@nan0web/db"
const db = new DB()
const res = await db.set("file.text", "save me!")
console.info(res) // ← "save me!"
console.info(db.data.get("file.text")) // ← "save me!"

Data.flatten(data)

Flattens nested object into paths as keys.

How to flatten object?

import { Data } from "@nan0web/db"
const flat = Data.flatten({ x: { a: [1, 2, { b: 3 }] } })
console.info(flat) // ← { 'x/a/[0]': 1, 'x/a/[1]': 2, 'x/a/[2]/b': 3 }

Data.unflatten(data)

Reconstructs nested structure from flat keys.

How to unflatten data?

import { Data } from "@nan0web/db"
const nested = Data.unflatten({
	"x/y/z": 7,
	"arr/[0]/title": "first",
	"arr/[1]/title": "second"
})
console.info(nested) // ← { x: { y: { z: 7 } }, arr: [ { title: 'first' }, { title: 'second' } ] }

Data.merge(a, b)

Deep merges two objects, handling array conflicts by replacing.

How to merge deeply?

import { Data } from "@nan0web/db"
const a = { x: { one: 1 }, arr: [0] }
const b = { y: "two", x: { two: 2 }, arr: [1] }
const merged = Data.merge(a, b)
console.info(merged) // ← { x: { one: 1, two: 2 }, y: 'two', arr: [ 1 ] }

Path Utilities

@nan0web/db/path provides URI/path resolution functions for cross-platform use. Supports normalization, basename/dirname extraction, and absolute/relative resolution.

Import Path Utilities

How to import path utilities?

import { normalize, basename, dirname, absolute, resolveSync } from '@nan0web/db/path'
console.info(normalize("a/b/../c")) // ← a/c
console.info(basename("path/to/file.txt")) // ← file.txt
console.info(dirname("path/to/file.txt")) // ← path/to/
console.info(absolute("/base", "root", "file")) // ← /base/root/file
console.info(resolveSync("/base", ".", "file.txt")) // ← file.txt

normalize(...segments)

Normalizes path segments, handling ../, ./, and duplicate slashes.

How to normalize path segments?

import { normalize } from '@nan0web/db/path'
console.info(normalize("a/b/../c")) // ← a/c
console.info(normalize("a//b///c")) // ← a/b/c
console.info(normalize("dir/sub/")) // ← dir/sub/

basename(uri, [suffix])

Extracts basename, optionally removing suffix or extension.

How to extract basename?

import { basename } from '@nan0web/db/path'
console.info(basename("/dir/file.txt")) // ← file.txt
console.info(basename("/dir/file.txt", ".txt")) // ← file
console.info(basename("/dir/file.txt", true)) // ← file (remove ext)
console.info(basename("/dir/")) // ← dir/

dirname(uri)

Extracts parent directory path.

How to extract dirname?

import { dirname } from '@nan0web/db/path'
console.info(dirname("/a/b/file")) // ← /a/b/
console.info(dirname("/a/b/")) // ← /a/
console.info(dirname("/file")) // ← /
console.info(dirname("file.txt")) // ← .

extname(uri)

Extracts file extension with dot (lowercase).

How to extract extension?

import { extname } from '@nan0web/db/path'
console.info(extname("file.TXT")) // ← .txt
console.info(extname("archive.tar.gz")) // ← .gz
console.info(extname("noext")) // ← ''
console.info(extname("/dir/")) // ← ''

resolveSync(cwd, root, ...segments)

Resolves segments relative to cwd/root (synchronous).

How to resolve path synchronously?

import { resolveSync } from '@nan0web/db/path'
console.info(resolveSync("/base", ".", "a/b/../c")) // ← a/c

relative(from, to)

Computes relative path from from to to.

How to compute relative path?

import { relative } from '@nan0web/db/path'
console.info(relative("/a/b", "/a/c")) // ← c
console.info(relative("/root/dir", "/root/")) // ← dir

absolute(cwd, root, ...segments)

Builds absolute path/URL from cwd, root, and segments.

How to build absolute path?

import { absolute } from '@nan0web/db/path'
console.info(absolute("/base", "root", "file")) // ← /base/root/file
console.info(absolute("https://ex.com", "api", "v1")) // ← https://ex.com/api/v1

isRemote(uri) & isAbsolute(uri)

Checks if URI is remote or absolute.

How to check URI type?

import { isRemote, isAbsolute } from '@nan0web/db/path'
console.info(isRemote("https://ex.com")) // ← true
console.info(isAbsolute("/abs/path")) // ← true
console.info(isAbsolute("./rel")) // ← false

Java•Script types & Autocomplete

Package is fully typed with jsdoc and d.ts.

How many d.ts files should cover the source?

Drivers & Extensions

Drivers extend DB with storage backends. Extend DBDriverProtocol for custom logic.

Basic Driver Extension

How to extend DBDriverProtocol?

import { DBDriverProtocol } from '@nan0web/db'
class MyDriver extends DBDriverProtocol {
	async read(uri) {
		// Custom read logic
		return { data: 'from custom storage' }
	}
}
const driver = new MyDriver()
console.log(await driver.read("/path")) // ← { data: 'from custom storage' }

Using Driver in DB

How to attach driver to DB?

import { DB, DBDriverProtocol } from '@nan0web/db'
class SimpleDriver extends DBDriverProtocol {
	async read(uri) { return `Read: ${uri}` }
	async write(uri, data) { return true }
}
class ExtendedDB extends DB {
	constructor() {
		super({ driver: new SimpleDriver() })
		this.loadDocument = async (uri) => await this.driver.read(uri)
		this.saveDocument = async (uri, data) => await this.driver.write(uri, data)
	}
}
const db = new ExtendedDB()
await db.connect()
console.info(await db.get('/test')) // ← Read: test

Authentication & Authorization

Use AuthContext for role-based access in DB operations.

Basic AuthContext Usage

How to create AuthContext?

import { AuthContext } from '@nan0web/db'
const ctx = new AuthContext({ role: 'user', roles: ['user', 'guest'] })
console.info(ctx.hasRole('user')) // ← true
console.info(ctx.role) // ← user

AuthContext with DB Access

How to use AuthContext in DB?

import { DB, AuthContext } from '@nan0web/db'
const db = new DB()
const ctx = new AuthContext({ role: 'admin' })
await db.set('secure/file.txt', 'secret', ctx)
console.info(await db.get('secure/file.txt', {}, ctx)) // ← secret

Handling Access Failures

How to handle auth failures?

import { AuthContext } from '@nan0web/db'
const ctx = new AuthContext()
ctx.fail(new Error('Access denied'))
console.info(ctx.fails) // ← [Error: Access denied]
console.info(ctx.hasRole('admin')) // ← false

Contributing

How to participate? – see CONTRIBUTING.md

License

ISC LICENSE – see full text