shokupan 0.7.0 → 0.10.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 (66) hide show
  1. package/README.md +53 -0
  2. package/dist/analyzer-BqIe1p0R.js +35 -0
  3. package/dist/analyzer-BqIe1p0R.js.map +1 -0
  4. package/dist/analyzer-CKLGLFtx.cjs +35 -0
  5. package/dist/analyzer-CKLGLFtx.cjs.map +1 -0
  6. package/dist/{analyzer-Ce_7JxZh.js → analyzer.impl-CV6W1Eq7.js} +238 -21
  7. package/dist/analyzer.impl-CV6W1Eq7.js.map +1 -0
  8. package/dist/{analyzer-Bei1sVWp.cjs → analyzer.impl-D9Yi1Hax.cjs} +237 -20
  9. package/dist/analyzer.impl-D9Yi1Hax.cjs.map +1 -0
  10. package/dist/cli.cjs +1 -1
  11. package/dist/cli.js +1 -1
  12. package/dist/context.d.ts +69 -22
  13. package/dist/{http-server-DFhwlK8e.cjs → http-server-BEMPIs33.cjs} +4 -2
  14. package/dist/http-server-BEMPIs33.cjs.map +1 -0
  15. package/dist/{http-server-0xH174zz.js → http-server-CCeagTyU.js} +4 -2
  16. package/dist/http-server-CCeagTyU.js.map +1 -0
  17. package/dist/index.cjs +2411 -329
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.js +2390 -308
  21. package/dist/index.js.map +1 -1
  22. package/dist/plugins/application/api-explorer/plugin.d.ts +9 -0
  23. package/dist/plugins/application/api-explorer/static/explorer-client.mjs +880 -0
  24. package/dist/plugins/application/api-explorer/static/style.css +767 -0
  25. package/dist/plugins/application/api-explorer/static/theme.css +128 -0
  26. package/dist/plugins/application/asyncapi/generator.d.ts +3 -0
  27. package/dist/plugins/application/asyncapi/plugin.d.ts +15 -0
  28. package/dist/plugins/application/asyncapi/static/asyncapi-client.mjs +748 -0
  29. package/dist/plugins/application/asyncapi/static/style.css +565 -0
  30. package/dist/plugins/application/asyncapi/static/theme.css +128 -0
  31. package/dist/plugins/application/auth.d.ts +3 -1
  32. package/dist/plugins/application/dashboard/metrics-collector.d.ts +14 -0
  33. package/dist/plugins/application/dashboard/plugin.d.ts +25 -9
  34. package/dist/plugins/application/dashboard/static/charts.js +328 -0
  35. package/dist/plugins/application/dashboard/static/failures.js +85 -0
  36. package/dist/plugins/application/dashboard/static/graph.mjs +523 -0
  37. package/dist/plugins/application/dashboard/static/poll.js +146 -0
  38. package/dist/plugins/application/dashboard/static/reactflow.css +18 -0
  39. package/dist/plugins/application/dashboard/static/registry.css +78 -0
  40. package/dist/plugins/application/dashboard/static/registry.js +269 -0
  41. package/dist/plugins/application/dashboard/static/requests.js +118 -0
  42. package/dist/plugins/application/dashboard/static/styles.css +184 -0
  43. package/dist/plugins/application/dashboard/static/tables.js +92 -0
  44. package/dist/plugins/application/dashboard/static/tabs.js +113 -0
  45. package/dist/plugins/application/dashboard/static/tabulator.css +118 -0
  46. package/dist/plugins/application/dashboard/static/theme.css +128 -0
  47. package/dist/plugins/application/graphql-apollo.d.ts +33 -0
  48. package/dist/plugins/application/graphql-yoga.d.ts +25 -0
  49. package/dist/plugins/application/openapi/analyzer.d.ts +12 -119
  50. package/dist/plugins/application/openapi/analyzer.impl.d.ts +167 -0
  51. package/dist/plugins/application/scalar.d.ts +9 -2
  52. package/dist/plugins/application/socket-io.d.ts +14 -0
  53. package/dist/router.d.ts +92 -51
  54. package/dist/shokupan.d.ts +34 -8
  55. package/dist/util/datastore.d.ts +71 -6
  56. package/dist/util/decorators.d.ts +7 -2
  57. package/dist/util/http-error.d.ts +38 -0
  58. package/dist/util/http-status.d.ts +30 -0
  59. package/dist/util/request.d.ts +1 -1
  60. package/dist/util/symbol.d.ts +19 -0
  61. package/dist/util/types.d.ts +126 -4
  62. package/package.json +38 -15
  63. package/dist/analyzer-Bei1sVWp.cjs.map +0 -1
  64. package/dist/analyzer-Ce_7JxZh.js.map +0 -1
  65. package/dist/http-server-0xH174zz.js.map +0 -1
  66. package/dist/http-server-DFhwlK8e.cjs.map +0 -1
