@teardown/cli 1.2.39 → 2.0.41

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 (260) hide show
  1. package/bin/teardown.js +11 -1
  2. package/package.json +77 -57
  3. package/src/cli/commands/init.ts +254 -0
  4. package/src/cli/commands/plugins.ts +93 -0
  5. package/src/cli/commands/prebuild.ts +168 -0
  6. package/src/cli/commands/run.ts +727 -0
  7. package/src/cli/commands/start.ts +87 -0
  8. package/src/cli/commands/validate.ts +62 -0
  9. package/src/cli/index.ts +59 -0
  10. package/src/config/index.ts +45 -0
  11. package/src/config/loader.ts +366 -0
  12. package/src/config/schema.ts +235 -0
  13. package/src/config/types.ts +322 -0
  14. package/src/index.ts +177 -0
  15. package/src/pipeline/cache.ts +179 -0
  16. package/src/pipeline/index.ts +10 -0
  17. package/src/pipeline/stages.ts +692 -0
  18. package/src/plugins/base.ts +370 -0
  19. package/src/plugins/capabilities/biometrics.ts +64 -0
  20. package/src/plugins/capabilities/bluetooth.ts +86 -0
  21. package/src/plugins/capabilities/calendar.ts +57 -0
  22. package/src/plugins/capabilities/camera.ts +77 -0
  23. package/src/plugins/capabilities/contacts.ts +57 -0
  24. package/src/plugins/capabilities/deep-linking.ts +124 -0
  25. package/src/plugins/capabilities/firebase.ts +138 -0
  26. package/src/plugins/capabilities/index.ts +96 -0
  27. package/src/plugins/capabilities/location.ts +87 -0
  28. package/src/plugins/capabilities/photo-library.ts +80 -0
  29. package/src/plugins/capabilities/push-notifications.ts +98 -0
  30. package/src/plugins/capabilities/sign-in-with-apple.ts +53 -0
  31. package/src/plugins/context.ts +220 -0
  32. package/src/plugins/index.ts +26 -0
  33. package/src/plugins/resolver.ts +321 -0
  34. package/src/templates/generator.ts +507 -0
  35. package/src/templates/index.ts +9 -0
  36. package/src/templates/paths.ts +25 -0
  37. package/src/transformers/android/gradle.ts +400 -0
  38. package/src/transformers/android/index.ts +19 -0
  39. package/src/transformers/android/manifest.ts +506 -0
  40. package/src/transformers/index.ts +39 -0
  41. package/src/transformers/ios/entitlements.ts +283 -0
  42. package/src/transformers/ios/index.ts +10 -0
  43. package/src/transformers/ios/pbxproj.ts +267 -0
  44. package/src/transformers/ios/plist.ts +198 -0
  45. package/src/utils/fs.ts +429 -0
  46. package/src/utils/index.ts +21 -0
  47. package/src/utils/logger.ts +203 -0
  48. package/templates/.gitignore +63 -0
  49. package/templates/Gemfile +3 -0
  50. package/templates/android/app/build.gradle.kts +97 -0
  51. package/templates/android/app/proguard-rules.pro +10 -0
  52. package/templates/android/app/src/main/AndroidManifest.xml +26 -0
  53. package/templates/android/app/src/main/java/com/appname/MainActivity.kt +22 -0
  54. package/templates/android/app/src/main/java/com/appname/MainApplication.kt +44 -0
  55. package/templates/android/app/src/main/res/values/strings.xml +3 -0
  56. package/templates/android/app/src/main/res/values/styles.xml +7 -0
  57. package/templates/android/build.gradle.kts +44 -0
  58. package/templates/android/gradle.properties +39 -0
  59. package/templates/android/settings.gradle.kts +12 -0
  60. package/templates/babel.config.js +15 -0
  61. package/templates/index.js +7 -0
  62. package/templates/ios/.xcode.env +11 -0
  63. package/templates/ios/AppName/AppDelegate.swift +25 -0
  64. package/templates/ios/AppName/AppName-Bridging-Header.h +4 -0
  65. package/templates/ios/AppName/AppName.entitlements +6 -0
  66. package/templates/ios/AppName/Images.xcassets/AppIcon.appiconset/Contents.json +35 -0
  67. package/templates/ios/AppName/Images.xcassets/Contents.json +6 -0
  68. package/templates/ios/AppName/Info.plist +49 -0
  69. package/templates/ios/AppName/LaunchScreen.storyboard +38 -0
  70. package/templates/ios/AppName.xcodeproj/project.pbxproj +402 -0
  71. package/templates/ios/AppName.xcodeproj/xcshareddata/xcschemes/AppName.xcscheme +78 -0
  72. package/templates/ios/Podfile +35 -0
  73. package/templates/metro.config.js +41 -0
  74. package/templates/package.json +57 -0
  75. package/templates/react-native.config.js +8 -0
  76. package/templates/src/app/index.tsx +34 -0
  77. package/templates/src/assets/fonts/.gitkeep +1 -0
  78. package/templates/src/assets/images/.gitkeep +1 -0
  79. package/templates/src/components/ui/accordion.tsx +114 -0
  80. package/templates/src/components/ui/avatar.tsx +75 -0
  81. package/templates/src/components/ui/button.tsx +93 -0
  82. package/templates/src/components/ui/card.tsx +120 -0
  83. package/templates/src/components/ui/checkbox.tsx +133 -0
  84. package/templates/src/components/ui/chip.tsx +95 -0
  85. package/templates/src/components/ui/dialog.tsx +134 -0
  86. package/templates/src/components/ui/divider.tsx +67 -0
  87. package/templates/src/components/ui/error-view.tsx +82 -0
  88. package/templates/src/components/ui/form-field.tsx +101 -0
  89. package/templates/src/components/ui/index.ts +100 -0
  90. package/templates/src/components/ui/popover.tsx +92 -0
  91. package/templates/src/components/ui/pressable-feedback.tsx +88 -0
  92. package/templates/src/components/ui/radio-group.tsx +153 -0
  93. package/templates/src/components/ui/scroll-shadow.tsx +108 -0
  94. package/templates/src/components/ui/select.tsx +165 -0
  95. package/templates/src/components/ui/skeleton-group.tsx +97 -0
  96. package/templates/src/components/ui/skeleton.tsx +87 -0
  97. package/templates/src/components/ui/spinner.tsx +87 -0
  98. package/templates/src/components/ui/surface.tsx +95 -0
  99. package/templates/src/components/ui/switch.tsx +124 -0
  100. package/templates/src/components/ui/tabs.tsx +154 -0
  101. package/templates/src/components/ui/text-field.tsx +106 -0
  102. package/templates/src/components/ui/toast.tsx +129 -0
  103. package/templates/src/contexts/.gitkeep +2 -0
  104. package/templates/src/core/clients/api/api.client.ts +113 -0
  105. package/templates/src/core/clients/api/index.ts +1 -0
  106. package/templates/src/core/clients/storage/index.ts +1 -0
  107. package/templates/src/core/clients/storage/storage.client.ts +121 -0
  108. package/templates/src/core/constants/index.ts +19 -0
  109. package/templates/src/core/core.ts +40 -0
  110. package/templates/src/core/index.ts +10 -0
  111. package/templates/src/global.css +87 -0
  112. package/templates/src/hooks/index.ts +6 -0
  113. package/templates/src/hooks/use-debounce.ts +23 -0
  114. package/templates/src/hooks/use-mounted.ts +21 -0
  115. package/templates/src/index.ts +28 -0
  116. package/templates/src/lib/index.ts +5 -0
  117. package/templates/src/lib/utils.ts +115 -0
  118. package/templates/src/modules/.gitkeep +6 -0
  119. package/templates/src/navigation/index.ts +8 -0
  120. package/templates/src/navigation/navigation-provider.tsx +36 -0
  121. package/templates/src/navigation/router.tsx +137 -0
  122. package/templates/src/providers/app.provider.tsx +29 -0
  123. package/templates/src/providers/index.ts +5 -0
  124. package/templates/src/routes/(tabs)/_layout.tsx +42 -0
  125. package/templates/src/routes/(tabs)/explore.tsx +161 -0
  126. package/templates/src/routes/(tabs)/home.tsx +138 -0
  127. package/templates/src/routes/(tabs)/profile.tsx +151 -0
  128. package/templates/src/routes/_layout.tsx +18 -0
  129. package/templates/src/routes/settings.tsx +194 -0
  130. package/templates/src/screens/auth/index.ts +6 -0
  131. package/templates/src/screens/auth/login.tsx +165 -0
  132. package/templates/src/screens/auth/register.tsx +203 -0
  133. package/templates/src/screens/home.tsx +204 -0
  134. package/templates/src/screens/index.ts +17 -0
  135. package/templates/src/screens/profile.tsx +210 -0
  136. package/templates/src/screens/settings.tsx +216 -0
  137. package/templates/src/screens/welcome.tsx +101 -0
  138. package/templates/src/styles/index.ts +103 -0
  139. package/templates/src/types/common.ts +71 -0
  140. package/templates/src/types/index.ts +5 -0
  141. package/templates/tsconfig.json +14 -0
  142. package/README.md +0 -15
  143. package/assets/favicon.ico +0 -0
  144. package/dist/commands/dev/dev.d.ts +0 -22
  145. package/dist/commands/dev/dev.js +0 -56
  146. package/dist/commands/dev/dev.js.map +0 -1
  147. package/dist/commands/init/init-teardown.d.ts +0 -9
  148. package/dist/commands/init/init-teardown.js +0 -27
  149. package/dist/commands/init/init-teardown.js.map +0 -1
  150. package/dist/index.d.ts +0 -1
  151. package/dist/index.js +0 -21
  152. package/dist/index.js.map +0 -1
  153. package/dist/modules/dev/dev-menu/keyboard-handler.d.ts +0 -21
  154. package/dist/modules/dev/dev-menu/keyboard-handler.js +0 -139
  155. package/dist/modules/dev/dev-menu/keyboard-handler.js.map +0 -1
  156. package/dist/modules/dev/dev-menu/open-debugger-keyboard-handler.d.ts +0 -18
  157. package/dist/modules/dev/dev-menu/open-debugger-keyboard-handler.js +0 -106
  158. package/dist/modules/dev/dev-menu/open-debugger-keyboard-handler.js.map +0 -1
  159. package/dist/modules/dev/dev-server/cdp/cdp.adapter.d.ts +0 -6
  160. package/dist/modules/dev/dev-server/cdp/cdp.adapter.js +0 -13
  161. package/dist/modules/dev/dev-server/cdp/cdp.adapter.js.map +0 -1
  162. package/dist/modules/dev/dev-server/cdp/index.d.ts +0 -2
  163. package/dist/modules/dev/dev-server/cdp/index.js +0 -19
  164. package/dist/modules/dev/dev-server/cdp/index.js.map +0 -1
  165. package/dist/modules/dev/dev-server/cdp/types.d.ts +0 -107
  166. package/dist/modules/dev/dev-server/cdp/types.js +0 -3
  167. package/dist/modules/dev/dev-server/cdp/types.js.map +0 -1
  168. package/dist/modules/dev/dev-server/dev-server-checker.d.ts +0 -22
  169. package/dist/modules/dev/dev-server/dev-server-checker.js +0 -73
  170. package/dist/modules/dev/dev-server/dev-server-checker.js.map +0 -1
  171. package/dist/modules/dev/dev-server/dev-server.d.ts +0 -74
  172. package/dist/modules/dev/dev-server/dev-server.js +0 -272
  173. package/dist/modules/dev/dev-server/dev-server.js.map +0 -1
  174. package/dist/modules/dev/dev-server/inspector/device.d.ts +0 -46
  175. package/dist/modules/dev/dev-server/inspector/device.event-reporter.d.ts +0 -37
  176. package/dist/modules/dev/dev-server/inspector/device.event-reporter.js +0 -166
  177. package/dist/modules/dev/dev-server/inspector/device.event-reporter.js.map +0 -1
  178. package/dist/modules/dev/dev-server/inspector/device.js +0 -578
  179. package/dist/modules/dev/dev-server/inspector/device.js.map +0 -1
  180. package/dist/modules/dev/dev-server/inspector/inspector.d.ts +0 -27
  181. package/dist/modules/dev/dev-server/inspector/inspector.js +0 -225
  182. package/dist/modules/dev/dev-server/inspector/inspector.js.map +0 -1
  183. package/dist/modules/dev/dev-server/inspector/types.d.ts +0 -156
  184. package/dist/modules/dev/dev-server/inspector/types.js +0 -3
  185. package/dist/modules/dev/dev-server/inspector/types.js.map +0 -1
  186. package/dist/modules/dev/dev-server/inspector/wss/servers/debugger-connection.server.d.ts +0 -14
  187. package/dist/modules/dev/dev-server/inspector/wss/servers/debugger-connection.server.js +0 -63
  188. package/dist/modules/dev/dev-server/inspector/wss/servers/debugger-connection.server.js.map +0 -1
  189. package/dist/modules/dev/dev-server/inspector/wss/servers/device-connection.server.d.ts +0 -19
  190. package/dist/modules/dev/dev-server/inspector/wss/servers/device-connection.server.js +0 -66
  191. package/dist/modules/dev/dev-server/inspector/wss/servers/device-connection.server.js.map +0 -1
  192. package/dist/modules/dev/dev-server/plugins/devtools.plugin.d.ts +0 -1
  193. package/dist/modules/dev/dev-server/plugins/devtools.plugin.js +0 -51
  194. package/dist/modules/dev/dev-server/plugins/devtools.plugin.js.map +0 -1
  195. package/dist/modules/dev/dev-server/plugins/favicon.plugin.d.ts +0 -1
  196. package/dist/modules/dev/dev-server/plugins/favicon.plugin.js +0 -19
  197. package/dist/modules/dev/dev-server/plugins/favicon.plugin.js.map +0 -1
  198. package/dist/modules/dev/dev-server/plugins/multipart.plugin.d.ts +0 -1
  199. package/dist/modules/dev/dev-server/plugins/multipart.plugin.js +0 -63
  200. package/dist/modules/dev/dev-server/plugins/multipart.plugin.js.map +0 -1
  201. package/dist/modules/dev/dev-server/plugins/systrace.plugin.d.ts +0 -1
  202. package/dist/modules/dev/dev-server/plugins/systrace.plugin.js +0 -29
  203. package/dist/modules/dev/dev-server/plugins/systrace.plugin.js.map +0 -1
  204. package/dist/modules/dev/dev-server/plugins/types.d.ts +0 -11
  205. package/dist/modules/dev/dev-server/plugins/types.js +0 -3
  206. package/dist/modules/dev/dev-server/plugins/types.js.map +0 -1
  207. package/dist/modules/dev/dev-server/plugins/wss/index.d.ts +0 -3
  208. package/dist/modules/dev/dev-server/plugins/wss/index.js +0 -20
  209. package/dist/modules/dev/dev-server/plugins/wss/index.js.map +0 -1
  210. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-api.server.d.ts +0 -37
  211. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-api.server.js +0 -67
  212. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-api.server.js.map +0 -1
  213. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-debugger.server.d.ts +0 -63
  214. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-debugger.server.js +0 -129
  215. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-debugger.server.js.map +0 -1
  216. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-dev-client.server.d.ts +0 -32
  217. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-dev-client.server.js +0 -76
  218. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-dev-client.server.js.map +0 -1
  219. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-events.server.d.ts +0 -75
  220. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-events.server.js +0 -199
  221. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-events.server.js.map +0 -1
  222. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-hmr.server.d.ts +0 -44
  223. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-hmr.server.js +0 -121
  224. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-hmr.server.js.map +0 -1
  225. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-message.server.d.ts +0 -135
  226. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-message.server.js +0 -364
  227. package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-message.server.js.map +0 -1
  228. package/dist/modules/dev/dev-server/plugins/wss/types.d.ts +0 -6
  229. package/dist/modules/dev/dev-server/plugins/wss/types.js +0 -3
  230. package/dist/modules/dev/dev-server/plugins/wss/types.js.map +0 -1
  231. package/dist/modules/dev/dev-server/plugins/wss/web-socket-router.d.ts +0 -32
  232. package/dist/modules/dev/dev-server/plugins/wss/web-socket-router.js +0 -58
  233. package/dist/modules/dev/dev-server/plugins/wss/web-socket-router.js.map +0 -1
  234. package/dist/modules/dev/dev-server/plugins/wss/web-socket-server-adapter.d.ts +0 -13
  235. package/dist/modules/dev/dev-server/plugins/wss/web-socket-server-adapter.js +0 -27
  236. package/dist/modules/dev/dev-server/plugins/wss/web-socket-server-adapter.js.map +0 -1
  237. package/dist/modules/dev/dev-server/plugins/wss/web-socket-server.d.ts +0 -39
  238. package/dist/modules/dev/dev-server/plugins/wss/web-socket-server.js +0 -47
  239. package/dist/modules/dev/dev-server/plugins/wss/web-socket-server.js.map +0 -1
  240. package/dist/modules/dev/dev-server/plugins/wss/wss.plugin.d.ts +0 -24
  241. package/dist/modules/dev/dev-server/plugins/wss/wss.plugin.js +0 -56
  242. package/dist/modules/dev/dev-server/plugins/wss/wss.plugin.js.map +0 -1
  243. package/dist/modules/dev/dev-server/sybmolicate/sybmolicate.plugin.d.ts +0 -7
  244. package/dist/modules/dev/dev-server/sybmolicate/sybmolicate.plugin.js +0 -41
  245. package/dist/modules/dev/dev-server/sybmolicate/sybmolicate.plugin.js.map +0 -1
  246. package/dist/modules/dev/dev-server/sybmolicate/types.d.ts +0 -64
  247. package/dist/modules/dev/dev-server/sybmolicate/types.js +0 -3
  248. package/dist/modules/dev/dev-server/sybmolicate/types.js.map +0 -1
  249. package/dist/modules/dev/terminal/base.terminal.reporter.d.ts +0 -25
  250. package/dist/modules/dev/terminal/base.terminal.reporter.js +0 -79
  251. package/dist/modules/dev/terminal/base.terminal.reporter.js.map +0 -1
  252. package/dist/modules/dev/terminal/terminal.reporter.d.ts +0 -13
  253. package/dist/modules/dev/terminal/terminal.reporter.js +0 -83
  254. package/dist/modules/dev/terminal/terminal.reporter.js.map +0 -1
  255. package/dist/modules/dev/types.d.ts +0 -20
  256. package/dist/modules/dev/types.js +0 -3
  257. package/dist/modules/dev/types.js.map +0 -1
  258. package/dist/modules/dev/utils/log.d.ts +0 -23
  259. package/dist/modules/dev/utils/log.js +0 -74
  260. package/dist/modules/dev/utils/log.js.map +0 -1
