Skip to content

Commit

Permalink
chore: Updating project no PR
Browse files Browse the repository at this point in the history
  • Loading branch information
iamhectorsosa committed May 8, 2024
1 parent b6c0e33 commit 543b118
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 52 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/production.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ jobs:
version: latest

- run: supabase link --project-ref $SUPABASE_PROJECT_ID --workdir ./apps/next
# - run: supabase db reset --linked --workdir ./apps/next
- run: supabase db reset --linked --workdir ./apps/next
- run: supabase db push --workdir ./apps/next
38 changes: 20 additions & 18 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,47 @@

Excited to hear that you are interested in contributing to this project! Thank you!

> Warning: This contributing guide is still work in progress.
> Warning: This contributing guide is **still** work in progress and subject to change.
## Modules structure

Modules are organzied in the `apps/` folder by framework. Each framework folder contains also runnable project along wit the modules source code.
### What is a module?

The modules contain async functions that abstract Supabase database interaction for the general use cases. They are located in `modules/` folder and are divided into subfolders by features (e.g. `user/` subfolder for authentication or profile management).
Modules are a contained group of logic to support a specific feature or domain (i.e., User Module contains authentication, profile, avatars, etc.). They could be as broad or specific as you would like, so long as they contain everything they need to operate independently.

The UI elements / parts are located in `components/` folder. The `components/ui` subfolder contains general purpose reusable UI elements. Other folders in the `components/` directory contain components per feature (e.g. user management components are in `components/user` subfolder).
High level modules should only be dependant on low level modules like User. If you create a module that is cross-depandant on multiple modules, you should consider combining these into a single module.

The `lib/` folder is for helpers used across the app.
Modules are organzied in the `apps/` folder by framework. Each framework folder contains also runnable project along wit the modules source code.

_Please perserve the described file structure when developing in the project._
### Module structure

## Code convention
Modules contain async functions (Server Actions) that abstract Supabase database interaction. They are located in `modules` directory and are divided into subdirectories by feature or domain (i.e., `user` module for authentication, profile, avatar, etc.).

Functions are declared with the `function` keyword.
- Each module contains supporting UI components to demo its functionality. These are located in the `components` directory.
- Module component structure should mimic the same structure as their supporting modules (i.e., `modules/user` module component should be located in `components/user` directory).
- The `components/ui` directory only contains general purpose UI elements.

### Components

