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
recursive
option toreaddir
andopendir
.
Install it by the following command:
npm install -g fidb
The 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-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
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?
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
.
- 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.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
, theserver.hostname
option is required. -
And each database in
/databases
might have it's owndatabase.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
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
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
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 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
.
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
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.