peachsim 0.1.577 → 0.1.579

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 (178) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +11 -9
  3. package/cli/app-catalog.ts +77 -0
  4. package/cli/app-fonts.ts +4 -20
  5. package/cli/app-splash.ts +2 -18
  6. package/cli/bridge-flow-runner.ts +505 -139
  7. package/cli/cloud-client.ts +1 -4
  8. package/cli/cloud-session.ts +1 -4
  9. package/cli/cloud-test-result-files.ts +3 -0
  10. package/cli/cloud-test-tunnel.ts +2 -5
  11. package/cli/command-registry.ts +2 -0
  12. package/cli/commands/agent.ts +149 -23
  13. package/cli/commands/assert.ts +1 -4
  14. package/cli/commands/box/peach-command.ts +62 -0
  15. package/cli/commands/box/plane-share.ts +0 -70
  16. package/cli/commands/box/rnx-command.ts +1 -60
  17. package/cli/commands/box/search-command.ts +14 -0
  18. package/cli/commands/box.ts +2 -2
  19. package/cli/commands/control.ts +121 -27
  20. package/cli/commands/cpu-profile.ts +23 -10
  21. package/cli/commands/daemon.ts +1 -9
  22. package/cli/commands/detox.ts +26 -18
  23. package/cli/commands/device.ts +129 -1
  24. package/cli/commands/film.ts +25 -16
  25. package/cli/commands/flow.ts +9 -2
  26. package/cli/commands/inspect/actions.ts +75 -1
  27. package/cli/commands/inspect/core.ts +81 -2
  28. package/cli/commands/inspect/describe.ts +2 -6
  29. package/cli/commands/inspect/env.ts +1 -1
  30. package/cli/commands/inspect/settling.ts +20 -3
  31. package/cli/commands/inspect/shared.ts +1 -4
  32. package/cli/commands/inspect/sleep.ts +1 -1
  33. package/cli/commands/inspect.ts +16 -49
  34. package/cli/commands/install-desktop.ts +8 -6
  35. package/cli/commands/login.ts +3 -5
  36. package/cli/commands/maestro-generate.ts +1 -4
  37. package/cli/commands/maestro.ts +38 -21
  38. package/cli/commands/no-bridge-hint.ts +0 -14
  39. package/cli/commands/permissions.ts +2 -2
  40. package/cli/commands/platform.ts +13 -6
  41. package/cli/commands/screenshot.ts +6 -1
  42. package/cli/commands/skills.ts +1 -1
  43. package/cli/commands/test.ts +6 -2
  44. package/cli/commands/three-mode.ts +162 -19
  45. package/cli/commands/upload.ts +3 -18
  46. package/cli/current-sim.ts +0 -1
  47. package/cli/desktop-companion.ts +40 -8
  48. package/cli/drivers/playwright-provisioning.ts +1 -4
  49. package/cli/flow-export.ts +1 -8
  50. package/cli/flow-session.ts +0 -4
  51. package/cli/hints.ts +1 -16
  52. package/cli/inspect-notice-state.ts +0 -4
  53. package/cli/main.ts +2 -4
  54. package/cli/outbound-endpoints.ts +1 -24
  55. package/cli/parse-args.ts +1 -2
  56. package/cli/rnx-in-process.ts +3 -1
  57. package/cli/run-rnx-core.ts +4 -2
  58. package/cli/run-rnx.ts +18 -10
  59. package/cli/send-to-box.ts +1 -4
  60. package/cli/telemetry.ts +1 -1
  61. package/cli/ws-bridge.ts +1 -5
  62. package/detox/gestures.ts +20 -6
  63. package/detox/index.ts +379 -123
  64. package/detox/navigation-lifecycle.ts +22 -13
  65. package/dist-lib/agent-daemon-client.cjs +21 -15
  66. package/dist-lib/agent-events.cjs +1 -1
  67. package/dist-lib/agent-identity.cjs +3 -17
  68. package/dist-lib/agent-sessions.cjs +5 -4
  69. package/dist-lib/attached-projects.cjs +1 -77
  70. package/dist-lib/auth/shared-session.cjs +1 -1
  71. package/dist-lib/backend-origin.cjs +11 -1
  72. package/dist-lib/beta.cjs +1 -1
  73. package/dist-lib/beta.mjs +1 -1
  74. package/dist-lib/bridge-constants.cjs +1 -1
  75. package/dist-lib/bridge-contract-input.cjs +7 -5
  76. package/dist-lib/bridge-contract-input.mjs +7 -5
  77. package/dist-lib/bridge-contract.cjs +1 -1
  78. package/dist-lib/bridge-contract.mjs +1 -1
  79. package/dist-lib/capture-contract.cjs +30 -7
  80. package/dist-lib/capture-contract.mjs +30 -7
  81. package/dist-lib/cli-constants.cjs +1 -1
  82. package/dist-lib/cloud-contract.cjs +1 -1
  83. package/dist-lib/cloud-contract.mjs +1 -1
  84. package/dist-lib/cloud-test-args.cjs +1 -1
  85. package/dist-lib/cloud-test-args.mjs +1 -1
  86. package/dist-lib/cloud.cjs +17 -11
  87. package/dist-lib/cloud.mjs +17 -11
  88. package/dist-lib/config.cjs +1 -1
  89. package/dist-lib/detox/index.cjs +321 -122
  90. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  91. package/dist-lib/home-paths.cjs +1 -1
  92. package/dist-lib/host/bridge-host.cjs +427 -212
  93. package/dist-lib/host/fetch-proxy-handler.cjs +5 -28
  94. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  95. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  96. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  97. package/dist-lib/host/websocket-proxy.cjs +1 -1
  98. package/dist-lib/index.cjs +315 -58
  99. package/dist-lib/jump-to-source-babel.cjs +1 -1
  100. package/dist-lib/jump-to-source-native.cjs +1 -1
  101. package/dist-lib/menu.cjs +67 -31
  102. package/dist-lib/menu.mjs +64 -28
  103. package/dist-lib/metro-fingerprint-registry.cjs +8 -4
  104. package/dist-lib/metro-fingerprint-registry.mjs +6 -4
  105. package/dist-lib/metro-production-bundle.cjs +2 -2
  106. package/dist-lib/metro-production-bundle.mjs +2 -2
  107. package/dist-lib/metro.cjs +8 -4
  108. package/dist-lib/profiles.cjs +1 -1
  109. package/dist-lib/public-brand.cjs +7 -4
  110. package/dist-lib/react-native-host-modules.cjs +1 -1
  111. package/dist-lib/react-native-host-modules.mjs +1 -1
  112. package/dist-lib/render-mode.cjs +3 -13
  113. package/dist-lib/scripts/dev-server-scanner.cjs +5 -17
  114. package/dist-lib/sdk.cjs +129 -10
  115. package/dist-lib/sdk.mjs +127 -10
  116. package/dist-lib/skills.cjs +1635 -1121
  117. package/dist-lib/swift-compile.cjs +277 -70
  118. package/dist-lib/swift-compile.mjs +275 -70
  119. package/dist-lib/swift-package.cjs +17 -5
  120. package/dist-lib/swift-package.mjs +15 -4
  121. package/dist-lib/swift-submit.cjs +32 -8
  122. package/dist-lib/swift-submit.mjs +29 -7
  123. package/dist-lib/swift.cjs +30912 -577
  124. package/dist-lib/vite-kotlin.cjs +356 -0
  125. package/dist-lib/vite-swift.cjs +1743 -0
  126. package/dist-lib/vite.cjs +208 -1039
  127. package/kotlin/README.md +18 -0
  128. package/kotlin/Sources/androidx/annotation/Keep.kt +4 -0
  129. package/kotlin/Sources/dev/onejs/one/OneNativeSourceDispatch.kt +7 -0
  130. package/kotlin/Sources/dev/onejs/one/source/OneModule.kt +4 -0
  131. package/kotlin/Sources/org/json/JSON.kt +244 -0
  132. package/kotlin/toolchain.json +19 -0
  133. package/package.json +14 -2
  134. package/scripts/dev-server-scanner.ts +0 -18
  135. package/scripts/optional-demo-registry.ts +0 -17
  136. package/skills/contrast/SKILL.md +2 -2
  137. package/skills/peach-setup/SKILL.md +16 -0
  138. package/src/agent-daemon-client.ts +36 -22
  139. package/src/agent-identity.ts +0 -15
  140. package/src/agent-prompt.ts +12 -0
  141. package/src/attached-projects.ts +0 -72
  142. package/src/backend-origin.ts +10 -0
  143. package/src/bridge-contract-input.ts +2 -5
  144. package/src/bridge-contract.ts +2 -0
  145. package/src/capture-contract.ts +53 -11
  146. package/src/cloud.ts +4 -9
  147. package/src/dev-server-open.ts +0 -99
  148. package/src/home-paths.ts +2 -3
  149. package/src/host/agent-host.ts +82 -36
  150. package/src/host/bridge-host.ts +5 -11
  151. package/src/host/fetch-proxy-handler.ts +19 -43
  152. package/src/is-record.ts +4 -0
  153. package/src/menu.ts +82 -37
  154. package/src/metro-fingerprint-registry.ts +1 -4
  155. package/src/metro-production-bundle.ts +1 -1
  156. package/src/plist.ts +1 -4
  157. package/src/public-brand.ts +5 -3
  158. package/src/render-mode.ts +0 -12
  159. package/src/runtime-assets.ts +9 -2
  160. package/src/screenshots/compose.ts +7 -1
  161. package/src/screenshots/frame-compose.ts +21 -10
  162. package/src/screenshots/schema.ts +1 -4
  163. package/src/sim-client.ts +2 -4
  164. package/src/skills/builtin/maestro-test.ts +1 -4
  165. package/src/sleep.ts +4 -0
  166. package/src/swift-compile.ts +209 -47
  167. package/src/swift-icu.ts +140 -0
  168. package/src/swift-package.ts +26 -2
  169. package/src/swift-submit.ts +84 -4
  170. package/src/swift.ts +2 -0
  171. package/src/vite-plugin-kotlin.ts +376 -0
  172. package/src/vite-plugin-one.ts +224 -36
  173. package/src/vite-plugin-swift.ts +382 -96
  174. package/src/vite-plugin.ts +121 -134
  175. package/src/vite.d.ts +10 -0
  176. package/cli/resolve-assets.ts +0 -63
  177. package/src/rolldown-plugin-swift.ts +0 -244
  178. package/src/team-machine-prompt.ts +0 -73
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.577 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.579 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -38,15 +38,115 @@ __export(swift_compile_exports, {
38
38
  compileTargets: () => compileTargets,
39
39
  emitSwiftPackageManifest: () => emitSwiftPackageManifest,
40
40
  swiftArtifactHash: () => swiftArtifactHash,
41
+ swiftIcuAsset: () => swiftIcuAsset,
41
42
  swiftModuleInputFiles: () => swiftModuleInputFiles,
43
+ withNativeSourceGlue: () => withNativeSourceGlue,
42
44
  writeSwiftProject: () => writeSwiftProject
43
45
  });
