shokupan 0.10.5 → 0.12.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.
Files changed (73) hide show
  1. package/README.md +46 -1815
  2. package/dist/{analyzer-BqIe1p0R.js → analyzer-BkNQHWj4.js} +3 -8
  3. package/dist/{analyzer-BqIe1p0R.js.map → analyzer-BkNQHWj4.js.map} +1 -1
  4. package/dist/{analyzer-CKLGLFtx.cjs → analyzer-DM-OlRq8.cjs} +2 -7
  5. package/dist/{analyzer-CKLGLFtx.cjs.map → analyzer-DM-OlRq8.cjs.map} +1 -1
  6. package/dist/{analyzer.impl-D9Yi1Hax.cjs → analyzer.impl-CVJ8zfGQ.cjs} +596 -42
  7. package/dist/analyzer.impl-CVJ8zfGQ.cjs.map +1 -0
  8. package/dist/{analyzer.impl-CV6W1Eq7.js → analyzer.impl-CsA1bS_s.js} +596 -42
  9. package/dist/analyzer.impl-CsA1bS_s.js.map +1 -0
  10. package/dist/cli.cjs +206 -18
  11. package/dist/cli.cjs.map +1 -1
  12. package/dist/cli.js +206 -18
  13. package/dist/cli.js.map +1 -1
  14. package/dist/context.d.ts +46 -9
  15. package/dist/index.cjs +3239 -1173
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.js +3236 -1171
  18. package/dist/index.js.map +1 -1
  19. package/dist/plugins/application/api-explorer/static/explorer-client.mjs +375 -29
  20. package/dist/plugins/application/api-explorer/static/style.css +327 -8
  21. package/dist/plugins/application/api-explorer/static/theme.css +11 -2
  22. package/dist/plugins/application/asyncapi/generator.d.ts +4 -0
  23. package/dist/plugins/application/asyncapi/static/asyncapi-client.mjs +154 -22
  24. package/dist/plugins/application/asyncapi/static/style.css +24 -8
  25. package/dist/plugins/application/auth.d.ts +5 -0
  26. package/dist/plugins/application/dashboard/fetch-interceptor.d.ts +119 -0
  27. package/dist/plugins/application/dashboard/metrics-collector.d.ts +38 -2
  28. package/dist/plugins/application/dashboard/plugin.d.ts +53 -1
  29. package/dist/plugins/application/dashboard/static/charts.js +127 -62
  30. package/dist/plugins/application/dashboard/static/client.js +160 -0
  31. package/dist/plugins/application/dashboard/static/graph.mjs +167 -56
  32. package/dist/plugins/application/dashboard/static/reactflow.css +20 -10
  33. package/dist/plugins/application/dashboard/static/registry.js +112 -8
  34. package/dist/plugins/application/dashboard/static/requests.js +1167 -71
  35. package/dist/plugins/application/dashboard/static/styles.css +186 -14
  36. package/dist/plugins/application/dashboard/static/tabs.js +44 -9
  37. package/dist/plugins/application/dashboard/static/tabulator.css +23 -3
  38. package/dist/plugins/application/dashboard/static/theme.css +11 -2
  39. package/dist/plugins/application/mcp-server/plugin.d.ts +39 -0
  40. package/dist/plugins/application/openapi/analyzer.impl.d.ts +65 -1
  41. package/dist/plugins/application/openapi/openapi.d.ts +3 -0
  42. package/dist/plugins/application/shared/ast-utils.d.ts +7 -0
  43. package/dist/plugins/middleware/compression.d.ts +12 -2
  44. package/dist/plugins/middleware/rate-limit.d.ts +5 -0
  45. package/dist/router.d.ts +59 -19
  46. package/dist/server.d.ts +22 -0
  47. package/dist/shokupan.d.ts +31 -3
  48. package/dist/util/adapter/bun.d.ts +8 -0
  49. package/dist/util/adapter/filesystem.d.ts +20 -0
  50. package/dist/util/adapter/index.d.ts +4 -0
  51. package/dist/util/adapter/interface.d.ts +12 -0
  52. package/dist/util/adapter/node.d.ts +8 -0
  53. package/dist/util/adapter/wintercg.d.ts +5 -0
  54. package/dist/util/body-parser.d.ts +30 -0
  55. package/dist/util/controller-scanner.d.ts +4 -0
  56. package/dist/util/cpu-monitor.d.ts +2 -0
  57. package/dist/util/decorators.d.ts +20 -3
  58. package/dist/util/di.d.ts +3 -8
  59. package/dist/util/metadata.d.ts +18 -0
  60. package/dist/util/middleware-tracker.d.ts +10 -0
  61. package/dist/util/request.d.ts +1 -0
  62. package/dist/util/symbol.d.ts +1 -0
  63. package/dist/util/types.d.ts +167 -1
  64. package/package.json +7 -5
  65. package/dist/analyzer.impl-CV6W1Eq7.js.map +0 -1
  66. package/dist/analyzer.impl-D9Yi1Hax.cjs.map +0 -1
  67. package/dist/http-server-BEMPIs33.cjs +0 -85
  68. package/dist/http-server-BEMPIs33.cjs.map +0 -1
  69. package/dist/http-server-CCeagTyU.js +0 -68
  70. package/dist/http-server-CCeagTyU.js.map +0 -1
  71. package/dist/plugins/application/dashboard/static/failures.js +0 -85
  72. package/dist/plugins/application/dashboard/static/poll.js +0 -146
  73. package/dist/plugins/application/http-server.d.ts +0 -13
