peachsim 0.1.638 → 0.1.640

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 (81) hide show
  1. package/cli/command-registry.ts +1 -0
  2. package/cli/commands/control.ts +75 -6
  3. package/cli/commands/swift.ts +326 -0
  4. package/cli/main.ts +11 -0
  5. package/cli/outbound-endpoints.ts +5 -1
  6. package/dist-lib/agent-daemon-client.cjs +1 -1
  7. package/dist-lib/agent-events.cjs +1 -1
  8. package/dist-lib/agent-identity.cjs +1 -1
  9. package/dist-lib/agent-sessions.cjs +1 -1
  10. package/dist-lib/attached-projects.cjs +1 -1
  11. package/dist-lib/auth/shared-session.cjs +1 -1
  12. package/dist-lib/backend-origin.cjs +1 -1
  13. package/dist-lib/beta.cjs +1 -1
  14. package/dist-lib/beta.mjs +1 -1
  15. package/dist-lib/bridge-constants.cjs +1 -1
  16. package/dist-lib/bridge-contract-input.cjs +1 -1
  17. package/dist-lib/bridge-contract-input.mjs +1 -1
  18. package/dist-lib/bridge-contract.cjs +1 -1
  19. package/dist-lib/bridge-contract.mjs +1 -1
  20. package/dist-lib/capture-contract.cjs +1 -1
  21. package/dist-lib/capture-contract.mjs +1 -1
  22. package/dist-lib/cli-constants.cjs +1 -1
  23. package/dist-lib/cloud-contract.cjs +1 -1
  24. package/dist-lib/cloud-contract.mjs +1 -1
  25. package/dist-lib/cloud-test-args.cjs +1 -1
  26. package/dist-lib/cloud-test-args.mjs +1 -1
  27. package/dist-lib/cloud.cjs +1 -1
  28. package/dist-lib/cloud.mjs +1 -1
  29. package/dist-lib/config.cjs +1 -1
  30. package/dist-lib/detox/index.cjs +1 -1
  31. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  32. package/dist-lib/home-paths.cjs +1 -1
  33. package/dist-lib/host/bridge-host.cjs +1 -1
  34. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  35. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  36. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  37. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  38. package/dist-lib/host/websocket-proxy.cjs +1 -1
  39. package/dist-lib/index.cjs +13 -4
  40. package/dist-lib/jump-to-source-babel.cjs +1 -1
  41. package/dist-lib/jump-to-source-native.cjs +1 -1
  42. package/dist-lib/kotlin-host.cjs +1 -1
  43. package/dist-lib/menu.cjs +1 -1
  44. package/dist-lib/menu.mjs +1 -1
  45. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  46. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  47. package/dist-lib/metro-production-bundle.cjs +1 -1
  48. package/dist-lib/metro-production-bundle.mjs +1 -1
  49. package/dist-lib/metro.cjs +1 -1
  50. package/dist-lib/native-app-identity.cjs +1 -1
  51. package/dist-lib/native-app-identity.mjs +1 -1
  52. package/dist-lib/profiles.cjs +1 -1
  53. package/dist-lib/public-brand.cjs +1 -1
  54. package/dist-lib/react-native-host-modules.cjs +1 -1
  55. package/dist-lib/react-native-host-modules.mjs +1 -1
  56. package/dist-lib/render-mode.cjs +1 -1
  57. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  58. package/dist-lib/sdk.cjs +1 -1
  59. package/dist-lib/sdk.mjs +1 -1
  60. package/dist-lib/skills.cjs +389 -232
  61. package/dist-lib/swift-compile.cjs +1 -1
  62. package/dist-lib/swift-compile.mjs +1 -1
  63. package/dist-lib/swift-package.cjs +1 -1
  64. package/dist-lib/swift-package.mjs +1 -1
  65. package/dist-lib/swift-submit.cjs +89 -8
  66. package/dist-lib/swift-submit.mjs +78 -8
  67. package/dist-lib/swift.cjs +16 -33308
  68. package/dist-lib/vite-swift.cjs +422 -247
  69. package/dist-lib/vite.cjs +13 -4
  70. package/package.json +1 -1
  71. package/skills/contrast/SKILL.md +1 -0
  72. package/src/assetCatalogContract.ts +16 -0
  73. package/src/dot-env.ts +148 -0
  74. package/src/metro-runtime-source.ts +15 -0
  75. package/src/swift-guest.ts +51 -0
  76. package/src/swift-host.ts +900 -0
  77. package/src/swift-submit.ts +97 -6
  78. package/src/swift.ts +36 -8
  79. package/src/swiftContract.ts +52 -0
  80. package/src/vite-plugin-one.ts +4 -3
  81. package/src/vite-plugin-swift.ts +43 -755
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.638 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.640 | (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;
@@ -801,8 +801,16 @@ function streamFile(res, stream) {
801
801
  stream.pipe(res);
802
802
  }
803
803
 
804
- // src/vite-plugin-one.ts
804
+ // src/swift-submit.ts
805
+ var SWIFT_PACKAGE_PATH = "/__peach/swift-package/";
805
806
  var SWIFT_HMR_PATH = "/__peach/swift-hmr";
807
+ var MAX_SWIFT_COMPILE_SOURCE_BYTES = 2 * 1024 * 1024;
808
+ var MAX_SWIFT_COMPILE_RESOURCE_BYTES = 2 * 1024 * 1024;
809
+ var MAX_SWIFT_COMPILE_RESOURCE_TOTAL_BYTES = 8 * 1024 * 1024;
810
+ var MAX_SWIFT_COMPILE_IMAGE_BYTES = 4 * 1024 * 1024;
811
+ var MAX_SWIFT_COMPILE_IMAGE_TOTAL_BYTES = 16 * 1024 * 1024;
812
+
813
+ // src/vite-plugin-one.ts
806
814
  var SWIFT_ROUTE_PREFIX = "/__peach/swift";
807
815
  var swiftHost;
808
816
  var loadSwiftHost = () => swiftHost ??= import("peachsim/vite-swift");
@@ -904,7 +912,8 @@ function rnxPlugin(options = {}) {
904
912
  if (!served) next();
905
913
  }).catch(next);
