@sitepong/fastnode 0.1.0
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 +81 -0
- package/bin/fastnode.js +13 -0
- package/bin/fastnode.ts +5 -0
- package/dist/actions/index.cjs +7405 -0
- package/dist/actions/index.cjs.map +1 -0
- package/dist/actions/index.d.cts +15 -0
- package/dist/actions/index.d.ts +15 -0
- package/dist/actions/index.mjs +7377 -0
- package/dist/actions/index.mjs.map +1 -0
- package/dist/cert/index.cjs +219 -0
- package/dist/cert/index.cjs.map +1 -0
- package/dist/cert/index.d.cts +4 -0
- package/dist/cert/index.d.ts +4 -0
- package/dist/cert/index.mjs +191 -0
- package/dist/cert/index.mjs.map +1 -0
- package/dist/cert-BmJGtYtb.d.cts +27 -0
- package/dist/cert-owkOFNW8.d.ts +27 -0
- package/dist/cli/index.cjs +7998 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +9 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.mjs +7972 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/client/index.cjs +2592 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +2 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.mjs +2582 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/context-CymLkfrS.d.cts +13 -0
- package/dist/context-CymLkfrS.d.ts +13 -0
- package/dist/core/index.cjs +281 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.mjs +254 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/deliver/index.cjs +328 -0
- package/dist/deliver/index.cjs.map +1 -0
- package/dist/deliver/index.d.cts +3 -0
- package/dist/deliver/index.d.ts +3 -0
- package/dist/deliver/index.mjs +322 -0
- package/dist/deliver/index.mjs.map +1 -0
- package/dist/enums-B609j2rb.d.cts +20 -0
- package/dist/enums-B609j2rb.d.ts +20 -0
- package/dist/frameit/index.cjs +247 -0
- package/dist/frameit/index.cjs.map +1 -0
- package/dist/frameit/index.d.cts +1 -0
- package/dist/frameit/index.d.ts +1 -0
- package/dist/frameit/index.mjs +242 -0
- package/dist/frameit/index.mjs.map +1 -0
- package/dist/gym/index.cjs +356 -0
- package/dist/gym/index.cjs.map +1 -0
- package/dist/gym/index.d.cts +2 -0
- package/dist/gym/index.d.ts +2 -0
- package/dist/gym/index.mjs +346 -0
- package/dist/gym/index.mjs.map +1 -0
- package/dist/index-1Vu2cRQ2.d.ts +99 -0
- package/dist/index-A5MimeQk.d.ts +72 -0
- package/dist/index-B0yhu_LZ.d.ts +76 -0
- package/dist/index-B9yXicrQ.d.ts +62 -0
- package/dist/index-BFdNOmPJ.d.cts +53 -0
- package/dist/index-BLubSlgK.d.cts +1513 -0
- package/dist/index-BN0ubxjZ.d.ts +70 -0
- package/dist/index-BQJIJlK7.d.cts +70 -0
- package/dist/index-BYonklf3.d.cts +84 -0
- package/dist/index-BYonklf3.d.ts +84 -0
- package/dist/index-BimqCmY8.d.cts +78 -0
- package/dist/index-BimqCmY8.d.ts +78 -0
- package/dist/index-BoU8qt8r.d.cts +59 -0
- package/dist/index-BoU8qt8r.d.ts +59 -0
- package/dist/index-C2yG3wXA.d.cts +95 -0
- package/dist/index-C2yG3wXA.d.ts +95 -0
- package/dist/index-CR3BFPIz.d.cts +77 -0
- package/dist/index-CR3BFPIz.d.ts +77 -0
- package/dist/index-CWNLnSOL.d.cts +99 -0
- package/dist/index-Cp6cjtd-.d.cts +65 -0
- package/dist/index-Cp6cjtd-.d.ts +65 -0
- package/dist/index-D1Izm7qt.d.ts +1513 -0
- package/dist/index-D5eihzwM.d.cts +76 -0
- package/dist/index-DImN9PWc.d.ts +155 -0
- package/dist/index-DfCUVJX1.d.cts +62 -0
- package/dist/index-DfirmFbC.d.ts +32 -0
- package/dist/index-DkvinY7_.d.ts +54 -0
- package/dist/index-DrUpRXRG.d.cts +155 -0
- package/dist/index-EcVvViW8.d.cts +72 -0
- package/dist/index-HRiaaX-Q.d.cts +54 -0
- package/dist/index-TfXqwuac.d.ts +53 -0
- package/dist/index-lt819Jgj.d.cts +32 -0
- package/dist/index.cjs +8464 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.mjs +8410 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lane/index.cjs +7641 -0
- package/dist/lane/index.cjs.map +1 -0
- package/dist/lane/index.d.cts +51 -0
- package/dist/lane/index.d.ts +51 -0
- package/dist/lane/index.mjs +7603 -0
- package/dist/lane/index.mjs.map +1 -0
- package/dist/match/index.cjs +942 -0
- package/dist/match/index.cjs.map +1 -0
- package/dist/match/index.d.cts +5 -0
- package/dist/match/index.d.ts +5 -0
- package/dist/match/index.mjs +913 -0
- package/dist/match/index.mjs.map +1 -0
- package/dist/pem/index.cjs +195 -0
- package/dist/pem/index.cjs.map +1 -0
- package/dist/pem/index.d.cts +3 -0
- package/dist/pem/index.d.ts +3 -0
- package/dist/pem/index.mjs +170 -0
- package/dist/pem/index.mjs.map +1 -0
- package/dist/pilot/index.cjs +206 -0
- package/dist/pilot/index.cjs.map +1 -0
- package/dist/pilot/index.d.cts +3 -0
- package/dist/pilot/index.d.ts +3 -0
- package/dist/pilot/index.mjs +196 -0
- package/dist/pilot/index.mjs.map +1 -0
- package/dist/precheck/index.cjs +277 -0
- package/dist/precheck/index.cjs.map +1 -0
- package/dist/precheck/index.d.cts +3 -0
- package/dist/precheck/index.d.ts +3 -0
- package/dist/precheck/index.mjs +274 -0
- package/dist/precheck/index.mjs.map +1 -0
- package/dist/produce/index.cjs +200 -0
- package/dist/produce/index.cjs.map +1 -0
- package/dist/produce/index.d.cts +3 -0
- package/dist/produce/index.d.ts +3 -0
- package/dist/produce/index.mjs +191 -0
- package/dist/produce/index.mjs.map +1 -0
- package/dist/scan/index.cjs +187 -0
- package/dist/scan/index.cjs.map +1 -0
- package/dist/scan/index.d.cts +1 -0
- package/dist/scan/index.d.ts +1 -0
- package/dist/scan/index.mjs +183 -0
- package/dist/scan/index.mjs.map +1 -0
- package/dist/sigh/index.cjs +203 -0
- package/dist/sigh/index.cjs.map +1 -0
- package/dist/sigh/index.d.cts +3 -0
- package/dist/sigh/index.d.ts +3 -0
- package/dist/sigh/index.mjs +198 -0
- package/dist/sigh/index.mjs.map +1 -0
- package/dist/snapshot/index.cjs +448 -0
- package/dist/snapshot/index.cjs.map +1 -0
- package/dist/snapshot/index.d.cts +1 -0
- package/dist/snapshot/index.d.ts +1 -0
- package/dist/snapshot/index.mjs +438 -0
- package/dist/snapshot/index.mjs.map +1 -0
- package/dist/trainer/index.cjs +395 -0
- package/dist/trainer/index.cjs.map +1 -0
- package/dist/trainer/index.d.cts +1 -0
- package/dist/trainer/index.d.ts +1 -0
- package/dist/trainer/index.mjs +372 -0
- package/dist/trainer/index.mjs.map +1 -0
- package/dist/xcode/index.cjs +188 -0
- package/dist/xcode/index.cjs.map +1 -0
- package/dist/xcode/index.d.cts +1 -0
- package/dist/xcode/index.d.ts +1 -0
- package/dist/xcode/index.mjs +176 -0
- package/dist/xcode/index.mjs.map +1 -0
- package/package.json +223 -0
|
@@ -0,0 +1,2582 @@
|
|
|
1
|
+
import { importPKCS8, SignJWT } from 'jose';
|
|
2
|
+
import { createHash, randomBytes, pbkdf2Sync } from 'crypto';
|
|
3
|
+
import { createInterface } from 'readline';
|
|
4
|
+
|
|
5
|
+
// src/client/auth.ts
|
|
6
|
+
var MAX_TOKEN_DURATION = 1200;
|
|
7
|
+
var DEFAULT_TOKEN_DURATION = 500;
|
|
8
|
+
var TokenManager = class {
|
|
9
|
+
config;
|
|
10
|
+
currentToken = null;
|
|
11
|
+
expiresAt = 0;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.config = config;
|
|
14
|
+
}
|
|
15
|
+
async getToken() {
|
|
16
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
17
|
+
if (this.currentToken && now < this.expiresAt - 30) {
|
|
18
|
+
return this.currentToken;
|
|
19
|
+
}
|
|
20
|
+
return this.refresh();
|
|
21
|
+
}
|
|
22
|
+
async refresh() {
|
|
23
|
+
const duration = Math.min(
|
|
24
|
+
this.config.duration ?? DEFAULT_TOKEN_DURATION,
|
|
25
|
+
MAX_TOKEN_DURATION
|
|
26
|
+
);
|
|
27
|
+
const audience = this.config.enterprise ? "apple-developer-enterprise-v1" : "appstoreconnect-v1";
|
|
28
|
+
const key = await importPKCS8(this.config.privateKey, "ES256");
|
|
29
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
30
|
+
let jwt = new SignJWT(this.config.issuerId ? {} : { sub: "user" }).setProtectedHeader({
|
|
31
|
+
alg: "ES256",
|
|
32
|
+
kid: this.config.keyId,
|
|
33
|
+
typ: "JWT"
|
|
34
|
+
}).setIssuedAt(now - 60).setExpirationTime(now + duration).setAudience(audience);
|
|
35
|
+
if (this.config.issuerId) {
|
|
36
|
+
jwt = jwt.setIssuer(this.config.issuerId);
|
|
37
|
+
}
|
|
38
|
+
this.currentToken = await jwt.sign(key);
|
|
39
|
+
this.expiresAt = now + duration;
|
|
40
|
+
return this.currentToken;
|
|
41
|
+
}
|
|
42
|
+
invalidate() {
|
|
43
|
+
this.currentToken = null;
|
|
44
|
+
this.expiresAt = 0;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var N_2048 = BigInt(
|
|
48
|
+
"0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73"
|
|
49
|
+
);
|
|
50
|
+
var g_2048 = 2n;
|
|
51
|
+
function numToHex(num) {
|
|
52
|
+
let hex = num.toString(16);
|
|
53
|
+
if (hex.length % 2 !== 0) hex = "0" + hex;
|
|
54
|
+
return hex.toLowerCase();
|
|
55
|
+
}
|
|
56
|
+
function hexToBytes(hex) {
|
|
57
|
+
return Buffer.from(hex, "hex");
|
|
58
|
+
}
|
|
59
|
+
function shaHex(h, algorithm) {
|
|
60
|
+
return createHash(algorithm).update(hexToBytes(h)).digest("hex");
|
|
61
|
+
}
|
|
62
|
+
function shaStr(s, algorithm) {
|
|
63
|
+
return createHash(algorithm).update(s).digest("hex");
|
|
64
|
+
}
|
|
65
|
+
function modExp(base, exp, mod) {
|
|
66
|
+
if (mod === 1n) return 0n;
|
|
67
|
+
let result = 1n;
|
|
68
|
+
base = base % mod;
|
|
69
|
+
while (exp > 0n) {
|
|
70
|
+
if (exp % 2n === 1n) {
|
|
71
|
+
result = result * base % mod;
|
|
72
|
+
}
|
|
73
|
+
exp = exp / 2n;
|
|
74
|
+
base = base * base % mod;
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
function H(algorithm, n, ...args) {
|
|
79
|
+
const nHex = numToHex(n);
|
|
80
|
+
const nlen = 2 * (nHex.length * 4 + 7 >> 3);
|
|
81
|
+
let hashin = "";
|
|
82
|
+
for (const s of args) {
|
|
83
|
+
if (s === void 0) continue;
|
|
84
|
+
const shex = typeof s === "string" ? s : numToHex(s);
|
|
85
|
+
if (shex.length > nlen) {
|
|
86
|
+
throw new Error("Bit width does not match - client uses different prime");
|
|
87
|
+
}
|
|
88
|
+
hashin += "0".repeat(nlen - shex.length) + shex;
|
|
89
|
+
}
|
|
90
|
+
const hashed = shaHex(hashin, algorithm);
|
|
91
|
+
return BigInt("0x" + hashed) % n;
|
|
92
|
+
}
|
|
93
|
+
var SRPClient = class {
|
|
94
|
+
N;
|
|
95
|
+
g;
|
|
96
|
+
hashAlg;
|
|
97
|
+
k;
|
|
98
|
+
a;
|
|
99
|
+
A;
|
|
100
|
+
S = null;
|
|
101
|
+
K = null;
|
|
102
|
+
M = null;
|
|
103
|
+
H_AMK = null;
|
|
104
|
+
constructor(group = 2048) {
|
|
105
|
+
if (group !== 2048) throw new Error("Only 2048-bit group is supported");
|
|
106
|
+
this.N = N_2048;
|
|
107
|
+
this.g = g_2048;
|
|
108
|
+
this.hashAlg = "sha256";
|
|
109
|
+
this.k = H(this.hashAlg, this.N, this.N, this.g);
|
|
110
|
+
this.a = BigInt("0x" + randomBytes(256).toString("hex"));
|
|
111
|
+
this.A = numToHex(modExp(this.g, this.a, this.N));
|
|
112
|
+
}
|
|
113
|
+
startAuthentication() {
|
|
114
|
+
return this.A;
|
|
115
|
+
}
|
|
116
|
+
processChallenge(username, password, xsalt, xbb, isPasswordEncrypted = false) {
|
|
117
|
+
const bb = BigInt("0x" + xbb);
|
|
118
|
+
if (bb % this.N === 0n) return false;
|
|
119
|
+
let x;
|
|
120
|
+
if (isPasswordEncrypted) {
|
|
121
|
+
x = this.calcXHex(password, xsalt);
|
|
122
|
+
} else {
|
|
123
|
+
x = this.calcX(username, password, xsalt);
|
|
124
|
+
}
|
|
125
|
+
const u = H(this.hashAlg, this.N, this.A, xbb);
|
|
126
|
+
if (u === 0n) return false;
|
|
127
|
+
const gx = modExp(this.g, x, this.N);
|
|
128
|
+
let base = (bb - this.k * gx) % this.N;
|
|
129
|
+
if (base < 0n) base += this.N;
|
|
130
|
+
const exp = this.a + x * u;
|
|
131
|
+
this.S = numToHex(modExp(base, exp, this.N));
|
|
132
|
+
this.K = shaHex(this.S, this.hashAlg);
|
|
133
|
+
const hxor = H(this.hashAlg, this.N, this.N) ^ H(this.hashAlg, this.N, this.g);
|
|
134
|
+
const buf = numToHex(hxor) + shaStr(username, this.hashAlg) + xsalt + this.A + xbb + this.K;
|
|
135
|
+
const bytes = hexToBytes(buf);
|
|
136
|
+
this.M = createHash(this.hashAlg).update(bytes).digest("hex");
|
|
137
|
+
const amkBytes = hexToBytes(this.A + this.M + this.K);
|
|
138
|
+
this.H_AMK = numToHex(
|
|
139
|
+
BigInt("0x" + createHash(this.hashAlg).update(amkBytes).digest("hex"))
|
|
140
|
+
);
|
|
141
|
+
return this.M;
|
|
142
|
+
}
|
|
143
|
+
calcX(username, password, xsalt) {
|
|
144
|
+
const spad = xsalt.length % 2 !== 0 ? "0" : "";
|
|
145
|
+
const inner = shaStr(`${username}:${password}`, this.hashAlg);
|
|
146
|
+
return BigInt("0x" + shaHex(spad + xsalt + inner, this.hashAlg));
|
|
147
|
+
}
|
|
148
|
+
calcXHex(xpassword, xsalt) {
|
|
149
|
+
const colonHex = ":".charCodeAt(0).toString(16);
|
|
150
|
+
const inner = shaHex(colonHex + xpassword, this.hashAlg);
|
|
151
|
+
return BigInt("0x" + shaHex(xsalt + inner, this.hashAlg));
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
function applePbkdf2(password, salt, iterations, keyLength, protocol) {
|
|
155
|
+
if (!["s2k", "s2k_fo"].includes(protocol)) {
|
|
156
|
+
throw new Error(`Unsupported protocol '${protocol}' for pbkdf2`);
|
|
157
|
+
}
|
|
158
|
+
let passwordBytes = createHash("sha256").update(password).digest();
|
|
159
|
+
if (protocol === "s2k_fo") {
|
|
160
|
+
passwordBytes = passwordBytes.toString("hex");
|
|
161
|
+
}
|
|
162
|
+
return pbkdf2Sync(passwordBytes, salt, iterations, keyLength, "sha256");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/client/apple-session.ts
|
|
166
|
+
var AUTH_BASE = "https://idmsa.apple.com/appleauth/auth";
|
|
167
|
+
var OLYMPUS_SESSION = "https://appstoreconnect.apple.com/olympus/v1/session";
|
|
168
|
+
var WIDGET_KEY_URL = "https://appstoreconnect.apple.com/olympus/v1/app/config?hostname=itunesconnect.apple.com";
|
|
169
|
+
var ProgramLicenseAgreementError = class extends Error {
|
|
170
|
+
constructor(message, agreements) {
|
|
171
|
+
super(message);
|
|
172
|
+
this.agreements = agreements;
|
|
173
|
+
this.name = "ProgramLicenseAgreementError";
|
|
174
|
+
}
|
|
175
|
+
agreements;
|
|
176
|
+
};
|
|
177
|
+
function checkPortalResponse(body, session) {
|
|
178
|
+
if (!body || typeof body !== "object") return;
|
|
179
|
+
if (body.resultCode === 4100) {
|
|
180
|
+
const userMsg = body.userString ?? "The selected team does not have an eligible program membership.";
|
|
181
|
+
const agreements = session?.pendingAgreements ?? [];
|
|
182
|
+
if (agreements.length > 0) {
|
|
183
|
+
throw new ProgramLicenseAgreementError(
|
|
184
|
+
`${userMsg}
|
|
185
|
+
|
|
186
|
+
\u26A0 Pending agreement: ${agreements[0].subject}
|
|
187
|
+
${agreements[0].message.replace(/<[^>]+>/g, "")}
|
|
188
|
+
|
|
189
|
+
Please accept the agreement at https://developer.apple.com/account before continuing.`,
|
|
190
|
+
agreements
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
throw new Error(userMsg);
|
|
194
|
+
}
|
|
195
|
+
if ((body.userString ?? "").includes("Program License Agreement")) {
|
|
196
|
+
throw new ProgramLicenseAgreementError(
|
|
197
|
+
`${body.userString} Please manually log into your Apple Developer account to review and accept the updated agreement.`,
|
|
198
|
+
session?.pendingAgreements ?? []
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
if (body.resultCode && body.resultCode !== 0) {
|
|
202
|
+
const msg = body.userString || body.resultString || `Portal API error (code ${body.resultCode})`;
|
|
203
|
+
throw new Error(msg);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async function loginWithAppleId(config) {
|
|
207
|
+
const log = config.onLog ?? console.log;
|
|
208
|
+
const promptFn = config.onPrompt ?? defaultPrompt;
|
|
209
|
+
log("Fetching Apple service key...");
|
|
210
|
+
const serviceKey = await fetchServiceKey();
|
|
211
|
+
const initRes = await fetch(`${AUTH_BASE}/signin?widgetKey=${serviceKey}`, {
|
|
212
|
+
headers: { "User-Agent": "Spaceship 2.225.0" }
|
|
213
|
+
});
|
|
214
|
+
const initCookies = parseCookies(initRes.headers);
|
|
215
|
+
const hcBits = initRes.headers.get("X-Apple-HC-Bits");
|
|
216
|
+
const hcChallenge = initRes.headers.get("X-Apple-HC-Challenge");
|
|
217
|
+
let hashcash;
|
|
218
|
+
if (hcBits && hcChallenge) {
|
|
219
|
+
log("Computing hashcash...");
|
|
220
|
+
hashcash = computeHashcash(parseInt(hcBits, 10), hcChallenge);
|
|
221
|
+
}
|
|
222
|
+
const cookieStr = Object.entries(initCookies).map(([k, v]) => k.startsWith("DES") ? `${k}="${v}"` : `${k}=${v}`).join("; ");
|
|
223
|
+
log("Starting SIRP Apple ID login...");
|
|
224
|
+
const response = await doSirp(config.email, config.password, serviceKey, cookieStr, hashcash);
|
|
225
|
+
const session = {
|
|
226
|
+
cookies: { ...initCookies, ...response.cookies },
|
|
227
|
+
sessionId: response.sessionId,
|
|
228
|
+
scnt: response.scnt,
|
|
229
|
+
serviceKey,
|
|
230
|
+
userEmail: config.email,
|
|
231
|
+
pendingAgreements: []
|
|
232
|
+
};
|
|
233
|
+
if (response.status === 403) {
|
|
234
|
+
throw new Error(`Invalid username and password combination. Used '${config.email}' as the username.`);
|
|
235
|
+
} else if (response.status === 200) {
|
|
236
|
+
log("Login successful.");
|
|
237
|
+
await fetchOlympusSession(session);
|
|
238
|
+
} else if (response.status === 409) {
|
|
239
|
+
await handleTwoStepOrFactor(session, log, promptFn);
|
|
240
|
+
await fetchOlympusSession(session);
|
|
241
|
+
} else if (response.status === 412) {
|
|
242
|
+
throw new Error("Need to acknowledge Apple's Apple ID and Privacy statement. Please manually log into https://appleid.apple.com.");
|
|
243
|
+
} else {
|
|
244
|
+
throw new Error(`Unexpected login response (${response.status}): ${JSON.stringify(response.body).slice(0, 500)}`);
|
|
245
|
+
}
|
|
246
|
+
const agreements = await fetchContractMessages(session);
|
|
247
|
+
if (agreements.length > 0) {
|
|
248
|
+
for (const msg of agreements) {
|
|
249
|
+
log(`\u26A0 ${msg.subject}: ${msg.message.replace(/<[^>]+>/g, "")}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
session.pendingAgreements = agreements;
|
|
253
|
+
log(`Logged in as ${session.userEmail}`);
|
|
254
|
+
return session;
|
|
255
|
+
}
|
|
256
|
+
async function doSirp(user, password, serviceKey, cookieStr, hashcash) {
|
|
257
|
+
const client = new SRPClient(2048);
|
|
258
|
+
const A = client.startAuthentication();
|
|
259
|
+
const aBase64 = Buffer.from(A, "hex").toString("base64");
|
|
260
|
+
const baseHeaders = {
|
|
261
|
+
"Content-Type": "application/json",
|
|
262
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
263
|
+
"X-Apple-Widget-Key": serviceKey,
|
|
264
|
+
Accept: "application/json, text/javascript"
|
|
265
|
+
};
|
|
266
|
+
if (cookieStr) baseHeaders["Cookie"] = cookieStr;
|
|
267
|
+
const initRes = await fetch(`${AUTH_BASE}/signin/init`, {
|
|
268
|
+
method: "POST",
|
|
269
|
+
headers: baseHeaders,
|
|
270
|
+
body: JSON.stringify({ a: aBase64, accountName: user, protocols: ["s2k", "s2k_fo"] }),
|
|
271
|
+
redirect: "manual"
|
|
272
|
+
});
|
|
273
|
+
const initBody = await initRes.json();
|
|
274
|
+
if (initBody.serviceErrors) throw new Error(`Apple auth error: ${JSON.stringify(initBody.serviceErrors)}`);
|
|
275
|
+
const { iteration: iterations, salt: saltB64, b: bB64, c, protocol } = initBody;
|
|
276
|
+
const salt = Buffer.from(saltB64, "base64");
|
|
277
|
+
const b = Buffer.from(bB64, "base64");
|
|
278
|
+
const encryptedPassword = applePbkdf2(password, salt, iterations, 32, protocol);
|
|
279
|
+
const m1 = client.processChallenge(user, encryptedPassword.toString("hex"), salt.toString("hex"), b.toString("hex"), true);
|
|
280
|
+
if (m1 === false) throw new Error("Error processing SIRP challenge");
|
|
281
|
+
const m2 = client.H_AMK;
|
|
282
|
+
const completeHeaders = { ...baseHeaders };
|
|
283
|
+
if (hashcash) completeHeaders["X-Apple-HC"] = hashcash;
|
|
284
|
+
const completeRes = await fetch(`${AUTH_BASE}/signin/complete?isRememberMeEnabled=false`, {
|
|
285
|
+
method: "POST",
|
|
286
|
+
headers: completeHeaders,
|
|
287
|
+
body: JSON.stringify({
|
|
288
|
+
accountName: user,
|
|
289
|
+
c,
|
|
290
|
+
m1: Buffer.from(m1, "hex").toString("base64"),
|
|
291
|
+
m2: m2 ? Buffer.from(m2, "hex").toString("base64") : "",
|
|
292
|
+
rememberMe: false
|
|
293
|
+
}),
|
|
294
|
+
redirect: "manual"
|
|
295
|
+
});
|
|
296
|
+
let body;
|
|
297
|
+
try {
|
|
298
|
+
body = await completeRes.json();
|
|
299
|
+
} catch {
|
|
300
|
+
body = "";
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
status: completeRes.status,
|
|
304
|
+
body,
|
|
305
|
+
cookies: parseCookies(completeRes.headers),
|
|
306
|
+
sessionId: completeRes.headers.get("x-apple-id-session-id") ?? "",
|
|
307
|
+
scnt: completeRes.headers.get("scnt") ?? ""
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
async function handleTwoStepOrFactor(session, log, promptFn) {
|
|
311
|
+
const r = await fetch(`${AUTH_BASE}`, { headers: buildAuthHeaders(session) });
|
|
312
|
+
const body = await r.json();
|
|
313
|
+
if (body.trustedDevices?.length > 0) {
|
|
314
|
+
await handleTwoStep(session, body, log, promptFn);
|
|
315
|
+
} else if (body.trustedPhoneNumbers?.length > 0) {
|
|
316
|
+
await handleTwoFactor(session, body, log, promptFn);
|
|
317
|
+
} else {
|
|
318
|
+
throw new Error("2FA required but no trusted devices or phone numbers found.");
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
async function handleTwoFactor(session, authBody, log, promptFn) {
|
|
322
|
+
log("Two-factor Authentication (6 digit code) is enabled for this account");
|
|
323
|
+
const codeLength = authBody.securityCode?.length ?? 6;
|
|
324
|
+
const phones = authBody.trustedPhoneNumbers ?? [];
|
|
325
|
+
const noTrusted = authBody.noTrustedDevices === true;
|
|
326
|
+
let codeType;
|
|
327
|
+
let reqBody;
|
|
328
|
+
if (noTrusted && phones.length === 1) {
|
|
329
|
+
const phone = phones[0];
|
|
330
|
+
log(`Code automatically sent to ${phone.numberWithDialCode}`);
|
|
331
|
+
const code = await promptFn(`Please enter the ${codeLength} digit code you received at ${phone.numberWithDialCode}: `);
|
|
332
|
+
codeType = "phone";
|
|
333
|
+
reqBody = JSON.stringify({ securityCode: { code }, phoneNumber: { id: phone.id }, mode: phone.pushMode ?? "sms" });
|
|
334
|
+
} else if (noTrusted) {
|
|
335
|
+
const phone = await choosePhone(phones, log, promptFn);
|
|
336
|
+
await requestPhoneCode(session, phone);
|
|
337
|
+
log(`Successfully requested text message to ${phone.numberWithDialCode}`);
|
|
338
|
+
const code = await promptFn(`Please enter the ${codeLength} digit code: `);
|
|
339
|
+
codeType = "phone";
|
|
340
|
+
reqBody = JSON.stringify({ securityCode: { code }, phoneNumber: { id: phone.id }, mode: phone.pushMode ?? "sms" });
|
|
341
|
+
} else {
|
|
342
|
+
log("(Input 'sms' to escape this prompt and select a trusted phone number to send the code as a text message)");
|
|
343
|
+
const input = await promptFn(`Please enter the ${codeLength} digit code: `);
|
|
344
|
+
if (input.toLowerCase() === "sms") {
|
|
345
|
+
const phone = await choosePhone(phones, log, promptFn);
|
|
346
|
+
await requestPhoneCode(session, phone);
|
|
347
|
+
const code = await promptFn(`Please enter the ${codeLength} digit code sent to ${phone.numberWithDialCode}: `);
|
|
348
|
+
codeType = "phone";
|
|
349
|
+
reqBody = JSON.stringify({ securityCode: { code }, phoneNumber: { id: phone.id }, mode: phone.pushMode ?? "sms" });
|
|
350
|
+
} else {
|
|
351
|
+
codeType = "trusteddevice";
|
|
352
|
+
reqBody = JSON.stringify({ securityCode: { code: input } });
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
log("Requesting session...");
|
|
356
|
+
const verifyRes = await fetch(`${AUTH_BASE}/verify/${codeType}/securitycode`, {
|
|
357
|
+
method: "POST",
|
|
358
|
+
headers: { ...buildAuthHeaders(session), "Content-Type": "application/json" },
|
|
359
|
+
body: reqBody
|
|
360
|
+
});
|
|
361
|
+
if (!verifyRes.ok) {
|
|
362
|
+
const err = await verifyRes.json().catch(() => ({}));
|
|
363
|
+
const msgs = (err?.service_errors ?? err?.serviceErrors ?? []).map((e) => e.message).filter(Boolean);
|
|
364
|
+
throw new Error(msgs.join("; ") || `Verification failed (${verifyRes.status})`);
|
|
365
|
+
}
|
|
366
|
+
Object.assign(session.cookies, parseCookies(verifyRes.headers));
|
|
367
|
+
await trustSession(session);
|
|
368
|
+
}
|
|
369
|
+
async function handleTwoStep(session, authBody, log, promptFn) {
|
|
370
|
+
log("Two-step Verification (4 digit code) is enabled for this account");
|
|
371
|
+
const devices = authBody.trustedDevices ?? [];
|
|
372
|
+
log("Please select a trusted device:");
|
|
373
|
+
for (let i = 0; i < devices.length; i++) {
|
|
374
|
+
log(` ${i + 1}. ${devices[i].name} ${devices[i].modelName ?? "SMS"} (${devices[i].id})`);
|
|
375
|
+
}
|
|
376
|
+
const choice = await promptFn("Enter device number: ");
|
|
377
|
+
const device = devices[Math.max(0, parseInt(choice, 10) - 1)] ?? devices[0];
|
|
378
|
+
await fetch(`${AUTH_BASE}/verify/device/${device.id}/securitycode`, { method: "PUT", headers: buildAuthHeaders(session) });
|
|
379
|
+
log("Successfully requested notification");
|
|
380
|
+
const code = await promptFn("Please enter the 4 digit code: ");
|
|
381
|
+
const verifyRes = await fetch(`${AUTH_BASE}/verify/phone/securitycode`, {
|
|
382
|
+
method: "POST",
|
|
383
|
+
headers: { ...buildAuthHeaders(session), "Content-Type": "application/json" },
|
|
384
|
+
body: JSON.stringify({ phoneNumber: { id: device.id }, securityCode: { code }, mode: "sms" })
|
|
385
|
+
});
|
|
386
|
+
if (!verifyRes.ok) throw new Error("Incorrect verification code.");
|
|
387
|
+
Object.assign(session.cookies, parseCookies(verifyRes.headers));
|
|
388
|
+
await trustSession(session);
|
|
389
|
+
}
|
|
390
|
+
async function choosePhone(phones, log, promptFn) {
|
|
391
|
+
log("Please select a trusted phone number:");
|
|
392
|
+
for (let i = 0; i < phones.length; i++) log(` ${i + 1}. ${phones[i].numberWithDialCode}`);
|
|
393
|
+
const choice = await promptFn("Enter number: ");
|
|
394
|
+
return phones[Math.max(0, parseInt(choice, 10) - 1)] ?? phones[0];
|
|
395
|
+
}
|
|
396
|
+
async function requestPhoneCode(session, phone) {
|
|
397
|
+
await fetch(`${AUTH_BASE}/verify/phone`, {
|
|
398
|
+
method: "PUT",
|
|
399
|
+
headers: { ...buildAuthHeaders(session), "Content-Type": "application/json" },
|
|
400
|
+
body: JSON.stringify({ phoneNumber: { id: phone.id }, mode: phone.pushMode ?? "sms" })
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
async function trustSession(session) {
|
|
404
|
+
const r = await fetch(`${AUTH_BASE}/2sv/trust`, { headers: buildAuthHeaders(session) });
|
|
405
|
+
Object.assign(session.cookies, parseCookies(r.headers));
|
|
406
|
+
}
|
|
407
|
+
async function fetchOlympusSession(session) {
|
|
408
|
+
const cookieStr = Object.entries(session.cookies).map(([k, v]) => `${k}=${v}`).join("; ");
|
|
409
|
+
const res = await fetch(OLYMPUS_SESSION, { headers: { Cookie: cookieStr, Accept: "application/json" } });
|
|
410
|
+
if (res.ok) {
|
|
411
|
+
const body = await res.json();
|
|
412
|
+
if (body?.user?.emailAddress) session.userEmail = body.user.emailAddress;
|
|
413
|
+
if (body?.provider?.providerId) session.teamId = String(body.provider.providerId);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
async function fetchContractMessages(session) {
|
|
417
|
+
const cookieStr = Object.entries(session.cookies).map(([k, v]) => `${k}=${v}`).join("; ");
|
|
418
|
+
try {
|
|
419
|
+
const res = await fetch("https://appstoreconnect.apple.com/olympus/v1/contractMessages", {
|
|
420
|
+
headers: { Cookie: cookieStr, Accept: "application/json" }
|
|
421
|
+
});
|
|
422
|
+
if (!res.ok) return [];
|
|
423
|
+
const body = await res.json();
|
|
424
|
+
return (body ?? []).map((m) => ({
|
|
425
|
+
id: m.id ?? "",
|
|
426
|
+
group: m.group ?? "",
|
|
427
|
+
subject: m.subject ?? "",
|
|
428
|
+
message: m.message ?? ""
|
|
429
|
+
}));
|
|
430
|
+
} catch {
|
|
431
|
+
return [];
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
async function fetchServiceKey() {
|
|
435
|
+
const res = await fetch(WIDGET_KEY_URL);
|
|
436
|
+
const body = await res.json();
|
|
437
|
+
if (!body?.authServiceKey) throw new Error("Could not fetch Apple service key");
|
|
438
|
+
return body.authServiceKey;
|
|
439
|
+
}
|
|
440
|
+
function buildAuthHeaders(session) {
|
|
441
|
+
const h = { "X-Apple-Widget-Key": session.serviceKey, Accept: "application/json" };
|
|
442
|
+
if (session.sessionId) h["X-Apple-Id-Session-Id"] = session.sessionId;
|
|
443
|
+
if (session.scnt) h["scnt"] = session.scnt;
|
|
444
|
+
const c = Object.entries(session.cookies).map(([k, v]) => `${k}=${v}`).join("; ");
|
|
445
|
+
if (c) h["Cookie"] = c;
|
|
446
|
+
return h;
|
|
447
|
+
}
|
|
448
|
+
function parseCookies(headers) {
|
|
449
|
+
const cookies = {};
|
|
450
|
+
for (const raw of headers.getSetCookie?.() ?? []) {
|
|
451
|
+
const m = raw.match(/^([^=]+)=([^;]*)/);
|
|
452
|
+
if (m) cookies[m[1]] = m[2];
|
|
453
|
+
}
|
|
454
|
+
return cookies;
|
|
455
|
+
}
|
|
456
|
+
function computeHashcash(bits, challenge) {
|
|
457
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T]/g, "").slice(0, 12);
|
|
458
|
+
let counter = 0;
|
|
459
|
+
while (true) {
|
|
460
|
+
const stamp = `1:${bits}:${date}:${challenge}::${counter.toString(36)}:`;
|
|
461
|
+
const hash = createHash("sha1").update(stamp).digest();
|
|
462
|
+
let zeroBits = 0;
|
|
463
|
+
for (const byte of hash) {
|
|
464
|
+
if (byte === 0) {
|
|
465
|
+
zeroBits += 8;
|
|
466
|
+
} else {
|
|
467
|
+
zeroBits += Math.clz32(byte) - 24;
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
if (zeroBits >= bits) break;
|
|
471
|
+
}
|
|
472
|
+
if (zeroBits >= bits) return stamp;
|
|
473
|
+
counter++;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
async function defaultPrompt(message) {
|
|
477
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
478
|
+
return new Promise((r) => {
|
|
479
|
+
rl.question(message, (a) => {
|
|
480
|
+
rl.close();
|
|
481
|
+
r(a.trim());
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// src/client/request.ts
|
|
487
|
+
var PRODUCTION_BASE = "https://api.appstoreconnect.apple.com";
|
|
488
|
+
var ENTERPRISE_BASE = "https://api.enterprise.developer.apple.com";
|
|
489
|
+
var MAX_RETRIES = 5;
|
|
490
|
+
var INITIAL_BACKOFF_MS = 1e3;
|
|
491
|
+
var MAX_BACKOFF_MS = 6e4;
|
|
492
|
+
var MAX_RATE_LIMIT_BACKOFF_MS = 36e5;
|
|
493
|
+
var AppStoreConnectError = class extends Error {
|
|
494
|
+
constructor(message, status, errors = []) {
|
|
495
|
+
super(message);
|
|
496
|
+
this.status = status;
|
|
497
|
+
this.errors = errors;
|
|
498
|
+
this.name = "AppStoreConnectError";
|
|
499
|
+
}
|
|
500
|
+
status;
|
|
501
|
+
errors;
|
|
502
|
+
};
|
|
503
|
+
var RateLimitError = class extends AppStoreConnectError {
|
|
504
|
+
constructor(retryAfter) {
|
|
505
|
+
super(`Rate limited. Retry after ${retryAfter}s`, 429);
|
|
506
|
+
this.retryAfter = retryAfter;
|
|
507
|
+
this.name = "RateLimitError";
|
|
508
|
+
}
|
|
509
|
+
retryAfter;
|
|
510
|
+
};
|
|
511
|
+
var RequestClient = class {
|
|
512
|
+
baseUrl;
|
|
513
|
+
tokenManager;
|
|
514
|
+
constructor(tokenManager, enterprise = false) {
|
|
515
|
+
this.tokenManager = tokenManager;
|
|
516
|
+
this.baseUrl = enterprise ? ENTERPRISE_BASE : PRODUCTION_BASE;
|
|
517
|
+
}
|
|
518
|
+
async request(path, options = {}) {
|
|
519
|
+
const { method = "GET", body, params, headers: extraHeaders } = options;
|
|
520
|
+
let url = `${this.baseUrl}${path}`;
|
|
521
|
+
if (params) {
|
|
522
|
+
const searchParams = new URLSearchParams();
|
|
523
|
+
for (const [key, value] of Object.entries(params)) {
|
|
524
|
+
if (value === void 0) continue;
|
|
525
|
+
if (Array.isArray(value)) {
|
|
526
|
+
searchParams.set(key, value.join(","));
|
|
527
|
+
} else {
|
|
528
|
+
searchParams.set(key, String(value));
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
const qs = searchParams.toString();
|
|
532
|
+
if (qs) url += `?${qs}`;
|
|
533
|
+
}
|
|
534
|
+
let lastError = null;
|
|
535
|
+
let rateLimitBackoffMs = INITIAL_BACKOFF_MS;
|
|
536
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
537
|
+
const token = await this.tokenManager.getToken();
|
|
538
|
+
const headers = {
|
|
539
|
+
Authorization: `Bearer ${token}`,
|
|
540
|
+
"Content-Type": "application/json",
|
|
541
|
+
...extraHeaders
|
|
542
|
+
};
|
|
543
|
+
const res = await fetch(url, {
|
|
544
|
+
method,
|
|
545
|
+
headers,
|
|
546
|
+
body: body ? JSON.stringify(body) : void 0
|
|
547
|
+
});
|
|
548
|
+
if (res.ok) {
|
|
549
|
+
if (res.status === 204) return void 0;
|
|
550
|
+
return await res.json();
|
|
551
|
+
}
|
|
552
|
+
if (res.status === 401 && attempt === 0) {
|
|
553
|
+
this.tokenManager.invalidate();
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
if (res.status === 429) {
|
|
557
|
+
if (rateLimitBackoffMs > MAX_RATE_LIMIT_BACKOFF_MS) {
|
|
558
|
+
throw new RateLimitError(Math.floor(rateLimitBackoffMs / 1e3));
|
|
559
|
+
}
|
|
560
|
+
const retryAfterHeader = res.headers.get("Retry-After");
|
|
561
|
+
const sleepMs = retryAfterHeader ? parseInt(retryAfterHeader, 10) * 1e3 : rateLimitBackoffMs;
|
|
562
|
+
await sleep(sleepMs);
|
|
563
|
+
rateLimitBackoffMs *= 2;
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
566
|
+
const errorBody = await res.json().catch(() => null);
|
|
567
|
+
const errors = errorBody?.errors || [];
|
|
568
|
+
if (res.status === 403) {
|
|
569
|
+
const firstCode = errors[0]?.code;
|
|
570
|
+
if (firstCode === "FORBIDDEN.REQUIRED_AGREEMENTS_MISSING_OR_EXPIRED") {
|
|
571
|
+
const detail2 = errors.map((e) => e.detail || e.title).join("; ") || "Required agreements are missing or expired.";
|
|
572
|
+
throw new ProgramLicenseAgreementError(
|
|
573
|
+
`${detail2} Please manually log into your Apple Developer account to review and accept the updated agreement.`,
|
|
574
|
+
[]
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
if (res.status === 502 && attempt < MAX_RETRIES) {
|
|
579
|
+
const bodyText = errorBody ? JSON.stringify(errorBody) : "";
|
|
580
|
+
if (bodyText.includes("Could not process this request")) {
|
|
581
|
+
const backoff = Math.min(
|
|
582
|
+
INITIAL_BACKOFF_MS * Math.pow(2, attempt),
|
|
583
|
+
MAX_BACKOFF_MS
|
|
584
|
+
);
|
|
585
|
+
await sleep(backoff + Math.random() * 500);
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
if (res.status >= 500 && attempt < MAX_RETRIES) {
|
|
590
|
+
const backoff = Math.min(
|
|
591
|
+
INITIAL_BACKOFF_MS * Math.pow(2, attempt),
|
|
592
|
+
MAX_BACKOFF_MS
|
|
593
|
+
);
|
|
594
|
+
await sleep(backoff + Math.random() * 500);
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
const detail = errors.map((e) => e.detail || e.title).join("; ") || `HTTP ${res.status}`;
|
|
598
|
+
lastError = new AppStoreConnectError(detail, res.status, errors);
|
|
599
|
+
break;
|
|
600
|
+
}
|
|
601
|
+
throw lastError || new Error("Request failed after retries");
|
|
602
|
+
}
|
|
603
|
+
async get(path, params) {
|
|
604
|
+
return this.request(path, { method: "GET", params });
|
|
605
|
+
}
|
|
606
|
+
async post(path, body) {
|
|
607
|
+
return this.request(path, { method: "POST", body });
|
|
608
|
+
}
|
|
609
|
+
async patch(path, body) {
|
|
610
|
+
return this.request(path, { method: "PATCH", body });
|
|
611
|
+
}
|
|
612
|
+
async delete(path) {
|
|
613
|
+
await this.request(path, { method: "DELETE" });
|
|
614
|
+
}
|
|
615
|
+
// Build query params from ListParams
|
|
616
|
+
buildListParams(params) {
|
|
617
|
+
const result = {};
|
|
618
|
+
if (params.filter) {
|
|
619
|
+
for (const [key, value] of Object.entries(params.filter)) {
|
|
620
|
+
result[`filter[${key}]`] = Array.isArray(value) ? value.join(",") : value;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
if (params.include) {
|
|
624
|
+
result["include"] = params.include;
|
|
625
|
+
}
|
|
626
|
+
if (params.fields) {
|
|
627
|
+
for (const [key, value] of Object.entries(params.fields)) {
|
|
628
|
+
result[`fields[${key}]`] = value;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
if (params.limit !== void 0) {
|
|
632
|
+
result["limit"] = String(params.limit);
|
|
633
|
+
}
|
|
634
|
+
if (params.sort) {
|
|
635
|
+
result["sort"] = params.sort;
|
|
636
|
+
}
|
|
637
|
+
if (params.cursor) {
|
|
638
|
+
result["page[after]"] = params.cursor;
|
|
639
|
+
}
|
|
640
|
+
return result;
|
|
641
|
+
}
|
|
642
|
+
async list(path, params = {}) {
|
|
643
|
+
const queryParams = this.buildListParams(params);
|
|
644
|
+
return this.get(path, queryParams);
|
|
645
|
+
}
|
|
646
|
+
async *paginate(path, params = {}) {
|
|
647
|
+
let cursor = params.cursor;
|
|
648
|
+
while (true) {
|
|
649
|
+
const response = await this.list(path, { ...params, cursor });
|
|
650
|
+
for (const item of response.data) {
|
|
651
|
+
yield item;
|
|
652
|
+
}
|
|
653
|
+
const nextLink = response.links?.next;
|
|
654
|
+
if (!nextLink) break;
|
|
655
|
+
const nextUrl = new URL(nextLink);
|
|
656
|
+
cursor = nextUrl.searchParams.get("page[after]") || void 0;
|
|
657
|
+
if (!cursor) break;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
async all(path, params = {}) {
|
|
661
|
+
const results = [];
|
|
662
|
+
for await (const item of this.paginate(path, params)) {
|
|
663
|
+
results.push(item);
|
|
664
|
+
}
|
|
665
|
+
return results;
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
function sleep(ms) {
|
|
669
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// src/resources/certificates.ts
|
|
673
|
+
var CertificatesResource = class {
|
|
674
|
+
constructor(http) {
|
|
675
|
+
this.http = http;
|
|
676
|
+
}
|
|
677
|
+
http;
|
|
678
|
+
async list(params) {
|
|
679
|
+
const listParams = {
|
|
680
|
+
filter: params?.filter,
|
|
681
|
+
limit: params?.limit ?? 200,
|
|
682
|
+
sort: params?.sort
|
|
683
|
+
};
|
|
684
|
+
if (params?.fields) {
|
|
685
|
+
listParams.fields = { certificates: params.fields.join(",") };
|
|
686
|
+
}
|
|
687
|
+
return this.http.all("/v1/certificates", listParams);
|
|
688
|
+
}
|
|
689
|
+
async get(id) {
|
|
690
|
+
const response = await this.http.get(
|
|
691
|
+
`/v1/certificates/${id}`
|
|
692
|
+
);
|
|
693
|
+
return response.data;
|
|
694
|
+
}
|
|
695
|
+
async create(params) {
|
|
696
|
+
const response = await this.http.post(
|
|
697
|
+
"/v1/certificates",
|
|
698
|
+
{
|
|
699
|
+
data: {
|
|
700
|
+
type: "certificates",
|
|
701
|
+
attributes: {
|
|
702
|
+
certificateType: params.certificateType,
|
|
703
|
+
csrContent: params.csrContent
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
);
|
|
708
|
+
return response.data;
|
|
709
|
+
}
|
|
710
|
+
async revoke(id) {
|
|
711
|
+
await this.http.delete(`/v1/certificates/${id}`);
|
|
712
|
+
}
|
|
713
|
+
async *paginate(params) {
|
|
714
|
+
const listParams = {
|
|
715
|
+
filter: params?.filter,
|
|
716
|
+
limit: params?.limit ?? 200
|
|
717
|
+
};
|
|
718
|
+
yield* this.http.paginate("/v1/certificates", listParams);
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
// src/resources/profiles.ts
|
|
723
|
+
var ProfilesResource = class {
|
|
724
|
+
constructor(http) {
|
|
725
|
+
this.http = http;
|
|
726
|
+
}
|
|
727
|
+
http;
|
|
728
|
+
async list(params) {
|
|
729
|
+
const listParams = {
|
|
730
|
+
filter: params?.filter,
|
|
731
|
+
include: params?.include,
|
|
732
|
+
limit: params?.limit ?? 200,
|
|
733
|
+
sort: params?.sort
|
|
734
|
+
};
|
|
735
|
+
if (params?.fields) {
|
|
736
|
+
listParams.fields = {};
|
|
737
|
+
for (const [key, value] of Object.entries(params.fields)) {
|
|
738
|
+
if (value) listParams.fields[key] = value.join(",");
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return this.http.all("/v1/profiles", listParams);
|
|
742
|
+
}
|
|
743
|
+
async get(id, params) {
|
|
744
|
+
const queryParams = {};
|
|
745
|
+
if (params?.include) queryParams["include"] = params.include;
|
|
746
|
+
const response = await this.http.get(
|
|
747
|
+
`/v1/profiles/${id}`,
|
|
748
|
+
queryParams
|
|
749
|
+
);
|
|
750
|
+
return response.data;
|
|
751
|
+
}
|
|
752
|
+
async create(params) {
|
|
753
|
+
const relationships = {
|
|
754
|
+
bundleId: {
|
|
755
|
+
data: { type: "bundleIds", id: params.bundleIdId }
|
|
756
|
+
},
|
|
757
|
+
certificates: {
|
|
758
|
+
data: params.certificateIds.map((id) => ({
|
|
759
|
+
type: "certificates",
|
|
760
|
+
id
|
|
761
|
+
}))
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
if (params.deviceIds && params.deviceIds.length > 0) {
|
|
765
|
+
relationships.devices = {
|
|
766
|
+
data: params.deviceIds.map((id) => ({
|
|
767
|
+
type: "devices",
|
|
768
|
+
id
|
|
769
|
+
}))
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
const response = await this.http.post(
|
|
773
|
+
"/v1/profiles",
|
|
774
|
+
{
|
|
775
|
+
data: {
|
|
776
|
+
type: "profiles",
|
|
777
|
+
attributes: {
|
|
778
|
+
name: params.name,
|
|
779
|
+
profileType: params.profileType
|
|
780
|
+
},
|
|
781
|
+
relationships
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
);
|
|
785
|
+
return response.data;
|
|
786
|
+
}
|
|
787
|
+
async delete(id) {
|
|
788
|
+
await this.http.delete(`/v1/profiles/${id}`);
|
|
789
|
+
}
|
|
790
|
+
async getCertificates(profileId) {
|
|
791
|
+
return this.http.all(
|
|
792
|
+
`/v1/profiles/${profileId}/certificates`
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
async getDevices(profileId) {
|
|
796
|
+
return this.http.all(`/v1/profiles/${profileId}/devices`);
|
|
797
|
+
}
|
|
798
|
+
async getBundleId(profileId) {
|
|
799
|
+
const response = await this.http.get(
|
|
800
|
+
`/v1/profiles/${profileId}/bundleId`
|
|
801
|
+
);
|
|
802
|
+
return response.data;
|
|
803
|
+
}
|
|
804
|
+
};
|
|
805
|
+
|
|
806
|
+
// src/resources/bundle-ids.ts
|
|
807
|
+
var BundleIdsResource = class {
|
|
808
|
+
constructor(http) {
|
|
809
|
+
this.http = http;
|
|
810
|
+
}
|
|
811
|
+
http;
|
|
812
|
+
async list(params) {
|
|
813
|
+
const listParams = {
|
|
814
|
+
filter: params?.filter,
|
|
815
|
+
include: params?.include,
|
|
816
|
+
limit: params?.limit ?? 200,
|
|
817
|
+
sort: params?.sort
|
|
818
|
+
};
|
|
819
|
+
if (params?.fields) {
|
|
820
|
+
listParams.fields = {};
|
|
821
|
+
for (const [key, value] of Object.entries(params.fields)) {
|
|
822
|
+
if (value) listParams.fields[key] = value.join(",");
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
return this.http.all("/v1/bundleIds", listParams);
|
|
826
|
+
}
|
|
827
|
+
async get(id, params) {
|
|
828
|
+
const queryParams = {};
|
|
829
|
+
if (params?.include) queryParams["include"] = params.include;
|
|
830
|
+
const response = await this.http.get(
|
|
831
|
+
`/v1/bundleIds/${id}`,
|
|
832
|
+
queryParams
|
|
833
|
+
);
|
|
834
|
+
return response.data;
|
|
835
|
+
}
|
|
836
|
+
async create(params) {
|
|
837
|
+
const attributes = {
|
|
838
|
+
identifier: params.identifier,
|
|
839
|
+
name: params.name,
|
|
840
|
+
platform: params.platform
|
|
841
|
+
};
|
|
842
|
+
if (params.seedId) attributes.seedId = params.seedId;
|
|
843
|
+
const response = await this.http.post(
|
|
844
|
+
"/v1/bundleIds",
|
|
845
|
+
{
|
|
846
|
+
data: {
|
|
847
|
+
type: "bundleIds",
|
|
848
|
+
attributes
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
);
|
|
852
|
+
return response.data;
|
|
853
|
+
}
|
|
854
|
+
async find(identifier) {
|
|
855
|
+
const results = await this.list({
|
|
856
|
+
filter: { identifier },
|
|
857
|
+
limit: 1
|
|
858
|
+
});
|
|
859
|
+
return results[0] ?? null;
|
|
860
|
+
}
|
|
861
|
+
async getCapabilities(bundleIdId) {
|
|
862
|
+
return this.http.all(
|
|
863
|
+
`/v1/bundleIds/${bundleIdId}/bundleIdCapabilities`
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
|
|
868
|
+
// src/resources/devices.ts
|
|
869
|
+
var DevicesResource = class {
|
|
870
|
+
constructor(http) {
|
|
871
|
+
this.http = http;
|
|
872
|
+
}
|
|
873
|
+
http;
|
|
874
|
+
async list(params) {
|
|
875
|
+
const listParams = {
|
|
876
|
+
filter: params?.filter,
|
|
877
|
+
limit: params?.limit ?? 200,
|
|
878
|
+
sort: params?.sort
|
|
879
|
+
};
|
|
880
|
+
if (params?.fields) {
|
|
881
|
+
listParams.fields = { devices: params.fields.join(",") };
|
|
882
|
+
}
|
|
883
|
+
return this.http.all("/v1/devices", listParams);
|
|
884
|
+
}
|
|
885
|
+
async get(id) {
|
|
886
|
+
const response = await this.http.get(
|
|
887
|
+
`/v1/devices/${id}`
|
|
888
|
+
);
|
|
889
|
+
return response.data;
|
|
890
|
+
}
|
|
891
|
+
async register(params) {
|
|
892
|
+
const response = await this.http.post(
|
|
893
|
+
"/v1/devices",
|
|
894
|
+
{
|
|
895
|
+
data: {
|
|
896
|
+
type: "devices",
|
|
897
|
+
attributes: {
|
|
898
|
+
name: params.name,
|
|
899
|
+
platform: params.platform,
|
|
900
|
+
udid: params.udid
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
);
|
|
905
|
+
return response.data;
|
|
906
|
+
}
|
|
907
|
+
async update(id, params) {
|
|
908
|
+
const response = await this.http.patch(
|
|
909
|
+
`/v1/devices/${id}`,
|
|
910
|
+
{
|
|
911
|
+
data: {
|
|
912
|
+
type: "devices",
|
|
913
|
+
id,
|
|
914
|
+
attributes: params
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
);
|
|
918
|
+
return response.data;
|
|
919
|
+
}
|
|
920
|
+
async findByUdid(udid) {
|
|
921
|
+
const results = await this.list({ filter: { udid }, limit: 1 });
|
|
922
|
+
return results[0] ?? null;
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
|
|
926
|
+
// src/resources/apps.ts
|
|
927
|
+
var AppsResource = class {
|
|
928
|
+
constructor(http) {
|
|
929
|
+
this.http = http;
|
|
930
|
+
}
|
|
931
|
+
http;
|
|
932
|
+
async list(params) {
|
|
933
|
+
const listParams = {
|
|
934
|
+
filter: params?.filter,
|
|
935
|
+
include: params?.include,
|
|
936
|
+
limit: params?.limit ?? 200,
|
|
937
|
+
sort: params?.sort
|
|
938
|
+
};
|
|
939
|
+
if (params?.fields) {
|
|
940
|
+
listParams.fields = {};
|
|
941
|
+
for (const [key, value] of Object.entries(params.fields)) {
|
|
942
|
+
if (value) listParams.fields[key] = value.join(",");
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
return this.http.all("/v1/apps", listParams);
|
|
946
|
+
}
|
|
947
|
+
async get(id, params) {
|
|
948
|
+
const queryParams = {};
|
|
949
|
+
if (params?.include) queryParams["include"] = params.include;
|
|
950
|
+
const response = await this.http.get(
|
|
951
|
+
`/v1/apps/${id}`,
|
|
952
|
+
queryParams
|
|
953
|
+
);
|
|
954
|
+
return response.data;
|
|
955
|
+
}
|
|
956
|
+
async findByBundleId(bundleId) {
|
|
957
|
+
const results = await this.list({
|
|
958
|
+
filter: { bundleId },
|
|
959
|
+
limit: 1
|
|
960
|
+
});
|
|
961
|
+
return results[0] ?? null;
|
|
962
|
+
}
|
|
963
|
+
};
|
|
964
|
+
|
|
965
|
+
// src/resources/builds.ts
|
|
966
|
+
var BuildsResource = class {
|
|
967
|
+
constructor(http) {
|
|
968
|
+
this.http = http;
|
|
969
|
+
}
|
|
970
|
+
http;
|
|
971
|
+
async list(params) {
|
|
972
|
+
const listParams = {
|
|
973
|
+
filter: params?.filter,
|
|
974
|
+
include: params?.include,
|
|
975
|
+
limit: params?.limit ?? 200,
|
|
976
|
+
sort: params?.sort
|
|
977
|
+
};
|
|
978
|
+
if (params?.fields) {
|
|
979
|
+
listParams.fields = {};
|
|
980
|
+
for (const [key, value] of Object.entries(params.fields)) {
|
|
981
|
+
if (value) listParams.fields[key] = value.join(",");
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
return this.http.all("/v1/builds", listParams);
|
|
985
|
+
}
|
|
986
|
+
async get(id, params) {
|
|
987
|
+
const queryParams = {};
|
|
988
|
+
if (params?.include) queryParams["include"] = params.include;
|
|
989
|
+
const response = await this.http.get(
|
|
990
|
+
`/v1/builds/${id}`,
|
|
991
|
+
queryParams
|
|
992
|
+
);
|
|
993
|
+
return response.data;
|
|
994
|
+
}
|
|
995
|
+
async getBetaDetail(buildId) {
|
|
996
|
+
const response = await this.http.get(
|
|
997
|
+
`/v1/builds/${buildId}/buildBetaDetail`
|
|
998
|
+
);
|
|
999
|
+
return response.data;
|
|
1000
|
+
}
|
|
1001
|
+
async getLocalizations(buildId) {
|
|
1002
|
+
return this.http.all(
|
|
1003
|
+
`/v1/builds/${buildId}/betaBuildLocalizations`
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
async createLocalization(params) {
|
|
1007
|
+
const response = await this.http.post("/v1/betaBuildLocalizations", {
|
|
1008
|
+
data: {
|
|
1009
|
+
type: "betaBuildLocalizations",
|
|
1010
|
+
attributes: {
|
|
1011
|
+
locale: params.locale,
|
|
1012
|
+
whatsNew: params.whatsNew
|
|
1013
|
+
},
|
|
1014
|
+
relationships: {
|
|
1015
|
+
build: {
|
|
1016
|
+
data: { type: "builds", id: params.buildId }
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
});
|
|
1021
|
+
return response.data;
|
|
1022
|
+
}
|
|
1023
|
+
async updateLocalization(localizationId, params) {
|
|
1024
|
+
const response = await this.http.patch(`/v1/betaBuildLocalizations/${localizationId}`, {
|
|
1025
|
+
data: {
|
|
1026
|
+
type: "betaBuildLocalizations",
|
|
1027
|
+
id: localizationId,
|
|
1028
|
+
attributes: {
|
|
1029
|
+
whatsNew: params.whatsNew
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
});
|
|
1033
|
+
return response.data;
|
|
1034
|
+
}
|
|
1035
|
+
async getPreReleaseVersion(buildId) {
|
|
1036
|
+
try {
|
|
1037
|
+
const response = await this.http.get(
|
|
1038
|
+
`/v1/builds/${buildId}/preReleaseVersion`
|
|
1039
|
+
);
|
|
1040
|
+
return response.data;
|
|
1041
|
+
} catch {
|
|
1042
|
+
return null;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
async submitForBetaReview(buildId) {
|
|
1046
|
+
await this.http.post("/v1/betaAppReviewSubmissions", {
|
|
1047
|
+
data: {
|
|
1048
|
+
type: "betaAppReviewSubmissions",
|
|
1049
|
+
relationships: {
|
|
1050
|
+
build: {
|
|
1051
|
+
data: { type: "builds", id: buildId }
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
async expireBuild(buildId) {
|
|
1058
|
+
await this.http.patch(`/v1/builds/${buildId}`, {
|
|
1059
|
+
data: {
|
|
1060
|
+
type: "builds",
|
|
1061
|
+
id: buildId,
|
|
1062
|
+
attributes: {
|
|
1063
|
+
expired: true
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
};
|
|
1069
|
+
|
|
1070
|
+
// src/resources/beta-groups.ts
|
|
1071
|
+
var BetaGroupsResource = class {
|
|
1072
|
+
constructor(http) {
|
|
1073
|
+
this.http = http;
|
|
1074
|
+
}
|
|
1075
|
+
http;
|
|
1076
|
+
async list(params) {
|
|
1077
|
+
const listParams = {
|
|
1078
|
+
filter: params?.filter,
|
|
1079
|
+
limit: params?.limit ?? 200,
|
|
1080
|
+
sort: params?.sort
|
|
1081
|
+
};
|
|
1082
|
+
if (params?.fields) {
|
|
1083
|
+
listParams.fields = { betaGroups: params.fields.join(",") };
|
|
1084
|
+
}
|
|
1085
|
+
return this.http.all("/v1/betaGroups", listParams);
|
|
1086
|
+
}
|
|
1087
|
+
async get(id) {
|
|
1088
|
+
const response = await this.http.get(
|
|
1089
|
+
`/v1/betaGroups/${id}`
|
|
1090
|
+
);
|
|
1091
|
+
return response.data;
|
|
1092
|
+
}
|
|
1093
|
+
async listForApp(appId) {
|
|
1094
|
+
return this.http.all(`/v1/apps/${appId}/betaGroups`);
|
|
1095
|
+
}
|
|
1096
|
+
async addBuilds(groupId, buildIds) {
|
|
1097
|
+
await this.http.post(`/v1/betaGroups/${groupId}/relationships/builds`, {
|
|
1098
|
+
data: buildIds.map((id) => ({ type: "builds", id }))
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
async removeBuilds(groupId, buildIds) {
|
|
1102
|
+
await this.http.request(
|
|
1103
|
+
`/v1/betaGroups/${groupId}/relationships/builds`,
|
|
1104
|
+
{
|
|
1105
|
+
method: "DELETE",
|
|
1106
|
+
body: {
|
|
1107
|
+
data: buildIds.map((id) => ({ type: "builds", id }))
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
);
|
|
1111
|
+
}
|
|
1112
|
+
async findByName(appId, name) {
|
|
1113
|
+
const groups = await this.listForApp(appId);
|
|
1114
|
+
return groups.find((g) => g.attributes.name === name) ?? null;
|
|
1115
|
+
}
|
|
1116
|
+
};
|
|
1117
|
+
|
|
1118
|
+
// src/resources/capabilities.ts
|
|
1119
|
+
var CapabilitiesResource = class {
|
|
1120
|
+
constructor(http) {
|
|
1121
|
+
this.http = http;
|
|
1122
|
+
}
|
|
1123
|
+
http;
|
|
1124
|
+
async listForBundleId(bundleIdId) {
|
|
1125
|
+
return this.http.all(
|
|
1126
|
+
`/v1/bundleIds/${bundleIdId}/bundleIdCapabilities`
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
async enable(params) {
|
|
1130
|
+
const attributes = {
|
|
1131
|
+
capabilityType: params.capabilityType
|
|
1132
|
+
};
|
|
1133
|
+
if (params.settings) {
|
|
1134
|
+
attributes.settings = params.settings;
|
|
1135
|
+
}
|
|
1136
|
+
const response = await this.http.post("/v1/bundleIdCapabilities", {
|
|
1137
|
+
data: {
|
|
1138
|
+
type: "bundleIdCapabilities",
|
|
1139
|
+
attributes,
|
|
1140
|
+
relationships: {
|
|
1141
|
+
bundleId: {
|
|
1142
|
+
data: { type: "bundleIds", id: params.bundleIdId }
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
});
|
|
1147
|
+
return response.data;
|
|
1148
|
+
}
|
|
1149
|
+
async update(capabilityId, params) {
|
|
1150
|
+
const attributes = {
|
|
1151
|
+
capabilityType: params.capabilityType
|
|
1152
|
+
};
|
|
1153
|
+
if (params.settings) {
|
|
1154
|
+
attributes.settings = params.settings;
|
|
1155
|
+
}
|
|
1156
|
+
const response = await this.http.patch(`/v1/bundleIdCapabilities/${capabilityId}`, {
|
|
1157
|
+
data: {
|
|
1158
|
+
type: "bundleIdCapabilities",
|
|
1159
|
+
id: capabilityId,
|
|
1160
|
+
attributes
|
|
1161
|
+
}
|
|
1162
|
+
});
|
|
1163
|
+
return response.data;
|
|
1164
|
+
}
|
|
1165
|
+
async disable(capabilityId) {
|
|
1166
|
+
await this.http.delete(`/v1/bundleIdCapabilities/${capabilityId}`);
|
|
1167
|
+
}
|
|
1168
|
+
};
|
|
1169
|
+
|
|
1170
|
+
// src/resources/app-store-versions.ts
|
|
1171
|
+
var AppStoreVersionsResource = class {
|
|
1172
|
+
constructor(http) {
|
|
1173
|
+
this.http = http;
|
|
1174
|
+
}
|
|
1175
|
+
http;
|
|
1176
|
+
async listForApp(appId, params) {
|
|
1177
|
+
const listParams = {
|
|
1178
|
+
filter: params?.filter,
|
|
1179
|
+
include: params?.include,
|
|
1180
|
+
limit: params?.limit ?? 200
|
|
1181
|
+
};
|
|
1182
|
+
return this.http.all(
|
|
1183
|
+
`/v1/apps/${appId}/appStoreVersions`,
|
|
1184
|
+
listParams
|
|
1185
|
+
);
|
|
1186
|
+
}
|
|
1187
|
+
async get(id, params) {
|
|
1188
|
+
const queryParams = {};
|
|
1189
|
+
if (params?.include) queryParams["include"] = params.include;
|
|
1190
|
+
const response = await this.http.get(
|
|
1191
|
+
`/v1/appStoreVersions/${id}`,
|
|
1192
|
+
queryParams
|
|
1193
|
+
);
|
|
1194
|
+
return response.data;
|
|
1195
|
+
}
|
|
1196
|
+
async create(params) {
|
|
1197
|
+
const attributes = {
|
|
1198
|
+
versionString: params.versionString,
|
|
1199
|
+
platform: params.platform
|
|
1200
|
+
};
|
|
1201
|
+
if (params.releaseType) attributes.releaseType = params.releaseType;
|
|
1202
|
+
if (params.earliestReleaseDate) attributes.earliestReleaseDate = params.earliestReleaseDate;
|
|
1203
|
+
if (params.copyright) attributes.copyright = params.copyright;
|
|
1204
|
+
const response = await this.http.post(
|
|
1205
|
+
"/v1/appStoreVersions",
|
|
1206
|
+
{
|
|
1207
|
+
data: {
|
|
1208
|
+
type: "appStoreVersions",
|
|
1209
|
+
attributes,
|
|
1210
|
+
relationships: {
|
|
1211
|
+
app: {
|
|
1212
|
+
data: { type: "apps", id: params.appId }
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
);
|
|
1218
|
+
return response.data;
|
|
1219
|
+
}
|
|
1220
|
+
async update(id, params) {
|
|
1221
|
+
const response = await this.http.patch(
|
|
1222
|
+
`/v1/appStoreVersions/${id}`,
|
|
1223
|
+
{
|
|
1224
|
+
data: {
|
|
1225
|
+
type: "appStoreVersions",
|
|
1226
|
+
id,
|
|
1227
|
+
attributes: params
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
);
|
|
1231
|
+
return response.data;
|
|
1232
|
+
}
|
|
1233
|
+
async setBuild(versionId, buildId) {
|
|
1234
|
+
await this.http.patch(`/v1/appStoreVersions/${versionId}/relationships/build`, {
|
|
1235
|
+
data: { type: "builds", id: buildId }
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
async getLocalizations(versionId) {
|
|
1239
|
+
return this.http.all(
|
|
1240
|
+
`/v1/appStoreVersions/${versionId}/appStoreVersionLocalizations`
|
|
1241
|
+
);
|
|
1242
|
+
}
|
|
1243
|
+
async createLocalization(params) {
|
|
1244
|
+
const { versionId, ...attributes } = params;
|
|
1245
|
+
const response = await this.http.post("/v1/appStoreVersionLocalizations", {
|
|
1246
|
+
data: {
|
|
1247
|
+
type: "appStoreVersionLocalizations",
|
|
1248
|
+
attributes,
|
|
1249
|
+
relationships: {
|
|
1250
|
+
appStoreVersion: {
|
|
1251
|
+
data: { type: "appStoreVersions", id: versionId }
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
});
|
|
1256
|
+
return response.data;
|
|
1257
|
+
}
|
|
1258
|
+
async updateLocalization(localizationId, params) {
|
|
1259
|
+
const response = await this.http.patch(`/v1/appStoreVersionLocalizations/${localizationId}`, {
|
|
1260
|
+
data: {
|
|
1261
|
+
type: "appStoreVersionLocalizations",
|
|
1262
|
+
id: localizationId,
|
|
1263
|
+
attributes: params
|
|
1264
|
+
}
|
|
1265
|
+
});
|
|
1266
|
+
return response.data;
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1269
|
+
|
|
1270
|
+
// src/resources/app-screenshots.ts
|
|
1271
|
+
var AppScreenshotsResource = class {
|
|
1272
|
+
constructor(http) {
|
|
1273
|
+
this.http = http;
|
|
1274
|
+
}
|
|
1275
|
+
http;
|
|
1276
|
+
async listSetsForLocalization(localizationId) {
|
|
1277
|
+
return this.http.all(
|
|
1278
|
+
`/v1/appStoreVersionLocalizations/${localizationId}/appScreenshotSets`
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
async createSet(params) {
|
|
1282
|
+
const response = await this.http.post("/v1/appScreenshotSets", {
|
|
1283
|
+
data: {
|
|
1284
|
+
type: "appScreenshotSets",
|
|
1285
|
+
attributes: {
|
|
1286
|
+
screenshotDisplayType: params.screenshotDisplayType
|
|
1287
|
+
},
|
|
1288
|
+
relationships: {
|
|
1289
|
+
appStoreVersionLocalization: {
|
|
1290
|
+
data: {
|
|
1291
|
+
type: "appStoreVersionLocalizations",
|
|
1292
|
+
id: params.localizationId
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
});
|
|
1298
|
+
return response.data;
|
|
1299
|
+
}
|
|
1300
|
+
async listScreenshots(setId) {
|
|
1301
|
+
return this.http.all(
|
|
1302
|
+
`/v1/appScreenshotSets/${setId}/appScreenshots`
|
|
1303
|
+
);
|
|
1304
|
+
}
|
|
1305
|
+
async reserveScreenshot(params) {
|
|
1306
|
+
const response = await this.http.post("/v1/appScreenshots", {
|
|
1307
|
+
data: {
|
|
1308
|
+
type: "appScreenshots",
|
|
1309
|
+
attributes: {
|
|
1310
|
+
fileName: params.fileName,
|
|
1311
|
+
fileSize: params.fileSize
|
|
1312
|
+
},
|
|
1313
|
+
relationships: {
|
|
1314
|
+
appScreenshotSet: {
|
|
1315
|
+
data: { type: "appScreenshotSets", id: params.setId }
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
});
|
|
1320
|
+
return response.data;
|
|
1321
|
+
}
|
|
1322
|
+
async commitScreenshot(screenshotId, params) {
|
|
1323
|
+
const response = await this.http.patch(`/v1/appScreenshots/${screenshotId}`, {
|
|
1324
|
+
data: {
|
|
1325
|
+
type: "appScreenshots",
|
|
1326
|
+
id: screenshotId,
|
|
1327
|
+
attributes: {
|
|
1328
|
+
sourceFileChecksum: params.sourceFileChecksum,
|
|
1329
|
+
uploaded: params.uploaded
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
});
|
|
1333
|
+
return response.data;
|
|
1334
|
+
}
|
|
1335
|
+
async deleteScreenshot(screenshotId) {
|
|
1336
|
+
await this.http.delete(`/v1/appScreenshots/${screenshotId}`);
|
|
1337
|
+
}
|
|
1338
|
+
async deleteSet(setId) {
|
|
1339
|
+
await this.http.delete(`/v1/appScreenshotSets/${setId}`);
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1342
|
+
|
|
1343
|
+
// src/resources/review-submissions.ts
|
|
1344
|
+
var ReviewSubmissionsResource = class {
|
|
1345
|
+
constructor(http) {
|
|
1346
|
+
this.http = http;
|
|
1347
|
+
}
|
|
1348
|
+
http;
|
|
1349
|
+
async submitVersion(versionId) {
|
|
1350
|
+
const response = await this.http.post("/v1/appStoreVersionSubmissions", {
|
|
1351
|
+
data: {
|
|
1352
|
+
type: "appStoreVersionSubmissions",
|
|
1353
|
+
relationships: {
|
|
1354
|
+
appStoreVersion: {
|
|
1355
|
+
data: { type: "appStoreVersions", id: versionId }
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
});
|
|
1360
|
+
return response.data;
|
|
1361
|
+
}
|
|
1362
|
+
async createReviewSubmission(params) {
|
|
1363
|
+
const response = await this.http.post("/v1/reviewSubmissions", {
|
|
1364
|
+
data: {
|
|
1365
|
+
type: "reviewSubmissions",
|
|
1366
|
+
attributes: {
|
|
1367
|
+
platform: params.platform
|
|
1368
|
+
},
|
|
1369
|
+
relationships: {
|
|
1370
|
+
app: {
|
|
1371
|
+
data: { type: "apps", id: params.appId }
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1376
|
+
return response.data;
|
|
1377
|
+
}
|
|
1378
|
+
async confirmReviewSubmission(submissionId) {
|
|
1379
|
+
const response = await this.http.patch(`/v1/reviewSubmissions/${submissionId}`, {
|
|
1380
|
+
data: {
|
|
1381
|
+
type: "reviewSubmissions",
|
|
1382
|
+
id: submissionId,
|
|
1383
|
+
attributes: {
|
|
1384
|
+
submitted: true
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1388
|
+
return response.data;
|
|
1389
|
+
}
|
|
1390
|
+
};
|
|
1391
|
+
|
|
1392
|
+
// src/resources/app-info.ts
|
|
1393
|
+
var AppInfosResource = class {
|
|
1394
|
+
constructor(http) {
|
|
1395
|
+
this.http = http;
|
|
1396
|
+
}
|
|
1397
|
+
http;
|
|
1398
|
+
async listForApp(appId, params) {
|
|
1399
|
+
const listParams = {
|
|
1400
|
+
limit: params?.limit ?? 200,
|
|
1401
|
+
include: params?.include
|
|
1402
|
+
};
|
|
1403
|
+
return this.http.all(`/v1/apps/${appId}/appInfos`, listParams);
|
|
1404
|
+
}
|
|
1405
|
+
async get(id, params) {
|
|
1406
|
+
const queryParams = {};
|
|
1407
|
+
if (params?.include) queryParams["include"] = params.include;
|
|
1408
|
+
const response = await this.http.get(
|
|
1409
|
+
`/v1/appInfos/${id}`,
|
|
1410
|
+
queryParams
|
|
1411
|
+
);
|
|
1412
|
+
return response.data;
|
|
1413
|
+
}
|
|
1414
|
+
async update(id, relationships) {
|
|
1415
|
+
const response = await this.http.patch(
|
|
1416
|
+
`/v1/appInfos/${id}`,
|
|
1417
|
+
{
|
|
1418
|
+
data: {
|
|
1419
|
+
type: "appInfos",
|
|
1420
|
+
id,
|
|
1421
|
+
...relationships ? {
|
|
1422
|
+
relationships: Object.fromEntries(
|
|
1423
|
+
Object.entries(relationships).map(([k, v]) => [k, { data: v }])
|
|
1424
|
+
)
|
|
1425
|
+
} : {}
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
);
|
|
1429
|
+
return response.data;
|
|
1430
|
+
}
|
|
1431
|
+
async delete(id) {
|
|
1432
|
+
await this.http.delete(`/v1/appInfos/${id}`);
|
|
1433
|
+
}
|
|
1434
|
+
};
|
|
1435
|
+
|
|
1436
|
+
// src/resources/app-info-localizations.ts
|
|
1437
|
+
var AppInfoLocalizationsResource = class {
|
|
1438
|
+
constructor(http) {
|
|
1439
|
+
this.http = http;
|
|
1440
|
+
}
|
|
1441
|
+
http;
|
|
1442
|
+
async listForAppInfo(appInfoId, params) {
|
|
1443
|
+
const listParams = {
|
|
1444
|
+
limit: params?.limit ?? 200
|
|
1445
|
+
};
|
|
1446
|
+
return this.http.all(
|
|
1447
|
+
`/v1/appInfos/${appInfoId}/appInfoLocalizations`,
|
|
1448
|
+
listParams
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
async get(id) {
|
|
1452
|
+
const response = await this.http.get(
|
|
1453
|
+
`/v1/appInfoLocalizations/${id}`
|
|
1454
|
+
);
|
|
1455
|
+
return response.data;
|
|
1456
|
+
}
|
|
1457
|
+
async create(params) {
|
|
1458
|
+
const response = await this.http.post(
|
|
1459
|
+
"/v1/appInfoLocalizations",
|
|
1460
|
+
{
|
|
1461
|
+
data: {
|
|
1462
|
+
type: "appInfoLocalizations",
|
|
1463
|
+
attributes: params.attributes,
|
|
1464
|
+
relationships: {
|
|
1465
|
+
appInfo: { data: { type: "appInfos", id: params.appInfoId } }
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
);
|
|
1470
|
+
return response.data;
|
|
1471
|
+
}
|
|
1472
|
+
async update(id, attributes) {
|
|
1473
|
+
const response = await this.http.patch(
|
|
1474
|
+
`/v1/appInfoLocalizations/${id}`,
|
|
1475
|
+
{ data: { type: "appInfoLocalizations", id, attributes } }
|
|
1476
|
+
);
|
|
1477
|
+
return response.data;
|
|
1478
|
+
}
|
|
1479
|
+
async delete(id) {
|
|
1480
|
+
await this.http.delete(`/v1/appInfoLocalizations/${id}`);
|
|
1481
|
+
}
|
|
1482
|
+
};
|
|
1483
|
+
|
|
1484
|
+
// src/resources/app-store-review-details.ts
|
|
1485
|
+
var AppStoreReviewDetailsResource = class {
|
|
1486
|
+
constructor(http) {
|
|
1487
|
+
this.http = http;
|
|
1488
|
+
}
|
|
1489
|
+
http;
|
|
1490
|
+
async getForAppStoreVersion(appStoreVersionId) {
|
|
1491
|
+
const response = await this.http.get(`/v1/appStoreVersions/${appStoreVersionId}/appStoreReviewDetail`);
|
|
1492
|
+
return response.data;
|
|
1493
|
+
}
|
|
1494
|
+
async get(id) {
|
|
1495
|
+
const response = await this.http.get(`/v1/appStoreReviewDetails/${id}`);
|
|
1496
|
+
return response.data;
|
|
1497
|
+
}
|
|
1498
|
+
async create(params) {
|
|
1499
|
+
const response = await this.http.post("/v1/appStoreReviewDetails", {
|
|
1500
|
+
data: {
|
|
1501
|
+
type: "appStoreReviewDetails",
|
|
1502
|
+
attributes: params.attributes,
|
|
1503
|
+
relationships: {
|
|
1504
|
+
appStoreVersion: {
|
|
1505
|
+
data: { type: "appStoreVersions", id: params.appStoreVersionId }
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
});
|
|
1510
|
+
return response.data;
|
|
1511
|
+
}
|
|
1512
|
+
async update(id, attributes) {
|
|
1513
|
+
const response = await this.http.patch(`/v1/appStoreReviewDetails/${id}`, {
|
|
1514
|
+
data: { type: "appStoreReviewDetails", id, attributes }
|
|
1515
|
+
});
|
|
1516
|
+
return response.data;
|
|
1517
|
+
}
|
|
1518
|
+
};
|
|
1519
|
+
|
|
1520
|
+
// src/resources/beta-testers.ts
|
|
1521
|
+
var BetaTestersResource = class {
|
|
1522
|
+
constructor(http) {
|
|
1523
|
+
this.http = http;
|
|
1524
|
+
}
|
|
1525
|
+
http;
|
|
1526
|
+
async list(params) {
|
|
1527
|
+
const listParams = {
|
|
1528
|
+
filter: params?.filter,
|
|
1529
|
+
include: params?.include,
|
|
1530
|
+
limit: params?.limit ?? 200,
|
|
1531
|
+
sort: params?.sort
|
|
1532
|
+
};
|
|
1533
|
+
return this.http.all("/v1/betaTesters", listParams);
|
|
1534
|
+
}
|
|
1535
|
+
async get(id) {
|
|
1536
|
+
const response = await this.http.get(
|
|
1537
|
+
`/v1/betaTesters/${id}`
|
|
1538
|
+
);
|
|
1539
|
+
return response.data;
|
|
1540
|
+
}
|
|
1541
|
+
async create(params) {
|
|
1542
|
+
const attributes = {
|
|
1543
|
+
email: params.email,
|
|
1544
|
+
firstName: params.firstName,
|
|
1545
|
+
lastName: params.lastName
|
|
1546
|
+
};
|
|
1547
|
+
const relationships = {};
|
|
1548
|
+
if (params.betaGroupIds?.length) {
|
|
1549
|
+
relationships.betaGroups = {
|
|
1550
|
+
data: params.betaGroupIds.map((id) => ({ type: "betaGroups", id }))
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
if (params.appIds?.length) {
|
|
1554
|
+
relationships.apps = {
|
|
1555
|
+
data: params.appIds.map((id) => ({ type: "apps", id }))
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
const response = await this.http.post(
|
|
1559
|
+
"/v1/betaTesters",
|
|
1560
|
+
{
|
|
1561
|
+
data: {
|
|
1562
|
+
type: "betaTesters",
|
|
1563
|
+
attributes,
|
|
1564
|
+
...Object.keys(relationships).length ? { relationships } : {}
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
);
|
|
1568
|
+
return response.data;
|
|
1569
|
+
}
|
|
1570
|
+
async delete(id) {
|
|
1571
|
+
await this.http.delete(`/v1/betaTesters/${id}`);
|
|
1572
|
+
}
|
|
1573
|
+
async findByEmail(email) {
|
|
1574
|
+
const results = await this.list({ filter: { email }, limit: 1 });
|
|
1575
|
+
return results[0] ?? null;
|
|
1576
|
+
}
|
|
1577
|
+
};
|
|
1578
|
+
|
|
1579
|
+
// src/resources/beta-app-review-submissions.ts
|
|
1580
|
+
var BetaAppReviewSubmissionsResource = class {
|
|
1581
|
+
constructor(http) {
|
|
1582
|
+
this.http = http;
|
|
1583
|
+
}
|
|
1584
|
+
http;
|
|
1585
|
+
async list(params) {
|
|
1586
|
+
const listParams = {
|
|
1587
|
+
filter: params?.filter,
|
|
1588
|
+
limit: params?.limit ?? 200
|
|
1589
|
+
};
|
|
1590
|
+
return this.http.all(
|
|
1591
|
+
"/v1/betaAppReviewSubmissions",
|
|
1592
|
+
listParams
|
|
1593
|
+
);
|
|
1594
|
+
}
|
|
1595
|
+
async get(id) {
|
|
1596
|
+
const response = await this.http.get(
|
|
1597
|
+
`/v1/betaAppReviewSubmissions/${id}`
|
|
1598
|
+
);
|
|
1599
|
+
return response.data;
|
|
1600
|
+
}
|
|
1601
|
+
async create(buildId) {
|
|
1602
|
+
const response = await this.http.post(
|
|
1603
|
+
"/v1/betaAppReviewSubmissions",
|
|
1604
|
+
{
|
|
1605
|
+
data: {
|
|
1606
|
+
type: "betaAppReviewSubmissions",
|
|
1607
|
+
relationships: {
|
|
1608
|
+
build: { data: { type: "builds", id: buildId } }
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
);
|
|
1613
|
+
return response.data;
|
|
1614
|
+
}
|
|
1615
|
+
};
|
|
1616
|
+
|
|
1617
|
+
// src/resources/beta-app-review-details.ts
|
|
1618
|
+
var BetaAppReviewDetailsResource = class {
|
|
1619
|
+
constructor(http) {
|
|
1620
|
+
this.http = http;
|
|
1621
|
+
}
|
|
1622
|
+
http;
|
|
1623
|
+
async getForApp(appId) {
|
|
1624
|
+
const response = await this.http.get(
|
|
1625
|
+
`/v1/apps/${appId}/betaAppReviewDetail`
|
|
1626
|
+
);
|
|
1627
|
+
return response.data;
|
|
1628
|
+
}
|
|
1629
|
+
async get(id) {
|
|
1630
|
+
const response = await this.http.get(
|
|
1631
|
+
`/v1/betaAppReviewDetails/${id}`
|
|
1632
|
+
);
|
|
1633
|
+
return response.data;
|
|
1634
|
+
}
|
|
1635
|
+
async update(id, attributes) {
|
|
1636
|
+
const response = await this.http.patch(
|
|
1637
|
+
`/v1/betaAppReviewDetails/${id}`,
|
|
1638
|
+
{ data: { type: "betaAppReviewDetails", id, attributes } }
|
|
1639
|
+
);
|
|
1640
|
+
return response.data;
|
|
1641
|
+
}
|
|
1642
|
+
};
|
|
1643
|
+
|
|
1644
|
+
// src/resources/beta-invitations.ts
|
|
1645
|
+
var BetaInvitationsResource = class {
|
|
1646
|
+
constructor(http) {
|
|
1647
|
+
this.http = http;
|
|
1648
|
+
}
|
|
1649
|
+
http;
|
|
1650
|
+
/** Send a TestFlight invitation email for an existing tester + app. */
|
|
1651
|
+
async send(params) {
|
|
1652
|
+
const response = await this.http.post(
|
|
1653
|
+
"/v1/betaTesterInvitations",
|
|
1654
|
+
{
|
|
1655
|
+
data: {
|
|
1656
|
+
type: "betaTesterInvitations",
|
|
1657
|
+
relationships: {
|
|
1658
|
+
app: { data: { type: "apps", id: params.appId } },
|
|
1659
|
+
betaTester: { data: { type: "betaTesters", id: params.betaTesterId } }
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
);
|
|
1664
|
+
return response.data;
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
|
|
1668
|
+
// src/resources/beta-licenses.ts
|
|
1669
|
+
var BetaLicensesResource = class {
|
|
1670
|
+
constructor(http) {
|
|
1671
|
+
this.http = http;
|
|
1672
|
+
}
|
|
1673
|
+
http;
|
|
1674
|
+
async list(params) {
|
|
1675
|
+
const listParams = {
|
|
1676
|
+
limit: params?.limit ?? 200
|
|
1677
|
+
};
|
|
1678
|
+
return this.http.all(
|
|
1679
|
+
"/v1/betaLicenseAgreements",
|
|
1680
|
+
listParams
|
|
1681
|
+
);
|
|
1682
|
+
}
|
|
1683
|
+
async get(id) {
|
|
1684
|
+
const response = await this.http.get(
|
|
1685
|
+
`/v1/betaLicenseAgreements/${id}`
|
|
1686
|
+
);
|
|
1687
|
+
return response.data;
|
|
1688
|
+
}
|
|
1689
|
+
async getForApp(appId) {
|
|
1690
|
+
const response = await this.http.get(
|
|
1691
|
+
`/v1/apps/${appId}/betaLicenseAgreement`
|
|
1692
|
+
);
|
|
1693
|
+
return response.data;
|
|
1694
|
+
}
|
|
1695
|
+
async update(id, attributes) {
|
|
1696
|
+
const response = await this.http.patch(`/v1/betaLicenseAgreements/${id}`, {
|
|
1697
|
+
data: { type: "betaLicenseAgreements", id, attributes }
|
|
1698
|
+
});
|
|
1699
|
+
return response.data;
|
|
1700
|
+
}
|
|
1701
|
+
};
|
|
1702
|
+
|
|
1703
|
+
// src/resources/app-previews.ts
|
|
1704
|
+
var AppPreviewsResource = class {
|
|
1705
|
+
constructor(http) {
|
|
1706
|
+
this.http = http;
|
|
1707
|
+
}
|
|
1708
|
+
http;
|
|
1709
|
+
async get(id) {
|
|
1710
|
+
const response = await this.http.get(
|
|
1711
|
+
`/v1/appPreviews/${id}`
|
|
1712
|
+
);
|
|
1713
|
+
return response.data;
|
|
1714
|
+
}
|
|
1715
|
+
async create(params) {
|
|
1716
|
+
const { appPreviewSetId, ...rest } = params;
|
|
1717
|
+
const response = await this.http.post(
|
|
1718
|
+
"/v1/appPreviews",
|
|
1719
|
+
{
|
|
1720
|
+
data: {
|
|
1721
|
+
type: "appPreviews",
|
|
1722
|
+
attributes: rest,
|
|
1723
|
+
relationships: {
|
|
1724
|
+
appPreviewSet: {
|
|
1725
|
+
data: { type: "appPreviewSets", id: appPreviewSetId }
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
);
|
|
1731
|
+
return response.data;
|
|
1732
|
+
}
|
|
1733
|
+
async update(id, attributes) {
|
|
1734
|
+
const response = await this.http.patch(
|
|
1735
|
+
`/v1/appPreviews/${id}`,
|
|
1736
|
+
{ data: { type: "appPreviews", id, attributes } }
|
|
1737
|
+
);
|
|
1738
|
+
return response.data;
|
|
1739
|
+
}
|
|
1740
|
+
async delete(id) {
|
|
1741
|
+
await this.http.delete(`/v1/appPreviews/${id}`);
|
|
1742
|
+
}
|
|
1743
|
+
};
|
|
1744
|
+
|
|
1745
|
+
// src/resources/app-preview-sets.ts
|
|
1746
|
+
var AppPreviewSetsResource = class {
|
|
1747
|
+
constructor(http) {
|
|
1748
|
+
this.http = http;
|
|
1749
|
+
}
|
|
1750
|
+
http;
|
|
1751
|
+
async listForLocalization(localizationId, params) {
|
|
1752
|
+
const listParams = {
|
|
1753
|
+
limit: params?.limit ?? 200,
|
|
1754
|
+
include: params?.include
|
|
1755
|
+
};
|
|
1756
|
+
return this.http.all(
|
|
1757
|
+
`/v1/appStoreVersionLocalizations/${localizationId}/appPreviewSets`,
|
|
1758
|
+
listParams
|
|
1759
|
+
);
|
|
1760
|
+
}
|
|
1761
|
+
async get(id, params) {
|
|
1762
|
+
const queryParams = {};
|
|
1763
|
+
if (params?.include) queryParams["include"] = params.include;
|
|
1764
|
+
const response = await this.http.get(
|
|
1765
|
+
`/v1/appPreviewSets/${id}`,
|
|
1766
|
+
queryParams
|
|
1767
|
+
);
|
|
1768
|
+
return response.data;
|
|
1769
|
+
}
|
|
1770
|
+
async create(params) {
|
|
1771
|
+
const response = await this.http.post(
|
|
1772
|
+
"/v1/appPreviewSets",
|
|
1773
|
+
{
|
|
1774
|
+
data: {
|
|
1775
|
+
type: "appPreviewSets",
|
|
1776
|
+
attributes: { previewType: params.previewType },
|
|
1777
|
+
relationships: {
|
|
1778
|
+
appStoreVersionLocalization: {
|
|
1779
|
+
data: {
|
|
1780
|
+
type: "appStoreVersionLocalizations",
|
|
1781
|
+
id: params.appStoreVersionLocalizationId
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
);
|
|
1788
|
+
return response.data;
|
|
1789
|
+
}
|
|
1790
|
+
async delete(id) {
|
|
1791
|
+
await this.http.delete(`/v1/appPreviewSets/${id}`);
|
|
1792
|
+
}
|
|
1793
|
+
};
|
|
1794
|
+
|
|
1795
|
+
// src/resources/app-prices.ts
|
|
1796
|
+
var AppPricesResource = class {
|
|
1797
|
+
constructor(http) {
|
|
1798
|
+
this.http = http;
|
|
1799
|
+
}
|
|
1800
|
+
http;
|
|
1801
|
+
async listForApp(appId, params) {
|
|
1802
|
+
const listParams = {
|
|
1803
|
+
limit: params?.limit ?? 200,
|
|
1804
|
+
include: params?.include
|
|
1805
|
+
};
|
|
1806
|
+
return this.http.all(`/v1/apps/${appId}/prices`, listParams);
|
|
1807
|
+
}
|
|
1808
|
+
async get(id, params) {
|
|
1809
|
+
const queryParams = {};
|
|
1810
|
+
if (params?.include) queryParams["include"] = params.include;
|
|
1811
|
+
const response = await this.http.get(
|
|
1812
|
+
`/v1/appPrices/${id}`,
|
|
1813
|
+
queryParams
|
|
1814
|
+
);
|
|
1815
|
+
return response.data;
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
|
|
1819
|
+
// src/resources/territories.ts
|
|
1820
|
+
var TerritoriesResource = class {
|
|
1821
|
+
constructor(http) {
|
|
1822
|
+
this.http = http;
|
|
1823
|
+
}
|
|
1824
|
+
http;
|
|
1825
|
+
async list(params) {
|
|
1826
|
+
const listParams = {
|
|
1827
|
+
limit: params?.limit ?? 200
|
|
1828
|
+
};
|
|
1829
|
+
return this.http.all("/v1/territories", listParams);
|
|
1830
|
+
}
|
|
1831
|
+
async get(id) {
|
|
1832
|
+
const response = await this.http.get(
|
|
1833
|
+
`/v1/territories/${id}`
|
|
1834
|
+
);
|
|
1835
|
+
return response.data;
|
|
1836
|
+
}
|
|
1837
|
+
};
|
|
1838
|
+
|
|
1839
|
+
// src/resources/age-rating-declarations.ts
|
|
1840
|
+
var AgeRatingDeclarationsResource = class {
|
|
1841
|
+
constructor(http) {
|
|
1842
|
+
this.http = http;
|
|
1843
|
+
}
|
|
1844
|
+
http;
|
|
1845
|
+
async get(id) {
|
|
1846
|
+
const response = await this.http.get(
|
|
1847
|
+
`/v1/ageRatingDeclarations/${id}`
|
|
1848
|
+
);
|
|
1849
|
+
return response.data;
|
|
1850
|
+
}
|
|
1851
|
+
async update(id, attributes) {
|
|
1852
|
+
const response = await this.http.patch(`/v1/ageRatingDeclarations/${id}`, {
|
|
1853
|
+
data: { type: "ageRatingDeclarations", id, attributes }
|
|
1854
|
+
});
|
|
1855
|
+
return response.data;
|
|
1856
|
+
}
|
|
1857
|
+
};
|
|
1858
|
+
|
|
1859
|
+
// src/resources/app-categories.ts
|
|
1860
|
+
var AppCategoriesResource = class {
|
|
1861
|
+
constructor(http) {
|
|
1862
|
+
this.http = http;
|
|
1863
|
+
}
|
|
1864
|
+
http;
|
|
1865
|
+
async list(params) {
|
|
1866
|
+
const listParams = {
|
|
1867
|
+
filter: params?.filter,
|
|
1868
|
+
include: params?.include,
|
|
1869
|
+
limit: params?.limit ?? 200
|
|
1870
|
+
};
|
|
1871
|
+
return this.http.all("/v1/appCategories", listParams);
|
|
1872
|
+
}
|
|
1873
|
+
async get(id, params) {
|
|
1874
|
+
const queryParams = {};
|
|
1875
|
+
if (params?.include) queryParams["include"] = params.include;
|
|
1876
|
+
const response = await this.http.get(
|
|
1877
|
+
`/v1/appCategories/${id}`,
|
|
1878
|
+
queryParams
|
|
1879
|
+
);
|
|
1880
|
+
return response.data;
|
|
1881
|
+
}
|
|
1882
|
+
};
|
|
1883
|
+
|
|
1884
|
+
// src/resources/app-encryption-declarations.ts
|
|
1885
|
+
var AppEncryptionDeclarationsResource = class {
|
|
1886
|
+
constructor(http) {
|
|
1887
|
+
this.http = http;
|
|
1888
|
+
}
|
|
1889
|
+
http;
|
|
1890
|
+
async list(params) {
|
|
1891
|
+
const listParams = {
|
|
1892
|
+
filter: params?.filter,
|
|
1893
|
+
limit: params?.limit ?? 200
|
|
1894
|
+
};
|
|
1895
|
+
return this.http.all(
|
|
1896
|
+
"/v1/appEncryptionDeclarations",
|
|
1897
|
+
listParams
|
|
1898
|
+
);
|
|
1899
|
+
}
|
|
1900
|
+
async get(id) {
|
|
1901
|
+
const response = await this.http.get(`/v1/appEncryptionDeclarations/${id}`);
|
|
1902
|
+
return response.data;
|
|
1903
|
+
}
|
|
1904
|
+
async assignToBuild(params) {
|
|
1905
|
+
await this.http.post(
|
|
1906
|
+
`/v1/appEncryptionDeclarations/${params.declarationId}/relationships/builds`,
|
|
1907
|
+
{ data: params.buildIds.map((id) => ({ type: "builds", id })) }
|
|
1908
|
+
);
|
|
1909
|
+
}
|
|
1910
|
+
};
|
|
1911
|
+
|
|
1912
|
+
// src/resources/idfa-declarations.ts
|
|
1913
|
+
var IdfaDeclarationsResource = class {
|
|
1914
|
+
constructor(http) {
|
|
1915
|
+
this.http = http;
|
|
1916
|
+
}
|
|
1917
|
+
http;
|
|
1918
|
+
async getForAppStoreVersion(appStoreVersionId) {
|
|
1919
|
+
const response = await this.http.get(
|
|
1920
|
+
`/v1/appStoreVersions/${appStoreVersionId}/idfaDeclaration`
|
|
1921
|
+
);
|
|
1922
|
+
return response.data;
|
|
1923
|
+
}
|
|
1924
|
+
async get(id) {
|
|
1925
|
+
const response = await this.http.get(
|
|
1926
|
+
`/v1/idfaDeclarations/${id}`
|
|
1927
|
+
);
|
|
1928
|
+
return response.data;
|
|
1929
|
+
}
|
|
1930
|
+
async create(params) {
|
|
1931
|
+
const response = await this.http.post(
|
|
1932
|
+
"/v1/idfaDeclarations",
|
|
1933
|
+
{
|
|
1934
|
+
data: {
|
|
1935
|
+
type: "idfaDeclarations",
|
|
1936
|
+
attributes: params.attributes,
|
|
1937
|
+
relationships: {
|
|
1938
|
+
appStoreVersion: {
|
|
1939
|
+
data: { type: "appStoreVersions", id: params.appStoreVersionId }
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
);
|
|
1945
|
+
return response.data;
|
|
1946
|
+
}
|
|
1947
|
+
async update(id, attributes) {
|
|
1948
|
+
const response = await this.http.patch(
|
|
1949
|
+
`/v1/idfaDeclarations/${id}`,
|
|
1950
|
+
{ data: { type: "idfaDeclarations", id, attributes } }
|
|
1951
|
+
);
|
|
1952
|
+
return response.data;
|
|
1953
|
+
}
|
|
1954
|
+
async delete(id) {
|
|
1955
|
+
await this.http.delete(`/v1/idfaDeclarations/${id}`);
|
|
1956
|
+
}
|
|
1957
|
+
};
|
|
1958
|
+
|
|
1959
|
+
// src/resources/pre-release-versions.ts
|
|
1960
|
+
var PreReleaseVersionsResource = class {
|
|
1961
|
+
constructor(http) {
|
|
1962
|
+
this.http = http;
|
|
1963
|
+
}
|
|
1964
|
+
http;
|
|
1965
|
+
async list(params) {
|
|
1966
|
+
const listParams = {
|
|
1967
|
+
filter: params?.filter,
|
|
1968
|
+
include: params?.include,
|
|
1969
|
+
limit: params?.limit ?? 200,
|
|
1970
|
+
sort: params?.sort
|
|
1971
|
+
};
|
|
1972
|
+
return this.http.all(
|
|
1973
|
+
"/v1/preReleaseVersions",
|
|
1974
|
+
listParams
|
|
1975
|
+
);
|
|
1976
|
+
}
|
|
1977
|
+
async get(id, params) {
|
|
1978
|
+
const queryParams = {};
|
|
1979
|
+
if (params?.include) queryParams["include"] = params.include;
|
|
1980
|
+
const response = await this.http.get(
|
|
1981
|
+
`/v1/preReleaseVersions/${id}`,
|
|
1982
|
+
queryParams
|
|
1983
|
+
);
|
|
1984
|
+
return response.data;
|
|
1985
|
+
}
|
|
1986
|
+
async findByVersion(params) {
|
|
1987
|
+
const filter = {
|
|
1988
|
+
app: params.appId,
|
|
1989
|
+
version: params.version
|
|
1990
|
+
};
|
|
1991
|
+
if (params.platform) filter.platform = params.platform;
|
|
1992
|
+
const results = await this.list({ filter, limit: 1 });
|
|
1993
|
+
return results[0] ?? null;
|
|
1994
|
+
}
|
|
1995
|
+
};
|
|
1996
|
+
|
|
1997
|
+
// src/resources/review-submission-items.ts
|
|
1998
|
+
var ReviewSubmissionItemsResource = class {
|
|
1999
|
+
constructor(http) {
|
|
2000
|
+
this.http = http;
|
|
2001
|
+
}
|
|
2002
|
+
http;
|
|
2003
|
+
async listForSubmission(reviewSubmissionId, params) {
|
|
2004
|
+
const listParams = {
|
|
2005
|
+
include: params?.include,
|
|
2006
|
+
limit: params?.limit ?? 200
|
|
2007
|
+
};
|
|
2008
|
+
return this.http.all(
|
|
2009
|
+
`/v1/reviewSubmissions/${reviewSubmissionId}/items`,
|
|
2010
|
+
listParams
|
|
2011
|
+
);
|
|
2012
|
+
}
|
|
2013
|
+
async get(id) {
|
|
2014
|
+
const response = await this.http.get(
|
|
2015
|
+
`/v1/reviewSubmissionItems/${id}`
|
|
2016
|
+
);
|
|
2017
|
+
return response.data;
|
|
2018
|
+
}
|
|
2019
|
+
async create(params) {
|
|
2020
|
+
const relationships = {
|
|
2021
|
+
reviewSubmission: {
|
|
2022
|
+
data: { type: "reviewSubmissions", id: params.reviewSubmissionId }
|
|
2023
|
+
}
|
|
2024
|
+
};
|
|
2025
|
+
if (params.appStoreVersionId) {
|
|
2026
|
+
relationships.appStoreVersion = {
|
|
2027
|
+
data: { type: "appStoreVersions", id: params.appStoreVersionId }
|
|
2028
|
+
};
|
|
2029
|
+
}
|
|
2030
|
+
if (params.appCustomProductPageVersionId) {
|
|
2031
|
+
relationships.appCustomProductPageVersion = {
|
|
2032
|
+
data: {
|
|
2033
|
+
type: "appCustomProductPageVersions",
|
|
2034
|
+
id: params.appCustomProductPageVersionId
|
|
2035
|
+
}
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2038
|
+
if (params.appStoreVersionExperimentId) {
|
|
2039
|
+
relationships.appStoreVersionExperiment = {
|
|
2040
|
+
data: {
|
|
2041
|
+
type: "appStoreVersionExperiments",
|
|
2042
|
+
id: params.appStoreVersionExperimentId
|
|
2043
|
+
}
|
|
2044
|
+
};
|
|
2045
|
+
}
|
|
2046
|
+
const response = await this.http.post(
|
|
2047
|
+
"/v1/reviewSubmissionItems",
|
|
2048
|
+
{
|
|
2049
|
+
data: {
|
|
2050
|
+
type: "reviewSubmissionItems",
|
|
2051
|
+
relationships
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
);
|
|
2055
|
+
return response.data;
|
|
2056
|
+
}
|
|
2057
|
+
async update(id, attributes) {
|
|
2058
|
+
const response = await this.http.patch(
|
|
2059
|
+
`/v1/reviewSubmissionItems/${id}`,
|
|
2060
|
+
{ data: { type: "reviewSubmissionItems", id, attributes } }
|
|
2061
|
+
);
|
|
2062
|
+
return response.data;
|
|
2063
|
+
}
|
|
2064
|
+
async delete(id) {
|
|
2065
|
+
await this.http.delete(`/v1/reviewSubmissionItems/${id}`);
|
|
2066
|
+
}
|
|
2067
|
+
};
|
|
2068
|
+
|
|
2069
|
+
// src/resources/users.ts
|
|
2070
|
+
var UsersResource = class {
|
|
2071
|
+
constructor(http) {
|
|
2072
|
+
this.http = http;
|
|
2073
|
+
}
|
|
2074
|
+
http;
|
|
2075
|
+
async list(params) {
|
|
2076
|
+
const listParams = {
|
|
2077
|
+
filter: params?.filter,
|
|
2078
|
+
include: params?.include,
|
|
2079
|
+
limit: params?.limit ?? 200,
|
|
2080
|
+
sort: params?.sort
|
|
2081
|
+
};
|
|
2082
|
+
return this.http.all("/v1/users", listParams);
|
|
2083
|
+
}
|
|
2084
|
+
async get(id) {
|
|
2085
|
+
const response = await this.http.get(`/v1/users/${id}`);
|
|
2086
|
+
return response.data;
|
|
2087
|
+
}
|
|
2088
|
+
async update(id, attributes, visibleAppIds) {
|
|
2089
|
+
const relationships = visibleAppIds ? {
|
|
2090
|
+
visibleApps: {
|
|
2091
|
+
data: visibleAppIds.map((id2) => ({ type: "apps", id: id2 }))
|
|
2092
|
+
}
|
|
2093
|
+
} : void 0;
|
|
2094
|
+
const response = await this.http.patch(
|
|
2095
|
+
`/v1/users/${id}`,
|
|
2096
|
+
{
|
|
2097
|
+
data: {
|
|
2098
|
+
type: "users",
|
|
2099
|
+
id,
|
|
2100
|
+
attributes,
|
|
2101
|
+
...relationships ? { relationships } : {}
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
);
|
|
2105
|
+
return response.data;
|
|
2106
|
+
}
|
|
2107
|
+
async delete(id) {
|
|
2108
|
+
await this.http.delete(`/v1/users/${id}`);
|
|
2109
|
+
}
|
|
2110
|
+
};
|
|
2111
|
+
|
|
2112
|
+
// src/resources/user-invitations.ts
|
|
2113
|
+
var UserInvitationsResource = class {
|
|
2114
|
+
constructor(http) {
|
|
2115
|
+
this.http = http;
|
|
2116
|
+
}
|
|
2117
|
+
http;
|
|
2118
|
+
async list(params) {
|
|
2119
|
+
const listParams = {
|
|
2120
|
+
filter: params?.filter,
|
|
2121
|
+
include: params?.include,
|
|
2122
|
+
limit: params?.limit ?? 200,
|
|
2123
|
+
sort: params?.sort
|
|
2124
|
+
};
|
|
2125
|
+
return this.http.all("/v1/userInvitations", listParams);
|
|
2126
|
+
}
|
|
2127
|
+
async get(id) {
|
|
2128
|
+
const response = await this.http.get(
|
|
2129
|
+
`/v1/userInvitations/${id}`
|
|
2130
|
+
);
|
|
2131
|
+
return response.data;
|
|
2132
|
+
}
|
|
2133
|
+
async create(params) {
|
|
2134
|
+
const relationships = params.visibleAppIds ? {
|
|
2135
|
+
visibleApps: {
|
|
2136
|
+
data: params.visibleAppIds.map((id) => ({ type: "apps", id }))
|
|
2137
|
+
}
|
|
2138
|
+
} : void 0;
|
|
2139
|
+
const response = await this.http.post(
|
|
2140
|
+
"/v1/userInvitations",
|
|
2141
|
+
{
|
|
2142
|
+
data: {
|
|
2143
|
+
type: "userInvitations",
|
|
2144
|
+
attributes: params.attributes,
|
|
2145
|
+
...relationships ? { relationships } : {}
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
);
|
|
2149
|
+
return response.data;
|
|
2150
|
+
}
|
|
2151
|
+
async delete(id) {
|
|
2152
|
+
await this.http.delete(`/v1/userInvitations/${id}`);
|
|
2153
|
+
}
|
|
2154
|
+
async findByEmail(email) {
|
|
2155
|
+
const results = await this.list({ filter: { email }, limit: 1 });
|
|
2156
|
+
return results[0] ?? null;
|
|
2157
|
+
}
|
|
2158
|
+
};
|
|
2159
|
+
|
|
2160
|
+
// src/resources/in-app-purchases.ts
|
|
2161
|
+
var InAppPurchasesResource = class {
|
|
2162
|
+
constructor(http) {
|
|
2163
|
+
this.http = http;
|
|
2164
|
+
}
|
|
2165
|
+
http;
|
|
2166
|
+
async listForApp(appId, params) {
|
|
2167
|
+
const listParams = {
|
|
2168
|
+
filter: params?.filter,
|
|
2169
|
+
include: params?.include,
|
|
2170
|
+
limit: params?.limit ?? 200,
|
|
2171
|
+
sort: params?.sort
|
|
2172
|
+
};
|
|
2173
|
+
return this.http.all(
|
|
2174
|
+
`/v2/apps/${appId}/inAppPurchasesV2`,
|
|
2175
|
+
listParams
|
|
2176
|
+
);
|
|
2177
|
+
}
|
|
2178
|
+
async get(id, params) {
|
|
2179
|
+
const queryParams = {};
|
|
2180
|
+
if (params?.include) queryParams["include"] = params.include;
|
|
2181
|
+
const response = await this.http.get(
|
|
2182
|
+
`/v2/inAppPurchases/${id}`,
|
|
2183
|
+
queryParams
|
|
2184
|
+
);
|
|
2185
|
+
return response.data;
|
|
2186
|
+
}
|
|
2187
|
+
};
|
|
2188
|
+
|
|
2189
|
+
// src/resources/game-center-detail.ts
|
|
2190
|
+
var GameCenterDetailResource = class {
|
|
2191
|
+
constructor(http) {
|
|
2192
|
+
this.http = http;
|
|
2193
|
+
}
|
|
2194
|
+
http;
|
|
2195
|
+
async getForApp(appId) {
|
|
2196
|
+
const response = await this.http.get(
|
|
2197
|
+
`/v1/apps/${appId}/gameCenterDetail`
|
|
2198
|
+
);
|
|
2199
|
+
return response.data;
|
|
2200
|
+
}
|
|
2201
|
+
async get(id) {
|
|
2202
|
+
const response = await this.http.get(
|
|
2203
|
+
`/v1/gameCenterDetails/${id}`
|
|
2204
|
+
);
|
|
2205
|
+
return response.data;
|
|
2206
|
+
}
|
|
2207
|
+
async update(id, attributes) {
|
|
2208
|
+
const response = await this.http.patch(
|
|
2209
|
+
`/v1/gameCenterDetails/${id}`,
|
|
2210
|
+
{ data: { type: "gameCenterDetails", id, attributes } }
|
|
2211
|
+
);
|
|
2212
|
+
return response.data;
|
|
2213
|
+
}
|
|
2214
|
+
};
|
|
2215
|
+
|
|
2216
|
+
// src/resources/xcode-metrics.ts
|
|
2217
|
+
var XcodeMetricsResource = class {
|
|
2218
|
+
constructor(http) {
|
|
2219
|
+
this.http = http;
|
|
2220
|
+
}
|
|
2221
|
+
http;
|
|
2222
|
+
async getPerfPowerMetrics(buildId) {
|
|
2223
|
+
const response = await this.http.get(
|
|
2224
|
+
`/v1/builds/${buildId}/perfPowerMetrics`
|
|
2225
|
+
);
|
|
2226
|
+
return response.data;
|
|
2227
|
+
}
|
|
2228
|
+
async getDiagnosticSignatures(buildId) {
|
|
2229
|
+
const response = await this.http.get(
|
|
2230
|
+
`/v1/builds/${buildId}/diagnosticSignatures`
|
|
2231
|
+
);
|
|
2232
|
+
return response.data;
|
|
2233
|
+
}
|
|
2234
|
+
async getPerfPowerMetric(id) {
|
|
2235
|
+
const response = await this.http.get(
|
|
2236
|
+
`/v1/perfPowerMetrics/${id}`
|
|
2237
|
+
);
|
|
2238
|
+
return response.data;
|
|
2239
|
+
}
|
|
2240
|
+
async getDiagnosticSignature(id) {
|
|
2241
|
+
const response = await this.http.get(
|
|
2242
|
+
`/v1/diagnosticSignatures/${id}`
|
|
2243
|
+
);
|
|
2244
|
+
return response.data;
|
|
2245
|
+
}
|
|
2246
|
+
};
|
|
2247
|
+
|
|
2248
|
+
// src/client/portal.ts
|
|
2249
|
+
var PORTAL_BASE = "https://developer.apple.com/services-account/QH65B2";
|
|
2250
|
+
var PortalClient = class _PortalClient {
|
|
2251
|
+
session;
|
|
2252
|
+
teamId;
|
|
2253
|
+
csrf = "";
|
|
2254
|
+
csrfTs = "";
|
|
2255
|
+
cookieStr;
|
|
2256
|
+
constructor(session, teamId) {
|
|
2257
|
+
this.session = session;
|
|
2258
|
+
this.teamId = teamId;
|
|
2259
|
+
this.cookieStr = Object.entries(session.cookies).map(([k, v]) => `${k}=${v}`).join("; ");
|
|
2260
|
+
}
|
|
2261
|
+
/** Initialize CSRF tokens — must be called before mutations */
|
|
2262
|
+
async init() {
|
|
2263
|
+
await this.post("account/listTeams.action", {});
|
|
2264
|
+
}
|
|
2265
|
+
async post(path, params) {
|
|
2266
|
+
const body = new URLSearchParams();
|
|
2267
|
+
for (const [k, v] of Object.entries(params)) {
|
|
2268
|
+
if (Array.isArray(v)) {
|
|
2269
|
+
for (const item of v) body.append(k, item);
|
|
2270
|
+
} else body.set(k, v);
|
|
2271
|
+
}
|
|
2272
|
+
const bodyStr = body.toString();
|
|
2273
|
+
const headers = {
|
|
2274
|
+
Cookie: this.cookieStr,
|
|
2275
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
2276
|
+
Accept: "application/json"
|
|
2277
|
+
};
|
|
2278
|
+
if (this.csrf) {
|
|
2279
|
+
headers["csrf"] = this.csrf;
|
|
2280
|
+
headers["csrf_ts"] = this.csrfTs;
|
|
2281
|
+
}
|
|
2282
|
+
if (process.env.FASTNODE_DEBUG) console.log(`[portal] POST ${path} body=${bodyStr.slice(0, 200)}`);
|
|
2283
|
+
const res = await fetch(`${PORTAL_BASE}/${path}`, { method: "POST", headers, body: bodyStr });
|
|
2284
|
+
if (res.headers.get("csrf")) {
|
|
2285
|
+
this.csrf = res.headers.get("csrf");
|
|
2286
|
+
this.csrfTs = res.headers.get("csrf_ts") ?? "";
|
|
2287
|
+
}
|
|
2288
|
+
for (const raw of res.headers.getSetCookie?.() ?? []) {
|
|
2289
|
+
const m = raw.match(/^([^=]+)=([^;]*)/);
|
|
2290
|
+
if (m && !this.cookieStr.includes(m[1] + "=")) this.cookieStr += "; " + m[1] + "=" + m[2];
|
|
2291
|
+
}
|
|
2292
|
+
const text = await res.text();
|
|
2293
|
+
let data;
|
|
2294
|
+
try {
|
|
2295
|
+
data = JSON.parse(text);
|
|
2296
|
+
} catch {
|
|
2297
|
+
throw new Error(`Portal returned non-JSON: ${text.slice(0, 200)}`);
|
|
2298
|
+
}
|
|
2299
|
+
checkPortalResponse(data, this.session);
|
|
2300
|
+
return data;
|
|
2301
|
+
}
|
|
2302
|
+
// ── Teams ──────────────────────────────────────────────────────────────
|
|
2303
|
+
async listTeams() {
|
|
2304
|
+
const data = await this.post("account/listTeams.action", {});
|
|
2305
|
+
return data.teams ?? [];
|
|
2306
|
+
}
|
|
2307
|
+
// ── App IDs / Bundle IDs ───────────────────────────────────────────────
|
|
2308
|
+
async listAppIds() {
|
|
2309
|
+
const data = await this.post("account/ios/identifiers/listAppIds.action", {
|
|
2310
|
+
teamId: this.teamId,
|
|
2311
|
+
pageSize: "500",
|
|
2312
|
+
pageNumber: "1",
|
|
2313
|
+
sort: "name=asc"
|
|
2314
|
+
});
|
|
2315
|
+
return data.appIds ?? [];
|
|
2316
|
+
}
|
|
2317
|
+
async createAppId(params) {
|
|
2318
|
+
const reqParams = {
|
|
2319
|
+
teamId: this.teamId,
|
|
2320
|
+
type: "explicit",
|
|
2321
|
+
identifier: params.identifier,
|
|
2322
|
+
name: params.name
|
|
2323
|
+
};
|
|
2324
|
+
if (params.enablePush) reqParams.push = "on";
|
|
2325
|
+
if (params.enableIAP !== false) reqParams.inAppPurchase = "on";
|
|
2326
|
+
const data = await this.post("account/ios/identifiers/addAppId.action", reqParams);
|
|
2327
|
+
return data.appId;
|
|
2328
|
+
}
|
|
2329
|
+
async deleteAppId(appIdId) {
|
|
2330
|
+
await this.post("account/ios/identifiers/deleteAppId.action", { teamId: this.teamId, appIdId });
|
|
2331
|
+
}
|
|
2332
|
+
// ── Certificates ───────────────────────────────────────────────────────
|
|
2333
|
+
async listCertificates(types) {
|
|
2334
|
+
const iosTypes = types ?? [
|
|
2335
|
+
_PortalClient.CERT_TYPES.IOS_DEVELOPMENT,
|
|
2336
|
+
_PortalClient.CERT_TYPES.IOS_DISTRIBUTION,
|
|
2337
|
+
..._PortalClient.OLDER_IOS_CERTIFICATE_TYPES
|
|
2338
|
+
];
|
|
2339
|
+
const data = await this.post("account/ios/certificate/listCertRequests.action", {
|
|
2340
|
+
teamId: this.teamId,
|
|
2341
|
+
pageSize: "500",
|
|
2342
|
+
pageNumber: "1",
|
|
2343
|
+
sort: "certRequestStatusCode=asc",
|
|
2344
|
+
types: iosTypes.join(",")
|
|
2345
|
+
});
|
|
2346
|
+
return data.certRequests ?? [];
|
|
2347
|
+
}
|
|
2348
|
+
async listPushCertificates() {
|
|
2349
|
+
const data = await this.post("account/ios/certificate/listCertRequests.action", {
|
|
2350
|
+
teamId: this.teamId,
|
|
2351
|
+
pageSize: "500",
|
|
2352
|
+
pageNumber: "1",
|
|
2353
|
+
sort: "certRequestStatusCode=asc",
|
|
2354
|
+
types: [_PortalClient.CERT_TYPES.IOS_PRODUCTION_PUSH, _PortalClient.CERT_TYPES.IOS_DEVELOPMENT_PUSH].join(",")
|
|
2355
|
+
});
|
|
2356
|
+
return data.certRequests ?? [];
|
|
2357
|
+
}
|
|
2358
|
+
async createCertificate(params) {
|
|
2359
|
+
const reqParams = {
|
|
2360
|
+
teamId: this.teamId,
|
|
2361
|
+
type: params.type,
|
|
2362
|
+
csrContent: params.csrContent
|
|
2363
|
+
};
|
|
2364
|
+
if (params.appIdId) reqParams.appIdId = params.appIdId;
|
|
2365
|
+
const data = await this.post("account/ios/certificate/submitCertificateRequest.action", reqParams);
|
|
2366
|
+
return data.certRequest;
|
|
2367
|
+
}
|
|
2368
|
+
async downloadCertificate(certId, type) {
|
|
2369
|
+
const headers = { Cookie: this.cookieStr, Accept: "application/json" };
|
|
2370
|
+
const res = await fetch(
|
|
2371
|
+
`${PORTAL_BASE}/account/ios/certificate/downloadCertificateContent.action?teamId=${this.teamId}&certificateId=${certId}&type=${type}`,
|
|
2372
|
+
{ headers }
|
|
2373
|
+
);
|
|
2374
|
+
return Buffer.from(await res.arrayBuffer());
|
|
2375
|
+
}
|
|
2376
|
+
async revokeCertificate(certId, type) {
|
|
2377
|
+
await this.post("account/ios/certificate/revokeCertificate.action", {
|
|
2378
|
+
teamId: this.teamId,
|
|
2379
|
+
certificateId: certId,
|
|
2380
|
+
type
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
// ── Devices ────────────────────────────────────────────────────────────
|
|
2384
|
+
async listDevices() {
|
|
2385
|
+
const data = await this.post("account/ios/device/listDevices.action", {
|
|
2386
|
+
teamId: this.teamId,
|
|
2387
|
+
pageSize: "500",
|
|
2388
|
+
pageNumber: "1",
|
|
2389
|
+
sort: "name=asc",
|
|
2390
|
+
includeRemovedDevices: "false"
|
|
2391
|
+
});
|
|
2392
|
+
return data.devices ?? [];
|
|
2393
|
+
}
|
|
2394
|
+
async registerDevice(params) {
|
|
2395
|
+
const data = await this.post("account/ios/device/addDevices.action", {
|
|
2396
|
+
teamId: this.teamId,
|
|
2397
|
+
deviceNames: params.name,
|
|
2398
|
+
deviceNumbers: params.udid,
|
|
2399
|
+
register: "single",
|
|
2400
|
+
deviceClasses: params.deviceClass ?? "iphone"
|
|
2401
|
+
});
|
|
2402
|
+
return (data.devices ?? [])[0];
|
|
2403
|
+
}
|
|
2404
|
+
// ── Provisioning Profiles ──────────────────────────────────────────────
|
|
2405
|
+
async listProfiles() {
|
|
2406
|
+
const data = await this.post("account/ios/profile/listProvisioningProfiles.action", {
|
|
2407
|
+
teamId: this.teamId,
|
|
2408
|
+
includeInactiveProfiles: "true",
|
|
2409
|
+
pageSize: "500",
|
|
2410
|
+
pageNumber: "1",
|
|
2411
|
+
sort: "name=asc"
|
|
2412
|
+
});
|
|
2413
|
+
return data.provisioningProfiles ?? [];
|
|
2414
|
+
}
|
|
2415
|
+
async createProfile(params) {
|
|
2416
|
+
const reqParams = {
|
|
2417
|
+
teamId: this.teamId,
|
|
2418
|
+
appIdId: params.appIdId,
|
|
2419
|
+
distributionType: params.distributionType,
|
|
2420
|
+
provisioningProfileName: params.name,
|
|
2421
|
+
certificateIds: params.certificateIds
|
|
2422
|
+
};
|
|
2423
|
+
if (params.deviceIds?.length) reqParams.deviceIds = params.deviceIds;
|
|
2424
|
+
const data = await this.post("account/ios/profile/createProvisioningProfile.action", reqParams);
|
|
2425
|
+
return data.provisioningProfile;
|
|
2426
|
+
}
|
|
2427
|
+
async deleteProfile(profileId) {
|
|
2428
|
+
await this.post("account/ios/profile/deleteProvisioningProfile.action", {
|
|
2429
|
+
teamId: this.teamId,
|
|
2430
|
+
provisioningProfileId: profileId
|
|
2431
|
+
});
|
|
2432
|
+
}
|
|
2433
|
+
async downloadProfile(profileId) {
|
|
2434
|
+
const headers = { Cookie: this.cookieStr };
|
|
2435
|
+
const res = await fetch(
|
|
2436
|
+
`${PORTAL_BASE}/account/ios/profile/downloadProfileContent?teamId=${this.teamId}&provisioningProfileId=${profileId}`,
|
|
2437
|
+
{ headers }
|
|
2438
|
+
);
|
|
2439
|
+
return Buffer.from(await res.arrayBuffer());
|
|
2440
|
+
}
|
|
2441
|
+
// ── Certificate Type Constants (matching Fastlane) ─────────────────────
|
|
2442
|
+
/**
|
|
2443
|
+
* Apple certificate type codes — copied 1:1 from Fastlane's
|
|
2444
|
+
* spaceship/portal/certificate.rb IOS_CERTIFICATE_TYPE_IDS / MAC_CERTIFICATE_TYPE_IDS
|
|
2445
|
+
*/
|
|
2446
|
+
static CERT_TYPES = {
|
|
2447
|
+
// iOS
|
|
2448
|
+
IOS_DEVELOPMENT: "5QPB9NHCEI",
|
|
2449
|
+
IOS_DISTRIBUTION: "R58UK2EWSO",
|
|
2450
|
+
// App Store Production
|
|
2451
|
+
IOS_IN_HOUSE: "9RQEK7MSXA",
|
|
2452
|
+
IOS_DEVELOPMENT_PUSH: "JKG5JZ54H7",
|
|
2453
|
+
IOS_PRODUCTION_PUSH: "UPV3DW712I",
|
|
2454
|
+
APPLE_PUSH_PRODUCTION: "UPV3DW712I",
|
|
2455
|
+
// alias
|
|
2456
|
+
APPLE_PUSH_SANDBOX: "JKG5JZ54H7",
|
|
2457
|
+
// alias
|
|
2458
|
+
PASSBOOK: "Y3B2F3TYSI",
|
|
2459
|
+
WEBSITE_PUSH: "3T2ZP62QW8",
|
|
2460
|
+
VOIP_PUSH: "E5D663CMZW",
|
|
2461
|
+
APPLE_PAY: "4APLUP237T",
|
|
2462
|
+
APPLE_PAY_MERCHANT_IDENTITY: "MD8Q2VRT6A",
|
|
2463
|
+
// Universal (Apple Development/Distribution)
|
|
2464
|
+
APPLE_DEVELOPMENT: "83Q87W3TGH",
|
|
2465
|
+
APPLE_DISTRIBUTION: "WXV89964HE",
|
|
2466
|
+
// Mac
|
|
2467
|
+
MAC_DEVELOPMENT: "749Y1QAGU7",
|
|
2468
|
+
MAC_APP_DISTRIBUTION: "HXZEUKP0FP",
|
|
2469
|
+
MAC_INSTALLER_DISTRIBUTION: "2PQI8IDXNH",
|
|
2470
|
+
MAC_PRODUCTION_PUSH: "CDZ7EMXIZ1",
|
|
2471
|
+
MAC_DEVELOPMENT_PUSH: "HQ4KP3I34R",
|
|
2472
|
+
DEVELOPER_ID_APPLICATION: "DIVN2GW3XT",
|
|
2473
|
+
DEVELOPER_ID_INSTALLER: "OYVN2GW35E"
|
|
2474
|
+
};
|
|
2475
|
+
/**
|
|
2476
|
+
* Legacy iOS certificate type codes that can still appear in the portal
|
|
2477
|
+
* responses. Port of Fastlane's Spaceship::Portal::Certificate
|
|
2478
|
+
* OLDER_IOS_CERTIFICATE_TYPES list (certificate.rb lines 180-189).
|
|
2479
|
+
*/
|
|
2480
|
+
static OLDER_IOS_CERTIFICATE_TYPES = [
|
|
2481
|
+
"3BQKVH9I2X",
|
|
2482
|
+
// old ProductionPush
|
|
2483
|
+
"BKLRAVXMGM",
|
|
2484
|
+
// old DevelopmentPush
|
|
2485
|
+
// Also sent by the browser, but not sure what they represent:
|
|
2486
|
+
"T44PTHVNID",
|
|
2487
|
+
"DZQUP8189Y",
|
|
2488
|
+
"FGQUP4785Z",
|
|
2489
|
+
"S5WE21TULA",
|
|
2490
|
+
"FUOY7LWJET"
|
|
2491
|
+
];
|
|
2492
|
+
};
|
|
2493
|
+
|
|
2494
|
+
// src/client/index.ts
|
|
2495
|
+
var AppStoreConnectClient = class {
|
|
2496
|
+
http;
|
|
2497
|
+
certificates;
|
|
2498
|
+
profiles;
|
|
2499
|
+
bundleIds;
|
|
2500
|
+
devices;
|
|
2501
|
+
apps;
|
|
2502
|
+
builds;
|
|
2503
|
+
betaGroups;
|
|
2504
|
+
capabilities;
|
|
2505
|
+
appStoreVersions;
|
|
2506
|
+
appScreenshots;
|
|
2507
|
+
reviewSubmissions;
|
|
2508
|
+
appInfos;
|
|
2509
|
+
appInfoLocalizations;
|
|
2510
|
+
appStoreReviewDetails;
|
|
2511
|
+
betaTesters;
|
|
2512
|
+
betaAppReviewSubmissions;
|
|
2513
|
+
betaAppReviewDetails;
|
|
2514
|
+
betaInvitations;
|
|
2515
|
+
betaLicenses;
|
|
2516
|
+
appPreviews;
|
|
2517
|
+
appPreviewSets;
|
|
2518
|
+
appPrices;
|
|
2519
|
+
territories;
|
|
2520
|
+
ageRatingDeclarations;
|
|
2521
|
+
appCategories;
|
|
2522
|
+
appEncryptionDeclarations;
|
|
2523
|
+
idfaDeclarations;
|
|
2524
|
+
preReleaseVersions;
|
|
2525
|
+
reviewSubmissionItems;
|
|
2526
|
+
users;
|
|
2527
|
+
userInvitations;
|
|
2528
|
+
inAppPurchases;
|
|
2529
|
+
gameCenterDetail;
|
|
2530
|
+
xcodeMetrics;
|
|
2531
|
+
constructor(config) {
|
|
2532
|
+
const tokenManager = new TokenManager({
|
|
2533
|
+
keyId: config.keyId,
|
|
2534
|
+
issuerId: config.issuerId,
|
|
2535
|
+
privateKey: config.privateKey,
|
|
2536
|
+
enterprise: config.enterprise,
|
|
2537
|
+
duration: config.tokenDuration
|
|
2538
|
+
});
|
|
2539
|
+
this.http = new RequestClient(tokenManager, config.enterprise);
|
|
2540
|
+
this.certificates = new CertificatesResource(this.http);
|
|
2541
|
+
this.profiles = new ProfilesResource(this.http);
|
|
2542
|
+
this.bundleIds = new BundleIdsResource(this.http);
|
|
2543
|
+
this.devices = new DevicesResource(this.http);
|
|
2544
|
+
this.apps = new AppsResource(this.http);
|
|
2545
|
+
this.builds = new BuildsResource(this.http);
|
|
2546
|
+
this.betaGroups = new BetaGroupsResource(this.http);
|
|
2547
|
+
this.capabilities = new CapabilitiesResource(this.http);
|
|
2548
|
+
this.appStoreVersions = new AppStoreVersionsResource(this.http);
|
|
2549
|
+
this.appScreenshots = new AppScreenshotsResource(this.http);
|
|
2550
|
+
this.reviewSubmissions = new ReviewSubmissionsResource(this.http);
|
|
2551
|
+
this.appInfos = new AppInfosResource(this.http);
|
|
2552
|
+
this.appInfoLocalizations = new AppInfoLocalizationsResource(this.http);
|
|
2553
|
+
this.appStoreReviewDetails = new AppStoreReviewDetailsResource(this.http);
|
|
2554
|
+
this.betaTesters = new BetaTestersResource(this.http);
|
|
2555
|
+
this.betaAppReviewSubmissions = new BetaAppReviewSubmissionsResource(this.http);
|
|
2556
|
+
this.betaAppReviewDetails = new BetaAppReviewDetailsResource(this.http);
|
|
2557
|
+
this.betaInvitations = new BetaInvitationsResource(this.http);
|
|
2558
|
+
this.betaLicenses = new BetaLicensesResource(this.http);
|
|
2559
|
+
this.appPreviews = new AppPreviewsResource(this.http);
|
|
2560
|
+
this.appPreviewSets = new AppPreviewSetsResource(this.http);
|
|
2561
|
+
this.appPrices = new AppPricesResource(this.http);
|
|
2562
|
+
this.territories = new TerritoriesResource(this.http);
|
|
2563
|
+
this.ageRatingDeclarations = new AgeRatingDeclarationsResource(this.http);
|
|
2564
|
+
this.appCategories = new AppCategoriesResource(this.http);
|
|
2565
|
+
this.appEncryptionDeclarations = new AppEncryptionDeclarationsResource(this.http);
|
|
2566
|
+
this.idfaDeclarations = new IdfaDeclarationsResource(this.http);
|
|
2567
|
+
this.preReleaseVersions = new PreReleaseVersionsResource(this.http);
|
|
2568
|
+
this.reviewSubmissionItems = new ReviewSubmissionItemsResource(this.http);
|
|
2569
|
+
this.users = new UsersResource(this.http);
|
|
2570
|
+
this.userInvitations = new UserInvitationsResource(this.http);
|
|
2571
|
+
this.inAppPurchases = new InAppPurchasesResource(this.http);
|
|
2572
|
+
this.gameCenterDetail = new GameCenterDetailResource(this.http);
|
|
2573
|
+
this.xcodeMetrics = new XcodeMetricsResource(this.http);
|
|
2574
|
+
}
|
|
2575
|
+
async request(path, options) {
|
|
2576
|
+
return this.http.request(path, options);
|
|
2577
|
+
}
|
|
2578
|
+
};
|
|
2579
|
+
|
|
2580
|
+
export { AppStoreConnectClient, AppStoreConnectError, PortalClient, ProgramLicenseAgreementError, RateLimitError, RequestClient, TokenManager, checkPortalResponse, loginWithAppleId };
|
|
2581
|
+
//# sourceMappingURL=index.mjs.map
|
|
2582
|
+
//# sourceMappingURL=index.mjs.map
|