dblx 0.1.46 → 0.1.47

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 +577 -42
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2079,9 +2079,13 @@ import {
2079
2079
  unlinkSync,
2080
2080
  existsSync
2081
2081
  } from "fs";
2082
- var CONFIG_DIR = join(homedir(), ".config");
2083
- var CONFIG_PATH = join(CONFIG_DIR, "dblx.json");
2084
2082
  var DEFAULT_API_URL = "https://app.dblebox.com";
2083
+ var DEFAULT_CONFIG_DIR = join(homedir(), ".config");
2084
+ var DEFAULT_CONFIG_PATH = join(DEFAULT_CONFIG_DIR, "dblx.json");
2085
+ var configPath = DEFAULT_CONFIG_PATH;
2086
+ function getConfigPath() {
2087
+ return configPath;
2088
+ }
2085
2089
  function loadConfig() {
2086
2090
  const envKey = process.env.DBLEBOX_API_KEY;
2087
2091
  if (envKey) {
@@ -2090,50 +2094,358 @@ function loadConfig() {
2090
2094
  api_url: process.env.DBLEBOX_API_URL || DEFAULT_API_URL
2091
2095
  };
2092
2096
  }
2093
- if (!existsSync(CONFIG_PATH)) {
2097
+ if (!existsSync(configPath)) {
2094
2098
  return null;
2095
2099
  }
2096
2100
  try {
2097
- const raw = readFileSync(CONFIG_PATH, "utf-8");
2101
+ const raw = readFileSync(configPath, "utf-8");
2098
2102
  return JSON.parse(raw);
2099
2103
  } catch {
2100
2104
  return null;
2101
2105
  }
2102
2106
  }
2103
2107
  function saveConfig(config) {
2104
- mkdirSync(CONFIG_DIR, { recursive: true });
2105
- writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + `
2108
+ const dir = join(configPath, "..");
2109
+ mkdirSync(dir, { recursive: true });
2110
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + `
2106
2111
  `, "utf-8");
2107
2112
  }
2108
2113
  function deleteConfig() {
2109
- if (existsSync(CONFIG_PATH)) {
2110
- unlinkSync(CONFIG_PATH);
2114
+ if (existsSync(configPath)) {
2115
+ unlinkSync(configPath);
2111
2116
  }
2112
2117
  }
2113
- function getConfigPath() {
2114
- return CONFIG_PATH;
2118
+
2119
+ // ../node_modules/@elysiajs/eden/dist/chunk-QSLHAOSM.mjs
2120
+ var s = class extends Error {
2121
+ constructor(e, n) {
2122
+ super(n + "");
2123
+ this.status = e;
2124
+ this.value = n;
2125
+ }
2126
+ };
2127
+ var i = /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/;
2128
+ var o = /(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{2}\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT(?:\+|-)\d{4}\s\([^)]+\)/;
2129
+ var c = /^(?:(?:(?:(?:0?[1-9]|[12][0-9]|3[01])[/\s-](?:0?[1-9]|1[0-2])[/\s-](?:19|20)\d{2})|(?:(?:19|20)\d{2}[/\s-](?:0?[1-9]|1[0-2])[/\s-](?:0?[1-9]|[12][0-9]|3[01]))))(?:\s(?:1[012]|0?[1-9]):[0-5][0-9](?::[0-5][0-9])?(?:\s[AP]M)?)?$/;
2130
+ var u = (t) => t.trim().length !== 0 && !Number.isNaN(Number(t));
2131
+ var d = (t) => {
2132
+ if (typeof t != "string")
2133
+ return null;
2134
+ let r = t.replace(/"/g, "");
2135
+ if (i.test(r) || o.test(r) || c.test(r)) {
2136
+ let e = new Date(r);
2137
+ if (!Number.isNaN(e.getTime()))
2138
+ return e;
2139
+ }
2140
+ return null;
2141
+ };
2142
+ var a = (t) => {
2143
+ let r = t.charCodeAt(0), e = t.charCodeAt(t.length - 1);
2144
+ return r === 123 && e === 125 || r === 91 && e === 93;
2145
+ };
2146
+ var p = (t) => JSON.parse(t, (r, e) => {
2147
+ let n = d(e);
2148
+ return n || e;
2149
+ });
2150
+ var g = (t) => {
2151
+ if (!t)
2152
+ return t;
2153
+ if (u(t))
2154
+ return +t;
2155
+ if (t === "true")
2156
+ return true;
2157
+ if (t === "false")
2158
+ return false;
2159
+ let r = d(t);
2160
+ if (r)
2161
+ return r;
2162
+ if (a(t))
2163
+ try {
2164
+ return p(t);
2165
+ } catch {}
2166
+ return t;
2167
+ };
2168
+ var S = (t) => {
2169
+ let r = t.data.toString();
2170
+ return r === "null" ? null : g(r);
2171
+ };
2172
+
2173
+ // ../node_modules/@elysiajs/eden/dist/chunk-LJDYVDXQ.mjs
2174
+ var F = class {
2175
+ constructor(t) {
2176
+ this.url = t;
2177
+ this.ws = new WebSocket(t);
2178
+ }
2179
+ ws;
2180
+ send(t) {
2181
+ return Array.isArray(t) ? (t.forEach((n) => this.send(n)), this) : (this.ws.send(typeof t == "object" ? JSON.stringify(t) : t.toString()), this);
2182
+ }
2183
+ on(t, n, s2) {
2184
+ return this.addEventListener(t, n, s2);
2185
+ }
2186
+ off(t, n, s2) {
2187
+ return this.ws.removeEventListener(t, n, s2), this;
2188
+ }
2189
+ subscribe(t, n) {
2190
+ return this.addEventListener("message", t, n);
2191
+ }
2192
+ addEventListener(t, n, s2) {
2193
+ return this.ws.addEventListener(t, (f) => {
2194
+ if (t === "message") {
2195
+ let o2 = S(f);
2196
+ n({ ...f, data: o2 });
2197
+ } else
2198
+ n(f);
2199
+ }, s2), this;
2200
+ }
2201
+ removeEventListener(t, n, s2) {
2202
+ return this.off(t, n, s2), this;
2203
+ }
2204
+ close() {
2205
+ return this.ws.close(), this;
2206
+ }
2207
+ };
2208
+ var J = ["get", "post", "put", "delete", "patch", "options", "head", "connect", "subscribe"];
2209
+ var D = ["localhost", "127.0.0.1", "0.0.0.0"];
2210
+ var K = typeof FileList > "u";
2211
+ var I = (e) => K ? e instanceof Blob : e instanceof FileList || e instanceof File;
2212
+ var P = (e) => {
2213
+ if (!e)
2214
+ return false;
2215
+ for (let t in e)
2216
+ if (I(e[t]) || Array.isArray(e[t]) && e[t].find(I))
2217
+ return true;
2218
+ return false;
2219
+ };
2220
+ var C = (e) => K ? e : new Promise((t) => {
2221
+ let n = new FileReader;
2222
+ n.onload = () => {
2223
+ let s2 = new File([n.result], e.name, { lastModified: e.lastModified, type: e.type });
2224
+ t(s2);
2225
+ }, n.readAsArrayBuffer(e);
2226
+ });
2227
+ var b = (e, t, n = {}, s2 = {}) => {
2228
+ if (Array.isArray(e)) {
2229
+ for (let f of e)
2230
+ if (!Array.isArray(f))
2231
+ s2 = b(f, t, n, s2);
2232
+ else {
2233
+ let o2 = f[0];
2234
+ if (typeof o2 == "string")
2235
+ s2[o2.toLowerCase()] = f[1];
2236
+ else
2237
+ for (let [i2, h] of o2)
2238
+ s2[i2.toLowerCase()] = h;
2239
+ }
2240
+ return s2;
2241
+ }
2242
+ if (!e)
2243
+ return s2;
2244
+ switch (typeof e) {
2245
+ case "function":
2246
+ if (e instanceof Headers)
2247
+ return b(e, t, n, s2);
2248
+ let f = e(t, n);
2249
+ return f ? b(f, t, n, s2) : s2;
2250
+ case "object":
2251
+ if (e instanceof Headers)
2252
+ return e.forEach((o2, i2) => {
2253
+ s2[i2.toLowerCase()] = o2;
2254
+ }), s2;
2255
+ for (let [o2, i2] of Object.entries(e))
2256
+ s2[o2.toLowerCase()] = i2;
2257
+ return s2;
2258
+ default:
2259
+ return s2;
2260
+ }
2261
+ };
2262
+ async function* U(e) {
2263
+ let t = e.body;
2264
+ if (!t)
2265
+ return;
2266
+ let n = t.getReader(), s2 = new TextDecoder;
2267
+ try {
2268
+ for (;; ) {
2269
+ let { done: f, value: o2 } = await n.read();
2270
+ if (f)
2271
+ break;
2272
+ let i2 = typeof o2 == "string" ? o2 : s2.decode(o2);
2273
+ i2.includes(`
2274
+
2275
+ `) ? yield* _(i2) : yield g(i2);
2276
+ }
2277
+ } finally {
2278
+ n.releaseLock();
2279
+ }
2115
2280
  }
2281
+ function* _(e) {
2282
+ let t = e.split(`
2283
+
2284
+ `);
2285
+ for (let n of t) {
2286
+ if (n.indexOf(":") <= 0) {
2287
+ n && (yield g(n));
2288
+ continue;
2289
+ }
2290
+ let s2 = n.split(`
2291
+ `), f = {};
2292
+ for (let o2 of s2) {
2293
+ let i2 = o2.indexOf(":");
2294
+ if (i2 > 0) {
2295
+ let h = o2.slice(0, i2).trim(), L = o2.slice(i2 + 1).trim();
2296
+ f[h] = g(L);
2297
+ }
2298
+ }
2299
+ yield f;
2300
+ }
2301
+ }
2302
+ var x = (e, t, n = [], s2) => new Proxy(() => {}, { get(f, o2) {
2303
+ return x(e, t, o2 === "index" ? n : [...n, o2], s2);
2304
+ }, apply(f, o2, [i2, h]) {
2305
+ if (!i2 || h || typeof i2 == "object" && Object.keys(i2).length !== 1 || J.includes(n.at(-1))) {
2306
+ let L = [...n], k = L.pop(), v = "/" + L.join("/"), { fetcher: N = fetch, headers: R, onRequest: g2, onResponse: E, fetch: H } = t, m = k === "get" || k === "head" || k === "subscribe";
2307
+ R = b(R, v, h);
2308
+ let T = m ? i2?.query : h?.query, O = "";
2309
+ if (T) {
2310
+ let r = (w, u2) => {
2311
+ O += (O ? "&" : "?") + `${encodeURIComponent(w)}=${encodeURIComponent(u2)}`;
2312
+ };
2313
+ for (let [w, u2] of Object.entries(T)) {
2314
+ if (Array.isArray(u2)) {
2315
+ for (let y of u2)
2316
+ r(w, y);
2317
+ continue;
2318
+ }
2319
+ if (u2 != null) {
2320
+ if (typeof u2 == "object") {
2321
+ r(w, JSON.stringify(u2));
2322
+ continue;
2323
+ }
2324
+ r(w, `${u2}`);
2325
+ }
2326
+ }
2327
+ }
2328
+ if (k === "subscribe") {
2329
+ let r = e.replace(/^([^]+):\/\//, e.startsWith("https://") ? "wss://" : e.startsWith("http://") || D.find((w) => e.includes(w)) ? "ws://" : "wss://") + v + O;
2330
+ return new F(r);
2331
+ }
2332
+ return (async () => {
2333
+ let r = { method: k?.toUpperCase(), body: i2, ...H, headers: R };
2334
+ r.headers = { ...R, ...b(m ? i2?.headers : h?.headers, v, r) };
2335
+ let w = m && typeof i2 == "object" ? i2.fetch : h?.fetch;
2336
+ if (r = { ...r, ...w }, m && delete r.body, g2) {
2337
+ Array.isArray(g2) || (g2 = [g2]);
2338
+ for (let l of g2) {
2339
+ let a2 = await l(v, r);
2340
+ typeof a2 == "object" && (r = { ...r, ...a2, headers: { ...r.headers, ...b(a2.headers, v, r) } });
2341
+ }
2342
+ }
2343
+ if (m && delete r.body, P(i2)) {
2344
+ let l = new FormData;
2345
+ for (let [a2, c2] of Object.entries(r.body)) {
2346
+ if (Array.isArray(c2)) {
2347
+ for (let d2 = 0;d2 < c2.length; d2++) {
2348
+ let j = c2[d2];
2349
+ l.append(a2, j instanceof File ? await C(j) : j);
2350
+ }
2351
+ continue;
2352
+ }
2353
+ if (K) {
2354
+ if (Array.isArray(c2))
2355
+ for (let d2 of c2)
2356
+ l.append(a2, d2);
2357
+ else
2358
+ l.append(a2, c2);
2359
+ continue;
2360
+ }
2361
+ if (c2 instanceof File) {
2362
+ l.append(a2, await C(c2));
2363
+ continue;
2364
+ }
2365
+ if (c2 instanceof FileList) {
2366
+ for (let d2 = 0;d2 < c2.length; d2++)
2367
+ l.append(a2, await C(c2[d2]));
2368
+ continue;
2369
+ }
2370
+ l.append(a2, c2);
2371
+ }
2372
+ r.body = l;
2373
+ } else
2374
+ typeof i2 == "object" ? (r.headers["content-type"] = "application/json", r.body = JSON.stringify(i2)) : i2 != null && (r.headers["content-type"] = "text/plain");
2375
+ if (m && delete r.body, g2) {
2376
+ Array.isArray(g2) || (g2 = [g2]);
2377
+ for (let l of g2) {
2378
+ let a2 = await l(v, r);
2379
+ typeof a2 == "object" && (r = { ...r, ...a2, headers: { ...r.headers, ...b(a2.headers, v, r) } });
2380
+ }
2381
+ }
2382
+ h?.headers?.["content-type"] && (r.headers["content-type"] = h?.headers["content-type"]);
2383
+ let u2 = e + v + O, y = await (s2?.handle(new Request(u2, r)) ?? N(u2, r)), p2 = null, S2 = null;
2384
+ if (E) {
2385
+ Array.isArray(E) || (E = [E]);
2386
+ for (let l of E)
2387
+ try {
2388
+ let a2 = await l(y.clone());
2389
+ if (a2 != null) {
2390
+ p2 = a2;
2391
+ break;
2392
+ }
2393
+ } catch (a2) {
2394
+ a2 instanceof s ? S2 = a2 : S2 = new s(422, a2);
2395
+ break;
2396
+ }
2397
+ }
2398
+ if (p2 !== null)
2399
+ return { data: p2, error: S2, response: y, status: y.status, headers: y.headers };
2400
+ switch (y.headers.get("Content-Type")?.split(";")[0]) {
2401
+ case "text/event-stream":
2402
+ p2 = U(y);
2403
+ break;
2404
+ case "application/json":
2405
+ p2 = JSON.parse(await y.text(), (a2, c2) => {
2406
+ if (typeof c2 != "string")
2407
+ return c2;
2408
+ let d2 = d(c2);
2409
+ return d2 || c2;
2410
+ });
2411
+ break;
2412
+ case "application/octet-stream":
2413
+ p2 = await y.arrayBuffer();
2414
+ break;
2415
+ case "multipart/form-data":
2416
+ let l = await y.formData();
2417
+ p2 = {}, l.forEach((a2, c2) => {
2418
+ p2[c2] = a2;
2419
+ });
2420
+ break;
2421
+ default:
2422
+ p2 = await y.text().then(g);
2423
+ }
2424
+ return (y.status >= 300 || y.status < 200) && (S2 = new s(y.status, p2), p2 = null), { data: p2, error: S2, response: y, status: y.status, headers: y.headers };
2425
+ })();
2426
+ }
2427
+ return typeof i2 == "object" ? x(e, t, [...n, Object.values(i2)[0]], s2) : x(e, t, n);
2428
+ } });
2429
+ var Q = (e, t = {}) => typeof e == "string" ? (t.keepDomain || (e.includes("://") || (e = (D.find((n) => e.includes(n)) ? "http://" : "https://") + e), e.endsWith("/") && (e = e.slice(0, -1))), x(e, t)) : (typeof window < "u" && console.warn("Elysia instance server found on client side, this is not recommended for security reason. Use generic type instead."), x("http://e.ly", t, [], e));
2116
2430
 
2117
2431
  // src/api.ts
2118
- async function apiRequest(path, options = {}) {
2432
+ function getApi() {
2119
2433
  const config = loadConfig();
2120
2434
  if (!config) {
2121
2435
  throw new Error("Not logged in. Run: dblx auth login");
2122
2436
  }
2123
- const url = `${config.api_url}${path}`;
2124
- const res = await fetch(url, {
2125
- ...options,
2437
+ return Q(config.api_url, {
2126
2438
  headers: {
2127
- Authorization: `Bearer ${config.api_key}`,
2128
- "Content-Type": "application/json",
2129
- ...options.headers
2439
+ Authorization: `Bearer ${config.api_key}`
2440
+ }
2441
+ });
2442
+ }
2443
+ function getApiWith(apiKey, apiUrl) {
2444
+ return Q(apiUrl, {
2445
+ headers: {
2446
+ Authorization: `Bearer ${apiKey}`
2130
2447
  }
2131
2448
  });
2132
- if (!res.ok) {
2133
- const body = await res.json().catch(() => ({}));
2134
- throw new Error(`API error (${res.status}): ${body.error || res.statusText}`);
2135
- }
2136
- return res.json();
2137
2449
  }
2138
2450
 
2139
2451
  // src/output.ts
@@ -2162,11 +2474,11 @@ function output(data, opts) {
2162
2474
  function printTable(rows) {
2163
2475
  const keys = Object.keys(rows[0]);
2164
2476
  const widths = keys.map((k) => Math.max(k.length, ...rows.map((r) => String(r[k] ?? "").length)));
2165
- const header = keys.map((k, i) => k.padEnd(widths[i])).join(" ");
2477
+ const header = keys.map((k, i2) => k.padEnd(widths[i2])).join(" ");
2166
2478
  console.log(header);
2167
2479
  console.log(widths.map((w) => "-".repeat(w)).join(" "));
2168
2480
  for (const row of rows) {
2169
- const line = keys.map((k, i) => String(row[k] ?? "").padEnd(widths[i])).join(" ");
2481
+ const line = keys.map((k, i2) => String(row[k] ?? "").padEnd(widths[i2])).join(" ");
2170
2482
  console.log(line);
2171
2483
  }
2172
2484
  }
@@ -2195,25 +2507,26 @@ var authCommand = new Command("auth").description("Manage authentication").addCo
2195
2507
  console.error('Invalid API key format. Keys should start with "dblx_".');
2196
2508
  process.exit(1);
2197
2509
  }
2198
- const config = { api_key: apiKey, api_url: opts.apiUrl };
2199
- saveConfig(config);
2200
- try {
2201
- const me = await apiRequest("/api/cli/v1/me");
2202
- console.log(`Logged in as ${me.username} (${me.email})`);
2203
- console.log(`Config saved to ${getConfigPath()}`);
2204
- } catch {
2205
- deleteConfig();
2510
+ const api = getApiWith(apiKey, opts.apiUrl);
2511
+ const { data, error } = await api.api.cli.v1.me.get();
2512
+ if (error) {
2206
2513
  console.error("Login failed. The API key may be invalid.");
2207
2514
  process.exit(1);
2208
2515
  }
2516
+ saveConfig({ api_key: apiKey, api_url: opts.apiUrl });
2517
+ console.log(`Logged in as ${data.username} (${data.email})`);
2518
+ console.log(`Config saved to ${getConfigPath()}`);
2209
2519
  })).addCommand(new Command("whoami").description("Show the current authenticated user").option("--json", "Output as JSON").action(async (opts) => {
2210
2520
  const config = loadConfig();
2211
2521
  if (!config) {
2212
2522
  console.error("Not logged in. Run: dblx auth login");
2213
2523
  process.exit(1);
2214
2524
  }
2215
- const me = await apiRequest("/api/cli/v1/me");
2216
- output(me, { json: opts.json });
2525
+ const api = getApi();
2526
+ const { data, error } = await api.api.cli.v1.me.get();
2527
+ if (error)
2528
+ throw error;
2529
+ output(data, { json: opts.json });
2217
2530
  })).addCommand(new Command("logout").description("Remove saved credentials").action(() => {
2218
2531
  deleteConfig();
2219
2532
  console.log("Logged out. Config removed.");
@@ -2221,13 +2534,15 @@ var authCommand = new Command("auth").description("Manage authentication").addCo
2221
2534
 
2222
2535
  // src/commands/threads.ts
2223
2536
  var threadsCommand = new Command("threads").description("Manage threads").addCommand(new Command("list").description("List your threads").option("--json", "Output as JSON").option("--archived", "Include archived threads").option("--snoozed", "Include snoozed threads").action(async (opts) => {
2224
- const params = new URLSearchParams;
2225
- if (opts.archived)
2226
- params.set("archived", "true");
2227
- if (opts.snoozed)
2228
- params.set("snoozed", "true");
2229
- const qs = params.toString();
2230
- const data = await apiRequest(`/api/cli/v1/threads${qs ? `?${qs}` : ""}`);
2537
+ const api = getApi();
2538
+ const { data, error } = await api.api.cli.v1.threads.get({
2539
+ query: {
2540
+ archived: opts.archived ? "true" : undefined,
2541
+ snoozed: opts.snoozed ? "true" : undefined
2542
+ }
2543
+ });
2544
+ if (error)
2545
+ throw error;
2231
2546
  if (opts.json) {
2232
2547
  output(data.threads, { json: true });
2233
2548
  return;
@@ -2240,11 +2555,228 @@ var threadsCommand = new Command("threads").description("Manage threads").addCom
2240
2555
  snoozed: t.snoozed ? "snoozed" : ""
2241
2556
  }));
2242
2557
  output(rows, { json: false });
2558
+ })).addCommand(new Command("create").description("Create a new thread").requiredOption("--title <title>", "Thread title").option("--comment <text>", "Optional first comment").option("--json", "Output as JSON").action(async (opts) => {
2559
+ const api = getApi();
2560
+ const { data, error } = await api.api.cli.v1.threads.post({
2561
+ body: opts.title,
2562
+ comment: opts.comment
2563
+ });
2564
+ if (error)
2565
+ throw error;
2566
+ if (opts.json) {
2567
+ output(data.thread, { json: true });
2568
+ return;
2569
+ }
2570
+ console.log(`Created thread ${data.thread.id.slice(0, 8)}: ${data.thread.body}`);
2571
+ })).addCommand(new Command("update").description("Update a thread title").argument("<id>", "Thread ID").requiredOption("--title <title>", "New title").option("--json", "Output as JSON").action(async (id, opts) => {
2572
+ const api = getApi();
2573
+ const { data, error } = await api.api.cli.v1.threads({ id }).put({
2574
+ body: opts.title
2575
+ });
2576
+ if (error)
2577
+ throw error;
2578
+ if (opts.json) {
2579
+ output(data.thread, { json: true });
2580
+ return;
2581
+ }
2582
+ console.log(`Updated thread ${data.thread.id.slice(0, 8)}: ${data.thread.body}`);
2583
+ })).addCommand(new Command("archive").description("Archive a thread").argument("<id>", "Thread ID").action(async (id) => {
2584
+ const api = getApi();
2585
+ const { error } = await api.api.cli.v1.threads({ id }).archive.put({
2586
+ archived: true
2587
+ });
2588
+ if (error)
2589
+ throw error;
2590
+ console.log("Archived.");
2591
+ })).addCommand(new Command("unarchive").description("Unarchive a thread").argument("<id>", "Thread ID").action(async (id) => {
2592
+ const api = getApi();
2593
+ const { error } = await api.api.cli.v1.threads({ id }).archive.put({
2594
+ archived: false
2595
+ });
2596
+ if (error)
2597
+ throw error;
2598
+ console.log("Unarchived.");
2599
+ })).addCommand(new Command("snooze").description("Snooze a thread").argument("<id>", "Thread ID").requiredOption("--until <datetime>", "Snooze until (ISO datetime)").action(async (id, opts) => {
2600
+ const api = getApi();
2601
+ const { error } = await api.api.cli.v1.threads({ id }).snooze.put({
2602
+ until: opts.until
2603
+ });
2604
+ if (error)
2605
+ throw error;
2606
+ console.log(`Snoozed until ${opts.until}.`);
2607
+ })).addCommand(new Command("unsnooze").description("Remove snooze from a thread").argument("<id>", "Thread ID").action(async (id) => {
2608
+ const api = getApi();
2609
+ const { error } = await api.api.cli.v1.threads({ id }).snooze.put({
2610
+ until: null
2611
+ });
2612
+ if (error)
2613
+ throw error;
2614
+ console.log("Unsnoozed.");
2615
+ })).addCommand(new Command("set-parent").description("Set a parent thread").argument("<id>", "Thread ID").requiredOption("--parent <parent-id>", "Parent thread ID").action(async (id, opts) => {
2616
+ const api = getApi();
2617
+ const { error } = await api.api.cli.v1.threads({ id }).parent.put({
2618
+ parent_id: opts.parent
2619
+ });
2620
+ if (error)
2621
+ throw error;
2622
+ console.log(`Parent set to ${opts.parent.slice(0, 8)}.`);
2623
+ })).addCommand(new Command("set-today").description("Assign thread to a date").argument("<id>", "Thread ID").option("--date <date>", "Date (YYYY-MM-DD)", new Date().toISOString().slice(0, 10)).action(async (id, opts) => {
2624
+ const api = getApi();
2625
+ const { error } = await api.api.cli.v1.threads({ id }).today.put({
2626
+ date: opts.date
2627
+ });
2628
+ if (error)
2629
+ throw error;
2630
+ console.log(`Assigned to ${opts.date}.`);
2631
+ })).addCommand(new Command("unset-today").description("Remove thread from a date").argument("<id>", "Thread ID").option("--date <date>", "Date (YYYY-MM-DD)", new Date().toISOString().slice(0, 10)).action(async (id, opts) => {
2632
+ const api = getApi();
2633
+ const { error } = await api.api.cli.v1.threads({ id }).today.delete({
2634
+ date: opts.date
2635
+ });
2636
+ if (error)
2637
+ throw error;
2638
+ console.log(`Removed from ${opts.date}.`);
2639
+ }));
2640
+
2641
+ // src/commands/comments.ts
2642
+ var commentsCommand = new Command("comments").description("Manage comments").addCommand(new Command("list").description("List comments in a thread").requiredOption("--thread <id>", "Thread ID").option("--json", "Output as JSON").action(async (opts) => {
2643
+ const api = getApi();
2644
+ const { data, error } = await api.api.cli.v1.threads({ id: opts.thread }).comments.get();
2645
+ if (error)
2646
+ throw error;
2647
+ if (opts.json) {
2648
+ output(data.comments, { json: true });
2649
+ return;
2650
+ }
2651
+ const rows = data.comments.map((c2) => ({
2652
+ id: c2.id.slice(0, 8),
2653
+ user: c2.creator_username,
2654
+ body: c2.body.length > 60 ? c2.body.slice(0, 57) + "..." : c2.body,
2655
+ created_at: c2.created_at
2656
+ }));
2657
+ output(rows, { json: false });
2658
+ })).addCommand(new Command("add").description("Add a comment to a thread").requiredOption("--thread <id>", "Thread ID").requiredOption("--body <text>", "Comment text").option("--json", "Output as JSON").action(async (opts) => {
2659
+ const api = getApi();
2660
+ const { data, error } = await api.api.cli.v1.threads({ id: opts.thread }).comments.post({ body: opts.body });
2661
+ if (error)
2662
+ throw error;
2663
+ if (opts.json) {
2664
+ output(data.comment, { json: true });
2665
+ return;
2666
+ }
2667
+ console.log(`Comment added (${data.comment.id.slice(0, 8)}).`);
2668
+ })).addCommand(new Command("edit").description("Edit a comment").argument("<id>", "Comment ID").requiredOption("--body <text>", "New comment text").option("--json", "Output as JSON").action(async (id, opts) => {
2669
+ const api = getApi();
2670
+ const { data, error } = await api.api.cli.v1.comments({ id }).put({ body: opts.body });
2671
+ if (error)
2672
+ throw error;
2673
+ if (opts.json) {
2674
+ output(data.comment, { json: true });
2675
+ return;
2676
+ }
2677
+ console.log(`Comment updated (${data.comment.id.slice(0, 8)}).`);
2678
+ }));
2679
+
2680
+ // src/commands/members.ts
2681
+ var membersCommand = new Command("members").description("Manage thread members").addCommand(new Command("list").description("List members of a thread").argument("<thread-id>", "Thread ID").option("--json", "Output as JSON").action(async (threadId, opts) => {
2682
+ const api = getApi();
2683
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).members.get();
2684
+ if (error)
2685
+ throw error;
2686
+ if (opts.json) {
2687
+ output(data.members, { json: true });
2688
+ return;
2689
+ }
2690
+ const rows = data.members.filter((m) => !m.revoked_at).map((m) => ({
2691
+ username: m.username,
2692
+ email: m.email
2693
+ }));
2694
+ output(rows, { json: false });
2695
+ })).addCommand(new Command("invite").description("Invite a user to a thread").argument("<thread-id>", "Thread ID").requiredOption("--user <email-or-username>", "User email or username").action(async (threadId, opts) => {
2696
+ const api = getApi();
2697
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).members.post({ user: opts.user });
2698
+ if (error)
2699
+ throw error;
2700
+ if (data.invited) {
2701
+ console.log(`Invited ${data.user?.username || opts.user}.`);
2702
+ } else {
2703
+ console.log(data.reason || "Could not invite user.");
2704
+ }
2705
+ }));
2706
+
2707
+ // src/commands/today.ts
2708
+ function localDate(dateArg) {
2709
+ if (dateArg)
2710
+ return dateArg;
2711
+ const now = new Date;
2712
+ const y = now.getFullYear();
2713
+ const m = String(now.getMonth() + 1).padStart(2, "0");
2714
+ const d2 = String(now.getDate()).padStart(2, "0");
2715
+ return `${y}-${m}-${d2}`;
2716
+ }
2717
+ var todayCommand = new Command("today").description("Today view — threads and daily note").option("--date <date>", "Date (YYYY-MM-DD)").option("--json", "Output as JSON").action(async (opts) => {
2718
+ const date = localDate(opts.date);
2719
+ const api = getApi();
2720
+ const { data, error } = await api.api.cli.v1.today.get({
2721
+ query: { date }
2722
+ });
2723
+ if (error)
2724
+ throw error;
2725
+ if (opts.json) {
2726
+ output(data, { json: true });
2727
+ return;
2728
+ }
2729
+ console.log(`Date: ${data.date}
2730
+ `);
2731
+ if (data.threads.length > 0) {
2732
+ console.log("Threads:");
2733
+ for (const t of data.threads) {
2734
+ console.log(` ${t.id.slice(0, 8)} ${t.body}`);
2735
+ }
2736
+ console.log();
2737
+ } else {
2738
+ console.log(`No threads for this date.
2739
+ `);
2740
+ }
2741
+ if (data.note) {
2742
+ console.log("Note:");
2743
+ console.log(data.note.content || "(empty)");
2744
+ } else {
2745
+ console.log("No daily note.");
2746
+ }
2747
+ }).addCommand(new Command("note").description("Read or update the daily note").option("--date <date>", "Date (YYYY-MM-DD)").option("--set <content>", "Set note content").option("--json", "Output as JSON").action(async (opts) => {
2748
+ const date = localDate(opts.date);
2749
+ const api = getApi();
2750
+ if (opts.set !== undefined) {
2751
+ const { data: data2, error: error2 } = await api.api.cli.v1.today.note.put({ content: opts.set }, { query: { date } });
2752
+ if (error2)
2753
+ throw error2;
2754
+ if (opts.json) {
2755
+ output(data2, { json: true });
2756
+ return;
2757
+ }
2758
+ console.log("Note updated.");
2759
+ return;
2760
+ }
2761
+ const { data, error } = await api.api.cli.v1.today.note.get({
2762
+ query: { date }
2763
+ });
2764
+ if (error)
2765
+ throw error;
2766
+ if (opts.json) {
2767
+ output(data, { json: true });
2768
+ return;
2769
+ }
2770
+ if (!data.note) {
2771
+ console.log("No daily note.");
2772
+ return;
2773
+ }
2774
+ console.log(data.note.content || "(empty)");
2243
2775
  }));
2244
2776
  // package.json
2245
2777
  var package_default = {
2246
2778
  name: "dblx",
2247
- version: "0.1.46",
2779
+ version: "0.1.47",
2248
2780
  description: "CLI for dblebox — thread-first communication",
2249
2781
  type: "module",
2250
2782
  bin: {
@@ -2272,6 +2804,9 @@ var package_default = {
2272
2804
  var program2 = new Command().name("dblx").description("CLI for dblebox — thread-first communication").version(package_default.version);
2273
2805
  program2.addCommand(authCommand);
2274
2806
  program2.addCommand(threadsCommand);
2807
+ program2.addCommand(commentsCommand);
2808
+ program2.addCommand(membersCommand);
2809
+ program2.addCommand(todayCommand);
2275
2810
  program2.parseAsync().catch((err) => {
2276
2811
  console.error(err.message);
2277
2812
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dblx",
3
- "version": "0.1.46",
3
+ "version": "0.1.47",
4
4
  "description": "CLI for dblebox — thread-first communication",
5
5
  "type": "module",
6
6
  "bin": {