@gpc-cli/core 0.9.75 → 0.9.77
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.js +82 -32
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -3134,7 +3134,9 @@ function formatReviewInsights(analysis) {
|
|
|
3134
3134
|
);
|
|
3135
3135
|
}
|
|
3136
3136
|
if (analysis.keywords.length > 0) {
|
|
3137
|
-
lines.push(
|
|
3137
|
+
lines.push(
|
|
3138
|
+
` keywords ${analysis.keywords.slice(0, 8).map((k) => k.word).join(", ")}`
|
|
3139
|
+
);
|
|
3138
3140
|
}
|
|
3139
3141
|
return lines;
|
|
3140
3142
|
}
|
|
@@ -4823,11 +4825,21 @@ function iconContentType(filePath) {
|
|
|
4823
4825
|
}
|
|
4824
4826
|
async function setAchievementIcon(client, achievementId, filePath) {
|
|
4825
4827
|
validateResourceId(achievementId, "achievement");
|
|
4826
|
-
return client.images.upload(
|
|
4828
|
+
return client.images.upload(
|
|
4829
|
+
achievementId,
|
|
4830
|
+
"ACHIEVEMENT_ICON",
|
|
4831
|
+
filePath,
|
|
4832
|
+
iconContentType(filePath)
|
|
4833
|
+
);
|
|
4827
4834
|
}
|
|
4828
4835
|
async function setLeaderboardIcon(client, leaderboardId, filePath) {
|
|
4829
4836
|
validateResourceId(leaderboardId, "leaderboard");
|
|
4830
|
-
return client.images.upload(
|
|
4837
|
+
return client.images.upload(
|
|
4838
|
+
leaderboardId,
|
|
4839
|
+
"LEADERBOARD_ICON",
|
|
4840
|
+
filePath,
|
|
4841
|
+
iconContentType(filePath)
|
|
4842
|
+
);
|
|
4831
4843
|
}
|
|
4832
4844
|
function safeConfigFilename(id) {
|
|
4833
4845
|
return `${id.replace(/[^a-zA-Z0-9_-]/g, "_")}.json`;
|
|
@@ -5930,8 +5942,8 @@ var RESTRICTED_PERMISSIONS = [
|
|
|
5930
5942
|
permission: "android.permission.READ_CALL_LOG",
|
|
5931
5943
|
severity: "critical",
|
|
5932
5944
|
title: "READ_CALL_LOG requires declaration form",
|
|
5933
|
-
message: "READ_CALL_LOG is restricted to default phone/assistant handler apps.",
|
|
5934
|
-
suggestion: "Remove READ_CALL_LOG unless your app is a default phone or assistant handler.",
|
|
5945
|
+
message: "READ_CALL_LOG is restricted to default phone/assistant handler apps. As of July 15, 2026, account verification via phone call is no longer an accepted use case for the Call Log permissions.",
|
|
5946
|
+
suggestion: "Remove READ_CALL_LOG unless your app is a default phone or assistant handler. For phone-number verification, use the Digital Credentials API; for one-time codes, use the SMS Retriever API instead of reading the call log.",
|
|
5935
5947
|
policyUrl: "https://support.google.com/googleplay/android-developer/answer/10208820"
|
|
5936
5948
|
},
|
|
5937
5949
|
{
|
|
@@ -6863,8 +6875,8 @@ var policyScanner = {
|
|
|
6863
6875
|
ruleId: "policy-developer-verification",
|
|
6864
6876
|
severity: "info",
|
|
6865
6877
|
title: "Developer verification enforcement (Sep 30, 2026)",
|
|
6866
|
-
message: "Google begins enforcing developer verification on September 30, 2026, first in Brazil, Indonesia, Singapore, and Thailand. Apps distributed in those markets need a verified developer identity and a registered package name. Apps using Play App Signing are auto-registered.",
|
|
6867
|
-
suggestion: "Run `gpc verify checklist` to review readiness. This is a distribution-market reminder, not an AAB/APK defect.",
|
|
6878
|
+
message: "Google begins enforcing developer verification on September 30, 2026, first in Brazil, Indonesia, Singapore, and Thailand. Apps distributed in those markets need a verified developer identity and a registered package name. Separately, as of July 15, 2026, all apps on Google Play must be registered in Play Console to meet these requirements, and unregistered apps risk removal from Google Play. Apps using Play App Signing are auto-registered.",
|
|
6879
|
+
suggestion: "Run `gpc verify checklist` to review readiness, including registration of every app on your account. This is a distribution-market and account-registration reminder, not an AAB/APK defect.",
|
|
6868
6880
|
policyUrl: "https://developer.android.com/developer-verification"
|
|
6869
6881
|
});
|
|
6870
6882
|
if (perms.has("android.permission.SYSTEM_ALERT_WINDOW")) {
|
|
@@ -8913,7 +8925,7 @@ async function sha256File(filePath) {
|
|
|
8913
8925
|
}
|
|
8914
8926
|
|
|
8915
8927
|
// src/commands/image-sync.ts
|
|
8916
|
-
import { readdir as readdir7 } from "fs/promises";
|
|
8928
|
+
import { readdir as readdir7, stat as stat10 } from "fs/promises";
|
|
8917
8929
|
import { join as join12, extname as extname5 } from "path";
|
|
8918
8930
|
import { PlayApiError } from "@gpc-cli/api";
|
|
8919
8931
|
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg"]);
|
|
@@ -8943,6 +8955,13 @@ async function scanLanguages(dir) {
|
|
|
8943
8955
|
return [];
|
|
8944
8956
|
}
|
|
8945
8957
|
}
|
|
8958
|
+
async function dirExists(path) {
|
|
8959
|
+
try {
|
|
8960
|
+
return (await stat10(path)).isDirectory();
|
|
8961
|
+
} catch {
|
|
8962
|
+
return false;
|
|
8963
|
+
}
|
|
8964
|
+
}
|
|
8946
8965
|
async function syncImages(client, packageName, dir, options) {
|
|
8947
8966
|
const details = [];
|
|
8948
8967
|
let uploaded = 0;
|
|
@@ -8980,23 +8999,59 @@ async function syncImages(client, packageName, dir, options) {
|
|
|
8980
8999
|
const hash = await sha256File(join12(localDir, file));
|
|
8981
9000
|
localHashes.set(file, hash);
|
|
8982
9001
|
}
|
|
8983
|
-
const
|
|
9002
|
+
const uploadLocal = async (file, reason) => {
|
|
9003
|
+
if (!options?.dryRun) {
|
|
9004
|
+
const filePath = join12(localDir, file);
|
|
9005
|
+
const check = await validateImage(filePath, imageType);
|
|
9006
|
+
if (!check.valid) {
|
|
9007
|
+
throw new GpcError(
|
|
9008
|
+
`Image validation failed for ${language}/${imageType}/${file}: ${check.errors.join("; ")}`,
|
|
9009
|
+
"IMAGE_INVALID",
|
|
9010
|
+
2,
|
|
9011
|
+
"Check image dimensions, file size, and format."
|
|
9012
|
+
);
|
|
9013
|
+
}
|
|
9014
|
+
await client.images.upload(packageName, edit.id, language, imageType, filePath);
|
|
9015
|
+
}
|
|
9016
|
+
uploaded++;
|
|
9017
|
+
details.push({ language, imageType, file, action: "upload", reason });
|
|
9018
|
+
};
|
|
8984
9019
|
if (options?.delete) {
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
if (!options?.dryRun) {
|
|
8988
|
-
await client.images.delete(packageName, edit.id, language, imageType, img.id);
|
|
8989
|
-
}
|
|
8990
|
-
deleted++;
|
|
9020
|
+
if (localFiles.length === 0 && remoteImages.length > 0 && !await dirExists(localDir)) {
|
|
9021
|
+
for (const img of remoteImages) {
|
|
8991
9022
|
details.push({
|
|
8992
9023
|
language,
|
|
8993
9024
|
imageType,
|
|
8994
9025
|
file: img.id,
|
|
8995
|
-
action: "
|
|
8996
|
-
reason: "
|
|
9026
|
+
action: "skip",
|
|
9027
|
+
reason: "no local directory; remote left untouched"
|
|
8997
9028
|
});
|
|
8998
9029
|
}
|
|
9030
|
+
continue;
|
|
8999
9031
|
}
|
|
9032
|
+
const localSeq = localFiles.map((file) => localHashes.get(file));
|
|
9033
|
+
const remoteSeq = remoteImages.map((img) => img.sha256.toLowerCase());
|
|
9034
|
+
const inOrder = localSeq.length === remoteSeq.length && localSeq.every((hash, i) => hash === remoteSeq[i]);
|
|
9035
|
+
if (inOrder) {
|
|
9036
|
+
for (const file of localFiles) {
|
|
9037
|
+
skipped++;
|
|
9038
|
+
details.push({ language, imageType, file, action: "skip", reason: "already in order" });
|
|
9039
|
+
}
|
|
9040
|
+
continue;
|
|
9041
|
+
}
|
|
9042
|
+
if (remoteImages.length > 0) {
|
|
9043
|
+
if (!options?.dryRun) {
|
|
9044
|
+
await client.images.deleteAll(packageName, edit.id, language, imageType);
|
|
9045
|
+
}
|
|
9046
|
+
for (const img of remoteImages) {
|
|
9047
|
+
deleted++;
|
|
9048
|
+
details.push({ language, imageType, file: img.id, action: "delete", reason: "reordering" });
|
|
9049
|
+
}
|
|
9050
|
+
}
|
|
9051
|
+
for (const file of localFiles) {
|
|
9052
|
+
await uploadLocal(file, "reordering");
|
|
9053
|
+
}
|
|
9054
|
+
continue;
|
|
9000
9055
|
}
|
|
9001
9056
|
for (const file of localFiles) {
|
|
9002
9057
|
const hash = localHashes.get(file);
|
|
@@ -9004,21 +9059,7 @@ async function syncImages(client, packageName, dir, options) {
|
|
|
9004
9059
|
skipped++;
|
|
9005
9060
|
details.push({ language, imageType, file, action: "skip", reason: "sha256 match" });
|
|
9006
9061
|
} else {
|
|
9007
|
-
|
|
9008
|
-
const filePath = join12(localDir, file);
|
|
9009
|
-
const check = await validateImage(filePath, imageType);
|
|
9010
|
-
if (!check.valid) {
|
|
9011
|
-
throw new GpcError(
|
|
9012
|
-
`Image validation failed for ${language}/${imageType}/${file}: ${check.errors.join("; ")}`,
|
|
9013
|
-
"IMAGE_INVALID",
|
|
9014
|
-
2,
|
|
9015
|
-
"Check image dimensions, file size, and format."
|
|
9016
|
-
);
|
|
9017
|
-
}
|
|
9018
|
-
await client.images.upload(packageName, edit.id, language, imageType, filePath);
|
|
9019
|
-
}
|
|
9020
|
-
uploaded++;
|
|
9021
|
-
details.push({ language, imageType, file, action: "upload", reason: "new or changed" });
|
|
9062
|
+
await uploadLocal(file, "new or changed");
|
|
9022
9063
|
}
|
|
9023
9064
|
}
|
|
9024
9065
|
}
|
|
@@ -9182,6 +9223,15 @@ function buildChecklist(input) {
|
|
|
9182
9223
|
answers
|
|
9183
9224
|
)
|
|
9184
9225
|
);
|
|
9226
|
+
items.push(
|
|
9227
|
+
resolveManualStep(
|
|
9228
|
+
"all-apps-registered",
|
|
9229
|
+
"All Play apps registered in Play Console",
|
|
9230
|
+
"As of July 15, 2026, every app on your account must be registered in Play Console to meet Android developer verification requirements. Unregistered apps risk removal from Google Play. Apps using Play App Signing are auto-registered; register any others manually.",
|
|
9231
|
+
PLAY_CONSOLE_SETTINGS,
|
|
9232
|
+
answers
|
|
9233
|
+
)
|
|
9234
|
+
);
|
|
9185
9235
|
if (input.appAccessible !== void 0) {
|
|
9186
9236
|
items.push({
|
|
9187
9237
|
id: "app-accessible",
|