@supacloud/cli 0.2.0 → 0.3.1
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 +20 -0
- package/dist/index.js +49 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,9 +14,29 @@ npx @supacloud/cli status
|
|
|
14
14
|
npx @supacloud/cli project get
|
|
15
15
|
npx @supacloud/cli project logs --log_type database
|
|
16
16
|
npx @supacloud/cli database query --sql "select now()"
|
|
17
|
+
npx @supacloud/cli database query --ref abc123 --file ./queries/vector-search.sql
|
|
18
|
+
npx @supacloud/cli database push_migrations --ref abc123 --dir supabase/migrations --dry_run
|
|
17
19
|
npx @supacloud/cli frontend list --ref abc123
|
|
18
20
|
```
|
|
19
21
|
|
|
22
|
+
Use `database query --file` for complex SQL, pgvector queries, and single-request transaction blocks.
|
|
23
|
+
|
|
24
|
+
```sql
|
|
25
|
+
CREATE EXTENSION IF NOT EXISTS vector;
|
|
26
|
+
|
|
27
|
+
CREATE TABLE documents (
|
|
28
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
29
|
+
content text NOT NULL,
|
|
30
|
+
embedding vector(1536)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
CREATE INDEX documents_embedding_hnsw_idx
|
|
34
|
+
ON documents
|
|
35
|
+
USING hnsw (embedding vector_cosine_ops);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Transaction boundary: SupaCloud supports transaction blocks inside one SQL request and transactional migrations. It does not expose long-lived HTTP transaction sessions; use a direct Postgres DSN for application-side long transactions.
|
|
39
|
+
|
|
20
40
|
Project commands owned by this CLI:
|
|
21
41
|
|
|
22
42
|
- `project get`
|
package/dist/index.js
CHANGED
|
@@ -4347,21 +4347,6 @@ class HttpTransport {
|
|
|
4347
4347
|
// src/shared/tools/database-tools.ts
|
|
4348
4348
|
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
4349
4349
|
import { basename, join } from "node:path";
|
|
4350
|
-
function normalizeSqlResponse(result) {
|
|
4351
|
-
if (!result.ok)
|
|
4352
|
-
return result;
|
|
4353
|
-
const data = result.data;
|
|
4354
|
-
if (Array.isArray(data?.result) && !Array.isArray(data.rows)) {
|
|
4355
|
-
return {
|
|
4356
|
-
...result,
|
|
4357
|
-
data: {
|
|
4358
|
-
rows: data.result,
|
|
4359
|
-
rowCount: data.result.length
|
|
4360
|
-
}
|
|
4361
|
-
};
|
|
4362
|
-
}
|
|
4363
|
-
return result;
|
|
4364
|
-
}
|
|
4365
4350
|
function migrationVersionFromFilename(file, fallbackIndex = 0) {
|
|
4366
4351
|
const match = basename(file).match(/^(\d{8,20})[_-]/);
|
|
4367
4352
|
if (match)
|
|
@@ -4369,7 +4354,7 @@ function migrationVersionFromFilename(file, fallbackIndex = 0) {
|
|
|
4369
4354
|
return Date.now() * 1000 + fallbackIndex;
|
|
4370
4355
|
}
|
|
4371
4356
|
function appliedMigrationKeys(data) {
|
|
4372
|
-
const rows =
|
|
4357
|
+
const rows = data?.rows || [];
|
|
4373
4358
|
const keys = new Set;
|
|
4374
4359
|
for (const row of rows) {
|
|
4375
4360
|
if (!row || typeof row !== "object")
|
|
@@ -4382,6 +4367,34 @@ function appliedMigrationKeys(data) {
|
|
|
4382
4367
|
}
|
|
4383
4368
|
return keys;
|
|
4384
4369
|
}
|
|
4370
|
+
function sqlReferencesVector(sql) {
|
|
4371
|
+
return /\bvector\s*\(\s*\d+\s*\)/i.test(sql) || /::\s*vector\b/i.test(sql) || /\bvector_(cosine|l2|ip)_ops\b/i.test(sql) || /<=>|<#>|<->/.test(sql);
|
|
4372
|
+
}
|
|
4373
|
+
function sqlCreatesVectorExtension(sql) {
|
|
4374
|
+
return /\bCREATE\s+EXTENSION\s+(?:IF\s+NOT\s+EXISTS\s+)?["']?vector["']?/i.test(sql);
|
|
4375
|
+
}
|
|
4376
|
+
function extensionRows(data) {
|
|
4377
|
+
const shaped = data;
|
|
4378
|
+
const rows = shaped?.rows || [];
|
|
4379
|
+
return Array.isArray(rows) ? rows : [];
|
|
4380
|
+
}
|
|
4381
|
+
function vectorWarningsForPendingMigrations(migrations, vectorEnabled) {
|
|
4382
|
+
const warnings = [];
|
|
4383
|
+
const vectorUsers = migrations.filter(({ sql }) => sqlReferencesVector(sql));
|
|
4384
|
+
const vectorCreators = migrations.filter(({ sql }) => sqlCreatesVectorExtension(sql));
|
|
4385
|
+
if (!vectorUsers.length && !vectorCreators.length)
|
|
4386
|
+
return warnings;
|
|
4387
|
+
if (vectorEnabled === false && vectorUsers.length && !vectorCreators.length) {
|
|
4388
|
+
warnings.push(`vector extension is not enabled, but pending migrations use vector types/operators: ${vectorUsers.map(({ file }) => file).join(", ")}`);
|
|
4389
|
+
}
|
|
4390
|
+
if (vectorEnabled === false && vectorCreators.length) {
|
|
4391
|
+
warnings.push(`pending migrations will enable pgvector: ${vectorCreators.map(({ file }) => file).join(", ")}`);
|
|
4392
|
+
}
|
|
4393
|
+
if (vectorEnabled === null) {
|
|
4394
|
+
warnings.push("could not verify whether vector extension is enabled");
|
|
4395
|
+
}
|
|
4396
|
+
return warnings;
|
|
4397
|
+
}
|
|
4385
4398
|
function registerDatabaseTools(server, http, config = {}) {
|
|
4386
4399
|
const { readOnly = false, projectRef } = config;
|
|
4387
4400
|
const actions = [
|
|
@@ -4431,7 +4444,7 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
|
|
|
4431
4444
|
return { content: [{ type: "text", text: `❌ Failed to read file ${args.file}: ${e.message}` }] };
|
|
4432
4445
|
}
|
|
4433
4446
|
}
|
|
4434
|
-
const execSql = async (sql) =>
|
|
4447
|
+
const execSql = async (sql) => http.post(`/v1/projects/${ref}/database/sql`, { sql });
|
|
4435
4448
|
let text;
|
|
4436
4449
|
switch (action) {
|
|
4437
4450
|
case "query": {
|
|
@@ -4578,13 +4591,26 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
|
|
|
4578
4591
|
const appliedKeys = appliedMigrationKeys(r.data);
|
|
4579
4592
|
const pending = migrationFiles.filter(({ name, version }) => !appliedKeys.has(name) && !appliedKeys.has(String(version)));
|
|
4580
4593
|
const alreadyApplied = migrationFiles.filter(({ name, version }) => appliedKeys.has(name) || appliedKeys.has(String(version)));
|
|
4594
|
+
const pendingWithSql = pending.map((migration) => ({
|
|
4595
|
+
...migration,
|
|
4596
|
+
sql: readFileSync2(join(dir, migration.file), "utf-8")
|
|
4597
|
+
}));
|
|
4598
|
+
let vectorEnabled = null;
|
|
4599
|
+
if (pendingWithSql.some(({ sql }) => sqlReferencesVector(sql) || sqlCreatesVectorExtension(sql))) {
|
|
4600
|
+
const extResult = await execSql("SELECT extname AS name FROM pg_extension WHERE extname = 'vector';");
|
|
4601
|
+
vectorEnabled = extResult.ok ? extensionRows(extResult.data).some((row) => row.name === "vector" || row.extname === "vector") : null;
|
|
4602
|
+
}
|
|
4603
|
+
const warnings = vectorWarningsForPendingMigrations(pendingWithSql, vectorEnabled);
|
|
4581
4604
|
text = [
|
|
4582
4605
|
`Migration dry run for ${dir}`,
|
|
4583
4606
|
`Total: ${migrationFiles.length}`,
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
...pending.length ?
|
|
4587
|
-
|
|
4607
|
+
"",
|
|
4608
|
+
"Pending:",
|
|
4609
|
+
...pending.length ? pending.map(({ file, version }) => ` - ${file} (${version})`) : [" - none"],
|
|
4610
|
+
"",
|
|
4611
|
+
"Already applied:",
|
|
4612
|
+
...alreadyApplied.length ? alreadyApplied.map(({ file, version }) => ` - ${file} (${version})`) : [" - none"],
|
|
4613
|
+
...warnings.length ? ["", "Warnings:", ...warnings.map((warning) => ` - ${warning}`)] : []
|
|
4588
4614
|
].join(`
|
|
4589
4615
|
`);
|
|
4590
4616
|
break;
|
|
@@ -5671,6 +5697,8 @@ EXAMPLES
|
|
|
5671
5697
|
supacloud project logs --log_type database
|
|
5672
5698
|
supacloud frontend list --ref abc123
|
|
5673
5699
|
supacloud database query --sql "select now()"
|
|
5700
|
+
supacloud database query --ref abc123 --file ./queries/vector-search.sql
|
|
5701
|
+
supacloud database push_migrations --ref abc123 --dir supabase/migrations --dry_run
|
|
5674
5702
|
supacloud edge_functions deploy --ref abc123 --slug hello --path ./supabase/functions/hello
|
|
5675
5703
|
supacloud edge_functions config --ref abc123 --slug hello --verify_jwt false --background_routes "/queue/*,/render/*"
|
|
5676
5704
|
|