ckweb-cli 0.6.0-beta.1 → 0.7.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/README.md CHANGED
@@ -72,15 +72,19 @@ ckweb seo traffic "example.com"
72
72
  | `referrals dashboard` | View referral stats |
73
73
  | `referrals request-payout` | Request payout |
74
74
  | `referrals payout-history` | View payout history |
75
+ | `referrals leaderboard\|tiers\|resolve\|track\|referees` | Referral discovery, tracking, and referee lookup |
75
76
  | `payout profile` | View payout profiles |
76
77
  | `payout create-profile` | Create payout profile |
77
78
  | `payout delete-profile` | Delete payout profile |
78
79
 
80
+ Payout profile note: current `claudekit-web` payout profile endpoints are browser-session routes. Full API-key automation for payout profile and VNeID conversion flows requires a backend API-key contract first.
81
+
79
82
  ### Content
80
83
  | Command | Description |
81
84
  |---------|-------------|
82
85
  | `blog list` | List blog articles |
83
86
  | `blog get <id>` | Get article details |
87
+ | `blog regenerate-html --article <id>\|--all` | Regenerate article HTML (admin key) |
84
88
  | `releases list [--tab]` | List product releases |
85
89
 
86
90
  ### Proxy Services (YouTube, Web, SEO)
@@ -97,12 +101,13 @@ ckweb seo traffic "example.com"
97
101
  | `pricing exchange-rate` | Get USD/VND rate |
98
102
  | `pricing early-access` | Early access status |
99
103
  | `loyalty eligibility` | Check loyalty eligibility |
104
+ | `premium validate` | Validate premium access for current API key |
100
105
  | `stats users` | Platform user count |
101
106
 
102
107
  ### Other
103
108
  | Command | Description |
104
109
  |---------|-------------|
105
- | `github invite\|revoke` | GitHub repo access |
110
+ | `github validate\|invite\|revoke` | GitHub username validation and repo access |
106
111
  | `newsletter subscribe\|unsubscribe` | Newsletter management |
107
112
  | `waitlist join` | Join product waitlist |
108
113
  | `health` | Check API health |
@@ -125,6 +130,10 @@ ckweb seo traffic "example.com"
125
130
  | `admin discount-groups` | list, get, create, update, delete |
126
131
  | `admin tiers` | list |
127
132
 
133
+ Admin payout note: backend payout PII/actions such as `/api/admin/payouts`, `/api/admin/payout-requests`, and `/api/admin/payout-vneid-requests` intentionally require an interactive browser admin session. The CLI documents those as unsupported by API-key auth instead of pretending they are safe automation commands.
134
+
135
+ Browser-session note: several dashboard endpoints in `claudekit-web` still use cookie session auth (`getCurrentUser()`), including user API-key management, teams, loyalty checkout, GDPR account actions, and referral payout requests. The coverage test tracks these as explicit backend-contract gaps, not working API-key CLI coverage.
136
+
128
137
  ## Authentication
129
138
 
130
139
  Two types of API keys:
@@ -237,7 +246,7 @@ Install beta builds with:
237
246
  npm install -g ckweb-cli@beta