@@ -14,7 +14,7 @@ html {
14
14
  body {
15
15
  display: flex;
16
16
  flex-direction: column;
17
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
17
+ font-family: var(--shokupan-font);
18
18
  background-color: var(--bg-primary);
19
19
  color: var(--text-primary);
20
20
  height: 100vh;
@@ -26,7 +26,6 @@ header {
26
26
  background-color: var(--bg-header);
27
27
  padding: 0 1rem;
28
28
  display: flex;
29
- justify-content: space-between;
30
29
  align-items: center;
31
30
  }
32
31
 
@@ -56,6 +55,15 @@ select {
56
55
  flex-direction: column;
57
56
  align-items: center;
58
57
  overflow: hidden;
58
+ width: 100%;
59
+ }
60
+
61
+ .contents {
62
+ width: 100%;
63
+ display: flex;
64
+ height: 100%;
65
+ overflow-y: auto;
66
+ justify-content: center;
59
67
  }
60
68
 
61
69
  .metrics-grid {
@@ -116,7 +124,6 @@ select {
116
124
  border: 1px solid var(--card-border);
117
125
  border-radius: 1rem;
118
126
  padding: 1.5rem;
119
- margin-bottom: 2rem;
120
127
  overflow: hidden;
121
128
  }
122
129
 
@@ -125,14 +132,13 @@ select {
125
132
  display: flex;
126
133
  gap: 1rem;
127
134
  border-bottom: 1px solid var(--card-border);
128
- margin-bottom: 2rem;
129
135
  }
130
136
 
131
137
  .tab-btn {
132
138
  background: none;
133
139
  border: none;
134
140
  color: var(--text-secondary);
135
- padding: 1rem;
141
+ padding: .5rem;
136
142
  cursor: pointer;
137
143
  font-size: 1rem;
138
144
  border-bottom: 2px solid transparent;
@@ -154,31 +160,197 @@ select {
154
160
 
155
161
  .tab-content {
156
162
  display: none;
157
- flex-direction: column;
158
163
  flex: 1;
159
- overflow: auto;
160
- width: -webkit-fill-available;
161
- /* width: 1200px; */
162
- max-width: 1200px;
163
- margin: 0 2rem;
164
+ flex-direction: column;
165
+ width: 100%
164
166
  }
165
167
 
166
168
  .tab-content.active {
167
- display: flex;
169
+ display: block;
168
170
  }
169
171
 
170
172
 
171
173
  /* Graph */
172
174
  #cy {
173
- width: 100%;
175
+ width: calc(100% - 4rem);
174
176
  height: 600px;
175
177
  background-color: var(--bg-secondary);
176
- border-radius: 1rem;
178
+ border-radius: 4px;
177
179
  border: 1px solid var(--card-border);
180
+ overflow: hidden
178
181
  }
179
182
 
180
183
  .card-container {
181
184
  display: grid;
182
185
  gap: 1rem;
183
186
  grid-template-columns: 1fr;
187
+ }
188
+
189
+ #tab-overview {
190
+ /* width: 100%; */
191
+ /* max-width: 1200px; */
192
+ max-width: 900px;
193
+ margin: 2rem
194
+ }
195
+
196
+ .button-group {
197
+ display: inline-flex;
198
+ background: var(--bg-secondary);
199
+ padding: 4px;
200
+ border-radius: 8px;
201
+ border: 1px solid var(--card-border);
202
+ }
203
+
204
+ .view-btn {
205
+ background: transparent;
206
+ border: none;
207
+ color: var(--text-secondary);
208
+ padding: 6px 12px;
209
+ border-radius: 6px;
210
+ font-size: 0.9rem;
211
+ cursor: pointer;
212
+ transition: all 0.2s;
213
+ }
214
+
215
+ .view-btn:hover {
216
+ color: var(--text-primary);
217
+ }
218
+
219
+ .view-btn.active {
220
+ background: var(--bg-primary);
221
+ color: var(--accent);
222
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
223
+ font-weight: 500;
224
+ }
225
+
226
+ .app-view {
227
+ display: none;
228
+ flex: 1;
229
+ width: 100%;
230
+ }
231
+
232
+ .app-view.active {
233
+ display: flex;
234
+ flex-direction: column;
235
+ }
236
+
237
+ .traffic-view {
238
+ display: none;
239
+ flex: 1;
240
+ width: 100%;
241
+ }
242
+
243
+ .traffic-view.active {
244
+ display: flex;
245
+ flex-direction: column;
246
+ }
247
+
248
+ .btn-action {
249
+ background: var(--bg-primary);
250
+ border: 1px solid var(--card-border);
251
+ color: var(--text-primary);
252
+ padding: 4px 8px;
253
+ border-radius: 4px;
254
+ font-size: 0.8rem;
255
+ cursor: pointer;
256
+ transition: all 0.2s;
257
+ display: flex;
258
+ align-items: center;
259
+ gap: 4px;
260
+ }
261
+
262
+ .btn-action:hover {
263
+ background: var(--bg-secondary);
264
+ border-color: var(--accent);
265
+ }
266
+
267
+ /* Network Tab Styles */
268
+
269
+ /* Tabulator Overrides for DevTools look */
270
+ .tabulator {
271
+ border: none !important;
272
+ background-color: var(--bg-secondary) !important;
273
+ }
274
+
275
+ .tabulator-header {
276
+ background-color: var(--bg-header) !important;
277
+ border-bottom: 1px solid var(--border-color) !important;
278
+ color: var(--text-secondary) !important;
279
+ font-weight: 500 !important;
280
+ }
281
+
282
+ .tabulator-col {
283
+ background-color: transparent !important;
284
+ border-right: 1px solid var(--border-color) !important;
285
+ }
286
+
287
+ .tabulator-row {
288
+ background-color: var(--bg-secondary) !important;
289
+ border-bottom: 1px solid var(--border-color) !important;
290
+ color: var(--text-primary) !important;
291
+ }
292
+
293
+ .tabulator-row:hover {
294
+ background-color: var(--bg-primary) !important;
295
+ cursor: pointer;
296
+ }
297
+
298
+ .tabulator-row.tabulator-selected {
299
+ background-color: #2e3440 !important;
300
+ color: #fff !important;
301
+ }
302
+
303
+ /* Tabs */
304
+ .tab-item {
305
+ transition: all 0.2s;
306
+ }
307
+
308
+ .tab-item:hover {
309
+ background-color: rgba(255, 255, 255, 0.05);
310
+ }
311
+
312
+ .tab-item.active {
313
+ background-color: rgba(59, 130, 246, 0.1);
314
+ }
315
+
316
+ /* Details Panel */
317
+ details>summary {
318
+ list-style: none;
319
+ }
320
+
321
+ details>summary::-webkit-details-marker {
322
+ display: none;
323
+ }
324
+
325
+ details>summary::before {
326
+ content: '▶';
327
+ font-size: 0.8em;
328
+ margin-right: 6px;
329
+ display: inline-block;
330
+ transition: transform 0.2s;
331
+ }
332
+
333
+ details[open]>summary::before {
334
+ transform: rotate(90deg);
335
+ }
336
+
337
+ /* Slightly lighter than bg-secondary */
338
+ /* border-left: 2px solid var(--accent) !important; */
339
+ /* Slightly lighter than bg-secondary */
340
+
341
+ /* Filter Bar */
342
+ #network-filter-bar input:focus,
343
+ #network-filter-bar select:focus {
344
+ border-color: var(--accent);
345
+ outline: none;
346
+ }
347
+
348
+ #tab-network {
349
+ height: 100%;
350
+ overflow: hidden;
351
+ flex-direction: column;
352
+ }
353
+
354
+ #tab-network.active {
355
+ display: flex !important;
184
356
  }
