quar 1.2.1 → 1.2.2

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/index.js CHANGED
@@ -51,9 +51,11 @@ try {
51
51
  (async () => {
52
52
 
53
53
  await mongoose.connect(`${args.uri || "mongodb://localhost:27017/"}${args.db}`)
54
+ console.log( chalk.blue.bold('[INFO]'), chalk.gray("Quar: Database connection established"))
55
+
54
56
  app.listen(app.get('port'), () => {
55
57
  const url = `http://127.0.0.1:${app.get('port')}`;
56
- console.log(chalk.green.bold('[SUCCESS]') + ` Server is running on ${chalk.underline(url)}`);
58
+ console.log(chalk.green.bold('[SUCCESS]') + chalk.gray(` Server is running on ${chalk.underline(url)}`));
57
59
  open(url);
58
60
  });
59
61
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quar",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
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",
@@ -8,7 +8,8 @@
8
8
  "quar": "./index.js"
9
9
  },
10
10
  "scripts": {
11
- "start": "node index.js"
11
+ "start": "node index.js",
12
+ "dev": "node .\\index.js --model .\\models\\ --db shopDB"
12
13
  },
13
14
  "author": "@IsmailBinMujeeb (IsmailBinMujeeb@gmail.com)",
14
15
  "license": "MIT",
@@ -25,6 +25,18 @@ async function toggleInsertTab() {
25
25
  const formData = new FormData(e.target);
26
26
  const data = Object.fromEntries(formData.entries());
27
27
 
28
+ const checkboxes = e.target.querySelectorAll('input[type="checkbox"]');
29
+ checkboxes.forEach(cb => {
30
+ data[cb.name] = cb.checked;
31
+ });
32
+
33
+ const textareas = e.target.querySelectorAll('textarea');
34
+ textareas.forEach(async tarea => {
35
+
36
+ data[tarea.name] = JSON.parse(tarea.value)
37
+
38
+ })
39
+
28
40
  const res = await fetch(`/insert/${modelName}`, {
29
41
  method: 'POST',
30
42
  headers: { 'Content-Type': 'application/json' },
@@ -40,8 +52,12 @@ async function toggleInsertTab() {
40
52
  loadDocuments();
41
53
  });
42
54
 
55
+
43
56
  for (const key in schema) {
57
+
58
+ if (/\.\$\*$/.test(key)) continue;
44
59
  const field = schema[key];
60
+ let inputType = null;
45
61
 
46
62
  const label = document.createElement('label');
47
63
  label.innerHTML = `${key}:`;
@@ -73,8 +89,44 @@ async function toggleInsertTab() {
73
89
  continue;
74
90
  }
75
91
 
92
+ if (field.type === 'String') inputType = 'text';
93
+ else if (field.type === 'Number') inputType = 'number';
94
+ else if (field.type === 'Boolean') inputType = 'checkbox';
95
+ else if (field.type === 'Date') inputType = 'date';
96
+ else if (field.type === 'Array' || field.type === "Map" || field.type === "Object" || field.type == "Mixed" || field.type === "Buffer") {
97
+ const input = document.createElement('textarea');
98
+
99
+ input.placeholder = field.type;
100
+ input.id = key;
101
+ input.name = key;
102
+ input.className = 'input';
103
+ field.type === "Array" ? input.textContent = "[ ]" : input.textContent = "{ }";
104
+ input.required = isRequired(field.require);
105
+ if (field.default !== undefined) input.value = field.default;
106
+
107
+ form.append(label, input);
108
+ continue;
109
+ };
110
+
111
+ if (field.enum) {
112
+ const select = document.createElement('select');
113
+ select.id = key;
114
+ select.name = key;
115
+ select.className = 'input';
116
+
117
+ field.enum.forEach(id => {
118
+ const option = document.createElement('option');
119
+ option.value = id;
120
+ option.innerText = id;
121
+ select.appendChild(option);
122
+ });
123
+
124
+ form.append(label, select);
125
+ continue;
126
+ }
127
+
76
128
  const input = document.createElement('input');
77
- input.type = field.type || 'text';
129
+ input.type = inputType || 'text';
78
130
  input.placeholder = field.type;
79
131
  input.id = key;
80
132
  input.name = key;
@@ -35,6 +35,8 @@ async function activateTab(modelName) {
35
35
 
36
36
  content.dataset.modelName = modelName;
37
37
  document.getElementById("page-value").innerText = 1;
38
+ document.querySelectorAll(".operations .btn")?.forEach( btn => btn.disabled = false )
39
+ document.querySelector(".operations select").disabled = false;
38
40
 
39
41
  const insertTab = document.querySelector('.insert-tab');
40
42
  insertTab.classList.remove('active');
@@ -62,9 +64,18 @@ function closeTab(event, modelName) {
62
64
  const keys = Object.keys(openTabs);
63
65
  const modelName = keys[keys.length - 1] || null;
64
66
  if (modelName) activateTab(modelName);
67
+ else disableAllOptions();
65
68
  }
66
69
  }
67
70
 
71
+ function disableAllOptions() {
72
+ content.dataset.modelName = '';
73
+
74
+ document.querySelectorAll(".operations .btn")?.forEach( btn => btn.disabled = true );
75
+ document.getElementById("document-count").innerText = 0;
76
+ document.querySelector(".operations select").disabled = true;
77
+ }
78
+
68
79
  async function loadDocuments() {
69
80
 
70
81
  content.innerHTML = "";
@@ -267,6 +278,7 @@ async function deleteDoc(modelName, id) {
267
278
  openModel(modelName);
268
279
  const data = await res.json();
269
280
  document.getElementById(`${modelName}-doc-count`).innerText = data.count || 0;
281
+ loadDocuments()
270
282
  } else {
271
283
  showModal('error', 'Delete Failed', await res.json().error || 'Delete failed, please try again.');
272
284
  }
@@ -31,7 +31,9 @@
31
31
  color: var(--text-color);
32
32
  }
33
33
 
34
- #insert-form input, select {
34
+ #insert-form input,
35
+ select,
36
+ textarea {
35
37
  width: 100%;
36
38
  padding: 10px;
37
39
  border: 1px solid var(--muted-color);
@@ -40,6 +42,21 @@
40
42
  color: var(--text-color);
41
43
  }
42
44
 
45
+ #insert-form textarea {
46
+ resize: vertical;
47
+ min-height: fit-content;
48
+ }
49
+
50
+ #insert-form input[type="checkbox"] {
51
+ width: 16px;
52
+ height: 16px;
53
+ accent-color: var(--green-color);
54
+ background-color: var(--bg-color);
55
+ border: 1px solid var(--muted-color);
56
+ border-radius: 10px;
57
+ cursor: pointer;
58
+ }
59
+
43
60
  #insert-form .btn {
44
61
  background: transparent;
45
62
  color: var(--text-color);
@@ -54,4 +71,4 @@
54
71
  background: var(--blue-color);
55
72
  color: var(--bg-color);
56
73
  }
57
- }
74
+ }
package/server.js CHANGED
@@ -108,6 +108,7 @@ app.get("/schema/:modelName", async (req, res) => {
108
108
  }
109
109
  }
