@auraindustry/aurajs 0.1.1 → 0.1.5

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 (144) hide show
  1. package/README.md +7 -0
  2. package/benchmarks/perf-thresholds.json +27 -0
  3. package/package.json +6 -1
  4. package/src/ai-guidance.mjs +302 -0
  5. package/src/asset-pack.mjs +2 -1
  6. package/src/authored-project.mjs +498 -2
  7. package/src/authored-runtime.mjs +14 -0
  8. package/src/bin-integrity.mjs +33 -26
  9. package/src/build-contract/capabilities.mjs +87 -1
  10. package/src/build-contract/constants.mjs +1 -0
  11. package/src/build-contract.mjs +2 -0
  12. package/src/bundler.mjs +143 -13
  13. package/src/cli.mjs +681 -13
  14. package/src/commands/packs.mjs +741 -0
  15. package/src/commands/project-authoring.mjs +128 -1
  16. package/src/conformance/cases/app-and-ui-runtime-cases.mjs +1 -2
  17. package/src/conformance/cases/core-runtime-cases.mjs +6 -2
  18. package/src/conformance/cases/scene3d-and-media-cases.mjs +238 -0
  19. package/src/conformance/cases/systems-and-gameplay-cases.mjs +1126 -10
  20. package/src/conformance-mobile.mjs +166 -0
  21. package/src/conformance.mjs +89 -30
  22. package/src/evidence-bundle.mjs +242 -0
  23. package/src/external-package-surface.mjs +1 -1
  24. package/src/headless-test/runtime-coordinator.mjs +186 -33
  25. package/src/headless-test.mjs +2 -0
  26. package/src/helpers/2d/index.mjs +183 -0
  27. package/src/helpers/index.mjs +26 -0
  28. package/src/helpers/starter-utils/adventure-objectives.js +102 -0
  29. package/src/helpers/starter-utils/adventure-world-2d.js +221 -0
  30. package/src/helpers/starter-utils/animation-2d.js +337 -0
  31. package/src/helpers/starter-utils/animation-packaging-2d.js +203 -0
  32. package/src/helpers/starter-utils/atlas-assets-2d.js +111 -0
  33. package/src/helpers/starter-utils/autoplay-debug-2d.js +215 -0
  34. package/src/helpers/starter-utils/avatar-3d.js +404 -0
  35. package/src/helpers/starter-utils/combat-feedback-2d.js +320 -0
  36. package/src/helpers/starter-utils/combat-runtime-2d.js +290 -0
  37. package/src/helpers/starter-utils/core.js +150 -0
  38. package/src/helpers/starter-utils/dialogue-2d.js +351 -0
  39. package/src/helpers/starter-utils/enemy-archetypes-2d.js +68 -0
  40. package/src/helpers/starter-utils/index.js +26 -0
  41. package/src/helpers/starter-utils/inventory-2d.js +268 -0
  42. package/src/helpers/starter-utils/journal-2d.js +267 -0
  43. package/src/helpers/starter-utils/platformer-3d.js +132 -0
  44. package/src/helpers/starter-utils/scene-audio-2d.js +236 -0
  45. package/src/helpers/starter-utils/streamed-world-2d.js +378 -0
  46. package/src/helpers/starter-utils/tilemap-nav-2d.js +499 -0
  47. package/src/helpers/starter-utils/tilemap-world-2d.js +205 -0
  48. package/src/helpers/starter-utils/triggers.js +662 -0
  49. package/src/helpers/starter-utils/tween-2d.js +615 -0
  50. package/src/helpers/starter-utils/wave-director.js +101 -0
  51. package/src/helpers/starter-utils/world-compositor-2d.js +253 -0
  52. package/src/helpers/starter-utils/world-persistence-2d.js +180 -0
  53. package/src/mobile/android/build.mjs +606 -0
  54. package/src/mobile/android/host-artifact.mjs +280 -0
  55. package/src/mobile/ios/build.mjs +1323 -0
  56. package/src/mobile/ios/host-artifact.mjs +819 -0
  57. package/src/mobile/shared/capabilities.mjs +174 -0
  58. package/src/package-integrity.mjs +18 -4
  59. package/src/packs/catalog.mjs +259 -0
  60. package/src/perf-benchmark-runner.mjs +17 -12
  61. package/src/perf-benchmark.mjs +408 -4
  62. package/src/publish-command.mjs +434 -17
  63. package/src/publish-validation.mjs +22 -11
  64. package/src/replay-runtime.mjs +257 -0
  65. package/src/scaffold/config.mjs +2 -0
  66. package/src/scaffold/fs.mjs +8 -1
  67. package/src/scaffold/project-docs.mjs +101 -41
  68. package/src/scaffold.mjs +4 -0
  69. package/src/session-runtime.mjs +4 -3
  70. package/src/web-conformance.mjs +0 -36
  71. package/templates/create/2d/src/runtime/app.js +4 -0
  72. package/templates/create/2d-adventure/config/gameplay/adventure.config.js +9 -6
  73. package/templates/create/2d-adventure/content/gameplay/dialogue.js +85 -0
  74. package/templates/create/2d-adventure/content/gameplay/world.js +32 -36
  75. package/templates/create/2d-adventure/content/gameplay/world.tilemap.json +273 -0
  76. package/templates/create/2d-adventure/docs/design/loop.md +4 -3
  77. package/templates/create/2d-adventure/prefabs/relic.prefab.js +10 -10
  78. package/templates/create/2d-adventure/prefabs/world.prefab.js +127 -74
  79. package/templates/create/2d-adventure/scenes/gameplay.scene.js +603 -112
  80. package/templates/create/2d-adventure/src/runtime/capabilities.js +16 -0
  81. package/templates/create/2d-adventure/ui/hud.screen.js +187 -4
  82. package/templates/create/2d-adventure/ui/journal.screen.js +183 -0
  83. package/templates/create/2d-survivor/src/runtime/app.js +4 -0
  84. package/templates/create/3d/scenes/gameplay.scene.js +30 -3
  85. package/templates/create/3d/src/runtime/app.js +4 -0
  86. package/templates/create/3d/src/runtime/capabilities.js +5 -0
  87. package/templates/create/3d/src/runtime/materials.js +10 -0
  88. package/templates/create/3d-adventure/scenes/gameplay.scene.js +30 -3
  89. package/templates/create/3d-adventure/src/runtime/capabilities.js +5 -0
  90. package/templates/create/3d-adventure/src/runtime/materials.js +11 -0
  91. package/templates/create/3d-collectathon/scenes/gameplay.scene.js +30 -3
  92. package/templates/create/3d-collectathon/src/runtime/app.js +4 -0
  93. package/templates/create/3d-collectathon/src/runtime/capabilities.js +5 -0
  94. package/templates/create/3d-collectathon/src/runtime/materials.js +10 -0
  95. package/templates/create/blank/assets/splash/aurajs-gg-wordmark.webp +0 -0
  96. package/templates/create/blank/assets/splash/bg.webp +0 -0
  97. package/templates/create/blank/assets/splash/boot-loop.wav +0 -0
  98. package/templates/create/blank/assets/splash/boot-sting.wav +0 -0
  99. package/templates/create/blank/assets/splash/logo-mascot-sheet.webp +0 -0
  100. package/templates/create/blank/assets/splash/logoholo.webp +0 -0
  101. package/templates/create/blank/src/main.js +5 -1
  102. package/templates/create/blank/src/runtime/splash.js +305 -0
  103. package/templates/create/local-multiplayer/scenes/gameplay.scene.js +186 -12
  104. package/templates/create/local-multiplayer/src/runtime/capabilities.js +8 -1
  105. package/templates/create/shared/assets/splash/aurajs-gg-wordmark.webp +0 -0
  106. package/templates/create/shared/assets/splash/bg.webp +0 -0
  107. package/templates/create/shared/assets/splash/boot-loop.wav +0 -0
  108. package/templates/create/shared/assets/splash/boot-sting.wav +0 -0
  109. package/templates/create/shared/assets/splash/logo-mascot-sheet.webp +0 -0
  110. package/templates/create/shared/assets/splash/logoholo.webp +0 -0
  111. package/templates/create/shared/src/runtime/splash.js +305 -0
  112. package/templates/create/shared/src/runtime/ui-forms.js +552 -0
  113. package/templates/create/shared/src/starter-utils/adventure-world-2d.js +221 -0
  114. package/templates/create/shared/src/starter-utils/animation-packaging-2d.js +203 -0
  115. package/templates/create/shared/src/starter-utils/atlas-assets-2d.js +111 -0
  116. package/templates/create/shared/src/starter-utils/autoplay-debug-2d.js +215 -0
  117. package/templates/create/shared/src/starter-utils/combat-runtime-2d.js +290 -0
  118. package/templates/create/shared/src/starter-utils/dialogue-2d.js +351 -0
  119. package/templates/create/shared/src/starter-utils/index.js +15 -1
  120. package/templates/create/shared/src/starter-utils/inventory-2d.js +268 -0
  121. package/templates/create/shared/src/starter-utils/journal-2d.js +267 -0
  122. package/templates/create/shared/src/starter-utils/scene-audio-2d.js +236 -0
  123. package/templates/create/shared/src/starter-utils/streamed-world-2d.js +378 -0
  124. package/templates/create/shared/src/starter-utils/tilemap-nav-2d.js +499 -0
  125. package/templates/create/shared/src/starter-utils/tilemap-world-2d.js +205 -0
  126. package/templates/create/shared/src/starter-utils/world-compositor-2d.js +253 -0
  127. package/templates/create/shared/src/starter-utils/world-persistence-2d.js +180 -0
  128. package/templates/create/video-cutscene/src/runtime/app.js +4 -0
  129. package/templates/create-bin/play.js +148 -7
  130. package/templates/skills/auramaxx/SKILL.md +46 -0
  131. package/templates/skills/auramaxx/project-requirements.md +68 -0
  132. package/templates/skills/auramaxx/starter-recipes.md +104 -0
  133. package/templates/skills/auramaxx/validation-checklist.md +49 -0
  134. package/templates/starter/assets/splash/aurajs-gg-wordmark.webp +0 -0
  135. package/templates/starter/assets/splash/bg.webp +0 -0
  136. package/templates/starter/assets/splash/boot-loop.wav +0 -0
  137. package/templates/starter/assets/splash/boot-sting.wav +0 -0
  138. package/templates/starter/assets/splash/logo-mascot-sheet.webp +0 -0
  139. package/templates/starter/assets/splash/logoholo.webp +0 -0
  140. package/templates/starter/src/main.js +4 -0
  141. package/templates/starter/src/runtime/splash.js +305 -0
  142. package/templates/skills/aurajs/SKILL.md +0 -96
  143. package/templates/skills/aurajs/api-contract-3d.md +0 -7
  144. package/templates/skills/aurajs/api-contract.md +0 -7
