Skip to content

Commit 985ac54

Browse files
committed
add drizzle orm to the app
1 parent 1d251b2 commit 985ac54

21 files changed

+13469
-18616
lines changed

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,9 @@ yarn-error.*
3333

3434
# typescript
3535
*.tsbuildinfo
36+
37+
# @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
38+
# The following patterns were generated by expo-cli
39+
40+
expo-env.d.ts
41+
# @end expo-cli

.yarn/install-state.gz

1.38 MB
Binary file not shown.

.yarnrc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2+
# yarn lockfile v1
3+
4+
5+
yarn-path ".yarn/releases/yarn-1.22.22.cjs"

.yarnrc.yml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nodeLinker: node-modules

.zed/settings.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Folder-specific settings
2+
//
3+
// For a full list of overridable settings, and general information on folder-specific settings,
4+
// see the documentation: https://zed.dev/docs/configuring-zed#folder-specific-settings
5+
{}

app/(tabs)/index.tsx

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
import { StyleSheet } from 'react-native';
1+
import { StyleSheet } from "react-native";
22

3-
import EditScreenInfo from '@/components/EditScreenInfo';
4-
import { Text, View } from '@/components/Themed';
3+
import EditScreenInfo from "@/components/EditScreenInfo";
4+
import { Text, View } from "@/components/Themed";
55

