@aimeloic/monkey-tester 2.0.2 → 2.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.
Files changed (2) hide show
  1. package/index.js +52 -66
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -54,23 +54,49 @@ export function endtesterExpress() {
54
54
  }
55
55
 
56
56
  // =========================
57
- // Extract req.body fields (FIXED MULTI-LINE)
57
+ // Context-Aware Static Fallbacks
58
+ // =========================
59
+ function getFallbackFieldsForPath(path) {
60
+ const lowerPath = path.toLowerCase();
61
+ let rawFields = [];
62
+
63
+ if (lowerPath.includes('login') || lowerPath.includes('auth') || lowerPath.includes('signin')) {
64
+ rawFields = ['email', 'password'];
65
+ } else if (lowerPath.includes('user') || lowerPath.includes('register') || lowerPath.includes('signup')) {
66
+ rawFields = ['username', 'email', 'password'];
67
+ } else if (lowerPath.includes('product')) {
68
+ rawFields = ['name', 'price', 'stock'];
69
+ } else {
70
+ return [];
71
+ }
72
+
73
+ return rawFields.map(field => ({
74
+ name: field,
75
+ label: field.charAt(0).toUpperCase() + field.slice(1),
76
+ type: detectInputType(field),
77
+ placeholder: `Enter ${field}`
78
+ }));
79
+ }
80
+
81
+ // =========================
82
+ // Extract req.body fields via Source Inspection
58
83
  // =========================
