Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

firestorm-db

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

firestorm-db

Self hosted Firestore-like database with API endpoints based on micro bulk operations

  • 1.11.1
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

firestorm-db

npm GitHub file size in bytes Static Badge Tests

Self hosted Firestore-like database with API endpoints based on micro bulk operations

Installation

npm install --save firestorm-db

JavaScript Part

The JavaScript index.js file is just an Axios wrapper of the library.

How to use it

First, you need to configure your API address, and your token if needed:

require("dotenv").config(); // add some env variables
const firestorm = require("firestorm-db");

// ex: 'http://example.com/path/to/firestorm/root/'
firestorm.address(process.env.FIRESTORM_URL);

// only necessary if you want to write or access private collections
// must match token stored in tokens.php file
firestorm.token(process.env.FIRESTORM_TOKEN);

Now you can use Firestorm to its full potential:

const firestorm = require("firestorm-db");

// returns a Collection instance
const userCollection = firestorm.collection("users");

// all methods return promises
userCollection
    .readRaw()
    .then((res) => console.log(res))
    .catch((err) => console.error(err));

Collection constructor

A collection takes one required argument and one optional argument:

  • The name of the collection as a String.
  • The method adder, which allows to inject methods to the get methods results. This would be a Function taking the element as an argument.
const firestorm = require("firestorm-db");

// returns a Collection instance
const userCollection = firestorm.collection("users", (el) => {
    el.hello = function () {
        console.log(`${el.name} says hello!`);
    };
});

// if you have a 'users' table with a printable field named name
const johnDoe = await userCollection.get(123456789);
// gives { name: "John Doe", hello: function}

johnDoe.hello(); // prints out "John Doe says hello!"

Available methods for a collection:

Read operations

NameParametersDescription
sha1()noneGet the sha1 hash of the file. Can be used to see if same file content without downloading the file.
readRaw()noneReturns the whole content of the JSON. ID values are injected for easier iteration, so this may be different to sha1().
get(id)id: string | numberGet an element from the collection.
search(searchOptions, random)searchOptions: SearchOption[] random?:boolean | numberSearch through the collection You can randomize the output order with random as true or a given seed.
searchKeys(keys)keys: string[] | number[]Search specific keys through the collection.
select(selectOption)selectOption: { field: string[] }Get only selected fields from the collection Essentially an upgraded version of readRaw.
random(max, seed, offset)max?: integer >= -1 seed?: integer offset?:integer >= 0Reads random entries of collection.

The search method can take one or more options to filter entries in a collection. A search option takes a field with a criteria and compares it to a value. You can also use the boolean ignoreCase option for string values.

Not all criteria are available depending the field type. There are more options available than the firestore where command, allowing you to get better and faster search results.

All search options available

CriteriaTypes allowedDescription
'!='boolean, number, stringSearches if the entry field's value is different from yours
'=='boolean, number, stringSearches if the entry field's value is equal to yours
'>='number, stringSearches if the entry field's value is greater or equal than yours
'<='number, stringSearches if the entry field's value is equal to than yours
'>'number, stringSearches if the entry field's value is greater than yours
'<'number, stringSearches if the entry field's value is lower than yours
'in'number, stringSearches if the entry field's value is in the array of values you gave
'includes'stringSearches if the entry field's value includes your substring
'startsWith'stringSearches if the entry field's value starts with your substring
'endsWith'stringSearches if the entry field's value ends with your substring
'array-contains'ArraySearches if the entry field's array contains your value
'array-contains-any'ArraySearches if the entry field's array ends contains your one value of more inside your values array
'array-length-eq'numberSearches if the entry field's array size is equal to your value
'array-length-df'numberSearches if the entry field's array size is different from your value
'array-length-lt'numberSearches if the entry field's array size is lower than your value
'array-length-gt'numberSearches if the entry field's array size is lower greater than your value
'array-length-le'numberSearches if the entry field's array size is lower or equal to your value
'array-length-ge'numberSearches if the entry field's array size is greater or equal to your value

Write operations

NameParametersDescription
writeRaw()noneSet the entire JSON file contents /!\ Very dangerous /!\
add(value)value: ObjectAdds one element with autoKey into the collection
addBulk(values)value: Object[]Adds multiple elements with autoKey into the collection
remove(key)key: string | numberRemove one element from the collection with the corresponding key
removeBulk(keys)keys: string[] | number[]Remove multiple elements from the collection with the corresponding keys
set(key, value)key: string | number, value: ObjectSets one element with its key and value into the collection
setBulk(keys, values)keys: string[] | number[], values: Object[]Sets multiple elements with their corresponding keys and values into the collection
editField(obj)obj: EditObjectChanges one field of a given element in a collection
editFieldBulk(objArray)objArray: EditObject[]Changes one field per element in a collection

Edit field operations

Edit objects have an id to get the wanted element, a field they want to edit, an operation with what to do to this field, and a possible value. Here is a list of operations:

