@gpc-cli/cli 0.9.35 → 0.9.37

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 (121) hide show
  1. package/README.md +9 -9
  2. package/dist/{anomalies-QZJGQXTZ.js → anomalies-KRRA75MJ.js} +1 -1
  3. package/dist/anomalies-KRRA75MJ.js.map +1 -0
  4. package/dist/{audit-4UPTLW37.js → audit-N2CRHWUN.js} +20 -4
  5. package/dist/audit-N2CRHWUN.js.map +1 -0
  6. package/dist/{auth-KPVEGAWV.js → auth-XGSTT5G5.js} +9 -3
  7. package/dist/auth-XGSTT5G5.js.map +1 -0
  8. package/dist/bin.js +2 -2
  9. package/dist/bin.js.map +1 -1
  10. package/dist/{bundle-7XYHNVNF.js → bundle-F43TD2BQ.js} +22 -13
  11. package/dist/{bundle-7XYHNVNF.js.map → bundle-F43TD2BQ.js.map} +1 -1
  12. package/dist/{cache-K23N6GJR.js → cache-SLNFRTI2.js} +7 -3
  13. package/dist/cache-SLNFRTI2.js.map +1 -0
  14. package/dist/{chunk-DDTPDKTB.js → chunk-EO7EJDT7.js} +49 -43
  15. package/dist/chunk-EO7EJDT7.js.map +1 -0
  16. package/dist/{chunk-7BXCQKJG.js → chunk-P5GF73XK.js} +1 -1
  17. package/dist/chunk-P5GF73XK.js.map +1 -0
  18. package/dist/{chunk-43SH6XEJ.js → chunk-U6ZTQ34I.js} +11 -13
  19. package/dist/chunk-U6ZTQ34I.js.map +1 -0
  20. package/dist/{completion-C3PPWNS7.js → completion-BCHRJSAT.js} +23 -10
  21. package/dist/completion-BCHRJSAT.js.map +1 -0
  22. package/dist/{config-REB7NINL.js → config-F2U3KUHX.js} +2 -2
  23. package/dist/{data-safety-GN5VBKAK.js → data-safety-JR6PZ2BD.js} +11 -8
  24. package/dist/data-safety-JR6PZ2BD.js.map +1 -0
  25. package/dist/{device-tiers-GHIYJPMB.js → device-tiers-5SGJPSYG.js} +7 -8
  26. package/dist/device-tiers-5SGJPSYG.js.map +1 -0
  27. package/dist/{docs-HIGQU4UL.js → docs-7DUXIKA3.js} +3 -3
  28. package/dist/docs-7DUXIKA3.js.map +1 -0
  29. package/dist/{doctor-QDIFTXNB.js → doctor-4BUPAVFT.js} +10 -8
  30. package/dist/doctor-4BUPAVFT.js.map +1 -0
  31. package/dist/{enterprise-IH5HXYRB.js → enterprise-7THXNBTC.js} +6 -2
  32. package/dist/{enterprise-IH5HXYRB.js.map → enterprise-7THXNBTC.js.map} +1 -1
  33. package/dist/{external-transactions-HCL7ROMN.js → external-transactions-O5P4QBIT.js} +5 -8
  34. package/dist/external-transactions-O5P4QBIT.js.map +1 -0
  35. package/dist/{feedback-NVGHRU7A.js → feedback-ERWH4SZF.js} +3 -3
  36. package/dist/{generated-apks-VX7HYZDU.js → generated-apks-KB2PLWDI.js} +2 -6
  37. package/dist/generated-apks-KB2PLWDI.js.map +1 -0
  38. package/dist/{grants-CXTTYKR3.js → grants-TKQJ3IER.js} +25 -6
  39. package/dist/grants-TKQJ3IER.js.map +1 -0
  40. package/dist/{iap-MBDD7VWP.js → iap-BNIAHBDN.js} +7 -3
  41. package/dist/iap-BNIAHBDN.js.map +1 -0
  42. package/dist/index.js +1 -1
  43. package/dist/{internal-sharing-E7SJYDW3.js → internal-sharing-M74VNIQ2.js} +7 -7
  44. package/dist/internal-sharing-M74VNIQ2.js.map +1 -0
  45. package/dist/{listings-7TWCGGMS.js → listings-IVHZJNES.js} +2 -2
  46. package/dist/listings-IVHZJNES.js.map +1 -0
  47. package/dist/{migrate-OHN2FDY6.js → migrate-SQT6RD6T.js} +2 -4
  48. package/dist/migrate-SQT6RD6T.js.map +1 -0
  49. package/dist/{one-time-products-2PK4QKWE.js → one-time-products-3WNXDKE3.js} +43 -28
  50. package/dist/one-time-products-3WNXDKE3.js.map +1 -0
  51. package/dist/{pricing-BYZSLN74.js → pricing-HMHZD44S.js} +1 -1
  52. package/dist/pricing-HMHZD44S.js.map +1 -0
  53. package/dist/{publish-XM43UA5R.js → publish-EPZXLGKZ.js} +3 -9
  54. package/dist/publish-EPZXLGKZ.js.map +1 -0
  55. package/dist/{purchases-WIDU3FDQ.js → purchases-7ZPVCN6D.js} +4 -2
  56. package/dist/purchases-7ZPVCN6D.js.map +1 -0
  57. package/dist/{quickstart-N7FXM5RQ.js → quickstart-EYNNOTVD.js} +2 -2
  58. package/dist/quickstart-EYNNOTVD.js.map +1 -0
  59. package/dist/quota-UHIQQYOY.js +58 -0
  60. package/dist/quota-UHIQQYOY.js.map +1 -0
  61. package/dist/{recovery-S5UNJDBO.js → recovery-YGPOVUFD.js} +7 -3
  62. package/dist/recovery-YGPOVUFD.js.map +1 -0
  63. package/dist/{releases-YRYM7JXC.js → releases-I7QQVKPJ.js} +59 -23
  64. package/dist/releases-I7QQVKPJ.js.map +1 -0
  65. package/dist/{reports-YOT4DQGL.js → reports-2YX3RDOS.js} +1 -1
  66. package/dist/reports-2YX3RDOS.js.map +1 -0
  67. package/dist/{reviews-NN7YQITF.js → reviews-MOVGATUI.js} +18 -9
  68. package/dist/reviews-MOVGATUI.js.map +1 -0
  69. package/dist/{status-L5S2FGZ4.js → status-G3AMJ34G.js} +5 -3
  70. package/dist/status-G3AMJ34G.js.map +1 -0
  71. package/dist/{subscriptions-OXAE7SNS.js → subscriptions-LSOJID6H.js} +8 -2
  72. package/dist/subscriptions-LSOJID6H.js.map +1 -0
  73. package/dist/{update-6XSZRXSU.js → update-O63L7KFJ.js} +6 -12
  74. package/dist/update-O63L7KFJ.js.map +1 -0
  75. package/dist/{users-JASXONRY.js → users-2YTC4Q36.js} +1 -1
  76. package/dist/users-2YTC4Q36.js.map +1 -0
  77. package/dist/{validate-NC4MWKOB.js → validate-VNIS6OEB.js} +2 -2
  78. package/dist/{version-2X32UAAE.js → version-JY5ITFST.js} +11 -9
  79. package/dist/version-JY5ITFST.js.map +1 -0
  80. package/dist/{vitals-LFL75LA6.js → vitals-H7DCI6JJ.js} +16 -9
  81. package/dist/vitals-H7DCI6JJ.js.map +1 -0
  82. package/package.json +5 -5
  83. package/dist/anomalies-QZJGQXTZ.js.map +0 -1
  84. package/dist/audit-4UPTLW37.js.map +0 -1
  85. package/dist/auth-KPVEGAWV.js.map +0 -1
  86. package/dist/cache-K23N6GJR.js.map +0 -1
  87. package/dist/chunk-43SH6XEJ.js.map +0 -1
  88. package/dist/chunk-7BXCQKJG.js.map +0 -1
  89. package/dist/chunk-DDTPDKTB.js.map +0 -1
  90. package/dist/completion-C3PPWNS7.js.map +0 -1
  91. package/dist/data-safety-GN5VBKAK.js.map +0 -1
  92. package/dist/device-tiers-GHIYJPMB.js.map +0 -1
  93. package/dist/docs-HIGQU4UL.js.map +0 -1
  94. package/dist/doctor-QDIFTXNB.js.map +0 -1
  95. package/dist/external-transactions-HCL7ROMN.js.map +0 -1
  96. package/dist/generated-apks-VX7HYZDU.js.map +0 -1
  97. package/dist/grants-CXTTYKR3.js.map +0 -1
  98. package/dist/iap-MBDD7VWP.js.map +0 -1
  99. package/dist/internal-sharing-E7SJYDW3.js.map +0 -1
  100. package/dist/listings-7TWCGGMS.js.map +0 -1
  101. package/dist/migrate-OHN2FDY6.js.map +0 -1
  102. package/dist/one-time-products-2PK4QKWE.js.map +0 -1
  103. package/dist/pricing-BYZSLN74.js.map +0 -1
  104. package/dist/publish-XM43UA5R.js.map +0 -1
  105. package/dist/purchases-WIDU3FDQ.js.map +0 -1
  106. package/dist/quickstart-N7FXM5RQ.js.map +0 -1
  107. package/dist/quota-SNUI75NM.js +0 -53
  108. package/dist/quota-SNUI75NM.js.map +0 -1
  109. package/dist/recovery-S5UNJDBO.js.map +0 -1
  110. package/dist/releases-YRYM7JXC.js.map +0 -1
  111. package/dist/reports-YOT4DQGL.js.map +0 -1
  112. package/dist/reviews-NN7YQITF.js.map +0 -1
  113. package/dist/status-L5S2FGZ4.js.map +0 -1
  114. package/dist/subscriptions-OXAE7SNS.js.map +0 -1
  115. package/dist/update-6XSZRXSU.js.map +0 -1
  116. package/dist/users-JASXONRY.js.map +0 -1
  117. package/dist/version-2X32UAAE.js.map +0 -1
  118. package/dist/vitals-LFL75LA6.js.map +0 -1
  119. /package/dist/{config-REB7NINL.js.map → config-F2U3KUHX.js.map} +0 -0
  120. /package/dist/{feedback-NVGHRU7A.js.map → feedback-ERWH4SZF.js.map} +0 -0
  121. /package/dist/{validate-NC4MWKOB.js.map → validate-VNIS6OEB.js.map} +0 -0
