db-model-router 1.0.7 → 1.0.9
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 +25 -4
- package/db-manager/.dbmanager.sqlite-shm +0 -0
- package/db-manager/.dbmanager.sqlite-wal +0 -0
- package/demo/.env.example +1 -0
- package/demo/app.js +2 -2
- package/demo/commons/db.js +0 -11
- package/demo/middleware/tenantIsolation.js +2 -0
- package/demo/package-lock.json +1224 -62
- package/demo/package.json +6 -3
- package/demo/routes/addresses/index.js +5 -1
- package/demo/routes/auth/index.js +1 -1
- package/demo/routes/carts/cart_items/index.js +5 -1
- package/demo/routes/carts/index.js +9 -1
- package/demo/routes/categories/index.js +5 -1
- package/demo/routes/coupons/index.js +5 -1
- package/demo/routes/index.js +1 -15
- package/demo/routes/orders/index.js +13 -1
- package/demo/routes/orders/order_items/index.js +5 -1
- package/demo/routes/orders/payments/index.js +5 -1
- package/demo/routes/orders/shipments/index.js +5 -1
- package/demo/routes/products/index.js +13 -1
- package/demo/routes/products/product_images/index.js +5 -1
- package/demo/routes/products/product_reviews/index.js +5 -1
- package/demo/routes/products/product_variants/index.js +5 -1
- package/demo/routes/roles/index.js +1 -1
- package/demo/routes/tenants/index.js +1 -1
- package/demo/routes/users/index.js +1 -1
- package/demo/routes/wishlists/index.js +5 -1
- package/demo/seeds/saas-seed.js +1 -1
- package/docs/dbmr-schema-spec.md +393 -0
- package/package.json +4 -2
- package/skill/SKILL.md +47 -4
- package/src/cli/commands/generate.js +45 -15
- package/src/cli/diff-engine.js +17 -5
- package/src/cli/generate-migration.js +207 -19
- package/src/cli/generate-route.js +156 -58
- package/src/cli/generate-saas-structure.js +8 -1
- package/src/cli/init/dependencies.js +5 -1
- package/src/cli/init/generators.js +4 -81
- package/src/cli/init.js +1 -2
- package/src/cli/saas/generate-saas-middleware.js +2 -0
- package/src/cli/saas/generate-saas-routes.js +3 -13
- package/src/cli/saas/generate-saas-tests.js +473 -0
- package/src/commons/route.js +6 -6
- /package/demo/migrations/{20260509170349_create_migrations_table.sql → 20260510193736_create_migrations_table.sql} +0 -0
- /package/demo/migrations/{20260509170349_create_saas_tables.sql → 20260510193737_create_saas_tables.sql} +0 -0
- /package/demo/migrations/{20260509170349_create_tables.sql → 20260510193737_create_tables.sql} +0 -0
package/demo/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "
|
|
7
|
+
"test": "dotenv -- mocha --exit",
|
|
8
8
|
"start": "node app.js",
|
|
9
9
|
"dev": "nodemon app.js",
|
|
10
10
|
"migrate": "node commons/migrate.js",
|
|
@@ -33,11 +33,14 @@
|
|
|
33
33
|
"better-sqlite3": "latest",
|
|
34
34
|
"express-rate-limit": "latest",
|
|
35
35
|
"helmet": "latest",
|
|
36
|
-
"kafkajs": "latest",
|
|
37
36
|
"winston": "latest",
|
|
38
37
|
"swagger-ui-express": "latest"
|
|
39
38
|
},
|
|
40
39
|
"devDependencies": {
|
|
41
|
-
"nodemon": "latest"
|
|
40
|
+
"nodemon": "latest",
|
|
41
|
+
"mocha": "latest",
|
|
42
|
+
"supertest": "latest",
|
|
43
|
+
"dotenv-cli": "latest",
|
|
44
|
+
"@faker-js/faker": "latest"
|
|
42
45
|
}
|
|
43
46
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { addresses } from "#models";
|
|
3
4
|
|
|
5
|
+
const router = express.Router({ mergeParams: true });
|
|
4
6
|
const { route } = dbModelRouter;
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
router.use("/", route(addresses));
|
|
9
|
+
|
|
10
|
+
export default router;
|
|
@@ -3,7 +3,7 @@ import authenticate from "#middleware/authenticate.js";
|
|
|
3
3
|
import { verifyPassword } from "#commons/password.js";
|
|
4
4
|
import { users, roles, role_permissions } from "#models";
|
|
5
5
|
|
|
6
|
-
const router = express.Router();
|
|
6
|
+
const router = express.Router({ mergeParams: true });
|
|
7
7
|
|
|
8
8
|
// POST /api/auth/login - Authenticate user and create session
|
|
9
9
|
router.post("/login", async (req, res) => {
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { cart_items } from "#models";
|
|
3
4
|
|
|
5
|
+
const router = express.Router({ mergeParams: true });
|
|
4
6
|
const { route } = dbModelRouter;
|
|
5
7
|
|
|
6
8
|
// Child route: scoped by parent carts via cart_id
|
|
7
|
-
|
|
9
|
+
router.use("/", route(cart_items, { cart_id: "params.cart_id" }));
|
|
10
|
+
|
|
11
|
+
export default router;
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { carts } from "#models";
|
|
4
|
+
import cart_itemsRoute from "./cart_items/index.js";
|
|
3
5
|
|
|
6
|
+
const router = express.Router({ mergeParams: true });
|
|
4
7
|
const { route } = dbModelRouter;
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
router.use("/:cart_id/cart_items", cart_itemsRoute);
|
|
10
|
+
|
|
11
|
+
// CRUD routes for carts
|
|
12
|
+
router.use("/", route(carts));
|
|
13
|
+
|
|
14
|
+
export default router;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { categories } from "#models";
|
|
3
4
|
|
|
5
|
+
const router = express.Router({ mergeParams: true });
|
|
4
6
|
const { route } = dbModelRouter;
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
router.use("/", route(categories));
|
|
9
|
+
|
|
10
|
+
export default router;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { coupons } from "#models";
|
|
3
4
|
|
|
5
|
+
const router = express.Router({ mergeParams: true });
|
|
4
6
|
const { route } = dbModelRouter;
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
router.use("/", route(coupons));
|
|
9
|
+
|
|
10
|
+
export default router;
|
package/demo/routes/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import express from "express";
|
|
2
2
|
|
|
3
|
-
const router = express.Router();
|
|
3
|
+
const router = express.Router({ mergeParams: true });
|
|
4
4
|
|
|
5
5
|
// SaaS auth & CRUD routes
|
|
6
6
|
import authRoute from "#routes/auth/index.js";
|
|
@@ -17,13 +17,6 @@ import couponsRoute from "#routes/coupons/index.js";
|
|
|
17
17
|
import ordersRoute from "#routes/orders/index.js";
|
|
18
18
|
import productsRoute from "#routes/products/index.js";
|
|
19
19
|
import wishlistsRoute from "#routes/wishlists/index.js";
|
|
20
|
-
import product_imagesChildRoute from "#routes/products/product_images/index.js";
|
|
21
|
-
import product_variantsChildRoute from "#routes/products/product_variants/index.js";
|
|
22
|
-
import product_reviewsChildRoute from "#routes/products/product_reviews/index.js";
|
|
23
|
-
import cart_itemsChildRoute from "#routes/carts/cart_items/index.js";
|
|
24
|
-
import order_itemsChildRoute from "#routes/orders/order_items/index.js";
|
|
25
|
-
import paymentsChildRoute from "#routes/orders/payments/index.js";
|
|
26
|
-
import shipmentsChildRoute from "#routes/orders/shipments/index.js";
|
|
27
20
|
import docsRoute from "#routes/docs.js";
|
|
28
21
|
|
|
29
22
|
// SaaS routes
|
|
@@ -34,13 +27,6 @@ router.use("/roles", saasRolesRoute);
|
|
|
34
27
|
router.use("/roles/:role_id/permissions", saasPermissionsRoute);
|
|
35
28
|
|
|
36
29
|
router.use("/docs", docsRoute);
|
|
37
|
-
router.use("/products/:product_id/product_images", product_imagesChildRoute);
|
|
38
|
-
router.use("/products/:product_id/product_variants", product_variantsChildRoute);
|
|
39
|
-
router.use("/products/:product_id/product_reviews", product_reviewsChildRoute);
|
|
40
|
-
router.use("/carts/:cart_id/cart_items", cart_itemsChildRoute);
|
|
41
|
-
router.use("/orders/:order_id/order_items", order_itemsChildRoute);
|
|
42
|
-
router.use("/orders/:order_id/payments", paymentsChildRoute);
|
|
43
|
-
router.use("/orders/:order_id/shipments", shipmentsChildRoute);
|
|
44
30
|
|
|
45
31
|
// Schema-generated routes
|
|
46
32
|
router.use("/addresses", addressesRoute);
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { orders } from "#models";
|
|
4
|
+
import order_itemsRoute from "./order_items/index.js";
|
|
5
|
+
import paymentsRoute from "./payments/index.js";
|
|
6
|
+
import shipmentsRoute from "./shipments/index.js";
|
|
3
7
|
|
|
8
|
+
const router = express.Router({ mergeParams: true });
|
|
4
9
|
const { route } = dbModelRouter;
|
|
5
10
|
|
|
6
|
-
|
|
11
|
+
router.use("/:order_id/order_items", order_itemsRoute);
|
|
12
|
+
router.use("/:order_id/payments", paymentsRoute);
|
|
13
|
+
router.use("/:order_id/shipments", shipmentsRoute);
|
|
14
|
+
|
|
15
|
+
// CRUD routes for orders
|
|
16
|
+
router.use("/", route(orders));
|
|
17
|
+
|
|
18
|
+
export default router;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { order_items } from "#models";
|
|
3
4
|
|
|
5
|
+
const router = express.Router({ mergeParams: true });
|
|
4
6
|
const { route } = dbModelRouter;
|
|
5
7
|
|
|
6
8
|
// Child route: scoped by parent orders via order_id
|
|
7
|
-
|
|
9
|
+
router.use("/", route(order_items, { order_id: "params.order_id" }));
|
|
10
|
+
|
|
11
|
+
export default router;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { payments } from "#models";
|
|
3
4
|
|
|
5
|
+
const router = express.Router({ mergeParams: true });
|
|
4
6
|
const { route } = dbModelRouter;
|
|
5
7
|
|
|
6
8
|
// Child route: scoped by parent orders via order_id
|
|
7
|
-
|
|
9
|
+
router.use("/", route(payments, { order_id: "params.order_id" }));
|
|
10
|
+
|
|
11
|
+
export default router;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { shipments } from "#models";
|
|
3
4
|
|
|
5
|
+
const router = express.Router({ mergeParams: true });
|
|
4
6
|
const { route } = dbModelRouter;
|
|
5
7
|
|
|
6
8
|
// Child route: scoped by parent orders via order_id
|
|
7
|
-
|
|
9
|
+
router.use("/", route(shipments, { order_id: "params.order_id" }));
|
|
10
|
+
|
|
11
|
+
export default router;
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { products } from "#models";
|
|
4
|
+
import product_imagesRoute from "./product_images/index.js";
|
|
5
|
+
import product_variantsRoute from "./product_variants/index.js";
|
|
6
|
+
import product_reviewsRoute from "./product_reviews/index.js";
|
|
3
7
|
|
|
8
|
+
const router = express.Router({ mergeParams: true });
|
|
4
9
|
const { route } = dbModelRouter;
|
|
5
10
|
|
|
6
|
-
|
|
11
|
+
router.use("/:product_id/product_images", product_imagesRoute);
|
|
12
|
+
router.use("/:product_id/product_variants", product_variantsRoute);
|
|
13
|
+
router.use("/:product_id/product_reviews", product_reviewsRoute);
|
|
14
|
+
|
|
15
|
+
// CRUD routes for products
|
|
16
|
+
router.use("/", route(products));
|
|
17
|
+
|
|
18
|
+
export default router;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { product_images } from "#models";
|
|
3
4
|
|
|
5
|
+
const router = express.Router({ mergeParams: true });
|
|
4
6
|
const { route } = dbModelRouter;
|
|
5
7
|
|
|
6
8
|
// Child route: scoped by parent products via product_id
|
|
7
|
-
|
|
9
|
+
router.use("/", route(product_images, { product_id: "params.product_id" }));
|
|
10
|
+
|
|
11
|
+
export default router;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { product_reviews } from "#models";
|
|
3
4
|
|
|
5
|
+
const router = express.Router({ mergeParams: true });
|
|
4
6
|
const { route } = dbModelRouter;
|
|
5
7
|
|
|
6
8
|
// Child route: scoped by parent products via product_id
|
|
7
|
-
|
|
9
|
+
router.use("/", route(product_reviews, { product_id: "params.product_id" }));
|
|
10
|
+
|
|
11
|
+
export default router;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { product_variants } from "#models";
|
|
3
4
|
|
|
5
|
+
const router = express.Router({ mergeParams: true });
|
|
4
6
|
const { route } = dbModelRouter;
|
|
5
7
|
|
|
6
8
|
// Child route: scoped by parent products via product_id
|
|
7
|
-
|
|
9
|
+
router.use("/", route(product_variants, { product_id: "params.product_id" }));
|
|
10
|
+
|
|
11
|
+
export default router;
|
|
@@ -4,7 +4,7 @@ import tenantIsolation from "#middleware/tenantIsolation.js";
|
|
|
4
4
|
import hasPermission from "#middleware/hasPermission.js";
|
|
5
5
|
import { roles } from "#models";
|
|
6
6
|
|
|
7
|
-
const router = express.Router();
|
|
7
|
+
const router = express.Router({ mergeParams: true });
|
|
8
8
|
|
|
9
9
|
function userHasGlobalPermission(req) {
|
|
10
10
|
return req.session.permission.some((p) => p.scope === "global");
|
|
@@ -4,7 +4,7 @@ import tenantIsolation from "#middleware/tenantIsolation.js";
|
|
|
4
4
|
import hasPermission from "#middleware/hasPermission.js";
|
|
5
5
|
import { tenants } from "#models";
|
|
6
6
|
|
|
7
|
-
const router = express.Router();
|
|
7
|
+
const router = express.Router({ mergeParams: true });
|
|
8
8
|
|
|
9
9
|
router.get("/", authenticate, tenantIsolation, hasPermission("tenants", "read"), async (req, res) => {
|
|
10
10
|
try {
|
|
@@ -4,7 +4,7 @@ import tenantIsolation from "#middleware/tenantIsolation.js";
|
|
|
4
4
|
import hasPermission from "#middleware/hasPermission.js";
|
|
5
5
|
import { users } from "#models";
|
|
6
6
|
|
|
7
|
-
const router = express.Router();
|
|
7
|
+
const router = express.Router({ mergeParams: true });
|
|
8
8
|
|
|
9
9
|
router.get("/", authenticate, tenantIsolation, hasPermission("users", "read"), async (req, res) => {
|
|
10
10
|
try {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import dbModelRouter from "db-model-router";
|
|
2
|
+
import express from "express";
|
|
2
3
|
import { wishlists } from "#models";
|
|
3
4
|
|
|
5
|
+
const router = express.Router({ mergeParams: true });
|
|
4
6
|
const { route } = dbModelRouter;
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
router.use("/", route(wishlists));
|
|
9
|
+
|
|
10
|
+
export default router;
|
package/demo/seeds/saas-seed.js
CHANGED
|
@@ -13,7 +13,7 @@ const SUPER_ADMIN_EMAIL = "admin@system.local";
|
|
|
13
13
|
* Generated password for the Super Admin.
|
|
14
14
|
* This is cryptographically random and unique per generation.
|
|
15
15
|
*/
|
|
16
|
-
const SUPER_ADMIN_PASSWORD = "
|
|
16
|
+
const SUPER_ADMIN_PASSWORD = "812fed18236314a46972a977b60c69a5";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Super Admin permissions: all actions for all modules with global scope.
|