@gpc-cli/core 0.9.37 → 0.9.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { OutputFormat, ResolvedConfig, WebhookConfig } from '@gpc-cli/config';
2
2
  import { AuthClient } from '@gpc-cli/auth';
3
3
  import { GpcPlugin, PluginManifest, CommandEvent, CommandResult, PluginError, RequestEvent, ResponseEvent, PluginCommand } from '@gpc-cli/plugin-sdk';
4
- import { PlayApiClient, Track, ExternallyHostedApk, ExternallyHostedApkResponse, UploadProgressEvent, ResumableUploadOptions, Listing, ImageType, CountryAvailability, Image, AppDetails, Review, ReviewReplyResponse, Subscription, SubscriptionOffer, OffersListResponse, BasePlanMigratePricesRequest, InAppProduct, SubscriptionDeferResponse, ProductPurchase, SubscriptionPurchaseV2, VoidedPurchase, UsersApiClient, User, DeveloperPermission, Grant, MetricRow, ReportingDimension, ReportingAggregation, VitalsMetricSet, ReportingApiClient, AnomalyDetectionResponse, MetricSetResponse, ErrorIssuesResponse, ConvertRegionPricesResponse, ReportType, StatsDimension, ReportBucket, Testers, AppRecoveryTargeting, AppRecoveryAction, CreateAppRecoveryActionRequest, DataSafety, ExternalTransaction, ExternalTransactionRefund, DeviceTierConfig, OneTimeOffer, OneTimeProduct, OneTimeOffersListResponse, OneTimeProductsListResponse, GamesApiClient, Achievement, GameEvent, Leaderboard, EnterpriseApiClient, CustomApp, GeneratedApk, PurchaseOption, PurchaseOptionsListResponse } from '@gpc-cli/api';
4
+ import { PlayApiClient, Track, ExternallyHostedApk, ExternallyHostedApkResponse, UploadProgressEvent, ResumableUploadOptions, Listing, ImageType, CountryAvailability, Image, AppDetails, Review, ReviewReplyResponse, Subscription, SubscriptionOffer, OffersListResponse, BasePlanMigratePricesRequest, InAppProduct, Order, SubscriptionDeferResponse, SubscriptionsV2DeferResponse, ProductPurchase, ProductPurchaseV2, SubscriptionPurchaseV2, VoidedPurchase, UsersApiClient, User, DeveloperPermission, Grant, MetricRow, ReportingDimension, ReportingAggregation, VitalsMetricSet, ReportingApiClient, AnomalyDetectionResponse, MetricSetResponse, ErrorIssuesResponse, ConvertRegionPricesResponse, ReportType, StatsDimension, ReportBucket, Testers, AppRecoveryTargeting, AppRecoveryAction, CreateAppRecoveryActionRequest, DataSafety, ExternalTransaction, ExternalTransactionRefund, DeviceTierConfig, OneTimeOffer, OneTimeProduct, OneTimeOffersListResponse, OneTimeProductsListResponse, GamesApiClient, Achievement, GameEvent, Leaderboard, EnterpriseApiClient, CustomApp, GeneratedApk, PurchaseOption, PurchaseOptionsListResponse } from '@gpc-cli/api';
5
5
 
6
6
  declare class GpcError extends Error {
7
7
  readonly code: string;
@@ -541,6 +541,11 @@ declare function refundOrder(client: PlayApiClient, packageName: string, orderId
541
541
  fullRefund?: boolean;
542
542
  proratedRefund?: boolean;
543
543
  }): Promise<void>;
544
+ declare function getOrderDetails(client: PlayApiClient, packageName: string, orderId: string): Promise<Order>;
545
+ declare function batchGetOrders(client: PlayApiClient, packageName: string, orderIds: string[]): Promise<Order[]>;
546
+ declare function getProductPurchaseV2(client: PlayApiClient, packageName: string, token: string): Promise<ProductPurchaseV2>;
547
+ declare function cancelSubscriptionV2(client: PlayApiClient, packageName: string, token: string, cancellationType?: string): Promise<void>;
548
+ declare function deferSubscriptionV2(client: PlayApiClient, packageName: string, token: string, desiredExpiryTime: string): Promise<SubscriptionsV2DeferResponse>;
544
549
 