We use [`shadcn/ui`](https://ui.shadcn.com/docs) for components in the project.

Names of UI component files are written in lowercase. If the name consists of two or more words use hyphen (e.g. `dynamic-navigation-links.tsx`).

Also note the usage of `cn()` utility. We use the own implementation from the `lib/utils` that wraps `clsx` utility with `twMerge`.
- We use [`shadcn/ui`](https://ui.shadcn.com/docs) for components in the project
- Names of UI component files are written in kebab case
- All components should be typed using `React.FC`
- All component-supporting functions should be declared using the keyword `function`
- To compose or combine CSS classes please make use of the `cn` utility from `lib/utils`

#### Zod

We use [`zod`](https://zod.dev/) for input validation and parsing values. It provides parsing and validation of values as well as static type inference.

### Data queries and manipulation

The UI parts implement some sort of functionality, many times related to the database. To fetch or manipulate data in the UI part component we use [`@tanstack/*-query`](https://tanstack.com/query/latest) library. There is a support for multiple javascript frameworks including React and Vue.
The UI parts implement some sort of functionality, many times related to the database. To fetch or manipulate data in the UI part component we use [`@tanstack/react-query`](https://tanstack.com/query/latest) library. There is a support for multiple javascript frameworks including React and Vue.

## Database

### Database development

Database can be developed locally using the Supabase Studio or Supabase CLI. After making changes to the DB it is necessary to save perserve them using migrations files. A migration file is a set of SQL commands that will be executed at database reset or init. It usually incorporates creation of the tables, setting security, creating custom functions and triggers, etc. Migration files are stored in the given framework project in the directory `supabase/migrations/` are prefixed with the timestamp, for example: `20240214100236_user.sql`.
Database development should take place locally using the Supabase Studio or Supabase CLI. After making changes to the DB it is necessary to save perserve them using migrations files. A migration file is a set of SQL commands that will be executed at database reset or init. It usually incorporates creation of the tables, setting security, creating custom functions and triggers, etc. Migration files are stored in the given framework project in the directory `supabase/migrations` are prefixed with the timestamp, for example: `20240214100236_user.sql`.

#### Save changes made to the database

Expand All @@ -52,11 +54,11 @@ supabase db diff --schema auth,public --use-migra user -f user

The above code will create a new migration file containing the new changes (that are not included in the previous migration files) with the "user" postfix in the `migrations` folder.

Due to modularity goals of this project, we also want to keep migrations file in the squashed format for given module. For example, in the `modules/user/` there is an `migrations.sql` that contains all the SQL code that should be applied to the DB when extracting only the user module to the target project. Currently there is not known Supabase CLI command that can create squashed migration file on table level, so this needs to be maintained manually every time new migrations for the given module are added to the `supabase/migrations/` folder.
Due to modularity goals of this project, we also want to keep migrations file in the squashed format for given module. For example, in the `modules/user` there is an `migrations.sql` that contains all the SQL code that should be applied to the DB when extracting only the user module to the target project. Currently there is not known Supabase CLI command that can create squashed migration file on table level, so this needs to be maintained manually every time new migrations for the given module are added to the `supabase/migrations` folder.

#### Applying changes from migrations to the database
#### Testing migration changes

To apply the changes from the migrations we can use the `reset` command. It will apply all SQL commands contained in the files in `supabase/migrations/` folder:
Test migration changes using the `reset` command. It will apply all SQL commands contained in the files in `supabase/migrations` folder:

```shell
supabase db reset
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ For example, our [Next.js](https://nextjs.org/) app looks like this:
- The logic lives in the `/modules` directory categorized by module name i.e. _user_.
- The database configuration lives in the `/supabase` directory where migrations can be identified by module name i.e. _20240214100236_user.sql_.

## Requirements

Requirements:

- Node: `>=20`,
- Package manager: `pnpm@8.15.1`

## Install

To install dependencies, run the following command from the root repository:
Expand All @@ -41,7 +48,7 @@ pnpm install

## Environment variables

Please refer to `.env.example` when working with environment variables. This repository is local-first development, so you should set all of your development variables in `.env.local` located in the root repository.
Please refer to `.env.example` when working with environment variables. This repository is local-first development, so you should set all of your development variables in `.env.local` located in the root repository.

If you want to connect to a remote Supabase instance you can set all of your variables in `.env` located in the root repository.

Expand Down
1 change: 1 addition & 0 deletions apps/next/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
}
}
],
"no-console": ["error", { "allow": ["error"] }],
"react/prop-types": "off",
"react/react-in-jsx-scope": "off",
"tailwindcss/no-custom-classname": "off",
Expand Down
3 changes: 2 additions & 1 deletion apps/next/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ node_modules
.next
.vscode
**/*.html
supabase
supabase
modules/types
18 changes: 15 additions & 3 deletions apps/next/components/user/login-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,18 @@ export const LoginForm: React.FC<{
searchParamError: error || null,
})

function handleAnonymousSignIn(): void {
anonymousSignIn.mutate({
redirect: {
url: "/guest",
},
})
}

return (
<LoginFormComponent
signIn={handleSignIn}
anonymousSignIn={() => anonymousSignIn.mutate({})}
anonymousSignIn={handleAnonymousSignIn}
isPending={signIn.isPending || passwordlessSignIn.isPending}
isError={isError}
errorMessage={errorMessage}
Expand Down Expand Up @@ -217,14 +225,18 @@ const LoginFormComponent: React.FC<{
/>
<Label htmlFor="OTP-login">Log in with One-Time password</Label>
</div>
<footer className="flex flex-col gap-2">
<footer className="flex flex-col gap-3">
<Button type="submit" disabled={isPending}>
{isPending && (
<CircleIcon className="mr-2 size-4 animate-spin" />
)}
{isLoginWithOTP ? "Email me a One-Time password" : "Sign in"}
</Button>
<Button type="button" onClick={anonymousSignIn}>
<Button
type="button"
variant="secondary"
onClick={anonymousSignIn}
>
Continue as guest
</Button>
<Button asChild variant="link">
Expand Down
2 changes: 0 additions & 2 deletions apps/next/modules/user/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ export async function signInAnonymously(
): Promise<void> {
const { redirect, ...credentials } = options
const supabase = createClient()
console.log({ credentials })

const { error } = await supabase.auth.signInAnonymously(credentials)
if (error) throw error
redirect?.url && _redirect(redirect.url, redirect.type)
Expand Down
27 changes: 17 additions & 10 deletions docs/modules/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ Then copy, paste and execute the contents of file `modules/user/migration.sql` i
## Authentication

Authentication supports the following methods:
* Sign ups using email and password
* Sign ins using email and password
* Sign ins using email One-Time password (OTP workflow)
* Password reset using email (Magic Link workflow)
* Updating credentials email and/or password

- Sign ups using email and password
- Sign ins using email and password
- Sign ins using email One-Time password (OTP workflow)
- Anonymous Sign ins
- Sign outs
- Password reset using email (Magic Link workflow)
- Updating credentials email and/or password

### `signUpWithEmailPassword`

Expand All @@ -41,18 +44,22 @@ Authentication supports the following methods:

<<< ../../apps/next/modules/user/auth.ts#signInWithOtp

### `verifyOtp`
### `signInAnonymously`

<<< ../../apps/next/modules/user/auth.ts#verifyOtp
<<< ../../apps/next/modules/user/auth.ts#signInAnonymously

### `resetPasswordForEmail`
### `verifyOtp`

<<< ../../apps/next/modules/user/auth.ts#resetPasswordForEmail
<<< ../../apps/next/modules/user/auth.ts#verifyOtp

### `signOut`

<<< ../../apps/next/modules/user/auth.ts#signOut

### `resetPasswordForEmail`

<<< ../../apps/next/modules/user/auth.ts#resetPasswordForEmail

### `updateUser`

<<< ../../apps/next/modules/user/auth.ts#updateUser
Expand All @@ -65,4 +72,4 @@ Authentication supports the following methods:

### `updateProfile`

<<< ../../apps/next/modules/user/profile.ts#updateProfile
<<< ../../apps/next/modules/user/profile.ts#updateProfile
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"db:gen-types": "turbo db:gen-types",
"email:dev": "turbo email:dev",
"email:export": "turbo email:export",
"lint": "turbo lint"
"lint": "turbo lint",
"format": "turbo format"
},
"devDependencies": {
"turbo": "^1.12.1",
Expand All @@ -21,4 +22,4 @@
"engines": {
"node": ">=20"
}
}
}
22 changes: 8 additions & 14 deletions turbo.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
{
"$schema": "https://turbo.build/schema.json",
"globalDotEnv": [
".env",
".env.local"
],
"globalDotEnv": [".env", ".env.local"],
"pipeline": {
"build": {
"outputs": [
Expand All @@ -14,19 +11,13 @@
]
},
"dev": {
"dotEnv": [
".env.local"
],
"dependsOn": [
"^build"
],
"dotEnv": [".env.local"],
"dependsOn": ["^build"],
"cache": false,
"persistent": true
},
"dev:remote": {
"dotEnv": [
".env"
]
"dotEnv": [".env"]
},
"db:start": {
"cache": false
Expand All @@ -46,6 +37,9 @@
},
"lint": {
"cache": false
},
"format": {
"cache": false
}
}
}
}

0 comments on commit 543b118

Please sign in to comment.