diff --git a/.gitignore b/.gitignore
index 87f9b7f..ca8b0ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,3 +43,6 @@ app-example
/android
.direnv/
+.db/
+.logs
+.env
diff --git a/app.json b/app.json
index 0321baf..38398b6 100644
--- a/app.json
+++ b/app.json
@@ -22,7 +22,7 @@
"predictiveBackGestureEnabled": false
},
"web": {
- "output": "static",
+ "output": "server",
"favicon": "./assets/images/favicon.png"
},
"plugins": [
diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx
deleted file mode 100644
index 54e11d0..0000000
--- a/app/(tabs)/_layout.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import { Tabs } from 'expo-router';
-import React from 'react';
-
-import { HapticTab } from '@/components/haptic-tab';
-import { IconSymbol } from '@/components/ui/icon-symbol';
-import { Colors } from '@/constants/theme';
-import { useColorScheme } from '@/hooks/use-color-scheme';
-
-export default function TabLayout() {
- const colorScheme = useColorScheme();
-
- return (
-
- ,
- }}
- />
- ,
- }}
- />
-
- );
-}
diff --git a/app/(tabs)/explore.tsx b/app/(tabs)/explore.tsx
deleted file mode 100644
index 71518f9..0000000
--- a/app/(tabs)/explore.tsx
+++ /dev/null
@@ -1,112 +0,0 @@
-import { Image } from 'expo-image';
-import { Platform, StyleSheet } from 'react-native';
-
-import { Collapsible } from '@/components/ui/collapsible';
-import { ExternalLink } from '@/components/external-link';
-import ParallaxScrollView from '@/components/parallax-scroll-view';
-import { ThemedText } from '@/components/themed-text';
-import { ThemedView } from '@/components/themed-view';
-import { IconSymbol } from '@/components/ui/icon-symbol';
-import { Fonts } from '@/constants/theme';
-
-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
-
-
-
-
- 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/app/(tabs)/index.tsx b/app/(tabs)/index.tsx
deleted file mode 100644
index 786b736..0000000
--- a/app/(tabs)/index.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import { Image } from 'expo-image';
-import { Platform, StyleSheet } from 'react-native';
-
-import { HelloWave } from '@/components/hello-wave';
-import ParallaxScrollView from '@/components/parallax-scroll-view';
-import { ThemedText } from '@/components/themed-text';
-import { ThemedView } from '@/components/themed-view';
-import { Link } from 'expo-router';
-
-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',
- web: 'F12',
- })}
- {' '}
- to open developer tools.
-
-
-
-
-
- Step 2: Explore
-
-
-
- alert('Action pressed')} />
- alert('Share pressed')}
- />
-
- alert('Delete pressed')}
- />
-
-
-
-
-
- {`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/app/_layout.tsx b/app/_layout.tsx
index f518c9b..29f8c70 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -4,6 +4,7 @@ import { StatusBar } from 'expo-status-bar';
import 'react-native-reanimated';
import { useColorScheme } from '@/hooks/use-color-scheme';
+import { authClient } from '@/lib/auth-client';
export const unstable_settings = {
anchor: '(tabs)',
@@ -11,12 +12,17 @@ export const unstable_settings = {
export default function RootLayout() {
const colorScheme = useColorScheme();
+ const { data, isPending } = authClient.useSession();
return (
-
-
+
+
+
+
+
+
diff --git a/app/api/auth/[...auth]+api.ts b/app/api/auth/[...auth]+api.ts
new file mode 100644
index 0000000..45b0481
--- /dev/null
+++ b/app/api/auth/[...auth]+api.ts
@@ -0,0 +1,4 @@
+import { auth } from "@/lib/auth";
+
+const handler = auth.handler;
+export { handler as GET, handler as POST };
diff --git a/app/auth.tsx b/app/auth.tsx
new file mode 100644
index 0000000..fd24e9f
--- /dev/null
+++ b/app/auth.tsx
@@ -0,0 +1,16 @@
+import { Button, View } from "react-native";
+import { authClient } from "@/lib/auth-client";
+
+export default function Auth() {
+ const onLogin = () => {
+ authClient.signIn.oauth2({
+ providerId: "koon-family",
+ });
+ };
+
+ return (
+
+
+
+ )
+}
diff --git a/app/index.tsx b/app/index.tsx
new file mode 100644
index 0000000..1db3e8f
--- /dev/null
+++ b/app/index.tsx
@@ -0,0 +1,18 @@
+import { ThemedText } from '@/components/themed-text';
+import { SafeAreaView } from 'react-native-safe-area-context';
+import { authClient } from '@/lib/auth-client';
+import { Button } from 'react-native';
+
+export default function HomeScreen() {
+ const { data } = authClient.useSession();
+ const onLogout = () => {
+ authClient.signOut();
+ }
+
+ return (
+
+ Hello {data?.user.name}
+
+
+ );
+}
diff --git a/app/modal.tsx b/app/modal.tsx
deleted file mode 100644
index 6dfbc1a..0000000
--- a/app/modal.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { Link } from 'expo-router';
-import { StyleSheet } from 'react-native';
-
-import { ThemedText } from '@/components/themed-text';
-import { ThemedView } from '@/components/themed-view';
-
-export default function ModalScreen() {
- return (
-
- This is a modal
-
- 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/flake.nix b/flake.nix
index c818d66..ffc0961 100644
--- a/flake.nix
+++ b/flake.nix
@@ -10,9 +10,18 @@
formatter = forAllSystems (pkgs: pkgs.alejandra);
devShells = forAllSystems (pkgs: {
default = pkgs.mkShell {
+
+ shellHook = ''
+ dev() {
+ process-compose up -p 0
+ }
+ '';
packages = with pkgs; [
corepack
nodejs_22
+
+ postgresql
+ process-compose
];
};
});
diff --git a/lib/auth-client.ts b/lib/auth-client.ts
new file mode 100644
index 0000000..ac03427
--- /dev/null
+++ b/lib/auth-client.ts
@@ -0,0 +1,16 @@
+import { createAuthClient } from "better-auth/react";
+import { genericOAuthClient } from "better-auth/client/plugins";
+import { expoClient } from "@better-auth/expo/client";
+import * as SecureStore from "expo-secure-store";
+
+export const authClient = createAuthClient({
+ baseURL: "http://localhost:8081",
+ plugins: [
+ expoClient({
+ scheme: "money",
+ storagePrefix: "money",
+ storage: SecureStore,
+ }),
+ genericOAuthClient(),
+ ]
+});
diff --git a/lib/auth.ts b/lib/auth.ts
new file mode 100644
index 0000000..00c414a
--- /dev/null
+++ b/lib/auth.ts
@@ -0,0 +1,24 @@
+import { betterAuth } from "better-auth";
+import { genericOAuth } from "better-auth/plugins";
+import { expo } from "@better-auth/expo";
+import { Pool } from "pg";
+
+export const auth = betterAuth({
+ database: new Pool({
+ connectionString: process.env.DATABASE_URL,
+ }),
+ plugins: [
+ expo(),
+ genericOAuth({
+ config: [
+ {
+ providerId: 'koon-family',
+ clientId: process.env.OAUTH_CLIENT_ID!,
+ clientSecret: process.env.OAUTH_CLIENT_SECRET!,
+ discoveryUrl: process.env.OAUTH_DISCOVERY_URL!,
+ scopes: ["profile", "email"],
+ }
+ ]
+ })
+ ]
+});
diff --git a/metro.config.js b/metro.config.js
new file mode 100644
index 0000000..6e007ef
--- /dev/null
+++ b/metro.config.js
@@ -0,0 +1,7 @@
+const { getDefaultConfig } = require("expo/metro-config");
+
+const config = getDefaultConfig(__dirname)
+
+config.resolver.unstable_enablePackageExports = true;
+
+module.exports = config;
diff --git a/package.json b/package.json
index 292dc75..da45b0f 100644
--- a/package.json
+++ b/package.json
@@ -11,10 +11,12 @@
"lint": "expo lint"
},
"dependencies": {
+ "@better-auth/expo": "^1.3.27",
"@expo/vector-icons": "^15.0.2",
"@react-navigation/bottom-tabs": "^7.4.0",
"@react-navigation/elements": "^2.6.3",
"@react-navigation/native": "^7.1.8",
+ "better-auth": "^1.3.27",
"expo": "~54.0.13",
"expo-constants": "~18.0.9",
"expo-font": "~14.0.9",
@@ -27,21 +29,23 @@
"expo-symbols": "~1.0.7",
"expo-system-ui": "~6.0.7",
"expo-web-browser": "~15.0.8",
+ "pg": "^8.16.3",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-native": "0.81.4",
"react-native-gesture-handler": "~2.28.0",
- "react-native-worklets": "0.5.1",
"react-native-reanimated": "~4.1.1",
"react-native-safe-area-context": "~5.6.0",
"react-native-screens": "~4.16.0",
- "react-native-web": "~0.21.0"
+ "react-native-web": "~0.21.0",
+ "react-native-worklets": "0.5.1"
},
"devDependencies": {
+ "@types/pg": "^8.15.5",
"@types/react": "~19.1.0",
- "typescript": "~5.9.2",
"eslint": "^9.25.0",
- "eslint-config-expo": "~10.0.0"
+ "eslint-config-expo": "~10.0.0",
+ "typescript": "~5.9.2"
},
"private": true
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8f98a99..83654fa 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,6 +8,9 @@ importers:
.:
dependencies:
+ '@better-auth/expo':
+ specifier: ^1.3.27
+ version: 1.3.27(better-auth@1.3.27(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(expo-constants@18.0.9)(expo-crypto@15.0.7(expo@54.0.13))(expo-linking@8.0.8)(expo-secure-store@15.0.7(expo@54.0.13))(expo-web-browser@15.0.8(expo@54.0.13)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0)))
'@expo/vector-icons':
specifier: ^15.0.2
version: 15.0.2(expo-font@14.0.9(expo@54.0.13)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
@@ -20,6 +23,9 @@ importers:
'@react-navigation/native':
specifier: ^7.1.8
version: 7.1.18(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
+ better-auth:
+ specifier: ^1.3.27
+ version: 1.3.27(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
expo:
specifier: ~54.0.13
version: 54.0.13(@babel/core@7.28.4)(@expo/metro-runtime@6.1.2)(expo-router@6.0.11)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
@@ -56,6 +62,9 @@ importers:
expo-web-browser:
specifier: ~15.0.8
version: 15.0.8(expo@54.0.13)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))
+ pg:
+ specifier: ^8.16.3
+ version: 8.16.3
react:
specifier: 19.1.0
version: 19.1.0
@@ -84,6 +93,9 @@ importers:
specifier: 0.5.1
version: 0.5.1(@babel/core@7.28.4)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
devDependencies:
+ '@types/pg':
+ specifier: ^8.15.5
+ version: 8.15.5
'@types/react':
specifier: ~19.1.0
version: 19.1.17
@@ -610,6 +622,25 @@ packages:
resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==}
engines: {node: '>=6.9.0'}
+ '@better-auth/core@1.3.27':
+ resolution: {integrity: sha512-3Sfdax6MQyronY+znx7bOsfQHI6m1SThvJWb0RDscFEAhfqLy95k1sl+/PgGyg0cwc2cUXoEiAOSqYdFYrg3vA==}
+
+ '@better-auth/expo@1.3.27':
+ resolution: {integrity: sha512-2bZ4Fi7Moa99ymjkIwRUzENbqmzZNjD9cjlq2lpuiF/+TGOA2LYJmS7RnR/i9+UHKi5T3AsXgrIRMFQgYtgZ2Q==}
+ peerDependencies:
+ better-auth: 1.3.27
+ expo-constants: '>=17.0.0'
+ expo-crypto: '>=13.0.0'
+ expo-linking: '>=7.0.0'
+ expo-secure-store: '>=14.0.0'
+ expo-web-browser: '>=14.0.0'
+
+ '@better-auth/utils@0.3.0':
+ resolution: {integrity: sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==}
+
+ '@better-fetch/fetch@1.1.18':
+ resolution: {integrity: sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==}
+
'@egjs/hammerjs@2.0.17':
resolution: {integrity: sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==}
engines: {node: '>=0.8.0'}
@@ -785,6 +816,9 @@ packages:
resolution: {integrity: sha512-ReZxZ8pdnoI3tP/dNnJdnmAk7uLT4FjsKDGW7YeDdvdOMz2XCQSmSCM9IWlrXuWtMF9zeSB6WJtEhCQ41gQOfw==}
hasBin: true
+ '@hexagon/base64@1.1.28':
+ resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==}
+
'@humanfs/core@0.19.1':
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
engines: {node: '>=18.18.0'}
@@ -864,9 +898,20 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+ '@levischuck/tiny-cbor@0.2.11':
+ resolution: {integrity: sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==}
+
'@napi-rs/wasm-runtime@0.2.12':
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
+ '@noble/ciphers@2.0.1':
+ resolution: {integrity: sha512-xHK3XHPUW8DTAobU+G0XT+/w+JLM7/8k1UFdB5xg/zTFPnFCobhftzw8wl4Lw2aq/Rvir5pxfZV5fEazmeCJ2g==}
+ engines: {node: '>= 20.19.0'}
+
+ '@noble/hashes@2.0.1':
+ resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==}
+ engines: {node: '>= 20.19.0'}
+
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -883,6 +928,42 @@ packages:
resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
engines: {node: '>=12.4.0'}
+ '@peculiar/asn1-android@2.5.0':
+ resolution: {integrity: sha512-t8A83hgghWQkcneRsgGs2ebAlRe54ns88p7ouv8PW2tzF1nAW4yHcL4uZKrFpIU+uszIRzTkcCuie37gpkId0A==}
+
+ '@peculiar/asn1-cms@2.5.0':
+ resolution: {integrity: sha512-p0SjJ3TuuleIvjPM4aYfvYw8Fk1Hn/zAVyPJZTtZ2eE9/MIer6/18ROxX6N/e6edVSfvuZBqhxAj3YgsmSjQ/A==}
+
+ '@peculiar/asn1-csr@2.5.0':
+ resolution: {integrity: sha512-ioigvA6WSYN9h/YssMmmoIwgl3RvZlAYx4A/9jD2qaqXZwGcNlAxaw54eSx2QG1Yu7YyBC5Rku3nNoHrQ16YsQ==}
+
+ '@peculiar/asn1-ecc@2.5.0':
+ resolution: {integrity: sha512-t4eYGNhXtLRxaP50h3sfO6aJebUCDGQACoeexcelL4roMFRRVgB20yBIu2LxsPh/tdW9I282gNgMOyg3ywg/mg==}
+
+ '@peculiar/asn1-pfx@2.5.0':
+ resolution: {integrity: sha512-Vj0d0wxJZA+Ztqfb7W+/iu8Uasw6hhKtCdLKXLG/P3kEPIQpqGI4P4YXlROfl7gOCqFIbgsj1HzFIFwQ5s20ug==}
+
+ '@peculiar/asn1-pkcs8@2.5.0':
+ resolution: {integrity: sha512-L7599HTI2SLlitlpEP8oAPaJgYssByI4eCwQq2C9eC90otFpm8MRn66PpbKviweAlhinWQ3ZjDD2KIVtx7PaVw==}
+
+ '@peculiar/asn1-pkcs9@2.5.0':
+ resolution: {integrity: sha512-UgqSMBLNLR5TzEZ5ZzxR45Nk6VJrammxd60WMSkofyNzd3DQLSNycGWSK5Xg3UTYbXcDFyG8pA/7/y/ztVCa6A==}
+
+ '@peculiar/asn1-rsa@2.5.0':
+ resolution: {integrity: sha512-qMZ/vweiTHy9syrkkqWFvbT3eLoedvamcUdnnvwyyUNv5FgFXA3KP8td+ATibnlZ0EANW5PYRm8E6MJzEB/72Q==}
+
+ '@peculiar/asn1-schema@2.5.0':
+ resolution: {integrity: sha512-YM/nFfskFJSlHqv59ed6dZlLZqtZQwjRVJ4bBAiWV08Oc+1rSd5lDZcBEx0lGDHfSoH3UziI2pXt2UM33KerPQ==}
+
+ '@peculiar/asn1-x509-attr@2.5.0':
+ resolution: {integrity: sha512-9f0hPOxiJDoG/bfNLAFven+Bd4gwz/VzrCIIWc1025LEI4BXO0U5fOCTNDPbbp2ll+UzqKsZ3g61mpBp74gk9A==}
+
+ '@peculiar/asn1-x509@2.5.0':
+ resolution: {integrity: sha512-CpwtMCTJvfvYTFMuiME5IH+8qmDe3yEWzKHe7OOADbGfq7ohxeLaXwQo0q4du3qs0AII3UbLCvb9NF/6q0oTKQ==}
+
+ '@peculiar/x509@1.14.0':
+ resolution: {integrity: sha512-Yc4PDxN3OrxUPiXgU63c+ZRXKGE8YKF2McTciYhUHFtHVB0KMnjeFSU0qpztGhsp4P0uKix4+J2xEpIEDu8oXg==}
+
'@pkgjs/parseargs@0.11.0':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
@@ -1227,6 +1308,13 @@ packages:
'@rtsao/scc@1.1.0':
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
+ '@simplewebauthn/browser@13.2.2':
+ resolution: {integrity: sha512-FNW1oLQpTJyqG5kkDg5ZsotvWgmBaC6jCHR7Ej0qUNep36Wl9tj2eZu7J5rP+uhXgHaLk+QQ3lqcw2vS5MX1IA==}
+
+ '@simplewebauthn/server@13.2.2':
+ resolution: {integrity: sha512-HcWLW28yTMGXpwE9VLx9J+N2KEUaELadLrkPEEI9tpI5la70xNEVEsu/C+m3u7uoq4FulLqZQhgBCzR9IZhFpA==}
+ engines: {node: '>=20.0.0'}
+
'@sinclair/typebox@0.27.8':
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
@@ -1278,6 +1366,9 @@ packages:
'@types/node@24.7.1':
resolution: {integrity: sha512-CmyhGZanP88uuC5GpWU9q+fI61j2SkhO3UGMUdfYRE6Bcy0ccyzn1Rqj9YAB/ZY4kOXmNf0ocah5GtphmLMP6Q==}
+ '@types/pg@8.15.5':
+ resolution: {integrity: sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ==}
+
'@types/react@19.1.17':
resolution: {integrity: sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA==}
@@ -1574,6 +1665,10 @@ packages:
asap@2.0.6:
resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
+ asn1js@3.0.6:
+ resolution: {integrity: sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==}
+ engines: {node: '>=12.0.0'}
+
async-function@1.0.0:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
@@ -1659,6 +1754,38 @@ packages:
resolution: {integrity: sha512-qsJ8/X+UypqxHXN75M7dF88jNK37dLBRW7LeUzCPz+TNs37G8cfWy9nWzS+LS//g600zrt2le9KuXt0rWfDz5Q==}
hasBin: true
+ better-auth@1.3.27:
+ resolution: {integrity: sha512-SwiGAJ7yU6dBhNg0NdV1h5M8T5sa7/AszZVc4vBfMDrLLmvUfbt9JoJ0uRUJUEdKRAAxTyl9yA+F3+GhtAD80w==}
+ peerDependencies:
+ '@lynx-js/react': '*'
+ '@sveltejs/kit': '*'
+ next: '*'
+ react: '*'
+ react-dom: '*'
+ solid-js: '*'
+ svelte: '*'
+ vue: '*'
+ peerDependenciesMeta:
+ '@lynx-js/react':
+ optional: true
+ '@sveltejs/kit':
+ optional: true
+ next:
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+ solid-js:
+ optional: true
+ svelte:
+ optional: true
+ vue:
+ optional: true
+
+ better-call@1.0.19:
+ resolution: {integrity: sha512-sI3GcA1SCVa3H+CDHl8W8qzhlrckwXOTKhqq3OOPXjgn5aTOMIqGY34zLY/pHA6tRRMjTUC3lz5Mi7EbDA24Kw==}
+
better-opn@3.0.2:
resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==}
engines: {node: '>=12.0.0'}
@@ -1935,6 +2062,9 @@ packages:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
engines: {node: '>= 0.4'}
+ defu@6.1.4:
+ resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
+
depd@2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
@@ -2191,6 +2321,11 @@ packages:
expo: '*'
react-native: '*'
+ expo-crypto@15.0.7:
+ resolution: {integrity: sha512-FUo41TwwGT2e5rA45PsjezI868Ch3M6wbCZsmqTWdF/hr+HyPcrp1L//dsh/hsrsyrQdpY/U96Lu71/wXePJeg==}
+ peerDependencies:
+ expo: '*'
+
expo-file-system@19.0.17:
resolution: {integrity: sha512-WwaS01SUFrxBnExn87pg0sCTJjZpf2KAOzfImG0o8yhkU7fbYpihpl/oocXBEsNbj58a8hVt1Y4CVV5c1tzu/g==}
peerDependencies:
@@ -2276,6 +2411,11 @@ packages:
react-server-dom-webpack:
optional: true
+ expo-secure-store@15.0.7:
+ resolution: {integrity: sha512-9q7+G1Zxr5P6J5NRIlm86KulvmYwc6UnQlYPjQLDu1drDnerz6AT6l884dPu29HgtDTn4rR0heYeeGFhMKM7/Q==}
+ peerDependencies:
+ expo: '*'
+
expo-server@1.0.1:
resolution: {integrity: sha512-J3JlpzNXOkkr4BbapTrcv6klBQcw6NzrBBVIU7qkNE2eU3U1on9rp27wi0+cihjG/QgxSIqQVkrga5z3HWnH0A==}
engines: {node: '>=20.16.0'}
@@ -2814,6 +2954,9 @@ packages:
jimp-compact@0.16.1:
resolution: {integrity: sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==}
+ jose@6.1.0:
+ resolution: {integrity: sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==}
+
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -2865,6 +3008,10 @@ packages:
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
engines: {node: '>=6'}
+ kysely@0.28.8:
+ resolution: {integrity: sha512-QUOgl5ZrS9IRuhq5FvOKFSsD/3+IA6MLE81/bOOTRA/YQpKDza2sFdN5g6JCB9BOpqMJDGefLCQ9F12hRS13TA==}
+ engines: {node: '>=20.0.0'}
+
lan-network@0.1.7:
resolution: {integrity: sha512-mnIlAEMu4OyEvUNdzco9xpuB9YVcPkQec+QsgycBCtPZvEqWPCDPfbAE4OJMdBBWpZWtpCn1xw9jJYlwjWI5zQ==}
hasBin: true
@@ -3185,6 +3332,10 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
+ nanostores@1.0.1:
+ resolution: {integrity: sha512-kNZ9xnoJYKg/AfxjrVL4SS0fKX++4awQReGqWnwTRHxeHGZ1FJFVgTqr/eMrNQdp0Tz7M7tG/TDaX8QfHDwVCw==}
+ engines: {node: ^20.0.0 || >=22.0.0}
+
napi-postinstall@0.3.4:
resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
@@ -3371,6 +3522,40 @@ packages:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'}
+ pg-cloudflare@1.2.7:
+ resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==}
+
+ pg-connection-string@2.9.1:
+ resolution: {integrity: sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==}
+
+ pg-int8@1.0.1:
+ resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
+ engines: {node: '>=4.0.0'}
+
+ pg-pool@3.10.1:
+ resolution: {integrity: sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==}
+ peerDependencies:
+ pg: '>=8.0'
+
+ pg-protocol@1.10.3:
+ resolution: {integrity: sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==}
+
+ pg-types@2.2.0:
+ resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
+ engines: {node: '>=4'}
+
+ pg@8.16.3:
+ resolution: {integrity: sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==}
+ engines: {node: '>= 16.0.0'}
+ peerDependencies:
+ pg-native: '>=3.0.1'
+ peerDependenciesMeta:
+ pg-native:
+ optional: true
+
+ pgpass@1.0.5:
+ resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -3409,6 +3594,22 @@ packages:
resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
engines: {node: ^10 || ^12 || >=14}
+ postgres-array@2.0.0:
+ resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
+ engines: {node: '>=4'}
+
+ postgres-bytea@1.0.0:
+ resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
+ engines: {node: '>=0.10.0'}
+
+ postgres-date@1.0.7:
+ resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
+ engines: {node: '>=0.10.0'}
+
+ postgres-interval@1.2.0:
+ resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
+ engines: {node: '>=0.10.0'}
+
prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
@@ -3446,6 +3647,13 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
+ pvtsutils@1.3.6:
+ resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==}
+
+ pvutils@1.1.3:
+ resolution: {integrity: sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==}
+ engines: {node: '>=6.0.0'}
+
qrcode-terminal@0.11.0:
resolution: {integrity: sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==}
hasBin: true
@@ -3588,6 +3796,9 @@ packages:
resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==}
engines: {node: '>=0.10.0'}
+ reflect-metadata@0.2.2:
+ resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
+
reflect.getprototypeof@1.0.10:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
engines: {node: '>= 0.4'}
@@ -3680,6 +3891,9 @@ packages:
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
+ rou3@0.5.1:
+ resolution: {integrity: sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ==}
+
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
@@ -3742,6 +3956,9 @@ packages:
server-only@0.0.1:
resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
+ set-cookie-parser@2.7.1:
+ resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
+
set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
@@ -3838,6 +4055,10 @@ packages:
resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==}
engines: {node: '>=6'}
+ split2@4.2.0:
+ resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
+ engines: {node: '>= 10.x'}
+
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
@@ -4018,9 +4239,16 @@ packages:
tsconfig-paths@3.15.0:
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
+ tslib@1.14.1:
+ resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
+
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+ tsyringe@4.10.0:
+ resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==}
+ engines: {node: '>= 6.0.0'}
+
type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
@@ -4066,6 +4294,9 @@ packages:
resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
engines: {node: '>= 0.4'}
+ uncrypto@0.1.3:
+ resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
+
undici-types@7.14.0:
resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==}
@@ -4284,6 +4515,10 @@ packages:
resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==}
engines: {node: '>=8.0'}
+ xtend@4.0.2:
+ resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
+ engines: {node: '>=0.4'}
+
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
@@ -4320,6 +4555,9 @@ packages:
zod@3.25.76:
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
+ zod@4.1.12:
+ resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==}
+
snapshots:
'@0no-co/graphql.web@1.2.0': {}
@@ -4934,6 +5172,26 @@ snapshots:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
+ '@better-auth/core@1.3.27':
+ dependencies:
+ better-call: 1.0.19
+ zod: 4.1.12
+
+ '@better-auth/expo@1.3.27(better-auth@1.3.27(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(expo-constants@18.0.9)(expo-crypto@15.0.7(expo@54.0.13))(expo-linking@8.0.8)(expo-secure-store@15.0.7(expo@54.0.13))(expo-web-browser@15.0.8(expo@54.0.13)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0)))':
+ dependencies:
+ '@better-fetch/fetch': 1.1.18
+ better-auth: 1.3.27(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ expo-constants: 18.0.9(expo@54.0.13)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))
+ expo-crypto: 15.0.7(expo@54.0.13)
+ expo-linking: 8.0.8(expo@54.0.13)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
+ expo-secure-store: 15.0.7(expo@54.0.13)
+ expo-web-browser: 15.0.8(expo@54.0.13)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))
+ zod: 4.1.12
+
+ '@better-auth/utils@0.3.0': {}
+
+ '@better-fetch/fetch@1.1.18': {}
+
'@egjs/hammerjs@2.0.17':
dependencies:
'@types/hammerjs': 2.0.46
@@ -5311,6 +5569,8 @@ snapshots:
find-up: 5.0.0
js-yaml: 4.1.0
+ '@hexagon/base64@1.1.28': {}
+
'@humanfs/core@0.19.1': {}
'@humanfs/node@0.16.7':
@@ -5424,6 +5684,8 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
+ '@levischuck/tiny-cbor@0.2.11': {}
+
'@napi-rs/wasm-runtime@0.2.12':
dependencies:
'@emnapi/core': 1.5.0
@@ -5431,6 +5693,10 @@ snapshots:
'@tybys/wasm-util': 0.10.1
optional: true
+ '@noble/ciphers@2.0.1': {}
+
+ '@noble/hashes@2.0.1': {}
+
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -5445,6 +5711,102 @@ snapshots:
'@nolyfill/is-core-module@1.0.39': {}
+ '@peculiar/asn1-android@2.5.0':
+ dependencies:
+ '@peculiar/asn1-schema': 2.5.0
+ asn1js: 3.0.6
+ tslib: 2.8.1
+
+ '@peculiar/asn1-cms@2.5.0':
+ dependencies:
+ '@peculiar/asn1-schema': 2.5.0
+ '@peculiar/asn1-x509': 2.5.0
+ '@peculiar/asn1-x509-attr': 2.5.0
+ asn1js: 3.0.6
+ tslib: 2.8.1
+
+ '@peculiar/asn1-csr@2.5.0':
+ dependencies:
+ '@peculiar/asn1-schema': 2.5.0
+ '@peculiar/asn1-x509': 2.5.0
+ asn1js: 3.0.6
+ tslib: 2.8.1
+
+ '@peculiar/asn1-ecc@2.5.0':
+ dependencies:
+ '@peculiar/asn1-schema': 2.5.0
+ '@peculiar/asn1-x509': 2.5.0
+ asn1js: 3.0.6
+ tslib: 2.8.1
+
+ '@peculiar/asn1-pfx@2.5.0':
+ dependencies:
+ '@peculiar/asn1-cms': 2.5.0
+ '@peculiar/asn1-pkcs8': 2.5.0
+ '@peculiar/asn1-rsa': 2.5.0
+ '@peculiar/asn1-schema': 2.5.0
+ asn1js: 3.0.6
+ tslib: 2.8.1
+
+ '@peculiar/asn1-pkcs8@2.5.0':
+ dependencies:
+ '@peculiar/asn1-schema': 2.5.0
+ '@peculiar/asn1-x509': 2.5.0
+ asn1js: 3.0.6
+ tslib: 2.8.1
+
+ '@peculiar/asn1-pkcs9@2.5.0':
+ dependencies:
+ '@peculiar/asn1-cms': 2.5.0
+ '@peculiar/asn1-pfx': 2.5.0
+ '@peculiar/asn1-pkcs8': 2.5.0
+ '@peculiar/asn1-schema': 2.5.0
+ '@peculiar/asn1-x509': 2.5.0
+ '@peculiar/asn1-x509-attr': 2.5.0
+ asn1js: 3.0.6
+ tslib: 2.8.1
+
+ '@peculiar/asn1-rsa@2.5.0':
+ dependencies:
+ '@peculiar/asn1-schema': 2.5.0
+ '@peculiar/asn1-x509': 2.5.0
+ asn1js: 3.0.6
+ tslib: 2.8.1
+
+ '@peculiar/asn1-schema@2.5.0':
+ dependencies:
+ asn1js: 3.0.6
+ pvtsutils: 1.3.6
+ tslib: 2.8.1
+
+ '@peculiar/asn1-x509-attr@2.5.0':
+ dependencies:
+ '@peculiar/asn1-schema': 2.5.0
+ '@peculiar/asn1-x509': 2.5.0
+ asn1js: 3.0.6
+ tslib: 2.8.1
+
+ '@peculiar/asn1-x509@2.5.0':
+ dependencies:
+ '@peculiar/asn1-schema': 2.5.0
+ asn1js: 3.0.6
+ pvtsutils: 1.3.6
+ tslib: 2.8.1
+
+ '@peculiar/x509@1.14.0':
+ dependencies:
+ '@peculiar/asn1-cms': 2.5.0
+ '@peculiar/asn1-csr': 2.5.0
+ '@peculiar/asn1-ecc': 2.5.0
+ '@peculiar/asn1-pkcs9': 2.5.0
+ '@peculiar/asn1-rsa': 2.5.0
+ '@peculiar/asn1-schema': 2.5.0
+ '@peculiar/asn1-x509': 2.5.0
+ pvtsutils: 1.3.6
+ reflect-metadata: 0.2.2
+ tslib: 2.8.1
+ tsyringe: 4.10.0
+
'@pkgjs/parseargs@0.11.0':
optional: true
@@ -5822,6 +6184,19 @@ snapshots:
'@rtsao/scc@1.1.0': {}
+ '@simplewebauthn/browser@13.2.2': {}
+
+ '@simplewebauthn/server@13.2.2':
+ dependencies:
+ '@hexagon/base64': 1.1.28
+ '@levischuck/tiny-cbor': 0.2.11
+ '@peculiar/asn1-android': 2.5.0
+ '@peculiar/asn1-ecc': 2.5.0
+ '@peculiar/asn1-rsa': 2.5.0
+ '@peculiar/asn1-schema': 2.5.0
+ '@peculiar/asn1-x509': 2.5.0
+ '@peculiar/x509': 1.14.0
+
'@sinclair/typebox@0.27.8': {}
'@sinonjs/commons@3.0.1':
@@ -5884,6 +6259,12 @@ snapshots:
dependencies:
undici-types: 7.14.0
+ '@types/pg@8.15.5':
+ dependencies:
+ '@types/node': 24.7.1
+ pg-protocol: 1.10.3
+ pg-types: 2.2.0
+
'@types/react@19.1.17':
dependencies:
csstype: 3.1.3
@@ -6200,6 +6581,12 @@ snapshots:
asap@2.0.6: {}
+ asn1js@3.0.6:
+ dependencies:
+ pvtsutils: 1.3.6
+ pvutils: 1.1.3
+ tslib: 2.8.1
+
async-function@1.0.0: {}
async-limiter@1.0.1: {}
@@ -6341,6 +6728,33 @@ snapshots:
baseline-browser-mapping@2.8.15: {}
+ better-auth@1.3.27(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
+ dependencies:
+ '@better-auth/core': 1.3.27
+ '@better-auth/utils': 0.3.0
+ '@better-fetch/fetch': 1.1.18
+ '@noble/ciphers': 2.0.1
+ '@noble/hashes': 2.0.1
+ '@simplewebauthn/browser': 13.2.2
+ '@simplewebauthn/server': 13.2.2
+ better-call: 1.0.19
+ defu: 6.1.4
+ jose: 6.1.0
+ kysely: 0.28.8
+ nanostores: 1.0.1
+ zod: 4.1.12
+ optionalDependencies:
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+
+ better-call@1.0.19:
+ dependencies:
+ '@better-auth/utils': 0.3.0
+ '@better-fetch/fetch': 1.1.18
+ rou3: 0.5.1
+ set-cookie-parser: 2.7.1
+ uncrypto: 0.1.3
+
better-opn@3.0.2:
dependencies:
open: 8.4.2
@@ -6627,6 +7041,8 @@ snapshots:
has-property-descriptors: 1.0.2
object-keys: 1.1.1
+ defu@6.1.4: {}
+
depd@2.0.0: {}
destroy@1.2.0: {}
@@ -6995,6 +7411,11 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ expo-crypto@15.0.7(expo@54.0.13):
+ dependencies:
+ base64-js: 1.5.1
+ expo: 54.0.13(@babel/core@7.28.4)(@expo/metro-runtime@6.1.2)(expo-router@6.0.11)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
+
expo-file-system@19.0.17(expo@54.0.13)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0)):
dependencies:
expo: 54.0.13(@babel/core@7.28.4)(@expo/metro-runtime@6.1.2)(expo-router@6.0.11)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
@@ -7092,6 +7513,10 @@ snapshots:
- '@types/react-dom'
- supports-color
+ expo-secure-store@15.0.7(expo@54.0.13):
+ dependencies:
+ expo: 54.0.13(@babel/core@7.28.4)(@expo/metro-runtime@6.1.2)(expo-router@6.0.11)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
+
expo-server@1.0.1: {}
expo-splash-screen@31.0.10(expo@54.0.13):
@@ -7703,6 +8128,8 @@ snapshots:
jimp-compact@0.16.1: {}
+ jose@6.1.0: {}
+
js-tokens@4.0.0: {}
js-yaml@3.14.1:
@@ -7745,6 +8172,8 @@ snapshots:
kleur@3.0.3: {}
+ kysely@0.28.8: {}
+
lan-network@0.1.7: {}
leven@3.1.0: {}
@@ -8253,6 +8682,8 @@ snapshots:
nanoid@3.3.11: {}
+ nanostores@1.0.1: {}
+
napi-postinstall@0.3.4: {}
natural-compare@1.4.0: {}
@@ -8435,6 +8866,41 @@ snapshots:
lru-cache: 10.4.3
minipass: 7.1.2
+ pg-cloudflare@1.2.7:
+ optional: true
+
+ pg-connection-string@2.9.1: {}
+
+ pg-int8@1.0.1: {}
+
+ pg-pool@3.10.1(pg@8.16.3):
+ dependencies:
+ pg: 8.16.3
+
+ pg-protocol@1.10.3: {}
+
+ pg-types@2.2.0:
+ dependencies:
+ pg-int8: 1.0.1
+ postgres-array: 2.0.0
+ postgres-bytea: 1.0.0
+ postgres-date: 1.0.7
+ postgres-interval: 1.2.0
+
+ pg@8.16.3:
+ dependencies:
+ pg-connection-string: 2.9.1
+ pg-pool: 3.10.1(pg@8.16.3)
+ pg-protocol: 1.10.3
+ pg-types: 2.2.0
+ pgpass: 1.0.5
+ optionalDependencies:
+ pg-cloudflare: 1.2.7
+
+ pgpass@1.0.5:
+ dependencies:
+ split2: 4.2.0
+
picocolors@1.1.1: {}
picomatch@2.3.1: {}
@@ -8463,6 +8929,16 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ postgres-array@2.0.0: {}
+
+ postgres-bytea@1.0.0: {}
+
+ postgres-date@1.0.7: {}
+
+ postgres-interval@1.2.0:
+ dependencies:
+ xtend: 4.0.2
+
prelude-ls@1.2.1: {}
pretty-bytes@5.6.0: {}
@@ -8498,6 +8974,12 @@ snapshots:
punycode@2.3.1: {}
+ pvtsutils@1.3.6:
+ dependencies:
+ tslib: 2.8.1
+
+ pvutils@1.1.3: {}
+
qrcode-terminal@0.11.0: {}
query-string@7.1.3:
@@ -8694,6 +9176,8 @@ snapshots:
react@19.1.0: {}
+ reflect-metadata@0.2.2: {}
+
reflect.getprototypeof@1.0.10:
dependencies:
call-bind: 1.0.8
@@ -8790,6 +9274,8 @@ snapshots:
dependencies:
glob: 7.2.3
+ rou3@0.5.1: {}
+
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
@@ -8876,6 +9362,8 @@ snapshots:
server-only@0.0.1: {}
+ set-cookie-parser@2.7.1: {}
+
set-function-length@1.2.2:
dependencies:
define-data-property: 1.1.4
@@ -8975,6 +9463,8 @@ snapshots:
split-on-first@1.1.0: {}
+ split2@4.2.0: {}
+
sprintf-js@1.0.3: {}
stable-hash@0.0.5: {}
@@ -9175,8 +9665,14 @@ snapshots:
minimist: 1.2.8
strip-bom: 3.0.0
+ tslib@1.14.1: {}
+
tslib@2.8.1: {}
+ tsyringe@4.10.0:
+ dependencies:
+ tslib: 1.14.1
+
type-check@0.4.0:
dependencies:
prelude-ls: 1.2.1
@@ -9231,6 +9727,8 @@ snapshots:
has-symbols: 1.1.0
which-boxed-primitive: 1.1.1
+ uncrypto@0.1.3: {}
+
undici-types@7.14.0: {}
undici@6.22.0: {}
@@ -9445,6 +9943,8 @@ snapshots:
xmlbuilder@15.1.1: {}
+ xtend@4.0.2: {}
+
y18n@5.0.8: {}
yallist@3.1.1: {}
@@ -9472,3 +9972,5 @@ snapshots:
zod: 3.25.76
zod@3.25.76: {}
+
+ zod@4.1.12: {}
diff --git a/process-compose.yaml b/process-compose.yaml
new file mode 100644
index 0000000..c0e8216
--- /dev/null
+++ b/process-compose.yaml
@@ -0,0 +1,41 @@
+version: "0.5"
+
+log_location: .logs
+log_level: info
+
+settings:
+ server:
+ port: 0
+
+processes:
+ db:
+ command: |
+ export PGDATA="./.db"
+
+ # Initialize if needed
+ if [ ! -d "$PGDATA" ]; then
+ initdb --auth=trust --no-locale --encoding=UTF8 -U postgres
+ fi
+
+ # Start PostgreSQL in foreground
+ postgres -D "$PGDATA" -k /tmp -p 5432
+ readiness_probe:
+ exec:
+ command: "pg_isready -h localhost -p 5432 -U postgres"
+ initial_delay_seconds: 2
+ period_seconds: 1
+
+ expo:
+ command: "pnpm i && pnpm start"
+ environment:
+ - "DATABASE_URL=postgresql://postgres@localhost:5432/money"
+
+
+ migrate:
+ command: |
+ createdb -h localhost -p 5432 -U postgres money 2>/dev/null || true
+
+ echo "Migration and seeding complete!"
+ depends_on:
+ db:
+ condition: process_healthy