Compare commits
51 Commits
@nhost/cli
...
@nhost/rea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ff9abee6a | ||
|
|
9d3f0521a5 | ||
|
|
744fd6929f | ||
|
|
f43f52e766 | ||
|
|
fd4c54ee91 | ||
|
|
b30ff6f507 | ||
|
|
ff7ae21a87 | ||
|
|
6d2c7b26c0 | ||
|
|
d2d3ba6eb7 | ||
|
|
e688600ea2 | ||
|
|
d9aec711c4 | ||
|
|
9bd01e756f | ||
|
|
8f7643a90e | ||
|
|
50b9d763ae | ||
|
|
63cb1f0ce6 | ||
|
|
7c70b1823d | ||
|
|
d2aae774a0 | ||
|
|
322e8a1b07 | ||
|
|
d154f8d71b | ||
|
|
0931afd84c | ||
|
|
837548cfd5 | ||
|
|
a6cabbca79 | ||
|
|
82f19fe717 | ||
|
|
82be281153 | ||
|
|
0112ca775f | ||
|
|
b30b812b93 | ||
|
|
bace64c306 | ||
|
|
be49b641e3 | ||
|
|
5ac8c2f516 | ||
|
|
168ae1d82b | ||
|
|
b4a2e28fc3 | ||
|
|
ca3ae21286 | ||
|
|
9f30c1af09 | ||
|
|
e1f9f64910 | ||
|
|
2634dd8335 | ||
|
|
42b4c78d4c | ||
|
|
54174c1b0f | ||
|
|
9fad359ae9 | ||
|
|
1cbf460223 | ||
|
|
8a3aa007b8 | ||
|
|
21b02a39e4 | ||
|
|
0d8afde2c3 | ||
|
|
f366158d02 | ||
|
|
2c8aac2123 | ||
|
|
2d9f6fbcfc | ||
|
|
31c845823d | ||
|
|
f949da055e | ||
|
|
0cd1654f88 | ||
|
|
a71ae28192 | ||
|
|
bd56c3522b | ||
|
|
a00152b8b6 |
@@ -25,6 +25,6 @@ esbuild
|
||||
platform: 'browser',
|
||||
format: 'esm',
|
||||
sourcemap: true,
|
||||
target: 'esnext'
|
||||
target: 'es2019'
|
||||
})
|
||||
.catch(() => process.exit(1))
|
||||
|
||||
@@ -38,10 +38,11 @@ export default defineConfig({
|
||||
fileName: 'index'
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ['react'],
|
||||
external: ['react', '@nhost/react'],
|
||||
output: {
|
||||
globals: {
|
||||
react: 'react'
|
||||
react: 'react',
|
||||
'@nhost/react': '@nhost/react'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
.github/workflows/changesets.yaml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
|
||||
- uses: pnpm/action-setup@v2.1.0
|
||||
with:
|
||||
version: 6.30.1
|
||||
version: 6.32.3
|
||||
run_install: true
|
||||
|
||||
- name: Create PR or Publish release
|
||||
|
||||
59
.github/workflows/tests.yaml
vendored
@@ -27,45 +27,44 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x, 14.x, 16.x]
|
||||
|
||||
node-version: [14, 16]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Cache pnpm modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.pnpm-store
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-
|
||||
|
||||
- uses: pnpm/action-setup@v2.0.1
|
||||
with:
|
||||
version: 6.30.1
|
||||
run_install: true
|
||||
|
||||
- name: Cache turbo
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ./node_modules/.cache
|
||||
key: ${{ runner.os }}-${{ matrix.node-version }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ matrix.node-version }}
|
||||
|
||||
- name: Install nhost CLI
|
||||
run: curl -L https://raw.githubusercontent.com/nhost/cli/main/get.sh | bash
|
||||
|
||||
- name: Start Nhost Backend
|
||||
run: |
|
||||
cd examples/testing-project
|
||||
cp -R examples/testing-project /tmp/
|
||||
cd /tmp/testing-project
|
||||
nhost dev &
|
||||
|
||||
nhost dev -d --no-browser &
|
||||
- name: Wait for Nhost Backend to start
|
||||
run: |
|
||||
pnpm dlx wait-on http://localhost:1337/v1/auth/healthz -i 500 -t 120000
|
||||
- uses: pnpm/action-setup@v2.2.1
|
||||
with:
|
||||
version: 6.32.3
|
||||
|
||||
- run: pnpm run ci
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Cache turbo
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ./node_modules/.cache/turbo
|
||||
key: turbo-${{ github.job }}-${{ github.ref_name }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
turbo-${{ github.job }}-${{ github.ref_name }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Wait for Nhost
|
||||
run: pnpm run wait
|
||||
|
||||
- name: Build, tests and lint
|
||||
run: pnpm run ci
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
**Nhost is a serverless backend for web and mobile apps** and is built with the following things in mind:
|
||||
**Nhost is a serverless backend for web and mobile apps** built with the following things in mind:
|
||||
|
||||
- Open Source
|
||||
- Developer Productivity
|
||||
@@ -36,6 +36,13 @@ Nhost consists of open source software:
|
||||
- Serverless Functions: Node.js (JavaScript and TypeScript)
|
||||
- [Nhost CLI](https://docs.nhost.io/reference/cli) for local development
|
||||
|
||||
<div align="center">
|
||||
<br />
|
||||
<img src="assets/nhost-diagram.png"/>
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
|
||||
Visit [https://docs.nhost.io](http://docs.nhost.io) for the complete documentation.
|
||||
|
||||
# How to get started
|
||||
|
||||
BIN
assets/nhost-diagram.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
@@ -2,12 +2,15 @@
|
||||
|
||||
## Get started
|
||||
|
||||
1. Install dependencies: `yarn`
|
||||
2. Start dev server: `yarn dev`
|
||||
From the **root** of the `nhost/nhost` repository:
|
||||
|
||||
## NOTES;
|
||||
```bash
|
||||
pnpm run clean:all
|
||||
pnpm i
|
||||
cd docs
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
The content is copied from the main `nhost/nhost` repo. This repo is only to modify styles/react components.
|
||||
|
||||
## Structure
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ const CustomLink = ({
|
||||
const components = {
|
||||
img: (props: DetailedHTMLProps<HTMLProps<HTMLImageElement>, HTMLImageElement>) => {
|
||||
return (
|
||||
<span className="block mx-10 mt-5 ">
|
||||
<span className="block mx-10 my-10 ">
|
||||
<img src={props.src} alt={props.alt} className="mx-auto mt-2" />
|
||||
</span>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: Sign In with Facebook
|
||||
---
|
||||
|
||||
Follow this guide to sign in users with Facebook with your Nhost App.
|
||||
|
||||

|
||||
|
||||
# Create Facebook account
|
||||
|
||||
- Create a new [Facebook account](https://www.facebook.com/) if you don’t have one already.
|
||||
|
||||
## Create Facebook App
|
||||
|
||||
- Go to [Meta for Developers](https://developers.facebook.com/).
|
||||
- Click **My Apps** in the top right
|
||||
- Click **Create App** in the top right.
|
||||
- Select your **app type** (e.g. Consumer).
|
||||
- Click **Next**.
|
||||
- Fill in the **Display name.**
|
||||
- Click **Create app**.
|
||||
|
||||
## Set up Facebook Login
|
||||
|
||||
- Click on Add Product in the left menu.
|
||||
- Click on Setup in the Facebook login card.
|
||||
- **Don’t** complete the quickstart. Instead, follow the next step.
|
||||
- Click on **Settings** under **Facebook Login** in the left menu.
|
||||
- Make sure **Embedded Browser OAuth Login** is set to **Yes**.
|
||||
- Fill in **Valid OAuth Redirect URIs** with your **OAuth Callback URL** from Nhost.
|
||||
- Click **Save changes**.
|
||||
|
||||
## Activate Facebook permissions and features
|
||||
|
||||
To make sure we can fetch all user data (email, profile picture and name). For that we need to enable **email** and **public_profile** permissions.
|
||||
|
||||
- Click on App Review and Permission and Features in the left menu
|
||||
- Search and for **email** in the **Search Permissions and Features** search box**.**
|
||||
- Click on Request advanced access and complete the steps.
|
||||
- Search and for **public_profile** in the **Search Permissions and Features** search box**.**
|
||||
- Click on **Request advanced access** and complete the steps.
|
||||
|
||||
## Configure Nhost
|
||||
|
||||
- Click **Settings** and then **Basic** in the left menu.
|
||||
- Copy and paste the **App ID (Client ID)** and **App secret (Client Secret)** from Facebook to your Nhost OAuth settings for Facebook. Make sure the [OAuth provider is enabled in Nhost](/platform/authentication/social-sign-in#enabling-social-sign-in).
|
||||
- Click the checkbox “**I have pasted the redirect URI into Facebook”**.
|
||||
- Click **Confirm settings**.
|
||||
|
||||
## Sign In users in your app
|
||||
|
||||
Use the [Nhost JavaScript client](/reference/sdk) to sign in users in your app:
|
||||
|
||||
```js
|
||||
nhost.auth.signIn({
|
||||
provider: 'facebook'
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Sign In with GitHub
|
||||
---
|
||||
|
||||
Follow this guide to sign in users with GitHub with your Nhost App.
|
||||
|
||||

|
||||
|
||||
# Create GitHub account
|
||||
|
||||
- Create a new [GitHub account](https://github.com/signup) if you don’t have one already.
|
||||
|
||||
## Create GitHub OAuth App
|
||||
|
||||
- Create a new OAuth application [(direct link)](https://github.com/settings/applications/new) by:
|
||||
- Click on your profile photo in the top right.
|
||||
- Click on Settings
|
||||
- In the left menu, click Developer settings at the bottom.
|
||||
- Click on Oauth Apps in the left menu
|
||||
- Click on New OAuth App button in the top right
|
||||
|
||||
## GitHub OAuth App information
|
||||
|
||||
- Fill in Application Name
|
||||
- Fill in Homepage URL
|
||||
- Fill in **Authorization callback URL** with your OAuth Callbacke URL from Nhost
|
||||
|
||||
## Configure Nhost
|
||||
|
||||
- Click Generate a new client secret to generate a OAuth client secret.
|
||||
- Copy and paste the **Client ID** and **Client Secret** from GitHub to your Nhost OAuth settings for GitHub. Make sure the [OAuth provider is enabled in Nhost](/platform/authentication/social-sign-in#enabling-social-sign-in).
|
||||
- Click the checkbox “**I have pasted the redirect URI into GitHub”**.
|
||||
- Click **Confirm settings**.
|
||||
|
||||
## Sign In users in your app
|
||||
|
||||
Use the [Nhost JavaScript client](/reference/sdk) to sign in users in your app:
|
||||
|
||||
```js
|
||||
nhost.auth.signIn({
|
||||
provider: 'github'
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: Sign In with Google
|
||||
---
|
||||
|
||||
Follow this guide to sign in users with Google with your Nhost App.
|
||||
|
||||

|
||||
|
||||
## Sign up for Google
|
||||
|
||||
- Sign up for [Google Cloud](https://cloud.google.com/free) if you don’t have one already.
|
||||
|
||||
## Create a Google Cloud Project
|
||||
|
||||
> 💡 You can skip this step if you already have a Google Cloud project you want to use.
|
||||
|
||||
- Create a new Google Cloud project if you don’t already have a project you want to use.
|
||||
|
||||
## Configure OAuth consent screen
|
||||
|
||||
- Search for **OAuth consent screen** in the top search bar in the Google Cloud Console.
|
||||
- Click on **OAuth consent screen** in the search results.
|
||||
- Select User Type **External** and click **CREATE**.
|
||||
|
||||
## **Edit app registration**
|
||||
|
||||
### OAuth consent screen
|
||||
|
||||
- Fill in your App information.
|
||||
- Click **SAVE AND CONTINUE.**
|
||||
|
||||
### Scopes
|
||||
|
||||
- Click **SAVE AND CONTINUE**.
|
||||
|
||||
### Test user
|
||||
|
||||
- Click **SAVE AND CONTINUE**.
|
||||
|
||||
### Summary
|
||||
|
||||
- Click **BACK TO DASHBOARD**.
|
||||
|
||||
## Create credentials
|
||||
|
||||
- Click on **Credentials** under **APIs & Services** in the left menu.
|
||||
- Click **+ CREATE CREDENTIALS** and then **OAuth client ID** in the top menu.
|
||||
- On the **Create OAuth client ID** page for **Application Type** select **Web application**.
|
||||
- Under **Authorized redirect URIs** add your **OAuth Callback URL** from Nhost.
|
||||
- Click **CREATE**.
|
||||
|
||||
## Configure Nhost
|
||||
|
||||
- A modal appears with your Google Client ID and Client secret.
|
||||
- Copy and paste the **Client ID** and **Client Secret** from Google to your Nhost OAuth settings for Google. Make sure the [OAuth provider is enabled in Nhost](/platform/authentication/social-sign-in#enabling-social-sign-in).
|
||||
- Click the checkbox “**I have pasted the redirect URI into Google”**.
|
||||
- Click **Confirm settings**.
|
||||
|
||||
## Sign In users in your app
|
||||
|
||||
Use the [Nhost JavaScript client](/reference/sdk) to sign in users in your app:
|
||||
|
||||
```js
|
||||
nhost.auth.signIn({
|
||||
provider: 'google'
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: Sign In with LinkedIn
|
||||
---
|
||||
|
||||
Follow this guide to sign in users with LinkedIn with your Nhost App.
|
||||
|
||||

|
||||
|
||||
## Create LinkedIn account
|
||||
|
||||
- Create a [LinkedIn account](https://linkedin.com/) if you don't have one already.
|
||||
|
||||
## Create LinkedIn OAuth App
|
||||
|
||||
- Go to the [LinkedIn Developer Dashboard](https://www.linkedin.com/developers/apps).
|
||||
- Click on Create App in the top right.
|
||||
- Fill in **App Name**, **LinkedIn Page** and **App Logo**.
|
||||
- Click **“I have read and agree to these terms”**.
|
||||
- Click **Create app** in the bottom right.
|
||||
|
||||
## LinkedIn OAuth App information
|
||||
|
||||
- Click on **Auth** in the top menu.
|
||||
- Click on the **pen icon** under **OAuth 2.0 settings** and right next to **Authorized redirect URLs for your app.**
|
||||
- Click **Add redirect URL**.
|
||||
- Copy and past the **OAuth Callback URL** from Nhost.
|
||||
- Click **Update**.
|
||||
|
||||
## Configure Nhost
|
||||
|
||||
- Copy and paste the **Client ID** and **Client Secret** from LinkedIn to your Nhost OAuth settings for LinkedIn.
|
||||
- Click the checkbox “**I have pasted the redirect URI into LinkedIn”**.
|
||||
- Click **Confirm settings**.
|
||||
|
||||
## Enable Auth for your LinkedIn OAuth App
|
||||
|
||||
- Click on **Products** in the top menu
|
||||
- Click Select on the **Sign In with LinkedIn**.
|
||||
- Check the checkbox **I have read and agree to these terms.**
|
||||
- Click **Add product**.
|
||||
|
||||
## Sign In users in your app
|
||||
|
||||
Use the [Nhost JavaScript client](/reference/sdk) to sign in users in your app:
|
||||
|
||||
```js
|
||||
nhost.auth.signIn({
|
||||
provider: 'linkedin'
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Sign In with Spotify
|
||||
---
|
||||
|
||||
Follow this guide to sign in users with Spotify with your Nhost App.
|
||||
|
||||

|
||||
|
||||
# Create Spotify account
|
||||
|
||||
- Create a new [Spotify account](https://www.spotify.com/) if you don't have one already.
|
||||
|
||||
## Create Spotify App
|
||||
|
||||
- Go to the [Spotify Developer Dashboard](https://developer.spotify.com/dashboard/).
|
||||
- Click on CREATE AN APP.
|
||||
- Fill in a App name and App description
|
||||
- Check the box to aggre Spotify's [Developer Terms of Service](https://developer.spotify.com/terms) and [Branding Guidelines](https://developer.spotify.com/branding-guidelines).
|
||||
|
||||
## Configure OAuth Callback URL
|
||||
|
||||
- Click EDIT SETTINGS
|
||||
- A modal appears
|
||||
- Fill in **Redirect URIs** with your **OAuth Callback URL** from Nhost.
|
||||
- Click ADD to add the OAuth callback URL.
|
||||
- Click SAVE.
|
||||
|
||||
## Configure Nhost
|
||||
|
||||
- Click SHOW CLIENT SECRET in the Spotify App Dashboard.
|
||||
- Copy and paste the **Client ID** and **Client Secret** from Spotify to your Nhost OAuth settings for Spotify.
|
||||
- Click the checkbox “**I have pasted the redirect URI into Spotify”**.
|
||||
- Click **Confirm settings**.
|
||||
|
||||
## Sign In users in your app
|
||||
|
||||
Use the [Nhost JavaScript client](/reference/sdk) to sign in users in your app:
|
||||
|
||||
```js
|
||||
nhost.auth.signIn({
|
||||
provider: 'spotify'
|
||||
})
|
||||
```
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
title: 'Social login'
|
||||
---
|
||||
|
||||
Nhost Auth supports the following social login providers:
|
||||
|
||||
- GitHub
|
||||
- Google
|
||||
- Facebook
|
||||
- LinkedIn
|
||||
|
||||
---
|
||||
|
||||
## Enabling social login
|
||||
|
||||
To start with social login, select your app in Nhost Console and go to **Users** → **Login settings**.
|
||||
|
||||
Enabling any of the supported login providers requires a developer account for the selected login provider. Follow the on-screen instructions to enable the login method of your choosing.
|
||||
|
||||
---
|
||||
|
||||
## Implementing login experience
|
||||
|
||||
To implement social login in your app, use the [Nhost JavaScript SDK](/reference/sdk) and the `signIn()` method:
|
||||
|
||||
```js
|
||||
nhost.auth.signIn({
|
||||
provider: 'github'
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## OAuth scopes
|
||||
|
||||
Scopes are a mechanism in OAuth to allow or limit an application's access to a user's account.
|
||||
|
||||
By default, Nhost sets the scope to get the name, email and avatar for each user. Editing scope is not currently supported.
|
||||
47
docs/content/docs/platform/authentication/social-sign-in.mdx
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: 'Social Sign-In Providers'
|
||||
---
|
||||
|
||||
Nhost Auth supports the following social sign-in providers:
|
||||
|
||||
- [GitHub](/platform/authentication/sign-in-with-github)
|
||||
- [Google](/platform/authentication/sign-in-with-google)
|
||||
- [Facebook](/platform/authentication/sign-in-with-facebook)
|
||||
- [LinkedIn](/platform/authentication/sign-in-with-linkedin)
|
||||
- [Spotify](/platform/authentication/sign-in-with-spotify)
|
||||
|
||||
---
|
||||
|
||||
## Enabling Social Sign-In Provider
|
||||
|
||||
To start with social sign-in, select your app in Nhost Console and go to **Users** → **Login settings**.
|
||||
|
||||
You need to set client ID and client secret for each provider that you want to enable.
|
||||
|
||||
---
|
||||
|
||||
## Implementing sign-in experience
|
||||
|
||||
Use the [Nhost JavaScript SDK](/reference/sdk) and the `signIn()` method to implement social sign-in in your app,
|
||||
|
||||
Here's an example of how to implement sign-in with GitHub:
|
||||
|
||||
```js
|
||||
nhost.auth.signIn({
|
||||
provider: 'github'
|
||||
})
|
||||
```
|
||||
|
||||
Users are redirected to your Nhost app's **client URL** by default. By default your Nhost app's client URL is set to `http://localhost:3000`. You can change the value of your client URL in the Nhost console by going to **Users** → **Login settings** → **Client URL**.
|
||||
|
||||
---
|
||||
|
||||
## Provider OAuth scopes
|
||||
|
||||
Scopes are a mechanism in OAuth to allow or limit an application's access to a user's account.
|
||||
|
||||
By default, Nhost sets the scope to get the name, email and avatar for each user. Editing scope is not currently supported.
|
||||
|
||||
## Provider OAuth Tokens
|
||||
|
||||
Nhost saves both access and refresh tokens for each user and provider in the `auth.user_providers` table. These tokens can be used to interact with the provider if needed.
|
||||
@@ -24,7 +24,7 @@ Example of getting one user in GraphQL:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
user(id: "some-user-id") {
|
||||
user(id: "<user-id>") {
|
||||
id
|
||||
displayName
|
||||
email
|
||||
|
||||
@@ -20,6 +20,8 @@ Access token data is included as headers with every API request. By default, eve
|
||||
|
||||
The default role for users is `user`.
|
||||
|
||||
> You can also [add custom permission](#add-permission-variables) varaibles if you need to.
|
||||
|
||||
---
|
||||
|
||||
## Select permissions
|
||||
@@ -60,3 +62,23 @@ In our example, we only select `name`, because we want all other other columns t
|
||||
We also want every new record's `user_id` value to be set to the ID of the user making the request. We can tell Hasura to do this with **column presets**.
|
||||
|
||||
1. Under column presets, set `user_id` to `x-hasura-user-id`.
|
||||
|
||||
## Add Permission Variables
|
||||
|
||||
You can add extra permission variables in the Nhost console under **Users** and then **Roles and permissions**. These permission variables are then available when creating permissions for your GraphQL API in the Hasura console.
|
||||
|
||||

|
||||
|
||||
As an example, let's say you add a new permission variable `x-hasura-organisation-id` with path `user.profile.organisation.id`. This means that Nhost Auth will get the value for `x-hasura-organisation-id` by internally generating the following GraphQL query:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
user(id: "<user-id>") {
|
||||
profile {
|
||||
organisation {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -39,10 +39,10 @@ HTTP endpoints are automatically generated based on the file structure under `fu
|
||||
As such, given this file structure:
|
||||
|
||||
```js
|
||||
functions / index.js
|
||||
users / index.ts
|
||||
active.ts
|
||||
my - company.js
|
||||
functions/index.js
|
||||
functions/users/index.ts
|
||||
functions/active.ts
|
||||
functions/my-company.js
|
||||
```
|
||||
|
||||
The following endpoints will be available:
|
||||
|
||||
@@ -2,45 +2,63 @@
|
||||
title: 'Configuration'
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
With yarn:
|
||||
|
||||
```sh
|
||||
yarn add @nhost/react @nhost/nextjs
|
||||
```
|
||||
|
||||
With Npm:
|
||||
|
||||
```sh
|
||||
npm install @nhost/react @nhost/nextjs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuring Nhost with Next.js follows the same logic as React, except we are initializing with `NhostSSR` instead of `Nhost`.
|
||||
Under the hood, `NhostSSR` uses cookies to store the refresh token, and disables auto-refresh and auto-login when running on the server-side.
|
||||
Configuring Nhost with Next.js follows the same logic as React, except we are initializing with the `NhostClient` from the `@nhost/nextjs` package.
|
||||
Under the hood, `NhostClient` uses cookies to store the refresh token, and disables auto-refresh and auto-login when running on the server-side.
|
||||
|
||||
```jsx
|
||||
// {project-root}/pages/_app.tsx
|
||||
import type { AppProps } from 'next/app'
|
||||
|
||||
import { NhostSSR, NhostProvider } from '@nhost/nextjs'
|
||||
import { NhostClient, NhostNextProvider } from '@nhost/nextjs'
|
||||
|
||||
import Header from '../components/Header'
|
||||
|
||||
const nhost = new NhostSSR({ backendUrl: 'my-app.nhost.run' })
|
||||
const nhost = new NhostClient({ backendUrl: 'my-app.nhost.run' })
|
||||
|
||||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
return (
|
||||
<NhostProvider nhost={nhost} initial={pageProps.nhostSession}>
|
||||
<NhostNextProvider nhost={nhost} initial={pageProps.nhostSession}>
|
||||
<div>
|
||||
<Header />
|
||||
<Component {...pageProps} />
|
||||
</div>
|
||||
</NhostProvider>
|
||||
</NhostNextProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default MyApp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Client-side rendering
|
||||
|
||||
The logic is the same as in a classic React application:
|
||||
|
||||
```jsx
|
||||
// {project-root}/pages/csr-page.jsx
|
||||
// {project-root}/pages/csr-page.tsx
|
||||
import { NextPageContext } from 'next'
|
||||
import React from 'react'
|
||||
|
||||
import { useAccessToken, useAuthenticated, useUserData } from '@nhost/nextjs'
|
||||
import { useAccessToken, useAuthenticated, useUserData } from '@nhost/react'
|
||||
|
||||
const ClientSidePage: React.FC = () => {
|
||||
const isAuthenticated = useAuthenticated()
|
||||
@@ -58,12 +76,14 @@ const ClientSidePage: React.FC = () => {
|
||||
export default ClientSidePage
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Server-side rendering
|
||||
|
||||
You need to load the session from the server first from `getServerSideProps`. Once it is done, the `_app` component will make sure to load or update the session through `pageProps`.
|
||||
|
||||
```jsx
|
||||
// {project-root}/pages/ssr-page.jsx
|
||||
// {project-root}/pages/ssr-page.tsx
|
||||
import { NextPageContext } from 'next'
|
||||
import React from 'react'
|
||||
|
||||
@@ -73,7 +93,7 @@ import {
|
||||
useAccessToken,
|
||||
useAuthenticated,
|
||||
useUserData
|
||||
} from '@nhost/nextjs'
|
||||
} from '@nhost/react'
|
||||
|
||||
export async function getServerSideProps(context: NextPageContext) {
|
||||
const nhostSession = await getNhostSession('my-app.nhost.run', context)
|
||||
|
||||
@@ -6,7 +6,7 @@ Create a `auth-protected.js` file:
|
||||
|
||||
```jsx
|
||||
import { useRouter } from 'next/router'
|
||||
import { useAuthLoading, useAuthenticated } from '@nhost/react'
|
||||
import { useAuthLoading, useAuthenticated } from '@nhost/nextjs'
|
||||
|
||||
export function authProtected(Comp) {
|
||||
return function AuthProtected(props) {
|
||||
|
||||
@@ -7,38 +7,37 @@ title: 'Apollo GraphQL'
|
||||
With Yarn:
|
||||
|
||||
```sh
|
||||
yarn add @nhost/react @nhost/react-apollo
|
||||
yarn add @nhost/react @nhost/react-apollo @apollo/client
|
||||
```
|
||||
|
||||
With Npm:
|
||||
|
||||
```sh
|
||||
npm install @nhost/react @nhost/react-apollo
|
||||
npm install @nhost/react @nhost/react-apollo @apollo/client
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Let's add a `NhostApolloProvider`. Make sure the Apollo Provider is nested into `NhostProvider`, as it will need the Nhost context to determine the authentication headers to be sent to the GraphQL endpoint.
|
||||
Let's add a `NhostApolloProvider`. Make sure the Apollo Provider is nested into `NhostReactProvider`, as it will need the Nhost context to determine the authentication headers to be sent to the GraphQL endpoint.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import App from './App'
|
||||
import { NhostApolloProvider } from '@nhost/react-apollo'
|
||||
import { NhostProvider } from '@nhost/react'
|
||||
import { Nhost } from '@nhost/client'
|
||||
import { NhostClient, NhostReactProvider } from '@nhost/react'
|
||||
|
||||
const nhost = new Nhost({
|
||||
const nhost = new NhostClient({
|
||||
backendUrl: 'http://localhost:1337'
|
||||
})
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<NhostProvider nhost={nhost}>
|
||||
<NhostApolloProvider>
|
||||
<NhostReactProvider nhost={nhost}>
|
||||
<NhostApolloProvider nhost={nhost}>
|
||||
<App />
|
||||
</NhostApolloProvider>
|
||||
</NhostProvider>
|
||||
</NhostReactProvider>
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
)
|
||||
|
||||
@@ -7,36 +7,36 @@ title: 'Hooks'
|
||||
### Email and Password Sign-Un
|
||||
|
||||
```js
|
||||
const { signUp, isLoading, isSuccess, needsVerification, isError, error } =
|
||||
useEmailPasswordSignUp(email?: string, password?: string, options?: Options )
|
||||
const { signUpEmailPassword, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
||||
useSignUpEmailPassword(email?: string, password?: string, options?: Options )
|
||||
```
|
||||
|
||||
| Name | Type | Notes |
|
||||
| ---------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `signUp` | (email?: string, password?: string) => void | Used for a new user to sign up. The email/password arguments will take precedence over the possible state values used when creating the hook. |
|
||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
||||
| `needsVerification` | boolean | Returns `true` if the sign-up has been accepted, but a verificaiton email has been sent and is awaiting. |
|
||||
| `isSuccess` | boolean | Returns `true` if the sign-up suceeded. Returns `false` if the new email needs to be verified first, or if an error occurred. |
|
||||
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||
| `error` | {status: number, error: string, message: string} \| undefined | Provides details about the error. |
|
||||
| `options.locale` | string \| undefined | Locale of the user, in two digits, for instance `en`. |
|
||||
| `options.allowedRoles` | string[] \| undefined | Allowed roles of the user. Must be a subset of the default allowed roles defined in Hasura Auth. |
|
||||
| `options.defaultRole` | string \| undefined | Default role of the user. Must be part of the default allowed roles defined in Hasura Auth. |
|
||||
| `options.displayName` | string \| undefined | |
|
||||
| `options.metadata` | Record<string, unknown> \| undefined | Custom additional user information stored in the `metadata` column. Can be any JSON object. |
|
||||
| `options.redirectTo` | string \| undefined | redirection path in the client application that will be used in the link in the verification email. For instance, if you want to redirect to `https://myapp.com/success`, the `redirectTo` value is `'/success'`. |
|
||||
| Name | Type | Notes |
|
||||
| ------------------------ | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `signUpEmailPassword` | (email?: string, password?: string) => void | Used for a new user to sign up. The email/password arguments will take precedence over the possible state values used when creating the hook. |
|
||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
||||
| `needsEmailVerification` | boolean | Returns `true` if the sign-up has been accepted, but a verificaiton email has been sent and is awaiting. |
|
||||
| `isSuccess` | boolean | Returns `true` if the sign-up suceeded. Returns `false` if the new email needs to be verified first, or if an error occurred. |
|
||||
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||
| `error` | {status: number, error: string, message: string} \| undefined | Provides details about the error. |
|
||||
| `options.locale` | string \| undefined | Locale of the user, in two digits, for instance `en`. |
|
||||
| `options.allowedRoles` | string[] \| undefined | Allowed roles of the user. Must be a subset of the default allowed roles defined in Hasura Auth. |
|
||||
| `options.defaultRole` | string \| undefined | Default role of the user. Must be part of the default allowed roles defined in Hasura Auth. |
|
||||
| `options.displayName` | string \| undefined | |
|
||||
| `options.metadata` | Record<string, unknown> \| undefined | Custom additional user information stored in the `metadata` column. Can be any JSON object. |
|
||||
| `options.redirectTo` | string \| undefined | redirection path in the client application that will be used in the link in the verification email. For instance, if you want to redirect to `https://myapp.com/success`, the `redirectTo` value is `'/success'`. |
|
||||
|
||||
#### Usage
|
||||
|
||||
```jsx
|
||||
import { useState } from 'react'
|
||||
import { useEmailPasswordSignUp } from '@nhost/react'
|
||||
import { useSignUpEmailPassword } from '@nhost/react'
|
||||
|
||||
const Component = () => {
|
||||
const [email, setEmail] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
const { signUp, isLoading, isSuccess, needsVerification, isError, error } =
|
||||
useEmailPasswordSignUp(email, password)
|
||||
const { signUpEmailPassword, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
||||
useSignUpEmailPassword(email, password)
|
||||
return (
|
||||
<div>
|
||||
<input value={email} onChange={(event) => setEmail(event.target.value)} placeholder="Email" />
|
||||
@@ -45,9 +45,9 @@ const Component = () => {
|
||||
onChange={(event) => setPassword(event.target.value)}
|
||||
placeholder="Password"
|
||||
/>
|
||||
<button onClick={signUp}>Register</button>
|
||||
<button onClick={signUpEmailPassword}>Register</button>
|
||||
{isSuccess && <div>Your account have beed created! You are now authenticated</div>}
|
||||
{needsVerification && (
|
||||
{needsEmailVerification && (
|
||||
<div>Please check your mailbox and follow the verification link to verify your email</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -58,30 +58,32 @@ const Component = () => {
|
||||
### Email and Password Sign-In
|
||||
|
||||
```js
|
||||
const { signIn, isLoading, needsVerification, isSuccess, isError, error } =
|
||||
useEmailPasswordSignIn(email?: string, password?: string)
|
||||
const { signInEmailPassword, isLoading, needsEmailVerification, needsMfaOtp, sendMfaOtp, isSuccess, isError, error } =
|
||||
useSignInEmailPassword(email?: string, password?: string)
|
||||
```
|
||||
|
||||
| Name | Type | Notes |
|
||||
| ------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `signIn` | (email?: string, password?: string) => void | Will try to authenticate. The email/password arguments will take precedence over the possible state values used when creating the hook. |
|
||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
||||
| `needsVerification` | boolean | Returns `true` if the user email is still pending verification. |
|
||||
| `isSuccess` | boolean | Returns `true` if the user has successfully authenticated. Returns `false` in case or error or if the new email needs to be verified first. |
|
||||
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||
| `error` | {status: number, error: string, message: string} \| undefined | Provides details about the error. |
|
||||
| Name | Type | Notes |
|
||||
| ------------------------ | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `signInEmailPassword` | (email?: string, password?: string) => void | Will try to authenticate. The email/password arguments will take precedence over the possible state values used when creating the hook. |
|
||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
||||
| `needsEmailVerification` | boolean | Returns `true` if the user email is still pending email verification. |
|
||||
| `needsMfaOtp` | boolean | Returns `true` if the server is awaiting an MFA one-time password to complete the authentication. |
|
||||
| `sendMfaOtp` | (otp: string) => void | Sends MFA One-time password. Will turn either `isSuccess` or `isError` to true, and store potential error in `error`. |
|
||||
| `isSuccess` | boolean | Returns `true` if the user has successfully authenticated. Returns `false` in case or error or if the new email needs to be verified first. |
|
||||
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||
| `error` | {status: number, error: string, message: string} \| undefined | Provides details about the error. |
|
||||
|
||||
#### Usage
|
||||
|
||||
```jsx
|
||||
import { useState } from 'react'
|
||||
import { useEmailPasswordSignIn } from '@nhost/react'
|
||||
import { useSignInEmailPassword } from '@nhost/react'
|
||||
|
||||
const Component = () => {
|
||||
const [email, setEmail] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
const { signIn, isLoading, isSuccess, needsVerification, isError, error } =
|
||||
useEmailPasswordSignIn(email, password)
|
||||
const { signInEmailPassword, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
||||
useSignInEmailPassword(email, password)
|
||||
return (
|
||||
<div>
|
||||
<input value={email} onChange={(event) => setEmail(event.target.value)} placeholder="Email" />
|
||||
@@ -90,9 +92,9 @@ const Component = () => {
|
||||
onChange={(event) => setPassword(event.target.value)}
|
||||
placeholder="Password"
|
||||
/>
|
||||
<button onClick={signUp}>Register</button>
|
||||
<button onClick={signInEmailPassword}>Register</button>
|
||||
{isSuccess && <div>Authentication suceeded</div>}
|
||||
{needsVerification && (
|
||||
{needsEmailVerification && (
|
||||
<div>
|
||||
You must verify your email to sign in. Check your mailbox and follow the instructions to
|
||||
verify your email.
|
||||
@@ -105,49 +107,69 @@ const Component = () => {
|
||||
|
||||
### Oauth Providers
|
||||
|
||||
```js
|
||||
const providerLink = useProviderLink(options?: Options)
|
||||
```
|
||||
|
||||
| Name | Type | Notes |
|
||||
| ---------------------- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `options.locale` | string \| undefined | Locale of the user, in two digits, for instance `en`. |
|
||||
| `options.allowedRoles` | string[] \| undefined | Allowed roles of the user. Must be a subset of the default allowed roles defined in Hasua Auth. |
|
||||
| `options.defaultRole` | string \| undefined | Default role of the user. Must be part of the default allowed roles defined in Hasura Auth. |
|
||||
| `options.displayName` | string \| undefined |
|
||||
| `options.metadata` | Record<string, unknown> \| undefined | Custom additional user information stored in the `metadata` column. Can be any JSON object. |
|
||||
| `options.redirectTo` | string \| undefined | Redirection path in the client application that will be used in the link in the verification email. For instance, if you want to redirect to `https://myapp.com/success`, the `redirectTo` value is `'/success'`. |
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
import { useProviderLink } from '@nhost/react'
|
||||
|
||||
const Component = () => {
|
||||
const { github } = useProviderLink()
|
||||
return <a href={github}>Authenticate with GitHub</a>
|
||||
const { facebook, github } = useProviderLink()
|
||||
return
|
||||
;<div>
|
||||
<a href={facebook}>Authenticate with Facebook</a>
|
||||
<a href={github}>Authenticate with GitHub</a>
|
||||
</div>
|
||||
}
|
||||
```
|
||||
|
||||
### Passwordless email authentication
|
||||
|
||||
```js
|
||||
const { signIn, isLoading, isSuccess, isError, error } =
|
||||
useEmailPasswordlessSignIn(email?: string, options?: Options)
|
||||
const { signInEmailPasswordless, isLoading, isSuccess, isError, error } =
|
||||
useSignInEmailPasswordless(email?: string, options?: Options)
|
||||
```
|
||||
|
||||
| Name | Type | Notes |
|
||||
| ---------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `signIn` | (email?: string) => void | Sends a magic link to the given email The email argument will take precedence over the the possible state value used when creating the hook. |
|
||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
||||
| `isSuccess` | boolean | Returns `true` if the magic link email user has successfully send. |
|
||||
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||
| `error` | {status: number, error: string, message: string} | Provides details about the error. |
|
||||
| `options.locale` | string \| undefined | Locale of the user, in two digits, for instance `en`. |
|
||||
| `options.allowedRoles` | string[] \| undefined | Allowed roles of the user. Must be a subset of the default allowed roles defined in Hasua Auth. |
|
||||
| `options.defaultRole` | string \| undefined | Default role of the user. Must be part of the default allowed roles defined in Hasura Auth. |
|
||||
| `options.displayName` | string \| undefined |
|
||||
| `options.metadata` | Record<string, unknown> \| undefined | Custom additional user information stored in the `metadata` column. Can be any JSON object. |
|
||||
| `options.redirectTo` | string \| undefined | Redirection path in the client application that will be used in the link in the verification email. For instance, if you want to redirect to `https://myapp.com/success`, the `redirectTo` value is `'/success'`. |
|
||||
| Name | Type | Notes |
|
||||
| ------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `signInEmailPasswordless` | (email?: string) => void | Sends a magic link to the given email The email argument will take precedence over the the possible state value used when creating the hook. |
|
||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
||||
| `isSuccess` | boolean | Returns `true` if the magic link email user has successfully send. |
|
||||
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||
| `error` | {status: number, error: string, message: string} | Provides details about the error. |
|
||||
| `options.locale` | string \| undefined | Locale of the user, in two digits, for instance `en`. |
|
||||
| `options.allowedRoles` | string[] \| undefined | Allowed roles of the user. Must be a subset of the default allowed roles defined in Hasua Auth. |
|
||||
| `options.defaultRole` | string \| undefined | Default role of the user. Must be part of the default allowed roles defined in Hasura Auth. |
|
||||
| `options.displayName` | string \| undefined |
|
||||
| `options.metadata` | Record<string, unknown> \| undefined | Custom additional user information stored in the `metadata` column. Can be any JSON object. |
|
||||
| `options.redirectTo` | string \| undefined | Redirection path in the client application that will be used in the link in the verification email. For instance, if you want to redirect to `https://myapp.com/success`, the `redirectTo` value is `'/success'`. |
|
||||
|
||||
#### Usage
|
||||
|
||||
```jsx
|
||||
import { useState } from 'react'
|
||||
import { useEmailPasswordlessSignIn } from '@nhost/react'
|
||||
import { useSignInEmailPasswordless } from '@nhost/react'
|
||||
|
||||
const Component = () => {
|
||||
const [email, setEmail] = useState('')
|
||||
const { signIn, isLoading, isSuccess, isError, error } = useEmailPasswordlessSignIn(email)
|
||||
const { signInEmailPasswordless, isLoading, isSuccess, isError, error } =
|
||||
useSignInEmailPasswordless(email)
|
||||
return (
|
||||
<div>
|
||||
<input value={email} onChange={(event) => setEmail(event.target.value)} placeholder="Email" />
|
||||
<button onClick={signUp}>Register</button>
|
||||
<button onClick={signInEmailPasswordless}>Authenticate</button>
|
||||
{isSuccess && (
|
||||
<div>
|
||||
An email has been sent to {email}. Please check your mailbox and click on the
|
||||
@@ -192,6 +214,8 @@ const Component = () => {
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Authentication status
|
||||
|
||||
### `useAuthLoading`
|
||||
@@ -216,29 +240,31 @@ const Component = () => {
|
||||
|
||||
### Get the JWT access token
|
||||
|
||||
<!-- TODO better documentation -->
|
||||
<!-- TODO ellaborate -->
|
||||
|
||||
```js
|
||||
const accessToken = useAccessToken()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## User management
|
||||
|
||||
### Change email
|
||||
|
||||
```js
|
||||
const { changeEmail, isLoading, isSuccess, needsVerification, isError, error } =
|
||||
const { changeEmail, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
||||
useChangeEmail(email?: string, options?: { redirectTo?: string })
|
||||
```
|
||||
|
||||
| Name | Type | Notes |
|
||||
| ------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `changeEmail` | (email?: string) => void | Rrequests the email change. The arguement password will take precedence over the the possible state value used when creating the hook. |
|
||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
||||
| `needsVerification` | boolean | Returns `true` if the email change has been requested, but that a email has been sent to the user to verify the new email. |
|
||||
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||
| `error` | {status: number, error: string, message: string} \| undefined | Provides details about the error. |
|
||||
| `redirectTo` | string \| undefined | Redirection path in the client application that will be used in the link in the verification email. For instance, if you want to redirect to `https://myapp.com/success`, the `redirectTo` value is `'/success'`. |
|
||||
| Name | Type | Notes |
|
||||
| ------------------------ | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `changeEmail` | (email?: string) => void | Requests the email change. The arguement password will take precedence over the the possible state value used when creating the hook. |
|
||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
||||
| `needsEmailVerification` | boolean | Returns `true` if the email change has been requested, but that a email has been sent to the user to verify the new email. |
|
||||
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||
| `error` | {status: number, error: string, message: string} \| undefined | Provides details about the error. |
|
||||
| `redirectTo` | string \| undefined | Redirection path in the client application that will be used in the link in the verification email. For instance, if you want to redirect to `https://myapp.com/success`, the `redirectTo` value is `'/success'`. |
|
||||
|
||||
#### Usage
|
||||
|
||||
@@ -248,12 +274,13 @@ import { useChangeEmail } from '@nhost/react'
|
||||
|
||||
const Component = () => {
|
||||
const [email, setEmail] = useState('')
|
||||
const { changeEmail, isLoading, needsVerification, isError, error } = useChangeEmail(password)
|
||||
const { changeEmail, isLoading, needsEmailVerification, isError, error } =
|
||||
useChangeEmail(password)
|
||||
return (
|
||||
<div>
|
||||
<input value={email} onChange={(event) => setEmail(event.target.value)} />
|
||||
<button onClick={changeEmail}>Change password</button>
|
||||
{needsVerification && (
|
||||
{needsEmailVerification && (
|
||||
<div>
|
||||
Please check your mailbox and follow the verification link to confirm your new email
|
||||
</div>
|
||||
@@ -330,9 +357,48 @@ const Component = () => {
|
||||
}
|
||||
```
|
||||
|
||||
### Send email verification
|
||||
|
||||
```js
|
||||
const { sendEmail, isLoading, isSent, isError, error } =
|
||||
useSendVerificationEmail(email?: string, options?: { redirectTo?: string })
|
||||
```
|
||||
|
||||
| Name | Type | Notes |
|
||||
| ------------ | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `sendEmail` | (email?: string) => void | Requests the email change. The arguement password will take precedence over the the possible state value used when creating the hook. |
|
||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
||||
| `isSent` | boolean | Returns `true` if the verification email has been sent |
|
||||
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||
| `error` | {status: number, error: string, message: string} \| undefined | Provides details about the error. |
|
||||
| `redirectTo` | string \| undefined | Redirection path in the client application that will be used in the link in the verification email. For instance, if you want to redirect to `https://myapp.com/success`, the `redirectTo` value is `'/success'`. |
|
||||
|
||||
#### Usage
|
||||
|
||||
```jsx
|
||||
import { useState } from 'react'
|
||||
import { useChangeEmail } from '@nhost/react'
|
||||
|
||||
const Component = () => {
|
||||
const [email, setEmail] = useState('')
|
||||
const { sendEmail, isLoading, isSent, isError, error } = useChangeEmail(password)
|
||||
return (
|
||||
<div>
|
||||
<input value={email} onChange={(event) => setEmail(event.target.value)} />
|
||||
<button onClick={sendEmail}>Send email verification</button>
|
||||
{isSent && (
|
||||
<div>Please check your mailbox and follow the verification link to confirm your email</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## User data
|
||||
|
||||
<!-- TODO document -->
|
||||
<!-- TODO ellaborate -->
|
||||
|
||||
```js
|
||||
const userData = useUserData()
|
||||
|
||||
@@ -16,43 +16,53 @@ With Npm:
|
||||
npm install @nhost/react
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
`@nhost/react` exports a React provider `NhostProvider` that makes the authentication state and the several hooks available in your application. Wrap this component around your whole App.
|
||||
`@nhost/react` exports a React provider `NhostReactProvider` that makes the authentication state and the several hooks available in your application. Wrap this component around your whole App.
|
||||
|
||||
```jsx
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
import { NhostProvider } from '@nhost/react'
|
||||
import { Nhost } from '@nhost/client'
|
||||
import { NhostClient, NhostReactProvider } from '@nhost/react'
|
||||
|
||||
import App from './App'
|
||||
|
||||
const nhost = new Nhost({
|
||||
const nhost = new NhostClient({
|
||||
backendUrl: 'http://localhost:1337'
|
||||
})
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<NhostProvider nhost={nhost}>
|
||||
<NhostReactProvider nhost={nhost}>
|
||||
<App />
|
||||
</NhostProvider>
|
||||
</NhostReactProvider>
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Options
|
||||
|
||||
```js
|
||||
const nhost = new Nhost({ backendUrl, autoSignIn, autoRefreshToken, storageGetter, storageSetter })
|
||||
const nhost = new NhostClient({
|
||||
backendUrl,
|
||||
autoLogin,
|
||||
autoRefreshToken,
|
||||
clientStorageGetter,
|
||||
clientStorageSetter
|
||||
})
|
||||
```
|
||||
|
||||
| Name | Type | Default | Notes |
|
||||
| ------------------ | ----------------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `backendUrl` | string | | The Nhost app url, for instance `https://my-app.nhost.run`. When using the CLI, its value is `http://localhost:1337` |
|
||||
| `autoSignIn` | boolean | `true` | If set to `true`, the client will detect credentials in the current URL that could have been sent during an email verification or an Oauth authentication. It will also automatically authenticate all the active tabs in the current browser. |
|
||||
| `autoRefreshToken` | boolean | `true` | If set to `true`, the JWT (access token) will be automatically refreshed before it expires. |
|
||||
| `storageGetter` | (key:string) => string \| null | use localStorage | Nhost stores a refresh token in `localStorage` so the session can be restored when starting the browser. |
|
||||
| `storageSetter` | (key: string, value: string \| null | use localStorage | |
|
||||
| Name | Type | Default | Notes |
|
||||
| --------------------- | ----------------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `backendUrl` | string | | The Nhost app url, for instance `https://my-app.nhost.run`. When using the CLI, its value is `http://localhost:1337` |
|
||||
| `autoLogin` | boolean | `true` | If set to `true`, the client will detect credentials in the current URL that could have been sent during an email verification or an Oauth authentication. It will also automatically authenticate all the active tabs in the current browser. |
|
||||
| `autoRefreshToken` | boolean | `true` | If set to `true`, the JWT (access token) will be automatically refreshed before it expires. |
|
||||
| `clientStorageGetter` | (key:string) => string \| null | use localStorage | Nhost stores a refresh token in `localStorage` so the session can be restored when starting the browser. |
|
||||
| `clientStorageGetter` | (key: string, value: string \| null | use localStorage | |
|
||||
| `refreshIntervalTime` | | |
|
||||
|
||||
@@ -2,12 +2,29 @@ export const orderTwo = {
|
||||
'get-started': {
|
||||
'quick-start': ['index', 'schema', 'javascript-client', 'permissions'],
|
||||
authentication: ['index'],
|
||||
'cli-workflow': ['index', 'workflow-setup', 'install-cli', 'local-changes', 'metadata-and-serverless-functions'],
|
||||
'cli-workflow': [
|
||||
'index',
|
||||
'workflow-setup',
|
||||
'install-cli',
|
||||
'local-changes',
|
||||
'metadata-and-serverless-functions'
|
||||
],
|
||||
upgrade: ['index']
|
||||
},
|
||||
platform: {
|
||||
database: ['index', 'permissions', 'graphql'],
|
||||
authentication: ['index', 'user-management', 'sign-in-methods', 'social-login', 'email-templates'],
|
||||
authentication: [
|
||||
'index',
|
||||
'user-management',
|
||||
'sign-in-methods',
|
||||
'social-sign-in',
|
||||
'sign-in-with-google',
|
||||
'sign-in-with-github',
|
||||
'sign-in-with-facebook',
|
||||
'sign-in-with-linkedin',
|
||||
'sign-in-with-spotify',
|
||||
'email-templates'
|
||||
],
|
||||
storage: ['index'],
|
||||
'serverless-functions': ['index', 'event-triggers'],
|
||||
nhost: ['index', 'environment-variables', 'github-integration', 'local-development']
|
||||
|
||||
@@ -15,6 +15,11 @@ module.exports = {
|
||||
source: '/reference/sdk/javascript-sdk',
|
||||
destination: '/reference/sdk',
|
||||
permanent: false
|
||||
},
|
||||
{
|
||||
source: '/platform/authentication/social-login',
|
||||
destination: '/platform/authentication/social-sign-in',
|
||||
permanent: false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
95
docs/public/images/platform/permission-variables-preview.svg
Normal file
|
After Width: | Height: | Size: 227 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
BIN
docs/public/images/platform/social-providers/github-preview.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
docs/public/images/platform/social-providers/google-preview.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
BIN
docs/public/images/platform/social-providers/spotify-preview.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
3589
docs/yarn.lock
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"presets": ["next/babel"],
|
||||
"plugins": []
|
||||
}
|
||||
1
examples/nextjs/.gitignore
vendored
@@ -35,3 +35,4 @@ yarn-error.log*
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
.nhost
|
||||
|
||||
@@ -1,34 +1,25 @@
|
||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||
## Nhost & Next.js example (WIP)
|
||||
|
||||
## Getting Started
|
||||
This demo is a work in progress, further improvements are to come
|
||||
|
||||
First, run the development server:
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
First, clone this repo. Then run the commands:
|
||||
|
||||
```sh
|
||||
cd examples/nextjs
|
||||
yarn
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
If you want to use this demo with your own cloud instance:
|
||||
|
||||
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
|
||||
- modify the `BACKEND_URL` value in `src/helpers/index.ts`
|
||||
- don't forget to change the client URL in the Nhost console so email verification will work: `Users -> Login Settings -> Client login URLs`: `http://localhost:4000`
|
||||
|
||||
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
|
||||
If you want to use a local Nhost instance, start the CLI in parallel to Nextjs:
|
||||
|
||||
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
||||
```sh
|
||||
# Inside examples/nextjs
|
||||
nhost -d
|
||||
```
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
import { gql } from '@apollo/client'
|
||||
|
||||
export const QUERY = gql`
|
||||
query MyQuery {
|
||||
test {
|
||||
export const BOOKS_QUERY = gql`
|
||||
query BookQuery {
|
||||
books {
|
||||
id
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const QUERY_INDEX = gql`
|
||||
query MyQuery {
|
||||
test {
|
||||
id
|
||||
bidon
|
||||
title
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
// * Only required to make it work with the monorepo. Is not required otherwise
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
typescript: {
|
||||
ignoreBuildErrors: true
|
||||
},
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true
|
||||
},
|
||||
webpack: (config, { isServer }) => {
|
||||
if (isServer) {
|
||||
// * Related to monorepo and the use of ws in @nhost/apollo
|
||||
config.resolve.fallback = { bufferutil: false, 'utf-8-validate': false }
|
||||
}
|
||||
return config
|
||||
}
|
||||
}
|
||||
|
||||
const withTM = require('next-transpile-modules')(
|
||||
['@nhost/client', '@nhost/react', '@nhost/react-apollo', '@nhost/apollo', '@nhost/nextjs'],
|
||||
{
|
||||
// resolveSymlinks: true
|
||||
// debug: true
|
||||
}
|
||||
) // pass the modules you would like to see transpiled
|
||||
|
||||
module.exports = withTM(nextConfig)
|
||||
133
examples/nextjs/nhost/config.yaml
Normal file
@@ -0,0 +1,133 @@
|
||||
metadata_directory: metadata
|
||||
services:
|
||||
mailhog:
|
||||
port: 8025
|
||||
hasura:
|
||||
version: v2.2.0
|
||||
environment:
|
||||
hasura_graphql_enable_remote_schema_permissions: false
|
||||
auth:
|
||||
version: 0.4.2
|
||||
auth:
|
||||
access_control:
|
||||
email:
|
||||
allowed_email_domains: ''
|
||||
allowed_emails: ''
|
||||
blocked_email_domains: ''
|
||||
blocked_emails: ''
|
||||
url:
|
||||
allowed_redirect_urls: ''
|
||||
anonymous_users_enabled: false
|
||||
client_url: http://localhost:3000
|
||||
disable_new_users: false
|
||||
email:
|
||||
passwordless:
|
||||
enabled: true
|
||||
template_fetch_url: ''
|
||||
gravatar:
|
||||
default: ''
|
||||
enabled: true
|
||||
rating: ''
|
||||
locale:
|
||||
allowed: en
|
||||
default: en
|
||||
password:
|
||||
hibp_enabled: false
|
||||
min_length: 3
|
||||
provider:
|
||||
apple:
|
||||
client_id: ''
|
||||
enabled: false
|
||||
key_id: ''
|
||||
private_key: ''
|
||||
scope: name,email
|
||||
team_id: ''
|
||||
bitbucket:
|
||||
client_id: ''
|
||||
client_secret: ''
|
||||
enabled: false
|
||||
facebook:
|
||||
client_id: ''
|
||||
client_secret: ''
|
||||
enabled: false
|
||||
scope: email,photos,displayName
|
||||
github:
|
||||
client_id: ''
|
||||
client_secret: ''
|
||||
enabled: false
|
||||
scope: user:email
|
||||
token_url: ''
|
||||
user_profile_url: ''
|
||||
gitlab:
|
||||
base_url: ''
|
||||
client_id: ''
|
||||
client_secret: ''
|
||||
enabled: false
|
||||
scope: read_user
|
||||
google:
|
||||
client_id: ''
|
||||
client_secret: ''
|
||||
enabled: false
|
||||
scope: email,profile
|
||||
linkedin:
|
||||
client_id: ''
|
||||
client_secret: ''
|
||||
enabled: false
|
||||
scope: r_emailaddress,r_liteprofile
|
||||
spotify:
|
||||
client_id: ''
|
||||
client_secret: ''
|
||||
enabled: false
|
||||
scope: user-read-email,user-read-private
|
||||
strava:
|
||||
client_id: ''
|
||||
client_secret: ''
|
||||
enabled: false
|
||||
twilio:
|
||||
account_sid: ''
|
||||
auth_token: ''
|
||||
enabled: false
|
||||
messaging_service_id: ''
|
||||
twitter:
|
||||
consumer_key: ''
|
||||
consumer_secret: ''
|
||||
enabled: false
|
||||
windows_live:
|
||||
client_id: ''
|
||||
client_secret: ''
|
||||
enabled: false
|
||||
scope: wl.basic,wl.emails,wl.contacts_emails
|
||||
sms:
|
||||
enabled: false
|
||||
passwordless:
|
||||
enabled: false
|
||||
provider:
|
||||
twilio:
|
||||
account_sid: ''
|
||||
auth_token: ''
|
||||
from: ''
|
||||
messaging_service_id: ''
|
||||
smtp:
|
||||
host: nhost_mailhog
|
||||
method: ''
|
||||
pass: password
|
||||
port: 1807
|
||||
secure: false
|
||||
sender: hasura-auth@example.com
|
||||
user: user
|
||||
token:
|
||||
access:
|
||||
expires_in: 900
|
||||
refresh:
|
||||
expires_in: 43200
|
||||
user:
|
||||
allowed_roles: user,me
|
||||
default_allowed_roles: user,me
|
||||
default_role: user
|
||||
mfa:
|
||||
enabled: false
|
||||
issuer: nhost
|
||||
signin_email_verified_required: true
|
||||
storage:
|
||||
force_download_for_content_types: text/html,application/javascript
|
||||
version: 3
|
||||
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Confirm Email Change</h2>
|
||||
<p>Use this link to confirm changing email:</p>
|
||||
<p>
|
||||
<a
|
||||
href="${serverUrl}/verify?&ticket=${ticket}&type=emailConfirmChange&redirectTo=${redirectTo}"
|
||||
>
|
||||
Change email
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Change your email address
|
||||
15
examples/nextjs/nhost/emails/en/email-verify/body.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Verify Email</h2>
|
||||
<p>Use this link to verify your email:</p>
|
||||
<p>
|
||||
<a href="${serverUrl}/verify?&ticket=${ticket}&type=emailVerify&redirectTo=${redirectTo}">
|
||||
Verify Email
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
1
examples/nextjs/nhost/emails/en/email-verify/subject.txt
Normal file
@@ -0,0 +1 @@
|
||||
Verify your email
|
||||
15
examples/nextjs/nhost/emails/en/password-reset/body.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Reset Password</h2>
|
||||
<p>Use this link to reset your password:</p>
|
||||
<p>
|
||||
<a href="${serverUrl}/verify?&ticket=${ticket}&type=passwordReset&redirectTo=${redirectTo}">
|
||||
Reset password
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Reset your password
|
||||
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Magic Link</h2>
|
||||
<p>Use this link to securely sign in:</p>
|
||||
<p>
|
||||
<a
|
||||
href="${serverUrl}/verify?&ticket=${ticket}&type=signinPasswordless&redirectTo=${redirectTo}"
|
||||
>
|
||||
Sign In
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Secure sign-in link
|
||||
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Confirmer changement de courriel</h2>
|
||||
<p>Utilisez ce lien pour confirmer le changement de courriel:</p>
|
||||
<p>
|
||||
<a
|
||||
href="${serverUrl}/verify?&ticket=${ticket}&type=emailConfirmChange&redirectTo=${redirectTo}"
|
||||
>
|
||||
Changer courriel
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Changez votre adresse courriel
|
||||
15
examples/nextjs/nhost/emails/fr/email-verify/body.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Vérifiez votre courriel</h2>
|
||||
<p>Utilisez ce lien pour vérifier votre courriel:</p>
|
||||
<p>
|
||||
<a href="${serverUrl}/verify?&ticket=${ticket}&type=emailVerify&redirectTo=${redirectTo}">
|
||||
Vérifier courriel
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
1
examples/nextjs/nhost/emails/fr/email-verify/subject.txt
Normal file
@@ -0,0 +1 @@
|
||||
Vérifier votre courriel
|
||||
15
examples/nextjs/nhost/emails/fr/password-reset/body.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Réinitializer votre mot de passe</h2>
|
||||
<p>Utilisez ce lien pour réinitializer votre mot de passe:</p>
|
||||
<p>
|
||||
<a href="${serverUrl}/verify?&ticket=${ticket}&type=passwordReset&redirectTo=${redirectTo}">
|
||||
Réinitializer mot de passe
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Réinitialiser votre mot de passe
|
||||
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Lien magique</h2>
|
||||
<p>Utilisez ce lien pour vous connecter de façon sécuritaire:</p>
|
||||
<p>
|
||||
<a
|
||||
href="${serverUrl}/verify?&ticket=${ticket}&type=signinPasswordless&redirectTo=${redirectTo}"
|
||||
>
|
||||
Connexion
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Lien de connexion sécurisé
|
||||
0
examples/nextjs/nhost/metadata/actions.graphql
Normal file
6
examples/nextjs/nhost/metadata/actions.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
actions: []
|
||||
custom_types:
|
||||
enums: []
|
||||
input_objects: []
|
||||
objects: []
|
||||
scalars: []
|
||||
1
examples/nextjs/nhost/metadata/allow_list.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
1
examples/nextjs/nhost/metadata/cron_triggers.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
14
examples/nextjs/nhost/metadata/databases/databases.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
- name: default
|
||||
kind: postgres
|
||||
configuration:
|
||||
connection_info:
|
||||
database_url:
|
||||
from_env: HASURA_GRAPHQL_DATABASE_URL
|
||||
isolation_level: read-committed
|
||||
pool_settings:
|
||||
connection_lifetime: 600
|
||||
idle_timeout: 180
|
||||
max_connections: 50
|
||||
retries: 20
|
||||
use_prepared_statements: true
|
||||
tables: "!include default/tables/tables.yaml"
|
||||
@@ -0,0 +1,18 @@
|
||||
table:
|
||||
name: provider_requests
|
||||
schema: auth
|
||||
configuration:
|
||||
custom_column_names:
|
||||
id: id
|
||||
redirect_url: redirectUrl
|
||||
custom_name: authProviderRequests
|
||||
custom_root_fields:
|
||||
delete: deleteAuthProviderRequests
|
||||
delete_by_pk: deleteAuthProviderRequest
|
||||
insert: insertAuthProviderRequests
|
||||
insert_one: insertAuthProviderRequest
|
||||
select: authProviderRequests
|
||||
select_aggregate: authProviderRequestsAggregate
|
||||
select_by_pk: authProviderRequest
|
||||
update: updateAuthProviderRequests
|
||||
update_by_pk: updateAuthProviderRequest
|
||||
@@ -0,0 +1,25 @@
|
||||
table:
|
||||
name: providers
|
||||
schema: auth
|
||||
configuration:
|
||||
custom_column_names:
|
||||
id: id
|
||||
custom_name: authProviders
|
||||
custom_root_fields:
|
||||
delete: deleteAuthProviders
|
||||
delete_by_pk: deleteAuthProvider
|
||||
insert: insertAuthProviders
|
||||
insert_one: insertAuthProvider
|
||||
select: authProviders
|
||||
select_aggregate: authProvidersAggregate
|
||||
select_by_pk: authProvider
|
||||
update: updateAuthProviders
|
||||
update_by_pk: updateAuthProvider
|
||||
array_relationships:
|
||||
- name: userProviders
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: provider_id
|
||||
table:
|
||||
name: user_providers
|
||||
schema: auth
|
||||
@@ -0,0 +1,24 @@
|
||||
table:
|
||||
name: refresh_tokens
|
||||
schema: auth
|
||||
configuration:
|
||||
custom_column_names:
|
||||
created_at: createdAt
|
||||
expires_at: expiresAt
|
||||
refresh_token: refreshToken
|
||||
user_id: userId
|
||||
custom_name: authRefreshTokens
|
||||
custom_root_fields:
|
||||
delete: deleteAuthRefreshTokens
|
||||
delete_by_pk: deleteAuthRefreshToken
|
||||
insert: insertAuthRefreshTokens
|
||||
insert_one: insertAuthRefreshToken
|
||||
select: authRefreshTokens
|
||||
select_aggregate: authRefreshTokensAggregate
|
||||
select_by_pk: authRefreshToken
|
||||
update: updateAuthRefreshTokens
|
||||
update_by_pk: updateAuthRefreshToken
|
||||
object_relationships:
|
||||
- name: user
|
||||
using:
|
||||
foreign_key_constraint_on: user_id
|
||||
@@ -0,0 +1,32 @@
|
||||
table:
|
||||
name: roles
|
||||
schema: auth
|
||||
configuration:
|
||||
custom_column_names:
|
||||
role: role
|
||||
custom_name: authRoles
|
||||
custom_root_fields:
|
||||
delete: deleteAuthRoles
|
||||
delete_by_pk: deleteAuthRole
|
||||
insert: insertAuthRoles
|
||||
insert_one: insertAuthRole
|
||||
select: authRoles
|
||||
select_aggregate: authRolesAggregate
|
||||
select_by_pk: authRole
|
||||
update: updateAuthRoles
|
||||
update_by_pk: updateAuthRole
|
||||
array_relationships:
|
||||
- name: userRoles
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: role
|
||||
table:
|
||||
name: user_roles
|
||||
schema: auth
|
||||
- name: usersByDefaultRole
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: default_role
|
||||
table:
|
||||
name: users
|
||||
schema: auth
|
||||
@@ -0,0 +1,31 @@
|
||||
table:
|
||||
name: user_providers
|
||||
schema: auth
|
||||
configuration:
|
||||
custom_column_names:
|
||||
access_token: accessToken
|
||||
created_at: createdAt
|
||||
id: id
|
||||
provider_id: providerId
|
||||
provider_user_id: providerUserId
|
||||
refresh_token: refreshToken
|
||||
updated_at: updatedAt
|
||||
user_id: userId
|
||||
custom_name: authUserProviders
|
||||
custom_root_fields:
|
||||
delete: deleteAuthUserProviders
|
||||
delete_by_pk: deleteAuthUserProvider
|
||||
insert: insertAuthUserProviders
|
||||
insert_one: insertAuthUserProvider
|
||||
select: authUserProviders
|
||||
select_aggregate: authUserProvidersAggregate
|
||||
select_by_pk: authUserProvider
|
||||
update: updateAuthUserProviders
|
||||
update_by_pk: updateAuthUserProvider
|
||||
object_relationships:
|
||||
- name: provider
|
||||
using:
|
||||
foreign_key_constraint_on: provider_id
|
||||
- name: user
|
||||
using:
|
||||
foreign_key_constraint_on: user_id
|
||||
@@ -0,0 +1,27 @@
|
||||
table:
|
||||
name: user_roles
|
||||
schema: auth
|
||||
configuration:
|
||||
custom_column_names:
|
||||
created_at: createdAt
|
||||
id: id
|
||||
role: role
|
||||
user_id: userId
|
||||
custom_name: authUserRoles
|
||||
custom_root_fields:
|
||||
delete: deleteAuthUserRoles
|
||||
delete_by_pk: deleteAuthUserRole
|
||||
insert: insertAuthUserRoles
|
||||
insert_one: insertAuthUserRole
|
||||
select: authUserRoles
|
||||
select_aggregate: authUserRolesAggregate
|
||||
select_by_pk: authUserRole
|
||||
update: updateAuthUserRoles
|
||||
update_by_pk: updateAuthUserRole
|
||||
object_relationships:
|
||||
- name: roleByRole
|
||||
using:
|
||||
foreign_key_constraint_on: role
|
||||
- name: user
|
||||
using:
|
||||
foreign_key_constraint_on: user_id
|
||||
@@ -0,0 +1,65 @@
|
||||
table:
|
||||
name: users
|
||||
schema: auth
|
||||
configuration:
|
||||
custom_column_names:
|
||||
active_mfa_type: activeMfaType
|
||||
avatar_url: avatarUrl
|
||||
created_at: createdAt
|
||||
default_role: defaultRole
|
||||
disabled: disabled
|
||||
display_name: displayName
|
||||
email: email
|
||||
email_verified: emailVerified
|
||||
id: id
|
||||
is_anonymous: isAnonymous
|
||||
last_seen: lastSeen
|
||||
locale: locale
|
||||
new_email: newEmail
|
||||
otp_hash: otpHash
|
||||
otp_hash_expires_at: otpHashExpiresAt
|
||||
otp_method_last_used: otpMethodLastUsed
|
||||
password_hash: passwordHash
|
||||
phone_number: phoneNumber
|
||||
phone_number_verified: phoneNumberVerified
|
||||
ticket: ticket
|
||||
ticket_expires_at: ticketExpiresAt
|
||||
totp_secret: totpSecret
|
||||
updated_at: updatedAt
|
||||
custom_name: users
|
||||
custom_root_fields:
|
||||
delete: deleteUsers
|
||||
delete_by_pk: deleteUser
|
||||
insert: insertUsers
|
||||
insert_one: insertUser
|
||||
select: users
|
||||
select_aggregate: userAggregate
|
||||
select_by_pk: user
|
||||
update: updateUsers
|
||||
update_by_pk: updateUser
|
||||
object_relationships:
|
||||
- name: defaultRoleByRole
|
||||
using:
|
||||
foreign_key_constraint_on: default_role
|
||||
array_relationships:
|
||||
- name: refreshTokens
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: user_id
|
||||
table:
|
||||
name: refresh_tokens
|
||||
schema: auth
|
||||
- name: roles
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: user_id
|
||||
table:
|
||||
name: user_roles
|
||||
schema: auth
|
||||
- name: userProviders
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: user_id
|
||||
table:
|
||||
name: user_providers
|
||||
schema: auth
|
||||
@@ -0,0 +1,10 @@
|
||||
table:
|
||||
name: books
|
||||
schema: public
|
||||
select_permissions:
|
||||
- permission:
|
||||
columns:
|
||||
- id
|
||||
- title
|
||||
filter: {}
|
||||
role: user
|
||||
@@ -0,0 +1,10 @@
|
||||
table:
|
||||
name: test
|
||||
schema: public
|
||||
select_permissions:
|
||||
- permission:
|
||||
columns:
|
||||
- bidon
|
||||
- id
|
||||
filter: {}
|
||||
role: user
|
||||
@@ -0,0 +1,32 @@
|
||||
table:
|
||||
name: buckets
|
||||
schema: storage
|
||||
configuration:
|
||||
custom_column_names:
|
||||
cache_control: cacheControl
|
||||
created_at: createdAt
|
||||
download_expiration: downloadExpiration
|
||||
id: id
|
||||
max_upload_file_size: maxUploadFileSize
|
||||
min_upload_file_size: minUploadFileSize
|
||||
presigned_urls_enabled: presignedUrlsEnabled
|
||||
updated_at: updatedAt
|
||||
custom_name: buckets
|
||||
custom_root_fields:
|
||||
delete: deleteBuckets
|
||||
delete_by_pk: deleteBucket
|
||||
insert: insertBuckets
|
||||
insert_one: insertBucket
|
||||
select: buckets
|
||||
select_aggregate: bucketsAggregate
|
||||
select_by_pk: bucket
|
||||
update: updateBuckets
|
||||
update_by_pk: updateBucket
|
||||
array_relationships:
|
||||
- name: files
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: bucket_id
|
||||
table:
|
||||
name: files
|
||||
schema: storage
|
||||
@@ -0,0 +1,30 @@
|
||||
table:
|
||||
name: files
|
||||
schema: storage
|
||||
configuration:
|
||||
custom_column_names:
|
||||
bucket_id: bucketId
|
||||
created_at: createdAt
|
||||
etag: etag
|
||||
id: id
|
||||
is_uploaded: isUploaded
|
||||
mime_type: mimeType
|
||||
name: name
|
||||
size: size
|
||||
updated_at: updatedAt
|
||||
uploaded_by_user_id: uploadedByUserId
|
||||
custom_name: files
|
||||
custom_root_fields:
|
||||
delete: deleteFiles
|
||||
delete_by_pk: deleteFile
|
||||
insert: insertFiles
|
||||
insert_one: insertFile
|
||||
select: files
|
||||
select_aggregate: filesAggregate
|
||||
select_by_pk: file
|
||||
update: updateFiles
|
||||
update_by_pk: updateFile
|
||||
object_relationships:
|
||||
- name: bucket
|
||||
using:
|
||||
foreign_key_constraint_on: bucket_id
|
||||
@@ -0,0 +1,10 @@
|
||||
- "!include auth_provider_requests.yaml"
|
||||
- "!include auth_providers.yaml"
|
||||
- "!include auth_refresh_tokens.yaml"
|
||||
- "!include auth_roles.yaml"
|
||||
- "!include auth_user_providers.yaml"
|
||||
- "!include auth_user_roles.yaml"
|
||||
- "!include auth_users.yaml"
|
||||
- "!include public_books.yaml"
|
||||
- "!include storage_buckets.yaml"
|
||||
- "!include storage_files.yaml"
|
||||
1
examples/nextjs/nhost/metadata/query_collections.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
1
examples/nextjs/nhost/metadata/remote_schemas.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
1
examples/nextjs/nhost/metadata/rest_endpoints.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
1
examples/nextjs/nhost/metadata/version.yaml
Normal file
@@ -0,0 +1 @@
|
||||
version: 3
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE "public"."test";
|
||||
@@ -0,0 +1,2 @@
|
||||
CREATE TABLE "public"."test" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), PRIMARY KEY ("id") );
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."test" add column "bidon" text
|
||||
-- null;
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."test" add column "bidon" text
|
||||
null;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- DROP table "public"."test";
|
||||
@@ -0,0 +1 @@
|
||||
DROP table "public"."test";
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE "public"."books";
|
||||
@@ -0,0 +1,2 @@
|
||||
CREATE TABLE "public"."books" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "title" text NOT NULL, PRIMARY KEY ("id") );
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
@@ -9,30 +9,21 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nhost/apollo": "workspace:^0.2.0",
|
||||
"@nhost/client": "workspace:^0.2.0",
|
||||
"@nhost/nextjs": "workspace:^0.2.0",
|
||||
"@nhost/react": "workspace:^0.2.0",
|
||||
"@nhost/react-apollo": "workspace:^3.0.0",
|
||||
"@xstate/react": "^2.0.0",
|
||||
"apollo-boost": "^0.4.9",
|
||||
"apollo-client": "^2.6.10",
|
||||
"next": "12.0.10",
|
||||
"@nhost/nextjs": "^0.2.0",
|
||||
"@nhost/react": "^0.2.0",
|
||||
"@nhost/react-apollo": "^3.0.0",
|
||||
"graphql": "^16.3.0",
|
||||
"next": "12.1.0",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"subscriptions-transport-ws": "^0.11.0"
|
||||
"react-dom": "17.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apollo/client": "^3.5.8",
|
||||
"@types/js-cookie": "^3.0.1",
|
||||
"@types/node": "17.0.17",
|
||||
"@types/react": "17.0.39",
|
||||
"@xstate/inspect": "^0.6.2",
|
||||
"eslint": "8.8.0",
|
||||
"eslint-config-next": "12.0.10",
|
||||
"graphql": "16",
|
||||
"next-transpile-modules": "^9.0.0",
|
||||
"typescript": "4.5.5",
|
||||
"ws": "^8.4.2"
|
||||
"ws": "^8.5.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { AppProps } from 'next/app'
|
||||
import React from 'react'
|
||||
|
||||
import { NhostSSR } from '@nhost/nextjs'
|
||||
import { NhostProvider } from '@nhost/react'
|
||||
import { NhostClient, NhostNextProvider } from '@nhost/nextjs'
|
||||
import { NhostApolloProvider } from '@nhost/react-apollo'
|
||||
import { inspect } from '@xstate/inspect'
|
||||
|
||||
@@ -10,25 +10,24 @@ import { BACKEND_URL } from '../helpers'
|
||||
|
||||
import '../styles/globals.css'
|
||||
|
||||
if (typeof window !== 'undefined' && process.env.NODE_ENV) {
|
||||
if (typeof window !== 'undefined' && process.env.NEXT_PUBLIC_DEBUG) {
|
||||
inspect({
|
||||
url: 'https://stately.ai/viz?inspect',
|
||||
iframe: false
|
||||
})
|
||||
}
|
||||
const nhost = new NhostSSR({ backendUrl: BACKEND_URL })
|
||||
const nhost = new NhostClient({ backendUrl: BACKEND_URL })
|
||||
|
||||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
// console.log('PAGE PROPS', pageProps.initial)
|
||||
return (
|
||||
<NhostProvider nhost={nhost} initial={pageProps.nhostSession}>
|
||||
<NhostApolloProvider>
|
||||
<NhostNextProvider nhost={nhost} initial={pageProps.nhostSession}>
|
||||
<NhostApolloProvider nhost={nhost}>
|
||||
<div className="App">
|
||||
<Header />
|
||||
<Component {...pageProps} />
|
||||
</div>
|
||||
</NhostApolloProvider>
|
||||
</NhostProvider>
|
||||
</NhostNextProvider>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,48 +1,56 @@
|
||||
import type { NextPage } from 'next'
|
||||
import { useState } from 'react'
|
||||
|
||||
import {
|
||||
useAccessToken,
|
||||
useAuthenticated,
|
||||
useChangeEmail,
|
||||
useChangePassword,
|
||||
useEmailPasswordlessSignIn,
|
||||
useEmailPasswordSignIn,
|
||||
useEmailPasswordSignUp,
|
||||
useSignInEmailPasswordless,
|
||||
useSignInEmailPassword,
|
||||
useSignUpEmailPassword,
|
||||
useSignOut
|
||||
} from '@nhost/react'
|
||||
import { useAuthQuery } from '@nhost/react-apollo'
|
||||
|
||||
import { QUERY_INDEX } from '../helpers'
|
||||
import { BOOKS_QUERY } from '../helpers'
|
||||
|
||||
// * Reference: https://blog.codepen.io/2021/09/01/331-next-js-apollo-server-side-rendering-ssr/
|
||||
|
||||
const Home: NextPage = () => {
|
||||
const isAuthenticated = useAuthenticated()
|
||||
const email = 'pilou@pilou.com'
|
||||
const password = 'piloupilou'
|
||||
const [email, setEmail] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
const [newEmail, setNewEmail] = useState('')
|
||||
const [newPassword, setNewPassword] = useState('')
|
||||
const accessToken = useAccessToken()
|
||||
const { signOut } = useSignOut()
|
||||
const { signUp, ...signUpResult } = useEmailPasswordSignUp(email, password)
|
||||
const { signIn } = useEmailPasswordSignIn(email, password)
|
||||
const { signIn: passwordlessSignIn } = useEmailPasswordlessSignIn(email)
|
||||
const { changeEmail, ...changeEmailResult } = useChangeEmail('bidon@bidon.com')
|
||||
const { changePassword } = useChangePassword('12345678')
|
||||
const { loading, data, error } = useAuthQuery(QUERY_INDEX)
|
||||
const { signUpEmailPassword, ...signUpResult } = useSignUpEmailPassword(email, password)
|
||||
const { signInEmailPassword } = useSignInEmailPassword(email, password)
|
||||
const { signInEmailPasswordless } = useSignInEmailPasswordless(email)
|
||||
const { changeEmail, ...changeEmailResult } = useChangeEmail(newEmail)
|
||||
const { changePassword, ...changePasswordResult } = useChangePassword(newPassword)
|
||||
const { loading, data, error } = useAuthQuery(BOOKS_QUERY)
|
||||
return (
|
||||
<div>
|
||||
{isAuthenticated ? (
|
||||
<>
|
||||
<button onClick={signOut}>Logout</button>
|
||||
<input value={newEmail} onChange={(e) => setNewEmail(e.target.value)} />
|
||||
<button onClick={changeEmail}>Change email</button>
|
||||
<div>{JSON.stringify(changeEmailResult)}</div>
|
||||
<button onClick={changePassword}>Change password</button>
|
||||
<input value={newPassword} onChange={(e) => setNewPassword(e.target.value)} />
|
||||
<div>{JSON.stringify(changePasswordResult)}</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<button onClick={signUp}>Register</button>
|
||||
<input value={email} onChange={(e) => setEmail(e.target.value)} />
|
||||
<button onClick={signInEmailPasswordless}>Passwordless signin</button>
|
||||
<div>{JSON.stringify(signUpResult)}</div>
|
||||
<button onClick={signIn}>Email + password signin</button>
|
||||
<button onClick={passwordlessSignIn}>Passwordless signin</button>
|
||||
<input value={password} onChange={(e) => setPassword(e.target.value)} type="password" />
|
||||
<button onClick={signUpEmailPassword}>Email + password sign-up</button>
|
||||
<button onClick={signInEmailPassword}>Email + password sign-in</button>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -50,8 +58,8 @@ const Home: NextPage = () => {
|
||||
<div>{accessToken}</div>
|
||||
{isAuthenticated && (
|
||||
<ul>
|
||||
{data?.test.map((item) => (
|
||||
<li key={item.id}>{item.id}</li>
|
||||
{data?.books.map((item) => (
|
||||
<li key={item.id}>{item.title}</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
|
||||
2004
examples/nextjs/yarn.lock
Normal file
1
examples/react-apollo-crm/.env.example
Normal file
@@ -0,0 +1 @@
|
||||
REACT_APP_BACKEND_URL=http://localhost:1337
|
||||
@@ -1,10 +0,0 @@
|
||||
# @nhost-examples/react-apollo
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [207ae38]
|
||||
- @nhost/react-apollo@3.0.0
|
||||
- @nhost/nhost-js@0.3.11
|
||||
- @nhost/react-auth@2.0.9
|
||||
@@ -1,29 +1,7 @@
|
||||
const path = require('path')
|
||||
const { getLoader, loaderByName } = require('@craco/craco')
|
||||
|
||||
const packageDirs = ['nhost', 'react-apollo', 'react-auth', 'hasura-auth', 'hasura-storage']
|
||||
const packages = packageDirs.map((dir) => path.join(__dirname, '../../packages', dir))
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
{
|
||||
plugin: {
|
||||
overrideWebpackConfig: ({ webpackConfig }) => {
|
||||
const { isFound, match } = getLoader(webpackConfig, loaderByName('babel-loader'))
|
||||
if (isFound) {
|
||||
const include = Array.isArray(match.loader.include)
|
||||
? match.loader.include
|
||||
: [match.loader.include]
|
||||
match.loader.include = include.concat(packages)
|
||||
}
|
||||
return webpackConfig
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
style: {
|
||||
postcss: {
|
||||
plugins: [require('tailwindcss'), require('autoprefixer')]
|
||||
}
|
||||
}
|
||||
}
|
||||
plugins: [require("tailwindcss"), require("autoprefixer")],
|
||||
},
|
||||
},
|
||||
};
|
||||
4
examples/react-apollo-crm/package-lock.json
generated
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "react-apollo",
|
||||
"name": "@nhost-examples/react-apollo-crm",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "react-apollo",
|
||||
"name": "@nhost-examples/react-apollo-crm",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.4.16",
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@nhost-examples/react-apollo",
|
||||
"version": "0.1.1",
|
||||
"name": "@nhost-examples/react-apollo-crm",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.4.16",
|
||||
"@craco/craco": "^6.4.0",
|
||||
"@headlessui/react": "^1.4.2",
|
||||
"@heroicons/react": "^1.0.5",
|
||||
"@nhost/nhost-js": "^0.3.11",
|
||||
"@nhost/react-apollo": "^3.0.0",
|
||||
"@nhost/react-auth": "^2.0.9",
|
||||
"@nhost/nhost-js": "^0.3.4",
|
||||
"@nhost/react-apollo": "^2.0.7-0",
|
||||
"@nhost/react-auth": "^2.0.3",
|
||||
"@saeris/apollo-server-vercel": "^1.0.1",
|
||||
"@tailwindcss/forms": "^0.3.4",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
@@ -32,10 +32,9 @@
|
||||
"web-vitals": "^1.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "SKIP_PREFLIGHT_CHECK=true craco start",
|
||||
"build": "SKIP_PREFLIGHT_CHECK=true craco build",
|
||||
"watch": "SKIP_PREFLIGHT_CHECK=true craco test",
|
||||
"test": "SKIP_PREFLIGHT_CHECK=true craco test --watchAll=false",
|
||||
"start": "craco start",
|
||||
"build": "craco build",
|
||||
"test": "craco test",
|
||||
"eject": "react-scripts eject",
|
||||
"codegen": "graphql-codegen --config codegen.yaml --errors-only"
|
||||
},
|
||||
@@ -69,4 +68,4 @@
|
||||
"postcss": "^7.0.39",
|
||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.17"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,5 +7,5 @@ Once in the example's directory, run the two following commands in parallel:
|
||||
nhost -d
|
||||
|
||||
# Start this project
|
||||
pnpm run dev
|
||||
yarn run dev
|
||||
```
|
||||
|
||||
@@ -7,7 +7,7 @@ services:
|
||||
environment:
|
||||
hasura_graphql_enable_remote_schema_permissions: false
|
||||
auth:
|
||||
version: 0.2.1
|
||||
version: 0.4.2
|
||||
auth:
|
||||
access_control:
|
||||
email:
|
||||
@@ -124,10 +124,10 @@ auth:
|
||||
allowed_roles: user,me
|
||||
default_allowed_roles: user,me
|
||||
default_role: user
|
||||
mfa:
|
||||
enabled: false
|
||||
issuer: nhost
|
||||
signin_email_verified_required: true
|
||||
mfa:
|
||||
enabled: true
|
||||
issuer: nhost
|
||||
storage:
|
||||
force_download_for_content_types: text/html,application/javascript
|
||||
version: 3
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@nhost/client": "workspace:*",
|
||||
"@nhost/react": "workspace:*",
|
||||
"@nhost/react-apollo": "workspace:*",
|
||||
"@nhost/react": "^0.2.0",
|
||||
"@nhost/react-apollo": "^3.0.0",
|
||||
"@rsuite/icons": "^1.0.2",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"react": "^17.0.2",
|
||||
@@ -39,7 +38,6 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apollo/client": "^3.5.9",
|
||||
"@types/react": "^17.0.39",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"@vitejs/plugin-react": "^1.2.0",
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Routes, Route, Link, useNavigate, useLocation } from 'react-router-dom'
|
||||
import { Container, Header, Navbar, Content, Nav } from 'rsuite'
|
||||
import { useEffect } from 'react'
|
||||
import { SignInPage } from './sign-in'
|
||||
import { AuthGate } from './components/auth-gates'
|
||||
import { AuthGate, PublicGate } from './components/auth-gates'
|
||||
import Home from './Home'
|
||||
import { ProfilePage } from './profile'
|
||||
import { ApolloPage } from './apollo'
|
||||
@@ -57,8 +57,22 @@ function App() {
|
||||
}
|
||||
/>
|
||||
<Route path="/about" element={<AboutPage />} />
|
||||
<Route path="/sign-in/*" element={<SignInPage />} />
|
||||
<Route path="/sign-up/*" element={<SignUpPage />} />
|
||||
<Route
|
||||
path="/sign-in/*"
|
||||
element={
|
||||
<PublicGate>
|
||||
<SignInPage />
|
||||
</PublicGate>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/sign-up/*"
|
||||
element={
|
||||
<PublicGate>
|
||||
<SignUpPage />
|
||||
</PublicGate>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/profile"
|
||||
element={
|
||||
|
||||
@@ -25,8 +25,7 @@ export const PublicGate: React.FC = ({ children }) => {
|
||||
}
|
||||
|
||||
if (isAuthenticated) {
|
||||
// ? stay on the same route - is it the best way to do so?
|
||||
return <Navigate to={location} state={{ from: location }} replace />
|
||||
return <Navigate to={'/'} state={{ from: location }} replace />
|
||||
}
|
||||
|
||||
return <div>{children}</div>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Button, Input, Message } from 'rsuite'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useEmailPasswordlessSignIn } from '@nhost/react'
|
||||
import { useSignInEmailPasswordless } from '@nhost/react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
export const EmailPasswordlessForm: React.FC = () => {
|
||||
const [email, setEmail] = useState('')
|
||||
const navigate = useNavigate()
|
||||
const { signIn, isError, isSuccess, error } = useEmailPasswordlessSignIn(email, {
|
||||
const { signInEmailPasswordless, isError, isSuccess, error } = useSignInEmailPasswordless(email, {
|
||||
redirectTo: '/profile'
|
||||
})
|
||||
const [showError, setShowError] = useState(true)
|
||||
@@ -42,7 +42,7 @@ export const EmailPasswordlessForm: React.FC = () => {
|
||||
style={{ marginTop: '0.5em' }}
|
||||
onClick={() => {
|
||||
setShowError(true)
|
||||
signIn()
|
||||
signInEmailPasswordless()
|
||||
}}
|
||||
>
|
||||
Continue with email
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Icon } from '@rsuite/icons'
|
||||
import { useProviderLink } from '@nhost/react'
|
||||
|
||||
export const OAuthLinks: React.FC = () => {
|
||||
// TODO show how to use options
|
||||
const { github, google, facebook } = useProviderLink()
|
||||
return (
|
||||
<div>
|
||||
|
||||