@teardown/dev-client 2.0.44

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 (32) hide show
  1. package/android/build.gradle.kts +34 -0
  2. package/android/react-native.config.js +10 -0
  3. package/android/src/main/AndroidManifest.xml +7 -0
  4. package/android/src/main/java/com/teardown/devclient/DevSettingsModule.kt +130 -0
  5. package/android/src/main/java/com/teardown/devclient/ShakeDetectorModule.kt +118 -0
  6. package/android/src/main/java/com/teardown/devclient/TeardownDevClientPackage.kt +23 -0
  7. package/ios/TeardownDevClient/DevSettingsModule.swift +135 -0
  8. package/ios/TeardownDevClient/ShakeDetector.swift +102 -0
  9. package/ios/TeardownDevClient/TeardownDevClient.h +14 -0
  10. package/ios/TeardownDevClient/TeardownDevClient.mm +42 -0
  11. package/ios/TeardownDevClient.podspec +23 -0
  12. package/package.json +56 -0
  13. package/src/components/dev-menu/dev-menu.tsx +254 -0
  14. package/src/components/dev-menu/index.ts +5 -0
  15. package/src/components/error-overlay/error-overlay.tsx +256 -0
  16. package/src/components/error-overlay/index.ts +5 -0
  17. package/src/components/index.ts +7 -0
  18. package/src/components/splash-screen/index.ts +5 -0
  19. package/src/components/splash-screen/splash-screen.tsx +99 -0
  20. package/src/dev-client-provider.tsx +204 -0
  21. package/src/hooks/index.ts +24 -0
  22. package/src/hooks/use-bundler-status.ts +139 -0
  23. package/src/hooks/use-dev-menu.ts +306 -0
  24. package/src/hooks/use-splash-screen.ts +177 -0
  25. package/src/index.ts +77 -0
  26. package/src/native/dev-settings.ts +132 -0
  27. package/src/native/index.ts +16 -0
  28. package/src/native/shake-detector.ts +105 -0
  29. package/src/types.ts +235 -0
  30. package/src/utils/bundler-url.ts +103 -0
  31. package/src/utils/index.ts +19 -0
  32. package/src/utils/platform.ts +64 -0
