Compare commits

..

117 Commits

Author SHA1 Message Date
Pilou
024f026241 Merge pull request #839 from nhost/changeset-release/main
chore: update versions
2022-07-19 10:43:17 +02:00
Pierre-Louis Mercereau
a422a4850d chore: correct peer deps bumps 2022-07-19 09:54:46 +02:00
github-actions[bot]
a7e67979fe chore: update versions 2022-07-19 07:48:08 +00:00
Pilou
1dcbf268db Merge pull request #820 from nhost/feat/sms-hook-and-composable
feat: useSignInSmsPasswordless
2022-07-19 09:47:05 +02:00
Pilou
5c5d489740 Merge pull request #841 from nhost/contributors-readme-action-mLUJqJcCpL
contributors readme action update
2022-07-19 09:46:51 +02:00
github-actions[bot]
a2559e3482 contrib-readme-action has updated readme 2022-07-19 07:46:19 +00:00
Pilou
bbef104a85 Merge pull request #840 from nhost/contributors-readme-action-MWLllvW8wS
contributors readme action update
2022-07-19 09:46:05 +02:00
github-actions[bot]
7843b1aec1 contrib-readme-action has updated readme 2022-07-19 07:41:45 +00:00
Pilou
4711bfa8ec Merge pull request #679 from Svarto/feat/changePassword-with-ticket
included an optional ticket in changePassword function to allow for c…
2022-07-19 09:41:27 +02:00
Pilou
6f3f8a5020 Merge pull request #838 from nhost/fix-providers
added twitch as provider
2022-07-19 09:38:32 +02:00
Pilou
a120bcc8fc Merge pull request #828 from dminkovsky/dminkovsky/fix-react-native-build
Fix React Native build
2022-07-19 09:36:02 +02:00
Johan Eliasson
53e20e87f3 Revert "Create stale-bags-design.md"
This reverts commit 9479aeb596.
2022-07-19 09:18:24 +02:00
Johan Eliasson
9479aeb596 Create stale-bags-design.md 2022-07-19 09:10:25 +02:00
Pilou
c4f11af072 Merge pull request #837 from nhost/contributors-readme-action-ZK2-b_IYkd
contributors readme action update
2022-07-19 09:07:47 +02:00
Johan Eliasson
747aa96914 Create dry-radios-allow.md 2022-07-19 09:07:43 +02:00
Johan Eliasson
5682d92592 added twitch as provider 2022-07-19 09:06:51 +02:00
github-actions[bot]
2cf6556499 contrib-readme-action has updated readme 2022-07-19 07:06:07 +00:00
Johan Eliasson
89553fcaf6 Merge pull request #830 from QuestGiverOrg/main
Add discord to provider types
2022-07-19 09:05:48 +02:00
Johan Eliasson
10beea7246 Create nine-students-design.md 2022-07-19 09:03:06 +02:00
Johan Eliasson
1334ddb693 added package.json export for all npm packages 2022-07-19 09:02:23 +02:00
Pilou
d212128815 Merge pull request #829 from nhost/changeset-release/main
chore: update versions
2022-07-16 15:22:46 +02:00
Gavan Wilhite
302c28b202 Merge pull request #1 from QuestGiverOrg/Adding-discord-to-provider-type
Added discord to provider type
2022-07-15 13:28:45 -07:00
Gavan Wilhite
f3f760b987 Added discord to provider type 2022-07-15 13:24:32 -07:00
github-actions[bot]
9d9caf9834 chore: update versions 2022-07-15 20:20:38 +00:00
Pilou
96cbf023ca Merge pull request #824 from nhost/docs/react-apollo-example-improvements
React Apollo example improvements
2022-07-15 22:19:01 +02:00
Pierre-Louis Mercereau
1ed534cb4a Merge branch 'main' into docs/react-apollo-example-improvements 2022-07-15 22:06:07 +02:00
Pilou
dcdee0b426 Merge pull request #819 from nhost/docs/vue-example-improvements
Vue example improvements
2022-07-15 22:02:58 +02:00
Pierre-Louis Mercereau
e31f4756b4 fix(vue-example): disabled & loading buttons 2022-07-15 20:13:44 +02:00
Pierre-Louis Mercereau
259e198d80 fix(react-apollo-example): fixed logo width 2022-07-15 19:45:22 +02:00
Pierre-Louis Mercereau
1d10a47414 fix(react-apollo-example): fit image logo 2022-07-15 19:42:37 +02:00
Dmitry Minkovsky
34470ff6e0 Fix React Native build fail 2022-07-15 12:11:18 -04:00
Pierre-Louis Mercereau
f30d6779bb chore: bump @apollo/client to v3.6.9 2022-07-15 15:55:29 +02:00
Pierre-Louis Mercereau
2a3b2c3af5 Merge branch 'main' into docs/vue-example-improvements 2022-07-15 15:39:38 +02:00
Pierre-Louis Mercereau
a0db6b58de chore: add hasura-auth 0.10 metadata 2022-07-15 12:06:08 +02:00
Pierre-Louis Mercereau
523d52aa7f Merge branch 'main' into docs/react-apollo-example-improvements 2022-07-15 11:48:41 +02:00
Pierre-Louis Mercereau
6e1ee1802d docs: explicit pnpm run 2022-07-15 11:45:45 +02:00
Pierre-Louis Mercereau
51ad1eb355 fix(react-apollo-example): qrcode img by alttext 2022-07-15 11:39:22 +02:00
Johan Eliasson
ee2dd8481b Merge pull request #825 from nhost/changeset-release/main
chore: update versions
2022-07-15 11:21:12 +02:00
github-actions[bot]
b8e787cb47 chore: update versions 2022-07-15 09:18:40 +00:00
Johan Eliasson
2ef5c238c1 Merge pull request #823 from nhost/patch/cookies
patch: Using same cookie package and made sure cookies are not becoming session cookies
2022-07-15 11:17:04 +02:00
Pierre-Louis Mercereau
e084643032 docs: correct readme 2022-07-15 11:11:35 +02:00
Pierre-Louis Mercereau
5514e81186 docs: update readme 2022-07-15 11:10:44 +02:00
Pierre-Louis Mercereau
16f38aa893 docs(example): update readme instructions 2022-07-15 11:09:08 +02:00
Pierre-Louis Mercereau
76c6e8d0d6 feat(react-apollo-example): improve navbar & index 2022-07-15 10:33:27 +02:00
Johan Eliasson
197d1d5cfc Create lovely-windows-accept.md 2022-07-15 10:03:25 +02:00
Johan Eliasson
abd43d0a8b typo 2022-07-15 09:49:03 +02:00
Johan Eliasson
70383c8c80 same cookie lib + added expires prop to avoid cookie being destroyed 2022-07-15 09:45:19 +02:00
Pierre-Louis Mercereau
a7d5c85f60 fix(example): hide nav drawer on small screens 2022-07-15 09:35:28 +02:00
Pierre-Louis Mercereau
bc657251d6 fix: remove refresh token from the url 2022-07-14 22:07:59 +02:00
Pierre-Louis Mercereau
5abc362a4d fix(example): close magic link sent dialog 2022-07-14 15:10:11 +02:00
Pierre-Louis Mercereau
7a4c9fa806 refactor(example): use form submit 2022-07-14 15:06:57 +02:00
Pierre-Louis Mercereau
348318d709 feat(example): add dialog after magic link is sent 2022-07-14 14:48:30 +02:00
Pierre-Louis Mercereau
4e4600d769 refactor: improve readability 2022-07-14 09:13:55 +02:00
Pierre-Louis Mercereau
44d57d4b89 refactor: from comments 2022-07-14 09:04:16 +02:00
Pierre-Louis Mercereau
84ba29dd7f feat: useSignInSmsPasswordless 2022-07-13 20:39:17 +02:00
Pierre-Louis Mercereau
b5f7f7fe5f refactor(example): toast errors on top of window 2022-07-13 19:45:38 +02:00
Pierre-Louis Mercereau
7116a4df8a refactor(example): misc improvements 2022-07-13 19:39:11 +02:00
Pierre-Louis Mercereau
7e4c52dbd1 feat(example): add title and GitHub link 2022-07-13 17:20:55 +02:00
Pierre-Louis Mercereau
446dc01bde feat(example): toast anonymous user errors 2022-07-13 17:07:25 +02:00
Pierre-Louis Mercereau
a1989c51f8 feat(example): enable anonymous users in the backend 2022-07-13 17:00:59 +02:00
Pierre-Louis Mercereau
1383de558a feat(example): add email verification dialog on sign-in 2022-07-13 17:00:39 +02:00
Pierre-Louis Mercereau
d828107f74 fix(example): remove "return" from previous "setup()" syntax 2022-07-13 16:43:10 +02:00
Pierre-Louis Mercereau
4a1650cb35 refactor(example): use the template "setup" syntax 2022-07-13 16:37:23 +02:00
Pierre-Louis Mercereau
913651d440 feat(example): add "verification email sent" dialog 2022-07-13 16:29:40 +02:00
Pierre-Louis Mercereau
6af2d52666 chore(vue): bump dependencies 2022-07-13 15:52:12 +02:00
Pilou
da7c2a2362 Merge pull request #818 from nhost/chore/hasura-storage-0.2.3
chore: bump hasura-storage version to 0.2.3
2022-07-13 15:25:04 +02:00
Pierre-Louis Mercereau
4a7940b59a chore: bump hasura-storage version to 0.2.3 2022-07-13 15:10:39 +02:00
Pilou
ddda8bb031 Merge pull request #817 from nhost/chore/hasura-auth-0.10.0
chore: bump hasura-auth version to 0.10.0
2022-07-13 13:28:52 +02:00
Pierre-Louis Mercereau
b146e60f7e chore: bump hasura-auth version to 0.10.0 2022-07-13 11:02:40 +02:00
Pilou
5591789840 Merge pull request #816 from nhost/contributors-readme-action-wpdtyjiZOQ
contributors readme action update
2022-07-13 10:12:05 +02:00
github-actions[bot]
fac5ddb866 contrib-readme-action has updated readme 2022-07-13 05:09:22 +00:00
Johan Eliasson
f2fab8dac2 Merge pull request #784 from nachoaldamav/patch-1
docs: Add "redirectTo" to provider sign-in
2022-07-13 07:09:03 +02:00
Pilou
6e3f2c382d Merge pull request #807 from nhost/doc/vue-live-example
fix: wrong package name
2022-07-07 17:53:51 +02:00
Pilou
05385d01dc Merge pull request #809 from nhost/contributors-readme-action-l3DsL6Hz69
contributors readme action update
2022-07-07 16:37:59 +02:00
github-actions[bot]
7ea72b799c contrib-readme-action has updated readme 2022-07-07 14:10:36 +00:00
Pilou
4936261cee Merge pull request #808 from nhost/docs/docker-functions
refactor: use nhost/functions docker image
2022-07-07 16:09:10 +02:00
Pierre-Louis Mercereau
80902b9cf1 refactor: use nhost/functions docker image 2022-07-07 15:53:30 +02:00
Pierre-Louis Mercereau
c3af490e67 fix: wrong package name 2022-07-07 14:32:13 +02:00
Pilou
6a24e32857 Merge pull request #806 from nhost/doc/vue-live-example
Vue example: add env var deps in turborepo
2022-07-07 14:21:38 +02:00
Pierre-Louis Mercereau
0ebddd30cf ci: add env var deps in turborepo 2022-07-07 14:17:11 +02:00
Johan Eliasson
d019f1de21 Merge pull request #805 from nhost/doc/vue-live-example
Adapt Vue-Apollo example to live demo
2022-07-07 12:35:02 +02:00
Pierre-Louis Mercereau
3abb57f510 chore: add vercel.json to handle redirections 2022-07-07 11:20:26 +02:00
Pierre-Louis Mercereau
4a2ad15f14 docs: adapt Vue-Apollo example to live demo 2022-07-07 11:17:02 +02:00
Pilou
ca45b612c9 Merge pull request #773 from nhost/build/sync-versions
Sync the Nhost services versions within the repository
2022-07-07 10:43:18 +02:00
Pilou
27ee9b721f Merge pull request #804 from nhost/docs/oauth-providers-alphabetic
Docs: List OAuth providers in order
2022-07-07 10:43:04 +02:00
Johan Eliasson
2a373dd50f revert 2022-07-07 10:36:37 +02:00
Johan Eliasson
a91f714c4c order 2022-07-07 10:34:51 +02:00
Pilou
3b4d89d5b6 Merge pull request #803 from nhost/elitan-patch-2
Missing `services:` in nhost config
2022-07-07 10:31:40 +02:00
Johan Eliasson
16d1b26298 Update config.yaml 2022-07-07 10:29:24 +02:00
Pierre-Louis Mercereau
86d8beb044 chore: update lockfile 2022-07-07 10:27:53 +02:00
Pierre-Louis Mercereau
17f870f31f Merge branch 'main' into build/sync-versions 2022-07-07 10:26:17 +02:00
Pilou
fbfffe25ca Merge pull request #799 from nhost/docs/discord-signin
Docs: Sign in with Discord and Twitch
2022-07-07 09:46:01 +02:00
Pilou
87a472b27e Merge pull request #802 from nhost/docs/video-iuasd
Docs: Update videos
2022-07-07 09:44:46 +02:00
Johan Eliasson
779b03b0b2 delete unused video 2022-07-07 07:16:00 +02:00
Johan Eliasson
9d933b6ffd open hasura console 2022-07-07 07:12:23 +02:00
Johan Eliasson
34d643868d typos 2022-07-06 20:25:47 +02:00
Johan Eliasson
0023f5f6f6 og images 2022-07-06 20:24:48 +02:00
Johan Eliasson
48f5c8bfb9 added docs for twitch + images 2022-07-06 20:22:12 +02:00
Johan Eliasson
f398b2e3ac update 2022-07-06 18:59:40 +02:00
Johan Eliasson
11795abe61 discord docs 2022-07-06 18:59:06 +02:00
Johan Eliasson
e2eafc9ee1 Merge pull request #796 from nhost/docs/apple-signin
Docs: Sign in with Apple
2022-07-06 07:29:30 +02:00
Johan Eliasson
4a908af7ef old domain structure 2022-07-05 11:27:58 +02:00
Johan Eliasson
a7b6498053 update information about service id 2022-07-05 11:02:02 +02:00
Johan Eliasson
7f418a7559 started 2022-07-05 10:54:36 +02:00
Pierre-Louis Mercereau
50474810bf refactor: run command with swc 2022-07-04 16:52:31 +02:00
Nacho Aldama
ead2c16aac Add "redirectTo" to documentation
When I was searching for the "redirectTo" param I didn't find anything in the docs, maybe it was my fault but I've missed this.