545
550
  declare const PERMISSION_PROPAGATION_WARNING = "Note: Permission changes may take up to 48 hours to propagate.";
546
551
  interface ListUsersOptions {
@@ -1166,6 +1171,7 @@ interface WatchOptions {
1166
1171
  declare function loadStatusCache(packageName: string, ttlSeconds?: number): Promise<AppStatus | null>;
1167
1172
  declare function saveStatusCache(packageName: string, data: AppStatus, ttlSeconds?: number): Promise<void>;
1168
1173
  declare function getAppStatus(client: PlayApiClient, reporting: ReportingApiClient, packageName: string, options?: GetAppStatusOptions): Promise<AppStatus>;
1174
+ declare function relativeTime(isoString: string): string;
1169
1175
  declare function formatStatusTable(status: AppStatus): string;
1170
1176
  declare function formatStatusSummary(status: AppStatus): string;
1171
1177
  declare function computeStatusDiff(prev: AppStatus, curr: AppStatus): StatusDiff;
@@ -1198,4 +1204,4 @@ declare function fetchChangelog(options?: FetchChangelogOptions): Promise<Change
1198
1204
  */
1199
1205
  declare function formatChangelogEntry(entry: ChangelogEntry): string;
1200
1206
 
1201
- export { ApiError, type AppInfo, type AppStatus, type AuditEntry, type BatchSyncResult, type BundleAnalysis, type BundleComparison, type BundleEntry, type BundleSizeCheckResult, type BundleSizeConfig, type ChangelogEntry, type CommandContext, ConfigError, DEFAULT_LIMITS, DEFAULT_PREFLIGHT_CONFIG, type DiffToken, type DiscoverPluginsOptions, type DryRunPublishResult, type DryRunResult, type DryRunUploadResult, type ExportImagesOptions, type ExportImagesSummary, type FastlaneDetection, type FastlaneLane, type FetchChangelogOptions, type FieldLintResult, type FileValidationResult, type FindingSeverity, GOOGLE_PLAY_LANGUAGES, type GetAppStatusOptions, type GitNotesOptions, type GitReleaseNotes, GpcError, type ImageValidationResult, type InitOptions, type InitResult, type InternalSharingUploadResult, type ListIapOptions, type ListSubscriptionsOptions, type ListUsersOptions, type ListVoidedOptions, type ListingDiff, type ListingFieldLimits, type ListingLintResult, type ListingsResult, type LoadedPlugin, type MigrationResult, NetworkError, type OneTimeProductDiff, PERMISSION_PROPAGATION_WARNING, type ParsedManifest, type ParsedMonth, PluginManager, type PreflightConfig, type PreflightFinding, type PreflightOptions, type PreflightResult, type PreflightScanner, type PublishOptions, type PublishResult, type PushResult, type QuotaUsage, type ReleaseDiff, type ReleaseNotesValidation, type ReleaseStatusResult, type ReviewAnalysis, type ReviewExportOptions, type ReviewsFilterOptions, SENSITIVE_ARG_KEYS, SENSITIVE_KEYS, SEVERITY_ORDER, type ScaffoldOptions, type ScaffoldResult, type Spinner, type StatusDiff, type StatusRelease, type StatusReviews, type StatusVitalMetric, type SubscriptionAnalytics, type SubscriptionDiff, type SyncResult, type ThresholdResult, type TrainConfig, type TrainState, type UploadResult, type ValidateCheck, type ValidateOptions, type ValidateResult, type VersionVitalsComparison, type VersionVitalsRow, type VitalsOverview, type VitalsQueryOptions, type VitalsTrendComparison, type WatchOptions, type WatchVitalsOptions, type WebhookPayload, abortTrain, acknowledgeProductPurchase, activateBasePlan, activateOffer, activatePurchaseOption, addRecoveryTargeting, addTesters, advanceTrain, analyzeBundle, analyzeRemoteListings, analyzeReviews, batchSyncInAppProducts, cancelRecoveryAction, cancelSubscriptionPurchase, checkBundleSize, checkThreshold, clearAuditLog, compareBundles, compareVersionVitals, compareVitalsTrend, computeStatusDiff, consumeProductPurchase, convertRegionPrices, createAuditEntry, createDeviceTier, createEnterpriseApp, createExternalTransaction, createGrant, createInAppProduct, createOffer, createOneTimeOffer, createOneTimeProduct, createPurchaseOption, createRecoveryAction, createSpinner, createSubscription, createTrack, deactivateBasePlan, deactivateOffer, deactivatePurchaseOption, deferSubscriptionPurchase, deleteBasePlan, deleteGrant, deleteImage, deleteInAppProduct, deleteListing, deleteOffer, deleteOneTimeOffer, deleteOneTimeProduct, deleteSubscription, deployRecoveryAction, detectFastlane, detectOutputFormat, diffListings, diffListingsCommand, diffListingsEnhanced, diffOneTimeProduct, diffReleases, diffSubscription, discoverPlugins, downloadGeneratedApk, downloadReport, exportDataSafety, exportImages, exportReviews, fetchChangelog, fetchReleaseNotes, formatChangelogEntry, formatCustomPayload, formatDiscordPayload, formatJunit, formatOutput, formatSlackPayload, formatStatusDiff, formatStatusSummary, formatStatusTable, formatWordDiff, generateMigrationPlan, generateNotesFromGit, getAllScannerNames, getAppInfo, getAppStatus, getCountryAvailability, getDataSafety, getDeviceTier, getExternalTransaction, getInAppProduct, getListings, getOffer, getOneTimeOffer, getOneTimeProduct, getProductPurchase, getPurchaseOption, getQuotaUsage, getReleasesStatus, getReview, getSubscription, getSubscriptionAnalytics, getSubscriptionPurchase, getTrainStatus, getUser, getVitalsAnomalies, getVitalsAnr, getVitalsBattery, getVitalsCrashes, getVitalsLmk, getVitalsMemory, getVitalsOverview, getVitalsRendering, getVitalsStartup, importDataSafety, importTestersFromCsv, initAudit, initProject, inviteUser, isFinancialReportType, isStatsReportType, isValidBcp47, isValidReportType, isValidStatsDimension, lintListing, lintListings, lintLocalListings, listAchievements, listAuditEvents, listDeviceTiers, listEnterpriseApps, listEvents, listGeneratedApks, listGrants, listImages, listInAppProducts, listLeaderboards, listOffers, listOneTimeOffers, listOneTimeProducts, listPurchaseOptions, listRecoveryActions, listReports, listReviews, listSubscriptions, listTesters, listTracks, listUsers, listVoidedPurchases, loadPreflightConfig, loadStatusCache, maybePaginate, migratePrices, parseAppfile, parseFastfile, parseGrantArg, parseMonth, pauseTrain, promoteRelease, publish, pullListings, pushListings, readListingsFromDir, readReleaseNotesFromDir, redactAuditArgs, redactSensitive, refundExternalTransaction, refundOrder, refundSubscriptionV2, removeTesters, removeUser, replyToReview, revokeSubscriptionPurchase, runPreflight, runWatchLoop, safePath, safePathWithin, saveStatusCache, scaffoldPlugin, searchAuditEvents, searchVitalsErrors, sendNotification, sendWebhook, sortResults, startTrain, statusHasBreach, syncInAppProducts, topFiles, trackBreachState, updateAppDetails, updateDataSafety, updateGrant, updateInAppProduct, updateListing, updateOffer, updateOneTimeOffer, updateOneTimeProduct, updateRollout, updateSubscription, updateTrackConfig, updateUser, uploadExternallyHosted, uploadImage, uploadInternalSharing, uploadRelease, validateImage, validateLanguageCode, validatePackageName, validatePreSubmission, validateReleaseNotes, validateSku, validateTrackName, validateUploadFile, validateVersionCode, watchVitalsWithAutoHalt, wordDiff, writeAuditLog, writeListingsToDir, writeMigrationOutput };
1207
+ export { ApiError, type AppInfo, type AppStatus, type AuditEntry, type BatchSyncResult, type BundleAnalysis, type BundleComparison, type BundleEntry, type BundleSizeCheckResult, type BundleSizeConfig, type ChangelogEntry, type CommandContext, ConfigError, DEFAULT_LIMITS, DEFAULT_PREFLIGHT_CONFIG, type DiffToken, type DiscoverPluginsOptions, type DryRunPublishResult, type DryRunResult, type DryRunUploadResult, type ExportImagesOptions, type ExportImagesSummary, type FastlaneDetection, type FastlaneLane, type FetchChangelogOptions, type FieldLintResult, type FileValidationResult, type FindingSeverity, GOOGLE_PLAY_LANGUAGES, type GetAppStatusOptions, type GitNotesOptions, type GitReleaseNotes, GpcError, type ImageValidationResult, type InitOptions, type InitResult, type InternalSharingUploadResult, type ListIapOptions, type ListSubscriptionsOptions, type ListUsersOptions, type ListVoidedOptions, type ListingDiff, type ListingFieldLimits, type ListingLintResult, type ListingsResult, type LoadedPlugin, type MigrationResult, NetworkError, type OneTimeProductDiff, PERMISSION_PROPAGATION_WARNING, type ParsedManifest, type ParsedMonth, PluginManager, type PreflightConfig, type PreflightFinding, type PreflightOptions, type PreflightResult, type PreflightScanner, type PublishOptions, type PublishResult, type PushResult, type QuotaUsage, type ReleaseDiff, type ReleaseNotesValidation, type ReleaseStatusResult, type ReviewAnalysis, type ReviewExportOptions, type ReviewsFilterOptions, SENSITIVE_ARG_KEYS, SENSITIVE_KEYS, SEVERITY_ORDER, type ScaffoldOptions, type ScaffoldResult, type Spinner, type StatusDiff, type StatusRelease, type StatusReviews, type StatusVitalMetric, type SubscriptionAnalytics, type SubscriptionDiff, type SyncResult, type ThresholdResult, type TrainConfig, type TrainState, type UploadResult, type ValidateCheck, type ValidateOptions, type ValidateResult, type VersionVitalsComparison, type VersionVitalsRow, type VitalsOverview, type VitalsQueryOptions, type VitalsTrendComparison, type WatchOptions, type WatchVitalsOptions, type WebhookPayload, abortTrain, acknowledgeProductPurchase, activateBasePlan, activateOffer, activatePurchaseOption, addRecoveryTargeting, addTesters, advanceTrain, analyzeBundle, analyzeRemoteListings, analyzeReviews, batchGetOrders, batchSyncInAppProducts, cancelRecoveryAction, cancelSubscriptionPurchase, cancelSubscriptionV2, checkBundleSize, checkThreshold, clearAuditLog, compareBundles, compareVersionVitals, compareVitalsTrend, computeStatusDiff, consumeProductPurchase, convertRegionPrices, createAuditEntry, createDeviceTier, createEnterpriseApp, createExternalTransaction, createGrant, createInAppProduct, createOffer, createOneTimeOffer, createOneTimeProduct, createPurchaseOption, createRecoveryAction, createSpinner, createSubscription, createTrack, deactivateBasePlan, deactivateOffer, deactivatePurchaseOption, deferSubscriptionPurchase, deferSubscriptionV2, deleteBasePlan, deleteGrant, deleteImage, deleteInAppProduct, deleteListing, deleteOffer, deleteOneTimeOffer, deleteOneTimeProduct, deleteSubscription, deployRecoveryAction, detectFastlane, detectOutputFormat, diffListings, diffListingsCommand, diffListingsEnhanced, diffOneTimeProduct, diffReleases, diffSubscription, discoverPlugins, downloadGeneratedApk, downloadReport, exportDataSafety, exportImages, exportReviews, fetchChangelog, fetchReleaseNotes, formatChangelogEntry, formatCustomPayload, formatDiscordPayload, formatJunit, formatOutput, formatSlackPayload, formatStatusDiff, formatStatusSummary, formatStatusTable, formatWordDiff, generateMigrationPlan, generateNotesFromGit, getAllScannerNames, getAppInfo, getAppStatus, getCountryAvailability, getDataSafety, getDeviceTier, getExternalTransaction, getInAppProduct, getListings, getOffer, getOneTimeOffer, getOneTimeProduct, getOrderDetails, getProductPurchase, getProductPurchaseV2, getPurchaseOption, getQuotaUsage, getReleasesStatus, getReview, getSubscription, getSubscriptionAnalytics, getSubscriptionPurchase, getTrainStatus, getUser, getVitalsAnomalies, getVitalsAnr, getVitalsBattery, getVitalsCrashes, getVitalsLmk, getVitalsMemory, getVitalsOverview, getVitalsRendering, getVitalsStartup, importDataSafety, importTestersFromCsv, initAudit, initProject, inviteUser, isFinancialReportType, isStatsReportType, isValidBcp47, isValidReportType, isValidStatsDimension, lintListing, lintListings, lintLocalListings, listAchievements, listAuditEvents, listDeviceTiers, listEnterpriseApps, listEvents, listGeneratedApks, listGrants, listImages, listInAppProducts, listLeaderboards, listOffers, listOneTimeOffers, listOneTimeProducts, listPurchaseOptions, listRecoveryActions, listReports, listReviews, listSubscriptions, listTesters, listTracks, listUsers, listVoidedPurchases, loadPreflightConfig, loadStatusCache, maybePaginate, migratePrices, parseAppfile, parseFastfile, parseGrantArg, parseMonth, pauseTrain, promoteRelease, publish, pullListings, pushListings, readListingsFromDir, readReleaseNotesFromDir, redactAuditArgs, redactSensitive, refundExternalTransaction, refundOrder, refundSubscriptionV2, relativeTime, removeTesters, removeUser, replyToReview, revokeSubscriptionPurchase, runPreflight, runWatchLoop, safePath, safePathWithin, saveStatusCache, scaffoldPlugin, searchAuditEvents, searchVitalsErrors, sendNotification, sendWebhook, sortResults, startTrain, statusHasBreach, syncInAppProducts, topFiles, trackBreachState, updateAppDetails, updateDataSafety, updateGrant, updateInAppProduct, updateListing, updateOffer, updateOneTimeOffer, updateOneTimeProduct, updateRollout, updateSubscription, updateTrackConfig, updateUser, uploadExternallyHosted, uploadImage, uploadInternalSharing, uploadRelease, validateImage, validateLanguageCode, validatePackageName, validatePreSubmission, validateReleaseNotes, validateSku, validateTrackName, validateUploadFile, validateVersionCode, watchVitalsWithAutoHalt, wordDiff, writeAuditLog, writeListingsToDir, writeMigrationOutput };
package/dist/index.js CHANGED
@@ -115,7 +115,7 @@ function redactSensitive(data) {
115
115
  if (typeof data === "object") {
116
116
  const result = {};
117
117
  for (const [key, value] of Object.entries(data)) {
118
- if (SENSITIVE_KEYS.has(key) && typeof value === "string") {
118
+ if (SENSITIVE_KEYS.has(key)) {
119
119
  result[key] = REDACTED;
120
120
  } else {
121
121
  result[key] = redactSensitive(value);
@@ -363,6 +363,10 @@ function formatJunit(data, commandName = "command") {
363
363
  }
364
364
 
365
365
  // src/plugins.ts
366
+ var FIRST_PARTY_PLUGINS = /* @__PURE__ */ new Set([
367
+ "@gpc-cli/plugin-ci",
368
+ "@gpc-cli/plugin-sdk"
369
+ ]);
366
370
  var PluginManager = class {
367
371
  plugins = [];
368
372
  beforeHandlers = [];
@@ -373,7 +377,7 @@ var PluginManager = class {
373
377
  registeredCommands = [];
374
378
  /** Load and register a plugin */
375
379
  async load(plugin, manifest) {
376
- const isTrusted = manifest?.trusted ?? plugin.name.startsWith("@gpc-cli/");
380
+ const isTrusted = manifest?.trusted ?? FIRST_PARTY_PLUGINS.has(plugin.name);
377
381
  if (!isTrusted && manifest?.permissions) {
378
382
  validatePermissions(manifest.permissions);
379
383
  }
@@ -1658,6 +1662,14 @@ async function exportImages(client, packageName, dir, options) {
1658
1662
  const dirPath = join12(dir, task.language, task.imageType);
1659
1663
  await mkdir8(dirPath, { recursive: true });
1660
1664
  const response = await fetch(task.url);
1665
+ if (!response.ok) {
1666
+ throw new GpcError(
1667
+ `Failed to download image: HTTP ${response.status} for ${task.imageType} (${task.language})`,
1668
+ "LISTINGS_IMAGE_DOWNLOAD_FAILED",
1669
+ 4,
1670
+ "Check that the image URL is still valid. Re-run the export to retry."
1671
+ );
1672
+ }
1661
1673
  const buffer = Buffer.from(await response.arrayBuffer());
1662
1674
  const filePath = join12(dirPath, `${task.index}.png`);
1663
1675
  await writeFile10(filePath, buffer);
@@ -3292,6 +3304,35 @@ async function refundOrder(client, packageName, orderId, options) {
3292
3304
  validatePackageName(packageName);
3293
3305
  return client.orders.refund(packageName, orderId, options);
3294
3306
  }
3307
+ async function getOrderDetails(client, packageName, orderId) {
3308
+ validatePackageName(packageName);
3309
+ return client.orders.get(packageName, orderId);
3310
+ }
3311
+ async function batchGetOrders(client, packageName, orderIds) {
3312
+ validatePackageName(packageName);
3313
+ if (orderIds.length === 0) {
3314
+ throw new GpcError("No order IDs provided", "ORDERS_BATCH_EMPTY", 2, "Pass at least one order ID with --ids");
3315
+ }
3316
+ if (orderIds.length > 1e3) {
3317
+ throw new GpcError(`Too many order IDs (${orderIds.length}). Maximum is 1000.`, "ORDERS_BATCH_LIMIT", 2, "Split into multiple requests of 1000 or fewer");
3318
+ }
3319
+ return client.orders.batchGet(packageName, orderIds);
3320
+ }
3321
+ async function getProductPurchaseV2(client, packageName, token) {
3322
+ validatePackageName(packageName);
3323
+ return client.purchases.getProductV2(packageName, token);
3324
+ }
3325
+ async function cancelSubscriptionV2(client, packageName, token, cancellationType) {
3326
+ validatePackageName(packageName);
3327
+ const body = cancellationType ? { cancellationType } : void 0;
3328
+ return client.purchases.cancelSubscriptionV2(packageName, token, body);
3329
+ }
3330
+ async function deferSubscriptionV2(client, packageName, token, desiredExpiryTime) {
3331
+ validatePackageName(packageName);
3332
+ return client.purchases.deferSubscriptionV2(packageName, token, {
3333
+ deferralInfo: { desiredExpiryTime }
3334
+ });
3335
+ }
3295
3336
 
3296
3337
  // src/commands/pricing.ts
3297
3338
  async function convertRegionPrices(client, packageName, currencyCode, amount) {
@@ -3970,7 +4011,7 @@ function createSpinner(message) {
3970
4011
 
3971
4012
  // src/utils/train-state.ts
3972
4013
  import { mkdir as mkdir3, readFile as readFile7, writeFile as writeFile4 } from "fs/promises";
3973
- import { join as join5 } from "path";
4014
+ import { dirname, join as join5 } from "path";
3974
4015
  import { getCacheDir } from "@gpc-cli/config";
3975
4016
  function stateFile(packageName) {
3976
4017
  return join5(getCacheDir(), `train-${packageName}.json`);
@@ -3986,7 +4027,7 @@ async function readTrainState(packageName) {
3986
4027
  }
3987
4028
  async function writeTrainState(packageName, state) {
3988
4029
  const path = stateFile(packageName);
3989
- const dir = path.substring(0, path.lastIndexOf("/"));
4030
+ const dir = dirname(path);
3990
4031
  await mkdir3(dir, { recursive: true });
3991
4032
  await writeFile4(path, JSON.stringify(state, null, 2), "utf-8");
3992
4033
  }
@@ -4085,8 +4126,11 @@ async function advanceTrain(apiClient, reportingClient, packageName) {
4085
4126
  state.status = "paused";
4086
4127
  state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
4087
4128
  await writeTrainState(packageName, state);
4088
- throw new Error(
4089
- `Crash gate failed: ${(value * 100).toFixed(3)}% > max ${state.gates.crashes.max}%. Train paused.`
4129
+ throw new GpcError(
4130
+ `Crash gate failed: ${(value * 100).toFixed(3)}% > max ${state.gates.crashes.max}%. Train paused.`,
4131
+ "TRAIN_CRASH_GATE_FAILED",
4132
+ 6,
4133
+ "Review crash data with: gpc vitals crashes --days 1"
4090
4134
  );
4091
4135
  }
4092
4136
  }
@@ -4099,8 +4143,11 @@ async function advanceTrain(apiClient, reportingClient, packageName) {
4099
4143
  state.status = "paused";
4100
4144
  state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
4101
4145
  await writeTrainState(packageName, state);
4102
- throw new Error(
4103
- `ANR gate failed: ${(value * 100).toFixed(3)}% > max ${state.gates.anr.max}%. Train paused.`
4146
+ throw new GpcError(
4147
+ `ANR gate failed: ${(value * 100).toFixed(3)}% > max ${state.gates.anr.max}%. Train paused.`,
4148
+ "TRAIN_ANR_GATE_FAILED",
4149
+ 6,
4150
+ "Review ANR data with: gpc vitals anr --days 1"
4104
4151
  );
4105
4152
  }
4106
4153
  }
@@ -4110,7 +4157,7 @@ async function advanceTrain(apiClient, reportingClient, packageName) {
4110
4157
  }
4111
4158
  async function executeStage(apiClient, packageName, state, stageIndex) {
4112
4159
  const stage = state.stages[stageIndex];
4113
- if (!stage) throw new Error(`Stage ${stageIndex} not found`);
4160
+ if (!stage) throw new GpcError(`Stage ${stageIndex} not found`, "TRAIN_STAGE_NOT_FOUND", 1, "Check your release train configuration.");
4114
4161
  const rolloutFraction = stage.rollout / 100;
4115
4162
  await updateRollout(apiClient, packageName, stage.track, "increase", rolloutFraction);
4116
4163
  stage.executedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -4556,7 +4603,7 @@ async function loadPreflightConfig(configPath) {
4556
4603
  import { open as yauzlOpen } from "yauzl";
4557
4604
 
4558
4605
  // src/preflight/manifest-parser.ts
4559
- import * as protobuf from "protobufjs";
4606
+ import protobuf from "protobufjs";
4560
4607
  var RESOURCE_IDS = {
4561
4608
  16842752: "theme",
4562
4609
  16842753: "label",
@@ -4722,12 +4769,8 @@ async function readAab(aabPath) {
4722
4769
  manifest = decodeManifest(manifestBuf);
4723
4770
  } catch (err) {
4724
4771
  const errMsg = err instanceof Error ? err.message : String(err);
4725
- if (errMsg.includes("index out of range") || errMsg.includes("invalid wire type")) {
4726
- manifest = createFallbackManifest();
4727
- manifest._parseError = `Manifest could not be fully parsed: ${errMsg}. Manifest-dependent checks will be skipped.`;
4728
- } else {
4729
- throw err;
4730
- }
4772
+ manifest = createFallbackManifest();
4773
+ manifest._parseError = `Manifest could not be fully parsed: ${errMsg}. Manifest-dependent checks will be skipped.`;
4731
4774
  }
4732
4775
  return { manifest, entries };
4733
4776
  }
@@ -6895,9 +6938,15 @@ function formatStatusSummary(status) {
6895
6938
  }
6896
6939
  return parts.join(" \xB7 ") + (statusHasBreach(status) ? " [ALERT]" : "");
6897
6940
  }
6941
+ function latestProductionVersion(releases) {
6942
+ const prod = releases.find((r) => r.track === "production");
6943
+ if (prod) return prod.versionCode;
6944
+ const nonDraft = releases.find((r) => r.status !== "draft");
6945
+ return nonDraft?.versionCode ?? releases[0]?.versionCode ?? null;
6946
+ }
6898
6947
  function computeStatusDiff(prev, curr) {
6899
- const prevVersion = prev.releases[0]?.versionCode ?? null;
6900
- const currVersion = curr.releases[0]?.versionCode ?? null;
6948
+ const prevVersion = latestProductionVersion(prev.releases);
6949
+ const currVersion = latestProductionVersion(curr.releases);
6901
6950
  const prevCrash = prev.vitals.crashes.value ?? null;
6902
6951
  const currCrash = curr.vitals.crashes.value ?? null;
6903
6952
  const prevAnr = prev.vitals.anr.value ?? null;
@@ -6956,8 +7005,6 @@ async function runWatchLoop(opts) {
6956
7005
  let running = true;
6957
7006
  const cleanup = () => {
6958
7007
  running = false;
6959
- process.stdout.write("\n");
6960
- process.exit(0);
6961
7008
  };
6962
7009
  process.on("SIGINT", cleanup);
6963
7010
  process.on("SIGTERM", cleanup);
@@ -7112,9 +7159,11 @@ export {
7112
7159
  analyzeBundle,
7113
7160
  analyzeRemoteListings,
7114
7161
  analyzeReviews2 as analyzeReviews,
7162
+ batchGetOrders,
7115
7163
  batchSyncInAppProducts,
7116
7164
  cancelRecoveryAction,
7117
7165
  cancelSubscriptionPurchase,
7166
+ cancelSubscriptionV2,
7118
7167
  checkBundleSize,
7119
7168
  checkThreshold,
7120
7169
  clearAuditLog,
@@ -7142,6 +7191,7 @@ export {
7142
7191
  deactivateOffer,
7143
7192
  deactivatePurchaseOption,
7144
7193
  deferSubscriptionPurchase,
7194
+ deferSubscriptionV2,
7145
7195
  deleteBasePlan,
7146
7196
  deleteGrant,
7147
7197
  deleteImage,
@@ -7192,7 +7242,9 @@ export {
7192
7242
  getOffer,
7193
7243
  getOneTimeOffer,
7194
7244
  getOneTimeProduct,
7245
+ getOrderDetails,
7195
7246
  getProductPurchase,
7247
+ getProductPurchaseV2,
7196
7248
  getPurchaseOption,
7197
7249
  getQuotaUsage,
7198
7250
  getReleasesStatus,
@@ -7266,6 +7318,7 @@ export {
7266
7318
  refundExternalTransaction,
7267
7319
  refundOrder,
7268
7320
  refundSubscriptionV2,
7321
+ relativeTime,
7269
7322
  removeTesters,
7270
7323
  removeUser,
7271
7324
  replyToReview,