run402 1.20.0 → 1.20.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.
Files changed (2) hide show
  1. package/lib/projects.mjs +13 -2
  2. package/package.json +1 -1
package/lib/projects.mjs CHANGED
@@ -13,7 +13,7 @@ Subcommands:
13
13
  list List all your projects (IDs, URLs, active marker)
14
14
  info <id> Show project details: REST URL, keys
15
15
  keys <id> Print anon_key and service_key as JSON
16
- sql <id> "<query>" [--file <path>] Run a SQL query against a project's Postgres DB
16
+ sql <id> "<query>" [--file <path>] [--params '<json>'] Run a SQL query (supports parameterized queries)
17
17
  rest <id> <table> [params] Query a table via the REST API (PostgREST)
18
18
  usage <id> Show compute/storage usage for a project
19
19
  schema <id> Inspect the database schema
@@ -29,6 +29,7 @@ Examples:
29
29
  run402 projects list
30
30
  run402 projects info abc123
31
31
  run402 projects sql abc123 "SELECT * FROM users LIMIT 5"
32
+ run402 projects sql abc123 "SELECT * FROM users WHERE id = $1" --params '[42]'
32
33
  run402 projects sql abc123 --file setup.sql
33
34
  run402 projects rest abc123 users "limit=10&select=id,name"
34
35
  run402 projects usage abc123
@@ -121,13 +122,23 @@ async function sqlCmd(projectId, args = []) {
121
122
  const p = findProject(projectId);
122
123
  let file = null;
123
124
  let query = null;
125
+ let paramsRaw = null;
124
126
  for (let i = 0; i < args.length; i++) {
125
127
  if (args[i] === "--file" && args[i + 1]) { file = args[++i]; }
128
+ else if (args[i] === "--params" && args[i + 1]) { paramsRaw = args[++i]; }
126
129
  else if (!query && !args[i].startsWith("--")) { query = args[i]; }
127
130
  }
128
131
  const sql = file ? readFileSync(file, "utf-8") : query;
129
132
  if (!sql) { console.error(JSON.stringify({ status: "error", message: "Missing SQL query. Provide inline or use --file <path>" })); process.exit(1); }
130
- const res = await fetch(`${API}/projects/v1/admin/${projectId}/sql`, { method: "POST", headers: { "Authorization": `Bearer ${p.service_key}`, "Content-Type": "text/plain" }, body: sql });
133
+ let params;
134
+ if (paramsRaw) {
135
+ try { params = JSON.parse(paramsRaw); } catch { console.error(JSON.stringify({ status: "error", message: "Invalid JSON for --params. Expected a JSON array, e.g. '[42, \"hello\"]'" })); process.exit(1); }
136
+ if (!Array.isArray(params)) { console.error(JSON.stringify({ status: "error", message: "--params must be a JSON array, e.g. '[42, \"hello\"]'" })); process.exit(1); }
137
+ }
138
+ const useParams = params && params.length > 0;
139
+ const headers = { "Authorization": `Bearer ${p.service_key}`, "Content-Type": useParams ? "application/json" : "text/plain" };
140
+ const body = useParams ? JSON.stringify({ sql, params }) : sql;
141
+ const res = await fetch(`${API}/projects/v1/admin/${projectId}/sql`, { method: "POST", headers, body });
131
142
  console.log(JSON.stringify(await res.json(), null, 2));
132
143
  }
133
144
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "run402",
3
- "version": "1.20.0",
3
+ "version": "1.20.1",
4
4
  "description": "CLI for Run402 — provision Postgres databases, deploy static sites, generate images, and manage wallets via x402 and MPP micropayments.",
5
5
  "type": "module",
6
6
  "bin": {