Skip to content
/ fidb Public

What if we use file system as database?

License

Notifications You must be signed in to change notification settings

ArchGPT/fidb

Repository files navigation

FiDB

[ Webwite | Manual | 手册 ]

This is a Node.js implementation of FiDB -- a suite of protocols to use file system as database.

Including a command-line tool to initialize and maintain database.

Commands:
  help [name]             Display help for a command
  init:database [path]    Initialize a directory to be a database
  serve:database [path]   Serve a database
  serve:subdomain [path]  Serve many databases using subdomain-based routing

And a HTTP server to generate REST API from a database.

POST   {data-path}?kind=data
GET    {data-path}?kind=data
PUT    {data-path}?kind=data
PATCH  {data-path}?kind=data
DELETE {data-path}?kind=data

GET    {data-directory}?kind=data-find

POST   {file}?kind=file
GET    {file}?kind=file
PUT    {flie}?kind=file
DELETE {flie}?kind=file

GET    {flie}?kind=file-metadata

POST   {flie}?kind=file-rename

POST   {directory}?kind=directory
GET    {directory}?kind=directory
DELETE {directory}?kind=directory

Ethos

The ethos of the FiDB project is the following "what if ...?"s.

What if we use file system as database?

What if we generate HTTP API from the database,
instead of writing trivial CRUD code over and over again?

What if we write web apps in a way that a user can switch backend,
even using their local backend?

Install

Requirements

Node.js version must be >= 20.8.0.

  • For the recursive option to readdir and opendir.

Command line tool

Install it by the following command:

npm install -g fidb

The command-line program is called fidb.

Docs

Init a database

A database is just a directory of subdirectories and JSON data files, with a database.json config file, and with some more data files serve as detailed system configurations.

Use the fidb init:database command to create a database:

fidb init:database hello-world

Example console output of fidb init:database:

17:07:19.297 [init] -- {"directory":"/databases/hello-world"}
17:07:19.301 [initDatabaseConfigFile] -- {"file":"/databases/hello-world/database.json"}

Let's see what files are created:

database.json
.groups/guest/index.json
.groups/owner/index.json
.groups/user/index.json
.guest-token-issuer/index.json
.tokens/guest/index.json

Serve one database

Use the fidb serve:database command to serve a database:

fidb serve:database hello-world

The default port of the server is 5108, which looks like FiDB isn't it?

Serve many databases

Use the fidb serve:subdomain command to serve many databases in one directory, using subdomain-based routing.

For example, I have a VPS machine, where I put all my databases in the /databases directory.

/databases/x-wiki
/databases/x-news
...

I bought a domain for my server -- say fidb.app, and configured my DNS to resolve fidb.app and *.fidb.app to my server.

I also created certificate files for my domain using certbot.

I can use fidb serve:subdomain command to serve all of the databases in /databases directory.

fidb serve:subdomain /databases/database.json

Where /databases/database.json is:

{
  "server": {
    "hostname": "fidb.app",
    "port": 5108,
    "tls": {
      "cert": "/etc/letsencrypt/live/fidb.app/fullchain.pem",
      "key": "/etc/letsencrypt/live/fidb.app/privkey.pem"
    }
  }
}
  • When using fidb serve:subdomain, the server.hostname option is required.

  • And each database in /databases might have it's own database.json config file.

Then I can access all my databases via subdomain of fidb.app.

https://x-wiki.fidb.app:5108
https://x-news.fidb.app:5108
...

If no subdomain is given in a request, www/ will be used as the default subdomain directory (while no redirect will be done).

Thus the following websites have the same contents:

https://fidb.app:5108
https://www.fidb.app:5108

Register a user

Use POST {data-file}?kind=password-register HTTP request to register a new user:

curl -X POST "http://127.0.0.1:5108/users/alice?kind=password-register" --data-binary @-<< END

{
  "password": "wonderland",
  "data": {
    "name": "Alice"
  }
}

END

Example response:

{
  "name": "Alice",
  "@path": "users/alice",
  "@revision": "b0b913da866105ad66299baf6aa4d783",
  "@createdAt": 1696152632809,
  "@updatedAt": 1696152632809
}

New data files for the user will be created:

users/alice/index.json
users/alice/.password/index.json
users/alice/.token-issuer/index.json

Login a user

Use POST {data-file}?kind=password-login HTTP request to login an initialized user:

curl -X POST "http://127.0.0.1:5108/users/alice?kind=password-login" --data-binary @-<< END

{
  "password": "wonderland"
}

END

Example response:

{ "token":"07cb46bde600f9ab97a22ecee8bc2389" }

New data file for the token will be created:

.tokens/07cb46bde600f9ab97a22ecee8bc2389/index.json

Which can be used in the Authorization header for future requests.

Authorization: token 34dbf6a79e7968ffc3cda1b51c3fada9

Config logger

We can config logger in /databases/database.json:

{
  ...,
  "logger": {
    "name": "pretty-line",
    "disableRequestLogging": true
  }
}

The type of logger options are:

export type LoggerOptions = {
  name: "json" | "silent" | "pretty" | "pretty-line"
  disableRequestLogging?: boolean
}

The default logger options are:

{
  "name": "pretty-line",
  "disableRequestLogging": false
}

Get free certificate

You can use certbot to get free certificate for your domains.

After install certbot, I prefer creating certificate via DNS TXT record, using the following command:

sudo certbot certonly --manual --preferred-challenges dns

Then you can follow the prompt of certbot to create the certificate files, during which you will need to add TXT record to the DNS record of your domain to accomplish the challenge given by certbot.

Use systemd to start service

Install service:

sudo cp <name>.service /etc/systemd/system/

Using service:

sudo systemctl start <name>.service
sudo systemctl enable <name>.service
sudo systemctl status <name>.service

To view log:

journalctl -f -u <name>.service

Reload systemd config files:

sudo systemctl daemon-reload

Development

npm install           # Install dependencies
npm run build         # Compile `src/` to `lib/`
npm run build:watch   # Watch the compilation
npm run format        # Format the code
npm run test          # Run test
npm run test:watch    # Watch the testing

Contributions

To make a contribution, fork this project and create a pull request.

Please read the STYLE-GUIDE.md before you change the code.

Remember to add yourself to AUTHORS. Your line belongs to you, you can write a little introduction to yourself but not too long.

License

GPLv3

About

What if we use file system as database?

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published