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.
- package/README.md +110 -16
- package/TODO.md +14 -0
- package/dbmr.schema.json +333 -0
- package/demo/.dockerignore +7 -0
- package/demo/.env.example +13 -0
- package/demo/Dockerfile +20 -0
- package/demo/app.js +37 -0
- package/demo/commons/add_migration.js +43 -0
- package/demo/commons/db.js +17 -0
- package/demo/commons/migrate.js +65 -0
- package/demo/commons/security.js +30 -0
- package/demo/commons/session.js +13 -0
- package/demo/dbmr.schema.json +362 -0
- package/demo/docs/llm.md +197 -0
- package/demo/llms.txt +70 -0
- package/demo/middleware/logger.js +67 -0
- package/demo/migrations/20260430155808_create_migrations_table.sql +6 -0
- package/demo/migrations/20260430155809_create_tables.sql +207 -0
- package/demo/models/addresses.js +22 -0
- package/demo/models/cart_items.js +18 -0
- package/demo/models/carts.js +16 -0
- package/demo/models/categories.js +20 -0
- package/demo/models/coupons.js +23 -0
- package/demo/models/order_items.js +21 -0
- package/demo/models/orders.js +25 -0
- package/demo/models/payments.js +21 -0
- package/demo/models/product_images.js +18 -0
- package/demo/models/product_reviews.js +20 -0
- package/demo/models/product_variants.js +20 -0
- package/demo/models/products.js +30 -0
- package/demo/models/shipments.js +19 -0
- package/demo/models/users.js +19 -0
- package/demo/models/wishlists.js +15 -0
- package/demo/openapi.json +5872 -0
- package/demo/package-lock.json +2810 -0
- package/demo/package.json +34 -0
- package/demo/routes/addresses.js +6 -0
- package/demo/routes/carts/cart_items.js +7 -0
- package/demo/routes/carts.js +6 -0
- package/demo/routes/categories.js +6 -0
- package/demo/routes/coupons.js +6 -0
- package/demo/routes/docs.js +18 -0
- package/demo/routes/health.js +35 -0
- package/demo/routes/index.js +39 -0
- package/demo/routes/orders/order_items.js +7 -0
- package/demo/routes/orders/payments.js +7 -0
- package/demo/routes/orders/shipments.js +7 -0
- package/demo/routes/orders.js +6 -0
- package/demo/routes/products/product_images.js +7 -0
- package/demo/routes/products/product_reviews.js +7 -0
- package/demo/routes/products/product_variants.js +7 -0
- package/demo/routes/products.js +6 -0
- package/demo/routes/users.js +6 -0
- package/demo/routes/wishlists.js +6 -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 +58 -17
- package/src/cli/commands/help.js +11 -6
- package/src/cli/commands/init.js +2 -2
- package/src/cli/commands/inspect.js +1 -0
- package/src/cli/diff-engine.js +52 -22
- package/src/cli/generate-docs-route.js +31 -0
- package/src/cli/generate-migration.js +356 -0
- package/src/cli/generate-route.js +52 -24
- package/src/cli/init/dependencies.js +3 -0
- package/src/cli/init/generators.js +1 -1
- package/src/cli/init.js +8 -8
- 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 +1 -0
- package/docs/SKILL.md +0 -419
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "demo",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"start": "node app.js",
|
|
9
|
+
"dev": "nodemon app.js",
|
|
10
|
+
"migrate": "node commons/migrate.js",
|
|
11
|
+
"add_migration": "node commons/add_migration.js",
|
|
12
|
+
"docker:build": "docker build -t app .",
|
|
13
|
+
"docker:up": "docker compose up -d",
|
|
14
|
+
"docker:down": "docker compose down"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [],
|
|
17
|
+
"author": "",
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"type": "module",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"db-model-router": "latest",
|
|
22
|
+
"dotenv": "latest",
|
|
23
|
+
"express": "latest",
|
|
24
|
+
"express-session": "latest",
|
|
25
|
+
"better-sqlite3": "latest",
|
|
26
|
+
"express-rate-limit": "latest",
|
|
27
|
+
"helmet": "latest",
|
|
28
|
+
"winston": "latest",
|
|
29
|
+
"swagger-ui-express": "latest"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"nodemon": "latest"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import swaggerUi from "swagger-ui-express";
|
|
3
|
+
import { readFileSync } from "fs";
|
|
4
|
+
import { dirname, join } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const spec = JSON.parse(readFileSync(join(__dirname, "../openapi.json"), "utf8"));
|
|
9
|
+
|
|
10
|
+
const router = express.Router();
|
|
11
|
+
|
|
12
|
+
router.use("/", swaggerUi.serve);
|
|
13
|
+
router.get("/", swaggerUi.setup(spec, {
|
|
14
|
+
customSiteTitle: "API Documentation",
|
|
15
|
+
customCss: ".swagger-ui .topbar { display: none }",
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
export default router;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
|
|
3
|
+
const router = express.Router();
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* GET /health
|
|
7
|
+
* Returns server health status, uptime, memory, and database connectivity.
|
|
8
|
+
*/
|
|
9
|
+
router.get("/", async (req, res) => {
|
|
10
|
+
const health = {
|
|
11
|
+
status: "ok",
|
|
12
|
+
timestamp: new Date().toISOString(),
|
|
13
|
+
uptime: process.uptime(),
|
|
14
|
+
memory: process.memoryUsage(),
|
|
15
|
+
db: { connected: false },
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
if (global.db && typeof global.db.query === "function") {
|
|
20
|
+
await global.db.query("SELECT NOW()");
|
|
21
|
+
health.db.connected = true;
|
|
22
|
+
} else if (global.db && typeof global.db.get === "function") {
|
|
23
|
+
// NoSQL adapters (mongodb, redis, dynamodb)
|
|
24
|
+
health.db.connected = true;
|
|
25
|
+
}
|
|
26
|
+
} catch (err) {
|
|
27
|
+
health.status = "degraded";
|
|
28
|
+
health.db.error = err.message;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const statusCode = health.status === "ok" ? 200 : 503;
|
|
32
|
+
res.status(statusCode).json(health);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export default router;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
|
|
3
|
+
const router = express.Router();
|
|
4
|
+
|
|
5
|
+
import addressesRoute from "./addresses.js";
|
|
6
|
+
import cartsRoute from "./carts.js";
|
|
7
|
+
import categoriesRoute from "./categories.js";
|
|
8
|
+
import couponsRoute from "./coupons.js";
|
|
9
|
+
import ordersRoute from "./orders.js";
|
|
10
|
+
import productsRoute from "./products.js";
|
|
11
|
+
import usersRoute from "./users.js";
|
|
12
|
+
import wishlistsRoute from "./wishlists.js";
|
|
13
|
+
import product_imagesChildRoute from "./products/product_images.js";
|
|
14
|
+
import product_variantsChildRoute from "./products/product_variants.js";
|
|
15
|
+
import product_reviewsChildRoute from "./products/product_reviews.js";
|
|
16
|
+
import cart_itemsChildRoute from "./carts/cart_items.js";
|
|
17
|
+
import order_itemsChildRoute from "./orders/order_items.js";
|
|
18
|
+
import paymentsChildRoute from "./orders/payments.js";
|
|
19
|
+
import shipmentsChildRoute from "./orders/shipments.js";
|
|
20
|
+
import docsRoute from "./docs.js";
|
|
21
|
+
|
|
22
|
+
router.use("/docs", docsRoute);
|
|
23
|
+
router.use("/addresses", addressesRoute);
|
|
24
|
+
router.use("/carts", cartsRoute);
|
|
25
|
+
router.use("/categories", categoriesRoute);
|
|
26
|
+
router.use("/coupons", couponsRoute);
|
|
27
|
+
router.use("/orders", ordersRoute);
|
|
28
|
+
router.use("/products", productsRoute);
|
|
29
|
+
router.use("/users", usersRoute);
|
|
30
|
+
router.use("/wishlists", wishlistsRoute);
|
|
31
|
+
router.use("/products/:product_id/product_images", product_imagesChildRoute);
|
|
32
|
+
router.use("/products/:product_id/product_variants", product_variantsChildRoute);
|
|
33
|
+
router.use("/products/:product_id/product_reviews", product_reviewsChildRoute);
|
|
34
|
+
router.use("/carts/:cart_id/cart_items", cart_itemsChildRoute);
|
|
35
|
+
router.use("/orders/:order_id/order_items", order_itemsChildRoute);
|
|
36
|
+
router.use("/orders/:order_id/payments", paymentsChildRoute);
|
|
37
|
+
router.use("/orders/:order_id/shipments", shipmentsChildRoute);
|
|
38
|
+
|
|
39
|
+
export default router;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import dbModelRouter from "db-model-router";
|
|
2
|
+
import product_images from "../../models/product_images.js";
|
|
3
|
+
|
|
4
|
+
const { route } = dbModelRouter;
|
|
5
|
+
|
|
6
|
+
// Child route: scoped by parent products via product_id
|
|
7
|
+
export default route(product_images, { product_id: "params.product_id" });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import dbModelRouter from "db-model-router";
|
|
2
|
+
import product_reviews from "../../models/product_reviews.js";
|
|
3
|
+
|
|
4
|
+
const { route } = dbModelRouter;
|
|
5
|
+
|
|
6
|
+
// Child route: scoped by parent products via product_id
|
|
7
|
+
export default route(product_reviews, { product_id: "params.product_id" });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import dbModelRouter from "db-model-router";
|
|
2
|
+
import product_variants from "../../models/product_variants.js";
|
|
3
|
+
|
|
4
|
+
const { route } = dbModelRouter;
|
|
5
|
+
|
|
6
|
+
// Child route: scoped by parent products via product_id
|
|
7
|
+
export default route(product_variants, { product_id: "params.product_id" });
|
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.5",
|
|
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");
|