110
110
  getSchema(paths)
111
+
111
112
  res.status(200).json(schema);
112
113
  } catch (error) {
113
114
  res.status(500).json({ error: error.message || "Intenral Server Error" })
@@ -22,4 +22,6 @@ export default (modelPath) => {
22
22
  await import(moduleUrl.href);
23
23
  }
24
24
  });
25
+
26
+ console.log(chalk.blue.bold('[INFO]'), chalk.gray("Models loaded from: " + modelPath))
25
27
  }
@@ -37,12 +37,12 @@ serve (
37
37
  <div class="text">Count</div>
38
38
  <div class="count-div" id="document-count">0</div>
39
39
  </div>
40
- <button class="btn" id="previous-page" onclick="gotoPreviousPage()">Previous</button>
40
+ <button class="btn" id="previous-page" onclick="gotoPreviousPage()" disabled>Previous</button>
41
41
  <div class="page-wrapper" id="page" data-page="1">
42
42
  <div class="text">Page</div>
43
43
  <div class="page-div" id="page-value">1</div>
44
44
  </div>
45
- <button class="btn" id="next-page" onclick="gotoNextPage()">Next</button>
45
+ <button class="btn" id="next-page" onclick="gotoNextPage()" disabled>Next</button>
46
46
  <button class="btn" onclick="toggleInsertTab()">Add Record</button>
47
47
  <button class="btn" onclick="deleteAllDocs()">🗑</button>
48
48
  </div>