npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@carlosjimenohernandez/restomatic

v1.0.5

Published

Set up REST automatically

Downloads

27

Readme

restomatic

Automatic REST on top of Node.js + SQLite + Express.

Installation

npm i -g @carlosjimenohernandez/restomatic

Features

  • REST operations:
    • select: at /api/v1/data/select
    • insert: at /api/v1/data/insert?token=admin
    • update: at /api/v1/data/update?token=admin
    • delete: at /api/v1/data/delete?token=admin
    • createTable: at /api/v1/data/createTable?token=admin
    • createColumn: at /api/v1/data/createColumn?token=admin
    • removeTable: at /api/v1/data/removeTable?token=admin
    • removeColumn: at /api/v1/data/removeColumn?token=admin
    • setFile: at /api/v1/data/setFile?token=admin
  • Static files: /static/...
    • to load js, css, images, etc.
  • Dynamic templates: /template/...
    • to load custom ejs-rendered content.
  • Filesystem operations:
    • readDirectory: at /api/v1/filesystem/readDirectory?token=admin
    • makeDirectory: at /api/v1/filesystem/makeDirectory?token=admin
    • deleteDirectory: at /api/v1/filesystem/deleteDirectory?token=admin
    • readFile: at /api/v1/filesystem/readFile?token=admin
    • writeFile: at /api/v1/filesystem/writeFile?token=admin
    • deleteFile: at /api/v1/filesystem/deleteFile?token=admin
    • isFile: at /api/v1/filesystem/isFile?token=admin

Dependencies

This is part of the package.json:

  "dependencies": {
    "better-sqlite3": "^12.2.0",
    "body-parser": "^2.2.0",
    "ejs": "^3.1.10",
    "express": "^5.1.0",
    "multer": "^2.0.2",
    "sqlstring": "^2.3.3"
  }

Usage

You have 2 options to run restomatic:

  • From command line
  • From node.js script

Both are explained below.

Usage from command line

From command line you can:

npx restomatic
  --port "9090"             # Port to listen
  --models "models.js"      # Models to import
  --routes "routes.js"      # Routes to include beside defaults
  --token "admin"           # Token for advanced operations
  --database "test.sqlite"  # File for database

Usage from node.js script

From a node.js script you can:

const restomaticInstance = await require("@carlosjimenohernandez/restomatic").create({
    port: "9090",
    models: "models.js",
    routes: "routes.js",
    token: "admin",
    database: "test.sqlite",
});

Parameters

The previous calls overstand some meaningful parameters, which are explained below.

Parameter port

You specify the port number which must open the instance.

Parameter token

The token parameter is used to filter advanced operations that require permissions, like:

  • /api/v1/data/insert
  • /api/v1/data/update
  • /api/v1/data/delete
  • /api/v1/data/createTable
  • /api/v1/data/createColumn
  • /api/v1/data/removeTable
  • /api/v1/data/removeColumn
  • /api/v1/filesystem/makeDirectory
  • /api/v1/filesystem/readDirectory
  • /api/v1/filesystem/deleteDirectory
  • /api/v1/filesystem/writeFile
  • /api/v1/filesystem/readFile
  • /api/v1/filesystem/deleteFile
  • /api/v1/filesystem/isFile

You have to provide directly the string that can match the token parameter on the request, either by, in this order:

  • request.headers.token
  • request.body.token
  • request.query.token

Parameter database

You specify the file that will be used (or created) as sqlite database.

Parameter models

On models.js you must have something like:

module.exports = {
  individuals: {
    columns: {
      nombre: { sql: "VARCHAR(255) UNIQUE", },
      edad:   { sql: "VARCHAR(255)", },
      tipo:   { sql: "VARCHAR(255)", },
      padre:  { sql: "INTEGER REFERENCES individuals(id)" }
    }
  }
};

Parameter routes

On routes.js you will want to have something like:

Restomatic.router.use("/path", function(request, response) {
    try {
        return response.success({
            message: "Your message",
            note: "This method is injected by «XXX.create-application.js»'
        });
    } catch(error) {
        return response.success(new Error("This method is injected by «XXX.create-application.js» too"));
    }
});

And a REST is set up for you automatically.

Operations

