postgresai 0.16.0-rc.4 → 0.16.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 +154 -0
- package/dist/bin/postgres-ai.js +2911 -255
- package/package.json +12 -3
- package/schemas/A002.schema.json +63 -0
- package/schemas/A003.schema.json +73 -0
- package/schemas/A004.schema.json +81 -0
- package/schemas/A007.schema.json +71 -0
- package/schemas/A013.schema.json +61 -0
- package/schemas/D001.schema.json +71 -0
- package/schemas/D004.schema.json +136 -0
- package/schemas/F001.schema.json +73 -0
- package/schemas/F002.schema.json +108 -0
- package/schemas/F003.schema.json +138 -0
- package/schemas/F004.schema.json +125 -0
- package/schemas/F005.schema.json +131 -0
- package/schemas/F009.schema.json +155 -0
- package/schemas/G001.schema.json +135 -0
- package/schemas/G003.schema.json +90 -0
- package/schemas/H001.schema.json +141 -0
- package/schemas/H002.schema.json +129 -0
- package/schemas/H004.schema.json +128 -0
- package/schemas/I001.schema.json +149 -0
- package/schemas/K001.schema.json +161 -0
- package/schemas/K003.schema.json +163 -0
- package/schemas/K004.schema.json +110 -0
- package/schemas/K005.schema.json +110 -0
- package/schemas/K006.schema.json +110 -0
- package/schemas/K007.schema.json +110 -0
- package/schemas/K008.schema.json +110 -0
- package/schemas/M001.schema.json +119 -0
- package/schemas/M002.schema.json +110 -0
- package/schemas/M003.schema.json +128 -0
- package/schemas/N001.schema.json +161 -0
- package/schemas/query.schema.json +62 -0
- package/CHANGELOG.md +0 -11
- package/bin/postgres-ai.ts +0 -5578
- package/bun.lock +0 -258
- package/bunfig.toml +0 -20
- package/lib/aas-onboard.ts +0 -251
- package/lib/auth-server.ts +0 -285
- package/lib/checkup-api.ts +0 -526
- package/lib/checkup-dictionary.ts +0 -103
- package/lib/checkup-summary.ts +0 -338
- package/lib/checkup.ts +0 -2261
- package/lib/config.ts +0 -171
- package/lib/init.ts +0 -1152
- package/lib/instances.ts +0 -245
- package/lib/issues.ts +0 -1060
- package/lib/mcp-server.ts +0 -667
- package/lib/metrics-loader.ts +0 -134
- package/lib/pkce.ts +0 -79
- package/lib/reports.ts +0 -373
- package/lib/storage.ts +0 -367
- package/lib/supabase.ts +0 -826
- package/lib/util.ts +0 -134
- package/packages/postgres-ai/README.md +0 -26
- package/packages/postgres-ai/bin/postgres-ai.js +0 -27
- package/packages/postgres-ai/package.json +0 -27
- package/scripts/embed-checkup-dictionary.ts +0 -115
- package/scripts/embed-metrics.ts +0 -160
- package/scripts/generate-release-notes.ts +0 -668
- package/test/PERMISSION_CHECK_TEST_SUMMARY.md +0 -139
- package/test/aas-onboard.test.ts +0 -301
- package/test/auth.test.ts +0 -287
- package/test/checkup.integration.test.ts +0 -413
- package/test/checkup.test.ts +0 -3626
- package/test/compose-cmd.test.ts +0 -120
- package/test/config-consistency.test.ts +0 -352
- package/test/init.integration.test.ts +0 -438
- package/test/init.test.ts +0 -1816
- package/test/issues.cli.test.ts +0 -1162
- package/test/issues.test.ts +0 -456
- package/test/mcp-server.test.ts +0 -2530
- package/test/monitoring.test.ts +0 -746
- package/test/permission-check-sql.test.ts +0 -116
- package/test/reports.cli.test.ts +0 -793
- package/test/reports.test.ts +0 -977
- package/test/schema-validation.test.ts +0 -231
- package/test/storage.test.ts +0 -935
- package/test/supabase.test.ts +0 -709
- package/test/targets-add-config.test.ts +0 -28
- package/test/test-utils.ts +0 -190
- package/test/upgrade.test.ts +0 -1056
- package/test/util.test.ts +0 -44
- package/tsconfig.json +0 -20
package/lib/auth-server.ts
DELETED
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
import * as http from "http";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* OAuth callback result
|
|
5
|
-
*/
|
|
6
|
-
export interface CallbackResult {
|
|
7
|
-
code: string;
|
|
8
|
-
state: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Callback server structure
|
|
13
|
-
*/
|
|
14
|
-
export interface CallbackServer {
|
|
15
|
-
server: { stop: () => void };
|
|
16
|
-
promise: Promise<CallbackResult>;
|
|
17
|
-
ready: Promise<number>; // Resolves with actual port when server is listening
|
|
18
|
-
getPort: () => number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Simple HTML escape utility
|
|
23
|
-
* @param str - String to escape
|
|
24
|
-
* @returns Escaped string
|
|
25
|
-
*/
|
|
26
|
-
function escapeHtml(str: string | null): string {
|
|
27
|
-
if (!str) return "";
|
|
28
|
-
return String(str)
|
|
29
|
-
.replace(/&/g, "&")
|
|
30
|
-
.replace(/</g, "<")
|
|
31
|
-
.replace(/>/g, ">")
|
|
32
|
-
.replace(/"/g, """)
|
|
33
|
-
.replace(/'/g, "'");
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Create and start callback server using Node.js http module
|
|
38
|
-
*
|
|
39
|
-
* @param port - Port to listen on (0 for random available port)
|
|
40
|
-
* @param expectedState - Expected state parameter for CSRF protection
|
|
41
|
-
* @param timeoutMs - Timeout in milliseconds
|
|
42
|
-
* @returns Server object with promise, ready promise, and getPort function
|
|
43
|
-
*
|
|
44
|
-
* @remarks
|
|
45
|
-
* The `ready` promise resolves with the actual port once the server is listening.
|
|
46
|
-
* Callers should await `ready` before using `getPort()` when using port 0.
|
|
47
|
-
*
|
|
48
|
-
* The server stops asynchronously ~100ms after the callback resolves/rejects.
|
|
49
|
-
* This delay ensures the HTTP response is fully sent before closing the connection.
|
|
50
|
-
* Callers should not attempt to reuse the same port immediately after the promise
|
|
51
|
-
* resolves - wait at least 200ms or use a different port.
|
|
52
|
-
*/
|
|
53
|
-
export function createCallbackServer(
|
|
54
|
-
port: number = 0,
|
|
55
|
-
expectedState: string | null = null,
|
|
56
|
-
timeoutMs: number = 300000
|
|
57
|
-
): CallbackServer {
|
|
58
|
-
let resolved = false;
|
|
59
|
-
let actualPort = port;
|
|
60
|
-
let resolveCallback: (value: CallbackResult) => void;
|
|
61
|
-
let rejectCallback: (reason: Error) => void;
|
|
62
|
-
let resolveReady: (port: number) => void;
|
|
63
|
-
let rejectReady: (reason: Error) => void;
|
|
64
|
-
let serverInstance: http.Server | null = null;
|
|
65
|
-
|
|
66
|
-
const promise = new Promise<CallbackResult>((resolve, reject) => {
|
|
67
|
-
resolveCallback = resolve;
|
|
68
|
-
rejectCallback = reject;
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const ready = new Promise<number>((resolve, reject) => {
|
|
72
|
-
resolveReady = resolve;
|
|
73
|
-
rejectReady = reject;
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
77
|
-
|
|
78
|
-
const stopServer = () => {
|
|
79
|
-
// Clear timeout to prevent it firing after manual stop
|
|
80
|
-
if (timeoutId) {
|
|
81
|
-
clearTimeout(timeoutId);
|
|
82
|
-
timeoutId = null;
|
|
83
|
-
}
|
|
84
|
-
if (serverInstance) {
|
|
85
|
-
serverInstance.close();
|
|
86
|
-
serverInstance = null;
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
// Timeout handler
|
|
91
|
-
timeoutId = setTimeout(() => {
|
|
92
|
-
if (!resolved) {
|
|
93
|
-
resolved = true;
|
|
94
|
-
timeoutId = null; // Already fired, clear reference
|
|
95
|
-
stopServer();
|
|
96
|
-
rejectCallback(new Error("Authentication timeout. Please try again."));
|
|
97
|
-
}
|
|
98
|
-
}, timeoutMs);
|
|
99
|
-
|
|
100
|
-
serverInstance = http.createServer((req, res) => {
|
|
101
|
-
if (resolved) {
|
|
102
|
-
res.writeHead(200, { "Content-Type": "text/plain" });
|
|
103
|
-
res.end("Already handled");
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const url = new URL(req.url || "/", `http://127.0.0.1:${actualPort}`);
|
|
108
|
-
|
|
109
|
-
// Only handle /callback path
|
|
110
|
-
if (!url.pathname.startsWith("/callback")) {
|
|
111
|
-
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
112
|
-
res.end("Not Found");
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const code = url.searchParams.get("code");
|
|
117
|
-
const state = url.searchParams.get("state");
|
|
118
|
-
const error = url.searchParams.get("error");
|
|
119
|
-
const errorDescription = url.searchParams.get("error_description");
|
|
120
|
-
|
|
121
|
-
// Handle OAuth error
|
|
122
|
-
if (error) {
|
|
123
|
-
resolved = true;
|
|
124
|
-
if (timeoutId) {
|
|
125
|
-
clearTimeout(timeoutId);
|
|
126
|
-
timeoutId = null;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
setTimeout(() => stopServer(), 100);
|
|
130
|
-
rejectCallback(new Error(`OAuth error: ${error}${errorDescription ? ` - ${errorDescription}` : ""}`));
|
|
131
|
-
|
|
132
|
-
res.writeHead(400, { "Content-Type": "text/html" });
|
|
133
|
-
res.end(`
|
|
134
|
-
<!DOCTYPE html>
|
|
135
|
-
<html>
|
|
136
|
-
<head>
|
|
137
|
-
<title>Authentication failed</title>
|
|
138
|
-
<style>
|
|
139
|
-
body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
|
|
140
|
-
.error { background: #fee; border: 1px solid #fcc; padding: 20px; border-radius: 8px; }
|
|
141
|
-
h1 { color: #c33; margin-top: 0; }
|
|
142
|
-
code { background: #f5f5f5; padding: 2px 6px; border-radius: 3px; }
|
|
143
|
-
</style>
|
|
144
|
-
</head>
|
|
145
|
-
<body>
|
|
146
|
-
<div class="error">
|
|
147
|
-
<h1>Authentication failed</h1>
|
|
148
|
-
<p><strong>Error:</strong> ${escapeHtml(error)}</p>
|
|
149
|
-
${errorDescription ? `<p><strong>Description:</strong> ${escapeHtml(errorDescription)}</p>` : ""}
|
|
150
|
-
<p>You can close this window and return to your terminal.</p>
|
|
151
|
-
</div>
|
|
152
|
-
</body>
|
|
153
|
-
</html>
|
|
154
|
-
`);
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Validate required parameters
|
|
159
|
-
if (!code || !state) {
|
|
160
|
-
res.writeHead(400, { "Content-Type": "text/html" });
|
|
161
|
-
res.end(`
|
|
162
|
-
<!DOCTYPE html>
|
|
163
|
-
<html>
|
|
164
|
-
<head>
|
|
165
|
-
<title>Authentication failed</title>
|
|
166
|
-
<style>
|
|
167
|
-
body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
|
|
168
|
-
.error { background: #fee; border: 1px solid #fcc; padding: 20px; border-radius: 8px; }
|
|
169
|
-
h1 { color: #c33; margin-top: 0; }
|
|
170
|
-
</style>
|
|
171
|
-
</head>
|
|
172
|
-
<body>
|
|
173
|
-
<div class="error">
|
|
174
|
-
<h1>Authentication failed</h1>
|
|
175
|
-
<p>Missing required parameters (code or state).</p>
|
|
176
|
-
<p>You can close this window and return to your terminal.</p>
|
|
177
|
-
</div>
|
|
178
|
-
</body>
|
|
179
|
-
</html>
|
|
180
|
-
`);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Validate state (CSRF protection)
|
|
185
|
-
if (expectedState && state !== expectedState) {
|
|
186
|
-
resolved = true;
|
|
187
|
-
if (timeoutId) {
|
|
188
|
-
clearTimeout(timeoutId);
|
|
189
|
-
timeoutId = null;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
setTimeout(() => stopServer(), 100);
|
|
193
|
-
rejectCallback(new Error("State mismatch (possible CSRF attack)"));
|
|
194
|
-
|
|
195
|
-
res.writeHead(400, { "Content-Type": "text/html" });
|
|
196
|
-
res.end(`
|
|
197
|
-
<!DOCTYPE html>
|
|
198
|
-
<html>
|
|
199
|
-
<head>
|
|
200
|
-
<title>Authentication failed</title>
|
|
201
|
-
<style>
|
|
202
|
-
body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
|
|
203
|
-
.error { background: #fee; border: 1px solid #fcc; padding: 20px; border-radius: 8px; }
|
|
204
|
-
h1 { color: #c33; margin-top: 0; }
|
|
205
|
-
</style>
|
|
206
|
-
</head>
|
|
207
|
-
<body>
|
|
208
|
-
<div class="error">
|
|
209
|
-
<h1>Authentication failed</h1>
|
|
210
|
-
<p>Invalid state parameter (possible CSRF attack).</p>
|
|
211
|
-
<p>You can close this window and return to your terminal.</p>
|
|
212
|
-
</div>
|
|
213
|
-
</body>
|
|
214
|
-
</html>
|
|
215
|
-
`);
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Success!
|
|
220
|
-
resolved = true;
|
|
221
|
-
if (timeoutId) {
|
|
222
|
-
clearTimeout(timeoutId);
|
|
223
|
-
timeoutId = null;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Resolve first, then stop server asynchronously after response is sent.
|
|
227
|
-
// The 100ms delay ensures the HTTP response is fully written before closing.
|
|
228
|
-
resolveCallback({ code, state });
|
|
229
|
-
setTimeout(() => stopServer(), 100);
|
|
230
|
-
|
|
231
|
-
res.writeHead(200, { "Content-Type": "text/html" });
|
|
232
|
-
res.end(`
|
|
233
|
-
<!DOCTYPE html>
|
|
234
|
-
<html>
|
|
235
|
-
<head>
|
|
236
|
-
<title>Authentication successful</title>
|
|
237
|
-
<style>
|
|
238
|
-
body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
|
|
239
|
-
.success { background: #efe; border: 1px solid #cfc; padding: 20px; border-radius: 8px; }
|
|
240
|
-
h1 { color: #3c3; margin-top: 0; }
|
|
241
|
-
</style>
|
|
242
|
-
</head>
|
|
243
|
-
<body>
|
|
244
|
-
<div class="success">
|
|
245
|
-
<h1>Authentication successful</h1>
|
|
246
|
-
<p>You have successfully authenticated the PostgresAI CLI.</p>
|
|
247
|
-
<p>You can close this window and return to your terminal.</p>
|
|
248
|
-
</div>
|
|
249
|
-
</body>
|
|
250
|
-
</html>
|
|
251
|
-
`);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
// Handle server errors (e.g., EADDRINUSE)
|
|
255
|
-
serverInstance.on("error", (err: NodeJS.ErrnoException) => {
|
|
256
|
-
if (timeoutId) {
|
|
257
|
-
clearTimeout(timeoutId);
|
|
258
|
-
timeoutId = null;
|
|
259
|
-
}
|
|
260
|
-
if (err.code === "EADDRINUSE") {
|
|
261
|
-
rejectReady(new Error(`Port ${port} is already in use`));
|
|
262
|
-
} else {
|
|
263
|
-
rejectReady(new Error(`Server error: ${err.message}`));
|
|
264
|
-
}
|
|
265
|
-
if (!resolved) {
|
|
266
|
-
resolved = true;
|
|
267
|
-
rejectCallback(err);
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
serverInstance.listen(port, "127.0.0.1", () => {
|
|
272
|
-
const address = serverInstance?.address();
|
|
273
|
-
if (address && typeof address === "object") {
|
|
274
|
-
actualPort = address.port;
|
|
275
|
-
}
|
|
276
|
-
resolveReady(actualPort);
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
return {
|
|
280
|
-
server: { stop: stopServer },
|
|
281
|
-
promise,
|
|
282
|
-
ready,
|
|
283
|
-
getPort: () => actualPort,
|
|
284
|
-
};
|
|
285
|
-
}
|