@@ -0,0 +1,124 @@
1
+ import { z } from "zod";
2
+ import type { AndroidIntentFilter, ProcessedAppConfig } from "../../config/types";
3
+ import { BasePlugin } from "../base";
4
+ import type { PluginContext } from "../context";
5
+
6
+ /**
7
+ * Deep linking plugin configuration schema
8
+ */
9
+ export const DeepLinkingPluginConfigSchema = z.object({
10
+ /** Custom URL scheme */
11
+ scheme: z.string().min(1, "URL scheme is required"),
12
+
13
+ /** Universal Links configuration (iOS) / App Links (Android) */
14
+ universalLinks: z
15
+ .object({
16
+ /** Associated domains */
17
+ domains: z.array(z.string()).min(1),
18
+ /** URL path patterns */
19
+ paths: z.array(z.string()).optional().default(["/*"]),
20
+ })
21
+ .optional(),
22
+
23
+ /** Android App Links configuration */
24
+ androidAppLinks: z
25
+ .object({
26
+ /** App Links host domains */
27
+ hosts: z.array(z.string()).min(1),
28
+ /** URL path patterns */
29
+ paths: z.array(z.string()).optional().default(["/*"]),
30
+ })
31
+ .optional(),
32
+ });
33
+
34
+ export type DeepLinkingPluginConfig = z.infer<typeof DeepLinkingPluginConfigSchema>;
35
+
36
+ /**
37
+ * Deep linking capability plugin
38
+ *
39
+ * Configures deep linking support including custom URL schemes,
40
+ * Universal Links (iOS), and App Links (Android).
41
+ */
42
+ export class DeepLinkingPlugin extends BasePlugin<DeepLinkingPluginConfig> {
43
+ readonly name = "deep-linking";
44
+ readonly version = "1.0.0";
45
+ readonly description = "Configure deep linking with custom schemes and Universal/App Links";
46
+ readonly configSchema = DeepLinkingPluginConfigSchema;
47
+
48
+ override provides = ["deep-linking", "universal-links", "app-links"];
49
+ override platforms: ("ios" | "android")[] = ["ios", "android"];
50
+
51
+ transform(
52
+ config: ProcessedAppConfig,
53
+ pluginConfig: DeepLinkingPluginConfig,
54
+ context: PluginContext
55
+ ): ProcessedAppConfig {
56
+ const { log } = context;
57
+ log.debug("Applying deep linking configuration...");
58
+
59
+ let result = config;
60
+
61
+ // Add custom URL scheme
62
+ result = this.addUrlScheme(result, pluginConfig.scheme);
63
+
64
+ // iOS: Configure Universal Links
65
+ if (pluginConfig.universalLinks) {
66
+ for (const domain of pluginConfig.universalLinks.domains) {
67
+ // Add associated domain entitlement
68
+ result = this.addAssociatedDomain(result, domain, "applinks");
69
+ // Also add webcredentials for password autofill
70
+ result = this.addAssociatedDomain(result, domain, "webcredentials");
71
+ }
72
+ }
73
+
74
+ // Android: Add intent filter for custom scheme
75
+ const schemeFilter: AndroidIntentFilter = {
76
+ actions: ["android.intent.action.VIEW"],
77
+ categories: ["android.intent.category.DEFAULT", "android.intent.category.BROWSABLE"],
78
+ data: [{ scheme: pluginConfig.scheme }],
79
+ };
80
+ result = this.addIntentFilter(result, schemeFilter);
81
+
82
+ // Android: Configure App Links
83
+ if (pluginConfig.androidAppLinks || pluginConfig.universalLinks) {
84
+ const hosts = pluginConfig.androidAppLinks?.hosts ?? pluginConfig.universalLinks?.domains ?? [];
85
+ const paths = pluginConfig.androidAppLinks?.paths ?? pluginConfig.universalLinks?.paths ?? ["/*"];
86
+
87
+ for (const host of hosts) {
88
+ const appLinkFilter: AndroidIntentFilter = {
89
+ actions: ["android.intent.action.VIEW"],
90
+ categories: ["android.intent.category.DEFAULT", "android.intent.category.BROWSABLE"],
91
+ data: paths.map((pathPrefix) => ({
92
+ scheme: "https",
93
+ host,
94
+ pathPrefix: pathPrefix.replace("*", ""),
95
+ })),
96
+ autoVerify: true,
97
+ };
98
+ result = this.addIntentFilter(result, appLinkFilter);
99
+ }
100
+ }
101
+
102
+ return result;
103
+ }
104
+
105
+ /**
106
+ * Helper to add associated domain entitlement
107
+ */
108
+ private addAssociatedDomain(
109
+ config: ProcessedAppConfig,
110
+ domain: string,
111
+ type: "applinks" | "webcredentials" | "activitycontinuation"
112
+ ): ProcessedAppConfig {
113
+ const key = "com.apple.developer.associated-domains";
114
+ const domainEntry = `${type}:${domain}`;
115
+
116
+ const existingDomains = (config.resolvedEntitlements[key] as string[]) || [];
117
+
118
+ if (!existingDomains.includes(domainEntry)) {
119
+ return this.addEntitlement(config, key, [...existingDomains, domainEntry]);
120
+ }
121
+
122
+ return config;
123
+ }
124
+ }
@@ -0,0 +1,138 @@
1
+ import { z } from "zod";
2
+ import type { ProcessedAppConfig } from "../../config/types";
3
+ import { BasePlugin } from "../base";
4
+ import type { PluginContext } from "../context";
5
+
6
+ /**
7
+ * Firebase plugin configuration schema
8
+ */
9
+ export const FirebasePluginConfigSchema = z.object({
10
+ /** Enable Firebase Analytics */
11
+ analytics: z.boolean().optional().default(true),
12
+
13
+ /** Enable Firebase Crashlytics */
14
+ crashlytics: z.boolean().optional().default(true),
15
+
16
+ /** Enable Firebase Cloud Messaging */
17
+ messaging: z.boolean().optional().default(false),
18
+
19
+ /** Enable Firebase Remote Config */
20
+ remoteConfig: z.boolean().optional().default(false),
21
+
22
+ /** Enable Firebase Performance Monitoring */
23
+ performance: z.boolean().optional().default(false),
24
+
25
+ /** Path to GoogleService-Info.plist (iOS) */
26
+ iosGoogleServicesFile: z.string().optional(),
27
+
28
+ /** Path to google-services.json (Android) */
29
+ androidGoogleServicesFile: z.string().optional(),
30
+ });
31
+
32
+ export type FirebasePluginConfig = z.infer<typeof FirebasePluginConfigSchema>;
33
+
34
+ /**
35
+ * Firebase capability plugin
36
+ *
37
+ * Configures Firebase SDK integration including Analytics,
38
+ * Crashlytics, Cloud Messaging, Remote Config, and Performance.
39
+ */
40
+ export class FirebasePlugin extends BasePlugin<FirebasePluginConfig> {
41
+ readonly name = "firebase";
42
+ readonly version = "1.0.0";
43
+ readonly description = "Configure Firebase SDK integration (Analytics, Crashlytics, FCM, etc.)";
44
+ readonly configSchema = FirebasePluginConfigSchema;
45
+
46
+ override provides = ["firebase", "analytics", "crashlytics"];
47
+ override platforms: ("ios" | "android")[] = ["ios", "android"];
48
+
49
+ transform(
50
+ config: ProcessedAppConfig,
51
+ pluginConfig: FirebasePluginConfig,
52
+ context: PluginContext
53
+ ): ProcessedAppConfig {
54
+ const { log } = context;
55
+ log.debug("Applying Firebase configuration...");
56
+
57
+ let result = config;
58
+
59
+ // iOS: Add Firebase CocoaPods
60
+ result = this.addPodDependency(result, { name: "Firebase/Core" });
61
+
62
+ if (pluginConfig.analytics) {
63
+ result = this.addPodDependency(result, { name: "Firebase/Analytics" });
64
+ }
65
+
66
+ if (pluginConfig.crashlytics) {
67
+ result = this.addPodDependency(result, { name: "Firebase/Crashlytics" });
68
+
69
+ // Enable Crashlytics collection
70
+ result = {
71
+ ...result,
72
+ resolvedInfoPlist: {
73
+ ...result.resolvedInfoPlist,
74
+ FirebaseCrashlyticsCollectionEnabled: true,
75
+ },
76
+ };
77
+ }
78
+
79
+ if (pluginConfig.messaging) {
80
+ result = this.addPodDependency(result, { name: "Firebase/Messaging" });
81
+
82
+ // Add push notification background mode
83
+ result = this.addBackgroundMode(result, "remote-notification");
84
+ }
85
+
86
+ if (pluginConfig.remoteConfig) {
87
+ result = this.addPodDependency(result, { name: "Firebase/RemoteConfig" });
88
+ }
89
+
90
+ if (pluginConfig.performance) {
91
+ result = this.addPodDependency(result, { name: "Firebase/Performance" });
92
+ }
93
+
94
+ // Android: Add Firebase dependencies
95
+ result = this.addGradleDependency(result, "com.google.firebase:firebase-bom:33.0.0");
96
+
97
+ if (pluginConfig.analytics) {
98
+ result = this.addGradleDependency(result, "com.google.firebase:firebase-analytics");
99
+ }
100
+
101
+ if (pluginConfig.crashlytics) {
102
+ result = this.addGradleDependency(result, "com.google.firebase:firebase-crashlytics");
103
+
104
+ // Add Crashlytics metadata
105
+ result = this.addAndroidMetadata(result, "firebase_crashlytics_collection_enabled", "true");
106
+ }
107
+
108
+ if (pluginConfig.messaging) {
109
+ result = this.addGradleDependency(result, "com.google.firebase:firebase-messaging");
110
+
111
+ // Add required permissions
112
+ result = this.addAndroidPermission(result, "android.permission.POST_NOTIFICATIONS");
113
+ result = this.addAndroidPermission(result, "android.permission.WAKE_LOCK");
114
+ }
115
+
116
+ if (pluginConfig.remoteConfig) {
117
+ result = this.addGradleDependency(result, "com.google.firebase:firebase-config");
118
+ }
119
+
120
+ if (pluginConfig.performance) {
121
+ result = this.addGradleDependency(result, "com.google.firebase:firebase-perf");
122
+ }
123
+
124
+ // Android: Add internet permission
125
+ result = this.addAndroidPermission(result, "android.permission.INTERNET");
126
+ result = this.addAndroidPermission(result, "android.permission.ACCESS_NETWORK_STATE");
127
+
128
+ return result;
129
+ }
130
+
131
+ override async postProcess(context: PluginContext): Promise<void> {
132
+ const { log, isDryRun } = context;
133
+
134
+ if (!isDryRun) {
135
+ log.debug("Firebase post-processing: Ensure GoogleService-Info.plist and google-services.json are present");
136
+ }
137
+ }
138
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Capability plugins for Teardown Launchpad
3
+ *
4
+ * These plugins configure native capabilities for iOS and Android,
5
+ * including permissions, entitlements, frameworks, and dependencies.
6
+ */
7
+
8
+ import { BiometricsPlugin, BiometricsPluginConfigSchema } from "./biometrics";
9
+ import { BluetoothPlugin, BluetoothPluginConfigSchema } from "./bluetooth";
10
+ import { CalendarPlugin, CalendarPluginConfigSchema } from "./calendar";
11
+ // Import all plugins for re-export and use in objects
12
+ import { CameraPlugin, CameraPluginConfigSchema } from "./camera";
13
+ import { ContactsPlugin, ContactsPluginConfigSchema } from "./contacts";
14
+ import { DeepLinkingPlugin, DeepLinkingPluginConfigSchema } from "./deep-linking";
15
+ import { FirebasePlugin, FirebasePluginConfigSchema } from "./firebase";
16
+ import { LocationPlugin, LocationPluginConfigSchema } from "./location";
17
+ import { PhotoLibraryPlugin, PhotoLibraryPluginConfigSchema } from "./photo-library";
18
+ import { PushNotificationsPlugin, PushNotificationsPluginConfigSchema } from "./push-notifications";
19
+ import { SignInWithApplePlugin, SignInWithApplePluginConfigSchema } from "./sign-in-with-apple";
20
+
21
+ // Re-export plugins
22
+ export {
23
+ CameraPlugin,
24
+ CameraPluginConfigSchema,
25
+ LocationPlugin,
26
+ LocationPluginConfigSchema,
27
+ PushNotificationsPlugin,
28
+ PushNotificationsPluginConfigSchema,
29
+ BiometricsPlugin,
30
+ BiometricsPluginConfigSchema,
31
+ DeepLinkingPlugin,
32
+ DeepLinkingPluginConfigSchema,
33
+ FirebasePlugin,
34
+ FirebasePluginConfigSchema,
35
+ ContactsPlugin,
36
+ ContactsPluginConfigSchema,
37
+ CalendarPlugin,
38
+ CalendarPluginConfigSchema,
39
+ PhotoLibraryPlugin,
40
+ PhotoLibraryPluginConfigSchema,
41
+ BluetoothPlugin,
42
+ BluetoothPluginConfigSchema,
43
+ SignInWithApplePlugin,
44
+ SignInWithApplePluginConfigSchema,
45
+ };
46
+
47
+ export type { BiometricsPluginConfig } from "./biometrics";
48
+ export type { BluetoothPluginConfig } from "./bluetooth";
49
+ export type { CalendarPluginConfig } from "./calendar";
50
+ // Re-export types
51
+ export type { CameraPluginConfig } from "./camera";
52
+ export type { ContactsPluginConfig } from "./contacts";
53
+ export type { DeepLinkingPluginConfig } from "./deep-linking";
54
+ export type { FirebasePluginConfig } from "./firebase";
55
+ export type { LocationPluginConfig } from "./location";
56
+ export type { PhotoLibraryPluginConfig } from "./photo-library";
57
+ export type { PushNotificationsPluginConfig } from "./push-notifications";
58
+ export type { SignInWithApplePluginConfig } from "./sign-in-with-apple";
59
+
60
+ /**
61
+ * All available capability plugins
62
+ */
63
+ export const CapabilityPlugins = {
64
+ CameraPlugin,
65
+ LocationPlugin,
66
+ PushNotificationsPlugin,
67
+ BiometricsPlugin,
68
+ DeepLinkingPlugin,
69
+ FirebasePlugin,
70
+ ContactsPlugin,
71
+ CalendarPlugin,
72
+ PhotoLibraryPlugin,
73
+ BluetoothPlugin,
74
+ SignInWithApplePlugin,
75
+ } as const;
76
+
77
+ /**
78
+ * Get a plugin by name
79
+ */
80
+ export function getPluginByName(name: string) {
81
+ const plugins: Record<string, unknown> = {
82
+ camera: CameraPlugin,
83
+ location: LocationPlugin,
84
+ "push-notifications": PushNotificationsPlugin,
85
+ biometrics: BiometricsPlugin,
86
+ "deep-linking": DeepLinkingPlugin,
87
+ firebase: FirebasePlugin,
88
+ contacts: ContactsPlugin,
89
+ calendar: CalendarPlugin,
90
+ "photo-library": PhotoLibraryPlugin,
91
+ bluetooth: BluetoothPlugin,
92
+ "sign-in-with-apple": SignInWithApplePlugin,
93
+ };
94
+
95
+ return plugins[name];
96
+ }
@@ -0,0 +1,87 @@
1
+ import { z } from "zod";
2
+ import type { ProcessedAppConfig } from "../../config/types";
3
+ import { BasePlugin } from "../base";
4
+ import type { PluginContext } from "../context";
5
+
6
+ /**
7
+ * Location plugin configuration schema
8
+ */
9
+ export const LocationPluginConfigSchema = z.object({
10
+ /** iOS when-in-use location usage description */
11
+ whenInUsePermission: z.string().min(1, "When-in-use permission description is required"),
12
+
13
+ /** iOS always-on location usage description */
14
+ alwaysPermission: z.string().optional(),
15
+
16
+ /** Show background location indicator */
17
+ backgroundIndicator: z.boolean().optional().default(true),
18
+
19
+ /** Enable high accuracy GPS */
20
+ highAccuracy: z.boolean().optional().default(true),
21
+ });
22
+
23
+ export type LocationPluginConfig = z.infer<typeof LocationPluginConfigSchema>;
24
+
25
+ /**
26
+ * Location capability plugin
27
+ *
28
+ * Configures location access for iOS and Android including
29
+ * foreground, background, and always-on location permissions.
30
+ */
31
+ export class LocationPlugin extends BasePlugin<LocationPluginConfig> {
32
+ readonly name = "location";
33
+ readonly version = "1.0.0";
34
+ readonly description = "Configure location services for geolocation features";
35
+ readonly configSchema = LocationPluginConfigSchema;
36
+
37
+ override provides = ["location"];
38
+ override platforms: ("ios" | "android")[] = ["ios", "android"];
39
+
40
+ transform(
41
+ config: ProcessedAppConfig,
42
+ pluginConfig: LocationPluginConfig,
43
+ context: PluginContext
44
+ ): ProcessedAppConfig {
45
+ const { log } = context;
46
+ log.debug("Applying location configuration...");
47
+
48
+ let result = config;
49
+
50
+ // iOS: Add usage descriptions
51
+ result = this.addUsageDescription(result, "NSLocationWhenInUseUsageDescription", pluginConfig.whenInUsePermission);
52
+
53
+ if (pluginConfig.alwaysPermission) {
54
+ result = this.addUsageDescription(
55
+ result,
56
+ "NSLocationAlwaysAndWhenInUseUsageDescription",
57
+ pluginConfig.alwaysPermission
58
+ );
59
+
60
+ // Also add legacy key for older iOS versions
61
+ result = this.addUsageDescription(result, "NSLocationAlwaysUsageDescription", pluginConfig.alwaysPermission);
62
+
63
+ // Add background mode
64
+ result = this.addBackgroundMode(result, "location");
65
+ }
66
+
67
+ // iOS: Add framework
68
+ result = this.addFramework(result, "CoreLocation");
69
+
70
+ // Android: Add permissions
71
+ result = this.addAndroidPermission(result, "android.permission.ACCESS_FINE_LOCATION");
72
+ result = this.addAndroidPermission(result, "android.permission.ACCESS_COARSE_LOCATION");
73
+
74
+ if (pluginConfig.alwaysPermission) {
75
+ result = this.addAndroidPermission(result, "android.permission.ACCESS_BACKGROUND_LOCATION");
76
+ result = this.addAndroidPermission(result, "android.permission.FOREGROUND_SERVICE");
77
+ result = this.addAndroidPermission(result, "android.permission.FOREGROUND_SERVICE_LOCATION");
78
+ }
79
+
80
+ // Android: Add GPS feature
81
+ if (pluginConfig.highAccuracy) {
82
+ result = this.addAndroidFeature(result, "android.hardware.location.gps");
83
+ }
84
+
85
+ return result;
86
+ }
87
+ }
@@ -0,0 +1,80 @@
1
+ import { z } from "zod";
2
+ import type { ProcessedAppConfig } from "../../config/types";
3
+ import { BasePlugin } from "../base";
4
+ import type { PluginContext } from "../context";
5
+
6
+ /**
7
+ * Photo library plugin configuration schema
8
+ */
9
+ export const PhotoLibraryPluginConfigSchema = z.object({
10
+ /** iOS photo library read permission description */
11
+ readPermission: z.string().min(1, "Photo library read permission description is required"),
12
+
13
+ /** iOS photo library write permission description */
14
+ writePermission: z.string().optional(),
15
+
16
+ /** Behavior for iOS 14+ limited photo access */
17
+ limitedAccessBehavior: z.enum(["prompt", "silent"]).optional().default("prompt"),
18
+ });
19
+
20
+ export type PhotoLibraryPluginConfig = z.infer<typeof PhotoLibraryPluginConfigSchema>;
21
+
22
+ /**
23
+ * Photo library capability plugin
24
+ */
25
+ export class PhotoLibraryPlugin extends BasePlugin<PhotoLibraryPluginConfig> {
26
+ readonly name = "photo-library";
27
+ readonly version = "1.0.0";
28
+ readonly description = "Configure photo library access for reading and writing photos/videos";
29
+ readonly configSchema = PhotoLibraryPluginConfigSchema;
30
+
31
+ override provides = ["photo-library", "photos"];
32
+ override platforms: ("ios" | "android")[] = ["ios", "android"];
33
+
34
+ transform(
35
+ config: ProcessedAppConfig,
36
+ pluginConfig: PhotoLibraryPluginConfig,
37
+ context: PluginContext
38
+ ): ProcessedAppConfig {
39
+ const { log } = context;
40
+ log.debug("Applying photo library configuration...");
41
+
42
+ let result = config;
43
+
44
+ // iOS: Add read usage description
45
+ result = this.addUsageDescription(result, "NSPhotoLibraryUsageDescription", pluginConfig.readPermission);
46
+
47
+ // iOS: Add write usage description
48
+ if (pluginConfig.writePermission) {
49
+ result = this.addUsageDescription(result, "NSPhotoLibraryAddUsageDescription", pluginConfig.writePermission);
50
+ }
51
+
52
+ // iOS: Configure limited photo access behavior
53
+ if (pluginConfig.limitedAccessBehavior === "silent") {
54
+ result = {
55
+ ...result,
56
+ resolvedInfoPlist: {
57
+ ...result.resolvedInfoPlist,
58
+ PHPhotoLibraryPreventAutomaticLimitedAccessAlert: true,
59
+ },
60
+ };
61
+ }
62
+
63
+ // iOS: Add Photos framework
64
+ result = this.addFramework(result, "Photos");
65
+ result = this.addFramework(result, "PhotosUI");
66
+
67
+ // Android: Add media permissions (Android 13+)
68
+ result = this.addAndroidPermission(result, "android.permission.READ_MEDIA_IMAGES");
69
+ result = this.addAndroidPermission(result, "android.permission.READ_MEDIA_VIDEO");
70
+
71
+ // Android: Legacy storage permission for older versions
72
+ result = this.addAndroidPermission(result, "android.permission.READ_EXTERNAL_STORAGE");
73
+
74
+ if (pluginConfig.writePermission) {
75
+ result = this.addAndroidPermission(result, "android.permission.WRITE_EXTERNAL_STORAGE");
76
+ }
77
+
78
+ return result;
79
+ }
80
+ }
@@ -0,0 +1,98 @@
1
+ import { z } from "zod";
2
+ import type { ProcessedAppConfig } from "../../config/types";
3
+ import { BasePlugin } from "../base";
4
+ import type { PluginContext } from "../context";
5
+
6
+ /**
7
+ * Push notifications plugin configuration schema
8
+ */
9
+ export const PushNotificationsPluginConfigSchema = z.object({
10
+ /** Push notification environment */
11
+ environment: z.enum(["development", "production"]).default("development"),
12
+
13
+ /** Default notification channel ID (Android) */
14
+ defaultChannelId: z.string().optional().default("default"),
15
+
16
+ /** Default notification icon resource (Android) */
17
+ defaultIcon: z.string().optional(),
18
+
19
+ /** Enable remote notification background mode (iOS) */
20
+ backgroundModes: z.boolean().optional().default(true),
21
+
22
+ /** Enable silent push notifications */
23
+ silentNotifications: z.boolean().optional().default(true),
24
+ });
25
+
26
+ export type PushNotificationsPluginConfig = z.infer<typeof PushNotificationsPluginConfigSchema>;
27
+
28
+ /**
29
+ * Push notifications capability plugin
30
+ *
31
+ * Configures push notification support for iOS (APNs) and Android (FCM)
32
+ * including entitlements, background modes, and notification settings.
33
+ */
34
+ export class PushNotificationsPlugin extends BasePlugin<PushNotificationsPluginConfig> {
35
+ readonly name = "push-notifications";
36
+ readonly version = "1.0.0";
37
+ readonly description = "Configure push notifications for iOS (APNs) and Android (FCM)";
38
+ readonly configSchema = PushNotificationsPluginConfigSchema;
39
+
40
+ override provides = ["push-notifications", "notifications"];
41
+ override platforms: ("ios" | "android")[] = ["ios", "android"];
42
+
43
+ transform(
44
+ config: ProcessedAppConfig,
45
+ pluginConfig: PushNotificationsPluginConfig,
46
+ context: PluginContext
47
+ ): ProcessedAppConfig {
48
+ const { log } = context;
49
+ log.debug("Applying push notifications configuration...");
50
+
51
+ let result = config;
52
+
53
+ // iOS: Add APS entitlement
54
+ result = this.addEntitlement(result, "aps-environment", pluginConfig.environment);
55
+
56
+ // iOS: Add background modes
57
+ if (pluginConfig.backgroundModes) {
58
+ result = this.addBackgroundMode(result, "remote-notification");
59
+ }
60
+
61
+ if (pluginConfig.silentNotifications) {
62
+ result = this.addBackgroundMode(result, "fetch");
63
+ }
64
+
65
+ // iOS: Add UserNotifications framework
66
+ result = this.addFramework(result, "UserNotifications");
67
+
68
+ // Android: Add POST_NOTIFICATIONS permission (Android 13+)
69
+ result = this.addAndroidPermission(result, "android.permission.POST_NOTIFICATIONS");
70
+
71
+ // Android: Add RECEIVE_BOOT_COMPLETED for scheduling
72
+ result = this.addAndroidPermission(result, "android.permission.RECEIVE_BOOT_COMPLETED");
73
+
74
+ // Android: Add VIBRATE permission
75
+ result = this.addAndroidPermission(result, "android.permission.VIBRATE");
76
+
77
+ // Android: Add wake lock for background processing
78
+ result = this.addAndroidPermission(result, "android.permission.WAKE_LOCK");
79
+
80
+ // Android: Add default notification icon metadata
81
+ if (pluginConfig.defaultIcon) {
82
+ result = this.addAndroidMetadata(
83
+ result,
84
+ "com.google.firebase.messaging.default_notification_icon",
85
+ pluginConfig.defaultIcon
86
+ );
87
+ }
88
+
89
+ // Android: Add default notification channel
90
+ result = this.addAndroidMetadata(
91
+ result,
92
+ "com.google.firebase.messaging.default_notification_channel_id",
93
+ pluginConfig.defaultChannelId ?? "default"
94
+ );
95
+
96
+ return result;
97
+ }
98
+ }
@@ -0,0 +1,53 @@
1
+ import { z } from "zod";
2
+ import type { ProcessedAppConfig } from "../../config/types";
3
+ import { BasePlugin } from "../base";
4
+ import type { PluginContext } from "../context";
5
+
6
+ /**
7
+ * Sign in with Apple plugin configuration schema
8
+ */
9
+ export const SignInWithApplePluginConfigSchema = z.object({
10
+ /** Enable Sign in with Apple */
11
+ enabled: z.boolean().optional().default(true),
12
+ });
13
+
14
+ export type SignInWithApplePluginConfig = z.infer<typeof SignInWithApplePluginConfigSchema>;
15
+
16
+ /**
17
+ * Sign in with Apple capability plugin
18
+ */
19
+ export class SignInWithApplePlugin extends BasePlugin<SignInWithApplePluginConfig> {
20
+ readonly name = "sign-in-with-apple";
21
+ readonly version = "1.0.0";
22
+ readonly description = "Configure Sign in with Apple authentication";
23
+ readonly configSchema = SignInWithApplePluginConfigSchema;
24
+
25
+ override provides = ["sign-in-with-apple", "apple-auth"];
26
+ override platforms: ("ios" | "android")[] = ["ios", "android"];
27
+
28
+ transform(
29
+ config: ProcessedAppConfig,
30
+ pluginConfig: SignInWithApplePluginConfig,
31
+ context: PluginContext
32
+ ): ProcessedAppConfig {
33
+ const { log } = context;
34
+
35
+ if (!pluginConfig.enabled) {
36
+ return config;
37
+ }
38
+
39
+ log.debug("Applying Sign in with Apple configuration...");
40
+
41
+ let result = config;
42
+
43
+ // iOS: Add entitlement
44
+ result = this.addEntitlement(result, "com.apple.developer.applesignin", ["Default"]);
45
+
46
+ // iOS: Add AuthenticationServices framework
47
+ result = this.addFramework(result, "AuthenticationServices");
48
+
49
+ // Android: No native configuration required (uses web-based OAuth)
50
+
51
+ return result;
52
+ }
53
+ }