@gpc-cli/cli 0.9.81 → 0.9.83

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.
Files changed (53) hide show
  1. package/README.md +1 -1
  2. package/dist/bin.js +2 -2
  3. package/dist/{changelog-STYBBYDC.js → changelog-4F6SYF2T.js} +4 -3
  4. package/dist/changelog-4F6SYF2T.js.map +1 -0
  5. package/dist/{chunk-LKI2MVT4.js → chunk-7UYPZIQZ.js} +19 -19
  6. package/dist/{config-3GHC45S5.js → config-UHHSRFXL.js} +2 -2
  7. package/dist/{docs-OU6LSSJD.js → docs-ADZRT76Y.js} +10 -6
  8. package/dist/docs-ADZRT76Y.js.map +1 -0
  9. package/dist/{doctor-AO52FMY4.js → doctor-4ZWCSYGF.js} +4 -4
  10. package/dist/{doctor-AO52FMY4.js.map → doctor-4ZWCSYGF.js.map} +1 -1
  11. package/dist/{external-transactions-IIF2TSH6.js → external-transactions-GFMGHOW2.js} +1 -1
  12. package/dist/external-transactions-GFMGHOW2.js.map +1 -0
  13. package/dist/{feedback-OT4VK7B6.js → feedback-HRSYQTUV.js} +2 -2
  14. package/dist/generated/docs-bundle.json +1 -1
  15. package/dist/{iap-S5X4O7XF.js → iap-BMXWA22W.js} +28 -4
  16. package/dist/iap-BMXWA22W.js.map +1 -0
  17. package/dist/index.js +1 -1
  18. package/dist/{one-time-products-YSX5VI6I.js → one-time-products-HHCHEDRJ.js} +4 -4
  19. package/dist/one-time-products-HHCHEDRJ.js.map +1 -0
  20. package/dist/{pricing-HYQRXKNO.js → pricing-B6Y5B335.js} +7 -5
  21. package/dist/pricing-B6Y5B335.js.map +1 -0
  22. package/dist/{purchases-3KUR5YR3.js → purchases-N73M3NJM.js} +14 -4
  23. package/dist/purchases-N73M3NJM.js.map +1 -0
  24. package/dist/{releases-IH2ZK3BB.js → releases-YJCNQHY7.js} +7 -4
  25. package/dist/releases-YJCNQHY7.js.map +1 -0
  26. package/dist/{reviews-FF2N2SLT.js → reviews-D5JXX252.js} +28 -10
  27. package/dist/reviews-D5JXX252.js.map +1 -0
  28. package/dist/{subscriptions-FR6GCMPC.js → subscriptions-KEF7KIST.js} +28 -5
  29. package/dist/subscriptions-KEF7KIST.js.map +1 -0
  30. package/dist/{system-apks-ZKVZLJPY.js → system-apks-6PTB7LLD.js} +6 -2
  31. package/dist/system-apks-6PTB7LLD.js.map +1 -0
  32. package/dist/{update-TXLKZ6JD.js → update-ROEAKMQD.js} +2 -2
  33. package/dist/{users-HJAXLZPM.js → users-EKXLDY2Y.js} +6 -2
  34. package/dist/users-EKXLDY2Y.js.map +1 -0
  35. package/dist/{version-BHRQPXO6.js → version-X3RJKLJW.js} +2 -2
  36. package/package.json +1 -1
  37. package/dist/changelog-STYBBYDC.js.map +0 -1
  38. package/dist/docs-OU6LSSJD.js.map +0 -1
  39. package/dist/external-transactions-IIF2TSH6.js.map +0 -1
  40. package/dist/iap-S5X4O7XF.js.map +0 -1
  41. package/dist/one-time-products-YSX5VI6I.js.map +0 -1
  42. package/dist/pricing-HYQRXKNO.js.map +0 -1
  43. package/dist/purchases-3KUR5YR3.js.map +0 -1
  44. package/dist/releases-IH2ZK3BB.js.map +0 -1
  45. package/dist/reviews-FF2N2SLT.js.map +0 -1
  46. package/dist/subscriptions-FR6GCMPC.js.map +0 -1
  47. package/dist/system-apks-ZKVZLJPY.js.map +0 -1
  48. package/dist/users-HJAXLZPM.js.map +0 -1
  49. /package/dist/{chunk-LKI2MVT4.js.map → chunk-7UYPZIQZ.js.map} +0 -0
  50. /package/dist/{config-3GHC45S5.js.map → config-UHHSRFXL.js.map} +0 -0
  51. /package/dist/{feedback-OT4VK7B6.js.map → feedback-HRSYQTUV.js.map} +0 -0
  52. /package/dist/{update-TXLKZ6JD.js.map → update-ROEAKMQD.js.map} +0 -0
  53. /package/dist/{version-BHRQPXO6.js.map → version-X3RJKLJW.js.map} +0 -0
@@ -26,12 +26,14 @@ import {
26
26
  formatOutput,
27
27
  maybePaginate,
28
28
  sortResults,
29
+ annotateListResult,
30
+ moreResultsFooter,
29
31
  GpcError
30
32
  } from "@gpc-cli/core";
31
33
  var MAX_REPLY_CHARS = 350;