@@ -0,0 +1,92 @@
1
+
2
+ // --- Table Config Helper ---
3
+ function createTable(id, columns, placeholder = "No data available") {
4
+ return new Tabulator(id, {
5
+ layout: "fitColumns",
6
+ height: "300px",
7
+ placeholder: placeholder,
8
+ data: [],
9
+ columns: columns,
10
+ layoutColumnsOnNewData: true,
11
+ });
12
+ }
13
+
14
+ // --- Top Requests Table ---
15
+ const topRequestsTable = createTable("#top-requests-table", [
16
+ { title: "Count", field: "count", align: "center", width: 100, sorter: "number" },
17
+ { title: "Method", field: "method", width: 110 },
18
+ { title: "URL", field: "url" },
19
+ ]);
20
+
21
+ // --- Top Errors Table ---
22
+ const topErrorsTable = createTable("#top-errors-table", [
23
+ { title: "Count", field: "count", align: "center", width: 100, sorter: "number" },
24
+ { title: "Error Message", field: "error" },
25
+ ]);
26
+
27
+ // --- Failing Requests Table ---
28
+ const failingRequestsTable = createTable("#failing-requests-table", [
29
+ { title: "Failures", field: "count", align: "center", width: 80, sorter: "number" },
30
+ { title: "Method", field: "method", width: 110 },
31
+ { title: "URL", field: "url" },
32
+ ]);
33
+
34
+ // --- Slowest Requests Table ---
35
+ const slowestRequestsTable = createTable("#slowest-requests-table", [
36
+ { title: "Duration (ms)", field: "duration", width: 130, sorter: "number", formatter: (cell) => printDuration(cell.getValue()) },
37
+ {
38
+ title: "URL", formatter: (cell) => {
39
+ const data = cell.getData() ?? {};
40
+ return data.method?.toUpperCase() + ": " + data.url;
41
+ }
42
+ },
43
+ {
44
+ title: "Status", field: "status", width: 100, align: "center", formatter: function (cell) {
45
+ const val = cell.getValue();
46
+ return `<span style="color: ${val >= 400 ? 'red' : 'green'}">${val}</span>`;
47
+ }
48
+ },
49
+ { title: "Time", field: "timestamp", width: 150, formatter: (cell) => new Date(cell.getValue()).toLocaleTimeString() }
50
+ ]);
51
+
52
+
53
+ async function fetchTopStats() {
54
+ // Get request headers from global function if available
55
+ const headers = typeof getRequestHeaders !== 'undefined' ? getRequestHeaders() : {};
56
+
57
+ // Determine base path for API requests
58
+ const basePath = window.location.pathname.endsWith('/') ? window.location.pathname.slice(0, -1) : window.location.pathname;
59
+ const url = basePath + '/';
60
+ const interval = document.getElementById('time-range-selector')?.value || '1m';
61
+ try {
62
+ // Top Requests
63
+ fetch(url + 'requests/top?interval=' + interval, { headers }).then(r => r.json()).then(d => {
64
+ if (d.top) topRequestsTable.setData(d.top);
65
+ });
66
+
67
+ // Top Errors
68
+ fetch(url + 'errors/top?interval=' + interval, { headers }).then(r => r.json()).then(d => {
69
+ if (d.top) topErrorsTable.setData(d.top);
70
+ });
71
+
72
+ // Failing Requests
73
+ fetch(url + 'requests/failing?interval=' + interval, { headers }).then(r => r.json()).then(d => {
74
+ if (d.top) failingRequestsTable.setData(d.top);
75
+ });
76
+
77
+ // Slowest Requests
78
+ fetch(url + 'requests/slowest?interval=' + interval, { headers }).then(r => r.json()).then(d => {
79
+ if (d.slowest) slowestRequestsTable.setData(d.slowest);
80
+ });
81
+
82
+ } catch (e) {
83
+ console.error("Failed to fetch top stats", e);
84
+ }
85
+ }
86
+
87
+ document.addEventListener("DOMContentLoaded", () => {
88
+ fetchTopStats();
89
+ // Refresh periodically
90
+ setInterval(fetchTopStats, 10000);
91
+ });
92
+
@@ -0,0 +1,113 @@
1
+ // --- Tabs Logic ---
2
+ function switchTab(tabId) {
3
+ console.log('Switching to tab:', tabId);
4
+ // Update buttons
5
+ document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
6
+ // Find the button that was clicked
7
+ const btn = Array.from(document.querySelectorAll('.tab-btn')).find(b => b.getAttribute('onclick') === `switchTab('${tabId}')`);
8
+ if (btn) btn.classList.add('active');
9
+
10
+ // Update content
11
+ document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
12
+ document.getElementById('tab-' + tabId).classList.add('active');
13
+
14
+ if (tabId === 'overview') {
15
+ if (typeof fetchTopStats === 'function') fetchTopStats();
16
+ }
17
+ else if (tabId === 'graph') {
18
+ initGraph();
19
+ }
20
+ else if (tabId === 'requests') {
21
+ if (typeof fetchRequests === 'function') fetchRequests();
22
+ }
23
+ else if (tabId === 'failures') {
24
+ fetchFailures();
25
+ }
26
+ else if (tabId === 'middleware') {
27
+ fetchMiddleware();
28
+ }
29
+ else if (tabId === 'registry') {
30
+ if (typeof fetchRegistry === 'function') fetchRegistry();
31
+ }
32
+ }
33
+
34
+ // Middleware fetch function
35
+ async function fetchMiddleware() {
36
+ try {
37
+ const headers = getRequestHeaders ? getRequestHeaders() : {};
38
+ const basePath = window.location.pathname.endsWith('/') ? '' : window.location.pathname;
39
+ const url = basePath + (basePath.endsWith('/') ? 'middleware' : '/middleware');
40
+
41
+ const res = await fetch(url, { headers });
42
+ if (!res.ok) return;
43
+ const data = await res.json();
44
+
45
+ // Initialize or update table
46
+ if (!window.middlewareTable) {
47
+ window.middlewareTable = new Tabulator("#middleware-table-container", {
48
+ layout: "fitColumns",
49
+ height: "500px",
50
+ placeholder: "No middleware executions tracked",
51
+ data: data.middleware || [],
52
+ columns: [
53
+ {
54
+ title: "Timestamp", field: "timestamp", width: 180, formatter: function (cell) {
55
+ return new Date(cell.getValue()).toLocaleString();
56
+ }
57
+ },
58
+ {
59
+ title: "Name", field: "name", width: 200,
60
+ formatter: function (cell) {
61
+ const row = cell.getRow().getData();
62
+ const isBuiltin = row.metadata?.isBuiltin;
63
+ const pluginName = row.metadata?.pluginName;
64
+ let badge = '';
65
+ if (isBuiltin) {
66
+ badge = ' <span style="background: #059669; color: white; padding: 2px 6px; border-radius: 4px; font-size: 0.7em;">BUILTIN</span>';
67
+ }
68
+ const plugin = pluginName ? ` <span style="color: #6ee7b7;">[${pluginName}]</span>` : '';
69
+ return cell.getValue() + badge + plugin;
70
+ }
71
+ },
72
+ { title: "Path", field: "path", headerFilter: "input" },
73
+ {
74
+ title: "Duration (ms)", field: "duration", width: 120,
75
+ formatter: (cell) => cell.getValue() ? cell.getValue().toFixed(2) : 'N/A'
76
+ },
77
+ {
78
+ title: "Status", field: "error", width: 100, formatter: function (cell) {
79
+ const error = cell.getValue();
80
+ if (error) {
81
+ return '<span style="color: #ef4444; font-weight: bold;">ERROR</span>';
82
+ }
83
+ return '<span style="color: #22c55e; font-weight: bold;">OK</span>';
84
+ }
85
+ }
86
+ ],
87
+ initialSort: [
88
+ { column: "timestamp", dir: "desc" }
89
+ ]
90
+ });
91
+ } else {
92
+ window.middlewareTable.replaceData(data.middleware || []);
93
+ }
94
+ } catch (e) {
95
+ console.error("Failed to fetch middleware", e);
96
+ }
97
+ }
98
+
99
+ async function fetchFailures() {
100
+ try {
101
+ const headers = getRequestHeaders ? getRequestHeaders() : {};
102
+ // Handle relative path issue
103
+ const basePath = window.location.pathname.endsWith('/') ? '' : window.location.pathname;
104
+ const url = basePath + (basePath.endsWith('/') ? 'failures' : '/failures');
105
+
106
+ const res = await fetch(url, { headers });
107
+ if (!res.ok) return;
108
+ const data = await res.json();
109
+ failuresTable.replaceData(data.failures);
110
+ } catch (e) {
111
+ console.error("Failed to fetch failures", e);
112
+ }
113
+ }
@@ -0,0 +1,118 @@
1
+ /* Tabulator Theme Overrides - Merged with Layout */
2
+ .tabulator {
3
+ height: 100%;
4
+ width: 100%;
5
+ background-color: var(--bg-card);
6
+ border: 1px solid var(--card-border);
7
+ color: var(--text-primary);
8
+ }
9
+
10
+ /* Header */
11
+ .tabulator .tabulator-header {
12
+ background-color: var(--bg-card);
13
+ border-top: 0;
14
+ border-bottom: 2px solid var(--table-header-border-color);
15
+ color: var(--primary);
16
+ font-weight: bold;
17
+ }
18
+
19
+ .tabulator .tabulator-header .tabulator-col {
20
+ background-color: var(--bg-card);
21
+ border-right: 1px solid var(--card-border);
22
+ }
23
+
24
+ .tabulator .tabulator-header .tabulator-col:hover {
25
+ background-color: var(--bg-primary);
26
+ }
27
+
28
+ .tabulator .tabulator-header .tabulator-col-content {
29
+ padding: 12px;
30
+ }
31
+
32
+ /* Sortable Columns */
33
+ .tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort=none] .tabulator-col-content .tabulator-col-sorter {
34
+ color: var(--text-secondary);
35
+ }
36
+
37
+ .tabulator .tabulator-header .tabulator-col.tabulator-sortable.tabulator-col-sorter-element:hover {
38
+ background-color: var(--bg-primary);
39
+ }
40
+
41
+ /* Filter Inputs */
42
+ .tabulator .tabulator-header .tabulator-col .tabulator-header-filter input {
43
+ background-color: var(--bg-primary);
44
+ color: var(--text-primary);
45
+ border: 1px solid var(--card-border);
46
+ }
47
+
48
+ .tabulator .tabulator-header .tabulator-col .tabulator-header-filter input:focus {
49
+ background-color: var(--bg-secondary);
50
+ color: var(--text-primary);
51
+ border-color: var(--primary);
52
+ outline: none;
53
+ }
54
+
55
+ /* Rows */
56
+ .tabulator .tabulator-row {
57
+ background-color: var(--bg-card);
58
+ border-bottom: 1px solid var(--card-border);
59
+ color: var(--text-primary);
60
+ transition: background-color 100ms ease;
61
+ }
62
+
63
+ /* Higher specificity to override Tabulator default themes */
64
+ .tabulator .tabulator-row.tabulator-row-even,
65
+ .tabulator-row.tabulator-row-even {
66
+ background-color: var(--bg-primary) !important;
67
+ }
68
+
69
+ .tabulator .tabulator-row.tabulator-row-odd,
70
+ .tabulator-row.tabulator-row-odd {
71
+ background-color: var(--bg-card) !important;
72
+ }
73
+
74
+ .tabulator .tabulator-row.tabulator-selected {
75
+ background-color: var(--bg-primary) !important;
76
+ color: var(--text-primary);
77
+ }
78
+
79
+ .tabulator .tabulator-row:hover {
80
+ background-color: var(--bg-primary) !important;
81
+ color: var(--text-primary);
82
+ cursor: pointer;
83
+ }
84
+
85
+ /* Cells */
86
+ .tabulator .tabulator-row .tabulator-cell {
87
+ border-right: 1px solid var(--card-border);
88
+ padding: 10px;
89
+ align-content: center;
90
+ }
91
+
92
+ /* Footer / Pagination */
93
+ .tabulator .tabulator-footer {
94
+ background-color: var(--bg-card);
95
+ border-top: 2px solid var(--table-header-border-color);
96
+ }
97
+
98
+ .tabulator .tabulator-footer .tabulator-page {
99
+ background-color: var(--bg-primary);
100
+ color: var(--text-primary);
101
+ border: 1px solid var(--border-color);
102
+ border-radius: 4px;
103
+ }
104
+
105
+ .tabulator .tabulator-footer .tabulator-page:hover {
106
+ background-color: var(--table-header-border-color);
107
+ color: var(--text-primary);
108
+ }
109
+
110
+ .tabulator .tabulator-footer .tabulator-page.active {
111
+ background-color: var(--primary);
112
+ color: var(--bg-card);
113
+ }
114
+
115
+ /* Sorting Icons */
116
+ .tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-arrow {
117
+ border-bottom-color: var(--text-secondary);
118
+ }
@@ -0,0 +1,128 @@
1
+ :root {
2
+ /* Raw Palette - Dark (Now Default) */
3
+ --palette-dark-primary: #FFB380;
4
+ /* Warm Filament */
5
+ --palette-dark-secondary: #7B5E7B;
6
+ /* Yeast Purple */
7
+ --palette-dark-accent: #D6D3D1;
8
+ /* Flour Dust */
9
+ --palette-dark-bg: #1A1614;
10
+ /* Oven Depth */
11
+ --palette-dark-card: #2A2421;
12
+
13
+ --palette-dark-header: rgb(39, 27, 19);
14
+ /* Proofing Drawer */
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;
18
+
19
+ /* Theme Variables - Enforced Dark Mode */
20
+ --bg-primary: var(--palette-dark-bg);
21
+ --bg-secondary: var(--palette-dark-card);
22
+ --bg-card: var(--palette-dark-card);
23
+ --bg-header: var(--palette-dark-header);
24
+
25
+ --text-primary: #F0F0F0;
26
+ --text-secondary: var(--palette-dark-accent);
27
+ --text-muted: rgba(214, 211, 209, 0.5);
28
+
29
+ --primary: var(--palette-dark-primary);
30
+ --secondary: var(--palette-dark-secondary);
31
+ --accent: var(--palette-dark-accent);
32
+
33
+ --border-color: rgba(214, 211, 209, 0.2);
34
+ --card-border: rgba(214, 211, 209, 0.2);
35
+
36
+ --table-header-border-color: rgba(214, 211, 209, 0.2);
37
+
38
+ --link-color: var(--palette-dark-primary);
39
+ --link-hover: #FFCBA0;
40
+
41
+ --button-bg: var(--palette-dark-primary);
42
+ --button-text: #1A1614;
43
+ }
44
+
45
+ ::-webkit-scrollbar {
46
+ width: 8px;
47
+ height: 8px;
48
+ background-color: var(--bg-primary);
49
+ }
50
+
51
+ ::-webkit-scrollbar-thumb {
52
+ border-radius: 10px;
53
+ background-color: var(--primary);
54
+ box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
55
+ }
56
+
57
+ ::-webkit-scrollbar-track {
58
+ border-radius: 10px;
59
+ background-color: var(--bg-secondary);
60
+ }
61
+
62
+ ::-webkit-scrollbar-corner {
63
+ box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
64
+ }
65
+
66
+ .badge-SEND {
67
+ background: rgba(59, 130, 246, 0.15);
68
+ color: #60a5fa;
69
+ border: 1px solid rgba(59, 130, 246, 0.3);
70
+ }
71
+
72
+ .badge-RECV {
73
+ background: rgba(16, 185, 129, 0.15);
74
+ color: #34d399;
75
+ border: 1px solid rgba(16, 185, 129, 0.3);
76
+ }
77
+
78
+ .badge-GET {
79
+ background: #0f172a;
80
+ color: #3b82f6;
81
+ border: 1px solid #3b82f6;
82
+ }
83
+
84
+ .badge-POST {
85
+ background: #0f172a;
86
+ color: #22c55e;
87
+ border: 1px solid #22c55e;
88
+ }
89
+
90
+ .badge-PUT {
91
+ background: #0f172a;
92
+ color: #eab308;
93
+ border: 1px solid #eab308;
94
+ }
95
+
96
+ .badge-PATCH {
97
+ background: #0f172a;
98
+ color: #08d3ea;
99
+ border: 1px solid #08eae6;
100
+ }
101
+
102
+ .badge-HEAD {
103
+ background: #0f172a;
104
+ color: #e3ea08;
105
+ border: 1px solid #e3ea08;
106
+ }
107
+
108
+ .badge-OPTIONS {
109
+ background: #0f172a;
110
+ color: #838383;
111
+ border: 1px solid #838383;
112
+ }
113
+
114
+ .badge-DELETE {
115
+ background: #0f172a;
116
+ color: #ef4444;
117
+ border: 1px solid #ef4444;
118
+ }
119
+
120
+ .badge-ROUTER {
121
+ background: #334155;
122
+ color: #f8fafc;
123
+ }
124
+
125
+ .badge-CONTROLLER {
126
+ background: #475569;
127
+ color: #f8fafc;
128
+ }
@@ -0,0 +1,33 @@
1
+ import { ApolloServer } from '@apollo/server';
2
+ import { ShokupanRouter } from '../../router';
3
+ import { Shokupan } from '../../shokupan';
4
+ import { ShokupanPlugin, ShokupanPluginOptions } from '../../util/types';
5
+ export interface GraphQLPluginOptions {
6
+ /**
7
+ * Path to mount the GraphQL endpoint to.
8
+ * @default '/graphql'
9
+ */
10
+ path?: string;
11
+ /**
12
+ * GraphQL Type Definitions
13
+ */
14
+ typeDefs: any;
15
+ /**
16
+ * GraphQL Resolvers
17
+ */
18
+ resolvers: any;
19
+ /**
20
+ * Optional Apollo Server configuration
21
+ */
22
+ apolloConfig?: Omit<ConstructorParameters<typeof ApolloServer>[0], 'typeDefs' | 'resolvers'>;
23
+ }
24
+ /**
25
+ * GraphQL Apollo Server Plugin for Shokupan.
26
+ * Enables serving GraphQL APIs using Apollo Server 4.
27
+ */
28
+ export declare class GraphQLApolloPlugin extends ShokupanRouter<any> implements ShokupanPlugin {
29
+ private pluginOptions;
30
+ private apolloServer;
31
+ constructor(pluginOptions: GraphQLPluginOptions);
32
+ onInit(app: Shokupan, options?: ShokupanPluginOptions): Promise<void>;
33
+ }
@@ -0,0 +1,25 @@
1
+ import { YogaServerOptions } from 'graphql-yoga';
2
+ import { ShokupanRouter } from '../../router';
3
+ import { Shokupan } from '../../shokupan';
4
+ import { ShokupanPlugin, ShokupanPluginOptions } from '../../util/types';
5
+ export interface GraphQLYogaPluginOptions {
6
+ /**
7
+ * Path to mount the GraphQL endpoint to.
8
+ * @default '/graphql'
9
+ */
10
+ path?: string;
11
+ /**
12
+ * Yoga Server configuration
13
+ */
14
+ yogaConfig: YogaServerOptions<any, any>;
15
+ }
16
+ /**
17
+ * GraphQL Yoga Plugin for Shokupan.
18
+ * Enables serving GraphQL APIs using GraphQL Yoga.
19
+ */
20
+ export declare class GraphQLYogaPlugin extends ShokupanRouter<any> implements ShokupanPlugin {
21
+ private pluginOptions;
22
+ private yoga;
23
+ constructor(pluginOptions: GraphQLYogaPluginOptions);
24
+ onInit(app: Shokupan, options?: ShokupanPluginOptions): Promise<void>;
25
+ }
@@ -1,133 +1,27 @@
1
+ import { ApplicationInstance } from './analyzer.impl';
2
+ export type { ApplicationInstance, RouteInfo } from './analyzer.impl';
1
3
  /**
2
- * Route information extracted from AST
3
- */
4
- export interface RouteInfo {
5
- method: string;
6
- path: string;
7
- handlerName?: string;
8
- handlerSource?: string;
9
- requestTypes?: {
10
- body?: any;
11
- query?: Record<string, string>;
12
- params?: Record<string, string>;
13
- headers?: Record<string, string>;
14
- };
15
- responseType?: string;
16
- responseSchema?: any;
17
- summary?: string;
18
- description?: string;
19
- tags?: string[];
20
- operationId?: string;
21
- }
22
- /**
23
- * Dependency information
24
- */
25
- interface DependencyInfo {
26
- packageName: string;
27
- version?: string;
28
- importPath: string;
29
- isExternal: boolean;
30
- }
31
- /**
32
- * Application/Router instance found in code
33
- */
34
- export interface ApplicationInstance {
35
- name: string;
36
- filePath: string;
37
- className: 'Shokupan' | 'ShokupanRouter' | 'Controller';
38
- routes: RouteInfo[];
39
- mounted: MountInfo[];
40
- }
41
- interface MountInfo {
42
- prefix: string;
43
- target: string;
44
- dependency?: DependencyInfo;
45
- }
46
- /**
47
- * Main analyzer class
4
+ * OpenAPI Analyzer Wrapper.
5
+ *
6
+ * This class wraps the actual OpenAPIAnalyzer implementation to facilitate
7
+ * lazy loading of the 'typescript' peer dependency. The actual implementation
8
+ * and the 'typescript' module are only loaded when `analyze()` is called.
48
9
  */
