@supacloud/cli 0.34.2 → 0.35.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 (2) hide show
  1. package/dist/index.js +94 -8
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6463,7 +6463,7 @@ var ACTION_POLICY = {
6463
6463
  local: ["list"]
6464
6464
  },
6465
6465
  database: {
6466
- read: ["list_tables", "describe_columns", "list_indexes", "list_constraints", "list_extensions", "rls_status", "rls_policies", "list_auth_users", "get_auth_user", "connections", "stats", "slow_queries", "list_migrations", "migration_inventory", "project_url", "generate_types"],
6466
+ read: ["list_tables", "describe_columns", "list_indexes", "list_constraints", "list_extensions", "rls_status", "rls_policies", "list_auth_users", "get_auth_user", "connections", "stats", "slow_queries", "list_migrations", "migration_inventory", "project_url", "generate_types", "database_lint", "db_lint", "rpc_catalog", "list_rpcs"],
6467
6467
  local: ["lint_migrations", "lint"],
6468
6468
  write: ["query", "apply_migration", "push_migrations", "baseline_migrations", "create_table_rls"]
6469
6469
  },
@@ -8090,7 +8090,11 @@ function registerDatabaseTools(server, http, config = {}) {
8090
8090
  "list_migrations",
8091
8091
  "migration_inventory",
8092
8092
  "project_url",
8093
- "generate_types"
8093
+ "generate_types",
8094
+ "database_lint",
8095
+ "db_lint",
8096
+ "rpc_catalog",
8097
+ "list_rpcs"
8094
8098
  ];
8095
8099
  const writeActions = ["apply_migration", "push_migrations", "baseline_migrations", "create_table_rls"];
8096
8100
  const remoteActions = [...readActions, ...localActions];
@@ -8103,13 +8107,13 @@ Actions: ${allActions.join(", ")}${localOnly ? " (local-only mode)" : readOnly ?
8103
8107
  file: optional(Type.String(), "[query/apply_migration/lint_migrations/lint] Read SQL from local file path (avoids shell escaping issues with $$ and multi-statement DDL)"),
8104
8108
  dir: optional(Type.String(), "[push_migrations/baseline_migrations/lint_migrations/lint] Directory containing .sql migration files (default: supabase/migrations)"),
8105
8109
  dry_run: optional(Type.Boolean(), "[push_migrations/baseline_migrations] Preview changes without applying them"),
8106
- strict: optional(Type.Boolean(), "[push_migrations/lint_migrations/lint] Exit with error if high-risk destructive migrations are detected"),
8107
- fail_on_high: optional(Type.Boolean(), "[push_migrations/lint_migrations/lint] Alias for --strict"),
8110
+ strict: optional(Type.Boolean(), "[push_migrations/lint_migrations/lint/database_lint] Exit with error if high-risk issues or migrations are detected"),
8111
+ fail_on_high: optional(Type.Boolean(), "[push_migrations/lint_migrations/lint/database_lint] Alias for --strict"),
8108
8112
  fail_on_medium: optional(Type.Boolean(), "[push_migrations/lint_migrations/lint] Exit with error if medium-risk or high-risk migrations are detected"),
8109
- json: optional(Type.Boolean(), "[lint_migrations/lint] Output structured JSON analysis"),
8110
- schema: optional(Type.String(), "[describe_columns/list_indexes/list_constraints/rls_status/rls_policies/create_table_rls] Schema name (default: public)"),
8113
+ json: optional(Type.Boolean(), "[lint_migrations/lint/database_lint/rpc_catalog] Output structured JSON analysis"),
8114
+ schema: optional(Type.String(), "[describe_columns/list_indexes/list_constraints/rls_status/rls_policies/create_table_rls/database_lint] Schema name (default: public)"),
8111
8115
  table: optional(Type.String(), "[describe_columns/indexes/constraints/rls_*] Table name"),
8112
- schemas: optional(Type.Array(Type.String()), "[list_tables/generate_types] Schemas array"),
8116
+ schemas: optional(Type.Array(Type.String()), "[list_tables/generate_types/rpc_catalog] Schemas array"),
8113
8117
  user_id: optional(Type.String(), "[get_auth_user] User UUID"),
8114
8118
  limit: optional(Type.Number(), "[list_auth_users] Max users (default: 20)"),
8115
8119
  name: optional(Type.String(), "[apply_migration] Migration name"),
@@ -8510,6 +8514,41 @@ ${riskReport}`
8510
8514
  text = `✅ Table '${schema}.${args.table}' created with RLS (${policyMode === "owner" ? "auth.uid() owner policy" : "deny-all by default"})`;
8511
8515
  break;
8512
8516
  }
8517
+ case "database_lint":
8518
+ case "db_lint": {
8519
+ const targetSchema = args.schema || "public";
8520
+ const safeRef = projectRefPathSegment(ref, "database_lint");
8521
+ const r = await managementHttp().get(`/v1/projects/${safeRef}/database/linter?schema=${encodeURIComponent(targetSchema)}`);
8522
+ if (!r.ok) {
8523
+ return { content: [{ type: "text", text: `❌ Database lint request failed (${r.status})` }], isError: true };
8524
+ }
8525
+ if (args.json) {
8526
+ text = JSON.stringify(r.data, null, 2);
8527
+ } else {
8528
+ text = formatDatabaseLintReport(r.data);
8529
+ }
8530
+ const strict = args.strict === true || args.fail_on_high === true;
8531
+ const dangerCount = r.data?.danger_count || 0;
8532
+ if (strict && dangerCount > 0) {
8533
+ return { content: [{ type: "text", text }], isError: true };
8534
+ }
8535
+ break;
8536
+ }
8537
+ case "rpc_catalog":
8538
+ case "list_rpcs": {
8539
+ const schemasList = args.schemas && args.schemas.length > 0 ? args.schemas : args.schema ? [args.schema] : ["public", "api"];
8540
+ const safeRef = projectRefPathSegment(ref, "rpc_catalog");
8541
+ const r = await managementHttp().get(`/v1/projects/${safeRef}/database/rpc-catalog?schemas=${encodeURIComponent(schemasList.join(","))}`);
8542
+ if (!r.ok) {
8543
+ return { content: [{ type: "text", text: `❌ RPC catalog request failed (${r.status})` }], isError: true };
8544
+ }
8545
+ if (args.json) {
8546
+ text = JSON.stringify(r.data, null, 2);
8547
+ } else {
8548
+ text = formatRpcCatalog(r.data);
8549
+ }
8550
+ break;
8551
+ }
8513
8552
  default:
8514
8553
  text = `❌ Unknown action: ${action}`;
8515
8554
  }
@@ -8552,6 +8591,53 @@ function buildRlsPolicySql(qualifiedTable, policyMode, ownerColumnValue) {
8552
8591
  CREATE POLICY "SupaCloud owner update" ON ${qualifiedTable} FOR UPDATE TO authenticated USING (${predicate}) WITH CHECK (${predicate});
8553
8592
  CREATE POLICY "SupaCloud owner delete" ON ${qualifiedTable} FOR DELETE TO authenticated USING (${predicate});`;
8554
8593
  }