32
34
  function registerReviewsCommands(program) {
33
35
  const reviews = program.command("reviews").description("Manage user reviews and ratings");
34
- reviews.command("list").description("List user reviews").option("--stars <n>", "Filter by star rating (1-5)", parseInt).option("--lang <code>", "Filter by reviewer language").option("--since <date>", "Filter reviews after date (ISO 8601)").option("--translate-to <lang>", "Translate reviews to language").option("--max <n>", "Maximum number of reviews per page", parseInt).option("--limit <n>", "Maximum total results", parseInt).option("--next-page <token>", "Resume from page token").option("--all", "Auto-paginate to fetch all reviews (API returns last 7 days only)").option("--sort <field>", "Sort by field (prefix with - for descending)").action(async (options) => {
36
+ reviews.command("list").description("List user reviews").option("--stars <n>", "Filter by star rating (1-5)", parseInt).option("--lang <code>", "Filter by reviewer language").option("--since <date>", "Filter reviews after date (ISO 8601)").option("--translate-to <lang>", "Translate reviews to language").option("--max <n>", "Maximum number of reviews per page", parseInt).option("--limit <n>", "Maximum total results", parseInt).option("--next-page <token>", "Resume from page token").option("--all", "Auto-paginate to fetch all reviews (API returns last 7 days only)").option("--sort <field>", "Sort by field (prefix with - for descending)").option("--full-text", "Show full review text in table output (not truncated)").action(async (options) => {
35
37
  const config = await loadConfig();
36
38
  const packageName = resolvePackageName(program.opts()["app"], config);
37
39
  const client = await getClient(config);
@@ -46,28 +48,44 @@ function registerReviewsCommands(program) {
46
48
  nextPage: options.nextPage,
47
49
  all: options.all
48
50
  });
49
- if (Array.isArray(result) && result.length === 0 && format !== "json") {
50
- console.log("No reviews found.");
51
- return;
52
- }
53
- const sorted = sortResults(result, options.sort);
54
- if (format !== "json" && Array.isArray(sorted)) {
51
+ const sorted = sortResults(result.reviews, options.sort);
52
+ if (format !== "json") {
53
+ if (sorted.length === 0) {
54
+ console.log("No reviews found.");
55
+ return;
56
+ }
55
57
  const rows = sorted.map((r) => {
56
58
  const rv = r;
57
59
  const comments = rv["comments"];
58
60
  const userComment = comments?.[0]?.["userComment"];
61
+ const hasReply = comments?.some((c) => c["developerComment"]) ? "yes" : "no";
62
+ const fullText = String(userComment?.["text"] || "-");
63
+ const truncated = !options.fullText && fullText.length > 80;
59
64
  return {
60
65
  reviewId: rv["reviewId"] || "-",
61
66
  author: rv["authorName"] || "-",
67
+ lang: userComment?.["reviewerLanguage"] || "-",
62
68
  stars: userComment?.["starRating"] || "-",
63
- text: String(userComment?.["text"] || "-").slice(0, 80),
69
+ text: truncated ? fullText.slice(0, 80) + "... [truncated]" : fullText,
70
+ hasReply,
64
71
  lastModified: userComment?.["lastModified"] ? String(userComment["lastModified"]?.["seconds"] || "-") : "-",
65
72
  thumbsUp: userComment?.["thumbsUpCount"] || 0
66
73
  };
67
74
  });
68
75
  await maybePaginate(formatOutput(rows, format));
76
+ const footer = moreResultsFooter(result.nextPageToken);
77
+ if (footer) console.log(footer);
69
78
  } else {
70
- await maybePaginate(formatOutput(sorted, format));
79
+ console.log(
80
+ formatOutput(
81
+ annotateListResult(
82
+ { reviews: sorted, nextPageToken: result.nextPageToken },
83
+ "reviews",
84
+ "No reviews found"
85
+ ),
86
+ format
87
+ )
88
+ );
71
89
  }
72
90
  });
73
91
  reviews.command("get <review-id>").description("Get a single review").option("--translate-to <lang>", "Translate review to language").action(async (reviewId, options) => {
@@ -194,4 +212,4 @@ Rating distribution:`);
194
212
  export {
195
213
  registerReviewsCommands
196
214
  };
197
- //# sourceMappingURL=reviews-FF2N2SLT.js.map
215
+ //# sourceMappingURL=reviews-D5JXX252.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/reviews.ts"],"sourcesContent":["import { resolvePackageName, getClient } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\n\nimport {\n listReviews,\n getReview,\n replyToReview,\n exportReviews,\n analyzeReviews,\n formatOutput,\n maybePaginate,\n sortResults,\n annotateListResult,\n moreResultsFooter,\n GpcError,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { isInteractive, requireOption } from \"../prompt.js\";\n\nconst MAX_REPLY_CHARS = 350;\n\nexport function registerReviewsCommands(program: Command): void {\n const reviews = program.command(\"reviews\").description(\"Manage user reviews and ratings\");\n\n reviews\n .command(\"list\")\n .description(\"List user reviews\")\n .option(\"--stars <n>\", \"Filter by star rating (1-5)\", parseInt)\n .option(\"--lang <code>\", \"Filter by reviewer language\")\n .option(\"--since <date>\", \"Filter reviews after date (ISO 8601)\")\n .option(\"--translate-to <lang>\", \"Translate reviews to language\")\n .option(\"--max <n>\", \"Maximum number of reviews per page\", parseInt)\n .option(\"--limit <n>\", \"Maximum total results\", parseInt)\n .option(\"--next-page <token>\", \"Resume from page token\")\n .option(\"--all\", \"Auto-paginate to fetch all reviews (API returns last 7 days only)\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending)\")\n .option(\"--full-text\", \"Show full review text in table output (not truncated)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listReviews(client, packageName, {\n stars: options.stars,\n language: options.lang,\n since: options.since,\n translationLanguage: options.translateTo,\n maxResults: options.max,\n limit: options.limit,\n nextPage: options.nextPage,\n all: options.all,\n });\n const sorted = sortResults(result.reviews, options.sort);\n if (format !== \"json\") {\n if (sorted.length === 0) {\n console.log(\"No reviews found.\");\n return;\n }\n const rows = sorted.map((r: unknown) => {\n const rv = r as Record<string, unknown>;\n const comments = rv[\"comments\"] as Record<string, unknown>[] | undefined;\n const userComment = comments?.[0]?.[\"userComment\"] as Record<string, unknown> | undefined;\n const hasReply = comments?.some((c) => c[\"developerComment\"]) ? \"yes\" : \"no\";\n const fullText = String(userComment?.[\"text\"] || \"-\");\n const truncated = !options.fullText && fullText.length > 80;\n return {\n reviewId: rv[\"reviewId\"] || \"-\",\n author: rv[\"authorName\"] || \"-\",\n lang: userComment?.[\"reviewerLanguage\"] || \"-\",\n stars: userComment?.[\"starRating\"] || \"-\",\n text: truncated ? fullText.slice(0, 80) + \"... [truncated]\" : fullText,\n hasReply,\n lastModified: userComment?.[\"lastModified\"]\n ? String((userComment[\"lastModified\"] as Record<string, unknown>)?.[\"seconds\"] || \"-\")\n : \"-\",\n thumbsUp: userComment?.[\"thumbsUpCount\"] || 0,\n };\n });\n await maybePaginate(formatOutput(rows, format));\n const footer = moreResultsFooter(result.nextPageToken);\n if (footer) console.log(footer);\n } else {\n console.log(\n formatOutput(\n annotateListResult(\n { reviews: sorted, nextPageToken: result.nextPageToken },\n \"reviews\",\n \"No reviews found\",\n ),\n format,\n ),\n );\n }\n });\n\n reviews\n .command(\"get <review-id>\")\n .description(\"Get a single review\")\n .option(\"--translate-to <lang>\", \"Translate review to language\")\n .action(async (reviewId: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await getReview(client, packageName, reviewId, options.translateTo);\n console.log(formatOutput(result, format));\n });\n\n reviews\n .command(\"reply <review-id>\")\n .description(\"Reply to a review\")\n .option(\"--text <text>\", \"Reply text (max 350 chars)\")\n .action(async (reviewId: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const interactive = isInteractive(program);\n\n options.text = await requireOption(\n \"text\",\n options.text,\n {\n message: \"Reply text (max 350 chars):\",\n },\n interactive,\n );\n\n if (options.text.length > MAX_REPLY_CHARS) {\n throw new GpcError(\n `Reply text exceeds ${MAX_REPLY_CHARS} characters (${options.text.length} chars). Google Play will reject this reply.`,\n \"REVIEWS_USAGE_ERROR\",\n 2,\n `Shorten your reply to ${MAX_REPLY_CHARS} characters or fewer.`,\n );\n }\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"reviews reply\",\n action: \"reply to\",\n target: reviewId,\n details: { text: options.text },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await replyToReview(client, packageName, reviewId, options.text);\n if (format !== \"json\") {\n const charCount = options.text.length;\n console.log(`Reply sent (${charCount}/350 chars)`);\n }\n console.log(formatOutput(result, format));\n });\n\n reviews\n .command(\"analyze\")\n .description(\"Analyze reviews: sentiment, topics, keywords, rating distribution\")\n .option(\"--stars <n>\", \"Filter by star rating (1-5)\", parseInt)\n .option(\"--lang <code>\", \"Filter by reviewer language\")\n .option(\"--since <date>\", \"Filter reviews after date (ISO 8601)\")\n .option(\"--max <n>\", \"Maximum number of reviews to analyze\", parseInt)\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await analyzeReviews(client, packageName, {\n stars: options.stars,\n language: options.lang,\n since: options.since,\n maxResults: options.max,\n });\n\n if (format === \"json\") {\n console.log(formatOutput(result, format));\n return;\n }\n\n console.log(`\\nReview Analysis — ${packageName}`);\n console.log(`${\"─\".repeat(50)}`);\n console.log(`Total reviews: ${result.totalReviews}`);\n console.log(\n `Average rating: ${result.avgRating > 0 ? result.avgRating.toFixed(2) + \" ★\" : \"N/A\"}`,\n );\n console.log(`\\nSentiment:`);\n console.log(\n ` Positive: ${result.sentiment.positive} Negative: ${result.sentiment.negative} Neutral: ${result.sentiment.neutral}`,\n );\n console.log(` Avg score: ${result.sentiment.avgScore} (range -1 to +1)`);\n\n if (result.topics.length > 0) {\n console.log(`\\nTop topics:`);\n for (const t of result.topics.slice(0, 8)) {\n const bar = t.avgScore > 0.1 ? \"+\" : t.avgScore < -0.1 ? \"-\" : \"~\";\n console.log(` [${bar}] ${t.topic.padEnd(20)} ${t.count} reviews`);\n }\n }\n\n if (result.keywords.length > 0) {\n console.log(\n `\\nTop keywords: ${result.keywords\n .slice(0, 10)\n .map((k) => k.word)\n .join(\", \")}`,\n );\n }\n\n if (Object.keys(result.ratingDistribution).length > 0) {\n console.log(`\\nRating distribution:`);\n for (let star = 5; star >= 1; star--) {\n const count = result.ratingDistribution[star] ?? 0;\n if (count > 0) console.log(` ${star}★ ${count}`);\n }\n }\n });\n\n reviews\n .command(\"export\")\n .description(\"Export reviews to JSON or CSV\")\n .option(\"--format <type>\", \"Output format: json or csv\", \"json\")\n .option(\"--stars <n>\", \"Filter by star rating (1-5)\", parseInt)\n .option(\"--lang <code>\", \"Filter by reviewer language\")\n .option(\"--since <date>\", \"Filter reviews after date (ISO 8601)\")\n .option(\"--translate-to <lang>\", \"Translate reviews to language\")\n .option(\"--output <file>\", \"Write output to file instead of stdout\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n\n const result = await exportReviews(client, packageName, {\n format: options.format as \"json\" | \"csv\",\n stars: options.stars,\n language: options.lang,\n since: options.since,\n translationLanguage: options.translateTo,\n });\n\n if (options.output) {\n const { writeFile } = await import(\"node:fs/promises\");\n await writeFile(options.output, result, \"utf-8\");\n console.log(`Reviews exported to ${options.output}`);\n } else {\n console.log(result);\n }\n });\n}\n"],"mappings":"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","names":[]}
@@ -41,7 +41,9 @@ import {
41
41
  getSubscriptionAnalytics,
42
42
  formatOutput,
43
43
  sortResults,
44
- maybePaginate
44
+ maybePaginate,
45
+ annotateListResult,
46
+ moreResultsFooter
45
47
  } from "@gpc-cli/core";
46
48
  function registerSubscriptionsCommands(program) {
47
49
  const subs = program.command("subscriptions").description("Manage subscriptions and base plans");
@@ -72,9 +74,18 @@ function registerSubscriptionsCommands(program) {
72
74
  firstBasePlanState: s.basePlans?.[0]?.state || "-"
73
75
  }));
74
76
  await maybePaginate(formatOutput(summary, format));
77
+ const footer = moreResultsFooter(result.nextPageToken);
78
+ if (footer) console.log(footer);
75
79
  } else {
76
80
  await maybePaginate(
77
- formatOutput(subs2.length === 0 ? { subscriptions: [] } : result, format)
81
+ formatOutput(
82
+ annotateListResult(
83
+ { ...result, subscriptions: subs2 },
84
+ "subscriptions",
85
+ "No subscriptions found"
86
+ ),
87
+ format
88
+ )
78
89
  );
79
90
  }
80
91
  });
@@ -270,7 +281,13 @@ function registerSubscriptionsCommands(program) {
270
281
  }
271
282
  const client = await getClient(config);
272
283
  const data = await readJsonFile(options.file);
273
- await migratePrices(client, packageName, productId, basePlanId, data);
284
+ await migratePrices(
285
+ client,
286
+ packageName,
287
+ productId,
288
+ basePlanId,
289
+ data
290
+ );
274
291
  console.log(formatOutput({ success: true }, format));
275
292
  }
276
293
  );
@@ -327,7 +344,13 @@ function registerSubscriptionsCommands(program) {
327
344
  }
328
345
  const client = await getClient(config);
329
346
  const data = await readJsonFile(options.file);
330
- const result = await createOffer(client, packageName, productId, basePlanId, data);
347
+ const result = await createOffer(
348
+ client,
349
+ packageName,
350
+ productId,
351
+ basePlanId,
352
+ data
353
+ );
331
354
  console.log(formatOutput(result, format));
332
355
  }
333
356
  );