Sorry if this is duplicated.
2022-07-02 19:19:25 +02:00
Pierre-Louis Mercereau
21fa83d115 build: adapt turborepo pipeline 2022-06-29 17:23:00 +02:00
Pierre-Louis Mercereau
522839d8f7 chore: keep original lockfile 2022-06-29 17:19:24 +02:00
Pierre-Louis Mercereau
87aad599f3 chore: update lockfile 2022-06-29 17:17:01 +02:00
Pierre-Louis Mercereau
5b097e635d chore: remove verbose 2022-06-29 17:10:43 +02:00
Pierre-Louis Mercereau
bfdcacd5a3 smaller eslintrc 2022-06-29 17:04:09 +02:00
Pierre-Louis Mercereau
dcb9055475 chore: remove console.log 2022-06-29 16:58:14 +02:00
Pierre-Louis Mercereau
6f0bf3d67c docs: typoe 2022-06-29 16:54:24 +02:00
Pierre-Louis Mercereau
3c96c561a0 chore: remove unused dependency 2022-06-29 16:45:33 +02:00
Pierre-Louis Mercereau
3d319364f3 build: sync nhost services versions 2022-06-29 16:44:15 +02:00
Svarto
18ac56d097 added changeset for hasura-auth-js 2022-06-06 21:38:53 +02:00
Svarto
366fc2403d included an optional ticket in changePassword function to allow for changeing password of logged out users, matches hasura-auth #186 2022-06-06 21:27:44 +02:00
141 changed files with 2554 additions and 1388 deletions

View File

@@ -1,4 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged

View File

@@ -1,6 +0,0 @@
{
"packages/(docgen|hasura-auth-js|hasura-storage-js|nextjs|nhost-js|react|core|vue)/src/**/*.{js,ts,jsx,tsx}": [
"pnpm docgen",
"git add docs"
]
}

View File

@@ -147,13 +147,6 @@ Here are some ways of contributing to making Nhost better:
<sub><b>Johan Eliasson</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/szilarddoro">
<img src="https://avatars.githubusercontent.com/u/310881?v=4" width="100;" alt="szilarddoro"/>
<br />
<sub><b>Szilárd Dóró</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/gdangelo">
<img src="https://avatars.githubusercontent.com/u/4352286?v=4" width="100;" alt="gdangelo"/>
@@ -174,15 +167,15 @@ Here are some ways of contributing to making Nhost better:
<br />
<sub><b>Guido Curcio</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/subatuba21">
<img src="https://avatars.githubusercontent.com/u/34824571?v=4" width="100;" alt="subatuba21"/>
<br />
<sub><b>Subha Das</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/sebagudelo">
<img src="https://avatars.githubusercontent.com/u/43288271?v=4" width="100;" alt="sebagudelo"/>
@@ -204,21 +197,35 @@ Here are some ways of contributing to making Nhost better:
<sub><b>Pratim</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/szilarddoro">
<img src="https://avatars.githubusercontent.com/u/310881?v=4" width="100;" alt="szilarddoro"/>
<br />
<sub><b>Szilárd Dóró</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/GavanWilhite">
<img src="https://avatars.githubusercontent.com/u/2085119?v=4" width="100;" alt="GavanWilhite"/>
<br />
<sub><b>Gavan Wilhite</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/FuzzyReason">
<img src="https://avatars.githubusercontent.com/u/62517920?v=4" width="100;" alt="FuzzyReason"/>
<br />
<sub><b>Vadim Smirnov</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/macmac49">
<img src="https://avatars.githubusercontent.com/u/831190?v=4" width="100;" alt="macmac49"/>
<br />
<sub><b>Macmac49</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/subhendukundu">
<img src="https://avatars.githubusercontent.com/u/20059141?v=4" width="100;" alt="subhendukundu"/>
@@ -253,13 +260,6 @@ Here are some ways of contributing to making Nhost better:
<br />
<sub><b>Filip Hájek</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/GavanWilhite">
<img src="https://avatars.githubusercontent.com/u/2085119?v=4" width="100;" alt="GavanWilhite"/>
<br />
<sub><b>Gavan Wilhite</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
@@ -391,6 +391,13 @@ Here are some ways of contributing to making Nhost better:
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/nachoaldamav">
<img src="https://avatars.githubusercontent.com/u/22749943?v=4" width="100;" alt="nachoaldamav"/>
<br />
<sub><b>Nacho Aldama</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ghoshnirmalya">
<img src="https://avatars.githubusercontent.com/u/6391763?v=4" width="100;" alt="ghoshnirmalya"/>

4
config/.husky/pre-commit Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged --config config/.lintstagedrc.js

8
config/.lintstagedrc.js Normal file
View File

@@ -0,0 +1,8 @@
module.exports = {
'packages/(docgen|hasura-auth-js|hasura-storage-js|nextjs|nhost-js|react|core|vue)/src/**/*.{js,ts,jsx,tsx}':
['pnpm docgen', 'git add docs'],
'(nhost-cloud.yaml|**/nhost/config.yaml)': () => [
'pnpm sync-versions',
"git add ':(glob)**/nhost/config.yaml'"
]
}

View File

@@ -1,5 +1,11 @@
# @nhost/docs
## 0.0.2
### Patch Changes
- 747aa969: fix: added twitch and discord as provider
## 0.0.1
### Patch Changes

View File

