dblx 0.1.50 → 0.1.64

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 +122 -42
  2. package/dist/index.js +445 -359
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -4,81 +4,161 @@ 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]
7
11
  ```
8
- bunx dblx <command>
12
+
13
+ Examples:
14
+
15
+ ```bash
16
+ dblx get threads
17
+ dblx get threads <thread-id>
18
+ dblx get threads --q "planning"
19
+ dblx get today
20
+ dblx create thread --title "New thread"
21
+ dblx set thread 12345678 --title "Renamed"
22
+ ```
23
+
24
+ ## Command Model
25
+
26
+ Read operations use `get`:
27
+
28
+ ```bash
29
+ dblx get ...
30
+ ```
31
+
32
+ Write operations use `create`, `set`, and `invite`:
33
+
34
+ ```bash
35
+ dblx create ...
36
+ dblx set ...
37
+ dblx invite ...
9
38
  ```
10
39
 
40
+ This keeps permission boundaries clear for agents and automation. A tool can be granted `dblx get ...` without also gaining write access.
41
+
11
42
  ## Authentication
12
43
 
13
44
  Generate an API key from **Settings > API Keys** in the dblebox web app, then:
14
45
 
15
- ```
46
+ ```bash
16
47
  dblx auth login
17
48
  ```
18
49
 
19
50
  You'll be prompted for your key (starts with `dblx_`). Credentials are saved to `~/.config/dblx.json`.
20
51
 
