Declarative, database‑driven REST endpoints generated from JSON configuration. Ship CRUD + advanced data operations (GET / POST / PUT / DELETE / PATCH / TRACE) without writing boilerplate code.
Quick guide to install and run the Flexurio No‑Code API on macOS/Linux using the built‑in installer script or Docker, plus how to log in and access endpoints.
- macOS or Linux (Windows works via WSL).
- Database: MySQL/PostgreSQL/SQLite (recommended to start with SQLite for a quick try).
- Rust toolchain only if you want to build from source (optional).
- Run
install-flexurio.sh
to install the binary into~/.local/bin
and create theflexurio
command. - After it finishes, reload your shell (e.g.,
source ~/.zshrc
). - The
flexurio
command automatically reads the.env
file in the current working directory when executed.
Note: The script detects your OS architecture and downloads the latest release binary from GitHub for your platform.
- Copy the example file:
cp env .env
and edit the values. - Minimum values to set:
DB_TYPE
and its connection URL (quick start:DB_TYPE=sqlite
andSQLITE_URL=sqlite://data.db
).SECRET_KEY
for JWT signing, andENCRYPT_KEY
for column encryption.LOC_CONFIG
pointing to a config profile, e.g.config/example
,config/pos
, orconfig/tms
.
- Avoid duplicate keys in
.env
(choose only oneDB_TYPE
and one matching URL).
Minimal example (SQLite, quick start):
DB_TYPE=sqlite
SQLITE_URL=sqlite://data.db
LOC_CONFIG="config/example"
SECRET_KEY=replace_with_a_long_secret
ENCRYPT_KEY=replace_with_another_secret
PORT=8080
DEBUG=True
LOGGING=True
LOC_STATIC=static
LOC_IMAGE=images
LOC_LOGGING=static/log
Pick one method:
- Using the installer: go to the project folder that contains
.env
, then runflexurio
. - Using a release binary: pick the file under
release/
that matches your OS and run it. - Build from source:
cargo build --release
then run./target/release/flexurio-api-nocode-v2
.
On the first start:
- The app ensures core tables (
flx_users
,flx_roles
) exist. If not, they will be created. - If no admin exists, the system creates a default admin user with email
admin
and a random 4‑digit password printed to the console: "Your admin Password: 1234". Save this password.
Use docker-compose.yaml
as a reference. Adjust volumes for your local paths. Example for macOS from the project root:
services:
rust-app:
build: .
container_name: flexurio-api-nocode-v2
restart: always
ports:
- "2121:8080" # access at http://localhost:2121
volumes:
- "./static:/app/static"
- "./config:/app/config"
- "./.env:/app/.env"
routes.json
contains the list of enabled routes and those that are public.- The
entity/
folder contains<route>.json
files describing the table schema and CRUD behavior. - Choose a sample profile under
config/example
,config/pos
, orconfig/tms
, or create your own.
Steps to add a new route:
- Add the route name to the
routes
array inLOC_CONFIG/routes.json
. - Create
LOC_CONFIG/entity/<route>.json
matching the target table and desired behavior. - (Optional) Call
POST /generate/table/<route>
if the physical table does not exist. - Validate the schema with
GET /validate/<route>
.
- Login endpoint:
POST /login
using the Basic Authorization header (Basic base64(email:password)
). - Default admin: email
admin
, password is printed on first start (see console logs). - After login you will receive a JWT. Include it in subsequent requests:
Authorization: Bearer <token>
. - Public endpoints are defined in
route_publics
insideroutes.json
. IP whitelist viaWHITE_LIST_IP
.
For each active route
:
GET /<route>
: read data (supports query parameters per schema).POST /<route>
: create data (supports multipart/form‑data for file uploads).PUT /<route>/:id
andDELETE /<route>/:id
.PATCH /<route>
andTRACE /<route>
for custom flows (stored procedure/pipeline) as defined in the schema.GET /validate/<route>
to validate the schema.
Tips:
- For extra steps before/after INSERT/UPDATE, use
post.before
,post.after
,put.before
,put.after
in the schema with theSQL:
prefix. - Use placeholders like
{request.field}
so values are safely bound (SQL injection safe).
- This repository is Flexurio’s No‑Code API engine. For real‑world config examples, see profiles under
config/pos
,config/tms
, orconfigmftl
. - Use
CUSTOME_JWT_QUERY
in.env
to add custom claims to the JWT after login.
If you need help, open an issue on GitHub or contact the Flexurio team.
Flexurio No‑Code API lets you stand up secure, multi‑database REST endpoints by describing each entity (table) in a JSON schema. At startup the engine:
- Loads the enabled route names from
LOC_CONFIG/routes.json
. - Loads the entity schema JSON files from
LOC_CONFIG/entity/*.json
matching each route name. - (Optionally) generates required tables (
/generate/table/<route>
) except for built‑ins (flx_users
,flx_roles
). - Exposes a uniform REST surface for every route:
GET
,POST
,PUT /:id
,DELETE /:id
,PATCH
(stored procedure / custom processing),TRACE
(custom select pipeline), plusGET /validate/<route>
. - Applies JWT auth for all non‑public routes (with public overrides from
route_publics
inroutes.json
and optional IP whitelist).
Core use cases:
- Rapid prototyping of admin/data panels
- Multi‑tenant internal tooling
- API scaffolding over existing MySQL/Postgres/SQLite data
- Adding computed / formula‑driven flows (TRACE & PATCH)
- Multi‑DB support: MySQL, PostgreSQL, SQLite (select via
DB_TYPE
). - JSON‑driven entity schema defining columns, primary key, indexes, Redis cache keys, CRUD behavior, joins, grouping, ordering, and formula expressions.
- Auto table creation endpoint (
/generate/table/<route>
). - Schema validation endpoint (
/validate/<route>
). - Role + bitwise permission model embedded in JWT claims (
rl
field, e.g.products/127,*/*
). - Configurable additional JWT claim via SQL (
CUSTOME_JWT_QUERY
). - IP whitelisting override (
WHITE_LIST_IP
). - Redis caching blueprint (keys + TTL) in schema (implementation hooks in place; extend as needed).
- Pluggable pre / post hooks for POST & PUT (string SQL markers in schema) and PATCH stored procedure like flows.
- Structured logging with optional file output path.
- Static file serving under
/static
(e.g. images, logs).
git clone https://github.com/flexurio/flx-nocode-api.git
cd flx-nocode-api
Copy the example environment file and adapt values.
cp .env_example .env
Minimum required adjustments:
PORT
(default 8080)- Database connection (set
DB_TYPE
and corresponding URL var) SECRET_KEY
(JWT signing) &ENCRYPT_KEY
(column encryption logic)LOC_CONFIG
path to a config profile (e.g.config/pos
)
Pick the binary matching your OS / architecture in release/
and run:
./flx-nocode-aarch64-apple-darwin # Apple Silicon
# or
./flx-nocode-x86_64-apple-darwin # Intel macOS
# or (on Windows)
flx-nocode-x86_64-pc-windows-gnu.exe
On first start the engine ensures flx_users
& flx_roles
exist and seeds an administrator account (Admin Flexurio
). Check console logs to retrieve initial credentials if emitted.
Requires Rust toolchain.
cargo build --release
./target/release/flx-nocode-api
Below is the authoritative list derived from .env_example
and source code.
Variable | Required | Description |
---|---|---|
PORT | Yes | HTTP listen port. |
DB_TYPE | Yes | One of mysql , postgres , sqlite . |
MYSQL_URL / POSTGRES_URL / SQLITE_URL | Cond. | Connection string for selected DB type. (SQLite: sqlite://data.db ). |
REDIS_HOST | No | Redis host (future caching usage / extension). |
REDIS_PORT | No | Redis port. |
REDIS_PASSWORD | No | Redis auth password. |
REDIS_DB | No | Redis DB index. |
SECRET_KEY | Yes | JWT HMAC secret. |
ENCRYPT_KEY | Yes | Symmetric encryption key for protected columns. |
BASE_URL | No | External base URL (used in logs / links). |
DEBUG | No | Set True for verbose debug flow. |
LOGGING | No | Set True to enable extended log output. |
LOC_LOGGING | No | Directory for log files (default logs ). |
LOC_CONFIG | Yes | Path to active configuration profile (contains routes.json + entity/ ). |
LOC_IMAGE | No | Static image directory (served under /static ). |
CUSTOME_JWT_QUERY | No | SQL template run at login to enrich JWT claim cs (use {:?} placeholder for user id). |
WHITE_LIST_IP | No | Comma separated IPs that bypass JWT validation. |
Example snippet:
DB_TYPE=mysql
MYSQL_URL=mysql://user:pass@localhost:3306/your_db
LOC_CONFIG="config/pos"
SECRET_KEY=change_me
ENCRYPT_KEY=change_me_too
PORT=8080
LOC_CONFIG/
routes.json # Lists enabled routes + public routes
entity/
<route>.json # Schema per route (must match route name)
{
"routes": ["flx_users", "flx_roles", "banks"],
"route_publics": ["login", "register"]
}
Each <route>.json
→ TableSchema
(see src/model.rs
). Key sections:
table
: Physical table name.primary_key.columns
: Array of PK columns (supports composite).columns
: Column definitions:name
,type_data
,auto_increment
,nullable
,function
(DB function override),encrypt
(bool).indexes
: Named index sets (withunique
).redis
:{ keys: [], ttl }
— blueprint for future caching.get
: Read pipeline (projectedcolumns
, acceptedparameters
,join_tables
,column_groups
,having
,order_by
).post
/put
:{ before, columns, after }
—before
/after
can embed SQL formulas prefixed withSQL:
. Column list defines allowed insert/update fields.del
:{ columns, type_delete }
wheretype_delete
=soft
orhard
.patch
: For invoking pre‑processing / stored procedure logic:{ pre_process_sp, parameters }
.trace
: Advanced pipeline (insert + select + grouping + conflict handling) for data journaling / change capture.
Expressions like {request.field}
inside before/after
or formulas are replaced with request JSON values. Patterns like {products[1].price}
produce sub‑queries (SELECT price FROM products WHERE id = 1)
.
The fields post.before
, post.after
, put.before
, and put.after
in entity/<route>.json
let you run extra SQL before or after the main INSERT/UPDATE operation.
- Where they run:
post.before
runs before the INSERT.post.after
runs after a successful INSERT.put.before
runs before the UPDATE.put.after
runs after a successful UPDATE.
- Must start with the
SQL:
prefix. Empty strings or values withoutSQL:
are ignored. - Placeholders are automatically bound as parameters (SQL‑injection safe). You don’t need to place
?
manually. - Hooks are not executed in a single transaction with the main operation. If you need atomicity/rollback across all steps, use DB triggers or move logic into a stored procedure.
- Hook errors are logged but do not roll back the main operation.
Minimal example (entity menus.json
):
{
"post": {
"before": "SQL:UPDATE counters SET val = val + 1 WHERE name = 'menus'",
"after": "SQL:INSERT INTO audit_logs(entity, action, user_id) VALUES('menus','CREATE',{request.created_by_id})",
"columns": ["name"]
},
"put": {
"before": "SQL:INSERT INTO audit_logs(entity, action, ref_id) VALUES('menus','BEFORE_UPDATE',{request.id})",
"after": "SQL:INSERT INTO audit_logs(entity, action, ref_id) VALUES('menus','AFTER_UPDATE',{request.id})",
"columns": ["name"]
}
}
Supported placeholders inside before/after:
{request.field}
– value from the request body. Multipart/form‑data is supported. Text fields are read as strings; if the text contains valid JSON, it is parsed. Dotted paths are supported, e.g.{request.user.id}
or{request.items.0.price}
.{table[123].col}
– becomes a subquery:(SELECT col FROM table WHERE id = 123)
.{table[{request.id}].col}
– subquery with a dynamic id from the request.
More complete example:
{
"post": {
"before": "SQL:UPDATE products SET stock = stock - {request.qty} WHERE id = {request.product_id}",
"after": "SQL:INSERT INTO order_items(order_id, product_id, price) VALUES({request.order_id}, {request.product_id}, {products[{request.product_id}].price})",
"columns": ["order_id", "product_id", "qty"]
}
}
Important notes:
- For PUT, the path parameter
/:id
is not automatically available in hooks. If you need it in formulas, includeid
in the request body. - For POST with auto‑increment IDs, the newly generated ID is not available via
{request.*}
. If you need to reference the ID inafter
, use a custom ID pattern viacolumns[].function
(POST) or provide theid
yourself in the body. - The engine auto‑infers numeric vs string bindings. On PostgreSQL,
?
placeholders are converted to$1,$2,...
internally. - Each hook is executed as a single statement. For multi‑step logic, prefer a stored procedure or DB‑side routine that encapsulates multiple statements.
For a route name <route>
listed in routes.json
:
GET /<route>?param=value
– filtered select.POST /<route>
– multipart/form-data create (supports file + fields).PUT /<route>/:id
– update by id.DELETE /<route>/:id
– delete (soft/hard per schemadel.type_delete
).PATCH /<route>?...
– custom stored procedure / parameterized op (patch
).TRACE /<route>?...
– custom select + insert/orchestrated flow (trace
).GET /validate/<route>
– validate entity JSON matches engine expectations.POST /generate/table/<route>
– create underlying table (except reserved core tables).
Authentication:
- Public endpoints:
/login
,/register
, plus any inroute_publics
. - Protected endpoints require
Authorization: Bearer <token>
. - IPs in
WHITE_LIST_IP
bypass token checks.
Permissions (bitwise):
1=delete 2=write 4=read 8=execute 16=open/close 32=export 64=approve/reject
rl
claim contains comma‑separated <route>/<value>
pairs (or *
wildcard). Engine resolves bit flags to allowed verbs.
- Add the name to
routes
array insideLOC_CONFIG/routes.json
. - Create
LOC_CONFIG/entity/banks.json
based on an existing sample (e.g.flx_users.json
). Ensuretable
and file name align. - (Optional) Call
POST /generate/table/banks
if the physical table does not exist. - Hit
GET /validate/banks
to confirm schema integrity (returns OK / NOT OK summary). - Start using CRUD endpoints:
GET /banks
,POST /banks
, etc.
POST /login
with credentials → JWT issued (id
,nm
,rl
, optionalcs
).- Include token in
Authorization
header for subsequent calls. - Optional enrichment via
CUSTOME_JWT_QUERY
(e.g. add user email) using{:?}
placeholder for user id.
Structured log entries display endpoint registration and query execution. Control levels via:
DEBUG=True
– enables extra diagnostic printing.LOGGING=True
– extended logging; destination path fromLOC_LOGGING
.
Static assets & logs can be served under /static
(e.g. GET /static/log/
).
- Worker count is currently fixed to 1 (
.workers(1)
). Adjust inmain.rs
for concurrency. - Redis objects defined in schema are scaffolds—implement actual cache get/set in DB adapters or select layer as an extension.
- Add rate limiting / audit trails by wrapping Actix middleware before app configuration.
- Extend permission mapping in
auth.rs
if you need more bit flags.
- Auto‑generate OpenAPI spec from schemas
- Built‑in Redis caching for GET queries
- Web UI for managing schemas + routes
- Row level security / attribute‑based access controls
- Soft delete recovery endpoint
- Query explain / performance metrics
Symptom | Cause | Fix |
---|---|---|
Exit with LOC_CONFIG must be set |
Missing env var | Set LOC_CONFIG to one of the config profiles. |
ROUTES NOT VALID ! |
Empty / invalid routes.json |
Validate JSON syntax & ensure at least one route. |
Duplicate table name error | Two schemas share same table value |
Rename one or consolidate. |
Unauthorized responses | Missing / invalid Authorization header | Re‑login and attach Bearer token. |
Table not found | Did not generate or create manually | Use POST /generate/table/<route> or create table yourself. |
- Use a long random
SECRET_KEY
. - Rotate keys regularly (redeploy + reissue tokens).
- Keep
ENCRYPT_KEY
secret; rotate with data re‑encrypt process if used. - Restrict DB user privileges to least required.
- Sanitize any dynamic formula inputs (engine applies a basic sanitizer; validate further if exposing external clients).
- Enable HTTPS at the reverse proxy (nginx / traefik) level.
- Fork & branch (
feat/<name>
). - Make changes with focused commits.
- Ensure schemas & example configs remain valid.
- Submit PR with clear description & test notes.
See LICENSE
file.
Flexurio Engineering Team. Built with Rust + Actix Web.
- Configure
.env
&LOC_CONFIG
. - List routes in
routes.json
. - Create matching
entity/<route>.json
schemas. - Run binary.
- (Optional)
POST /generate/table/<route>
. - Validate with
GET /validate/<route>
. - Use REST endpoints with JWT auth.
Happy building.