@teardown/cli 1.2.38 → 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.
- package/bin/teardown.js +11 -1
- package/package.json +77 -57
- package/src/cli/commands/init.ts +254 -0
- package/src/cli/commands/plugins.ts +93 -0
- package/src/cli/commands/prebuild.ts +168 -0
- package/src/cli/commands/run.ts +727 -0
- package/src/cli/commands/start.ts +87 -0
- package/src/cli/commands/validate.ts +62 -0
- package/src/cli/index.ts +59 -0
- package/src/config/index.ts +45 -0
- package/src/config/loader.ts +366 -0
- package/src/config/schema.ts +235 -0
- package/src/config/types.ts +322 -0
- package/src/index.ts +177 -0
- package/src/pipeline/cache.ts +179 -0
- package/src/pipeline/index.ts +10 -0
- package/src/pipeline/stages.ts +692 -0
- package/src/plugins/base.ts +370 -0
- package/src/plugins/capabilities/biometrics.ts +64 -0
- package/src/plugins/capabilities/bluetooth.ts +86 -0
- package/src/plugins/capabilities/calendar.ts +57 -0
- package/src/plugins/capabilities/camera.ts +77 -0
- package/src/plugins/capabilities/contacts.ts +57 -0
- package/src/plugins/capabilities/deep-linking.ts +124 -0
- package/src/plugins/capabilities/firebase.ts +138 -0
- package/src/plugins/capabilities/index.ts +96 -0
- package/src/plugins/capabilities/location.ts +87 -0
- package/src/plugins/capabilities/photo-library.ts +80 -0
- package/src/plugins/capabilities/push-notifications.ts +98 -0
- package/src/plugins/capabilities/sign-in-with-apple.ts +53 -0
- package/src/plugins/context.ts +220 -0
- package/src/plugins/index.ts +26 -0
- package/src/plugins/resolver.ts +321 -0
- package/src/templates/generator.ts +507 -0
- package/src/templates/index.ts +9 -0
- package/src/templates/paths.ts +25 -0
- package/src/transformers/android/gradle.ts +400 -0
- package/src/transformers/android/index.ts +19 -0
- package/src/transformers/android/manifest.ts +506 -0
- package/src/transformers/index.ts +39 -0
- package/src/transformers/ios/entitlements.ts +283 -0
- package/src/transformers/ios/index.ts +10 -0
- package/src/transformers/ios/pbxproj.ts +267 -0
- package/src/transformers/ios/plist.ts +198 -0
- package/src/utils/fs.ts +429 -0
- package/src/utils/index.ts +21 -0
- package/src/utils/logger.ts +203 -0
- package/templates/.gitignore +63 -0
- package/templates/Gemfile +3 -0
- package/templates/android/app/build.gradle.kts +97 -0
- package/templates/android/app/proguard-rules.pro +10 -0
- package/templates/android/app/src/main/AndroidManifest.xml +26 -0
- package/templates/android/app/src/main/java/com/appname/MainActivity.kt +22 -0
- package/templates/android/app/src/main/java/com/appname/MainApplication.kt +44 -0
- package/templates/android/app/src/main/res/values/strings.xml +3 -0
- package/templates/android/app/src/main/res/values/styles.xml +7 -0
- package/templates/android/build.gradle.kts +44 -0
- package/templates/android/gradle.properties +39 -0
- package/templates/android/settings.gradle.kts +12 -0
- package/templates/babel.config.js +15 -0
- package/templates/index.js +7 -0
- package/templates/ios/.xcode.env +11 -0
- package/templates/ios/AppName/AppDelegate.swift +25 -0
- package/templates/ios/AppName/AppName-Bridging-Header.h +4 -0
- package/templates/ios/AppName/AppName.entitlements +6 -0
- package/templates/ios/AppName/Images.xcassets/AppIcon.appiconset/Contents.json +35 -0
- package/templates/ios/AppName/Images.xcassets/Contents.json +6 -0
- package/templates/ios/AppName/Info.plist +49 -0
- package/templates/ios/AppName/LaunchScreen.storyboard +38 -0
- package/templates/ios/AppName.xcodeproj/project.pbxproj +402 -0
- package/templates/ios/AppName.xcodeproj/xcshareddata/xcschemes/AppName.xcscheme +78 -0
- package/templates/ios/Podfile +35 -0
- package/templates/metro.config.js +41 -0
- package/templates/package.json +57 -0
- package/templates/react-native.config.js +8 -0
- package/templates/src/app/index.tsx +34 -0
- package/templates/src/assets/fonts/.gitkeep +1 -0
- package/templates/src/assets/images/.gitkeep +1 -0
- package/templates/src/components/ui/accordion.tsx +114 -0
- package/templates/src/components/ui/avatar.tsx +75 -0
- package/templates/src/components/ui/button.tsx +93 -0
- package/templates/src/components/ui/card.tsx +120 -0
- package/templates/src/components/ui/checkbox.tsx +133 -0
- package/templates/src/components/ui/chip.tsx +95 -0
- package/templates/src/components/ui/dialog.tsx +134 -0
- package/templates/src/components/ui/divider.tsx +67 -0
- package/templates/src/components/ui/error-view.tsx +82 -0
- package/templates/src/components/ui/form-field.tsx +101 -0
- package/templates/src/components/ui/index.ts +100 -0
- package/templates/src/components/ui/popover.tsx +92 -0
- package/templates/src/components/ui/pressable-feedback.tsx +88 -0
- package/templates/src/components/ui/radio-group.tsx +153 -0
- package/templates/src/components/ui/scroll-shadow.tsx +108 -0
- package/templates/src/components/ui/select.tsx +165 -0
- package/templates/src/components/ui/skeleton-group.tsx +97 -0
- package/templates/src/components/ui/skeleton.tsx +87 -0
- package/templates/src/components/ui/spinner.tsx +87 -0
- package/templates/src/components/ui/surface.tsx +95 -0
- package/templates/src/components/ui/switch.tsx +124 -0
- package/templates/src/components/ui/tabs.tsx +154 -0
- package/templates/src/components/ui/text-field.tsx +106 -0
- package/templates/src/components/ui/toast.tsx +129 -0
- package/templates/src/contexts/.gitkeep +2 -0
- package/templates/src/core/clients/api/api.client.ts +113 -0
- package/templates/src/core/clients/api/index.ts +1 -0
- package/templates/src/core/clients/storage/index.ts +1 -0
- package/templates/src/core/clients/storage/storage.client.ts +121 -0
- package/templates/src/core/constants/index.ts +19 -0
- package/templates/src/core/core.ts +40 -0
- package/templates/src/core/index.ts +10 -0
- package/templates/src/global.css +87 -0
- package/templates/src/hooks/index.ts +6 -0
- package/templates/src/hooks/use-debounce.ts +23 -0
- package/templates/src/hooks/use-mounted.ts +21 -0
- package/templates/src/index.ts +28 -0
- package/templates/src/lib/index.ts +5 -0
- package/templates/src/lib/utils.ts +115 -0
- package/templates/src/modules/.gitkeep +6 -0
- package/templates/src/navigation/index.ts +8 -0
- package/templates/src/navigation/navigation-provider.tsx +36 -0
- package/templates/src/navigation/router.tsx +137 -0
- package/templates/src/providers/app.provider.tsx +29 -0
- package/templates/src/providers/index.ts +5 -0
- package/templates/src/routes/(tabs)/_layout.tsx +42 -0
- package/templates/src/routes/(tabs)/explore.tsx +161 -0
- package/templates/src/routes/(tabs)/home.tsx +138 -0
- package/templates/src/routes/(tabs)/profile.tsx +151 -0
- package/templates/src/routes/_layout.tsx +18 -0
- package/templates/src/routes/settings.tsx +194 -0
- package/templates/src/screens/auth/index.ts +6 -0
- package/templates/src/screens/auth/login.tsx +165 -0
- package/templates/src/screens/auth/register.tsx +203 -0
- package/templates/src/screens/home.tsx +204 -0
- package/templates/src/screens/index.ts +17 -0
- package/templates/src/screens/profile.tsx +210 -0
- package/templates/src/screens/settings.tsx +216 -0
- package/templates/src/screens/welcome.tsx +101 -0
- package/templates/src/styles/index.ts +103 -0
- package/templates/src/types/common.ts +71 -0
- package/templates/src/types/index.ts +5 -0
- package/templates/tsconfig.json +14 -0
- package/README.md +0 -15
- package/assets/favicon.ico +0 -0
- package/dist/commands/dev/dev.js +0 -55
- package/dist/commands/init/init-teardown.js +0 -26
- package/dist/index.js +0 -20
- package/dist/modules/dev/dev-menu/keyboard-handler.js +0 -138
- package/dist/modules/dev/dev-menu/open-debugger-keyboard-handler.js +0 -105
- package/dist/modules/dev/dev-server/cdp/cdp.adapter.js +0 -12
- package/dist/modules/dev/dev-server/cdp/index.js +0 -18
- package/dist/modules/dev/dev-server/cdp/types.js +0 -2
- package/dist/modules/dev/dev-server/dev-server-checker.js +0 -72
- package/dist/modules/dev/dev-server/dev-server.js +0 -269
- package/dist/modules/dev/dev-server/inspector/device.event-reporter.js +0 -165
- package/dist/modules/dev/dev-server/inspector/device.js +0 -577
- package/dist/modules/dev/dev-server/inspector/inspector.js +0 -204
- package/dist/modules/dev/dev-server/inspector/types.js +0 -2
- package/dist/modules/dev/dev-server/inspector/wss/servers/debugger-connection.server.js +0 -61
- package/dist/modules/dev/dev-server/inspector/wss/servers/device-connection.server.js +0 -64
- package/dist/modules/dev/dev-server/plugins/devtools.plugin.js +0 -50
- package/dist/modules/dev/dev-server/plugins/favicon.plugin.js +0 -19
- package/dist/modules/dev/dev-server/plugins/multipart.plugin.js +0 -62
- package/dist/modules/dev/dev-server/plugins/systrace.plugin.js +0 -28
- package/dist/modules/dev/dev-server/plugins/types.js +0 -2
- package/dist/modules/dev/dev-server/plugins/wss/index.js +0 -19
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-api.server.js +0 -66
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-debugger.server.js +0 -128
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-dev-client.server.js +0 -75
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-events.server.js +0 -198
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-hmr.server.js +0 -120
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-message.server.js +0 -357
- package/dist/modules/dev/dev-server/plugins/wss/types.js +0 -2
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-router.js +0 -57
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-server-adapter.js +0 -26
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-server.js +0 -46
- package/dist/modules/dev/dev-server/plugins/wss/wss.plugin.js +0 -55
- package/dist/modules/dev/dev-server/sybmolicate/sybmolicate.plugin.js +0 -36
- package/dist/modules/dev/dev-server/sybmolicate/types.js +0 -2
- package/dist/modules/dev/terminal/base.terminal.reporter.js +0 -78
- package/dist/modules/dev/terminal/terminal.reporter.js +0 -76
- package/dist/modules/dev/types.js +0 -2
- package/dist/modules/dev/utils/log.js +0 -73
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Client
|
|
3
|
+
*
|
|
4
|
+
* HTTP client for making API requests.
|
|
5
|
+
* Handles authentication, error handling, and request/response transformation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ApiResponse, RequestConfig } from "@/types";
|
|
9
|
+
|
|
10
|
+
export class ApiClient {
|
|
11
|
+
private baseUrl: string;
|
|
12
|
+
private headers: Record<string, string>;
|
|
13
|
+
|
|
14
|
+
constructor(baseUrl = "") {
|
|
15
|
+
this.baseUrl = baseUrl;
|
|
16
|
+
this.headers = {
|
|
17
|
+
"Content-Type": "application/json",
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Set the base URL for all requests
|
|
23
|
+
*/
|
|
24
|
+
setBaseUrl(url: string): void {
|
|
25
|
+
this.baseUrl = url;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Set an authorization token
|
|
30
|
+
*/
|
|
31
|
+
setAuthToken(token: string): void {
|
|
32
|
+
this.headers["Authorization"] = `Bearer ${token}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Clear the authorization token
|
|
37
|
+
*/
|
|
38
|
+
clearAuthToken(): void {
|
|
39
|
+
delete this.headers["Authorization"];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Make a GET request
|
|
44
|
+
*/
|
|
45
|
+
async get<T>(endpoint: string, config?: RequestConfig): Promise<ApiResponse<T>> {
|
|
46
|
+
return this.request<T>("GET", endpoint, undefined, config);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Make a POST request
|
|
51
|
+
*/
|
|
52
|
+
async post<T>(endpoint: string, body?: unknown, config?: RequestConfig): Promise<ApiResponse<T>> {
|
|
53
|
+
return this.request<T>("POST", endpoint, body, config);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Make a PUT request
|
|
58
|
+
*/
|
|
59
|
+
async put<T>(endpoint: string, body?: unknown, config?: RequestConfig): Promise<ApiResponse<T>> {
|
|
60
|
+
return this.request<T>("PUT", endpoint, body, config);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Make a DELETE request
|
|
65
|
+
*/
|
|
66
|
+
async delete<T>(endpoint: string, config?: RequestConfig): Promise<ApiResponse<T>> {
|
|
67
|
+
return this.request<T>("DELETE", endpoint, undefined, config);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Internal request handler
|
|
72
|
+
*/
|
|
73
|
+
private async request<T>(
|
|
74
|
+
method: string,
|
|
75
|
+
endpoint: string,
|
|
76
|
+
body?: unknown,
|
|
77
|
+
config?: RequestConfig,
|
|
78
|
+
): Promise<ApiResponse<T>> {
|
|
79
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
80
|
+
const headers = { ...this.headers, ...config?.headers };
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
const response = await fetch(url, {
|
|
84
|
+
method,
|
|
85
|
+
headers,
|
|
86
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
87
|
+
signal: config?.signal,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const data = await response.json();
|
|
91
|
+
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
return {
|
|
94
|
+
success: false,
|
|
95
|
+
error: data.message || "Request failed",
|
|
96
|
+
status: response.status,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
success: true,
|
|
102
|
+
data,
|
|
103
|
+
status: response.status,
|
|
104
|
+
};
|
|
105
|
+
} catch (error) {
|
|
106
|
+
return {
|
|
107
|
+
success: false,
|
|
108
|
+
error: error instanceof Error ? error.message : "Network error",
|
|
109
|
+
status: 0,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ApiClient } from "./api.client";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StorageClient, createStorage } from "./storage.client";
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Client
|
|
3
|
+
*
|
|
4
|
+
* Abstraction over MMKV for fast local data persistence.
|
|
5
|
+
* MMKV is ~30x faster than AsyncStorage and fully synchronous.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { MMKV } from "react-native-mmkv";
|
|
9
|
+
|
|
10
|
+
export class StorageClient {
|
|
11
|
+
private storage: MMKV;
|
|
12
|
+
|
|
13
|
+
constructor(id = "app-storage") {
|
|
14
|
+
this.storage = new MMKV({ id });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get a string value
|
|
19
|
+
*/
|
|
20
|
+
getString(key: string): string | undefined {
|
|
21
|
+
return this.storage.getString(key);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get a number value
|
|
26
|
+
*/
|
|
27
|
+
getNumber(key: string): number | undefined {
|
|
28
|
+
return this.storage.getNumber(key);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get a boolean value
|
|
33
|
+
*/
|
|
34
|
+
getBoolean(key: string): boolean | undefined {
|
|
35
|
+
return this.storage.getBoolean(key);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get a JSON value (parsed)
|
|
40
|
+
*/
|
|
41
|
+
getObject<T>(key: string): T | null {
|
|
42
|
+
const value = this.storage.getString(key);
|
|
43
|
+
if (!value) return null;
|
|
44
|
+
try {
|
|
45
|
+
return JSON.parse(value) as T;
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Set a string value
|
|
53
|
+
*/
|
|
54
|
+
setString(key: string, value: string): void {
|
|
55
|
+
this.storage.set(key, value);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Set a number value
|
|
60
|
+
*/
|
|
61
|
+
setNumber(key: string, value: number): void {
|
|
62
|
+
this.storage.set(key, value);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Set a boolean value
|
|
67
|
+
*/
|
|
68
|
+
setBoolean(key: string, value: boolean): void {
|
|
69
|
+
this.storage.set(key, value);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Set a JSON value (stringified)
|
|
74
|
+
*/
|
|
75
|
+
setObject<T>(key: string, value: T): void {
|
|
76
|
+
this.storage.set(key, JSON.stringify(value));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Check if a key exists
|
|
81
|
+
*/
|
|
82
|
+
contains(key: string): boolean {
|
|
83
|
+
return this.storage.contains(key);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Remove a value
|
|
88
|
+
*/
|
|
89
|
+
remove(key: string): void {
|
|
90
|
+
this.storage.delete(key);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get all keys
|
|
95
|
+
*/
|
|
96
|
+
getAllKeys(): string[] {
|
|
97
|
+
return this.storage.getAllKeys();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Clear all stored data
|
|
102
|
+
*/
|
|
103
|
+
clear(): void {
|
|
104
|
+
this.storage.clearAll();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get the underlying MMKV instance for advanced usage
|
|
109
|
+
*/
|
|
110
|
+
getInstance(): MMKV {
|
|
111
|
+
return this.storage;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Create a new storage instance with a specific ID
|
|
117
|
+
* Useful for isolating different data domains
|
|
118
|
+
*/
|
|
119
|
+
export function createStorage(id: string): StorageClient {
|
|
120
|
+
return new StorageClient(id);
|
|
121
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App Constants
|
|
3
|
+
*
|
|
4
|
+
* Define global constants here.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const APP_NAME = "<%= appName %>";
|
|
8
|
+
export const APP_VERSION = "<%= version %>";
|
|
9
|
+
|
|
10
|
+
// API Configuration
|
|
11
|
+
export const API_BASE_URL = "";
|
|
12
|
+
export const API_TIMEOUT = 30000;
|
|
13
|
+
|
|
14
|
+
// Storage Keys
|
|
15
|
+
export const STORAGE_KEYS = {
|
|
16
|
+
AUTH_TOKEN: "auth_token",
|
|
17
|
+
USER_PREFERENCES: "user_preferences",
|
|
18
|
+
ONBOARDING_COMPLETE: "onboarding_complete",
|
|
19
|
+
} as const;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Application Services
|
|
3
|
+
*
|
|
4
|
+
* Singleton class that instantiates and provides access to all core services.
|
|
5
|
+
* Add your API clients, storage, auth, and other service clients here.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { StorageClient } from "./clients/storage";
|
|
9
|
+
import { ApiClient } from "./clients/api";
|
|
10
|
+
|
|
11
|
+
class AppCore {
|
|
12
|
+
public readonly storage: StorageClient;
|
|
13
|
+
public readonly api: ApiClient;
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
// Initialize clients in dependency order
|
|
17
|
+
this.storage = new StorageClient();
|
|
18
|
+
this.api = new ApiClient();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Initialize async services
|
|
23
|
+
* Call this during app startup
|
|
24
|
+
*/
|
|
25
|
+
async initialize(): Promise<void> {
|
|
26
|
+
// Add initialization logic here
|
|
27
|
+
// e.g., load cached data, restore auth state
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Cleanup resources
|
|
32
|
+
* Call this on app termination
|
|
33
|
+
*/
|
|
34
|
+
async cleanup(): Promise<void> {
|
|
35
|
+
// Add cleanup logic here
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Export singleton instance
|
|
40
|
+
export const core = new AppCore();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Module Exports
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all core services and utilities.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { core } from "./core";
|
|
8
|
+
export { StorageClient, createStorage } from "./clients/storage";
|
|
9
|
+
export { ApiClient } from "./clients/api";
|
|
10
|
+
export * from "./constants";
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global CSS for Uniwind
|
|
3
|
+
*
|
|
4
|
+
* This file imports Tailwind CSS 4 and Uniwind for React Native styling.
|
|
5
|
+
* The location of this file determines the app root for Tailwind scanning.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
@import "tailwindcss";
|
|
9
|
+
@import "uniwind";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Custom CSS Variables (Design Tokens)
|
|
13
|
+
* Customize these to match your brand.
|
|
14
|
+
*/
|
|
15
|
+
:root {
|
|
16
|
+
/* Primary Colors */
|
|
17
|
+
--color-primary: #3b82f6;
|
|
18
|
+
--color-primary-foreground: #ffffff;
|
|
19
|
+
|
|
20
|
+
/* Secondary Colors */
|
|
21
|
+
--color-secondary: #64748b;
|
|
22
|
+
--color-secondary-foreground: #ffffff;
|
|
23
|
+
|
|
24
|
+
/* Accent Colors */
|
|
25
|
+
--color-accent: #8b5cf6;
|
|
26
|
+
--color-accent-foreground: #ffffff;
|
|
27
|
+
|
|
28
|
+
/* Destructive Colors */
|
|
29
|
+
--color-destructive: #ef4444;
|
|
30
|
+
--color-destructive-foreground: #ffffff;
|
|
31
|
+
|
|
32
|
+
/* Background Colors */
|
|
33
|
+
--color-background: #ffffff;
|
|
34
|
+
--color-foreground: #0f172a;
|
|
35
|
+
|
|
36
|
+
/* Muted Colors */
|
|
37
|
+
--color-muted: #f1f5f9;
|
|
38
|
+
--color-muted-foreground: #64748b;
|
|
39
|
+
|
|
40
|
+
/* Card Colors */
|
|
41
|
+
--color-card: #ffffff;
|
|
42
|
+
--color-card-foreground: #0f172a;
|
|
43
|
+
|
|
44
|
+
/* Border Colors */
|
|
45
|
+
--color-border: #e2e8f0;
|
|
46
|
+
|
|
47
|
+
/* Input Colors */
|
|
48
|
+
--color-input: #e2e8f0;
|
|
49
|
+
--color-ring: #3b82f6;
|
|
50
|
+
|
|
51
|
+
/* Spacing */
|
|
52
|
+
--radius-sm: 0.375rem;
|
|
53
|
+
--radius-md: 0.5rem;
|
|
54
|
+
--radius-lg: 0.75rem;
|
|
55
|
+
--radius-xl: 1rem;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Dark mode support
|
|
60
|
+
*/
|
|
61
|
+
.dark {
|
|
62
|
+
--color-primary: #60a5fa;
|
|
63
|
+
--color-primary-foreground: #0f172a;
|
|
64
|
+
|
|
65
|
+
--color-secondary: #94a3b8;
|
|
66
|
+
--color-secondary-foreground: #0f172a;
|
|
67
|
+
|
|
68
|
+
--color-accent: #a78bfa;
|
|
69
|
+
--color-accent-foreground: #0f172a;
|
|
70
|
+
|
|
71
|
+
--color-destructive: #f87171;
|
|
72
|
+
--color-destructive-foreground: #0f172a;
|
|
73
|
+
|
|
74
|
+
--color-background: #0f172a;
|
|
75
|
+
--color-foreground: #f8fafc;
|
|
76
|
+
|
|
77
|
+
--color-muted: #1e293b;
|
|
78
|
+
--color-muted-foreground: #94a3b8;
|
|
79
|
+
|
|
80
|
+
--color-card: #1e293b;
|
|
81
|
+
--color-card-foreground: #f8fafc;
|
|
82
|
+
|
|
83
|
+
--color-border: #334155;
|
|
84
|
+
|
|
85
|
+
--color-input: #334155;
|
|
86
|
+
--color-ring: #60a5fa;
|
|
87
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useDebounce Hook
|
|
3
|
+
*
|
|
4
|
+
* Debounces a value by the specified delay.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useState, useEffect } from "react";
|
|
8
|
+
|
|
9
|
+
export function useDebounce<T>(value: T, delay: number): T {
|
|
10
|
+
const [debouncedValue, setDebouncedValue] = useState<T>(value);
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const timer = setTimeout(() => {
|
|
14
|
+
setDebouncedValue(value);
|
|
15
|
+
}, delay);
|
|
16
|
+
|
|
17
|
+
return () => {
|
|
18
|
+
clearTimeout(timer);
|
|
19
|
+
};
|
|
20
|
+
}, [value, delay]);
|
|
21
|
+
|
|
22
|
+
return debouncedValue;
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useMounted Hook
|
|
3
|
+
*
|
|
4
|
+
* Returns true if the component is mounted.
|
|
5
|
+
* Useful for avoiding state updates on unmounted components.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useEffect, useRef } from "react";
|
|
9
|
+
|
|
10
|
+
export function useMounted(): boolean {
|
|
11
|
+
const mounted = useRef(false);
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
mounted.current = true;
|
|
15
|
+
return () => {
|
|
16
|
+
mounted.current = false;
|
|
17
|
+
};
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
return mounted.current;
|
|
21
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App Entry Point
|
|
3
|
+
*
|
|
4
|
+
* This file registers the root component with React Native's AppRegistry.
|
|
5
|
+
* The app is wrapped with DevClientProvider for development tools.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { AppRegistry } from "react-native";
|
|
9
|
+
import { DevClientProvider } from "@teardown/dev-client";
|
|
10
|
+
import { devClientConfig } from "../../dev-client.config";
|
|
11
|
+
import { App } from "./app";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Root component with development client wrapper
|
|
15
|
+
*/
|
|
16
|
+
function Root() {
|
|
17
|
+
return (
|
|
18
|
+
<DevClientProvider config={devClientConfig}>
|
|
19
|
+
<App />
|
|
20
|
+
</DevClientProvider>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
AppRegistry.registerComponent("<%= appName %>", () => Root);
|
|
25
|
+
|
|
26
|
+
// Export core modules for external use
|
|
27
|
+
export * from "./core";
|
|
28
|
+
export * from "./types";
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility Functions
|
|
3
|
+
*
|
|
4
|
+
* Common utility functions used across the application.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Sleep for a specified duration
|
|
9
|
+
*/
|
|
10
|
+
export function sleep(ms: number): Promise<void> {
|
|
11
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Clamp a number between min and max
|
|
16
|
+
*/
|
|
17
|
+
export function clamp(value: number, min: number, max: number): number {
|
|
18
|
+
return Math.min(Math.max(value, min), max);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Format a number as currency
|
|
23
|
+
*/
|
|
24
|
+
export function formatCurrency(
|
|
25
|
+
amount: number,
|
|
26
|
+
currency = "USD",
|
|
27
|
+
locale = "en-US",
|
|
28
|
+
): string {
|
|
29
|
+
return new Intl.NumberFormat(locale, {
|
|
30
|
+
style: "currency",
|
|
31
|
+
currency,
|
|
32
|
+
}).format(amount);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Format a date
|
|
37
|
+
*/
|
|
38
|
+
export function formatDate(
|
|
39
|
+
date: Date | string | number,
|
|
40
|
+
options?: Intl.DateTimeFormatOptions,
|
|
41
|
+
locale = "en-US",
|
|
42
|
+
): string {
|
|
43
|
+
const d = new Date(date);
|
|
44
|
+
return new Intl.DateTimeFormat(locale, options).format(d);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Truncate a string
|
|
49
|
+
*/
|
|
50
|
+
export function truncate(str: string, length: number, suffix = "..."): string {
|
|
51
|
+
if (str.length <= length) return str;
|
|
52
|
+
return str.slice(0, length - suffix.length) + suffix;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Generate a random ID
|
|
57
|
+
*/
|
|
58
|
+
export function generateId(length = 8): string {
|
|
59
|
+
return Math.random()
|
|
60
|
+
.toString(36)
|
|
61
|
+
.substring(2, 2 + length);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Check if a value is empty (null, undefined, empty string, empty array, empty object)
|
|
66
|
+
*/
|
|
67
|
+
export function isEmpty(value: unknown): boolean {
|
|
68
|
+
if (value === null || value === undefined) return true;
|
|
69
|
+
if (typeof value === "string") return value.trim().length === 0;
|
|
70
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
71
|
+
if (typeof value === "object") return Object.keys(value).length === 0;
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Deep clone an object
|
|
77
|
+
*/
|
|
78
|
+
export function deepClone<T>(obj: T): T {
|
|
79
|
+
return JSON.parse(JSON.stringify(obj));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Debounce a function
|
|
84
|
+
*/
|
|
85
|
+
export function debounce<T extends (...args: unknown[]) => unknown>(
|
|
86
|
+
func: T,
|
|
87
|
+
wait: number,
|
|
88
|
+
): (...args: Parameters<T>) => void {
|
|
89
|
+
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
90
|
+
|
|
91
|
+
return (...args: Parameters<T>) => {
|
|
92
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
93
|
+
timeoutId = setTimeout(() => func(...args), wait);
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Throttle a function
|
|
99
|
+
*/
|
|
100
|
+
export function throttle<T extends (...args: unknown[]) => unknown>(
|
|
101
|
+
func: T,
|
|
102
|
+
limit: number,
|
|
103
|
+
): (...args: Parameters<T>) => void {
|
|
104
|
+
let inThrottle = false;
|
|
105
|
+
|
|
106
|
+
return (...args: Parameters<T>) => {
|
|
107
|
+
if (!inThrottle) {
|
|
108
|
+
func(...args);
|
|
109
|
+
inThrottle = true;
|
|
110
|
+
setTimeout(() => {
|
|
111
|
+
inThrottle = false;
|
|
112
|
+
}, limit);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Navigation Provider
|
|
3
|
+
*
|
|
4
|
+
* Wraps the app with NavigationContainer and linking configuration.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from "react";
|
|
8
|
+
import { NavigationContainer } from "@react-navigation/native";
|
|
9
|
+
|
|
10
|
+
interface NavigationProviderProps {
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Linking configuration for deep links.
|
|
16
|
+
* Routes are automatically generated by @teardown/navigation-metro.
|
|
17
|
+
*/
|
|
18
|
+
const linking = {
|
|
19
|
+
prefixes: ["<%= slug %>://"],
|
|
20
|
+
config: {
|
|
21
|
+
screens: {
|
|
22
|
+
"(tabs)": {
|
|
23
|
+
screens: {
|
|
24
|
+
home: "home",
|
|
25
|
+
explore: "explore",
|
|
26
|
+
profile: "profile",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
settings: "settings",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export function NavigationProvider({ children }: NavigationProviderProps): React.JSX.Element {
|
|
35
|
+
return <NavigationContainer linking={linking}>{children}</NavigationContainer>;
|
|
36
|
+
}
|