package/src/types.ts ADDED
@@ -0,0 +1,235 @@
1
+ /**
2
+ * @teardown/dev-client type definitions
3
+ */
4
+
5
+ import type { ImageSourcePropType } from "react-native";
6
+
7
+ /**
8
+ * Dev client configuration options
9
+ */
10
+ export interface DevClientConfig {
11
+ /** Whether to enable shake gesture for dev menu (default: true) */
12
+ enableShakeGesture?: boolean;
13
+
14
+ /** Whether to enable 3-finger tap for dev menu (default: true) */
15
+ enableThreeFingerTap?: boolean;
16
+
17
+ /** Splash screen configuration */
18
+ splash?: SplashScreenConfig;
19
+
20
+ /** Custom dev menu actions */
21
+ customMenuItems?: DevMenuItem[];
22
+
23
+ /** Metro bundler URL override */
24
+ bundlerUrl?: string;
25
+
26
+ /** Enable verbose logging (default: __DEV__) */
27
+ verbose?: boolean;
28
+ }
29
+
30
+ /**
31
+ * Splash screen configuration
32
+ */
33
+ export interface SplashScreenConfig {
34
+ /** Background color (hex string, default: #ffffff) */
35
+ backgroundColor?: string;
36
+
37
+ /** Logo image source */
38
+ logo?: ImageSourcePropType;
39
+
40
+ /** Resize mode for logo (default: contain) */
41
+ resizeMode?: "contain" | "cover" | "center";
42
+
43
+ /** Minimum display time in ms (default: 500) */
44
+ minDisplayTime?: number;
45
+
46
+ /** Fade out duration in ms (default: 300) */
47
+ fadeOutDuration?: number;
48
+
49
+ /** Auto-hide when app is ready (default: true) */
50
+ autoHide?: boolean;
51
+ }
52
+
53
+ /**
54
+ * Dev menu item configuration
55
+ */
56
+ export interface DevMenuItem {
57
+ /** Unique identifier for the menu item */
58
+ id: string;
59
+
60
+ /** Display label */
61
+ label: string;
62
+
63
+ /** Optional icon name */
64
+ icon?: string;
65
+
66
+ /** Action handler */
67
+ onPress: () => void | Promise<void>;
68
+
69
+ /** Show only in development (default: true) */
70
+ devOnly?: boolean;
71
+ }
72
+
73
+ /**
74
+ * Bundler connection status
75
+ */
76
+ export interface BundlerStatus {
77
+ /** Whether connected to Metro bundler */
78
+ connected: boolean;
79
+
80
+ /** Current bundler URL */
81
+ url: string | null;
82
+
83
+ /** Error message if connection failed */
84
+ error: string | null;
85
+
86
+ /** Last successful connection timestamp */
87
+ lastConnectedAt: Date | null;
88
+ }
89
+
90
+ /**
91
+ * Dev menu state
92
+ */
93
+ export interface DevMenuState {
94
+ /** Whether dev menu is visible */
95
+ isVisible: boolean;
96
+
97
+ /** Whether an action is in progress */
98
+ isLoading: boolean;
99
+
100
+ /** Current bundler status */
101
+ bundlerStatus: BundlerStatus;
102
+
103
+ /** Whether hot reloading is enabled */
104
+ hotReloadEnabled: boolean;
105
+
106
+ /** Whether fast refresh is enabled */
107
+ fastRefreshEnabled: boolean;
108
+ }
109
+
110
+ /**
111
+ * Dev menu actions
112
+ */
113
+ export interface DevMenuActions {
114
+ /** Show the dev menu */
115
+ show: () => void;
116
+
117
+ /** Hide the dev menu */
118
+ hide: () => void;
119
+
120
+ /** Toggle dev menu visibility */
121
+ toggle: () => void;
122
+
123
+ /** Reload the app */
124
+ reload: () => Promise<void>;
125
+
126
+ /** Open debugger */
127
+ openDebugger: () => Promise<void>;
128
+
129
+ /** Toggle element inspector */
130
+ toggleElementInspector: () => Promise<void>;
131
+
132
+ /** Toggle performance monitor */
133
+ togglePerfMonitor: () => Promise<void>;
134
+
135
+ /** Set hot reload enabled state */
136
+ setHotReloadEnabled: (enabled: boolean) => Promise<void>;
137
+ }
138
+
139
+ /**
140
+ * Native module interface for dev settings
141
+ */
142
+ export interface DevSettingsNativeModule {
143
+ /** Reload the JavaScript bundle */
144
+ reload(): void;
145
+
146
+ /** Open the debugger */
147
+ openDebugger(): void;
148
+
149
+ /** Toggle element inspector overlay */
150
+ toggleElementInspector(): void;
151
+
152
+ /** Set hot loading enabled state */
153
+ setHotLoadingEnabled(enabled: boolean): void;
154
+
155
+ /** Set fast refresh enabled state */
156
+ setFastRefreshEnabled(enabled: boolean): void;
157
+
158
+ /** Get current dev settings */
159
+ getDevSettings(): Promise<DevSettings>;
160
+
161
+ /** Open native dev menu */
162
+ openDevMenu(): void;
163
+ }
164
+
165
+ /**
166
+ * Current dev settings state from native
167
+ */
168
+ export interface DevSettings {
169
+ /** Whether remote JS debugging is enabled */
170
+ isDebuggingRemotely: boolean;
171
+
172
+ /** Whether element inspector is shown */
173
+ isElementInspectorShown: boolean;
174
+
175
+ /** Whether hot loading is enabled */
176
+ isHotLoadingEnabled: boolean;
177
+
178
+ /** Whether fast refresh is enabled */
179
+ isFastRefreshEnabled: boolean;
180
+
181
+ /** Whether performance monitor is shown */
182
+ isPerfMonitorShown: boolean;
183
+ }
184
+
185
+ /**
186
+ * Splash screen control API
187
+ */
188
+ export interface SplashScreenApi {
189
+ /** Hide the splash screen */
190
+ hide: (options?: { fade?: boolean }) => Promise<void>;
191
+
192
+ /** Show the splash screen (for manual control) */
193
+ show: () => Promise<void>;
194
+
195
+ /** Whether splash screen is currently visible */
196
+ isVisible: boolean;
197
+ }
198
+
199
+ /**
200
+ * Dev client context value
201
+ */
202
+ export interface DevClientContextValue {
203
+ /** Current configuration */
204
+ config: DevClientConfig;
205
+
206
+ /** Dev menu state and actions */
207
+ devMenu: {
208
+ state: DevMenuState;
209
+ actions: DevMenuActions;
210
+ defaultItems: DevMenuItem[];
211
+ };
212
+
213
+ /** Splash screen API */
214
+ splashScreen: SplashScreenApi;
215
+
216
+ /** Bundler status */
217
+ bundlerStatus: BundlerStatus;
218
+ }
219
+
220
+ /**
221
+ * Options for getting bundler URL
222
+ */
223
+ export interface GetBundlerUrlOptions {
224
+ /** Target platform */
225
+ platform: "ios" | "android";
226
+
227
+ /** Whether running on emulator/simulator */
228
+ isEmulator: boolean;
229
+
230
+ /** Custom port (default: 8081) */
231
+ port?: number;
232
+
233
+ /** URL override */
234
+ override?: string;
235
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Bundler URL utilities
3
+ *
4
+ * Provides helpers for determining and validating Metro bundler URLs
5
+ * based on platform and environment.
6
+ */
7
+
8
+ import type { GetBundlerUrlOptions } from "../types";
9
+
10
+ /** Default Metro bundler port */
11
+ export const DEFAULT_BUNDLER_PORT = 8081;
12
+
13
+ /** Android emulator host - special IP that routes to host machine */
14
+ const ANDROID_EMULATOR_HOST = "10.0.2.2";
15
+
16
+ /** Default host for iOS and physical devices */
17
+ const DEFAULT_HOST = "localhost";
18
+
19
+ /**
20
+ * Get the default bundler URL based on platform and environment
21
+ *
22
+ * @param platform - Target platform (ios or android)
23
+ * @param isEmulator - Whether running on emulator/simulator
24
+ * @param port - Custom port (defaults to 8081)
25
+ * @returns The bundler URL string
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * getDefaultBundlerUrl('ios', true); // http://localhost:8081
30
+ * getDefaultBundlerUrl('android', true); // http://10.0.2.2:8081
31
+ * getDefaultBundlerUrl('android', true, 9000); // http://10.0.2.2:9000
32
+ * ```
33
+ */
34
+ export function getDefaultBundlerUrl(
35
+ platform: "ios" | "android",
36
+ isEmulator: boolean,
37
+ port: number = DEFAULT_BUNDLER_PORT
38
+ ): string {
39
+ // Android emulator needs special host to reach the host machine
40
+ const host = platform === "android" && isEmulator ? ANDROID_EMULATOR_HOST : DEFAULT_HOST;
41
+
42
+ return `http://${host}:${port}`;
43
+ }
44
+
45
+ /**
46
+ * Validate a bundler URL
47
+ *
48
+ * @param url - URL string to validate
49
+ * @returns true if the URL is valid for bundler connection
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * isValidBundlerUrl('http://localhost:8081'); // true
54
+ * isValidBundlerUrl('https://bundler.example.com'); // true
55
+ * isValidBundlerUrl('not-a-url'); // false
56
+ * ```
57
+ */
58
+ export function isValidBundlerUrl(url: string): boolean {
59
+ if (!url || url.trim() === "") {
60
+ return false;
61
+ }
62
+
63
+ try {
64
+ const parsed = new URL(url);
65
+ // Only allow http and https protocols
66
+ return parsed.protocol === "http:" || parsed.protocol === "https:";
67
+ } catch {
68
+ return false;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Get the bundler URL based on options
74
+ *
75
+ * Respects override URL if provided and valid, otherwise
76
+ * returns the appropriate default URL for the platform.
77
+ *
78
+ * @param options - Configuration options
79
+ * @returns The bundler URL string
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * getBundlerUrl({ platform: 'ios', isEmulator: true });
84
+ * // Returns: http://localhost:8081
85
+ *
86
+ * getBundlerUrl({ platform: 'android', isEmulator: true, port: 9000 });
87
+ * // Returns: http://10.0.2.2:9000
88
+ *
89
+ * getBundlerUrl({ platform: 'ios', isEmulator: true, override: 'http://custom:8080' });
90
+ * // Returns: http://custom:8080
91
+ * ```
92
+ */
93
+ export function getBundlerUrl(options: GetBundlerUrlOptions): string {
94
+ const { platform, isEmulator, port = DEFAULT_BUNDLER_PORT, override } = options;
95
+
96
+ // Use override if provided and valid
97
+ if (override && isValidBundlerUrl(override)) {
98
+ return override;
99
+ }
100
+
101
+ // Return default URL for platform
102
+ return getDefaultBundlerUrl(platform, isEmulator, port);
103
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Utility exports
3
+ */
4
+
5
+ export {
6
+ DEFAULT_BUNDLER_PORT,
7
+ getBundlerUrl,
8
+ getDefaultBundlerUrl,
9
+ isValidBundlerUrl,
10
+ } from "./bundler-url";
11
+
12
+ export {
13
+ currentPlatform,
14
+ isAndroid,
15
+ isDev,
16
+ isEmulator,
17
+ isIOS,
18
+ platformSelect,
19
+ } from "./platform";
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Platform detection utilities
3
+ */
4
+
5
+ import { Platform } from "react-native";
6
+
7
+ /**
8
+ * Current platform
9
+ */
10
+ export const currentPlatform = Platform.OS as "ios" | "android";
11
+
12
+ /**
13
+ * Whether running on iOS
14
+ */
15
+ export const isIOS = Platform.OS === "ios";
16
+
17
+ /**
18
+ * Whether running on Android
19
+ */
20
+ export const isAndroid = Platform.OS === "android";
21
+
22
+ /**
23
+ * Whether running in development mode
24
+ * Safe when __DEV__ is not defined (e.g. in test runners).
25
+ */
26
+ export const isDev =
27
+ typeof globalThis !== "undefined" && "__DEV__" in globalThis
28
+ ? (globalThis as typeof globalThis & { __DEV__: boolean }).__DEV__
29
+ : false;
30
+
31
+ /**
32
+ * Detect if running on an emulator/simulator
33
+ *
34
+ * Note: This is a heuristic and may not be 100% accurate.
35
+ * For iOS, simulators have specific device names.
36
+ * For Android, emulators typically have specific fingerprints.
37
+ *
38
+ * @returns Promise resolving to true if likely on emulator
39
+ */
40
+ export async function isEmulator(): Promise<boolean> {
41
+ // In development, we generally assume emulator for simplicity
42
+ // A more robust implementation would check device info
43
+ if (__DEV__) {
44
+ return true;
45
+ }
46
+
47
+ // In production, assume physical device
48
+ return false;
49
+ }
50
+
51
+ /**
52
+ * Get platform-specific value
53
+ *
54
+ * @param options - Object with ios and android values
55
+ * @returns The value for the current platform
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * const color = platformSelect({ ios: 'blue', android: 'green' });
60
+ * ```
61
+ */
62
+ export function platformSelect<T>(options: { ios: T; android: T }): T {
63
+ return Platform.select(options) as T;
64
+ }