@zanfia/cli 0.9.0 → 0.10.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/index.js +417 -30
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7380,7 +7380,8 @@ var mockBackend = {
|
|
|
7380
7380
|
status: "draft",
|
|
7381
7381
|
isFree: false,
|
|
7382
7382
|
createdAt: now(),
|
|
7383
|
-
clientCount: 0
|
|
7383
|
+
clientCount: 0,
|
|
7384
|
+
language: input.language ?? null
|
|
7384
7385
|
};
|
|
7385
7386
|
products.push(product);
|
|
7386
7387
|
return toSummary(product);
|
|
@@ -7390,6 +7391,7 @@ var mockBackend = {
|
|
|
7390
7391
|
if (!product) return null;
|
|
7391
7392
|
if (input.name !== void 0) product.name = input.name;
|
|
7392
7393
|
if (input.description !== void 0) product.description = input.description;
|
|
7394
|
+
if (input.language !== void 0) product.language = input.language;
|
|
7393
7395
|
return { productId: id };
|
|
7394
7396
|
},
|
|
7395
7397
|
archiveProduct(id) {
|
|
@@ -7897,6 +7899,9 @@ function createMockClient() {
|
|
|
7897
7899
|
async listClientTags() {
|
|
7898
7900
|
return { count: 0, tags: [] };
|
|
7899
7901
|
},
|
|
7902
|
+
async listClientCustomFields() {
|
|
7903
|
+
return { count: 0, fields: [] };
|
|
7904
|
+
},
|
|
7900
7905
|
async createClientTag() {
|
|
7901
7906
|
throw new ApiError(501, "client tag writes are not available in mock mode");
|
|
7902
7907
|
},
|
|
@@ -8119,6 +8124,7 @@ function createMockClient() {
|
|
|
8119
8124
|
przelewy24: false,
|
|
8120
8125
|
paypal: false,
|
|
8121
8126
|
dodo: false,
|
|
8127
|
+
tubapay: false,
|
|
8122
8128
|
manual: null
|
|
8123
8129
|
},
|
|
8124
8130
|
sms: { defaultProvider: null, twilio: null, smsapi: null }
|
|
@@ -9248,6 +9254,7 @@ function createHttpClient(config) {
|
|
|
9248
9254
|
),
|
|
9249
9255
|
changeClientEmail: (id, newEmail) => request("POST", `/clients/${encodeURIComponent(id)}/change-email`, { newEmail }),
|
|
9250
9256
|
listClientTags: () => request("GET", "/clients/tags"),
|
|
9257
|
+
listClientCustomFields: (includeArchived) => request("GET", `/clients/custom-fields${includeArchived ? "?includeArchived=true" : ""}`),
|
|
9251
9258
|
createClientTag: (input) => request("POST", "/clients/tags", input),
|
|
9252
9259
|
updateClientTag: (tagId, input) => request("PATCH", `/clients/tags/${encodeURIComponent(tagId)}`, input),
|
|
9253
9260
|
deleteClientTag: (tagId) => request("DELETE", `/clients/tags/${encodeURIComponent(tagId)}`),
|
|
@@ -10157,6 +10164,27 @@ function parseStorefrontVisibility(value) {
|
|
|
10157
10164
|
}
|
|
10158
10165
|
return visibility;
|
|
10159
10166
|
}
|
|
10167
|
+
var PRODUCT_LANGUAGES = ["pl", "en"];
|
|
10168
|
+
var PRODUCT_LANGUAGE_NONE = "none";
|
|
10169
|
+
function parseProductLanguage(value) {
|
|
10170
|
+
const language = PRODUCT_LANGUAGES.find((candidate) => candidate === value.trim().toLowerCase());
|
|
10171
|
+
if (language === void 0) {
|
|
10172
|
+
throw new Error(
|
|
10173
|
+
`Invalid --language: ${value} (expected one of: ${PRODUCT_LANGUAGES.join(", ")})`
|
|
10174
|
+
);
|
|
10175
|
+
}
|
|
10176
|
+
return language;
|
|
10177
|
+
}
|
|
10178
|
+
function parseProductLanguageOrNone(value) {
|
|
10179
|
+
if (value.trim().toLowerCase() === PRODUCT_LANGUAGE_NONE) return PRODUCT_LANGUAGE_NONE;
|
|
10180
|
+
const language = PRODUCT_LANGUAGES.find((candidate) => candidate === value.trim().toLowerCase());
|
|
10181
|
+
if (language === void 0) {
|
|
10182
|
+
throw new Error(
|
|
10183
|
+
`Invalid --language: ${value} (expected one of: ${PRODUCT_LANGUAGES.join(", ")}, ${PRODUCT_LANGUAGE_NONE})`
|
|
10184
|
+
);
|
|
10185
|
+
}
|
|
10186
|
+
return language;
|
|
10187
|
+
}
|
|
10160
10188
|
function parseCommaList(flag) {
|
|
10161
10189
|
return (value) => {
|
|
10162
10190
|
const items = [
|
|
@@ -10327,18 +10355,19 @@ function registerCertificatesCommands(program2) {
|
|
|
10327
10355
|
"Course-completion and event-participation certificates \u2014 issue for course or event clients, revoke/reinstate, resend the email, and manage designer templates (`certificates templates \u2026`)"
|
|
10328
10356
|
);
|
|
10329
10357
|
certificates.command("list").summary("List certificates").description(
|
|
10330
|
-
"Issued certificates of the workspace (course completion and event participation), newest first, optionally filtered to one product (`productId`); `limit` caps the rows (service default applies). Each row is the credential: public `certificateId` (`cert_\u2026`, the id every certificate write takes), `productType` (`course` / `event`), recipient name/email, product (`courseName`) and issuer names, completion/issued dates, `issuedBy` (manual vs automatic), template id/version, PDF and verification URLs, `status` (active/revoked), `expiresAt` and delivery/engagement signals (email status, views, downloads, LinkedIn add). Also the polling endpoint after issue-certificates \u2014 a newly enqueued client shows up here once its PDF has been rendered."
|
|
10358
|
+
"Issued certificates of the workspace (course completion and event participation), newest first, optionally filtered to one product (`productId`); `limit` caps the rows per page (service default applies) and `nextCursor` (pass it back as `cursor`) continues the list. Each row is the credential: public `certificateId` (`cert_\u2026`, the id every certificate write takes), `productType` (`course` / `event`), recipient name/email, product (`courseName`) and issuer names, completion/issued dates, `issuedBy` (manual vs automatic), template id/version, PDF and verification URLs, `status` (active/revoked), `expiresAt` and delivery/engagement signals (email status, views, downloads, LinkedIn add). Also the polling endpoint after issue-certificates \u2014 a newly enqueued client shows up here once its PDF has been rendered."
|
|
10331
10359
|
).option("--product <value>", "Course or event product id \u2014 omit for all products.").option(
|
|
10332
10360
|
"--limit <n>",
|
|
10333
|
-
"Max rows, newest first (max 500; the service default applies when omitted).",
|
|
10361
|
+
"Max rows per page, newest first (max 500; the service default applies when omitted).",
|
|
10334
10362
|
parseNumberOption("--limit", NumberFormat.Integer)
|
|
10335
|
-
).action(async (options, command) => {
|
|
10363
|
+
).option("--cursor <value>", "`nextCursor` of the previous page; omit for the first page.").action(async (options, command) => {
|
|
10336
10364
|
const flags = getGlobalFlags(command);
|
|
10337
10365
|
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
10338
10366
|
const params = {};
|
|
10339
10367
|
const payload = {
|
|
10340
10368
|
productId: options.product,
|
|
10341
|
-
limit: options.limit
|
|
10369
|
+
limit: options.limit,
|
|
10370
|
+
cursor: options.cursor
|
|
10342
10371
|
};
|
|
10343
10372
|
const result = await client.call("GET", "/certificates", params, payload, void 0);
|
|
10344
10373
|
const rows = tableRowsOf(result, "certificates");
|
|
@@ -10699,10 +10728,270 @@ function registerBlogCommands(program2) {
|
|
|
10699
10728
|
});
|
|
10700
10729
|
}
|
|
10701
10730
|
|
|
10731
|
+
// src/commands/_generated/site-redirects.ts
|
|
10732
|
+
var listSiteRedirectsColumns = ["from", "to", "kind"];
|
|
10733
|
+
function registerSiteRedirectsCommands(program2) {
|
|
10734
|
+
const siteRedirects = program2.command("site-redirects");
|
|
10735
|
+
siteRedirects.description(
|
|
10736
|
+
"The site's 301 redirect map (Your site \u2192 Redirects): old addresses and where they go; checked by the same rules as the dashboard"
|
|
10737
|
+
);
|
|
10738
|
+
siteRedirects.command("list").summary("List site redirects").description(
|
|
10739
|
+
"The site's 301 redirect map (dashboard: Your site \u2192 Redirects): old addresses of a site moved to Zanfia and where they go now, in map order, plus `max` (the cap). A line fires only when nothing on the site answers the address. `kind` = `exact` (one address) or `folder` (`/news/*`, every address under it). The `from` of a line is its id for update-site-redirect and delete-site-redirect."
|
|
10740
|
+
).action(async (_options, command) => {
|
|
10741
|
+
const flags = getGlobalFlags(command);
|
|
10742
|
+
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
10743
|
+
const params = {};
|
|
10744
|
+
const result = await client.call("GET", "/site/redirects", params, void 0, void 0);
|
|
10745
|
+
const rows = tableRowsOf(result, "redirects");
|
|
10746
|
+
emit(flags, result ?? {}, () => printTable(rows, listSiteRedirectsColumns));
|
|
10747
|
+
});
|
|
10748
|
+
siteRedirects.command("create").summary("Add a site redirect").description(
|
|
10749
|
+
"Adds one line at the end of the site's 301 map; live at once. Refused (400 `site-redirects-refused`, `issues[]` = index, from, to, issue) exactly like the dashboard save: a malformed address (`invalid-from` / `invalid-to`), the home page or an address Zanfia owns (`/blog`, `/p/\u2026`, `/app`: `reserved-from`), the member area (`portal-from`), a published page (`page-exists`), a `from` the map already has (`duplicate`), a chain or a loop (`chain`), `/*` in `to` without a folder `from` (`rest-without-folder`), over 500 lines (`too-many-entries`). Returns the line as stored."
|
|
10750
|
+
).argument(
|
|
10751
|
+
"<from>",
|
|
10752
|
+
"The old address on the site: a path (`/o-nas`), a full address on the site (`https://example.com/o-nas/`, stored as its path) or a folder ending with `/*` (`/news/*`, every address under it). Query string and `#\u2026` are dropped; case is kept."
|
|
10753
|
+
).argument(
|
|
10754
|
+
"<to>",
|
|
10755
|
+
"Where it goes: a path on the site (`/o-mnie`; a folder line may end with `/*` to keep the rest of the old address: `/news/*` \u2192 `/blog/*`) or an absolute `https://` address."
|
|
10756
|
+
).action(async (from, to, _options, command) => {
|
|
10757
|
+
const flags = getGlobalFlags(command);
|
|
10758
|
+
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
10759
|
+
const params = {};
|
|
10760
|
+
const payload = {
|
|
10761
|
+
from,
|
|
10762
|
+
to
|
|
10763
|
+
};
|
|
10764
|
+
const result = await client.call("POST", "/site/redirects", params, void 0, payload);
|
|
10765
|
+
emit(flags, result ?? {}, () => printJson(result ?? {}));
|
|
10766
|
+
});
|
|
10767
|
+
siteRedirects.command("update").summary("Change a site redirect").description(
|
|
10768
|
+
"Changes one line of the 301 map, picked by its current `from`: `newFrom`, `to` or both; a field not given keeps its value and the line keeps its place. Live at once. 404 `site-redirect-not-found` when no line has that `from`; refused like create-site-redirect (400 `site-redirects-refused` with `issues[]`). Returns the line as stored."
|
|
10769
|
+
).argument(
|
|
10770
|
+
"<from>",
|
|
10771
|
+
"The line to change, by its current `from` (as list-site-redirects shows it; `/o-nas/` or a full address on the site also match)."
|
|
10772
|
+
).option(
|
|
10773
|
+
"--new-from <value>",
|
|
10774
|
+
"The old address on the site: a path (`/o-nas`), a full address on the site (`https://example.com/o-nas/`, stored as its path) or a folder ending with `/*` (`/news/*`, every address under it). Query string and `#\u2026` are dropped; case is kept."
|
|
10775
|
+
).option(
|
|
10776
|
+
"--to <value>",
|
|
10777
|
+
"Where it goes: a path on the site (`/o-mnie`; a folder line may end with `/*` to keep the rest of the old address: `/news/*` \u2192 `/blog/*`) or an absolute `https://` address."
|
|
10778
|
+
).action(async (from, options, command) => {
|
|
10779
|
+
const flags = getGlobalFlags(command);
|
|
10780
|
+
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
10781
|
+
const params = {};
|
|
10782
|
+
const payload = {
|
|
10783
|
+
from,
|
|
10784
|
+
newFrom: options.newFrom,
|
|
10785
|
+
to: options.to
|
|
10786
|
+
};
|
|
10787
|
+
const result = await client.call("PATCH", "/site/redirects", params, void 0, payload);
|
|
10788
|
+
emit(flags, result ?? {}, () => printJson(result ?? {}));
|
|
10789
|
+
});
|
|
10790
|
+
siteRedirects.command("delete").summary("Remove a site redirect").description(
|
|
10791
|
+
"Removes one line of the 301 map, picked by its `from` (sent in the JSON body). The old address answers 404 again at once (links to it in search results and old posts break). 404 `site-redirect-not-found` when no line has that `from`. Returns the removed line."
|
|
10792
|
+
).argument(
|
|
10793
|
+
"<from>",
|
|
10794
|
+
"The line to change, by its current `from` (as list-site-redirects shows it; `/o-nas/` or a full address on the site also match)."
|
|
10795
|
+
).option(
|
|
10796
|
+
"--confirm",
|
|
10797
|
+
"required \u2014 acknowledge that you want to the old address answers 404 again"
|
|
10798
|
+
).action(async (from, options, command) => {
|
|
10799
|
+
const flags = getGlobalFlags(command);
|
|
10800
|
+
requireConfirm(options.confirm, "the old address answers 404 again");
|
|
10801
|
+
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
10802
|
+
const params = {};
|
|
10803
|
+
const payload = {
|
|
10804
|
+
from
|
|
10805
|
+
};
|
|
10806
|
+
const result = await client.call("DELETE", "/site/redirects", params, void 0, payload);
|
|
10807
|
+
emit(flags, result ?? {}, () => printJson(result ?? {}));
|
|
10808
|
+
});
|
|
10809
|
+
}
|
|
10810
|
+
|
|
10811
|
+
// src/commands/_generated/popups.ts
|
|
10812
|
+
var listPopupsColumns = ["id", "name", "status", "priority", "updatedAt"];
|
|
10813
|
+
function registerPopupsCommands(program2) {
|
|
10814
|
+
const popups = program2.command("popups");
|
|
10815
|
+
popups.description(
|
|
10816
|
+
"Pop-ups on the workspace site (Your site \u2192 Pop-ups): a signup form shown on entry or after scrolling, after the cookie decision, never again after a signup"
|
|
10817
|
+
);
|
|
10818
|
+
popups.command("list").summary("List pop-ups").description(
|
|
10819
|
+
"Every pop-up of the workspace site (drafts, active, paused) in priority order: copy, form content, triggers per device, targeting, frequency and schedule. The id source for every other pop-up tool."
|
|
10820
|
+
).action(async (_options, command) => {
|
|
10821
|
+
const flags = getGlobalFlags(command);
|
|
10822
|
+
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
10823
|
+
const params = {};
|
|
10824
|
+
const result = await client.call("GET", "/popups", params, void 0, void 0);
|
|
10825
|
+
const rows = tableRowsOf(result, "popups");
|
|
10826
|
+
emit(flags, result ?? {}, () => printTable(rows, listPopupsColumns));
|
|
10827
|
+
});
|
|
10828
|
+
popups.command("create").summary("Create a pop-up").description(
|
|
10829
|
+
"Creates a pop-up as a DRAFT holding a signup form. Without `content.formId` a new standalone signup form named after the pop-up is created (visible in Forms). Defaults: desktop after 10 s on the page, phones after 40 % scroll as a bottom sheet, again after 7 days, all hosted pages except thank-you / download / member pages, hidden for subscribers. Activate it with set-popup-status once it has a title and a button text. Requires the pop-ups feature on the plan (403 otherwise)."
|
|
10830
|
+
).requiredOption(
|
|
10831
|
+
"--name <value>",
|
|
10832
|
+
"Internal name (panel only); also the name of a provisioned form."
|
|
10833
|
+
).option(
|
|
10834
|
+
"--priority <n>",
|
|
10835
|
+
"Lower shows first when several pop-ups match a page; default = after the others.",
|
|
10836
|
+
parseNumberOption("--priority", NumberFormat.Integer)
|
|
10837
|
+
).addOption(
|
|
10838
|
+
new Option(
|
|
10839
|
+
"--language <pl|en|default>",
|
|
10840
|
+
"Built-in labels (close, errors): `pl`, `en` or `default` (= the page language)."
|
|
10841
|
+
).choices(["pl", "en", "default"])
|
|
10842
|
+
).option(
|
|
10843
|
+
"--copy <json|file>",
|
|
10844
|
+
"Headline, text, button and image.",
|
|
10845
|
+
parseJsonObjectFileOrInline("--copy")
|
|
10846
|
+
).option(
|
|
10847
|
+
"--content <json|file>",
|
|
10848
|
+
"What the pop-up holds: a signup form.",
|
|
10849
|
+
parseJsonObjectFileOrInline("--content")
|
|
10850
|
+
).option("--design <json|file>", "design", parseJsonObjectFileOrInline("--design")).option(
|
|
10851
|
+
"--trigger <json|file>",
|
|
10852
|
+
"When it opens, per device.",
|
|
10853
|
+
parseJsonObjectFileOrInline("--trigger")
|
|
10854
|
+
).option(
|
|
10855
|
+
"--targeting <json|file>",
|
|
10856
|
+
"Where and for whom.",
|
|
10857
|
+
parseJsonObjectFileOrInline("--targeting")
|
|
10858
|
+
).option(
|
|
10859
|
+
"--frequency <json|file>",
|
|
10860
|
+
"How often one visitor sees it; never again after a signup. Default every 7 days.",
|
|
10861
|
+
parseJsonObjectFileOrInline("--frequency")
|
|
10862
|
+
).option(
|
|
10863
|
+
"--schedule <json|file>",
|
|
10864
|
+
"From / to (applied within a few minutes).",
|
|
10865
|
+
parseJsonObjectFileOrInline("--schedule")
|
|
10866
|
+
).action(async (options, command) => {
|
|
10867
|
+
const flags = getGlobalFlags(command);
|
|
10868
|
+
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
10869
|
+
const params = {};
|
|
10870
|
+
const payload = {
|
|
10871
|
+
name: options.name,
|
|
10872
|
+
priority: options.priority,
|
|
10873
|
+
language: options.language,
|
|
10874
|
+
copy: options.copy,
|
|
10875
|
+
content: options.content,
|
|
10876
|
+
design: options.design,
|
|
10877
|
+
trigger: options.trigger,
|
|
10878
|
+
targeting: options.targeting,
|
|
10879
|
+
frequency: options.frequency,
|
|
10880
|
+
schedule: options.schedule
|
|
10881
|
+
};
|
|
10882
|
+
const result = await client.call("POST", "/popups", params, void 0, payload);
|
|
10883
|
+
emit(flags, result ?? {}, () => printJson(result ?? {}));
|
|
10884
|
+
});
|
|
10885
|
+
popups.command("get").summary("Pop-up detail").description(
|
|
10886
|
+
"One pop-up in full: status, copy, form content, triggers, targeting, frequency, schedule."
|
|
10887
|
+
).argument("<id>", "Pop-up id (`popup_\u2026`) from list-popups.").action(async (id, _options, command) => {
|
|
10888
|
+
const flags = getGlobalFlags(command);
|
|
10889
|
+
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
10890
|
+
const params = {
|
|
10891
|
+
popupId: id
|
|
10892
|
+
};
|
|
10893
|
+
const result = await client.call("GET", "/popups/:popupId", params, void 0, void 0);
|
|
10894
|
+
emit(flags, result ?? {}, () => printJson(result ?? {}));
|
|
10895
|
+
});
|
|
10896
|
+
popups.command("update").summary("Update a pop-up").description(
|
|
10897
|
+
"Partial update of a pop-up: each section sent merges into the current one (copy, content, design, targeting, schedule field by field; a trigger rule, the page list and the frequency are replaced whole). An active pop-up must keep its title, button and form (400 popup-incomplete). Live sites pick changes up within a few minutes."
|
|
10898
|
+
).argument("<id>", "Pop-up id (`popup_\u2026`) from list-popups.").option("--name <value>", "Internal name (panel only).").option(
|
|
10899
|
+
"--priority <n>",
|
|
10900
|
+
"Lower shows first when several pop-ups match a page; default = after the others.",
|
|
10901
|
+
parseNumberOption("--priority", NumberFormat.Integer)
|
|
10902
|
+
).addOption(
|
|
10903
|
+
new Option(
|
|
10904
|
+
"--language <pl|en|default>",
|
|
10905
|
+
"Built-in labels (close, errors): `pl`, `en` or `default` (= the page language)."
|
|
10906
|
+
).choices(["pl", "en", "default"])
|
|
10907
|
+
).option(
|
|
10908
|
+
"--copy <json|file>",
|
|
10909
|
+
"Headline, text, button and image.",
|
|
10910
|
+
parseJsonObjectFileOrInline("--copy")
|
|
10911
|
+
).option(
|
|
10912
|
+
"--content <json|file>",
|
|
10913
|
+
"What the pop-up holds: a signup form.",
|
|
10914
|
+
parseJsonObjectFileOrInline("--content")
|
|
10915
|
+
).option("--design <json|file>", "design", parseJsonObjectFileOrInline("--design")).option(
|
|
10916
|
+
"--trigger <json|file>",
|
|
10917
|
+
"When it opens, per device.",
|
|
10918
|
+
parseJsonObjectFileOrInline("--trigger")
|
|
10919
|
+
).option(
|
|
10920
|
+
"--targeting <json|file>",
|
|
10921
|
+
"Where and for whom.",
|
|
10922
|
+
parseJsonObjectFileOrInline("--targeting")
|
|
10923
|
+
).option(
|
|
10924
|
+
"--frequency <json|file>",
|
|
10925
|
+
"How often one visitor sees it; never again after a signup. Default every 7 days.",
|
|
10926
|
+
parseJsonObjectFileOrInline("--frequency")
|
|
10927
|
+
).option(
|
|
10928
|
+
"--schedule <json|file>",
|
|
10929
|
+
"From / to (applied within a few minutes).",
|
|
10930
|
+
parseJsonObjectFileOrInline("--schedule")
|
|
10931
|
+
).action(async (id, options, command) => {
|
|
10932
|
+
const flags = getGlobalFlags(command);
|
|
10933
|
+
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
10934
|
+
const params = {
|
|
10935
|
+
popupId: id
|
|
10936
|
+
};
|
|
10937
|
+
const payload = {
|
|
10938
|
+
name: options.name,
|
|
10939
|
+
priority: options.priority,
|
|
10940
|
+
language: options.language,
|
|
10941
|
+
copy: options.copy,
|
|
10942
|
+
content: options.content,
|
|
10943
|
+
design: options.design,
|
|
10944
|
+
trigger: options.trigger,
|
|
10945
|
+
targeting: options.targeting,
|
|
10946
|
+
frequency: options.frequency,
|
|
10947
|
+
schedule: options.schedule
|
|
10948
|
+
};
|
|
10949
|
+
const result = await client.call("PATCH", "/popups/:popupId", params, void 0, payload);
|
|
10950
|
+
emit(flags, result ?? {}, () => printJson(result ?? {}));
|
|
10951
|
+
});
|
|
10952
|
+
popups.command("status").summary("Activate or pause a pop-up").description(
|
|
10953
|
+
"Activates or pauses a pop-up. Activation needs a title, a button text and an existing signup form (400 popup-incomplete / 404 form-not-found), the pop-ups feature on the plan (403) and a free slot: at most 20 active pop-ups (409 too-many-active-popups). Visitors see it after their cookie decision, by its trigger, once per page view."
|
|
10954
|
+
).argument("<id>", "Pop-up id (`popup_\u2026`) from list-popups.").argument(
|
|
10955
|
+
"<status>",
|
|
10956
|
+
"`active` shows it on the site (within a few minutes), `paused` takes it off."
|
|
10957
|
+
).action(async (id, status, _options, command) => {
|
|
10958
|
+
const flags = getGlobalFlags(command);
|
|
10959
|
+
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
10960
|
+
const params = {
|
|
10961
|
+
popupId: id
|
|
10962
|
+
};
|
|
10963
|
+
const payload = {
|
|
10964
|
+
status
|
|
10965
|
+
};
|
|
10966
|
+
const result = await client.call(
|
|
10967
|
+
"POST",
|
|
10968
|
+
"/popups/:popupId/status",
|
|
10969
|
+
params,
|
|
10970
|
+
void 0,
|
|
10971
|
+
payload
|
|
10972
|
+
);
|
|
10973
|
+
emit(flags, result ?? {}, () => printJson(result ?? {}));
|
|
10974
|
+
});
|
|
10975
|
+
popups.command("delete").summary("Delete a pop-up").description(
|
|
10976
|
+
"Deletes a pop-up for good; an active one leaves the site within a few minutes. Its form and the signups stay. No undo - prefer pausing."
|
|
10977
|
+
).argument("<id>", "Pop-up id (`popup_\u2026`) from list-popups.").option("--confirm", "required \u2014 acknowledge that you want to deletes the pop-up for good").action(async (id, options, command) => {
|
|
10978
|
+
const flags = getGlobalFlags(command);
|
|
10979
|
+
requireConfirm(options.confirm, "deletes the pop-up for good");
|
|
10980
|
+
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
10981
|
+
const params = {
|
|
10982
|
+
popupId: id
|
|
10983
|
+
};
|
|
10984
|
+
const result = await client.call("DELETE", "/popups/:popupId", params, void 0, void 0);
|
|
10985
|
+
emit(flags, result ?? {}, () => printJson(result ?? {}));
|
|
10986
|
+
});
|
|
10987
|
+
}
|
|
10988
|
+
|
|
10702
10989
|
// src/commands/_generated/index.ts
|
|
10703
10990
|
function registerGeneratedCommands(program2) {
|
|
10704
10991
|
registerCertificatesCommands(program2);
|
|
10705
10992
|
registerBlogCommands(program2);
|
|
10993
|
+
registerSiteRedirectsCommands(program2);
|
|
10994
|
+
registerPopupsCommands(program2);
|
|
10706
10995
|
}
|
|
10707
10996
|
|
|
10708
10997
|
// src/commands/ads/index.ts
|
|
@@ -13305,7 +13594,8 @@ var CREDENTIAL_PAYMENT_GATEWAYS = [
|
|
|
13305
13594
|
"przelewy24",
|
|
13306
13595
|
"paynow",
|
|
13307
13596
|
"paypal",
|
|
13308
|
-
"dodo"
|
|
13597
|
+
"dodo",
|
|
13598
|
+
"tubapay"
|
|
13309
13599
|
];
|
|
13310
13600
|
var COMMUNITY_EVENT_LOCATION_TYPES = [
|
|
13311
13601
|
"online",
|
|
@@ -14176,6 +14466,33 @@ Next page: --cursor ${page.nextCursor}
|
|
|
14176
14466
|
process.stdout.write(` Previous emails: ${detail.previousEmails.join(", ")}
|
|
14177
14467
|
`);
|
|
14178
14468
|
}
|
|
14469
|
+
const customFields = Object.entries(detail.customFields ?? {});
|
|
14470
|
+
if (customFields.length > 0) {
|
|
14471
|
+
process.stdout.write(" Custom fields:\n");
|
|
14472
|
+
for (const [key, value] of customFields) {
|
|
14473
|
+
process.stdout.write(` ${key}: ${String(value)}
|
|
14474
|
+
`);
|
|
14475
|
+
}
|
|
14476
|
+
}
|
|
14477
|
+
});
|
|
14478
|
+
});
|
|
14479
|
+
clients2.command("fields").description(
|
|
14480
|
+
"List the custom contact fields (key, name, type, options); set values with `clients update --field key=value`"
|
|
14481
|
+
).option("--include-archived", "also list archived fields (their values are read-only)").action(async (options, command) => {
|
|
14482
|
+
const flags = getGlobalFlags(command);
|
|
14483
|
+
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
14484
|
+
const result = await client.listClientCustomFields(options.includeArchived === true);
|
|
14485
|
+
emit(flags, result, () => {
|
|
14486
|
+
printTable(
|
|
14487
|
+
result.fields.map((field) => ({
|
|
14488
|
+
key: field.key,
|
|
14489
|
+
name: field.name,
|
|
14490
|
+
type: field.type,
|
|
14491
|
+
options: field.options.filter((option) => !option.archived).map((option) => `${option.key}=${option.label}`).join(", "),
|
|
14492
|
+
archived: field.archived ? "yes" : ""
|
|
14493
|
+
})),
|
|
14494
|
+
["key", "name", "type", "options", "archived"]
|
|
14495
|
+
);
|
|
14179
14496
|
});
|
|
14180
14497
|
});
|
|
14181
14498
|
registerClientTagsCommands(clients2);
|
|
@@ -14289,12 +14606,27 @@ Next page: --cursor ${page.nextCursor}
|
|
|
14289
14606
|
`);
|
|
14290
14607
|
});
|
|
14291
14608
|
});
|
|
14292
|
-
clients2.command("update").description("Update a client's profile (name, phone, language)").argument("<id>", "workspace client id (wcid)").option("--first-name <name>", "new first name").option("--last-name <name>", "new last name").option("--phone <number>", "new phone number").option("--language <code>", "new preferred language code (e.g. en, pl)").
|
|
14609
|
+
clients2.command("update").description("Update a client's profile (name, phone, language) and custom field values").argument("<id>", "workspace client id (wcid)").option("--first-name <name>", "new first name").option("--last-name <name>", "new last name").option("--phone <number>", "new phone number").option("--language <code>", "new preferred language code (e.g. en, pl)").option(
|
|
14610
|
+
"--field <key=value>",
|
|
14611
|
+
"set a custom field value (repeatable; keys from `clients fields`, e.g. --field plan=premium)",
|
|
14612
|
+
collectRepeatable2,
|
|
14613
|
+
[]
|
|
14614
|
+
).option("--clear-field <key>", "clear a custom field value (repeatable)", collectRepeatable2, []).action(
|
|
14293
14615
|
async (id, options, command) => {
|
|
14294
14616
|
const flags = getGlobalFlags(command);
|
|
14295
|
-
|
|
14617
|
+
const customFields = {};
|
|
14618
|
+
for (const entry of options.field) {
|
|
14619
|
+
const separator = entry.indexOf("=");
|
|
14620
|
+
if (separator <= 0) {
|
|
14621
|
+
throw new Error(`Invalid --field "${entry}": use key=value.`);
|
|
14622
|
+
}
|
|
14623
|
+
customFields[entry.slice(0, separator).trim()] = entry.slice(separator + 1);
|
|
14624
|
+
}
|
|
14625
|
+
for (const key of options.clearField) customFields[key.trim()] = null;
|
|
14626
|
+
const hasCustomFields = Object.keys(customFields).length > 0;
|
|
14627
|
+
if (options.firstName === void 0 && options.lastName === void 0 && options.phone === void 0 && options.language === void 0 && !hasCustomFields) {
|
|
14296
14628
|
throw new Error(
|
|
14297
|
-
"Nothing to update \u2014 pass at least one of --first-name, --last-name, --phone, --language."
|
|
14629
|
+
"Nothing to update \u2014 pass at least one of --first-name, --last-name, --phone, --language, --field, --clear-field."
|
|
14298
14630
|
);
|
|
14299
14631
|
}
|
|
14300
14632
|
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
@@ -14302,7 +14634,8 @@ Next page: --cursor ${page.nextCursor}
|
|
|
14302
14634
|
firstName: options.firstName,
|
|
14303
14635
|
lastName: options.lastName,
|
|
14304
14636
|
phoneNumber: options.phone,
|
|
14305
|
-
language: options.language
|
|
14637
|
+
language: options.language,
|
|
14638
|
+
...hasCustomFields ? { customFields } : {}
|
|
14306
14639
|
});
|
|
14307
14640
|
emit(flags, result, () => {
|
|
14308
14641
|
process.stdout.write(`Updated client ${result.clientId}.
|
|
@@ -18670,7 +19003,7 @@ function printOverview(overview) {
|
|
|
18670
19003
|
const p = overview.payments;
|
|
18671
19004
|
const on = (value) => value ? "on" : "off";
|
|
18672
19005
|
process.stdout.write(
|
|
18673
|
-
`Payments: stripe=${on(p.stripe)} payU=${on(p.payU)} tpay=${on(p.tpay)} payNow=${on(p.payNow)} przelewy24=${on(p.przelewy24)} paypal=${on(p.paypal)} dodo=${on(p.dodo)} manual=${p.manual ? `on (${p.manual.name})` : "off"}
|
|
19006
|
+
`Payments: stripe=${on(p.stripe)} payU=${on(p.payU)} tpay=${on(p.tpay)} payNow=${on(p.payNow)} przelewy24=${on(p.przelewy24)} paypal=${on(p.paypal)} dodo=${on(p.dodo)} tubapay=${on(p.tubapay)} manual=${p.manual ? `on (${p.manual.name})` : "off"}
|
|
18674
19007
|
`
|
|
18675
19008
|
);
|
|
18676
19009
|
}
|
|
@@ -18945,7 +19278,7 @@ function readSecret2(label, value, fromStdin, fromEnv) {
|
|
|
18945
19278
|
function printPayments(payments) {
|
|
18946
19279
|
const on = (value) => value ? "on" : "off";
|
|
18947
19280
|
process.stdout.write(
|
|
18948
|
-
`Payments: stripe=${on(payments.stripe)} payu=${on(payments.payU)} tpay=${on(payments.tpay)} paynow=${on(payments.payNow)} przelewy24=${on(payments.przelewy24)} paypal=${on(payments.paypal)} dodo=${on(payments.dodo)} manual=${payments.manual ? "on" : "off"}
|
|
19281
|
+
`Payments: stripe=${on(payments.stripe)} payu=${on(payments.payU)} tpay=${on(payments.tpay)} paynow=${on(payments.payNow)} przelewy24=${on(payments.przelewy24)} paypal=${on(payments.paypal)} dodo=${on(payments.dodo)} tubapay=${on(payments.tubapay)} manual=${payments.manual ? "on" : "off"}
|
|
18949
19282
|
`
|
|
18950
19283
|
);
|
|
18951
19284
|
}
|
|
@@ -19024,6 +19357,11 @@ function buildGatewayInput(gateway, o) {
|
|
|
19024
19357
|
case "dodo":
|
|
19025
19358
|
input.apiKey = secret(o.apiKey, "--api-key");
|
|
19026
19359
|
break;
|
|
19360
|
+
case "tubapay":
|
|
19361
|
+
input.clientId = need(o.clientId, "--client-id");
|
|
19362
|
+
input.clientSecret = secret(o.clientSecret, "--client-secret");
|
|
19363
|
+
input.callbackSecret = secret(o.callbackSecret, "--callback-secret");
|
|
19364
|
+
break;
|
|
19027
19365
|
}
|
|
19028
19366
|
return input;
|
|
19029
19367
|
}
|
|
@@ -19064,11 +19402,11 @@ function registerIntegrationProviderCommands(integrations) {
|
|
|
19064
19402
|
}
|
|
19065
19403
|
);
|
|
19066
19404
|
const payments = integrations.command("payments").description(
|
|
19067
|
-
"Credential payment gateways: payu, tpay, przelewy24 (p24), paynow, paypal, dodo. Stripe connects in the dashboard (OAuth); the transfer method is `integrations manual-payment`."
|
|
19405
|
+
"Credential payment gateways: payu, tpay, przelewy24 (p24), paynow, paypal, dodo, tubapay. Stripe connects in the dashboard (OAuth); the transfer method is `integrations manual-payment`."
|
|
19068
19406
|
);
|
|
19069
19407
|
payments.command("connect <gateway>").description(
|
|
19070
19408
|
"Connect a gateway \u2014 credentials are verified with the gateway first. With --secrets-env every secret flag takes an environment variable NAME instead of the value."
|
|
19071
|
-
).requiredOption("--name <name>", "creator-facing label").option("--pos-id <id>", "payu / tpay / przelewy24").option("--client-id <id>", "payu / tpay / paypal").option("--client-secret <secret>", "payu / tpay / paypal").option("--second-key <key>", "payu: the second (MD5) key").option("--safety-key <key>", "tpay: the security key").option("--api-key <key>", "przelewy24 / paynow / dodo").option("--signature-key <key>", "paynow").option("--merchant-id <id>", "przelewy24").option("--crc-key <key>", "przelewy24").option("--secrets-env", "treat every secret flag value as an environment variable name").action(async (gatewayArg, options, command) => {
|
|
19409
|
+
).requiredOption("--name <name>", "creator-facing label").option("--pos-id <id>", "payu / tpay / przelewy24").option("--client-id <id>", "payu / tpay / paypal; tubapay: the Partner ID").option("--client-secret <secret>", "payu / tpay / paypal / tubapay").option("--second-key <key>", "payu: the second (MD5) key").option("--safety-key <key>", "tpay: the security key").option("--api-key <key>", "przelewy24 / paynow / dodo").option("--signature-key <key>", "paynow").option("--merchant-id <id>", "przelewy24").option("--crc-key <key>", "przelewy24").option("--callback-secret <key>", "tubapay: the key TubaPay signs its notifications with").option("--secrets-env", "treat every secret flag value as an environment variable name").action(async (gatewayArg, options, command) => {
|
|
19072
19410
|
const flags = getGlobalFlags(command);
|
|
19073
19411
|
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
19074
19412
|
const status = await client.connectPaymentGateway(
|
|
@@ -19646,15 +19984,28 @@ join again to refresh it.
|
|
|
19646
19984
|
// src/commands/liveRooms/index.ts
|
|
19647
19985
|
var minutes = (seconds) => `${Math.round(seconds / 60)} min`;
|
|
19648
19986
|
var percent = (part, whole) => whole > 0 ? `${Math.round(part / whole * 100)}%` : "-";
|
|
19987
|
+
var countOrDash = (value) => value === null || value === void 0 ? "-" : String(value);
|
|
19649
19988
|
var WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
19989
|
+
function describeExclusions(schedule) {
|
|
19990
|
+
const parts = [];
|
|
19991
|
+
if (schedule.kind !== "daily" && schedule.nightWindow) {
|
|
19992
|
+
parts.push(`none ${schedule.nightWindow.from}-${schedule.nightWindow.to}`);
|
|
19993
|
+
}
|
|
19994
|
+
if (schedule.blackoutDates && schedule.blackoutDates.length > 0) {
|
|
19995
|
+
const days = schedule.blackoutDates.map((range) => range.from === range.to ? range.from : `${range.from}..${range.to}`).join(", ");
|
|
19996
|
+
parts.push(`none on ${days}`);
|
|
19997
|
+
}
|
|
19998
|
+
return parts.length > 0 ? `; ${parts.join("; ")}` : "";
|
|
19999
|
+
}
|
|
19650
20000
|
function describeSchedule(room) {
|
|
19651
20001
|
if (!room.schedule) return "fixed";
|
|
19652
20002
|
const until = room.schedule.until ? ` until ${room.schedule.until}` : "";
|
|
20003
|
+
const exclusions = describeExclusions(room.schedule);
|
|
19653
20004
|
if (room.schedule.kind === "daily") {
|
|
19654
20005
|
const days = room.schedule.weekdays ? room.schedule.weekdays.map((day) => WEEKDAYS[day - 1] ?? String(day)).join(", ") : "daily";
|
|
19655
|
-
return `${days} at ${room.schedule.times.join(", ")} (${room.timezone})${until}`;
|
|
20006
|
+
return `${days} at ${room.schedule.times.join(", ")} (${room.timezone})${until}${exclusions}`;
|
|
19656
20007
|
}
|
|
19657
|
-
return `every ${room.schedule.everyMinutes} min${until}`;
|
|
20008
|
+
return `every ${room.schedule.everyMinutes} min${until}${exclusions}`;
|
|
19658
20009
|
}
|
|
19659
20010
|
function registerLiveRoomsCommands(program2) {
|
|
19660
20011
|
const liveRooms = program2.command("live-rooms").description(
|
|
@@ -19687,6 +20038,7 @@ function registerLiveRoomsCommands(program2) {
|
|
|
19687
20038
|
printTable(
|
|
19688
20039
|
result.sessions.map((session) => ({
|
|
19689
20040
|
session: session.sessionStartAt,
|
|
20041
|
+
registered: countOrDash(session.registered),
|
|
19690
20042
|
attendees: session.attendees,
|
|
19691
20043
|
identified: session.identified,
|
|
19692
20044
|
avgWatched: `${minutes(session.averageWatchedSeconds)} (${percent(
|
|
@@ -19695,10 +20047,29 @@ function registerLiveRoomsCommands(program2) {
|
|
|
19695
20047
|
)})`,
|
|
19696
20048
|
toEnd: `${session.watchedToEnd} (${percent(session.watchedToEnd, session.attendees)})`,
|
|
19697
20049
|
sawOffer: session.sawOffer,
|
|
19698
|
-
clickedOffer: session.clickedOffer
|
|
20050
|
+
clickedOffer: session.clickedOffer,
|
|
20051
|
+
bought: countOrDash(session.purchased)
|
|
19699
20052
|
})),
|
|
19700
|
-
[
|
|
20053
|
+
[
|
|
20054
|
+
"session",
|
|
20055
|
+
"registered",
|
|
20056
|
+
"attendees",
|
|
20057
|
+
"identified",
|
|
20058
|
+
"avgWatched",
|
|
20059
|
+
"toEnd",
|
|
20060
|
+
"sawOffer",
|
|
20061
|
+
"clickedOffer",
|
|
20062
|
+
"bought"
|
|
20063
|
+
]
|
|
19701
20064
|
);
|
|
20065
|
+
const totals = result.totals;
|
|
20066
|
+
if (totals) {
|
|
20067
|
+
process.stdout.write(
|
|
20068
|
+
`
|
|
20069
|
+
Room total (${totals.sessions} started sessions): registered ${countOrDash(totals.registered)} \u2192 attended ${totals.attendees} \u2192 saw the offer ${totals.sawOffer} \u2192 clicked ${totals.clickedOffer} \u2192 bought ${countOrDash(totals.purchased)}${totals.capped ? " (at least: a read hit its cap)" : ""}
|
|
20070
|
+
`
|
|
20071
|
+
);
|
|
20072
|
+
}
|
|
19702
20073
|
if (options.session !== void 0) {
|
|
19703
20074
|
process.stdout.write(`
|
|
19704
20075
|
Viewers of ${options.session}:
|
|
@@ -25676,6 +26047,10 @@ function registerProductsCommands(program2) {
|
|
|
25676
26047
|
`);
|
|
25677
26048
|
if (product.storefrontVisibility) {
|
|
25678
26049
|
process.stdout.write(` Visibility: ${product.storefrontVisibility}
|
|
26050
|
+
`);
|
|
26051
|
+
}
|
|
26052
|
+
if (product.language !== void 0) {
|
|
26053
|
+
process.stdout.write(` Language: ${product.language ?? "none (platform language)"}
|
|
25679
26054
|
`);
|
|
25680
26055
|
}
|
|
25681
26056
|
process.stdout.write(` Clients: ${product.clientCount}
|
|
@@ -25695,6 +26070,10 @@ function registerProductsCommands(program2) {
|
|
|
25695
26070
|
"--period <period>",
|
|
25696
26071
|
"billing period for --amount: one_time, monthly or yearly (default one_time)"
|
|
25697
26072
|
).option("--description-file <path>", "read the product description from a file").option(
|
|
26073
|
+
"--language <pl|en>",
|
|
26074
|
+
"the product's language (buyer-facing pages and e-mails; omitted = the platform's language). Also picks the --amount currency when --currency is omitted (pl \u2192 pln, else usd)",
|
|
26075
|
+
parseProductLanguage
|
|
26076
|
+
).option(
|
|
25698
26077
|
"--cover <pathOrUrl>",
|
|
25699
26078
|
"cover image: a local file (uploaded to the media library first) or an https URL"
|
|
25700
26079
|
).option(
|
|
@@ -25715,7 +26094,8 @@ function registerProductsCommands(program2) {
|
|
|
25715
26094
|
name: options.name,
|
|
25716
26095
|
productType: options.type,
|
|
25717
26096
|
description,
|
|
25718
|
-
offer
|
|
26097
|
+
offer,
|
|
26098
|
+
language: options.language
|
|
25719
26099
|
});
|
|
25720
26100
|
const outcome = {};
|
|
25721
26101
|
try {
|
|
@@ -25764,21 +26144,28 @@ function registerProductsCommands(program2) {
|
|
|
25764
26144
|
});
|
|
25765
26145
|
}
|
|
25766
26146
|
);
|
|
25767
|
-
products2.command("update").description("Update a product's name, description and/or
|
|
26147
|
+
products2.command("update").description("Update a product's name, description, storefront visibility and/or language").argument("<id>", "product id").option("--name <name>", "new product name").option("--description <description>", "new product description").option(
|
|
25768
26148
|
"--visibility <public|unlisted|private>",
|
|
25769
26149
|
"where buyers find it once published: public (store + product page), unlisted (product page by link only), private (checkout links only)",
|
|
25770
26150
|
parseStorefrontVisibility
|
|
26151
|
+
).option(
|
|
26152
|
+
"--language <pl|en|none>",
|
|
26153
|
+
"the product's language (buyer-facing pages and e-mails); none clears it (the platform's language applies)",
|
|
26154
|
+
parseProductLanguageOrNone
|
|
25771
26155
|
).action(
|
|
25772
26156
|
async (id, options, command) => {
|
|
25773
|
-
if (options.name === void 0 && options.description === void 0 && options.visibility === void 0) {
|
|
25774
|
-
throw new Error(
|
|
26157
|
+
if (options.name === void 0 && options.description === void 0 && options.visibility === void 0 && options.language === void 0) {
|
|
26158
|
+
throw new Error(
|
|
26159
|
+
"Nothing to update: pass --name, --description, --visibility and/or --language."
|
|
26160
|
+
);
|
|
25775
26161
|
}
|
|
25776
26162
|
const flags = getGlobalFlags(command);
|
|
25777
26163
|
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
25778
26164
|
const result = await client.updateProduct(id, {
|
|
25779
26165
|
name: options.name,
|
|
25780
26166
|
description: options.description,
|
|
25781
|
-
storefrontVisibility: options.visibility
|
|
26167
|
+
storefrontVisibility: options.visibility,
|
|
26168
|
+
language: options.language === PRODUCT_LANGUAGE_NONE ? null : options.language
|
|
25782
26169
|
});
|
|
25783
26170
|
emit(flags, result, () => {
|
|
25784
26171
|
process.stdout.write(`Updated product ${result.productId}
|
|
@@ -26788,7 +27175,7 @@ function buildUpdateInput2(options) {
|
|
|
26788
27175
|
}
|
|
26789
27176
|
function registerReferralsCommands(program2) {
|
|
26790
27177
|
const referrals = program2.command("referrals").description(
|
|
26791
|
-
|
|
27178
|
+
'Referral programs: "Nagrody za polecenia" (kind referral, reward ladders for your customers) and "Program partnerski" (kind affiliate, partner commission), both from the Growth plan. Create programs over your products, enroll clients, approve or reject earned rewards, and retry failed reward deliveries'
|
|
26792
27179
|
);
|
|
26793
27180
|
referrals.command("list").description("List referral programs (kind, status, products, headline stats)").action(async (_, command) => {
|
|
26794
27181
|
const flags = getGlobalFlags(command);
|
|
@@ -26887,7 +27274,7 @@ Failed deliveries (${result.failedDeliveries.length})
|
|
|
26887
27274
|
});
|
|
26888
27275
|
});
|
|
26889
27276
|
referrals.command("create").description(
|
|
26890
|
-
"Create a program over one or more products. Deep config (milestones, commission, attribution) goes in --json; flat flags win over --json keys."
|
|
27277
|
+
"Create a program over one or more products (both kinds need the Growth plan). Deep config (milestones, commission, attribution) goes in --json; flat flags win over --json keys."
|
|
26891
27278
|
).requiredOption("--kind <kind>", `program kind (${PROGRAM_KINDS.join(" | ")})`).requiredOption("--name <name>", "program name").requiredOption("--product <ids>", "comma-separated product ids whose purchases count").option("--enrollment <mode>", `how participants join (${ENROLLMENT_MODES.join(" | ")})`).option("--status <status>", `initial status (${WRITABLE_STATUSES.join(" | ")})`).option(
|
|
26892
27279
|
"--json <fileOrJson>",
|
|
26893
27280
|
"inline JSON object or .json path with `milestones`, `commission` and/or `attribution` (write it as --json=<value> \u2014 a bare --json is the global JSON-output flag)"
|
|
@@ -26902,7 +27289,7 @@ Failed deliveries (${result.failedDeliveries.length})
|
|
|
26902
27289
|
});
|
|
26903
27290
|
});
|
|
26904
27291
|
referrals.command("update").description(
|
|
26905
|
-
"Update a program. --product and --json `milestones` are FULL replaces (read the program first); flat flags win over --json keys. Use `referrals archive` to archive."
|
|
27292
|
+
"Update a program. --product and --json `milestones` are FULL replaces (read the program first); flat flags win over --json keys. Activating (--status active) needs the Growth plan. Use `referrals archive` to archive."
|
|
26906
27293
|
).argument("<programId>", "program id").option("--name <name>", "program name").option("--status <status>", `status (${WRITABLE_STATUSES.join(" | ")})`).option("--product <ids>", "comma-separated product ids (full replace)").option("--enrollment <mode>", `how participants join (${ENROLLMENT_MODES.join(" | ")})`).option(
|
|
26907
27294
|
"--json <fileOrJson>",
|
|
26908
27295
|
"inline JSON object or .json path with `milestones`, `commission` and/or `attribution` (write it as --json=<value> \u2014 a bare --json is the global JSON-output flag)"
|
|
@@ -26930,7 +27317,7 @@ Failed deliveries (${result.failedDeliveries.length})
|
|
|
26930
27317
|
});
|
|
26931
27318
|
});
|
|
26932
27319
|
referrals.command("enroll").description(
|
|
26933
|
-
"Enroll one client as a participant (idempotent \u2014 re-enrolling reports `alreadyEnrolled`). Prints the ref code the client shares."
|
|
27320
|
+
"Enroll one client as a participant (idempotent \u2014 re-enrolling reports `alreadyEnrolled`). Prints the ref code the client shares. Needs the Growth plan."
|
|
26934
27321
|
).argument("<programId>", "program id").requiredOption("--client <clientId>", "workspace client id (wcid)").requiredOption("--email <email>", "the client's email").option("--first-name <name>", "first name (optional)").option("--last-name <name>", "last name (optional)").action(async (programId, options, command) => {
|
|
26935
27322
|
const flags = getGlobalFlags(command);
|
|
26936
27323
|
const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
|
|
@@ -26949,7 +27336,7 @@ Failed deliveries (${result.failedDeliveries.length})
|
|
|
26949
27336
|
});
|
|
26950
27337
|
});
|
|
26951
27338
|
referrals.command("enroll-all").description(
|
|
26952
|
-
|
|
27339
|
+
'Enroll EVERY client with access to one of the program products ("Nagrody za polecenia" only: a "Program partnerski" is refused, partners join by invite link). Needs the Growth plan. Requires --confirm. Reports enrolled / alreadyEnrolled / skippedWithoutAccount counts.'
|
|
26953
27340
|
).argument("<programId>", "program id").option("--confirm", "required \u2014 acknowledge the bulk enrollment").action(async (programId, options, command) => {
|
|
26954
27341
|
const flags = getGlobalFlags(command);
|
|
26955
27342
|
requireConfirm13(options.confirm, `enroll all clients in program ${programId}`);
|
|
@@ -30376,8 +30763,8 @@ function applyShortHelp(program2) {
|
|
|
30376
30763
|
|
|
30377
30764
|
// src/program.ts
|
|
30378
30765
|
function resolveCliVersion() {
|
|
30379
|
-
if ("0.
|
|
30380
|
-
return "0.
|
|
30766
|
+
if ("0.10.0".length > 0) {
|
|
30767
|
+
return "0.10.0";
|
|
30381
30768
|
}
|
|
30382
30769
|
try {
|
|
30383
30770
|
const raw = readFileSync28(new URL("../package.json", import.meta.url), "utf8");
|