@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/restomaticFeatures
- 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
- select: at
- Static files:
/static/...- to load js, css, images, etc.
- Dynamic templates:
/template/...- to load custom
ejs-rendered content.
- to load custom
- 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
- readDirectory: at
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 databaseUsage 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.tokenrequest.body.tokenrequest.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
- Defaults to
- Parameter
- 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
- Parameter
- 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
- Parameter
- Delete data at
/api/v1/data/delete- Parameter
from: String- with the name of the table
- Parameter
where: Array- with the conditions
- Parameter
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
- Parameter
- 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
- Parameter
- Remove table at
/api/v1/data/removeTable- Parameter
table: String- with the name of the table
- Parameter
- 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
- Parameter
- Set file at
/api/v1/data/setFile- This operation requires
multipart/form-data(seetest/run.js) - Parameter
file: Blob- with the contents of the file
- This operation requires
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
- Parameter
- Write file at
/api/v1/filesystem/writeFile- Parameter
path: String - Parameter
content: String
- Parameter
- Delete file at
/api/v1/filesystem/deleteFile- Parameter
path: String
- Parameter
- Read directory at
/api/v1/filesystem/readDirectory- Parameter
path: String
- Parameter
- Make directory at
/api/v1/filesystem/makeDirectory- Parameter
path: String
- Parameter
- Delete directory at
/api/v1/filesystem/deleteDirectory- Parameter
path: String
- Parameter
- Is file at
/api/v1/filesystem/isFile- Parameter
path: String
- Parameter
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:
requestresponseRestomatic
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.