238
247
  ```
239
248
 
240
- Current status: verified on `dev` by Beta Release run `26148322508`, published as `ckweb-cli@0.6.0-beta.0` with npm dist-tag `beta`.
249
+ Current status: verified on `dev` by Beta Release run `26159614526`, published as `ckweb-cli@0.6.0-beta.1` with npm dist-tag `beta`.
241
250
  - no relevant commits → skipped
242
251
 
243
252
  The workflow bumps `package.json`, creates `chore(release): vX.Y.Z` commit + tag,
package/dist/index.js CHANGED
@@ -211,7 +211,7 @@ function buildUrl(path2, params) {
211
211
  }
212
212
  function buildHeaders(apiKey, hasBody) {
213
213
  const headers = {
214
- "User-Agent": `ckweb-cli/${"0.6.0-beta.1"}`
214
+ "User-Agent": `ckweb-cli/${"0.7.0"}`
215
215
  };
216
216
  if (hasBody) {
217
217
  headers["Content-Type"] = "application/json";
@@ -823,6 +823,22 @@ var PAYOUT_COLUMNS = [
823
823
  { key: "status", header: "Status", width: 12 },
824
824
  { key: "createdAt", header: "Created", width: 22 }
825
825
  ];
826
+ var REFEREE_STATUSES = ["all", "pending", "approved", "paid", "cancelled"];
827
+ var REFEREE_SORTS = ["createdAt", "amount", "status"];
828
+ var REFEREE_ORDERS = ["asc", "desc"];
829
+ function parseBoundedInteger(value, label, min, max) {
830
+ const parsed = Number(value);
831
+ if (!Number.isFinite(parsed) || !Number.isInteger(parsed) || parsed < min || parsed > max) {
832
+ throw new CliError(`${label} must be an integer between ${min} and ${max}`);
833
+ }
834
+ return parsed;
835
+ }
836
+ function assertOneOf(value, allowed, label) {
837
+ if (!allowed.includes(value)) {
838
+ throw new CliError(`${label} must be one of: ${allowed.join(", ")}`);
839
+ }
840
+ return value;
841
+ }
826
842
  function registerReferralsCommand(program2) {
827
843
  const referrals = program2.command("referrals").description("Referral program management");
828
844
  referrals.command("dashboard").description("View your referral dashboard").action(async function() {
@@ -853,6 +869,69 @@ function registerReferralsCommand(program2) {
853
869
  handleError(err);
854
870
  }
855
871
  });
872
+ referrals.command("leaderboard").description("View public referral leaderboard").action(async function() {
873
+ try {
874
+ const data = await fetchApi("GET", "/referrals/leaderboard", { noAuth: true });
875
+ formatOutput(data, getOutputOpts(this));
876
+ } catch (err) {
877
+ handleError(err);
878
+ }
879
+ });
880
+ referrals.command("tiers").description("List public referral tiers").action(async function() {
881
+ try {
882
+ const data = await fetchApi("GET", "/referrals/tiers", { noAuth: true });
883
+ formatOutput(data, getOutputOpts(this));
884
+ } catch (err) {
885
+ handleError(err);
886
+ }
887
+ });
888
+ referrals.command("resolve <code>").description("Resolve a referral code").action(async function(code) {
889
+ try {
890
+ const data = await fetchApi("GET", "/referrals/resolve", {
891
+ noAuth: true,
892
+ params: { code }
893
+ });
894
+ formatOutput(data, getOutputOpts(this));
895
+ } catch (err) {
896
+ handleError(err);
897
+ }
898
+ });
899
+ referrals.command("track <code>").description("Track a referral click").action(async function(code) {
900
+ try {
901
+ const data = await fetchApi("GET", "/referrals/track", {
902
+ noAuth: true,
903
+ params: { code }
904
+ });
905
+ formatOutput(data, getOutputOpts(this));
906
+ } catch (err) {
907
+ handleError(err);
908
+ }
909
+ });
910
+ referrals.command("referees").description("List referees attributed to your referral account").option("--status <status>", "Filter by commission status", "all").option("--sort <field>", "Sort by createdAt, amount, or status", "createdAt").option("--order <direction>", "Sort direction: asc or desc", "desc").option("--order-ref <id>", "Filter by 8-character order display ID").option("--limit <n>", "Page size", "50").option("--offset <n>", "Offset for pagination", "0").action(async function() {
911
+ try {
912
+ ensureAuth();
913
+ const opts = this.opts();
914
+ const limit = parseBoundedInteger(opts.limit, "--limit", 1, 100);
915
+ const offset = parseBoundedInteger(opts.offset, "--offset", 0, 5e3);
916
+ const params = {
917
+ status: assertOneOf(opts.status, REFEREE_STATUSES, "--status"),
918
+ sort: assertOneOf(opts.sort, REFEREE_SORTS, "--sort"),
919
+ order: assertOneOf(opts.order, REFEREE_ORDERS, "--order"),
920
+ limit: String(limit),
921
+ offset: String(offset)
922
+ };
923
+ if (opts.orderRef) {
924
+ if (!/^[0-9a-fA-F]{8}$/.test(opts.orderRef)) {
925
+ throw new CliError("--order-ref must be an 8-character order display ID");
926
+ }
927
+ params["orderRef"] = opts.orderRef.toLowerCase();
928
+ }
929
+ const data = await fetchApi("GET", "/referrals/referees", { params });
930
+ formatOutput(data, getOutputOpts(this));
931
+ } catch (err) {
932
+ handleError(err);
933
+ }
934
+ });
856
935
  }
857
936
 
858
937
  // src/commands/blog.ts
@@ -881,6 +960,26 @@ function registerBlogCommand(program2) {
881
960
  handleError(err);
882
961
  }
883
962
  });
963
+ blog.command("regenerate-html").description("Regenerate stored HTML for missing article content").option("--article <id>", "Regenerate one article by ID").option("--all", "Regenerate all articles missing HTML").action(async function() {
964
+ try {
965
+ ensureAdminAuth();
966
+ const opts = this.opts();
967
+ if (!opts.article && !opts.all) {
968
+ throw new CliError("Provide --article <id> or explicit --all.");
969
+ }
970
+ if (opts.article && opts.all) {
971
+ throw new CliError("Use either --article <id> or --all, not both.");
972
+ }
973
+ const body = opts.article ? { articleId: opts.article } : {};
974
+ const data = await fetchApi("POST", "/blog/regenerate-html", {
975
+ adminAuth: true,
976
+ body
977
+ });
978
+ formatOutput(data, getOutputOpts(this));
979
+ } catch (err) {
980
+ handleError(err);
981
+ }
982
+ });
884
983
  }
885
984
 
886
985
  // src/commands/health.ts
@@ -987,6 +1086,17 @@ function registerCheckoutCommand(program2) {
987
1086
  import * as readline3 from "readline/promises";
988
1087
  function registerGithubCommand(program2) {
989
1088
  const github = program2.command("github").description("GitHub repository access");
1089
+ github.command("validate <username>").description("Validate a GitHub username").action(async function(username) {
1090
+ try {
1091
+ const data = await fetchApi("GET", "/github/validate", {
1092
+ noAuth: true,
1093
+ params: { username }
1094
+ });
1095
+ formatOutput(data, getOutputOpts(this));
1096
+ } catch (err) {
1097
+ handleError(err);
1098
+ }
1099
+ });
990
1100
  github.command("invite").description("Grant GitHub repository access via license").requiredOption("--license <id>", "License ID").action(async function() {
991
1101
  try {
992
1102
  ensureAuth();
@@ -1154,6 +1264,20 @@ function registerPricingCommand(program2) {
1154
1264
  });
1155
1265
  }
1156
1266
 
1267
+ // src/commands/premium.ts
1268
+ function registerPremiumCommand(program2) {
1269
+ const premium = program2.command("premium").description("Premium license utilities");
1270
+ premium.command("validate").description("Validate whether the current API key has premium access").action(async function() {
1271
+ try {
1272
+ ensureAuth();
1273
+ const data = await fetchApi("GET", "/premium/validate");
1274
+ formatOutput(data, getOutputOpts(this));
1275
+ } catch (err) {
1276
+ handleError(err);
1277
+ }
1278
+ });
1279
+ }
1280
+
1157
1281
  // src/commands/refunds.ts
1158
1282
  import * as readline5 from "readline/promises";
1159
1283
  function registerRefundsCommand(program2) {
@@ -3133,7 +3257,7 @@ function registerAdminCommand(program2) {
3133
3257
  // src/index.ts
3134
3258
  loadDotenvFiles();
3135
3259
  var program = new Command();
3136
- program.name("ckweb").description("CLI for interacting with ClaudeKit.cc API").version("0.6.0-beta.1");
3260
+ program.name("ckweb").description("CLI for interacting with ClaudeKit.cc API").version("0.7.0");
3137
3261
  program.option("--json", "Output as JSON").option("--table", "Output as table").option("--quiet", "Minimal output");
3138
3262
  registerAuthCommand(program);
3139
3263
  registerHealthCommand(program);
@@ -3147,6 +3271,7 @@ registerLoyaltyCommand(program);
3147
3271
  registerNewsletterCommand(program);
3148
3272
  registerPayoutCommand(program);
3149
3273
  registerPricingCommand(program);
3274
+ registerPremiumCommand(program);
3150
3275
  registerRefundsCommand(program);
3151
3276
  registerReleasesCommand(program);
3152
3277
  registerStatsCommand(program);