package/README.md CHANGED
@@ -77,17 +77,17 @@ REVIEWS (last 30 days)
77
77
 
78
78
  187 API endpoints across these command groups:
79
79
 
80
- | Group | What you can do |
81
- | ----------------- | ------------------------------------------------------------------------------------- |
82
- | **Releases** | Upload, promote, rollout increase/halt/resume, end-to-end `publish` |
80
+ | Group | What you can do |
81
+ | ----------------- | -------------------------------------------------------------------------------------- |
82
+ | **Releases** | Upload, promote, rollout increase/halt/resume, end-to-end `publish` |
83
83
  | **Listings** | Pull and push store listings, upload screenshots — works with Fastlane metadata format |
84
- | **Reviews** | Filter by stars, reply to users, export to CSV |
85
- | **Vitals** | Crash rates, ANR, startup, rendering — with CI threshold gates |
86
- | **Bundle** | Per-module size breakdown, build-to-build diff, size CI gates |
84
+ | **Reviews** | Filter by stars, reply to users, export to CSV |
85
+ | **Vitals** | Crash rates, ANR, startup, rendering — with CI threshold gates |
86
+ | **Bundle** | Per-module size breakdown, build-to-build diff, size CI gates |
87
87
  | **Subscriptions** | Create and manage base plans, offers, and pricing |
88
- | **IAP** | Sync products from local files, batch get and update |
89
- | **Purchases** | Verify, acknowledge, cancel, refund, list voided |
90
- | **Reports** | Download financial and stats reports |
88
+ | **IAP** | Sync products from local files, batch get and update |
89
+ | **Purchases** | Verify, acknowledge, cancel, refund, list voided |
90
+ | **Reports** | Download financial and stats reports |
91
91
  | **Testers** | Add, remove, import from CSV |
92
92
  | **Users** | Invite, update, remove, manage per-app grants |
93
93
 
