postgresai 0.14.0-dev.82 → 0.14.0-dev.83
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/bin/postgres-ai.ts +11 -7
- package/bun.lock +4 -4
- package/dist/bin/postgres-ai.js +13 -224
- package/lib/checkup.ts +0 -268
- package/lib/mcp-server.ts +1 -1
- package/lib/supabase.ts +17 -4
- package/package.json +3 -3
- package/test/checkup.test.ts +62 -1
- package/test/init.test.ts +10 -10
- package/test/issues.test.ts +11 -11
- package/test/mcp-server.test.ts +40 -40
- package/test/supabase.test.ts +141 -0
package/test/mcp-server.test.ts
CHANGED
|
@@ -96,21 +96,21 @@ describe("MCP Server", () => {
|
|
|
96
96
|
});
|
|
97
97
|
|
|
98
98
|
// Mock fetch to verify API key is used
|
|
99
|
-
let capturedHeaders:
|
|
99
|
+
let capturedHeaders: Record<string, string> | undefined;
|
|
100
100
|
globalThis.fetch = mock((url: string, options?: RequestInit) => {
|
|
101
|
-
capturedHeaders = options?.headers;
|
|
101
|
+
capturedHeaders = options?.headers as Record<string, string> | undefined;
|
|
102
102
|
return Promise.resolve(
|
|
103
103
|
new Response(JSON.stringify([]), {
|
|
104
104
|
status: 200,
|
|
105
105
|
headers: { "Content-Type": "application/json" },
|
|
106
106
|
})
|
|
107
107
|
);
|
|
108
|
-
});
|
|
108
|
+
}) as unknown as typeof fetch;
|
|
109
109
|
|
|
110
110
|
await handleToolCall(createRequest("list_issues"), { apiKey: "test-api-key" });
|
|
111
111
|
|
|
112
112
|
expect(capturedHeaders).toBeDefined();
|
|
113
|
-
expect(
|
|
113
|
+
expect(capturedHeaders!["access-token"]).toBe("test-api-key");
|
|
114
114
|
|
|
115
115
|
readConfigSpy.mockRestore();
|
|
116
116
|
});
|
|
@@ -123,21 +123,21 @@ describe("MCP Server", () => {
|
|
|
123
123
|
defaultProject: null,
|
|
124
124
|
});
|
|
125
125
|
|
|
126
|
-
let capturedHeaders:
|
|
126
|
+
let capturedHeaders: Record<string, string> | undefined;
|
|
127
127
|
globalThis.fetch = mock((url: string, options?: RequestInit) => {
|
|
128
|
-
capturedHeaders = options?.headers;
|
|
128
|
+
capturedHeaders = options?.headers as Record<string, string> | undefined;
|
|
129
129
|
return Promise.resolve(
|
|
130
130
|
new Response(JSON.stringify([]), {
|
|
131
131
|
status: 200,
|
|
132
132
|
headers: { "Content-Type": "application/json" },
|
|
133
133
|
})
|
|
134
134
|
);
|
|
135
|
-
});
|
|
135
|
+
}) as unknown as typeof fetch;
|
|
136
136
|
|
|
137
137
|
await handleToolCall(createRequest("list_issues"));
|
|
138
138
|
|
|
139
139
|
expect(capturedHeaders).toBeDefined();
|
|
140
|
-
expect(
|
|
140
|
+
expect(capturedHeaders!["access-token"]).toBe("config-api-key");
|
|
141
141
|
|
|
142
142
|
readConfigSpy.mockRestore();
|
|
143
143
|
});
|
|
@@ -152,21 +152,21 @@ describe("MCP Server", () => {
|
|
|
152
152
|
defaultProject: null,
|
|
153
153
|
});
|
|
154
154
|
|
|
155
|
-
let capturedHeaders:
|
|
155
|
+
let capturedHeaders: Record<string, string> | undefined;
|
|
156
156
|
globalThis.fetch = mock((url: string, options?: RequestInit) => {
|
|
157
|
-
capturedHeaders = options?.headers;
|
|
157
|
+
capturedHeaders = options?.headers as Record<string, string> | undefined;
|
|
158
158
|
return Promise.resolve(
|
|
159
159
|
new Response(JSON.stringify([]), {
|
|
160
160
|
status: 200,
|
|
161
161
|
headers: { "Content-Type": "application/json" },
|
|
162
162
|
})
|
|
163
163
|
);
|
|
164
|
-
});
|
|
164
|
+
}) as unknown as typeof fetch;
|
|
165
165
|
|
|
166
166
|
await handleToolCall(createRequest("list_issues"));
|
|
167
167
|
|
|
168
168
|
expect(capturedHeaders).toBeDefined();
|
|
169
|
-
expect(
|
|
169
|
+
expect(capturedHeaders!["access-token"]).toBe("env-api-key");
|
|
170
170
|
|
|
171
171
|
readConfigSpy.mockRestore();
|
|
172
172
|
});
|
|
@@ -193,7 +193,7 @@ describe("MCP Server", () => {
|
|
|
193
193
|
headers: { "Content-Type": "application/json" },
|
|
194
194
|
})
|
|
195
195
|
)
|
|
196
|
-
);
|
|
196
|
+
) as unknown as typeof fetch;
|
|
197
197
|
|
|
198
198
|
const response = await handleToolCall(createRequest("list_issues"));
|
|
199
199
|
|
|
@@ -220,7 +220,7 @@ describe("MCP Server", () => {
|
|
|
220
220
|
headers: { "Content-Type": "application/json" },
|
|
221
221
|
})
|
|
222
222
|
)
|
|
223
|
-
);
|
|
223
|
+
) as unknown as typeof fetch;
|
|
224
224
|
|
|
225
225
|
const response = await handleToolCall(createRequest("list_issues"));
|
|
226
226
|
|
|
@@ -280,7 +280,7 @@ describe("MCP Server", () => {
|
|
|
280
280
|
headers: { "Content-Type": "application/json" },
|
|
281
281
|
})
|
|
282
282
|
)
|
|
283
|
-
);
|
|
283
|
+
) as unknown as typeof fetch;
|
|
284
284
|
|
|
285
285
|
const response = await handleToolCall(createRequest("view_issue", { issue_id: "nonexistent-id" }));
|
|
286
286
|
|
|
@@ -319,7 +319,7 @@ describe("MCP Server", () => {
|
|
|
319
319
|
headers: { "Content-Type": "application/json" },
|
|
320
320
|
})
|
|
321
321
|
);
|
|
322
|
-
});
|
|
322
|
+
}) as unknown as typeof fetch;
|
|
323
323
|
|
|
324
324
|
const response = await handleToolCall(createRequest("view_issue", { issue_id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" }));
|
|
325
325
|
|
|
@@ -386,7 +386,7 @@ describe("MCP Server", () => {
|
|
|
386
386
|
headers: { "Content-Type": "application/json" },
|
|
387
387
|
})
|
|
388
388
|
);
|
|
389
|
-
});
|
|
389
|
+
}) as unknown as typeof fetch;
|
|
390
390
|
|
|
391
391
|
await handleToolCall(
|
|
392
392
|
createRequest("post_issue_comment", {
|
|
@@ -419,7 +419,7 @@ describe("MCP Server", () => {
|
|
|
419
419
|
headers: { "Content-Type": "application/json" },
|
|
420
420
|
})
|
|
421
421
|
);
|
|
422
|
-
});
|
|
422
|
+
}) as unknown as typeof fetch;
|
|
423
423
|
|
|
424
424
|
const response = await handleToolCall(
|
|
425
425
|
createRequest("post_issue_comment", {
|
|
@@ -504,7 +504,7 @@ describe("MCP Server", () => {
|
|
|
504
504
|
headers: { "Content-Type": "application/json" },
|
|
505
505
|
})
|
|
506
506
|
);
|
|
507
|
-
});
|
|
507
|
+
}) as unknown as typeof fetch;
|
|
508
508
|
|
|
509
509
|
await handleToolCall(createRequest("create_issue", { title: "Test Issue" }));
|
|
510
510
|
|
|
@@ -532,7 +532,7 @@ describe("MCP Server", () => {
|
|
|
532
532
|
headers: { "Content-Type": "application/json" },
|
|
533
533
|
})
|
|
534
534
|
);
|
|
535
|
-
});
|
|
535
|
+
}) as unknown as typeof fetch;
|
|
536
536
|
|
|
537
537
|
await handleToolCall(
|
|
538
538
|
createRequest("create_issue", {
|
|
@@ -566,7 +566,7 @@ describe("MCP Server", () => {
|
|
|
566
566
|
headers: { "Content-Type": "application/json" },
|
|
567
567
|
})
|
|
568
568
|
);
|
|
569
|
-
});
|
|
569
|
+
}) as unknown as typeof fetch;
|
|
570
570
|
|
|
571
571
|
const response = await handleToolCall(
|
|
572
572
|
createRequest("create_issue", {
|
|
@@ -679,7 +679,7 @@ describe("MCP Server", () => {
|
|
|
679
679
|
headers: { "Content-Type": "application/json" },
|
|
680
680
|
})
|
|
681
681
|
);
|
|
682
|
-
});
|
|
682
|
+
}) as unknown as typeof fetch;
|
|
683
683
|
|
|
684
684
|
await handleToolCall(
|
|
685
685
|
createRequest("update_issue", {
|
|
@@ -712,7 +712,7 @@ describe("MCP Server", () => {
|
|
|
712
712
|
headers: { "Content-Type": "application/json" },
|
|
713
713
|
})
|
|
714
714
|
)
|
|
715
|
-
);
|
|
715
|
+
) as unknown as typeof fetch;
|
|
716
716
|
|
|
717
717
|
const response = await handleToolCall(
|
|
718
718
|
createRequest("update_issue", { issue_id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", title: "New Title" })
|
|
@@ -740,7 +740,7 @@ describe("MCP Server", () => {
|
|
|
740
740
|
headers: { "Content-Type": "application/json" },
|
|
741
741
|
})
|
|
742
742
|
);
|
|
743
|
-
});
|
|
743
|
+
}) as unknown as typeof fetch;
|
|
744
744
|
|
|
745
745
|
const response = await handleToolCall(
|
|
746
746
|
createRequest("update_issue", { issue_id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", status: 1 })
|
|
@@ -771,7 +771,7 @@ describe("MCP Server", () => {
|
|
|
771
771
|
headers: { "Content-Type": "application/json" },
|
|
772
772
|
})
|
|
773
773
|
);
|
|
774
|
-
});
|
|
774
|
+
}) as unknown as typeof fetch;
|
|
775
775
|
|
|
776
776
|
const response = await handleToolCall(
|
|
777
777
|
createRequest("update_issue", { issue_id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", labels: ["new-label"] })
|
|
@@ -802,7 +802,7 @@ describe("MCP Server", () => {
|
|
|
802
802
|
headers: { "Content-Type": "application/json" },
|
|
803
803
|
})
|
|
804
804
|
);
|
|
805
|
-
});
|
|
805
|
+
}) as unknown as typeof fetch;
|
|
806
806
|
|
|
807
807
|
const response = await handleToolCall(
|
|
808
808
|
createRequest("update_issue", { issue_id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", status: 0 })
|
|
@@ -871,7 +871,7 @@ describe("MCP Server", () => {
|
|
|
871
871
|
headers: { "Content-Type": "application/json" },
|
|
872
872
|
})
|
|
873
873
|
);
|
|
874
|
-
});
|
|
874
|
+
}) as unknown as typeof fetch;
|
|
875
875
|
|
|
876
876
|
await handleToolCall(
|
|
877
877
|
createRequest("update_issue_comment", {
|
|
@@ -902,7 +902,7 @@ describe("MCP Server", () => {
|
|
|
902
902
|
headers: { "Content-Type": "application/json" },
|
|
903
903
|
})
|
|
904
904
|
)
|
|
905
|
-
);
|
|
905
|
+
) as unknown as typeof fetch;
|
|
906
906
|
|
|
907
907
|
const response = await handleToolCall(
|
|
908
908
|
createRequest("update_issue_comment", {
|
|
@@ -999,7 +999,7 @@ describe("MCP Server", () => {
|
|
|
999
999
|
headers: { "Content-Type": "application/json" },
|
|
1000
1000
|
})
|
|
1001
1001
|
)
|
|
1002
|
-
);
|
|
1002
|
+
) as unknown as typeof fetch;
|
|
1003
1003
|
|
|
1004
1004
|
const response = await handleToolCall(createRequest("view_action_item", { action_item_id: "00000000-0000-0000-0000-000000000000" }));
|
|
1005
1005
|
|
|
@@ -1036,7 +1036,7 @@ describe("MCP Server", () => {
|
|
|
1036
1036
|
headers: { "Content-Type": "application/json" },
|
|
1037
1037
|
})
|
|
1038
1038
|
)
|
|
1039
|
-
);
|
|
1039
|
+
) as unknown as typeof fetch;
|
|
1040
1040
|
|
|
1041
1041
|
const response = await handleToolCall(createRequest("view_action_item", { action_item_id: "11111111-1111-1111-1111-111111111111" }));
|
|
1042
1042
|
|
|
@@ -1072,7 +1072,7 @@ describe("MCP Server", () => {
|
|
|
1072
1072
|
headers: { "Content-Type": "application/json" },
|
|
1073
1073
|
})
|
|
1074
1074
|
);
|
|
1075
|
-
});
|
|
1075
|
+
}) as unknown as typeof fetch;
|
|
1076
1076
|
|
|
1077
1077
|
const response = await handleToolCall(createRequest("view_action_item", { action_item_ids: ["11111111-1111-1111-1111-111111111111", "22222222-2222-2222-2222-222222222222"] }));
|
|
1078
1078
|
|
|
@@ -1141,7 +1141,7 @@ describe("MCP Server", () => {
|
|
|
1141
1141
|
headers: { "Content-Type": "application/json" },
|
|
1142
1142
|
})
|
|
1143
1143
|
)
|
|
1144
|
-
);
|
|
1144
|
+
) as unknown as typeof fetch;
|
|
1145
1145
|
|
|
1146
1146
|
const response = await handleToolCall(createRequest("list_action_items", { issue_id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" }));
|
|
1147
1147
|
|
|
@@ -1208,7 +1208,7 @@ describe("MCP Server", () => {
|
|
|
1208
1208
|
headers: { "Content-Type": "application/json" },
|
|
1209
1209
|
})
|
|
1210
1210
|
);
|
|
1211
|
-
});
|
|
1211
|
+
}) as unknown as typeof fetch;
|
|
1212
1212
|
|
|
1213
1213
|
const response = await handleToolCall(
|
|
1214
1214
|
createRequest("create_action_item", {
|
|
@@ -1243,7 +1243,7 @@ describe("MCP Server", () => {
|
|
|
1243
1243
|
headers: { "Content-Type": "application/json" },
|
|
1244
1244
|
})
|
|
1245
1245
|
);
|
|
1246
|
-
});
|
|
1246
|
+
}) as unknown as typeof fetch;
|
|
1247
1247
|
|
|
1248
1248
|
const response = await handleToolCall(
|
|
1249
1249
|
createRequest("create_action_item", {
|
|
@@ -1284,7 +1284,7 @@ describe("MCP Server", () => {
|
|
|
1284
1284
|
headers: { "Content-Type": "application/json" },
|
|
1285
1285
|
})
|
|
1286
1286
|
);
|
|
1287
|
-
});
|
|
1287
|
+
}) as unknown as typeof fetch;
|
|
1288
1288
|
|
|
1289
1289
|
await handleToolCall(
|
|
1290
1290
|
createRequest("create_action_item", {
|
|
@@ -1375,7 +1375,7 @@ describe("MCP Server", () => {
|
|
|
1375
1375
|
headers: { "Content-Type": "application/json" },
|
|
1376
1376
|
})
|
|
1377
1377
|
);
|
|
1378
|
-
});
|
|
1378
|
+
}) as unknown as typeof fetch;
|
|
1379
1379
|
|
|
1380
1380
|
const response = await handleToolCall(
|
|
1381
1381
|
createRequest("update_action_item", { action_item_id: "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", title: "New Title" })
|
|
@@ -1407,7 +1407,7 @@ describe("MCP Server", () => {
|
|
|
1407
1407
|
headers: { "Content-Type": "application/json" },
|
|
1408
1408
|
})
|
|
1409
1409
|
);
|
|
1410
|
-
});
|
|
1410
|
+
}) as unknown as typeof fetch;
|
|
1411
1411
|
|
|
1412
1412
|
const response = await handleToolCall(
|
|
1413
1413
|
createRequest("update_action_item", { action_item_id: "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", is_done: true })
|
|
@@ -1438,7 +1438,7 @@ describe("MCP Server", () => {
|
|
|
1438
1438
|
headers: { "Content-Type": "application/json" },
|
|
1439
1439
|
})
|
|
1440
1440
|
);
|
|
1441
|
-
});
|
|
1441
|
+
}) as unknown as typeof fetch;
|
|
1442
1442
|
|
|
1443
1443
|
const response = await handleToolCall(
|
|
1444
1444
|
createRequest("update_action_item", {
|
|
@@ -1492,7 +1492,7 @@ describe("MCP Server", () => {
|
|
|
1492
1492
|
headers: { "Content-Type": "application/json" },
|
|
1493
1493
|
})
|
|
1494
1494
|
)
|
|
1495
|
-
);
|
|
1495
|
+
) as unknown as typeof fetch;
|
|
1496
1496
|
|
|
1497
1497
|
const response = await handleToolCall(
|
|
1498
1498
|
createRequest("create_issue", { title: "Test Issue" })
|
|
@@ -1512,7 +1512,7 @@ describe("MCP Server", () => {
|
|
|
1512
1512
|
defaultProject: null,
|
|
1513
1513
|
});
|
|
1514
1514
|
|
|
1515
|
-
globalThis.fetch = mock(() => Promise.reject(new Error("Network error")));
|
|
1515
|
+
globalThis.fetch = mock(() => Promise.reject(new Error("Network error"))) as unknown as typeof fetch;
|
|
1516
1516
|
|
|
1517
1517
|
const response = await handleToolCall(
|
|
1518
1518
|
createRequest("create_issue", { title: "Test Issue" })
|
package/test/supabase.test.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { describe, expect, test, beforeEach, afterEach, mock } from "bun:test";
|
|
|
2
2
|
import {
|
|
3
3
|
resolveSupabaseConfig,
|
|
4
4
|
extractProjectRefFromUrl,
|
|
5
|
+
fetchPoolerDatabaseUrl,
|
|
5
6
|
SupabaseClient,
|
|
6
7
|
applyInitPlanViaSupabase,
|
|
7
8
|
verifyInitSetupViaSupabase,
|
|
@@ -137,6 +138,146 @@ describe("Supabase module", () => {
|
|
|
137
138
|
});
|
|
138
139
|
});
|
|
139
140
|
|
|
141
|
+
describe("fetchPoolerDatabaseUrl", () => {
|
|
142
|
+
const originalFetch = globalThis.fetch;
|
|
143
|
+
|
|
144
|
+
afterEach(() => {
|
|
145
|
+
globalThis.fetch = originalFetch;
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("returns pooler db url with username including project ref (db_host/db_port/db_name response)", async () => {
|
|
149
|
+
globalThis.fetch = mock(() =>
|
|
150
|
+
Promise.resolve(
|
|
151
|
+
new Response(
|
|
152
|
+
JSON.stringify([
|
|
153
|
+
{
|
|
154
|
+
db_host: "aws-1-eu-west-1.pooler.supabase.com",
|
|
155
|
+
db_port: 6543,
|
|
156
|
+
db_name: "postgres",
|
|
157
|
+
},
|
|
158
|
+
]),
|
|
159
|
+
{ status: 200 }
|
|
160
|
+
)
|
|
161
|
+
)
|
|
162
|
+
) as unknown as typeof fetch;
|
|
163
|
+
|
|
164
|
+
const url = await fetchPoolerDatabaseUrl(
|
|
165
|
+
{ projectRef: "xhaqmsvczjkkvkgdyast", accessToken: "token" },
|
|
166
|
+
"postgres_ai_mon"
|
|
167
|
+
);
|
|
168
|
+
expect(url).toBe(
|
|
169
|
+
"postgresql://postgres_ai_mon.xhaqmsvczjkkvkgdyast@aws-1-eu-west-1.pooler.supabase.com:6543/postgres"
|
|
170
|
+
);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test("does not double-append project ref if username already has it", async () => {
|
|
174
|
+
globalThis.fetch = mock(() =>
|
|
175
|
+
Promise.resolve(
|
|
176
|
+
new Response(
|
|
177
|
+
JSON.stringify([
|
|
178
|
+
{
|
|
179
|
+
db_host: "aws-1-eu-west-1.pooler.supabase.com",
|
|
180
|
+
db_port: 6543,
|
|
181
|
+
db_name: "postgres",
|
|
182
|
+
},
|
|
183
|
+
]),
|
|
184
|
+
{ status: 200 }
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
) as unknown as typeof fetch;
|
|
188
|
+
|
|
189
|
+
const url = await fetchPoolerDatabaseUrl(
|
|
190
|
+
{ projectRef: "xhaqmsvczjkkvkgdyast", accessToken: "token" },
|
|
191
|
+
"postgres_ai_mon.xhaqmsvczjkkvkgdyast"
|
|
192
|
+
);
|
|
193
|
+
expect(url).toBe(
|
|
194
|
+
"postgresql://postgres_ai_mon.xhaqmsvczjkkvkgdyast@aws-1-eu-west-1.pooler.supabase.com:6543/postgres"
|
|
195
|
+
);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("returns pooler db url via connection_string fallback path", async () => {
|
|
199
|
+
globalThis.fetch = mock(() =>
|
|
200
|
+
Promise.resolve(
|
|
201
|
+
new Response(
|
|
202
|
+
JSON.stringify([
|
|
203
|
+
{
|
|
204
|
+
// No db_host/db_port/db_name - uses connection_string fallback
|
|
205
|
+
connection_string:
|
|
206
|
+
"postgresql://ignored@aws-1-eu-west-1.pooler.supabase.com:6543/postgres",
|
|
207
|
+
},
|
|
208
|
+
]),
|
|
209
|
+
{ status: 200 }
|
|
210
|
+
)
|
|
211
|
+
)
|
|
212
|
+
) as unknown as typeof fetch;
|
|
213
|
+
|
|
214
|
+
const url = await fetchPoolerDatabaseUrl(
|
|
215
|
+
{ projectRef: "xhaqmsvczjkkvkgdyast", accessToken: "token" },
|
|
216
|
+
"postgres_ai_mon"
|
|
217
|
+
);
|
|
218
|
+
expect(url).toBe(
|
|
219
|
+
"postgresql://postgres_ai_mon.xhaqmsvczjkkvkgdyast@aws-1-eu-west-1.pooler.supabase.com:6543/postgres"
|
|
220
|
+
);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test("returns null for invalid connection_string URL", async () => {
|
|
224
|
+
globalThis.fetch = mock(() =>
|
|
225
|
+
Promise.resolve(
|
|
226
|
+
new Response(
|
|
227
|
+
JSON.stringify([
|
|
228
|
+
{
|
|
229
|
+
connection_string: "not-a-valid-url",
|
|
230
|
+
},
|
|
231
|
+
]),
|
|
232
|
+
{ status: 200 }
|
|
233
|
+
)
|
|
234
|
+
)
|
|
235
|
+
) as unknown as typeof fetch;
|
|
236
|
+
|
|
237
|
+
const url = await fetchPoolerDatabaseUrl(
|
|
238
|
+
{ projectRef: "xhaqmsvczjkkvkgdyast", accessToken: "token" },
|
|
239
|
+
"postgres_ai_mon"
|
|
240
|
+
);
|
|
241
|
+
expect(url).toBeNull();
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
test("returns null for empty API response", async () => {
|
|
245
|
+
globalThis.fetch = mock(() =>
|
|
246
|
+
Promise.resolve(new Response(JSON.stringify([]), { status: 200 }))
|
|
247
|
+
) as unknown as typeof fetch;
|
|
248
|
+
|
|
249
|
+
const url = await fetchPoolerDatabaseUrl(
|
|
250
|
+
{ projectRef: "xhaqmsvczjkkvkgdyast", accessToken: "token" },
|
|
251
|
+
"postgres_ai_mon"
|
|
252
|
+
);
|
|
253
|
+
expect(url).toBeNull();
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
test("returns null for API error response", async () => {
|
|
257
|
+
globalThis.fetch = mock(() =>
|
|
258
|
+
Promise.resolve(new Response("Unauthorized", { status: 401 }))
|
|
259
|
+
) as unknown as typeof fetch;
|
|
260
|
+
|
|
261
|
+
const url = await fetchPoolerDatabaseUrl(
|
|
262
|
+
{ projectRef: "xhaqmsvczjkkvkgdyast", accessToken: "token" },
|
|
263
|
+
"postgres_ai_mon"
|
|
264
|
+
);
|
|
265
|
+
expect(url).toBeNull();
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test("returns null when fetch throws network error", async () => {
|
|
269
|
+
globalThis.fetch = mock(() =>
|
|
270
|
+
Promise.reject(new Error("Network error"))
|
|
271
|
+
) as unknown as typeof fetch;
|
|
272
|
+
|
|
273
|
+
const url = await fetchPoolerDatabaseUrl(
|
|
274
|
+
{ projectRef: "xhaqmsvczjkkvkgdyast", accessToken: "token" },
|
|
275
|
+
"postgres_ai_mon"
|
|
276
|
+
);
|
|
277
|
+
expect(url).toBeNull();
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
|
|
140
281
|
describe("SupabaseClient", () => {
|
|
141
282
|
test("throws error when project ref is empty", () => {
|
|
142
283
|
expect(() => new SupabaseClient({ projectRef: "", accessToken: "token" })).toThrow(
|