Compare commits

..

90 Commits

Author SHA1 Message Date
Szilárd Dóró
3601de3f85 Merge pull request #1208 from nhost/changeset-release/main
chore: update versions
2022-11-24 20:20:45 +01:00
github-actions[bot]
ac9404610b chore: update versions 2022-11-24 19:09:19 +00:00
Szilárd Dóró
63570db57c Merge pull request #1207 from nhost/contributors-readme-action-MBHUTcRQyD
contributors readme action update
2022-11-24 20:08:33 +01:00
github-actions[bot]
538ed78f5a contrib-readme-action has updated readme 2022-11-24 19:07:02 +00:00
Szilárd Dóró
b1a31ecb00 Merge pull request #1181 from nhost/fix/dashboard-custom-local-ports
feat(dashboard): make backend port configurable
2022-11-24 20:06:44 +01:00
Siarhei Lipchyk
bac8ace434 Add support for custom ports via placeholders 2022-11-24 19:03:02 +01:00
Pilou
a402fc17de Merge pull request #1192 from nhost/changeset-release/main
chore: update versions
2022-11-24 17:21:07 +01:00
github-actions[bot]
de0a125e98 chore: update versions 2022-11-24 09:38:59 +00:00
Pilou
ea1ad29031 Merge pull request #1200 from nhost/plmercereau-patch-storage-tag
Update docker-compose.yaml
2022-11-24 10:37:25 +01:00
Szilárd Dóró
3da40e5712 Merge pull request #1205 from nhost/fix/dashboard-meta
fix(dashboard): update terminology
2022-11-24 10:35:48 +01:00
Szilárd Dóró
b9087a4add fix(dashboard): console / dashboard terminology 2022-11-24 09:54:44 +01:00
Szilárd Dóró
1b7a6d0252 fix(dashboard): update terminology 2022-11-24 09:23:08 +01:00
Szilárd Dóró
1417d3e794 Merge pull request #1203 from nhost/contributors-readme-action-FFIU1CawPP
contributors readme action update
2022-11-24 08:55:41 +01:00
github-actions[bot]
e187923858 contrib-readme-action has updated readme 2022-11-24 07:52:33 +00:00
Johan Eliasson
8a60ed4074 Merge pull request #1199 from nhost/functions-more-examples
examples(serverless-functions): smtp + async/await
2022-11-24 08:52:19 +01:00
Pilou
d7d11a44a7 Update docker-compose.yaml
There's no latest tag on storage
2022-11-23 22:04:40 +01:00
Johan Eliasson
062e4691cd added examples 2022-11-23 21:53:25 +01:00
Pilou
a95d49fa2c Merge pull request #1197 from nhost/docs/custom-claims-singleton-array
docs: custom claims and singleton arrays
2022-11-23 19:06:34 +01:00
Johan Eliasson
d14fc96899 Merge pull request #1036 from ejkkan/feat/add-charges-to-stripe-package
feat(stripe-graphql-js): add charges, payment intents and connected accounts
2022-11-23 19:03:37 +01:00
Johan Eliasson
93db718254 Create blue-ghosts-accept.md 2022-11-23 19:03:12 +01:00
Pierre-Louis Mercereau
c367bd58b9 docs: custom claims and singleton arrays 2022-11-23 19:01:29 +01:00
Pilou
0bfed4d9e1 Merge pull request #1196 from nhost/plmercereau-patch-1
Update docker-compose.yaml
2022-11-23 18:43:36 +01:00
Pilou
1f3aecd379 Merge pull request #1193 from nhost/chore/bump-service-versions
ci: 🎡 bump services versions and trigger CI
2022-11-23 18:43:20 +01:00
Pilou
42306ea3bb Update docker-compose.yaml 2022-11-23 18:19:41 +01:00
Pilou
1b12a175f6 Update docker-compose.yaml 2022-11-23 18:18:06 +01:00
Szilárd Dóró
32060aaea0 Merge pull request #1195 from nhost/chore/dashboard-version
chore(dashboard): add changeset
2022-11-23 16:00:18 +01:00
Szilárd Dóró
f94cace5f2 Merge pull request #1194 from nhost/feat/dashboard-vercel-deployment
feat(dashboard): add Vercel deployment
2022-11-23 15:22:09 +01:00
Szilárd Dóró
5de965d9a5 chore(dashboard): add changeset 2022-11-23 15:15:08 +01:00
Szilárd Dóró
e10b3adc11 chore(changesets): incorporate Vercel deployment into publish process 2022-11-23 15:08:21 +01:00
Szilárd Dóró
457db76b06 Merge pull request #1191 from nhost/fix/sign-in-methods-order
fix(dashboard): alphabetic ordering of providers
2022-11-23 15:04:26 +01:00
Szilárd Dóró
1e952a026e chore(changesets): update publish step's name 2022-11-23 15:01:55 +01:00
Szilárd Dóró
2f4c040789 feat(dashboard): add Vercel deployment 2022-11-23 14:33:00 +01:00
Pierre-Louis Mercereau
74648752b4 ci: use correct hasura version 2022-11-23 13:12:32 +01:00
Szilárd Dóró
09d218a3fe fix(dashboard): sign-in method phrasing 2022-11-23 13:12:24 +01:00
Szilárd Dóró
2e8938dbb0 fix(dashboard): add missing Twilio icon 2022-11-23 13:00:12 +01:00
Pierre-Louis Mercereau
ec60d03536 ci: 🎡 bump services versions and trigger CI 2022-11-23 12:57:04 +01:00
Johan Eliasson
2f3767552f Merge pull request #1189 from nhost/docs-workos
docs(workos): WorkOS Docs
2022-11-23 12:14:57 +01:00
Szilárd Dóró
bc401c0dd2 fix(dashboard): alphabetic ordering of providers
- fixes #1188
- fix checkbox font size on the Settings page
2022-11-23 12:12:39 +01:00
Pilou
2907ecb7ff Merge pull request #1179 from nhost/changeset-release/main
chore: update versions
2022-11-23 11:24:55 +01:00
Pierre-Louis Mercereau
05d7f5207f chore: no major bump of peer dependencies 2022-11-23 11:22:55 +01:00
github-actions[bot]
07a053ee80 chore: update versions 2022-11-23 09:58:39 +00:00
Szilárd Dóró
2145243b19 chore(dashboard): update environment variables 2022-11-23 10:56:47 +01:00
Pilou
61e4414a8f Merge pull request #1190 from nhost/changeset-react-components
react components changeset added
2022-11-23 10:55:04 +01:00
Johan Eliasson
4601d84e0e changeset added 2022-11-23 10:29:19 +01:00
Johan Eliasson
ca012d790c Create tidy-teachers-flow.md 2022-11-23 10:27:23 +01:00
Johan Eliasson
aeda14ef53 docs link 2022-11-23 10:25:18 +01:00
Johan Eliasson
3fa5e2005a updates 2022-11-23 10:23:40 +01:00
Johan Eliasson
4dd2e99159 Merge pull request #1187 from nhost/docs-git-8g712asd
docs(git): git docs updates
2022-11-23 08:27:17 +01:00
Johan Eliasson
282c6c6d24 git docs update 2022-11-23 08:16:55 +01:00
Johan Eliasson
beadd84adb moving files 2022-11-23 07:52:57 +01:00
Johan Eliasson
f8f55d2b99 Merge branch 'main' into feat/add-charges-to-stripe-package 2022-11-23 07:49:17 +01:00
Johan Eliasson
03a98d4f3a config updates 2022-11-23 07:36:31 +01:00
Johan Eliasson
8ed8e04ab6 merge 2022-11-23 07:31:37 +01:00
Erik Magnusson
587efd4551 re-applied isAdmin checks for connected account field types 2022-11-23 08:15:44 +02:00
Johan Eliasson
c78227b085 Merge pull request #1185 from nhost/docs/node-16
docs: update developer's guide
2022-11-23 07:06:10 +01:00
Pierre-Louis Mercereau
d87e520307 docs: lessons learned from Sheena and Chris 2022-11-22 21:44:48 +01:00
Pilou
bbed04e4da Merge pull request #1158 from nhost/fix/use-user-roles
fix: 🐛 make `useUserRoles` reactive
2022-11-22 21:35:06 +01:00
Pilou
273afc9740 Merge pull request #1184 from nhost/contributors-readme-action-h-P6q9XKTD
contributors readme action update
2022-11-22 21:32:07 +01:00
github-actions[bot]
f4083aa4b3 contrib-readme-action has updated readme 2022-11-22 20:12:23 +00:00
Pilou
ddd2641726 Merge pull request #1183 from massless/min-version-node
Update minimum version of node
2022-11-22 21:12:04 +01:00
Chris Wetherell
4658aeb31e Update minimum version of node 2022-11-22 12:08:47 -08:00
Johan Eliasson
cc8e5fe4a9 Merge pull request #1180 from nhost/react-components-iy8gasd9
React Auth components: SignedIn and SignedOut
2022-11-22 19:54:19 +01:00
Szilárd Dóró
85c897c717 chore(docs): update source code references 2022-11-22 18:32:48 +01:00
Szilárd Dóró
c99e5552e6 chore(react): simplify component signature 2022-11-22 18:31:39 +01:00
Szilárd Dóró
97a2520ea1 feat(docgen): add support for components 2022-11-22 18:24:23 +01:00
Johan Eliasson
964af2912b inline docs 2022-11-22 17:04:39 +01:00
Szilárd Dóró
a48dd5bf74 chore(dashboard): add changeset 2022-11-22 14:32:53 +01:00
Szilárd Dóró
ef53df5cb3 feat(dashboard): make backend port configurable
- additionally: improve the way Hasura service ports are. configured through environment variables
2022-11-22 14:32:13 +01:00
Johan Eliasson
afea682a8c merge 2022-11-22 14:09:38 +01:00
Pierre-Louis Mercereau
fefa2baa2e refactor: readability 2022-11-22 13:28:09 +01:00
Pilou
f09b3cfd24 Merge pull request #1178 from nhost/ci/freeze-pnpm-version
ci: set explicit pnpm version in the dashboard dockerfile
2022-11-22 13:20:35 +01:00
Pilou
dd3b2c41f1 Merge pull request #1171 from nhost/chore/vue-file-upload-changeset
chore: add changeset to vue, and correct inline documentation
2022-11-22 13:20:21 +01:00
Szilárd Dóró
aaced20f31 Merge pull request #1173 from nhost/fix/dashboard-provider-redirect-url
fix(dashboard): correct redirect URL input opacity
2022-11-22 13:15:35 +01:00
Pierre-Louis Mercereau
3e91c19e13 ci: set explicit pnpm version in the dashboard dockerfile 2022-11-22 13:11:00 +01:00
Johan Eliasson
d4fd4ec3e9 signedin and signedout 2022-11-22 10:48:24 +01:00
Szilárd Dóró
89bd37bc28 chore(dashboard): add changeset 2022-11-22 10:20:52 +01:00
Szilárd Dóró
0df73a41c9 fix(dashboard): redirect URL opacity 2022-11-22 10:20:09 +01:00
Pierre-Louis Mercereau
f6d2042adb chore: add changeset to vue, and correct inline documentation 2022-11-22 09:34:47 +01:00
Pierre-Louis Mercereau
843087cb11 fix: 🐛 make useUserRoles reactive 2022-11-21 15:58:55 +01:00
Erik Magnusson
7055ffc37a Merge branch 'feat/add-charges-to-stripe-package' of https://github.com/ejkkan/nhost into feat/add-charges-to-stripe-package 2022-10-20 20:57:56 +02:00
Erik Magnusson
c68ce6d480 removed isAdmin checks for connected accounts related schema fields 2022-10-20 20:57:01 +02:00
Erik Magnusson
98a149c8bf Update packages/stripe-graphql-js/src/schema/charge.ts
Co-authored-by: Johan Eliasson <johan@eliasson.me>
2022-10-18 08:48:58 +02:00
Erik Magnusson
ceb558975e Update packages/stripe-graphql-js/src/schema/charge.ts
Co-authored-by: Johan Eliasson <johan@eliasson.me>
2022-10-18 08:48:46 +02:00
Erik Magnusson
7a87321a7e fixd imports and linting 2022-10-14 21:21:25 +02:00
Erik Magnusson
9349766c0a corrected spelling 2022-10-14 21:19:23 +02:00
Erik Magnusson
31655191a3 added connected accounts 2022-10-14 21:05:57 +02:00
Erik Magnusson
e3b91efa84 feat/added charges 2022-10-14 20:13:35 +02:00
Erik Magnusson
cfe736776a feat/added charges 2022-10-14 20:03:19 +02:00
Erik Magnusson
481bf237cc updated naming convention to camel casing 2022-10-14 10:11:02 +02:00
Erik Magnusson
33ce9bf1b9 added payment intents type for customer and invoice objects 2022-10-04 18:10:02 +02:00
118 changed files with 1714 additions and 579 deletions

View File

@@ -18,6 +18,7 @@ env:
jobs:
version:
name: Version
runs-on: ubuntu-latest
outputs:
hasChangesets: ${{ steps.changesets.outputs.hasChangesets }}
@@ -61,6 +62,7 @@ jobs:
secrets: inherit
publish:
name: Publish
runs-on: ubuntu-latest
needs:
- test
@@ -110,6 +112,8 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
push: true
- name: Trigger a Vercel deployment
run: curl -X POST -d {} https://api.vercel.com/v1/integrations/deploy/${{ secrets.DASHBOARD_VERCEL_PROJECT_ID }}/${{ secrets.DASHBOARD_VERCEL_WEBHOOK_ID }}
- name: Create GitHub Release
uses: taiki-e/create-gh-release-action@v1
with:

