@legendapp/spark 0.0.1-next.2 → 0.0.1-next.4

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 (422) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -4
  3. package/ai-codex.ts +1 -0
  4. package/ai.ts +1 -0
  5. package/app-documents.ts +1 -0
  6. package/camera.ts +13 -0
  7. package/config-plugin.d.cts +2 -0
  8. package/contracts.ts +2 -0
  9. package/diagnostics.ts +1 -0
  10. package/expo-config.d.cts +1 -0
  11. package/metro.cjs +4 -1
  12. package/metro.d.cts +12 -0
  13. package/native.cjs +3 -1
  14. package/native.d.cts +6 -0
  15. package/package.json +93 -15
  16. package/patches/camera/react-native-nitro-image.patch +320 -0
  17. package/patches/camera/react-native-nitro-modules.patch +50 -0
  18. package/patches/camera/react-native-vision-camera.patch +2662 -0
  19. package/patches/camera/upstream.json +22 -0
  20. package/patches/dependencies.json +8 -0
  21. package/patches/react-native-enriched-markdown@1.0.2.patch +8684 -0
  22. package/postinstall.cjs +1 -0
  23. package/schema.json +276 -58
  24. package/settings-observable.ts +1 -0
  25. package/settings-window.ts +1 -0
  26. package/shortcuts-commands.ts +1 -0
  27. package/shortcuts-keyboard.ts +3 -0
  28. package/ui-classnames.ts +1 -0
  29. package/ui-glass.ts +1 -0
  30. package/ui-search.ts +1 -0
  31. package/ui-sidebar.ts +1 -0
  32. package/ui-split-view.ts +1 -0
  33. package/ui-swipe.ts +1 -0
  34. package/ui-symbol.ts +1 -0
  35. package/vendor/node_modules/@legendapp/spark-ai/package.json +19 -0
  36. package/vendor/node_modules/@legendapp/spark-ai/src/availability.ts +17 -0
  37. package/vendor/node_modules/@legendapp/spark-ai/src/index.ts +15 -0
  38. package/vendor/node_modules/@legendapp/spark-ai/src/invocations.ts +34 -0
  39. package/vendor/node_modules/@legendapp/spark-ai/src/output.ts +62 -0
  40. package/vendor/node_modules/@legendapp/spark-ai/src/run.ts +12 -0
  41. package/vendor/node_modules/@legendapp/spark-ai/src/types.ts +16 -0
  42. package/vendor/node_modules/@legendapp/spark-audio/macos/RNSparkAudio.h +2 -1
  43. package/vendor/node_modules/@legendapp/spark-audio/macos/RNSparkAudio.mm +126 -24
  44. package/vendor/node_modules/@legendapp/spark-audio/package.json +5 -2
  45. package/vendor/node_modules/@legendapp/spark-audio/src/NativeSparkAudio.ts +5 -1
  46. package/vendor/node_modules/@legendapp/spark-audio/src/desktop.ts +36 -32
  47. package/vendor/node_modules/@legendapp/spark-audio/src/events.ts +11 -0
  48. package/vendor/node_modules/@legendapp/spark-audio/src/hooks.ts +65 -0
  49. package/vendor/node_modules/@legendapp/spark-audio/src/index.web.ts +92 -33
  50. package/vendor/node_modules/@legendapp/spark-audio/src/media-session-unavailable.ts +6 -4
  51. package/vendor/node_modules/@legendapp/spark-audio/src/media-session.ts +52 -19
  52. package/vendor/node_modules/@legendapp/spark-audio/src/media-session.web.ts +18 -10
  53. package/vendor/node_modules/@legendapp/spark-audio/src/media-types.ts +40 -13
  54. package/vendor/node_modules/@legendapp/spark-audio/src/mobile.ts +40 -32
  55. package/vendor/node_modules/@legendapp/spark-audio/src/player.ts +97 -0
  56. package/vendor/node_modules/@legendapp/spark-audio/src/status-listeners.ts +21 -15
  57. package/vendor/node_modules/@legendapp/spark-audio/src/types.ts +9 -4
  58. package/vendor/node_modules/@legendapp/spark-audio/windows/SparkAudio/SparkAudio.h +67 -20
  59. package/vendor/node_modules/@legendapp/spark-auth-session/package.json +4 -3
  60. package/vendor/node_modules/@legendapp/spark-auth-session/src/core.ts +60 -42
  61. package/vendor/node_modules/@legendapp/spark-auth-session/src/index.ts +28 -12
  62. package/vendor/node_modules/@legendapp/spark-auth-session/src/mobile.ts +97 -41
  63. package/vendor/node_modules/@legendapp/spark-auth-session/src/types.ts +20 -9
  64. package/vendor/node_modules/@legendapp/spark-cli/dist/add-desktop.js +50 -7
  65. package/vendor/node_modules/@legendapp/spark-cli/dist/build-mode.js +1 -1
  66. package/vendor/node_modules/@legendapp/spark-cli/dist/build.js +145 -59
  67. package/vendor/node_modules/@legendapp/spark-cli/dist/cli-arguments.js +61 -0
  68. package/vendor/node_modules/@legendapp/spark-cli/dist/commands.js +10 -4
  69. package/vendor/node_modules/@legendapp/spark-cli/dist/create.js +37 -8
  70. package/vendor/node_modules/@legendapp/spark-cli/dist/credentials.js +86 -25
  71. package/vendor/node_modules/@legendapp/spark-cli/dist/dependency-pins.js +132 -0
  72. package/vendor/node_modules/@legendapp/spark-cli/dist/dev-command.js +13 -4
  73. package/vendor/node_modules/@legendapp/spark-cli/dist/dev.js +13 -10
  74. package/vendor/node_modules/@legendapp/spark-cli/dist/errors.js +100 -0
  75. package/vendor/node_modules/@legendapp/spark-cli/dist/examples.js +2 -2
  76. package/vendor/node_modules/@legendapp/spark-cli/dist/expo-dev-patch.cjs +4 -2
  77. package/vendor/node_modules/@legendapp/spark-cli/dist/expo-metro.cjs +1 -1
  78. package/vendor/node_modules/@legendapp/spark-cli/dist/expo-native.cjs +5 -1
  79. package/vendor/node_modules/@legendapp/spark-cli/dist/expo-node.js +3 -3
  80. package/vendor/node_modules/@legendapp/spark-cli/dist/helpers.js +1 -1
  81. package/vendor/node_modules/@legendapp/spark-cli/dist/index.js +52 -44
  82. package/vendor/node_modules/@legendapp/spark-cli/dist/json.js +16 -0
  83. package/vendor/node_modules/@legendapp/spark-cli/dist/local.js +1 -1
  84. package/vendor/node_modules/@legendapp/spark-cli/dist/metro.cjs +26 -5
  85. package/vendor/node_modules/@legendapp/spark-cli/dist/native-metadata.js +26 -0
  86. package/vendor/node_modules/@legendapp/spark-cli/dist/native-patch-preflight.js +86 -0
  87. package/vendor/node_modules/@legendapp/spark-cli/dist/native-preparation.js +88 -0
  88. package/vendor/node_modules/@legendapp/spark-cli/dist/notary-profiles.js +75 -0
  89. package/vendor/node_modules/@legendapp/spark-cli/dist/package.js +4 -2
  90. package/vendor/node_modules/@legendapp/spark-cli/dist/platform.js +16 -2
  91. package/vendor/node_modules/@legendapp/spark-cli/dist/process.js +7 -0
  92. package/vendor/node_modules/@legendapp/spark-cli/dist/project.js +90 -32
  93. package/vendor/node_modules/@legendapp/spark-cli/dist/release.js +86 -5
  94. package/vendor/node_modules/@legendapp/spark-cli/dist/release.json +23 -18
  95. package/vendor/node_modules/@legendapp/spark-cli/dist/runner-install.js +145 -31
  96. package/vendor/node_modules/@legendapp/spark-cli/dist/signing.js +4 -3
  97. package/vendor/node_modules/@legendapp/spark-cli/dist/universal.cjs +2 -1
  98. package/vendor/node_modules/@legendapp/spark-cli/dist/updates.js +41 -4
  99. package/vendor/node_modules/@legendapp/spark-cli/dist/windows.js +5 -9
  100. package/vendor/node_modules/@legendapp/spark-cli/package.json +7 -6
  101. package/vendor/node_modules/@legendapp/spark-cli/templates/blank-typescript/App.tsx +6 -12
  102. package/vendor/node_modules/@legendapp/spark-cli/templates/blank-typescript/desktop.config.json +5 -3
  103. package/vendor/node_modules/@legendapp/spark-cli/templates/blank-typescript/package.json +12 -10
  104. package/vendor/node_modules/@legendapp/spark-cli/templates/diff-lite/Git.macos.tsx +2 -2
  105. package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/Integration.macos.tsx +23 -21
  106. package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/Integration.windows.tsx +23 -21
  107. package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/io.desktop.ts +11 -8
  108. package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/io.macos.ts +3 -3
  109. package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/Lifecycle.desktop.tsx +8 -14
  110. package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/OpenFiles.desktop.tsx +5 -10
  111. package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/io.desktop.ts +11 -8
  112. package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/io.macos.ts +3 -3
  113. package/vendor/node_modules/@legendapp/spark-cli/templates/music-lite/assets.desktop.ts +2 -2
  114. package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/Activation.desktop.tsx +2 -2
  115. package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/Desktop.desktop.ts +37 -15
  116. package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/session.ts +5 -6
  117. package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/window-session.ts +5 -4
  118. package/vendor/node_modules/@legendapp/spark-cli/templates/universal/desktop.config.json +5 -3
  119. package/vendor/node_modules/@legendapp/spark-cli/templates/universal/metro.config.js +1 -1
  120. package/vendor/node_modules/@legendapp/spark-cli/templates/universal/package.json +14 -12
  121. package/vendor/node_modules/@legendapp/spark-cli/templates/universal/react-native.config.js +1 -1
  122. package/vendor/node_modules/@legendapp/spark-cli/templates/windows/package.json +14 -12
  123. package/vendor/node_modules/@legendapp/spark-cli/templates/windows/react-native.config.js +1 -1
  124. package/vendor/node_modules/@legendapp/spark-clipboard/macos/RNDesktopClipboard.mm +10 -16
  125. package/vendor/node_modules/@legendapp/spark-clipboard/package.json +2 -2
  126. package/vendor/node_modules/@legendapp/spark-clipboard/src/NativeDesktopClipboard.ts +1 -1
  127. package/vendor/node_modules/@legendapp/spark-clipboard/src/desktop.ts +55 -31
  128. package/vendor/node_modules/@legendapp/spark-clipboard/src/expo.ts +21 -11
  129. package/vendor/node_modules/@legendapp/spark-clipboard/src/options.ts +8 -0
  130. package/vendor/node_modules/@legendapp/spark-clipboard/src/types.ts +10 -0
  131. package/vendor/node_modules/@legendapp/spark-clipboard/windows/SparkClipboard/SparkClipboard.h +38 -15
  132. package/vendor/node_modules/@legendapp/spark-clipboard/windows/SparkClipboard/SparkClipboard.vcxproj +2 -0
  133. package/vendor/node_modules/@legendapp/spark-codex/RNCodex.podspec +22 -0
  134. package/vendor/node_modules/@legendapp/spark-codex/cpp/HybridCodexAppServer.hpp +23 -0
  135. package/vendor/node_modules/@legendapp/spark-codex/cpp/HybridCodexAppServer.mm +1529 -0
  136. package/vendor/node_modules/@legendapp/spark-codex/nitro.json +21 -0
  137. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/.gitattributes +1 -0
  138. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex+autolinking.rb +62 -0
  139. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex-Swift-Cxx-Bridge.cpp +17 -0
  140. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex-Swift-Cxx-Bridge.hpp +27 -0
  141. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex-Swift-Cxx-Umbrella.hpp +38 -0
  142. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodexAutolinking.mm +35 -0
  143. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodexAutolinking.swift +16 -0
  144. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/CodexAvailability.hpp +95 -0
  145. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/CodexRunResult.hpp +99 -0
  146. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/HybridCodexAppServerSpec.cpp +24 -0
  147. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/HybridCodexAppServerSpec.hpp +71 -0
  148. package/vendor/node_modules/@legendapp/spark-codex/package.json +35 -0
  149. package/vendor/node_modules/@legendapp/spark-codex/react-native.config.js +11 -0
  150. package/vendor/node_modules/@legendapp/spark-codex/src/Codex.nitro.ts +30 -0
  151. package/vendor/node_modules/@legendapp/spark-codex/src/index.ts +65 -0
  152. package/vendor/node_modules/@legendapp/spark-codex/src/native.ts +6 -0
  153. package/vendor/node_modules/@legendapp/spark-commands/package.json +21 -0
  154. package/vendor/node_modules/@legendapp/spark-commands/src/bindings.ts +90 -0
  155. package/vendor/node_modules/@legendapp/spark-commands/src/index.tsx +400 -0
  156. package/vendor/node_modules/@legendapp/spark-commands/src/router.ts +138 -0
  157. package/vendor/node_modules/@legendapp/spark-commands/src/storage.ts +20 -0
  158. package/vendor/node_modules/@legendapp/spark-context-menu/macos/RNContextMenu.mm +7 -8
  159. package/vendor/node_modules/@legendapp/spark-context-menu/package.json +4 -3
  160. package/vendor/node_modules/@legendapp/spark-context-menu/src/NativeContextMenu.ts +1 -1
  161. package/vendor/node_modules/@legendapp/spark-context-menu/src/index.ts +26 -26
  162. package/vendor/node_modules/@legendapp/spark-context-menu/windows/SparkContextMenu/SparkContextMenu.h +3 -2
  163. package/vendor/node_modules/@legendapp/spark-desktop-app/RNDesktopApp.podspec +2 -1
  164. package/vendor/node_modules/@legendapp/spark-desktop-app/cpp/SparkBinaryJSI.hpp +89 -0
  165. package/vendor/node_modules/@legendapp/spark-desktop-app/cpp/SparkBinaryWindows.hpp +22 -0
  166. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/RNDesktopApp.mm +13 -7
  167. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkBinaryJSI.h +48 -0
  168. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkDesktop.h +4 -0
  169. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkDesktop.mm +33 -33
  170. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkDesktopError.h +20 -0
  171. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkLifecycle.h +26 -0
  172. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkLifecycle.mm +49 -0
  173. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkQuitCoordinator.h +9 -0
  174. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkQuitCoordinator.mm +70 -0
  175. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkWindow.mm +9 -6
  176. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/recent-documents/RNRecentDocumentController.mm +55 -0
  177. package/vendor/node_modules/@legendapp/spark-desktop-app/package.json +5 -3
  178. package/vendor/node_modules/@legendapp/spark-desktop-app/src/NativeDesktopApp.ts +1 -1
  179. package/vendor/node_modules/@legendapp/spark-desktop-app/src/api.ts +86 -40
  180. package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/accelerator.ts +40 -0
  181. package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/index.ts +56 -0
  182. package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/menu.ts +116 -0
  183. package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/native-buffer.ts +22 -0
  184. package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/path.ts +24 -0
  185. package/vendor/node_modules/@legendapp/spark-desktop-app/src/events.ts +75 -0
  186. package/vendor/node_modules/@legendapp/spark-desktop-app/src/index.ts +2 -0
  187. package/vendor/node_modules/@legendapp/spark-desktop-app/src/index.windows.ts +2 -0
  188. package/vendor/node_modules/@legendapp/spark-desktop-app/src/open-requests.ts +43 -0
  189. package/vendor/node_modules/@legendapp/spark-desktop-app/src/restoration.ts +11 -0
  190. package/vendor/node_modules/@legendapp/spark-desktop-app/src/transport.ts +10 -0
  191. package/vendor/node_modules/@legendapp/spark-desktop-config/app.plugin.cjs +10 -5
  192. package/vendor/node_modules/@legendapp/spark-desktop-config/app.plugin.d.cts +3 -0
  193. package/vendor/node_modules/@legendapp/spark-desktop-config/autolinking.cjs +35 -0
  194. package/vendor/node_modules/@legendapp/spark-desktop-config/config.cjs +18 -3
  195. package/vendor/node_modules/@legendapp/spark-desktop-config/config.d.cts +89 -9
  196. package/vendor/node_modules/@legendapp/spark-desktop-config/expo.cjs +1 -0
  197. package/vendor/node_modules/@legendapp/spark-desktop-config/expo.d.cts +3 -0
  198. package/vendor/node_modules/@legendapp/spark-desktop-config/identity.cjs +3 -2
  199. package/vendor/node_modules/@legendapp/spark-desktop-config/lifecycle.cjs +20 -0
  200. package/vendor/node_modules/@legendapp/spark-desktop-config/native-patches.cjs +106 -0
  201. package/vendor/node_modules/@legendapp/spark-desktop-config/native-patches.d.cts +1 -0
  202. package/vendor/node_modules/@legendapp/spark-desktop-config/package.json +7 -5
  203. package/vendor/node_modules/@legendapp/spark-desktop-config/schema.json +276 -58
  204. package/vendor/node_modules/@legendapp/spark-desktop-config/updates.cjs +1 -0
  205. package/vendor/node_modules/@legendapp/spark-desktop-config/validation.cjs +35 -0
  206. package/vendor/node_modules/@legendapp/spark-desktop-config/windows.plugin.cjs +2 -1
  207. package/vendor/node_modules/@legendapp/spark-desktop-host/AppDelegate.mm +129 -11
  208. package/vendor/node_modules/@legendapp/spark-desktop-host/package.json +2 -2
  209. package/vendor/node_modules/@legendapp/spark-desktop-host/windows/application.inc +277 -121
  210. package/vendor/node_modules/@legendapp/spark-desktop-links/common/AuthLoopback.h +5 -7
  211. package/vendor/node_modules/@legendapp/spark-desktop-links/macos/RNDesktopLinks.mm +10 -9
  212. package/vendor/node_modules/@legendapp/spark-desktop-links/package.json +2 -2
  213. package/vendor/node_modules/@legendapp/spark-desktop-links/src/NativeDesktopLinks.ts +1 -1
  214. package/vendor/node_modules/@legendapp/spark-desktop-links/src/api.ts +27 -33
  215. package/vendor/node_modules/@legendapp/spark-desktop-links/src/expo.ts +3 -4
  216. package/vendor/node_modules/@legendapp/spark-desktop-links/src/native.ts +9 -0
  217. package/vendor/node_modules/@legendapp/spark-desktop-links/windows/SparkLinks/SparkLinks.h +22 -22
  218. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/RNDesktopShortcuts.podspec +1 -0
  219. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/macos/RNDesktopShortcuts.mm +1 -1
  220. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/macos/keyboard-manager/RNKeyboardManager.h +9 -0
  221. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/macos/keyboard-manager/RNKeyboardManager.mm +307 -0
  222. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/package.json +8 -5
  223. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/NativeDesktopShortcuts.ts +1 -1
  224. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/api.ts +39 -14
  225. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/keyboard-manager/NativeKeyboardManager.ts +12 -0
  226. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/keyboard-manager/codes.ts +108 -0
  227. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/keyboard-manager/index.ts +99 -0
  228. package/vendor/node_modules/@legendapp/spark-desktop-windows/RNDesktopWindows.podspec +2 -0
  229. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/RNDesktopWindows.mm +229 -103
  230. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/SparkWindowGeometry.h +63 -0
  231. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/LegendWindowRegistry.h +20 -0
  232. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/LegendWindowRegistry.mm +27 -0
  233. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/RNWindowManager.h +12 -0
  234. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/RNWindowManager.mm +3169 -0
  235. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/RNWindowManagerStartup.mm +31 -0
  236. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/SidebarStartupFallbacks.mm +14 -0
  237. package/vendor/node_modules/@legendapp/spark-desktop-windows/package.json +10 -6
  238. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/NativeDesktopWindowManager.ts +1 -1
  239. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/api.ts +146 -70
  240. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/diagnostics.ts +17 -0
  241. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/index.ts +3 -1
  242. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/index.windows.ts +3 -1
  243. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/macos-adapter.ts +53 -0
  244. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/macos.ts +51 -0
  245. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/transport.ts +41 -0
  246. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/types.ts +140 -0
  247. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/validation.ts +162 -0
  248. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/window-manager/NativeWindowManager.ts +28 -0
  249. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/WindowProvider.tsx +20 -0
  250. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/createWindowsNavigator.tsx +78 -0
  251. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/index.ts +6 -0
  252. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/primaryWindowLifecycle.ts +34 -0
  253. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/types.ts +11 -0
  254. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/usePrimaryWindowLifecycle.ts +18 -0
  255. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/useWindowFocusEffect.ts +17 -0
  256. package/vendor/node_modules/@legendapp/spark-documents/package.json +22 -0
  257. package/vendor/node_modules/@legendapp/spark-documents/src/controller.ts +97 -0
  258. package/vendor/node_modules/@legendapp/spark-documents/src/documentTransition.ts +13 -0
  259. package/vendor/node_modules/@legendapp/spark-documents/src/hooks.ts +139 -0
  260. package/vendor/node_modules/@legendapp/spark-documents/src/index.tsx +50 -0
  261. package/vendor/node_modules/@legendapp/spark-documents/src/reload.ts +39 -0
  262. package/vendor/node_modules/@legendapp/spark-documents/src/requests.ts +15 -0
  263. package/vendor/node_modules/@legendapp/spark-drag-drop/package.json +4 -3
  264. package/vendor/node_modules/@legendapp/spark-drag-drop/src/DesktopDragViewNativeComponent.ts +1 -1
  265. package/vendor/node_modules/@legendapp/spark-drag-drop/src/contracts.ts +73 -18
  266. package/vendor/node_modules/@legendapp/spark-drag-drop/src/index.tsx +58 -15
  267. package/vendor/node_modules/@legendapp/spark-drag-drop/windows/SparkDragDrop/SparkDragDrop.h +14 -8
  268. package/vendor/node_modules/@legendapp/spark-file-dialog/ios/RNFileDialog.mm +34 -121
  269. package/vendor/node_modules/@legendapp/spark-file-dialog/package.json +12 -5
  270. package/vendor/node_modules/@legendapp/spark-file-dialog/src/NativeFileDialog.ts +1 -5
  271. package/vendor/node_modules/@legendapp/spark-file-dialog/src/index.ts +19 -84
  272. package/vendor/node_modules/@legendapp/spark-file-dialog/src/native.ts +12 -0
  273. package/vendor/node_modules/@legendapp/spark-file-dialog/src/options.ts +34 -14
  274. package/vendor/node_modules/@legendapp/spark-file-dialog/src/types.ts +26 -0
  275. package/vendor/node_modules/@legendapp/spark-file-dialog/windows/SparkFileDialog/SparkFileDialog.h +42 -58
  276. package/vendor/node_modules/@legendapp/spark-file-system/RNDesktopFileSystem.podspec +1 -0
  277. package/vendor/node_modules/@legendapp/spark-file-system/macos/RNDesktopFileSystem.mm +32 -21
  278. package/vendor/node_modules/@legendapp/spark-file-system/macos/SparkFileMutations.h +24 -0
  279. package/vendor/node_modules/@legendapp/spark-file-system/macos/SparkFileMutations.mm +215 -0
  280. package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScanner.h +9 -0
  281. package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScanner.mm +82 -0
  282. package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScannerCore.h +47 -0
  283. package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScannerCore.mm +306 -0
  284. package/vendor/node_modules/@legendapp/spark-file-system/package.json +8 -6
  285. package/vendor/node_modules/@legendapp/spark-file-system/src/NativeDesktopFileSystem.ts +1 -1
  286. package/vendor/node_modules/@legendapp/spark-file-system/src/file-scanner/NativeFileScanner.ts +11 -0
  287. package/vendor/node_modules/@legendapp/spark-file-system/src/file-scanner/index.ts +93 -0
  288. package/vendor/node_modules/@legendapp/spark-file-system/src/handles.ts +48 -14
  289. package/vendor/node_modules/@legendapp/spark-file-system/src/index.ts +134 -45
  290. package/vendor/node_modules/@legendapp/spark-file-system/src/path.ts +1 -9
  291. package/vendor/node_modules/@legendapp/spark-file-system/windows/SparkFileSystem/SparkFileSystem.h +102 -26
  292. package/vendor/node_modules/@legendapp/spark-file-system/windows/SparkFileSystem/SparkFileSystem.vcxproj +2 -0
  293. package/vendor/node_modules/@legendapp/spark-global-shortcuts/RNDesktopGlobalShortcuts.podspec +1 -0
  294. package/vendor/node_modules/@legendapp/spark-global-shortcuts/macos/RNDesktopGlobalShortcuts.mm +7 -4
  295. package/vendor/node_modules/@legendapp/spark-global-shortcuts/package.json +4 -3
  296. package/vendor/node_modules/@legendapp/spark-global-shortcuts/src/NativeDesktopGlobalShortcuts.ts +1 -1
  297. package/vendor/node_modules/@legendapp/spark-global-shortcuts/src/index.ts +39 -10
  298. package/vendor/node_modules/@legendapp/spark-global-shortcuts/windows/SparkGlobalShortcuts/SparkGlobalShortcuts.h +5 -4
  299. package/vendor/node_modules/@legendapp/spark-message-dialog/macos/RNDesktopMessageDialog.mm +2 -2
  300. package/vendor/node_modules/@legendapp/spark-message-dialog/package.json +2 -2
  301. package/vendor/node_modules/@legendapp/spark-message-dialog/src/NativeDesktopMessageDialog.ts +1 -1
  302. package/vendor/node_modules/@legendapp/spark-message-dialog/src/index.ts +48 -11
  303. package/vendor/node_modules/@legendapp/spark-native-menu/ios/RNNativeMenu.mm +141 -609
  304. package/vendor/node_modules/@legendapp/spark-native-menu/package.json +9 -4
  305. package/vendor/node_modules/@legendapp/spark-native-menu/src/NativeMenu.ts +2 -7
  306. package/vendor/node_modules/@legendapp/spark-native-menu/src/api.ts +76 -121
  307. package/vendor/node_modules/@legendapp/spark-native-menu/src/hooks.ts +97 -0
  308. package/vendor/node_modules/@legendapp/spark-native-menu/src/windows-menus.ts +43 -37
  309. package/vendor/node_modules/@legendapp/spark-notifications/macos/RNDesktopNotifications.mm +75 -30
  310. package/vendor/node_modules/@legendapp/spark-notifications/package.json +2 -2
  311. package/vendor/node_modules/@legendapp/spark-notifications/src/NativeDesktopNotifications.ts +1 -1
  312. package/vendor/node_modules/@legendapp/spark-notifications/src/index.ts +130 -42
  313. package/vendor/node_modules/@legendapp/spark-notifications/windows/SparkNotifications/SparkNotifications.h +51 -8
  314. package/vendor/node_modules/@legendapp/spark-processes/macos/RNDesktopProcesses.mm +94 -21
  315. package/vendor/node_modules/@legendapp/spark-processes/package.json +4 -3
  316. package/vendor/node_modules/@legendapp/spark-processes/src/NativeDesktopProcesses.ts +1 -1
  317. package/vendor/node_modules/@legendapp/spark-processes/src/index.ts +124 -28
  318. package/vendor/node_modules/@legendapp/spark-processes/src/types.ts +34 -0
  319. package/vendor/node_modules/@legendapp/spark-processes/windows/SparkProcesses/SparkProcesses.h +83 -34
  320. package/vendor/node_modules/@legendapp/spark-processes/windows/SparkProcesses/SparkProcesses.vcxproj +2 -0
  321. package/vendor/node_modules/@legendapp/spark-secure-storage/macos/RNDesktopSecureStorage.mm +49 -40
  322. package/vendor/node_modules/@legendapp/spark-secure-storage/package.json +2 -2
  323. package/vendor/node_modules/@legendapp/spark-secure-storage/src/NativeDesktopSecureStorage.ts +1 -1
  324. package/vendor/node_modules/@legendapp/spark-secure-storage/src/desktop.ts +16 -14
  325. package/vendor/node_modules/@legendapp/spark-secure-storage/src/expo.ts +0 -1
  326. package/vendor/node_modules/@legendapp/spark-secure-storage/src/options.ts +3 -2
  327. package/vendor/node_modules/@legendapp/spark-secure-storage/src/unavailable.ts +6 -3
  328. package/vendor/node_modules/@legendapp/spark-settings/package.json +10 -3
  329. package/vendor/node_modules/@legendapp/spark-settings/src/fileStorage.ts +11 -0
  330. package/vendor/node_modules/@legendapp/spark-settings/src/index.ts +7 -9
  331. package/vendor/node_modules/@legendapp/spark-settings/src/storage/index.ts +142 -0
  332. package/vendor/node_modules/@legendapp/spark-settings/src/store.ts +63 -21
  333. package/vendor/node_modules/@legendapp/spark-settings-ui/package.json +20 -0
  334. package/vendor/node_modules/@legendapp/spark-settings-ui/src/index.tsx +436 -0
  335. package/vendor/node_modules/@legendapp/spark-settings-ui/src/options.ts +10 -0
  336. package/vendor/node_modules/@legendapp/spark-sqlite/package.json +3 -3
  337. package/vendor/node_modules/@legendapp/spark-sqlite/src/database.ts +182 -0
  338. package/vendor/node_modules/@legendapp/spark-sqlite/src/index.ts +19 -6
  339. package/vendor/node_modules/@legendapp/spark-sqlite/src/types.ts +22 -0
  340. package/vendor/node_modules/@legendapp/spark-system/macos/RNDesktopSystem.mm +36 -11
  341. package/vendor/node_modules/@legendapp/spark-system/package.json +2 -2
  342. package/vendor/node_modules/@legendapp/spark-system/src/NativeDesktopSystem.ts +1 -1
  343. package/vendor/node_modules/@legendapp/spark-system/src/index.ts +89 -32
  344. package/vendor/node_modules/@legendapp/spark-system/windows/SparkSystem/SparkSystem.h +8 -4
  345. package/vendor/node_modules/@legendapp/spark-tray/macos/RNDesktopTray.mm +20 -8
  346. package/vendor/node_modules/@legendapp/spark-tray/package.json +2 -2
  347. package/vendor/node_modules/@legendapp/spark-tray/src/NativeDesktopTray.ts +1 -1
  348. package/vendor/node_modules/@legendapp/spark-tray/src/index.ts +91 -34
  349. package/vendor/node_modules/@legendapp/spark-tray/windows/SparkTray/SparkTray.h +45 -15
  350. package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkButton.mm +2 -1
  351. package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkTextInput.mm +10 -2
  352. package/vendor/node_modules/@legendapp/spark-ui/macos/appkit-split-view/RNSidebarSplitViewComponent.h +15 -0
  353. package/vendor/node_modules/@legendapp/spark-ui/macos/appkit-split-view/RNSidebarSplitViewComponent.mm +1419 -0
  354. package/vendor/node_modules/@legendapp/spark-ui/macos/glass-effect-view/RNGlassEffectView.mm +72 -0
  355. package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSegmentedControl.h +15 -0
  356. package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSegmentedControl.mm +194 -0
  357. package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSelect.h +15 -0
  358. package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSelect.mm +180 -0
  359. package/vendor/node_modules/@legendapp/spark-ui/macos/sf-symbol/RNSFSymbol.h +15 -0
  360. package/vendor/node_modules/@legendapp/spark-ui/macos/sf-symbol/RNSFSymbol.mm +155 -0
  361. package/vendor/node_modules/@legendapp/spark-ui/macos/sidebar/RNSidebar.h +18 -0
  362. package/vendor/node_modules/@legendapp/spark-ui/macos/sidebar/RNSidebar.mm +645 -0
  363. package/vendor/node_modules/@legendapp/spark-ui/macos/swipe-actions/RNSwipeActions.h +10 -0
  364. package/vendor/node_modules/@legendapp/spark-ui/macos/swipe-actions/RNSwipeActions.mm +422 -0
  365. package/vendor/node_modules/@legendapp/spark-ui/macos/text-input-search/RNTextInputSearch.h +15 -0
  366. package/vendor/node_modules/@legendapp/spark-ui/macos/text-input-search/RNTextInputSearch.mm +164 -0
  367. package/vendor/node_modules/@legendapp/spark-ui/package.json +17 -4
  368. package/vendor/node_modules/@legendapp/spark-ui/src/SparkSelectNativeComponent.ts +3 -1
  369. package/vendor/node_modules/@legendapp/spark-ui/src/SparkTextInputNativeComponent.ts +6 -2
  370. package/vendor/node_modules/@legendapp/spark-ui/src/appkit-split-view/SidebarSplitViewNativeComponent.ts +37 -0
  371. package/vendor/node_modules/@legendapp/spark-ui/src/appkit-split-view/index.tsx +86 -0
  372. package/vendor/node_modules/@legendapp/spark-ui/src/availability.ts +10 -0
  373. package/vendor/node_modules/@legendapp/spark-ui/src/classnames/index.ts +8 -0
  374. package/vendor/node_modules/@legendapp/spark-ui/src/control.ts +42 -0
  375. package/vendor/node_modules/@legendapp/spark-ui/src/desktop.tsx +56 -0
  376. package/vendor/node_modules/@legendapp/spark-ui/src/glass-effect-view/index.tsx +15 -0
  377. package/vendor/node_modules/@legendapp/spark-ui/src/index.android.tsx +35 -21
  378. package/vendor/node_modules/@legendapp/spark-ui/src/index.ios.tsx +55 -26
  379. package/vendor/node_modules/@legendapp/spark-ui/src/index.tsx +1 -27
  380. package/vendor/node_modules/@legendapp/spark-ui/src/index.web.tsx +45 -14
  381. package/vendor/node_modules/@legendapp/spark-ui/src/index.windows.tsx +1 -42
  382. package/vendor/node_modules/@legendapp/spark-ui/src/mobile-input.tsx +11 -0
  383. package/vendor/node_modules/@legendapp/spark-ui/src/native-select/NativeSegmentedControlNativeComponent.ts +17 -0
  384. package/vendor/node_modules/@legendapp/spark-ui/src/native-select/NativeSelectNativeComponent.ts +17 -0
  385. package/vendor/node_modules/@legendapp/spark-ui/src/select.ts +5 -3
  386. package/vendor/node_modules/@legendapp/spark-ui/src/sf-symbol/SFSymbolNativeComponent.ts +13 -0
  387. package/vendor/node_modules/@legendapp/spark-ui/src/sf-symbol/index.tsx +27 -0
  388. package/vendor/node_modules/@legendapp/spark-ui/src/sidebar/SidebarItemNativeComponent.ts +25 -0
  389. package/vendor/node_modules/@legendapp/spark-ui/src/sidebar/SidebarNativeComponent.ts +24 -0
  390. package/vendor/node_modules/@legendapp/spark-ui/src/sidebar/index.tsx +104 -0
  391. package/vendor/node_modules/@legendapp/spark-ui/src/specialized.ts +22 -0
  392. package/vendor/node_modules/@legendapp/spark-ui/src/swipe-actions/SwipeActionsNativeComponent.ts +11 -0
  393. package/vendor/node_modules/@legendapp/spark-ui/src/swipe-actions/index.tsx +41 -0
  394. package/vendor/node_modules/@legendapp/spark-ui/src/text-input-search/TextInputSearchNativeComponent.ts +33 -0
  395. package/vendor/node_modules/@legendapp/spark-ui/src/text-input-search/index.tsx +34 -0
  396. package/vendor/node_modules/@legendapp/spark-ui/src/types.ts +30 -19
  397. package/vendor/node_modules/@legendapp/spark-ui/uniwind.ts +3 -1
  398. package/vendor/node_modules/@legendapp/spark-ui/uniwind.web.ts +3 -1
  399. package/vendor/node_modules/@legendapp/spark-ui/windows/SparkUI/SparkUI.h +16 -11
  400. package/vendor/node_modules/@legendapp/spark-updates/macos/RNDesktopUpdates.mm +21 -8
  401. package/vendor/node_modules/@legendapp/spark-updates/package.json +2 -2
  402. package/vendor/node_modules/@legendapp/spark-updates/src/NativeDesktopUpdates.ts +3 -2
  403. package/vendor/node_modules/@legendapp/spark-updates/src/index.ts +71 -15
  404. package/vendor/node_modules/@legendapp/spark-webview/package.json +2 -2
  405. package/vendor/node_modules/@legendapp/spark-webview/src/WebView.tsx +11 -0
  406. package/vendor/node_modules/@legendapp/spark-webview/src/adapter.ts +55 -0
  407. package/vendor/node_modules/@legendapp/spark-webview/src/index.ts +2 -2
  408. package/vendor/node_modules/@legendapp/spark-webview/src/types.ts +32 -0
  409. package/vendor/node_modules/@legendapp/spark-webview/src/view-props.ts +28 -0
  410. package/vendor/node_modules/@legendapp/spark-window-options/index.cjs +51 -14
  411. package/vendor/node_modules/@legendapp/spark-window-options/index.d.ts +21 -8
  412. package/vendor/node_modules/@legendapp/spark-window-options/package.json +1 -1
  413. package/windows-macos.ts +1 -0
  414. package/expo-metro.cjs +0 -1
  415. package/message-dialog.ts +0 -1
  416. package/universal.cjs +0 -1
  417. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/accelerator.ts +0 -22
  418. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows-options.ts +0 -11
  419. package/vendor/node_modules/@legendapp/spark-file-dialog/src/index.windows.ts +0 -15
  420. package/vendor/node_modules/@legendapp/spark-global-shortcuts/src/accelerator.ts +0 -22
  421. package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkSelect.h +0 -4
  422. package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkSelect.mm +0 -53