@@ -14,20 +14,55 @@ function switchTab(tabId) {
14
14
  if (tabId === 'overview') {
15
15
  if (typeof fetchTopStats === 'function') fetchTopStats();
16
16
  }
17
- else if (tabId === 'graph') {
18
- initGraph();
17
+ else if (tabId === 'application') {
18
+ const activeView = document.querySelector('.app-view.active');
19
+ if (!activeView || activeView.id === 'app-view-registry') {
20
+ switchApplicationView('registry');
21
+ } else {
22
+ switchApplicationView('graph');
23
+ }
19
24
  }
20
- else if (tabId === 'requests') {
25
+ else if (tabId === 'network') {
21
26
  if (typeof fetchRequests === 'function') fetchRequests();
27
+ // Redraw table if it exists to fix layout issues when unhiding
28
+ setTimeout(() => {
29
+ if (window.requestsTable) window.requestsTable.redraw();
30
+ }, 50);
22
31
  }
23
- else if (tabId === 'failures') {
24
- fetchFailures();
25
- }
26
- else if (tabId === 'middleware') {
27
- fetchMiddleware();
32
+ }
33
+
34
+
35
+ function switchApplicationView(viewId) {
36
+ console.log('Switching application view to:', viewId);
37
+
38
+ // Update buttons
39
+ const container = document.getElementById('tab-application');
40
+ if (!container) return;
41
+
42
+ container.querySelectorAll('.view-btn').forEach(btn => btn.classList.remove('active'));
43
+ // Find button
44
+ const btn = Array.from(container.querySelectorAll('.view-btn')).find(b => b.getAttribute('onclick') === `switchApplicationView('${viewId}')`);
45
+ if (btn) btn.classList.add('active');
46
+
47
+ // Update content
48
+ container.querySelectorAll('.app-view').forEach(view => {
49
+ view.classList.remove('active');
50
+ view.style.display = 'none';
51
+ });
52
+
53
+ const activeView = document.getElementById('app-view-' + viewId);
54
+ if (activeView) {
55
+ activeView.classList.add('active');
56
+ activeView.style.display = 'block';
28
57
  }
29
- else if (tabId === 'registry') {
58
+
59
+ if (viewId === 'registry') {
30
60
  if (typeof fetchRegistry === 'function') fetchRegistry();
61
+ } else if (viewId === 'graph') {
62
+ // Build graph if needed
63
+ setTimeout(() => {
64
+ if (typeof initGraph === 'function') initGraph();
65
+ }, 50);
31
66
  }
32
67
  }
33
68
 
@@ -16,6 +16,21 @@
16
16
  font-weight: bold;
17
17
  }
18
18
 
19
+ .tabulator-menu .tabulator-menu-separator {
20
+ border-color: var(--card-border);
21
+ }
22
+
23
+ .tabulator-popup-container {
24
+ background-color: var(--bg-card);
25
+ border: 1px solid var(--card-border);
26
+ border-radius: 4px;
27
+ color: var(--text-primary);
28
+ }
29
+
30
+ .tabulator-menu .tabulator-menu-item:not(.tabulator-menu-item-disabled):hover {
31
+ background-color: var(--bg-primary);
32
+ }
33
+
19
34
  .tabulator .tabulator-header .tabulator-col {
20
35
  background-color: var(--bg-card);
21
36
  border-right: 1px solid var(--card-border);
@@ -58,6 +73,7 @@
58
73
  border-bottom: 1px solid var(--card-border);
59
74
  color: var(--text-primary);
60
75
  transition: background-color 100ms ease;
76
+ min-height: unset !important;
61
77
  }
62
78
 
63
79
  /* Higher specificity to override Tabulator default themes */
@@ -72,12 +88,12 @@
72
88
  }
73
89
 
74
90
  .tabulator .tabulator-row.tabulator-selected {
75
- background-color: var(--bg-primary) !important;
91
+ background-color: var(--table-row-selected-color) !important;
76
92
  color: var(--text-primary);
77
93
  }
78
94
 
79
95
  .tabulator .tabulator-row:hover {
80
- background-color: var(--bg-primary) !important;
96
+ background-color: var(--table-row-hover-color) !important;
81
97
  color: var(--text-primary);
82
98
  cursor: pointer;
83
99
  }
@@ -85,7 +101,7 @@
85
101
  /* Cells */
86
102
  .tabulator .tabulator-row .tabulator-cell {
87
103
  border-right: 1px solid var(--card-border);
88
- padding: 10px;
104
+ padding: 6px;
89
105
  align-content: center;
90
106
  }
91
107
 
@@ -115,4 +131,8 @@
115
131
  /* Sorting Icons */
116
132
  .tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-arrow {
117
133
  border-bottom-color: var(--text-secondary);
134
+ }
135
+
136
+ .tabulator [tabulator-field="timestamp"] {
137
+ padding: 0 4px !important;
118
138
  }
@@ -13,8 +13,8 @@
13
13
  --palette-dark-header: rgb(39, 27, 19);
14
14
  /* Proofing Drawer */
15
15
 
16
- /* Universal defaults (tokens) */
17
- --shokupan-font: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
16
+ --shokupan-font: "Vend Sans", 'Open Sans', 'Helvetica Neue', sans-serif;
17
+ --shokupan-font-mono: "Google Sans Code", monospace;
18
18
 
19
19
  /* Theme Variables - Enforced Dark Mode */
20
20
  --bg-primary: var(--palette-dark-bg);
@@ -24,6 +24,7 @@
24
24
 
25
25
  --text-primary: #F0F0F0;
26
26
  --text-secondary: var(--palette-dark-accent);
27
+ --text-flavor: #ffcc80;
27
28
  --text-muted: rgba(214, 211, 209, 0.5);
28
29
 
29
30
  --primary: var(--palette-dark-primary);
@@ -34,12 +35,20 @@
34
35
  --card-border: rgba(214, 211, 209, 0.2);
35
36
 
36
37
  --table-header-border-color: rgba(214, 211, 209, 0.2);
38
+ --table-row-hover-color: #382818;
39
+ --table-row-selected-color: #48331e;
37
40
 
38
41
  --link-color: var(--palette-dark-primary);
39
42
  --link-hover: #FFCBA0;
40
43
 
41
44
  --button-bg: var(--palette-dark-primary);
42
45
  --button-text: #1A1614;
46
+
47
+ }
48
+
49
+ * {
50
+ box-sizing: border-box;
51
+ font-optical-sizing: auto;
43
52
  }
44
53
 
45
54
  ::-webkit-scrollbar {
@@ -0,0 +1,39 @@
1
+ import { Shokupan } from '../../../shokupan';
2
+ import { ShokupanPlugin } from '../../../util/types';
3
+ export interface MCPServerPluginOptions {
4
+ /**
5
+ * The path to mount the MCP server to.
6
+ */
7
+ path?: string;
8
+ /**
9
+ * The root directory to scan for OpenAPI documents.
10
+ */
11
+ rootDir?: string;
12
+ /**
13
+ * Whether to allow the introspection tool.
14
+ */
15
+ allowIntrospection?: boolean;
16
+ /**
17
+ * Whether to allow tool execution.
18
+ */
19
+ allowToolExecution?: boolean;
20
+ }
21
+ /**
22
+ * Attaches an MCP server to the application.
23
+ * This MCP server is focus-designed to provide introspection and tool execution capabilities.
24
+ *
25
+ * If your application design requires anything custom, implement your own MCP server.
26
+ */
27
+ export declare class MCPServerPlugin implements ShokupanPlugin {
28
+ private options;
29
+ private router;
30
+ private mcpServer;
31
+ private transport;
32
+ private analyzer;
33
+ constructor(options?: MCPServerPluginOptions);
34
+ onInit(app: Shokupan): void;
35
+ private setupRoutes;
36
+ private registerTools;
37
+ private registerResources;
38
+ private registerPrompts;
39
+ }
@@ -14,6 +14,7 @@ export interface RouteInfo {
14
14
  };
15
15
  responseType?: string;
16
16
  responseSchema?: any;
17
+ hasUnknownFields?: boolean;
17
18
  summary?: string;
18
19
  description?: string;
19
20
  tags?: string[];
@@ -33,7 +34,7 @@ export interface RouteInfo {
33
34
  highlights?: {
34
35
  startLine: number;
35
36
  endLine: number;
36
- type: 'emit' | 'return-success' | 'return-warning';
37
+ type: 'emit' | 'return-success' | 'return-warning' | 'dynamic-path';
37
38
  }[];
38
39
  };
39
40
  }
@@ -56,6 +57,7 @@ export interface ApplicationInstance {
56
57
  controllerPrefix?: string;
57
58
  routes: RouteInfo[];
58
59
  mounted: MountInfo[];
60
+ middleware: MiddlewareInfo[];
59
61
  }
60
62
  interface MountInfo {
61
63
  prefix: string;
@@ -68,6 +70,31 @@ interface MountInfo {
68
70
  endLine: number;
69
71
  };
70
72
  }
73
+ /**
74
+ * Middleware information extracted from AST
75
+ */
76
+ export interface MiddlewareInfo {
77
+ name: string;
78
+ file: string;
79
+ startLine: number;
80
+ endLine: number;
81
+ handlerSource?: string;
82
+ responseTypes?: Record<string, any>;
83
+ headers?: string[];
84
+ scope: 'global' | 'router' | 'route';
85
+ sourceContext?: {
86
+ file: string;
87
+ startLine: number;
88
+ endLine: number;
89
+ snippet?: string;
90
+ snippetStartLine?: number;
91
+ highlights?: {
92
+ startLine: number;
93
+ endLine: number;
94
+ type: 'emit' | 'return-success' | 'return-warning';
95
+ }[];
96
+ };
97
+ }
71
98
  /**
72
99
  * Main analyzer class
73
100
  */
@@ -77,10 +104,15 @@ export declare class OpenAPIAnalyzer {
77
104
  private applications;
78
105
  private program?;
79
106
  private entrypoint?;
107
+ private imports;
80
108
  constructor(rootDir: string, entrypoint?: string);
81
109
  /**
82
110
  * Main analysis entry point
83
111
  */
112
+ /**
113
+ * Main analysis entry point
114
+ */
115
+ private cachedResult?;
84
116
  /**
85
117
  * Main analysis entry point
86
118
  */
@@ -99,6 +131,10 @@ export declare class OpenAPIAnalyzer {
99
131
  * Process source maps to reconstruct TypeScript
100
132
  */
101
133
  private processSourceMaps;
134
+ /**
135
+ * Collect all imports from source files for later resolution
136
+ */
137
+ private collectImports;
102
138
  /**
103
139
  * Parse TypeScript files and create AST
104
140
  */
@@ -123,6 +159,10 @@ export declare class OpenAPIAnalyzer {
123
159
  * Extract routes from a specific file
124
160
  */
125
161
  private extractRoutesFromFile;
162
+ /**
163
+ * Resolve string value from expression (literals, concatenation, templates, constants)
164
+ */
165
+ private resolveStringValue;
126
166
  /**
127
167
  * Extract route information from a route call (e.g., app.get('/path', handler))
128
168
  */
@@ -135,6 +175,14 @@ export declare class OpenAPIAnalyzer {
135
175
  * Convert an Expression node to an OpenAPI schema (best effort)
136
176
  */
137
177
  private convertExpressionToSchema;
178
+ /**
179
+ * Deduplicate schemas by comparing their JSON representations
180
+ */
181
+ private deduplicateSchemas;
182
+ /**
183
+ * Check if a schema contains fields with unknown types
184
+ */
185
+ private hasUnknownFields;
138
186
  /**
139
187
  * Check if an expression is a call to ctx.body()
140
188
  */
@@ -143,10 +191,26 @@ export declare class OpenAPIAnalyzer {
143
191
  * Convert a TypeScript TypeNode to an OpenAPI schema
144
192
  */
145
193
  private convertTypeNodeToSchema;
194
+ /**
195
+ * Convert a TypeScript Type (from type checker) to an OpenAPI schema
196
+ */
197
+ private convertTypeToSchema;
146
198
  /**
147
199
  * Extract mount information from mount call
148
200
  */
149
201
  private extractMountFromCall;
202
+ /**
203
+ * Extract middleware information from .use() call
204
+ */
205
+ private extractMiddlewareFromCall;
206
+ /**
207
+ * Analyze middleware function to extract response types and headers
208
+ */
209
+ private analyzeMiddleware;
210
+ /**
211
+ * Resolve an imported middleware identifier and analyze its definition
212
+ */
213
+ private resolveImportedMiddlewareDefinition;
150
214
  /**
151
215
  * Check if a reference is to an external dependency
152
216
  */
@@ -1,5 +1,8 @@
1
1
  import { ShokupanRouter } from '../../../router';
2
2
  import { OpenAPIOptions } from '../../../util/types';
3
+ /**
4
+ * Gets deduped AST routes if available.
5
+ */
3
6
  /**
4
7
  * Statically generate an OpenAPI spec from a ShokupanRouter instance.
5
8
  *
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Gets deduped AST routes if available.
3
+ */
4
+ export declare function getAstRoutes(applications: any[], options?: {
5
+ includePrefix?: boolean;
6
+ pathTransform?: (p: string) => string;
7
+ }): Promise<any[]>;
@@ -1,13 +1,23 @@
1
1
  import { Middleware } from '../../util/types';
2
2
  export interface CompressionOptions {
3
3
  /**
4
- * Minimum byte size to compress
4
+ * Minimum byte size to compress responses
5
5
  */
6
6
  threshold?: number;
7
7
  /**
8
- * Allowed algorithms
8
+ * Allowed algorithms for response compression
9
9
  */
10
10
  allowedAlgorithms?: string[];
11
+ /**
12
+ * Enable request decompression
13
+ * @default true
14
+ */
15
+ decompress?: boolean;
16
+ /**
17
+ * Maximum size of decompressed request body in bytes to prevent zipbomb style attacks
18
+ * @default 10485760 (10MB)
19
+ */
20
+ maxDecompressedSize?: number;
11
21
  }
12
22
  /**
13
23
  * Compression middleware.
@@ -49,6 +49,11 @@ export interface RateLimitOptions {
49
49
  * List of trusted proxy IPs
50
50
  */
51
51
  trustedProxies?: string[];
52
+ /**
53
+ * Interval in milliseconds to clean up expired entries.
54
+ * Defaults to windowMs.
55
+ */
56
+ cleanupInterval?: number;
52
57
  }
53
58
  /**
54
59
  * Rate limit middleware.