@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,198 @@
1
+ import { mkdir, writeFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { homedir } from 'os';
4
+
5
+ // src/sigh/index.ts
6
+ function resolveProfileType(options) {
7
+ if (options.profileType) return options.profileType;
8
+ const platform = options.platform ?? "ios";
9
+ const isDev = options.development ?? false;
10
+ const isAdhoc = options.adhoc ?? false;
11
+ const isInHouse = options.inHouse ?? false;
12
+ switch (platform) {
13
+ case "macos":
14
+ if (isDev) return "MAC_APP_DEVELOPMENT";
15
+ if (isInHouse) return "MAC_APP_INHOUSE";
16
+ return "MAC_APP_STORE";
17
+ case "tvos":
18
+ if (isDev) return "TVOS_APP_DEVELOPMENT";
19
+ if (isAdhoc) return "TVOS_APP_ADHOC";
20
+ if (isInHouse) return "TVOS_APP_INHOUSE";
21
+ return "TVOS_APP_STORE";
22
+ case "catalyst":
23
+ if (isDev) return "MAC_CATALYST_APP_DEVELOPMENT";
24
+ if (isInHouse) return "MAC_CATALYST_APP_INHOUSE";
25
+ return "MAC_CATALYST_APP_STORE";
26
+ default:
27
+ if (isDev) return "IOS_APP_DEVELOPMENT";
28
+ if (isAdhoc) return "IOS_APP_ADHOC";
29
+ if (isInHouse) return "IOS_APP_INHOUSE";
30
+ return "IOS_APP_STORE";
31
+ }
32
+ }
33
+ function certificateTypesForProfile(profileType) {
34
+ switch (profileType) {
35
+ case "IOS_APP_DEVELOPMENT":
36
+ case "TVOS_APP_DEVELOPMENT":
37
+ case "MAC_CATALYST_APP_DEVELOPMENT":
38
+ return ["IOS_DEVELOPMENT"];
39
+ case "MAC_APP_DEVELOPMENT":
40
+ return ["MAC_APP_DEVELOPMENT"];
41
+ case "IOS_APP_STORE":
42
+ case "IOS_APP_ADHOC":
43
+ case "TVOS_APP_STORE":
44
+ case "TVOS_APP_ADHOC":
45
+ case "MAC_CATALYST_APP_STORE":
46
+ return ["IOS_DISTRIBUTION"];
47
+ case "IOS_APP_INHOUSE":
48
+ case "TVOS_APP_INHOUSE":
49
+ case "MAC_CATALYST_APP_INHOUSE":
50
+ return ["IOS_DISTRIBUTION"];
51
+ case "MAC_APP_STORE":
52
+ case "MAC_APP_INHOUSE":
53
+ return ["MAC_APP_DISTRIBUTION"];
54
+ case "MAC_APP_DIRECT":
55
+ return ["DEVELOPER_ID_APPLICATION"];
56
+ default:
57
+ return ["IOS_DISTRIBUTION"];
58
+ }
59
+ }
60
+ function needsDevices(profileType) {
61
+ return profileType.includes("DEVELOPMENT") || profileType.includes("ADHOC");
62
+ }
63
+ function profileExtension(profileType) {
64
+ return profileType.startsWith("MAC_") && !profileType.includes("CATALYST") ? ".provisionprofile" : ".mobileprovision";
65
+ }
66
+ async function findMatchingProfile(options) {
67
+ const profileType = resolveProfileType(options);
68
+ const profiles = await options.client.profiles.list({
69
+ filter: { profileType },
70
+ include: "bundleId",
71
+ limit: 200
72
+ });
73
+ const now = /* @__PURE__ */ new Date();
74
+ for (const profile of profiles) {
75
+ const bundleIdRel = profile.relationships?.bundleId?.data;
76
+ if (bundleIdRel) {
77
+ const bundleId = await options.client.bundleIds.get(bundleIdRel.id);
78
+ if (bundleId.attributes.identifier !== options.bundleIdentifier) continue;
79
+ }
80
+ if (profile.attributes.profileState !== "ACTIVE") continue;
81
+ if (new Date(profile.attributes.expirationDate) <= now) continue;
82
+ if (options.profileName && profile.attributes.name !== options.profileName) {
83
+ continue;
84
+ }
85
+ return profile;
86
+ }
87
+ return null;
88
+ }
89
+ async function createProfile(options) {
90
+ const profileType = resolveProfileType(options);
91
+ if (options.force) {
92
+ const existing = await findMatchingProfile(options);
93
+ if (existing) {
94
+ await options.client.profiles.delete(existing.id);
95
+ }
96
+ } else {
97
+ const existing = await findMatchingProfile(options);
98
+ if (existing) {
99
+ return downloadAndReturn(options, existing);
100
+ }
101
+ }
102
+ let bundleId = await options.client.bundleIds.find(options.bundleIdentifier);
103
+ if (!bundleId) {
104
+ throw new Error(
105
+ `Bundle ID '${options.bundleIdentifier}' not found. Register it first with produce.registerBundleId().`
106
+ );
107
+ }
108
+ const certTypes = certificateTypesForProfile(profileType);
109
+ let certificateIds = options.certificateIds;
110
+ if (!certificateIds || certificateIds.length === 0) {
111
+ const certs = await options.client.certificates.list({
112
+ filter: { certificateType: certTypes }
113
+ });
114
+ const now = /* @__PURE__ */ new Date();
115
+ const validCerts = certs.filter(
116
+ (c) => new Date(c.attributes.expirationDate) > now
117
+ );
118
+ if (validCerts.length === 0) {
119
+ throw new Error(
120
+ `No valid certificates found of type ${certTypes.join(", ")}. Create one first with cert.createCertificate().`
121
+ );
122
+ }
123
+ certificateIds = options.includeAllCertificates ? validCerts.map((c) => c.id) : [validCerts[0].id];
124
+ }
125
+ let deviceIds = options.deviceIds;
126
+ if (needsDevices(profileType) && (!deviceIds || deviceIds.length === 0)) {
127
+ const platform = options.platform === "macos" ? "MAC_OS" : options.platform === "tvos" ? "TVOS" : "IOS";
128
+ const devices = await options.client.devices.list({
129
+ filter: { platform, status: "ENABLED" }
130
+ });
131
+ deviceIds = devices.map((d) => d.id);
132
+ }
133
+ const profileName = options.profileName ?? `${profileType} ${options.bundleIdentifier} ${Date.now()}`;
134
+ const profile = await options.client.profiles.create({
135
+ name: profileName,
136
+ profileType,
137
+ bundleIdId: bundleId.id,
138
+ certificateIds,
139
+ deviceIds
140
+ });
141
+ return downloadAndReturn(options, profile);
142
+ }
143
+ async function downloadAndReturn(options, profile) {
144
+ const content = Buffer.from(profile.attributes.profileContent, "base64");
145
+ const profileType = resolveProfileType(options);
146
+ const ext = profileExtension(profileType);
147
+ const result = {
148
+ profile,
149
+ profileContent: content,
150
+ uuid: profile.attributes.uuid,
151
+ name: profile.attributes.name
152
+ };
153
+ if (options.outputDir) {
154
+ await mkdir(options.outputDir, { recursive: true });
155
+ const filename = `${profileType}_${options.bundleIdentifier}${ext}`;
156
+ const filePath = join(options.outputDir, filename);
157
+ await writeFile(filePath, content);
158
+ result.filePath = filePath;
159
+ }
160
+ if (!options.skipInstall && process.platform === "darwin") {
161
+ await installProfile(content, profile.attributes.uuid);
162
+ }
163
+ return result;
164
+ }
165
+ async function downloadProfile(client, id) {
166
+ const profile = await client.profiles.get(id);
167
+ return Buffer.from(profile.attributes.profileContent, "base64");
168
+ }
169
+ async function installProfile(profileContent, uuid) {
170
+ const legacyDir = join(
171
+ homedir(),
172
+ "Library",
173
+ "MobileDevice",
174
+ "Provisioning Profiles"
175
+ );
176
+ const xcode16Dir = join(
177
+ homedir(),
178
+ "Library",
179
+ "Developer",
180
+ "Xcode",
181
+ "UserData",
182
+ "Provisioning Profiles"
183
+ );
184
+ const filename = `${uuid}.mobileprovision`;
185
+ await mkdir(legacyDir, { recursive: true });
186
+ const legacyPath = join(legacyDir, filename);
187
+ await writeFile(legacyPath, profileContent);
188
+ try {
189
+ await mkdir(xcode16Dir, { recursive: true });
190
+ await writeFile(join(xcode16Dir, filename), profileContent);
191
+ } catch {
192
+ }
193
+ return legacyPath;
194
+ }
195
+
196
+ export { createProfile, downloadProfile, findMatchingProfile, installProfile };
197
+ //# sourceMappingURL=index.mjs.map
198
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/sigh/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { writeFile, mkdir, copyFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { AppStoreConnectClient } from \"../client/index.js\";\nimport type { Profile, ProfileType, CertificateType, Platform } from \"../types/index.js\";\n\nexport interface SighOptions {\n client: AppStoreConnectClient;\n bundleIdentifier: string;\n profileType?: ProfileType;\n profileName?: string;\n certificateIds?: string[];\n deviceIds?: string[];\n force?: boolean;\n outputDir?: string;\n platform?: \"ios\" | \"macos\" | \"tvos\" | \"catalyst\";\n development?: boolean;\n adhoc?: boolean;\n inHouse?: boolean;\n readonly?: boolean;\n skipInstall?: boolean;\n skipCertificateVerification?: boolean;\n includeAllCertificates?: boolean;\n}\n\nexport interface SighResult {\n profile: Profile;\n profileContent: Buffer;\n uuid: string;\n name: string;\n filePath?: string;\n}\n\nfunction resolveProfileType(options: SighOptions): ProfileType {\n if (options.profileType) return options.profileType;\n\n const platform = options.platform ?? \"ios\";\n const isDev = options.development ?? false;\n const isAdhoc = options.adhoc ?? false;\n const isInHouse = options.inHouse ?? false;\n\n switch (platform) {\n case \"macos\":\n if (isDev) return \"MAC_APP_DEVELOPMENT\";\n if (isInHouse) return \"MAC_APP_INHOUSE\";\n return \"MAC_APP_STORE\";\n case \"tvos\":\n if (isDev) return \"TVOS_APP_DEVELOPMENT\";\n if (isAdhoc) return \"TVOS_APP_ADHOC\";\n if (isInHouse) return \"TVOS_APP_INHOUSE\";\n return \"TVOS_APP_STORE\";\n case \"catalyst\":\n if (isDev) return \"MAC_CATALYST_APP_DEVELOPMENT\";\n if (isInHouse) return \"MAC_CATALYST_APP_INHOUSE\";\n return \"MAC_CATALYST_APP_STORE\";\n default:\n if (isDev) return \"IOS_APP_DEVELOPMENT\";\n if (isAdhoc) return \"IOS_APP_ADHOC\";\n if (isInHouse) return \"IOS_APP_INHOUSE\";\n return \"IOS_APP_STORE\";\n }\n}\n\nfunction certificateTypesForProfile(\n profileType: ProfileType\n): CertificateType[] {\n switch (profileType) {\n case \"IOS_APP_DEVELOPMENT\":\n case \"TVOS_APP_DEVELOPMENT\":\n case \"MAC_CATALYST_APP_DEVELOPMENT\":\n return [\"IOS_DEVELOPMENT\"];\n case \"MAC_APP_DEVELOPMENT\":\n return [\"MAC_APP_DEVELOPMENT\"];\n case \"IOS_APP_STORE\":\n case \"IOS_APP_ADHOC\":\n case \"TVOS_APP_STORE\":\n case \"TVOS_APP_ADHOC\":\n case \"MAC_CATALYST_APP_STORE\":\n return [\"IOS_DISTRIBUTION\"];\n case \"IOS_APP_INHOUSE\":\n case \"TVOS_APP_INHOUSE\":\n case \"MAC_CATALYST_APP_INHOUSE\":\n return [\"IOS_DISTRIBUTION\"];\n case \"MAC_APP_STORE\":\n case \"MAC_APP_INHOUSE\":\n return [\"MAC_APP_DISTRIBUTION\"];\n case \"MAC_APP_DIRECT\":\n return [\"DEVELOPER_ID_APPLICATION\"];\n default:\n return [\"IOS_DISTRIBUTION\"];\n }\n}\n\nfunction needsDevices(profileType: ProfileType): boolean {\n return (\n profileType.includes(\"DEVELOPMENT\") || profileType.includes(\"ADHOC\")\n );\n}\n\nfunction profileExtension(profileType: ProfileType): string {\n return profileType.startsWith(\"MAC_\") && !profileType.includes(\"CATALYST\")\n ? \".provisionprofile\"\n : \".mobileprovision\";\n}\n\nexport async function findMatchingProfile(\n options: Omit<SighOptions, \"force\">\n): Promise<Profile | null> {\n const profileType = resolveProfileType(options as SighOptions);\n const profiles = await options.client.profiles.list({\n filter: { profileType },\n include: \"bundleId\",\n limit: 200,\n });\n\n const now = new Date();\n for (const profile of profiles) {\n // Check bundle ID match\n const bundleIdRel = profile.relationships?.bundleId?.data;\n if (bundleIdRel) {\n const bundleId = await options.client.bundleIds.get(bundleIdRel.id);\n if (bundleId.attributes.identifier !== options.bundleIdentifier) continue;\n }\n\n // Check state and expiration\n if (profile.attributes.profileState !== \"ACTIVE\") continue;\n if (new Date(profile.attributes.expirationDate) <= now) continue;\n\n // Check name if specified\n if (\n options.profileName &&\n profile.attributes.name !== options.profileName\n ) {\n continue;\n }\n\n return profile;\n }\n\n return null;\n}\n\nexport async function createProfile(\n options: SighOptions\n): Promise<SighResult> {\n const profileType = resolveProfileType(options);\n\n // If force, delete existing first\n if (options.force) {\n const existing = await findMatchingProfile(options);\n if (existing) {\n await options.client.profiles.delete(existing.id);\n }\n } else {\n // Check for existing\n const existing = await findMatchingProfile(options);\n if (existing) {\n return downloadAndReturn(options, existing);\n }\n }\n\n // Find or verify bundle ID\n let bundleId = await options.client.bundleIds.find(options.bundleIdentifier);\n if (!bundleId) {\n throw new Error(\n `Bundle ID '${options.bundleIdentifier}' not found. Register it first with produce.registerBundleId().`\n );\n }\n\n // Get certificates\n const certTypes = certificateTypesForProfile(profileType);\n let certificateIds = options.certificateIds;\n if (!certificateIds || certificateIds.length === 0) {\n const certs = await options.client.certificates.list({\n filter: { certificateType: certTypes },\n });\n const now = new Date();\n const validCerts = certs.filter(\n (c) => new Date(c.attributes.expirationDate) > now\n );\n if (validCerts.length === 0) {\n throw new Error(\n `No valid certificates found of type ${certTypes.join(\", \")}. Create one first with cert.createCertificate().`\n );\n }\n certificateIds = options.includeAllCertificates\n ? validCerts.map((c) => c.id)\n : [validCerts[0].id];\n }\n\n // Get devices if needed\n let deviceIds = options.deviceIds;\n if (needsDevices(profileType) && (!deviceIds || deviceIds.length === 0)) {\n const platform: Platform =\n options.platform === \"macos\"\n ? \"MAC_OS\"\n : options.platform === \"tvos\"\n ? \"TVOS\"\n : \"IOS\";\n const devices = await options.client.devices.list({\n filter: { platform, status: \"ENABLED\" },\n });\n deviceIds = devices.map((d) => d.id);\n }\n\n // Generate profile name\n const profileName =\n options.profileName ??\n `${profileType} ${options.bundleIdentifier} ${Date.now()}`;\n\n // Create profile\n const profile = await options.client.profiles.create({\n name: profileName,\n profileType,\n bundleIdId: bundleId.id,\n certificateIds,\n deviceIds,\n });\n\n return downloadAndReturn(options, profile);\n}\n\nasync function downloadAndReturn(\n options: SighOptions,\n profile: Profile\n): Promise<SighResult> {\n const content = Buffer.from(profile.attributes.profileContent, \"base64\");\n const profileType = resolveProfileType(options);\n const ext = profileExtension(profileType);\n\n const result: SighResult = {\n profile,\n profileContent: content,\n uuid: profile.attributes.uuid,\n name: profile.attributes.name,\n };\n\n if (options.outputDir) {\n await mkdir(options.outputDir, { recursive: true });\n const filename = `${profileType}_${options.bundleIdentifier}${ext}`;\n const filePath = join(options.outputDir, filename);\n await writeFile(filePath, content);\n result.filePath = filePath;\n }\n\n // Install on macOS\n if (!options.skipInstall && process.platform === \"darwin\") {\n await installProfile(content, profile.attributes.uuid);\n }\n\n return result;\n}\n\nexport async function downloadProfile(\n client: AppStoreConnectClient,\n id: string\n): Promise<Buffer> {\n const profile = await client.profiles.get(id);\n return Buffer.from(profile.attributes.profileContent, \"base64\");\n}\n\n/**\n * Install a provisioning profile to both the legacy MobileDevice directory\n * (Xcode ≤ 15) and the new Xcode 16+ location. Xcode 16 moved the default\n * profiles directory to `~/Library/Developer/Xcode/UserData/Provisioning\n * Profiles/`; writing to both keeps old and new Xcodes happy without needing\n * to detect the installed Xcode version.\n *\n * Returns the legacy path as the primary install location.\n */\nexport async function installProfile(\n profileContent: Buffer,\n uuid: string\n): Promise<string> {\n const legacyDir = join(\n homedir(),\n \"Library\",\n \"MobileDevice\",\n \"Provisioning Profiles\"\n );\n const xcode16Dir = join(\n homedir(),\n \"Library\",\n \"Developer\",\n \"Xcode\",\n \"UserData\",\n \"Provisioning Profiles\"\n );\n const filename = `${uuid}.mobileprovision`;\n\n await mkdir(legacyDir, { recursive: true });\n const legacyPath = join(legacyDir, filename);\n await writeFile(legacyPath, profileContent);\n\n // Also install into the Xcode 16+ location. Non-fatal if it fails\n // (e.g. sandboxed environments).\n try {\n await mkdir(xcode16Dir, { recursive: true });\n await writeFile(join(xcode16Dir, filename), profileContent);\n } catch {\n // Ignore — legacy path install is the authoritative one.\n }\n\n return legacyPath;\n}\n"]}
@@ -0,0 +1,448 @@
1
+ 'use strict';
2
+
3
+ var child_process = require('child_process');
4
+ var util = require('util');
5
+ var fs = require('fs');
6
+ var path = require('path');
7
+
8
+ var __defProp = Object.defineProperty;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __esm = (fn, res) => function __init() {
11
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
+ };
13
+ var __export = (target, all) => {
14
+ for (var name in all)
15
+ __defProp(target, name, { get: all[name], enumerable: true });
16
+ };
17
+
18
+ // src/xcode/platform.ts
19
+ function requireMacOS(feature) {
20
+ if (process.platform !== "darwin") {
21
+ throw new Error(
22
+ `${feature} requires macOS. This operation uses Xcode command-line tools which are not available on ${process.platform}.`
23
+ );
24
+ }
25
+ }
26
+ var init_platform = __esm({
27
+ "src/xcode/platform.ts"() {
28
+ }
29
+ });
30
+
31
+ // src/snapshot/simulator.ts
32
+ var simulator_exports = {};
33
+ __export(simulator_exports, {
34
+ bootSimulator: () => bootSimulator,
35
+ eraseSimulator: () => eraseSimulator,
36
+ findDevice: () => findDevice,
37
+ listSimulators: () => listSimulators,
38
+ localizeSimulator: () => localizeSimulator,
39
+ overrideStatusBar: () => overrideStatusBar,
40
+ setInterfaceStyle: () => setInterfaceStyle,
41
+ shutdownAll: () => shutdownAll
42
+ });
43
+ async function listSimulators() {
44
+ requireMacOS("Simulator management");
45
+ const { stdout } = await execFileAsync("xcrun", ["simctl", "list", "devices", "-j"]);
46
+ const parsed = JSON.parse(stdout);
47
+ const devices = [];
48
+ for (const [runtimeId, runtimeDevices] of Object.entries(parsed.devices)) {
49
+ for (const dev of runtimeDevices) {
50
+ devices.push({
51
+ udid: dev.udid,
52
+ name: dev.name,
53
+ state: dev.state,
54
+ isAvailable: dev.isAvailable,
55
+ runtime: runtimeId,
56
+ deviceTypeIdentifier: dev.deviceTypeIdentifier
57
+ });
58
+ }
59
+ }
60
+ return devices;
61
+ }
62
+ async function findDevice(deviceName, runtimeFilter) {
63
+ const devices = await listSimulators();
64
+ const candidates = devices.filter((d) => {
65
+ if (!d.isAvailable) return false;
66
+ if (d.name !== deviceName) return false;
67
+ if (runtimeFilter && !d.runtime.includes(runtimeFilter)) return false;
68
+ return true;
69
+ });
70
+ if (candidates.length === 0) return null;
71
+ const booted = candidates.find((d) => d.state === "Booted");
72
+ return booted ?? candidates[0];
73
+ }
74
+ async function bootSimulator(udid) {
75
+ requireMacOS("Simulator management");
76
+ const devices = await listSimulators();
77
+ const device = devices.find((d) => d.udid === udid);
78
+ if (device?.state === "Booted") return;
79
+ await execFileAsync("xcrun", ["simctl", "boot", udid]);
80
+ const deadline = Date.now() + 3e4;
81
+ while (Date.now() < deadline) {
82
+ const refreshed = await listSimulators();
83
+ const current = refreshed.find((d) => d.udid === udid);
84
+ if (current?.state === "Booted") return;
85
+ await new Promise((r) => setTimeout(r, 1e3));
86
+ }
87
+ }
88
+ async function shutdownAll() {
89
+ requireMacOS("Simulator management");
90
+ await execFileAsync("xcrun", ["simctl", "shutdown", "all"]);
91
+ }
92
+ async function eraseSimulator(udid) {
93
+ requireMacOS("Simulator management");
94
+ const devices = await listSimulators();
95
+ const device = devices.find((d) => d.udid === udid);
96
+ if (device?.state === "Booted") {
97
+ await execFileAsync("xcrun", ["simctl", "shutdown", udid]);
98
+ }
99
+ await execFileAsync("xcrun", ["simctl", "erase", udid]);
100
+ }
101
+ async function localizeSimulator(udid, language, locale) {
102
+ requireMacOS("Simulator management");
103
+ const deviceDataPath = getDeviceDataPath(udid);
104
+ const prefsDir = path.join(deviceDataPath, "data", "Library", "Preferences");
105
+ const prefsFile = path.join(prefsDir, ".GlobalPreferences.plist");
106
+ if (!fs.existsSync(prefsDir)) {
107
+ fs.mkdirSync(prefsDir, { recursive: true });
108
+ }
109
+ const effectiveLocale = locale ?? language.replace("-", "_");
110
+ const plistXml = [
111
+ '<?xml version="1.0" encoding="UTF-8"?>',
112
+ '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
113
+ '<plist version="1.0">',
114
+ "<dict>",
115
+ " <key>AppleLanguages</key>",
116
+ " <array>",
117
+ " <string>" + escapeXml(language) + "</string>",
118
+ " </array>",
119
+ " <key>AppleLocale</key>",
120
+ " <string>" + escapeXml(effectiveLocale) + "</string>",
121
+ " <key>AppleKeyboards</key>",
122
+ " <array>",
123
+ " <string>" + escapeXml(effectiveLocale) + "@sw=QWERTY;hw=Automatic</string>",
124
+ " </array>",
125
+ " <key>AppleKeyboardsExpanded</key>",
126
+ " <integer>1</integer>",
127
+ "</dict>",
128
+ "</plist>"
129
+ ].join("\n");
130
+ fs.writeFileSync(prefsFile, plistXml, "utf-8");
131
+ try {
132
+ await execFileAsync("plutil", ["-convert", "binary1", prefsFile]);
133
+ } catch {
134
+ }
135
+ }
136
+ async function setInterfaceStyle(udid, style) {
137
+ requireMacOS("Simulator management");
138
+ const appearance = style === "dark" ? "dark" : "light";
139
+ await execFileAsync("xcrun", ["simctl", "ui", udid, "appearance", appearance]);
140
+ }
141
+ async function overrideStatusBar(udid, options) {
142
+ requireMacOS("Simulator management");
143
+ const args = [
144
+ "simctl",
145
+ "status_bar",
146
+ udid,
147
+ "override",
148
+ "--time",
149
+ options?.time ?? "9:41",
150
+ "--batteryLevel",
151
+ String(options?.batteryLevel ?? 100),
152
+ "--batteryState",
153
+ options?.batteryState ?? "charged",
154
+ "--wifiMode",
155
+ options?.wifiMode ?? "active",
156
+ "--wifiBars",
157
+ "3",
158
+ "--cellularMode",
159
+ options?.cellularMode ?? "active",
160
+ "--cellularBars",
161
+ "4"
162
+ ];
163
+ if (options?.dataNetwork) {
164
+ args.push("--dataNetwork", options.dataNetwork);
165
+ }
166
+ await execFileAsync("xcrun", args);
167
+ }
168
+ function getDeviceDataPath(udid) {
169
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "/tmp";
170
+ return path.join(home, "Library", "Developer", "CoreSimulator", "Devices", udid);
171
+ }
172
+ function escapeXml(str) {
173
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
174
+ }
175
+ var execFileAsync;
176
+ var init_simulator = __esm({
177
+ "src/snapshot/simulator.ts"() {
178
+ init_platform();
179
+ execFileAsync = util.promisify(child_process.execFile);
180
+ }
181
+ });
182
+
183
+ // src/snapshot/index.ts
184
+ init_platform();
185
+ init_simulator();
186
+ init_simulator();
187
+ var execFileAsync2 = util.promisify(child_process.execFile);
188
+ async function captureScreenshots(options) {
189
+ requireMacOS("Screenshot capture");
190
+ if (!options.scheme && !options.workspace && !options.project) {
191
+ throw new Error(
192
+ "At least one of scheme, workspace, or project must be specified"
193
+ );
194
+ }
195
+ if (options.devices.length === 0) {
196
+ throw new Error("At least one device must be specified");
197
+ }
198
+ if (options.languages.length === 0) {
199
+ throw new Error("At least one language must be specified");
200
+ }
201
+ const outputDir = options.outputDirectory ?? path.join(process.cwd(), "screenshots");
202
+ const retries = options.numberOfRetries ?? 1;
203
+ if (options.clearPreviousScreenshots && fs.existsSync(outputDir)) {
204
+ const { rm } = await import('fs/promises');
205
+ await rm(outputDir, { recursive: true, force: true });
206
+ }
207
+ fs.mkdirSync(outputDir, { recursive: true });
208
+ const screenshots = {};
209
+ const failedDevices = [];
210
+ const matrix = buildMatrix(options.devices, options.languages);
211
+ if (options.concurrent) {
212
+ const results = await Promise.allSettled(
213
+ matrix.map(
214
+ (entry) => runSingleCombination(entry, options, outputDir, retries)
215
+ )
216
+ );
217
+ for (let i = 0; i < results.length; i++) {
218
+ const result = results[i];
219
+ const entry = matrix[i];
220
+ if (result.status === "fulfilled") {
221
+ mergeScreenshots(screenshots, result.value);
222
+ } else {
223
+ const key = entry.device + " / " + entry.language;
224
+ failedDevices.push(key);
225
+ }
226
+ }
227
+ } else {
228
+ for (const entry of matrix) {
229
+ try {
230
+ const result = await runSingleCombination(
231
+ entry,
232
+ options,
233
+ outputDir,
234
+ retries
235
+ );
236
+ mergeScreenshots(screenshots, result);
237
+ } catch {
238
+ const key = entry.device + " / " + entry.language;
239
+ failedDevices.push(key);
240
+ }
241
+ }
242
+ }
243
+ return {
244
+ success: failedDevices.length === 0,
245
+ screenshots,
246
+ failedDevices
247
+ };
248
+ }
249
+ function buildMatrix(devices, languages) {
250
+ const entries = [];
251
+ for (const device of devices) {
252
+ for (const language of languages) {
253
+ entries.push({ device, language });
254
+ }
255
+ }
256
+ return entries;
257
+ }
258
+ async function runSingleCombination(entry, options, outputDir, retries) {
259
+ const { device: deviceName, language } = entry;
260
+ const simDevice = await findDevice(deviceName);
261
+ if (!simDevice) {
262
+ throw new Error("Simulator device not found: " + deviceName);
263
+ }
264
+ let lastError = null;
265
+ for (let attempt = 0; attempt < retries; attempt++) {
266
+ try {
267
+ return await runOnSimulator(simDevice, language, options, outputDir);
268
+ } catch (err) {
269
+ lastError = err instanceof Error ? err : new Error(String(err));
270
+ options.onOutput?.(
271
+ "Attempt " + (attempt + 1) + " failed for " + deviceName + " / " + language + ": " + lastError.message + "\n"
272
+ );
273
+ }
274
+ }
275
+ throw lastError ?? new Error("All retries exhausted");
276
+ }
277
+ async function runOnSimulator(simDevice, language, options, outputDir) {
278
+ const udid = simDevice.udid;
279
+ const deviceName = simDevice.name;
280
+ if (options.eraseSimulatorBeforeRun) {
281
+ await eraseSimulator(udid);
282
+ }
283
+ try {
284
+ await execFileAsync2("xcrun", ["simctl", "shutdown", udid]);
285
+ } catch {
286
+ }
287
+ await localizeSimulator(udid, language);
288
+ await bootSimulator(udid);
289
+ if (options.overrideStatusBar !== false) {
290
+ try {
291
+ await overrideStatusBar(udid);
292
+ } catch {
293
+ }
294
+ }
295
+ if (options.darkMode) {
296
+ try {
297
+ const { setInterfaceStyle: setInterfaceStyle2 } = await Promise.resolve().then(() => (init_simulator(), simulator_exports));
298
+ await setInterfaceStyle2(udid, "dark");
299
+ } catch {
300
+ }
301
+ }
302
+ const derivedDataPath = options.derivedDataPath ?? path.join(outputDir, ".derived-data", deviceName + "-" + language);
303
+ fs.mkdirSync(derivedDataPath, { recursive: true });
304
+ const exitCode = await runXcodebuildTest(
305
+ udid,
306
+ derivedDataPath,
307
+ options
308
+ );
309
+ if (exitCode !== 0 && exitCode !== 65) {
310
+ throw new Error(
311
+ "xcodebuild test failed with exit code " + exitCode
312
+ );
313
+ }
314
+ const deviceOutputDir = path.join(outputDir, deviceName, language);
315
+ fs.mkdirSync(deviceOutputDir, { recursive: true });
316
+ const collectedPaths = collectScreenshots(derivedDataPath, deviceOutputDir);
317
+ const simScreenshotDir = getSimulatorScreenshotDir(udid);
318
+ if (fs.existsSync(simScreenshotDir)) {
319
+ const simPaths = collectScreenshots(simScreenshotDir, deviceOutputDir);
320
+ collectedPaths.push(...simPaths);
321
+ }
322
+ const result = {};
323
+ if (!result[deviceName]) result[deviceName] = {};
324
+ result[deviceName][language] = collectedPaths;
325
+ return result;
326
+ }
327
+ function runXcodebuildTest(udid, derivedDataPath, options) {
328
+ return new Promise((resolve) => {
329
+ const args = buildXcodebuildArgs(udid, derivedDataPath, options);
330
+ const proc = child_process.spawn("xcodebuild", args, {
331
+ stdio: ["ignore", "pipe", "pipe"]
332
+ });
333
+ proc.stdout.on("data", (chunk) => {
334
+ const text = chunk.toString();
335
+ options.onOutput?.(text);
336
+ });
337
+ proc.stderr.on("data", (chunk) => {
338
+ const text = chunk.toString();
339
+ options.onOutput?.(text);
340
+ });
341
+ proc.on("close", (code) => {
342
+ resolve(code ?? 1);
343
+ });
344
+ proc.on("error", () => {
345
+ resolve(1);
346
+ });
347
+ });
348
+ }
349
+ function buildXcodebuildArgs(udid, derivedDataPath, options) {
350
+ const args = [];
351
+ if (options.workspace) {
352
+ args.push("-workspace", options.workspace);
353
+ } else if (options.project) {
354
+ args.push("-project", options.project);
355
+ }
356
+ if (options.scheme) {
357
+ args.push("-scheme", options.scheme);
358
+ }
359
+ if (options.configuration) {
360
+ args.push("-configuration", options.configuration);
361
+ }
362
+ args.push(
363
+ "-destination",
364
+ "platform=iOS Simulator,id=" + udid,
365
+ "-derivedDataPath",
366
+ derivedDataPath,
367
+ "test"
368
+ );
369
+ if (options.testPlan) {
370
+ args.push("-testPlan", options.testPlan);
371
+ }
372
+ if (options.launchArguments && options.launchArguments.length > 0) {
373
+ const launchArgsStr = options.launchArguments.map((a) => "'" + a + "'").join(" ");
374
+ args.push("SNAPSHOT_LAUNCH_ARGUMENTS=" + launchArgsStr);
375
+ }
376
+ if (options.xcargs) {
377
+ args.push(...options.xcargs.split(/\s+/).filter(Boolean));
378
+ }
379
+ return args;
380
+ }
381
+ function collectScreenshots(sourceDir, destDir) {
382
+ const collected = [];
383
+ if (!fs.existsSync(sourceDir)) return collected;
384
+ const screenshotExtensions = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg"]);
385
+ function walk(dir) {
386
+ let entries;
387
+ try {
388
+ entries = fs.readdirSync(dir, { withFileTypes: true }).map((e) => {
389
+ if (e.isDirectory()) {
390
+ walk(path.join(dir, e.name));
391
+ return "";
392
+ }
393
+ return e.name;
394
+ }).filter(Boolean);
395
+ } catch {
396
+ return;
397
+ }
398
+ for (const name of entries) {
399
+ const ext = path.extname(name).toLowerCase();
400
+ if (screenshotExtensions.has(ext)) {
401
+ const srcPath = path.join(dir, name);
402
+ const destPath = path.join(destDir, path.basename(name));
403
+ try {
404
+ fs.copyFileSync(srcPath, destPath);
405
+ collected.push(destPath);
406
+ } catch {
407
+ }
408
+ }
409
+ }
410
+ }
411
+ walk(sourceDir);
412
+ return collected;
413
+ }
414
+ function getSimulatorScreenshotDir(udid) {
415
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "/tmp";
416
+ return path.join(
417
+ home,
418
+ "Library",
419
+ "Developer",
420
+ "CoreSimulator",
421
+ "Devices",
422
+ udid,
423
+ "data",
424
+ "tmp",
425
+ "Screenshots"
426
+ );
427
+ }
428
+ function mergeScreenshots(target, source) {
429
+ for (const [device, languages] of Object.entries(source)) {
430
+ if (!target[device]) target[device] = {};
431
+ for (const [lang, paths] of Object.entries(languages)) {
432
+ if (!target[device][lang]) target[device][lang] = [];
433
+ target[device][lang].push(...paths);
434
+ }
435
+ }
436
+ }
437
+
438
+ exports.bootSimulator = bootSimulator;
439
+ exports.captureScreenshots = captureScreenshots;
440
+ exports.eraseSimulator = eraseSimulator;
441
+ exports.findDevice = findDevice;
442
+ exports.listSimulators = listSimulators;
443
+ exports.localizeSimulator = localizeSimulator;
444
+ exports.overrideStatusBar = overrideStatusBar;
445
+ exports.setInterfaceStyle = setInterfaceStyle;
446
+ exports.shutdownAll = shutdownAll;
447
+ //# sourceMappingURL=index.cjs.map
448
+ //# sourceMappingURL=index.cjs.map