db-model-router 1.0.4 → 1.0.5

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.
Files changed (92) hide show
  1. package/README.md +110 -16
  2. package/TODO.md +14 -0
  3. package/dbmr.schema.json +333 -0
  4. package/demo/.dockerignore +7 -0
  5. package/demo/.env.example +13 -0
  6. package/demo/Dockerfile +20 -0
  7. package/demo/app.js +37 -0
  8. package/demo/commons/add_migration.js +43 -0
  9. package/demo/commons/db.js +17 -0
  10. package/demo/commons/migrate.js +65 -0
  11. package/demo/commons/security.js +30 -0
  12. package/demo/commons/session.js +13 -0
  13. package/demo/dbmr.schema.json +362 -0
  14. package/demo/docs/llm.md +197 -0
  15. package/demo/llms.txt +70 -0
  16. package/demo/middleware/logger.js +67 -0
  17. package/demo/migrations/20260430155808_create_migrations_table.sql +6 -0
  18. package/demo/migrations/20260430155809_create_tables.sql +207 -0
  19. package/demo/models/addresses.js +22 -0
  20. package/demo/models/cart_items.js +18 -0
  21. package/demo/models/carts.js +16 -0
  22. package/demo/models/categories.js +20 -0
  23. package/demo/models/coupons.js +23 -0
  24. package/demo/models/order_items.js +21 -0
  25. package/demo/models/orders.js +25 -0
  26. package/demo/models/payments.js +21 -0
  27. package/demo/models/product_images.js +18 -0
  28. package/demo/models/product_reviews.js +20 -0
  29. package/demo/models/product_variants.js +20 -0
  30. package/demo/models/products.js +30 -0
  31. package/demo/models/shipments.js +19 -0
  32. package/demo/models/users.js +19 -0
  33. package/demo/models/wishlists.js +15 -0
  34. package/demo/openapi.json +5872 -0
  35. package/demo/package-lock.json +2810 -0
  36. package/demo/package.json +34 -0
  37. package/demo/routes/addresses.js +6 -0
  38. package/demo/routes/carts/cart_items.js +7 -0
  39. package/demo/routes/carts.js +6 -0
  40. package/demo/routes/categories.js +6 -0
  41. package/demo/routes/coupons.js +6 -0
  42. package/demo/routes/docs.js +18 -0
  43. package/demo/routes/health.js +35 -0
  44. package/demo/routes/index.js +39 -0
  45. package/demo/routes/orders/order_items.js +7 -0
  46. package/demo/routes/orders/payments.js +7 -0
  47. package/demo/routes/orders/shipments.js +7 -0
  48. package/demo/routes/orders.js +6 -0
  49. package/demo/routes/products/product_images.js +7 -0
  50. package/demo/routes/products/product_reviews.js +7 -0
  51. package/demo/routes/products/product_variants.js +7 -0
  52. package/demo/routes/products.js +6 -0
  53. package/demo/routes/users.js +6 -0
  54. package/demo/routes/wishlists.js +6 -0
  55. package/docker-compose.yml +1 -1
  56. package/package.json +8 -7
  57. package/scripts/demo-create.js +47 -0
  58. package/skill/SKILL.md +464 -0
  59. package/skill/references/cockroachdb.md +49 -0
  60. package/skill/references/dynamodb.md +53 -0
  61. package/skill/references/mongodb.md +56 -0
  62. package/skill/references/mssql.md +55 -0
  63. package/skill/references/oracle.md +52 -0
  64. package/skill/references/postgres.md +50 -0
  65. package/skill/references/redis.md +53 -0
  66. package/skill/references/sqlite3.md +43 -0
  67. package/src/cli/commands/generate.js +58 -17
  68. package/src/cli/commands/help.js +11 -6
  69. package/src/cli/commands/init.js +2 -2
  70. package/src/cli/commands/inspect.js +1 -0
  71. package/src/cli/diff-engine.js +52 -22
  72. package/src/cli/generate-docs-route.js +31 -0
  73. package/src/cli/generate-migration.js +356 -0
  74. package/src/cli/generate-route.js +52 -24
  75. package/src/cli/init/dependencies.js +3 -0
  76. package/src/cli/init/generators.js +1 -1
  77. package/src/cli/init.js +8 -8
  78. package/src/cockroachdb/db.js +90 -59
  79. package/src/commons/route.js +20 -20
  80. package/src/commons/validator.js +58 -1
  81. package/src/dynamodb/db.js +50 -27
  82. package/src/mongodb/db.js +1 -0
  83. package/src/mssql/db.js +89 -61
  84. package/src/mysql/db.js +1 -0
  85. package/src/oracle/db.js +1 -0
  86. package/src/postgres/db.js +61 -41
  87. package/src/redis/db.js +1 -0
  88. package/src/schema/schema-parser.js +43 -1
  89. package/src/schema/schema-printer.js +7 -0
  90. package/src/schema/schema-validator.js +17 -0
  91. package/src/sqlite3/db.js +1 -0
  92. package/docs/SKILL.md +0 -419
