@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,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