@gpc-cli/core 0.10.1 → 0.10.2
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 +46 -4
- package/dist/index.js +208 -31
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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, EditCommitOptions, Track, ExternallyHostedApk, ExternallyHostedApkResponse, DeobfuscationFileType, UploadProgressEvent, ResumableUploadOptions, Listing, ImageType, CountryAvailability, Image, AppDetails, Review, ReviewReplyResponse, Subscription, SubscriptionOffer, OffersListResponse, BasePlanMigratePricesRequest, InAppProduct, Order, SubscriptionDeferResponse, SubscriptionsV2DeferResponse, ProductPurchase, ProductPurchaseV2, SubscriptionPurchaseV2, VoidedPurchase, UsersApiClient, User, DeveloperLevelPermission, Grant, MetricRow, ReportingDimension, ReportingAggregation, VitalsMetricSet, ReportingApiClient, AnomalyDetectionResponse, MetricSetResponse, ErrorIssuesResponse, ConvertRegionPricesResponse, ReportType, StatsDimension, Testers, AppRecoveryTargeting, AppRecoveryAction, CreateAppRecoveryActionRequest, DataSafetyResponse, DataSafetyRequest, ExternalTransaction, ExternalTransactionRefund, DeviceTierConfig, OneTimeOffer, OneTimeProduct, OneTimeOffersListResponse, OneTimeProductsListResponse, GamesConfigClient, AchievementConfiguration, LeaderboardConfiguration, AchievementConfigurationListResponse, GamesApiClient, Achievement, LeaderboardConfigurationListResponse, Leaderboard, ImageConfiguration, EnterpriseApiClient, CustomApp, GeneratedApksPerSigningKey, Bundle } from '@gpc-cli/api';
|
|
4
|
+
import { PlayApiClient, EditCommitOptions, Track, ExternallyHostedApk, ExternallyHostedApkResponse, DeobfuscationFileType, UploadProgressEvent, ResumableUploadOptions, Listing, ImageType, CountryAvailability, Image, AppDetails, Review, ReviewReplyResponse, Subscription, SubscriptionOffer, OffersListResponse, BasePlanMigratePricesRequest, InAppProduct, ConsumptionUsageEvent, RefundPreference, Order, SubscriptionDeferResponse, SubscriptionsV2DeferResponse, ProductPurchase, ProductPurchaseV2, SubscriptionPurchaseV2, VoidedPurchase, UsersApiClient, User, DeveloperLevelPermission, Grant, MetricRow, ReportingDimension, ReportingAggregation, VitalsMetricSet, ReportingApiClient, AnomalyDetectionResponse, MetricSetResponse, ErrorIssuesResponse, ConvertRegionPricesResponse, ReportType, StatsDimension, Testers, AppRecoveryTargeting, AppRecoveryAction, CreateAppRecoveryActionRequest, DataSafetyResponse, DataSafetyRequest, ExternalTransaction, ExternalTransactionRefund, DeviceTierConfig, OneTimeOffer, OneTimeProduct, OneTimeOffersListResponse, OneTimeProductsListResponse, GamesConfigClient, AchievementConfiguration, LeaderboardConfiguration, AchievementConfigurationListResponse, GamesApiClient, Achievement, LeaderboardConfigurationListResponse, Leaderboard, ImageConfiguration, EnterpriseApiClient, CustomApp, GeneratedApksPerSigningKey, Bundle } from '@gpc-cli/api';
|
|
5
5
|
|
|
6
6
|
declare class GpcError extends Error {
|
|
7
7
|
readonly code: string;
|
|
@@ -367,7 +367,9 @@ declare function pushListings(client: PlayApiClient, packageName: string, dir: s
|
|
|
367
367
|
commitOptions?: EditCommitOptions;
|
|
368
368
|
}): Promise<PushResult | DryRunResult>;
|
|
369
369
|
declare function listImages(client: PlayApiClient, packageName: string, language: string, imageType: ImageType): Promise<Image[]>;
|
|
370
|
-
declare function uploadImage(client: PlayApiClient, packageName: string, language: string, imageType: ImageType, filePath: string, commitOptions?: EditCommitOptions
|
|
370
|
+
declare function uploadImage(client: PlayApiClient, packageName: string, language: string, imageType: ImageType, filePath: string, commitOptions?: EditCommitOptions, uploadOptions?: {
|
|
371
|
+
aiGenerated?: boolean;
|
|
372
|
+
}): Promise<Image>;
|
|
371
373
|
declare function deleteImage(client: PlayApiClient, packageName: string, language: string, imageType: ImageType, imageId: string, commitOptions?: EditCommitOptions): Promise<void>;
|
|
372
374
|
declare function diffListingsCommand(client: PlayApiClient, packageName: string, dir: string): Promise<ListingDiff[]>;
|
|
373
375
|
declare function getCountryAvailability(client: PlayApiClient, packageName: string, track: string): Promise<CountryAvailability>;
|
|
@@ -661,6 +663,32 @@ declare function batchGetOrders(client: PlayApiClient, packageName: string, orde
|
|
|
661
663
|
declare function getProductPurchaseV2(client: PlayApiClient, packageName: string, token: string): Promise<ProductPurchaseV2>;
|
|
662
664
|
declare function cancelSubscriptionV2(client: PlayApiClient, packageName: string, token: string, cancellationType?: string): Promise<void>;
|
|
663
665
|
declare function deferSubscriptionV2(client: PlayApiClient, packageName: string, token: string, deferDuration: string, etag?: string): Promise<SubscriptionsV2DeferResponse>;
|
|
666
|
+
/** CLI-facing refund preference, mapped to the Google Play API enum. */
|
|
667
|
+
type RefundReviewPreference = "approve" | "decline" | "neutral";
|
|
668
|
+
interface ReviewOrderRefundOptions {
|
|
669
|
+
/** Token from the PendingRefundReviewNotification RTDN. */
|
|
670
|
+
pendingRefundToken: string;
|
|
671
|
+
preference: RefundReviewPreference;
|
|
672
|
+
/** Whether a free sample, trial, or functionality info was offered before purchase. */
|
|
673
|
+
sampleContentProvided: boolean;
|
|
674
|
+
consumptionPercentageMilliunits?: number;
|
|
675
|
+
consumptionUsageEvents?: ConsumptionUsageEvent[];
|
|
676
|
+
}
|
|
677
|
+
interface ReviewOrderRefundResult {
|
|
678
|
+
packageName: string;
|
|
679
|
+
orderId: string;
|
|
680
|
+
refundPreference: RefundPreference;
|
|
681
|
+
sampleContentProvided: boolean;
|
|
682
|
+
consumptionPercentageMilliunits?: number;
|
|
683
|
+
consumptionUsageEventCount: number;
|
|
684
|
+
submitted: boolean;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Respond to a chargeback review (PendingRefundReviewNotification) with a refund
|
|
688
|
+
* preference and optional purchase-usage evidence. Google Play expects a response
|
|
689
|
+
* within 24 hours of the notification.
|
|
690
|
+
*/
|
|
691
|
+
declare function reviewOrderRefund(client: PlayApiClient, packageName: string, orderId: string, options: ReviewOrderRefundOptions): Promise<ReviewOrderRefundResult>;
|
|
664
692
|
|
|
665
693
|
declare const PERMISSION_PROPAGATION_WARNING = "Note: Permission changes may take up to 48 hours to propagate.";
|
|
666
694
|
interface ListUsersOptions {
|
|
@@ -1005,7 +1033,9 @@ declare function refundExternalTransaction(client: PlayApiClient, packageName: s
|
|
|
1005
1033
|
|
|
1006
1034
|
declare function listDeviceTiers(client: PlayApiClient, packageName: string): Promise<DeviceTierConfig[]>;
|
|
1007
1035
|
declare function getDeviceTier(client: PlayApiClient, packageName: string, configId: string): Promise<DeviceTierConfig>;
|
|
1008
|
-
declare function createDeviceTier(client: PlayApiClient, packageName: string, config: DeviceTierConfig
|
|
1036
|
+
declare function createDeviceTier(client: PlayApiClient, packageName: string, config: DeviceTierConfig, options?: {
|
|
1037
|
+
allowUnknownDevices?: boolean;
|
|
1038
|
+
}): Promise<DeviceTierConfig>;
|
|
1009
1039
|
|
|
1010
1040
|
declare function listOneTimeProducts(client: PlayApiClient, packageName: string): Promise<OneTimeProductsListResponse>;
|
|
1011
1041
|
declare function getOneTimeProduct(client: PlayApiClient, packageName: string, productId: string): Promise<OneTimeProduct>;
|
|
@@ -1771,6 +1801,16 @@ interface DecodedNotification {
|
|
|
1771
1801
|
productType: number;
|
|
1772
1802
|
refundType?: number;
|
|
1773
1803
|
};
|
|
1804
|
+
/** Chargeback review request — respond within 24h via `orders review-refund`. */
|
|
1805
|
+
pendingRefundReviewNotification?: {
|
|
1806
|
+
version: string;
|
|
1807
|
+
pendingRefundToken: string;
|
|
1808
|
+
orderId: string;
|
|
1809
|
+
/** Pending reviews currently only use CHARGEBACK (7). */
|
|
1810
|
+
refundReason?: number;
|
|
1811
|
+
obfuscatedAccountId?: string;
|
|
1812
|
+
obfuscatedProfileId?: string;
|
|
1813
|
+
};
|
|
1774
1814
|
testNotification?: {
|
|
1775
1815
|
version: string;
|
|
1776
1816
|
};
|
|
@@ -1827,6 +1867,8 @@ interface ImageSyncOptions {
|
|
|
1827
1867
|
delete?: boolean;
|
|
1828
1868
|
dryRun?: boolean;
|
|
1829
1869
|
commitOptions?: EditCommitOptions;
|
|
1870
|
+
/** Attest that the synced images were (or were not) generated by AI. */
|
|
1871
|
+
aiGenerated?: boolean;
|
|
1830
1872
|
}
|
|
1831
1873
|
interface ImageSyncDetail {
|
|
1832
1874
|
language: string;
|
|
@@ -1935,4 +1977,4 @@ declare function readinessBadgeColor(grade: ReadinessGrade): string;
|
|
|
1935
1977
|
declare function readinessBadgeUrl(score: ReadinessScore): string;
|
|
1936
1978
|
declare function readinessBadgeMarkdown(score: ReadinessScore): string;
|
|
1937
1979
|
|
|
1938
|
-
export { ApiError, type ApiSigningFingerprint, type AppInfo, type AppStatus, type ApplyReleaseNotesResult, type AuditEntry, type BatchSyncResult, type BundleAnalysis, type BundleComparison, type BundleEntry, type BundleSizeCheckResult, type BundleSizeConfig, type BundlesWaitOptions, type ChangelogEntry, type ChecklistInput, type ChecklistItem, type ChecklistResult, type CommandContext, type CommitCluster, type CommitResult, ConfigError, type CreateEnterpriseAppParams, DEFAULT_LIMITS, DEFAULT_MODELS, DEFAULT_PREFLIGHT_CONFIG, DEFAULT_WATCH_THRESHOLDS, type DecodedNotification, type DiffToken, type DiscoverPluginsOptions, type DiscoveredPlugin, type DryRunPublishResult, type DryRunResult, type DryRunUploadResult, type ErrorReason, type ExportImagesOptions, type ExportImagesSummary, type FastlaneDetection, type FastlaneLane, type FetchChangelogOptions, type FieldLintResult, type FileValidationResult, type FinancialReportDownload, type FindingSeverity, GOOGLE_PLAY_LANGUAGES, type GameConfigDiff, type GamesPushOptions, type GamesSyncResult, type GenerateOptions, type GeneratedChangelog, type GetAppStatusOptions, type GitNotesOptions, type GitReleaseNotes, type GitRunner, GpcError, type ImageSyncDetail, type ImageSyncOptions, type ImageSyncResult, type ImageValidationResult, type InitOptions, type InitResult, type InternalSharingUploadResult, type KeystoreFingerprint, type ListGamesConfigOptions, type ListIapOptions, type ListReportsResult, type ListSubscriptionsOptions, type ListUsersOptions, type ListVoidedOptions, type ListingDiff, type ListingFieldLimits, type ListingLintResult, type ListingsResult, type LoadedPlugin, type LocaleBundle, type LocaleEntry, type MigrationResult, NetworkError, type OneTimeProductDiff, type OutputMode, PERMISSION_PROPAGATION_WARNING, PLACEHOLDER_TEXT, PLAY_STORE_LIMIT, PROVIDER_WHITELIST, type ParsedCommit, type ParsedManifest, type ParsedMonth, type PlayStoreFormat, type PlayStoreRenderOptions, PluginManager, type PreflightConfig, type PreflightFinding, type PreflightOptions, type PreflightResult, type PreflightScanner, type Provider, type PublishOptions, type PublishResult, type PushResult, type QuotaUsage, RENDERERS, REVIEW_SORT_PRESETS, type RawCommit, type ReadinessBreakdownEntry, type ReadinessGrade, type ReadinessScore, type ReadinessSignal, type ReadinessSignalStatus, type ReleaseDiff, type ReleaseNotesValidation, type ReleaseStatusResult, type Renderer, type ReportObject, type ReportsAuth, type ResolveAiConfigOptions, type ResolveLocalesOptions, type ReviewAnalysis, type ReviewExportOptions, type ReviewSortPreset, type ReviewsFilterOptions, type RevocationRefundType, type RtdnStatus, SECTION_ORDER, SENSITIVE_ARG_KEYS, SENSITIVE_KEYS, SEVERITY_ORDER, type ScaffoldOptions, type ScaffoldResult, type SigningConsistencyResult, type SigningKeyComparison, type Spinner, type StatsReportDownload, type StatusDiff, type StatusRelease, type StatusReviews, type StatusVitalMetric, type SubscriptionAnalytics, type SubscriptionDiff, type SyncResult, type ThresholdResult, type TrainConfig, type TrainState, type TranslateBundleOptions, type TranslatedBundle, type TranslationFailure, type TranslationPath, type TranslationResult, type Translator, type TranslatorConfig, type UploadResult, VALID_WATCH_METRICS, type ValidateCheck, type ValidateOptions, type ValidateResult, type ValidatedPluginApproval, type VersionVitalsComparison, type VersionVitalsRow, type VitalsOverview, type VitalsQueryOptions, type VitalsTrendComparison, type WatchAction, type WatchCallbacks, type WatchConfig, type WatchEvent, type WatchMetric, type WatchOptions, type WatchRollout, type WatchSummary, type WatchVitalReading, type WatchVitalsOptions, type WebhookPayload, type ZipCsvEntry, abortTrain, acknowledgeProductPurchase, activateBasePlan, activateOffer, addRecoveryTargeting, addTesters, advanceTrain, analyzeBundle, analyzeRemoteListings, analyzeReviews, annotateListResult, applyReleaseNotes, assignRelease, batchGetOrders, batchSyncInAppProducts, buildChecklist, buildLocaleBundle, bundleToReleaseNotes, cancelRecoveryAction, cancelSubscriptionPurchase, cancelSubscriptionV2, checkBundleSize, checkSigningConsistency, checkThreshold, classifyError, clearAuditLog, commitWithRescue, compareBundles, compareFingerprints, compareVersionVitals, compareVitalsTrend, computeStatusDiff, consumeProductPurchase, convertRegionPrices, createAchievementConfig, createAuditEntry, createDeviceTier, createEnterpriseApp, createExternalTransaction, createGrant, createInAppProduct, createLeaderboardConfig, createOffer, createOneTimeOffer, createOneTimeProduct, createRecoveryAction, createSpinner, createSubscription, createTrack, createTranslator, deactivateBasePlan, deactivateOffer, decodeCsvText, decodeNotification, decodeStatsCsv, defaultGitRunner, deferSubscriptionPurchase, deferSubscriptionV2, deleteAchievementConfig, deleteBasePlan, deleteGrant, deleteImage, deleteInAppProduct, deleteLeaderboardConfig, deleteListing, deleteOffer, deleteOneTimeOffer, deleteOneTimeProduct, deleteSubscription, deployRecoveryAction, detectFastlane, detectOutputFormat, diffAchievementConfig, diffLeaderboardConfig, diffListings, diffListingsCommand, diffListingsEnhanced, diffOneTimeProduct, diffReleases, diffSubscription, discoverPluginEntries, discoverPlugins, dispatchWebhook, downloadFinancialReport, downloadGeneratedApk, downloadReportObject, downloadStatsReport, exportImages, exportReviews, extractCsvEntriesFromZip, fetchAggregateCost, fetchChangelog, fetchReleaseNotes, findBundle, formatChangelogEntry, formatCustomPayload, formatDiscordPayload, formatJunit, formatMoney, formatNotification, formatOutput, formatPathLabel, formatSlackPayload, formatStatusDiff, formatStatusSummary, formatStatusTable, formatWordDiff, generateChangelog, generateMigrationPlan, generateNotesFromGit, getAchievementConfig, getAllScannerNames, getApiSigningFingerprint, getAppInfo, getAppStatus, getCountryAvailability, getDeviceTier, getExternalTransaction, getInAppProduct, getKeystoreFingerprint, getLeaderboardConfig, getListings, getOffer, getOneTimeOffer, getOneTimeProduct, getOrderDetails, getProductPurchase, getProductPurchaseV2, getQuotaUsage, getReleasesStatus, getReview, getRtdnStatus, getSubscription, getSubscriptionAnalytics, getSubscriptionPurchase, getTrainStatus, getUser, getVitalsAnomalies, getVitalsAnr, getVitalsBattery, getVitalsCrashes, getVitalsErrorCount, getVitalsLmk, getVitalsMemory, getVitalsOverview, getVitalsRendering, getVitalsStartup, gradeFromPercent, gunzipIfNeeded, handleBreach, importDataSafety, importTestersFromCsv, initAudit, initProject, inviteUser, isFinancialReportType, isGzip, isStatsReportType, isValidBcp47, isValidReportType, isValidStatsDimension, isVersionedNotesDir, isZip, lintListing, lintListings, lintLocalListings, listAchievementConfigs, listAchievements, listAuditEvents, listBundles, listDeviceTiers, listGeneratedApks, listGrants, listImages, listInAppProducts, listLeaderboardConfigs, listLeaderboards, listOffers, listOneTimeOffers, listOneTimeProducts, listRecoveryActions, listReportObjects, listReports, listReviews, listSubscriptions, listTesters, listTracks, listUsers, listVoidedPurchases, loadPreflightConfig, loadStatusCache, maybePaginate, migratePrices, monthToken, moreResultsFooter, normalizeFingerprint, parseAppfile, parseCommit, parseFastfile, parseGrantArg, parseKeytoolOutput, parseMonth, parseRemoteUrl, pauseTrain, promoteRelease, publish, publishEnterpriseApp, pullAchievementConfigs, pullLeaderboardConfigs, pullListings, pushAchievementConfigs, pushLeaderboardConfigs, pushListings, readListingsFromDir, readReleaseNotesForVersion, readReleaseNotesFromDir, readinessBadgeColor, readinessBadgeMarkdown, readinessBadgeUrl, redactAuditArgs, redactSensitive, refundExternalTransaction, refundOrder, relativeTime, removeTesters, removeUser, renderChecklistMarkdown, renderJson, renderMarkdown, renderPlayStore, renderPlayStoreJson, renderPlayStoreMd, renderPlayStorePrompt, renderPrompt, replyToReview, reportAccessDeniedError, reportBucketNotFoundError, reportObjectNotFoundError, reportPrefix, resolveAiConfig, resolveLocales, resolveReportsBucket, retryOnUploadNotComplete, revokeSubscriptionPurchase, runPreflight, runWatch, runWatchLoop, safePath, safePathWithin, saveStatusCache, scaffoldPlugin, scoreReadiness, searchAuditEvents, searchVitalsErrors, sendNotification, sendWebhook, setAchievementIcon, setLeaderboardIcon, sha256File, sortResults, sortReviews, startTrain, statusHasBreach, syncImages, syncInAppProducts, topFiles, trackBreachState, translateBundle, updateAchievementConfig, updateAppDetails, updateDataSafety, updateGrant, updateInAppProduct, updateLeaderboardConfig, updateListing, updateOffer, updateOneTimeOffer, updateOneTimeProduct, updateRollout, updateSubscription, updateTrackConfig, updateUser, uploadExternallyHosted, uploadImage, uploadInternalSharing, uploadRelease, validateAndCommit, validateBundleForApply, validateImage, validateLanguageCode, validatePackageName, validatePluginForApproval, validatePreSubmission, validateReleaseNotes, validateSku, validateTrackName, validateUploadFile, validateVersionCode, waitForBundle, waitForBundleProcessing, watchVitalsWithAutoHalt, wordDiff, writeAuditLog, writeListingsToDir, writeMigrationOutput };
|
|
1980
|
+
export { ApiError, type ApiSigningFingerprint, type AppInfo, type AppStatus, type ApplyReleaseNotesResult, type AuditEntry, type BatchSyncResult, type BundleAnalysis, type BundleComparison, type BundleEntry, type BundleSizeCheckResult, type BundleSizeConfig, type BundlesWaitOptions, type ChangelogEntry, type ChecklistInput, type ChecklistItem, type ChecklistResult, type CommandContext, type CommitCluster, type CommitResult, ConfigError, type CreateEnterpriseAppParams, DEFAULT_LIMITS, DEFAULT_MODELS, DEFAULT_PREFLIGHT_CONFIG, DEFAULT_WATCH_THRESHOLDS, type DecodedNotification, type DiffToken, type DiscoverPluginsOptions, type DiscoveredPlugin, type DryRunPublishResult, type DryRunResult, type DryRunUploadResult, type ErrorReason, type ExportImagesOptions, type ExportImagesSummary, type FastlaneDetection, type FastlaneLane, type FetchChangelogOptions, type FieldLintResult, type FileValidationResult, type FinancialReportDownload, type FindingSeverity, GOOGLE_PLAY_LANGUAGES, type GameConfigDiff, type GamesPushOptions, type GamesSyncResult, type GenerateOptions, type GeneratedChangelog, type GetAppStatusOptions, type GitNotesOptions, type GitReleaseNotes, type GitRunner, GpcError, type ImageSyncDetail, type ImageSyncOptions, type ImageSyncResult, type ImageValidationResult, type InitOptions, type InitResult, type InternalSharingUploadResult, type KeystoreFingerprint, type ListGamesConfigOptions, type ListIapOptions, type ListReportsResult, type ListSubscriptionsOptions, type ListUsersOptions, type ListVoidedOptions, type ListingDiff, type ListingFieldLimits, type ListingLintResult, type ListingsResult, type LoadedPlugin, type LocaleBundle, type LocaleEntry, type MigrationResult, NetworkError, type OneTimeProductDiff, type OutputMode, PERMISSION_PROPAGATION_WARNING, PLACEHOLDER_TEXT, PLAY_STORE_LIMIT, PROVIDER_WHITELIST, type ParsedCommit, type ParsedManifest, type ParsedMonth, type PlayStoreFormat, type PlayStoreRenderOptions, PluginManager, type PreflightConfig, type PreflightFinding, type PreflightOptions, type PreflightResult, type PreflightScanner, type Provider, type PublishOptions, type PublishResult, type PushResult, type QuotaUsage, RENDERERS, REVIEW_SORT_PRESETS, type RawCommit, type ReadinessBreakdownEntry, type ReadinessGrade, type ReadinessScore, type ReadinessSignal, type ReadinessSignalStatus, type RefundReviewPreference, type ReleaseDiff, type ReleaseNotesValidation, type ReleaseStatusResult, type Renderer, type ReportObject, type ReportsAuth, type ResolveAiConfigOptions, type ResolveLocalesOptions, type ReviewAnalysis, type ReviewExportOptions, type ReviewOrderRefundOptions, type ReviewOrderRefundResult, type ReviewSortPreset, type ReviewsFilterOptions, type RevocationRefundType, type RtdnStatus, SECTION_ORDER, SENSITIVE_ARG_KEYS, SENSITIVE_KEYS, SEVERITY_ORDER, type ScaffoldOptions, type ScaffoldResult, type SigningConsistencyResult, type SigningKeyComparison, type Spinner, type StatsReportDownload, type StatusDiff, type StatusRelease, type StatusReviews, type StatusVitalMetric, type SubscriptionAnalytics, type SubscriptionDiff, type SyncResult, type ThresholdResult, type TrainConfig, type TrainState, type TranslateBundleOptions, type TranslatedBundle, type TranslationFailure, type TranslationPath, type TranslationResult, type Translator, type TranslatorConfig, type UploadResult, VALID_WATCH_METRICS, type ValidateCheck, type ValidateOptions, type ValidateResult, type ValidatedPluginApproval, type VersionVitalsComparison, type VersionVitalsRow, type VitalsOverview, type VitalsQueryOptions, type VitalsTrendComparison, type WatchAction, type WatchCallbacks, type WatchConfig, type WatchEvent, type WatchMetric, type WatchOptions, type WatchRollout, type WatchSummary, type WatchVitalReading, type WatchVitalsOptions, type WebhookPayload, type ZipCsvEntry, abortTrain, acknowledgeProductPurchase, activateBasePlan, activateOffer, addRecoveryTargeting, addTesters, advanceTrain, analyzeBundle, analyzeRemoteListings, analyzeReviews, annotateListResult, applyReleaseNotes, assignRelease, batchGetOrders, batchSyncInAppProducts, buildChecklist, buildLocaleBundle, bundleToReleaseNotes, cancelRecoveryAction, cancelSubscriptionPurchase, cancelSubscriptionV2, checkBundleSize, checkSigningConsistency, checkThreshold, classifyError, clearAuditLog, commitWithRescue, compareBundles, compareFingerprints, compareVersionVitals, compareVitalsTrend, computeStatusDiff, consumeProductPurchase, convertRegionPrices, createAchievementConfig, createAuditEntry, createDeviceTier, createEnterpriseApp, createExternalTransaction, createGrant, createInAppProduct, createLeaderboardConfig, createOffer, createOneTimeOffer, createOneTimeProduct, createRecoveryAction, createSpinner, createSubscription, createTrack, createTranslator, deactivateBasePlan, deactivateOffer, decodeCsvText, decodeNotification, decodeStatsCsv, defaultGitRunner, deferSubscriptionPurchase, deferSubscriptionV2, deleteAchievementConfig, deleteBasePlan, deleteGrant, deleteImage, deleteInAppProduct, deleteLeaderboardConfig, deleteListing, deleteOffer, deleteOneTimeOffer, deleteOneTimeProduct, deleteSubscription, deployRecoveryAction, detectFastlane, detectOutputFormat, diffAchievementConfig, diffLeaderboardConfig, diffListings, diffListingsCommand, diffListingsEnhanced, diffOneTimeProduct, diffReleases, diffSubscription, discoverPluginEntries, discoverPlugins, dispatchWebhook, downloadFinancialReport, downloadGeneratedApk, downloadReportObject, downloadStatsReport, exportImages, exportReviews, extractCsvEntriesFromZip, fetchAggregateCost, fetchChangelog, fetchReleaseNotes, findBundle, formatChangelogEntry, formatCustomPayload, formatDiscordPayload, formatJunit, formatMoney, formatNotification, formatOutput, formatPathLabel, formatSlackPayload, formatStatusDiff, formatStatusSummary, formatStatusTable, formatWordDiff, generateChangelog, generateMigrationPlan, generateNotesFromGit, getAchievementConfig, getAllScannerNames, getApiSigningFingerprint, getAppInfo, getAppStatus, getCountryAvailability, getDeviceTier, getExternalTransaction, getInAppProduct, getKeystoreFingerprint, getLeaderboardConfig, getListings, getOffer, getOneTimeOffer, getOneTimeProduct, getOrderDetails, getProductPurchase, getProductPurchaseV2, getQuotaUsage, getReleasesStatus, getReview, getRtdnStatus, getSubscription, getSubscriptionAnalytics, getSubscriptionPurchase, getTrainStatus, getUser, getVitalsAnomalies, getVitalsAnr, getVitalsBattery, getVitalsCrashes, getVitalsErrorCount, getVitalsLmk, getVitalsMemory, getVitalsOverview, getVitalsRendering, getVitalsStartup, gradeFromPercent, gunzipIfNeeded, handleBreach, importDataSafety, importTestersFromCsv, initAudit, initProject, inviteUser, isFinancialReportType, isGzip, isStatsReportType, isValidBcp47, isValidReportType, isValidStatsDimension, isVersionedNotesDir, isZip, lintListing, lintListings, lintLocalListings, listAchievementConfigs, listAchievements, listAuditEvents, listBundles, listDeviceTiers, listGeneratedApks, listGrants, listImages, listInAppProducts, listLeaderboardConfigs, listLeaderboards, listOffers, listOneTimeOffers, listOneTimeProducts, listRecoveryActions, listReportObjects, listReports, listReviews, listSubscriptions, listTesters, listTracks, listUsers, listVoidedPurchases, loadPreflightConfig, loadStatusCache, maybePaginate, migratePrices, monthToken, moreResultsFooter, normalizeFingerprint, parseAppfile, parseCommit, parseFastfile, parseGrantArg, parseKeytoolOutput, parseMonth, parseRemoteUrl, pauseTrain, promoteRelease, publish, publishEnterpriseApp, pullAchievementConfigs, pullLeaderboardConfigs, pullListings, pushAchievementConfigs, pushLeaderboardConfigs, pushListings, readListingsFromDir, readReleaseNotesForVersion, readReleaseNotesFromDir, readinessBadgeColor, readinessBadgeMarkdown, readinessBadgeUrl, redactAuditArgs, redactSensitive, refundExternalTransaction, refundOrder, relativeTime, removeTesters, removeUser, renderChecklistMarkdown, renderJson, renderMarkdown, renderPlayStore, renderPlayStoreJson, renderPlayStoreMd, renderPlayStorePrompt, renderPrompt, replyToReview, reportAccessDeniedError, reportBucketNotFoundError, reportObjectNotFoundError, reportPrefix, resolveAiConfig, resolveLocales, resolveReportsBucket, retryOnUploadNotComplete, reviewOrderRefund, revokeSubscriptionPurchase, runPreflight, runWatch, runWatchLoop, safePath, safePathWithin, saveStatusCache, scaffoldPlugin, scoreReadiness, searchAuditEvents, searchVitalsErrors, sendNotification, sendWebhook, setAchievementIcon, setLeaderboardIcon, sha256File, sortResults, sortReviews, startTrain, statusHasBreach, syncImages, syncInAppProducts, topFiles, trackBreachState, translateBundle, updateAchievementConfig, updateAppDetails, updateDataSafety, updateGrant, updateInAppProduct, updateLeaderboardConfig, updateListing, updateOffer, updateOneTimeOffer, updateOneTimeProduct, updateRollout, updateSubscription, updateTrackConfig, updateUser, uploadExternallyHosted, uploadImage, uploadInternalSharing, uploadRelease, validateAndCommit, validateBundleForApply, validateImage, validateLanguageCode, validatePackageName, validatePluginForApproval, validatePreSubmission, validateReleaseNotes, validateSku, validateTrackName, validateUploadFile, validateVersionCode, waitForBundle, waitForBundleProcessing, watchVitalsWithAutoHalt, wordDiff, writeAuditLog, writeListingsToDir, writeMigrationOutput };
|
package/dist/index.js
CHANGED
|
@@ -1324,7 +1324,7 @@ async function listImages(client, packageName, language, imageType) {
|
|
|
1324
1324
|
throw error;
|
|
1325
1325
|
}
|
|
1326
1326
|
}
|
|
1327
|
-
async function uploadImage(client, packageName, language, imageType, filePath, commitOptions) {
|
|
1327
|
+
async function uploadImage(client, packageName, language, imageType, filePath, commitOptions, uploadOptions) {
|
|
1328
1328
|
validateLanguage(language);
|
|
1329
1329
|
const imageCheck = await validateImage(filePath, imageType);
|
|
1330
1330
|
if (!imageCheck.valid) {
|
|
@@ -1340,7 +1340,14 @@ async function uploadImage(client, packageName, language, imageType, filePath, c
|
|
|
1340
1340
|
}
|
|
1341
1341
|
const edit = await client.edits.insert(packageName);
|
|
1342
1342
|
try {
|
|
1343
|
-
const image = await client.images.upload(
|
|
1343
|
+
const image = await client.images.upload(
|
|
1344
|
+
packageName,
|
|
1345
|
+
edit.id,
|
|
1346
|
+
language,
|
|
1347
|
+
imageType,
|
|
1348
|
+
filePath,
|
|
1349
|
+
uploadOptions
|
|
1350
|
+
);
|
|
1344
1351
|
await validateAndCommit(client, packageName, edit.id, commitOptions);
|
|
1345
1352
|
return image;
|
|
1346
1353
|
} catch (error) {
|
|
@@ -3979,6 +3986,87 @@ async function deferSubscriptionV2(client, packageName, token, deferDuration, et
|
|
|
3979
3986
|
deferralContext: { etag: resolvedEtag, deferDuration }
|
|
3980
3987
|
});
|
|
3981
3988
|
}
|
|
3989
|
+
var REFUND_PREFERENCES = {
|
|
3990
|
+
approve: "APPROVE",
|
|
3991
|
+
decline: "DECLINE",
|
|
3992
|
+
neutral: "NEUTRAL"
|
|
3993
|
+
};
|
|
3994
|
+
var MAX_CONSUMPTION_USAGE_EVENTS = 1e3;
|
|
3995
|
+
var MAX_CONSUMPTION_MILLIUNITS = 1e5;
|
|
3996
|
+
var RFC3339 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;
|
|
3997
|
+
function invalidReviewRefund(message, suggestion) {
|
|
3998
|
+
return new GpcError(message, "ORDER_REVIEW_REFUND_INVALID", 2, suggestion);
|
|
3999
|
+
}
|
|
4000
|
+
async function reviewOrderRefund(client, packageName, orderId, options) {
|
|
4001
|
+
validatePackageName(packageName);
|
|
4002
|
+
if (!orderId.trim()) {
|
|
4003
|
+
throw invalidReviewRefund(
|
|
4004
|
+
"orderId is required",
|
|
4005
|
+
"Pass the order ID from the pending refund review notification"
|
|
4006
|
+
);
|
|
4007
|
+
}
|
|
4008
|
+
const pendingRefundToken = options.pendingRefundToken.trim();
|
|
4009
|
+
if (!pendingRefundToken) {
|
|
4010
|
+
throw invalidReviewRefund(
|
|
4011
|
+
"pendingRefundToken is required and cannot be empty",
|
|
4012
|
+
"Pass --pending-refund-token with the token from the PendingRefundReviewNotification"
|
|
4013
|
+
);
|
|
4014
|
+
}
|
|
4015
|
+
const refundPreference = REFUND_PREFERENCES[options.preference];
|
|
4016
|
+
if (!refundPreference) {
|
|
4017
|
+
throw invalidReviewRefund(
|
|
4018
|
+
`Invalid refund preference "${options.preference}"`,
|
|
4019
|
+
"Use --preference with one of: approve, decline, neutral"
|
|
4020
|
+
);
|
|
4021
|
+
}
|
|
4022
|
+
const milliunits = options.consumptionPercentageMilliunits;
|
|
4023
|
+
if (milliunits !== void 0) {
|
|
4024
|
+
if (!Number.isInteger(milliunits) || milliunits < 0 || milliunits > MAX_CONSUMPTION_MILLIUNITS) {
|
|
4025
|
+
throw invalidReviewRefund(
|
|
4026
|
+
`consumptionPercentageMilliunits must be an integer between 0 and ${MAX_CONSUMPTION_MILLIUNITS}, got ${milliunits}`,
|
|
4027
|
+
"Pass --consumption-percent with a value between 0 and 100"
|
|
4028
|
+
);
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
4031
|
+
const events = options.consumptionUsageEvents ?? [];
|
|
4032
|
+
if (events.length > MAX_CONSUMPTION_USAGE_EVENTS) {
|
|
4033
|
+
throw invalidReviewRefund(
|
|
4034
|
+
`consumptionUsageEvents has ${events.length} entries; Google Play rejects lists over ${MAX_CONSUMPTION_USAGE_EVENTS}`,
|
|
4035
|
+
`Trim the usage-events file to at most ${MAX_CONSUMPTION_USAGE_EVENTS} events`
|
|
4036
|
+
);
|
|
4037
|
+
}
|
|
4038
|
+
events.forEach((event, index) => {
|
|
4039
|
+
const time = event.consumptionTime;
|
|
4040
|
+
if (time !== void 0 && (!RFC3339.test(time) || Number.isNaN(Date.parse(time)))) {
|
|
4041
|
+
throw invalidReviewRefund(
|
|
4042
|
+
`consumptionUsageEvents[${index}].consumptionTime "${time}" is not an RFC 3339 timestamp`,
|
|
4043
|
+
"Use a timestamp like 2026-08-30T10:15:00Z"
|
|
4044
|
+
);
|
|
4045
|
+
}
|
|
4046
|
+
if (event.location && !event.location.regionCode?.trim()) {
|
|
4047
|
+
throw invalidReviewRefund(
|
|
4048
|
+
`consumptionUsageEvents[${index}].location.regionCode is required when a location is supplied`,
|
|
4049
|
+
'Set a CLDR region code such as "US" on each location'
|
|
4050
|
+
);
|
|
4051
|
+
}
|
|
4052
|
+
});
|
|
4053
|
+
await client.orders.reviewRefund(packageName, orderId, {
|
|
4054
|
+
pendingRefundToken,
|
|
4055
|
+
refundPreference,
|
|
4056
|
+
sampleContentProvided: options.sampleContentProvided,
|
|
4057
|
+
...milliunits !== void 0 ? { consumptionPercentageMilliunits: milliunits } : {},
|
|
4058
|
+
...events.length > 0 ? { consumptionUsageEvents: events } : {}
|
|
4059
|
+
});
|
|
4060
|
+
return {
|
|
4061
|
+
packageName,
|
|
4062
|
+
orderId,
|
|
4063
|
+
refundPreference,
|
|
4064
|
+
sampleContentProvided: options.sampleContentProvided,
|
|
4065
|
+
...milliunits !== void 0 ? { consumptionPercentageMilliunits: milliunits } : {},
|
|
4066
|
+
consumptionUsageEventCount: events.length,
|
|
4067
|
+
submitted: true
|
|
4068
|
+
};
|
|
4069
|
+
}
|
|
3982
4070
|
|
|
3983
4071
|
// src/commands/pricing.ts
|
|
3984
4072
|
async function convertRegionPrices(client, packageName, currencyCode, amount) {
|
|
@@ -4796,7 +4884,7 @@ async function getDeviceTier(client, packageName, configId) {
|
|
|
4796
4884
|
}
|
|
4797
4885
|
return client.deviceTiers.get(packageName, configId);
|
|
4798
4886
|
}
|
|
4799
|
-
async function createDeviceTier(client, packageName, config) {
|
|
4887
|
+
async function createDeviceTier(client, packageName, config, options) {
|
|
4800
4888
|
if (!packageName) {
|
|
4801
4889
|
throw new GpcError(
|
|
4802
4890
|
"Package name is required",
|
|
@@ -4813,7 +4901,7 @@ async function createDeviceTier(client, packageName, config) {
|
|
|
4813
4901
|
"Provide a valid config with deviceGroups."
|
|
4814
4902
|
);
|
|
4815
4903
|
}
|
|
4816
|
-
return client.deviceTiers.create(packageName, config);
|
|
4904
|
+
return client.deviceTiers.create(packageName, config, options);
|
|
4817
4905
|
}
|
|
4818
4906
|
|
|
4819
4907
|
// src/commands/one-time-products.ts
|
|
@@ -4857,7 +4945,14 @@ var OTP_ID_FIELDS = /* @__PURE__ */ new Set(["productId", "packageName"]);
|
|
|
4857
4945
|
function deriveOtpUpdateMask(data) {
|
|
4858
4946
|
return Object.keys(data).filter((k) => !OTP_ID_FIELDS.has(k)).join(",");
|
|
4859
4947
|
}
|
|
4860
|
-
var OTP_OFFER_ID_FIELDS = /* @__PURE__ */ new Set([
|
|
4948
|
+
var OTP_OFFER_ID_FIELDS = /* @__PURE__ */ new Set([
|
|
4949
|
+
"packageName",
|
|
4950
|
+
"productId",
|
|
4951
|
+
"purchaseOptionId",
|
|
4952
|
+
"offerId",
|
|
4953
|
+
"state",
|
|
4954
|
+
"regionsVersion"
|
|
4955
|
+
]);
|
|
4861
4956
|
function deriveOtpOfferUpdateMask(data) {
|
|
4862
4957
|
return Object.keys(data).filter((k) => !OTP_OFFER_ID_FIELDS.has(k)).join(",");
|
|
4863
4958
|
}
|
|
@@ -4930,7 +5025,7 @@ async function createOneTimeOffer(client, packageName, productId, data, purchase
|
|
|
4930
5025
|
}
|
|
4931
5026
|
async function updateOneTimeOffer(client, packageName, productId, offerId, data, updateMask, purchaseOptionId = "-", regionsVersion) {
|
|
4932
5027
|
try {
|
|
4933
|
-
const mask = updateMask || deriveOtpOfferUpdateMask(data);
|
|
5028
|
+
const mask = updateMask || deriveOtpOfferUpdateMask(data) || void 0;
|
|
4934
5029
|
return await client.oneTimeProducts.updateOffer(
|
|
4935
5030
|
packageName,
|
|
4936
5031
|
productId,
|
|
@@ -6254,6 +6349,9 @@ var manifestScanner = {
|
|
|
6254
6349
|
requires: ["manifest"],
|
|
6255
6350
|
async scan(ctx) {
|
|
6256
6351
|
const manifest = ctx.manifest;
|
|
6352
|
+
if (!manifest) {
|
|
6353
|
+
throw new Error('The "manifest" scanner requires manifest in the preflight context');
|
|
6354
|
+
}
|
|
6257
6355
|
const findings = [];
|
|
6258
6356
|
const minTargetSdk = ctx.config.targetSdkMinimum;
|
|
6259
6357
|
if (manifest.targetSdk < minTargetSdk) {
|
|
@@ -6569,6 +6667,9 @@ var permissionsScanner = {
|
|
|
6569
6667
|
requires: ["manifest"],
|
|
6570
6668
|
async scan(ctx) {
|
|
6571
6669
|
const manifest = ctx.manifest;
|
|
6670
|
+
if (!manifest) {
|
|
6671
|
+
throw new Error('The "permissions" scanner requires manifest in the preflight context');
|
|
6672
|
+
}
|
|
6572
6673
|
const findings = [];
|
|
6573
6674
|
const allowed = new Set(ctx.config.allowedPermissions);
|
|
6574
6675
|
for (const perm of manifest.permissions) {
|
|
@@ -6712,13 +6813,16 @@ var nativeLibsScanner = {
|
|
|
6712
6813
|
requires: ["zipEntries"],
|
|
6713
6814
|
async scan(ctx) {
|
|
6714
6815
|
const entries = ctx.zipEntries;
|
|
6816
|
+
if (!entries) {
|
|
6817
|
+
throw new Error('The "native-libs" scanner requires zipEntries in the preflight context');
|
|
6818
|
+
}
|
|
6715
6819
|
const findings = [];
|
|
6716
6820
|
const abisFound = /* @__PURE__ */ new Set();
|
|
6717
6821
|
let totalNativeSize = 0;
|
|
6718
6822
|
for (const entry of entries) {
|
|
6719
|
-
const
|
|
6720
|
-
if (
|
|
6721
|
-
abisFound.add(
|
|
6823
|
+
const abi = LIB_PATH_RE.exec(entry.path)?.[1];
|
|
6824
|
+
if (abi) {
|
|
6825
|
+
abisFound.add(abi);
|
|
6722
6826
|
totalNativeSize += entry.uncompressedSize;
|
|
6723
6827
|
}
|
|
6724
6828
|
}
|
|
@@ -6831,6 +6935,9 @@ var metadataScanner = {
|
|
|
6831
6935
|
requires: ["metadataDir"],
|
|
6832
6936
|
async scan(ctx) {
|
|
6833
6937
|
const dir = ctx.metadataDir;
|
|
6938
|
+
if (!dir) {
|
|
6939
|
+
throw new Error('The "metadata" scanner requires metadataDir in the preflight context');
|
|
6940
|
+
}
|
|
6834
6941
|
const findings = [];
|
|
6835
6942
|
let entries;
|
|
6836
6943
|
try {
|
|
@@ -6936,7 +7043,7 @@ var metadataScanner = {
|
|
|
6936
7043
|
});
|
|
6937
7044
|
}
|
|
6938
7045
|
}
|
|
6939
|
-
const defaultLang = locales.includes("en-US") ? "en-US" : locales[0];
|
|
7046
|
+
const defaultLang = locales.includes("en-US") ? "en-US" : locales[0] ?? "en-US";
|
|
6940
7047
|
const privacyPath = join10(dir, defaultLang, "privacy_policy_url.txt");
|
|
6941
7048
|
try {
|
|
6942
7049
|
const url = await readFile13(privacyPath, "utf-8");
|
|
@@ -7079,6 +7186,7 @@ var secretsScanner = {
|
|
|
7079
7186
|
requires: ["sourceDir"],
|
|
7080
7187
|
async scan(ctx) {
|
|
7081
7188
|
const dir = ctx.sourceDir;
|
|
7189
|
+
if (!dir) throw new Error('The "secrets" scanner requires sourceDir in the preflight context');
|
|
7082
7190
|
const findings = [];
|
|
7083
7191
|
const files = await collectSourceFiles(dir, SCAN_EXTENSIONS);
|
|
7084
7192
|
for (const filePath of files) {
|
|
@@ -7091,6 +7199,7 @@ var secretsScanner = {
|
|
|
7091
7199
|
const lines = content.split("\n");
|
|
7092
7200
|
for (let i = 0; i < lines.length; i++) {
|
|
7093
7201
|
const line = lines[i];
|
|
7202
|
+
if (line === void 0) continue;
|
|
7094
7203
|
for (const pattern of SECRET_PATTERNS) {
|
|
7095
7204
|
if (pattern.pattern.test(line)) {
|
|
7096
7205
|
const relativePath = filePath.startsWith(dir) ? filePath.slice(dir.length + 1) : filePath;
|
|
@@ -7167,6 +7276,7 @@ var billingScanner = {
|
|
|
7167
7276
|
requires: ["sourceDir"],
|
|
7168
7277
|
async scan(ctx) {
|
|
7169
7278
|
const dir = ctx.sourceDir;
|
|
7279
|
+
if (!dir) throw new Error('The "billing" scanner requires sourceDir in the preflight context');
|
|
7170
7280
|
const findings = [];
|
|
7171
7281
|
const detectedSdks = /* @__PURE__ */ new Set();
|
|
7172
7282
|
const files = await collectSourceFiles(dir, SCAN_EXTENSIONS2);
|
|
@@ -7233,6 +7343,7 @@ var privacyScanner = {
|
|
|
7233
7343
|
requires: ["sourceDir"],
|
|
7234
7344
|
async scan(ctx) {
|
|
7235
7345
|
const dir = ctx.sourceDir;
|
|
7346
|
+
if (!dir) throw new Error('The "privacy" scanner requires sourceDir in the preflight context');
|
|
7236
7347
|
const findings = [];
|
|
7237
7348
|
const detectedSdks = /* @__PURE__ */ new Set();
|
|
7238
7349
|
const files = await collectSourceFiles(dir, SCAN_EXTENSIONS3);
|
|
@@ -7314,6 +7425,9 @@ var policyScanner = {
|
|
|
7314
7425
|
requires: ["manifest"],
|
|
7315
7426
|
async scan(ctx) {
|
|
7316
7427
|
const manifest = ctx.manifest;
|
|
7428
|
+
if (!manifest) {
|
|
7429
|
+
throw new Error('The "policy" scanner requires manifest in the preflight context');
|
|
7430
|
+
}
|
|
7317
7431
|
const findings = [];
|
|
7318
7432
|
const perms = new Set(manifest.permissions);
|
|
7319
7433
|
if (manifest.targetSdk >= 28) {
|
|
@@ -7423,6 +7537,9 @@ var sizeScanner = {
|
|
|
7423
7537
|
requires: ["zipEntries"],
|
|
7424
7538
|
async scan(ctx) {
|
|
7425
7539
|
const entries = ctx.zipEntries;
|
|
7540
|
+
if (!entries) {
|
|
7541
|
+
throw new Error('The "size" scanner requires zipEntries in the preflight context');
|
|
7542
|
+
}
|
|
7426
7543
|
const findings = [];
|
|
7427
7544
|
const maxMb = ctx.config.maxDownloadSizeMb;
|
|
7428
7545
|
const totalCompressed = entries.reduce((sum, e) => sum + e.compressedSize, 0);
|
|
@@ -7571,12 +7688,12 @@ async function runPreflight(options) {
|
|
|
7571
7688
|
}
|
|
7572
7689
|
const settled = await Promise.allSettled(applicableScanners.map((scanner) => scanner.scan(ctx)));
|
|
7573
7690
|
let findings = [...earlyFindings];
|
|
7574
|
-
for (
|
|
7691
|
+
for (const [i, scanner] of applicableScanners.entries()) {
|
|
7575
7692
|
const result = settled[i];
|
|
7693
|
+
if (!result) continue;
|
|
7576
7694
|
if (result.status === "fulfilled") {
|
|
7577
7695
|
findings.push(...result.value);
|
|
7578
7696
|
} else {
|
|
7579
|
-
const scanner = applicableScanners[i];
|
|
7580
7697
|
findings.push({
|
|
7581
7698
|
scanner: scanner.name,
|
|
7582
7699
|
ruleId: "scanner-error",
|
|
@@ -8167,7 +8284,7 @@ async function fetchChangelog(options) {
|
|
|
8167
8284
|
return releases.filter((r) => r.tag_name.startsWith("v")).map((r) => ({
|
|
8168
8285
|
version: r.tag_name,
|
|
8169
8286
|
title: r.name || r.tag_name,
|
|
8170
|
-
date: r.published_at ? r.published_at.split("T")[0] : "unknown",
|
|
8287
|
+
date: r.published_at ? r.published_at.split("T")[0] ?? "unknown" : "unknown",
|
|
8171
8288
|
body: r.body || "No release notes.",
|
|
8172
8289
|
url: r.html_url
|
|
8173
8290
|
}));
|
|
@@ -8457,12 +8574,14 @@ var TYPE_PRIORITY = {
|
|
|
8457
8574
|
function clusterCommits(commits) {
|
|
8458
8575
|
const n = commits.length;
|
|
8459
8576
|
const parent = Array.from({ length: n }, (_, i) => i);
|
|
8577
|
+
const parentOf = (i) => parent[i] ?? i;
|
|
8460
8578
|
const find = (i) => {
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
|
|
8579
|
+
let cur = i;
|
|
8580
|
+
while (parentOf(cur) !== cur) {
|
|
8581
|
+
parent[cur] = parentOf(parentOf(cur));
|
|
8582
|
+
cur = parentOf(cur);
|
|
8464
8583
|
}
|
|
8465
|
-
return
|
|
8584
|
+
return cur;
|
|
8466
8585
|
};
|
|
8467
8586
|
const union = (i, j) => {
|
|
8468
8587
|
const ri = find(i);
|
|
@@ -8471,20 +8590,32 @@ function clusterCommits(commits) {
|
|
|
8471
8590
|
};
|
|
8472
8591
|
const tokens = commits.map((c) => tokenize2(c.subject));
|
|
8473
8592
|
for (let i = 0; i < n; i++) {
|
|
8593
|
+
const ci = commits[i];
|
|
8594
|
+
const ti = tokens[i];
|
|
8595
|
+
if (ci === void 0 || ti === void 0) continue;
|
|
8474
8596
|
for (let j = i + 1; j < n; j++) {
|
|
8475
|
-
|
|
8597
|
+
const cj = commits[j];
|
|
8598
|
+
const tj = tokens[j];
|
|
8599
|
+
if (cj === void 0 || tj === void 0) continue;
|
|
8600
|
+
if (shouldCluster(ci, cj, ti, tj)) union(i, j);
|
|
8476
8601
|
}
|
|
8477
8602
|
}
|
|
8478
8603
|
const groups = /* @__PURE__ */ new Map();
|
|
8479
8604
|
for (let i = 0; i < n; i++) {
|
|
8605
|
+
const commit = commits[i];
|
|
8606
|
+
if (commit === void 0) continue;
|
|
8480
8607
|
const root = find(i);
|
|
8481
|
-
|
|
8482
|
-
|
|
8608
|
+
let group = groups.get(root);
|
|
8609
|
+
if (!group) {
|
|
8610
|
+
group = [];
|
|
8611
|
+
groups.set(root, group);
|
|
8612
|
+
}
|
|
8613
|
+
group.push(commit);
|
|
8483
8614
|
}
|
|
8484
8615
|
const clusters = [];
|
|
8485
8616
|
for (const [, members] of groups) {
|
|
8486
8617
|
const weight = members.reduce((s, m) => s + m.weight, 0);
|
|
8487
|
-
const primaryType = members.map((m) => m.type).sort((a, b) => (TYPE_PRIORITY[a] ?? 99) - (TYPE_PRIORITY[b] ?? 99))[0];
|
|
8618
|
+
const primaryType = members.map((m) => m.type).sort((a, b) => (TYPE_PRIORITY[a] ?? 99) - (TYPE_PRIORITY[b] ?? 99))[0] ?? "other";
|
|
8488
8619
|
const label = clusterLabel(members);
|
|
8489
8620
|
clusters.push({
|
|
8490
8621
|
id: label.toLowerCase().replace(/\s+/g, "-"),
|
|
@@ -8527,7 +8658,7 @@ function clusterLabel(members) {
|
|
|
8527
8658
|
bestTokenCount = c;
|
|
8528
8659
|
}
|
|
8529
8660
|
}
|
|
8530
|
-
return bestToken ?? members[0]
|
|
8661
|
+
return bestToken ?? members[0]?.subject.slice(0, 30) ?? "changes";
|
|
8531
8662
|
}
|
|
8532
8663
|
function scoreHeadlines(clusters) {
|
|
8533
8664
|
return [...clusters].sort((a, b) => {
|
|
@@ -8596,8 +8727,8 @@ async function generateChangelog(opts = {}, runner = defaultGitRunner) {
|
|
|
8596
8727
|
const headlineCandidates = scoreHeadlines(clusters);
|
|
8597
8728
|
const grouped = {};
|
|
8598
8729
|
for (const c of visible) {
|
|
8599
|
-
|
|
8600
|
-
|
|
8730
|
+
const bucket = grouped[c.type] ??= [];
|
|
8731
|
+
bucket.push(c);
|
|
8601
8732
|
}
|
|
8602
8733
|
warnings.push(...lintJargon(visible));
|
|
8603
8734
|
return {
|
|
@@ -9243,6 +9374,9 @@ var OTP_NOTIFICATION_TYPES = {
|
|
|
9243
9374
|
1: "ONE_TIME_PRODUCT_PURCHASED",
|
|
9244
9375
|
2: "ONE_TIME_PRODUCT_CANCELED"
|
|
9245
9376
|
};
|
|
9377
|
+
var REFUND_REASONS = {
|
|
9378
|
+
7: "CHARGEBACK"
|
|
9379
|
+
};
|
|
9246
9380
|
async function getRtdnStatus(client, packageName) {
|
|
9247
9381
|
try {
|
|
9248
9382
|
const edit = await client.edits.insert(packageName);
|
|
@@ -9309,6 +9443,20 @@ function formatNotification(notification) {
|
|
|
9309
9443
|
purchaseToken: n.purchaseToken.slice(0, 16) + "..."
|
|
9310
9444
|
};
|
|
9311
9445
|
}
|
|
9446
|
+
if (notification.pendingRefundReviewNotification) {
|
|
9447
|
+
const n = notification.pendingRefundReviewNotification;
|
|
9448
|
+
return {
|
|
9449
|
+
...base,
|
|
9450
|
+
type: "pending-refund-review",
|
|
9451
|
+
event: "PENDING_REFUND_REVIEW",
|
|
9452
|
+
orderId: n.orderId,
|
|
9453
|
+
// An absent reason is plain "UNKNOWN"; only an unrecognised value is worth echoing.
|
|
9454
|
+
refundReason: n.refundReason == null ? "UNKNOWN" : REFUND_REASONS[n.refundReason] ?? `UNKNOWN(${n.refundReason})`,
|
|
9455
|
+
// A partial notification (hand-crafted, or a Google field we have not seen
|
|
9456
|
+
// yet) must not crash the decoder.
|
|
9457
|
+
pendingRefundToken: typeof n.pendingRefundToken === "string" ? n.pendingRefundToken.slice(0, 16) + "..." : "(missing)"
|
|
9458
|
+
};
|
|
9459
|
+
}
|
|
9312
9460
|
if (notification.testNotification) {
|
|
9313
9461
|
return { ...base, type: "test", event: "TEST_NOTIFICATION" };
|
|
9314
9462
|
}
|
|
@@ -9538,7 +9686,14 @@ async function syncImages(client, packageName, dir, options) {
|
|
|
9538
9686
|
"Check image dimensions, file size, and format."
|
|
9539
9687
|
);
|
|
9540
9688
|
}
|
|
9541
|
-
await client.images.upload(
|
|
9689
|
+
await client.images.upload(
|
|
9690
|
+
packageName,
|
|
9691
|
+
edit.id,
|
|
9692
|
+
language,
|
|
9693
|
+
imageType,
|
|
9694
|
+
filePath,
|
|
9695
|
+
options?.aiGenerated === void 0 ? void 0 : { aiGenerated: options.aiGenerated }
|
|
9696
|
+
);
|
|
9542
9697
|
}
|
|
9543
9698
|
uploaded++;
|
|
9544
9699
|
details.push({ language, imageType, file, action: "upload", reason });
|
|
@@ -9556,7 +9711,7 @@ async function syncImages(client, packageName, dir, options) {
|
|
|
9556
9711
|
}
|
|
9557
9712
|
continue;
|
|
9558
9713
|
}
|
|
9559
|
-
const localSeq = localFiles.map((file) => localHashes.get(file));
|
|
9714
|
+
const localSeq = localFiles.map((file) => localHashes.get(file) ?? "");
|
|
9560
9715
|
const remoteSeq = remoteImages.map((img) => img.sha256.toLowerCase());
|
|
9561
9716
|
const inOrder = localSeq.length === remoteSeq.length && localSeq.every((hash, i) => hash === remoteSeq[i]);
|
|
9562
9717
|
if (inOrder) {
|
|
@@ -9594,7 +9749,7 @@ async function syncImages(client, packageName, dir, options) {
|
|
|
9594
9749
|
}
|
|
9595
9750
|
for (const file of localFiles) {
|
|
9596
9751
|
const hash = localHashes.get(file);
|
|
9597
|
-
if (remoteSha256Set.has(hash)) {
|
|
9752
|
+
if (hash !== void 0 && remoteSha256Set.has(hash)) {
|
|
9598
9753
|
skipped++;
|
|
9599
9754
|
details.push({ language, imageType, file, action: "skip", reason: "sha256 match" });
|
|
9600
9755
|
} else {
|
|
@@ -9657,7 +9812,8 @@ async function checkSigningConsistency(accessToken, packageName, apiHost = "andr
|
|
|
9657
9812
|
}
|
|
9658
9813
|
const bundlesData = await bundlesResp.json();
|
|
9659
9814
|
const bundles = (bundlesData.bundles ?? []).sort((a, b) => b.versionCode - a.versionCode);
|
|
9660
|
-
|
|
9815
|
+
const [current, previous] = bundles;
|
|
9816
|
+
if (!current) {
|
|
9661
9817
|
throw new GpcError(
|
|
9662
9818
|
"No bundles found for this app",
|
|
9663
9819
|
"NO_BUNDLES",
|
|
@@ -9665,9 +9821,9 @@ async function checkSigningConsistency(accessToken, packageName, apiHost = "andr
|
|
|
9665
9821
|
"Upload at least one AAB with 'gpc publish' before checking signing consistency"
|
|
9666
9822
|
);
|
|
9667
9823
|
}
|
|
9668
|
-
const currentVc =
|
|
9824
|
+
const currentVc = current.versionCode;
|
|
9669
9825
|
const currentFp = await fetchFingerprint(baseUrl, accessToken, currentVc);
|
|
9670
|
-
if (
|
|
9826
|
+
if (!previous) {
|
|
9671
9827
|
return {
|
|
9672
9828
|
currentVersionCode: currentVc,
|
|
9673
9829
|
currentFingerprint: currentFp,
|
|
@@ -9675,7 +9831,7 @@ async function checkSigningConsistency(accessToken, packageName, apiHost = "andr
|
|
|
9675
9831
|
firstRelease: true
|
|
9676
9832
|
};
|
|
9677
9833
|
}
|
|
9678
|
-
const previousVc =
|
|
9834
|
+
const previousVc = previous.versionCode;
|
|
9679
9835
|
const previousFp = await fetchFingerprint(baseUrl, accessToken, previousVc);
|
|
9680
9836
|
const consistent = normalizeFingerprint(currentFp) === normalizeFingerprint(previousFp);
|
|
9681
9837
|
return {
|
|
@@ -9725,6 +9881,8 @@ async function fetchFingerprint(baseUrl, accessToken, versionCode) {
|
|
|
9725
9881
|
var PLAY_CONSOLE_SETTINGS = "https://play.google.com/console/developers/settings";
|
|
9726
9882
|
var VERIFICATION_PAGE = "https://developer.android.com/developer-verification";
|
|
9727
9883
|
var PLAY_APP_SIGNING = "https://support.google.com/googleplay/android-developer/answer/9842756";
|
|
9884
|
+
var QUALITY_REQUIREMENTS_ANNOUNCEMENT = "https://android-developers.googleblog.com/2026/08/app-quality-memory-optimization-secure-onboarding.html";
|
|
9885
|
+
var RESTORE_CREDENTIALS_DOCS = "https://developer.android.com/identity/sign-in/restore-credentials";
|
|
9728
9886
|
function buildChecklist(input) {
|
|
9729
9887
|
const items = [];
|
|
9730
9888
|
const answers = input.interactiveAnswers ?? {};
|
|
@@ -9771,6 +9929,24 @@ function buildChecklist(input) {
|
|
|
9771
9929
|
answers
|
|
9772
9930
|
)
|
|
9773
9931
|
);
|
|
9932
|
+
items.push(
|
|
9933
|
+
resolveManualStep(
|
|
9934
|
+
"memory-quality-thresholds",
|
|
9935
|
+
"Memory quality requirements reviewed",
|
|
9936
|
+
"Starting February 2027, apps and games must meet Google Play's dynamic memory, bitmap memory, and DEX code optimization thresholds (at least 25% coverage using R8 or another shrinking tool); apps that miss them may see reduced visibility and publishing capabilities. Review the dynamic memory metrics, out of memory crash filters, and DEX optimization insights in Play Console under Android vitals. Source: " + QUALITY_REQUIREMENTS_ANNOUNCEMENT,
|
|
9937
|
+
QUALITY_REQUIREMENTS_ANNOUNCEMENT,
|
|
9938
|
+
answers
|
|
9939
|
+
)
|
|
9940
|
+
);
|
|
9941
|
+
items.push(
|
|
9942
|
+
resolveManualStep(
|
|
9943
|
+
"restore-credentials",
|
|
9944
|
+
"Zero-Tap Sign-In (Restore Credentials API) implemented",
|
|
9945
|
+
"Starting April 2027, apps that support user sign-in must restore the signed-in state when a user moves to a new Android device, using the Android Restore Credentials API, to keep full publishing capabilities and optimal Play Store visibility. Games are currently exempt. Adopt the Restore Credentials API in your sign-in flow. Source: " + QUALITY_REQUIREMENTS_ANNOUNCEMENT,
|
|
9946
|
+
RESTORE_CREDENTIALS_DOCS,
|
|
9947
|
+
answers
|
|
9948
|
+
)
|
|
9949
|
+
);
|
|
9774
9950
|
if (input.appAccessible !== void 0) {
|
|
9775
9951
|
items.push({
|
|
9776
9952
|
id: "app-accessible",
|
|
@@ -10174,6 +10350,7 @@ export {
|
|
|
10174
10350
|
resolveLocales,
|
|
10175
10351
|
resolveReportsBucket,
|
|
10176
10352
|
retryOnUploadNotComplete,
|
|
10353
|
+
reviewOrderRefund,
|
|
10177
10354
|
revokeSubscriptionPurchase,
|
|
10178
10355
|
runPreflight,
|
|
10179
10356
|
runWatch,
|