@paragraph-com/cli 0.2.0 → 0.3.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 +256 -23
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -980,7 +980,7 @@ var require_command = __commonJS({
|
|
|
980
980
|
var EventEmitter = __require("events").EventEmitter;
|
|
981
981
|
var childProcess = __require("child_process");
|
|
982
982
|
var path2 = __require("path");
|
|
983
|
-
var
|
|
983
|
+
var fs9 = __require("fs");
|
|
984
984
|
var process2 = __require("process");
|
|
985
985
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
986
986
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1913,10 +1913,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1913
1913
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1914
1914
|
function findFile(baseDir, baseName) {
|
|
1915
1915
|
const localBin = path2.resolve(baseDir, baseName);
|
|
1916
|
-
if (
|
|
1916
|
+
if (fs9.existsSync(localBin)) return localBin;
|
|
1917
1917
|
if (sourceExt.includes(path2.extname(baseName))) return void 0;
|
|
1918
1918
|
const foundExt = sourceExt.find(
|
|
1919
|
-
(ext) =>
|
|
1919
|
+
(ext) => fs9.existsSync(`${localBin}${ext}`)
|
|
1920
1920
|
);
|
|
1921
1921
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1922
1922
|
return void 0;
|
|
@@ -1928,7 +1928,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1928
1928
|
if (this._scriptPath) {
|
|
1929
1929
|
let resolvedScriptPath;
|
|
1930
1930
|
try {
|
|
1931
|
-
resolvedScriptPath =
|
|
1931
|
+
resolvedScriptPath = fs9.realpathSync(this._scriptPath);
|
|
1932
1932
|
} catch (err) {
|
|
1933
1933
|
resolvedScriptPath = this._scriptPath;
|
|
1934
1934
|
}
|
|
@@ -3266,7 +3266,7 @@ async function loadSellPeers() {
|
|
|
3266
3266
|
throw err;
|
|
3267
3267
|
}
|
|
3268
3268
|
}
|
|
3269
|
-
var BASE_URL, currentApiKey, setCurrentApiKey, ParagraphApiError, customAxios, getParagraphAPI, QueryResult, executeAbi, permit2Abi, AnalyticsResource, AuthResource, MISSING_COIN_PEERS_MESSAGE, CoinsResource, FeedResource, MeResource, PostsResource, PublicationsResource, SearchResource, SubscribersResource, UsersResource, ParagraphAPI;
|
|
3269
|
+
var BASE_URL, currentApiKey, setCurrentApiKey, ParagraphApiError, customAxios, getParagraphAPI, QueryResult, executeAbi, permit2Abi, AnalyticsResource, AuthResource, MISSING_COIN_PEERS_MESSAGE, CoinsResource, EmailsResource, FeedResource, MeResource, PostsResource, PublicationsResource, SearchResource, SubscribersResource, UsersResource, ParagraphAPI;
|
|
3270
3270
|
var init_dist = __esm({
|
|
3271
3271
|
"node_modules/@paragraph-com/sdk/dist/index.mjs"() {
|
|
3272
3272
|
"use strict";
|
|
@@ -3695,6 +3695,16 @@ var init_dist = __esm({
|
|
|
3695
3695
|
}
|
|
3696
3696
|
);
|
|
3697
3697
|
};
|
|
3698
|
+
const sendCustomEmail2 = (sendCustomEmailBody2) => {
|
|
3699
|
+
return customAxios(
|
|
3700
|
+
{
|
|
3701
|
+
url: `/v1/emails/send`,
|
|
3702
|
+
method: "POST",
|
|
3703
|
+
headers: { "Content-Type": "application/json" },
|
|
3704
|
+
data: sendCustomEmailBody2
|
|
3705
|
+
}
|
|
3706
|
+
);
|
|
3707
|
+
};
|
|
3698
3708
|
const createAuthSession = (createAuthSessionBody2) => {
|
|
3699
3709
|
return customAxios(
|
|
3700
3710
|
{
|
|
@@ -3721,7 +3731,7 @@ var init_dist = __esm({
|
|
|
3721
3731
|
}
|
|
3722
3732
|
);
|
|
3723
3733
|
};
|
|
3724
|
-
return { getPublicationById, updatePublication: updatePublication2, getPublicationBySlug, getPublicationByDomain: getPublicationByDomain2, getSubscriberCount: getSubscriberCount2, getPostsFeed, getPostsByTag: getPostsByTag2, getPosts, getPostById, updatePost: updatePost2, deletePost: deletePost2, getPostByPublicationIdAndPostSlug, getPostByPublicationSlugAndPostSlug, createPost: createPost2, listOwnPosts, updatePostBySlug, deletePostBySlug, sendTestEmail: sendTestEmail2, getMe, getUser: getUser2, getUserByWallet, getCoin: getCoin2, getCoinByContract, getCoinHoldersById, getCoinHoldersByContract, getBuyArgsById, getBuyArgsByContract, getSellArgsById, getSellArgsByContract, getQuoteById, getQuoteByContract, getPopularCoins: getPopularCoins2, importSubscribers: importSubscribers2, addSubscriber: addSubscriber2, removeSubscriber: removeSubscriber2, listSubscribers: listSubscribers2, searchPosts: searchPosts2, searchBlogs: searchBlogs2, searchCoins: searchCoins2, analyticsQuery, analyticsSchema, createAuthSession, getAuthSession, deleteAuthSession };
|
|
3734
|
+
return { getPublicationById, updatePublication: updatePublication2, getPublicationBySlug, getPublicationByDomain: getPublicationByDomain2, getSubscriberCount: getSubscriberCount2, getPostsFeed, getPostsByTag: getPostsByTag2, getPosts, getPostById, updatePost: updatePost2, deletePost: deletePost2, getPostByPublicationIdAndPostSlug, getPostByPublicationSlugAndPostSlug, createPost: createPost2, listOwnPosts, updatePostBySlug, deletePostBySlug, sendTestEmail: sendTestEmail2, getMe, getUser: getUser2, getUserByWallet, getCoin: getCoin2, getCoinByContract, getCoinHoldersById, getCoinHoldersByContract, getBuyArgsById, getBuyArgsByContract, getSellArgsById, getSellArgsByContract, getQuoteById, getQuoteByContract, getPopularCoins: getPopularCoins2, importSubscribers: importSubscribers2, addSubscriber: addSubscriber2, removeSubscriber: removeSubscriber2, listSubscribers: listSubscribers2, searchPosts: searchPosts2, searchBlogs: searchBlogs2, searchCoins: searchCoins2, analyticsQuery, analyticsSchema, sendCustomEmail: sendCustomEmail2, createAuthSession, getAuthSession, deleteAuthSession };
|
|
3725
3735
|
};
|
|
3726
3736
|
QueryResult = class {
|
|
3727
3737
|
constructor(promise) {
|
|
@@ -4230,6 +4240,68 @@ var init_dist = __esm({
|
|
|
4230
4240
|
throw new Error("Invalid identifier provided to getQuote.");
|
|
4231
4241
|
}
|
|
4232
4242
|
};
|
|
4243
|
+
EmailsResource = class {
|
|
4244
|
+
constructor(api) {
|
|
4245
|
+
this.api = api;
|
|
4246
|
+
}
|
|
4247
|
+
/**
|
|
4248
|
+
* Sends a custom email from your publication to a list of recipient
|
|
4249
|
+
* addresses. Markdown body, rendered to HTML server-side. Each recipient
|
|
4250
|
+
* receives the email individually with a mandatory unsubscribe footer.
|
|
4251
|
+
* Requires an API key.
|
|
4252
|
+
*
|
|
4253
|
+
* **Eligibility:** Publications must be approved by Paragraph before they
|
|
4254
|
+
* can send custom emails. Ineligible publications receive a 403.
|
|
4255
|
+
*
|
|
4256
|
+
* **Per-recipient filtering:**
|
|
4257
|
+
* - Malformed addresses and known disposable domains are skipped (`invalid`).
|
|
4258
|
+
* - Addresses that previously unsubscribed from this publication are skipped
|
|
4259
|
+
* (`suppressed`).
|
|
4260
|
+
* - Skipped recipients are returned in the response; nothing is delivered to
|
|
4261
|
+
* them.
|
|
4262
|
+
*
|
|
4263
|
+
* **Caps:** Maximum of 10,000 addresses per call.
|
|
4264
|
+
*
|
|
4265
|
+
* **Async delivery:** A 200 response means recipients were accepted, not
|
|
4266
|
+
* delivered. Sends are queued asynchronously.
|
|
4267
|
+
*
|
|
4268
|
+
* @example
|
|
4269
|
+
* ```ts
|
|
4270
|
+
* const api = new ParagraphAPI({ apiKey: "your-api-key" });
|
|
4271
|
+
*
|
|
4272
|
+
* // Send a markdown email to a list of recipients
|
|
4273
|
+
* const { accepted, skipped } = await api.emails.send({
|
|
4274
|
+
* subject: "Hello from Paragraph",
|
|
4275
|
+
* body: "# Welcome\n\nThanks for reading.",
|
|
4276
|
+
* emails: ["reader@example.com", "another@example.com"],
|
|
4277
|
+
* });
|
|
4278
|
+
* console.log(`${accepted} queued, ${skipped.length} skipped`);
|
|
4279
|
+
* skipped.forEach(s => console.log(`${s.email}: ${s.reason}`));
|
|
4280
|
+
*
|
|
4281
|
+
* // Dry run — check filtering without sending
|
|
4282
|
+
* const preview = await api.emails.send({
|
|
4283
|
+
* subject: "Preview",
|
|
4284
|
+
* body: "Body here",
|
|
4285
|
+
* emails: ["reader@example.com"],
|
|
4286
|
+
* dryRun: true,
|
|
4287
|
+
* });
|
|
4288
|
+
* ```
|
|
4289
|
+
*
|
|
4290
|
+
* @param body - The email send request.
|
|
4291
|
+
* @param body.subject - Subject line (1–998 characters).
|
|
4292
|
+
* @param body.body - Markdown body, rendered to HTML server-side (max 100KB).
|
|
4293
|
+
* @param body.emails - Recipient email addresses (max 10,000).
|
|
4294
|
+
* @param body.dryRun - If true, run filtering and return the accepted/skipped
|
|
4295
|
+
* split without scheduling delivery.
|
|
4296
|
+
* @returns A promise resolving to `{ accepted, skipped }`. `accepted` is the
|
|
4297
|
+
* number of recipients queued for delivery; `skipped` lists rejected
|
|
4298
|
+
* recipients with their reason (`suppressed`, `invalid`, or
|
|
4299
|
+
* `scheduling_failed`).
|
|
4300
|
+
*/
|
|
4301
|
+
send(body) {
|
|
4302
|
+
return this.api.sendCustomEmail(body);
|
|
4303
|
+
}
|
|
4304
|
+
};
|
|
4233
4305
|
FeedResource = class {
|
|
4234
4306
|
constructor(api) {
|
|
4235
4307
|
this.api = api;
|
|
@@ -4899,6 +4971,7 @@ var init_dist = __esm({
|
|
|
4899
4971
|
this.feed = new FeedResource(this.api);
|
|
4900
4972
|
this.users = new UsersResource(this.api);
|
|
4901
4973
|
this.coins = new CoinsResource(this.api);
|
|
4974
|
+
this.emails = new EmailsResource(this.api);
|
|
4902
4975
|
this.search = new SearchResource(this.api);
|
|
4903
4976
|
this.me = new MeResource(this.api);
|
|
4904
4977
|
}
|
|
@@ -7112,7 +7185,7 @@ var init_auth2 = __esm({
|
|
|
7112
7185
|
|
|
7113
7186
|
// node_modules/@paragraph-com/sdk/dist/zod.mjs
|
|
7114
7187
|
import * as zod from "zod";
|
|
7115
|
-
var getPublicationByIdParams, getPublicationByIdResponseSlugMax, getPublicationByIdResponseSummaryMax, getPublicationByIdResponse, updatePublicationParams, updatePublicationBodyNameMax, updatePublicationBodySummaryMax, updatePublicationBodyPinnedPostIdsItemMax, updatePublicationBodyPinnedPostIdsMax, updatePublicationBody, updatePublicationResponseSlugMax, updatePublicationResponseSummaryMax, updatePublicationResponse, getPublicationBySlugPathSlugMax, getPublicationBySlugParams, getPublicationBySlugResponseSlugMax, getPublicationBySlugResponseSummaryMax, getPublicationBySlugResponse, getPublicationByDomainParams, getPublicationByDomainResponseSlugMax, getPublicationByDomainResponseSummaryMax, getPublicationByDomainResponse, getSubscriberCountParams, getSubscriberCountResponse, getPostsFeedQueryLimitDefault, getPostsFeedQueryLimitMax, getPostsFeedQueryParams, getPostsFeedResponseItemsItemPostTitleMax, getPostsFeedResponseItemsItemPostSubtitleMax, getPostsFeedResponseItemsItemPostSlugMax, getPostsFeedResponseItemsItemPostAuthorsItemWalletAddressRegExp, getPostsFeedResponseItemsItemPostAuthorsItemBioMax, getPostsFeedResponseItemsItemPublicationSlugMax, getPostsFeedResponseItemsItemPublicationSummaryMax, getPostsFeedResponseItemsItemUserWalletAddressRegExp, getPostsFeedResponseItemsItemUserBioMax, getPostsFeedResponse, getPostsByTagParams, getPostsByTagQueryLimitDefault, getPostsByTagQueryLimitMax, getPostsByTagQueryParams, getPostsByTagResponseItemsItemTitleMax, getPostsByTagResponseItemsItemSubtitleMax, getPostsByTagResponseItemsItemSlugMax, getPostsByTagResponseItemsItemAuthorsItemWalletAddressRegExp, getPostsByTagResponseItemsItemAuthorsItemBioMax, getPostsByTagResponse, getPostsParams, getPostsQueryLimitDefault, getPostsQueryLimitMax, getPostsQueryParams, getPostsResponseItemsItemTitleMax, getPostsResponseItemsItemSubtitleMax, getPostsResponseItemsItemSlugMax, getPostsResponseItemsItemAuthorsItemWalletAddressRegExp, getPostsResponseItemsItemAuthorsItemBioMax, getPostsResponse, getPostByIdParams, getPostByIdQueryParams, getPostByIdResponseTitleMax, getPostByIdResponseSubtitleMax, getPostByIdResponseSlugMax, getPostByIdResponseAuthorsItemWalletAddressRegExp, getPostByIdResponseAuthorsItemBioMax, getPostByIdResponse, updatePostParams, updatePostBodyTitleMax, updatePostBodySubtitleMax, updatePostBodySlugMax, updatePostBodyPostPreviewMax, updatePostBodyScheduledAtMin, updatePostBodyPublishedAtMin, updatePostBody, updatePostResponse, deletePostParams, deletePostBody, deletePostResponse, getPostByPublicationIdAndPostSlugPathPostSlugMax, getPostByPublicationIdAndPostSlugParams, getPostByPublicationIdAndPostSlugQueryParams, getPostByPublicationIdAndPostSlugResponseTitleMax, getPostByPublicationIdAndPostSlugResponseSubtitleMax, getPostByPublicationIdAndPostSlugResponseSlugMax, getPostByPublicationIdAndPostSlugResponseAuthorsItemWalletAddressRegExp, getPostByPublicationIdAndPostSlugResponseAuthorsItemBioMax, getPostByPublicationIdAndPostSlugResponse, getPostByPublicationSlugAndPostSlugPathPublicationSlugMax, getPostByPublicationSlugAndPostSlugPathPostSlugMax, getPostByPublicationSlugAndPostSlugParams, getPostByPublicationSlugAndPostSlugQueryParams, getPostByPublicationSlugAndPostSlugResponseTitleMax, getPostByPublicationSlugAndPostSlugResponseSubtitleMax, getPostByPublicationSlugAndPostSlugResponseSlugMax, getPostByPublicationSlugAndPostSlugResponseAuthorsItemWalletAddressRegExp, getPostByPublicationSlugAndPostSlugResponseAuthorsItemBioMax, getPostByPublicationSlugAndPostSlugResponse, createPostBodyTitleMax, createPostBodySubtitleMax, createPostBodySlugMax, createPostBodyPostPreviewMax, createPostBodyScheduledAtMin, createPostBody, createPostResponse, listOwnPostsQueryLimitDefault, listOwnPostsQueryLimitMax, listOwnPostsQueryParams, listOwnPostsResponseItemsItemTitleMax, listOwnPostsResponseItemsItemSubtitleMax, listOwnPostsResponseItemsItemSlugMax, listOwnPostsResponseItemsItemAuthorsItemWalletAddressRegExp, listOwnPostsResponseItemsItemAuthorsItemBioMax, listOwnPostsResponse, updatePostBySlugPathSlugMax, updatePostBySlugParams, updatePostBySlugBodyTitleMax, updatePostBySlugBodySubtitleMax, updatePostBySlugBodySlugMax, updatePostBySlugBodyPostPreviewMax, updatePostBySlugBodyScheduledAtMin, updatePostBySlugBodyPublishedAtMin, updatePostBySlugBody, updatePostBySlugResponse, deletePostBySlugPathSlugMax, deletePostBySlugParams, deletePostBySlugBody, deletePostBySlugResponse, sendTestEmailParams, sendTestEmailBody, sendTestEmailResponse, getMeResponseSlugMax, getMeResponseSummaryMax, getMeResponse, getUserParams, getUserResponseWalletAddressRegExp, getUserResponseBioMax, getUserResponse, getUserByWalletPathWalletAddressRegExp, getUserByWalletParams, getUserByWalletResponseWalletAddressRegExp, getUserByWalletResponseBioMax, getUserByWalletResponse, getCoinParams, getCoinResponseContractAddressRegExp, getCoinResponse, getCoinByContractPathContractAddressRegExp, getCoinByContractParams, getCoinByContractResponseContractAddressRegExp, getCoinByContractResponse, getCoinHoldersByIdParams, getCoinHoldersByIdQueryLimitDefault, getCoinHoldersByIdQueryLimitMax, getCoinHoldersByIdQueryParams, getCoinHoldersByIdResponseItemsItemWalletAddressRegExp, getCoinHoldersByIdResponseItemsItemBalanceRegExp, getCoinHoldersByIdResponse, getCoinHoldersByContractPathContractAddressRegExp, getCoinHoldersByContractParams, getCoinHoldersByContractQueryLimitDefault, getCoinHoldersByContractQueryLimitMax, getCoinHoldersByContractQueryParams, getCoinHoldersByContractResponseItemsItemWalletAddressRegExp, getCoinHoldersByContractResponseItemsItemBalanceRegExp, getCoinHoldersByContractResponse, getBuyArgsByIdParams, getBuyArgsByIdQueryWalletAddressRegExp, getBuyArgsByIdQueryAmountRegExp, getBuyArgsByIdQueryParams, getBuyArgsByIdResponseCommandsRegExp, getBuyArgsByIdResponseInputsItemRegExp, getBuyArgsByIdResponse, getBuyArgsByContractPathContractAddressRegExp, getBuyArgsByContractParams, getBuyArgsByContractQueryWalletAddressRegExp, getBuyArgsByContractQueryAmountRegExp, getBuyArgsByContractQueryParams, getBuyArgsByContractResponseCommandsRegExp, getBuyArgsByContractResponseInputsItemRegExp, getBuyArgsByContractResponse, getSellArgsByIdParams, getSellArgsByIdQueryWalletAddressRegExp, getSellArgsByIdQueryAmountRegExp, getSellArgsByIdQueryParams, getSellArgsByIdResponseCommandsRegExp, getSellArgsByIdResponseInputsItemRegExp, getSellArgsByIdResponse, getSellArgsByContractPathContractAddressRegExp, getSellArgsByContractParams, getSellArgsByContractQueryWalletAddressRegExp, getSellArgsByContractQueryAmountRegExp, getSellArgsByContractQueryParams, getSellArgsByContractResponseCommandsRegExp, getSellArgsByContractResponseInputsItemRegExp, getSellArgsByContractResponse, getQuoteByIdParams, getQuoteByIdQueryAmountRegExp, getQuoteByIdQueryParams, getQuoteByIdResponse, getQuoteByContractParams, getQuoteByContractQueryAmountRegExp, getQuoteByContractQueryParams, getQuoteByContractResponse, getPopularCoinsResponseCoinsItemContractAddressRegExp, getPopularCoinsResponse, importSubscribersBody, importSubscribersResponse, addSubscriberBodyWalletRegExp, addSubscriberBody, addSubscriberResponse, removeSubscriberBodyWalletRegExp, removeSubscriberBody, removeSubscriberResponse, listSubscribersQueryLimitDefault, listSubscribersQueryLimitMax, listSubscribersQueryParams, listSubscribersResponseItemsItemWalletAddressRegExp, listSubscribersResponse, searchPostsQueryParams, searchPostsResponseItem, searchPostsResponse, searchBlogsQueryParams, searchBlogsResponseItem, searchBlogsResponse, searchCoinsQueryParams, searchCoinsResponseItem, searchCoinsResponse, analyticsQueryBody, analyticsQueryResponse, analyticsSchemaResponse, createAuthSessionBodyDeviceNameMax, createAuthSessionBodyCallbackUrlMax, createAuthSessionBody, getAuthSessionParams, getAuthSessionResponse, deleteAuthSessionParams, deleteAuthSessionResponse;
|
|
7188
|
+
var getPublicationByIdParams, getPublicationByIdResponseSlugMax, getPublicationByIdResponseSummaryMax, getPublicationByIdResponse, updatePublicationParams, updatePublicationBodyNameMax, updatePublicationBodySummaryMax, updatePublicationBodyPinnedPostIdsItemMax, updatePublicationBodyPinnedPostIdsMax, updatePublicationBody, updatePublicationResponseSlugMax, updatePublicationResponseSummaryMax, updatePublicationResponse, getPublicationBySlugPathSlugMax, getPublicationBySlugParams, getPublicationBySlugResponseSlugMax, getPublicationBySlugResponseSummaryMax, getPublicationBySlugResponse, getPublicationByDomainParams, getPublicationByDomainResponseSlugMax, getPublicationByDomainResponseSummaryMax, getPublicationByDomainResponse, getSubscriberCountParams, getSubscriberCountResponse, getPostsFeedQueryLimitDefault, getPostsFeedQueryLimitMax, getPostsFeedQueryParams, getPostsFeedResponseItemsItemPostTitleMax, getPostsFeedResponseItemsItemPostSubtitleMax, getPostsFeedResponseItemsItemPostSlugMax, getPostsFeedResponseItemsItemPostAuthorsItemWalletAddressRegExp, getPostsFeedResponseItemsItemPostAuthorsItemBioMax, getPostsFeedResponseItemsItemPublicationSlugMax, getPostsFeedResponseItemsItemPublicationSummaryMax, getPostsFeedResponseItemsItemUserWalletAddressRegExp, getPostsFeedResponseItemsItemUserBioMax, getPostsFeedResponse, getPostsByTagParams, getPostsByTagQueryLimitDefault, getPostsByTagQueryLimitMax, getPostsByTagQueryParams, getPostsByTagResponseItemsItemTitleMax, getPostsByTagResponseItemsItemSubtitleMax, getPostsByTagResponseItemsItemSlugMax, getPostsByTagResponseItemsItemAuthorsItemWalletAddressRegExp, getPostsByTagResponseItemsItemAuthorsItemBioMax, getPostsByTagResponse, getPostsParams, getPostsQueryLimitDefault, getPostsQueryLimitMax, getPostsQueryParams, getPostsResponseItemsItemTitleMax, getPostsResponseItemsItemSubtitleMax, getPostsResponseItemsItemSlugMax, getPostsResponseItemsItemAuthorsItemWalletAddressRegExp, getPostsResponseItemsItemAuthorsItemBioMax, getPostsResponse, getPostByIdParams, getPostByIdQueryParams, getPostByIdResponseTitleMax, getPostByIdResponseSubtitleMax, getPostByIdResponseSlugMax, getPostByIdResponseAuthorsItemWalletAddressRegExp, getPostByIdResponseAuthorsItemBioMax, getPostByIdResponse, updatePostParams, updatePostBodyTitleMax, updatePostBodySubtitleMax, updatePostBodySlugMax, updatePostBodyPostPreviewMax, updatePostBodyScheduledAtMin, updatePostBodyPublishedAtMin, updatePostBody, updatePostResponse, deletePostParams, deletePostBody, deletePostResponse, getPostByPublicationIdAndPostSlugPathPostSlugMax, getPostByPublicationIdAndPostSlugParams, getPostByPublicationIdAndPostSlugQueryParams, getPostByPublicationIdAndPostSlugResponseTitleMax, getPostByPublicationIdAndPostSlugResponseSubtitleMax, getPostByPublicationIdAndPostSlugResponseSlugMax, getPostByPublicationIdAndPostSlugResponseAuthorsItemWalletAddressRegExp, getPostByPublicationIdAndPostSlugResponseAuthorsItemBioMax, getPostByPublicationIdAndPostSlugResponse, getPostByPublicationSlugAndPostSlugPathPublicationSlugMax, getPostByPublicationSlugAndPostSlugPathPostSlugMax, getPostByPublicationSlugAndPostSlugParams, getPostByPublicationSlugAndPostSlugQueryParams, getPostByPublicationSlugAndPostSlugResponseTitleMax, getPostByPublicationSlugAndPostSlugResponseSubtitleMax, getPostByPublicationSlugAndPostSlugResponseSlugMax, getPostByPublicationSlugAndPostSlugResponseAuthorsItemWalletAddressRegExp, getPostByPublicationSlugAndPostSlugResponseAuthorsItemBioMax, getPostByPublicationSlugAndPostSlugResponse, createPostBodyTitleMax, createPostBodySubtitleMax, createPostBodySlugMax, createPostBodyPostPreviewMax, createPostBodyScheduledAtMin, createPostBody, createPostResponse, listOwnPostsQueryLimitDefault, listOwnPostsQueryLimitMax, listOwnPostsQueryParams, listOwnPostsResponseItemsItemTitleMax, listOwnPostsResponseItemsItemSubtitleMax, listOwnPostsResponseItemsItemSlugMax, listOwnPostsResponseItemsItemAuthorsItemWalletAddressRegExp, listOwnPostsResponseItemsItemAuthorsItemBioMax, listOwnPostsResponse, updatePostBySlugPathSlugMax, updatePostBySlugParams, updatePostBySlugBodyTitleMax, updatePostBySlugBodySubtitleMax, updatePostBySlugBodySlugMax, updatePostBySlugBodyPostPreviewMax, updatePostBySlugBodyScheduledAtMin, updatePostBySlugBodyPublishedAtMin, updatePostBySlugBody, updatePostBySlugResponse, deletePostBySlugPathSlugMax, deletePostBySlugParams, deletePostBySlugBody, deletePostBySlugResponse, sendTestEmailParams, sendTestEmailBody, sendTestEmailResponse, getMeResponseSlugMax, getMeResponseSummaryMax, getMeResponse, getUserParams, getUserResponseWalletAddressRegExp, getUserResponseBioMax, getUserResponse, getUserByWalletPathWalletAddressRegExp, getUserByWalletParams, getUserByWalletResponseWalletAddressRegExp, getUserByWalletResponseBioMax, getUserByWalletResponse, getCoinParams, getCoinResponseContractAddressRegExp, getCoinResponse, getCoinByContractPathContractAddressRegExp, getCoinByContractParams, getCoinByContractResponseContractAddressRegExp, getCoinByContractResponse, getCoinHoldersByIdParams, getCoinHoldersByIdQueryLimitDefault, getCoinHoldersByIdQueryLimitMax, getCoinHoldersByIdQueryParams, getCoinHoldersByIdResponseItemsItemWalletAddressRegExp, getCoinHoldersByIdResponseItemsItemBalanceRegExp, getCoinHoldersByIdResponse, getCoinHoldersByContractPathContractAddressRegExp, getCoinHoldersByContractParams, getCoinHoldersByContractQueryLimitDefault, getCoinHoldersByContractQueryLimitMax, getCoinHoldersByContractQueryParams, getCoinHoldersByContractResponseItemsItemWalletAddressRegExp, getCoinHoldersByContractResponseItemsItemBalanceRegExp, getCoinHoldersByContractResponse, getBuyArgsByIdParams, getBuyArgsByIdQueryWalletAddressRegExp, getBuyArgsByIdQueryAmountRegExp, getBuyArgsByIdQueryParams, getBuyArgsByIdResponseCommandsRegExp, getBuyArgsByIdResponseInputsItemRegExp, getBuyArgsByIdResponse, getBuyArgsByContractPathContractAddressRegExp, getBuyArgsByContractParams, getBuyArgsByContractQueryWalletAddressRegExp, getBuyArgsByContractQueryAmountRegExp, getBuyArgsByContractQueryParams, getBuyArgsByContractResponseCommandsRegExp, getBuyArgsByContractResponseInputsItemRegExp, getBuyArgsByContractResponse, getSellArgsByIdParams, getSellArgsByIdQueryWalletAddressRegExp, getSellArgsByIdQueryAmountRegExp, getSellArgsByIdQueryParams, getSellArgsByIdResponseCommandsRegExp, getSellArgsByIdResponseInputsItemRegExp, getSellArgsByIdResponse, getSellArgsByContractPathContractAddressRegExp, getSellArgsByContractParams, getSellArgsByContractQueryWalletAddressRegExp, getSellArgsByContractQueryAmountRegExp, getSellArgsByContractQueryParams, getSellArgsByContractResponseCommandsRegExp, getSellArgsByContractResponseInputsItemRegExp, getSellArgsByContractResponse, getQuoteByIdParams, getQuoteByIdQueryAmountRegExp, getQuoteByIdQueryParams, getQuoteByIdResponse, getQuoteByContractParams, getQuoteByContractQueryAmountRegExp, getQuoteByContractQueryParams, getQuoteByContractResponse, getPopularCoinsResponseCoinsItemContractAddressRegExp, getPopularCoinsResponse, importSubscribersBody, importSubscribersResponse, addSubscriberBodyWalletRegExp, addSubscriberBody, addSubscriberResponse, removeSubscriberBodyWalletRegExp, removeSubscriberBody, removeSubscriberResponse, listSubscribersQueryLimitDefault, listSubscribersQueryLimitMax, listSubscribersQueryParams, listSubscribersResponseItemsItemWalletAddressRegExp, listSubscribersResponse, searchPostsQueryParams, searchPostsResponseItem, searchPostsResponse, searchBlogsQueryParams, searchBlogsResponseItem, searchBlogsResponse, searchCoinsQueryParams, searchCoinsResponseItem, searchCoinsResponse, analyticsQueryBody, analyticsQueryResponse, analyticsSchemaResponse, sendCustomEmailBodySubjectMax, sendCustomEmailBodyBodyMax, sendCustomEmailBodyEmailsItemMin, sendCustomEmailBodyEmailsItemMax, sendCustomEmailBodyEmailsMax, sendCustomEmailBody, sendCustomEmailResponse, createAuthSessionBodyDeviceNameMax, createAuthSessionBodyCallbackUrlMax, createAuthSessionBody, getAuthSessionParams, getAuthSessionResponse, deleteAuthSessionParams, deleteAuthSessionResponse;
|
|
7116
7189
|
var init_zod = __esm({
|
|
7117
7190
|
"node_modules/@paragraph-com/sdk/dist/zod.mjs"() {
|
|
7118
7191
|
"use strict";
|
|
@@ -7540,9 +7613,11 @@ var init_zod = __esm({
|
|
|
7540
7613
|
"postPreview": zod.string().max(updatePostBodyPostPreviewMax).optional().describe("Preview text for the post"),
|
|
7541
7614
|
"categories": zod.union([zod.array(zod.string()), zod.string()]).optional().describe("Category tags for the post. Can also be a comma-separated string."),
|
|
7542
7615
|
"status": zod.enum(["draft", "published", "archived"]).optional().describe("Set to 'published' to publish, 'draft' to unpublish, or 'archived' to archive"),
|
|
7543
|
-
"scheduledAt": zod.number().min(updatePostBodyScheduledAtMin).nullish().describe("Unix timestamp (milliseconds) to schedule the post's first publish at a future time. Must be in the future and at most 30 days out. Only valid for draft posts that haven't been published or already scheduled. Cannot be combined with status: 'draft' or 'archived'. Pass null to cancel a previously scheduled publish."),
|
|
7616
|
+
"scheduledAt": zod.number().min(updatePostBodyScheduledAtMin).nullish().describe("Unix timestamp (milliseconds) to schedule the post's first publish at a future time. Must be in the future and at most 30 days out. Only valid for draft posts that haven't been published or already scheduled. Cannot be combined with status: 'draft' or 'archived'. Pass null to cancel a previously scheduled publish. The value 0 is treated the same as omitting the field (no scheduling request); note that on an already-scheduled post, omitting `scheduledAt` while changing `status` cancels the schedule."),
|
|
7544
7617
|
"sendNewsletter": zod.union([zod.boolean(), zod.enum(["true", "false", "1", "0"])]).optional().describe("Whether to send an email newsletter to subscribers when the post publishes. Only meaningful when publishing (status: 'published') or scheduling (scheduledAt set). Default: false"),
|
|
7545
|
-
"publishedAt": zod.number().min(updatePostBodyPublishedAtMin).optional().describe("Unix timestamp (milliseconds) to set as the post's publish date. Once set, the date is preserved across re-publishes.")
|
|
7618
|
+
"publishedAt": zod.number().min(updatePostBodyPublishedAtMin).optional().describe("Unix timestamp (milliseconds) to set as the post's publish date. Once set, the date is preserved across re-publishes."),
|
|
7619
|
+
"imageUrl": zod.string().url().optional().describe("URL of an image to set as the post's cover/hero image. The image is fetched, re-hosted on Paragraph's CDN, and a placeholder is generated. Pass clearImage: true instead to remove the existing cover."),
|
|
7620
|
+
"clearImage": zod.boolean().optional().describe("When true, removes the post's existing cover/hero image. Ignored if imageUrl is also provided.")
|
|
7546
7621
|
});
|
|
7547
7622
|
updatePostResponse = zod.object({
|
|
7548
7623
|
"success": zod.literal(true).describe("Whether the update succeeded")
|
|
@@ -7656,7 +7731,7 @@ var init_zod = __esm({
|
|
|
7656
7731
|
"slug": zod.string().min(1).max(createPostBodySlugMax).optional().describe("Optional URL-friendly identifier for the post. If not provided, will be generated from title"),
|
|
7657
7732
|
"postPreview": zod.string().max(createPostBodyPostPreviewMax).optional().describe("Optional preview text for the post. If not provided, will be generated from content"),
|
|
7658
7733
|
"categories": zod.union([zod.array(zod.string()), zod.string()]).optional().describe("Optional array of category tags for the post. Can also be a comma-separated string."),
|
|
7659
|
-
"scheduledAt": zod.number().min(createPostBodyScheduledAtMin).optional().describe("Optional Unix timestamp (milliseconds) to schedule first-publish of the post at a future time. Must be in the future. Cannot be combined with status: 'draft'. When set, the post is created and queued to publish (and send newsletter, if requested) at the specified time.")
|
|
7734
|
+
"scheduledAt": zod.number().min(createPostBodyScheduledAtMin).optional().describe("Optional Unix timestamp (milliseconds) to schedule first-publish of the post at a future time. Must be in the future. Cannot be combined with status: 'draft'. When set, the post is created and queued to publish (and send newsletter, if requested) at the specified time. Pass 0 or omit the field for an unscheduled post.")
|
|
7660
7735
|
});
|
|
7661
7736
|
createPostResponse = zod.object({
|
|
7662
7737
|
"id": zod.string().describe("The ID of the created post"),
|
|
@@ -7730,9 +7805,11 @@ var init_zod = __esm({
|
|
|
7730
7805
|
"postPreview": zod.string().max(updatePostBySlugBodyPostPreviewMax).optional().describe("Preview text for the post"),
|
|
7731
7806
|
"categories": zod.union([zod.array(zod.string()), zod.string()]).optional().describe("Category tags for the post. Can also be a comma-separated string."),
|
|
7732
7807
|
"status": zod.enum(["draft", "published", "archived"]).optional().describe("Set to 'published' to publish, 'draft' to unpublish, or 'archived' to archive"),
|
|
7733
|
-
"scheduledAt": zod.number().min(updatePostBySlugBodyScheduledAtMin).nullish().describe("Unix timestamp (milliseconds) to schedule the post's first publish at a future time. Must be in the future and at most 30 days out. Only valid for draft posts that haven't been published or already scheduled. Cannot be combined with status: 'draft' or 'archived'. Pass null to cancel a previously scheduled publish."),
|
|
7808
|
+
"scheduledAt": zod.number().min(updatePostBySlugBodyScheduledAtMin).nullish().describe("Unix timestamp (milliseconds) to schedule the post's first publish at a future time. Must be in the future and at most 30 days out. Only valid for draft posts that haven't been published or already scheduled. Cannot be combined with status: 'draft' or 'archived'. Pass null to cancel a previously scheduled publish. The value 0 is treated the same as omitting the field (no scheduling request); note that on an already-scheduled post, omitting `scheduledAt` while changing `status` cancels the schedule."),
|
|
7734
7809
|
"sendNewsletter": zod.union([zod.boolean(), zod.enum(["true", "false", "1", "0"])]).optional().describe("Whether to send an email newsletter to subscribers when the post publishes. Only meaningful when publishing (status: 'published') or scheduling (scheduledAt set). Default: false"),
|
|
7735
|
-
"publishedAt": zod.number().min(updatePostBySlugBodyPublishedAtMin).optional().describe("Unix timestamp (milliseconds) to set as the post's publish date. Once set, the date is preserved across re-publishes.")
|
|
7810
|
+
"publishedAt": zod.number().min(updatePostBySlugBodyPublishedAtMin).optional().describe("Unix timestamp (milliseconds) to set as the post's publish date. Once set, the date is preserved across re-publishes."),
|
|
7811
|
+
"imageUrl": zod.string().url().optional().describe("URL of an image to set as the post's cover/hero image. The image is fetched, re-hosted on Paragraph's CDN, and a placeholder is generated. Pass clearImage: true instead to remove the existing cover."),
|
|
7812
|
+
"clearImage": zod.boolean().optional().describe("When true, removes the post's existing cover/hero image. Ignored if imageUrl is also provided.")
|
|
7736
7813
|
});
|
|
7737
7814
|
updatePostBySlugResponse = zod.object({
|
|
7738
7815
|
"success": zod.literal(true).describe("Whether the update succeeded")
|
|
@@ -8203,6 +8280,24 @@ var init_zod = __esm({
|
|
|
8203
8280
|
"is_nullable": zod.string()
|
|
8204
8281
|
})).describe("One row per column, grouped by table in ordinal order")
|
|
8205
8282
|
});
|
|
8283
|
+
sendCustomEmailBodySubjectMax = 998;
|
|
8284
|
+
sendCustomEmailBodyBodyMax = 1e5;
|
|
8285
|
+
sendCustomEmailBodyEmailsItemMin = 3;
|
|
8286
|
+
sendCustomEmailBodyEmailsItemMax = 254;
|
|
8287
|
+
sendCustomEmailBodyEmailsMax = 1e4;
|
|
8288
|
+
sendCustomEmailBody = zod.object({
|
|
8289
|
+
"subject": zod.string().min(1).max(sendCustomEmailBodySubjectMax).describe("Subject line of the email"),
|
|
8290
|
+
"body": zod.string().min(1).max(sendCustomEmailBodyBodyMax).describe("Email body. Markdown; rendered to HTML server-side. Max 100KB."),
|
|
8291
|
+
"emails": zod.array(zod.string().min(sendCustomEmailBodyEmailsItemMin).max(sendCustomEmailBodyEmailsItemMax)).min(1).max(sendCustomEmailBodyEmailsMax).describe('Recipient email addresses (max 10,000). Malformed addresses are returned in `skipped` with `reason: "invalid"` rather than rejecting the whole request.'),
|
|
8292
|
+
"dryRun": zod.boolean().optional().describe("If true, run filtering and return the accepted/skipped split without scheduling delivery")
|
|
8293
|
+
});
|
|
8294
|
+
sendCustomEmailResponse = zod.object({
|
|
8295
|
+
"accepted": zod.number().describe("Number of recipients queued for delivery (or that would be queued when dryRun is true)"),
|
|
8296
|
+
"skipped": zod.array(zod.object({
|
|
8297
|
+
"email": zod.string(),
|
|
8298
|
+
"reason": zod.enum(["suppressed", "invalid", "scheduling_failed"])
|
|
8299
|
+
})).describe("Recipients that were rejected, with the reason each one was skipped. `scheduling_failed` means filtering passed but the delivery task could not be queued \u2014 retry these addresses.")
|
|
8300
|
+
});
|
|
8206
8301
|
createAuthSessionBodyDeviceNameMax = 100;
|
|
8207
8302
|
createAuthSessionBodyCallbackUrlMax = 2048;
|
|
8208
8303
|
createAuthSessionBody = zod.object({
|
|
@@ -8363,7 +8458,9 @@ async function updatePost(idOrSlug, params) {
|
|
|
8363
8458
|
subtitle: params.subtitle,
|
|
8364
8459
|
markdown: params.markdown,
|
|
8365
8460
|
categories: params.tags,
|
|
8366
|
-
publishedAt: params.publishedAt
|
|
8461
|
+
publishedAt: params.publishedAt,
|
|
8462
|
+
imageUrl: params.imageUrl,
|
|
8463
|
+
clearImage: params.clearImage
|
|
8367
8464
|
};
|
|
8368
8465
|
updatePostBody.parse(body);
|
|
8369
8466
|
const client = createClient(params.apiKey);
|
|
@@ -8656,22 +8753,24 @@ Examples:
|
|
|
8656
8753
|
handleError(err);
|
|
8657
8754
|
}
|
|
8658
8755
|
});
|
|
8659
|
-
const updateCmd = (parent) => parent.command("update [id-or-slug]").description("Update a post").option("--id <id-or-slug>", "Post ID or slug").option("--title <title>", "Post title").option("--text <markdown>", "Post content as markdown string").option("--file <path>", "Read post content from a file").option("--subtitle <subtitle>", "Post subtitle").option("--tags <tags>", "Comma-separated tags").option("--published-at <time>", "Set the post's display publish date (ISO 8601 or Unix ms). Sticks across re-publishes \u2014 useful for backdating.").addHelpText("after", `
|
|
8756
|
+
const updateCmd = (parent) => parent.command("update [id-or-slug]").description("Update a post").option("--id <id-or-slug>", "Post ID or slug").option("--title <title>", "Post title").option("--text <markdown>", "Post content as markdown string").option("--file <path>", "Read post content from a file").option("--subtitle <subtitle>", "Post subtitle").option("--tags <tags>", "Comma-separated tags").option("--published-at <time>", "Set the post's display publish date (ISO 8601 or Unix ms). Sticks across re-publishes \u2014 useful for backdating.").option("--image-url <url>", "URL of an image to set as the post's cover. Fetched server-side, re-hosted on Paragraph's CDN.").option("--clear-image", "Remove the post's existing cover image. Ignored if --image-url is also provided.").addHelpText("after", `
|
|
8660
8757
|
Examples:
|
|
8661
8758
|
$ paragraph post update my-post --title "New Title"
|
|
8662
8759
|
$ paragraph post update --id my-post --title "New Title"
|
|
8663
8760
|
$ paragraph post update my-post --file ./updated.md
|
|
8664
8761
|
$ cat updated.md | paragraph post update my-post
|
|
8665
8762
|
$ paragraph post update my-post --tags "web3,defi" --json
|
|
8666
|
-
$ paragraph post update my-post --published-at "2024-01-01T00:00:00Z"
|
|
8763
|
+
$ paragraph post update my-post --published-at "2024-01-01T00:00:00Z"
|
|
8764
|
+
$ paragraph post update my-post --image-url https://example.com/cover.jpg
|
|
8765
|
+
$ paragraph post update my-post --clear-image`).action(async function(idOrSlug, opts) {
|
|
8667
8766
|
try {
|
|
8668
8767
|
const id = requireArg(idOrSlug, opts.id, "post ID or slug");
|
|
8669
8768
|
const apiKey = requireApiKey();
|
|
8670
8769
|
const markdown = await resolveMarkdown(opts);
|
|
8671
8770
|
const publishedAt = opts.publishedAt ? parseScheduleTime(opts.publishedAt) : void 0;
|
|
8672
|
-
if (!opts.title && !opts.subtitle && !markdown && !opts.tags && publishedAt === void 0) {
|
|
8771
|
+
if (!opts.title && !opts.subtitle && !markdown && !opts.tags && publishedAt === void 0 && !opts.imageUrl && !opts.clearImage) {
|
|
8673
8772
|
throw new Error(
|
|
8674
|
-
"Nothing to update. Provide --title, --subtitle, --text, --file, --tags, or --
|
|
8773
|
+
"Nothing to update. Provide --title, --subtitle, --text, --file, --tags, --published-at, --image-url, or --clear-image."
|
|
8675
8774
|
);
|
|
8676
8775
|
}
|
|
8677
8776
|
await updatePost(id, {
|
|
@@ -8680,7 +8779,9 @@ Examples:
|
|
|
8680
8779
|
markdown,
|
|
8681
8780
|
subtitle: opts.subtitle,
|
|
8682
8781
|
tags: opts.tags?.split(",").map((t) => t.trim()),
|
|
8683
|
-
publishedAt
|
|
8782
|
+
publishedAt,
|
|
8783
|
+
imageUrl: opts.imageUrl,
|
|
8784
|
+
clearImage: opts.clearImage
|
|
8684
8785
|
});
|
|
8685
8786
|
writeSuccess(`Post updated: ${id}`);
|
|
8686
8787
|
outputData(
|
|
@@ -9662,10 +9763,140 @@ var init_analytics2 = __esm({
|
|
|
9662
9763
|
}
|
|
9663
9764
|
});
|
|
9664
9765
|
|
|
9766
|
+
// src/services/emails.ts
|
|
9767
|
+
async function sendCustomEmail(params) {
|
|
9768
|
+
const client = createClient(params.apiKey);
|
|
9769
|
+
return client.emails.send({
|
|
9770
|
+
subject: params.subject,
|
|
9771
|
+
body: params.body,
|
|
9772
|
+
emails: params.emails,
|
|
9773
|
+
...params.dryRun ? { dryRun: true } : {}
|
|
9774
|
+
});
|
|
9775
|
+
}
|
|
9776
|
+
var init_emails = __esm({
|
|
9777
|
+
"src/services/emails.ts"() {
|
|
9778
|
+
"use strict";
|
|
9779
|
+
init_client();
|
|
9780
|
+
}
|
|
9781
|
+
});
|
|
9782
|
+
|
|
9783
|
+
// src/cli/commands/email.ts
|
|
9784
|
+
import * as fs6 from "fs";
|
|
9785
|
+
async function resolveBody(opts) {
|
|
9786
|
+
if (opts.body) return opts.body;
|
|
9787
|
+
if (opts.bodyFile) {
|
|
9788
|
+
if (!fs6.existsSync(opts.bodyFile)) {
|
|
9789
|
+
throw new Error(
|
|
9790
|
+
`File not found: "${opts.bodyFile}". Check the path, or use --body <markdown> to pass content inline.`
|
|
9791
|
+
);
|
|
9792
|
+
}
|
|
9793
|
+
return fs6.readFileSync(opts.bodyFile, "utf-8");
|
|
9794
|
+
}
|
|
9795
|
+
const stdin = await readStdin();
|
|
9796
|
+
return stdin || void 0;
|
|
9797
|
+
}
|
|
9798
|
+
function collectRecipients(value, previous) {
|
|
9799
|
+
const parts = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
9800
|
+
return previous.concat(parts);
|
|
9801
|
+
}
|
|
9802
|
+
function registerEmailCommands(program2) {
|
|
9803
|
+
const email = program2.command("email").description("Send custom emails from your publication");
|
|
9804
|
+
email.command("send").description("Send a custom markdown email to a list of recipients").requiredOption("--subject <subject>", "Email subject").option("--body <markdown>", "Email body as markdown string").option("--body-file <path>", "Read email body from a file").option(
|
|
9805
|
+
"--to <emails>",
|
|
9806
|
+
"Recipient email (repeatable, or comma-separated)",
|
|
9807
|
+
collectRecipients,
|
|
9808
|
+
[]
|
|
9809
|
+
).option(
|
|
9810
|
+
"--dry-run",
|
|
9811
|
+
"Run filtering and show the accepted/skipped split without sending"
|
|
9812
|
+
).option("--yes", "Skip the confirmation prompt before sending").addHelpText(
|
|
9813
|
+
"after",
|
|
9814
|
+
`
|
|
9815
|
+
Examples:
|
|
9816
|
+
$ paragraph email send --subject "Hello" --body "# Hi" --to reader@example.com
|
|
9817
|
+
$ paragraph email send --subject "Update" --body-file ./body.md --to a@x.com --to b@x.com
|
|
9818
|
+
$ paragraph email send --subject "Update" --body-file ./body.md --to "a@x.com,b@x.com"
|
|
9819
|
+
$ cat body.md | paragraph email send --subject "Update" --to reader@example.com
|
|
9820
|
+
$ paragraph email send --subject "Update" --body "# Hi" --to a@x.com --dry-run`
|
|
9821
|
+
).action(async function(opts) {
|
|
9822
|
+
try {
|
|
9823
|
+
const apiKey = requireApiKey();
|
|
9824
|
+
const body = await resolveBody(opts);
|
|
9825
|
+
if (!body) {
|
|
9826
|
+
throw new Error(
|
|
9827
|
+
"Provide email body via --body, --body-file, or pipe to stdin."
|
|
9828
|
+
);
|
|
9829
|
+
}
|
|
9830
|
+
const recipients = opts.to;
|
|
9831
|
+
if (recipients.length === 0) {
|
|
9832
|
+
throw new Error(
|
|
9833
|
+
"Provide at least one recipient via --to <email>. Repeat the flag or pass a comma-separated list."
|
|
9834
|
+
);
|
|
9835
|
+
}
|
|
9836
|
+
if (!opts.dryRun && !opts.yes) {
|
|
9837
|
+
if (!process.stdin.isTTY) {
|
|
9838
|
+
throw new Error(
|
|
9839
|
+
"Cannot confirm send in non-interactive mode. Use --yes to confirm, or --dry-run to preview."
|
|
9840
|
+
);
|
|
9841
|
+
}
|
|
9842
|
+
const ok = await confirm(
|
|
9843
|
+
`Send "${opts.subject}" to ${recipients.length} recipient${recipients.length === 1 ? "" : "s"}?`
|
|
9844
|
+
);
|
|
9845
|
+
if (!ok) {
|
|
9846
|
+
process.stderr.write("Aborted.\n");
|
|
9847
|
+
process.exit(1);
|
|
9848
|
+
}
|
|
9849
|
+
}
|
|
9850
|
+
const result = await sendCustomEmail({
|
|
9851
|
+
apiKey,
|
|
9852
|
+
subject: opts.subject,
|
|
9853
|
+
body,
|
|
9854
|
+
emails: recipients,
|
|
9855
|
+
dryRun: opts.dryRun
|
|
9856
|
+
});
|
|
9857
|
+
const action = opts.dryRun ? "Dry run" : "Email queued";
|
|
9858
|
+
writeSuccess(
|
|
9859
|
+
`${action}: ${result.accepted} accepted, ${result.skipped.length} skipped`
|
|
9860
|
+
);
|
|
9861
|
+
if (result.skipped.length > 0) {
|
|
9862
|
+
writeInfo("Skipped recipients:");
|
|
9863
|
+
for (const s of result.skipped) {
|
|
9864
|
+
process.stderr.write(` ${s.email} \u2014 ${s.reason}
|
|
9865
|
+
`);
|
|
9866
|
+
}
|
|
9867
|
+
}
|
|
9868
|
+
outputData(
|
|
9869
|
+
this,
|
|
9870
|
+
{
|
|
9871
|
+
Subject: opts.subject,
|
|
9872
|
+
Recipients: recipients.length,
|
|
9873
|
+
Accepted: result.accepted,
|
|
9874
|
+
Skipped: result.skipped.length,
|
|
9875
|
+
DryRun: opts.dryRun ? "yes" : "no"
|
|
9876
|
+
},
|
|
9877
|
+
{ ...result, dryRun: !!opts.dryRun }
|
|
9878
|
+
);
|
|
9879
|
+
} catch (err) {
|
|
9880
|
+
handleError(err);
|
|
9881
|
+
}
|
|
9882
|
+
});
|
|
9883
|
+
}
|
|
9884
|
+
var init_email = __esm({
|
|
9885
|
+
"src/cli/commands/email.ts"() {
|
|
9886
|
+
"use strict";
|
|
9887
|
+
init_auth();
|
|
9888
|
+
init_emails();
|
|
9889
|
+
init_output();
|
|
9890
|
+
init_error();
|
|
9891
|
+
init_stdin();
|
|
9892
|
+
init_prompt();
|
|
9893
|
+
}
|
|
9894
|
+
});
|
|
9895
|
+
|
|
9665
9896
|
// src/cli/program.ts
|
|
9666
9897
|
function createProgram() {
|
|
9667
9898
|
const program2 = new Command();
|
|
9668
|
-
program2.name("paragraph").description("CLI for Paragraph").version("0.
|
|
9899
|
+
program2.name("paragraph").description("CLI for Paragraph").version("0.3.1", "-v, --version").option("--json", "Output as JSON").option("--verbose", "Show detailed output for debugging").exitOverride().configureOutput({
|
|
9669
9900
|
writeOut: (str) => process.stdout.write(str),
|
|
9670
9901
|
writeErr: (str) => {
|
|
9671
9902
|
if (process.argv.includes("--json")) {
|
|
@@ -9685,6 +9916,7 @@ function createProgram() {
|
|
|
9685
9916
|
registerCoinCommands(program2);
|
|
9686
9917
|
registerUserCommands(program2);
|
|
9687
9918
|
registerAnalyticsCommands(program2);
|
|
9919
|
+
registerEmailCommands(program2);
|
|
9688
9920
|
return program2;
|
|
9689
9921
|
}
|
|
9690
9922
|
var init_program = __esm({
|
|
@@ -9699,6 +9931,7 @@ var init_program = __esm({
|
|
|
9699
9931
|
init_coin();
|
|
9700
9932
|
init_user();
|
|
9701
9933
|
init_analytics2();
|
|
9934
|
+
init_email();
|
|
9702
9935
|
}
|
|
9703
9936
|
});
|
|
9704
9937
|
|
|
@@ -10952,7 +11185,7 @@ import { useState as useState9 } from "react";
|
|
|
10952
11185
|
import { Box as Box21, Text as Text14, useInput as useInput17 } from "ink";
|
|
10953
11186
|
import { TextInput as TextInput5, Spinner as Spinner9 } from "@inkjs/ui";
|
|
10954
11187
|
import { StatusMessage as StatusMessage9 } from "@inkjs/ui";
|
|
10955
|
-
import * as
|
|
11188
|
+
import * as fs7 from "fs";
|
|
10956
11189
|
import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
10957
11190
|
function PostCreate() {
|
|
10958
11191
|
const { goBack } = useNavigation();
|
|
@@ -10974,7 +11207,7 @@ function PostCreate() {
|
|
|
10974
11207
|
try {
|
|
10975
11208
|
let markdown = "";
|
|
10976
11209
|
if (filePath) {
|
|
10977
|
-
markdown =
|
|
11210
|
+
markdown = fs7.readFileSync(filePath, "utf-8");
|
|
10978
11211
|
} else {
|
|
10979
11212
|
throw new Error("A file path is required for post content.");
|
|
10980
11213
|
}
|
|
@@ -11100,7 +11333,7 @@ import { useState as useState10 } from "react";
|
|
|
11100
11333
|
import { Box as Box22, Text as Text15, useInput as useInput18 } from "ink";
|
|
11101
11334
|
import { TextInput as TextInput6, Spinner as Spinner10 } from "@inkjs/ui";
|
|
11102
11335
|
import { StatusMessage as StatusMessage10 } from "@inkjs/ui";
|
|
11103
|
-
import * as
|
|
11336
|
+
import * as fs8 from "fs";
|
|
11104
11337
|
import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
11105
11338
|
function PostUpdate() {
|
|
11106
11339
|
const { goBack, screen } = useNavigation();
|
|
@@ -11121,7 +11354,7 @@ function PostUpdate() {
|
|
|
11121
11354
|
setStep("updating");
|
|
11122
11355
|
try {
|
|
11123
11356
|
let markdown;
|
|
11124
|
-
if (filePath) markdown =
|
|
11357
|
+
if (filePath) markdown = fs8.readFileSync(filePath, "utf-8");
|
|
11125
11358
|
await updatePost(idOrSlug, {
|
|
11126
11359
|
apiKey,
|
|
11127
11360
|
title: title || void 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paragraph-com/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for Paragraph",
|
|
6
6
|
"repository": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@inkjs/ui": "^2.0.0",
|
|
46
|
-
"@paragraph-com/sdk": "^2.1
|
|
46
|
+
"@paragraph-com/sdk": "^2.2.1",
|
|
47
47
|
"cli-table3": "^0.6.5",
|
|
48
48
|
"commander": "^12.0.0",
|
|
49
49
|
"ink": "^5.1.0",
|