db-model-router 1.0.2 → 1.0.3

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.
@@ -46,4 +46,4 @@ CREATE TABLE users (
46
46
  );
47
47
  ```
48
48
 
49
- [← Back to main docs](../README.md)
49
+ [← Back to main docs](../../README.md)
@@ -50,4 +50,4 @@ aws dynamodb create-table \
50
50
  --endpoint-url http://localhost:8000
51
51
  ```
52
52
 
53
- [← Back to main docs](../README.md)
53
+ [← Back to main docs](../../README.md)
@@ -53,4 +53,4 @@ const users = model(
53
53
  );
54
54
  ```
55
55
 
56
- [← Back to main docs](../README.md)
56
+ [← Back to main docs](../../README.md)
@@ -52,4 +52,4 @@ CREATE TABLE users (
52
52
  );
53
53
  ```
54
54
 
55
- [← Back to main docs](../README.md)
55
+ [← Back to main docs](../../README.md)
@@ -49,4 +49,4 @@ CREATE TABLE users (
49
49
  );
50
50
  ```
51
51
 
52
- [← Back to main docs](../README.md)
52
+ [← Back to main docs](../../README.md)
@@ -47,4 +47,4 @@ CREATE TABLE users (
47
47
  );
48
48
  ```
49
49
 
50
- [← Back to main docs](../README.md)
50
+ [← Back to main docs](../../README.md)
@@ -50,4 +50,4 @@ const users = model(
50
50
  );
51
51
  ```
52
52
 
53
- [← Back to main docs](../README.md)
53
+ [← Back to main docs](../../README.md)
@@ -40,4 +40,4 @@ CREATE TABLE users (
40
40
  );
41
41
  ```
42
42
 
43
- [← Back to main docs](../README.md)
43
+ [← Back to main docs](../../README.md)
package/package.json CHANGED
@@ -1,12 +1,10 @@
1
1
  {
2
2
  "name": "db-model-router",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Generative API Creation using mysql2 and express libraries in node js",
5
5
  "main": "src/index.js",
6
6
  "bin": {
7
- "db-model-router-generate-model": "src/cli/generate-model.js",
8
- "db-model-router-generate-route": "src/cli/generate-route.js",
9
- "db-model-router-generate-app": "src/cli/generate-app.js"
7
+ "db-model-router": "src/cli/main.js"
10
8
  },
11
9
  "scripts": {
12
10
  "dev": "nodemon src/serve.js",
@@ -43,6 +41,7 @@
43
41
  "homepage": "https://github.com/AvinashSKaranth/db-model-router#readme",
44
42
  "dependencies": {
45
43
  "dotenv": "^10.0.0",
44
+ "inquirer": "^8.2.6",
46
45
  "lodash": "^4.17.21",
47
46
  "node-input-validator": "^4.5.0"
48
47
  },
@@ -95,7 +94,6 @@
95
94
  }
96
95
  },
