@use-voltra/ios-client 2.2.0 → 2.3.1

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 (289) hide show
  1. package/Voltra.podspec +1 -0
  2. package/build/commonjs/events.js +23 -0
  3. package/build/commonjs/events.js.map +1 -1
  4. package/build/commonjs/index.js +59 -0
  5. package/build/commonjs/index.js.map +1 -1
  6. package/build/commonjs/live-activity/api.js +3 -1
  7. package/build/commonjs/live-activity/api.js.map +1 -1
  8. package/build/commonjs/live-activity/dynamic-api.js +173 -0
  9. package/build/commonjs/live-activity/dynamic-api.js.map +1 -0
  10. package/build/commonjs/native/NativeVoltra.js.map +1 -1
  11. package/build/commonjs/utils/enableDynamicLiveActivityHotReload.js +47 -0
  12. package/build/commonjs/utils/enableDynamicLiveActivityHotReload.js.map +1 -0
  13. package/build/commonjs/utils/enableWidgetHotReload.js +8 -11
  14. package/build/commonjs/utils/enableWidgetHotReload.js.map +1 -1
  15. package/build/commonjs/utils/useUpdateOnHMR.js +3 -7
  16. package/build/commonjs/utils/useUpdateOnHMR.js.map +1 -1
  17. package/build/commonjs/widgets/server-credentials.js +9 -0
  18. package/build/commonjs/widgets/server-credentials.js.map +1 -1
  19. package/build/commonjs/widgets/server-update.js +78 -0
  20. package/build/commonjs/widgets/server-update.js.map +1 -0
  21. package/build/module/events.js +23 -0
  22. package/build/module/events.js.map +1 -1
  23. package/build/module/index.js +3 -0
  24. package/build/module/index.js.map +1 -1
  25. package/build/module/live-activity/api.js +2 -2
  26. package/build/module/live-activity/api.js.map +1 -1
  27. package/build/module/live-activity/dynamic-api.js +167 -0
  28. package/build/module/live-activity/dynamic-api.js.map +1 -0
  29. package/build/module/native/NativeVoltra.js.map +1 -1
  30. package/build/module/utils/enableDynamicLiveActivityHotReload.js +43 -0
  31. package/build/module/utils/enableDynamicLiveActivityHotReload.js.map +1 -0
  32. package/build/module/utils/enableWidgetHotReload.js +9 -11
  33. package/build/module/utils/enableWidgetHotReload.js.map +1 -1
  34. package/build/module/utils/useUpdateOnHMR.js +3 -7
  35. package/build/module/utils/useUpdateOnHMR.js.map +1 -1
  36. package/build/module/widgets/server-credentials.js +9 -0
  37. package/build/module/widgets/server-credentials.js.map +1 -1
  38. package/build/module/widgets/server-update.js +72 -0
  39. package/build/module/widgets/server-update.js.map +1 -0
  40. package/build/typescript/commonjs/events.d.ts +7 -0
  41. package/build/typescript/commonjs/events.d.ts.map +1 -1
  42. package/build/typescript/commonjs/index.d.ts +3 -0
  43. package/build/typescript/commonjs/index.d.ts.map +1 -1
  44. package/build/typescript/commonjs/live-activity/api.d.ts +7 -0
  45. package/build/typescript/commonjs/live-activity/api.d.ts.map +1 -1
  46. package/build/typescript/commonjs/live-activity/dynamic-api.d.ts +54 -0
  47. package/build/typescript/commonjs/live-activity/dynamic-api.d.ts.map +1 -0
  48. package/build/typescript/commonjs/native/NativeVoltra.d.ts +20 -0
  49. package/build/typescript/commonjs/native/NativeVoltra.d.ts.map +1 -1
  50. package/build/typescript/commonjs/types.d.ts +1 -1
  51. package/build/typescript/commonjs/types.d.ts.map +1 -1
  52. package/build/typescript/commonjs/utils/enableDynamicLiveActivityHotReload.d.ts +15 -0
  53. package/build/typescript/commonjs/utils/enableDynamicLiveActivityHotReload.d.ts.map +1 -0
  54. package/build/typescript/commonjs/utils/enableWidgetHotReload.d.ts +5 -7
  55. package/build/typescript/commonjs/utils/enableWidgetHotReload.d.ts.map +1 -1
  56. package/build/typescript/commonjs/utils/useUpdateOnHMR.d.ts +0 -3
  57. package/build/typescript/commonjs/utils/useUpdateOnHMR.d.ts.map +1 -1
  58. package/build/typescript/commonjs/widgets/server-credentials.d.ts +8 -0
  59. package/build/typescript/commonjs/widgets/server-credentials.d.ts.map +1 -1
  60. package/build/typescript/commonjs/widgets/server-update.d.ts +64 -0
  61. package/build/typescript/commonjs/widgets/server-update.d.ts.map +1 -0
  62. package/build/typescript/module/events.d.ts +7 -0
  63. package/build/typescript/module/events.d.ts.map +1 -1
  64. package/build/typescript/module/index.d.ts +3 -0
  65. package/build/typescript/module/index.d.ts.map +1 -1
  66. package/build/typescript/module/live-activity/api.d.ts +7 -0
  67. package/build/typescript/module/live-activity/api.d.ts.map +1 -1
  68. package/build/typescript/module/live-activity/dynamic-api.d.ts +54 -0
  69. package/build/typescript/module/live-activity/dynamic-api.d.ts.map +1 -0
  70. package/build/typescript/module/native/NativeVoltra.d.ts +20 -0
  71. package/build/typescript/module/native/NativeVoltra.d.ts.map +1 -1
  72. package/build/typescript/module/types.d.ts +1 -1
  73. package/build/typescript/module/types.d.ts.map +1 -1
  74. package/build/typescript/module/utils/enableDynamicLiveActivityHotReload.d.ts +15 -0
  75. package/build/typescript/module/utils/enableDynamicLiveActivityHotReload.d.ts.map +1 -0
  76. package/build/typescript/module/utils/enableWidgetHotReload.d.ts +5 -7
  77. package/build/typescript/module/utils/enableWidgetHotReload.d.ts.map +1 -1
  78. package/build/typescript/module/utils/useUpdateOnHMR.d.ts +0 -3
  79. package/build/typescript/module/utils/useUpdateOnHMR.d.ts.map +1 -1
  80. package/build/typescript/module/widgets/server-credentials.d.ts +8 -0
  81. package/build/typescript/module/widgets/server-credentials.d.ts.map +1 -1
  82. package/build/typescript/module/widgets/server-update.d.ts +64 -0
  83. package/build/typescript/module/widgets/server-update.d.ts.map +1 -0
  84. package/expo-plugin/build/cjs/constants.js +20 -1
  85. package/expo-plugin/build/cjs/constants.js.map +1 -1
  86. package/expo-plugin/build/cjs/index.js +6 -0
  87. package/expo-plugin/build/cjs/index.js.map +1 -1
  88. package/expo-plugin/build/cjs/ios/index.js +1 -0
  89. package/expo-plugin/build/cjs/ios/index.js.map +1 -1
  90. package/expo-plugin/build/cjs/ios/infoPlist.js +28 -5
  91. package/expo-plugin/build/cjs/ios/infoPlist.js.map +1 -1
  92. package/expo-plugin/build/cjs/ios/serverUpdate.js +25 -0
  93. package/expo-plugin/build/cjs/ios/serverUpdate.js.map +1 -0
  94. package/expo-plugin/build/cjs/ios-widget/clientRendered.js +4 -4
  95. package/expo-plugin/build/cjs/ios-widget/clientRendered.js.map +1 -1
  96. package/expo-plugin/build/cjs/ios-widget/clientRenderedPrerender.js +5 -5
  97. package/expo-plugin/build/cjs/ios-widget/clientRenderedPrerender.js.map +1 -1
  98. package/expo-plugin/build/cjs/ios-widget/dynamic-live-activity/swift.js +130 -0
  99. package/expo-plugin/build/cjs/ios-widget/dynamic-live-activity/swift.js.map +1 -0
  100. package/expo-plugin/build/cjs/ios-widget/files/index.js +9 -2
  101. package/expo-plugin/build/cjs/ios-widget/files/index.js.map +1 -1
  102. package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js +6 -3
  103. package/expo-plugin/build/cjs/ios-widget/files/infoPlist.js.map +1 -1
  104. package/expo-plugin/build/cjs/ios-widget/files/manifest.js +24 -0
  105. package/expo-plugin/build/cjs/ios-widget/files/manifest.js.map +1 -1
  106. package/expo-plugin/build/cjs/ios-widget/files/swift-utils.js +7 -0
  107. package/expo-plugin/build/cjs/ios-widget/files/swift-utils.js.map +1 -0
  108. package/expo-plugin/build/cjs/ios-widget/files/swift.js +56 -26
  109. package/expo-plugin/build/cjs/ios-widget/files/swift.js.map +1 -1
  110. package/expo-plugin/build/cjs/ios-widget/index.js +9 -3
  111. package/expo-plugin/build/cjs/ios-widget/index.js.map +1 -1
  112. package/expo-plugin/build/cjs/ios-widget/widgetPlist.js +34 -22
  113. package/expo-plugin/build/cjs/ios-widget/widgetPlist.js.map +1 -1
  114. package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js +51 -11
  115. package/expo-plugin/build/cjs/ios-widget/xcode/buildPhases.js.map +1 -1
  116. package/expo-plugin/build/cjs/ios-widget/xcode/index.js +21 -5
  117. package/expo-plugin/build/cjs/ios-widget/xcode/index.js.map +1 -1
  118. package/expo-plugin/build/cjs/utils/urlScheme.js +36 -14
  119. package/expo-plugin/build/cjs/utils/urlScheme.js.map +1 -1
  120. package/expo-plugin/build/cjs/validation.js +54 -0
  121. package/expo-plugin/build/cjs/validation.js.map +1 -1
  122. package/expo-plugin/build/esm/constants.js +17 -0
  123. package/expo-plugin/build/esm/constants.js.map +1 -1
  124. package/expo-plugin/build/esm/index.js +6 -0
  125. package/expo-plugin/build/esm/index.js.map +1 -1
  126. package/expo-plugin/build/esm/ios/index.js +1 -0
  127. package/expo-plugin/build/esm/ios/index.js.map +1 -1
  128. package/expo-plugin/build/esm/ios/infoPlist.js +28 -5
  129. package/expo-plugin/build/esm/ios/infoPlist.js.map +1 -1
  130. package/expo-plugin/build/esm/ios/serverUpdate.js +21 -0
  131. package/expo-plugin/build/esm/ios/serverUpdate.js.map +1 -0
  132. package/expo-plugin/build/esm/ios-widget/clientRendered.js +5 -5
  133. package/expo-plugin/build/esm/ios-widget/clientRendered.js.map +1 -1
  134. package/expo-plugin/build/esm/ios-widget/clientRenderedPrerender.js +6 -6
  135. package/expo-plugin/build/esm/ios-widget/clientRenderedPrerender.js.map +1 -1
  136. package/expo-plugin/build/esm/ios-widget/dynamic-live-activity/swift.js +122 -0
  137. package/expo-plugin/build/esm/ios-widget/dynamic-live-activity/swift.js.map +1 -0
  138. package/expo-plugin/build/esm/ios-widget/files/index.js +10 -3
  139. package/expo-plugin/build/esm/ios-widget/files/index.js.map +1 -1
  140. package/expo-plugin/build/esm/ios-widget/files/infoPlist.js +6 -3
  141. package/expo-plugin/build/esm/ios-widget/files/infoPlist.js.map +1 -1
  142. package/expo-plugin/build/esm/ios-widget/files/manifest.js +23 -1
  143. package/expo-plugin/build/esm/ios-widget/files/manifest.js.map +1 -1
  144. package/expo-plugin/build/esm/ios-widget/files/swift-utils.js +4 -0
  145. package/expo-plugin/build/esm/ios-widget/files/swift-utils.js.map +1 -0
  146. package/expo-plugin/build/esm/ios-widget/files/swift.js +50 -20
  147. package/expo-plugin/build/esm/ios-widget/files/swift.js.map +1 -1
  148. package/expo-plugin/build/esm/ios-widget/index.js +9 -3
  149. package/expo-plugin/build/esm/ios-widget/index.js.map +1 -1
  150. package/expo-plugin/build/esm/ios-widget/widgetPlist.js +34 -22
  151. package/expo-plugin/build/esm/ios-widget/widgetPlist.js.map +1 -1
  152. package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js +51 -11
  153. package/expo-plugin/build/esm/ios-widget/xcode/buildPhases.js.map +1 -1
  154. package/expo-plugin/build/esm/ios-widget/xcode/index.js +21 -5
  155. package/expo-plugin/build/esm/ios-widget/xcode/index.js.map +1 -1
  156. package/expo-plugin/build/esm/utils/urlScheme.js +34 -14
  157. package/expo-plugin/build/esm/utils/urlScheme.js.map +1 -1
  158. package/expo-plugin/build/esm/validation.js +54 -1
  159. package/expo-plugin/build/esm/validation.js.map +1 -1
  160. package/expo-plugin/build/types/constants.d.ts +10 -1
  161. package/expo-plugin/build/types/constants.d.ts.map +1 -1
  162. package/expo-plugin/build/types/index.d.ts +1 -1
  163. package/expo-plugin/build/types/index.d.ts.map +1 -1
  164. package/expo-plugin/build/types/ios/index.d.ts +2 -0
  165. package/expo-plugin/build/types/ios/index.d.ts.map +1 -1
  166. package/expo-plugin/build/types/ios/infoPlist.d.ts +2 -0
  167. package/expo-plugin/build/types/ios/infoPlist.d.ts.map +1 -1
  168. package/expo-plugin/build/types/ios/serverUpdate.d.ts +11 -0
  169. package/expo-plugin/build/types/ios/serverUpdate.d.ts.map +1 -0
  170. package/expo-plugin/build/types/ios-widget/clientRendered.d.ts.map +1 -1
  171. package/expo-plugin/build/types/ios-widget/clientRenderedPrerender.d.ts.map +1 -1
  172. package/expo-plugin/build/types/ios-widget/dynamic-live-activity/swift.d.ts +7 -0
  173. package/expo-plugin/build/types/ios-widget/dynamic-live-activity/swift.d.ts.map +1 -0
  174. package/expo-plugin/build/types/ios-widget/files/index.d.ts +3 -1
  175. package/expo-plugin/build/types/ios-widget/files/index.d.ts.map +1 -1
  176. package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts +2 -1
  177. package/expo-plugin/build/types/ios-widget/files/infoPlist.d.ts.map +1 -1
  178. package/expo-plugin/build/types/ios-widget/files/manifest.d.ts +9 -2
  179. package/expo-plugin/build/types/ios-widget/files/manifest.d.ts.map +1 -1
  180. package/expo-plugin/build/types/ios-widget/files/swift-utils.d.ts +2 -0
  181. package/expo-plugin/build/types/ios-widget/files/swift-utils.d.ts.map +1 -0
  182. package/expo-plugin/build/types/ios-widget/files/swift.d.ts +6 -2
  183. package/expo-plugin/build/types/ios-widget/files/swift.d.ts.map +1 -1
  184. package/expo-plugin/build/types/ios-widget/index.d.ts +3 -1
  185. package/expo-plugin/build/types/ios-widget/index.d.ts.map +1 -1
  186. package/expo-plugin/build/types/ios-widget/widgetPlist.d.ts.map +1 -1
  187. package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts +3 -1
  188. package/expo-plugin/build/types/ios-widget/xcode/buildPhases.d.ts.map +1 -1
  189. package/expo-plugin/build/types/ios-widget/xcode/index.d.ts +2 -1
  190. package/expo-plugin/build/types/ios-widget/xcode/index.d.ts.map +1 -1
  191. package/expo-plugin/build/types/types.d.ts +23 -4
  192. package/expo-plugin/build/types/types.d.ts.map +1 -1
  193. package/expo-plugin/build/types/utils/urlScheme.d.ts +16 -0
  194. package/expo-plugin/build/types/utils/urlScheme.d.ts.map +1 -1
  195. package/expo-plugin/build/types/validation.d.ts +2 -1
  196. package/expo-plugin/build/types/validation.d.ts.map +1 -1
  197. package/expo-plugin/src/constants.ts +24 -1
  198. package/expo-plugin/src/index.ts +9 -0
  199. package/expo-plugin/src/ios/index.ts +3 -0
  200. package/expo-plugin/src/ios/infoPlist.ts +33 -5
  201. package/expo-plugin/src/ios/serverUpdate.ts +29 -0
  202. package/expo-plugin/src/ios-widget/clientRendered.ts +9 -5
  203. package/expo-plugin/src/ios-widget/clientRenderedPrerender.ts +11 -6
  204. package/expo-plugin/src/ios-widget/dynamic-live-activity/swift.ts +138 -0
  205. package/expo-plugin/src/ios-widget/files/index.ts +15 -4
  206. package/expo-plugin/src/ios-widget/files/infoPlist.ts +17 -3
  207. package/expo-plugin/src/ios-widget/files/manifest.ts +42 -2
  208. package/expo-plugin/src/ios-widget/files/swift-utils.ts +3 -0
  209. package/expo-plugin/src/ios-widget/files/swift.ts +69 -22
  210. package/expo-plugin/src/ios-widget/index.ts +13 -3
  211. package/expo-plugin/src/ios-widget/widgetPlist.ts +37 -23
  212. package/expo-plugin/src/ios-widget/xcode/__snapshots__/applyXcodeChanges.node.test.ts.snap +34 -28
  213. package/expo-plugin/src/ios-widget/xcode/buildPhases.ts +59 -12
  214. package/expo-plugin/src/ios-widget/xcode/index.ts +23 -6
  215. package/expo-plugin/src/types.ts +28 -4
  216. package/expo-plugin/src/utils/urlScheme.ts +47 -17
  217. package/expo-plugin/src/validation.ts +76 -1
  218. package/ios/Package.swift +32 -3
  219. package/ios/VoltraWidget.podspec +1 -0
  220. package/ios/app/NativeVoltra.mm +107 -7
  221. package/ios/app/VoltraLiveActivityManager.swift +30 -0
  222. package/ios/app/VoltraLiveActivityService.swift +77 -5
  223. package/ios/app/VoltraModule.swift +99 -1
  224. package/ios/app/VoltraModuleImpl.swift +100 -2
  225. package/ios/app/VoltraViewComponentView.mm +3 -3
  226. package/ios/app/VoltraWidgetService.swift +147 -12
  227. package/ios/app/dynamic-live-activity/VoltraDynamicLiveActivityService.swift +97 -0
  228. package/ios/app/dynamic-live-activity/VoltraLiveActivityChronology.swift +68 -0
  229. package/ios/shared/DynamicWidgetPropsStore.swift +73 -6
  230. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerFetchResolver.swift +34 -0
  231. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerProps.swift +55 -0
  232. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerPropsStore.swift +146 -0
  233. package/ios/shared/DynamicWidgetServerUpdate/DynamicWidgetServerUpdateRunner.swift +193 -0
  234. package/ios/shared/ServerWidgetContentResolver.swift +60 -0
  235. package/ios/shared/ServerWidgetResponseStore.swift +25 -0
  236. package/ios/shared/ShortNames.swift +6 -0
  237. package/ios/shared/VoltraConfig.swift +41 -0
  238. package/ios/shared/VoltraConstants.swift +15 -0
  239. package/ios/shared/VoltraElement.swift +127 -43
  240. package/ios/shared/VoltraEventBus.swift +52 -7
  241. package/ios/shared/VoltraJSRenderer.swift +90 -22
  242. package/ios/shared/VoltraNode.swift +1 -109
  243. package/ios/shared/VoltraRefreshIntent.swift +1 -1
  244. package/ios/shared/VoltraWidgetKind.swift +41 -0
  245. package/ios/shared/VoltraWidgetServerFetcher.swift +52 -107
  246. package/ios/shared/WidgetServer/VoltraWidgetAppearance.swift +17 -0
  247. package/ios/shared/WidgetServer/VoltraWidgetServer.swift +138 -0
  248. package/ios/shared/WidgetServer/WidgetCanonicalConfiguration.swift +77 -0
  249. package/ios/shared/WidgetServer/WidgetScope.swift +55 -0
  250. package/ios/shared/WidgetServer/WidgetServerEtagStore.swift +55 -0
  251. package/ios/shared/WidgetServer/WidgetServerFetcher.swift +179 -0
  252. package/ios/shared/WidgetServer/WidgetServerRequestBuilder.swift +114 -0
  253. package/ios/shared/WidgetServer/WidgetServerSettingsCodec.swift +47 -0
  254. package/ios/shared/WidgetServer/WidgetServerSettingsResolver.swift +129 -0
  255. package/ios/shared/WidgetServer/WidgetServerSettingsStore.swift +170 -0
  256. package/ios/shared/WidgetServer/WidgetServerSettingsValidator.swift +73 -0
  257. package/ios/shared/WidgetServer/WidgetServerUpdateSettings.swift +123 -0
  258. package/ios/shared/WidgetServer/WidgetServerUpdateSettingsJson.swift +115 -0
  259. package/ios/shared/dynamic-live-activity/DynamicLiveActivityPropsCodec.swift +13 -0
  260. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityBundleSource.swift +156 -0
  261. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityObserver.swift +97 -0
  262. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityOperations.swift +105 -0
  263. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityPayloadValidator.swift +55 -0
  264. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRegistry.swift +143 -0
  265. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderFailureQueue.swift +158 -0
  266. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderFailureReporter.swift +120 -0
  267. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityRenderer.swift +370 -0
  268. package/ios/shared/dynamic-live-activity/VoltraDynamicLiveActivityTypes.swift +87 -0
  269. package/ios/shared/dynamic-live-activity/VoltraLiveActivityOrder.swift +19 -0
  270. package/ios/target/VoltraClientWidgetRuntime.swift +44 -6
  271. package/ios/target/VoltraDynamicWidgetServerUpdateProvider.swift +204 -0
  272. package/ios/target/VoltraHomeWidget.swift +85 -90
  273. package/ios/ui/Extensions/VoltraNode+View.swift +113 -0
  274. package/ios/ui/Generated/Parameters/ChartParameters.swift +3 -0
  275. package/ios/ui/Helpers/VoltraDeepLinkResolver.swift +2 -2
  276. package/ios/ui/Views/VoltraChart.swift +108 -0
  277. package/package.json +4 -4
  278. package/src/events.ts +34 -0
  279. package/src/index.ts +22 -0
  280. package/src/live-activity/api.ts +2 -2
  281. package/src/live-activity/dynamic-api.ts +240 -0
  282. package/src/native/NativeVoltra.ts +21 -0
  283. package/src/types.ts +4 -0
  284. package/src/utils/enableDynamicLiveActivityHotReload.ts +50 -0
  285. package/src/utils/enableWidgetHotReload.ts +9 -16
  286. package/src/utils/useUpdateOnHMR.ts +3 -12
  287. package/src/widgets/server-credentials.ts +8 -0
  288. package/src/widgets/server-update.ts +84 -0
  289. /package/ios/shared/{VoltraKeychainHelper.swift → WidgetServer/VoltraKeychainHelper.swift} +0 -0
