@paragraph-com/cli 0.1.0 → 0.1.1
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/index.js +58 -23
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -4741,6 +4741,7 @@ async function validateApiKey(token) {
|
|
|
4741
4741
|
const client = createClient(token);
|
|
4742
4742
|
const me = await client.me.get();
|
|
4743
4743
|
return {
|
|
4744
|
+
id: me.id,
|
|
4744
4745
|
name: me.name,
|
|
4745
4746
|
slug: me.slug,
|
|
4746
4747
|
customDomain: me.customDomain
|
|
@@ -4781,7 +4782,7 @@ async function waitForLogin(sessionId, signal) {
|
|
|
4781
4782
|
} catch (err) {
|
|
4782
4783
|
const msg = err instanceof Error ? err.message : String(err);
|
|
4783
4784
|
if (msg.includes("404") || msg.includes("Not found")) {
|
|
4784
|
-
throw new Error("Login was denied or expired.
|
|
4785
|
+
throw new Error("Login was denied or expired. For non-interactive use, pass the key directly: `paragraph login --token <key>` (get one at paragraph.com/settings \u2192 Publication \u2192 Developer).");
|
|
4785
4786
|
}
|
|
4786
4787
|
continue;
|
|
4787
4788
|
}
|
|
@@ -4789,10 +4790,10 @@ async function waitForLogin(sessionId, signal) {
|
|
|
4789
4790
|
return status.apiKey;
|
|
4790
4791
|
}
|
|
4791
4792
|
if (status.status !== "pending") {
|
|
4792
|
-
throw new Error("Login was denied or expired.
|
|
4793
|
+
throw new Error("Login was denied or expired. For non-interactive use, pass the key directly: `paragraph login --token <key>` (get one at paragraph.com/settings \u2192 Publication \u2192 Developer).");
|
|
4793
4794
|
}
|
|
4794
4795
|
}
|
|
4795
|
-
throw new Error("Login timed out after 5 minutes.
|
|
4796
|
+
throw new Error("Login timed out after 5 minutes. For non-interactive use, pass the key directly: `paragraph login --token <key>` (get one at paragraph.com/settings \u2192 Publication \u2192 Developer).");
|
|
4796
4797
|
}
|
|
4797
4798
|
function openBrowser(url) {
|
|
4798
4799
|
return new Promise((resolve, reject) => {
|
|
@@ -6733,8 +6734,11 @@ function extractError(err) {
|
|
|
6733
6734
|
const message = data?.message || err.message;
|
|
6734
6735
|
if (status === 401) {
|
|
6735
6736
|
return { message: "Unauthorized. Check your API key or run `paragraph login`.", status, code: errorCode(status) };
|
|
6737
|
+
} else if (status === 403) {
|
|
6738
|
+
return { message: "Forbidden. Your API key doesn't have access to this resource. Run `paragraph whoami --json` to verify which publication the key is for.", status, code: errorCode(status) };
|
|
6736
6739
|
} else if (status === 404) {
|
|
6737
|
-
|
|
6740
|
+
const detail = message ? `${message}. ` : "";
|
|
6741
|
+
return { message: `Not found. ${detail}Verify the identifier is correct \u2014 use the matching list command (e.g. \`paragraph post list --json\`, \`paragraph subscriber list --json\`) to find valid values.`, status, code: errorCode(status) };
|
|
6738
6742
|
} else if (status === 429) {
|
|
6739
6743
|
return { message: "Rate limited. Please wait and try again.", status, code: errorCode(status) };
|
|
6740
6744
|
}
|
|
@@ -6822,7 +6826,7 @@ Examples:
|
|
|
6822
6826
|
chunks.push(chunk);
|
|
6823
6827
|
}
|
|
6824
6828
|
token = Buffer.concat(chunks).toString("utf-8").trim();
|
|
6825
|
-
if (!token) throw new Error("No API key received on stdin.");
|
|
6829
|
+
if (!token) throw new Error("No API key received on stdin. Pipe the key (e.g. `echo $PARAGRAPH_API_KEY | paragraph login --with-token`) or use --token <key>.");
|
|
6826
6830
|
} else if (!process.stdin.isTTY) {
|
|
6827
6831
|
throw new Error(
|
|
6828
6832
|
"No --token provided and stdin is not a TTY. Use --token <key> or --with-token."
|
|
@@ -6877,6 +6881,7 @@ Examples:
|
|
|
6877
6881
|
const apiKey = requireApiKey();
|
|
6878
6882
|
const me = await validateApiKey(apiKey);
|
|
6879
6883
|
outputData(this, {
|
|
6884
|
+
ID: me.id,
|
|
6880
6885
|
Name: me.name,
|
|
6881
6886
|
Slug: me.slug,
|
|
6882
6887
|
Domain: me.customDomain
|
|
@@ -6999,7 +7004,8 @@ var init_zod = __esm({
|
|
|
6999
7004
|
}).optional().describe("Farcaster profile information, if linked")
|
|
7000
7005
|
})).optional().describe("Authors of this post"),
|
|
7001
7006
|
"authorIds": zod.array(zod.string()).optional().describe("IDs of the authors of this post"),
|
|
7002
|
-
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts")
|
|
7007
|
+
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts"),
|
|
7008
|
+
"status": zod.enum(["published", "draft", "scheduled", "archived"]).optional().describe("Current publish status. Only set on authenticated endpoints (listOwn, getById for your own post). Use this instead of publishedAt to determine publish state \u2014 publishedAt is preserved across unpublishing.")
|
|
7003
7009
|
}).describe("The post content"),
|
|
7004
7010
|
"publication": zod.object({
|
|
7005
7011
|
"id": zod.string().describe("Unique identifier for the publication"),
|
|
@@ -7073,7 +7079,8 @@ var init_zod = __esm({
|
|
|
7073
7079
|
}).optional().describe("Farcaster profile information, if linked")
|
|
7074
7080
|
})).optional().describe("Authors of this post"),
|
|
7075
7081
|
"authorIds": zod.array(zod.string()).optional().describe("IDs of the authors of this post"),
|
|
7076
|
-
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts")
|
|
7082
|
+
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts"),
|
|
7083
|
+
"status": zod.enum(["published", "draft", "scheduled", "archived"]).optional().describe("Current publish status. Only set on authenticated endpoints (listOwn, getById for your own post). Use this instead of publishedAt to determine publish state \u2014 publishedAt is preserved across unpublishing.")
|
|
7077
7084
|
})).describe("Array of items in this page"),
|
|
7078
7085
|
"pagination": zod.object({
|
|
7079
7086
|
"cursor": zod.string().optional().describe("Cursor for fetching the next page of results"),
|
|
@@ -7124,7 +7131,8 @@ var init_zod = __esm({
|
|
|
7124
7131
|
}).optional().describe("Farcaster profile information, if linked")
|
|
7125
7132
|
})).optional().describe("Authors of this post"),
|
|
7126
7133
|
"authorIds": zod.array(zod.string()).optional().describe("IDs of the authors of this post"),
|
|
7127
|
-
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts")
|
|
7134
|
+
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts"),
|
|
7135
|
+
"status": zod.enum(["published", "draft", "scheduled", "archived"]).optional().describe("Current publish status. Only set on authenticated endpoints (listOwn, getById for your own post). Use this instead of publishedAt to determine publish state \u2014 publishedAt is preserved across unpublishing.")
|
|
7128
7136
|
})).describe("Array of items in this page"),
|
|
7129
7137
|
"pagination": zod.object({
|
|
7130
7138
|
"cursor": zod.string().optional().describe("Cursor for fetching the next page of results"),
|
|
@@ -7170,7 +7178,8 @@ var init_zod = __esm({
|
|
|
7170
7178
|
}).optional().describe("Farcaster profile information, if linked")
|
|
7171
7179
|
})).optional().describe("Authors of this post"),
|
|
7172
7180
|
"authorIds": zod.array(zod.string()).optional().describe("IDs of the authors of this post"),
|
|
7173
|
-
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts")
|
|
7181
|
+
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts"),
|
|
7182
|
+
"status": zod.enum(["published", "draft", "scheduled", "archived"]).optional().describe("Current publish status. Only set on authenticated endpoints (listOwn, getById for your own post). Use this instead of publishedAt to determine publish state \u2014 publishedAt is preserved across unpublishing.")
|
|
7174
7183
|
});
|
|
7175
7184
|
updatePostParams = zod.object({
|
|
7176
7185
|
"postId": zod.string().describe("Unique identifier of the post to update")
|
|
@@ -7241,7 +7250,8 @@ var init_zod = __esm({
|
|
|
7241
7250
|
}).optional().describe("Farcaster profile information, if linked")
|
|
7242
7251
|
})).optional().describe("Authors of this post"),
|
|
7243
7252
|
"authorIds": zod.array(zod.string()).optional().describe("IDs of the authors of this post"),
|
|
7244
|
-
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts")
|
|
7253
|
+
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts"),
|
|
7254
|
+
"status": zod.enum(["published", "draft", "scheduled", "archived"]).optional().describe("Current publish status. Only set on authenticated endpoints (listOwn, getById for your own post). Use this instead of publishedAt to determine publish state \u2014 publishedAt is preserved across unpublishing.")
|
|
7245
7255
|
});
|
|
7246
7256
|
getPostByPublicationSlugAndPostSlugPathPublicationSlugMax = 256;
|
|
7247
7257
|
getPostByPublicationSlugAndPostSlugPathPostSlugMax = 256;
|
|
@@ -7284,7 +7294,8 @@ var init_zod = __esm({
|
|
|
7284
7294
|
}).optional().describe("Farcaster profile information, if linked")
|
|
7285
7295
|
})).optional().describe("Authors of this post"),
|
|
7286
7296
|
"authorIds": zod.array(zod.string()).optional().describe("IDs of the authors of this post"),
|
|
7287
|
-
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts")
|
|
7297
|
+
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts"),
|
|
7298
|
+
"status": zod.enum(["published", "draft", "scheduled", "archived"]).optional().describe("Current publish status. Only set on authenticated endpoints (listOwn, getById for your own post). Use this instead of publishedAt to determine publish state \u2014 publishedAt is preserved across unpublishing.")
|
|
7288
7299
|
});
|
|
7289
7300
|
createPostBodyTitleMax = 200;
|
|
7290
7301
|
createPostBodySubtitleMax = 300;
|
|
@@ -7348,7 +7359,8 @@ var init_zod = __esm({
|
|
|
7348
7359
|
}).optional().describe("Farcaster profile information, if linked")
|
|
7349
7360
|
})).optional().describe("Authors of this post"),
|
|
7350
7361
|
"authorIds": zod.array(zod.string()).optional().describe("IDs of the authors of this post"),
|
|
7351
|
-
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts")
|
|
7362
|
+
"views": zod.number().optional().describe("Total page views. Only included when fetching your own posts via GET /v1/posts"),
|
|
7363
|
+
"status": zod.enum(["published", "draft", "scheduled", "archived"]).optional().describe("Current publish status. Only set on authenticated endpoints (listOwn, getById for your own post). Use this instead of publishedAt to determine publish state \u2014 publishedAt is preserved across unpublishing.")
|
|
7352
7364
|
})).describe("Array of items in this page"),
|
|
7353
7365
|
"pagination": zod.object({
|
|
7354
7366
|
"cursor": zod.string().optional().describe("Cursor for fetching the next page of results"),
|
|
@@ -7905,7 +7917,7 @@ async function resolveOwnPost(idOrSlug, apiKey) {
|
|
|
7905
7917
|
const pub = await validateApiKey2(apiKey);
|
|
7906
7918
|
const pubSlug = pub.slug;
|
|
7907
7919
|
if (!pubSlug) {
|
|
7908
|
-
throw new Error(`Post not found: ${idOrSlug}
|
|
7920
|
+
throw new Error(`Post not found: "${idOrSlug}". Run \`paragraph post list --json\` to see your posts, or use the full \`@publication/slug\` form for posts outside your publication.`);
|
|
7909
7921
|
}
|
|
7910
7922
|
return getPostBySlugs(pubSlug, idOrSlug, apiKey);
|
|
7911
7923
|
}
|
|
@@ -7960,7 +7972,7 @@ async function updatePost(idOrSlug, params) {
|
|
|
7960
7972
|
await client.posts.update({ id: idOrSlug, ...body });
|
|
7961
7973
|
return;
|
|
7962
7974
|
} catch {
|
|
7963
|
-
if (!isSlug(idOrSlug)) throw new Error(`Post not found: ${idOrSlug}
|
|
7975
|
+
if (!isSlug(idOrSlug)) throw new Error(`Post not found: "${idOrSlug}". Run \`paragraph post list --json\` to see your posts, or use the full \`@publication/slug\` form for posts outside your publication.`);
|
|
7964
7976
|
}
|
|
7965
7977
|
await client.posts.update({ slug: idOrSlug, ...body });
|
|
7966
7978
|
}
|
|
@@ -7974,7 +7986,7 @@ async function deletePost(idOrSlug, apiKey) {
|
|
|
7974
7986
|
await client.posts.delete({ id: idOrSlug });
|
|
7975
7987
|
return;
|
|
7976
7988
|
} catch {
|
|
7977
|
-
if (!isSlug(idOrSlug)) throw new Error(`Post not found: ${idOrSlug}
|
|
7989
|
+
if (!isSlug(idOrSlug)) throw new Error(`Post not found: "${idOrSlug}". Run \`paragraph post list --json\` to see your posts, or use the full \`@publication/slug\` form for posts outside your publication.`);
|
|
7978
7990
|
}
|
|
7979
7991
|
await client.posts.delete({ slug: idOrSlug });
|
|
7980
7992
|
}
|
|
@@ -7985,7 +7997,7 @@ async function updatePostStatus(idOrSlug, status, apiKey, sendNewsletter) {
|
|
|
7985
7997
|
await client.posts.update({ id: idOrSlug, ...body });
|
|
7986
7998
|
return;
|
|
7987
7999
|
} catch {
|
|
7988
|
-
if (!isSlug(idOrSlug)) throw new Error(`Post not found: ${idOrSlug}
|
|
8000
|
+
if (!isSlug(idOrSlug)) throw new Error(`Post not found: "${idOrSlug}". Run \`paragraph post list --json\` to see your posts, or use the full \`@publication/slug\` form for posts outside your publication.`);
|
|
7989
8001
|
}
|
|
7990
8002
|
await client.posts.update({ slug: idOrSlug, ...body });
|
|
7991
8003
|
}
|
|
@@ -7999,7 +8011,7 @@ async function schedulePost(idOrSlug, scheduledAt, apiKey, sendNewsletter) {
|
|
|
7999
8011
|
await client.posts.update({ id: idOrSlug, ...body });
|
|
8000
8012
|
return;
|
|
8001
8013
|
} catch {
|
|
8002
|
-
if (!isSlug(idOrSlug)) throw new Error(`Post not found: ${idOrSlug}
|
|
8014
|
+
if (!isSlug(idOrSlug)) throw new Error(`Post not found: "${idOrSlug}". Run \`paragraph post list --json\` to see your posts, or use the full \`@publication/slug\` form for posts outside your publication.`);
|
|
8003
8015
|
}
|
|
8004
8016
|
await client.posts.update({ slug: idOrSlug, ...body });
|
|
8005
8017
|
}
|
|
@@ -8010,7 +8022,7 @@ async function cancelSchedule(idOrSlug, apiKey) {
|
|
|
8010
8022
|
await client.posts.update({ id: idOrSlug, ...body });
|
|
8011
8023
|
return;
|
|
8012
8024
|
} catch {
|
|
8013
|
-
if (!isSlug(idOrSlug)) throw new Error(`Post not found: ${idOrSlug}
|
|
8025
|
+
if (!isSlug(idOrSlug)) throw new Error(`Post not found: "${idOrSlug}". Run \`paragraph post list --json\` to see your posts, or use the full \`@publication/slug\` form for posts outside your publication.`);
|
|
8014
8026
|
}
|
|
8015
8027
|
await client.posts.update({ slug: idOrSlug, ...body });
|
|
8016
8028
|
}
|
|
@@ -8086,7 +8098,7 @@ var init_prompt = __esm({
|
|
|
8086
8098
|
// src/cli/lib/args.ts
|
|
8087
8099
|
function requireArg(positional, flag, name, flagName = "--id") {
|
|
8088
8100
|
if (positional && flag && positional !== flag) {
|
|
8089
|
-
throw new Error(`Conflicting values for ${name}: "${positional}" (argument) vs "${flag}" (${flagName}).`);
|
|
8101
|
+
throw new Error(`Conflicting values for ${name}: "${positional}" (argument) vs "${flag}" (${flagName}). Pass only one.`);
|
|
8090
8102
|
}
|
|
8091
8103
|
const value = positional || flag;
|
|
8092
8104
|
if (!value) throw new Error(`Missing ${name}. Pass it as an argument or with ${flagName}.`);
|
|
@@ -8122,7 +8134,7 @@ async function resolveMarkdown(opts) {
|
|
|
8122
8134
|
if (opts.text) return opts.text;
|
|
8123
8135
|
if (opts.file) {
|
|
8124
8136
|
if (!fs2.existsSync(opts.file)) {
|
|
8125
|
-
throw new Error(`File not found: ${opts.file}
|
|
8137
|
+
throw new Error(`File not found: "${opts.file}". Check the path, or use --text <markdown> to pass content inline.`);
|
|
8126
8138
|
}
|
|
8127
8139
|
return fs2.readFileSync(opts.file, "utf-8");
|
|
8128
8140
|
}
|
|
@@ -8192,10 +8204,11 @@ Examples:
|
|
|
8192
8204
|
limit: parseLimit(opts.limit),
|
|
8193
8205
|
cursor: opts.cursor
|
|
8194
8206
|
});
|
|
8195
|
-
const headers = ["ID", "Title", "Date"];
|
|
8207
|
+
const headers = ["ID", "Title", "Status", "Date"];
|
|
8196
8208
|
const rows = result.items.map((p) => [
|
|
8197
8209
|
p.id,
|
|
8198
8210
|
p.title,
|
|
8211
|
+
p.status ?? "\u2014",
|
|
8199
8212
|
formatDate(p)
|
|
8200
8213
|
]);
|
|
8201
8214
|
outputTable(this, headers, rows, result.items, { cursor: result.cursor });
|
|
@@ -8234,6 +8247,7 @@ Examples:
|
|
|
8234
8247
|
Title: data.title,
|
|
8235
8248
|
Subtitle: data.subtitle,
|
|
8236
8249
|
Slug: data.slug,
|
|
8250
|
+
Status: data.status ?? "\u2014",
|
|
8237
8251
|
Date: formatDate(data),
|
|
8238
8252
|
Content: preview
|
|
8239
8253
|
},
|
|
@@ -8635,6 +8649,16 @@ async function listSubscribers(apiKey, pagination) {
|
|
|
8635
8649
|
}
|
|
8636
8650
|
async function getSubscriberCount(publicationId) {
|
|
8637
8651
|
const client = createClient();
|
|
8652
|
+
try {
|
|
8653
|
+
await client.publications.get({ id: publicationId }).single();
|
|
8654
|
+
} catch (err) {
|
|
8655
|
+
if (err instanceof ParagraphApiError && err.status === 404) {
|
|
8656
|
+
throw new Error(
|
|
8657
|
+
`Invalid publication ID "${publicationId}". Run \`paragraph whoami --json\` to get the valid publication ID.`
|
|
8658
|
+
);
|
|
8659
|
+
}
|
|
8660
|
+
throw err;
|
|
8661
|
+
}
|
|
8638
8662
|
const result = await client.subscribers.getCount({ id: publicationId });
|
|
8639
8663
|
return result.count || 0;
|
|
8640
8664
|
}
|
|
@@ -8653,6 +8677,7 @@ var init_subscribers = __esm({
|
|
|
8653
8677
|
"src/services/subscribers.ts"() {
|
|
8654
8678
|
"use strict";
|
|
8655
8679
|
init_zod();
|
|
8680
|
+
init_dist();
|
|
8656
8681
|
init_client();
|
|
8657
8682
|
}
|
|
8658
8683
|
});
|
|
@@ -8696,7 +8721,17 @@ Examples:
|
|
|
8696
8721
|
$ paragraph subscriber count --publication abc123
|
|
8697
8722
|
$ paragraph subscriber count abc123 --json`).action(async function(positionalId, opts) {
|
|
8698
8723
|
try {
|
|
8699
|
-
const id =
|
|
8724
|
+
const id = positionalId || opts.publication;
|
|
8725
|
+
if (!id) {
|
|
8726
|
+
throw new Error(
|
|
8727
|
+
"Missing publication ID. Run `paragraph whoami --json` to get the publication ID, then pass it as an argument or with --publication."
|
|
8728
|
+
);
|
|
8729
|
+
}
|
|
8730
|
+
if (positionalId && opts.publication && positionalId !== opts.publication) {
|
|
8731
|
+
throw new Error(
|
|
8732
|
+
`Conflicting values for publication ID: "${positionalId}" (argument) vs "${opts.publication}" (--publication).`
|
|
8733
|
+
);
|
|
8734
|
+
}
|
|
8700
8735
|
const count = await getSubscriberCount(id);
|
|
8701
8736
|
outputData(this, { Count: count }, { count });
|
|
8702
8737
|
} catch (err) {
|
|
@@ -8963,7 +8998,7 @@ var init_user = __esm({
|
|
|
8963
8998
|
// src/cli/program.ts
|
|
8964
8999
|
function createProgram() {
|
|
8965
9000
|
const program2 = new Command();
|
|
8966
|
-
program2.name("paragraph").description("CLI for Paragraph").version("0.1.
|
|
9001
|
+
program2.name("paragraph").description("CLI for Paragraph").version("0.1.1", "-v, --version").option("--json", "Output as JSON").option("--verbose", "Show detailed output for debugging").exitOverride().configureOutput({
|
|
8967
9002
|
writeOut: (str) => process.stdout.write(str),
|
|
8968
9003
|
writeErr: (str) => {
|
|
8969
9004
|
if (process.argv.includes("--json")) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paragraph-com/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for Paragraph",
|
|
6
6
|
"repository": {
|
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@inkjs/ui": "^2.0.0",
|
|
46
|
-
"@paragraph-com/sdk": "^2.0.
|
|
47
|
-
"zod": "^3.24.0",
|
|
46
|
+
"@paragraph-com/sdk": "^2.0.1",
|
|
48
47
|
"cli-table3": "^0.6.5",
|
|
49
48
|
"commander": "^12.0.0",
|
|
50
49
|
"ink": "^5.1.0",
|
|
51
50
|
"picocolors": "^1.1.0",
|
|
52
|
-
"react": "^18.3.1"
|
|
51
|
+
"react": "^18.3.1",
|
|
52
|
+
"zod": "^3.24.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/node": "^20.0.0",
|