@@ -507,4 +530,4 @@ By product:`);
507
530
  export {
508
531
  registerSubscriptionsCommands
509
532
  };
510
- //# sourceMappingURL=subscriptions-FR6GCMPC.js.map
533
+ //# sourceMappingURL=subscriptions-KEF7KIST.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/subscriptions.ts"],"sourcesContent":["import { resolvePackageName, getClient } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { Option } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\n\nimport type { Subscription, BasePlanMigratePricesRequest, SubscriptionOffer } from \"@gpc-cli/api\";\nimport {\n listSubscriptions,\n getSubscription,\n createSubscription,\n updateSubscription,\n deleteSubscription,\n activateBasePlan,\n deactivateBasePlan,\n deleteBasePlan,\n migratePrices,\n listOffers,\n getOffer,\n createOffer,\n updateOffer,\n deleteOffer,\n activateOffer,\n deactivateOffer,\n diffSubscription,\n getSubscriptionAnalytics,\n formatOutput,\n sortResults,\n maybePaginate,\n annotateListResult,\n moreResultsFooter,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { readJsonFile } from \"../json.js\";\n\nexport function registerSubscriptionsCommands(program: Command): void {\n const subs = program.command(\"subscriptions\").description(\"Manage subscriptions and base plans\");\n\n subs\n .command(\"list\")\n .description(\"List subscriptions\")\n .addOption(new Option(\"--page-size <n>\", \"Results per page\").argParser(parseInt).hideHelp())\n .addOption(new Option(\"--page-token <token>\", \"Page token\").hideHelp())\n .option(\"--limit <n>\", \"Maximum total results\", parseInt)\n .option(\"--next-page <token>\", \"Resume from page token\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listSubscriptions(client, packageName, {\n pageSize: options.pageSize,\n pageToken: options.pageToken,\n limit: options.limit,\n nextPage: options.nextPage,\n });\n if (options.sort) {\n result.subscriptions = sortResults(result.subscriptions, options.sort);\n }\n const subs = result.subscriptions || [];\n if (format !== \"json\") {\n if (subs.length === 0) {\n console.log(\"No subscriptions found.\");\n return;\n }\n const summary = subs.map((s: Subscription) => ({\n productId: s.productId,\n basePlans: s.basePlans?.length || 0,\n listings: s.listings ? s.listings.length : 0,\n firstBasePlanState: s.basePlans?.[0]?.state || \"-\",\n }));\n await maybePaginate(formatOutput(summary, format));\n const footer = moreResultsFooter(result.nextPageToken);\n if (footer) console.log(footer);\n } else {\n await maybePaginate(\n formatOutput(\n annotateListResult(\n { ...result, subscriptions: subs },\n \"subscriptions\",\n \"No subscriptions found\",\n ),\n format,\n ),\n );\n }\n });\n\n subs\n .command(\"get <product-id>\")\n .description(\"Get a subscription\")\n .action(async (productId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await getSubscription(client, packageName, productId);\n if (format !== \"json\") {\n const s = result as unknown as Record<string, unknown>;\n const basePlans = s[\"basePlans\"] as Array<Record<string, unknown>> | undefined;\n const listings = s[\"listings\"] as\n | Record<string, unknown>\n | Array<Record<string, unknown>>\n | undefined;\n const listingLanguages = listings\n ? Array.isArray(listings)\n ? listings.map((l) => l[\"languageCode\"] || l[\"language\"] || \"?\").join(\", \")\n : Object.keys(listings).join(\", \")\n : \"-\";\n const listingCount = listings\n ? Array.isArray(listings)\n ? listings.length\n : Object.keys(listings).length\n : 0;\n const summary = {\n productId: s[\"productId\"],\n basePlans: basePlans?.length || 0,\n basePlanIds: basePlans?.map((bp) => bp[\"basePlanId\"]).join(\", \") || \"-\",\n listings: listingCount,\n listingLanguages,\n taxCategory: (s[\"taxAndComplianceSettings\"] as Record<string, unknown>)?.[\n \"taxRateInfoByRegionCode\"\n ]\n ? \"configured\"\n : \"-\",\n };\n console.log(formatOutput(summary, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n subs\n .command(\"create\")\n .description(\"Create a subscription from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with subscription data\")\n .option(\"--activate\", \"Activate all base plans after creation\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"subscriptions create\",\n action: \"create\",\n target: `subscription from ${options.file}`,\n details: options.activate ? { activate: true } : undefined,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const data = await readJsonFile(options.file);\n const result = await createSubscription(client, packageName, data as Subscription);\n\n if (options.activate && result.basePlans) {\n for (const bp of result.basePlans) {\n if (bp.state === \"DRAFT\") {\n await activateBasePlan(client, packageName, result.productId, bp.basePlanId);\n console.error(`Activated base plan: ${bp.basePlanId}`);\n }\n }\n // Re-fetch to get updated state\n const updated = await getSubscription(client, packageName, result.productId);\n console.log(formatOutput(updated, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n subs\n .command(\"update <product-id>\")\n .description(\"Update a subscription from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with subscription data\")\n .option(\"--update-mask <fields>\", \"Comma-separated field mask\")\n .action(async (productId: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"subscriptions update\",\n action: \"update\",\n target: productId,\n details: { file: options.file, updateMask: options.updateMask },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const data = await readJsonFile(options.file);\n const result = await updateSubscription(\n client,\n packageName,\n productId,\n data as Subscription,\n options.updateMask,\n );\n console.log(formatOutput(result, format));\n });\n\n subs\n .command(\"delete <product-id>\")\n .description(\"Delete a subscription\")\n .action(async (productId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Delete subscription \"${productId}\"?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"subscriptions delete\",\n action: \"delete\",\n target: productId,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await deleteSubscription(client, packageName, productId);\n console.log(`Subscription ${productId} deleted.`);\n });\n\n // --- Base Plans ---\n const basePlans = subs.command(\"base-plans\").description(\"Manage base plans\");\n\n basePlans\n .command(\"activate <product-id> <base-plan-id>\")\n .description(\"Activate a base plan\")\n .action(async (productId: string, basePlanId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"subscriptions base-plans activate\",\n action: \"activate\",\n target: `${productId}/${basePlanId}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await activateBasePlan(client, packageName, productId, basePlanId);\n console.log(formatOutput(result, format));\n });\n\n basePlans\n .command(\"deactivate <product-id> <base-plan-id>\")\n .description(\"Deactivate a base plan\")\n .action(async (productId: string, basePlanId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"subscriptions base-plans deactivate\",\n action: \"deactivate\",\n target: `${productId}/${basePlanId}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await deactivateBasePlan(client, packageName, productId, basePlanId);\n console.log(formatOutput(result, format));\n });\n\n basePlans\n .command(\"delete <product-id> <base-plan-id>\")\n .description(\"Delete a base plan\")\n .action(async (productId: string, basePlanId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(\n `Delete base plan \"${basePlanId}\" from subscription \"${productId}\"?`,\n program,\n );\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"subscriptions base-plans delete\",\n action: \"delete\",\n target: `${productId}/${basePlanId}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await deleteBasePlan(client, packageName, productId, basePlanId);\n console.log(`Base plan ${basePlanId} deleted.`);\n });\n\n basePlans\n .command(\"migrate-prices <product-id> <base-plan-id>\")\n .description(\"Migrate base plan prices\")\n .requiredOption(\"--file <path>\", \"JSON file with migration data\")\n .action(\n async (\n productId: string,\n basePlanId: string,\n options: { file: string; updateMask?: string },\n ) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"subscriptions base-plans migrate-prices\",\n action: \"migrate prices for\",\n target: `${productId}/${basePlanId}`,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const data = await readJsonFile(options.file);\n await migratePrices(\n client,\n packageName,\n productId,\n basePlanId,\n data as BasePlanMigratePricesRequest,\n );\n console.log(formatOutput({ success: true }, format));\n },\n );\n\n // --- Offers ---\n const offers = subs.command(\"offers\").description(\"Manage subscription offers\");\n\n offers\n .command(\"list <product-id> <base-plan-id>\")\n .description(\"List offers for a base plan\")\n .action(async (productId: string, basePlanId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listOffers(client, packageName, productId, basePlanId);\n const offers_list = (result as unknown as Record<string, unknown>)[\"subscriptionOffers\"] as\n | Array<Record<string, unknown>>\n | undefined;\n if (format !== \"json\") {\n if (!offers_list || offers_list.length === 0) {\n console.log(\"No offers found.\");\n return;\n }\n const summary = offers_list.map((o) => ({\n offerId: o[\"offerId\"],\n basePlanId: o[\"basePlanId\"],\n state: o[\"state\"] || \"-\",\n phases: (o[\"phases\"] as unknown[])?.length || 0,\n regionalConfigs: (o[\"regionalConfigs\"] as unknown[])?.length || 0,\n }));\n console.log(formatOutput(summary, format));\n } else {\n console.log(formatOutput(result, format));\n }\n });\n\n offers\n .command(\"get <product-id> <base-plan-id> <offer-id>\")\n .description(\"Get an offer\")\n .action(async (productId: string, basePlanId: string, offerId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await getOffer(client, packageName, productId, basePlanId, offerId);\n console.log(formatOutput(result, format));\n });\n\n offers\n .command(\"create <product-id> <base-plan-id>\")\n .description(\"Create an offer from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with offer data\")\n .action(\n async (\n productId: string,\n basePlanId: string,\n options: { file: string; updateMask?: string },\n ) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"subscriptions offers create\",\n action: \"create offer for\",\n target: `${productId}/${basePlanId}`,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const data = await readJsonFile(options.file);\n const result = await createOffer(\n client,\n packageName,\n productId,\n basePlanId,\n data as SubscriptionOffer,\n );\n console.log(formatOutput(result, format));\n },\n );\n\n offers\n .command(\"update <product-id> <base-plan-id> <offer-id>\")\n .description(\"Update an offer from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with offer data\")\n .option(\"--update-mask <fields>\", \"Comma-separated field mask\")\n .action(\n async (\n productId: string,\n basePlanId: string,\n offerId: string,\n options: { file: string; updateMask?: string },\n ) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"subscriptions offers update\",\n action: \"update offer\",\n target: `${productId}/${basePlanId}/${offerId}`,\n details: { file: options.file, updateMask: options.updateMask },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const data = await readJsonFile(options.file);\n const result = await updateOffer(\n client,\n packageName,\n productId,\n basePlanId,\n offerId,\n data as SubscriptionOffer,\n options.updateMask,\n );\n console.log(formatOutput(result, format));\n },\n );\n\n offers\n .command(\"delete <product-id> <base-plan-id> <offer-id>\")\n .description(\"Delete an offer\")\n .action(async (productId: string, basePlanId: string, offerId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Delete offer \"${offerId}\"?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"subscriptions offers delete\",\n action: \"delete offer\",\n target: `${productId}/${basePlanId}/${offerId}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await deleteOffer(client, packageName, productId, basePlanId, offerId);\n console.log(`Offer ${offerId} deleted.`);\n });\n\n offers\n .command(\"activate <product-id> <base-plan-id> <offer-id>\")\n .description(\"Activate an offer\")\n .action(async (productId: string, basePlanId: string, offerId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"subscriptions offers activate\",\n action: \"activate offer\",\n target: `${productId}/${basePlanId}/${offerId}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await activateOffer(client, packageName, productId, basePlanId, offerId);\n console.log(formatOutput(result, format));\n });\n\n offers\n .command(\"deactivate <product-id> <base-plan-id> <offer-id>\")\n .description(\"Deactivate an offer\")\n .action(async (productId: string, basePlanId: string, offerId: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"subscriptions offers deactivate\",\n action: \"deactivate offer\",\n target: `${productId}/${basePlanId}/${offerId}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await deactivateOffer(client, packageName, productId, basePlanId, offerId);\n console.log(formatOutput(result, format));\n });\n\n offers\n .command(\"batch-get <product-id> <base-plan-id>\")\n .description(\"Batch get multiple offers (max 100)\")\n .requiredOption(\"--ids <offer-ids>\", \"Comma-separated offer IDs\")\n .action(async (productId: string, basePlanId: string, options: { ids: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const offerIds = options.ids.split(\",\").map((id) => id.trim());\n const result = await client.subscriptions.batchGetOffers(\n packageName,\n productId,\n basePlanId,\n offerIds,\n );\n console.log(formatOutput(result, format));\n });\n\n offers\n .command(\"batch-update-states <product-id> <base-plan-id>\")\n .description(\"Batch activate or deactivate multiple offers (max 100)\")\n .requiredOption(\"--file <path>\", \"JSON file with state transition requests\")\n .action(async (productId: string, basePlanId: string, options: { file: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"subscriptions offers batch-update-states\",\n action: \"batch update offer states\",\n target: `${productId}/${basePlanId}`,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n const requests = await readJsonFile(options.file);\n const result = await client.subscriptions.batchUpdateOfferStates(\n packageName,\n productId,\n basePlanId,\n requests as {\n requests: Array<{\n activateSubscriptionOfferRequest?: { offerId: string };\n deactivateSubscriptionOfferRequest?: { offerId: string };\n }>;\n },\n );\n console.log(formatOutput(result, format));\n });\n\n // --- Diff ---\n subs\n .command(\"diff <product-id>\")\n .description(\"Compare local JSON file against remote subscription\")\n .requiredOption(\"--file <path>\", \"Local JSON file to compare against remote\")\n .action(async (productId: string, options: { file: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const localData = (await readJsonFile(options.file)) as Subscription;\n const diffs = await diffSubscription(client, packageName, productId, localData);\n if (diffs.length === 0) {\n console.log(\"No differences found.\");\n } else {\n console.log(formatOutput(diffs, format));\n }\n });\n\n subs\n .command(\"analytics\")\n .description(\"Subscription catalog analytics: active plans, offer counts, state breakdown\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await getSubscriptionAnalytics(client, packageName);\n\n if (format === \"json\") {\n console.log(formatOutput(result, format));\n return;\n }\n\n console.log(`\\nSubscription Analytics — ${packageName}`);\n console.log(`${\"─\".repeat(50)}`);\n console.log(`Total subscriptions: ${result.totalSubscriptions}`);\n console.log(`Active subscriptions: ${result.activeCount}`);\n console.log(`Active base plans: ${result.activeBasePlans}`);\n console.log(`Draft base plans: ${result.trialBasePlans}`);\n console.log(`Inactive base plans: ${result.pausedBasePlans}`);\n console.log(`Total offers: ${result.offerCount}`);\n\n if (result.byProductId.length > 0) {\n console.log(`\\nBy product:`);\n console.log(formatOutput(result.byProductId, format));\n }\n });\n}\n"],"mappings":"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","names":["subs","basePlans"]}
@@ -80,7 +80,11 @@ function registerSystemApksCommands(program) {
80
80
  }
