@usesocial/cli 0.3.6 → 0.5.0
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 +12 -0
- package/README.md +13 -3
- package/dist/index.d.mts +5 -4
- package/dist/index.mjs +194 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @usesocial/cli
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#29](https://github.com/usesocial/monorepo/pull/29) [`f99f1b3`](https://github.com/usesocial/monorepo/commit/f99f1b3da1215c74a1044aac3aed210604562fcc) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Add `social account billing` and `social account billing portal` for CLI billing status and hosted portal handoff.
|
|
8
|
+
|
|
9
|
+
## 0.4.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [#25](https://github.com/usesocial/monorepo/pull/25) [`1121b7c`](https://github.com/usesocial/monorepo/commit/1121b7c938bfb213606722247d50a5eafca138c4) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Add `social feedback bug|feature` — submit a bug report or feature request by piping text via stdin (`echo "..." | social feedback bug`). Each submission is captured server-side and acknowledged with a reference id.
|
|
14
|
+
|
|
3
15
|
## 0.3.6
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ stdin; if stdin parses as JSON but is not an object, the command rejects it.
|
|
|
90
90
|
|
|
91
91
|
| Command | Description |
|
|
92
92
|
|---|---|
|
|
93
|
-
| `social account` | Show auth state and connected accounts; login, logout, connect accounts, inspect usage/logs, and configure local CLI settings. |
|
|
93
|
+
| `social account` | Show auth state and connected accounts; login, logout, connect accounts, inspect billing/usage/logs, and configure local CLI settings. |
|
|
94
94
|
| `social schema` | Print the compact command tree, inspect one command with `social schema "<command path>"`, or emit agent command contracts with `social schema --leaves`. |
|
|
95
95
|
| `social x <…>` | X operations (below). |
|
|
96
96
|
| `social linkedin <…>` | LinkedIn operations (below). |
|
|
@@ -108,6 +108,8 @@ stdin; if stdin parses as JSON but is not an object, the command rejects it.
|
|
|
108
108
|
| `reconnect x <account>` | Re-auth an existing X account by opening or printing an OAuth URL. | ✎ write |
|
|
109
109
|
| `disconnect linkedin <account>` | Disconnect a LinkedIn account. | ✎ write |
|
|
110
110
|
| `disconnect x <account>` | Disconnect an X account. | ✎ write |
|
|
111
|
+
| `billing` | Show seats, subscription, and current usage billing. | |
|
|
112
|
+
| `billing portal` | Open the hosted billing portal and print its URL. | |
|
|
111
113
|
| `usage` | Aggregate proxy usage and billing stats. | |
|
|
112
114
|
| `logs` | Recent proxy calls. | |
|
|
113
115
|
| `config cache mode` | Read or set the cache mode preset. | |
|
|
@@ -227,6 +229,11 @@ namespace, verified session when available, and connected accounts.
|
|
|
227
229
|
`social account login` requires an interactive terminal and is not supported from CI,
|
|
228
230
|
background jobs, or agent-mediated setup flows.
|
|
229
231
|
|
|
232
|
+
`social account billing` prints the current seat/subscription snapshot plus
|
|
233
|
+
aggregate usage billing. `social account billing portal` opens the hosted billing
|
|
234
|
+
portal when possible and always prints the portal URL as JSON; use the portal for
|
|
235
|
+
payment methods, invoices, plan changes, seat changes, and cancellation.
|
|
236
|
+
|
|
230
237
|
## Cache config
|
|
231
238
|
|
|
232
239
|
Allowlisted GET requests use a local proxy cache. Cacheable commands send
|
|
@@ -266,8 +273,9 @@ social linkedin messages --limit 20 | jq '{cost: .meta.cost, cursor: .meta.curso
|
|
|
266
273
|
social x bookmarks --limit 20 | jq '{cost: .meta.cost, cursor: .meta.cursor}'
|
|
267
274
|
```
|
|
268
275
|
|
|
269
|
-
Agents should watch `.meta.cost` during high-fanout loops
|
|
270
|
-
|
|
276
|
+
Agents should watch `.meta.cost` during high-fanout loops, use `social account billing`
|
|
277
|
+
for the current plan snapshot, and use `social account usage` or `social account logs`
|
|
278
|
+
after a run to summarize actual spend.
|
|
271
279
|
|
|
272
280
|
## Account safety
|
|
273
281
|
|
|
@@ -300,6 +308,8 @@ echo "gm" | social x post
|
|
|
300
308
|
social linkedin post < draft.md
|
|
301
309
|
|
|
302
310
|
# Usage / billing
|
|
311
|
+
social account billing
|
|
312
|
+
social account billing portal
|
|
303
313
|
social account usage
|
|
304
314
|
social account logs --limit 20 --from 2026-05-01T00:00:00Z
|
|
305
315
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1377,21 +1377,22 @@ declare const createSocialCommand: (deps?: {
|
|
|
1377
1377
|
disconnect: any;
|
|
1378
1378
|
};
|
|
1379
1379
|
billing: {
|
|
1380
|
-
status: () => Promise<
|
|
1381
|
-
canConnect: any;
|
|
1382
|
-
seats: any;
|
|
1383
|
-
}>;
|
|
1380
|
+
status: () => Promise<any>;
|
|
1384
1381
|
prepareAccountConnect: () => Promise<{
|
|
1385
1382
|
canConnect: any;
|
|
1386
1383
|
paymentURL: any;
|
|
1387
1384
|
requiredAction: any;
|
|
1388
1385
|
seats: any;
|
|
1389
1386
|
}>;
|
|
1387
|
+
portalURL: any;
|
|
1390
1388
|
};
|
|
1391
1389
|
usage: {
|
|
1392
1390
|
summary: any;
|
|
1393
1391
|
list: any;
|
|
1394
1392
|
};
|
|
1393
|
+
feedback: {
|
|
1394
|
+
submit: any;
|
|
1395
|
+
};
|
|
1395
1396
|
};
|
|
1396
1397
|
api: KyInstance;
|
|
1397
1398
|
parseResourceId: (name: string, value: unknown) => string;
|
package/dist/index.mjs
CHANGED
|
@@ -9740,6 +9740,14 @@ pgTable("profiles", {
|
|
|
9740
9740
|
index$1("profiles_platform_handle_idx").on(table.platform, table.handle),
|
|
9741
9741
|
check("profiles_platform_check", sql`${table.platform} in ('linkedin', 'x')`)
|
|
9742
9742
|
]);
|
|
9743
|
+
pgTable("feedback_submissions", {
|
|
9744
|
+
id: text$1("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
9745
|
+
userId: text$1("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
|
|
9746
|
+
type: text$1("type", { enum: ["bug", "feature"] }).notNull(),
|
|
9747
|
+
text: text$1("text").notNull(),
|
|
9748
|
+
issueNumber: integer$1("issue_number"),
|
|
9749
|
+
createdAt: timestamptz("created_at").notNull().defaultNow()
|
|
9750
|
+
}, (table) => [index$1("feedback_submissions_user_created_idx").on(table.userId, table.createdAt.desc()), check("feedback_submissions_type_check", sql`${table.type} in ('bug', 'feature')`)]);
|
|
9743
9751
|
pgTable("cli_session_grants", {
|
|
9744
9752
|
sessionId: text$1("session_id").primaryKey().references(() => session.id, { onDelete: "cascade" }),
|
|
9745
9753
|
userId: text$1("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
|
|
@@ -13333,8 +13341,8 @@ const dataWithAuditableWriteTarget = (op, data, body) => {
|
|
|
13333
13341
|
post_id: postId
|
|
13334
13342
|
};
|
|
13335
13343
|
};
|
|
13336
|
-
const trimTrailingNewline$
|
|
13337
|
-
const noBodyTextError$
|
|
13344
|
+
const trimTrailingNewline$2 = (value) => value.endsWith("\r\n") ? value.slice(0, -2) : value.endsWith("\n") ? value.slice(0, -1) : value;
|
|
13345
|
+
const noBodyTextError$2 = (commandLabel) => new UsageError(`No body text. Pipe it via stdin: \`echo "..." | ${commandLabel}\`.`);
|
|
13338
13346
|
const parseStdinBody$1 = (deps, bodyTextName, bodyTextKey, value) => {
|
|
13339
13347
|
try {
|
|
13340
13348
|
JSON.parse(value);
|
|
@@ -13350,12 +13358,12 @@ const resolveBodyTextFromStdin$1 = async (op, deps, args, commandLabel) => {
|
|
|
13350
13358
|
const displayTextArg = bodyTextDisplayKeyFor$1(op) ?? bodyTextArg;
|
|
13351
13359
|
const required = stdinBodyTextRequired$1(op);
|
|
13352
13360
|
if (deps.isStdinTTY()) {
|
|
13353
|
-
if (required) throw noBodyTextError$
|
|
13361
|
+
if (required) throw noBodyTextError$2(commandLabel);
|
|
13354
13362
|
return;
|
|
13355
13363
|
}
|
|
13356
|
-
const piped = trimTrailingNewline$
|
|
13364
|
+
const piped = trimTrailingNewline$2(await deps.readStdin());
|
|
13357
13365
|
if (piped.length > 0) args.body = JSON.stringify(parseStdinBody$1(deps, displayTextArg, bodyTextArg, piped));
|
|
13358
|
-
else if (required) throw noBodyTextError$
|
|
13366
|
+
else if (required) throw noBodyTextError$2(commandLabel);
|
|
13359
13367
|
};
|
|
13360
13368
|
const runOperation$1 = async (op, contract, deps, args, rawArgs = []) => {
|
|
13361
13369
|
rejectUnsupportedArgs(commandPathFor(op), args, Object.keys(buildArgs$1(op)));
|
|
@@ -14002,11 +14010,11 @@ const buildMessageEdit = (deps) => {
|
|
|
14002
14010
|
const account = typeof args.account === "string" ? args.account : void 0;
|
|
14003
14011
|
const message_id = messageIdFrom(deps, args.message_id ?? positionals[1]);
|
|
14004
14012
|
let textInput;
|
|
14005
|
-
if (deps.isStdinTTY()) throw noBodyTextError$
|
|
14006
|
-
const piped = trimTrailingNewline$
|
|
14013
|
+
if (deps.isStdinTTY()) throw noBodyTextError$2("social linkedin message <target> edit message_id:<id>");
|
|
14014
|
+
const piped = trimTrailingNewline$2(await deps.readStdin());
|
|
14007
14015
|
if (piped.length > 0) textInput = piped;
|
|
14008
14016
|
const text = textInput === void 0 ? void 0 : deps.parseBodyText("<text>", textInput);
|
|
14009
|
-
if (text === void 0) throw noBodyTextError$
|
|
14017
|
+
if (text === void 0) throw noBodyTextError$2("social linkedin message <target> edit message_id:<id>");
|
|
14010
14018
|
const resolved = [];
|
|
14011
14019
|
const chatIdResolved = await deps.resolveTarget("target", args.target ?? positionals[0], {
|
|
14012
14020
|
platform: "linkedin",
|
|
@@ -14085,10 +14093,10 @@ const buildMessage$1 = (deps, sendCommand) => {
|
|
|
14085
14093
|
}
|
|
14086
14094
|
const target = args.target ?? (Array.isArray(args._) && args._.length > 0 ? args._[0] : void 0);
|
|
14087
14095
|
let body;
|
|
14088
|
-
if (deps.isStdinTTY()) throw noBodyTextError$
|
|
14089
|
-
const piped = trimTrailingNewline$
|
|
14096
|
+
if (deps.isStdinTTY()) throw noBodyTextError$2("social linkedin message <target>");
|
|
14097
|
+
const piped = trimTrailingNewline$2(await deps.readStdin());
|
|
14090
14098
|
if (piped.length > 0) body = parseStdinBody$1(deps, "text", "text", piped);
|
|
14091
|
-
else throw noBodyTextError$
|
|
14099
|
+
else throw noBodyTextError$2("social linkedin message <target>");
|
|
14092
14100
|
if (target === void 0) throw new UsageError("Pass a conversation or person target.");
|
|
14093
14101
|
if (body === void 0 || typeof body.text !== "string") throw new UsageError("Pass body text via stdin.");
|
|
14094
14102
|
const account = typeof args.account === "string" ? args.account : void 0;
|
|
@@ -17423,8 +17431,8 @@ const withEchoedTargetId = (op, data, body) => {
|
|
|
17423
17431
|
}
|
|
17424
17432
|
};
|
|
17425
17433
|
};
|
|
17426
|
-
const trimTrailingNewline = (value) => value.endsWith("\r\n") ? value.slice(0, -2) : value.endsWith("\n") ? value.slice(0, -1) : value;
|
|
17427
|
-
const noBodyTextError = (commandLabel) => new UsageError(`No body text. Pipe it via stdin: \`echo "..." | ${commandLabel}\`.`);
|
|
17434
|
+
const trimTrailingNewline$1 = (value) => value.endsWith("\r\n") ? value.slice(0, -2) : value.endsWith("\n") ? value.slice(0, -1) : value;
|
|
17435
|
+
const noBodyTextError$1 = (commandLabel) => new UsageError(`No body text. Pipe it via stdin: \`echo "..." | ${commandLabel}\`.`);
|
|
17428
17436
|
const parseStdinBody = (deps, bodyTextName, bodyTextKey, value) => {
|
|
17429
17437
|
try {
|
|
17430
17438
|
JSON.parse(value);
|
|
@@ -17440,12 +17448,12 @@ const resolveBodyTextFromStdin = async (op, deps, args, commandLabel) => {
|
|
|
17440
17448
|
const displayTextArg = bodyTextDisplayKeyFor(op) ?? bodyTextArg;
|
|
17441
17449
|
const required = stdinBodyTextRequired(op);
|
|
17442
17450
|
if (deps.isStdinTTY()) {
|
|
17443
|
-
if (required) throw noBodyTextError(commandLabel);
|
|
17451
|
+
if (required) throw noBodyTextError$1(commandLabel);
|
|
17444
17452
|
return;
|
|
17445
17453
|
}
|
|
17446
|
-
const piped = trimTrailingNewline(await deps.readStdin());
|
|
17454
|
+
const piped = trimTrailingNewline$1(await deps.readStdin());
|
|
17447
17455
|
if (piped.length > 0) args.body = JSON.stringify(parseStdinBody(deps, displayTextArg, bodyTextArg, piped));
|
|
17448
|
-
else if (required) throw noBodyTextError(commandLabel);
|
|
17456
|
+
else if (required) throw noBodyTextError$1(commandLabel);
|
|
17449
17457
|
};
|
|
17450
17458
|
const runOperation = async (op, contract, deps, args, rawArgs = []) => {
|
|
17451
17459
|
rejectUnknownArgs(op, args);
|
|
@@ -18019,14 +18027,14 @@ const buildMessage = (deps) => {
|
|
|
18019
18027
|
if (typeof args.body === "string") throw new UsageError("Unsupported option --body for x message.");
|
|
18020
18028
|
const recipientsInput = args.recipients ?? args.target ?? (Array.isArray(args._) && args._.length > 0 ? args._[0] : void 0);
|
|
18021
18029
|
let body;
|
|
18022
|
-
if (deps.isStdinTTY()) throw noBodyTextError("social x message <recipients>");
|
|
18023
|
-
const piped = trimTrailingNewline(await deps.readStdin());
|
|
18030
|
+
if (deps.isStdinTTY()) throw noBodyTextError$1("social x message <recipients>");
|
|
18031
|
+
const piped = trimTrailingNewline$1(await deps.readStdin());
|
|
18024
18032
|
if (piped.length > 0) body = parseStdinBody(deps, "text", "text", piped);
|
|
18025
|
-
else throw noBodyTextError("social x message <recipients>");
|
|
18033
|
+
else throw noBodyTextError$1("social x message <recipients>");
|
|
18026
18034
|
if (recipientsInput === void 0) throw new UsageError("Pass a conversation or user target.");
|
|
18027
18035
|
const recipients = String(recipientsInput).split(",").map((recipient) => recipient.trim()).filter((recipient) => recipient.length > 0);
|
|
18028
18036
|
if (recipients.length === 0) throw new UsageError("Pass at least one recipient.");
|
|
18029
|
-
if (body === void 0) throw noBodyTextError("social x message <recipients>");
|
|
18037
|
+
if (body === void 0) throw noBodyTextError$1("social x message <recipients>");
|
|
18030
18038
|
const resolved = [];
|
|
18031
18039
|
const account = typeof args.account === "string" ? args.account : void 0;
|
|
18032
18040
|
const selectedAccount = await deps.resolveAccount({
|
|
@@ -21102,7 +21110,7 @@ const createInstance = (defaults) => {
|
|
|
21102
21110
|
const ky = createInstance();
|
|
21103
21111
|
//#endregion
|
|
21104
21112
|
//#region package.json
|
|
21105
|
-
var version$1 = "0.
|
|
21113
|
+
var version$1 = "0.5.0";
|
|
21106
21114
|
//#endregion
|
|
21107
21115
|
//#region src/lib/env.ts
|
|
21108
21116
|
const URLWithTrailingSlash = url().transform(ensureTrailingSlash);
|
|
@@ -22030,6 +22038,102 @@ const configCommand = defineCommand({
|
|
|
22030
22038
|
}) }
|
|
22031
22039
|
});
|
|
22032
22040
|
//#endregion
|
|
22041
|
+
//#region src/billing/index.ts
|
|
22042
|
+
const readAuthContract$1 = {
|
|
22043
|
+
required: true,
|
|
22044
|
+
scope: "read"
|
|
22045
|
+
};
|
|
22046
|
+
const BillingOutput = object({
|
|
22047
|
+
seats: object({
|
|
22048
|
+
total: number().int().nonnegative(),
|
|
22049
|
+
used: number().int().nonnegative(),
|
|
22050
|
+
available: number().int().nonnegative()
|
|
22051
|
+
}),
|
|
22052
|
+
subscription: object({
|
|
22053
|
+
active: boolean$1(),
|
|
22054
|
+
quantity: number().int().nonnegative(),
|
|
22055
|
+
currentPeriodEnd: string().nullable()
|
|
22056
|
+
}).nullable(),
|
|
22057
|
+
usage: object({
|
|
22058
|
+
calls: object({ total: number().int().nonnegative() }),
|
|
22059
|
+
credits: object({
|
|
22060
|
+
available: number().nonnegative(),
|
|
22061
|
+
used: number().nonnegative(),
|
|
22062
|
+
additional: number().nonnegative()
|
|
22063
|
+
}),
|
|
22064
|
+
billing: object({
|
|
22065
|
+
seats: number().nonnegative(),
|
|
22066
|
+
usage: number().nonnegative()
|
|
22067
|
+
})
|
|
22068
|
+
})
|
|
22069
|
+
});
|
|
22070
|
+
const BillingPortalOutput = object({
|
|
22071
|
+
url: string(),
|
|
22072
|
+
opened: boolean$1()
|
|
22073
|
+
});
|
|
22074
|
+
const writeOutput$2 = async (deps, value) => {
|
|
22075
|
+
if (deps.writeOutput) {
|
|
22076
|
+
await deps.writeOutput(value);
|
|
22077
|
+
return;
|
|
22078
|
+
}
|
|
22079
|
+
printData(value);
|
|
22080
|
+
};
|
|
22081
|
+
const clientFrom = (deps) => deps.client ?? createORPCAPIClient();
|
|
22082
|
+
const createBillingCommand = (deps = {}) => {
|
|
22083
|
+
const portal = defineCommand({
|
|
22084
|
+
meta: commandMeta({
|
|
22085
|
+
name: "portal",
|
|
22086
|
+
description: "Open the hosted billing portal.",
|
|
22087
|
+
capability: "read",
|
|
22088
|
+
contract: {
|
|
22089
|
+
capability: "read",
|
|
22090
|
+
auth: readAuthContract$1,
|
|
22091
|
+
mutates: false,
|
|
22092
|
+
outputSchema: BillingPortalOutput,
|
|
22093
|
+
confirmation: {
|
|
22094
|
+
required: true,
|
|
22095
|
+
reason: "Opens a hosted billing portal where payment methods, seats, plan, and cancellation can be managed."
|
|
22096
|
+
},
|
|
22097
|
+
hazards: [{
|
|
22098
|
+
code: "billing_portal_handoff",
|
|
22099
|
+
message: "Hosted billing portal handoff; billing changes happen outside the CLI after the URL opens."
|
|
22100
|
+
}]
|
|
22101
|
+
}
|
|
22102
|
+
}),
|
|
22103
|
+
run: async () => {
|
|
22104
|
+
const { url } = await clientFrom(deps).billing.portalURL();
|
|
22105
|
+
const result = deps.isInteractiveTerminal?.() === true && deps.openURL !== void 0 ? await deps.openURL?.(url) : void 0;
|
|
22106
|
+
await writeOutput$2(deps, {
|
|
22107
|
+
url: result?.url ?? url,
|
|
22108
|
+
opened: result?.opened === true
|
|
22109
|
+
});
|
|
22110
|
+
}
|
|
22111
|
+
});
|
|
22112
|
+
return defineCommand({
|
|
22113
|
+
meta: commandMeta({
|
|
22114
|
+
name: "billing",
|
|
22115
|
+
description: "Show billing status and manage the hosted billing portal.",
|
|
22116
|
+
capability: "read",
|
|
22117
|
+
contract: {
|
|
22118
|
+
capability: "read",
|
|
22119
|
+
auth: readAuthContract$1,
|
|
22120
|
+
mutates: false,
|
|
22121
|
+
outputSchema: BillingOutput
|
|
22122
|
+
}
|
|
22123
|
+
}),
|
|
22124
|
+
subCommands: { portal },
|
|
22125
|
+
run: async () => {
|
|
22126
|
+
const client = clientFrom(deps);
|
|
22127
|
+
const [status, usage] = await Promise.all([client.billing.status(), client.usage.summary({})]);
|
|
22128
|
+
await writeOutput$2(deps, {
|
|
22129
|
+
seats: status.seats,
|
|
22130
|
+
subscription: status.subscription,
|
|
22131
|
+
usage
|
|
22132
|
+
});
|
|
22133
|
+
}
|
|
22134
|
+
});
|
|
22135
|
+
};
|
|
22136
|
+
//#endregion
|
|
22033
22137
|
//#region ../../node_modules/.bun/posthog-node@5.35.6+63120419cc93e79b/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
|
|
22034
22138
|
function createModulerModifier() {
|
|
22035
22139
|
const getModuleFromFileName = createGetModuleFromFilename();
|
|
@@ -28461,6 +28565,7 @@ const createAccountCommand = (deps) => {
|
|
|
28461
28565
|
})
|
|
28462
28566
|
}
|
|
28463
28567
|
}),
|
|
28568
|
+
billing: createBillingCommand(deps),
|
|
28464
28569
|
usage: createUsageCommand(deps),
|
|
28465
28570
|
logs: createUsageLogsCommand(deps),
|
|
28466
28571
|
config: configCommand
|
|
@@ -28493,6 +28598,66 @@ const createAccountCommand = (deps) => {
|
|
|
28493
28598
|
});
|
|
28494
28599
|
};
|
|
28495
28600
|
//#endregion
|
|
28601
|
+
//#region src/lib/stdin.ts
|
|
28602
|
+
const trimTrailingNewline = (value) => value.endsWith("\r\n") ? value.slice(0, -2) : value.endsWith("\n") ? value.slice(0, -1) : value;
|
|
28603
|
+
const noBodyTextError = (commandLabel) => new UsageError(`No body text. Pipe it via stdin: \`echo "..." | ${commandLabel}\`.`);
|
|
28604
|
+
const readPipedText = async (deps, commandLabel) => {
|
|
28605
|
+
if (deps.isStdinTTY()) throw noBodyTextError(commandLabel);
|
|
28606
|
+
const text = trimTrailingNewline(await deps.readStdin());
|
|
28607
|
+
if (text.length === 0) throw noBodyTextError(commandLabel);
|
|
28608
|
+
return text;
|
|
28609
|
+
};
|
|
28610
|
+
//#endregion
|
|
28611
|
+
//#region src/feedback/index.ts
|
|
28612
|
+
const submitContract = {
|
|
28613
|
+
capability: "write",
|
|
28614
|
+
auth: {
|
|
28615
|
+
required: true,
|
|
28616
|
+
scope: "read,write"
|
|
28617
|
+
},
|
|
28618
|
+
mutates: true,
|
|
28619
|
+
outputSchema: object({
|
|
28620
|
+
id: string(),
|
|
28621
|
+
type: _enum(["bug", "feature"]),
|
|
28622
|
+
issueNumber: number().int().nullable(),
|
|
28623
|
+
createdAt: string()
|
|
28624
|
+
}),
|
|
28625
|
+
confirmation: false,
|
|
28626
|
+
hazards: [{
|
|
28627
|
+
code: "feedback_submit",
|
|
28628
|
+
message: "Sends your text to the maintainers as a tracked report."
|
|
28629
|
+
}]
|
|
28630
|
+
};
|
|
28631
|
+
const createSubmitCommand = (deps, type) => {
|
|
28632
|
+
const noun = type === "bug" ? "bug report" : "feature request";
|
|
28633
|
+
const label = `social feedback ${type}`;
|
|
28634
|
+
return defineCommand({
|
|
28635
|
+
meta: commandMeta({
|
|
28636
|
+
name: type,
|
|
28637
|
+
description: `Submit a ${noun} [write] | usage: \`echo "..." | ${label}\``,
|
|
28638
|
+
capability: "write",
|
|
28639
|
+
contract: submitContract
|
|
28640
|
+
}),
|
|
28641
|
+
run: async () => {
|
|
28642
|
+
const text = await readPipedText(deps, label);
|
|
28643
|
+
deps.printData(await deps.client.feedback.submit({
|
|
28644
|
+
type,
|
|
28645
|
+
text
|
|
28646
|
+
}));
|
|
28647
|
+
}
|
|
28648
|
+
});
|
|
28649
|
+
};
|
|
28650
|
+
const createFeedbackCommand = (deps) => defineCommand({
|
|
28651
|
+
meta: {
|
|
28652
|
+
name: "feedback",
|
|
28653
|
+
description: "Report a bug or request a feature."
|
|
28654
|
+
},
|
|
28655
|
+
subCommands: {
|
|
28656
|
+
bug: createSubmitCommand(deps, "bug"),
|
|
28657
|
+
feature: createSubmitCommand(deps, "feature")
|
|
28658
|
+
}
|
|
28659
|
+
});
|
|
28660
|
+
//#endregion
|
|
28496
28661
|
//#region src/lib/account.ts
|
|
28497
28662
|
const LEADING_AT_PATTERN = /^@+/;
|
|
28498
28663
|
const normalizeAccountIdentifier = (value) => value.trim().replace(LEADING_AT_PATTERN, "").toLowerCase();
|
|
@@ -28632,11 +28797,7 @@ const createCLIDeps = () => {
|
|
|
28632
28797
|
},
|
|
28633
28798
|
billing: {
|
|
28634
28799
|
status: async () => {
|
|
28635
|
-
|
|
28636
|
-
return {
|
|
28637
|
-
canConnect: status.canConnect,
|
|
28638
|
-
seats: status.seats
|
|
28639
|
-
};
|
|
28800
|
+
return await client.billing.status();
|
|
28640
28801
|
},
|
|
28641
28802
|
prepareAccountConnect: async () => {
|
|
28642
28803
|
const status = await client.billing.prepareAccountConnect();
|
|
@@ -28646,12 +28807,14 @@ const createCLIDeps = () => {
|
|
|
28646
28807
|
requiredAction: status.requiredAction,
|
|
28647
28808
|
seats: status.seats
|
|
28648
28809
|
};
|
|
28649
|
-
}
|
|
28810
|
+
},
|
|
28811
|
+
portalURL: client.billing.portalURL
|
|
28650
28812
|
},
|
|
28651
28813
|
usage: {
|
|
28652
28814
|
summary: client.usage.summary,
|
|
28653
28815
|
list: client.usage.list
|
|
28654
|
-
}
|
|
28816
|
+
},
|
|
28817
|
+
feedback: { submit: client.feedback.submit }
|
|
28655
28818
|
},
|
|
28656
28819
|
api,
|
|
28657
28820
|
parseResourceId,
|
|
@@ -29199,6 +29362,7 @@ const createSocialCommand = (deps = createCLIDeps()) => {
|
|
|
29199
29362
|
const accountCommand = createAccountCommand(deps);
|
|
29200
29363
|
const linkedinCommand = createLinkedinCommands(deps);
|
|
29201
29364
|
const xCommand = createXCommands(deps);
|
|
29365
|
+
const feedbackCommand = createFeedbackCommand(deps);
|
|
29202
29366
|
const socialCommand = defineCommand({
|
|
29203
29367
|
meta: {
|
|
29204
29368
|
name: "social",
|
|
@@ -29209,7 +29373,8 @@ const createSocialCommand = (deps = createCLIDeps()) => {
|
|
|
29209
29373
|
account: accountCommand,
|
|
29210
29374
|
schema: schemaCommand,
|
|
29211
29375
|
x: xCommand,
|
|
29212
|
-
linkedin: linkedinCommand
|
|
29376
|
+
linkedin: linkedinCommand,
|
|
29377
|
+
feedback: feedbackCommand
|
|
29213
29378
|
}
|
|
29214
29379
|
});
|
|
29215
29380
|
setSchemaRootCommand(socialCommand);
|