db-model-router 1.0.3 → 1.0.4

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 CHANGED
@@ -21,6 +21,7 @@ For the LLM skill reference, see [SKILL.md](./docs/SKILL.md).
21
21
  | Adapter | Module Key | Driver | Install |
22
22
  | --------------------------------------------- | ------------- | ------------------------ | ---------------------------------------------------------------------- |
23
23
  | [MySQL](#mysql-example) | `mysql` | mysql2 | `npm i db-model-router mysql2` |
24
+ | MariaDB | `mariadb` | mysql2 | `npm i db-model-router mysql2` |
24
25
  | [PostgreSQL](./docs/adapters/postgres.md) | `postgres` | pg | `npm i db-model-router pg` |
25
26
  | [SQLite3](./docs/adapters/sqlite3.md) | `sqlite3` | better-sqlite3 | `npm i db-model-router better-sqlite3` |
26
27
  | [MongoDB](./docs/adapters/mongodb.md) | `mongodb` | mongodb | `npm i db-model-router mongodb` |
@@ -106,17 +107,21 @@ Instead of running multiple CLI commands manually, you can define your entire pr
106
107
  "session": "redis",
107
108
  "rateLimiting": true,
108
109
  "helmet": true,
109
- "logger": true
110
+ "logger": true,
111
+ "loki": false
110
112
  },
