peachsim 0.1.1625 → 0.1.1640

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 (169) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +15 -2
  3. package/cli/app-config.ts +18 -6
  4. package/cli/app-fonts.ts +37 -17
  5. package/cli/app-stubs.ts +284 -20
  6. package/cli/bridge-flow-runner.ts +66 -45
  7. package/cli/cloud-client.ts +60 -40
  8. package/cli/command-registry.ts +1 -0
  9. package/cli/commands/control.ts +283 -49
  10. package/cli/commands/doctor.ts +30 -189
  11. package/cli/commands/flow.ts +79 -11
  12. package/cli/commands/inspect/core.ts +10 -5
  13. package/cli/commands/inspect/settling.ts +14 -2
  14. package/cli/commands/inspect/shared.ts +9 -4
  15. package/cli/commands/inspect/wait-ready.ts +12 -0
  16. package/cli/commands/inspect.ts +91 -50
  17. package/cli/commands/install-desktop.ts +1 -0
  18. package/cli/commands/maestro-compare.ts +97 -38
  19. package/cli/commands/maestro.ts +9 -1
  20. package/cli/commands/preview.ts +1 -1
  21. package/cli/commands/record.ts +118 -48
  22. package/cli/commands/screenshot.ts +23 -1
  23. package/cli/commands/serve.ts +7 -2
  24. package/cli/commands/setup.ts +19 -42
  25. package/cli/commands/swift.ts +14 -3
  26. package/cli/commands/upload.ts +93 -48
  27. package/cli/desktop-companion.ts +102 -17
  28. package/cli/drivers/desktop.ts +14 -1
  29. package/cli/drivers/playwright-sim-host.ts +103 -45
  30. package/cli/drivers/playwright.ts +9 -8
  31. package/cli/drivers/types.ts +5 -0
  32. package/cli/maestro-accessibility.ts +1 -1
  33. package/cli/maestro-compare.ts +84 -12
  34. package/cli/main.ts +3 -2
  35. package/cli/outbound-endpoints.ts +20 -6
  36. package/cli/pause-aware-timeout.ts +106 -0
  37. package/cli/scene-video.ts +89 -0
  38. package/cli/ws-bridge.ts +37 -19
  39. package/detox/attempt-events.cjs +66 -5
  40. package/detox/attempt-events.d.cts +7 -0
  41. package/detox/expectations.ts +7 -3
  42. package/detox/index.ts +269 -170
  43. package/detox/motion-change.cjs +206 -21
  44. package/detox/motion-change.d.cts +39 -2
  45. package/detox/navigation-lifecycle.ts +35 -3
  46. package/dist-lib/agent-daemon-client.cjs +1 -1
  47. package/dist-lib/agent-events.cjs +1 -1
  48. package/dist-lib/attached-projects.cjs +1 -1
  49. package/dist-lib/auth/shared-session.cjs +1 -1
  50. package/dist-lib/backend-origin.cjs +8 -7
  51. package/dist-lib/beta.cjs +1 -1
  52. package/dist-lib/beta.mjs +1 -1
  53. package/dist-lib/bridge-constants.cjs +13 -1
  54. package/dist-lib/bridge-contract-input.cjs +1 -1
  55. package/dist-lib/bridge-contract-input.mjs +1 -1
  56. package/dist-lib/bridge-contract.cjs +14 -8
  57. package/dist-lib/bridge-contract.mjs +13 -7
  58. package/dist-lib/bundle-channel.cjs +11887 -7900
  59. package/dist-lib/capture-contract.cjs +1 -1
  60. package/dist-lib/capture-contract.mjs +1 -1
  61. package/dist-lib/cloud-contract.cjs +1 -1
  62. package/dist-lib/cloud-contract.mjs +1 -1
  63. package/dist-lib/cloud-test-args.cjs +1 -1
  64. package/dist-lib/cloud-test-args.mjs +1 -1
  65. package/dist-lib/cloud.cjs +1 -1
  66. package/dist-lib/cloud.mjs +1 -1
  67. package/dist-lib/config.cjs +6 -3
  68. package/dist-lib/config.mjs +6 -3
  69. package/dist-lib/detox/index.cjs +1379 -725
  70. package/dist-lib/dev-bundle-resolution.cjs +14 -2
  71. package/dist-lib/expo-swift-bundle.cjs +9341 -5462
  72. package/dist-lib/expo-swift-metadata.cjs +11 -7
  73. package/dist-lib/expo-swift-metadata.mjs +11 -7
  74. package/dist-lib/home-paths.cjs +32 -3
  75. package/dist-lib/host/bridge-host.cjs +50204 -7258
  76. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  77. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  78. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  79. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  80. package/dist-lib/host/websocket-proxy.cjs +1 -1
  81. package/dist-lib/index.cjs +3541 -448
  82. package/dist-lib/jump-to-source-babel.cjs +1 -1
  83. package/dist-lib/jump-to-source-native.cjs +1 -1
  84. package/dist-lib/kotlin-host.cjs +1 -1
  85. package/dist-lib/menu.cjs +1 -1
  86. package/dist-lib/menu.mjs +1 -1
  87. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  88. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  89. package/dist-lib/metro-production-bundle.cjs +1 -1
  90. package/dist-lib/metro-production-bundle.mjs +1 -1
  91. package/dist-lib/metro.cjs +2931 -104
  92. package/dist-lib/native-app-identity-project.cjs +289 -49
  93. package/dist-lib/native-app-identity-project.mjs +289 -49
  94. package/dist-lib/native-app-identity.cjs +77 -26
  95. package/dist-lib/native-app-identity.mjs +76 -26
  96. package/dist-lib/native-firebase-metadata.cjs +1 -1
  97. package/dist-lib/native-firebase-metadata.mjs +1 -1
  98. package/dist-lib/plist.cjs +1 -1
  99. package/dist-lib/plist.mjs +1 -1
  100. package/dist-lib/profiles.cjs +1 -1
  101. package/dist-lib/public-brand.cjs +1 -1
  102. package/dist-lib/react-native-host-modules.cjs +6 -2
  103. package/dist-lib/react-native-host-modules.mjs +6 -2
  104. package/dist-lib/scripts/dev-server-scanner.cjs +22 -8
  105. package/dist-lib/sdk.cjs +27 -11
  106. package/dist-lib/sdk.mjs +27 -10
  107. package/dist-lib/skills.cjs +72201 -26208
  108. package/dist-lib/swift-compile.cjs +1007 -140
  109. package/dist-lib/swift-compile.mjs +1049 -174
  110. package/dist-lib/swift-package.cjs +12 -3
  111. package/dist-lib/swift-package.mjs +12 -3
  112. package/dist-lib/swift-submit.cjs +13 -5
  113. package/dist-lib/swift-submit.mjs +11 -5
  114. package/dist-lib/swift-toolchain.cjs +423 -33
  115. package/dist-lib/swift.cjs +1 -1
  116. package/dist-lib/vite-swift.cjs +8628 -5268
  117. package/dist-lib/vite.cjs +2859 -12
  118. package/dist-lib/worklet-executable.cjs +14 -2
  119. package/dist-lib/worklet-executable.mjs +14 -2
  120. package/kotlin/AppSources/dev/peach/app/PeachDrawable.kt +21 -14
  121. package/kotlin/Sources/androidx/annotation/DrawableRes.kt +14 -0
  122. package/package.json +1 -1
  123. package/scripts/dev-server-scanner.ts +2 -1
  124. package/skills/peach-perf/SKILL.md +11 -5
  125. package/skills/peach-setup/SKILL.md +16 -19
  126. package/src/backend-origin.ts +13 -6
  127. package/src/bridge-constants.ts +11 -0
  128. package/src/bridge-contract.ts +22 -34
  129. package/src/config.ts +15 -0
  130. package/src/desktop-host-delivery.ts +5 -1
  131. package/src/dev-bundle-resolution.ts +2 -1
  132. package/src/expo-manifest-body.ts +13 -0
  133. package/src/expo-swift-host.ts +196 -49
  134. package/src/expo-swift-ready.ts +78 -0
  135. package/src/expoKotlinContract.ts +4 -7
  136. package/src/expoSwiftContract.ts +17 -6
  137. package/src/home-paths.ts +48 -2
  138. package/src/host/bridge-host.ts +5 -2
  139. package/src/host/staged-host-files.ts +9 -0
  140. package/src/native-app-identity-project.ts +27 -6
  141. package/src/native-app-identity.ts +91 -4
  142. package/src/native-firebase-config.ts +209 -13
  143. package/src/nativeAppIconContract.ts +1 -4
  144. package/src/output-lock-stdio.ts +36 -0
  145. package/src/process-group.ts +25 -2
  146. package/src/react-native-bridge-modules.ts +431 -0
  147. package/src/react-native-host-modules.ts +8 -1
  148. package/src/settings-bundle.ts +1 -4
  149. package/src/swift-binary-modules.ts +2 -2
  150. package/src/swift-compile.ts +918 -109
  151. package/src/swift-compiler-digest.ts +14 -0
  152. package/src/swift-distribution.lock.json +24 -12
  153. package/src/swift-distribution.ts +103 -4
  154. package/src/swift-host.ts +180 -55
  155. package/src/swift-icu.ts +27 -13
  156. package/src/swift-objc-compile.ts +355 -0
  157. package/src/swift-objc-sdk.ts +821 -27
  158. package/src/swift-objc-standin.ts +148 -14
  159. package/src/swift-package-manifest.ts +60 -7
  160. package/src/swift-package.ts +15 -1
  161. package/src/swift-packages.ts +154 -81
  162. package/src/swift-standin-emit.ts +96 -15
  163. package/src/swift-standins.ts +530 -116
  164. package/src/swift-submit.ts +13 -5
  165. package/src/swift-toolchain.ts +500 -42
  166. package/src/vite-plugin.ts +12 -1
  167. package/src/worker-system-chunks.ts +11 -12
  168. package/src/worklet-executable.ts +19 -1
  169. package/src/xcode-project.ts +270 -30
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -32,18 +32,70 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
32
32
  // src/swift-toolchain.ts