@@ -1,12 +1,15 @@
1
1
  import { ConfigPlugin, withInfoPlist } from '@expo/config-plugins'
2
2
 
3
+ import { widgetKindOverrides } from '../constants'
3
4
  import type { IOSWidgetConfig } from '../types'
5
+ import { resolveIOSWidgetServerUpdate } from './serverUpdate'
4
6
 
5
7
  export interface ConfigureInfoPlistProps {
6
8
  groupIdentifier?: string
7
9
  widgetIds?: string[]
8
10
  widgets?: IOSWidgetConfig[]
9
11
  keychainGroup?: string
12
+ voltraVersion: string
10
13
  }
11
14
 
12
15
  /**
@@ -16,14 +19,16 @@ export interface ConfigureInfoPlistProps {
16
19
  * - NSSupportsLiveActivities: Enables Live Activities support
17
20
  * - Voltra_AppGroupIdentifier: App group ID for widget communication (if provided)
18
21
  * - Voltra_WidgetIds: Array of widget IDs for native module access (if provided)
22
+ * - Voltra_WidgetKinds: Map of widget IDs to custom WidgetKit kinds (if any widget sets `kind`)
19
23
  * - Voltra_WidgetServerUrls: Map of widget IDs to server URLs (if any widgets have serverUpdate)
20
24
  * - Voltra_WidgetServerIntervals: Map of widget IDs to update intervals (if any widgets have serverUpdate)
21
25
  * - Voltra_KeychainGroup: Keychain access group for shared credentials (if provided)
22
26
  */