The following titles describe the common operations enabled by default on /api/v1/data/{operation} path of the application.

  • Schema at /api/v1/data/schema
  • Select data at /api/v1/data/select
    • Parameter from: String
      • with the name of the table
    • Parameter where: Array
      • with the conditions
    • Parameter order: Array
      • with the columns in order
      • Can use ! to reverse the order
    • Parameter page: Integer
      • with the page
      • Starts on 1
    • Parameter items: Integer
      • Defaults to 100
  • Insert data at /api/v1/data/insert
    • Parameter into: String
      • with the name of the table
    • Parameter values: Array | Object
      • with the values for the new object/s
  • Update data at /api/v1/data/update
    • Parameter from: String
      • with the name of the table
    • Parameter where: Array
      • with the conditions
    • Parameter set: Object
      • with the new values
  • Delete data at /api/v1/data/delete
    • Parameter from: String
      • with the name of the table
    • Parameter where: Array
      • with the conditions

Also, you can alter the schema by the following operations:

  • Create table at /api/v1/data/createTable
    • Parameter table: String
      • with the name of the table
    • Parameter content: String
      • with the SQLite code of the table
  • Create column at /api/v1/data/createColumn
    • Parameter table: String
      • with the name of the table
    • Parameter column: String
      • with the name of the column
    • Parameter content: String
      • with the SQLite code of the column
  • Remove table at /api/v1/data/removeTable
    • Parameter table: String
      • with the name of the table
  • Remove column at /api/v1/data/removeColumn
    • Parameter table: String
      • with the name of the table
    • Parameter column: String
      • with the name of the column
  • Set file at /api/v1/data/setFile
    • This operation requires multipart/form-data (see test/run.js)
    • Parameter file: Blob
      • with the contents of the file

Also, you can access and modify the filesystem (only /static and /template folders) by the following operations:

  • Read file at /api/v1/filesystem/readFile
    • Parameter path: String
  • Write file at /api/v1/filesystem/writeFile
    • Parameter path: String
    • Parameter content: String
  • Delete file at /api/v1/filesystem/deleteFile
    • Parameter path: String
  • Read directory at /api/v1/filesystem/readDirectory
    • Parameter path: String
  • Make directory at /api/v1/filesystem/makeDirectory
    • Parameter path: String
  • Delete directory at /api/v1/filesystem/deleteDirectory
    • Parameter path: String
  • Is file at /api/v1/filesystem/isFile
    • Parameter path: String

Select data

You can select (without admin token):

const res = await fetch("http://127.0.0.1:9090/api/v1/data/select", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "none", // This is not required for select operations
        from: "individuals",
        where: [
            ["id", "is not null"],
            ["id", "!=", "1000"],
            ["id", ">=", "1"],
            ["id", ">", "0"],
            ["id", "<", "1000"],
            ["id", "<=", "1000"],
            ["id", "like", "%"],
            ["id", "not like", "x%"],
            ["id", "in", [1,2,3]],
            ["id", "not in", [4,5,6]],
        ],
        order: ["!id"]    // with ! for DESC [endant]
        page: 1,          // defaults to 1
        items: 100,       // defaults to 100
    })
});
console.log(await res.json());

Insert data

Once running, you can insert with admin token:

const res = await fetch("http://127.0.0.1:9090/api/v1/data/insert", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        into: "individuals",
        values: [{
            nombre: "Carlos Jimeno Hernández",
            edad: 35
        }, {
            nombre: "Ada Jimeno Hernández",
            edad: 9,
        }, {
            nombre: "Gatito Jimeno Hernández",
            edad: 4,
        }]
    })
});
console.log(await res.json());

Update data

You can update with admin token:

const res = await fetch("http://127.0.0.1:9090/api/v1/data/select", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        from: "individuals",
        set: {
            tipo: "Familiar"
        },
        where: [
            ["id", "is not null"],
            ["id", "!=", "1000"],
            ["id", ">=", "1"],
            ["id", ">", "0"],
            ["id", "<", "1000"],
            ["id", "<=", "1000"],
            ["id", "like", "%"],
            ["id", "not like", "x%"],
            ["id", "in", [1,2,3]],
            ["id", "not in", [4,5,6]],
        ]
    })
});
console.log(await res.json());

Delete data

You can delete with admin token:

