@teardown/cli 1.2.39 → 2.0.42
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.d.ts +0 -22
- package/dist/commands/dev/dev.js +0 -56
- package/dist/commands/dev/dev.js.map +0 -1
- package/dist/commands/init/init-teardown.d.ts +0 -9
- package/dist/commands/init/init-teardown.js +0 -27
- package/dist/commands/init/init-teardown.js.map +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -21
- package/dist/index.js.map +0 -1
- package/dist/modules/dev/dev-menu/keyboard-handler.d.ts +0 -21
- package/dist/modules/dev/dev-menu/keyboard-handler.js +0 -139
- package/dist/modules/dev/dev-menu/keyboard-handler.js.map +0 -1
- package/dist/modules/dev/dev-menu/open-debugger-keyboard-handler.d.ts +0 -18
- package/dist/modules/dev/dev-menu/open-debugger-keyboard-handler.js +0 -106
- package/dist/modules/dev/dev-menu/open-debugger-keyboard-handler.js.map +0 -1
- package/dist/modules/dev/dev-server/cdp/cdp.adapter.d.ts +0 -6
- package/dist/modules/dev/dev-server/cdp/cdp.adapter.js +0 -13
- package/dist/modules/dev/dev-server/cdp/cdp.adapter.js.map +0 -1
- package/dist/modules/dev/dev-server/cdp/index.d.ts +0 -2
- package/dist/modules/dev/dev-server/cdp/index.js +0 -19
- package/dist/modules/dev/dev-server/cdp/index.js.map +0 -1
- package/dist/modules/dev/dev-server/cdp/types.d.ts +0 -107
- package/dist/modules/dev/dev-server/cdp/types.js +0 -3
- package/dist/modules/dev/dev-server/cdp/types.js.map +0 -1
- package/dist/modules/dev/dev-server/dev-server-checker.d.ts +0 -22
- package/dist/modules/dev/dev-server/dev-server-checker.js +0 -73
- package/dist/modules/dev/dev-server/dev-server-checker.js.map +0 -1
- package/dist/modules/dev/dev-server/dev-server.d.ts +0 -74
- package/dist/modules/dev/dev-server/dev-server.js +0 -272
- package/dist/modules/dev/dev-server/dev-server.js.map +0 -1
- package/dist/modules/dev/dev-server/inspector/device.d.ts +0 -46
- package/dist/modules/dev/dev-server/inspector/device.event-reporter.d.ts +0 -37
- package/dist/modules/dev/dev-server/inspector/device.event-reporter.js +0 -166
- package/dist/modules/dev/dev-server/inspector/device.event-reporter.js.map +0 -1
- package/dist/modules/dev/dev-server/inspector/device.js +0 -578
- package/dist/modules/dev/dev-server/inspector/device.js.map +0 -1
- package/dist/modules/dev/dev-server/inspector/inspector.d.ts +0 -27
- package/dist/modules/dev/dev-server/inspector/inspector.js +0 -225
- package/dist/modules/dev/dev-server/inspector/inspector.js.map +0 -1
- package/dist/modules/dev/dev-server/inspector/types.d.ts +0 -156
- package/dist/modules/dev/dev-server/inspector/types.js +0 -3
- package/dist/modules/dev/dev-server/inspector/types.js.map +0 -1
- package/dist/modules/dev/dev-server/inspector/wss/servers/debugger-connection.server.d.ts +0 -14
- package/dist/modules/dev/dev-server/inspector/wss/servers/debugger-connection.server.js +0 -63
- package/dist/modules/dev/dev-server/inspector/wss/servers/debugger-connection.server.js.map +0 -1
- package/dist/modules/dev/dev-server/inspector/wss/servers/device-connection.server.d.ts +0 -19
- package/dist/modules/dev/dev-server/inspector/wss/servers/device-connection.server.js +0 -66
- package/dist/modules/dev/dev-server/inspector/wss/servers/device-connection.server.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/devtools.plugin.d.ts +0 -1
- package/dist/modules/dev/dev-server/plugins/devtools.plugin.js +0 -51
- package/dist/modules/dev/dev-server/plugins/devtools.plugin.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/favicon.plugin.d.ts +0 -1
- package/dist/modules/dev/dev-server/plugins/favicon.plugin.js +0 -19
- package/dist/modules/dev/dev-server/plugins/favicon.plugin.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/multipart.plugin.d.ts +0 -1
- package/dist/modules/dev/dev-server/plugins/multipart.plugin.js +0 -63
- package/dist/modules/dev/dev-server/plugins/multipart.plugin.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/systrace.plugin.d.ts +0 -1
- package/dist/modules/dev/dev-server/plugins/systrace.plugin.js +0 -29
- package/dist/modules/dev/dev-server/plugins/systrace.plugin.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/types.d.ts +0 -11
- package/dist/modules/dev/dev-server/plugins/types.js +0 -3
- package/dist/modules/dev/dev-server/plugins/types.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/index.d.ts +0 -3
- package/dist/modules/dev/dev-server/plugins/wss/index.js +0 -20
- package/dist/modules/dev/dev-server/plugins/wss/index.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-api.server.d.ts +0 -37
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-api.server.js +0 -67
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-api.server.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-debugger.server.d.ts +0 -63
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-debugger.server.js +0 -129
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-debugger.server.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-dev-client.server.d.ts +0 -32
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-dev-client.server.js +0 -76
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-dev-client.server.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-events.server.d.ts +0 -75
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-events.server.js +0 -199
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-events.server.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-hmr.server.d.ts +0 -44
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-hmr.server.js +0 -121
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-hmr.server.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-message.server.d.ts +0 -135
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-message.server.js +0 -364
- package/dist/modules/dev/dev-server/plugins/wss/servers/web-socket-message.server.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/types.d.ts +0 -6
- package/dist/modules/dev/dev-server/plugins/wss/types.js +0 -3
- package/dist/modules/dev/dev-server/plugins/wss/types.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-router.d.ts +0 -32
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-router.js +0 -58
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-router.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-server-adapter.d.ts +0 -13
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-server-adapter.js +0 -27
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-server-adapter.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-server.d.ts +0 -39
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-server.js +0 -47
- package/dist/modules/dev/dev-server/plugins/wss/web-socket-server.js.map +0 -1
- package/dist/modules/dev/dev-server/plugins/wss/wss.plugin.d.ts +0 -24
- package/dist/modules/dev/dev-server/plugins/wss/wss.plugin.js +0 -56
- package/dist/modules/dev/dev-server/plugins/wss/wss.plugin.js.map +0 -1
- package/dist/modules/dev/dev-server/sybmolicate/sybmolicate.plugin.d.ts +0 -7
- package/dist/modules/dev/dev-server/sybmolicate/sybmolicate.plugin.js +0 -41
- package/dist/modules/dev/dev-server/sybmolicate/sybmolicate.plugin.js.map +0 -1
- package/dist/modules/dev/dev-server/sybmolicate/types.d.ts +0 -64
- package/dist/modules/dev/dev-server/sybmolicate/types.js +0 -3
- package/dist/modules/dev/dev-server/sybmolicate/types.js.map +0 -1
- package/dist/modules/dev/terminal/base.terminal.reporter.d.ts +0 -25
- package/dist/modules/dev/terminal/base.terminal.reporter.js +0 -79
- package/dist/modules/dev/terminal/base.terminal.reporter.js.map +0 -1
- package/dist/modules/dev/terminal/terminal.reporter.d.ts +0 -13
- package/dist/modules/dev/terminal/terminal.reporter.js +0 -83
- package/dist/modules/dev/terminal/terminal.reporter.js.map +0 -1
- package/dist/modules/dev/types.d.ts +0 -20
- package/dist/modules/dev/types.js +0 -3
- package/dist/modules/dev/types.js.map +0 -1
- package/dist/modules/dev/utils/log.d.ts +0 -23
- package/dist/modules/dev/utils/log.js +0 -74
- package/dist/modules/dev/utils/log.js.map +0 -1
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import type { PrebuildWarning, ProcessedAppConfig, TeardownConfig } from "../config/types";
|
|
2
|
+
import type { VirtualFileSystem } from "../utils/fs";
|
|
3
|
+
import type { Logger } from "../utils/logger";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Plugin context provides shared state and utilities for plugins
|
|
7
|
+
*/
|
|
8
|
+
export interface PluginContext {
|
|
9
|
+
/**
|
|
10
|
+
* Shared state between plugins - allows plugins to communicate
|
|
11
|
+
*/
|
|
12
|
+
readonly sharedState: Map<string, unknown>;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Access another plugin's output by name
|
|
16
|
+
*/
|
|
17
|
+
getPluginOutput<T>(pluginName: string): T | undefined;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Set output for this plugin (accessible by other plugins)
|
|
21
|
+
*/
|
|
22
|
+
setPluginOutput<T>(pluginName: string, output: T): void;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Register a capability that this plugin provides
|
|
26
|
+
*/
|
|
27
|
+
registerCapability(capability: string): void;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Check if a capability has been registered by any plugin
|
|
31
|
+
*/
|
|
32
|
+
hasCapability(capability: string): boolean;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get all registered capabilities
|
|
36
|
+
*/
|
|
37
|
+
getCapabilities(): string[];
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Project root directory path
|
|
41
|
+
*/
|
|
42
|
+
readonly projectRoot: string;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Target platform(s) for this prebuild
|
|
46
|
+
*/
|
|
47
|
+
readonly platform: "ios" | "android" | "both";
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Virtual file system for dry-run support
|
|
51
|
+
*/
|
|
52
|
+
readonly fs: VirtualFileSystem;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Logger instance
|
|
56
|
+
*/
|
|
57
|
+
readonly log: Logger;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Original configuration (before plugin modifications)
|
|
61
|
+
*/
|
|
62
|
+
readonly originalConfig: TeardownConfig;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Current processed configuration (accumulates changes)
|
|
66
|
+
*/
|
|
67
|
+
config: ProcessedAppConfig;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Add a warning to the prebuild output
|
|
71
|
+
*/
|
|
72
|
+
addWarning(warning: PrebuildWarning): void;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get all accumulated warnings
|
|
76
|
+
*/
|
|
77
|
+
getWarnings(): PrebuildWarning[];
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Check if running in dry-run mode
|
|
81
|
+
*/
|
|
82
|
+
readonly isDryRun: boolean;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Check if verbose logging is enabled
|
|
86
|
+
*/
|
|
87
|
+
readonly isVerbose: boolean;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* iOS-specific paths
|
|
91
|
+
*/
|
|
92
|
+
readonly iosPaths: {
|
|
93
|
+
projectRoot: string;
|
|
94
|
+
infoPlist: string;
|
|
95
|
+
entitlements: string;
|
|
96
|
+
pbxproj: string;
|
|
97
|
+
podfile: string;
|
|
98
|
+
appDelegate: string;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Android-specific paths
|
|
103
|
+
*/
|
|
104
|
+
readonly androidPaths: {
|
|
105
|
+
projectRoot: string;
|
|
106
|
+
manifest: string;
|
|
107
|
+
buildGradle: string;
|
|
108
|
+
appBuildGradle: string;
|
|
109
|
+
mainActivity: string;
|
|
110
|
+
mainApplication: string;
|
|
111
|
+
stringsXml: string;
|
|
112
|
+
networkSecurityConfig: string;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Create a new plugin context
|
|
118
|
+
*/
|
|
119
|
+
export function createPluginContext(options: {
|
|
120
|
+
projectRoot: string;
|
|
121
|
+
platform: "ios" | "android" | "both";
|
|
122
|
+
config: TeardownConfig;
|
|
123
|
+
fs: VirtualFileSystem;
|
|
124
|
+
log: Logger;
|
|
125
|
+
isDryRun: boolean;
|
|
126
|
+
isVerbose: boolean;
|
|
127
|
+
}): PluginContext {
|
|
128
|
+
const { projectRoot, platform, config, fs, log, isDryRun, isVerbose } = options;
|
|
129
|
+
|
|
130
|
+
const sharedState = new Map<string, unknown>();
|
|
131
|
+
const pluginOutputs = new Map<string, unknown>();
|
|
132
|
+
const capabilities = new Set<string>();
|
|
133
|
+
const warnings: PrebuildWarning[] = [];
|
|
134
|
+
|
|
135
|
+
// Derive app name for paths
|
|
136
|
+
const appName = config.name.replace(/[^a-zA-Z0-9]/g, "");
|
|
137
|
+
const packagePath = config.android?.packageName?.replace(/\./g, "/") ?? "com/example/app";
|
|
138
|
+
|
|
139
|
+
// Create processed config with empty resolved fields
|
|
140
|
+
const processedConfig: ProcessedAppConfig = {
|
|
141
|
+
...config,
|
|
142
|
+
resolvedInfoPlist: {},
|
|
143
|
+
resolvedEntitlements: {},
|
|
144
|
+
resolvedAndroidPermissions: [],
|
|
145
|
+
resolvedAndroidFeatures: [],
|
|
146
|
+
resolvedAndroidMetadata: {},
|
|
147
|
+
resolvedGradleDependencies: [],
|
|
148
|
+
resolvedFrameworks: [],
|
|
149
|
+
resolvedPodDependencies: [],
|
|
150
|
+
resolvedBackgroundModes: [],
|
|
151
|
+
resolvedUrlSchemes: [],
|
|
152
|
+
resolvedIntentFilters: [],
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const iosPaths = {
|
|
156
|
+
projectRoot: `${projectRoot}/ios`,
|
|
157
|
+
infoPlist: `${projectRoot}/ios/${appName}/Info.plist`,
|
|
158
|
+
entitlements: `${projectRoot}/ios/${appName}/${appName}.entitlements`,
|
|
159
|
+
pbxproj: `${projectRoot}/ios/${appName}.xcodeproj/project.pbxproj`,
|
|
160
|
+
podfile: `${projectRoot}/ios/Podfile`,
|
|
161
|
+
appDelegate: `${projectRoot}/ios/${appName}/AppDelegate.swift`,
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const androidPaths = {
|
|
165
|
+
projectRoot: `${projectRoot}/android`,
|
|
166
|
+
manifest: `${projectRoot}/android/app/src/main/AndroidManifest.xml`,
|
|
167
|
+
buildGradle: `${projectRoot}/android/build.gradle.kts`,
|
|
168
|
+
appBuildGradle: `${projectRoot}/android/app/build.gradle.kts`,
|
|
169
|
+
mainActivity: `${projectRoot}/android/app/src/main/java/${packagePath}/MainActivity.kt`,
|
|
170
|
+
mainApplication: `${projectRoot}/android/app/src/main/java/${packagePath}/MainApplication.kt`,
|
|
171
|
+
stringsXml: `${projectRoot}/android/app/src/main/res/values/strings.xml`,
|
|
172
|
+
networkSecurityConfig: `${projectRoot}/android/app/src/main/res/xml/network_security_config.xml`,
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
sharedState,
|
|
177
|
+
|
|
178
|
+
getPluginOutput<T>(pluginName: string): T | undefined {
|
|
179
|
+
return pluginOutputs.get(pluginName) as T | undefined;
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
setPluginOutput<T>(pluginName: string, output: T): void {
|
|
183
|
+
pluginOutputs.set(pluginName, output);
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
registerCapability(capability: string): void {
|
|
187
|
+
capabilities.add(capability);
|
|
188
|
+
log.debug(`Registered capability: ${capability}`);
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
hasCapability(capability: string): boolean {
|
|
192
|
+
return capabilities.has(capability);
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
getCapabilities(): string[] {
|
|
196
|
+
return Array.from(capabilities);
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
projectRoot,
|
|
200
|
+
platform,
|
|
201
|
+
fs,
|
|
202
|
+
log,
|
|
203
|
+
originalConfig: config,
|
|
204
|
+
config: processedConfig,
|
|
205
|
+
isDryRun,
|
|
206
|
+
isVerbose,
|
|
207
|
+
|
|
208
|
+
addWarning(warning: PrebuildWarning): void {
|
|
209
|
+
warnings.push(warning);
|
|
210
|
+
log.warn(`[${warning.code}] ${warning.message}`);
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
getWarnings(): PrebuildWarning[] {
|
|
214
|
+
return [...warnings];
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
iosPaths,
|
|
218
|
+
androidPaths,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin system for Teardown Launchpad
|
|
3
|
+
*
|
|
4
|
+
* Provides the base plugin class, context, and dependency resolution
|
|
5
|
+
* for implementing native capability plugins.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type {
|
|
9
|
+
AndroidActivity,
|
|
10
|
+
AndroidIntentData,
|
|
11
|
+
AndroidIntentFilter,
|
|
12
|
+
AndroidManifest,
|
|
13
|
+
AndroidProvider,
|
|
14
|
+
AndroidReceiver,
|
|
15
|
+
AndroidService,
|
|
16
|
+
Entitlements,
|
|
17
|
+
InfoPlist,
|
|
18
|
+
PluginConstructor,
|
|
19
|
+
} from "./base";
|
|
20
|
+
export { BasePlugin } from "./base";
|
|
21
|
+
// Re-export capability plugins
|
|
22
|
+
export * from "./capabilities";
|
|
23
|
+
export type { PluginContext } from "./context";
|
|
24
|
+
export { createPluginContext } from "./context";
|
|
25
|
+
export type { CycleInfo } from "./resolver";
|
|
26
|
+
export { DependencyResolver, PluginResolutionError } from "./resolver";
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import type { Logger } from "../utils/logger";
|
|
2
|
+
import type { BasePlugin, PluginConstructor } from "./base";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Plugin resolution error
|
|
6
|
+
*/
|
|
7
|
+
export class PluginResolutionError extends Error {
|
|
8
|
+
constructor(
|
|
9
|
+
message: string,
|
|
10
|
+
public readonly code: string,
|
|
11
|
+
public readonly details?: unknown
|
|
12
|
+
) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "PluginResolutionError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Cycle detection result
|
|
20
|
+
*/
|
|
21
|
+
export interface CycleInfo {
|
|
22
|
+
plugins: string[];
|
|
23
|
+
path: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Plugin registry and dependency resolver
|
|
28
|
+
*
|
|
29
|
+
* Handles plugin registration, dependency resolution, and topological sorting
|
|
30
|
+
*/
|
|
31
|
+
export class DependencyResolver {
|
|
32
|
+
private plugins: Map<string, BasePlugin> = new Map();
|
|
33
|
+
private pluginConfigs: Map<string, unknown> = new Map();
|
|
34
|
+
private logger: Logger;
|
|
35
|
+
|
|
36
|
+
constructor(logger: Logger) {
|
|
37
|
+
this.logger = logger;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Register a plugin instance
|
|
42
|
+
*/
|
|
43
|
+
registerPlugin<TConfig>(plugin: BasePlugin<TConfig>, config?: TConfig): void {
|
|
44
|
+
if (this.plugins.has(plugin.name)) {
|
|
45
|
+
throw new PluginResolutionError(`Plugin "${plugin.name}" is already registered`, "DUPLICATE_PLUGIN");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Validate config if provided
|
|
49
|
+
if (config !== undefined) {
|
|
50
|
+
try {
|
|
51
|
+
plugin.validateConfig(config);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
throw new PluginResolutionError(
|
|
54
|
+
`Invalid configuration for plugin "${plugin.name}": ${error instanceof Error ? error.message : String(error)}`,
|
|
55
|
+
"INVALID_CONFIG",
|
|
56
|
+
error
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.plugins.set(plugin.name, plugin);
|
|
62
|
+
if (config !== undefined) {
|
|
63
|
+
this.pluginConfigs.set(plugin.name, config);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.logger.debug(`Registered plugin: ${plugin.name} v${plugin.version}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Register a plugin from constructor and config
|
|
71
|
+
*/
|
|
72
|
+
registerPluginFromConstructor<TConfig>(Constructor: PluginConstructor<TConfig>, config?: TConfig): void {
|
|
73
|
+
const plugin = new Constructor();
|
|
74
|
+
this.registerPlugin(plugin, config);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get a registered plugin by name
|
|
79
|
+
*/
|
|
80
|
+
getPlugin(name: string): BasePlugin | undefined {
|
|
81
|
+
return this.plugins.get(name);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get plugin configuration
|
|
86
|
+
*/
|
|
87
|
+
getPluginConfig<TConfig>(name: string): TConfig | undefined {
|
|
88
|
+
return this.pluginConfigs.get(name) as TConfig | undefined;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Check if a plugin is registered
|
|
93
|
+
*/
|
|
94
|
+
hasPlugin(name: string): boolean {
|
|
95
|
+
return this.plugins.has(name);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get all registered plugin names
|
|
100
|
+
*/
|
|
101
|
+
getPluginNames(): string[] {
|
|
102
|
+
return Array.from(this.plugins.keys());
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Resolve plugin execution order using topological sort
|
|
107
|
+
* Returns plugins in order such that dependencies come before dependents
|
|
108
|
+
*/
|
|
109
|
+
resolveOrder(): BasePlugin[] {
|
|
110
|
+
// First, check for cycles
|
|
111
|
+
const cycles = this.detectCycles();
|
|
112
|
+
if (cycles.length > 0) {
|
|
113
|
+
const cycleStr = cycles.map((c) => c.path).join("; ");
|
|
114
|
+
throw new PluginResolutionError(`Circular dependencies detected: ${cycleStr}`, "CIRCULAR_DEPENDENCY", cycles);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Check for missing dependencies
|
|
118
|
+
const missingDeps = this.findMissingDependencies();
|
|
119
|
+
if (missingDeps.length > 0) {
|
|
120
|
+
const missingStr = missingDeps.map((m) => `${m.plugin} requires ${m.dependency}`).join(", ");
|
|
121
|
+
throw new PluginResolutionError(`Missing dependencies: ${missingStr}`, "MISSING_DEPENDENCY", missingDeps);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Perform topological sort using Kahn's algorithm
|
|
125
|
+
const inDegree = new Map<string, number>();
|
|
126
|
+
const adjacency = new Map<string, string[]>();
|
|
127
|
+
|
|
128
|
+
// Initialize
|
|
129
|
+
for (const [name] of this.plugins) {
|
|
130
|
+
inDegree.set(name, 0);
|
|
131
|
+
adjacency.set(name, []);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Build graph
|
|
135
|
+
for (const [name, plugin] of this.plugins) {
|
|
136
|
+
for (const dep of plugin.dependencies) {
|
|
137
|
+
if (this.plugins.has(dep)) {
|
|
138
|
+
adjacency.get(dep)?.push(name);
|
|
139
|
+
inDegree.set(name, (inDegree.get(name) || 0) + 1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Find all nodes with no incoming edges
|
|
145
|
+
const queue: string[] = [];
|
|
146
|
+
for (const [name, degree] of inDegree) {
|
|
147
|
+
if (degree === 0) {
|
|
148
|
+
queue.push(name);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Process queue
|
|
153
|
+
const result: BasePlugin[] = [];
|
|
154
|
+
while (queue.length > 0) {
|
|
155
|
+
const current = queue.shift()!;
|
|
156
|
+
result.push(this.plugins.get(current)!);
|
|
157
|
+
|
|
158
|
+
for (const neighbor of adjacency.get(current) || []) {
|
|
159
|
+
const newDegree = (inDegree.get(neighbor) || 1) - 1;
|
|
160
|
+
inDegree.set(neighbor, newDegree);
|
|
161
|
+
if (newDegree === 0) {
|
|
162
|
+
queue.push(neighbor);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
this.logger.debug(`Plugin execution order: ${result.map((p) => p.name).join(" -> ")}`);
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Detect circular dependencies using Tarjan's algorithm
|
|
173
|
+
*/
|
|
174
|
+
detectCycles(): CycleInfo[] {
|
|
175
|
+
const cycles: CycleInfo[] = [];
|
|
176
|
+
const visited = new Set<string>();
|
|
177
|
+
const recursionStack = new Set<string>();
|
|
178
|
+
const path: string[] = [];
|
|
179
|
+
|
|
180
|
+
const dfs = (name: string): boolean => {
|
|
181
|
+
visited.add(name);
|
|
182
|
+
recursionStack.add(name);
|
|
183
|
+
path.push(name);
|
|
184
|
+
|
|
185
|
+
const plugin = this.plugins.get(name);
|
|
186
|
+
if (plugin) {
|
|
187
|
+
for (const dep of plugin.dependencies) {
|
|
188
|
+
if (!this.plugins.has(dep)) {
|
|
189
|
+
continue; // Skip missing deps (handled separately)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!visited.has(dep)) {
|
|
193
|
+
if (dfs(dep)) {
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
} else if (recursionStack.has(dep)) {
|
|
197
|
+
// Found a cycle
|
|
198
|
+
const cycleStart = path.indexOf(dep);
|
|
199
|
+
const cyclePath = path.slice(cycleStart);
|
|
200
|
+
cycles.push({
|
|
201
|
+
plugins: [...cyclePath],
|
|
202
|
+
path: `${cyclePath.join(" -> ")} -> ${dep}`,
|
|
203
|
+
});
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
path.pop();
|
|
210
|
+
recursionStack.delete(name);
|
|
211
|
+
return false;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
for (const name of this.plugins.keys()) {
|
|
215
|
+
if (!visited.has(name)) {
|
|
216
|
+
dfs(name);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return cycles;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Find dependencies that are not registered
|
|
225
|
+
*/
|
|
226
|
+
findMissingDependencies(): Array<{ plugin: string; dependency: string }> {
|
|
227
|
+
const missing: Array<{ plugin: string; dependency: string }> = [];
|
|
228
|
+
|
|
229
|
+
for (const [name, plugin] of this.plugins) {
|
|
230
|
+
for (const dep of plugin.dependencies) {
|
|
231
|
+
if (!this.plugins.has(dep)) {
|
|
232
|
+
missing.push({ plugin: name, dependency: dep });
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return missing;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Get plugins that depend on a specific plugin
|
|
242
|
+
*/
|
|
243
|
+
getDependents(pluginName: string): BasePlugin[] {
|
|
244
|
+
const dependents: BasePlugin[] = [];
|
|
245
|
+
|
|
246
|
+
for (const plugin of this.plugins.values()) {
|
|
247
|
+
if (plugin.dependencies.includes(pluginName)) {
|
|
248
|
+
dependents.push(plugin);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return dependents;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Get plugins that a specific plugin depends on
|
|
257
|
+
*/
|
|
258
|
+
getDependencies(pluginName: string): BasePlugin[] {
|
|
259
|
+
const plugin = this.plugins.get(pluginName);
|
|
260
|
+
if (!plugin) {
|
|
261
|
+
return [];
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return plugin.dependencies.map((dep) => this.plugins.get(dep)).filter((p): p is BasePlugin => p !== undefined);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Clear all registered plugins
|
|
269
|
+
*/
|
|
270
|
+
clear(): void {
|
|
271
|
+
this.plugins.clear();
|
|
272
|
+
this.pluginConfigs.clear();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Get all registered plugins (unordered)
|
|
277
|
+
*/
|
|
278
|
+
getAllPlugins(): BasePlugin[] {
|
|
279
|
+
return Array.from(this.plugins.values());
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Validate all plugin configurations
|
|
284
|
+
*/
|
|
285
|
+
validateAllConfigs(): Array<{ plugin: string; error: string }> {
|
|
286
|
+
const errors: Array<{ plugin: string; error: string }> = [];
|
|
287
|
+
|
|
288
|
+
for (const [name, plugin] of this.plugins) {
|
|
289
|
+
const config = this.pluginConfigs.get(name);
|
|
290
|
+
if (config !== undefined) {
|
|
291
|
+
try {
|
|
292
|
+
plugin.validateConfig(config);
|
|
293
|
+
} catch (error) {
|
|
294
|
+
errors.push({
|
|
295
|
+
plugin: name,
|
|
296
|
+
error: error instanceof Error ? error.message : String(error),
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return errors;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Get all capabilities provided by registered plugins
|
|
307
|
+
*/
|
|
308
|
+
getAllProvidedCapabilities(): Map<string, string[]> {
|
|
309
|
+
const capabilities = new Map<string, string[]>();
|
|
310
|
+
|
|
311
|
+
for (const plugin of this.plugins.values()) {
|
|
312
|
+
for (const capability of plugin.provides) {
|
|
313
|
+
const providers = capabilities.get(capability) || [];
|
|
314
|
+
providers.push(plugin.name);
|
|
315
|
+
capabilities.set(capability, providers);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return capabilities;
|
|
320
|
+
}
|
|
321
|
+
}
|