@@ -0,0 +1,98 @@
---
title: Sign In with Apple
sidebar_label: Apple
slug: /platform/authentication/sign-in-with-apple
image: /img/og/platform/sign-in-with-apple.png
---
Follow this guide to sign in users with Apple with your Nhost App.
<p align="center">
<img
alt="Apple Sign In Preview"
src="/img/social-providers/apple-preview.svg"
width={480}
height={267}
/>
</p>
## Create Apple Developer Account
- Click on "Account" in the top menu.
- Create a new [Apple Developer account](https://developer.apple.com) if you don't have one already and sign in to the Apple Developer platform.
## Get an App ID
- Go to the [Apple Developer Dashboard](https://developer.apple.com/account/).
- Click on **Certificates, IDs & Profiles** in the left menu.
- Click on **Identifiers** in the left menu.
- Click on the "+" button in the header next to "Identifiers".
- Select **App IDs** and click **Continue**.
- Select type **App** and click **Continue**.
- Fill in the App information:
- Description.
- Bundle ID (ex. io.nhost.app or com.your-startup.app).
- Scroll down and check **Sign In With Apple**.
- Click **Continue** in the top right corner.
- Click **Register** in the top right corner.
- Click on the newly created app to see **Team ID**.
- **Team ID**: Copy and paste the **Team ID** to your Nhost OAuth settings for Apple.
## Get a Service ID
- Go to the [Apple Developer Dashboard](https://developer.apple.com/account/).
- Click on **Certificates, IDs & Profiles** in the left menu.
- Click on **Identifiers** in the left menu.
- Click on **Certificates, IDs & Profiles** in the left menu.
- Click on **Identifiers** in the left menu.
- Click on the "+" button in the header next to "Identifiers".
- Select **Service IDs** and click **Continue**.
- Fill in the Service information:
- Description.
- Identifier (Service ID) (ex. _service_.io.nhost.app or _service_.com.your-startup.app). Notice you can't use the same identifier as for the app so we recommend adding "service" at the beginning if the identifier.
- **Service ID**: Copy and paste the **Identifier (Service ID)** to your Nhost OAuth settings for Apple.
- Click **Continue** in the top right corner.
- Click **Register** in the top right corner.
- Click on the newly created service in the list of Identifiers.
- Click the checkbox to enable "Sign in with Apple".
- Click **Configure** next to "Sign in with Apple".
- Make sure your newly created Bundle ID is selected under Primary App ID.
- Add your base auth domain under "Domains and Subdomains". E.g. `<subdomain>.nhost.run`.
- Add the full callback URL under "Return URLs". E.g. `https://<subdomain>.nhost.run/v1/auth/signin/provider/apple/callback`.
- Click **Next**.
- Click **Done**.
- Click **Continue** in the top right corner.
- Click **Save** in the top right corner.
## Generate Key
- Go to the [Apple Developer Dashboard](https://developer.apple.com/account/).
- Click on **Certificates, IDs & Profiles** in the left menu.
- Click on **Keys** in the left menu.
- Click on **Create a key**.
- Fill in a name for your key.
- Click the checkbox to enable "Sign in with Apple".
- Click **Configure** next to "Sign in with Apple".
- Select your newly created App ID in the dropdown selector.
- Click **Save** in the top right corner.
- Click **Continue** in the top right corner.
- Click **Register** in the top right corner.
- **Key ID**: Copy and paste the **Key ID** to your Nhost OAuth settings for Apple.
- Click **Download** to download the key to your computer.
- **Private Key**: Copy and paste the content of the downloaded key to your Nhost OAuth settings for Apple.
## Sign In Users
Use the [Nhost JavaScript client](/reference/javascript) to sign in users in your app:
```js
nhost.auth.signIn({
provider: 'apple'
})
```

View File

@@ -0,0 +1,45 @@
---
title: Sign In with Discord
sidebar_label: Discord
slug: /platform/authentication/sign-in-with-discord
image: /img/og/platform/sign-in-with-discord.png
---
Follow this guide to sign in users with Discord with your Nhost App.
<p align="center">
<img
alt="Discord Sign In Preview"
src="/img/social-providers/discord-preview.svg"
width={480}
height={267}
/>
</p>
## Create Discord Account
- Create a new [Discord account](https://discord.com/) if you don't have one already.
## Create Discord App
- Sign in to the [Discord Developer Portal](https://discord.com/developers/applications).
- Click on **New Application** in the top right corner.
- Fill in the name of your Discord Application and click **Create**.
- Click on **OAuth2** settings in the left menu.
- Copy the **Client ID** and paste it into your Nhost OAuth settings for Discord.
- Click on **Reset Secret**.
- Click **Yes, do it** to generate a new secret.
- Copy the **Client Secret** and paste it into your Nhost OAuth settings for Discord.
- Click on **Add Redirect**.
- Copy and paste the callback URL from your Nhost OAuth settings for Discord to the input field in the Discord Developer portal.
- Click **Save Changes** to save the added callback URL.
## Sign In Users
Use the [Nhost JavaScript client](/reference/javascript) to sign in users in your app:
```js
nhost.auth.signIn({
provider: 'discord'
})
```

View File

@@ -0,0 +1,47 @@
---
title: Sign In with Twitch
sidebar_label: Twitch
slug: /platform/authentication/sign-in-with-twitch
image: /img/og/platform/sign-in-with-twitch.png
---
Follow this guide to sign in users with Twitch with your Nhost App.
<p align="center">
<img
alt="Twitch Sign In Preview"
src="/img/social-providers/twitch-preview.svg"
width={480}
height={267}
/>
</p>
## Create Twitch Account
- Create a new [Twitch account](https://twitch.tv/) if you don't have one already.
## Create Twitch App
- Sign in to the [Twitch Developer Console](https://dev.twitch.tv/console).
- Click on **Register Your Application**.
- Fill in a **Twitch application name**.
- Copy and paste the callback URL from your Nhost OAuth settings for Twitch to the input field under **OAuth Redirect URLs** and click **Add** to the right of the input field.
- Select an application **Category**. E.g. _Application Integration_.
- Click **Create**.
## Get Twitch Appplication Client ID and Client Secret
- Click on **Manage** on your newly created Twitch application.
- Copy the **Client ID** and paste it into your Nhost OAuth settings for Twitch.
- Click on **New Secret** to generate a new client secret.
- Copy the **Client Secret** and paste it into your Nhost OAuth settings for Twitch.
## Sign In Users
Use the [Nhost JavaScript client](/reference/javascript) to sign in users in your app:
```js
nhost.auth.signIn({
provider: 'twitch'
})
```

View File

@@ -35,6 +35,18 @@ nhost.auth.signIn({
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****Authentication Settings****Client URL**.
Here is an example of how to redirect to another host or path:
```js
nhost.auth.signIn({
provider: '<provider>'
options: {
redirectTo: "<host>/<slug>" // Example: "https://example.com/dashboard"
},
})
```
## Provider OAuth scopes
Scopes are a mechanism in OAuth to allow or limit an application's access to a user's account.

View File

@@ -22,4 +22,6 @@ type Provider =
| 'strava'
| 'gitlab'
| 'bitbucket'
| 'discord'
| 'twitch'
```

View File

@@ -0,0 +1,50 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: useSignInSmsPasswordless()
sidebar_label: useSignInSmsPasswordless()
slug: /reference/nextjs/use-sign-in-sms-passwordless
description: Use the hook `useSignInSmsPasswordless` to sign in a user with a one-time password sent via SMS to a phone.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSmsPasswordless.ts#L57
---
# `useSignInSmsPasswordless()`
Use the hook `useSignInSmsPasswordless` to sign in a user with a one-time password sent via SMS to a phone.
1. The `signInSmsPasswordless` action sends a one-time password to the given phone number.
2. The client is then awaiting the OTP. `needsOtp` equals true.
3. After the code is received by SMS, the client sends the code with `sendOtp`. On success, the client is authenticated, and `isSuccess` equals `true`.
Any error is monitored through `isError` and `error`. While the `signInSmsPasswordless` and `sendOtp` actions are running, `isLoading` equals `true`.
```tsx
const {
signInSmsPasswordless,
sendOtp,
needsOtp,
isLoading,
isSuccess,
isError,
error
} = useSignInSmsPasswordless()
console.log({ isLoading, isSuccess, isError, error })
const askCode = async (e) => {
e.preventDefault()
await signInSmsPasswordless('+32455555555')
}
const sendCode = async (e) => {
e.preventDefault()
await sendOtp('123456')
}
```
## Parameters
---
**<span className="parameter-name">stateOptions</span>** <span className="optional-status">optional</span> `PasswordlessOptions`
---

View File

@@ -0,0 +1,10 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignInSmsPasswordlessHandler
sidebar_label: SignInSmsPasswordlessHandler
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSmsPasswordless.ts#L14
---
# `SignInSmsPasswordlessHandler`

View File

@@ -0,0 +1,62 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignInSmsPasswordlessHookResult
sidebar_label: SignInSmsPasswordlessHookResult
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSmsPasswordless.ts#L23
---
# `SignInSmsPasswordlessHookResult`
## Parameters
---
**<span className="parameter-name">needsOtp</span>** <span className="optional-status">required</span> `boolean`
Returns true when the one-time password has been sent over by SMS, and the user needs to send it back to complete sign-in.
---
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> `boolean`
**`@returns`**
`true` if an error occurred
**`@depreacted`**
use `!isSuccess` or `!!error` instead
---
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> `null` | `ErrorPayload`
Provides details about the error
---
**<span className="parameter-name">isLoading</span>** <span className="optional-status">required</span> `boolean`
**`@returns`**
`true` when the action is executing, `false` when it finished its execution.
---
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> `boolean`
Returns `true` if the action is successful.
---
**<span className="parameter-name">signInSmsPasswordless</span>** <span className="optional-status">required</span> [`SignInSmsPasswordlessHandler`](/reference/docgen/nextjs/types/sign-in-sms-passwordless-handler)
Sends a one-time code to the given phoneNumber
---
**<span className="parameter-name">sendOtp</span>** <span className="optional-status">required</span> [`SignInSmsPasswordlessOtpHandler`](/reference/docgen/nextjs/types/sign-in-sms-passwordless-otp-handler)
---

View File

@@ -0,0 +1,10 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignInSmsPasswordlessOtpHandler
sidebar_label: SignInSmsPasswordlessOtpHandler
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSmsPasswordless.ts#L18
---
# `SignInSmsPasswordlessOtpHandler`

View File

@@ -0,0 +1,50 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: useSignInSmsPasswordless()
sidebar_label: useSignInSmsPasswordless()
slug: /reference/react/use-sign-in-sms-passwordless
description: Use the hook `useSignInSmsPasswordless` to sign in a user with a one-time password sent via SMS to a phone.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSmsPasswordless.ts#L57
---
# `useSignInSmsPasswordless()`
Use the hook `useSignInSmsPasswordless` to sign in a user with a one-time password sent via SMS to a phone.
1. The `signInSmsPasswordless` action sends a one-time password to the given phone number.
2. The client is then awaiting the OTP. `needsOtp` equals true.
3. After the code is received by SMS, the client sends the code with `sendOtp`. On success, the client is authenticated, and `isSuccess` equals `true`.
Any error is monitored through `isError` and `error`. While the `signInSmsPasswordless` and `sendOtp` actions are running, `isLoading` equals `true`.
```tsx
const {
signInSmsPasswordless,
sendOtp,
needsOtp,
isLoading,
isSuccess,
isError,
error
} = useSignInSmsPasswordless()
console.log({ isLoading, isSuccess, isError, error })
const askCode = async (e) => {
e.preventDefault()
await signInSmsPasswordless('+32455555555')
}
const sendCode = async (e) => {
e.preventDefault()
await sendOtp('123456')
}
```
## Parameters
---
**<span className="parameter-name">stateOptions</span>** <span className="optional-status">optional</span> `PasswordlessOptions`
---

View File

@@ -0,0 +1,10 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignInSmsPasswordlessHandler
sidebar_label: SignInSmsPasswordlessHandler
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSmsPasswordless.ts#L14
---
# `SignInSmsPasswordlessHandler`

View File

@@ -0,0 +1,62 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignInSmsPasswordlessHookResult
sidebar_label: SignInSmsPasswordlessHookResult
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSmsPasswordless.ts#L23
---
# `SignInSmsPasswordlessHookResult`
## Parameters
---
**<span className="parameter-name">needsOtp</span>** <span className="optional-status">required</span> `boolean`
Returns true when the one-time password has been sent over by SMS, and the user needs to send it back to complete sign-in.
---
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> `boolean`
**`@returns`**
`true` if an error occurred
**`@depreacted`**
use `!isSuccess` or `!!error` instead
---
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> `null` | `ErrorPayload`
Provides details about the error
---
**<span className="parameter-name">isLoading</span>** <span className="optional-status">required</span> `boolean`
**`@returns`**
`true` when the action is executing, `false` when it finished its execution.
---
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> `boolean`
Returns `true` if the action is successful.
---
**<span className="parameter-name">signInSmsPasswordless</span>** <span className="optional-status">required</span> [`SignInSmsPasswordlessHandler`](/reference/docgen/react/types/sign-in-sms-passwordless-handler)
Sends a one-time code to the given phoneNumber
---
**<span className="parameter-name">sendOtp</span>** <span className="optional-status">required</span> [`SignInSmsPasswordlessOtpHandler`](/reference/docgen/react/types/sign-in-sms-passwordless-otp-handler)
---

View File

@@ -0,0 +1,10 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignInSmsPasswordlessOtpHandler
sidebar_label: SignInSmsPasswordlessOtpHandler
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/useSignInSmsPasswordless.ts#L18
---
# `SignInSmsPasswordlessOtpHandler`

View File

@@ -0,0 +1,50 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: useSignInSmsPasswordless()
sidebar_label: useSignInSmsPasswordless()
slug: /reference/vue/use-sign-in-sms-passwordless
description: Use the composable `useSignInSmsPasswordless` to sign in a user with a one-time password sent via SMS to a phone.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/vue/src/useSignInSmsPasswordless.ts#L65
---
# `useSignInSmsPasswordless()`
Use the composable `useSignInSmsPasswordless` to sign in a user with a one-time password sent via SMS to a phone.
1. The `signInSmsPasswordless` action sends a one-time password to the given phone number.
2. The client is then awaiting the OTP. `needsOtp` equals true.
3. After the code is received by SMS, the client sends the code with `sendOtp`. On success, the client is authenticated, and `isSuccess` equals `true`.
Any error is monitored through `isError` and `error`. While the `signInSmsPasswordless` and `sendOtp` actions are running, `isLoading` equals `true`.
```tsx
const {
signInSmsPasswordless,
sendOtp,
needsOtp,
isLoading,
isSuccess,
isError,
error
} = useSignInSmsPasswordless()
console.log({ isLoading, isSuccess, isError, error })
const askCode = async (e) => {
e.preventDefault()
await signInSmsPasswordless('+32455555555')
}
const sendCode = async (e) => {
e.preventDefault()
await sendOtp('123456')
}
```
## Parameters
---
**<span className="parameter-name">stateOptions</span>** <span className="optional-status">optional</span> `NestedRefOfValue<undefined | PasswordlessOptions>`
---

View File

@@ -0,0 +1,62 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignInSmsPasswordlessComposableResult
sidebar_label: SignInSmsPasswordlessComposableResult
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/vue/src/useSignInSmsPasswordless.ts#L31
---
# `SignInSmsPasswordlessComposableResult`
## Parameters
---
**<span className="parameter-name">needsOtp</span>** <span className="optional-status">required</span> `Ref<boolean>`
Returns true when the one-time password has been sent over by SMS, and the user needs to send it back to complete sign-in.
---
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> `Ref<boolean>`
**`@returns`**
`true` if an error occurred
**`@depreacted`**
use `!isSuccess` or `!!error` instead
---
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> `Ref<null | ErrorPayload>`
Provides details about the error
---
**<span className="parameter-name">isLoading</span>** <span className="optional-status">required</span> `Ref<boolean>`
**`@returns`**
`true` when the action is executing, `false` when it finished its execution.
---
**<span className="parameter-name">isSuccess</span>** <span className="optional-status">required</span> `Ref<boolean>`
Returns `true` if the action is successful.
---
**<span className="parameter-name">signInSmsPasswordless</span>** <span className="optional-status">required</span> [`SignInSmsPasswordlessHandler`](/reference/docgen/vue/types/sign-in-sms-passwordless-handler)
Sends a one-time code to the given phoneNumber
---
**<span className="parameter-name">sendOtp</span>** <span className="optional-status">required</span> [`SignInSmsPasswordlessOtpHandler`](/reference/docgen/vue/types/sign-in-sms-passwordless-otp-handler)
---

View File

@@ -0,0 +1,10 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignInSmsPasswordlessHandler
sidebar_label: SignInSmsPasswordlessHandler
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/vue/src/useSignInSmsPasswordless.ts#L16
---
# `SignInSmsPasswordlessHandler`

View File

@@ -0,0 +1,10 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: SignInSmsPasswordlessOtpHandler
sidebar_label: SignInSmsPasswordlessOtpHandler
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/vue/src/useSignInSmsPasswordless.ts#L23
---
# `SignInSmsPasswordlessOtpHandler`

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/docs",
"version": "0.0.1",
"version": "0.0.2",
"private": true,
"scripts": {
"docusaurus": "docusaurus",

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 67 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,5 @@
metadata_directory: metadata
services:
mailhog:
port: 8025
hasura:
@@ -6,9 +7,9 @@ metadata_directory: metadata
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
version: 0.9.1
version: 0.10.0
storage:
version: 0.2.2
version: 0.2.3
minio:
environment:
minio_root_password: minioaccesskey123123
@@ -20,12 +21,12 @@ metadata_directory: metadata
auth:
access_control:
email:
allowed_email_domains: ""
allowed_emails: ""
blocked_email_domains: ""
blocked_emails: ""
allowed_email_domains: ''
allowed_emails: ''
blocked_email_domains: ''
blocked_emails: ''
url:
allowed_redirect_urls: ""
allowed_redirect_urls: ''
anonymous_users_enabled: false
client_url: http://localhost:3000
disable_new_users: false
@@ -34,11 +35,11 @@ auth:
passwordless:
enabled: false
signin_email_verified_required: true
template_fetch_url: ""
template_fetch_url: ''
gravatar:
default: ""
default: ''
enabled: true
rating: ""
rating: ''
locale:
allowed: en
default: en
@@ -47,65 +48,65 @@ auth:
min_length: 3
provider:
apple:
client_id: ""
client_id: ''
enabled: false
key_id: ""
private_key: ""
key_id: ''
private_key: ''
scope: name,email
team_id: ""
team_id: ''
bitbucket:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
facebook:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: email,photos,displayName
github:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: user:email
token_url: ""
user_profile_url: ""
token_url: ''
user_profile_url: ''
gitlab:
base_url: ""
client_id: ""
client_secret: ""
base_url: ''
client_id: ''
client_secret: ''
enabled: false
scope: read_user
google:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: email,profile
linkedin:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: r_emailaddress,r_liteprofile
spotify:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: user-read-email,user-read-private
strava:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
twilio:
account_sid: ""
auth_token: ""
account_sid: ''
auth_token: ''
enabled: false
messaging_service_id: ""
messaging_service_id: ''
twitter:
consumer_key: ""
consumer_secret: ""
consumer_key: ''
consumer_secret: ''
enabled: false
windows_live:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: wl.basic,wl.emails,wl.contacts_emails
sms:
@@ -114,13 +115,13 @@ auth:
enabled: false
provider:
twilio:
account_sid: ""
auth_token: ""
from: ""
messaging_service_id: ""
account_sid: ''
auth_token: ''
from: ''
messaging_service_id: ''
smtp:
host: nhost_mailhog
method: ""
method: ''
pass: password
port: 1706
secure: false

View File

@@ -101,7 +101,7 @@ services:
- "traefik.http.routers.storage.middlewares=strip-suffix@docker"
command: serve
functions:
build: docker-functions
image: nhost/functions:latest
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.strip-functions.stripprefix.prefixes=/v1/functions"

View File

@@ -1,37 +0,0 @@
FROM node:14-alpine
# * Same version as in Watchtower
ARG EXPRESS_VERSION 4.17.1
ENV EXPRESS_VERSION $EXPRESS_VERSION
# * path to the server files
ARG SERVER_PATH /opt/server
ENV SERVER_PATH=$SERVER_PATH
# * Required to access to the globally installed modules
ENV NODE_PATH=/usr/local/lib/node_modules
# * Add path to the stored pnpm packages
ENV PNPM_HOME=/root/.local/share/pnpm
ENV PATH=$PATH:$PNPM_HOME
# * Directory where the Nhost project is located
ENV NHOST_PROJECT_PATH=/opt/project
# * Default package manager
ENV PACKAGE_MANAGER=pnpm
# * Install packages that are required for this docker image to run
RUN npm install -g pnpm nodemon express@$EXPRESS_VERSION glob @swc-node/register typescript @antfu/ni
# * The pnpm store should be mounted in the same volume as node_modules (requires hard links)
# * See https://pnpm.io/6.x/npmrc#store-dir
RUN pnpm config set store-dir $NHOST_PROJECT_PATH/node_modules/.pnpm-store
# * Copy server files
COPY nodemon.json start.sh server.ts $SERVER_PATH/
# * Change working directory to the Nhost project directory
WORKDIR $NHOST_PROJECT_PATH
CMD $SERVER_PATH/start.sh

View File

@@ -1,7 +0,0 @@
{
"ignore": ["!(package*.json|pnpm-*.yaml|yarn.lock)"],
"execMap": {
"json": "ni && nodemon -w functions -x 'node -r @swc-node/register' $SERVER_PATH/server.ts"
},
"ext": "json,yaml,lock"
}

View File

@@ -1,37 +0,0 @@
import path from 'path'
import express from 'express'
import glob from 'glob'
const PORT = 3000
const main = async () => {
const app = express()
// * Same settings as in Watchtower
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.disable('x-powered-by')
const functionsPath = path.join(process.cwd(), 'functions')
const files = glob.sync('**/*.@(js|ts)', { cwd: functionsPath })
for (const file of files) {
const { default: handler } = await import(path.join(functionsPath, file))
if (handler) {
const route = `/${file}`
.replace(/(\.ts|\.js)$/, '')
.replace(/\/index$/, '/')
app.all(route, handler)
console.log(`Loaded route ${route} from ./functions/${file}`)
} else {
console.warn(`No default export in ./functions/${file}`)
}
}
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`)
})
}
main()

View File

@@ -1,9 +0,0 @@
# * Set the default package manager to use if cannot be guessed from lock files
echo "defaultAgent=$PACKAGE_MANAGER" > ~/.nirc
# * Create a default package.json file if it doesn't exist yet
npm init -y 1> /dev/null
# * Start nodemon that listens to package.json and lock files and run npm/pnpm/yarn install,
# * Then run another nodemon that listens to the functions directory and run the server
nodemon --config $SERVER_PATH/nodemon.json package.json

View File

@@ -3,6 +3,7 @@ services:
hasura:
environment:
hasura_graphql_enable_remote_schema_permissions: false
version: v2.8.0
minio:
environment:
minio_root_password: minioaccesskey123123
@@ -11,6 +12,10 @@ services:
environment:
postgres_password: postgres
postgres_user: postgres
auth:
version: 0.10.0
storage:
version: 0.2.3
auth:
access_control:
email:

View File

@@ -7,9 +7,9 @@ services:
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
version: 0.9.1
version: 0.10.0
storage:
version: 0.2.2
version: 0.2.3
auth:
access_control:
email:

View File

@@ -15,7 +15,7 @@
"verify:fix": "run-p prettier:fix lint:fix"
},
"dependencies": {
"@apollo/client": "^3.6.2",
"@apollo/client": "^3.6.9",
"@mantine/core": "^4.2.2",
"@mantine/hooks": "^4.2.2",
"@mantine/next": "^4.2.2",

View File

@@ -5,9 +5,9 @@ services:
environment:
hasura_graphql_enable_remote_schema_permissions: true
auth:
version: 0.9.1
version: 0.10.0
storage:
version: 0.2.2
version: 0.2.3
auth:
access_control:
email:

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@apollo/client": "^3.5.10",
"@apollo/client": "^3.6.9",
"@headlessui/react": "^1.5.0",
"@heroicons/react": "^1.0.6",
"@nhost/react": "*",
@@ -55,11 +55,11 @@
"@graphql-codegen/typescript": "^2.4.8",
"@graphql-codegen/typescript-operations": "^2.3.5",
"@graphql-codegen/typescript-react-apollo": "^3.2.11",
"@types/express": "^4.17.13",
"@types/jest": "^26.0.24",
"@types/node": "^12.20.48",
"@types/react": "^17.0.44",
"@types/react-dom": "^17.0.15",
"@types/express": "^4.17.13",
"@vitejs/plugin-react": "^1.3.2",
"autoprefixer": "^10.4.4",
"express": "^4.17.3",

View File

@@ -1,4 +1,4 @@
# React-Apollo example
# Nhost React + Apollo example
## See this example live
@@ -13,20 +13,26 @@ git clone https://github.com/nhost/nhost
cd nhost
```
2. Install dependencies
2. Install and build dependencies
```sh
pnpm install
pnpm run build
```
3. Go to the example folder
```sh
cd examples/react-apollo
pnpm install
```
3. Terminal 1: Start Nhost
4. Terminal 1: Start Nhost
```sh
nhost dev
```
4. Terminal 2: Start the React application
5. Terminal 2: Start the React application
```sh
pnpm run dev

View File

@@ -43,36 +43,32 @@ context('Sign in with email+password', () => {
.findByRole('button')
.click()
cy.findByText(/Activate 2-step verification/i)
.get('img')
.then(async (img) => {
// * Activate MFA
const result = await new Decoder().scan(img.prop('src'))
const [, params] = result.data.split('?')
const { secret, algorithm, digits, period } = Object.fromEntries(
new URLSearchParams(params)
)
const code = totp(secret, {
algorithm: algorithm.replace('SHA1', 'SHA-1'),
digits: parseInt(digits),
period: parseInt(period)
})
cy.findByPlaceholderText('Enter activation code').type(code)
cy.findByRole('button', { name: /Activate/i }).click()
cy.contains('MFA has been activated!!!')
cy.signOut()
// * Sign-in with MFA
cy.visit('/sign-in')
cy.findByRole('button', { name: /Continue with email \+ password/i }).click()
cy.findByPlaceholderText('Email Address').type(email)
cy.findByPlaceholderText('Password').type(password)
cy.findByRole('button', { name: /Sign in/i }).click()
cy.contains('Send 2-step verification code')
const newCode = totp(secret, { timestamp: Date.now() })
cy.findByPlaceholderText('One-time password').type(newCode)
cy.findByRole('button', { name: /Send 2-step verification code/i }).click()
cy.contains('You are authenticated')
cy.findAllByAltText(/qrcode/i).then(async (img) => {
// * Activate MFA
const result = await new Decoder().scan(img.prop('src'))
const [, params] = result.data.split('?')
const { secret, algorithm, digits, period } = Object.fromEntries(new URLSearchParams(params))
const code = totp(secret, {
algorithm: algorithm.replace('SHA1', 'SHA-1'),
digits: parseInt(digits),
period: parseInt(period)
})
cy.findByPlaceholderText('Enter activation code').type(code)
cy.findByRole('button', { name: /Activate/i }).click()
cy.contains('MFA has been activated!!!')
cy.signOut()
// * Sign-in with MFA
cy.visit('/sign-in')
cy.findByRole('button', { name: /Continue with email \+ password/i }).click()
cy.findByPlaceholderText('Email Address').type(email)
cy.findByPlaceholderText('Password').type(password)
cy.findByRole('button', { name: /Sign in/i }).click()
cy.contains('Send 2-step verification code')
const newCode = totp(secret, { timestamp: Date.now() })
cy.findByPlaceholderText('One-time password').type(newCode)
cy.findByRole('button', { name: /Send 2-step verification code/i }).click()
cy.contains('You are authenticated')
})
})
})

View File

@@ -1,13 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Nhost with React and Apollo</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

View File

@@ -7,9 +7,9 @@ services:
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
version: 0.9.1
version: 0.10.0
storage:
version: 0.2.2
version: 0.2.3
auth:
access_control:
email:

View File

@@ -0,0 +1,30 @@
table:
name: user_authenticators
schema: auth
configuration:
column_config:
credential_id:
custom_name: credentialId
credential_public_key:
custom_name: credentialPublicKey
user_id:
custom_name: userId
custom_column_names:
credential_id: credentialId
credential_public_key: credentialPublicKey
user_id: userId
custom_name: authUserAuthenticators
custom_root_fields:
delete: deleteAuthUserAuthenticators
delete_by_pk: deleteAuthUserAuthenticator
insert: insertAuthUserAuthenticators
insert_one: insertAuthUserAuthenticator
select: authUserAuthenticators
select_aggregate: authUserAuthenticatorsAggregate
select_by_pk: authUserAuthenticator
update: updateAuthUserAuthenticators
update_by_pk: updateAuthUserAuthenticator
object_relationships:
- name: user
using:
foreign_key_constraint_on: user_id

View File

@@ -39,6 +39,8 @@ configuration:
custom_name: totpSecret
updated_at:
custom_name: updatedAt
webauthn_current_challenge:
custom_name: currentChallenge
custom_column_names:
active_mfa_type: activeMfaType
avatar_url: avatarUrl
@@ -58,6 +60,7 @@ configuration:
ticket_expires_at: ticketExpiresAt
totp_secret: totpSecret
updated_at: updatedAt
webauthn_current_challenge: currentChallenge
custom_name: users
custom_root_fields:
delete: deleteUsers
@@ -74,6 +77,13 @@ object_relationships:
using:
foreign_key_constraint_on: default_role
array_relationships:
- name: authenticators
using:
foreign_key_constraint_on:
column: user_id
table:
name: user_authenticators
schema: auth
- name: refreshTokens
using:
foreign_key_constraint_on:

View File

@@ -2,6 +2,7 @@
- "!include auth_providers.yaml"
- "!include auth_refresh_tokens.yaml"
- "!include auth_roles.yaml"
- "!include auth_user_authenticators.yaml"
- "!include auth_user_providers.yaml"
- "!include auth_user_roles.yaml"
- "!include auth_users.yaml"

View File

@@ -3,7 +3,7 @@
"version": "0.0.1",
"private": true,
"dependencies": {
"@apollo/client": "^3.6.2",
"@apollo/client": "^3.6.9",
"@mantine/core": "^4.2.2",
"@mantine/dropzone": "^4.2.6",
"@mantine/hooks": "^4.2.2",
@@ -16,7 +16,8 @@
"react-dom": "^18.1.0",
"react-icons": "^4.3.1",
"react-router": "^6.3.0",
"react-router-dom": "^6.3.0"
"react-router-dom": "^6.3.0",
"tabler-icons-react": "^1.52.0"
},
"scripts": {
"dev": "vite",
@@ -66,4 +67,4 @@
"ws": "^8.7.0",
"xstate": "^4.32.1"
}
}
}

View File

@@ -0,0 +1,10 @@
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M88.0355 21.4793L53.1776 1.35118C50.0502 -0.450393 46.168 -0.450393 43.0343 1.35118C39.9069 3.1591 37.9657 6.52119 37.9657 10.1307V12.7569L35.6948 11.4438C32.5674 9.64222 28.6851 9.64222 25.5514 11.4438C22.424 13.2517 20.4829 16.6138 20.4829 20.2296V22.8559L18.2119 21.5428C15.0845 19.7412 11.2022 19.7412 8.06851 21.5428C4.94113 23.3507 3 26.7128 3 30.3286V93.3963C3 95.2106 4.05303 96.898 5.68967 97.6846C7.31996 98.4775 9.29916 98.2619 10.7201 97.1391L28.0063 83.5067L54.662 98.8962C55.3979 99.3212 56.2225 99.5306 57.0472 99.5306C57.8719 99.5306 58.6965 99.3149 59.4324 98.8962C60.9041 98.0462 61.8176 96.4666 61.8176 94.7666V56.813C61.8176 50.5836 58.4682 44.7856 53.0761 41.6709L44.3347 36.6214V10.137C44.3347 8.79218 45.0579 7.53616 46.2251 6.86374C47.3923 6.19132 48.8386 6.19132 50.0058 6.86374L84.8638 26.9855C88.2956 28.9647 90.4271 32.663 90.4271 36.6214V83.881C90.4271 85.2258 89.7039 86.4819 88.5367 87.1543L79.3004 92.4892V46.714C79.3004 40.4846 75.951 34.6866 70.559 31.5719L49.0987 19.1829V26.5225L67.3809 37.0782C70.8127 39.0573 72.9442 42.7493 72.9442 46.714V95.236C72.9442 96.9297 73.8577 98.5156 75.3294 99.3656C76.0652 99.7907 76.8899 100 77.7145 100C78.5392 100 79.3639 99.7843 80.0997 99.3656L91.7212 92.6541C94.8485 90.8462 96.7897 87.4841 96.7897 83.8683V36.6087C96.777 30.3984 93.4276 24.594 88.0355 21.4793ZM49.8853 47.1771C53.3172 49.1563 55.4486 52.8483 55.4486 56.813V92.0198L33.373 79.2756L40.4588 73.6932C42.9137 71.7584 44.322 68.8594 44.322 65.732V43.9736L49.8853 47.1771ZM37.9657 40.2943V65.7194C37.9657 66.8866 37.4392 67.9713 36.5258 68.6881L9.35626 90.1104V30.3223C9.35626 28.9774 10.0794 27.7214 11.2466 27.049C12.4139 26.3766 13.8602 26.3766 15.0274 27.049L20.4829 30.1954V75.2664L26.8391 70.255V20.2296C26.8391 18.8848 27.5623 17.6288 28.7295 16.9564C29.8967 16.2839 31.3431 16.2839 32.5103 16.9564L37.9657 20.1028V32.9485L31.6095 29.2756V36.6214L37.9657 40.2943Z" fill="#0052CD"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="93.7897" height="100" fill="white" transform="translate(3)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1,6 +1,7 @@
import { Route, Routes } from 'react-router-dom'
import { BrandGithub } from 'tabler-icons-react'
import { AppShell, Header, MantineProvider } from '@mantine/core'
import { AppShell, Button, Group, Header, Image, MantineProvider, Title } from '@mantine/core'
import { NotificationsProvider } from '@mantine/notifications'
import { AuthGate, PublicGate } from './components/auth-gates'
@@ -17,13 +18,13 @@ import './App.css'
const title = 'Nhost with React and Apollo'
function App() {
const colorScheme = 'light'
return (
<MantineProvider
withGlobalStyles
withNormalizeCSS
theme={{
/** Put your mantine theme override here */
colorScheme: 'light'
colorScheme
}}
>
<NotificationsProvider>
@@ -32,7 +33,24 @@ function App() {
navbar={<NavBar />}
header={
<Header height={60} p="xs">
{title}
<Group position="apart" noWrap>
<Group noWrap>
<Image src="/logo.svg" height={35} fit="contain" width={120} />
<Title order={3} style={{ whiteSpace: 'nowrap' }}>
{title}
</Title>
</Group>
<Button
leftIcon={<BrandGithub />}
variant="outline"
color={colorScheme}
component="a"
href="https://github.com/nhost/nhost/tree/main/examples/react-apollo"
target="_blank"
>
GitHub
</Button>
</Group>
</Header>
}
styles={(theme) => ({

View File

@@ -1 +1,39 @@
# Nhost Vue3 Apollo example
# Nhost Vue 3 + Apollo example
## See this example live
Visit our demo application on [vue-apollo.example.nhost.io](https://vue-apollo.example.nhost.io)
## Get started
1. Clone the repository
```sh
git clone https://github.com/nhost/nhost
cd nhost
```
2. Install and build dependencies
```sh
pnpm install
pnpm build
```
3. Go to the example folder
```sh
cd examples/vue-apollo
```
4. Terminal 1: Start Nhost
```sh
nhost dev
```
5. Terminal 2: Start the Vue application
```sh
pnpm run dev
```

View File

@@ -1,13 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Nhost with Vue and Apollo</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -7,9 +7,9 @@ services:
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
version: 0.9.1
version: 0.10.0
storage:
version: 0.2.2
version: 0.2.3
auth:
access_control:
email:
@@ -18,7 +18,7 @@ auth:
blocked_email_domains: ''
blocked_emails: ''
allowed_redirect_urls: ''
anonymous_users_enabled: false
anonymous_users_enabled: true
client_url: http://localhost:3000
disable_new_users: false
email:

View File

@@ -2,6 +2,7 @@ table:
name: provider_requests
schema: auth
configuration:
column_config: {}
custom_column_names: {}
custom_name: authProviderRequests
custom_root_fields:

View File

@@ -2,6 +2,7 @@ table:
name: providers
schema: auth
configuration:
column_config: {}
custom_column_names: {}
custom_name: authProviders
custom_root_fields:

View File

@@ -2,6 +2,15 @@ table:
name: refresh_tokens
schema: auth
configuration:
column_config:
created_at:
custom_name: createdAt
expires_at:
custom_name: expiresAt
refresh_token:
custom_name: refreshToken
user_id:
custom_name: userId
custom_column_names:
created_at: createdAt
expires_at: expiresAt

View File

@@ -2,6 +2,7 @@ table:
name: roles
schema: auth
configuration:
column_config: {}
custom_column_names: {}
custom_name: authRoles
custom_root_fields:

View File

@@ -0,0 +1,30 @@
table:
name: user_authenticators
schema: auth
configuration:
column_config:
credential_id:
custom_name: credentialId
credential_public_key:
custom_name: credentialPublicKey
user_id:
custom_name: userId
custom_column_names:
credential_id: credentialId
credential_public_key: credentialPublicKey
user_id: userId
custom_name: authUserAuthenticators
custom_root_fields:
delete: deleteAuthUserAuthenticators
delete_by_pk: deleteAuthUserAuthenticator
insert: insertAuthUserAuthenticators
insert_one: insertAuthUserAuthenticator
select: authUserAuthenticators
select_aggregate: authUserAuthenticatorsAggregate
select_by_pk: authUserAuthenticator
update: updateAuthUserAuthenticators
update_by_pk: updateAuthUserAuthenticator
object_relationships:
- name: user
using:
foreign_key_constraint_on: user_id

View File

@@ -2,6 +2,21 @@ table:
name: user_providers
schema: auth
configuration:
column_config:
access_token:
custom_name: accessToken
created_at:
custom_name: createdAt
provider_id:
custom_name: providerId
provider_user_id:
custom_name: providerUserId
refresh_token:
custom_name: refreshToken
updated_at:
custom_name: updatedAt
user_id:
custom_name: userId
custom_column_names:
access_token: accessToken
created_at: createdAt

View File

@@ -2,6 +2,11 @@ table:
name: user_roles
schema: auth
configuration:
column_config:
created_at:
custom_name: createdAt
user_id:
custom_name: userId
custom_column_names:
created_at: createdAt
user_id: userId

View File

@@ -2,6 +2,45 @@ table:
name: users
schema: auth
configuration:
column_config:
active_mfa_type:
custom_name: activeMfaType
avatar_url:
custom_name: avatarUrl
created_at:
custom_name: createdAt
default_role:
custom_name: defaultRole
display_name:
custom_name: displayName
email_verified:
custom_name: emailVerified
is_anonymous:
custom_name: isAnonymous
last_seen:
custom_name: lastSeen
new_email:
custom_name: newEmail
otp_hash:
custom_name: otpHash
otp_hash_expires_at:
custom_name: otpHashExpiresAt
otp_method_last_used:
custom_name: otpMethodLastUsed
password_hash:
custom_name: passwordHash
phone_number:
custom_name: phoneNumber
phone_number_verified:
custom_name: phoneNumberVerified
ticket_expires_at:
custom_name: ticketExpiresAt
totp_secret:
custom_name: totpSecret
updated_at:
custom_name: updatedAt
webauthn_current_challenge:
custom_name: currentChallenge
custom_column_names:
active_mfa_type: activeMfaType
avatar_url: avatarUrl
@@ -21,6 +60,7 @@ configuration:
ticket_expires_at: ticketExpiresAt
totp_secret: totpSecret
updated_at: updatedAt
webauthn_current_challenge: currentChallenge
custom_name: users
custom_root_fields:
delete: deleteUsers
@@ -37,6 +77,13 @@ object_relationships:
using:
foreign_key_constraint_on: default_role
array_relationships:
- name: authenticators
using:
foreign_key_constraint_on:
column: user_id
table:
name: user_authenticators
schema: auth
- name: refreshTokens
using:
foreign_key_constraint_on:

View File

@@ -2,6 +2,23 @@ table:
name: buckets
schema: storage
configuration:
column_config:
cache_control:
custom_name: cacheControl
created_at:
custom_name: createdAt
download_expiration:
custom_name: downloadExpiration
id:
custom_name: id
max_upload_file_size:
custom_name: maxUploadFileSize
min_upload_file_size:
custom_name: minUploadFileSize
presigned_urls_enabled:
custom_name: presignedUrlsEnabled
updated_at:
custom_name: updatedAt
custom_column_names:
cache_control: cacheControl
created_at: createdAt

View File

@@ -2,6 +2,27 @@ table:
name: files
schema: storage
configuration:
column_config:
bucket_id:
custom_name: bucketId
created_at:
custom_name: createdAt
etag:
custom_name: etag
id:
custom_name: id
is_uploaded:
custom_name: isUploaded
mime_type:
custom_name: mimeType
name:
custom_name: name
size:
custom_name: size
updated_at:
custom_name: updatedAt
uploaded_by_user_id:
custom_name: uploadedByUserId
custom_column_names:
bucket_id: bucketId
created_at: createdAt

View File

@@ -2,6 +2,7 @@
- "!include auth_providers.yaml"
- "!include auth_refresh_tokens.yaml"
- "!include auth_roles.yaml"
- "!include auth_user_authenticators.yaml"
- "!include auth_user_providers.yaml"
- "!include auth_user_roles.yaml"
- "!include auth_users.yaml"

View File

@@ -14,16 +14,16 @@
"verify:fix": "run-p prettier:fix lint:fix"
},
"dependencies": {
"@apollo/client": "^3.6.2",
"@apollo/client": "^3.6.9",
"@mdi/font": "5.9.55",
"@nhost/apollo": "*",
"@nhost/vue": "*",
"@vue/apollo-composable": "^4.0.0-alpha.17",
"@vue/apollo-composable": "4.0.0-alpha.18",
"graphql": "15.7.2",
"graphql-tag": "^2.12.6",
"roboto-fontface": "*",
"vue": "^3.2.25",
"vue-router": "^4.0.3",
"vue": "^3.2.37",
"vue-router": "^4.1.2",
"vuetify": "^3.0.0-beta.0",
"webfontloader": "^1.0.0"
},
@@ -31,12 +31,12 @@
"@nhost/core": "*",
"@types/webfontloader": "^1.0.0",
"@vitejs/plugin-vue": "^2.3.1",
"@vuetify/vite-plugin": "^1.0.0-alpha.0",
"@vuetify/vite-plugin": "1.0.0-alpha.11",
"@xstate/inspect": "^0.6.2",
"sass": "1.32.0",
"typescript": "^4.5.4",
"typescript": "^4.7.4",
"vite": "^2.9.0",
"vue-tsc": "^0.29.8"
"vue-tsc": "^0.38.5"
},
"eslintConfig": {
"root": true,

View File

@@ -4,11 +4,13 @@
<template #prepend>
<v-app-bar-nav-icon @click.stop="drawer = !drawer" />
</template>
<v-app-bar-title>Nhost with Vue and Apollo</v-app-bar-title>
<template #append>
<v-btn icon="mdi-github" href="https://github.com/nhost/nhost/tree/main/examples/vue-apollo" target="_blank" />
<v-btn v-if="isAuthenticated" icon="mdi-exit-to-app" @click="signOutHandler" />
</template>
</v-app-bar>
<v-navigation-drawer v-model="drawer" permanent>
<v-navigation-drawer v-model="drawer" :permanent="mdAndUp">
<nav-bar />
</v-navigation-drawer>
<v-main class="my-4">
@@ -17,30 +19,22 @@
</v-app>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
<script lang="ts" setup>
import { useDisplay } from 'vuetify'
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { useAuthenticated, useSignOut } from '@nhost/vue'
import NavBar from './components/NavBar.vue'
export default defineComponent({
components: { NavBar },
setup() {
const router = useRouter()
const isAuthenticated = useAuthenticated()
const { signOut } = useSignOut()
const drawer = ref(true)
const signOutHandler = async () => {
await signOut()
router.replace('/signout')
}
return {
drawer,
isAuthenticated,
signOutHandler
}
}
})
const { mdAndUp } = useDisplay()
const router = useRouter()
const isAuthenticated = useAuthenticated()
const { signOut } = useSignOut()
const drawer = ref()
const signOutHandler = async () => {
await signOut()
router.replace('/signout')
}
</script>

View File

@@ -1,25 +1,45 @@
<template>
<div>
<v-text-field v-model="email" placeholder="Email Address" autofocus />
<v-btn block color="primary" @click="signIn"> Continue with email </v-btn>
<form @submit="submit">
<v-text-field v-model="email" placeholder="Email Address" autofocus />
<v-btn block color="primary" type="submit" :disabled="isLoading" :loading="isLoading"> Continue with email
</v-btn>
</form>
<error-snack-bar :error="error" />
<v-dialog v-model="emailSentDialog">
<v-card>
<v-card-title>
<span class="text-h5">Verification email sent</span>
</v-card-title>
<v-card-text>
A email has been sent to {{ email }}. Please follow the link to sign in to the application.
</v-card-text>
<v-card-actions class="d-flex justify-center">
<v-btn text @click="emailSentDialog = false">
Close
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
<script lang="ts" setup>
import { ref } from 'vue'
import { useSignInEmailPasswordless } from '@nhost/vue'
export default defineComponent({
setup() {
const email = ref('')
const { signInEmailPasswordless, error } = useSignInEmailPasswordless({
redirectTo: '/#/profile'
})
const email = ref('')
const emailSentDialog = ref(false)
const signIn = () => signInEmailPasswordless(email)
return { email, signIn, error }
}
const { signInEmailPasswordless, error, isLoading } = useSignInEmailPasswordless({
redirectTo: '/profile'
})
const submit = async (e: Event) => {
e.preventDefault()
const { isSuccess } = await signInEmailPasswordless(email)
if (isSuccess) {
emailSentDialog.value = true
}
}
</script>

View File

@@ -1,39 +1,27 @@
<template>
<v-snackbar
v-model="snack"
:timeout="2_000"
>
<v-snackbar v-model="snack" :timeout="2_000" top>
{{ error?.message }}
<template #actions>
<v-btn
color="blue"
variant="text"
@click="snack = false"
>
Close
</v-btn>
<v-btn color="blue" variant="text" @click="snack = false"> Close </v-btn>
</template>
</v-snackbar>
</template>
<script lang="ts">
import { defineComponent, PropType, ref, watchEffect } from 'vue'
<script lang="ts" setup>
import { PropType, ref, watchEffect } from 'vue'
import { ErrorPayload } from '@nhost/core'
export default defineComponent({
props: {
error: Object as PropType<ErrorPayload | null>
},
setup(props) {
const snack = ref(false)
watchEffect(() => {
if (props.error) {
snack.value = true
}
})
return { snack }
const props = defineProps({
error: Object as PropType<ErrorPayload | null>
})
const snack = ref(false)
watchEffect(() => {
if (props.error) {
snack.value = true
}
})
</script>

View File

@@ -7,25 +7,17 @@
<v-list-item v-if="authenticated" title="Sign out" prepend-icon="mdi-exit-to-app" @click="signOutHandler" />
</v-list>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
<script lang="ts" setup>
import { useRouter } from 'vue-router'
import { useAuthenticated, useSignOut } from '@nhost/vue'
export default defineComponent({
setup() {
const router = useRouter()
const { signOut } = useSignOut()
const authenticated = useAuthenticated()
const signOutHandler = async () => {
await signOut()
router.push('/')
}
return {
authenticated,
signOutHandler
}
}
})
const router = useRouter()
const { signOut } = useSignOut()
const authenticated = useAuthenticated()
const signOutHandler = async () => {
await signOut()
router.push('/')
}
</script>

View File

@@ -1,48 +1,21 @@
<template>
<v-btn
class="my-1"
block
variant="contained-text"
prepend-icon="mdi-github"
color="white"
style="background-color: #333"
:href="github"
>
<v-btn class="my-1" block variant="contained-text" prepend-icon="mdi-github" color="white"
style="background-color: #333" :href="github">
Continue with GitHub
</v-btn>
<v-btn
class="my-1"
block
variant="contained-text"
prepend-icon="mdi-google"
color="white"
style="background-color: #de5246"
:href="google"
>
<v-btn class="my-1" block variant="contained-text" prepend-icon="mdi-google" color="white"
style="background-color: #de5246" :href="google">
Continue with Google
</v-btn>
<v-btn
class="my-1"
block
variant="contained-text"
prepend-icon="mdi-facebook"
color="white"
style="background-color: #3b5998"
:href="facebook"
>
<v-btn class="my-1" block variant="contained-text" prepend-icon="mdi-facebook" color="white"
style="background-color: #3b5998" :href="facebook">
Continue with Facebook
</v-btn>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
<script lang="ts" setup>
import { useProviderLink } from '@nhost/vue'
export default defineComponent({
setup() {
const { github, google, facebook } = useProviderLink()
return { github, google, facebook }
}
})
const { github, google, facebook } = useProviderLink({ redirectTo: '/' })
</script>

View File

@@ -0,0 +1,22 @@
<template>
<v-dialog v-model="modelValue">
<v-card>
<v-card-title>
<span class="text-h5">Verification email sent</span>
</v-card-title>
<v-card-text>
A email has been sent to {{ email }}. Please follow the link to verify your email address and to
complete your registration.
</v-card-text>
<v-card-actions class="d-flex justify-center">
<v-btn text @click="$emit('update:modelValue', false)">
Close
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script lang="ts" setup>
defineProps(['modelValue', 'email'])
</script>

View File

@@ -1,5 +1,5 @@
import { createApp } from 'vue'
import { createRouter, createWebHashHistory } from 'vue-router'
import { createRouter, createWebHistory } from 'vue-router'
import { createVuetify, ThemeDefinition } from 'vuetify'
import { createApolloClient } from '@nhost/apollo'
@@ -13,6 +13,7 @@ import 'vuetify/styles'
import EmailPasswordless from './components/EmailPasswordlessForm.vue'
import ErrorSnackBar from './components/ErrorSnackBar.vue'
import OauthLinks from './components/OAuthLinks.vue'
import VerificationEmailDialog from './components/VerificationEmailDialog.vue'
import App from './App.vue'
import { routes } from './routes'
@@ -43,7 +44,7 @@ const vuetify = createVuetify({
}
})
const devTools = !!import.meta.env.VITE_DEBUG
const devTools = import.meta.env.VITE_DEBUG === 'true'
if (devTools) {
inspect({
url: 'https://stately.ai/viz?inspect',
@@ -52,7 +53,9 @@ if (devTools) {
}
const nhost = new NhostClient({
backendUrl: import.meta.env.VITE_NHOST_URL
subdomain: import.meta.env.VITE_NHOST_SUBDOMAIN || 'localhost:1337',
region: import.meta.env.VITE_NHOST_REGION,
devTools
})
const apolloClient = createApolloClient({ nhost })
@@ -66,7 +69,7 @@ nhost.auth.onAuthStateChanged((d) => {
})
const router = createRouter({
history: createWebHashHistory(),
history: createWebHistory(),
routes
})
@@ -86,4 +89,5 @@ createApp(App)
.component('ErrorSnackBar', ErrorSnackBar)
.component('EmailPasswordless', EmailPasswordless)
.component('OauthLinks', OauthLinks)
.component('VerificationEmailDialog', VerificationEmailDialog)
.mount('#app')

View File

@@ -1,7 +1,29 @@
<template>
<div className="d-flex align-center flex-column">
<v-card width="400">
<v-card-text> About </v-card-text>
<v-card-title>About this example</v-card-title>
<v-card-text>This application demonstrates the available features of the Nhost stack.
<p class="pt-2">Nhost cloud leverages the
following services in the backend:
<ul class="px-8">
<li>Hasura</li>
<li>Hasura Auth</li>
<li>Hasura Storage</li>
<li>Lambda Functions</li>
</ul>
</p>
<p class="py-2">
This frontend is built with the following technologies:
<ul class="px-8">
<li>Vue 3</li>
<li>Vue-router</li>
<li>Vuetify 3</li>
<li>and of course, the Nhost Vue client</li>
</ul>
</p>
Now let's go to the <router-link to="/">Home page</router-link>.
</v-card-text>
</v-card>
</div>
</template>

View File

@@ -1,19 +1,21 @@
<template>
<div className="d-flex align-center flex-column">
<v-card width="400" tile>
<v-card-text> Apollo </v-card-text>
<v-list density="compact" v-if="result">
<v-list-subheader>Books</v-list-subheader>
<v-list-item v-for="(item, i) in result.books" :key="i" :value="item.id">
<v-list-item-title v-text="item.title"></v-list-item-title>
</v-list-item>
</v-list>
<v-card-title> Apollo </v-card-title>
<v-card-text>
<v-list density="compact" v-if="result">
<v-list-subheader>Books</v-list-subheader>
<v-list-item v-for="(item, i) in result.books" :key="i" :value="item.id">
<v-list-item-title v-text="item.title"></v-list-item-title>
</v-list-item>
</v-list>
</v-card-text>
</v-card>
</div>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
<script lang="ts" setup>
import { computed } from 'vue'
import { gql } from '@apollo/client/core'
import { useAuthenticated } from '@nhost/vue'
@@ -28,20 +30,15 @@ const GET_BOOKS = gql`
}
`
export default defineComponent({
setup() {
const isAuthenticated = useAuthenticated()
// TODO check if the query always runs with the headers
const { result } = useQuery(
GET_BOOKS,
null,
computed(() => ({
pollInterval: 5000,
fetchPolicy: 'cache-and-network',
enabled: isAuthenticated.value
}))
)
return { result }
}
})
const isAuthenticated = useAuthenticated()
// TODO check if the query always runs with the headers
const { result } = useQuery(
GET_BOOKS,
null,
computed(() => ({
pollInterval: 5000,
fetchPolicy: 'cache-and-network',
enabled: isAuthenticated.value
}))
)
</script>

View File

@@ -6,14 +6,8 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
<script lang="ts" setup>
import { useRouter } from 'vue-router'
export default defineComponent({
setup() {
const router = useRouter()
setTimeout(() => router.replace('/'), 2_500)
return {}
}
})
const router = useRouter()
setTimeout(() => router.replace('/'), 2_500)
</script>

View File

@@ -11,13 +11,7 @@
>
Continue with passwordless email
</v-btn>
<v-btn
class="my-1"
block
variant="text"
color="primary"
to="/signin/email-password"
>
<v-btn class="my-1" block variant="text" color="primary" to="/signin/email-password">
Continue with email + password
</v-btn>
</template>

View File

@@ -1,59 +1,37 @@
<template>
<v-text-field
v-model="email"
label="Email"
/>
<v-text-field
v-model="password"
label="Password"
type="password"
/>
<v-btn
block
color="primary"
class="my-1"
@click="signIn"
>
Sign in
</v-btn>
<v-btn
class="my-1"
block
variant="text"
color="primary"
to="/signin"
>
&#8592; Other Login Options
<form @submit="handleSignIn">
<v-text-field v-model="email" label="Email" />
<v-text-field v-model="password" label="Password" type="password" />
<v-btn block color="primary" class="my-1" type="submit" :disabled="isLoading" :loading="isLoading"> Sign in </v-btn>
</form>
<v-btn class="my-1" block variant="text" color="primary" to="/signin">
&#8592; Other Sign-in Options
</v-btn>
<error-snack-bar :error="error" />
<verification-email-dialog v-model="emailVerificationDialog" :email="email" />
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
<script lang="ts" setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { useSignInEmailPassword } from '@nhost/vue'
export default defineComponent({
setup() {
const email = ref('')
const password = ref('')
const email = ref('')
const password = ref('')
const emailVerificationDialog = ref(false)
const router = useRouter()
const { signInEmailPassword, error } = useSignInEmailPassword()
const signIn = async () => {
const { isSuccess } = await signInEmailPassword(email, password)
if (isSuccess) {
router.replace('/')
}
}
const router = useRouter()
const { signInEmailPassword, error, isLoading } = useSignInEmailPassword()
return {
email,
error,
password,
signIn
}
const handleSignIn = async (e: Event) => {
e.preventDefault()
const { isSuccess, needsEmailVerification } = await signInEmailPassword(email, password)
if (isSuccess) {
router.replace('/')
}
})
if (needsEmailVerification) {
emailVerificationDialog.value = true
}
}
</script>

View File

@@ -1,12 +1,6 @@
<template>
<email-passwordless />
<v-btn
class="my-1"
block
variant="text"
color="primary"
to="/signin"
>
&#8592; Other Login Options
<v-btn class="my-1" block variant="text" color="primary" to="/signin">
&#8592; Other Sign-in Options
</v-btn>
</template>

View File

@@ -1,33 +1,32 @@
<script setup lang="ts">
import { useRouter } from 'vue-router'
import { useSignInAnonymous } from '@nhost/vue'
const { signInAnonymous } = useSignInAnonymous()
const router = useRouter()
const handleSignInAnonymous = async (e: Event) => {
e.preventDefault()
const { isSuccess, error } = await signInAnonymous()
if (isSuccess) {
router.push('/profile')
} else {
console.log(error)
}
}
</script>
<template>
<div className="d-flex align-center flex-column">
<v-card width="400">
<v-card-title>Log in to the Application</v-card-title>
<v-card-title>Sign in to the Application</v-card-title>
<v-card-text>
<router-view />
</v-card-text>
</v-card>
<v-divider class="my-4" style="min-width: 90%" />
<div>
Don&lsquo;t have an account? <router-link to="/signup">
Sign up
</router-link> or <a href="#" @click="handleSignInAnonymous">sign in anonymously</a>
Don&lsquo;t have an account? <router-link to="/signup"> Sign up </router-link> or
<a v-if="!isLoading" href="#" @click="handleSignInAnonymous">sign in anonymously</a>
<v-progress-circular v-else indeterminate />
</div>
</div>
<error-snack-bar :error="error" />
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router'
import { useSignInAnonymous } from '@nhost/vue'
const { signInAnonymous, error, isLoading } = useSignInAnonymous()
const router = useRouter()
const handleSignInAnonymous = async (e: Event) => {
e.preventDefault()
const { isSuccess } = await signInAnonymous()
if (isSuccess) {
router.push('/profile')
}
}
</script>

View File

@@ -11,13 +11,7 @@
>
Continue with passwordless email
</v-btn>
<v-btn
class="my-1"
block
variant="text"
color="primary"
to="/signup/email-password"
>
<v-btn class="my-1" block variant="text" color="primary" to="/signup/email-password">
Continue with email + password
</v-btn>
</template>

View File

@@ -1,56 +1,33 @@
<template>
<v-text-field
v-model="email"
label="Email"
/>
<v-text-field
v-model="password"
label="Password"
type="password"
/>
<v-btn
block
color="primary"
class="my-1"
@click="signUp"
>
Sign up
</v-btn>
<v-btn
class="my-1"
block
variant="text"
color="primary"
to="/signup"
>
<form @submit="handleSignUp">
<v-text-field v-model="email" label="Email" />
<v-text-field v-model="password" label="Password" type="password" />
<v-btn block color="primary" class="my-1" type="submit" :disabled="isLoading" :loading="isLoading"> Sign up </v-btn>
</form>
<v-btn class="my-1" block variant="text" color="primary" to="/signup">
&#8592; Other registration Options!
</v-btn>
<error-snack-bar :error="error" />
<verification-email-dialog v-model="emailVerificationDialog" :email="email" />
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
<script lang="ts" setup>
import { ref } from 'vue'
import { useSignUpEmailPassword } from '@nhost/vue'
export default defineComponent({
setup() {
const email = ref('')
const password = ref('')
const { signUpEmailPassword, error } = useSignUpEmailPassword()
const signUp = async () => {
const result = await signUpEmailPassword(email, password)
if (result.error) {
}
}
return {
email,
error,
password,
signUp
}
}
const emailVerificationDialog = ref(false)
const email = ref('')
const password = ref('')
const { signUpEmailPassword, error, isLoading } = useSignUpEmailPassword({
redirectTo: '/'
})
const handleSignUp = async (e: Event) => {
e.preventDefault()
const result = await signUpEmailPassword(email, password)
if (result.needsEmailVerification) {
emailVerificationDialog.value = true
}
}
</script>

View File

@@ -1,13 +1,6 @@
<template>
<email-passwordless />
<v-btn
class="my-1"
block
variant="text"
color="primary"
to="/signup"
>
<v-btn class="my-1" block variant="text" color="primary" to="/signup">
&#8592; Other registration Options
</v-btn>
</template>

View File

@@ -6,14 +6,7 @@
<router-view />
</v-card-text>
</v-card>
<v-divider
class="my-4"
style="min-width: 90%"
/>
<div>
Already have an account? <router-link to="/signin">
Sign in
</router-link>
</div>
<v-divider class="my-4" style="min-width: 90%" />
<div>Already have an account? <router-link to="/signin"> Sign in </router-link></div>
</div>
</template>

View File

@@ -50,5 +50,5 @@ export const routes: RouteRecordRaw[] = [
}
]
},
{ path: '/apollo', component: ApolloPage }
{ path: '/apollo', component: ApolloPage, meta: { auth: true } }
]

View File

@@ -17,7 +17,7 @@
"noEmit": true,
"jsx": "preserve",
"declaration": false,
"declarationMap": false
"declarationMap": false,
},
"include": ["src"]
}

View File

@@ -0,0 +1,3 @@
{
"rewrites": [{ "source": "/(.*)", "destination": "/" }]
}

View File

@@ -1,5 +1,5 @@
import { defineConfig } from 'vite'
import path from 'path'
import vue from '@vitejs/plugin-vue'
import vuetify from '@vuetify/vite-plugin'

View File

@@ -47,6 +47,8 @@ declare global {
const refDefault: typeof import('@vueuse/core')['refDefault']
const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const syncRef: typeof import('@vueuse/core')['syncRef']
const syncRefs: typeof import('@vueuse/core')['syncRefs']
const templateRef: typeof import('@vueuse/core')['templateRef']
@@ -65,6 +67,7 @@ declare global {
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useBase64: typeof import('@vueuse/core')['useBase64']
const useBattery: typeof import('@vueuse/core')['useBattery']
const useBluetooth: typeof import('@vueuse/core')['useBluetooth']
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
@@ -89,6 +92,7 @@ declare global {
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useDropZone: typeof import('@vueuse/core')['useDropZone']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover']
@@ -100,6 +104,7 @@ declare global {
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
const useFavicon: typeof import('@vueuse/core')['useFavicon']
const useFetch: typeof import('@vueuse/core')['useFetch']
const useFileDialog: typeof import('@vueuse/core')['useFileDialog']
const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess']
const useFocus: typeof import('@vueuse/core')['useFocus']
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
@@ -108,6 +113,7 @@ declare global {
const useGamepad: typeof import('@vueuse/core')['useGamepad']
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
const useIdle: typeof import('@vueuse/core')['useIdle']
const useImage: typeof import('@vueuse/core')['useImage']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
const useInterval: typeof import('@vueuse/core')['useInterval']
@@ -129,6 +135,7 @@ declare global {
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
const useNetwork: typeof import('@vueuse/core')['useNetwork']
const useNow: typeof import('@vueuse/core')['useNow']
const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl']
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
const useOnline: typeof import('@vueuse/core')['useOnline']
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
@@ -153,11 +160,13 @@ declare global {
const useShare: typeof import('@vueuse/core')['useShare']
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
const useStepper: typeof import('@vueuse/core')['useStepper']
const useStorage: typeof import('@vueuse/core')['useStorage']
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
const useThrottle: typeof import('@vueuse/core')['useThrottle']
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
@@ -184,12 +193,14 @@ declare global {
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
const watchArray: typeof import('@vueuse/core')['watchArray']
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchPausable: typeof import('@vueuse/core')['watchPausable']
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
}

View File

@@ -10,15 +10,15 @@
"test": "vitest"
},
"dependencies": {
"@apollo/client": "^3.6.2",
"@apollo/client": "^3.6.9",
"@nhost/apollo": "*",
"@nhost/vue": "*",
"@vue/apollo-composable": "^4.0.0-alpha.17",
"@vueuse/core": "^8.4.2",
"@vue/apollo-composable": "4.0.0-alpha.18",
"@vueuse/core": "^8.9.2",
"graphql": "^15.7.2",
"graphql-tag": "^2.12.6",
"vue": "^3.2.33",
"vue-router": "^4.0.15"
"vue": "^3.2.37",
"vue-router": "^4.1.2"
},
"devDependencies": {
"@antfu/eslint-config": "^0.23.0",
@@ -26,7 +26,7 @@
"@types/node": "^17.0.32",
"@unocss/reset": "^0.33.2",
"@vitejs/plugin-vue": "^2.3.2",
"@vue/test-utils": "^2.0.0-rc.21",
"@vue/test-utils": "^2.0.2",
"eslint": "^8.15.0",
"jsdom": "^19.0.0",
"pnpm": "^7.0.1",
@@ -37,6 +37,6 @@
"vite": "^2.9.8",
"vite-plugin-pages": "^0.23.0",
"vitest": "^0.12.4",
"vue-tsc": "^0.34.12"
"vue-tsc": "^0.38.5"
}
}

4
nhost-cloud.yaml Normal file
View File

@@ -0,0 +1,4 @@
# Docker image versions used in the cloud
hasura: v2.8.0
auth: 0.10.0
storage: 0.2.3

View File

@@ -15,7 +15,7 @@
},
"scripts": {
"preinstall": "npx only-allow pnpm",
"prepare": "husky install",
"prepare": "husky install config/.husky",
"build": "pnpm run build:all --filter=!@nhost/docs --filter=!@nhost-examples/*",
"build:docs": "pnpm run build:all --filter=@nhost/docs",
"build:all": "turbo run build --include-dependencies",
@@ -34,7 +34,8 @@
"test": "turbo run test --filter=!@nhost/docs --filter=!@nhost-examples/* --no-deps --include-dependencies",
"e2e": "turbo run e2e --concurrency=1",
"changeset": "changeset",
"docgen": "turbo run build --filter=@nhost/docgen --no-deps && turbo run docgen --filter='@nhost/*' && :"
"docgen": "turbo run build --filter=@nhost/docgen --no-deps && turbo run docgen --filter='@nhost/*' && :",
"sync-versions": "turbo run start --filter=@nhost/sync-versions --no-deps"
},
"workspaces": [
"packages/*",

Some files were not shown because too many files have changed in this diff Show More