@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.
- 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,198 @@
|
|
|
1
|
+
import * as plist from "simple-plist";
|
|
2
|
+
import type { ProcessedAppConfig } from "../../config/types";
|
|
3
|
+
import type { PluginContext } from "../../plugins/context";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Info.plist structure
|
|
7
|
+
*/
|
|
8
|
+
export interface InfoPlistContent {
|
|
9
|
+
CFBundleName: string;
|
|
10
|
+
CFBundleDisplayName: string;
|
|
11
|
+
CFBundleIdentifier: string;
|
|
12
|
+
CFBundleVersion: string;
|
|
13
|
+
CFBundleShortVersionString: string;
|
|
14
|
+
CFBundlePackageType: string;
|
|
15
|
+
CFBundleExecutable: string;
|
|
16
|
+
UILaunchStoryboardName: string;
|
|
17
|
+
UIRequiredDeviceCapabilities: string[];
|
|
18
|
+
UISupportedInterfaceOrientations: string[];
|
|
19
|
+
UIStatusBarStyle?: string;
|
|
20
|
+
UIViewControllerBasedStatusBarAppearance?: boolean;
|
|
21
|
+
UIBackgroundModes?: string[];
|
|
22
|
+
LSApplicationQueriesSchemes?: string[];
|
|
23
|
+
CFBundleURLTypes?: CFBundleURLType[];
|
|
24
|
+
NSAppTransportSecurity?: {
|
|
25
|
+
NSAllowsArbitraryLoads?: boolean;
|
|
26
|
+
NSAllowsLocalNetworking?: boolean;
|
|
27
|
+
NSExceptionDomains?: Record<string, unknown>;
|
|
28
|
+
};
|
|
29
|
+
[key: string]: unknown;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface CFBundleURLType {
|
|
33
|
+
CFBundleURLName?: string;
|
|
34
|
+
CFBundleURLSchemes: string[];
|
|
35
|
+
CFBundleTypeRole?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Plist transformer for iOS Info.plist files
|
|
40
|
+
*/
|
|
41
|
+
export class PlistTransformer {
|
|
42
|
+
/**
|
|
43
|
+
* Transform the Info.plist file with configuration
|
|
44
|
+
*/
|
|
45
|
+
async transform(context: PluginContext, config: ProcessedAppConfig): Promise<void> {
|
|
46
|
+
const { fs, log, iosPaths } = context;
|
|
47
|
+
|
|
48
|
+
log.debug("Transforming Info.plist...");
|
|
49
|
+
|
|
50
|
+
let existingPlist: InfoPlistContent;
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const content = await fs.readFile(iosPaths.infoPlist);
|
|
54
|
+
existingPlist = plist.parse(content) as InfoPlistContent;
|
|
55
|
+
} catch {
|
|
56
|
+
// Create default plist if doesn't exist
|
|
57
|
+
existingPlist = this.createDefaultPlist(config);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Apply configuration
|
|
61
|
+
const updatedPlist = this.applyConfig(existingPlist, config);
|
|
62
|
+
|
|
63
|
+
// Write back
|
|
64
|
+
const plistContent = plist.stringify(updatedPlist);
|
|
65
|
+
await fs.writeFile(iosPaths.infoPlist, plistContent);
|
|
66
|
+
|
|
67
|
+
log.debug("Info.plist transformation complete");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Create default Info.plist content
|
|
72
|
+
*/
|
|
73
|
+
private createDefaultPlist(config: ProcessedAppConfig): InfoPlistContent {
|
|
74
|
+
const appName = config.name.replace(/[^a-zA-Z0-9]/g, "");
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
CFBundleName: config.name,
|
|
78
|
+
CFBundleDisplayName: config.name,
|
|
79
|
+
CFBundleIdentifier: config.ios?.bundleIdentifier ?? "com.example.app",
|
|
80
|
+
CFBundleVersion: String(config.ios?.buildNumber ?? 1),
|
|
81
|
+
CFBundleShortVersionString: config.version,
|
|
82
|
+
CFBundlePackageType: "APPL",
|
|
83
|
+
CFBundleExecutable: appName,
|
|
84
|
+
UILaunchStoryboardName: "LaunchScreen",
|
|
85
|
+
UIRequiredDeviceCapabilities: ["arm64"],
|
|
86
|
+
UISupportedInterfaceOrientations: this.getOrientations(config),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Apply configuration to existing plist
|
|
92
|
+
*/
|
|
93
|
+
private applyConfig(plist: InfoPlistContent, config: ProcessedAppConfig): InfoPlistContent {
|
|
94
|
+
// Update basic info
|
|
95
|
+
plist.CFBundleName = config.name;
|
|
96
|
+
plist.CFBundleDisplayName = config.name;
|
|
97
|
+
plist.CFBundleIdentifier = config.ios?.bundleIdentifier ?? plist.CFBundleIdentifier;
|
|
98
|
+
plist.CFBundleVersion = String(config.ios?.buildNumber ?? 1);
|
|
99
|
+
plist.CFBundleShortVersionString = config.version;
|
|
100
|
+
|
|
101
|
+
// Apply orientation
|
|
102
|
+
plist.UISupportedInterfaceOrientations = this.getOrientations(config);
|
|
103
|
+
|
|
104
|
+
// Apply user interface style
|
|
105
|
+
if (config.userInterfaceStyle === "light") {
|
|
106
|
+
plist.UIUserInterfaceStyle = "Light";
|
|
107
|
+
} else if (config.userInterfaceStyle === "dark") {
|
|
108
|
+
plist.UIUserInterfaceStyle = "Dark";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Apply background modes
|
|
112
|
+
if (config.resolvedBackgroundModes.length > 0) {
|
|
113
|
+
plist.UIBackgroundModes = config.resolvedBackgroundModes;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Apply URL schemes
|
|
117
|
+
if (config.resolvedUrlSchemes.length > 0 || config.scheme) {
|
|
118
|
+
const schemes = [...config.resolvedUrlSchemes];
|
|
119
|
+
if (config.scheme && !schemes.includes(config.scheme)) {
|
|
120
|
+
schemes.push(config.scheme);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
plist.CFBundleURLTypes = plist.CFBundleURLTypes ?? [];
|
|
124
|
+
|
|
125
|
+
for (const scheme of schemes) {
|
|
126
|
+
// Check if scheme already exists
|
|
127
|
+
const existing = plist.CFBundleURLTypes.find((t) => t.CFBundleURLSchemes.includes(scheme));
|
|
128
|
+
|
|
129
|
+
if (!existing) {
|
|
130
|
+
plist.CFBundleURLTypes.push({
|
|
131
|
+
CFBundleURLName: config.ios?.bundleIdentifier ?? "",
|
|
132
|
+
CFBundleURLSchemes: [scheme],
|
|
133
|
+
CFBundleTypeRole: "Editor",
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Apply plugin-resolved Info.plist entries (permissions, etc.)
|
|
140
|
+
for (const [key, value] of Object.entries(config.resolvedInfoPlist)) {
|
|
141
|
+
plist[key] = value;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Apply custom Info.plist entries from config
|
|
145
|
+
if (config.ios?.infoPlist) {
|
|
146
|
+
for (const [key, value] of Object.entries(config.ios.infoPlist)) {
|
|
147
|
+
plist[key] = value;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return plist;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get supported interface orientations based on config
|
|
156
|
+
*/
|
|
157
|
+
private getOrientations(config: ProcessedAppConfig): string[] {
|
|
158
|
+
const orientations: string[] = [];
|
|
159
|
+
|
|
160
|
+
switch (config.orientation) {
|
|
161
|
+
case "portrait":
|
|
162
|
+
orientations.push("UIInterfaceOrientationPortrait");
|
|
163
|
+
orientations.push("UIInterfaceOrientationPortraitUpsideDown");
|
|
164
|
+
break;
|
|
165
|
+
case "landscape":
|
|
166
|
+
orientations.push("UIInterfaceOrientationLandscapeLeft");
|
|
167
|
+
orientations.push("UIInterfaceOrientationLandscapeRight");
|
|
168
|
+
break;
|
|
169
|
+
default:
|
|
170
|
+
orientations.push(
|
|
171
|
+
"UIInterfaceOrientationPortrait",
|
|
172
|
+
"UIInterfaceOrientationPortraitUpsideDown",
|
|
173
|
+
"UIInterfaceOrientationLandscapeLeft",
|
|
174
|
+
"UIInterfaceOrientationLandscapeRight"
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return orientations;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Read and parse an existing plist file
|
|
183
|
+
*/
|
|
184
|
+
static async readPlist(filePath: string): Promise<InfoPlistContent> {
|
|
185
|
+
const fs = await import("node:fs/promises");
|
|
186
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
187
|
+
return plist.parse(content) as InfoPlistContent;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Write plist content to file
|
|
192
|
+
*/
|
|
193
|
+
static async writePlist(filePath: string, content: InfoPlistContent): Promise<void> {
|
|
194
|
+
const fs = await import("node:fs/promises");
|
|
195
|
+
const plistContent = plist.stringify(content);
|
|
196
|
+
await fs.writeFile(filePath, plistContent, "utf-8");
|
|
197
|
+
}
|
|
198
|
+
}
|
package/src/utils/fs.ts
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import type { FileChange } from "../config/types";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Virtual file system that can operate in dry-run mode
|
|
7
|
+
*
|
|
8
|
+
* In normal mode, operations are performed on the real filesystem.
|
|
9
|
+
* In dry-run mode, operations are recorded but not applied.
|
|
10
|
+
*/
|
|
11
|
+
export interface VirtualFileSystem {
|
|
12
|
+
/**
|
|
13
|
+
* Read a file
|
|
14
|
+
*/
|
|
15
|
+
readFile(filePath: string): Promise<string>;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Read a file synchronously
|
|
19
|
+
*/
|
|
20
|
+
readFileSync(filePath: string): string;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Write a file
|
|
24
|
+
*/
|
|
25
|
+
writeFile(filePath: string, content: string): Promise<void>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Write a file synchronously
|
|
29
|
+
*/
|
|
30
|
+
writeFileSync(filePath: string, content: string): void;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Check if a file exists
|
|
34
|
+
*/
|
|
35
|
+
exists(filePath: string): Promise<boolean>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Check if a file exists synchronously
|
|
39
|
+
*/
|
|
40
|
+
existsSync(filePath: string): boolean;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create a directory recursively
|
|
44
|
+
*/
|
|
45
|
+
mkdir(dirPath: string): Promise<void>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Create a directory recursively synchronously
|
|
49
|
+
*/
|
|
50
|
+
mkdirSync(dirPath: string): void;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Delete a file
|
|
54
|
+
*/
|
|
55
|
+
unlink(filePath: string): Promise<void>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Delete a file synchronously
|
|
59
|
+
*/
|
|
60
|
+
unlinkSync(filePath: string): void;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Delete a directory recursively
|
|
64
|
+
*/
|
|
65
|
+
rmdir(dirPath: string): Promise<void>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Copy a file
|
|
69
|
+
*/
|
|
70
|
+
copyFile(src: string, dest: string): Promise<void>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Copy a file synchronously
|
|
74
|
+
*/
|
|
75
|
+
copyFileSync(src: string, dest: string): void;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get all recorded changes (for dry-run mode)
|
|
79
|
+
*/
|
|
80
|
+
getChanges(): FileChange[];
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Commit all pending changes to the real filesystem
|
|
84
|
+
*/
|
|
85
|
+
commit(): Promise<void>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Check if operating in dry-run mode
|
|
89
|
+
*/
|
|
90
|
+
isDryRun(): boolean;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Create a virtual file system
|
|
95
|
+
*/
|
|
96
|
+
export function createVirtualFileSystem(options: { dryRun?: boolean; projectRoot: string }): VirtualFileSystem {
|
|
97
|
+
const { dryRun = false, projectRoot } = options;
|
|
98
|
+
const changes: FileChange[] = [];
|
|
99
|
+
const virtualFiles: Map<string, string> = new Map();
|
|
100
|
+
const deletedFiles: Set<string> = new Set();
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Normalize path to absolute
|
|
104
|
+
*/
|
|
105
|
+
const normalizePath = (filePath: string): string => {
|
|
106
|
+
if (path.isAbsolute(filePath)) {
|
|
107
|
+
return filePath;
|
|
108
|
+
}
|
|
109
|
+
return path.join(projectRoot, filePath);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Read from virtual or real filesystem
|
|
114
|
+
*/
|
|
115
|
+
const readFromVirtualOrReal = (filePath: string): string | null => {
|
|
116
|
+
const normalizedPath = normalizePath(filePath);
|
|
117
|
+
|
|
118
|
+
// Check if deleted
|
|
119
|
+
if (deletedFiles.has(normalizedPath)) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check virtual files first
|
|
124
|
+
if (virtualFiles.has(normalizedPath)) {
|
|
125
|
+
return virtualFiles.get(normalizedPath)!;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Fall back to real filesystem
|
|
129
|
+
try {
|
|
130
|
+
return fs.readFileSync(normalizedPath, "utf-8");
|
|
131
|
+
} catch {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Record a file change
|
|
138
|
+
*/
|
|
139
|
+
const recordChange = (
|
|
140
|
+
filePath: string,
|
|
141
|
+
operation: "create" | "modify" | "delete",
|
|
142
|
+
before: string | undefined,
|
|
143
|
+
after: string
|
|
144
|
+
): void => {
|
|
145
|
+
const normalizedPath = normalizePath(filePath);
|
|
146
|
+
|
|
147
|
+
// Find existing change for this file
|
|
148
|
+
const existingIndex = changes.findIndex((c) => c.path === normalizedPath);
|
|
149
|
+
|
|
150
|
+
if (existingIndex >= 0) {
|
|
151
|
+
// Update existing change
|
|
152
|
+
changes[existingIndex] = {
|
|
153
|
+
...changes[existingIndex],
|
|
154
|
+
after,
|
|
155
|
+
operation: operation === "delete" ? "delete" : changes[existingIndex].operation,
|
|
156
|
+
};
|
|
157
|
+
} else {
|
|
158
|
+
changes.push({
|
|
159
|
+
path: normalizedPath,
|
|
160
|
+
operation,
|
|
161
|
+
before,
|
|
162
|
+
after,
|
|
163
|
+
diff: generateDiff(before, after),
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
async readFile(filePath: string): Promise<string> {
|
|
170
|
+
const content = readFromVirtualOrReal(filePath);
|
|
171
|
+
if (content === null) {
|
|
172
|
+
throw new Error(`File not found: ${filePath}`);
|
|
173
|
+
}
|
|
174
|
+
return content;
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
readFileSync(filePath: string): string {
|
|
178
|
+
const content = readFromVirtualOrReal(filePath);
|
|
179
|
+
if (content === null) {
|
|
180
|
+
throw new Error(`File not found: ${filePath}`);
|
|
181
|
+
}
|
|
182
|
+
return content;
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
async writeFile(filePath: string, content: string): Promise<void> {
|
|
186
|
+
const normalizedPath = normalizePath(filePath);
|
|
187
|
+
const before = readFromVirtualOrReal(filePath) ?? undefined;
|
|
188
|
+
const isNew = before === undefined;
|
|
189
|
+
|
|
190
|
+
if (dryRun) {
|
|
191
|
+
virtualFiles.set(normalizedPath, content);
|
|
192
|
+
deletedFiles.delete(normalizedPath);
|
|
193
|
+
recordChange(filePath, isNew ? "create" : "modify", before, content);
|
|
194
|
+
} else {
|
|
195
|
+
// Ensure directory exists
|
|
196
|
+
const dir = path.dirname(normalizedPath);
|
|
197
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
198
|
+
await fs.promises.writeFile(normalizedPath, content, "utf-8");
|
|
199
|
+
recordChange(filePath, isNew ? "create" : "modify", before, content);
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
writeFileSync(filePath: string, content: string): void {
|
|
204
|
+
const normalizedPath = normalizePath(filePath);
|
|
205
|
+
const before = readFromVirtualOrReal(filePath) ?? undefined;
|
|
206
|
+
const isNew = before === undefined;
|
|
207
|
+
|
|
208
|
+
if (dryRun) {
|
|
209
|
+
virtualFiles.set(normalizedPath, content);
|
|
210
|
+
deletedFiles.delete(normalizedPath);
|
|
211
|
+
recordChange(filePath, isNew ? "create" : "modify", before, content);
|
|
212
|
+
} else {
|
|
213
|
+
// Ensure directory exists
|
|
214
|
+
const dir = path.dirname(normalizedPath);
|
|
215
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
216
|
+
fs.writeFileSync(normalizedPath, content, "utf-8");
|
|
217
|
+
recordChange(filePath, isNew ? "create" : "modify", before, content);
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
async exists(filePath: string): Promise<boolean> {
|
|
222
|
+
const normalizedPath = normalizePath(filePath);
|
|
223
|
+
|
|
224
|
+
if (deletedFiles.has(normalizedPath)) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (virtualFiles.has(normalizedPath)) {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
try {
|
|
233
|
+
await fs.promises.access(normalizedPath);
|
|
234
|
+
return true;
|
|
235
|
+
} catch {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
existsSync(filePath: string): boolean {
|
|
241
|
+
const normalizedPath = normalizePath(filePath);
|
|
242
|
+
|
|
243
|
+
if (deletedFiles.has(normalizedPath)) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (virtualFiles.has(normalizedPath)) {
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return fs.existsSync(normalizedPath);
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
async mkdir(dirPath: string): Promise<void> {
|
|
255
|
+
if (!dryRun) {
|
|
256
|
+
await fs.promises.mkdir(normalizePath(dirPath), { recursive: true });
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
mkdirSync(dirPath: string): void {
|
|
261
|
+
if (!dryRun) {
|
|
262
|
+
fs.mkdirSync(normalizePath(dirPath), { recursive: true });
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
async unlink(filePath: string): Promise<void> {
|
|
267
|
+
const normalizedPath = normalizePath(filePath);
|
|
268
|
+
const before = readFromVirtualOrReal(filePath) ?? "";
|
|
269
|
+
|
|
270
|
+
if (dryRun) {
|
|
271
|
+
virtualFiles.delete(normalizedPath);
|
|
272
|
+
deletedFiles.add(normalizedPath);
|
|
273
|
+
recordChange(filePath, "delete", before, "");
|
|
274
|
+
} else {
|
|
275
|
+
await fs.promises.unlink(normalizedPath);
|
|
276
|
+
recordChange(filePath, "delete", before, "");
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
unlinkSync(filePath: string): void {
|
|
281
|
+
const normalizedPath = normalizePath(filePath);
|
|
282
|
+
const before = readFromVirtualOrReal(filePath) ?? "";
|
|
283
|
+
|
|
284
|
+
if (dryRun) {
|
|
285
|
+
virtualFiles.delete(normalizedPath);
|
|
286
|
+
deletedFiles.add(normalizedPath);
|
|
287
|
+
recordChange(filePath, "delete", before, "");
|
|
288
|
+
} else {
|
|
289
|
+
fs.unlinkSync(normalizedPath);
|
|
290
|
+
recordChange(filePath, "delete", before, "");
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
|
|
294
|
+
async rmdir(dirPath: string): Promise<void> {
|
|
295
|
+
if (!dryRun) {
|
|
296
|
+
await fs.promises.rm(normalizePath(dirPath), { recursive: true, force: true });
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
async copyFile(src: string, dest: string): Promise<void> {
|
|
301
|
+
const content = await this.readFile(src);
|
|
302
|
+
await this.writeFile(dest, content);
|
|
303
|
+
},
|
|
304
|
+
|
|
305
|
+
copyFileSync(src: string, dest: string): void {
|
|
306
|
+
const content = this.readFileSync(src);
|
|
307
|
+
this.writeFileSync(dest, content);
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
getChanges(): FileChange[] {
|
|
311
|
+
return [...changes];
|
|
312
|
+
},
|
|
313
|
+
|
|
314
|
+
async commit(): Promise<void> {
|
|
315
|
+
if (!dryRun) {
|
|
316
|
+
// Changes are already committed in non-dry-run mode
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Apply all virtual changes to real filesystem
|
|
321
|
+
for (const change of changes) {
|
|
322
|
+
switch (change.operation) {
|
|
323
|
+
case "create":
|
|
324
|
+
case "modify": {
|
|
325
|
+
const dir = path.dirname(change.path);
|
|
326
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
327
|
+
await fs.promises.writeFile(change.path, change.after, "utf-8");
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
case "delete": {
|
|
331
|
+
try {
|
|
332
|
+
await fs.promises.unlink(change.path);
|
|
333
|
+
} catch {
|
|
334
|
+
// File might not exist
|
|
335
|
+
}
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Clear virtual state
|
|
342
|
+
virtualFiles.clear();
|
|
343
|
+
deletedFiles.clear();
|
|
344
|
+
},
|
|
345
|
+
|
|
346
|
+
isDryRun(): boolean {
|
|
347
|
+
return dryRun;
|
|
348
|
+
},
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Generate a simple diff between two strings
|
|
354
|
+
*/
|
|
355
|
+
function generateDiff(before: string | undefined, after: string): string {
|
|
356
|
+
if (before === undefined) {
|
|
357
|
+
return `+ ${after.split("\n").length} lines added`;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const beforeLines = before.split("\n");
|
|
361
|
+
const afterLines = after.split("\n");
|
|
362
|
+
|
|
363
|
+
const added = afterLines.length - beforeLines.length;
|
|
364
|
+
const removed = beforeLines.filter((line, i) => afterLines[i] !== line).length;
|
|
365
|
+
|
|
366
|
+
const parts: string[] = [];
|
|
367
|
+
if (added > 0) parts.push(`+${added}`);
|
|
368
|
+
if (added < 0) parts.push(`${added}`);
|
|
369
|
+
if (removed > 0) parts.push(`~${removed} changed`);
|
|
370
|
+
|
|
371
|
+
return parts.join(", ") || "no changes";
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Recursively copy a directory
|
|
376
|
+
*/
|
|
377
|
+
export async function copyDirectory(src: string, dest: string): Promise<void> {
|
|
378
|
+
await fs.promises.mkdir(dest, { recursive: true });
|
|
379
|
+
|
|
380
|
+
const entries = await fs.promises.readdir(src, { withFileTypes: true });
|
|
381
|
+
|
|
382
|
+
for (const entry of entries) {
|
|
383
|
+
const srcPath = path.join(src, entry.name);
|
|
384
|
+
const destPath = path.join(dest, entry.name);
|
|
385
|
+
|
|
386
|
+
if (entry.isDirectory()) {
|
|
387
|
+
await copyDirectory(srcPath, destPath);
|
|
388
|
+
} else {
|
|
389
|
+
await fs.promises.copyFile(srcPath, destPath);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Remove directory recursively
|
|
396
|
+
*/
|
|
397
|
+
export async function removeDirectory(dirPath: string): Promise<void> {
|
|
398
|
+
try {
|
|
399
|
+
await fs.promises.rm(dirPath, { recursive: true, force: true });
|
|
400
|
+
} catch {
|
|
401
|
+
// Directory might not exist
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Ensure directory exists
|
|
407
|
+
*/
|
|
408
|
+
export async function ensureDirectory(dirPath: string): Promise<void> {
|
|
409
|
+
await fs.promises.mkdir(dirPath, { recursive: true });
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Find files matching a pattern
|
|
414
|
+
*/
|
|
415
|
+
export async function findFiles(dir: string, pattern: RegExp, results: string[] = []): Promise<string[]> {
|
|
416
|
+
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
|
417
|
+
|
|
418
|
+
for (const entry of entries) {
|
|
419
|
+
const fullPath = path.join(dir, entry.name);
|
|
420
|
+
|
|
421
|
+
if (entry.isDirectory()) {
|
|
422
|
+
await findFiles(fullPath, pattern, results);
|
|
423
|
+
} else if (pattern.test(entry.name)) {
|
|
424
|
+
results.push(fullPath);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return results;
|
|
429
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for Teardown Launchpad
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type { VirtualFileSystem } from "./fs";
|
|
6
|
+
export {
|
|
7
|
+
copyDirectory,
|
|
8
|
+
createVirtualFileSystem,
|
|
9
|
+
ensureDirectory,
|
|
10
|
+
findFiles,
|
|
11
|
+
removeDirectory,
|
|
12
|
+
} from "./fs";
|
|
13
|
+
export type { Logger, LoggerConfig, LogLevel } from "./logger";
|
|
14
|
+
export {
|
|
15
|
+
createLogger,
|
|
16
|
+
defaultLogger,
|
|
17
|
+
formatBytes,
|
|
18
|
+
formatDuration,
|
|
19
|
+
formatKeyValue,
|
|
20
|
+
formatList,
|
|
21
|
+
} from "./logger";
|