aport-cli 0.4.0 → 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/dist/cli.js +34 -25
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* aport accounts # list identities, show active
|
|
9
9
|
* aport use creator # switch active account
|
|
10
10
|
* export APORT_ACCOUNT=fan # bind an account to a shell/Hermes session
|
|
11
|
-
* aport --account fan
|
|
11
|
+
* aport --account fan post ... # per-command override
|
|
12
12
|
*
|
|
13
|
-
* Then: search /
|
|
13
|
+
* Then: post / search / subscribe / feed / read over the signed HTTP API.
|
|
14
14
|
* Target API: --url, or APORT_API_URL, or the hosted default.
|
|
15
15
|
*/
|
|
16
16
|
import { readFile } from "node:fs/promises";
|
|
@@ -86,10 +86,10 @@ async function signedGet(g, id, path) {
|
|
|
86
86
|
}
|
|
87
87
|
function renderTable(rows) {
|
|
88
88
|
const cols = [
|
|
89
|
-
{ header: "
|
|
89
|
+
{ header: "POST", get: (r) => r.description ?? "(untitled)" },
|
|
90
90
|
{ header: "PRICE", get: (r) => `$${Number(r.priceUsd).toFixed(2)}` },
|
|
91
91
|
{ header: "SIM", get: (r) => Number(r.similarity).toFixed(3) },
|
|
92
|
-
{ header: "
|
|
92
|
+
{ header: "ID", get: (r) => r.id },
|
|
93
93
|
];
|
|
94
94
|
const widths = cols.map((c) => Math.max(c.header.length, ...rows.map((r) => c.get(r).length)));
|
|
95
95
|
const row = (cells) => "| " + cells.map((cell, i) => cell.padEnd(widths[i] ?? 0)).join(" | ") + " |";
|
|
@@ -166,7 +166,7 @@ const program = new Command();
|
|
|
166
166
|
program
|
|
167
167
|
.name("aport")
|
|
168
168
|
.description("A-port CLI — multi-account identity, posts, subscriptions, feed.")
|
|
169
|
-
.version("0.
|
|
169
|
+
.version("0.5.0")
|
|
170
170
|
.option("-u, --url <url>", "API base URL (default APORT_API_URL or the hosted A-port)")
|
|
171
171
|
.option("--account <name>", "use this account (overrides $APORT_ACCOUNT / active)");
|
|
172
172
|
/* ---- identity / accounts ---- */
|
|
@@ -229,42 +229,51 @@ program
|
|
|
229
229
|
});
|
|
230
230
|
/* ---- marketplace ---- */
|
|
231
231
|
program
|
|
232
|
-
.command("
|
|
233
|
-
.description("
|
|
234
|
-
.requiredOption("--
|
|
235
|
-
.
|
|
236
|
-
.
|
|
237
|
-
.option("--price <usd>", "price in USD", "0")
|
|
232
|
+
.command("post")
|
|
233
|
+
.description("Post to your feed — free, or priced for premium (signed).")
|
|
234
|
+
.requiredOption("--title <text>", "post title / caption (public)")
|
|
235
|
+
.option("--file <path>", "body content from a file (premium payload)")
|
|
236
|
+
.option("--text <text>", "body content inline (alternative to --file)")
|
|
237
|
+
.option("--price <usd>", "price in USD (0 = free)", "0")
|
|
238
238
|
.action(async (opts, command) => {
|
|
239
239
|
const g = command.optsWithGlobals();
|
|
240
240
|
const id = loadOrExit(g);
|
|
241
241
|
if (!id)
|
|
242
242
|
return;
|
|
243
243
|
let body;
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
244
|
+
if (opts.file) {
|
|
245
|
+
try {
|
|
246
|
+
body = await readFile(opts.file, "utf8");
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
console.error(red(`cannot read file: ${opts.file}`));
|
|
250
|
+
process.exitCode = 1;
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
else if (typeof opts.text === "string") {
|
|
255
|
+
body = opts.text;
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
console.error(red("provide --file <path> or --text <content> for the post body"));
|
|
249
259
|
process.exitCode = 1;
|
|
250
260
|
return;
|
|
251
261
|
}
|
|
252
262
|
const { res, json } = await signedPost(g, id, "/api/articles/publish", {
|
|
253
|
-
|
|
254
|
-
description: opts.desc,
|
|
263
|
+
description: opts.title,
|
|
255
264
|
body,
|
|
256
265
|
priceUsd: Number(opts.price),
|
|
257
266
|
});
|
|
258
267
|
if (!res.ok) {
|
|
259
|
-
console.error(red(`✗
|
|
268
|
+
console.error(red(`✗ post failed (${res.status}): ${errorMessage(json, "unknown error")}`));
|
|
260
269
|
process.exitCode = 1;
|
|
261
270
|
return;
|
|
262
271
|
}
|
|
263
272
|
const data = json;
|
|
264
|
-
console.log(green(`✓
|
|
265
|
-
console.log(`
|
|
266
|
-
console.log(`
|
|
267
|
-
console.log(` price
|
|
273
|
+
console.log(green(`✓ posted to ${id.name}'s feed`));
|
|
274
|
+
console.log(` id : ${data.id}`);
|
|
275
|
+
console.log(` title : ${opts.title}`);
|
|
276
|
+
console.log(` price : $${Number(opts.price).toFixed(2)} (${body.length} bytes)`);
|
|
268
277
|
});
|
|
269
278
|
program
|
|
270
279
|
.command("search")
|
|
@@ -402,8 +411,8 @@ program
|
|
|
402
411
|
for (const p of feed) {
|
|
403
412
|
const mark = p.locked ? red("🔒") : green("●");
|
|
404
413
|
const price = p.priceUsd > 0 ? `$${Number(p.priceUsd).toFixed(2)}` : "free";
|
|
405
|
-
console.log(`${mark} ${cyan(p.
|
|
406
|
-
console.log(dim(` id ${p.id}${p.locked ? "
|
|
414
|
+
console.log(`${mark} ${cyan(p.description)} ${dim(price)}`);
|
|
415
|
+
console.log(dim(` id ${p.id}${p.locked ? " · 🔒 subscribe to read" : ""}`));
|
|
407
416
|
}
|
|
408
417
|
});
|
|
409
418
|
program
|