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