package/demo/llms.txt ADDED
@@ -0,0 +1,70 @@
1
+ # db-model-router — LLM Quick Reference
2
+
3
+ ## Schema File: dbmr.schema.json
4
+ { "adapter": "<adapter>", "framework": "<framework>", "tables": { "<name>": { "columns": { "<col>": "<rule>" }, "pk": "<col>", "unique": ["<col>"], "softDelete": "<col>" } }, "relationships": [{ "parent": "<t>", "child": "<t>", "foreignKey": "<col>" }], "options": {} }
5
+
6
+ Adapters: mysql, postgres, sqlite3, mongodb, mssql, cockroachdb, oracle, redis, dynamodb
7
+ Frameworks: express, ultimate-express
8
+ Column rules: (required|)?(string|integer|numeric|boolean|object) e.g. "required|string"
9
+
10
+ ## Universal Flags
11
+ --yes --json --dry-run --no-install --help
12
+
13
+ ## Commands
14
+
15
+ ### init
16
+ Scaffold a new project.
17
+ --from <schema> Read config from schema file
18
+ --framework <fw> Framework (express|ultimate-express)
19
+ --database <db> Adapter name
20
+ Example: db-model-router init --from dbmr.schema.json --yes --no-install
21
+
22
+ ### inspect
23
+ Introspect a live database and produce a schema file.
24
+ --type <adapter> Database adapter
25
+ --env <path> Path to .env file
26
+ --out <path> Output path (default: dbmr.schema.json)
27
+ --tables <list> Comma-separated table filter
28
+ Example: db-model-router inspect --type sqlite3 --env .env --out schema.json
29
+
30
+ ### generate
31
+ Generate code artifacts from schema.
32
+ --from <schema> Schema file (default: dbmr.schema.json)
33
+ --models Generate model files only
34
+ --routes Generate route files only
35
+ --openapi Generate OpenAPI spec only
36
+ --tests Generate test files only
37
+ --llm-docs Generate LLM documentation only
38
+ Example: db-model-router generate --from dbmr.schema.json
39
+ Example: db-model-router generate --models --dry-run
40
+
41
+ ### doctor
42
+ Validate schema, check dependencies, verify file sync.
43
+ --from <schema> Schema file (default: dbmr.schema.json)
44
+ Example: db-model-router doctor --from dbmr.schema.json --json
45
+
46
+ ### diff
47
+ Preview changes between schema and generated files.
48
+ --from <schema> Schema file (default: dbmr.schema.json)
49
+ Example: db-model-router diff --from dbmr.schema.json
50
+
51
+ ## Route Contract (per table)
52
+ GET /api/<table>/ List (page, size, sort, select_columns)
53
+ POST /api/<table>/ Bulk insert
54
+ PUT /api/<table>/ Bulk update
55
+ DELETE /api/<table>/ Bulk delete
56
+ GET /api/<table>/:id Get by ID
57
+ POST /api/<table>/:id Insert one
58
+ PUT /api/<table>/:id Update one
59
+ PATCH /api/<table>/:id Partial update one
60
+ DELETE /api/<table>/:id Delete one
61
+
62
+ ## Generated Files
63
+ models/<table>.js Model with CRUD operations
64
+ routes/<table>.js Express route handlers
65
+ routes/<child>_child_of_<parent>.js Child route
66
+ routes/index.js Route mounting index
67
+ test/<table>.test.js CRUD endpoint tests
68
+ openapi.json OpenAPI 3.0 spec
69
+ llms.txt This file
70
+ docs/llm.md Full LLM reference
@@ -0,0 +1,67 @@
1
+ import winston from "winston";
2
+
3
+ /**
4
+ * Winston logger with Console transport.
5
+ * If LOKI_HOST is set in .env, adds a Loki transport for Grafana visualization.
6
+ */
7
+ const transports = [
8
+ new winston.transports.Console({
9
+ format: winston.format.combine(
10
+ winston.format.colorize(),
11
+ winston.format.printf(({ timestamp, level, message, ...meta }) => {
12
+ const metaStr = Object.keys(meta).length > 1
13
+ ? " " + JSON.stringify(meta)
14
+ : "";
15
+ return `[${timestamp}] [${level}] ${message}${metaStr}`;
16
+ }),
17
+ ),
18
+ }),
19
+ ];
20
+
21
+ // Add Loki transport only when LOKI_HOST is configured
22
+ if (process.env.LOKI_HOST) {
23
+ const { default: LokiTransport } = await import("winston-loki");
24
+ transports.push(
25
+ new LokiTransport({
26
+ host: process.env.LOKI_HOST,
27
+ labels: { app: process.env.APP_NAME || "app" },
28
+ json: true,
29
+ onConnectionError: (err) => console.error("Loki connection error:", err),
30
+ }),
31
+ );
32
+ }
33
+
34
+ const logger = winston.createLogger({
35
+ level: process.env.LOG_LEVEL || "info",
36
+ format: winston.format.combine(
37
+ winston.format.timestamp(),
38
+ winston.format.json(),
39
+ ),
40
+ defaultMeta: { service: process.env.APP_NAME || "app" },
41
+ transports,
42
+ });
43
+
44
+ /**
45
+ * Express middleware that logs every request/response.
46
+ */
47
+ function requestLogger(req, res, next) {
48
+ const start = Date.now();
49
+
50
+ res.on("finish", () => {
51
+ const duration = Date.now() - start;
52
+ const level = res.statusCode >= 400 ? "warn" : "info";
53
+ logger.log({
54
+ level,
55
+ message: `${req.method} ${req.originalUrl} ${res.statusCode} ${duration}ms`,
56
+ method: req.method,
57
+ url: req.originalUrl,
58
+ status: res.statusCode,
59
+ duration,
60
+ });
61
+ });
62
+
63
+ next();
64
+ }
65
+
66
+ requestLogger.logger = logger;
67
+ export default requestLogger;
@@ -0,0 +1,6 @@
1
+ CREATE TABLE IF NOT EXISTS _migrations (
2
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
3
+ filename VARCHAR(255) NOT NULL UNIQUE,
4
+ executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
5
+ checksum VARCHAR(64) NOT NULL
6
+ );
@@ -0,0 +1,207 @@
1
+ CREATE TABLE IF NOT EXISTS addresses (
2
+ address_id INTEGER PRIMARY KEY AUTOINCREMENT,
3
+ user_id INTEGER NOT NULL,
4
+ label VARCHAR(255),
5
+ line1 VARCHAR(255) NOT NULL,
6
+ line2 VARCHAR(255),
7
+ city VARCHAR(255) NOT NULL,
8
+ state VARCHAR(255) NOT NULL,
9
+ postal_code VARCHAR(255) NOT NULL,
10
+ country VARCHAR(255) NOT NULL,
11
+ is_default BOOLEAN,
12
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
13
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
14
+ );
15
+
16
+ CREATE TABLE IF NOT EXISTS cart_items (
17
+ cart_item_id INTEGER PRIMARY KEY AUTOINCREMENT,
18
+ cart_id INTEGER NOT NULL,
19
+ product_id INTEGER NOT NULL,
20
+ variant_id INTEGER,
21
+ quantity INTEGER NOT NULL,
22
+ unit_price DECIMAL(12,2) NOT NULL,
23
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
24
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
25
+ );
26
+
27
+ CREATE TABLE IF NOT EXISTS carts (
28
+ cart_id INTEGER PRIMARY KEY AUTOINCREMENT,
29
+ user_id INTEGER,
30
+ session_id VARCHAR(255),
31
+ currency VARCHAR(255) NOT NULL,
32
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
33
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
34
+ );
35
+
36
+ CREATE TABLE IF NOT EXISTS categories (
37
+ category_id INTEGER PRIMARY KEY AUTOINCREMENT,
38
+ name VARCHAR(255) NOT NULL,
39
+ slug VARCHAR(255) NOT NULL,
40
+ description VARCHAR(255),
41
+ parent_category_id INTEGER,
42
+ image_url VARCHAR(255),
43
+ sort_order INTEGER,
44
+ is_active BOOLEAN,
45
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
46
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
47
+ UNIQUE (slug)
48
+ );
49
+
50
+ CREATE TABLE IF NOT EXISTS coupons (
51
+ coupon_id INTEGER PRIMARY KEY AUTOINCREMENT,
52
+ code VARCHAR(255) NOT NULL,
53
+ description VARCHAR(255),
54
+ discount_type VARCHAR(255) NOT NULL,
55
+ discount_value DECIMAL(12,2) NOT NULL,
56
+ min_order_amount DECIMAL(12,2),
57
+ max_uses INTEGER,
58
+ used_count INTEGER,
59
+ starts_at TIMESTAMP,
60
+ expires_at TIMESTAMP,
61
+ is_active BOOLEAN,
62
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
63
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
64
+ UNIQUE (code)
65
+ );
66
+
67
+ CREATE TABLE IF NOT EXISTS order_items (
68
+ order_item_id INTEGER PRIMARY KEY AUTOINCREMENT,
69
+ order_id INTEGER NOT NULL,
70
+ product_id INTEGER NOT NULL,
71
+ variant_id INTEGER,
72
+ product_name VARCHAR(255) NOT NULL,
73
+ sku VARCHAR(255) NOT NULL,
74
+ quantity INTEGER NOT NULL,
75
+ unit_price DECIMAL(12,2) NOT NULL,
76
+ total_price DECIMAL(12,2) NOT NULL,
77
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
78
+ );
79
+
80
+ CREATE TABLE IF NOT EXISTS orders (
81
+ order_id INTEGER PRIMARY KEY AUTOINCREMENT,
82
+ user_id INTEGER NOT NULL,
83
+ order_number VARCHAR(255) NOT NULL,
84
+ status VARCHAR(255) NOT NULL,
85
+ subtotal DECIMAL(12,2) NOT NULL,
86
+ tax_amount DECIMAL(12,2) NOT NULL,
87
+ shipping_amount DECIMAL(12,2) NOT NULL,
88
+ discount_amount DECIMAL(12,2),
89
+ total DECIMAL(12,2) NOT NULL,
90
+ currency VARCHAR(255) NOT NULL,
91
+ shipping_address_id INTEGER,
92
+ billing_address_id INTEGER,
93
+ notes VARCHAR(255),
94
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
95
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
96
+ UNIQUE (order_number)
97
+ );
98
+
99
+ CREATE TABLE IF NOT EXISTS payments (
100
+ payment_id INTEGER PRIMARY KEY AUTOINCREMENT,
101
+ order_id INTEGER NOT NULL,
102
+ method VARCHAR(255) NOT NULL,
103
+ provider VARCHAR(255),
104
+ provider_transaction_id VARCHAR(255),
105
+ amount DECIMAL(12,2) NOT NULL,
106
+ currency VARCHAR(255) NOT NULL,
107
+ status VARCHAR(255) NOT NULL,
108
+ paid_at TIMESTAMP,
109
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
110
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
111
+ );
112
+
113
+ CREATE TABLE IF NOT EXISTS product_images (
114
+ product_image_id INTEGER PRIMARY KEY AUTOINCREMENT,
115
+ product_id INTEGER NOT NULL,
116
+ url VARCHAR(255) NOT NULL,
117
+ alt_text VARCHAR(255),
118
+ sort_order INTEGER,
119
+ is_primary BOOLEAN,
120
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
121
+ );
122
+
123
+ CREATE TABLE IF NOT EXISTS product_reviews (
124
+ review_id INTEGER PRIMARY KEY AUTOINCREMENT,
125
+ product_id INTEGER NOT NULL,
126
+ user_id INTEGER NOT NULL,
127
+ rating INTEGER NOT NULL,
128
+ title VARCHAR(255),
129
+ body VARCHAR(255),
130
+ is_verified BOOLEAN,
131
+ is_approved BOOLEAN,
132
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
133
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
134
+ );
135
+
136
+ CREATE TABLE IF NOT EXISTS product_variants (
137
+ variant_id INTEGER PRIMARY KEY AUTOINCREMENT,
138
+ product_id INTEGER NOT NULL,
139
+ name VARCHAR(255) NOT NULL,
140
+ sku VARCHAR(255) NOT NULL,
141
+ price DECIMAL(12,2) NOT NULL,
142
+ stock_quantity INTEGER NOT NULL,
143
+ attributes TEXT,
144
+ is_active BOOLEAN,
145
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
146
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
147
+ UNIQUE (sku)
148
+ );
149
+
150
+ CREATE TABLE IF NOT EXISTS products (
151
+ product_id INTEGER PRIMARY KEY AUTOINCREMENT,
152
+ category_id INTEGER NOT NULL,
153
+ name VARCHAR(255) NOT NULL,
154
+ slug VARCHAR(255) NOT NULL,
155
+ description VARCHAR(255),
156
+ short_description VARCHAR(255),
157
+ sku VARCHAR(255) NOT NULL,
158
+ price DECIMAL(12,2) NOT NULL,
159
+ compare_at_price DECIMAL(12,2),
160
+ cost_price DECIMAL(12,2),
161
+ currency VARCHAR(255) NOT NULL,
162
+ stock_quantity INTEGER NOT NULL,
163
+ low_stock_threshold INTEGER,
164
+ weight DECIMAL(12,2),
165
+ weight_unit VARCHAR(255),
166
+ is_active BOOLEAN,
167
+ is_featured BOOLEAN,
168
+ is_deleted BOOLEAN DEFAULT FALSE,
169
+ meta TEXT,
170
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
171
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
172
+ UNIQUE (sku),
173
+ UNIQUE (slug)
174
+ );
175
+
176
+ CREATE TABLE IF NOT EXISTS shipments (
177
+ shipment_id INTEGER PRIMARY KEY AUTOINCREMENT,
178
+ order_id INTEGER NOT NULL,
179
+ carrier VARCHAR(255) NOT NULL,
180
+ tracking_number VARCHAR(255),
181
+ status VARCHAR(255) NOT NULL,
182
+ shipped_at TIMESTAMP,
183
+ delivered_at TIMESTAMP,
184
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
185
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
186
+ );
187
+
188
+ CREATE TABLE IF NOT EXISTS users (
189
+ user_id INTEGER PRIMARY KEY AUTOINCREMENT,
190
+ name VARCHAR(255) NOT NULL,
191
+ email VARCHAR(255) NOT NULL,
192
+ password_hash VARCHAR(255) NOT NULL,
193
+ phone VARCHAR(255),
194
+ avatar_url VARCHAR(255),
195
+ role VARCHAR(255) NOT NULL,
196
+ is_deleted BOOLEAN DEFAULT FALSE,
197
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
198
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
199
+ UNIQUE (email)
200
+ );
201
+
202
+ CREATE TABLE IF NOT EXISTS wishlists (
203
+ wishlist_id INTEGER PRIMARY KEY AUTOINCREMENT,
204
+ user_id INTEGER NOT NULL,
205
+ product_id INTEGER NOT NULL,
206
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
207
+ );
@@ -0,0 +1,22 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const addresses = model(
4
+ db,
5
+ "addresses",
6
+ {
7
+ "user_id": "required|integer",
8
+ "label": "string",
9
+ "line1": "required|string",
10
+ "line2": "string",
11
+ "city": "required|string",
12
+ "state": "required|string",
13
+ "postal_code": "required|string",
14
+ "country": "required|string",
15
+ "is_default": "boolean"
16
+ },
17
+ "address_id",
18
+ ["address_id"],
19
+ { created_at: "created_at", modified_at: "updated_at" },
20
+ );
21
+
22
+ module.exports = addresses;
@@ -0,0 +1,18 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const cart_items = model(
4
+ db,
5
+ "cart_items",
6
+ {
7
+ "cart_id": "required|integer",
8
+ "product_id": "required|integer",
9
+ "variant_id": "integer",
10
+ "quantity": "required|integer",
11
+ "unit_price": "required|numeric"
12
+ },
13
+ "cart_item_id",
14
+ ["cart_item_id"],
15
+ { created_at: "created_at", modified_at: "updated_at" },
16
+ );
17
+
18
+ module.exports = cart_items;
@@ -0,0 +1,16 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const carts = model(
4
+ db,
5
+ "carts",
6
+ {
7
+ "user_id": "integer",
8
+ "session_id": "string",
9
+ "currency": "required|string"
10
+ },
11
+ "cart_id",
12
+ ["cart_id"],
13
+ { created_at: "created_at", modified_at: "updated_at" },
14
+ );
15
+
16
+ module.exports = carts;
@@ -0,0 +1,20 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const categories = model(
4
+ db,
5
+ "categories",
6
+ {
7
+ "name": "required|string",
8
+ "slug": "required|string",
9
+ "description": "string",
10
+ "parent_category_id": "integer",
11
+ "image_url": "string",
12
+ "sort_order": "integer",
13
+ "is_active": "boolean"
14
+ },
15
+ "category_id",
16
+ ["slug"],
17
+ { created_at: "created_at", modified_at: "updated_at" },
18
+ );
19
+
20
+ module.exports = categories;
@@ -0,0 +1,23 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const coupons = model(
4
+ db,
5
+ "coupons",
6
+ {
7
+ "code": "required|string",
8
+ "description": "string",
9
+ "discount_type": "required|string",
10
+ "discount_value": "required|numeric",
11
+ "min_order_amount": "numeric",
12
+ "max_uses": "integer",
13
+ "used_count": "integer",
14
+ "starts_at": "datetime",
15
+ "expires_at": "datetime",
16
+ "is_active": "boolean"
17
+ },
18
+ "coupon_id",
19
+ ["code"],
20
+ { created_at: "created_at", modified_at: "updated_at" },
21
+ );
22
+
23
+ module.exports = coupons;
@@ -0,0 +1,21 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const order_items = model(
4
+ db,
5
+ "order_items",
6
+ {
7
+ "order_id": "required|integer",
8
+ "product_id": "required|integer",
9
+ "variant_id": "integer",
10
+ "product_name": "required|string",
11
+ "sku": "required|string",
12
+ "quantity": "required|integer",
13
+ "unit_price": "required|numeric",
14
+ "total_price": "required|numeric"
15
+ },
16
+ "order_item_id",
17
+ ["order_item_id"],
18
+ { created_at: "created_at" },
19
+ );
20
+
21
+ module.exports = order_items;
@@ -0,0 +1,25 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const orders = model(
4
+ db,
5
+ "orders",
6
+ {
7
+ "user_id": "required|integer",
8
+ "order_number": "required|string",
9
+ "status": "required|string",
10
+ "subtotal": "required|numeric",
11
+ "tax_amount": "required|numeric",
12
+ "shipping_amount": "required|numeric",
13
+ "discount_amount": "numeric",
14
+ "total": "required|numeric",
15
+ "currency": "required|string",
16
+ "shipping_address_id": "integer",
17
+ "billing_address_id": "integer",
18
+ "notes": "string"
19
+ },
20
+ "order_id",
21
+ ["order_number"],
22
+ { created_at: "created_at", modified_at: "updated_at" },
23
+ );
24
+
25
+ module.exports = orders;
@@ -0,0 +1,21 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const payments = model(
4
+ db,
5
+ "payments",
6
+ {
7
+ "order_id": "required|integer",
8
+ "method": "required|string",
9
+ "provider": "string",
10
+ "provider_transaction_id": "string",
11
+ "amount": "required|numeric",
12
+ "currency": "required|string",
13
+ "status": "required|string",
14
+ "paid_at": "datetime"
15
+ },
16
+ "payment_id",
17
+ ["payment_id"],
18
+ { created_at: "created_at", modified_at: "updated_at" },
19
+ );
20
+
21
+ module.exports = payments;
@@ -0,0 +1,18 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const product_images = model(
4
+ db,
5
+ "product_images",
6
+ {
7
+ "product_id": "required|integer",
8
+ "url": "required|string",
9
+ "alt_text": "string",
10
+ "sort_order": "integer",
11
+ "is_primary": "boolean"
12
+ },
13
+ "product_image_id",
14
+ ["product_image_id"],
15
+ { created_at: "created_at" },
16
+ );
17
+
18
+ module.exports = product_images;
@@ -0,0 +1,20 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const product_reviews = model(
4
+ db,
5
+ "product_reviews",
6
+ {
7
+ "product_id": "required|integer",
8
+ "user_id": "required|integer",
9
+ "rating": "required|integer",
10
+ "title": "string",
11
+ "body": "string",
12
+ "is_verified": "boolean",
13
+ "is_approved": "boolean"
14
+ },
15
+ "review_id",
16
+ ["review_id"],
17
+ { created_at: "created_at", modified_at: "updated_at" },
18
+ );
19
+
20
+ module.exports = product_reviews;
@@ -0,0 +1,20 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const product_variants = model(
4
+ db,
5
+ "product_variants",
6
+ {
7
+ "product_id": "required|integer",
8
+ "name": "required|string",
9
+ "sku": "required|string",
10
+ "price": "required|numeric",
11
+ "stock_quantity": "required|integer",
12
+ "attributes": "object",
13
+ "is_active": "boolean"
14
+ },
15
+ "variant_id",
16
+ ["sku"],
17
+ { created_at: "created_at", modified_at: "updated_at" },
18
+ );
19
+
20
+ module.exports = product_variants;
@@ -0,0 +1,30 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const products = model(
4
+ db,
5
+ "products",
6
+ {
7
+ "category_id": "required|integer",
8
+ "name": "required|string",
9
+ "slug": "required|string",
10
+ "description": "string",
11
+ "short_description": "string",
12
+ "sku": "required|string",
13
+ "price": "required|numeric",
14
+ "compare_at_price": "numeric",
15
+ "cost_price": "numeric",
16
+ "currency": "required|string",
17
+ "stock_quantity": "required|integer",
18
+ "low_stock_threshold": "integer",
19
+ "weight": "numeric",
20
+ "weight_unit": "string",
21
+ "is_active": "boolean",
22
+ "is_featured": "boolean",
23
+ "meta": "object"
24
+ },
25
+ "product_id",
26
+ ["sku","slug"],
27
+ { safeDelete: "is_deleted", created_at: "created_at", modified_at: "updated_at" },
28
+ );
29
+
30
+ module.exports = products;
@@ -0,0 +1,19 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const shipments = model(
4
+ db,
5
+ "shipments",
6
+ {
7
+ "order_id": "required|integer",
8
+ "carrier": "required|string",
9
+ "tracking_number": "string",
10
+ "status": "required|string",
11
+ "shipped_at": "datetime",
12
+ "delivered_at": "datetime"
13
+ },
14
+ "shipment_id",
15
+ ["shipment_id"],
16
+ { created_at: "created_at", modified_at: "updated_at" },
17
+ );
18
+
19
+ module.exports = shipments;
@@ -0,0 +1,19 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const users = model(
4
+ db,
5
+ "users",
6
+ {
7
+ "name": "required|string",
8
+ "email": "required|string",
9
+ "password_hash": "required|string",
10
+ "phone": "string",
11
+ "avatar_url": "string",
12
+ "role": "required|string"
13
+ },
14
+ "user_id",
15
+ ["email"],
16
+ { safeDelete: "is_deleted", created_at: "created_at", modified_at: "updated_at" },
17
+ );
18
+
19
+ module.exports = users;
@@ -0,0 +1,15 @@
1
+ const { db, model } = require("db-model-router");
2
+
3
+ const wishlists = model(
4
+ db,
5
+ "wishlists",
6
+ {
7
+ "user_id": "required|integer",
8
+ "product_id": "required|integer"
9
+ },
10
+ "wishlist_id",
11
+ ["wishlist_id"],
12
+ { created_at: "created_at" },
13
+ );
14
+
15
+ module.exports = wishlists;