33
33
  var swift_toolchain_exports = {};
34
34
  __export(swift_toolchain_exports, {
35
+ SWIFT_HOST_COMPILER_ID: () => SWIFT_HOST_COMPILER_ID,
36
+ SWIFT_HOST_COMPILER_RELEASE: () => SWIFT_HOST_COMPILER_RELEASE,
37
+ confineSwiftScratch: () => confineSwiftScratch,
38
+ installSwiftWasmSdk: () => installSwiftWasmSdk,
39
+ swiftCompiler: () => swiftCompiler,
40
+ swiftCompilerInstallSteps: () => swiftCompilerInstallSteps,
35
41
  swiftCompilerRelease: () => swiftCompilerRelease,
42
+ swiftEnvironment: () => swiftEnvironment,
43
+ swiftFileChecksum: () => swiftFileChecksum,
44
+ swiftHostCompilerArchive: () => swiftHostCompilerArchive,
36
45
  swiftInstallSteps: () => swiftInstallSteps,
46
+ swiftSdkInstallStep: () => swiftSdkInstallStep,
47
+ swiftSdkOptions: () => swiftSdkOptions,
37
48
  swiftToolchain: () => swiftToolchain,
38
- swiftToolchainBin: () => swiftToolchainBin
49
+ swiftToolchainBin: () => swiftToolchainBin,
50
+ swiftUpstreamRelease: () => swiftUpstreamRelease,
51
+ verifySwiftHostCompiler: () => verifySwiftHostCompiler
39
52
  });
