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.
Files changed (85) hide show
  1. package/README.md +154 -0
  2. package/dist/bin/postgres-ai.js +2911 -255
  3. package/package.json +12 -3
  4. package/schemas/A002.schema.json +63 -0
  5. package/schemas/A003.schema.json +73 -0
  6. package/schemas/A004.schema.json +81 -0
  7. package/schemas/A007.schema.json +71 -0
  8. package/schemas/A013.schema.json +61 -0
  9. package/schemas/D001.schema.json +71 -0
  10. package/schemas/D004.schema.json +136 -0
  11. package/schemas/F001.schema.json +73 -0
  12. package/schemas/F002.schema.json +108 -0
  13. package/schemas/F003.schema.json +138 -0
  14. package/schemas/F004.schema.json +125 -0
  15. package/schemas/F005.schema.json +131 -0
  16. package/schemas/F009.schema.json +155 -0
  17. package/schemas/G001.schema.json +135 -0
  18. package/schemas/G003.schema.json +90 -0
  19. package/schemas/H001.schema.json +141 -0
  20. package/schemas/H002.schema.json +129 -0
  21. package/schemas/H004.schema.json +128 -0
  22. package/schemas/I001.schema.json +149 -0
  23. package/schemas/K001.schema.json +161 -0
  24. package/schemas/K003.schema.json +163 -0
  25. package/schemas/K004.schema.json +110 -0
  26. package/schemas/K005.schema.json +110 -0
  27. package/schemas/K006.schema.json +110 -0
  28. package/schemas/K007.schema.json +110 -0
  29. package/schemas/K008.schema.json +110 -0
  30. package/schemas/M001.schema.json +119 -0
  31. package/schemas/M002.schema.json +110 -0
  32. package/schemas/M003.schema.json +128 -0
  33. package/schemas/N001.schema.json +161 -0
  34. package/schemas/query.schema.json +62 -0
  35. package/CHANGELOG.md +0 -11
  36. package/bin/postgres-ai.ts +0 -5578
  37. package/bun.lock +0 -258
  38. package/bunfig.toml +0 -20
  39. package/lib/aas-onboard.ts +0 -251
  40. package/lib/auth-server.ts +0 -285
  41. package/lib/checkup-api.ts +0 -526
  42. package/lib/checkup-dictionary.ts +0 -103
  43. package/lib/checkup-summary.ts +0 -338
  44. package/lib/checkup.ts +0 -2261
  45. package/lib/config.ts +0 -171
  46. package/lib/init.ts +0 -1152
  47. package/lib/instances.ts +0 -245
  48. package/lib/issues.ts +0 -1060
  49. package/lib/mcp-server.ts +0 -667
  50. package/lib/metrics-loader.ts +0 -134
  51. package/lib/pkce.ts +0 -79
  52. package/lib/reports.ts +0 -373
  53. package/lib/storage.ts +0 -367
  54. package/lib/supabase.ts +0 -826
  55. package/lib/util.ts +0 -134
  56. package/packages/postgres-ai/README.md +0 -26
  57. package/packages/postgres-ai/bin/postgres-ai.js +0 -27
  58. package/packages/postgres-ai/package.json +0 -27
  59. package/scripts/embed-checkup-dictionary.ts +0 -115
  60. package/scripts/embed-metrics.ts +0 -160
  61. package/scripts/generate-release-notes.ts +0 -668
  62. package/test/PERMISSION_CHECK_TEST_SUMMARY.md +0 -139
  63. package/test/aas-onboard.test.ts +0 -301
  64. package/test/auth.test.ts +0 -287
  65. package/test/checkup.integration.test.ts +0 -413
  66. package/test/checkup.test.ts +0 -3626
  67. package/test/compose-cmd.test.ts +0 -120
  68. package/test/config-consistency.test.ts +0 -352
  69. package/test/init.integration.test.ts +0 -438
  70. package/test/init.test.ts +0 -1816
  71. package/test/issues.cli.test.ts +0 -1162
  72. package/test/issues.test.ts +0 -456
  73. package/test/mcp-server.test.ts +0 -2530
  74. package/test/monitoring.test.ts +0 -746
  75. package/test/permission-check-sql.test.ts +0 -116
  76. package/test/reports.cli.test.ts +0 -793
  77. package/test/reports.test.ts +0 -977
  78. package/test/schema-validation.test.ts +0 -231
  79. package/test/storage.test.ts +0 -935
  80. package/test/supabase.test.ts +0 -709
  81. package/test/targets-add-config.test.ts +0 -28
  82. package/test/test-utils.ts +0 -190
  83. package/test/upgrade.test.ts +0 -1056
  84. package/test/util.test.ts +0 -44
  85. package/tsconfig.json +0 -20
@@ -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, "&amp;")
30
- .replace(/</g, "&lt;")
31
- .replace(/>/g, "&gt;")
32
- .replace(/"/g, "&quot;")
33
- .replace(/'/g, "&#39;");
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
- }