@use-voltra/expo-plugin 1.3.0

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 (244) hide show
  1. package/README.md +34 -0
  2. package/build/cjs/android/files/assets.js +259 -0
  3. package/build/cjs/android/files/assets.js.map +1 -0
  4. package/build/cjs/android/files/fonts.js +69 -0
  5. package/build/cjs/android/files/fonts.js.map +1 -0
  6. package/build/cjs/android/files/index.js +81 -0
  7. package/build/cjs/android/files/index.js.map +1 -0
  8. package/build/cjs/android/files/initialStates.js +83 -0
  9. package/build/cjs/android/files/initialStates.js.map +1 -0
  10. package/build/cjs/android/files/kotlin.js +142 -0
  11. package/build/cjs/android/files/kotlin.js.map +1 -0
  12. package/build/cjs/android/files/xml.js +247 -0
  13. package/build/cjs/android/files/xml.js.map +1 -0
  14. package/build/cjs/android/index.js +33 -0
  15. package/build/cjs/android/index.js.map +1 -0
  16. package/build/cjs/android/manifest.js +63 -0
  17. package/build/cjs/android/manifest.js.map +1 -0
  18. package/build/cjs/constants.js +48 -0
  19. package/build/cjs/constants.js.map +1 -0
  20. package/build/cjs/index.js +71 -0
  21. package/build/cjs/index.js.map +1 -0
  22. package/build/cjs/ios/eas.js +28 -0
  23. package/build/cjs/ios/eas.js.map +1 -0
  24. package/build/cjs/ios/entitlements.js +46 -0
  25. package/build/cjs/ios/entitlements.js.map +1 -0
  26. package/build/cjs/ios/index.js +39 -0
  27. package/build/cjs/ios/index.js.map +1 -0
  28. package/build/cjs/ios/infoPlist.js +51 -0
  29. package/build/cjs/ios/infoPlist.js.map +1 -0
  30. package/build/cjs/ios/pushNotifications.js +22 -0
  31. package/build/cjs/ios/pushNotifications.js.map +1 -0
  32. package/build/cjs/ios-widget/eas.js +66 -0
  33. package/build/cjs/ios-widget/eas.js.map +1 -0
  34. package/build/cjs/ios-widget/files/assets.js +199 -0
  35. package/build/cjs/ios-widget/files/assets.js.map +1 -0
  36. package/build/cjs/ios-widget/files/entitlements.js +77 -0
  37. package/build/cjs/ios-widget/files/entitlements.js.map +1 -0
  38. package/build/cjs/ios-widget/files/index.js +92 -0
  39. package/build/cjs/ios-widget/files/index.js.map +1 -0
  40. package/build/cjs/ios-widget/files/infoPlist.js +91 -0
  41. package/build/cjs/ios-widget/files/infoPlist.js.map +1 -0
  42. package/build/cjs/ios-widget/files/swift.js +256 -0
  43. package/build/cjs/ios-widget/files/swift.js.map +1 -0
  44. package/build/cjs/ios-widget/fonts.js +151 -0
  45. package/build/cjs/ios-widget/fonts.js.map +1 -0
  46. package/build/cjs/ios-widget/index.js +46 -0
  47. package/build/cjs/ios-widget/index.js.map +1 -0
  48. package/build/cjs/ios-widget/podfile.js +43 -0
  49. package/build/cjs/ios-widget/podfile.js.map +1 -0
  50. package/build/cjs/ios-widget/widgetPlist.js +99 -0
  51. package/build/cjs/ios-widget/widgetPlist.js.map +1 -0
  52. package/build/cjs/ios-widget/xcode/buildPhases.js +245 -0
  53. package/build/cjs/ios-widget/xcode/buildPhases.js.map +1 -0
  54. package/build/cjs/ios-widget/xcode/configurationList.js +91 -0
  55. package/build/cjs/ios-widget/xcode/configurationList.js.map +1 -0
  56. package/build/cjs/ios-widget/xcode/groups.js +65 -0
  57. package/build/cjs/ios-widget/xcode/groups.js.map +1 -0
  58. package/build/cjs/ios-widget/xcode/index.js +155 -0
  59. package/build/cjs/ios-widget/xcode/index.js.map +1 -0
  60. package/build/cjs/ios-widget/xcode/mainAppSettings.js +71 -0
  61. package/build/cjs/ios-widget/xcode/mainAppSettings.js.map +1 -0
  62. package/build/cjs/ios-widget/xcode/productFile.js +74 -0
  63. package/build/cjs/ios-widget/xcode/productFile.js.map +1 -0
  64. package/build/cjs/ios-widget/xcode/target.js +113 -0
  65. package/build/cjs/ios-widget/xcode/target.js.map +1 -0
  66. package/build/cjs/package.json +3 -0
  67. package/build/cjs/types.js +3 -0
  68. package/build/cjs/types.js.map +1 -0
  69. package/build/cjs/utils/entitlements.js +21 -0
  70. package/build/cjs/utils/entitlements.js.map +1 -0
  71. package/build/cjs/utils/fileDiscovery.js +107 -0
  72. package/build/cjs/utils/fileDiscovery.js.map +1 -0
  73. package/build/cjs/utils/fonts.js +75 -0
  74. package/build/cjs/utils/fonts.js.map +1 -0
  75. package/build/cjs/utils/logger.js +51 -0
  76. package/build/cjs/utils/logger.js.map +1 -0
  77. package/build/cjs/utils/prerender.js +191 -0
  78. package/build/cjs/utils/prerender.js.map +1 -0
  79. package/build/cjs/utils/urlScheme.js +40 -0
  80. package/build/cjs/utils/urlScheme.js.map +1 -0
  81. package/build/cjs/validation.js +231 -0
  82. package/build/cjs/validation.js.map +1 -0
  83. package/build/esm/android/files/assets.js +223 -0
  84. package/build/esm/android/files/assets.js.map +1 -0
  85. package/build/esm/android/files/fonts.js +33 -0
  86. package/build/esm/android/files/fonts.js.map +1 -0
  87. package/build/esm/android/files/index.js +77 -0
  88. package/build/esm/android/files/index.js.map +1 -0
  89. package/build/esm/android/files/initialStates.js +44 -0
  90. package/build/esm/android/files/initialStates.js.map +1 -0
  91. package/build/esm/android/files/kotlin.js +103 -0
  92. package/build/esm/android/files/kotlin.js.map +1 -0
  93. package/build/esm/android/files/xml.js +206 -0
  94. package/build/esm/android/files/xml.js.map +1 -0
  95. package/build/esm/android/index.js +29 -0
  96. package/build/esm/android/index.js.map +1 -0
  97. package/build/esm/android/manifest.js +59 -0
  98. package/build/esm/android/manifest.js.map +1 -0
  99. package/build/esm/constants.js +45 -0
  100. package/build/esm/constants.js.map +1 -0
  101. package/build/esm/index.js +69 -0
  102. package/build/esm/index.js.map +1 -0
  103. package/build/esm/ios/eas.js +24 -0
  104. package/build/esm/ios/eas.js.map +1 -0
  105. package/build/esm/ios/entitlements.js +42 -0
  106. package/build/esm/ios/entitlements.js.map +1 -0
  107. package/build/esm/ios/index.js +34 -0
  108. package/build/esm/ios/index.js.map +1 -0
  109. package/build/esm/ios/infoPlist.js +47 -0
  110. package/build/esm/ios/infoPlist.js.map +1 -0
  111. package/build/esm/ios/pushNotifications.js +18 -0
  112. package/build/esm/ios/pushNotifications.js.map +1 -0
  113. package/build/esm/ios-widget/eas.js +62 -0
  114. package/build/esm/ios-widget/eas.js.map +1 -0
  115. package/build/esm/ios-widget/files/assets.js +163 -0
  116. package/build/esm/ios-widget/files/assets.js.map +1 -0
  117. package/build/esm/ios-widget/files/entitlements.js +37 -0
  118. package/build/esm/ios-widget/files/entitlements.js.map +1 -0
  119. package/build/esm/ios-widget/files/index.js +55 -0
  120. package/build/esm/ios-widget/files/index.js.map +1 -0
  121. package/build/esm/ios-widget/files/infoPlist.js +55 -0
  122. package/build/esm/ios-widget/files/infoPlist.js.map +1 -0
  123. package/build/esm/ios-widget/files/swift.js +217 -0
  124. package/build/esm/ios-widget/files/swift.js.map +1 -0
  125. package/build/esm/ios-widget/fonts.js +111 -0
  126. package/build/esm/ios-widget/fonts.js.map +1 -0
  127. package/build/esm/ios-widget/index.js +42 -0
  128. package/build/esm/ios-widget/index.js.map +1 -0
  129. package/build/esm/ios-widget/podfile.js +39 -0
  130. package/build/esm/ios-widget/podfile.js.map +1 -0
  131. package/build/esm/ios-widget/widgetPlist.js +92 -0
  132. package/build/esm/ios-widget/widgetPlist.js.map +1 -0
  133. package/build/esm/ios-widget/xcode/buildPhases.js +208 -0
  134. package/build/esm/ios-widget/xcode/buildPhases.js.map +1 -0
  135. package/build/esm/ios-widget/xcode/configurationList.js +87 -0
  136. package/build/esm/ios-widget/xcode/configurationList.js.map +1 -0
  137. package/build/esm/ios-widget/xcode/groups.js +61 -0
  138. package/build/esm/ios-widget/xcode/groups.js.map +1 -0
  139. package/build/esm/ios-widget/xcode/index.js +118 -0
  140. package/build/esm/ios-widget/xcode/index.js.map +1 -0
  141. package/build/esm/ios-widget/xcode/mainAppSettings.js +68 -0
  142. package/build/esm/ios-widget/xcode/mainAppSettings.js.map +1 -0
  143. package/build/esm/ios-widget/xcode/productFile.js +70 -0
  144. package/build/esm/ios-widget/xcode/productFile.js.map +1 -0
  145. package/build/esm/ios-widget/xcode/target.js +108 -0
  146. package/build/esm/ios-widget/xcode/target.js.map +1 -0
  147. package/build/esm/package.json +3 -0
  148. package/build/esm/types.js +2 -0
  149. package/build/esm/types.js.map +1 -0
  150. package/build/esm/utils/entitlements.js +18 -0
  151. package/build/esm/utils/entitlements.js.map +1 -0
  152. package/build/esm/utils/fileDiscovery.js +71 -0
  153. package/build/esm/utils/fileDiscovery.js.map +1 -0
  154. package/build/esm/utils/fonts.js +39 -0
  155. package/build/esm/utils/fonts.js.map +1 -0
  156. package/build/esm/utils/logger.js +48 -0
  157. package/build/esm/utils/logger.js.map +1 -0
  158. package/build/esm/utils/prerender.js +152 -0
  159. package/build/esm/utils/prerender.js.map +1 -0
  160. package/build/esm/utils/urlScheme.js +37 -0
  161. package/build/esm/utils/urlScheme.js.map +1 -0
  162. package/build/esm/validation.js +193 -0
  163. package/build/esm/validation.js.map +1 -0
  164. package/build/types/android/files/assets.d.ts +26 -0
  165. package/build/types/android/files/assets.d.ts.map +1 -0
  166. package/build/types/android/files/fonts.d.ts +19 -0
  167. package/build/types/android/files/fonts.d.ts.map +1 -0
  168. package/build/types/android/files/index.d.ts +21 -0
  169. package/build/types/android/files/index.d.ts.map +1 -0
  170. package/build/types/android/files/initialStates.d.ts +14 -0
  171. package/build/types/android/files/initialStates.d.ts.map +1 -0
  172. package/build/types/android/files/kotlin.d.ts +11 -0
  173. package/build/types/android/files/kotlin.d.ts.map +1 -0
  174. package/build/types/android/files/xml.d.ts +25 -0
  175. package/build/types/android/files/xml.d.ts.map +1 -0
  176. package/build/types/android/index.d.ts +12 -0
  177. package/build/types/android/index.d.ts.map +1 -0
  178. package/build/types/android/manifest.d.ts +15 -0
  179. package/build/types/android/manifest.d.ts.map +1 -0
  180. package/build/types/constants.d.ts +29 -0
  181. package/build/types/constants.d.ts.map +1 -0
  182. package/build/types/index.d.ts +13 -0
  183. package/build/types/index.d.ts.map +1 -0
  184. package/build/types/ios/eas.d.ts +12 -0
  185. package/build/types/ios/eas.d.ts.map +1 -0
  186. package/build/types/ios/entitlements.d.ts +14 -0
  187. package/build/types/ios/entitlements.d.ts.map +1 -0
  188. package/build/types/ios/index.d.ts +19 -0
  189. package/build/types/ios/index.d.ts.map +1 -0
  190. package/build/types/ios/infoPlist.d.ts +21 -0
  191. package/build/types/ios/infoPlist.d.ts.map +1 -0
  192. package/build/types/ios/pushNotifications.d.ts +10 -0
  193. package/build/types/ios/pushNotifications.d.ts.map +1 -0
  194. package/build/types/ios-widget/eas.d.ts +15 -0
  195. package/build/types/ios-widget/eas.d.ts.map +1 -0
  196. package/build/types/ios-widget/files/assets.d.ts +13 -0
  197. package/build/types/ios-widget/files/assets.d.ts.map +1 -0
  198. package/build/types/ios-widget/files/entitlements.d.ts +17 -0
  199. package/build/types/ios-widget/files/entitlements.d.ts.map +1 -0
  200. package/build/types/ios-widget/files/index.d.ts +24 -0
  201. package/build/types/ios-widget/files/index.d.ts.map +1 -0
  202. package/build/types/ios-widget/files/infoPlist.d.ts +10 -0
  203. package/build/types/ios-widget/files/infoPlist.d.ts.map +1 -0
  204. package/build/types/ios-widget/files/swift.d.ts +15 -0
  205. package/build/types/ios-widget/files/swift.d.ts.map +1 -0
  206. package/build/types/ios-widget/fonts.d.ts +22 -0
  207. package/build/types/ios-widget/fonts.d.ts.map +1 -0
  208. package/build/types/ios-widget/index.d.ts +31 -0
  209. package/build/types/ios-widget/index.d.ts.map +1 -0
  210. package/build/types/ios-widget/podfile.d.ts +9 -0
  211. package/build/types/ios-widget/podfile.d.ts.map +1 -0
  212. package/build/types/ios-widget/widgetPlist.d.ts +20 -0
  213. package/build/types/ios-widget/widgetPlist.d.ts.map +1 -0
  214. package/build/types/ios-widget/xcode/buildPhases.d.ts +25 -0
  215. package/build/types/ios-widget/xcode/buildPhases.d.ts.map +1 -0
  216. package/build/types/ios-widget/xcode/configurationList.d.ts +20 -0
  217. package/build/types/ios-widget/xcode/configurationList.d.ts.map +1 -0
  218. package/build/types/ios-widget/xcode/groups.d.ts +15 -0
  219. package/build/types/ios-widget/xcode/groups.d.ts.map +1 -0
  220. package/build/types/ios-widget/xcode/index.d.ts +20 -0
  221. package/build/types/ios-widget/xcode/index.d.ts.map +1 -0
  222. package/build/types/ios-widget/xcode/mainAppSettings.d.ts +15 -0
  223. package/build/types/ios-widget/xcode/mainAppSettings.d.ts.map +1 -0
  224. package/build/types/ios-widget/xcode/productFile.d.ts +14 -0
  225. package/build/types/ios-widget/xcode/productFile.d.ts.map +1 -0
  226. package/build/types/ios-widget/xcode/target.d.ts +42 -0
  227. package/build/types/ios-widget/xcode/target.d.ts.map +1 -0
  228. package/build/types/types.d.ts +261 -0
  229. package/build/types/types.d.ts.map +1 -0
  230. package/build/types/utils/entitlements.d.ts +9 -0
  231. package/build/types/utils/entitlements.d.ts.map +1 -0
  232. package/build/types/utils/fileDiscovery.d.ts +13 -0
  233. package/build/types/utils/fileDiscovery.d.ts.map +1 -0
  234. package/build/types/utils/fonts.d.ts +2 -0
  235. package/build/types/utils/fonts.d.ts.map +1 -0
  236. package/build/types/utils/logger.d.ts +30 -0
  237. package/build/types/utils/logger.d.ts.map +1 -0
  238. package/build/types/utils/prerender.d.ts +25 -0
  239. package/build/types/utils/prerender.d.ts.map +1 -0
  240. package/build/types/utils/urlScheme.d.ts +10 -0
  241. package/build/types/utils/urlScheme.d.ts.map +1 -0
  242. package/build/types/validation.d.ts +17 -0
  243. package/build/types/validation.d.ts.map +1 -0
  244. package/package.json +58 -0