21
- ```
22
- dblx auth whoami # show current user
23
- dblx auth logout # remove saved credentials
52
+ ```bash
53
+ dblx auth whoami
54
+ dblx auth logout
24
55
  ```
25
56
 
26
57
  You can also set `DBLEBOX_API_KEY` and `DBLEBOX_API_URL` environment variables instead of using `auth login`.
27
58
 
28
- ## Threads
59
+ ## Read Commands
60
+
61
+ ### Threads
29
62
 
63
+ ```bash
64
+ dblx get threads
65
+ dblx get threads <thread-id>
66
+ dblx get threads --archived
67
+ dblx get threads --snoozed
68
+ dblx get threads --archived --snoozed
69
+ dblx get threads --q "plan"
70
+ dblx get threads --q "#dblebox" --archived --snoozed
30
71
  ```
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>
72
+
73
+ ### Get All Thread Content, Including Comments and Notes
74
+
75
+ ```bash
76
+ dblx get threads <thread-id>
50
77
  ```
51
78
 
52
- ## Comments
79
+ ### Today
53
80
 
81
+ ```bash
82
+ dblx get today
83
+ dblx get today --date 2026-03-01
54
84
  ```
55
- dblx comments list --thread <id>
56
- dblx comments add --thread <id> --body "Hello"
57
- dblx comments edit <comment-id> --body "Updated text"
85
+
86
+ ### Notes
87
+
88
+ ```bash
89
+ dblx get thread-note <thread-id>
90
+ dblx get today-note
91
+ dblx get today-note --date 2026-03-01
58
92
  ```
59
93
 
60
- ## Members
94
+ ### Comments
61
95
 
96
+ ```bash
97
+ dblx get comments --thread <thread-id>
62
98
  ```
63
- dblx members list <thread-id>
64
- dblx members invite <thread-id> --user alice@example.com
99
+
100
+ ### Members
101
+
102
+ ```bash
103
+ dblx get members <thread-id>
65
104
  ```
66
105
 
67
- ## Today
106
+ ## Write Commands
107
+
108
+ ### Threads
68
109
 
110
+ ```bash
111
+ dblx create thread --title "New thread"
112
+ dblx create thread --title "..." --comment "First message"
113
+ dblx create thread --title "..." --note "Draft spec..."
114
+
115
+ dblx set thread <thread-id> --title "New title"
116
+ dblx set thread <thread-id> --archived true
117
+ dblx set thread <thread-id> --archived false
118
+ dblx set thread <thread-id> --snoozed-until 2026-03-01T09:00:00
119
+ dblx set thread <thread-id> --snoozed-until none
69
120
  ```
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
121
+
122
+ ### Notes
123
+
124
+ Reading and writing notes are separate commands.
125
+
126
+ ```bash
127
+ dblx set thread-note <thread-id> --content "Updated note"
128
+ dblx set today-note --content "My note"
129
+ dblx set today-note --date 2026-03-01 --content "My note"
75
130
  ```
76
131
 
77
- ## JSON output
132
+ ### Relationships
78
133
 
79
- All read commands support `--json` for machine-readable output:
134
+ ```bash
135
+ dblx set thread-parent <thread-id> --parent <parent-id>
136
+ dblx set thread-today <thread-id> --date 2026-03-01
137
+ dblx set thread-today <thread-id> --remove
138
+ dblx set thread-today <thread-id> --date 2026-03-01 --remove
139
+ ```
80
140
 
141
+ ### Comments
142
+
143
+ ```bash
144
+ dblx create comment --thread <thread-id> --body "Hello"
145
+ dblx set comment <comment-id> --body "Updated text"
146
+ ```
147
+
148
+ ### Members
149
+
150
+ ```bash
151
+ dblx invite member <thread-id> --user alice@example.com
81
152
  ```
82
- dblx threads list --json
83
- dblx today --json
153
+
154
+ ## JSON Output
155
+
156
+ All read commands support `--json` for machine-readable output:
157
+
158
+ ```bash
159
+ dblx get threads --json
160
+ dblx get threads <thread-id> --json
161
+ dblx get threads --q "plan" --json
162
+ dblx get today --json
163
+ dblx get thread-note <thread-id> --json
84
164
  ```
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);
2314
+ }
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);
2309
2319
  }
2310
- yield f;
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 }));
2434
2461
  }
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 };
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;
2466
+ }
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,26 +2587,72 @@ 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
+ function relatedThreadLabel(thread) {
2609
+ return `${thread.thread.id.slice(0, 8)} ${thread.thread.body}`;
2610
+ }
2611
+ var getCommand = new Command("get").description("Read data from dblebox").addCommand(new Command("threads").description("List or search your threads").argument("[thread-id]", "Thread ID").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 (threadId, opts) => {
2557
2612
  const api = getApi();
2558
- const { data, error } = await api.api.cli.v1.threads.get({
2559
- query: {
2560
- archived: opts.archived ? "true" : undefined,
2561
- snoozed: opts.snoozed ? "true" : undefined
2613
+ if (threadId) {
2614
+ if (opts.q || opts.archived || opts.snoozed) {
2615
+ throw new Error("Thread lookup does not support --q, --archived, or --snoozed.");
2616
+ }
2617
+ const { data: data2, error: error2 } = await api.api.cli.v1.threads({ id: threadId }).get();
2618
+ if (error2)
2619
+ throw error2;
2620
+ if (opts.json) {
2621
+ output(data2, { json: true });
2622
+ return;
2623
+ }
2624
+ console.log(`Thread: ${data2.thread.body}`);
2625
+ console.log(`ID: ${data2.thread.id}`);
2626
+ console.log(`Created: ${data2.thread.created_at}`);
2627
+ console.log(`
2628
+ Note:`);
2629
+ console.log(data2.note ? data2.note.content || "(empty)" : "(none)");
2630
+ console.log(`
2631
+ Comments:`);
2632
+ if (data2.comments.length === 0) {
2633
+ console.log("(none)");
2634
+ } else {
2635
+ for (const comment of data2.comments) {
2636
+ console.log(`- [${comment.created_at}] @${comment.creator_username}: ${comment.body}`);
2637
+ }
2638
+ }
2639
+ console.log(`
2640
+ Parent:`);
2641
+ console.log(data2.parent_thread ? relatedThreadLabel(data2.parent_thread) : "(none)");
2642
+ console.log(`
2643
+ Children:`);
2644
+ if (data2.child_threads.length === 0) {
2645
+ console.log("(none)");
2646
+ } else {
2647
+ for (const child of data2.child_threads) {
2648
+ console.log(`- ${relatedThreadLabel(child)}`);
2649
+ }
2562
2650
  }
2563
- });
2564
- if (error)
2565
- throw error;
2566
- if (opts.json) {
2567
- output(data.threads, { json: true });
2568
2651
  return;
2569
2652
  }
2570
- 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) => {
2572
- const api = getApi();
2573
2653
  const { data, error } = await api.api.cli.v1.threads.get({
2574
2654
  query: {
2575
- q: query,
2655
+ q: opts.q,
2576
2656
  archived: opts.archived ? "true" : undefined,
2577
2657
  snoozed: opts.snoozed ? "true" : undefined
2578
2658
  }
@@ -2584,13 +2664,11 @@ var threadsCommand = new Command("threads").description("Manage threads").addCom
2584
2664
  return;
2585
2665
  }
2586
2666
  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) => {
2667
+ })).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) => {
2668
+ const date = localDate(opts.date);
2588
2669
  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
2670
+ const { data, error } = await api.api.cli.v1.today.get({
2671
+ query: { date }
2594
2672
  });
2595
2673
  if (error)
2596
2674
  throw error;
@@ -2598,34 +2676,44 @@ var threadsCommand = new Command("threads").description("Manage threads").addCom
2598
2676
  output(data, { json: true });
2599
2677
  return;
2600
2678
  }
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) => {
2679
+ console.log(`Date: ${data.date}
2680
+ `);
2681
+ if (data.threads.length > 0) {
2682
+ console.log("Threads:");
2683
+ for (const t of data.threads) {
2684
+ console.log(` ${t.id.slice(0, 8)} ${t.body}`);
2685
+ }
2686
+ console.log();
2687
+ } else {
2688
+ console.log(`No threads for this date.
2689
+ `);
2690
+ }
2691
+ if (data.note) {
2692
+ console.log("Note:");
2693
+ console.log(data.note.content || "(empty)");
2694
+ } else {
2695
+ console.log("No daily note.");
2696
+ }
2697
+ })).addCommand(new Command("thread-note").description("Read a thread note").argument("<thread-id>", "Thread ID").option("--json", "Output as JSON").action(async (threadId, opts) => {
2604
2698
  const api = getApi();
2605
- const { data, error } = await api.api.cli.v1.threads({ id }).put({
2606
- body: opts.title
2607
- });
2699
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).note.get();
2608
2700
  if (error)
2609
2701
  throw error;
2610
2702
  if (opts.json) {
2611
- output(data.thread, { json: true });
2703
+ output(data, { json: true });
2612
2704
  return;
2613
2705
  }
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) => {
2616
- 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.");
2706
+ if (!data.note) {
2707
+ console.log("No thread note.");
2626
2708
  return;
2627
2709
  }
2628
- const { data, error } = await api.api.cli.v1.threads({ id }).note.get();
2710
+ console.log(data.note.content || "(empty)");
2711
+ })).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) => {
2712
+ const date = localDate(opts.date);
2713
+ const api = getApi();
2714
+ const { data, error } = await api.api.cli.v1.today.note.get({
2715
+ query: { date }
2716
+ });
2629
2717
  if (error)
2630
2718
  throw error;
2631
2719
  if (opts.json) {
@@ -2633,70 +2721,11 @@ var threadsCommand = new Command("threads").description("Manage threads").addCom
2633
2721
  return;
2634
2722
  }
2635
2723
  if (!data.note) {
2636
- console.log("No thread note.");
2724
+ console.log("No daily note.");
2637
2725
  return;
2638
2726
  }
2639
2727
  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) => {
2728
+ })).addCommand(new Command("comments").description("List comments in a thread").requiredOption("--thread <id>", "Thread ID").option("--json", "Output as JSON").action(async (opts) => {
2700
2729
  const api = getApi();
2701
2730
  const { data, error } = await api.api.cli.v1.threads({ id: opts.thread }).comments.get();
2702
2731
  if (error)
@@ -2712,111 +2741,155 @@ var commentsCommand = new Command("comments").description("Manage comments").add
2712
2741
  created_at: c2.created_at
2713
2742
  }));
2714
2743
  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) => {
2744
+ })).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
2745
  const api = getApi();
2717
- const { data, error } = await api.api.cli.v1.threads({ id: opts.thread }).comments.post({ body: opts.body });
2746
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).members.get();
2718
2747
  if (error)
2719
2748
  throw error;
2720
2749
  if (opts.json) {
2721
- output(data.comment, { json: true });
2750
+ output(data.members, { json: true });
2722
2751
  return;
2723
2752
  }
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) => {
2753
+ const rows = data.members.filter((m) => !m.revoked_at).map((m) => ({
2754
+ username: m.username,
2755
+ email: m.email
2756
+ }));
2757
+ output(rows, { json: false });
2758
+ }));
2759
+
2760
+ // src/commands/create.ts
2761
+ 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
2762
  const api = getApi();
2727
- const { data, error } = await api.api.cli.v1.comments({ id }).put({ body: opts.body });
2763
+ const noteContent = opts.note !== undefined ? opts.note : undefined;
2764
+ const { data, error } = await api.api.cli.v1.threads.post({
2765
+ body: opts.title,
2766
+ comment: opts.comment,
2767
+ note_content: noteContent
2768
+ });
2769
+ if (error)
2770
+ throw error;
2771
+ if (opts.json) {
2772
+ output(data, { json: true });
2773
+ return;
2774
+ }
2775
+ const noteSuffix = data.note ? ` (note ${data.note.id.slice(0, 8)} attached)` : "";
2776
+ console.log(`Created thread ${data.thread.id.slice(0, 8)}: ${data.thread.body}${noteSuffix}`);
2777
+ })).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) => {
2778
+ const api = getApi();
2779
+ const { data, error } = await api.api.cli.v1.threads({ id: opts.thread }).comments.post({ body: opts.body });
2728
2780
  if (error)
2729
2781
  throw error;
2730
2782
  if (opts.json) {
2731
2783
  output(data.comment, { json: true });
2732
2784
  return;
2733
2785
  }
2734
- console.log(`Comment updated (${data.comment.id.slice(0, 8)}).`);
2786
+ console.log(`Comment added (${data.comment.id.slice(0, 8)}).`);
2735
2787
  }));
2736
2788
 
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) => {
2789
+ // src/commands/set.ts
2790
+ 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
2791
  const api = getApi();
2740
- const { data, error } = await api.api.cli.v1.threads({ id: threadId }).members.get();
2741
- if (error)
2742
- throw error;
2792
+ const result = {};
2793
+ const messages = [];
2794
+ if (opts.title !== undefined) {
2795
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).put({
2796
+ body: opts.title
2797
+ });
2798
+ if (error)
2799
+ throw error;
2800
+ result.thread = data.thread;
2801
+ messages.push(`Updated thread ${data.thread.id.slice(0, 8)}: ${data.thread.body}`);
2802
+ }
2803
+ if (opts.archived !== undefined) {
2804
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).archive.put({
2805
+ archived: opts.archived
2806
+ });
2807
+ if (error)
2808
+ throw error;
2809
+ result.archived = data.archived;
2810
+ messages.push(data.archived ? "Archived." : "Unarchived.");
2811
+ }
2812
+ if (opts.snoozedUntil !== undefined) {
2813
+ const until = opts.snoozedUntil === "none" ? null : opts.snoozedUntil;
2814
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).snooze.put({
2815
+ until
2816
+ });
2817
+ if (error)
2818
+ throw error;
2819
+ result.snooze_until = data.snooze_until;
2820
+ messages.push(data.snooze_until ? `Snoozed until ${data.snooze_until}.` : "Unsnoozed.");
2821
+ }
2822
+ if (messages.length === 0) {
2823
+ throw new Error("No updates specified. Provide --title, --archived, or --snoozed-until.");
2824
+ }
2743
2825
  if (opts.json) {
2744
- output(data.members, { json: true });
2826
+ output(result, { json: true });
2745
2827
  return;
2746
2828
  }
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) => {
2829
+ for (const message of messages) {
2830
+ console.log(message);
2831
+ }
2832
+ })).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
2833
  const api = getApi();
2754
- const { data, error } = await api.api.cli.v1.threads({ id: threadId }).members.post({ user: opts.user });
2834
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).note.put({ content: opts.content });
2755
2835
  if (error)
2756
2836
  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.");
2837
+ if (opts.json) {
2838
+ output(data, { json: true });
2839
+ return;
2761
2840
  }
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) => {
2841
+ console.log("Note updated.");
2842
+ })).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
2843
  const date = localDate(opts.date);
2776
2844
  const api = getApi();
2777
- const { data, error } = await api.api.cli.v1.today.get({
2778
- query: { date }
2779
- });
2845
+ const { data, error } = await api.api.cli.v1.today.note.put({ content: opts.content }, { query: { date } });
2780
2846
  if (error)
2781
2847
  throw error;
2782
2848
  if (opts.json) {
2783
2849
  output(data, { json: true });
2784
2850
  return;
2785
2851
  }
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
- `);
2852
+ console.log("Note updated.");
2853
+ })).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) => {
2854
+ const api = getApi();
2855
+ const { data, error } = await api.api.cli.v1.comments({ id: commentId }).put({ body: opts.body });
2856
+ if (error)
2857
+ throw error;
2858
+ if (opts.json) {
2859
+ output(data.comment, { json: true });
2860
+ return;
2797
2861
  }
2798
- if (data.note) {
2799
- console.log("Note:");
2800
- console.log(data.note.content || "(empty)");
2801
- } else {
2802
- console.log("No daily note.");
2862
+ console.log(`Comment updated (${data.comment.id.slice(0, 8)}).`);
2863
+ })).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) => {
2864
+ const api = getApi();
2865
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).parent.put({
2866
+ parent_id: opts.parent
2867
+ });
2868
+ if (error)
2869
+ throw error;
2870
+ if (opts.json) {
2871
+ output(data.thread, { json: true });
2872
+ return;
2803
2873
  }
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) => {
2874
+ console.log(`Parent set to ${opts.parent.slice(0, 8)}.`);
2875
+ })).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
2876
  const date = localDate(opts.date);