OperationValue requiredTypes allowedDescription
setYesanySets a field to a given value
removeNoanyRemoves a field from the element
appendYesstringAppends string at the end of the string field
invertNoanyInverts tate of boolean field
incrementNonumberAdds a number to the field, default is 1
decrementNonumberRetrieves a number to the field, default is -1
array-push YesanyPush an element to the end of an array field
array-deleteYesintegerRemoves and element at a certain index in an array field, check array_splice documentation offset for more infos
array-spliceYes[integer, integer]Removes certain elements, check array_splice documentation offset and length for more infos

PHP files

The PHP files are the ones handling files, read and writes. They also handle GET and POST requests to manipulate the database.

PHP setup

The developer has to create two main files at the root of their Firestorm setup: tokens.php and config.php.

tokens.php will contain the tokens inside a $db_tokens value array with the tokens to use. You will use these tokens to write data or read private tables.

config.php stores all of your collections config. You will create a $database_list variable with an array of JSONDatabase instances

<?php
// config.php
require_once('./classes/JSONDatabase.php');

$database_list = array();

$tmp = new JSONDatabase;
$tmp->folderPath = './files/';
$tmp->fileName = 'users';
$tmp->autoKey = false;

$database_list[$tmp->fileName] = $tmp;

$tmp = new JSONDatabase;
$tmp->folderPath = './files/';
$tmp->fileName = 'paths';
$tmp->autoKey = true;

$database_list[$tmp->fileName] = $tmp;
?>

The database will be stored in <folderPath>/<filename>.json and autoKey allows or forbids some write operations.

Files feature

File API functions are detailed in the files.php PHP script. If you do not want to include this functionality, then just delete this file.

You have to add 2 new configuration variables to your config.php file:

// whitelist of correct extensions
$authorized_file_extension = array('.txt', '.png');

// subfolder of uploads location, must start with dirname($_SERVER['SCRIPT_FILENAME'])
// to force a subfolder of firestorm installation
$STORAGE_LOCATION = dirname($_SERVER['SCRIPT_FILENAME']) . '/uploads/';

You can use the wrapper functions in order to upload, get and delete a file. If the folder is accessible from server url, you can directly type its address.

File rights

The PHP scripts create folders and files, so the script will fail if the PHP user doesn't have write permissions. You can give rights to a folder with the following command:

sudo chown -R www-data "/path/to/uploads/"

Upload a file

In order to upload a file, you have to give the function a FormData object. This class is generated from forms and is native in modern browsers but in Node.js can be imported with the form-data package.

The uploaded file content can be a String, a Blob, a Buffer or an ArrayBuffer.

There is additionally an overwrite option in order to avoid big mistakes and allow unique file names.

const firestorm = require("firestorm-db");
firestorm.address("ADDRESS_VALUE");
firestorm.token("TOKEN_VALUE");

const form = new FormData();
form.append("path", "/quote.txt");
form.append("file", "but your kids are gonna love it.", "quote.txt"); // make sure to set a temporary name to the file
form.append("overwrite", "true"); // override optional argument (do not append to set to false)
const uploadPromise = firestorm.files.upload(form);

uploadPromise
    .then(() => {
        console.log("Upload successful");
    })
    .catch((err) => {
        consoler.error(err);
    });

Get a file

You can get a file via its direct file URL location or its content with a request.

const firestorm = require("firestorm-db");
firestorm.address("ADDRESS_VALUE");

const getPromise = firestorm.files.get("/quote.txt");

getPromise
    .then((fileContent) => {
        console.log(fileContent); // 'but your kids are gonna love it.
    })
    .catch((err) => {
        console.error(err);
    });

Delete a file

Because I am a nice guy, I thought about deletion too. So I figured I would put a method to delete the files too.

const firestorm = require("firestorm-db");
firestorm.address("ADDRESS_VALUE");
firestorm.token("TOKEN_VALUE");

const deletePromise = firestorm.files.delete("/quote.txt");

deletePromise
    .then(() => {
        console.log("File successfully deleted");
    })
    .catch((err) => {
        console.error(err);
    });

Memory warning

Handling big collections can cause memory allocation issues like:

Fatal error:
Allowed memory size of 134217728 bytes exhausted (tried to allocate 32360168 bytes)

If you encounter a memory allocation issue, you have to allow more memory through this file /etc/php/7.4/apache2/php.ini with a bigger value here:

memory_limit = 256M

API endpoints

All Firestorm methods correspond to an equivalent Axios request to the relevant PHP file. Read requests are GET requests and write requests are POST requests with provided JSON data.

You always have the same first keys and the one key per method:

{
  "collection": "<collectionName>",
  "token": "<writeTokenIfNecessary>",
  "command": "<methodName>",
  ...
}

Keywords

FAQs

Package last updated on 12 Feb 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc