@supacloud/cli 0.7.0 → 0.9.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 +49 -11
  2. package/package.json +2 -3
package/dist/index.js CHANGED
@@ -14,9 +14,6 @@ var __export = (target, all) => {
14
14
  });
15
15
  };
16
16
 
17
- // src/index.ts
18
- import path from "node:path";
19
-
20
17
  // node_modules/zod/v4/classic/external.js
21
18
  var exports_external = {};
22
19
  __export(exports_external, {
@@ -14780,7 +14777,9 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
14780
14777
  user_id: exports_external.string().optional().describe("[get_auth_user] User UUID"),
14781
14778
  limit: exports_external.number().optional().describe("[list_auth_users] Max users (default: 20)"),
14782
14779
  name: exports_external.string().optional().describe("[apply_migration] Migration name"),
14783
- columns: exports_external.string().optional().describe("[create_table_rls] Column definitions")
14780
+ columns: exports_external.string().optional().describe("[create_table_rls] Column definitions"),
14781
+ policy_mode: exports_external.enum(["deny_all", "owner"]).optional().describe("[create_table_rls] RLS policy mode (default: deny_all)"),
14782
+ owner_column: exports_external.string().optional().describe("[create_table_rls owner] UUID owner column matched to auth.uid()")
14784
14783
  }, async (args) => {
14785
14784
  const { action } = args;
14786
14785
  const ref = projectRef || args.ref;
@@ -15056,9 +15055,15 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
15056
15055
  case "create_table_rls": {
15057
15056
  if (!args.table || !args.columns)
15058
15057
  throw new Error("'table' and 'columns' required");
15059
- const sql = `BEGIN; CREATE TABLE IF NOT EXISTS "${schema}"."${args.table}" (${args.columns}); ALTER TABLE "${schema}"."${args.table}" ENABLE ROW LEVEL SECURITY; CREATE POLICY "Enable ALL for authenticated" ON "${schema}"."${args.table}" FOR ALL TO authenticated USING (true) WITH CHECK (true); COMMIT;`;
15058
+ const qualifiedTable = `${quoteIdentifier(schema, "schema")}.${quoteIdentifier(args.table, "table")}`;
15059
+ const columns = validateColumnDefinitions(args.columns);
15060
+ const policyMode = args.policy_mode || "deny_all";
15061
+ if (policyMode !== "deny_all" && policyMode !== "owner")
15062
+ throw new Error("Invalid RLS policy mode");
15063
+ const policySql = buildRlsPolicySql(qualifiedTable, policyMode, args.owner_column);
15064
+ const sql = `BEGIN; CREATE TABLE IF NOT EXISTS ${qualifiedTable} (${columns}); ALTER TABLE ${qualifiedTable} ENABLE ROW LEVEL SECURITY; ${policySql} COMMIT;`;
15060
15065
  const r = await execSql(sql);
15061
- text = r.ok ? `✅ Table '${schema}.${args.table}' created with RLS` : `❌ Failed (${r.status}): ${JSON.stringify(r.data)}`;
15066
+ text = r.ok ? `✅ Table '${schema}.${args.table}' created with RLS (${policyMode === "owner" ? "auth.uid() owner policy" : "deny-all by default"})` : `❌ Failed (${r.status}): ${JSON.stringify(r.data)}`;
15062
15067
  break;
15063
15068
  }
15064
15069
  default:
@@ -15067,6 +15072,42 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
15067
15072
  return { content: [{ type: "text", text }] };
15068
15073
  });
15069
15074
  }
15075
+ function quoteIdentifier(value, label) {
15076
+ if (typeof value !== "string" || !/^[A-Za-z_][A-Za-z0-9_]{0,62}$/.test(value)) {
15077
+ throw new Error(`Invalid ${label} identifier`);
15078
+ }
15079
+ return `"${value}"`;
15080
+ }
15081
+ function validateColumnDefinitions(value) {
15082
+ if (typeof value !== "string")
15083
+ throw new Error("Invalid column definitions");
15084
+ const columns = value.trim();
15085
+ if (!columns || columns.length > 16384)
15086
+ throw new Error("Invalid column definitions");
15087
+ if (/[;\0]/.test(columns) || /--|\/\*|\*\//.test(columns) || /\b(?:ALTER|CREATE|DROP|GRANT|REVOKE|TRUNCATE|COPY|CALL|DO)\b/i.test(columns)) {
15088
+ throw new Error("Unsafe column definitions");
15089
+ }
15090
+ return columns;
15091
+ }
15092
+ function buildRlsPolicySql(qualifiedTable, policyMode, ownerColumnValue) {
15093
+ const policyNames = [
15094
+ "Enable ALL for authenticated",
15095
+ "SupaCloud owner select",
15096
+ "SupaCloud owner insert",
15097
+ "SupaCloud owner update",
15098
+ "SupaCloud owner delete"
15099
+ ];
15100
+ const dropPolicies = policyNames.map((name) => `DROP POLICY IF EXISTS "${name}" ON ${qualifiedTable};`).join(" ");
15101
+ if (policyMode === "deny_all")
15102
+ return dropPolicies;
15103
+ const ownerColumn = quoteIdentifier(ownerColumnValue, "owner column");
15104
+ const predicate = `auth.uid() IS NOT NULL AND auth.uid() = ${ownerColumn}`;
15105
+ return `${dropPolicies}
15106
+ CREATE POLICY "SupaCloud owner select" ON ${qualifiedTable} FOR SELECT TO authenticated USING (${predicate});
15107
+ CREATE POLICY "SupaCloud owner insert" ON ${qualifiedTable} FOR INSERT TO authenticated WITH CHECK (${predicate});
15108
+ CREATE POLICY "SupaCloud owner update" ON ${qualifiedTable} FOR UPDATE TO authenticated USING (${predicate}) WITH CHECK (${predicate});
15109
+ CREATE POLICY "SupaCloud owner delete" ON ${qualifiedTable} FOR DELETE TO authenticated USING (${predicate});`;
15110
+ }
15070
15111
  function sqlString(value) {
15071
15112
  return `'${value.replace(/'/g, "''")}'`;
15072
15113
  }
@@ -16908,9 +16949,8 @@ Actions: routes, upsert_route, update_route, delete_route, config, get_certifica
16908
16949
  }
16909
16950
 
16910
16951
  // src/index.ts
16911
- var invokedCommand = path.basename(process.argv[1] || "supacloud-cli");
16912
- var commandName = invokedCommand === "supacloud" ? "supacloud" : "supacloud-cli";
16913
- var preferredCommand = "supacloud-cli";
16952
+ var commandName = "supacloud-cli";
16953
+ var preferredCommand = commandName;
16914
16954
  var projectActionSchema = exports_external.enum([
16915
16955
  "get",
16916
16956
  "health",
@@ -16957,8 +16997,6 @@ function printHelp(context = resolveSupaCloudContext()) {
16957
16997
  ║ Project CLI for SupaCloud users ║
16958
16998
  ╚═══════════════════════════════════════════════════════════╝
16959
16999
 
16960
- ${commandName === "supacloud" ? "NOTE\n\n `supacloud` is kept as a compatibility alias. Prefer `supacloud-cli`\n to avoid confusion with the server binary at /usr/local/bin/supacloud.\n" : ""}
16961
-
16962
17000
  USAGE
16963
17001
 
16964
17002
  ${preferredCommand} <module> <action> [--flags]
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "@supacloud/cli",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "Project-scoped CLI for SupaCloud users",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "bin": {
8
- "supacloud-cli": "dist/index.js",
9
- "supacloud": "dist/index.js"
8
+ "supacloud-cli": "dist/index.js"
10
9
  },
11
10
  "files": [
12
11
  "dist",