@usesocial/cli 0.1.0 → 0.1.3
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/CHANGELOG.md +9 -0
- package/README.md +182 -94
- package/bin/social.mjs +7 -0
- package/dist/index.d.mts +98 -1
- package/dist/index.mjs +23404 -7550
- package/package.json +26 -10
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# @usesocial/cli
|
|
2
|
+
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`158bf58`](https://github.com/usesocial/monorepo/commit/158bf5804d47112fa2ed941fd7e78174a53b3947) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Release the promoted account lifecycle, schema, and publishing pipeline updates.
|
|
8
|
+
|
|
9
|
+
Future release entries are managed by Changesets.
|
package/README.md
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://usesocial.dev/app-icon-dark.svg" />
|
|
4
|
+
<img alt="social" height="84" src="https://usesocial.dev/app-icon.svg" width="84" />
|
|
5
|
+
</picture>
|
|
6
|
+
</p>
|
|
2
7
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
8
|
+
<h1 align="center">@usesocial/cli</h1>
|
|
9
|
+
|
|
10
|
+
**Agent-run distribution.** One install, one login, and your agent can run
|
|
11
|
+
distribution work across X and LinkedIn — outreach, posting, audience insights,
|
|
12
|
+
and the follow-up loops between them — from any shell.
|
|
6
13
|
|
|
7
14
|
`social` is built for people who live in a terminal with an agent open and are on
|
|
8
15
|
the hook for their own distribution. The work you keep meaning to do — see who
|
|
@@ -15,21 +22,17 @@ Published as `@usesocial/cli` on npm; the binary is `social`.
|
|
|
15
22
|
## Install
|
|
16
23
|
|
|
17
24
|
```sh
|
|
18
|
-
|
|
19
|
-
# or
|
|
20
|
-
bun install -g @usesocial/cli@latest
|
|
21
|
-
# or
|
|
22
|
-
npm install -g @usesocial/cli
|
|
25
|
+
curl -fsSL https://usesocial.dev/install.sh | bash
|
|
23
26
|
```
|
|
24
27
|
|
|
25
28
|
## Quickstart
|
|
26
29
|
|
|
27
30
|
```sh
|
|
28
|
-
social login
|
|
29
|
-
social
|
|
30
|
-
social linkedin
|
|
31
|
-
social
|
|
32
|
-
social x
|
|
31
|
+
social account login # device sign-in, choose scope, set up billing
|
|
32
|
+
social account connect linkedin # connect a LinkedIn account
|
|
33
|
+
social linkedin profile
|
|
34
|
+
social account connect x # connect an X account
|
|
35
|
+
social x profile
|
|
33
36
|
```
|
|
34
37
|
|
|
35
38
|
## What you can hand your agent
|
|
@@ -39,122 +42,203 @@ A few of the things the command surface supports:
|
|
|
39
42
|
|
|
40
43
|
| You ask | The agent reaches for |
|
|
41
44
|
|---|---|
|
|
42
|
-
| "Surface the ten connections worth reaching out to this week." | `linkedin
|
|
43
|
-
| "Pull everyone who reacted to my last LinkedIn post and flag the warm leads." | `linkedin
|
|
44
|
-
| "Read this creator's recent posts and break down what makes them land." | `linkedin
|
|
45
|
-
| "Find what people are saying about AI agents this week and summarize the themes." | `linkedin search posts`, `x
|
|
46
|
-
| "Draft a reply to this thread and post it once I approve." | `linkedin
|
|
45
|
+
| "Surface the ten connections worth reaching out to this week." | `linkedin connections`, `x tweets` |
|
|
46
|
+
| "Pull everyone who reacted to my last LinkedIn post and flag the warm leads." | `linkedin reactions`, `linkedin profile` |
|
|
47
|
+
| "Read this creator's recent posts and break down what makes them land." | `linkedin posts`, `x tweets` |
|
|
48
|
+
| "Find what people are saying about AI agents this week and summarize the themes." | `linkedin search posts`, `x timeline` |
|
|
49
|
+
| "Draft a reply to this thread and post it once I approve." | `linkedin comment`, `x post` |
|
|
47
50
|
|
|
48
51
|
## Commands
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
The main command surfaces print compact JSON by default. List commands commonly
|
|
54
|
+
accept `--limit` and `--cursor`; time windows are command-specific. Pass `--help`
|
|
55
|
+
on any subcommand for the full flag list, or run `social schema "<command path>"`
|
|
56
|
+
for the machine-readable contract for a runnable command. Agents planning across
|
|
57
|
+
many calls can run `social schema --leaves` for a manifest of runnable commands
|
|
58
|
+
keyed by command path.
|
|
54
59
|
|
|
55
60
|
Commands marked **✎ write** mutate your account and require an explicit write
|
|
56
61
|
scope (see [Account safety](#account-safety)).
|
|
57
62
|
|
|
63
|
+
### Targets
|
|
64
|
+
|
|
65
|
+
Commands with `[target]` or `<target>` accept `@handle` or `@public-identifier`,
|
|
66
|
+
a full X/LinkedIn URL, a LinkedIn URN, or a typed ID such as `profile_id:<id>`,
|
|
67
|
+
`post_id:<id>`, `list_id:<id>`, `chat_id:<id>`, `company_id:<id>`, or `request_id:<id>`. Bare IDs are not
|
|
68
|
+
accepted. When an optional target is omitted, the command acts on your own
|
|
69
|
+
connected account.
|
|
70
|
+
|
|
58
71
|
### Top level
|
|
59
72
|
|
|
60
73
|
| Command | Description |
|
|
61
74
|
|---|---|
|
|
62
|
-
| `social
|
|
63
|
-
| `social
|
|
64
|
-
| `social schema` | Print the full command tree as JSON — a manifest for agents. |
|
|
65
|
-
| `social usage` | Recent calls or an aggregate billing/usage summary. |
|
|
66
|
-
| `social linkedin <…>` | LinkedIn operations (below). |
|
|
75
|
+
| `social account` | Show auth state and connected accounts; login, logout, connect accounts, inspect usage/logs, and configure local CLI settings. |
|
|
76
|
+
| `social schema` | Print the compact command tree, inspect one command with `social schema "<command path>"`, or emit agent command contracts with `social schema --leaves`. |
|
|
67
77
|
| `social x <…>` | X operations (below). |
|
|
78
|
+
| `social linkedin <…>` | LinkedIn operations (below). |
|
|
79
|
+
|
|
80
|
+
### `social account`
|
|
81
|
+
|
|
82
|
+
| Command | Description | |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| `(bare)` | Show who is signed in and list connected accounts. | |
|
|
85
|
+
| `login` | Device sign-in, scope selection, and billing. | |
|
|
86
|
+
| `logout` | Revoke the session and clear the saved token. | |
|
|
87
|
+
| `connect linkedin` | Connect a LinkedIn account through the browser. | ✎ write |
|
|
88
|
+
| `connect x` | Connect an X account through OAuth. | ✎ write |
|
|
89
|
+
| `reconnect linkedin <account>` | Re-auth an existing LinkedIn account. | ✎ write |
|
|
90
|
+
| `reconnect x <account>` | Re-auth an existing X account. | ✎ write |
|
|
91
|
+
| `disconnect linkedin <account>` | Disconnect a LinkedIn account. | ✎ write |
|
|
92
|
+
| `disconnect x <account>` | Disconnect an X account. | ✎ write |
|
|
93
|
+
| `usage` | Aggregate proxy usage and billing stats. | |
|
|
94
|
+
| `logs` | Recent proxy calls. | |
|
|
95
|
+
| `config cache mode` | Read or set the cache mode preset. | |
|
|
96
|
+
| `config cache ttl` | Set a custom cache TTL in seconds. | |
|
|
97
|
+
|
|
98
|
+
`social account` returns compact JSON with the signed-in user and connected accounts.
|
|
68
99
|
|
|
69
100
|
### `social linkedin`
|
|
70
101
|
|
|
71
102
|
| Command | Description | |
|
|
72
103
|
|---|---|---|
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `posts
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
104
|
+
| `post <text>` | Create a post. | ✎ write |
|
|
105
|
+
| `comment <target> <text>` | Comment on a post. | ✎ write |
|
|
106
|
+
| `react <target> [type=like]` | React to a post or comment. | ✎ write |
|
|
107
|
+
| `requests send <target> [message]` | Send a connection request. | ✎ write |
|
|
108
|
+
| `requests sent` | List pending sent connection requests; supports `--limit`, `--cursor`, `--offset`, and `-H/--header`. | |
|
|
109
|
+
| `requests received` | List pending received connection requests; supports `--limit`, `--cursor`, `--offset`, and `-H/--header`. | |
|
|
110
|
+
| `requests accept request_id:<id>` | Accept a received connection request. | ✎ write |
|
|
111
|
+
| `requests cancel request_id:<id>` | Cancel a sent request or refuse a received connection request. | ✎ write |
|
|
112
|
+
| `posts [target]` | List a user's or company's posts; omit the target for your own account. | |
|
|
113
|
+
| `comments <target>` | List a post's comments. | |
|
|
114
|
+
| `reactions <target>` | List a post's reactions. | |
|
|
115
|
+
| `profile [target]` | Fetch a profile; omit the target for your own account. | |
|
|
116
|
+
| `connections [target]` | List connections; omit the target for account-level connections. | |
|
|
117
|
+
| `company <target>` | Fetch a company profile. | |
|
|
118
|
+
| `jobs <target>` | List a company's job postings. | |
|
|
119
|
+
| `search people <keywords>` | Search for people. | |
|
|
120
|
+
| `search posts <keywords>` | Search for posts. | |
|
|
121
|
+
| `search jobs <keywords>` | Search for jobs. | |
|
|
122
|
+
| `search companies <keywords>` | Search for companies. | |
|
|
123
|
+
| `messages` | List conversations. | |
|
|
124
|
+
| `messages <target>` | Read a conversation by `chat_id:<id>`, `@handle`, `profile_id:<id>`, profile URL, or messaging-thread URL. | |
|
|
125
|
+
| `message <target> <text>` | Send a message. | ✎ write |
|
|
126
|
+
| `message <target> delete message_id:<id>` | Delete one of your own messages. | ✎ write |
|
|
127
|
+
| `message <target> edit message_id:<id> <text>` | Edit one of your own messages. | ✎ write |
|
|
128
|
+
| `messages <target> mark read` | Mark a conversation read. | ✎ write |
|
|
129
|
+
| `messages <target> mark unread` | Mark a conversation unread. | ✎ write |
|
|
90
130
|
|
|
91
131
|
### `social x`
|
|
92
132
|
|
|
93
133
|
| Command | Description | |
|
|
94
134
|
|---|---|---|
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `tweets
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
108
|
-
| `
|
|
135
|
+
| `post <text>` | Create a post. | ✎ write |
|
|
136
|
+
| `repost <target>` · `unrepost <target>` | Repost or undo a repost. | ✎ write |
|
|
137
|
+
| `like <target>` · `unlike <target>` | Like or unlike a post. | ✎ write |
|
|
138
|
+
| `follow <target>` · `unfollow <target>` | Follow or unfollow a user. | ✎ write |
|
|
139
|
+
| `followers [target]` | List a user's followers; omit the target for your own account. | |
|
|
140
|
+
| `following [target]` | List accounts a user follows; omit the target for your own account. | |
|
|
141
|
+
| `tweet <target>` | Fetch a single post. | |
|
|
142
|
+
| `tweets [target]` | List a user's recent posts; omit the target for your own account. | |
|
|
143
|
+
| `profile [target]` | Fetch a profile; omit the target for your own account. | |
|
|
144
|
+
| `timeline` | Read the home timeline. | |
|
|
145
|
+
| `bookmark <target>` · `unbookmark <target>` | Add or remove a bookmark. | ✎ write |
|
|
146
|
+
| `messages` | List conversations. | |
|
|
147
|
+
| `messages <target>` | Read a DM conversation or participant target: chat URL, `chat_id:<id>`, `@handle`, profile URL, or `profile_id:<id>`. | |
|
|
148
|
+
| `message <recipients> [text]` | Send a message to a chat URL, `chat_id:<id>`, `@handle`, profile URL, or `profile_id:<id>`; comma-separate profile targets for a group. | ✎ write |
|
|
109
149
|
|
|
110
150
|
## Built for agents
|
|
111
151
|
|
|
112
|
-
- **Everything speaks JSON.**
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
- **The same
|
|
116
|
-
|
|
152
|
+
- **Everything speaks JSON.** Pipe output through `jq`, `fzf`, or your agent's
|
|
153
|
+
planner — anything that reads stdin. Structured errors and predictable exit
|
|
154
|
+
codes mean an agent can branch on what happened.
|
|
155
|
+
- **The same patterns across networks.** `--limit`, `--cursor`, and `--account`
|
|
156
|
+
behave consistently on LinkedIn and X. Cacheable reads also list `-H/--header`
|
|
157
|
+
when proxy request headers such as `Cache-Control: no-cache` can be overridden.
|
|
117
158
|
- **A skill you drop straight in.** Install the public skill repo with
|
|
118
159
|
`npx skills add usesocial/skill`; Claude, Codex, or any other supported agent
|
|
119
|
-
then knows the commands.
|
|
160
|
+
then knows the commands.
|
|
120
161
|
|
|
121
162
|
```sh
|
|
122
|
-
# Find hiring posts, fan out to reaction graphs, rank warm contacts
|
|
123
|
-
social linkedin search posts "AI infra hiring" --limit
|
|
124
|
-
|
|
125
|
-
| xargs -I{} social linkedin
|
|
126
|
-
| jq -s '[.[].
|
|
127
|
-
| group_by(.actor.id)
|
|
128
|
-
| map({
|
|
163
|
+
# Find hiring posts, fan out to reaction graphs, rank warm contacts.
|
|
164
|
+
social linkedin search posts "AI infra hiring" --limit 25 > /tmp/hiring-posts.json
|
|
165
|
+
jq -r '.items[].id' /tmp/hiring-posts.json \
|
|
166
|
+
| xargs -I{} social linkedin reactions post_id:{} \
|
|
167
|
+
| jq -s '[ .[] | .items[] ]
|
|
168
|
+
| group_by(.actor.id // .reactor.id // .profile_id)
|
|
169
|
+
| map({person: (.[0].actor // .[0].reactor), signals: length})
|
|
129
170
|
| sort_by(-.signals) | .[0:15]'
|
|
130
171
|
```
|
|
131
172
|
|
|
173
|
+
## Exit codes
|
|
174
|
+
|
|
175
|
+
| Code | Meaning | Agent action |
|
|
176
|
+
|---:|---|---|
|
|
177
|
+
| `0` | Success | Continue. |
|
|
178
|
+
| `2` | Usage or validation error | Fix the command, flags, IDs, JSON body, or local input. |
|
|
179
|
+
| `3` | Not found | Check the resource ID or pick a different item. |
|
|
180
|
+
| `4` | Auth or scope error | Run `social account login`, or log out and choose the needed scope. |
|
|
181
|
+
| `5` | API or unexpected error | Retry later or surface the server error. |
|
|
182
|
+
| `7` | Rate limited | Back off; JSON errors may include `retryAfterSeconds`. |
|
|
183
|
+
|
|
132
184
|
## Auth
|
|
133
185
|
|
|
134
|
-
`social login` runs a device-authorization flow:
|
|
186
|
+
`social account login` runs a device-authorization flow:
|
|
135
187
|
|
|
136
|
-
1.
|
|
137
|
-
|
|
138
|
-
2.
|
|
139
|
-
3.
|
|
188
|
+
1. Asks what access to grant the agent. Read and Write are both selected by
|
|
189
|
+
default; clear Write in the prompt to grant read-only access.
|
|
190
|
+
2. Asks for your email address.
|
|
191
|
+
3. Shows you a verification code and approval URL, then tries to open that URL
|
|
192
|
+
in your browser.
|
|
193
|
+
4. Waits until you approve the session in the browser.
|
|
194
|
+
5. Confirms billing checkout in the terminal when a seat is needed.
|
|
195
|
+
6. Stores the returned token in your OS keyring, falling back to
|
|
140
196
|
`~/.social/credentials.json` (mode `0600`) when no keyring is available.
|
|
197
|
+
Non-production `SOCIAL_API_URL` values use an API-specific credential
|
|
198
|
+
namespace so staging tests do not overwrite the production session.
|
|
199
|
+
|
|
200
|
+
`social account logout` revokes the session and removes the stored token from both places.
|
|
201
|
+
Bare `social account` prints compact JSON with the current auth state, credential
|
|
202
|
+
namespace, verified session when available, and connected accounts.
|
|
203
|
+
`social account login` requires an interactive terminal and is not supported from CI,
|
|
204
|
+
background jobs, or agent-mediated setup flows.
|
|
141
205
|
|
|
142
|
-
|
|
206
|
+
## Cache config
|
|
143
207
|
|
|
144
|
-
|
|
208
|
+
Allowlisted GET requests use a local proxy cache. Cacheable commands send
|
|
209
|
+
`Cache-Control: max-age=<seconds>` from your local config:
|
|
145
210
|
|
|
146
211
|
```sh
|
|
147
|
-
social
|
|
212
|
+
social account config cache mode # read the current cache mode and TTL
|
|
213
|
+
social account config cache mode live # 15 minutes, default
|
|
214
|
+
social account config cache mode analytical # 24 hours
|
|
215
|
+
social account config cache mode historical # 1 week
|
|
216
|
+
social account config cache ttl 3600 # custom TTL in seconds
|
|
148
217
|
```
|
|
149
218
|
|
|
219
|
+
Setting `ttl` switches the mode to `custom`. Config is stored at
|
|
220
|
+
`~/.social/config.json` with mode `0600`. Use command-level
|
|
221
|
+
`-H "Cache-Control: no-cache"` when a command lists `--header` in help and you
|
|
222
|
+
need to bypass a cached read.
|
|
223
|
+
|
|
224
|
+
Command output exposes actual per-call cost and pagination under `meta`:
|
|
225
|
+
|
|
226
|
+
```sh
|
|
227
|
+
social linkedin messages --limit 20 | jq '.meta.cost'
|
|
228
|
+
social x bookmarks --limit 20 | jq '{cost: .meta.cost, cursor: .meta.cursor}'
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Agents should watch `.meta.cost` during high-fanout loops and use `social account usage`
|
|
232
|
+
or `social account logs` after a run to summarize actual spend.
|
|
233
|
+
|
|
150
234
|
## Account safety
|
|
151
235
|
|
|
152
236
|
Built so your accounts outlive your prototype.
|
|
153
237
|
|
|
154
|
-
- **Read scope by default.**
|
|
155
|
-
read-only session can't post, react, or
|
|
238
|
+
- **Read/write scope by default.** Clear Write during login when you want a
|
|
239
|
+
read-only session that can't post, react, or request connections.
|
|
156
240
|
- **A write never fires twice.** Rate-limit and server errors surface verbatim and
|
|
157
|
-
writes are never retried — so a post or
|
|
241
|
+
writes are never retried — so a post or connection request can't double-send.
|
|
158
242
|
- **A residential IP per account.** Each connected account runs over a dedicated
|
|
159
243
|
residential proxy with smart rate-limiting, so the network sees a normal session.
|
|
160
244
|
|
|
@@ -162,24 +246,28 @@ Built so your accounts outlive your prototype.
|
|
|
162
246
|
|
|
163
247
|
```sh
|
|
164
248
|
# LinkedIn
|
|
165
|
-
social linkedin search people "founder ai"
|
|
166
|
-
social linkedin
|
|
249
|
+
social linkedin search people "founder ai"
|
|
250
|
+
social linkedin profile
|
|
167
251
|
|
|
168
252
|
# X
|
|
169
|
-
social x
|
|
170
|
-
social x
|
|
253
|
+
social x bookmarks --limit 50
|
|
254
|
+
social x followers --limit 100
|
|
255
|
+
social x following profile_id:<x-user-id> --limit 100
|
|
256
|
+
social x messages --limit 50
|
|
171
257
|
|
|
172
258
|
# Usage / billing
|
|
173
|
-
social usage
|
|
174
|
-
social
|
|
259
|
+
social account usage
|
|
260
|
+
social account logs --limit 20 --from 2026-05-01T00:00:00Z
|
|
175
261
|
|
|
176
|
-
#
|
|
177
|
-
social schema
|
|
262
|
+
# Command schema
|
|
263
|
+
social schema
|
|
264
|
+
social schema --leaves
|
|
265
|
+
social schema "x post"
|
|
178
266
|
```
|
|
179
267
|
|
|
180
268
|
## Links
|
|
181
269
|
|
|
182
|
-
- Pricing and limits: <https://
|
|
183
|
-
- Terms: <https://
|
|
270
|
+
- Pricing and limits: <https://usesocial.dev/pricing>
|
|
271
|
+
- Terms: <https://usesocial.dev/terms> · Privacy: <https://usesocial.dev/privacy>
|
|
184
272
|
|
|
185
|
-
Built by founders
|
|
273
|
+
Built by founders who needed their agents to keep distribution moving.
|
package/bin/social.mjs
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
2
3
|
import { dirname, join } from "node:path";
|
|
4
|
+
import { loadEnvFile } from "node:process";
|
|
3
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
6
|
|
|
5
7
|
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
8
|
+
const localEnvPath = join(packageRoot, "..", "..", ".env.staging");
|
|
6
9
|
const entryURL = pathToFileURL(join(packageRoot, "dist", "index.mjs")).href;
|
|
7
10
|
|
|
11
|
+
if (existsSync(localEnvPath)) {
|
|
12
|
+
loadEnvFile(localEnvPath);
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
import(entryURL).catch((error) => {
|
|
9
16
|
console.error(error);
|
|
10
17
|
process.exit(1);
|
package/dist/index.d.mts
CHANGED
|
@@ -1 +1,98 @@
|
|
|
1
|
-
|
|
1
|
+
//#region ../../node_modules/.bun/citty@0.2.2/node_modules/citty/dist/index.d.mts
|
|
2
|
+
//#region src/types.d.ts
|
|
3
|
+
type ArgType = "boolean" | "string" | "enum" | "positional" | undefined;
|
|
4
|
+
type _ArgDef<T extends ArgType, VT extends boolean | number | string> = {
|
|
5
|
+
type?: T;
|
|
6
|
+
description?: string;
|
|
7
|
+
valueHint?: string;
|
|
8
|
+
alias?: string | string[];
|
|
9
|
+
default?: VT;
|
|
10
|
+
required?: boolean;
|
|
11
|
+
options?: string[];
|
|
12
|
+
};
|
|
13
|
+
type BooleanArgDef = Omit<_ArgDef<"boolean", boolean>, "options"> & {
|
|
14
|
+
negativeDescription?: string;
|
|
15
|
+
};
|
|
16
|
+
type StringArgDef = Omit<_ArgDef<"string", string>, "options">;
|
|
17
|
+
type EnumArgDef = _ArgDef<"enum", string>;
|
|
18
|
+
type PositionalArgDef = Omit<_ArgDef<"positional", string>, "alias" | "options">;
|
|
19
|
+
type ArgDef = BooleanArgDef | StringArgDef | PositionalArgDef | EnumArgDef;
|
|
20
|
+
type ArgsDef = Record<string, ArgDef>;
|
|
21
|
+
type ResolveParsedArgType<T extends ArgDef, VT> = T extends {
|
|
22
|
+
default?: any;
|
|
23
|
+
required?: boolean;
|
|
24
|
+
} ? T["default"] extends NonNullable<VT> ? VT : T["required"] extends true ? VT : VT | undefined : VT | undefined;
|
|
25
|
+
type ParsedPositionalArg<T extends ArgDef> = T extends {
|
|
26
|
+
type: "positional";
|
|
27
|
+
} ? ResolveParsedArgType<T, string> : never;
|
|
28
|
+
type ParsedStringArg<T extends ArgDef> = T extends {
|
|
29
|
+
type: "string";
|
|
30
|
+
} ? ResolveParsedArgType<T, string> : never;
|
|
31
|
+
type ParsedBooleanArg<T extends ArgDef> = T extends {
|
|
32
|
+
type: "boolean";
|
|
33
|
+
} ? ResolveParsedArgType<T, boolean> : never;
|
|
34
|
+
type ParsedEnumArg<T extends ArgDef> = T extends {
|
|
35
|
+
type: "enum";
|
|
36
|
+
options: infer U;
|
|
37
|
+
} ? U extends Array<any> ? ResolveParsedArgType<T, U[number]> : never : never;
|
|
38
|
+
type RawArgs = {
|
|
39
|
+
_: string[];
|
|
40
|
+
};
|
|
41
|
+
type ParsedArg<T extends ArgDef> = T["type"] extends "positional" ? ParsedPositionalArg<T> : T["type"] extends "boolean" ? ParsedBooleanArg<T> : T["type"] extends "string" ? ParsedStringArg<T> : T["type"] extends "enum" ? ParsedEnumArg<T> : never;
|
|
42
|
+
type ParsedArgs<T extends ArgsDef = ArgsDef> = RawArgs & { [K in keyof T]: ParsedArg<T[K]> } & { [K in keyof T as T[K] extends {
|
|
43
|
+
alias: string;
|
|
44
|
+
} ? T[K]["alias"] : never]: ParsedArg<T[K]> } & { [K in keyof T as T[K] extends {
|
|
45
|
+
alias: string[];
|
|
46
|
+
} ? T[K]["alias"][number] : never]: ParsedArg<T[K]> } & Record<string, string | number | boolean | string[]>;
|
|
47
|
+
interface CommandMeta {
|
|
48
|
+
name?: string;
|
|
49
|
+
version?: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
hidden?: boolean;
|
|
52
|
+
alias?: string | string[];
|
|
53
|
+
}
|
|
54
|
+
type SubCommandsDef = Record<string, Resolvable<CommandDef<any>>>;
|
|
55
|
+
type CommandDef<T extends ArgsDef = ArgsDef> = {
|
|
56
|
+
meta?: Resolvable<CommandMeta>;
|
|
57
|
+
args?: Resolvable<T>;
|
|
58
|
+
default?: Resolvable<string>;
|
|
59
|
+
subCommands?: Resolvable<SubCommandsDef>;
|
|
60
|
+
plugins?: Resolvable<CittyPlugin>[];
|
|
61
|
+
setup?: (context: CommandContext<T>) => any | Promise<any>;
|
|
62
|
+
cleanup?: (context: CommandContext<T>) => any | Promise<any>;
|
|
63
|
+
run?: (context: CommandContext<T>) => any | Promise<any>;
|
|
64
|
+
};
|
|
65
|
+
type CommandContext<T extends ArgsDef = ArgsDef> = {
|
|
66
|
+
rawArgs: string[];
|
|
67
|
+
args: ParsedArgs<T>;
|
|
68
|
+
cmd: CommandDef<T>;
|
|
69
|
+
subCommand?: CommandDef<T>;
|
|
70
|
+
data?: any;
|
|
71
|
+
};
|
|
72
|
+
type CittyPlugin = {
|
|
73
|
+
name: string;
|
|
74
|
+
setup?(context: CommandContext<any>): void | Promise<void>;
|
|
75
|
+
cleanup?(context: CommandContext<any>): void | Promise<void>;
|
|
76
|
+
};
|
|
77
|
+
type Resolvable<T> = T | Promise<T> | (() => T) | (() => Promise<T>); //#endregion
|
|
78
|
+
//#region src/command.d.ts
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/index.d.ts
|
|
81
|
+
type MutableCommand = CommandDef<any> & {
|
|
82
|
+
args?: any;
|
|
83
|
+
meta?: any;
|
|
84
|
+
subCommands?: any;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Resolves the chain of matched command NAMES for analytics, e.g.
|
|
88
|
+
* `social x tweets get <id>` → `["x", "tweets", "get"]`. Mirrors the
|
|
89
|
+
* `commandForUsage` walk but collects names.
|
|
90
|
+
*
|
|
91
|
+
* PRIVACY: only tokens that resolve to a real subcommand are appended. The first
|
|
92
|
+
* arg that does not resolve (a positional value: tweet ID, handle, query text,
|
|
93
|
+
* flag value) breaks the walk and is NEVER captured. Never returns rawArgs or
|
|
94
|
+
* flag values.
|
|
95
|
+
*/
|
|
96
|
+
declare const resolveCommandPath: (command: MutableCommand, rawArgs: string[]) => Promise<string[]>;
|
|
97
|
+
//#endregion
|
|
98
|
+
export { resolveCommandPath };
|