View File

@@ -2,6 +2,8 @@
## Requirements
- This repository works with **Node 16**
- We use [pnpm](https://pnpm.io/) as a package manager to speed up development and builds, and as a basis for our monorepo. You need to make sure it's installed on your machine. There are [several ways to install it](https://pnpm.io/installation), but the easiest way is with `npm`:
```sh
@@ -97,6 +99,12 @@ You can take a look at the changeset documentation: [How to add a changeset](htt
You'll notice that `git commit` takes a few seconds to run. We set a commit hook that scans the changes in the code, automatically generates documentation from the inline [TSDoc](https://tsdoc.org/) annotations, and adds these generated documentation files to the commit. They automatically update the [reference documentation](https://docs.nhost.io/reference).
The document generation script that is run in the pre-commit hook requires to be built first. You may need to run the following command before the commit:
```sh
pnpm run build
```
<!-- ## Good practices
- lint
- prettier

View File

@@ -179,14 +179,21 @@ Here are some ways of contributing to making Nhost better:
<sub><b>Grégory D'Angelo</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ejkkan">
<img src="https://avatars.githubusercontent.com/u/32518962?v=4" width="100;" alt="ejkkan"/>
<br />
<sub><b>Erik Magnusson</b></sub>
</a>
</td></tr>
<tr>
<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>
<td align="center">
<a href="https://github.com/subatuba21">
<img src="https://avatars.githubusercontent.com/u/34824571?v=4" width="100;" alt="subatuba21"/>
@@ -221,15 +228,15 @@ Here are some ways of contributing to making Nhost better:
<br />
<sub><b>Christopher Möller</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/GavanWilhite">
<img src="https://avatars.githubusercontent.com/u/2085119?v=4" width="100;" alt="GavanWilhite"/>
<br />
<sub><b>Gavan Wilhite</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/FuzzyReason">
<img src="https://avatars.githubusercontent.com/u/62517920?v=4" width="100;" alt="FuzzyReason"/>
@@ -237,13 +244,6 @@ Here are some ways of contributing to making Nhost better:
<sub><b>Vadim Smirnov</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ejkkan">
<img src="https://avatars.githubusercontent.com/u/32518962?v=4" width="100;" alt="ejkkan"/>
<br />
<sub><b>Erik Magnusson</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/macmac49">
<img src="https://avatars.githubusercontent.com/u/831190?v=4" width="100;" alt="macmac49"/>
@@ -380,6 +380,13 @@ Here are some ways of contributing to making Nhost better:
<sub><b>Chris</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/massless">
<img src="https://avatars.githubusercontent.com/u/44389?v=4" width="100;" alt="massless"/>
<br />
<sub><b>Chris Wetherell</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"/>
@@ -393,15 +400,15 @@ Here are some ways of contributing to making Nhost better:
<br />
<sub><b>Dago</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/dminkovsky">
<img src="https://avatars.githubusercontent.com/u/218725?v=4" width="100;" alt="dminkovsky"/>
<br />
<sub><b>Dmitry Minkovsky</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/dohomi">
<img src="https://avatars.githubusercontent.com/u/489221?v=4" width="100;" alt="dohomi"/>
@@ -436,15 +443,15 @@ Here are some ways of contributing to making Nhost better:
<br />
<sub><b>Ikko Ashimine</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/jladuval">
<img src="https://avatars.githubusercontent.com/u/1935359?v=4" width="100;" alt="jladuval"/>
<br />
<sub><b>Jacob Duval</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/leothorp">
<img src="https://avatars.githubusercontent.com/u/12928449?v=4" width="100;" alt="leothorp"/>
@@ -479,15 +486,22 @@ Here are some ways of contributing to making Nhost better:
<br />
<sub><b>Nirmalya Ghosh</b></sub>
</a>
</td>
</td></tr>
<tr>
<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>
<td align="center">
<a href="https://github.com/elephant3">
<img src="https://avatars.githubusercontent.com/u/48279149?v=4" width="100;" alt="elephant3"/>
<br />
<sub><b>Siarhei Lipchyk</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/altschuler">
<img src="https://avatars.githubusercontent.com/u/956928?v=4" width="100;" alt="altschuler"/>
@@ -515,7 +529,8 @@ Here are some ways of contributing to making Nhost better:
<br />
<sub><b>Vadim</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/TheRedLancer">
<img src="https://avatars.githubusercontent.com/u/58493767?v=4" width="100;" alt="TheRedLancer"/>
@@ -529,8 +544,7 @@ Here are some ways of contributing to making Nhost better:
<br />
<sub><b>Komninos</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/meesvandongen">
<img src="https://avatars.githubusercontent.com/u/35409045?v=4" width="100;" alt="meesvandongen"/>

View File

@@ -1,5 +1,30 @@
# @nhost/dashboard
## 0.5.0
### Minor Changes
- a48dd5bf: feat(dashboard): make backend port configurable
## 0.4.3
### Patch Changes
- 5de965d9: fix(dashboard): alphabetic ordering of providers
- b9087a4a: fix(dashboard): console -> dashboard terminology
- ca012d79: docs(workos): WorkOS Docs
## 0.4.2
### Patch Changes
- 89bd37bc: fix(dashboard): correct redirect URL input opacity
- Updated dependencies [4601d84e]
- Updated dependencies [843087cb]
- @nhost/react@0.15.0
- @nhost/nextjs@1.9.0
- @nhost/react-apollo@4.9.0
## 0.4.1
### Patch Changes

View File

@@ -1,4 +1,3 @@
FROM node:16-alpine AS pruner
RUN apk add --no-cache libc6-compat
RUN apk update
@@ -17,12 +16,15 @@ RUN apk update
WORKDIR /app
ENV NEXT_TELEMETRY_DISABLED 1
ENV NEXT_PUBLIC_NHOST_PLATFORM false
ENV NEXT_PUBLIC_NHOST_MIGRATIONS_URL http://localhost:9693
ENV NEXT_PUBLIC_NHOST_HASURA_URL http://localhost:9695
ENV NEXT_PUBLIC_ENV dev
ENV NEXT_PUBLIC_NHOST_PLATFORM false
RUN yarn global add pnpm
# placeholders for ports, will be replaced on runtime by entrypoint script
ENV NEXT_PUBLIC_NHOST_MIGRATIONS_PORT __NEXT_PUBLIC_NHOST_MIGRATIONS_PORT__
ENV NEXT_PUBLIC_NHOST_HASURA_PORT __NEXT_PUBLIC_NHOST_HASURA_PORT__
ENV NEXT_PUBLIC_NHOST_LOCAL_BACKEND_PORT __NEXT_PUBLIC_NHOST_LOCAL_BACKEND_PORT__
RUN yarn global add pnpm@7.17.0
COPY .gitignore .gitignore
COPY --from=pruner /app/out/json/ .
COPY --from=pruner /app/out/pnpm-*.yaml .
@@ -40,11 +42,14 @@ RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
USER nextjs
COPY --from=builder /app/dashboard/next.config.js .
COPY --from=builder /app/dashboard/package.json .
COPY --from=builder /app/dashboard/public ./dashboard/public
COPY --chown=nextjs:nodejs dashboard/docker-entrypoint.sh .
COPY --from=builder --chown=nextjs:nodejs /app/dashboard/next.config.js .
COPY --from=builder --chown=nextjs:nodejs /app/dashboard/package.json .
COPY --from=builder --chown=nextjs:nodejs /app/dashboard/public ./dashboard/public
COPY --from=builder --chown=nextjs:nodejs /app/dashboard/.next/standalone/app ./
COPY --from=builder --chown=nextjs:nodejs /app/dashboard/.next/static ./dashboard/.next/static
CMD node dashboard/server.js
ENTRYPOINT ["./docker-entrypoint.sh"]
CMD ["node", "dashboard/server.js"]

View File

@@ -30,31 +30,27 @@ First, you need to run the following command to start your backend locally:
cd <your_nhost_project> && nhost dev
```
Two environment variables are required to connect the Nhost Dashboard to your local backend:
You can connect the Nhost Dashboard to your locally running backend by setting the following environment variables in `.env.development.local`:
- `NEXT_PUBLIC_NHOST_PLATFORM` should be set to `false`, because otherwise the Nhost Dashboard will try to connect to the Nhost platform.
- `NEXT_PUBLIC_NHOST_MIGRATIONS_URL` should be set to `http://localhost:9693` unless Hasura is configured to run on a different port. This is the URL of Hasura's migrations endpoint.
Example:
```
```bash
NEXT_PUBLIC_ENV=dev
NEXT_PUBLIC_NHOST_PLATFORM=false
NEXT_PUBLIC_NHOST_MIGRATIONS_URL=http://localhost:9693
```
### Full list of environment variables
| Name | Description |
| ------------------------------------ | ------------------------------------------------------------------------------------------------ |
| `NEXT_PUBLIC_NHOST_PLATFORM` | This should be set to `false` to connect the Nhost Dashboard to a locally running Nhost backend. |
| `NEXT_PUBLIC_NHOST_MIGRATIONS_URL` | URL of Hasura's migrations endpoint. Used only if local development is enabled. |
| `NEXT_PUBLIC_NHOST_HASURA_URL` | URL of the Hasura Console. Used only when `NEXT_PUBLIC_ENV` is `dev`. |
| `NEXT_PUBLIC_ENV` | `dev`, `staging` or `prod`. Should be set to `dev` in most cases. |
| `NEXT_PUBLIC_NHOST_BACKEND_URL` | Backend URL. Not necessary for local development. |
| `NEXT_PUBLIC_STRIPE_PK` | Stripe public key. Not necessary for local development. |
| `NEXT_PUBLIC_GITHUB_APP_INSTALL_URL` | URL of the GitHub application. Not necessary for local development. |
| `NEXT_PUBLIC_ANALYTICS_WRITE_KEY` | Analytics key. Not necessary for local development. |
| `NEXT_PUBLIC_NHOST_BRAGI_WEBSOCKET` | URL of the Bragi websocket. Not necessary for local development. |
| Name | Description |
| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NEXT_PUBLIC_ENV` | `dev`, `staging` or `prod`. Should be set to `dev` in most cases. |
| `NEXT_PUBLIC_NHOST_PLATFORM` | This should be set to `false` to connect the Nhost Dashboard to a locally running Nhost backend. Setting this to `true` turns off local development. |
| `NEXT_PUBLIC_NHOST_LOCAL_MIGRATIONS_PORT` | Custom port that was passed to the CLI. Used only if local development is enabled. Default: `9693` |
| `NEXT_PUBLIC_NHOST_LOCAL_HASURA_PORT` | Custom port that was passed to the CLI. Used only if local development is enabled and `NEXT_PUBLIC_ENV` is `dev`. Default: `9695` |
| `NEXT_PUBLIC_NHOST_LOCAL_BACKEND_PORT` | Custom port that was passed to the CLI. Used only if local development is enabled. Default: `1337` |
| `NEXT_PUBLIC_NHOST_BACKEND_URL` | Backend URL. Not necessary for local development. |
| `NEXT_PUBLIC_STRIPE_PK` | Stripe public key. Not necessary for local development. |
| `NEXT_PUBLIC_GITHUB_APP_INSTALL_URL` | URL of the GitHub application. Not necessary for local development. |
| `NEXT_PUBLIC_ANALYTICS_WRITE_KEY` | Analytics key. Not necessary for local development. |
| `NEXT_PUBLIC_NHOST_BRAGI_WEBSOCKET` | URL of the Bragi websocket. Not necessary for local development. |
## ESLint Rules
@@ -67,6 +63,7 @@ NEXT_PUBLIC_NHOST_MIGRATIONS_URL=http://localhost:9693
| `import/extensions` | JS / TS files should be imported without file extensions. |
| `react/jsx-filename-extension` | JSX should only appear in `.jsx` and `.tsx` files. |
| `react/jsx-no-bind` | Further investigation must be made on the performance impact of functions directly passed as props to components. |
| `import/order` | Until we have a better auto-formatter, we disable this rule. |
| `import/no-extraneous-dependencies` | `devDependencies` should be excluded from the list of disallowed imports. |
| `curly` | By default it only enforces curly braces for multi-line blocks, but it should be enforced for single-line blocks as well. |
| `no-restricted-exports` | `export { default } from './module'` is used heavily in `@/ui/v2` which is a restricted export by default. |

15
dashboard/docker-entrypoint.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
set -e
# read ports from env variables or use defaults
NEXT_PUBLIC_NHOST_MIGRATIONS_PORT="${NEXT_PUBLIC_NHOST_MIGRATIONS_PORT:=9693}"
NEXT_PUBLIC_NHOST_HASURA_PORT="${NEXT_PUBLIC_NHOST_HASURA_PORT:=9695}"
NEXT_PUBLIC_NHOST_LOCAL_BACKEND_PORT="${NEXT_PUBLIC_NHOST_LOCAL_BACKEND_PORT:=1337}"
# replace placeholders
find dashboard -type f -exec sed -i "s/__NEXT_PUBLIC_NHOST_MIGRATIONS_PORT__/${NEXT_PUBLIC_NHOST_MIGRATIONS_PORT}/g" {} +
find dashboard -type f -exec sed -i "s/__NEXT_PUBLIC_NHOST_HASURA_PORT__/${NEXT_PUBLIC_NHOST_HASURA_PORT}/g" {} +
find dashboard -type f -exec sed -i "s/__NEXT_PUBLIC_NHOST_LOCAL_BACKEND_PORT__/${NEXT_PUBLIC_NHOST_LOCAL_BACKEND_PORT}/g" {} +
exec "$@"

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/dashboard",
"version": "0.4.1",
"version": "0.5.0",
"private": true,
"scripts": {
"preinstall": "npx only-allow pnpm",
@@ -35,10 +35,10 @@
"@mui/system": "^5.10.14",
"@mui/x-date-pickers": "^5.0.8",
"@nhost/core": "^0.9.3",
"@nhost/nextjs": "^1.8.3",
"@nhost/nextjs": "^1.9.0",
"@nhost/nhost-js": "^1.6.1",
"@nhost/react": "^0.14.3",
"@nhost/react-apollo": "^4.8.3",
"@nhost/react": "^0.15.0",
"@nhost/react-apollo": "^4.9.0",
"@segment/snippet": "^4.15.3",
"@tailwindcss/forms": "^0.5.3",
"@tanstack/react-query": "^4.16.1",
@@ -169,4 +169,4 @@
"last 1 safari version"
]
}
}
}