66
export default function TabOneScreen() {
77
return (
88
<View style={styles.container}>
99
<Text style={styles.title}>Tab One</Text>
10-
<View style={styles.separator} lightColor="#eee" darkColor="rgba(255,255,255,0.1)" />
10+
<View
11+
style={styles.separator}
12+
lightColor="#eee"
13+
darkColor="rgba(255,255,255,0.1)"
14+
/>
1115
<EditScreenInfo path="app/(tabs)/index.tsx" />
1216
</View>
1317
);
@@ -16,16 +20,16 @@ export default function TabOneScreen() {
1620
const styles = StyleSheet.create({
1721
container: {
1822
flex: 1,
19-
alignItems: 'center',
20-
justifyContent: 'center',
23+
alignItems: "center",
24+
justifyContent: "center",
2125
},
2226
title: {
2327
fontSize: 20,
24-
fontWeight: 'bold',
28+
fontWeight: "bold",
2529
},
2630
separator: {
2731
marginVertical: 30,
2832
height: 1,
29-
width: '80%',
33+
width: "80%",
3034
},
3135
});

app/_layout.tsx

+22-15
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
1-
import FontAwesome from '@expo/vector-icons/FontAwesome';
2-
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
3-
import { useFonts } from 'expo-font';
4-
import { Stack } from 'expo-router';
5-
import * as SplashScreen from 'expo-splash-screen';
6-
import { useEffect } from 'react';
1+
import FontAwesome from "@expo/vector-icons/FontAwesome";
2+
import {
3+
DarkTheme,
4+
DefaultTheme,
5+
ThemeProvider,
6+
} from "@react-navigation/native";
7+
import { useFonts } from "expo-font";
8+
import { Stack } from "expo-router";
9+
import * as SplashScreen from "expo-splash-screen";
10+
import { useEffect } from "react";
711

8-
import { useColorScheme } from '@/components/useColorScheme';
12+
import { useColorScheme } from "@/components/useColorScheme";
13+
import MigrationProvider from "../components/MigrationProvider";
914

1015
export {
1116
// Catch any errors thrown by the Layout component.
1217
ErrorBoundary,
13-
} from 'expo-router';
18+
} from "expo-router";
1419

1520
export const unstable_settings = {
1621
// Ensure that reloading on `/modal` keeps a back button present.
17-
initialRouteName: '(tabs)',
22+
initialRouteName: "(tabs)",
1823
};
1924

2025
// Prevent the splash screen from auto-hiding before asset loading is complete.
2126
SplashScreen.preventAutoHideAsync();
2227

2328
export default function RootLayout() {
2429
const [loaded, error] = useFonts({
25-
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
30+
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
2631
...FontAwesome.font,
2732
});
2833

@@ -48,11 +53,13 @@ function RootLayoutNav() {
4853
const colorScheme = useColorScheme();
4954

5055
return (
51-
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
52-
<Stack>
53-
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
54-
<Stack.Screen name="modal" options={{ presentation: 'modal' }} />
55-
</Stack>
56+
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
57+
<MigrationProvider>
58+
<Stack>
59+
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
60+
<Stack.Screen name="modal" options={{ presentation: "modal" }} />
61+
</Stack>
62+
</MigrationProvider>
5663
</ThemeProvider>
5764
);
5865
}

babel.config.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module.exports = function (api) {
22
api.cache(true);
33
return {
4-
presets: ['babel-preset-expo']
4+
presets: ["babel-preset-expo"],
5+
plugins: [["inline-import", { extensions: [".sql"] }]],
56
};
67
};

components/MigrationProvider.tsx

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { useMigrations } from "drizzle-orm/expo-sqlite/migrator";
2+
import migrations from "../drizzle/migrations";
3+
import { View, Text } from "react-native";
4+
import React from "react";
5+
import { db } from "./db";
6+
7+
export default function MigrationProvider({
8+
children,
9+
}: React.PropsWithChildren) {
10+
const { success, error } = useMigrations(db, migrations);
11+
if (error) {
12+
return (
13+
<View>
14+
<Text>Migration error: {error.message}</Text>
15+
</View>
16+
);
17+
}
18+
if (!success) {
19+
return (
20+
<View>
21+
<Text>Migration is in progress...</Text>
22+
</View>
23+
);
24+
}
25+
return children;
26+
}

components/db.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { drizzle } from "drizzle-orm/expo-sqlite";
2+
import { openDatabaseSync } from "expo-sqlite/next";
3+
import * as schema from "@/db/schema";
4+
5+
const expoDb = openDatabaseSync("db.db");
6+
export const db = drizzle(expoDb, { schema });

db/schema.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { sql } from "drizzle-orm";
2+
import { text, integer, sqliteTable, blob } from "drizzle-orm/sqlite-core";
3+
4+
export const questions = sqliteTable("questions", {
5+
id: integer("id").primaryKey({ autoIncrement: true }),
6+
question: text("question").notNull(),
7+
answers: blob("answers").$type<string[]>().notNull(),
8+
});
9+
10+
export const answers = sqliteTable("answers", {
11+
id: integer("id").primaryKey({ autoIncrement: true }),
12+
questionId: text("questionId")
13+
.notNull()
14+
.references(() => questions.id),
15+
answer: integer("answer").notNull(),
16+
});

drizzle.config.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import type { Config } from 'drizzle-kit';
2+
export default {
3+
schema: './db/schema.ts',
4+
out: './drizzle',
5+
driver: 'expo', // <--- very important
6+
} satisfies Config;

drizzle/0000_safe_shadow_king.sql

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CREATE TABLE `answers` (
2+
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
3+
`questionId` text NOT NULL,
4+
`answer` integer NOT NULL,
5+
FOREIGN KEY (`questionId`) REFERENCES `questions`(`id`) ON UPDATE no action ON DELETE no action
6+
);
7+
--> statement-breakpoint
8+
CREATE TABLE `questions` (
9+
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
10+
`question` text NOT NULL,
11+
`answers` blob NOT NULL
12+
);

drizzle/meta/0000_snapshot.json

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
{
2+
"version": "5",
3+
"dialect": "sqlite",
4+
"id": "ceb773d3-4019-4f92-92fd-0ba6b21b30db",
5+
"prevId": "00000000-0000-0000-0000-000000000000",
6+
"tables": {
7+
"answers": {
8+
"name": "answers",
9+
"columns": {
10+
"id": {
11+
"name": "id",
12+
"type": "integer",
13+
"primaryKey": true,
14+
"notNull": true,
15+
"autoincrement": true
16+
},
17+
"questionId": {
18+
"name": "questionId",
19+
"type": "text",
20+
"primaryKey": false,
21+
"notNull": true,
22+
"autoincrement": false
23+
},
24+
"answer": {
25+
"name": "answer",
26+
"type": "integer",
27+
"primaryKey": false,
28+
"notNull": true,
29+
"autoincrement": false
30+
}
31+
},
32+
"indexes": {},
33+
"foreignKeys": {
34+
"answers_questionId_questions_id_fk": {
35+
"name": "answers_questionId_questions_id_fk",
36+
"tableFrom": "answers",
37+
"tableTo": "questions",
38+
"columnsFrom": [
39+
"questionId"
40+
],
41+
"columnsTo": [
42+
"id"
43+
],
44+
"onDelete": "no action",
45+
"onUpdate": "no action"
46+
}
47+
},
48+
"compositePrimaryKeys": {},
49+
"uniqueConstraints": {}
50+
},
51+
"questions": {
52+
"name": "questions",
53+
"columns": {
54+
"id": {
55+
"name": "id",
56+
"type": "integer",
57+
"primaryKey": true,
58+
"notNull": true,
59+
"autoincrement": true
60+
},
61+
"question": {
62+
"name": "question",
63+
"type": "text",
64+
"primaryKey": false,
65+
"notNull": true,
66+
"autoincrement": false
67+
},
68+
"answers": {
69+
"name": "answers",
70+
"type": "blob",
71+
"primaryKey": false,
72+
"notNull": true,
73+
"autoincrement": false
74+
}
75+
},
76+
"indexes": {},
77+
"foreignKeys": {},
78+
"compositePrimaryKeys": {},
79+
"uniqueConstraints": {}
80+
}
81+
},
82+
"enums": {},
83+
"_meta": {
84+
"schemas": {},
85+
"tables": {},
86+
"columns": {}
87+
}
88+
}

drizzle/meta/_journal.json

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"version": "5",
3+
"dialect": "sqlite",
4+
"entries": [
5+
{
6+
"idx": 0,
7+
"version": "5",
8+
"when": 1713255870936,
9+
"tag": "0000_safe_shadow_king",
10+
"breakpoints": true
11+
}
12+
]
13+
}

drizzle/migrations.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// This file is required for Expo/React Native SQLite migrations - https://orm.drizzle.team/quick-sqlite/expo
2+
3+
import journal from './meta/_journal.json';
4+
import m0000 from './0000_safe_shadow_king.sql';
5+
6+
export default {
7+
journal,
8+
migrations: {
9+
m0000
10+
}
11+
}
12+

metro.config.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const { getDefaultConfig } = require('expo/metro-config');
2+
/** @type {import('expo/metro-config').MetroConfig} */
3+
const config = getDefaultConfig(__dirname);
4+
config.resolver.sourceExts.push('sql'); // <--- add this
5+
module.exports = config;

0 commit comments

Comments
 (0)