@aimeloic/monkey-tester 1.0.6 → 1.0.8

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/htmlTemplate.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export function getHtmlTemplate(endpoints) {
2
+ // Safe stringification for HTML attribute encoding to prevent script engine parsing breaks
2
3
  const safeJsonString = Buffer.from(JSON.stringify(endpoints)).toString('base64');
3
4
 
4
5
  return `
@@ -148,13 +149,10 @@ function buildSidebar() {
148
149
  if (keys.length > 0) renderPanel(keys[0]);
149
150
  }
150
151
 
151
- function makeInput(type, id, placeholder, defaultValue) {
152
- var el = document.createElement('input');
153
- el.type = type;
154
- el.id = id;
155
- if (placeholder) el.placeholder = placeholder;
156
- if (defaultValue !== undefined) el.value = defaultValue;
157
- return el.outerHTML;
152
+ function makeInputString(type, id, placeholder, defaultValue) {
153
+ const pAttr = placeholder ? ' placeholder="' + placeholder + '"' : '';
154
+ const vAttr = defaultValue !== undefined ? ' value=\'' + defaultValue + '\'' : '';
155
+ return '<input type="' + type + '" id="' + id + '"' + pAttr + vAttr + ' />';
158
156
  }
159
157
 
160
158
  function renderPanel(epKey) {
@@ -163,39 +161,50 @@ function renderPanel(epKey) {
163
161
  const main = document.getElementById('main-panel');
164
162
  if (!ep) return;
165
163
 
166
- let html = '<div class="endpoint-title">' + ep.title + '</div>' +
167
- '<div class="endpoint-path">' +
168
- '<span class="method-badge ' + ep.method + '">' + ep.method + '</span>' +
169
- '<span>' + ep.path + '</span>' +
170
- '</div>' +
171
- '<div class="endpoint-desc">' + ep.desc + '</div>';
164
+ // Render core elements utilizing un-escaped container tokens safely
165
+ let html = \`
166
+ <div class="endpoint-title">\${ep.title}</div>
167
+ <div class="endpoint-path">
168
+ <span class="method-badge \${ep.method}">\${ep.method}</span>
169
+ <span>\${ep.path}</span>
170
+ </div>
171
+ <div class="endpoint-desc">\${ep.desc}</div>
172
+ \`;
172
173
 
173
174
  if (ep.params && ep.params.length) {
174
- html += '<div class="form-section"><div class="form-section-title">Path Parameters</div>';
175
+ html += \`<div class="form-section"><div class="form-section-title">Path Parameters</div>\`;
175
176
  ep.params.forEach(function(p) {
176
- html += '<div class="field-row">' +
177
- '<label class="field-label">' + p.label + '</label>' +
178
- makeInput('text', 'param-' + p.name, p.placeholder, '') +
179
- '</div>';
177
+ const inputHtml = makeInputString('text', 'param-' + p.name, p.placeholder, '');
178
+ html += \`
179
+ <div class="field-row">
180
+ <label class="field-label">\${p.label}</label>
181
+ \${inputHtml}
182
+ </div>
183
+ \`;
180
184
  });
181
- html += '</div>';
185
+ html += \`</div>\`;
182
186
  }
183
187
 
184
188
  if (ep.fields && ep.fields.length) {
185
- html += '<div class="form-section"><div class="form-section-title">JSON Request Body Raw Payload</div>';
189
+ html += \`<div class="form-section"><div class="form-section-title">JSON Request Body Raw Payload</div>\`;
186
190
  ep.fields.forEach(function(f) {
187
- html += '<div class="field-row">' +
188
- '<label class="field-label">' + f.label + '</label>' +
189
- makeInput('text', 'field-' + f.name, '', '{"key": "value"}') +
190
- '</div>';
191
+ const inputHtml = makeInputString('text', 'field-' + f.name, '', '{"key": "value"}');
192
+ html += \`
193
+ <div class="field-row">
194
+ <label class="field-label">\${f.label}</label>
195
+ \${inputHtml}
196
+ </div>
197
+ \`;
191
198
  });
192
- html += '</div>';
199
+ html += \`</div>\`;
193
200
  }
194
201
 
195
- html += '<div class="btn-row">' +
196
- '<button class="btn" onclick="sendRequest()">Execute Route</button>' +
197
- '<button class="btn btn-secondary" onclick="clearResponse()">Clear Context</button>' +
198
- '</div>';
202
+ html += \`
203
+ <div class="btn-row">
204
+ <button class="btn" onclick="sendRequest()">Execute Route</button>
205
+ <button class="btn btn-secondary" onclick="clearResponse()">Clear Context</button>
206
+ </div>
207
+ \`;
199
208
 
200
209
  main.innerHTML = html;
201
210
  }
@@ -212,7 +221,7 @@ async function sendRequest() {
212
221
  }
213
222
  }
214
223
 
215
- const baseUrl = document.getElementById('base-url').value.replace(/\/+$/, '');
224
+ const baseUrl = document.getElementById('base-url').value.replace(/[/]+$/, '');
216
225
  const url = baseUrl + path;
217
226
  const headers = { 'Content-Type': 'application/json' };
218
227
 
@@ -274,7 +283,7 @@ function clearResponse() {
274
283
 
275
284
  function highlightJson(str) {
276
285
  return str
277
- .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
286
+ .replace(/&/g, '&amp;').replace(/[<]/g, '&lt;').replace(/[>]/g, '&gt;')
278
287
  .replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function(match) {
279
288
  if (/^"/.test(match)) {
280
289
  if (/:$/.test(match)) return '<span class="json-key">' + match + '</span>';
package/index.js CHANGED
@@ -9,17 +9,15 @@ export function endtesterExpress() {
9
9
  const expressApp = req.app;
10
10
  const detectedEndpoints = {};
11
11
 
12
- // Recursive function to dig through all layers of Express routes
13
12
  function parseStack(stack, prefix = '') {
14
13
  if (!stack) return;
15
14
 
16
15
  stack.forEach((layer) => {
17
16
  if (layer.route) {
18
- // It's a direct route (e.g., app.get('/path'))
19
17
  const methods = Object.keys(layer.route.methods);
20
18
  const path = (prefix + layer.route.path).replace(/\/+/g, '/');
21
19
 
22
- if (path.includes('/api/tester')) return; // Skip ourselves
20
+ if (path.includes('/api/tester')) return;
23
21
 
24
22
  methods.forEach((method) => {
25
23
  const httpMethod = method.toUpperCase();
@@ -42,10 +40,8 @@ export function endtesterExpress() {
42
40
  };
43
41
  });
44
42
  } else if (layer.name === 'router' && layer.handle && layer.handle.stack) {
45
- // It's a router middleware (e.g., app.use('/api', myRouter))
46
43
  let routerPath = '';
47
44
  if (layer.regexp) {
48
- // Extract the base path string from the router regex safely
49
45
  const match = layer.regexp.toString().match(/^\/\^\\(.*?)\\\/\?/);
50
46
  if (match && match[1]) {
51
47
  routerPath = match[1].replace(/\\/g, '');
@@ -56,7 +52,6 @@ export function endtesterExpress() {
56
52
  });
57
53
  }
58
54
 
59
- // Fire the scanner on the main app router stack
60
55
  if (expressApp._router && expressApp._router.stack) {
61
56
  parseStack(expressApp._router.stack);
62
57
  }
package/package.json CHANGED
@@ -1,13 +1,10 @@
1
1
  {
2
2
  "name": "@aimeloic/monkey-tester",
3
- "version": "1.0.6",
4
- "description": "Embedded interactive API testing UI for Node.js backends",
3
+ "version": "1.0.8",
4
+ "description": "Auto route scanning visual runner dashboard.",
5
5
  "main": "index.js",
6
- "type":"module",
7
- "scripts": {
8
- "test": "echo \"Error: no test specified\" && exit 1"
9
- },
10
- "keywords": [],
11
- "author": "",
6
+ "type": "module",
7
+ "keywords": ["express", "tester", "autodiscover"],
8
+ "author": "aimeloic",
12
9
  "license": "ISC"
13
10
  }