db-model-router 1.0.4 → 1.0.6
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 +110 -16
- package/TODO.md +15 -0
- package/dbmr.schema.json +333 -0
- package/docker-compose.yml +1 -1
- package/package.json +8 -7
- package/scripts/demo-create.js +47 -0
- package/skill/SKILL.md +464 -0
- package/skill/references/cockroachdb.md +49 -0
- package/skill/references/dynamodb.md +53 -0
- package/skill/references/mongodb.md +56 -0
- package/skill/references/mssql.md +55 -0
- package/skill/references/oracle.md +52 -0
- package/skill/references/postgres.md +50 -0
- package/skill/references/redis.md +53 -0
- package/skill/references/sqlite3.md +43 -0
- package/src/cli/commands/generate.js +95 -31
- package/src/cli/commands/help.js +12 -7
- package/src/cli/commands/init.js +2 -2
- package/src/cli/commands/inspect.js +1 -0
- package/src/cli/diff-engine.js +54 -23
- package/src/cli/generate-db-manager.js +1573 -0
- package/src/cli/generate-docs-route.js +31 -0
- package/src/cli/generate-migration.js +356 -0
- package/src/cli/generate-model.js +9 -4
- package/src/cli/generate-openapi.js +40 -13
- package/src/cli/generate-route.js +55 -27
- package/src/cli/init/dependencies.js +3 -0
- package/src/cli/init/generators.js +37 -31
- package/src/cli/init.js +8 -8
- package/src/cli/main.js +2 -2
- package/src/cockroachdb/db.js +90 -59
- package/src/commons/route.js +20 -20
- package/src/commons/validator.js +58 -1
- package/src/dynamodb/db.js +50 -27
- package/src/mongodb/db.js +1 -0
- package/src/mssql/db.js +89 -61
- package/src/mysql/db.js +1 -0
- package/src/oracle/db.js +1 -0
- package/src/postgres/db.js +61 -41
- package/src/redis/db.js +1 -0
- package/src/schema/schema-parser.js +43 -1
- package/src/schema/schema-printer.js +7 -0
- package/src/schema/schema-validator.js +17 -0
- package/src/sqlite3/db.js +12 -0
- package/docs/SKILL.md +0 -419
- package/src/cli/commands/generate-llm-docs.js +0 -418
package/README.md
CHANGED
|
@@ -14,7 +14,11 @@ Scaffold the project, write the migrations, generate models and routes with pare
|
|
|
14
14
|
relationships for projects.tasks, and make sure everything runs.
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
For the LLM skill reference, see [SKILL.md](./
|
|
17
|
+
For the LLM skill reference, see [SKILL.md](./skill/SKILL.md). You can also add it directly to your AI assistant:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx skills add https://github.com/AvinashSKaranth/db-model-router/skill
|
|
21
|
+
```
|
|
18
22
|
|
|
19
23
|
## Supported Adapters
|
|
20
24
|
|
|
@@ -97,7 +101,31 @@ Instead of running multiple CLI commands manually, you can define your entire pr
|
|
|
97
101
|
|
|
98
102
|
### The Schema File
|
|
99
103
|
|
|
100
|
-
`dbmr.schema.json` is a declarative JSON file that describes your adapter, framework, tables, columns,
|
|
104
|
+
`dbmr.schema.json` is a declarative JSON file that describes your adapter, framework, tables, columns, module hierarchy, and options — all in one place.
|
|
105
|
+
|
|
106
|
+
#### Modules and the `parent` Field
|
|
107
|
+
|
|
108
|
+
Each table in the schema represents a **module**. Modules are either top-level or nested under a parent module using the `parent` field:
|
|
109
|
+
|
|
110
|
+
- `"parent": null` — top-level module, routes mount at `/<table>/`
|
|
111
|
+
- `"parent": "posts"` — child module, routes mount at `/posts/:post_id/comments/:comment_id`
|
|
112
|
+
|
|
113
|
+
When a table has `parent` set, the CLI automatically:
|
|
114
|
+
|
|
115
|
+
1. Creates a child route file scoped by the parent's PK as a URL parameter
|
|
116
|
+
2. Mounts the child routes under the parent path
|
|
117
|
+
3. Also mounts the child as a top-level route for direct access
|
|
118
|
+
|
|
119
|
+
#### Best Practice: Don't Use System Tables as Parents
|
|
120
|
+
|
|
121
|
+
Tables like `users`, `tenants`, `roles`, `permissions`, `sessions`, and `role_permissions` are cross-cutting concerns — they are referenced by almost every feature module via foreign key columns (e.g. `user_id`, `tenant_id`). Making them route parents would nest every feature module under them, which is not the intent.
|
|
122
|
+
|
|
123
|
+
Keep system tables as top-level modules (`"parent": null`) and reference them via FK columns in your feature tables. Only use `parent` for true domain hierarchies like `posts → comments`, `orders → order_items`, or `projects → tasks`.
|
|
124
|
+
|
|
125
|
+
Examples of tables that should stay top-level (not be parents of feature modules):
|
|
126
|
+
`users`, `tenants`, `roles`, `role_permissions`, `permissions`, `sessions`, `accounts`, `auth_tokens`
|
|
127
|
+
|
|
128
|
+
#### Example Schema
|
|
101
129
|
|
|
102
130
|
```json
|
|
103
131
|
{
|
|
@@ -127,7 +155,8 @@ Instead of running multiple CLI commands manually, you can define your entire pr
|
|
|
127
155
|
"timestamps": {
|
|
128
156
|
"created_at": "created_at",
|
|
129
157
|
"modified_at": "updated_at"
|
|
130
|
-
}
|
|
158
|
+
},
|
|
159
|
+
"parent": null
|
|
131
160
|
},
|
|
132
161
|
"posts": {
|
|
133
162
|
"columns": {
|
|
@@ -139,16 +168,35 @@ Instead of running multiple CLI commands manually, you can define your entire pr
|
|
|
139
168
|
"modified_at": "datetime"
|
|
140
169
|
},
|
|
141
170
|
"pk": "post_id",
|
|
142
|
-
"unique": ["post_id"]
|
|
171
|
+
"unique": ["post_id"],
|
|
172
|
+
"parent": null
|
|
173
|
+
},
|
|
174
|
+
"comments": {
|
|
175
|
+
"columns": {
|
|
176
|
+
"comment_id": "auto_increment",
|
|
177
|
+
"post_id": "required|integer",
|
|
178
|
+
"user_id": "required|integer",
|
|
179
|
+
"body": "required|string",
|
|
180
|
+
"created_at": "datetime"
|
|
181
|
+
},
|
|
182
|
+
"pk": "comment_id",
|
|
183
|
+
"unique": ["comment_id"],
|
|
184
|
+
"parent": "posts"
|
|
143
185
|
}
|
|
144
|
-
}
|
|
145
|
-
"relationships": [
|
|
146
|
-
{ "parent": "users", "child": "posts", "foreignKey": "user_id" }
|
|
147
|
-
]
|
|
186
|
+
}
|
|
148
187
|
}
|
|
149
188
|
```
|
|
150
189
|
|
|
151
|
-
|
|
190
|
+
This generates routes:
|
|
191
|
+
|
|
192
|
+
- `GET /users/`, `GET /users/:user_id` — top-level
|
|
193
|
+
- `GET /posts/`, `GET /posts/:post_id` — top-level
|
|
194
|
+
- `GET /posts/:post_id/comments/`, `GET /posts/:post_id/comments/:comment_id` — nested under posts
|
|
195
|
+
- `GET /comments/`, `GET /comments/:comment_id` — also available as top-level
|
|
196
|
+
|
|
197
|
+
Note: `comments` has `user_id` as a foreign key column but `users` is NOT its parent — `posts` is. The `user_id` is just a data reference, not a route hierarchy.
|
|
198
|
+
|
|
199
|
+
#### Table Fields
|
|
152
200
|
|
|
153
201
|
| Field | Required | Description |
|
|
154
202
|
| ------------ | -------- | ------------------------------------------------------------------------ |
|
|
@@ -157,12 +205,23 @@ Table entries support these fields:
|
|
|
157
205
|
| `unique` | No | Array of unique constraint columns (defaults to `[pk]`) |
|
|
158
206
|
| `softDelete` | No | Column name used for soft-delete |
|
|
159
207
|
| `timestamps` | No | Object with `created_at` and `modified_at` column name mapping |
|
|
208
|
+
| `parent` | No | Parent table name for route nesting, or `null` for top-level |
|
|
209
|
+
|
|
210
|
+
#### Column Rules
|
|
160
211
|
|
|
161
|
-
|
|
212
|
+
Format: `(required|)?(string|integer|numeric|boolean|object|datetime|auto_increment)`
|
|
162
213
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
214
|
+
| Type | Description |
|
|
215
|
+
| ---------------- | ------------------------------------------------------------------ |
|
|
216
|
+
| `auto_increment` | Auto-incrementing PK (SERIAL in Postgres, AUTO_INCREMENT in MySQL) |
|
|
217
|
+
| `datetime` | Date/time columns (TIMESTAMP, DATETIME, DATE) |
|
|
218
|
+
| `string` | Text columns (VARCHAR, TEXT, CHAR, UUID) |
|
|
219
|
+
| `integer` | Integer columns (INT, BIGINT, SMALLINT) |
|
|
220
|
+
| `numeric` | Decimal columns (DECIMAL, FLOAT, DOUBLE, MONEY) |
|
|
221
|
+
| `boolean` | Boolean columns (BOOLEAN, BIT) |
|
|
222
|
+
| `object` | JSON columns (JSON, JSONB) |
|
|
223
|
+
|
|
224
|
+
Prefix with `required|` for NOT NULL constraint (e.g. `"required|string"`).
|
|
166
225
|
|
|
167
226
|
### Unified CLI: `db-model-router`
|
|
168
227
|
|
|
@@ -436,7 +495,7 @@ This creates 9 endpoints:
|
|
|
436
495
|
| GET | `/users/` | List with pagination |
|
|
437
496
|
| POST | `/users/` | Bulk insert (`{ data: [...] }`) |
|
|
438
497
|
| PUT | `/users/` | Bulk update (`{ data: [...] }`) |
|
|
439
|
-
| DELETE | `/users/` | Bulk delete
|
|
498
|
+
| DELETE | `/users/` | Bulk delete `{ name: "Bob" }` |
|
|
440
499
|
|
|
441
500
|
### 4. Payload Override
|
|
442
501
|
|
|
@@ -543,7 +602,7 @@ await users.remove({ name: "Bob" });
|
|
|
543
602
|
|
|
544
603
|
Filters use a nested array structure: `[OR_groups[AND_conditions[column, operator, value]]]`
|
|
545
604
|
|
|
546
|
-
Supported operators: `=`, `
|
|
605
|
+
Supported operators: `=`, `!=`, `<`, `>`, `<=`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`
|
|
547
606
|
|
|
548
607
|
```js
|
|
549
608
|
// Find users named Alice OR aged > 30
|
|
@@ -561,6 +620,31 @@ const result = await db.get("users", [
|
|
|
561
620
|
]);
|
|
562
621
|
```
|
|
563
622
|
|
|
623
|
+
### Query Parameter Filter Operators
|
|
624
|
+
|
|
625
|
+
When using `GET /` (list endpoint), query parameters are automatically parsed into filter conditions. Special value prefixes and patterns control the SQL operator used:
|
|
626
|
+
|
|
627
|
+
| Query Param Value | Operator | Example URL | Resulting Filter |
|
|
628
|
+
| ---------------------- | ---------- | ----------------------------- | ------------------------------------ |
|
|
629
|
+
| `value` | `=` | `?name=john` | `name = 'john'` |
|
|
630
|
+
| `!value` | `!=` | `?name=!john` | `name != 'john'` |
|
|
631
|
+
| `>value` | `>` | `?age=>25` | `age > 25` |
|
|
632
|
+
| `>=value` (use `>%3D`) | `>=` | `?age=>%3D25` | `age >= 25` |
|
|
633
|
+
| `<value` | `<` | `?age=<25` | `age < 25` |
|
|
634
|
+
| `<=value` (use `<%3D`) | `<=` | `?age=<%3D25` | `age <= 25` |
|
|
635
|
+
| `%value%` (use `%25`) | `LIKE` | `?name=%25john%25` | `name LIKE '%john%'` |
|
|
636
|
+
| `!%value%` | `NOT LIKE` | `?name=!%25john%25` | `name NOT LIKE '%john%'` |
|
|
637
|
+
| `in(a,b,c)` | `IN` | `?status=in(active,pending)` | `status IN ('active','pending')` |
|
|
638
|
+
| `!in(a,b,c)` | `NOT IN` | `?status=!in(active,pending)` | `status NOT IN ('active','pending')` |
|
|
639
|
+
|
|
640
|
+
**Notes:**
|
|
641
|
+
|
|
642
|
+
- `%` must be URL-encoded as `%25` in query strings. After URL decoding, the `%` character triggers `LIKE` detection.
|
|
643
|
+
- `=` in `>=` and `<=` must be URL-encoded as `%3D` (e.g. `>%3D25` for `>=25`).
|
|
644
|
+
- `LIKE` patterns follow SQL conventions: `%25john%25` → contains "john", `%25john` → ends with "john", `john%25` → starts with "john".
|
|
645
|
+
- `IN` and `NOT IN` values are comma-separated inside parentheses.
|
|
646
|
+
Operators are detected in order of specificity: `!in(...)` → `in(...)` → `!%...%` → `%...%` → `>=` → `<=` → `>` → `<` → `!value` → `=` (default).
|
|
647
|
+
|
|
564
648
|
## Switching Adapters
|
|
565
649
|
|
|
566
650
|
To use a different database, call `init()` before `db.connect()`:
|
|
@@ -617,4 +701,14 @@ Apache-2.0
|
|
|
617
701
|
|
|
618
702
|
## LLM Skill Reference
|
|
619
703
|
|
|
620
|
-
For AI/LLM integration, see the [Skill Reference](./
|
|
704
|
+
For AI/LLM integration, see the [Skill Reference](./skill/SKILL.md) — a structured document covering the full API surface, patterns, constraints, and connection configs for all adapters.
|
|
705
|
+
|
|
706
|
+
### Add the Skill to Your AI Assistant
|
|
707
|
+
|
|
708
|
+
You can install the db-model-router skill directly into any compatible AI assistant using:
|
|
709
|
+
|
|
710
|
+
```bash
|
|
711
|
+
npx skills add https://github.com/AvinashSKaranth/db-model-router/skill
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
Once installed, your AI assistant will automatically know how to scaffold projects, generate models and routes, write migrations, and work with all 10 supported database adapters.
|
package/TODO.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
in generate --db-manager should generate
|
|
2
|
+
DB manager using ejs db manager in the generated codebase (dark theme)
|
|
3
|
+
There is login page with just password -> Needs to login status in session (req.session["db-manager"])
|
|
4
|
+
the password will be in .env as DATABASE_MANAGER_PASSWORD
|
|
5
|
+
Then db manager page
|
|
6
|
+
Left sidebar will have list of tables with local search
|
|
7
|
+
Main page will have 3 tabs
|
|
8
|
+
|
|
9
|
+
1. Table Structure
|
|
10
|
+
2. Data top 30 rows with filter,sort,pagenation
|
|
11
|
+
3. Query page where user can type the raw query
|
|
12
|
+
This needs to added in route like /database
|
|
13
|
+
|
|
14
|
+
The api that this will use is POST /database/login, GET /database/tables, GET /database/tables/:table_name?sort=1&size=30&post_name=%title%
|
|
15
|
+
the UI should be able to filter,sort and move through the pages
|
package/dbmr.schema.json
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adapter": "sqlite3",
|
|
3
|
+
"framework": "express",
|
|
4
|
+
"options": {
|
|
5
|
+
"session": "memory",
|
|
6
|
+
"rateLimiting": true,
|
|
7
|
+
"helmet": true,
|
|
8
|
+
"logger": true,
|
|
9
|
+
"loki": false
|
|
10
|
+
},
|
|
11
|
+
"tables": {
|
|
12
|
+
"users": {
|
|
13
|
+
"columns": {
|
|
14
|
+
"user_id": "auto_increment",
|
|
15
|
+
"name": "required|string",
|
|
16
|
+
"email": "required|string",
|
|
17
|
+
"password_hash": "required|string",
|
|
18
|
+
"phone": "string",
|
|
19
|
+
"avatar_url": "string",
|
|
20
|
+
"role": "required|string",
|
|
21
|
+
"is_deleted": "boolean",
|
|
22
|
+
"created_at": "datetime",
|
|
23
|
+
"updated_at": "datetime"
|
|
24
|
+
},
|
|
25
|
+
"pk": "user_id",
|
|
26
|
+
"unique": ["email"],
|
|
27
|
+
"softDelete": "is_deleted",
|
|
28
|
+
"timestamps": {
|
|
29
|
+
"created_at": "created_at",
|
|
30
|
+
"modified_at": "updated_at"
|
|
31
|
+
},
|
|
32
|
+
"parent": null
|
|
33
|
+
},
|
|
34
|
+
"addresses": {
|
|
35
|
+
"columns": {
|
|
36
|
+
"address_id": "auto_increment",
|
|
37
|
+
"user_id": "required|integer",
|
|
38
|
+
"label": "string",
|
|
39
|
+
"line1": "required|string",
|
|
40
|
+
"line2": "string",
|
|
41
|
+
"city": "required|string",
|
|
42
|
+
"state": "required|string",
|
|
43
|
+
"postal_code": "required|string",
|
|
44
|
+
"country": "required|string",
|
|
45
|
+
"is_default": "boolean",
|
|
46
|
+
"created_at": "datetime",
|
|
47
|
+
"updated_at": "datetime"
|
|
48
|
+
},
|
|
49
|
+
"pk": "address_id",
|
|
50
|
+
"unique": ["address_id"],
|
|
51
|
+
"timestamps": {
|
|
52
|
+
"created_at": "created_at",
|
|
53
|
+
"modified_at": "updated_at"
|
|
54
|
+
},
|
|
55
|
+
"parent": null
|
|
56
|
+
},
|
|
57
|
+
"categories": {
|
|
58
|
+
"columns": {
|
|
59
|
+
"category_id": "auto_increment",
|
|
60
|
+
"name": "required|string",
|
|
61
|
+
"slug": "required|string",
|
|
62
|
+
"description": "string",
|
|
63
|
+
"parent_category_id": "integer",
|
|
64
|
+
"image_url": "string",
|
|
65
|
+
"sort_order": "integer",
|
|
66
|
+
"is_active": "boolean",
|
|
67
|
+
"created_at": "datetime",
|
|
68
|
+
"updated_at": "datetime"
|
|
69
|
+
},
|
|
70
|
+
"pk": "category_id",
|
|
71
|
+
"unique": ["slug"],
|
|
72
|
+
"timestamps": {
|
|
73
|
+
"created_at": "created_at",
|
|
74
|
+
"modified_at": "updated_at"
|
|
75
|
+
},
|
|
76
|
+
"parent": null
|
|
77
|
+
},
|
|
78
|
+
"products": {
|
|
79
|
+
"columns": {
|
|
80
|
+
"product_id": "auto_increment",
|
|
81
|
+
"category_id": "required|integer",
|
|
82
|
+
"name": "required|string",
|
|
83
|
+
"slug": "required|string",
|
|
84
|
+
"description": "string",
|
|
85
|
+
"short_description": "string",
|
|
86
|
+
"sku": "required|string",
|
|
87
|
+
"price": "required|numeric",
|
|
88
|
+
"compare_at_price": "numeric",
|
|
89
|
+
"cost_price": "numeric",
|
|
90
|
+
"currency": "required|string",
|
|
91
|
+
"stock_quantity": "required|integer",
|
|
92
|
+
"low_stock_threshold": "integer",
|
|
93
|
+
"weight": "numeric",
|
|
94
|
+
"weight_unit": "string",
|
|
95
|
+
"is_active": "boolean",
|
|
96
|
+
"is_featured": "boolean",
|
|
97
|
+
"is_deleted": "boolean",
|
|
98
|
+
"meta": "object",
|
|
99
|
+
"created_at": "datetime",
|
|
100
|
+
"updated_at": "datetime"
|
|
101
|
+
},
|
|
102
|
+
"pk": "product_id",
|
|
103
|
+
"unique": ["sku", "slug"],
|
|
104
|
+
"softDelete": "is_deleted",
|
|
105
|
+
"timestamps": {
|
|
106
|
+
"created_at": "created_at",
|
|
107
|
+
"modified_at": "updated_at"
|
|
108
|
+
},
|
|
109
|
+
"parent": null
|
|
110
|
+
},
|
|
111
|
+
"product_images": {
|
|
112
|
+
"columns": {
|
|
113
|
+
"product_image_id": "auto_increment",
|
|
114
|
+
"product_id": "required|integer",
|
|
115
|
+
"url": "required|string",
|
|
116
|
+
"alt_text": "string",
|
|
117
|
+
"sort_order": "integer",
|
|
118
|
+
"is_primary": "boolean",
|
|
119
|
+
"created_at": "datetime"
|
|
120
|
+
},
|
|
121
|
+
"pk": "product_image_id",
|
|
122
|
+
"unique": ["product_image_id"],
|
|
123
|
+
"timestamps": {
|
|
124
|
+
"created_at": "created_at"
|
|
125
|
+
},
|
|
126
|
+
"parent": "products"
|
|
127
|
+
},
|
|
128
|
+
"product_variants": {
|
|
129
|
+
"columns": {
|
|
130
|
+
"variant_id": "auto_increment",
|
|
131
|
+
"product_id": "required|integer",
|
|
132
|
+
"name": "required|string",
|
|
133
|
+
"sku": "required|string",
|
|
134
|
+
"price": "required|numeric",
|
|
135
|
+
"stock_quantity": "required|integer",
|
|
136
|
+
"attributes": "object",
|
|
137
|
+
"is_active": "boolean",
|
|
138
|
+
"created_at": "datetime",
|
|
139
|
+
"updated_at": "datetime"
|
|
140
|
+
},
|
|
141
|
+
"pk": "variant_id",
|
|
142
|
+
"unique": ["sku"],
|
|
143
|
+
"timestamps": {
|
|
144
|
+
"created_at": "created_at",
|
|
145
|
+
"modified_at": "updated_at"
|
|
146
|
+
},
|
|
147
|
+
"parent": "products"
|
|
148
|
+
},
|
|
149
|
+
"product_reviews": {
|
|
150
|
+
"columns": {
|
|
151
|
+
"review_id": "auto_increment",
|
|
152
|
+
"product_id": "required|integer",
|
|
153
|
+
"user_id": "required|integer",
|
|
154
|
+
"rating": "required|integer",
|
|
155
|
+
"title": "string",
|
|
156
|
+
"body": "string",
|
|
157
|
+
"is_verified": "boolean",
|
|
158
|
+
"is_approved": "boolean",
|
|
159
|
+
"created_at": "datetime",
|
|
160
|
+
"updated_at": "datetime"
|
|
161
|
+
},
|
|
162
|
+
"pk": "review_id",
|
|
163
|
+
"unique": ["review_id"],
|
|
164
|
+
"timestamps": {
|
|
165
|
+
"created_at": "created_at",
|
|
166
|
+
"modified_at": "updated_at"
|
|
167
|
+
},
|
|
168
|
+
"parent": "products"
|
|
169
|
+
},
|
|
170
|
+
"carts": {
|
|
171
|
+
"columns": {
|
|
172
|
+
"cart_id": "auto_increment",
|
|
173
|
+
"user_id": "integer",
|
|
174
|
+
"session_id": "string",
|
|
175
|
+
"currency": "required|string",
|
|
176
|
+
"created_at": "datetime",
|
|
177
|
+
"updated_at": "datetime"
|
|
178
|
+
},
|
|
179
|
+
"pk": "cart_id",
|
|
180
|
+
"unique": ["cart_id"],
|
|
181
|
+
"timestamps": {
|
|
182
|
+
"created_at": "created_at",
|
|
183
|
+
"modified_at": "updated_at"
|
|
184
|
+
},
|
|
185
|
+
"parent": null
|
|
186
|
+
},
|
|
187
|
+
"cart_items": {
|
|
188
|
+
"columns": {
|
|
189
|
+
"cart_item_id": "auto_increment",
|
|
190
|
+
"cart_id": "required|integer",
|
|
191
|
+
"product_id": "required|integer",
|
|
192
|
+
"variant_id": "integer",
|
|
193
|
+
"quantity": "required|integer",
|
|
194
|
+
"unit_price": "required|numeric",
|
|
195
|
+
"created_at": "datetime",
|
|
196
|
+
"updated_at": "datetime"
|
|
197
|
+
},
|
|
198
|
+
"pk": "cart_item_id",
|
|
199
|
+
"unique": ["cart_item_id"],
|
|
200
|
+
"timestamps": {
|
|
201
|
+
"created_at": "created_at",
|
|
202
|
+
"modified_at": "updated_at"
|
|
203
|
+
},
|
|
204
|
+
"parent": "carts"
|
|
205
|
+
},
|
|
206
|
+
"orders": {
|
|
207
|
+
"columns": {
|
|
208
|
+
"order_id": "auto_increment",
|
|
209
|
+
"user_id": "required|integer",
|
|
210
|
+
"order_number": "required|string",
|
|
211
|
+
"status": "required|string",
|
|
212
|
+
"subtotal": "required|numeric",
|
|
213
|
+
"tax_amount": "required|numeric",
|
|
214
|
+
"shipping_amount": "required|numeric",
|
|
215
|
+
"discount_amount": "numeric",
|
|
216
|
+
"total": "required|numeric",
|
|
217
|
+
"currency": "required|string",
|
|
218
|
+
"shipping_address_id": "integer",
|
|
219
|
+
"billing_address_id": "integer",
|
|
220
|
+
"notes": "string",
|
|
221
|
+
"created_at": "datetime",
|
|
222
|
+
"updated_at": "datetime"
|
|
223
|
+
},
|
|
224
|
+
"pk": "order_id",
|
|
225
|
+
"unique": ["order_number"],
|
|
226
|
+
"timestamps": {
|
|
227
|
+
"created_at": "created_at",
|
|
228
|
+
"modified_at": "updated_at"
|
|
229
|
+
},
|
|
230
|
+
"parent": null
|
|
231
|
+
},
|
|
232
|
+
"order_items": {
|
|
233
|
+
"columns": {
|
|
234
|
+
"order_item_id": "auto_increment",
|
|
235
|
+
"order_id": "required|integer",
|
|
236
|
+
"product_id": "required|integer",
|
|
237
|
+
"variant_id": "integer",
|
|
238
|
+
"product_name": "required|string",
|
|
239
|
+
"sku": "required|string",
|
|
240
|
+
"quantity": "required|integer",
|
|
241
|
+
"unit_price": "required|numeric",
|
|
242
|
+
"total_price": "required|numeric",
|
|
243
|
+
"created_at": "datetime"
|
|
244
|
+
},
|
|
245
|
+
"pk": "order_item_id",
|
|
246
|
+
"unique": ["order_item_id"],
|
|
247
|
+
"timestamps": {
|
|
248
|
+
"created_at": "created_at"
|
|
249
|
+
},
|
|
250
|
+
"parent": "orders"
|
|
251
|
+
},
|
|
252
|
+
"payments": {
|
|
253
|
+
"columns": {
|
|
254
|
+
"payment_id": "auto_increment",
|
|
255
|
+
"order_id": "required|integer",
|
|
256
|
+
"method": "required|string",
|
|
257
|
+
"provider": "string",
|
|
258
|
+
"provider_transaction_id": "string",
|
|
259
|
+
"amount": "required|numeric",
|
|
260
|
+
"currency": "required|string",
|
|
261
|
+
"status": "required|string",
|
|
262
|
+
"paid_at": "datetime",
|
|
263
|
+
"created_at": "datetime",
|
|
264
|
+
"updated_at": "datetime"
|
|
265
|
+
},
|
|
266
|
+
"pk": "payment_id",
|
|
267
|
+
"unique": ["payment_id"],
|
|
268
|
+
"timestamps": {
|
|
269
|
+
"created_at": "created_at",
|
|
270
|
+
"modified_at": "updated_at"
|
|
271
|
+
},
|
|
272
|
+
"parent": "orders"
|
|
273
|
+
},
|
|
274
|
+
"shipments": {
|
|
275
|
+
"columns": {
|
|
276
|
+
"shipment_id": "auto_increment",
|
|
277
|
+
"order_id": "required|integer",
|
|
278
|
+
"carrier": "required|string",
|
|
279
|
+
"tracking_number": "string",
|
|
280
|
+
"status": "required|string",
|
|
281
|
+
"shipped_at": "datetime",
|
|
282
|
+
"delivered_at": "datetime",
|
|
283
|
+
"created_at": "datetime",
|
|
284
|
+
"updated_at": "datetime"
|
|
285
|
+
},
|
|
286
|
+
"pk": "shipment_id",
|
|
287
|
+
"unique": ["shipment_id"],
|
|
288
|
+
"timestamps": {
|
|
289
|
+
"created_at": "created_at",
|
|
290
|
+
"modified_at": "updated_at"
|
|
291
|
+
},
|
|
292
|
+
"parent": "orders"
|
|
293
|
+
},
|
|
294
|
+
"coupons": {
|
|
295
|
+
"columns": {
|
|
296
|
+
"coupon_id": "auto_increment",
|
|
297
|
+
"code": "required|string",
|
|
298
|
+
"description": "string",
|
|
299
|
+
"discount_type": "required|string",
|
|
300
|
+
"discount_value": "required|numeric",
|
|
301
|
+
"min_order_amount": "numeric",
|
|
302
|
+
"max_uses": "integer",
|
|
303
|
+
"used_count": "integer",
|
|
304
|
+
"starts_at": "datetime",
|
|
305
|
+
"expires_at": "datetime",
|
|
306
|
+
"is_active": "boolean",
|
|
307
|
+
"created_at": "datetime",
|
|
308
|
+
"updated_at": "datetime"
|
|
309
|
+
},
|
|
310
|
+
"pk": "coupon_id",
|
|
311
|
+
"unique": ["code"],
|
|
312
|
+
"timestamps": {
|
|
313
|
+
"created_at": "created_at",
|
|
314
|
+
"modified_at": "updated_at"
|
|
315
|
+
},
|
|
316
|
+
"parent": null
|
|
317
|
+
},
|
|
318
|
+
"wishlists": {
|
|
319
|
+
"columns": {
|
|
320
|
+
"wishlist_id": "auto_increment",
|
|
321
|
+
"user_id": "required|integer",
|
|
322
|
+
"product_id": "required|integer",
|
|
323
|
+
"created_at": "datetime"
|
|
324
|
+
},
|
|
325
|
+
"pk": "wishlist_id",
|
|
326
|
+
"unique": ["wishlist_id"],
|
|
327
|
+
"timestamps": {
|
|
328
|
+
"created_at": "created_at"
|
|
329
|
+
},
|
|
330
|
+
"parent": null
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
package/docker-compose.yml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "db-model-router",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Generative API Creation using mysql2 and express libraries in node js",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"test:mssql": "dotenv -e env/.env.mssql -- mocha test/adapters/mssql.*.test.js --timeout 30000 --exit",
|
|
21
21
|
"test:properties": "mocha test/properties/*.property.test.js --timeout 30000 --exit",
|
|
22
22
|
"test:all": "mocha test/adapters/*.test.js test/properties/*.property.test.js test/function.test.js --timeout 30000 --exit",
|
|
23
|
-
"
|
|
23
|
+
"demo:clear": "node -e \"var fs=require('fs'),p=require('path'),d=p.join(__dirname,'demo');fs.existsSync(d)&&fs.rmSync(d,{recursive:true,force:true});fs.mkdirSync(d,{recursive:true})\"",
|
|
24
|
+
"demo:create": "node scripts/demo-create.js"
|
|
24
25
|
},
|
|
25
26
|
"repository": {
|
|
26
27
|
"type": "git",
|
|
@@ -54,14 +55,14 @@
|
|
|
54
55
|
"node-input-validator": "^4.5.0"
|
|
55
56
|
},
|
|
56
57
|
"peerDependencies": {
|
|
57
|
-
"@aws-sdk/client-dynamodb": "^3.
|
|
58
|
-
"@aws-sdk/lib-dynamodb": "^3.
|
|
58
|
+
"@aws-sdk/client-dynamodb": "^3.1039.0",
|
|
59
|
+
"@aws-sdk/lib-dynamodb": "^3.1039.0",
|
|
59
60
|
"better-sqlite3": "^12.9.0",
|
|
60
61
|
"express": "^4.17.2 || ^5.0.0",
|
|
61
62
|
"ioredis": "^5.10.1",
|
|
62
|
-
"mongodb": "^7.
|
|
63
|
-
"mssql": "^12.
|
|
64
|
-
"mysql2": "^3.
|
|
63
|
+
"mongodb": "^7.2.0",
|
|
64
|
+
"mssql": "^12.5.0",
|
|
65
|
+
"mysql2": "^3.22.3",
|
|
65
66
|
"oracledb": "^6.10.0",
|
|
66
67
|
"pg": "^8.20.0",
|
|
67
68
|
"ultimate-express": "^2.0.0"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const { execSync } = require("child_process");
|
|
7
|
+
|
|
8
|
+
const ROOT = path.resolve(__dirname, "..");
|
|
9
|
+
const DEMO = path.join(ROOT, "demo");
|
|
10
|
+
|
|
11
|
+
// 1. Clear demo folder
|
|
12
|
+
if (fs.existsSync(DEMO)) {
|
|
13
|
+
fs.rmSync(DEMO, { recursive: true, force: true });
|
|
14
|
+
}
|
|
15
|
+
fs.mkdirSync(DEMO, { recursive: true });
|
|
16
|
+
|
|
17
|
+
const run = (cmd, cwd) => {
|
|
18
|
+
console.log(`\n> ${cmd}`);
|
|
19
|
+
execSync(cmd, { cwd, stdio: "inherit" });
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// 2. Scaffold project with sqlite3
|
|
23
|
+
run("node ../src/cli/main.js init --database sqlite3 --yes --no-install", DEMO);
|
|
24
|
+
|
|
25
|
+
// 3. Copy schema and patch adapter to sqlite3
|
|
26
|
+
const schema = JSON.parse(
|
|
27
|
+
fs.readFileSync(path.join(ROOT, "dbmr.schema.json"), "utf8"),
|
|
28
|
+
);
|
|
29
|
+
schema.adapter = "sqlite3";
|
|
30
|
+
if (schema.options) {
|
|
31
|
+
delete schema.options.session;
|
|
32
|
+
delete schema.options.loki;
|
|
33
|
+
}
|
|
34
|
+
fs.writeFileSync(
|
|
35
|
+
path.join(DEMO, "dbmr.schema.json"),
|
|
36
|
+
JSON.stringify(schema, null, 2) + "\n",
|
|
37
|
+
);
|
|
38
|
+
console.log("\n> Copied and patched dbmr.schema.json (adapter → sqlite3)");
|
|
39
|
+
|
|
40
|
+
// 4. Generate models, routes, tests, openapi from schema
|
|
41
|
+
run("node ../src/cli/main.js generate --from dbmr.schema.json", DEMO);
|
|
42
|
+
|
|
43
|
+
// 5. Install dependencies
|
|
44
|
+
run("npm install", DEMO);
|
|
45
|
+
|
|
46
|
+
console.log("\n✔ Demo project ready in ./demo");
|
|
47
|
+
console.log(" cd demo && npm run dev\n");
|