40
53
  module.exports = __toCommonJS(swift_toolchain_exports);
41
54
  var import_node_child_process = require("node:child_process");
55
+ var import_node_crypto = require("node:crypto");
42
56
  var import_node_fs = __toESM(require("node:fs"), 1);
43
57
  var import_node_os = __toESM(require("node:os"), 1);
44
58
  var import_node_path = __toESM(require("node:path"), 1);
59
+ var import_node_url = require("node:url");
60
+ function swiftSdkOptions() {
61
+ const directory = process.env.PEACH_SWIFT_SDKS_PATH;
62
+ return directory ? ["--swift-sdks-path", import_node_path.default.resolve(directory)] : [];
63
+ }
64
+ var SWIFT_HOST_COMPILER_RELEASE = "swift-6.4.0-RELEASE-custom-0d775d32d7c74eae";
65
+ var SWIFT_HOST_COMPILER_ID = "0d775d32d7c74eae";
66
+ var compilerArchives = {
67
+ "darwin-arm64": {
68
+ checksum: "957e85486f92327ee5cf8d3c5bb9336d17ab80145c87645c637c49130a50477a",
69
+ manifest: "c63e2f81694e8d8ad046d10c71d0638dbae4e5a36601294ed670988d1cb5b6f1"
70
+ },
71
+ "linux-x64": {
72
+ checksum: "6302230fb126b79c9af5fc2bc0208a936bb573c343da7ae949c5c1687e761cd2",
73
+ manifest: "31b507a6a8648a2266a187b9fed092e29a63cae99d57c5defdf2e82a7cbbc113"
74
+ },
75
+ "linux-arm64": {
76
+ checksum: "9b40d39ea5ba82fd9a417868f0a449f5e98e37cf83acaac9cedd3a8b8d91a218",
77
+ manifest: "fe07a29d4f4374cad47b29de70e90aa2e3b7664e08c8b53d304585e65637da24"
78
+ }
79
+ };
80
+ function swiftHostCompilerArchive(release, host = `${process.platform}-${process.arch}`) {
81
+ if (release !== SWIFT_HOST_COMPILER_RELEASE)
82
+ throw new Error(`unqualified host compiler ${release}`);
83
+ const archive = compilerArchives[host];
84
+ if (!archive) throw new Error(`unsupported Swift compiler host ${host}`);
85
+ return {
86
+ ...archive,
87
+ identity: SWIFT_HOST_COMPILER_ID,
88
+ url: `https://r2.sootsim.com/swift-host-compiler/${SWIFT_HOST_COMPILER_ID}/${release}-${host}.tar.gz`
89
+ };
90
+ }
91
+ function swiftUpstreamRelease(release) {
92
+ return release.replace(/-custom-[a-f0-9]{16}$/, "");
93
+ }
45
94
  function swiftCompilerRelease(release) {
46
- return release.replace(/^swift-(\d+\.\d+)\.0-RELEASE$/, "swift-$1-RELEASE");
95
+ return swiftUpstreamRelease(release).replace(
96
+ /^swift-(\d+\.\d+)\.0-RELEASE$/,
97
+ "swift-$1-RELEASE"
98
+ );
47
99
  }
