@jsondb-cloud/cli 1.0.13 → 1.0.15

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/README.md CHANGED
@@ -5,8 +5,12 @@ The official CLI tool for [jsondb.cloud](https://jsondb.cloud) — a hosted JSON
5
5
  [![npm version](https://img.shields.io/npm/v/@jsondb-cloud/cli)](https://www.npmjs.com/package/@jsondb-cloud/cli)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/@jsondb-cloud/cli)](https://www.npmjs.com/package/@jsondb-cloud/cli)
7
7
  [![CI](https://github.com/JsonDBCloud/cli/actions/workflows/ci.yml/badge.svg)](https://github.com/JsonDBCloud/cli/actions)
8
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5-blue)](https://www.typescriptlang.org/)
9
9
  [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
10
+ [![Bundle size](https://img.shields.io/bundlephobia/min/@jsondb-cloud/cli)](https://bundlephobia.com/package/@jsondb-cloud/cli)
11
+ [![GitHub stars](https://img.shields.io/github/stars/JsonDBCloud/cli)](https://github.com/JsonDBCloud/cli)
12
+ [![Last commit](https://img.shields.io/github/last-commit/JsonDBCloud/cli)](https://github.com/JsonDBCloud/cli)
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
10
14
 
11
15
  ## Install
12
16
 
@@ -134,7 +134,8 @@ async function listCollectionsCommand(client) {
134
134
  // List documents and extract unique collection names
135
135
  const res = await client.get("?limit=100");
136
136
  if (!res.ok) {
137
- (0, output_1.error)("Failed to list collections");
137
+ const data = await res.json().catch(() => ({}));
138
+ (0, output_1.error)(data.error?.message || `Failed to list collections: ${res.status}`);
138
139
  process.exit(1);
139
140
  }
140
141
  const data = await res.json();
@@ -151,7 +152,8 @@ async function listDocumentsCommand(collection, client, options) {
151
152
  const limit = options.limit || "20";
152
153
  const res = await client.get(`${collection}?limit=${limit}`);
153
154
  if (!res.ok) {
154
- (0, output_1.error)("Failed to list documents");
155
+ const data = await res.json().catch(() => ({}));
156
+ (0, output_1.error)(data.error?.message || `Failed to list documents: ${res.status}`);
155
157
  process.exit(1);
156
158
  }
157
159
  const data = await res.json();
@@ -7,7 +7,8 @@ const output_1 = require("../lib/output");
7
7
  async function listKeysCommand(client) {
8
8
  const res = await client.rawGet("/api/keys");
9
9
  if (!res.ok) {
10
- (0, output_1.error)("Failed to list API keys");
10
+ const errData = await res.json().catch(() => ({}));
11
+ (0, output_1.error)(errData.error?.message || `Failed to list API keys: ${res.status}`);
11
12
  process.exit(1);
12
13
  }
13
14
  const data = await res.json();
@@ -28,7 +29,7 @@ async function listKeysCommand(client) {
28
29
  (0, output_1.printTable)(headers, rows);
29
30
  }
30
31
  async function createKeyCommand(client, options) {
31
- const res = await client.rawGet("/api/keys"); // POST via the dashboard API
32
+ await client.rawGet("/api/keys"); // POST via the dashboard API
32
33
  // Actually we need to post to create. Use a different approach
33
34
  const body = {
34
35
  name: options.name || "CLI-generated key",
@@ -61,7 +61,7 @@ async function pullCommand(collection, client, options) {
61
61
  if (options.out) {
62
62
  fs.writeFileSync(options.out, content, "utf-8");
63
63
  // Count documents
64
- let count = 0;
64
+ let count;
65
65
  if (format === "json") {
66
66
  try {
67
67
  count = JSON.parse(content).length;
package/dist/index.js CHANGED
@@ -19,9 +19,10 @@ program
19
19
  .description("The jsondb.cloud CLI — manage your JSON database from the terminal")
20
20
  .version("1.0.0")
21
21
  .option("--api-key <key>", "Use a specific API key")
22
- .option("--project <ns>", "Target project (default: \"default\")")
22
+ .option("--project <ns>", 'Target project (default: "default")')
23
23
  .option("--base-url <url>", "API base URL")
24
- .option("--format <fmt>", "Output format: json, raw, ndjson, table");
24
+ .option("--format <fmt>", "Output format: json, raw, ndjson, table")
25
+ .option("--verbose", "Show debug info (request URLs, status codes)");
25
26
  function getClient() {
26
27
  const opts = program.opts();
27
28
  const config = (0, config_1.loadConfig)();
@@ -30,11 +31,14 @@ function getClient() {
30
31
  (0, output_1.error)("Not authenticated", "Run `jsondb login` to authenticate, or pass --api-key");
31
32
  process.exit(1);
32
33
  }
33
- return new client_1.ApiClient({
34
+ const client = new client_1.ApiClient({
34
35
  apiKey,
35
36
  project: opts.project || config?.project || "default",
36
37
  baseUrl: opts.baseUrl || config?.baseUrl || "https://api.jsondb.cloud",
37
38
  });
39
+ if (opts.verbose)
40
+ client.verbose = true;
41
+ return client;
38
42
  }
39
43
  // ─── Auth commands ───
40
44
  program
@@ -149,14 +153,14 @@ keys
149
153
  .option("--name <name>", "Key name")
150
154
  .option("--scope <scope>", "Scope: read-only, read-write", "read-write")
151
155
  .option("--project <ns>", "Target project")
152
- .action(async (opts) => {
156
+ .action(async (_opts) => {
153
157
  (0, output_1.error)("Key creation requires dashboard authentication. Use the web dashboard at https://jsondb.cloud/dashboard/api-keys");
154
158
  process.exit(1);
155
159
  });
156
160
  keys
157
161
  .command("revoke <id>")
158
162
  .description("Revoke an API key")
159
- .action(async (id) => {
163
+ .action(async (_id) => {
160
164
  (0, output_1.error)("Key revocation requires dashboard authentication. Use the web dashboard at https://jsondb.cloud/dashboard/api-keys");
161
165
  process.exit(1);
162
166
  });
@@ -1,9 +1,12 @@
1
1
  import type { CliConfig } from "./config";
2
2
  export declare class ApiClient {
3
3
  private config;
4
+ verbose: boolean;
4
5
  constructor(config: CliConfig);
6
+ private log;
5
7
  private url;
6
8
  private headers;
9
+ private request;
7
10
  get(path: string, accept?: string): Promise<Response>;
8
11
  post(path: string, body?: unknown, extraHeaders?: Record<string, string>): Promise<Response>;
9
12
  postRaw(path: string, body: string, contentType: string): Promise<Response>;
@@ -3,9 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ApiClient = void 0;
4
4
  class ApiClient {
5
5
  config;
6
+ verbose = false;
6
7
  constructor(config) {
7
8
  this.config = config;
8
9
  }
10
+ log(msg) {
11
+ if (this.verbose) {
12
+ console.error(`\x1b[2m[debug] ${msg}\x1b[0m`);
13
+ }
14
+ }
9
15
  url(path) {
10
16
  const base = this.config.baseUrl.replace(/\/$/, "");
11
17
  return `${base}/${this.config.project}/${path}`;
@@ -17,54 +23,38 @@ class ApiClient {
17
23
  ...extra,
18
24
  };
19
25
  }
26
+ async request(method, url, headers, body) {
27
+ this.log(`${method} ${url}`);
28
+ const res = await fetch(url, { method, headers, body });
29
+ this.log(`${res.status} ${res.statusText}`);
30
+ return res;
31
+ }
20
32
  async get(path, accept) {
21
33
  const headers = this.headers(accept ? { Accept: accept } : undefined);
22
- return fetch(this.url(path), { method: "GET", headers });
34
+ return this.request("GET", this.url(path), headers);
23
35
  }
24
36
  async post(path, body, extraHeaders) {
25
- return fetch(this.url(path), {
26
- method: "POST",
27
- headers: this.headers(extraHeaders),
28
- body: body !== undefined ? JSON.stringify(body) : undefined,
29
- });
37
+ return this.request("POST", this.url(path), this.headers(extraHeaders), body !== undefined ? JSON.stringify(body) : undefined);
30
38
  }
31
39
  async postRaw(path, body, contentType) {
32
- return fetch(this.url(path), {
33
- method: "POST",
34
- headers: {
35
- Authorization: `Bearer ${this.config.apiKey}`,
36
- "Content-Type": contentType,
37
- },
38
- body,
39
- });
40
+ return this.request("POST", this.url(path), {
41
+ Authorization: `Bearer ${this.config.apiKey}`,
42
+ "Content-Type": contentType,
43
+ }, body);
40
44
  }
41
45
  async put(path, body) {
42
- return fetch(this.url(path), {
43
- method: "PUT",
44
- headers: this.headers(),
45
- body: JSON.stringify(body),
46
- });
46
+ return this.request("PUT", this.url(path), this.headers(), JSON.stringify(body));
47
47
  }
48
48
  async patch(path, body, contentType) {
49
- return fetch(this.url(path), {
50
- method: "PATCH",
51
- headers: this.headers(contentType ? { "Content-Type": contentType } : undefined),
52
- body: JSON.stringify(body),
53
- });
49
+ return this.request("PATCH", this.url(path), this.headers(contentType ? { "Content-Type": contentType } : undefined), JSON.stringify(body));
54
50
  }
55
51
  async delete(path) {
56
- return fetch(this.url(path), {
57
- method: "DELETE",
58
- headers: this.headers(),
59
- });
52
+ return this.request("DELETE", this.url(path), this.headers());
60
53
  }
61
54
  /** Raw API call without project prefix */
62
55
  async rawGet(fullPath) {
63
56
  const base = this.config.baseUrl.replace(/\/$/, "");
64
- return fetch(`${base}${fullPath}`, {
65
- method: "GET",
66
- headers: this.headers(),
67
- });
57
+ return this.request("GET", `${base}${fullPath}`, this.headers());
68
58
  }
69
59
  }
70
60
  exports.ApiClient = ApiClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsondb-cloud/cli",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "description": "CLI tool for jsondb.cloud — push, pull, manage your JSON database from the terminal",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -15,14 +15,24 @@
15
15
  "scripts": {
16
16
  "build": "tsc",
17
17
  "dev": "tsc --watch",
18
- "typecheck": "tsc --noEmit"
18
+ "typecheck": "tsc --noEmit",
19
+ "lint": "eslint src/",
20
+ "lint:fix": "eslint src/ --fix",
21
+ "format": "prettier --write 'src/**/*.ts'",
22
+ "format:check": "prettier --check 'src/**/*.ts'",
23
+ "test": "vitest run"
19
24
  },
20
25
  "dependencies": {
21
26
  "commander": "^13.0.0"
22
27
  },
23
28
  "devDependencies": {
29
+ "@eslint/js": "^10.0.1",
30
+ "@types/node": "^20.0.0",
31
+ "eslint": "^10.0.2",
32
+ "prettier": "^3.8.1",
24
33
  "typescript": "^5.4.0",
25
- "@types/node": "^20.0.0"
34
+ "typescript-eslint": "^8.56.1",
35
+ "vitest": "^4.0.18"
26
36
  },
27
37
  "keywords": [
28
38
  "jsondb",