@gpc-cli/core 0.9.36 → 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.
- package/dist/index.d.ts +25 -1
- package/dist/index.js +102 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -885,6 +885,8 @@ interface ParsedManifest {
|
|
|
885
885
|
services: ManifestComponent[];
|
|
886
886
|
receivers: ManifestComponent[];
|
|
887
887
|
providers: ManifestComponent[];
|
|
888
|
+
/** Set when the manifest could not be fully parsed — manifest-dependent scanners should skip. */
|
|
889
|
+
_parseError?: string;
|
|
888
890
|
}
|
|
889
891
|
interface ManifestFeature {
|
|
890
892
|
name: string;
|
|
@@ -1174,4 +1176,26 @@ declare function trackBreachState(packageName: string, isBreaching: boolean): Pr
|
|
|
1174
1176
|
declare function sendNotification(title: string, body: string): void;
|
|
1175
1177
|
declare function statusHasBreach(status: AppStatus): boolean;
|
|
1176
1178
|
|
|
1177
|
-
|
|
1179
|
+
interface ChangelogEntry {
|
|
1180
|
+
version: string;
|
|
1181
|
+
title: string;
|
|
1182
|
+
date: string;
|
|
1183
|
+
body: string;
|
|
1184
|
+
url: string;
|
|
1185
|
+
}
|
|
1186
|
+
interface FetchChangelogOptions {
|
|
1187
|
+
limit?: number;
|
|
1188
|
+
version?: string;
|
|
1189
|
+
}
|
|
1190
|
+
/**
|
|
1191
|
+
* Fetch release history from GitHub Releases API.
|
|
1192
|
+
* Public endpoint — no auth required (60 req/hour rate limit).
|
|
1193
|
+
*/
|
|
1194
|
+
declare function fetchChangelog(options?: FetchChangelogOptions): Promise<ChangelogEntry[]>;
|
|
1195
|
+
/**
|
|
1196
|
+
* Format a changelog entry as readable terminal text.
|
|
1197
|
+
* Strips markdown formatting for clean terminal output.
|
|
1198
|
+
*/
|
|
1199
|
+
declare function formatChangelogEntry(entry: ChangelogEntry): string;
|
|
1200
|
+
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -4717,9 +4717,39 @@ async function readAab(aabPath) {
|
|
|
4717
4717
|
`AAB is missing ${MANIFEST_PATH}. This does not appear to be a valid Android App Bundle.`
|
|
4718
4718
|
);
|
|
4719
4719
|
}
|
|
4720
|
-
|
|
4720
|
+
let manifest;
|
|
4721
|
+
try {
|
|
4722
|
+
manifest = decodeManifest(manifestBuf);
|
|
4723
|
+
} catch (err) {
|
|
4724
|
+
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
|
+
}
|
|
4731
|
+
}
|
|
4721
4732
|
return { manifest, entries };
|
|
4722
4733
|
}
|
|
4734
|
+
function createFallbackManifest() {
|
|
4735
|
+
return {
|
|
4736
|
+
packageName: "",
|
|
4737
|
+
versionCode: 0,
|
|
4738
|
+
versionName: "",
|
|
4739
|
+
minSdk: 0,
|
|
4740
|
+
targetSdk: 0,
|
|
4741
|
+
debuggable: false,
|
|
4742
|
+
testOnly: false,
|
|
4743
|
+
usesCleartextTraffic: false,
|
|
4744
|
+
extractNativeLibs: true,
|
|
4745
|
+
permissions: [],
|
|
4746
|
+
features: [],
|
|
4747
|
+
activities: [],
|
|
4748
|
+
services: [],
|
|
4749
|
+
receivers: [],
|
|
4750
|
+
providers: []
|
|
4751
|
+
};
|
|
4752
|
+
}
|
|
4723
4753
|
function openAndScan(aabPath) {
|
|
4724
4754
|
return new Promise((resolve2, reject) => {
|
|
4725
4755
|
yauzlOpen(aabPath, { lazyEntries: true, autoClose: false }, (err, zipfile) => {
|
|
@@ -5868,11 +5898,23 @@ async function runPreflight(options) {
|
|
|
5868
5898
|
failOn: options.failOn ?? fileConfig.failOn ?? DEFAULT_PREFLIGHT_CONFIG.failOn
|
|
5869
5899
|
};
|
|
5870
5900
|
const ctx = { config };
|
|
5901
|
+
const earlyFindings = [];
|
|
5871
5902
|
if (options.aabPath) {
|
|
5872
5903
|
ctx.aabPath = options.aabPath;
|
|
5873
5904
|
const aab = await readAab(options.aabPath);
|
|
5874
5905
|
ctx.manifest = aab.manifest;
|
|
5875
5906
|
ctx.zipEntries = aab.entries;
|
|
5907
|
+
if (aab.manifest._parseError) {
|
|
5908
|
+
earlyFindings.push({
|
|
5909
|
+
scanner: "manifest-parser",
|
|
5910
|
+
ruleId: "manifest-parse-error",
|
|
5911
|
+
severity: "warning",
|
|
5912
|
+
title: "Manifest could not be fully parsed",
|
|
5913
|
+
message: aab.manifest._parseError,
|
|
5914
|
+
suggestion: "Manifest-dependent scanners (manifest, permissions, policy, privacy) were skipped. Other scanners (native-libs, size, secrets, billing) still ran."
|
|
5915
|
+
});
|
|
5916
|
+
ctx.manifest = void 0;
|
|
5917
|
+
}
|
|
5876
5918
|
}
|
|
5877
5919
|
if (options.metadataDir) ctx.metadataDir = options.metadataDir;
|
|
5878
5920
|
if (options.sourceDir) ctx.sourceDir = options.sourceDir;
|
|
@@ -5888,7 +5930,7 @@ async function runPreflight(options) {
|
|
|
5888
5930
|
return true;
|
|
5889
5931
|
});
|
|
5890
5932
|
const settled = await Promise.allSettled(applicableScanners.map((scanner) => scanner.scan(ctx)));
|
|
5891
|
-
let findings = [];
|
|
5933
|
+
let findings = [...earlyFindings];
|
|
5892
5934
|
for (let i = 0; i < settled.length; i++) {
|
|
5893
5935
|
const result = settled[i];
|
|
5894
5936
|
if (result.status === "fulfilled") {
|
|
@@ -6990,6 +7032,62 @@ function sendNotification(title, body) {
|
|
|
6990
7032
|
function statusHasBreach(status) {
|
|
6991
7033
|
return status.vitals.crashes.status === "breach" || status.vitals.anr.status === "breach" || status.vitals.slowStarts.status === "breach" || status.vitals.slowRender.status === "breach";
|
|
6992
7034
|
}
|
|
7035
|
+
|
|
7036
|
+
// src/commands/changelog.ts
|
|
7037
|
+
var GITHUB_RELEASES_URL = "https://api.github.com/repos/yasserstudio/gpc/releases";
|
|
7038
|
+
var DOCS_CHANGELOG_URL = "https://yasserstudio.github.io/gpc/reference/changelog";
|
|
7039
|
+
async function fetchChangelog(options) {
|
|
7040
|
+
const limit = options?.limit ?? 5;
|
|
7041
|
+
const url = options?.version ? `${GITHUB_RELEASES_URL}/tags/${options.version.startsWith("v") ? options.version : `v${options.version}`}` : `${GITHUB_RELEASES_URL}?per_page=${Math.min(limit, 100)}`;
|
|
7042
|
+
const controller = new AbortController();
|
|
7043
|
+
const timer = setTimeout(() => controller.abort(), 1e4);
|
|
7044
|
+
let response;
|
|
7045
|
+
try {
|
|
7046
|
+
response = await fetch(url, {
|
|
7047
|
+
headers: {
|
|
7048
|
+
Accept: "application/vnd.github+json",
|
|
7049
|
+
"User-Agent": "gpc-cli"
|
|
7050
|
+
},
|
|
7051
|
+
signal: controller.signal
|
|
7052
|
+
});
|
|
7053
|
+
} catch {
|
|
7054
|
+
throw new Error(
|
|
7055
|
+
`Could not fetch changelog. View online: ${DOCS_CHANGELOG_URL}`
|
|
7056
|
+
);
|
|
7057
|
+
} finally {
|
|
7058
|
+
clearTimeout(timer);
|
|
7059
|
+
}
|
|
7060
|
+
if (!response.ok) {
|
|
7061
|
+
if (response.status === 404 && options?.version) {
|
|
7062
|
+
throw new Error(
|
|
7063
|
+
`Version ${options.version} not found. Run: gpc changelog --limit 10`
|
|
7064
|
+
);
|
|
7065
|
+
}
|
|
7066
|
+
throw new Error(
|
|
7067
|
+
`GitHub API returned ${response.status}. View online: ${DOCS_CHANGELOG_URL}`
|
|
7068
|
+
);
|
|
7069
|
+
}
|
|
7070
|
+
const data = await response.json();
|
|
7071
|
+
const releases = Array.isArray(data) ? data : [data];
|
|
7072
|
+
return releases.filter((r) => r.tag_name.startsWith("v")).map((r) => ({
|
|
7073
|
+
version: r.tag_name,
|
|
7074
|
+
title: r.name || r.tag_name,
|
|
7075
|
+
date: r.published_at ? r.published_at.split("T")[0] : "unknown",
|
|
7076
|
+
body: r.body || "No release notes.",
|
|
7077
|
+
url: r.html_url
|
|
7078
|
+
}));
|
|
7079
|
+
}
|
|
7080
|
+
function formatChangelogEntry(entry) {
|
|
7081
|
+
const lines = [];
|
|
7082
|
+
lines.push(`${entry.version} \u2014 ${entry.title}`);
|
|
7083
|
+
lines.push(`Released: ${entry.date}`);
|
|
7084
|
+
lines.push("");
|
|
7085
|
+
const body = entry.body.replace(/^### /gm, "").replace(/^## /gm, "").replace(/^# /gm, "").replace(/\*\*(.*?)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").trim();
|
|
7086
|
+
lines.push(body);
|
|
7087
|
+
lines.push("");
|
|
7088
|
+
lines.push(`Full notes: ${entry.url}`);
|
|
7089
|
+
return lines.join("\n");
|
|
7090
|
+
}
|
|
6993
7091
|
export {
|
|
6994
7092
|
ApiError,
|
|
6995
7093
|
ConfigError,
|
|
@@ -7068,7 +7166,9 @@ export {
|
|
|
7068
7166
|
exportDataSafety,
|
|
7069
7167
|
exportImages,
|
|
7070
7168
|
exportReviews,
|
|
7169
|
+
fetchChangelog,
|
|
7071
7170
|
fetchReleaseNotes,
|
|
7171
|
+
formatChangelogEntry,
|
|
7072
7172
|
formatCustomPayload,
|
|
7073
7173
|
formatDiscordPayload,
|
|
7074
7174
|
formatJunit,
|