diff --git a/README.md b/README.md index 78cbe5d..aee3d47 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@

React Native CRUD

-

React Native Expo @@ -9,11 +8,11 @@ Expo Router NativeWind SQLite + Drizzle ORM Bun

-

- A full-featured CRUD application built with React Native, Expo Router, NativeWind, and SQLite. Create, read, update, and delete records with a clean, production-ready mobile interface. + A full-featured CRUD application built with React Native, Expo Router, NativeWind, Drizzle ORM, and SQLite. Create, read, update, and delete records with a clean, production-ready mobile interface.

--- @@ -21,7 +20,6 @@

Tech Stack

-

@@ -48,7 +46,13 @@ cd react-native-crud bun i ``` -### 3. Run the App (Start the development server): +### 3. Generate Database Migrations + +```bash +bun run db:generate +``` + +### 4. Run the App (Start the development server): ```bash bun run dev @@ -64,6 +68,28 @@ Open the app: --- +

+ Available Scripts +

+ +| Script | Description | +| ------------------------ | ----------------------------------------------- | +| `bun run dev` | Start the development server (with cache clear) | +| `bun run android` | Start on Android Emulator | +| `bun run ios` | Start on iOS Simulator | +| `bun run web` | Start on Web | +| `bun run db:generate` | Generate Drizzle ORM migration files | +| `bun run prebuild` | Rebuild native directories with Expo Prebuild | +| `bun run ios:native` | Run native iOS build | +| `bun run android:native` | Run native Android build | +| `bun run lint` | Check code with Biome | +| `bun run lint:fix` | Auto-fix lint issues with Biome | +| `bun run format` | Format code with Biome | +| `bun run typecheck` | Run TypeScript type checking | +| `bun test` | Run tests with Bun | + +--- +

Core Technologies

@@ -74,6 +100,8 @@ Open the app: - **TypeScript** – Type-safe development - **NativeWind** – Tailwind CSS for React Native - **SQLite (Expo SQLite)** – Local persistent storage for CRUD operations +- **Drizzle ORM** – Type-safe ORM for SQLite with migration support +- **Expo Crypto** – Cryptographic utilities for secure ID generation and hashing - **React Native Reusables** – Accessible UI component system --- @@ -84,6 +112,9 @@ Open the app: - Full CRUD operations — Create, Read, Update, and Delete records - Local data persistence with SQLite via Expo SQLite +- Type-safe database queries with Drizzle ORM +- Drizzle Studio integration via `expo-drizzle-studio-plugin` for database inspection during development +- Secure ID generation with Expo Crypto - Production-ready scalable structure - File-based routing with Expo Router - Dark mode support @@ -117,33 +148,53 @@ Before starting, ensure you have: react-native-crud/ ├── src/ │ ├── app/ # Expo Router routes -│ │ ├── _layout.tsx # Root layout -│ │ ├── index.tsx # Initial redirect │ │ ├── (auth)/ # Public auth routes -│ │ │ ├── _layout.tsx -│ │ │ ├── login.tsx -│ │ │ ├── forgot-password.tsx -│ │ │ └── reset-password.tsx -│ │ └── (app)/ # Protected app routes -│ │ ├── _layout.tsx -│ │ ├── index.tsx # Home (logged in) -│ │ ├── items/ -│ │ │ ├── index.tsx # List items -│ │ │ ├── new.tsx # Create item -│ │ │ └── [id].tsx # Edit / detail -│ │ └── settings.tsx # Settings & logout +│ │ │ ├── +html.tsx +│ │ │ ├── +not-found.tsx +│ │ │ └── _layout.tsx │ └── shared/ +│ ├── auth/ # Auth context & logic +│ │ ├── context.ts +│ │ ├── index.ts +│ │ └── provider.tsx +│ ├── components/ +│ │ ├── language/ # i18n / language components +│ │ │ ├── flags/ +│ │ │ └── index.tsx +│ │ └── ui/ # Reusable UI components +│ │ ├── forgot-password-form.tsx +│ │ ├── reset-password-form.tsx +│ │ ├── sign-in-form.tsx +│ │ ├── sign-up-form.tsx +│ │ ├── social-connections.tsx +│ │ ├── user-menu.tsx +│ │ └── verify-email-form.tsx +│ ├── constants/ +│ │ ├── Colors.ts +│ │ └── theme-icon.tsx │ ├── db/ # Database layer │ │ ├── client.ts # SQLite client setup -│ │ ├── migrations.ts # Schema migrations -│ │ ├── auth.ts # Auth queries -│ │ └── items.ts # Items queries (CRUD) -│ ├── providers/ -│ │ └── auth-provider.tsx # Auth context & session +│ │ ├── db-migration.tsx # Migration runner +│ │ ├── index.ts +│ │ ├── provider.tsx # DB context provider +│ │ └── schema.ts # Drizzle schema definitions +│ ├── hooks/ +│ │ ├── useAuth.ts +│ │ └── useColorScheme.ts +│ ├── lib/ +│ │ ├── theme.ts +│ │ └── utils.ts +│ ├── services/ +│ │ └── userService.ts │ └── types/ -│ └── auth.ts # Auth type definitions +│ ├── auth.ts +│ ├── icon.ts +│ └── locale.ts +├── tests/ # Test files ├── assets/ # Images and fonts +├── global.css # Global styles ├── app.json # Expo configuration +├── drizzle.config.ts # Drizzle Kit configuration ├── package.json # Dependencies ├── tailwind.config.js # NativeWind config ├── tsconfig.json # TypeScript config @@ -152,6 +203,30 @@ react-native-crud/ --- +

