dblx 0.1.49 → 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.
- package/README.md +113 -37
- package/dist/index.js +442 -342
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,76 +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
|
-
|
|
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
|
|
23
|
-
dblx auth logout
|
|
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
|
-
##
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
dblx
|
|
36
|
-
dblx threads update <id> --title "New title"
|
|
37
|
-
dblx threads archive <id>
|
|
38
|
-
dblx threads unarchive <id>
|
|
39
|
-
dblx threads snooze <id> --until 2026-03-01T09:00:00
|
|
40
|
-
dblx threads unsnooze <id>
|
|
41
|
-
dblx threads set-parent <id> --parent <parent-id>
|
|
42
|
-
dblx threads set-today <id> # assign to today
|
|
43
|
-
dblx threads set-today <id> --date 2026-03-01
|
|
44
|
-
dblx threads unset-today <id>
|
|
85
|
+
|
|
86
|
+
### Comments
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
dblx get comments --thread <thread-id>
|
|
45
90
|
```
|
|
46
91
|
|
|
47
|
-
|
|
92
|
+
### Members
|
|
48
93
|
|
|
94
|
+
```bash
|
|
95
|
+
dblx get members <thread-id>
|
|
49
96
|
```
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
|
53
112
|
```
|
|
54
113
|
|
|
55
|
-
|
|
114
|
+
### Notes
|
|
56
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"
|
|
57
122
|
```
|
|
58
|
-
|
|
59
|
-
|
|
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
|
|
60
131
|
```
|
|
61
132
|
|
|
62
|
-
|
|
133
|
+
### Comments
|
|
63
134
|
|
|
135
|
+
```bash
|
|
136
|
+
dblx create comment --thread <thread-id> --body "Hello"
|
|
137
|
+
dblx set comment <comment-id> --body "Updated text"
|
|
64
138
|
```
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
dblx
|
|
139
|
+
|
|
140
|
+
### Members
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
dblx invite member <thread-id> --user alice@example.com
|
|
70
144
|
```
|
|
71
145
|
|
|
72
|
-
## JSON
|
|
146
|
+
## JSON Output
|
|
73
147
|
|
|
74
148
|
All read commands support `--json` for machine-readable output:
|
|
75
149
|
|
|
76
|
-
```
|
|
77
|
-
dblx threads
|
|
78
|
-
dblx
|
|
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
|
|
79
155
|
```
|
package/dist/index.js
CHANGED
|
@@ -2088,21 +2088,32 @@ function getConfigPath() {
|
|
|
2088
2088
|
}
|
|
2089
2089
|
function loadConfig() {
|
|
2090
2090
|
const envKey = process.env.DBLEBOX_API_KEY;
|
|
2091
|
+
const envUrl = process.env.DBLEBOX_API_URL;
|
|
2091
2092
|
if (envKey) {
|
|
2092
2093
|
return {
|
|
2093
2094
|
api_key: envKey,
|
|
2094
|
-
api_url:
|
|
2095
|
+
api_url: envUrl || DEFAULT_API_URL
|
|
2095
2096
|
};
|
|
2096
2097
|
}
|
|
2097
|
-
|
|
2098
|
-
|
|
2098
|
+
let fileConfig = null;
|
|
2099
|
+
if (existsSync(configPath)) {
|
|
2100
|
+
try {
|
|
2101
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
2102
|
+
fileConfig = JSON.parse(raw);
|
|
2103
|
+
} catch {
|
|
2104
|
+
return null;
|
|
2105
|
+
}
|
|
2099
2106
|
}
|
|
2100
|
-
|
|
2101
|
-
const raw = readFileSync(configPath, "utf-8");
|
|
2102
|
-
return JSON.parse(raw);
|
|
2103
|
-
} catch {
|
|
2107
|
+
if (!fileConfig) {
|
|
2104
2108
|
return null;
|
|
2105
2109
|
}
|
|
2110
|
+
if (envUrl) {
|
|
2111
|
+
return {
|
|
2112
|
+
api_key: fileConfig.api_key,
|
|
2113
|
+
api_url: envUrl
|
|
2114
|
+
};
|
|
2115
|
+
}
|
|
2116
|
+
return fileConfig;
|
|
2106
2117
|
}
|
|
2107
2118
|
function saveConfig(config) {
|
|
2108
2119
|
const dir = join(configPath, "..");
|
|
@@ -2116,62 +2127,64 @@ function deleteConfig() {
|
|
|
2116
2127
|
}
|
|
2117
2128
|
}
|
|
2118
2129
|
|
|
2119
|
-
// ../node_modules/@elysiajs/eden/dist/chunk-
|
|
2120
|
-
var
|
|
2121
|
-
constructor(e,
|
|
2122
|
-
super(
|
|
2130
|
+
// ../node_modules/@elysiajs/eden/dist/chunk-I5KHAGLL.mjs
|
|
2131
|
+
var d = class extends Error {
|
|
2132
|
+
constructor(e, s) {
|
|
2133
|
+
super(s + "");
|
|
2123
2134
|
this.status = e;
|
|
2124
|
-
this.value =
|
|
2135
|
+
this.value = s;
|
|
2125
2136
|
}
|
|
2126
2137
|
};
|
|
2127
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))/;
|
|
2128
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\([^)]+\)/;
|
|
2129
|
-
var
|
|
2130
|
-
var
|
|
2131
|
-
var
|
|
2132
|
-
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)
|
|
2133
2144
|
return null;
|
|
2134
|
-
let
|
|
2135
|
-
if (i.test(
|
|
2136
|
-
let
|
|
2137
|
-
if (!Number.isNaN(
|
|
2138
|
-
return
|
|
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;
|
|
2139
2150
|
}
|
|
2140
2151
|
return null;
|
|
2141
2152
|
};
|
|
2142
|
-
var
|
|
2153
|
+
var p = (t) => {
|
|
2143
2154
|
let r = t.charCodeAt(0), e = t.charCodeAt(t.length - 1);
|
|
2144
2155
|
return r === 123 && e === 125 || r === 91 && e === 93;
|
|
2145
2156
|
};
|
|
2146
|
-
var
|
|
2147
|
-
let n =
|
|
2148
|
-
return n ||
|
|
2157
|
+
var f = (t, r) => JSON.parse(t, (e, s) => {
|
|
2158
|
+
let n = a(s, r);
|
|
2159
|
+
return n || s;
|
|
2149
2160
|
});
|
|
2150
|
-
var g = (t) => {
|
|
2161
|
+
var g = (t, r) => {
|
|
2151
2162
|
if (!t)
|
|
2152
2163
|
return t;
|
|
2153
|
-
if (
|
|
2164
|
+
if (c(t))
|
|
2154
2165
|
return +t;
|
|
2155
2166
|
if (t === "true")
|
|
2156
2167
|
return true;
|
|
2157
2168
|
if (t === "false")
|
|
2158
2169
|
return false;
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2170
|
+
if (r?.parseDate !== false) {
|
|
2171
|
+
let e = a(t, r);
|
|
2172
|
+
if (e)
|
|
2173
|
+
return e;
|
|
2174
|
+
}
|
|
2175
|
+
if (p(t))
|
|
2163
2176
|
try {
|
|
2164
|
-
return
|
|
2177
|
+
return f(t, r);
|
|
2165
2178
|
} catch {}
|
|
2166
2179
|
return t;
|
|
2167
2180
|
};
|
|
2168
|
-
var S = (t) => {
|
|
2169
|
-
let
|
|
2170
|
-
return
|
|
2181
|
+
var S = (t, r) => {
|
|
2182
|
+
let e = t.data.toString();
|
|
2183
|
+
return e === "null" ? null : g(e, r);
|
|
2171
2184
|
};
|
|
2172
2185
|
|
|
2173
|
-
// ../node_modules/@elysiajs/eden/dist/chunk-
|
|
2174
|
-
var
|
|
2186
|
+
// ../node_modules/@elysiajs/eden/dist/chunk-AB4FCYGG.mjs
|
|
2187
|
+
var W = class {
|
|
2175
2188
|
constructor(t) {
|
|
2176
2189
|
this.url = t;
|
|
2177
2190
|
this.ws = new WebSocket(t);
|
|
@@ -2180,253 +2193,283 @@ var F = class {
|
|
|
2180
2193
|
send(t) {
|
|
2181
2194
|
return Array.isArray(t) ? (t.forEach((n) => this.send(n)), this) : (this.ws.send(typeof t == "object" ? JSON.stringify(t) : t.toString()), this);
|
|
2182
2195
|
}
|
|
2183
|
-
on(t, n,
|
|
2184
|
-
return this.addEventListener(t, n,
|
|
2196
|
+
on(t, n, r) {
|
|
2197
|
+
return this.addEventListener(t, n, r);
|
|
2185
2198
|
}
|
|
2186
|
-
off(t, n,
|
|
2187
|
-
return this.ws.removeEventListener(t, n,
|
|
2199
|
+
off(t, n, r) {
|
|
2200
|
+
return this.ws.removeEventListener(t, n, r), this;
|
|
2188
2201
|
}
|
|
2189
2202
|
subscribe(t, n) {
|
|
2190
2203
|
return this.addEventListener("message", t, n);
|
|
2191
2204
|
}
|
|
2192
|
-
addEventListener(t, n,
|
|
2193
|
-
return this.ws.addEventListener(t, (
|
|
2205
|
+
addEventListener(t, n, r) {
|
|
2206
|
+
return this.ws.addEventListener(t, (c2) => {
|
|
2194
2207
|
if (t === "message") {
|
|
2195
|
-
let
|
|
2196
|
-
n({ ...
|
|
2208
|
+
let i2 = S(c2);
|
|
2209
|
+
n({ ...c2, data: i2 });
|
|
2197
2210
|
} else
|
|
2198
|
-
n(
|
|
2199
|
-
},
|
|
2211
|
+
n(c2);
|
|
2212
|
+
}, r), this;
|
|
2200
2213
|
}
|
|
2201
|
-
removeEventListener(t, n,
|
|
2202
|
-
return this.off(t, n,
|
|
2214
|
+
removeEventListener(t, n, r) {
|
|
2215
|
+
return this.off(t, n, r), this;
|
|
2203
2216
|
}
|
|
2204
2217
|
close() {
|
|
2205
2218
|
return this.ws.close(), this;
|
|
2206
2219
|
}
|
|
2207
2220
|
};
|
|
2208
|
-
var
|
|
2209
|
-
var
|
|
2210
|
-
var
|
|
2211
|
-
var
|
|
2212
|
-
var
|
|
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) => {
|
|
2213
2227
|
if (!e)
|
|
2214
2228
|
return false;
|
|
2215
2229
|
for (let t in e)
|
|
2216
|
-
if (
|
|
2230
|
+
if (H(e[t]) || Array.isArray(e[t]) && e[t].find(H))
|
|
2217
2231
|
return true;
|
|
2218
2232
|
return false;
|
|
2219
2233
|
};
|
|
2220
|
-
var
|
|
2234
|
+
var K = (e) => q ? e : new Promise((t) => {
|
|
2221
2235
|
let n = new FileReader;
|
|
2222
2236
|
n.onload = () => {
|
|
2223
|
-
let
|
|
2224
|
-
t(
|
|
2237
|
+
let r = new File([n.result], e.name, { lastModified: e.lastModified, type: e.type });
|
|
2238
|
+
t(r);
|
|
2225
2239
|
}, n.readAsArrayBuffer(e);
|
|
2226
2240
|
});
|
|
2227
|
-
var
|
|
2241
|
+
var A = async (e, t, n = {}, r = {}) => {
|
|
2228
2242
|
if (Array.isArray(e)) {
|
|
2229
|
-
for (let
|
|
2230
|
-
if (!Array.isArray(
|
|
2231
|
-
|
|
2243
|
+
for (let c2 of e)
|
|
2244
|
+
if (!Array.isArray(c2))
|
|
2245
|
+
r = await A(c2, t, n, r);
|
|
2232
2246
|
else {
|
|
2233
|
-
let
|
|
2234
|
-
if (typeof
|
|
2235
|
-
|
|
2247
|
+
let i2 = c2[0];
|
|
2248
|
+
if (typeof i2 == "string")
|
|
2249
|
+
r[i2.toLowerCase()] = c2[1];
|
|
2236
2250
|
else
|
|
2237
|
-
for (let [
|
|
2238
|
-
|
|
2251
|
+
for (let [a2, l] of i2)
|
|
2252
|
+
r[a2.toLowerCase()] = l;
|
|
2239
2253
|
}
|
|
2240
|
-
return
|
|
2254
|
+
return r;
|
|
2241
2255
|
}
|
|
2242
2256
|
if (!e)
|
|
2243
|
-
return
|
|
2257
|
+
return r;
|
|
2244
2258
|
switch (typeof e) {
|
|
2245
2259
|
case "function":
|
|
2246
2260
|
if (e instanceof Headers)
|
|
2247
|
-
return
|
|
2248
|
-
let
|
|
2249
|
-
return
|
|
2261
|
+
return A(e, t, n, r);
|
|
2262
|
+
let c2 = await e(t, n);
|
|
2263
|
+
return c2 ? A(c2, t, n, r) : r;
|
|
2250
2264
|
case "object":
|
|
2251
2265
|
if (e instanceof Headers)
|
|
2252
|
-
return e.forEach((
|
|
2253
|
-
|
|
2254
|
-
}),
|
|
2255
|
-
for (let [
|
|
2256
|
-
|
|
2257
|
-
return
|
|
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;
|
|
2258
2272
|
default:
|
|
2259
|
-
return
|
|
2273
|
+
return r;
|
|
2260
2274
|
}
|
|
2261
2275
|
};
|
|
2262
|
-
|
|
2263
|
-
let
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
let i2 = typeof o2 == "string" ? o2 : s2.decode(o2);
|
|
2273
|
-
i2.includes(`
|
|
2274
|
-
|
|
2275
|
-
`) ? 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);
|
|
2276
2286
|
}
|
|
2277
|
-
} finally {
|
|
2278
|
-
n.releaseLock();
|
|
2279
2287
|
}
|
|
2288
|
+
return Object.keys(r).length > 0 ? r : null;
|
|
2280
2289
|
}
|
|
2281
|
-
function*
|
|
2282
|
-
let
|
|
2290
|
+
function* B(e, t) {
|
|
2291
|
+
let n;
|
|
2292
|
+
for (;(n = e.value.indexOf(`
|
|
2283
2293
|
|
|
2284
|
-
`);
|
|
2285
|
-
|
|
2286
|
-
if (
|
|
2287
|
-
|
|
2288
|
-
|
|
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);
|
|
2289
2299
|
}
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
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);
|
|
2298
2319
|
}
|
|
2299
|
-
|
|
2320
|
+
} finally {
|
|
2321
|
+
r.releaseLock();
|
|
2300
2322
|
}
|
|
2301
2323
|
}
|
|
2302
|
-
var
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
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 + "")}`);
|
|
2312
2333
|
};
|
|
2313
|
-
for (let [
|
|
2314
|
-
if (Array.isArray(
|
|
2315
|
-
for (let
|
|
2316
|
-
|
|
2334
|
+
for (let [m, d2] of Object.entries(M)) {
|
|
2335
|
+
if (Array.isArray(d2)) {
|
|
2336
|
+
for (let T of d2)
|
|
2337
|
+
s(m, T);
|
|
2317
2338
|
continue;
|
|
2318
2339
|
}
|
|
2319
|
-
|
|
2320
|
-
if (typeof u2 == "object") {
|
|
2321
|
-
r(w, JSON.stringify(u2));
|
|
2322
|
-
continue;
|
|
2323
|
-
}
|
|
2324
|
-
r(w, `${u2}`);
|
|
2325
|
-
}
|
|
2340
|
+
s(m, d2);
|
|
2326
2341
|
}
|
|
2327
2342
|
}
|
|
2328
2343
|
if (k === "subscribe") {
|
|
2329
|
-
let
|
|
2330
|
-
return new
|
|
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);
|
|
2331
2346
|
}
|
|
2332
2347
|
return (async () => {
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
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) {
|
|
2337
2353
|
Array.isArray(g2) || (g2 = [g2]);
|
|
2338
|
-
for (let
|
|
2339
|
-
let
|
|
2340
|
-
typeof
|
|
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) } });
|
|
2341
2357
|
}
|
|
2342
2358
|
}
|
|
2343
|
-
if (
|
|
2344
|
-
let
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
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
|
+
}
|
|
2351
2380
|
continue;
|
|
2352
2381
|
}
|
|
2353
|
-
if (
|
|
2354
|
-
if (Array.isArray(
|
|
2355
|
-
for (let
|
|
2356
|
-
|
|
2382
|
+
if (q) {
|
|
2383
|
+
if (Array.isArray(p2))
|
|
2384
|
+
for (let x of p2)
|
|
2385
|
+
u2.append(f2, await w(x));
|
|
2357
2386
|
else
|
|
2358
|
-
|
|
2387
|
+
u2.append(f2, await w(p2));
|
|
2359
2388
|
continue;
|
|
2360
2389
|
}
|
|
2361
|
-
if (
|
|
2362
|
-
|
|
2390
|
+
if (p2 instanceof File) {
|
|
2391
|
+
u2.append(f2, await K(p2));
|
|
2363
2392
|
continue;
|
|
2364
2393
|
}
|
|
2365
|
-
if (
|
|
2366
|
-
for (let
|
|
2367
|
-
|
|
2394
|
+
if (p2 instanceof FileList) {
|
|
2395
|
+
for (let x = 0;x < p2.length; x++)
|
|
2396
|
+
u2.append(f2, await K(p2[x]));
|
|
2368
2397
|
continue;
|
|
2369
2398
|
}
|
|
2370
|
-
|
|
2399
|
+
u2.append(f2, await w(p2));
|
|
2371
2400
|
}
|
|
2372
|
-
|
|
2401
|
+
s.body = u2;
|
|
2373
2402
|
} else
|
|
2374
|
-
typeof
|
|
2375
|
-
if (
|
|
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) {
|
|
2376
2405
|
Array.isArray(g2) || (g2 = [g2]);
|
|
2377
|
-
for (let
|
|
2378
|
-
let
|
|
2379
|
-
typeof
|
|
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) } });
|
|
2380
2409
|
}
|
|
2381
2410
|
}
|
|
2382
|
-
|
|
2383
|
-
let
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
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)
|
|
2387
2425
|
try {
|
|
2388
|
-
let
|
|
2389
|
-
if (
|
|
2390
|
-
|
|
2426
|
+
let o2 = await u2(y.clone());
|
|
2427
|
+
if (o2 != null) {
|
|
2428
|
+
h = o2;
|
|
2391
2429
|
break;
|
|
2392
2430
|
}
|
|
2393
|
-
} catch (
|
|
2394
|
-
|
|
2431
|
+
} catch (o2) {
|
|
2432
|
+
o2 instanceof d ? v = o2 : v = new d(422, o2);
|
|
2395
2433
|
break;
|
|
2396
2434
|
}
|
|
2397
2435
|
}
|
|
2398
|
-
if (
|
|
2399
|
-
return { data:
|
|
2436
|
+
if (h !== null)
|
|
2437
|
+
return { data: h, error: v, response: y, status: y.status, headers: y.headers };
|
|
2400
2438
|
switch (y.headers.get("Content-Type")?.split(";")[0]) {
|
|
2401
2439
|
case "text/event-stream":
|
|
2402
|
-
|
|
2440
|
+
h = Y(y, { parseDate: t.parseDate });
|
|
2403
2441
|
break;
|
|
2404
2442
|
case "application/json":
|
|
2405
|
-
|
|
2406
|
-
if (typeof
|
|
2407
|
-
return
|
|
2408
|
-
let
|
|
2409
|
-
return
|
|
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;
|
|
2410
2448
|
});
|
|
2411
2449
|
break;
|
|
2412
2450
|
case "application/octet-stream":
|
|
2413
|
-
|
|
2451
|
+
h = await y.arrayBuffer();
|
|
2414
2452
|
break;
|
|
2415
2453
|
case "multipart/form-data":
|
|
2416
|
-
let
|
|
2417
|
-
|
|
2418
|
-
|
|
2454
|
+
let u2 = await y.formData();
|
|
2455
|
+
h = {}, u2.forEach((o2, w) => {
|
|
2456
|
+
h[w] = o2;
|
|
2419
2457
|
});
|
|
2420
2458
|
break;
|
|
2421
2459
|
default:
|
|
2422
|
-
|
|
2460
|
+
h = await y.text().then((o2) => g(o2, { parseDate: t.parseDate }));
|
|
2423
2461
|
}
|
|
2424
|
-
|
|
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 };
|
|
2425
2468
|
})();
|
|
2426
2469
|
}
|
|
2427
|
-
return typeof
|
|
2470
|
+
return typeof a2 == "object" ? F(e, t, [...n, Object.values(a2)[0]], r) : F(e, t, n);
|
|
2428
2471
|
} });
|
|
2429
|
-
var
|
|
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));
|
|
2430
2473
|
|
|
2431
2474
|
// src/api.ts
|
|
2432
2475
|
function getApi() {
|
|
@@ -2434,14 +2477,16 @@ function getApi() {
|
|
|
2434
2477
|
if (!config) {
|
|
2435
2478
|
throw new Error("Not logged in. Run: dblx auth login");
|
|
2436
2479
|
}
|
|
2437
|
-
return
|
|
2480
|
+
return se(config.api_url, {
|
|
2481
|
+
parseDate: false,
|
|
2438
2482
|
headers: {
|
|
2439
2483
|
Authorization: `Bearer ${config.api_key}`
|
|
2440
2484
|
}
|
|
2441
2485
|
});
|
|
2442
2486
|
}
|
|
2443
2487
|
function getApiWith(apiKey, apiUrl) {
|
|
2444
|
-
return
|
|
2488
|
+
return se(apiUrl, {
|
|
2489
|
+
parseDate: false,
|
|
2445
2490
|
headers: {
|
|
2446
2491
|
Authorization: `Bearer ${apiKey}`
|
|
2447
2492
|
}
|
|
@@ -2532,11 +2577,39 @@ var authCommand = new Command("auth").description("Manage authentication").addCo
|
|
|
2532
2577
|
console.log("Logged out. Config removed.");
|
|
2533
2578
|
}));
|
|
2534
2579
|
|
|
2535
|
-
// src/commands/
|
|
2536
|
-
|
|
2580
|
+
// src/commands/helpers.ts
|
|
2581
|
+
function threadRows(threads) {
|
|
2582
|
+
return threads.map((t) => ({
|
|
2583
|
+
id: t.id.slice(0, 8),
|
|
2584
|
+
body: t.body.length > 60 ? t.body.slice(0, 57) + "..." : t.body,
|
|
2585
|
+
unread: t.unread ? "*" : "",
|
|
2586
|
+
archived: t.archived ? "archived" : "",
|
|
2587
|
+
snoozed: t.snoozed ? "snoozed" : ""
|
|
2588
|
+
}));
|
|
2589
|
+
}
|
|
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) => {
|
|
2537
2609
|
const api = getApi();
|
|
2538
2610
|
const { data, error } = await api.api.cli.v1.threads.get({
|
|
2539
2611
|
query: {
|
|
2612
|
+
q: opts.q,
|
|
2540
2613
|
archived: opts.archived ? "true" : undefined,
|
|
2541
2614
|
snoozed: opts.snoozed ? "true" : undefined
|
|
2542
2615
|
}
|
|
@@ -2547,99 +2620,69 @@ var threadsCommand = new Command("threads").description("Manage threads").addCom
|
|
|
2547
2620
|
output(data.threads, { json: true });
|
|
2548
2621
|
return;
|
|
2549
2622
|
}
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
unread: t.unread ? "*" : "",
|
|
2554
|
-
archived: t.archived ? "archived" : "",
|
|
2555
|
-
snoozed: t.snoozed ? "snoozed" : ""
|
|
2556
|
-
}));
|
|
2557
|
-
output(rows, { json: false });
|
|
2558
|
-
})).addCommand(new Command("create").description("Create a new thread").requiredOption("--title <title>", "Thread title").option("--comment <text>", "Optional first comment").option("--json", "Output as JSON").action(async (opts) => {
|
|
2623
|
+
output(threadRows(data.threads), { json: false });
|
|
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);
|
|
2559
2626
|
const api = getApi();
|
|
2560
|
-
const { data, error } = await api.api.cli.v1.
|
|
2561
|
-
|
|
2562
|
-
comment: opts.comment
|
|
2627
|
+
const { data, error } = await api.api.cli.v1.today.get({
|
|
2628
|
+
query: { date }
|
|
2563
2629
|
});
|
|
2564
2630
|
if (error)
|
|
2565
2631
|
throw error;
|
|
2566
2632
|
if (opts.json) {
|
|
2567
|
-
output(data
|
|
2633
|
+
output(data, { json: true });
|
|
2568
2634
|
return;
|
|
2569
2635
|
}
|
|
2570
|
-
console.log(`
|
|
2571
|
-
|
|
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) => {
|
|
2572
2655
|
const api = getApi();
|
|
2573
|
-
const { data, error } = await api.api.cli.v1.threads({ id }).
|
|
2574
|
-
body: opts.title
|
|
2575
|
-
});
|
|
2656
|
+
const { data, error } = await api.api.cli.v1.threads({ id: threadId }).note.get();
|
|
2576
2657
|
if (error)
|
|
2577
2658
|
throw error;
|
|
2578
2659
|
if (opts.json) {
|
|
2579
|
-
output(data
|
|
2660
|
+
output(data, { json: true });
|
|
2580
2661
|
return;
|
|
2581
2662
|
}
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
throw error;
|
|
2590
|
-
console.log("Archived.");
|
|
2591
|
-
})).addCommand(new Command("unarchive").description("Unarchive a thread").argument("<id>", "Thread ID").action(async (id) => {
|
|
2592
|
-
const api = getApi();
|
|
2593
|
-
const { error } = await api.api.cli.v1.threads({ id }).archive.put({
|
|
2594
|
-
archived: false
|
|
2595
|
-
});
|
|
2596
|
-
if (error)
|
|
2597
|
-
throw error;
|
|
2598
|
-
console.log("Unarchived.");
|
|
2599
|
-
})).addCommand(new Command("snooze").description("Snooze a thread").argument("<id>", "Thread ID").requiredOption("--until <datetime>", "Snooze until (ISO datetime)").action(async (id, opts) => {
|
|
2600
|
-
const api = getApi();
|
|
2601
|
-
const { error } = await api.api.cli.v1.threads({ id }).snooze.put({
|
|
2602
|
-
until: opts.until
|
|
2603
|
-
});
|
|
2604
|
-
if (error)
|
|
2605
|
-
throw error;
|
|
2606
|
-
console.log(`Snoozed until ${opts.until}.`);
|
|
2607
|
-
})).addCommand(new Command("unsnooze").description("Remove snooze from a thread").argument("<id>", "Thread ID").action(async (id) => {
|
|
2608
|
-
const api = getApi();
|
|
2609
|
-
const { error } = await api.api.cli.v1.threads({ id }).snooze.put({
|
|
2610
|
-
until: null
|
|
2611
|
-
});
|
|
2612
|
-
if (error)
|
|
2613
|
-
throw error;
|
|
2614
|
-
console.log("Unsnoozed.");
|
|
2615
|
-
})).addCommand(new Command("set-parent").description("Set a parent thread").argument("<id>", "Thread ID").requiredOption("--parent <parent-id>", "Parent thread ID").action(async (id, opts) => {
|
|
2616
|
-
const api = getApi();
|
|
2617
|
-
const { error } = await api.api.cli.v1.threads({ id }).parent.put({
|
|
2618
|
-
parent_id: opts.parent
|
|
2619
|
-
});
|
|
2620
|
-
if (error)
|
|
2621
|
-
throw error;
|
|
2622
|
-
console.log(`Parent set to ${opts.parent.slice(0, 8)}.`);
|
|
2623
|
-
})).addCommand(new Command("set-today").description("Assign thread to a date").argument("<id>", "Thread ID").option("--date <date>", "Date (YYYY-MM-DD)", new Date().toISOString().slice(0, 10)).action(async (id, opts) => {
|
|
2624
|
-
const api = getApi();
|
|
2625
|
-
const { error } = await api.api.cli.v1.threads({ id }).today.put({
|
|
2626
|
-
date: opts.date
|
|
2627
|
-
});
|
|
2628
|
-
if (error)
|
|
2629
|
-
throw error;
|
|
2630
|
-
console.log(`Assigned to ${opts.date}.`);
|
|
2631
|
-
})).addCommand(new Command("unset-today").description("Remove thread from a date").argument("<id>", "Thread ID").option("--date <date>", "Date (YYYY-MM-DD)", new Date().toISOString().slice(0, 10)).action(async (id, opts) => {
|
|
2663
|
+
if (!data.note) {
|
|
2664
|
+
console.log("No thread note.");
|
|
2665
|
+
return;
|
|
2666
|
+
}
|
|
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);
|
|
2632
2670
|
const api = getApi();
|
|
2633
|
-
const { error } = await api.api.cli.v1.
|
|
2634
|
-
|
|
2671
|
+
const { data, error } = await api.api.cli.v1.today.note.get({
|
|
2672
|
+
query: { date }
|
|
2635
2673
|
});
|
|
2636
2674
|
if (error)
|
|
2637
2675
|
throw error;
|
|
2638
|
-
|
|
2639
|
-
})
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2676
|
+
if (opts.json) {
|
|
2677
|
+
output(data, { json: true });
|
|
2678
|
+
return;
|
|
2679
|
+
}
|
|
2680
|
+
if (!data.note) {
|
|
2681
|
+
console.log("No daily note.");
|
|
2682
|
+
return;
|
|
2683
|
+
}
|
|
2684
|
+
console.log(data.note.content || "(empty)");
|
|
2685
|
+
})).addCommand(new Command("comments").description("List comments in a thread").requiredOption("--thread <id>", "Thread ID").option("--json", "Output as JSON").action(async (opts) => {
|
|
2643
2686
|
const api = getApi();
|
|
2644
2687
|
const { data, error } = await api.api.cli.v1.threads({ id: opts.thread }).comments.get();
|
|
2645
2688
|
if (error)
|
|
@@ -2655,111 +2698,155 @@ var commentsCommand = new Command("comments").description("Manage comments").add
|
|
|
2655
2698
|
created_at: c2.created_at
|
|
2656
2699
|
}));
|
|
2657
2700
|
output(rows, { json: false });
|
|
2658
|
-
})).addCommand(new Command("
|
|
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) => {
|
|
2659
2702
|
const api = getApi();
|
|
2660
|
-
const { data, error } = await api.api.cli.v1.threads({ id:
|
|
2703
|
+
const { data, error } = await api.api.cli.v1.threads({ id: threadId }).members.get();
|
|
2661
2704
|
if (error)
|
|
2662
2705
|
throw error;
|
|
2663
2706
|
if (opts.json) {
|
|
2664
|
-
output(data.
|
|
2707
|
+
output(data.members, { json: true });
|
|
2665
2708
|
return;
|
|
2666
2709
|
}
|
|
2667
|
-
|
|
2668
|
-
|
|
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) => {
|
|
2669
2719
|
const api = getApi();
|
|
2670
|
-
const
|
|
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 });
|
|
2671
2737
|
if (error)
|
|
2672
2738
|
throw error;
|
|
2673
2739
|
if (opts.json) {
|
|
2674
2740
|
output(data.comment, { json: true });
|
|
2675
2741
|
return;
|
|
2676
2742
|
}
|
|
2677
|
-
console.log(`Comment
|
|
2743
|
+
console.log(`Comment added (${data.comment.id.slice(0, 8)}).`);
|
|
2678
2744
|
}));
|
|
2679
2745
|
|
|
2680
|
-
// src/commands/
|
|
2681
|
-
var
|
|
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) => {
|
|
2682
2748
|
const api = getApi();
|
|
2683
|
-
const
|
|
2684
|
-
|
|
2685
|
-
|
|
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
|
+
}
|
|
2686
2782
|
if (opts.json) {
|
|
2687
|
-
output(
|
|
2783
|
+
output(result, { json: true });
|
|
2688
2784
|
return;
|
|
2689
2785
|
}
|
|
2690
|
-
const
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
output(rows, { json: false });
|
|
2695
|
-
})).addCommand(new Command("invite").description("Invite a user to a thread").argument("<thread-id>", "Thread ID").requiredOption("--user <email-or-username>", "User email or username").action(async (threadId, opts) => {
|
|
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) => {
|
|
2696
2790
|
const api = getApi();
|
|
2697
|
-
const { data, error } = await api.api.cli.v1.threads({ id: threadId }).
|
|
2791
|
+
const { data, error } = await api.api.cli.v1.threads({ id: threadId }).note.put({ content: opts.content });
|
|
2698
2792
|
if (error)
|
|
2699
2793
|
throw error;
|
|
2700
|
-
if (
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
console.log(data.reason || "Could not invite user.");
|
|
2794
|
+
if (opts.json) {
|
|
2795
|
+
output(data, { json: true });
|
|
2796
|
+
return;
|
|
2704
2797
|
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
// src/commands/today.ts
|
|
2708
|
-
function localDate(dateArg) {
|
|
2709
|
-
if (dateArg)
|
|
2710
|
-
return dateArg;
|
|
2711
|
-
const now = new Date;
|
|
2712
|
-
const y = now.getFullYear();
|
|
2713
|
-
const m = String(now.getMonth() + 1).padStart(2, "0");
|
|
2714
|
-
const d2 = String(now.getDate()).padStart(2, "0");
|
|
2715
|
-
return `${y}-${m}-${d2}`;
|
|
2716
|
-
}
|
|
2717
|
-
var todayCommand = new Command("today").description("Today view — threads and daily note").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) => {
|
|
2718
2800
|
const date = localDate(opts.date);
|
|
2719
2801
|
const api = getApi();
|
|
2720
|
-
const { data, error } = await api.api.cli.v1.today.
|
|
2721
|
-
query: { date }
|
|
2722
|
-
});
|
|
2802
|
+
const { data, error } = await api.api.cli.v1.today.note.put({ content: opts.content }, { query: { date } });
|
|
2723
2803
|
if (error)
|
|
2724
2804
|
throw error;
|
|
2725
2805
|
if (opts.json) {
|
|
2726
2806
|
output(data, { json: true });
|
|
2727
2807
|
return;
|
|
2728
2808
|
}
|
|
2729
|
-
console.log(
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
console.log(`No threads for this date.
|
|
2739
|
-
`);
|
|
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;
|
|
2740
2818
|
}
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
}
|
|
2745
|
-
|
|
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;
|
|
2746
2830
|
}
|
|
2747
|
-
|
|
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) => {
|
|
2748
2833
|
const date = localDate(opts.date);
|
|
2749
2834
|
const api = getApi();
|
|
2750
|
-
if (opts.
|
|
2751
|
-
const { data: data2, error: error2 } = await api.api.cli.v1.
|
|
2835
|
+
if (opts.remove) {
|
|
2836
|
+
const { data: data2, error: error2 } = await api.api.cli.v1.threads({ id: threadId }).today.delete({
|
|
2837
|
+
date
|
|
2838
|
+
});
|
|
2752
2839
|
if (error2)
|
|
2753
2840
|
throw error2;
|
|
2754
2841
|
if (opts.json) {
|
|
2755
2842
|
output(data2, { json: true });
|
|
2756
2843
|
return;
|
|
2757
2844
|
}
|
|
2758
|
-
console.log(
|
|
2845
|
+
console.log(`Removed from ${date}.`);
|
|
2759
2846
|
return;
|
|
2760
2847
|
}
|
|
2761
|
-
const { data, error } = await api.api.cli.v1.today.
|
|
2762
|
-
|
|
2848
|
+
const { data, error } = await api.api.cli.v1.threads({ id: threadId }).today.put({
|
|
2849
|
+
date
|
|
2763
2850
|
});
|
|
2764
2851
|
if (error)
|
|
2765
2852
|
throw error;
|
|
@@ -2767,16 +2854,29 @@ var todayCommand = new Command("today").description("Today view — threads and
|
|
|
2767
2854
|
output(data, { json: true });
|
|
2768
2855
|
return;
|
|
2769
2856
|
}
|
|
2770
|
-
|
|
2771
|
-
|
|
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 });
|
|
2772
2868
|
return;
|
|
2773
2869
|
}
|
|
2774
|
-
|
|
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
|
+
}
|
|
2775
2875
|
}));
|
|
2776
2876
|
// package.json
|
|
2777
2877
|
var package_default = {
|
|
2778
2878
|
name: "dblx",
|
|
2779
|
-
version: "0.1.
|
|
2879
|
+
version: "0.1.63",
|
|
2780
2880
|
description: "CLI for dblebox — thread-first communication",
|
|
2781
2881
|
type: "module",
|
|
2782
2882
|
bin: {
|
|
@@ -2803,10 +2903,10 @@ var package_default = {
|
|
|
2803
2903
|
// src/index.ts
|
|
2804
2904
|
var program2 = new Command().name("dblx").description("CLI for dblebox — thread-first communication").version(package_default.version).enablePositionalOptions();
|
|
2805
2905
|
program2.addCommand(authCommand);
|
|
2806
|
-
program2.addCommand(
|
|
2807
|
-
program2.addCommand(
|
|
2808
|
-
program2.addCommand(
|
|
2809
|
-
program2.addCommand(
|
|
2906
|
+
program2.addCommand(getCommand);
|
|
2907
|
+
program2.addCommand(createCommand2);
|
|
2908
|
+
program2.addCommand(setCommand);
|
|
2909
|
+
program2.addCommand(inviteCommand);
|
|
2810
2910
|
program2.parseAsync().catch((err) => {
|
|
2811
2911
|
console.error(err.message);
|
|
2812
2912
|
process.exit(1);
|