@@ -56,4 +56,4 @@ function registerAnomaliesCommands(program) {
56
56
  export {
57
57
  registerAnomaliesCommands
58
58
  };
59
- //# sourceMappingURL=anomalies-QZJGQXTZ.js.map
59
+ //# sourceMappingURL=anomalies-KRRA75MJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/anomalies.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 { createReportingClient } from \"@gpc-cli/api\";\nimport { getVitalsAnomalies, formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\nfunction resolvePackageName(packageArg: string | undefined, config: GpcConfig): string {\n const name = packageArg || config.app;\n if (!name) {\n console.error(\"Error: No package name. Use --app <package> or gpc config set app <package>\");\n process.exit(2);\n }\n return name;\n}\n\nasync function getReportingClient(config: GpcConfig) {\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n return createReportingClient({ auth });\n}\n\nexport function registerAnomaliesCommands(program: Command): void {\n const anomalies = program.command(\"anomalies\").description(\"Detect and list vitals anomalies\");\n\n anomalies\n .command(\"list\")\n .description(\"List detected vitals anomalies\")\n .action(async () => {\n const config = await loadConfig();\n const packageName = resolvePackageName(program.opts()[\"app\"], config);\n const reporting = await getReportingClient(config);\n const format = getOutputFormat(program, config);\n\n try {\n const result = await getVitalsAnomalies(reporting, packageName);\n const items = (result as unknown as Record<string, unknown>)[\"anomalies\"] as\n | unknown[]\n | undefined;\n\n if (format !== \"json\") {\n if (!items || items.length === 0) {\n console.log(\"No anomalies detected.\");\n return;\n }\n const rows = items.map((item) => {\n const a = item as Record<string, unknown>;\n return {\n name: String(a[\"name\"] ?? \"-\"),\n metricSet: String(a[\"metricSet\"] ?? \"-\"),\n aggregationPeriod: String(a[\"aggregationPeriod\"] ?? \"-\"),\n };\n });\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(result, format));\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n}\n"],"mappings":";;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,6BAA6B;AACtC,SAAS,oBAAoB,oBAAoB;AAGjD,SAAS,mBAAmB,YAAgC,QAA2B;AACrF,QAAM,OAAO,cAAc,OAAO;AAClC,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,6EAA6E;AAC3F,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEA,eAAe,mBAAmB,QAAmB;AACnD,QAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,SAAO,sBAAsB,EAAE,KAAK,CAAC;AACvC;AAEO,SAAS,0BAA0B,SAAwB;AAChE,QAAM,YAAY,QAAQ,QAAQ,WAAW,EAAE,YAAY,kCAAkC;AAE7F,YACG,QAAQ,MAAM,EACd,YAAY,gCAAgC,EAC5C,OAAO,YAAY;AAClB,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,mBAAmB,QAAQ,KAAK,EAAE,KAAK,GAAG,MAAM;AACpE,UAAM,YAAY,MAAM,mBAAmB,MAAM;AACjD,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AACF,YAAM,SAAS,MAAM,mBAAmB,WAAW,WAAW;AAC9D,YAAM,QAAS,OAA8C,WAAW;AAIxE,UAAI,WAAW,QAAQ;AACrB,YAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC,kBAAQ,IAAI,wBAAwB;AACpC;AAAA,QACF;AACA,cAAM,OAAO,MAAM,IAAI,CAAC,SAAS;AAC/B,gBAAM,IAAI;AACV,iBAAO;AAAA,YACL,MAAM,OAAO,EAAE,MAAM,KAAK,GAAG;AAAA,YAC7B,WAAW,OAAO,EAAE,WAAW,KAAK,GAAG;AAAA,YACvC,mBAAmB,OAAO,EAAE,mBAAmB,KAAK,GAAG;AAAA,UACzD;AAAA,QACF,CAAC;AACD,gBAAQ,IAAI,aAAa,MAAM,MAAM,CAAC;AAAA,MACxC,OAAO;AACL,gBAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,MAC1C;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;","names":[]}
@@ -26,13 +26,27 @@ function formatAuditTimestamp(iso) {
26
26
  const diffMin = Math.floor(diffMs / 6e4);
27
27
  if (diffMin < 60) return diffMin < 1 ? "just now" : `${diffMin} min ago`;
28
28
  const diffHr = Math.floor(diffMin / 60);
29
- if (diffHr < 24) return `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}:${String(date.getSeconds()).padStart(2, "0")}`;
29
+ if (diffHr < 24)
30
+ return `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}:${String(date.getSeconds()).padStart(2, "0")}`;
30
31
  const diffDays = Math.floor(diffHr / 24);
31
32
  if (diffDays < 7) {
32
33
  const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
33
34
  return `${days[date.getDay()]} ${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
34
35
  }
35
- const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
36
+ const months = [
37
+ "Jan",
38
+ "Feb",
39
+ "Mar",
40
+ "Apr",
41
+ "May",
42
+ "Jun",
43
+ "Jul",
44
+ "Aug",
45
+ "Sep",
46
+ "Oct",
47
+ "Nov",
48
+ "Dec"
49
+ ];
36
50
  return `${months[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;
37
51
  }
38
52
  function registerAuditCommands(program) {
@@ -107,7 +121,9 @@ function registerAuditCommands(program) {
107
121
  dryRun
108
122
  });
109
123
  if (dryRun) {
110
- console.log(`[dry-run] Would delete ${result.deleted} entries, ${result.remaining} would remain.`);
124
+ console.log(
125
+ `[dry-run] Would delete ${result.deleted} entries, ${result.remaining} would remain.`
126
+ );
111
127
  } else {
112
128
  console.log(`Deleted ${result.deleted} entries. ${result.remaining} remaining.`);
113
129
  }
@@ -120,4 +136,4 @@ function registerAuditCommands(program) {
120
136
  export {
121
137
  registerAuditCommands
122
138
  };
123
- //# sourceMappingURL=audit-4UPTLW37.js.map
139
+ //# sourceMappingURL=audit-N2CRHWUN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/audit.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { getConfigDir } from \"@gpc-cli/config\";\nimport {\n initAudit,\n listAuditEvents,\n searchAuditEvents,\n clearAuditLog,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { isDryRun } from \"../dry-run.js\";\nimport { requireConfirm } from \"../prompt.js\";\n\nfunction formatAuditTimestamp(iso: string): string {\n const date = new Date(iso);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 60) return diffMin < 1 ? \"just now\" : `${diffMin} min ago`;\n const diffHr = Math.floor(diffMin / 60);\n if (diffHr < 24)\n return `${String(date.getHours()).padStart(2, \"0\")}:${String(date.getMinutes()).padStart(2, \"0\")}:${String(date.getSeconds()).padStart(2, \"0\")}`;\n const diffDays = Math.floor(diffHr / 24);\n if (diffDays < 7) {\n const days = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n return `${days[date.getDay()]} ${String(date.getHours()).padStart(2, \"0\")}:${String(date.getMinutes()).padStart(2, \"0\")}`;\n }\n const months = [\n \"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"May\",\n \"Jun\",\n \"Jul\",\n \"Aug\",\n \"Sep\",\n \"Oct\",\n \"Nov\",\n \"Dec\",\n ];\n return `${months[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;\n}\n\nexport function registerAuditCommands(program: Command): void {\n const audit = program.command(\"audit\").description(\"Query and manage audit logs\");\n\n audit\n .command(\"list\")\n .description(\"List recent audit events\")\n .option(\"--limit <n>\", \"Maximum events to show\", parseInt, 50)\n .option(\"--since <date>\", \"Show events since date (ISO 8601)\")\n .option(\"--command <name>\", \"Filter by command name\")\n .action(async (options) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n initAudit(getConfigDir());\n\n try {\n const events = await listAuditEvents({\n limit: options.limit,\n since: options.since,\n command: options.command,\n });\n if (events.length === 0 && format !== \"json\") {\n console.log(\"No audit events found.\");\n return;\n }\n if (format !== \"json\") {\n const rows = events.map((e) => ({\n timestamp: formatAuditTimestamp(e.timestamp),\n command: e.command,\n app: e.app || \"-\",\n success: e.success !== undefined ? String(e.success) : \"-\",\n durationMs: e.durationMs ?? \"-\",\n }));\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(events, format));\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n\n audit\n .command(\"search <query>\")\n .description(\"Search audit events by keyword\")\n .action(async (query: string) => {\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n initAudit(getConfigDir());\n\n try {\n const events = await searchAuditEvents(query);\n if (events.length === 0 && format !== \"json\") {\n console.log(`No audit events matching \"${query}\".`);\n return;\n }\n if (format !== \"json\") {\n const rows = events.map((e) => ({\n timestamp: formatAuditTimestamp(e.timestamp),\n command: e.command,\n app: e.app || \"-\",\n success: e.success !== undefined ? String(e.success) : \"-\",\n }));\n console.log(formatOutput(rows, format));\n } else {\n console.log(formatOutput(events, format));\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n\n audit\n .command(\"clear\")\n .description(\"Clear audit log entries\")\n .option(\"--before <date>\", \"Clear entries before date (ISO 8601)\")\n .option(\"--dry-run\", \"Preview what would be cleared\")\n .action(async (options, cmd: Command) => {\n const dryRun = options.dryRun || isDryRun(cmd);\n await loadConfig();\n initAudit(getConfigDir());\n\n if (!dryRun && !options.before) {\n await requireConfirm(\"Clear all audit log entries?\", program);\n }\n\n try {\n const result = await clearAuditLog({\n before: options.before,\n dryRun,\n });\n if (dryRun) {\n console.log(\n `[dry-run] Would delete ${result.deleted} entries, ${result.remaining} would remain.`,\n );\n } else {\n console.log(`Deleted ${result.deleted} entries. ${result.remaining} remaining.`);\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n}\n"],"mappings":"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","names":[]}
@@ -47,12 +47,18 @@ Authenticated via Application Default Credentials`);
47
47
  }
48
48
  }
49
49
  const profileName = await askQuestion(rl, "\nProfile name (optional, press Enter to skip): ");
50
- const packageName = await askQuestion(rl, "Default package name (optional, e.g. com.example.app): ");
50
+ const packageName = await askQuestion(
51
+ rl,
52
+ "Default package name (optional, e.g. com.example.app): "
53
+ );
51
54
  const { loadServiceAccountKey: loadKey } = await import("@gpc-cli/auth");
52
55
  const key = await loadKey(saPath);
53
56
  if (profileName) {
54
57
  const { setProfileConfig } = await import("@gpc-cli/config");
55
- await setProfileConfig(profileName, { auth: { serviceAccount: saPath }, ...packageName && { app: packageName } });
58
+ await setProfileConfig(profileName, {
59
+ auth: { serviceAccount: saPath },
60
+ ...packageName && { app: packageName }
61
+ });
56
62
  console.log(`
57
63
  Profile "${profileName}" configured with ${key.client_email}`);
58
64
  } else {
@@ -240,4 +246,4 @@ function registerAuthCommands(program) {
240
246
  export {
241
247
  registerAuthCommands
242
248
  };
243
- //# sourceMappingURL=auth-KPVEGAWV.js.map
249
+ //# sourceMappingURL=auth-XGSTT5G5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/auth.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { createInterface } from \"node:readline\";\nimport { access } from \"node:fs/promises\";\nimport { resolveAuth, loadServiceAccountKey, clearTokenCache, AuthError } from \"@gpc-cli/auth\";\nimport { loadConfig, getCacheDir } from \"@gpc-cli/config\";\nimport { formatOutput } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\nasync function askQuestion(\n rl: ReturnType<typeof createInterface>,\n question: string,\n): Promise<string> {\n return new Promise((resolve) => {\n rl.question(question, (answer) => resolve(answer.trim()));\n });\n}\n\nasync function runLoginWizard(): Promise<void> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n\n try {\n console.log(\"\\nGPC Authentication Setup\");\n console.log(\"─────────────────────────\");\n\n // Step 1: auth method\n console.log(\"\\nAuthentication methods:\");\n console.log(\" 1. Service account key file (recommended)\");\n console.log(\" 2. Application Default Credentials (ADC)\");\n const method = await askQuestion(rl, \"\\nSelect method [1]: \");\n const useAdc = method === \"2\";\n\n if (useAdc) {\n const { resolveAuth: ra } = await import(\"@gpc-cli/auth\");\n const client = await ra();\n console.log(`\\nAuthenticated via Application Default Credentials`);\n console.log(`Account: ${client.getClientEmail()}`);\n return;\n }\n\n // Step 2: credentials path with validation loop\n let saPath = \"\";\n while (!saPath) {\n const input = await askQuestion(rl, \"\\nPath to service account JSON key: \");\n if (!input) {\n console.log(\" Path is required.\");\n continue;\n }\n try {\n await access(input);\n saPath = input;\n } catch {\n console.log(` File not found: ${input}`);\n }\n }\n\n // Step 3: optional profile name\n const profileName = await askQuestion(rl, \"\\nProfile name (optional, press Enter to skip): \");\n\n // Step 4: default package name\n const packageName = await askQuestion(\n rl,\n \"Default package name (optional, e.g. com.example.app): \",\n );\n\n // Apply settings\n const { loadServiceAccountKey: loadKey } = await import(\"@gpc-cli/auth\");\n const key = await loadKey(saPath);\n\n if (profileName) {\n const { setProfileConfig } = await import(\"@gpc-cli/config\");\n await setProfileConfig(profileName, {\n auth: { serviceAccount: saPath },\n ...(packageName && { app: packageName }),\n });\n console.log(`\\nProfile \"${profileName}\" configured with ${key.client_email}`);\n } else {\n const { setConfigValue } = await import(\"@gpc-cli/config\");\n await setConfigValue(\"auth.serviceAccount\", saPath);\n if (packageName) await setConfigValue(\"app\", packageName);\n console.log(`\\nAuthenticated as ${key.client_email}`);\n }\n console.log(`Project: ${key.project_id}`);\n console.log(\"\\nRun 'gpc doctor' to verify your setup.\");\n } finally {\n rl.close();\n }\n}\n\nexport function registerAuthCommands(program: Command): void {\n const auth = program.command(\"auth\").description(\"Manage authentication\");\n\n auth\n .command(\"login\")\n .description(\"Authenticate with Google Play Developer API\")\n .option(\"--service-account <path>\", \"Path to service account JSON key file\")\n .option(\"--adc\", \"Use Application Default Credentials\")\n .option(\"--profile <name>\", \"Store credentials under a named profile\")\n .action(async (options: { serviceAccount?: string; adc?: boolean; profile?: string }) => {\n try {\n if (options.serviceAccount) {\n const key = await loadServiceAccountKey(options.serviceAccount);\n\n if (options.profile) {\n const { setProfileConfig } = await import(\"@gpc-cli/config\");\n await setProfileConfig(options.profile, {\n auth: { serviceAccount: options.serviceAccount },\n });\n console.log(`Profile \"${options.profile}\" configured with ${key.client_email}`);\n } else {\n const { setConfigValue } = await import(\"@gpc-cli/config\");\n await setConfigValue(\"auth.serviceAccount\", options.serviceAccount);\n console.log(`Authenticated as ${key.client_email}`);\n }\n console.log(`Project: ${key.project_id}`);\n } else if (options.adc) {\n const client = await resolveAuth();\n console.log(`Authenticated via Application Default Credentials`);\n console.log(`Account: ${client.getClientEmail()}`);\n } else {\n // Interactive wizard when no flags provided and in interactive mode\n const opts = program.opts();\n const interactive =\n opts[\"interactive\"] !== false && opts[\"ci\"] !== true && process.stdin.isTTY;\n if (interactive) {\n await runLoginWizard();\n } else {\n console.log(\"Usage: gpc auth login --service-account <path>\");\n console.log(\"\");\n console.log(\"Authentication methods:\");\n console.log(\" --service-account <path> Service account JSON key file\");\n console.log(\" --adc Application Default Credentials\");\n console.log(\"\");\n console.log(\"Options:\");\n console.log(\" --profile <name> Store under a named profile\");\n }\n }\n } catch (error) {\n if (error instanceof AuthError) {\n console.error(`Error: ${error.message}`);\n if (error.suggestion) console.error(`Suggestion: ${error.suggestion}`);\n process.exit(3);\n }\n throw error;\n }\n });\n\n auth\n .command(\"status\")\n .description(\"Show current authentication status\")\n .action(async () => {\n const config = await loadConfig();\n try {\n const client = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n cachePath: getCacheDir(),\n });\n const format = getOutputFormat(program, config);\n const data = {\n authenticated: true,\n account: client.getClientEmail(),\n project: client.getProjectId(),\n ...(config.profile && { profile: config.profile }),\n };\n console.log(formatOutput(data, format));\n } catch (error) {\n if (error instanceof AuthError) {\n const format = getOutputFormat(program, config);\n const data = {\n authenticated: false,\n error: error.message,\n suggestion: error.suggestion,\n };\n console.log(formatOutput(data, format));\n process.exit(3);\n }\n throw error;\n }\n });\n\n auth\n .command(\"logout\")\n .description(\"Clear stored credentials and token cache\")\n .action(async () => {\n const { setConfigValue } = await import(\"@gpc-cli/config\");\n await setConfigValue(\"auth.serviceAccount\", \"\");\n await clearTokenCache(getCacheDir());\n console.log(\"Credentials and token cache cleared.\");\n });\n\n auth\n .command(\"whoami\")\n .description(\"Show current authenticated identity\")\n .action(async () => {\n try {\n const config = await loadConfig();\n const client = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n cachePath: getCacheDir(),\n });\n console.log(client.getClientEmail());\n } catch {\n console.error(\"Not authenticated. Run: gpc auth login\");\n process.exit(3);\n }\n });\n\n auth\n .command(\"switch <profile>\")\n .description(\"Switch to a named profile\")\n .action(async (profile: string) => {\n try {\n // Verify profile exists\n const config = await loadConfig({ profile });\n const { setConfigValue } = await import(\"@gpc-cli/config\");\n await setConfigValue(\"profile\", profile);\n console.log(`Switched to profile \"${profile}\"`);\n if (config.auth?.serviceAccount) {\n console.log(`Service account: ${config.auth.serviceAccount}`);\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(2);\n }\n });\n\n auth\n .command(\"token\")\n .description(\"Print the current access token (useful for manual API calls)\")\n .action(async () => {\n try {\n const config = await loadConfig();\n const authClient = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n cachePath: getCacheDir(),\n });\n const token = await authClient.getAccessToken();\n console.log(token);\n } catch (error) {\n if (error instanceof AuthError) {\n console.error(`Error: ${error.message}`);\n process.exit(3);\n }\n throw error;\n }\n });\n\n auth\n .command(\"setup-gcp\")\n .description(\"Step-by-step guide to create a Google Cloud service account\")\n .action(() => {\n console.log(\"\\nGPC — Google Cloud Service Account Setup\");\n console.log(\"═══════════════════════════════════════════\");\n console.log(\"\\nStep 1: Open the Google Cloud Console\");\n console.log(\" https://console.cloud.google.com/iam-admin/serviceaccounts\");\n console.log(\"\\nStep 2: Create a service account\");\n console.log(\" • Click 'Create Service Account'\");\n console.log(\" • Name it: gpc-deploy (or any name you like)\");\n console.log(\" • Description: GPC Google Play Console access\");\n console.log(\"\\nStep 3: Grant roles\");\n console.log(\" No GCP roles needed — permissions are managed in Google Play Console.\");\n console.log(\"\\nStep 4: Download the JSON key\");\n console.log(\" • Click your new service account → Keys → Add Key → Create new key → JSON\");\n console.log(\" • Save as: ~/gpc-service-account.json\");\n console.log(\"\\nStep 5: Add to Google Play Console\");\n console.log(\" https://play.google.com/console/developers\");\n console.log(\" • Users and Permissions → Invite new users\");\n console.log(\" • Paste the service account email (ends with @...gserviceaccount.com)\");\n console.log(\" • Grant: Release manager + View app info + Reply to reviews\");\n console.log(\"\\nStep 6: Authenticate\");\n console.log(\" gpc auth login --service-account ~/gpc-service-account.json\");\n console.log(\"\\nStep 7: Verify\");\n console.log(\" gpc doctor\");\n console.log(\"\\nSee full docs: https://yasserstudio.github.io/gpc/guide/authentication\");\n });\n\n auth\n .command(\"profiles\")\n .description(\"List configured profiles\")\n .action(async () => {\n const { listProfiles } = await import(\"@gpc-cli/config\");\n const config = await loadConfig();\n const profiles = await listProfiles();\n const format = getOutputFormat(program, config);\n\n if (profiles.length === 0) {\n console.log(\n \"No profiles configured. Use: gpc auth login --service-account <path> --profile <name>\",\n );\n return;\n }\n\n const data = profiles.map((name) => ({\n name,\n active: name === config.profile,\n }));\n console.log(formatOutput(data, format));\n });\n}\n"],"mappings":"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","names":[]}
package/dist/bin.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  createProgram,
4
4
  handleCliError,
5
5
  loadPlugins
6
- } from "./chunk-DDTPDKTB.js";
6
+ } from "./chunk-EO7EJDT7.js";
7
7
  import {
8
8
  checkForUpdate,
9
9
  formatUpdateNotification
@@ -44,7 +44,7 @@ if (!_isJsonMode && !_isQuiet && !existsSync(getUserConfigPath())) {
44
44
  }
45
45
  await setupNetworking();
46
46
  initAudit(getConfigDir());
47
- var currentVersion = "0.9.35";
47
+ var currentVersion = "0.9.37";
48
48
  var isUpdateCommand = process.argv[2] === "update";
49
49
  var updateCheckPromise = isUpdateCommand ? Promise.resolve(null) : checkForUpdate(currentVersion);
50
50
  if (process.argv.includes("--ci")) {
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin.ts","../src/networking.ts"],"sourcesContent":["if (process.env[\"GPC_NO_COLOR\"] === \"1\") process.env[\"NO_COLOR\"] = \"1\";\nif (process.argv.includes(\"--no-color\")) {\n process.env[\"NO_COLOR\"] = \"1\";\n}\nimport { existsSync } from \"node:fs\";\nimport { setupNetworking } from \"./networking.js\";\nimport { createProgram } from \"./program.js\";\nimport { loadPlugins } from \"./plugins.js\";\nimport { handleCliError } from \"./error-handler.js\";\nimport { initAudit, sendWebhook } from \"@gpc-cli/core\";\nimport type { WebhookPayload } from \"@gpc-cli/core\";\nimport { getConfigDir, loadConfig, getUserConfigPath } from \"@gpc-cli/config\";\nimport { checkForUpdate, formatUpdateNotification } from \"./update-check.js\";\n\n// First-run banner\nconst _isJsonMode =\n process.argv.includes(\"--json\") ||\n process.argv.includes(\"-j\") ||\n process.argv.includes(\"--ci\") ||\n (process.argv.includes(\"--output\") &&\n process.argv[process.argv.indexOf(\"--output\") + 1] === \"json\") ||\n (process.argv.includes(\"-o\") &&\n process.argv[process.argv.indexOf(\"-o\") + 1] === \"json\");\nconst _isQuiet = process.argv.includes(\"--quiet\") || process.argv.includes(\"-q\");\n\nif (!_isJsonMode && !_isQuiet && !existsSync(getUserConfigPath())) {\n process.stderr.write(\"✦ First time? Run gpc config init to get set up.\\n\\n\");\n}\n\nawait setupNetworking();\ninitAudit(getConfigDir());\n\nconst currentVersion = process.env[\"__GPC_VERSION\"] || \"0.0.0\";\n\n// Skip passive update check when the user is explicitly running `gpc update` —\n// that command does its own check against the GitHub Releases API.\nconst isUpdateCommand = process.argv[2] === \"update\";\n\n// Start update check before command execution (non-blocking)\nconst updateCheckPromise = isUpdateCommand ? Promise.resolve(null) : checkForUpdate(currentVersion);\n\n// Handle --ci and --json flags early (before command parsing)\nif (process.argv.includes(\"--ci\")) {\n process.env[\"CI\"] = \"1\";\n // --ci implies --output json --no-interactive --no-color\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n if (!process.argv.includes(\"--no-interactive\")) {\n process.argv.push(\"--no-interactive\");\n }\n if (!process.argv.includes(\"--no-color\")) {\n process.argv.push(\"--no-color\");\n }\n}\nif (process.argv.includes(\"--json\") || process.argv.includes(\"-j\")) {\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n}\n\nconst pluginManager = await loadPlugins();\nconst program = await createProgram(pluginManager);\n\n// GPC_DEBUG=1 enables verbose mode without mutating process.argv\nif (process.env[\"GPC_DEBUG\"] === \"1\") {\n program.setOptionValueWithSource(\"verbose\", true, \"env\");\n}\n\nconst startTime = Date.now();\nlet commandSuccess = true;\nlet commandError: string | undefined;\n\nawait program.parseAsync(process.argv).catch((error: unknown) => {\n commandSuccess = false;\n commandError = error instanceof Error ? error.message : String(error);\n const exitCode = handleCliError(error);\n process.exit(exitCode);\n});\n\n// Send webhook notification if --notify was set\nconst notifyOpt = program.opts()[\"notify\"] as string | boolean | undefined;\nif (notifyOpt !== undefined && notifyOpt !== false) {\n try {\n const config = await loadConfig();\n if (config.webhooks) {\n const commandName = process.argv.slice(2).filter((a) => !a.startsWith(\"--notify\")).join(\" \");\n const payload: WebhookPayload = {\n command: commandName || \"unknown\",\n success: commandSuccess,\n duration: Date.now() - startTime,\n app: program.opts()[\"app\"] as string | undefined,\n error: commandError,\n };\n\n const target = typeof notifyOpt === \"string\" ? notifyOpt : undefined;\n // Fire-and-forget — do not block exit\n sendWebhook(config.webhooks, payload, target).catch(() => {});\n }\n } catch {\n // Never let webhook logic break the CLI\n }\n}\n\n// After command completes, show update notification if available\n// isUpdateCommand is declared above — update check was skipped for this command\ntry {\n const result = await Promise.race([\n updateCheckPromise,\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 3000)),\n ]);\n\n if (\n result &&\n result.updateAvailable &&\n !isUpdateCommand &&\n process.stdout.isTTY &&\n !process.argv.includes(\"--json\") &&\n program.opts()[\"output\"] !== \"json\"\n ) {\n process.stderr.write(`\\n${formatUpdateNotification(result)}\\n`);\n }\n} catch {\n // Silently ignore update check failures\n}\n","/**\n * Set up proxy and custom CA certificate support.\n * Must be called before any fetch() calls.\n */\nexport async function setupNetworking(): Promise<void> {\n // Map GPC_CA_CERT to NODE_EXTRA_CA_CERTS (works in both Node and Bun)\n const caCert = process.env[\"GPC_CA_CERT\"];\n if (caCert && !process.env[\"NODE_EXTRA_CA_CERTS\"]) {\n process.env[\"NODE_EXTRA_CA_CERTS\"] = caCert;\n }\n\n // In standalone binary mode, Bun handles HTTPS_PROXY/HTTP_PROXY natively\n if (process.env[\"__GPC_BINARY\"] === \"1\") return;\n\n const proxyUrl =\n process.env[\"HTTPS_PROXY\"] ||\n process.env[\"https_proxy\"] ||\n process.env[\"HTTP_PROXY\"] ||\n process.env[\"http_proxy\"];\n if (proxyUrl) {\n try {\n // @ts-expect-error undici types not available in all environments\n const { ProxyAgent, setGlobalDispatcher } = await import(\"undici\");\n setGlobalDispatcher(new ProxyAgent(proxyUrl));\n } catch {\n console.error(\"Warning: Proxy support requires Node.js 20+. HTTPS_PROXY will be ignored.\");\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/bin.ts","../src/networking.ts"],"sourcesContent":["if (process.env[\"GPC_NO_COLOR\"] === \"1\") process.env[\"NO_COLOR\"] = \"1\";\nif (process.argv.includes(\"--no-color\")) {\n process.env[\"NO_COLOR\"] = \"1\";\n}\nimport { existsSync } from \"node:fs\";\nimport { setupNetworking } from \"./networking.js\";\nimport { createProgram } from \"./program.js\";\nimport { loadPlugins } from \"./plugins.js\";\nimport { handleCliError } from \"./error-handler.js\";\nimport { initAudit, sendWebhook } from \"@gpc-cli/core\";\nimport type { WebhookPayload } from \"@gpc-cli/core\";\nimport { getConfigDir, loadConfig, getUserConfigPath } from \"@gpc-cli/config\";\nimport { checkForUpdate, formatUpdateNotification } from \"./update-check.js\";\n\n// First-run banner\nconst _isJsonMode =\n process.argv.includes(\"--json\") ||\n process.argv.includes(\"-j\") ||\n process.argv.includes(\"--ci\") ||\n (process.argv.includes(\"--output\") &&\n process.argv[process.argv.indexOf(\"--output\") + 1] === \"json\") ||\n (process.argv.includes(\"-o\") && process.argv[process.argv.indexOf(\"-o\") + 1] === \"json\");\nconst _isQuiet = process.argv.includes(\"--quiet\") || process.argv.includes(\"-q\");\n\nif (!_isJsonMode && !_isQuiet && !existsSync(getUserConfigPath())) {\n process.stderr.write(\"✦ First time? Run gpc config init to get set up.\\n\\n\");\n}\n\nawait setupNetworking();\ninitAudit(getConfigDir());\n\nconst currentVersion = process.env[\"__GPC_VERSION\"] || \"0.0.0\";\n\n// Skip passive update check when the user is explicitly running `gpc update` —\n// that command does its own check against the GitHub Releases API.\nconst isUpdateCommand = process.argv[2] === \"update\";\n\n// Start update check before command execution (non-blocking)\nconst updateCheckPromise = isUpdateCommand ? Promise.resolve(null) : checkForUpdate(currentVersion);\n\n// Handle --ci and --json flags early (before command parsing)\nif (process.argv.includes(\"--ci\")) {\n process.env[\"CI\"] = \"1\";\n // --ci implies --output json --no-interactive --no-color\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n if (!process.argv.includes(\"--no-interactive\")) {\n process.argv.push(\"--no-interactive\");\n }\n if (!process.argv.includes(\"--no-color\")) {\n process.argv.push(\"--no-color\");\n }\n}\nif (process.argv.includes(\"--json\") || process.argv.includes(\"-j\")) {\n if (!process.argv.some((a) => a.startsWith(\"--output\") || a.startsWith(\"-o\"))) {\n process.argv.push(\"--output\", \"json\");\n }\n}\n\nconst pluginManager = await loadPlugins();\nconst program = await createProgram(pluginManager);\n\n// GPC_DEBUG=1 enables verbose mode without mutating process.argv\nif (process.env[\"GPC_DEBUG\"] === \"1\") {\n program.setOptionValueWithSource(\"verbose\", true, \"env\");\n}\n\nconst startTime = Date.now();\nlet commandSuccess = true;\nlet commandError: string | undefined;\n\nawait program.parseAsync(process.argv).catch((error: unknown) => {\n commandSuccess = false;\n commandError = error instanceof Error ? error.message : String(error);\n const exitCode = handleCliError(error);\n process.exit(exitCode);\n});\n\n// Send webhook notification if --notify was set\nconst notifyOpt = program.opts()[\"notify\"] as string | boolean | undefined;\nif (notifyOpt !== undefined && notifyOpt !== false) {\n try {\n const config = await loadConfig();\n if (config.webhooks) {\n const commandName = process.argv\n .slice(2)\n .filter((a) => !a.startsWith(\"--notify\"))\n .join(\" \");\n const payload: WebhookPayload = {\n command: commandName || \"unknown\",\n success: commandSuccess,\n duration: Date.now() - startTime,\n app: program.opts()[\"app\"] as string | undefined,\n error: commandError,\n };\n\n const target = typeof notifyOpt === \"string\" ? notifyOpt : undefined;\n // Fire-and-forget — do not block exit\n sendWebhook(config.webhooks, payload, target).catch(() => {});\n }\n } catch {\n // Never let webhook logic break the CLI\n }\n}\n\n// After command completes, show update notification if available\n// isUpdateCommand is declared above — update check was skipped for this command\ntry {\n const result = await Promise.race([\n updateCheckPromise,\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 3000)),\n ]);\n\n if (\n result &&\n result.updateAvailable &&\n !isUpdateCommand &&\n process.stdout.isTTY &&\n !process.argv.includes(\"--json\") &&\n program.opts()[\"output\"] !== \"json\"\n ) {\n process.stderr.write(`\\n${formatUpdateNotification(result)}\\n`);\n }\n} catch {\n // Silently ignore update check failures\n}\n","/**\n * Set up proxy and custom CA certificate support.\n * Must be called before any fetch() calls.\n */\nexport async function setupNetworking(): Promise<void> {\n // Map GPC_CA_CERT to NODE_EXTRA_CA_CERTS (works in both Node and Bun)\n const caCert = process.env[\"GPC_CA_CERT\"];\n if (caCert && !process.env[\"NODE_EXTRA_CA_CERTS\"]) {\n process.env[\"NODE_EXTRA_CA_CERTS\"] = caCert;\n }\n\n // In standalone binary mode, Bun handles HTTPS_PROXY/HTTP_PROXY natively\n if (process.env[\"__GPC_BINARY\"] === \"1\") return;\n\n const proxyUrl =\n process.env[\"HTTPS_PROXY\"] ||\n process.env[\"https_proxy\"] ||\n process.env[\"HTTP_PROXY\"] ||\n process.env[\"http_proxy\"];\n if (proxyUrl) {\n try {\n // @ts-expect-error undici types not available in all environments\n const { ProxyAgent, setGlobalDispatcher } = await import(\"undici\");\n setGlobalDispatcher(new ProxyAgent(proxyUrl));\n } catch {\n console.error(\"Warning: Proxy support requires Node.js 20+. HTTPS_PROXY will be ignored.\");\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -125,10 +125,7 @@ Threshold breached: ${formatSize(analysis.totalCompressed)} > ${opts.threshold}
125
125
  bundle.command("compare <file1> <file2>").description("Compare size differences between two bundles or APKs").action(async (file1, file2) => {
126
126
  const format = getOutputFormat(program, await getConfig());
127
127
  try {
128
- const [before, after] = await Promise.all([
129
- analyzeBundle(file1),
130
- analyzeBundle(file2)
131
- ]);
128
+ const [before, after] = await Promise.all([analyzeBundle(file1), analyzeBundle(file2)]);
132
129
  const comparison = compareBundles(before, after);
133
130
  if (format === "json") {
134
131
  console.log(formatOutput(comparison, format));
@@ -150,9 +147,15 @@ Threshold breached: ${formatSize(analysis.totalCompressed)} > ${opts.threshold}
150
147
  console.log();
151
148
  console.log(`| | Path | Size |`);
152
149
  console.log(`| --- | --- | --- |`);
153
- console.log(`| Before | \`${comparison.before.path}\` | ${formatSize(comparison.before.totalCompressed)} |`);
154
- console.log(`| After | \`${comparison.after.path}\` | ${formatSize(comparison.after.totalCompressed)} |`);
155
- console.log(`| **Delta** | | **${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)** |`);
150
+ console.log(
151
+ `| Before | \`${comparison.before.path}\` | ${formatSize(comparison.before.totalCompressed)} |`
152
+ );
153
+ console.log(
154
+ `| After | \`${comparison.after.path}\` | ${formatSize(comparison.after.totalCompressed)} |`
155
+ );
156
+ console.log(
157
+ `| **Delta** | | **${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)** |`
158
+ );
156
159
  if (moduleRows.length > 0) {
157
160
  console.log();
158
161
  console.log(`### Module Changes`);
@@ -167,11 +170,17 @@ Threshold breached: ${formatSize(analysis.totalCompressed)} > ${opts.threshold}
167
170
  }
168
171
  } else {
169
172
  const sign = comparison.sizeDelta >= 0 ? "+" : "";
170
- console.log(`
171
- Before: ${comparison.before.path} (${formatSize(comparison.before.totalCompressed)})`);
172
- console.log(`After: ${comparison.after.path} (${formatSize(comparison.after.totalCompressed)})`);
173
- console.log(`Delta: ${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)
174
- `);
173
+ console.log(
174
+ `
175
+ Before: ${comparison.before.path} (${formatSize(comparison.before.totalCompressed)})`
176
+ );
177
+ console.log(
178
+ `After: ${comparison.after.path} (${formatSize(comparison.after.totalCompressed)})`
179
+ );
180
+ console.log(
181
+ `Delta: ${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)
182
+ `
183
+ );
175
184
  const moduleRows = comparison.moduleDeltas.filter((m) => m.delta !== 0).map((m) => ({
176
185
  module: m.module,
177
186
  before: formatSize(m.before),
@@ -206,4 +215,4 @@ async function getConfig() {
206
215
  export {
207
216
  registerBundleCommands
208
217
  };
209
- //# sourceMappingURL=bundle-7XYHNVNF.js.map
218
+ //# sourceMappingURL=bundle-F43TD2BQ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/bundle.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport {\n analyzeBundle,\n compareBundles,\n topFiles,\n checkBundleSize,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\nfunction formatSize(bytes: number): string {\n const abs = Math.abs(bytes);\n const sign = bytes < 0 ? \"-\" : \"\";\n if (abs < 1024) return `${sign}${abs} B`;\n if (abs < 1024 * 1024) return `${sign}${(abs / 1024).toFixed(1)} KB`;\n return `${sign}${(abs / (1024 * 1024)).toFixed(2)} MB`;\n}\n\nfunction formatDelta(delta: number): string {\n const prefix = delta > 0 ? \"+\" : \"\";\n return `${prefix}${formatSize(delta)}`;\n}\n\nexport function registerBundleCommands(program: Command): void {\n const bundle = program.command(\"bundle\").description(\"Analyze app bundles and APKs\");\n\n bundle\n .command(\"analyze <file>\")\n .description(\"Analyze size breakdown of an AAB or APK\")\n .option(\"--threshold <mb>\", \"Fail if compressed size exceeds threshold (MB)\", parseFloat)\n .option(\"--top <n>\", \"Show top N largest files\", (v) => parseInt(v, 10))\n .option(\"--config <file>\", \"Check against .bundlesize.json thresholds\")\n .action(async (file: string, opts: { threshold?: number; top?: number; config?: string }) => {\n const format = getOutputFormat(program, await getConfig());\n\n try {\n const analysis = await analyzeBundle(file);\n\n if (format === \"json\") {\n console.log(formatOutput(analysis, format));\n } else if (format === \"markdown\") {\n const moduleRows = analysis.modules.map((m) => ({\n module: m.name,\n compressed: formatSize(m.compressedSize),\n uncompressed: formatSize(m.uncompressedSize),\n entries: m.entries,\n }));\n const categoryRows = analysis.categories.map((c) => ({\n category: c.name,\n compressed: formatSize(c.compressedSize),\n uncompressed: formatSize(c.uncompressedSize),\n entries: c.entries,\n }));\n console.log(`## Bundle Analysis: \\`${analysis.filePath}\\``);\n console.log();\n console.log(`| Property | Value |`);\n console.log(`| --- | --- |`);\n console.log(`| Type | ${analysis.fileType.toUpperCase()} |`);\n console.log(`| Total compressed | ${formatSize(analysis.totalCompressed)} |`);\n console.log(`| Total uncompressed | ${formatSize(analysis.totalUncompressed)} |`);\n console.log(`| Entries | ${analysis.entryCount} |`);\n console.log();\n console.log(`### Modules`);\n console.log();\n console.log(formatOutput(moduleRows, \"markdown\"));\n console.log();\n console.log(`### Categories`);\n console.log();\n console.log(formatOutput(categoryRows, \"markdown\"));\n } else {\n console.log(`\\nFile: ${analysis.filePath}`);\n console.log(`Type: ${analysis.fileType.toUpperCase()}`);\n console.log(`Total compressed: ${formatSize(analysis.totalCompressed)}`);\n console.log(`Total uncompressed: ${formatSize(analysis.totalUncompressed)}`);\n console.log(`Entries: ${analysis.entryCount}\\n`);\n\n // Modules table\n const moduleRows = analysis.modules.map((m) => ({\n module: m.name,\n compressed: formatSize(m.compressedSize),\n uncompressed: formatSize(m.uncompressedSize),\n entries: m.entries,\n }));\n console.log(\"Modules:\");\n console.log(formatOutput(moduleRows, \"table\"));\n\n // Categories table\n const categoryRows = analysis.categories.map((c) => ({\n category: c.name,\n compressed: formatSize(c.compressedSize),\n uncompressed: formatSize(c.uncompressedSize),\n entries: c.entries,\n }));\n console.log(\"\\nCategories:\");\n console.log(formatOutput(categoryRows, \"table\"));\n }\n\n // Top N files\n if (opts.top !== undefined) {\n const largest = topFiles(analysis, opts.top);\n const topRows = largest.map((e) => ({\n path: e.path,\n compressed: formatSize(e.compressedSize),\n uncompressed: formatSize(e.uncompressedSize),\n category: e.category,\n }));\n console.log(`\\nTop ${opts.top} files:`);\n console.log(formatOutput(topRows, format === \"json\" ? \"table\" : format));\n }\n\n // .bundlesize.json config check\n if (opts.config) {\n const check = await checkBundleSize(analysis, opts.config);\n if (!check.passed) {\n console.error(`\\nBundle size check failed:`);\n for (const v of check.violations) {\n console.error(` ${v.subject}: ${formatSize(v.actual)} > max ${formatSize(v.max)}`);\n }\n process.exit(6);\n }\n }\n\n // Legacy --threshold check\n if (opts.threshold !== undefined) {\n const thresholdBytes = opts.threshold * 1024 * 1024;\n if (analysis.totalCompressed > thresholdBytes) {\n console.error(\n `\\nThreshold breached: ${formatSize(analysis.totalCompressed)} > ${opts.threshold} MB`,\n );\n process.exit(6);\n }\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n\n bundle\n .command(\"compare <file1> <file2>\")\n .description(\"Compare size differences between two bundles or APKs\")\n .action(async (file1: string, file2: string) => {\n const format = getOutputFormat(program, await getConfig());\n\n try {\n const [before, after] = await Promise.all([\n analyzeBundle(file1),\n analyzeBundle(file2),\n ]);\n const comparison = compareBundles(before, after);\n\n if (format === \"json\") {\n console.log(formatOutput(comparison, format));\n } else if (format === \"markdown\") {\n const sign = comparison.sizeDelta >= 0 ? \"+\" : \"\";\n const moduleRows = comparison.moduleDeltas\n .filter((m) => m.delta !== 0)\n .map((m) => ({\n module: m.module,\n before: formatSize(m.before),\n after: formatSize(m.after),\n delta: formatDelta(m.delta),\n }));\n const categoryRows = comparison.categoryDeltas\n .filter((c) => c.delta !== 0)\n .map((c) => ({\n category: c.category,\n before: formatSize(c.before),\n after: formatSize(c.after),\n delta: formatDelta(c.delta),\n }));\n console.log(`## Bundle Comparison`);\n console.log();\n console.log(`| | Path | Size |`);\n console.log(`| --- | --- | --- |`);\n console.log(`| Before | \\`${comparison.before.path}\\` | ${formatSize(comparison.before.totalCompressed)} |`);\n console.log(`| After | \\`${comparison.after.path}\\` | ${formatSize(comparison.after.totalCompressed)} |`);\n console.log(`| **Delta** | | **${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)** |`);\n if (moduleRows.length > 0) {\n console.log();\n console.log(`### Module Changes`);\n console.log();\n console.log(formatOutput(moduleRows, \"markdown\"));\n }\n if (categoryRows.length > 0) {\n console.log();\n console.log(`### Category Changes`);\n console.log();\n console.log(formatOutput(categoryRows, \"markdown\"));\n }\n } else {\n const sign = comparison.sizeDelta >= 0 ? \"+\" : \"\";\n console.log(`\\nBefore: ${comparison.before.path} (${formatSize(comparison.before.totalCompressed)})`);\n console.log(`After: ${comparison.after.path} (${formatSize(comparison.after.totalCompressed)})`);\n console.log(`Delta: ${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)\\n`);\n\n // Module deltas\n const moduleRows = comparison.moduleDeltas\n .filter((m) => m.delta !== 0)\n .map((m) => ({\n module: m.module,\n before: formatSize(m.before),\n after: formatSize(m.after),\n delta: formatDelta(m.delta),\n }));\n if (moduleRows.length > 0) {\n console.log(\"Module changes:\");\n console.log(formatOutput(moduleRows, \"table\"));\n }\n\n // Category deltas\n const categoryRows = comparison.categoryDeltas\n .filter((c) => c.delta !== 0)\n .map((c) => ({\n category: c.category,\n before: formatSize(c.before),\n after: formatSize(c.after),\n delta: formatDelta(c.delta),\n }));\n if (categoryRows.length > 0) {\n console.log(\"\\nCategory changes:\");\n console.log(formatOutput(categoryRows, \"table\"));\n }\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n}\n\nasync function getConfig() {\n const { loadConfig } = await import(\"@gpc-cli/config\");\n return loadConfig();\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/bundle.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport {\n analyzeBundle,\n compareBundles,\n topFiles,\n checkBundleSize,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\nfunction formatSize(bytes: number): string {\n const abs = Math.abs(bytes);\n const sign = bytes < 0 ? \"-\" : \"\";\n if (abs < 1024) return `${sign}${abs} B`;\n if (abs < 1024 * 1024) return `${sign}${(abs / 1024).toFixed(1)} KB`;\n return `${sign}${(abs / (1024 * 1024)).toFixed(2)} MB`;\n}\n\nfunction formatDelta(delta: number): string {\n const prefix = delta > 0 ? \"+\" : \"\";\n return `${prefix}${formatSize(delta)}`;\n}\n\nexport function registerBundleCommands(program: Command): void {\n const bundle = program.command(\"bundle\").description(\"Analyze app bundles and APKs\");\n\n bundle\n .command(\"analyze <file>\")\n .description(\"Analyze size breakdown of an AAB or APK\")\n .option(\"--threshold <mb>\", \"Fail if compressed size exceeds threshold (MB)\", parseFloat)\n .option(\"--top <n>\", \"Show top N largest files\", (v) => parseInt(v, 10))\n .option(\"--config <file>\", \"Check against .bundlesize.json thresholds\")\n .action(async (file: string, opts: { threshold?: number; top?: number; config?: string }) => {\n const format = getOutputFormat(program, await getConfig());\n\n try {\n const analysis = await analyzeBundle(file);\n\n if (format === \"json\") {\n console.log(formatOutput(analysis, format));\n } else if (format === \"markdown\") {\n const moduleRows = analysis.modules.map((m) => ({\n module: m.name,\n compressed: formatSize(m.compressedSize),\n uncompressed: formatSize(m.uncompressedSize),\n entries: m.entries,\n }));\n const categoryRows = analysis.categories.map((c) => ({\n category: c.name,\n compressed: formatSize(c.compressedSize),\n uncompressed: formatSize(c.uncompressedSize),\n entries: c.entries,\n }));\n console.log(`## Bundle Analysis: \\`${analysis.filePath}\\``);\n console.log();\n console.log(`| Property | Value |`);\n console.log(`| --- | --- |`);\n console.log(`| Type | ${analysis.fileType.toUpperCase()} |`);\n console.log(`| Total compressed | ${formatSize(analysis.totalCompressed)} |`);\n console.log(`| Total uncompressed | ${formatSize(analysis.totalUncompressed)} |`);\n console.log(`| Entries | ${analysis.entryCount} |`);\n console.log();\n console.log(`### Modules`);\n console.log();\n console.log(formatOutput(moduleRows, \"markdown\"));\n console.log();\n console.log(`### Categories`);\n console.log();\n console.log(formatOutput(categoryRows, \"markdown\"));\n } else {\n console.log(`\\nFile: ${analysis.filePath}`);\n console.log(`Type: ${analysis.fileType.toUpperCase()}`);\n console.log(`Total compressed: ${formatSize(analysis.totalCompressed)}`);\n console.log(`Total uncompressed: ${formatSize(analysis.totalUncompressed)}`);\n console.log(`Entries: ${analysis.entryCount}\\n`);\n\n // Modules table\n const moduleRows = analysis.modules.map((m) => ({\n module: m.name,\n compressed: formatSize(m.compressedSize),\n uncompressed: formatSize(m.uncompressedSize),\n entries: m.entries,\n }));\n console.log(\"Modules:\");\n console.log(formatOutput(moduleRows, \"table\"));\n\n // Categories table\n const categoryRows = analysis.categories.map((c) => ({\n category: c.name,\n compressed: formatSize(c.compressedSize),\n uncompressed: formatSize(c.uncompressedSize),\n entries: c.entries,\n }));\n console.log(\"\\nCategories:\");\n console.log(formatOutput(categoryRows, \"table\"));\n }\n\n // Top N files\n if (opts.top !== undefined) {\n const largest = topFiles(analysis, opts.top);\n const topRows = largest.map((e) => ({\n path: e.path,\n compressed: formatSize(e.compressedSize),\n uncompressed: formatSize(e.uncompressedSize),\n category: e.category,\n }));\n console.log(`\\nTop ${opts.top} files:`);\n console.log(formatOutput(topRows, format === \"json\" ? \"table\" : format));\n }\n\n // .bundlesize.json config check\n if (opts.config) {\n const check = await checkBundleSize(analysis, opts.config);\n if (!check.passed) {\n console.error(`\\nBundle size check failed:`);\n for (const v of check.violations) {\n console.error(` ${v.subject}: ${formatSize(v.actual)} > max ${formatSize(v.max)}`);\n }\n process.exit(6);\n }\n }\n\n // Legacy --threshold check\n if (opts.threshold !== undefined) {\n const thresholdBytes = opts.threshold * 1024 * 1024;\n if (analysis.totalCompressed > thresholdBytes) {\n console.error(\n `\\nThreshold breached: ${formatSize(analysis.totalCompressed)} > ${opts.threshold} MB`,\n );\n process.exit(6);\n }\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n\n bundle\n .command(\"compare <file1> <file2>\")\n .description(\"Compare size differences between two bundles or APKs\")\n .action(async (file1: string, file2: string) => {\n const format = getOutputFormat(program, await getConfig());\n\n try {\n const [before, after] = await Promise.all([analyzeBundle(file1), analyzeBundle(file2)]);\n const comparison = compareBundles(before, after);\n\n if (format === \"json\") {\n console.log(formatOutput(comparison, format));\n } else if (format === \"markdown\") {\n const sign = comparison.sizeDelta >= 0 ? \"+\" : \"\";\n const moduleRows = comparison.moduleDeltas\n .filter((m) => m.delta !== 0)\n .map((m) => ({\n module: m.module,\n before: formatSize(m.before),\n after: formatSize(m.after),\n delta: formatDelta(m.delta),\n }));\n const categoryRows = comparison.categoryDeltas\n .filter((c) => c.delta !== 0)\n .map((c) => ({\n category: c.category,\n before: formatSize(c.before),\n after: formatSize(c.after),\n delta: formatDelta(c.delta),\n }));\n console.log(`## Bundle Comparison`);\n console.log();\n console.log(`| | Path | Size |`);\n console.log(`| --- | --- | --- |`);\n console.log(\n `| Before | \\`${comparison.before.path}\\` | ${formatSize(comparison.before.totalCompressed)} |`,\n );\n console.log(\n `| After | \\`${comparison.after.path}\\` | ${formatSize(comparison.after.totalCompressed)} |`,\n );\n console.log(\n `| **Delta** | | **${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)** |`,\n );\n if (moduleRows.length > 0) {\n console.log();\n console.log(`### Module Changes`);\n console.log();\n console.log(formatOutput(moduleRows, \"markdown\"));\n }\n if (categoryRows.length > 0) {\n console.log();\n console.log(`### Category Changes`);\n console.log();\n console.log(formatOutput(categoryRows, \"markdown\"));\n }\n } else {\n const sign = comparison.sizeDelta >= 0 ? \"+\" : \"\";\n console.log(\n `\\nBefore: ${comparison.before.path} (${formatSize(comparison.before.totalCompressed)})`,\n );\n console.log(\n `After: ${comparison.after.path} (${formatSize(comparison.after.totalCompressed)})`,\n );\n console.log(\n `Delta: ${sign}${formatSize(comparison.sizeDelta)} (${sign}${comparison.sizeDeltaPercent}%)\\n`,\n );\n\n // Module deltas\n const moduleRows = comparison.moduleDeltas\n .filter((m) => m.delta !== 0)\n .map((m) => ({\n module: m.module,\n before: formatSize(m.before),\n after: formatSize(m.after),\n delta: formatDelta(m.delta),\n }));\n if (moduleRows.length > 0) {\n console.log(\"Module changes:\");\n console.log(formatOutput(moduleRows, \"table\"));\n }\n\n // Category deltas\n const categoryRows = comparison.categoryDeltas\n .filter((c) => c.delta !== 0)\n .map((c) => ({\n category: c.category,\n before: formatSize(c.before),\n after: formatSize(c.after),\n delta: formatDelta(c.delta),\n }));\n if (categoryRows.length > 0) {\n console.log(\"\\nCategory changes:\");\n console.log(formatOutput(categoryRows, \"table\"));\n }\n }\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n}\n\nasync function getConfig() {\n const { loadConfig } = await import(\"@gpc-cli/config\");\n return loadConfig();\n}\n"],"mappings":"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","names":[]}
@@ -74,7 +74,9 @@ function registerCacheCommand(program) {
74
74
  if (opts.type) {
75
75
  const matcher = FILE_TYPES[opts.type];
76
76
  if (!matcher) {
77
- console.error(`Error: Unknown cache type "${opts.type}". Valid types: ${Object.keys(FILE_TYPES).join(", ")}`);
77
+ console.error(
78
+ `Error: Unknown cache type "${opts.type}". Valid types: ${Object.keys(FILE_TYPES).join(", ")}`
79
+ );
78
80
  process.exit(2);
79
81
  }
80
82
  toDelete = allFiles.filter((f) => matcher(f.name));
@@ -90,7 +92,9 @@ function registerCacheCommand(program) {
90
92
  }
91
93
  const { createInterface } = await import("readline");
92
94
  const rl = createInterface({ input: process.stdin, output: process.stdout });
93
- const answer = await new Promise((resolve) => rl.question("Proceed? [y/N] ", resolve));
95
+ const answer = await new Promise(
96
+ (resolve) => rl.question("Proceed? [y/N] ", resolve)
97
+ );
94
98
  rl.close();
95
99
  if (answer.toLowerCase() !== "y") {
96
100
  console.log("Aborted.");
@@ -111,4 +115,4 @@ function registerCacheCommand(program) {
111
115
  export {
112
116
  registerCacheCommand
113
117
  };
114
- //# sourceMappingURL=cache-K23N6GJR.js.map
118
+ //# sourceMappingURL=cache-SLNFRTI2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/cache.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { readdir, stat, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { getCacheDir } from \"@gpc-cli/config\";\n\nconst FILE_TYPES: Record<string, (name: string) => boolean> = {\n status: (name) => name.startsWith(\"status-\") && name.endsWith(\".json\"),\n token: (name) => name === \"token-cache.json\",\n update: (name) => name === \"update-check.json\",\n};\n\nasync function getCacheFiles(\n cacheDir: string,\n): Promise<{ name: string; path: string; size: number; mtime: Date }[]> {\n let entries: string[];\n try {\n entries = await readdir(cacheDir);\n } catch {\n return [];\n }\n\n const files: { name: string; path: string; size: number; mtime: Date }[] = [];\n for (const entry of entries) {\n if (!entry.endsWith(\".json\")) continue;\n const filePath = join(cacheDir, entry);\n try {\n const info = await stat(filePath);\n if (info.isFile()) {\n files.push({ name: entry, path: filePath, size: info.size, mtime: info.mtime });\n }\n } catch {\n /* ignore */\n }\n }\n return files;\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction fileType(name: string): string {\n for (const [type, matcher] of Object.entries(FILE_TYPES)) {\n if (matcher(name)) return type;\n }\n return \"other\";\n}\n\nexport function registerCacheCommand(program: Command): void {\n const cache = program.command(\"cache\").description(\"Manage local cache files\");\n\n cache\n .command(\"info\")\n .description(\"Show cache directory and total size\")\n .action(async () => {\n const cacheDir = getCacheDir();\n const files = await getCacheFiles(cacheDir);\n const totalSize = files.reduce((sum, f) => sum + f.size, 0);\n console.log(`Cache directory: ${cacheDir}`);\n console.log(`Files: ${files.length}`);\n console.log(`Total size: ${formatBytes(totalSize)}`);\n });\n\n cache\n .command(\"list\")\n .description(\"List all cache files with size and age\")\n .action(async () => {\n const cacheDir = getCacheDir();\n const files = await getCacheFiles(cacheDir);\n if (files.length === 0) {\n console.log(\"No cache files found.\");\n return;\n }\n const now = Date.now();\n for (const f of files) {\n const ageMs = now - f.mtime.getTime();\n const ageMins = Math.floor(ageMs / 60000);\n const ageStr =\n ageMins < 60\n ? `${ageMins}m ago`\n : ageMins < 1440\n ? `${Math.floor(ageMins / 60)}h ago`\n : `${Math.floor(ageMins / 1440)}d ago`;\n const type = fileType(f.name);\n console.log(` ${f.name} [${type}] ${formatBytes(f.size)} ${ageStr}`);\n }\n });\n\n cache\n .command(\"clear\")\n .description(\"Remove cache files\")\n .option(\"--force\", \"Skip confirmation prompt\")\n .option(\"--type <type>\", \"Remove only files of this type (status|token|update)\")\n .action(async (opts) => {\n const cacheDir = getCacheDir();\n const allFiles = await getCacheFiles(cacheDir);\n\n let toDelete = allFiles;\n if (opts.type) {\n const matcher = FILE_TYPES[opts.type];\n if (!matcher) {\n console.error(\n `Error: Unknown cache type \"${opts.type}\". Valid types: ${Object.keys(FILE_TYPES).join(\", \")}`,\n );\n process.exit(2);\n }\n toDelete = allFiles.filter((f) => matcher(f.name));\n }\n\n if (toDelete.length === 0) {\n console.log(\"No cache files to remove.\");\n return;\n }\n\n if (!opts.force) {\n console.log(`About to remove ${toDelete.length} file(s) from ${cacheDir}:`);\n for (const f of toDelete) {\n console.log(` ${f.name} (${formatBytes(f.size)})`);\n }\n const { createInterface } = await import(\"node:readline\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) =>\n rl.question(\"Proceed? [y/N] \", resolve),\n );\n rl.close();\n if (answer.toLowerCase() !== \"y\") {\n console.log(\"Aborted.\");\n return;\n }\n }\n\n let removed = 0;\n for (const f of toDelete) {\n try {\n await unlink(f.path);\n removed++;\n } catch {\n /* ignore */\n }\n }\n console.log(`Removed ${removed} file(s).`);\n });\n}\n"],"mappings":"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","names":[]}