@@ -15,8 +15,10 @@ const patches = [
15
15
  ' const onPressAsync = async (key)=>{',
16
16
  ` const onPressAsync = async (key)=>{\n try {\n if (await require(${extension}).handleKey(key)) return;\n } catch (error) {\n _log.exception(error);\n return;\n }`],
17
17
  ['startAsync.js', '0e062078e63ad6264b1393d403ad56d65a38c6430d30fdac50cd656486cd418b',
18
- ' mcpServer == null ? void 0 : mcpServer.start();',
19
- ` mcpServer == null ? void 0 : mcpServer.start();\n require(${extension}).ready(devServerManager.getNativeDevServerPort(), { dev: options.dev, minify: options.minify, https: options.https });`],
18
+ ' await (0, _profile.profile)(devServerManager.startAsync.bind(devServerManager))(startOptions);',
19
+ // Dependency validation can wait on the network after Metro is listening.
20
+ // Report actual server readiness before those optional startup checks.
21
+ ` await (0, _profile.profile)(devServerManager.startAsync.bind(devServerManager))(startOptions);\n require(${extension}).ready(devServerManager.getNativeDevServerPort(), { dev: options.dev, minify: options.minify, https: options.https });`],
20
22
  ];
21
23
 
22
24
  function preparePatch(root) {
@@ -19,7 +19,7 @@ exports.withSparkMetro = config => {
19
19
  if (config && typeof config.then === 'function') return config.then(exports.withSparkMetro);
20
20
  if (!config || typeof config !== 'object') throw new Error('Spark needs an object or promise from metro.config');
21
21
  const upstream = defaults.get(path.resolve(config.projectRoot || process.cwd()));
22
- if (!upstream) throw new Error('Compose Metro with getDefaultConfig from @legendapp/spark-cli/src/expo-metro.cjs');
22
+ if (!upstream) throw new Error('Compose Metro with getDefaultConfig from @legendapp/spark/metro');
23
23
  const customResolve = config.resolver?.resolveRequest;
24
24
  if (customResolve && customResolve !== upstream.resolveRequest) {
25
25
  const desktopResolve = upstream.resolveRequest;
@@ -1,5 +1,9 @@
1
1
  exports.withSparkNative = (original, root) => {
2
- if (!['macos', 'windows'].includes(process.env.SPARK_PLATFORM)) return original;
2
+ if (!['macos', 'windows'].includes(process.env.SPARK_PLATFORM)) {
3
+ const patched = require('@legendapp/spark-desktop-config/native-patches.cjs').prepareNativePatches(root);
4
+ if (!Object.keys(patched).length) return original;
5
+ return { ...original, dependencies: { ...patched, ...original.dependencies } };
6
+ }
3
7
  const generated = require('./universal.cjs').nativeConfig(root);
4
8
  const dependencies = { ...original.dependencies };
5
9
  for (const [name, config] of Object.entries(generated.dependencies ?? {})) {
@@ -2,7 +2,7 @@ import { spawnProcess, which } from "./process.js";
2
2
  import { createRequire } from "node:module";
3
3
  import path from "node:path";
4
4
  import { pathToFileURL } from "node:url";
5
- /** Check the actual Node/Expo pair before handing work to Expo Desktop beta. */
5
+ /** Check the actual Node/Expo pair before handing work to Expo Desktop. */
6
6
  export async function checkExpoDesktopNode(root) {
7
7
  const requireApp = createRequire(path.join(root, "package.json"));
8
8
  const requireDesktop = createRequire(requireApp.resolve("expo-desktop/package.json"));
@@ -10,12 +10,12 @@ export async function checkExpoDesktopNode(root) {
10
10
  const node = which("node");
11
11
  if (!node)
12
12
  throw new Error("Missing node. Install Node 24.19.0 (the version in .nvmrc), then retry.");
13
- // Use the same static named imports as beta.5. Older Node releases cannot
13
+ // Use the static named imports used by Expo Desktop. Older Node releases cannot
14
14
  // discover these exports in Expo's Babel-generated CommonJS modules.
15
15
  const child = spawnProcess([node, "--input-type=module", "-e",
16
16
  `import { AndroidConfig, IOSConfig } from ${JSON.stringify(configPlugins)}; if (!AndroidConfig || !IOSConfig) throw new Error('Missing Expo config exports');`,
17
17
  ], { cwd: root, stdout: "ignore", stderr: "pipe" });
18
18
  const [stderr, code] = await Promise.all([new Response(child.stderr).text(), child.exited]);
19
19
  if (code !== 0)
20
- throw new Error(`Expo Desktop beta could not load its config plugins using ${node}. Use Node 24.19.0 (nvm install && nvm use from the framework checkout), then retry. Node 24.12.0 cannot import these CommonJS named exports.\n${stderr.trim()}`);
20
+ throw new Error(`Expo Desktop could not load its config plugins using ${node}. Use Node 24.19.0 (nvm install && nvm use from the framework checkout), then retry. Node 24.12.0 cannot import these CommonJS named exports.\n${stderr.trim()}`);
21
21
  }
@@ -2,8 +2,8 @@ import { copyFileSync, lstatSync, mkdirSync, realpathSync, chmodSync, readdirSyn
2
2
  import path from "node:path";
3
3
  import { createRequire } from "node:module";
4
4
  import { architecture } from "./platform.js";
5
- const { validateHelpers } = createRequire(import.meta.url)("@legendapp/spark-desktop-config/helpers.cjs");
6
5
  export function resolveHelpers(root, helpers = {}, platform = "macos", arch = architecture(platform)) {
6
+ const { validateHelpers } = createRequire(import.meta.url)("@legendapp/spark-desktop-config/helpers.cjs");
7
7
  validateHelpers(helpers);
8
8
  const base = realpathSync(root);
9
9
  function inspect(file) {
@@ -1,13 +1,13 @@
1
- import { spawnProcess } from "./process.js";
1
+ import { nodeCommand, spawnProcess } from "./process.js";
2
2
  import { examples } from "./examples.js";
3
3
  import { prepareGoProfile } from "./go-profile.js";
4
4
  import { exportSDK, importSDK } from "./sdk-transfer.js";
5
5
  import { hostPlatform } from "./platform.js";
6
6
  import path from "node:path";
7
- import { parseArgs } from "node:util";
7
+ import { cliArguments } from "./cli-arguments.js";
8
8
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
9
9
  import { prepareConfig, readConfig, isExpoProject } from "@legendapp/spark-desktop-config/config.cjs";
10
- import { nodeCommand, prepareWindows } from "./windows.js";
10
+ import { prepareWindows } from "./windows.js";
11
11
  import { create, refreshLocalPackages } from "./create.js";
12
12
  import { addDesktop } from "./add-desktop.js";
13
13
  import { buildMode } from "./build-mode.js";
@@ -20,37 +20,13 @@ import { doctor, run } from "./commands.js";
20
20
  import { findFramework, findProject, sparkHome, creationManifest, packageManifest, registerRuntime } from "./local.js";
21
21
  import { readJson, stateFile, VERSION, writeJson } from "./project.js";
22
22
  import { devCommand } from "./dev-command.js";
23
+ import { printDependencyPins, upgradeDependencyPins } from "./dependency-pins.js";
24
+ import { reportError } from "./errors.js";
23
25
  async function main() {
24
26
  const argv = process.argv.slice(2);
25
27
  if (argv[0] === "dev")
26
28
  return devCommand(argv.slice(1));
27
- const { positionals, values } = parseArgs({
28
- args: argv,
29
- allowPositionals: true,
30
- options: {
31
- example: { type: "string" },
32
- "package-manager": { type: "string" },
33
- runtime: { type: "string", multiple: true },
34
- universal: { type: "boolean" },
35
- device: { type: "string" },
36
- project: { type: "string" },
37
- platform: { type: "string" },
38
- packages: { type: "string" },
39
- port: { type: "string" },
40
- runner: { type: "boolean" },
41
- prebuilt: { type: "boolean" },
42
- go: { type: "boolean" }, // Legacy desktop build alias; dev --go belongs to Expo.
43
- dev: { type: "boolean" },
44
- release: { type: "boolean" },
45
- preview: { type: "boolean" },
46
- force: { type: "boolean" },
47
- "no-open": { type: "boolean" },
48
- "submission-id": { type: "string" },
49
- help: { type: "boolean", short: "h" },
50
- },
51
- });
52
- if (values.platform && !["macos", "windows", "ios", "android", "web"].includes(values.platform))
53
- throw new Error("Platform must be macos, windows, ios, android, or web.");
29
+ const { positionals, values } = cliArguments(argv);
54
30
  if (values.platform)
55
31
  process.env.SPARK_PLATFORM = values.platform;
56
32
  const platform = (values.platform ?? hostPlatform());
@@ -58,25 +34,25 @@ async function main() {
58
34
  const start = path.resolve(projectOption ?? process.cwd());
59
35
  const project = () => findProject(start);
60
36
  const port = values.port === undefined ? undefined : Number(values.port);
61
- if (port !== undefined && (!Number.isInteger(port) || port < 1 || port > 65535))
62
- throw new Error("Port must be an integer between 1 and 65535.");
63
37
  const command = positionals[0];
64
38
  if (!values.help && !values.platform && !(command === "open" && positionals[1]) && ["build", "prebuild", "analyze", "package", "open", "updates", "credentials"].includes(command ?? "") && isExpoProject(project())) {
65
39
  process.env.SPARK_PLATFORM = readConfig(project()).expo.platforms[0];
66
40
  }
67
41
  if (values.example && (command !== "create" || !examples.includes(values.example)))
68
42
  throw new Error(`Use create --example ${examples.join(" | ")}`);
69
- if (values.universal && command !== "create")
70
- throw new Error("--universal is a create option.");
71
43
  if (!values.help && ["build", "prebuild"].includes(command ?? "")) {
72
44
  const root = project();
73
45
  const selected = readConfig(root).expo.platforms[0];
46
+ if (!["ios", "android", "web"].includes(selected) && (values.device || values.port))
47
+ throw new Error("--device and --port are mobile build options; use spark dev for desktop launch options.");
74
48
  if (["ios", "android", "web"].includes(selected)) {
49
+ if (values.force)
50
+ throw new Error("--force is a desktop build option.");
75
51
  if (command === "build" && selected === "web")
76
52
  throw new Error("Use expo export --platform web for web production output.");
77
53
  if (command === "prebuild" && selected === "web")
78
54
  throw new Error("Web has no native project to prebuild.");
79
- if (values.runner || values.prebuilt || values.go || values.release || values.preview || (command === "build" && !values.dev))
55
+ if (values.runner || values.release || values.preview || (command === "build" && !values.dev))
80
56
  throw new Error("Mobile builds use --dev in this slice; Expo owns mobile distribution workflows.");
81
57
  prepareConfig(root);
82
58
  const args = command === "prebuild" ? ["prebuild", "--platform", selected, "--no-install"] : [`run:${selected}`, ...(values.device ? ["--device", values.device] : []), ...(port ? ["--port", String(port)] : [])];
@@ -104,6 +80,8 @@ async function main() {
104
80
  spark build Build a standalone desktop app
105
81
  spark prebuild Generate a Windows/mobile native project
106
82
  spark package Sign and notarize a distribution archive
83
+ spark doctor Check app dependency pins and native tooling (exits 1 on issues)
84
+ spark upgrade Align app dependency pins with Spark (--dry-run previews changes)
107
85
 
108
86
  Inside an app: npm run dev, npm run build, npm run package (or pnpm, yarn, bun)
109
87
 
@@ -125,8 +103,6 @@ Overrides: --project <directory>, --port <number>, dev --runner-binary <runtime
125
103
  case "create": {
126
104
  if (!positionals[1])
127
105
  throw new Error("Usage: spark create MyApp");
128
- if (!values.universal && !["macos", "windows"].includes(platform))
129
- throw new Error("Use create --universal for mobile/web targets");
130
106
  await create(path.resolve(positionals[1]), creationManifest(values.packages), platform, !!values.universal || !!values.example, values.example, values["package-manager"]);
131
107
  break;
132
108
  }
@@ -169,8 +145,6 @@ Overrides: --project <directory>, --port <number>, dev --runner-binary <runtime
169
145
  process.exitCode = 2;
170
146
  break;
171
147
  }
172
- case "build-go": // Legacy alias; persisted runtime metadata still uses "go".
173
- case "build-prebuilt": // Legacy command alias.
174
148
  case "build-runner": {
175
149
  let root;
176
150
  if (projectOption)
@@ -201,10 +175,44 @@ Overrides: --project <directory>, --port <number>, dev --runner-binary <runtime
201
175
  throw new Error("For macOS, spark build --dev generates and builds the native project.");
202
176
  await prepareWindows(project(), "dev");
203
177
  break;
204
- case "doctor":
205
- await doctor(start);
178
+ case "doctor": {
179
+ let root;
180
+ let pinIssues = false;
181
+ try {
182
+ root = project();
183
+ }
184
+ catch {
185
+ console.log("No Spark app found; skipping dependency pin check.");
186
+ }
187
+ if (root) {
188
+ try {
189
+ const issues = upgradeDependencyPins(root, true);
190
+ printDependencyPins(issues);
191
+ if (issues.length) {
192
+ process.exitCode = 1;
193
+ pinIssues = true;
194
+ }
195
+ }
196
+ catch (error) {
197
+ console.error(`Dependency pin check failed: ${error instanceof Error ? error.message : String(error)}`);
198
+ process.exitCode = 1;
199
+ pinIssues = true;
200
+ }
201
+ }
202
+ await doctor(root ?? start);
206
203
  console.log("Native toolchain available.");
204
+ if (pinIssues)
205
+ console.log("Dependency pin issues found; run spark upgrade.");
206
+ break;
207
+ }
208
+ case "upgrade": {
209
+ const issues = upgradeDependencyPins(project(), !!values["dry-run"]);
210
+ console.log(values["dry-run"] ? "Dependency pin changes (dry run):" : "Dependency pin changes:");
211
+ printDependencyPins(issues);
212
+ if (issues.length)
213
+ console.log(values["dry-run"] ? "No files changed. Run spark upgrade, then run your package manager's install command (npm/pnpm/yarn/bun install)." : "Updated package.json. Run your package manager's install command (npm/pnpm/yarn/bun install).");
207
214
  break;
215
+ }
208
216
  case "updates": {
209
217
  if (positionals[1] !== "init" || !positionals[2])
210
218
  throw new Error("Usage: spark updates init https://example.com/updates/appcast.xml");
@@ -216,8 +224,8 @@ Overrides: --project <directory>, --port <number>, dev --runner-binary <runtime
216
224
  console.log("Signing credentials configured. Run spark package to prepare a distribution archive.");
217
225
  break;
218
226
  case "package": {
219
- if (process.platform !== "darwin" || process.arch !== "arm64")
220
- throw new Error("Packaging currently supports Apple Silicon macOS only.");
227
+ if (process.platform !== "darwin")
228
+ throw new Error("macOS packaging requires macOS.");
221
229
  const result = await packageApp(project(), { force: !!values.force, submissionId: values["submission-id"] });
222
230
  if (result.pending)
223
231
  process.exitCode = 2;
@@ -258,6 +266,6 @@ try {
258
266
  await main();
259
267
  }
260
268
  catch (error) {
261
- console.error(error instanceof Error ? error.message : String(error));
269
+ reportError(process.cwd(), error, "Spark");
262
270
  process.exitCode = 1;
263
271
  }
@@ -0,0 +1,16 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from "node:fs";
2
+ import path from "node:path";
3
+ export function readJson(file) {
4
+ return JSON.parse(readFileSync(file, "utf8"));
5
+ }
6
+ export function writeJson(file, value) {
7
+ const content = JSON.stringify(value, null, 2) + "\n";
8
+ // Metro watches JSON too: rewriting unchanged session state on every runtime
9
+ // check causes empty Fast Refresh updates even when app code has not changed.
10
+ if (existsSync(file) && readFileSync(file, "utf8") === content)
11
+ return;
12
+ mkdirSync(path.dirname(file), { recursive: true });
13
+ const temporary = `${file}.${process.pid}.tmp`;
14
+ writeFileSync(temporary, content);
15
+ renameSync(temporary, file);
16
+ }
@@ -35,7 +35,7 @@ export function readRuntime(app) {
35
35
  try {
36
36
  const windows = existsSync(path.join(app, "spark-runtime.json"));
37
37
  const runtime = readJson(path.join(app, windows ? "spark-runtime.json" : "Contents/Resources/spark-runtime.json"));
38
- if (runtime.schema !== 1 || runtime.framework !== VERSION || !["macos", "windows"].includes(runtime.platform) || !(runtime.platform === "windows" ? ["arm64", "x64"] : ["arm64"]).includes(runtime.arch) || !runtime.modules || typeof runtime.modules !== "object" || typeof runtime.fingerprint !== "string")
38
+ if (runtime.schema !== 1 || runtime.framework !== VERSION || !["macos", "windows"].includes(runtime.platform) || !["arm64", "x64"].includes(runtime.arch) || !runtime.modules || typeof runtime.modules !== "object" || typeof runtime.fingerprint !== "string")
39
39
  return undefined;
40
40
  if (!existsSync(path.join(app, windows ? "MyApp.exe" : "Contents/MacOS")) || windows !== (runtime.platform === "windows"))
41
41
  return undefined;
@@ -16,6 +16,11 @@ function runtimePlan(root, env = process.env) {
16
16
  .map(e => e.name).concat(["src"]) };
17
17
  }
18
18
  function withDesktop(config, options = {}) {
19
+ if (!options || typeof options !== "object" || Array.isArray(options)) throw new Error("Expected desktop Metro options");
20
+ for (const [key, value] of Object.entries(options)) {
21
+ if (!["runtimes", "watch"].includes(key)) throw new Error(`Unknown desktop Metro option: ${key}`);
22
+ if (value !== undefined && typeof value !== "boolean") throw new Error(`${key} must be boolean`);
23
+ }
19
24
  // Expo 54 sets the react-native export condition only for iOS/Android.
20
25
  // Desktop must also select native package exports (e.g. Uniwind's runtime).
21
26
  const conditions = { ...config.resolver?.unstable_conditionsByPlatform };
@@ -24,10 +29,26 @@ function withDesktop(config, options = {}) {
24
29
  }
25
30
  config = { ...config, resolver: { ...config.resolver, unstable_conditionsByPlatform: conditions } };
26
31
  const root = path.resolve(config.projectRoot || process.cwd());
27
- // Prebuilt hosts request /index.bundle and /.threaded-runtime/entry.bundle.
28
- // Keep those URLs relative to the app inside a monorepo; Expo still discovers
29
- // workspace watch folders and package dependencies.
30
- config = { ...config, server: { ...config.server, unstable_serverRoot: root } };
32
+ // Keep the configured workspace root so lazy imports outside the app have
33
+ // valid URLs. Only the prebuilt host's fixed entry URLs are app-relative.
34
+ const serverRoot = path.resolve(config.server?.unstable_serverRoot || root);
35
+ const entryPrefix = path.relative(serverRoot, root).split(path.sep).map(encodeURIComponent).join("/");
36
+ if (entryPrefix && (entryPrefix === ".." || entryPrefix.startsWith("../"))) {
37
+ throw new Error("Metro's server root must contain the Spark project");
38
+ }
39
+ const rewrite = config.server?.rewriteRequestUrl;
40
+ config = { ...config, server: { ...config.server, unstable_serverRoot: serverRoot,
41
+ rewriteRequestUrl(value) {
42
+ const url = new URL(value, "http://localhost");
43
+ const platform = url.searchParams.get("platform");
44
+ if (entryPrefix && (!platform || ["macos", "windows"].includes(platform)) &&
45
+ /^\/(index|\.threaded-runtime\/entry)\.(bundle|map|delta)$/.test(url.pathname)) {
46
+ url.pathname = `/${entryPrefix}${url.pathname}`;
47
+ value = value.startsWith("/") ? `${url.pathname}${url.search}${url.hash}` : url.href;
48
+ }
49
+ return rewrite ? rewrite(value) : value;
50
+ },
51
+ } };
31
52
  let core;
32
53
  try { core = require.resolve("@react-native-runtimes/core/metro", { paths: [root] }); } catch {}
33
54
  if (!core || options.runtimes === false) {
@@ -40,7 +61,7 @@ function withDesktop(config, options = {}) {
40
61
  const plan = runtimePlan(root);
41
62
  const generatedEntry = path.join(root, ".threaded-runtime/entry.js");
42
63
  if (plan.enabled) {
43
- config = withThreadedRuntime(config, { ...options, roots: plan.roots, watch: plan.production ? false : options.watch });
64
+ config = withThreadedRuntime(config, { roots: plan.roots, watch: plan.production ? false : options.watch });
44
65
  // Production roots come from Metro's resolved graph, including worker files
45
66
  // shipped by dependencies. Do not register unrelated index.<name>.ts files.
46
67
  if (plan.production) generateThreadedRuntimeEntry({ projectRoot: root, generatedEntry, roots: plan.roots, runtimeEntries: [] });
@@ -0,0 +1,26 @@
1
+ import { existsSync, readdirSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { run } from "./commands.js";
4
+ import { createRequire } from "node:module";
5
+ const { identity } = createRequire(import.meta.url)("@legendapp/spark-desktop-config/identity.cjs");
6
+ /** Restore app-owned values after Expo Desktop's template string replacement. */
7
+ export async function restoreNativeMetadata(root, config, execute = run) {
8
+ const overrides = { ...config.macos?.infoPlist, ...identity(config) };
9
+ const nativeRoot = path.join(root, "macos");
10
+ const matches = [];
11
+ for (const entry of readdirSync(nativeRoot, { withFileTypes: true })) {
12
+ if (!entry.isDirectory())
13
+ continue;
14
+ const file = path.join(nativeRoot, entry.name, "Info.plist");
15
+ if (!existsSync(file))
16
+ continue;
17
+ const info = JSON.parse(await execute(root, ["plutil", "-convert", "json", "-o", "-", file], { capture: true }));
18
+ if ("SparkProjectIdentifier" in info)
19
+ matches.push({ file, info });
20
+ }
21
+ if (matches.length !== 1)
22
+ throw new Error(`Expected one generated Spark Info.plist, found ${matches.length}`);
23
+ const { file, info } = matches[0];
24
+ writeFileSync(file, JSON.stringify({ ...info, ...overrides }));
25
+ await execute(root, ["plutil", "-convert", "xml1", file], { capture: true });
26
+ }
@@ -0,0 +1,86 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import path from "node:path";
4
+ import { prepareNativePatches } from "@legendapp/spark-desktop-config/native-patches.cjs";
5
+ import { findFramework } from "./local.js";
6
+ import { installedPackages, readJson, VERSION } from "./project.js";
7
+ const required = ["@react-native-runtimes/core", "react-native-nitro-modules", "@op-engineering/op-sqlite", "react-native-webview"];
8
+ const optional = ["expo-audio"];
9
+ export function validatePackedNativePatches(packages, requirements, frameworkVersion = VERSION) {
10
+ if (!requirements || requirements.schema !== 1 || requirements.frameworkVersion !== frameworkVersion || !requirements.packages || typeof requirements.packages !== "object")
11
+ return [`The installed @legendapp/spark SDK does not include native patch provenance for ${frameworkVersion}. Run spark add desktop to install the matching SDK packages, then retry.`];
12
+ const installed = new Map(packages.map(pkg => [pkg.name, pkg.json]));
13
+ const errors = [];
14
+ for (const name of required)
15
+ if (!installed.has(name))
16
+ errors.push(`${name} is missing; reinstall the dependencies from this Spark SDK.`);
17
+ for (const name of [...required, ...optional]) {
18
+ const actual = installed.get(name);
19
+ if (!actual)
20
+ continue;
21
+ const expected = requirements.packages[name];
22
+ const spark = actual.spark;
23
+ if (!expected || typeof expected.version !== "string" || !/^[a-f0-9]{64}$/.test(expected.patchHash) ||
24
+ (!expected.upstreamIntegrity && !expected.upstreamRevision) || actual.version !== expected.version || spark?.sdk !== true || spark.patchHash !== expected.patchHash ||
25
+ spark.upstreamIntegrity !== expected.upstreamIntegrity || spark.upstreamRevision !== expected.upstreamRevision) {
26
+ errors.push(`${name}@${actual.version} is not the matching patched Spark SDK package.`);
27
+ }
28
+ }
29
+ return errors;
30
+ }
31
+ export function validateWorkspaceNativePatches(root, packages) {
32
+ const framework = findFramework(root);
33
+ if (!framework)
34
+ return ["The Spark SDK is missing native patch provenance. Run spark add desktop to install matching SDK packages, then retry."];
35
+ const frameworkPackage = readJson(path.join(framework, "package.json"));
36
+ const map = frameworkPackage.sparkWorkspacePatches;
37
+ if (!map)
38
+ return ["The Spark workspace has no install-time patch inventory. Run npm run postinstall in the framework checkout, then retry."];
39
+ const pins = readJson(path.join(framework, "patches/workspace/upstream.json"));
40
+ const installed = new Map(packages.map(pkg => [pkg.name, pkg]));
41
+ const errors = [];
42
+ for (const name of [...required, ...optional]) {
43
+ const pkg = installed.get(name);
44
+ if (!pkg) {
45
+ if (required.includes(name))
46
+ errors.push(`${name} is missing; reinstall the dependencies from this Spark workspace.`);
47
+ continue;
48
+ }
49
+ const entry = Object.entries(map).find(([key]) => key.slice(0, key.lastIndexOf("@")) === name);
50
+ const pin = pins[name];
51
+ if (!entry || !pin || !entry[0].endsWith(`@${pin.version}`) || pkg.json.version !== pin.version) {
52
+ errors.push(`${name}@${pkg.json.version} does not match the Spark workspace patch inventory.`);
53
+ continue;
54
+ }
55
+ const patchFile = path.resolve(framework, entry[1]);
56
+ if (!patchFile.startsWith(framework + path.sep) || !existsSync(patchFile)) {
57
+ errors.push(`${name} has no readable Spark workspace patch. Run npm run postinstall in the framework checkout.`);
58
+ continue;
59
+ }
60
+ const patchHash = createHash("sha256").update(readFileSync(patchFile)).digest("hex");
61
+ const receipt = pkg.json.spark?.workspacePatch;
62
+ const expectedRevision = pin.revision;
63
+ if (!receipt || receipt.schema !== 1 || receipt.version !== pin.version || receipt.patchHash !== patchHash ||
64
+ receipt.upstreamIntegrity !== pin.integrity || (expectedRevision && receipt.upstreamRevision !== expectedRevision)) {
65
+ errors.push(`${name}@${pkg.json.version} has no matching applied workspace patch stamp. Run npm run postinstall in the framework checkout, then retry.`);
66
+ }
67
+ }
68
+ return errors;
69
+ }
70
+ export function assertNativePatchPreflight(root) {
71
+ prepareNativePatches(root);
72
+ const packages = installedPackages(root);
73
+ const framework = findFramework(root);
74
+ let errors;
75
+ const spark = packages.find(pkg => pkg.name === "@legendapp/spark");
76
+ const requirements = spark?.json.spark?.nativePatchRequirements;
77
+ if (requirements)
78
+ errors = validatePackedNativePatches(packages, requirements);
79
+ else if (framework)
80
+ errors = validateWorkspaceNativePatches(root, packages);
81
+ else {
82
+ errors = validatePackedNativePatches(packages, requirements);
83
+ }
84
+ if (errors.length)
85
+ throw new Error(`Native patch preparation stopped before changing project files:\n${errors.map(error => `- ${error}`).join("\n")}`);
86
+ }
@@ -0,0 +1,88 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { stateFile } from "./project.js";
4
+ export async function preserveMacOSPods(root, prepare) {
5
+ const native = path.join(root, "macos");
6
+ const cache = stateFile(root, "prebuild-cache/macos");
7
+ const entries = ["Pods", "Podfile.lock"];
8
+ function restore() {
9
+ for (const entry of entries) {
10
+ const saved = path.join(cache, entry);
11
+ const destination = path.join(native, entry);
12
+ if (!existsSync(saved))
13
+ continue;
14
+ if (existsSync(destination))
15
+ throw new Error(`Cannot restore CocoaPods cache: both ${saved} and ${destination} exist.`);
16
+ mkdirSync(native, { recursive: true });
17
+ renameSync(saved, destination);
18
+ }
19
+ rmSync(cache, { recursive: true, force: true });
20
+ }
21
+ // A terminated prebuild may leave the only copy of Pods in the cache.
22
+ restore();
23
+ try {
24
+ for (const entry of entries) {
25
+ const source = path.join(native, entry);
26
+ if (!existsSync(source))
27
+ continue;
28
+ mkdirSync(cache, { recursive: true });
29
+ renameSync(source, path.join(cache, entry));
30
+ }
31
+ await prepare();
32
+ }
33
+ finally {
34
+ restore();
35
+ }
36
+ }
37
+ export function preparationChanges(previous, current) {
38
+ if (!previous?.inputs)
39
+ return ["native preparation provenance missing"];
40
+ const reasons = [];
41
+ if (JSON.stringify(previous.inputs.config) !== JSON.stringify(current.inputs?.config)) {
42
+ const updatesChanged = JSON.stringify(previous.inputs.config.expo?.extra?.spark?.updates) !== JSON.stringify(current.inputs?.config.expo?.extra?.spark?.updates);
43
+ reasons.push(updatesChanged ? "native configuration changed (updater settings)" : "native configuration changed");
44
+ }
45
+ if (previous.inputs.plugin !== current.inputs?.plugin)
46
+ reasons.push("native host/config plugin changed");
47
+ const before = new Map(previous.inputs.packages.map(([name, root, contents]) => [name, { root, contents }]));
48
+ for (const [name, root, contents] of current.inputs?.packages ?? []) {
49
+ const prior = before.get(name);
50
+ if (!prior)
51
+ reasons.push(`${name} added`);
52
+ else {
53
+ if (prior.root !== root)
54
+ reasons.push(`${name} location changed`);
55
+ if (prior.contents !== contents)
56
+ reasons.push(`${name} preparation sources changed`);
57
+ }
58
+ before.delete(name);
59
+ }
60
+ for (const name of before.keys())
61
+ reasons.push(`${name} removed`);
62
+ return reasons.length ? reasons : previous.fingerprint !== current.fingerprint ? ["native preparation inputs changed"] : [];
63
+ }
64
+ export function missingNativeFrameworks(root) {
65
+ const pods = path.join(root, "macos/Pods");
66
+ const support = path.join(pods, "Target Support Files");
67
+ if (!existsSync(support))
68
+ return [support];
69
+ const missing = new Set();
70
+ for (const target of readdirSync(support)) {
71
+ const script = path.join(support, target, `${target}-xcframeworks.sh`);
72
+ if (!existsSync(script))
73
+ continue;
74
+ // CocoaPods lists only the frameworks and slices selected for this target.
75
+ for (const match of readFileSync(script, "utf8").matchAll(/^install_xcframework "([^"]+)" "[^"]+" "[^"]+" (.+)$/gm)) {
76
+ const framework = match[1].replaceAll("${PODS_ROOT}", pods).replaceAll("$(PODS_ROOT)", pods);
77
+ if (framework.includes("$"))
78
+ throw new Error(`Cannot resolve native framework input: ${framework}`);
79
+ if (!existsSync(path.join(framework, "Info.plist")))
80
+ missing.add(path.normalize(framework));
81
+ for (const slice of match[2].matchAll(/"([^"]+)"/g)) {
82
+ if (!existsSync(path.join(framework, slice[1])))
83
+ missing.add(path.join(framework, slice[1]));
84
+ }
85
+ }
86
+ }
87
+ return [...missing];
88
+ }
@@ -0,0 +1,75 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { run } from "./commands.js";
4
+ import { stateFile } from "./project.js";
5
+ // Security returns attributes only. Never request or print credential data.
6
+ const discovery = String.raw `
7
+ import Foundation
8
+ import Security
9
+ import LocalAuthentication
10
+
11
+ struct KeychainError: Error { let status: OSStatus }
12
+ func check(_ status: OSStatus) throws {
13
+ if status != errSecSuccess { throw KeychainError(status: status) }
14
+ }
15
+ func profiles(_ query: [CFString: Any]) throws -> [String] {
16
+ var result: CFTypeRef?
17
+ let status = SecItemCopyMatching(query as CFDictionary, &result)
18
+ var names: [String] = []
19
+ if status != errSecItemNotFound {
20
+ try check(status)
21
+ let prefix = "com.apple.gke.notary.tool.saved-creds."
22
+ for item in result as? [[String: Any]] ?? [] {
23
+ if let account = item[kSecAttrAccount as String] as? String, account.hasPrefix(prefix) {
24
+ let name = String(account.dropFirst(prefix.count))
25
+ if !name.isEmpty { names.append(name) }
26
+ }
27
+ }
28
+ }
29
+ return names
30
+ }
31
+
32
+ do {
33
+ let context = LAContext()
34
+ context.interactionNotAllowed = true
35
+ var query: [CFString: Any] = [
36
+ kSecClass: kSecClassGenericPassword,
37
+ kSecAttrLabel: "com.apple.gke.notary.tool",
38
+ kSecMatchLimit: kSecMatchLimitAll,
39
+ kSecReturnAttributes: true,
40
+ kSecReturnData: false,
41
+ kSecUseAuthenticationContext: context
42
+ ]
43
+ if CommandLine.arguments.count > 1 {
44
+ var keychain: SecKeychain?
45
+ try check(SecKeychainOpen(CommandLine.arguments[1], &keychain))
46
+ if let keychain { query[kSecMatchSearchList] = [keychain] }
47
+ }
48
+ var names = try profiles(query)
49
+ if CommandLine.arguments.count == 1 {
50
+ query[kSecUseDataProtectionKeychain] = true
51
+ query[kSecAttrSynchronizable] = kSecAttrSynchronizableAny
52
+ names += try profiles(query)
53
+ }
54
+ let data = try JSONSerialization.data(withJSONObject: Array(Set(names)).sorted())
55
+ print(String(decoding: data, as: UTF8.self))
56
+ } catch {
57
+ let message: String
58
+ if let error = error as? KeychainError {
59
+ message = SecCopyErrorMessageString(error.status, nil) as String? ?? "OSStatus \(error.status)"
60
+ } else { message = String(describing: error) }
61
+ FileHandle.standardError.write(Data("Cannot list notarization Keychain profiles: \(message)\n".utf8))
62
+ exit(1)
63
+ }
64
+ `;
65
+ export async function listNotaryProfiles(root, keychain, execute = run) {
66
+ const file = stateFile(root, "notary-profiles.swift");
67
+ mkdirSync(path.dirname(file), { recursive: true });
68
+ writeFileSync(file, discovery);
69
+ const output = await execute(root, ["xcrun", "swift", "-suppress-warnings", file, ...(keychain ? [keychain] : [])], { capture: true });
70
+ const profiles = JSON.parse(output);
71
+ if (!Array.isArray(profiles) || !profiles.every(profile => typeof profile === "string" && profile.length > 0)) {
72
+ throw new Error("Invalid notarization profile discovery result.");
73
+ }
74
+ return [...new Set(profiles)].sort();
75
+ }
@@ -69,16 +69,18 @@ async function packageUnlocked(root, options, deps) {
69
69
  if (config.extra?.spark?.updates && !result.runtime.modules["@legendapp/spark-updates"])
70
70
  throw new Error("Updates are configured but the module was pruned. Import @legendapp/spark/updates from the app entry.");
71
71
  const entitlements = distributionEntitlements(appEntitlements(root, result.runtime.modules));
72
+ if (!config.macos?.bundleIdentifier || !config.version)
73
+ throw new Error("Packaging requires macos.bundleIdentifier and version");
72
74
  const byPath = config.extra?.spark?.signing?.macos?.entitlementsByPath ?? {};
73
75
  const info = JSON.parse(await execute(root, ["plutil", "-convert", "json", "-o", "-", path.join(result.app, "Contents/Info.plist")], { capture: true }));
74
- const expected = { runner: options.runner, bundleId: config.macos.bundleIdentifier, version: config.version, buildVersion: info.CFBundleVersion, entitlements, byPath };
76
+ const expected = { arch: result.runtime.arch, runner: options.runner, bundleId: config.macos.bundleIdentifier, version: config.version, buildVersion: info.CFBundleVersion, entitlements, byPath };
75
77
  if (!expected.bundleId || !expected.version || !expected.buildVersion)
76
78
  throw new Error("Bundle identifier and release version metadata must be configured before packaging.");
77
79
  const inputHash = artifactHash(result.app);
78
80
  const key = digest(JSON.stringify({ recipe: 1, inputHash, identity: identity.hash, entitlements, byPath }));
79
81
  const folder = stateFile(root, `packaging/${key}`);
80
82
  const app = path.join(folder, path.basename(result.app));
81
- const safeName = `${config.slug ?? config.name}-${config.version}-arm64`.replace(/[^A-Za-z0-9._-]/g, "-");
83
+ const safeName = `${config.slug ?? config.name}-${config.version}-${result.runtime.arch}`.replace(/[^A-Za-z0-9._-]/g, "-");
82
84
  const upload = path.join(folder, `${safeName}-${key.slice(0, 16)}-notary.zip`);
83
85
  const statePath = path.join(folder, "state.json");
84
86
  mkdirSync(folder, { recursive: true });