+ Database & Migrations +

+ +This project uses **Drizzle ORM** on top of **Expo SQLite** for type-safe, local database operations. + +### Generating Migrations + +After modifying the schema, run: + +```bash +bun run db:generate +``` + +This will generate SQL migration files inside the `drizzle/` folder using Drizzle Kit. + +### Inspecting the Database with Drizzle Studio + +With the development server running (`bun run dev`), press `Shift + M` in the terminal to open the Dev Tools menu, then select **`expo-drizzle-studio-plugin`** from the list. Drizzle Studio will open in a new browser tab, allowing you to browse and manage your local SQLite database visually. + +> **Note:** This plugin is available during native development only (iOS/Android). It does not work on Web. + +--- +

Adding Components

diff --git a/bun.lock b/bun.lock index 1baf995..d4d2330 100644 --- a/bun.lock +++ b/bun.lock @@ -22,6 +22,7 @@ "expo": "~54.0.29", "expo-constants": "~18.0.12", "expo-crypto": "15.0.8", + "expo-drizzle-studio-plugin": "^0.2.1", "expo-linking": "~8.0.10", "expo-localization": "~17.0.8", "expo-router": "~6.0.19", @@ -830,6 +831,8 @@ "expo-crypto": ["expo-crypto@15.0.8", "", { "dependencies": { "base64-js": "^1.3.0" }, "peerDependencies": { "expo": "*" } }, "sha512-aF7A914TB66WIlTJvl5J6/itejfY78O7dq3ibvFltL9vnTALJ/7LYHvLT4fwmx9yUNS6ekLBtDGWivFWnj2Fcw=="], + "expo-drizzle-studio-plugin": ["expo-drizzle-studio-plugin@0.2.1", "", { "peerDependencies": { "expo": ">=53.0.5", "expo-sqlite": ">=15.2.9" } }, "sha512-AjMC7SOutMAv/MkeJSp/26gnHLAA17SG8EtsjIKW6tDcBkq4plDVhjMLusoGe9f0vzYK8KrOvWjEWZ/R+KvIGg=="], + "expo-file-system": ["expo-file-system@19.0.21", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-s3DlrDdiscBHtab/6W1osrjGL+C2bvoInPJD7sOwmxfJ5Woynv2oc+Fz1/xVXaE/V7HE/+xrHC/H45tu6lZzzg=="], "expo-font": ["expo-font@14.0.11", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-ga0q61ny4s/kr4k8JX9hVH69exVSIfcIc19+qZ7gt71Mqtm7xy2c6kwsPTCyhBW2Ro5yXTT8EaZOpuRi35rHbg=="], diff --git a/package.json b/package.json index e5242c2..a3e4fa9 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "expo": "~54.0.29", "expo-constants": "~18.0.12", "expo-crypto": "15.0.8", + "expo-drizzle-studio-plugin": "^0.2.1", "expo-linking": "~8.0.10", "expo-localization": "~17.0.8", "expo-router": "~6.0.19", diff --git a/src/shared/db/provider.tsx b/src/shared/db/provider.tsx index 8240548..5d5dc9e 100644 --- a/src/shared/db/provider.tsx +++ b/src/shared/db/provider.tsx @@ -1,10 +1,18 @@ -import { SQLiteProvider } from "expo-sqlite"; +import { useDrizzleStudio } from "expo-drizzle-studio-plugin"; +import { SQLiteProvider, useSQLiteContext } from "expo-sqlite"; import type React from "react"; import { MigrationGate } from "./db-migration"; +function DrizzleStudio() { + const db = useSQLiteContext(); + useDrizzleStudio(db); + return null; +} + export function DbProvider({ children }: { children: React.ReactNode }) { return ( + {children} );