@supacloud/cli 0.1.0 → 0.2.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/dist/index.js +222 -55
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __returnValue = (v) => v;
|
|
5
4
|
function __exportSetter(name, newValue) {
|
|
@@ -14,7 +13,6 @@ var __export = (target, all) => {
|
|
|
14
13
|
set: __exportSetter.bind(all, name)
|
|
15
14
|
});
|
|
16
15
|
};
|
|
17
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
18
16
|
|
|
19
17
|
// node_modules/zod/v3/external.js
|
|
20
18
|
var exports_external = {};
|
|
@@ -4347,6 +4345,8 @@ class HttpTransport {
|
|
|
4347
4345
|
}
|
|
4348
4346
|
|
|
4349
4347
|
// src/shared/tools/database-tools.ts
|
|
4348
|
+
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
4349
|
+
import { basename, join } from "node:path";
|
|
4350
4350
|
function normalizeSqlResponse(result) {
|
|
4351
4351
|
if (!result.ok)
|
|
4352
4352
|
return result;
|
|
@@ -4362,6 +4362,26 @@ function normalizeSqlResponse(result) {
|
|
|
4362
4362
|
}
|
|
4363
4363
|
return result;
|
|
4364
4364
|
}
|
|
4365
|
+
function migrationVersionFromFilename(file, fallbackIndex = 0) {
|
|
4366
|
+
const match = basename(file).match(/^(\d{8,20})[_-]/);
|
|
4367
|
+
if (match)
|
|
4368
|
+
return Number(match[1]);
|
|
4369
|
+
return Date.now() * 1000 + fallbackIndex;
|
|
4370
|
+
}
|
|
4371
|
+
function appliedMigrationKeys(data) {
|
|
4372
|
+
const rows = Array.isArray(data) ? data : data?.rows || [];
|
|
4373
|
+
const keys = new Set;
|
|
4374
|
+
for (const row of rows) {
|
|
4375
|
+
if (!row || typeof row !== "object")
|
|
4376
|
+
continue;
|
|
4377
|
+
const migration = row;
|
|
4378
|
+
if (migration.version != null)
|
|
4379
|
+
keys.add(String(migration.version));
|
|
4380
|
+
if (migration.name != null)
|
|
4381
|
+
keys.add(String(migration.name));
|
|
4382
|
+
}
|
|
4383
|
+
return keys;
|
|
4384
|
+
}
|
|
4365
4385
|
function registerDatabaseTools(server, http, config = {}) {
|
|
4366
4386
|
const { readOnly = false, projectRef } = config;
|
|
4367
4387
|
const actions = [
|
|
@@ -4382,7 +4402,7 @@ function registerDatabaseTools(server, http, config = {}) {
|
|
|
4382
4402
|
"project_url",
|
|
4383
4403
|
"generate_types"
|
|
4384
4404
|
];
|
|
4385
|
-
const writeActions = ["apply_migration", "create_table_rls"];
|
|
4405
|
+
const writeActions = ["apply_migration", "push_migrations", "create_table_rls"];
|
|
4386
4406
|
const allActions = readOnly ? actions : [...actions, ...writeActions];
|
|
4387
4407
|
server.tool("database", `Database operations: query, schema, RLS, migrations, stats.
|
|
4388
4408
|
Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
|
|
@@ -4390,6 +4410,8 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
|
|
|
4390
4410
|
ref: projectRef ? exports_external.string().optional() : exports_external.string().optional().describe("Project ref"),
|
|
4391
4411
|
sql: exports_external.string().optional().describe("[query/apply_migration] SQL statement"),
|
|
4392
4412
|
file: exports_external.string().optional().describe("[query/apply_migration] Read SQL from local file path (avoids shell escaping issues with $$ and multi-statement DDL)"),
|
|
4413
|
+
dir: exports_external.string().optional().describe("[push_migrations] Directory containing .sql migration files (default: supabase/migrations)"),
|
|
4414
|
+
dry_run: exports_external.boolean().optional().describe("[push_migrations] List pending migration files without applying them"),
|
|
4393
4415
|
schema: exports_external.string().optional().describe("[*] Schema name (default: public)"),
|
|
4394
4416
|
table: exports_external.string().optional().describe("[describe_columns/indexes/constraints/rls_*] Table name"),
|
|
4395
4417
|
schemas: exports_external.array(exports_external.string()).optional().describe("[list_tables/generate_types] Schemas array"),
|
|
@@ -4404,7 +4426,7 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
|
|
|
4404
4426
|
const schemas = args.schemas || ["public"];
|
|
4405
4427
|
if (args.file && !args.sql) {
|
|
4406
4428
|
try {
|
|
4407
|
-
args.sql =
|
|
4429
|
+
args.sql = readFileSync2(args.file, "utf-8");
|
|
4408
4430
|
} catch (e) {
|
|
4409
4431
|
return { content: [{ type: "text", text: `❌ Failed to read file ${args.file}: ${e.message}` }] };
|
|
4410
4432
|
}
|
|
@@ -4532,6 +4554,72 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
|
|
|
4532
4554
|
text = r.ok ? `✅ Migration '${args.name}' applied` : `❌ Failed (${r.status}): ${JSON.stringify(r.data)}`;
|
|
4533
4555
|
break;
|
|
4534
4556
|
}
|
|
4557
|
+
case "push_migrations": {
|
|
4558
|
+
const dir = args.dir || "supabase/migrations";
|
|
4559
|
+
if (!existsSync2(dir) || !statSync(dir).isDirectory()) {
|
|
4560
|
+
throw new Error(`Migration directory not found: ${dir}`);
|
|
4561
|
+
}
|
|
4562
|
+
const files = readdirSync(dir).filter((file) => file.endsWith(".sql")).sort();
|
|
4563
|
+
if (!files.length) {
|
|
4564
|
+
text = `No .sql migration files found in ${dir}`;
|
|
4565
|
+
break;
|
|
4566
|
+
}
|
|
4567
|
+
const migrationFiles = files.map((file, i) => ({
|
|
4568
|
+
file,
|
|
4569
|
+
name: basename(file, ".sql"),
|
|
4570
|
+
version: migrationVersionFromFilename(file, i)
|
|
4571
|
+
}));
|
|
4572
|
+
if (args.dry_run) {
|
|
4573
|
+
const r = await http.get(`/v1/projects/${ref}/database/migrations`);
|
|
4574
|
+
if (!r.ok) {
|
|
4575
|
+
text = `❌ Failed to load applied migrations (${r.status}): ${JSON.stringify(r.data)}`;
|
|
4576
|
+
break;
|
|
4577
|
+
}
|
|
4578
|
+
const appliedKeys = appliedMigrationKeys(r.data);
|
|
4579
|
+
const pending = migrationFiles.filter(({ name, version }) => !appliedKeys.has(name) && !appliedKeys.has(String(version)));
|
|
4580
|
+
const alreadyApplied = migrationFiles.filter(({ name, version }) => appliedKeys.has(name) || appliedKeys.has(String(version)));
|
|
4581
|
+
text = [
|
|
4582
|
+
`Migration dry run for ${dir}`,
|
|
4583
|
+
`Total: ${migrationFiles.length}`,
|
|
4584
|
+
`Pending: ${pending.length}`,
|
|
4585
|
+
`Already applied: ${alreadyApplied.length}`,
|
|
4586
|
+
...pending.length ? ["", "Would apply:", ...pending.map(({ file, version }) => ` - ${file} (${version})`)] : [],
|
|
4587
|
+
...alreadyApplied.length ? ["", "Already applied:", ...alreadyApplied.map(({ file, version }) => ` - ${file} (${version})`)] : []
|
|
4588
|
+
].join(`
|
|
4589
|
+
`);
|
|
4590
|
+
break;
|
|
4591
|
+
}
|
|
4592
|
+
const applied = [];
|
|
4593
|
+
const skipped = [];
|
|
4594
|
+
for (const { file, name, version } of migrationFiles) {
|
|
4595
|
+
const sql = readFileSync2(join(dir, file), "utf-8");
|
|
4596
|
+
const r = await http.post(`/v1/projects/${ref}/database/migrations`, { name, sql, version });
|
|
4597
|
+
if (r.ok) {
|
|
4598
|
+
applied.push(file);
|
|
4599
|
+
} else if (r.status === 409) {
|
|
4600
|
+
skipped.push(file);
|
|
4601
|
+
} else {
|
|
4602
|
+
text = [
|
|
4603
|
+
`❌ Failed to apply ${file} (${r.status})`,
|
|
4604
|
+
JSON.stringify(r.data, null, 2),
|
|
4605
|
+
"",
|
|
4606
|
+
`Applied before failure: ${applied.length}`,
|
|
4607
|
+
`Skipped before failure: ${skipped.length}`
|
|
4608
|
+
].join(`
|
|
4609
|
+
`);
|
|
4610
|
+
return { content: [{ type: "text", text }] };
|
|
4611
|
+
}
|
|
4612
|
+
}
|
|
4613
|
+
text = [
|
|
4614
|
+
`✅ Migration push completed for ${dir}`,
|
|
4615
|
+
`Applied: ${applied.length}`,
|
|
4616
|
+
`Skipped: ${skipped.length}`,
|
|
4617
|
+
...applied.length ? ["", "Applied files:", ...applied.map((file) => ` - ${file}`)] : [],
|
|
4618
|
+
...skipped.length ? ["", "Skipped files:", ...skipped.map((file) => ` - ${file}`)] : []
|
|
4619
|
+
].join(`
|
|
4620
|
+
`);
|
|
4621
|
+
break;
|
|
4622
|
+
}
|
|
4535
4623
|
case "create_table_rls": {
|
|
4536
4624
|
if (!args.table || !args.columns)
|
|
4537
4625
|
throw new Error("'table' and 'columns' required");
|
|
@@ -5028,69 +5116,125 @@ Actions: status, list_buckets, list_files, upload_base64, delete_file`, {
|
|
|
5028
5116
|
}
|
|
5029
5117
|
|
|
5030
5118
|
// src/shared/tools/advanced-tools.ts
|
|
5119
|
+
import { existsSync as existsSync3, mkdtempSync, readFileSync as readFileSync3, rmSync, statSync as statSync2, writeFileSync } from "node:fs";
|
|
5120
|
+
import { tmpdir } from "node:os";
|
|
5121
|
+
import { basename as basename2, join as join2, resolve as resolve2 } from "node:path";
|
|
5122
|
+
import { promisify } from "node:util";
|
|
5123
|
+
import { execFile } from "node:child_process";
|
|
5124
|
+
var execFileAsync = promisify(execFile);
|
|
5125
|
+
async function runBunBuild(args) {
|
|
5126
|
+
try {
|
|
5127
|
+
return await execFileAsync("bun", ["build", ...args], { maxBuffer: 10 * 1024 * 1024 });
|
|
5128
|
+
} catch (error) {
|
|
5129
|
+
const e = error;
|
|
5130
|
+
if (e.code === "ENOENT") {
|
|
5131
|
+
throw new Error("Bun is required for local edge function bundling. Install Bun or use deploy_bundle with explicit files.");
|
|
5132
|
+
}
|
|
5133
|
+
throw error;
|
|
5134
|
+
}
|
|
5135
|
+
}
|
|
5136
|
+
async function bundleEdgeFunctionPath(pathArg) {
|
|
5137
|
+
const entrypoint = resolveEntrypoint(pathArg);
|
|
5138
|
+
const tmpDir = mkdtempSync(join2(tmpdir(), "supacloud-edge-"));
|
|
5139
|
+
const outfile = join2(tmpDir, `${basename2(entrypoint).replace(/\.[^.]+$/, "") || "index"}.js`);
|
|
5140
|
+
try {
|
|
5141
|
+
const { stderr } = await runBunBuild([entrypoint, "--target", "bun", "--outfile", outfile]);
|
|
5142
|
+
if (!existsSync3(outfile))
|
|
5143
|
+
throw new Error(`Bundle failed: ${stderr}`);
|
|
5144
|
+
return readFileSync3(outfile, "utf-8");
|
|
5145
|
+
} finally {
|
|
5146
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
5147
|
+
}
|
|
5148
|
+
}
|
|
5149
|
+
function resolveEntrypoint(pathArg) {
|
|
5150
|
+
const resolved = resolve2(pathArg);
|
|
5151
|
+
const stat = statSync2(resolved);
|
|
5152
|
+
if (!stat.isDirectory())
|
|
5153
|
+
return resolved;
|
|
5154
|
+
const entrypoint = join2(resolved, "index.ts");
|
|
5155
|
+
if (!existsSync3(entrypoint)) {
|
|
5156
|
+
throw new Error(`Directory provided but no index.ts found at ${entrypoint}`);
|
|
5157
|
+
}
|
|
5158
|
+
return entrypoint;
|
|
5159
|
+
}
|
|
5160
|
+
var backgroundRoutesSchema = exports_external.preprocess((value) => {
|
|
5161
|
+
if (typeof value !== "string")
|
|
5162
|
+
return value;
|
|
5163
|
+
const trimmed = value.trim();
|
|
5164
|
+
if (!trimmed)
|
|
5165
|
+
return [];
|
|
5166
|
+
if (!trimmed.startsWith("["))
|
|
5167
|
+
return trimmed.split(",").map((route) => route.trim()).filter(Boolean);
|
|
5168
|
+
try {
|
|
5169
|
+
return JSON.parse(trimmed);
|
|
5170
|
+
} catch {
|
|
5171
|
+
return [trimmed];
|
|
5172
|
+
}
|
|
5173
|
+
}, exports_external.array(exports_external.string()).optional().superRefine((routes, ctx) => {
|
|
5174
|
+
if (!routes)
|
|
5175
|
+
return;
|
|
5176
|
+
for (const route of routes) {
|
|
5177
|
+
if (route.trim().startsWith("[")) {
|
|
5178
|
+
ctx.addIssue({
|
|
5179
|
+
code: exports_external.ZodIssueCode.custom,
|
|
5180
|
+
message: "Invalid background_routes JSON array. Use a valid JSON array or comma-separated routes like /queue/*,/render/*."
|
|
5181
|
+
});
|
|
5182
|
+
return;
|
|
5183
|
+
}
|
|
5184
|
+
}
|
|
5185
|
+
}));
|
|
5031
5186
|
function registerAdvancedTools(server, http) {
|
|
5032
5187
|
server.tool("edge_functions", `Edge Function management (Deno/Bun serverless). Server auto-bundles dependencies.
|
|
5033
|
-
Actions: list, deploy, deploy_bundle, source, delete, check`, {
|
|
5034
|
-
action: exports_external.enum(["list", "deploy", "deploy_bundle", "source", "delete", "check"]).describe("Action"),
|
|
5188
|
+
Actions: list, deploy, deploy_bundle, config, source, delete, check`, {
|
|
5189
|
+
action: exports_external.enum(["list", "deploy", "deploy_bundle", "config", "source", "delete", "check"]).describe("Action"),
|
|
5035
5190
|
ref: exports_external.string().describe("Project ref"),
|
|
5036
|
-
slug: exports_external.string().optional().describe("[deploy/deploy_bundle/source/delete/check] Function name"),
|
|
5191
|
+
slug: exports_external.string().optional().describe("[deploy/deploy_bundle/config/source/delete/check] Function name"),
|
|
5037
5192
|
code: exports_external.string().optional().describe("[deploy/check] Function source code (TypeScript)"),
|
|
5038
5193
|
path: exports_external.string().optional().describe("[deploy/check] Local file path to read code from (alternative to code)"),
|
|
5039
5194
|
files: exports_external.record(exports_external.string()).optional().describe("[deploy_bundle] File map: { 'index.ts': '...', '_shared/x.ts': '...' }"),
|
|
5040
5195
|
entrypoint: exports_external.string().optional().describe("[deploy_bundle] Entrypoint file (default: index.ts)"),
|
|
5041
|
-
minify: exports_external.boolean().optional().describe("[deploy/deploy_bundle] Minify bundle")
|
|
5196
|
+
minify: exports_external.boolean().optional().describe("[deploy/deploy_bundle] Minify bundle"),
|
|
5197
|
+
verify_jwt: exports_external.boolean().optional().describe("[deploy/deploy_bundle/config] Set JWT verification for this function"),
|
|
5198
|
+
background_routes: backgroundRoutesSchema.describe("[deploy/deploy_bundle/config] Background route paths; pass comma-separated or JSON array in CLI")
|
|
5042
5199
|
}, async (args) => {
|
|
5043
|
-
const { action, ref, slug, path: pathArg, files, entrypoint, minify } = args;
|
|
5200
|
+
const { action, ref, slug, path: pathArg, files, entrypoint, minify, verify_jwt, background_routes } = args;
|
|
5044
5201
|
let code = args.code;
|
|
5045
5202
|
const need = (f, v) => {
|
|
5046
5203
|
if (!v)
|
|
5047
5204
|
throw new Error(`'${f}' required for '${action}'`);
|
|
5048
5205
|
};
|
|
5049
5206
|
let text;
|
|
5207
|
+
const functionConfig = () => ({
|
|
5208
|
+
...typeof verify_jwt === "boolean" ? { verify_jwt } : {},
|
|
5209
|
+
...Array.isArray(background_routes) ? { background_routes } : {}
|
|
5210
|
+
});
|
|
5211
|
+
const hasFunctionConfig = () => Object.keys(functionConfig()).length > 0;
|
|
5212
|
+
const updateFunctionConfig = async () => {
|
|
5213
|
+
need("slug", slug);
|
|
5214
|
+
if (!hasFunctionConfig()) {
|
|
5215
|
+
throw new Error("'verify_jwt' or 'background_routes' required for 'config'");
|
|
5216
|
+
}
|
|
5217
|
+
const cr = await http.patch(`/v1/projects/${ref}/functions/${slug}/config`, functionConfig());
|
|
5218
|
+
return cr.ok ? `✅ Function ${slug} config updated
|
|
5219
|
+
${JSON.stringify(cr.data, null, 2)}` : `❌ Config update failed (${cr.status}): ${JSON.stringify(cr.data)}`;
|
|
5220
|
+
};
|
|
5050
5221
|
const checkSyntax = async (sourceCode) => {
|
|
5051
|
-
const
|
|
5052
|
-
const
|
|
5053
|
-
|
|
5054
|
-
const execAsync = promisify(__require("child_process").exec);
|
|
5055
|
-
const tmpFile = `${os.tmpdir()}/supacloud_edge_${Date.now()}.ts`;
|
|
5056
|
-
fs.writeFileSync(tmpFile, sourceCode);
|
|
5222
|
+
const tmpDir = mkdtempSync(join2(tmpdir(), "supacloud-edge-check-"));
|
|
5223
|
+
const tmpFile = join2(tmpDir, "index.ts");
|
|
5224
|
+
writeFileSync(tmpFile, sourceCode);
|
|
5057
5225
|
try {
|
|
5058
|
-
await
|
|
5226
|
+
await runBunBuild([tmpFile, "--external", "*"]);
|
|
5059
5227
|
return { ok: true };
|
|
5060
5228
|
} catch (e) {
|
|
5061
|
-
return { ok: false, err: e.stdout
|
|
5062
|
-
|
|
5229
|
+
return { ok: false, err: `${e.stdout || ""}
|
|
5230
|
+
${e.stderr || e.message}` };
|
|
5063
5231
|
} finally {
|
|
5064
|
-
|
|
5065
|
-
fs.unlinkSync(tmpFile);
|
|
5066
|
-
} catch (e) {}
|
|
5232
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
5067
5233
|
}
|
|
5068
5234
|
};
|
|
5069
5235
|
if (pathArg && !code) {
|
|
5070
5236
|
try {
|
|
5071
|
-
|
|
5072
|
-
const os = __require("os");
|
|
5073
|
-
const { promisify } = __require("util");
|
|
5074
|
-
const execAsync = promisify(__require("child_process").exec);
|
|
5075
|
-
const stat = fs.statSync(pathArg);
|
|
5076
|
-
let entrypoint2 = pathArg;
|
|
5077
|
-
if (stat.isDirectory()) {
|
|
5078
|
-
entrypoint2 = `${pathArg}/index.ts`;
|
|
5079
|
-
if (!fs.existsSync(entrypoint2)) {
|
|
5080
|
-
throw new Error(`Directory provided but no index.ts found at ${entrypoint2}`);
|
|
5081
|
-
}
|
|
5082
|
-
}
|
|
5083
|
-
const tmpOut = `${os.tmpdir()}/supacloud_bundled_${Date.now()}.js`;
|
|
5084
|
-
try {
|
|
5085
|
-
const { stderr } = await execAsync(`bun build ${entrypoint2} --target bun --outfile ${tmpOut}`);
|
|
5086
|
-
if (!fs.existsSync(tmpOut))
|
|
5087
|
-
throw new Error(`Bundle failed: ${stderr}`);
|
|
5088
|
-
code = fs.readFileSync(tmpOut, "utf-8");
|
|
5089
|
-
} finally {
|
|
5090
|
-
try {
|
|
5091
|
-
fs.unlinkSync(tmpOut);
|
|
5092
|
-
} catch (e) {}
|
|
5093
|
-
}
|
|
5237
|
+
code = await bundleEdgeFunctionPath(pathArg);
|
|
5094
5238
|
} catch (e) {
|
|
5095
5239
|
throw new Error(`Failed to bundle/read path ${pathArg}: ${e.message}`);
|
|
5096
5240
|
}
|
|
@@ -5119,13 +5263,26 @@ ${deployCheck.err}`;
|
|
|
5119
5263
|
break;
|
|
5120
5264
|
}
|
|
5121
5265
|
const dr = await http.post(`/v1/projects/${ref}/functions/${slug}`, { code, minify });
|
|
5122
|
-
|
|
5266
|
+
if (!dr.ok) {
|
|
5267
|
+
text = `❌ Failed (${dr.status}): ${JSON.stringify(dr.data)}`;
|
|
5268
|
+
break;
|
|
5269
|
+
}
|
|
5270
|
+
text = hasFunctionConfig() ? `✅ Function ${slug} deployed
|
|
5271
|
+
${await updateFunctionConfig()}` : `✅ Function ${slug} deployed`;
|
|
5123
5272
|
break;
|
|
5124
5273
|
case "deploy_bundle":
|
|
5125
5274
|
need("slug", slug);
|
|
5126
5275
|
need("files", files);
|
|
5127
5276
|
const br = await http.post(`/v1/projects/${ref}/functions/${slug}/bundle`, { files, entrypoint, minify });
|
|
5128
|
-
|
|
5277
|
+
if (!br.ok) {
|
|
5278
|
+
text = `❌ Failed (${br.status}): ${JSON.stringify(br.data)}`;
|
|
5279
|
+
break;
|
|
5280
|
+
}
|
|
5281
|
+
text = hasFunctionConfig() ? `✅ Function ${slug} bundle deployed (${Object.keys(files).length} files)
|
|
5282
|
+
${await updateFunctionConfig()}` : `✅ Function ${slug} bundle deployed (${Object.keys(files).length} files)`;
|
|
5283
|
+
break;
|
|
5284
|
+
case "config":
|
|
5285
|
+
text = await updateFunctionConfig();
|
|
5129
5286
|
break;
|
|
5130
5287
|
case "source":
|
|
5131
5288
|
need("slug", slug);
|
|
@@ -5230,7 +5387,8 @@ ${JSON.stringify(r.data, null, 2)}` : `❌ Failed (${r.status})`;
|
|
|
5230
5387
|
}
|
|
5231
5388
|
|
|
5232
5389
|
// src/shared/tools/frontend-tools.ts
|
|
5233
|
-
import {
|
|
5390
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
5391
|
+
import { basename as basename3 } from "node:path";
|
|
5234
5392
|
function registerFrontendTools(server, http) {
|
|
5235
5393
|
server.tool("frontend", `Frontend hosting (static sites & SSR). Supports: static, react, vue, svelte, sveltekit, nextjs, nuxt, astro.
|
|
5236
5394
|
Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy, build_logs, add_domain, remove_domain, set_env, list_frameworks, list_records`, {
|
|
@@ -5324,14 +5482,12 @@ Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy,
|
|
|
5324
5482
|
need("ref", ref);
|
|
5325
5483
|
need("id", id);
|
|
5326
5484
|
need("zip_path", zip_path);
|
|
5327
|
-
|
|
5328
|
-
if (!await file.exists()) {
|
|
5485
|
+
if (!existsSync4(zip_path)) {
|
|
5329
5486
|
throw new Error(`Zip file not found: ${zip_path}`);
|
|
5330
5487
|
}
|
|
5488
|
+
const zipBuffer = readFileSync4(zip_path);
|
|
5331
5489
|
const form = new FormData;
|
|
5332
|
-
form.append("file", new
|
|
5333
|
-
type: "application/zip"
|
|
5334
|
-
}));
|
|
5490
|
+
form.append("file", new Blob([zipBuffer], { type: "application/zip" }), basename3(zip_path));
|
|
5335
5491
|
text = ok(await http.postMultipart(`/v1/projects/${ref}/frontend/deployments/${id}/deploy/upload`, form));
|
|
5336
5492
|
break;
|
|
5337
5493
|
case "redeploy":
|
|
@@ -5462,6 +5618,15 @@ function registerUserProjectCliTools(server, http, options = {}) {
|
|
|
5462
5618
|
// src/index.ts
|
|
5463
5619
|
var projectActionSchema = exports_external.enum(["get", "health", "logs", "api_keys", "settings", "tasks"]);
|
|
5464
5620
|
var genericActionSchema = exports_external.string();
|
|
5621
|
+
function unwrapMcpSchema(schema) {
|
|
5622
|
+
if (schema && typeof schema === "object" && !Array.isArray(schema) && "args" in schema) {
|
|
5623
|
+
const argsSchema = schema.args;
|
|
5624
|
+
if (argsSchema && typeof argsSchema === "object" && !Array.isArray(argsSchema)) {
|
|
5625
|
+
return argsSchema;
|
|
5626
|
+
}
|
|
5627
|
+
}
|
|
5628
|
+
return schema;
|
|
5629
|
+
}
|
|
5465
5630
|
function captureTools(register) {
|
|
5466
5631
|
const tools = {};
|
|
5467
5632
|
const server = {
|
|
@@ -5469,7 +5634,7 @@ function captureTools(register) {
|
|
|
5469
5634
|
if (typeof schemaOrCallback === "function") {
|
|
5470
5635
|
tools[name] = { schema: {}, callback: schemaOrCallback };
|
|
5471
5636
|
} else {
|
|
5472
|
-
tools[name] = { schema: schemaOrCallback, callback };
|
|
5637
|
+
tools[name] = { schema: unwrapMcpSchema(schemaOrCallback), callback };
|
|
5473
5638
|
}
|
|
5474
5639
|
}
|
|
5475
5640
|
};
|
|
@@ -5507,6 +5672,7 @@ EXAMPLES
|
|
|
5507
5672
|
supacloud frontend list --ref abc123
|
|
5508
5673
|
supacloud database query --sql "select now()"
|
|
5509
5674
|
supacloud edge_functions deploy --ref abc123 --slug hello --path ./supabase/functions/hello
|
|
5675
|
+
supacloud edge_functions config --ref abc123 --slug hello --verify_jwt false --background_routes "/queue/*,/render/*"
|
|
5510
5676
|
|
|
5511
5677
|
SEPARATE ADMIN CLI
|
|
5512
5678
|
|
|
@@ -5615,10 +5781,11 @@ function createCliTools() {
|
|
|
5615
5781
|
assign(captureTools((server) => registerUserProjectCliTools(server, http, {
|
|
5616
5782
|
projectRef: context.projectRef || undefined
|
|
5617
5783
|
})));
|
|
5618
|
-
|
|
5784
|
+
const databaseTools = captureTools((server) => registerDatabaseTools(server, http, {
|
|
5619
5785
|
projectRef: context.projectRef || undefined,
|
|
5620
5786
|
readOnly: context.readOnly
|
|
5621
|
-
}))
|
|
5787
|
+
}));
|
|
5788
|
+
assign(databaseTools);
|
|
5622
5789
|
assign(captureTools((server) => registerAuthTools(server, http)));
|
|
5623
5790
|
assign(captureTools((server) => registerStorageTools(server, http)));
|
|
5624
5791
|
assign(captureTools((server) => registerAdvancedTools(server, http)));
|