44
46
  module.exports = __toCommonJS(swift_compile_exports);
47
+ var import_node_child_process2 = require("node:child_process");
48
+ var import_node_crypto2 = require("node:crypto");
49
+ var import_node_fs2 = require("node:fs");
50
+ var import_node_os = __toESM(require("node:os"), 1);
51
+ var import_node_path2 = __toESM(require("node:path"), 1);
52
+ var import_node_util2 = require("node:util");
53
+
54
+ // src/swift-icu.ts
45
55
  var import_node_child_process = require("node:child_process");
46
56
  var import_node_crypto = require("node:crypto");
47
57
  var import_node_fs = require("node:fs");
48
58
  var import_node_path = __toESM(require("node:path"), 1);
49
59
  var import_node_util = require("node:util");
60
+ var import_node_zlib = require("node:zlib");
61
+ var run = (0, import_node_util.promisify)(import_node_child_process.execFile);
62
+ var deflate = (0, import_node_util.promisify)(import_node_zlib.gzip);
63
+ var ARCHIVE = "wasi/lib_FoundationICU.a";
64
+ var MEMBER = "icu_packaged_data.cpp.obj";
65
+ var raw = /* @__PURE__ */ new Map();
66
+ var assets = /* @__PURE__ */ new Map();
67
+ function memo(cache, key, load2) {
68
+ let pending = cache.get(key);
69
+ if (!pending) {
70
+ pending = load2();
71
+ pending.catch(() => cache.delete(key));
72
+ cache.set(key, pending);
73
+ }
74
+ return pending;
75
+ }
76
+ function swiftIcuData(toolchainBin, release) {
77
+ return memo(raw, `${toolchainBin}\0${release}`, () => load(toolchainBin, release));
78
+ }
79
+ function swiftIcuAsset(toolchainBin, release) {
80
+ return memo(assets, `${toolchainBin}\0${release}`, async () => {
81
+ const zipped = await deflate(await swiftIcuData(toolchainBin, release));
82
+ return { sha256: (0, import_node_crypto.createHash)("sha256").update(zipped).digest("hex"), gzip: zipped };
83
+ });
84
+ }
85
+ async function load(toolchainBin, release) {
86
+ const { stdout } = await run(import_node_path.default.join(toolchainBin, "swift"), [
87
+ "sdk",
88
+ "configure",
89
+ "--show-configuration",
90
+ `${release}_wasm`,
91
+ "wasm32-unknown-wasip1"
92
+ ]);
93
+ const resources = /^swiftStaticResourcesPath: (.+)$/m.exec(stdout)?.[1]?.trim();
94
+ if (!resources) throw new Error(`swift-icu: ${release}_wasm names no static resources`);
95
+ return Buffer.from(
96
+ icuSegment(archiveMember((0, import_node_fs.readFileSync)(import_node_path.default.join(resources, ARCHIVE)), MEMBER))
97
+ );
98
+ }
99
+ function archiveMember(archive, name) {
100
+ if (archive.toString("latin1", 0, 8) !== "!<arch>\n")
101
+ throw new Error("swift-icu: not an ar archive");
102
+ let names = "";
103
+ for (let at = 8; at + 60 <= archive.length; ) {
104
+ const raw2 = archive.toString("latin1", at, at + 16).trimEnd();
105
+ const size = Number(archive.toString("latin1", at + 48, at + 58).trim());
106
+ const body = archive.subarray(at + 60, at + 60 + size);
107
+ if (raw2 === "//") names = body.toString("latin1");
108
+ const member = /^\/\d+$/.test(raw2) ? names.slice(Number(raw2.slice(1)), names.indexOf("/\n", Number(raw2.slice(1)))) : raw2.replace(/\/$/, "");
109
+ if (member === name) return body;
110
+ at += 60 + size + size % 2;
111
+ }
112
+ throw new Error(`swift-icu: ${name} is not in the sdk's icu archive`);
113
+ }
114
+ function icuSegment(object) {
115
+ let at = 8;
116
+ const leb = () => {
117
+ let result = 0;
118
+ let shift = 0;
119
+ let byte;
120
+ do {
121
+ byte = object[at++];
122
+ result += (byte & 127) * 2 ** shift;
123
+ shift += 7;
124
+ } while (byte & 128);
125
+ return result;
126
+ };
127
+ const found = [];
128
+ while (at < object.length) {
129
+ const id = object[at++];
130
+ const size = leb();
131
+ const end = at + size;
132
+ if (id === 11) {
133
+ for (let count = leb(); count > 0; count--) {
134
+ if (leb() !== 0) throw new Error("swift-icu: unexpected data segment kind");
135
+ at++;
136
+ leb();
137
+ at++;
138
+ const length = leb();
139
+ const bytes = object.subarray(at, at + length);
140
+ if (bytes[2] === 218 && bytes[3] === 39) found.push(bytes);
141
+ at += length;
142
+ }
143
+ }
144
+ at = end;
145
+ }
146
+ if (found.length !== 1)
147
+ throw new Error(`swift-icu: expected one icu data segment, found ${found.length}`);
148
+ return found[0];
149
+ }
50
150
 