81
81
  const client = await getClient(config);
82
82
  const spec = await readJsonFile(options.file);
83
- const result = await client.systemApks.create(packageName, versionCode, spec);
83
+ const result = await client.systemApks.create(
84
+ packageName,
85
+ versionCode,
86
+ spec
87
+ );
84
88
  console.log(formatOutput(result, format));
85
89
  });
86
90
  cmd.command("download <version-code> <variant-id>").description("Download a system APK variant").requiredOption("--output <path>", "Output file path").action(async (versionCodeStr, variantIdStr, options) => {
@@ -108,4 +112,4 @@ function registerSystemApksCommands(program) {
108
112
  export {
109
113
  registerSystemApksCommands
110
114
  };
111
- //# sourceMappingURL=system-apks-ZKVZLJPY.js.map
115
+ //# sourceMappingURL=system-apks-6PTB7LLD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/system-apks.ts"],"sourcesContent":["import { resolvePackageName, getClient } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport type { SystemApkVariant } from \"@gpc-cli/api\";\nimport { formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { readJsonFile } from \"../json.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { writeFile, access } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nfunction parsePositiveInt(str: string, label: string): number {\n const n = parseInt(str, 10);\n if (isNaN(n) || n <= 0) {\n const err = new Error(`${label} must be a positive number`);\n Object.assign(err, { code: \"USAGE_ERROR\", exitCode: 2 });\n throw err;\n }\n return n;\n}\n\nexport function registerSystemApksCommands(program: Command): void {\n const cmd = program.command(\"system-apks\").description(\"Manage system APKs for OEM pre-installs\");\n\n cmd\n .command(\"list <version-code>\")\n .description(\"List system APK variants for a version code\")\n .action(async (versionCodeStr: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n const versionCode = parsePositiveInt(versionCodeStr, \"version-code\");\n\n const result = await client.systemApks.list(packageName, versionCode);\n const variants = result.variants || [];\n if (variants.length === 0) {\n console.log(\"No system APK variants found.\");\n } else {\n console.log(formatOutput(variants, format));\n }\n });\n\n cmd\n .command(\"get <version-code> <variant-id>\")\n .description(\"Get a system APK variant\")\n .action(async (versionCodeStr: string, variantIdStr: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n const versionCode = parsePositiveInt(versionCodeStr, \"version-code\");\n const variantId = parsePositiveInt(variantIdStr, \"variant-id\");\n\n const result = await client.systemApks.get(packageName, versionCode, variantId);\n console.log(formatOutput(result, format));\n });\n\n cmd\n .command(\"create <version-code>\")\n .description(\"Create a system APK variant from a device spec JSON file\")\n .requiredOption(\n \"--file <path>\",\n \"JSON file with device spec (supportedAbis, supportedLocales, screenDensity)\",\n )\n .action(async (versionCodeStr: string, options: { file: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n const versionCode = parsePositiveInt(versionCodeStr, \"version-code\");\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"system-apks create\",\n action: \"create system APK variant\",\n target: `v${versionCode}`,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n const spec = await readJsonFile(options.file);\n const result = await client.systemApks.create(\n packageName,\n versionCode,\n spec as SystemApkVariant,\n );\n console.log(formatOutput(result, format));\n });\n\n cmd\n .command(\"download <version-code> <variant-id>\")\n .description(\"Download a system APK variant\")\n .requiredOption(\"--output <path>\", \"Output file path\")\n .action(async (versionCodeStr: string, variantIdStr: string, options: { output: string }) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const versionCode = parsePositiveInt(versionCodeStr, \"version-code\");\n const variantId = parsePositiveInt(variantIdStr, \"variant-id\");\n\n const outputPath = resolve(options.output);\n if (outputPath.includes(\"\\0\")) {\n const err = new Error(\"Output path contains null bytes\");\n Object.assign(err, { code: \"USAGE_ERROR\", exitCode: 2 });\n throw err;\n }\n try {\n await access(outputPath);\n // File exists -- require confirmation\n await requireConfirm(`File \"${outputPath}\" already exists. Overwrite?`, program);\n } catch {\n // File does not exist -- safe to write\n }\n\n const client = await getClient(config);\n const data = await client.systemApks.download(packageName, versionCode, variantId);\n await writeFile(outputPath, Buffer.from(data));\n console.log(`Downloaded to ${outputPath}`);\n });\n}\n"],"mappings":"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","names":[]}
@@ -17,7 +17,7 @@ function registerUpdateCommand(program) {
17
17
  program.command("update").description("Update gpc to the latest version").option("--check", "Check for updates without installing (exits 0 always)").option("--force", "Update even if already on the latest version").action(async (opts, cmd) => {
18
18
  const parentOpts = cmd.parent?.opts() ?? {};
19
19
  const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
20
- const currentVersion = "0.9.81";
20
+ const currentVersion = "0.9.83";
21
21
  if (currentVersion === "0.0.0") {
22
22
  if (jsonMode) {
23
23
  console.log(
@@ -172,4 +172,4 @@ Run: gpc update`);
172
172
  export {
173
173
  registerUpdateCommand
174
174
  };
175
- //# sourceMappingURL=update-TXLKZ6JD.js.map
175
+ //# sourceMappingURL=update-ROEAKMQD.js.map
@@ -24,6 +24,8 @@ import {
24
24
  PERMISSION_PROPAGATION_WARNING,
25
25
  formatOutput,
26
26
  sortResults,
27
+ annotateListResult,
28
+ moreResultsFooter,
27
29
  GpcError
28
30
  } from "@gpc-cli/core";
29
31
  function resolveDeveloperId(devIdArg, config) {
@@ -69,9 +71,11 @@ function registerUsersCommands(program) {
69
71
  permissions: Array.isArray(u["developerAccountPermissions"]) ? u["developerAccountPermissions"].length : Array.isArray(u["developerAccountPermission"]) ? u["developerAccountPermission"].length : 0
70
72
  }));
71
73
  console.log(formatOutput(rows, format));
74
+ const footer = moreResultsFooter(result.nextPageToken);
75
+ if (footer) console.log(footer);
72
76
  }
73
77
  } else {
74
- console.log(formatOutput(result, format));
78
+ console.log(formatOutput(annotateListResult(result, "users", "No users found"), format));
75
79
  }
76
80
  });
77
81
  users.command("get <email>").description("Get user details").action(async (email) => {
@@ -162,4 +166,4 @@ function registerUsersCommands(program) {
162
166
  export {
163
167
  registerUsersCommands
164
168
  };
165
- //# sourceMappingURL=users-HJAXLZPM.js.map
169
+ //# sourceMappingURL=users-EKXLDY2Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/users.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport type { GpcConfig } from \"@gpc-cli/config\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createUsersClient } from \"@gpc-cli/api\";\nimport type { DeveloperPermission } from \"@gpc-cli/api\";\nimport {\n listUsers,\n getUser,\n inviteUser,\n updateUser,\n removeUser,\n parseGrantArg,\n PERMISSION_PROPAGATION_WARNING,\n formatOutput,\n sortResults,\n annotateListResult,\n moreResultsFooter,\n GpcError,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\n\nfunction resolveDeveloperId(devIdArg: string | undefined, config: GpcConfig): string {\n const id = devIdArg || config.developerId;\n if (!id) {\n throw new GpcError(\n \"No developer ID. Use --developer-id <id> or gpc config set developerId <id>\",\n \"MISSING_DEVELOPER_ID\",\n 2,\n \"gpc config set developerId <id>\",\n );\n }\n return id;\n}\n\nasync function getUsersClient(config: GpcConfig) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createUsersClient({ auth });\n}\n\nexport function registerUsersCommands(program: Command): void {\n const users = program\n .command(\"users\")\n .description(\"Manage developer account users and permissions\")\n .option(\"--developer-id <id>\", \"Developer account ID\");\n\n users\n .command(\"list\")\n .description(\"List all users in the developer account\")\n .option(\"--limit <n>\", \"Maximum total results\", parseInt)\n .option(\"--next-page <token>\", \"Resume from page token\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending)\")\n .action(async (options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(users.opts()[\"developerId\"], config);\n const client = await getUsersClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await listUsers(client, developerId, {\n limit: options.limit,\n nextPage: options.nextPage,\n });\n if (options.sort) {\n result.users = sortResults(result.users, options.sort);\n }\n if (format !== \"json\") {\n const users = (result.users || []) as unknown as Record<string, unknown>[];\n if (users.length === 0) {\n console.log(\"No users found.\");\n } else {\n const rows = users.map((u) => ({\n email: u[\"email\"] || \"-\",\n name: u[\"name\"] || \"-\",\n accessState: u[\"accessState\"] || \"-\",\n grants: Array.isArray(u[\"grants\"]) ? (u[\"grants\"] as unknown[]).length : 0,\n permissions: Array.isArray(u[\"developerAccountPermissions\"])\n ? (u[\"developerAccountPermissions\"] as unknown[]).length\n : Array.isArray(u[\"developerAccountPermission\"])\n ? (u[\"developerAccountPermission\"] as unknown[]).length\n : 0,\n }));\n console.log(formatOutput(rows, format));\n const footer = moreResultsFooter(result.nextPageToken);\n if (footer) console.log(footer);\n }\n } else {\n console.log(formatOutput(annotateListResult(result, \"users\", \"No users found\"), format));\n }\n });\n\n users\n .command(\"get <email>\")\n .description(\"Get user details\")\n .action(async (email: string) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(users.opts()[\"developerId\"], config);\n const client = await getUsersClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await getUser(client, developerId, email);\n console.log(formatOutput(result, format));\n });\n\n users\n .command(\"invite <email>\")\n .description(\"Invite a user to the developer account\")\n .option(\"--role <permissions...>\", \"Developer-level permissions\")\n .option(\n \"--grant <grants...>\",\n \"Per-app grants (format: com.example.app:PERMISSION1,PERMISSION2)\",\n )\n .action(async (email: string, options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(users.opts()[\"developerId\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"users invite\",\n action: \"invite\",\n target: email,\n details: { role: options.role, grant: options.grant },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getUsersClient(config);\n\n const permissions = options.role as DeveloperPermission[] | undefined;\n const grants = options.grant?.map((g: string) => parseGrantArg(g));\n const result = await inviteUser(client, developerId, email, permissions, grants);\n console.log(formatOutput(result, format));\n console.error(PERMISSION_PROPAGATION_WARNING);\n });\n\n users\n .command(\"update <email>\")\n .description(\"Update user permissions\")\n .option(\"--role <permissions...>\", \"Developer-level permissions\")\n .option(\n \"--grant <grants...>\",\n \"Per-app grants (format: com.example.app:PERMISSION1,PERMISSION2)\",\n )\n .action(async (email: string, options) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(users.opts()[\"developerId\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"users update\",\n action: \"update\",\n target: email,\n details: { role: options.role, grant: options.grant },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getUsersClient(config);\n\n const permissions = options.role as DeveloperPermission[] | undefined;\n const grants = options.grant?.map((g: string) => parseGrantArg(g));\n const result = await updateUser(client, developerId, email, permissions, grants);\n console.log(formatOutput(result, format));\n console.error(PERMISSION_PROPAGATION_WARNING);\n });\n\n users\n .command(\"remove <email>\")\n .description(\"Remove a user from the developer account\")\n .action(async (email: string) => {\n const config = await loadConfig();\n const developerId = resolveDeveloperId(users.opts()[\"developerId\"], config);\n\n await requireConfirm(`Remove user \"${email}\" from developer account?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"users remove\",\n action: \"remove\",\n target: email,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getUsersClient(config);\n\n await removeUser(client, developerId, email);\n console.log(`User ${email} removed.`);\n console.error(PERMISSION_PROPAGATION_WARNING);\n });\n}\n"],"mappings":"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","names":["users"]}
@@ -7,7 +7,7 @@ import "./chunk-3SJ6OXCZ.js";
7
7
  // src/commands/version.ts
8
8
  function registerVersionCommand(program) {
9
9
  program.command("version").description("Show version information").action(() => {
10
- const version = "0.9.81";
10
+ const version = "0.9.83";
11
11
  if (program.opts()["output"] === "json") {
12
12
  console.log(
13
13
  JSON.stringify({
@@ -25,4 +25,4 @@ function registerVersionCommand(program) {
25
25
  export {
26
26
  registerVersionCommand
27
27
  };
28
- //# sourceMappingURL=version-BHRQPXO6.js.map
28
+ //# sourceMappingURL=version-X3RJKLJW.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gpc-cli/cli",
3
- "version": "0.9.81",
3
+ "version": "0.9.83",
4
4
  "description": "GPC — Google Play Console CLI. 217 API endpoints including Managed Google Play. Upload AABs, manage releases, monitor vitals, publish private enterprise apps. Fastlane alternative for Android.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/changelog.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport {\n fetchChangelog,\n formatChangelogEntry,\n formatOutput,\n generateChangelog,\n RENDERERS,\n renderPlayStore,\n renderPlayStoreMd,\n renderPlayStorePrompt,\n buildLocaleBundle,\n translateBundle,\n resolveAiConfig,\n createTranslator,\n fetchAggregateCost,\n formatPathLabel,\n PROVIDER_WHITELIST,\n resolveLocales,\n validateBundleForApply,\n bundleToReleaseNotes,\n applyReleaseNotes,\n GpcError,\n type OutputMode,\n type PlayStoreFormat,\n} from \"@gpc-cli/core\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { getOutputFormat } from \"../format.js\";\nimport { yellow, dim } from \"../colors.js\";\nimport { resolvePackageName, getClient } from \"../resolve.js\";\n\nconst VALID_OUTPUT_MODES: OutputMode[] = [\"md\", \"json\", \"prompt\"];\nconst VALID_TARGETS = [\"github\", \"play-store\"] as const;\ntype ChangelogTarget = (typeof VALID_TARGETS)[number];\nconst REPO_RE = /^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+$/;\n\ninterface ApplyContext {\n bundle: Parameters<typeof validateBundleForApply>[0];\n program: Command;\n track: string;\n dryRun: boolean;\n aiBlock?: Record<string, unknown>;\n}\n\nasync function performApply(ctx: ApplyContext): Promise<boolean> {\n const blocked = validateBundleForApply(ctx.bundle);\n if (blocked.length > 0) {\n process.stderr.write(\n `Cannot --apply: ${blocked.length} locale(s) blocked:\\n` +\n blocked.map((b) => ` ${b}`).join(\"\\n\") +\n \"\\n\",\n );\n process.exitCode = 1;\n return false;\n }\n const notes = bundleToReleaseNotes(ctx.bundle);\n const config = await loadConfig();\n const packageName = resolvePackageName(ctx.program.opts()[\"app\"], config);\n if (ctx.dryRun) {\n const payload: Record<string, unknown> = {\n dryRun: true,\n action: \"apply release notes\",\n track: ctx.track,\n packageName,\n localeCount: notes.length,\n releaseNotes: notes,\n };\n if (ctx.aiBlock) payload[\"ai\"] = ctx.aiBlock;\n console.log(JSON.stringify(payload, null, 2));\n return false;\n }\n const client = await getClient(config);\n const result = await applyReleaseNotes(client, packageName, ctx.track, notes);\n process.stderr.write(\n `${dim(`→ Applied ${result.localeCount} locale(s) to draft on ${result.track} (${packageName})`)}\\n`,\n );\n return true;\n}\n\nexport function registerChangelogCommand(program: Command): void {\n const changelog = program\n .command(\"changelog\")\n .description(\"Show release history\")\n .option(\"-n, --limit <count>\", \"Number of releases to show\", parseInt, 5)\n .option(\"--tag <tag>\", \"Show a specific release (e.g., v0.9.43)\")\n .option(\"--all\", \"Show all releases\")\n .action(async (opts: { limit: number; tag?: string; all?: boolean }) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n\n const entries = await fetchChangelog({\n limit: opts.all ? 100 : opts.limit,\n version: opts.tag,\n });\n\n if (entries.length === 0) {\n console.log(\"No releases found.\");\n return;\n }\n\n if (format === \"json\") {\n console.log(formatOutput(entries, \"json\"));\n return;\n }\n\n if (opts.tag || entries.length === 1) {\n console.log(formatChangelogEntry(entries[0]!));\n return;\n }\n\n const header = \"VERSION DATE TITLE\";\n const separator = \"─\".repeat(header.length);\n console.log(header);\n console.log(separator);\n for (const entry of entries) {\n const version = entry.version.padEnd(12);\n const date = entry.date.padEnd(12);\n console.log(`${version} ${date} ${entry.title}`);\n }\n console.log(\"\");\n console.log(\n `Showing ${entries.length} releases. Use --tag <tag> for details, or --all for full history.`,\n );\n });\n\n changelog\n .command(\"generate\")\n .description(\"Generate release notes from local git commits\")\n .option(\"--from <ref>\", \"Starting ref (default: latest v* tag)\")\n .option(\"--to <ref>\", \"Ending ref (default: HEAD)\")\n .option(\"--format <mode>\", \"Renderer: md, json, or prompt\", \"md\")\n .option(\"--repo <owner/name>\", \"Override auto-detected repo (e.g., yasserstudio/gpc)\")\n .option(\"--target <mode>\", \"Output target: github or play-store\", \"github\")\n .option(\n \"--locales <csv|auto>\",\n \"Comma-separated BCP 47 locales, or 'auto' (play-store target only)\",\n )\n .option(\"--ai\", \"Translate non-source locales via LLM (play-store target only, BYO key)\")\n .option(\n \"--provider <name>\",\n `AI provider (${PROVIDER_WHITELIST.join(\"|\")}). Defaults to first env key detected`,\n )\n .option(\"--model <id>\", \"Override default model for the chosen provider\")\n .option(\"--strict\", \"Exit non-zero if warnings, overflows, or translation failures occur\")\n .option(\"--apply\", \"Write notes into the draft release on --track (play-store target only)\")\n .option(\"--track <name>\", \"Play Store track for --apply (default: production)\", \"production\")\n .action(\n async (opts: {\n from?: string;\n to?: string;\n format: string;\n repo?: string;\n target: string;\n locales?: string;\n strict?: boolean;\n ai?: boolean;\n provider?: string;\n model?: string;\n apply?: boolean;\n track: string;\n }) => {\n const dryRun = !!program.opts()[\"dryRun\"];\n const mode = opts.format as OutputMode;\n if (!VALID_OUTPUT_MODES.includes(mode)) {\n process.stderr.write(\n `Invalid --format \"${opts.format}\". Valid: ${VALID_OUTPUT_MODES.join(\", \")}\\n`,\n );\n process.exitCode = 2;\n return;\n }\n if (!VALID_TARGETS.includes(opts.target as ChangelogTarget)) {\n process.stderr.write(\n `Invalid --target \"${opts.target}\". Valid: ${VALID_TARGETS.join(\", \")}\\n`,\n );\n process.exitCode = 2;\n return;\n }\n const target = opts.target as ChangelogTarget;\n if (opts.repo && !REPO_RE.test(opts.repo)) {\n process.stderr.write(\n `Invalid --repo \"${opts.repo}\". Expected \"owner/name\" (e.g., yasserstudio/gpc).\\n`,\n );\n process.exitCode = 2;\n return;\n }\n if (target === \"github\" && opts.locales) {\n process.stderr.write(\n `--locales only applies to --target play-store (current target: github)\\n`,\n );\n process.exitCode = 2;\n return;\n }\n // Only block when the AI-adjacent flags are explicitly set. The root\n // program has its own `--dry-run` flag that may already be set\n // globally by the user for unrelated reasons; we silently ignore it\n // on non-AI code paths.\n if (target === \"github\" && (opts.ai || opts.provider || opts.model)) {\n process.stderr.write(\"--ai / --provider / --model only apply to --target play-store\\n\");\n process.exitCode = 2;\n return;\n }\n // --format prompt + --ai is nonsensical outside --dry-run: it would\n // render a \"please translate this\" prompt from already-translated\n // text. Either inspect the prompt via --dry-run, or pick md/json.\n if (opts.ai && opts.format === \"prompt\" && !dryRun) {\n process.stderr.write(\n \"--ai with --format prompt only makes sense with --dry-run\\n\" +\n \" (otherwise it would re-wrap translated text in a translation prompt).\\n\" +\n \" Hint: use --format md or --format json for live translation, or add --dry-run to inspect the prompt.\\n\",\n );\n process.exitCode = 2;\n return;\n }\n if (opts.apply && target !== \"play-store\") {\n process.stderr.write(\"--apply only applies to --target play-store\\n\");\n process.exitCode = 2;\n return;\n }\n if (opts.apply && mode === \"prompt\") {\n process.stderr.write(\n \"--apply cannot be combined with --format prompt\\n\" +\n \" Hint: use --format md or --format json.\\n\",\n );\n process.exitCode = 2;\n return;\n }\n if (target === \"play-store\" && !opts.locales) {\n process.stderr.write(\n \"--target play-store requires --locales <csv|auto>\\n\" +\n \" Example: --locales en-US,fr-FR,de-DE\\n\" +\n \" Example: --locales auto (reads current Play Store listing — requires --app)\\n\",\n );\n process.exitCode = 2;\n return;\n }\n\n const generated = await generateChangelog({\n from: opts.from,\n to: opts.to,\n repo: opts.repo,\n });\n\n for (const w of generated.warnings) {\n process.stderr.write(`${yellow(\"warn:\")} ${w}\\n`);\n }\n if (generated.warnings.length > 0) {\n process.stderr.write(\n `${dim(`(${generated.warnings.length} warning${generated.warnings.length === 1 ? \"\" : \"s\"} — review before publishing)`)}\\n`,\n );\n }\n\n if (target === \"github\") {\n const output = RENDERERS[mode](generated);\n console.log(output);\n if (opts.strict && generated.warnings.length > 0) {\n process.exitCode = 1;\n }\n return;\n }\n\n // target === \"play-store\"\n let locales: string[];\n try {\n if (opts.locales === \"auto\") {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n locales = await resolveLocales(\"auto\", { client, packageName });\n } else {\n locales = await resolveLocales(opts.locales!);\n }\n } catch (error) {\n if (error instanceof GpcError) {\n process.stderr.write(`${error.message}\\n`);\n if (error.suggestion) process.stderr.write(`${dim(error.suggestion)}\\n`);\n process.exitCode = error.exitCode;\n return;\n }\n throw error;\n }\n\n const playStoreFormat = mode as PlayStoreFormat;\n\n // Non-AI path: existing v0.9.62 behavior\n if (!opts.ai) {\n const { output, bundle } = renderPlayStore(generated, {\n locales,\n format: playStoreFormat,\n });\n console.log(output);\n\n for (const lang of bundle.overflows) {\n process.stderr.write(\n `${yellow(\"warn:\")} ${lang} exceeds ${bundle.limit} chars (truncated)\\n`,\n );\n }\n\n if (opts.apply) {\n const ok = await performApply({ bundle, program, track: opts.track, dryRun });\n if (!ok) return;\n }\n\n const hasOverflow = bundle.overflows.length > 0;\n const hasWarnings = generated.warnings.length > 0;\n if (opts.strict && (hasWarnings || hasOverflow)) {\n process.exitCode = 1;\n }\n return;\n }\n\n // --ai path: resolve config, translate, render with ai block\n let aiConfig;\n try {\n aiConfig = resolveAiConfig({ provider: opts.provider, model: opts.model });\n } catch (error) {\n if (error instanceof GpcError) {\n process.stderr.write(`${error.message}\\n`);\n if (error.suggestion) process.stderr.write(`${dim(error.suggestion)}\\n`);\n process.exitCode = error.exitCode;\n return;\n }\n throw error;\n }\n\n process.stderr.write(`${dim(`→ ${formatPathLabel(aiConfig)}`)}\\n`);\n\n const baseBundle = buildLocaleBundle(generated, {\n locales,\n format: playStoreFormat,\n });\n\n if (dryRun) {\n const preview = renderPlayStorePrompt(baseBundle, generated);\n console.log(preview);\n process.stderr.write(\n `${dim(\"(--dry-run: no API call was made; the prompt above is what would be sent per locale)\")}\\n`,\n );\n return;\n }\n\n const translator = await createTranslator(aiConfig);\n let translated;\n try {\n translated = await translateBundle(baseBundle, {\n translator,\n strict: opts.strict,\n onError: ({ language, reason }) => {\n process.stderr.write(\n `${yellow(\"warn:\")} ${language} translation failed: ${reason}\\n`,\n );\n },\n });\n } catch (error) {\n if (error instanceof GpcError) {\n process.stderr.write(`${error.message}\\n`);\n if (error.suggestion) process.stderr.write(`${dim(error.suggestion)}\\n`);\n process.exitCode = error.exitCode;\n return;\n }\n throw error;\n }\n\n const costUsd =\n aiConfig.path === \"gateway\" ? await fetchAggregateCost(aiConfig.runId) : undefined;\n\n const aiBlock: Record<string, unknown> = {\n path: aiConfig.path,\n provider: aiConfig.provider,\n model: aiConfig.model,\n tokensIn: translated.tokensIn,\n tokensOut: translated.tokensOut,\n };\n if (aiConfig.path === \"gateway\") {\n aiBlock[\"runId\"] = aiConfig.runId;\n if (typeof costUsd === \"number\") aiBlock[\"costUsd\"] = costUsd;\n }\n\n if (playStoreFormat === \"json\") {\n const payload = {\n from: translated.from,\n to: translated.to,\n limit: translated.limit,\n sourceLanguage: translated.sourceLanguage,\n ai: aiBlock,\n locales: translated.locales,\n overflows: translated.overflows,\n failures: translated.failures,\n };\n console.log(JSON.stringify(payload, null, 2));\n } else if (playStoreFormat === \"prompt\") {\n console.log(renderPlayStorePrompt(translated, generated));\n } else {\n console.log(renderPlayStoreMd(translated));\n }\n\n for (const lang of translated.overflows) {\n process.stderr.write(\n `${yellow(\"warn:\")} ${lang} exceeds ${translated.limit} chars (truncated)\\n`,\n );\n }\n\n if (translated.failures.length > 0) {\n process.stderr.write(\n `${dim(`(${translated.failures.length} locale${translated.failures.length === 1 ? \"\" : \"s\"} failed — see placeholders in output)`)}\\n`,\n );\n }\n\n if (typeof costUsd === \"number\") {\n process.stderr.write(`${dim(`(run cost: $${costUsd.toFixed(4)})`)}\\n`);\n }\n\n if (opts.apply) {\n const ok = await performApply({\n bundle: translated,\n program,\n track: opts.track,\n dryRun,\n aiBlock,\n });\n if (!ok) return;\n }\n\n const hasOverflow = translated.overflows.length > 0;\n const hasWarnings = generated.warnings.length > 0;\n const hasFailures = translated.failures.length > 0;\n if (opts.strict && (hasWarnings || hasOverflow || hasFailures)) {\n process.exitCode = 1;\n }\n },\n );\n}\n"],"mappings":"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","names":["hasOverflow","hasWarnings"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/docs.ts","../src/docs-renderer.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport * as cp from \"node:child_process\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { renderMarkdown, formatSearchResult } from \"../docs-renderer.js\";\nimport { bold, dim } from \"../colors.js\";\nimport { getOutputFormat } from \"../format.js\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { formatOutput, GpcError } from \"@gpc-cli/core\";\nimport type { DocPage, DocsBundle } from \"../generated/docs-types.js\";\n\nlet _bundle: DocsBundle | undefined;\nlet _pageMap: Map<string, DocPage> | undefined;\n\nfunction getBundle(): DocsBundle {\n if (!_bundle) {\n const moduleDir = dirname(fileURLToPath(import.meta.url));\n // Works from src/commands/ (dev/test) and dist/ (built output)\n const candidates = [\n join(moduleDir, \"..\", \"generated\", \"docs-bundle.json\"),\n join(moduleDir, \"generated\", \"docs-bundle.json\"),\n ];\n const bundlePath = candidates.find((p) => existsSync(p));\n if (!bundlePath) {\n throw new GpcError(\n \"Embedded docs bundle not found. Run the build first.\",\n \"DOCS_BUNDLE_MISSING\",\n 1,\n \"Run: pnpm build --filter @gpc-cli/cli\",\n );\n }\n _bundle = JSON.parse(readFileSync(bundlePath, \"utf-8\")) as DocsBundle;\n }\n return _bundle;\n}\n\nfunction getPageMap(): Map<string, DocPage> {\n if (!_pageMap) {\n const bundle = getBundle();\n _pageMap = new Map<string, DocPage>();\n for (const page of bundle.pages) {\n _pageMap.set(page.slug, page);\n }\n }\n return _pageMap;\n}\n\nfunction fuzzyMatch(query: string, pages: DocPage[]): DocPage | undefined {\n const q = query.toLowerCase();\n // Exact full slug match (e.g., \"guide/authentication\")\n const exact = pages.find((p) => p.slug === q);\n if (exact) return exact;\n // Match on the filename part (e.g., \"authentication\" matches \"guide/authentication\")\n const byName = pages.find((p) => p.slug.endsWith(`/${q}`));\n if (byName) return byName;\n // Prefix match on filename part\n const prefix = pages.find((p) => {\n const name = p.slug.split(\"/\").pop() || \"\";\n return name.startsWith(q);\n });\n if (prefix) return prefix;\n // Contains match anywhere in slug\n const contains = pages.find((p) => p.slug.includes(q));\n if (contains) return contains;\n // Title match\n const titleMatch = pages.find((p) => p.title.toLowerCase().includes(q));\n if (titleMatch) return titleMatch;\n return undefined;\n}\n\nfunction searchPages(\n query: string,\n bundle: DocsBundle,\n): { page: DocPage; score: number; snippet: string }[] {\n const words = query\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n\n if (words.length === 0) return [];\n\n const pageMap = getPageMap();\n const scores = new Map<string, number>();\n for (const word of words) {\n const entries = bundle.searchIndex[word];\n if (!entries) continue;\n for (const entry of entries) {\n scores.set(entry.slug, (scores.get(entry.slug) || 0) + entry.score);\n }\n }\n\n const results: { page: DocPage; score: number; snippet: string }[] = [];\n for (const [slug, score] of scores) {\n const page = pageMap.get(slug);\n if (!page) continue;\n const snippet = extractSnippet(page.content, words);\n results.push({ page, score, snippet });\n }\n\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, 15);\n}\n\nfunction extractSnippet(content: string, words: string[]): string {\n const lines = content.split(\"\\n\");\n for (let i = 0; i < lines.length; i++) {\n const lower = lines[i]!.toLowerCase();\n if (words.some((w) => lower.includes(w))) {\n const start = Math.max(0, i - 1);\n const end = Math.min(lines.length, i + 2);\n return lines.slice(start, end).join(\"\\n\");\n }\n }\n return lines.slice(0, 3).join(\"\\n\");\n}\n\nconst DOCS_BASE = \"https://yasserstudio.github.io/gpc/\";\n\nfunction openInBrowser(url: string): void {\n const platform = process.platform;\n if (platform === \"win32\") {\n cp.exec(`start \"\" \"${url}\"`, (error) => {\n if (error) console.log(`Open in your browser: ${url}`);\n });\n } else {\n const cmd = platform === \"darwin\" ? \"open\" : \"xdg-open\";\n cp.execFile(cmd, [url], (error) => {\n if (error) console.log(`Open in your browser: ${url}`);\n });\n }\n}\n\nexport function registerDocsCommand(program: Command): void {\n const docs = program\n .command(\"docs\")\n .description(\"Access embedded documentation (list, show, search, init, web)\");\n\n docs\n .command(\"list\")\n .description(\"List all available documentation topics\")\n .action(async () => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n const bundle = getBundle();\n\n if (format === \"json\") {\n const data = bundle.pages.map((p) => ({\n slug: p.slug,\n section: p.section,\n title: p.title,\n description: p.description,\n }));\n console.log(formatOutput(data, \"json\"));\n return;\n }\n\n const bySection = new Map<string, DocPage[]>();\n for (const page of bundle.pages) {\n if (!bySection.has(page.section)) bySection.set(page.section, []);\n bySection.get(page.section)!.push(page);\n }\n\n for (const [section, pages] of bySection) {\n console.log(bold(`\\n ${section.toUpperCase()}`));\n for (const page of pages) {\n const label = page.slug.padEnd(36);\n console.log(` ${label} ${dim(page.title || page.slug)}`);\n }\n }\n console.log(\"\");\n console.log(dim(` ${bundle.pageCount} topics. Use: gpc docs show <topic>`));\n });\n\n docs\n .command(\"show <topic>\")\n .description(\"Show a documentation page in the terminal\")\n .action(async (topic: string) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n const bundle = getBundle();\n\n const page = fuzzyMatch(topic, bundle.pages);\n if (!page) {\n const suggestions = bundle.pages\n .filter((p) => p.slug.includes(topic.toLowerCase().slice(0, 3)))\n .slice(0, 5)\n .map((p) => p.slug);\n\n throw new GpcError(\n `No documentation found for \"${topic}\"`,\n \"DOCS_NOT_FOUND\",\n 2,\n suggestions.length > 0\n ? `Did you mean: ${suggestions.join(\", \")}?\\nRun: gpc docs list`\n : \"Run: gpc docs list\",\n );\n }\n\n if (format === \"json\") {\n console.log(\n formatOutput(\n { slug: page.slug, section: page.section, title: page.title, content: page.content },\n \"json\",\n ),\n );\n return;\n }\n\n console.log(renderMarkdown(page.content));\n });\n\n docs\n .command(\"search <query>\")\n .description(\"Search documentation\")\n .action(async (query: string) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n const bundle = getBundle();\n\n const results = searchPages(query, bundle);\n\n if (results.length === 0) {\n console.log(dim(` No results for \"${query}\".`));\n console.log(dim(\" Try a different search term, or: gpc docs list\"));\n return;\n }\n\n if (format === \"json\") {\n const data = results.map((r) => ({\n slug: r.page.slug,\n section: r.page.section,\n title: r.page.title,\n score: r.score,\n }));\n console.log(formatOutput(data, \"json\"));\n return;\n }\n\n console.log(bold(`\\n Search results for \"${query}\"\\n`));\n for (const r of results) {\n console.log(\" \" + formatSearchResult(r.page.slug, r.page.title, r.snippet, r.score));\n console.log(\"\");\n }\n console.log(\n dim(\n ` ${results.length} result${results.length === 1 ? \"\" : \"s\"}. Use: gpc docs show <topic>`,\n ),\n );\n });\n\n docs\n .command(\"init\")\n .description(\"Create GPC.md quick-reference for AI agents in this directory\")\n .option(\"--force\", \"Overwrite existing GPC.md\")\n .option(\"--path <dir>\", \"Output directory\", \".\")\n .action(async (opts: { force?: boolean; path: string }) => {\n const outDir = opts.path;\n const outFile = join(outDir, \"GPC.md\");\n\n if (existsSync(outFile) && !opts.force) {\n throw new GpcError(\n `GPC.md already exists at ${outFile}`,\n \"DOCS_INIT_EXISTS\",\n 1,\n \"Use --force to overwrite.\",\n );\n }\n\n const bundle = getBundle();\n const content = generateQuickReference(bundle);\n await writeFile(outFile, content, \"utf-8\");\n console.log(`Created ${outFile} (${bundle.pageCount} topics indexed)`);\n\n for (const agentFile of [\"CLAUDE.md\", \"AGENTS.md\"]) {\n const agentPath = join(outDir, agentFile);\n if (existsSync(agentPath)) {\n const existing = await readFile(agentPath, \"utf-8\");\n if (!existing.includes(\"GPC.md\")) {\n const separator = existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n await writeFile(\n agentPath,\n existing + separator + \"See also: @GPC.md for GPC CLI reference.\\n\",\n \"utf-8\",\n );\n console.log(`Updated ${agentPath} (added @GPC.md reference)`);\n }\n }\n }\n });\n\n docs\n .command(\"web [topic]\")\n .description(\"Open documentation in browser\")\n .action((topic?: string) => {\n const bundle = getBundle();\n if (!topic) {\n openInBrowser(DOCS_BASE);\n return;\n }\n const page = fuzzyMatch(topic, bundle.pages);\n if (page) {\n openInBrowser(`${DOCS_BASE}${page.slug}`);\n } else {\n openInBrowser(DOCS_BASE);\n console.log(dim(`Topic \"${topic}\" not found. Opened docs home page.`));\n }\n });\n}\n\nfunction generateQuickReference(bundle: DocsBundle): string {\n const lines: string[] = [\n \"# GPC Quick Reference\",\n \"\",\n \"> Auto-generated by `gpc docs init`. See full docs: https://yasserstudio.github.io/gpc/\",\n \"\",\n \"## Commands\",\n \"\",\n ];\n\n const commandPages = bundle.pages\n .filter((p) => p.section === \"commands\")\n .sort((a, b) => a.slug.localeCompare(b.slug));\n\n for (const page of commandPages) {\n const desc = page.description || page.title;\n lines.push(`- **gpc ${page.slug}** -- ${desc}`);\n }\n\n lines.push(\"\", \"## Guides\", \"\");\n\n const guidePages = bundle.pages\n .filter((p) => p.section === \"guide\")\n .sort((a, b) => a.slug.localeCompare(b.slug));\n\n for (const page of guidePages) {\n lines.push(`- **${page.title || page.slug}** -- \\`gpc docs show ${page.slug}\\``);\n }\n\n lines.push(\n \"\",\n \"## Quick Workflows\",\n \"\",\n \"```bash\",\n \"# Upload and publish\",\n \"gpc publish app.aab\",\n \"\",\n \"# Check vitals before release\",\n \"gpc preflight app.aab\",\n \"\",\n \"# Generate changelog with AI translation\",\n \"gpc changelog generate --target play-store --locales auto --ai\",\n \"\",\n \"# Staged rollout\",\n \"gpc releases rollout --fraction 0.1 --app com.example.app\",\n \"```\",\n \"\",\n `*${bundle.pageCount} docs pages available offline via \\`gpc docs show <topic>\\`*`,\n \"\",\n );\n\n return lines.join(\"\\n\");\n}\n","import { bold, dim, yellow, green, gray } from \"./colors.js\";\n\nexport function renderMarkdown(content: string): string {\n const lines = content.split(\"\\n\");\n const out: string[] = [];\n\n let inCodeBlock = false;\n\n for (const line of lines) {\n if (line.startsWith(\"```\")) {\n inCodeBlock = !inCodeBlock;\n if (inCodeBlock) {\n out.push(dim(\" ┌─────────────────────────────────────\"));\n } else {\n out.push(dim(\" └─────────────────────────────────────\"));\n }\n continue;\n }\n\n if (inCodeBlock) {\n out.push(dim(` │ ${line}`));\n continue;\n }\n\n // Headers\n const h1 = line.match(/^# (.+)$/);\n if (h1) {\n out.push(\"\");\n out.push(bold(green(` ${h1[1]!}`)));\n out.push(green(\" \" + \"─\".repeat(h1[1]!.length)));\n out.push(\"\");\n continue;\n }\n const h2 = line.match(/^## (.+)$/);\n if (h2) {\n out.push(\"\");\n out.push(bold(yellow(` ${h2[1]}`)));\n out.push(\"\");\n continue;\n }\n const h3 = line.match(/^### (.+)$/);\n if (h3) {\n out.push(bold(` ${h3[1]}`));\n continue;\n }\n\n // Blockquotes (converted from ::: containers)\n if (line.startsWith(\"> \")) {\n out.push(dim(` │ ${renderInline(line.slice(2))}`));\n continue;\n }\n\n // Table rows\n if (line.startsWith(\"|\")) {\n if (line.match(/^\\|[\\s-|]+\\|$/)) {\n out.push(gray(\" \" + \"─\".repeat(Math.min(line.length, 60))));\n continue;\n }\n const cells = line\n .split(\"|\")\n .filter(Boolean)\n .map((c) => c.trim());\n out.push(\" \" + cells.join(\" \"));\n continue;\n }\n\n // List items\n if (line.match(/^\\s*[-*]\\s/)) {\n out.push(` ${renderInline(line)}`);\n continue;\n }\n\n // Numbered list items\n if (line.match(/^\\s*\\d+\\.\\s/)) {\n out.push(` ${renderInline(line)}`);\n continue;\n }\n\n // Regular text\n out.push(` ${renderInline(line)}`);\n }\n\n // Close unclosed code block gracefully\n if (inCodeBlock) {\n out.push(dim(\" └─────────────────────────────────────\"));\n }\n\n return out.join(\"\\n\");\n}\n\nfunction renderInline(text: string): string {\n let result = text.replace(/\\*\\*(.+?)\\*\\*/g, (_, t) => bold(t));\n result = result.replace(/`([^`]+)`/g, (_, t) => dim(t));\n result = result.replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n (_, label, url) => `${label} ${dim(`(${url})`)}`,\n );\n return result;\n}\n\nexport function formatSearchResult(\n slug: string,\n title: string,\n snippet: string,\n score: number,\n): string {\n const header = bold(slug) + dim(` (score: ${score})`);\n const titleLine = ` ${title}`;\n const snippetLines = snippet\n .split(\"\\n\")\n .slice(0, 3)\n .map((l) => gray(` ${l.trim()}`))\n .join(\"\\n\");\n return `${header}\\n${titleLine}\\n${snippetLines}`;\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/external-transactions.ts"],"sourcesContent":["import { resolvePackageName, getClient } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\n\nimport {\n createExternalTransaction,\n getExternalTransaction,\n refundExternalTransaction,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { readFileSync } from \"node:fs\";\n\nexport function registerExternalTransactionsCommands(program: Command): void {\n const extTxn = program\n .command(\"external-transactions\")\n .alias(\"ext-txn\")\n .description(\"Manage external transactions (alternative billing)\");\n\n extTxn\n .command(\"create\")\n .description(\"Create a new external transaction\")\n .requiredOption(\"--file <path>\", \"Path to JSON file with transaction data\")\n .requiredOption(\"--transaction-id <id>\", \"External transaction ID\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(readFileSync(options.file, \"utf-8\"));\n } catch (err) {\n const error = new Error(\n `Could not read transaction data from ${options.file}: ${err instanceof Error ? err.message : String(err)}`,\n );\n Object.assign(error, {\n code: \"INVALID_INPUT\",\n exitCode: 2,\n suggestion: \"Check the file path and ensure it contains valid JSON.\",\n });\n throw error;\n }\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"external-transactions create\",\n action: \"create external transaction\",\n target: packageName,\n details: data,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await createExternalTransaction(\n client,\n packageName,\n data as any,\n options.transactionId,\n );\n console.log(formatOutput(result, format));\n });\n\n extTxn\n .command(\"get <id>\")\n .description(\"Get an external transaction by ID\")\n .action(async (id: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n const result = await getExternalTransaction(client, packageName, id);\n console.log(formatOutput(result, format));\n });\n\n extTxn\n .command(\"refund <id>\")\n .description(\"Refund an external transaction\")\n .option(\"--full\", \"Full refund\")\n .option(\"--partial-amount <micros>\", \"Partial refund pre-tax amount in micros (e.g., 1990000)\")\n .option(\"--currency <code>\", \"Currency code for partial refund (e.g. USD)\")\n .action(async (id: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n const refundData: Record<string, unknown> = {};\n if (options.full) {\n refundData[\"fullRefund\"] = {};\n } else if (options.partialAmount) {\n refundData[\"partialRefund\"] = {\n refundPreTaxAmount: {\n priceMicros: options.partialAmount,\n currency: options.currency,\n },\n };\n } else {\n refundData[\"fullRefund\"] = {};\n }\n\n await requireConfirm(`Refund external transaction \"${id}\"?`, program);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"external-transactions refund\",\n action: \"refund external transaction\",\n target: id,\n details: refundData,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const result = await refundExternalTransaction(client, packageName, id, refundData);\n console.log(formatOutput(result, format));\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAEA,SAAS,kBAAkB;AAE3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIP,SAAS,oBAAoB;AAEtB,SAAS,qCAAqC,SAAwB;AAC3E,QAAM,SAAS,QACZ,QAAQ,uBAAuB,EAC/B,MAAM,SAAS,EACf,YAAY,oDAAoD;AAEnE,SACG,QAAQ,QAAQ,EAChB,YAAY,mCAAmC,EAC/C,eAAe,iBAAiB,yCAAyC,EACzE,eAAe,yBAAyB,yBAAyB,EACjE,OAAO,OAAO,YAAY;AACzB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,aAAa,QAAQ,MAAM,OAAO,CAAC;AAAA,IACvD,SAAS,KAAK;AACZ,YAAM,QAAQ,IAAI;AAAA,QAChB,wCAAwC,QAAQ,IAAI,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC3G;AACA,aAAO,OAAO,OAAO;AAAA,QACnB,MAAM;AAAA,QACN,UAAU;AAAA,QACV,YAAY;AAAA,MACd,CAAC;AACD,YAAM;AAAA,IACR;AAEA,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,SAAS;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV;AACA,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,SACG,QAAQ,UAAU,EAClB,YAAY,mCAAmC,EAC/C,OAAO,OAAO,OAAe;AAC5B,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,MAAM,UAAU,MAAM;AACrC,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,SAAS,MAAM,uBAAuB,QAAQ,aAAa,EAAE;AACnE,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AAEH,SACG,QAAQ,aAAa,EACrB,YAAY,gCAAgC,EAC5C,OAAO,UAAU,aAAa,EAC9B,OAAO,6BAA6B,yDAAyD,EAC7F,OAAO,qBAAqB,6CAA6C,EACzE,OAAO,OAAO,IAAY,YAAY;AACrC,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,UAAM,aAAsC,CAAC;AAC7C,QAAI,QAAQ,MAAM;AAChB,iBAAW,YAAY,IAAI,CAAC;AAAA,IAC9B,WAAW,QAAQ,eAAe;AAChC,iBAAW,eAAe,IAAI;AAAA,QAC5B,oBAAoB;AAAA,UAClB,aAAa,QAAQ;AAAA,UACrB,UAAU,QAAQ;AAAA,QACpB;AAAA,MACF;AAAA,IACF,OAAO;AACL,iBAAW,YAAY,IAAI,CAAC;AAAA,IAC9B;AAEA,UAAM,eAAe,gCAAgC,EAAE,MAAM,OAAO;AAEpE,QAAI,SAAS,OAAO,GAAG;AACrB;AAAA,QACE;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,SAAS;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,MAAM;AAErC,UAAM,SAAS,MAAM,0BAA0B,QAAQ,aAAa,IAAI,UAAU;AAClF,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,CAAC;AACL;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/iap.ts"],"sourcesContent":["import { resolvePackageName, getClient } from \"../resolve.js\";\nimport type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\n\nimport {\n listOneTimeProducts,\n getOneTimeProduct,\n createInAppProduct,\n updateInAppProduct,\n deleteInAppProduct,\n syncInAppProducts,\n formatOutput,\n sortResults,\n createSpinner,\n} from \"@gpc-cli/core\";\nimport { isDryRun, printDryRun } from \"../dry-run.js\";\nimport { getOutputFormat } from \"../format.js\";\nimport { requireConfirm } from \"../prompt.js\";\nimport { readJsonFile } from \"../json.js\";\n\nexport function registerIapCommands(program: Command): void {\n const iap = program\n .command(\"iap\")\n .description(\"Manage in-app products (uses one-time products API)\");\n\n iap\n .command(\"list\")\n .description(\"List in-app products\")\n .option(\"--max <n>\", \"Maximum results per page\", parseInt)\n .option(\"--limit <n>\", \"Maximum total results\", parseInt)\n .option(\"--next-page <token>\", \"Resume from page token\")\n .option(\"--sort <field>\", \"Sort by field (prefix with - for descending)\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n console.error(\n \"Note: Using oneTimeProducts API (inappproducts endpoint is deprecated, shutdown Aug 2027)\",\n );\n\n const result = await listOneTimeProducts(client, packageName);\n let products = result.oneTimeProducts || [];\n if (options.sort) {\n products = sortResults(products, options.sort);\n }\n console.log(formatOutput(products, format));\n });\n\n iap\n .command(\"get <sku>\")\n .description(\"Get an in-app product\")\n .action(async (sku: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n\n console.error(\n \"Note: Using oneTimeProducts API (inappproducts endpoint is deprecated, shutdown Aug 2027)\",\n );\n\n const result = await getOneTimeProduct(client, packageName, sku);\n console.log(formatOutput(result, format));\n });\n\n iap\n .command(\"create\")\n .description(\"Create an in-app product from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with product data\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"iap create\",\n action: \"create\",\n target: `in-app product from ${options.file}`,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const data = await readJsonFile(options.file);\n const result = await createInAppProduct(client, packageName, data as any);\n console.log(formatOutput(result, format));\n });\n\n iap\n .command(\"update <sku>\")\n .description(\"Update an in-app product from JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with product data\")\n .action(async (sku: string, options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (isDryRun(program)) {\n printDryRun(\n {\n command: \"iap update\",\n action: \"update\",\n target: sku,\n details: { file: options.file },\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n const data = await readJsonFile(options.file);\n const result = await updateInAppProduct(client, packageName, sku, data as any);\n console.log(formatOutput(result, format));\n });\n\n iap\n .command(\"delete <sku>\")\n .description(\"Delete an in-app product\")\n .action(async (sku: string) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n\n await requireConfirm(`Delete in-app product \"${sku}\"?`, program);\n\n if (isDryRun(program)) {\n const format = getOutputFormat(program, config);\n printDryRun(\n {\n command: \"iap delete\",\n action: \"delete\",\n target: sku,\n },\n format,\n formatOutput,\n );\n return;\n }\n\n const client = await getClient(config);\n\n await deleteInAppProduct(client, packageName, sku);\n console.log(`In-app product ${sku} deleted.`);\n });\n\n iap\n .command(\"sync\")\n .description(\"Sync in-app products from a directory of JSON files\")\n .requiredOption(\"--dir <path>\", \"Directory containing product JSON files\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const client = await getClient(config);\n const format = getOutputFormat(program, config);\n const dryRun = isDryRun(program);\n\n const spinner = createSpinner(\"Syncing in-app products...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const result = await syncInAppProducts(client, packageName, options.dir, {\n dryRun,\n });\n spinner.stop(\"Sync complete\");\n if (dryRun) {\n console.log(`[dry-run] Would create: ${result.created}, update: ${result.updated}`);\n }\n console.log(formatOutput(result, format));\n } catch (error) {\n spinner.fail(\"Sync failed\");\n throw error;\n }\n });\n\n iap\n .command(\"batch-get\")\n .description(\"Batch get multiple in-app products\")\n .option(\"--skus <skus>\", \"Comma-separated list of SKUs\")\n .option(\"--file <path>\", \"JSON file with array of SKUs\")\n .action(async (_options) => {\n throw Object.assign(\n new Error(\n \"The inappproducts batchGet endpoint is permanently blocked by Google Play (returns 403 PERMISSION_DENIED).\",\n ),\n {\n code: \"IAP_BATCH_GET_UNAVAILABLE\",\n exitCode: 1,\n suggestion:\n \"Use `gpc iap get <sku>` for a single product, or `gpc iap list` for all products.\",\n },\n );\n });\n\n iap\n .command(\"batch-update\")\n .description(\"Batch update multiple in-app products from a JSON file\")\n .requiredOption(\"--file <path>\", \"JSON file with array of product objects\")\n .option(\"--dry-run\", \"Preview changes without executing\")\n .action(async (options) => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const format = getOutputFormat(program, config);\n\n if (options.dryRun || isDryRun(program)) {\n const data = await readJsonFile(options.file);\n const products = Array.isArray(data) ? data : [];\n console.log(`[dry-run] Would batch update ${products.length} product(s)`);\n if (format !== \"json\") {\n const rows = products.map((p: Record<string, unknown>) => ({\n sku: p[\"sku\"] || \"-\",\n action: \"update\",\n }));\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(products, format));\n }\n return;\n }\n\n const client = await getClient(config);\n console.error(\"Note: Using inappproducts batch API\");\n\n const spinner = createSpinner(\"Batch updating products...\");\n if (!program.opts()[\"quiet\"] && process.stderr.isTTY) spinner.start();\n\n try {\n const data = await readJsonFile(options.file);\n const products = Array.isArray(data) ? data : [];\n const request = {\n requests: products.map((p: Record<string, unknown>) => ({\n inappproduct: p,\n packageName,\n sku: p[\"sku\"] as string,\n })),\n };\n const result = await client.inappproducts.batchUpdate(packageName, request as any);\n spinner.stop(\"Batch update complete\");\n console.log(formatOutput(result, format));\n } catch (error) {\n spinner.fail(\"Batch update failed\");\n throw error;\n }\n });\n}\n"],"mappings":"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","names":[]}