postgresai 0.14.0-dev.73 → 0.14.0-dev.74
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/dist/bin/postgres-ai.js +8 -4
- package/lib/metrics-embedded.ts +1 -1
- package/lib/supabase.ts +10 -2
- package/package.json +1 -1
- package/test/supabase.test.ts +59 -0
package/dist/bin/postgres-ai.js
CHANGED
|
@@ -13064,7 +13064,7 @@ var {
|
|
|
13064
13064
|
// package.json
|
|
13065
13065
|
var package_default = {
|
|
13066
13066
|
name: "postgresai",
|
|
13067
|
-
version: "0.14.0-dev.
|
|
13067
|
+
version: "0.14.0-dev.74",
|
|
13068
13068
|
description: "postgres_ai CLI",
|
|
13069
13069
|
license: "Apache-2.0",
|
|
13070
13070
|
private: false,
|
|
@@ -15887,7 +15887,7 @@ var Result = import_lib.default.Result;
|
|
|
15887
15887
|
var TypeOverrides = import_lib.default.TypeOverrides;
|
|
15888
15888
|
var defaults = import_lib.default.defaults;
|
|
15889
15889
|
// package.json
|
|
15890
|
-
var version = "0.14.0-dev.
|
|
15890
|
+
var version = "0.14.0-dev.74";
|
|
15891
15891
|
var package_default2 = {
|
|
15892
15892
|
name: "postgresai",
|
|
15893
15893
|
version,
|
|
@@ -25314,6 +25314,10 @@ class SupabaseClient {
|
|
|
25314
25314
|
}
|
|
25315
25315
|
async function fetchPoolerDatabaseUrl(config2, username) {
|
|
25316
25316
|
const url = `${SUPABASE_API_BASE}/v1/projects/${encodeURIComponent(config2.projectRef)}/config/database/pooler`;
|
|
25317
|
+
const effectiveUsername = (() => {
|
|
25318
|
+
const suffix = `.${config2.projectRef}`;
|
|
25319
|
+
return username.endsWith(suffix) ? username : `${username}${suffix}`;
|
|
25320
|
+
})();
|
|
25317
25321
|
try {
|
|
25318
25322
|
const response = await fetch(url, {
|
|
25319
25323
|
method: "GET",
|
|
@@ -25328,13 +25332,13 @@ async function fetchPoolerDatabaseUrl(config2, username) {
|
|
|
25328
25332
|
if (Array.isArray(data) && data.length > 0) {
|
|
25329
25333
|
const pooler = data[0];
|
|
25330
25334
|
if (pooler.db_host && pooler.db_port && pooler.db_name) {
|
|
25331
|
-
return `postgresql://${
|
|
25335
|
+
return `postgresql://${effectiveUsername}@${pooler.db_host}:${pooler.db_port}/${pooler.db_name}`;
|
|
25332
25336
|
}
|
|
25333
25337
|
if (typeof pooler.connection_string === "string") {
|
|
25334
25338
|
try {
|
|
25335
25339
|
const connUrl = new URL(pooler.connection_string);
|
|
25336
25340
|
const portPart = connUrl.port ? `:${connUrl.port}` : "";
|
|
25337
|
-
return `postgresql://${
|
|
25341
|
+
return `postgresql://${effectiveUsername}@${connUrl.hostname}${portPart}${connUrl.pathname}`;
|
|
25338
25342
|
} catch {
|
|
25339
25343
|
return null;
|
|
25340
25344
|
}
|
package/lib/metrics-embedded.ts
CHANGED
package/lib/supabase.ts
CHANGED
|
@@ -347,6 +347,14 @@ export async function fetchPoolerDatabaseUrl(
|
|
|
347
347
|
): Promise<string | null> {
|
|
348
348
|
const url = `${SUPABASE_API_BASE}/v1/projects/${encodeURIComponent(config.projectRef)}/config/database/pooler`;
|
|
349
349
|
|
|
350
|
+
// For Supabase pooler connections, the username must include the project ref:
|
|
351
|
+
// <user>.<project_ref>
|
|
352
|
+
// Example:
|
|
353
|
+
// postgresql://postgres_ai_mon.xhaqmsvczjkkvkgdyast@aws-1-eu-west-1.pooler.supabase.com:6543/postgres
|
|
354
|
+
const effectiveUsername = (() => {
|
|
355
|
+
const suffix = `.${config.projectRef}`;
|
|
356
|
+
return username.endsWith(suffix) ? username : `${username}${suffix}`;
|
|
357
|
+
})();
|
|
350
358
|
try {
|
|
351
359
|
const response = await fetch(url, {
|
|
352
360
|
method: "GET",
|
|
@@ -367,7 +375,7 @@ export async function fetchPoolerDatabaseUrl(
|
|
|
367
375
|
const pooler = data[0];
|
|
368
376
|
// Build URL from components if available
|
|
369
377
|
if (pooler.db_host && pooler.db_port && pooler.db_name) {
|
|
370
|
-
return `postgresql://${
|
|
378
|
+
return `postgresql://${effectiveUsername}@${pooler.db_host}:${pooler.db_port}/${pooler.db_name}`;
|
|
371
379
|
}
|
|
372
380
|
// Fallback: try to extract from connection_string if present
|
|
373
381
|
if (typeof pooler.connection_string === "string") {
|
|
@@ -375,7 +383,7 @@ export async function fetchPoolerDatabaseUrl(
|
|
|
375
383
|
const connUrl = new URL(pooler.connection_string);
|
|
376
384
|
// Use provided username; handle empty port for default ports (e.g., 5432)
|
|
377
385
|
const portPart = connUrl.port ? `:${connUrl.port}` : "";
|
|
378
|
-
return `postgresql://${
|
|
386
|
+
return `postgresql://${effectiveUsername}@${connUrl.hostname}${portPart}${connUrl.pathname}`;
|
|
379
387
|
} catch {
|
|
380
388
|
return null;
|
|
381
389
|
}
|
package/package.json
CHANGED
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,64 @@ 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
|
+
|
|
140
199
|
describe("SupabaseClient", () => {
|
|
141
200
|
test("throws error when project ref is empty", () => {
|
|
142
201
|
expect(() => new SupabaseClient({ projectRef: "", accessToken: "token" })).toThrow(
|