diff --git a/.gitignore b/.gitignore
index dd05106..9000ad3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,10 @@
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
# project
-/build
-/webui/dist
+/apps/*/build
+/apps/*/dist
+/packages/*/build
+/packages/*/dist
# test fixtures
*.temp.jsonl
diff --git a/apps/example/.env b/apps/example/.env
new file mode 100644
index 0000000..8b83b8c
--- /dev/null
+++ b/apps/example/.env
@@ -0,0 +1,2 @@
+EXPO_USE_FAST_RESOLVER=true
+EXPO_UNSTABLE_ATLAS=true
diff --git a/apps/example/README.md b/apps/example/README.md
new file mode 100644
index 0000000..cd4feb8
--- /dev/null
+++ b/apps/example/README.md
@@ -0,0 +1,50 @@
+# Welcome to your Expo app 👋
+
+This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
+
+## Get started
+
+1. Install dependencies
+
+ ```bash
+ npm install
+ ```
+
+2. Start the app
+
+ ```bash
+ npx expo start
+ ```
+
+In the output, you'll find options to open the app in a
+
+- [development build](https://docs.expo.dev/develop/development-builds/introduction/)
+- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
+- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
+- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
+
+You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
+
+## Get a fresh project
+
+When you're ready, run:
+
+```bash
+npm run reset-project
+```
+
+This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
+
+## Learn more
+
+To learn more about developing your project with Expo, look at the following resources:
+
+- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
+- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
+
+## Join the community
+
+Join our community of developers creating universal apps.
+
+- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
+- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
diff --git a/apps/example/app.json b/apps/example/app.json
new file mode 100644
index 0000000..e81c20e
--- /dev/null
+++ b/apps/example/app.json
@@ -0,0 +1,36 @@
+{
+ "expo": {
+ "name": "example",
+ "slug": "example",
+ "version": "1.0.0",
+ "orientation": "portrait",
+ "icon": "./assets/images/icon.png",
+ "scheme": "myapp",
+ "userInterfaceStyle": "automatic",
+ "splash": {
+ "image": "./assets/images/splash.png",
+ "resizeMode": "contain",
+ "backgroundColor": "#ffffff"
+ },
+ "ios": {
+ "supportsTablet": true
+ },
+ "android": {
+ "adaptiveIcon": {
+ "foregroundImage": "./assets/images/adaptive-icon.png",
+ "backgroundColor": "#ffffff"
+ }
+ },
+ "web": {
+ "bundler": "metro",
+ "output": "static",
+ "favicon": "./assets/images/favicon.png"
+ },
+ "plugins": [
+ "expo-router"
+ ],
+ "experiments": {
+ "typedRoutes": true
+ }
+ }
+}
diff --git a/apps/example/app/(tabs)/_layout.tsx b/apps/example/app/(tabs)/_layout.tsx
new file mode 100644
index 0000000..22a49b6
--- /dev/null
+++ b/apps/example/app/(tabs)/_layout.tsx
@@ -0,0 +1,37 @@
+import { Tabs } from 'expo-router';
+import React from 'react';
+
+import { TabBarIcon } from '@/components/navigation/TabBarIcon';
+import { Colors } from '@/constants/Colors';
+import { useColorScheme } from '@/hooks/useColorScheme';
+
+export default function TabLayout() {
+ const colorScheme = useColorScheme();
+
+ return (
+
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+
+ );
+}
diff --git a/apps/example/app/(tabs)/explore.tsx b/apps/example/app/(tabs)/explore.tsx
new file mode 100644
index 0000000..e480218
--- /dev/null
+++ b/apps/example/app/(tabs)/explore.tsx
@@ -0,0 +1,102 @@
+import Ionicons from '@expo/vector-icons/Ionicons';
+import { StyleSheet, Image, Platform } from 'react-native';
+
+import { Collapsible } from '@/components/Collapsible';
+import { ExternalLink } from '@/components/ExternalLink';
+import ParallaxScrollView from '@/components/ParallaxScrollView';
+import { ThemedText } from '@/components/ThemedText';
+import { ThemedView } from '@/components/ThemedView';
+
+export default function TabTwoScreen() {
+ return (
+ }>
+
+ Explore
+
+ This app includes example code to help you get started.
+
+
+ This app has two screens:{' '}
+ app/(tabs)/index.tsx and{' '}
+ app/(tabs)/explore.tsx
+
+
+ The layout file in app/(tabs)/_layout.tsx{' '}
+ sets up the tab navigator.
+
+
+ Learn more
+
+
+
+
+ You can open this project on Android, iOS, and the web. To open the web version, press{' '}
+ w in the terminal running this project.
+
+
+
+
+ For static images, you can use the @2x and{' '}
+ @3x suffixes to provide files for
+ different screen densities
+
+
+
+ Learn more
+
+
+
+
+ Open app/_layout.tsx to see how to load{' '}
+
+ custom fonts such as this one.
+
+
+
+ Learn more
+
+
+
+
+ This template has light and dark mode support. The{' '}
+ useColorScheme() hook lets you inspect
+ what the user's current color scheme is, and so you can adjust UI colors accordingly.
+
+
+ Learn more
+
+
+
+
+ This template includes an example of an animated component. The{' '}
+ components/HelloWave.tsx component uses
+ the powerful react-native-reanimated library
+ to create a waving hand animation.
+
+ {Platform.select({
+ ios: (
+
+ The components/ParallaxScrollView.tsx{' '}
+ component provides a parallax effect for the header image.
+
+ ),
+ })}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ headerImage: {
+ color: '#808080',
+ bottom: -90,
+ left: -35,
+ position: 'absolute',
+ },
+ titleContainer: {
+ flexDirection: 'row',
+ gap: 8,
+ },
+});
diff --git a/apps/example/app/(tabs)/index.tsx b/apps/example/app/(tabs)/index.tsx
new file mode 100644
index 0000000..324aeb7
--- /dev/null
+++ b/apps/example/app/(tabs)/index.tsx
@@ -0,0 +1,70 @@
+import { Image, StyleSheet, Platform } from 'react-native';
+
+import { HelloWave } from '@/components/HelloWave';
+import ParallaxScrollView from '@/components/ParallaxScrollView';
+import { ThemedText } from '@/components/ThemedText';
+import { ThemedView } from '@/components/ThemedView';
+
+export default function HomeScreen() {
+ return (
+
+ }>
+
+ Welcome!
+
+
+
+ Step 1: Try it
+
+ Edit app/(tabs)/index.tsx to see changes.
+ Press{' '}
+
+ {Platform.select({ ios: 'cmd + d', android: 'cmd + m' })}
+ {' '}
+ to open developer tools.
+
+
+
+ Step 2: Explore
+
+ Tap the Explore tab to learn more about what's included in this starter app.
+
+
+
+ Step 3: Get a fresh start
+
+ When you're ready, run{' '}
+ npm run reset-project to get a fresh{' '}
+ app directory. This will move the current{' '}
+ app to{' '}
+ app-example.
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ titleContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 8,
+ },
+ stepContainer: {
+ gap: 8,
+ marginBottom: 8,
+ },
+ reactLogo: {
+ height: 178,
+ width: 290,
+ bottom: 0,
+ left: 0,
+ position: 'absolute',
+ },
+});
diff --git a/apps/example/app/+html.tsx b/apps/example/app/+html.tsx
new file mode 100644
index 0000000..8b92456
--- /dev/null
+++ b/apps/example/app/+html.tsx
@@ -0,0 +1,39 @@
+import { ScrollViewStyleReset } from 'expo-router/html';
+import { type PropsWithChildren } from 'react';
+
+/**
+ * This file is web-only and used to configure the root HTML for every web page during static rendering.
+ * The contents of this function only run in Node.js environments and do not have access to the DOM or browser APIs.
+ */
+export default function Root({ children }: PropsWithChildren) {
+ return (
+
+
+
+
+
+
+ {/*
+ Disable body scrolling on web. This makes ScrollView components work closer to how they do on native.
+ However, body scrolling is often nice to have for mobile web. If you want to enable it, remove this line.
+ */}
+
+
+ {/* Using raw CSS styles as an escape-hatch to ensure the background color never flickers in dark-mode. */}
+
+ {/* Add any additional elements that you want globally available on web... */}
+
+ {children}
+
+ );
+}
+
+const responsiveBackground = `
+body {
+ background-color: #fff;
+}
+@media (prefers-color-scheme: dark) {
+ body {
+ background-color: #000;
+ }
+}`;
diff --git a/apps/example/app/+not-found.tsx b/apps/example/app/+not-found.tsx
new file mode 100644
index 0000000..963b04f
--- /dev/null
+++ b/apps/example/app/+not-found.tsx
@@ -0,0 +1,32 @@
+import { Link, Stack } from 'expo-router';
+import { StyleSheet } from 'react-native';
+
+import { ThemedText } from '@/components/ThemedText';
+import { ThemedView } from '@/components/ThemedView';
+
+export default function NotFoundScreen() {
+ return (
+ <>
+
+
+ This screen doesn't exist.
+
+ Go to home screen!
+
+
+ >
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ padding: 20,
+ },
+ link: {
+ marginTop: 15,
+ paddingVertical: 15,
+ },
+});
diff --git a/apps/example/app/_layout.tsx b/apps/example/app/_layout.tsx
new file mode 100644
index 0000000..2e37cdd
--- /dev/null
+++ b/apps/example/app/_layout.tsx
@@ -0,0 +1,37 @@
+import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
+import { useFonts } from 'expo-font';
+import { Stack } from 'expo-router';
+import * as SplashScreen from 'expo-splash-screen';
+import { useEffect } from 'react';
+import 'react-native-reanimated';
+
+import { useColorScheme } from '@/hooks/useColorScheme';
+
+// Prevent the splash screen from auto-hiding before asset loading is complete.
+SplashScreen.preventAutoHideAsync();
+
+export default function RootLayout() {
+ const colorScheme = useColorScheme();
+ const [loaded] = useFonts({
+ SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
+ });
+
+ useEffect(() => {
+ if (loaded) {
+ SplashScreen.hideAsync();
+ }
+ }, [loaded]);
+
+ if (!loaded) {
+ return null;
+ }
+
+ return (
+
+
+
+
+
+
+ );
+}
diff --git a/apps/example/assets/fonts/SpaceMono-Regular.ttf b/apps/example/assets/fonts/SpaceMono-Regular.ttf
new file mode 100755
index 0000000..28d7ff7
Binary files /dev/null and b/apps/example/assets/fonts/SpaceMono-Regular.ttf differ
diff --git a/apps/example/assets/images/adaptive-icon.png b/apps/example/assets/images/adaptive-icon.png
new file mode 100644
index 0000000..03d6f6b
Binary files /dev/null and b/apps/example/assets/images/adaptive-icon.png differ
diff --git a/apps/example/assets/images/favicon.png b/apps/example/assets/images/favicon.png
new file mode 100644
index 0000000..e75f697
Binary files /dev/null and b/apps/example/assets/images/favicon.png differ
diff --git a/apps/example/assets/images/icon.png b/apps/example/assets/images/icon.png
new file mode 100644
index 0000000..a0b1526
Binary files /dev/null and b/apps/example/assets/images/icon.png differ
diff --git a/apps/example/assets/images/partial-react-logo.png b/apps/example/assets/images/partial-react-logo.png
new file mode 100644
index 0000000..66fd957
Binary files /dev/null and b/apps/example/assets/images/partial-react-logo.png differ
diff --git a/apps/example/assets/images/react-logo.png b/apps/example/assets/images/react-logo.png
new file mode 100644
index 0000000..9d72a9f
Binary files /dev/null and b/apps/example/assets/images/react-logo.png differ
diff --git a/apps/example/assets/images/react-logo@2x.png b/apps/example/assets/images/react-logo@2x.png
new file mode 100644
index 0000000..2229b13
Binary files /dev/null and b/apps/example/assets/images/react-logo@2x.png differ
diff --git a/apps/example/assets/images/react-logo@3x.png b/apps/example/assets/images/react-logo@3x.png
new file mode 100644
index 0000000..a99b203
Binary files /dev/null and b/apps/example/assets/images/react-logo@3x.png differ
diff --git a/apps/example/assets/images/splash.png b/apps/example/assets/images/splash.png
new file mode 100644
index 0000000..0e89705
Binary files /dev/null and b/apps/example/assets/images/splash.png differ
diff --git a/apps/example/babel.config.js b/apps/example/babel.config.js
new file mode 100644
index 0000000..9d89e13
--- /dev/null
+++ b/apps/example/babel.config.js
@@ -0,0 +1,6 @@
+module.exports = function (api) {
+ api.cache(true);
+ return {
+ presets: ['babel-preset-expo'],
+ };
+};
diff --git a/apps/example/components/Collapsible.tsx b/apps/example/components/Collapsible.tsx
new file mode 100644
index 0000000..c326473
--- /dev/null
+++ b/apps/example/components/Collapsible.tsx
@@ -0,0 +1,41 @@
+import Ionicons from '@expo/vector-icons/Ionicons';
+import { PropsWithChildren, useState } from 'react';
+import { StyleSheet, TouchableOpacity, useColorScheme } from 'react-native';
+
+import { ThemedText } from '@/components/ThemedText';
+import { ThemedView } from '@/components/ThemedView';
+import { Colors } from '@/constants/Colors';
+
+export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
+ const [isOpen, setIsOpen] = useState(false);
+ const theme = useColorScheme() ?? 'light';
+
+ return (
+
+ setIsOpen((value) => !value)}
+ activeOpacity={0.8}>
+
+ {title}
+
+ {isOpen && {children}}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ heading: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 6,
+ },
+ content: {
+ marginTop: 6,
+ marginLeft: 24,
+ },
+});
diff --git a/apps/example/components/ExternalLink.tsx b/apps/example/components/ExternalLink.tsx
new file mode 100644
index 0000000..8f05675
--- /dev/null
+++ b/apps/example/components/ExternalLink.tsx
@@ -0,0 +1,24 @@
+import { Link } from 'expo-router';
+import { openBrowserAsync } from 'expo-web-browser';
+import { type ComponentProps } from 'react';
+import { Platform } from 'react-native';
+
+type Props = Omit, 'href'> & { href: string };
+
+export function ExternalLink({ href, ...rest }: Props) {
+ return (
+ {
+ if (Platform.OS !== 'web') {
+ // Prevent the default behavior of linking to the default browser on native.
+ event.preventDefault();
+ // Open the link in an in-app browser.
+ await openBrowserAsync(href);
+ }
+ }}
+ />
+ );
+}
diff --git a/apps/example/components/HelloWave.tsx b/apps/example/components/HelloWave.tsx
new file mode 100644
index 0000000..f4b6ea5
--- /dev/null
+++ b/apps/example/components/HelloWave.tsx
@@ -0,0 +1,37 @@
+import { StyleSheet } from 'react-native';
+import Animated, {
+ useSharedValue,
+ useAnimatedStyle,
+ withTiming,
+ withRepeat,
+ withSequence,
+} from 'react-native-reanimated';
+
+import { ThemedText } from '@/components/ThemedText';
+
+export function HelloWave() {
+ const rotationAnimation = useSharedValue(0);
+
+ rotationAnimation.value = withRepeat(
+ withSequence(withTiming(25, { duration: 150 }), withTiming(0, { duration: 150 })),
+ 4 // Run the animation 4 times
+ );
+
+ const animatedStyle = useAnimatedStyle(() => ({
+ transform: [{ rotate: `${rotationAnimation.value}deg` }],
+ }));
+
+ return (
+
+ 👋
+
+ );
+}
+
+const styles = StyleSheet.create({
+ text: {
+ fontSize: 28,
+ lineHeight: 32,
+ marginTop: -6,
+ },
+});
diff --git a/apps/example/components/ParallaxScrollView.tsx b/apps/example/components/ParallaxScrollView.tsx
new file mode 100644
index 0000000..0a35419
--- /dev/null
+++ b/apps/example/components/ParallaxScrollView.tsx
@@ -0,0 +1,76 @@
+import type { PropsWithChildren, ReactElement } from 'react';
+import { StyleSheet, useColorScheme } from 'react-native';
+import Animated, {
+ interpolate,
+ useAnimatedRef,
+ useAnimatedStyle,
+ useScrollViewOffset,
+} from 'react-native-reanimated';
+
+import { ThemedView } from '@/components/ThemedView';
+
+const HEADER_HEIGHT = 250;
+
+type Props = PropsWithChildren<{
+ headerImage: ReactElement;
+ headerBackgroundColor: { dark: string; light: string };
+}>;
+
+export default function ParallaxScrollView({
+ children,
+ headerImage,
+ headerBackgroundColor,
+}: Props) {
+ const colorScheme = useColorScheme() ?? 'light';
+ const scrollRef = useAnimatedRef();
+ const scrollOffset = useScrollViewOffset(scrollRef);
+
+ const headerAnimatedStyle = useAnimatedStyle(() => {
+ return {
+ transform: [
+ {
+ translateY: interpolate(
+ scrollOffset.value,
+ [-HEADER_HEIGHT, 0, HEADER_HEIGHT],
+ [-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75]
+ ),
+ },
+ {
+ scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]),
+ },
+ ],
+ };
+ });
+
+ return (
+
+
+
+ {headerImage}
+
+ {children}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ header: {
+ height: 250,
+ overflow: 'hidden',
+ },
+ content: {
+ flex: 1,
+ padding: 32,
+ gap: 16,
+ overflow: 'hidden',
+ },
+});
diff --git a/apps/example/components/ThemedText.tsx b/apps/example/components/ThemedText.tsx
new file mode 100644
index 0000000..c0e1a78
--- /dev/null
+++ b/apps/example/components/ThemedText.tsx
@@ -0,0 +1,60 @@
+import { Text, type TextProps, StyleSheet } from 'react-native';
+
+import { useThemeColor } from '@/hooks/useThemeColor';
+
+export type ThemedTextProps = TextProps & {
+ lightColor?: string;
+ darkColor?: string;
+ type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link';
+};
+
+export function ThemedText({
+ style,
+ lightColor,
+ darkColor,
+ type = 'default',
+ ...rest
+}: ThemedTextProps) {
+ const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
+
+ return (
+
+ );
+}
+
+const styles = StyleSheet.create({
+ default: {
+ fontSize: 16,
+ lineHeight: 24,
+ },
+ defaultSemiBold: {
+ fontSize: 16,
+ lineHeight: 24,
+ fontWeight: '600',
+ },
+ title: {
+ fontSize: 32,
+ fontWeight: 'bold',
+ lineHeight: 32,
+ },
+ subtitle: {
+ fontSize: 20,
+ fontWeight: 'bold',
+ },
+ link: {
+ lineHeight: 30,
+ fontSize: 16,
+ color: '#0a7ea4',
+ },
+});
diff --git a/apps/example/components/ThemedView.tsx b/apps/example/components/ThemedView.tsx
new file mode 100644
index 0000000..4d2cb09
--- /dev/null
+++ b/apps/example/components/ThemedView.tsx
@@ -0,0 +1,14 @@
+import { View, type ViewProps } from 'react-native';
+
+import { useThemeColor } from '@/hooks/useThemeColor';
+
+export type ThemedViewProps = ViewProps & {
+ lightColor?: string;
+ darkColor?: string;
+};
+
+export function ThemedView({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) {
+ const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
+
+ return ;
+}
diff --git a/apps/example/components/__tests__/ThemedText-test.tsx b/apps/example/components/__tests__/ThemedText-test.tsx
new file mode 100644
index 0000000..1ac3225
--- /dev/null
+++ b/apps/example/components/__tests__/ThemedText-test.tsx
@@ -0,0 +1,10 @@
+import * as React from 'react';
+import renderer from 'react-test-renderer';
+
+import { ThemedText } from '../ThemedText';
+
+it(`renders correctly`, () => {
+ const tree = renderer.create(Snapshot test!).toJSON();
+
+ expect(tree).toMatchSnapshot();
+});
diff --git a/apps/example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap b/apps/example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap
new file mode 100644
index 0000000..b68e53e
--- /dev/null
+++ b/apps/example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap
@@ -0,0 +1,24 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders correctly 1`] = `
+
+ Snapshot test!
+
+`;
diff --git a/apps/example/components/navigation/TabBarIcon.tsx b/apps/example/components/navigation/TabBarIcon.tsx
new file mode 100644
index 0000000..b7302c3
--- /dev/null
+++ b/apps/example/components/navigation/TabBarIcon.tsx
@@ -0,0 +1,9 @@
+// You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/
+
+import Ionicons from '@expo/vector-icons/Ionicons';
+import { type IconProps } from '@expo/vector-icons/build/createIconSet';
+import { type ComponentProps } from 'react';
+
+export function TabBarIcon({ style, ...rest }: IconProps['name']>) {
+ return ;
+}
diff --git a/apps/example/constants/Colors.ts b/apps/example/constants/Colors.ts
new file mode 100644
index 0000000..14e6784
--- /dev/null
+++ b/apps/example/constants/Colors.ts
@@ -0,0 +1,26 @@
+/**
+ * Below are the colors that are used in the app. The colors are defined in the light and dark mode.
+ * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc.
+ */
+
+const tintColorLight = '#0a7ea4';
+const tintColorDark = '#fff';
+
+export const Colors = {
+ light: {
+ text: '#11181C',
+ background: '#fff',
+ tint: tintColorLight,
+ icon: '#687076',
+ tabIconDefault: '#687076',
+ tabIconSelected: tintColorLight,
+ },
+ dark: {
+ text: '#ECEDEE',
+ background: '#151718',
+ tint: tintColorDark,
+ icon: '#9BA1A6',
+ tabIconDefault: '#9BA1A6',
+ tabIconSelected: tintColorDark,
+ },
+};
diff --git a/apps/example/hooks/useColorScheme.ts b/apps/example/hooks/useColorScheme.ts
new file mode 100644
index 0000000..17e3c63
--- /dev/null
+++ b/apps/example/hooks/useColorScheme.ts
@@ -0,0 +1 @@
+export { useColorScheme } from 'react-native';
diff --git a/apps/example/hooks/useColorScheme.web.ts b/apps/example/hooks/useColorScheme.web.ts
new file mode 100644
index 0000000..6dcd80d
--- /dev/null
+++ b/apps/example/hooks/useColorScheme.web.ts
@@ -0,0 +1,8 @@
+// NOTE: The default React Native styling doesn't support server rendering.
+// Server rendered styles should not change between the first render of the HTML
+// and the first render on the client. Typically, web developers will use CSS media queries
+// to render different styles on the client and server, these aren't directly supported in React Native
+// but can be achieved using a styling library like Nativewind.
+export function useColorScheme() {
+ return 'light';
+}
diff --git a/apps/example/hooks/useThemeColor.ts b/apps/example/hooks/useThemeColor.ts
new file mode 100644
index 0000000..ae43b47
--- /dev/null
+++ b/apps/example/hooks/useThemeColor.ts
@@ -0,0 +1,22 @@
+/**
+ * Learn more about light and dark modes:
+ * https://docs.expo.dev/guides/color-schemes/
+ */
+
+import { useColorScheme } from 'react-native';
+
+import { Colors } from '@/constants/Colors';
+
+export function useThemeColor(
+ props: { light?: string; dark?: string },
+ colorName: keyof typeof Colors.light & keyof typeof Colors.dark
+) {
+ const theme = useColorScheme() ?? 'light';
+ const colorFromProps = props[theme];
+
+ if (colorFromProps) {
+ return colorFromProps;
+ } else {
+ return Colors[theme][colorName];
+ }
+}
diff --git a/apps/example/package.json b/apps/example/package.json
new file mode 100644
index 0000000..d410ca3
--- /dev/null
+++ b/apps/example/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "expo-atlas-example",
+ "main": "expo-router/entry",
+ "version": "1.0.0",
+ "scripts": {
+ "start": "expo start",
+ "android": "expo start --android",
+ "ios": "expo start --ios",
+ "web": "expo start --web",
+ "test": "jest --watchAll",
+ "lint": "expo lint"
+ },
+ "jest": {
+ "preset": "jest-expo"
+ },
+ "dependencies": {
+ "@expo/vector-icons": "^14.0.2",
+ "@react-navigation/native": "^6.0.2",
+ "expo": "~51.0.28",
+ "expo-atlas": "workspace:*",
+ "expo-constants": "~16.0.2",
+ "expo-font": "~12.0.9",
+ "expo-linking": "~6.3.1",
+ "expo-router": "~3.5.23",
+ "expo-splash-screen": "~0.27.5",
+ "expo-status-bar": "~1.12.1",
+ "expo-system-ui": "~3.0.7",
+ "expo-web-browser": "~13.0.3",
+ "react": "18.2.0",
+ "react-dom": "18.2.0",
+ "react-native": "0.74.5",
+ "react-native-gesture-handler": "~2.16.1",
+ "react-native-reanimated": "~3.10.1",
+ "react-native-safe-area-context": "4.10.5",
+ "react-native-screens": "3.31.1",
+ "react-native-web": "~0.19.10"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.20.0",
+ "@types/jest": "^29.5.12",
+ "@types/react": "~18.2.45",
+ "@types/react-test-renderer": "^18.0.7",
+ "jest": "^29.2.1",
+ "jest-expo": "~51.0.3",
+ "react-test-renderer": "18.2.0",
+ "typescript": "~5.3.3"
+ },
+ "private": true
+}
diff --git a/apps/example/tsconfig.json b/apps/example/tsconfig.json
new file mode 100644
index 0000000..909e901
--- /dev/null
+++ b/apps/example/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "extends": "expo/tsconfig.base",
+ "compilerOptions": {
+ "strict": true,
+ "paths": {
+ "@/*": [
+ "./*"
+ ]
+ }
+ },
+ "include": [
+ "**/*.ts",
+ "**/*.tsx",
+ ".expo/types/**/*.ts",
+ "expo-env.d.ts"
+ ]
+}
diff --git a/bun.lockb b/bun.lockb
index d05adb6..8a2412d 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index 42a909a..ee6ce89 100644
--- a/package.json
+++ b/package.json
@@ -1,145 +1,15 @@
{
- "sideEffects": false,
- "name": "expo-atlas",
- "version": "0.3.13",
- "description": "Inspect bundle contents, on module level, from Metro",
- "keywords": [
- "expo",
- "atlas",
- "devtools"
+ "private": true,
+ "name": "expo-atlas-monorepo",
+ "version": "0.0.0",
+ "workspaces": [
+ "apps/*",
+ "packages/*"
],
- "bin": "build/src/cli/bin.js",
- "main": "build/src/index.js",
- "types": "build/src/index.d.ts",
- "files": [
- "build",
- "!build/tsconfig.tsbuildinfo",
- "expo-module.config.json",
- "cli.js",
- "cli.d.ts",
- "metro.js",
- "metro.d.ts",
- "static",
- "webui/dist"
- ],
- "homepage": "https://github.com/expo/expo-atlas",
- "bugs": {
- "url": "https://github.com/expo/expo-atlas/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/expo/expo-atlas"
- },
- "scripts": {
- "build": "expo-module build",
- "clean": "expo-module clean",
- "lint": "eslint . --ext js,ts,tsx",
- "typecheck": "expo-module typecheck"
- },
- "license": "MIT",
"dependencies": {
- "@expo/server": "^0.4.2",
- "arg": "^5.0.2",
- "chalk": "^4.1.2",
- "compression": "^1.7.4",
- "connect": "^3.7.0",
- "express": "^4.18.2",
- "freeport-async": "^2.0.0",
- "getenv": "^1.0.0",
- "morgan": "^1.10.0",
- "open": "^8.4.2",
- "serve-static": "^1.15.0",
- "stream-json": "^1.8.0"
- },
- "devDependencies": {
- "@types/bun": "^1.0.8",
- "@types/chai": "^4",
- "@types/express": "^4.17.21",
- "@types/node": "^20.11.26",
- "@types/stream-json": "^1.7.7",
- "chai": "^4.3.10",
"eslint": "^8.57.0",
- "eslint-config-universe": "^12.0.0",
- "expo": "~50.0.1",
- "expo-module-scripts": "^3.1.0",
- "metro": "^0.80.6",
- "prettier": "^3.2.5",
- "typescript": "^5.1.3"
- },
- "peerDependencies": {
- "expo": "*"
- },
- "eslintConfig": {
- "extends": "universe",
- "ignorePatterns": [
- "build",
- "dist",
- "node_modules",
- "webui/expo-env.d.ts"
- ],
- "rules": {
- "@typescript-eslint/no-unused-vars": [
- "warn",
- {
- "args": "all",
- "argsIgnorePattern": "^_",
- "caughtErrors": "all",
- "caughtErrorsIgnorePattern": "^_",
- "destructuredArrayIgnorePattern": "^_",
- "varsIgnorePattern": "^_",
- "ignoreRestSiblings": true
- }
- ]
- },
- "overrides": [
- {
- "files": [
- "webui/src/app/**/*.ts",
- "!webui/src/app/**/*+api.ts"
- ],
- "extends": [
- "universe/web"
- ],
- "rules": {
- "@typescript-eslint/no-unused-vars": [
- "warn",
- {
- "args": "all",
- "argsIgnorePattern": "^_",
- "caughtErrors": "all",
- "caughtErrorsIgnorePattern": "^_",
- "destructuredArrayIgnorePattern": "^_",
- "varsIgnorePattern": "^_",
- "ignoreRestSiblings": true
- }
- ]
- }
- },
- {
- "files": [
- "metro.config.js",
- "babel.config.js",
- "webui/src/app/**/*+api.ts"
- ],
- "extends": [
- "universe/node"
- ],
- "rules": {
- "@typescript-eslint/no-unused-vars": [
- "warn",
- {
- "args": "all",
- "argsIgnorePattern": "^_",
- "caughtErrors": "all",
- "caughtErrorsIgnorePattern": "^_",
- "destructuredArrayIgnorePattern": "^_",
- "varsIgnorePattern": "^_",
- "ignoreRestSiblings": true
- }
- ]
- }
- }
- ]
+ "eslint-config-universe": "^13.0.0",
+ "expo-module-scripts": "^3.5.2"
},
"prettier": {
"printWidth": 100,
diff --git a/packages/expo-atlas-ui/.env b/packages/expo-atlas-ui/.env
new file mode 100644
index 0000000..5e77997
--- /dev/null
+++ b/packages/expo-atlas-ui/.env
@@ -0,0 +1 @@
+EXPO_USE_FAST_RESOLVER=true
diff --git a/webui/.gitattributes b/packages/expo-atlas-ui/.gitattributes
similarity index 100%
rename from webui/.gitattributes
rename to packages/expo-atlas-ui/.gitattributes
diff --git a/webui/.gitignore b/packages/expo-atlas-ui/.gitignore
similarity index 100%
rename from webui/.gitignore
rename to packages/expo-atlas-ui/.gitignore
diff --git a/webui/app.json b/packages/expo-atlas-ui/app.json
similarity index 100%
rename from webui/app.json
rename to packages/expo-atlas-ui/app.json
diff --git a/webui/babel.config.js b/packages/expo-atlas-ui/babel.config.js
similarity index 100%
rename from webui/babel.config.js
rename to packages/expo-atlas-ui/babel.config.js
diff --git a/webui/fixture/expo-51-default-windows.jsonl b/packages/expo-atlas-ui/fixture/expo-51-default-windows.jsonl
similarity index 100%
rename from webui/fixture/expo-51-default-windows.jsonl
rename to packages/expo-atlas-ui/fixture/expo-51-default-windows.jsonl
diff --git a/webui/fixture/expo-51-default.jsonl b/packages/expo-atlas-ui/fixture/expo-51-default.jsonl
similarity index 100%
rename from webui/fixture/expo-51-default.jsonl
rename to packages/expo-atlas-ui/fixture/expo-51-default.jsonl
diff --git a/webui/metro.config.js b/packages/expo-atlas-ui/metro.config.js
similarity index 100%
rename from webui/metro.config.js
rename to packages/expo-atlas-ui/metro.config.js
diff --git a/packages/expo-atlas-ui/package.json b/packages/expo-atlas-ui/package.json
new file mode 100644
index 0000000..ab11469
--- /dev/null
+++ b/packages/expo-atlas-ui/package.json
@@ -0,0 +1,130 @@
+{
+ "private": true,
+ "name": "expo-atlas-ui",
+ "version": "0.0.1-private",
+ "main": "src/index.ts",
+ "scripts": {
+ "start": "expo start",
+ "android": "expo start --android",
+ "ios": "expo start --ios",
+ "web": "expo start --web",
+ "build": "expo export --platform web",
+ "typecheck": "expo-module typecheck",
+ "production": "EXPO_ATLAS_NO_VALIDATION=true node ../build/src/cli/bin.js ./fixture/atlas-tabs-50.jsonl",
+ "lint": "eslint . --ext js,ts,tsx"
+ },
+ "dependencies": {
+ "@expo/styleguide": "^8.2.2",
+ "@expo/styleguide-native": "^7.0.1",
+ "@radix-ui/react-checkbox": "^1.0.4",
+ "@radix-ui/react-collapsible": "^1.0.3",
+ "@radix-ui/react-context-menu": "^2.2.1",
+ "@radix-ui/react-dialog": "^1.0.5",
+ "@radix-ui/react-label": "^2.0.2",
+ "@radix-ui/react-select": "^2.0.0",
+ "@radix-ui/react-toast": "^1.1.5",
+ "@radix-ui/react-tooltip": "^1.1.2",
+ "@tailwindcss/typography": "^0.5.10",
+ "@tanstack/react-query": "^5.22.2",
+ "class-variance-authority": "^0.7.0",
+ "echarts": "^5.5.0",
+ "echarts-for-react": "^3.0.2",
+ "expo": "~51.0.8",
+ "expo-atlas": "workspace:*",
+ "expo-linking": "~6.3.1",
+ "expo-router": "~3.5.14",
+ "expo-status-bar": "~1.12.1",
+ "lucide-react": "^0.336.0",
+ "nativewind": "^4.0.36",
+ "picomatch": "^4.0.1",
+ "prettier": "^3.2.5",
+ "react": "18.2.0",
+ "react-dom": "18.2.0",
+ "react-native": "0.74.1",
+ "react-native-reanimated": "~3.10.1",
+ "react-native-safe-area-context": "4.10.1",
+ "react-native-svg": "15.2.0",
+ "react-native-web": "~0.19.6",
+ "shiki": "^1.2.4",
+ "tailwind-gradient-mask-image": "^1.2.0",
+ "tailwindcss": "^3.4.1",
+ "tailwindcss-animate": "^1.0.7"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.20.0",
+ "@types/picomatch": "^2.3.3",
+ "@types/react": "~18.2.79",
+ "typescript": "~5.3.3"
+ },
+ "eslintConfig": {
+ "extends": "universe",
+ "ignorePatterns": [
+ "build",
+ "dist",
+ "node_modules",
+ "expo-env.d.ts"
+ ],
+ "rules": {
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ {
+ "args": "all",
+ "argsIgnorePattern": "^_",
+ "caughtErrors": "all",
+ "caughtErrorsIgnorePattern": "^_",
+ "destructuredArrayIgnorePattern": "^_",
+ "varsIgnorePattern": "^_",
+ "ignoreRestSiblings": true
+ }
+ ]
+ },
+ "overrides": [
+ {
+ "files": [
+ "src/app/**/*.ts",
+ "!src/app/**/*+api.ts"
+ ],
+ "extends": [
+ "universe/web"
+ ],
+ "rules": {
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ {
+ "args": "all",
+ "argsIgnorePattern": "^_",
+ "caughtErrors": "all",
+ "caughtErrorsIgnorePattern": "^_",
+ "destructuredArrayIgnorePattern": "^_",
+ "varsIgnorePattern": "^_",
+ "ignoreRestSiblings": true
+ }
+ ]
+ }
+ },
+ {
+ "files": [
+ "*.config.js",
+ "webui/src/app/**/*+api.ts"
+ ],
+ "extends": [
+ "universe/node"
+ ],
+ "rules": {
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ {
+ "args": "all",
+ "argsIgnorePattern": "^_",
+ "caughtErrors": "all",
+ "caughtErrorsIgnorePattern": "^_",
+ "destructuredArrayIgnorePattern": "^_",
+ "varsIgnorePattern": "^_",
+ "ignoreRestSiblings": true
+ }
+ ]
+ }
+ }
+ ]
+ }
+}
diff --git a/webui/src/app/(atlas)/[bundle].tsx b/packages/expo-atlas-ui/src/app/(atlas)/[bundle].tsx
similarity index 100%
rename from webui/src/app/(atlas)/[bundle].tsx
rename to packages/expo-atlas-ui/src/app/(atlas)/[bundle].tsx
diff --git a/webui/src/app/(atlas)/[bundle]/folders/[path].tsx b/packages/expo-atlas-ui/src/app/(atlas)/[bundle]/folders/[path].tsx
similarity index 100%
rename from webui/src/app/(atlas)/[bundle]/folders/[path].tsx
rename to packages/expo-atlas-ui/src/app/(atlas)/[bundle]/folders/[path].tsx
diff --git a/webui/src/app/(atlas)/[bundle]/modules/[path].tsx b/packages/expo-atlas-ui/src/app/(atlas)/[bundle]/modules/[path].tsx
similarity index 98%
rename from webui/src/app/(atlas)/[bundle]/modules/[path].tsx
rename to packages/expo-atlas-ui/src/app/(atlas)/[bundle]/modules/[path].tsx
index d0b02cb..9bfe356 100644
--- a/webui/src/app/(atlas)/[bundle]/modules/[path].tsx
+++ b/packages/expo-atlas-ui/src/app/(atlas)/[bundle]/modules/[path].tsx
@@ -1,4 +1,5 @@
import { keepPreviousData, useQuery } from '@tanstack/react-query';
+import type { AtlasModule } from 'expo-atlas';
import { useLocalSearchParams } from 'expo-router';
import { BreadcrumbLinks } from '~/components/BreadcrumbLinks';
@@ -13,7 +14,6 @@ import { useBundle } from '~/providers/bundle';
import { Layout, LayoutHeader, LayoutNavigation, LayoutTitle } from '~/ui/Layout';
import { Skeleton } from '~/ui/Skeleton';
import { fetchApi, handleApiError } from '~/utils/api';
-import { type AtlasModule } from '~core/data/types';
export default function ModulePage() {
const { bundle } = useBundle();
diff --git a/webui/src/app/+html.tsx b/packages/expo-atlas-ui/src/app/+html.tsx
similarity index 100%
rename from webui/src/app/+html.tsx
rename to packages/expo-atlas-ui/src/app/+html.tsx
diff --git a/webui/src/app/--/bundles/[bundle]/hmr+api.ts b/packages/expo-atlas-ui/src/app/--/bundles/[bundle]/hmr+api.ts
similarity index 100%
rename from webui/src/app/--/bundles/[bundle]/hmr+api.ts
rename to packages/expo-atlas-ui/src/app/--/bundles/[bundle]/hmr+api.ts
diff --git a/webui/src/app/--/bundles/[bundle]/index+api.ts b/packages/expo-atlas-ui/src/app/--/bundles/[bundle]/index+api.ts
similarity index 100%
rename from webui/src/app/--/bundles/[bundle]/index+api.ts
rename to packages/expo-atlas-ui/src/app/--/bundles/[bundle]/index+api.ts
diff --git a/webui/src/app/--/bundles/[bundle]/modules/graph+api.ts b/packages/expo-atlas-ui/src/app/--/bundles/[bundle]/modules/graph+api.ts
similarity index 96%
rename from webui/src/app/--/bundles/[bundle]/modules/graph+api.ts
rename to packages/expo-atlas-ui/src/app/--/bundles/[bundle]/modules/graph+api.ts
index 1423b34..8cb180a 100644
--- a/webui/src/app/--/bundles/[bundle]/modules/graph+api.ts
+++ b/packages/expo-atlas-ui/src/app/--/bundles/[bundle]/modules/graph+api.ts
@@ -1,7 +1,8 @@
+import type { AtlasBundle } from 'expo-atlas';
+
import { getSource } from '~/utils/atlas';
import { filterModules, moduleFiltersFromParams } from '~/utils/filters';
import { type TreemapNode, createModuleTree, finalizeModuleTree } from '~/utils/treemap';
-import type { AtlasBundle } from '~core/data/types';
export type ModuleGraphResponse = {
data: TreemapNode;
diff --git a/webui/src/app/--/bundles/[bundle]/modules/index+api.ts b/packages/expo-atlas-ui/src/app/--/bundles/[bundle]/modules/index+api.ts
similarity index 97%
rename from webui/src/app/--/bundles/[bundle]/modules/index+api.ts
rename to packages/expo-atlas-ui/src/app/--/bundles/[bundle]/modules/index+api.ts
index d7b1ef4..2ce338a 100644
--- a/webui/src/app/--/bundles/[bundle]/modules/index+api.ts
+++ b/packages/expo-atlas-ui/src/app/--/bundles/[bundle]/modules/index+api.ts
@@ -1,6 +1,7 @@
+import type { AtlasBundle, AtlasModule } from 'expo-atlas';
+
import { getSource } from '~/utils/atlas';
import { filterModules, moduleFiltersFromParams } from '~/utils/filters';
-import type { AtlasBundle, AtlasModule } from '~core/data/types';
/** The partial module data, when listing all available modules from an entry */
export type PartialModule = Omit;
diff --git a/webui/src/app/--/bundles/[bundle]/reload+api.ts b/packages/expo-atlas-ui/src/app/--/bundles/[bundle]/reload+api.ts
similarity index 100%
rename from webui/src/app/--/bundles/[bundle]/reload+api.ts
rename to packages/expo-atlas-ui/src/app/--/bundles/[bundle]/reload+api.ts
diff --git a/webui/src/app/--/bundles/index+api.ts b/packages/expo-atlas-ui/src/app/--/bundles/index+api.ts
similarity index 100%
rename from webui/src/app/--/bundles/index+api.ts
rename to packages/expo-atlas-ui/src/app/--/bundles/index+api.ts
diff --git a/webui/src/app/--/bundles/reload+api.ts b/packages/expo-atlas-ui/src/app/--/bundles/reload+api.ts
similarity index 96%
rename from webui/src/app/--/bundles/reload+api.ts
rename to packages/expo-atlas-ui/src/app/--/bundles/reload+api.ts
index 33b9d81..5f27e07 100644
--- a/webui/src/app/--/bundles/reload+api.ts
+++ b/packages/expo-atlas-ui/src/app/--/bundles/reload+api.ts
@@ -1,5 +1,6 @@
+import type { AtlasBundle } from 'expo-atlas';
+
import { getSource } from '~/utils/atlas';
-import { AtlasBundle } from '~core/data/types';
export async function POST(_request: Request) {
try {
diff --git a/webui/src/app/_layout.tsx b/packages/expo-atlas-ui/src/app/_layout.tsx
similarity index 100%
rename from webui/src/app/_layout.tsx
rename to packages/expo-atlas-ui/src/app/_layout.tsx
diff --git a/webui/src/app/index.tsx b/packages/expo-atlas-ui/src/app/index.tsx
similarity index 100%
rename from webui/src/app/index.tsx
rename to packages/expo-atlas-ui/src/app/index.tsx
diff --git a/webui/src/components/BreadcrumbLinks.tsx b/packages/expo-atlas-ui/src/components/BreadcrumbLinks.tsx
similarity index 98%
rename from webui/src/components/BreadcrumbLinks.tsx
rename to packages/expo-atlas-ui/src/components/BreadcrumbLinks.tsx
index 4a687f8..4e2c131 100644
--- a/webui/src/components/BreadcrumbLinks.tsx
+++ b/packages/expo-atlas-ui/src/components/BreadcrumbLinks.tsx
@@ -1,3 +1,4 @@
+import type { PartialAtlasBundle } from 'expo-atlas';
import { Link } from 'expo-router';
import { type ComponentProps, Fragment, useMemo } from 'react';
@@ -10,7 +11,6 @@ import {
BreadcrumbPage,
BreadcrumbSeparator,
} from '~/ui/Breadcrumb';
-import { type PartialAtlasBundle } from '~core/data/types';
type BreadcrumbLinksProps = {
/** The current opened bundle, used to generate the proper links */
diff --git a/webui/src/components/BundleGraph.tsx b/packages/expo-atlas-ui/src/components/BundleGraph.tsx
similarity index 99%
rename from webui/src/components/BundleGraph.tsx
rename to packages/expo-atlas-ui/src/components/BundleGraph.tsx
index 4fdc2e9..d9a0c5d 100644
--- a/webui/src/components/BundleGraph.tsx
+++ b/packages/expo-atlas-ui/src/components/BundleGraph.tsx
@@ -5,12 +5,12 @@ import * as echarts from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';
import type { CallbackDataParams, TooltipFormatterCallback } from 'echarts/types/dist/shared';
import EchartsReact from 'echarts-for-react/lib/core';
+import type { PartialAtlasBundle } from 'expo-atlas';
import { useRouter } from 'expo-router';
import { useMemo } from 'react';
import { formatByteSize } from '~/components/FileSize';
import type { TreemapNode } from '~/utils/treemap';
-import type { PartialAtlasBundle } from '~core/data/types';
// Register used echarts components, to avoid loading unused code
echarts.use([TooltipComponent, TitleComponent, TreemapChart, CanvasRenderer]);
diff --git a/webui/src/components/BundleSelectForm.tsx b/packages/expo-atlas-ui/src/components/BundleSelectForm.tsx
similarity index 98%
rename from webui/src/components/BundleSelectForm.tsx
rename to packages/expo-atlas-ui/src/components/BundleSelectForm.tsx
index 2eeeec0..12cb648 100644
--- a/webui/src/components/BundleSelectForm.tsx
+++ b/packages/expo-atlas-ui/src/components/BundleSelectForm.tsx
@@ -1,3 +1,4 @@
+import type { PartialAtlasBundle } from 'expo-atlas';
import { useRouter } from 'expo-router';
import { useMemo } from 'react';
@@ -14,7 +15,6 @@ import {
SelectValue,
} from '~/ui/Select';
import { relativeBundlePath } from '~/utils/bundle';
-import type { PartialAtlasBundle } from '~core/data/types';
export function BundleSelectForm() {
const router = useRouter();
diff --git a/webui/src/components/BundleTag.tsx b/packages/expo-atlas-ui/src/components/BundleTag.tsx
similarity index 98%
rename from webui/src/components/BundleTag.tsx
rename to packages/expo-atlas-ui/src/components/BundleTag.tsx
index f902d3e..6167c45 100644
--- a/webui/src/components/BundleTag.tsx
+++ b/packages/expo-atlas-ui/src/components/BundleTag.tsx
@@ -1,4 +1,5 @@
import { cva, type VariantProps } from 'class-variance-authority';
+import type { AtlasBundle } from 'expo-atlas';
import { type ComponentProps } from 'react';
import { EnvironmentIcon } from '~/components/EnvironmentIcon';
@@ -6,7 +7,6 @@ import { EnvironmentName } from '~/components/EnvironmentName';
import { PlatformName } from '~/components/PlatformName';
import { Tag } from '~/ui/Tag';
import { Tooltip, TooltipContent, TooltipTrigger } from '~/ui/Tooltip';
-import type { AtlasBundle } from '~core/data/types';
const bundleTagVariants = cva('', {
variants: {
diff --git a/webui/src/components/EnvironmentIcon.tsx b/packages/expo-atlas-ui/src/components/EnvironmentIcon.tsx
similarity index 92%
rename from webui/src/components/EnvironmentIcon.tsx
rename to packages/expo-atlas-ui/src/components/EnvironmentIcon.tsx
index 7726be9..d67da9b 100644
--- a/webui/src/components/EnvironmentIcon.tsx
+++ b/packages/expo-atlas-ui/src/components/EnvironmentIcon.tsx
@@ -1,7 +1,6 @@
+import type { AtlasBundle } from 'expo-atlas';
import type { LucideProps } from 'lucide-react';
-import type { AtlasBundle } from '~core/data/types';
-
type EnvironmentIconProps = Omit<
LucideProps & {
environment: AtlasBundle['environment'];
diff --git a/webui/src/components/EnvironmentName.tsx b/packages/expo-atlas-ui/src/components/EnvironmentName.tsx
similarity index 89%
rename from webui/src/components/EnvironmentName.tsx
rename to packages/expo-atlas-ui/src/components/EnvironmentName.tsx
index d070576..dba8b51 100644
--- a/webui/src/components/EnvironmentName.tsx
+++ b/packages/expo-atlas-ui/src/components/EnvironmentName.tsx
@@ -1,7 +1,6 @@
+import type { AtlasBundle } from 'expo-atlas';
import type { PropsWithChildren } from 'react';
-import type { AtlasBundle } from '~core/data/types';
-
type EnvironmentNameProps = PropsWithChildren<{
environment: AtlasBundle['environment'];
className?: string;
diff --git a/webui/src/components/FilePathMenu.tsx b/packages/expo-atlas-ui/src/components/FilePathMenu.tsx
similarity index 100%
rename from webui/src/components/FilePathMenu.tsx
rename to packages/expo-atlas-ui/src/components/FilePathMenu.tsx
diff --git a/webui/src/components/FileSize.tsx b/packages/expo-atlas-ui/src/components/FileSize.tsx
similarity index 100%
rename from webui/src/components/FileSize.tsx
rename to packages/expo-atlas-ui/src/components/FileSize.tsx
diff --git a/webui/src/components/ModuleCode.tsx b/packages/expo-atlas-ui/src/components/ModuleCode.tsx
similarity index 98%
rename from webui/src/components/ModuleCode.tsx
rename to packages/expo-atlas-ui/src/components/ModuleCode.tsx
index f8d9e80..7335f71 100644
--- a/webui/src/components/ModuleCode.tsx
+++ b/packages/expo-atlas-ui/src/components/ModuleCode.tsx
@@ -1,3 +1,4 @@
+import type { AtlasModule } from 'expo-atlas';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { CodeAction, CodeContent, CodeHeader, CodeTitle } from '~/ui/Code';
@@ -5,7 +6,6 @@ import { Panel, PanelGroup } from '~/ui/Panel';
import { Skeleton } from '~/ui/Skeleton';
import { prettifyCode } from '~/utils/prettier';
import { getHighlightedHtml, getLanguageFromPath, useHighlighter } from '~/utils/shiki';
-import { type AtlasModule } from '~core/data/types';
type ModuleCodeProps = {
module: AtlasModule;
diff --git a/webui/src/components/ModuleFilterForm.tsx b/packages/expo-atlas-ui/src/components/ModuleFilterForm.tsx
similarity index 100%
rename from webui/src/components/ModuleFilterForm.tsx
rename to packages/expo-atlas-ui/src/components/ModuleFilterForm.tsx
diff --git a/webui/src/components/ModuleReference.tsx b/packages/expo-atlas-ui/src/components/ModuleReference.tsx
similarity index 98%
rename from webui/src/components/ModuleReference.tsx
rename to packages/expo-atlas-ui/src/components/ModuleReference.tsx
index 951d9da..1f6d7e5 100644
--- a/webui/src/components/ModuleReference.tsx
+++ b/packages/expo-atlas-ui/src/components/ModuleReference.tsx
@@ -1,4 +1,5 @@
import { cva, cx } from 'class-variance-authority';
+import type { AtlasModule, PartialAtlasBundle } from 'expo-atlas';
// @ts-expect-error
import ChevronDownIcon from 'lucide-react/dist/esm/icons/chevron-down';
import { type ComponentProps, useState, useRef, useLayoutEffect } from 'react';
@@ -6,7 +7,6 @@ import { type ComponentProps, useState, useRef, useLayoutEffect } from 'react';
import { ModuleReferenceList } from './ModuleReferenceList';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/ui/Collapsible';
-import type { AtlasModule, PartialAtlasBundle } from '~core/data/types';
type ModuleReferenceProps = {
bundle: PartialAtlasBundle;
diff --git a/webui/src/components/ModuleReferenceList.tsx b/packages/expo-atlas-ui/src/components/ModuleReferenceList.tsx
similarity index 96%
rename from webui/src/components/ModuleReferenceList.tsx
rename to packages/expo-atlas-ui/src/components/ModuleReferenceList.tsx
index d4ca125..5c4b461 100644
--- a/webui/src/components/ModuleReferenceList.tsx
+++ b/packages/expo-atlas-ui/src/components/ModuleReferenceList.tsx
@@ -1,3 +1,4 @@
+import type { AtlasModuleRef, PartialAtlasBundle } from 'expo-atlas';
import { Link } from 'expo-router';
// @ts-expect-error
import PackageIcon from 'lucide-react/dist/esm/icons/box';
@@ -6,7 +7,6 @@ import FileIcon from 'lucide-react/dist/esm/icons/file';
import { PropsWithChildren } from 'react';
import { FilePathMenu } from '~/components/FilePathMenu';
-import type { AtlasModuleRef, PartialAtlasBundle } from '~core/data/types';
type ModuleReferenceListProps = PropsWithChildren<{
bundle: PartialAtlasBundle;
diff --git a/webui/src/components/PlatformName.tsx b/packages/expo-atlas-ui/src/components/PlatformName.tsx
similarity index 94%
rename from webui/src/components/PlatformName.tsx
rename to packages/expo-atlas-ui/src/components/PlatformName.tsx
index 455d47f..f999865 100644
--- a/webui/src/components/PlatformName.tsx
+++ b/packages/expo-atlas-ui/src/components/PlatformName.tsx
@@ -1,8 +1,7 @@
import { cva } from 'class-variance-authority';
+import type { AtlasBundle } from 'expo-atlas';
import type { PropsWithChildren } from 'react';
-import type { AtlasBundle } from '~core/data/types';
-
type PlatformNameProps = PropsWithChildren<{
platform: AtlasBundle['platform'];
className?: string;
diff --git a/webui/src/components/PropertySummary.tsx b/packages/expo-atlas-ui/src/components/PropertySummary.tsx
similarity index 100%
rename from webui/src/components/PropertySummary.tsx
rename to packages/expo-atlas-ui/src/components/PropertySummary.tsx
diff --git a/webui/src/components/StateInfo.tsx b/packages/expo-atlas-ui/src/components/StateInfo.tsx
similarity index 100%
rename from webui/src/components/StateInfo.tsx
rename to packages/expo-atlas-ui/src/components/StateInfo.tsx
diff --git a/webui/src/hooks/useModuleFilters.ts b/packages/expo-atlas-ui/src/hooks/useModuleFilters.ts
similarity index 100%
rename from webui/src/hooks/useModuleFilters.ts
rename to packages/expo-atlas-ui/src/hooks/useModuleFilters.ts
diff --git a/webui/src/index.ts b/packages/expo-atlas-ui/src/index.ts
similarity index 100%
rename from webui/src/index.ts
rename to packages/expo-atlas-ui/src/index.ts
diff --git a/webui/src/providers/bundle.tsx b/packages/expo-atlas-ui/src/providers/bundle.tsx
similarity index 97%
rename from webui/src/providers/bundle.tsx
rename to packages/expo-atlas-ui/src/providers/bundle.tsx
index 787afca..7d27b4a 100644
--- a/webui/src/providers/bundle.tsx
+++ b/packages/expo-atlas-ui/src/providers/bundle.tsx
@@ -1,11 +1,11 @@
import { useQuery } from '@tanstack/react-query';
+import { type PartialAtlasBundle } from 'expo-atlas';
import { useGlobalSearchParams, useLocalSearchParams } from 'expo-router';
import { type PropsWithChildren, createContext, useContext, useMemo } from 'react';
import { StateInfo } from '~/components/StateInfo';
import { Spinner } from '~/ui/Spinner';
import { fetchApi, handleApiError } from '~/utils/api';
-import { type PartialAtlasBundle } from '~core/data/types';
type BundleContext = {
bundles: NonNullable['data']>;
diff --git a/webui/src/providers/hmr/hmr-client.ts b/packages/expo-atlas-ui/src/providers/hmr/hmr-client.ts
similarity index 98%
rename from webui/src/providers/hmr/hmr-client.ts
rename to packages/expo-atlas-ui/src/providers/hmr/hmr-client.ts
index 9110066..d5f1fc3 100644
--- a/webui/src/providers/hmr/hmr-client.ts
+++ b/packages/expo-atlas-ui/src/providers/hmr/hmr-client.ts
@@ -1,4 +1,4 @@
-import type { AtlasBundle, AtlasBundleHmr } from '~core/data/types';
+import type { AtlasBundle, AtlasBundleHmr } from 'expo-atlas';
/**
* The HMR messages received from the server
diff --git a/webui/src/providers/hmr/hmr-provider.tsx b/packages/expo-atlas-ui/src/providers/hmr/hmr-provider.tsx
similarity index 98%
rename from webui/src/providers/hmr/hmr-provider.tsx
rename to packages/expo-atlas-ui/src/providers/hmr/hmr-provider.tsx
index 7359199..d33428e 100644
--- a/webui/src/providers/hmr/hmr-provider.tsx
+++ b/packages/expo-atlas-ui/src/providers/hmr/hmr-provider.tsx
@@ -1,4 +1,5 @@
import { useQuery, useQueryClient } from '@tanstack/react-query';
+import type { AtlasBundleHmr } from 'expo-atlas';
import { type PropsWithChildren, useCallback, useEffect, useState } from 'react';
import { AtlasHmrClient, type HmrServerUpdate } from './hmr-client';
@@ -7,7 +8,6 @@ import { useBundleId } from '~/providers/bundle';
import { Button } from '~/ui/Button';
import { ToastAction, type ToasterToast, useToast } from '~/ui/Toast';
import { fetchApi, handleApiError } from '~/utils/api';
-import type { AtlasBundleHmr } from '~core/data/types';
/** The function to reload all bundle data in Atlas */
type ReloadBundle = () => Promise;
diff --git a/webui/src/providers/hmr/index.ts b/packages/expo-atlas-ui/src/providers/hmr/index.ts
similarity index 100%
rename from webui/src/providers/hmr/index.ts
rename to packages/expo-atlas-ui/src/providers/hmr/index.ts
diff --git a/webui/src/providers/query.tsx b/packages/expo-atlas-ui/src/providers/query.tsx
similarity index 100%
rename from webui/src/providers/query.tsx
rename to packages/expo-atlas-ui/src/providers/query.tsx
diff --git a/webui/src/providers/theme.tsx b/packages/expo-atlas-ui/src/providers/theme.tsx
similarity index 100%
rename from webui/src/providers/theme.tsx
rename to packages/expo-atlas-ui/src/providers/theme.tsx
diff --git a/webui/src/styles-expo.css b/packages/expo-atlas-ui/src/styles-expo.css
similarity index 100%
rename from webui/src/styles-expo.css
rename to packages/expo-atlas-ui/src/styles-expo.css
diff --git a/webui/src/styles.css b/packages/expo-atlas-ui/src/styles.css
similarity index 100%
rename from webui/src/styles.css
rename to packages/expo-atlas-ui/src/styles.css
diff --git a/webui/src/ui/Breadcrumb.tsx b/packages/expo-atlas-ui/src/ui/Breadcrumb.tsx
similarity index 100%
rename from webui/src/ui/Breadcrumb.tsx
rename to packages/expo-atlas-ui/src/ui/Breadcrumb.tsx
diff --git a/webui/src/ui/Button.tsx b/packages/expo-atlas-ui/src/ui/Button.tsx
similarity index 100%
rename from webui/src/ui/Button.tsx
rename to packages/expo-atlas-ui/src/ui/Button.tsx
diff --git a/webui/src/ui/Checkbox.tsx b/packages/expo-atlas-ui/src/ui/Checkbox.tsx
similarity index 100%
rename from webui/src/ui/Checkbox.tsx
rename to packages/expo-atlas-ui/src/ui/Checkbox.tsx
diff --git a/webui/src/ui/Code.tsx b/packages/expo-atlas-ui/src/ui/Code.tsx
similarity index 100%
rename from webui/src/ui/Code.tsx
rename to packages/expo-atlas-ui/src/ui/Code.tsx
diff --git a/webui/src/ui/Collapsible.tsx b/packages/expo-atlas-ui/src/ui/Collapsible.tsx
similarity index 100%
rename from webui/src/ui/Collapsible.tsx
rename to packages/expo-atlas-ui/src/ui/Collapsible.tsx
diff --git a/webui/src/ui/Input.tsx b/packages/expo-atlas-ui/src/ui/Input.tsx
similarity index 100%
rename from webui/src/ui/Input.tsx
rename to packages/expo-atlas-ui/src/ui/Input.tsx
diff --git a/webui/src/ui/Label.tsx b/packages/expo-atlas-ui/src/ui/Label.tsx
similarity index 100%
rename from webui/src/ui/Label.tsx
rename to packages/expo-atlas-ui/src/ui/Label.tsx
diff --git a/webui/src/ui/Layout.tsx b/packages/expo-atlas-ui/src/ui/Layout.tsx
similarity index 100%
rename from webui/src/ui/Layout.tsx
rename to packages/expo-atlas-ui/src/ui/Layout.tsx
diff --git a/webui/src/ui/Menu.tsx b/packages/expo-atlas-ui/src/ui/Menu.tsx
similarity index 100%
rename from webui/src/ui/Menu.tsx
rename to packages/expo-atlas-ui/src/ui/Menu.tsx
diff --git a/webui/src/ui/Panel.tsx b/packages/expo-atlas-ui/src/ui/Panel.tsx
similarity index 100%
rename from webui/src/ui/Panel.tsx
rename to packages/expo-atlas-ui/src/ui/Panel.tsx
diff --git a/webui/src/ui/Select.tsx b/packages/expo-atlas-ui/src/ui/Select.tsx
similarity index 100%
rename from webui/src/ui/Select.tsx
rename to packages/expo-atlas-ui/src/ui/Select.tsx
diff --git a/webui/src/ui/Sheet.tsx b/packages/expo-atlas-ui/src/ui/Sheet.tsx
similarity index 100%
rename from webui/src/ui/Sheet.tsx
rename to packages/expo-atlas-ui/src/ui/Sheet.tsx
diff --git a/webui/src/ui/Skeleton.tsx b/packages/expo-atlas-ui/src/ui/Skeleton.tsx
similarity index 100%
rename from webui/src/ui/Skeleton.tsx
rename to packages/expo-atlas-ui/src/ui/Skeleton.tsx
diff --git a/webui/src/ui/Spinner.tsx b/packages/expo-atlas-ui/src/ui/Spinner.tsx
similarity index 100%
rename from webui/src/ui/Spinner.tsx
rename to packages/expo-atlas-ui/src/ui/Spinner.tsx
diff --git a/webui/src/ui/Tag.tsx b/packages/expo-atlas-ui/src/ui/Tag.tsx
similarity index 100%
rename from webui/src/ui/Tag.tsx
rename to packages/expo-atlas-ui/src/ui/Tag.tsx
diff --git a/webui/src/ui/Toast.tsx b/packages/expo-atlas-ui/src/ui/Toast.tsx
similarity index 100%
rename from webui/src/ui/Toast.tsx
rename to packages/expo-atlas-ui/src/ui/Toast.tsx
diff --git a/webui/src/ui/Tooltip.tsx b/packages/expo-atlas-ui/src/ui/Tooltip.tsx
similarity index 100%
rename from webui/src/ui/Tooltip.tsx
rename to packages/expo-atlas-ui/src/ui/Tooltip.tsx
diff --git a/webui/src/utils/api.ts b/packages/expo-atlas-ui/src/utils/api.ts
similarity index 100%
rename from webui/src/utils/api.ts
rename to packages/expo-atlas-ui/src/utils/api.ts
diff --git a/webui/src/utils/atlas.ts b/packages/expo-atlas-ui/src/utils/atlas.ts
similarity index 88%
rename from webui/src/utils/atlas.ts
rename to packages/expo-atlas-ui/src/utils/atlas.ts
index 8fada86..e495a05 100644
--- a/webui/src/utils/atlas.ts
+++ b/packages/expo-atlas-ui/src/utils/atlas.ts
@@ -1,4 +1,4 @@
-import '~core/utils/global';
+import 'expo-atlas/build/src/utils/global';
/**
* Get the Expo Atlas data source, from global property.
diff --git a/webui/src/utils/bundle.ts b/packages/expo-atlas-ui/src/utils/bundle.ts
similarity index 91%
rename from webui/src/utils/bundle.ts
rename to packages/expo-atlas-ui/src/utils/bundle.ts
index 10e9d59..33f1c7f 100644
--- a/webui/src/utils/bundle.ts
+++ b/packages/expo-atlas-ui/src/utils/bundle.ts
@@ -1,4 +1,4 @@
-import { PartialAtlasBundle } from '~core/data/types';
+import type { PartialAtlasBundle } from 'expo-atlas';
/**
* Translate an absolute path to a relative path, based on the bundle's project root.
diff --git a/webui/src/utils/debounce.ts b/packages/expo-atlas-ui/src/utils/debounce.ts
similarity index 100%
rename from webui/src/utils/debounce.ts
rename to packages/expo-atlas-ui/src/utils/debounce.ts
diff --git a/webui/src/utils/filters.ts b/packages/expo-atlas-ui/src/utils/filters.ts
similarity index 98%
rename from webui/src/utils/filters.ts
rename to packages/expo-atlas-ui/src/utils/filters.ts
index e9bf59b..a9331f0 100644
--- a/webui/src/utils/filters.ts
+++ b/packages/expo-atlas-ui/src/utils/filters.ts
@@ -1,7 +1,6 @@
+import type { AtlasModule } from 'expo-atlas';
import picomatch from 'picomatch';
-import { type AtlasModule } from '~core/data/types';
-
export type ModuleFilters = {
/** Only match the project code, or all code including (external) packages */
scope?: 'project';
diff --git a/webui/src/utils/prettier.ts b/packages/expo-atlas-ui/src/utils/prettier.ts
similarity index 100%
rename from webui/src/utils/prettier.ts
rename to packages/expo-atlas-ui/src/utils/prettier.ts
diff --git a/webui/src/utils/shiki-theme.ts b/packages/expo-atlas-ui/src/utils/shiki-theme.ts
similarity index 100%
rename from webui/src/utils/shiki-theme.ts
rename to packages/expo-atlas-ui/src/utils/shiki-theme.ts
diff --git a/webui/src/utils/shiki.ts b/packages/expo-atlas-ui/src/utils/shiki.ts
similarity index 100%
rename from webui/src/utils/shiki.ts
rename to packages/expo-atlas-ui/src/utils/shiki.ts
diff --git a/webui/src/utils/treemap.ts b/packages/expo-atlas-ui/src/utils/treemap.ts
similarity index 99%
rename from webui/src/utils/treemap.ts
rename to packages/expo-atlas-ui/src/utils/treemap.ts
index e18afa1..bd2ab24 100644
--- a/webui/src/utils/treemap.ts
+++ b/packages/expo-atlas-ui/src/utils/treemap.ts
@@ -1,4 +1,4 @@
-import type { AtlasBundle, AtlasModule } from '~core/data/types';
+import type { AtlasBundle, AtlasModule } from 'expo-atlas';
export type TreemapNode = {
/** If the current node is the root of the treemap */
diff --git a/webui/tailwind.config.js b/packages/expo-atlas-ui/tailwind.config.js
similarity index 100%
rename from webui/tailwind.config.js
rename to packages/expo-atlas-ui/tailwind.config.js
diff --git a/webui/tsconfig.json b/packages/expo-atlas-ui/tsconfig.json
similarity index 74%
rename from webui/tsconfig.json
rename to packages/expo-atlas-ui/tsconfig.json
index bf13aa9..776354d 100644
--- a/webui/tsconfig.json
+++ b/packages/expo-atlas-ui/tsconfig.json
@@ -6,14 +6,8 @@
"~/*": [
"./src/*"
],
- "~core/*": ["../src/*"]
}
},
- "references": [
- {
- "path": "../"
- }
- ],
"include": [
"**/*.ts",
"**/*.tsx",
diff --git a/cli.d.ts b/packages/expo-atlas/cli.d.ts
similarity index 100%
rename from cli.d.ts
rename to packages/expo-atlas/cli.d.ts
diff --git a/cli.js b/packages/expo-atlas/cli.js
similarity index 100%
rename from cli.js
rename to packages/expo-atlas/cli.js
diff --git a/expo-module.config.json b/packages/expo-atlas/expo-module.config.json
similarity index 100%
rename from expo-module.config.json
rename to packages/expo-atlas/expo-module.config.json
diff --git a/metro.d.ts b/packages/expo-atlas/metro.d.ts
similarity index 100%
rename from metro.d.ts
rename to packages/expo-atlas/metro.d.ts
diff --git a/metro.js b/packages/expo-atlas/metro.js
similarity index 100%
rename from metro.js
rename to packages/expo-atlas/metro.js
diff --git a/packages/expo-atlas/package.json b/packages/expo-atlas/package.json
new file mode 100644
index 0000000..1da7c17
--- /dev/null
+++ b/packages/expo-atlas/package.json
@@ -0,0 +1,90 @@
+{
+ "sideEffects": false,
+ "name": "expo-atlas",
+ "version": "0.3.13",
+ "description": "Inspect bundle contents, on module level, from Metro",
+ "keywords": [
+ "expo",
+ "atlas",
+ "devtools"
+ ],
+ "bin": "build/src/cli/bin.js",
+ "main": "build/src/index.js",
+ "types": "build/src/index.d.ts",
+ "files": [
+ "build",
+ "!build/tsconfig.tsbuildinfo",
+ "expo-module.config.json",
+ "cli.js",
+ "cli.d.ts",
+ "metro.js",
+ "metro.d.ts",
+ "static",
+ "webui/dist"
+ ],
+ "homepage": "https://github.com/expo/expo-atlas",
+ "bugs": {
+ "url": "https://github.com/expo/expo-atlas/issues"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/expo/expo-atlas"
+ },
+ "scripts": {
+ "build": "expo-module build",
+ "clean": "expo-module clean",
+ "lint": "eslint . --ext js,ts,tsx",
+ "typecheck": "expo-module typecheck"
+ },
+ "license": "MIT",
+ "dependencies": {
+ "@expo/server": "^0.4.2",
+ "arg": "^5.0.2",
+ "chalk": "^4.1.2",
+ "compression": "^1.7.4",
+ "connect": "^3.7.0",
+ "express": "^4.18.2",
+ "freeport-async": "^2.0.0",
+ "getenv": "^1.0.0",
+ "morgan": "^1.10.0",
+ "open": "^8.4.2",
+ "serve-static": "^1.15.0",
+ "stream-json": "^1.8.0"
+ },
+ "devDependencies": {
+ "@types/bun": "^1.0.8",
+ "@types/chai": "^4",
+ "@types/express": "^4.17.21",
+ "@types/node": "^20.11.26",
+ "@types/stream-json": "^1.7.7",
+ "chai": "^4.3.10",
+ "expo": "~50.0.1",
+ "metro": "^0.80.6",
+ "prettier": "^3.2.5",
+ "typescript": "^5.1.3"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ },
+ "eslintConfig": {
+ "extends": "universe",
+ "ignorePatterns": [
+ "build",
+ "node_modules"
+ ],
+ "rules": {
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ {
+ "args": "all",
+ "argsIgnorePattern": "^_",
+ "caughtErrors": "all",
+ "caughtErrorsIgnorePattern": "^_",
+ "destructuredArrayIgnorePattern": "^_",
+ "varsIgnorePattern": "^_",
+ "ignoreRestSiblings": true
+ }
+ ]
+ }
+ }
+}
diff --git a/src/cli.ts b/packages/expo-atlas/src/cli.ts
similarity index 100%
rename from src/cli.ts
rename to packages/expo-atlas/src/cli.ts
diff --git a/src/cli/bin.ts b/packages/expo-atlas/src/cli/bin.ts
similarity index 100%
rename from src/cli/bin.ts
rename to packages/expo-atlas/src/cli/bin.ts
diff --git a/src/cli/createServer.ts b/packages/expo-atlas/src/cli/createServer.ts
similarity index 100%
rename from src/cli/createServer.ts
rename to packages/expo-atlas/src/cli/createServer.ts
diff --git a/src/cli/resolveOptions.ts b/packages/expo-atlas/src/cli/resolveOptions.ts
similarity index 100%
rename from src/cli/resolveOptions.ts
rename to packages/expo-atlas/src/cli/resolveOptions.ts
diff --git a/src/data/AtlasFileSource.ts b/packages/expo-atlas/src/data/AtlasFileSource.ts
similarity index 100%
rename from src/data/AtlasFileSource.ts
rename to packages/expo-atlas/src/data/AtlasFileSource.ts
diff --git a/src/data/MetroGraphSource.ts b/packages/expo-atlas/src/data/MetroGraphSource.ts
similarity index 97%
rename from src/data/MetroGraphSource.ts
rename to packages/expo-atlas/src/data/MetroGraphSource.ts
index 0ac9bf9..de7392c 100644
--- a/src/data/MetroGraphSource.ts
+++ b/packages/expo-atlas/src/data/MetroGraphSource.ts
@@ -14,15 +14,15 @@ type MetroModule = metro.Module;
type ConvertGraphToAtlasOptions = {
projectRoot: string;
entryPoint: string;
- preModules: Readonly;
+ preModules: readonly MetroModule[];
graph: MetroGraph;
serializeOptions: Readonly;
/** Options passed-through from the Metro config */
metroConfig: {
- watchFolders?: Readonly;
+ watchFolders?: readonly string[];
resolver?: {
- sourceExts?: Readonly;
- assetExts?: Readonly;
+ sourceExts?: readonly string[];
+ assetExts?: readonly string[];
};
};
};
@@ -241,7 +241,7 @@ function getSharedRoot(options: Pick