23
- export const configureInfoPlist: ConfigPlugin<ConfigureInfoPlistProps> = (config, props = {}) => {
27
+ export const configureInfoPlist: ConfigPlugin<ConfigureInfoPlistProps> = (config, props) => {
24
28
  return withInfoPlist(config, (mod) => {
25
29
  mod.modResults.NSSupportsLiveActivities = true
26
30
  mod.modResults.NSSupportsLiveActivitiesFrequentUpdates = false
31
+ mod.modResults.Voltra_Version = props.voltraVersion
27
32
 
28
33
  // Only add group identifier if provided
29
34
  if (props.groupIdentifier) {
@@ -35,21 +40,44 @@ export const configureInfoPlist: ConfigPlugin<ConfigureInfoPlistProps> = (config
35
40
  mod.modResults.Voltra_WidgetIds = props.widgetIds
36
41
  }
37
42
 
43
+ // Store custom widget kinds so native code can map ids to kinds and back. A prebuild over an
44
+ // existing ios/ directory keeps whatever the plist already holds, so a `kind` that was removed
45
+ // from the config has to be deleted here or the widget would keep a kind nobody configured.
46
+ const widgetKinds = widgetKindOverrides(props.widgets)
47
+ if (widgetKinds) {
48
+ mod.modResults.Voltra_WidgetKinds = widgetKinds
49
+ } else {
50
+ delete mod.modResults.Voltra_WidgetKinds
51
+ }
52
+
38
53
  // Configure server update URLs and intervals for widgets
39
54
  if (props.widgets && props.widgets.length > 0) {
40
55
  const serverUrls: Record<string, string> = {}
41
56
  const serverIntervals: Record<string, number> = {}
42
57
 
43
58
  for (const widget of props.widgets) {
44
- if (widget.serverUpdate) {
45
- serverUrls[widget.id] = widget.serverUpdate.url
46
- serverIntervals[widget.id] = widget.serverUpdate.intervalMinutes ?? 15
59
+ const serverUpdate = resolveIOSWidgetServerUpdate(widget)
60
+
61
+ if (!serverUpdate) {
62
+ continue
63
+ }
64
+
65
+ // Every server-driven widget gets an interval, so this dictionary's keys are the set of
66
+ // server-driven widget ids the runtime settings store validates against. A URL is written
67
+ // only when app.json set one; otherwise the app supplies it with setWidgetServerUpdate.
68
+ serverIntervals[widget.id] = serverUpdate.intervalMinutes
69
+
70
+ if (serverUpdate.url !== undefined) {
71
+ serverUrls[widget.id] = serverUpdate.url
47
72
  }
48
73
  }
49
74
 
75
+ if (Object.keys(serverIntervals).length > 0) {
76
+ mod.modResults.Voltra_WidgetServerIntervals = serverIntervals
77
+ }
78
+
50
79
  if (Object.keys(serverUrls).length > 0) {
51
80
  mod.modResults.Voltra_WidgetServerUrls = serverUrls
52
- mod.modResults.Voltra_WidgetServerIntervals = serverIntervals
53
81
  }
54
82
  }
55
83
 
@@ -0,0 +1,29 @@
1
+ import { resolveWidgetServerUpdate } from '@use-voltra/expo-plugin'
2
+
3
+ import type { ResolvedWidgetServerUpdateConfig, WidgetServerUpdateRules } from '@use-voltra/expo-plugin'
4
+
5
+ import type { IOSWidgetConfig } from '../types'
6
+
7
+ /**
8
+ * iOS payload widgets have always defaulted to 15 minutes and accepted anything down to 1, since
9
+ * WidgetKit stretches a timeline it cannot honour rather than refusing it. A widget with an
10
+ * `entry` follows ADR 0002 instead: default 15, floor 15 on both platforms.
11
+ */
12
+ export function iosServerUpdateRules(widget: Pick<IOSWidgetConfig, 'entry'>): WidgetServerUpdateRules {
13
+ return {
14
+ hasEntry: widget.entry !== undefined,
15
+ defaultIntervalMinutes: 15,
16
+ minimumIntervalMinutes: 1,
17
+ }
18
+ }
19
+
20
+ /** `serverUpdate` with defaults applied, as the plist and Swift generators consume it. */
21
+ export function resolveIOSWidgetServerUpdate(
22
+ widget: Pick<IOSWidgetConfig, 'entry' | 'serverUpdate'>
23
+ ): ResolvedWidgetServerUpdateConfig | undefined {
24
+ if (widget.serverUpdate === undefined) {
25
+ return undefined
26
+ }
27
+
28
+ return resolveWidgetServerUpdate(widget.serverUpdate, iosServerUpdateRules(widget))
29
+ }
@@ -1,7 +1,7 @@
1
1
  import * as fs from 'fs'
2
2
  import * as path from 'path'
3
3
 
4
- import { evaluateWidgetModuleExports } from '@use-voltra/expo-plugin'
4
+ import { createPrerenderWidgetModuleLoader, type WidgetModuleLoader } from '@use-voltra/expo-plugin'
5
5
 
6
6
  import type { IOSWidgetConfig } from '../types'
7
7
 
@@ -30,7 +30,8 @@ let hasWarnedExperimental = false
30
30
 
31
31
  /** Inspect every widget once and tag entry-backed widgets as Dynamic Widgets. */
32
32
  export function detectClientRenderedWidgets(widgets: IOSWidgetConfig[], projectRoot: string): DetectedIOSWidget[] {
33
- const detected = widgets.map((widget) => detectSingleWidget(widget, projectRoot))
33
+ const loader = createPrerenderWidgetModuleLoader(projectRoot, 'ios')
34
+ const detected = widgets.map((widget) => detectSingleWidget(widget, projectRoot, loader))
34
35
 
35
36
  if (!hasWarnedExperimental) {
36
37
  const clientWidgetIds = detected.filter((widget) => widget.clientRendered).map((widget) => widget.id)
@@ -47,7 +48,11 @@ export function detectClientRenderedWidgets(widgets: IOSWidgetConfig[], projectR
47
48
  return detected
48
49
  }
49
50
 
50
- function detectSingleWidget(widget: IOSWidgetConfig, projectRoot: string): DetectedIOSWidget {
51
+ function detectSingleWidget(
52
+ widget: IOSWidgetConfig,
53
+ projectRoot: string,
54
+ loader: WidgetModuleLoader
55
+ ): DetectedIOSWidget {
51
56
  if (widget.entry === undefined) {
52
57
  return {
53
58
  ...widget,
@@ -65,8 +70,7 @@ function detectSingleWidget(widget: IOSWidgetConfig, projectRoot: string): Detec
65
70
  )
66
71
  }
67
72
 
68
- const widgetModule = evaluateWidgetModuleExports(projectRoot, sourcePath)
69
- const widgetFn = widgetModule?.default ?? widgetModule
73
+ const widgetFn = loader.loadDefaultExport(sourcePath)
70
74
  if (typeof widgetFn !== 'function') {
71
75
  throw new Error(
72
76
  `[voltra] Dynamic Widget "${widget.id}" at ${path.relative(
@@ -1,4 +1,9 @@
1
- import { evaluateWidgetModuleExports, logger, type PrerenderedWidgetStates } from '@use-voltra/expo-plugin'
1
+ import {
2
+ createPrerenderWidgetModuleLoader,
3
+ logger,
4
+ resolveInstalledPackageVersion,
5
+ type PrerenderedWidgetStates,
6
+ } from '@use-voltra/expo-plugin'
2
7
 
3
8
  import type { DetectedIOSWidget } from './clientRendered'
4
9
 
@@ -31,7 +36,7 @@ const SINGLE_LOCALE_KEY = '__default'
31
36
  * mirror `WidgetEnvironment` from packages/core/src/widget-environment.ts so the widget
32
37
  * function sees the same shape it gets at runtime.
33
38
  */
34
- function buildPlaceholderEnv(): Record<string, unknown> {
39
+ function buildPlaceholderEnv(voltraVersion: string): Record<string, unknown> {
35
40
  return {
36
41
  date: Date.now(),
37
42
  widgetFamily: 'systemMedium',
@@ -44,7 +49,7 @@ function buildPlaceholderEnv(): Record<string, unknown> {
44
49
  isDev: false,
45
50
  metroUrl: null,
46
51
  appVersion: 'unknown',
47
- voltraVersion: '1.4.1',
52
+ voltraVersion,
48
53
  },
49
54
  }
50
55
  }
@@ -75,12 +80,12 @@ export async function prerenderClientRenderedWidgets(
75
80
  renderVoltraVariantToJson: (element: unknown) => unknown
76
81
  }
77
82
 
78
- const placeholderEnv = buildPlaceholderEnv()
83
+ const placeholderEnv = buildPlaceholderEnv(resolveInstalledPackageVersion(projectRoot, '@use-voltra/ios-client'))
84
+ const loader = createPrerenderWidgetModuleLoader(projectRoot, 'ios')
79
85
 
80
86
  for (const widget of clientWidgets) {
81
87
  try {
82
- const widgetModule = evaluateWidgetModuleExports(projectRoot, widget.clientSourcePath)
83
- const widgetFn = widgetModule?.default ?? widgetModule
88
+ const widgetFn = loader.loadDefaultExport(widget.clientSourcePath)
84
89
  if (typeof widgetFn !== 'function') {
85
90
  throw new Error(
86
91
  `Expected the entry module at ${widget.clientSourcePath} to default-export a function or component.`
@@ -0,0 +1,138 @@
1
+ import dedent from 'dedent'
2
+
3
+ import { getDynamicLiveActivityAttributesType } from '@use-voltra/expo-plugin'
4
+
5
+ import type { IOSDynamicLiveActivityConfig } from '../../types'
6
+ import { escapeForSwiftStringLiteral } from '../files/swift-utils'
7
+
8
+ export function generateDynamicLiveActivityWidgetInstances(liveActivities: IOSDynamicLiveActivityConfig[]): string {
9
+ return sortedDefinitions(liveActivities)
10
+ .map((liveActivity) => `VoltraDynamicLiveActivity_${getDynamicLiveActivityAttributesType(liveActivity.id)}()`)
11
+ .join('\n ')
12
+ }
13
+
14
+ /** Generates the Dynamic Live Activity types shared by the app and extension targets. */
15
+ export function generateDynamicLiveActivityTypesSwift(liveActivities: IOSDynamicLiveActivityConfig[]): string {
16
+ const definitions = sortedDefinitions(liveActivities)
17
+ const typeDefinitions = definitions.map(generateDynamicLiveActivitySwift).map(normalizeIndent).join('\n\n')
18
+
19
+ const header = dedent`
20
+ //
21
+ // VoltraDynamicLiveActivityTypes.swift
22
+ //
23
+ // Auto-generated by Voltra config plugin. Do not edit.
24
+ //
25
+
26
+ import ActivityKit
27
+ import Foundation
28
+
29
+ import VoltraRuntime
30
+
31
+ @objc(VoltraGeneratedDynamicLiveActivityRegistration)
32
+ public final class VoltraGeneratedDynamicLiveActivityRegistration: NSObject {
33
+ @objc public static func registerDefinitions() {
34
+ ${definitions
35
+ .map(
36
+ (liveActivity) =>
37
+ ` VoltraDynamicLiveActivityRegistry.shared.register(${getDynamicLiveActivityAttributesType(
38
+ liveActivity.id
39
+ )}.self)`
40
+ )
41
+ .join('\n')}
42
+ }
43
+ }
44
+
45
+ `
46
+ return [header.trim(), typeDefinitions.trim()].filter(Boolean).join('\n\n')
47
+ }
48
+
49
+ /** Generates extension-only ActivityConfiguration declarations for Dynamic Live Activities. */
50
+ export function generateDynamicLiveActivitiesSwift(liveActivities: IOSDynamicLiveActivityConfig[]): string {
51
+ const configurations = sortedDefinitions(liveActivities)
52
+ .map((liveActivity) => {
53
+ const attributesType = getDynamicLiveActivityAttributesType(liveActivity.id)
54
+ const definitionId = escapeForSwiftStringLiteral(liveActivity.id)
55
+ return dedent`
56
+ public struct VoltraDynamicLiveActivity_${attributesType}: Widget {
57
+ public init() {}
58
+
59
+ public var body: some WidgetConfiguration {
60
+ if #available(iOS 18.0, *) {
61
+ return adaptiveConfig()
62
+ } else {
63
+ return defaultConfig()
64
+ }
65
+ }
66
+
67
+ @available(iOS 18.0, *)
68
+ private func adaptiveConfig() -> some WidgetConfiguration {
69
+ ActivityConfiguration(for: ${attributesType}.self) { context in
70
+ VoltraDynamicLiveActivityRenderer.lockScreen(definitionId: "${definitionId}", context: context)
71
+ } dynamicIsland: { context in
72
+ VoltraDynamicLiveActivityRenderer.dynamicIsland(definitionId: "${definitionId}", context: context)
73
+ }
74
+ .supplementalActivityFamilies([.small, .medium])
75
+ }
76
+
77
+ private func defaultConfig() -> some WidgetConfiguration {
78
+ ActivityConfiguration(for: ${attributesType}.self) { context in
79
+ VoltraDynamicLiveActivityRenderer.lockScreen(definitionId: "${definitionId}", context: context)
80
+ } dynamicIsland: { context in
81
+ VoltraDynamicLiveActivityRenderer.dynamicIsland(definitionId: "${definitionId}", context: context)
82
+ }
83
+ }
84
+ }
85
+ `
86
+ })
87
+ .map(normalizeIndent)
88
+ .join('\n\n')
89
+
90
+ const header = dedent`
91
+ //
92
+ // VoltraDynamicLiveActivities.swift
93
+ //
94
+ // Auto-generated by Voltra config plugin. Do not edit.
95
+ //
96
+
97
+ import ActivityKit
98
+ import SwiftUI
99
+ import WidgetKit
100
+ import VoltraRuntime
101
+
102
+ `
103
+ return [header.trim(), configurations.trim()].filter(Boolean).join('\n\n')
104
+ }
105
+
106
+ function generateDynamicLiveActivitySwift(liveActivity: IOSDynamicLiveActivityConfig): string {
107
+ const attributesType = getDynamicLiveActivityAttributesType(liveActivity.id)
108
+ const definitionId = escapeForSwiftStringLiteral(liveActivity.id)
109
+
110
+ return dedent`
111
+ public struct ${attributesType}: ActivityAttributes {
112
+ public typealias ContentState = VoltraDynamicLiveActivityContentState
113
+
114
+ public let name: String
115
+ public let deepLinkUrl: String?
116
+
117
+ public init(name: String, deepLinkUrl: String?) {
118
+ self.name = name
119
+ self.deepLinkUrl = deepLinkUrl
120
+ }
121
+ }
122
+
123
+ extension ${attributesType}: VoltraDynamicLiveActivityDefinition {
124
+ public static let definitionId = "${definitionId}"
125
+ }
126
+
127
+ `
128
+ }
129
+
130
+ function sortedDefinitions(liveActivities: IOSDynamicLiveActivityConfig[]): IOSDynamicLiveActivityConfig[] {
131
+ return [...liveActivities].sort((left, right) => left.id.localeCompare(right.id))
132
+ }
133
+
134
+ function normalizeIndent(source: string): string {
135
+ const lines = source.trim().split('\n')
136
+ const indent = Math.min(...lines.filter(Boolean).map((line) => line.match(/^\s*/)?.[0].length ?? 0))
137
+ return lines.map((line) => line.slice(indent)).join('\n')
138
+ }
@@ -2,20 +2,22 @@ import { ConfigPlugin, withDangerousMod } from '@expo/config-plugins'
2
2
  import * as fs from 'fs'
3
3
  import * as path from 'path'
4
4
 
5
- import type { IOSWidgetConfig } from '../../types'
5
+ import type { IOSDynamicLiveActivityConfig, IOSWidgetConfig } from '../../types'
6
6
  import { generateAssets } from './assets'
7
7
  import { generateEntitlements } from './entitlements'
8
8
  import { generateInfoPlist } from './infoPlist'
9
- import { generateIOSDynamicWidgetsManifest } from './manifest'
9
+ import { generateIOSDynamicLiveActivitiesManifest, generateIOSDynamicWidgetsManifest } from './manifest'
10
10
  import { generateSwiftFiles } from './swift'
11
11
 
12
12
  export interface GenerateWidgetExtensionFilesProps {
13
13
  targetName: string
14
14
  widgets?: IOSWidgetConfig[]
15
+ liveActivities?: IOSDynamicLiveActivityConfig[]
15
16
  groupIdentifier?: string
16
17
  keychainGroup?: string
17
18
  version: string
18
19
  buildNumber: string
20
+ voltraVersion: string
19
21
  }
20
22
 
21
23
  /**
@@ -31,7 +33,8 @@ export interface GenerateWidgetExtensionFilesProps {
31
33
  * This should run before configureXcodeProject so the files exist when Xcode project is configured.
32
34
  */
33
35
  export const generateWidgetExtensionFiles: ConfigPlugin<GenerateWidgetExtensionFilesProps> = (config, props) => {
34
- const { targetName, widgets, groupIdentifier, keychainGroup, version, buildNumber } = props
36
+ const { targetName, widgets, liveActivities, groupIdentifier, keychainGroup, version, buildNumber, voltraVersion } =
37
+ props
35
38
 
36
39
  return withDangerousMod(config, [
37
40
  'ios',
@@ -49,7 +52,7 @@ export const generateWidgetExtensionFiles: ConfigPlugin<GenerateWidgetExtensionF
49
52
  }
50
53
 
51
54
  // Generate Info.plist
52
- generateInfoPlist(targetPath, targetName, version, buildNumber)
55
+ generateInfoPlist(targetPath, targetName, version, buildNumber, voltraVersion)
53
56
 
54
57
  // Generate Assets.xcassets and copy user images
55
58
  generateAssets({ targetPath })
@@ -59,6 +62,7 @@ export const generateWidgetExtensionFiles: ConfigPlugin<GenerateWidgetExtensionF
59
62
  targetPath,
60
63
  projectRoot,
61
64
  widgets,
65
+ liveActivities,
62
66
  })
63
67
 
64
68
  // Write the iOS-owned Dynamic Widgets manifest for Metro to consume later.
@@ -67,6 +71,13 @@ export const generateWidgetExtensionFiles: ConfigPlugin<GenerateWidgetExtensionF
67
71
  widgets,
68
72
  })
69
73
 
74
+ // Dynamic Live Activities have their own Metro manifest so their IDs may overlap with
75
+ // Dynamic Widgets and stale declarations never leak into a later prebuild.
76
+ generateIOSDynamicLiveActivitiesManifest({
77
+ projectRoot,
78
+ liveActivities,
79
+ })
80
+
70
81
  // Generate entitlements file (may be empty if no groupIdentifier or keychainGroup)
71
82
  generateEntitlements({
72
83
  targetPath,
@@ -9,7 +9,12 @@ import { logger } from '@use-voltra/expo-plugin'
9
9
  * This includes version information and the required WidgetKit extension point.
10
10
  * Version keys are written directly to the plist following the Expo pattern.
11
11
  */
12
- function generateInfoPlistContent(targetName: string, version: string, buildNumber: string): string {
12
+ function generateInfoPlistContent(
13
+ targetName: string,
14
+ version: string,
15
+ buildNumber: string,
16
+ voltraVersion: string
17
+ ): string {
13
18
  return `<?xml version="1.0" encoding="UTF-8"?>
14
19
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
15
20
  <plist version="1.0">
@@ -32,6 +37,8 @@ function generateInfoPlistContent(targetName: string, version: string, buildNumb
32
37
  <string>${version}</string>
33
38
  <key>CFBundleVersion</key>
34
39
  <string>${buildNumber}</string>
40
+ <key>Voltra_Version</key>
41
+ <string>${voltraVersion}</string>
35
42
  <key>NSExtension</key>
36
43
  <dict>
37
44
  <key>NSExtensionPointIdentifier</key>
@@ -49,9 +56,16 @@ function generateInfoPlistContent(targetName: string, version: string, buildNumb
49
56
  * @param targetName - The widget extension target name (used for CFBundleDisplayName)
50
57
  * @param version - The app version (CFBundleShortVersionString)
51
58
  * @param buildNumber - The build number (CFBundleVersion)
59
+ * @param voltraVersion - The installed @use-voltra/ios-client package version
52
60
  */
53
- export function generateInfoPlist(targetPath: string, targetName: string, version: string, buildNumber: string): void {
61
+ export function generateInfoPlist(
62
+ targetPath: string,
63
+ targetName: string,
64
+ version: string,
65
+ buildNumber: string,
66
+ voltraVersion: string
67
+ ): void {
54
68
  const infoPlistPath = path.join(targetPath, 'Info.plist')
55
- fs.writeFileSync(infoPlistPath, generateInfoPlistContent(targetName, version, buildNumber))
69
+ fs.writeFileSync(infoPlistPath, generateInfoPlistContent(targetName, version, buildNumber, voltraVersion))
56
70
  logger.info('Generated Info.plist')
57
71
  }
@@ -1,17 +1,28 @@
1
1
  import * as fs from 'fs'
2
2
  import * as path from 'path'
3
3
 
4
- import { type DynamicWidgetManifest, logger, validateWidgetEntry } from '@use-voltra/expo-plugin'
4
+ import {
5
+ type DynamicLiveActivityManifest,
6
+ type DynamicWidgetManifest,
7
+ logger,
8
+ validateWidgetEntry,
9
+ } from '@use-voltra/expo-plugin'
5
10
 
6
- import type { IOSWidgetConfig } from '../../types'
11
+ import type { IOSDynamicLiveActivityConfig, IOSWidgetConfig } from '../../types'
7
12
 
8
13
  const MANIFEST_PATH = path.join('.voltra', 'manifest.ios.json')
14
+ const LIVE_ACTIVITIES_MANIFEST_PATH = path.join('.voltra', 'manifest.ios.live-activities.json')
9
15
 
10
16
  export interface GenerateIOSDynamicWidgetsManifestOptions {
11
17
  projectRoot: string
12
18
  widgets?: IOSWidgetConfig[]
13
19
  }
14
20
 
21
+ export interface GenerateIOSDynamicLiveActivitiesManifestOptions {
22
+ projectRoot: string
23
+ liveActivities?: IOSDynamicLiveActivityConfig[]
24
+ }
25
+
15
26
  export function createIOSDynamicWidgetsManifest(
16
27
  projectRoot: string,
17
28
  widgets: IOSWidgetConfig[]
@@ -36,6 +47,22 @@ export function createIOSDynamicWidgetsManifest(
36
47
  }
37
48
  }
38
49
 
50
+ export function createIOSDynamicLiveActivitiesManifest(
51
+ projectRoot: string,
52
+ liveActivities: IOSDynamicLiveActivityConfig[]
53
+ ): DynamicLiveActivityManifest {
54
+ return {
55
+ version: 1,
56
+ platform: 'ios',
57
+ liveActivities: [...liveActivities]
58
+ .sort((left, right) => left.id.localeCompare(right.id))
59
+ .map((liveActivity) => ({
60
+ id: liveActivity.id,
61
+ entry: validateWidgetEntry(liveActivity.entry, liveActivity.id, projectRoot),
62
+ })),
63
+ }
64
+ }
65
+
39
66
  export function generateIOSDynamicWidgetsManifest(options: GenerateIOSDynamicWidgetsManifestOptions): void {
40
67
  const { projectRoot, widgets } = options
41
68
  const manifestPath = path.join(projectRoot, MANIFEST_PATH)
@@ -45,3 +72,16 @@ export function generateIOSDynamicWidgetsManifest(options: GenerateIOSDynamicWid
45
72
  fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`)
46
73
  logger.info(`Generated ${MANIFEST_PATH}`)
47
74
  }
75
+
76
+ /** Writes the dedicated Dynamic Live Activity manifest on every prebuild, including when empty. */
77
+ export function generateIOSDynamicLiveActivitiesManifest(
78
+ options: GenerateIOSDynamicLiveActivitiesManifestOptions
79
+ ): void {
80
+ const { projectRoot, liveActivities } = options
81
+ const manifestPath = path.join(projectRoot, LIVE_ACTIVITIES_MANIFEST_PATH)
82
+ const manifest = createIOSDynamicLiveActivitiesManifest(projectRoot, liveActivities ?? [])
83
+
84
+ fs.mkdirSync(path.dirname(manifestPath), { recursive: true })
85
+ fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`)
86
+ logger.info(`Generated ${LIVE_ACTIVITIES_MANIFEST_PATH}`)
87
+ }
@@ -0,0 +1,3 @@
1
+ export function escapeForSwiftStringLiteral(value: string): string {
2
+ return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r')
3
+ }