Build your backend fast and simple | Easy document-based database with no query language | Adapt the server to your project |
---|---|---|
jServ is an open source project designed to help backend developers get a server, database, and API up and running as soon as possible. |
jServ has a flexible data structure that allows you to customize the database and it's functionality, with or without modifying the code. |
jServ's driving force is it's use of multiple markup languages in it's data structure, and custom endpoints functions powered by Python. |
To set up jServ, download the latest release, and unzip it into a folder, and run the executable. You will have a config.json
file, a keys.jserv
file, and an admin.jserv
file.
There will also be a directory called Collections
, with an example.dat
given to get started. To add a collection to the program, simply add a .dat
file of any name, and the program will read it.
Before you execute the program for the first time, you should check in your config and data files.
The config.json
file should look something like this:
{
"appname": "New app",
"debug": true,
"admin-path": "admin.jserv",
"key-path": "keys.jserv",
"ip": "localhost",
"port": 4040,
"write-interval": 10,
"Requests":
{
"GET": true,
"POST": true,
"PUT": false,
"HEAD": true,
"DELETE": true,
"PATCH": false,
"OPTIONS": false
},
"Permissions":
{
"Query": "user",
"Add": "user",
"Mod": "user",
"Delete": "user",
"Purge": "user"
},
"Aliases":
{
"127.0.0.1":"localhost"
},
"Services":
{
"/" : "index"
}
}
Change the IP and port to whatever you need. Debug mode will show more detailed console logging. The requests list determines which requests the program will accept.
The permissions list determines which requests can be made with the user keys, whereas admin keys will have access to all of them.
The aliases list will change how certain addresses are displayed within the console.
When you run the program for the first time, an Admin API key will generate in the admin.jserv
file, and a User API key will generate in the keys.jserv
file.
The program will reject any requests that do not have these keys in the "x-api-key"
header.
jServ's database relies on the use of HTTP requests to send instructions and data back and forth between the instance and your program. There are built-in request handlers that execute a variety of database operations (See below).
Each request will give a response in the form of a JSON object. It appears as follows (with example values)
{
"status": "ok",
"message": "Successfully queried some-database for some-object",
"data": {
"some-data": "some-value"
}
}
The status
value will appear as either "ok"
or "error"
, and the message
value will display a message either confirming the success, or explaining the error. The data
value may not appear, and will only contain data if the request returns it.
The database follows a document-based structure which internally relies on three classes, Document
, Attribute
, and Collection
.
Document
is the class that represents objects in the database. When serialized as a JSON object, it appears as follows (with example values)
{
"_id": "some-unique-identifier",
"data": {"some-key": "some-value"}
}
There is no pre-defined schema like in relational databases like MySQL. Each document can have a unique set of data
The _id
field is the only guaranteed value attached to any document. It is dependent on the user to implement field enforcement in your applications, and to ensure that the data fields are consistent across all objects if that is required.
Attribute
is a class that serves the sole purpose of being a proxy between fields passed in the API requests. When serialized as a JSON object, it appears as follows (with example values)
{
"some-key": "some-value"
}
Some of the requests require a single value to be passed in to the request body in a form resembling an Attribute
object. The Attribute
class acts as a model within the program to translate that data seamlessly to the Collection
and Document
classes.
Collection
is a grouping of documents within a file. When written as a JSON object, it appears as follows (with example values)
{
"name": "some-name",
"list": [
{
"id": 0,
"data": {"some-key": "some-value"}
}
]
}
Internally, the name corresponds to a filename in the Collections
folder, which contains the serialized data of list
.
(All of these structures can also be found in the jServ core library)
jServ's database operations are called through HTTP requests. This eliminates the need for a query language, as the properties of every operation can be encapsulated into serialized objects passed into each request.
__/j/db/query
-
Queries a list of, or all, collections for documents based on a set of rules. Returns a list of documents.
Possible properties of a query, written in JSON format, are as follows:{ //List of collections to be queried //If omitted, all collections will be queried "collections": [ "some-collection", "another-collection" ], //List of attributes a document must have "has": [ "some-attribute", "another-attribute" ], //Attributes that must be equal to a given value "equals": { "some-attribute": "some-value" }, //Attributes that must not be equal to a given value "not-equals": { "some-attribute": "some-value" }, //Attributes that must be less than a given value "lt": { "some-attribute": "some-value" }, //Attributes that must be less than or equal to a given value "lte": { "some-attribute": "some-value" }, //Attributes that must be greater than or equal to a given value "gte": { "some-attribute": "some-value" }, //Attributes that must be greater than a given value "gt": { "some-attribute": "some-value" }, //Attributes that must be between two given values "between": { "some-attribute": ["lower-value", "upper-value"] } }
This request returns the list of documents queried.
__/j/db/add
-
Adds documents to, or attributes to specific documents in, a collection.
The format of an Add, written in JSON, is as follows:{ //Name of the collection to add to, will fail if omitted "collection": "some-collection", //List of full documents to add to the collection "documents": [ { "_id": "some-new-id", "data": { "some-attribute": "some-value" } } ], //Map of new attributes that will be added to the documents they are listed under. Note that "_id" cannot be added as an attribute "values":{ "some-document-id": { "some-new-attribute": "some-new-value" } } }
This request returns a list of elements added, and elements skipped.
__/j/db/mod
-
Modifies attributes of a specific document within a collection.
The format of a Mod, written in JSON, is as follows:{ //Collection containing the document. Will fail if this collection does not exist "collection": "some-collection", //_id of Document to be modified. Will fail if this document does not exist "document": "some-document-id", //Map of attributes to be changed. Note that the _id can also be changed in this operation. "values":{ "_id": "some-new-id", "some-attribute": "some-new-value" } }
This request returns a list of changes made, and changes skipped.
__/j/db/delete
-
Deletes attributes of a specific document within a collection.
The format of a Delete, written in Json, is very similar to a Mod, as follows:{ //Collection containing the document. Will fail if this collection does not exist "collection": "some-collection", //_id of Document to be modified. Will fail if this document does not exist "document": "some-document-id", //List of attributes to be deleted. Note that _id cannot be deleted in this operation. "values":[ "some-attribute", "another-attribute" ] }
This request returns a list of attributes deleted, and attributes skipped.
__/j/db/purge
-
Deletes documents from a list of, or all, collections, based on query rules.
See__/j/db/query
above, as this request has an identical structure.This request returns the list of document _ids deleted.
When performing operations such as Mod or Add, the request body contains rules for finding the targets of the operations. However, these may not always match up with the data, for example, trying to add a document whose _id already exists within that collection. In cases such as these, this part of the operation is skipped, and message is relayed back to the user through the HTTP Response data.
Services are small python scripts that can be assigned to run on specific endpoints.
This feature isn't implemented yet :(
Copyright (c) 2024, alchemicode. All Rights Reserved. Permission to modify and redistribute is granted under the terms of the Apache 2.0.