@egdesk/next-api-plugin 1.0.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.
- package/README.md +176 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.js +60 -0
- package/dist/generate-helpers.d.ts +9 -0
- package/dist/generate-helpers.js +172 -0
- package/dist/generate-middleware.d.ts +10 -0
- package/dist/generate-middleware.js +137 -0
- package/dist/generate-proxy.d.ts +12 -0
- package/dist/generate-proxy.js +136 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +91 -0
- package/dist/setup-userdata.d.ts +37 -0
- package/dist/setup-userdata.js +225 -0
- package/package.json +34 -0
- package/src/cli.ts +63 -0
- package/src/generate-helpers.ts +140 -0
- package/src/generate-middleware.ts +108 -0
- package/src/generate-proxy.ts +107 -0
- package/src/index.ts +109 -0
- package/src/setup-userdata.ts +238 -0
- package/tsconfig.json +18 -0
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# @egdesk/next-api-plugin
|
|
2
|
+
|
|
3
|
+
Next.js plugin for EGDesk database proxy integration. Provides middleware-based CORS-free database access for Next.js applications.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔒 CORS-free database access via Next.js middleware
|
|
8
|
+
- 🌐 Works in both local and tunneled environments
|
|
9
|
+
- 📝 Type-safe table definitions and helper functions
|
|
10
|
+
- 🚀 Auto-discovery of database tables
|
|
11
|
+
- 🔧 Zero configuration after setup
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @egdesk/next-api-plugin
|
|
17
|
+
# or
|
|
18
|
+
yarn add @egdesk/next-api-plugin
|
|
19
|
+
# or
|
|
20
|
+
pnpm add @egdesk/next-api-plugin
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
1. Run the setup command in your Next.js project:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx egdesk-next-setup
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This will generate:
|
|
32
|
+
- `middleware.ts` - Database proxy middleware
|
|
33
|
+
- `egdesk.config.ts` - Type-safe table definitions
|
|
34
|
+
- `egdesk-helpers.ts` - Helper functions for database access
|
|
35
|
+
- `.env.local` - Environment variables
|
|
36
|
+
|
|
37
|
+
2. Add `.env.local` to your `.gitignore` (if not already there)
|
|
38
|
+
|
|
39
|
+
3. Restart your Next.js dev server
|
|
40
|
+
|
|
41
|
+
4. Use the helpers in your components:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { queryTable } from './egdesk-helpers';
|
|
45
|
+
import { TABLES } from './egdesk.config';
|
|
46
|
+
|
|
47
|
+
export default async function MyPage() {
|
|
48
|
+
const data = await queryTable(TABLES.table1.name, { limit: 10 });
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div>
|
|
52
|
+
<pre>{JSON.stringify(data, null, 2)}</pre>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Configuration
|
|
59
|
+
|
|
60
|
+
### Environment Variables
|
|
61
|
+
|
|
62
|
+
The plugin uses Next.js environment variables:
|
|
63
|
+
|
|
64
|
+
```env
|
|
65
|
+
NEXT_PUBLIC_EGDESK_API_URL=http://localhost:8080
|
|
66
|
+
NEXT_PUBLIC_EGDESK_API_KEY=your-api-key-here
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Custom Setup
|
|
70
|
+
|
|
71
|
+
You can programmatically run the setup:
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { setupNextApiPlugin } from '@egdesk/next-api-plugin';
|
|
75
|
+
|
|
76
|
+
await setupNextApiPlugin('/path/to/project', {
|
|
77
|
+
egdeskUrl: 'http://localhost:8080',
|
|
78
|
+
apiKey: 'optional-api-key'
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## How It Works
|
|
83
|
+
|
|
84
|
+
The plugin creates a Next.js middleware that intercepts requests to `__user_data_proxy` and forwards them to your EGDesk MCP server. This allows your Next.js app to make database queries without CORS issues, even in tunneled environments.
|
|
85
|
+
|
|
86
|
+
**Request Flow:**
|
|
87
|
+
1. Your component calls `queryTable()` or other helpers
|
|
88
|
+
2. Helper makes a fetch to `__user_data_proxy`
|
|
89
|
+
3. Next.js middleware intercepts the request
|
|
90
|
+
4. Middleware forwards to `localhost:8080/user-data/tools/call`
|
|
91
|
+
5. Response is returned to your component
|
|
92
|
+
|
|
93
|
+
## API Reference
|
|
94
|
+
|
|
95
|
+
### Helper Functions
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// Query table data
|
|
99
|
+
queryTable(tableName: string, options?: {
|
|
100
|
+
filters?: Record<string, string>;
|
|
101
|
+
limit?: number;
|
|
102
|
+
offset?: number;
|
|
103
|
+
orderBy?: string;
|
|
104
|
+
orderDirection?: 'ASC' | 'DESC';
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
// Search table
|
|
108
|
+
searchTable(tableName: string, searchQuery: string, limit?: number)
|
|
109
|
+
|
|
110
|
+
// Aggregate data
|
|
111
|
+
aggregateTable(tableName: string, column: string, aggregateFunction: 'SUM' | 'AVG' | 'MIN' | 'MAX' | 'COUNT', options?: {
|
|
112
|
+
filters?: Record<string, string>;
|
|
113
|
+
groupBy?: string;
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
// Execute raw SQL
|
|
117
|
+
executeSQL(query: string)
|
|
118
|
+
|
|
119
|
+
// List all tables
|
|
120
|
+
listTables()
|
|
121
|
+
|
|
122
|
+
// Get table schema
|
|
123
|
+
getTableSchema(tableName: string)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Configuration Types
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
interface TableDefinition {
|
|
130
|
+
name: string;
|
|
131
|
+
displayName: string;
|
|
132
|
+
description?: string;
|
|
133
|
+
rowCount: number;
|
|
134
|
+
columnCount: number;
|
|
135
|
+
columns: string[];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const TABLES = {
|
|
139
|
+
table1: TableDefinition,
|
|
140
|
+
table2: TableDefinition,
|
|
141
|
+
// ...
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const TABLE_NAMES = {
|
|
145
|
+
table1: 'actual_table_name',
|
|
146
|
+
table2: 'another_table_name',
|
|
147
|
+
// ...
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Troubleshooting
|
|
152
|
+
|
|
153
|
+
### Middleware not working
|
|
154
|
+
|
|
155
|
+
Make sure:
|
|
156
|
+
- `middleware.ts` is in your project root (not in `src/` or `app/`)
|
|
157
|
+
- Your Next.js version is 13.0.0 or higher
|
|
158
|
+
- You've restarted your dev server after setup
|
|
159
|
+
|
|
160
|
+
### CORS errors
|
|
161
|
+
|
|
162
|
+
If you're still seeing CORS errors:
|
|
163
|
+
- Check that middleware.ts was generated correctly
|
|
164
|
+
- Verify environment variables are set in `.env.local`
|
|
165
|
+
- Make sure you're using the relative URL `__user_data_proxy` (no leading slash)
|
|
166
|
+
|
|
167
|
+
### Table discovery fails
|
|
168
|
+
|
|
169
|
+
Ensure:
|
|
170
|
+
- EGDesk MCP server is running on `localhost:8080`
|
|
171
|
+
- You have tables imported in EGDesk
|
|
172
|
+
- API key is correct (if required)
|
|
173
|
+
|
|
174
|
+
## License
|
|
175
|
+
|
|
176
|
+
MIT
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* CLI entry point for @egdesk/next-api-plugin
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx egdesk-next-setup
|
|
8
|
+
* npx egdesk-next-setup --url http://localhost:8080 --api-key YOUR_KEY
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
const index_1 = require("./index");
|
|
12
|
+
async function main() {
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
// Parse command line arguments
|
|
15
|
+
let egdeskUrl = 'http://localhost:8080';
|
|
16
|
+
let apiKey;
|
|
17
|
+
let useProxy = true; // Use proxy.ts by default (Next.js 16+)
|
|
18
|
+
for (let i = 0; i < args.length; i++) {
|
|
19
|
+
if (args[i] === '--url' && i + 1 < args.length) {
|
|
20
|
+
egdeskUrl = args[i + 1];
|
|
21
|
+
i++;
|
|
22
|
+
}
|
|
23
|
+
else if (args[i] === '--api-key' && i + 1 < args.length) {
|
|
24
|
+
apiKey = args[i + 1];
|
|
25
|
+
i++;
|
|
26
|
+
}
|
|
27
|
+
else if (args[i] === '--legacy-middleware') {
|
|
28
|
+
useProxy = false;
|
|
29
|
+
}
|
|
30
|
+
else if (args[i] === '--help' || args[i] === '-h') {
|
|
31
|
+
console.log('Usage: egdesk-next-setup [options]');
|
|
32
|
+
console.log('');
|
|
33
|
+
console.log('Options:');
|
|
34
|
+
console.log(' --url <url> EGDesk server URL (default: http://localhost:8080)');
|
|
35
|
+
console.log(' --api-key <key> API key for authentication');
|
|
36
|
+
console.log(' --legacy-middleware Use middleware.ts instead of proxy.ts (for Next.js <16)');
|
|
37
|
+
console.log(' --help, -h Show this help message');
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log('Example:');
|
|
40
|
+
console.log(' egdesk-next-setup --url http://localhost:8080 --api-key mykey');
|
|
41
|
+
console.log(' egdesk-next-setup --legacy-middleware # For Next.js <16');
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Get current working directory (project root)
|
|
46
|
+
const projectPath = process.cwd();
|
|
47
|
+
console.log('🚀 EGDesk Next.js Setup');
|
|
48
|
+
console.log(`📂 Project: ${projectPath}`);
|
|
49
|
+
console.log(`🔗 EGDesk URL: ${egdeskUrl}`);
|
|
50
|
+
console.log('');
|
|
51
|
+
try {
|
|
52
|
+
await (0, index_1.setupNextApiPlugin)(projectPath, { egdeskUrl, apiKey, useProxy });
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error('Setup failed:', error);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
main();
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Generate helper functions for EGDesk database access in Next.js
|
|
4
|
+
*
|
|
5
|
+
* Creates egdesk-helpers.ts with type-safe helper functions.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.generateHelpers = generateHelpers;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
/**
|
|
45
|
+
* Generate egdesk-helpers.ts file
|
|
46
|
+
*/
|
|
47
|
+
function generateHelpers(projectPath) {
|
|
48
|
+
const helperPath = path.join(projectPath, 'egdesk-helpers.ts');
|
|
49
|
+
const helperContent = `/**
|
|
50
|
+
* EGDesk User Data Helper Functions for Next.js
|
|
51
|
+
*
|
|
52
|
+
* Type-safe helpers for accessing EGDesk user data.
|
|
53
|
+
* Works in both client and server components.
|
|
54
|
+
*
|
|
55
|
+
* Generated by @egdesk/next-api-plugin
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Call EGDesk user-data MCP tool
|
|
60
|
+
*
|
|
61
|
+
* Uses a proxy endpoint to work in both local and tunneled environments.
|
|
62
|
+
* The Next.js middleware intercepts these requests and forwards them to localhost:8080.
|
|
63
|
+
*/
|
|
64
|
+
export async function callUserDataTool(
|
|
65
|
+
toolName: string,
|
|
66
|
+
args: Record<string, any> = {}
|
|
67
|
+
): Promise<any> {
|
|
68
|
+
const headers: Record<string, string> = {
|
|
69
|
+
'Content-Type': 'application/json'
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Use proxy endpoint - works in both local and tunneled environments
|
|
73
|
+
// Absolute URL with leading slash to ensure correct resolution from any route
|
|
74
|
+
const response = await fetch('/__user_data_proxy', {
|
|
75
|
+
method: 'POST',
|
|
76
|
+
headers,
|
|
77
|
+
body: JSON.stringify({ tool: toolName, arguments: args })
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
throw new Error(\`HTTP \${response.status}: \${response.statusText}\`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const result = await response.json();
|
|
85
|
+
|
|
86
|
+
if (!result.success) {
|
|
87
|
+
throw new Error(result.error || 'Tool call failed');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Parse MCP response format
|
|
91
|
+
const content = result.result?.content?.[0]?.text;
|
|
92
|
+
return content ? JSON.parse(content) : null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Query table data
|
|
97
|
+
*/
|
|
98
|
+
export async function queryTable(
|
|
99
|
+
tableName: string,
|
|
100
|
+
options: {
|
|
101
|
+
filters?: Record<string, string>;
|
|
102
|
+
limit?: number;
|
|
103
|
+
offset?: number;
|
|
104
|
+
orderBy?: string;
|
|
105
|
+
orderDirection?: 'ASC' | 'DESC';
|
|
106
|
+
} = {}
|
|
107
|
+
) {
|
|
108
|
+
return callUserDataTool('user_data_query', {
|
|
109
|
+
tableName,
|
|
110
|
+
...options
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Search table
|
|
116
|
+
*/
|
|
117
|
+
export async function searchTable(
|
|
118
|
+
tableName: string,
|
|
119
|
+
searchQuery: string,
|
|
120
|
+
limit: number = 50
|
|
121
|
+
) {
|
|
122
|
+
return callUserDataTool('user_data_search', {
|
|
123
|
+
tableName,
|
|
124
|
+
searchQuery,
|
|
125
|
+
limit
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Aggregate data
|
|
131
|
+
*/
|
|
132
|
+
export async function aggregateTable(
|
|
133
|
+
tableName: string,
|
|
134
|
+
column: string,
|
|
135
|
+
aggregateFunction: 'SUM' | 'AVG' | 'MIN' | 'MAX' | 'COUNT',
|
|
136
|
+
options: {
|
|
137
|
+
filters?: Record<string, string>;
|
|
138
|
+
groupBy?: string;
|
|
139
|
+
} = {}
|
|
140
|
+
) {
|
|
141
|
+
return callUserDataTool('user_data_aggregate', {
|
|
142
|
+
tableName,
|
|
143
|
+
column,
|
|
144
|
+
function: aggregateFunction,
|
|
145
|
+
...options
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Execute raw SQL query
|
|
151
|
+
*/
|
|
152
|
+
export async function executeSQL(query: string) {
|
|
153
|
+
return callUserDataTool('user_data_sql_query', { query });
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* List all available tables
|
|
158
|
+
*/
|
|
159
|
+
export async function listTables() {
|
|
160
|
+
return callUserDataTool('user_data_list_tables', {});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get table schema
|
|
165
|
+
*/
|
|
166
|
+
export async function getTableSchema(tableName: string) {
|
|
167
|
+
return callUserDataTool('user_data_get_schema', { tableName });
|
|
168
|
+
}
|
|
169
|
+
`;
|
|
170
|
+
fs.writeFileSync(helperPath, helperContent, 'utf-8');
|
|
171
|
+
console.log(`✅ Generated ${helperPath}`);
|
|
172
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate Next.js middleware for EGDesk database proxy
|
|
3
|
+
*
|
|
4
|
+
* Creates middleware.ts that intercepts __user_data_proxy requests
|
|
5
|
+
* and forwards them to the EGDesk MCP server.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Generate middleware.ts file in the correct location (root or src/)
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateMiddleware(projectPath: string): void;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Generate Next.js middleware for EGDesk database proxy
|
|
4
|
+
*
|
|
5
|
+
* Creates middleware.ts that intercepts __user_data_proxy requests
|
|
6
|
+
* and forwards them to the EGDesk MCP server.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.generateMiddleware = generateMiddleware;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
/**
|
|
46
|
+
* Detect if project uses src/ directory structure
|
|
47
|
+
*/
|
|
48
|
+
function usesSrcDirectory(projectPath) {
|
|
49
|
+
const srcPath = path.join(projectPath, 'src');
|
|
50
|
+
const srcAppPath = path.join(projectPath, 'src', 'app');
|
|
51
|
+
return fs.existsSync(srcPath) && fs.existsSync(srcAppPath);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Generate middleware.ts file in the correct location (root or src/)
|
|
55
|
+
*/
|
|
56
|
+
function generateMiddleware(projectPath) {
|
|
57
|
+
// Detect if project uses src/ directory
|
|
58
|
+
const hasSrc = usesSrcDirectory(projectPath);
|
|
59
|
+
const targetDir = hasSrc ? path.join(projectPath, 'src') : projectPath;
|
|
60
|
+
const middlewarePath = path.join(targetDir, 'middleware.ts');
|
|
61
|
+
console.log(`📁 Detected ${hasSrc ? 'src/' : 'root'} directory structure`);
|
|
62
|
+
console.log(`📝 Generating middleware at: ${middlewarePath}`);
|
|
63
|
+
// Check if middleware.ts already exists
|
|
64
|
+
if (fs.existsSync(middlewarePath)) {
|
|
65
|
+
console.log('⚠️ middleware.ts already exists - backing up to middleware.backup.ts');
|
|
66
|
+
const backupPath = path.join(targetDir, 'middleware.backup.ts');
|
|
67
|
+
fs.copyFileSync(middlewarePath, backupPath);
|
|
68
|
+
}
|
|
69
|
+
const middlewareContent = `import { NextResponse } from 'next/server';
|
|
70
|
+
import type { NextRequest } from 'next/server';
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* EGDesk Database Proxy Middleware
|
|
74
|
+
*
|
|
75
|
+
* Intercepts __user_data_proxy requests and forwards them to the EGDesk MCP server.
|
|
76
|
+
* This allows CORS-free database access in both local and tunneled environments.
|
|
77
|
+
*
|
|
78
|
+
* Generated by @egdesk/next-api-plugin
|
|
79
|
+
*/
|
|
80
|
+
export async function middleware(request: NextRequest) {
|
|
81
|
+
const { pathname } = request.nextUrl;
|
|
82
|
+
|
|
83
|
+
// Intercept __user_data_proxy requests
|
|
84
|
+
if (pathname.includes('__user_data_proxy')) {
|
|
85
|
+
try {
|
|
86
|
+
const body = await request.text();
|
|
87
|
+
|
|
88
|
+
// Read API key and URL from environment
|
|
89
|
+
const apiKey = process.env.NEXT_PUBLIC_EGDESK_API_KEY;
|
|
90
|
+
const apiUrl = process.env.NEXT_PUBLIC_EGDESK_API_URL || 'http://localhost:8080';
|
|
91
|
+
|
|
92
|
+
const headers: HeadersInit = {
|
|
93
|
+
'Content-Type': 'application/json',
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
if (apiKey) {
|
|
97
|
+
headers['X-Api-Key'] = apiKey;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Forward to EGDesk MCP server
|
|
101
|
+
const response = await fetch(\`\${apiUrl}/user-data/tools/call\`, {
|
|
102
|
+
method: 'POST',
|
|
103
|
+
headers,
|
|
104
|
+
body,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const result = await response.json();
|
|
108
|
+
|
|
109
|
+
return NextResponse.json(result, { status: response.status });
|
|
110
|
+
} catch (error: any) {
|
|
111
|
+
return NextResponse.json(
|
|
112
|
+
{ error: 'Proxy error', message: error.message },
|
|
113
|
+
{ status: 500 }
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Continue to next middleware or route
|
|
119
|
+
return NextResponse.next();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const config = {
|
|
123
|
+
matcher: [
|
|
124
|
+
/*
|
|
125
|
+
* Match all request paths except for the ones starting with:
|
|
126
|
+
* - api (API routes)
|
|
127
|
+
* - _next/static (static files)
|
|
128
|
+
* - _next/image (image optimization files)
|
|
129
|
+
* - favicon.ico (favicon file)
|
|
130
|
+
*/
|
|
131
|
+
'/((?!api|_next/static|_next/image|favicon.ico).*)',
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
`;
|
|
135
|
+
fs.writeFileSync(middlewarePath, middlewareContent, 'utf-8');
|
|
136
|
+
console.log(`✅ Generated ${middlewarePath}`);
|
|
137
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate Next.js 16+ proxy for EGDesk database proxy
|
|
3
|
+
*
|
|
4
|
+
* Creates proxy.ts that intercepts __user_data_proxy requests
|
|
5
|
+
* and forwards them to the EGDesk MCP server.
|
|
6
|
+
*
|
|
7
|
+
* This is the Next.js 16+ recommended approach (replaces middleware.ts)
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Generate proxy.ts file in the correct location (root or src/)
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateProxy(projectPath: string): void;
|