feat: add auth to zero queries
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -31,7 +31,7 @@ yarn-error.*
|
||||
*.pem
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
.env
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
|
||||
3
app.json
3
app.json
@@ -38,7 +38,8 @@
|
||||
"backgroundColor": "#000000"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"expo-sqlite"
|
||||
],
|
||||
"experiments": {
|
||||
"typedRoutes": true,
|
||||
|
||||
@@ -3,23 +3,50 @@ import 'react-native-reanimated';
|
||||
|
||||
import { authClient } from '@/lib/auth-client';
|
||||
import { ZeroProvider } from '@rocicorp/zero/react';
|
||||
import { zero } from '@/lib/zero';
|
||||
import { useMemo } from 'react';
|
||||
import { authDataSchema } from '@/shared/src/auth';
|
||||
import { Platform } from 'react-native';
|
||||
import type { ZeroOptions } from '@rocicorp/zero';
|
||||
import { schema, type Schema } from '@/shared/src';
|
||||
import { expoSQLiteStoreProvider } from "@rocicorp/zero/react-native";
|
||||
|
||||
export const unstable_settings = {
|
||||
anchor: '(tabs)',
|
||||
anchor: 'index',
|
||||
};
|
||||
|
||||
const kvStore = Platform.OS === "web" ? undefined : expoSQLiteStoreProvider();
|
||||
|
||||
export default function RootLayout() {
|
||||
const { data, isPending } = authClient.useSession();
|
||||
const { data: session, isPending } = authClient.useSession();
|
||||
|
||||
const authData = useMemo(() => {
|
||||
const result = authDataSchema.safeParse(session);
|
||||
return result.success ? result.data : null;
|
||||
}, [session]);
|
||||
|
||||
const cookie = useMemo(() => {
|
||||
return Platform.OS == 'web' ? undefined : authClient.getCookie();
|
||||
}, [session, isPending]);
|
||||
|
||||
const zeroProps = useMemo(() => {
|
||||
return {
|
||||
storageKey: 'money',
|
||||
kvStore,
|
||||
server: 'http://localhost:4848',
|
||||
userID: authData?.user.id ?? "anon",
|
||||
schema,
|
||||
// mutators: createMutators(),
|
||||
auth: cookie,
|
||||
} as const satisfies ZeroOptions<Schema>;
|
||||
}, [authData, cookie]);
|
||||
|
||||
return (
|
||||
<ZeroProvider zero={zero}>
|
||||
<ZeroProvider {...zeroProps}>
|
||||
<Stack>
|
||||
<Stack.Protected guard={!isPending && !!data}>
|
||||
<Stack.Protected guard={!isPending && !!session}>
|
||||
<Stack.Screen name="index" />
|
||||
</Stack.Protected>
|
||||
<Stack.Protected guard={!isPending && !data}>
|
||||
<Stack.Protected guard={!isPending && !session}>
|
||||
<Stack.Screen name="auth" />
|
||||
</Stack.Protected>
|
||||
</Stack>
|
||||
|
||||
@@ -5,15 +5,15 @@ import { useQuery, useZero } from "@rocicorp/zero/react";
|
||||
import { queries } from '@money/shared';
|
||||
|
||||
export default function HomeScreen() {
|
||||
const { data } = authClient.useSession();
|
||||
const { data: session } = authClient.useSession();
|
||||
const onLogout = () => {
|
||||
authClient.signOut();
|
||||
}
|
||||
const [transactions] = useQuery(queries.allTransactions());
|
||||
const [transactions] = useQuery(queries.allTransactions(session));
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Text>Hello {data?.user.name}</Text>
|
||||
<Text>Hello {session?.user.name}</Text>
|
||||
<Button onPress={onLogout} title="Logout" />
|
||||
<Text>Transactions: {JSON.stringify(transactions, null, 4)}</Text>
|
||||
</SafeAreaView>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import {Zero} from '@rocicorp/zero';
|
||||
import { schema } from "@money/shared";
|
||||
|
||||
export const zero = new Zero({
|
||||
userID: 'anon',
|
||||
server: 'http://localhost:4848',
|
||||
schema,
|
||||
});
|
||||
@@ -2,6 +2,9 @@ const { getDefaultConfig } = require("expo/metro-config");
|
||||
|
||||
const config = getDefaultConfig(__dirname)
|
||||
|
||||
// Add wasm asset support
|
||||
config.resolver.assetExts.push("wasm");
|
||||
|
||||
config.resolver.unstable_enablePackageExports = true;
|
||||
|
||||
module.exports = config;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"expo-linking": "~8.0.8",
|
||||
"expo-router": "~6.0.11",
|
||||
"expo-splash-screen": "~31.0.10",
|
||||
"expo-sqlite": "~16.0.8",
|
||||
"expo-status-bar": "~3.0.8",
|
||||
"expo-symbols": "~1.0.7",
|
||||
"expo-system-ui": "~6.0.7",
|
||||
|
||||
22
pnpm-lock.yaml
generated
22
pnpm-lock.yaml
generated
@@ -56,6 +56,9 @@ importers:
|
||||
expo-splash-screen:
|
||||
specifier: ~31.0.10
|
||||
version: 31.0.10(expo@54.0.13)
|
||||
expo-sqlite:
|
||||
specifier: ~16.0.8
|
||||
version: 16.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-status-bar:
|
||||
specifier: ~3.0.8
|
||||
version: 3.0.8(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||
@@ -2574,6 +2577,9 @@ packages:
|
||||
avvio@9.1.0:
|
||||
resolution: {integrity: sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==}
|
||||
|
||||
await-lock@2.2.2:
|
||||
resolution: {integrity: sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==}
|
||||
|
||||
babel-jest@29.7.0:
|
||||
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
@@ -3424,6 +3430,13 @@ packages:
|
||||
peerDependencies:
|
||||
expo: '*'
|
||||
|
||||
expo-sqlite@16.0.8:
|
||||
resolution: {integrity: sha512-xw776gFgH4ZM5oGs0spSLNmkHO/kJ/EuRXGzE4/22yII9EmG84vm7aM/M2aEb8taBTqwhSGYUpkwkRT5YFFmsg==}
|
||||
peerDependencies:
|
||||
expo: '*'
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
|
||||
expo-status-bar@3.0.8:
|
||||
resolution: {integrity: sha512-L248XKPhum7tvREoS1VfE0H6dPCaGtoUWzRsUv7hGKdiB4cus33Rc0sxkWkoQ77wE8stlnUlL5lvmT0oqZ3ZBw==}
|
||||
peerDependencies:
|
||||
@@ -9041,6 +9054,8 @@ snapshots:
|
||||
'@fastify/error': 4.2.0
|
||||
fastq: 1.19.1
|
||||
|
||||
await-lock@2.2.2: {}
|
||||
|
||||
babel-jest@29.7.0(@babel/core@7.28.4):
|
||||
dependencies:
|
||||
'@babel/core': 7.28.4
|
||||
@@ -10124,6 +10139,13 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
expo-sqlite@16.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):
|
||||
dependencies:
|
||||
await-lock: 2.2.2
|
||||
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)
|
||||
react: 19.1.0
|
||||
react-native: 0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0)
|
||||
|
||||
expo-status-bar@3.0.8(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||
dependencies:
|
||||
react: 19.1.0
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { syncedQuery } from "@rocicorp/zero";
|
||||
import { syncedQueryWithContext } from "@rocicorp/zero";
|
||||
import { z } from "zod";
|
||||
import { builder } from "@money/shared";
|
||||
import type { AuthData } from "./auth";
|
||||
import { isLoggedIn } from "./zql";
|
||||
|
||||
export const queries = {
|
||||
allTransactions: syncedQuery('allTransactions', z.tuple([]), () =>
|
||||
builder.transaction.limit(10)
|
||||
allTransactions: syncedQueryWithContext('allTransactions', z.tuple([]), (authData: AuthData | null) => {
|
||||
isLoggedIn(authData);
|
||||
return builder.transaction
|
||||
.where('user_id', '=', authData.user.id)
|
||||
.limit(10)
|
||||
}
|
||||
),
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createSchema, table, string, number, createBuilder, definePermissions } from "@rocicorp/zero";
|
||||
import { type Schema as ZeroSchema, createSchema, table, string, number, createBuilder, definePermissions } from "@rocicorp/zero";
|
||||
|
||||
const transaction = table('transaction')
|
||||
.columns({
|
||||
@@ -7,13 +7,20 @@ const transaction = table('transaction')
|
||||
name: string(),
|
||||
amount: number(),
|
||||
})
|
||||
.primaryKey('id');
|
||||
.primaryKey('id').schema;
|
||||
|
||||
export const schema = createSchema({
|
||||
tables: [transaction],
|
||||
export const schema = {
|
||||
tables: { transaction },
|
||||
relationships: {},
|
||||
enableLegacyMutators: false,
|
||||
enableLegacyQueries: false,
|
||||
});
|
||||
} satisfies ZeroSchema;
|
||||
|
||||
// export const schema = createSchema({
|
||||
// tables: [transaction],
|
||||
// enableLegacyMutators: false,
|
||||
// enableLegacyQueries: false,
|
||||
// });
|
||||
|
||||
export const builder = createBuilder(schema);
|
||||
|
||||
|
||||
9
shared/src/zql.ts
Normal file
9
shared/src/zql.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { AuthData } from "./auth";
|
||||
|
||||
export function isLoggedIn(
|
||||
authData: AuthData | null,
|
||||
): asserts authData is AuthData {
|
||||
if (!authData?.user.id) {
|
||||
throw new Error("User is not logged in");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user