View File

@@ -0,0 +1 @@
<svg width="21" height="21" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10.08 0c5.578 0 10.08 4.507 10.08 10.09 0 5.584-4.502 10.09-10.08 10.09A10.072 10.072 0 0 1 0 10.09C0 4.507 4.503 0 10.08 0Zm0 2.69a7.375 7.375 0 0 0-7.392 7.4c0 4.104 3.293 7.4 7.392 7.4 4.1 0 7.392-3.296 7.392-7.4 0-4.103-3.293-7.4-7.392-7.4Zm-2.486 7.804c1.142 0 2.083.942 2.083 2.085 0 1.144-.94 2.086-2.083 2.086a2.095 2.095 0 0 1-2.083-2.086c0-1.143.94-2.085 2.083-2.085Zm4.973 0c1.142 0 2.083.942 2.083 2.085 0 1.144-.94 2.086-2.083 2.086a2.095 2.095 0 0 1-2.084-2.086c0-1.143.941-2.085 2.084-2.085Zm0-4.978c1.142 0 2.083.942 2.083 2.085 0 1.144-.94 2.086-2.083 2.086A2.095 2.095 0 0 1 10.483 7.6c0-1.143.941-2.085 2.084-2.085Zm-4.973 0c1.142 0 2.083.942 2.083 2.085 0 1.144-.94 2.086-2.083 2.086A2.095 2.095 0 0 1 5.51 7.6c0-1.143.94-2.085 2.083-2.085Z" fill="#F22F46"/></svg>

After

Width:  |  Height:  |  Size: 869 B

View File

