reddb-cli 0.1.2-next.37 → 0.1.2-next.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -271
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,339 +1,203 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">RedDB</h1>
|
|
3
|
+
<p align="center"><strong>The AI-first multi-model database.</strong></p>
|
|
4
|
+
<p align="center">Tables. Documents. Graphs. Vectors. KV. One engine. Ask it anything.</p>
|
|
5
|
+
</p>
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://github.com/forattini-dev/reddb/releases"><img src="https://img.shields.io/github/v/release/forattini-dev/reddb?style=flat-square" alt="Release"></a>
|
|
9
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="License"></a>
|
|
10
|
+
<a href="https://www.npmjs.com/package/reddb-cli"><img src="https://img.shields.io/npm/v/reddb-cli?style=flat-square&label=npm" alt="npm"></a>
|
|
11
|
+
</p>
|
|
4
12
|
|
|
5
|
-
|
|
13
|
+
---
|
|
6
14
|
|
|
7
|
-
|
|
8
|
-
- JSON-like documents
|
|
9
|
-
- graph nodes and edges
|
|
10
|
-
- vector embeddings and similarity search
|
|
11
|
-
- key-value records
|
|
15
|
+
## The Killer Feature: `ASK`
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
RedDB lets one application work with different data shapes in the same database file or server runtime.
|
|
16
|
-
|
|
17
|
-
Typical use cases:
|
|
18
|
-
|
|
19
|
-
- operational application state with SQL-style querying
|
|
20
|
-
- graph-aware products that also need regular tables
|
|
21
|
-
- semantic retrieval and vector search next to first-party data
|
|
22
|
-
- local-first or edge deployments that want an embedded database
|
|
23
|
-
- AI/agent workflows that need MCP, HTTP, gRPC, or in-process access
|
|
24
|
-
|
|
25
|
-
## How RedDB works
|
|
26
|
-
|
|
27
|
-
RedDB uses the same core engine across three practical modes:
|
|
28
|
-
|
|
29
|
-
| Mode | When to use it | How you access it |
|
|
30
|
-
|:-----|:---------------|:------------------|
|
|
31
|
-
| Embedded | Your app should own the database directly, like SQLite | Rust API (`RedDB` or `RedDBRuntime`) |
|
|
32
|
-
| Server | Multiple clients or services need to connect | HTTP or gRPC |
|
|
33
|
-
| Agent / tooling | You want CLI or MCP integration on top of the same engine | `red` CLI or MCP server |
|
|
34
|
-
|
|
35
|
-
That means the storage model stays the same whether you:
|
|
36
|
-
|
|
37
|
-
- open a local `.rdb` file inside your Rust process
|
|
38
|
-
- run `red server --grpc-bind 127.0.0.1:50051 --http-bind 127.0.0.1:8080`
|
|
39
|
-
- expose the same database to AI agents through MCP
|
|
40
|
-
|
|
41
|
-
## Install
|
|
42
|
-
|
|
43
|
-
### GitHub releases
|
|
44
|
-
|
|
45
|
-
The recommended install path is the release installer, which pulls the correct asset from GitHub Releases:
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
curl -fsSL https://raw.githubusercontent.com/forattini-dev/reddb/main/install.sh | bash
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Pin a version:
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
curl -fsSL https://raw.githubusercontent.com/forattini-dev/reddb/main/install.sh | bash -s -- --version v0.1.2
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
Use the prerelease channel:
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
curl -fsSL https://raw.githubusercontent.com/forattini-dev/reddb/main/install.sh | bash -s -- --channel next
|
|
17
|
+
```sql
|
|
18
|
+
ASK 'who owns CPF 000.000.000-00 and what services do they use?'
|
|
61
19
|
```
|
|
62
20
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Release page:
|
|
21
|
+
One command. RedDB searches across tables, graphs, vectors, documents, and key-value stores -- builds context -- calls an LLM -- returns a natural-language answer. No pipelines. No glue code. No other database does this.
|
|
66
22
|
|
|
67
|
-
|
|
23
|
+
---
|
|
68
24
|
|
|
69
|
-
|
|
25
|
+
## 5 Data Models, 1 Engine
|
|
70
26
|
|
|
71
|
-
|
|
27
|
+
Stop running Postgres + Neo4j + Pinecone + Redis + Mongo. RedDB unifies them.
|
|
72
28
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
npx reddb-cli@latest version
|
|
77
|
-
```
|
|
29
|
+
```sql
|
|
30
|
+
-- Relational rows
|
|
31
|
+
INSERT INTO users (name, email) VALUES ('Alice', 'alice@co.com')
|
|
78
32
|
|
|
79
|
-
|
|
33
|
+
-- JSON documents
|
|
34
|
+
INSERT INTO logs DOCUMENT (body) VALUES ('{"level":"info","msg":"login"}')
|
|
80
35
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
```
|
|
36
|
+
-- Graph edges
|
|
37
|
+
INSERT INTO network EDGE (label, from, to) VALUES ('CONNECTS', 1, 2)
|
|
84
38
|
|
|
85
|
-
|
|
39
|
+
-- Vector similarity search
|
|
40
|
+
SEARCH SIMILAR TEXT 'anomaly detected' COLLECTION events
|
|
86
41
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
./target/release/red version
|
|
42
|
+
-- Key-value
|
|
43
|
+
PUT config.theme = 'dark'
|
|
90
44
|
```
|
|
91
45
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
### Local Dev
|
|
46
|
+
Same file. Same engine. Same query language.
|
|
95
47
|
|
|
96
|
-
|
|
97
|
-
mkdir -p ./data
|
|
98
|
-
red server \
|
|
99
|
-
--path ./data/reddb.rdb \
|
|
100
|
-
--grpc-bind 127.0.0.1:50051 \
|
|
101
|
-
--http-bind 127.0.0.1:8080
|
|
102
|
-
```
|
|
48
|
+
---
|
|
103
49
|
|
|
104
|
-
|
|
50
|
+
## AI-Native From Day One
|
|
105
51
|
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
-d '{
|
|
110
|
-
"fields": {
|
|
111
|
-
"ip": "10.0.0.1",
|
|
112
|
-
"os": "linux",
|
|
113
|
-
"critical": true
|
|
114
|
-
}
|
|
115
|
-
}'
|
|
116
|
-
```
|
|
52
|
+
```sql
|
|
53
|
+
-- Semantic search without managing vectors yourself
|
|
54
|
+
SEARCH SIMILAR TEXT 'suspicious login' COLLECTION logs USING groq
|
|
117
55
|
|
|
118
|
-
|
|
56
|
+
-- Auto-embed on insert -- vectors are created for you
|
|
57
|
+
INSERT INTO articles (title, body) VALUES ('AI Safety', 'Alignment research...')
|
|
58
|
+
WITH AUTO EMBED (body) USING openai
|
|
119
59
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
-H 'content-type: application/json' \
|
|
123
|
-
-d '{"query":"SELECT * FROM hosts WHERE critical = true"}'
|
|
124
|
-
```
|
|
60
|
+
-- Context search: find everything related to an entity across all models
|
|
61
|
+
SEARCH CONTEXT '192.168.1.1' FIELD ip DEPTH 2
|
|
125
62
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
curl -s http://127.0.0.1:8080/health
|
|
63
|
+
-- Ask questions in plain English
|
|
64
|
+
ASK 'what vulnerabilities affect host 10.0.0.1?' USING anthropic
|
|
130
65
|
```
|
|
131
66
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
- HTTP for `curl`, browser tooling, and scripts
|
|
135
|
-
- gRPC for `red connect` and service-to-service clients
|
|
67
|
+
RedDB retrieves context from every data model, feeds it to the LLM, and gives you a grounded answer. RAG built into the database layer.
|
|
136
68
|
|
|
137
|
-
|
|
69
|
+
---
|
|
138
70
|
|
|
139
|
-
|
|
71
|
+
## 11 AI Providers
|
|
140
72
|
|
|
141
|
-
|
|
142
|
-
- `red connect` opens a gRPC session to a running RedDB server.
|
|
73
|
+
Swap providers with a keyword. No code changes.
|
|
143
74
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
75
|
+
| Provider | Keyword | API Key Required |
|
|
76
|
+
|:---------|:--------|:-----------------|
|
|
77
|
+
| OpenAI | `openai` | Yes |
|
|
78
|
+
| Anthropic | `anthropic` | Yes |
|
|
79
|
+
| Groq | `groq` | Yes |
|
|
80
|
+
| OpenRouter | `openrouter` | Yes |
|
|
81
|
+
| Together | `together` | Yes |
|
|
82
|
+
| Venice | `venice` | Yes |
|
|
83
|
+
| DeepSeek | `deepseek` | Yes |
|
|
84
|
+
| HuggingFace | `huggingface` | Yes |
|
|
85
|
+
| Ollama | `ollama` | No (local) |
|
|
86
|
+
| Local | `local` | No |
|
|
87
|
+
| Custom URL | `https://...` | Configurable |
|
|
148
88
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
89
|
+
```sql
|
|
90
|
+
ASK 'summarize alerts' USING groq MODEL 'llama-3.3-70b-versatile'
|
|
91
|
+
ASK 'summarize alerts' USING ollama MODEL 'llama3'
|
|
92
|
+
ASK 'summarize alerts' USING anthropic
|
|
152
93
|
```
|
|
153
94
|
|
|
154
|
-
|
|
95
|
+
---
|
|
155
96
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
```bash
|
|
159
|
-
red server \
|
|
160
|
-
--path ./data/reddb.rdb \
|
|
161
|
-
--grpc-bind 127.0.0.1:50051 \
|
|
162
|
-
--http-bind 127.0.0.1:8080
|
|
163
|
-
```
|
|
97
|
+
## SQL Extensions
|
|
164
98
|
|
|
165
|
-
|
|
99
|
+
RedDB extends SQL with `WITH` clauses for operational semantics:
|
|
166
100
|
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
|
|
101
|
+
```sql
|
|
102
|
+
-- TTL: auto-expire records
|
|
103
|
+
INSERT INTO sessions (token) VALUES ('abc') WITH TTL 1 h
|
|
170
104
|
|
|
171
|
-
|
|
105
|
+
-- Context indexes for cross-model search
|
|
106
|
+
CREATE TABLE customers (cpf TEXT) WITH CONTEXT INDEX ON (cpf)
|
|
172
107
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
```
|
|
108
|
+
-- Graph expansion inline with SELECT
|
|
109
|
+
SELECT * FROM users WITH EXPAND GRAPH DEPTH 2
|
|
176
110
|
|
|
177
|
-
|
|
111
|
+
-- Metadata on write
|
|
112
|
+
INSERT INTO logs (msg) VALUES ('deploy') WITH METADATA (source = 'ci')
|
|
178
113
|
|
|
179
|
-
|
|
180
|
-
|
|
114
|
+
-- Absolute expiration
|
|
115
|
+
INSERT INTO events (name) VALUES ('launch') WITH EXPIRES AT 1735689600000
|
|
181
116
|
```
|
|
182
117
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
If you want RedDB inside your process, open the database directly from Rust and work against the same engine without a separate server.
|
|
186
|
-
|
|
187
|
-
### Fluent embedded API
|
|
188
|
-
|
|
189
|
-
```rust
|
|
190
|
-
use reddb::RedDB;
|
|
191
|
-
use reddb::storage::schema::Value;
|
|
192
|
-
|
|
193
|
-
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
194
|
-
let db = RedDB::open("./data/reddb.rdb")?;
|
|
118
|
+
---
|
|
195
119
|
|
|
196
|
-
|
|
197
|
-
("name", Value::Text("Alice".into())),
|
|
198
|
-
("active", Value::Boolean(true)),
|
|
199
|
-
]).save()?;
|
|
120
|
+
## 6 Query Languages
|
|
200
121
|
|
|
201
|
-
|
|
202
|
-
.node_type("account")
|
|
203
|
-
.property("name", "Alice")
|
|
204
|
-
.save()?;
|
|
122
|
+
Write in whatever you think in. The engine auto-detects the language.
|
|
205
123
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
124
|
+
| Language | Example |
|
|
125
|
+
|:---------|:--------|
|
|
126
|
+
| **SQL** | `SELECT * FROM hosts WHERE os = 'linux'` |
|
|
127
|
+
| **Cypher** | `MATCH (a:User)-[:FOLLOWS]->(b) RETURN b.name` |
|
|
128
|
+
| **Gremlin** | `g.V().hasLabel('person').out('FOLLOWS').values('name')` |
|
|
129
|
+
| **SPARQL** | `SELECT ?name WHERE { ?p :name ?name }` |
|
|
130
|
+
| **Natural Language** | `show me all critical hosts` |
|
|
131
|
+
| **ASK (RAG)** | `ASK 'what changed in the last 24 hours?'` |
|
|
211
132
|
|
|
212
|
-
|
|
133
|
+
All six hit the same engine, same data, same indexes.
|
|
213
134
|
|
|
214
|
-
|
|
215
|
-
Ok(())
|
|
216
|
-
}
|
|
217
|
-
```
|
|
135
|
+
---
|
|
218
136
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
If you want embedded execution with the runtime/use-case layer, use `RedDBRuntime`. This is the closest path to using RedDB "like SQLite", but with the project's multi-model runtime.
|
|
222
|
-
|
|
223
|
-
```rust
|
|
224
|
-
use reddb::application::{CreateRowInput, ExecuteQueryInput};
|
|
225
|
-
use reddb::storage::schema::Value;
|
|
226
|
-
use reddb::{EntityUseCases, QueryUseCases, RedDBOptions, RedDBRuntime};
|
|
227
|
-
|
|
228
|
-
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
229
|
-
let rt = RedDBRuntime::with_options(
|
|
230
|
-
RedDBOptions::persistent("./data/reddb.rdb")
|
|
231
|
-
)?;
|
|
232
|
-
|
|
233
|
-
EntityUseCases::new(&rt).create_row(CreateRowInput {
|
|
234
|
-
collection: "users".into(),
|
|
235
|
-
fields: vec![
|
|
236
|
-
("name".into(), Value::Text("Alice".into())),
|
|
237
|
-
("age".into(), Value::Integer(30)),
|
|
238
|
-
],
|
|
239
|
-
metadata: vec![],
|
|
240
|
-
node_links: vec![],
|
|
241
|
-
vector_links: vec![],
|
|
242
|
-
})?;
|
|
243
|
-
|
|
244
|
-
let result = QueryUseCases::new(&rt).execute(ExecuteQueryInput {
|
|
245
|
-
query: "SELECT * FROM users".into(),
|
|
246
|
-
})?;
|
|
247
|
-
|
|
248
|
-
println!("rows = {}", result.result.records.len());
|
|
249
|
-
rt.checkpoint()?;
|
|
250
|
-
Ok(())
|
|
251
|
-
}
|
|
252
|
-
```
|
|
137
|
+
## 48 Built-in Types
|
|
253
138
|
|
|
254
|
-
|
|
139
|
+
Not just `TEXT` and `INTEGER`. RedDB understands your domain.
|
|
255
140
|
|
|
256
|
-
|
|
141
|
+
**Network:** `IpAddr`, `Ipv4`, `Ipv6`, `MacAddr`, `Cidr`, `Subnet`, `Port`
|
|
142
|
+
**Geo:** `Latitude`, `Longitude`, `GeoPoint`
|
|
143
|
+
**Locale:** `Country2`, `Country3`, `Lang2`, `Lang5`, `Currency`
|
|
144
|
+
**Identity:** `Uuid`, `Email`, `Url`, `Phone`, `Semver`
|
|
145
|
+
**Visual:** `Color`, `ColorAlpha`
|
|
146
|
+
**Cross-model refs:** `NodeRef`, `EdgeRef`, `VectorRef`, `RowRef`, `KeyRef`, `DocRef`, `TableRef`, `PageRef`
|
|
147
|
+
**Primitives:** `Integer`, `UnsignedInteger`, `Float`, `Decimal`, `BigInt`, `Text`, `Blob`, `Boolean`, `Json`, `Array`, `Enum`
|
|
148
|
+
**Temporal:** `Timestamp`, `TimestampMs`, `Date`, `Time`, `Duration`
|
|
257
149
|
|
|
258
|
-
|
|
150
|
+
Validation on write. No parsing in your app.
|
|
259
151
|
|
|
260
|
-
|
|
152
|
+
---
|
|
261
153
|
|
|
262
|
-
|
|
263
|
-
SEARCH CONTEXT '081.232.036-08' FIELD cpf
|
|
264
|
-
SEARCH CONTEXT 'Alice' COLLECTION customers DEPTH 2 LIMIT 50
|
|
265
|
-
```
|
|
154
|
+
## 3 Deployment Modes
|
|
266
155
|
|
|
267
|
-
|
|
156
|
+
| Mode | Think of it as... | Access via |
|
|
157
|
+
|:-----|:-------------------|:-----------|
|
|
158
|
+
| **Embedded** | SQLite | Rust API -- `RedDB::open("data.rdb")` |
|
|
159
|
+
| **Server** | Postgres | HTTP + gRPC -- dual-stack |
|
|
160
|
+
| **Agent** | MCP tool | `red mcp` -- AI agent integration |
|
|
268
161
|
|
|
269
|
-
|
|
162
|
+
Same storage format across all three. Start embedded, scale to server, expose to agents -- no migration.
|
|
270
163
|
|
|
271
|
-
|
|
164
|
+
---
|
|
272
165
|
|
|
273
|
-
|
|
274
|
-
-- Time-to-live on INSERT and UPDATE
|
|
275
|
-
INSERT INTO sessions (token) VALUES ('abc') WITH TTL 1 h
|
|
276
|
-
UPDATE sessions SET active = true WHERE id = 1 WITH TTL 2 h
|
|
166
|
+
## Quick Start
|
|
277
167
|
|
|
278
|
-
|
|
279
|
-
|
|
168
|
+
```bash
|
|
169
|
+
# Install
|
|
170
|
+
curl -fsSL https://raw.githubusercontent.com/forattini-dev/reddb/main/install.sh | bash
|
|
280
171
|
|
|
281
|
-
|
|
282
|
-
|
|
172
|
+
# Start the server
|
|
173
|
+
red server --http-bind 127.0.0.1:8080 --path ./data.rdb
|
|
283
174
|
|
|
284
|
-
|
|
285
|
-
|
|
175
|
+
# Insert data
|
|
176
|
+
curl -X POST http://127.0.0.1:8080/query \
|
|
177
|
+
-H 'content-type: application/json' \
|
|
178
|
+
-d '{"query":"INSERT INTO hosts (ip, os) VALUES ('\''10.0.0.1'\'', '\''linux'\'')"}'
|
|
286
179
|
|
|
287
|
-
|
|
288
|
-
|
|
180
|
+
# Query it
|
|
181
|
+
curl -X POST http://127.0.0.1:8080/query \
|
|
182
|
+
-H 'content-type: application/json' \
|
|
183
|
+
-d '{"query":"SELECT * FROM hosts"}'
|
|
289
184
|
```
|
|
290
185
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
Group results and filter groups after aggregation:
|
|
186
|
+
Or via npm:
|
|
294
187
|
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
SELECT dept, role FROM employees GROUP BY dept, role
|
|
298
|
-
SELECT dept FROM employees GROUP BY dept HAVING dept > 5 ORDER BY dept
|
|
188
|
+
```bash
|
|
189
|
+
npx reddb-cli@latest server --http --bind 127.0.0.1:8080
|
|
299
190
|
```
|
|
300
191
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
The query engine auto-detects the language, so you can mix paradigms against the same dataset:
|
|
304
|
-
|
|
305
|
-
| Language | Example |
|
|
306
|
-
|:---------|:--------|
|
|
307
|
-
| SQL | `SELECT * FROM hosts WHERE os = 'linux'` |
|
|
308
|
-
| Cypher | `MATCH (a:User)-[:FOLLOWS]->(b) RETURN b.name` |
|
|
309
|
-
| Gremlin | `g.V().hasLabel('person').out('FOLLOWS').values('name')` |
|
|
310
|
-
| SPARQL | `SELECT ?name WHERE { ?p :name ?name }` |
|
|
311
|
-
| Natural language | `show me all critical hosts` |
|
|
312
|
-
|
|
313
|
-
See [multi-mode queries](docs/query/multi-mode.md) for supported steps and patterns.
|
|
192
|
+
---
|
|
314
193
|
|
|
315
|
-
|
|
194
|
+
## Links
|
|
316
195
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
curl http://127.0.0.1:8080/collections/config/kvs/theme
|
|
322
|
-
|
|
323
|
-
# Write a key
|
|
324
|
-
curl -X PUT http://127.0.0.1:8080/collections/config/kvs/theme \
|
|
325
|
-
-d '{"value":"dark"}'
|
|
326
|
-
|
|
327
|
-
# Delete a key
|
|
328
|
-
curl -X DELETE http://127.0.0.1:8080/collections/config/kvs/theme
|
|
329
|
-
```
|
|
196
|
+
- [Documentation](https://forattini-dev.github.io/reddb)
|
|
197
|
+
- [GitHub](https://github.com/forattini-dev/reddb)
|
|
198
|
+
- [npm package](https://www.npmjs.com/package/reddb-cli)
|
|
199
|
+
- [Releases](https://github.com/forattini-dev/reddb/releases)
|
|
330
200
|
|
|
331
|
-
|
|
201
|
+
---
|
|
332
202
|
|
|
333
|
-
|
|
334
|
-
- Installation: [docs/getting-started/installation.md](docs/getting-started/installation.md)
|
|
335
|
-
- Quick start: [docs/getting-started/quick-start.md](docs/getting-started/quick-start.md)
|
|
336
|
-
- Connection guide: [docs/getting-started/connect.md](docs/getting-started/connect.md)
|
|
337
|
-
- Embedded guide: [docs/api/embedded.md](docs/api/embedded.md)
|
|
338
|
-
- HTTP API: [docs/api/http.md](docs/api/http.md)
|
|
339
|
-
- CLI reference: [docs/api/cli.md](docs/api/cli.md)
|
|
203
|
+
**MIT License** -- Built by [Filipe Forattini](https://github.com/forattini-dev)
|