@gpc-cli/api 1.0.25 → 1.0.27
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/README.md +1 -1
- package/dist/index.d.ts +113 -13
- package/dist/index.js +274 -98
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -549,6 +549,31 @@ function enhanceApiError(status, body) {
|
|
|
549
549
|
].join("\n")
|
|
550
550
|
};
|
|
551
551
|
}
|
|
552
|
+
if ((status === 403 || status === 400) && (errorMsg.includes("changes not sent for review") || errorMsg.includes("changesnotsentforreview") || errorMsg.includes("review") && errorMsg.includes("rejected"))) {
|
|
553
|
+
return {
|
|
554
|
+
code: "API_CHANGES_NOT_SENT_FOR_REVIEW",
|
|
555
|
+
message: "This app has a rejected update. The API requires explicit acknowledgement before committing changes.",
|
|
556
|
+
suggestion: [
|
|
557
|
+
"Add --changes-not-sent-for-review to your command:",
|
|
558
|
+
" gpc releases upload app.aab --track internal --changes-not-sent-for-review",
|
|
559
|
+
"",
|
|
560
|
+
"This applies your changes without sending them for review.",
|
|
561
|
+
"You must manually send for review from the Google Play Console when ready."
|
|
562
|
+
].join("\n")
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
if (status === 400 && (errorMsg.includes("changes_already_in_review") || errorMsg.includes("already in review"))) {
|
|
566
|
+
return {
|
|
567
|
+
code: "API_CHANGES_ALREADY_IN_REVIEW",
|
|
568
|
+
message: "Changes are already in review. Committing this edit would cancel the existing review.",
|
|
569
|
+
suggestion: [
|
|
570
|
+
"Wait for the current review to complete, or re-run without --error-if-in-review",
|
|
571
|
+
"to cancel the existing review and submit new changes.",
|
|
572
|
+
"",
|
|
573
|
+
"To prevent accidental review cancellation in CI, keep --error-if-in-review."
|
|
574
|
+
].join("\n")
|
|
575
|
+
};
|
|
576
|
+
}
|
|
552
577
|
return void 0;
|
|
553
578
|
}
|
|
554
579
|
function mapStatusToError(status, body) {
|
|
@@ -733,7 +758,8 @@ function createHttpClient(options) {
|
|
|
733
758
|
return Math.max(timeout, 3e4 + Math.ceil(sizeMb) * 1e3);
|
|
734
759
|
}
|
|
735
760
|
async function uploadRequest(path, filePath, contentType, baseUrl = UPLOAD_BASE_URL) {
|
|
736
|
-
const
|
|
761
|
+
const separator = path.includes("?") ? "&" : "?";
|
|
762
|
+
const url = `${baseUrl}${path}${separator}uploadType=media`;
|
|
737
763
|
const safeFilePath = validateFilePath(filePath);
|
|
738
764
|
const fileBuffer = await readFile(safeFilePath);
|
|
739
765
|
const effectiveTimeout = computeUploadTimeout(fileBuffer.byteLength);
|
|
@@ -942,13 +968,104 @@ function createHttpClient(options) {
|
|
|
942
968
|
};
|
|
943
969
|
}
|
|
944
970
|
|
|
971
|
+
// src/rate-limiter.ts
|
|
972
|
+
var RATE_LIMIT_BUCKETS = {
|
|
973
|
+
edits: { name: "edits", maxTokens: 3e3, refillRate: 3e3, refillIntervalMs: 6e4 },
|
|
974
|
+
purchases: { name: "purchases", maxTokens: 3e3, refillRate: 3e3, refillIntervalMs: 6e4 },
|
|
975
|
+
reviews: { name: "reviews", maxTokens: 3e3, refillRate: 3e3, refillIntervalMs: 6e4 },
|
|
976
|
+
reporting: { name: "reporting", maxTokens: 3e3, refillRate: 3e3, refillIntervalMs: 6e4 },
|
|
977
|
+
monetization: { name: "monetization", maxTokens: 3e3, refillRate: 3e3, refillIntervalMs: 6e4 },
|
|
978
|
+
default: { name: "default", maxTokens: 3e3, refillRate: 3e3, refillIntervalMs: 6e4 }
|
|
979
|
+
};
|
|
980
|
+
function resolveBucket(path) {
|
|
981
|
+
if (path.includes("/edits/") || path.includes("/edits:")) return "edits";
|
|
982
|
+
if (path.includes("/purchases/") || path.includes("/orders")) return "purchases";
|
|
983
|
+
if (path.includes("/reviews")) return "reviews";
|
|
984
|
+
if (path.includes("playdeveloperreporting") || path.includes("MetricSet") || path.includes("anomalies")) return "reporting";
|
|
985
|
+
if (path.includes("/inappproducts") || path.includes("/oneTimeProducts") || path.includes("/subscriptions") || path.includes("/monetization")) return "monetization";
|
|
986
|
+
return "default";
|
|
987
|
+
}
|
|
988
|
+
function createRateLimiter(buckets) {
|
|
989
|
+
const states = /* @__PURE__ */ new Map();
|
|
990
|
+
const effectiveBuckets = buckets ?? Object.values(RATE_LIMIT_BUCKETS);
|
|
991
|
+
for (const bucket of effectiveBuckets) {
|
|
992
|
+
states.set(bucket.name, {
|
|
993
|
+
tokens: bucket.maxTokens,
|
|
994
|
+
lastRefillTime: Date.now(),
|
|
995
|
+
config: bucket
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
return {
|
|
999
|
+
async acquire(bucket) {
|
|
1000
|
+
const state = states.get(bucket);
|
|
1001
|
+
if (!state) return;
|
|
1002
|
+
const now = Date.now();
|
|
1003
|
+
const elapsed = now - state.lastRefillTime;
|
|
1004
|
+
const refill = Math.floor(
|
|
1005
|
+
elapsed / state.config.refillIntervalMs * state.config.refillRate
|
|
1006
|
+
);
|
|
1007
|
+
if (refill > 0) {
|
|
1008
|
+
state.tokens = Math.min(state.config.maxTokens, state.tokens + refill);
|
|
1009
|
+
state.lastRefillTime = now;
|
|
1010
|
+
}
|
|
1011
|
+
if (state.tokens > 0) {
|
|
1012
|
+
state.tokens--;
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
const tokensNeeded = 1;
|
|
1016
|
+
const waitMs = Math.ceil(
|
|
1017
|
+
tokensNeeded / state.config.refillRate * state.config.refillIntervalMs
|
|
1018
|
+
);
|
|
1019
|
+
await new Promise((r) => setTimeout(r, waitMs));
|
|
1020
|
+
const afterWait = Date.now();
|
|
1021
|
+
const totalElapsed = afterWait - state.lastRefillTime;
|
|
1022
|
+
const newTokens = Math.floor(
|
|
1023
|
+
totalElapsed / state.config.refillIntervalMs * state.config.refillRate
|
|
1024
|
+
);
|
|
1025
|
+
state.tokens = Math.max(0, Math.min(state.config.maxTokens, newTokens) - 1);
|
|
1026
|
+
state.lastRefillTime = afterWait;
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
|
|
945
1031
|
// src/client.ts
|
|
946
|
-
|
|
947
|
-
|
|
1032
|
+
var DEFAULT_REGIONS_VERSION = "2022/02";
|
|
1033
|
+
function applyMutationOptions(params, options) {
|
|
1034
|
+
if (options?.allowMissing) params["allowMissing"] = "true";
|
|
1035
|
+
if (options?.latencyTolerance) params["latencyTolerance"] = options.latencyTolerance;
|
|
1036
|
+
}
|
|
1037
|
+
async function autoRateLimit(limiter, path) {
|
|
1038
|
+
if (!limiter) return;
|
|
1039
|
+
const bucket = resolveBucket(path);
|
|
1040
|
+
await limiter.acquire(bucket);
|
|
948
1041
|
}
|
|
949
1042
|
function createApiClient(options) {
|
|
950
|
-
const
|
|
951
|
-
const
|
|
1043
|
+
const rawHttp = createHttpClient(options);
|
|
1044
|
+
const defaultLimiter = createRateLimiter();
|
|
1045
|
+
const limiter = options.rateLimiter || defaultLimiter;
|
|
1046
|
+
const http = {
|
|
1047
|
+
...rawHttp,
|
|
1048
|
+
async get(path, params) {
|
|
1049
|
+
await autoRateLimit(limiter, path);
|
|
1050
|
+
return rawHttp.get(path, params);
|
|
1051
|
+
},
|
|
1052
|
+
async post(path, body) {
|
|
1053
|
+
await autoRateLimit(limiter, path);
|
|
1054
|
+
return rawHttp.post(path, body);
|
|
1055
|
+
},
|
|
1056
|
+
async put(path, body) {
|
|
1057
|
+
await autoRateLimit(limiter, path);
|
|
1058
|
+
return rawHttp.put(path, body);
|
|
1059
|
+
},
|
|
1060
|
+
async patch(path, body) {
|
|
1061
|
+
await autoRateLimit(limiter, path);
|
|
1062
|
+
return rawHttp.patch(path, body);
|
|
1063
|
+
},
|
|
1064
|
+
async delete(path) {
|
|
1065
|
+
await autoRateLimit(limiter, path);
|
|
1066
|
+
return rawHttp.delete(path);
|
|
1067
|
+
}
|
|
1068
|
+
};
|
|
952
1069
|
return {
|
|
953
1070
|
edits: {
|
|
954
1071
|
async insert(packageName) {
|
|
@@ -963,8 +1080,15 @@ function createApiClient(options) {
|
|
|
963
1080
|
const { data } = await http.post(`/${packageName}/edits/${editId}:validate`);
|
|
964
1081
|
return data;
|
|
965
1082
|
},
|
|
966
|
-
async commit(packageName, editId) {
|
|
967
|
-
|
|
1083
|
+
async commit(packageName, editId, options2) {
|
|
1084
|
+
let path = `/${packageName}/edits/${editId}:commit`;
|
|
1085
|
+
if (options2?.changesNotSentForReview || options2?.changesInReviewBehavior) {
|
|
1086
|
+
const params = new URLSearchParams();
|
|
1087
|
+
if (options2.changesNotSentForReview) params.set("changesNotSentForReview", "true");
|
|
1088
|
+
if (options2.changesInReviewBehavior) params.set("changesInReviewBehavior", options2.changesInReviewBehavior);
|
|
1089
|
+
path += `?${params.toString()}`;
|
|
1090
|
+
}
|
|
1091
|
+
const { data } = await http.post(path);
|
|
968
1092
|
return data;
|
|
969
1093
|
},
|
|
970
1094
|
async delete(packageName, editId) {
|
|
@@ -998,9 +1122,13 @@ function createApiClient(options) {
|
|
|
998
1122
|
);
|
|
999
1123
|
return data.bundles;
|
|
1000
1124
|
},
|
|
1001
|
-
async upload(packageName, editId, filePath, uploadOptions) {
|
|
1125
|
+
async upload(packageName, editId, filePath, uploadOptions, deviceTierConfigId) {
|
|
1126
|
+
let bundlePath = `/${packageName}/edits/${editId}/bundles`;
|
|
1127
|
+
if (deviceTierConfigId) {
|
|
1128
|
+
bundlePath += `?${new URLSearchParams({ deviceTierConfigId }).toString()}`;
|
|
1129
|
+
}
|
|
1002
1130
|
const { data } = await http.uploadResumable(
|
|
1003
|
-
|
|
1131
|
+
bundlePath,
|
|
1004
1132
|
filePath,
|
|
1005
1133
|
"application/octet-stream",
|
|
1006
1134
|
uploadOptions
|
|
@@ -1057,6 +1185,29 @@ function createApiClient(options) {
|
|
|
1057
1185
|
}
|
|
1058
1186
|
},
|
|
1059
1187
|
apks: {
|
|
1188
|
+
async list(packageName, editId) {
|
|
1189
|
+
const { data } = await http.get(
|
|
1190
|
+
`/${packageName}/edits/${editId}/apks`
|
|
1191
|
+
);
|
|
1192
|
+
return data.apks || [];
|
|
1193
|
+
},
|
|
1194
|
+
async upload(packageName, editId, filePath, uploadOptions) {
|
|
1195
|
+
const { data } = await http.uploadResumable(
|
|
1196
|
+
`/${packageName}/edits/${editId}/apks`,
|
|
1197
|
+
filePath,
|
|
1198
|
+
"application/vnd.android.package-archive",
|
|
1199
|
+
uploadOptions
|
|
1200
|
+
);
|
|
1201
|
+
if (!data || !data.versionCode) {
|
|
1202
|
+
throw new PlayApiError(
|
|
1203
|
+
"Upload succeeded but no APK data returned",
|
|
1204
|
+
"API_EMPTY_RESPONSE",
|
|
1205
|
+
200,
|
|
1206
|
+
"This is unexpected. Retry the upload or contact Google Play support if the issue persists."
|
|
1207
|
+
);
|
|
1208
|
+
}
|
|
1209
|
+
return data;
|
|
1210
|
+
},
|
|
1060
1211
|
async addExternallyHosted(packageName, editId, apkData) {
|
|
1061
1212
|
const { data } = await http.post(
|
|
1062
1213
|
`/${packageName}/edits/${editId}/apks/externallyHosted`,
|
|
@@ -1134,6 +1285,36 @@ function createApiClient(options) {
|
|
|
1134
1285
|
return data.deleted || [];
|
|
1135
1286
|
}
|
|
1136
1287
|
},
|
|
1288
|
+
expansionFiles: {
|
|
1289
|
+
async get(packageName, editId, apkVersionCode, expansionFileType) {
|
|
1290
|
+
const { data } = await http.get(
|
|
1291
|
+
`/${packageName}/edits/${editId}/apks/${apkVersionCode}/expansionFiles/${expansionFileType}`
|
|
1292
|
+
);
|
|
1293
|
+
return data;
|
|
1294
|
+
},
|
|
1295
|
+
async update(packageName, editId, apkVersionCode, expansionFileType, body) {
|
|
1296
|
+
const { data } = await http.put(
|
|
1297
|
+
`/${packageName}/edits/${editId}/apks/${apkVersionCode}/expansionFiles/${expansionFileType}`,
|
|
1298
|
+
body
|
|
1299
|
+
);
|
|
1300
|
+
return data;
|
|
1301
|
+
},
|
|
1302
|
+
async patch(packageName, editId, apkVersionCode, expansionFileType, body) {
|
|
1303
|
+
const { data } = await http.patch(
|
|
1304
|
+
`/${packageName}/edits/${editId}/apks/${apkVersionCode}/expansionFiles/${expansionFileType}`,
|
|
1305
|
+
body
|
|
1306
|
+
);
|
|
1307
|
+
return data;
|
|
1308
|
+
},
|
|
1309
|
+
async upload(packageName, editId, apkVersionCode, expansionFileType, filePath) {
|
|
1310
|
+
const { data } = await http.upload(
|
|
1311
|
+
`/${packageName}/edits/${editId}/apks/${apkVersionCode}/expansionFiles/${expansionFileType}`,
|
|
1312
|
+
filePath,
|
|
1313
|
+
"application/octet-stream"
|
|
1314
|
+
);
|
|
1315
|
+
return data.expansionFile;
|
|
1316
|
+
}
|
|
1317
|
+
},
|
|
1137
1318
|
countryAvailability: {
|
|
1138
1319
|
async get(packageName, editId, track) {
|
|
1139
1320
|
const { data } = await http.get(
|
|
@@ -1154,10 +1335,10 @@ function createApiClient(options) {
|
|
|
1154
1335
|
},
|
|
1155
1336
|
reviews: {
|
|
1156
1337
|
async list(packageName, options2) {
|
|
1157
|
-
await rateLimit(limiter, "reviewsGet");
|
|
1158
1338
|
const params = {};
|
|
1159
1339
|
if (options2?.token) params["token"] = options2.token;
|
|
1160
1340
|
if (options2?.maxResults) params["maxResults"] = String(options2.maxResults);
|
|
1341
|
+
if (options2?.startIndex !== void 0) params["startIndex"] = String(options2.startIndex);
|
|
1161
1342
|
if (options2?.translationLanguage)
|
|
1162
1343
|
params["translationLanguage"] = options2.translationLanguage;
|
|
1163
1344
|
const hasParams = Object.keys(params).length > 0;
|
|
@@ -1168,7 +1349,6 @@ function createApiClient(options) {
|
|
|
1168
1349
|
return data;
|
|
1169
1350
|
},
|
|
1170
1351
|
async get(packageName, reviewId, translationLanguage) {
|
|
1171
|
-
await rateLimit(limiter, "reviewsGet");
|
|
1172
1352
|
const params = {};
|
|
1173
1353
|
if (translationLanguage) params["translationLanguage"] = translationLanguage;
|
|
1174
1354
|
const hasParams = Object.keys(params).length > 0;
|
|
@@ -1179,7 +1359,6 @@ function createApiClient(options) {
|
|
|
1179
1359
|
return data;
|
|
1180
1360
|
},
|
|
1181
1361
|
async reply(packageName, reviewId, replyText) {
|
|
1182
|
-
await rateLimit(limiter, "reviewsPost");
|
|
1183
1362
|
const body = { replyText };
|
|
1184
1363
|
const { data } = await http.post(
|
|
1185
1364
|
`/${packageName}/reviews/${reviewId}:reply`,
|
|
@@ -1204,18 +1383,19 @@ function createApiClient(options) {
|
|
|
1204
1383
|
const { data } = await http.get(`/${packageName}/subscriptions/${productId}`);
|
|
1205
1384
|
return data;
|
|
1206
1385
|
},
|
|
1207
|
-
async create(packageName, body, productId) {
|
|
1386
|
+
async create(packageName, body, productId, regionsVersion) {
|
|
1208
1387
|
const params = {};
|
|
1209
1388
|
if (productId) params["productId"] = productId;
|
|
1210
|
-
params["regionsVersion.version"] =
|
|
1389
|
+
params["regionsVersion.version"] = regionsVersion || DEFAULT_REGIONS_VERSION;
|
|
1211
1390
|
const path = `/${packageName}/subscriptions?${new URLSearchParams(params).toString()}`;
|
|
1212
1391
|
const { data } = await http.post(path, body);
|
|
1213
1392
|
return data;
|
|
1214
1393
|
},
|
|
1215
|
-
async update(packageName, productId, body, updateMask, regionsVersion) {
|
|
1394
|
+
async update(packageName, productId, body, updateMask, regionsVersion, options2) {
|
|
1216
1395
|
const params = {};
|
|
1217
1396
|
if (updateMask) params["updateMask"] = updateMask;
|
|
1218
|
-
params["regionsVersion.version"] = regionsVersion ||
|
|
1397
|
+
params["regionsVersion.version"] = regionsVersion || DEFAULT_REGIONS_VERSION;
|
|
1398
|
+
applyMutationOptions(params, options2);
|
|
1219
1399
|
const path = `/${packageName}/subscriptions/${productId}?${new URLSearchParams(params).toString()}`;
|
|
1220
1400
|
const { data } = await http.patch(path, body);
|
|
1221
1401
|
return data;
|
|
@@ -1271,18 +1451,19 @@ function createApiClient(options) {
|
|
|
1271
1451
|
);
|
|
1272
1452
|
return data;
|
|
1273
1453
|
},
|
|
1274
|
-
async createOffer(packageName, productId, basePlanId, body, offerId) {
|
|
1454
|
+
async createOffer(packageName, productId, basePlanId, body, offerId, regionsVersion) {
|
|
1275
1455
|
const params = {};
|
|
1276
1456
|
if (offerId) params["offerId"] = offerId;
|
|
1277
|
-
params["regionsVersion.version"] =
|
|
1457
|
+
params["regionsVersion.version"] = regionsVersion || DEFAULT_REGIONS_VERSION;
|
|
1278
1458
|
const path = `/${packageName}/subscriptions/${productId}/basePlans/${basePlanId}/offers?${new URLSearchParams(params).toString()}`;
|
|
1279
1459
|
const { data } = await http.post(path, body);
|
|
1280
1460
|
return data;
|
|
1281
1461
|
},
|
|
1282
|
-
async updateOffer(packageName, productId, basePlanId, offerId, body, updateMask, regionsVersion) {
|
|
1462
|
+
async updateOffer(packageName, productId, basePlanId, offerId, body, updateMask, regionsVersion, options2) {
|
|
1283
1463
|
const params = {};
|
|
1284
1464
|
if (updateMask) params["updateMask"] = updateMask;
|
|
1285
|
-
params["regionsVersion.version"] = regionsVersion ||
|
|
1465
|
+
params["regionsVersion.version"] = regionsVersion || DEFAULT_REGIONS_VERSION;
|
|
1466
|
+
applyMutationOptions(params, options2);
|
|
1286
1467
|
const path = `/${packageName}/subscriptions/${productId}/basePlans/${basePlanId}/offers/${offerId}?${new URLSearchParams(params).toString()}`;
|
|
1287
1468
|
const { data } = await http.patch(path, body);
|
|
1288
1469
|
return data;
|
|
@@ -1303,6 +1484,34 @@ function createApiClient(options) {
|
|
|
1303
1484
|
`/${packageName}/subscriptions/${productId}/basePlans/${basePlanId}/offers/${offerId}:deactivate`
|
|
1304
1485
|
);
|
|
1305
1486
|
return data;
|
|
1487
|
+
},
|
|
1488
|
+
async batchUpdateBasePlanStates(packageName, productId, requests) {
|
|
1489
|
+
const { data } = await http.post(
|
|
1490
|
+
`/${packageName}/subscriptions/${productId}/basePlans:batchUpdateStates`,
|
|
1491
|
+
requests
|
|
1492
|
+
);
|
|
1493
|
+
return data;
|
|
1494
|
+
},
|
|
1495
|
+
async batchGetOffers(packageName, productId, basePlanId, offerIds) {
|
|
1496
|
+
const { data } = await http.post(
|
|
1497
|
+
`/${packageName}/subscriptions/${productId}/basePlans/${basePlanId}/offers:batchGet`,
|
|
1498
|
+
{ requests: offerIds.map((id) => ({ offerId: id })) }
|
|
1499
|
+
);
|
|
1500
|
+
return data;
|
|
1501
|
+
},
|
|
1502
|
+
async batchUpdateOffers(packageName, productId, basePlanId, requests) {
|
|
1503
|
+
const { data } = await http.post(
|
|
1504
|
+
`/${packageName}/subscriptions/${productId}/basePlans/${basePlanId}/offers:batchUpdate`,
|
|
1505
|
+
requests
|
|
1506
|
+
);
|
|
1507
|
+
return data;
|
|
1508
|
+
},
|
|
1509
|
+
async batchUpdateOfferStates(packageName, productId, basePlanId, requests) {
|
|
1510
|
+
const { data } = await http.post(
|
|
1511
|
+
`/${packageName}/subscriptions/${productId}/basePlans/${basePlanId}/offers:batchUpdateStates`,
|
|
1512
|
+
requests
|
|
1513
|
+
);
|
|
1514
|
+
return data;
|
|
1306
1515
|
}
|
|
1307
1516
|
},
|
|
1308
1517
|
inappproducts: {
|
|
@@ -1443,11 +1652,11 @@ function createApiClient(options) {
|
|
|
1443
1652
|
return data;
|
|
1444
1653
|
},
|
|
1445
1654
|
async listVoided(packageName, options2) {
|
|
1446
|
-
await rateLimit(limiter, "voidedBurst");
|
|
1447
|
-
await rateLimit(limiter, "voidedDaily");
|
|
1448
1655
|
const params = {};
|
|
1449
1656
|
if (options2?.startTime) params["startTime"] = options2.startTime;
|
|
1450
1657
|
if (options2?.endTime) params["endTime"] = options2.endTime;
|
|
1658
|
+
if (options2?.type !== void 0) params["type"] = String(options2.type);
|
|
1659
|
+
if (options2?.includeQuantityBasedPartialRefund) params["includeQuantityBasedPartialRefund"] = "true";
|
|
1451
1660
|
if (options2?.maxResults) params["maxResults"] = String(options2.maxResults);
|
|
1452
1661
|
if (options2?.token) params["token"] = options2.token;
|
|
1453
1662
|
const hasParams = Object.keys(params).length > 0;
|
|
@@ -1510,9 +1719,10 @@ function createApiClient(options) {
|
|
|
1510
1719
|
}
|
|
1511
1720
|
},
|
|
1512
1721
|
deobfuscation: {
|
|
1513
|
-
async upload(packageName, editId, versionCode, filePath) {
|
|
1722
|
+
async upload(packageName, editId, versionCode, filePath, fileType) {
|
|
1723
|
+
const deobType = fileType || "proguard";
|
|
1514
1724
|
const { data } = await http.upload(
|
|
1515
|
-
`/${packageName}/edits/${editId}/apks/${versionCode}/deobfuscationFiles
|
|
1725
|
+
`/${packageName}/edits/${editId}/apks/${versionCode}/deobfuscationFiles/${deobType}`,
|
|
1516
1726
|
filePath,
|
|
1517
1727
|
"application/octet-stream"
|
|
1518
1728
|
);
|
|
@@ -1603,9 +1813,14 @@ function createApiClient(options) {
|
|
|
1603
1813
|
}
|
|
1604
1814
|
},
|
|
1605
1815
|
oneTimeProducts: {
|
|
1606
|
-
async list(packageName) {
|
|
1816
|
+
async list(packageName, options2) {
|
|
1817
|
+
const params = {};
|
|
1818
|
+
if (options2?.pageToken) params["pageToken"] = options2.pageToken;
|
|
1819
|
+
if (options2?.pageSize) params["pageSize"] = String(options2.pageSize);
|
|
1820
|
+
const hasParams = Object.keys(params).length > 0;
|
|
1607
1821
|
const { data } = await http.get(
|
|
1608
|
-
`/${packageName}/oneTimeProducts
|
|
1822
|
+
`/${packageName}/oneTimeProducts`,
|
|
1823
|
+
hasParams ? params : void 0
|
|
1609
1824
|
);
|
|
1610
1825
|
return data;
|
|
1611
1826
|
},
|
|
@@ -1615,18 +1830,19 @@ function createApiClient(options) {
|
|
|
1615
1830
|
);
|
|
1616
1831
|
return data;
|
|
1617
1832
|
},
|
|
1618
|
-
async create(packageName, body) {
|
|
1619
|
-
const params = new URLSearchParams({ "regionsVersion.version":
|
|
1833
|
+
async create(packageName, body, regionsVersion) {
|
|
1834
|
+
const params = new URLSearchParams({ "regionsVersion.version": regionsVersion || DEFAULT_REGIONS_VERSION });
|
|
1620
1835
|
const { data } = await http.post(
|
|
1621
1836
|
`/${packageName}/oneTimeProducts?${params.toString()}`,
|
|
1622
1837
|
body
|
|
1623
1838
|
);
|
|
1624
1839
|
return data;
|
|
1625
1840
|
},
|
|
1626
|
-
async update(packageName, productId, body, updateMask, regionsVersion) {
|
|
1841
|
+
async update(packageName, productId, body, updateMask, regionsVersion, options2) {
|
|
1627
1842
|
const params = {};
|
|
1628
1843
|
if (updateMask) params["updateMask"] = updateMask;
|
|
1629
|
-
params["regionsVersion.version"] = regionsVersion ||
|
|
1844
|
+
params["regionsVersion.version"] = regionsVersion || DEFAULT_REGIONS_VERSION;
|
|
1845
|
+
applyMutationOptions(params, options2);
|
|
1630
1846
|
const path = `/${packageName}/oneTimeProducts/${productId}?${new URLSearchParams(params).toString()}`;
|
|
1631
1847
|
const { data } = await http.patch(path, body);
|
|
1632
1848
|
return data;
|
|
@@ -1646,23 +1862,45 @@ function createApiClient(options) {
|
|
|
1646
1862
|
);
|
|
1647
1863
|
return data;
|
|
1648
1864
|
},
|
|
1649
|
-
async createOffer(packageName, productId, body) {
|
|
1865
|
+
async createOffer(packageName, productId, body, regionsVersion) {
|
|
1866
|
+
const params = new URLSearchParams({ "regionsVersion.version": regionsVersion || DEFAULT_REGIONS_VERSION });
|
|
1650
1867
|
const { data } = await http.post(
|
|
1651
|
-
`/${packageName}/oneTimeProducts/${productId}/offers`,
|
|
1868
|
+
`/${packageName}/oneTimeProducts/${productId}/offers?${params.toString()}`,
|
|
1652
1869
|
body
|
|
1653
1870
|
);
|
|
1654
1871
|
return data;
|
|
1655
1872
|
},
|
|
1656
|
-
async updateOffer(packageName, productId, offerId, body, updateMask, regionsVersion) {
|
|
1873
|
+
async updateOffer(packageName, productId, offerId, body, updateMask, regionsVersion, options2) {
|
|
1657
1874
|
const params = {};
|
|
1658
1875
|
if (updateMask) params["updateMask"] = updateMask;
|
|
1659
|
-
params["regionsVersion.version"] = regionsVersion ||
|
|
1876
|
+
params["regionsVersion.version"] = regionsVersion || DEFAULT_REGIONS_VERSION;
|
|
1877
|
+
applyMutationOptions(params, options2);
|
|
1660
1878
|
const path = `/${packageName}/oneTimeProducts/${productId}/offers/${offerId}?${new URLSearchParams(params).toString()}`;
|
|
1661
1879
|
const { data } = await http.patch(path, body);
|
|
1662
1880
|
return data;
|
|
1663
1881
|
},
|
|
1664
1882
|
async deleteOffer(packageName, productId, offerId) {
|
|
1665
1883
|
await http.delete(`/${packageName}/oneTimeProducts/${productId}/offers/${offerId}`);
|
|
1884
|
+
},
|
|
1885
|
+
async batchGet(packageName, productIds) {
|
|
1886
|
+
const params = productIds.map((id) => `productIds=${encodeURIComponent(id)}`).join("&");
|
|
1887
|
+
const { data } = await http.get(
|
|
1888
|
+
`/${packageName}/oneTimeProducts:batchGet?${params}`
|
|
1889
|
+
);
|
|
1890
|
+
return data.oneTimeProducts || [];
|
|
1891
|
+
},
|
|
1892
|
+
async batchUpdate(packageName, requests) {
|
|
1893
|
+
const { data } = await http.post(
|
|
1894
|
+
`/${packageName}/oneTimeProducts:batchUpdate`,
|
|
1895
|
+
requests
|
|
1896
|
+
);
|
|
1897
|
+
return data;
|
|
1898
|
+
},
|
|
1899
|
+
async batchDelete(packageName, productIds) {
|
|
1900
|
+
await http.post(
|
|
1901
|
+
`/${packageName}/oneTimeProducts:batchDelete`,
|
|
1902
|
+
{ requests: productIds.map((id) => ({ productId: id })) }
|
|
1903
|
+
);
|
|
1666
1904
|
}
|
|
1667
1905
|
},
|
|
1668
1906
|
purchaseOptions: {
|
|
@@ -1727,69 +1965,6 @@ function createApiClient(options) {
|
|
|
1727
1965
|
};
|
|
1728
1966
|
}
|
|
1729
1967
|
|
|
1730
|
-
// src/rate-limiter.ts
|
|
1731
|
-
var RATE_LIMIT_BUCKETS = {
|
|
1732
|
-
default: { name: "default", maxTokens: 200, refillRate: 200, refillIntervalMs: 1e3 },
|
|
1733
|
-
reviewsGet: { name: "reviewsGet", maxTokens: 200, refillRate: 200, refillIntervalMs: 36e5 },
|
|
1734
|
-
reviewsPost: {
|
|
1735
|
-
name: "reviewsPost",
|
|
1736
|
-
maxTokens: 2e3,
|
|
1737
|
-
refillRate: 2e3,
|
|
1738
|
-
refillIntervalMs: 864e5
|
|
1739
|
-
},
|
|
1740
|
-
voidedBurst: { name: "voidedBurst", maxTokens: 30, refillRate: 30, refillIntervalMs: 3e4 },
|
|
1741
|
-
voidedDaily: {
|
|
1742
|
-
name: "voidedDaily",
|
|
1743
|
-
maxTokens: 6e3,
|
|
1744
|
-
refillRate: 6e3,
|
|
1745
|
-
refillIntervalMs: 864e5
|
|
1746
|
-
},
|
|
1747
|
-
reporting: { name: "reporting", maxTokens: 10, refillRate: 10, refillIntervalMs: 1e3 }
|
|
1748
|
-
};
|
|
1749
|
-
function createRateLimiter(buckets) {
|
|
1750
|
-
const states = /* @__PURE__ */ new Map();
|
|
1751
|
-
if (buckets) {
|
|
1752
|
-
for (const bucket of buckets) {
|
|
1753
|
-
states.set(bucket.name, {
|
|
1754
|
-
tokens: bucket.maxTokens,
|
|
1755
|
-
lastRefillTime: Date.now(),
|
|
1756
|
-
config: bucket
|
|
1757
|
-
});
|
|
1758
|
-
}
|
|
1759
|
-
}
|
|
1760
|
-
return {
|
|
1761
|
-
async acquire(bucket) {
|
|
1762
|
-
const state = states.get(bucket);
|
|
1763
|
-
if (!state) return;
|
|
1764
|
-
const now = Date.now();
|
|
1765
|
-
const elapsed = now - state.lastRefillTime;
|
|
1766
|
-
const refill = Math.floor(
|
|
1767
|
-
elapsed / state.config.refillIntervalMs * state.config.refillRate
|
|
1768
|
-
);
|
|
1769
|
-
if (refill > 0) {
|
|
1770
|
-
state.tokens = Math.min(state.config.maxTokens, state.tokens + refill);
|
|
1771
|
-
state.lastRefillTime = now;
|
|
1772
|
-
}
|
|
1773
|
-
if (state.tokens > 0) {
|
|
1774
|
-
state.tokens--;
|
|
1775
|
-
return;
|
|
1776
|
-
}
|
|
1777
|
-
const tokensNeeded = 1;
|
|
1778
|
-
const waitMs = Math.ceil(
|
|
1779
|
-
tokensNeeded / state.config.refillRate * state.config.refillIntervalMs
|
|
1780
|
-
);
|
|
1781
|
-
await new Promise((r) => setTimeout(r, waitMs));
|
|
1782
|
-
const afterWait = Date.now();
|
|
1783
|
-
const totalElapsed = afterWait - state.lastRefillTime;
|
|
1784
|
-
const newTokens = Math.floor(
|
|
1785
|
-
totalElapsed / state.config.refillIntervalMs * state.config.refillRate
|
|
1786
|
-
);
|
|
1787
|
-
state.tokens = Math.min(state.config.maxTokens, newTokens) - 1;
|
|
1788
|
-
state.lastRefillTime = afterWait;
|
|
1789
|
-
}
|
|
1790
|
-
};
|
|
1791
|
-
}
|
|
1792
|
-
|
|
1793
1968
|
// src/reporting-client.ts
|
|
1794
1969
|
var REPORTING_BASE_URL = "https://playdeveloperreporting.googleapis.com/v1beta1";
|
|
1795
1970
|
function createReportingClient(options) {
|
|
@@ -2038,6 +2213,7 @@ export {
|
|
|
2038
2213
|
createUsersClient,
|
|
2039
2214
|
paginate,
|
|
2040
2215
|
paginateAll,
|
|
2041
|
-
paginateParallel
|
|
2216
|
+
paginateParallel,
|
|
2217
|
+
resolveBucket
|
|
2042
2218
|
};
|
|
2043
2219
|
//# sourceMappingURL=index.js.map
|