906
914
  });
907
- server.watcher.on("change", (file) => {
915
+ server.watcher.on("all", (event, file) => {
916
+ if (event !== "add" && event !== "unlink" && event !== "change") return;
908
917
  if (activeSwiftPackages.size === 0) return;
909
918
  const moduleRoot = moduleRootFor();
910
919
  let packages;
@@ -952,7 +961,7 @@ function rnxPlugin(options = {}) {
952
961
  if (!pathname.startsWith(SWIFT_ROUTE_PREFIX)) return next();
953
962
  loadSwiftHost().then((host) => {
954
963
  if (host.serveSwiftPackageAsset(pathname, res)) return;
955
- const prefix2 = "/__peach/swift-package/";
964
+ const prefix2 = SWIFT_PACKAGE_PATH;
956
965
  if (!pathname.startsWith(prefix2)) return next();
957
966
  if (!swiftSockets) {
958
967
  res.statusCode = 501;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peachsim",
3
- "version": "0.1.638",
3
+ "version": "0.1.640",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for peach.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -19,6 +19,7 @@ automation, inspecting the render tree, and managing sims.
19
19
 
20
20
  | command | description |
21
21
  | --- | --- |
22
+ | `peach swift` | preview a SwiftPM app with hosted compilation and live Swift edits |
22
23
  | `peach maestro` | author, generate, and run Maestro YAML flows against peach |
23
24
  | `peach detox` | run existing Detox suites against peach on headless Chromium |
24
25
  | `peach cleanup` | inspect and reclaim local peach disk usage |
@@ -0,0 +1,16 @@
1
+ // the asset data exchanged by project hosts and the private renderer.
2
+ export interface SwiftImageSource {
3
+ uri: string
4
+ scale: number
5
+ }
6
+
7
+ // an app catalog color resolves by appearance or names a system color.
8
+ export type AppCatalogColor = { light: string; dark: string } | { system: string }
9
+
10
+ export interface SfSymbolVector {
11
+ viewBox: '0 0 24 24'
12
+ advance: number
13
+ box?: readonly [number, number, number, number]
14
+ controlBoxes?: Record<string, readonly [number, number, number]>
15
+ layers: readonly { d: string; color?: string }[]
16
+ }
package/src/dot-env.ts ADDED
@@ -0,0 +1,148 @@
1
+ // the env file an iOS build compiles into the binary for react-native-config,
2
+ // read the way its build phase reads it (`ios/ReactNativeConfig/ReadDotEnv.rb`
3
+ // and `BuildDotenvConfig.rb`, 1.7.2). `peach open --load-env` hands the result
4
+ // to the tenant, where the RNCConfigModule seam answers `getConfig()` with it.
5
+ //
6
+ // the build picks `/tmp/envfile`, then `ENVFILE` (expanding `$(VAR)`, `${VAR}`
7
+ // and `$VAR` from the environment), then `.env`, and falls back to `.env` when
8
+ // the requested file is missing. each value is written into an Objective-C
9
+ // string literal with only `"` escaped, so the compiler then decodes any
10
+ // backslash escape the value carries; a value that ends the literal early
11
+ // fails the build.
12
+
13
+ import fs from 'node:fs'
14
+ import path from 'node:path'
15
+
16
+ const DEFAULT_ENV_FILE = '.env'
17
+ // ReadDotEnv.rb's dotenv_pattern. Ruby's [[:alnum:]] is Unicode alphabetic or
18
+ // decimal digit, \s is [ \t\n\v\f\r], and `.` matches anything but \n.
19
+ const DOTENV_PATTERN =
20
+ /^(?:export[ \t\n\v\f\r]+|)(?<key>[\p{Alphabetic}\p{Nd}_]+)[ \t\n\v\f\r]*=[ \t\n\v\f\r]*((?<quote>["'])?(?<val>[^\n]*?[^\\\n])\k<quote>?|)$/u
21
+ const BUILD_SETTING_PATTERN =
22
+ /\$[({]([A-Za-z_][A-Za-z0-9_]*)[)}]|\$([A-Za-z_][A-Za-z0-9_]*)/g
23
+ const INVALID_ENTRY =
24
+ 'Invalid entry in .env file. Please verify your .env file is correctly formatted.'
25
+
26
+ export type DotEnvResult = {
27
+ config: Record<string, string>
28
+ // what the build phase prints, for the caller to show
29
+ notices: string[]
30
+ }
31
+
32
+ function selectEnvFile(env: NodeJS.ProcessEnv, notices: string[]) {
33
+ if (fs.existsSync('/tmp/envfile')) {
34
+ return { name: fs.readFileSync('/tmp/envfile', 'utf8').trim(), fromEnvfile: false }
35
+ }
36
+ const requested = env.ENVFILE
37
+ if (!requested) return { name: DEFAULT_ENV_FILE, fromEnvfile: false }
38
+ const unset: string[] = []
39
+ const name = requested.replace(BUILD_SETTING_PATTERN, (_, braced, bare) => {
40
+ const variable: string = braced ?? bare
41
+ const value = env[variable]
42
+ if (!value) unset.push(variable)
43
+ return value ?? ''
44
+ })
45
+ notices.push(`ENVFILE=${requested}`)
46
+ if (name !== requested) notices.push(` expands to ${name}`)
47
+ if (unset.length) {
48
+ notices.push(
49
+ ` note: ${[...new Set(unset)].join(', ')} resolved to nothing. Outside Xcode these build settings are not set - pass the file name directly, or run the build through Xcode.`,
50
+ )
51
+ }
52
+ return { name, fromEnvfile: true }
53
+ }
54
+
55
+ // how clang reads the value inside `@"..."`
56
+ function decodeObjCStringLiteral(source: string): string {
57
+ let out = ''
58
+ for (let i = 0; i < source.length; i++) {
59
+ const char = source[i]
60
+ if (char === '"') throw new Error(`GeneratedDotEnv.m does not compile: ${source}`)
61
+ if (char !== '\\') {
62
+ out += char
63
+ continue
64
+ }
65
+ const next = source[++i]
66
+ if (next === undefined)
67
+ throw new Error(`GeneratedDotEnv.m does not compile: ${source}`)
68
+ const simple: Record<string, string> = {
69
+ n: '\n',
70
+ t: '\t',
71
+ r: '\r',
72
+ a: '\x07',
73
+ b: '\b',
74
+ f: '\f',
75
+ v: '\v',
76
+ e: '\x1b',
77
+ }
78
+ if (next in simple) out += simple[next]
79
+ else if (/[0-7]/.test(next)) {
80
+ const digits = /^[0-7]{1,3}/.exec(source.slice(i))![0]
81
+ out += String.fromCodePoint(Number.parseInt(digits, 8))
82
+ i += digits.length - 1
83
+ } else if (next === 'x' || next === 'u' || next === 'U') {
84
+ const digits =
85
+ next === 'x'
86
+ ? (/^[0-9a-fA-F]+/.exec(source.slice(i + 1))?.[0] ?? '')
87
+ : source.slice(i + 1, i + 1 + (next === 'u' ? 4 : 8))
88
+ const code = Number.parseInt(digits, 16)
89
+ if (!/^[0-9a-fA-F]+$/.test(digits) || code > (next === 'x' ? 0xff : 0x10ffff)) {
90
+ throw new Error(`GeneratedDotEnv.m does not compile: ${source}`)
91
+ }
92
+ out += String.fromCodePoint(code)
93
+ i += digits.length
94
+ } else out += next
95
+ }
96
+ return out
97
+ }
98
+
99
+ export function readProjectDotEnv(
100
+ envsRoot: string,
101
+ env: NodeJS.ProcessEnv = process.env,
102
+ ): DotEnvResult {
103
+ const notices: string[] = []
104
+ const selection = selectEnvFile(env, notices)
105
+ // File.expand_path(File.join(root, name)) joins even an absolute name onto root
106
+ const requestedPaths = [
107
+ path.resolve(path.join(envsRoot, selection.name)),
108
+ path.resolve(selection.name),
109
+ ]
110
+ const candidates = [
111
+ ...requestedPaths,
112
+ path.resolve(path.join(envsRoot, DEFAULT_ENV_FILE)),
113
+ ]
114
+ if (!fs.existsSync(candidates[2])) candidates.push(path.resolve(DEFAULT_ENV_FILE))
115
+ const tried = [...new Set(candidates)]
116
+ const resolved = tried.find((candidate) => fs.existsSync(candidate))
117
+ if (!resolved) {
118
+ notices.push(
119
+ '*** Missing .env file ****',
120
+ 'Tried, in order:',
121
+ ...tried.map((candidate) => ` - ${candidate}`),
122
+ 'The build will succeed and Config will be empty at runtime.',
123
+ )
124
+ return { config: {}, notices }
125
+ }
126
+ if (selection.fromEnvfile && !requestedPaths.includes(resolved)) {
127
+ notices.push(
128
+ '*** ENVFILE was set, but that file is missing ',
129
+ `Asked for: ${selection.name}`,
130
+ 'Not found at:',
131
+ ...requestedPaths.map((candidate) => ` - ${candidate}`),
132
+ `Falling back to: ${resolved}`,
133
+ )
134
+ }
135
+ const config: Record<string, string> = {}
136
+ for (const line of fs.readFileSync(resolved, 'utf8').split('\n')) {
137
+ if (!line.trim()) continue
138
+ if (/^[ \t\n\v\f\r]*#/.test(line)) continue
139
+ const match = DOTENV_PATTERN.exec(line)
140
+ if (!match?.groups) throw new Error(INVALID_ENTRY)
141
+ // BuildDotenvConfig.rb writes @"#{v.chomp}" after escaping `"`
142
+ const literal = (match.groups.val ?? '')
143
+ .replaceAll('"', '\\"')
144
+ .replace(/(\r\n|\n|\r)$/, '')
145
+ config[match.groups.key] = decodeObjCStringLiteral(literal)
146
+ }
147
+ return { config, notices }
148
+ }
@@ -0,0 +1,15 @@
1
+ // GENERATED by scripts/generate-runtime-source.ts — do not edit.
2
+ // verbatim metro-runtime@0.84.4 sources, inlined so the worker never touches a filesystem.
3
+
4
+ export const METRO_RUNTIME_VERSION = '0.84.4'
5
+
6
+ // metro-runtime/src/polyfills/require.js — defines global.__d / __r / __c / __accept
7
+ export const METRO_REQUIRE_POLYFILL =
8
+ '"use strict";\n\nglobal.__r = metroRequire;\nglobal[`${__METRO_GLOBAL_PREFIX__}__d`] = define;\nglobal.__c = clear;\nglobal.__registerSegment = registerSegment;\nvar modules = clear();\nconst EMPTY = {};\nconst CYCLE_DETECTED = {};\nconst { hasOwnProperty } = {};\nif (__DEV__) {\n global.$RefreshReg$ = global.$RefreshReg$ ?? (() => {});\n global.$RefreshSig$ = global.$RefreshSig$ ?? (() => (type) => type);\n}\nfunction clear() {\n modules = new Map();\n return modules;\n}\nif (__DEV__) {\n var verboseNamesToModuleIds = new Map();\n var getModuleIdForVerboseName = (verboseName) => {\n const moduleId = verboseNamesToModuleIds.get(verboseName);\n if (moduleId == null) {\n throw new Error(`Unknown named module: "${verboseName}"`);\n }\n return moduleId;\n };\n var initializingModuleIds = [];\n}\nfunction define(factory, moduleId, dependencyMap) {\n if (modules.has(moduleId)) {\n if (__DEV__) {\n const inverseDependencies = arguments[4];\n if (inverseDependencies) {\n global.__accept(moduleId, factory, dependencyMap, inverseDependencies);\n }\n }\n return;\n }\n const mod = {\n dependencyMap,\n factory,\n hasError: false,\n importedAll: EMPTY,\n importedDefault: EMPTY,\n isInitialized: false,\n publicModule: {\n exports: {},\n },\n };\n modules.set(moduleId, mod);\n if (__DEV__) {\n mod.hot = createHotReloadingObject();\n const verboseName = arguments[3];\n if (verboseName) {\n mod.verboseName = verboseName;\n verboseNamesToModuleIds.set(verboseName, moduleId);\n }\n }\n}\nfunction metroRequire(moduleId, maybeNameForDev) {\n if (moduleId === null) {\n if (__DEV__ && typeof maybeNameForDev === "string") {\n throw new Error("Cannot find module \'" + maybeNameForDev + "\'");\n }\n throw new Error("Cannot find module");\n }\n if (__DEV__ && typeof moduleId === "string") {\n const verboseName = moduleId;\n moduleId = getModuleIdForVerboseName(verboseName);\n console.warn(\n `Requiring module "${verboseName}" by name is only supported for ` +\n "debugging purposes and will BREAK IN PRODUCTION!",\n );\n }\n const moduleIdReallyIsNumber = moduleId;\n if (__DEV__) {\n const initializingIndex = initializingModuleIds.indexOf(\n moduleIdReallyIsNumber,\n );\n if (initializingIndex !== -1) {\n const cycle = initializingModuleIds\n .slice(initializingIndex)\n .map((id) => modules.get(id)?.verboseName ?? "[unknown]");\n if (shouldPrintRequireCycle(cycle)) {\n cycle.push(cycle[0]);\n console.warn(\n `Require cycle: ${cycle.join(" -> ")}\\n\\n` +\n "Require cycles are allowed, but can result in uninitialized values. " +\n "Consider refactoring to remove the need for a cycle.",\n );\n }\n }\n }\n const module = modules.get(moduleIdReallyIsNumber);\n return module && module.isInitialized\n ? module.publicModule.exports\n : guardedLoadModule(moduleIdReallyIsNumber, module);\n}\nfunction shouldPrintRequireCycle(modules) {\n const regExps =\n global[__METRO_GLOBAL_PREFIX__ + "__requireCycleIgnorePatterns"];\n if (!Array.isArray(regExps)) {\n return true;\n }\n const isIgnored = (module) =>\n module != null && regExps.some((regExp) => regExp.test(module));\n return modules.every((module) => !isIgnored(module));\n}\nfunction metroImportDefault(moduleId) {\n if (__DEV__ && typeof moduleId === "string") {\n const verboseName = moduleId;\n moduleId = getModuleIdForVerboseName(verboseName);\n }\n const moduleIdReallyIsNumber = moduleId;\n const maybeInitializedModule = modules.get(moduleIdReallyIsNumber);\n if (\n maybeInitializedModule &&\n maybeInitializedModule.importedDefault !== EMPTY\n ) {\n return maybeInitializedModule.importedDefault;\n }\n const exports = metroRequire(moduleIdReallyIsNumber);\n const importedDefault =\n exports && exports.__esModule ? exports.default : exports;\n const initializedModule = modules.get(moduleIdReallyIsNumber);\n return (initializedModule.importedDefault = importedDefault);\n}\nmetroRequire.importDefault = metroImportDefault;\nfunction metroImportAll(moduleId) {\n if (__DEV__ && typeof moduleId === "string") {\n const verboseName = moduleId;\n moduleId = getModuleIdForVerboseName(verboseName);\n }\n const moduleIdReallyIsNumber = moduleId;\n const maybeInitializedModule = modules.get(moduleIdReallyIsNumber);\n if (maybeInitializedModule && maybeInitializedModule.importedAll !== EMPTY) {\n return maybeInitializedModule.importedAll;\n }\n const exports = metroRequire(moduleIdReallyIsNumber);\n let importedAll;\n if (exports && exports.__esModule) {\n importedAll = exports;\n } else {\n importedAll = {};\n if (exports) {\n for (const key in exports) {\n if (hasOwnProperty.call(exports, key)) {\n importedAll[key] = exports[key];\n }\n }\n }\n importedAll.default = exports;\n }\n const initializedModule = modules.get(moduleIdReallyIsNumber);\n return (initializedModule.importedAll = importedAll);\n}\nmetroRequire.importAll = metroImportAll;\nmetroRequire.context = function fallbackRequireContext() {\n if (__DEV__) {\n throw new Error(\n "The experimental Metro feature `require.context` is not enabled in your project.\\nThis can be enabled by setting the `transformer.unstable_allowRequireContext` property to `true` in your Metro configuration.",\n );\n }\n throw new Error(\n "The experimental Metro feature `require.context` is not enabled in your project.",\n );\n};\nmetroRequire.resolveWeak = function fallbackRequireResolveWeak() {\n if (__DEV__) {\n throw new Error(\n "require.resolveWeak cannot be called dynamically. Ensure you are using the same version of `metro` and `metro-runtime`.",\n );\n }\n throw new Error("require.resolveWeak cannot be called dynamically.");\n};\nlet inGuard = false;\nfunction guardedLoadModule(moduleId, module) {\n if (!inGuard && global.ErrorUtils) {\n inGuard = true;\n let returnValue;\n try {\n returnValue = loadModuleImplementation(moduleId, module);\n } catch (e) {\n global.ErrorUtils.reportFatalError(e);\n }\n inGuard = false;\n return returnValue;\n } else {\n return loadModuleImplementation(moduleId, module);\n }\n}\nconst ID_MASK_SHIFT = 16;\nconst LOCAL_ID_MASK = ~0 >>> ID_MASK_SHIFT;\nfunction unpackModuleId(moduleId) {\n const segmentId = moduleId >>> ID_MASK_SHIFT;\n const localId = moduleId & LOCAL_ID_MASK;\n return {\n segmentId,\n localId,\n };\n}\nmetroRequire.unpackModuleId = unpackModuleId;\nfunction packModuleId(value) {\n return (value.segmentId << ID_MASK_SHIFT) + value.localId;\n}\nmetroRequire.packModuleId = packModuleId;\nconst moduleDefinersBySegmentID = [];\nconst definingSegmentByModuleID = new Map();\nfunction registerSegment(segmentId, moduleDefiner, moduleIds) {\n moduleDefinersBySegmentID[segmentId] = moduleDefiner;\n if (__DEV__) {\n if (segmentId === 0 && moduleIds) {\n throw new Error(\n "registerSegment: Expected moduleIds to be null for main segment",\n );\n }\n if (segmentId !== 0 && !moduleIds) {\n throw new Error(\n "registerSegment: Expected moduleIds to be passed for segment #" +\n segmentId,\n );\n }\n }\n if (moduleIds) {\n moduleIds.forEach((moduleId) => {\n if (!modules.has(moduleId) && !definingSegmentByModuleID.has(moduleId)) {\n definingSegmentByModuleID.set(moduleId, segmentId);\n }\n });\n }\n}\nfunction loadModuleImplementation(moduleId, module) {\n if (!module && moduleDefinersBySegmentID.length > 0) {\n const segmentId = definingSegmentByModuleID.get(moduleId) ?? 0;\n const definer = moduleDefinersBySegmentID[segmentId];\n if (definer != null) {\n definer(moduleId);\n module = modules.get(moduleId);\n definingSegmentByModuleID.delete(moduleId);\n }\n }\n const nativeRequire = global.nativeRequire;\n if (!module && nativeRequire) {\n const { segmentId, localId } = unpackModuleId(moduleId);\n nativeRequire(localId, segmentId);\n module = modules.get(moduleId);\n }\n if (!module) {\n throw unknownModuleError(moduleId);\n }\n if (module.hasError) {\n throw module.error;\n }\n if (__DEV__) {\n var Systrace = requireSystrace();\n var Refresh = requireRefresh();\n }\n module.isInitialized = true;\n const { factory, dependencyMap } = module;\n if (__DEV__) {\n initializingModuleIds.push(moduleId);\n }\n try {\n if (__DEV__) {\n Systrace.beginEvent("JS_require_" + (module.verboseName || moduleId));\n }\n const moduleObject = module.publicModule;\n if (__DEV__) {\n moduleObject.hot = module.hot;\n var prevRefreshReg = global.$RefreshReg$;\n var prevRefreshSig = global.$RefreshSig$;\n if (Refresh != null) {\n const RefreshRuntime = Refresh;\n global.$RefreshReg$ = (type, id) => {\n const prefixedModuleId =\n __METRO_GLOBAL_PREFIX__ + " " + moduleId + " " + id;\n RefreshRuntime.register(type, prefixedModuleId);\n };\n global.$RefreshSig$ =\n RefreshRuntime.createSignatureFunctionForTransform;\n }\n }\n moduleObject.id = moduleId;\n factory(\n global,\n metroRequire,\n metroImportDefault,\n metroImportAll,\n moduleObject,\n moduleObject.exports,\n dependencyMap,\n );\n if (!__DEV__) {\n module.factory = undefined;\n module.dependencyMap = undefined;\n }\n if (__DEV__) {\n Systrace.endEvent();\n if (Refresh != null) {\n const prefixedModuleId = __METRO_GLOBAL_PREFIX__ + " " + moduleId;\n registerExportsForReactRefresh(\n Refresh,\n moduleObject.exports,\n prefixedModuleId,\n );\n }\n }\n return moduleObject.exports;\n } catch (e) {\n module.hasError = true;\n module.error = e;\n module.isInitialized = false;\n module.publicModule.exports = undefined;\n throw e;\n } finally {\n if (__DEV__) {\n if (initializingModuleIds.pop() !== moduleId) {\n throw new Error(\n "initializingModuleIds is corrupt; something is terribly wrong",\n );\n }\n global.$RefreshReg$ = prevRefreshReg;\n global.$RefreshSig$ = prevRefreshSig;\n }\n }\n}\nfunction unknownModuleError(id) {\n let message = \'Requiring unknown module "\' + id + \'".\';\n if (__DEV__) {\n message +=\n " If you are sure the module exists, try restarting Metro. " +\n "You may also want to run `yarn` or `npm install`.";\n }\n return Error(message);\n}\nif (__DEV__) {\n metroRequire.Systrace = {\n beginEvent: () => {},\n endEvent: () => {},\n };\n metroRequire.getModules = () => {\n return modules;\n };\n var createHotReloadingObject = function () {\n const hot = {\n _acceptCallback: null,\n _disposeCallback: null,\n _didAccept: false,\n accept: (callback) => {\n hot._didAccept = true;\n hot._acceptCallback = callback;\n },\n dispose: (callback) => {\n hot._disposeCallback = callback;\n },\n };\n return hot;\n };\n let reactRefreshTimeout = null;\n const metroHotUpdateModule = function (\n id,\n factory,\n dependencyMap,\n inverseDependencies,\n ) {\n const mod = modules.get(id);\n if (!mod) {\n if (factory) {\n return;\n }\n throw unknownModuleError(id);\n }\n const forceFullRefreshPatterns =\n global[__METRO_GLOBAL_PREFIX__ + "__unstable_forceFullRefreshPatterns"];\n if (\n forceFullRefreshPatterns != null &&\n Array.isArray(forceFullRefreshPatterns) &&\n mod.verboseName != null &&\n forceFullRefreshPatterns.some((pattern) =>\n pattern.test(mod.verboseName ?? ""),\n )\n ) {\n performFullRefresh("Module matched unstable_forceFullRefreshPatterns", {\n source: mod,\n });\n return;\n }\n if (!mod.hasError && !mod.isInitialized) {\n mod.factory = factory;\n mod.dependencyMap = dependencyMap;\n return;\n }\n const Refresh = requireRefresh();\n const refreshBoundaryIDs = new Set();\n let didBailOut = false;\n let updatedModuleIDs;\n try {\n updatedModuleIDs = topologicalSort(\n [id],\n (pendingID) => {\n const pendingModule = modules.get(pendingID);\n if (pendingModule == null) {\n return [];\n }\n const pendingHot = pendingModule.hot;\n if (pendingHot == null) {\n throw new Error(\n "[Refresh] Expected module.hot to always exist in DEV.",\n );\n }\n let canAccept = pendingHot._didAccept;\n if (!canAccept && Refresh != null) {\n const isBoundary = isReactRefreshBoundary(\n Refresh,\n pendingModule.publicModule.exports,\n );\n if (isBoundary) {\n canAccept = true;\n refreshBoundaryIDs.add(pendingID);\n }\n }\n if (canAccept) {\n return [];\n }\n const parentIDs = inverseDependencies[pendingID];\n if (parentIDs.length === 0) {\n performFullRefresh("No root boundary", {\n source: mod,\n failed: pendingModule,\n });\n didBailOut = true;\n return [];\n }\n return parentIDs;\n },\n () => didBailOut,\n ).reverse();\n } catch (e) {\n if (e === CYCLE_DETECTED) {\n performFullRefresh("Dependency cycle", {\n source: mod,\n });\n return;\n }\n throw e;\n }\n if (didBailOut) {\n return;\n }\n const seenModuleIDs = new Set();\n for (let i = 0; i < updatedModuleIDs.length; i++) {\n const updatedID = updatedModuleIDs[i];\n if (seenModuleIDs.has(updatedID)) {\n continue;\n }\n seenModuleIDs.add(updatedID);\n const updatedMod = modules.get(updatedID);\n if (updatedMod == null) {\n throw new Error("[Refresh] Expected to find the updated module.");\n }\n const prevExports = updatedMod.publicModule.exports;\n const didError = runUpdatedModule(\n updatedID,\n updatedID === id ? factory : undefined,\n updatedID === id ? dependencyMap : undefined,\n );\n const nextExports = updatedMod.publicModule.exports;\n if (didError) {\n return;\n }\n if (refreshBoundaryIDs.has(updatedID)) {\n const isNoLongerABoundary = !isReactRefreshBoundary(\n Refresh,\n nextExports,\n );\n const didInvalidate = shouldInvalidateReactRefreshBoundary(\n Refresh,\n prevExports,\n nextExports,\n );\n if (isNoLongerABoundary || didInvalidate) {\n const parentIDs = inverseDependencies[updatedID];\n if (parentIDs.length === 0) {\n performFullRefresh(\n isNoLongerABoundary\n ? "No longer a boundary"\n : "Invalidated boundary",\n {\n source: mod,\n failed: updatedMod,\n },\n );\n return;\n }\n for (let j = 0; j < parentIDs.length; j++) {\n const parentID = parentIDs[j];\n const parentMod = modules.get(parentID);\n if (parentMod == null) {\n throw new Error("[Refresh] Expected to find parent module.");\n }\n const canAcceptParent = isReactRefreshBoundary(\n Refresh,\n parentMod.publicModule.exports,\n );\n if (canAcceptParent) {\n refreshBoundaryIDs.add(parentID);\n updatedModuleIDs.push(parentID);\n } else {\n performFullRefresh("Invalidated boundary", {\n source: mod,\n failed: parentMod,\n });\n return;\n }\n }\n }\n }\n }\n if (Refresh != null) {\n if (reactRefreshTimeout == null) {\n reactRefreshTimeout = setTimeout(() => {\n reactRefreshTimeout = null;\n Refresh.performReactRefresh();\n }, 30);\n }\n }\n };\n const topologicalSort = function (roots, getEdges, earlyStop) {\n const result = [];\n const visited = new Set();\n const stack = new Set();\n function traverseDependentNodes(node) {\n if (stack.has(node)) {\n throw CYCLE_DETECTED;\n }\n if (visited.has(node)) {\n return;\n }\n visited.add(node);\n stack.add(node);\n const dependentNodes = getEdges(node);\n if (earlyStop(node)) {\n stack.delete(node);\n return;\n }\n dependentNodes.forEach((dependent) => {\n traverseDependentNodes(dependent);\n });\n stack.delete(node);\n result.push(node);\n }\n roots.forEach((root) => {\n traverseDependentNodes(root);\n });\n return result;\n };\n const runUpdatedModule = function (id, factory, dependencyMap) {\n const mod = modules.get(id);\n if (mod == null) {\n throw new Error("[Refresh] Expected to find the module.");\n }\n const { hot } = mod;\n if (!hot) {\n throw new Error("[Refresh] Expected module.hot to always exist in DEV.");\n }\n if (hot._disposeCallback) {\n try {\n hot._disposeCallback();\n } catch (error) {\n console.error(\n `Error while calling dispose handler for module ${id}: `,\n error,\n );\n }\n }\n if (factory) {\n mod.factory = factory;\n }\n if (dependencyMap) {\n mod.dependencyMap = dependencyMap;\n }\n mod.hasError = false;\n mod.error = undefined;\n mod.importedAll = EMPTY;\n mod.importedDefault = EMPTY;\n mod.isInitialized = false;\n const prevExports = mod.publicModule.exports;\n mod.publicModule.exports = {};\n hot._didAccept = false;\n hot._acceptCallback = null;\n hot._disposeCallback = null;\n metroRequire(id);\n if (mod.hasError) {\n mod.hasError = false;\n mod.isInitialized = true;\n mod.error = null;\n mod.publicModule.exports = prevExports;\n return true;\n }\n if (hot._acceptCallback) {\n try {\n hot._acceptCallback();\n } catch (error) {\n console.error(\n `Error while calling accept handler for module ${id}: `,\n error,\n );\n }\n }\n return false;\n };\n const performFullRefresh = (reason, modules) => {\n if (\n typeof window !== "undefined" &&\n window.location != null &&\n typeof window.location.reload === "function"\n ) {\n window.location.reload();\n } else {\n const Refresh = requireRefresh();\n if (Refresh != null) {\n const sourceName = modules.source?.verboseName ?? "unknown";\n const failedName = modules.failed?.verboseName ?? "unknown";\n Refresh.performFullRefresh(\n `Fast Refresh - ${reason} <${sourceName}> <${failedName}>`,\n );\n } else {\n console.warn("Could not reload the application after an edit.");\n }\n }\n };\n const isExportSafeToAccess = (moduleExports, key) => {\n return (\n moduleExports?.__esModule ||\n Object.getOwnPropertyDescriptor(moduleExports, key)?.get == null\n );\n };\n var isReactRefreshBoundary = function (Refresh, moduleExports) {\n if (Refresh.isLikelyComponentType(moduleExports)) {\n return true;\n }\n if (moduleExports == null || typeof moduleExports !== "object") {\n return false;\n }\n let hasExports = false;\n let areAllExportsComponents = true;\n for (const key in moduleExports) {\n hasExports = true;\n if (key === "__esModule") {\n continue;\n } else if (!isExportSafeToAccess(moduleExports, key)) {\n return false;\n }\n const exportValue = moduleExports[key];\n if (!Refresh.isLikelyComponentType(exportValue)) {\n areAllExportsComponents = false;\n }\n }\n return hasExports && areAllExportsComponents;\n };\n var shouldInvalidateReactRefreshBoundary = (\n Refresh,\n prevExports,\n nextExports,\n ) => {\n const prevSignature = getRefreshBoundarySignature(Refresh, prevExports);\n const nextSignature = getRefreshBoundarySignature(Refresh, nextExports);\n if (prevSignature.length !== nextSignature.length) {\n return true;\n }\n for (let i = 0; i < nextSignature.length; i++) {\n if (prevSignature[i] !== nextSignature[i]) {\n return true;\n }\n }\n return false;\n };\n var getRefreshBoundarySignature = (Refresh, moduleExports) => {\n const signature = [];\n signature.push(Refresh.getFamilyByType(moduleExports));\n if (moduleExports == null || typeof moduleExports !== "object") {\n return signature;\n }\n for (const key in moduleExports) {\n if (key === "__esModule") {\n continue;\n } else if (!isExportSafeToAccess(moduleExports, key)) {\n continue;\n }\n const exportValue = moduleExports[key];\n signature.push(key);\n signature.push(Refresh.getFamilyByType(exportValue));\n }\n return signature;\n };\n var registerExportsForReactRefresh = (Refresh, moduleExports, moduleID) => {\n Refresh.register(moduleExports, moduleID + " %exports%");\n if (moduleExports == null || typeof moduleExports !== "object") {\n return;\n }\n for (const key in moduleExports) {\n if (!isExportSafeToAccess(moduleExports, key)) {\n continue;\n }\n const exportValue = moduleExports[key];\n const typeID = moduleID + " %exports% " + key;\n Refresh.register(exportValue, typeID);\n }\n };\n global.__accept = metroHotUpdateModule;\n}\nif (__DEV__) {\n var requireSystrace = function requireSystrace() {\n return (\n global[__METRO_GLOBAL_PREFIX__ + "__SYSTRACE"] || metroRequire.Systrace\n );\n };\n var requireRefresh = function requireRefresh() {\n return (\n global[__METRO_GLOBAL_PREFIX__ + "__ReactRefresh"] ||\n global[global.__METRO_GLOBAL_PREFIX__ + "__ReactRefresh"] ||\n metroRequire.Refresh\n );\n };\n}\n'
9
+
10
+ // metro-runtime/src/modules/asyncRequire.js — the module import() compiles down to
11
+ export const METRO_ASYNC_REQUIRE =
12
+ '"use strict";\n\nfunction maybeLoadBundle(moduleID, paths) {\n const loadBundle = global[`${__METRO_GLOBAL_PREFIX__}__loadBundleAsync`];\n if (loadBundle != null) {\n const stringModuleID = String(moduleID);\n if (paths != null) {\n const bundlePath = paths[stringModuleID];\n if (bundlePath != null) {\n return loadBundle(bundlePath);\n }\n }\n }\n return undefined;\n}\nfunction asyncRequireImpl(moduleID, paths) {\n const maybeLoadBundlePromise = maybeLoadBundle(moduleID, paths);\n const importAll = () => require.importAll(moduleID);\n if (maybeLoadBundlePromise != null) {\n return maybeLoadBundlePromise.then(importAll);\n }\n return importAll();\n}\nasync function asyncRequire(moduleID, paths, moduleName) {\n return asyncRequireImpl(moduleID, paths);\n}\nasyncRequire.unstable_importMaybeSync = function unstable_importMaybeSync(\n moduleID,\n paths,\n) {\n return asyncRequireImpl(moduleID, paths);\n};\nasyncRequire.prefetch = function (moduleID, paths, moduleName) {\n maybeLoadBundle(moduleID, paths)?.then(\n () => {},\n () => {},\n );\n};\nmodule.exports = asyncRequire;\n'
13
+
14
+ // metro-runtime/src/modules/empty-module.js — what a browser-field `false` redirect resolves to
15
+ export const METRO_EMPTY_MODULE = '"use strict";\n'
@@ -0,0 +1,51 @@
1
+ // the built-in guest uses the existing Metro runtime and host module seam.
2
+ // the author supplies Swift; this entry carries no engine or compiler code.
3
+ import {
4
+ appendRNXMetroModuleIdentityFooter,
5
+ RNX_METRO_MODULE_IDENTITY_VERSION,
6
+ } from './metro-production-bundle'
7
+ import { METRO_REQUIRE_POLYFILL } from './metro-runtime-source'
8
+
9
+ export function swiftGuestBundle(packageName: string): string {
10
+ const modules = [
11
+ {
12
+ name: 'peach-swift-entry.js',
13
+ code: `const { AppRegistry } = require(1)
14
+ const { createSwiftPreviewEntry } = require(2)
15
+ AppRegistry.registerComponent('PeachSwift', () => createSwiftPreviewEntry(${JSON.stringify(packageName)}))`,
16
+ deps: [1, 2],
17
+ },
18
+ {
19
+ name: 'react-native',
20
+ code: `module.exports = global.__contrastHostModules['react-native']`,
21
+ deps: [],
22
+ },
23
+ {
24
+ name: 'peachsim/swift',
25
+ code: `module.exports = global.__contrastHostModules['peachsim/swift']`,
26
+ deps: [],
27
+ },
28
+ {
29
+ name: 'react',
30
+ code: `module.exports = global.__contrastHostModules['react']`,
31
+ deps: [],
32
+ },
33
+ ]
34
+ const bundle = [
35
+ `var __METRO_GLOBAL_PREFIX__='';`,
36
+ `(function(global){${METRO_REQUIRE_POLYFILL}})(globalThis);`,
37
+ ...modules.map(
38
+ (module, id) =>
39
+ `__d(function(global,require,_importDefault,_importAll,module,exports,_dependencyMap){\n${module.code}\n},${id},${JSON.stringify(module.deps)},${JSON.stringify(module.name)});`,
40
+ ),
41
+ '__r(0);',
42
+ ].join('\n')
43
+ return appendRNXMetroModuleIdentityFooter(bundle, {
44
+ version: RNX_METRO_MODULE_IDENTITY_VERSION,
45
+ identitySource: 'contrast-bundler',
46
+ modulePaths: Object.fromEntries(modules.map((module, id) => [id, module.name])),
47
+ logicalSpecifiers: Object.fromEntries(
48
+ modules.flatMap((module, id) => (id === 0 ? [] : [[id, [module.name]]])),
49
+ ),
50
+ })
51
+ }