8594
+ function formatDatabaseLintReport(data) {
8595
+ if (!data || typeof data !== "object")
8596
+ return JSON.stringify(data, null, 2);
8597
+ const d = data;
8598
+ if (!d.issues || d.issues.length === 0) {
8599
+ return "✅ Database Lint: No issues found! Schema follows best practices for RLS, primary keys, and function security.";
8600
+ }
8601
+ const lines = [];
8602
+ const icon = (d.danger_count || 0) > 0 ? "\uD83D\uDD34" : (d.warning_count || 0) > 0 ? "\uD83D\uDFE1" : "ℹ️";
8603
+ lines.push(`${icon} Database Lint (${d.schema || "public"}): ${d.total_issues} issue(s) detected [${d.danger_count || 0} Danger, ${d.warning_count || 0} Warning, ${d.info_count || 0} Info]`);
8604
+ lines.push("");
8605
+ for (const issue of d.issues) {
8606
+ const itemIcon = issue.severity === "danger" ? "\uD83D\uDD34" : issue.severity === "warning" ? "\uD83D\uDFE1" : "ℹ️";
8607
+ lines.push(` ${itemIcon} [${issue.severity.toUpperCase()}] ${issue.schema_name}.${issue.object_name} (${issue.type})`);
8608
+ lines.push(` Detail: ${issue.detail}`);
8609
+ lines.push(` Recommendation: ${issue.recommendation}`);
8610
+ if (issue.fix_sql) {
8611
+ lines.push(` Fix SQL: ${issue.fix_sql}`);
8612
+ }
8613
+ lines.push("");
8614
+ }
8615
+ return lines.join(`
8616
+ `).trimEnd();
8617
+ }
8618
+ function formatRpcCatalog(data) {
8619
+ if (!data || typeof data !== "object")
8620
+ return JSON.stringify(data, null, 2);
8621
+ const d = data;
8622
+ if (!d.rpcs || d.rpcs.length === 0) {
8623
+ return `No RPC functions found in schema(s): ${(d.schemas || []).join(", ")}`;
8624
+ }
8625
+ const lines = [];
8626
+ lines.push(`\uD83D\uDCCB RPC Catalog (${d.total_rpcs || d.rpcs.length} total: ${d.commands || 0} commands, ${d.queries || 0} queries, ${d.internal || 0} internal)`);
8627
+ lines.push("");
8628
+ for (const rpc of d.rpcs) {
8629
+ const kindBadge = rpc.inferred_kind === "command" ? "⚡ [COMMAND]" : rpc.inferred_kind === "query" ? "\uD83D\uDD0D [QUERY]" : "\uD83D\uDD12 [INTERNAL]";
8630
+ const secBadge = rpc.security === "DEFINER" ? "\uD83D\uDEE1️ DEFINER" : "\uD83D\uDC64 INVOKER";
8631
+ lines.push(` ${kindBadge} ${rpc.schema_name}.${rpc.function_name}(${rpc.identity_args}) -> ${rpc.return_type}`);
8632
+ lines.push(` Security: ${secBadge} | Volatility: ${rpc.volatility}${rpc.search_path ? ` | search_path: ${rpc.search_path}` : ""}`);
8633
+ const tagEntries = Object.entries(rpc.smart_tags || {});
8634
+ if (tagEntries.length > 0) {
8635
+ lines.push(` Tags: ${tagEntries.map(([k, v]) => `@${k}${v === true ? "" : ` ${v}`}`).join(", ")}`);
8636
+ }
8637
+ }
8638
+ return lines.join(`
8639
+ `);
8640
+ }
8555
8641
  function formatSqlResult(data) {
8556
8642
  if (!data || typeof data !== "object")
8557
8643
  return JSON.stringify(data, null, 2);
@@ -14869,7 +14955,7 @@ function registerReleaseTools(server, http, options = {}) {
14869
14955
  // package.json
14870
14956
  var package_default = {
14871
14957
  name: "@supacloud/cli",
14872
- version: "0.34.2",
14958
+ version: "0.35.0",
14873
14959
  description: "Project-scoped CLI for SupaCloud users",
14874
14960
  type: "module",
14875
14961
  main: "./dist/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supacloud/cli",
3
- "version": "0.34.2",
3
+ "version": "0.35.0",
4
4
  "description": "Project-scoped CLI for SupaCloud users",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",