111
113
  "tables": {
112
114
  "users": {
113
115
  "columns": {
116
+ "user_id": "auto_increment",
114
117
  "name": "required|string",
115
118
  "email": "required|string",
116
119
  "age": "integer",
117
- "is_deleted": "boolean"
120
+ "is_deleted": "boolean",
121
+ "created_at": "datetime",
122
+ "updated_at": "datetime"
118
123
  },
119
- "pk": "id",
124
+ "pk": "user_id",
120
125
  "unique": ["email"],
121
126
  "softDelete": "is_deleted",
122
127
  "timestamps": {
@@ -126,12 +131,15 @@ Instead of running multiple CLI commands manually, you can define your entire pr
126
131
  },
127
132
  "posts": {
128
133
  "columns": {
134
+ "post_id": "auto_increment",
129
135
  "title": "required|string",
130
136
  "body": "string",
131
- "user_id": "required|integer"
137
+ "user_id": "required|integer",
138
+ "created_at": "datetime",
139
+ "modified_at": "datetime"
132
140
  },
133
- "pk": "id",
134
- "unique": ["id"]
141
+ "pk": "post_id",
142
+ "unique": ["post_id"]
135
143
  }
136
144
  },
137
145
  "relationships": [
@@ -142,15 +150,19 @@ Instead of running multiple CLI commands manually, you can define your entire pr
142
150
 
143
151
  Table entries support these fields:
144
152
 
145
- | Field | Required | Description |
146
- | ------------ | -------- | -------------------------------------------------------------- |
147
- | `columns` | Yes | Object mapping column names to Column_Rule strings |
148
- | `pk` | No | Primary key column name (defaults to `"id"`) |
149
- | `unique` | No | Array of unique constraint columns (defaults to `[pk]`) |
150
- | `softDelete` | No | Column name used for soft-delete |
151
- | `timestamps` | No | Object with `created_at` and `modified_at` column name mapping |
153
+ | Field | Required | Description |
154
+ | ------------ | -------- | ------------------------------------------------------------------------ |
155
+ | `columns` | Yes | Object mapping column names to Column_Rule strings (include ALL columns) |
156
+ | `pk` | Yes | Primary key column name (convention: `<table>_id`) |
157
+ | `unique` | No | Array of unique constraint columns (defaults to `[pk]`) |
158
+ | `softDelete` | No | Column name used for soft-delete |
159
+ | `timestamps` | No | Object with `created_at` and `modified_at` column name mapping |
152
160
 
153
- Column rules use the format `(required|)?(string|integer|numeric|boolean|object)` — e.g. `"required|string"`, `"integer"`, `"object"`.
161
+ Column rules use the format `(required|)?(string|integer|numeric|boolean|object|datetime|auto_increment)`.
162
+
163
+ - `auto_increment` — auto-incrementing PK (SERIAL in Postgres, AUTO_INCREMENT in MySQL/MariaDB)
164
+ - `datetime` — date/time columns (TIMESTAMP, DATETIME, DATE)
165
+ - `required|<type>` — NOT NULL constraint on insert/update
154
166
 
155
167
  ### Unified CLI: `db-model-router`
156
168
 
@@ -206,6 +218,158 @@ db-model-router init --from dbmr.schema.json --yes --no-install
206
218
  db-model-router generate --from dbmr.schema.json
207
219
  ```
208
220
 
221
+ ### Command Reference
222
+
223
+ #### `init`
224
+
225
+ Scaffold a new project from a schema file or interactively. Generates an ESM-based project (`"type": "module"` in package.json) with Docker support.
226
+
227
+ | Flag / Arg | Description |
228
+ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
229
+ | `--from <path>` | Read adapter, framework, and options from a `dbmr.schema.json` file |
230
+ | `--framework <name>` | Express framework: `express` or `ultimate-express` |
231
+ | `--database <name>` | Database adapter: `mysql`, `mariadb`, `postgres`, `sqlite3`, `mongodb`, `mssql`, `cockroachdb`, `oracle`, `redis`, `dynamodb` |
232
+ | `--db <name>` | Alias for `--database` |
233
+ | `--session <type>` | Session store: `memory`, `redis`, `database` |
234
+ | `--output <dir>` | Directory for backend source files (relative to cwd). `package.json` and `app.js` stay in root; `commons/`, `route/`, `middleware/`, `migrations/` go inside this folder. |
235
+ | `--rateLimiting` | Enable rate limiting via `express-rate-limit` (default: yes) |
236
+ | `--helmet` | Enable Helmet security headers (default: yes) |
237
+ | `--logger` | Enable Winston request logger (default: yes) |
238
+ | `--loki` | Enable Grafana Loki log transport + Loki/Grafana in docker-compose (default: no, only asked when `--logger` is enabled) |
239
+
240
+ ```bash
241
+ # Non-interactive with output directory
242
+ db-model-router init --framework express --database postgres --output backend --yes
243
+
244
+ # With Loki logging
245
+ db-model-router init --database postgres --logger --loki --yes
246
+
247
+ # From schema, skip install
248
+ db-model-router init --from dbmr.schema.json --yes --no-install
249
+
250
+ # Dry run to preview files
251
+ db-model-router init --from dbmr.schema.json --dry-run
252
+ ```
253
+
254
+ Generated project structure (with `--output backend`):
255
+
256
+ ```
257
+ ├── package.json # root (type: "module")
258
+ ├── app.js # ESM entry point
259
+ ├── .env / .env.example
260
+ ├── .gitignore
261
+ ├── Dockerfile # node:alpine production image
262
+ ├── .dockerignore
263
+ ├── docker-compose.yml # database + CloudBeaver + optional Loki/Grafana
264
+ ├── .cloudbeaver/
265
+ │ └── data-sources.json # auto-connects CloudBeaver to your DB
266
+ ├── .grafana/ # (only when --loki)
267
+ │ └── datasources.yml # auto-connects Grafana to Loki
268
+ └── backend/
269
+ ├── commons/
270
+ │ ├── db.js # database init, connect, global.db
271
+ │ ├── session.js # session configuration
272
+ │ ├── security.js # helmet, rate limiting, custom headers
273
+ │ ├── migrate.js # migration runner (importable + standalone script)
274
+ │ └── add_migration.js # migration creator (importable + standalone script)
275
+ ├── middleware/
276
+ │ └── logger.js # Winston logger (+ Loki transport when LOKI_HOST is set)
277
+ ├── route/
278
+ │ ├── index.js # central route mounting
279
+ │ └── health.js # GET /health with DB connectivity check
280
+ └── migrations/
281
+ └── <timestamp>_create_migrations_table.sql
282
+ ```
283
+
284
+ Docker services included automatically:
285
+
286
+ | Service | When | Port | Description |
287
+ | ----------- | ------------------------------------- | ------ | -------------------------------------- |
288
+ | Database | Always (except sqlite3) | Varies | Selected database with random password |
289
+ | Redis | `--session redis` (if DB isn't redis) | 6379 | Session store |
290
+ | CloudBeaver | SQL/MongoDB databases | 8978 | Web-based DB admin, auto-connected |
291
+ | Loki | `--loki` | 3100 | Log aggregation |
292
+ | Grafana | `--loki` | 3001 | Log visualization, Loki pre-configured |
293
+
294
+ npm scripts added: `start`, `dev`, `test`, `migrate`, `add_migration`, `docker:build`, `docker:up`, `docker:down`.
295
+
296
+ #### `inspect`
297
+
298
+ Introspect a live database and produce a `dbmr.schema.json` file.
299
+
300
+ | Flag / Arg | Description |
301
+ | ------------------ | ---------------------------------------------------------------------------------------------------------------------- |
302
+ | `--type <adapter>` | Database adapter to introspect (required): `mysql`, `mariadb`, `postgres`, `sqlite3`, `mssql`, `oracle`, `cockroachdb` |
303
+ | `--env <path>` | Path to `.env` file for database connection parameters |
304
+ | `--out <path>` | Output file path (default: `dbmr.schema.json`) |
305
+ | `--tables <list>` | Comma-separated list of tables to include (omit for all) |
306
+
307
+ ```bash
308
+ db-model-router inspect --type postgres --env .env
309
+ db-model-router inspect --type sqlite3 --out schema.json --tables users,posts
310
+ db-model-router inspect --type mysql --json
311
+ ```
312
+
313
+ #### `generate`
314
+
315
+ Generate models, routes, tests, OpenAPI spec, and LLM docs from a schema file. All generated code is ESM (`import`/`export`).
316
+
317
+ | Flag / Arg | Description |
318
+ | --------------- | ------------------------------------------------------------ |
319
+ | `--from <path>` | Path to schema file (default: `dbmr.schema.json`) |
320
+ | `--models` | Generate only model files |
321
+ | `--routes` | Generate only route files (including child routes and index) |
322
+ | `--openapi` | Generate only OpenAPI spec |
323
+ | `--tests` | Generate only test files |
324
+ | `--llm-docs` | Generate only LLM documentation (`llms.txt` + `docs/llm.md`) |
325
+
326
+ When no artifact flags are provided, all artifact types are generated.
327
+
328
+ ```bash
329
+ db-model-router generate --from dbmr.schema.json
330
+ db-model-router generate --models --dry-run
331
+ db-model-router generate --routes --tests
332
+ db-model-router generate --from dbmr.schema.json --json
333
+ ```
334
+
335
+ #### `doctor`
336
+
337
+ Validate schema, check adapter driver dependencies, and verify generated files are in sync.
338
+
339
+ | Flag / Arg | Description |
340
+ | --------------- | ------------------------------------------------- |
341
+ | `--from <path>` | Path to schema file (default: `dbmr.schema.json`) |
342
+
343
+ ```bash
344
+ db-model-router doctor --from dbmr.schema.json
345
+ db-model-router doctor --json
346
+ ```
347
+
348
+ Reports three checks: schema validation, dependency check, sync check.
349
+
350
+ #### `diff`
351
+
352
+ Preview changes between the current generated files and what the schema would produce. Read-only.
353
+
354
+ | Flag / Arg | Description |
355
+ | --------------- | ------------------------------------------------- |
356
+ | `--from <path>` | Path to schema file (default: `dbmr.schema.json`) |
357
+
358
+ ```bash
359
+ db-model-router diff --from dbmr.schema.json
360
+ db-model-router diff --json
361
+ ```
362
+
363
+ #### `help`
364
+
365
+ Show help for any command.
366
+
367
+ ```bash
368
+ db-model-router help # general overview with per-command flags
369
+ db-model-router help init # detailed help for init
370
+ db-model-router init --help # same as above
371
+ ```
372
+
209
373
  ## MySQL Example
210
374
 
211
375
  ### 1. Connect
package/docs/SKILL.md CHANGED
@@ -1,21 +1,22 @@
1
1
  ---
2
2
  name: db-model-router
3
- description: Database-agnostic REST API generator for Node.js/Express. Define model → get CRUD API + Express routes. 9 adapters, identical API. Works with express or ultimate-express.
3
+ description: Database-agnostic REST API generator for Node.js/Express. Define model → get CRUD API + Express routes. 10 adapters, identical API. Works with express or ultimate-express.
4
4
  ---
5
5
 
6
6
  # db-model-router — LLM Skill Reference
7
7
 
8
- Database-agnostic REST API generator for Node.js/Express. Define model → get CRUD API + Express routes. 9 adapters, identical API. Works with `express` or `ultimate-express`.
8
+ Database-agnostic REST API generator for Node.js/Express. Define model → get CRUD API + Express routes. 10 adapters, identical API. Works with `express` or `ultimate-express`. Generated projects use ESM (`import`/`export`).
9
9
 
10
10
  ## LLM Workflow (follow this order)
11
11
 
12
- 1. **Scaffold**: `db-model-router-init --framework express --database postgres --session redis --rateLimiting --helmet --logger` (all flags → zero prompts)
13
- 2. **Migrations**: Write SQL/JS migration files into `migrations/` for the user's schema, then `npm run migrate`
14
- 3. **Generate models**: `db-model-router-generate-model --type postgres --env .env --output ./models`
15
- 4. **Generate routes + tests**: `db-model-router-generate-route --models ./models --output ./routes --tables users,posts,posts.comments`
16
- 5. **Run**: `npm run dev`
12
+ 1. **Scaffold**: `db-model-router init --framework express --database postgres --session redis --rateLimiting --helmet --logger --yes` (all flags → zero prompts)
13
+ 2. **Start infra**: `npm run docker:up` (starts DB + CloudBeaver + optional Loki/Grafana)
14
+ 3. **Migrations**: Write SQL/JS migration files into `migrations/`, then `npm run migrate`
15
+ 4. **Generate models**: `db-model-router generate --from dbmr.schema.json --models`
16
+ 5. **Generate routes + tests**: `db-model-router generate --from dbmr.schema.json --routes --tests`
17
+ 6. **Run**: `npm run dev`
17
18
 
18
- Step 1 creates the project. Step 2 defines the schema. Steps 3-4 introspect the DB and generate models, routes, tests, and OpenAPI spec. Step 5 starts the server.
19
+ Step 1 creates the project with ESM, Docker, and all infrastructure. Step 2 starts containers. Steps 3-5 define schema and generate code. Step 6 starts the server.
19
20
 
20
21
  ## Install
21
22
 
@@ -31,6 +32,7 @@ Drivers: `mysql2`, `pg`, `better-sqlite3`, `mongodb`, `mssql`, `oracledb`, `iore
31
32
  | Module Key | Driver | Default Port |
32
33
  | ------------- | ------------------------------------------------ | ------------ |
33
34
  | `mysql` | mysql2 | 3306 |
35
+ | `mariadb` | mysql2 | 3306 |
34
36
  | `postgres` | pg | 5432 |
35
37
  | `sqlite3` | better-sqlite3 | — |
36
38
  | `mongodb` | mongodb | 27017 |
@@ -72,12 +74,12 @@ app.use("/users", route(users));
72
74
 
73
75
  ## model(db, table, structure, pk, unique, option)
74
76
 
75
- | Param | Type | Description |
76
- | --------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------ |
77
- | structure | `{col: "rule"}` | Types: `string\|integer\|numeric\|boolean\|object`. Prefix `required\|` for NOT NULL. Exclude PK, timestamps, soft-delete cols |
78
- | pk | string | Primary key column. Default `"id"` |
79
- | unique | string[] | Columns for upsert conflict resolution |
80
- | option | object | `{ safeDelete, created_at, modified_at }` — column names or null |
77
+ | Param | Type | Description |
78
+ | --------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
79
+ | structure | `{col: "rule"}` | Types: `string\|integer\|numeric\|boolean\|object\|datetime\|auto_increment`. Prefix `required\|` for NOT NULL. PK, timestamps, soft-delete cols are auto-excluded by the code generator |
80
+ | pk | string | Primary key column. Convention: `<table>_id` |
81
+ | unique | string[] | Columns for upsert conflict resolution |
82
+ | option | object | `{ safeDelete, created_at, modified_at }` — column names or null |
81
83
 
82
84
  ## Model Methods (all async)
83
85
 
@@ -153,94 +155,128 @@ Generates Express Router with 9 endpoints:
153
155
 
154
156
  ## CLI Tools
155
157
 
156
- ### db-model-router-init (interactive project scaffold)
157
-
158
- Scaffolds a complete Express-based REST API project from scratch. Supports both interactive prompts and fully non-interactive CLI flags.
158
+ ### Unified CLI: `db-model-router`
159
159
 
160
160
  ```bash
161
- # Interactive (prompts for everything)
162
- npx db-model-router-init
161
+ db-model-router <command> [options]
162
+ db-model-router help <command> # detailed help for any command
163
+ ```
163
164
 
164
- # Fully non-interactive (LLM-friendly no prompts)
165
- db-model-router-init --framework express --database postgres --session redis --rateLimiting --helmet --logger
165
+ #### `init`Project Scaffold
166
166
 
167
- # Partial flags only prompts for missing values
168
- db-model-router-init --database mysql --session memory
169
- ```
167
+ Scaffolds a complete ESM-based Express REST API project with Docker support.
170
168
 
171
- Flags: `--framework <name>`, `--database <name>` (or `--db`), `--session <type>`, `--rateLimiting`, `--helmet`, `--logger`, `--help`
169
+ ```bash
170
+ # Fully non-interactive (LLM-friendly — zero prompts)
171
+ db-model-router init --framework express --database postgres --session redis \
172
+ --rateLimiting --helmet --logger --yes
172
173
 
173
- When all 6 options are provided, runs with zero prompts.
174
+ # With Loki logging + Grafana
175
+ db-model-router init --database postgres --logger --loki --yes
174
176
 
175
- Prompts (for missing values): framework (`ultimate-express`|`express`), database (9 options), session (`memory`|`redis`|`database`), rate limiting (y/n), helmet (y/n), logger (y/n).
177
+ # With output directory
178
+ db-model-router init --database mysql --output backend --yes
176
179
 
177
- If no `package.json` exists, runs `npm init` first. After prompts: generates files, updates `package.json`, runs `npm install`.
180
+ # From schema file
181
+ db-model-router init --from dbmr.schema.json --yes --no-install
182
+ ```
178
183
 
179
- Generated structure:
184
+ | Flag | Description | Default |
185
+ | -------------------- | ----------------------------------------------------------------------------------------------------------- | ---------- |
186
+ | `--from <path>` | Read config from schema file | |
187
+ | `--framework <name>` | `express` or `ultimate-express` | (prompted) |
188
+ | `--database <name>` | `mysql`, `mariadb`, `postgres`, `sqlite3`, `mongodb`, `mssql`, `cockroachdb`, `oracle`, `redis`, `dynamodb` | (prompted) |
189
+ | `--db <name>` | Alias for `--database` | |
190
+ | `--session <type>` | `memory`, `redis`, `database` | (prompted) |
191
+ | `--output <dir>` | Backend source directory (relative to cwd) | (root) |
192
+ | `--rateLimiting` | Enable rate limiting | yes |
193
+ | `--helmet` | Enable Helmet security headers | yes |
194
+ | `--logger` | Enable Winston request logger | yes |
195
+ | `--loki` | Enable Loki transport + Loki/Grafana in docker-compose | no |
196
+
197
+ Generated files (ESM, `"type": "module"`):
180
198
 
181
199
  ```
182
- app.js, .env, .env.example, .gitignore, migrate.js, add_migration.js,
183
- middleware/logger.js, migrations/{timestamp}_create_migrations_table.sql|.js
200
+ app.js Express entry point
201
+ .env / .env.example Environment config (random passwords)
202
+ Dockerfile node:alpine production image
203
+ docker-compose.yml DB + CloudBeaver + optional Loki/Grafana
204
+ .cloudbeaver/data-sources.json Auto-connects CloudBeaver to DB
205
+ .grafana/datasources.yml Auto-connects Grafana to Loki (when --loki)
206
+ <output>/commons/db.js Database init, connect, global.db
207
+ <output>/commons/session.js Session configuration
208
+ <output>/commons/security.js Helmet, rate limiting, custom headers
209
+ <output>/commons/migrate.js Migration runner (importable + standalone)
210
+ <output>/commons/add_migration.js Migration creator (importable + standalone)
211
+ <output>/middleware/logger.js Winston logger (+ Loki when LOKI_HOST is set)
212
+ <output>/route/index.js Central route mounting
213
+ <output>/route/health.js GET /health with DB connectivity check
214
+ <output>/migrations/ Initial migration files
184
215
  ```
185
216
 
186
- Session migration (`{timestamp}_create_sessions_table.sql`) generated only for SQL databases with `session=database`.
217
+ Docker services (auto-generated in docker-compose.yml):
187
218
 
188
- Scripts added: `start` (node app.js), `dev` (nodemon app.js), `test`, `migrate` (node migrate.js), `add_migration` (node add_migration.js).
219
+ | Service | When | Port | Notes |
220
+ | ----------- | --------------------------- | ------ | ------------------------------------- |
221
+ | Database | Always (except sqlite3) | Varies | Random password, bind mount `./data/` |
222
+ | Redis | `session=redis`, DB ≠ redis | 6379 | Session store |
223
+ | CloudBeaver | SQL/MongoDB databases | 8978 | Web DB admin, auto-connected |
224
+ | Loki | `--loki` | 3100 | Log aggregation |
225
+ | Grafana | `--loki` | 3001 | Log visualization |
189
226
 
190
- Dependencies always included: `db-model-router`, `dotenv`, selected framework, database driver(s), `express-session`. DevDeps: `nodemon`.
191
- Conditional: `connect-redis` + `ioredis` (session=redis), `express-rate-limit`, `helmet`, `express-mung` (logger).
227
+ Scripts: `start`, `dev`, `test`, `migrate`, `add_migration`, `docker:build`, `docker:up`, `docker:down`.
192
228
 
193
- #### Environment Variables by Database
229
+ **Critical**: `db-model-router` is CJS. Generated ESM code must use: `import dbModelRouter from "db-model-router"; const { init, db } = dbModelRouter;` — NOT named imports.
194
230
 
195
- | Database | Variables |
196
- | ----------- | --------------------------------------------------------------------------- |
197
- | mysql | `PORT=3000 DB_HOST DB_PORT=3306 DB_NAME DB_USER DB_PASS` |
198
- | postgres | `PORT=3000 DB_HOST DB_PORT=5432 DB_NAME DB_USER DB_PASS` |
199
- | cockroachdb | `PORT=3000 DB_HOST DB_PORT=26257 DB_NAME DB_USER DB_PASS` |
200
- | sqlite3 | `PORT=3000 DB_NAME=./data.db` |
201
- | mongodb | `PORT=3000 DB_HOST DB_PORT=27017 DB_NAME DB_USER DB_PASS` |
202
- | mssql | `PORT=3000 DB_HOST DB_PORT=1433 DB_NAME DB_USER DB_PASS` |
203
- | oracle | `PORT=3000 DB_HOST DB_PORT=1521 DB_NAME DB_USER DB_PASS` |
204
- | redis | `PORT=3000 DB_HOST DB_PORT=6379 DB_PASS` |
205
- | dynamodb | `PORT=3000 AWS_REGION AWS_ENDPOINT AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY` |
231
+ #### `inspect` — DB Introspection
206
232
 
207
- When `session=redis` and database ≠ redis: adds `REDIS_HOST=localhost REDIS_PORT=6379 REDIS_PASS`.
208
-
209
- #### Migration Infrastructure
233
+ ```bash
234
+ db-model-router inspect --type postgres --env .env [--out schema.json] [--tables t1,t2]
235
+ ```
210
236
 
211
- - `migrate.js` — reads `migrations/` dir, diffs against `_migrations` tracking table, executes pending in order
212
- - `add_migration.js` creates timestamped empty migration (`.sql` for SQL, `.js` for NoSQL)
213
- - Tracking table `_migrations`: `{id, filename, executed_at, checksum}` (SQL) or equivalent collection/hash/table (NoSQL)
214
- - Timestamp format: `YYYYMMDDHHMMSS`
237
+ | Flag | Description |
238
+ | ------------------ | --------------------------------------- |
239
+ | `--type <adapter>` | Database adapter (required) |
240
+ | `--env <path>` | Path to .env file |
241
+ | `--out <path>` | Output file (default: dbmr.schema.json) |
242
+ | `--tables <list>` | Comma-separated table filter |
215
243
 
216
- ### generate-model (DB introspection → model files)
244
+ #### `generate` Code Generation
217
245
 
218
246
  ```bash
219
- db-model-router-generate-model --type <db> --env .env [--output ./models] [--tables t1,t2] [--schema public]
247
+ db-model-router generate --from dbmr.schema.json [--models] [--routes] [--openapi] [--tests] [--llm-docs]
220
248
  ```
221
249
 
222
- Options: `--type`, `--host`, `--port`, `--database`, `--user`, `--password`, `--schema`, `--output`, `--tables`, `--env`
250
+ | Flag | Description |
251
+ | --------------- | --------------------------------------- |
252
+ | `--from <path>` | Schema file (default: dbmr.schema.json) |
253
+ | `--models` | Generate only model files |
254
+ | `--routes` | Generate only route files + index |
255
+ | `--openapi` | Generate only OpenAPI spec |
256
+ | `--tests` | Generate only test files |
257
+ | `--llm-docs` | Generate only LLM docs |
223
258
 
224
- Auto-detects: PK, unique indexes, DEFAULT→optional, timestamp cols (`created_at`, `updated_at`, `modified_at`, `createdAt`, etc.), soft-delete cols (`is_deleted`, `deleted`, `is_active`, `archived`, etc.). Multi-column unique indexes correctly grouped.
259
+ No flags = generate all. Generated routes/tests use ESM imports.
225
260
 
226
- ### generate-route (model files → route files + tests + OpenAPI)
261
+ #### `doctor` Validation
227
262
 
228
263
  ```bash
229
- db-model-router-generate-route --models ./models --output ./routes [--tables posts,posts.comments]
264
+ db-model-router doctor [--from dbmr.schema.json] [--json]
230
265
  ```
231
266
 
232
- Options: `--models`, `--output`, `--type`, `--host`, `--port`, `--database`, `--user`, `--password`, `--schema`, `--tables`, `--env`
267
+ Checks: schema validation, dependency check, file sync.
233
268
 
234
- Generates:
269
+ #### `diff` — Preview Changes
235
270
 
236
- - Route files for each model
237
- - `index.js` mounting all routes on an Express Router
238
- - `openapi.json` (OpenAPI 3.0 spec)
239
- - Test files in `tests/` directory for all routes and methods (uses `supertest` + `assert`)
271
+ ```bash
272
+ db-model-router diff [--from dbmr.schema.json] [--json]
273
+ ```
240
274
 
241
- Dot notation `parent.child` creates nested routes: `parent/:parent_id/child` with FK scoping via `<parent_singular>_id`. Also generates child route test files.
275
+ Shows added/modified/deleted files without writing.
242
276
 
243
- Generated test files cover all 8 CRUD endpoints per table: GET by ID, POST add, PUT update, DELETE, list, bulk insert, bulk update, bulk delete.
277
+ #### Universal Flags (all commands)
278
+
279
+ `--yes`, `--json`, `--dry-run`, `--no-install`, `--help`
244
280
 
245
281
  ## Connection Configs
246
282
 
@@ -294,21 +330,42 @@ db.connect({ region, endpoint, accessKeyId, secretAccessKey });
294
330
 
295
331
  ## Rules
296
332
 
297
- 1. `init()` before `db.connect()`. Don't destructure `db` before `init()`.
298
- 2. `model structure` excludes: PK col, timestamp cols, soft-delete cols.
299
- 3. `update()`/`patch()` require PK in payload. `upsert()` PK is optional.
300
- 4. `findOne()` returns `false` on no match. `byId()` returns `null`.
301
- 5. Bulk ops wrap in `{ data: [...] }`. Single ops use flat object.
302
- 6. Timestamps auto-stripped from payloads. DB handles defaults/triggers.
303
- 7. `safeDelete` makes `remove()` soft-delete; all reads auto-filter deleted rows.
304
- 8. `list()` defaults: page=0, size=30. `sort` array: `["-col"]` for DESC.
305
- 9. CommonJS only (`require`). Use dynamic `import()` for ESM.
306
- 10. `db-model-router-init` for new projects (interactive). `generate-model` + `generate-route` for existing databases. Or use the unified `db-model-router` CLI with a `dbmr.schema.json` file.
307
- 11. `generate-route` auto-generates test files alongside routes. Tests use `supertest`.
308
-
309
- ## Schema-Driven Workflow (Unified CLI)
310
-
311
- The `db-model-router` command is the unified CLI entry point. It uses a single `dbmr.schema.json` file as the source of truth for all code generation.
333
+ 1. `init()` before `db.connect()`. Don't destructure `db` before `init()` — it's a getter.
334
+ 2. Generated projects are ESM (`"type": "module"`). The library itself is CJS. Use default import: `import dbModelRouter from "db-model-router"; const { init, db } = dbModelRouter;`
335
+ 3. `model structure` excludes: PK col, timestamp cols, soft-delete cols.
336
+ 4. `update()`/`patch()` require PK in payload. `upsert()` PK is optional.
337
+ 5. `findOne()` returns `false` on no match. `byId()` returns `null`.
338
+ 6. Bulk ops wrap in `{ data: [...] }`. Single ops use flat object.
339
+ 7. Timestamps auto-stripped from payloads. DB handles defaults/triggers.
340
+ 8. `safeDelete` makes `remove()` soft-delete; all reads auto-filter deleted rows.
341
+ 9. `list()` defaults: page=0, size=30. `sort` array: `["-col"]` for DESC.
342
+ 10. Use the unified `db-model-router` CLI with `dbmr.schema.json` for new projects.
343
+ 11. `generate` auto-generates test files alongside routes. Tests use `supertest`.
344
+ 12. `global.db` is set by `commons/db.js` — accessible anywhere without imports.
345
+ 13. Logger dynamically loads `winston-loki` only when `LOKI_HOST` env var is set.
346
+ 14. Docker passwords are randomly generated and shared between `.env` and `docker-compose.yml`.
347
+
348
+ ## Environment Variables by Database
349
+
350
+ | Database | Variables |
351
+ | ----------- | ---------------------------------------------------------------------- |
352
+ | mysql | `PORT DB_HOST DB_PORT=3306 DB_NAME DB_USER DB_PASS` |
353
+ | mariadb | `PORT DB_HOST DB_PORT=3306 DB_NAME DB_USER DB_PASS` |
354
+ | postgres | `PORT DB_HOST DB_PORT=5432 DB_NAME DB_USER DB_PASS` |
355
+ | cockroachdb | `PORT DB_HOST DB_PORT=26257 DB_NAME DB_USER DB_PASS` |
356
+ | sqlite3 | `PORT DB_NAME=./data/data.db` |
357
+ | mongodb | `PORT DB_HOST DB_PORT=27017 DB_NAME DB_USER DB_PASS` |
358
+ | mssql | `PORT DB_HOST DB_PORT=1433 DB_NAME DB_USER DB_PASS` |
359
+ | oracle | `PORT DB_HOST DB_PORT=1521 DB_NAME DB_USER DB_PASS` |
360
+ | redis | `PORT DB_HOST DB_PORT=6379 DB_PASS` |
361
+ | dynamodb | `PORT AWS_REGION AWS_ENDPOINT AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY` |
362
+
363
+ When `session=redis` and database ≠ redis: adds `REDIS_HOST REDIS_PORT REDIS_PASS`.
364
+ When `logger=true`: adds `APP_NAME LOG_LEVEL LOKI_HOST` (LOKI_HOST empty unless `--loki`).
365
+
366
+ ## Schema-Driven Workflow
367
+
368
+ The `db-model-router` command uses `dbmr.schema.json` as the source of truth.
312
369
 
313
370
  ### LLM Workflow (schema-driven)
314
371
 
@@ -318,27 +375,6 @@ The `db-model-router` command is the unified CLI entry point. It uses a single `
318
375
  4. **Doctor**: `db-model-router doctor --from dbmr.schema.json` → validate schema + check sync
319
376
  5. **Run**: `npm run dev`
320
377
 
321
- Or for new projects: `db-model-router init --from dbmr.schema.json --yes`
322
-
323
- ### Subcommands
324
-
325
- | Subcommand | Description |
326
- | ---------- | ----------------------------------------------------------- |
327
- | `init` | Scaffold project (optionally from schema file via `--from`) |
328
- | `inspect` | Introspect live DB → produce `dbmr.schema.json` |
329
- | `generate` | Generate models/routes/tests/OpenAPI from schema |
330
- | `doctor` | Validate schema, check deps, verify files in sync |
331
- | `diff` | Preview changes regeneration would make (read-only) |
332
-
333
- ### Universal Flags
334
-
335
- All subcommands accept: `--yes`, `--json`, `--dry-run`, `--no-install`, `--help`.
336
-
337
- - `--yes`: suppress prompts, accept defaults
338
- - `--json`: machine-readable JSON output only
339
- - `--dry-run`: preview without writing files
340
- - `--no-install`: skip `npm install`
341
-
342
378
  ### dbmr.schema.json Format
343
379
 
344
380
  ```json
@@ -349,16 +385,21 @@ All subcommands accept: `--yes`, `--json`, `--dry-run`, `--no-install`, `--help`
349
385
  "session": "redis",
350
386
  "rateLimiting": true,
351
387
  "helmet": true,
352
- "logger": true
388
+ "logger": true,
389
+ "loki": false
353
390
  },
354
391
  "tables": {
355
392
  "users": {
356
393
  "columns": {
394
+ "user_id": "auto_increment",
357
395
  "name": "required|string",
358
396
  "email": "required|string",
359
- "age": "integer"
397
+ "age": "integer",
398
+ "is_deleted": "boolean",
399
+ "created_at": "datetime",
400
+ "updated_at": "datetime"
360
401
  },
361
- "pk": "id",
402
+ "pk": "user_id",
362
403
  "unique": ["email"],
363
404
  "softDelete": "is_deleted",
364
405
  "timestamps": { "created_at": "created_at", "modified_at": "updated_at" }
@@ -370,5 +411,9 @@ All subcommands accept: `--yes`, `--json`, `--dry-run`, `--no-install`, `--help`
370
411
  }
371
412
  ```
372
413
 
373
- Fields per table: `columns` (required), `pk` (default `"id"`), `unique` (default `[pk]`), `softDelete`, `timestamps`.
374
- Column rules: `(required|)?(string|integer|numeric|boolean|object)`.
414
+ Fields per table: `columns` (required, include ALL columns), `pk` (required, convention: `<table>_id`), `unique` (default `[pk]`), `softDelete`, `timestamps`.
415
+ Column rules: `(required|)?(string|integer|numeric|boolean|object|datetime|auto_increment)`.
416
+
417
+ - `auto_increment` — auto-incrementing PK (SERIAL in Postgres, AUTO_INCREMENT in MySQL/MariaDB)
418
+ - `datetime` — date/time columns (TIMESTAMP, DATETIME, DATE)
419
+ - `required|<type>` — NOT NULL constraint
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "db-model-router",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Generative API Creation using mysql2 and express libraries in node js",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -19,7 +19,8 @@
19
19
  "test:cockroachdb": "dotenv -e env/.env.cockroachdb -- mocha test/adapters/cockroachdb.*.test.js --timeout 15000 --exit",
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
- "test:all": "mocha test/adapters/*.test.js test/properties/*.property.test.js test/function.test.js --timeout 30000 --exit"
22
+ "test:all": "mocha test/adapters/*.test.js test/properties/*.property.test.js test/function.test.js --timeout 30000 --exit",
23
+ "clean:demo": "rm -rf demo/* demo/.*"
23
24
  },
24
25
  "repository": {
25
26
  "type": "git",
@@ -27,6 +28,13 @@
27
28
  },
28
29
  "keywords": [
29
30
  "mysql2",
31
+ "sqlite3",
32
+ "oracledb",
33
+ "postgres",
34
+ "pg",
35
+ "dynamodb",
36
+ "mongodb",
37
+ "mssql",
30
38
  "express",
31
39
  "ultimate-express",
32
40
  "generative",