49
10
  export declare class OpenAPIAnalyzer {
50
11
  private rootDir;
51
- private files;
52
- private applications;
53
- private program?;
54
12
  private entrypoint?;
13
+ private analyzerImpl;
55
14
  constructor(rootDir: string, entrypoint?: string);
56
15
  /**
57
- * Main analysis entry point
58
- */
59
- /**
60
- * Main analysis entry point
16
+ * Main analysis entry point.
17
+ * Dynamically imports the implementation and runs the analysis.
61
18
  */
62
19
  analyze(): Promise<{
63
20
  applications: ApplicationInstance[];
64
21
  }>;
65
22
  /**
66
- * Recursively scan directory for TypeScript/JavaScript files
67
- */
68
- private scanDirectory;
69
- /**
70
- * Process source maps to reconstruct TypeScript
71
- */
72
- private processSourceMaps;
73
- /**
74
- * Parse TypeScript files and create AST
75
- */
76
- private parseTypeScriptFiles;
77
- /**
78
- * Find all Shokupan/ShokupanRouter instances
79
- */
80
- private findApplications;
81
- /**
82
- * Visit AST node to find application instances
83
- */
84
- private visitNode;
85
- /**
86
- * Extract route information from applications
87
- */
88
- private extractRoutes;
89
- /**
90
- * Extract routes from a Controller class
91
- */
92
- private extractRoutesFromController;
93
- /**
94
- * Extract routes from a specific file
95
- */
96
- private extractRoutesFromFile;
97
- /**
98
- * Extract route information from a route call (e.g., app.get('/path', handler))
99
- */
100
- private extractRouteFromCall;
101
- /**
102
- * Analyze a route handler to extract type information
103
- */
104
- private analyzeHandler;
105
- /**
106
- * Convert an Expression node to an OpenAPI schema (best effort)
107
- */
108
- private convertExpressionToSchema;
109
- /**
110
- * Check if an expression is a call to ctx.body()
111
- */
112
- private isCtxBodyCall;
113
- /**
114
- * Convert a TypeScript TypeNode to an OpenAPI schema
115
- */
116
- private convertTypeNodeToSchema;
117
- /**
118
- * Extract mount information from mount call
119
- */
120
- private extractMountFromCall;
121
- /**
122
- * Check if a reference is to an external dependency
123
- */
124
- private checkIfExternalDependency;
125
- /**
126
- * Get package version from package.json
127
- */
128
- private getPackageVersion;
129
- /**
130
- * Generate OpenAPI specification
23
+ * Generate OpenAPI specification.
24
+ * Must be called after analyze().
131
25
  */
132
26
  generateOpenAPISpec(): any;
133
27
  }
@@ -135,4 +29,3 @@ export declare class OpenAPIAnalyzer {
135
29
  * Analyze a directory and generate OpenAPI spec
136
30
  */
137
31
  export declare function analyzeDirectory(directory: string): Promise<any>;
138
- export {};