Compare commits
129 Commits
@nhost/rea
...
@nhost/rea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1446a8f13b | ||
|
|
ff75998e93 | ||
|
|
9cc044ca9f | ||
|
|
c65e44b8d6 | ||
|
|
9ec73b4c22 | ||
|
|
94b70e0ce9 | ||
|
|
d108dff4f4 | ||
|
|
7a8e771a72 | ||
|
|
f8fb4bbedd | ||
|
|
c6b1c33a8e | ||
|
|
65b36eff13 | ||
|
|
c192cb9503 | ||
|
|
94ff290264 | ||
|
|
78781ebfec | ||
|
|
63d6059981 | ||
|
|
022d49fb25 | ||
|
|
3bd1aa4d53 | ||
|
|
f3cca4997b | ||
|
|
0fd7a487d6 | ||
|
|
1bb032c1e7 | ||
|
|
2c97db68b5 | ||
|
|
714f2872ee | ||
|
|
65fc26a0e8 | ||
|
|
86a56f28c1 | ||
|
|
6e8abe28d6 | ||
|
|
39925ff5ca | ||
|
|
583a77ed0d | ||
|
|
e704831500 | ||
|
|
95948dd5b9 | ||
|
|
247b69c952 | ||
|
|
7d15b76402 | ||
|
|
b1ae65fd72 | ||
|
|
0063fd1840 | ||
|
|
743a7e6507 | ||
|
|
078652861f | ||
|
|
39840cfd95 | ||
|
|
940a36a68f | ||
|
|
77b109b3df | ||
|
|
15907d65e6 | ||
|
|
7d7d16fa71 | ||
|
|
3f39e48cbd | ||
|
|
97ade32869 | ||
|
|
8583af8290 | ||
|
|
a28193a6ba | ||
|
|
9d6c64430a | ||
|
|
519d1bf5cb | ||
|
|
5ffb0320b5 | ||
|
|
6607e73cc2 | ||
|
|
b4bac161a5 | ||
|
|
37d15377c8 | ||
|
|
8ee1df3be4 | ||
|
|
47ffca945e | ||
|
|
d60f5e623c | ||
|
|
6f80643ee0 | ||
|
|
8d5084725d | ||
|
|
693498dd09 | ||
|
|
4d36a966ea | ||
|
|
239a075f1d | ||
|
|
931194812e | ||
|
|
c8f80c58f3 | ||
|
|
7fdb5aee0a | ||
|
|
1710808fef | ||
|
|
696815d4a8 | ||
|
|
5cc9be00b6 | ||
|
|
28dae23a91 | ||
|
|
7819e20cf4 | ||
|
|
6be3758668 | ||
|
|
658c67faf4 | ||
|
|
e7f3a5f6e0 | ||
|
|
7135aee78b | ||
|
|
587eaff734 | ||
|
|
7cf875f4b8 | ||
|
|
657cfb91c5 | ||
|
|
103dd6e98e | ||
|
|
3c8caa680b | ||
|
|
1bcee357fe | ||
|
|
b729aa9290 | ||
|
|
57780ee645 | ||
|
|
aad8d22380 | ||
|
|
85d33c4de0 | ||
|
|
ab3e2dcee9 | ||
|
|
12f4504b61 | ||
|
|
71d7a11c96 | ||
|
|
16a6c5073e | ||
|
|
3fcc86792a | ||
|
|
27909128e4 | ||
|
|
72371c72a1 | ||
|
|
d878414b10 | ||
|
|
9b840f7c4a | ||
|
|
83d3c90f43 | ||
|
|
058956bdcb | ||
|
|
47c57ff665 | ||
|
|
1cb330016b | ||
|
|
497652d1b4 | ||
|
|
20eb7aa381 | ||
|
|
4a3c2f92b1 | ||
|
|
5647e64265 | ||
|
|
c113debf46 | ||
|
|
3f0ae4a58c | ||
|
|
3d5b8183e8 | ||
|
|
789ef8f783 | ||
|
|
94df175ca3 | ||
|
|
c8bcefb0e5 | ||
|
|
fc52f59eb8 | ||
|
|
a80389e5c7 | ||
|
|
923276422b | ||
|
|
7c9192f3a0 | ||
|
|
51d139b7aa | ||
|
|
8fe1bdb6f7 | ||
|
|
5b288bc0d1 | ||
|
|
27cd769c76 | ||
|
|
5bb370869d | ||
|
|
ec68f64db4 | ||
|
|
4cf8f146c9 | ||
|
|
61cf317541 | ||
|
|
a2066c9b41 | ||
|
|
817b152704 | ||
|
|
cc73494c91 | ||
|
|
64ed4083b9 | ||
|
|
77e8c58cc6 | ||
|
|
0cd2eab309 | ||
|
|
7d8c843c74 | ||
|
|
da1c2d6914 | ||
|
|
3a949301f9 | ||
|
|
585eebab49 | ||
|
|
45c3e4686e | ||
|
|
52f2e67952 | ||
|
|
929774aa5b | ||
|
|
e711e338e7 |
28
.github/workflows/changesets.yaml
vendored
28
.github/workflows/changesets.yaml
vendored
@@ -16,29 +16,33 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
- name: Cache pnpm modules
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
with:
|
||||||
path: ~/.pnpm-store
|
fetch-depth: 0
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2.1.0
|
- uses: pnpm/action-setup@v2.1.0
|
||||||
with:
|
with:
|
||||||
version: 6.32.3
|
version: 6.32.3
|
||||||
run_install: true
|
# run_install: true
|
||||||
|
- name: Use Node.js 17
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: '17.8.0'
|
||||||
|
cache: 'pnpm'
|
||||||
|
- name: Pick the right npm version
|
||||||
|
# * See: https://github.com/pnpm/pnpm/issues/4348
|
||||||
|
run: npm install --global npm@8.4
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install
|
||||||
- name: Create PR or Publish release
|
- name: Create PR or Publish release
|
||||||
id: changesets
|
id: changesets
|
||||||
uses: changesets/action@v1
|
uses: changesets/action@v1
|
||||||
with:
|
with:
|
||||||
version: pnpm ci:version
|
version: pnpm run ci:version
|
||||||
commit: 'chore: update versions'
|
commit: 'chore: update versions'
|
||||||
title: 'chore: update versions'
|
title: 'chore: update versions'
|
||||||
publish: pnpm release
|
publish: pnpm run release
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|||||||
15
.github/workflows/contributors.yaml
vendored
Normal file
15
.github/workflows/contributors.yaml
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
name: Add contributors
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
contrib-readme-job:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: A job to automate contrib in readme
|
||||||
|
steps:
|
||||||
|
- name: Contribute List
|
||||||
|
uses: akhilmhdh/contributors-readme-action@v2.3.4
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
201
README.md
201
README.md
@@ -1,8 +1,8 @@
|
|||||||
<div align="center">
|