@@ -0,0 +1,1323 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import {
3
+ cpSync,
4
+ existsSync,
5
+ mkdirSync,
6
+ readFileSync,
7
+ readdirSync,
8
+ rmSync,
9
+ statSync,
10
+ writeFileSync,
11
+ } from 'node:fs';
12
+ import { join, relative, resolve } from 'node:path';
13
+
14
+ const IOS_BUILD_MANIFEST_SCHEMA = 'aurajs.ios-build-manifest.v1';
15
+ const IOS_BUILD_CONFIGURATION = 'Release';
16
+ const IOS_RESOURCE_ROOT_NAME = 'aurajs';
17
+ const IOS_HOST_XCFRAMEWORK_NAME = 'aurajs-host.xcframework';
18
+ const IOS_HOST_FRAMEWORK_DIRECTORY = 'aurajs-host.framework';
19
+ const IOS_HOST_FRAMEWORK_BINARY = 'aurajs-host';
20
+ const IOS_DEVICE_LIBRARY_IDENTIFIER = 'ios-arm64';
21
+ const IOS_SIMULATOR_LIBRARY_IDENTIFIER = 'ios-arm64-simulator';
22
+ const IOS_XCODE_PROJECT_NAME = 'AuraJSApp.xcodeproj';
23
+ const IOS_XCODE_PROJECT_FILE = 'project.pbxproj';
24
+ const IOS_XCODE_SCHEME_NAME = 'AuraJSApp';
25
+ const IOS_XCODE_PRODUCT_NAME = 'AuraJSApp.app';
26
+ const IOS_EXPORT_OPTIONS_FILE = 'ExportOptions.plist';
27
+ const IOS_DERIVED_DATA_ROOT = 'derived-data';
28
+ const TEMPLATE_ROOT = resolve(
29
+ new URL('../../../../platform/ios/template/', import.meta.url).pathname,
30
+ );
31
+ const DIST_ROOT = resolve(
32
+ new URL('../../../../platform/dist/ios/', import.meta.url).pathname,
33
+ );
34
+ const HOST_XCFRAMEWORK_ROOT = resolve(
35
+ new URL('../../../../platform/ios/host/aurajs-host.xcframework/', import.meta.url).pathname,
36
+ );
37
+
38
+ const IOS_GENERATED_PROJECT_PBXPROJ = `// !$*UTF8*$!
39
+ {
40
+ \tarchiveVersion = 1;
41
+ \tclasses = {
42
+ \t};
43
+ \tobjectVersion = 56;
44
+ \tobjects = {
45
+
46
+ /* Begin PBXBuildFile section */
47
+ \t\tA1B2C3D41E00000100000001 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D31E00000100000001 /* AppDelegate.swift */; };
48
+ \t\tA1B2C3D51E00000100000001 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B2C3D61E00000100000001 /* UIKit.framework */; };
49
+ /* End PBXBuildFile section */
50
+
51
+ /* Begin PBXFileReference section */
52
+ \t\tA1B2C3D01E00000100000001 /* AuraJSApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AuraJSApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
53
+ \t\tA1B2C3D31E00000100000001 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuraJSApp/AppDelegate.swift; sourceTree = SOURCE_ROOT; };
54
+ \t\tA1B2C3D21E00000100000001 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = AuraJSApp/Info.plist; sourceTree = SOURCE_ROOT; };
55
+ \t\tA1B2C3D61E00000100000001 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
56
+ /* End PBXFileReference section */
57
+
58
+ /* Begin PBXFrameworksBuildPhase section */
59
+ \t\tA1B2C3D81E00000100000001 /* Frameworks */ = {
60
+ \t\t\tisa = PBXFrameworksBuildPhase;
61
+ \t\t\tbuildActionMask = 2147483647;
62
+ \t\t\tfiles = (
63
+ \t\t\t\tA1B2C3D51E00000100000001 /* UIKit.framework in Frameworks */,
64
+ \t\t\t);
65
+ \t\t\trunOnlyForDeploymentPostprocessing = 0;
66
+ \t\t};
67
+ /* End PBXFrameworksBuildPhase section */
68
+
69
+ /* Begin PBXShellScriptBuildPhase section */
70
+ \t\tA1B2C3D61E00000100000002 /* Sync AuraJS Runtime */ = {
71
+ \t\t\tisa = PBXShellScriptBuildPhase;
72
+ \t\t\tbuildActionMask = 2147483647;
73
+ \t\t\tfiles = (
74
+ \t\t\t);
75
+ \t\t\tinputPaths = (
76
+ \t\t\t);
77
+ \t\t\tname = "Sync AuraJS Runtime";
78
+ \t\t\toutputPaths = (
79
+ \t\t\t);
80
+ \t\t\trunOnlyForDeploymentPostprocessing = 0;
81
+ \t\t\tshellPath = /bin/sh;
82
+ \t\t\tshellScript = "set -eu\\nAURAJS_RESOURCE_ROOT=\\\"\${PROJECT_DIR}/../staging/aurajs\\\"\\nAURAJS_RESOURCE_DEST=\\\"\${TARGET_BUILD_DIR}/\${UNLOCALIZED_RESOURCES_FOLDER_PATH}/aurajs\\\"\\nif [ ! -d \\\"\${AURAJS_RESOURCE_ROOT}\\\" ]; then\\n echo \\\"Missing AuraJS staged resources at \${AURAJS_RESOURCE_ROOT}. Run the AuraJS iOS staging build first.\\\" >&2\\n exit 1\\nfi\\nrm -rf \\\"\${AURAJS_RESOURCE_DEST}\\\"\\nmkdir -p \\\"$(dirname \\\"\${AURAJS_RESOURCE_DEST}\\\")\\\"\\nditto \\\"\${AURAJS_RESOURCE_ROOT}\\\" \\\"\${AURAJS_RESOURCE_DEST}\\\"\\ncase \\\"\${PLATFORM_NAME}\\\" in\\n iphonesimulator)\\n AURAJS_FRAMEWORK_SLICE=ios-arm64-simulator\\n ;;\\n iphoneos)\\n AURAJS_FRAMEWORK_SLICE=ios-arm64\\n ;;\\n *)\\n echo \\\"Unsupported Apple platform: \${PLATFORM_NAME}\\\" >&2\\n exit 1\\n ;;\\nesac\\nAURAJS_FRAMEWORK_SOURCE=\\\"\${PROJECT_DIR}/../host/aurajs-host.xcframework/\${AURAJS_FRAMEWORK_SLICE}/aurajs-host.framework\\\"\\nAURAJS_FRAMEWORK_DEST=\\\"\${TARGET_BUILD_DIR}/\${FRAMEWORKS_FOLDER_PATH}/aurajs-host.framework\\\"\\nif [ ! -d \\\"\${AURAJS_FRAMEWORK_SOURCE}\\\" ]; then\\n echo \\\"Missing AuraJS host framework slice at \${AURAJS_FRAMEWORK_SOURCE}. Run the AuraJS iOS host-artifact build first.\\\" >&2\\n exit 1\\nfi\\nrm -rf \\\"\${AURAJS_FRAMEWORK_DEST}\\\"\\nmkdir -p \\\"$(dirname \\\"\${AURAJS_FRAMEWORK_DEST}\\\")\\\"\\nditto \\\"\${AURAJS_FRAMEWORK_SOURCE}\\\" \\\"\${AURAJS_FRAMEWORK_DEST}\\\"\\n";
83
+ \t\t};
84
+ /* End PBXShellScriptBuildPhase section */
85
+
86
+ /* Begin PBXGroup section */
87
+ \t\tA1B2C3DB1E00000100000001 = {
88
+ \t\t\tisa = PBXGroup;
89
+ \t\t\tchildren = (
90
+ \t\t\t\tA1B2C3DD1E00000100000001 /* AuraJSApp */,
91
+ \t\t\t\tA1B2C3DC1E00000100000001 /* Frameworks */,
92
+ \t\t\t\tA1B2C3DE1E00000100000001 /* Products */,
93
+ \t\t\t);
94
+ \t\t\tsourceTree = "<group>";
95
+ \t\t};
96
+ \t\tA1B2C3DC1E00000100000001 /* Frameworks */ = {
97
+ \t\t\tisa = PBXGroup;
98
+ \t\t\tchildren = (
99
+ \t\t\t\tA1B2C3D61E00000100000001 /* UIKit.framework */,
100
+ \t\t\t);
101
+ \t\t\tname = Frameworks;
102
+ \t\t\tsourceTree = "<group>";
103
+ \t\t};
104
+ \t\tA1B2C3DD1E00000100000001 /* AuraJSApp */ = {
105
+ \t\t\tisa = PBXGroup;
106
+ \t\t\tchildren = (
107
+ \t\t\t\tA1B2C3D31E00000100000001 /* AppDelegate.swift */,
108
+ \t\t\t\tA1B2C3D21E00000100000001 /* Info.plist */,
109
+ \t\t\t);
110
+ \t\t\tname = AuraJSApp;
111
+ \t\t\tsourceTree = "<group>";
112
+ \t\t};
113
+ \t\tA1B2C3DE1E00000100000001 /* Products */ = {
114
+ \t\t\tisa = PBXGroup;
115
+ \t\t\tchildren = (
116
+ \t\t\t\tA1B2C3D01E00000100000001 /* AuraJSApp.app */,
117
+ \t\t\t);
118
+ \t\t\tname = Products;
119
+ \t\t\tsourceTree = "<group>";
120
+ \t\t};
121
+ /* End PBXGroup section */
122
+
123
+ /* Begin PBXNativeTarget section */
124
+ \t\tA1B2C3D71E00000100000001 /* AuraJSApp */ = {
125
+ \t\t\tisa = PBXNativeTarget;
126
+ \t\t\tbuildConfigurationList = A1B2C3E31E00000100000001 /* Build configuration list for PBXNativeTarget "AuraJSApp" */;
127
+ \t\t\tbuildPhases = (
128
+ \t\t\t\tA1B2C3D91E00000100000001 /* Sources */,
129
+ \t\t\t\tA1B2C3D81E00000100000001 /* Frameworks */,
130
+ \t\t\t\tA1B2C3DA1E00000100000001 /* Resources */,
131
+ \t\t\t\tA1B2C3D61E00000100000002 /* Sync AuraJS Runtime */,
132
+ \t\t\t);
133
+ \t\t\tbuildRules = (
134
+ \t\t\t);
135
+ \t\t\tdependencies = (
136
+ \t\t\t);
137
+ \t\t\tname = AuraJSApp;
138
+ \t\t\tproductName = AuraJSApp;
139
+ \t\t\tproductReference = A1B2C3D01E00000100000001 /* AuraJSApp.app */;
140
+ \t\t\tproductType = "com.apple.product-type.application";
141
+ \t\t};
142
+ /* End PBXNativeTarget section */
143
+
144
+ /* Begin PBXProject section */
145
+ \t\tA1B2C3DF1E00000100000001 /* Project object */ = {
146
+ \t\t\tisa = PBXProject;
147
+ \t\t\tattributes = {
148
+ \t\t\t\tBuildIndependentTargetsInParallel = 1;
149
+ \t\t\t\tLastSwiftUpdateCheck = 1600;
150
+ \t\t\t\tLastUpgradeCheck = 1600;
151
+ \t\t\t\tTargetAttributes = {
152
+ \t\t\t\t\tA1B2C3D71E00000100000001 = {
153
+ \t\t\t\t\t\tCreatedOnToolsVersion = 16.0;
154
+ \t\t\t\t\t};
155
+ \t\t\t\t};
156
+ \t\t\t};
157
+ \t\t\tbuildConfigurationList = A1B2C3E01E00000100000001 /* Build configuration list for PBXProject "AuraJSApp" */;
158
+ \t\t\tcompatibilityVersion = "Xcode 14.0";
159
+ \t\t\tdevelopmentRegion = en;
160
+ \t\t\thasScannedForEncodings = 0;
161
+ \t\t\tknownRegions = (
162
+ \t\t\t\ten,
163
+ \t\t\t\tBase,
164
+ \t\t\t);
165
+ \t\t\tmainGroup = A1B2C3DB1E00000100000001;
166
+ \t\t\tproductRefGroup = A1B2C3DE1E00000100000001 /* Products */;
167
+ \t\t\tprojectDirPath = "";
168
+ \t\t\tprojectRoot = "";
169
+ \t\t\ttargets = (
170
+ \t\t\t\tA1B2C3D71E00000100000001 /* AuraJSApp */,
171
+ \t\t\t);
172
+ \t\t};
173
+ /* End PBXProject section */
174
+
175
+ /* Begin PBXResourcesBuildPhase section */
176
+ \t\tA1B2C3DA1E00000100000001 /* Resources */ = {
177
+ \t\t\tisa = PBXResourcesBuildPhase;
178
+ \t\t\tbuildActionMask = 2147483647;
179
+ \t\t\tfiles = (
180
+ \t\t\t);
181
+ \t\t\trunOnlyForDeploymentPostprocessing = 0;
182
+ \t\t};
183
+ /* End PBXResourcesBuildPhase section */
184
+
185
+ /* Begin PBXSourcesBuildPhase section */
186
+ \t\tA1B2C3D91E00000100000001 /* Sources */ = {
187
+ \t\t\tisa = PBXSourcesBuildPhase;
188
+ \t\t\tbuildActionMask = 2147483647;
189
+ \t\t\tfiles = (
190
+ \t\t\t\tA1B2C3D41E00000100000001 /* AppDelegate.swift in Sources */,
191
+ \t\t\t);
192
+ \t\t\trunOnlyForDeploymentPostprocessing = 0;
193
+ \t\t};
194
+ /* End PBXSourcesBuildPhase section */
195
+
196
+ /* Begin XCBuildConfiguration section */
197
+ \t\tA1B2C3E11E00000100000001 /* Debug */ = {
198
+ \t\t\tisa = XCBuildConfiguration;
199
+ \t\t\tbuildSettings = {
200
+ \t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;
201
+ \t\t\t\tCLANG_ENABLE_MODULES = YES;
202
+ \t\t\t\tCOPY_PHASE_STRIP = NO;
203
+ \t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;
204
+ \t\t\t\tENABLE_TESTABILITY = YES;
205
+ \t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu17;
206
+ \t\t\t\tGCC_NO_COMMON_BLOCKS = YES;
207
+ \t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 16.0;
208
+ \t\t\t\tSDKROOT = iphoneos;
209
+ \t\t\t\tSWIFT_VERSION = 5.0;
210
+ \t\t\t};
211
+ \t\t\tname = Debug;
212
+ \t\t};
213
+ \t\tA1B2C3E21E00000100000001 /* Release */ = {
214
+ \t\t\tisa = XCBuildConfiguration;
215
+ \t\t\tbuildSettings = {
216
+ \t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;
217
+ \t\t\t\tCLANG_ENABLE_MODULES = YES;
218
+ \t\t\t\tCOPY_PHASE_STRIP = NO;
219
+ \t\t\t\tDEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
220
+ \t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu17;
221
+ \t\t\t\tGCC_NO_COMMON_BLOCKS = YES;
222
+ \t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 16.0;
223
+ \t\t\t\tSDKROOT = iphoneos;
224
+ \t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;
225
+ \t\t\t\tSWIFT_VERSION = 5.0;
226
+ \t\t\t};
227
+ \t\t\tname = Release;
228
+ \t\t};
229
+ \t\tA1B2C3E41E00000100000001 /* Debug */ = {
230
+ \t\t\tisa = XCBuildConfiguration;
231
+ \t\t\tbuildSettings = {
232
+ \t\t\t\tCODE_SIGN_STYLE = Automatic;
233
+ \t\t\t\tCURRENT_PROJECT_VERSION = 1;
234
+ \t\t\t\tGENERATE_INFOPLIST_FILE = NO;
235
+ \t\t\t\tINFOPLIST_FILE = AuraJSApp/Info.plist;
236
+ \t\t\t\tLD_RUNPATH_SEARCH_PATHS = (
237
+ \t\t\t\t\t"$(inherited)",
238
+ \t\t\t\t\t"@executable_path/Frameworks",
239
+ \t\t\t\t);
240
+ \t\t\t\tMARKETING_VERSION = 0.1.0;
241
+ \t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.aurajs.template;
242
+ \t\t\t\tPRODUCT_NAME = "$(TARGET_NAME)";
243
+ \t\t\t\tSUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
244
+ \t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;
245
+ \t\t\t\tTARGETED_DEVICE_FAMILY = "1,2";
246
+ \t\t\t};
247
+ \t\t\tname = Debug;
248
+ \t\t};
249
+ \t\tA1B2C3E51E00000100000001 /* Release */ = {
250
+ \t\t\tisa = XCBuildConfiguration;
251
+ \t\t\tbuildSettings = {
252
+ \t\t\t\tCODE_SIGN_STYLE = Automatic;
253
+ \t\t\t\tCURRENT_PROJECT_VERSION = 1;
254
+ \t\t\t\tGENERATE_INFOPLIST_FILE = NO;
255
+ \t\t\t\tINFOPLIST_FILE = AuraJSApp/Info.plist;
256
+ \t\t\t\tLD_RUNPATH_SEARCH_PATHS = (
257
+ \t\t\t\t\t"$(inherited)",
258
+ \t\t\t\t\t"@executable_path/Frameworks",
259
+ \t\t\t\t);
260
+ \t\t\t\tMARKETING_VERSION = 0.1.0;
261
+ \t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.aurajs.template;
262
+ \t\t\t\tPRODUCT_NAME = "$(TARGET_NAME)";
263
+ \t\t\t\tSUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
264
+ \t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;
265
+ \t\t\t\tTARGETED_DEVICE_FAMILY = "1,2";
266
+ \t\t\t};
267
+ \t\t\tname = Release;
268
+ \t\t};
269
+ /* End XCBuildConfiguration section */
270
+
271
+ /* Begin XCConfigurationList section */
272
+ \t\tA1B2C3E01E00000100000001 /* Build configuration list for PBXProject "AuraJSApp" */ = {
273
+ \t\t\tisa = XCConfigurationList;
274
+ \t\t\tbuildConfigurations = (
275
+ \t\t\t\tA1B2C3E11E00000100000001 /* Debug */,
276
+ \t\t\t\tA1B2C3E21E00000100000001 /* Release */,
277
+ \t\t\t);
278
+ \t\t\tdefaultConfigurationIsVisible = 0;
279
+ \t\t\tdefaultConfigurationName = Release;
280
+ \t\t};
281
+ \t\tA1B2C3E31E00000100000001 /* Build configuration list for PBXNativeTarget "AuraJSApp" */ = {
282
+ \t\t\tisa = XCConfigurationList;
283
+ \t\t\tbuildConfigurations = (
284
+ \t\t\t\tA1B2C3E41E00000100000001 /* Debug */,
285
+ \t\t\t\tA1B2C3E51E00000100000001 /* Release */,
286
+ \t\t\t);
287
+ \t\t\tdefaultConfigurationIsVisible = 0;
288
+ \t\t\tdefaultConfigurationName = Release;
289
+ \t\t};
290
+ /* End XCConfigurationList section */
291
+ \t};
292
+ \trootObject = A1B2C3DF1E00000100000001 /* Project object */;
293
+ }
294
+ `;
295
+
296
+ const IOS_GENERATED_XCSCHEME = `<?xml version="1.0" encoding="UTF-8"?>
297
+ <Scheme
298
+ LastUpgradeVersion = "1600"
299
+ version = "1.7">
300
+ <BuildAction
301
+ parallelizeBuildables = "YES"
302
+ buildImplicitDependencies = "YES">
303
+ <BuildActionEntries>
304
+ <BuildActionEntry
305
+ buildForTesting = "YES"
306
+ buildForRunning = "YES"
307
+ buildForProfiling = "YES"
308
+ buildForArchiving = "YES"
309
+ buildForAnalyzing = "YES">
310
+ <BuildableReference
311
+ BuildableIdentifier = "primary"
312
+ BlueprintIdentifier = "A1B2C3D71E00000100000001"
313
+ BuildableName = "AuraJSApp.app"
314
+ BlueprintName = "AuraJSApp"
315
+ ReferencedContainer = "container:AuraJSApp.xcodeproj">
316
+ </BuildableReference>
317
+ </BuildActionEntry>
318
+ </BuildActionEntries>
319
+ </BuildAction>
320
+ <TestAction
321
+ buildConfiguration = "Debug"
322
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
323
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
324
+ shouldUseLaunchSchemeArgsEnv = "YES">
325
+ <Testables>
326
+ </Testables>
327
+ </TestAction>
328
+ <LaunchAction
329
+ buildConfiguration = "Debug"
330
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
331
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
332
+ launchStyle = "0"
333
+ useCustomWorkingDirectory = "NO"
334
+ ignoresPersistentStateOnLaunch = "NO"
335
+ debugDocumentVersioning = "YES"
336
+ debugServiceExtension = "internal"
337
+ allowLocationSimulation = "YES">
338
+ <BuildableProductRunnable
339
+ runnableDebuggingMode = "0">
340
+ <BuildableReference
341
+ BuildableIdentifier = "primary"
342
+ BlueprintIdentifier = "A1B2C3D71E00000100000001"
343
+ BuildableName = "AuraJSApp.app"
344
+ BlueprintName = "AuraJSApp"
345
+ ReferencedContainer = "container:AuraJSApp.xcodeproj">
346
+ </BuildableReference>
347
+ </BuildableProductRunnable>
348
+ </LaunchAction>
349
+ <ProfileAction
350
+ buildConfiguration = "Release"
351
+ shouldUseLaunchSchemeArgsEnv = "YES"
352
+ savedToolIdentifier = ""
353
+ useCustomWorkingDirectory = "NO"
354
+ debugDocumentVersioning = "YES">
355
+ <BuildableProductRunnable
356
+ runnableDebuggingMode = "0">
357
+ <BuildableReference
358
+ BuildableIdentifier = "primary"
359
+ BlueprintIdentifier = "A1B2C3D71E00000100000001"
360
+ BuildableName = "AuraJSApp.app"
361
+ BlueprintName = "AuraJSApp"
362
+ ReferencedContainer = "container:AuraJSApp.xcodeproj">
363
+ </BuildableReference>
364
+ </BuildableProductRunnable>
365
+ </ProfileAction>
366
+ <AnalyzeAction
367
+ buildConfiguration = "Debug">
368
+ </AnalyzeAction>
369
+ <ArchiveAction
370
+ buildConfiguration = "Release"
371
+ revealArchiveInOrganizer = "YES">
372
+ </ArchiveAction>
373
+ </Scheme>
374
+ `;
375
+
376
+ export function stageIosProject(options = {}) {
377
+ const projectRoot = resolve(options.projectRoot || process.cwd());
378
+ const outRoot = resolve(options.outRoot || join(projectRoot, 'build', 'ios'));
379
+ const buildManifestPath = resolveRequiredPath(options.buildManifestPath, 'buildManifestPath');
380
+ const assetsManifestPath = resolveRequiredPath(options.assetsManifestPath, 'assetsManifestPath');
381
+ const bundlePath = resolveRequiredPath(options.bundlePath, 'bundlePath');
382
+ const identity = normalizeIdentity(options.identity || {});
383
+ const sourceBuildRoot = options.sourceBuildRoot
384
+ ? resolve(options.sourceBuildRoot)
385
+ : resolve(bundlePath, '..', '..');
386
+ const hostFrameworkContract = resolveHostFrameworkContract({
387
+ projectRoot,
388
+ hostFrameworkPath: options.hostFrameworkPath || null,
389
+ distRoot: options.distRoot || DIST_ROOT,
390
+ });
391
+
392
+ const toolchain = detectIosToolchain({
393
+ environment: options.environment || process.env,
394
+ spawnSyncImpl: options.spawnSyncImpl || spawnSync,
395
+ xcodebuildExecutable: options.xcodebuildExecutable || null,
396
+ });
397
+ const signing = detectIosSigning({
398
+ environment: options.environment || process.env,
399
+ bundleId: identity.bundleId,
400
+ });
401
+
402
+ mkdirSync(outRoot, { recursive: true });
403
+ const templateOutRoot = join(outRoot, 'template');
404
+ const hostOutRoot = join(outRoot, 'host');
405
+ const hostFrameworkPath = join(hostOutRoot, IOS_HOST_XCFRAMEWORK_NAME);
406
+ const stagingRoot = join(outRoot, 'staging', IOS_RESOURCE_ROOT_NAME);
407
+ const stagingJsRoot = join(stagingRoot, 'js');
408
+ const stagingAssetsRoot = join(stagingRoot, 'assets');
409
+ const simulatorAppPath = join(outRoot, 'simulator', `${identity.appName}.app`);
410
+ const deviceAppPath = join(outRoot, 'device', `${identity.appName}.app`);
411
+ const archivePath = join(outRoot, 'archive', `${identity.appName}.xcarchive`);
412
+ const exportPath = join(outRoot, 'export', `${identity.appName}.ipa`);
413
+
414
+ copyDirectory(TEMPLATE_ROOT, templateOutRoot);
415
+ writeGeneratedXcodeProject(templateOutRoot);
416
+ copyDirectory(hostFrameworkContract.sourcePath, hostFrameworkPath);
417
+
418
+ mkdirSync(stagingJsRoot, { recursive: true });
419
+ mkdirSync(stagingAssetsRoot, { recursive: true });
420
+
421
+ cpSync(buildManifestPath, join(stagingRoot, 'build-manifest.json'));
422
+ cpSync(assetsManifestPath, join(stagingRoot, 'assets-manifest.json'));
423
+ cpSync(bundlePath, join(stagingJsRoot, 'game.bundle.js'));
424
+ const sourceRuntimeConfigPath = join(sourceBuildRoot, 'runtime-config.json');
425
+ if (existsSync(sourceRuntimeConfigPath) && statSync(sourceRuntimeConfigPath).isFile()) {
426
+ cpSync(sourceRuntimeConfigPath, join(stagingRoot, 'runtime-config.json'));
427
+ }
428
+
429
+ const sourceAssetsRoot = join(sourceBuildRoot, 'assets');
430
+ if (existsSync(sourceAssetsRoot) && statSync(sourceAssetsRoot).isDirectory()) {
431
+ copyDirectory(sourceAssetsRoot, stagingAssetsRoot);
432
+ }
433
+
434
+ mkdirSync(simulatorAppPath, { recursive: true });
435
+ mkdirSync(deviceAppPath, { recursive: true });
436
+ mkdirSync(dirnameSafe(archivePath), { recursive: true });
437
+ mkdirSync(dirnameSafe(exportPath), { recursive: true });
438
+ const bundledDeviceResourceRoot = join(deviceAppPath, IOS_RESOURCE_ROOT_NAME);
439
+ const bundledSimulatorResourceRoot = join(simulatorAppPath, IOS_RESOURCE_ROOT_NAME);
440
+ copyDirectory(stagingRoot, bundledDeviceResourceRoot);
441
+ copyDirectory(stagingRoot, bundledSimulatorResourceRoot);
442
+ const embeddedFrameworks = embedHostFrameworkSlices({
443
+ contract: hostFrameworkContract,
444
+ deviceAppPath,
445
+ simulatorAppPath,
446
+ });
447
+
448
+ const manifest = {
449
+ schema: IOS_BUILD_MANIFEST_SCHEMA,
450
+ schemaVersion: '1.0.0',
451
+ buildTarget: 'ios',
452
+ packagingForm: 'xcframework',
453
+ hostFramework: relativePosix(outRoot, hostFrameworkPath),
454
+ hostFrameworkStatus: {
455
+ reasonCode: hostFrameworkContract.reasonCode,
456
+ sourceKind: hostFrameworkContract.sourceKind,
457
+ sourcePath: relativeToRootOrAbsolute(projectRoot, hostFrameworkContract.sourcePath),
458
+ stagedPath: relativePosix(outRoot, hostFrameworkPath),
459
+ expectedSlices: {
460
+ device: `${IOS_DEVICE_LIBRARY_IDENTIFIER}/${IOS_HOST_FRAMEWORK_DIRECTORY}`,
461
+ simulator: `${IOS_SIMULATOR_LIBRARY_IDENTIFIER}/${IOS_HOST_FRAMEWORK_DIRECTORY}`,
462
+ },
463
+ embeddedFrameworks: {
464
+ device: embeddedFrameworks.device
465
+ ? relativePosix(outRoot, embeddedFrameworks.device)
466
+ : null,
467
+ simulator: embeddedFrameworks.simulator
468
+ ? relativePosix(outRoot, embeddedFrameworks.simulator)
469
+ : null,
470
+ },
471
+ },
472
+ templateRoot: relativePosix(outRoot, templateOutRoot),
473
+ resourceRoot: relativePosix(outRoot, stagingRoot),
474
+ identity: {
475
+ appName: identity.appName,
476
+ bundleId: identity.bundleId,
477
+ version: identity.version,
478
+ buildNumber: identity.buildNumber,
479
+ },
480
+ slices: {
481
+ device: {
482
+ sdk: 'iphoneos',
483
+ architectures: ['arm64'],
484
+ app: relativePosix(outRoot, deviceAppPath),
485
+ },
486
+ simulator: {
487
+ sdk: 'iphonesimulator',
488
+ architectures: ['arm64'],
489
+ app: relativePosix(outRoot, simulatorAppPath),
490
+ },
491
+ },
492
+ artifacts: {
493
+ buildDeviceApp: relativePosix(outRoot, deviceAppPath),
494
+ buildSimulatorApp: relativePosix(outRoot, simulatorAppPath),
495
+ archive: relativePosix(outRoot, archivePath),
496
+ exportIpa: relativePosix(outRoot, exportPath),
497
+ },
498
+ resourceContract: {
499
+ root: `${IOS_RESOURCE_ROOT_NAME}/`,
500
+ buildManifest: `${IOS_RESOURCE_ROOT_NAME}/build-manifest.json`,
501
+ assetsManifest: `${IOS_RESOURCE_ROOT_NAME}/assets-manifest.json`,
502
+ bundle: `${IOS_RESOURCE_ROOT_NAME}/js/game.bundle.js`,
503
+ assetsRoot: `${IOS_RESOURCE_ROOT_NAME}/assets`,
504
+ bundledDeviceRoot: relativePosix(outRoot, bundledDeviceResourceRoot),
505
+ bundledSimulatorRoot: relativePosix(outRoot, bundledSimulatorResourceRoot),
506
+ },
507
+ buildStatus: {
508
+ simulator: 'not_built',
509
+ device: 'not_built',
510
+ archive: 'not_built',
511
+ export: 'not_built',
512
+ reasonCode: 'ios_external_build_not_run',
513
+ },
514
+ toolchain,
515
+ signing,
516
+ };
517
+
518
+ const manifestPath = join(outRoot, 'ios-build-manifest.json');
519
+ writeCanonicalJson(manifestPath, manifest);
520
+
521
+ return {
522
+ outRoot,
523
+ manifestPath,
524
+ templateOutRoot,
525
+ hostFrameworkPath,
526
+ stagingRoot,
527
+ simulatorAppPath,
528
+ deviceAppPath,
529
+ archivePath,
530
+ exportPath,
531
+ toolchain,
532
+ signing,
533
+ };
534
+ }
535
+
536
+ export function detectIosToolchain(options = {}) {
537
+ const environment = options.environment || process.env;
538
+ const spawnSyncImpl = options.spawnSyncImpl || spawnSync;
539
+ const xcodebuildExecutable = cleanString(options.xcodebuildExecutable)
540
+ || cleanString(environment.AURA_IOS_XCODEBUILD)
541
+ || 'xcodebuild';
542
+ if (String(environment.AURAJS_SKIP_XCODE_PROBE || '') === '1') {
543
+ return {
544
+ available: false,
545
+ reasonCode: 'ios_xcode_probe_skipped',
546
+ detail: 'Xcode probing was skipped by AURAJS_SKIP_XCODE_PROBE=1.',
547
+ executablePath: xcodebuildExecutable,
548
+ };
549
+ }
550
+
551
+ const result = spawnSyncImpl(xcodebuildExecutable, ['-version'], {
552
+ encoding: 'utf8',
553
+ env: environment,
554
+ });
555
+ if (result.status !== 0) {
556
+ return {
557
+ available: false,
558
+ reasonCode: 'ios_xcodebuild_missing',
559
+ detail: 'xcodebuild was not available in PATH.',
560
+ executablePath: xcodebuildExecutable,
561
+ };
562
+ }
563
+
564
+ const versionLine = String(result.stdout || '')
565
+ .split('\n')
566
+ .map((line) => line.trim())
567
+ .find((line) => line.startsWith('Xcode '))
568
+ || null;
569
+
570
+ return {
571
+ available: true,
572
+ reasonCode: 'ios_xcodebuild_available',
573
+ detail: versionLine,
574
+ executablePath: xcodebuildExecutable,
575
+ };
576
+ }
577
+
578
+ export function detectIosSigning(options = {}) {
579
+ const environment = options.environment || process.env;
580
+ const bundleId = cleanString(environment.AURA_IOS_BUNDLE_ID) || cleanString(options.bundleId);
581
+ const teamId = cleanString(environment.AURA_IOS_TEAM_ID);
582
+ const codeSignIdentity = cleanString(environment.AURA_IOS_CODE_SIGN_IDENTITY);
583
+
584
+ if (bundleId && (teamId || codeSignIdentity)) {
585
+ return {
586
+ configured: true,
587
+ reasonCode: 'ios_signing_configured',
588
+ bundleId,
589
+ teamId,
590
+ codeSignIdentity,
591
+ };
592
+ }
593
+
594
+ return {
595
+ configured: false,
596
+ reasonCode: 'ios_signing_unconfigured',
597
+ bundleId: bundleId || null,
598
+ teamId,
599
+ codeSignIdentity,
600
+ };
601
+ }
602
+
603
+ export function buildIosArtifacts(options = {}) {
604
+ const outRoot = resolveRequiredPath(options.outRoot, 'outRoot');
605
+ const manifestPath = resolveRequiredPath(
606
+ options.manifestPath || join(outRoot, 'ios-build-manifest.json'),
607
+ 'manifestPath',
608
+ );
609
+ const environment = options.environment || process.env;
610
+ const spawnSyncImpl = options.spawnSyncImpl || spawnSync;
611
+ const operations = normalizeIosOperations(options.operations);
612
+ const manifest = readIosBuildManifest(manifestPath);
613
+ const toolchain = detectIosToolchain({
614
+ environment,
615
+ spawnSyncImpl,
616
+ xcodebuildExecutable: options.xcodebuildExecutable || null,
617
+ });
618
+ const signing = detectIosSigning({
619
+ environment,
620
+ bundleId: manifest.identity?.bundleId || null,
621
+ });
622
+ const hostFrameworkRoot = join(outRoot, manifest.hostFramework);
623
+ const projectBundlePath = join(outRoot, manifest.templateRoot, IOS_XCODE_PROJECT_NAME);
624
+ const stagingRoot = join(outRoot, manifest.resourceRoot);
625
+ const derivedDataPath = resolve(options.derivedDataPath || join(outRoot, IOS_DERIVED_DATA_ROOT));
626
+ const buildStatus = {
627
+ simulator: manifest.buildStatus?.simulator || 'not_built',
628
+ device: manifest.buildStatus?.device || 'not_built',
629
+ archive: manifest.buildStatus?.archive || 'not_built',
630
+ export: manifest.buildStatus?.export || 'not_built',
631
+ };
632
+ const executedPhases = [];
633
+ const outputs = {
634
+ simulatorApp: null,
635
+ deviceApp: null,
636
+ archive: null,
637
+ exportIpa: null,
638
+ };
639
+
640
+ manifest.toolchain = toolchain;
641
+ manifest.signing = signing;
642
+
643
+ if (!toolchain.available) {
644
+ return finalizeIosBuildFailure({
645
+ manifest,
646
+ manifestPath,
647
+ buildStatus,
648
+ reasonCode: toolchain.reasonCode,
649
+ outRoot,
650
+ detail: toolchain.detail,
651
+ executedPhases,
652
+ outputs,
653
+ derivedDataPath,
654
+ exportOptionsPath: null,
655
+ });
656
+ }
657
+
658
+ if (manifest.hostFrameworkStatus?.reasonCode !== 'ios_host_framework_validated') {
659
+ return finalizeIosBuildFailure({
660
+ manifest,
661
+ manifestPath,
662
+ buildStatus,
663
+ reasonCode: manifest.hostFrameworkStatus?.reasonCode || 'ios_host_framework_placeholder',
664
+ outRoot,
665
+ detail: 'A validated iOS host xcframework is required before build/archive/export can run.',
666
+ executedPhases,
667
+ outputs,
668
+ derivedDataPath,
669
+ exportOptionsPath: null,
670
+ });
671
+ }
672
+
673
+ if (!existsSync(join(projectBundlePath, IOS_XCODE_PROJECT_FILE))) {
674
+ return finalizeIosBuildFailure({
675
+ manifest,
676
+ manifestPath,
677
+ buildStatus,
678
+ reasonCode: 'ios_xcode_project_missing',
679
+ outRoot,
680
+ detail: `Missing generated Xcode project at ${projectBundlePath}.`,
681
+ executedPhases,
682
+ outputs,
683
+ derivedDataPath,
684
+ exportOptionsPath: null,
685
+ });
686
+ }
687
+
688
+ const frameworkSlices = validateHostFrameworkSlices(hostFrameworkRoot);
689
+ let exportOptionsPath = null;
690
+
691
+ try {
692
+ if (operations.simulator) {
693
+ executeXcodebuildPhase({
694
+ phase: 'build-simulator',
695
+ outRoot,
696
+ spawnSyncImpl,
697
+ executablePath: toolchain.executablePath,
698
+ environment,
699
+ args: buildIosCommandArgs({
700
+ projectBundlePath,
701
+ identity: manifest.identity,
702
+ sdk: 'iphonesimulator',
703
+ derivedDataPath,
704
+ signing,
705
+ signBuild: false,
706
+ }),
707
+ });
708
+ synchronizeBuiltApp({
709
+ sourceAppPath: resolveRequiredPath(
710
+ join(
711
+ derivedDataPath,
712
+ 'Build',
713
+ 'Products',
714
+ `${IOS_BUILD_CONFIGURATION}-iphonesimulator`,
715
+ IOS_XCODE_PRODUCT_NAME,
716
+ ),
717
+ 'simulator build output',
718
+ ),
719
+ outputAppPath: join(outRoot, manifest.artifacts.buildSimulatorApp),
720
+ stagingRoot,
721
+ frameworkSlicePath: frameworkSlices.simulator,
722
+ });
723
+ buildStatus.simulator = 'built';
724
+ outputs.simulatorApp = join(outRoot, manifest.artifacts.buildSimulatorApp);
725
+ executedPhases.push('build-simulator');
726
+ }
727
+
728
+ if ((operations.device || operations.archive || operations.export) && !signing.configured) {
729
+ return finalizeIosBuildFailure({
730
+ manifest,
731
+ manifestPath,
732
+ buildStatus,
733
+ reasonCode: signing.reasonCode,
734
+ outRoot,
735
+ detail: 'Device build, archive, and export require configured signing state.',
736
+ executedPhases,
737
+ outputs,
738
+ derivedDataPath,
739
+ exportOptionsPath,
740
+ });
741
+ }
742
+
743
+ if (operations.device) {
744
+ executeXcodebuildPhase({
745
+ phase: 'build-device',
746
+ outRoot,
747
+ spawnSyncImpl,
748
+ executablePath: toolchain.executablePath,
749
+ environment,
750
+ args: buildIosCommandArgs({
751
+ projectBundlePath,
752
+ identity: manifest.identity,
753
+ sdk: 'iphoneos',
754
+ derivedDataPath,
755
+ signing,
756
+ signBuild: true,
757
+ }),
758
+ });
759
+ synchronizeBuiltApp({
760
+ sourceAppPath: resolveRequiredPath(
761
+ join(
762
+ derivedDataPath,
763
+ 'Build',
764
+ 'Products',
765
+ `${IOS_BUILD_CONFIGURATION}-iphoneos`,
766
+ IOS_XCODE_PRODUCT_NAME,
767
+ ),
768
+ 'device build output',
769
+ ),
770
+ outputAppPath: join(outRoot, manifest.artifacts.buildDeviceApp),
771
+ stagingRoot,
772
+ frameworkSlicePath: frameworkSlices.device,
773
+ });
774
+ buildStatus.device = 'built';
775
+ outputs.deviceApp = join(outRoot, manifest.artifacts.buildDeviceApp);
776
+ executedPhases.push('build-device');
777
+ }
778
+
779
+ if (operations.archive) {
780
+ executeXcodebuildPhase({
781
+ phase: 'archive',
782
+ outRoot,
783
+ spawnSyncImpl,
784
+ executablePath: toolchain.executablePath,
785
+ environment,
786
+ args: archiveIosCommandArgs({
787
+ projectBundlePath,
788
+ identity: manifest.identity,
789
+ archivePath: join(outRoot, manifest.artifacts.archive),
790
+ derivedDataPath,
791
+ signing,
792
+ }),
793
+ });
794
+ const archiveAppPath = resolveArchiveApplicationPath(join(outRoot, manifest.artifacts.archive));
795
+ injectBundledRuntimeIntoApp({
796
+ appPath: archiveAppPath,
797
+ stagingRoot,
798
+ frameworkSlicePath: frameworkSlices.device,
799
+ });
800
+ buildStatus.archive = 'built';
801
+ outputs.archive = join(outRoot, manifest.artifacts.archive);
802
+ executedPhases.push('archive');
803
+ }
804
+
805
+ if (operations.export) {
806
+ const archivePath = join(outRoot, manifest.artifacts.archive);
807
+ if (!existsSync(archivePath)) {
808
+ return finalizeIosBuildFailure({
809
+ manifest,
810
+ manifestPath,
811
+ buildStatus,
812
+ reasonCode: 'ios_archive_missing',
813
+ outRoot,
814
+ detail: `Cannot export without archive: ${archivePath}`,
815
+ executedPhases,
816
+ outputs,
817
+ derivedDataPath,
818
+ exportOptionsPath,
819
+ });
820
+ }
821
+ exportOptionsPath = writeIosExportOptionsPlist({
822
+ outRoot,
823
+ signing,
824
+ exportMethod: cleanString(options.exportMethod)
825
+ || cleanString(environment.AURA_IOS_EXPORT_METHOD)
826
+ || 'development',
827
+ });
828
+ const exportStagingRoot = join(outRoot, 'export', '.xcodebuild');
829
+ rmSync(exportStagingRoot, { recursive: true, force: true });
830
+ mkdirSync(exportStagingRoot, { recursive: true });
831
+ executeXcodebuildPhase({
832
+ phase: 'export',
833
+ outRoot,
834
+ spawnSyncImpl,
835
+ executablePath: toolchain.executablePath,
836
+ environment,
837
+ args: exportIosCommandArgs({
838
+ archivePath,
839
+ exportRoot: exportStagingRoot,
840
+ exportOptionsPath,
841
+ }),
842
+ });
843
+ const sourceIpaPath = resolveExportedIpaPath(exportStagingRoot);
844
+ const outputIpaPath = join(outRoot, manifest.artifacts.exportIpa);
845
+ mkdirSync(dirnameSafe(outputIpaPath), { recursive: true });
846
+ cpSync(sourceIpaPath, outputIpaPath, { force: true });
847
+ buildStatus.export = 'built';
848
+ outputs.exportIpa = outputIpaPath;
849
+ executedPhases.push('export');
850
+ }
851
+ } catch (error) {
852
+ return finalizeIosBuildFailure({
853
+ manifest,
854
+ manifestPath,
855
+ buildStatus,
856
+ reasonCode: error?.reasonCode || 'ios_xcodebuild_failed',
857
+ outRoot,
858
+ detail: error instanceof Error ? error.message : String(error),
859
+ executedPhases,
860
+ outputs,
861
+ derivedDataPath,
862
+ exportOptionsPath,
863
+ });
864
+ }
865
+
866
+ manifest.buildStatus = {
867
+ simulator: buildStatus.simulator,
868
+ device: buildStatus.device,
869
+ archive: buildStatus.archive,
870
+ export: buildStatus.export,
871
+ reasonCode: 'ios_xcodebuild_complete',
872
+ executedPhases,
873
+ derivedDataPath: relativeToRootOrAbsolute(outRoot, derivedDataPath),
874
+ exportOptionsPath: exportOptionsPath
875
+ ? relativeToRootOrAbsolute(outRoot, exportOptionsPath)
876
+ : null,
877
+ };
878
+ writeCanonicalJson(manifestPath, manifest);
879
+
880
+ return {
881
+ ok: true,
882
+ manifestPath,
883
+ manifest,
884
+ toolchain,
885
+ signing,
886
+ outputs,
887
+ derivedDataPath,
888
+ exportOptionsPath,
889
+ };
890
+ }
891
+
892
+ function normalizeIdentity(identity) {
893
+ const appName = cleanString(identity.appName) || 'AuraJSGame';
894
+ return {
895
+ appName,
896
+ bundleId: cleanString(identity.bundleId) || `com.aurajs.${slugify(appName)}`,
897
+ version: cleanString(identity.version) || '0.1.0',
898
+ buildNumber: cleanString(identity.buildNumber) || '1',
899
+ };
900
+ }
901
+
902
+ function normalizeIosOperations(value) {
903
+ const requested = Array.isArray(value) && value.length > 0
904
+ ? value
905
+ : ['simulator', 'device', 'archive', 'export'];
906
+ const set = new Set(
907
+ requested
908
+ .map((entry) => String(entry || '').trim().toLowerCase())
909
+ .filter(Boolean),
910
+ );
911
+ return {
912
+ simulator: set.has('simulator'),
913
+ device: set.has('device'),
914
+ archive: set.has('archive'),
915
+ export: set.has('export'),
916
+ };
917
+ }
918
+
919
+ function buildIosCommandArgs({
920
+ projectBundlePath,
921
+ identity,
922
+ sdk,
923
+ derivedDataPath,
924
+ signing,
925
+ signBuild,
926
+ }) {
927
+ const args = [
928
+ '-project',
929
+ projectBundlePath,
930
+ '-scheme',
931
+ IOS_XCODE_SCHEME_NAME,
932
+ '-configuration',
933
+ IOS_BUILD_CONFIGURATION,
934
+ '-sdk',
935
+ sdk,
936
+ '-derivedDataPath',
937
+ derivedDataPath,
938
+ `PRODUCT_BUNDLE_IDENTIFIER=${identity.bundleId}`,
939
+ `MARKETING_VERSION=${identity.version}`,
940
+ `CURRENT_PROJECT_VERSION=${identity.buildNumber}`,
941
+ ];
942
+ if (sdk === 'iphonesimulator') {
943
+ args.push('-destination', 'generic/platform=iOS Simulator');
944
+ } else {
945
+ args.push('-destination', 'generic/platform=iOS');
946
+ }
947
+ if (signBuild) {
948
+ if (signing.teamId) {
949
+ args.push(`DEVELOPMENT_TEAM=${signing.teamId}`);
950
+ }
951
+ if (signing.codeSignIdentity) {
952
+ args.push(`CODE_SIGN_IDENTITY=${signing.codeSignIdentity}`);
953
+ }
954
+ } else {
955
+ args.push('CODE_SIGNING_ALLOWED=NO', 'CODE_SIGNING_REQUIRED=NO');
956
+ }
957
+ args.push('build');
958
+ return args;
959
+ }
960
+
961
+ function archiveIosCommandArgs({
962
+ projectBundlePath,
963
+ identity,
964
+ archivePath,
965
+ derivedDataPath,
966
+ signing,
967
+ }) {
968
+ const args = [
969
+ '-project',
970
+ projectBundlePath,
971
+ '-scheme',
972
+ IOS_XCODE_SCHEME_NAME,
973
+ '-configuration',
974
+ IOS_BUILD_CONFIGURATION,
975
+ '-sdk',
976
+ 'iphoneos',
977
+ '-destination',
978
+ 'generic/platform=iOS',
979
+ '-archivePath',
980
+ archivePath,
981
+ '-derivedDataPath',
982
+ derivedDataPath,
983
+ `PRODUCT_BUNDLE_IDENTIFIER=${identity.bundleId}`,
984
+ `MARKETING_VERSION=${identity.version}`,
985
+ `CURRENT_PROJECT_VERSION=${identity.buildNumber}`,
986
+ ];
987
+ if (signing.teamId) {
988
+ args.push(`DEVELOPMENT_TEAM=${signing.teamId}`);
989
+ }
990
+ if (signing.codeSignIdentity) {
991
+ args.push(`CODE_SIGN_IDENTITY=${signing.codeSignIdentity}`);
992
+ }
993
+ args.push('archive');
994
+ return args;
995
+ }
996
+
997
+ function exportIosCommandArgs({ archivePath, exportRoot, exportOptionsPath }) {
998
+ return [
999
+ '-exportArchive',
1000
+ '-archivePath',
1001
+ archivePath,
1002
+ '-exportPath',
1003
+ exportRoot,
1004
+ '-exportOptionsPlist',
1005
+ exportOptionsPath,
1006
+ ];
1007
+ }
1008
+
1009
+ function writeIosExportOptionsPlist({ outRoot, signing, exportMethod }) {
1010
+ const exportRoot = join(outRoot, 'export');
1011
+ mkdirSync(exportRoot, { recursive: true });
1012
+ const exportOptionsPath = join(exportRoot, IOS_EXPORT_OPTIONS_FILE);
1013
+ const lines = [
1014
+ '<?xml version="1.0" encoding="UTF-8"?>',
1015
+ '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
1016
+ '<plist version="1.0">',
1017
+ '<dict>',
1018
+ ' <key>compileBitcode</key>',
1019
+ ' <false/>',
1020
+ ' <key>method</key>',
1021
+ ` <string>${escapeXml(exportMethod)}</string>`,
1022
+ ' <key>signingStyle</key>',
1023
+ ' <string>automatic</string>',
1024
+ ];
1025
+ if (signing.teamId) {
1026
+ lines.push(' <key>teamID</key>');
1027
+ lines.push(` <string>${escapeXml(signing.teamId)}</string>`);
1028
+ }
1029
+ lines.push('</dict>');
1030
+ lines.push('</plist>');
1031
+ lines.push('');
1032
+ writeFileSync(exportOptionsPath, lines.join('\n'), 'utf8');
1033
+ return exportOptionsPath;
1034
+ }
1035
+
1036
+ function escapeXml(value) {
1037
+ return String(value)
1038
+ .replaceAll('&', '&amp;')
1039
+ .replaceAll('<', '&lt;')
1040
+ .replaceAll('>', '&gt;')
1041
+ .replaceAll('"', '&quot;');
1042
+ }
1043
+
1044
+ function executeXcodebuildPhase({
1045
+ phase,
1046
+ outRoot,
1047
+ spawnSyncImpl,
1048
+ executablePath,
1049
+ environment,
1050
+ args,
1051
+ }) {
1052
+ const result = spawnSyncImpl(executablePath, args, {
1053
+ cwd: outRoot,
1054
+ encoding: 'utf8',
1055
+ env: environment,
1056
+ });
1057
+ if (result.status !== 0) {
1058
+ const message = String(result.stderr || result.stdout || '').trim() || `${phase} failed`;
1059
+ const error = new Error(message);
1060
+ error.reasonCode = `ios_${phase.replaceAll('-', '_')}_failed`;
1061
+ throw error;
1062
+ }
1063
+ }
1064
+
1065
+ function synchronizeBuiltApp({
1066
+ sourceAppPath,
1067
+ outputAppPath,
1068
+ stagingRoot,
1069
+ frameworkSlicePath,
1070
+ }) {
1071
+ replaceDirectory(sourceAppPath, outputAppPath);
1072
+ injectBundledRuntimeIntoApp({
1073
+ appPath: outputAppPath,
1074
+ stagingRoot,
1075
+ frameworkSlicePath,
1076
+ });
1077
+ }
1078
+
1079
+ function resolveArchiveApplicationPath(archivePath) {
1080
+ const applicationsRoot = resolveRequiredPath(
1081
+ join(archivePath, 'Products', 'Applications'),
1082
+ 'archive applications root',
1083
+ );
1084
+ const entries = readdirSync(applicationsRoot, { withFileTypes: true })
1085
+ .filter((entry) => entry.isDirectory() && entry.name.endsWith('.app'));
1086
+ if (entries.length === 0) {
1087
+ throw Object.assign(new Error(`archive did not contain an .app under ${applicationsRoot}`), {
1088
+ reasonCode: 'ios_archive_missing',
1089
+ });
1090
+ }
1091
+ return join(applicationsRoot, entries[0].name);
1092
+ }
1093
+
1094
+ function resolveExportedIpaPath(exportRoot) {
1095
+ const entries = readdirSync(resolveRequiredPath(exportRoot, 'exportRoot'), { withFileTypes: true })
1096
+ .filter((entry) => entry.isFile() && entry.name.endsWith('.ipa'));
1097
+ if (entries.length === 0) {
1098
+ throw Object.assign(new Error(`export did not emit an .ipa under ${exportRoot}`), {
1099
+ reasonCode: 'ios_export_ipa_missing',
1100
+ });
1101
+ }
1102
+ return join(exportRoot, entries[0].name);
1103
+ }
1104
+
1105
+ function injectBundledRuntimeIntoApp({ appPath, stagingRoot, frameworkSlicePath }) {
1106
+ replaceDirectory(stagingRoot, join(appPath, IOS_RESOURCE_ROOT_NAME));
1107
+ replaceDirectory(frameworkSlicePath, join(appPath, 'Frameworks', IOS_HOST_FRAMEWORK_DIRECTORY));
1108
+ }
1109
+
1110
+ function finalizeIosBuildFailure({
1111
+ manifest,
1112
+ manifestPath,
1113
+ buildStatus,
1114
+ reasonCode,
1115
+ outRoot,
1116
+ detail,
1117
+ executedPhases,
1118
+ outputs,
1119
+ derivedDataPath,
1120
+ exportOptionsPath,
1121
+ }) {
1122
+ manifest.buildStatus = {
1123
+ simulator: buildStatus.simulator,
1124
+ device: buildStatus.device,
1125
+ archive: buildStatus.archive,
1126
+ export: buildStatus.export,
1127
+ reasonCode,
1128
+ executedPhases,
1129
+ derivedDataPath: relativeToRootOrAbsolute(outRoot, derivedDataPath),
1130
+ exportOptionsPath: exportOptionsPath
1131
+ ? relativeToRootOrAbsolute(outRoot, exportOptionsPath)
1132
+ : null,
1133
+ };
1134
+ writeCanonicalJson(manifestPath, manifest);
1135
+ return {
1136
+ ok: false,
1137
+ reasonCode,
1138
+ detail,
1139
+ manifestPath,
1140
+ manifest,
1141
+ toolchain: manifest.toolchain,
1142
+ signing: manifest.signing,
1143
+ outputs,
1144
+ derivedDataPath,
1145
+ exportOptionsPath,
1146
+ };
1147
+ }
1148
+
1149
+ function slugify(input) {
1150
+ return String(input || '')
1151
+ .trim()
1152
+ .toLowerCase()
1153
+ .replace(/[^a-z0-9]+/g, '-')
1154
+ .replace(/^-+|-+$/g, '')
1155
+ || 'game';
1156
+ }
1157
+
1158
+ function cleanString(value) {
1159
+ return typeof value === 'string' && value.trim() ? value.trim() : null;
1160
+ }
1161
+
1162
+ function resolveRequiredPath(value, label) {
1163
+ if (!value) {
1164
+ throw new Error(`ios build requires ${label}.`);
1165
+ }
1166
+ const resolved = resolve(value);
1167
+ if (!existsSync(resolved)) {
1168
+ throw new Error(`ios build requires existing ${label}: ${resolved}`);
1169
+ }
1170
+ return resolved;
1171
+ }
1172
+
1173
+ function resolveHostFrameworkContract({ projectRoot, hostFrameworkPath, distRoot }) {
1174
+ let sourcePath = null;
1175
+ let sourceKind = null;
1176
+ let reasonCode = 'ios_host_framework_validated';
1177
+
1178
+ if (hostFrameworkPath) {
1179
+ sourcePath = resolveRequiredPath(hostFrameworkPath, 'hostFrameworkPath');
1180
+ sourceKind = 'explicit_input';
1181
+ } else {
1182
+ const distFrameworkPath = join(resolve(distRoot || DIST_ROOT), IOS_HOST_XCFRAMEWORK_NAME);
1183
+ if (existsSync(distFrameworkPath)) {
1184
+ sourcePath = resolveRequiredPath(distFrameworkPath, 'distRoot/aurajs-host.xcframework');
1185
+ sourceKind = 'platform_dist';
1186
+ }
1187
+ }
1188
+
1189
+ if (!sourcePath) {
1190
+ return {
1191
+ sourcePath: HOST_XCFRAMEWORK_ROOT,
1192
+ sourceKind: 'placeholder_scaffold',
1193
+ reasonCode: 'ios_host_framework_placeholder',
1194
+ validatedSlices: null,
1195
+ };
1196
+ }
1197
+
1198
+ const validatedSlices = validateHostFrameworkSlices(sourcePath);
1199
+ return {
1200
+ sourcePath,
1201
+ sourceKind,
1202
+ reasonCode,
1203
+ validatedSlices,
1204
+ };
1205
+ }
1206
+
1207
+ function validateHostFrameworkSlices(hostFrameworkPath) {
1208
+ resolveRequiredPath(join(hostFrameworkPath, 'Info.plist'), 'hostFrameworkPath/Info.plist');
1209
+ const deviceFrameworkPath = resolveRequiredPath(
1210
+ join(
1211
+ hostFrameworkPath,
1212
+ IOS_DEVICE_LIBRARY_IDENTIFIER,
1213
+ IOS_HOST_FRAMEWORK_DIRECTORY,
1214
+ IOS_HOST_FRAMEWORK_BINARY,
1215
+ ),
1216
+ 'hostFrameworkPath device slice binary',
1217
+ );
1218
+ const simulatorFrameworkPath = resolveRequiredPath(
1219
+ join(
1220
+ hostFrameworkPath,
1221
+ IOS_SIMULATOR_LIBRARY_IDENTIFIER,
1222
+ IOS_HOST_FRAMEWORK_DIRECTORY,
1223
+ IOS_HOST_FRAMEWORK_BINARY,
1224
+ ),
1225
+ 'hostFrameworkPath simulator slice binary',
1226
+ );
1227
+
1228
+ return {
1229
+ device: dirnameSafe(deviceFrameworkPath),
1230
+ simulator: dirnameSafe(simulatorFrameworkPath),
1231
+ };
1232
+ }
1233
+
1234
+ function embedHostFrameworkSlices({ contract, deviceAppPath, simulatorAppPath }) {
1235
+ if (!contract.validatedSlices) {
1236
+ return {
1237
+ device: null,
1238
+ simulator: null,
1239
+ };
1240
+ }
1241
+
1242
+ const deviceFrameworkPath = join(deviceAppPath, 'Frameworks', IOS_HOST_FRAMEWORK_DIRECTORY);
1243
+ const simulatorFrameworkPath = join(
1244
+ simulatorAppPath,
1245
+ 'Frameworks',
1246
+ IOS_HOST_FRAMEWORK_DIRECTORY,
1247
+ );
1248
+ copyDirectory(contract.validatedSlices.device, deviceFrameworkPath);
1249
+ copyDirectory(contract.validatedSlices.simulator, simulatorFrameworkPath);
1250
+ return {
1251
+ device: deviceFrameworkPath,
1252
+ simulator: simulatorFrameworkPath,
1253
+ };
1254
+ }
1255
+
1256
+ function writeGeneratedXcodeProject(templateOutRoot) {
1257
+ const projectRoot = join(templateOutRoot, IOS_XCODE_PROJECT_NAME);
1258
+ const projectFilePath = join(projectRoot, IOS_XCODE_PROJECT_FILE);
1259
+ const schemePath = join(projectRoot, 'xcshareddata', 'xcschemes', `${IOS_XCODE_SCHEME_NAME}.xcscheme`);
1260
+ mkdirSync(dirnameSafe(projectFilePath), { recursive: true });
1261
+ mkdirSync(dirnameSafe(schemePath), { recursive: true });
1262
+ writeFileSync(projectFilePath, IOS_GENERATED_PROJECT_PBXPROJ, 'utf8');
1263
+ writeFileSync(schemePath, IOS_GENERATED_XCSCHEME, 'utf8');
1264
+ return projectRoot;
1265
+ }
1266
+
1267
+ function dirnameSafe(path) {
1268
+ return resolve(path, '..');
1269
+ }
1270
+
1271
+ function replaceDirectory(sourceRoot, destRoot) {
1272
+ rmSync(destRoot, { recursive: true, force: true });
1273
+ copyDirectory(sourceRoot, destRoot);
1274
+ }
1275
+
1276
+ function copyDirectory(sourceRoot, destRoot) {
1277
+ mkdirSync(destRoot, { recursive: true });
1278
+ cpSync(sourceRoot, destRoot, {
1279
+ recursive: true,
1280
+ dereference: false,
1281
+ force: true,
1282
+ });
1283
+ }
1284
+
1285
+ function relativePosix(fromRoot, targetPath) {
1286
+ return relative(fromRoot, targetPath).replace(/\\/g, '/');
1287
+ }
1288
+
1289
+ function relativeToRootOrAbsolute(root, targetPath) {
1290
+ const rel = relative(root, targetPath).replace(/\\/g, '/');
1291
+ if (!rel || (!rel.startsWith('../') && rel !== '..')) {
1292
+ return rel || '.';
1293
+ }
1294
+ return targetPath;
1295
+ }
1296
+
1297
+ function writeCanonicalJson(path, value) {
1298
+ writeFileSync(path, `${JSON.stringify(sortKeysDeep(value), null, 2)}\n`, 'utf8');
1299
+ }
1300
+
1301
+ function sortKeysDeep(value) {
1302
+ if (Array.isArray(value)) {
1303
+ return value.map(sortKeysDeep);
1304
+ }
1305
+ if (value && typeof value === 'object') {
1306
+ return Object.fromEntries(
1307
+ Object.keys(value)
1308
+ .sort()
1309
+ .map((key) => [key, sortKeysDeep(value[key])]),
1310
+ );
1311
+ }
1312
+ return value;
1313
+ }
1314
+
1315
+ export function readIosBuildManifest(path) {
1316
+ return JSON.parse(readFileSync(resolveRequiredPath(path, 'manifestPath'), 'utf8'));
1317
+ }
1318
+
1319
+ export {
1320
+ IOS_BUILD_MANIFEST_SCHEMA,
1321
+ IOS_HOST_XCFRAMEWORK_NAME,
1322
+ IOS_RESOURCE_ROOT_NAME,
1323
+ };