2806
2877
  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 } });
2878
+ if (opts.remove) {
2879
+ const { data: data2, error: error2 } = await api.api.cli.v1.threads({ id: threadId }).today.delete({
2880
+ date
2881
+ });
2809
2882
  if (error2)
2810
2883
  throw error2;
2811
2884
  if (opts.json) {
2812
2885
  output(data2, { json: true });
2813
2886
  return;
2814
2887
  }
2815
- console.log("Note updated.");
2888
+ console.log(`Removed from ${date}.`);
2816
2889
  return;
2817
2890
  }
2818
- const { data, error } = await api.api.cli.v1.today.note.get({
2819
- query: { date }
2891
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).today.put({
2892
+ date
2820
2893
  });
2821
2894
  if (error)
2822
2895
  throw error;
@@ -2824,16 +2897,29 @@ var todayCommand = new Command("today").description("Today view — threads and
2824
2897
  output(data, { json: true });
2825
2898
  return;
2826
2899
  }
2827
- if (!data.note) {
2828
- console.log("No daily note.");
2900
+ console.log(`Assigned to ${date}.`);
2901
+ }));
2902
+
2903
+ // src/commands/invite.ts
2904
+ 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) => {
2905
+ const api = getApi();
2906
+ const { data, error } = await api.api.cli.v1.threads({ id: threadId }).members.post({ user: opts.user });
2907
+ if (error)
2908
+ throw error;
2909
+ if (opts.json) {
2910
+ output(data, { json: true });
2829
2911
  return;
2830
2912
  }
2831
- console.log(data.note.content || "(empty)");
2913
+ if (data.invited) {
2914
+ console.log(`Invited ${data.user?.username || opts.user}.`);
2915
+ } else {
2916
+ console.log(data.reason || "Could not invite user.");
2917
+ }
2832
2918
  }));
2833
2919
  // package.json
2834
2920
  var package_default = {
2835
2921
  name: "dblx",
2836
- version: "0.1.50",
2922
+ version: "0.1.64",
2837
2923
  description: "CLI for dblebox — thread-first communication",
2838
2924
  type: "module",
2839
2925
  bin: {
@@ -2860,10 +2946,10 @@ var package_default = {
2860
2946
  // src/index.ts
2861
2947
  var program2 = new Command().name("dblx").description("CLI for dblebox — thread-first communication").version(package_default.version).enablePositionalOptions();
2862
2948
  program2.addCommand(authCommand);
2863
- program2.addCommand(threadsCommand);
2864
- program2.addCommand(commentsCommand);
2865
- program2.addCommand(membersCommand);
2866
- program2.addCommand(todayCommand);
2949
+ program2.addCommand(getCommand);
2950
+ program2.addCommand(createCommand2);
2951
+ program2.addCommand(setCommand);
2952
+ program2.addCommand(inviteCommand);
2867
2953
  program2.parseAsync().catch((err) => {
2868
2954
  console.error(err.message);
2869
2955
  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.64",
4
4
  "description": "CLI for dblebox — thread-first communication",
5
5
  "type": "module",
6
6
  "bin": {