|
||||||
<img width="237" src="https://raw.githubusercontent.com/nhost/nhost/main/assets/logo.png"/>
|
|
||||||
|
|
||||||
<br />
|
<div align="center">
|
||||||
<br />
|
|
||||||
|
# Nhost
|
||||||
|
|
||||||
<a href="https://docs.nhost.io/get-started">Quickstart</a>
|
<a href="https://docs.nhost.io/get-started">Quickstart</a>
|
||||||
<span> • </span>
|
<span> • </span>
|
||||||
@@ -20,9 +20,9 @@
|
|||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
**Nhost is a serverless backend for web and mobile apps** built with the following things in mind:
|
**Nhost is a open-source GraphQL backend,** built with the following things in mind:
|
||||||
|
|
||||||
- Open Source
|
- Open-Source
|
||||||
- Developer Productivity
|
- Developer Productivity
|
||||||
- SQL
|
- SQL
|
||||||
- GraphQL
|
- GraphQL
|
||||||
@@ -110,7 +110,7 @@ First and foremost: **Star and watch this repository** to stay up-to-date.
|
|||||||
|
|
||||||
Also, follow Nhost on [GitHub Discussions](https://github.com/nhost/nhost/discussions), our [Blog](https://nhost.io/blog), and on [Twitter](https://twitter.com/nhostio). You can chat with the team and other members on [Discord](https://discord.com/invite/9V7Qb2U) and follow our tutorials and other video material at [YouTube](https://www.youtube.com/channel/UCJ7irtvV9Y0EQMxpabb6ntg?view_as=subscriber).
|
Also, follow Nhost on [GitHub Discussions](https://github.com/nhost/nhost/discussions), our [Blog](https://nhost.io/blog), and on [Twitter](https://twitter.com/nhostio). You can chat with the team and other members on [Discord](https://discord.com/invite/9V7Qb2U) and follow our tutorials and other video material at [YouTube](https://www.youtube.com/channel/UCJ7irtvV9Y0EQMxpabb6ntg?view_as=subscriber).
|
||||||
|
|
||||||
## Nhost is Open Source
|
### Nhost is Open Source
|
||||||
|
|
||||||
This repository, and most of our other open source projects, are licensed under the MIT license.
|
This repository, and most of our other open source projects, are licensed under the MIT license.
|
||||||
|
|
||||||
@@ -122,6 +122,189 @@ Here are some ways of contributing to making Nhost better:
|
|||||||
- Join our [Discord](https://discord.com/invite/9V7Qb2U) and connect with other members to share and learn from.
|
- Join our [Discord](https://discord.com/invite/9V7Qb2U) and connect with other members to share and learn from.
|
||||||
- Send a pull request to any of our [open source repositories](https://github.com/nhost) on Github. Check our [contribution guide](https://github.com/nhost/nhost/blob/main/CONTRIBUTING.md) for more details about how to contribute. We're looking forward to your contribution!
|
- Send a pull request to any of our [open source repositories](https://github.com/nhost) on Github. Check our [contribution guide](https://github.com/nhost/nhost/blob/main/CONTRIBUTING.md) for more details about how to contribute. We're looking forward to your contribution!
|
||||||
|
|
||||||
## Security
|
### Contributors
|
||||||
|
|
||||||
If you discover a security vulnerability within Nhost, please e-mail [security@nhost.io](mailto:security@nhost.io). All security vulnerabilities will be promptly addressed.
|
<!-- readme: contributors -start -->
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/plmercereau">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/24897252?v=4" width="100;" alt="plmercereau"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Pilou</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/elitan">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/331818?v=4" width="100;" alt="elitan"/>
|
||||||
|
<br />
|
||||||
|
<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/nunopato">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/1523504?v=4" width="100;" alt="nunopato"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Nuno Pato</b></sub>
|
||||||
|
</a>
|
||||||
|
</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 align="center">
|
||||||
|
<a href="https://github.com/guicurcio">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/20285232?v=4" width="100;" alt="guicurcio"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Guido Curcio</b></sub>
|
||||||
|
</a>
|
||||||
|
</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"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Sebagudelo</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/mrinalwahal">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/9859731?v=4" width="100;" alt="mrinalwahal"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Mrinal Wahal</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"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Grégory D'Angelo</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 align="center">
|
||||||
|
<a href="https://github.com/subhendukundu">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/20059141?v=4" width="100;" alt="subhendukundu"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Subhendu Kundu</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/chrtze">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/3797215?v=4" width="100;" alt="chrtze"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Christopher Möller</b></sub>
|
||||||
|
</a>
|
||||||
|
</td></tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/jerryjappinen">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/1101002?v=4" width="100;" alt="jerryjappinen"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Jerry Jäppinen</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/mustafa-hanif">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/30019262?v=4" width="100;" alt="mustafa-hanif"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Mustafa Hanif</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/Savinvadim1312">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/16936043?v=4" width="100;" alt="Savinvadim1312"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Savin Vadim</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/ahmic">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/13452362?v=4" width="100;" alt="ahmic"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Amir Ahmic</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/akd-io">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/30059155?v=4" width="100;" alt="akd-io"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Anders Kjær Damgaard</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/rustyb">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/53086?v=4" width="100;" alt="rustyb"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Colin Broderick</b></sub>
|
||||||
|
</a>
|
||||||
|
</td></tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/dohomi">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/489221?v=4" width="100;" alt="dohomi"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Dominic Garms</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/alveshelio">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/8176422?v=4" width="100;" alt="alveshelio"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Helio Alves</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/nkhdo">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/26102306?v=4" width="100;" alt="nkhdo"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Hoang Do</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"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Nirmalya Ghosh</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/timpratim">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/32492961?v=4" width="100;" alt="timpratim"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Pratim</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/quentin-decre">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/1137511?v=4" width="100;" alt="quentin-decre"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Quentin Decré</b></sub>
|
||||||
|
</a>
|
||||||
|
</td></tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/komninoschat">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/29049104?v=4" width="100;" alt="komninoschat"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Komninos</b></sub>
|
||||||
|
</a>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
<!-- readme: contributors -end -->
|
||||||
|
|||||||
@@ -2,15 +2,15 @@ import { lightNhostTheme } from '@/data/lightTheme'
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'
|
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'
|
||||||
import js from 'react-syntax-highlighter/dist/cjs/languages/hljs/javascript'
|
import js from 'react-syntax-highlighter/dist/cjs/languages/hljs/javascript'
|
||||||
|
import ts from 'react-syntax-highlighter/dist/cjs/languages/hljs/typescript'
|
||||||
|
|
||||||
import Check from '../icons/Check'
|
import Check from '../icons/Check'
|
||||||
import Copy from '../icons/Copy'
|
import Copy from '../icons/Copy'
|
||||||
|
|
||||||
// @ts-ignore -> add to types
|
SyntaxHighlighter.registerLanguage('language-js', js)
|
||||||
// @ts-ignore -> add to types
|
SyntaxHighlighter.registerLanguage('language-ts', ts)
|
||||||
SyntaxHighlighter.registerLanguage('js', js)
|
|
||||||
// TODO highlight JSX
|
// TODO highlight JSX
|
||||||
SyntaxHighlighter.registerLanguage('jsx', js)
|
SyntaxHighlighter.registerLanguage('language-jsx', js)
|
||||||
|
|
||||||
export interface CodeEditorProps {
|
export interface CodeEditorProps {
|
||||||
code: string
|
code: string
|
||||||
@@ -24,7 +24,7 @@ export interface CodeEditorProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CodeEditor = (props: CodeEditorProps) => {
|
const CodeEditor = (props: CodeEditorProps) => {
|
||||||
const { children, url } = props
|
const { children, className } = props
|
||||||
const [copied, setCopied] = useState(false)
|
const [copied, setCopied] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -53,6 +53,7 @@ const CodeEditor = (props: CodeEditorProps) => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<SyntaxHighlighter
|
<SyntaxHighlighter
|
||||||
|
language={className}
|
||||||
style={lightNhostTheme}
|
style={lightNhostTheme}
|
||||||
wrapLongLines={true}
|
wrapLongLines={true}
|
||||||
wrapLines={true}
|
wrapLines={true}
|
||||||
|
|||||||
@@ -18,9 +18,14 @@ In this guide, we'll keep the example simple. We're not using a frontend framewo
|
|||||||
|
|
||||||
Create a new folder called `nhost-todos`, and initialize a new JavaScript app there:
|
Create a new folder called `nhost-todos`, and initialize a new JavaScript app there:
|
||||||
|
|
||||||
|
Using npm package manager
|
||||||
```sh
|
```sh
|
||||||
npm init -y
|
npm init -y
|
||||||
# or
|
```
|
||||||
|
or
|
||||||
|
|
||||||
|
Using Yarn package manager
|
||||||
|
```sh
|
||||||
yarn init -y
|
yarn init -y
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -28,9 +33,13 @@ yarn init -y
|
|||||||
|
|
||||||
Install Nhost JavaScript SDK:
|
Install Nhost JavaScript SDK:
|
||||||
|
|
||||||
|
Using npm package manager
|
||||||
```sh
|
```sh
|
||||||
npm install @nhost/nhost-js
|
npm install @nhost/nhost-js
|
||||||
# or
|
```
|
||||||
|
or
|
||||||
|
Using Yarn package manager
|
||||||
|
```sh
|
||||||
yarn add @nhost/nhost-js
|
yarn add @nhost/nhost-js
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ title: Environment Variables
|
|||||||
| AUTH_SMS_TWILIO_FROM | | |
|
| AUTH_SMS_TWILIO_FROM | | |
|
||||||
| AUTH_EMAIL_SIGNIN_EMAIL_VERIFIED_REQUIRED | When enabled, any email-based authentication requires emails to be verified by a link sent to this email. | `true` |
|
| AUTH_EMAIL_SIGNIN_EMAIL_VERIFIED_REQUIRED | When enabled, any email-based authentication requires emails to be verified by a link sent to this email. | `true` |
|
||||||
| AUTH_ACCESS_CONTROL_ALLOWED_REDIRECT_URLS | | |
|
| AUTH_ACCESS_CONTROL_ALLOWED_REDIRECT_URLS | | |
|
||||||
| AUTH_MFA_ENABLED | Enables users to use Multi Factor Authentication | `false` |
|
| AUTH_MFA_ENABLED | Enables users to use Multi Factor Authentication. | `false` |
|
||||||
| AUTH_MFA_TOTP_ISSUER | The name of the One Time Password (OTP) issuer. Probably your app's name. | `hasura-auth` |
|
| AUTH_MFA_TOTP_ISSUER | The name of the One Time Password (OTP) issuer. Probably your app's name. | `hasura-auth` |
|
||||||
| AUTH_ACCESS_TOKEN_EXPIRES_IN | | `900`(15 minutes) |
|
| AUTH_ACCESS_TOKEN_EXPIRES_IN | Number of seconds before the access token (JWT) expires. | `900`(15 minutes) |
|
||||||
| AUTH_REFRESH_TOKEN_EXPIRES_IN | | `43200` (12 hours) |
|
| AUTH_REFRESH_TOKEN_EXPIRES_IN | Number of seconds before the refresh token expires. | `2592000` (30 days) |
|
||||||
| AUTH_EMAIL_TEMPLATE_FETCH_URL | | |
|
| AUTH_EMAIL_TEMPLATE_FETCH_URL | | |
|
||||||
| AUTH_JWT_CUSTOM_CLAIMS | | |
|
| AUTH_JWT_CUSTOM_CLAIMS | | |
|
||||||
|
|
||||||
|
|||||||
@@ -8,23 +8,25 @@ title: 'Hooks'
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const { signUpEmailPassword, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
const { signUpEmailPassword, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
||||||
useSignUpEmailPassword(email?: string, password?: string, options?: Options )
|
useSignUpEmailPassword(options?: Options)
|
||||||
```
|
```
|
||||||
|
|
||||||
| Name | Type | Notes |
|
| 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. |
|
| `signUpEmailPassword` | (email?: string, password?: string) => void | Used for a new user to sign up. Returns a promise with the current context |
|
||||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
| `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. |
|
| `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. |
|
| `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. |
|
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||||
| `error` | {status: number, error: string, message: string} \| undefined | Provides details about the error. |
|
| `error` | {status: number, error: string, message: string} \| null | Provides details about the error. |
|
||||||
| `options.locale` | string \| undefined | Locale of the user, in two digits, for instance `en`. |
|
| `user` | User \| null | User information |
|
||||||
| `options.allowedRoles` | string[] \| undefined | Allowed roles of the user. Must be a subset of the default allowed roles defined in Hasura Auth. |
|
| `accessToken` | string \| null | Access token (JWT) |
|
||||||
| `options.defaultRole` | string \| undefined | Default role of the user. Must be part of the default allowed roles defined in Hasura Auth. |
|
| `options.locale` | string \| undefined | Locale of the user, in two digits, for instance `en`. |
|
||||||
| `options.displayName` | string \| undefined | |
|
| `options.allowedRoles` | string[] \| undefined | Allowed roles of the user. Must be a subset of the default allowed roles defined in Hasura Auth. |
|
||||||
| `options.metadata` | Record<string, unknown> \| undefined | Custom additional user information stored in the `metadata` column. Can be any JSON object. |
|
| `options.defaultRole` | string \| undefined | Default role of the user. Must be part of the default allowed roles defined in Hasura Auth. |
|
||||||
| `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'`. |
|
| `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
|
#### Usage
|
||||||
|
|
||||||
@@ -36,7 +38,7 @@ const Component = () => {
|
|||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const { signUpEmailPassword, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
const { signUpEmailPassword, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
||||||
useSignUpEmailPassword(email, password)
|
useSignUpEmailPassword()
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input value={email} onChange={(event) => setEmail(event.target.value)} placeholder="Email" />
|
<input value={email} onChange={(event) => setEmail(event.target.value)} placeholder="Email" />
|
||||||
@@ -45,7 +47,7 @@ const Component = () => {
|
|||||||
onChange={(event) => setPassword(event.target.value)}
|
onChange={(event) => setPassword(event.target.value)}
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
/>
|
/>
|
||||||
<button onClick={signUpEmailPassword}>Register</button>
|
<button onClick={() => signUpEmailPassword(email, password)}>Register</button>
|
||||||
{isSuccess && <div>Your account have beed created! You are now authenticated</div>}
|
{isSuccess && <div>Your account have beed created! You are now authenticated</div>}
|
||||||
{needsEmailVerification && (
|
{needsEmailVerification && (
|
||||||
<div>Please check your mailbox and follow the verification link to verify your email</div>
|
<div>Please check your mailbox and follow the verification link to verify your email</div>
|
||||||
@@ -58,20 +60,31 @@ const Component = () => {
|
|||||||
### Email and Password Sign-In
|
### Email and Password Sign-In
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const { signInEmailPassword, isLoading, needsEmailVerification, needsMfaOtp, sendMfaOtp, isSuccess, isError, error } =
|
const {
|
||||||
useSignInEmailPassword(email?: string, password?: string)
|
signInEmailPassword,
|
||||||
|
isLoading,
|
||||||
|
needsEmailVerification,
|
||||||
|
needsMfaOtp,
|
||||||
|
sendMfaOtp,
|
||||||
|
isSuccess,
|
||||||
|
isError,
|
||||||
|
error,
|
||||||
|
user
|
||||||
|
} = useSignInEmailPassword()
|
||||||
```
|
```
|
||||||
|
|
||||||
| Name | Type | Notes |
|
| 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. |
|
| `signInEmailPassword` | (email?: string, password?: string) | Will try to authenticate. Returns a promise with the current context |
|
||||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
| `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. |
|
| `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. |
|
| `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`. |
|
| `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. |
|
| `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. |
|
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||||
| `error` | {status: number, error: string, message: string} \| undefined | Provides details about the error. |
|
| `error` | {status: number, error: string, message: string} \| null | Provides details about the error. |
|
||||||
|
| `user` | User \| null | User information |
|
||||||
|
| `accessToken` | string \| null | Access token (JWT) |
|
||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
@@ -83,7 +96,7 @@ const Component = () => {
|
|||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const { signInEmailPassword, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
const { signInEmailPassword, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
||||||
useSignInEmailPassword(email, password)
|
useSignInEmailPassword()
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input value={email} onChange={(event) => setEmail(event.target.value)} placeholder="Email" />
|
<input value={email} onChange={(event) => setEmail(event.target.value)} placeholder="Email" />
|
||||||
@@ -92,7 +105,7 @@ const Component = () => {
|
|||||||
onChange={(event) => setPassword(event.target.value)}
|
onChange={(event) => setPassword(event.target.value)}
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
/>
|
/>
|
||||||
<button onClick={signInEmailPassword}>Register</button>
|
<button onClick={() => signInEmailPassword(email, password)}>Register</button>
|
||||||
{isSuccess && <div>Authentication suceeded</div>}
|
{isSuccess && <div>Authentication suceeded</div>}
|
||||||
{needsEmailVerification && (
|
{needsEmailVerification && (
|
||||||
<div>
|
<div>
|
||||||
@@ -139,12 +152,12 @@ const Component = () => {
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const { signInEmailPasswordless, isLoading, isSuccess, isError, error } =
|
const { signInEmailPasswordless, isLoading, isSuccess, isError, error } =
|
||||||
useSignInEmailPasswordless(email?: string, options?: Options)
|
useSignInEmailPasswordless(options?: Options)
|
||||||
```
|
```
|
||||||
|
|
||||||
| Name | Type | Notes |
|
| 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. |
|
| `signInEmailPasswordless` | (email?: string) => void | Sends a magic link to the given email. |
|
||||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
| `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. |
|
| `isSuccess` | boolean | Returns `true` if the magic link email user has successfully send. |
|
||||||
| `isError` | boolean | Returns `true` if an error occurred. |
|
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||||
@@ -165,11 +178,11 @@ import { useSignInEmailPasswordless } from '@nhost/react'
|
|||||||
const Component = () => {
|
const Component = () => {
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const { signInEmailPasswordless, isLoading, isSuccess, isError, error } =
|
const { signInEmailPasswordless, isLoading, isSuccess, isError, error } =
|
||||||
useSignInEmailPasswordless(email)
|
useSignInEmailPasswordless()
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input value={email} onChange={(event) => setEmail(event.target.value)} placeholder="Email" />
|
<input value={email} onChange={(event) => setEmail(event.target.value)} placeholder="Email" />
|
||||||
<button onClick={signInEmailPasswordless}>Authenticate</button>
|
<button onClick={() => signInEmailPasswordless(email)}>Authenticate</button>
|
||||||
{isSuccess && (
|
{isSuccess && (
|
||||||
<div>
|
<div>
|
||||||
An email has been sent to {email}. Please check your mailbox and click on the
|
An email has been sent to {email}. Please check your mailbox and click on the
|
||||||
@@ -253,17 +266,17 @@ const accessToken = useAccessToken()
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const { changeEmail, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
const { changeEmail, isLoading, isSuccess, needsEmailVerification, isError, error } =
|
||||||
useChangeEmail(email?: string, options?: { redirectTo?: string })
|
useChangeEmail(options?: { redirectTo?: string })
|
||||||
```
|
```
|
||||||
|
|
||||||
| Name | Type | Notes |
|
| 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. |
|
| `changeEmail` | (email?: string) => void | Requests the email change. Returns a promise with the current context |
|
||||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
| `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. |
|
| `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. |
|
| `isError` | boolean | Returns `true` if an error occurred. |
|
||||||
| `error` | {status: number, error: string, message: string} \| undefined | Provides details about the error. |
|
| `error` | {status: number, error: string, message: string} \| null | 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'`. |
|
| `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
|
#### Usage
|
||||||
|
|
||||||
@@ -273,12 +286,11 @@ import { useChangeEmail } from '@nhost/react'
|
|||||||
|
|
||||||
const Component = () => {
|
const Component = () => {
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const { changeEmail, isLoading, needsEmailVerification, isError, error } =
|
const { changeEmail, isLoading, needsEmailVerification, isError, error } = useChangeEmail()
|
||||||
useChangeEmail(password)
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input value={email} onChange={(event) => setEmail(event.target.value)} />
|
<input value={email} onChange={(event) => setEmail(event.target.value)} />
|
||||||
<button onClick={changeEmail}>Change password</button>
|
<button onClick={() => changeEmail(email)}>Change email</button>
|
||||||
{needsEmailVerification && (
|
{needsEmailVerification && (
|
||||||
<div>
|
<div>
|
||||||
Please check your mailbox and follow the verification link to confirm your new email
|
Please check your mailbox and follow the verification link to confirm your new email
|
||||||
@@ -292,16 +304,16 @@ const Component = () => {
|
|||||||
### Change password
|
### Change password
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const { changePassword, isLoading, isSuccess, isError, error } = useChangePassword(password?: string)
|
const { changePassword, isLoading, isSuccess, isError, error } = useChangePassword()
|
||||||
```
|
```
|
||||||
|
|
||||||
| Name | Type | Notes |
|
| Name | Type | Notes |
|
||||||
| ---------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||||
| `changePassword` | (password?: string) => void | Requests the password change. The arguement password will take precedence over the the possible state value used when creating the hook. |
|
| `changePassword` | (password?: string) | Requests the password change. Returns a promise with the current context |
|
||||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
||||||
| `isSuccess` | boolean | Returns `true` if the password has beed successfully changed. |
|
| `isSuccess` | boolean | Returns `true` if the password has beed successfully changed. |
|
||||||
| `isError` | boolean | Returns `true` 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. |
|
| `error` | {status: number, error: string, message: string} \| null | Provides details about the error. |
|
||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
@@ -311,11 +323,11 @@ import { useChangePassword } from '@nhost/react'
|
|||||||
|
|
||||||
const Component = () => {
|
const Component = () => {
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const { changePassword, isLoading, isSuccess, isError, error } = useChangePassword(password)
|
const { changePassword, isLoading, isSuccess, isError, error } = useChangePassword()
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input value={password} onChange={(event) => setPassword(event.target.value)} />
|
<input value={password} onChange={(event) => setPassword(event.target.value)} />
|
||||||
<button onClick={changePassword}>Change password</button>
|
<button onClick={() => changePassword(password)}>Change password</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -326,17 +338,17 @@ const Component = () => {
|
|||||||
If a user loses their password, we can resend them an email to authenticate so that they can change it to a new one:
|
If a user loses their password, we can resend them an email to authenticate so that they can change it to a new one:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const { resetPassword, isLoading, isSent, isError, error } = useResetPassword(email?: string, options?: { redirectTo?: string })
|
const { resetPassword, isLoading, isSent, isError, error } = useResetPassword(options?: { redirectTo?: string })
|
||||||
```
|
```
|
||||||
|
|
||||||
| Name | Type | Notes |
|
| Name | Type | Notes |
|
||||||
| --------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| --------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `resetPassword` | (email?: string) => void | Sends an email with a temporary connection link. The arguement email will take precedence over the the possible state value used when creating the hook. |
|
| `resetPassword` | (email?: string) | Sends an email with a temporary connection link. Returns a promise with the current context |
|
||||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
||||||
| `isSent` | boolean | Returns `true` when the email has been successfully sent. |
|
| `isSent` | boolean | Returns `true` when the email has been successfully sent. |
|
||||||
| `isError` | boolean | Returns `true` 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. |
|
| `error` | {status: number, error: string, message: string} \| null | 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'`. |
|
| `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
|
#### Usage
|
||||||
|
|
||||||
@@ -345,12 +357,12 @@ import { useState } from 'react'
|
|||||||
import { useResetPassword } from '@nhost/react'
|
import { useResetPassword } from '@nhost/react'
|
||||||
|
|
||||||
const Component = () => {
|
const Component = () => {
|
||||||
const [email, setEamil] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const { resetPassword, isLoading, isSent, isError, error } = useResetPassword(email?: string)
|
const { resetPassword, isLoading, isSent, isError, error } = useResetPassword()
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input value={email} onChange={(event) => setEmail(event.target.value)} />
|
<input value={email} onChange={(event) => setEmail(event.target.value)} />
|
||||||
<button onClick={resetPassword}>Send reset link</button>
|
<button onClick={() => resetPassword(email)}>Send reset link</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -360,17 +372,17 @@ const Component = () => {
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const { sendEmail, isLoading, isSent, isError, error } =
|
const { sendEmail, isLoading, isSent, isError, error } =
|
||||||
useSendVerificationEmail(email?: string, options?: { redirectTo?: string })
|
useSendVerificationEmail(options?: { redirectTo?: string })
|
||||||
```
|
```
|
||||||
|
|
||||||
| Name | Type | Notes |
|
| Name | Type | Notes |
|
||||||
| ------------ | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------ | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `sendEmail` | (email?: string) => void | Resend the verification email. |
|
| `sendEmail` | (email?: string) | Resend the verification email. Returns a promise with the current context |
|
||||||
| `isLoading` | boolean | Returns `true` when the action is executing, `false` when it finished its execution. |
|
| `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 |
|
| `isSent` | boolean | Returns `true` if the verification email has been sent |
|
||||||
| `isError` | boolean | Returns `true` 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. |
|
| `error` | {status: number, error: string, message: string} \| null | 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'`. |
|
| `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
|
#### Usage
|
||||||
|
|
||||||
@@ -380,11 +392,11 @@ import { useSendVerificationEmail } from '@nhost/react'
|
|||||||
|
|
||||||
const Component = () => {
|
const Component = () => {
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const { sendEmail, isLoading, isSent, isError, error } = useSendVerificationEmail(email)
|
const { sendEmail, isLoading, isSent, isError, error } = useSendVerificationEmail()
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input value={email} onChange={(event) => setEmail(event.target.value)} />
|
<input value={email} onChange={(event) => setEmail(event.target.value)} />
|
||||||
<button onClick={sendEmail}>Send email verification</button>
|
<button onClick={() => sendEmail(email)}>Send email verification</button>
|
||||||
{isSent && (
|
{isSent && (
|
||||||
<div>Please check your mailbox and follow the verification link to confirm your email</div>
|
<div>Please check your mailbox and follow the verification link to confirm your email</div>
|
||||||
)}
|
)}
|
||||||
@@ -397,10 +409,41 @@ const Component = () => {
|
|||||||
|
|
||||||
## User data
|
## User data
|
||||||
|
|
||||||
<!-- TODO ellaborate -->
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const userData = useUserData()
|
const { id, email, displayName, avatarUrl, isAnonymous, locale, defaultRole, roles, metadata, createdAt } = useUserData()
|
||||||
|
```
|
||||||
|
|
||||||
|
| Name | Type | Default | Notes |
|
||||||
|
| ------------- | ------------- | ---------------- | ------------------------------------------------------ |
|
||||||
|
| `id` | string | | User's unique identifier (uuid) |
|
||||||
|
| `email` | string | | User's email address |
|
||||||
|
| `displayName` | string | `""` | User's display name |
|
||||||
|
| `avatarUrl` | string | `""` | The URL to the user's profile picture |
|
||||||
|
| `isAnonymous` | boolean | `false` | Whether or not the user is anonymous |
|
||||||
|
| `locale` | string | `"en"` | A two-characters locale |
|
||||||
|
| `defaultRole` | string | `"user"` | The default role of the user |
|
||||||
|
| `roles` | string[] | `["me", "user"]` | The roles assigned to the user |
|
||||||
|
| `metadata` | JSON object | `null` | Additional attributes used for user information |
|
||||||
|
| `createdAt` | string | | The date-time when the user has been created |
|
||||||
|
|
||||||
|
Example of an authenticated user:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"avatarUrl": "https://s.gravatar.com/avatar/3020737ed9d932c6665111a5550454d2?r=g&default=blank",
|
||||||
|
"createdAt": "2022-04-11T16:33:14.780439+00:00",
|
||||||
|
"defaultRole": "user",
|
||||||
|
"displayName": "Grégory D'Angelo",
|
||||||
|
"email": "greg@nhost.io",
|
||||||
|
"id": "05e054c7-a722-42e7-90a6-3f77a2f118c8",
|
||||||
|
"isAnonymous": false,
|
||||||
|
"locale": "en",
|
||||||
|
"metadata": {
|
||||||
|
"lastName": "D'Angelo",
|
||||||
|
"firstName": "Grégory"
|
||||||
|
},
|
||||||
|
"roles": ["user", "me"]
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Avatar
|
### Avatar
|
||||||
@@ -433,7 +476,7 @@ const Avatar = () => {
|
|||||||
### Display name
|
### Display name
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { displayName } from '@nhost/react'
|
import { useDisplayName } from '@nhost/react'
|
||||||
|
|
||||||
const Avatar = () => {
|
const Avatar = () => {
|
||||||
const displayName = useDisplayName()
|
const displayName = useDisplayName()
|
||||||
|
|||||||
@@ -64,5 +64,5 @@ const nhost = new NhostClient({
|
|||||||
| `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. |
|
| `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. |
|
| `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) => 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 | |
|
| `clientStorageSetter` | (key: string, value: string \| null | use localStorage | |
|
||||||
| `refreshIntervalTime` | | |
|
| `refreshIntervalTime` | | |
|
||||||
|
|||||||
@@ -4,40 +4,67 @@ title: 'Protecting routes'
|
|||||||
|
|
||||||
## React Router
|
## React Router
|
||||||
|
|
||||||
You can protect routes by creating an `AuthGate` component when using `@nhost/react` with [React Router](https://reactrouter.com/web/guides/quick-start).
|
> This example uses the latest version of [React Router (v6)](https://reactrouter.com/docs/en/v6).
|
||||||
|
|
||||||
|
You can protect routes by creating a wrapper component, `ProtectedRoute`, to implement the authentication logic using `@nhost/react`.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { Redirect } from 'react-router-dom'
|
// src/components/ProtectedRoute.js
|
||||||
import { useAuthenticationStatus } from '@nhost/react'
|
|
||||||
|
|
||||||
export function AuthGate(children) {
|
import { useAuthenticationStatus } from '@nhost/react';
|
||||||
const { isLoading, isAuthenticated } = useAuthenticationStatus()
|
import { Navigate, Outlet, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
const ProtectedRoute = () => {
|
||||||
|
const { isAuthenticated, isLoading } = useAuthenticationStatus();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <div>Loading...</div>
|
return <div>Loading...</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
return <Redirect to="/login" />
|
return <Navigate to="/login" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return children
|
return <Outlet />;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default ProtectedRoute;
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, in your React Router, wrap the `AuthGate` component around the routes you want to protect:
|
So, if the user is not authenticated, we redirect him to the `/login` route using the [`Navigate`](https://reactrouter.com/docs/en/v6/api#navigate) component from React Router. Otherwise, we render the [`Outlet`](https://reactrouter.com/docs/en/v6/api#outlet) component, also provided by React Router, to render the `ProtectedRoute` child route elements.
|
||||||
|
|
||||||
|
Then, in your `App.js` file, you can use a [layout route](https://reactrouter.com/docs/en/v6/getting-started/concepts#layout-route) to wrap the `ProtectedRoute` component around the routes you want to protect:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
<Router>
|
// src/App.js
|
||||||
<Switch>
|
|
||||||
<Route path="/login">
|
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||||||
<Login />
|
import { NhostReactProvider } from '@nhost/react';
|
||||||
</Route>
|
|
||||||
<Route path="/" exact>
|
import ProtectedRoute from './components/ProtectedRoute';
|
||||||
<AuthGate> // <--- Use AuthGate component like this
|
|
||||||
<div>My protected dashboard</div>
|
import Home from './pages/Home';
|
||||||
</AuthGate>
|
import Login from './pages/Login';
|
||||||
</Route>
|
import Dashboard from './pages/Dashboard';
|
||||||
</Switch>
|
import Profile from './pages/Profile';
|
||||||
</Router>
|
|
||||||
|
import { nhost } from './lib/nhost';
|
||||||
|
|
||||||
|
export function App() {
|
||||||
|
return (
|
||||||
|
<NhostReactProvider nhost={nhost}>
|
||||||
|
<BrowserRouter>
|
||||||
|
<Routes>
|
||||||
|
<Route path="/" element={<Home />} />
|
||||||
|
<Route path="/login" element={<Login />} />
|
||||||
|
<Route path="/dashboard" element={<ProtectedRoute />}>
|
||||||
|
<Route index element={<Dashboard />} />
|
||||||
|
<Route path="profile" element={<Profile />} />
|
||||||
|
</Route>
|
||||||
|
</Routes>
|
||||||
|
</BrowserRouter>
|
||||||
|
</NhostReactProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
"name": "nhost-documentation",
|
"name": "nhost-documentation",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next",
|
"dev": "next",
|
||||||
"build:next": "next build",
|
"build:next": "next build",
|
||||||
@@ -38,6 +37,7 @@
|
|||||||
"swagger-ui-react": "^4.5.2"
|
"swagger-ui-react": "^4.5.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/node": "^17.0.21",
|
||||||
"@types/react": "^17.0.37",
|
"@types/react": "^17.0.37",
|
||||||
"autoprefixer": "^10.4.0",
|
"autoprefixer": "^10.4.0",
|
||||||
"next-sitemap": "^1.6.203",
|
"next-sitemap": "^1.6.203",
|
||||||
|
|||||||
@@ -668,6 +668,23 @@
|
|||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"example": { "firstName": "John", "lastName": "Smith" },
|
"example": { "firstName": "John", "lastName": "Smith" },
|
||||||
"default": {}
|
"default": {}
|
||||||
|
},
|
||||||
|
"activeMfaType": {
|
||||||
|
"anyOf": [
|
||||||
|
{ "type": "string", "enum": [""] },
|
||||||
|
{ "type": "string", "enum": ["totp"] }
|
||||||
|
],
|
||||||
|
"description": "Multi-factor authentication type. A null value deactivates MFA",
|
||||||
|
"example": "totp"
|
||||||
|
},
|
||||||
|
"emailVerified": { "type": "boolean", "default": false },
|
||||||
|
"phoneNumber": { "type": "string" },
|
||||||
|
"phoneNumberVerified": { "type": "boolean", "default": false },
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "oneOf": [{ "enum": ["me"] }, { "enum": ["user"] }] },
|
||||||
|
"example": ["me", "user"],
|
||||||
|
"default": ["me", "user"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -678,7 +695,12 @@
|
|||||||
"email",
|
"email",
|
||||||
"isAnonymous",
|
"isAnonymous",
|
||||||
"defaultRole",
|
"defaultRole",
|
||||||
"metadata"
|
"metadata",
|
||||||
|
"activeMfaType",
|
||||||
|
"emailVerified",
|
||||||
|
"phoneNumber",
|
||||||
|
"phoneNumberVerified",
|
||||||
|
"roles"
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,46 +1,57 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
|
||||||
<url><loc>https://docs.nhost.io</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/reference</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started/authentication</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started/authentication</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started/cli-workflow</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started/cli-workflow</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started/quick-start</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started/quick-start</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started/upgrade</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started/upgrade</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/authentication</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/authentication</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/database</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/database</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/nhost</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/nhost</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/serverless-functions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/serverless-functions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/storage</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/storage</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/cli</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/reference/cli</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/nextjs</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/reference/hasura-auth</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/react</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/reference/nextjs</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.648Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/sdk</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/reference/react</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/supporting-libraries</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/reference/sdk</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started/cli-workflow/install-cli</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started/cli-workflow/install-cli</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started/cli-workflow/local-changes</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started/cli-workflow/local-changes</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started/cli-workflow/metadata-and-serverless-functions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started/cli-workflow/metadata-and-serverless-functions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started/cli-workflow/workflow-setup</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started/cli-workflow/workflow-setup</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started/quick-start/javascript-client</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started/quick-start/javascript-client</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started/quick-start/permissions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started/quick-start/permissions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/get-started/quick-start/schema</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/get-started/quick-start/schema</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/authentication/sign-in-methods</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/authentication/email-templates</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/authentication/social-login</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/authentication/sign-in-methods</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/authentication/user-management</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/authentication/sign-in-with-facebook</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/database/graphql</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/authentication/sign-in-with-github</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/database/permissions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/authentication/sign-in-with-google</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/nhost/environment-variables</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/authentication/sign-in-with-linkedin</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/nhost/github-integration</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/authentication/sign-in-with-spotify</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/nhost/local-development</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/authentication/social-sign-in</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/platform/serverless-functions/event-triggers</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/authentication/user-management</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/nextjs/server-side</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/database/graphql</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/react/apollo</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/database/permissions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/react/hooks</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/nhost/environment-variables</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/sdk/authentication</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/nhost/github-integration</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/sdk/functions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/nhost/local-development</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/sdk/graphql</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/platform/serverless-functions/event-triggers</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/sdk/storage</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/reference/hasura-auth/api-reference</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/supporting-libraries/react-apollo</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/reference/hasura-auth/configuration</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
<url><loc>https://docs.nhost.io/reference/supporting-libraries/react-auth</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-02-21T10:17:26.089Z</lastmod></url>
|
<url><loc>https://docs.nhost.io/reference/hasura-auth/environment-variables</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
|
<url><loc>https://docs.nhost.io/reference/hasura-auth/installation</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
|
<url><loc>https://docs.nhost.io/reference/hasura-auth/schema</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
|
<url><loc>https://docs.nhost.io/reference/nextjs/configuration</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
|
<url><loc>https://docs.nhost.io/reference/nextjs/protecting-routes</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
|
<url><loc>https://docs.nhost.io/reference/react/apollo</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
|
<url><loc>https://docs.nhost.io/reference/react/hooks</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
|
<url><loc>https://docs.nhost.io/reference/react/protecting-routes</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
|
<url><loc>https://docs.nhost.io/reference/sdk/authentication</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
|
<url><loc>https://docs.nhost.io/reference/sdk/functions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
|
<url><loc>https://docs.nhost.io/reference/sdk/graphql</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
|
<url><loc>https://docs.nhost.io/reference/sdk/storage</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2022-04-08T13:10:11.649Z</lastmod></url>
|
||||||
</urlset>
|
</urlset>
|
||||||
@@ -10,9 +10,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.5.10",
|
"@apollo/client": "^3.5.10",
|
||||||
"@nhost/nextjs": "^1.0.0",
|
"@nhost/nextjs": "^1.0.10",
|
||||||
"@nhost/react": "^0.3.0",
|
"@nhost/react": "^0.5.0",
|
||||||
"@nhost/react-apollo": "^4.0.0",
|
"@nhost/react-apollo": "^4.0.10",
|
||||||
"graphql": "^16.3.0",
|
"graphql": "^16.3.0",
|
||||||
"next": "12.1.0",
|
"next": "12.1.0",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ const Home: NextPage = () => {
|
|||||||
const [newPassword, setNewPassword] = useState('')
|
const [newPassword, setNewPassword] = useState('')
|
||||||
const accessToken = useAccessToken()
|
const accessToken = useAccessToken()
|
||||||
const { signOut } = useSignOut()
|
const { signOut } = useSignOut()
|
||||||
const { signUpEmailPassword, ...signUpResult } = useSignUpEmailPassword(email, password)
|
const { signUpEmailPassword, ...signUpResult } = useSignUpEmailPassword()
|
||||||
const { signInEmailPassword } = useSignInEmailPassword(email, password)
|
const { signInEmailPassword } = useSignInEmailPassword()
|
||||||
const { signInEmailPasswordless } = useSignInEmailPasswordless(email)
|
const { signInEmailPasswordless } = useSignInEmailPasswordless()
|
||||||
const { changeEmail, ...changeEmailResult } = useChangeEmail(newEmail)
|
const { changeEmail, ...changeEmailResult } = useChangeEmail()
|
||||||
const { changePassword, ...changePasswordResult } = useChangePassword(newPassword)
|
const { changePassword, ...changePasswordResult } = useChangePassword()
|
||||||
const { loading, data, error } = useAuthQuery(BOOKS_QUERY)
|
const { loading, data, error } = useAuthQuery(BOOKS_QUERY)
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -37,20 +37,24 @@ const Home: NextPage = () => {
|
|||||||
<>
|
<>
|
||||||
<button onClick={signOut}>Logout</button>
|
<button onClick={signOut}>Logout</button>
|
||||||
<input value={newEmail} onChange={(e) => setNewEmail(e.target.value)} />
|
<input value={newEmail} onChange={(e) => setNewEmail(e.target.value)} />
|
||||||
<button onClick={changeEmail}>Change email</button>
|
<button onClick={() => changeEmail(email)}>Change email</button>
|
||||||
<div>{JSON.stringify(changeEmailResult)}</div>
|
<div>{JSON.stringify(changeEmailResult)}</div>
|
||||||
<button onClick={changePassword}>Change password</button>
|
<button onClick={() => changePassword(password)}>Change password</button>
|
||||||
<input value={newPassword} onChange={(e) => setNewPassword(e.target.value)} />
|
<input value={newPassword} onChange={(e) => setNewPassword(e.target.value)} />
|
||||||
<div>{JSON.stringify(changePasswordResult)}</div>
|
<div>{JSON.stringify(changePasswordResult)}</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<input value={email} onChange={(e) => setEmail(e.target.value)} />
|
<input value={email} onChange={(e) => setEmail(e.target.value)} />
|
||||||
<button onClick={signInEmailPasswordless}>Passwordless signin</button>
|
<button onClick={() => signInEmailPasswordless(email)}>Passwordless signin</button>
|
||||||
<div>{JSON.stringify(signUpResult)}</div>
|
<div>{JSON.stringify(signUpResult)}</div>
|
||||||
<input value={password} onChange={(e) => setPassword(e.target.value)} type="password" />
|
<input value={password} onChange={(e) => setPassword(e.target.value)} type="password" />
|
||||||
<button onClick={signUpEmailPassword}>Email + password sign-up</button>
|
<button onClick={() => signUpEmailPassword(email, password)}>
|
||||||
<button onClick={signInEmailPassword}>Email + password sign-in</button>
|
Email + password sign-up
|
||||||
|
</button>
|
||||||
|
<button onClick={() => signInEmailPassword(email, password)}>
|
||||||
|
Email + password sign-in
|
||||||
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -136,71 +136,71 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.0.tgz#d27e7e76c87a460a4da99c5bfdb1618dcd6cd064"
|
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.0.tgz#d27e7e76c87a460a4da99c5bfdb1618dcd6cd064"
|
||||||
integrity sha512-aBvcbMwuanDH4EMrL2TthNJy+4nP59Bimn8egqv6GHMVj0a44cU6Au4PjOhLNqEh9l+IpRGBqMTzec94UdC5xg==
|
integrity sha512-aBvcbMwuanDH4EMrL2TthNJy+4nP59Bimn8egqv6GHMVj0a44cU6Au4PjOhLNqEh9l+IpRGBqMTzec94UdC5xg==
|
||||||
|
|
||||||
"@nhost/apollo@0.3.0":
|
"@nhost/apollo@^0.3.7":
|
||||||
version "0.3.0"
|
version "0.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/apollo/-/apollo-0.3.0.tgz#89a66e97aa6af4de6045bf0c780e8b9590c06d9b"
|
resolved "https://registry.yarnpkg.com/@nhost/apollo/-/apollo-0.3.7.tgz#761d3d60519df60caaa7220909ab11bd2c629e3a"
|
||||||
integrity sha512-97DSycgPEnQQtzAWPB36yENAuQFDEl8c7qLB9xOzSnplImv5NGces40XMAkTDEWam0eD//PtXP9zi+TYNeMNjw==
|
integrity sha512-NH1WCC5D6K/Ft8/EXYIgeAhOBq5Gt1OtX9U9RzV2IqmVRGigDw+YlXr8P5GRPAzBeZUVWrM1wvBt+oBk8zw/7g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nhost/core" "0.3.0"
|
"@nhost/core" "^0.3.8"
|
||||||
graphql "16"
|
graphql "16"
|
||||||
subscriptions-transport-ws "^0.11.0"
|
subscriptions-transport-ws "^0.11.0"
|
||||||
|
|
||||||
"@nhost/core@0.3.0":
|
"@nhost/core@^0.3.8":
|
||||||
version "0.3.0"
|
version "0.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/core/-/core-0.3.0.tgz#fa630afef50840cd7b8415e17894c7765cda273f"
|
resolved "https://registry.yarnpkg.com/@nhost/core/-/core-0.3.8.tgz#0269ab5daa36b1bdd2b2864c174809a86d4d2a7a"
|
||||||
integrity sha512-wEdq+BLOHH7bOhBvF5gql9vtWuEtlLWvw65AtpstfX8pAUY8ce2yqamV6Z8kxr/RSYXZA+aLsKwig50qSZa99w==
|
integrity sha512-6mOv23H16n0YN0voXdXSGS18rUELe1YI2+HXMRlaeksCib4BvSf28lsideEOjFnyfHA3Y4wAX1SMxnyaEj1qaQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
axios "^0.25.0"
|
axios "^0.25.0"
|
||||||
broadcast-channel "^4.10.0"
|
broadcast-channel "^4.10.0"
|
||||||
js-cookie "^3.0.1"
|
js-cookie "^3.0.1"
|
||||||
xstate "^4.30.5"
|
xstate "^4.30.5"
|
||||||
|
|
||||||
"@nhost/hasura-auth-js@1.0.0":
|
"@nhost/hasura-auth-js@^1.0.9":
|
||||||
version "1.0.0"
|
version "1.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/hasura-auth-js/-/hasura-auth-js-1.0.0.tgz#0f3c267614ca328c944797f33a1921c8103dd3e5"
|
resolved "https://registry.yarnpkg.com/@nhost/hasura-auth-js/-/hasura-auth-js-1.0.9.tgz#7e5cfe7a59b18778352dd6d2bef368c765ce9886"
|
||||||
integrity sha512-hENPB1aMdekYxfDejthPAdoj9JarqaVkBKNRa+jun247Un1X6eFGDPo52Y2tZfP44pJEUK4EqTqkWH3DwT4uXg==
|
integrity sha512-d0UDfakzUO9N0/4RRy9NptoOLgpcRmr2F5XxVVzqLYX67+XzZoqT+LMhOF8spKP4+JqFlKFgqbNulmuRRc5FfA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nhost/core" "0.3.0"
|
"@nhost/core" "^0.3.8"
|
||||||
|
|
||||||
"@nhost/hasura-storage-js@0.2.0":
|
"@nhost/hasura-storage-js@^0.2.0":
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/hasura-storage-js/-/hasura-storage-js-0.2.0.tgz#e8c127d883d231313cd262553732da3b0dccb858"
|
resolved "https://registry.yarnpkg.com/@nhost/hasura-storage-js/-/hasura-storage-js-0.2.0.tgz#e8c127d883d231313cd262553732da3b0dccb858"
|
||||||
integrity sha512-JumgUhnScU6Bv8SBmN2F4sY+LbrD3i25Ppr30Zjbv4MvbUguBclx9zzAwqub/P2n/azc7bjjRvYl2n2/jjKRXw==
|
integrity sha512-JumgUhnScU6Bv8SBmN2F4sY+LbrD3i25Ppr30Zjbv4MvbUguBclx9zzAwqub/P2n/azc7bjjRvYl2n2/jjKRXw==
|
||||||
dependencies:
|
dependencies:
|
||||||
axios "^0.21.1"
|
axios "^0.21.1"
|
||||||
|
|
||||||
"@nhost/nextjs@^1.0.0":
|
"@nhost/nextjs@^1.0.10":
|
||||||
version "1.0.0"
|
version "1.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/nextjs/-/nextjs-1.0.0.tgz#2e91cce4352ec7c521099c8f9fccd5fef94ec902"
|
resolved "https://registry.yarnpkg.com/@nhost/nextjs/-/nextjs-1.0.10.tgz#ac78e1b32b6a89e6379179108c49d71cf23aeed8"
|
||||||
integrity sha512-yrRXd3796wcLjabeqIbBgZ/IdD40xpC9LhBA9LoXHqHfNaqZ4ujtcMnSc7IZWJv45P5rDO3T8kKKk+Sm6vTAvQ==
|
integrity sha512-BTNe4KHhWLbRKd8XfppYncLIohXZ0C+oCTZApVwwgVexqdQ5dxhObw0nQin2K7TlP2Mis+Ldzjjn3SO/hcb3xw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nhost/nhost-js" "1.0.0"
|
"@nhost/nhost-js" "^1.0.9"
|
||||||
cookies "^0.8.0"
|
cookies "^0.8.0"
|
||||||
|
|
||||||
"@nhost/nhost-js@1.0.0":
|
"@nhost/nhost-js@^1.0.9":
|
||||||
version "1.0.0"
|
version "1.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/nhost-js/-/nhost-js-1.0.0.tgz#d57aa66c889922926b9bde6278d35000729f884c"
|
resolved "https://registry.yarnpkg.com/@nhost/nhost-js/-/nhost-js-1.0.9.tgz#a1b0bc0c35e15ade2867da4d211b1f81f3bc5e28"
|
||||||
integrity sha512-ve5+TqYGcQbRwDqxVDMCJKZQlj5BFCsTzqEhIAUnLP6Gu8YlNVeUQL3Bbc19j71OkHDNhw8TAJbE2zcFUBT2Fw==
|
integrity sha512-/SZLk3Be560scVAbUswcRSE4RMwf6M7xanbNLqGUuI/sr1Ir253WPhaD2YWXZChP1v2LBzONhdJNI2g7u1NzoA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nhost/hasura-auth-js" "1.0.0"
|
"@nhost/hasura-auth-js" "^1.0.9"
|
||||||
"@nhost/hasura-storage-js" "0.2.0"
|
"@nhost/hasura-storage-js" "^0.2.0"
|
||||||
axios "^0.23.0"
|
axios "^0.23.0"
|
||||||
jwt-decode "^3.1.2"
|
jwt-decode "^3.1.2"
|
||||||
query-string "^7.0.1"
|
query-string "^7.0.1"
|
||||||
|
|
||||||
"@nhost/react-apollo@^4.0.0":
|
"@nhost/react-apollo@^4.0.10":
|
||||||
version "4.0.0"
|
version "4.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/react-apollo/-/react-apollo-4.0.0.tgz#08be35946eadbb746f27435c3fc72cd092a97b61"
|
resolved "https://registry.yarnpkg.com/@nhost/react-apollo/-/react-apollo-4.0.10.tgz#d28819019f35aff7fb69a3b485489ab0492643e1"
|
||||||
integrity sha512-ZmFgBgHFJE2Z2ZBYx3U4Gry9TprUOb4NXw/K5lSKv11zPeEaclfpqn+aeQbtCj02oCnzRe+MJLsJenpcuhQRuw==
|
integrity sha512-MTIBk9aQVCIfVR17eEKM6ssELadpDhIAh2ERjaZY8+i9KMgVyjEt0s4842nl1Bwq7OFIXf5GRykr3RtTjuT/Ug==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nhost/apollo" "0.3.0"
|
"@nhost/apollo" "^0.3.7"
|
||||||
|
|
||||||
"@nhost/react@^0.3.0":
|
"@nhost/react@^0.5.0":
|
||||||
version "0.3.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/react/-/react-0.3.0.tgz#5401922dce91bb66db5d575de1869df00fabbb8e"
|
resolved "https://registry.yarnpkg.com/@nhost/react/-/react-0.5.0.tgz#5276ae7e13691f32ceaa0e6ca2460ef2605820f6"
|
||||||
integrity sha512-jxyt4dYfphgv3bf6jvV7qDKnV5qUArFvdTYExKlBA9tsBQYta0heawMsJk0rEarEZGUw1iioiUYFKdZyl2Qi5Q==
|
integrity sha512-d89I3Q1Y6+9QJ6jP9yU9xrEJv8dCvTwll7tctd7emqZyPWGgInLpmZ9OA+/xrannowck5MsgaBdz0zxQ9bjJBA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nhost/nhost-js" "1.0.0"
|
"@nhost/nhost-js" "^1.0.9"
|
||||||
"@xstate/react" "^2.0.1"
|
"@xstate/react" "^2.0.1"
|
||||||
immer "^9.0.12"
|
immer "^9.0.12"
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Nhost React+Apollo demo</title>
|
<title>Vite App</title>
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
<body>
|
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
</body>
|
</body>
|
||||||
|
</html>
|
||||||
</html>
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ table:
|
|||||||
name: provider_requests
|
name: provider_requests
|
||||||
schema: auth
|
schema: auth
|
||||||
configuration:
|
configuration:
|
||||||
custom_column_names:
|
|
||||||
redirect_url: redirectUrl
|
|
||||||
custom_name: authProviderRequests
|
custom_name: authProviderRequests
|
||||||
custom_root_fields:
|
custom_root_fields:
|
||||||
delete: deleteAuthProviderRequests
|
delete: deleteAuthProviderRequests
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost-examples/react-apollo",
|
"name": "@nhost-examples/react-apollo",
|
||||||
"version": "0.2.0",
|
"version": "0.0.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.5.10",
|
"@apollo/client": "^3.5.10",
|
||||||
"@nhost/react": "^0.3.0",
|
"@nhost/react": "^0.5.0",
|
||||||
"@nhost/react-apollo": "^4.0.0",
|
"@nhost/react-apollo": "^4.0.10",
|
||||||
"@rsuite/icons": "^1.0.2",
|
"@rsuite/icons": "^1.0.2",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
|
"less": "^4.1.2",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-icons": "^4.3.1",
|
"react-icons": "^4.3.1",
|
||||||
"react-json-view": "^1.21.3",
|
"react-json-view": "^1.21.3",
|
||||||
"react-router-dom": "^6.2.1",
|
"react-router": "^6.3.0",
|
||||||
"rsuite": "^5.6.2"
|
"react-router-dom": "^6.3.0",
|
||||||
|
"rsuite": "^5.7.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -38,14 +40,10 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^17.0.39",
|
"@types/react": "^17.0.43",
|
||||||
"@types/react-dom": "^17.0.11",
|
"@types/react-dom": "^17.0.14",
|
||||||
"@vitejs/plugin-react": "^1.2.0",
|
"@vitejs/plugin-react": "^1.3.0",
|
||||||
"@xstate/inspect": "^0.6.2",
|
"typescript": "^4.6.3",
|
||||||
"graphql": "15.7.2",
|
"vite": "^2.9.1"
|
||||||
"less": "^4.1.2",
|
|
||||||
"typescript": "^4.5.5",
|
|
||||||
"vite": "^2.8.5",
|
|
||||||
"ws": "^8.5.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import React from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Panel } from 'rsuite'
|
import { Panel } from 'rsuite'
|
||||||
|
|
||||||
@@ -19,11 +20,11 @@ export const AboutPage: React.FC = () => (
|
|||||||
<li>React</li>
|
<li>React</li>
|
||||||
<li>React-router</li>
|
<li>React-router</li>
|
||||||
<li>RSuite</li>
|
<li>RSuite</li>
|
||||||
<li>...and of course, the Nhost React client</li>
|
<li>and of course, the Nhost React client</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Noew let's go to the <Link to="/">index page</Link>
|
Noew let's go to the <Link to="/">index page</Link>
|
||||||
</div>
|
</div>
|
||||||
</Panel>
|
</Panel>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
import './App.css'
|
/* eslint-disable react/react-in-jsx-scope */
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
import { Link, Route, Routes, useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
import { Container, Content, Header, Nav, Navbar } from 'rsuite'
|
||||||
|
|
||||||
import { useAuthenticated, useSignOut } from '@nhost/react'
|
import { useAuthenticated, useSignOut } from '@nhost/react'
|
||||||
import ExitIcon from '@rsuite/icons/Exit'
|
import ExitIcon from '@rsuite/icons/Exit'
|
||||||
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, PublicGate } from './components/auth-gates'
|
import { AuthGate, PublicGate } from './components/auth-gates'
|
||||||
|
import { AboutPage } from './About'
|
||||||
|
import { ApolloPage } from './apollo'
|
||||||
import Home from './Home'
|
import Home from './Home'
|
||||||
import { ProfilePage } from './profile'
|
import { ProfilePage } from './profile'
|
||||||
import { ApolloPage } from './apollo'
|
import { SignInPage } from './sign-in'
|
||||||
import { SignUpPage } from './sign-up'
|
import { SignUpPage } from './sign-up'
|
||||||
import { AboutPage } from './About'
|
|
||||||
|
import './App.css'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const isAuthenticated = useAuthenticated()
|
const isAuthenticated = useAuthenticated()
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import React from 'react'
|
||||||
import { Panel } from 'rsuite'
|
import { Panel } from 'rsuite'
|
||||||
|
|
||||||
const HomePage: React.FC = () => {
|
const HomePage: React.FC = () => {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { gql } from '@apollo/client'
|
import React from 'react'
|
||||||
import { Panel, Table } from 'rsuite'
|
import { Panel, Table } from 'rsuite'
|
||||||
|
|
||||||
|
import { gql } from '@apollo/client'
|
||||||
import { useAuthQuery } from '@nhost/react-apollo'
|
import { useAuthQuery } from '@nhost/react-apollo'
|
||||||
|
|
||||||
const GET_BOOKS = gql`
|
const GET_BOOKS = gql`
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import React from 'react'
|
||||||
import { Navigate, useLocation } from 'react-router-dom'
|
import { Navigate, useLocation } from 'react-router-dom'
|
||||||
|
|
||||||
import { useAuthenticationStatus } from '@nhost/react'
|
import { useAuthenticationStatus } from '@nhost/react'
|
||||||
|
|
||||||
export const AuthGate: React.FC = ({ children }) => {
|
export const AuthGate: React.FC = ({ children }) => {
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { Button, Input, Message } from 'rsuite'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import { Button, Input, Message } from 'rsuite'
|
||||||
|
|
||||||
import { useSignInEmailPasswordless } from '@nhost/react'
|
import { useSignInEmailPasswordless } from '@nhost/react'
|
||||||
import React, { useState, useEffect } from 'react'
|
|
||||||
|
|
||||||
export const EmailPasswordlessForm: React.FC = () => {
|
export const EmailPasswordlessForm: React.FC = () => {
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { signInEmailPasswordless, isError, isSuccess, error } = useSignInEmailPasswordless(email, {
|
const { signInEmailPasswordless, isError, isSuccess, error } = useSignInEmailPasswordless({
|
||||||
redirectTo: '/profile'
|
redirectTo: '/profile'
|
||||||
})
|
})
|
||||||
const [showError, setShowError] = useState(true)
|
const [showError, setShowError] = useState(true)
|
||||||
@@ -42,7 +43,7 @@ export const EmailPasswordlessForm: React.FC = () => {
|
|||||||
style={{ marginTop: '0.5em' }}
|
style={{ marginTop: '0.5em' }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowError(true)
|
setShowError(true)
|
||||||
signInEmailPasswordless()
|
signInEmailPasswordless(email)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Continue with email
|
Continue with email
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
/* eslint-disable react/react-in-jsx-scope */
|
||||||
|
import { FaFacebook, FaGithub, FaGoogle } from 'react-icons/fa'
|
||||||
import { IconButton } from 'rsuite'
|
import { IconButton } from 'rsuite'
|
||||||
import { FaGithub, FaGoogle, FaFacebook } from 'react-icons/fa'
|
|
||||||
import { Icon } from '@rsuite/icons'
|
|
||||||
import { useProviderLink } from '@nhost/react'
|
import { useProviderLink } from '@nhost/react'
|
||||||
|
import { Icon } from '@rsuite/icons'
|
||||||
|
|
||||||
export const OAuthLinks: React.FC = () => {
|
export const OAuthLinks: React.FC = () => {
|
||||||
// TODO show how to use options
|
// TODO show how to use options
|
||||||
|
|||||||
14
examples/react-apollo/src/env.d.ts
vendored
14
examples/react-apollo/src/env.d.ts
vendored
@@ -1,10 +1,10 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
interface ImportMetaEnv {
|
interface ImportMetaEnv {
|
||||||
readonly VITE_NHOST_URL: string
|
readonly VITE_NHOST_URL: string
|
||||||
// more env variables...
|
// more env variables...
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImportMeta {
|
interface ImportMeta {
|
||||||
readonly env: ImportMetaEnv
|
readonly env: ImportMetaEnv
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import App from './App'
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
|
|
||||||
import { NhostClient, NhostReactProvider } from '@nhost/react'
|
import { NhostClient, NhostReactProvider } from '@nhost/react'
|
||||||
|
import { NhostApolloProvider } from '@nhost/react-apollo'
|
||||||
|
|
||||||
import 'rsuite/styles/index.less' // or 'rsuite/dist/rsuite.min.css'
|
import 'rsuite/styles/index.less' // or 'rsuite/dist/rsuite.min.css'
|
||||||
|
|
||||||
import { BrowserRouter } from 'react-router-dom'
|
import App from './App'
|
||||||
import { NhostApolloProvider } from '@nhost/react-apollo'
|
|
||||||
|
|
||||||
const nhost = new NhostClient({
|
const nhost = new NhostClient({
|
||||||
backendUrl: import.meta.env.VITE_NHOST_URL || 'http://localhost:1337'
|
backendUrl: import.meta.env.VITE_NHOST_URL || 'http://localhost:1337'
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import { useChangeEmail, useEmail } from '@nhost/react'
|
/* eslint-disable react/react-in-jsx-scope */
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { Button, FlexboxGrid, Input, Message, Panel, toaster, Notification } from 'rsuite'
|
import { Button, FlexboxGrid, Input, Message, Notification, Panel, toaster } from 'rsuite'
|
||||||
|
|
||||||
|
import { useChangeEmail, useEmail } from '@nhost/react'
|
||||||
|
|
||||||
export const ChangeEmail: React.FC = () => {
|
export const ChangeEmail: React.FC = () => {
|
||||||
const [newEmail, setNewEmail] = useState('')
|
const [newEmail, setNewEmail] = useState('')
|
||||||
const email = useEmail()
|
const email = useEmail()
|
||||||
const { changeEmail, error, needsEmailVerification } = useChangeEmail(newEmail, {
|
const { changeEmail, error, needsEmailVerification } = useChangeEmail({
|
||||||
redirectTo: '/profile'
|
redirectTo: '/profile'
|
||||||
})
|
})
|
||||||
const [errorMessage, setErrorMessage] = useState('')
|
const [errorMessage, setErrorMessage] = useState('')
|
||||||
@@ -45,7 +47,7 @@ export const ChangeEmail: React.FC = () => {
|
|||||||
<Input value={newEmail} onChange={setNewEmail} placeholder="New email" />
|
<Input value={newEmail} onChange={setNewEmail} placeholder="New email" />
|
||||||
</FlexboxGrid.Item>
|
</FlexboxGrid.Item>
|
||||||
<FlexboxGrid.Item colspan={12}>
|
<FlexboxGrid.Item colspan={12}>
|
||||||
<Button onClick={changeEmail} block appearance="primary">
|
<Button onClick={() => changeEmail(email)} block appearance="primary">
|
||||||
Change
|
Change
|
||||||
</Button>
|
</Button>
|
||||||
</FlexboxGrid.Item>
|
</FlexboxGrid.Item>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { useChangePassword } from '@nhost/react'
|
import React from 'react'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { Button, FlexboxGrid, Input, Message, Panel, toaster, Notification } from 'rsuite'
|
import { Button, FlexboxGrid, Input, Message, Notification, Panel, toaster } from 'rsuite'
|
||||||
|
|
||||||
|
import { useChangePassword } from '@nhost/react'
|
||||||
|
|
||||||
export const ChangePassword: React.FC = () => {
|
export const ChangePassword: React.FC = () => {
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const { changePassword, isSuccess, error } = useChangePassword(password)
|
const { changePassword, isSuccess, error } = useChangePassword()
|
||||||
const [errorMessage, setErrorMessage] = useState('')
|
const [errorMessage, setErrorMessage] = useState('')
|
||||||
|
|
||||||
// * See https://github.com/rsuite/rsuite/issues/2336
|
// * See https://github.com/rsuite/rsuite/issues/2336
|
||||||
@@ -44,7 +46,7 @@ export const ChangePassword: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</FlexboxGrid.Item>
|
</FlexboxGrid.Item>
|
||||||
<FlexboxGrid.Item colspan={12}>
|
<FlexboxGrid.Item colspan={12}>
|
||||||
<Button onClick={changePassword} block appearance="primary">
|
<Button onClick={() => changePassword(password)} block appearance="primary">
|
||||||
Change
|
Change
|
||||||
</Button>
|
</Button>
|
||||||
</FlexboxGrid.Item>
|
</FlexboxGrid.Item>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import decode from 'jwt-decode'
|
import decode from 'jwt-decode'
|
||||||
|
import React from 'react'
|
||||||
import ReactJson from 'react-json-view'
|
import ReactJson from 'react-json-view'
|
||||||
import { Button, Col, Panel, Row } from 'rsuite'
|
import { Button, Col, Panel, Row } from 'rsuite'
|
||||||
|
|
||||||
import { useAccessToken, useNhostClient, useUserData } from '@nhost/react'
|
import { useAccessToken, useNhostClient, useUserData } from '@nhost/react'
|
||||||
|
|
||||||
import { ChangeEmail } from './change-email'
|
import { ChangeEmail } from './change-email'
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { useConfigMfa } from '@nhost/react'
|
import React from 'react'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { Button, Input, Panel } from 'rsuite'
|
import { Button, Input, Panel } from 'rsuite'
|
||||||
|
|
||||||
|
import { useConfigMfa } from '@nhost/react'
|
||||||
|
|
||||||
export const Mfa: React.FC = () => {
|
export const Mfa: React.FC = () => {
|
||||||
const [code, setCode] = useState('')
|
const [code, setCode] = useState('')
|
||||||
const { generateQrCode, activateMfa, isActivated, isGenerated, qrCodeDataUrl } =
|
const { generateQrCode, activateMfa, isActivated, isGenerated, qrCodeDataUrl } = useConfigMfa()
|
||||||
useConfigMfa(code)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Panel header="Activate 2-step verification" bordered>
|
<Panel header="Activate 2-step verification" bordered>
|
||||||
@@ -18,7 +19,7 @@ export const Mfa: React.FC = () => {
|
|||||||
<div>
|
<div>
|
||||||
<img alt="qrcode" src={qrCodeDataUrl} />
|
<img alt="qrcode" src={qrCodeDataUrl} />
|
||||||
<Input value={code} onChange={setCode} placeholder="Enter activation code" />
|
<Input value={code} onChange={setCode} placeholder="Enter activation code" />
|
||||||
<Button block appearance="primary" onClick={activateMfa}>
|
<Button block appearance="primary" onClick={() => activateMfa(code)}>
|
||||||
Activate
|
Activate
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { Button, Divider, Input, Message } from 'rsuite'
|
|
||||||
import { useSignInEmailPassword } from '@nhost/react'
|
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
|
import { Button, Divider, Input, Message } from 'rsuite'
|
||||||
|
|
||||||
|
import { useSignInEmailPassword } from '@nhost/react'
|
||||||
|
|
||||||
const Footer: React.FC = () => (
|
const Footer: React.FC = () => (
|
||||||
<div>
|
<div>
|
||||||
@@ -80,7 +81,14 @@ export const EmailPassword: React.FC = () => {
|
|||||||
</Message>
|
</Message>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Button appearance="primary" onClick={signInEmailPassword} block>
|
<Button
|
||||||
|
appearance="primary"
|
||||||
|
onClick={async () => {
|
||||||
|
const result = await signInEmailPassword(email, password)
|
||||||
|
console.log(result)
|
||||||
|
}}
|
||||||
|
block
|
||||||
|
>
|
||||||
Sign in
|
Sign in
|
||||||
</Button>
|
</Button>
|
||||||
<Button as={NavLink} block to="/sign-in/forgot-password">
|
<Button as={NavLink} block to="/sign-in/forgot-password">
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Button } from 'rsuite'
|
|
||||||
import { NavLink } from 'react-router-dom'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
|
import { Button } from 'rsuite'
|
||||||
|
|
||||||
import { EmailPasswordlessForm } from '../components/email-passwordless-form'
|
import { EmailPasswordlessForm } from '../components/email-passwordless-form'
|
||||||
export const EmailPasswordless: React.FC = () => {
|
export const EmailPasswordless: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { Button, Divider, Input, Message, Notification, toaster } from 'rsuite'
|
|
||||||
import { useResetPassword } from '@nhost/react'
|
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
|
import { Button, Divider, Input, Message, Notification, toaster } from 'rsuite'
|
||||||
|
|
||||||
|
import { useResetPassword } from '@nhost/react'
|
||||||
|
|
||||||
export const ForgotPassword: React.FC = () => {
|
export const ForgotPassword: React.FC = () => {
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const { resetPassword, isSent, error } = useResetPassword(email, { redirectTo: '/profile' })
|
const { resetPassword, isSent, error } = useResetPassword({ redirectTo: '/profile' })
|
||||||
|
|
||||||
const [errorMessage, setErrorMessage] = useState('')
|
const [errorMessage, setErrorMessage] = useState('')
|
||||||
// * Set error message from the authentication hook errors
|
// * Set error message from the authentication hook errors
|
||||||
@@ -16,16 +17,12 @@ export const ForgotPassword: React.FC = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setErrorMessage('')
|
setErrorMessage('')
|
||||||
}, [email])
|
}, [email])
|
||||||
// * See https://github.com/rsuite/rsuite/issues/2336
|
|
||||||
useEffect(() => {
|
|
||||||
toaster.push(<div />)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSent) {
|
if (isSent) {
|
||||||
toaster.push(
|
toaster.push(
|
||||||
<Notification type="info" header="Info" closable>
|
<Notification type="info" header="Info" closable>
|
||||||
An email has been sent with a passwordless authentication link, so you'll be able to
|
An email has been sent with a passwordless authentication link, so you will be able to
|
||||||
authenticate and change your password.
|
authenticate and change your password.
|
||||||
</Notification>
|
</Notification>
|
||||||
)
|
)
|
||||||
@@ -48,7 +45,7 @@ export const ForgotPassword: React.FC = () => {
|
|||||||
</Message>
|
</Message>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Button appearance="primary" onClick={resetPassword} block>
|
<Button appearance="primary" onClick={() => resetPassword(email)} block>
|
||||||
Reset your password
|
Reset your password
|
||||||
</Button>
|
</Button>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
/* eslint-disable jsx-a11y/anchor-is-valid */
|
import React from 'react'
|
||||||
|
import { FaLock } from 'react-icons/fa'
|
||||||
import { Link, NavLink, Route, Routes } from 'react-router-dom'
|
import { Link, NavLink, Route, Routes } from 'react-router-dom'
|
||||||
import { Button, Divider, FlexboxGrid, IconButton, Panel } from 'rsuite'
|
import { Button, Divider, FlexboxGrid, IconButton, Panel } from 'rsuite'
|
||||||
|
|
||||||
import { Icon } from '@rsuite/icons'
|
import { Icon } from '@rsuite/icons'
|
||||||
import { FaLock } from 'react-icons/fa'
|
|
||||||
|
|
||||||
import { OAuthLinks } from '../components'
|
import { OAuthLinks } from '../components'
|
||||||
import { VerificationEmailSent } from '../verification-email-sent'
|
import { VerificationEmailSent } from '../verification-email-sent'
|
||||||
|
|
||||||
import { EmailPassword } from './email-password'
|
import { EmailPassword } from './email-password'
|
||||||
import { ForgotPassword } from './forgot-password'
|
|
||||||
import { EmailPasswordless } from './email-passwordless'
|
import { EmailPasswordless } from './email-passwordless'
|
||||||
|
import { ForgotPassword } from './forgot-password'
|
||||||
// import { useSignInAnonymous } from '@nhost/react'
|
// import { useSignInAnonymous } from '@nhost/react'
|
||||||
|
|
||||||
const Index: React.FC = () => (
|
const Index: React.FC = () => (
|
||||||
@@ -48,7 +50,7 @@ export const SignInPage: React.FC = () => {
|
|||||||
</FlexboxGrid.Item>
|
</FlexboxGrid.Item>
|
||||||
</FlexboxGrid>
|
</FlexboxGrid>
|
||||||
<Divider />
|
<Divider />
|
||||||
Don't have an account? <Link to="/sign-up">Sign up</Link>
|
Don‘t have an account? <Link to="/sign-up">Sign up</Link>
|
||||||
{/* or{' '}
|
{/* or{' '}
|
||||||
<a href="#" onClick={signIn}>
|
<a href="#" onClick={signIn}>
|
||||||
enter the app anonymously
|
enter the app anonymously
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { Button, Input, Message } from 'rsuite'
|
/* eslint-disable react/react-in-jsx-scope */
|
||||||
import { useSignUpEmailPassword } from '@nhost/react'
|
|
||||||
import { useEffect, useMemo, useState } from 'react'
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
import { NavLink, useNavigate } from 'react-router-dom'
|
import { NavLink, useNavigate } from 'react-router-dom'
|
||||||
|
import { Button, Input, Message } from 'rsuite'
|
||||||
|
|
||||||
|
import { useSignUpEmailPassword } from '@nhost/react'
|
||||||
|
|
||||||
export const EmailPassword: React.FC = () => {
|
export const EmailPassword: React.FC = () => {
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
@@ -14,11 +16,8 @@ export const EmailPassword: React.FC = () => {
|
|||||||
)
|
)
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [confirmPassword, setConfirmPassword] = useState('')
|
const [confirmPassword, setConfirmPassword] = useState('')
|
||||||
const { signUpEmailPassword, error, needsEmailVerification, isSuccess } = useSignUpEmailPassword(
|
const { signUpEmailPassword, error, needsEmailVerification, isSuccess } =
|
||||||
email,
|
useSignUpEmailPassword(options)
|
||||||
password,
|
|
||||||
options
|
|
||||||
)
|
|
||||||
const [errorMessage, setErrorMessage] = useState('')
|
const [errorMessage, setErrorMessage] = useState('')
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (needsEmailVerification) navigate('/sign-up/verification-email-sent')
|
if (needsEmailVerification) navigate('/sign-up/verification-email-sent')
|
||||||
@@ -89,9 +88,10 @@ export const EmailPassword: React.FC = () => {
|
|||||||
|
|
||||||
<Button
|
<Button
|
||||||
appearance="primary"
|
appearance="primary"
|
||||||
onClick={() => {
|
onClick={async () => {
|
||||||
setErrorMessage('')
|
setErrorMessage('')
|
||||||
signUpEmailPassword()
|
const result = await signUpEmailPassword(email, password)
|
||||||
|
console.log(result)
|
||||||
}}
|
}}
|
||||||
block
|
block
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Button } from 'rsuite'
|
|
||||||
import { NavLink } from 'react-router-dom'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
|
import { Button } from 'rsuite'
|
||||||
|
|
||||||
import { EmailPasswordlessForm } from '../components/email-passwordless-form'
|
import { EmailPasswordlessForm } from '../components/email-passwordless-form'
|
||||||
export const EmailPasswordless: React.FC = () => {
|
export const EmailPasswordless: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
import { Icon } from '@rsuite/icons'
|
import React from 'react'
|
||||||
import { FaLock } from 'react-icons/fa'
|
import { FaLock } from 'react-icons/fa'
|
||||||
import { Button, Divider, FlexboxGrid, IconButton, Panel } from 'rsuite'
|
|
||||||
import { Link, NavLink, Route, Routes } from 'react-router-dom'
|
import { Link, NavLink, Route, Routes } from 'react-router-dom'
|
||||||
|
import { Button, Divider, FlexboxGrid, IconButton, Panel } from 'rsuite'
|
||||||
|
|
||||||
|
import { Icon } from '@rsuite/icons'
|
||||||
|
|
||||||
import { OAuthLinks } from '../components'
|
import { OAuthLinks } from '../components'
|
||||||
import { VerificationEmailSent } from '../verification-email-sent'
|
import { VerificationEmailSent } from '../verification-email-sent'
|
||||||
|
|
||||||
import { EmailPassword } from './email-password'
|
import { EmailPassword } from './email-password'
|
||||||
import { EmailPasswordless } from './email-passwordless'
|
import { EmailPasswordless } from './email-passwordless'
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { useAuthenticated } from '@nhost/react'
|
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
|
import { useAuthenticated } from '@nhost/react'
|
||||||
|
|
||||||
export const VerificationEmailSent: React.FC = () => {
|
export const VerificationEmailSent: React.FC = () => {
|
||||||
const isAuthenticated = useAuthenticated()
|
const isAuthenticated = useAuthenticated()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.7.tgz#078d8b833fbbcc95286613be8c716cef2b519fa2"
|
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.7.tgz#078d8b833fbbcc95286613be8c716cef2b519fa2"
|
||||||
integrity sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==
|
integrity sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==
|
||||||
|
|
||||||
"@babel/core@^7.16.12":
|
"@babel/core@^7.17.8":
|
||||||
version "7.17.8"
|
version "7.17.8"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.8.tgz#3dac27c190ebc3a4381110d46c80e77efe172e1a"
|
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.8.tgz#3dac27c190ebc3a4381110d46c80e77efe172e1a"
|
||||||
integrity sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==
|
integrity sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==
|
||||||
@@ -217,7 +217,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.16.7"
|
"@babel/helper-plugin-utils" "^7.16.7"
|
||||||
|
|
||||||
"@babel/plugin-transform-react-jsx@^7.16.7":
|
"@babel/plugin-transform-react-jsx@^7.16.7", "@babel/plugin-transform-react-jsx@^7.17.3":
|
||||||
version "7.17.3"
|
version "7.17.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1"
|
||||||
integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==
|
integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==
|
||||||
@@ -296,67 +296,67 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.3.1.tgz#b50a781709c81e10701004214340f25475a171a0"
|
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.3.1.tgz#b50a781709c81e10701004214340f25475a171a0"
|
||||||
integrity sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw==
|
integrity sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw==
|
||||||
|
|
||||||
"@nhost/apollo@0.3.0":
|
"@nhost/apollo@^0.3.7":
|
||||||
version "0.3.0"
|
version "0.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/apollo/-/apollo-0.3.0.tgz#89a66e97aa6af4de6045bf0c780e8b9590c06d9b"
|
resolved "https://registry.yarnpkg.com/@nhost/apollo/-/apollo-0.3.7.tgz#761d3d60519df60caaa7220909ab11bd2c629e3a"
|
||||||
integrity sha512-97DSycgPEnQQtzAWPB36yENAuQFDEl8c7qLB9xOzSnplImv5NGces40XMAkTDEWam0eD//PtXP9zi+TYNeMNjw==
|
integrity sha512-NH1WCC5D6K/Ft8/EXYIgeAhOBq5Gt1OtX9U9RzV2IqmVRGigDw+YlXr8P5GRPAzBeZUVWrM1wvBt+oBk8zw/7g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nhost/core" "0.3.0"
|
"@nhost/core" "^0.3.8"
|
||||||
graphql "16"
|
graphql "16"
|
||||||
subscriptions-transport-ws "^0.11.0"
|
subscriptions-transport-ws "^0.11.0"
|
||||||
|
|
||||||
"@nhost/core@0.3.0":
|
"@nhost/core@^0.3.8":
|
||||||
version "0.3.0"
|
version "0.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/core/-/core-0.3.0.tgz#fa630afef50840cd7b8415e17894c7765cda273f"
|
resolved "https://registry.yarnpkg.com/@nhost/core/-/core-0.3.8.tgz#0269ab5daa36b1bdd2b2864c174809a86d4d2a7a"
|
||||||
integrity sha512-wEdq+BLOHH7bOhBvF5gql9vtWuEtlLWvw65AtpstfX8pAUY8ce2yqamV6Z8kxr/RSYXZA+aLsKwig50qSZa99w==
|
integrity sha512-6mOv23H16n0YN0voXdXSGS18rUELe1YI2+HXMRlaeksCib4BvSf28lsideEOjFnyfHA3Y4wAX1SMxnyaEj1qaQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
axios "^0.25.0"
|
axios "^0.25.0"
|
||||||
broadcast-channel "^4.10.0"
|
broadcast-channel "^4.10.0"
|
||||||
js-cookie "^3.0.1"
|
js-cookie "^3.0.1"
|
||||||
xstate "^4.30.5"
|
xstate "^4.30.5"
|
||||||
|
|
||||||
"@nhost/hasura-auth-js@1.0.0":
|
"@nhost/hasura-auth-js@^1.0.9":
|
||||||
version "1.0.0"
|
version "1.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/hasura-auth-js/-/hasura-auth-js-1.0.0.tgz#0f3c267614ca328c944797f33a1921c8103dd3e5"
|
resolved "https://registry.yarnpkg.com/@nhost/hasura-auth-js/-/hasura-auth-js-1.0.9.tgz#7e5cfe7a59b18778352dd6d2bef368c765ce9886"
|
||||||
integrity sha512-hENPB1aMdekYxfDejthPAdoj9JarqaVkBKNRa+jun247Un1X6eFGDPo52Y2tZfP44pJEUK4EqTqkWH3DwT4uXg==
|
integrity sha512-d0UDfakzUO9N0/4RRy9NptoOLgpcRmr2F5XxVVzqLYX67+XzZoqT+LMhOF8spKP4+JqFlKFgqbNulmuRRc5FfA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nhost/core" "0.3.0"
|
"@nhost/core" "^0.3.8"
|
||||||
|
|
||||||
"@nhost/hasura-storage-js@0.2.0":
|
"@nhost/hasura-storage-js@^0.2.0":
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/hasura-storage-js/-/hasura-storage-js-0.2.0.tgz#e8c127d883d231313cd262553732da3b0dccb858"
|
resolved "https://registry.yarnpkg.com/@nhost/hasura-storage-js/-/hasura-storage-js-0.2.0.tgz#e8c127d883d231313cd262553732da3b0dccb858"
|
||||||
integrity sha512-JumgUhnScU6Bv8SBmN2F4sY+LbrD3i25Ppr30Zjbv4MvbUguBclx9zzAwqub/P2n/azc7bjjRvYl2n2/jjKRXw==
|
integrity sha512-JumgUhnScU6Bv8SBmN2F4sY+LbrD3i25Ppr30Zjbv4MvbUguBclx9zzAwqub/P2n/azc7bjjRvYl2n2/jjKRXw==
|
||||||
dependencies:
|
dependencies:
|
||||||
axios "^0.21.1"
|
axios "^0.21.1"
|
||||||
|
|
||||||
"@nhost/nhost-js@1.0.0":
|
"@nhost/nhost-js@^1.0.9":
|
||||||
version "1.0.0"
|
version "1.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/nhost-js/-/nhost-js-1.0.0.tgz#d57aa66c889922926b9bde6278d35000729f884c"
|
resolved "https://registry.yarnpkg.com/@nhost/nhost-js/-/nhost-js-1.0.9.tgz#a1b0bc0c35e15ade2867da4d211b1f81f3bc5e28"
|
||||||
integrity sha512-ve5+TqYGcQbRwDqxVDMCJKZQlj5BFCsTzqEhIAUnLP6Gu8YlNVeUQL3Bbc19j71OkHDNhw8TAJbE2zcFUBT2Fw==
|
integrity sha512-/SZLk3Be560scVAbUswcRSE4RMwf6M7xanbNLqGUuI/sr1Ir253WPhaD2YWXZChP1v2LBzONhdJNI2g7u1NzoA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nhost/hasura-auth-js" "1.0.0"
|
"@nhost/hasura-auth-js" "^1.0.9"
|
||||||
"@nhost/hasura-storage-js" "0.2.0"
|
"@nhost/hasura-storage-js" "^0.2.0"
|
||||||
axios "^0.23.0"
|
axios "^0.23.0"
|
||||||
jwt-decode "^3.1.2"
|
jwt-decode "^3.1.2"
|
||||||
query-string "^7.0.1"
|
query-string "^7.0.1"
|
||||||
|
|
||||||
"@nhost/react-apollo@^4.0.0":
|
"@nhost/react-apollo@^4.0.10":
|
||||||
version "4.0.0"
|
version "4.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/react-apollo/-/react-apollo-4.0.0.tgz#08be35946eadbb746f27435c3fc72cd092a97b61"
|
resolved "https://registry.yarnpkg.com/@nhost/react-apollo/-/react-apollo-4.0.10.tgz#d28819019f35aff7fb69a3b485489ab0492643e1"
|
||||||
integrity sha512-ZmFgBgHFJE2Z2ZBYx3U4Gry9TprUOb4NXw/K5lSKv11zPeEaclfpqn+aeQbtCj02oCnzRe+MJLsJenpcuhQRuw==
|
integrity sha512-MTIBk9aQVCIfVR17eEKM6ssELadpDhIAh2ERjaZY8+i9KMgVyjEt0s4842nl1Bwq7OFIXf5GRykr3RtTjuT/Ug==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nhost/apollo" "0.3.0"
|
"@nhost/apollo" "^0.3.7"
|
||||||
|
|
||||||
"@nhost/react@^0.3.0":
|
"@nhost/react@^0.5.0":
|
||||||
version "0.3.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@nhost/react/-/react-0.3.0.tgz#5401922dce91bb66db5d575de1869df00fabbb8e"
|
resolved "https://registry.yarnpkg.com/@nhost/react/-/react-0.5.0.tgz#5276ae7e13691f32ceaa0e6ca2460ef2605820f6"
|
||||||
integrity sha512-jxyt4dYfphgv3bf6jvV7qDKnV5qUArFvdTYExKlBA9tsBQYta0heawMsJk0rEarEZGUw1iioiUYFKdZyl2Qi5Q==
|
integrity sha512-d89I3Q1Y6+9QJ6jP9yU9xrEJv8dCvTwll7tctd7emqZyPWGgInLpmZ9OA+/xrannowck5MsgaBdz0zxQ9bjJBA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nhost/nhost-js" "1.0.0"
|
"@nhost/nhost-js" "^1.0.9"
|
||||||
"@xstate/react" "^2.0.1"
|
"@xstate/react" "^2.0.1"
|
||||||
immer "^9.0.12"
|
immer "^9.0.12"
|
||||||
|
|
||||||
"@rollup/pluginutils@^4.1.2":
|
"@rollup/pluginutils@^4.2.0":
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.0.tgz#a14bbd058fdbba0a5647143b16ed0d86fb60bd08"
|
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.0.tgz#a14bbd058fdbba0a5647143b16ed0d86fb60bd08"
|
||||||
integrity sha512-2WUyJNRkyH5p487pGnn4tWAsxhEFKN/pT8CMgHshd5H+IXkOnKvKZwsz5ZWz+YCXkleZRAU5kwbfgF8CPfDRqA==
|
integrity sha512-2WUyJNRkyH5p487pGnn4tWAsxhEFKN/pT8CMgHshd5H+IXkOnKvKZwsz5ZWz+YCXkleZRAU5kwbfgF8CPfDRqA==
|
||||||
@@ -394,7 +394,7 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
|
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
|
||||||
integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
|
integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
|
||||||
|
|
||||||
"@types/react-dom@^17.0.11":
|
"@types/react-dom@^17.0.14":
|
||||||
version "17.0.14"
|
version "17.0.14"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.14.tgz#c8f917156b652ddf807711f5becbd2ab018dea9f"
|
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.14.tgz#c8f917156b652ddf807711f5becbd2ab018dea9f"
|
||||||
integrity sha512-H03xwEP1oXmSfl3iobtmQ/2dHF5aBHr8aUMwyGZya6OW45G+xtdzmq6HkncefiBt5JU8DVyaWl/nWZbjZCnzAQ==
|
integrity sha512-H03xwEP1oXmSfl3iobtmQ/2dHF5aBHr8aUMwyGZya6OW45G+xtdzmq6HkncefiBt5JU8DVyaWl/nWZbjZCnzAQ==
|
||||||
@@ -409,7 +409,7 @@
|
|||||||
"@types/prop-types" "*"
|
"@types/prop-types" "*"
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react@*", "@types/react@^17.0.39":
|
"@types/react@*", "@types/react@^17.0.43":
|
||||||
version "17.0.43"
|
version "17.0.43"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.43.tgz#4adc142887dd4a2601ce730bc56c3436fdb07a55"
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.43.tgz#4adc142887dd4a2601ce730bc56c3436fdb07a55"
|
||||||
integrity sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A==
|
integrity sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A==
|
||||||
@@ -423,17 +423,17 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
|
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
|
||||||
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
|
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
|
||||||
|
|
||||||
"@vitejs/plugin-react@^1.2.0":
|
"@vitejs/plugin-react@^1.3.0":
|
||||||
version "1.2.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-1.2.0.tgz#4cfb4c0475e93885e56d66ff15e12ef4c34b0af0"
|
resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-1.3.0.tgz#efd4b4383edc12780cd8d230c2daa9d266690bb9"
|
||||||
integrity sha512-Rywwt0IXXg6yQ0hv3cMT3mtdDcGIw31mGaa+MMMAT651LhoXLF2yFy4LrakiTs7UKs7RPBo9eNgaS8pgl2A6Qw==
|
integrity sha512-H+yIupjUE4a+E4oeWUv4xUJIMR0DWBIMUG/DYgvj0J9Vu1rdHAlJ5JdbI+N1KDUD7Ee2fZ1DMPZ/NBg6mXtoCw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/core" "^7.16.12"
|
"@babel/core" "^7.17.8"
|
||||||
"@babel/plugin-transform-react-jsx" "^7.16.7"
|
"@babel/plugin-transform-react-jsx" "^7.17.3"
|
||||||
"@babel/plugin-transform-react-jsx-development" "^7.16.7"
|
"@babel/plugin-transform-react-jsx-development" "^7.16.7"
|
||||||
"@babel/plugin-transform-react-jsx-self" "^7.16.7"
|
"@babel/plugin-transform-react-jsx-self" "^7.16.7"
|
||||||
"@babel/plugin-transform-react-jsx-source" "^7.16.7"
|
"@babel/plugin-transform-react-jsx-source" "^7.16.7"
|
||||||
"@rollup/pluginutils" "^4.1.2"
|
"@rollup/pluginutils" "^4.2.0"
|
||||||
react-refresh "^0.11.0"
|
react-refresh "^0.11.0"
|
||||||
resolve "^1.22.0"
|
resolve "^1.22.0"
|
||||||
|
|
||||||
@@ -458,13 +458,6 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.3.0"
|
tslib "^2.3.0"
|
||||||
|
|
||||||
"@xstate/inspect@^0.6.2":
|
|
||||||
version "0.6.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/@xstate/inspect/-/inspect-0.6.4.tgz#dd12abb30375dcb0471b81e8db3b81377cd00be6"
|
|
||||||
integrity sha512-2Gz5wu/RdpeLEpQ93qWQe/lDybJHQq8NzgWyB/EmDUBhOggCeZu4JqJCT7/RsQ7FNSEenZILFbNTftOY00Kg4A==
|
|
||||||
dependencies:
|
|
||||||
fast-safe-stringify "^2.0.7"
|
|
||||||
|
|
||||||
"@xstate/react@^2.0.1":
|
"@xstate/react@^2.0.1":
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@xstate/react/-/react-2.0.1.tgz#2b4717369d419e78a6c67f2dfcd1a3be9abce2d9"
|
resolved "https://registry.yarnpkg.com/@xstate/react/-/react-2.0.1.tgz#2b4717369d419e78a6c67f2dfcd1a3be9abce2d9"
|
||||||
@@ -682,131 +675,131 @@ errno@^0.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prr "~1.0.1"
|
prr "~1.0.1"
|
||||||
|
|
||||||
esbuild-android-64@0.14.27:
|
esbuild-android-64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.27.tgz#b868bbd9955a92309c69df628d8dd1945478b45c"
|
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.32.tgz#cf23a9c6052bb48901f5541c7e5a4168495fca36"
|
||||||
integrity sha512-LuEd4uPuj/16Y8j6kqy3Z2E9vNY9logfq8Tq+oTE2PZVuNs3M1kj5Qd4O95ee66yDGb3isaOCV7sOLDwtMfGaQ==
|
integrity sha512-q1qjB2UcoWehR9Yp9dO2RdJUeLLrXAYsbOU4tkYa+GmJzxTwuvOrMdvaemsXYqb7F4STVTca9KpfqGicEChtUg==
|
||||||
|
|
||||||
esbuild-android-arm64@0.14.27:
|
esbuild-android-arm64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.27.tgz#e7d6430555e8e9c505fd87266bbc709f25f1825c"
|
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.32.tgz#5840407c8d8b577eea847eecce8df9610c0f58fd"
|
||||||
integrity sha512-E8Ktwwa6vX8q7QeJmg8yepBYXaee50OdQS3BFtEHKrzbV45H4foMOeEE7uqdjGQZFBap5VAqo7pvjlyA92wznQ==
|
integrity sha512-bs1uu+RuM15f8yjFc0FhPDE/6NID4fKl7beDVsGCme6Q8ld2IzRXmp5QaHurlcH93PFyQnUgVvdahIWgtK2QZw==
|
||||||
|
|
||||||
esbuild-darwin-64@0.14.27:
|
esbuild-darwin-64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.27.tgz#4dc7484127564e89b4445c0a560a3cb50b3d68e1"
|
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.32.tgz#c6defc12a60f27408f1a30bb233c9d0e66ea2a55"
|
||||||
integrity sha512-czw/kXl/1ZdenPWfw9jDc5iuIYxqUxgQ/Q+hRd4/3udyGGVI31r29LCViN2bAJgGvQkqyLGVcG03PJPEXQ5i2g==
|
integrity sha512-6MekflAld28wYtzanwZTxQlxMPeYw/yv1ToFG2hpo3LGxOIE2mBD5IJaMCcyy1//EYvGnGToO3p6XKdbS8E1QQ==
|
||||||
|
|
||||||
esbuild-darwin-arm64@0.14.27:
|
esbuild-darwin-arm64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.27.tgz#469e59c665f84a8ed323166624c5e7b9b2d22ac1"
|
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.32.tgz#fc878496516a90fc4982ee7cf8f2d2f484dbd64a"
|
||||||
integrity sha512-BEsv2U2U4o672oV8+xpXNxN9bgqRCtddQC6WBh4YhXKDcSZcdNh7+6nS+DM2vu7qWIWNA4JbRG24LUUYXysimQ==
|
integrity sha512-BHYIjiPDYQTD+4zwqdqRo+I2bbg3fn9mah/gZm4SCCy+7uwTTYOYobIunHT7wVCgxnFCr50PJUdaMrEoCImRbw==
|
||||||
|
|
||||||
esbuild-freebsd-64@0.14.27:
|
esbuild-freebsd-64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.27.tgz#895df03bf5f87094a56c9a5815bf92e591903d70"
|
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.32.tgz#c136e8e8bab8e7ea95a7fbe4b689d2c940bf48f2"
|
||||||
integrity sha512-7FeiFPGBo+ga+kOkDxtPmdPZdayrSzsV9pmfHxcyLKxu+3oTcajeZlOO1y9HW+t5aFZPiv7czOHM4KNd0tNwCA==
|
integrity sha512-6BOBhtfAf9AlfjL1AvtfVOxwY82tHPfYrA0lskJpFjfiEMGTLU6e0vdOwb4+4x++gGz49azuGK0woYqdfL03uw==
|
||||||
|
|
||||||
esbuild-freebsd-arm64@0.14.27:
|
esbuild-freebsd-arm64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.27.tgz#0b72a41a6b8655e9a8c5608f2ec1afdcf6958441"
|
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.32.tgz#46668a10e5a51665ed800b10a02b757bf6bc6fbf"
|
||||||
integrity sha512-8CK3++foRZJluOWXpllG5zwAVlxtv36NpHfsbWS7TYlD8S+QruXltKlXToc/5ZNzBK++l6rvRKELu/puCLc7jA==
|
integrity sha512-zIRR4gKQW56p/xLM8TlpxVBNiX0w3VoR9ZxfH4nrfJ7QiL0SYHRy8YPL5C7zMWRjSze2WxQRHfS9bHKdVrVXBw==
|
||||||
|
|
||||||
esbuild-linux-32@0.14.27:
|
esbuild-linux-32@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.27.tgz#43b8ba3803b0bbe7f051869c6a8bf6de1e95de28"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.32.tgz#ac51a64f26f638618ff62a1a966babe065bc54cc"
|
||||||
integrity sha512-qhNYIcT+EsYSBClZ5QhLzFzV5iVsP1YsITqblSaztr3+ZJUI+GoK8aXHyzKd7/CKKuK93cxEMJPpfi1dfsOfdw==
|
integrity sha512-kn0AkGtPvzA6xiv93/mavvZ7DVinu/ewh2F2S0/8mE8/PXi3D4+svZ6V3beV5DIH7vcHVuGhoooWav8HPF04tg==
|
||||||
|
|
||||||
esbuild-linux-64@0.14.27:
|
esbuild-linux-64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.27.tgz#dc8072097327ecfadba1735562824ce8c05dd0bd"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.32.tgz#a3dfeb772f339fb34f0ff61df753a70a01be243a"
|
||||||
integrity sha512-ESjck9+EsHoTaKWlFKJpPZRN26uiav5gkI16RuI8WBxUdLrrAlYuYSndxxKgEn1csd968BX/8yQZATYf/9+/qg==
|
integrity sha512-Ie+PMvrPj/HCOmSc0QubKttDxP2iBtPzDu+b+V3HGDGwkGmVpDkyXx1NXp5LjkIphIay2QekMwy1dSw3KDqCew==
|
||||||
|
|
||||||
esbuild-linux-arm64@0.14.27:
|
esbuild-linux-arm64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.27.tgz#c52b58cbe948426b1559910f521b0a3f396f10b8"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.32.tgz#df2fead5c0d9228eede866359f35b3e0eef4e192"
|
||||||
integrity sha512-no6Mi17eV2tHlJnqBHRLekpZ2/VYx+NfGxKcBE/2xOMYwctsanCaXxw4zapvNrGE9X38vefVXLz6YCF8b1EHiQ==
|
integrity sha512-ykoqKaxX95nB+lk2K/+qxr0ke+BxkeVi0yKOnymCR5Ive7IZDHa4BJX53NEGSBKLfWPwKE6SXTz8qcEewSntoA==
|
||||||
|
|
||||||
esbuild-linux-arm@0.14.27:
|
esbuild-linux-arm@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.27.tgz#df869dbd67d4ee3a04b3c7273b6bd2b233e78a18"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.32.tgz#64633aa6491e91d935324cf041795ebce18c071b"
|
||||||
integrity sha512-JnnmgUBdqLQO9hoNZQqNHFWlNpSX82vzB3rYuCJMhtkuaWQEmQz6Lec1UIxJdC38ifEghNTBsF9bbe8dFilnCw==
|
integrity sha512-R/Bvn/YQNDyvfN0SERh/I7hKPqN+nSSruQdVeiYEJ+jc3fUi73jXYAscpTQgIBeER/yXnEsgJGU/UQ9+sscr7A==
|
||||||
|
|
||||||
esbuild-linux-mips64le@0.14.27:
|
esbuild-linux-mips64le@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.27.tgz#a2b646d9df368b01aa970a7b8968be6dd6b01d19"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.32.tgz#f0a7a083e8fdfb6e4edffb93ec27de2c5d732f01"
|
||||||
integrity sha512-NolWP2uOvIJpbwpsDbwfeExZOY1bZNlWE/kVfkzLMsSgqeVcl5YMen/cedRe9mKnpfLli+i0uSp7N+fkKNU27A==
|
integrity sha512-IilnlBexpHpt/5po0cle/L/S6CYnwaq23UuAqWzxp+opHLOCNnyANpC1jOoP551aRx4JuZ7z3xZZ7bYQZB147w==
|
||||||
|
|
||||||
esbuild-linux-ppc64le@0.14.27:
|
esbuild-linux-ppc64le@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.27.tgz#9a21af766a0292578a3009c7408b8509cac7cefd"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.32.tgz#dc22b766dd4ddd20c28febe36e8b92b9c11faa63"
|
||||||
integrity sha512-/7dTjDvXMdRKmsSxKXeWyonuGgblnYDn0MI1xDC7J1VQXny8k1qgNp6VmrlsawwnsymSUUiThhkJsI+rx0taNA==
|
integrity sha512-TR6l5nWZbfq7jSY+1vsiQjT4m67NWplNhbX6GBieZq6DBt0nTx1XgTZAdKROF7jTuaK7YrCYlPXtfO3w86Mysw==
|
||||||
|
|
||||||
esbuild-linux-riscv64@0.14.27:
|
esbuild-linux-riscv64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.27.tgz#344a27f91568056a5903ad5841b447e00e78d740"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.32.tgz#0ae09eee847de5993cbe1529591d5ca17c7303c5"
|
||||||
integrity sha512-D+aFiUzOJG13RhrSmZgrcFaF4UUHpqj7XSKrIiCXIj1dkIkFqdrmqMSOtSs78dOtObWiOrFCDDzB24UyeEiNGg==
|
integrity sha512-aSOcUzTeIAslfri8e+bMpyzQuxhcIiNhWyuCGGXum2PtxwYiUqR8/UCMYfwYtYkhr1yABOFOfs83mm9KBy5qCQ==
|
||||||
|
|
||||||
esbuild-linux-s390x@0.14.27:
|
esbuild-linux-s390x@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.27.tgz#73a7309bd648a07ef58f069658f989a5096130db"
|
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.32.tgz#1297f9f130cd93495e7ce25c63a79dab223b89de"
|
||||||
integrity sha512-CD/D4tj0U4UQjELkdNlZhQ8nDHU5rBn6NGp47Hiz0Y7/akAY5i0oGadhEIg0WCY/HYVXFb3CsSPPwaKcTOW3bg==
|
integrity sha512-dNlip+EvexxKjRZitFCWCd7DVk64c7R5ySr8aFEMHCb/RriNiyDxYJGzYWm4EMJsMRMupMUHlMY64BAa3Op9FA==
|
||||||
|
|
||||||
esbuild-netbsd-64@0.14.27:
|
esbuild-netbsd-64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.27.tgz#482a587cdbd18a6c264a05136596927deb46c30a"
|
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.32.tgz#902bf5ba7c54db9c7274f019c4d006b1b963fb7d"
|
||||||
integrity sha512-h3mAld69SrO1VoaMpYl3a5FNdGRE/Nqc+E8VtHOag4tyBwhCQXxtvDDOAKOUQexBGca0IuR6UayQ4ntSX5ij1Q==
|
integrity sha512-Pa3QByYqxzlBFQQQhjYBPg3WUfSjwibqzh1hC6mPDRUHnCeUcrLoBuIiG4xqOYEpQM9/kDowIBsrGIQEVWWdQA==
|
||||||
|
|
||||||
esbuild-openbsd-64@0.14.27:
|
esbuild-openbsd-64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.27.tgz#e99f8cdc63f1628747b63edd124d53cf7796468d"
|
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.32.tgz#0fbfbdf555deeb05a8915daf0b71168d09773437"
|
||||||
integrity sha512-xwSje6qIZaDHXWoPpIgvL+7fC6WeubHHv18tusLYMwL+Z6bEa4Pbfs5IWDtQdHkArtfxEkIZz77944z8MgDxGw==
|
integrity sha512-uWKKqpCjkMY8TCIobFvaSETonQY3OrmgnoTCC3tF+lvMoneYjppB6akx7L5Xv0kP+1tnSbrIof1ca8PfqGUyjw==
|
||||||
|
|
||||||
esbuild-sunos-64@0.14.27:
|
esbuild-sunos-64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.27.tgz#8611d825bcb8239c78d57452e83253a71942f45c"
|
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.32.tgz#d493ca5222703dd0b8c489324d1517cd622618e8"
|
||||||
integrity sha512-/nBVpWIDjYiyMhuqIqbXXsxBc58cBVH9uztAOIfWShStxq9BNBik92oPQPJ57nzWXRNKQUEFWr4Q98utDWz7jg==
|
integrity sha512-Ar+u3mBk0oVV4Fwv/qlinJZNIPPtTBSG+1W42o8lOaVxJ+rJgecDoeUN+5uyd9at0BK1SVrQ1qZ4wjHKB0qFpQ==
|
||||||
|
|
||||||
esbuild-windows-32@0.14.27:
|
esbuild-windows-32@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.27.tgz#c06374206d4d92dd31d4fda299b09f51a35e82f6"
|
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.32.tgz#c6b0f4cf952c6f562a32fe763acab9fb8cb3912a"
|
||||||
integrity sha512-Q9/zEjhZJ4trtWhFWIZvS/7RUzzi8rvkoaS9oiizkHTTKd8UxFwn/Mm2OywsAfYymgUYm8+y2b+BKTNEFxUekw==
|
integrity sha512-rLMsbflMY6Hjh3rmQnCDVZahJQ7n+XfT6o1+no5pHRpDlMh38MHthgGh35q+EcOMgrGP3ppnw70rhJq80SaYTQ==
|
||||||
|
|
||||||
esbuild-windows-64@0.14.27:
|
esbuild-windows-64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.27.tgz#756631c1d301dfc0d1a887deed2459ce4079582f"
|
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.32.tgz#2ad9322a963fd26bb4818ad1c0ee7acde63ebb81"
|
||||||
integrity sha512-b3y3vTSl5aEhWHK66ngtiS/c6byLf6y/ZBvODH1YkBM+MGtVL6jN38FdHUsZasCz9gFwYs/lJMVY9u7GL6wfYg==
|
integrity sha512-OHnMMxYufVgLXIMnwLynLMKguHMrsVnWcehieSP9i6ZX31KEsOFYWrorcnTWOn4rbZVLSL10ofxLuVIgRW3SWw==
|
||||||
|
|
||||||
esbuild-windows-arm64@0.14.27:
|
esbuild-windows-arm64@0.14.32:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.27.tgz#ad7e187193dcd18768b16065a950f4441d7173f4"
|
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.32.tgz#bb589106c0fd5d582cce62bd7995a6e5db52e7b4"
|
||||||
integrity sha512-I/reTxr6TFMcR5qbIkwRGvldMIaiBu2+MP0LlD7sOlNXrfqIl9uNjsuxFPGEG4IRomjfQ5q8WT+xlF/ySVkqKg==
|
integrity sha512-ddavy6IPUBySMfqDfG243TgtuqwQBNJQJPVaA4DaavmMfpBsUxFrSV+HzBWXTKU3I9EcuoEvIATLuQ7NJKxjwg==
|
||||||
|
|
||||||
esbuild@^0.14.14:
|
esbuild@^0.14.27:
|
||||||
version "0.14.27"
|
version "0.14.32"
|
||||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.27.tgz#41fe0f1b6b68b9f77cac025009bc54bb96e616f1"
|
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.32.tgz#f55245ccd4b820707147ac4cc69a2c3e1a76af03"
|
||||||
integrity sha512-MZQt5SywZS3hA9fXnMhR22dv0oPGh6QtjJRIYbgL1AeqAoQZE+Qn5ppGYQAoHv/vq827flj4tIJ79Mrdiwk46Q==
|
integrity sha512-RuzVUP/bkStmnVHK6Gh3gjaMjfXNLqBqvYVDiS9JKl5KdRdRLUeW5Wo8NrbL7cL6CW7Cyak7SvACqyPOBuA8vA==
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
esbuild-android-64 "0.14.27"
|
esbuild-android-64 "0.14.32"
|
||||||
esbuild-android-arm64 "0.14.27"
|
esbuild-android-arm64 "0.14.32"
|
||||||
esbuild-darwin-64 "0.14.27"
|
esbuild-darwin-64 "0.14.32"
|
||||||
esbuild-darwin-arm64 "0.14.27"
|
esbuild-darwin-arm64 "0.14.32"
|
||||||
esbuild-freebsd-64 "0.14.27"
|
esbuild-freebsd-64 "0.14.32"
|
||||||
esbuild-freebsd-arm64 "0.14.27"
|
esbuild-freebsd-arm64 "0.14.32"
|
||||||
esbuild-linux-32 "0.14.27"
|
esbuild-linux-32 "0.14.32"
|
||||||
esbuild-linux-64 "0.14.27"
|
esbuild-linux-64 "0.14.32"
|
||||||
esbuild-linux-arm "0.14.27"
|
esbuild-linux-arm "0.14.32"
|
||||||
esbuild-linux-arm64 "0.14.27"
|
esbuild-linux-arm64 "0.14.32"
|
||||||
esbuild-linux-mips64le "0.14.27"
|
esbuild-linux-mips64le "0.14.32"
|
||||||
esbuild-linux-ppc64le "0.14.27"
|
esbuild-linux-ppc64le "0.14.32"
|
||||||
esbuild-linux-riscv64 "0.14.27"
|
esbuild-linux-riscv64 "0.14.32"
|
||||||
esbuild-linux-s390x "0.14.27"
|
esbuild-linux-s390x "0.14.32"
|
||||||
esbuild-netbsd-64 "0.14.27"
|
esbuild-netbsd-64 "0.14.32"
|
||||||
esbuild-openbsd-64 "0.14.27"
|
esbuild-openbsd-64 "0.14.32"
|
||||||
esbuild-sunos-64 "0.14.27"
|
esbuild-sunos-64 "0.14.32"
|
||||||
esbuild-windows-32 "0.14.27"
|
esbuild-windows-32 "0.14.32"
|
||||||
esbuild-windows-64 "0.14.27"
|
esbuild-windows-64 "0.14.32"
|
||||||
esbuild-windows-arm64 "0.14.27"
|
esbuild-windows-arm64 "0.14.32"
|
||||||
|
|
||||||
escalade@^3.1.1:
|
escalade@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
@@ -833,11 +826,6 @@ eventemitter3@^4.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
||||||
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
|
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
|
||||||
|
|
||||||
fast-safe-stringify@^2.0.7:
|
|
||||||
version "2.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884"
|
|
||||||
integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==
|
|
||||||
|
|
||||||
fbemitter@^3.0.0:
|
fbemitter@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-3.0.0.tgz#00b2a1af5411254aab416cd75f9e6289bee4bff3"
|
resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-3.0.0.tgz#00b2a1af5411254aab416cd75f9e6289bee4bff3"
|
||||||
@@ -930,11 +918,6 @@ graphql-tag@^2.12.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
graphql@15.7.2:
|
|
||||||
version "15.7.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.7.2.tgz#85ab0eeb83722977151b3feb4d631b5f2ab287ef"
|
|
||||||
integrity sha512-AnnKk7hFQFmU/2I9YSQf3xw44ctnSFCfp3zE0N6W174gqe9fWG/2rKaKxROK7CcI3XtERpjEKFqts8o319Kf7A==
|
|
||||||
|
|
||||||
graphql@16:
|
graphql@16:
|
||||||
version "16.3.0"
|
version "16.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05"
|
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05"
|
||||||
@@ -1225,7 +1208,7 @@ pify@^4.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
|
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
|
||||||
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
|
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
|
||||||
|
|
||||||
postcss@^8.4.6:
|
postcss@^8.4.12:
|
||||||
version "8.4.12"
|
version "8.4.12"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905"
|
||||||
integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==
|
integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==
|
||||||
@@ -1324,18 +1307,18 @@ react-refresh@^0.11.0:
|
|||||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
|
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
|
||||||
integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
|
integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
|
||||||
|
|
||||||
react-router-dom@^6.2.1:
|
react-router-dom@^6.3.0:
|
||||||
version "6.2.2"
|
version "6.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.2.2.tgz#f1a2c88365593c76b9612ae80154a13fcb72e442"
|
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d"
|
||||||
integrity sha512-AtYEsAST7bDD4dLSQHDnk/qxWLJdad5t1HFa1qJyUrCeGgEuCSw0VB/27ARbF9Fi/W5598ujvJOm3ujUCVzuYQ==
|
integrity sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==
|
||||||
dependencies:
|
dependencies:
|
||||||
history "^5.2.0"
|
history "^5.2.0"
|
||||||
react-router "6.2.2"
|
react-router "6.3.0"
|
||||||
|
|
||||||
react-router@6.2.2:
|
react-router@6.3.0, react-router@^6.3.0:
|
||||||
version "6.2.2"
|
version "6.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.2.2.tgz#495e683a0c04461eeb3d705fe445d6cf42f0c249"
|
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557"
|
||||||
integrity sha512-/MbxyLzd7Q7amp4gDOGaYvXwhEojkJD5BtExkuKmj39VEE0m3l/zipf6h2WIB2jyAO0lI6NGETh4RDcktRm4AQ==
|
integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
history "^5.2.0"
|
history "^5.2.0"
|
||||||
|
|
||||||
@@ -1409,10 +1392,10 @@ rsuite-table@^5.3.6:
|
|||||||
lodash "^4.17.21"
|
lodash "^4.17.21"
|
||||||
react-is "^17.0.2"
|
react-is "^17.0.2"
|
||||||
|
|
||||||
rsuite@^5.6.2:
|
rsuite@^5.7.1:
|
||||||
version "5.6.6"
|
version "5.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/rsuite/-/rsuite-5.6.6.tgz#03b97ec32a24212aaa95e3d14e5e85db2255175a"
|
resolved "https://registry.yarnpkg.com/rsuite/-/rsuite-5.7.1.tgz#2c50161e568cbf0074b42e7b65592b25a3b9412d"
|
||||||
integrity sha512-N4xnfnOpbxkEQ4+6GP/ll76XC8motkCQUNy1WL5wayZGgmOjzbVLbOUUHn9iGN32sBLyH8/d3Lo/WxfAjprj3g==
|
integrity sha512-vvqBadf9vJ49CW4gboFpj+Ol7M5sK7a72irwQxgxBxHBD2YEWUx9LQp137RIJV6w/nXg1P5yaObZULb5n77QoA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.8.4"
|
"@babel/runtime" "^7.8.4"
|
||||||
"@juggle/resize-observer" "^3.3.1"
|
"@juggle/resize-observer" "^3.3.1"
|
||||||
@@ -1555,7 +1538,7 @@ tslib@^2.1.0, tslib@^2.3.0:
|
|||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
||||||
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
|
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
|
||||||
|
|
||||||
typescript@^4.5.5:
|
typescript@^4.6.3:
|
||||||
version "4.6.3"
|
version "4.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c"
|
||||||
integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==
|
integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==
|
||||||
@@ -1597,13 +1580,13 @@ use-subscription@^1.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
|
|
||||||
vite@^2.8.5:
|
vite@^2.9.1:
|
||||||
version "2.8.6"
|
version "2.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/vite/-/vite-2.8.6.tgz#32d50e23c99ca31b26b8ccdc78b1d72d4d7323d3"
|
resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.1.tgz#84bce95fae210a7beb566a0af06246748066b48f"
|
||||||
integrity sha512-e4H0QpludOVKkmOsRyqQ7LTcMUDF3mcgyNU4lmi0B5JUbe0ZxeBBl8VoZ8Y6Rfn9eFKYtdXNPcYK97ZwH+K2ug==
|
integrity sha512-vSlsSdOYGcYEJfkQ/NeLXgnRv5zZfpAsdztkIrs7AZHV8RCMZQkwjo4DS5BnrYTqoWqLoUe1Cah4aVO4oNNqCQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild "^0.14.14"
|
esbuild "^0.14.27"
|
||||||
postcss "^8.4.6"
|
postcss "^8.4.12"
|
||||||
resolve "^1.22.0"
|
resolve "^1.22.0"
|
||||||
rollup "^2.59.0"
|
rollup "^2.59.0"
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -1632,11 +1615,6 @@ wrappy@1:
|
|||||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67"
|
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67"
|
||||||
integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==
|
integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==
|
||||||
|
|
||||||
ws@^8.5.0:
|
|
||||||
version "8.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f"
|
|
||||||
integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==
|
|
||||||
|
|
||||||
xstate@^4.30.5:
|
xstate@^4.30.5:
|
||||||
version "4.30.6"
|
version "4.30.6"
|
||||||
resolved "https://registry.yarnpkg.com/xstate/-/xstate-4.30.6.tgz#62b6dea37a500e0e1c0ff7c553a801eea5119554"
|
resolved "https://registry.yarnpkg.com/xstate/-/xstate-4.30.6.tgz#62b6dea37a500e0e1c0ff7c553a801eea5119554"
|
||||||
|
|||||||
@@ -28,11 +28,11 @@
|
|||||||
"prettier:fix": "prettier --write .",
|
"prettier:fix": "prettier --write .",
|
||||||
"lint": "pnpm turbo run lint --stream",
|
"lint": "pnpm turbo run lint --stream",
|
||||||
"lint:fix": "pnpm turbo run lint:fix --stream",
|
"lint:fix": "pnpm turbo run lint:fix --stream",
|
||||||
"test": "pnpm turbo run test --scope='@nhost/*' --no-deps --include-dependencies",
|
|
||||||
"prerelease": "pnpm clean && pnpm install && pnpm build",
|
"prerelease": "pnpm clean && pnpm install && pnpm build",
|
||||||
"release": "pnpm run prerelease && changeset publish && git push --follow-tags && git status && pnpm -r publish",
|
"release": "pnpm run prerelease && changeset publish",
|
||||||
"changeset": "changeset",
|
|
||||||
"snapshot": "pnpm prerelease && changeset version --snapshot preview && pnpm install && changeset publish --tag preview",
|
"snapshot": "pnpm prerelease && changeset version --snapshot preview && pnpm install && changeset publish --tag preview",
|
||||||
|
"test": "pnpm turbo run test --scope='@nhost/*' --no-deps --include-dependencies",
|
||||||
|
"changeset": "changeset",
|
||||||
"wait": "wait-on http://localhost:1337/v1/auth/healthz -i 500 -t 120000"
|
"wait": "wait-on http://localhost:1337/v1/auth/healthz -i 500 -t 120000"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
|
|||||||
@@ -1,5 +1,49 @@
|
|||||||
# @nhost/apollo
|
# @nhost/apollo
|
||||||
|
|
||||||
|
## 0.3.9
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [63d6059]
|
||||||
|
- Updated dependencies [63d6059]
|
||||||
|
- @nhost/core@0.3.10
|
||||||
|
|
||||||
|
## 0.3.8
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [2c97db6]
|
||||||
|
- @nhost/core@0.3.9
|
||||||
|
|
||||||
|
## 0.3.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [058956b]
|
||||||
|
- Updated dependencies [7cf875f]
|
||||||
|
- @nhost/core@0.3.8
|
||||||
|
|
||||||
|
## 0.3.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [16a6c50]
|
||||||
|
- @nhost/core@0.3.4
|
||||||
|
|
||||||
|
## 0.3.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- correct dependencies
|
||||||
|
|
||||||
|
See this related issues:
|
||||||
|
|
||||||
|
- [nhost](https://github.com/nhost/nhost/issues/326)
|
||||||
|
- [pnpm](https://github.com/pnpm/pnpm/issues/4348)
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @nhost/core@0.3.2
|
||||||
|
|
||||||
## 0.3.1
|
## 0.3.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
@@ -18,7 +62,6 @@
|
|||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
||||||
- Updated dependencies [744fd69]
|
|
||||||
- Updated dependencies [744fd69]
|
- Updated dependencies [744fd69]
|
||||||
- @nhost/core@0.3.0
|
- @nhost/core@0.3.0
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/apollo",
|
"name": "@nhost/apollo",
|
||||||
"version": "0.3.1",
|
"version": "0.3.9",
|
||||||
"description": "Nhost Apollo Client library",
|
"description": "Nhost Apollo Client library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -1,5 +1,52 @@
|
|||||||
# @nhost/core
|
# @nhost/core
|
||||||
|
|
||||||
|
## 0.3.10
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 63d6059: Set onTokenChanged before the state interpreter started
|
||||||
|
Fixes [#384](https://github.com/nhost/nhost/issues/384), thanks [@noverby](https://github.com/noverby)
|
||||||
|
- 63d6059: Trigger onTokenChanged when token changes
|
||||||
|
Fixes [#373](https://github.com/nhost/nhost/issues/373), thanks [@yureckey](https://github.com/yureckey)
|
||||||
|
|
||||||
|
## 0.3.9
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 2c97db6: Keep authentication status and access token in sync
|
||||||
|
The authentication events where not set correctly, leading the main Nhost client not to update internal states of storage/graphql/functions sub-clients when using non-react clients.
|
||||||
|
The use of private fields (`#`) is also avoided as they conflict with the use of proxies in Vue, leading to errors in the upcoming Vue library.
|
||||||
|
Fixes #373 and #378
|
||||||
|
|
||||||
|
## 0.3.8
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 058956b: Add missing provider types
|
||||||
|
`strava`, `gitlab`, and `bitbucket` were missing from the list of providers in Typescript and are now available.
|
||||||
|
- 058956b: Add `emailVerified`, `phoneNumber`, `phoneNumberVerified`, and `activeMfaType` to User type
|
||||||
|
|
||||||
|
Some information is missing in the `User` payload (see [this issue](https://github.com/nhost/nhost/issues/306)). The above properties have been added in the Typescript `User` type and are available when using Hasura Auth versions from [this pull request](https://github.com/nhost/hasura-auth/pull/128) (tentative version number: `0.5.1`)
|
||||||
|
|
||||||
|
- 7cf875f: Export error code payloads and type
|
||||||
|
|
||||||
|
## 0.3.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 16a6c50: Correct autoSignIn
|
||||||
|
|
||||||
|
## 0.3.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- correct dependencies
|
||||||
|
|
||||||
|
See this related issues:
|
||||||
|
|
||||||
|
- [nhost](https://github.com/nhost/nhost/issues/326)
|
||||||
|
- [pnpm](https://github.com/pnpm/pnpm/issues/4348)
|
||||||
|
|
||||||
## 0.3.1
|
## 0.3.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/core",
|
"name": "@nhost/core",
|
||||||
"version": "0.3.1",
|
"version": "0.3.10",
|
||||||
"description": "Nhost core client library",
|
"description": "Nhost core client library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ export class AuthClient {
|
|||||||
readonly backendUrl: string
|
readonly backendUrl: string
|
||||||
readonly clientUrl: string
|
readonly clientUrl: string
|
||||||
readonly machine: AuthMachine
|
readonly machine: AuthMachine
|
||||||
#interpreter?: AuthInterpreter
|
private _interpreter?: AuthInterpreter
|
||||||
#channel?: BroadcastChannel
|
private _channel?: BroadcastChannel
|
||||||
#subscriptions: Set<(client: AuthClient) => void> = new Set()
|
private _subscriptions: Set<(client: AuthClient) => void> = new Set()
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
backendUrl,
|
backendUrl,
|
||||||
@@ -45,8 +45,8 @@ export class AuthClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof window !== 'undefined' && autoSignIn) {
|
if (typeof window !== 'undefined' && autoSignIn) {
|
||||||
this.#channel = new BroadcastChannel<string>('nhost')
|
this._channel = new BroadcastChannel<string>('nhost')
|
||||||
this.#channel.addEventListener('message', (token) => {
|
this._channel.addEventListener('message', (token) => {
|
||||||
const existingToken = this.interpreter?.state.context.refreshToken
|
const existingToken = this.interpreter?.state.context.refreshToken
|
||||||
if (this.interpreter && token !== existingToken) {
|
if (this.interpreter && token !== existingToken) {
|
||||||
this.interpreter.send({ type: 'TRY_TOKEN', token })
|
this.interpreter.send({ type: 'TRY_TOKEN', token })
|
||||||
@@ -56,16 +56,23 @@ export class AuthClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get interpreter(): AuthInterpreter | undefined {
|
get interpreter(): AuthInterpreter | undefined {
|
||||||
return this.#interpreter
|
return this._interpreter
|
||||||
}
|
}
|
||||||
set interpreter(interpreter: AuthInterpreter | undefined) {
|
set interpreter(interpreter: AuthInterpreter | undefined) {
|
||||||
this.#interpreter = interpreter
|
this._interpreter = interpreter
|
||||||
if (interpreter) {
|
if (interpreter) {
|
||||||
this.#subscriptions.forEach((fn) => fn(this))
|
this._subscriptions.forEach((fn) => fn(this))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onStart(fn: (interpreter: AuthClient) => void) {
|
onStart(fn: (client: AuthClient) => void) {
|
||||||
this.#subscriptions.add(fn)
|
if (this.interpreter) {
|
||||||
|
// * The interpreter is already available: we can add the listener straight ahead
|
||||||
|
fn(this)
|
||||||
|
} else {
|
||||||
|
// * The interpreter is not yet available: we add the listener to a queue that will be started when setting the interpreter
|
||||||
|
// * Note: in React, the Xstate interpreter does not start from the global state, but from the root component
|
||||||
|
this._subscriptions.add(fn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ export type { NhostClientOptions } from './client'
|
|||||||
export { AuthClient } from './client'
|
export { AuthClient } from './client'
|
||||||
export * from './constants'
|
export * from './constants'
|
||||||
export { AuthClientSSR } from './coookie-client'
|
export { AuthClientSSR } from './coookie-client'
|
||||||
|
export * from './errors'
|
||||||
export * from './machines'
|
export * from './machines'
|
||||||
export * from './storage'
|
export * from './storage'
|
||||||
export * from './types'
|
export * from './types'
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ export const createChangeEmailMachine = ({ backendUrl, clientUrl, interpreter }:
|
|||||||
error: (_, { data: { error } }: any) => error
|
error: (_, { data: { error } }: any) => error
|
||||||
}),
|
}),
|
||||||
reportError: send((ctx) => ({ type: 'ERROR', error: ctx.error })),
|
reportError: send((ctx) => ({ type: 'ERROR', error: ctx.error })),
|
||||||
|
// TODO change email in the main machine (context.user.email)
|
||||||
reportSuccess: send('SUCCESS')
|
reportSuccess: send('SUCCESS')
|
||||||
},
|
},
|
||||||
guards: {
|
guards: {
|
||||||
|
|||||||
@@ -401,7 +401,12 @@ export const createAuthMachine = ({
|
|||||||
src: 'refreshToken',
|
src: 'refreshToken',
|
||||||
id: 'refreshToken',
|
id: 'refreshToken',
|
||||||
onDone: {
|
onDone: {
|
||||||
actions: ['saveSession', 'persist', 'resetTimer'],
|
actions: [
|
||||||
|
'saveSession',
|
||||||
|
'persist',
|
||||||
|
'resetTimer',
|
||||||
|
'reportTokenChanged'
|
||||||
|
],
|
||||||
target: 'pending'
|
target: 'pending'
|
||||||
},
|
},
|
||||||
onError: [
|
onError: [
|
||||||
@@ -634,26 +639,31 @@ export const createAuthMachine = ({
|
|||||||
options: rewriteRedirectTo(clientUrl, options)
|
options: rewriteRedirectTo(clientUrl, options)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If autoSignIn is enabled, attempts to get the refreshToken from the current location's hash
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
autoSignIn: async () => {
|
autoSignIn: async () => {
|
||||||
|
// TODO throwing errors is not really important as they are captured by the xstate invoker
|
||||||
|
// * Still, keep them for the moment as it needs to be tested in every environemnt e.g. nodejs, expo, react-native...
|
||||||
if (typeof window === 'undefined' || !window.location)
|
if (typeof window === 'undefined' || !window.location)
|
||||||
throw Error('window is undefined or location does not exist')
|
throw Error('window is undefined or location does not exist')
|
||||||
const { hash } = window.location
|
const { hash } = window.location
|
||||||
if (!hash) return
|
if (!hash) throw Error('No hash in window.location')
|
||||||
const params = new URLSearchParams(hash.slice(1))
|
const params = new URLSearchParams(hash.slice(1))
|
||||||
const refreshToken = params.get('refreshToken')
|
const refreshToken = params.get('refreshToken')
|
||||||
if (refreshToken) {
|
if (!refreshToken) throw Error('No refresh token in the location hash')
|
||||||
const session = await postRequest('/token', {
|
const session = await postRequest('/token', {
|
||||||
refreshToken
|
refreshToken
|
||||||
})
|
})
|
||||||
// * remove hash from the current url after consumming the token
|
// * remove hash from the current url after consumming the token
|
||||||
// TODO remove the hash. For the moment, it is kept to avoid regression from the current SDK.
|
// TODO remove the hash. For the moment, it is kept to avoid regression from the current SDK.
|
||||||
// * Then, only `refreshToken` will be in the hash, while `type` will be sent by hasura-auth as a query parameter
|
// * Then, only `refreshToken` will be in the hash, while `type` will be sent by hasura-auth as a query parameter
|
||||||
// window.history.pushState({}, '', location.pathname)
|
// window.history.pushState({}, '', location.pathname)
|
||||||
const channel = new BroadcastChannel('nhost')
|
const channel = new BroadcastChannel('nhost')
|
||||||
// TODO broadcat session instead of token
|
// ? broadcat session instead of token ?
|
||||||
channel.postMessage(refreshToken)
|
channel.postMessage(refreshToken)
|
||||||
return { session }
|
return { session }
|
||||||
}
|
|
||||||
},
|
},
|
||||||
importRefreshToken: async () => {
|
importRefreshToken: async () => {
|
||||||
const stringExpiresAt = await clientStorageGetter(NHOST_JWT_EXPIRES_AT_KEY)
|
const stringExpiresAt = await clientStorageGetter(NHOST_JWT_EXPIRES_AT_KEY)
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export interface Typegen0 {
|
|||||||
| 'done.invoke.authenticateAnonymously'
|
| 'done.invoke.authenticateAnonymously'
|
||||||
| 'done.invoke.signInMfaTotp'
|
| 'done.invoke.signInMfaTotp'
|
||||||
| 'done.invoke.registerUser'
|
| 'done.invoke.registerUser'
|
||||||
|
| 'done.invoke.refreshToken'
|
||||||
| 'done.invoke.authenticateWithToken'
|
| 'done.invoke.authenticateWithToken'
|
||||||
saveRefreshToken: 'done.invoke.importRefreshToken'
|
saveRefreshToken: 'done.invoke.importRefreshToken'
|
||||||
saveInvalidEmail: 'SIGNIN_PASSWORD' | 'SIGNIN_PASSWORDLESS_EMAIL'
|
saveInvalidEmail: 'SIGNIN_PASSWORD' | 'SIGNIN_PASSWORDLESS_EMAIL'
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ type RegistrationOptions = {
|
|||||||
metadata?: Record<string, unknown>
|
metadata?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
type RedirectOption = {
|
export type RedirectOption = {
|
||||||
redirectTo?: string
|
redirectTo?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,6 +26,7 @@ export type SendVerificationEmailOptions = RedirectOption
|
|||||||
export type DeanonymizeOptions = { email?: string; password?: string } & RegistrationOptions
|
export type DeanonymizeOptions = { email?: string; password?: string } & RegistrationOptions
|
||||||
export type ProviderOptions = RegistrationOptions & RedirectOption
|
export type ProviderOptions = RegistrationOptions & RedirectOption
|
||||||
|
|
||||||
|
// TODO share with hasura-auth
|
||||||
export type User = {
|
export type User = {
|
||||||
id: string
|
id: string
|
||||||
createdAt: string
|
createdAt: string
|
||||||
@@ -37,9 +38,13 @@ export type User = {
|
|||||||
defaultRole: string
|
defaultRole: string
|
||||||
roles: string[]
|
roles: string[]
|
||||||
metadata: Record<string, unknown>
|
metadata: Record<string, unknown>
|
||||||
|
emailVerified: boolean
|
||||||
|
phoneNumber: string | null
|
||||||
|
phoneNumberVerified: boolean
|
||||||
|
activeMfaType: 'totp' | null
|
||||||
}
|
}
|
||||||
|
|
||||||
// ! copy-paste from hasura-auth
|
// TODO share with hasura-auth
|
||||||
export type NhostSession = {
|
export type NhostSession = {
|
||||||
accessToken: string
|
accessToken: string
|
||||||
accessTokenExpiresIn: number
|
accessTokenExpiresIn: number
|
||||||
@@ -51,6 +56,7 @@ export type Mfa = {
|
|||||||
ticket: string
|
ticket: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO share with hasura-auth
|
||||||
export type Provider =
|
export type Provider =
|
||||||
| 'apple'
|
| 'apple'
|
||||||
| 'facebook'
|
| 'facebook'
|
||||||
@@ -60,3 +66,6 @@ export type Provider =
|
|||||||
| 'spotify'
|
| 'spotify'
|
||||||
| 'twitter'
|
| 'twitter'
|
||||||
| 'windowslive'
|
| 'windowslive'
|
||||||
|
| 'strava'
|
||||||
|
| 'gitlab'
|
||||||
|
| 'bitbucket'
|
||||||
|
|||||||
@@ -1,5 +1,70 @@
|
|||||||
# @nhost/hasura-auth-js
|
# @nhost/hasura-auth-js
|
||||||
|
|
||||||
|
## 1.0.11
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 63d6059: Add TSDoc information about Nhost client options
|
||||||
|
- 63d6059: Set onTokenChanged before the state interpreter started
|
||||||
|
Fixes [#384](https://github.com/nhost/nhost/issues/384), thanks [@noverby](https://github.com/noverby)
|
||||||
|
- 63d6059: Trigger onTokenChanged when token changes
|
||||||
|
Fixes [#373](https://github.com/nhost/nhost/issues/373), thanks [@yureckey](https://github.com/yureckey)
|
||||||
|
- Updated dependencies [63d6059]
|
||||||
|
- Updated dependencies [63d6059]
|
||||||
|
- @nhost/core@0.3.10
|
||||||
|
|
||||||
|
## 1.0.10
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 2c97db6: Keep authentication status and access token in sync
|
||||||
|
The authentication events where not set correctly, leading the main Nhost client not to update internal states of storage/graphql/functions sub-clients when using non-react clients.
|
||||||
|
The use of private fields (`#`) is also avoided as they conflict with the use of proxies in Vue, leading to errors in the upcoming Vue library.
|
||||||
|
Fixes #373 and #378
|
||||||
|
- Updated dependencies [2c97db6]
|
||||||
|
- @nhost/core@0.3.9
|
||||||
|
|
||||||
|
## 1.0.9
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 058956b: Add missing provider types
|
||||||
|
`strava`, `gitlab`, and `bitbucket` were missing from the list of providers in Typescript and are now available.
|
||||||
|
- 058956b: Add `emailVerified`, `phoneNumber`, `phoneNumberVerified`, and `activeMfaType` to User type
|
||||||
|
|
||||||
|
Some information is missing in the `User` payload (see [this issue](https://github.com/nhost/nhost/issues/306)). The above properties have been added in the Typescript `User` type and are available when using Hasura Auth versions from [this pull request](https://github.com/nhost/hasura-auth/pull/128) (tentative version number: `0.5.1`)
|
||||||
|
|
||||||
|
- Updated dependencies [058956b]
|
||||||
|
- Updated dependencies [7cf875f]
|
||||||
|
- @nhost/core@0.3.8
|
||||||
|
|
||||||
|
## 1.0.8
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 6be3758: bug: Correct OAuth provider link.
|
||||||
|
|
||||||
|
## 1.0.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [16a6c50]
|
||||||
|
- @nhost/core@0.3.4
|
||||||
|
|
||||||
|
## 1.0.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- correct dependencies
|
||||||
|
|
||||||
|
See this related issues:
|
||||||
|
|
||||||
|
- [nhost](https://github.com/nhost/nhost/issues/326)
|
||||||
|
- [pnpm](https://github.com/pnpm/pnpm/issues/4348)
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @nhost/core@0.3.2
|
||||||
|
|
||||||
## 1.0.2
|
## 1.0.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
@@ -41,7 +106,6 @@
|
|||||||
2. hasura-auth validates the link, attaches the token and redirects to the frontend
|
2. hasura-auth validates the link, attaches the token and redirects to the frontend
|
||||||
3. the sdk gets the refresh token from the url
|
3. the sdk gets the refresh token from the url
|
||||||
4. the sdk consumes the refresh token
|
4. the sdk consumes the refresh token
|
||||||
- Updated dependencies [744fd69]
|
|
||||||
- Updated dependencies [744fd69]
|
- Updated dependencies [744fd69]
|
||||||
- @nhost/core@0.3.0
|
- @nhost/core@0.3.0
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/hasura-auth-js",
|
"name": "@nhost/hasura-auth-js",
|
||||||
"version": "1.0.2",
|
"version": "1.0.11",
|
||||||
"description": "Hasura-auth client",
|
"description": "Hasura-auth client",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -53,9 +53,7 @@ const EMAIL_NEEDS_VERIFICATION: ApiError = {
|
|||||||
status: 102
|
status: 102
|
||||||
}
|
}
|
||||||
export class HasuraAuthClient {
|
export class HasuraAuthClient {
|
||||||
#client: AuthClient
|
private _client: AuthClient
|
||||||
private onTokenChangedSubscriptions: Set<AuthInterpreter> = new Set()
|
|
||||||
private onAuthStateChangedSubscriptions: Set<AuthInterpreter> = new Set()
|
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
url,
|
url,
|
||||||
@@ -69,7 +67,7 @@ export class HasuraAuthClient {
|
|||||||
start = true,
|
start = true,
|
||||||
Client = AuthClient
|
Client = AuthClient
|
||||||
}: NhostAuthConstructorParams) {
|
}: NhostAuthConstructorParams) {
|
||||||
this.#client = new Client({
|
this._client = new Client({
|
||||||
backendUrl: url,
|
backendUrl: url,
|
||||||
autoRefreshToken,
|
autoRefreshToken,
|
||||||
autoSignIn: autoLogin,
|
autoSignIn: autoLogin,
|
||||||
@@ -157,8 +155,8 @@ export class HasuraAuthClient {
|
|||||||
if ('provider' in params) {
|
if ('provider' in params) {
|
||||||
const { provider, options } = params
|
const { provider, options } = params
|
||||||
const providerUrl = encodeQueryParameters(
|
const providerUrl = encodeQueryParameters(
|
||||||
`${this.#client.backendUrl}/v1/auth/signin/provider/${provider}`,
|
`${this._client.backendUrl}/signin/provider/${provider}`,
|
||||||
rewriteRedirectTo(this.#client.clientUrl, options)
|
rewriteRedirectTo(this._client.clientUrl, options)
|
||||||
)
|
)
|
||||||
if (isBrowser()) {
|
if (isBrowser()) {
|
||||||
window.location.href = providerUrl
|
window.location.href = providerUrl
|
||||||
@@ -301,7 +299,7 @@ export class HasuraAuthClient {
|
|||||||
*/
|
*/
|
||||||
async resetPassword({ email, options }: ResetPasswordParams): Promise<ApiResetPasswordResponse> {
|
async resetPassword({ email, options }: ResetPasswordParams): Promise<ApiResetPasswordResponse> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const service = interpret(createResetPasswordMachine(this.#client))
|
const service = interpret(createResetPasswordMachine(this._client))
|
||||||
service.onTransition(({ event }) => {
|
service.onTransition(({ event }) => {
|
||||||
if (event.type === 'ERROR') return resolve({ error: event.error })
|
if (event.type === 'ERROR') return resolve({ error: event.error })
|
||||||
else if (event.type === 'SUCCESS') return resolve({ error: null })
|
else if (event.type === 'SUCCESS') return resolve({ error: null })
|
||||||
@@ -321,7 +319,7 @@ export class HasuraAuthClient {
|
|||||||
*/
|
*/
|
||||||
async changePassword(params: ChangePasswordParams): Promise<ApiChangePasswordResponse> {
|
async changePassword(params: ChangePasswordParams): Promise<ApiChangePasswordResponse> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const service = interpret(createChangePasswordMachine(this.#client))
|
const service = interpret(createChangePasswordMachine(this._client))
|
||||||
service.onTransition(({ event }) => {
|
service.onTransition(({ event }) => {
|
||||||
if (event.type === 'ERROR') return resolve({ error: event.error })
|
if (event.type === 'ERROR') return resolve({ error: event.error })
|
||||||
else if (event.type === 'SUCCESS') return resolve({ error: null })
|
else if (event.type === 'SUCCESS') return resolve({ error: null })
|
||||||
@@ -344,7 +342,7 @@ export class HasuraAuthClient {
|
|||||||
params: SendVerificationEmailParams
|
params: SendVerificationEmailParams
|
||||||
): Promise<ApiSendVerificationEmailResponse> {
|
): Promise<ApiSendVerificationEmailResponse> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const service = interpret(createSendVerificationEmailMachine(this.#client))
|
const service = interpret(createSendVerificationEmailMachine(this._client))
|
||||||
service.onTransition(({ event }) => {
|
service.onTransition(({ event }) => {
|
||||||
if (event.type === 'ERROR') return resolve({ error: event.error })
|
if (event.type === 'ERROR') return resolve({ error: event.error })
|
||||||
else if (event.type === 'SUCCESS') return resolve({ error: null })
|
else if (event.type === 'SUCCESS') return resolve({ error: null })
|
||||||
@@ -364,7 +362,7 @@ export class HasuraAuthClient {
|
|||||||
*/
|
*/
|
||||||
async changeEmail({ newEmail, options }: ChangeEmailParams): Promise<ApiChangeEmailResponse> {
|
async changeEmail({ newEmail, options }: ChangeEmailParams): Promise<ApiChangeEmailResponse> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const service = interpret(createChangeEmailMachine(this.#client))
|
const service = interpret(createChangeEmailMachine(this._client))
|
||||||
service.onTransition(({ event }) => {
|
service.onTransition(({ event }) => {
|
||||||
if (event.type === 'ERROR') return resolve({ error: event.error })
|
if (event.type === 'ERROR') return resolve({ error: event.error })
|
||||||
else if (event.type === 'SUCCESS') return resolve({ error: null })
|
else if (event.type === 'SUCCESS') return resolve({ error: null })
|
||||||
@@ -414,17 +412,23 @@ export class HasuraAuthClient {
|
|||||||
* @docs https://docs.nhost.io/TODO
|
* @docs https://docs.nhost.io/TODO
|
||||||
*/
|
*/
|
||||||
onTokenChanged(fn: OnTokenChangedFunction): Function {
|
onTokenChanged(fn: OnTokenChangedFunction): Function {
|
||||||
if (this.#client.interpreter)
|
const listen = (interpreter: AuthInterpreter) =>
|
||||||
this.onTokenChangedSubscriptions.add(
|
interpreter.onTransition(({ event, context }) => {
|
||||||
this.#client.interpreter?.onTransition(({ event, context }) => {
|
if (event.type === 'TOKEN_CHANGED') fn(getSession(context))
|
||||||
if (event.type === 'TOKEN_CHANGED') fn(getSession(context))
|
})
|
||||||
})
|
|
||||||
)
|
if (this._client.interpreter) {
|
||||||
else {
|
const subscription = listen(this._client.interpreter)
|
||||||
console.log('onTokenChanged: no interpreter is set yet', fn)
|
return () => subscription.stop()
|
||||||
}
|
} else {
|
||||||
return () => {
|
this._client.onStart((client) => {
|
||||||
this.onTokenChangedSubscriptions.forEach((subscription) => subscription.stop())
|
listen(client.interpreter as AuthInterpreter)
|
||||||
|
})
|
||||||
|
return () => {
|
||||||
|
console.log(
|
||||||
|
'onTokenChanged was added before the interpreter started. Cannot unsubscribe listener.'
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,18 +445,23 @@ export class HasuraAuthClient {
|
|||||||
* @docs https://docs.nhost.io/reference/sdk/authentication#nhost-auth-onauthstatechangedevent,-session
|
* @docs https://docs.nhost.io/reference/sdk/authentication#nhost-auth-onauthstatechangedevent,-session
|
||||||
*/
|
*/
|
||||||
onAuthStateChanged(fn: AuthChangedFunction): Function {
|
onAuthStateChanged(fn: AuthChangedFunction): Function {
|
||||||
if (this.#client.interpreter)
|
const listen = (interpreter: AuthInterpreter) =>
|
||||||
this.onAuthStateChangedSubscriptions.add(
|
interpreter.onTransition(({ event, context }) => {
|
||||||
this.#client.interpreter?.onTransition(({ event, context }) => {
|
if (event.type === 'SIGNED_IN' || event.type === 'SIGNED_OUT')
|
||||||
if (event.type === 'SIGNED_IN') fn('SIGNED_IN', getSession(context))
|
fn(event.type, getSession(context))
|
||||||
else if (event.type === 'SIGNED_OUT') fn('SIGNED_OUT', getSession(context))
|
})
|
||||||
})
|
if (this._client.interpreter) {
|
||||||
)
|
const subscription = listen(this._client.interpreter)
|
||||||
else {
|
return () => subscription.stop()
|
||||||
console.log('onAuthStateChanged: no interpreter is set yet', fn)
|
} else {
|
||||||
}
|
this._client.onStart((client) => {
|
||||||
return () => {
|
listen(client.interpreter as AuthInterpreter)
|
||||||
this.onAuthStateChangedSubscriptions.forEach((subscription) => subscription.stop())
|
})
|
||||||
|
return () => {
|
||||||
|
console.log(
|
||||||
|
'onAuthStateChanged was added before the interpreter started. Cannot unsubscribe listener.'
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,7 +483,7 @@ export class HasuraAuthClient {
|
|||||||
* @docs https://docs.nhost.io/TODO
|
* @docs https://docs.nhost.io/TODO
|
||||||
*/
|
*/
|
||||||
isAuthenticated(): boolean {
|
isAuthenticated(): boolean {
|
||||||
return !!this.#client.interpreter?.state.matches({ authentication: 'signedIn' })
|
return !!this._client.interpreter?.state.matches({ authentication: 'signedIn' })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -543,7 +552,7 @@ export class HasuraAuthClient {
|
|||||||
* @docs https://docs.nhost.io/TODO
|
* @docs https://docs.nhost.io/TODO
|
||||||
*/
|
*/
|
||||||
getAccessToken(): string | undefined {
|
getAccessToken(): string | undefined {
|
||||||
return this.#client.interpreter?.state.context.accessToken.value ?? undefined
|
return this._client.interpreter?.state.context.accessToken.value ?? undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -590,7 +599,7 @@ export class HasuraAuthClient {
|
|||||||
* @docs https://docs.nhost.io/TODO
|
* @docs https://docs.nhost.io/TODO
|
||||||
*/
|
*/
|
||||||
getSession() {
|
getSession() {
|
||||||
return getSession(this.#client.interpreter?.state?.context)
|
return getSession(this._client.interpreter?.state?.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -604,7 +613,7 @@ export class HasuraAuthClient {
|
|||||||
* @docs https://docs.nhost.io/reference/sdk/authentication#nhost-auth-getuser
|
* @docs https://docs.nhost.io/reference/sdk/authentication#nhost-auth-getuser
|
||||||
*/
|
*/
|
||||||
getUser() {
|
getUser() {
|
||||||
return this.#client.interpreter?.state?.context?.user || null
|
return this._client.interpreter?.state?.context?.user || null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -613,7 +622,7 @@ export class HasuraAuthClient {
|
|||||||
*/
|
*/
|
||||||
private waitUntilReady(): Promise<AuthInterpreter> {
|
private waitUntilReady(): Promise<AuthInterpreter> {
|
||||||
const TIMEOUT_IN_SECONS = 15
|
const TIMEOUT_IN_SECONS = 15
|
||||||
const interpreter = this.#client.interpreter
|
const interpreter = this._client.interpreter
|
||||||
if (!interpreter) {
|
if (!interpreter) {
|
||||||
throw Error('Auth interpreter not set')
|
throw Error('Auth interpreter not set')
|
||||||
}
|
}
|
||||||
@@ -633,10 +642,10 @@ export class HasuraAuthClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private isReady() {
|
private isReady() {
|
||||||
return !!this.#client.interpreter?.state?.hasTag('ready')
|
return !!this._client.interpreter?.state?.hasTag('ready')
|
||||||
}
|
}
|
||||||
|
|
||||||
get client() {
|
get client() {
|
||||||
return this.#client
|
return this._client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,30 @@
|
|||||||
import { AuthClient, StorageGetter, StorageSetter, User } from '@nhost/core'
|
import {
|
||||||
|
AuthClient,
|
||||||
|
PasswordlessOptions,
|
||||||
|
Provider,
|
||||||
|
ProviderOptions,
|
||||||
|
RedirectOption,
|
||||||
|
SignUpOptions,
|
||||||
|
StorageGetter,
|
||||||
|
StorageSetter,
|
||||||
|
User
|
||||||
|
} from '@nhost/core'
|
||||||
|
export type { AuthClient, Provider, StorageGetter, StorageSetter, User }
|
||||||
export interface NhostAuthConstructorParams {
|
export interface NhostAuthConstructorParams {
|
||||||
url: string
|
url: string
|
||||||
|
/** Time interval until token refreshes, in seconds */
|
||||||
refreshIntervalTime?: number
|
refreshIntervalTime?: number
|
||||||
/** @deprecated Use clientStorageGetter and clientStorageSetter options instead */
|
/** @deprecated Use clientStorageGetter and clientStorageSetter options instead */
|
||||||
clientStorage?: ClientStorage
|
clientStorage?: ClientStorage
|
||||||
/** @deprecated Use clientStorageGetter and clientStorageSetter options instead */
|
/** @deprecated Use clientStorageGetter and clientStorageSetter options instead */
|
||||||
clientStorageType?: ClientStorageType
|
clientStorageType?: ClientStorageType
|
||||||
|
/** Define a way to get information about the refresh token and its exipration date */
|
||||||
clientStorageGetter?: StorageGetter
|
clientStorageGetter?: StorageGetter
|
||||||
|
/** Define a way to set information about the refresh token and its exipration date */
|
||||||
clientStorageSetter?: StorageSetter
|
clientStorageSetter?: StorageSetter
|
||||||
|
/** When set to true, will automatically refresh token before it expires */
|
||||||
autoRefreshToken?: boolean
|
autoRefreshToken?: boolean
|
||||||
|
/** When set to true, will parse the url on startup to check if it contains a refresh token to start the session with */
|
||||||
autoLogin?: boolean
|
autoLogin?: boolean
|
||||||
start?: boolean
|
start?: boolean
|
||||||
Client?: typeof AuthClient
|
Client?: typeof AuthClient
|
||||||
@@ -30,14 +45,7 @@ export interface ApiError {
|
|||||||
export interface SignUpEmailPasswordParams {
|
export interface SignUpEmailPasswordParams {
|
||||||
email: string
|
email: string
|
||||||
password: string
|
password: string
|
||||||
options?: {
|
options?: SignUpOptions
|
||||||
locale?: string
|
|
||||||
allowedRoles?: string[]
|
|
||||||
defaultRole?: string
|
|
||||||
displayName?: string
|
|
||||||
redirectTo?: string
|
|
||||||
metadata?: Record<string, unknown>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SignUpParams = SignUpEmailPasswordParams
|
export type SignUpParams = SignUpEmailPasswordParams
|
||||||
@@ -54,55 +62,21 @@ export interface SignInEmailPasswordParams {
|
|||||||
|
|
||||||
export interface SignInPasswordlessEmailParams {
|
export interface SignInPasswordlessEmailParams {
|
||||||
email: string
|
email: string
|
||||||
options?: {
|
options?: PasswordlessOptions
|
||||||
locale?: string
|
|
||||||
allowedRoles?: string[]
|
|
||||||
defaultRole?: string
|
|
||||||
displayName?: string
|
|
||||||
redirectTo?: string
|
|
||||||
metadata?: Record<string, unknown>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SignInPasswordlessSmsParams {
|
export interface SignInPasswordlessSmsParams {
|
||||||
phoneNumber: string
|
phoneNumber: string
|
||||||
options?: {
|
options?: PasswordlessOptions
|
||||||
locale?: string
|
|
||||||
allowedRoles?: string[]
|
|
||||||
defaultRole?: string
|
|
||||||
displayName?: string
|
|
||||||
redirectTo?: string
|
|
||||||
metadata?: Record<string, unknown>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SignInPasswordlessSmsOtpParams {
|
export interface SignInPasswordlessSmsOtpParams {
|
||||||
phoneNumber: string
|
phoneNumber: string
|
||||||
otp: string
|
otp: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Provider =
|
|
||||||
| 'facebook'
|
|
||||||
| 'github'
|
|
||||||
| 'google'
|
|
||||||
| 'linkedin'
|
|
||||||
| 'spotify'
|
|
||||||
| 'discord'
|
|
||||||
| 'twitch'
|
|
||||||
| 'apple'
|
|
||||||
| 'twitter'
|
|
||||||
| 'windowslive'
|
|
||||||
|
|
||||||
export interface SignInWithProviderOptions {
|
export interface SignInWithProviderOptions {
|
||||||
provider: Provider
|
provider: Provider
|
||||||
options?: {
|
options?: ProviderOptions
|
||||||
locale?: string
|
|
||||||
allowedRoles?: string[]
|
|
||||||
defaultRole?: string
|
|
||||||
displayName?: string
|
|
||||||
redirectTo?: string
|
|
||||||
metadata?: Record<string, unknown>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SignInParams =
|
export type SignInParams =
|
||||||
@@ -125,18 +99,15 @@ export interface ChangePasswordParams {
|
|||||||
|
|
||||||
export interface SendVerificationEmailParams {
|
export interface SendVerificationEmailParams {
|
||||||
email: string
|
email: string
|
||||||
options?: {
|
options?: RedirectOption
|
||||||
redirectTo?: string
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChangeEmailParams {
|
export interface ChangeEmailParams {
|
||||||
newEmail: string
|
newEmail: string
|
||||||
options?: {
|
options?: RedirectOption
|
||||||
redirectTo?: string
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO define type in @nhost/core
|
||||||
export interface DeanonymizeParams {
|
export interface DeanonymizeParams {
|
||||||
signInMethod: 'email-password' | 'passwordless'
|
signInMethod: 'email-password' | 'passwordless'
|
||||||
email: string
|
email: string
|
||||||
|
|||||||
@@ -1,5 +1,59 @@
|
|||||||
# @nhost/nextjs
|
# @nhost/nextjs
|
||||||
|
|
||||||
|
## 1.0.12
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@1.0.11
|
||||||
|
- @nhost/react@0.5.2
|
||||||
|
|
||||||
|
## 1.0.11
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [2c97db6]
|
||||||
|
- @nhost/nhost-js@1.0.10
|
||||||
|
- @nhost/react@0.5.1
|
||||||
|
|
||||||
|
## 1.0.10
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [7cf875f]
|
||||||
|
- Updated dependencies [7135aee]
|
||||||
|
- Updated dependencies [587eaff]
|
||||||
|
- @nhost/react@0.5.0
|
||||||
|
- @nhost/nhost-js@1.0.9
|
||||||
|
|
||||||
|
## 1.0.9
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@1.0.8
|
||||||
|
- @nhost/react@0.4.7
|
||||||
|
|
||||||
|
## 1.0.8
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@1.0.5
|
||||||
|
- @nhost/react@0.4.4
|
||||||
|
|
||||||
|
## 1.0.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- correct dependencies
|
||||||
|
|
||||||
|
See this related issues:
|
||||||
|
|
||||||
|
- [nhost](https://github.com/nhost/nhost/issues/326)
|
||||||
|
- [pnpm](https://github.com/pnpm/pnpm/issues/4348)
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @nhost/nhost-js@1.0.3
|
||||||
|
- @nhost/react@0.4.2
|
||||||
|
|
||||||
## 1.0.3
|
## 1.0.3
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/nextjs",
|
"name": "@nhost/nextjs",
|
||||||
"version": "1.0.3",
|
"version": "1.0.12",
|
||||||
"description": "Nhost NextJS library",
|
"description": "Nhost NextJS library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -1,5 +1,59 @@
|
|||||||
# @nhost/nhost-js
|
# @nhost/nhost-js
|
||||||
|
|
||||||
|
## 1.0.11
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [63d6059]
|
||||||
|
- Updated dependencies [63d6059]
|
||||||
|
- Updated dependencies [63d6059]
|
||||||
|
- @nhost/hasura-auth-js@1.0.11
|
||||||
|
|
||||||
|
## 1.0.10
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 2c97db6: Keep authentication status and access token in sync
|
||||||
|
The authentication events where not set correctly, leading the main Nhost client not to update internal states of storage/graphql/functions sub-clients when using non-react clients.
|
||||||
|
The use of private fields (`#`) is also avoided as they conflict with the use of proxies in Vue, leading to errors in the upcoming Vue library.
|
||||||
|
Fixes #373 and #378
|
||||||
|
- Updated dependencies [2c97db6]
|
||||||
|
- @nhost/hasura-auth-js@1.0.10
|
||||||
|
|
||||||
|
## 1.0.9
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [058956b]
|
||||||
|
- @nhost/hasura-auth-js@1.0.9
|
||||||
|
|
||||||
|
## 1.0.8
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [6be3758]
|
||||||
|
- @nhost/hasura-auth-js@1.0.8
|
||||||
|
|
||||||
|
## 1.0.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/hasura-auth-js@1.0.5
|
||||||
|
|
||||||
|
## 1.0.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- correct dependencies
|
||||||
|
|
||||||
|
See this related issues:
|
||||||
|
|
||||||
|
- [nhost](https://github.com/nhost/nhost/issues/326)
|
||||||
|
- [pnpm](https://github.com/pnpm/pnpm/issues/4348)
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @nhost/hasura-auth-js@1.0.3
|
||||||
|
|
||||||
## 1.0.2
|
## 1.0.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
@@ -32,8 +86,6 @@
|
|||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
||||||
- Updated dependencies [744fd69]
|
|
||||||
- Updated dependencies [744fd69]
|
|
||||||
- Updated dependencies [744fd69]
|
- Updated dependencies [744fd69]
|
||||||
- @nhost/hasura-auth-js@1.0.0
|
- @nhost/hasura-auth-js@1.0.0
|
||||||
- @nhost/hasura-storage-js@0.2.0
|
- @nhost/hasura-storage-js@0.2.0
|
||||||
@@ -53,7 +105,6 @@
|
|||||||
Some systems based on older versions of Webpack or Babel don't support the current esbuild configuration e.g, [this issue](https://github.com/nhost/nhost/issues/275).
|
Some systems based on older versions of Webpack or Babel don't support the current esbuild configuration e.g, [this issue](https://github.com/nhost/nhost/issues/275).
|
||||||
- Updated dependencies [e688600]
|
- Updated dependencies [e688600]
|
||||||
- Updated dependencies [8f7643a]
|
- Updated dependencies [8f7643a]
|
||||||
- Updated dependencies [e688600]
|
|
||||||
- Updated dependencies [50b9d76]
|
- Updated dependencies [50b9d76]
|
||||||
- @nhost/hasura-auth-js@0.1.15
|
- @nhost/hasura-auth-js@0.1.15
|
||||||
- @nhost/hasura-storage-js@0.0.12
|
- @nhost/hasura-storage-js@0.0.12
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/nhost-js",
|
"name": "@nhost/nhost-js",
|
||||||
"version": "1.0.2",
|
"version": "1.0.11",
|
||||||
"description": "Nhost JavaScript SDK",
|
"description": "Nhost JavaScript SDK",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -60,20 +60,22 @@ export class NhostClient {
|
|||||||
url: `${backendUrl}/v1/graphql`
|
url: `${backendUrl}/v1/graphql`
|
||||||
})
|
})
|
||||||
|
|
||||||
// set current token if token is already accessable
|
// * Set current token if token is already accessable
|
||||||
this.storage.setAccessToken(this.auth.getAccessToken())
|
this.storage.setAccessToken(this.auth.getAccessToken())
|
||||||
this.functions.setAccessToken(this.auth.getAccessToken())
|
this.functions.setAccessToken(this.auth.getAccessToken())
|
||||||
this.graphql.setAccessToken(this.auth.getAccessToken())
|
this.graphql.setAccessToken(this.auth.getAccessToken())
|
||||||
|
|
||||||
this.auth.client.onStart(() => {
|
this.auth.client.onStart(() => {
|
||||||
// update access token for clients
|
// * Set access token when signing out
|
||||||
this.auth.onAuthStateChanged((_event, session) => {
|
this.auth.onAuthStateChanged((_event, session) => {
|
||||||
this.storage.setAccessToken(session?.accessToken)
|
if (_event === 'SIGNED_OUT') {
|
||||||
this.functions.setAccessToken(session?.accessToken)
|
this.storage.setAccessToken(undefined)
|
||||||
this.graphql.setAccessToken(session?.accessToken)
|
this.functions.setAccessToken(undefined)
|
||||||
|
this.graphql.setAccessToken(undefined)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// update access token for clients
|
// * Update access token for clients, including when signin in
|
||||||
this.auth.onTokenChanged((session) => {
|
this.auth.onTokenChanged((session) => {
|
||||||
this.storage.setAccessToken(session?.accessToken)
|
this.storage.setAccessToken(session?.accessToken)
|
||||||
this.functions.setAccessToken(session?.accessToken)
|
this.functions.setAccessToken(session?.accessToken)
|
||||||
|
|||||||
@@ -1,5 +1,59 @@
|
|||||||
# @nhost/react-apollo
|
# @nhost/react-apollo
|
||||||
|
|
||||||
|
## 4.0.12
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@0.5.2
|
||||||
|
- @nhost/apollo@0.3.9
|
||||||
|
|
||||||
|
## 4.0.11
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 8583af8: correct documentation link in readme
|
||||||
|
- @nhost/apollo@0.3.8
|
||||||
|
- @nhost/react@0.5.1
|
||||||
|
|
||||||
|
## 4.0.10
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [7cf875f]
|
||||||
|
- Updated dependencies [7135aee]
|
||||||
|
- Updated dependencies [587eaff]
|
||||||
|
- @nhost/react@0.5.0
|
||||||
|
- @nhost/apollo@0.3.7
|
||||||
|
|
||||||
|
## 4.0.9
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/react@0.4.7
|
||||||
|
- @nhost/apollo@0.3.6
|
||||||
|
|
||||||
|
## 4.0.8
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/apollo@0.3.4
|
||||||
|
- @nhost/react@0.4.4
|
||||||
|
|
||||||
|
## 4.0.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- correct dependencies
|
||||||
|
|
||||||
|
See this related issues:
|
||||||
|
|
||||||
|
- [nhost](https://github.com/nhost/nhost/issues/326)
|
||||||
|
- [pnpm](https://github.com/pnpm/pnpm/issues/4348)
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @nhost/apollo@0.3.2
|
||||||
|
- @nhost/react@0.4.2
|
||||||
|
|
||||||
## 4.0.3
|
## 4.0.3
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -38,4 +38,4 @@ ReactDOM.render(
|
|||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
[https://docs.nhost.io/reference/supporting-libraries/react-apollo](https://docs.nhost.io/reference/supporting-libraries/react-apollo)
|
[https://docs.nhost.io/reference/react/apollo](https://docs.nhost.io/reference/react/apollo)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/react-apollo",
|
"name": "@nhost/react-apollo",
|
||||||
"version": "4.0.3",
|
"version": "4.0.12",
|
||||||
"description": "Nhost React Apollo client",
|
"description": "Nhost React Apollo client",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -1,5 +1,96 @@
|
|||||||
# @nhost/react
|
# @nhost/react
|
||||||
|
|
||||||
|
## 0.5.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@1.0.11
|
||||||
|
|
||||||
|
## 0.5.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [2c97db6]
|
||||||
|
- @nhost/nhost-js@1.0.10
|
||||||
|
|
||||||
|
## 0.5.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- 7135aee: Add user and accessToken to authentication hooks
|
||||||
|
|
||||||
|
Hooks that can complete a successful authentication now have two additional `user` and `accessToken` exported states:
|
||||||
|
|
||||||
|
- `useSignInEmailPassword`
|
||||||
|
- `useSignInAnonymous`
|
||||||
|
- `useSignUpEmailPassword`
|
||||||
|
|
||||||
|
- 587eaff: Return a promise with the current context to hooks actions
|
||||||
|
It is now possible to get the result of an action. Hook handlers return the action context in a promise.
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
const { signInEmailPasswordless, isError } = useSignInEmailPasswordless()
|
||||||
|
const MyComponent = () => {
|
||||||
|
return <div>
|
||||||
|
<button onClick={async () => {
|
||||||
|
const { isSuccess, isError, error } = await signInEmailPasswordless('johan@ikea.se')
|
||||||
|
if (isError) {
|
||||||
|
console.log(error)
|
||||||
|
}}}/>
|
||||||
|
{isError && <div>an error occurred</div>}
|
||||||
|
<div>
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 7cf875f: Deprecate the use of values sent as hook parameters
|
||||||
|
|
||||||
|
Although handlers parameters of authentication hooks can be given when creating the hook, it is recommended to use them when executing the handler. For instance, instead of:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { signInEmailPasswordless } = useSignInEmailPasswordless('nuno@fcporto.pt')
|
||||||
|
signInEmailPasswordless()
|
||||||
|
```
|
||||||
|
|
||||||
|
It is recommended to use the following syntax:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { signInEmailPasswordless } = useSignInEmailPasswordless()
|
||||||
|
signInEmailPasswordless('nuno@fcporto.pt')
|
||||||
|
```
|
||||||
|
|
||||||
|
No breaking change has been introduced. For instance, `useSignUpEmailPassword('szilard@brussels.be','1234', options)` will appear as deprecated but will work, while `useSignUpEmailPassword(options)` will work too.
|
||||||
|
|
||||||
|
- @nhost/nhost-js@1.0.9
|
||||||
|
|
||||||
|
## 0.4.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@1.0.8
|
||||||
|
|
||||||
|
## 0.4.6
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @nhost/nhost-js@1.0.5
|
||||||
|
|
||||||
|
## 0.4.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- correct dependencies
|
||||||
|
|
||||||
|
See this related issues:
|
||||||
|
|
||||||
|
- [nhost](https://github.com/nhost/nhost/issues/326)
|
||||||
|
- [pnpm](https://github.com/pnpm/pnpm/issues/4348)
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @nhost/nhost-js@1.0.3
|
||||||
|
|
||||||
## 0.4.1
|
## 0.4.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/react",
|
"name": "@nhost/react",
|
||||||
"version": "0.4.1",
|
"version": "0.5.2",
|
||||||
"description": "Nhost React library",
|
"description": "Nhost React library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -5,35 +5,123 @@ import {
|
|||||||
PasswordlessOptions,
|
PasswordlessOptions,
|
||||||
Provider,
|
Provider,
|
||||||
ProviderOptions,
|
ProviderOptions,
|
||||||
rewriteRedirectTo
|
rewriteRedirectTo,
|
||||||
|
User
|
||||||
} from '@nhost/core'
|
} from '@nhost/core'
|
||||||
import { useSelector } from '@xstate/react'
|
import { useSelector } from '@xstate/react'
|
||||||
|
|
||||||
import { NhostReactContext } from '../provider'
|
import { NhostReactContext } from '../provider'
|
||||||
|
|
||||||
import { useAuthenticated, useAuthInterpreter } from './common'
|
import { ActionHookState, useAuthenticated, useAuthInterpreter } from './common'
|
||||||
|
|
||||||
export const useSignInEmailPassword = (
|
type SignInEmailPasswordHookState = ActionHookState & {
|
||||||
|
needsMfaOtp: boolean
|
||||||
|
needsEmailVerification: boolean
|
||||||
|
user: User | null
|
||||||
|
accessToken: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
type SignInEmailPasswordHandlerResult = Omit<SignInEmailPasswordHookState, 'isLoading'>
|
||||||
|
|
||||||
|
type SignInEmailPasswordHandler = {
|
||||||
|
(email: string, password: string): Promise<SignInEmailPasswordHandlerResult>
|
||||||
|
/** @deprecated */
|
||||||
|
(email?: unknown, password?: string): Promise<SignInEmailPasswordHandlerResult>
|
||||||
|
}
|
||||||
|
|
||||||
|
type SendMfaOtpHander = {
|
||||||
|
(otp: string): void
|
||||||
|
/** @deprecated */
|
||||||
|
(otp?: unknown): void
|
||||||
|
}
|
||||||
|
|
||||||
|
type SignInEmailPasswordHookResult = {
|
||||||
|
signInEmailPassword: SignInEmailPasswordHandler
|
||||||
|
sendMfaOtp: SendMfaOtpHander
|
||||||
|
} & SignInEmailPasswordHookState
|
||||||
|
|
||||||
|
type SignInEmailPasswordHook = {
|
||||||
|
(): SignInEmailPasswordHookResult
|
||||||
|
/** @deprecated */
|
||||||
|
(email?: string, password?: string, otp?: string): SignInEmailPasswordHookResult
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSignInEmailPassword: SignInEmailPasswordHook = (
|
||||||
stateEmail?: string,
|
stateEmail?: string,
|
||||||
statePassword?: string,
|
statePassword?: string,
|
||||||
stateOtp?: string
|
stateOtp?: string
|
||||||
) => {
|
) => {
|
||||||
const service = useAuthInterpreter()
|
const service = useAuthInterpreter()
|
||||||
const signInEmailPassword = (valueEmail?: string | unknown, valuePassword?: string | unknown) =>
|
const signInEmailPassword: SignInEmailPasswordHandler = (
|
||||||
service.send({
|
valueEmail?: string | unknown,
|
||||||
type: 'SIGNIN_PASSWORD',
|
valuePassword?: string
|
||||||
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
) =>
|
||||||
password: typeof valuePassword === 'string' ? valuePassword : statePassword
|
new Promise<SignInEmailPasswordHandlerResult>((resolve) => {
|
||||||
|
service.send({
|
||||||
|
type: 'SIGNIN_PASSWORD',
|
||||||
|
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
||||||
|
password: typeof valuePassword === 'string' ? valuePassword : statePassword
|
||||||
|
})
|
||||||
|
service.onTransition((state) => {
|
||||||
|
if (state.matches({ authentication: { signedOut: 'needsEmailVerification' } })) {
|
||||||
|
resolve({
|
||||||
|
accessToken: null,
|
||||||
|
error: null,
|
||||||
|
isError: false,
|
||||||
|
isSuccess: false,
|
||||||
|
needsEmailVerification: true,
|
||||||
|
needsMfaOtp: false,
|
||||||
|
user: null
|
||||||
|
})
|
||||||
|
} else if (state.matches({ authentication: { signedOut: 'needsMfa' } })) {
|
||||||
|
resolve({
|
||||||
|
accessToken: null,
|
||||||
|
error: null,
|
||||||
|
isError: false,
|
||||||
|
isSuccess: false,
|
||||||
|
needsEmailVerification: false,
|
||||||
|
needsMfaOtp: true,
|
||||||
|
user: null
|
||||||
|
})
|
||||||
|
} else if (state.matches({ authentication: { signedOut: 'failed' } })) {
|
||||||
|
resolve({
|
||||||
|
accessToken: null,
|
||||||
|
error: state.context.errors.authentication || null,
|
||||||
|
isError: true,
|
||||||
|
isSuccess: false,
|
||||||
|
needsEmailVerification: false,
|
||||||
|
needsMfaOtp: false,
|
||||||
|
user: null
|
||||||
|
})
|
||||||
|
} else if (state.matches({ authentication: 'signedIn' })) {
|
||||||
|
resolve({
|
||||||
|
accessToken: state.context.accessToken.value,
|
||||||
|
error: null,
|
||||||
|
isError: false,
|
||||||
|
isSuccess: true,
|
||||||
|
needsEmailVerification: false,
|
||||||
|
needsMfaOtp: false,
|
||||||
|
user: state.context.user
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
const sendMfaOtp = (valueOtp?: string | unknown) => {
|
|
||||||
|
const sendMfaOtp: SendMfaOtpHander = (valueOtp?: string | unknown) => {
|
||||||
service.send({
|
service.send({
|
||||||
type: 'SIGNIN_MFA_TOTP',
|
type: 'SIGNIN_MFA_TOTP',
|
||||||
otp: typeof valueOtp === 'string' ? valueOtp : stateOtp
|
otp: typeof valueOtp === 'string' ? valueOtp : stateOtp
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const user = useSelector(
|
||||||
|
service,
|
||||||
|
(state) => state.context.user,
|
||||||
|
(a, b) => a?.id === b?.id
|
||||||
|
)
|
||||||
|
const accessToken = useSelector(service, (state) => state.context.accessToken.value)
|
||||||
const error = useSelector(
|
const error = useSelector(
|
||||||
service,
|
service,
|
||||||
(state) => state.context.errors.authentication,
|
(state) => state.context.errors.authentication || null,
|
||||||
(a, b) => a?.error === b?.error
|
(a, b) => a?.error === b?.error
|
||||||
)
|
)
|
||||||
const isSuccess = useAuthenticated()
|
const isSuccess = useAuthenticated()
|
||||||
@@ -59,32 +147,70 @@ export const useSignInEmailPassword = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
signInEmailPassword,
|
accessToken,
|
||||||
|
error,
|
||||||
|
isError,
|
||||||
isLoading,
|
isLoading,
|
||||||
isSuccess,
|
isSuccess,
|
||||||
needsEmailVerification,
|
needsEmailVerification,
|
||||||
needsMfaOtp,
|
needsMfaOtp,
|
||||||
sendMfaOtp,
|
sendMfaOtp,
|
||||||
isError,
|
signInEmailPassword,
|
||||||
error
|
user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useSignInEmailPasswordless = (
|
type SignInEmailPasswordlessHandlerResult = Omit<ActionHookState, 'isLoading'>
|
||||||
stateEmail?: string,
|
type SignInEmailPasswordlessHandler = {
|
||||||
stateOptions?: PasswordlessOptions
|
(email: string, options?: PasswordlessOptions): Promise<SignInEmailPasswordlessHandlerResult>
|
||||||
|
/** @deprecated */
|
||||||
|
(email?: unknown, options?: PasswordlessOptions): Promise<SignInEmailPasswordlessHandlerResult>
|
||||||
|
}
|
||||||
|
|
||||||
|
type SignInEmailPasswordlessHookResult = {
|
||||||
|
signInEmailPasswordless: SignInEmailPasswordlessHandler
|
||||||
|
} & ActionHookState
|
||||||
|
|
||||||
|
type SignInEmailPasswordlessdHook = {
|
||||||
|
(options?: PasswordlessOptions): SignInEmailPasswordlessHookResult
|
||||||
|
/** @deprecated */
|
||||||
|
(email?: string, options?: PasswordlessOptions): SignInEmailPasswordlessHookResult
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSignInEmailPasswordless: SignInEmailPasswordlessdHook = (
|
||||||
|
a?: string | PasswordlessOptions,
|
||||||
|
b?: PasswordlessOptions
|
||||||
) => {
|
) => {
|
||||||
|
const stateEmail = typeof a === 'string' ? a : undefined
|
||||||
|
const stateOptions = typeof a === 'string' ? b : a
|
||||||
const service = useAuthInterpreter()
|
const service = useAuthInterpreter()
|
||||||
const signInEmailPasswordless = (valueEmail?: string | unknown, valueOptions = stateOptions) =>
|
|
||||||
service.send({
|
const signInEmailPasswordless: SignInEmailPasswordlessHandler = (
|
||||||
type: 'SIGNIN_PASSWORDLESS_EMAIL',
|
valueEmail?: string | unknown,
|
||||||
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
valueOptions = stateOptions
|
||||||
options: valueOptions
|
) =>
|
||||||
|
new Promise<SignInEmailPasswordlessHandlerResult>((resolve) => {
|
||||||
|
service.send({
|
||||||
|
type: 'SIGNIN_PASSWORDLESS_EMAIL',
|
||||||
|
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
||||||
|
options: valueOptions
|
||||||
|
})
|
||||||
|
service.onTransition((state) => {
|
||||||
|
if (state.matches({ authentication: { signedOut: 'failed' } })) {
|
||||||
|
resolve({
|
||||||
|
error: state.context.errors.authentication || null,
|
||||||
|
isError: true,
|
||||||
|
isSuccess: false
|
||||||
|
})
|
||||||
|
} else if (state.matches({ authentication: { signedOut: 'needsEmailVerification' } })) {
|
||||||
|
resolve({ error: null, isError: false, isSuccess: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const error = useSelector(
|
const error = useSelector(
|
||||||
service,
|
service,
|
||||||
(state) => state.context.errors.authentication,
|
(state) => state.context.errors.authentication || null,
|
||||||
(a, b) => a?.error === b?.error
|
(a, b) => a?.error === b?.error
|
||||||
)
|
)
|
||||||
const isLoading =
|
const isLoading =
|
||||||
@@ -93,9 +219,9 @@ export const useSignInEmailPasswordless = (
|
|||||||
const isSuccess =
|
const isSuccess =
|
||||||
!!service.status &&
|
!!service.status &&
|
||||||
service.state.matches({ authentication: { signedOut: 'needsEmailVerification' } })
|
service.state.matches({ authentication: { signedOut: 'needsEmailVerification' } })
|
||||||
|
|
||||||
const isError =
|
const isError =
|
||||||
!!service.status && service.state.matches({ authentication: { signedOut: 'failed' } })
|
!!service.status && service.state.matches({ authentication: { signedOut: 'failed' } })
|
||||||
|
|
||||||
return { signInEmailPasswordless, isLoading, isSuccess, isError, error }
|
return { signInEmailPasswordless, isLoading, isSuccess, isError, error }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +241,13 @@ export const useSignInAnonymous = () => {
|
|||||||
const isSuccess = useAuthenticated()
|
const isSuccess = useAuthenticated()
|
||||||
const isError =
|
const isError =
|
||||||
!!service.status && service.state.matches({ authentication: { signedOut: 'failed' } })
|
!!service.status && service.state.matches({ authentication: { signedOut: 'failed' } })
|
||||||
return { signInAnonymous, isLoading, isSuccess, isError, error }
|
const user = useSelector(
|
||||||
|
service,
|
||||||
|
(state) => state.context.user,
|
||||||
|
(a, b) => a?.id === b?.id
|
||||||
|
)
|
||||||
|
const accessToken = useSelector(service, (state) => state.context.accessToken.value)
|
||||||
|
return { accessToken, error, isError, isLoading, isSuccess, signInAnonymous, user }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useProviderLink = (options?: ProviderOptions) => {
|
export const useProviderLink = (options?: ProviderOptions) => {
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
import { useContext, useEffect, useState } from 'react'
|
import { useContext, useEffect, useState } from 'react'
|
||||||
import { InterpreterFrom } from 'xstate'
|
import { InterpreterFrom } from 'xstate'
|
||||||
|
|
||||||
import { AuthMachine } from '@nhost/core'
|
import { AuthMachine, ErrorPayload } from '@nhost/core'
|
||||||
import { NhostClient } from '@nhost/nhost-js'
|
import { NhostClient } from '@nhost/nhost-js'
|
||||||
import { useSelector } from '@xstate/react'
|
import { useSelector } from '@xstate/react'
|
||||||
|
|
||||||
import { NhostReactContext } from '../provider'
|
import { NhostReactContext } from '../provider'
|
||||||
|
|
||||||
|
export type ActionHookState<T extends string = 'isSuccess'> = {
|
||||||
|
isLoading: boolean
|
||||||
|
|
||||||
|
isError: boolean
|
||||||
|
error: ErrorPayload | null
|
||||||
|
} & Record<T, boolean>
|
||||||
|
|
||||||
export const useNhostClient = (): NhostClient => {
|
export const useNhostClient = (): NhostClient => {
|
||||||
const nhost = useContext(NhostReactContext)
|
const nhost = useContext(NhostReactContext)
|
||||||
return nhost
|
return nhost
|
||||||
|
|||||||
@@ -1,21 +1,55 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
|
|
||||||
import { SignUpOptions } from '@nhost/core'
|
import { SignUpOptions, User } from '@nhost/core'
|
||||||
import { useSelector } from '@xstate/react'
|
import { useSelector } from '@xstate/react'
|
||||||
|
|
||||||
import { useAuthenticationStatus, useAuthInterpreter } from './common'
|
import { ActionHookState, useAuthenticationStatus, useAuthInterpreter } from './common'
|
||||||
|
|
||||||
export const useSignUpEmailPassword = (
|
type SignUpEmailPasswordHookState = ActionHookState & {
|
||||||
stateEmail?: string,
|
needsEmailVerification: boolean
|
||||||
statePassword?: string,
|
user: User | null
|
||||||
stateOptions?: SignUpOptions
|
accessToken: string | null
|
||||||
|
}
|
||||||
|
type SignUpEmailPasswordHandlerResult = Omit<SignUpEmailPasswordHookState, 'isLoading'>
|
||||||
|
|
||||||
|
type SignUpEmailPasswordHandler = {
|
||||||
|
(
|
||||||
|
email: string,
|
||||||
|
password: string,
|
||||||
|
options?: SignUpOptions
|
||||||
|
): Promise<SignUpEmailPasswordHandlerResult>
|
||||||
|
/** @deprecated */
|
||||||
|
(
|
||||||
|
email?: unknown,
|
||||||
|
password?: string,
|
||||||
|
options?: SignUpOptions
|
||||||
|
): Promise<SignUpEmailPasswordHandlerResult>
|
||||||
|
}
|
||||||
|
|
||||||
|
type SignUpEmailPasswordHookResult = {
|
||||||
|
signUpEmailPassword: SignUpEmailPasswordHandler
|
||||||
|
} & SignUpEmailPasswordHookState
|
||||||
|
|
||||||
|
type SignUpEmailPasswordHook = {
|
||||||
|
(options?: SignUpOptions): SignUpEmailPasswordHookResult
|
||||||
|
/** @deprecated */
|
||||||
|
(email?: string, password?: string, options?: SignUpOptions): SignUpEmailPasswordHookResult
|
||||||
|
}
|
||||||
|
export const useSignUpEmailPassword: SignUpEmailPasswordHook = (
|
||||||
|
a?: string | SignUpOptions,
|
||||||
|
b?: string,
|
||||||
|
c?: SignUpOptions
|
||||||
) => {
|
) => {
|
||||||
|
const stateEmail: string | undefined = typeof a === 'string' ? a : undefined
|
||||||
|
const statePassword: string | undefined = typeof b === 'string' ? b : undefined
|
||||||
|
const stateOptions = c || (typeof a !== 'string' ? a : undefined)
|
||||||
|
|
||||||
const service = useAuthInterpreter()
|
const service = useAuthInterpreter()
|
||||||
const isError =
|
const isError =
|
||||||
!!service.status && service.state.matches({ authentication: { signedOut: 'failed' } })
|
!!service.status && service.state.matches({ authentication: { signedOut: 'failed' } })
|
||||||
const error = useSelector(
|
const error = useSelector(
|
||||||
service,
|
service,
|
||||||
(state) => state.context.errors.registration,
|
(state) => state.context.errors.registration || null,
|
||||||
(a, b) => a?.error === b?.error
|
(a, b) => a?.error === b?.error
|
||||||
)
|
)
|
||||||
const { isLoading: loading, isAuthenticated: isSuccess } = useAuthenticationStatus()
|
const { isLoading: loading, isAuthenticated: isSuccess } = useAuthenticationStatus()
|
||||||
@@ -24,23 +58,65 @@ export const useSignUpEmailPassword = (
|
|||||||
!!service.status &&
|
!!service.status &&
|
||||||
service.state.matches({ authentication: { signedOut: 'needsEmailVerification' } })
|
service.state.matches({ authentication: { signedOut: 'needsEmailVerification' } })
|
||||||
|
|
||||||
const signUpEmailPassword = (
|
const signUpEmailPassword: SignUpEmailPasswordHandler = (
|
||||||
valueEmail?: string | unknown,
|
valueEmail?: string | unknown,
|
||||||
valuePassword = statePassword,
|
valuePassword = statePassword,
|
||||||
valueOptions = stateOptions
|
valueOptions = stateOptions
|
||||||
) =>
|
) =>
|
||||||
service.send({
|
new Promise<SignUpEmailPasswordHandlerResult>((resolve) => {
|
||||||
type: 'SIGNUP_EMAIL_PASSWORD',
|
service.send({
|
||||||
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
type: 'SIGNUP_EMAIL_PASSWORD',
|
||||||
password: valuePassword,
|
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
||||||
options: valueOptions
|
password: valuePassword,
|
||||||
|
options: valueOptions
|
||||||
|
})
|
||||||
|
service.onTransition((state) => {
|
||||||
|
if (state.matches({ authentication: { signedOut: 'failed' } })) {
|
||||||
|
resolve({
|
||||||
|
accessToken: null,
|
||||||
|
error: state.context.errors.registration || null,
|
||||||
|
isError: true,
|
||||||
|
isSuccess: false,
|
||||||
|
needsEmailVerification: false,
|
||||||
|
user: null
|
||||||
|
})
|
||||||
|
} else if (state.matches({ authentication: { signedOut: 'needsEmailVerification' } })) {
|
||||||
|
resolve({
|
||||||
|
accessToken: null,
|
||||||
|
error: null,
|
||||||
|
isError: false,
|
||||||
|
isSuccess: false,
|
||||||
|
needsEmailVerification: true,
|
||||||
|
user: null
|
||||||
|
})
|
||||||
|
} else if (state.matches({ authentication: 'signedIn' })) {
|
||||||
|
resolve({
|
||||||
|
accessToken: state.context.accessToken.value,
|
||||||
|
error: null,
|
||||||
|
isError: false,
|
||||||
|
isSuccess: true,
|
||||||
|
needsEmailVerification: false,
|
||||||
|
user: state.context.user
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const user = useSelector(
|
||||||
|
service,
|
||||||
|
(state) => state.context.user,
|
||||||
|
(a, b) => a?.id === b?.id
|
||||||
|
)
|
||||||
|
const accessToken = useSelector(service, (state) => state.context.accessToken.value)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
signUpEmailPassword,
|
accessToken,
|
||||||
|
error,
|
||||||
|
isError,
|
||||||
isLoading,
|
isLoading,
|
||||||
isSuccess,
|
isSuccess,
|
||||||
isError,
|
needsEmailVerification,
|
||||||
error,
|
signUpEmailPassword,
|
||||||
needsEmailVerification
|
user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ChangeEmailOptions,
|
ChangeEmailOptions,
|
||||||
@@ -7,64 +7,171 @@ import {
|
|||||||
createEnableMfaMachine,
|
createEnableMfaMachine,
|
||||||
createResetPasswordMachine,
|
createResetPasswordMachine,
|
||||||
createSendVerificationEmailMachine,
|
createSendVerificationEmailMachine,
|
||||||
|
ErrorPayload,
|
||||||
ResetPasswordOptions,
|
ResetPasswordOptions,
|
||||||
SendVerificationEmailOptions
|
SendVerificationEmailOptions
|
||||||
} from '@nhost/core'
|
} from '@nhost/core'
|
||||||
import { useMachine, useSelector } from '@xstate/react'
|
import { useMachine, useSelector } from '@xstate/react'
|
||||||
|
|
||||||
import { useAuthInterpreter, useNhostClient } from './common'
|
import { ActionHookState, useAuthInterpreter, useNhostClient } from './common'
|
||||||
|
|
||||||
export const useChangeEmail = (stateEmail?: string, stateOptions?: ChangeEmailOptions) => {
|
type ChangeEmailHookState = ActionHookState<'needsEmailVerification'>
|
||||||
|
type ChangeEmailHandlerResult = Omit<ChangeEmailHookState, 'isLoading'>
|
||||||
|
type ChangeEmailHandler = {
|
||||||
|
(email: string, options?: ChangeEmailOptions): Promise<ChangeEmailHandlerResult>
|
||||||
|
/** @deprecated */
|
||||||
|
(email?: unknown, options?: ChangeEmailOptions): Promise<ChangeEmailHandlerResult>
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChangeEmailHookResult = {
|
||||||
|
changeEmail: ChangeEmailHandler
|
||||||
|
} & ChangeEmailHookState
|
||||||
|
|
||||||
|
type ChangeEmailHook = {
|
||||||
|
(options?: ChangeEmailOptions): ChangeEmailHookResult
|
||||||
|
/** @deprecated */
|
||||||
|
(email?: string, options?: ChangeEmailOptions): ChangeEmailHookResult
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useChangeEmail: ChangeEmailHook = (
|
||||||
|
a?: string | ChangeEmailOptions,
|
||||||
|
b?: ChangeEmailOptions
|
||||||
|
) => {
|
||||||
|
const stateEmail = typeof a === 'string' ? a : undefined
|
||||||
|
const stateOptions = typeof a !== 'string' ? a : b
|
||||||
const nhost = useNhostClient()
|
const nhost = useNhostClient()
|
||||||
const machine = useMemo(() => createChangeEmailMachine(nhost.auth.client), [nhost])
|
const machine = useMemo(() => createChangeEmailMachine(nhost.auth.client), [nhost])
|
||||||
const [current, send] = useMachine(machine)
|
const [, send, service] = useMachine(machine)
|
||||||
|
const [isError, setIsError] = useState(false)
|
||||||
const isError = current.matches({ idle: 'error' })
|
const [needsEmailVerification, setNeedsEmailVerification] = useState(false)
|
||||||
const needsEmailVerification = current.matches({ idle: 'success' })
|
const [error, setError] = useState<ErrorPayload | null>(null)
|
||||||
const error = current.context.error
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const isLoading = current.matches('requesting')
|
const changeEmail: ChangeEmailHandler = async (
|
||||||
|
valueEmail?: string | unknown,
|
||||||
const changeEmail = (valueEmail?: string | unknown, valueOptions = stateOptions) =>
|
valueOptions = stateOptions
|
||||||
send({
|
) =>
|
||||||
type: 'REQUEST',
|
new Promise<ChangeEmailHandlerResult>((resolve) => {
|
||||||
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
send({
|
||||||
options: valueOptions
|
type: 'REQUEST',
|
||||||
|
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
||||||
|
options: valueOptions
|
||||||
|
})
|
||||||
|
service.onTransition((state) => {
|
||||||
|
if (state.matches({ idle: 'error' })) {
|
||||||
|
const error = state.context.error
|
||||||
|
setIsError(true)
|
||||||
|
setError(error)
|
||||||
|
setIsLoading(false)
|
||||||
|
resolve({ isError: true, error, needsEmailVerification })
|
||||||
|
} else if (state.matches('requesting')) {
|
||||||
|
setIsLoading(true)
|
||||||
|
} else if (state.matches({ idle: 'success' })) {
|
||||||
|
setIsError(false)
|
||||||
|
setError(null)
|
||||||
|
setIsLoading(false)
|
||||||
|
setNeedsEmailVerification(true)
|
||||||
|
resolve({ isError: false, error: null, needsEmailVerification: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return { changeEmail, isLoading, needsEmailVerification, isError, error }
|
return { changeEmail, isLoading, needsEmailVerification, isError, error }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useChangePassword = (statePassword?: string) => {
|
type ChangePasswordHandlerResult = Omit<ActionHookState, 'isLoading'>
|
||||||
|
type ChangePasswordHandler = {
|
||||||
|
(password: string): Promise<ChangePasswordHandlerResult>
|
||||||
|
/** @deprecated */
|
||||||
|
(password?: unknown): Promise<ChangePasswordHandlerResult>
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChangePasswordHookResult = {
|
||||||
|
changePassword: ChangePasswordHandler
|
||||||
|
} & ActionHookState
|
||||||
|
|
||||||
|
type ChangePasswordHook = {
|
||||||
|
(): ChangePasswordHookResult
|
||||||
|
/** @deprecated */
|
||||||
|
(email?: string): ChangePasswordHookResult
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useChangePassword: ChangePasswordHook = (statePassword?: string) => {
|
||||||
const nhost = useNhostClient()
|
const nhost = useNhostClient()
|
||||||
const machine = useMemo(() => createChangePasswordMachine(nhost.auth.client), [nhost])
|
const machine = useMemo(() => createChangePasswordMachine(nhost.auth.client), [nhost])
|
||||||
const [current, send] = useMachine(machine)
|
const [current, send, service] = useMachine(machine)
|
||||||
const isError = current.matches({ idle: 'error' })
|
const isError = current.matches({ idle: 'error' })
|
||||||
const isSuccess = current.matches({ idle: 'success' })
|
const isSuccess = current.matches({ idle: 'success' })
|
||||||
const error = current.context.error
|
const error = current.context.error
|
||||||
const isLoading = current.matches('requesting')
|
const isLoading = current.matches('requesting')
|
||||||
|
|
||||||
const changePassword = (valuePassword?: string | unknown) =>
|
const changePassword: ChangePasswordHandler = (valuePassword?: string | unknown) =>
|
||||||
send({
|
new Promise<ChangePasswordHandlerResult>((resolve) => {
|
||||||
type: 'REQUEST',
|
send({
|
||||||
password: typeof valuePassword === 'string' ? valuePassword : statePassword
|
type: 'REQUEST',
|
||||||
|
password: typeof valuePassword === 'string' ? valuePassword : statePassword
|
||||||
|
})
|
||||||
|
service.onTransition((state) => {
|
||||||
|
if (state.matches({ idle: 'error' })) {
|
||||||
|
resolve({ error: state.context.error, isError: true, isSuccess: false })
|
||||||
|
} else if (state.matches({ idle: 'success' })) {
|
||||||
|
resolve({ error: null, isError: false, isSuccess: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return { changePassword, isLoading, isSuccess, isError, error }
|
return { changePassword, isLoading, isSuccess, isError, error }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useResetPassword = (stateEmail?: string, stateOptions?: ResetPasswordOptions) => {
|
type ResetPasswordHandlerResult = Omit<ResetPasswordHookState, 'isLoading'>
|
||||||
|
type ResetPasswordHandler = {
|
||||||
|
(email: string, options?: ResetPasswordOptions): Promise<ResetPasswordHandlerResult>
|
||||||
|
/** @deprecated */
|
||||||
|
(email?: unknown, options?: ResetPasswordOptions): Promise<ResetPasswordHandlerResult>
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResetPasswordHookState = ActionHookState<'isSent'>
|
||||||
|
|
||||||
|
type ResetPasswordHookResult = {
|
||||||
|
resetPassword: ResetPasswordHandler
|
||||||
|
} & ResetPasswordHookState
|
||||||
|
|
||||||
|
type ResetPasswordHook = {
|
||||||
|
(options?: ResetPasswordOptions): ResetPasswordHookResult
|
||||||
|
/** @deprecated */
|
||||||
|
(email?: string, options?: ResetPasswordOptions): ResetPasswordHookResult
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useResetPassword: ResetPasswordHook = (
|
||||||
|
a?: string | ResetPasswordOptions,
|
||||||
|
b?: ResetPasswordOptions
|
||||||
|
) => {
|
||||||
|
const stateEmail = typeof a === 'string' ? a : undefined
|
||||||
|
const stateOptions = typeof a !== 'string' ? a : b
|
||||||
const nhost = useNhostClient()
|
const nhost = useNhostClient()
|
||||||
const machine = useMemo(() => createResetPasswordMachine(nhost.auth.client), [nhost])
|
const machine = useMemo(() => createResetPasswordMachine(nhost.auth.client), [nhost])
|
||||||
const [current, send] = useMachine(machine)
|
const [current, send, service] = useMachine(machine)
|
||||||
const isError = current.matches({ idle: 'error' })
|
const isError = current.matches({ idle: 'error' })
|
||||||
const isSent = current.matches({ idle: 'success' })
|
const isSent = current.matches({ idle: 'success' })
|
||||||
const error = current.context.error
|
const error = current.context.error
|
||||||
const isLoading = current.matches('requesting')
|
const isLoading = current.matches('requesting')
|
||||||
|
|
||||||
const resetPassword = (valueEmail?: string | unknown, valueOptions = stateOptions) =>
|
const resetPassword: ResetPasswordHandler = (
|
||||||
send({
|
valueEmail?: string | unknown,
|
||||||
type: 'REQUEST',
|
valueOptions = stateOptions
|
||||||
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
) =>
|
||||||
options: valueOptions
|
new Promise<ResetPasswordHandlerResult>((resolve) => {
|
||||||
|
send({
|
||||||
|
type: 'REQUEST',
|
||||||
|
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
||||||
|
options: valueOptions
|
||||||
|
})
|
||||||
|
service.onTransition((state) => {
|
||||||
|
if (state.matches({ idle: 'error' })) {
|
||||||
|
resolve({ error: state.context.error, isError: true, isSent: false })
|
||||||
|
} else if (state.matches({ idle: 'success' })) {
|
||||||
|
resolve({ error: null, isError: false, isSent: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
return { resetPassword, isLoading, isSent, isError, error }
|
return { resetPassword, isLoading, isSent, isError, error }
|
||||||
}
|
}
|
||||||
@@ -150,37 +257,103 @@ export const useUserRoles = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useSendVerificationEmail = (
|
type SendVerificationEmailHandlerResult = Omit<SendVerificationEmailHookState, 'isLoading'>
|
||||||
stateEmail?: string,
|
type SendVerificationEmailHandler = {
|
||||||
stateOptions?: SendVerificationEmailOptions
|
(
|
||||||
|
email: string,
|
||||||
|
options?: SendVerificationEmailOptions
|
||||||
|
): Promise<SendVerificationEmailHandlerResult>
|
||||||
|
/** @deprecated */
|
||||||
|
(
|
||||||
|
email?: unknown,
|
||||||
|
options?: SendVerificationEmailOptions
|
||||||
|
): Promise<SendVerificationEmailHandlerResult>
|
||||||
|
}
|
||||||
|
|
||||||
|
type SendVerificationEmailHookState = ActionHookState<'isSent'>
|
||||||
|
|
||||||
|
type SendVerificationEmailHookResult = {
|
||||||
|
sendEmail: SendVerificationEmailHandler
|
||||||
|
} & SendVerificationEmailHookState
|
||||||
|
|
||||||
|
type SendVerificationEmailHook = {
|
||||||
|
(options?: SendVerificationEmailOptions): SendVerificationEmailHookResult
|
||||||
|
/** @deprecated */
|
||||||
|
(email?: string, options?: SendVerificationEmailOptions): SendVerificationEmailHookResult
|
||||||
|
}
|
||||||
|
export const useSendVerificationEmail: SendVerificationEmailHook = (
|
||||||
|
a?: string | SendVerificationEmailOptions,
|
||||||
|
b?: SendVerificationEmailOptions
|
||||||
) => {
|
) => {
|
||||||
|
const stateEmail = typeof a === 'string' ? a : undefined
|
||||||
|
const stateOptions = typeof a !== 'string' ? a : b
|
||||||
const nhost = useNhostClient()
|
const nhost = useNhostClient()
|
||||||
const machine = useMemo(() => createSendVerificationEmailMachine(nhost.auth.client), [nhost])
|
const machine = useMemo(() => createSendVerificationEmailMachine(nhost.auth.client), [nhost])
|
||||||
const [current, send] = useMachine(machine)
|
const [current, send, service] = useMachine(machine)
|
||||||
const isError = current.matches({ idle: 'error' })
|
const isError = current.matches({ idle: 'error' })
|
||||||
const isSent = current.matches({ idle: 'success' })
|
const isSent = current.matches({ idle: 'success' })
|
||||||
const error = current.context.error
|
const error = current.context.error
|
||||||
const isLoading = current.matches('requesting')
|
const isLoading = current.matches('requesting')
|
||||||
|
|
||||||
const sendEmail = (valueEmail?: string | unknown, valueOptions = stateOptions) =>
|
const sendEmail: SendVerificationEmailHandler = (
|
||||||
send({
|
valueEmail?: string | unknown,
|
||||||
type: 'REQUEST',
|
valueOptions = stateOptions
|
||||||
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
) =>
|
||||||
options: valueOptions
|
new Promise<SendVerificationEmailHandlerResult>((resolve) => {
|
||||||
|
send({
|
||||||
|
type: 'REQUEST',
|
||||||
|
email: typeof valueEmail === 'string' ? valueEmail : stateEmail,
|
||||||
|
options: valueOptions
|
||||||
|
})
|
||||||
|
service.onTransition((state) => {
|
||||||
|
if (state.matches({ idle: 'error' })) {
|
||||||
|
resolve({ error: state.context.error, isError: true, isSent: false })
|
||||||
|
} else if (state.matches({ idle: 'success' })) {
|
||||||
|
resolve({ error: null, isError: false, isSent: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
return { sendEmail, isLoading, isSent, isError, error }
|
return { sendEmail, isLoading, isSent, isError, error }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ActivateMfaHookState = {
|
||||||
|
isActivating: boolean
|
||||||
|
isActivated: boolean
|
||||||
|
isError: boolean
|
||||||
|
error: ErrorPayload | null
|
||||||
|
}
|
||||||
|
type GenerateQrCodeHookState = {
|
||||||
|
qrCodeDataUrl: string
|
||||||
|
isGenerating: boolean
|
||||||
|
isGenerated: boolean
|
||||||
|
isError: boolean
|
||||||
|
error: ErrorPayload | null
|
||||||
|
}
|
||||||
|
type ActivateMfaHandlerResult = Omit<ActivateMfaHookState, 'isActivating'>
|
||||||
|
type ActivateMfaHandler = (code: string) => Promise<ActivateMfaHandlerResult>
|
||||||
|
|
||||||
|
type GenerateQrCodeHandlerResult = Omit<GenerateQrCodeHookState, 'isGenerating'>
|
||||||
|
type GenerateQrCodeHandler = () => Promise<GenerateQrCodeHandlerResult>
|
||||||
|
|
||||||
|
type ConfigMfaHookState = ActivateMfaHookState &
|
||||||
|
GenerateQrCodeHookState & {
|
||||||
|
generateQrCode: GenerateQrCodeHandler
|
||||||
|
activateMfa: ActivateMfaHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConfigMfaHook = () => ConfigMfaHookState
|
||||||
|
|
||||||
// TODO documentation when available in Nhost Cloud - see changelog
|
// TODO documentation when available in Nhost Cloud - see changelog
|
||||||
export const useConfigMfa = (stateCode?: string) => {
|
export const useConfigMfa: ConfigMfaHook = () => {
|
||||||
const nhost = useNhostClient()
|
const nhost = useNhostClient()
|
||||||
|
|
||||||
const machine = useMemo(() => createEnableMfaMachine(nhost.auth.client), [nhost])
|
const machine = useMemo(() => createEnableMfaMachine(nhost.auth.client), [nhost])
|
||||||
const [current, send] = useMachine(machine)
|
const [current, send, service] = useMachine(machine)
|
||||||
|
|
||||||
const isError = useMemo(() => {
|
const isError = useMemo(
|
||||||
current.matches({ idle: 'error' }) || current.matches({ generated: { idle: 'error' } })
|
() => current.matches({ idle: 'error' }) || current.matches({ generated: { idle: 'error' } }),
|
||||||
}, [current])
|
[current]
|
||||||
|
)
|
||||||
const isGenerating = current.matches('generating')
|
const isGenerating = current.matches('generating')
|
||||||
const isGenerated = current.matches('generated')
|
const isGenerated = current.matches('generated')
|
||||||
const isActivating = current.matches({ generated: 'activating' })
|
const isActivating = current.matches({ generated: 'activating' })
|
||||||
@@ -188,12 +361,41 @@ export const useConfigMfa = (stateCode?: string) => {
|
|||||||
const error = current.context.error
|
const error = current.context.error
|
||||||
const qrCodeDataUrl = current.context.imageUrl || ''
|
const qrCodeDataUrl = current.context.imageUrl || ''
|
||||||
|
|
||||||
const generateQrCode = () => send('GENERATE')
|
const generateQrCode: GenerateQrCodeHandler = () =>
|
||||||
const activateMfa = (valueCode?: string | unknown) =>
|
new Promise<GenerateQrCodeHandlerResult>((resolve) => {
|
||||||
send({
|
send('GENERATE')
|
||||||
type: 'ACTIVATE',
|
service.onTransition((state) => {
|
||||||
activeMfaType: 'totp',
|
if (state.matches('generated')) {
|
||||||
code: typeof valueCode === 'string' ? valueCode : stateCode
|
resolve({
|
||||||
|
error: null,
|
||||||
|
isError: false,
|
||||||
|
isGenerated: true,
|
||||||
|
qrCodeDataUrl: state.context.imageUrl || ''
|
||||||
|
})
|
||||||
|
} else if (state.matches({ idle: 'error' })) {
|
||||||
|
resolve({
|
||||||
|
error: state.context.error || null,
|
||||||
|
isError: true,
|
||||||
|
isGenerated: false,
|
||||||
|
qrCodeDataUrl: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const activateMfa: ActivateMfaHandler = (code: string) =>
|
||||||
|
new Promise<ActivateMfaHandlerResult>((resolve) => {
|
||||||
|
send({
|
||||||
|
type: 'ACTIVATE',
|
||||||
|
activeMfaType: 'totp',
|
||||||
|
code
|
||||||
|
})
|
||||||
|
service.onTransition((state) => {
|
||||||
|
if (state.matches({ generated: 'activated' })) {
|
||||||
|
resolve({ error: null, isActivated: true, isError: false })
|
||||||
|
} else if (state.matches({ generated: { idle: 'error' } })) {
|
||||||
|
resolve({ error: state.context.error, isActivated: false, isError: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
generateQrCode,
|
generateQrCode,
|
||||||
|
|||||||
2
pnpm-lock.yaml
generated
2
pnpm-lock.yaml
generated
@@ -83,6 +83,7 @@ importers:
|
|||||||
specifiers:
|
specifiers:
|
||||||
'@heroicons/react': ^1.0.5
|
'@heroicons/react': ^1.0.5
|
||||||
'@mailchimp/mailchimp_marketing': ^3.0.74
|
'@mailchimp/mailchimp_marketing': ^3.0.74
|
||||||
|
'@types/node': ^17.0.21
|
||||||
'@types/react': ^17.0.37
|
'@types/react': ^17.0.37
|
||||||
autoprefixer: ^10.4.0
|
autoprefixer: ^10.4.0
|
||||||
axios: ^0.24.0
|
axios: ^0.24.0
|
||||||
@@ -135,6 +136,7 @@ importers:
|
|||||||
react-syntax-highlighter: 15.4.5_react@17.0.2
|
react-syntax-highlighter: 15.4.5_react@17.0.2
|
||||||
swagger-ui-react: 4.8.0_react-dom@17.0.2+react@17.0.2
|
swagger-ui-react: 4.8.0_react-dom@17.0.2+react@17.0.2
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@types/node': 17.0.21
|
||||||
'@types/react': 17.0.40
|
'@types/react': 17.0.40
|
||||||
autoprefixer: 10.4.2_postcss@8.4.8
|
autoprefixer: 10.4.2_postcss@8.4.8
|
||||||
next-sitemap: 1.9.12_next@12.1.0
|
next-sitemap: 1.9.12_next@12.1.0
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"removeComments": true,
|
"removeComments": false,
|
||||||
"noLib": false,
|
"noLib": false,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user