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 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?
Node.js version must be >= 20.8.0.
- For the
recursiveoption toreaddirandopendir.
Install it by the following command:
npm install -g fidbThe command-line program is called fidb.
- Init a database
- Serve one database
- Serve many databases
- Register a user
- Login a user
- Config logger
- Get free certificate
- Use systemd to start service
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-worldExample 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 Use the fidb serve:database command to serve a database:
fidb serve:database hello-worldThe default port of the server is 5108, which looks like FiDB isn't it?
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 example.com, and configured my DNS to resolve example.com and *.example.com to my server.
I also created certificate files for my domain using certbot.
- About how to use
certbot, please see the "Get free certificate" section.
I can use fidb serve:subdomain command to serve all of the databases in /databases directory.
fidb serve:subdomain /databases/database.jsonWhere /databases/database.json is:
{ "server": { "hostname": "example.com", "port": 5108, "tls": { "cert": "/etc/letsencrypt/live/example.com/fullchain.pem", "key": "/etc/letsencrypt/live/example.com/privkey.pem" } } }-
When using
fidb serve:subdomain, theserver.hostnameoption is required. -
And each database in
/databasesmight have it's owndatabase.jsonconfig file.
Then I can access all my databases via subdomain of example.com.
https://x-wiki.example.com:5108 https://x-news.example.com: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://example.com:5108 https://www.example.com:5108 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" } } ENDExample 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 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" } ENDExample 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 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 }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 dnsThen 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.
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 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