@@ -5,6 +5,7 @@ import Button from '@/ui/v2/Button';
import ArrowSquareOutIcon from '@/ui/v2/icons/ArrowSquareOutIcon';
import Link from '@/ui/v2/Link';
import Text from '@/ui/v2/Text';
import { LOCAL_HASURA_URL } from '@/utils/env';
import { generateRemoteAppUrl } from '@/utils/helpers';
import Image from 'next/image';
@@ -24,7 +25,7 @@ export function HasuraData({ close }: HasuraDataProps) {
const hasuraUrl =
process.env.NEXT_PUBLIC_ENV === 'dev'
? process.env.NEXT_PUBLIC_NHOST_HASURA_URL || 'http://localhost:9695'
? LOCAL_HASURA_URL
: generateRemoteAppUrl(currentApplication.subdomain);
return (

View File

@@ -79,7 +79,7 @@ export default function AnonymousSignInSettings() {
<Form onSubmit={handlePasswordProtectionSettingsChange}>
<SettingsContainer
title="Anonymous Users"
description="Allow users to sign-in anonymously."
description="Allow users to sign in anonymously."
primaryActionButtonProps={{
disabled:
form.formState.isSubmitting ||

View File

@@ -107,7 +107,7 @@ export default function AppleProviderSettings() {
<Form onSubmit={handleProviderUpdate}>
<SettingsContainer
title="Apple"
description="Allows users to sign in with Apple."
description="Allow users to sign in with Apple."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,
@@ -168,7 +168,7 @@ export default function AppleProviderSettings() {
<Input
name="redirectUrl"
id="redirectUrl"
placeholder={`${generateRemoteAppUrl(
defaultValue={`${generateRemoteAppUrl(
currentApplication.subdomain,
)}/v1/auth/signin/provider/apple/callback`}
className="col-span-2"

View File

@@ -88,7 +88,7 @@ export default function DiscordProviderSettings() {
<Form onSubmit={handleProviderUpdate}>
<SettingsContainer
title="Discord"
description="Allows users to sign in with Discord."
description="Allow users to sign in with Discord."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,
@@ -112,7 +112,7 @@ export default function DiscordProviderSettings() {
fullWidth
hideEmptyHelperText
label="Redirect URL"
value={`${generateRemoteAppUrl(
defaultValue={`${generateRemoteAppUrl(
currentApplication.subdomain,
)}/v1/auth/signin/provider/discord/callback`}
disabled

View File

@@ -23,7 +23,7 @@ export interface EmailAndPasswordFormValues {
authPasswordHibpEnabled: boolean;
}
export default function EmailSettings() {
export default function EmailAndPasswordSettings() {
const { currentApplication } = useCurrentWorkspaceAndApplication();
const [updateApp] = useUpdateAppMutation({
refetchQueries: [GetAppLoginDataDocument],
@@ -61,7 +61,7 @@ export default function EmailSettings() {
const { formState } = form;
const handleEmailSettingsChange = async (
const handleEmailAndPasswordSettingsChange = async (
values: EmailAndPasswordFormValues,
) => {
const updateAppMutation = updateApp({
@@ -90,10 +90,10 @@ export default function EmailSettings() {
return (
<FormProvider {...form}>
<Form onSubmit={handleEmailSettingsChange}>
<Form onSubmit={handleEmailAndPasswordSettingsChange}>
<SettingsContainer
title="Email and Password"
description="Sign in users using email and password."
description="Allow users to sign in with email and password."
docsLink="https://docs.nhost.io/authentication/sign-in-with-email-and-password"
docsTitle="how to sign in users with email and password"
className="grid grid-flow-row"
@@ -109,10 +109,8 @@ export default function EmailSettings() {
name="authEmailSigninEmailVerifiedRequired"
id="authEmailSigninEmailVerifiedRequired"
label={
<span className="inline-grid grid-flow-row gap-y-[2px] text-[15px]">
<span className="text-[15px] font-medium">
Require Verified Emails
</span>
<span className="inline-grid grid-flow-row gap-y-0.5 text-sm+">
<span className="font-medium">Require Verified Emails</span>
<span className="font-normal text-greyscaleMedium">
Users must verify their email to be able to sign in.
</span>
@@ -124,11 +122,9 @@ export default function EmailSettings() {
name="authPasswordHibpEnabled"
id="authPasswordHibpEnabled"
label={
<span className="inline-grid grid-flow-row gap-y-[2px] text-[15px]">
<span className="text-[15px] font-medium">
Password Protection
</span>
<span className="text-[12px] font-normal text-greyscaleMedium">
<span className="inline-grid grid-flow-row gap-y-0.5 text-sm+">
<span className="font-medium">Password Protection</span>
<span className="font-normal text-greyscaleMedium">
Passwords must pass haveibeenpwned.com during sign-up.
</span>
</span>

View File

@@ -0,0 +1,2 @@
export * from './EmailAndPasswordSettings';
export { default } from './EmailAndPasswordSettings';

View File

@@ -1,2 +0,0 @@
export * from './EmailSettings';
export { default } from './EmailSettings';

View File

@@ -88,7 +88,7 @@ export default function FacebookProviderSettings() {
<Form onSubmit={handleProviderUpdate}>
<SettingsContainer
title="Facebook"
description="Allows users to sign in with Facebook."
description="Allow users to sign in with Facebook."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,
@@ -112,7 +112,7 @@ export default function FacebookProviderSettings() {
fullWidth
hideEmptyHelperText
label="Redirect URL"
value={`${generateRemoteAppUrl(
defaultValue={`${generateRemoteAppUrl(
currentApplication.subdomain,
)}/v1/auth/signin/provider/facebook/callback`}
disabled

View File

@@ -88,7 +88,7 @@ export default function GitHubProviderSettings() {
<Form onSubmit={handleProviderUpdate}>
<SettingsContainer
title="GitHub"
description="Allows users to sign in with GitHub."
description="Allow users to sign in with GitHub."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,
@@ -112,7 +112,7 @@ export default function GitHubProviderSettings() {
fullWidth
hideEmptyHelperText
label="Redirect URL"
value={`${generateRemoteAppUrl(
defaultValue={`${generateRemoteAppUrl(
currentApplication.subdomain,
)}/v1/auth/signin/provider/github/callback`}
disabled

View File

@@ -88,7 +88,7 @@ export default function GoogleProviderSettings() {
<Form onSubmit={handleProviderUpdate}>
<SettingsContainer
title="Google"
description="Allows users to sign in with Google."
description="Allow users to sign in with Google."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,
@@ -112,7 +112,7 @@ export default function GoogleProviderSettings() {
fullWidth
hideEmptyHelperText
label="Redirect URL"
value={`${generateRemoteAppUrl(
defaultValue={`${generateRemoteAppUrl(
currentApplication.subdomain,
)}/v1/auth/signin/provider/google/callback`}
disabled

View File

@@ -88,7 +88,7 @@ export default function LinkedInProviderSettings() {
<Form onSubmit={handleProviderUpdate}>
<SettingsContainer
title="LinkedIn"
description="Allows users to sign in with LinkedIn"
description="Allow users to sign in with LinkedIn."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,
@@ -112,7 +112,7 @@ export default function LinkedInProviderSettings() {
fullWidth
hideEmptyHelperText
label="Redirect URL"
value={`${generateRemoteAppUrl(
defaultValue={`${generateRemoteAppUrl(
currentApplication.subdomain,
)}/v1/auth/signin/provider/linkedin/callback`}
disabled

View File

@@ -80,7 +80,7 @@ export default function MagicLinkSettings() {
<Form onSubmit={handleMagicLinkSettingsUpdate}>
<SettingsContainer
title="Magic Link"
description="Allow users to sign-in with a magic link."
description="Allow users to sign in with a magic link."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,

View File

@@ -88,7 +88,7 @@ export default function SpotifyProviderSettings() {
<Form onSubmit={handleProviderUpdate}>
<SettingsContainer
title="Spotify"
description="Allows users to sign in with Spotify."
description="Allow users to sign in with Spotify."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,
@@ -112,7 +112,7 @@ export default function SpotifyProviderSettings() {
fullWidth
hideEmptyHelperText
label="Redirect URL"
value={`${generateRemoteAppUrl(
defaultValue={`${generateRemoteAppUrl(
currentApplication.subdomain,
)}/v1/auth/signin/provider/spotify/callback`}
disabled

View File

@@ -88,7 +88,7 @@ export default function TwitchProviderSettings() {
<Form onSubmit={handleProviderUpdate}>
<SettingsContainer
title="Twitch"
description="Allows users to sign in with Twitch."
description="Allow users to sign in with Twitch."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,
@@ -112,7 +112,7 @@ export default function TwitchProviderSettings() {
fullWidth
hideEmptyHelperText
label="Redirect URL"
value={`${generateRemoteAppUrl(
defaultValue={`${generateRemoteAppUrl(
currentApplication.subdomain,
)}/v1/auth/signin/provider/twitch/callback`}
disabled

View File

@@ -87,7 +87,7 @@ export default function TwitterProviderSettings() {
<Form onSubmit={handleProviderUpdate}>
<SettingsContainer
title="Twitter"
description="Allows users to sign in with Twitter."
description="Allow users to sign in with Twitter."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,
@@ -125,7 +125,7 @@ export default function TwitterProviderSettings() {
<Input
name="redirectUrl"
id="redirectUrl"
placeholder={`${generateRemoteAppUrl(
defaultValue={`${generateRemoteAppUrl(
currentApplication.subdomain,
)}/v1/auth/signin/provider/twitter/callback`}
className="col-span-2"
@@ -133,11 +133,6 @@ export default function TwitterProviderSettings() {
hideEmptyHelperText
label="Redirect URL"
disabled
slotProps={{
input: {
className: 'bg-opacity-5',
},
}}
endAdornment={
<InputAdornment position="end" className="absolute right-2">
<IconButton

View File

@@ -81,7 +81,7 @@ export default function WebAuthnSettings() {
<Form onSubmit={handleWebAuthnSettingsUpdate}>
<SettingsContainer
title="Security Keys"
description="Allow users to sign-in with security keys using WebAuthn."
description="Allow users to sign in with security keys using WebAuthn."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,

View File

@@ -88,7 +88,7 @@ export default function WindowsLiveProviderSettings() {
<Form onSubmit={handleProviderUpdate}>
<SettingsContainer
title="Windows Live"
description="Allows users to sign in with Windows Live."
description="Allow users to sign in with Windows Live."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,
@@ -111,7 +111,7 @@ export default function WindowsLiveProviderSettings() {
fullWidth
hideEmptyHelperText
label="Redirect URL"
value={`${generateRemoteAppUrl(
defaultValue={`${generateRemoteAppUrl(
currentApplication.subdomain,
)}/v1/auth/signin/provider/microsoft/callback`}
disabled

View File

@@ -94,11 +94,13 @@ export default function WorkOsProviderSettings() {
<Form onSubmit={handleProviderUpdate}>
<SettingsContainer
title="WorkOS"
description="Allows users to sign in with WorkOS."
description="Allow users to sign in with WorkOS."
primaryActionButtonProps={{
disabled: !formState.isValid || !formState.isDirty,
loading: formState.isSubmitting,
}}
docsLink="https://docs.nhost.io/authentication/sign-in-with-workos"
docsTitle="how to sign in users with WorkOS"
icon="/logos/WorkOs.svg"
switchId="authWorkOsEnabled"
showSwitch
@@ -112,8 +114,8 @@ export default function WorkOsProviderSettings() {
{...register(`authWorkOsClientId`)}
name="authWorkOsClientId"
id="authWorkOsClientId"
label="WorkOS Client ID"
placeholder="WorkOS Client ID"
label="Client ID"
placeholder="Enter your Client ID"
className="col-span-3"
fullWidth
hideEmptyHelperText
@@ -122,28 +124,28 @@ export default function WorkOsProviderSettings() {
{...register('authWorkOsClientSecret')}
name="authWorkOsClientSecret"
id="authWorkOsClientSecret"
label="WorkOS Client Secret"
placeholder="WorkOS Client Secret"
label="Client Secret"
placeholder="Enter your Client Secret"
className="col-span-3"
fullWidth
hideEmptyHelperText
/>
<Input
{...register('authWorkOsDefaultDomain')}
name="authWorkOsDefaultDomain"
id="authWorkOsDefaultDomain"
label="Default Domain"
placeholder="Default Domain"
className="col-span-2"
fullWidth
hideEmptyHelperText
/>
<Input
{...register('authWorkOsDefaultOrganization')}
name="authWorkOsDefaultOrganization"
id="authWorkOsDefaultOrganization"
label="Default Organization"
placeholder="Default Organization"
label="Default Organization ID (optional)"
placeholder="Default Organization ID"
className="col-span-2"
fullWidth
hideEmptyHelperText
/>
<Input
{...register('authWorkOsDefaultDomain')}
name="authWorkOsDefaultDomain"
id="authWorkOsDefaultDomain"
label="Default Domain (optional)"
placeholder="Default Domain"
className="col-span-2"
fullWidth
hideEmptyHelperText
@@ -152,7 +154,7 @@ export default function WorkOsProviderSettings() {
{...register('authWorkOsDefaultConnection')}
name="authWorkOsDefaultConnection"
id="authWorkOsDefaultConnection"
label="Default Connection"
label="Default Connection (optional)"
placeholder="Default Connection"
className="col-span-2"
fullWidth
@@ -161,7 +163,7 @@ export default function WorkOsProviderSettings() {
<Input
name="redirectUrl"
id="redirectUrl"
placeholder={`${generateRemoteAppUrl(
defaultValue={`${generateRemoteAppUrl(
currentApplication.subdomain,
)}/v1/auth/signin/provider/workos/callback`}
className="col-span-6"
@@ -169,11 +171,6 @@ export default function WorkOsProviderSettings() {
hideEmptyHelperText
label="Redirect URL"
disabled
slotProps={{
input: {
className: 'bg-opacity-5',
},
}}
endAdornment={
<InputAdornment position="end" className="absolute right-2">
<IconButton

View File

@@ -7,6 +7,7 @@ import type {
} from '@/types/data-browser';
import { getPreparedHasuraQuery } from '@/utils/dataBrowser/hasuraQueryHelpers';
import normalizeQueryError from '@/utils/dataBrowser/normalizeQueryError';
import { LOCAL_MIGRATIONS_URL } from '@/utils/env';
import prepareCreateColumnQuery from './prepareCreateColumnQuery';
export interface CreateColumnMigrationVariables {
@@ -33,30 +34,27 @@ export default async function createColumnMigration({
column,
});
const response = await fetch(
`${process.env.NEXT_PUBLIC_NHOST_MIGRATIONS_URL}/apis/migrate`,
{
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `alter_table_${schema}_${table}_add_column_${column.name}`,
down: [
getPreparedHasuraQuery(
dataSource,
'ALTER TABLE %I.%I DROP COLUMN IF EXISTS %I',
schema,
table,
column.name,
),
],
up: args,
}),
const response = await fetch(`${LOCAL_MIGRATIONS_URL}/apis/migrate`, {
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
);
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `alter_table_${schema}_${table}_add_column_${column.name}`,
down: [
getPreparedHasuraQuery(
dataSource,
'ALTER TABLE %I.%I DROP COLUMN IF EXISTS %I',
schema,
table,
column.name,
),
],
up: args,
}),
});
const responseData: [AffectedRowsResult, QueryResult<string[]>] | QueryError =
await response.json();

View File

@@ -7,6 +7,7 @@ import type {
} from '@/types/data-browser';
import { getPreparedHasuraQuery } from '@/utils/dataBrowser/hasuraQueryHelpers';
import normalizeQueryError from '@/utils/dataBrowser/normalizeQueryError';
import { LOCAL_MIGRATIONS_URL } from '@/utils/env';
import prepareCreateTableQuery from './prepareCreateTableQuery';
export interface CreateTableMigrationVariables {
@@ -27,29 +28,26 @@ export default async function createTableMigration({
}: CreateTableMigrationOptions & CreateTableMigrationVariables) {
const args = prepareCreateTableQuery({ dataSource, schema, table });
const response = await fetch(
`${process.env.NEXT_PUBLIC_NHOST_MIGRATIONS_URL}/apis/migrate`,
{
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `create_table_${schema}_${table.name}`,
down: [
getPreparedHasuraQuery(
dataSource,
'DROP TABLE IF EXISTS %I.%I',
schema,
table.name,
),
],
up: args,
}),
const response = await fetch(`${LOCAL_MIGRATIONS_URL}/apis/migrate`, {
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
);
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `create_table_${schema}_${table.name}`,
down: [
getPreparedHasuraQuery(
dataSource,
'DROP TABLE IF EXISTS %I.%I',
schema,
table.name,
),
],
up: args,
}),
});
const responseData: [AffectedRowsResult, QueryResult<string[]>] | QueryError =
await response.json();

View File

@@ -8,6 +8,7 @@ import type {
} from '@/types/data-browser';
import { getPreparedHasuraQuery } from '@/utils/dataBrowser/hasuraQueryHelpers';
import normalizeQueryError from '@/utils/dataBrowser/normalizeQueryError';
import { LOCAL_MIGRATIONS_URL } from '@/utils/env';
export interface DeleteColumnMigrationVariables {
/**
@@ -45,30 +46,27 @@ export default async function deleteColumnMigration({
},
});
const response = await fetch(
`${process.env.NEXT_PUBLIC_NHOST_MIGRATIONS_URL}/apis/migrate`,
{
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `alter_table_${schema}_${table}_drop_column_${column.id}`,
down: recreateColumnArgs,
up: [
getPreparedHasuraQuery(
dataSource,
'ALTER TABLE %I.%I DROP COLUMN IF EXISTS %I CASCADE',
schema,
table,
column.id,
),
],
}),
const response = await fetch(`${LOCAL_MIGRATIONS_URL}/apis/migrate`, {
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
);
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `alter_table_${schema}_${table}_drop_column_${column.id}`,
down: recreateColumnArgs,
up: [
getPreparedHasuraQuery(
dataSource,
'ALTER TABLE %I.%I DROP COLUMN IF EXISTS %I CASCADE',
schema,
table,
column.id,
),
],
}),
});
const responseData: [AffectedRowsResult, QueryResult<string[]>] | QueryError =
await response.json();

View File

@@ -9,6 +9,7 @@ import {
getPreparedHasuraQuery,
} from '@/utils/dataBrowser/hasuraQueryHelpers';
import normalizeQueryError from '@/utils/dataBrowser/normalizeQueryError';
import { LOCAL_MIGRATIONS_URL } from '@/utils/env';
export interface DeleteTableMigrationVariables {
/**
@@ -39,32 +40,29 @@ export default async function deleteTable({
),
];
const response = await fetch(
`${process.env.NEXT_PUBLIC_NHOST_MIGRATIONS_URL}/apis/migrate`,
{
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `drop_table_${schema}_${table}`,
down: [
{
type: 'run_sql',
args: {
cascade: false,
read_only: false,
source: '',
sql: getEmptyDownMigrationMessage(deleteTableArgs),
},
},
],
up: deleteTableArgs,
}),
const response = await fetch(`${LOCAL_MIGRATIONS_URL}/apis/migrate`, {
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
);
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `drop_table_${schema}_${table}`,
down: [
{
type: 'run_sql',
args: {
cascade: false,
read_only: false,
source: '',
sql: getEmptyDownMigrationMessage(deleteTableArgs),
},
},
],
up: deleteTableArgs,
}),
});
const responseData: [AffectedRowsResult, QueryResult<string[]>] | QueryError =
await response.json();

View File

@@ -6,6 +6,7 @@ import type {
QueryResult,
} from '@/types/data-browser';
import normalizeQueryError from '@/utils/dataBrowser/normalizeQueryError';
import { LOCAL_MIGRATIONS_URL } from '@/utils/env';
import prepareTrackForeignKeyRelationsMetadata from './prepareTrackForeignKeyRelationsMetadata';
export interface TrackForeignKeyRelationsMigrationVariables {
@@ -45,23 +46,20 @@ export default async function trackForeignKeyRelationsMigration({
foreignKeyRelations,
});
const response = await fetch(
`${process.env.NEXT_PUBLIC_NHOST_MIGRATIONS_URL}/apis/migrate`,
{
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `track_foreign_key_relations_${schema}_${table}`,
down: [],
up: creatableRelationships,
}),
const response = await fetch(`${LOCAL_MIGRATIONS_URL}/apis/migrate`, {
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
);
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `track_foreign_key_relations_${schema}_${table}`,
down: [],
up: creatableRelationships,
}),
});
const responseData: [AffectedRowsResult, QueryResult<string[]>] | QueryError =
await response.json();

View File

@@ -6,6 +6,7 @@ import type {
QueryResult,
} from '@/types/data-browser';
import normalizeQueryError from '@/utils/dataBrowser/normalizeQueryError';
import { LOCAL_MIGRATIONS_URL } from '@/utils/env';
export interface TrackTableMigrationVariables {
/**
@@ -23,32 +24,29 @@ export default async function trackTableMigration({
adminSecret,
table,
}: TrackTableMigrationOptions & TrackTableMigrationVariables) {
const response = await fetch(
`${process.env.NEXT_PUBLIC_NHOST_MIGRATIONS_URL}/apis/migrate`,
{
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `add_existing_table_or_view_${schema}_${table.name}`,
down: [
{
type: 'pg_untrack_table',
args: { source: dataSource, table: { schema, name: table.name } },
},
],
up: [
{
args: { source: dataSource, table: { schema, name: table.name } },
type: 'pg_track_table',
},
],
}),
const response = await fetch(`${LOCAL_MIGRATIONS_URL}/apis/migrate`, {
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
);
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `add_existing_table_or_view_${schema}_${table.name}`,
down: [
{
type: 'pg_untrack_table',
args: { source: dataSource, table: { schema, name: table.name } },
},
],
up: [
{
args: { source: dataSource, table: { schema, name: table.name } },
type: 'pg_track_table',
},
],
}),
});
const responseData: [AffectedRowsResult, QueryResult<string[]>] | QueryError =
await response.json();

View File

@@ -7,6 +7,7 @@ import type {
} from '@/types/data-browser';
import { getEmptyDownMigrationMessage } from '@/utils/dataBrowser/hasuraQueryHelpers';
import normalizeQueryError from '@/utils/dataBrowser/normalizeQueryError';
import { LOCAL_MIGRATIONS_URL } from '@/utils/env';
import prepareUpdateColumnQuery from './prepareUpdateColumnQuery';
export interface UpdateColumnMigrationVariables {
@@ -65,22 +66,19 @@ export default async function updateColumnMigration({
];
}
const response = await fetch(
`${process.env.NEXT_PUBLIC_NHOST_MIGRATIONS_URL}/apis/migrate`,
{
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `alter_table_${schema}_${table}_alter_column_${originalColumn.name}`,
down: columnUpdateDownMigration,
up: columnUpdateUpMigration,
}),
const response = await fetch(`${LOCAL_MIGRATIONS_URL}/apis/migrate`, {
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
);
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `alter_table_${schema}_${table}_alter_column_${originalColumn.name}`,
down: columnUpdateDownMigration,
up: columnUpdateUpMigration,
}),
});
const responseData: [AffectedRowsResult, QueryResult<string[]>] | QueryError =
await response.json();

View File

@@ -10,6 +10,7 @@ import type {
} from '@/types/data-browser';
import { getEmptyDownMigrationMessage } from '@/utils/dataBrowser/hasuraQueryHelpers';
import normalizeQueryError from '@/utils/dataBrowser/normalizeQueryError';
import { LOCAL_MIGRATIONS_URL } from '@/utils/env';
import prepareUpdateTableQuery from './prepareUpdateTableQuery';
export interface UpdateTableMigrationVariables {
@@ -56,32 +57,29 @@ export default async function updateTableMigration({
return;
}
const response = await fetch(
`${process.env.NEXT_PUBLIC_NHOST_MIGRATIONS_URL}/apis/migrate`,
{
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `alter_table_${schema}_${originalTable.table_name}`,
down: [
{
type: 'run_sql',
args: {
cascade: false,
read_only: false,
source: '',
sql: getEmptyDownMigrationMessage(args),
},
},
],
up: args,
}),
const response = await fetch(`${LOCAL_MIGRATIONS_URL}/apis/migrate`, {
method: 'POST',
headers: {
'x-hasura-admin-secret': adminSecret,
},
);
body: JSON.stringify({
dataSource,
skip_execution: false,
name: `alter_table_${schema}_${originalTable.table_name}`,
down: [
{
type: 'run_sql',
args: {
cascade: false,
read_only: false,
source: '',
sql: getEmptyDownMigrationMessage(args),
},
},
],
up: args,
}),
});
const responseData: [AffectedRowsResult, QueryResult<string[]>] | QueryError =
await response.json();

View File

@@ -1,3 +1,4 @@
import { LOCAL_SUBDOMAIN } from '@/utils/env';
import { isDevOrStaging } from '@/utils/helpers';
import type { NhostClientConstructorParams } from '@nhost/nhost-js';
import { NhostClient } from '@nhost/nhost-js';
@@ -20,7 +21,7 @@ export function useAppClient(
if (process.env.NEXT_PUBLIC_ENV === 'dev') {
return new NhostClient({
subdomain: 'localhost:1337',
subdomain: LOCAL_SUBDOMAIN,
start: false,
...options,
});

View File

@@ -3,7 +3,7 @@ import SettingsLayout from '@/components/settings/SettingsLayout';
import AnonymousSignInSettings from '@/components/settings/signInMethods/AnonymousSignInSettings';
import AppleProviderSettings from '@/components/settings/signInMethods/AppleProviderSettings';
import DiscordProviderSettings from '@/components/settings/signInMethods/DiscordProviderSettings';
import EmailSettings from '@/components/settings/signInMethods/EmailSettings';
import EmailAndPasswordSettings from '@/components/settings/signInMethods/EmailAndPasswordSettings';
import FacebookProviderSettings from '@/components/settings/signInMethods/FacebookProviderSettings';
import GitHubProviderSettings from '@/components/settings/signInMethods/GitHubProviderSettings';
import GoogleProviderSettings from '@/components/settings/signInMethods/GoogleProviderSettings';
@@ -35,7 +35,7 @@ export default function SettingsSignInMethodsPage() {
return (
<ActivityIndicator
delay={1000}
label="Loading Sign-In Methods Settings..."
label="Loading sign-in method settings..."
className="justify-center"
/>
);
@@ -50,21 +50,21 @@ export default function SettingsSignInMethodsPage() {
className="max-w-5xl space-y-8 bg-fafafa"
wrapperClassName="bg-fafafa"
>
<EmailSettings />
<EmailAndPasswordSettings />
<MagicLinkSettings />
<WebAuthnSettings />
<AnonymousSignInSettings />
<SMSSettings />
<GoogleProviderSettings />
<GitHubProviderSettings />
<LinkedInProviderSettings />
<AppleProviderSettings />
<WindowsLiveProviderSettings />
<DiscordProviderSettings />
<FacebookProviderSettings />
<GitHubProviderSettings />
<GoogleProviderSettings />
<LinkedInProviderSettings />
<SpotifyProviderSettings />
<TwitchProviderSettings />
<DiscordProviderSettings />
<TwitterProviderSettings />
<WindowsLiveProviderSettings />
<WorkOsProviderSettings />
</Container>
);
@@ -72,11 +72,7 @@ export default function SettingsSignInMethodsPage() {
SettingsSignInMethodsPage.getLayout = function getLayout(page: ReactElement) {
return (
<SettingsLayout
mainContainerProps={{
className: 'bg-fafafa',
}}
>
<SettingsLayout mainContainerProps={{ className: 'bg-fafafa' }}>
{page}
</SettingsLayout>
);

View File

@@ -11,8 +11,8 @@ export default class MyDocument extends Document {
render() {
const meta = {
title: 'Nhost 2.0 | Console',
description: 'Nhost Console 2.0',
title: 'Dashboard - Nhost',
description: 'Nhost Dashboard',
image: '/assets/splash.png',
};

View File

@@ -26,5 +26,5 @@ export default function IndexPage() {
}
IndexPage.getLayout = function getLayout(page: ReactElement) {
return <AuthenticatedLayout title="Console">{page}</AuthenticatedLayout>;
return <AuthenticatedLayout title="Dashboard">{page}</AuthenticatedLayout>;
};

View File

@@ -0,0 +1,36 @@
/**
* URL of Hasura's Migration API. This is only used when local development is
* enabled.
*/
export const LOCAL_MIGRATIONS_URL = `http://localhost:${
process.env.NEXT_PUBLIC_NHOST_LOCAL_MIGRATIONS_PORT || 9693
}`;
/**
* Port of the locally running backend.s
*/
export const LOCAL_BACKEND_PORT =
process.env.NEXT_PUBLIC_NHOST_LOCAL_BACKEND_PORT;
/**
* Local subdomain. This is only used when local development is enabled.
*/
export const LOCAL_SUBDOMAIN = LOCAL_BACKEND_PORT
? `localhost:${LOCAL_BACKEND_PORT}`
: 'localhost';
/**
* URL of Hasura Console. This is only used when running the Nhost Dashboard
* locally.
*/
export const LOCAL_HASURA_URL = `http://localhost:${
process.env.NEXT_PUBLIC_NHOST_LOCAL_HASURA_PORT || 9695
}`;
/**
* Backend URL for the locally running instance. This is only used when running
* the Nhost Dashboard locally.
*/
export const LOCAL_BACKEND_URL = `http://localhost:${
process.env.NEXT_PUBLIC_NHOST_LOCAL_BACKEND_PORT || 1337
}`;

View File

@@ -6,6 +6,7 @@ import features from '@/data/features.json';
import { ApplicationStatus } from '@/types/application';
import type { NextRouter } from 'next/router';
import slugify from 'slugify';
import { LOCAL_BACKEND_URL } from './env';
import type { DeploymentRowFragment } from './__generated__/graphql';
export function getLastLiveDeployment(deployments: DeploymentRowFragment[]) {
@@ -57,11 +58,11 @@ export function getCurrentEnvironment(): Environment {
export function generateRemoteAppUrl(subdomain: string): string {
if (process.env.NEXT_PUBLIC_NHOST_PLATFORM !== 'true') {
return 'http://localhost:1337';
return LOCAL_BACKEND_URL;
}
if (process.env.NEXT_PUBLIC_ENV === 'dev') {
return process.env.NEXT_PUBLIC_NHOST_BACKEND_URL || 'http://localhost:1337';
return process.env.NEXT_PUBLIC_NHOST_BACKEND_URL || LOCAL_BACKEND_URL;
}
if (process.env.NEXT_PUBLIC_ENV === 'staging') {

View File

@@ -1,8 +1,9 @@
import { NhostClient } from '@nhost/nextjs';
import { LOCAL_SUBDOMAIN } from './env';
const nhost = new NhostClient({
backendUrl: process.env.NEXT_PUBLIC_NHOST_BACKEND_URL as string,
});
export const nhost =
process.env.NEXT_PUBLIC_NHOST_PLATFORM === 'true'
? new NhostClient({ backendUrl: process.env.NEXT_PUBLIC_NHOST_BACKEND_URL })
: new NhostClient({ subdomain: LOCAL_SUBDOMAIN });
export { nhost };
export default nhost;

View File

@@ -1,5 +1,11 @@
# @nhost/docs
## 0.0.5
### Patch Changes
- ca012d79: docs(workos): WorkOS Docs
## 0.0.4
### Patch Changes

View File

@@ -33,7 +33,7 @@ Follow this guide to sign in users with GitHub.
- Fill in Application Name.
- Fill in Homepage URL.
- Fill in **Authorization callback URL** with your OAuth Callbacke URL from Nhost.
- Fill in **Authorization callback URL** with your OAuth Callback URL from Nhost.
## Configure Nhost

View File

@@ -0,0 +1,67 @@
---
title: Sign In with WorkOS
sidebar_label: WorkOS
slug: /authentication/sign-in-with-workos
image: /img/og/sign-in-with-workos.png
---
Follow this guide to sign in users with WorkOS.
<p align="center">
<img
alt="WorkOS Sign In Preview"
src="/img/social-providers/workos-preview.svg"
width={480}
height={267}
/>
</p>
## Create WorkOS Account
- Go to [WorkOS's website](https://workos.com/).
- Click on **Sign In** in the top menu and create a WorkOS account.
## Get the Client ID
- In the WorkOS dashboard, click on **Configuration** in the left menu.
- Copy the **Client ID**, which starts with `project_`.
- Paste the **Client ID** in the **Client ID** field in the WorkOS settings in the Nhost Dashboard.
## Set correct Redirect URI
- In the WorkOS dashboard, click on **Configuration** in the left menu.
- Click on **Edit Redirect URIs** in the Redirect URIs section.
- Add the **Redirect URL** from the Nhost Dashboard to the list of Redirect URIs.
- Set the newly added redirect URI as the **Default Redirect URI**.
- Click on **Close**.
## Get the Client Secret
- In the WorkOS dashboard, click on **API Keys** in the left menu.
- Click on the eye icon next to the **Client Secret** to reveal it.
- Copy the **Client Secret**, which stars with `sk_`.
- Paste the **Client Secret** in the **Client Secret** field in the WorkOS settings in the Nhost Dashboard.
## Get Organization ID
- In the WorkOS dashboard, click on **Organizations** in the left menu.
- Click on **Create an Organization**.
- Fill in the organization details and click on **Create Organization**.
- Click on the newly created organization.
- Copy the **Organization ID**, which stars with `org_`.
- Paste the **Organization ID** in the **Organization ID** field in the WorkOS settings in the Nhost Dashboard.
- Click **Save** in the Nhost Dashboard to save all WorkOS settings.
The WorkOS configuration is now completed with Nhost.
See the [WorkOS documentation](https://workos.com/docs/) to learn more about how to configure WorkOS.
## Sign In Users
Use the [Nhost JavaScript client](/reference/javascript) to sign in users:
```js
nhost.auth.signIn({
provider: 'workos'
})
```

View File

@@ -88,6 +88,26 @@ custom_claims: '{"organisation-id":"user.profile.organisation.id"}'
JSON columns cannot be used in custom claims, with the exception of the `users.metadata` column.
### Arrays
When the target value is expected to be an array, it is important to explicitly add a `[]` at the end of the expression. For instance: if `organisationIds` is expected to be an array, you must set the expression to `organisationIds[]`. It will otherwise return a litteral when the array is a singleton.
✅ Singleton array with `'{"organisation-ids":"organisationIds[]"}'`
```json
{
"x-hasura-organisation-ids": "{\"org-id-1\"}"
}
```
🛑 Singleton array with `'{"organisation-ids":"organisationIds"}'`
```json
{
"x-hasura-organisation-ids": "org-id-1"
}
```
## Roles
Every GraphQL request is resolved based on a **single role**. Roles are added in the Hasura Console when selecting a table and clicking **Permisisons**.

View File

@@ -12,13 +12,14 @@ Nhost allows you to automatically deploy your Nhost project when you do changes
Support GitLab, BitBucket, and other Git providers are on our roadmap.
## How It Works
## Deployment
The following things are deployed:
- Database migrations
- Hasura metadata
- Serverless Functions
- Email Templates
:::caution
Settings in `nhost/config.yaml` are **not** deployed. That means you need to manually sync settings between local and remote environments between the CLI and Nhost Cloud.
@@ -40,20 +41,14 @@ Settings in `nhost/config.yaml` are **not** deployed. That means you need to man
## Deployment Branch
Nhost only deploys your **deployment branch**. By default, your deployment branch matches the default branch set on GitHub (usually `main`).
Nhost only deploys changes from the **Deployment Branch**. By default, your deployment branch matches the default branch (usually `main`).
You can change the deployment branch by clicking **Edit** next to the repository in your Nhost project's Overview.
You can change the Deployment Branch on the **Git** page in the **Settings** section.
You can have multiple Nhost projects connected to the same GitHub repository and use different deployment branches (e.g., `main` and `staging`).
<center>
<img src="/img/github-integration/deployment-branch.png" alt="drawing" width="50%" />
</center>
It's possible to have multiple Nhost projects connected to the same Git repository and use different Deployment Branches (e.g., `main` and `staging`). Learn more about [multiple environments](/platform/multiple-environments).
## Base Directory
If your Nhost project is not at the root of your git repository (typically when using a monorepo), you can set a custom base directory. The base directory is where the `nhost` directory is located. In other words, the base directory is the **parent directory** of the `nhost` folder.
If your Nhost project is not located at the root of your Git repository, which is typically the case when using a monorepo, it's possible to set a custom Base Directory. The Base Directory is where the `nhost/` directory is located. In other words, the Base Directory is the **parent directory** of the `nhost/` directory.
<center>
<img src="/img/github-integration/base-directory.png" alt="drawing" width="50%" />
</center>
You can change the Base Directory on the **Git** page in the **Settings** section.

View File

@@ -0,0 +1,35 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: <SignedIn />
sidebar_label: <SignedIn />
slug: /reference/nextjs/signed-in
description: Use `<SignedIn />` to control the rendering of components for users. Components inside `<SignedIn />` are only rendered if the user is authenticated.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/components/SignedIn.tsx#L28
---
# `SignedIn()`
Use `<SignedIn />` to control the rendering of components for users. Components inside `<SignedIn />` are only rendered if the user is authenticated.
```tsx
import { NhostProvider, SignedOut } from '@nhost/react'
import { nhost } from '@/utils/nhost'
function Page() {
return (
<NhostProvider nhost={nhost}>
<SignedIn>
<h1>Only rendered if the user is authenticated</h1>
</SignedIn>
</NhostProvider>
)
}
```
## Parameters
---
**<span className="parameter-name">\_\_namedParameters</span>** <span className="optional-status">required</span> `{ children: ReactNode }`
---

View File

@@ -0,0 +1,35 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: <SignedOut />
sidebar_label: <SignedOut />
slug: /reference/nextjs/signed-out
description: Use `<SignedOut />` to control the rendering of components for users. Components inside `<SignedOut />` are only rendered if the user is not authenticated.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/components/SignedOut.tsx#L28
---
# `SignedOut()`
Use `<SignedOut />` to control the rendering of components for users. Components inside `<SignedOut />` are only rendered if the user is not authenticated.
```tsx
import { NhostProvider, SignedOut } from '@nhost/react'
import { nhost } from '@/utils/nhost'
function Page() {
return (
<NhostProvider nhost={nhost}>
<SignedOut>
<h1>Only rendered if the user is not authenticated</h1>
</SignedOut>
</NhostProvider>
)
}
```
## Parameters
---
**<span className="parameter-name">\_\_namedParameters</span>** <span className="optional-status">required</span> `{ children: ReactNode }`
---

View File

@@ -0,0 +1,35 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: <SignedIn />
sidebar_label: <SignedIn />
slug: /reference/react/signed-in
description: Use `<SignedIn />` to control the rendering of components for users. Components inside `<SignedIn />` are only rendered if the user is authenticated.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/components/SignedIn.tsx#L28
---
# `SignedIn()`
Use `<SignedIn />` to control the rendering of components for users. Components inside `<SignedIn />` are only rendered if the user is authenticated.
```tsx
import { NhostProvider, SignedOut } from '@nhost/react'
import { nhost } from '@/utils/nhost'
function Page() {
return (
<NhostProvider nhost={nhost}>
<SignedIn>
<h1>Only rendered if the user is authenticated</h1>
</SignedIn>
</NhostProvider>
)
}
```
## Parameters
---
**<span className="parameter-name">\_\_namedParameters</span>** <span className="optional-status">required</span> `{ children: ReactNode }`
---

View File

@@ -0,0 +1,35 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: <SignedOut />
sidebar_label: <SignedOut />
slug: /reference/react/signed-out
description: Use `<SignedOut />` to control the rendering of components for users. Components inside `<SignedOut />` are only rendered if the user is not authenticated.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/react/src/components/SignedOut.tsx#L28
---
# `SignedOut()`
Use `<SignedOut />` to control the rendering of components for users. Components inside `<SignedOut />` are only rendered if the user is not authenticated.
```tsx
import { NhostProvider, SignedOut } from '@nhost/react'
import { nhost } from '@/utils/nhost'
function Page() {
return (
<NhostProvider nhost={nhost}>
<SignedOut>
<h1>Only rendered if the user is not authenticated</h1>
</SignedOut>
</NhostProvider>
)
}
```
## Parameters
---
**<span className="parameter-name">\_\_namedParameters</span>** <span className="optional-status">required</span> `{ children: ReactNode }`
---

View File

@@ -0,0 +1,44 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: useFileUploadItem()
sidebar_label: useFileUploadItem()
slug: /reference/vue/use-file-upload-item
description: Use the composable `useFileUploadItem` to control the file upload of a file in a multiple file upload.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/vue/src/useFileUpload.ts#L61
---
# `useFileUploadItem()`
Use the composable `useFileUploadItem` to control the file upload of a file in a multiple file upload.
It has the same signature as `useFileUpload`.
```tsx
const Item = ({ itemRef }) => {
const { name, progress } = useFileUploadItem(itemRef)
return (
<li>
{name} {progress}
</li>
)
}
const List = () => {
const { list } = useMultipleFilesUpload()
return (
<ul>
{list.map((itemRef) => (
<Item key={item.id} itemRef={item} />
))}
</ul>
)
}
```
## Parameters
---
**<span className="parameter-name">ref</span>** <span className="optional-status">required</span> `ActorRefWithDeprecatedState<FileUploadContext, { type: "ADD", file: File, id: string, bucketId: string, name: string } | { type: "UPLOAD", url: string, file: File, id: string, bucketId: string, name: string, accessToken: string, adminSecret: string } | { type: "UPLOAD_PROGRESS", progress: number, loaded: number, additions: number } | { type: "UPLOAD_DONE", id: string, bucketId: string } | { type: "UPLOAD_ERROR", error: ErrorPayload } | { type: "CANCEL" } | { type: "DESTROY" }, { value: any, context: FileUploadContext }, ResolveTypegenMeta<Typegen0, { type: "ADD", file: File, id: string, bucketId: string, name: string } | { type: "UPLOAD", url: string, file: File, id: string, bucketId: string, name: string, accessToken: string, adminSecret: string } | { type: "UPLOAD_PROGRESS", progress: number, loaded: number, additions: number } | { type: "UPLOAD_DONE", id: string, bucketId: string } | { type: "UPLOAD_ERROR", error: ErrorPayload } | { type: "CANCEL" } | { type: "DESTROY" }, BaseActionObject, ServiceMap>>` | `Interpreter<FileUploadContext, any, { type: "ADD", file: File, id: string, bucketId: string, name: string } | { type: "UPLOAD", url: string, file: File, id: string, bucketId: string, name: string, accessToken: string, adminSecret: string } | { type: "UPLOAD_PROGRESS", progress: number, loaded: number, additions: number } | { type: "UPLOAD_DONE", id: string, bucketId: string } | { type: "UPLOAD_ERROR", error: ErrorPayload } | { type: "CANCEL" } | { type: "DESTROY" }, { value: any, context: FileUploadContext }, ResolveTypegenMeta<Typegen0, { type: "ADD", file: File, id: string, bucketId: string, name: string } | { type: "UPLOAD", url: string, file: File, id: string, bucketId: string, name: string, accessToken: string, adminSecret: string } | { type: "UPLOAD_PROGRESS", progress: number, loaded: number, additions: number } | { type: "UPLOAD_DONE", id: string, bucketId: string } | { type: "UPLOAD_ERROR", error: ErrorPayload } | { type: "CANCEL" } | { type: "DESTROY" }, BaseActionObject, ServiceMap>>`
---

View File

@@ -0,0 +1,33 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: useFileUpload()
sidebar_label: useFileUpload()
slug: /reference/vue/use-file-upload
description: Use the composable `useFileUpload` to upload a file.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/vue/src/useFileUpload.ts#L142
---
# `useFileUpload()`
Use the composable `useFileUpload` to upload a file.
```tsx
const {
add,
upload,
cancel,
isUploaded,
isUploading,
isError,
progress,
id,
bucketId,
name
} = useFileUpload()
const handleFormSubmit = async (e) => {
e.preventDefault()
await upload({ file })
}
```

View File

@@ -0,0 +1,10 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: FileItemRef
sidebar_label: FileItemRef
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/hasura-storage-js/src/machines/multiple-files-upload.ts#L7
---
# `FileItemRef`

View File

@@ -0,0 +1,80 @@
---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: FileUploadComposableResult
sidebar_label: FileUploadComposableResult
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/vue/src/useFileUpload.ts#L16
---
# `FileUploadComposableResult`
## Parameters
---
**<span className="parameter-name">isError</span>** <span className="optional-status">required</span> `boolean`
**`@returns`**
`true` if an error occurred
**`@depreacted`**
use `!isSuccess` or `!!error` instead
---
**<span className="parameter-name">error</span>** <span className="optional-status">required</span> `null` | `ErrorPayload`
Provides details about the error
---
**<span className="parameter-name">isUploading</span>** <span className="optional-status">required</span> `boolean`
Returns `true` when the file is being uploaded.
---
**<span className="parameter-name">progress</span>** <span className="optional-status">required</span> `null` | `number`
Returns the progress of the upload, from 0 to 100. Returns null if the upload has not started yet.
---
**<span className="parameter-name">isUploaded</span>** <span className="optional-status">required</span> `boolean`
Returns `true` when the file has been successfully uploaded.
---
**<span className="parameter-name">id</span>** <span className="optional-status">optional</span> `string`
Returns the id of the file.
---
**<span className="parameter-name">bucketId</span>** <span className="optional-status">optional</span> `string`
Returns the bucket id.
---
**<span className="parameter-name">name</span>** <span className="optional-status">optional</span> `string`
Returns the name of the file.
---
**<span className="parameter-name">add</span>** <span className="optional-status">required</span> `(params: StorageUploadFileParams) => void`
---
**<span className="parameter-name">upload</span>** <span className="optional-status">required</span> `(params: Partial<StorageUploadFileParams>) => Promise<UploadFileHandlerResult>`
---
**<span className="parameter-name">cancel</span>** <span className="optional-status">required</span> `() => void`
---

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -1,13 +1,13 @@
metadata_directory: metadata
services:
hasura:
image: hasura/graphql-engine:v2.10.1
image: hasura/graphql-engine:v2.15.2
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.15.0
image: nhost/hasura-auth:0.16.1
storage:
image: nhost/hasura-storage:0.2.5
image: nhost/hasura-storage:0.3.0
auth:
access_control:
email:

View File

@@ -1,13 +1,13 @@
metadata_directory: metadata
services:
hasura:
image: hasura/graphql-engine:v2.10.1
image: hasura/graphql-engine:v2.15.2
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.15.0
image: nhost/hasura-auth:0.16.1
storage:
image: nhost/hasura-storage:0.2.5
image: nhost/hasura-storage:0.3.0
auth:
access_control:
email:

View File

@@ -24,7 +24,7 @@ services:
ports:
- '5432:5432'
graphql-engine:
image: hasura/graphql-engine:v2.2.0
image: hasura/graphql-engine:v2.15.2
depends_on:
- 'postgres'
restart: always
@@ -72,7 +72,7 @@ services:
- "traefik.http.routers.auth.middlewares=strip-auth@docker"
- "traefik.http.routers.auth.entrypoints=web"
storage:
image: nhost/hasura-storage:0.2.1
image: nhost/hasura-storage:0.3.1
depends_on:
- postgres
- graphql-engine

View File

@@ -1,13 +1,13 @@
metadata_directory: metadata
services:
hasura:
image: hasura/graphql-engine:v2.10.1
image: hasura/graphql-engine:v2.15.2
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.15.0
image: nhost/hasura-auth:0.16.1
storage:
image: nhost/hasura-storage:0.2.5
image: nhost/hasura-storage:0.3.0
auth:
access_control:
email:

View File

@@ -7,7 +7,7 @@
- ba785da1: Bump dependencies versions
- Updated dependencies [ba785da1]
- Updated dependencies [6da44bf8]
- @nhost/nextjs@2.0.0
- @nhost/nextjs@1.9.0
- @nhost/react@0.14.0
- @nhost/react-apollo@5.0.0

View File

@@ -1,13 +1,13 @@
metadata_directory: metadata
services:
hasura:
image: hasura/graphql-engine:v2.10.1
image: hasura/graphql-engine:v2.15.2
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.15.0
image: nhost/hasura-auth:0.16.1
storage:
image: nhost/hasura-storage:0.2.5
image: nhost/hasura-storage:0.3.0
auth:
access_control:
email:

View File

@@ -1,13 +1,13 @@
metadata_directory: metadata
services:
hasura:
image: hasura/graphql-engine:v2.10.1
image: hasura/graphql-engine:v2.15.2
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.15.0
image: nhost/hasura-auth:0.16.1
storage:
image: nhost/hasura-storage:0.2.5
image: nhost/hasura-storage:0.3.0
auth:
access_control:
email:
@@ -15,7 +15,7 @@ auth:
allowed_emails: ''
blocked_email_domains: ''
blocked_emails: ''
allowed_redirect_urls: 'http://127.0.0.1:3000'
allowed_redirect_urls: http://127.0.0.1:3000
anonymous_users_enabled: true
client_url: http://localhost:3000
disable_new_users: false

View File

@@ -3,7 +3,7 @@ services:
hasura:
environment:
hasura_graphql_enable_remote_schema_permissions: false
image: hasura/graphql-engine:v2.10.1
image: hasura/graphql-engine:v2.15.2
minio:
environment:
minio_root_password: minioaccesskey123123
@@ -13,9 +13,9 @@ services:
postgres_password: postgres
postgres_user: postgres
auth:
image: nhost/hasura-auth:0.15.0
image: nhost/hasura-auth:0.16.1
storage:
image: nhost/hasura-storage:0.2.5
image: nhost/hasura-storage:0.3.0
auth:
webauthn:
enabled: true

View File

@@ -1,10 +1,11 @@
metadata_directory: metadata
services:
storage:
image: nhost/hasura-storage:0.2.7
image: nhost/hasura-storage:0.3.0
hasura:
environment:
hasura_graphql_enable_remote_schema_permissions: false
image: hasura/graphql-engine:v2.15.2
minio:
environment:
minio_root_password: minioaccesskey123123
@@ -13,6 +14,8 @@ services:
environment:
postgres_password: postgres
postgres_user: postgres
auth:
image: nhost/hasura-auth:0.16.1
auth:
access_control:
email:

View File

@@ -3,6 +3,7 @@ services:
hasura:
environment:
hasura_graphql_enable_remote_schema_permissions: false
image: hasura/graphql-engine:v2.15.2
minio:
environment:
minio_root_password: minioaccesskey123123
@@ -11,15 +12,19 @@ services:
environment:
postgres_password: postgres
postgres_user: postgres
auth:
image: nhost/hasura-auth:0.16.1
storage:
image: nhost/hasura-storage:0.3.0
auth:
access_control:
email:
allowed_email_domains: ""
allowed_emails: ""
blocked_email_domains: ""
blocked_emails: ""
allowed_email_domains: ''
allowed_emails: ''
blocked_email_domains: ''
blocked_emails: ''
url:
allowed_redirect_urls: ""
allowed_redirect_urls: ''
anonymous_users_enabled: false
client_url: http://localhost:3000
disable_new_users: false
@@ -28,11 +33,11 @@ auth:
passwordless:
enabled: false
signin_email_verified_required: true
template_fetch_url: ""
template_fetch_url: ''
gravatar:
default: ""
default: ''
enabled: true
rating: ""
rating: ''
locale:
allowed: en
default: en
@@ -41,65 +46,65 @@ auth:
min_length: 3
provider:
apple:
client_id: ""
client_id: ''
enabled: false
key_id: ""
private_key: ""
key_id: ''
private_key: ''
scope: name,email
team_id: ""
team_id: ''
bitbucket:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
facebook:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: email,photos,displayName
github:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: user:email
token_url: ""
user_profile_url: ""
token_url: ''
user_profile_url: ''
gitlab:
base_url: ""
client_id: ""
client_secret: ""
base_url: ''
client_id: ''
client_secret: ''
enabled: false
scope: read_user
google:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: email,profile
linkedin:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: r_emailaddress,r_liteprofile
spotify:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: user-read-email,user-read-private
strava:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
twilio:
account_sid: ""
auth_token: ""
account_sid: ''
auth_token: ''
enabled: false
messaging_service_id: ""
messaging_service_id: ''
twitter:
consumer_key: ""
consumer_secret: ""
consumer_key: ''
consumer_secret: ''
enabled: false
windows_live:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: wl.basic,wl.emails,wl.contacts_emails
sms:
@@ -108,13 +113,13 @@ auth:
enabled: false
provider:
twilio:
account_sid: ""
auth_token: ""
from: ""
messaging_service_id: ""
account_sid: ''
auth_token: ''
from: ''
messaging_service_id: ''
smtp:
host: mailhog
method: ""
method: ''
pass: password
port: 1025
secure: false

View File

@@ -0,0 +1,9 @@
# @nhost-examples/serverless-functions
## 0.0.2
### Patch Changes
- 93db7182: feat(stripe-graphql-js): add charges, payment intents and connected accounts
- Updated dependencies [93db7182]
- @nhost/stripe-graphql-js@0.0.6

View File

@@ -0,0 +1,25 @@
/*
- How to use async/await.
Test:
curl http://localhost:1337/v1/functions/async-await
*/
import fetch from 'cross-fetch'
import { Request, Response } from 'express'
// using async in the function signature
export default async (req: Request, res: Response) => {
// using await
const result = await fetch('//api.github.com/repos/nhost/nhost')
if (result.status >= 400) {
throw new Error('Bad response from server')
}
const repo = await result.json()
res.json(repo)
}

View File

@@ -0,0 +1,44 @@
/*
- How to send an email via SMTP.
Test:
curl http://localhost:1337/v1/functions/send-email
*/
import { Request, Response } from 'express'
import nodemailer from 'nodemailer'
export default async (req: Request, res: Response) => {
// Only needed if you don't have a real mail account for testing
let testAccount = await nodemailer.createTestAccount()
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: 'smtp.ethereal.email',
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: testAccount.user, // generated ethereal user
pass: testAccount.pass // generated ethereal password
}
})
// send mail with defined transport object
let info = await transporter.sendMail({
from: '"Fred Foo 👻" <foo@example.com>', // sender address
to: 'bar@example.com, baz@example.com', // list of receivers
subject: 'Hello ✔', // Subject line
text: 'Hello world?', // plain text body
html: '<b>Hello world?</b>' // html body
})
console.log('Message sent: %s', info.messageId)
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>
// Preview only available when sending through an Ethereal account
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info))
res.json('Message sent')
}

View File

@@ -3,6 +3,7 @@ services:
hasura:
environment:
hasura_graphql_enable_remote_schema_permissions: false
image: hasura/graphql-engine:v2.15.2
minio:
environment:
minio_root_password: minioaccesskey123123
@@ -11,15 +12,19 @@ services:
environment:
postgres_password: postgres
postgres_user: postgres
auth:
image: nhost/hasura-auth:0.16.1
storage:
image: nhost/hasura-storage:0.3.0
auth:
access_control:
email:
allowed_email_domains: ""
allowed_emails: ""
blocked_email_domains: ""
blocked_emails: ""
allowed_email_domains: ''
allowed_emails: ''
blocked_email_domains: ''
blocked_emails: ''
url:
allowed_redirect_urls: ""
allowed_redirect_urls: ''
anonymous_users_enabled: false
client_url: http://localhost:3000
disable_new_users: false
@@ -28,11 +33,11 @@ auth:
passwordless:
enabled: false
signin_email_verified_required: true
template_fetch_url: ""
template_fetch_url: ''
gravatar:
default: ""
default: ''
enabled: true
rating: ""
rating: ''
locale:
allowed: en
default: en
@@ -41,65 +46,65 @@ auth:
min_length: 3
provider:
apple:
client_id: ""
client_id: ''
enabled: false
key_id: ""
private_key: ""
key_id: ''
private_key: ''
scope: name,email
team_id: ""
team_id: ''
bitbucket:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
facebook:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: email,photos,displayName
github:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: user:email
token_url: ""
user_profile_url: ""
token_url: ''
user_profile_url: ''
gitlab:
base_url: ""
client_id: ""
client_secret: ""
base_url: ''
client_id: ''
client_secret: ''
enabled: false
scope: read_user
google:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: email,profile
linkedin:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: r_emailaddress,r_liteprofile
spotify:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: user-read-email,user-read-private
strava:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
twilio:
account_sid: ""
auth_token: ""
account_sid: ''
auth_token: ''
enabled: false
messaging_service_id: ""
messaging_service_id: ''
twitter:
consumer_key: ""
consumer_secret: ""
consumer_key: ''
consumer_secret: ''
enabled: false
windows_live:
client_id: ""
client_secret: ""
client_id: ''
client_secret: ''
enabled: false
scope: wl.basic,wl.emails,wl.contacts_emails
sms:
@@ -108,13 +113,13 @@ auth:
enabled: false
provider:
twilio:
account_sid: ""
auth_token: ""
from: ""
messaging_service_id: ""
account_sid: ''
auth_token: ''
from: ''
messaging_service_id: ''
smtp:
host: mailhog
method: ""
method: ''
pass: password
port: 1025
secure: false

View File

@@ -1,15 +1,17 @@
{
"name": "@nhost-examples/serverless-functions",
"private": true,
"version": "0.0.1",
"version": "0.0.2",
"devDependencies": {
"@types/express": "^4.17.13"
},
"dependencies": {
"@graphql-yoga/node": "^2.13.13",
"@nhost/stripe-graphql-js": "^0.0.5",
"@nhost/stripe-graphql-js": "^0.0.6",
"@pothos/core": "^3.21.0",
"cross-fetch": "^3.1.5",
"graphql": "15.7.2",
"nodemailer": "^6.8.0",
"slugify": "^1.6.5"
}
}

View File

@@ -1,13 +1,13 @@
metadata_directory: metadata
services:
hasura:
image: hasura/graphql-engine:v2.10.1
image: hasura/graphql-engine:v2.15.2
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.15.0
image: nhost/hasura-auth:0.16.1
storage:
image: nhost/hasura-storage:0.2.5
image: nhost/hasura-storage:0.3.0
auth:
access_control:
email:

View File

@@ -1,5 +1,11 @@
# @nhost/stripe-graphql-js
## 0.0.6
### Patch Changes
- 93db7182: feat(stripe-graphql-js): add charges, payment intents and connected accounts
## 0.0.5
### Patch Changes

View File

@@ -197,6 +197,14 @@ Start the development server:
pnpm dev
```
Include the correct admin secret header for admin access
```js
{
"x-hasura-admin-secret":"<secret value matching your NHOST_ADMIN_SECRET environment variable>"
}
```
The GraphQL Server will reload every time the code changes.
Open GraphiQL:

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/stripe-graphql-js",
"version": "0.0.5",
"version": "0.0.6",
"description": "Stripe GraphQL API",
"license": "MIT",
"keywords": [

View File

@@ -3,7 +3,13 @@ import Stripe from 'stripe'
import SchemaBuilder from '@pothos/core'
import { Context, StripeInvoice, StripePaymentMethod, StripeSubscription } from './types'
import {
Context,
StripeCharge,
StripeInvoice,
StripePaymentIntent,
StripePaymentMethod,
StripeSubscription} from './types'
// TODO: Make sure we either use Type or Types (e.g. StripePaymentMethodTypes or StripePaymentMethodType ) everywhere
@@ -93,6 +99,18 @@ const builder = new SchemaBuilder<{
// BILLING PORTAL
StripeBillingPortalSession: Stripe.BillingPortal.Session
// PAYMENT INTENT
StripePaymentIntent: StripePaymentIntent
StripePaymentIntents: Stripe.ApiList<StripePaymentIntent>
// CHARGES
StripeCharge: StripeCharge
StripeCharges: Stripe.ApiList<StripeCharge>
// CONNECTED ACCOUNTS
StripeConnectedAccount: Stripe.Account
StripeConnectedAccounts: Stripe.ApiList<Stripe.Account>
}
Context: Context
}>({})

View File

@@ -0,0 +1,82 @@
import Stripe from 'stripe'
import { builder } from '../builder'
import { StripeInvoice } from '../types'
import { stripe } from '../utils'
builder.objectType('StripeCharge', {
description: 'Stripe charge object',
fields: (t) => ({
id: t.exposeString('id'),
customer: t.exposeString('customer'),
amount: t.exposeInt('amount'),
amountCaptured: t.exposeInt('amount_captured'),
amountRefunded: t.exposeInt('amount_refunded'),
applicationFeeAmount: t.exposeInt('application_fee_amount', { nullable: true }),
calculatedStatementDescriptor: t.exposeString('calculated_statement_descriptor', {
nullable: true
}),
billingDetails: t.expose('billing_details', { type: 'JSON', nullable: true }),
captured: t.exposeBoolean('captured'),
created: t.exposeInt('created', {
nullable: true
}),
currency: t.exposeString('currency'),
description: t.exposeString('description', { nullable: true }),
disputed: t.exposeBoolean('disputed'),
failureCode: t.exposeString('failure_code', { nullable: true }),
invoice: t.field({
type: 'StripeInvoice',
nullable: true,
resolve: async (charge) => {
const { invoice } = charge
if (!invoice) {
return null
}
const invoiceData = await stripe.invoices.retrieve(invoice as string)
return invoiceData as Stripe.Response<StripeInvoice>
}
}),
application: t.field({
type: 'StripeConnectedAccount',
nullable: true,
resolve: async (charge) => {
const { application } = charge
if (!application) return null
const connectedAccount = await stripe.accounts.retrieve(application as string)
return connectedAccount
}
}),
livemode: t.exposeBoolean('livemode'),
metadata: t.expose('metadata', { nullable: true, type: 'JSON' }),
outcome: t.expose('outcome', { nullable: true, type: 'JSON' }),
fraudDetails: t.expose('fraud_details', { nullable: true, type: 'JSON' }),
paid: t.exposeBoolean('paid'),
receiptEmail: t.exposeString('receipt_email', { nullable: true }),
receiptNumber: t.exposeString('receipt_number', { nullable: true }),
receiptUrl: t.exposeString('receipt_url', { nullable: true }),
refunded: t.exposeBoolean('refunded'),
shipping: t.expose('shipping', { nullable: true, type: 'JSON' }),
statementDescriptor: t.exposeString('statement_descriptor', { nullable: true }),
statementDescriptorSuffix: t.exposeString('statement_descriptor_suffix', { nullable: true }),
status: t.exposeString('status'),
transferData: t.expose('transfer_data', { nullable: true, type: 'JSON' }),
transferGroup: t.exposeString('transfer_group', { nullable: true }),
refunds: t.expose('refunds', { nullable: true, type: 'JSON' }),
paymentMethodDetails: t.expose('payment_method_details', { nullable: true, type: 'JSON' }),
paymentIntent: t.exposeString('payment_intent', { nullable: true }),
paymentMethod: t.exposeString('payment_method', { nullable: true })
// todo: add missing fields
// application_fee
// balance_transaction
// on_behalf_of
// failure_balance_transaction
// source_transfer
})
})

View File

@@ -0,0 +1,14 @@
import { builder } from '../builder'
builder.objectType('StripeCharges', {
description: 'List of Stripe charge objects',
fields: (t) => ({
object: t.exposeString('object'),
url: t.exposeString('url'),
hasMore: t.exposeBoolean('has_more'),
data: t.expose('data', {
type: ['StripeCharge'],
nullable: false
})
})
})

View File

@@ -0,0 +1,28 @@
import { builder } from '../builder'
builder.objectType('StripeConnectedAccount', {
description: 'Stripe charge object',
fields: (t) => ({
id: t.exposeString('id'),
object: t.exposeString('object'),
country: t.exposeString('country', { nullable: true }),
businessType: t.exposeString('business_type', { nullable: true }),
capabilities: t.expose('capabilities', { type: 'JSON' }),
company: t.expose('company', { type: 'JSON' }),
email: t.exposeString('email', { nullable: true }),
individual: t.expose('individual', { type: 'JSON' }),
metadata: t.expose('metadata', { type: 'JSON' }),
requirements: t.expose('requirements', { type: 'JSON' }),
tosAcceptance: t.expose('tos_acceptance', { type: 'JSON' }),
businessProfile: t.expose('business_profile', { type: 'JSON' }),
chargesEnabled: t.exposeBoolean('charges_enabled'),
controller: t.expose('controller', { nullable: true, type: 'JSON' }),
created: t.exposeInt('created', { nullable: true }),
defaultCurrency: t.exposeString('default_currency', { nullable: true }),
detailsSubmitted: t.exposeBoolean('details_submitted'),
externalAccounts: t.expose('external_accounts', { type: 'JSON' }),
futureRequirements: t.expose('future_requirements', { type: 'JSON' }),
payoutsEnabled: t.exposeBoolean('payouts_enabled'),
settings: t.expose('settings', { type: 'JSON' })
})
})

View File

@@ -0,0 +1,14 @@
import { builder } from '../builder'
builder.objectType('StripeConnectedAccounts', {
description: 'List of Stripe Connected Account objects',
fields: (t) => ({
object: t.exposeString('object'),
url: t.exposeString('url'),
hasMore: t.exposeBoolean('has_more'),
data: t.expose('data', {
type: ['StripeConnectedAccount'],
nullable: false
})
})
})

View File

@@ -1,7 +1,12 @@
import Stripe from 'stripe'
import { builder } from '../builder'
import { StripeInvoice, StripePaymentMethod, StripeSubscription } from '../types'
import {
StripeCharge,
StripeInvoice,
StripePaymentIntent,
StripePaymentMethod,
StripeSubscription} from '../types'
import { stripe } from '../utils'
import { StripePaymentMethodTypes } from './payment-methods'
@@ -110,6 +115,16 @@ builder.objectType('StripeCustomer', {
return invoices as Stripe.Response<Stripe.ApiList<StripeInvoice>>
}
}),
paymentIntents: t.field({
type: 'StripePaymentIntents',
nullable: false,
resolve: async (customer) => {
const paymentIntents = await stripe.paymentIntents.list({
customer: customer.id
})
return paymentIntents as Stripe.Response<Stripe.ApiList<StripePaymentIntent>>
}
}),
paymentMethods: t.field({
type: 'StripePaymentMethods',
args: {
@@ -138,6 +153,16 @@ builder.objectType('StripeCustomer', {
})
return paymentMethods as Stripe.Response<Stripe.ApiList<StripePaymentMethod>>
}
}),
charges: t.field({
type: 'StripeCharges',
nullable: false,
resolve: async (customer) => {
const charges = await stripe.charges.list({
customer: customer.id
})
return charges as Stripe.Response<Stripe.ApiList<StripeCharge>>
}
})
})
})

View File

@@ -42,6 +42,12 @@ import './product'
import './tax-rate'
import './test-clock'
import './billing-portal-session'
import './payment-intent'
import './payment-intents'
import './charges'
import './charge'
import './connectedAccount'
import './connectedAccounts'
import { builder } from '../builder'

View File

@@ -32,7 +32,18 @@ builder.objectType('StripeInvoice', {
amountRemaining: t.exposeInt('amount_remaining', {
description: `The difference between amount_due and amount_paid, in %s.`
}),
// todo: application
application: t.field({
type: 'StripeConnectedAccount',
nullable: true,
resolve: async (invoice) => {
const { application } = invoice
if (!application) return null
const connectedAccount = await stripe.accounts.retrieve(application as string)
return connectedAccount
}
}),
applicationFeeAmount: t.exposeInt('application_fee_amount', {
description: `The fee in %s that will be applied to the invoice and transferred to the application owner's Stripe account when the invoice is paid.`,
nullable: true

View File

@@ -0,0 +1,75 @@
import Stripe from 'stripe'
import { builder } from '../builder'
import { StripeInvoice } from '../types'
import { stripe } from '../utils'
builder.objectType('StripePaymentIntent', {
description: 'Payment intents',
fields: (t) => ({
id: t.exposeString('id'),
object: t.exposeString('object'),
amount: t.exposeInt('amount'),
currency: t.exposeString('currency'),
description: t.exposeString('description', {
nullable: true
}),
metadata: t.expose('metadata', {
type: 'JSON',
nullable: true
}),
paymentMethodTypes: t.exposeStringList('payment_method_types'),
statementDescriptor: t.exposeString('statement_descriptor', {
nullable: true
}),
statementDescriptorSuffix: t.exposeString('statement_descriptor_suffix', {
nullable: true
}),
receiptEmail: t.exposeString('receipt_email', {
nullable: true
}),
customer: t.exposeString('customer'),
amountCapturable: t.exposeInt('amount_capturable'),
amountDetails: t.expose('amount_details', {
nullable: true,
type: 'JSON'
}),
amountReceived: t.exposeInt('amount_received'),
applicationFeeAmount: t.exposeInt('application_fee_amount', {
nullable: true
}),
canceledAt: t.exposeInt('canceled_at', {
nullable: true
}),
transferGroup: t.exposeString('transfer_group', {
nullable: true
}),
cancellationReason: t.exposeString('cancellation_reason', {
nullable: true
}),
created: t.exposeInt('created', {
nullable: true
}),
status: t.exposeString('status'),
invoice: t.field({
type: 'StripeInvoice',
nullable: true,
resolve: async (paymentIntent) => {
const { invoice } = paymentIntent
if (!invoice) {
return null
}
const invoiceData = await stripe.invoices.retrieve(invoice as string)
return invoiceData as Stripe.Response<StripeInvoice>
}
})
// todo: missing fields
// capture_method
// add charges
// application
})
})

View File

@@ -0,0 +1,13 @@
import { builder } from '../builder'
builder.objectType('StripePaymentIntents', {
fields: (t) => ({
object: t.exposeString('object'),
url: t.exposeString('url'),
hasMore: t.exposeBoolean('has_more'),
data: t.expose('data', {
type: ['StripePaymentIntent'],
nullable: false
})
})
})

View File

@@ -7,6 +7,35 @@ import { stripe } from '../utils'
builder.objectType('Stripe', {
fields: (t) => ({
connectedAccounts: t.field({
type: 'StripeConnectedAccounts',
resolve: async (_parent, _, context) => {
const { isAdmin } = context
if (!isAdmin) throw new GraphQLYogaError('Not allowed')
const connectedAccounts = await stripe.accounts.list()
return connectedAccounts
}
}),
connectedAccount: t.field({
type: 'StripeConnectedAccount',
args: {
id: t.arg.string({
required: true
})
},
resolve: async (_parent, { id }, context) => {
const { isAdmin } = context
if (!isAdmin) throw new GraphQLYogaError('Not allowed')
const connectedAccount = await stripe.accounts.retrieve(id)
return connectedAccount
}
}),
customer: t.field({
type: 'StripeCustomer',
args: {

View File

@@ -31,6 +31,16 @@ export type StripeInvoice = Stripe.Invoice & {
id: string
customer: string
default_payment_method: StripePaymentMethod | null
payment_intent: any
}
export type StripePaymentIntent = Stripe.PaymentIntent & {
customer: string
}
export type StripeCharge = Stripe.Charge & {
customer: string
payment_intent: string | null
}
export type UserHasuraClaims = {

View File

@@ -1,4 +1,4 @@
# Docker image versions used in the cloud
hasura: v2.10.1
auth: 0.15.0
storage: 0.2.5
hasura: v2.15.2
auth: 0.16.1
storage: 0.3.0

View File

@@ -88,7 +88,7 @@
},
"packageManager": "pnpm@7.17.0",
"engines": {
"node": ">=14 <17",
"node": ">=16 <17",
"pnpm": ">=7.17.0"
},
"eslintConfig": {

View File

@@ -8,7 +8,9 @@ test('should categorize elements of groups in a Map', () => {
{ title: 'Classes', kind: 0, children: [1, 2, 3] },
{ title: 'Properties', kind: 0, children: [4, 5, 6, 7] },
{ title: 'Type aliases', kind: 0, children: [8, 9] },
{ title: 'Functions', kind: 0, children: [10] }
{ title: 'Functions', kind: 0, children: [10] },
{ title: 'Components', kind: 0, children: [11, 12, 13] },
{ title: 'References', kind: 0, children: [14, 15] }
])
).toEqual(
new Map([
@@ -21,7 +23,12 @@ test('should categorize elements of groups in a Map', () => {
[7, 'Property'],
[8, 'Type alias'],
[9, 'Type alias'],
[10, 'Function']
[10, 'Function'],
[11, 'Component'],
[12, 'Component'],
[13, 'Component'],
[14, 'Reference'],
[15, 'Reference']
])
)
})
@@ -57,3 +64,46 @@ test('should set content type to "undefined" if value does not exist in dictiona
])
)
})
test('should not treat the same text with different letter casing differently', () => {
expect(
getModuleContentMap([
{ title: 'Type aliases', kind: 0, children: [1, 2, 3] },
{ title: 'Type Aliases', kind: 0, children: [4] },
{ title: 'TYPE ALIASES', kind: 0, children: [5, 6] }
])
).toEqual(
new Map([
[1, 'Type alias'],
[2, 'Type alias'],
[3, 'Type alias'],
[4, 'Type alias'],
[5, 'Type alias'],
[6, 'Type alias']
])
)
})
test('should update the type of a child if it has a special category (not "Other")', () => {
expect(
getModuleContentMap([
{
title: 'Functions',
kind: 0,
children: [1, 2, 3],
categories: [
{ title: 'Components', children: [3] },
{ title: 'Other', children: [1] }
]
},
{ title: 'Type Aliases', kind: 0, children: [4] }
])
).toEqual(
new Map([
[1, 'Function'],
[2, 'Function'],
[3, 'Component'],
[4, 'Type alias']
])
)
})

View File

@@ -4,17 +4,19 @@ import { Group } from '../types'
* Used to convert plural names coming from TypeDoc to singular names.
*/
const pluralSingularDictionary = new Map([
['Classes', 'Class'],
['Properties', 'Property'],
['Methods', 'Method'],
['Functions', 'Function'],
['Type aliases', 'Type alias'],
['Interfaces', 'Interface'],
['Modules', 'Module'],
['Methods', 'Method'],
['Variables', 'Variable'],
['Accessors', 'Accessor'],
['Constructors', 'Constructor']
['classes', 'Class'],
['properties', 'Property'],
['methods', 'Method'],
['functions', 'Function'],
['type aliases', 'Type alias'],
['interfaces', 'Interface'],
['modules', 'Module'],
['methods', 'Method'],
['variables', 'Variable'],
['accessors', 'Accessor'],
['constructors', 'Constructor'],
['components', 'Component'],
['references', 'Reference']
])
/**
@@ -28,13 +30,27 @@ export function getModuleContentMap(
groups: Array<Group>,
originalMap: Map<number, string> = new Map()
): Map<number, string> {
return groups.reduce((contentMap, { title, children }) => {
const singularTitle = pluralSingularDictionary.get(title)
return groups.reduce((contentMap, { title, children, categories }) => {
const singularTitle = pluralSingularDictionary.get(title.toLowerCase())
children.forEach((child) => {
contentMap.set(child, singularTitle || 'undefined')
})
if (categories) {
categories.forEach(({ title: categoryTitle, children: categoryChildren }) => {
if (categoryTitle === 'Other') {
return
}
const singularTitle = pluralSingularDictionary.get(categoryTitle.toLowerCase())
categoryChildren.forEach((categoryChild) => {
contentMap.set(categoryChild, singularTitle || 'undefined')
})
})
}
return contentMap
}, originalMap)
}

View File

@@ -16,7 +16,7 @@ import { Signature } from '../types'
* @returns Prettified function page template
*/
export const FunctionTemplate = (
{ name, comment, signatures, sources }: Signature,
{ id, name, comment, signatures, sources }: Signature,
originalDocument?: Array<Signature>,
slug?: string,
functionFragmentOptions?: FunctionFragmentOptions
@@ -25,13 +25,14 @@ export const FunctionTemplate = (
const allChildrenDeprecated = signatures?.every((signature) =>
signature.comment?.tags?.some(({ tag }) => tag === 'deprecated')
)
const { baseEditUrl } = snapshot(appState)
const { baseEditUrl, contentReferences } = snapshot(appState)
const isComponent = contentReferences.get(id) === 'Component'
const source = sources?.[0]
const header = `---
# ⚠️ AUTO-GENERATED CONTENT. DO NOT EDIT THIS FILE DIRECTLY! ⚠️
title: ${name}()
sidebar_label: ${alias || name}()
title: ${isComponent ? `<${name} />` : `${name}()`}
sidebar_label: ${isComponent ? `<${alias || name} />` : `${alias || name}()`}
${slug ? `slug: ${slug}` : ``}
${allChildrenDeprecated ? 'sidebar_class_name: deprecated' : ''}
${

View File

@@ -29,6 +29,7 @@ export type Group = {
title: string
kind: number
children: Array<number>
categories?: Array<{ title: string; children: Array<number> }>
}
export type Source = {

View File

@@ -1,13 +1,13 @@
metadata_directory: metadata
services:
hasura:
image: hasura/graphql-engine:v2.10.1
image: hasura/graphql-engine:v2.15.2
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.15.0
image: nhost/hasura-auth:0.16.1
storage:
image: nhost/hasura-storage:0.2.5
image: nhost/hasura-storage:0.3.0
auth:
access_control:
email:

View File

@@ -1,13 +1,13 @@
metadata_directory: metadata
services:
hasura:
image: hasura/graphql-engine:v2.10.1
image: hasura/graphql-engine:v2.15.2
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.15.0
image: nhost/hasura-auth:0.16.1
storage:
image: nhost/hasura-storage:0.2.5
image: nhost/hasura-storage:0.3.0
auth:
access_control:
email:

View File

@@ -1,5 +1,13 @@
# @nhost/nextjs
## 1.9.0
### Patch Changes
- Updated dependencies [4601d84e]
- Updated dependencies [843087cb]
- @nhost/react@0.15.0
## 1.8.3
### Patch Changes

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