59
84
  function extractBodyFields(handler) {
60
85
  try {
61
86
  const source = handler.toString();
87
+
88
+ // If it's a bound handler or lacks source reference code text
89
+ if (!source || source.includes('[native code]')) return [];
62
90
 
63
- // FIXED: The 's' flag allows matching across multiple lines (\n)
64
91
  const regex = /(const|let|var)\s*\{\s*([^}]+)\s*\}\s*=\s*req\.body/gs;
65
92
  const matches = [...source.matchAll(regex)];
66
93
  const fields = [];
67
94
 
68
95
  matches.forEach((match) => {
69
- // Clean out formatting line-breaks, tabs, or rogue inner code comments
70
96
  const cleanedVariablesBlock = match[2]
71
- .replace(/\/\/.*$/gm, '') // strip inline comments
72
- .replace(/\/\*[\s\S]*?\*\//g, '') // strip block comments
73
- .replace(/[\r\n\t]/g, ' '); // normalize lines to spaces
97
+ .replace(/\/\/.*$/gm, '')
98
+ .replace(/\/\*[\s\S]*?\*\//g, '')
99
+ .replace(/[\r\n\t]/g, ' ');
74
100
 
75
101
  const variables = cleanedVariablesBlock
76
102
  .split(',')
@@ -80,29 +106,22 @@ export function endtesterExpress() {
80
106
  variables.forEach((field) => {
81
107
  let realField = field;
82
108
 
83
- // Support aliases (e.g., name: username)
84
109
  if (field.includes(':')) {
85
110
  realField = field.split(':')[0].trim();
86
111
  }
87
112
 
88
- // Remove defaults values (e.g., age = 0)
89
113
  if (realField.includes('=')) {
90
114
  realField = realField.split('=')[0].trim();
91
115
  }
92
116
 
93
- // Clean any trailing whitespace variations
94
117
  realField = realField.trim();
95
118
 
96
- const alreadyExists = fields.find(
97
- f => f.name === realField
98
- );
119
+ const alreadyExists = fields.find(f => f.name === realField);
99
120
 
100
121
  if (!alreadyExists && realField) {
101
122
  fields.push({
102
123
  name: realField,
103
- label:
104
- realField.charAt(0).toUpperCase() +
105
- realField.slice(1),
124
+ label: realField.charAt(0).toUpperCase() + realField.slice(1),
106
125
  type: detectInputType(realField),
107
126
  placeholder: `Enter ${realField}`
108
127
  });
@@ -128,13 +147,8 @@ export function endtesterExpress() {
128
147
  // ROUTES
129
148
  // =========================
130
149
  if (layer.route) {
131
- const methods = Object.keys(
132
- layer.route.methods
133
- );
134
-
135
- const path = (
136
- prefix + layer.route.path
137
- ).replace(/\/+/g, '/');
150
+ const methods = Object.keys(layer.route.methods);
151
+ const path = (prefix + layer.route.path).replace(/\/+/g, '/');
138
152
 
139
153
  if (path.includes('/api/tester')) {
140
154
  return;
@@ -142,14 +156,8 @@ export function endtesterExpress() {
142
156
 
143
157
  methods.forEach((method) => {
144
158
  const httpMethod = method.toUpperCase();
159
+ const key = `${httpMethod.toLowerCase()}-` + path.replace(/[^a-zA-Z0-9]/g, '-');
145
160
 
146
- const key =
147
- `${httpMethod.toLowerCase()}-` +
148
- path.replace(/[^a-zA-Z0-9]/g, '-');
149
-
150
- // =========================
151
- // PATH PARAMS
152
- // =========================
153
161
  const pathParams = layer.route.keys
154
162
  ? layer.route.keys.map((k) => ({
155
163
  name: k.name,
@@ -159,37 +167,27 @@ export function endtesterExpress() {
159
167
  : [];
160
168
 
161
169
  // =========================
162
- // BODY FIELDS
170
+ // BODY FIELDS COMPILING
163
171
  // =========================
164
172
  let bodyFields = [];
165
173
 
166
- if (
167
- ['POST', 'PUT', 'PATCH'].includes(
168
- httpMethod
169
- )
170
- ) {
174
+ if (['POST', 'PUT', 'PATCH'].includes(httpMethod)) {
171
175
  layer.route.stack.forEach((stackLayer) => {
172
- if (
173
- stackLayer.handle &&
174
- typeof stackLayer.handle === 'function'
175
- ) {
176
- const extractedFields =
177
- extractBodyFields(
178
- stackLayer.handle
179
- );
180
-
176
+ if (stackLayer.handle && typeof stackLayer.handle === 'function') {
177
+ const extractedFields = extractBodyFields(stackLayer.handle);
181
178
  bodyFields.push(...extractedFields);
182
179
  }
183
180
  });
184
181
 
185
- // Remove duplicates
182
+ // Deduplicate discovered elements
186
183
  bodyFields = bodyFields.filter(
187
- (field, index, self) =>
188
- index ===
189
- self.findIndex(
190
- f => f.name === field.name
191
- )
184
+ (field, index, self) => index === self.findIndex(f => f.name === field.name)
192
185
  );
186
+
187
+ // CRITICAL FAILSAFE: If code reflection extracted nothing, apply smart path-based fallback fields
188
+ if (bodyFields.length === 0) {
189
+ bodyFields = getFallbackFieldsForPath(path);
190
+ }
193
191
  }
194
192
 
195
193
  detectedEndpoints[key] = {
@@ -219,10 +217,7 @@ export function endtesterExpress() {
219
217
  .match(/^\/\^\\(.*?)\\\/\?/);
220
218
 
221
219
  if (match && match[1]) {
222
- routerPath = match[1].replace(
223
- /\\/g,
224
- ''
225
- );
220
+ routerPath = match[1].replace(/\\/g, '');
226
221
  }
227
222
  }
228
223
 
@@ -237,24 +232,15 @@ export function endtesterExpress() {
237
232
  // =========================
238
233
  // START PARSING
239
234
  // =========================
240
- if (
241
- expressApp._router &&
242
- expressApp._router.stack
243
- ) {
235
+ if (expressApp._router && expressApp._router.stack) {
244
236
  parseStack(expressApp._router.stack);
245
237
  }
246
238
 
247
239
  // =========================
248
240
  // RENDER HTML
249
241
  // =========================
250
- const fullHtml =
251
- getHtmlTemplate(detectedEndpoints);
252
-
253
- res.setHeader(
254
- 'Content-Type',
255
- 'text/html'
256
- );
257
-
242
+ const fullHtml = getHtmlTemplate(detectedEndpoints);
243
+ res.setHeader('Content-Type', 'text/html');
258
244
  return res.send(fullHtml);
259
245
  };
260
246
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aimeloic/monkey-tester",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "Auto route scanning visual runner dashboard.",
5
5
  "main": "index.js",
6
6
  "type": "module",