@@ -0,0 +1,62 @@
1
+ import { addApplicationGroupsEntitlement } from '../utils/entitlements';
2
+ import { getWidgetExtensionEntitlements } from './files/entitlements';
3
+ /**
4
+ * Plugin step that configures EAS build settings for the widget extension.
5
+ *
6
+ * This:
7
+ * - Adds the widget extension to the EAS build experimental iOS appExtensions
8
+ * - Configures entitlements for both the extension and main app
9
+ */
10
+ export const configureEasBuild = (config, { bundleIdentifier, targetName, groupIdentifier }) => {
11
+ let configIndex = null;
12
+ // Check if extension already exists
13
+ config.extra?.eas?.build?.experimental?.ios?.appExtensions?.forEach((ext, index) => {
14
+ if (ext.targetName === targetName) {
15
+ configIndex = index;
16
+ }
17
+ });
18
+ // Add extension if not already present
19
+ if (configIndex === null) {
20
+ config.extra = {
21
+ ...config.extra,
22
+ eas: {
23
+ ...config.extra?.eas,
24
+ build: {
25
+ ...config.extra?.eas?.build,
26
+ experimental: {
27
+ ...config.extra?.eas?.build?.experimental,
28
+ ios: {
29
+ ...config.extra?.eas?.build?.experimental?.ios,
30
+ appExtensions: [
31
+ ...(config.extra?.eas?.build?.experimental?.ios?.appExtensions ?? []),
32
+ {
33
+ targetName,
34
+ bundleIdentifier,
35
+ },
36
+ ],
37
+ },
38
+ },
39
+ },
40
+ },
41
+ };
42
+ configIndex = (config.extra?.eas?.build?.experimental?.ios?.appExtensions?.length ?? 1) - 1;
43
+ }
44
+ // Configure entitlements (may be empty if no groupIdentifier)
45
+ if (configIndex != null && config.extra) {
46
+ const widgetsExtensionConfig = config.extra.eas.build.experimental.ios.appExtensions[configIndex];
47
+ widgetsExtensionConfig.entitlements = {
48
+ ...widgetsExtensionConfig.entitlements,
49
+ ...getWidgetExtensionEntitlements(groupIdentifier),
50
+ };
51
+ if (groupIdentifier) {
52
+ config.ios = {
53
+ ...config.ios,
54
+ entitlements: {
55
+ ...addApplicationGroupsEntitlement(config.ios?.entitlements ?? {}, groupIdentifier),
56
+ },
57
+ };
58
+ }
59
+ }
60
+ return config;
61
+ };
62
+ //# sourceMappingURL=eas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eas.js","sourceRoot":"","sources":["../../../src/ios-widget/eas.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAA;AACvE,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAA;AAQrE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAyC,CACrE,MAAM,EACN,EAAE,gBAAgB,EAAE,UAAU,EAAE,eAAe,EAAE,EACjD,EAAE;IACF,IAAI,WAAW,GAAkB,IAAI,CAAA;IAErC,oCAAoC;IACpC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC,GAAQ,EAAE,KAAa,EAAE,EAAE;QAC9F,IAAI,GAAG,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;YAClC,WAAW,GAAG,KAAK,CAAA;QACrB,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,uCAAuC;IACvC,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,CAAC,KAAK,GAAG;YACb,GAAG,MAAM,CAAC,KAAK;YACf,GAAG,EAAE;gBACH,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG;gBACpB,KAAK,EAAE;oBACL,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK;oBAC3B,YAAY,EAAE;wBACZ,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY;wBACzC,GAAG,EAAE;4BACH,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG;4BAC9C,aAAa,EAAE;gCACb,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,IAAI,EAAE,CAAC;gCACrE;oCACE,UAAU;oCACV,gBAAgB;iCACjB;6BACF;yBACF;qBACF;iBACF;aACF;SACF,CAAA;QACD,WAAW,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;IAC7F,CAAC;IAED,8DAA8D;IAC9D,IAAI,WAAW,IAAI,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,sBAAsB,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,WAAW,CAAC,CAAA;QAEjG,sBAAsB,CAAC,YAAY,GAAG;YACpC,GAAG,sBAAsB,CAAC,YAAY;YACtC,GAAG,8BAA8B,CAAC,eAAe,CAAC;SACnD,CAAA;QAED,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,CAAC,GAAG,GAAG;gBACX,GAAG,MAAM,CAAC,GAAG;gBACb,YAAY,EAAE;oBACZ,GAAG,+BAA+B,CAAC,MAAM,CAAC,GAAG,EAAE,YAAY,IAAI,EAAE,EAAE,eAAe,CAAC;iBACpF;aACF,CAAA;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"}
@@ -0,0 +1,163 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { DEFAULT_USER_IMAGES_PATH, MAX_IMAGE_SIZE_BYTES, SUPPORTED_IMAGE_EXTENSIONS } from '../../constants';
4
+ import { logger } from '../../utils/logger';
5
+ // ============================================================================
6
+ // Main Function
7
+ // ============================================================================
8
+ /**
9
+ * Generates all asset files for the widget extension.
10
+ *
11
+ * This creates:
12
+ * - Assets.xcassets/ directory structure
13
+ * - Copies user images to the asset catalog
14
+ */
15
+ export function generateAssets(options) {
16
+ const { targetPath, userImagesPath = DEFAULT_USER_IMAGES_PATH } = options;
17
+ // Generate Assets.xcassets structure
18
+ generateAssetsCatalog(targetPath);
19
+ logger.info('Generated Assets.xcassets');
20
+ // Copy user images to asset catalog
21
+ const assetsPath = path.join(targetPath, 'Assets.xcassets');
22
+ copyUserImages(userImagesPath, assetsPath);
23
+ }
24
+ // ============================================================================
25
+ // Asset Catalog
26
+ // ============================================================================
27
+ /**
28
+ * Contents.json for the root of Assets.xcassets
29
+ */
30
+ const ASSETS_CATALOG_CONTENTS = {
31
+ info: {
32
+ author: 'xcode',
33
+ version: 1,
34
+ },
35
+ };
36
+ /**
37
+ * Contents.json for an imageset
38
+ */
39
+ function createImagesetContents(filename) {
40
+ return {
41
+ images: [
42
+ {
43
+ filename,
44
+ idiom: 'universal',
45
+ },
46
+ ],
47
+ info: {
48
+ author: 'xcode',
49
+ version: 1,
50
+ },
51
+ };
52
+ }
53
+ /**
54
+ * Generates the Assets.xcassets directory structure for a widget extension.
55
+ *
56
+ * Creates the minimal required asset catalog structure:
57
+ * - Assets.xcassets/
58
+ * - Contents.json (required root manifest)
59
+ *
60
+ * @param targetPath - Path to the widget extension target directory
61
+ */
62
+ function generateAssetsCatalog(targetPath) {
63
+ const assetsPath = path.join(targetPath, 'Assets.xcassets');
64
+ // Create Assets.xcassets directory
65
+ if (!fs.existsSync(assetsPath)) {
66
+ fs.mkdirSync(assetsPath, { recursive: true });
67
+ }
68
+ // Write root Contents.json
69
+ fs.writeFileSync(path.join(assetsPath, 'Contents.json'), JSON.stringify(ASSETS_CATALOG_CONTENTS, null, 2));
70
+ }
71
+ /**
72
+ * Adds an image to the Assets.xcassets catalog as an imageset.
73
+ *
74
+ * Creates:
75
+ * - {imageName}.imageset/
76
+ * - {originalFilename}
77
+ * - Contents.json
78
+ *
79
+ * @param assetsPath - Path to Assets.xcassets directory
80
+ * @param imagePath - Path to the source image file
81
+ */
82
+ function addImageToAssetsCatalog(assetsPath, imagePath) {
83
+ const filename = path.basename(imagePath);
84
+ const imageName = path.basename(filename, path.extname(filename));
85
+ const imagesetPath = path.join(assetsPath, `${imageName}.imageset`);
86
+ // Create imageset directory
87
+ if (!fs.existsSync(imagesetPath)) {
88
+ fs.mkdirSync(imagesetPath, { recursive: true });
89
+ }
90
+ // Copy the image file
91
+ fs.copyFileSync(imagePath, path.join(imagesetPath, filename));
92
+ // Write Contents.json for the imageset
93
+ fs.writeFileSync(path.join(imagesetPath, 'Contents.json'), JSON.stringify(createImagesetContents(filename), null, 2));
94
+ }
95
+ // ============================================================================
96
+ // Image Handling
97
+ // ============================================================================
98
+ /**
99
+ * Checks if an image file exceeds the size limit for Live Activities.
100
+ * Logs a warning if the image is too large.
101
+ *
102
+ * @param imagePath - Path to the image file
103
+ * @returns true if the image is within the size limit, false otherwise
104
+ */
105
+ function checkImageSize(imagePath) {
106
+ const stats = fs.statSync(imagePath);
107
+ const imageSizeInBytes = stats.size;
108
+ if (imageSizeInBytes >= MAX_IMAGE_SIZE_BYTES) {
109
+ const fileName = path.basename(imagePath);
110
+ logger.warnRed(`Image "${fileName}" is ${imageSizeInBytes} bytes (${(imageSizeInBytes / 1024).toFixed(2)}KB). ` +
111
+ `This image will not display correctly in Live Activities as images for Live Activities need to be lower than 4KB.`);
112
+ return false;
113
+ }
114
+ return true;
115
+ }
116
+ /**
117
+ * Checks if a file is a supported image type.
118
+ */
119
+ function isSupportedImage(filePath) {
120
+ return SUPPORTED_IMAGE_EXTENSIONS.test(path.extname(filePath));
121
+ }
122
+ /**
123
+ * Copies user images from the source directory to the widget's Assets.xcassets.
124
+ *
125
+ * Images are validated for size (must be < 4KB for Live Activities) and
126
+ * added as imagesets to the asset catalog.
127
+ *
128
+ * @param userImagesPath - Path to directory containing user images (relative to project root)
129
+ * @param targetAssetsPath - Path to the Assets.xcassets directory in the widget target
130
+ * @returns Array of image filenames that were copied
131
+ */
132
+ function copyUserImages(userImagesPath, targetAssetsPath) {
133
+ const copiedImages = [];
134
+ if (!fs.existsSync(userImagesPath)) {
135
+ logger.warn(`Skipping user images: directory does not exist at ${userImagesPath}`);
136
+ return copiedImages;
137
+ }
138
+ if (!fs.lstatSync(userImagesPath).isDirectory()) {
139
+ logger.warn(`Skipping user images: ${userImagesPath} is not a directory`);
140
+ return copiedImages;
141
+ }
142
+ const files = fs.readdirSync(userImagesPath);
143
+ for (const file of files) {
144
+ const sourcePath = path.join(userImagesPath, file);
145
+ // Skip directories and non-image files
146
+ if (fs.lstatSync(sourcePath).isDirectory()) {
147
+ continue;
148
+ }
149
+ if (!isSupportedImage(file)) {
150
+ continue;
151
+ }
152
+ // Check image size for Live Activity compatibility (warns if too large)
153
+ checkImageSize(sourcePath);
154
+ // Add to asset catalog
155
+ addImageToAssetsCatalog(targetAssetsPath, sourcePath);
156
+ copiedImages.push(file);
157
+ }
158
+ if (copiedImages.length > 0) {
159
+ logger.info(`Copied ${copiedImages.length} user image(s) to widget assets`);
160
+ }
161
+ return copiedImages;
162
+ }
163
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../../../src/ios-widget/files/assets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import plist from '@expo/plist';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { addApplicationGroupsEntitlement } from '../../utils/entitlements';
5
+ import { logger } from '../../utils/logger';
6
+ /**
7
+ * Gets the entitlements for the widget extension.
8
+ */
9
+ export function getWidgetExtensionEntitlements(groupIdentifier, keychainGroup) {
10
+ const entitlements = {};
11
+ if (groupIdentifier) {
12
+ addApplicationGroupsEntitlement(entitlements, groupIdentifier);
13
+ }
14
+ if (keychainGroup) {
15
+ const existingGroups = (entitlements['keychain-access-groups'] ?? []).filter(Boolean);
16
+ const deduped = Array.from(new Set(existingGroups));
17
+ if (!deduped.includes(keychainGroup)) {
18
+ deduped.push(keychainGroup);
19
+ }
20
+ entitlements['keychain-access-groups'] = deduped;
21
+ }
22
+ return entitlements;
23
+ }
24
+ /**
25
+ * Generates the entitlements file for the widget extension.
26
+ *
27
+ * @param options - Generation options
28
+ */
29
+ export function generateEntitlements(options) {
30
+ const { targetPath, targetName, groupIdentifier, keychainGroup } = options;
31
+ const filePath = path.join(targetPath, `${targetName}.entitlements`);
32
+ const extensionEntitlements = getWidgetExtensionEntitlements(groupIdentifier, keychainGroup);
33
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
34
+ fs.writeFileSync(filePath, plist.build(extensionEntitlements));
35
+ logger.info(`Generated ${targetName}.entitlements`);
36
+ }
37
+ //# sourceMappingURL=entitlements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entitlements.js","sourceRoot":"","sources":["../../../../src/ios-widget/files/entitlements.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,aAAa,CAAA;AAC/B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B,OAAO,EAAE,+BAA+B,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAE3C;;GAEG;AACH,MAAM,UAAU,8BAA8B,CAAC,eAAwB,EAAE,aAAsB;IAC7F,MAAM,YAAY,GAAwB,EAAE,CAAA;IAC5C,IAAI,eAAe,EAAE,CAAC;QACpB,+BAA+B,CAAC,YAAY,EAAE,eAAe,CAAC,CAAA;IAChE,CAAC;IACD,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,cAAc,GAAG,CAAE,YAAY,CAAC,wBAAwB,CAAc,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACnG,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC,CAAA;QACnD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC7B,CAAC;QACD,YAAY,CAAC,wBAAwB,CAAC,GAAG,OAAO,CAAA;IAClD,CAAC;IACD,OAAO,YAAY,CAAA;AACrB,CAAC;AASD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAoC;IACvE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,GAAG,OAAO,CAAA;IAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,UAAU,eAAe,CAAC,CAAA;IAEpE,MAAM,qBAAqB,GAAG,8BAA8B,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;IAE5F,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAA;IAC9D,MAAM,CAAC,IAAI,CAAC,aAAa,UAAU,eAAe,CAAC,CAAA;AACrD,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { withDangerousMod } from '@expo/config-plugins';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { generateAssets } from './assets';
5
+ import { generateEntitlements } from './entitlements';
6
+ import { generateInfoPlist } from './infoPlist';
7
+ import { generateSwiftFiles } from './swift';
8
+ /**
9
+ * Plugin step that generates all widget extension files.
10
+ *
11
+ * This creates:
12
+ * - Info.plist (required extension manifest)
13
+ * - Assets.xcassets/ (asset catalog with user images)
14
+ * - VoltraWidgetBundle.swift (widget bundle definition)
15
+ * - VoltraWidgetInitialStates.swift (pre-rendered widget states)
16
+ * - {targetName}.entitlements (entitlements file)
17
+ *
18
+ * This should run before configureXcodeProject so the files exist when Xcode project is configured.
19
+ */
20
+ export const generateWidgetExtensionFiles = (config, props) => {
21
+ const { targetName, widgets, groupIdentifier, keychainGroup, version, buildNumber } = props;
22
+ return withDangerousMod(config, [
23
+ 'ios',
24
+ async (config) => {
25
+ if (config.modRequest.introspect) {
26
+ return config;
27
+ }
28
+ const { platformProjectRoot, projectRoot } = config.modRequest;
29
+ const targetPath = path.join(platformProjectRoot, targetName);
30
+ // Ensure target directory exists
31
+ if (!fs.existsSync(targetPath)) {
32
+ fs.mkdirSync(targetPath, { recursive: true });
33
+ }
34
+ // Generate Info.plist
35
+ generateInfoPlist(targetPath, targetName, version, buildNumber);
36
+ // Generate Assets.xcassets and copy user images
37
+ generateAssets({ targetPath });
38
+ // Generate Swift files (widget bundle, initial states)
39
+ await generateSwiftFiles({
40
+ targetPath,
41
+ projectRoot,
42
+ widgets,
43
+ });
44
+ // Generate entitlements file (may be empty if no groupIdentifier or keychainGroup)
45
+ generateEntitlements({
46
+ targetPath,
47
+ targetName,
48
+ groupIdentifier,
49
+ keychainGroup,
50
+ });
51
+ return config;
52
+ },
53
+ ]);
54
+ };
55
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/ios-widget/files/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACrE,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAG5B,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAW5C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAoD,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;IAC7G,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,KAAK,CAAA;IAE3F,OAAO,gBAAgB,CAAC,MAAM,EAAE;QAC9B,KAAK;QACL,KAAK,EAAE,MAAM,EAAE,EAAE;YACf,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;gBACjC,OAAO,MAAM,CAAA;YACf,CAAC;YAED,MAAM,EAAE,mBAAmB,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,UAAU,CAAA;YAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAA;YAE7D,iCAAiC;YACjC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YAC/C,CAAC;YAED,sBAAsB;YACtB,iBAAiB,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,CAAA;YAE/D,gDAAgD;YAChD,cAAc,CAAC,EAAE,UAAU,EAAE,CAAC,CAAA;YAE9B,uDAAuD;YACvD,MAAM,kBAAkB,CAAC;gBACvB,UAAU;gBACV,WAAW;gBACX,OAAO;aACR,CAAC,CAAA;YAEF,mFAAmF;YACnF,oBAAoB,CAAC;gBACnB,UAAU;gBACV,UAAU;gBACV,eAAe;gBACf,aAAa;aACd,CAAC,CAAA;YAEF,OAAO,MAAM,CAAA;QACf,CAAC;KACF,CAAC,CAAA;AACJ,CAAC,CAAA"}
@@ -0,0 +1,55 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { logger } from '../../utils/logger';
4
+ /**
5
+ * Generates the Info.plist content for a WidgetKit extension.
6
+ *
7
+ * This includes version information and the required WidgetKit extension point.
8
+ * Version keys are written directly to the plist following the Expo pattern.
9
+ */
10
+ function generateInfoPlistContent(targetName, version, buildNumber) {
11
+ return `<?xml version="1.0" encoding="UTF-8"?>
12
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
13
+ <plist version="1.0">
14
+ <dict>
15
+ <key>CFBundleDevelopmentRegion</key>
16
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
17
+ <key>CFBundleDisplayName</key>
18
+ <string>${targetName}</string>
19
+ <key>CFBundleExecutable</key>
20
+ <string>$(EXECUTABLE_NAME)</string>
21
+ <key>CFBundleIdentifier</key>
22
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
23
+ <key>CFBundleInfoDictionaryVersion</key>
24
+ <string>6.0</string>
25
+ <key>CFBundleName</key>
26
+ <string>$(PRODUCT_NAME)</string>
27
+ <key>CFBundlePackageType</key>
28
+ <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
29
+ <key>CFBundleShortVersionString</key>
30
+ <string>${version}</string>
31
+ <key>CFBundleVersion</key>
32
+ <string>${buildNumber}</string>
33
+ <key>NSExtension</key>
34
+ <dict>
35
+ <key>NSExtensionPointIdentifier</key>
36
+ <string>com.apple.widgetkit-extension</string>
37
+ </dict>
38
+ </dict>
39
+ </plist>
40
+ `;
41
+ }
42
+ /**
43
+ * Generates the Info.plist file for the widget extension.
44
+ *
45
+ * @param targetPath - Path to the widget extension target directory
46
+ * @param targetName - The widget extension target name (used for CFBundleDisplayName)
47
+ * @param version - The app version (CFBundleShortVersionString)
48
+ * @param buildNumber - The build number (CFBundleVersion)
49
+ */
50
+ export function generateInfoPlist(targetPath, targetName, version, buildNumber) {
51
+ const infoPlistPath = path.join(targetPath, 'Info.plist');
52
+ fs.writeFileSync(infoPlistPath, generateInfoPlistContent(targetName, version, buildNumber));
53
+ logger.info('Generated Info.plist');
54
+ }
55
+ //# sourceMappingURL=infoPlist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infoPlist.js","sourceRoot":"","sources":["../../../../src/ios-widget/files/infoPlist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAE3C;;;;;GAKG;AACH,SAAS,wBAAwB,CAAC,UAAkB,EAAE,OAAe,EAAE,WAAmB;IACxF,OAAO;;;;;;;WAOE,UAAU;;;;;;;;;;;;WAYV,OAAO;;WAEP,WAAW;;;;;;;;CAQrB,CAAA;AACD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB,EAAE,UAAkB,EAAE,OAAe,EAAE,WAAmB;IAC5G,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;IACzD,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,wBAAwB,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAA;IAC3F,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;AACrC,CAAC"}
@@ -0,0 +1,217 @@
1
+ import dedent from 'dedent';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { DEFAULT_WIDGET_FAMILIES, WIDGET_FAMILY_MAP } from '../../constants';
5
+ import { logger } from '../../utils/logger';
6
+ import { prerenderWidgetState } from '../../utils/prerender';
7
+ // ============================================================================
8
+ // Main Function
9
+ // ============================================================================
10
+ /**
11
+ * Generates all Swift files for the widget extension.
12
+ *
13
+ * This creates:
14
+ * - VoltraWidgetInitialStates.swift (pre-rendered widget states)
15
+ * - VoltraWidgetBundle.swift (widget bundle definition)
16
+ */
17
+ export async function generateSwiftFiles(options) {
18
+ const { targetPath, projectRoot, widgets } = options;
19
+ // Dynamic import for ESM module compatibility
20
+ // voltra/server is an ESM module, but the plugin is compiled to CommonJS
21
+ const serverModuleId = 'voltra/server';
22
+ const { renderWidgetToString } = (await import(serverModuleId));
23
+ // Prerender widget initial states if any widgets have initialStatePath configured
24
+ const prerenderedStates = await prerenderWidgetState(widgets || [], projectRoot, renderWidgetToString);
25
+ // Generate the initial states Swift file
26
+ const initialStatesContent = generateInitialStatesSwift(prerenderedStates);
27
+ const initialStatesPath = path.join(targetPath, 'VoltraWidgetInitialStates.swift');
28
+ fs.writeFileSync(initialStatesPath, initialStatesContent);
29
+ logger.info(`Generated VoltraWidgetInitialStates.swift with ${prerenderedStates.size} pre-rendered widget states`);
30
+ // Generate the widget bundle Swift file
31
+ const widgetBundleContent = widgets && widgets.length > 0 ? generateWidgetBundleSwift(widgets) : generateDefaultWidgetBundleSwift();
32
+ const widgetBundlePath = path.join(targetPath, 'VoltraWidgetBundle.swift');
33
+ fs.writeFileSync(widgetBundlePath, widgetBundleContent);
34
+ logger.info(`Generated VoltraWidgetBundle.swift with ${widgets?.length ?? 0} home screen widgets`);
35
+ }
36
+ // ============================================================================
37
+ // Widget Bundle
38
+ // ============================================================================
39
+ /**
40
+ * Generates Swift code for a single widget struct
41
+ */
42
+ function generateWidgetStruct(widget) {
43
+ const families = widget.supportedFamilies ?? DEFAULT_WIDGET_FAMILIES;
44
+ const familiesSwift = families.map((f) => WIDGET_FAMILY_MAP[f]).join(', ');
45
+ // Sanitize the widget id for use as a Swift identifier
46
+ const structName = `VoltraWidget_${widget.id}`;
47
+ return dedent `
48
+ public struct ${structName}: Widget {
49
+ private let widgetId = "${widget.id}"
50
+
51
+ public init() {}
52
+
53
+ public var body: some WidgetConfiguration {
54
+ StaticConfiguration(
55
+ kind: "Voltra_Widget_${widget.id}",
56
+ provider: VoltraHomeWidgetProvider(
57
+ widgetId: widgetId,
58
+ initialState: VoltraWidgetInitialStates.getInitialState(for: widgetId)
59
+ )
60
+ ) { entry in
61
+ VoltraHomeWidgetView(entry: entry)
62
+ }
63
+ .configurationDisplayName("${widget.displayName}")
64
+ .description("${widget.description}")
65
+ .supportedFamilies([${familiesSwift}])
66
+ .contentMarginsDisabled()
67
+ }
68
+ }
69
+ `;
70
+ }
71
+ /**
72
+ * Generates the VoltraWidgetBundle.swift file content with configured widgets
73
+ */
74
+ function generateWidgetBundleSwift(widgets) {
75
+ // Generate widget structs
76
+ const widgetStructs = widgets.map(generateWidgetStruct).join('\n\n');
77
+ // Generate widget bundle body entries
78
+ const widgetInstances = widgets.map((w) => `VoltraWidget_${w.id}()`).join('\n ');
79
+ return dedent `
80
+ //
81
+ // VoltraWidgetBundle.swift
82
+ //
83
+ // Auto-generated by Voltra config plugin.
84
+ // This file defines which Voltra widgets are available in your app.
85
+ //
86
+
87
+ import SwiftUI
88
+ import WidgetKit
89
+ import VoltraWidget
90
+
91
+ @main
92
+ struct VoltraWidgetBundle: WidgetBundle {
93
+ var body: some Widget {
94
+ // Live Activity (with Watch/CarPlay support)
95
+ VoltraWidget()
96
+
97
+ // Home Screen Widgets
98
+ ${widgetInstances}
99
+ }
100
+ }
101
+
102
+ // MARK: - Home Screen Widget Definitions
103
+
104
+ ${widgetStructs}
105
+ `;
106
+ }
107
+ /**
108
+ * Generates the VoltraWidgetBundle.swift file content when no widgets are configured
109
+ * (only Live Activities)
110
+ */
111
+ function generateDefaultWidgetBundleSwift() {
112
+ return dedent `
113
+ //
114
+ // VoltraWidgetBundle.swift
115
+ //
116
+ // This file defines which Voltra widgets are available in your app.
117
+ // You can customize which widgets to include by adding or removing them below.
118
+ //
119
+
120
+ import SwiftUI
121
+ import WidgetKit
122
+ import VoltraWidget // Import Voltra widgets
123
+
124
+ @main
125
+ struct VoltraWidgetBundle: WidgetBundle {
126
+ var body: some Widget {
127
+ // Live Activity (with Watch/CarPlay support)
128
+ VoltraWidget()
129
+ }
130
+ }
131
+ `;
132
+ }
133
+ // ============================================================================
134
+ // Initial States
135
+ // ============================================================================
136
+ /**
137
+ * Generates Swift code that bundles pre-rendered widget initial states.
138
+ */
139
+ function generateInitialStatesSwift(prerenderedStates) {
140
+ if (prerenderedStates.size === 0) {
141
+ return generateEmptyInitialStatesSwift();
142
+ }
143
+ // Generate the bundled states dictionary
144
+ const stateEntries = Array.from(prerenderedStates.entries())
145
+ .map(([widgetId, json]) => {
146
+ const delimiter = getSwiftRawStringDelimiter(json);
147
+ return `"${widgetId}": ${delimiter}"${json}"${delimiter}`;
148
+ })
149
+ .join(',\n ');
150
+ return dedent `
151
+ //
152
+ // VoltraWidgetInitialStates.swift
153
+ //
154
+ // Auto-generated by Voltra config plugin.
155
+ // Contains pre-rendered initial states for home screen widgets.
156
+ //
157
+
158
+ import Foundation
159
+
160
+ public enum VoltraWidgetInitialStates {
161
+ private static let bundledStates: [String: String] = [
162
+ ${stateEntries}
163
+ ]
164
+
165
+ /// Get the bundled initial state JSON for a widget.
166
+ /// Returns nil if no initial state was configured for the widget.
167
+ public static func getInitialState(for widgetId: String) -> Data? {
168
+ guard let jsonString = bundledStates[widgetId] else { return nil }
169
+ return jsonString.data(using: .utf8)
170
+ }
171
+ }
172
+ `;
173
+ }
174
+ /**
175
+ * Generates empty Swift code when no widgets have initial states configured.
176
+ */
177
+ function generateEmptyInitialStatesSwift() {
178
+ return dedent `
179
+ //
180
+ // VoltraWidgetInitialStates.swift
181
+ //
182
+ // Auto-generated by Voltra config plugin.
183
+ // No widget initial states configured.
184
+ //
185
+
186
+ import Foundation
187
+
188
+ public enum VoltraWidgetInitialStates {
189
+ /// Get the bundled initial state JSON for a widget.
190
+ /// Always returns nil since no initial states are configured.
191
+ public static func getInitialState(for widgetId: String) -> Data? {
192
+ return nil
193
+ }
194
+ }
195
+ `;
196
+ }
197
+ /**
198
+ * Determines the appropriate Swift raw string delimiter for a given string.
199
+ * Counts the maximum consecutive '#' characters after a '"' in the content
200
+ * and returns a delimiter with one more '#' than that maximum.
201
+ *
202
+ * For example:
203
+ * - Content has no '"#' → returns '#'
204
+ * - Content has '"#' (1 hash) → returns '##'
205
+ * - Content has '"##' (2 hashes) → returns '###'
206
+ */
207
+ function getSwiftRawStringDelimiter(str) {
208
+ // Find all sequences of '#' that follow a '"'
209
+ const matches = str.match(/"#+/g);
210
+ if (!matches) {
211
+ return '#';
212
+ }
213
+ // Find the maximum number of consecutive '#' after a '"'
214
+ const maxHashes = Math.max(...matches.map((m) => m.length - 1)); // -1 to exclude the '"'
215
+ return '#'.repeat(maxHashes + 1);
216
+ }
217
+ //# sourceMappingURL=swift.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swift.js","sourceRoot":"","sources":["../../../../src/ios-widget/files/swift.ts"],"names":[],"mappings":"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"}