const res = await fetch("http://127.0.0.1:9090/api/v1/data/delete", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        from: "individuals",
        where: [
            ["id", "is null"],
            ["id", "!=", "1000"],
            ["id", ">=", "1"],
            ["id", ">", "0"],
            ["id", "<", "1000"],
            ["id", "<=", "1000"],
            ["id", "like", "%"],
            ["id", "not like", "x%"],
            ["id", "in", [1,2,3]],
            ["id", "not in", [4,5,6]],
        ]
    })
});
console.log(await res.json());

Create table

For example, using GET:

http://127.0.0.1:9090/api/v1/data/createTable?token=admin&table=lote

Or using POST:

const res = await fetch("http://127.0.0.1:9090/api/v1/data/createTable", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        table: "lote",
        content: `
            numero INTEGER UNIQUE NOT NULL,
            contenedor INTEGER REFERENCES lote(id)
        `
    })
});
console.log(await res.json());

Create column

For example:

const res = await fetch("http://127.0.0.1:9090/api/v1/data/createColumn", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        table: "lote",
        column: "identificador",
        content: `VARCHAR(255) NOT NULL`
    })
});
console.log(await res.json());

Remove table

For example:

const res = await fetch("http://127.0.0.1:9090/api/v1/data/removeTable", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        table: "lote",
    })
});
console.log(await res.json());

Remove column

For example:

const res = await fetch("http://127.0.0.1:9090/api/v1/data/removeTable", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        table: "lote",
        column: "identificador",
    })
});
console.log(await res.json());

Other features

Below are listed other features the tool offers automatically.

  • Static content
  • Dynamic content
  • Upload files

Static content

You can access the files under src/static by:

http://127.0.0.1/static/whatever.txt

Dynamic content

You can access the files under src/template by:

http://127.0.0.1/static/whatever.ejs

They will always be rendered as ejs files.

You can access the following variables:

  • request
  • response
  • Restomatic

You can use this snippet to force some mime-type when rendering and serving a file, and so, load css or html or any, but dynamically:

<% response.type("html") %>
<% response.type("css") %>
<% response.type("js") %>

Upload files

Only admin can upload files, as it is a potentially conflictive behaviour.

The example run on test/run.js demonstrates how this can work without downloading libraries in node.js:

const fs = require("fs");
const form = new FormData();
const fileBuffer = fs.readFileSync(__dirname + "/example.txt");

form.append("file", new Blob([fileBuffer]), "example.txt");

const r = await fetch("http://127.0.0.1:9090/api/v1/data/setFile", {
    method: "POST",
    body: form,
    headers: {
        token: "admin"
    }
});

const response = await r.text();

console.log(response);

Filesystem operations

Only admin can commit filesystem operations, as they have potentially conflictive behaviours.

Make directory

For example:

const res = await fetch("http://127.0.0.1:9090/api/v1/filesystem/makeDirectory", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        path: "/static/newdir", // This has to start with /static or /template
    })
});
console.log(await res.json());

Read directory

For example:

const res = await fetch("http://127.0.0.1:9090/api/v1/filesystem/readDirectory", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        path: "/static/newdir", // This has to start with /static or /template
    })
});
console.log(await res.json());

Delete directory

For example:

const res = await fetch("http://127.0.0.1:9090/api/v1/filesystem/deleteDirectory", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        path: "/static/newdir", // This has to start with /static or /template
    })
});
console.log(await res.json());

Write file

For example:

const res = await fetch("http://127.0.0.1:9090/api/v1/filesystem/writeFile", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        path: "/static/newdir/file1.txt", // This has to start with /static or /template
        content: "Hello!", 
    })
});
console.log(await res.json());

Read file

For example:

const res = await fetch("http://127.0.0.1:9090/api/v1/filesystem/readFile", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        path: "/static/newdir/file1.txt", // This has to start with /static or /template
    })
});
console.log(await res.json());

Delete file

For example:

const res = await fetch("http://127.0.0.1:9090/api/v1/filesystem/deleteFile", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        path: "/static/newdir/file1.txt", // This has to start with /static or /template
    })
});
console.log(await res.json());

Is file?

For example:

const res = await fetch("http://127.0.0.1:9090/api/v1/filesystem/isFile", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
        token: "admin", // This has to match with provided cmd token
        path: "/static/jquery.js", // This has to start with /static or /template
    })
});
console.log(await res.json());

Customize by your own

The npm run build command takes bundlelist.js exported files and dumps them in a all-in-one file called restomatic.js.

By this reason, all the files have its __dirname pointing on top of the project.

Use it at your own convenience, the final file is quite short.