@batadata/cli 0.2.1 → 0.2.3

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.
@@ -5,7 +5,7 @@
5
5
  * and execs psql with the connection string.
6
6
  */
7
7
  import { execSync, spawn } from "node:child_process";
8
- import { api } from "../api.js";
8
+ import { api, asList } from "../api.js";
9
9
  import { requireToken, loadConfig, isJsonMode } from "../config.js";
10
10
  import { colors, log, error, spinner, info as logInfo } from "../utils/logger.js";
11
11
  import { emitError } from "../utils/errors.js";
@@ -35,7 +35,7 @@ export async function connect(args) {
35
35
  : projRes.status >= 500 || projRes.status === 0 ? "API_UNAVAILABLE"
36
36
  : "CLI_ERROR", "Failed to fetch projects.", "");
37
37
  }
38
- const projects = Array.isArray(projRes.data) ? projRes.data : [];
38
+ const projects = asList(projRes.data);
39
39
  const found = projects.find((p) => p.name === projectName || p.id === projectName);
40
40
  if (!found) {
41
41
  emitError("NOT_FOUND", `Project "${projectName}" not found.`, "");
@@ -79,7 +79,13 @@ export async function connect(args) {
79
79
  process.exit(1);
80
80
  }
81
81
  log();
82
- logInfo(`Connecting to ${colors.cyan(connRes.data.project_name)}`);
82
+ logInfo(`Connecting to ${colors.cyan(connRes.data.project_name)} ${colors.dim(`(${connRes.data.project_id})`)}`);
83
+ if (!projectName || projectName.startsWith("-")) {
84
+ // No explicit project argument — this resolved through the link/config
85
+ // default. Say so loudly: a silently-resolved default once pointed a
86
+ // benchmark harness at an entirely different project.
87
+ log(` ${colors.yellow("!")} resolved from the linked/default project, not an explicit argument`);
88
+ }
83
89
  log(` ${colors.dim(connectionUri)}`);
84
90
  log();
85
91
  // Check if psql is available
@@ -27,6 +27,9 @@ async function getConnectionInfo(projectId, token) {
27
27
  database: c.params?.database,
28
28
  user: c.params?.user,
29
29
  password: c.params?.password,
30
+ project_id: res.data?.project_id,
31
+ project_name: res.data?.project_name,
32
+ branch_name: c.branch_name,
30
33
  };
31
34
  }
32
35
  function formatDate(iso) {
@@ -186,10 +189,24 @@ export async function url() {
186
189
  emitError("NOT_FOUND", "Could not fetch connection string.", "");
187
190
  }
188
191
  if (isJsonMode()) {
189
- json({ direct: conn.connection_uri, pooled: conn.pooled_uri ?? null });
192
+ json({
193
+ direct: conn.connection_uri,
194
+ pooled: conn.pooled_uri ?? null,
195
+ // Identity of what was resolved (link > config default when no explicit
196
+ // project) — so a script can ASSERT it got the project it meant. A
197
+ // silently-resolved default once handed a benchmark harness another
198
+ // project's URI; the URI alone gives no way to notice.
199
+ project_id: conn.project_id ?? projectId,
200
+ project_name: conn.project_name ?? null,
201
+ branch_name: conn.branch_name ?? null,
202
+ });
190
203
  return;
191
204
  }
192
- // Print raw URL for piping
205
+ // Raw URL on stdout for piping; resolved identity on STDERR so pipes stay
206
+ // clean but a human (or a captured log) always sees WHICH project answered.
207
+ process.stderr.write(`# project: ${conn.project_name ?? "?"} (${conn.project_id ?? projectId})` +
208
+ (conn.branch_name ? ` · branch: ${conn.branch_name}` : "") +
209
+ "\n");
193
210
  process.stdout.write(conn.connection_uri + "\n");
194
211
  }
195
212
  export async function branches() {
@@ -4,7 +4,7 @@
4
4
  * Lists projects with branch count, compute status, and storage size.
5
5
  * Colorized output: green for running, yellow for suspended, red for error.
6
6
  */
7
- import { api, apiError, resolveTeamId } from "../api.js";
7
+ import { api, apiError, resolveTeamId, asList } from "../api.js";
8
8
  import { requireToken, loadConfig, isJsonMode } from "../config.js";
9
9
  import { colors, log, json, spinner, table, heading } from "../utils/logger.js";
10
10
  import { emitError } from "../utils/errors.js";
@@ -55,7 +55,10 @@ export async function status() {
55
55
  : "CLI_ERROR", apiError(res, "Failed to fetch projects"), "");
56
56
  }
57
57
  s?.stop();
58
- const projects = Array.isArray(res.data) ? res.data : [];
58
+ // The list endpoint returns `{ data: [...] }` — a bare Array.isArray(res.data)
59
+ // silently read that envelope as "no projects" while the team had plenty
60
+ // (real regression seen live). asList normalizes every envelope shape.
61
+ const projects = asList(res.data);
59
62
  const defaultProj = validDefaultProject(projects, config.defaultProject);
60
63
  if (jsonMode) {
61
64
  json({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@batadata/cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "CLI for BataDB — serverless Postgres platform",
5
5
  "bin": {
6
6
  "bata": "./dist/index.js"