@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,370 @@
1
+ import type { z } from "zod";
2
+ import type { ProcessedAppConfig } from "../config/types";
3
+ import type { PluginContext } from "./context";
4
+
5
+ /**
6
+ * Info.plist entries type
7
+ */
8
+ export type InfoPlist = Record<string, unknown>;
9
+
10
+ /**
11
+ * Entitlements type
12
+ */
13
+ export type Entitlements = Record<string, unknown>;
14
+
15
+ /**
16
+ * Android Manifest type (simplified)
17
+ */
18
+ export interface AndroidManifest {
19
+ permissions: string[];
20
+ features: string[];
21
+ metadata: Record<string, string>;
22
+ activities: AndroidActivity[];
23
+ services: AndroidService[];
24
+ receivers: AndroidReceiver[];
25
+ providers: AndroidProvider[];
26
+ }
27
+
28
+ export interface AndroidActivity {
29
+ name: string;
30
+ intentFilters?: AndroidIntentFilter[];
31
+ exported?: boolean;
32
+ launchMode?: string;
33
+ screenOrientation?: string;
34
+ configChanges?: string;
35
+ }
36
+
37
+ export interface AndroidIntentFilter {
38
+ actions: string[];
39
+ categories: string[];
40
+ data?: AndroidIntentData[];
41
+ autoVerify?: boolean;
42
+ }
43
+
44
+ export interface AndroidIntentData {
45
+ scheme?: string;
46
+ host?: string;
47
+ pathPrefix?: string;
48
+ path?: string;
49
+ }
50
+
51
+ export interface AndroidService {
52
+ name: string;
53
+ exported?: boolean;
54
+ permission?: string;
55
+ intentFilters?: AndroidIntentFilter[];
56
+ }
57
+
58
+ export interface AndroidReceiver {
59
+ name: string;
60
+ exported?: boolean;
61
+ intentFilters?: AndroidIntentFilter[];
62
+ }
63
+
64
+ export interface AndroidProvider {
65
+ name: string;
66
+ authorities: string;
67
+ exported?: boolean;
68
+ grantUriPermissions?: boolean;
69
+ }
70
+
71
+ /**
72
+ * Abstract base class for all Teardown plugins
73
+ *
74
+ * Plugins extend this class to implement native configuration
75
+ * for specific capabilities (camera, location, push notifications, etc.)
76
+ */
77
+ export abstract class BasePlugin<TConfig = unknown> {
78
+ /**
79
+ * Unique plugin identifier
80
+ */
81
+ abstract readonly name: string;
82
+
83
+ /**
84
+ * Plugin version (semver)
85
+ */
86
+ abstract readonly version: string;
87
+
88
+ /**
89
+ * Zod schema for validating plugin configuration
90
+ */
91
+ abstract readonly configSchema: z.ZodSchema<TConfig>;
92
+
93
+ /**
94
+ * Human-readable description of what this plugin does
95
+ */
96
+ abstract readonly description: string;
97
+
98
+ /**
99
+ * Plugin names that this plugin depends on (must run first)
100
+ */
101
+ dependencies: string[] = [];
102
+
103
+ /**
104
+ * Capabilities that this plugin provides
105
+ */
106
+ provides: string[] = [];
107
+
108
+ /**
109
+ * Platforms this plugin supports
110
+ */
111
+ platforms: ("ios" | "android")[] = ["ios", "android"];
112
+
113
+ /**
114
+ * Validate and parse plugin configuration
115
+ */
116
+ validateConfig(config: unknown): TConfig {
117
+ return this.configSchema.parse(config);
118
+ }
119
+
120
+ /**
121
+ * Check if plugin supports the target platform
122
+ */
123
+ supportsPlatform(platform: "ios" | "android"): boolean {
124
+ return this.platforms.includes(platform);
125
+ }
126
+
127
+ /**
128
+ * Pre-process hook - runs before transform
129
+ * Use for validation, setup, or reading existing files
130
+ */
131
+ async preProcess(_context: PluginContext): Promise<void> {
132
+ // Default implementation does nothing
133
+ }
134
+
135
+ /**
136
+ * Main transformation method - modifies the app configuration
137
+ * This is the core method that plugins must implement
138
+ */
139
+ abstract transform(config: ProcessedAppConfig, pluginConfig: TConfig, context: PluginContext): ProcessedAppConfig;
140
+
141
+ /**
142
+ * Post-process hook - runs after transform
143
+ * Use for cleanup, file generation, or additional modifications
144
+ */
145
+ async postProcess(_context: PluginContext): Promise<void> {
146
+ // Default implementation does nothing
147
+ }
148
+
149
+ /**
150
+ * Modify iOS Info.plist entries
151
+ * Override in subclass to add plist modifications
152
+ */
153
+ protected modifyInfoPlist(plist: InfoPlist, _config: TConfig, _context: PluginContext): InfoPlist {
154
+ return plist;
155
+ }
156
+
157
+ /**
158
+ * Modify iOS entitlements
159
+ * Override in subclass to add entitlement modifications
160
+ */
161
+ protected modifyEntitlements(entitlements: Entitlements, _config: TConfig, _context: PluginContext): Entitlements {
162
+ return entitlements;
163
+ }
164
+
165
+ /**
166
+ * Modify Android manifest
167
+ * Override in subclass to add manifest modifications
168
+ */
169
+ protected modifyAndroidManifest(
170
+ manifest: AndroidManifest,
171
+ _config: TConfig,
172
+ _context: PluginContext
173
+ ): AndroidManifest {
174
+ return manifest;
175
+ }
176
+
177
+ /**
178
+ * Modify Android build.gradle content
179
+ * Override in subclass to add Gradle modifications
180
+ */
181
+ protected modifyBuildGradle(content: string, _config: TConfig, _context: PluginContext): string {
182
+ return content;
183
+ }
184
+
185
+ /**
186
+ * Get iOS frameworks required by this plugin
187
+ */
188
+ protected getRequiredFrameworks(_config: TConfig): string[] {
189
+ return [];
190
+ }
191
+
192
+ /**
193
+ * Get CocoaPods dependencies required by this plugin
194
+ */
195
+ protected getPodDependencies(
196
+ _config: TConfig
197
+ ): Array<{ name: string; version?: string; options?: Record<string, unknown> }> {
198
+ return [];
199
+ }
200
+
201
+ /**
202
+ * Get Gradle dependencies required by this plugin
203
+ */
204
+ protected getGradleDependencies(_config: TConfig): string[] {
205
+ return [];
206
+ }
207
+
208
+ /**
209
+ * Get Android permissions required by this plugin
210
+ */
211
+ protected getAndroidPermissions(_config: TConfig): string[] {
212
+ return [];
213
+ }
214
+
215
+ /**
216
+ * Get iOS background modes required by this plugin
217
+ */
218
+ protected getBackgroundModes(_config: TConfig): string[] {
219
+ return [];
220
+ }
221
+
222
+ /**
223
+ * Helper to add Info.plist usage description
224
+ */
225
+ protected addUsageDescription(config: ProcessedAppConfig, key: string, description: string): ProcessedAppConfig {
226
+ return {
227
+ ...config,
228
+ resolvedInfoPlist: {
229
+ ...config.resolvedInfoPlist,
230
+ [key]: description,
231
+ },
232
+ };
233
+ }
234
+
235
+ /**
236
+ * Helper to add iOS entitlement
237
+ */
238
+ protected addEntitlement(config: ProcessedAppConfig, key: string, value: unknown): ProcessedAppConfig {
239
+ return {
240
+ ...config,
241
+ resolvedEntitlements: {
242
+ ...config.resolvedEntitlements,
243
+ [key]: value,
244
+ },
245
+ };
246
+ }
247
+
248
+ /**
249
+ * Helper to add Android permission
250
+ */
251
+ protected addAndroidPermission(config: ProcessedAppConfig, permission: string): ProcessedAppConfig {
252
+ if (config.resolvedAndroidPermissions.includes(permission)) {
253
+ return config;
254
+ }
255
+ return {
256
+ ...config,
257
+ resolvedAndroidPermissions: [...config.resolvedAndroidPermissions, permission],
258
+ };
259
+ }
260
+
261
+ /**
262
+ * Helper to add Android feature
263
+ */
264
+ protected addAndroidFeature(config: ProcessedAppConfig, feature: string): ProcessedAppConfig {
265
+ if (config.resolvedAndroidFeatures.includes(feature)) {
266
+ return config;
267
+ }
268
+ return {
269
+ ...config,
270
+ resolvedAndroidFeatures: [...config.resolvedAndroidFeatures, feature],
271
+ };
272
+ }
273
+
274
+ /**
275
+ * Helper to add iOS background mode
276
+ */
277
+ protected addBackgroundMode(config: ProcessedAppConfig, mode: string): ProcessedAppConfig {
278
+ if (config.resolvedBackgroundModes.includes(mode)) {
279
+ return config;
280
+ }
281
+ return {
282
+ ...config,
283
+ resolvedBackgroundModes: [...config.resolvedBackgroundModes, mode],
284
+ };
285
+ }
286
+
287
+ /**
288
+ * Helper to add iOS framework
289
+ */
290
+ protected addFramework(config: ProcessedAppConfig, framework: string): ProcessedAppConfig {
291
+ if (config.resolvedFrameworks.includes(framework)) {
292
+ return config;
293
+ }
294
+ return {
295
+ ...config,
296
+ resolvedFrameworks: [...config.resolvedFrameworks, framework],
297
+ };
298
+ }
299
+
300
+ /**
301
+ * Helper to add Gradle dependency
302
+ */
303
+ protected addGradleDependency(config: ProcessedAppConfig, dependency: string): ProcessedAppConfig {
304
+ if (config.resolvedGradleDependencies.includes(dependency)) {
305
+ return config;
306
+ }
307
+ return {
308
+ ...config,
309
+ resolvedGradleDependencies: [...config.resolvedGradleDependencies, dependency],
310
+ };
311
+ }
312
+
313
+ /**
314
+ * Helper to add CocoaPods dependency
315
+ */
316
+ protected addPodDependency(
317
+ config: ProcessedAppConfig,
318
+ pod: { name: string; version?: string; options?: Record<string, unknown> }
319
+ ): ProcessedAppConfig {
320
+ const existing = config.resolvedPodDependencies.find((p) => p.name === pod.name);
321
+ if (existing) {
322
+ return config;
323
+ }
324
+ return {
325
+ ...config,
326
+ resolvedPodDependencies: [...config.resolvedPodDependencies, pod],
327
+ };
328
+ }
329
+
330
+ /**
331
+ * Helper to add URL scheme
332
+ */
333
+ protected addUrlScheme(config: ProcessedAppConfig, scheme: string): ProcessedAppConfig {
334
+ if (config.resolvedUrlSchemes.includes(scheme)) {
335
+ return config;
336
+ }
337
+ return {
338
+ ...config,
339
+ resolvedUrlSchemes: [...config.resolvedUrlSchemes, scheme],
340
+ };
341
+ }
342
+
343
+ /**
344
+ * Helper to add Android intent filter
345
+ */
346
+ protected addIntentFilter(config: ProcessedAppConfig, intentFilter: AndroidIntentFilter): ProcessedAppConfig {
347
+ return {
348
+ ...config,
349
+ resolvedIntentFilters: [...config.resolvedIntentFilters, intentFilter],
350
+ };
351
+ }
352
+
353
+ /**
354
+ * Helper to add Android metadata
355
+ */
356
+ protected addAndroidMetadata(config: ProcessedAppConfig, key: string, value: string): ProcessedAppConfig {
357
+ return {
358
+ ...config,
359
+ resolvedAndroidMetadata: {
360
+ ...config.resolvedAndroidMetadata,
361
+ [key]: value,
362
+ },
363
+ };
364
+ }
365
+ }
366
+
367
+ /**
368
+ * Plugin constructor type for registration
369
+ */
370
+ export type PluginConstructor<TConfig = unknown> = new () => BasePlugin<TConfig>;
@@ -0,0 +1,64 @@
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
+ * Biometrics plugin configuration schema
8
+ */
9
+ export const BiometricsPluginConfigSchema = z.object({
10
+ /** iOS Face ID usage description */
11
+ faceIdPermission: z.string().min(1, "Face ID permission description is required"),
12
+
13
+ /** Allow device credential (PIN/password) as fallback */
14
+ allowDeviceCredentialFallback: z.boolean().optional().default(true),
15
+ });
16
+
17
+ export type BiometricsPluginConfig = z.infer<typeof BiometricsPluginConfigSchema>;
18
+
19
+ /**
20
+ * Biometrics capability plugin
21
+ *
22
+ * Configures biometric authentication (Face ID, Touch ID, fingerprint)
23
+ * for iOS and Android.
24
+ */
25
+ export class BiometricsPlugin extends BasePlugin<BiometricsPluginConfig> {
26
+ readonly name = "biometrics";
27
+ readonly version = "1.0.0";
28
+ readonly description = "Configure biometric authentication (Face ID, Touch ID, fingerprint)";
29
+ readonly configSchema = BiometricsPluginConfigSchema;
30
+
31
+ override provides = ["biometrics", "authentication"];
32
+ override platforms: ("ios" | "android")[] = ["ios", "android"];
33
+
34
+ transform(
35
+ config: ProcessedAppConfig,
36
+ pluginConfig: BiometricsPluginConfig,
37
+ context: PluginContext
38
+ ): ProcessedAppConfig {
39
+ const { log } = context;
40
+ log.debug("Applying biometrics configuration...");
41
+
42
+ let result = config;
43
+
44
+ // iOS: Add Face ID usage description
45
+ result = this.addUsageDescription(result, "NSFaceIDUsageDescription", pluginConfig.faceIdPermission);
46
+
47
+ // iOS: Add LocalAuthentication framework
48
+ result = this.addFramework(result, "LocalAuthentication");
49
+
50
+ // Android: Add biometric permission
51
+ result = this.addAndroidPermission(result, "android.permission.USE_BIOMETRIC");
52
+
53
+ // Android: Add fingerprint permission (for older devices)
54
+ result = this.addAndroidPermission(result, "android.permission.USE_FINGERPRINT");
55
+
56
+ // Android: Add biometric feature (optional)
57
+ result = this.addAndroidFeature(result, "android.hardware.fingerprint");
58
+
59
+ // Android: Add androidx.biometric dependency
60
+ result = this.addGradleDependency(result, "androidx.biometric:biometric:1.2.0-alpha05");
61
+
62
+ return result;
63
+ }
64
+ }
@@ -0,0 +1,86 @@
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
+ * Bluetooth plugin configuration schema
8
+ */
9
+ export const BluetoothPluginConfigSchema = z.object({
10
+ /** iOS Bluetooth always-on permission description */
11
+ alwaysPermission: z.string().min(1, "Bluetooth permission description is required"),
12
+
13
+ /** Enable BLE central mode (connecting to devices) */
14
+ centralMode: z.boolean().optional().default(true),
15
+
16
+ /** Enable BLE peripheral mode (advertising) */
17
+ peripheralMode: z.boolean().optional().default(false),
18
+
19
+ /** Enable background Bluetooth */
20
+ backgroundMode: z.boolean().optional().default(false),
21
+ });
22
+
23
+ export type BluetoothPluginConfig = z.infer<typeof BluetoothPluginConfigSchema>;
24
+
25
+ /**
26
+ * Bluetooth capability plugin
27
+ */
28
+ export class BluetoothPlugin extends BasePlugin<BluetoothPluginConfig> {
29
+ readonly name = "bluetooth";
30
+ readonly version = "1.0.0";
31
+ readonly description = "Configure Bluetooth Low Energy (BLE) access";
32
+ readonly configSchema = BluetoothPluginConfigSchema;
33
+
34
+ override provides = ["bluetooth", "ble"];
35
+ override platforms: ("ios" | "android")[] = ["ios", "android"];
36
+
37
+ transform(
38
+ config: ProcessedAppConfig,
39
+ pluginConfig: BluetoothPluginConfig,
40
+ context: PluginContext
41
+ ): ProcessedAppConfig {
42
+ const { log } = context;
43
+ log.debug("Applying Bluetooth configuration...");
44
+
45
+ let result = config;
46
+
47
+ // iOS: Add Bluetooth usage description
48
+ result = this.addUsageDescription(result, "NSBluetoothAlwaysUsageDescription", pluginConfig.alwaysPermission);
49
+
50
+ // iOS: Legacy Bluetooth peripheral description
51
+ result = this.addUsageDescription(result, "NSBluetoothPeripheralUsageDescription", pluginConfig.alwaysPermission);
52
+
53
+ // iOS: Add CoreBluetooth framework
54
+ result = this.addFramework(result, "CoreBluetooth");
55
+
56
+ // iOS: Add background modes
57
+ if (pluginConfig.backgroundMode) {
58
+ if (pluginConfig.centralMode) {
59
+ result = this.addBackgroundMode(result, "bluetooth-central");
60
+ }
61
+ if (pluginConfig.peripheralMode) {
62
+ result = this.addBackgroundMode(result, "bluetooth-peripheral");
63
+ }
64
+ }
65
+
66
+ // Android: Add Bluetooth permissions (API 31+)
67
+ result = this.addAndroidPermission(result, "android.permission.BLUETOOTH_SCAN");
68
+ result = this.addAndroidPermission(result, "android.permission.BLUETOOTH_CONNECT");
69
+
70
+ if (pluginConfig.peripheralMode) {
71
+ result = this.addAndroidPermission(result, "android.permission.BLUETOOTH_ADVERTISE");
72
+ }
73
+
74
+ // Android: Legacy Bluetooth permissions
75
+ result = this.addAndroidPermission(result, "android.permission.BLUETOOTH");
76
+ result = this.addAndroidPermission(result, "android.permission.BLUETOOTH_ADMIN");
77
+
78
+ // Android: Location permission (required for BLE scanning on older versions)
79
+ result = this.addAndroidPermission(result, "android.permission.ACCESS_FINE_LOCATION");
80
+
81
+ // Android: Add Bluetooth LE feature
82
+ result = this.addAndroidFeature(result, "android.hardware.bluetooth_le");
83
+
84
+ return result;
85
+ }
86
+ }
@@ -0,0 +1,57 @@
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
+ * Calendar plugin configuration schema
8
+ */
9
+ export const CalendarPluginConfigSchema = z.object({
10
+ /** iOS calendar usage description */
11
+ permission: z.string().min(1, "Calendar permission description is required"),
12
+
13
+ /** Enable write access to calendar */
14
+ writeAccess: z.boolean().optional().default(false),
15
+ });
16
+
17
+ export type CalendarPluginConfig = z.infer<typeof CalendarPluginConfigSchema>;
18
+
19
+ /**
20
+ * Calendar capability plugin
21
+ */
22
+ export class CalendarPlugin extends BasePlugin<CalendarPluginConfig> {
23
+ readonly name = "calendar";
24
+ readonly version = "1.0.0";
25
+ readonly description = "Configure calendar access for reading and writing events";
26
+ readonly configSchema = CalendarPluginConfigSchema;
27
+
28
+ override provides = ["calendar"];
29
+ override platforms: ("ios" | "android")[] = ["ios", "android"];
30
+
31
+ transform(
32
+ config: ProcessedAppConfig,
33
+ pluginConfig: CalendarPluginConfig,
34
+ context: PluginContext
35
+ ): ProcessedAppConfig {
36
+ const { log } = context;
37
+ log.debug("Applying calendar configuration...");
38
+
39
+ let result = config;
40
+
41
+ // iOS: Add usage description
42
+ result = this.addUsageDescription(result, "NSCalendarsUsageDescription", pluginConfig.permission);
43
+
44
+ // iOS: Add EventKit framework
45
+ result = this.addFramework(result, "EventKit");
46
+
47
+ // Android: Add read permission
48
+ result = this.addAndroidPermission(result, "android.permission.READ_CALENDAR");
49
+
50
+ // Android: Add write permission if needed
51
+ if (pluginConfig.writeAccess) {
52
+ result = this.addAndroidPermission(result, "android.permission.WRITE_CALENDAR");
53
+ }
54
+
55
+ return result;
56
+ }
57
+ }
@@ -0,0 +1,77 @@
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
+ * Camera plugin configuration schema
8
+ */
9
+ export const CameraPluginConfigSchema = z.object({
10
+ /** iOS camera usage description */
11
+ cameraPermission: z.string().min(1, "Camera permission description is required"),
12
+
13
+ /** iOS microphone usage description (for video recording) */
14
+ microphonePermission: z.string().optional(),
15
+
16
+ /** iOS photo library usage description */
17
+ photosPermission: z.string().optional(),
18
+
19
+ /** Enable barcode scanning support */
20
+ enableBarcodeScan: z.boolean().optional().default(false),
21
+ });
22
+
23
+ export type CameraPluginConfig = z.infer<typeof CameraPluginConfigSchema>;
24
+
25
+ /**
26
+ * Camera capability plugin
27
+ *
28
+ * Configures camera access for iOS and Android including
29
+ * permissions, frameworks, and optional barcode scanning.
30
+ */
31
+ export class CameraPlugin extends BasePlugin<CameraPluginConfig> {
32
+ readonly name = "camera";
33
+ readonly version = "1.0.0";
34
+ readonly description = "Configure camera access for capturing photos and videos";
35
+ readonly configSchema = CameraPluginConfigSchema;
36
+
37
+ override provides = ["camera"];
38
+ override platforms: ("ios" | "android")[] = ["ios", "android"];
39
+
40
+ transform(config: ProcessedAppConfig, pluginConfig: CameraPluginConfig, context: PluginContext): ProcessedAppConfig {
41
+ const { log } = context;
42
+ log.debug("Applying camera configuration...");
43
+
44
+ let result = config;
45
+
46
+ // iOS: Add usage descriptions
47
+ result = this.addUsageDescription(result, "NSCameraUsageDescription", pluginConfig.cameraPermission);
48
+
49
+ if (pluginConfig.microphonePermission) {
50
+ result = this.addUsageDescription(result, "NSMicrophoneUsageDescription", pluginConfig.microphonePermission);
51
+ }
52
+
53
+ if (pluginConfig.photosPermission) {
54
+ result = this.addUsageDescription(result, "NSPhotoLibraryUsageDescription", pluginConfig.photosPermission);
55
+ }
56
+
57
+ // iOS: Add frameworks
58
+ result = this.addFramework(result, "AVFoundation");
59
+
60
+ if (pluginConfig.enableBarcodeScan) {
61
+ result = this.addFramework(result, "Vision");
62
+ }
63
+
64
+ // Android: Add permissions
65
+ result = this.addAndroidPermission(result, "android.permission.CAMERA");
66
+
67
+ if (pluginConfig.microphonePermission) {
68
+ result = this.addAndroidPermission(result, "android.permission.RECORD_AUDIO");
69
+ }
70
+
71
+ // Android: Add camera feature
72
+ result = this.addAndroidFeature(result, "android.hardware.camera");
73
+ result = this.addAndroidFeature(result, "android.hardware.camera.autofocus");
74
+
75
+ return result;
76
+ }
77
+ }
@@ -0,0 +1,57 @@
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
+ * Contacts plugin configuration schema
8
+ */
9
+ export const ContactsPluginConfigSchema = z.object({
10
+ /** iOS contacts usage description */
11
+ permission: z.string().min(1, "Contacts permission description is required"),
12
+
13
+ /** Enable write access to contacts */
14
+ writeAccess: z.boolean().optional().default(false),
15
+ });
16
+
17
+ export type ContactsPluginConfig = z.infer<typeof ContactsPluginConfigSchema>;
18
+
19
+ /**
20
+ * Contacts capability plugin
21
+ */
22
+ export class ContactsPlugin extends BasePlugin<ContactsPluginConfig> {
23
+ readonly name = "contacts";
24
+ readonly version = "1.0.0";
25
+ readonly description = "Configure contacts access for reading and writing contacts";
26
+ readonly configSchema = ContactsPluginConfigSchema;
27
+
28
+ override provides = ["contacts"];
29
+ override platforms: ("ios" | "android")[] = ["ios", "android"];
30
+
31
+ transform(
32
+ config: ProcessedAppConfig,
33
+ pluginConfig: ContactsPluginConfig,
34
+ context: PluginContext
35
+ ): ProcessedAppConfig {
36
+ const { log } = context;
37
+ log.debug("Applying contacts configuration...");
38
+
39
+ let result = config;
40
+
41
+ // iOS: Add usage description
42
+ result = this.addUsageDescription(result, "NSContactsUsageDescription", pluginConfig.permission);
43
+
44
+ // iOS: Add Contacts framework
45
+ result = this.addFramework(result, "Contacts");
46
+
47
+ // Android: Add read permission
48
+ result = this.addAndroidPermission(result, "android.permission.READ_CONTACTS");
49
+
50
+ // Android: Add write permission if needed
51
+ if (pluginConfig.writeAccess) {
52
+ result = this.addAndroidPermission(result, "android.permission.WRITE_CONTACTS");
53
+ }
54
+
55
+ return result;
56
+ }
57
+ }