dblx 0.1.50 → 0.1.63

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 (3) hide show
  1. package/README.md +113 -42
  2. package/dist/index.js +404 -361
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -4,81 +4,152 @@ CLI for [dblebox](https://app.dblebox.com) — thread-first communication.
4
4
 
5
5
  ## Usage
6
6
 
7
+ The CLI uses a verb-first command structure:
8
+
9
+ ```bash
10
+ bunx dblx <verb> <noun> [options]
11
+ ```
12
+
13
+ Examples:
14
+
15
+ ```bash
16
+ dblx get threads
17
+ dblx get threads --q "planning"
18
+ dblx get today
19
+ dblx create thread --title "New thread"
20
+ dblx set thread 12345678 --title "Renamed"
21
+ ```
22
+
23
+ ## Command Model
24
+
25
+ Read operations use `get`:
26
+
27
+ ```bash
28
+ dblx get ...
7
29
  ```
8
- bunx dblx <command>
30
+
31
+ Write operations use `create`, `set`, and `invite`:
32
+
33
+ ```bash
34
+ dblx create ...
35
+ dblx set ...
36
+ dblx invite ...
9
37
  ```
10
38
 
39
+ This keeps permission boundaries clear for agents and automation. A tool can be granted `dblx get ...` without also gaining write access.
40
+
11
41
  ## Authentication
12
42
 
13
43
  Generate an API key from **Settings > API Keys** in the dblebox web app, then:
14
44
 
15
- ```
45
+ ```bash
16
46
  dblx auth login
17
47
  ```
18
48
 
19
49
  You'll be prompted for your key (starts with `dblx_`). Credentials are saved to `~/.config/dblx.json`.
20
50
 
21
- ```
22
- dblx auth whoami # show current user
23
- dblx auth logout # remove saved credentials
51
+ ```bash
52
+ dblx auth whoami
53
+ dblx auth logout
24
54
  ```
25
55
 
26
56
  You can also set `DBLEBOX_API_KEY` and `DBLEBOX_API_URL` environment variables instead of using `auth login`.
27
57
 
28
- ## Threads
58
+ ## Read Commands
59
+
60
+ ### Threads
61
+
62
+ ```bash
63
+ dblx get threads
64
+ dblx get threads --archived
65
+ dblx get threads --snoozed
66
+ dblx get threads --archived --snoozed
67
+ dblx get threads --q "plan"
68
+ dblx get threads --q "#dblebox" --archived --snoozed
69
+ ```
70
+
71
+ ### Today
72
+
73
+ ```bash
74
+ dblx get today
75
+ dblx get today --date 2026-03-01
76
+ ```
77
+
78
+ ### Notes
29
79
 
80
+ ```bash
81
+ dblx get thread-note <thread-id>
82
+ dblx get today-note
83
+ dblx get today-note --date 2026-03-01
30
84
  ```
31
- dblx threads list # list your threads
32
- dblx threads list --archived # include archived
33
- dblx threads list --snoozed # include snoozed
34
- dblx threads search "plan" # search by partial text
35
- dblx threads search "plan" --archived --snoozed
36
- dblx threads create --title "New thread" # create a thread
37
- dblx threads create --title "..." --comment "First message"
38
- dblx threads create --title "..." --note "Draft spec..."
39
- dblx threads update <id> --title "New title"
40
- dblx threads note <id> # read thread note
41
- dblx threads note <id> --set "Updated note"
42
- dblx threads archive <id>
43
- dblx threads unarchive <id>
44
- dblx threads snooze <id> --until 2026-03-01T09:00:00
45
- dblx threads unsnooze <id>
46
- dblx threads set-parent <id> --parent <parent-id>
47
- dblx threads set-today <id> # assign to today
48
- dblx threads set-today <id> --date 2026-03-01
49
- dblx threads unset-today <id>
85
+
86
+ ### Comments
87
+
88
+ ```bash
89
+ dblx get comments --thread <thread-id>
50
90
  ```
51
91
 
52
- ## Comments
92
+ ### Members
53
93
 
94
+ ```bash
95
+ dblx get members <thread-id>
54
96
  ```
55
- dblx comments list --thread <id>
56
- dblx comments add --thread <id> --body "Hello"
57
- dblx comments edit <comment-id> --body "Updated text"
97
+
98
+ ## Write Commands
99
+
100
+ ### Threads
101
+
102
+ ```bash
103
+ dblx create thread --title "New thread"
104
+ dblx create thread --title "..." --comment "First message"
105
+ dblx create thread --title "..." --note "Draft spec..."
106
+
107
+ dblx set thread <thread-id> --title "New title"
108
+ dblx set thread <thread-id> --archived true
109
+ dblx set thread <thread-id> --archived false
110
+ dblx set thread <thread-id> --snoozed-until 2026-03-01T09:00:00
111
+ dblx set thread <thread-id> --snoozed-until none
58
112
  ```
59
113
 
60
- ## Members
114
+ ### Notes
61
115
 
116
+ Reading and writing notes are separate commands.
117
+
118
+ ```bash
119
+ dblx set thread-note <thread-id> --content "Updated note"
120
+ dblx set today-note --content "My note"
121
+ dblx set today-note --date 2026-03-01 --content "My note"
62
122
  ```
63
- dblx members list <thread-id>
64
- dblx members invite <thread-id> --user alice@example.com
123
+
124
+ ### Relationships
125
+
126
+ ```bash
127
+ dblx set thread-parent <thread-id> --parent <parent-id>
128
+ dblx set thread-today <thread-id> --date 2026-03-01
129
+ dblx set thread-today <thread-id> --remove
130
+ dblx set thread-today <thread-id> --date 2026-03-01 --remove
65
131
  ```
66
132
 
67
- ## Today
133
+ ### Comments
68
134
 
135
+ ```bash
136
+ dblx create comment --thread <thread-id> --body "Hello"
137
+ dblx set comment <comment-id> --body "Updated text"
69
138
  ```
70
- dblx today # show today's threads and note
71
- dblx today --date 2026-03-01 # show a specific date
72
- dblx today note # read today's daily note
73
- dblx today note --set "My note" # update today's daily note
74
- dblx today note --date 2026-03-01
139
+
140
+ ### Members
141
+
142
+ ```bash
143
+ dblx invite member <thread-id> --user alice@example.com
75
144
  ```
76
145
 
77
- ## JSON output
146
+ ## JSON Output
78
147
 
79
148
  All read commands support `--json` for machine-readable output:
80
149
 
81
- ```
82
- dblx threads list --json
83
- dblx today --json
150
+ ```bash
151
+ dblx get threads --json
152
+ dblx get threads --q "plan" --json
153
+ dblx get today --json
154
+ dblx get thread-note <thread-id> --json
84
155
  ```
package/dist/index.js CHANGED
@@ -2127,62 +2127,64 @@ function deleteConfig() {
2127
2127
  }
2128
2128
  }
2129
2129
 
2130
- // ../node_modules/@elysiajs/eden/dist/chunk-QSLHAOSM.mjs
2131
- var s = class extends Error {
2132
- constructor(e, n) {
2133
- super(n + "");
2130
+ // ../node_modules/@elysiajs/eden/dist/chunk-I5KHAGLL.mjs
2131
+ var d = class extends Error {
2132
+ constructor(e, s) {
2133
+ super(s + "");
2134
2134
  this.status = e;
2135
- this.value = n;
2135
+ this.value = s;
2136
2136
  }
2137
2137
  };
2138
2138
  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))/;
2139
2139
  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\([^)]+\)/;
2140
- 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)?)?$/;
2141
- var u = (t) => t.trim().length !== 0 && !Number.isNaN(Number(t));
2142
- var d = (t) => {
2143
- if (typeof t != "string")
2140
+ var u = /^(?:(?:(?:(?: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)?)?$/;
2141
+ var c = (t) => t.trim().length !== 0 && !Number.isNaN(Number(t));
2142
+ var a = (t, r) => {
2143
+ if (typeof t != "string" || r?.parseDate === false)
2144
2144
  return null;
2145
- let r = t.replace(/"/g, "");
2146
- if (i.test(r) || o.test(r) || c.test(r)) {
2147
- let e = new Date(r);
2148
- if (!Number.isNaN(e.getTime()))
2149
- return e;
2145
+ let e = t.replace(/"/g, "");
2146
+ if (i.test(e) || o.test(e) || u.test(e)) {
2147
+ let s = new Date(e);
2148
+ if (!Number.isNaN(s.getTime()))
2149
+ return s;
2150
2150
  }
2151
2151
  return null;
2152
2152
  };
2153
- var a = (t) => {
2153
+ var p = (t) => {
2154
2154
  let r = t.charCodeAt(0), e = t.charCodeAt(t.length - 1);
2155
2155
  return r === 123 && e === 125 || r === 91 && e === 93;
2156
2156
  };
2157
- var p = (t) => JSON.parse(t, (r, e) => {
2158
- let n = d(e);
2159
- return n || e;
2157
+ var f = (t, r) => JSON.parse(t, (e, s) => {
2158
+ let n = a(s, r);
2159
+ return n || s;
2160
2160
  });
2161
- var g = (t) => {
2161
+ var g = (t, r) => {
2162
2162
  if (!t)
2163
2163
  return t;
2164
- if (u(t))
2164
+ if (c(t))
2165
2165
  return +t;
2166
2166
  if (t === "true")
2167
2167
  return true;
2168
2168
  if (t === "false")
2169
2169
  return false;
2170
- let r = d(t);
2171
- if (r)
2172
- return r;
2173
- if (a(t))
2170
+ if (r?.parseDate !== false) {
2171
+ let e = a(t, r);
2172
+ if (e)
2173
+ return e;
2174
+ }
2175
+ if (p(t))
2174
2176
  try {
2175
- return p(t);
2177
+ return f(t, r);
2176
2178
  } catch {}
2177
2179
  return t;
2178
2180
  };
2179
- var S = (t) => {
2180
- let r = t.data.toString();
2181
- return r === "null" ? null : g(r);
2181
+ var S = (t, r) => {
2182
+ let e = t.data.toString();
2183
+ return e === "null" ? null : g(e, r);
2182
2184
  };
2183
2185
 
2184
- // ../node_modules/@elysiajs/eden/dist/chunk-LJDYVDXQ.mjs
2185
- var F = class {
2186
+ // ../node_modules/@elysiajs/eden/dist/chunk-AB4FCYGG.mjs
2187
+ var W = class {
2186
2188
  constructor(t) {
2187
2189
  this.url = t;
2188
2190
  this.ws = new WebSocket(t);
@@ -2191,253 +2193,283 @@ var F = class {
2191
2193
  send(t) {
2192
2194
  return Array.isArray(t) ? (t.forEach((n) => this.send(n)), this) : (this.ws.send(typeof t == "object" ? JSON.stringify(t) : t.toString()), this);
2193
2195
  }
2194
- on(t, n, s2) {
2195
- return this.addEventListener(t, n, s2);
2196
+ on(t, n, r) {
2197
+ return this.addEventListener(t, n, r);
2196
2198
  }
2197
- off(t, n, s2) {
2198
- return this.ws.removeEventListener(t, n, s2), this;
2199
+ off(t, n, r) {
2200
+ return this.ws.removeEventListener(t, n, r), this;
2199
2201
  }
2200
2202
  subscribe(t, n) {
2201
2203
  return this.addEventListener("message", t, n);
2202
2204
  }
2203
- addEventListener(t, n, s2) {
2204
- return this.ws.addEventListener(t, (f) => {
2205
+ addEventListener(t, n, r) {
2206
+ return this.ws.addEventListener(t, (c2) => {
2205
2207
  if (t === "message") {
2206
- let o2 = S(f);
2207
- n({ ...f, data: o2 });
2208
+ let i2 = S(c2);
2209
+ n({ ...c2, data: i2 });
2208
2210
  } else
2209
- n(f);
2210
- }, s2), this;
2211
+ n(c2);
2212
+ }, r), this;
2211
2213
  }
2212
- removeEventListener(t, n, s2) {
2213
- return this.off(t, n, s2), this;
2214
+ removeEventListener(t, n, r) {
2215
+ return this.off(t, n, r), this;
2214
2216
  }
2215
2217
  close() {
2216
2218
  return this.ws.close(), this;
2217
2219
  }
2218
2220
  };
2219
- var J = ["get", "post", "put", "delete", "patch", "options", "head", "connect", "subscribe"];
2220
- var D = ["localhost", "127.0.0.1", "0.0.0.0"];
2221
- var K = typeof FileList > "u";
2222
- var I = (e) => K ? e instanceof Blob : e instanceof FileList || e instanceof File;
2223
- var P = (e) => {
2221
+ var Q = ["get", "post", "put", "delete", "patch", "options", "head", "connect", "subscribe"];
2222
+ var P = (e, t) => typeof t == "function" ? t(e) : t === true;
2223
+ var U = ["localhost", "127.0.0.1", "0.0.0.0"];
2224
+ var q = typeof FileList > "u";
2225
+ var H = (e) => q ? e instanceof Blob : e instanceof FileList || e instanceof File;
2226
+ var X = (e) => {
2224
2227
  if (!e)
2225
2228
  return false;
2226
2229
  for (let t in e)
2227
- if (I(e[t]) || Array.isArray(e[t]) && e[t].find(I))
2230
+ if (H(e[t]) || Array.isArray(e[t]) && e[t].find(H))
2228
2231
  return true;
2229
2232
  return false;
2230
2233
  };
2231
- var C = (e) => K ? e : new Promise((t) => {
2234
+ var K = (e) => q ? e : new Promise((t) => {
2232
2235
  let n = new FileReader;
2233
2236
  n.onload = () => {
2234
- let s2 = new File([n.result], e.name, { lastModified: e.lastModified, type: e.type });
2235
- t(s2);
2237
+ let r = new File([n.result], e.name, { lastModified: e.lastModified, type: e.type });
2238
+ t(r);
2236
2239
  }, n.readAsArrayBuffer(e);
2237
2240
  });
2238
- var b = (e, t, n = {}, s2 = {}) => {
2241
+ var A = async (e, t, n = {}, r = {}) => {
2239
2242
  if (Array.isArray(e)) {
2240
- for (let f of e)
2241
- if (!Array.isArray(f))
2242
- s2 = b(f, t, n, s2);
2243
+ for (let c2 of e)
2244
+ if (!Array.isArray(c2))
2245
+ r = await A(c2, t, n, r);
2243
2246
  else {
2244
- let o2 = f[0];
2245
- if (typeof o2 == "string")
2246
- s2[o2.toLowerCase()] = f[1];
2247
+ let i2 = c2[0];
2248
+ if (typeof i2 == "string")
2249
+ r[i2.toLowerCase()] = c2[1];
2247
2250
  else
2248
- for (let [i2, h] of o2)
2249
- s2[i2.toLowerCase()] = h;
2251
+ for (let [a2, l] of i2)
2252
+ r[a2.toLowerCase()] = l;
2250
2253
  }
2251
- return s2;
2254
+ return r;
2252
2255
  }
2253
2256
  if (!e)
2254
- return s2;
2257
+ return r;
2255
2258
  switch (typeof e) {
2256
2259
  case "function":
2257
2260
  if (e instanceof Headers)
2258
- return b(e, t, n, s2);
2259
- let f = e(t, n);
2260
- return f ? b(f, t, n, s2) : s2;
2261
+ return A(e, t, n, r);
2262
+ let c2 = await e(t, n);
2263
+ return c2 ? A(c2, t, n, r) : r;
2261
2264
  case "object":
2262
2265
  if (e instanceof Headers)
2263
- return e.forEach((o2, i2) => {
2264
- s2[i2.toLowerCase()] = o2;
2265
- }), s2;
2266
- for (let [o2, i2] of Object.entries(e))
2267
- s2[o2.toLowerCase()] = i2;
2268
- return s2;
2266
+ return e.forEach((i2, a2) => {
2267
+ r[a2.toLowerCase()] = i2;
2268
+ }), r;
2269
+ for (let [i2, a2] of Object.entries(e))
2270
+ r[i2.toLowerCase()] = a2;
2271
+ return r;
2269
2272
  default:
2270
- return s2;
2273
+ return r;
2271
2274
  }
2272
2275
  };
2273
- async function* U(e) {
2274
- let t = e.body;
2275
- if (!t)
2276
- return;
2277
- let n = t.getReader(), s2 = new TextDecoder;
2278
- try {
2279
- for (;; ) {
2280
- let { done: f, value: o2 } = await n.read();
2281
- if (f)
2282
- break;
2283
- let i2 = typeof o2 == "string" ? o2 : s2.decode(o2);
2284
- i2.includes(`
2285
-
2286
- `) ? yield* _(i2) : yield g(i2);
2276
+ function _(e, t) {
2277
+ let n = e.split(`
2278
+ `), r = {};
2279
+ for (let c2 of n) {
2280
+ if (!c2 || c2.startsWith(":"))
2281
+ continue;
2282
+ let i2 = c2.indexOf(":");
2283
+ if (i2 > 0) {
2284
+ let a2 = c2.slice(0, i2).trim(), l = c2.slice(i2 + 1).replace(/^ /, "");
2285
+ r[a2] = l && g(l, t);
2287
2286
  }
2288
- } finally {
2289
- n.releaseLock();
2290
2287
  }
2288
+ return Object.keys(r).length > 0 ? r : null;
2291
2289
  }
2292
- function* _(e) {
2293
- let t = e.split(`
2290
+ function* B(e, t) {
2291
+ let n;
2292
+ for (;(n = e.value.indexOf(`
2294
2293
 
2295
- `);
2296
- for (let n of t) {
2297
- if (n.indexOf(":") <= 0) {
2298
- n && (yield g(n));
2299
- continue;
2294
+ `)) !== -1; ) {
2295
+ let r = e.value.slice(0, n);
2296
+ if (e.value = e.value.slice(n + 2), r.trim()) {
2297
+ let c2 = _(r, t);
2298
+ c2 && (yield c2);
2300
2299
  }
2301
- let s2 = n.split(`
2302
- `), f = {};
2303
- for (let o2 of s2) {
2304
- let i2 = o2.indexOf(":");
2305
- if (i2 > 0) {
2306
- let h = o2.slice(0, i2).trim(), L = o2.slice(i2 + 1).trim();
2307
- f[h] = g(L);
2308
- }
2300
+ }
2301
+ }
2302
+ async function* Y(e, t) {
2303
+ let n = e.body;
2304
+ if (!n)
2305
+ return;
2306
+ let r = n.getReader(), c2 = new TextDecoder("utf-8"), i2 = { value: "" };
2307
+ try {
2308
+ for (;; ) {
2309
+ let { done: l, value: O } = await r.read();
2310
+ if (l)
2311
+ break;
2312
+ let k = typeof O == "string" ? O : c2.decode(O, { stream: true });
2313
+ i2.value += k, yield* B(i2, t);
2309
2314
  }
2310
- yield f;
2315
+ let a2 = c2.decode();
2316
+ if (a2 && (i2.value += a2), yield* B(i2, t), i2.value.trim()) {
2317
+ let l = _(i2.value, t);
2318
+ l && (yield l);
2319
+ }
2320
+ } finally {
2321
+ r.releaseLock();
2311
2322
  }
2312
2323
  }
2313
- var x = (e, t, n = [], s2) => new Proxy(() => {}, { get(f, o2) {
2314
- return x(e, t, o2 === "index" ? n : [...n, o2], s2);
2315
- }, apply(f, o2, [i2, h]) {
2316
- if (!i2 || h || typeof i2 == "object" && Object.keys(i2).length !== 1 || J.includes(n.at(-1))) {
2317
- 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";
2318
- R = b(R, v, h);
2319
- let T = m ? i2?.query : h?.query, O = "";
2320
- if (T) {
2321
- let r = (w, u2) => {
2322
- O += (O ? "&" : "?") + `${encodeURIComponent(w)}=${encodeURIComponent(u2)}`;
2324
+ var F = (e, t, n = [], r) => new Proxy(() => {}, { get(c2, i2) {
2325
+ if (!(n.length === 0 && (i2 === "then" || i2 === "catch" || i2 === "finally")))
2326
+ return F(e, t, [...n, i2], r);
2327
+ }, apply(c2, i2, [a2, l]) {
2328
+ if (!a2 || l || typeof a2 == "object" && Object.keys(a2).length !== 1 || Q.includes(n.at(-1))) {
2329
+ let O = [...n], k = O.pop(), b = "/" + O.join("/"), { fetcher: V = fetch, headers: L, onRequest: g2, onResponse: R, fetch: G } = t, E = k === "get" || k === "head" || k === "subscribe", M = E ? a2?.query : l?.query, D = "";
2330
+ if (M) {
2331
+ let s = (m, d2) => {
2332
+ d2 != null && (d2 instanceof Date && (d2 = d2.toISOString()), D += (D ? "&" : "?") + `${encodeURIComponent(m)}=${encodeURIComponent(typeof d2 == "object" ? JSON.stringify(d2) : d2 + "")}`);
2323
2333
  };
2324
- for (let [w, u2] of Object.entries(T)) {
2325
- if (Array.isArray(u2)) {
2326
- for (let y of u2)
2327
- r(w, y);
2334
+ for (let [m, d2] of Object.entries(M)) {
2335
+ if (Array.isArray(d2)) {
2336
+ for (let T of d2)
2337
+ s(m, T);
2328
2338
  continue;
2329
2339
  }
2330
- if (u2 != null) {
2331
- if (typeof u2 == "object") {
2332
- r(w, JSON.stringify(u2));
2333
- continue;
2334
- }
2335
- r(w, `${u2}`);
2336
- }
2340
+ s(m, d2);
2337
2341
  }
2338
2342
  }
2339
2343
  if (k === "subscribe") {
2340
- let r = e.replace(/^([^]+):\/\//, e.startsWith("https://") ? "wss://" : e.startsWith("http://") || D.find((w) => e.includes(w)) ? "ws://" : "wss://") + v + O;
2341
- return new F(r);
2344
+ let s = e.replace(/^([^]+):\/\//, e.startsWith("https://") ? "wss://" : e.startsWith("http://") || U.find((m) => e.includes(m)) ? "ws://" : "wss://") + b + D;
2345
+ return new W(s);
2342
2346
  }
2343
2347
  return (async () => {
2344
- let r = { method: k?.toUpperCase(), body: i2, ...H, headers: R };
2345
- r.headers = { ...R, ...b(m ? i2?.headers : h?.headers, v, r) };
2346
- let w = m && typeof i2 == "object" ? i2.fetch : h?.fetch;
2347
- if (r = { ...r, ...w }, m && delete r.body, g2) {
2348
+ L = await A(L, b, l);
2349
+ let s = { method: k?.toUpperCase(), body: a2, ...G, headers: L };
2350
+ s.headers = { ...L, ...await A(E ? a2?.headers : l?.headers, b, s) };
2351
+ let m = E && typeof a2 == "object" ? a2.fetch : l?.fetch, T = (E && typeof a2 == "object" ? a2.throwHttpError : l?.throwHttpError) ?? t.throwHttpError;
2352
+ if (s = { ...s, ...m }, E && delete s.body, g2) {
2348
2353
  Array.isArray(g2) || (g2 = [g2]);
2349
- for (let l of g2) {
2350
- let a2 = await l(v, r);
2351
- typeof a2 == "object" && (r = { ...r, ...a2, headers: { ...r.headers, ...b(a2.headers, v, r) } });
2354
+ for (let u2 of g2) {
2355
+ let o2 = await u2(b, s);
2356
+ typeof o2 == "object" && (s = { ...s, ...o2, headers: { ...s.headers, ...await A(o2.headers, b, s) } });
2352
2357
  }
2353
2358
  }
2354
- if (m && delete r.body, P(i2)) {
2355
- let l = new FormData;
2356
- for (let [a2, c2] of Object.entries(r.body)) {
2357
- if (Array.isArray(c2)) {
2358
- for (let d2 = 0;d2 < c2.length; d2++) {
2359
- let j = c2[d2];
2360
- l.append(a2, j instanceof File ? await C(j) : j);
2361
- }
2359
+ if (E && delete s.body, X(a2)) {
2360
+ let u2 = new FormData, o2 = (f2) => {
2361
+ if (typeof f2 == "string" || H(f2))
2362
+ return false;
2363
+ if (typeof f2 == "object") {
2364
+ if (f2 !== null)
2365
+ return true;
2366
+ if (f2 instanceof Date)
2367
+ return false;
2368
+ }
2369
+ return false;
2370
+ }, w = async (f2) => f2 instanceof File ? await K(f2) : o2(f2) ? JSON.stringify(f2) : f2;
2371
+ for (let [f2, p2] of Object.entries(s.body)) {
2372
+ if (Array.isArray(p2)) {
2373
+ if (p2.some((S2) => typeof S2 == "object" && S2 !== null && !H(S2)))
2374
+ u2.append(f2, JSON.stringify(p2));
2375
+ else
2376
+ for (let S2 = 0;S2 < p2.length; S2++) {
2377
+ let $ = p2[S2], z = await w($);
2378
+ u2.append(f2, z);
2379
+ }
2362
2380
  continue;
2363
2381
  }
2364
- if (K) {
2365
- if (Array.isArray(c2))
2366
- for (let d2 of c2)
2367
- l.append(a2, d2);
2382
+ if (q) {
2383
+ if (Array.isArray(p2))
2384
+ for (let x of p2)
2385
+ u2.append(f2, await w(x));
2368
2386
  else
2369
- l.append(a2, c2);
2387
+ u2.append(f2, await w(p2));
2370
2388
  continue;
2371
2389
  }
2372
- if (c2 instanceof File) {
2373
- l.append(a2, await C(c2));
2390
+ if (p2 instanceof File) {
2391
+ u2.append(f2, await K(p2));
2374
2392
  continue;
2375
2393
  }
2376
- if (c2 instanceof FileList) {
2377
- for (let d2 = 0;d2 < c2.length; d2++)
2378
- l.append(a2, await C(c2[d2]));
2394
+ if (p2 instanceof FileList) {
2395
+ for (let x = 0;x < p2.length; x++)
2396
+ u2.append(f2, await K(p2[x]));
2379
2397
  continue;
2380
2398
  }
2381
- l.append(a2, c2);
2399
+ u2.append(f2, await w(p2));
2382
2400
  }
2383
- r.body = l;
2401
+ s.body = u2;
2384
2402
  } else
2385
- typeof i2 == "object" ? (r.headers["content-type"] = "application/json", r.body = JSON.stringify(i2)) : i2 != null && (r.headers["content-type"] = "text/plain");
2386
- if (m && delete r.body, g2) {
2403
+ typeof a2 == "object" ? (s.headers["content-type"] = "application/json", s.body = JSON.stringify(a2)) : a2 != null && (s.headers["content-type"] = "text/plain");
2404
+ if (E && delete s.body, g2) {
2387
2405
  Array.isArray(g2) || (g2 = [g2]);
2388
- for (let l of g2) {
2389
- let a2 = await l(v, r);
2390
- typeof a2 == "object" && (r = { ...r, ...a2, headers: { ...r.headers, ...b(a2.headers, v, r) } });
2406
+ for (let u2 of g2) {
2407
+ let o2 = await u2(b, s);
2408
+ typeof o2 == "object" && (s = { ...s, ...o2, headers: { ...s.headers, ...await A(o2.headers, b, s) } });
2391
2409
  }
2392
2410
  }
2393
- h?.headers?.["content-type"] && (r.headers["content-type"] = h?.headers["content-type"]);
2394
- let u2 = e + v + O, y = await (s2?.handle(new Request(u2, r)) ?? N(u2, r)), p2 = null, S2 = null;
2395
- if (E) {
2396
- Array.isArray(E) || (E = [E]);
2397
- for (let l of E)
2411
+ l?.headers?.["content-type"] && (s.headers["content-type"] = l?.headers["content-type"]);
2412
+ let I = e + b + D, y;
2413
+ try {
2414
+ y = await (r?.handle(new Request(I, s)) ?? V(I, s));
2415
+ } catch (u2) {
2416
+ let o2 = new d(503, u2);
2417
+ if (P(o2, T))
2418
+ throw o2;
2419
+ return { data: null, error: o2, response: undefined, status: 503, headers: undefined };
2420
+ }
2421
+ let h = null, v = null;
2422
+ if (R) {
2423
+ Array.isArray(R) || (R = [R]);
2424
+ for (let u2 of R)
2398
2425
  try {
2399
- let a2 = await l(y.clone());
2400
- if (a2 != null) {
2401
- p2 = a2;
2426
+ let o2 = await u2(y.clone());
2427
+ if (o2 != null) {
2428
+ h = o2;
2402
2429
  break;
2403
2430
  }
2404
- } catch (a2) {
2405
- a2 instanceof s ? S2 = a2 : S2 = new s(422, a2);
2431
+ } catch (o2) {
2432
+ o2 instanceof d ? v = o2 : v = new d(422, o2);
2406
2433
  break;
2407
2434
  }
2408
2435
  }
2409
- if (p2 !== null)
2410
- return { data: p2, error: S2, response: y, status: y.status, headers: y.headers };
2436
+ if (h !== null)
2437
+ return { data: h, error: v, response: y, status: y.status, headers: y.headers };
2411
2438
  switch (y.headers.get("Content-Type")?.split(";")[0]) {
2412
2439
  case "text/event-stream":
2413
- p2 = U(y);
2440
+ h = Y(y, { parseDate: t.parseDate });
2414
2441
  break;
2415
2442
  case "application/json":
2416
- p2 = JSON.parse(await y.text(), (a2, c2) => {
2417
- if (typeof c2 != "string")
2418
- return c2;
2419
- let d2 = d(c2);
2420
- return d2 || c2;
2443
+ h = JSON.parse(await y.text(), (o2, w) => {
2444
+ if (typeof w != "string")
2445
+ return w;
2446
+ let f2 = a(w, { parseDate: t.parseDate });
2447
+ return f2 || w;
2421
2448
  });
2422
2449
  break;
2423
2450
  case "application/octet-stream":
2424
- p2 = await y.arrayBuffer();
2451
+ h = await y.arrayBuffer();
2425
2452
  break;
2426
2453
  case "multipart/form-data":
2427
- let l = await y.formData();
2428
- p2 = {}, l.forEach((a2, c2) => {
2429
- p2[c2] = a2;
2454
+ let u2 = await y.formData();
2455
+ h = {}, u2.forEach((o2, w) => {
2456
+ h[w] = o2;
2430
2457
  });
2431
2458
  break;
2432
2459
  default:
2433
- p2 = await y.text().then(g);
2460
+ h = await y.text().then((o2) => g(o2, { parseDate: t.parseDate }));
2461
+ }
2462
+ if (y.status >= 300 || y.status < 200) {
2463
+ if (v = new d(y.status, h), P(v, T))
2464
+ throw v;
2465
+ h = null;
2434
2466
  }
2435
- 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 };
2467
+ return { data: h, error: v, response: y, status: y.status, headers: y.headers };
2436
2468
  })();
2437
2469
  }
2438
- return typeof i2 == "object" ? x(e, t, [...n, Object.values(i2)[0]], s2) : x(e, t, n);
2470
+ return typeof a2 == "object" ? F(e, t, [...n, Object.values(a2)[0]], r) : F(e, t, n);
2439
2471
  } });
2440
- 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));
2472
+ var se = (e, t = {}) => typeof e == "string" ? (t.keepDomain || (e.includes("://") || (e = (U.find((n) => e.includes(n)) ? "http://" : "https://") + e), e.endsWith("/") && (e = e.slice(0, -1))), F(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."), F("http://e.ly", t, [], e));
2441
2473
 
2442
2474
  // src/api.ts
2443
2475
  function getApi() {
@@ -2445,14 +2477,16 @@ function getApi() {
2445
2477
  if (!config) {
2446
2478
  throw new Error("Not logged in. Run: dblx auth login");
2447
2479
  }
2448
- return Q(config.api_url, {
2480
+ return se(config.api_url, {
2481
+ parseDate: false,
2449
2482
  headers: {
2450
2483
  Authorization: `Bearer ${config.api_key}`
2451
2484
  }
2452
2485
  });
2453
2486
  }
2454
2487
  function getApiWith(apiKey, apiUrl) {
2455
- return Q(apiUrl, {
2488
+ return se(apiUrl, {
2489
+ parseDate: false,
2456
2490
  headers: {
2457
2491
  Authorization: `Bearer ${apiKey}`
2458
2492
  }
@@ -2543,7 +2577,7 @@ var authCommand = new Command("auth").description("Manage authentication").addCo
2543
2577
  console.log("Logged out. Config removed.");
2544
2578
  }));
2545
2579
 
2546
- // src/commands/threads.ts
2580
+ // src/commands/helpers.ts
2547
2581
  function threadRows(threads) {
2548
2582
  return threads.map((t) => ({
2549
2583
  id: t.id.slice(0, 8),
@@ -2553,10 +2587,29 @@ function threadRows(threads) {
2553
2587
  snoozed: t.snoozed ? "snoozed" : ""
2554
2588
  }));
2555
2589
  }
2556
- 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) => {
2590
+ function localDate(dateArg) {
2591
+ if (dateArg)
2592
+ return dateArg;
2593
+ const now = new Date;
2594
+ const y = now.getFullYear();
2595
+ const m = String(now.getMonth() + 1).padStart(2, "0");
2596
+ const d2 = String(now.getDate()).padStart(2, "0");
2597
+ return `${y}-${m}-${d2}`;
2598
+ }
2599
+ function parseBooleanish(value) {
2600
+ if (value === "true")
2601
+ return true;
2602
+ if (value === "false")
2603
+ return false;
2604
+ throw new InvalidArgumentError('Expected "true" or "false".');
2605
+ }
2606
+
2607
+ // src/commands/get.ts
2608
+ var getCommand = new Command("get").description("Read data from dblebox").addCommand(new Command("threads").description("List or search your threads").option("--q <query>", "Filter by partial title/body text").option("--json", "Output as JSON").option("--archived", "Include archived threads").option("--snoozed", "Include snoozed threads").action(async (opts) => {
2557
2609
  const api = getApi();
2558
2610
  const { data, error } = await api.api.cli.v1.threads.get({
2559
2611
  query: {
2612
+ q: opts.q,
2560
2613
  archived: opts.archived ? "true" : undefined,
2561
2614
  snoozed: opts.snoozed ? "true" : undefined
2562
2615
  }
@@ -2568,64 +2621,56 @@ var threadsCommand = new Command("threads").description("Manage threads").addCom
2568
2621
  return;
2569
2622
  }
2570
2623
  output(threadRows(data.threads), { json: false });
2571
- })).addCommand(new Command("search").description("Search threads by partial text").argument("<query>", "Partial title/body text to match").option("--json", "Output as JSON").option("--archived", "Include archived threads").option("--snoozed", "Include snoozed threads").action(async (query, opts) => {
2624
+ })).addCommand(new Command("today").description("Show threads and note for a date").option("--date <date>", "Date (YYYY-MM-DD)").option("--json", "Output as JSON").action(async (opts) => {
2625
+ const date = localDate(opts.date);
2572
2626
  const api = getApi();
2573
- const { data, error } = await api.api.cli.v1.threads.get({
2574
- query: {
2575
- q: query,
2576
- archived: opts.archived ? "true" : undefined,
2577
- snoozed: opts.snoozed ? "true" : undefined
2578
- }
2627
+ const { data, error } = await api.api.cli.v1.today.get({
2628
+ query: { date }
2579
2629
  });
2580
2630
  if (error)
2581
2631
  throw error;
2582
2632
  if (opts.json) {
2583
- output(data.threads, { json: true });
2633
+ output(data, { json: true });
2584
2634
  return;
2585
2635
  }
2586
- output(threadRows(data.threads), { json: false });
2587
- })).addCommand(new Command("create").description("Create a new thread").requiredOption("--title <title>", "Thread title").option("--comment <text>", "Optional first comment").option("--note <content>", "Create and attach a block note with content").option("--json", "Output as JSON").action(async (opts) => {
2636
+ console.log(`Date: ${data.date}
2637
+ `);
2638
+ if (data.threads.length > 0) {
2639
+ console.log("Threads:");
2640
+ for (const t of data.threads) {
2641
+ console.log(` ${t.id.slice(0, 8)} ${t.body}`);
2642
+ }
2643
+ console.log();
2644
+ } else {
2645
+ console.log(`No threads for this date.
2646
+ `);
2647
+ }
2648
+ if (data.note) {
2649
+ console.log("Note:");
2650
+ console.log(data.note.content || "(empty)");
2651
+ } else {
2652
+ console.log("No daily note.");
2653
+ }
2654
+ })).addCommand(new Command("thread-note").description("Read a thread note").argument("<thread-id>", "Thread ID").option("--json", "Output as JSON").action(async (threadId, opts) => {
2588
2655
  const api = getApi();
2589
- const noteContent = opts.note !== undefined ? opts.note : undefined;
2590
- const { data, error } = await api.api.cli.v1.threads.post({
2591
- body: opts.title,
2592
- comment: opts.comment,
2593
- note_content: noteContent
2594
- });
2656
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).note.get();
2595
2657
  if (error)
2596
2658
  throw error;
2597
2659
  if (opts.json) {
2598
2660
  output(data, { json: true });
2599
2661
  return;
2600
2662
  }
2601
- const noteSuffix = data.note ? ` (note ${data.note.id.slice(0, 8)} attached)` : "";
2602
- console.log(`Created thread ${data.thread.id.slice(0, 8)}: ${data.thread.body}${noteSuffix}`);
2603
- })).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) => {
2604
- const api = getApi();
2605
- const { data, error } = await api.api.cli.v1.threads({ id }).put({
2606
- body: opts.title
2607
- });
2608
- if (error)
2609
- throw error;
2610
- if (opts.json) {
2611
- output(data.thread, { json: true });
2663
+ if (!data.note) {
2664
+ console.log("No thread note.");
2612
2665
  return;
2613
2666
  }
2614
- console.log(`Updated thread ${data.thread.id.slice(0, 8)}: ${data.thread.body}`);
2615
- })).addCommand(new Command("note").description("Read or update a thread block note").argument("<id>", "Thread ID").option("--set <content>", "Set note content").option("--json", "Output as JSON").action(async (id, opts) => {
2667
+ console.log(data.note.content || "(empty)");
2668
+ })).addCommand(new Command("today-note").description("Read a daily note").option("--date <date>", "Date (YYYY-MM-DD)").option("--json", "Output as JSON").action(async (opts) => {
2669
+ const date = localDate(opts.date);
2616
2670
  const api = getApi();
2617
- if (opts.set !== undefined) {
2618
- const { data: data2, error: error2 } = await api.api.cli.v1.threads({ id }).note.put({ content: opts.set });
2619
- if (error2)
2620
- throw error2;
2621
- if (opts.json) {
2622
- output(data2, { json: true });
2623
- return;
2624
- }
2625
- console.log("Note updated.");
2626
- return;
2627
- }
2628
- const { data, error } = await api.api.cli.v1.threads({ id }).note.get();
2671
+ const { data, error } = await api.api.cli.v1.today.note.get({
2672
+ query: { date }
2673
+ });
2629
2674
  if (error)
2630
2675
  throw error;
2631
2676
  if (opts.json) {
@@ -2633,70 +2678,11 @@ var threadsCommand = new Command("threads").description("Manage threads").addCom
2633
2678
  return;
2634
2679
  }
2635
2680
  if (!data.note) {
2636
- console.log("No thread note.");
2681
+ console.log("No daily note.");
2637
2682
  return;
2638
2683
  }
2639
2684
  console.log(data.note.content || "(empty)");
2640
- })).addCommand(new Command("archive").description("Archive a thread").argument("<id>", "Thread ID").action(async (id) => {
2641
- const api = getApi();
2642
- const { error } = await api.api.cli.v1.threads({ id }).archive.put({
2643
- archived: true
2644
- });
2645
- if (error)
2646
- throw error;
2647
- console.log("Archived.");
2648
- })).addCommand(new Command("unarchive").description("Unarchive a thread").argument("<id>", "Thread ID").action(async (id) => {
2649
- const api = getApi();
2650
- const { error } = await api.api.cli.v1.threads({ id }).archive.put({
2651
- archived: false
2652
- });
2653
- if (error)
2654
- throw error;
2655
- console.log("Unarchived.");
2656
- })).addCommand(new Command("snooze").description("Snooze a thread").argument("<id>", "Thread ID").requiredOption("--until <datetime>", "Snooze until (ISO datetime)").action(async (id, opts) => {
2657
- const api = getApi();
2658
- const { error } = await api.api.cli.v1.threads({ id }).snooze.put({
2659
- until: opts.until
2660
- });
2661
- if (error)
2662
- throw error;
2663
- console.log(`Snoozed until ${opts.until}.`);
2664
- })).addCommand(new Command("unsnooze").description("Remove snooze from a thread").argument("<id>", "Thread ID").action(async (id) => {
2665
- const api = getApi();
2666
- const { error } = await api.api.cli.v1.threads({ id }).snooze.put({
2667
- until: null
2668
- });
2669
- if (error)
2670
- throw error;
2671
- console.log("Unsnoozed.");
2672
- })).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) => {
2673
- const api = getApi();
2674
- const { error } = await api.api.cli.v1.threads({ id }).parent.put({
2675
- parent_id: opts.parent
2676
- });
2677
- if (error)
2678
- throw error;
2679
- console.log(`Parent set to ${opts.parent.slice(0, 8)}.`);
2680
- })).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) => {
2681
- const api = getApi();
2682
- const { error } = await api.api.cli.v1.threads({ id }).today.put({
2683
- date: opts.date
2684
- });
2685
- if (error)
2686
- throw error;
2687
- console.log(`Assigned to ${opts.date}.`);
2688
- })).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) => {
2689
- const api = getApi();
2690
- const { error } = await api.api.cli.v1.threads({ id }).today.delete({
2691
- date: opts.date
2692
- });
2693
- if (error)
2694
- throw error;
2695
- console.log(`Removed from ${opts.date}.`);
2696
- }));
2697
-
2698
- // src/commands/comments.ts
2699
- 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) => {
2685
+ })).addCommand(new Command("comments").description("List comments in a thread").requiredOption("--thread <id>", "Thread ID").option("--json", "Output as JSON").action(async (opts) => {
2700
2686
  const api = getApi();
2701
2687
  const { data, error } = await api.api.cli.v1.threads({ id: opts.thread }).comments.get();
2702
2688
  if (error)
@@ -2712,111 +2698,155 @@ var commentsCommand = new Command("comments").description("Manage comments").add
2712
2698
  created_at: c2.created_at
2713
2699
  }));
2714
2700
  output(rows, { json: false });
2715
- })).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) => {
2701
+ })).addCommand(new Command("members").description("List members of a thread").argument("<thread-id>", "Thread ID").option("--json", "Output as JSON").action(async (threadId, opts) => {
2716
2702
  const api = getApi();
2717
- const { data, error } = await api.api.cli.v1.threads({ id: opts.thread }).comments.post({ body: opts.body });
2703
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).members.get();
2718
2704
  if (error)
2719
2705
  throw error;
2720
2706
  if (opts.json) {
2721
- output(data.comment, { json: true });
2707
+ output(data.members, { json: true });
2722
2708
  return;
2723
2709
  }
2724
- console.log(`Comment added (${data.comment.id.slice(0, 8)}).`);
2725
- })).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) => {
2710
+ const rows = data.members.filter((m) => !m.revoked_at).map((m) => ({
2711
+ username: m.username,
2712
+ email: m.email
2713
+ }));
2714
+ output(rows, { json: false });
2715
+ }));
2716
+
2717
+ // src/commands/create.ts
2718
+ var createCommand2 = new Command("create").description("Create new dblebox objects").addCommand(new Command("thread").description("Create a thread").requiredOption("--title <title>", "Thread title").option("--comment <text>", "Optional first comment").option("--note <content>", "Create and attach a block note with content").option("--json", "Output as JSON").action(async (opts) => {
2726
2719
  const api = getApi();
2727
- const { data, error } = await api.api.cli.v1.comments({ id }).put({ body: opts.body });
2720
+ const noteContent = opts.note !== undefined ? opts.note : undefined;
2721
+ const { data, error } = await api.api.cli.v1.threads.post({
2722
+ body: opts.title,
2723
+ comment: opts.comment,
2724
+ note_content: noteContent
2725
+ });
2726
+ if (error)
2727
+ throw error;
2728
+ if (opts.json) {
2729
+ output(data, { json: true });
2730
+ return;
2731
+ }
2732
+ const noteSuffix = data.note ? ` (note ${data.note.id.slice(0, 8)} attached)` : "";
2733
+ console.log(`Created thread ${data.thread.id.slice(0, 8)}: ${data.thread.body}${noteSuffix}`);
2734
+ })).addCommand(new Command("comment").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) => {
2735
+ const api = getApi();
2736
+ const { data, error } = await api.api.cli.v1.threads({ id: opts.thread }).comments.post({ body: opts.body });
2728
2737
  if (error)
2729
2738
  throw error;
2730
2739
  if (opts.json) {
2731
2740
  output(data.comment, { json: true });
2732
2741
  return;
2733
2742
  }
2734
- console.log(`Comment updated (${data.comment.id.slice(0, 8)}).`);
2743
+ console.log(`Comment added (${data.comment.id.slice(0, 8)}).`);
2735
2744
  }));
2736
2745
 
2737
- // src/commands/members.ts
2738
- 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) => {
2746
+ // src/commands/set.ts
2747
+ var setCommand = new Command("set").description("Update existing dblebox objects").addCommand(new Command("thread").description("Update thread title, archive state, or snooze state").argument("<thread-id>", "Thread ID").option("--title <title>", "New thread title").option("--archived <true|false>", "Set archived state", parseBooleanish).option("--snoozed-until <datetime-or-none>", 'Set snooze until (ISO datetime), or "none" to clear').option("--json", "Output as JSON").action(async (threadId, opts) => {
2739
2748
  const api = getApi();
2740
- const { data, error } = await api.api.cli.v1.threads({ id: threadId }).members.get();
2741
- if (error)
2742
- throw error;
2749
+ const result = {};
2750
+ const messages = [];
2751
+ if (opts.title !== undefined) {
2752
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).put({
2753
+ body: opts.title
2754
+ });
2755
+ if (error)
2756
+ throw error;
2757
+ result.thread = data.thread;
2758
+ messages.push(`Updated thread ${data.thread.id.slice(0, 8)}: ${data.thread.body}`);
2759
+ }
2760
+ if (opts.archived !== undefined) {
2761
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).archive.put({
2762
+ archived: opts.archived
2763
+ });
2764
+ if (error)
2765
+ throw error;
2766
+ result.archived = data.archived;
2767
+ messages.push(data.archived ? "Archived." : "Unarchived.");
2768
+ }
2769
+ if (opts.snoozedUntil !== undefined) {
2770
+ const until = opts.snoozedUntil === "none" ? null : opts.snoozedUntil;
2771
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).snooze.put({
2772
+ until
2773
+ });
2774
+ if (error)
2775
+ throw error;
2776
+ result.snooze_until = data.snooze_until;
2777
+ messages.push(data.snooze_until ? `Snoozed until ${data.snooze_until}.` : "Unsnoozed.");
2778
+ }
2779
+ if (messages.length === 0) {
2780
+ throw new Error("No updates specified. Provide --title, --archived, or --snoozed-until.");
2781
+ }
2743
2782
  if (opts.json) {
2744
- output(data.members, { json: true });
2783
+ output(result, { json: true });
2745
2784
  return;
2746
2785
  }
2747
- const rows = data.members.filter((m) => !m.revoked_at).map((m) => ({
2748
- username: m.username,
2749
- email: m.email
2750
- }));
2751
- output(rows, { json: false });
2752
- })).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) => {
2786
+ for (const message of messages) {
2787
+ console.log(message);
2788
+ }
2789
+ })).addCommand(new Command("thread-note").description("Create or update a thread note").argument("<thread-id>", "Thread ID").requiredOption("--content <content>", "Note content").option("--json", "Output as JSON").action(async (threadId, opts) => {
2753
2790
  const api = getApi();
2754
- const { data, error } = await api.api.cli.v1.threads({ id: threadId }).members.post({ user: opts.user });
2791
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).note.put({ content: opts.content });
2755
2792
  if (error)
2756
2793
  throw error;
2757
- if (data.invited) {
2758
- console.log(`Invited ${data.user?.username || opts.user}.`);
2759
- } else {
2760
- console.log(data.reason || "Could not invite user.");
2794
+ if (opts.json) {
2795
+ output(data, { json: true });
2796
+ return;
2761
2797
  }
2762
- }));
2763
-
2764
- // src/commands/today.ts
2765
- function localDate(dateArg) {
2766
- if (dateArg)
2767
- return dateArg;
2768
- const now = new Date;
2769
- const y = now.getFullYear();
2770
- const m = String(now.getMonth() + 1).padStart(2, "0");
2771
- const d2 = String(now.getDate()).padStart(2, "0");
2772
- return `${y}-${m}-${d2}`;
2773
- }
2774
- var todayCommand = new Command("today").description("Today view — threads and daily note").enablePositionalOptions().passThroughOptions().option("--date <date>", "Date (YYYY-MM-DD)").option("--json", "Output as JSON").action(async (opts) => {
2798
+ console.log("Note updated.");
2799
+ })).addCommand(new Command("today-note").description("Create or update a daily note").requiredOption("--content <content>", "Note content").option("--date <date>", "Date (YYYY-MM-DD)").option("--json", "Output as JSON").action(async (opts) => {
2775
2800
  const date = localDate(opts.date);
2776
2801
  const api = getApi();
2777
- const { data, error } = await api.api.cli.v1.today.get({
2778
- query: { date }
2779
- });
2802
+ const { data, error } = await api.api.cli.v1.today.note.put({ content: opts.content }, { query: { date } });
2780
2803
  if (error)
2781
2804
  throw error;
2782
2805
  if (opts.json) {
2783
2806
  output(data, { json: true });
2784
2807
  return;
2785
2808
  }
2786
- console.log(`Date: ${data.date}
2787
- `);
2788
- if (data.threads.length > 0) {
2789
- console.log("Threads:");
2790
- for (const t of data.threads) {
2791
- console.log(` ${t.id.slice(0, 8)} ${t.body}`);
2792
- }
2793
- console.log();
2794
- } else {
2795
- console.log(`No threads for this date.
2796
- `);
2809
+ console.log("Note updated.");
2810
+ })).addCommand(new Command("comment").description("Edit a comment").argument("<comment-id>", "Comment ID").requiredOption("--body <text>", "New comment text").option("--json", "Output as JSON").action(async (commentId, opts) => {
2811
+ const api = getApi();
2812
+ const { data, error } = await api.api.cli.v1.comments({ id: commentId }).put({ body: opts.body });
2813
+ if (error)
2814
+ throw error;
2815
+ if (opts.json) {
2816
+ output(data.comment, { json: true });
2817
+ return;
2797
2818
  }
2798
- if (data.note) {
2799
- console.log("Note:");
2800
- console.log(data.note.content || "(empty)");
2801
- } else {
2802
- console.log("No daily note.");
2819
+ console.log(`Comment updated (${data.comment.id.slice(0, 8)}).`);
2820
+ })).addCommand(new Command("thread-parent").description("Set a thread parent").argument("<thread-id>", "Thread ID").requiredOption("--parent <parent-id>", "Parent thread ID").option("--json", "Output as JSON").action(async (threadId, opts) => {
2821
+ const api = getApi();
2822
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).parent.put({
2823
+ parent_id: opts.parent
2824
+ });
2825
+ if (error)
2826
+ throw error;
2827
+ if (opts.json) {
2828
+ output(data.thread, { json: true });
2829
+ return;
2803
2830
  }
2804
- }).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) => {
2831
+ console.log(`Parent set to ${opts.parent.slice(0, 8)}.`);
2832
+ })).addCommand(new Command("thread-today").description("Assign or remove a thread from a date").argument("<thread-id>", "Thread ID").option("--date <date>", "Date (YYYY-MM-DD)").option("--remove", "Remove instead of assign").option("--json", "Output as JSON").action(async (threadId, opts) => {
2805
2833
  const date = localDate(opts.date);
2806
2834
  const api = getApi();
2807
- if (opts.set !== undefined) {
2808
- const { data: data2, error: error2 } = await api.api.cli.v1.today.note.put({ content: opts.set }, { query: { date } });
2835
+ if (opts.remove) {
2836
+ const { data: data2, error: error2 } = await api.api.cli.v1.threads({ id: threadId }).today.delete({
2837
+ date
2838
+ });
2809
2839
  if (error2)
2810
2840
  throw error2;
2811
2841
  if (opts.json) {
2812
2842
  output(data2, { json: true });
2813
2843
  return;
2814
2844
  }
2815
- console.log("Note updated.");
2845
+ console.log(`Removed from ${date}.`);
2816
2846
  return;
2817
2847
  }
2818
- const { data, error } = await api.api.cli.v1.today.note.get({
2819
- query: { date }
2848
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).today.put({
2849
+ date
2820
2850
  });
2821
2851
  if (error)
2822
2852
  throw error;
@@ -2824,16 +2854,29 @@ var todayCommand = new Command("today").description("Today view — threads and
2824
2854
  output(data, { json: true });
2825
2855
  return;
2826
2856
  }
2827
- if (!data.note) {
2828
- console.log("No daily note.");
2857
+ console.log(`Assigned to ${date}.`);
2858
+ }));
2859
+
2860
+ // src/commands/invite.ts
2861
+ var inviteCommand = new Command("invite").description("Invite collaborators").addCommand(new Command("member").description("Invite a user to a thread").argument("<thread-id>", "Thread ID").requiredOption("--user <email-or-username>", "User email or username").option("--json", "Output as JSON").action(async (threadId, opts) => {
2862
+ const api = getApi();
2863
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).members.post({ user: opts.user });
2864
+ if (error)
2865
+ throw error;
2866
+ if (opts.json) {
2867
+ output(data, { json: true });
2829
2868
  return;
2830
2869
  }
2831
- console.log(data.note.content || "(empty)");
2870
+ if (data.invited) {
2871
+ console.log(`Invited ${data.user?.username || opts.user}.`);
2872
+ } else {
2873
+ console.log(data.reason || "Could not invite user.");
2874
+ }
2832
2875
  }));
2833
2876
  // package.json
2834
2877
  var package_default = {
2835
2878
  name: "dblx",
2836
- version: "0.1.50",
2879
+ version: "0.1.63",
2837
2880
  description: "CLI for dblebox — thread-first communication",
2838
2881
  type: "module",
2839
2882
  bin: {
@@ -2860,10 +2903,10 @@ var package_default = {
2860
2903
  // src/index.ts
2861
2904
  var program2 = new Command().name("dblx").description("CLI for dblebox — thread-first communication").version(package_default.version).enablePositionalOptions();
2862
2905
  program2.addCommand(authCommand);
2863
- program2.addCommand(threadsCommand);
2864
- program2.addCommand(commentsCommand);
2865
- program2.addCommand(membersCommand);
2866
- program2.addCommand(todayCommand);
2906
+ program2.addCommand(getCommand);
2907
+ program2.addCommand(createCommand2);
2908
+ program2.addCommand(setCommand);
2909
+ program2.addCommand(inviteCommand);
2867
2910
  program2.parseAsync().catch((err) => {
2868
2911
  console.error(err.message);
2869
2912
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dblx",
3
- "version": "0.1.50",
3
+ "version": "0.1.63",
4
4
  "description": "CLI for dblebox — thread-first communication",
5
5
  "type": "module",
6
6
  "bin": {