97
96
  "devDependencies": {
98
- "better-sqlite3": "^12.9.0",
99
97
  "dotenv-cli": "^11.0.0",
100
98
  "express": "^4.21.0",
101
99
  "faker": "^5.5.3",
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const { parseSchema } = require("../../schema/schema-parser");
6
+ const { SchemaValidationError } = require("../../schema/schema-validator");
7
+ const { schemaToModelMeta } = require("../../schema/schema-to-meta");
8
+ const { computeDiff } = require("../diff-engine");
9
+
10
+ /**
11
+ * Diff command handler for the unified CLI.
12
+ *
13
+ * Compares the current generated files against what the schema would produce,
14
+ * reporting additions, modifications (with line diffs), and deletions.
15
+ * Does NOT modify any files on disk.
16
+ *
17
+ * Supported flags:
18
+ * --from Path to schema file (default: dbmr.schema.json)
19
+ * --json Output JSON result via ctx
20
+ *
21
+ * @param {object} args - Parsed key-value args
22
+ * @param {object} flags - Universal flags: { yes, json, dryRun, noInstall, help }
23
+ * @param {import('../flags').OutputContext} ctx - Output context
24
+ */
25
+ async function diff(args, flags, ctx) {
26
+ const schemaFile = args.from || "dbmr.schema.json";
27
+ const schemaPath = path.resolve(schemaFile);
28
+ const baseDir = process.cwd();
29
+
30
+ // --- 1. Read and parse schema ---
31
+ if (!fs.existsSync(schemaPath)) {
32
+ const msg = `Schema file not found: ${schemaFile}`;
33
+ if (flags.json) {
34
+ ctx.result({ error: true, code: "SCHEMA_NOT_FOUND", message: msg });
35
+ } else {
36
+ ctx.log(`Error: ${msg}`);
37
+ }
38
+ process.exitCode = 1;
39
+ return;
40
+ }
41
+
42
+ let schema;
43
+ try {
44
+ const raw = fs.readFileSync(schemaPath, "utf8");
45
+ schema = parseSchema(raw);
46
+ } catch (err) {
47
+ const msg = `Schema parse error: ${err.message}`;
48
+ if (flags.json) {
49
+ ctx.result({
50
+ error: true,
51
+ code: "SCHEMA_VALIDATION",
52
+ message: msg,
53
+ errors: err.errors || [],
54
+ });
55
+ } else {
56
+ ctx.log(`Error: ${msg}`);
57
+ }
58
+ process.exitCode = 1;
59
+ return;
60
+ }
61
+
62
+ // --- 2. Compute diff ---
63
+ const meta = schemaToModelMeta(schema);
64
+ const relationships = schema.relationships || [];
65
+ const result = computeDiff(baseDir, meta, relationships);
66
+
67
+ // --- 3. Output results ---
68
+ if (flags.json) {
69
+ ctx.result({
70
+ added: result.added,
71
+ modified: result.modified,
72
+ deleted: result.deleted,
73
+ });
74
+ } else {
75
+ const total =
76
+ result.added.length + result.modified.length + result.deleted.length;
77
+
78
+ if (total === 0) {
79
+ ctx.log("All generated files are up to date.");
80
+ return;
81
+ }
82
+
83
+ if (result.added.length > 0) {
84
+ ctx.log("Added (new files to create):");
85
+ for (const f of result.added) {
86
+ ctx.log(` + ${f}`);
87
+ }
88
+ }
89
+
90
+ if (result.modified.length > 0) {
91
+ ctx.log("Modified (files with changes):");
92
+ for (const m of result.modified) {
93
+ ctx.log(` ~ ${m.file}`);
94
+ // Display line diffs indented
95
+ for (const line of m.diff.split("\n")) {
96
+ if (line) {
97
+ ctx.log(` ${line}`);
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ if (result.deleted.length > 0) {
104
+ ctx.log("Deleted (extra files to remove):");
105
+ for (const f of result.deleted) {
106
+ ctx.log(` - ${f}`);
107
+ }
108
+ }
109
+
110
+ ctx.log(`\n${total} file(s) differ.`);
111
+ }
112
+ }
113
+
114
+ module.exports = diff;
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const { parseSchema } = require("../../schema/schema-parser");
6
+ const { SchemaValidationError } = require("../../schema/schema-validator");
7
+ const { schemaToModelMeta } = require("../../schema/schema-to-meta");
8
+ const { computeDiff } = require("../diff-engine");
9
+
10
+ /**
11
+ * Adapter-to-driver mapping.
12
+ * Maps each supported adapter to the npm package name required.
13
+ */
14
+ const ADAPTER_DRIVER_MAP = {
15
+ mysql: "mysql2",
16
+ postgres: "pg",
17
+ sqlite3: "better-sqlite3",
18
+ mongodb: "mongodb",
19
+ mssql: "tedious",
20
+ cockroachdb: "pg",
21
+ oracle: "oracledb",
22
+ redis: "redis",
23
+ dynamodb: "@aws-sdk/client-dynamodb",
24
+ };
25
+
26
+ /**
27
+ * Doctor command handler for the unified CLI.
28
+ *
29
+ * Validates the schema, checks adapter driver dependencies in package.json,
30
+ * and verifies generated files are in sync with the schema.
31
+ *
32
+ * Supported flags:
33
+ * --from Path to schema file (default: dbmr.schema.json)
34
+ * --json Output JSON result via ctx
35
+ *
36
+ * @param {object} args - Parsed key-value args
37
+ * @param {object} flags - Universal flags: { yes, json, dryRun, noInstall, help }
38
+ * @param {import('../flags').OutputContext} ctx - Output context
39
+ */
40
+ async function doctor(args, flags, ctx) {
41
+ const schemaFile = args.from || "dbmr.schema.json";
42
+ const schemaPath = path.resolve(schemaFile);
43
+ const baseDir = process.cwd();
44
+
45
+ // --- 1. Schema validation ---
46
+ const validation = { valid: true, errors: [] };
47
+ let schema = null;
48
+
49
+ if (!fs.existsSync(schemaPath)) {
50
+ validation.valid = false;
51
+ validation.errors.push({
52
+ path: "",
53
+ message: `Schema file not found: ${schemaFile}`,
54
+ });
55
+ } else {
56
+ try {
57
+ const raw = fs.readFileSync(schemaPath, "utf8");
58
+ schema = parseSchema(raw);
59
+ } catch (err) {
60
+ validation.valid = false;
61
+ if (err instanceof SchemaValidationError) {
62
+ validation.errors = err.errors;
63
+ } else {
64
+ validation.errors.push({ path: "", message: err.message });
65
+ }
66
+ }
67
+ }
68
+
69
+ // --- 2. Dependency check ---
70
+ const dependencies = { ok: true, missing: [] };
71
+
72
+ if (schema) {
73
+ const driver = ADAPTER_DRIVER_MAP[schema.adapter];
74
+ if (driver) {
75
+ const pkgPath = path.join(baseDir, "package.json");
76
+ if (fs.existsSync(pkgPath)) {
77
+ try {
78
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
79
+ const allDeps = Object.assign(
80
+ {},
81
+ pkg.dependencies || {},
82
+ pkg.devDependencies || {},
83
+ );
84
+ if (!allDeps[driver]) {
85
+ dependencies.ok = false;
86
+ dependencies.missing.push({
87
+ adapter: schema.adapter,
88
+ driver,
89
+ });
90
+ }
91
+ } catch (_) {
92
+ // If package.json is unreadable, report driver as missing
93
+ dependencies.ok = false;
94
+ dependencies.missing.push({
95
+ adapter: schema.adapter,
96
+ driver,
97
+ });
98
+ }
99
+ } else {
100
+ dependencies.ok = false;
101
+ dependencies.missing.push({
102
+ adapter: schema.adapter,
103
+ driver,
104
+ });
105
+ }
106
+ }
107
+ }
108
+
109
+ // --- 3. Sync check ---
110
+ const sync = { ok: true, outOfSync: [] };
111
+
112
+ if (schema) {
113
+ const meta = schemaToModelMeta(schema);
114
+ const relationships = schema.relationships || [];
115
+ const diff = computeDiff(baseDir, meta, relationships);
116
+
117
+ if (
118
+ diff.added.length > 0 ||
119
+ diff.modified.length > 0 ||
120
+ diff.deleted.length > 0
121
+ ) {
122
+ sync.ok = false;
123
+ for (const f of diff.added) {
124
+ sync.outOfSync.push({ file: f, status: "missing" });
125
+ }
126
+ for (const m of diff.modified) {
127
+ sync.outOfSync.push({ file: m.file, status: "modified" });
128
+ }
129
+ for (const f of diff.deleted) {
130
+ sync.outOfSync.push({ file: f, status: "extra" });
131
+ }
132
+ }
133
+ }
134
+
135
+ // --- 4. Report results ---
136
+ const allPass = validation.valid && dependencies.ok && sync.ok;
137
+ const report = { validation, dependencies, sync };
138
+
139
+ if (flags.json) {
140
+ ctx.result(report);
141
+ } else {
142
+ // Validation
143
+ if (validation.valid) {
144
+ ctx.log("✓ Schema validation passed");
145
+ } else {
146
+ ctx.log("✗ Schema validation failed:");
147
+ for (const e of validation.errors) {
148
+ const loc = e.path ? ` (${e.path})` : "";
149
+ ctx.log(` ${e.message}${loc}`);
150
+ }
151
+ }
152
+
153
+ // Dependencies
154
+ if (dependencies.ok) {
155
+ ctx.log("✓ Dependencies OK");
156
+ } else {
157
+ ctx.log("✗ Missing dependencies:");
158
+ for (const m of dependencies.missing) {
159
+ ctx.log(` ${m.adapter} requires "${m.driver}" in package.json`);
160
+ }
161
+ }
162
+
163
+ // Sync
164
+ if (sync.ok) {
165
+ ctx.log("✓ Generated files in sync");
166
+ } else {
167
+ ctx.log("✗ Files out of sync:");
168
+ for (const s of sync.outOfSync) {
169
+ ctx.log(` ${s.file} (${s.status})`);
170
+ }
171
+ }
172
+ }
173
+
174
+ // --- 5. Exit code ---
175
+ if (!allPass) {
176
+ process.exitCode = 1;
177
+ }
178
+ }
179
+
180
+ module.exports = doctor;
181
+ module.exports.ADAPTER_DRIVER_MAP = ADAPTER_DRIVER_MAP;