quar 2.0.0 → 2.1.0
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/CHANGELOG.md +13 -0
- package/package.json +4 -2
- package/server.js +166 -174
- package/utils/loadModels.js +21 -18
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quar",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "This will load all Mongoose models from the folder and start a local web UI to Create, view, update, and delete documents.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
"chalk": "^5.4.1",
|
|
23
23
|
"express": "^5.1.0",
|
|
24
24
|
"minimist": "^1.2.8",
|
|
25
|
-
"mongoose": "^9.1.1",
|
|
26
25
|
"open": "^10.1.2",
|
|
27
26
|
"zare": "2.6.0"
|
|
28
27
|
},
|
|
@@ -36,5 +35,8 @@
|
|
|
36
35
|
"homepage": "https://github.com/IsmailBinMujeeb/quar-studio#readme",
|
|
37
36
|
"devDependencies": {
|
|
38
37
|
"@changesets/cli": "^2.29.8"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"mongoose": "^9.1.1"
|
|
39
41
|
}
|
|
40
42
|
}
|
package/server.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import express from
|
|
2
|
-
import mongoose from
|
|
3
|
-
import path from "path"
|
|
4
|
-
import loadModels from
|
|
1
|
+
import express from "express";
|
|
2
|
+
import mongoose from "mongoose";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import loadModels from "./utils/loadModels.js";
|
|
5
5
|
|
|
6
6
|
const app = express();
|
|
7
7
|
const PORT = 8319;
|
|
8
8
|
|
|
9
|
-
app.set(
|
|
9
|
+
app.set("view engine", "zare");
|
|
10
10
|
app.set("views", path.join(import.meta.dirname, "views"));
|
|
11
11
|
app.set("port", PORT);
|
|
12
12
|
|
|
@@ -14,229 +14,221 @@ app.use(express.static(path.join(import.meta.dirname, "public")));
|
|
|
14
14
|
app.use(express.json());
|
|
15
15
|
app.use(express.urlencoded({ extended: true }));
|
|
16
16
|
|
|
17
|
-
app.get(
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
app.get("/", async (_, res) => {
|
|
18
|
+
try {
|
|
19
|
+
const modelNames = mongoose.modelNames();
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
modelNames.sort((a, b) => a.localeCompare(b));
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
const result = await Promise.all(
|
|
24
|
+
modelNames.map(async (name) => {
|
|
25
|
+
const model = mongoose.model(name);
|
|
26
|
+
const count = await model.countDocuments();
|
|
27
|
+
return { name, count };
|
|
28
|
+
})
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
res.render("pages/index", { models: result });
|
|
32
|
+
} catch (error) {
|
|
33
|
+
res.status(500).json({ error: error.message || "Internal server error" });
|
|
34
|
+
}
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
app.get("/models", async (_, res) => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
38
|
+
try {
|
|
39
|
+
if (!app.locals.modelPath)
|
|
40
|
+
return res.status(409).json({ error: "model directory path not set" });
|
|
41
|
+
loadModels(app.locals.modelPath);
|
|
42
|
+
const modelNames = mongoose.modelNames();
|
|
43
|
+
modelNames.sort((a, b) => a.localeCompare(b));
|
|
44
|
+
|
|
45
|
+
const result = await Promise.all(
|
|
46
|
+
modelNames.map(async (name) => {
|
|
47
|
+
const model = mongoose.model(name);
|
|
48
|
+
const count = await model.countDocuments();
|
|
49
|
+
return { name, count };
|
|
50
|
+
})
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
res.status(200).json({ models: result });
|
|
54
|
+
} catch (error) {
|
|
55
|
+
res.status(500).json({ error: error.message || "Internal server error" });
|
|
56
|
+
}
|
|
58
57
|
});
|
|
59
58
|
|
|
60
59
|
app.get("/models/:modelName", async (req, res) => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
60
|
+
try {
|
|
61
|
+
const { modelName } = req.params;
|
|
62
|
+
const { page = 1, limit = 100 } = req.query;
|
|
63
|
+
const model = mongoose.model(modelName);
|
|
64
|
+
const documents = await model
|
|
65
|
+
.find({})
|
|
66
|
+
.limit(limit)
|
|
67
|
+
.skip((page - 1) * limit);
|
|
68
|
+
const totalCount = await model.countDocuments();
|
|
69
|
+
const count = documents.length;
|
|
70
|
+
const totalPages = Math.ceil(totalCount / limit);
|
|
71
|
+
|
|
72
|
+
res.status(200).json({ documents, totalCount, count, totalPages });
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.log(error);
|
|
75
|
+
res.status(500).json({ error: error.message || "Internal server error" });
|
|
76
|
+
}
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
app.get("/schema/:modelName", async (req, res) => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (!Model) return res.status(404).json({ error: 'Model not found' });
|
|
85
|
-
|
|
86
|
-
const paths = Model.schema.paths;
|
|
87
|
-
const schema = {};
|
|
80
|
+
try {
|
|
81
|
+
const modelName = req.params.modelName;
|
|
82
|
+
const Model = mongoose.model(modelName);
|
|
88
83
|
|
|
89
|
-
|
|
90
|
-
for (const path in paths) {
|
|
84
|
+
if (!Model) return res.status(404).json({ error: "Model not found" });
|
|
91
85
|
|
|
92
|
-
|
|
86
|
+
const paths = Model.schema.paths;
|
|
87
|
+
const schema = {};
|
|
93
88
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
};
|
|
89
|
+
function getSchema(paths) {
|
|
90
|
+
for (const path in paths) {
|
|
91
|
+
if (path === "_id" || path === "__v") continue;
|
|
98
92
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
93
|
+
if (paths[path].instance === "Embedded") {
|
|
94
|
+
getSchema(paths[path].schema.paths);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
102
97
|
|
|
103
|
-
|
|
98
|
+
const field = paths[path];
|
|
99
|
+
const fieldType = field.instance;
|
|
100
|
+
const fieldOptions = Object.assign({}, field.options);
|
|
104
101
|
|
|
105
|
-
|
|
106
|
-
type: fieldType,
|
|
107
|
-
...fieldOptions
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
getSchema(paths)
|
|
102
|
+
delete fieldOptions["type"];
|
|
112
103
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
104
|
+
schema[path] = {
|
|
105
|
+
type: fieldType,
|
|
106
|
+
...fieldOptions,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
116
109
|
}
|
|
110
|
+
getSchema(paths);
|
|
111
|
+
|
|
112
|
+
res.status(200).json(schema);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
res.status(500).json({ error: error.message || "Intenral Server Error" });
|
|
115
|
+
}
|
|
117
116
|
});
|
|
118
117
|
|
|
119
118
|
app.get("/id/:modelName", async (req, res) => {
|
|
119
|
+
try {
|
|
120
|
+
const { modelName } = req.params;
|
|
121
|
+
const Model = mongoose.model(modelName);
|
|
122
|
+
if (!Model) return res.status(404).json({ error: "model not found" });
|
|
120
123
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const Model = mongoose.model(modelName)
|
|
124
|
-
if (!Model) return res.status(404).json({ error: "model not found" });
|
|
125
|
-
|
|
126
|
-
const docs = await Model.find({});
|
|
127
|
-
const ids = [];
|
|
124
|
+
const docs = await Model.find({});
|
|
125
|
+
const ids = [];
|
|
128
126
|
|
|
129
|
-
|
|
127
|
+
docs.map((doc) => ids.push(doc._id));
|
|
130
128
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
})
|
|
129
|
+
res.status(200).json(ids);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
res.status(500).json({ error: error.message || "Internal server error" });
|
|
132
|
+
}
|
|
133
|
+
});
|
|
136
134
|
|
|
137
135
|
app.post("/insert/:modelName", async (req, res) => {
|
|
136
|
+
try {
|
|
137
|
+
const { modelName } = req.params;
|
|
138
|
+
const body = req.body;
|
|
138
139
|
|
|
139
|
-
|
|
140
|
-
const { modelName } = req.params;
|
|
141
|
-
const body = req.body;
|
|
140
|
+
const Model = mongoose.model(modelName);
|
|
142
141
|
|
|
143
|
-
|
|
142
|
+
if (!Model) return res.status(404).json({ error: "model not found" });
|
|
144
143
|
|
|
145
|
-
|
|
144
|
+
const paths = Model.schema.paths;
|
|
146
145
|
|
|
147
|
-
|
|
146
|
+
function getSchema(paths) {
|
|
147
|
+
let schema = {};
|
|
148
|
+
for (const path in paths) {
|
|
149
|
+
if (path === "_id" || path === "__v") continue;
|
|
148
150
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
for (const path in paths) {
|
|
153
|
-
|
|
154
|
-
if (path === '_id' || path === '__v') continue;
|
|
155
|
-
|
|
156
|
-
if (paths[path].instance === 'Embedded') {
|
|
157
|
-
schema[path] = getSchema(paths[path].schema.paths);
|
|
158
|
-
continue;
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
schema[path] = paths[path].instance;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return schema;
|
|
151
|
+
if (paths[path].instance === "Embedded") {
|
|
152
|
+
schema[path] = getSchema(paths[path].schema.paths);
|
|
153
|
+
continue;
|
|
165
154
|
}
|
|
166
155
|
|
|
167
|
-
|
|
156
|
+
schema[path] = paths[path].instance;
|
|
157
|
+
}
|
|
168
158
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
let data = {};
|
|
172
|
-
|
|
173
|
-
for (const key in schema) {
|
|
174
|
-
if (typeof schema[key] === 'object' && schema[key] !== null) {
|
|
159
|
+
return schema;
|
|
160
|
+
}
|
|
175
161
|
|
|
176
|
-
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
162
|
+
const schema = getSchema(paths);
|
|
179
163
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
}
|
|
164
|
+
function getData(body, schema) {
|
|
165
|
+
let data = {};
|
|
184
166
|
|
|
185
|
-
|
|
167
|
+
for (const key in schema) {
|
|
168
|
+
if (typeof schema[key] === "object" && schema[key] !== null) {
|
|
169
|
+
data[key] = getData(body, schema[key]);
|
|
170
|
+
continue;
|
|
186
171
|
}
|
|
187
172
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
173
|
+
if (Object.keys(body).includes(key)) {
|
|
174
|
+
data[key] = body[key];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
191
177
|
|
|
192
|
-
|
|
193
|
-
} catch (error) {
|
|
194
|
-
res.status(500).json({ error: error.message || "Internal server error" })
|
|
178
|
+
return data;
|
|
195
179
|
}
|
|
196
|
-
})
|
|
197
180
|
|
|
198
|
-
|
|
199
|
-
try {
|
|
200
|
-
const { modelName, id } = req.params;
|
|
201
|
-
const model = mongoose.model(modelName);
|
|
202
|
-
const updatedDoc = req.body;
|
|
181
|
+
const data = getData(body, schema);
|
|
203
182
|
|
|
204
|
-
|
|
205
|
-
const result = await model.findByIdAndUpdate(id, updatedDoc, { new: true });
|
|
183
|
+
const result = await Model.create(data);
|
|
206
184
|
|
|
207
|
-
|
|
208
|
-
|
|
185
|
+
res.status(200).json(result);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
res.status(500).json({ error: error.message || "Internal server error" });
|
|
188
|
+
}
|
|
189
|
+
});
|
|
209
190
|
|
|
210
|
-
|
|
211
|
-
|
|
191
|
+
app.put("/update/:modelName/:id", async (req, res) => {
|
|
192
|
+
try {
|
|
193
|
+
const { modelName, id } = req.params;
|
|
194
|
+
const model = mongoose.model(modelName);
|
|
195
|
+
const updatedDoc = req.body;
|
|
196
|
+
|
|
197
|
+
delete updatedDoc._id;
|
|
198
|
+
const result = await model.findByIdAndUpdate(id, updatedDoc, { new: true });
|
|
199
|
+
|
|
200
|
+
res.status(200).json(result);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
res.status(500).json({ error: error.message || "Internal server error" });
|
|
203
|
+
}
|
|
212
204
|
});
|
|
213
205
|
|
|
214
206
|
app.delete("/delete/:modelName/:id", async (req, res) => {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
207
|
+
try {
|
|
208
|
+
const { modelName, id } = req.params;
|
|
209
|
+
const model = mongoose.model(modelName);
|
|
218
210
|
|
|
219
|
-
|
|
220
|
-
|
|
211
|
+
await model.findByIdAndDelete(id);
|
|
212
|
+
const count = await model.countDocuments();
|
|
221
213
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
214
|
+
res.status(200).json({ count });
|
|
215
|
+
} catch (error) {
|
|
216
|
+
res.status(500).json({ error: error.message || "Internal server error" });
|
|
217
|
+
}
|
|
226
218
|
});
|
|
227
219
|
|
|
228
220
|
app.delete("/delete-all/:modelName", async (req, res) => {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
221
|
+
try {
|
|
222
|
+
const { modelName } = req.params;
|
|
223
|
+
const model = mongoose.model(modelName);
|
|
224
|
+
if (!model) return res.status(404).json({ error: "model not found" });
|
|
233
225
|
|
|
234
|
-
|
|
226
|
+
await model.deleteMany({});
|
|
235
227
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
})
|
|
228
|
+
res.status(200).json({ success: true });
|
|
229
|
+
} catch (error) {
|
|
230
|
+
res.status(500).json({ error: error.message || "Internal server error" });
|
|
231
|
+
}
|
|
232
|
+
});
|
|
241
233
|
|
|
242
|
-
export default app;
|
|
234
|
+
export default app;
|
package/utils/loadModels.js
CHANGED
|
@@ -5,23 +5,26 @@ import chalk from "chalk";
|
|
|
5
5
|
import { pathToFileURL } from "url";
|
|
6
6
|
|
|
7
7
|
export default (modelPath) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
if (!fs.existsSync(modelPath)) {
|
|
9
|
+
console.log(
|
|
10
|
+
chalk.red.bold("[ERROR]") +
|
|
11
|
+
" The specified model path does not exist:\n " +
|
|
12
|
+
chalk.gray(modelPath)
|
|
13
|
+
);
|
|
14
|
+
console.log("Tip: Check the path or create the folder first.");
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
fs.readdirSync(modelPath).forEach(async (file) => {
|
|
19
|
+
if (file.endsWith(".js") || file.endsWith(".ts")) {
|
|
20
|
+
const filePath = path.join(modelPath, file);
|
|
21
|
+
const moduleUrl = pathToFileURL(filePath);
|
|
22
|
+
await import(moduleUrl.href);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
console.log(
|
|
27
|
+
chalk.blue.bold("[INFO]"),
|
|
28
|
+
chalk.gray("Models loaded from: " + modelPath)
|
|
29
|
+
);
|
|
30
|
+
};
|