51
151
  // src/swift-package.ts
52
152
  function swiftManifestTargets(manifest) {
@@ -57,7 +157,8 @@ function swiftManifestTargets(manifest) {
57
157
  while ((match = pattern.exec(code)) !== null) {
58
158
  const executable = match[1] === "executableTarget";
59
159
  let depth = 1;
60
- let i = pattern.lastIndex;
160
+ const start = pattern.lastIndex;
161
+ let i = start;
61
162
  let inString = false;
62
163
  let escaped = false;
63
164
  let flat = "";
@@ -86,26 +187,67 @@ function swiftManifestTargets(manifest) {
86
187
  if (!name) continue;
87
188
  const rawPath = /\bpath\s*:\s*"([^"]*)"/.exec(flat)?.[1];
88
189
  const targetPath = rawPath == null || rawPath === "" ? `Sources/${name}` : rawPath.replace(/^\.\//, "").replace(/\/+$/, "");
89
- targets.push({ name, path: targetPath, executable });
190
+ const call = code.slice(start, i);
191
+ const languageMode = Number(
192
+ /\.swiftLanguageMode\(\s*\.v(\d+)\s*\)/.exec(call)?.[1] ?? "5"
193
+ );
194
+ const mainActorIsolation = /\.defaultIsolation\(\s*MainActor\.self\s*\)/.test(call);
195
+ targets.push({ name, path: targetPath, executable, languageMode, mainActorIsolation });
90
196
  }
91
197
  return targets;
92
198
  }
199
+ function swiftPackagePartition(manifest) {
200
+ const targets = swiftManifestTargets(manifest);
201
+ return targets.length === 1 && targets[0].executable && targets[0].path === "." ? [] : targets;
202
+ }
93
203
 
94
204
  // src/swift-compile.ts
95
- var run = (0, import_node_util.promisify)(import_node_child_process.execFile);
205
+ var run2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
96
206
  var WASM_TRIPLE = "wasm32-unknown-wasip1";
207
+ var cores = import_node_os.default.availableParallelism();
208
+ var BUILD_ENV = { ...process.env, BINARYEN_CORES: String(Math.min(4, cores)) };
209
+ var BUILD_JOBS = String(Math.max(1, Math.floor(cores / 2)));
97
210
  function swiftModuleInputFiles(root) {
98
- const files = ["Package.swift", "scripts/contrast-app-Package.swift"];
211
+ const files = [
212
+ "Package.swift",
213
+ "scripts/contrast-app-Package.swift",
214
+ "toolchain.json"
215
+ ];
99
216
  const walk = (dir) => {
100
- for (const entry of (0, import_node_fs.readdirSync)(import_node_path.default.join(root, dir), { withFileTypes: true })) {
217
+ for (const entry of (0, import_node_fs2.readdirSync)(import_node_path2.default.join(root, dir), { withFileTypes: true })) {
101
218
  const relative = `${dir}/${entry.name}`;
102
219
  if (entry.isDirectory()) walk(relative);
103
- else if (entry.name.endsWith(".swift")) files.push(relative);
220
+ else if (/\.(swift|c|h)$/.test(entry.name)) files.push(relative);
104
221
  }
105
222
  };
106
223
  walk("Sources");
107
224
  return files.sort();
108
225
  }
226
+ async function ensureMacroPlugins(moduleRoot, toolchainBin) {
227
+ const dir = import_node_path2.default.join(moduleRoot, ".build/host/RnxPreviewMacros");
228
+ const ext = process.platform === "darwin" ? "dylib" : "so";
229
+ const plugins = [
230
+ {
231
+ library: import_node_path2.default.join(dir, `libRnxPreviewMacros.${ext}`),
232
+ source: import_node_path2.default.join(moduleRoot, "Sources/RnxPreviewMacros/PreviewMacro.swift")
233
+ },
234
+ {
235
+ library: import_node_path2.default.join(dir, `libFoundationMacros.${ext}`),
236
+ source: import_node_path2.default.join(moduleRoot, "Sources/FoundationMacros/PredicateMacro.swift")
237
+ }
238
+ ];
239
+ const stale = plugins.some(
240
+ ({ library, source }) => !(0, import_node_fs2.existsSync)(library) || (0, import_node_fs2.statSync)(source).mtimeMs > (0, import_node_fs2.statSync)(library).mtimeMs
241
+ );
242
+ if (stale) {
243
+ await run2("sh", [
244
+ import_node_path2.default.join(moduleRoot, "scripts/build-preview-plugin.sh"),
245
+ toolchainBin,
246
+ plugins[0].library
247
+ ]);
248
+ }
249
+ return plugins.map(({ library }) => library);
250
+ }
109
251
  var linkedModuleDigests = /* @__PURE__ */ new Map();
110
252
  function clearLinkedModuleDigests(root) {
111
253
  if (root === void 0) linkedModuleDigests.clear();
@@ -113,9 +255,9 @@ function clearLinkedModuleDigests(root) {
113
255
  }
114
256
  function linkedModuleDigest(root) {
115
257
  const files = swiftModuleInputFiles(root);
116
- const stampHash = (0, import_node_crypto.createHash)("sha256");
258
+ const stampHash = (0, import_node_crypto2.createHash)("sha256");
117
259
  for (const file of files) {
118
- const stat = (0, import_node_fs.statSync)(import_node_path.default.join(root, file), { bigint: true });
260
+ const stat = (0, import_node_fs2.statSync)(import_node_path2.default.join(root, file), { bigint: true });
119
261
  stampHash.update(file);
120
262
  stampHash.update(
121
263
  `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}
@@ -125,11 +267,11 @@ function linkedModuleDigest(root) {
125
267
  const stamp = stampHash.digest("hex");
126
268
  const cached = linkedModuleDigests.get(root);
127
269
  if (cached?.stamp === stamp) return cached.digest;
128
- const hash = (0, import_node_crypto.createHash)("sha256");
270
+ const hash = (0, import_node_crypto2.createHash)("sha256");
129
271
  for (const file of files) {
130
- hash.update((0, import_node_crypto.createHash)("sha256").update(file).digest());
272
+ hash.update((0, import_node_crypto2.createHash)("sha256").update(file).digest());
131
273
  hash.update(
132
- (0, import_node_crypto.createHash)("sha256").update((0, import_node_fs.readFileSync)(import_node_path.default.join(root, file))).digest()
274
+ (0, import_node_crypto2.createHash)("sha256").update((0, import_node_fs2.readFileSync)(import_node_path2.default.join(root, file))).digest()
133
275
  );
134
276
  }
135
277
  const digest = hash.digest();
@@ -138,7 +280,22 @@ function linkedModuleDigest(root) {
138
280
  }
139
281
  function compileTargets(input) {
140
282
  const manifest = input.files["Package.swift"];
141
- return manifest === void 0 ? [] : swiftManifestTargets(manifest);
283
+ return manifest === void 0 ? [] : swiftPackagePartition(manifest);
284
+ }
285
+ function withNativeSourceGlue(input, glue) {
286
+ const targets = compileTargets(input);
287
+ if (targets.length > 1) {
288
+ throw new Error("swift native modules need one SwiftPM target");
289
+ }
290
+ const targetPath = targets[0]?.path === "." ? "" : targets[0]?.path ?? "";
291
+ return {
292
+ ...input,
293
+ files: {
294
+ ...input.files,
295
+ [import_node_path2.default.posix.join(targetPath, "OneNativeSource.generated.swift")]: glue
296
+ },
297
+ oneModule: true
298
+ };
142
299
  }
143
300
  function swiftSiblingDependencies(files, targets) {
144
301
  const names = new Set(targets.map((target) => target.name));
@@ -148,7 +305,9 @@ function swiftSiblingDependencies(files, targets) {
148
305
  const deps = /* @__PURE__ */ new Set();
149
306
  for (const [file, contents] of Object.entries(files)) {
150
307
  if (file === "Package.swift" || !file.startsWith(prefix)) continue;
151
- for (const match of contents.matchAll(/^\s*import\s+([A-Za-z_][A-Za-z0-9_]*)/gm)) {
308
+ for (const match of contents.matchAll(
309
+ /^\s*(?:@\w+(?:\([^)]*\))?\s+)*import\s+(?:(?:typealias|struct|class|enum|protocol|let|var|func)\s+)?([A-Za-z_][A-Za-z0-9_]*)/gm
310
+ )) {
152
311
  if (names.has(match[1]) && match[1] !== target.name) deps.add(match[1]);
153
312
  }
154
313
  }
@@ -156,29 +315,32 @@ function swiftSiblingDependencies(files, targets) {
156
315
  }
157
316
  return siblings;
158
317
  }
159
- var MULTI_MANIFEST_VERSION = 1;
318
+ var ONE_PRODUCT = '.product(name: "One", package: "sootsim-swift")';
319
+ var ONE_IMPLICIT_FLAGS = ', "-Xfrontend", "-import-module", "-Xfrontend", "One"';
320
+ var MULTI_MANIFEST_VERSION = 5;
160
321
  function swiftArtifactHash(input, release, moduleRoot) {
161
- const hash = (0, import_node_crypto.createHash)("sha256");
322
+ const hash = (0, import_node_crypto2.createHash)("sha256");
162
323
  hash.update(`swift-compile/v1
163
324
  ${release}
164
325
  `);
326
+ if (input.oneModule) hash.update("one-module\n");
165
327
  hash.update(linkedModuleDigest(moduleRoot));
166
328
  for (const file of Object.keys(input.files).sort()) {
167
- hash.update((0, import_node_crypto.createHash)("sha256").update(file).digest());
168
- hash.update((0, import_node_crypto.createHash)("sha256").update(input.files[file]).digest());
329
+ hash.update((0, import_node_crypto2.createHash)("sha256").update(file).digest());
330
+ hash.update((0, import_node_crypto2.createHash)("sha256").update(input.files[file]).digest());
169
331
  }
170
332
  for (const base of Object.keys(input.resources ?? {}).sort()) {
171
- hash.update((0, import_node_crypto.createHash)("sha256").update(base).digest());
333
+ hash.update((0, import_node_crypto2.createHash)("sha256").update(base).digest());
172
334
  hash.update(
173
- (0, import_node_crypto.createHash)("sha256").update(input.resources?.[base] ?? "").digest()
335
+ (0, import_node_crypto2.createHash)("sha256").update(input.resources?.[base] ?? "").digest()
174
336
  );
175
337
  }
176
338
  for (const name of Object.keys(input.images ?? {}).sort()) {
177
339
  const image = input.images?.[name];
178
340
  if (!image) continue;
179
- hash.update((0, import_node_crypto.createHash)("sha256").update(name).digest());
180
- hash.update((0, import_node_crypto.createHash)("sha256").update(image.file).digest());
181
- hash.update((0, import_node_crypto.createHash)("sha256").update(image.data).digest());
341
+ hash.update((0, import_node_crypto2.createHash)("sha256").update(name).digest());
342
+ hash.update((0, import_node_crypto2.createHash)("sha256").update(image.file).digest());
343
+ hash.update((0, import_node_crypto2.createHash)("sha256").update(image.data).digest());
182
344
  }
183
345
  const targets = compileTargets(input);
184
346
  if (targets.length > 0) {
@@ -196,13 +358,15 @@ ${release}
196
358
  return hash.digest("hex");
197
359
  }
198
360
  function emitSwiftPackageManifest(args) {
199
- const { targets, siblings, moduleRoot } = args;
361
+ const { targets, siblings, moduleRoot, oneModule } = args;
200
362
  const executable = targets.find((target) => target.executable);
201
363
  if (!executable) throw new Error("swift-compile: no executable target to emit");
202
- const swiftSettings = 'swiftSettings: [.swiftLanguageMode(.v5), .unsafeFlags(["-Osize"])]';
203
364
  const stanza = (target) => {
365
+ const isolation = target.mainActorIsolation ? " .defaultIsolation(MainActor.self)," : "";
366
+ const swiftSettings = `swiftSettings: [.swiftLanguageMode(.v${target.languageMode}),${isolation} .unsafeFlags(["-Osize"${oneModule ? ONE_IMPLICIT_FLAGS : ""}])]`;
204
367
  const deps = [
205
368
  '.product(name: "SwiftUI", package: "sootsim-swift")',
369
+ ...oneModule ? [ONE_PRODUCT] : [],
206
370
  ...(siblings.get(target.name) ?? []).map((sibling) => `"${sibling}"`)
207
371
  ].join(", ");
208
372
  const kind = target.executable ? ".executableTarget" : ".target";
@@ -224,7 +388,7 @@ function emitSwiftPackageManifest(args) {
224
388
  ].join("\n");
225
389
  };
226
390
  return [
227
- "// swift-tools-version: 6.0",
391
+ "// swift-tools-version: 6.2",
228
392
  "import PackageDescription",
229
393
  "",
230
394
  "// generated by swift-compile from the project package partition.",
@@ -239,42 +403,63 @@ function emitSwiftPackageManifest(args) {
239
403
  ""
240
404
  ].join("\n");
241
405
  }
406
+ function syncSwiftTree(base, files) {
407
+ (0, import_node_fs2.mkdirSync)(base, { recursive: true });
408
+ const walk = (dir) => {
409
+ for (const entry of (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true })) {
410
+ const full = import_node_path2.default.join(dir, entry.name);
411
+ if (dir === base && entry.name === ".build") continue;
412
+ if (entry.isDirectory()) walk(full);
413
+ else if (!files.has(full)) (0, import_node_fs2.rmSync)(full, { force: true });
414
+ }
415
+ };
416
+ walk(base);
417
+ for (const [full, contents] of files) {
418
+ if ((0, import_node_fs2.existsSync)(full) && (0, import_node_fs2.readFileSync)(full, "utf8") === contents) continue;
419
+ (0, import_node_fs2.mkdirSync)(import_node_path2.default.dirname(full), { recursive: true });
420
+ (0, import_node_fs2.writeFileSync)(full, contents, "utf8");
421
+ }
422
+ }
242
423
  function writeSwiftProject(layout, input, moduleRoot) {
243
424
  const targets = compileTargets(input);
425
+ const files = /* @__PURE__ */ new Map();
244
426
  if (targets.length === 0) {
245
- (0, import_node_fs.rmSync)(layout.sources, { recursive: true, force: true });
246
427
  for (const [file, contents] of Object.entries(input.files)) {
247
- const target = import_node_path.default.join(layout.sources, file);
248
- (0, import_node_fs.mkdirSync)(import_node_path.default.dirname(target), { recursive: true });
249
- (0, import_node_fs.writeFileSync)(target, contents, "utf8");
428
+ if (file === "Package.swift") continue;
429
+ files.set(import_node_path2.default.join(layout.sources, file), contents);
250
430
  }
251
- const manifest = (0, import_node_fs.readFileSync)(
252
- import_node_path.default.join(moduleRoot, "scripts/contrast-app-Package.swift"),
431
+ let manifest = (0, import_node_fs2.readFileSync)(
432
+ import_node_path2.default.join(moduleRoot, "scripts/contrast-app-Package.swift"),
253
433
  "utf8"
254
434
  ).replaceAll("__SOOTSIM_SWIFT_PACKAGE__", moduleRoot);
255
- (0, import_node_fs.writeFileSync)(import_node_path.default.join(layout.root, "Package.swift"), manifest, "utf8");
256
- return;
257
- }
258
- (0, import_node_fs.mkdirSync)(layout.root, { recursive: true });
259
- for (const child of (0, import_node_fs.readdirSync)(layout.root)) {
260
- if (child === ".build") continue;
261
- (0, import_node_fs.rmSync)(import_node_path.default.join(layout.root, child), { recursive: true, force: true });
262
- }
263
- for (const [file, contents] of Object.entries(input.files)) {
264
- if (file === "Package.swift") continue;
265
- const target = import_node_path.default.join(layout.root, file);
266
- (0, import_node_fs.mkdirSync)(import_node_path.default.dirname(target), { recursive: true });
267
- (0, import_node_fs.writeFileSync)(target, contents, "utf8");
435
+ if (input.oneModule) {
436
+ const product = '.product(name: "CoreLocation", package: "sootsim-swift"),';
437
+ const flags = '"-Osize"';
438
+ if (!manifest.includes(product) || !manifest.includes(flags)) {
439
+ throw new Error(
440
+ "scripts/contrast-app-Package.swift lost the lines the One module links at"
441
+ );
442
+ }
443
+ manifest = manifest.replace(product, `${product}
444
+ ${ONE_PRODUCT},`).replace(flags, `${flags}${ONE_IMPLICIT_FLAGS}`);
445
+ }
446
+ files.set(import_node_path2.default.join(layout.root, "Package.swift"), manifest);
447
+ } else {
448
+ for (const [file, contents] of Object.entries(input.files)) {
449
+ if (file === "Package.swift") continue;
450
+ files.set(import_node_path2.default.join(layout.root, file), contents);
451
+ }
452
+ files.set(
453
+ import_node_path2.default.join(layout.root, "Package.swift"),
454
+ emitSwiftPackageManifest({
455
+ targets,
456
+ siblings: swiftSiblingDependencies(input.files, targets),
457
+ moduleRoot,
458
+ oneModule: input.oneModule
459
+ })
460
+ );
268
461
  }
269
- (0, import_node_fs.writeFileSync)(
270
- import_node_path.default.join(layout.root, "Package.swift"),
271
- emitSwiftPackageManifest({
272
- targets,
273
- siblings: swiftSiblingDependencies(input.files, targets),
274
- moduleRoot
275
- }),
276
- "utf8"
277
- );
462
+ syncSwiftTree(layout.root, files);
278
463
  }
279
464
  function streamText(value) {
280
465
  if (typeof value === "string") return value.trim();
@@ -292,18 +477,24 @@ function outputOf(error) {
292
477
  return error instanceof Error ? error.message : String(error);
293
478
  }
294
479
  function builtArtifact(layout) {
295
- const binDir = import_node_path.default.join(layout.root, ".build", WASM_TRIPLE, "release");
296
- const artifacts = (0, import_node_fs.existsSync)(binDir) ? (0, import_node_fs.readdirSync)(binDir).filter((name) => name.endsWith(".wasm")).sort() : [];
297
- if (artifacts.length !== 1) {
480
+ const binDir = import_node_path2.default.join(layout.root, ".build", WASM_TRIPLE, "release");
481
+ const manifest = (0, import_node_fs2.readFileSync)(import_node_path2.default.join(layout.root, "Package.swift"), "utf8");
482
+ const executable = swiftManifestTargets(manifest).find((target) => target.executable);
483
+ if (executable === void 0) {
484
+ throw new Error("swift-compile: the written manifest names no executable target");
485
+ }
486
+ const file = import_node_path2.default.join(binDir, `${executable.name}.wasm`);
487
+ if (!(0, import_node_fs2.existsSync)(file)) {
488
+ const found = (0, import_node_fs2.existsSync)(binDir) ? (0, import_node_fs2.readdirSync)(binDir).filter((name) => name.endsWith(".wasm")).sort() : [];
298
489
  throw new Error(
299
- `swift-compile: the build produced ${artifacts.length} wasm artifacts; exactly one executable is the app`
490
+ `swift-compile: the build produced no ${executable.name}.wasm (found: ${found.join(", ") || "none"})`
300
491
  );
301
492
  }
302
- return import_node_path.default.join(binDir, artifacts[0]);
493
+ return file;
303
494
  }
304
495
  function projectDiagnostic(output, layout) {
305
496
  const base = layout.multi ? layout.root : layout.sources;
306
- const prefix = `${base}${import_node_path.default.sep}`;
497
+ const prefix = `${base}${import_node_path2.default.sep}`;
307
498
  return output.split("\n").map((line) => line.startsWith(prefix) ? line.slice(prefix.length) : line).join("\n").trim();
308
499
  }
309
500
  var ROOT_LOCKS = Symbol.for("peachsim.swiftCompile.rootLocks");
@@ -320,28 +511,32 @@ function serialize(root, work) {
320
511
  return next;
321
512
  }
322
513
  function compileSwiftProjectUnit(input, options) {
323
- (0, import_node_fs.mkdirSync)(options.buildRoot, { recursive: true });
324
- const root = (0, import_node_fs.realpathSync)(options.buildRoot);
325
- const moduleRoot = import_node_path.default.resolve(options.moduleRoot);
514
+ (0, import_node_fs2.mkdirSync)(options.buildRoot, { recursive: true });
515
+ const root = (0, import_node_fs2.realpathSync)(options.buildRoot);
516
+ const moduleRoot = import_node_path2.default.resolve(options.moduleRoot);
326
517
  const layout = {
327
518
  root,
328
- sources: import_node_path.default.join(root, "Sources", "App"),
519
+ sources: import_node_path2.default.join(root, "Sources", "App"),
329
520
  multi: compileTargets(input).length > 0
330
521
  };
331
522
  const hash = swiftArtifactHash(input, options.release, moduleRoot);
332
523
  return serialize(root, async () => {
333
524
  writeSwiftProject(layout, input, moduleRoot);
334
- const swift = import_node_path.default.join(options.toolchainBin, "swift");
335
- if (!(0, import_node_fs.existsSync)(swift)) {
525
+ const swift = import_node_path2.default.join(options.toolchainBin, "swift");
526
+ if (!(0, import_node_fs2.existsSync)(swift)) {
336
527
  throw new Error(
337
528
  `swift-compile: no swift.org toolchain at ${options.toolchainBin}; install ${options.release} and its matching wasm sdk`
338
529
  );
339
530
  }
531
+ const macroPlugins = await ensureMacroPlugins(moduleRoot, options.toolchainBin);
532
+ const icu = swiftIcuAsset(options.toolchainBin, options.release);
340
533
  try {
341
- await run(
534
+ await run2(
342
535
  swift,
343
536
  [
344
537
  "build",
538
+ "-j",
539
+ BUILD_JOBS,
345
540
  "--package-path",
346
541
  root,
347
542
  "--swift-sdk",
@@ -349,14 +544,24 @@ function compileSwiftProjectUnit(input, options) {
349
544
  "-c",
350
545
  "release",
351
546
  "-Xswiftc",
352
- "-Osize"
547
+ "-Osize",
548
+ ...macroPlugins.flatMap((plugin) => [
549
+ "-Xswiftc",
550
+ "-load-plugin-library",
551
+ "-Xswiftc",
552
+ plugin
553
+ ])
353
554
  ],
354
- { maxBuffer: 64 * 1024 * 1024, timeout: options.timeoutMs }
555
+ { env: BUILD_ENV, maxBuffer: 64 * 1024 * 1024, timeout: options.timeoutMs }
355
556
  );
356
557
  } catch (error) {
357
558
  throw new Error(projectDiagnostic(outputOf(error), layout), { cause: error });
358
559
  }
359
- return { hash, bytes: (0, import_node_fs.readFileSync)(builtArtifact(layout)) };
560
+ return {
561
+ hash,
562
+ bytes: (0, import_node_fs2.readFileSync)(builtArtifact(layout)),
563
+ icu: await icu
564
+ };
360
565
  });
361
566
  }
362
567
  // Annotate the CommonJS export names for ESM import in node:
@@ -367,6 +572,8 @@ function compileSwiftProjectUnit(input, options) {
367
572
  compileTargets,
368
573
  emitSwiftPackageManifest,
369
574
  swiftArtifactHash,
575
+ swiftIcuAsset,
370
576
  swiftModuleInputFiles,
577
+ withNativeSourceGlue,
371
578
  writeSwiftProject
372
579
  });