48
100
  function swiftToolchainBin(release) {
49
101
  if (process.platform === "darwin") {
@@ -57,64 +109,402 @@ function swiftToolchainBin(release) {
57
109
  }
58
110
  const image = import_node_path.default.join("/opt/swift", release, "usr/bin");
59
111
  if (import_node_fs.default.existsSync(import_node_path.default.join(image, "swift"))) return image;
112
+ if (release.includes("-custom-"))
113
+ return import_node_path.default.join(peachHome(), "swift", "toolchains", release, "usr/bin");
60
114
  return (process.env.PATH ?? "").split(import_node_path.default.delimiter).find((dir) => dir && import_node_fs.default.existsSync(import_node_path.default.join(dir, "swift"))) ?? image;
61
115
  }
62
- var verified = /* @__PURE__ */ new Map();
116
+ function peachHome() {
117
+ const override = process.env.PEACH_HOME;
118
+ return override ? import_node_path.default.resolve(override) : import_node_path.default.join(import_node_os.default.homedir(), ".peach");
119
+ }
120
+ var scratch;
121
+ var swiftHome;
122
+ function confineSwiftScratch(root) {
123
+ if (scratch) return;
124
+ import_node_fs.default.mkdirSync(root, { recursive: true });
125
+ for (const name of import_node_fs.default.readdirSync(root)) {
126
+ const pid = Number(name);
127
+ if (Number.isInteger(pid) && pid > 0 && !processRuns(pid))
128
+ import_node_fs.default.rmSync(import_node_path.default.join(root, name), { recursive: true, force: true });
129
+ }
130
+ const dir = import_node_path.default.join(root, String(process.pid));
131
+ import_node_fs.default.mkdirSync(dir, { recursive: true });
132
+ scratch = dir;
133
+ if (process.platform === "linux") {
134
+ swiftHome = import_node_path.default.join(root, "home");
135
+ import_node_fs.default.mkdirSync(swiftHome, { recursive: true });
136
+ }
137
+ const seeded = import_node_path.default.join(import_node_os.default.homedir(), ".swiftpm");
138
+ const dirAbsentBefore = lstatIfKnown(seeded) === null;
139
+ const absentBefore = swiftpmSeeds.filter(
140
+ (name) => lstatIfKnown(import_node_path.default.join(seeded, name)) === null
141
+ );
142
+ process.once("exit", () => {
143
+ import_node_fs.default.rmSync(dir, { recursive: true, force: true });
144
+ for (const name of absentBefore) removeSwiftpmSeed(import_node_path.default.join(seeded, name), name);
145
+ if (dirAbsentBefore && lstatIfKnown(seeded)?.isDirectory())
146
+ try {
147
+ import_node_fs.default.rmdirSync(seeded);
148
+ } catch {
149
+ }
150
+ });
151
+ }
152
+ var swiftpmSeeds = ["cache", "configuration", "security"];
153
+ function lstatIfKnown(entry) {
154
+ try {
155
+ return import_node_fs.default.lstatSync(entry);
156
+ } catch (error) {
157
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") return null;
158
+ return void 0;
159
+ }
160
+ }
161
+ function removeSwiftpmSeed(entry, name) {
162
+ const stat = lstatIfKnown(entry);
163
+ if (!stat) return;
164
+ try {
165
+ if (name === "cache") {
166
+ if (stat.isSymbolicLink() && import_node_fs.default.readlinkSync(entry).endsWith("/.cache/org.swift.swiftpm"))
167
+ import_node_fs.default.unlinkSync(entry);
168
+ } else if (stat.isDirectory()) {
169
+ import_node_fs.default.rmdirSync(entry);
170
+ }
171
+ } catch {
172
+ }
173
+ }
174
+ function processRuns(pid) {
175
+ try {
176
+ process.kill(pid, 0);
177
+ return true;
178
+ } catch (error) {
179
+ return error instanceof Error && "code" in error && error.code === "EPERM";
180
+ }
181
+ }
182
+ function swiftEnvironment(base = process.env) {
183
+ if (!scratch) return base;
184
+ return swiftHome ? { ...base, TMPDIR: scratch, HOME: swiftHome } : { ...base, TMPDIR: scratch };
185
+ }
63
186
  function swiftToolchain(release, sdk) {
64
- const cached = verified.get(`${release}\0${sdk.wasmSdkId}`);
65
- if (cached) return cached;
66
- const bin = swiftToolchainBin(release);
67
- const swift = import_node_path.default.join(bin, "swift");
68
- const version = import_node_fs.default.existsSync(swift) ? (0, import_node_child_process.execFileSync)(swift, ["--version"], {
69
- encoding: "utf8",
70
- stdio: ["ignore", "pipe", "pipe"]
71
- }) : "";
72
- if (!version.includes(`(${swiftCompilerRelease(release)})`)) {
73
- const found = version ? `found ${version.split("\n")[0]?.trim()} at ${swift}` : process.platform === "darwin" ? `found no ${release}.xctoolchain in ~/Library/Developer/Toolchains or /Library/Developer/Toolchains` : "found no swift on PATH";
187
+ validateSwiftSdkIdentity(sdk);
188
+ let bin;
189
+ try {
190
+ bin = swiftCompiler(release);
191
+ } catch (error) {
192
+ const reason = error instanceof Error ? error.message : String(error);
74
193
  throw new Error(
75
- `peach compiles Swift with the swift.org toolchain ${release} and its wasm SDK; ${found}.
194
+ `Swift compiler ${release} is unavailable or differs from its pin: ${reason}
76
195
  ${swiftInstallSteps(release, sdk)}`
77
196
  );
78
197
  }
79
- const sdks = (0, import_node_child_process.execFileSync)(swift, ["sdk", "list"], {
198
+ const swift = import_node_path.default.join(bin, "swift");
199
+ const sdks = (0, import_node_child_process.execFileSync)(swift, ["sdk", "list", ...swiftSdkOptions()], {
80
200
  encoding: "utf8",
201
+ env: swiftEnvironment(),
81
202
  stdio: ["ignore", "pipe", "pipe"]
82
203
  });
83
204
  if (!sdks.split("\n").some((line) => line.trim() === sdk.wasmSdkId)) {
84
205
  throw new Error(
85
206
  `peach compiles Swift with the ${sdk.wasmSdkId} SDK, which ${swift} does not have.
86
- ${swiftInstallSteps(release, sdk)}`
207
+ ${swiftSdkInstallStep(release, sdk)}`
208
+ );
209
+ }
210
+ try {
211
+ verifySwiftSdk(swift, sdk);
212
+ } catch (error) {
213
+ const reason = error instanceof Error ? error.message : String(error);
214
+ throw new Error(`${reason}
215
+ ${swiftSdkInstallStep(release, sdk)}`);
216
+ }
217
+ return bin;
218
+ }
219
+ function validateSwiftSdkIdentity(sdk) {
220
+ if (!/^[a-zA-Z0-9._-]+$/.test(sdk.wasmSdkId) || !/^[a-f0-9]{64}$/.test(sdk.wasmSdkChecksum))
221
+ throw new Error("invalid Swift SDK identity or checksum");
222
+ }
223
+ function swiftSdkBundle(swift, id, options) {
224
+ const configuration = (0, import_node_child_process.execFileSync)(
225
+ swift,
226
+ ["sdk", "configure", ...options, "--show-configuration", id, "wasm32-unknown-wasip1"],
227
+ { encoding: "utf8", env: swiftEnvironment(), stdio: ["ignore", "pipe", "pipe"] }
228
+ );
229
+ const sysroot = /^sdkRootPath: (.+)$/m.exec(configuration)?.[1]?.trim();
230
+ if (!sysroot || !import_node_path.default.isAbsolute(sysroot))
231
+ throw new Error(`Swift SDK ${id} reports no absolute sdkRootPath`);
232
+ let bundle = sysroot;
233
+ while (!bundle.endsWith(".artifactbundle")) {
234
+ const parent = import_node_path.default.dirname(bundle);
235
+ if (parent === bundle)
236
+ throw new Error(`Swift SDK ${id} is outside an artifact bundle`);
237
+ bundle = parent;
238
+ }
239
+ return import_node_fs.default.realpathSync(bundle);
240
+ }
241
+ var sdkFileHashes = /* @__PURE__ */ new Map();
242
+ function swiftSdkPayloadChecksum(bundle) {
243
+ const hash = (0, import_node_crypto.createHash)("sha256");
244
+ function visit(relative) {
245
+ const file = import_node_path.default.join(bundle, relative);
246
+ const stat = import_node_fs.default.lstatSync(file, { bigint: true });
247
+ if (stat.isSymbolicLink()) {
248
+ const resolved = import_node_path.default.relative(bundle, import_node_fs.default.realpathSync(file));
249
+ if (resolved === ".." || resolved.startsWith(`..${import_node_path.default.sep}`) || import_node_path.default.isAbsolute(resolved))
250
+ throw new Error(`Swift SDK symlink escapes its bundle: ${relative}`);
251
+ hash.update(JSON.stringify([relative, "link", import_node_fs.default.readlinkSync(file)]) + "\n");
252
+ } else if (stat.isDirectory()) {
253
+ hash.update(JSON.stringify([relative, "directory"]) + "\n");
254
+ for (const name of import_node_fs.default.readdirSync(file).sort()) visit(import_node_path.default.join(relative, name));
255
+ } else if (stat.isFile()) {
256
+ const stamp = [stat.dev, stat.ino, stat.size, stat.mtimeNs, stat.ctimeNs].join(":");
257
+ let cached = sdkFileHashes.get(file);
258
+ if (cached?.stamp !== stamp) {
259
+ cached = { stamp, checksum: swiftFileChecksum(file) };
260
+ sdkFileHashes.set(file, cached);
261
+ }
262
+ hash.update(
263
+ JSON.stringify([relative, "file", Number(stat.mode & 0o111n), cached.checksum]) + "\n"
264
+ );
265
+ } else throw new Error(`unsupported Swift SDK payload entry: ${relative}`);
266
+ }
267
+ visit("");
268
+ return hash.digest("hex");
269
+ }
270
+ function swiftSdkVerificationFile(bundle, sdk) {
271
+ return import_node_path.default.join(
272
+ import_node_path.default.dirname(bundle),
273
+ ".peach-sdk-checksums",
274
+ `${sdk.wasmSdkId}-${sdk.wasmSdkChecksum}.json`
275
+ );
276
+ }
277
+ function verifySwiftSdk(swift, sdk) {
278
+ const bundle = swiftSdkBundle(swift, sdk.wasmSdkId, swiftSdkOptions());
279
+ const file = swiftSdkVerificationFile(bundle, sdk);
280
+ if (!import_node_fs.default.existsSync(file))
281
+ throw new Error(
282
+ `Swift SDK ${sdk.wasmSdkId} has no verified archive binding for ${sdk.wasmSdkChecksum}. Hydrate it with installSwiftWasmSdk before compiling.`
283
+ );
284
+ const receipt = JSON.parse(import_node_fs.default.readFileSync(file, "utf8"));
285
+ if (!receipt || typeof receipt !== "object" || !("wasmSdkId" in receipt) || receipt.wasmSdkId !== sdk.wasmSdkId || !("wasmSdkChecksum" in receipt) || receipt.wasmSdkChecksum !== sdk.wasmSdkChecksum || !("payloadChecksum" in receipt) || receipt.payloadChecksum !== swiftSdkPayloadChecksum(bundle))
286
+ throw new Error(
287
+ `Swift SDK ${sdk.wasmSdkId} installed payload differs from its verified archive ${sdk.wasmSdkChecksum}`
87
288
  );
289
+ }
290
+ function installSwiftSdkArchive(swift, sdk, archive) {
291
+ validateSwiftSdkIdentity(sdk);
292
+ const staging = import_node_fs.default.realpathSync(
293
+ import_node_fs.default.mkdtempSync(import_node_path.default.join(scratch ?? import_node_os.default.tmpdir(), "peach-sdk-verification-"))
294
+ );
295
+ try {
296
+ if (swiftFileChecksum(archive) !== sdk.wasmSdkChecksum)
297
+ throw new Error("declared Swift SDK archive checksum mismatch");
298
+ const store = import_node_path.default.join(staging, "sdks");
299
+ import_node_fs.default.mkdirSync(store);
300
+ (0, import_node_child_process.execFileSync)(
301
+ swift,
302
+ [
303
+ "sdk",
304
+ "install",
305
+ archive,
306
+ "--checksum",
307
+ sdk.wasmSdkChecksum,
308
+ "--swift-sdks-path",
309
+ store
310
+ ],
311
+ { env: swiftEnvironment(), stdio: "inherit" }
312
+ );
313
+ const stagedBundle = swiftSdkBundle(swift, sdk.wasmSdkId, [
314
+ "--swift-sdks-path",
315
+ store
316
+ ]);
317
+ const expected = swiftSdkPayloadChecksum(stagedBundle);
318
+ const directory = process.env.PEACH_SWIFT_SDKS_PATH;
319
+ const locks = directory ? import_node_path.default.join(import_node_path.default.resolve(directory), ".peach-locks") : import_node_path.default.join(import_node_os.default.homedir(), ".swiftpm", "builder-locks");
320
+ import_node_fs.default.mkdirSync(locks, { recursive: true });
321
+ (0, import_node_child_process.execFileSync)(
322
+ "perl",
323
+ [
324
+ "-e",
325
+ 'use Fcntl qw(:flock); my ($lock, $id, $bundle, $swift, @options) = @ARGV; open(my $fd, ">>", $lock) or die $!; flock($fd, LOCK_EX) or die $!; open(my $list, "-|", $swift, "sdk", "list", @options) or die $!; my $found = 0; while (<$list>) { s/^\\s+|\\s+$//g; $found = 1 if $_ eq $id; } close($list) or die "swift sdk list failed"; unless ($found) { system($swift, "sdk", "install", $bundle, @options); exit(($? & 127) ? 128 + ($? & 127) : $? >> 8); }',
326
+ import_node_path.default.join(locks, "wasm-sdk.lock"),
327
+ sdk.wasmSdkId,
328
+ stagedBundle,
329
+ swift,
330
+ ...swiftSdkOptions()
331
+ ],
332
+ { env: swiftEnvironment(), stdio: "inherit" }
333
+ );
334
+ const bundle = swiftSdkBundle(swift, sdk.wasmSdkId, swiftSdkOptions());
335
+ if (swiftSdkPayloadChecksum(bundle) !== expected)
336
+ throw new Error(
337
+ `Swift SDK ${sdk.wasmSdkId} already exists with different payload bytes; select a separate --swift-sdks-path. No installed SDK was replaced.`
338
+ );
339
+ const file = swiftSdkVerificationFile(bundle, sdk);
340
+ import_node_fs.default.mkdirSync(import_node_path.default.dirname(file), { recursive: true });
341
+ const temporary = `${file}.${process.pid}.tmp`;
342
+ try {
343
+ import_node_fs.default.writeFileSync(
344
+ temporary,
345
+ JSON.stringify({
346
+ wasmSdkId: sdk.wasmSdkId,
347
+ wasmSdkChecksum: sdk.wasmSdkChecksum,
348
+ payloadChecksum: expected
349
+ }) + "\n"
350
+ );
351
+ import_node_fs.default.renameSync(temporary, file);
352
+ } finally {
353
+ import_node_fs.default.rmSync(temporary, { force: true });
354
+ }
355
+ } finally {
356
+ import_node_fs.default.rmSync(staging, { recursive: true, force: true });
357
+ for (const file of sdkFileHashes.keys())
358
+ if (file.startsWith(staging + import_node_path.default.sep)) sdkFileHashes.delete(file);
88
359
  }
89
- verified.set(`${release}\0${sdk.wasmSdkId}`, bin);
360
+ }
361
+ function installSwiftWasmSdk(release, sdk) {
362
+ validateSwiftSdkIdentity(sdk);
363
+ try {
364
+ swiftToolchain(release, sdk);
365
+ return;
366
+ } catch {
367
+ }
368
+ const swift = import_node_path.default.join(swiftCompiler(release), "swift");
369
+ const staging = import_node_fs.default.mkdtempSync(import_node_path.default.join(scratch ?? import_node_os.default.tmpdir(), "builder-swift-sdk-"));
370
+ const archive = import_node_path.default.join(staging, "sdk.artifactbundle.tar.gz");
371
+ try {
372
+ if (sdk.wasmSdkUrl.startsWith("file:"))
373
+ import_node_fs.default.copyFileSync((0, import_node_url.fileURLToPath)(sdk.wasmSdkUrl), archive);
374
+ else
375
+ (0, import_node_child_process.execFileSync)("curl", ["-fsSL", sdk.wasmSdkUrl, "-o", archive], { stdio: "inherit" });
376
+ installSwiftSdkArchive(swift, sdk, archive);
377
+ swiftToolchain(release, sdk);
378
+ } finally {
379
+ import_node_fs.default.rmSync(staging, { recursive: true, force: true });
380
+ }
381
+ }
382
+ function swiftFileChecksum(file) {
383
+ const hash = (0, import_node_crypto.createHash)("sha256");
384
+ const fd = import_node_fs.default.openSync(file, "r");
385
+ const buffer = Buffer.allocUnsafe(1024 * 1024);
386
+ try {
387
+ let size = import_node_fs.default.readSync(fd, buffer, 0, buffer.length, null);
388
+ while (size > 0) {
389
+ hash.update(buffer.subarray(0, size));
390
+ size = import_node_fs.default.readSync(fd, buffer, 0, buffer.length, null);
391
+ }
392
+ } finally {
393
+ import_node_fs.default.closeSync(fd);
394
+ }
395
+ return hash.digest("hex");
396
+ }
397
+ function verifySwiftHostCompiler(release, root) {
398
+ const pin = swiftHostCompilerArchive(release);
399
+ const file = import_node_path.default.join(root, "compiler.json");
400
+ if (swiftFileChecksum(file) !== pin.manifest)
401
+ throw new Error(`Swift compiler manifest mismatch at ${root}`);
402
+ const manifest = JSON.parse(import_node_fs.default.readFileSync(file, "utf8"));
403
+ if (!manifest || typeof manifest !== "object" || !("identity" in manifest) || manifest.identity !== pin.identity || !("host" in manifest) || manifest.host !== `${process.platform}-${process.arch}` || !("files" in manifest) || !manifest.files || typeof manifest.files !== "object") {
404
+ throw new Error(`Swift compiler identity mismatch at ${root}`);
405
+ }
406
+ const files = Object.entries(manifest.files);
407
+ if (files.length !== 16) throw new Error("incomplete Swift compiler manifest");
408
+ for (const [relative, checksum] of files) {
409
+ if (relative.startsWith("/") || relative.split("/").includes("..") || typeof checksum !== "string" || swiftFileChecksum(import_node_path.default.join(root, relative)) !== checksum) {
410
+ throw new Error(`Swift compiler binary mismatch: ${relative}`);
411
+ }
412
+ }
413
+ }
414
+ var verifiedCompilers = /* @__PURE__ */ new Map();
415
+ function swiftCompiler(release) {
416
+ const cached = verifiedCompilers.get(release);
417
+ if (cached) return cached;
418
+ const bin = swiftToolchainBin(release);
419
+ if (release.includes("-custom-"))
420
+ verifySwiftHostCompiler(release, import_node_path.default.resolve(bin, "../.."));
421
+ const version = (0, import_node_child_process.execFileSync)(import_node_path.default.join(bin, "swift"), ["--version"], {
422
+ encoding: "utf8",
423
+ env: swiftEnvironment(),
424
+ stdio: ["ignore", "pipe", "pipe"]
425
+ });
426
+ if (!version.includes(`(${swiftCompilerRelease(release)})`))
427
+ throw new Error(`compiler release mismatch at ${bin}`);
428
+ verifiedCompilers.set(release, bin);
90
429
  return bin;
91
430
  }
431
+ function swiftSdkInstallStep(release, wasmSdk) {
432
+ return `install the pinned SDK:
433
+ ${swiftSdkInstallCommand(release, wasmSdk)}`;
434
+ }
435
+ function swiftSdkInstallCommand(release, wasmSdk) {
436
+ const { wasmSdkId, wasmSdkUrl, wasmSdkChecksum } = wasmSdk;
437
+ const program = `import { installSwiftWasmSdk } from "peachsim/swift-toolchain"; installSwiftWasmSdk(${JSON.stringify(release)}, ${JSON.stringify({ wasmSdkId, wasmSdkUrl, wasmSdkChecksum })})`;
438
+ const directory = process.env.PEACH_SWIFT_SDKS_PATH;
439
+ const environment = directory ? `PEACH_SWIFT_SDKS_PATH='${import_node_path.default.resolve(directory).replaceAll("'", "'\\''")}' ` : "";
440
+ return `${environment}node --input-type=module -e '${program.replaceAll("'", "'\\''")}'`;
441
+ }
92
442
  function swiftInstallSteps(release, wasmSdk) {
443
+ const { note, commands } = swiftCompilerInstall(release);
444
+ return [
445
+ `install the pinned compiler and SDK${note}:`,
446
+ ...[...commands, swiftSdkInstallCommand(release, wasmSdk)].map((line) => ` ${line}`)
447
+ ].join("\n");
448
+ }
449
+ function swiftCompilerInstallSteps(release) {
450
+ const { note, commands } = swiftCompilerInstall(release);
451
+ return [
452
+ `install the pinned compiler${note}:`,
453
+ ...commands.map((line) => ` ${line}`)
454
+ ].join("\n");
455
+ }
456
+ function swiftCompilerInstall(release) {
457
+ if (release.includes("-custom-")) {
458
+ const archive = swiftHostCompilerArchive(release);
459
+ const directory = import_node_path.default.resolve(swiftToolchainBin(release), "../..");
460
+ return {
461
+ note: "",
462
+ commands: [
463
+ `curl -fsSL ${archive.url} -o compiler.tar.gz`,
464
+ `echo '${archive.checksum} compiler.tar.gz' | shasum -a 256 -c -`,
465
+ `mkdir -p '${directory}'`,
466
+ `tar -xzf compiler.tar.gz --strip-components=1 -C '${directory}'`
467
+ ]
468
+ };
469
+ }
93
470
  const version = release.replace(/^swift-/, "").toLowerCase();
94
471
  const downloads = `https://download.swift.org/swift-${version}`;
95
- const sdk = `swift sdk install ${wasmSdk.wasmSdkUrl} --checksum ${wasmSdk.wasmSdkChecksum}`;
96
472
  if (process.platform === "darwin") {
97
- const swift = `~/Library/Developer/Toolchains/${release}.xctoolchain/usr/bin/swift`;
98
- return [
99
- "install it:",
100
- ` curl -fsSLO ${downloads}/xcode/${release}/${release}-osx.pkg`,
101
- ` installer -pkg ${release}-osx.pkg -target CurrentUserHomeDirectory`,
102
- ` ${swift} ${sdk.replace(/^swift /, "")}`
103
- ].join("\n");
473
+ return {
474
+ note: "",
475
+ commands: [
476
+ `curl -fsSLO ${downloads}/xcode/${release}/${release}-osx.pkg`,
477
+ `installer -pkg ${release}-osx.pkg -target CurrentUserHomeDirectory`
478
+ ]
479
+ };
104
480
  }
105
481
  const platform = `debian12${process.arch === "arm64" ? "-aarch64" : ""}`;
106
482
  const name = `${release}-${platform}`;
107
- return [
108
- "install it (Debian 12 shown; other distributions: https://www.swift.org/install/linux/):",
109
- ` curl -fsSL ${downloads}/${platform}/${release}/${name}.tar.gz | tar -xz -C /opt`,
110
- ` export PATH=/opt/${name}/usr/bin:$PATH`,
111
- ` ${sdk}`
112
- ].join("\n");
483
+ return {
484
+ note: " (Debian 12 shown; other distributions: https://www.swift.org/install/linux/)",
485
+ commands: [
486
+ `curl -fsSL ${downloads}/${platform}/${release}/${name}.tar.gz | tar -xz -C /opt`,
487
+ `export PATH=/opt/${name}/usr/bin:$PATH`
488
+ ]
489
+ };
113
490
  }
114
491
  // Annotate the CommonJS export names for ESM import in node:
115
492
  0 && (module.exports = {
493
+ SWIFT_HOST_COMPILER_ID,
494
+ SWIFT_HOST_COMPILER_RELEASE,
495
+ confineSwiftScratch,
496
+ installSwiftWasmSdk,
497
+ swiftCompiler,
498
+ swiftCompilerInstallSteps,
116
499
  swiftCompilerRelease,
500
+ swiftEnvironment,
501
+ swiftFileChecksum,
502
+ swiftHostCompilerArchive,
117
503
  swiftInstallSteps,
504
+ swiftSdkInstallStep,
505
+ swiftSdkOptions,
118
506
  swiftToolchain,
119
- swiftToolchainBin
507
+ swiftToolchainBin,
508
+ swiftUpstreamRelease,
509
+ verifySwiftHostCompiler
120
510
  });
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;