Compare commits

...

20 Commits

Author SHA1 Message Date
github-actions[bot]
2b6a4adf40 chore: update versions (#3202)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @nhost/apollo@8.0.5

### Patch Changes

-   Updated dependencies [6b8163d]
    -   @nhost/nhost-js@3.2.5

## @nhost/google-translation@0.2.2

### Patch Changes

- 6b8163d: fix(nhost-js) update service URL generation for local
environments

## @nhost/react-apollo@17.0.1

### Patch Changes

-   @nhost/apollo@8.0.5
-   @nhost/react@3.10.1

## @nhost/react-urql@14.0.1

### Patch Changes

-   @nhost/react@3.10.1

## @nhost/hasura-auth-js@2.10.1

### Patch Changes

- 6b8163d: fix(nhost-js) update service URL generation for local
environments

## @nhost/nextjs@2.2.4

### Patch Changes

-   @nhost/react@3.10.1

## @nhost/nhost-js@3.2.5

### Patch Changes

- 6b8163d: fix(nhost-js) update service URL generation for local
environments
-   Updated dependencies [6b8163d]
    -   @nhost/hasura-auth-js@2.10.1

## @nhost/react@3.10.1

### Patch Changes

-   Updated dependencies [6b8163d]
    -   @nhost/nhost-js@3.2.5

## @nhost/vue@2.9.2

### Patch Changes

-   Updated dependencies [6b8163d]
    -   @nhost/nhost-js@3.2.5

## @nhost/dashboard@2.21.0

# @nhost/dashboard

## 2.17.0

### Minor Changes

-   fd59918: fix: redirect to 404 with nhost cli dashboard

## 2.16.0

### Minor Changes

-   f8e6b61: fix: can add rule groups in table permissions
-   9e404c8: fix: not redirect to 404 page if using local Nhost backend
-   ac4aa01: fix: can delete column in database page
-   4385524: fix: update url to check service health in local dashboard

### Patch Changes

-   @nhost/react-apollo@16.0.1
-   @nhost/nextjs@2.2.2

## 2.15.0

### Minor Changes

- f1052a8: fix: improve stability of the dashboard when pausing projects
-   30daa41: fix: update links to docs in overview page
-   7537237: feat: add image preview toggle in storage

## 2.14.0

### Minor Changes

- d43931e: fix: invalid organization slug/project subdomain doesn't open
404 page
- 5df6fa2: feat: add unencrypted disk warning in storage capacity
settings

### Patch Changes

-   44c1e17: chore: update `msw` to v1.3.5 to fix vulnerabilities
    -   @nhost/react-apollo@16.0.0
    -   @nhost/nextjs@2.2.1

## 2.13.0

### Minor Changes

- 21e90da: chore: remove restrictions on SMTP sender so My Name
[name@acme.com](mailto:name@acme.com) can be added
- 865dd93: fix: duplicate Run placeholders when there is an error in the
backend
- 6902a36: fix: can remove resources if postgres capacity is higher than
10
-   a535aa3: fix: fetch user roles locally in auth section
-   0c50816: fix: allow decimal numbers in database row insert
- aea6d18: chore: add warning when pausing a project about losing Run
services persistent volume data
- d3b4fc3: feat: allow to change postgres settings if project is paused
-   29d27e1: chore: update `next` to v14.2.22 to fix vulnerabilities
-   c9dca09: feat: add reset password form
-   b3bcacb: fix: paused project banner cannot read null project name

### Patch Changes

-   Updated dependencies [46fc520]
-   Updated dependencies [29d27e1]
    -   @nhost/nextjs@2.2.0
    -   @nhost/react-apollo@15.0.1

## 2.12.0

### Minor Changes

- eb95562: fix: show all available permission variables in permission
dropdown select

### Patch Changes

- 8b5c4a0: chore: cleanup layout and add disable duplicate atom key
checking in development mode

## 2.11.3

### Patch Changes

- 714dffa: fix: improve project polling logic and unify usage across
components

## 2.11.2

### Patch Changes

- 6a34f89: fix: improve project polling logic and unify usage across
components

## 2.11.1

### Patch Changes

-   0f6ce52: fix: consolidate useProject hook and fix jwt expired error

## 2.11.0

### Minor Changes

-   cea3ef5: Feat: add org and project placeholders

## 2.10.0

### Minor Changes

-   86ecf27: feat: add support for additional metrics in overview
- 21708be: feat: dashboard: add support for storage buckets to AI
assistants

## 1.30.0

### Minor Changes

- 50441a8: feat: add ui for project autoscaler settings and run services
autoscaler settings

## 1.29.0

### Minor Changes

-   55d8bb5: feat: integrate turnstile for signup verification
-   2a2e54c: fix: update docs url in run services form tooltip
- 18f942f: fix: display long error messages in error toast without
overflow

### Patch Changes

-   @nhost/react-apollo@13.0.0
-   @nhost/nextjs@2.1.22

## 1.28.2

### Patch Changes

- 52a38fe: chore: update dependencies to address security
vulnerabilities
-   Updated dependencies [52a38fe]
    -   @nhost/nextjs@2.1.21

## 1.28.1

### Patch Changes

-   9735fa2: chore: remove broken link

## 1.28.0

### Minor Changes

- 526183a: feat: allow filtering users in "make request as" in graphql
section
-   be3b85b: feat: add conceal errors toggle on auth settings page

### Patch Changes

- 35a2f12: fix: prevent run service details from opening when attempting
to delete
    -   @nhost/react-apollo@12.0.6
    -   @nhost/nextjs@2.1.20

## 1.27.0

### Minor Changes

-   a7cd02c: fix: resolve rate limit query

## 1.26.0

### Minor Changes

-   3773ad7: chore: update pricing information
- b63250d: fix: not allow run service creation form resubmission while
creating a run service
-   a44a1d4: feat: add rate limits settings page

### Patch Changes

-   @nhost/react-apollo@12.0.5
-   @nhost/nextjs@2.1.19

## 1.25.0

### Minor Changes

- d1ceede: feat: add setting to migrate postgres major and/or minor
versions
- e5d3d1a: fix: allow manually typing column for custom check in
database row permissions

### Patch Changes

-   @nhost/react-apollo@12.0.4
-   @nhost/nextjs@2.1.18

## 1.24.1

### Patch Changes

- 49f2e55: fix: use service subdomain in service form and service
details dialog
- 598b988: fix: use current project subdomain in ServiceDetailsDialog
component

## 1.24.0

### Minor Changes

-   abb24af: chore: add redirect to support page when project is locked
- 18a6455: feat: show contact us info and locked reason when project is
locked

### Patch Changes

-   e31eefa: fix: include ingresses field when updating run services

## 1.23.0

### Minor Changes

-   33284d3: fix: don't show double scrollbar in configuration editor

### Patch Changes

-   @nhost/react-apollo@12.0.3
-   @nhost/nextjs@2.1.17

## 1.22.0

### Minor Changes

-   998c037: fix: align drop-down list in select component
- 807b8c0: fix: show city name in region selection for project creation

## 1.21.0

### Minor Changes

- a2efeed: fix: improve project health error handling, add unknown state
and polling interval for health state

## 1.20.0

### Minor Changes

- 8ea4210: fix: error toasts can be closed individually, instead of
dismissing all toasts at once
- 58919ba: chore: add blink animation when project health service is
updating

## 1.19.0

### Minor Changes

- b519862: fix: get configuration in configuration editor using local
development environment

## 1.18.0

### Minor Changes

- 502abad: feat: add services health checks indicators to the overview
page
-   b3ff6ad: chore: update title text on service status modal
- dbadf59: feat: add project configuration TOML editor to the settings
page

## 1.17.0

### Minor Changes

- 77fba27: fix: postgres version validation when activating ai in ai
settings page
-   ac6d1b6: feat: use name instead of awsName

## 1.16.3

### Patch Changes

- 87a37cf: fix: remove unnecessary isPlatform check from verify button
disable logic on custom domains
    -   @nhost/react-apollo@12.0.2
    -   @nhost/nextjs@2.1.16

## 1.16.2

### Patch Changes

- a9413af: fix: update `GetAllWorkspacesAndProjects` query polling to
use exponential backoff
    -   @nhost/react-apollo@12.0.1
    -   @nhost/nextjs@2.1.15

## 1.16.1

### Patch Changes

-   @nhost/react-apollo@12.0.0
-   @nhost/nextjs@2.1.14

## 1.16.0

### Minor Changes

- c6d5c5c: feat: add toggle switch to enable/disable public access in
the database settings

## 1.15.2

### Patch Changes

-   @nhost/react-apollo@11.0.4
-   @nhost/nextjs@2.1.13

## 1.15.1

### Patch Changes

-   @nhost/react-apollo@11.0.3
-   @nhost/nextjs@2.1.12

## 1.15.0

### Minor Changes

-   a7bde37: feat: send metadata in the edit form

### Patch Changes

- 1bc615b: feat: improve error message handling in `ErrorToast`
component
    -   @nhost/react-apollo@11.0.2
    -   @nhost/nextjs@2.1.11

## 1.14.0

### Minor Changes

-   a448d7d: feat: allow configuring postmark and delete SMTP settings

## 1.13.3

### Patch Changes

-   5924bc3: fix: include password in `GetSmtpSettings` query
- c5ad634: fix: resolved an issue where one-click install links were
broken on Safari
- 7278991: fix: update graphql auto-embeddings configuration to use
String type for model field

## 1.13.2

### Patch Changes

-   026f84f: fix: use configuration server URL from environment variable

## 1.13.1

### Patch Changes

-   7e9a2ce: fix: resolve issue where run services form fails to open

## 1.13.0

### Minor Changes

-   dd5d262: feat: add model field to the auto-embeddings form
- 09962be: feat: enable settings and run services when running the
dashboard locally
- 9cdecb6: feat: enable users to update their email address from the
account settings page

## 1.12.2

### Patch Changes

-   c195c51: fix: send email upon signin for unverified users

## 1.12.1

### Patch Changes

- 93ebdf8: fix: use service urls when initilizaing NhostClient running
local dashboard
    -   @nhost/react-apollo@11.0.1
    -   @nhost/nextjs@2.1.10

## 1.12.0

### Minor Changes

- f242e4b: feat: add connect with github to the user's account settings
-   768ca17: chore: update dependencies
- d62bd0f: fix: "Track this" option within the SQL editor now correctly
updates the metadata
- 91c2bb6: feat: refactor sign-in and sign-up pages to enforce email
verification

### Patch Changes

-   943831f: fix: resolve an error toast issue when unpausing a project
-   Updated dependencies [768ca17]
    -   @nhost/react-apollo@11.0.0
    -   @nhost/nextjs@2.1.9

## 1.11.2

### Patch Changes

-   @nhost/react-apollo@10.0.2
-   @nhost/nextjs@2.1.8

## 1.11.1

### Patch Changes

-   981404f: fix: set default value for healthCheck field validation

## 1.11.0

### Minor Changes

- 7789469: chore: upgrade dependency `@graphql-codegen/cli` to `5.0.2`
to address vulnerability
- 6c11b75: feat: add update user displayName section in account settings

### Patch Changes

-   @nhost/react-apollo@10.0.1
-   @nhost/nextjs@2.1.7

## 1.10.0

### Minor Changes

-   49a80c2: chore: update dependencies
-   150c04a: feat: add healthcheck config to run services

### Patch Changes

- e03f141: fix: allow insert, update and delete on tables in `auth` and
`storage` schemas
- 28676f4: feat: add min postgres version check to enable the ai service
-   Updated dependencies [49a80c2]
    -   @nhost/react-apollo@10.0.0
    -   @nhost/nextjs@2.1.6

## 1.9.0

### Minor Changes

-   d86e5c9: feat: add support for filtering the logs using a RegExp

## 1.8.3

### Patch Changes

-   @nhost/react-apollo@9.0.3
-   @nhost/nextjs@2.1.5

## 1.8.2

### Patch Changes

- 6df4f02: fix: use custom error toast and show correct message when
sending an invite

## 1.8.1

### Patch Changes

-   @nhost/react-apollo@9.0.2
-   @nhost/nextjs@2.1.4

## 1.8.0

### Minor Changes

- 713d53c: feat: add catch-all route for workspace/project - useful for
documentation

### Patch Changes

-   3db2999: fix: refresh table list after running SQL using the editor
- 3c4dd55: fix: handle `Error` objects properly in the `ErrorToast`
component
- 92b434e: fix: resolve an issue where the checkbox in the data-grid
header did not select all rows
    -   @nhost/react-apollo@9.0.1
    -   @nhost/nextjs@2.1.3

## 1.7.0

### Minor Changes

-   0d8d0eb: Update docs and dashboard references

## 1.6.9

### Patch Changes

-   @nhost/react-apollo@9.0.0
-   @nhost/nextjs@2.1.2

## 1.6.8

### Patch Changes

-   @nhost/react-apollo@8.0.1
-   @nhost/nextjs@2.1.1

## 1.6.7

### Patch Changes

-   5ef5189: fix: update `@apollo/client` to `3.9.4` to fix a cache bug

## 1.6.6

### Patch Changes

-   3ba485e: fix: added discord.com to connect-src
-   e5bab6a: chore: update dependencies
-   Updated dependencies [b19ffed]
-   Updated dependencies [e5bab6a]
    -   @nhost/nextjs@2.1.0
    -   @nhost/react-apollo@8.0.0

## 1.6.5

### Patch Changes

- ba73bb4: fix: update ErrorToast component to show the internal graphql
error
- d5337ff: fix: utilize accumulator in the creation of validation schema
within data grid utils

## 1.6.4

### Patch Changes

-   7c2a1c2: feat: show error and debug info in the error toast

## 1.6.3

### Patch Changes

-   6b8aad5: fix: add bare nhost.run to CSP

## 1.6.2

### Patch Changes

-   b18edc0: feat: added CSP and X-Frame-Options

## 1.6.1

### Patch Changes

-   8d91f71: chore: update deps and enable pnpm audit
- 3b8473b: chore: update turbo to `1.11.3` and pnpm to `8.10.5` in
Dockerfile
-   Updated dependencies [8d91f71]
    -   @nhost/react-apollo@7.0.2
    -   @nhost/nextjs@2.0.2

## 1.6.0

### Minor Changes

-   3ff1c2b53: fix: show upgrade option for pro projects

## 1.5.0

### Minor Changes

-   c2ef17c0a: feat: add support for new Team plan

## 1.4.0

### Minor Changes

-   7883bbcbd: feat: don't show deprecated plans
- 44be6dc0a: feat: set redirectTo during sign-in to support preview
environments

### Patch Changes

- 3c3594898: fix: allow access to graphite when configured running in
local dashboard
-   32c246b7a: chore: update docs icon

## 1.3.2

### Patch Changes

-   174b4165b: chore: use env variables when running graphql codegen
-   7c977e714: chore: change `Allowed Roles` to `Default Allowed Roles`
-   46f028b9f: fix: remove hardcoded ai version setting

## 1.3.1

### Patch Changes

- af33c21d1: chore: remove backendUrl deprecation notice and remove all
references to `providersUpdated`

## 1.3.0

### Minor Changes

-   04784d880: Fix graphite's default version

## 1.2.0

### Minor Changes

-   5733162ed: feat: add settings and ui for graphite

## 1.1.0

### Minor Changes

-   e2b79b5ec: chore: remove sharp from deps

## 1.0.1

### Patch Changes

-   @nhost/react-apollo@7.0.1
-   @nhost/nextjs@2.0.1

## 1.0.0

### Major Changes

- bc9eff6e4: chore: remove support for using backendUrl when
instantiating the Nhost client

### Patch Changes

-   Updated dependencies [bc9eff6e4]
    -   @nhost/nextjs@2.0.0
    -   @nhost/react-apollo@7.0.0

## 0.21.1

### Patch Changes

-   97ced73a3: fix(dashboard): prevent dashboard from resolving secrets

## 0.21.0

### Minor Changes

- ed1a8d458: Update alert message on increasing PostgreSQL's volume
capacity
-   2e2248fd4: feat(dashboard): add SQL editor

## 0.20.28

### Patch Changes

-   7c2c31082: feat: add support for users to delete their account
    -   @nhost/react-apollo@6.0.1
    -   @nhost/nextjs@1.13.40

## 0.20.27

### Patch Changes

- fa79b7709: chore(dashboard): tweaks and fixes to the service form and
dialog
-   8df84d782: fix(dashboard): allow resetting custom domains
    -   @nhost/react-apollo@6.0.0
    -   @nhost/nextjs@1.13.39

## 0.20.26

### Patch Changes

- 331ba0376: feat(dashboard): add postgres storage capacity modifier in
the settings
-   b7f801874: feat(dashboard): add new settings page for custom domains

## 0.20.25

### Patch Changes

-   @nhost/react-apollo@5.0.38

## 0.20.24

### Patch Changes

-   e10389ecf: fix(dashboard): disable run tab when developing locally
    -   @nhost/react-apollo@5.0.37

## 0.20.23

### Patch Changes

-   c01568a7d: chore(dashboard): show alert to update oauth providers

## 0.20.22

### Patch Changes

-   c3efb7ec8: feat(dashboard): query latest announcement from platform

## 0.20.21

### Patch Changes

-   3e46d3873: chore: update link to node18 announcement

## 0.20.20

### Patch Changes

-   @nhost/react-apollo@5.0.36
-   @nhost/nextjs@1.13.38

## 0.20.19

### Patch Changes

-   75c4c8ae3: feat(dashboard): make env value input multiline

## 0.20.18

### Patch Changes

- 425d485f8: fix(dashboard): make sure dedicated resources pricing
follows total resources

## 0.20.17

### Patch Changes

-   ae324f67f: fix(dashboard): remove unused graphql fields

## 0.20.16

### Patch Changes

-   df5b4302c: chore(dashboard): remove run feature flag
- bf4a1f6c2: feat(dashboard): fetch auth, postgres, hasura and storage
versions from dashboard
- 34fc08ca7: fix(dashboard/run): show correct private registry in
service details
-   885d10620: chore(dashboard): change feedback to contact us

## 0.20.15

### Patch Changes

- ed16c8b5d: feat(run): add a confirmation dialog when deleting a run
service
- 216990888: fix(run): center loading indicator when selecting a project

## 0.20.14

### Patch Changes

-   9fbea9787: feat: add node18 announcement

## 0.20.13

### Patch Changes

- e84acf469: fix(run): handle subdomain undefined error when creating a
new service

## 0.20.12

### Patch Changes

-   b7c799d62: feat(run): add dialog to copy registry and URLs

## 0.20.11

### Patch Changes

-   8903e6abd: fix(dashboard): show correct egress limit in usage stats

## 0.20.10

### Patch Changes

- 666a75a23: feat(dashboard): add functions execution time and egress
volume to usage stats

## 0.20.9

### Patch Changes

-   5e1e80aa8: fix(dashboard): show correct locales in user details
    -   @nhost/react-apollo@5.0.35
    -   @nhost/nextjs@1.13.37

## 0.20.8

### Patch Changes

-   @nhost/react-apollo@5.0.34
-   @nhost/nextjs@1.13.36

## 0.20.7

### Patch Changes

-   4a7ede11e: fix: distinguish files that were not uploaded
- 202b64723: feat(nhost-run): add support for one-click-install run
services
- 074a0fa11: feat(dashboard): add settings toggle to enable/disable
antivirus
    -   @nhost/react-apollo@5.0.33
    -   @nhost/nextjs@1.13.35

## 0.20.6

### Patch Changes

-   b20761e97: feat(services): add pricing info and confirmation dialog
-   90df6d81d: fix(services): handle null values when editing a service
-   aa8508467: fix: query service logs correctly
    feat: enable multiline support for environment value input

## 0.20.5

### Patch Changes

-   8d7f84b8d: fix: make announcement adapt to theme

## 0.20.4

### Patch Changes

-   3b75bfce2: fix: make announcement close properly
- f49819075: fix: show correct values when dedicated resources are
disabled

## 0.20.3

### Patch Changes

-   e643bd362: fix(services): fix errors when config is null
-   bcdab66bf: feat: add annoucement for nhost run
-   f967a2e59: added note about storage not being able to be downsized
-   311c7756d: chore(services): consistent naming for compute

## 0.20.2

### Patch Changes

-   9073182d5: chore(dashboard): bump `turbo` to 1.10.11
-   ece717d6e: feat(logs): show services in the logs page
- 82b335311: feat(metrics): change grafana link to point to the
dashboards
- b135ef695: fix(services): set command as optional and set min replicas
to 0

## 0.20.1

### Patch Changes

-   3d5c34f4c: fix(auth): fix users pagination limit

## 0.20.0

### Minor Changes

-   c99d117d1: feat(services): add support for custom services

## 0.19.2

### Patch Changes

-   face99ccd: chore(deps): bump turbo version
-   cfe527307: style: tweak pull config warning in dark mode
- a9d7da8af: chore(deps): update dependency @types/pluralize to ^0.0.30
-   9aa4371ef: chore: add hasura-auth version 0.21.2
- d14e112bf: chore(deps): update dependency prettier-plugin-tailwindcss
to ^0.4.0
-   d3e8bb94a: chore(deps): update dependency vite-plugin-dts to v3

## 0.19.1

### Patch Changes

-   @nhost/react-apollo@5.0.32
-   @nhost/nextjs@1.13.34

## 0.19.0

### Minor Changes

- 9c61c69a7: chore(dashboard):add postgres 14.6-20230705-1 to the
version selector

### Patch Changes

-   47bda15ff: feat(settings): add warning to pull config

## 0.18.0

### Minor Changes

- ee0b9b8ed: chore(dashboard):add hasura v2.28.2 and v2.29.0 to the
version selector

## 0.17.20

### Patch Changes

-   @nhost/react-apollo@5.0.31
-   @nhost/nextjs@1.13.33

## 0.17.19

### Patch Changes

-   f866120a6: fix(users): use the password length from the config

## 0.17.18

### Patch Changes

-   @nhost/react-apollo@5.0.30
-   @nhost/nextjs@1.13.32

## 0.17.17

### Patch Changes

-   ea7b102c0: fix(pat): highlight expired tokens

## 0.17.16

### Patch Changes

- b3b64a3b7: chore(deps): bump `@types/react` to `v18.2.14` and
`@types/react-dom` to `v18.2.6`
-   32b221f94: chore(deps): bump `graphiql` to `v3`
-   3a56c12df: chore(deps): bump `turbo` to `v1.10.6`
-   Updated dependencies [b3b64a3b7]
    -   @nhost/react-apollo@5.0.29
    -   @nhost/nextjs@1.13.31

## 0.17.15

### Patch Changes

-   f41fdc12a: chore(deps): bump `turbo` to `1.10.5`
-   6199c1c55: fix(projects): don't redirect to 404 page
-   Updated dependencies [07a45fde0]
    -   @nhost/react-apollo@5.0.28
    -   @nhost/nextjs@1.13.30

## 0.17.14

### Patch Changes

- 80b22724d: chore(deps): bump `@types/react` to `v18.2.13`,
`@types/react-dom` to `v18.2.6` and `@storybook/testing-library` to
`v0.2.0`

## 0.17.13

### Patch Changes

-   cc02902cb: chore(docs): update environment variable documentation

## 0.17.12

### Patch Changes

-   660d339e1: fix(storybook): don't break storybook
-   660d339e1: fix(tests): prevent warnings during tests
    -   @nhost/react-apollo@5.0.27
    -   @nhost/nextjs@1.13.29

## 0.17.11

### Patch Changes

- bd4d0c270: chore(dashboard):add postgres 14.6-20230613-1 to the
version selector

## 0.17.10

### Patch Changes

-   c8c2a10b2: fix(database): don't break the password reset flow
- e70b45498: chore(deps): bump `@types/react` to `v18.2.12` and
`@types/react-dom` to `v18.2.5`

## 0.17.9

### Patch Changes

- 842055099: chore(deps): bump `turbo` to `v1.10.3` and `pnpm` to
`v8.6.2`
- fd12aa0a8: chore(projects): remove the postgres password input from
the project creation screen
-   022b76e78: chore(deps): bump `@types/react` to `v18.2.11`
-   3555ab2b7: chore(deps): bump `vitest` monorepo to `v0.32.0`
-   c43e54922: feat(backups): add download button to backups

## 0.17.8

### Patch Changes

-   d0457fe5c: feat(settings): improve the dashboard and config parity
    -   @nhost/react-apollo@5.0.26
    -   @nhost/nextjs@1.13.28

## 0.17.7

### Patch Changes

-   4f0368b95: fix(account): don't break account settings page

## 0.17.6

### Patch Changes

- 64a8f41d0: chore(resources): lower the maximum allowed resources per
service

## 0.17.5

### Patch Changes

-   @nhost/react-apollo@5.0.25
-   @nhost/nextjs@1.13.27

## 0.17.4

### Patch Changes

- 9b1d0f7a5: fix(deployments): use correct timestamp for deployment
details
-   6d2963ffa: chore(deps): bump `@types/react` to `v18.2.8`
- 8871267b9: chore(deps): downgrade `pnpm` to `v8.5.1` because of no
Turborepo support

## 0.17.3

### Patch Changes

-   01eeef9de: chore(misc): under the hood improvements
- 21e13db05: chore(deps): bump `@types/react` to `v18.2.7` and `turbo`
to `v1.10.1`
- f16433ae6: chore(secrets): allow empty secrets and environment
variables
-   aa3c62989: chore(cli): bump Nhost CLI version to v1.0
    -   @nhost/react-apollo@5.0.24
    -   @nhost/nextjs@1.13.26

## 0.17.2

### Patch Changes

-   88a4983f: chore(misc): under the hood improvements

## 0.17.1

### Patch Changes

-   9b0d4dde: feat(secrets): enable secrets

## 0.17.0

### Minor Changes

-   15d84a19: Add postgres 14.6-20230525

## 0.16.14

### Patch Changes

-   4c626174: chore: updated import paths, improved directory structure
-   cc047b71: chore(deps): bump `@fontsource` monorepo to `v5.0.0`
-   99edd012: feat(account): add support for personal access tokens

## 0.16.13

### Patch Changes

-   78c7109c: feat(settings): allow selecting service versions

## 0.16.12

### Patch Changes

- 399009d6: fix(gql): don't enter an infinite loop when fetching remote
app data
- 329e5a91: fix(deployments): use the same sorting of deployments
everywhere
- 6d559d6e: chore(settings): add under the hood improvements to the
settings page
- 12eb236c: chore(deps): bump `prettier-plugin-tailwindcss` to `v0.3.0`
-   f9b81a2a: chore(deps): bump `turbo` to `v1.9.8`
-   1345741b: fix(projects): don't redirect to 404 on project creation
-   Updated dependencies [7fea29a8]
    -   @nhost/react-apollo@5.0.23
    -   @nhost/nextjs@1.13.25

## 0.16.11

### Patch Changes

- 1230b722: fix(projects): don't redirect to 404 on when the project is
renamed
    -   @nhost/react-apollo@5.0.22
    -   @nhost/nextjs@1.13.24

## 0.16.10

### Patch Changes

-   Updated dependencies [da03bf39]
    -   @nhost/react-apollo@5.0.21
    -   @nhost/nextjs@1.13.23

## 0.16.9

### Patch Changes

- 349aac36: fix(settings): use region domain when constructing the
postgres connection string

## 0.16.8

### Patch Changes

- 20fb69fa: chore(projects): change the way how API URLs are constructed

## 0.16.7

### Patch Changes

- 49f9b837: chore(docker): bump `pnpm` to `v8.4.0` and `turbo` to
`v1.9.3`
- 3f478a4e: chore(deps): bump `vitest` to `v0.31.0`, `@types/react` to
`v18.2.6` and `@types/react-dom` to `v18.2.4`

## 0.16.6

### Patch Changes

- d926f156: fix(projects): redirect to 404 when an invalid project is
opened
- 49b99728: fix(projects): disable features for non-owner members of
workspaces

## 0.16.5

### Patch Changes

-   12e2855f: chore(deps): bump `jsdom` to v22
-   e4972b83: feat(metrics): add Grafana page

## 0.16.4

### Patch Changes

- 3f396a9e: fix(projects): unpause after upgrading a paused project to
pro
- 3f396a9e: fix(projects): don't redirect to 404 page after project
creation

## 0.16.3

### Patch Changes

-   Updated dependencies [90c60311]
    -   @nhost/react-apollo@5.0.20
    -   @nhost/nextjs@1.13.22

## 0.16.2

### Patch Changes

-   0f34f0c6: fix(projects): disallow downgrading to free plan
- 8da291ad: chore(deps): bump `@types/react` to v18.2.0 and
`@types/react-dom` to v18.2.1

## 0.16.1

### Patch Changes

- adc828a5: fix(gql): don't enter an infinite loop when fetching remote
app data

## 0.16.0

### Minor Changes

-   2fb1145f: feat(compute): add support for replicas

### Patch Changes

- d8ceccec: chore(env): remove deprecated `NHOST_BACKEND_URL`
environment variable

## 0.15.2

### Patch Changes

-   84b84ab7: fix(projects): filter projects by workspace

## 0.15.1

### Patch Changes

-   2faf7907: chore(deps): bump `graphql-request` to v6
-   f1b5a944: chore(deps): bump `@vitejs/plugin-react` to v4
-   7f1785ac: chore(deps): bump `@types/react` to v18.0.37
    -   @nhost/react-apollo@5.0.19

## 0.15.0

### Minor Changes

-   85889ee8: feat(dashboard): add Compute management to the settings

## 0.14.8

### Patch Changes

-   668c8771: chore(dialogs): unify dialog management of payment dialogs

## 0.14.7

### Patch Changes

-   d4ccc656: chore: cleanup unused code
    -   @nhost/react-apollo@5.0.18
    -   @nhost/nextjs@1.13.21

## 0.14.6

### Patch Changes

-   b299cfc9: chore(deps): bump `vitest` to v0.30.0
-   411cb65b: chore(projects): refactor workspace and project hooks
- 43b1b144: chore(deps): bump `@types/react` to v18.0.34 and
`@types/react-dom` to v18.0.11
-   Updated dependencies [43b1b144]
    -   @nhost/react-apollo@5.0.17
    -   @nhost/nextjs@1.13.20

## 0.14.5

### Patch Changes

-   ba0d57ee: fix(i18n): revert i18n library
-   3328ed05: feat(projects): improve overview when there is an error

## 0.14.4

### Patch Changes

-   5e0920ba: chore(deps): bump `next-seo` to v6
-   706c9dc3: chore(deps): bump `@types/react` to 18.0.33
-   99f8f6b3: feat(metrics): show metrics on the overview

## 0.14.3

### Patch Changes

-   @nhost/react-apollo@5.0.16

## 0.14.2

### Patch Changes

-   3cb67300: fix(logs): don't break UI when clearing time picker
-   7453bf3b: feat(projects): show project creator info
-   c166dad0: chore(tests): improve auth page tests
-   6a290bb2: chore(deps): bump `@types/react` to 18.0.32

## 0.14.1

### Patch Changes

-   @nhost/react-apollo@5.0.15
-   @nhost/nextjs@1.13.19

## 0.14.0

### Minor Changes

-   6e1f03ea: feat(dashboard): add support for the Azure AD provider

### Patch Changes

-   1bd2c373: chore(deps): bump `turbo` to 1.8.6
-   d329b621: chore(deps): bump `@types/react` to 18.0.30
-   cb248f0d: fix(tests): avoid name collision in database tests
-   867c8076: chore(deps): bump `@types/react` to 18.0.29

## 0.13.10

### Patch Changes

- e93b06ab: fix(dashboard): remove left margin from workspace list on
mobile
-   1c4806bf: chore(deps): bump `sharp` to 0.32.0
    -   @nhost/react-apollo@5.0.14
    -   @nhost/nextjs@1.13.18

## 0.13.9

### Patch Changes

-   912ed76c: chore(dashboard): bump `@apollo/client` to 3.7.10
-   Updated dependencies [912ed76c]
    -   @nhost/react-apollo@5.0.13

## 0.13.8

### Patch Changes

-   7c127372: chore(dashboard): bump `react-error-boundary` to v4

## 0.13.7

### Patch Changes

- 9130ab12: chore(dashboard): bump `yup` to v1 and `@hookform/resolvers`
to v3

## 0.13.6

### Patch Changes

- 253dd235: using new mutation to create projects + refactor Create
Project page.

## 0.13.5

### Patch Changes

-   @nhost/react-apollo@5.0.12
-   @nhost/nextjs@1.13.17

## 0.13.4

### Patch Changes

-   b48bc034: fix(dashboard): disable new users
-   798e591b: fix(dashboard): show correct date in data grid

## 0.13.3

### Patch Changes

-   bfb4c1a6: chore(dashboard): remove `useAxios` property
-   d8d8394b: Dashboard: allow to override hasura admin secret in docker
-   Updated dependencies [ce1ee40d]
    -   @nhost/nextjs@1.13.16
    -   @nhost/react-apollo@5.0.11

## 0.13.2

### Patch Changes

-   beed2eba: Fix docker entrypoint for dashboard
- 2c8559a3: fix(dashboard): refresh project list after deleting a
project
-   4329d048: chore(dashboard): bump `graphiql` dependencies

## 0.13.1

### Patch Changes

-   cbb1fc5b: chore(dashboard): cleanup GraphQL operations

## 0.13.0

### Minor Changes

-   088584e7: feat(dashboard): add support for custom local subdomains

### Patch Changes

-   2ac90dfd: fix(dashboard): improve mobile responsive layout
-   Updated dependencies [f375eacc]
    -   @nhost/nextjs@1.13.15
    -   @nhost/react-apollo@5.0.10

## 0.12.4

### Patch Changes

-   @nhost/react-apollo@5.0.9
-   @nhost/nextjs@1.13.14

## 0.12.3

### Patch Changes

-   2b1338f7: chore(dashboard): bump `turbo` to 1.8.3
- 5223ee93: fix(dashboard): show correct deployment status on the main
page
-   850a049c: chore(deps): update docker/build-push-action action to v4
-   Updated dependencies [850a049c]
    -   @nhost/nextjs@1.13.13
    -   @nhost/react-apollo@5.0.8

## 0.12.2

### Patch Changes

-   4bf40995: chore(deps): bump `typescript` to `4.9.5`
-   8bb097c9: chore(deps): bump `vitest`
- 35d52aab: chore(deps): replace `cross-fetch` with `isomorphic-unfetch`
-   Updated dependencies [4bf40995]
-   Updated dependencies [8bb097c9]
-   Updated dependencies [35d52aab]
    -   @nhost/react-apollo@5.0.7
    -   @nhost/nextjs@1.13.12

## 0.12.1

### Patch Changes

-   c96d7ccd: fix(dashboard): fix docker builds

## 0.12.0

### Minor Changes

-   d1671210: feat(dashboard): use mimir to manage project configuration

### Patch Changes

-   f65e4de9: chore(deps): bump @graphql-codegen monorepo to v3

## 0.11.20

### Patch Changes

-   4b4f0d01: chore(dashboard): improve dialog management

## 0.11.19

### Patch Changes

-   @nhost/react-apollo@5.0.6
-   @nhost/nextjs@1.13.11

## 0.11.18

### Patch Changes

-   01318860: fix(nhost-js): use correct URL for functions requests
-   Updated dependencies [01318860]
    -   @nhost/react-apollo@5.0.5
    -   @nhost/nextjs@1.13.10

## 0.11.17

### Patch Changes

-   f673adea: fix(dashboard): set correct Content-Type for user creation
-   445d8ef4: chore(deps): bump `@nhost/react-apollo` to 5.0.4
-   445d8ef4: chore(deps): bump `@nhost/nextjs` to 1.13.9
- 0368663d: fix(dashboard): allow permission editing for auth and
storage schemas
-   Updated dependencies [445d8ef4]
-   Updated dependencies [445d8ef4]
    -   @nhost/react-apollo@5.0.4
    -   @nhost/nextjs@1.13.9

## 0.11.16

### Patch Changes

-   b755e908: fix(dashboard): use correct date for last seen
-   2d9145f9: chore(deps): revert GraphQL client
- 1ddf704c: fix(dashboard): don't show false positive message for failed
user creation
    -   @nhost/react-apollo@5.0.3
    -   @nhost/nextjs@1.13.8

## 0.11.15

### Patch Changes

-   @nhost/react-apollo@5.0.2
-   @nhost/nextjs@1.13.7

## 0.11.14

### Patch Changes

- 2cc18dcb: fix(dashboard): prevent permission editor dropdown from
being always open

## 0.11.13

### Patch Changes

- 3343a363: chore(dashboard): bump `@testing-library/react` to v14 and
`@testing-library/dom` to v9
    -   @nhost/react-apollo@5.0.1
    -   @nhost/nextjs@1.13.6

## 0.11.12

### Patch Changes

- 87eda76e: chore(dashboard): bump `@types/react` to v18.0.28 and
`@types/react-dom` to v18.0.11
-   6f0ac570: feat(dashboard): show dashboard version in account menu

## 0.11.11

### Patch Changes

-   bf1e4071: chore(dashboard): bump `react-is` version to `18.2.0`
-   Updated dependencies [bf1e4071]
-   Updated dependencies [5013213b]
    -   @nhost/nextjs@1.13.5
    -   @nhost/react-apollo@4.13.5

## 0.11.10

### Patch Changes

- a37a430b: fix(dashboard): don't break UI when deployments are
unavailable
    -   @nhost/react-apollo@4.13.4
    -   @nhost/nextjs@1.13.4

## 0.11.9

### Patch Changes

-   7b970e68: fix(dashboard): fix header link color

## 0.11.8

### Patch Changes

- f33242f2: feat(dashboard): add new sign up, sign in and reset password
pages

## 0.11.7

### Patch Changes

-   e9c8909c: fix(dashboard): use correct theme color in dark mode

## 0.11.6

### Patch Changes

-   902f486b: fix(dashboard): re-enable Hasura on logs page

## 0.11.5

### Patch Changes

-   1f9720fa: fix(dashboard): apply select permissions properly

## 0.11.4

### Patch Changes

-   deb14b51: fix(dashboard): don't break billing form

## 0.11.3

### Patch Changes

-   @nhost/react-apollo@4.13.3
-   @nhost/nextjs@1.13.3

## 0.11.2

### Patch Changes

-   f143e51d: chore(dashboard): pin Turborepo to 1.6.3

## 0.11.1

### Patch Changes

-   c2b5a41a: chore(dashboard): select system colors by default

## 0.11.0

### Minor Changes

-   1ebaf429: feat(dashboard): introduce Dark Mode 🌚

### Patch Changes

- 63b445c4: fixed duplicated logs bug and made to date count during live
mode

## 0.10.1

### Patch Changes

-   e146d32e: chore(deps): update dependency @types/react to v18.0.27
-   59347fcd: correct allowed role name
-   5b65cac9: updated authentication documentation
-   963f9b5e: feat(dashboard): include project info in feedback

## 0.10.0

### Minor Changes

-   ed4c7801: chore(dashboard): remove Functions section

## 0.9.10

### Patch Changes

-   4e2f8ccd: fix(dashboard): don't break Auth page in local mode

## 0.9.9

### Patch Changes

-   31abbe5f: fix(dashboard): enable toggle when settings are filled in

## 0.9.8

### Patch Changes

- 5bdd31ad: chore(dashboard): list fewer images per page on the Storage
page
- 5121851c: fix(dashboard): don't throw validation error for valid
permission rules

## 0.9.7

### Patch Changes

-   c126b20d: fix(dashboard): correct redeployment button

## 0.9.6

### Patch Changes

-   36c3519c: feat(dashboard): retrigger deployments

## 0.9.5

### Patch Changes

- 200e9f77: chore(deps): update dependency @types/react-dom to v18.0.10
-   Updated dependencies [200e9f77]
    -   @nhost/nextjs@1.13.2
    -   @nhost/react-apollo@4.13.2

## 0.9.4

### Patch Changes

- dbd3ded5: fix(dashboard): workspaces creation, new form, correct
redirects.

## 0.9.3

### Patch Changes

-   85f0f943: fix(dashboard): don't break the table creation process

## 0.9.2

### Patch Changes

-   Updated dependencies [d42c27ae]
-   Updated dependencies [927be4a2]
    -   @nhost/nextjs@1.13.1
    -   @nhost/react-apollo@4.13.1

## 0.9.1

### Patch Changes

-   d0f80811: fix(dashboard): don't show error when signing out the user

## 0.9.0

### Minor Changes

- d92891b2: feat(dashboard): add Permission Editor to the Database
section

### Patch Changes

-   3d379128: fix(dashboard): create new user
    -   @nhost/react-apollo@4.13.0
    -   @nhost/nextjs@1.13.0

## 0.8.1

### Patch Changes

-   7cadd944: fix(dashboard): display Twitter provider settings

## 0.8.0

### Minor Changes

-   9a1aa7bb: add functions to the log dashboard
-   f29abe62: feat(dashboard): Users Management v2

### Patch Changes

-   7766624b: feat(dashboard): add JWT secret editor modal
    -   @nhost/react-apollo@4.12.1
    -   @nhost/nextjs@1.12.1

## 0.7.13

### Patch Changes

-   dd0738d5: fix(dashboard): provisioning status polling

## 0.7.12

### Patch Changes

-   b21222b3: chore(deps): update dependency @types/node to v16
-   9e0486a3: fix(dashboard): close modals when navigating
-   Updated dependencies [b21222b3]
-   Updated dependencies [65687bee]
-   Updated dependencies [54df0df4]
    -   @nhost/nextjs@1.12.0
    -   @nhost/react-apollo@4.12.0

## 0.7.11

### Patch Changes

-   d6527122: fix(dashboard): use correct service URLs

## 0.7.10

### Patch Changes

-   Updated dependencies [57db5b83]
    -   @nhost/nextjs@1.11.0
    -   @nhost/nhost-js@1.7.0
    -   @nhost/react@0.17.0
    -   @nhost/react-apollo@4.11.0

## 0.7.9

### Patch Changes

- a6d31dc2: fix(dashboard): don't break the UI when project is not
loaded yet

## 0.7.8

### Patch Changes

- 7f251111: Use `NhostProvider` instead of `NhostReactProvider` and
`NhostNextProvider`

    `NhostReactProvider` and `NhostNextProvider` are now deprecated

-   f4d70f88: fix(dashboard): do not break when region is nullish

- 4a9471cc: Windows Live Provider displayed link updated to match
backend url

- 594488e4: fix(dashboard): do not show error when submitting Apple
provider settings

-   Updated dependencies [7f251111]
    -   @nhost/nextjs@1.10.0
    -   @nhost/react@0.16.0
    -   @nhost/react-apollo@4.10.0

## 0.7.7

### Patch Changes

-   80b604ad: fix(dashboard): use correct Hasura slug

## 0.7.6

### Patch Changes

-   2d2beb53: fix(dashboard): prevent error on GraphQL page
-   ac8efcbd: chore(dashboard): deprecate old DNS name

## 0.7.5

### Patch Changes

-   132a4f4b: chore(dashboard): remove unused dependencies
- 132a4f4b: chore(deps): synchronize @types/react-dom and @types/react
versions
-   db57572f: fix(dashboard): correct section paddings when no env vars
-   Updated dependencies [132a4f4b]
    -   @nhost/react@0.15.2
    -   @nhost/react-apollo@4.9.2
    -   @nhost/nextjs@1.9.3

## 0.7.4

### Patch Changes

-   34d85e54: chore(deps): update dependency critters to ^0.0.16
- 9b93cf95: chore(deps): update dependency @netlify/functions to ^0.11.0
-   e0439030: chore(deps): update dependency @types/react-dom to v18.0.9
-   Updated dependencies [82124329]
    -   @nhost/nextjs@1.9.2

## 0.7.3

### Patch Changes

-   a1193da4: fix(dashboard): remove character limit from env var inputs

## 0.7.2

### Patch Changes

-   44f13f62: chore(dashboard): cleanup unused files

## 0.7.1

### Patch Changes

- e01cb2ed: chore(dashboard): change settings sidebar menu item density

## 0.7.0

### Minor Changes

- db342f45: chore(dashboard): refactor Roles and Permissions settings
sections
-   8b9fa0b1: feat(dashboard): add Environment Variables page

### Patch Changes

-   Updated dependencies [66b4f3d0]
-   Updated dependencies [2e6923dc]
-   Updated dependencies [ef117c28]
-   Updated dependencies [aebb8225]
    -   @nhost/core@0.9.4
    -   @nhost/nhost-js@1.6.2
    -   @nhost/nextjs@1.9.1
    -   @nhost/react@0.15.1
    -   @nhost/react-apollo@4.9.1

## 0.6.0

### Minor Changes

-   eef9c914: feat(dashboard): add Roles and Permissions page

## 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

-   766cb612: fix(dashboard): correct redirect URL for oauth providers
-   Updated dependencies [53bdc294]
-   Updated dependencies [f2aaff05]
    -   @nhost/nextjs@1.8.3
    -   @nhost/core@0.9.3
    -   @nhost/react@0.14.3
    -   @nhost/nhost-js@1.6.1
    -   @nhost/react-apollo@4.8.3

## 0.4.0

### Minor Changes

-   9211743d: feat(dashboard): migrate Settings page features

## 0.3.0

### Minor Changes

-   73da6a67: fix(dashboard): avoid using BACKEND_URL locally

## 0.2.0

### Minor Changes

-   db118f97: feat(dashboard): generate Docker image

## @nhost/docs@2.28.1

### Patch Changes

- 6b8163d: fix(nhost-js) update service URL generation for local
environments

## @nhost-examples/cli@0.3.18

### Patch Changes

-   Updated dependencies [6b8163d]
    -   @nhost/nhost-js@3.2.5

## @nhost-examples/codegen-react-apollo@0.5.1

### Patch Changes

-   @nhost/react@3.10.1
-   @nhost/react-apollo@17.0.1

## @nhost-examples/codegen-react-query@0.5.1

### Patch Changes

- 6b8163d: fix(nhost-js) update service URL generation for local
environments
    -   @nhost/react@3.10.1

## @nhost-examples/codegen-react-urql@0.4.1

### Patch Changes

-   @nhost/react@3.10.1
-   @nhost/react-urql@14.0.1

## @nhost-examples/multi-tenant-one-to-many@2.2.19

### Patch Changes

-   Updated dependencies [6b8163d]
    -   @nhost/nhost-js@3.2.5

## @nhost-examples/nextjs@0.4.4

### Patch Changes

-   @nhost/react@3.10.1
-   @nhost/react-apollo@17.0.1
-   @nhost/nextjs@2.2.4

## @nhost-examples/node-storage@0.2.18

### Patch Changes

-   Updated dependencies [6b8163d]
    -   @nhost/nhost-js@3.2.5

## @nhost-examples/nextjs-server-components@0.5.3

### Patch Changes

- 6b8163d: fix(nhost-js) update service URL generation for local
environments
-   Updated dependencies [6b8163d]
    -   @nhost/nhost-js@3.2.5

## @nhost-examples/react-apollo@1.3.1

### Patch Changes

-   @nhost/react@3.10.1
-   @nhost/react-apollo@17.0.1

## @nhost-examples/react-gqty@1.3.1

### Patch Changes

-   @nhost/react@3.10.1

## @nhost-examples/react-native@0.1.5

### Patch Changes

-   @nhost/react@3.10.1
-   @nhost/react-apollo@17.0.1

## @nhost-examples/seed-data-storage@0.0.5

### Patch Changes

- 6b8163d: fix(nhost-js) update service URL generation for local
environments

## @nhost-examples/vue-apollo@0.9.1

### Patch Changes

-   Updated dependencies [6b8163d]
    -   @nhost/nhost-js@3.2.5
    -   @nhost/apollo@8.0.5
    -   @nhost/vue@2.9.2

## @nhost-examples/vue-quickstart@0.3.1

### Patch Changes

-   @nhost/apollo@8.0.5
-   @nhost/vue@2.9.2

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-02-25 15:11:23 -01:00
Nuno Pato
6cc8f954e1 chore: dashboard: add org slug and project subdomain properites to se… (#3216)
### **User description**
- adds 2 properties (org slug and project subdomain) to the page event
on segment


___

### **PR Type**
Enhancement


___

### **Description**
- Add organization slug and project subdomain to Segment page event

- Update Analytics component to include new properties

- Refactor route change handling for analytics

- Add changeset for minor version bump


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>analytics.tsx</strong><dd><code>Enhance Analytics
component with org and project data</code>&nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>

dashboard/src/components/analytics/analytics.tsx

<li>Import hooks for current org and project<br> <li> Add org slug and
project subdomain to analytics page event<br> <li> Refactor route change
handling with custom properties<br> <li> Update dependency array in
useEffect


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3216/files#diff-8879790b4a5836d5613a5ee9442b801b87b3385be9b4767e85e880cefda4d52e">+15/-4</a>&nbsp;
&nbsp; </td>

</tr>
</table></td></tr><tr><td><strong>Documentation</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>wild-rings-count.md</strong><dd><code>Add changeset for
analytics enhancement</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></summary>
<hr>

.changeset/wild-rings-count.md

<li>Add changeset file for minor version bump<br> <li> Include
description of changes to Segment page event


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3216/files#diff-752a27afc38e7de05f5621253e536d3eec5ad48ff50eb97ae43e36ccb97e1a84">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-25 13:59:30 -01:00
David BM
1821df7a96 fix (ci): github actions signature checks when installing packages (#3217)
### **User description**
Should fix `dashboard: release form` action

Reference:
https://vercel.com/guides/corepack-errors-github-actions#how-to-fix-it


___

### **PR Type**
Enhancement, Bug fix


___

### **Description**
- Update Corepack to latest version

- Enable Corepack for package management

- Install and verify Corepack and pnpm versions

- Improve CI workflow for package installation


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>action.yaml</strong><dd><code>Update CI workflow with
Corepack and version checks</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></summary>
<hr>

.github/actions/install-dependencies/action.yaml

<li>Add step to install and enable latest Corepack<br> <li> Display
Corepack and pnpm versions for verification<br> <li> Improve package
installation process in CI


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3217/files#diff-342d59190b4737ee45e2062eb625ada477bcea5b4a843b25900ad55d7982f200">+8/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-25 15:06:16 +01:00
David BM
ab8a55ede4 chore: update nix config to use pnpm10 (#3218)
### **PR Type**
Enhancement


___

### **Description**
- Update pnpm version from 9 to 10

- Modify flake.nix to use pnpm_10


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Configuration
changes</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>flake.nix</strong><dd><code>Upgrade pnpm from version 9
to 10</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

flake.nix

<li>Replace <code>pnpm_9</code> with <code>pnpm_10</code> in
nativeBuildInputs<br> <li> Update <code>pnpm_9</code> to
<code>pnpm_10</code> in devShells buildInputs


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3218/files#diff-206b9ce276ab5971a2489d75eb1b12999d4bf3843b7988cbe8d687cfde61dea0">+2/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-25 14:35:40 +01:00
David BM
39eb70678b fix (dashboard): database storage capacity setting paywall (#3214)
### **PR Type**
Enhancement


___

### **Description**
- Add paywall for database storage capacity setting

- Implement UpgradeNotification component for free projects

- Replace legacy plan check with isFreeProject flag

- Add TransferProjectDialog for project upgrades


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>

<summary><strong>DatabaseStorageCapacity.tsx</strong><dd><code>Implement
paywall for database storage capacity</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>


dashboard/src/features/orgs/projects/database/settings/components/DatabaseStorageCapacity/DatabaseStorageCapacity.tsx

<li>Implemented UpgradeNotification component for free projects<br> <li>
Added TransferProjectDialog for project upgrades<br> <li> Replaced
legacy plan check with isFreeProject flag<br> <li> Updated UI components
and imports


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3214/files#diff-097a59d13b44816051386182a444eadfe2dcacd69b88c121af6733d7eca3ee43">+61/-7</a>&nbsp;
&nbsp; </td>

</tr>
</table></td></tr><tr><td><strong>Documentation</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>neat-bikes-provide.md</strong><dd><code>Add changeset
for paywall implementation</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></summary>
<hr>

.changeset/neat-bikes-provide.md

<li>Added changeset file for minor version bump<br> <li> Described fix
for database storage capacity setting paywall


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3214/files#diff-90c63b40b7b544622b40a21bc350f5f90b56bc65047bb2f8055fd6c59acc6aae">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-24 20:04:39 -01:00
Nuno Pato
e3cd5f858f chore: dashboard: add segment analytics (#3213)
### **User description**
- adds segment `page` event


___

### **PR Type**
Enhancement


___

### **Description**
- Add Segment analytics to dashboard

- Implement page tracking for route changes

- Replace Segment snippet with Analytics-Next library

- Update environment variables and dependencies


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>analytics.tsx</strong><dd><code>Add Analytics component
for Segment integration</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

dashboard/src/components/analytics/analytics.tsx

<li>Create new Analytics component<br> <li> Initialize Segment
analytics<br> <li> Set up page tracking on route changes


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3213/files#diff-8879790b4a5836d5613a5ee9442b801b87b3385be9b4767e85e880cefda4d52e">+19/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>segment.ts</strong><dd><code>Set up Segment
AnalyticsBrowser configuration</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

dashboard/src/lib/segment.ts

<li>Initialize AnalyticsBrowser from Segment<br> <li> Load Segment with
CDN URL and write key


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3213/files#diff-a23427ba42161ffe844159b21f2901e32e6518c61895d5b0e90c653df6876d0c">+6/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>_app.tsx</strong><dd><code>Integrate Analytics
component in _app.tsx</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>

dashboard/src/pages/_app.tsx

<li>Import and use new Analytics component<br> <li> Remove old Segment
snippet implementation<br> <li> Update page tracking logic


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3213/files#diff-944e6c6d89cc2a23522cb7246ab566c540c8a06660c9c5385363493d3fb613af">+2/-22</a>&nbsp;
&nbsp; </td>

</tr>
</table></td></tr><tr><td><strong>Documentation</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>weak-clocks-approve.md</strong><dd><code>Add changeset
for Segment analytics integration</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

.changeset/weak-clocks-approve.md

<li>Add changeset for minor version bump<br> <li> Describe addition of
Segment and page event tracking


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3213/files#diff-9ae958fefce4c3b404dba6efd018e882be2e5c88c70bf695bb869d3bc4b97205">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr><tr><td><strong>Configuration
changes</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>.env.example</strong><dd><code>Update .env.example with
Segment CDN URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>

dashboard/.env.example

- Add NEXT_PUBLIC_SEGMENT_CDN_URL environment variable


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3213/files#diff-b47cf46119af2f0298d96e5657e53e57161833e8b02d87526ac5c1ed9393d477">+1/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr><tr><td><strong>Dependencies</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>package.json</strong><dd><code>Update dependencies for
Segment Analytics-Next</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

dashboard/package.json

<li>Replace @segment/snippet with @segment/analytics-next<br> <li>
Remove analytics-node dependency


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3213/files#diff-2d8d55c799cd71f1b35e831f075f8178ed1734c4820a2ad548b4dd24d6938d7c">+1/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-24 13:44:14 -01:00
David BM
69d9ab60c8 fix (CI): update PNPM overrides to address security vulnerabilities (#3204)
### **User description**
Fixes PNPM vulnerabilities with PNPM version overrides

vulnerable advisories were:

https://github.com/advisories/GHSA-67mh-4wv8-2f99
https://github.com/advisories/GHSA-76p7-773f-r4q5
https://github.com/advisories/GHSA-h5c3-5r3r-rr8q
https://github.com/advisories/GHSA-rmvr-2pp2-xj38
https://github.com/advisories/GHSA-xx4v-prfh-6cgc


___

### **PR Type**
Enhancement, Bug fix


___

### **Description**
- Update PNPM overrides to address security vulnerabilities

- Add new package version constraints for security

- Upgrade multiple dependencies to secure versions

- Enhance CI/CD pipeline security measures


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Dependencies</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>package.json</strong><dd><code>Update PNPM overrides to
address security vulnerabilities</code></dd></summary>
<hr>

package.json

<li>Added new PNPM overrides for @octokit packages<br> <li> Included
override for serialize-javascript<br> <li> Added override for
esbuild<br> <li> Updated existing overrides for better security


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3204/files#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519">+6/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-17 23:40:10 +01:00
David BM
a8961c0ab0 fix (dashboard): regex search with service filter (#3193)
### **User description**
Fixes #3154


___

### **PR Type**
Bug fix, Enhancement


___

### **Description**
- Fix regex search with service filter

- Refactor service label mapping

- Add new service types (Grafana, Backup Jobs, AI)

- Improve code maintainability and readability


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>LogsHeader.tsx</strong><dd><code>Refactor service label
mapping in LogsHeader</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>


dashboard/src/features/orgs/projects/logs/components/LogsHeader/LogsHeader.tsx

<li>Import LOGS_SERVICE_TO_LABEL constant<br> <li> Replace hardcoded
label mappings with LOGS_SERVICE_TO_LABEL<br> <li> Simplify service
label mapping logic


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3193/files#diff-ebb3285aa776c9c5ea8b72672c4aafd55994c6c694998bbf56ca9c56d1e77664">+5/-13</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>services.ts</strong><dd><code>Enhance and centralize
service type definitions</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>


dashboard/src/features/orgs/projects/logs/utils/constants/services/services.ts

<li>Add new service types: GRAFANA, JOB_BACKUP, AI<br> <li> Replace
LOGS_AVAILABLE_SERVICES array with LOGS_SERVICE_TO_LABEL <br>object<br>
<li> Simplify and centralize service label mappings


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3193/files#diff-8fcdaed33322718091b613ae22c65cc3eb61972904b5af46866b160c9bbbe48c">+16/-29</a>&nbsp;
</td>

</tr>
</table></td></tr><tr><td><strong>Documentation</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>twenty-icons-kneel.md</strong><dd><code>Add changeset
for version bump and bug fix</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>

.changeset/twenty-icons-kneel.md

<li>Add changeset file for version bump<br> <li> Describe fix for regex
filtering with service type filter


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3193/files#diff-9b50bf5928d06c1e8c05f66991d39cf389309cc4235feb23e59880b4305c0085">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-17 17:16:54 +01:00
robertkasza
6b8163d21f fix(nhost-js): update service URL generation for local environments (#3197)
### **User description**
- remove unnecessary redirectTo option from nextjs quickstart/example
- update README for nextjs quickstart/example
- update local URL-s in the repo to use the correct format


___

### **PR Type**
Bug fix


___

### **Description**
- Update local service URLs to include '.local'

- Remove unnecessary redirectTo option in NextJS example

- Update README for NextJS quickstart/example


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Bug
fix</strong></td><td><details><summary>19 files</summary><table>
<tr>
<td><strong>OverviewDeployments.test.tsx</strong><dd><code>Update local
GraphQL URL in tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-a9440d76cf165e4df8e9db020ee2ab3896281633dbe5ba3691e775d57188bc80">+148/-136</a></td>

</tr>

<tr>
<td><strong>OverviewDeployments.test.tsx</strong><dd><code>Update local
GraphQL URL in tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-7cc449a1b6f28a29590e4ea85aa4318961f1dcf9770447080b689432bb58e697">+117/-105</a></td>

</tr>

<tr>
<td><strong>nhostGraphQLLink.ts</strong><dd><code>Update local GraphQL
URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-c687b3a6fa4667366a494cee0a0cd8a956e97ab435d1dcca0e3d9758952db695">+3/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>hasuraMetadataQuery.ts</strong><dd><code>Update local Hasura
URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-2828f4a1163f0d281abf2517e76fc9dd393bb870478aea874019a42f9c4b7ac3">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>tableQuery.ts</strong><dd><code>Update local Hasura
URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-fdb6ad2a7e58c374f3a6772219e7f7e72ca2927def74ec75893b064caba12639">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>tokenQuery.ts</strong><dd><code>Update local Auth
URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-c86f0dec25fa37d82ed9765646ffaa9812f3b8b6f36d74056ab9e2dbe3416d0a">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>testUtils.tsx</strong><dd><code>Update local service URLs in
test utils</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-6ebbd73e167641a1706f1b8d30b00569336d10f3c2ab7626d81e639015383e5e">+9/-8</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>testUtils.tsx</strong><dd><code>Update local service URLs in
test utils</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-78f29250407edf853a353b48242d3cee59aa5724f38a60bb23bebdfc1ea2f9b5">+9/-8</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>env.ts</strong><dd><code>Update local service URLs in
environment utils</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-38801f053432e037993a6c8359ff512d7a6cfa9579597b92449f12c05c9c14e9">+11/-8</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>SignIn.tsx</strong><dd><code>Update local Mailhog
URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-0a87ee2c1dd8b5251f9b633fec0796102216844f7839e9182309fabe5c86dafe">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>config.ts</strong><dd><code>Update local Mailhog and Auth
URLs</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-2fb71947fac3f4de3e100b1e28b8c4a7141cdac93155b6635a19eb414eb62e8d">+2/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>helpers.ts</strong><dd><code>Update local Auth
URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-4aa73c18d80efc7dbe2fe5c76039c0df6d155f6e43835a4aecbd08cd1186dd77">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>config.ts</strong><dd><code>Update local Auth
URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-ee105dd14f110b5642103092f69d3310bb652bfb12e68b1588c62a270fd3f603">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>helpers.ts</strong><dd><code>Update local Storage
URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-f50172c9dba0fa2de72135ff70ff1d96f8a524f1388a9429182d3e8809909d3f">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>helpers.ts</strong><dd><code>Update URL generation for local
services</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-772264ae234cf88eeab12134a272a425ac41273afc392a07316fb26d7c573023">+2/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>utils.test.ts</strong><dd><code>Update local service URLs in
tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-940f24899a0f0f423f25dc4f3809920f2cfbdf3211f892f16011d964ac4ac319">+5/-5</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>seed-storage.sh</strong><dd><code>Update local Storage URL
in seed script</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-211c009c503a489da990b07865b1ad981ddcaae38b96fbb327e832d66eab63b9">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>test-nhost-cli-action.yaml</strong><dd><code>Update local
service URLs in CLI action tests</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-defe9dba19ff27b93c6b21e6308904b606b75cad29218bf849d29f7a8506a30e">+2/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>graphite.graphql.config.yaml</strong><dd><code>Update local
GraphQL URL in config</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-74a8fb68417df04d2af42e94ab298fd54e22d42676b50572b16a2293446f0988">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

</table></details></td></tr><tr><td><strong>Enhancement</strong></td><td><details><summary>2
files</summary><table>
<tr>
<td><strong>sign-in-apple.ts</strong><dd><code>Remove redirectTo option
from Apple sign-in</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-1b6954885dd5b8b4406ed46dfd8102b5cc92175f093cd3c0ebe26477e1346d42">+1/-4</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>sign-in-google.ts</strong><dd><code>Remove redirectTo option
from Google sign-in</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-a155d7f9e27b15453c109c16e2d1c76d3632b28bfafcdaa4180caf40f50102d9">+1/-4</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

</table></details></td></tr><tr><td><strong>Documentation</strong></td><td><details><summary>21
files</summary><table>
<tr>
<td><strong>hip-falcons-applaud.md</strong><dd><code>Add changeset for
URL generation update</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-a41c3544b060502eb895d87553a84ecf238b60567347dafb4168d64fe119e385">+12/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>.env.example</strong><dd><code>Update local service URLs in
example env file</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-b47cf46119af2f0298d96e5657e53e57161833e8b02d87526ac5c1ed9393d477">+8/-8</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>README.md</strong><dd><code>Update local service URLs in
README</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-c15729e6c35a283a4b0eda60a991303b6c36c03903ba42dbf832bb8d0daa1a1a">+7/-7</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>commands.mdx</strong><dd><code>Update local service URLs in
CLI documentation</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-2053eb5138f4c468b9aa94e6fd7302ad2f577839be107741f265ae1b2d9bfcaa">+17/-21</a>&nbsp;
</td>

</tr>

<tr>
<td><strong>getting-started.mdx</strong><dd><code>Update local service
URLs in CLI documentation</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-05cc8d760dce63f257bee91e9c0293424a63e0ed210d26c7bca78bc3a3d5d763">+8/-8</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>overview.mdx</strong><dd><code>Update local service URLs in
CLI overview</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-dfcca51e047037e649bbf76e68ab3aa9161a85c1bd25cf385acc5e764bea0cd3">+9/-9</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>assistants.mdx</strong><dd><code>Update local Functions URL
in AI assistants guide</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-3fe162cc8ef81dc6517dcd3e7a5531ed695df9fc300595d6b923677a2de7af99">+85/-116</a></td>

</tr>

<tr>
<td><strong>custom-jwts.mdx</strong><dd><code>Update local Functions URL
in custom JWTs guide</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-3e3f4be3ef4e3ddc1f5dbf30b76be0aa275309755cfbcc1afa865a13b433522c">+2/-5</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>local-development.mdx</strong><dd><code>Update local service
URLs in CLI guide</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-00fc275afa2ec0920232682aec7a0f553457675b09fede84fff1cf33fd928422">+14/-16</a>&nbsp;
</td>

</tr>

<tr>
<td><strong>migrate-config.mdx</strong><dd><code>Update local service
URLs in migration guide</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-d85182dc59541186f337991dcbc95179140091cd62bc64acf484f7e9c74dd247">+7/-8</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>multiple-projects.mdx</strong><dd><code>Update local service
URLs in multiple projects guide</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-842182f7c0367b8667570df1f6903fb09b6e9ee5062feac58733dbb238e9c252">+7/-9</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>seeds.mdx</strong><dd><code>Update local Hasura URL in seeds
guide</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-3d5c1396d5c9c028ffa0c8493cb64f0dc06223e651665c173fdb6df30c7f5cb0">+12/-5</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>local-development.mdx</strong><dd><code>Update local GraphQL
URL in run guide</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-9ddcc07c6add2efbb2630dfa5b718656444e9c566e84d38f577eb6a026f4d870">+21/-7</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>overview.mdx</strong><dd><code>Update local Storage URL in
storage overview</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-c2641bf1319034c16ea03895511bac4dcabd62660fe49f713371529041495c5e">+7/-6</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>diagrams.txt</strong><dd><code>Update local Functions and
GraphQL URLs in diagrams</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-b0815782a1cb44a8e50e0616704b74f4e2b4785b4358ce705872f94bf635b573">+2/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>openapi-auth-old.yaml</strong><dd><code>Update local Auth
URL in OpenAPI spec</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-bc23e66a45c276e58845db366df3759415034d4e045b655953a3c557b9c0f09f">+57/-63</a>&nbsp;
</td>

</tr>

<tr>
<td><strong>openapi-storage.yaml</strong><dd><code>Update local Storage
URL in OpenAPI spec</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-81afd91a70cb5516a39e6900392de5136771981bec072a97e5f48975bbf6afd3">+8/-8</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>upload-file.mdx</strong><dd><code>Update local Storage URL
in file upload reference</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-d0a3eae50a19e63cf2d66ab4f644104fa20a946b24122254ec4a368f847292d1">+8/-10</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>README.md</strong><dd><code>Update README with new local
dashboard URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-411e8e55ab182bb59f03f2a8e1539b08afbc0f42796f73f5bfcb0c47a015c5c4">+24/-2</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>README.md</strong><dd><code>Update local Storage URLs in
seed data example</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-d2af072cf65c3cc8f02d82d7346a492ddb81a768948ccf02ccb2e8ec1800029c">+2/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>README.md</strong><dd><code>Update local Functions URLs in
Google Translation README</code>&nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-b3790312c229004898229cf8ee576c443fce25ef8fdfe6079e1242db932e9d94">+2/-2</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></details></td></tr><tr><td><strong>Configuration
changes</strong></td><td><details><summary>1 files</summary><table>
<tr>
<td><strong>nhost.toml</strong><dd><code>Update OAuth and WebAuthn
configurations</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3197/files#diff-eff7b73b949a7fd005b4c51ae54a7757b8447c831168c0d014b6034adc7539bb">+2/-4</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></details></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-17 11:11:21 +01:00
David BM
a21553c774 chore: update links in README (#3199)
### **PR Type**
Documentation


___

### **Description**
- Updated links in README to reflect new documentation structure

- Revised quickstart and CLI documentation URLs

- Updated links for framework-specific quickstart guides

- Refreshed 'Try out Nhost' link in contribution section


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Documentation</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>README.md</strong><dd><code>Update documentation and
quickstart guide links</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

README.md

<li>Updated quickstart link to new documentation structure<br> <li>
Revised CLI documentation link<br> <li> Updated links for Next.js,
React, and Vue.js quickstart guides<br> <li> Refreshed 'Try out Nhost'
link in contribution section


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3199/files#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5">+6/-6</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-14 16:47:30 +01:00
github-actions[bot]
2dd4df5170 chore: update versions (#3191)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @nhost/dashboard@2.20.0

# @nhost/dashboard

## 2.17.0

### Minor Changes

-   fd59918: fix: redirect to 404 with nhost cli dashboard

## 2.16.0

### Minor Changes

-   f8e6b61: fix: can add rule groups in table permissions
-   9e404c8: fix: not redirect to 404 page if using local Nhost backend
-   ac4aa01: fix: can delete column in database page
-   4385524: fix: update url to check service health in local dashboard

### Patch Changes

-   @nhost/react-apollo@16.0.1
-   @nhost/nextjs@2.2.2

## 2.15.0

### Minor Changes

- f1052a8: fix: improve stability of the dashboard when pausing projects
-   30daa41: fix: update links to docs in overview page
-   7537237: feat: add image preview toggle in storage

## 2.14.0

### Minor Changes

- d43931e: fix: invalid organization slug/project subdomain doesn't open
404 page
- 5df6fa2: feat: add unencrypted disk warning in storage capacity
settings

### Patch Changes

-   44c1e17: chore: update `msw` to v1.3.5 to fix vulnerabilities
    -   @nhost/react-apollo@16.0.0
    -   @nhost/nextjs@2.2.1

## 2.13.0

### Minor Changes

- 21e90da: chore: remove restrictions on SMTP sender so My Name
[name@acme.com](mailto:name@acme.com) can be added
- 865dd93: fix: duplicate Run placeholders when there is an error in the
backend
- 6902a36: fix: can remove resources if postgres capacity is higher than
10
-   a535aa3: fix: fetch user roles locally in auth section
-   0c50816: fix: allow decimal numbers in database row insert
- aea6d18: chore: add warning when pausing a project about losing Run
services persistent volume data
- d3b4fc3: feat: allow to change postgres settings if project is paused
-   29d27e1: chore: update `next` to v14.2.22 to fix vulnerabilities
-   c9dca09: feat: add reset password form
-   b3bcacb: fix: paused project banner cannot read null project name

### Patch Changes

-   Updated dependencies [46fc520]
-   Updated dependencies [29d27e1]
    -   @nhost/nextjs@2.2.0
    -   @nhost/react-apollo@15.0.1

## 2.12.0

### Minor Changes

- eb95562: fix: show all available permission variables in permission
dropdown select

### Patch Changes

- 8b5c4a0: chore: cleanup layout and add disable duplicate atom key
checking in development mode

## 2.11.3

### Patch Changes

- 714dffa: fix: improve project polling logic and unify usage across
components

## 2.11.2

### Patch Changes

- 6a34f89: fix: improve project polling logic and unify usage across
components

## 2.11.1

### Patch Changes

-   0f6ce52: fix: consolidate useProject hook and fix jwt expired error

## 2.11.0

### Minor Changes

-   cea3ef5: Feat: add org and project placeholders

## 2.10.0

### Minor Changes

-   86ecf27: feat: add support for additional metrics in overview
- 21708be: feat: dashboard: add support for storage buckets to AI
assistants

## 1.30.0

### Minor Changes

- 50441a8: feat: add ui for project autoscaler settings and run services
autoscaler settings

## 1.29.0

### Minor Changes

-   55d8bb5: feat: integrate turnstile for signup verification
-   2a2e54c: fix: update docs url in run services form tooltip
- 18f942f: fix: display long error messages in error toast without
overflow

### Patch Changes

-   @nhost/react-apollo@13.0.0
-   @nhost/nextjs@2.1.22

## 1.28.2

### Patch Changes

- 52a38fe: chore: update dependencies to address security
vulnerabilities
-   Updated dependencies [52a38fe]
    -   @nhost/nextjs@2.1.21

## 1.28.1

### Patch Changes

-   9735fa2: chore: remove broken link

## 1.28.0

### Minor Changes

- 526183a: feat: allow filtering users in "make request as" in graphql
section
-   be3b85b: feat: add conceal errors toggle on auth settings page

### Patch Changes

- 35a2f12: fix: prevent run service details from opening when attempting
to delete
    -   @nhost/react-apollo@12.0.6
    -   @nhost/nextjs@2.1.20

## 1.27.0

### Minor Changes

-   a7cd02c: fix: resolve rate limit query

## 1.26.0

### Minor Changes

-   3773ad7: chore: update pricing information
- b63250d: fix: not allow run service creation form resubmission while
creating a run service
-   a44a1d4: feat: add rate limits settings page

### Patch Changes

-   @nhost/react-apollo@12.0.5
-   @nhost/nextjs@2.1.19

## 1.25.0

### Minor Changes

- d1ceede: feat: add setting to migrate postgres major and/or minor
versions
- e5d3d1a: fix: allow manually typing column for custom check in
database row permissions

### Patch Changes

-   @nhost/react-apollo@12.0.4
-   @nhost/nextjs@2.1.18

## 1.24.1

### Patch Changes

- 49f2e55: fix: use service subdomain in service form and service
details dialog
- 598b988: fix: use current project subdomain in ServiceDetailsDialog
component

## 1.24.0

### Minor Changes

-   abb24af: chore: add redirect to support page when project is locked
- 18a6455: feat: show contact us info and locked reason when project is
locked

### Patch Changes

-   e31eefa: fix: include ingresses field when updating run services

## 1.23.0

### Minor Changes

-   33284d3: fix: don't show double scrollbar in configuration editor

### Patch Changes

-   @nhost/react-apollo@12.0.3
-   @nhost/nextjs@2.1.17

## 1.22.0

### Minor Changes

-   998c037: fix: align drop-down list in select component
- 807b8c0: fix: show city name in region selection for project creation

## 1.21.0

### Minor Changes

- a2efeed: fix: improve project health error handling, add unknown state
and polling interval for health state

## 1.20.0

### Minor Changes

- 8ea4210: fix: error toasts can be closed individually, instead of
dismissing all toasts at once
- 58919ba: chore: add blink animation when project health service is
updating

## 1.19.0

### Minor Changes

- b519862: fix: get configuration in configuration editor using local
development environment

## 1.18.0

### Minor Changes

- 502abad: feat: add services health checks indicators to the overview
page
-   b3ff6ad: chore: update title text on service status modal
- dbadf59: feat: add project configuration TOML editor to the settings
page

## 1.17.0

### Minor Changes

- 77fba27: fix: postgres version validation when activating ai in ai
settings page
-   ac6d1b6: feat: use name instead of awsName

## 1.16.3

### Patch Changes

- 87a37cf: fix: remove unnecessary isPlatform check from verify button
disable logic on custom domains
    -   @nhost/react-apollo@12.0.2
    -   @nhost/nextjs@2.1.16

## 1.16.2

### Patch Changes

- a9413af: fix: update `GetAllWorkspacesAndProjects` query polling to
use exponential backoff
    -   @nhost/react-apollo@12.0.1
    -   @nhost/nextjs@2.1.15

## 1.16.1

### Patch Changes

-   @nhost/react-apollo@12.0.0
-   @nhost/nextjs@2.1.14

## 1.16.0

### Minor Changes

- c6d5c5c: feat: add toggle switch to enable/disable public access in
the database settings

## 1.15.2

### Patch Changes

-   @nhost/react-apollo@11.0.4
-   @nhost/nextjs@2.1.13

## 1.15.1

### Patch Changes

-   @nhost/react-apollo@11.0.3
-   @nhost/nextjs@2.1.12

## 1.15.0

### Minor Changes

-   a7bde37: feat: send metadata in the edit form

### Patch Changes

- 1bc615b: feat: improve error message handling in `ErrorToast`
component
    -   @nhost/react-apollo@11.0.2
    -   @nhost/nextjs@2.1.11

## 1.14.0

### Minor Changes

-   a448d7d: feat: allow configuring postmark and delete SMTP settings

## 1.13.3

### Patch Changes

-   5924bc3: fix: include password in `GetSmtpSettings` query
- c5ad634: fix: resolved an issue where one-click install links were
broken on Safari
- 7278991: fix: update graphql auto-embeddings configuration to use
String type for model field

## 1.13.2

### Patch Changes

-   026f84f: fix: use configuration server URL from environment variable

## 1.13.1

### Patch Changes

-   7e9a2ce: fix: resolve issue where run services form fails to open

## 1.13.0

### Minor Changes

-   dd5d262: feat: add model field to the auto-embeddings form
- 09962be: feat: enable settings and run services when running the
dashboard locally
- 9cdecb6: feat: enable users to update their email address from the
account settings page

## 1.12.2

### Patch Changes

-   c195c51: fix: send email upon signin for unverified users

## 1.12.1

### Patch Changes

- 93ebdf8: fix: use service urls when initilizaing NhostClient running
local dashboard
    -   @nhost/react-apollo@11.0.1
    -   @nhost/nextjs@2.1.10

## 1.12.0

### Minor Changes

- f242e4b: feat: add connect with github to the user's account settings
-   768ca17: chore: update dependencies
- d62bd0f: fix: "Track this" option within the SQL editor now correctly
updates the metadata
- 91c2bb6: feat: refactor sign-in and sign-up pages to enforce email
verification

### Patch Changes

-   943831f: fix: resolve an error toast issue when unpausing a project
-   Updated dependencies [768ca17]
    -   @nhost/react-apollo@11.0.0
    -   @nhost/nextjs@2.1.9

## 1.11.2

### Patch Changes

-   @nhost/react-apollo@10.0.2
-   @nhost/nextjs@2.1.8

## 1.11.1

### Patch Changes

-   981404f: fix: set default value for healthCheck field validation

## 1.11.0

### Minor Changes

- 7789469: chore: upgrade dependency `@graphql-codegen/cli` to `5.0.2`
to address vulnerability
- 6c11b75: feat: add update user displayName section in account settings

### Patch Changes

-   @nhost/react-apollo@10.0.1
-   @nhost/nextjs@2.1.7

## 1.10.0

### Minor Changes

-   49a80c2: chore: update dependencies
-   150c04a: feat: add healthcheck config to run services

### Patch Changes

- e03f141: fix: allow insert, update and delete on tables in `auth` and
`storage` schemas
- 28676f4: feat: add min postgres version check to enable the ai service
-   Updated dependencies [49a80c2]
    -   @nhost/react-apollo@10.0.0
    -   @nhost/nextjs@2.1.6

## 1.9.0

### Minor Changes

-   d86e5c9: feat: add support for filtering the logs using a RegExp

## 1.8.3

### Patch Changes

-   @nhost/react-apollo@9.0.3
-   @nhost/nextjs@2.1.5

## 1.8.2

### Patch Changes

- 6df4f02: fix: use custom error toast and show correct message when
sending an invite

## 1.8.1

### Patch Changes

-   @nhost/react-apollo@9.0.2
-   @nhost/nextjs@2.1.4

## 1.8.0

### Minor Changes

- 713d53c: feat: add catch-all route for workspace/project - useful for
documentation

### Patch Changes

-   3db2999: fix: refresh table list after running SQL using the editor
- 3c4dd55: fix: handle `Error` objects properly in the `ErrorToast`
component
- 92b434e: fix: resolve an issue where the checkbox in the data-grid
header did not select all rows
    -   @nhost/react-apollo@9.0.1
    -   @nhost/nextjs@2.1.3

## 1.7.0

### Minor Changes

-   0d8d0eb: Update docs and dashboard references

## 1.6.9

### Patch Changes

-   @nhost/react-apollo@9.0.0
-   @nhost/nextjs@2.1.2

## 1.6.8

### Patch Changes

-   @nhost/react-apollo@8.0.1
-   @nhost/nextjs@2.1.1

## 1.6.7

### Patch Changes

-   5ef5189: fix: update `@apollo/client` to `3.9.4` to fix a cache bug

## 1.6.6

### Patch Changes

-   3ba485e: fix: added discord.com to connect-src
-   e5bab6a: chore: update dependencies
-   Updated dependencies [b19ffed]
-   Updated dependencies [e5bab6a]
    -   @nhost/nextjs@2.1.0
    -   @nhost/react-apollo@8.0.0

## 1.6.5

### Patch Changes

- ba73bb4: fix: update ErrorToast component to show the internal graphql
error
- d5337ff: fix: utilize accumulator in the creation of validation schema
within data grid utils

## 1.6.4

### Patch Changes

-   7c2a1c2: feat: show error and debug info in the error toast

## 1.6.3

### Patch Changes

-   6b8aad5: fix: add bare nhost.run to CSP

## 1.6.2

### Patch Changes

-   b18edc0: feat: added CSP and X-Frame-Options

## 1.6.1

### Patch Changes

-   8d91f71: chore: update deps and enable pnpm audit
- 3b8473b: chore: update turbo to `1.11.3` and pnpm to `8.10.5` in
Dockerfile
-   Updated dependencies [8d91f71]
    -   @nhost/react-apollo@7.0.2
    -   @nhost/nextjs@2.0.2

## 1.6.0

### Minor Changes

-   3ff1c2b53: fix: show upgrade option for pro projects

## 1.5.0

### Minor Changes

-   c2ef17c0a: feat: add support for new Team plan

## 1.4.0

### Minor Changes

-   7883bbcbd: feat: don't show deprecated plans
- 44be6dc0a: feat: set redirectTo during sign-in to support preview
environments

### Patch Changes

- 3c3594898: fix: allow access to graphite when configured running in
local dashboard
-   32c246b7a: chore: update docs icon

## 1.3.2

### Patch Changes

-   174b4165b: chore: use env variables when running graphql codegen
-   7c977e714: chore: change `Allowed Roles` to `Default Allowed Roles`
-   46f028b9f: fix: remove hardcoded ai version setting

## 1.3.1

### Patch Changes

- af33c21d1: chore: remove backendUrl deprecation notice and remove all
references to `providersUpdated`

## 1.3.0

### Minor Changes

-   04784d880: Fix graphite's default version

## 1.2.0

### Minor Changes

-   5733162ed: feat: add settings and ui for graphite

## 1.1.0

### Minor Changes

-   e2b79b5ec: chore: remove sharp from deps

## 1.0.1

### Patch Changes

-   @nhost/react-apollo@7.0.1
-   @nhost/nextjs@2.0.1

## 1.0.0

### Major Changes

- bc9eff6e4: chore: remove support for using backendUrl when
instantiating the Nhost client

### Patch Changes

-   Updated dependencies [bc9eff6e4]
    -   @nhost/nextjs@2.0.0
    -   @nhost/react-apollo@7.0.0

## 0.21.1

### Patch Changes

-   97ced73a3: fix(dashboard): prevent dashboard from resolving secrets

## 0.21.0

### Minor Changes

- ed1a8d458: Update alert message on increasing PostgreSQL's volume
capacity
-   2e2248fd4: feat(dashboard): add SQL editor

## 0.20.28

### Patch Changes

-   7c2c31082: feat: add support for users to delete their account
    -   @nhost/react-apollo@6.0.1
    -   @nhost/nextjs@1.13.40

## 0.20.27

### Patch Changes

- fa79b7709: chore(dashboard): tweaks and fixes to the service form and
dialog
-   8df84d782: fix(dashboard): allow resetting custom domains
    -   @nhost/react-apollo@6.0.0
    -   @nhost/nextjs@1.13.39

## 0.20.26

### Patch Changes

- 331ba0376: feat(dashboard): add postgres storage capacity modifier in
the settings
-   b7f801874: feat(dashboard): add new settings page for custom domains

## 0.20.25

### Patch Changes

-   @nhost/react-apollo@5.0.38

## 0.20.24

### Patch Changes

-   e10389ecf: fix(dashboard): disable run tab when developing locally
    -   @nhost/react-apollo@5.0.37

## 0.20.23

### Patch Changes

-   c01568a7d: chore(dashboard): show alert to update oauth providers

## 0.20.22

### Patch Changes

-   c3efb7ec8: feat(dashboard): query latest announcement from platform

## 0.20.21

### Patch Changes

-   3e46d3873: chore: update link to node18 announcement

## 0.20.20

### Patch Changes

-   @nhost/react-apollo@5.0.36
-   @nhost/nextjs@1.13.38

## 0.20.19

### Patch Changes

-   75c4c8ae3: feat(dashboard): make env value input multiline

## 0.20.18

### Patch Changes

- 425d485f8: fix(dashboard): make sure dedicated resources pricing
follows total resources

## 0.20.17

### Patch Changes

-   ae324f67f: fix(dashboard): remove unused graphql fields

## 0.20.16

### Patch Changes

-   df5b4302c: chore(dashboard): remove run feature flag
- bf4a1f6c2: feat(dashboard): fetch auth, postgres, hasura and storage
versions from dashboard
- 34fc08ca7: fix(dashboard/run): show correct private registry in
service details
-   885d10620: chore(dashboard): change feedback to contact us

## 0.20.15

### Patch Changes

- ed16c8b5d: feat(run): add a confirmation dialog when deleting a run
service
- 216990888: fix(run): center loading indicator when selecting a project

## 0.20.14

### Patch Changes

-   9fbea9787: feat: add node18 announcement

## 0.20.13

### Patch Changes

- e84acf469: fix(run): handle subdomain undefined error when creating a
new service

## 0.20.12

### Patch Changes

-   b7c799d62: feat(run): add dialog to copy registry and URLs

## 0.20.11

### Patch Changes

-   8903e6abd: fix(dashboard): show correct egress limit in usage stats

## 0.20.10

### Patch Changes

- 666a75a23: feat(dashboard): add functions execution time and egress
volume to usage stats

## 0.20.9

### Patch Changes

-   5e1e80aa8: fix(dashboard): show correct locales in user details
    -   @nhost/react-apollo@5.0.35
    -   @nhost/nextjs@1.13.37

## 0.20.8

### Patch Changes

-   @nhost/react-apollo@5.0.34
-   @nhost/nextjs@1.13.36

## 0.20.7

### Patch Changes

-   4a7ede11e: fix: distinguish files that were not uploaded
- 202b64723: feat(nhost-run): add support for one-click-install run
services
- 074a0fa11: feat(dashboard): add settings toggle to enable/disable
antivirus
    -   @nhost/react-apollo@5.0.33
    -   @nhost/nextjs@1.13.35

## 0.20.6

### Patch Changes

-   b20761e97: feat(services): add pricing info and confirmation dialog
-   90df6d81d: fix(services): handle null values when editing a service
-   aa8508467: fix: query service logs correctly
    feat: enable multiline support for environment value input

## 0.20.5

### Patch Changes

-   8d7f84b8d: fix: make announcement adapt to theme

## 0.20.4

### Patch Changes

-   3b75bfce2: fix: make announcement close properly
- f49819075: fix: show correct values when dedicated resources are
disabled

## 0.20.3

### Patch Changes

-   e643bd362: fix(services): fix errors when config is null
-   bcdab66bf: feat: add annoucement for nhost run
-   f967a2e59: added note about storage not being able to be downsized
-   311c7756d: chore(services): consistent naming for compute

## 0.20.2

### Patch Changes

-   9073182d5: chore(dashboard): bump `turbo` to 1.10.11
-   ece717d6e: feat(logs): show services in the logs page
- 82b335311: feat(metrics): change grafana link to point to the
dashboards
- b135ef695: fix(services): set command as optional and set min replicas
to 0

## 0.20.1

### Patch Changes

-   3d5c34f4c: fix(auth): fix users pagination limit

## 0.20.0

### Minor Changes

-   c99d117d1: feat(services): add support for custom services

## 0.19.2

### Patch Changes

-   face99ccd: chore(deps): bump turbo version
-   cfe527307: style: tweak pull config warning in dark mode
- a9d7da8af: chore(deps): update dependency @types/pluralize to ^0.0.30
-   9aa4371ef: chore: add hasura-auth version 0.21.2
- d14e112bf: chore(deps): update dependency prettier-plugin-tailwindcss
to ^0.4.0
-   d3e8bb94a: chore(deps): update dependency vite-plugin-dts to v3

## 0.19.1

### Patch Changes

-   @nhost/react-apollo@5.0.32
-   @nhost/nextjs@1.13.34

## 0.19.0

### Minor Changes

- 9c61c69a7: chore(dashboard):add postgres 14.6-20230705-1 to the
version selector

### Patch Changes

-   47bda15ff: feat(settings): add warning to pull config

## 0.18.0

### Minor Changes

- ee0b9b8ed: chore(dashboard):add hasura v2.28.2 and v2.29.0 to the
version selector

## 0.17.20

### Patch Changes

-   @nhost/react-apollo@5.0.31
-   @nhost/nextjs@1.13.33

## 0.17.19

### Patch Changes

-   f866120a6: fix(users): use the password length from the config

## 0.17.18

### Patch Changes

-   @nhost/react-apollo@5.0.30
-   @nhost/nextjs@1.13.32

## 0.17.17

### Patch Changes

-   ea7b102c0: fix(pat): highlight expired tokens

## 0.17.16

### Patch Changes

- b3b64a3b7: chore(deps): bump `@types/react` to `v18.2.14` and
`@types/react-dom` to `v18.2.6`
-   32b221f94: chore(deps): bump `graphiql` to `v3`
-   3a56c12df: chore(deps): bump `turbo` to `v1.10.6`
-   Updated dependencies [b3b64a3b7]
    -   @nhost/react-apollo@5.0.29
    -   @nhost/nextjs@1.13.31

## 0.17.15

### Patch Changes

-   f41fdc12a: chore(deps): bump `turbo` to `1.10.5`
-   6199c1c55: fix(projects): don't redirect to 404 page
-   Updated dependencies [07a45fde0]
    -   @nhost/react-apollo@5.0.28
    -   @nhost/nextjs@1.13.30

## 0.17.14

### Patch Changes

- 80b22724d: chore(deps): bump `@types/react` to `v18.2.13`,
`@types/react-dom` to `v18.2.6` and `@storybook/testing-library` to
`v0.2.0`

## 0.17.13

### Patch Changes

-   cc02902cb: chore(docs): update environment variable documentation

## 0.17.12

### Patch Changes

-   660d339e1: fix(storybook): don't break storybook
-   660d339e1: fix(tests): prevent warnings during tests
    -   @nhost/react-apollo@5.0.27
    -   @nhost/nextjs@1.13.29

## 0.17.11

### Patch Changes

- bd4d0c270: chore(dashboard):add postgres 14.6-20230613-1 to the
version selector

## 0.17.10

### Patch Changes

-   c8c2a10b2: fix(database): don't break the password reset flow
- e70b45498: chore(deps): bump `@types/react` to `v18.2.12` and
`@types/react-dom` to `v18.2.5`

## 0.17.9

### Patch Changes

- 842055099: chore(deps): bump `turbo` to `v1.10.3` and `pnpm` to
`v8.6.2`
- fd12aa0a8: chore(projects): remove the postgres password input from
the project creation screen
-   022b76e78: chore(deps): bump `@types/react` to `v18.2.11`
-   3555ab2b7: chore(deps): bump `vitest` monorepo to `v0.32.0`
-   c43e54922: feat(backups): add download button to backups

## 0.17.8

### Patch Changes

-   d0457fe5c: feat(settings): improve the dashboard and config parity
    -   @nhost/react-apollo@5.0.26
    -   @nhost/nextjs@1.13.28

## 0.17.7

### Patch Changes

-   4f0368b95: fix(account): don't break account settings page

## 0.17.6

### Patch Changes

- 64a8f41d0: chore(resources): lower the maximum allowed resources per
service

## 0.17.5

### Patch Changes

-   @nhost/react-apollo@5.0.25
-   @nhost/nextjs@1.13.27

## 0.17.4

### Patch Changes

- 9b1d0f7a5: fix(deployments): use correct timestamp for deployment
details
-   6d2963ffa: chore(deps): bump `@types/react` to `v18.2.8`
- 8871267b9: chore(deps): downgrade `pnpm` to `v8.5.1` because of no
Turborepo support

## 0.17.3

### Patch Changes

-   01eeef9de: chore(misc): under the hood improvements
- 21e13db05: chore(deps): bump `@types/react` to `v18.2.7` and `turbo`
to `v1.10.1`
- f16433ae6: chore(secrets): allow empty secrets and environment
variables
-   aa3c62989: chore(cli): bump Nhost CLI version to v1.0
    -   @nhost/react-apollo@5.0.24
    -   @nhost/nextjs@1.13.26

## 0.17.2

### Patch Changes

-   88a4983f: chore(misc): under the hood improvements

## 0.17.1

### Patch Changes

-   9b0d4dde: feat(secrets): enable secrets

## 0.17.0

### Minor Changes

-   15d84a19: Add postgres 14.6-20230525

## 0.16.14

### Patch Changes

-   4c626174: chore: updated import paths, improved directory structure
-   cc047b71: chore(deps): bump `@fontsource` monorepo to `v5.0.0`
-   99edd012: feat(account): add support for personal access tokens

## 0.16.13

### Patch Changes

-   78c7109c: feat(settings): allow selecting service versions

## 0.16.12

### Patch Changes

- 399009d6: fix(gql): don't enter an infinite loop when fetching remote
app data
- 329e5a91: fix(deployments): use the same sorting of deployments
everywhere
- 6d559d6e: chore(settings): add under the hood improvements to the
settings page
- 12eb236c: chore(deps): bump `prettier-plugin-tailwindcss` to `v0.3.0`
-   f9b81a2a: chore(deps): bump `turbo` to `v1.9.8`
-   1345741b: fix(projects): don't redirect to 404 on project creation
-   Updated dependencies [7fea29a8]
    -   @nhost/react-apollo@5.0.23
    -   @nhost/nextjs@1.13.25

## 0.16.11

### Patch Changes

- 1230b722: fix(projects): don't redirect to 404 on when the project is
renamed
    -   @nhost/react-apollo@5.0.22
    -   @nhost/nextjs@1.13.24

## 0.16.10

### Patch Changes

-   Updated dependencies [da03bf39]
    -   @nhost/react-apollo@5.0.21
    -   @nhost/nextjs@1.13.23

## 0.16.9

### Patch Changes

- 349aac36: fix(settings): use region domain when constructing the
postgres connection string

## 0.16.8

### Patch Changes

- 20fb69fa: chore(projects): change the way how API URLs are constructed

## 0.16.7

### Patch Changes

- 49f9b837: chore(docker): bump `pnpm` to `v8.4.0` and `turbo` to
`v1.9.3`
- 3f478a4e: chore(deps): bump `vitest` to `v0.31.0`, `@types/react` to
`v18.2.6` and `@types/react-dom` to `v18.2.4`

## 0.16.6

### Patch Changes

- d926f156: fix(projects): redirect to 404 when an invalid project is
opened
- 49b99728: fix(projects): disable features for non-owner members of
workspaces

## 0.16.5

### Patch Changes

-   12e2855f: chore(deps): bump `jsdom` to v22
-   e4972b83: feat(metrics): add Grafana page

## 0.16.4

### Patch Changes

- 3f396a9e: fix(projects): unpause after upgrading a paused project to
pro
- 3f396a9e: fix(projects): don't redirect to 404 page after project
creation

## 0.16.3

### Patch Changes

-   Updated dependencies [90c60311]
    -   @nhost/react-apollo@5.0.20
    -   @nhost/nextjs@1.13.22

## 0.16.2

### Patch Changes

-   0f34f0c6: fix(projects): disallow downgrading to free plan
- 8da291ad: chore(deps): bump `@types/react` to v18.2.0 and
`@types/react-dom` to v18.2.1

## 0.16.1

### Patch Changes

- adc828a5: fix(gql): don't enter an infinite loop when fetching remote
app data

## 0.16.0

### Minor Changes

-   2fb1145f: feat(compute): add support for replicas

### Patch Changes

- d8ceccec: chore(env): remove deprecated `NHOST_BACKEND_URL`
environment variable

## 0.15.2

### Patch Changes

-   84b84ab7: fix(projects): filter projects by workspace

## 0.15.1

### Patch Changes

-   2faf7907: chore(deps): bump `graphql-request` to v6
-   f1b5a944: chore(deps): bump `@vitejs/plugin-react` to v4
-   7f1785ac: chore(deps): bump `@types/react` to v18.0.37
    -   @nhost/react-apollo@5.0.19

## 0.15.0

### Minor Changes

-   85889ee8: feat(dashboard): add Compute management to the settings

## 0.14.8

### Patch Changes

-   668c8771: chore(dialogs): unify dialog management of payment dialogs

## 0.14.7

### Patch Changes

-   d4ccc656: chore: cleanup unused code
    -   @nhost/react-apollo@5.0.18
    -   @nhost/nextjs@1.13.21

## 0.14.6

### Patch Changes

-   b299cfc9: chore(deps): bump `vitest` to v0.30.0
-   411cb65b: chore(projects): refactor workspace and project hooks
- 43b1b144: chore(deps): bump `@types/react` to v18.0.34 and
`@types/react-dom` to v18.0.11
-   Updated dependencies [43b1b144]
    -   @nhost/react-apollo@5.0.17
    -   @nhost/nextjs@1.13.20

## 0.14.5

### Patch Changes

-   ba0d57ee: fix(i18n): revert i18n library
-   3328ed05: feat(projects): improve overview when there is an error

## 0.14.4

### Patch Changes

-   5e0920ba: chore(deps): bump `next-seo` to v6
-   706c9dc3: chore(deps): bump `@types/react` to 18.0.33
-   99f8f6b3: feat(metrics): show metrics on the overview

## 0.14.3

### Patch Changes

-   @nhost/react-apollo@5.0.16

## 0.14.2

### Patch Changes

-   3cb67300: fix(logs): don't break UI when clearing time picker
-   7453bf3b: feat(projects): show project creator info
-   c166dad0: chore(tests): improve auth page tests
-   6a290bb2: chore(deps): bump `@types/react` to 18.0.32

## 0.14.1

### Patch Changes

-   @nhost/react-apollo@5.0.15
-   @nhost/nextjs@1.13.19

## 0.14.0

### Minor Changes

-   6e1f03ea: feat(dashboard): add support for the Azure AD provider

### Patch Changes

-   1bd2c373: chore(deps): bump `turbo` to 1.8.6
-   d329b621: chore(deps): bump `@types/react` to 18.0.30
-   cb248f0d: fix(tests): avoid name collision in database tests
-   867c8076: chore(deps): bump `@types/react` to 18.0.29

## 0.13.10

### Patch Changes

- e93b06ab: fix(dashboard): remove left margin from workspace list on
mobile
-   1c4806bf: chore(deps): bump `sharp` to 0.32.0
    -   @nhost/react-apollo@5.0.14
    -   @nhost/nextjs@1.13.18

## 0.13.9

### Patch Changes

-   912ed76c: chore(dashboard): bump `@apollo/client` to 3.7.10
-   Updated dependencies [912ed76c]
    -   @nhost/react-apollo@5.0.13

## 0.13.8

### Patch Changes

-   7c127372: chore(dashboard): bump `react-error-boundary` to v4

## 0.13.7

### Patch Changes

- 9130ab12: chore(dashboard): bump `yup` to v1 and `@hookform/resolvers`
to v3

## 0.13.6

### Patch Changes

- 253dd235: using new mutation to create projects + refactor Create
Project page.

## 0.13.5

### Patch Changes

-   @nhost/react-apollo@5.0.12
-   @nhost/nextjs@1.13.17

## 0.13.4

### Patch Changes

-   b48bc034: fix(dashboard): disable new users
-   798e591b: fix(dashboard): show correct date in data grid

## 0.13.3

### Patch Changes

-   bfb4c1a6: chore(dashboard): remove `useAxios` property
-   d8d8394b: Dashboard: allow to override hasura admin secret in docker
-   Updated dependencies [ce1ee40d]
    -   @nhost/nextjs@1.13.16
    -   @nhost/react-apollo@5.0.11

## 0.13.2

### Patch Changes

-   beed2eba: Fix docker entrypoint for dashboard
- 2c8559a3: fix(dashboard): refresh project list after deleting a
project
-   4329d048: chore(dashboard): bump `graphiql` dependencies

## 0.13.1

### Patch Changes

-   cbb1fc5b: chore(dashboard): cleanup GraphQL operations

## 0.13.0

### Minor Changes

-   088584e7: feat(dashboard): add support for custom local subdomains

### Patch Changes

-   2ac90dfd: fix(dashboard): improve mobile responsive layout
-   Updated dependencies [f375eacc]
    -   @nhost/nextjs@1.13.15
    -   @nhost/react-apollo@5.0.10

## 0.12.4

### Patch Changes

-   @nhost/react-apollo@5.0.9
-   @nhost/nextjs@1.13.14

## 0.12.3

### Patch Changes

-   2b1338f7: chore(dashboard): bump `turbo` to 1.8.3
- 5223ee93: fix(dashboard): show correct deployment status on the main
page
-   850a049c: chore(deps): update docker/build-push-action action to v4
-   Updated dependencies [850a049c]
    -   @nhost/nextjs@1.13.13
    -   @nhost/react-apollo@5.0.8

## 0.12.2

### Patch Changes

-   4bf40995: chore(deps): bump `typescript` to `4.9.5`
-   8bb097c9: chore(deps): bump `vitest`
- 35d52aab: chore(deps): replace `cross-fetch` with `isomorphic-unfetch`
-   Updated dependencies [4bf40995]
-   Updated dependencies [8bb097c9]
-   Updated dependencies [35d52aab]
    -   @nhost/react-apollo@5.0.7
    -   @nhost/nextjs@1.13.12

## 0.12.1

### Patch Changes

-   c96d7ccd: fix(dashboard): fix docker builds

## 0.12.0

### Minor Changes

-   d1671210: feat(dashboard): use mimir to manage project configuration

### Patch Changes

-   f65e4de9: chore(deps): bump @graphql-codegen monorepo to v3

## 0.11.20

### Patch Changes

-   4b4f0d01: chore(dashboard): improve dialog management

## 0.11.19

### Patch Changes

-   @nhost/react-apollo@5.0.6
-   @nhost/nextjs@1.13.11

## 0.11.18

### Patch Changes

-   01318860: fix(nhost-js): use correct URL for functions requests
-   Updated dependencies [01318860]
    -   @nhost/react-apollo@5.0.5
    -   @nhost/nextjs@1.13.10

## 0.11.17

### Patch Changes

-   f673adea: fix(dashboard): set correct Content-Type for user creation
-   445d8ef4: chore(deps): bump `@nhost/react-apollo` to 5.0.4
-   445d8ef4: chore(deps): bump `@nhost/nextjs` to 1.13.9
- 0368663d: fix(dashboard): allow permission editing for auth and
storage schemas
-   Updated dependencies [445d8ef4]
-   Updated dependencies [445d8ef4]
    -   @nhost/react-apollo@5.0.4
    -   @nhost/nextjs@1.13.9

## 0.11.16

### Patch Changes

-   b755e908: fix(dashboard): use correct date for last seen
-   2d9145f9: chore(deps): revert GraphQL client
- 1ddf704c: fix(dashboard): don't show false positive message for failed
user creation
    -   @nhost/react-apollo@5.0.3
    -   @nhost/nextjs@1.13.8

## 0.11.15

### Patch Changes

-   @nhost/react-apollo@5.0.2
-   @nhost/nextjs@1.13.7

## 0.11.14

### Patch Changes

- 2cc18dcb: fix(dashboard): prevent permission editor dropdown from
being always open

## 0.11.13

### Patch Changes

- 3343a363: chore(dashboard): bump `@testing-library/react` to v14 and
`@testing-library/dom` to v9
    -   @nhost/react-apollo@5.0.1
    -   @nhost/nextjs@1.13.6

## 0.11.12

### Patch Changes

- 87eda76e: chore(dashboard): bump `@types/react` to v18.0.28 and
`@types/react-dom` to v18.0.11
-   6f0ac570: feat(dashboard): show dashboard version in account menu

## 0.11.11

### Patch Changes

-   bf1e4071: chore(dashboard): bump `react-is` version to `18.2.0`
-   Updated dependencies [bf1e4071]
-   Updated dependencies [5013213b]
    -   @nhost/nextjs@1.13.5
    -   @nhost/react-apollo@4.13.5

## 0.11.10

### Patch Changes

- a37a430b: fix(dashboard): don't break UI when deployments are
unavailable
    -   @nhost/react-apollo@4.13.4
    -   @nhost/nextjs@1.13.4

## 0.11.9

### Patch Changes

-   7b970e68: fix(dashboard): fix header link color

## 0.11.8

### Patch Changes

- f33242f2: feat(dashboard): add new sign up, sign in and reset password
pages

## 0.11.7

### Patch Changes

-   e9c8909c: fix(dashboard): use correct theme color in dark mode

## 0.11.6

### Patch Changes

-   902f486b: fix(dashboard): re-enable Hasura on logs page

## 0.11.5

### Patch Changes

-   1f9720fa: fix(dashboard): apply select permissions properly

## 0.11.4

### Patch Changes

-   deb14b51: fix(dashboard): don't break billing form

## 0.11.3

### Patch Changes

-   @nhost/react-apollo@4.13.3
-   @nhost/nextjs@1.13.3

## 0.11.2

### Patch Changes

-   f143e51d: chore(dashboard): pin Turborepo to 1.6.3

## 0.11.1

### Patch Changes

-   c2b5a41a: chore(dashboard): select system colors by default

## 0.11.0

### Minor Changes

-   1ebaf429: feat(dashboard): introduce Dark Mode 🌚

### Patch Changes

- 63b445c4: fixed duplicated logs bug and made to date count during live
mode

## 0.10.1

### Patch Changes

-   e146d32e: chore(deps): update dependency @types/react to v18.0.27
-   59347fcd: correct allowed role name
-   5b65cac9: updated authentication documentation
-   963f9b5e: feat(dashboard): include project info in feedback

## 0.10.0

### Minor Changes

-   ed4c7801: chore(dashboard): remove Functions section

## 0.9.10

### Patch Changes

-   4e2f8ccd: fix(dashboard): don't break Auth page in local mode

## 0.9.9

### Patch Changes

-   31abbe5f: fix(dashboard): enable toggle when settings are filled in

## 0.9.8

### Patch Changes

- 5bdd31ad: chore(dashboard): list fewer images per page on the Storage
page
- 5121851c: fix(dashboard): don't throw validation error for valid
permission rules

## 0.9.7

### Patch Changes

-   c126b20d: fix(dashboard): correct redeployment button

## 0.9.6

### Patch Changes

-   36c3519c: feat(dashboard): retrigger deployments

## 0.9.5

### Patch Changes

- 200e9f77: chore(deps): update dependency @types/react-dom to v18.0.10
-   Updated dependencies [200e9f77]
    -   @nhost/nextjs@1.13.2
    -   @nhost/react-apollo@4.13.2

## 0.9.4

### Patch Changes

- dbd3ded5: fix(dashboard): workspaces creation, new form, correct
redirects.

## 0.9.3

### Patch Changes

-   85f0f943: fix(dashboard): don't break the table creation process

## 0.9.2

### Patch Changes

-   Updated dependencies [d42c27ae]
-   Updated dependencies [927be4a2]
    -   @nhost/nextjs@1.13.1
    -   @nhost/react-apollo@4.13.1

## 0.9.1

### Patch Changes

-   d0f80811: fix(dashboard): don't show error when signing out the user

## 0.9.0

### Minor Changes

- d92891b2: feat(dashboard): add Permission Editor to the Database
section

### Patch Changes

-   3d379128: fix(dashboard): create new user
    -   @nhost/react-apollo@4.13.0
    -   @nhost/nextjs@1.13.0

## 0.8.1

### Patch Changes

-   7cadd944: fix(dashboard): display Twitter provider settings

## 0.8.0

### Minor Changes

-   9a1aa7bb: add functions to the log dashboard
-   f29abe62: feat(dashboard): Users Management v2

### Patch Changes

-   7766624b: feat(dashboard): add JWT secret editor modal
    -   @nhost/react-apollo@4.12.1
    -   @nhost/nextjs@1.12.1

## 0.7.13

### Patch Changes

-   dd0738d5: fix(dashboard): provisioning status polling

## 0.7.12

### Patch Changes

-   b21222b3: chore(deps): update dependency @types/node to v16
-   9e0486a3: fix(dashboard): close modals when navigating
-   Updated dependencies [b21222b3]
-   Updated dependencies [65687bee]
-   Updated dependencies [54df0df4]
    -   @nhost/nextjs@1.12.0
    -   @nhost/react-apollo@4.12.0

## 0.7.11

### Patch Changes

-   d6527122: fix(dashboard): use correct service URLs

## 0.7.10

### Patch Changes

-   Updated dependencies [57db5b83]
    -   @nhost/nextjs@1.11.0
    -   @nhost/nhost-js@1.7.0
    -   @nhost/react@0.17.0
    -   @nhost/react-apollo@4.11.0

## 0.7.9

### Patch Changes

- a6d31dc2: fix(dashboard): don't break the UI when project is not
loaded yet

## 0.7.8

### Patch Changes

- 7f251111: Use `NhostProvider` instead of `NhostReactProvider` and
`NhostNextProvider`

    `NhostReactProvider` and `NhostNextProvider` are now deprecated

-   f4d70f88: fix(dashboard): do not break when region is nullish

- 4a9471cc: Windows Live Provider displayed link updated to match
backend url

- 594488e4: fix(dashboard): do not show error when submitting Apple
provider settings

-   Updated dependencies [7f251111]
    -   @nhost/nextjs@1.10.0
    -   @nhost/react@0.16.0
    -   @nhost/react-apollo@4.10.0

## 0.7.7

### Patch Changes

-   80b604ad: fix(dashboard): use correct Hasura slug

## 0.7.6

### Patch Changes

-   2d2beb53: fix(dashboard): prevent error on GraphQL page
-   ac8efcbd: chore(dashboard): deprecate old DNS name

## 0.7.5

### Patch Changes

-   132a4f4b: chore(dashboard): remove unused dependencies
- 132a4f4b: chore(deps): synchronize @types/react-dom and @types/react
versions
-   db57572f: fix(dashboard): correct section paddings when no env vars
-   Updated dependencies [132a4f4b]
    -   @nhost/react@0.15.2
    -   @nhost/react-apollo@4.9.2
    -   @nhost/nextjs@1.9.3

## 0.7.4

### Patch Changes

-   34d85e54: chore(deps): update dependency critters to ^0.0.16
- 9b93cf95: chore(deps): update dependency @netlify/functions to ^0.11.0
-   e0439030: chore(deps): update dependency @types/react-dom to v18.0.9
-   Updated dependencies [82124329]
    -   @nhost/nextjs@1.9.2

## 0.7.3

### Patch Changes

-   a1193da4: fix(dashboard): remove character limit from env var inputs

## 0.7.2

### Patch Changes

-   44f13f62: chore(dashboard): cleanup unused files

## 0.7.1

### Patch Changes

- e01cb2ed: chore(dashboard): change settings sidebar menu item density

## 0.7.0

### Minor Changes

- db342f45: chore(dashboard): refactor Roles and Permissions settings
sections
-   8b9fa0b1: feat(dashboard): add Environment Variables page

### Patch Changes

-   Updated dependencies [66b4f3d0]
-   Updated dependencies [2e6923dc]
-   Updated dependencies [ef117c28]
-   Updated dependencies [aebb8225]
    -   @nhost/core@0.9.4
    -   @nhost/nhost-js@1.6.2
    -   @nhost/nextjs@1.9.1
    -   @nhost/react@0.15.1
    -   @nhost/react-apollo@4.9.1

## 0.6.0

### Minor Changes

-   eef9c914: feat(dashboard): add Roles and Permissions page

## 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

-   766cb612: fix(dashboard): correct redirect URL for oauth providers
-   Updated dependencies [53bdc294]
-   Updated dependencies [f2aaff05]
    -   @nhost/nextjs@1.8.3
    -   @nhost/core@0.9.3
    -   @nhost/react@0.14.3
    -   @nhost/nhost-js@1.6.1
    -   @nhost/react-apollo@4.8.3

## 0.4.0

### Minor Changes

-   9211743d: feat(dashboard): migrate Settings page features

## 0.3.0

### Minor Changes

-   73da6a67: fix(dashboard): avoid using BACKEND_URL locally

## 0.2.0

### Minor Changes

-   db118f97: feat(dashboard): generate Docker image

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-02-11 08:34:08 +01:00
David Barroso
403a45d2cf chore (dashboard): update schema (#3192)
### **PR Type**
Enhancement


___

### **Description**
- Update schema for resource configuration

- Remove replicas and autoscaler from Postgres

- Refactor initial resource retrieval logic

- Adjust GraphQL types for Postgres resources


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>ResourcesForm.tsx</strong><dd><code>Refactor initial
resource retrieval logic</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>


dashboard/src/features/orgs/projects/resources/settings/components/ResourcesForm/ResourcesForm.tsx

<li>Refactored <code>getInitialServiceResources</code> function<br> <li>
Added checks for <code>replicas</code> and <code>autoscaler</code>
properties<br> <li> Initialized <code>replicas</code> to 1 if not
present


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3192/files#diff-0a7e99e6ee09c17eec103656a9aa088b379c7927a182098538b793488a1f9337">+11/-1</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>ResourcesForm.tsx</strong><dd><code>Update resource
form logic and submission</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></summary>
<hr>


dashboard/src/features/projects/resources/settings/components/ResourcesForm/ResourcesForm.tsx

<li>Updated <code>getInitialServiceResources</code> function similar to
org version<br> <li> Removed <code>replicas</code> and
<code>autoscaler</code> from database resources in form <br>submission


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3192/files#diff-6d00a7b503dbd4b76f86d3949458d7f0bd62622cf17c523e0d668e3b459b67b5">+11/-7</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>graphql.ts</strong><dd><code>Update GraphQL types for
Postgres resources</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

dashboard/src/utils/__generated__/graphql.ts

<li>Updated <code>ConfigPostgresResources</code> type<br> <li> Removed
<code>replicas</code>, <code>autoscaler</code>, and
<code>networking</code> fields<br> <li> Added
<code>ConfigPostgresResourcesStorage</code> type<br> <li> Updated
related comparison, insert, and update types


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3192/files#diff-fbd5db84b560b1c91675004448c6c7fa0dcbfb28b9eb05d53b03e6cb7b83ebac">+28/-46</a>&nbsp;
</td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>getResources.gql</strong><dd><code>Update Postgres
resources GraphQL query</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></summary>
<hr>


dashboard/src/features/orgs/projects/resources/settings/gql/getResources.gql

<li>Removed <code>replicas</code> and <code>autoscaler</code> fields
from Postgres resources query


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3192/files#diff-45c2f030236a2836bd4ba61e46a20bc0b40f2ab08874c056c49b285a9c2c80eb">+0/-4</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>

---------

Co-authored-by: robertkasza <robert@nhost.io>
2025-02-11 08:29:06 +01:00
David BM
05f063b8e2 fix (dashboard): undefined is not an object in logs page (#3139)
### **PR Type**
Bug fix


___

### **Description**
- Fixed undefined object evaluation in logs page

- Improved error handling in LogsHeader component

- Enhanced data loading checks in LogsPage

- Refactored imports for better organization


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Bug
fix</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>LogsHeader.tsx</strong><dd><code>Improve error handling
in LogsHeader component</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>


dashboard/src/features/orgs/projects/logs/components/LogsHeader/LogsHeader.tsx

<li>Added null check for <code>data</code> in useEffect hooks<br> <li>
Reordered imports for better organization


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3139/files#diff-ebb3285aa776c9c5ea8b72672c4aafd55994c6c694998bbf56ca9c56d1e77664">+3/-3</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>logs.tsx</strong><dd><code>Enhance data loading and
error handling in LogsPage</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></summary>
<hr>

dashboard/src/pages/orgs/[orgSlug]/projects/[appSubdomain]/logs.tsx

<li>Added <code>loadingProject</code> to useProject hook<br> <li>
Destructured <code>loadingLogs</code> from useGetProjectLogsQuery<br>
<li> Created combined <code>loading</code> state<br> <li> Fixed
potential undefined <code>project</code> in subscription


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3139/files#diff-77489a68a7526d74f06d59019ad68c44728b7620637308d70fba38d6649b73fa">+18/-10</a>&nbsp;
</td>

</tr>
</table></td></tr><tr><td><strong>Documentation</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>empty-dancers-do.md</strong><dd><code>Add changeset for
bug fix in logs page</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

.changeset/empty-dancers-do.md

<li>Added changeset file for version bump<br> <li> Described fix for
undefined object in logs page


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3139/files#diff-1b8f8750870d40489590edead6484834991c219568156c38b95a55aa55d9362b">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> 💡 **PR-Agent usage**: Comment `/help "your question"` on any pull
request to receive relevant information
2025-02-06 21:23:03 +01:00
github-actions[bot]
09f5bed1e8 chore: update versions (#3187)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @nhost/dashboard@2.19.0

# @nhost/dashboard

## 2.17.0

### Minor Changes

-   fd59918: fix: redirect to 404 with nhost cli dashboard

## 2.16.0

### Minor Changes

-   f8e6b61: fix: can add rule groups in table permissions
-   9e404c8: fix: not redirect to 404 page if using local Nhost backend
-   ac4aa01: fix: can delete column in database page
-   4385524: fix: update url to check service health in local dashboard

### Patch Changes

-   @nhost/react-apollo@16.0.1
-   @nhost/nextjs@2.2.2

## 2.15.0

### Minor Changes

- f1052a8: fix: improve stability of the dashboard when pausing projects
-   30daa41: fix: update links to docs in overview page
-   7537237: feat: add image preview toggle in storage

## 2.14.0

### Minor Changes

- d43931e: fix: invalid organization slug/project subdomain doesn't open
404 page
- 5df6fa2: feat: add unencrypted disk warning in storage capacity
settings

### Patch Changes

-   44c1e17: chore: update `msw` to v1.3.5 to fix vulnerabilities
    -   @nhost/react-apollo@16.0.0
    -   @nhost/nextjs@2.2.1

## 2.13.0

### Minor Changes

- 21e90da: chore: remove restrictions on SMTP sender so My Name
[name@acme.com](mailto:name@acme.com) can be added
- 865dd93: fix: duplicate Run placeholders when there is an error in the
backend
- 6902a36: fix: can remove resources if postgres capacity is higher than
10
-   a535aa3: fix: fetch user roles locally in auth section
-   0c50816: fix: allow decimal numbers in database row insert
- aea6d18: chore: add warning when pausing a project about losing Run
services persistent volume data
- d3b4fc3: feat: allow to change postgres settings if project is paused
-   29d27e1: chore: update `next` to v14.2.22 to fix vulnerabilities
-   c9dca09: feat: add reset password form
-   b3bcacb: fix: paused project banner cannot read null project name

### Patch Changes

-   Updated dependencies [46fc520]
-   Updated dependencies [29d27e1]
    -   @nhost/nextjs@2.2.0
    -   @nhost/react-apollo@15.0.1

## 2.12.0

### Minor Changes

- eb95562: fix: show all available permission variables in permission
dropdown select

### Patch Changes

- 8b5c4a0: chore: cleanup layout and add disable duplicate atom key
checking in development mode

## 2.11.3

### Patch Changes

- 714dffa: fix: improve project polling logic and unify usage across
components

## 2.11.2

### Patch Changes

- 6a34f89: fix: improve project polling logic and unify usage across
components

## 2.11.1

### Patch Changes

-   0f6ce52: fix: consolidate useProject hook and fix jwt expired error

## 2.11.0

### Minor Changes

-   cea3ef5: Feat: add org and project placeholders

## 2.10.0

### Minor Changes

-   86ecf27: feat: add support for additional metrics in overview
- 21708be: feat: dashboard: add support for storage buckets to AI
assistants

## 1.30.0

### Minor Changes

- 50441a8: feat: add ui for project autoscaler settings and run services
autoscaler settings

## 1.29.0

### Minor Changes

-   55d8bb5: feat: integrate turnstile for signup verification
-   2a2e54c: fix: update docs url in run services form tooltip
- 18f942f: fix: display long error messages in error toast without
overflow

### Patch Changes

-   @nhost/react-apollo@13.0.0
-   @nhost/nextjs@2.1.22

## 1.28.2

### Patch Changes

- 52a38fe: chore: update dependencies to address security
vulnerabilities
-   Updated dependencies [52a38fe]
    -   @nhost/nextjs@2.1.21

## 1.28.1

### Patch Changes

-   9735fa2: chore: remove broken link

## 1.28.0

### Minor Changes

- 526183a: feat: allow filtering users in "make request as" in graphql
section
-   be3b85b: feat: add conceal errors toggle on auth settings page

### Patch Changes

- 35a2f12: fix: prevent run service details from opening when attempting
to delete
    -   @nhost/react-apollo@12.0.6
    -   @nhost/nextjs@2.1.20

## 1.27.0

### Minor Changes

-   a7cd02c: fix: resolve rate limit query

## 1.26.0

### Minor Changes

-   3773ad7: chore: update pricing information
- b63250d: fix: not allow run service creation form resubmission while
creating a run service
-   a44a1d4: feat: add rate limits settings page

### Patch Changes

-   @nhost/react-apollo@12.0.5
-   @nhost/nextjs@2.1.19

## 1.25.0

### Minor Changes

- d1ceede: feat: add setting to migrate postgres major and/or minor
versions
- e5d3d1a: fix: allow manually typing column for custom check in
database row permissions

### Patch Changes

-   @nhost/react-apollo@12.0.4
-   @nhost/nextjs@2.1.18

## 1.24.1

### Patch Changes

- 49f2e55: fix: use service subdomain in service form and service
details dialog
- 598b988: fix: use current project subdomain in ServiceDetailsDialog
component

## 1.24.0

### Minor Changes

-   abb24af: chore: add redirect to support page when project is locked
- 18a6455: feat: show contact us info and locked reason when project is
locked

### Patch Changes

-   e31eefa: fix: include ingresses field when updating run services

## 1.23.0

### Minor Changes

-   33284d3: fix: don't show double scrollbar in configuration editor

### Patch Changes

-   @nhost/react-apollo@12.0.3
-   @nhost/nextjs@2.1.17

## 1.22.0

### Minor Changes

-   998c037: fix: align drop-down list in select component
- 807b8c0: fix: show city name in region selection for project creation

## 1.21.0

### Minor Changes

- a2efeed: fix: improve project health error handling, add unknown state
and polling interval for health state

## 1.20.0

### Minor Changes

- 8ea4210: fix: error toasts can be closed individually, instead of
dismissing all toasts at once
- 58919ba: chore: add blink animation when project health service is
updating

## 1.19.0

### Minor Changes

- b519862: fix: get configuration in configuration editor using local
development environment

## 1.18.0

### Minor Changes

- 502abad: feat: add services health checks indicators to the overview
page
-   b3ff6ad: chore: update title text on service status modal
- dbadf59: feat: add project configuration TOML editor to the settings
page

## 1.17.0

### Minor Changes

- 77fba27: fix: postgres version validation when activating ai in ai
settings page
-   ac6d1b6: feat: use name instead of awsName

## 1.16.3

### Patch Changes

- 87a37cf: fix: remove unnecessary isPlatform check from verify button
disable logic on custom domains
    -   @nhost/react-apollo@12.0.2
    -   @nhost/nextjs@2.1.16

## 1.16.2

### Patch Changes

- a9413af: fix: update `GetAllWorkspacesAndProjects` query polling to
use exponential backoff
    -   @nhost/react-apollo@12.0.1
    -   @nhost/nextjs@2.1.15

## 1.16.1

### Patch Changes

-   @nhost/react-apollo@12.0.0
-   @nhost/nextjs@2.1.14

## 1.16.0

### Minor Changes

- c6d5c5c: feat: add toggle switch to enable/disable public access in
the database settings

## 1.15.2

### Patch Changes

-   @nhost/react-apollo@11.0.4
-   @nhost/nextjs@2.1.13

## 1.15.1

### Patch Changes

-   @nhost/react-apollo@11.0.3
-   @nhost/nextjs@2.1.12

## 1.15.0

### Minor Changes

-   a7bde37: feat: send metadata in the edit form

### Patch Changes

- 1bc615b: feat: improve error message handling in `ErrorToast`
component
    -   @nhost/react-apollo@11.0.2
    -   @nhost/nextjs@2.1.11

## 1.14.0

### Minor Changes

-   a448d7d: feat: allow configuring postmark and delete SMTP settings

## 1.13.3

### Patch Changes

-   5924bc3: fix: include password in `GetSmtpSettings` query
- c5ad634: fix: resolved an issue where one-click install links were
broken on Safari
- 7278991: fix: update graphql auto-embeddings configuration to use
String type for model field

## 1.13.2

### Patch Changes

-   026f84f: fix: use configuration server URL from environment variable

## 1.13.1

### Patch Changes

-   7e9a2ce: fix: resolve issue where run services form fails to open

## 1.13.0

### Minor Changes

-   dd5d262: feat: add model field to the auto-embeddings form
- 09962be: feat: enable settings and run services when running the
dashboard locally
- 9cdecb6: feat: enable users to update their email address from the
account settings page

## 1.12.2

### Patch Changes

-   c195c51: fix: send email upon signin for unverified users

## 1.12.1

### Patch Changes

- 93ebdf8: fix: use service urls when initilizaing NhostClient running
local dashboard
    -   @nhost/react-apollo@11.0.1
    -   @nhost/nextjs@2.1.10

## 1.12.0

### Minor Changes

- f242e4b: feat: add connect with github to the user's account settings
-   768ca17: chore: update dependencies
- d62bd0f: fix: "Track this" option within the SQL editor now correctly
updates the metadata
- 91c2bb6: feat: refactor sign-in and sign-up pages to enforce email
verification

### Patch Changes

-   943831f: fix: resolve an error toast issue when unpausing a project
-   Updated dependencies [768ca17]
    -   @nhost/react-apollo@11.0.0
    -   @nhost/nextjs@2.1.9

## 1.11.2

### Patch Changes

-   @nhost/react-apollo@10.0.2
-   @nhost/nextjs@2.1.8

## 1.11.1

### Patch Changes

-   981404f: fix: set default value for healthCheck field validation

## 1.11.0

### Minor Changes

- 7789469: chore: upgrade dependency `@graphql-codegen/cli` to `5.0.2`
to address vulnerability
- 6c11b75: feat: add update user displayName section in account settings

### Patch Changes

-   @nhost/react-apollo@10.0.1
-   @nhost/nextjs@2.1.7

## 1.10.0

### Minor Changes

-   49a80c2: chore: update dependencies
-   150c04a: feat: add healthcheck config to run services

### Patch Changes

- e03f141: fix: allow insert, update and delete on tables in `auth` and
`storage` schemas
- 28676f4: feat: add min postgres version check to enable the ai service
-   Updated dependencies [49a80c2]
    -   @nhost/react-apollo@10.0.0
    -   @nhost/nextjs@2.1.6

## 1.9.0

### Minor Changes

-   d86e5c9: feat: add support for filtering the logs using a RegExp

## 1.8.3

### Patch Changes

-   @nhost/react-apollo@9.0.3
-   @nhost/nextjs@2.1.5

## 1.8.2

### Patch Changes

- 6df4f02: fix: use custom error toast and show correct message when
sending an invite

## 1.8.1

### Patch Changes

-   @nhost/react-apollo@9.0.2
-   @nhost/nextjs@2.1.4

## 1.8.0

### Minor Changes

- 713d53c: feat: add catch-all route for workspace/project - useful for
documentation

### Patch Changes

-   3db2999: fix: refresh table list after running SQL using the editor
- 3c4dd55: fix: handle `Error` objects properly in the `ErrorToast`
component
- 92b434e: fix: resolve an issue where the checkbox in the data-grid
header did not select all rows
    -   @nhost/react-apollo@9.0.1
    -   @nhost/nextjs@2.1.3

## 1.7.0

### Minor Changes

-   0d8d0eb: Update docs and dashboard references

## 1.6.9

### Patch Changes

-   @nhost/react-apollo@9.0.0
-   @nhost/nextjs@2.1.2

## 1.6.8

### Patch Changes

-   @nhost/react-apollo@8.0.1
-   @nhost/nextjs@2.1.1

## 1.6.7

### Patch Changes

-   5ef5189: fix: update `@apollo/client` to `3.9.4` to fix a cache bug

## 1.6.6

### Patch Changes

-   3ba485e: fix: added discord.com to connect-src
-   e5bab6a: chore: update dependencies
-   Updated dependencies [b19ffed]
-   Updated dependencies [e5bab6a]
    -   @nhost/nextjs@2.1.0
    -   @nhost/react-apollo@8.0.0

## 1.6.5

### Patch Changes

- ba73bb4: fix: update ErrorToast component to show the internal graphql
error
- d5337ff: fix: utilize accumulator in the creation of validation schema
within data grid utils

## 1.6.4

### Patch Changes

-   7c2a1c2: feat: show error and debug info in the error toast

## 1.6.3

### Patch Changes

-   6b8aad5: fix: add bare nhost.run to CSP

## 1.6.2

### Patch Changes

-   b18edc0: feat: added CSP and X-Frame-Options

## 1.6.1

### Patch Changes

-   8d91f71: chore: update deps and enable pnpm audit
- 3b8473b: chore: update turbo to `1.11.3` and pnpm to `8.10.5` in
Dockerfile
-   Updated dependencies [8d91f71]
    -   @nhost/react-apollo@7.0.2
    -   @nhost/nextjs@2.0.2

## 1.6.0

### Minor Changes

-   3ff1c2b53: fix: show upgrade option for pro projects

## 1.5.0

### Minor Changes

-   c2ef17c0a: feat: add support for new Team plan

## 1.4.0

### Minor Changes

-   7883bbcbd: feat: don't show deprecated plans
- 44be6dc0a: feat: set redirectTo during sign-in to support preview
environments

### Patch Changes

- 3c3594898: fix: allow access to graphite when configured running in
local dashboard
-   32c246b7a: chore: update docs icon

## 1.3.2

### Patch Changes

-   174b4165b: chore: use env variables when running graphql codegen
-   7c977e714: chore: change `Allowed Roles` to `Default Allowed Roles`
-   46f028b9f: fix: remove hardcoded ai version setting

## 1.3.1

### Patch Changes

- af33c21d1: chore: remove backendUrl deprecation notice and remove all
references to `providersUpdated`

## 1.3.0

### Minor Changes

-   04784d880: Fix graphite's default version

## 1.2.0

### Minor Changes

-   5733162ed: feat: add settings and ui for graphite

## 1.1.0

### Minor Changes

-   e2b79b5ec: chore: remove sharp from deps

## 1.0.1

### Patch Changes

-   @nhost/react-apollo@7.0.1
-   @nhost/nextjs@2.0.1

## 1.0.0

### Major Changes

- bc9eff6e4: chore: remove support for using backendUrl when
instantiating the Nhost client

### Patch Changes

-   Updated dependencies [bc9eff6e4]
    -   @nhost/nextjs@2.0.0
    -   @nhost/react-apollo@7.0.0

## 0.21.1

### Patch Changes

-   97ced73a3: fix(dashboard): prevent dashboard from resolving secrets

## 0.21.0

### Minor Changes

- ed1a8d458: Update alert message on increasing PostgreSQL's volume
capacity
-   2e2248fd4: feat(dashboard): add SQL editor

## 0.20.28

### Patch Changes

-   7c2c31082: feat: add support for users to delete their account
    -   @nhost/react-apollo@6.0.1
    -   @nhost/nextjs@1.13.40

## 0.20.27

### Patch Changes

- fa79b7709: chore(dashboard): tweaks and fixes to the service form and
dialog
-   8df84d782: fix(dashboard): allow resetting custom domains
    -   @nhost/react-apollo@6.0.0
    -   @nhost/nextjs@1.13.39

## 0.20.26

### Patch Changes

- 331ba0376: feat(dashboard): add postgres storage capacity modifier in
the settings
-   b7f801874: feat(dashboard): add new settings page for custom domains

## 0.20.25

### Patch Changes

-   @nhost/react-apollo@5.0.38

## 0.20.24

### Patch Changes

-   e10389ecf: fix(dashboard): disable run tab when developing locally
    -   @nhost/react-apollo@5.0.37

## 0.20.23

### Patch Changes

-   c01568a7d: chore(dashboard): show alert to update oauth providers

## 0.20.22

### Patch Changes

-   c3efb7ec8: feat(dashboard): query latest announcement from platform

## 0.20.21

### Patch Changes

-   3e46d3873: chore: update link to node18 announcement

## 0.20.20

### Patch Changes

-   @nhost/react-apollo@5.0.36
-   @nhost/nextjs@1.13.38

## 0.20.19

### Patch Changes

-   75c4c8ae3: feat(dashboard): make env value input multiline

## 0.20.18

### Patch Changes

- 425d485f8: fix(dashboard): make sure dedicated resources pricing
follows total resources

## 0.20.17

### Patch Changes

-   ae324f67f: fix(dashboard): remove unused graphql fields

## 0.20.16

### Patch Changes

-   df5b4302c: chore(dashboard): remove run feature flag
- bf4a1f6c2: feat(dashboard): fetch auth, postgres, hasura and storage
versions from dashboard
- 34fc08ca7: fix(dashboard/run): show correct private registry in
service details
-   885d10620: chore(dashboard): change feedback to contact us

## 0.20.15

### Patch Changes

- ed16c8b5d: feat(run): add a confirmation dialog when deleting a run
service
- 216990888: fix(run): center loading indicator when selecting a project

## 0.20.14

### Patch Changes

-   9fbea9787: feat: add node18 announcement

## 0.20.13

### Patch Changes

- e84acf469: fix(run): handle subdomain undefined error when creating a
new service

## 0.20.12

### Patch Changes

-   b7c799d62: feat(run): add dialog to copy registry and URLs

## 0.20.11

### Patch Changes

-   8903e6abd: fix(dashboard): show correct egress limit in usage stats

## 0.20.10

### Patch Changes

- 666a75a23: feat(dashboard): add functions execution time and egress
volume to usage stats

## 0.20.9

### Patch Changes

-   5e1e80aa8: fix(dashboard): show correct locales in user details
    -   @nhost/react-apollo@5.0.35
    -   @nhost/nextjs@1.13.37

## 0.20.8

### Patch Changes

-   @nhost/react-apollo@5.0.34
-   @nhost/nextjs@1.13.36

## 0.20.7

### Patch Changes

-   4a7ede11e: fix: distinguish files that were not uploaded
- 202b64723: feat(nhost-run): add support for one-click-install run
services
- 074a0fa11: feat(dashboard): add settings toggle to enable/disable
antivirus
    -   @nhost/react-apollo@5.0.33
    -   @nhost/nextjs@1.13.35

## 0.20.6

### Patch Changes

-   b20761e97: feat(services): add pricing info and confirmation dialog
-   90df6d81d: fix(services): handle null values when editing a service
-   aa8508467: fix: query service logs correctly
    feat: enable multiline support for environment value input

## 0.20.5

### Patch Changes

-   8d7f84b8d: fix: make announcement adapt to theme

## 0.20.4

### Patch Changes

-   3b75bfce2: fix: make announcement close properly
- f49819075: fix: show correct values when dedicated resources are
disabled

## 0.20.3

### Patch Changes

-   e643bd362: fix(services): fix errors when config is null
-   bcdab66bf: feat: add annoucement for nhost run
-   f967a2e59: added note about storage not being able to be downsized
-   311c7756d: chore(services): consistent naming for compute

## 0.20.2

### Patch Changes

-   9073182d5: chore(dashboard): bump `turbo` to 1.10.11
-   ece717d6e: feat(logs): show services in the logs page
- 82b335311: feat(metrics): change grafana link to point to the
dashboards
- b135ef695: fix(services): set command as optional and set min replicas
to 0

## 0.20.1

### Patch Changes

-   3d5c34f4c: fix(auth): fix users pagination limit

## 0.20.0

### Minor Changes

-   c99d117d1: feat(services): add support for custom services

## 0.19.2

### Patch Changes

-   face99ccd: chore(deps): bump turbo version
-   cfe527307: style: tweak pull config warning in dark mode
- a9d7da8af: chore(deps): update dependency @types/pluralize to ^0.0.30
-   9aa4371ef: chore: add hasura-auth version 0.21.2
- d14e112bf: chore(deps): update dependency prettier-plugin-tailwindcss
to ^0.4.0
-   d3e8bb94a: chore(deps): update dependency vite-plugin-dts to v3

## 0.19.1

### Patch Changes

-   @nhost/react-apollo@5.0.32
-   @nhost/nextjs@1.13.34

## 0.19.0

### Minor Changes

- 9c61c69a7: chore(dashboard):add postgres 14.6-20230705-1 to the
version selector

### Patch Changes

-   47bda15ff: feat(settings): add warning to pull config

## 0.18.0

### Minor Changes

- ee0b9b8ed: chore(dashboard):add hasura v2.28.2 and v2.29.0 to the
version selector

## 0.17.20

### Patch Changes

-   @nhost/react-apollo@5.0.31
-   @nhost/nextjs@1.13.33

## 0.17.19

### Patch Changes

-   f866120a6: fix(users): use the password length from the config

## 0.17.18

### Patch Changes

-   @nhost/react-apollo@5.0.30
-   @nhost/nextjs@1.13.32

## 0.17.17

### Patch Changes

-   ea7b102c0: fix(pat): highlight expired tokens

## 0.17.16

### Patch Changes

- b3b64a3b7: chore(deps): bump `@types/react` to `v18.2.14` and
`@types/react-dom` to `v18.2.6`
-   32b221f94: chore(deps): bump `graphiql` to `v3`
-   3a56c12df: chore(deps): bump `turbo` to `v1.10.6`
-   Updated dependencies [b3b64a3b7]
    -   @nhost/react-apollo@5.0.29
    -   @nhost/nextjs@1.13.31

## 0.17.15

### Patch Changes

-   f41fdc12a: chore(deps): bump `turbo` to `1.10.5`
-   6199c1c55: fix(projects): don't redirect to 404 page
-   Updated dependencies [07a45fde0]
    -   @nhost/react-apollo@5.0.28
    -   @nhost/nextjs@1.13.30

## 0.17.14

### Patch Changes

- 80b22724d: chore(deps): bump `@types/react` to `v18.2.13`,
`@types/react-dom` to `v18.2.6` and `@storybook/testing-library` to
`v0.2.0`

## 0.17.13

### Patch Changes

-   cc02902cb: chore(docs): update environment variable documentation

## 0.17.12

### Patch Changes

-   660d339e1: fix(storybook): don't break storybook
-   660d339e1: fix(tests): prevent warnings during tests
    -   @nhost/react-apollo@5.0.27
    -   @nhost/nextjs@1.13.29

## 0.17.11

### Patch Changes

- bd4d0c270: chore(dashboard):add postgres 14.6-20230613-1 to the
version selector

## 0.17.10

### Patch Changes

-   c8c2a10b2: fix(database): don't break the password reset flow
- e70b45498: chore(deps): bump `@types/react` to `v18.2.12` and
`@types/react-dom` to `v18.2.5`

## 0.17.9

### Patch Changes

- 842055099: chore(deps): bump `turbo` to `v1.10.3` and `pnpm` to
`v8.6.2`
- fd12aa0a8: chore(projects): remove the postgres password input from
the project creation screen
-   022b76e78: chore(deps): bump `@types/react` to `v18.2.11`
-   3555ab2b7: chore(deps): bump `vitest` monorepo to `v0.32.0`
-   c43e54922: feat(backups): add download button to backups

## 0.17.8

### Patch Changes

-   d0457fe5c: feat(settings): improve the dashboard and config parity
    -   @nhost/react-apollo@5.0.26
    -   @nhost/nextjs@1.13.28

## 0.17.7

### Patch Changes

-   4f0368b95: fix(account): don't break account settings page

## 0.17.6

### Patch Changes

- 64a8f41d0: chore(resources): lower the maximum allowed resources per
service

## 0.17.5

### Patch Changes

-   @nhost/react-apollo@5.0.25
-   @nhost/nextjs@1.13.27

## 0.17.4

### Patch Changes

- 9b1d0f7a5: fix(deployments): use correct timestamp for deployment
details
-   6d2963ffa: chore(deps): bump `@types/react` to `v18.2.8`
- 8871267b9: chore(deps): downgrade `pnpm` to `v8.5.1` because of no
Turborepo support

## 0.17.3

### Patch Changes

-   01eeef9de: chore(misc): under the hood improvements
- 21e13db05: chore(deps): bump `@types/react` to `v18.2.7` and `turbo`
to `v1.10.1`
- f16433ae6: chore(secrets): allow empty secrets and environment
variables
-   aa3c62989: chore(cli): bump Nhost CLI version to v1.0
    -   @nhost/react-apollo@5.0.24
    -   @nhost/nextjs@1.13.26

## 0.17.2

### Patch Changes

-   88a4983f: chore(misc): under the hood improvements

## 0.17.1

### Patch Changes

-   9b0d4dde: feat(secrets): enable secrets

## 0.17.0

### Minor Changes

-   15d84a19: Add postgres 14.6-20230525

## 0.16.14

### Patch Changes

-   4c626174: chore: updated import paths, improved directory structure
-   cc047b71: chore(deps): bump `@fontsource` monorepo to `v5.0.0`
-   99edd012: feat(account): add support for personal access tokens

## 0.16.13

### Patch Changes

-   78c7109c: feat(settings): allow selecting service versions

## 0.16.12

### Patch Changes

- 399009d6: fix(gql): don't enter an infinite loop when fetching remote
app data
- 329e5a91: fix(deployments): use the same sorting of deployments
everywhere
- 6d559d6e: chore(settings): add under the hood improvements to the
settings page
- 12eb236c: chore(deps): bump `prettier-plugin-tailwindcss` to `v0.3.0`
-   f9b81a2a: chore(deps): bump `turbo` to `v1.9.8`
-   1345741b: fix(projects): don't redirect to 404 on project creation
-   Updated dependencies [7fea29a8]
    -   @nhost/react-apollo@5.0.23
    -   @nhost/nextjs@1.13.25

## 0.16.11

### Patch Changes

- 1230b722: fix(projects): don't redirect to 404 on when the project is
renamed
    -   @nhost/react-apollo@5.0.22
    -   @nhost/nextjs@1.13.24

## 0.16.10

### Patch Changes

-   Updated dependencies [da03bf39]
    -   @nhost/react-apollo@5.0.21
    -   @nhost/nextjs@1.13.23

## 0.16.9

### Patch Changes

- 349aac36: fix(settings): use region domain when constructing the
postgres connection string

## 0.16.8

### Patch Changes

- 20fb69fa: chore(projects): change the way how API URLs are constructed

## 0.16.7

### Patch Changes

- 49f9b837: chore(docker): bump `pnpm` to `v8.4.0` and `turbo` to
`v1.9.3`
- 3f478a4e: chore(deps): bump `vitest` to `v0.31.0`, `@types/react` to
`v18.2.6` and `@types/react-dom` to `v18.2.4`

## 0.16.6

### Patch Changes

- d926f156: fix(projects): redirect to 404 when an invalid project is
opened
- 49b99728: fix(projects): disable features for non-owner members of
workspaces

## 0.16.5

### Patch Changes

-   12e2855f: chore(deps): bump `jsdom` to v22
-   e4972b83: feat(metrics): add Grafana page

## 0.16.4

### Patch Changes

- 3f396a9e: fix(projects): unpause after upgrading a paused project to
pro
- 3f396a9e: fix(projects): don't redirect to 404 page after project
creation

## 0.16.3

### Patch Changes

-   Updated dependencies [90c60311]
    -   @nhost/react-apollo@5.0.20
    -   @nhost/nextjs@1.13.22

## 0.16.2

### Patch Changes

-   0f34f0c6: fix(projects): disallow downgrading to free plan
- 8da291ad: chore(deps): bump `@types/react` to v18.2.0 and
`@types/react-dom` to v18.2.1

## 0.16.1

### Patch Changes

- adc828a5: fix(gql): don't enter an infinite loop when fetching remote
app data

## 0.16.0

### Minor Changes

-   2fb1145f: feat(compute): add support for replicas

### Patch Changes

- d8ceccec: chore(env): remove deprecated `NHOST_BACKEND_URL`
environment variable

## 0.15.2

### Patch Changes

-   84b84ab7: fix(projects): filter projects by workspace

## 0.15.1

### Patch Changes

-   2faf7907: chore(deps): bump `graphql-request` to v6
-   f1b5a944: chore(deps): bump `@vitejs/plugin-react` to v4
-   7f1785ac: chore(deps): bump `@types/react` to v18.0.37
    -   @nhost/react-apollo@5.0.19

## 0.15.0

### Minor Changes

-   85889ee8: feat(dashboard): add Compute management to the settings

## 0.14.8

### Patch Changes

-   668c8771: chore(dialogs): unify dialog management of payment dialogs

## 0.14.7

### Patch Changes

-   d4ccc656: chore: cleanup unused code
    -   @nhost/react-apollo@5.0.18
    -   @nhost/nextjs@1.13.21

## 0.14.6

### Patch Changes

-   b299cfc9: chore(deps): bump `vitest` to v0.30.0
-   411cb65b: chore(projects): refactor workspace and project hooks
- 43b1b144: chore(deps): bump `@types/react` to v18.0.34 and
`@types/react-dom` to v18.0.11
-   Updated dependencies [43b1b144]
    -   @nhost/react-apollo@5.0.17
    -   @nhost/nextjs@1.13.20

## 0.14.5

### Patch Changes

-   ba0d57ee: fix(i18n): revert i18n library
-   3328ed05: feat(projects): improve overview when there is an error

## 0.14.4

### Patch Changes

-   5e0920ba: chore(deps): bump `next-seo` to v6
-   706c9dc3: chore(deps): bump `@types/react` to 18.0.33
-   99f8f6b3: feat(metrics): show metrics on the overview

## 0.14.3

### Patch Changes

-   @nhost/react-apollo@5.0.16

## 0.14.2

### Patch Changes

-   3cb67300: fix(logs): don't break UI when clearing time picker
-   7453bf3b: feat(projects): show project creator info
-   c166dad0: chore(tests): improve auth page tests
-   6a290bb2: chore(deps): bump `@types/react` to 18.0.32

## 0.14.1

### Patch Changes

-   @nhost/react-apollo@5.0.15
-   @nhost/nextjs@1.13.19

## 0.14.0

### Minor Changes

-   6e1f03ea: feat(dashboard): add support for the Azure AD provider

### Patch Changes

-   1bd2c373: chore(deps): bump `turbo` to 1.8.6
-   d329b621: chore(deps): bump `@types/react` to 18.0.30
-   cb248f0d: fix(tests): avoid name collision in database tests
-   867c8076: chore(deps): bump `@types/react` to 18.0.29

## 0.13.10

### Patch Changes

- e93b06ab: fix(dashboard): remove left margin from workspace list on
mobile
-   1c4806bf: chore(deps): bump `sharp` to 0.32.0
    -   @nhost/react-apollo@5.0.14
    -   @nhost/nextjs@1.13.18

## 0.13.9

### Patch Changes

-   912ed76c: chore(dashboard): bump `@apollo/client` to 3.7.10
-   Updated dependencies [912ed76c]
    -   @nhost/react-apollo@5.0.13

## 0.13.8

### Patch Changes

-   7c127372: chore(dashboard): bump `react-error-boundary` to v4

## 0.13.7

### Patch Changes

- 9130ab12: chore(dashboard): bump `yup` to v1 and `@hookform/resolvers`
to v3

## 0.13.6

### Patch Changes

- 253dd235: using new mutation to create projects + refactor Create
Project page.

## 0.13.5

### Patch Changes

-   @nhost/react-apollo@5.0.12
-   @nhost/nextjs@1.13.17

## 0.13.4

### Patch Changes

-   b48bc034: fix(dashboard): disable new users
-   798e591b: fix(dashboard): show correct date in data grid

## 0.13.3

### Patch Changes

-   bfb4c1a6: chore(dashboard): remove `useAxios` property
-   d8d8394b: Dashboard: allow to override hasura admin secret in docker
-   Updated dependencies [ce1ee40d]
    -   @nhost/nextjs@1.13.16
    -   @nhost/react-apollo@5.0.11

## 0.13.2

### Patch Changes

-   beed2eba: Fix docker entrypoint for dashboard
- 2c8559a3: fix(dashboard): refresh project list after deleting a
project
-   4329d048: chore(dashboard): bump `graphiql` dependencies

## 0.13.1

### Patch Changes

-   cbb1fc5b: chore(dashboard): cleanup GraphQL operations

## 0.13.0

### Minor Changes

-   088584e7: feat(dashboard): add support for custom local subdomains

### Patch Changes

-   2ac90dfd: fix(dashboard): improve mobile responsive layout
-   Updated dependencies [f375eacc]
    -   @nhost/nextjs@1.13.15
    -   @nhost/react-apollo@5.0.10

## 0.12.4

### Patch Changes

-   @nhost/react-apollo@5.0.9
-   @nhost/nextjs@1.13.14

## 0.12.3

### Patch Changes

-   2b1338f7: chore(dashboard): bump `turbo` to 1.8.3
- 5223ee93: fix(dashboard): show correct deployment status on the main
page
-   850a049c: chore(deps): update docker/build-push-action action to v4
-   Updated dependencies [850a049c]
    -   @nhost/nextjs@1.13.13
    -   @nhost/react-apollo@5.0.8

## 0.12.2

### Patch Changes

-   4bf40995: chore(deps): bump `typescript` to `4.9.5`
-   8bb097c9: chore(deps): bump `vitest`
- 35d52aab: chore(deps): replace `cross-fetch` with `isomorphic-unfetch`
-   Updated dependencies [4bf40995]
-   Updated dependencies [8bb097c9]
-   Updated dependencies [35d52aab]
    -   @nhost/react-apollo@5.0.7
    -   @nhost/nextjs@1.13.12

## 0.12.1

### Patch Changes

-   c96d7ccd: fix(dashboard): fix docker builds

## 0.12.0

### Minor Changes

-   d1671210: feat(dashboard): use mimir to manage project configuration

### Patch Changes

-   f65e4de9: chore(deps): bump @graphql-codegen monorepo to v3

## 0.11.20

### Patch Changes

-   4b4f0d01: chore(dashboard): improve dialog management

## 0.11.19

### Patch Changes

-   @nhost/react-apollo@5.0.6
-   @nhost/nextjs@1.13.11

## 0.11.18

### Patch Changes

-   01318860: fix(nhost-js): use correct URL for functions requests
-   Updated dependencies [01318860]
    -   @nhost/react-apollo@5.0.5
    -   @nhost/nextjs@1.13.10

## 0.11.17

### Patch Changes

-   f673adea: fix(dashboard): set correct Content-Type for user creation
-   445d8ef4: chore(deps): bump `@nhost/react-apollo` to 5.0.4
-   445d8ef4: chore(deps): bump `@nhost/nextjs` to 1.13.9
- 0368663d: fix(dashboard): allow permission editing for auth and
storage schemas
-   Updated dependencies [445d8ef4]
-   Updated dependencies [445d8ef4]
    -   @nhost/react-apollo@5.0.4
    -   @nhost/nextjs@1.13.9

## 0.11.16

### Patch Changes

-   b755e908: fix(dashboard): use correct date for last seen
-   2d9145f9: chore(deps): revert GraphQL client
- 1ddf704c: fix(dashboard): don't show false positive message for failed
user creation
    -   @nhost/react-apollo@5.0.3
    -   @nhost/nextjs@1.13.8

## 0.11.15

### Patch Changes

-   @nhost/react-apollo@5.0.2
-   @nhost/nextjs@1.13.7

## 0.11.14

### Patch Changes

- 2cc18dcb: fix(dashboard): prevent permission editor dropdown from
being always open

## 0.11.13

### Patch Changes

- 3343a363: chore(dashboard): bump `@testing-library/react` to v14 and
`@testing-library/dom` to v9
    -   @nhost/react-apollo@5.0.1
    -   @nhost/nextjs@1.13.6

## 0.11.12

### Patch Changes

- 87eda76e: chore(dashboard): bump `@types/react` to v18.0.28 and
`@types/react-dom` to v18.0.11
-   6f0ac570: feat(dashboard): show dashboard version in account menu

## 0.11.11

### Patch Changes

-   bf1e4071: chore(dashboard): bump `react-is` version to `18.2.0`
-   Updated dependencies [bf1e4071]
-   Updated dependencies [5013213b]
    -   @nhost/nextjs@1.13.5
    -   @nhost/react-apollo@4.13.5

## 0.11.10

### Patch Changes

- a37a430b: fix(dashboard): don't break UI when deployments are
unavailable
    -   @nhost/react-apollo@4.13.4
    -   @nhost/nextjs@1.13.4

## 0.11.9

### Patch Changes

-   7b970e68: fix(dashboard): fix header link color

## 0.11.8

### Patch Changes

- f33242f2: feat(dashboard): add new sign up, sign in and reset password
pages

## 0.11.7

### Patch Changes

-   e9c8909c: fix(dashboard): use correct theme color in dark mode

## 0.11.6

### Patch Changes

-   902f486b: fix(dashboard): re-enable Hasura on logs page

## 0.11.5

### Patch Changes

-   1f9720fa: fix(dashboard): apply select permissions properly

## 0.11.4

### Patch Changes

-   deb14b51: fix(dashboard): don't break billing form

## 0.11.3

### Patch Changes

-   @nhost/react-apollo@4.13.3
-   @nhost/nextjs@1.13.3

## 0.11.2

### Patch Changes

-   f143e51d: chore(dashboard): pin Turborepo to 1.6.3

## 0.11.1

### Patch Changes

-   c2b5a41a: chore(dashboard): select system colors by default

## 0.11.0

### Minor Changes

-   1ebaf429: feat(dashboard): introduce Dark Mode 🌚

### Patch Changes

- 63b445c4: fixed duplicated logs bug and made to date count during live
mode

## 0.10.1

### Patch Changes

-   e146d32e: chore(deps): update dependency @types/react to v18.0.27
-   59347fcd: correct allowed role name
-   5b65cac9: updated authentication documentation
-   963f9b5e: feat(dashboard): include project info in feedback

## 0.10.0

### Minor Changes

-   ed4c7801: chore(dashboard): remove Functions section

## 0.9.10

### Patch Changes

-   4e2f8ccd: fix(dashboard): don't break Auth page in local mode

## 0.9.9

### Patch Changes

-   31abbe5f: fix(dashboard): enable toggle when settings are filled in

## 0.9.8

### Patch Changes

- 5bdd31ad: chore(dashboard): list fewer images per page on the Storage
page
- 5121851c: fix(dashboard): don't throw validation error for valid
permission rules

## 0.9.7

### Patch Changes

-   c126b20d: fix(dashboard): correct redeployment button

## 0.9.6

### Patch Changes

-   36c3519c: feat(dashboard): retrigger deployments

## 0.9.5

### Patch Changes

- 200e9f77: chore(deps): update dependency @types/react-dom to v18.0.10
-   Updated dependencies [200e9f77]
    -   @nhost/nextjs@1.13.2
    -   @nhost/react-apollo@4.13.2

## 0.9.4

### Patch Changes

- dbd3ded5: fix(dashboard): workspaces creation, new form, correct
redirects.

## 0.9.3

### Patch Changes

-   85f0f943: fix(dashboard): don't break the table creation process

## 0.9.2

### Patch Changes

-   Updated dependencies [d42c27ae]
-   Updated dependencies [927be4a2]
    -   @nhost/nextjs@1.13.1
    -   @nhost/react-apollo@4.13.1

## 0.9.1

### Patch Changes

-   d0f80811: fix(dashboard): don't show error when signing out the user

## 0.9.0

### Minor Changes

- d92891b2: feat(dashboard): add Permission Editor to the Database
section

### Patch Changes

-   3d379128: fix(dashboard): create new user
    -   @nhost/react-apollo@4.13.0
    -   @nhost/nextjs@1.13.0

## 0.8.1

### Patch Changes

-   7cadd944: fix(dashboard): display Twitter provider settings

## 0.8.0

### Minor Changes

-   9a1aa7bb: add functions to the log dashboard
-   f29abe62: feat(dashboard): Users Management v2

### Patch Changes

-   7766624b: feat(dashboard): add JWT secret editor modal
    -   @nhost/react-apollo@4.12.1
    -   @nhost/nextjs@1.12.1

## 0.7.13

### Patch Changes

-   dd0738d5: fix(dashboard): provisioning status polling

## 0.7.12

### Patch Changes

-   b21222b3: chore(deps): update dependency @types/node to v16
-   9e0486a3: fix(dashboard): close modals when navigating
-   Updated dependencies [b21222b3]
-   Updated dependencies [65687bee]
-   Updated dependencies [54df0df4]
    -   @nhost/nextjs@1.12.0
    -   @nhost/react-apollo@4.12.0

## 0.7.11

### Patch Changes

-   d6527122: fix(dashboard): use correct service URLs

## 0.7.10

### Patch Changes

-   Updated dependencies [57db5b83]
    -   @nhost/nextjs@1.11.0
    -   @nhost/nhost-js@1.7.0
    -   @nhost/react@0.17.0
    -   @nhost/react-apollo@4.11.0

## 0.7.9

### Patch Changes

- a6d31dc2: fix(dashboard): don't break the UI when project is not
loaded yet

## 0.7.8

### Patch Changes

- 7f251111: Use `NhostProvider` instead of `NhostReactProvider` and
`NhostNextProvider`

    `NhostReactProvider` and `NhostNextProvider` are now deprecated

-   f4d70f88: fix(dashboard): do not break when region is nullish

- 4a9471cc: Windows Live Provider displayed link updated to match
backend url

- 594488e4: fix(dashboard): do not show error when submitting Apple
provider settings

-   Updated dependencies [7f251111]
    -   @nhost/nextjs@1.10.0
    -   @nhost/react@0.16.0
    -   @nhost/react-apollo@4.10.0

## 0.7.7

### Patch Changes

-   80b604ad: fix(dashboard): use correct Hasura slug

## 0.7.6

### Patch Changes

-   2d2beb53: fix(dashboard): prevent error on GraphQL page
-   ac8efcbd: chore(dashboard): deprecate old DNS name

## 0.7.5

### Patch Changes

-   132a4f4b: chore(dashboard): remove unused dependencies
- 132a4f4b: chore(deps): synchronize @types/react-dom and @types/react
versions
-   db57572f: fix(dashboard): correct section paddings when no env vars
-   Updated dependencies [132a4f4b]
    -   @nhost/react@0.15.2
    -   @nhost/react-apollo@4.9.2
    -   @nhost/nextjs@1.9.3

## 0.7.4

### Patch Changes

-   34d85e54: chore(deps): update dependency critters to ^0.0.16
- 9b93cf95: chore(deps): update dependency @netlify/functions to ^0.11.0
-   e0439030: chore(deps): update dependency @types/react-dom to v18.0.9
-   Updated dependencies [82124329]
    -   @nhost/nextjs@1.9.2

## 0.7.3

### Patch Changes

-   a1193da4: fix(dashboard): remove character limit from env var inputs

## 0.7.2

### Patch Changes

-   44f13f62: chore(dashboard): cleanup unused files

## 0.7.1

### Patch Changes

- e01cb2ed: chore(dashboard): change settings sidebar menu item density

## 0.7.0

### Minor Changes

- db342f45: chore(dashboard): refactor Roles and Permissions settings
sections
-   8b9fa0b1: feat(dashboard): add Environment Variables page

### Patch Changes

-   Updated dependencies [66b4f3d0]
-   Updated dependencies [2e6923dc]
-   Updated dependencies [ef117c28]
-   Updated dependencies [aebb8225]
    -   @nhost/core@0.9.4
    -   @nhost/nhost-js@1.6.2
    -   @nhost/nextjs@1.9.1
    -   @nhost/react@0.15.1
    -   @nhost/react-apollo@4.9.1

## 0.6.0

### Minor Changes

-   eef9c914: feat(dashboard): add Roles and Permissions page

## 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

-   766cb612: fix(dashboard): correct redirect URL for oauth providers
-   Updated dependencies [53bdc294]
-   Updated dependencies [f2aaff05]
    -   @nhost/nextjs@1.8.3
    -   @nhost/core@0.9.3
    -   @nhost/react@0.14.3
    -   @nhost/nhost-js@1.6.1
    -   @nhost/react-apollo@4.8.3

## 0.4.0

### Minor Changes

-   9211743d: feat(dashboard): migrate Settings page features

## 0.3.0

### Minor Changes

-   73da6a67: fix(dashboard): avoid using BACKEND_URL locally

## 0.2.0

### Minor Changes

-   db118f97: feat(dashboard): generate Docker image

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-02-06 14:36:09 +01:00
David BM
91d5fbba42 fix (dashboard): invalid slug/subdomain should open 404 (#3172)
### **User description**
Fixes #3119


___

### **PR Type**
Bug fix, Enhancement


___

### **Description**
- Fix invalid slug/subdomain to open 404 page

- Disable inaccessible pages in local CLI dashboard

- Improve project page navigation and accessibility

- Enhance not found redirect logic


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>OrgPagesComboBox.tsx</strong><dd><code>Disable
organization pages combo box for non-platform use</code></dd></summary>
<hr>

dashboard/src/components/layout/Header/OrgPagesComboBox.tsx

<li>Import useIsPlatform hook<br> <li> Disable PopoverTrigger when not
on platform


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3172/files#diff-b70a46a4233201c9a2650c930192b4417f35a27303ff5c78872c05a41a92c8ac">+4/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>ProjectPagesComboBox.tsx</strong><dd><code>Enhance
project pages combo box with platform-specific
disabling</code></dd></summary>
<hr>

dashboard/src/components/layout/Header/ProjectPagesComboBox.tsx

<li>Refactor projectPages to use useMemo<br> <li> Add 'disabled'
property to project page options<br> <li> Disable certain pages based on
isPlatform value


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3172/files#diff-70b3af41358f0a22b83e502409a70a0df15e8946d958dbaee4c32b6ebdb38cf6">+106/-83</a></td>

</tr>
</table></td></tr><tr><td><strong>Bug fix</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>useNotFoundRedirect.ts</strong><dd><code>Improve 404
redirect logic for invalid slugs and subdomains</code></dd></summary>
<hr>


dashboard/src/features/projects/common/hooks/useNotFoundRedirect/useNotFoundRedirect.ts

<li>Add checks for valid organization and project<br> <li> Implement
platform-specific redirect logic<br> <li> Include additional loading
states in redirect decision


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3172/files#diff-837279cf43199053bca09913f62c4af019063a2e8dc7bfb7643ec54b7cecd29d">+41/-10</a>&nbsp;
</td>

</tr>
</table></td></tr><tr><td><strong>Documentation</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>heavy-eyes-smile.md</strong><dd><code>Add changeset for
dashboard improvements</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></summary>
<hr>

.changeset/heavy-eyes-smile.md

<li>Add changeset for @nhost/dashboard package<br> <li> Describe fix for
invalid slug/subdomain and local CLI dashboard


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3172/files#diff-9a0418cf1a2622ce3bbec8df535fa44974433329d5386f0a90eee7e60167b1c6">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-06 14:30:00 +01:00
David Barroso
498363db25 chore (dashboard): regenerate graphql bindings (#3188)
### **PR Type**
Enhancement


___

### **Description**
- Updated GraphQL bindings in dashboard

- Changed postgres config from optional to required

- Removed 'Graphite' from Software_Type_Enum

- Modified ConfigPostgres and related types


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>graphql.ts</strong><dd><code>Update GraphQL types and
queries for Postgres</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

dashboard/src/utils/__generated__/graphql.ts

<li>Changed <code>postgres</code> from optional to required in
ConfigConfig<br> <li> Updated ConfigPostgres and related types<br> <li>
Removed 'Graphite' from Software_Type_Enum<br> <li> Modified query and
mutation types to reflect changes


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3188/files#diff-fbd5db84b560b1c91675004448c6c7fa0dcbfb28b9eb05d53b03e6cb7b83ebac">+12/-14</a>&nbsp;
</td>

</tr>
</table></td></tr><tr><td><strong>Documentation</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>perfect-hairs-wave.md</strong><dd><code>Add changeset
for GraphQL bindings update</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></summary>
<hr>

.changeset/perfect-hairs-wave.md

<li>Added changeset file for patch version bump<br> <li> Described
change as regenerating GraphQL bindings


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3188/files#diff-a0885845ed7d68d0b6922f52b710db28275617df1ae791a850f16f58d90a6097">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-06 14:08:33 +01:00
robertkasza
8c2779930b fix (dashboard): fetch allowed roles from the project's auth.roles table (#3179)
### **User description**
fetch allowed roles from the project's auth.roles table


___

### **PR Type**
Enhancement, Bug fix


___

### **Description**
- Fetch allowed roles from project's auth.roles table

- Implement useAllowedUserRoles custom hook

- Update UsersBody component to use new hook

- Add GraphQL query for fetching allowed roles


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>index.ts</strong><dd><code>Export new
useAllowedUserRoles hook</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

dashboard/src/features/orgs/hooks/useAllowedUserRoles/index.ts

- Export useAllowedUserRoles hook


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3179/files#diff-d6a91d913b67d5e22fab8ee1ad0998e13e23be19fee0bff8329bd2e7e49d3ac4">+1/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>useAllowedUserRoles.ts</strong><dd><code>Implement
useAllowedUserRoles custom hook</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></summary>
<hr>


dashboard/src/features/orgs/hooks/useAllowedUserRoles/useAllowedUserRoles.ts

<li>Implement useAllowedUserRoles custom hook<br> <li> Fetch auth roles
from remote application<br> <li> Process and return allowed user roles


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3179/files#diff-aa27d882a97f3ae9286266919c70218e5df29b1419769d8cd2886e80d4e95c04">+17/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>UsersBody.tsx</strong><dd><code>Refactor UsersBody to
use new useAllowedUserRoles hook</code>&nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>


dashboard/src/features/orgs/projects/authentication/users/components/UsersBody/UsersBody.tsx

<li>Replace useGetRolesPermissionsQuery with useAllowedUserRoles<br>
<li> Remove unused imports and variables<br> <li> Simplify code by using
new hook


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3179/files#diff-33b33017f46d5cb8e4652c183619f3dc86c5377125ed3a612888739e0da22484">+3/-25</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>graphql.ts</strong><dd><code>Add generated types for
new allowed roles query</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

dashboard/src/utils/__generated__/graphql.ts

<li>Add GetRemoteAppAllowedRolesQuery type and related functions<br>
<li> Generate GraphQL hooks for new query


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3179/files#diff-fbd5db84b560b1c91675004448c6c7fa0dcbfb28b9eb05d53b03e6cb7b83ebac">+42/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>getAllowedRoles.graphql</strong><dd><code>Add GraphQL
query for fetching allowed roles</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>

dashboard/src/gql/remote-app/getAllowedRoles.graphql

- Add GraphQL query to fetch allowed roles from authRoles table


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3179/files#diff-442c2503cc0e462029c952852520773a1ea1a8526949398ce59f2535d7131aec">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr><tr><td><strong>Documentation</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>tall-houses-mix.md</strong><dd><code>Add changeset for
allowed roles fix</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

.changeset/tall-houses-mix.md

<li>Add changeset for minor version bump<br> <li> Describe fix for
fetching allowed roles


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3179/files#diff-a7caacd8e8e971694232815f20297858ecefe39e86e80190e776b5fb47652191">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-05 17:28:16 +01:00
robertkasza
0aa27a2fd1 feat (dashboard): allow to create new org from the transfer project dialog (#3169)
### **User description**
feat (dashboard): allow to create new org from the transfer project
dialog

___

### **PR Type**
Enhancement, Bug fix


___

### **Description**
- Allow creating new org from transfer project dialog

- Improve upgrade to pro button functionality

- Add unit tests for new features

- Fix error after redirecting from checkout


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><details><summary>15
files</summary><table>
<tr>
<td><strong>OpenTransferDialogButton.tsx</strong><dd><code>Add new
OpenTransferDialogButton component</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-e86a4216c48c54e1a2652ff3609575d6bf193d085ad42849a85dc6d4abba950c">+40/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>index.ts</strong><dd><code>Export OpenTransferDialogButton
component</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-c1fd683ba66a0e7f6a4622051d9e548ee32f215f29bcf0dd22b0827f8c38bc12">+1/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>UpgradeToProBanner.tsx</strong><dd><code>Refactor
UpgradeToProBanner to use OpenTransferDialogButton</code></dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-f38fc14d24ec6ee22f9a100cc473c641dcdc66284d41d030c456bf505094ed9d">+5/-28</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>CreateOrgFormDialog.tsx</strong><dd><code>Enhance
CreateOrgDialog with new props and functionality</code>&nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-9a1ed9e851328393b81356d80ade3509016aa55c254ed1f4deb692b0bd96f02e">+47/-18</a>&nbsp;
</td>

</tr>

<tr>
<td><strong>FinishOrgCreationProcess.tsx</strong><dd><code>Add new
FinishOrgCreationProcess component</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-7602855e6aaab1dd3810c866acbedd5b9eb22c271806969eb9a3435f1c76ca8d">+53/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>index.ts</strong><dd><code>Export FinishOrgCreationProcess
component</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-a9faaff5f8d044125799178a6e33aa49ebed3aa1aaa8c2261162e2b25e24e0bd">+1/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>FinishOrgCreation.tsx</strong><dd><code>Add new
FinishOrgCreation component</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-bf22866bc3f80e45cdf18035146a8c7be6a38d1f6726b0e28d63879aacd263a4">+24/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>TransferProjectDialog.tsx</strong><dd><code>Enhance
TransferProjectDialog with new org creation</code>&nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-b68d4641a67e07a8bf8c14e1f705059c564e1bca53e591783581af27a488d86e">+221/-114</a></td>

</tr>

<tr>
<td><strong>NotificationsTray.tsx</strong><dd><code>Update
NotificationsTray to handle session_id</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-8b559ee1d3176203e8a4e1588924d57944d09d792117ed578b27cd5401ee5d4f">+15/-4</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>index.ts</strong><dd><code>Export useFinishOrgCreation
hook</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-de59152f45a5fbf6b999d3cd9e4e14eefbde27e4cccf0d6ed6da5e2956db24ec">+1/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
<td><strong>useFinishOrgCreation.ts</strong><dd><code>Add new
useFinishOrgCreation custom hook</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-3b8bf7608ab36d8ab0df895e400f0d2d9e29fad2055b40b33d8d9912a27c99c3">+92/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>OverviewTopBar.tsx</strong><dd><code>Add
UpgradeProjectDialog to OverviewTopBar</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-560ae107ed8e458fa4b4a226b9f5c24e24b042b5f9bcea9317c78e75929faa4b">+20/-15</a>&nbsp;
</td>

</tr>

<tr>
<td><strong>UpgradeProjectDialog.tsx</strong><dd><code>Add new
UpgradeProjectDialog component</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-7bfab4ad088dbc503c1304f5620e22e02f70602bf14ba6b495969b882b2eb30e">+20/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>utils.ts</strong><dd><code>Add isEmptyValue and
isNotEmptyValue utilities</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-57035bfd3b91de326fec3e5a0bf19487f03130a9a09dc3e428c79f556677081b">+17/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>verify.tsx</strong><dd><code>Refactor verify page to use
FinishOrgCreationProcess</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-5fa0ea2519bed6649a8aa98826526945868bd7a925c5ce5edb3fd14e81273947">+24/-104</a></td>

</tr>

</table></details></td></tr><tr><td><strong>Tests</strong></td><td><details><summary>5
files</summary><table>
<tr>
<td><strong>TransferProjectDialog.test.tsx</strong><dd><code>Add unit
tests for TransferProjectDialog</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-d4ebdb8af76a7c9e73606708718c3448445545259ad553d73b6d322408e3eb8c">+233/-0</a>&nbsp;
</td>

</tr>

<tr>
<td><strong>NotificationsTray.test.tsx</strong><dd><code>Add unit tests
for NotificationsTray</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-727f6debec6a102557407e55c56363e0c75486e30a732158f85c81ada892f77c">+167/-0</a>&nbsp;
</td>

</tr>

<tr>
<td><strong>utils.test.ts</strong><dd><code>Add unit tests for
isEmptyValue utility</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-d85d96942b9d8ae1eae8781e4f092ee9c8183affd76669a6195df713bc801184">+35/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>setupTests.ts</strong><dd><code>Mock ResizeObserver in test
setup</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-20b15fc9d6987586d0a853c077a4aff66b005fdb2e2b99bb5eb494d4c8c38366">+11/-1</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
<td><strong>mocks.ts</strong><dd><code>Add mock data for
organizations</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-d1ef12c0f15123bb4e23a0c513fc3d9b5c16af421c71c2909fde3717e09a9d89">+53/-0</a>&nbsp;
&nbsp; </td>

</tr>
</table></details></td></tr><tr><td><strong>Additional
files</strong></td><td><details><summary>8 files</summary><table>
<tr>
  <td><strong>shiny-feet-rest.md</strong></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-a358ec02ec88d2af39c757f5cb97adcd184ba2614974df53dcb358591b6ca8d0">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
  <td><strong>settings.json</strong></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-5ea4d30be0c6c4cf5c0f1980f0dfe7cd7bdecee565746acb5ec90b0f79ff9314">+1/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>

<tr>
  <td><strong>getOrganizationQuery.ts</strong></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-8a0d854ee3a00b7a8b6661eb8008f3fe2140190fc6543a9674d287f786466d21">+22/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td><strong>getProjectQuery.ts</strong></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-01bab55f0611d27001640c4215cb6d97f8e2b1d45bc56e519d78b282a12c05e7">+12/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td><strong>organizationRequests.ts</strong></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-3cf4d908676a8050fe83c1bf53a57e6577a24fcae13b142ada89da7072d0975e">+22/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td><strong>prefetchNewAppQuery.ts</strong></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-0a3a444a14b5f5495ef86c90f200a3a672732770e90d4b7206468e2ac265d9fe">+73/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td><strong>testUtils.tsx</strong></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-6ebbd73e167641a1706f1b8d30b00569336d10f3c2ab7626d81e639015383e5e">+50/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td><strong>tsconfig.test.json</strong></td>
<td><a
href="https://github.com/nhost/nhost/pull/3169/files#diff-e7bc653278c33281fda4e64da0f34c8c613b99891a16611366edc1c05870a935">+1/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></details></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-05 17:04:18 +01:00
David BM
8656749e5a fix (dashboard CI): e2e tests teardown (#3186)
### **PR Type**
Tests, Enhancement


___

### **Description**
- Added new e2e tests for database permissions.

- Implemented a new teardown process for database cleanup.

- Removed global teardown script and updated configuration.

- Enhanced utility functions for test operations.


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Tests</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>permissions-table.test.ts</strong><dd><code>Add e2e
tests for database permissions</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

dashboard/e2e/database/permissions-table.test.ts

<li>Added tests for creating tables with role permissions.<br> <li>
Included tests for custom checks on row selection.<br> <li> Utilized
Playwright for browser automation in tests.


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3186/files#diff-f4b586f5b8f3bb97ddf64f8f38c461ac0424e101789f61e325d1b80bb8dc1047">+149/-0</a>&nbsp;
</td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>database.teardown.ts</strong><dd><code>Implement
database cleanup teardown script</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></summary>
<hr>

dashboard/e2e/teardown/database.teardown.ts

<li>Implemented new teardown script for database cleanup.<br> <li>
Automated table deletion using SQL in Playwright.<br> <li> Set up
browser context for teardown operations.


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3186/files#diff-4c0d8019f6c1586d9dc41b89d10e9a71f5913559112fdf6eed38094d832a126d">+61/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>global-teardown.ts</strong><dd><code>Remove global
teardown script</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></summary>
<hr>

dashboard/global-teardown.ts

<li>Removed global teardown script.<br> <li> Deprecated old teardown
approach using Hasura.


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3186/files#diff-1ee3d64258c498cdfa30665ec61605ab817622c7dae2a09bd4b6b23606c13e9f">+0/-67</a>&nbsp;
&nbsp; </td>

</tr>
</table></td></tr><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>utils.ts</strong><dd><code>Add utility function for
permission button clicks</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></summary>
<hr>

dashboard/e2e/utils.ts

<li>Added utility function for clicking permission buttons.<br> <li>
Enhanced test utilities for role-based operations.


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3186/files#diff-490448aa83585151d8c61d698273c43486fdcac6a5d28a9b7e5be2729bbffd12">+20/-0</a>&nbsp;
&nbsp; </td>

</tr>
</table></td></tr><tr><td><strong>Configuration
changes</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>playwright.config.ts</strong><dd><code>Update
Playwright configuration for new teardown</code>&nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

dashboard/playwright.config.ts

<li>Updated Playwright config to remove global teardown.<br> <li> Added
new teardown project configuration.


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3186/files#diff-3ce7004405593146d0b9c501fc50a6a5ae2da8bb48b57dee2faf79ca9c09cf62">+5/-1</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-05 16:08:00 +01:00
robertkasza
d097eb8feb fix (dashboard): fix edit permission form cannot be saved (#3183)
### **PR Type**
Bug fix


___

### **Description**
- Fix edit permission form saving issue

- Update validation schema for rule groups

- Modify operator validation in EditPermissionsForm

- Add new development script for dashboard


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Bug
fix</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>validationSchemas.ts</strong><dd><code>Update
validation schema for EditPermissionsForm</code>&nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>


dashboard/src/features/orgs/projects/database/dataGrid/components/EditPermissionsForm/validationSchemas.ts

<li>Updated operator validation message<br> <li> Added custom test for
operator in ruleGroupSchema<br> <li> Implemented conditional validation
for operator based on filter <br>presence


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3183/files#diff-98f990165c3aca93bc01808ac0dcbde7b347ad2fd86fe52311d306a2fb3aaf0f">+19/-2</a>&nbsp;
&nbsp; </td>

</tr>
</table></td></tr><tr><td><strong>Documentation</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>curly-toys-peel.md</strong><dd><code>Add changeset for
dashboard patch</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

.changeset/curly-toys-peel.md

<li>Added changeset file for @nhost/dashboard patch<br> <li> Described
fix for edit permission form saving issue


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3183/files#diff-ee0a00268ee800059ef11e5531cc42195a54f4b8779466be210968e2bb2e30f3">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>package.json</strong><dd><code>Add development script
for dashboard</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

package.json

<li>Added new script 'dev:dashboard' for running dashboard in
development <br>mode


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3183/files#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519">+1/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
2025-02-05 10:05:51 +01:00
159 changed files with 3230 additions and 2206 deletions

View File

@@ -30,6 +30,14 @@ runs:
uses: actions/setup-node@v3
with:
node-version: 20
- shell: bash
name: Use Latest Corepack
run: |
echo "Before: corepack version => $(corepack --version || echo 'not installed')"
npm install -g corepack@latest
echo "After : corepack version => $(corepack --version)"
corepack enable
pnpm --version
- shell: bash
name: Install packages
run: pnpm install --frozen-lockfile

View File

@@ -28,7 +28,7 @@ jobs:
path: packages/nhost-js
start: true
- name: should be running
run: curl -sSf 'https://local.hasura.nhost.run' > /dev/null
run: curl -sSf 'https://local.hasura.local.nhost.run' > /dev/null
stop:
runs-on: ubuntu-latest
@@ -59,7 +59,7 @@ jobs:
start: true
- name: should find the injected hasura-auth version
run: |
VERSION=$(curl -sSf 'https://local.auth.nhost.run/v1/version')
VERSION=$(curl -sSf 'https://local.auth.local.nhost.run/v1/version')
EXPECTED_VERSION='{"version":"v0.20.1"}'
if [ "$VERSION" != "$EXPECTED_VERSION" ]; then
echo "Expected version $EXPECTED_VERSION but got $VERSION"

2
.gitignore vendored
View File

@@ -63,3 +63,5 @@ out/
# Nix
.envrc
.direnv/
/.vscode/

View File

@@ -4,7 +4,7 @@
# Nhost
<a href="https://docs.nhost.io/#quickstart">Quickstart</a>
<a href="https://docs.nhost.io/introduction#quick-start-guides">Quickstart</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
<a href="http://nhost.io/">Website</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
@@ -36,7 +36,7 @@ Nhost consists of open source software:
- Authentication: [Hasura Auth](https://github.com/nhost/hasura-auth/)
- Storage: [Hasura Storage](https://github.com/nhost/hasura-storage)
- Serverless Functions: Node.js (JavaScript and TypeScript)
- [Nhost CLI](https://docs.nhost.io/cli) for local development
- [Nhost CLI](https://docs.nhost.io/development/cli/overview) for local development
## Architecture of Nhost
@@ -89,12 +89,12 @@ await nhost.graphql.request(`{
Nhost is frontend agnostic, which means Nhost works with all frontend frameworks.
<div align="center">
<a href="https://docs.nhost.io/platform/quickstarts/nextjs"><img src="assets/nextjs.svg"/></a>
<a href="https://docs.nhost.io/guides/quickstarts/nextjs"><img src="assets/nextjs.svg"/></a>
<a href="https://docs.nhost.io/reference/javascript"><img src="assets/nuxtjs.svg"/></a>
<a href="https://docs.nhost.io/platform/quickstarts/react"><img src="assets/react.svg"/></a>
<a href="https://docs.nhost.io/guides/quickstarts/react"><img src="assets/react.svg"/></a>
<a href="https://docs.nhost.io/reference/javascript"><img src="assets/react-native.svg"/></a>
<a href="https://docs.nhost.io/reference/javascript"><img src="assets/svelte.svg"/></a>
<a href="https://docs.nhost.io/platform/quickstarts/vue"><img src="assets/vuejs.svg"/></a>
<a href="https://docs.nhost.io/guides/quickstarts/vue"><img src="assets/vuejs.svg"/></a>
</div>
# Resources
@@ -140,7 +140,7 @@ This repository, and most of our other open source projects, are licensed under
Here are some ways of contributing to making Nhost better:
- **[Try out Nhost](https://docs.nhost.io/get-started/quick-start)**, and think of ways to make the service better. Let us know here on GitHub.
- **[Try out Nhost](https://docs.nhost.io/introduction)**, and think of ways to make the service better. Let us know here on GitHub.
- Join our [Discord](https://discord.com/invite/9V7Qb2U) and connect with other members to share and learn from.
- Send a pull request to any of our [open source repositories](https://github.com/nhost) on Github. Check our [contribution guide](https://github.com/nhost/nhost/blob/main/CONTRIBUTING.md) and our [developers guide](https://github.com/nhost/nhost/blob/main/DEVELOPERS.md) for more details about how to contribute. We're looking forward to your contribution!

View File

@@ -3,18 +3,19 @@ NEXT_PUBLIC_ENV=dev
NEXT_PUBLIC_NHOST_PLATFORM=false
# Environment Variables for Self Hosting and Local Development
NEXT_PUBLIC_NHOST_AUTH_URL=https://local.auth.nhost.run/v1
NEXT_PUBLIC_NHOST_FUNCTIONS_URL=https://local.functions.nhost.run/v1
NEXT_PUBLIC_NHOST_GRAPHQL_URL=https://local.graphql.nhost.run/v1
NEXT_PUBLIC_NHOST_STORAGE_URL=https://local.storage.nhost.run/v1
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL=https://local.hasura.nhost.run
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL=https://local.hasura.nhost.run/v1/migrations
NEXT_PUBLIC_NHOST_HASURA_API_URL=https://local.hasura.nhost.run
NEXT_PUBLIC_NHOST_AUTH_URL=https://local.auth.nhost.local.run/v1
NEXT_PUBLIC_NHOST_FUNCTIONS_URL=https://local.functions.local.nhost.run/v1
NEXT_PUBLIC_NHOST_GRAPHQL_URL=https://local.graphql.local.nhost.run/v1
NEXT_PUBLIC_NHOST_STORAGE_URL=https://local.storage.local.nhost.run/v1
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL=https://local.hasura.local.nhost.run
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL=https://local.hasura.local.nhost.run/v1/migrations
NEXT_PUBLIC_NHOST_HASURA_API_URL=https://local.hasura.local.nhost.run
# Environment Variables when running the Nhost Dashboard against the Nhost Backend
NEXT_PUBLIC_STRIPE_PK=<nhost_stripe_public_key>
NEXT_PUBLIC_GITHUB_APP_INSTALL_URL=<github_app_install_url>
NEXT_PUBLIC_ANALYTICS_WRITE_KEY=<analytics_write_key>
NEXT_PUBLIC_SEGMENT_CDN_URL=<segment_cdn_url>
NEXT_PUBLIC_NHOST_BRAGI_WEBSOCKET=<nhost_bragi_websocket>
NEXT_PUBLIC_ZENDESK_URL=
@@ -22,6 +23,6 @@ NEXT_PUBLIC_ZENDESK_API_KEY=
NEXT_PUBLIC_ZENDESK_USER_EMAIL=
CODEGEN_GRAPHQL_URL=https://local.graphql.nhost.run/v1
CODEGEN_GRAPHQL_URL=https://local.graphql.local.nhost.run/v1
CODEGEN_HASURA_ADMIN_SECRET=nhost-admin-secret
NEXT_PUBLIC_TURNSTILE_SITE_KEY=FIXME

View File

@@ -1,6 +1,6 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.codeActionsOnSave": {
"source.organizeImports": true
"source.organizeImports": "explicit"
}
}

View File

@@ -33,7 +33,7 @@ ENV NEXT_PUBLIC_NHOST_CONFIGSERVER_URL=__NEXT_PUBLIC_NHOST_CONFIGSERVER_URL__
RUN yarn global add pnpm@9.15.0
COPY .gitignore .gitignore
COPY --from=pruner /app/out/json/ .
COPY --from=pruner /app/out/pnpm-*.yaml .
COPY --from=pruner /app/out/pnpm-*.yaml ./
RUN pnpm install --frozen-lockfile
COPY --from=pruner /app/out/full/ .

View File

@@ -51,13 +51,13 @@ You can connect the Nhost Dashboard to your locally running backend by setting t
```bash
NEXT_PUBLIC_ENV=dev
NEXT_PUBLIC_NHOST_PLATFORM=false
NEXT_PUBLIC_NHOST_AUTH_URL=https://local.auth.nhost.run/v1
NEXT_PUBLIC_NHOST_FUNCTIONS_URL=https://local.functions.nhost.run/v1
NEXT_PUBLIC_NHOST_GRAPHQL_URL=https://local.graphql.nhost.run/v1
NEXT_PUBLIC_NHOST_STORAGE_URL=https://local.storage.nhost.run/v1
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL=https://local.hasura.nhost.run
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL=https://local.hasura.nhost.run/v1/migrations
NEXT_PUBLIC_NHOST_HASURA_API_URL=https://local.hasura.nhost.run
NEXT_PUBLIC_NHOST_AUTH_URL=https://local.auth.local.nhost.run/v1
NEXT_PUBLIC_NHOST_FUNCTIONS_URL=https://local.functions.local.nhost.run/v1
NEXT_PUBLIC_NHOST_GRAPHQL_URL=https://local.graphql.local.nhost.run/v1
NEXT_PUBLIC_NHOST_STORAGE_URL=https://local.storage.local.nhost.run/v1
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL=https://local.hasura.local.nhost.run
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL=https://local.hasura.local.nhost.run/v1/migrations
NEXT_PUBLIC_NHOST_HASURA_API_URL=https://local.hasura.local.nhost.run
```
This will connect the Nhost Dashboard to your locally running Nhost backend.

View File

@@ -0,0 +1,149 @@
import { TEST_ORGANIZATION_SLUG, TEST_PROJECT_SUBDOMAIN } from '@/e2e/env';
import {
clickPermissionButton,
navigateToProject,
prepareTable,
} from '@/e2e/utils';
import { faker } from '@faker-js/faker';
import type { Page } from '@playwright/test';
import { expect, test } from '@playwright/test';
import { snakeCase } from 'snake-case';
let page: Page;
test.beforeAll(async ({ browser }) => {
page = await browser.newPage();
});
test.beforeEach(async () => {
await page.goto('/');
await navigateToProject({
page,
orgSlug: TEST_ORGANIZATION_SLUG,
projectSubdomain: TEST_PROJECT_SUBDOMAIN,
});
const databaseRoute = `/orgs/${TEST_ORGANIZATION_SLUG}/projects/${TEST_PROJECT_SUBDOMAIN}/database/browser/default`;
await page.goto(databaseRoute);
await page.waitForURL(databaseRoute);
});
test.afterAll(async () => {
await page.close();
});
test('should create a table with role permissions to select row', async () => {
await page.getByRole('button', { name: /new table/i }).click();
await expect(page.getByText(/create a new table/i)).toBeVisible();
const tableName = snakeCase(faker.lorem.words(3));
await prepareTable({
page,
name: tableName,
primaryKey: 'id',
columns: [
{ name: 'id', type: 'uuid', defaultValue: 'gen_random_uuid()' },
{ name: 'title', type: 'text' },
],
});
// create table
await page.getByRole('button', { name: /create/i }).click();
await page.waitForURL(
`/orgs/${TEST_ORGANIZATION_SLUG}/projects/${TEST_PROJECT_SUBDOMAIN}/database/browser/default/public/${tableName}`,
);
await expect(
page.getByRole('link', { name: tableName, exact: true }),
).toBeVisible();
// Press three horizontal dots more options button next to the table name
await page
.locator(`li:has-text("${tableName}") #table-management-menu button`)
.click();
await page.getByRole('menuitem', { name: /edit permissions/i }).click();
await clickPermissionButton({ page, role: 'user', permission: 'Select' });
await page.getByLabel('Without any checks').click();
await page.getByRole('button', { name: /select all/i }).click();
await page.getByRole('button', { name: /save/i }).click();
await expect(
page.getByText(/permission has been saved successfully/i),
).toBeVisible();
});
test('should create a table with role permissions and a custom check to select rows', async () => {
await page.getByRole('button', { name: /new table/i }).click();
await expect(page.getByText(/create a new table/i)).toBeVisible();
const tableName = snakeCase(faker.lorem.words(3));
await prepareTable({
page,
name: tableName,
primaryKey: 'id',
columns: [
{ name: 'id', type: 'uuid', defaultValue: 'gen_random_uuid()' },
{ name: 'title', type: 'text' },
],
});
// create table
await page.getByRole('button', { name: /create/i }).click();
await page.waitForURL(
`/orgs/${TEST_ORGANIZATION_SLUG}/projects/${TEST_PROJECT_SUBDOMAIN}/database/browser/default/public/${tableName}`,
);
await expect(
page.getByRole('link', { name: tableName, exact: true }),
).toBeVisible();
// Press three horizontal dots more options button next to the table name
await page
.locator(`li:has-text("${tableName}") #table-management-menu button`)
.click();
await page.getByRole('menuitem', { name: /edit permissions/i }).click();
await clickPermissionButton({ page, role: 'user', permission: 'Select' });
await page.getByLabel('With custom check').click();
// await page.getByRole('combobox', { name: /select a column/i }).click();
await page.getByText('Select a column', { exact: true }).click();
const columnSelector = page.locator('input[role="combobox"]');
await columnSelector.fill('id');
await columnSelector.press('Enter');
await expect(page.getByText(/_eq/i)).toBeVisible();
// limit on number of rows fetched per request.
await page.locator('#limit').fill('100');
await page.getByText('Select variable...', { exact: true }).click();
const variableSelector = await page.locator('input[role="combobox"]');
await variableSelector.fill('X-Hasura-User-Id');
await variableSelector.press('Enter');
await page.getByRole('button', { name: /select all/i }).click();
await page.getByRole('button', { name: /save/i }).click();
await expect(
page.getByText(/permission has been saved successfully/i),
).toBeVisible();
});

View File

@@ -0,0 +1,61 @@
import {
TEST_DASHBOARD_URL,
TEST_ORGANIZATION_SLUG,
TEST_PROJECT_SUBDOMAIN,
} from '@/e2e/env';
import { navigateToProject } from '@/e2e/utils';
import { type Page, expect, test as teardown } from '@playwright/test';
let page: Page;
teardown.beforeAll(async ({ browser }) => {
const context = await browser.newContext({
baseURL: TEST_DASHBOARD_URL,
storageState: 'e2e/.auth/user.json',
});
page = await context.newPage();
});
teardown.beforeEach(async () => {
await page.goto('/');
await navigateToProject({
page,
orgSlug: TEST_ORGANIZATION_SLUG,
projectSubdomain: TEST_PROJECT_SUBDOMAIN,
});
const databaseRoute = `/orgs/${TEST_ORGANIZATION_SLUG}/projects/${TEST_PROJECT_SUBDOMAIN}/database/browser/default`;
await page.goto(databaseRoute);
await page.waitForURL(databaseRoute);
});
teardown.afterAll(async () => {
await page.close();
});
teardown('clean up database tables', async () => {
await page.getByRole('link', { name: /sql editor/i }).click();
await page.waitForURL(
`/orgs/${TEST_ORGANIZATION_SLUG}/projects/${TEST_PROJECT_SUBDOMAIN}/database/browser/default/editor`,
);
const inputField = page.locator('[contenteditable]');
await inputField.fill(`
DO $$ DECLARE
tablename text;
BEGIN
FOR tablename IN
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public'
LOOP
EXECUTE 'DROP TABLE IF EXISTS public.' || quote_ident(tablename) || ' CASCADE';
END LOOP;
END $$;
`);
await page.locator('button[type="button"]', { hasText: /run/i }).click();
await expect(page.getByText(/success/i)).toBeVisible();
});

View File

@@ -191,3 +191,23 @@ export function generateTestEmail(prefix: string = 'Nhost_Test_') {
return [prefix, email].join('');
}
export async function clickPermissionButton({
page,
role,
permission,
}: {
page: Page;
role: string;
permission: 'Insert' | 'Select' | 'Update' | 'Delete';
}) {
const permissionIndex =
['Insert', 'Select', 'Update', 'Delete'].indexOf(permission) + 1;
await page
.locator('tr', { hasText: role })
.locator('td')
.nth(permissionIndex)
.locator('button')
.click();
}

View File

@@ -1,67 +0,0 @@
import {
TEST_DASHBOARD_URL,
TEST_ORGANIZATION_SLUG,
TEST_PROJECT_ADMIN_SECRET,
TEST_PROJECT_SUBDOMAIN,
} from '@/e2e/env';
import { navigateToProject } from '@/e2e/utils';
import { chromium } from '@playwright/test';
async function globalTeardown() {
const browser = await chromium.launch({ slowMo: 1000 });
const context = await browser.newContext({
baseURL: TEST_DASHBOARD_URL,
storageState: 'e2e/.auth/user.json',
});
const page = await context.newPage();
await navigateToProject({
page,
orgSlug: TEST_ORGANIZATION_SLUG,
projectSubdomain: TEST_PROJECT_SUBDOMAIN,
});
const pagePromise = context.waitForEvent('page');
await page.getByRole('link', { name: /hasura/i }).click();
await page.getByRole('link', { name: /open hasura/i }).click();
const hasuraPage = await pagePromise;
await hasuraPage.waitForLoadState();
const adminSecretInput = hasuraPage.getByPlaceholder(/enter admin-secret/i);
// note: a more ideal way would be to paste from clipboard, but Playwright
// doesn't support that yet
await adminSecretInput.fill(TEST_PROJECT_ADMIN_SECRET);
await adminSecretInput.press('Enter');
// note: getByRole doesn't work here
await hasuraPage.locator('a', { hasText: /data/i }).nth(0).click();
await hasuraPage.locator('[data-test="sql-link"]').click();
// Set the value of the Ace code editor using JavaScript evaluation in the browser context
await hasuraPage.evaluate(() => {
const editor = ace.edit('raw_sql');
editor.setValue(`
DO $$ DECLARE
tablename text;
BEGIN
FOR tablename IN
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public'
LOOP
EXECUTE 'DROP TABLE IF EXISTS public.' || quote_ident(tablename) || ' CASCADE';
END LOOP;
END $$;
`);
});
await hasuraPage.getByRole('button', { name: /run!/i }).click();
await hasuraPage.getByText(/sql executed!/i).waitFor();
}
export default globalTeardown;

View File

@@ -1,5 +1,5 @@
schema:
- https://local.graphql.nhost.run/v1:
- https://local.graphql.local.nhost.run/v1:
headers:
x-hasura-admin-secret: nhost-admin-secret
generates:

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/dashboard",
"version": "2.18.0",
"version": "2.21.0",
"private": true,
"scripts": {
"preinstall": "npx only-allow pnpm",
@@ -56,7 +56,7 @@
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@segment/snippet": "^4.16.2",
"@segment/analytics-next": "^1.77.0",
"@stripe/react-stripe-js": "^2.6.2",
"@stripe/stripe-js": "^1.54.2",
"@tailwindcss/forms": "^0.5.7",
@@ -67,7 +67,6 @@
"@uiw/codemirror-theme-bbedit": "^4.22.2",
"@uiw/codemirror-theme-github": "^4.21.25",
"@uiw/react-codemirror": "^4.21.25",
"analytics-node": "^6.2.0",
"bcryptjs": "^2.4.3",
"class-variance-authority": "^0.7.0",
"clsx": "^1.2.1",

View File

@@ -15,7 +15,6 @@ export default defineConfig({
retries: process.env.CI ? 2 : 0,
workers: 1,
reporter: 'html',
globalTeardown: require.resolve('./global-teardown'),
use: {
actionTimeout: 0,
trace: 'on-first-retry',
@@ -28,6 +27,11 @@ export default defineConfig({
{
name: 'setup',
testMatch: ['**/setup/*.setup.ts'],
teardown: 'teardown',
},
{
name: 'teardown',
testMatch: ['**/teardown/*.teardown.ts'],
},
{
name: 'chromium',

View File

@@ -0,0 +1,30 @@
import { useCurrentOrg } from '@/features/orgs/projects/hooks/useCurrentOrg';
import { useProject } from '@/features/orgs/projects/hooks/useProject';
import { analytics } from '@/lib/segment';
import { useRouter } from 'next/router';
import { useEffect } from 'react';
export default function Analytics() {
const router = useRouter();
const { org } = useCurrentOrg();
const { project } = useProject();
useEffect(() => {
const customProperties = {
organizationSlug: org?.slug || '',
projectSubdomain: project?.subdomain || '',
};
analytics.page(customProperties);
const handleRouteChange = () => analytics.page(customProperties);
router.events.on('routeChangeComplete', handleRouteChange);
return () => {
router.events.off('routeChangeComplete', handleRouteChange);
};
}, [router.events, org?.slug, project?.subdomain]);
return null;
}

View File

@@ -0,0 +1,40 @@
import { useDialog } from '@/components/common/DialogProvider';
import { Button } from '@/components/ui/v2/Button';
import { Text } from '@/components/ui/v2/Text';
import { useIsCurrentUserOwner } from '@/features/orgs/projects/common/hooks/useIsCurrentUserOwner';
interface Props {
buttonText?: string;
onClick?: () => void;
}
function OpenTransferDialogButton({ buttonText, onClick }: Props) {
const text = buttonText ?? 'Transfer Project';
const isOwner = useIsCurrentUserOwner();
const { openAlertDialog } = useDialog();
const handleClick = () => {
if (isOwner) {
onClick();
} else {
openAlertDialog({
title: "You can't migrate this project",
payload: (
<Text variant="subtitle1" component="span">
Ask an owner of this organization to migrate the project.
</Text>
),
props: {
secondaryButtonText: 'I understand',
hidePrimaryAction: true,
},
});
}
};
return (
<Button className="max-w-xs lg:w-auto" onClick={handleClick}>
{text}
</Button>
);
}
export default OpenTransferDialogButton;

View File

@@ -0,0 +1 @@
export { default as OpenTransferDialogButton } from './OpenTransferDialogButton';

View File

@@ -1,14 +1,13 @@
import { useDialog } from '@/components/common/DialogProvider';
import { NhostIcon } from '@/components/presentational/NhostIcon';
import { Box } from '@/components/ui/v2/Box';
import { Button } from '@/components/ui/v2/Button';
import { ArrowSquareOutIcon } from '@/components/ui/v2/icons/ArrowSquareOutIcon';
import { Link } from '@/components/ui/v2/Link';
import { Text } from '@/components/ui/v2/Text';
import { TransferProjectDialog } from '@/features/orgs/components/common/TransferProjectDialog';
import { useIsCurrentUserOwner } from '@/features/orgs/projects/common/hooks/useIsCurrentUserOwner';
import { useState } from 'react';
import { OpenTransferDialogButton } from '@/components/common/OpenTransferDialogButton';
import Image from 'next/image';
import { type ReactNode } from 'react';
@@ -21,11 +20,11 @@ export default function UpgradeToProBanner({
title,
description,
}: UpgradeToProBannerProps) {
const isOwner = useIsCurrentUserOwner();
const { openAlertDialog } = useDialog();
const [transferProjectDialogOpen, setTransferProjectDialogOpen] =
useState(false);
const handleTransferDialogOpen = () => setTransferProjectDialogOpen(true);
return (
<Box
sx={{ backgroundColor: 'primary.light' }}
@@ -51,29 +50,7 @@ export default function UpgradeToProBanner({
</div>
<div className="flex flex-col gap-2 space-y-2 lg:flex-row lg:items-center lg:space-x-2 lg:space-y-0">
<Button
className="max-w-xs lg:w-auto"
onClick={() => {
if (isOwner) {
setTransferProjectDialogOpen(true);
} else {
openAlertDialog({
title: "You can't migrate this project",
payload: (
<Text variant="subtitle1" component="span">
Ask an owner of this organization to migrate the project.
</Text>
),
props: {
secondaryButtonText: 'I understand',
hidePrimaryAction: true,
},
});
}
}}
>
Transfer Project
</Button>
<OpenTransferDialogButton onClick={handleTransferDialogOpen} />
<TransferProjectDialog
open={transferProjectDialogOpen}
setOpen={setTransferProjectDialogOpen}

View File

@@ -18,6 +18,7 @@ import {
PopoverTrigger,
} from '@/components/ui/v3/popover';
import { useIsPlatform } from '@/features/orgs/projects/common/hooks/useIsPlatform';
import { Check, ChevronsUpDown } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
@@ -40,6 +41,8 @@ export default function OrgPagesComboBox() {
asPath,
} = useRouter();
const isPlatform = useIsPlatform();
const pathSegments = useMemo(() => asPath.split('/'), [asPath]);
const orgPageFromUrl = pathSegments[3] || null;
@@ -64,7 +67,7 @@ export default function OrgPagesComboBox() {
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<PopoverTrigger disabled={!isPlatform} asChild>
<Button
variant="ghost"
size="sm"

View File

@@ -32,6 +32,7 @@ import {
PopoverContent,
PopoverTrigger,
} from '@/components/ui/v3/popover';
import { useIsPlatform } from '@/features/orgs/projects/common/hooks/useIsPlatform';
import { cn } from '@/lib/utils';
import { useRouter } from 'next/router';
import { useEffect, useMemo, useState, type ReactElement } from 'react';
@@ -40,88 +41,10 @@ type Option = {
value: string;
label: string;
icon: ReactElement;
disabled: boolean;
};
const projectPages = [
{
label: 'Overview',
value: 'overview',
icon: <HomeIcon className="h-4 w-4" />,
slug: '',
},
{
label: 'Database',
value: 'database',
icon: <DatabaseIcon className="h-4 w-4" />,
slug: '/database/browser/default',
},
{
label: 'GraphQL',
value: 'graphql',
icon: <GraphQLIcon className="h-4 w-4" />,
slug: 'graphql',
},
{
label: 'Hasura',
value: 'hasura',
icon: <HasuraIcon className="h-4 w-4" />,
slug: 'hasura',
},
{
label: 'Auth',
value: 'users',
icon: <UserIcon className="h-4 w-4" />,
slug: 'users',
},
{
label: 'Storage',
value: 'storage',
icon: <StorageIcon className="h-4 w-4" />,
slug: 'storage',
},
{
label: 'Run',
value: 'run',
icon: <ServicesIcon className="h-4 w-4" />,
slug: 'run',
},
{
label: 'AI',
value: 'ai',
icon: <AIIcon className="h-4 w-4" />,
slug: 'ai/auto-embeddings',
},
{
label: 'Deployments',
value: 'deployments',
icon: <RocketIcon className="h-4 w-4" />,
slug: 'deployments',
},
{
label: 'Backups',
value: 'backups',
icon: <CloudIcon className="h-4 w-4" />,
slug: 'backups',
},
{
label: 'Logs',
value: 'logs',
icon: <FileTextIcon className="h-4 w-4" />,
slug: 'logs',
},
{
label: 'Metrics',
value: 'metrics',
icon: <GaugeIcon className="h-4 w-4" />,
slug: 'metrics',
},
{
label: 'Settings',
value: 'settings',
icon: <CogIcon className="h-4 w-4" />,
slug: 'settings',
},
];
type SelectedOption = Omit<Option, 'disabled'>;
export default function ProjectPagesComboBox() {
const {
@@ -130,6 +53,105 @@ export default function ProjectPagesComboBox() {
asPath,
} = useRouter();
const isPlatform = useIsPlatform();
const projectPages = useMemo(
() => [
{
label: 'Overview',
value: 'overview',
icon: <HomeIcon className="h-4 w-4" />,
slug: '',
disabled: false,
},
{
label: 'Database',
value: 'database',
icon: <DatabaseIcon className="h-4 w-4" />,
slug: '/database/browser/default',
disabled: false,
},
{
label: 'GraphQL',
value: 'graphql',
icon: <GraphQLIcon className="h-4 w-4" />,
slug: 'graphql',
disabled: false,
},
{
label: 'Hasura',
value: 'hasura',
icon: <HasuraIcon className="h-4 w-4" />,
slug: 'hasura',
disabled: false,
},
{
label: 'Auth',
value: 'users',
icon: <UserIcon className="h-4 w-4" />,
slug: 'users',
disabled: false,
},
{
label: 'Storage',
value: 'storage',
icon: <StorageIcon className="h-4 w-4" />,
slug: 'storage',
disabled: false,
},
{
label: 'Run',
value: 'run',
icon: <ServicesIcon className="h-4 w-4" />,
slug: 'run',
disabled: false,
},
{
label: 'AI',
value: 'ai',
icon: <AIIcon className="h-4 w-4" />,
slug: 'ai/auto-embeddings',
disabled: false,
},
{
label: 'Deployments',
value: 'deployments',
icon: <RocketIcon className="h-4 w-4" />,
slug: 'deployments',
disabled: !isPlatform,
},
{
label: 'Backups',
value: 'backups',
icon: <CloudIcon className="h-4 w-4" />,
slug: 'backups',
disabled: !isPlatform,
},
{
label: 'Logs',
value: 'logs',
icon: <FileTextIcon className="h-4 w-4" />,
slug: 'logs',
disabled: !isPlatform,
},
{
label: 'Metrics',
value: 'metrics',
icon: <GaugeIcon className="h-4 w-4" />,
slug: 'metrics',
disabled: !isPlatform,
},
{
label: 'Settings',
value: 'settings',
icon: <CogIcon className="h-4 w-4" />,
slug: 'settings',
disabled: false,
},
],
[isPlatform],
);
const pathSegments = useMemo(() => asPath.split('/'), [asPath]);
const projectPageFromUrl = appSubdomain
? pathSegments[5] || 'overview'
@@ -137,9 +159,8 @@ export default function ProjectPagesComboBox() {
const selectedProjectPageFromUrl = projectPages.find(
(item) => item.value === projectPageFromUrl,
);
const [selectedProjectPage, setSelectedProjectPage] = useState<Option | null>(
null,
);
const [selectedProjectPage, setSelectedProjectPage] =
useState<SelectedOption | null>(null);
useEffect(() => {
if (selectedProjectPageFromUrl) {
@@ -155,6 +176,7 @@ export default function ProjectPagesComboBox() {
label: app.label,
value: app.slug,
icon: app.icon,
disabled: app.disabled,
}));
const [open, setOpen] = useState(false);
@@ -188,6 +210,7 @@ export default function ProjectPagesComboBox() {
<CommandItem
key={option.value}
value={option.label}
disabled={option.disabled}
onSelect={() => {
setSelectedProjectPage(option);
setOpen(false);

View File

@@ -20,7 +20,7 @@ import { getUserRoles } from '@/features/projects/roles/settings/utils/getUserRo
import { useRemoteApplicationGQLClient } from '@/hooks/useRemoteApplicationGQLClient';
import type { DialogFormProps } from '@/types/common';
import {
RemoteAppGetUsersDocument,
RemoteAppGetUsersAndAuthRolesDocument,
useGetProjectLocalesQuery,
useGetRolesPermissionsQuery,
useUpdateRemoteAppUserMutation,
@@ -116,7 +116,7 @@ export default function EditUserForm({
const [updateUser] = useUpdateRemoteAppUserMutation({
client: remoteProjectGQLClient,
refetchQueries: [RemoteAppGetUsersDocument],
refetchQueries: [RemoteAppGetUsersAndAuthRolesDocument],
});
const form = useForm<EditUserFormValues>({

View File

@@ -6,7 +6,7 @@ import { Input } from '@/components/ui/v2/Input';
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
import { useRemoteApplicationGQLClient } from '@/hooks/useRemoteApplicationGQLClient';
import type { DialogFormProps } from '@/types/common';
import type { RemoteAppGetUsersQuery } from '@/utils/__generated__/graphql';
import type { RemoteAppGetUsersAndAuthRolesQuery } from '@/utils/__generated__/graphql';
import {
useGetSignInMethodsQuery,
useUpdateRemoteAppUserMutation,
@@ -26,7 +26,7 @@ export interface EditUserPasswordFormProps extends DialogFormProps {
/**
* The selected user.
*/
user: RemoteAppGetUsersQuery['users'][0];
user: RemoteAppGetUsersAndAuthRolesQuery['users'][0];
}
export default function EditUserPasswordForm({

View File

@@ -175,7 +175,23 @@ function CreateOrgForm({ plans, onSubmit, onCancel }: CreateOrgFormProps) {
);
}
export default function CreateOrgDialog() {
interface CreateOrgDialogProps {
hideNewOrgButton?: boolean;
isOpen?: boolean;
onOpenStateChange?: (newState: boolean) => void;
redirectUrl?: string;
}
function isPropSet(prop: any) {
return prop !== undefined;
}
export default function CreateOrgDialog({
hideNewOrgButton,
isOpen,
onOpenStateChange,
redirectUrl,
}: CreateOrgDialogProps) {
const { maintenanceActive } = useUI();
const user = useUserData();
const isPlatform = useIsPlatform();
@@ -186,6 +202,16 @@ export default function CreateOrgDialog() {
const [createOrganizationRequest] = useCreateOrganizationRequestMutation();
const [stripeClientSecret, setStripeClientSecret] = useState('');
const handleOpenChange = (newOpenState: boolean) => {
const controlledFromOutSide =
isPropSet(isOpen) && isPropSet(onOpenStateChange);
if (controlledFromOutSide) {
onOpenStateChange(newOpenState);
} else {
setOpen(newOpenState);
}
};
const createOrg = async ({
name,
plan,
@@ -195,16 +221,17 @@ export default function CreateOrgDialog() {
}) => {
await execPromiseWithErrorToast(
async () => {
const defaultRedirectUrl = `${window.location.origin}/orgs/verify`;
const {
data: { billingCreateOrganizationRequest: clientSecret },
} = await createOrganizationRequest({
variables: {
organizationName: name,
planID: plan,
redirectURL: `${window.location.origin}/orgs/verify`,
redirectURL: redirectUrl ?? defaultRedirectUrl,
},
});
setStripeClientSecret(clientSecret);
},
{
@@ -224,20 +251,22 @@ export default function CreateOrgDialog() {
}
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button
disabled={maintenanceActive}
className={cn(
'flex h-8 w-full flex-row justify-start gap-3 px-2',
'bg-background text-foreground hover:bg-accent dark:hover:bg-muted',
)}
onClick={() => setStripeClientSecret('')}
>
<Plus className="h-4 w-4 font-bold" strokeWidth={3} />
New Organization
</Button>
</DialogTrigger>
<Dialog open={isOpen ?? open} onOpenChange={handleOpenChange}>
{!hideNewOrgButton && (
<DialogTrigger asChild>
<Button
disabled={maintenanceActive}
className={cn(
'flex h-8 w-full flex-row justify-start gap-3 px-2',
'bg-background text-foreground hover:bg-accent dark:hover:bg-muted',
)}
onClick={() => setStripeClientSecret('')}
>
<Plus className="h-4 w-4 font-bold" strokeWidth={3} />
New Organization
</Button>
</DialogTrigger>
)}
<DialogContent
className={cn(
'text-foreground sm:max-w-xl',
@@ -264,7 +293,7 @@ export default function CreateOrgDialog() {
<CreateOrgForm
plans={data?.plans}
onSubmit={createOrg}
onCancel={() => setOpen(false)}
onCancel={() => handleOpenChange(false)}
/>
)}
{!loading && stripeClientSecret && (

View File

@@ -0,0 +1,53 @@
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
import { CheckoutStatus } from '@/utils/__generated__/graphql';
import { memo } from 'react';
interface Props {
loading: boolean;
status: CheckoutStatus | null;
successMessage: string;
loadingMessage: string;
errorMessage: string;
pendingMessage: string;
}
function FinishOrgCreationProcess({
loading,
status,
successMessage,
loadingMessage,
errorMessage,
pendingMessage,
}: Props) {
let message: string | undefined;
switch (status) {
case CheckoutStatus.Completed: {
message = successMessage;
break;
}
case CheckoutStatus.Expired: {
message = errorMessage;
break;
}
case CheckoutStatus.Open: {
message = pendingMessage;
break;
}
default:
message = loadingMessage;
}
return (
<div className="relative flex flex-auto overflow-x-hidden">
<div className="flex h-full w-full flex-col items-center justify-center space-y-2">
{(loading || status === CheckoutStatus.Completed) && (
<ActivityIndicator circularProgressProps={{ className: 'w-6 h-6' }} />
)}
<span>{message}</span>
</div>
</div>
);
}
export default memo(FinishOrgCreationProcess);

View File

@@ -0,0 +1 @@
export { default as FinishOrgCreationProcess } from './FinishOrgCreationProcess';

View File

@@ -0,0 +1,24 @@
import { FinishOrgCreationProcess } from '@/features/orgs/components/common/FinishOrgCreationProcess';
import { useFinishOrgCreation } from '@/features/orgs/hooks/useFinishOrgCreation';
import { type FinishOrgCreationOnCompletedCb } from '@/features/orgs/hooks/useFinishOrgCreation/useFinishOrgCreation';
interface Props {
onCompleted: FinishOrgCreationOnCompletedCb;
onError: () => void;
}
function FinishOrgCreation({ onCompleted, onError }: Props) {
const [loading, status] = useFinishOrgCreation({ onCompleted, onError });
return (
<FinishOrgCreationProcess
loading={loading}
status={status}
loadingMessage="Processing new organization request"
successMessage="Organization created successfully."
pendingMessage="Organization creation is pending..."
errorMessage="Error occurred while creating the organization. Please try again."
/>
);
}
export default FinishOrgCreation;

View File

@@ -0,0 +1,233 @@
import {
mockMatchMediaValue,
mockOrganization,
mockOrganizations,
mockOrganizationsWithNewOrg,
newOrg,
} from '@/tests/mocks';
import { getOrganization } from '@/tests/msw/mocks/graphql/getOrganizationQuery';
import { getProjectQuery } from '@/tests/msw/mocks/graphql/getProjectQuery';
import { prefetchNewAppQuery } from '@/tests/msw/mocks/graphql/prefetchNewAppQuery';
import tokenQuery from '@/tests/msw/mocks/rest/tokenQuery';
import {
createGraphqlMockResolver,
fireEvent,
mockPointerEvent,
queryClient,
render,
screen,
waitFor,
} from '@/tests/orgs/testUtils';
import userEvent from '@testing-library/user-event';
import { setupServer } from 'msw/node';
import { useState } from 'react';
import { afterAll, beforeAll, vi } from 'vitest';
import TransferProjectDialog from './TransferProjectDialog';
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: vi.fn().mockImplementation(mockMatchMediaValue),
});
mockPointerEvent();
const getUseRouterObject = (session_id?: string) => ({
basePath: '',
pathname: '/orgs/xyz/projects/test-project',
route: '/orgs/[orgSlug]/projects/[appSubdomain]',
asPath: '/orgs/xyz/projects/test-project',
isLocaleDomain: false,
isReady: true,
isPreview: false,
query: {
orgSlug: 'xyz',
appSubdomain: 'test-project',
session_id,
},
push: vi.fn(),
replace: vi.fn(),
reload: vi.fn(),
back: vi.fn(),
prefetch: vi.fn(),
beforePopState: vi.fn(),
events: {
on: vi.fn(),
off: vi.fn(),
emit: vi.fn(),
},
isFallback: false,
});
const mocks = vi.hoisted(() => ({
useRouter: vi.fn(),
useOrgs: vi.fn(),
}));
vi.mock('@/features/orgs/projects/hooks/useOrgs', async () => {
const actualUseOrgs = await vi.importActual<any>(
'@/features/orgs/projects/hooks/useOrgs',
);
return {
...actualUseOrgs,
useOrgs: mocks.useOrgs,
};
});
const postOrganizationRequestResolver = createGraphqlMockResolver(
'postOrganizationRequest',
'mutation',
);
vi.mock('next/router', () => ({
useRouter: mocks.useRouter,
}));
export function DialogWrapper({
defaultOpen = true,
}: {
defaultOpen?: boolean;
}) {
const [open, setOpen] = useState(defaultOpen);
return <TransferProjectDialog open={open} setOpen={setOpen} />;
}
const server = setupServer(tokenQuery);
beforeAll(() => {
process.env.NEXT_PUBLIC_NHOST_PLATFORM = 'true';
process.env.NEXT_PUBLIC_ENV = 'production';
server.listen();
});
afterEach(() => {
queryClient.clear();
mocks.useRouter.mockRestore();
});
afterAll(() => {
server.close();
vi.restoreAllMocks();
});
test('opens create org dialog when selecting "create new org" and closes transfer dialog', async () => {
mocks.useRouter.mockImplementation(() => getUseRouterObject());
const user = userEvent.setup();
server.use(getProjectQuery);
server.use(getOrganization);
mocks.useOrgs.mockImplementation(() => ({
orgs: mockOrganizations,
currentOrg: mockOrganization,
loading: false,
refetch: vi.fn(),
}));
server.use(prefetchNewAppQuery);
render(<DialogWrapper />);
const organizationCombobox = await screen.findByRole('combobox', {
name: /Organization/i,
});
expect(organizationCombobox).toBeInTheDocument();
await user.click(organizationCombobox);
const newOrgOption = await screen.findByRole('option', {
name: 'New Organization',
});
await user.click(newOrgOption);
expect(organizationCombobox).toHaveTextContent('New Organization');
const submitButton = await screen.findByText('Continue');
expect(submitButton).toHaveTextContent('Continue');
fireEvent(
submitButton,
new MouseEvent('click', {
bubbles: true,
cancelable: true,
}),
);
await waitFor(() => {
expect(submitButton).not.toBeInTheDocument();
});
const newOrgTitle = await screen.findByText('New Organization');
expect(newOrgTitle).toBeInTheDocument();
const closeButton = await screen.findByText('Close');
fireEvent(
closeButton,
new MouseEvent('click', {
bubbles: true,
cancelable: true,
}),
);
await waitFor(() => {
expect(newOrgTitle).not.toBeInTheDocument();
});
const submitButtonAfterClosingNewOrgDialog =
await screen.findByText('Continue');
await waitFor(() => {
expect(submitButtonAfterClosingNewOrgDialog).toHaveTextContent('Continue');
});
});
test(`transfer dialog opens automatically when there is a session_id and selects the ${newOrg.name} from the dropdown`, async () => {
mocks.useRouter.mockImplementation(() => getUseRouterObject('session_id'));
server.use(getProjectQuery);
server.use(getOrganization);
mocks.useOrgs.mockImplementation(() => ({
orgs: mockOrganizations,
currentOrg: mockOrganization,
loading: false,
refetch: vi.fn(),
}));
server.use(prefetchNewAppQuery);
server.use(postOrganizationRequestResolver.handler);
render(<DialogWrapper defaultOpen={false} />);
const processingNewOrgText = await screen.findByText(
'Processing new organization request',
);
expect(processingNewOrgText).toBeInTheDocument();
const closeButton = await screen.findByText('Close');
fireEvent(
closeButton,
new MouseEvent('click', {
bubbles: true,
cancelable: true,
}),
);
await waitFor(() => {});
expect(closeButton).toBeInTheDocument();
postOrganizationRequestResolver.resolve({
billingPostOrganizationRequest: {
Status: 'COMPLETED',
Slug: newOrg.slug,
ClientSecret: null,
__typename: 'PostOrganizationRequestResponse',
},
});
mocks.useOrgs.mockImplementation(() => ({
orgs: mockOrganizationsWithNewOrg,
currentOrg: mockOrganization,
loading: false,
refetch: vi.fn(),
}));
const organizationCombobox = await screen.findByRole('combobox', {
name: /Organization/i,
});
expect(organizationCombobox).toHaveTextContent(newOrg.name);
const submitButton = await screen.findByText('Transfer');
expect(submitButton).not.toBeDisabled();
});

View File

@@ -1,5 +1,3 @@
import { Badge } from '@/components/ui/v3/badge';
import { Button } from '@/components/ui/v3/button';
import {
Dialog,
DialogContent,
@@ -10,6 +8,8 @@ import {
import { LoadingScreen } from '@/components/presentational/LoadingScreen';
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
import { Badge } from '@/components/ui/v3/badge';
import { Button } from '@/components/ui/v3/button';
import {
Form,
FormControl,
@@ -25,20 +25,26 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/v3/select';
import FinishOrgCreation from '@/features/orgs/components/common/TransferProjectDialog/FinishOrgCreation';
import CreateOrgDialog from '@/features/orgs/components/CreateOrgFormDialog/CreateOrgFormDialog';
import type { FinishOrgCreationOnCompletedCb } from '@/features/orgs/hooks/useFinishOrgCreation/useFinishOrgCreation';
import { useOrgs, type Org } from '@/features/orgs/projects/hooks/useOrgs';
import { useProject } from '@/features/orgs/projects/hooks/useProject';
import { execPromiseWithErrorToast } from '@/features/orgs/utils/execPromiseWithErrorToast';
import { cn } from '@/lib/utils';
import { cn, isNotEmptyValue } from '@/lib/utils';
import {
Organization_Members_Role_Enum,
useBillingTransferAppMutation,
} from '@/utils/__generated__/graphql';
import { zodResolver } from '@hookform/resolvers/zod';
import { useUserId } from '@nhost/nextjs';
import { Plus } from 'lucide-react';
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
const CREATE_NEW_ORG = 'createNewOrg';
interface TransferProjectDialogProps {
open: boolean;
setOpen: (value: boolean) => void;
@@ -52,11 +58,21 @@ export default function TransferProjectDialog({
open,
setOpen,
}: TransferProjectDialogProps) {
const { push } = useRouter();
const { push, asPath, query, replace, pathname } = useRouter();
const { session_id, test, ...remainingQuery } = query;
const currentUserId = useUserId();
const { project, loading: projectLoading } = useProject();
const { orgs, currentOrg, loading: orgsLoading } = useOrgs();
const {
orgs,
currentOrg,
loading: orgsLoading,
refetch: refetchOrgs,
} = useOrgs();
const [transferProject] = useBillingTransferAppMutation();
const [showCreateOrgModal, setShowCreateOrgModal] = useState(false);
const [finishOrgCreation, setFinishOrgCreation] = useState(false);
const [preventClose, setPreventClose] = useState(false);
const [newOrgSlug, setNewOrgSlug] = useState<string | undefined>();
const form = useForm<z.infer<typeof transferProjectFormSchema>>({
resolver: zodResolver(transferProjectFormSchema),
@@ -65,29 +81,62 @@ export default function TransferProjectDialog({
},
});
useEffect(() => {
if (session_id) {
setOpen(true);
setFinishOrgCreation(true);
setPreventClose(true);
}
}, [session_id, setOpen]);
useEffect(() => {
if (isNotEmptyValue(newOrgSlug)) {
const newOrg = orgs.find((org) => org.slug === newOrgSlug);
if (newOrg) {
form.setValue('organization', newOrg?.id, { shouldDirty: true });
}
}
}, [newOrgSlug, orgs, form]);
const createNewFormSelected = form.watch('organization') === CREATE_NEW_ORG;
const submitButtonText = createNewFormSelected ? 'Continue' : 'Transfer';
const path = asPath.split('?')[0];
const redirectUrl = `${window.location.origin}${path}`;
const handleCreateDialogOpenStateChange = (newState: boolean) => {
setShowCreateOrgModal(newState);
setOpen(true);
};
const onSubmit = async (
values: z.infer<typeof transferProjectFormSchema>,
) => {
const { organization } = values;
await execPromiseWithErrorToast(
async () => {
await transferProject({
variables: {
appID: project?.id,
organizationID: organization,
},
});
if (organization === CREATE_NEW_ORG) {
setShowCreateOrgModal(true);
setOpen(false);
} else {
await execPromiseWithErrorToast(
async () => {
await transferProject({
variables: {
appID: project?.id,
organizationID: organization,
},
});
const targetOrg = orgs.find((o) => o.id === organization);
await push(`/orgs/${targetOrg.slug}/projects`);
},
{
loadingMessage: 'Transferring project...',
successMessage: 'Project transferred successfully!',
errorMessage: 'Error transferring project. Please try again.',
},
);
const targetOrg = orgs.find((o) => o.id === organization);
await push(`/orgs/${targetOrg.slug}/projects`);
},
{
loadingMessage: 'Transferring project...',
successMessage: 'Project transferred successfully!',
errorMessage: 'Error transferring project. Please try again.',
},
);
}
};
const isUserAdminOfOrg = (org: Org, userId: string) =>
@@ -97,103 +146,161 @@ export default function TransferProjectDialog({
member.user.id === userId,
);
const removeSessionIdFromQuery = () => {
replace({ pathname, query: remainingQuery }, undefined, { shallow: true });
};
const handleFinishOrgCreationCompleted: FinishOrgCreationOnCompletedCb =
async (data) => {
const { Slug } = data;
await refetchOrgs();
setNewOrgSlug(Slug);
setFinishOrgCreation(false);
removeSessionIdFromQuery();
setPreventClose(false);
};
const handleTransferProjectDialogOpenChange = (newValue: boolean) => {
if (preventClose) {
return;
}
if (!newValue) {
setNewOrgSlug(undefined);
}
form.reset();
setOpen(newValue);
};
if (projectLoading || orgsLoading) {
return <LoadingScreen />;
}
return (
<Dialog
open={open}
onOpenChange={(value) => {
form.reset();
setOpen(value);
}}
>
<DialogContent className="z-[9999] text-foreground sm:max-w-xl">
<DialogHeader className="flex gap-2">
<DialogTitle>
Move the current project to a different organization.
</DialogTitle>
<DialogDescription>
To transfer a project between organizations, you must be an{' '}
<span className="font-bold">ADMIN</span> in both.
</DialogDescription>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="organization"
render={({ field }) => (
<FormItem>
<FormLabel>Organization</FormLabel>
<Select
onValueChange={field.onChange}
defaultValue={field.value}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Organization" />
</SelectTrigger>
</FormControl>
<SelectContent>
{orgs.map((org) => (
<SelectItem
key={org.id}
value={org.id}
disabled={
org.plan.isFree || // disable the personal org
org.id === currentOrg.id || // disable the current org as it can't be a destination org
!isUserAdminOfOrg(org, currentUserId) // disable orgs that the current user is not admin of
}
>
{org.name}
<Badge
variant={org.plan.isFree ? 'outline' : 'default'}
className={cn(
org.plan.isFree ? 'bg-muted' : '',
'hover:none ml-2 h-5 px-[6px] text-[10px]',
)}
>
{org.plan.name}
</Badge>
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<>
<Dialog open={open} onOpenChange={handleTransferProjectDialogOpenChange}>
<DialogContent className="z-[9999] text-foreground sm:max-w-xl">
<DialogHeader className="flex gap-2">
<DialogTitle>
Move the current project to a different organization.{' '}
</DialogTitle>
<div className="flex justify-end space-x-2">
<Button
variant="secondary"
type="button"
disabled={form.formState.isSubmitting}
onClick={() => {
form.reset();
setOpen(false);
}}
{!finishOrgCreation && (
<DialogDescription>
To transfer a project between organizations, you must be an{' '}
<span className="font-bold">ADMIN</span> in both.
<br />
When transferred to a new organization, the project will adopt
that organizations plan.
</DialogDescription>
)}
</DialogHeader>
{finishOrgCreation ? (
<FinishOrgCreation
onCompleted={handleFinishOrgCreationCompleted}
onError={() => setPreventClose(false)}
/>
) : (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-4"
>
Cancel
</Button>
<Button
type="submit"
disabled={
form.formState.isSubmitting || !form.formState.isDirty
}
>
{form.formState.isSubmitting ? (
<ActivityIndicator />
) : (
'Transfer'
)}
</Button>
</div>
</form>
</Form>
</DialogContent>
</Dialog>
<FormField
control={form.control}
name="organization"
render={({ field }) => (
<FormItem>
<FormLabel>Organization</FormLabel>
<Select
onValueChange={field.onChange}
value={field.value}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Organization" />
</SelectTrigger>
</FormControl>
<SelectContent>
{orgs.map((org) => (
<SelectItem
key={org.id}
value={org.id}
disabled={
org.plan.isFree || // disable the personal org
org.id === currentOrg.id || // disable the current org as it can't be a destination org
!isUserAdminOfOrg(org, currentUserId) // disable orgs that the current user is not admin of
}
>
{org.name}
<Badge
variant={
org.plan.isFree ? 'outline' : 'default'
}
className={cn(
org.plan.isFree ? 'bg-muted' : '',
'hover:none ml-2 h-5 px-[6px] text-[10px]',
)}
>
{org.plan.name}
</Badge>
</SelectItem>
))}
<SelectItem
key={CREATE_NEW_ORG}
value={CREATE_NEW_ORG}
>
<div className="flex items-center justify-center gap-2">
<Plus
className="h-4 w-4 font-bold"
strokeWidth={3}
/>{' '}
<span>New Organization</span>
</div>
</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<div className="flex justify-end space-x-2">
<Button
variant="secondary"
type="button"
disabled={form.formState.isSubmitting || preventClose}
onClick={() => {
form.reset();
setOpen(false);
}}
>
Cancel
</Button>
<Button
type="submit"
disabled={
form.formState.isSubmitting || !form.formState.isDirty
}
>
{form.formState.isSubmitting ? (
<ActivityIndicator />
) : (
submitButtonText
)}
</Button>
</div>
</form>
</Form>
)}
</DialogContent>
</Dialog>
<CreateOrgDialog
hideNewOrgButton
isOpen={showCreateOrgModal}
onOpenStateChange={handleCreateDialogOpenStateChange}
redirectUrl={redirectUrl}
/>
</>
);
}

View File

@@ -0,0 +1,167 @@
import { mockMatchMediaValue } from '@/tests/mocks';
import { getOrganizations } from '@/tests/msw/mocks/graphql/getOrganizationQuery';
import tokenQuery from '@/tests/msw/mocks/rest/tokenQuery';
import { mockSession } from '@/tests/orgs/mocks';
import { queryClient, render, waitFor } from '@/tests/orgs/testUtils';
import { CheckoutStatus } from '@/utils/__generated__/graphql';
import { setupServer } from 'msw/node';
import { afterAll, beforeAll, vi } from 'vitest';
import NotificationsTray from './NotificationsTray';
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: vi.fn().mockImplementation(mockMatchMediaValue),
});
export const getUseRouterObject = (session_id?: string) => ({
basePath: '',
pathname: '/orgs/xyz/projects/test-project',
route: '/orgs/[orgSlug]/projects/[appSubdomain]',
asPath: '/orgs/xyz/projects/test-project',
isLocaleDomain: false,
isReady: true,
isPreview: false,
query: {
orgSlug: 'xyz',
appSubdomain: 'test-project',
session_id,
},
push: vi.fn(),
replace: vi.fn(),
reload: vi.fn(),
back: vi.fn(),
prefetch: vi.fn(),
beforePopState: vi.fn(),
events: {
on: vi.fn(),
off: vi.fn(),
emit: vi.fn(),
},
isFallback: false,
});
const mocks = vi.hoisted(() => ({
useRouter: vi.fn(),
useOrganizationNewRequestsLazyQuery: vi.fn(),
usePostOrganizationRequestMutation: vi.fn(),
useOrganizationMemberInvitesLazyQuery: vi.fn(),
fetchPostOrganizationResponseMock: vi.fn(),
userData: vi.fn(),
}));
vi.mock('next/router', () => ({
useRouter: mocks.useRouter,
}));
vi.mock('@nhost/nextjs', async () => {
const actualNhostNextjs = await vi.importActual<any>('@nhost/nextjs');
return {
...actualNhostNextjs,
userData: mocks.userData,
};
});
vi.mock('@/utils/__generated__/graphql', async () => {
const actual = await vi.importActual<any>('@/utils/__generated__/graphql');
return {
...actual,
useOrganizationNewRequestsLazyQuery:
mocks.useOrganizationNewRequestsLazyQuery,
usePostOrganizationRequestMutation:
mocks.usePostOrganizationRequestMutation,
useOrganizationMemberInvitesLazyQuery:
mocks.useOrganizationMemberInvitesLazyQuery,
};
});
const server = setupServer(tokenQuery);
beforeAll(() => {
process.env.NEXT_PUBLIC_NHOST_PLATFORM = 'true';
process.env.NEXT_PUBLIC_ENV = 'production';
});
afterEach(() => {
queryClient.clear();
vi.restoreAllMocks();
});
afterAll(() => {
server.close();
});
const fetchOrganizationMemberInvitesMock = () => [
async () => ({ data: { organizationMemberInvites: [] } }),
{
loading: true,
refetch: vi.fn(),
data: { organizationMemberInvites: [] },
},
];
const fetchOrganizationNewRequestsResponseMock = async () => ({
data: {
organizationNewRequests: [
{
id: 'org-request-id-1',
sessionID: 'session-id-1',
__typename: 'organization_new_request',
},
],
},
});
const fetchPostOrganizationResponseMock = vi.fn();
test('if there is NO session_id in the url the billingPostOrganizationRequest is fetched from the server', async () => {
server.use(getOrganizations);
mocks.useOrganizationMemberInvitesLazyQuery.mockImplementation(
fetchOrganizationMemberInvitesMock,
);
mocks.useRouter.mockImplementation(() => getUseRouterObject());
mocks.userData.mockImplementation(() => mockSession.user);
mocks.useOrganizationNewRequestsLazyQuery.mockImplementation(() => [
fetchOrganizationNewRequestsResponseMock,
]);
mocks.usePostOrganizationRequestMutation.mockImplementation(() => [
fetchPostOrganizationResponseMock.mockImplementation(() => ({
data: {
billingPostOrganizationRequest: {
Status: CheckoutStatus.Open,
Slug: 'newOrgSlug',
ClientSecret: 'very_secret_secret',
__typename: 'PostOrganizationRequestResponse',
},
},
})),
]);
render(<NotificationsTray />);
await waitFor(() => {
/* Wait for the component to be update */
});
expect(fetchPostOrganizationResponseMock).toHaveBeenCalled();
});
test('if there is a session_id in the url the billingPostOrganizationRequest is NOT fetched from the server ', async () => {
server.use(getOrganizations);
mocks.useOrganizationMemberInvitesLazyQuery.mockImplementation(
fetchOrganizationMemberInvitesMock,
);
mocks.useRouter.mockImplementation(() => getUseRouterObject('SESSION_ID'));
mocks.userData.mockImplementation(() => mockSession.user);
mocks.useOrganizationNewRequestsLazyQuery.mockImplementation(() => [
fetchOrganizationNewRequestsResponseMock,
]);
mocks.usePostOrganizationRequestMutation.mockImplementation(() => [
fetchPostOrganizationResponseMock,
]);
render(<NotificationsTray />);
await waitFor(() => {
/* Wait for the component to be update */
});
expect(fetchPostOrganizationResponseMock).not.toHaveBeenCalled();
});

View File

@@ -18,6 +18,7 @@ import {
import { StripeEmbeddedForm } from '@/features/orgs/components/StripeEmbeddedForm';
import { useOrgs } from '@/features/orgs/projects/hooks/useOrgs';
import { execPromiseWithErrorToast } from '@/features/orgs/utils/execPromiseWithErrorToast';
import { isEmptyValue } from '@/lib/utils';
import {
CheckoutStatus,
useDeleteOrganizationMemberInviteMutation,
@@ -38,7 +39,8 @@ type Invite = OrganizationMemberInvitesQuery['organizationMemberInvites'][0];
export default function NotificationsTray() {
const userData = useUserData();
const { asPath, route, push } = useRouter();
const { asPath, route, push, query } = useRouter();
const { session_id } = query;
const { refetch: refetchOrgs } = useOrgs();
const [open, setOpen] = useState(false);
@@ -76,7 +78,6 @@ export default function NotificationsTray() {
userID: userData.id,
},
});
if (organizationNewRequests.length > 0) {
const { sessionID } = organizationNewRequests.at(0);
@@ -109,10 +110,20 @@ export default function NotificationsTray() {
}
};
if (userData && !['/', '/orgs/verify'].includes(route)) {
if (
userData &&
!['/', '/orgs/verify'].includes(route) &&
isEmptyValue(session_id)
) {
checkForPendingOrgRequests();
}
}, [route, userData, getOrganizationNewRequests, postOrganizationRequest]);
}, [
route,
userData,
getOrganizationNewRequests,
postOrganizationRequest,
session_id,
]);
const [acceptInvite] = useOrganizationMemberInviteAcceptMutation();
const [deleteInvite] = useDeleteOrganizationMemberInviteMutation();

View File

@@ -0,0 +1 @@
export { default as useFinishOrgCreation } from './useFinishOrgCreation';

View File

@@ -0,0 +1,92 @@
import {
CheckoutStatus,
type PostOrganizationRequestMutation,
usePostOrganizationRequestMutation,
} from '@/utils/__generated__/graphql';
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
import { useAuthenticationStatus } from '@nhost/nextjs';
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
export type FinishOrgCreationOnCompletedCb = (
data: PostOrganizationRequestMutation['billingPostOrganizationRequest'],
) => void;
interface UseFinishOrgCreationProps {
onCompleted: FinishOrgCreationOnCompletedCb;
onError?: () => void;
}
function useFinishOrgCreation({
onCompleted,
onError,
}: UseFinishOrgCreationProps): [boolean, CheckoutStatus] {
const router = useRouter();
const { session_id } = router.query;
const { isAuthenticated } = useAuthenticationStatus();
const [loading, setLoading] = useState(false);
const [postOrganizationRequest] = usePostOrganizationRequestMutation();
const [status, setPostOrganizationRequestStatus] =
useState<CheckoutStatus | null>(null);
useEffect(() => {
async function finishOrgCreation() {
if (session_id && isAuthenticated) {
setLoading(true);
execPromiseWithErrorToast(
async () => {
const {
data: { billingPostOrganizationRequest },
} = await postOrganizationRequest({
variables: {
sessionID: session_id as string,
},
});
const { Status } = billingPostOrganizationRequest;
setLoading(false);
setPostOrganizationRequestStatus(Status);
switch (Status) {
case CheckoutStatus.Completed:
onCompleted(billingPostOrganizationRequest);
break;
case CheckoutStatus.Expired:
onError();
throw new Error('Request to create organization has expired');
case CheckoutStatus.Open:
// TODO discuss what to do in this case
onError();
throw new Error(
'Request to create organization with status "Open"',
);
default:
break;
}
},
{
loadingMessage: 'Processing new organization request',
successMessage:
'The new organization has been created successfully.',
errorMessage:
'An error occurred while creating the new organization.',
onError,
},
);
}
}
finishOrgCreation();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [session_id, isAuthenticated]);
return [loading, status];
}
export default useFinishOrgCreation;

View File

@@ -24,7 +24,7 @@ import { getUserRoles } from '@/features/projects/roles/settings/utils/getUserRo
import { type RemoteAppUser } from '@/pages/orgs/[orgSlug]/projects/[appSubdomain]/users';
import type { DialogFormProps } from '@/types/common';
import {
RemoteAppGetUsersDocument,
RemoteAppGetUsersAndAuthRolesDocument,
useGetProjectLocalesQuery,
useGetRolesPermissionsQuery,
useUpdateRemoteAppUserMutation,
@@ -120,7 +120,7 @@ export default function EditUserForm({
const [updateUser] = useUpdateRemoteAppUserMutation({
client: remoteProjectGQLClient,
refetchQueries: [RemoteAppGetUsersDocument],
refetchQueries: [RemoteAppGetUsersAndAuthRolesDocument],
});
const form = useForm<EditUserFormValues>({

View File

@@ -7,7 +7,7 @@ import { useRemoteApplicationGQLClient } from '@/features/orgs/hooks/useRemoteAp
import { useProject } from '@/features/orgs/projects/hooks/useProject';
import { execPromiseWithErrorToast } from '@/features/orgs/utils/execPromiseWithErrorToast';
import type { DialogFormProps } from '@/types/common';
import type { RemoteAppGetUsersQuery } from '@/utils/__generated__/graphql';
import type { RemoteAppGetUsersAndAuthRolesQuery } from '@/utils/__generated__/graphql';
import {
useGetSignInMethodsQuery,
useUpdateRemoteAppUserMutation,
@@ -26,7 +26,7 @@ export interface EditUserPasswordFormProps extends DialogFormProps {
/**
* The selected user.
*/
user: RemoteAppGetUsersQuery['users'][0];
user: RemoteAppGetUsersAndAuthRolesQuery['users'][0];
}
export default function EditUserPasswordForm({

View File

@@ -15,15 +15,11 @@ import { Text } from '@/components/ui/v2/Text';
import { useRemoteApplicationGQLClient } from '@/features/orgs/hooks/useRemoteApplicationGQLClient';
import type { EditUserFormValues } from '@/features/orgs/projects/authentication/users/components/EditUserForm';
import { getReadableProviderName } from '@/features/orgs/projects/authentication/users/utils/getReadableProviderName';
import { useIsPlatform } from '@/features/orgs/projects/common/hooks/useIsPlatform';
import { useLocalMimirClient } from '@/features/orgs/projects/hooks/useLocalMimirClient';
import { useProject } from '@/features/orgs/projects/hooks/useProject';
import { execPromiseWithErrorToast } from '@/features/orgs/utils/execPromiseWithErrorToast';
import { getUserRoles } from '@/features/projects/roles/settings/utils/getUserRoles';
import type { RemoteAppUser } from '@/pages/orgs/[orgSlug]/projects/[appSubdomain]/users';
import type { Role } from '@/types/application';
import {
useDeleteRemoteAppUserRolesMutation,
useGetRolesPermissionsQuery,
useInsertRemoteAppUserRolesMutation,
useRemoteAppDeleteUserMutation,
useUpdateRemoteAppUserMutation,
@@ -33,7 +29,7 @@ import { formatDistance } from 'date-fns';
import kebabCase from 'just-kebab-case';
import dynamic from 'next/dynamic';
import Image from 'next/image';
import { Fragment, useMemo } from 'react';
import { Fragment } from 'react';
const EditUserForm = dynamic(
() =>
@@ -59,14 +55,16 @@ export interface UsersBodyProps {
* @example onSuccessfulAction={() => router.reload()}
*/
onSubmit?: () => Promise<any>;
allAvailableProjectRoles: Role[];
}
export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
export default function UsersBody({
users,
onSubmit,
allAvailableProjectRoles,
}: UsersBodyProps) {
const theme = useTheme();
const isPlatform = useIsPlatform();
const localMimirClient = useLocalMimirClient();
const { openAlertDialog, openDrawer, closeDrawer } = useDialog();
const { project } = useProject();
const remoteProjectGQLClient = useRemoteApplicationGQLClient();
const [deleteUser] = useRemoteAppDeleteUserMutation({
@@ -85,23 +83,6 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
client: remoteProjectGQLClient,
});
/**
* We want to fetch the queries of the application on this page since we're
* going to use once the user selects a user of their application; we use it
* in the drawer form.
*/
const { data: dataRoles } = useGetRolesPermissionsQuery({
variables: { appId: project?.id },
...(!isPlatform ? { client: localMimirClient } : {}),
});
const { allowed: allowedRoles } = dataRoles?.config?.auth?.user?.roles || {};
const allAvailableProjectRoles = useMemo(
() => getUserRoles(allowedRoles),
[allowedRoles],
);
async function handleEditUser(
values: EditUserFormValues,
user: RemoteAppUser,

View File

@@ -18,7 +18,24 @@ const ruleSchema = Yup.object().shape({
});
const ruleGroupSchema = Yup.object().shape({
operator: Yup.string().required('Please select an operator.'),
operator: Yup.string().test(
'operator',
'Please select an operator.',
(selectedOperator, ctx) => {
// `from` is part of the Yup API, but it's not typed.
// @ts-ignore
const [, { value }] = ctx.from;
if (
value.filter &&
Object.keys(value.filter).length > 0 &&
!selectedOperator
) {
return false;
}
return true;
},
),
rules: Yup.array().of(ruleSchema),
groups: Yup.array().of(Yup.lazy(() => ruleGroupSchema) as any),
});

View File

@@ -1,14 +1,17 @@
import { OpenTransferDialogButton } from '@/components/common/OpenTransferDialogButton';
import { useUI } from '@/components/common/UIProvider';
import { Form } from '@/components/form/Form';
import { SettingsContainer } from '@/components/layout/SettingsContainer';
import { NhostIcon } from '@/components/presentational/NhostIcon';
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
import { Alert } from '@/components/ui/v2/Alert';
import { Box } from '@/components/ui/v2/Box';
import { ArrowSquareOutIcon } from '@/components/ui/v2/icons/ArrowSquareOutIcon';
import { Input } from '@/components/ui/v2/Input';
import { InputAdornment } from '@/components/ui/v2/InputAdornment';
import { Link } from '@/components/ui/v2/Link';
import { Text } from '@/components/ui/v2/Text';
import { UpgradeNotification } from '@/features/orgs/projects/common/components/UpgradeNotification';
import { TransferProjectDialog } from '@/features/orgs/components/common/TransferProjectDialog';
import { useAppState } from '@/features/orgs/projects/common/hooks/useAppState';
import { useIsPlatform } from '@/features/orgs/projects/common/hooks/useIsPlatform';
import { DatabaseStorageCapacityWarning } from '@/features/orgs/projects/database/settings/components/DatabaseStorageCapacityWarning';
@@ -23,7 +26,7 @@ import {
} from '@/generated/graphql';
import { ApplicationStatus } from '@/types/application';
import { yupResolver } from '@hookform/resolvers/yup';
import { useEffect, useMemo } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import * as Yup from 'yup';
@@ -39,6 +42,57 @@ export type DatabaseStorageCapacityFormValues = Yup.InferType<
typeof validationSchema
>;
function UpgradeNotification() {
const [transferProjectDialogOpen, setTransferProjectDialogOpen] =
useState(false);
const handleTransferDialogOpen = () => setTransferProjectDialogOpen(true);
return (
<Alert className="flex w-full flex-col justify-between gap-4 lg:flex-row">
<div className="flex flex-col gap-4">
<div className="flex flex-col space-y-2 lg:flex-row lg:space-x-2 lg:space-y-0">
<Text className="text-left">Available with</Text>
<div className="flex flex-row space-x-2">
<NhostIcon />
<Text
sx={{ color: 'primary.main' }}
className="text-left font-semibold"
>
Nhost Pro & Team
</Text>
</div>
</div>
<Text component="span" className="max-w-[50ch] text-left">
To unlock more storage capacity, transfer this project to a Pro or
Team organization.
</Text>
</div>
<Text className="flex flex-row items-center gap-4 self-end">
<Link
href="https://nhost.io/pricing"
target="_blank"
rel="noopener noreferrer"
underline="hover"
className="whitespace-nowrap text-center font-medium"
sx={{
color: 'text.secondary',
}}
>
See all features
<ArrowSquareOutIcon className="ml-1 h-4 w-4" />
</Link>
<OpenTransferDialogButton onClick={handleTransferDialogOpen} />
<TransferProjectDialog
open={transferProjectDialogOpen}
setOpen={setTransferProjectDialogOpen}
/>
</Text>
</Alert>
);
}
export default function DatabaseStorageCapacity() {
const isPlatform = useIsPlatform();
const { org } = useCurrentOrg();
@@ -46,6 +100,8 @@ export default function DatabaseStorageCapacity() {
const localMimirClient = useLocalMimirClient();
const { project } = useProject();
const isFreeProject = !!org?.plan.isFree;
const {
data,
loading,
@@ -172,9 +228,7 @@ export default function DatabaseStorageCapacity() {
}}
className="flex flex-col"
>
{project.legacyPlan?.isFree && (
<UpgradeNotification message="Unlock by upgrading your project to the Pro plan." />
)}
{isFreeProject && <UpgradeNotification />}
<Box className="grid grid-flow-row lg:grid-cols-5">
<Input
{...register('capacity')}
@@ -187,13 +241,13 @@ export default function DatabaseStorageCapacity() {
</InputAdornment>
}
fullWidth
disabled={project.legacyPlan?.isFree}
disabled={isFreeProject}
className="lg:col-span-2"
error={Boolean(formState.errors.capacity?.message)}
helperText={formState.errors.capacity?.message}
/>
</Box>
{!project.legacyPlan?.isFree && (
{!isFreeProject && (
<DatabaseStorageCapacityWarning
state={state}
decreasingSize={decreasingSize}

View File

@@ -158,7 +158,7 @@ export default function LogsBody({ logsData, loading, error }: LogsBodyProps) {
);
}
if (!logsData || logsData.logs?.length === 0) {
if (logsData?.logs?.length === 0) {
return (
<LogsBodyCustomMessage>
<Text className="truncate font-mono text-xs- font-normal">

View File

@@ -1,4 +1,3 @@
import { ControlledSelect } from '@/components/form/ControlledSelect';
import { Form } from '@/components/form/Form';
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
import type { BoxProps } from '@/components/ui/v2/Box';
@@ -12,14 +11,19 @@ import { Option } from '@/components/ui/v2/Option';
import { Tooltip } from '@/components/ui/v2/Tooltip';
import { useProject } from '@/features/orgs/projects/hooks/useProject';
import { LogsRangeSelector } from '@/features/orgs/projects/logs/components/LogsRangeSelector';
import { AvailableLogsService } from '@/features/orgs/projects/logs/utils/constants/services';
import {
AvailableLogsService,
LOGS_SERVICE_TO_LABEL,
} from '@/features/orgs/projects/logs/utils/constants/services';
import { isEmptyValue } from '@/lib/utils';
import { useGetServiceLabelValuesQuery } from '@/utils/__generated__/graphql';
import { MINUTES_TO_DECREASE_FROM_CURRENT_DATE } from '@/utils/constants/common';
import { yupResolver } from '@hookform/resolvers/yup';
import { subMinutes } from 'date-fns';
import { useEffect, useState } from 'react';
import { useEffect, useMemo } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import * as Yup from 'yup';
import LogsServiceFilter from './LogsServiceFilter';
export const validationSchema = Yup.object({
from: Yup.date(),
@@ -49,42 +53,33 @@ export default function LogsHeader({
}: LogsHeaderProps) {
const { project } = useProject();
const [serviceLabels, setServiceLabels] = useState<
{ label: string; value: string }[]
>([]);
const { data } = useGetServiceLabelValuesQuery({
variables: { appID: project?.id },
skip: !project?.id,
});
const { data, loading: loadingServiceLabelValues } =
useGetServiceLabelValuesQuery({
variables: { appID: project?.id },
});
useEffect(() => {
if (!loadingServiceLabelValues) {
const labels = data.getServiceLabelValues ?? [];
setServiceLabels(labels.map((l) => ({ label: l, value: l })));
const serviceOptions = useMemo(() => {
if (isEmptyValue(data)) {
return [];
}
}, [loadingServiceLabelValues, data]);
useEffect(() => {
if (!loadingServiceLabelValues) {
const labels = data.getServiceLabelValues ?? [];
const options = [
{
label: LOGS_SERVICE_TO_LABEL[AvailableLogsService.ALL],
value: AvailableLogsService.ALL,
},
...data.getServiceLabelValues.map((l) => ({
label: LOGS_SERVICE_TO_LABEL[l] ?? l,
value: l,
})),
];
const labelMappings = {
'hasura-auth': 'Auth',
'hasura-storage': 'Storage',
postgres: 'Postgres',
functions: 'Functions',
hasura: 'Hasura',
grafana: 'Grafana',
'job-backup': 'Backup Jobs',
ai: 'AI',
};
setServiceLabels(
labels.map((l) => ({ label: labelMappings[l] ?? l, value: l })),
);
}
}, [loadingServiceLabelValues, data]);
return options.map(({ value, label }) => (
<Option key={value} value={value} className="text-sm+ font-medium">
{label}
</Option>
));
}, [data]);
const form = useForm<LogsFilterFormValues>({
defaultValues: {
@@ -119,30 +114,10 @@ export default function LogsHeader({
className="grid w-full grid-flow-row items-center gap-2 md:w-[initial] md:grid-flow-col md:gap-3 lg:justify-end"
>
<Box className="flex flex-row space-x-2">
<ControlledSelect
{...register('service')}
className="w-full min-w-fit text-sm font-normal"
placeholder="All Services"
aria-label="Select service"
hideEmptyHelperText
slotProps={{
root: {
className: 'min-h-[initial] h-10 leading-[initial]',
},
}}
>
{[{ label: 'All services', value: '' }, ...serviceLabels].map(
({ value, label }) => (
<Option
key={value}
value={value}
className="text-sm+ font-medium"
>
{label}
</Option>
),
)}
</ControlledSelect>
<LogsServiceFilter
register={register}
serviceOptions={serviceOptions}
/>
<div className="w-full min-w-fit">
<LogsRangeSelector onSubmitFilterValues={onSubmitFilterValues} />
</div>

View File

@@ -0,0 +1,29 @@
import { ControlledSelect } from '@/components/form/ControlledSelect';
import { memo } from 'react';
import type { UseFormRegister } from 'react-hook-form';
import type { LogsFilterFormValues } from './LogsHeader';
interface LogsServiceFilterProps {
register: UseFormRegister<LogsFilterFormValues>;
serviceOptions: JSX.Element[];
}
const LogsServiceFilter = memo(
({ register, serviceOptions }: LogsServiceFilterProps) => (
<ControlledSelect
{...register('service')}
className="w-full min-w-fit text-sm font-normal"
placeholder="All Services"
aria-label="Select service"
hideEmptyHelperText
slotProps={{
root: {
className: 'min-h-[initial] h-10 leading-[initial]',
},
}}
>
{serviceOptions}
</ControlledSelect>
),
);
export default LogsServiceFilter;

View File

@@ -10,34 +10,21 @@ export enum AvailableLogsService {
STORAGE = 'hasura-storage',
HASURA = 'hasura',
FUNCTIONS = 'functions',
GRAFANA = 'grafana',
JOB_BACKUP = 'job-backup',
AI = 'ai',
}
export const LOGS_AVAILABLE_SERVICES: {
label: string;
value: AvailableLogsService;
}[] = [
{
label: 'All Services',
value: AvailableLogsService.ALL,
},
{
label: 'Postgres',
value: AvailableLogsService.POSTGRES,
},
{
label: 'Auth',
value: AvailableLogsService.AUTH,
},
{
label: 'Storage',
value: AvailableLogsService.STORAGE,
},
{
label: 'Hasura',
value: AvailableLogsService.HASURA,
},
{
label: 'Functions',
value: AvailableLogsService.FUNCTIONS,
},
];
export const LOGS_SERVICE_TO_LABEL: Required<
Record<AvailableLogsService, string>
> = {
[AvailableLogsService.ALL]: 'All Services',
[AvailableLogsService.POSTGRES]: 'Postgres',
[AvailableLogsService.AUTH]: 'Auth',
[AvailableLogsService.STORAGE]: 'Storage',
[AvailableLogsService.HASURA]: 'Hasura',
[AvailableLogsService.FUNCTIONS]: 'Functions',
[AvailableLogsService.GRAFANA]: 'Grafana',
[AvailableLogsService.JOB_BACKUP]: 'Backup Jobs',
[AvailableLogsService.AI]: 'AI',
};

View File

@@ -36,7 +36,7 @@ vi.mock('next/router', () => ({
const server = setupServer(
tokenQuery,
rest.get('https://local.graphql.nhost.run/v1', (_req, res, ctx) =>
rest.get('https://local.graphql.local.nhost.run/v1', (_req, res, ctx) =>
res(ctx.status(200)),
),
);
@@ -49,7 +49,7 @@ beforeAll(() => {
afterEach(() => {
server.resetHandlers(
rest.get('https://local.graphql.nhost.run/v1', (_req, res, ctx) =>
rest.get('https://local.graphql.local.nhost.run/v1', (_req, res, ctx) =>
res(ctx.status(200)),
),
);
@@ -63,33 +63,36 @@ afterAll(() => {
test('should render an empty state when GitHub is not connected', async () => {
server.use(
rest.post('https://local.graphql.nhost.run/v1', async (req, res, ctx) => {
const { operationName } = await req.json();
rest.post(
'https://local.graphql.local.nhost.run/v1',
async (req, res, ctx) => {
const { operationName } = await req.json();
if (operationName === 'getProject') {
return res(
ctx.json({
apps: [{ ...mockApplication, githubRepository: null }],
}),
);
}
if (operationName === 'getOrganization') {
return res(
ctx.json({
organizations: [{ ...mockOrganization }],
}),
);
}
if (operationName === 'getProject') {
return res(
ctx.json({
apps: [{ ...mockApplication, githubRepository: null }],
data: {
deployments: [],
},
}),
);
}
if (operationName === 'getOrganization') {
return res(
ctx.json({
organizations: [{ ...mockOrganization }],
}),
);
}
return res(
ctx.json({
data: {
deployments: [],
},
}),
);
}),
},
),
);
render(<OverviewDeployments />);
@@ -102,31 +105,34 @@ test('should render an empty state when GitHub is not connected', async () => {
test('should render an empty state when GitHub is connected, but there are no deployments', async () => {
server.use(
rest.post('https://local.graphql.nhost.run/v1', async (_req, res, ctx) => {
const { operationName } = await _req.json();
rest.post(
'https://local.graphql.local.nhost.run/v1',
async (_req, res, ctx) => {
const { operationName } = await _req.json();
if (operationName === 'getProject') {
return res(
ctx.json({
data: {
apps: [{ ...mockApplication }],
},
}),
);
}
if (operationName === 'getProject') {
return res(
ctx.json({
data: {
apps: [{ ...mockApplication }],
},
}),
);
}
if (operationName === 'getOrganization') {
return res(
ctx.json({
data: {
organizations: [{ ...mockOrganization }],
},
}),
);
}
if (operationName === 'getOrganization') {
return res(
ctx.json({
data: {
organizations: [{ ...mockOrganization }],
},
}),
);
}
return res(ctx.json({ data: { deployments: [] } }));
}),
return res(ctx.json({ data: { deployments: [] } }));
},
),
);
render(<OverviewDeployments />);
@@ -147,52 +153,55 @@ test('should render an empty state when GitHub is connected, but there are no de
test('should render a list of deployments', async () => {
server.use(
tokenQuery,
rest.post('https://local.graphql.nhost.run/v1', async (_req, res, ctx) => {
const { operationName } = await _req.json();
rest.post(
'https://local.graphql.local.nhost.run/v1',
async (_req, res, ctx) => {
const { operationName } = await _req.json();
if (operationName === 'ScheduledOrPendingDeploymentsSub') {
return res(ctx.json({ data: { deployments: [] } }));
}
if (operationName === 'ScheduledOrPendingDeploymentsSub') {
return res(ctx.json({ data: { deployments: [] } }));
}
if (operationName === 'getProject') {
return res(
ctx.json({
data: {
apps: [{ ...mockApplication }],
},
}),
);
}
if (operationName === 'getOrganization') {
return res(
ctx.json({
data: {
organizations: [{ ...mockOrganization }],
},
}),
);
}
return res(
ctx.json({
data: {
deployments: [
{
id: '1',
commitSHA: 'abc123',
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
deploymentStatus: 'DEPLOYED',
commitUserName: 'test.user',
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
commitMessage: 'Test commit message',
if (operationName === 'getProject') {
return res(
ctx.json({
data: {
apps: [{ ...mockApplication }],
},
],
},
}),
);
}),
}),
);
}
if (operationName === 'getOrganization') {
return res(
ctx.json({
data: {
organizations: [{ ...mockOrganization }],
},
}),
);
}
return res(
ctx.json({
data: {
deployments: [
{
id: '1',
commitSHA: 'abc123',
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
deploymentStatus: 'DEPLOYED',
commitUserName: 'test.user',
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
commitMessage: 'Test commit message',
},
],
},
}),
);
},
),
);
render(<OverviewDeployments />);
@@ -216,20 +225,62 @@ test('should render a list of deployments', async () => {
test('should disable redeployments if a deployment is already in progress', async () => {
server.use(
tokenQuery,
rest.post('https://local.graphql.nhost.run/v1', async (req, res, ctx) => {
const { operationName } = await req.json();
rest.post(
'https://local.graphql.local.nhost.run/v1',
async (req, res, ctx) => {
const { operationName } = await req.json();
if (operationName === 'ScheduledOrPendingDeploymentsSub') {
return res(
ctx.json({
data: {
deployments: [
{
id: '2',
commitSHA: 'abc234',
deploymentStartedAt: '2021-08-02T00:00:00.000Z',
deploymentEndedAt: null,
deploymentStatus: 'PENDING',
commitUserName: 'test.user',
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
commitMessage: 'Test commit message',
},
],
},
}),
);
}
if (operationName === 'getProject') {
return res(
ctx.json({
data: {
apps: [{ ...mockApplication }],
},
}),
);
}
if (operationName === 'getOrganization') {
return res(
ctx.json({
data: {
organizations: [{ ...mockOrganization }],
},
}),
);
}
if (operationName === 'ScheduledOrPendingDeploymentsSub') {
return res(
ctx.json({
data: {
deployments: [
{
id: '2',
commitSHA: 'abc234',
deploymentStartedAt: '2021-08-02T00:00:00.000Z',
deploymentEndedAt: null,
deploymentStatus: 'PENDING',
id: '1',
commitSHA: 'abc123',
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
deploymentStatus: 'DEPLOYED',
commitUserName: 'test.user',
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
commitMessage: 'Test commit message',
@@ -238,47 +289,8 @@ test('should disable redeployments if a deployment is already in progress', asyn
},
}),
);
}
if (operationName === 'getProject') {
return res(
ctx.json({
data: {
apps: [{ ...mockApplication }],
},
}),
);
}
if (operationName === 'getOrganization') {
return res(
ctx.json({
data: {
organizations: [{ ...mockOrganization }],
},
}),
);
}
return res(
ctx.json({
data: {
deployments: [
{
id: '1',
commitSHA: 'abc123',
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
deploymentStatus: 'DEPLOYED',
commitUserName: 'test.user',
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
commitMessage: 'Test commit message',
},
],
},
}),
);
}),
},
),
);
render(<OverviewDeployments />);

View File

@@ -5,6 +5,7 @@ import { Button } from '@/components/ui/v3/button';
import { useIsPlatform } from '@/features/orgs/projects/common/hooks/useIsPlatform';
import { useCurrentOrg } from '@/features/orgs/projects/hooks/useCurrentOrg';
import { useProject } from '@/features/orgs/projects/hooks/useProject';
import UpgradeProjectDialog from '@/features/orgs/projects/overview/components/OverviewTopBar/UpgradeProjectDialog';
import { formatDistanceToNowStrict, parseISO } from 'date-fns';
import Image from 'next/image';
import Link from 'next/link';
@@ -15,6 +16,8 @@ export default function OverviewTopBar() {
const { project } = useProject();
const { maintenanceActive } = useUI();
const isFreeProject = !!org?.plan.isFree;
if (!isPlatform) {
return (
<div className="flex flex-row place-content-between items-center py-5">
@@ -87,22 +90,24 @@ export default function OverviewTopBar() {
</div>
</div>
</div>
<Link
href={`/orgs/${org?.slug}/projects/${project?.subdomain}/settings`}
passHref
legacyBehavior
>
<Button
variant="outline"
className="gap-2"
color="secondary"
disabled={maintenanceActive}
<div className="flex content-center gap-4">
{isFreeProject && <UpgradeProjectDialog />}
<Link
href={`/orgs/${org?.slug}/projects/${project?.subdomain}/settings`}
passHref
legacyBehavior
>
Settings
<CogIcon className="h-4 w-4" />
</Button>
</Link>
<Button
variant="outline"
className="gap-2"
color="secondary"
disabled={maintenanceActive}
>
Settings
<CogIcon className="h-4 w-4" />
</Button>
</Link>
</div>
</div>
);
}

View File

@@ -0,0 +1,20 @@
import { OpenTransferDialogButton } from '@/components/common/OpenTransferDialogButton';
import { TransferProjectDialog } from '@/features/orgs/components/common/TransferProjectDialog';
import { useCallback, useState } from 'react';
function UpgradeProjectDialog() {
const [open, setOpen] = useState(false);
const handleDialogOpen = useCallback(() => setOpen(true), []);
return (
<>
<OpenTransferDialogButton
buttonText="Upgrade project"
onClick={handleDialogOpen}
/>
<TransferProjectDialog open={open} setOpen={setOpen} />
</>
);
}
export default UpgradeProjectDialog;

View File

@@ -44,7 +44,7 @@ export default function ResourcesConfirmationDialog({
const billableResources = calculateBillableResources(
{
replicas: formValues.database?.replicas,
replicas: 1,
vcpu: formValues.database?.vcpu,
memory: formValues.database?.memory,
},
@@ -128,7 +128,6 @@ export default function ResourcesConfirmationDialog({
included in the {proPlan.name} plan.
</Text>
)}
<Box className="grid grid-flow-row gap-4">
{/* <Box className="grid justify-between grid-flow-col gap-2">
<Text className="font-medium">{proPlan.name} Plan</Text>
@@ -227,7 +226,6 @@ export default function ResourcesConfirmationDialog({
</Text>
)}
</Box>
<Box className="grid grid-flow-row gap-2">
<Button
color={totalBillableVCPU > 0 ? 'primary' : 'error'}

View File

@@ -40,9 +40,16 @@ function getInitialServiceResources(
data: GetResourcesQuery,
service: Exclude<keyof GetResourcesQuery['config'], '__typename'>,
) {
const { compute, replicas, autoscaler, ...rest } =
if (service === 'postgres') {
const { compute, ...rest } = data?.config?.[service]?.resources || {};
return {
vcpu: compute?.cpu || 0,
memory: compute?.memory || 0,
rest,
};
}
const { compute, autoscaler, replicas, ...rest } =
data?.config?.[service]?.resources || {};
return {
replicas,
vcpu: compute?.cpu || 0,
@@ -103,11 +110,8 @@ export default function ResourcesForm() {
totalAvailableVCPU: totalInitialVCPU || 2000,
totalAvailableMemory: totalInitialMemory || 4096,
database: {
replicas: initialDatabaseResources.replicas || 1,
vcpu: initialDatabaseResources.vcpu || 1000,
memory: initialDatabaseResources.memory || 2048,
autoscale: !!initialDatabaseResources.autoscale || false,
maxReplicas: initialDatabaseResources.autoscale?.maxReplicas || 10,
},
hasura: {
replicas: initialHasuraResources.replicas || 1,
@@ -160,7 +164,7 @@ export default function ResourcesForm() {
const billableResources = calculateBillableResources(
{
replicas: initialDatabaseResources.replicas,
replicas: 1,
vcpu: initialDatabaseResources.vcpu,
},
{
@@ -207,12 +211,6 @@ export default function ResourcesForm() {
cpu: sanitizedValues.database.vcpu,
memory: sanitizedValues.database.memory,
},
replicas: sanitizedValues.database.replicas,
autoscaler: sanitizedValues.database.autoscale
? {
maxReplicas: sanitizedValues.database.maxReplicas,
}
: null,
...sanitizedInitialDatabaseResources.rest,
},
},
@@ -268,8 +266,6 @@ export default function ResourcesForm() {
postgres: {
resources: {
compute: null,
replicas: null,
autoscaler: null,
...sanitizedInitialDatabaseResources.rest,
},
},
@@ -341,9 +337,6 @@ export default function ResourcesForm() {
totalAvailableVCPU: 2000,
totalAvailableMemory: 4096,
database: {
replicas: 1,
maxReplicas: 1,
autoscale: false,
vcpu: 1000,
memory: 2048,
},

View File

@@ -49,7 +49,7 @@ export default function ResourcesFormFooter() {
const billableResources = calculateBillableResources(
{
replicas: database?.replicas,
replicas: 1, // database replica is always one
vcpu: database?.vcpu,
},
{

View File

@@ -43,10 +43,6 @@ fragment ServiceResources on ConfigConfig {
cpu
memory
}
replicas
autoscaler {
maxReplicas
}
}
}
storage {

View File

@@ -76,7 +76,7 @@ export const MAX_SERVICE_MEMORY =
RESOURCE_VCPU_MEMORY_RATIO *
RESOURCE_MEMORY_MULTIPLIER;
const serviceValidationSchema = Yup.object({
const genericServiceValidationSchema = Yup.object({
replicas: Yup.number()
.label('Replicas')
.required()
@@ -115,6 +115,18 @@ const serviceValidationSchema = Yup.object({
),
});
const postgresServiceValidationSchema = Yup.object({
vcpu: Yup.number()
.label('vCPUs')
.required()
.min(MIN_SERVICE_VCPU)
.max(MAX_SERVICE_VCPU),
memory: Yup.number()
.required()
.min(MIN_SERVICE_MEMORY)
.max(MAX_SERVICE_MEMORY)
});
export const resourceSettingsValidationSchema = Yup.object({
enabled: Yup.boolean(),
totalAvailableVCPU: Yup.number()
@@ -147,10 +159,10 @@ export const resourceSettingsValidationSchema = Yup.object({
parent.storage.memory ===
totalAvailableMemory,
),
database: serviceValidationSchema.required(),
hasura: serviceValidationSchema.required(),
auth: serviceValidationSchema.required(),
storage: serviceValidationSchema.required(),
database: postgresServiceValidationSchema.required(),
hasura: genericServiceValidationSchema.required(),
auth: genericServiceValidationSchema.required(),
storage: genericServiceValidationSchema.required(),
});
export type ResourceSettingsFormValues = Yup.InferType<

View File

@@ -1,17 +1,35 @@
import { useIsPlatform } from '@/features/orgs/projects/common/hooks/useIsPlatform';
import { useCurrentOrg } from '@/features/orgs/projects/hooks/useCurrentOrg';
import { useProject } from '@/features/orgs/projects/hooks/useProject';
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
import { useRouter } from 'next/router';
import { useEffect } from 'react';
/**
* Redirects to 404 page if either currentWorkspace/currentProject resolves to undefined.
* Redirects to 404 page if either currentWorkspace/currentProject resolves to undefined
* or if the current pathname is not a valid organization/project.
* Not applicable if running dashboard with local Nhost backend.
*/
export default function useNotFoundRedirect() {
const router = useRouter();
const {
query: { orgSlug, workspaceSlug, appSubdomain, updating, appSlug },
query: {
orgSlug: urlOrgSlug,
workspaceSlug: urlWorkspaceSlug,
appSubdomain: urlAppSubdomain,
updating,
appSlug: urlAppSlug,
},
isReady,
} = router;
const { project, loading: projectLoading } = useProject();
const isPlatform = useIsPlatform();
const { org, loading: orgLoading } = useCurrentOrg();
const { subdomain: projectSubdomain } = project || {};
const { slug: currentOrgSlug } = org || {};
const { currentProject, currentWorkspace, loading } =
useCurrentWorkspaceAndProject();
@@ -23,6 +41,10 @@ export default function useNotFoundRedirect() {
!isReady ||
// If the current workspace and project are not loaded, we don't want to redirect to 404
loading ||
// If the project is loading, we don't want to redirect to 404
projectLoading ||
// If the org is loading, we don't want to redirect to 404
orgLoading ||
// If we're already on the 404 page, we don't want to redirect to 404
router.pathname === '/404' ||
router.pathname === '/' ||
@@ -31,12 +53,16 @@ export default function useNotFoundRedirect() {
router.pathname === '/run-one-click-install' ||
router.pathname.includes('/orgs/_') ||
router.pathname.includes('/orgs/_/projects/_') ||
orgSlug ||
(orgSlug && appSubdomain) ||
(!isPlatform && router.pathname.includes('/orgs/local')) ||
(!isPlatform && router.pathname.includes('/orgs/[orgSlug]/projects')) ||
// If we are on a valid org and project, we don't want to redirect to 404
(urlOrgSlug && currentOrgSlug && urlAppSubdomain && projectSubdomain) ||
// If we are on a valid org and no project is selected, we don't want to redirect to 404
(urlOrgSlug && currentOrgSlug && !urlAppSubdomain && !projectSubdomain) ||
// If we are on a valid workspace and project, we don't want to redirect to 404
(workspaceSlug && currentWorkspace && appSlug && currentProject) ||
(urlWorkspaceSlug && currentWorkspace && urlAppSlug && currentProject) ||
// If we are on a valid workspace and no project is selected, we don't want to redirect to 404
(workspaceSlug && currentWorkspace && !appSlug && !currentProject)
(urlWorkspaceSlug && currentWorkspace && !urlAppSlug && !currentProject)
) {
return;
}
@@ -47,11 +73,16 @@ export default function useNotFoundRedirect() {
currentWorkspace,
isReady,
loading,
appSubdomain,
appSlug,
urlAppSubdomain,
urlAppSlug,
router,
updating,
workspaceSlug,
orgSlug,
projectLoading,
orgLoading,
currentOrgSlug,
projectSubdomain,
urlWorkspaceSlug,
urlOrgSlug,
isPlatform,
]);
}

View File

@@ -36,7 +36,7 @@ vi.mock('next/router', () => ({
const server = setupServer(
tokenQuery,
rest.get('https://local.graphql.nhost.run/v1', (_req, res, ctx) =>
rest.get('https://local.graphql.local.nhost.run/v1', (_req, res, ctx) =>
res(ctx.status(200)),
),
);
@@ -49,7 +49,7 @@ beforeAll(() => {
afterEach(() => {
server.resetHandlers(
rest.get('https://local.graphql.nhost.run/v1', (_req, res, ctx) =>
rest.get('https://local.graphql.local.nhost.run/v1', (_req, res, ctx) =>
res(ctx.status(200)),
),
);
@@ -63,33 +63,36 @@ afterAll(() => {
test('should render an empty state when GitHub is not connected', async () => {
server.use(
rest.post('https://local.graphql.nhost.run/v1', async (req, res, ctx) => {
const { operationName } = await req.json();
rest.post(
'https://local.graphql.local.nhost.run/v1',
async (req, res, ctx) => {
const { operationName } = await req.json();
if (operationName === 'GetWorkspaceAndProject') {
return res(
ctx.json({
data: {
workspaces: [
{
...mockWorkspace,
projects: [{ ...mockApplication, githubRepository: null }],
},
],
projects: [{ ...mockApplication, githubRepository: null }],
},
}),
);
}
if (operationName === 'GetWorkspaceAndProject') {
return res(
ctx.json({
data: {
workspaces: [
{
...mockWorkspace,
projects: [{ ...mockApplication, githubRepository: null }],
},
],
projects: [{ ...mockApplication, githubRepository: null }],
deployments: [],
},
}),
);
}
return res(
ctx.json({
data: {
deployments: [],
},
}),
);
}),
},
),
);
render(<OverviewDeployments />);
@@ -102,22 +105,25 @@ test('should render an empty state when GitHub is not connected', async () => {
test('should render an empty state when GitHub is connected, but there are no deployments', async () => {
server.use(
rest.post('https://local.graphql.nhost.run/v1', async (_req, res, ctx) => {
const { operationName } = await _req.json();
rest.post(
'https://local.graphql.local.nhost.run/v1',
async (_req, res, ctx) => {
const { operationName } = await _req.json();
if (operationName === 'GetWorkspaceAndProject') {
return res(
ctx.json({
data: {
workspaces: [mockWorkspace],
projects: [mockApplication],
},
}),
);
}
if (operationName === 'GetWorkspaceAndProject') {
return res(
ctx.json({
data: {
workspaces: [mockWorkspace],
projects: [mockApplication],
},
}),
);
}
return res(ctx.json({ data: { deployments: [] } }));
}),
return res(ctx.json({ data: { deployments: [] } }));
},
),
);
render(<OverviewDeployments />);
@@ -138,43 +144,46 @@ test('should render an empty state when GitHub is connected, but there are no de
test('should render a list of deployments', async () => {
server.use(
tokenQuery,
rest.post('https://local.graphql.nhost.run/v1', async (_req, res, ctx) => {
const { operationName } = await _req.json();
rest.post(
'https://local.graphql.local.nhost.run/v1',
async (_req, res, ctx) => {
const { operationName } = await _req.json();
if (operationName === 'ScheduledOrPendingDeploymentsSub') {
return res(ctx.json({ data: { deployments: [] } }));
}
if (operationName === 'ScheduledOrPendingDeploymentsSub') {
return res(ctx.json({ data: { deployments: [] } }));
}
if (operationName === 'GetWorkspaceAndProject') {
return res(
ctx.json({
data: {
workspaces: [mockWorkspace],
projects: [mockApplication],
},
}),
);
}
if (operationName === 'GetWorkspaceAndProject') {
return res(
ctx.json({
data: {
workspaces: [mockWorkspace],
projects: [mockApplication],
deployments: [
{
id: '1',
commitSHA: 'abc123',
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
deploymentStatus: 'DEPLOYED',
commitUserName: 'test.user',
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
commitMessage: 'Test commit message',
},
],
},
}),
);
}
return res(
ctx.json({
data: {
deployments: [
{
id: '1',
commitSHA: 'abc123',
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
deploymentStatus: 'DEPLOYED',
commitUserName: 'test.user',
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
commitMessage: 'Test commit message',
},
],
},
}),
);
}),
},
),
);
render(<OverviewDeployments />);
@@ -198,20 +207,53 @@ test('should render a list of deployments', async () => {
test('should disable redeployments if a deployment is already in progress', async () => {
server.use(
tokenQuery,
rest.post('https://local.graphql.nhost.run/v1', async (req, res, ctx) => {
const { operationName } = await req.json();
rest.post(
'https://local.graphql.local.nhost.run/v1',
async (req, res, ctx) => {
const { operationName } = await req.json();
if (operationName === 'ScheduledOrPendingDeploymentsSub') {
return res(
ctx.json({
data: {
deployments: [
{
id: '2',
commitSHA: 'abc234',
deploymentStartedAt: '2021-08-02T00:00:00.000Z',
deploymentEndedAt: null,
deploymentStatus: 'PENDING',
commitUserName: 'test.user',
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
commitMessage: 'Test commit message',
},
],
},
}),
);
}
if (operationName === 'GetWorkspaceAndProject') {
return res(
ctx.json({
data: {
workspaces: [mockWorkspace],
projects: [mockApplication],
},
}),
);
}
if (operationName === 'ScheduledOrPendingDeploymentsSub') {
return res(
ctx.json({
data: {
deployments: [
{
id: '2',
commitSHA: 'abc234',
deploymentStartedAt: '2021-08-02T00:00:00.000Z',
deploymentEndedAt: null,
deploymentStatus: 'PENDING',
id: '1',
commitSHA: 'abc123',
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
deploymentStatus: 'DEPLOYED',
commitUserName: 'test.user',
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
commitMessage: 'Test commit message',
@@ -220,38 +262,8 @@ test('should disable redeployments if a deployment is already in progress', asyn
},
}),
);
}
if (operationName === 'GetWorkspaceAndProject') {
return res(
ctx.json({
data: {
workspaces: [mockWorkspace],
projects: [mockApplication],
},
}),
);
}
return res(
ctx.json({
data: {
deployments: [
{
id: '1',
commitSHA: 'abc123',
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
deploymentStatus: 'DEPLOYED',
commitUserName: 'test.user',
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
commitMessage: 'Test commit message',
},
],
},
}),
);
}),
},
),
);
render(<OverviewDeployments />);

View File

@@ -37,14 +37,24 @@ function getInitialServiceResources(
data: GetResourcesQuery,
service: Exclude<keyof GetResourcesQuery['config'], '__typename'>,
) {
const { compute, replicas, autoscaler } =
if (service === 'postgres') {
const { compute, ...rest } = data?.config?.[service]?.resources || {};
return {
replicas: 1,
vcpu: compute?.cpu || 0,
memory: compute?.memory || 0,
autoscale: null,
rest,
};
}
const { compute, autoscaler, replicas, ...rest } =
data?.config?.[service]?.resources || {};
return {
replicas,
vcpu: compute?.cpu || 0,
memory: compute?.memory || 0,
autoscale: autoscaler || null,
rest,
};
}
@@ -190,12 +200,6 @@ export default function ResourcesForm() {
cpu: formValues.database.vcpu,
memory: formValues.database.memory,
},
replicas: formValues.database.replicas,
autoscaler: formValues.database.autoscale
? {
maxReplicas: formValues.database.maxReplicas,
}
: null,
}
: null,
},

View File

@@ -23,7 +23,11 @@ fragment RemoteAppGetUsers on users {
disabled
}
query remoteAppGetUsers($where: users_bool_exp!, $limit: Int!, $offset: Int!) {
query remoteAppGetUsersAndAuthRoles(
$where: users_bool_exp!
$limit: Int!
$offset: Int!
) {
users(
where: $where
limit: $limit
@@ -42,6 +46,9 @@ query remoteAppGetUsers($where: users_bool_exp!, $limit: Int!, $offset: Int!) {
count
}
}
authRoles {
role
}
}
query remoteAppGetUsersCustom(

View File

@@ -0,0 +1,6 @@
import { AnalyticsBrowser } from "@segment/analytics-next";
export const analytics = AnalyticsBrowser.load({
cdnURL: process.env.NEXT_PUBLIC_SEGMENT_CDN_URL!,
writeKey: process.env.NEXT_PUBLIC_ANALYTICS_WRITE_KEY!,
});

View File

@@ -0,0 +1,35 @@
import { isEmptyValue } from './utils';
test('returns true when the value is undefined or "undefined"', () => {
expect(isEmptyValue(undefined)).toBe(true)
expect(isEmptyValue('undefined')).toBe(true)
})
test('returns true when the value is null or "null"', () => {
expect(isEmptyValue(null)).toBe(true)
expect(isEmptyValue('null')).toBe(true)
})
test('returns true when the value is an empty string', () => {
expect(isEmptyValue('')).toBe(true)
})
test('returns true when the value is "NaN" or not a number', () => {
expect(isEmptyValue("NaN")).toBe(true)
expect(isEmptyValue(NaN)).toBe(true)
})
test('returns true when the value is an empty object or array', () => {
expect(isEmptyValue({})).toBe(true)
expect(isEmptyValue([])).toBe(true)
})
test('returns false when the value is has at least one property or the array has at least on item in it', () => {
expect(isEmptyValue({foo: 'Bar'})).toBe(false)
expect(isEmptyValue(['foo', 'bar'])).toBe(false)
})
test('returns false when the value is either a number or string', () => {
expect(isEmptyValue(1234)).toBe(false)
expect(isEmptyValue('Hello there')).toBe(false)
})

View File

@@ -4,3 +4,20 @@ import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
export function isEmptyValue<T>(value: T) {
return (
value === undefined ||
value === 'undefined' ||
value === null ||
value === '' ||
value === 'null' ||
value === 'NaN' ||
(typeof value === 'number' && Number.isNaN(value)) ||
(typeof value === 'object' && Object.keys(value).length === 0)
)
}
export function isNotEmptyValue<T>(value: T): value is Exclude<T, undefined | null> {
return !isEmptyValue(value)
}

View File

@@ -13,15 +13,15 @@ import { CreateUserForm } from '@/features/authentication/users/components/Creat
import { UsersBody } from '@/features/authentication/users/components/UsersBody';
import { ProjectLayout } from '@/features/orgs/layout/ProjectLayout';
import { useRemoteApplicationGQLClient } from '@/hooks/useRemoteApplicationGQLClient';
import type { RemoteAppGetUsersQuery } from '@/utils/__generated__/graphql';
import { useRemoteAppGetUsersQuery } from '@/utils/__generated__/graphql';
import type { RemoteAppGetUsersAndAuthRolesQuery } from '@/utils/__generated__/graphql';
import { useRemoteAppGetUsersAndAuthRolesQuery } from '@/utils/__generated__/graphql';
import debounce from 'lodash.debounce';
import Router, { useRouter } from 'next/router';
import type { ChangeEvent, ReactElement } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
export type RemoteAppUser = Exclude<
RemoteAppGetUsersQuery['users'][0],
RemoteAppGetUsersAndAuthRolesQuery['users'][0],
'__typename'
>;
@@ -75,7 +75,7 @@ export default function UsersPage() {
data: dataRemoteAppUsers,
refetch: refetchProjectUsers,
loading: loadingRemoteAppUsersQuery,
} = useRemoteAppGetUsersQuery({
} = useRemoteAppGetUsersAndAuthRolesQuery({
variables: remoteAppGetUserVariables,
client: remoteProjectGQLClient,
});

View File

@@ -1,3 +1,4 @@
import Analytics from '@/components/analytics/analytics';
import { DialogProvider } from '@/components/common/DialogProvider';
import { UIProvider } from '@/components/common/UIProvider';
import { TreeNavStateProvider } from '@/components/layout/MainNav/TreeNavStateContext';
@@ -28,14 +29,12 @@ import '@fontsource/roboto-mono/400.css';
import '@fontsource/roboto-mono/500.css';
import { NhostProvider } from '@nhost/nextjs';
import { NhostApolloProvider } from '@nhost/react-apollo';
import * as snippet from '@segment/snippet';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import type { NextPage } from 'next';
import { PagesProgressBar as ProgressBar } from 'next-nprogress-bar';
import { DefaultSeo } from 'next-seo';
import type { AppProps } from 'next/app';
import { useRouter } from 'next/router';
import Script from 'next/script';
import type { ReactElement } from 'react';
import { useEffect } from 'react';
import { Toaster } from 'react-hot-toast';
@@ -62,20 +61,6 @@ function MyApp({
const isPlatform = useIsPlatform();
const router = useRouter();
// segment snippet
function renderSnippet() {
const opts = {
apiKey: process.env.NEXT_PUBLIC_ANALYTICS_WRITE_KEY,
page: true,
};
if (process.env.NODE_ENV === 'development') {
return snippet.max(opts);
}
return snippet.min(opts);
}
useEffect(() => {
// track page changes
const handleRouteChange = () => {
@@ -103,12 +88,7 @@ function MyApp({
<UIProvider>
<Toaster position="bottom-center" />
{isPlatform && (
<Script
id="segment"
dangerouslySetInnerHTML={{ __html: renderSnippet() }}
/>
)}
{isPlatform && <Analytics />}
<ThemeProvider
colorPreferenceStorageKey={COLOR_PREFERENCE_STORAGE_KEY}

View File

@@ -30,7 +30,7 @@ interface LogsFilters {
}
export default function LogsPage() {
const { project } = useProject();
const { project, loading: loadingProject } = useProject();
// create a client that sends http requests to Hasura but websocket requests to Bragi
const clientWithSplit = useRemoteApplicationGQLClientWithSubscriptions();
@@ -43,13 +43,19 @@ export default function LogsPage() {
service: AvailableLogsService.ALL,
});
const { data, error, subscribeToMore, client, loading, refetch } =
useGetProjectLogsQuery({
variables: { appID: project?.id, ...filters },
client: clientWithSplit,
fetchPolicy: 'cache-and-network',
notifyOnNetworkStatusChange: true,
});
const {
data,
error,
subscribeToMore,
client,
loading: loadingLogs,
} = useGetProjectLogsQuery({
variables: { appID: project?.id, ...filters },
client: clientWithSplit,
fetchPolicy: 'cache-and-network',
notifyOnNetworkStatusChange: true,
skip: !project,
});
const subscribeToMoreLogs = useCallback(
() =>
@@ -102,15 +108,19 @@ export default function LogsPage() {
);
useEffect(() => {
if (!project || loadingProject) {
return;
}
if (filters.to && subscriptionReturn.current !== null) {
subscriptionReturn.current();
subscriptionReturn.current = null;
return () => {};
return;
}
if (filters.to) {
return () => {};
return;
}
if (subscriptionReturn.current) {
@@ -120,18 +130,17 @@ export default function LogsPage() {
// This will open the websocket connection and it will return a function to close it.
subscriptionReturn.current = subscribeToMoreLogs();
return () => {};
}, [filters, subscribeToMoreLogs, client]);
}, [filters, subscribeToMoreLogs, client, project, loadingProject]);
const onSubmitFilterValues = useCallback(
async (values: LogsFilterFormValues) => {
setFilters({ ...(values as LogsFilters) });
await refetch();
},
[setFilters, refetch],
[setFilters],
);
const loading = loadingProject || loadingLogs;
return (
<div className="flex h-full w-full flex-col">
<RetryableErrorBoundary>

View File

@@ -13,15 +13,16 @@ import { useRemoteApplicationGQLClient } from '@/features/orgs/hooks/useRemoteAp
import { ProjectLayout } from '@/features/orgs/layout/ProjectLayout';
import { CreateUserForm } from '@/features/orgs/projects/authentication/users/components/CreateUserForm';
import { UsersBody } from '@/features/orgs/projects/authentication/users/components/UsersBody';
import type { RemoteAppGetUsersQuery } from '@/utils/__generated__/graphql';
import { useRemoteAppGetUsersQuery } from '@/utils/__generated__/graphql';
import { getUserRoles } from '@/features/projects/roles/settings/utils/getUserRoles';
import type { RemoteAppGetUsersAndAuthRolesQuery } from '@/utils/__generated__/graphql';
import { useRemoteAppGetUsersAndAuthRolesQuery } from '@/utils/__generated__/graphql';
import debounce from 'lodash.debounce';
import Router, { useRouter } from 'next/router';
import type { ChangeEvent, ReactElement } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
export type RemoteAppUser = Exclude<
RemoteAppGetUsersQuery['users'][0],
RemoteAppGetUsersAndAuthRolesQuery['users'][0],
'__typename'
>;
@@ -72,14 +73,13 @@ export default function UsersPage() {
);
const {
data: dataRemoteAppUsers,
data: dataRemoteAppUsersAndAuthRoles,
refetch: refetchProjectUsers,
loading: loadingRemoteAppUsersQuery,
} = useRemoteAppGetUsersQuery({
} = useRemoteAppGetUsersAndAuthRolesQuery({
variables: remoteAppGetUserVariables,
client: remoteProjectGQLClient,
});
/**
* This function will remove query params from the URL.
*
@@ -175,13 +175,13 @@ export default function UsersPage() {
}
const userCount = searchString
? dataRemoteAppUsers?.filteredUsersAggreggate.aggregate.count
: dataRemoteAppUsers?.usersAggregate?.aggregate?.count;
? dataRemoteAppUsersAndAuthRoles?.filteredUsersAggreggate.aggregate.count
: dataRemoteAppUsersAndAuthRoles?.usersAggregate?.aggregate?.count;
setNrOfPages(Math.ceil(userCount / limit.current));
}, [
dataRemoteAppUsers?.filteredUsersAggreggate.aggregate.count,
dataRemoteAppUsers?.usersAggregate.aggregate.count,
dataRemoteAppUsersAndAuthRoles?.filteredUsersAggreggate.aggregate.count,
dataRemoteAppUsersAndAuthRoles?.usersAggregate.aggregate.count,
loadingRemoteAppUsersQuery,
searchString,
]);
@@ -208,17 +208,26 @@ export default function UsersPage() {
}
const users = useMemo(
() => dataRemoteAppUsers?.users.map((user) => user) ?? [],
[dataRemoteAppUsers],
() => dataRemoteAppUsersAndAuthRoles?.users.map((user) => user) ?? [],
[dataRemoteAppUsersAndAuthRoles],
);
const usersCount = useMemo(
() => dataRemoteAppUsers?.usersAggregate?.aggregate?.count ?? -1,
[dataRemoteAppUsers],
() =>
dataRemoteAppUsersAndAuthRoles?.usersAggregate?.aggregate?.count ?? -1,
[dataRemoteAppUsersAndAuthRoles],
);
const authRoles = (dataRemoteAppUsersAndAuthRoles?.authRoles || []).map(
(authRole) => authRole.role,
);
const allAvailableProjectRoles = useMemo(
() => getUserRoles(authRoles),
[authRoles],
);
const thereAreUsers =
dataRemoteAppUsers?.filteredUsersAggreggate.aggregate.count ||
dataRemoteAppUsersAndAuthRoles?.filteredUsersAggreggate.aggregate.count ||
usersCount <= 0;
if (loadingRemoteAppUsersQuery) {
@@ -315,8 +324,8 @@ export default function UsersPage() {
OAuth Providers
</Text>
</Box>
{dataRemoteAppUsers?.filteredUsersAggreggate.aggregate.count ===
0 &&
{dataRemoteAppUsersAndAuthRoles?.filteredUsersAggreggate.aggregate
.count === 0 &&
usersCount !== 0 && (
<Box className="flex flex-col items-center justify-center space-y-5 border-x border-b px-48 py-12">
<UserIcon
@@ -336,22 +345,27 @@ export default function UsersPage() {
)}
{thereAreUsers && (
<div className="grid grid-flow-row gap-4">
<UsersBody users={users} onSubmit={refetchProjectUsers} />
<UsersBody
users={users}
onSubmit={refetchProjectUsers}
allAvailableProjectRoles={allAvailableProjectRoles}
/>
<Pagination
className="px-2"
totalNrOfPages={nrOfPages}
currentPageNumber={currentPage}
totalNrOfElements={
searchString
? dataRemoteAppUsers?.filteredUsersAggreggate.aggregate
.count
: dataRemoteAppUsers?.usersAggregate?.aggregate?.count
? dataRemoteAppUsersAndAuthRoles?.filteredUsersAggreggate
.aggregate.count
: dataRemoteAppUsersAndAuthRoles?.usersAggregate
?.aggregate?.count
}
itemsLabel="users"
elementsPerPage={
searchString
? dataRemoteAppUsers?.filteredUsersAggreggate.aggregate
.count
? dataRemoteAppUsersAndAuthRoles?.filteredUsersAggreggate
.aggregate.count
: limit.current
}
onPrevPageClick={async () => {

View File

@@ -1,31 +1,20 @@
'use client';
import { BaseLayout } from '@/components/layout/BaseLayout';
import { Header } from '@/components/layout/Header';
import { RetryableErrorBoundary } from '@/components/presentational/RetryableErrorBoundary';
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
import { FinishOrgCreationProcess } from '@/features/orgs/components/common/FinishOrgCreationProcess';
import { useFinishOrgCreation } from '@/features/orgs/hooks/useFinishOrgCreation';
import { useIsPlatform } from '@/features/projects/common/hooks/useIsPlatform';
import {
CheckoutStatus,
useGetOrganizationByIdLazyQuery,
usePostOrganizationRequestMutation,
} from '@/utils/__generated__/graphql';
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
import type { PostOrganizationRequestMutation } from '@/utils/__generated__/graphql';
import { useAuthenticationStatus } from '@nhost/nextjs';
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
import { useCallback, useEffect } from 'react';
export default function PostCheckout() {
const router = useRouter();
const { session_id } = router.query;
const isPlatform = useIsPlatform();
const [loading, setLoading] = useState(false);
const [postOrganizationRequest] = usePostOrganizationRequestMutation();
const { isAuthenticated, isLoading } = useAuthenticationStatus();
const [fetchOrg] = useGetOrganizationByIdLazyQuery();
const [postOrganizationRequestStatus, setPostOrganizationRequestStatus] =
useState<CheckoutStatus | null>(null);
useEffect(() => {
if (!isPlatform || isLoading || isAuthenticated) {
return;
@@ -34,99 +23,30 @@ export default function PostCheckout() {
router.push('/signin');
}, [isLoading, isAuthenticated, router, isPlatform]);
useEffect(() => {
(async () => {
if (session_id && isAuthenticated) {
setLoading(true);
const onCompleted = useCallback(
(
data: PostOrganizationRequestMutation['billingPostOrganizationRequest'],
) => {
const { Slug } = data;
router.push(`/orgs/${Slug}/projects`);
},
[router],
);
execPromiseWithErrorToast(
async () => {
const {
data: { billingPostOrganizationRequest },
} = await postOrganizationRequest({
variables: {
sessionID: session_id as string,
},
});
const { Status, Slug } = billingPostOrganizationRequest;
setLoading(false);
setPostOrganizationRequestStatus(Status);
switch (Status) {
case CheckoutStatus.Completed:
await router.push(`/orgs/${Slug}/projects`);
break;
case CheckoutStatus.Expired:
throw new Error('Request to create organization has expired');
case CheckoutStatus.Open:
// TODO discuss what to do in this case
throw new Error(
'Request to create organization with status "Open"',
);
default:
break;
}
},
{
loadingMessage: 'Processing new organization request',
successMessage:
'The new organization has been created successfully.',
errorMessage:
'An error occurred while creating the new organization.',
},
);
}
})();
}, [session_id, postOrganizationRequest, router, fetchOrg, isAuthenticated]);
const [loading, status] = useFinishOrgCreation({ onCompleted });
return (
<BaseLayout className="flex h-screen flex-col">
<Header className="flex py-1" />
<div className="flex h-screen w-full flex-col">
<RetryableErrorBoundary errorMessageProps={{ className: 'pt-20' }}>
<div className="relative flex flex-auto overflow-x-hidden">
{loading && (
<div className="flex h-full w-full flex-col items-center justify-center space-y-2">
<ActivityIndicator
circularProgressProps={{ className: 'w-6 h-6' }}
/>
<span>Processing new organization request</span>
</div>
)}
{!loading &&
postOrganizationRequestStatus === CheckoutStatus.Completed && (
<div className="flex h-full w-full flex-col items-center justify-center space-y-2">
<ActivityIndicator
circularProgressProps={{ className: 'w-6 h-6' }}
/>
<span>Organization created successfully. Redirecting...</span>
</div>
)}
{!loading &&
postOrganizationRequestStatus === CheckoutStatus.Expired && (
<div className="flex h-full w-full flex-col items-center justify-center space-y-2">
<span>
Error occurred while creating the organization. Please try
again.
</span>
</div>
)}
{!loading &&
postOrganizationRequestStatus === CheckoutStatus.Open && (
<div className="flex h-full w-full flex-col items-center justify-center space-y-2">
<span>Organization creation is pending...</span>
</div>
)}
</div>
</RetryableErrorBoundary>
<FinishOrgCreationProcess
loading={loading}
status={status}
loadingMessage="Processing new organization request"
successMessage="Organization created successfully. Redirecting..."
pendingMessage="Organization creation is pending..."
errorMessage="Error occurred while creating the organization. Please try again."
/>
</div>
</BaseLayout>
);

View File

@@ -1,7 +1,17 @@
import '@testing-library/jest-dom/extend-expect';
import matchers from '@testing-library/jest-dom/matchers';
import fetch from 'node-fetch';
import { expect } from 'vitest';
import { expect, vi } from 'vitest';
// Mock the ResizeObserver
const ResizeObserverMock = vi.fn(() => ({
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn(),
}));
// Stub the global ResizeObserver
vi.stubGlobal('ResizeObserver', ResizeObserverMock);
// @ts-ignore
global.fetch = fetch;

View File

@@ -141,3 +141,56 @@ export const mockOrganization: Organization = {
],
__typename: 'organizations',
};
export const mockOrganizations: Organization[] = [
{
id: 'org-1',
name: "User's Personal Organization",
slug: 'ynrnjteywyxjhlmgzgif',
status: Organization_Status_Enum.Ok,
plan: {
id: 'starter',
name: 'Starter',
price: 0,
deprecated: false,
individual: true,
isFree: true,
featureMaxDbSize: 1,
__typename: 'plans',
},
apps: [],
members: [],
__typename: 'organizations',
},
{
id: 'org-2',
name: 'Second First Try',
slug: 'kbdoxvsoisppkrwzjhwl',
status: Organization_Status_Enum.Ok,
plan: {
id: 'pro',
name: 'Pro',
price: 25,
deprecated: false,
individual: false,
isFree: false,
featureMaxDbSize: 10,
__typename: 'plans',
},
apps: [],
members: [],
__typename: 'organizations',
},
];
export const newOrg: Organization = {
...mockOrganization,
id: 'newOrg',
name: 'New Org',
slug: 'new-org',
};
export const mockOrganizationsWithNewOrg: Organization[] = [
...mockOrganizations,
newOrg,
];

View File

@@ -0,0 +1,22 @@
import { mockOrganization, mockOrganizations } from '@/tests/mocks';
import nhostGraphQLLink from './nhostGraphQLLink';
export const getOrganizations = nhostGraphQLLink.query(
'getOrganizations',
(_req, res, ctx) =>
res(
ctx.data({
organizations: mockOrganizations,
}),
),
);
export const getOrganization = nhostGraphQLLink.query(
'getOrganization',
(_req, res, ctx) =>
res(
ctx.data({
organizations: [{ ...mockOrganization }],
}),
),
);

View File

@@ -0,0 +1,12 @@
import { mockApplication } from '@/tests/mocks';
import nhostGraphQLLink from './nhostGraphQLLink';
export const getProjectQuery = nhostGraphQLLink.query(
'getProject',
(_req, res, ctx) =>
res(
ctx.data({
apps: [{ ...mockApplication, githubRepository: null }],
}),
),
);

View File

@@ -1,5 +1,7 @@
import { graphql } from 'msw';
const nhostGraphQLLink = graphql.link('https://local.graphql.nhost.run/v1');
const nhostGraphQLLink = graphql.link(
'https://local.graphql.local.nhost.run/v1',
);
export default nhostGraphQLLink;

View File

@@ -0,0 +1,22 @@
import nhostGraphQLLink from './nhostGraphQLLink';
export const organizationMemberInvites = nhostGraphQLLink.query(
'organizationMemberInvites',
(_req, res, ctx) => res(ctx.data({ organizationMemberInvites: [] })),
);
export const organizationNewRequests = nhostGraphQLLink.query(
'organizationNewRequests',
(_req, res, ctx) =>
res(
ctx.data({
organizationNewRequests: [
{
id: 'org-request-id-1',
sessionID: 'session-id-1',
__typename: 'organization_new_request',
},
],
}),
),
);

View File

@@ -0,0 +1,73 @@
import nhostGraphQLLink from './nhostGraphQLLink';
export const prefetchNewAppQuery = nhostGraphQLLink.query(
'PrefetchNewApp',
(_req, res, ctx) =>
res(
ctx.data({
regions: [
{
id: 'dd6f8e01-35a9-4ba6-8dc6-ed972f2db93c',
city: 'Frankfurt',
active: true,
country: { code: 'DE', name: 'Germany', __typename: 'countries' },
__typename: 'regions',
},
{
id: 'd44dc594-022f-4aa7-84b2-0cebee5f1d13',
city: 'London',
active: false,
country: {
code: 'GB',
name: 'United Kingdom',
__typename: 'countries',
},
__typename: 'regions',
},
{
id: '55985cd4-af14-4d2a-90a5-2a1253ebc1db',
city: 'N. Virginia',
active: true,
country: {
code: 'US',
name: 'United States of America',
__typename: 'countries',
},
__typename: 'regions',
},
{
id: '8fe50a9b-ef48-459c-9dd0-a2fd28968224',
city: 'Singapore',
active: false,
country: { code: 'SG', name: 'Singapore', __typename: 'countries' },
__typename: 'regions',
},
],
plans: [
{
id: 'dc5e805e-1bef-4d43-809e-9fdf865e211a',
name: 'Pro',
isDefault: false,
isFree: false,
price: 25,
featureBackupEnabled: true,
featureCustomDomainsEnabled: true,
featureMaxDbSize: 10,
__typename: 'plans',
},
{
id: '9860b992-5658-4031-8580-d8135e18db7c',
name: 'Team',
isDefault: false,
isFree: false,
price: 599,
featureBackupEnabled: true,
featureCustomDomainsEnabled: true,
featureMaxDbSize: 10,
__typename: 'plans',
},
],
workspaces: [],
}),
),
);

View File

@@ -1,7 +1,7 @@
import { rest } from 'msw';
const hasuraMetadataQuery = rest.post(
'https://local.hasura.nhost.run/v1/metadata',
'https://local.hasura.local.nhost.run/v1/metadata',
(_req, res, ctx) =>
res(
ctx.delay(250),

View File

@@ -1,7 +1,7 @@
import { rest } from 'msw';
const tableQuery = rest.post(
'https://local.hasura.nhost.run/v2/query',
'https://local.hasura.local.nhost.run/v2/query',
async (req, res, ctx) => {
const body = await req.json();

View File

@@ -3,7 +3,7 @@ import type { NhostSession } from '@nhost/nextjs';
import { rest } from 'msw';
const tokenQuery = rest.post(
`https://local.auth.nhost.run/v1/token`,
`https://local.auth.local.nhost.run/v1/token`,
(_req, res, ctx) =>
res(
ctx.json<NhostSession>({

View File

@@ -24,6 +24,8 @@ import {
import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime';
import type { PropsWithChildren, ReactElement } from 'react';
import { Toaster } from 'react-hot-toast';
import { vi } from 'vitest';
import nhostGraphQLLink from '../msw/mocks/graphql/nhostGraphQLLink';
// Client-side cache, shared for the whole session of the user in the browser.
const emotionCache = createEmotionCache();
@@ -33,13 +35,14 @@ process.env = {
NODE_ENV: 'development',
NEXT_PUBLIC_NHOST_PLATFORM: 'false',
NEXT_PUBLIC_ENV: 'dev',
NEXT_PUBLIC_NHOST_AUTH_URL: 'https://local.auth.nhost.run/v1',
NEXT_PUBLIC_NHOST_FUNCTIONS_URL: 'https://local.functions.nhost.run/v1',
NEXT_PUBLIC_NHOST_GRAPHQL_URL: 'https://local.graphql.nhost.run/v1',
NEXT_PUBLIC_NHOST_STORAGE_URL: 'https://local.storage.nhost.run/v1',
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL: 'https://local.hasura.nhost.run',
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL: 'https://local.hasura.nhost.run',
NEXT_PUBLIC_NHOST_HASURA_API_URL: 'https://local.hasura.nhost.run',
NEXT_PUBLIC_NHOST_AUTH_URL: 'https://local.auth.local.nhost.run/v1',
NEXT_PUBLIC_NHOST_FUNCTIONS_URL: 'https://local.functions.local.nhost.run/v1',
NEXT_PUBLIC_NHOST_GRAPHQL_URL: 'https://local.graphql.local.nhost.run/v1',
NEXT_PUBLIC_NHOST_STORAGE_URL: 'https://local.storage.local.nhost.run/v1',
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL: 'https://local.hasura.local.nhost.run',
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL:
'https://local.hasura.local.nhost.run',
NEXT_PUBLIC_NHOST_HASURA_API_URL: 'https://local.hasura.local.nhost.run',
};
export const queryClient = new QueryClient({
@@ -66,7 +69,7 @@ function Providers({ children }: PropsWithChildren<{}>) {
nhost={nhost}
generateLinks={() => [
createHttpLink({
uri: 'https://local.graphql.nhost.run/v1',
uri: 'https://local.graphql.local.nhost.run/v1',
}),
]}
>
@@ -109,5 +112,53 @@ async function waitForElementToBeRemoved<T>(
}
}
const graphqlRequestHandlerFactory = (
operationName: string,
type: 'mutation' | 'query',
responsePromise,
) =>
nhostGraphQLLink[type](operationName, async (_req, res, ctx) => {
const data = await responsePromise;
return res(ctx.data(data));
});
/* Helper function to pause responses to be able to test loading states */
export const createGraphqlMockResolver = (
operationName: string,
type: 'mutation' | 'query',
defaultResponse?: any,
) => {
let resolver;
const responsePromise = new Promise((resolve) => {
resolver = resolve;
});
return {
handler: graphqlRequestHandlerFactory(operationName, type, responsePromise),
resolve: (response = undefined) => resolver(response ?? defaultResponse),
};
};
export const mockPointerEvent = () => {
// Note: Workaround based on https://github.com/radix-ui/primitives/issues/1382#issuecomment-1122069313
class MockPointerEvent extends Event {
button: number;
ctrlKey: boolean;
pointerType: string;
constructor(type: string, props: PointerEventInit) {
super(type, props);
this.button = props.button || 0;
this.ctrlKey = props.ctrlKey || false;
this.pointerType = props.pointerType || 'mouse';
}
}
window.PointerEvent = MockPointerEvent as any;
window.HTMLElement.prototype.scrollIntoView = vi.fn();
window.HTMLElement.prototype.releasePointerCapture = vi.fn();
window.HTMLElement.prototype.hasPointerCapture = vi.fn();
};
export * from '@testing-library/react';
export { render, waitForElementToBeRemoved };

View File

@@ -33,13 +33,14 @@ process.env = {
NODE_ENV: 'development',
NEXT_PUBLIC_NHOST_PLATFORM: 'false',
NEXT_PUBLIC_ENV: 'dev',
NEXT_PUBLIC_NHOST_AUTH_URL: 'https://local.auth.nhost.run/v1',
NEXT_PUBLIC_NHOST_FUNCTIONS_URL: 'https://local.functions.nhost.run/v1',
NEXT_PUBLIC_NHOST_GRAPHQL_URL: 'https://local.graphql.nhost.run/v1',
NEXT_PUBLIC_NHOST_STORAGE_URL: 'https://local.storage.nhost.run/v1',
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL: 'https://local.hasura.nhost.run',
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL: 'https://local.hasura.nhost.run',
NEXT_PUBLIC_NHOST_HASURA_API_URL: 'https://local.hasura.nhost.run',
NEXT_PUBLIC_NHOST_AUTH_URL: 'https://local.auth.local.nhost.run/v1',
NEXT_PUBLIC_NHOST_FUNCTIONS_URL: 'https://local.functions.local.nhost.run/v1',
NEXT_PUBLIC_NHOST_GRAPHQL_URL: 'https://local.graphql.local.nhost.run/v1',
NEXT_PUBLIC_NHOST_STORAGE_URL: 'https://local.storage.local.nhost.run/v1',
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL: 'https://local.hasura.local.nhost.run',
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL:
'https://local.hasura.local.nhost.run',
NEXT_PUBLIC_NHOST_HASURA_API_URL: 'https://local.hasura.local.nhost.run',
};
export const queryClient = new QueryClient({
@@ -66,7 +67,7 @@ function Providers({ children }: PropsWithChildren<{}>) {
nhost={nhost}
generateLinks={() => [
createHttpLink({
uri: 'https://local.graphql.nhost.run/v1',
uri: 'https://local.graphql.local.nhost.run/v1',
}),
]}
>

View File

@@ -1283,7 +1283,7 @@ export type ConfigConfig = {
/** Configuration for observability service */
observability: ConfigObservability;
/** Configuration for postgres service */
postgres?: Maybe<ConfigPostgres>;
postgres: ConfigPostgres;
/** Configuration for third party providers like SMTP, SMS, etc. */
provider?: Maybe<ConfigProvider>;
/** Configuration for storage service */
@@ -1314,7 +1314,7 @@ export type ConfigConfigInsertInput = {
graphql?: InputMaybe<ConfigGraphqlInsertInput>;
hasura: ConfigHasuraInsertInput;
observability: ConfigObservabilityInsertInput;
postgres?: InputMaybe<ConfigPostgresInsertInput>;
postgres: ConfigPostgresInsertInput;
provider?: InputMaybe<ConfigProviderInsertInput>;
storage?: InputMaybe<ConfigStorageInsertInput>;
};
@@ -2247,7 +2247,7 @@ export type ConfigPortComparisonExp = {
export type ConfigPostgres = {
__typename?: 'ConfigPostgres';
/** Resources for the service */
resources?: Maybe<ConfigPostgresResources>;
resources: ConfigPostgresResources;
settings?: Maybe<ConfigPostgresSettings>;
/**
* Version of postgres, you can see available versions in the URL below:
@@ -2266,7 +2266,7 @@ export type ConfigPostgresComparisonExp = {
};
export type ConfigPostgresInsertInput = {
resources?: InputMaybe<ConfigPostgresResourcesInsertInput>;
resources: ConfigPostgresResourcesInsertInput;
settings?: InputMaybe<ConfigPostgresSettingsInsertInput>;
version?: InputMaybe<Scalars['String']>;
};
@@ -2274,43 +2274,50 @@ export type ConfigPostgresInsertInput = {
/** Resources for the service */
export type ConfigPostgresResources = {
__typename?: 'ConfigPostgresResources';
autoscaler?: Maybe<ConfigAutoscaler>;
compute?: Maybe<ConfigResourcesCompute>;
enablePublicAccess?: Maybe<Scalars['Boolean']>;
networking?: Maybe<ConfigNetworking>;
/** Number of replicas for a service */
replicas?: Maybe<Scalars['ConfigUint8']>;
storage?: Maybe<ConfigPostgresStorage>;
storage: ConfigPostgresResourcesStorage;
};
export type ConfigPostgresResourcesComparisonExp = {
_and?: InputMaybe<Array<ConfigPostgresResourcesComparisonExp>>;
_not?: InputMaybe<ConfigPostgresResourcesComparisonExp>;
_or?: InputMaybe<Array<ConfigPostgresResourcesComparisonExp>>;
autoscaler?: InputMaybe<ConfigAutoscalerComparisonExp>;
compute?: InputMaybe<ConfigResourcesComputeComparisonExp>;
enablePublicAccess?: InputMaybe<ConfigBooleanComparisonExp>;
networking?: InputMaybe<ConfigNetworkingComparisonExp>;
replicas?: InputMaybe<ConfigUint8ComparisonExp>;
storage?: InputMaybe<ConfigPostgresStorageComparisonExp>;
storage?: InputMaybe<ConfigPostgresResourcesStorageComparisonExp>;
};
export type ConfigPostgresResourcesInsertInput = {
autoscaler?: InputMaybe<ConfigAutoscalerInsertInput>;
compute?: InputMaybe<ConfigResourcesComputeInsertInput>;
enablePublicAccess?: InputMaybe<Scalars['Boolean']>;
networking?: InputMaybe<ConfigNetworkingInsertInput>;
replicas?: InputMaybe<Scalars['ConfigUint8']>;
storage?: InputMaybe<ConfigPostgresStorageInsertInput>;
storage: ConfigPostgresResourcesStorageInsertInput;
};
export type ConfigPostgresResourcesStorage = {
__typename?: 'ConfigPostgresResourcesStorage';
capacity: Scalars['ConfigUint32'];
};
export type ConfigPostgresResourcesStorageComparisonExp = {
_and?: InputMaybe<Array<ConfigPostgresResourcesStorageComparisonExp>>;
_not?: InputMaybe<ConfigPostgresResourcesStorageComparisonExp>;
_or?: InputMaybe<Array<ConfigPostgresResourcesStorageComparisonExp>>;
capacity?: InputMaybe<ConfigUint32ComparisonExp>;
};
export type ConfigPostgresResourcesStorageInsertInput = {
capacity: Scalars['ConfigUint32'];
};
export type ConfigPostgresResourcesStorageUpdateInput = {
capacity?: InputMaybe<Scalars['ConfigUint32']>;
};
export type ConfigPostgresResourcesUpdateInput = {
autoscaler?: InputMaybe<ConfigAutoscalerUpdateInput>;
compute?: InputMaybe<ConfigResourcesComputeUpdateInput>;
enablePublicAccess?: InputMaybe<Scalars['Boolean']>;
networking?: InputMaybe<ConfigNetworkingUpdateInput>;
replicas?: InputMaybe<Scalars['ConfigUint8']>;
storage?: InputMaybe<ConfigPostgresStorageUpdateInput>;
storage?: InputMaybe<ConfigPostgresResourcesStorageUpdateInput>;
};
export type ConfigPostgresSettings = {
@@ -2413,27 +2420,6 @@ export type ConfigPostgresSettingsUpdateInput = {
workMem?: InputMaybe<Scalars['String']>;
};
export type ConfigPostgresStorage = {
__typename?: 'ConfigPostgresStorage';
/** GiB */
capacity: Scalars['ConfigUint32'];
};
export type ConfigPostgresStorageComparisonExp = {
_and?: InputMaybe<Array<ConfigPostgresStorageComparisonExp>>;
_not?: InputMaybe<ConfigPostgresStorageComparisonExp>;
_or?: InputMaybe<Array<ConfigPostgresStorageComparisonExp>>;
capacity?: InputMaybe<ConfigUint32ComparisonExp>;
};
export type ConfigPostgresStorageInsertInput = {
capacity: Scalars['ConfigUint32'];
};
export type ConfigPostgresStorageUpdateInput = {
capacity?: InputMaybe<Scalars['ConfigUint32']>;
};
export type ConfigPostgresUpdateInput = {
resources?: InputMaybe<ConfigPostgresResourcesUpdateInput>;
settings?: InputMaybe<ConfigPostgresSettingsUpdateInput>;
@@ -27633,7 +27619,7 @@ export type GetAiSettingsQueryVariables = Exact<{
}>;
export type GetAiSettingsQuery = { __typename?: 'query_root', config?: { __typename?: 'ConfigConfig', postgres?: { __typename?: 'ConfigPostgres', version?: string | null } | null, ai?: { __typename?: 'ConfigAI', version?: string | null, webhookSecret: string, autoEmbeddings?: { __typename?: 'ConfigAIAutoEmbeddings', synchPeriodMinutes?: any | null } | null, openai: { __typename?: 'ConfigAIOpenai', apiKey: string, organization?: string | null }, resources: { __typename?: 'ConfigAIResources', compute: { __typename?: 'ConfigComputeResources', cpu: any, memory: any } } } | null } | null };
export type GetAiSettingsQuery = { __typename?: 'query_root', config?: { __typename?: 'ConfigConfig', postgres: { __typename?: 'ConfigPostgres', version?: string | null }, ai?: { __typename?: 'ConfigAI', version?: string | null, webhookSecret: string, autoEmbeddings?: { __typename?: 'ConfigAIAutoEmbeddings', synchPeriodMinutes?: any | null } | null, openai: { __typename?: 'ConfigAIOpenai', apiKey: string, organization?: string | null }, resources: { __typename?: 'ConfigAIResources', compute: { __typename?: 'ConfigComputeResources', cpu: any, memory: any } } } | null } | null };
export type GetAuthenticationSettingsQueryVariables = Exact<{
appId: Scalars['uuid'];
@@ -27647,7 +27633,7 @@ export type GetPostgresSettingsQueryVariables = Exact<{
}>;
export type GetPostgresSettingsQuery = { __typename?: 'query_root', systemConfig?: { __typename?: 'ConfigSystemConfig', postgres: { __typename?: 'ConfigSystemConfigPostgres', database: string } } | null, config?: { __typename: 'ConfigConfig', id: 'ConfigConfig', postgres?: { __typename?: 'ConfigPostgres', version?: string | null, resources?: { __typename?: 'ConfigPostgresResources', enablePublicAccess?: boolean | null, storage?: { __typename?: 'ConfigPostgresStorage', capacity: any } | null } | null } | null } | null };
export type GetPostgresSettingsQuery = { __typename?: 'query_root', systemConfig?: { __typename?: 'ConfigSystemConfig', postgres: { __typename?: 'ConfigSystemConfigPostgres', database: string } } | null, config?: { __typename: 'ConfigConfig', id: 'ConfigConfig', postgres: { __typename?: 'ConfigPostgres', version?: string | null, resources: { __typename?: 'ConfigPostgresResources', enablePublicAccess?: boolean | null, storage: { __typename?: 'ConfigPostgresResourcesStorage', capacity: any } } } } | null };
export type ResetDatabasePasswordMutationVariables = Exact<{
appId: Scalars['String'];
@@ -27703,14 +27689,14 @@ export type GetObservabilitySettingsQueryVariables = Exact<{
export type GetObservabilitySettingsQuery = { __typename?: 'query_root', config?: { __typename: 'ConfigConfig', id: 'ConfigConfig', observability: { __typename?: 'ConfigObservability', grafana: { __typename?: 'ConfigGrafana', alerting?: { __typename?: 'ConfigGrafanaAlerting', enabled?: boolean | null } | null, smtp?: { __typename?: 'ConfigGrafanaSmtp', host: string, password: string, port: any, sender: string, user: string } | null, contacts?: { __typename?: 'ConfigGrafanaContacts', emails?: Array<string> | null, discord?: Array<{ __typename?: 'ConfigGrafanacontactsDiscord', avatarUrl: string, url: string }> | null, pagerduty?: Array<{ __typename?: 'ConfigGrafanacontactsPagerduty', integrationKey: string, severity: string, class: string, component: string, group: string }> | null, slack?: Array<{ __typename?: 'ConfigGrafanacontactsSlack', recipient: string, token: string, username: string, iconEmoji: string, iconURL: string, mentionUsers: Array<string>, mentionGroups: Array<string>, mentionChannel: string, url: string, endpointURL: string }> | null, webhook?: Array<{ __typename?: 'ConfigGrafanacontactsWebhook', url: string, httpMethod: string, username: string, password: string, authorizationScheme: string, authorizationCredentials: string, maxAlerts: number }> | null } | null } } } | null };
export type ServiceResourcesFragment = { __typename?: 'ConfigConfig', auth?: { __typename?: 'ConfigAuth', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null, networking?: { __typename?: 'ConfigNetworking', ingresses?: Array<{ __typename?: 'ConfigIngress', fqdn?: Array<string> | null }> | null } | null } | null } | null, hasura: { __typename?: 'ConfigHasura', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null, networking?: { __typename?: 'ConfigNetworking', ingresses?: Array<{ __typename?: 'ConfigIngress', fqdn?: Array<string> | null }> | null } | null } | null }, postgres?: { __typename?: 'ConfigPostgres', resources?: { __typename?: 'ConfigPostgresResources', enablePublicAccess?: boolean | null, replicas?: any | null, storage?: { __typename?: 'ConfigPostgresStorage', capacity: any } | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null } | null } | null, storage?: { __typename?: 'ConfigStorage', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null } | null } | null };
export type ServiceResourcesFragment = { __typename?: 'ConfigConfig', auth?: { __typename?: 'ConfigAuth', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null, networking?: { __typename?: 'ConfigNetworking', ingresses?: Array<{ __typename?: 'ConfigIngress', fqdn?: Array<string> | null }> | null } | null } | null } | null, hasura: { __typename?: 'ConfigHasura', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null, networking?: { __typename?: 'ConfigNetworking', ingresses?: Array<{ __typename?: 'ConfigIngress', fqdn?: Array<string> | null }> | null } | null } | null }, postgres: { __typename?: 'ConfigPostgres', resources: { __typename?: 'ConfigPostgresResources', enablePublicAccess?: boolean | null, storage: { __typename?: 'ConfigPostgresResourcesStorage', capacity: any }, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null } }, storage?: { __typename?: 'ConfigStorage', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null } | null } | null };
export type GetResourcesQueryVariables = Exact<{
appId: Scalars['uuid'];
}>;
export type GetResourcesQuery = { __typename?: 'query_root', config?: { __typename?: 'ConfigConfig', auth?: { __typename?: 'ConfigAuth', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null, networking?: { __typename?: 'ConfigNetworking', ingresses?: Array<{ __typename?: 'ConfigIngress', fqdn?: Array<string> | null }> | null } | null } | null } | null, hasura: { __typename?: 'ConfigHasura', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null, networking?: { __typename?: 'ConfigNetworking', ingresses?: Array<{ __typename?: 'ConfigIngress', fqdn?: Array<string> | null }> | null } | null } | null }, postgres?: { __typename?: 'ConfigPostgres', resources?: { __typename?: 'ConfigPostgresResources', enablePublicAccess?: boolean | null, replicas?: any | null, storage?: { __typename?: 'ConfigPostgresStorage', capacity: any } | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null } | null } | null, storage?: { __typename?: 'ConfigStorage', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null } | null } | null } | null };
export type GetResourcesQuery = { __typename?: 'query_root', config?: { __typename?: 'ConfigConfig', auth?: { __typename?: 'ConfigAuth', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null, networking?: { __typename?: 'ConfigNetworking', ingresses?: Array<{ __typename?: 'ConfigIngress', fqdn?: Array<string> | null }> | null } | null } | null } | null, hasura: { __typename?: 'ConfigHasura', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null, networking?: { __typename?: 'ConfigNetworking', ingresses?: Array<{ __typename?: 'ConfigIngress', fqdn?: Array<string> | null }> | null } | null } | null }, postgres: { __typename?: 'ConfigPostgres', resources: { __typename?: 'ConfigPostgresResources', enablePublicAccess?: boolean | null, storage: { __typename?: 'ConfigPostgresResourcesStorage', capacity: any }, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null } }, storage?: { __typename?: 'ConfigStorage', resources?: { __typename?: 'ConfigResources', replicas?: any | null, compute?: { __typename?: 'ConfigResourcesCompute', cpu: any, memory: any } | null, autoscaler?: { __typename?: 'ConfigAutoscaler', maxReplicas: any } | null } | null } | null } | null };
export type GetStorageSettingsQueryVariables = Exact<{
appId: Scalars['uuid'];
@@ -27770,7 +27756,7 @@ export type GetConfiguredVersionsQueryVariables = Exact<{
}>;
export type GetConfiguredVersionsQuery = { __typename?: 'query_root', config?: { __typename?: 'ConfigConfig', auth?: { __typename?: 'ConfigAuth', version?: string | null } | null, postgres?: { __typename?: 'ConfigPostgres', version?: string | null } | null, hasura: { __typename?: 'ConfigHasura', version?: string | null }, ai?: { __typename?: 'ConfigAI', version?: string | null } | null, storage?: { __typename?: 'ConfigStorage', version?: string | null } | null } | null };
export type GetConfiguredVersionsQuery = { __typename?: 'query_root', config?: { __typename?: 'ConfigConfig', auth?: { __typename?: 'ConfigAuth', version?: string | null } | null, postgres: { __typename?: 'ConfigPostgres', version?: string | null }, hasura: { __typename?: 'ConfigHasura', version?: string | null }, ai?: { __typename?: 'ConfigAI', version?: string | null } | null, storage?: { __typename?: 'ConfigStorage', version?: string | null } | null } | null };
export type GetProjectIsLockedQueryVariables = Exact<{
appId: Scalars['uuid'];
@@ -27969,7 +27955,7 @@ export type UpdateConfigMutationVariables = Exact<{
}>;
export type UpdateConfigMutation = { __typename?: 'mutation_root', updateConfig: { __typename?: 'ConfigConfig', id: 'ConfigConfig', postgres?: { __typename?: 'ConfigPostgres', resources?: { __typename?: 'ConfigPostgresResources', enablePublicAccess?: boolean | null, storage?: { __typename?: 'ConfigPostgresStorage', capacity: any } | null } | null } | null, ai?: { __typename?: 'ConfigAI', version?: string | null, webhookSecret: string, autoEmbeddings?: { __typename?: 'ConfigAIAutoEmbeddings', synchPeriodMinutes?: any | null } | null, openai: { __typename?: 'ConfigAIOpenai', organization?: string | null, apiKey: string }, resources: { __typename?: 'ConfigAIResources', compute: { __typename?: 'ConfigComputeResources', cpu: any, memory: any } } } | null } };
export type UpdateConfigMutation = { __typename?: 'mutation_root', updateConfig: { __typename?: 'ConfigConfig', id: 'ConfigConfig', postgres: { __typename?: 'ConfigPostgres', resources: { __typename?: 'ConfigPostgresResources', enablePublicAccess?: boolean | null, storage: { __typename?: 'ConfigPostgresResourcesStorage', capacity: any } } }, ai?: { __typename?: 'ConfigAI', version?: string | null, webhookSecret: string, autoEmbeddings?: { __typename?: 'ConfigAIAutoEmbeddings', synchPeriodMinutes?: any | null } | null, openai: { __typename?: 'ConfigAIOpenai', organization?: string | null, apiKey: string }, resources: { __typename?: 'ConfigAIResources', compute: { __typename?: 'ConfigComputeResources', cpu: any, memory: any } } } | null } };
export type UpdateDatabaseVersionMutationVariables = Exact<{
appId: Scalars['uuid'];
@@ -28435,14 +28421,14 @@ export type GetRemoteAppMetricsQuery = { __typename?: 'query_root', filesAggrega
export type RemoteAppGetUsersFragment = { __typename?: 'users', id: any, createdAt: any, displayName: string, avatarUrl: string, email?: any | null, emailVerified: boolean, phoneNumber?: string | null, phoneNumberVerified: boolean, disabled: boolean, defaultRole: string, lastSeen?: any | null, locale: string, metadata?: any | null, roles: Array<{ __typename?: 'authUserRoles', id: any, role: string }>, userProviders: Array<{ __typename?: 'authUserProviders', id: any, providerId: string }> };
export type RemoteAppGetUsersQueryVariables = Exact<{
export type RemoteAppGetUsersAndAuthRolesQueryVariables = Exact<{
where: Users_Bool_Exp;
limit: Scalars['Int'];
offset: Scalars['Int'];
}>;
export type RemoteAppGetUsersQuery = { __typename?: 'query_root', users: Array<{ __typename?: 'users', id: any, createdAt: any, displayName: string, avatarUrl: string, email?: any | null, emailVerified: boolean, phoneNumber?: string | null, phoneNumberVerified: boolean, disabled: boolean, defaultRole: string, lastSeen?: any | null, locale: string, metadata?: any | null, roles: Array<{ __typename?: 'authUserRoles', id: any, role: string }>, userProviders: Array<{ __typename?: 'authUserProviders', id: any, providerId: string }> }>, filteredUsersAggreggate: { __typename?: 'users_aggregate', aggregate?: { __typename?: 'users_aggregate_fields', count: number } | null }, usersAggregate: { __typename?: 'users_aggregate', aggregate?: { __typename?: 'users_aggregate_fields', count: number } | null } };
export type RemoteAppGetUsersAndAuthRolesQuery = { __typename?: 'query_root', users: Array<{ __typename?: 'users', id: any, createdAt: any, displayName: string, avatarUrl: string, email?: any | null, emailVerified: boolean, phoneNumber?: string | null, phoneNumberVerified: boolean, disabled: boolean, defaultRole: string, lastSeen?: any | null, locale: string, metadata?: any | null, roles: Array<{ __typename?: 'authUserRoles', id: any, role: string }>, userProviders: Array<{ __typename?: 'authUserProviders', id: any, providerId: string }> }>, filteredUsersAggreggate: { __typename?: 'users_aggregate', aggregate?: { __typename?: 'users_aggregate_fields', count: number } | null }, usersAggregate: { __typename?: 'users_aggregate', aggregate?: { __typename?: 'users_aggregate_fields', count: number } | null }, authRoles: Array<{ __typename?: 'authRoles', role: string }> };
export type RemoteAppGetUsersCustomQueryVariables = Exact<{
where: Users_Bool_Exp;
@@ -28721,10 +28707,6 @@ export const ServiceResourcesFragmentDoc = gql`
cpu
memory
}
replicas
autoscaler {
maxReplicas
}
}
}
storage {
@@ -34044,8 +34026,8 @@ export type GetRemoteAppMetricsQueryResult = Apollo.QueryResult<GetRemoteAppMetr
export function refetchGetRemoteAppMetricsQuery(variables?: GetRemoteAppMetricsQueryVariables) {
return { query: GetRemoteAppMetricsDocument, variables: variables }
}
export const RemoteAppGetUsersDocument = gql`
query remoteAppGetUsers($where: users_bool_exp!, $limit: Int!, $offset: Int!) {
export const RemoteAppGetUsersAndAuthRolesDocument = gql`
query remoteAppGetUsersAndAuthRoles($where: users_bool_exp!, $limit: Int!, $offset: Int!) {
users(
where: $where
limit: $limit
@@ -34064,20 +34046,23 @@ export const RemoteAppGetUsersDocument = gql`
count
}
}
authRoles {
role
}
}
${RemoteAppGetUsersFragmentDoc}`;
/**
* __useRemoteAppGetUsersQuery__
* __useRemoteAppGetUsersAndAuthRolesQuery__
*
* To run a query within a React component, call `useRemoteAppGetUsersQuery` and pass it any options that fit your needs.
* When your component renders, `useRemoteAppGetUsersQuery` returns an object from Apollo Client that contains loading, error, and data properties
* To run a query within a React component, call `useRemoteAppGetUsersAndAuthRolesQuery` and pass it any options that fit your needs.
* When your component renders, `useRemoteAppGetUsersAndAuthRolesQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useRemoteAppGetUsersQuery({
* const { data, loading, error } = useRemoteAppGetUsersAndAuthRolesQuery({
* variables: {
* where: // value for 'where'
* limit: // value for 'limit'
@@ -34085,19 +34070,19 @@ export const RemoteAppGetUsersDocument = gql`
* },
* });
*/
export function useRemoteAppGetUsersQuery(baseOptions: Apollo.QueryHookOptions<RemoteAppGetUsersQuery, RemoteAppGetUsersQueryVariables>) {
export function useRemoteAppGetUsersAndAuthRolesQuery(baseOptions: Apollo.QueryHookOptions<RemoteAppGetUsersAndAuthRolesQuery, RemoteAppGetUsersAndAuthRolesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<RemoteAppGetUsersQuery, RemoteAppGetUsersQueryVariables>(RemoteAppGetUsersDocument, options);
return Apollo.useQuery<RemoteAppGetUsersAndAuthRolesQuery, RemoteAppGetUsersAndAuthRolesQueryVariables>(RemoteAppGetUsersAndAuthRolesDocument, options);
}
export function useRemoteAppGetUsersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<RemoteAppGetUsersQuery, RemoteAppGetUsersQueryVariables>) {
export function useRemoteAppGetUsersAndAuthRolesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<RemoteAppGetUsersAndAuthRolesQuery, RemoteAppGetUsersAndAuthRolesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<RemoteAppGetUsersQuery, RemoteAppGetUsersQueryVariables>(RemoteAppGetUsersDocument, options);
return Apollo.useLazyQuery<RemoteAppGetUsersAndAuthRolesQuery, RemoteAppGetUsersAndAuthRolesQueryVariables>(RemoteAppGetUsersAndAuthRolesDocument, options);
}
export type RemoteAppGetUsersQueryHookResult = ReturnType<typeof useRemoteAppGetUsersQuery>;
export type RemoteAppGetUsersLazyQueryHookResult = ReturnType<typeof useRemoteAppGetUsersLazyQuery>;
export type RemoteAppGetUsersQueryResult = Apollo.QueryResult<RemoteAppGetUsersQuery, RemoteAppGetUsersQueryVariables>;
export function refetchRemoteAppGetUsersQuery(variables: RemoteAppGetUsersQueryVariables) {
return { query: RemoteAppGetUsersDocument, variables: variables }
export type RemoteAppGetUsersAndAuthRolesQueryHookResult = ReturnType<typeof useRemoteAppGetUsersAndAuthRolesQuery>;
export type RemoteAppGetUsersAndAuthRolesLazyQueryHookResult = ReturnType<typeof useRemoteAppGetUsersAndAuthRolesLazyQuery>;
export type RemoteAppGetUsersAndAuthRolesQueryResult = Apollo.QueryResult<RemoteAppGetUsersAndAuthRolesQuery, RemoteAppGetUsersAndAuthRolesQueryVariables>;
export function refetchRemoteAppGetUsersAndAuthRolesQuery(variables: RemoteAppGetUsersAndAuthRolesQueryVariables) {
return { query: RemoteAppGetUsersAndAuthRolesDocument, variables: variables }
}
export const RemoteAppGetUsersCustomDocument = gql`
query remoteAppGetUsersCustom($where: users_bool_exp!, $limit: Int!, $offset: Int!) {

View File

@@ -17,7 +17,8 @@ export function getHasuraAdminSecret() {
*/
export function getAuthServiceUrl() {
return (
process.env.NEXT_PUBLIC_NHOST_AUTH_URL || 'https://local.auth.nhost.run/v1'
process.env.NEXT_PUBLIC_NHOST_AUTH_URL ||
'https://local.auth.local.nhost.run/v1'
);
}
@@ -25,7 +26,9 @@ export function getAuthServiceUrl() {
* Custom URL of the Database service.
*/
export function getDatabaseServiceUrl() {
return process.env.NEXT_PUBLIC_NHOST_DATABASE_URL || 'local.db.nhost.run';
return (
process.env.NEXT_PUBLIC_NHOST_DATABASE_URL || 'local.db.local.nhost.run'
);
}
/**
@@ -34,7 +37,7 @@ export function getDatabaseServiceUrl() {
export function getGraphqlServiceUrl() {
return (
process.env.NEXT_PUBLIC_NHOST_GRAPHQL_URL ||
'https://local.graphql.nhost.run/v1'
'https://local.graphql.local.nhost.run/v1'
);
}
@@ -44,7 +47,7 @@ export function getGraphqlServiceUrl() {
export function getStorageServiceUrl() {
return (
process.env.NEXT_PUBLIC_NHOST_STORAGE_URL ||
'https://local.storage.nhost.run/v1'
'https://local.storage.local.nhost.run/v1'
);
}
@@ -54,7 +57,7 @@ export function getStorageServiceUrl() {
export function getFunctionsServiceUrl() {
return (
process.env.NEXT_PUBLIC_NHOST_FUNCTIONS_URL ||
'https://local.functions.nhost.run/v1'
'https://local.functions.local.nhost.run/v1'
);
}
@@ -64,7 +67,7 @@ export function getFunctionsServiceUrl() {
export function getHasuraConsoleServiceUrl() {
return (
process.env.NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL ||
'https://local.hasura.nhost.run'
'https://local.hasura.local.nhost.run'
);
}
@@ -84,7 +87,7 @@ export function getHasuraMigrationsApiUrl() {
export function getHasuraApiUrl() {
return (
process.env.NEXT_PUBLIC_NHOST_HASURA_API_URL ||
'https://local.hasura.nhost.run'
'https://local.hasura.local.nhost.run'
);
}
@@ -94,6 +97,6 @@ export function getHasuraApiUrl() {
export function getConfigServerUrl() {
return (
process.env.NEXT_PUBLIC_NHOST_CONFIGSERVER_URL ||
'https://local.dashboard.nhost.run/v1/configserver/graphql'
'https://local.dashboard.local.nhost.run/v1/configserver/graphql'
);
}

View File

@@ -4,6 +4,7 @@
"jsx": "react-jsx",
"types": ["vitest/globals"],
"paths": {
"@/*": ["./*"],
"@/tests/*": ["tests/*"],
"@/e2e/*": ["../e2e/*"],
"@/components/*": ["components/*"],

View File

@@ -1,5 +1,11 @@
# @nhost/docs
## 2.28.1
### Patch Changes
- 6b8163d: fix(nhost-js) update service URL generation for local environments
## 2.28.0
### Minor Changes

View File

@@ -6,21 +6,21 @@ icon: rectangle-code
## `nhost init`
Initializes current directory with a new project containing configuration and objects necessary to run Nhost locally.
Initializes current directory with a new project containing configuration and objects necessary to run Nhost locally.
<Accordion title="Output">
Initializing Nhost project
Initializing Nhost project
Successfully initialized Nhost project, run `nhost up` to start development
Successfully initialized Nhost project, run `nhost up` to start development
</Accordion>
### Flags
### Flags
`--remote` optional `false` <br />
Pulls state from a remote Nhost instance.
## `nhost up`
Starts Nhost for development and testing purposes. Requires scaffolding from `nhost init`.
@@ -31,13 +31,13 @@ Starts Nhost for development and testing purposes. Requires scaffolding from `nh
Nhost development environment started.
URLs:
- Postgres: postgres://postgres:postgres@localhost:5432/local
- Hasura: https://local.hasura.nhost.run
- GraphQL: https://local.graphql.nhost.run
- Auth: https://local.auth.nhost.run
- Storage: https://local.storage.nhost.run
- Functions: https://local.functions.nhost.run
- Dashboard: https://local.dashboard.nhost.run
- Mailhog: https://local.mailhog.nhost.run
- Hasura: https://local.hasura.local.nhost.run
- GraphQL: https://local.graphql.local.nhost.run
- Auth: https://local.auth.local.nhost.run
- Storage: https://local.storage.local.nhost.run
- Functions: https://local.functions.local.nhost.run
- Dashboard: https://local.dashboard.local.nhost.run
- Mailhog: https://local.mailhog.local.nhost.run
SDK Configuration:
Subdomain: local
@@ -50,26 +50,22 @@ Run `nhost logs` to watch the logs
</Accordion>
## `nhost down`
Stops all services and deletes all containers.
### Flags
### Flags
`--volumes` optional `false` <br />
Remove volumes.
## `nhost login`
Login to an Nhost account to perform authenticated operations.
<Accordion title="Output">
- email: user@domain.com
- password:
- password:
Authenticating <br />
Successfully logged in, creating PAT <br />
@@ -78,7 +74,7 @@ Storing PAT for future user
</Accordion>
### Flags
### Flags
`--email` optional <br />
Email adress.
@@ -104,7 +100,7 @@ app-auth-1 | {"level":"info","message":"Running on port 4000"}
</Accordion>
### Flags
### Flags
`--follow` optional <br />
Follow (or tail) log output.
@@ -146,6 +142,7 @@ List all remote Nhost projects this user has access to.
12 │ xmhqdbhkvskuubnelgkc │ monitoring-app-london │ monitoring │ eu-west-2 │
13 │ jjetetkbmovfgyewremk │ monitoring-app-mumbai │ monitoring │ ap-south-1 │
```
</Accordion>
## `nhost secrets`
@@ -159,4 +156,3 @@ Manage secrets in the Nhost cloud.
<Accordion title="Output">
</Accordion>

View File

@@ -12,7 +12,7 @@ To install the Nhost CLI copy the following command and paste it into your termi
sudo curl -L https://raw.githubusercontent.com/nhost/cli/main/get.sh | bash
```
The `get.sh` script checks for both the architecture and operating system and installs the right binary.
The `get.sh` script checks for both the architecture and operating system and installs the right binary.
### Supported Platforms:
@@ -56,13 +56,13 @@ With the project scaffolding in place, start the local Nhost instance with `nhos
Nhost development environment started.
URLs:
- Postgres: postgres://postgres:postgres@localhost:5432/local
- Hasura: https://local.hasura.nhost.run
- GraphQL: https://local.graphql.nhost.run
- Auth: https://local.auth.nhost.run
- Storage: https://local.storage.nhost.run
- Functions: https://local.functions.nhost.run
- Dashboard: https://local.dashboard.nhost.run
- Mailhog: https://local.mailhog.nhost.run
- Hasura: https://local.hasura.local.nhost.run
- GraphQL: https://local.graphql.local.nhost.run
- Auth: https://local.auth.local.nhost.run
- Storage: https://local.storage.local.nhost.run
- Functions: https://local.functions.local.nhost.run
- Dashboard: https://local.dashboard.local.nhost.run
- Mailhog: https://local.mailhog.local.nhost.run
SDK Configuration:
Subdomain: local

View File

@@ -4,9 +4,9 @@ description: 'Developing locally with the Nhost CLI'
icon: hand-wave
---
Run the Nhost Stack on your computer with `nhost init` and `nhost start`. The Nhost CLI ships with all the tools you need to run, test, and operate your projects.
Run the Nhost Stack on your computer with `nhost init` and `nhost start`. The Nhost CLI ships with all the tools you need to run, test, and operate your projects.
Manage configuration, database migrations, API schema changes, and more, with ease.
Manage configuration, database migrations, API schema changes, and more, with ease.
```bash
> nhost up
@@ -14,13 +14,13 @@ Manage configuration, database migrations, API schema changes, and more, with ea
Nhost development environment started.
URLs:
- Postgres: postgres://postgres:postgres@localhost:5432/local
- Hasura: https://local.hasura.nhost.run
- GraphQL: https://local.graphql.nhost.run
- Auth: https://local.auth.nhost.run
- Storage: https://local.storage.nhost.run
- Functions: https://local.functions.nhost.run
- Dashboard: https://local.dashboard.nhost.run
- Mailhog: https://local.mailhog.nhost.run
- Hasura: https://local.hasura.local.nhost.run
- GraphQL: https://local.graphql.local.nhost.run
- Auth: https://local.auth.local.nhost.run
- Storage: https://local.storage.local.nhost.run
- Functions: https://local.functions.local.nhost.run
- Dashboard: https://local.dashboard.local.nhost.run
- Mailhog: https://local.mailhog.local.nhost.run
SDK Configuration:
Subdomain: local

View File

@@ -1,6 +1,6 @@
---
title: "Assistants"
description: "Deploy your customized AI assistants"
title: 'Assistants'
description: 'Deploy your customized AI assistants'
icon: wand-magic-sparkles
---
@@ -23,110 +23,82 @@ The first step is to create an AI assistant. You can create an AI assistant by u
```graphql
mutation {
graphite {
insertAssistant(object: {
name: "awesome-assistant-for-my-users",
description: "My Awesome assistant for my users",
instructions: "You are a useful assistant for this demo application. You are an expert on movies. You also know a bit about deep questions.",
model: "gpt-3.5-turbo-1106",
graphql: [
{
description: "get movies with higher score than the input"
name: "GetMoviesWithScoreHigherThan",
query: "query ($score: numeric!) { movies(where: {score: {_gt: $score}}) { name overview score }}",
arguments: [
{
name: "score",
description: "score to compare against",
type: "number",
required: true,
}
]
},
{
description: "search movies using natural language",
name: "SearchMovies",
query: "query GraphiteSearchMovies($query: String!) { graphiteSearchMovies(args: {query: $query, amount: 5}) { id name overview genre } }",
arguments: [
{
name: "query",
description: "Text to search",
type: "string",
required: true,
}
]
}
{
description: "insert a movie into the database",
name: "InsertMovie",
query: "mutation InsertMovie($name: String, $overview: String, $genre: String, $crew: String, $budget: bigint, $revenue: bigint, $country: String, $score: numeric) { insertMovie(object: {name: $name, overview: $overview, score: $score, genre: $genre, crew: $crew, budget: $budget, revenue: $revenue, country: $country}) {id}}",
arguments: [
{
name: "name",
description: "Name of the movie",
type: "string",
required: true,
},
{
name: "overview",
description: "Overview of the movie",
type: "string",
required: true,
},
{
name: "genre",
description: "Genre of the movie",
type: "string",
required: true,
},
{
name: "crew",
description: "Crew of the movie",
type: "string",
required: true,
},
{
name: "budget",
description: "Budget of the movie",
type: "number",
required: true,
},
{
name: "revenue",
description: "Revenue generated by the movie",
type: "number",
required: true,
},
{
name: "country",
description: "Country of origin for the movie",
type: "string",
required: true,
},
{
name: "score",
description: "Score of the movie",
type: "number",
required: true,
},
]
}
],
webhooks: [
{
name: "answer_deep_questions",
description: "Answers deep questions about life, the universe and everything",
URL: "https://local.functions.nhost.run/v1/meaning",
arguments: [
{
name: "question",
description: "question that needs answer",
type: "string",
required: true,
}
],
}
]
}) {
insertAssistant(
object: {
name: "awesome-assistant-for-my-users"
description: "My Awesome assistant for my users"
instructions: "You are a useful assistant for this demo application. You are an expert on movies. You also know a bit about deep questions."
model: "gpt-3.5-turbo-1106"
graphql: [
{
description: "get movies with higher score than the input"
name: "GetMoviesWithScoreHigherThan"
query: "query ($score: numeric!) { movies(where: {score: {_gt: $score}}) { name overview score }}"
arguments: [
{
name: "score"
description: "score to compare against"
type: "number"
required: true
}
]
}
{
description: "search movies using natural language"
name: "SearchMovies"
query: "query GraphiteSearchMovies($query: String!) { graphiteSearchMovies(args: {query: $query, amount: 5}) { id name overview genre } }"
arguments: [
{ name: "query", description: "Text to search", type: "string", required: true }
]
}
{
description: "insert a movie into the database"
name: "InsertMovie"
query: "mutation InsertMovie($name: String, $overview: String, $genre: String, $crew: String, $budget: bigint, $revenue: bigint, $country: String, $score: numeric) { insertMovie(object: {name: $name, overview: $overview, score: $score, genre: $genre, crew: $crew, budget: $budget, revenue: $revenue, country: $country}) {id}}"
arguments: [
{ name: "name", description: "Name of the movie", type: "string", required: true }
{
name: "overview"
description: "Overview of the movie"
type: "string"
required: true
}
{ name: "genre", description: "Genre of the movie", type: "string", required: true }
{ name: "crew", description: "Crew of the movie", type: "string", required: true }
{ name: "budget", description: "Budget of the movie", type: "number", required: true }
{
name: "revenue"
description: "Revenue generated by the movie"
type: "number"
required: true
}
{
name: "country"
description: "Country of origin for the movie"
type: "string"
required: true
}
{ name: "score", description: "Score of the movie", type: "number", required: true }
]
}
]
webhooks: [
{
name: "answer_deep_questions"
description: "Answers deep questions about life, the universe and everything"
URL: "https://local.functions.local.nhost.run/v1/meaning"
arguments: [
{
name: "question"
description: "question that needs answer"
type: "string"
required: true
}
]
}
]
}
) {
assistantID
}
}
@@ -140,7 +112,6 @@ mutation {
In order to enhance our AI assistants we are leveraging tools. Tools can be either queries or mutations performed against your project's GraphQL engine or they can also be any arbitrary endpoint you choose. Using the example above, we added 4 different tools to our AI Assistant:
- The GraphQL query `GetMoviesWithScoreHigherThan`, which will allow the AI Assistant to query movies based on their score.
- The GraphQL query `SearchMovies`, which leverages [auto-embeddings](auto-embeddings) and will allow the AI Assistant to query movies using natural language.
- The GraphQL mutation `InsertMovie`, which will let the AI Assistant to insert new movies directly into the database.
@@ -160,7 +131,7 @@ To start a session you can use the mutation `startSession` and pass the id of th
```graphql
mutation {
graphite {
startSession(assistantID:"asst_xolmq2yeBBRi8CKGc5YWXGaA") {
startSession(assistantID: "asst_xolmq2yeBBRi8CKGc5YWXGaA") {
sessionID
}
}
@@ -188,10 +159,10 @@ Now that you have started a session you can send your first message:
```graphql
mutation {
graphite {
sendMessage(
sessionID:"thread_dxHHNpQryFpJ8wXXD9Q2fQJg",
sendMessage(
sessionID: "thread_dxHHNpQryFpJ8wXXD9Q2fQJg"
message: "what is the meaning of life?"
prevMessageID: "",
prevMessageID: ""
) {
sessionID
messages {
@@ -207,7 +178,6 @@ mutation {
The field `prevMessageID` is used to only return messages after this one. As this is the beginning of the conversation we send an empty string to get all messages back. After executing that mutation we should receive a response like:
```json
{
"data": {
@@ -249,10 +219,10 @@ We can continue the conversation by performing from mutations. Notice this time
```graphql
mutation {
graphite {
sendMessage(
sessionID:"thread_dxHHNpQryFpJ8wXXD9Q2fQJg",
sendMessage(
sessionID: "thread_dxHHNpQryFpJ8wXXD9Q2fQJg"
message: "recommend a comedy movie for a rainy day with score higher than 80"
prevMessageID: "msg_kTZonuiwZDxnipDADXk4bgFd",
prevMessageID: "msg_kTZonuiwZDxnipDADXk4bgFd"
) {
sessionID
messages {
@@ -302,7 +272,6 @@ In this case ChatGPT detected some of the information needed to formulate the an
Interactions are not limited to just one tool or to simply query data. Tools can be combined and they can perform any action you wish. For instance, let's take a look to the following session:
```json
{
"data": {

View File

@@ -150,7 +150,7 @@ curl -X POST \
-H "Content-Type: application/json" \
-H "x-hasura-admin-secret: nhost-admin-secret" \
-d '{"userId": "FFAB5354-C5EB-42C1-8BC3-AD21D2297883", "defaultRole": "user", "allowedRoles": ["user", "me"]}' \
https://local.functions.nhost.run/v1/custom-jwt
https://local.functions.local.nhost.run/v1/custom-jwt
{"accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTcxNDIyMTMsImh0dHBzOi8vaGFzdXJhLmlvL2p3dC9jbGFpbXMiOnsieC1oYXN1cmEtYWxsb3dlZC1yb2xlcyI6WyJ1c2VyIiwibWUiXSwieC1oYXN1cmEtZGVmYXVsdC1yb2xlIjoidXNlciIsIngtaGFzdXJhLXVzZXItaWQiOiJGRkFCNTM1NC1DNUVCLTQyQzEtOEJDMy1BRDIxRDIyOTc4ODMiLCJ4LWhhc3VyYS11c2VyLWlzLWFub255bW91cyI6ImZhbHNlIiwieC1oYXN1cmEtb24tYmVoYWxmLW9mIjoiYWRtaW4ifSwiaWF0IjoxNzE3MTM4NjEzLCJpc3MiOiJjdXN0b20tbGFtYmRhIiwic3ViIjoiRkZBQjUzNTQtQzVFQi00MkMxLThCQzMtQUQyMUQyMjk3ODgzIn0.bRhzJvXMdkQA8aXPH95uMT17WHED2rSRq3gE21Vp3Ak"}
```
@@ -160,10 +160,7 @@ The new token should be a valid token for your application with the custom value
{
"exp": 1717141288,
"https://hasura.io/jwt/claims": {
"x-hasura-allowed-roles": [
"a",
"b"
],
"x-hasura-allowed-roles": ["a", "b"],
"x-hasura-default-role": "user",
"x-hasura-user-id": "FFAB5354-C5EB-42C1-8BC3-AD21D2297883",
"x-hasura-user-is-anonymous": "false",

View File

@@ -1,12 +1,11 @@
---
title: Local Development
description: Learn how to start a development instance of Nhost
description: Learn how to start a development instance of Nhost
icon: code
---
Nhost's command-line interface (CLI) lets you run a complete Nhost development environment locally with the following services: PostgreSQL database, Hasura, Authentication, Storage (MinIO), Serverless Functions, and Emails (Mailhog).
## Dependencies
- [Git](https://git-scm.com/downloads)
@@ -18,8 +17,10 @@ Nhost's command-line interface (CLI) lets you run a complete Nhost development e
nhost login
```
<Info>If you used GitHub to register, you will have to first set a password in your [account page](https://app.nhost.io/account).</Info>
<Info>
If you used GitHub to register, you will have to first set a password in your [account
page](https://app.nhost.io/account).
</Info>
## Initialize local project
@@ -38,7 +39,6 @@ nhost init
`nhost init` creates all the configuration necessary for your project, including database migrations and Hasura metadata.
We can now start your project with `nhost up`.
```bash
@@ -52,13 +52,13 @@ Nhost development environment started.
URLs:
- Postgres: postgres://postgres:postgres@localhost:5432/local
- Hasura: https://local.hasura.nhost.run
- GraphQL: https://local.graphql.nhost.run
- Auth: https://local.auth.nhost.run
- Storage: https://local.storage.nhost.run
- Functions: https://local.functions.nhost.run
- Dashboard: https://local.dashboard.nhost.run
- Mailhog: https://local.mailhog.nhost.run
- Hasura: https://local.hasura.local.nhost.run
- GraphQL: https://local.graphql.local.nhost.run
- Auth: https://local.auth.local.nhost.run
- Storage: https://local.storage.local.nhost.run
- Functions: https://local.functions.local.nhost.run
- Dashboard: https://local.dashboard.local.nhost.run
- Mailhog: https://local.mailhog.local.nhost.run
SDK Configuration:
Subdomain: local
@@ -77,7 +77,7 @@ You can use `nhost down` at any time to tear down your environment.
To test that the services are running, let's curl the Auth endpoint and get its version:
```bash
curl https://local.auth.nhost.run/v1/version
curl https://local.auth.local.nhost.run/v1/version
{"version":"v0.20.1"}
```
@@ -108,8 +108,7 @@ Let's create a new table called `messages`, with the following columns:
- author_id (UUID)
- created_at (Timestamp)
There are other ways to generate a migration, here we will use the local Nhost Dashboard running on `https://local.dashboard.nhost.run/local/local`. Please head to the `database` tab and add the columns as follows:
There are other ways to generate a migration, here we will use the local Nhost Dashboard running on `https://local.dashboard.local.nhost.run/local/local`. Please head to the `database` tab and add the columns as follows:
![Nhost Local Dashboard](/images/guides/cli/create-table-messages.png)
@@ -201,4 +200,3 @@ To check out your deployment, head over to the **Deployments** tab (https://app.
![Deployments](/images/guides/cli/deployments.png)
You should now have the same `messages` table (and permissions) on your production instance!

View File

@@ -81,13 +81,13 @@ INFO nothing to apply on database: default
Nhost development environment started.
URLs:
- Postgres: postgres://postgres:postgres@localhost:5432/postgres
- Hasura: https://local.hasura.nhost.run
- GraphQL: https://local.graphql.nhost.run
- Auth: https://local.auth.nhost.run
- Storage: https://local.storage.nhost.run
- Functions: https://local.functions.nhost.run
- Dashboard: https://local.dashboard.nhost.run
- Mailhog: https://local.mailhog.nhost.run
- Hasura: https://local.hasura.local.nhost.run
- GraphQL: https://local.graphql.local.nhost.run
- Auth: https://local.auth.local.nhost.run
- Storage: https://local.storage.local.nhost.run
- Functions: https://local.functions.local.nhost.run
- Dashboard: https://local.dashboard.local.nhost.run
- Mailhog: https://local.mailhog.local.nhost.run
SDK Configuration:
Subdomain: local
Region: (empty)
@@ -95,4 +95,3 @@ Run `nhost up` to reload the development environment
Run `nhost down` to stop the development environment
Run `nhost logs` to watch the logs
```

View File

@@ -29,13 +29,13 @@ INFO nothing to apply on database: default
Nhost development environment started.
URLs:
- Postgres: postgres://postgres:postgres@localhost:5432/postgres
- Hasura: https://local.hasura.nhost.run
- GraphQL: https://local.graphql.nhost.run
- Auth: https://local.auth.nhost.run
- Storage: https://local.storage.nhost.run
- Functions: https://local.functions.nhost.run
- Dashboard: https://local.dashboard.nhost.run
- Mailhog: https://local.mailhog.nhost.run
- Hasura: https://local.hasura.local.nhost.run
- GraphQL: https://local.graphql.local.nhost.run
- Auth: https://local.auth.local.nhost.run
- Storage: https://local.storage.local.nhost.run
- Functions: https://local.functions.local.nhost.run
- Dashboard: https://local.dashboard.local.nhost.run
- Mailhog: https://local.mailhog.local.nhost.run
SDK Configuration:
Subdomain: local
@@ -103,5 +103,3 @@ alternativeproject-auth-1 | {"level":"info","message":"Applying metadata..."}
alternativeproject-auth-1 | {"level":"info","message":"Metadata applied"}
alternativeproject-auth-1 | {"level":"info","message":"Running on port 4000"}
```

View File

@@ -12,7 +12,7 @@ As mentioned before, you can create a seed from any environment. In this guide,
```bash
$ nhost dev hasura seed create some-initial-data \
--endpoint https://local.hasura.nhost.run \
--endpoint https://local.hasura.local.nhost.run \
--admin-secret nhost-admin-secret \
--database-name default \
--from-table animals
@@ -20,7 +20,12 @@ $ nhost dev hasura seed create some-initial-data \
INFO created seed file successfully file=/app/seeds/default/1685692310174_some-initial-data.sql
```
<Info>In the previous command, we instructed the CLI to create a seed named `some-initial-data` while specifying the connection parameters for our local environment. You could also extract data from a cloud project by specifying the correct parameters. Finally, we are only extracting data from the `animals` table, but you could also extract data from any other table or even from all tables.</Info>
<Info>
In the previous command, we instructed the CLI to create a seed named `some-initial-data` while
specifying the connection parameters for our local environment. You could also extract data from a
cloud project by specifying the correct parameters. Finally, we are only extracting data from the
`animals` table, but you could also extract data from any other table or even from all tables.
</Info>
We can now inspect the file and see its contents:
@@ -67,7 +72,7 @@ INFO Metadata applied
(...) omitted for brevity
$ nhost dev hasura seed apply \
--endpoint https://local.hasura.nhost.run \
--endpoint https://local.hasura.local.nhost.run \
--admin-secret nhost-admin-secret \
--database-name default
INFO Help us improve Hasura! The cli collects anonymized usage stats which
@@ -76,5 +81,7 @@ visit https://hasura.io/docs/latest/graphql/core/guides/telemetry.html
INFO Seeds planted
```
<Info>Seeds are different from migrations because seeds are not automatically applied. If there is data that you want to have in all of your environments, it is best to use a database migration.</Info>
<Info>
Seeds are different from migrations because seeds are not automatically applied. If there is data
that you want to have in all of your environments, it is best to use a database migration.
</Info>

View File

@@ -21,9 +21,16 @@ The last thing to notice in the screenshot is that the URLs include information
Based on the information above, if you want to connect directly to your service from your laptop you can use the URL `http://localhost:5000` while if you want to connect to the Run service from another service (i.e. another Run service or hasura) you can use `http://run-bun-gen:5000`
<Note>You can also use the environment variable `NHOST_RUN_SERVICE` passing comma-separated values. For instance, the equivalent environment variable for this example would be `NHOST_RUN_SERVICE=../mysvc/nhost-run-service.toml:mysvc,../mysvc/nhost-run-service.toml`</Note>
<Note>
You can also use the environment variable `NHOST_RUN_SERVICE` passing comma-separated values. For
instance, the equivalent environment variable for this example would be
`NHOST_RUN_SERVICE=../mysvc/nhost-run-service.toml:mysvc,../mysvc/nhost-run-service.toml`
</Note>
<Warning>The Nhost CLI doesn't build services so make sure you build any image that might be needed for running `nhost run --run-service...`</Warning>
<Warning>
The Nhost CLI doesn't build services so make sure you build any image that might be needed for
running `nhost run --run-service...`
</Warning>
# Quick Development
@@ -43,7 +50,8 @@ value = 'some-value'
[[environment]]
name = 'SECRET_KEY'
value = '{{ secrets.SECRET_KEY }}'
```
````
</Tab>
<Tab title="overlay">
@@ -58,12 +66,13 @@ value = '{{ secrets.SECRET_KEY }}'
"path": "/environment/-"
},
{
"value": "https://local.graphql.nhost.run/v1/graphql",
"value": "https://local.graphql.local.nhost.run/v1/graphql",
"op": "replace",
"path": "/environment/0/value"
}
]
```
````
</Tab>
<Tab title=".secrets">
```toml
@@ -77,12 +86,17 @@ We can then generate an `env` file for our service with the folllowing command:
```
$ nhost run env --config ../mysvc/nhost-run-service.toml --overlay-name local-dev > .env
$ cat .env
HASURA_GRAPHQL_URL="https://local.graphql.nhost.run/v1/graphql"
HASURA_GRAPHQL_URL="https://local.graphql.local.nhost.run/v1/graphql"
SOME_CONFIGURATION_PARAMETER="some-value"
SECRET_KEY="#asdasd;l;kq23\\n40-0as9d\"\$\\"
ENVIRONMENT="dev"
```
<Warning>
Keep in mind you may need to use different configuration when attempting to connect to other services in the stack. For instance, in the example above we are using `http://hasura-service:8080/v1/graphql` to connect to hasura in production and in the CLI but when running the service in the host machine using the env file we are using an overlay to change the value to `https://local.graphql.nhost.run/v1/graphql`. Refer to the [network](networking) configuration for more details.
Keep in mind you may need to use different configuration when attempting to connect to other
services in the stack. For instance, in the example above we are using
`http://hasura-service:8080/v1/graphql` to connect to hasura in production and in the CLI but when
running the service in the host machine using the env file we are using an overlay to change the
value to `https://local.graphql.local.nhost.run/v1/graphql`. Refer to the [network](networking)
configuration for more details.
</Warning>

View File

@@ -17,7 +17,8 @@ File metadata is stored in your database in the `files` table in the `storage` s
- Create GraphQL relationships between files and your database tables.
<Warning>
Don't modify the database schema, nor GraphQL root fields in any of the tables in the `storage` schema.
Don't modify the database schema, nor GraphQL root fields in any of the tables in the `storage`
schema.
</Warning>
<Tip>
@@ -25,7 +26,7 @@ You're allowed to add and modify the following:
- GraphQL Relationships
- Permissions
</Tip>
</Tip>
### Upload File
@@ -44,7 +45,7 @@ Learn more about [`upload()`](/reference/javascript/storage/upload).
<Tab title="HTTP">
```http
POST https://local.storage.nhost.run/v1/files HTTP/1.1
POST https://local.storage.local.nhost.run/v1/files HTTP/1.1
```
</Tab>
@@ -76,7 +77,7 @@ Learn more about [`getPublicUrl()`](/reference/javascript/storage/get-public-url
<Tab title="HTTP">
```http
GET https://local.storage.nhost.run/v1/files/{file_id} HTTP/1.1
GET https://local.storage.local.nhost.run/v1/files/{file_id} HTTP/1.1
```
</Tab>
@@ -105,7 +106,7 @@ Learn more about [`getPresignedUrl()`](/reference/javascript/storage/get-presign
<Tab title="HTTP">
```http
GET https://local.storage.nhost.run/v1/files/{file_id}/presignedurl HTTP/1.1
GET https://local.storage.local.nhost.run/v1/files/{file_id}/presignedurl HTTP/1.1
```
</Tab>
@@ -128,7 +129,7 @@ Learn more about [`delete()`](/reference/javascript/storage/delete).
<Tab title="HTTP">
```http
DELETE https://local.storage.nhost.run/v1/files/{file_id} HTTP/1.1
DELETE https://local.storage.local.nhost.run/v1/files/{file_id} HTTP/1.1
```
</Tab>

View File

@@ -2,7 +2,7 @@ sequenceDiagram
user->>+graphite: What is the meaning of life?
graphite->>+chatgpt: What is the meaning of life?
chatgpt->>-graphite: run `answer_deep_questions`<br/>with {"question": "what is the meaning of life?"}?
graphite->>+webhook: POST https://local.functions.nhost.fun/v1/meaning<br/>{"question": "what is the meaning of life?"}
graphite->>+webhook: POST https://local.functions.local.nhost.fun/v1/meaning<br/>{"question": "what is the meaning of life?"}
webhook->>-graphite: HTTP STATUS OK, Response body: 42
graphite->>+chatgpt: 42
chatgpt->>-graphite: The answer to the meaning of life is 42...
@@ -13,7 +13,7 @@ sequenceDiagram
user->>+graphite: recommend a comedy movie...
graphite->>+chatgpt: recommend a comedy movie...
chatgpt->>-graphite: run `GetMoviesWithScoreHigherThan`<br/>with {"score": 80}
graphite->>+graphql: POST https://local.graphql.nhost.fun/v1<br/>query ($score: numeric!) { movies(where: ...
graphite->>+graphql: POST https://local.graphql.local.nhost.fun/v1<br/>query ($score: numeric!) { movies(where: ...
graphql->>-graphite: { graphql response with movies }
graphite->>+chatgpt: { graphql response with movies }
chatgpt->>-graphite: Here are a few comedy...

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/docs",
"version": "2.28.0",
"version": "2.28.1",
"private": true,
"scripts": {
"start": "mintlify dev"

View File

@@ -9,10 +9,9 @@ info:
name: LICENSE-TBD
url: https://LICENSE-TBD
servers:
- url: https://local.auth.nhost.run/v1
- url: https://local.auth.local.nhost.run/v1
description: API Server
components:
securitySchemes:
BearerAuth:
scheme: bearer
@@ -20,7 +19,6 @@ components:
bearerFormat: JWT
description: JSON Web Token to authorize requests.
schemas:
SignInWebauthnSessionPayload:
type: object
properties:
@@ -42,13 +40,13 @@ components:
rpId:
type: string
example:
challenge: "KOGeoAfC2nrZ_SluhmU5RYYMvBsRDvzghjERGdXbbfQ"
challenge: 'KOGeoAfC2nrZ_SluhmU5RYYMvBsRDvzghjERGdXbbfQ'
allowCredentials:
- id: "zCnsWvxgtMrOCeX6eA_yqQ"
type: "public-key"
- id: 'zCnsWvxgtMrOCeX6eA_yqQ'
type: 'public-key'
timeout: 60000
userVerification: "preferred"
rpId: "react-apollo.example.nhost.io"
userVerification: 'preferred'
rpId: 'react-apollo.example.nhost.io'
ElevateWebauthnSessionPayload:
type: object
@@ -71,13 +69,13 @@ components:
rpId:
type: string
example:
challenge: "KOGeoAfC2nrZ_SluhmU5RYYMvBsRDvzghjERGdXbbfQ"
challenge: 'KOGeoAfC2nrZ_SluhmU5RYYMvBsRDvzghjERGdXbbfQ'
allowCredentials:
- id: "zCnsWvxgtMrOCeX6eA_yqQ"
type: "public-key"
- id: 'zCnsWvxgtMrOCeX6eA_yqQ'
type: 'public-key'
timeout: 60000
userVerification: "preferred"
rpId: "react-apollo.example.nhost.io"
userVerification: 'preferred'
rpId: 'react-apollo.example.nhost.io'
WebauthnSessionPayload:
type: object
@@ -126,39 +124,39 @@ components:
userVerification:
type: string
example:
challenge: "eKdWG60F0lB-wNOviefzn6En0jvdf_GYDyCK2Zuznh8"
challenge: 'eKdWG60F0lB-wNOviefzn6En0jvdf_GYDyCK2Zuznh8'
rp:
name: "hasura-auth"
id: "localhost"
name: 'hasura-auth'
id: 'localhost'
user:
id: "44b96e0d-18ad-48b9-a517-6537d32223da"
name: "john.smith@nhost.io"
displayName: "John Smith"
id: '44b96e0d-18ad-48b9-a517-6537d32223da'
name: 'john.smith@nhost.io'
displayName: 'John Smith'
pubKeyCredParams:
- alg: -7
type: "public-key"
type: 'public-key'
- alg: -8
type: "public-key"
type: 'public-key'
- alg: -36
type: "public-key"
type: 'public-key'
- alg: -37
type: "public-key"
type: 'public-key'
- alg: -38
type: "public-key"
type: 'public-key'
- alg: -39
type: "public-key"
type: 'public-key'
- alg: -257
type: "public-key"
type: 'public-key'
- alg: -258
type: "public-key"
type: 'public-key'
- alg: -259
type: "public-key"
type: 'public-key'
timeout: 60000
attestation: "indirect"
attestation: 'indirect'
excludeCredentials: []
authenticatorSelection:
requireResidentKey: false
userVerification: "preferred"
userVerification: 'preferred'
CannotSendSmsError:
additionalProperties: false
@@ -745,17 +743,17 @@ components:
type: object
example:
credential:
id: "zCnsWvxgtMrOCeX6eA_yqQ"
rawId: "zCnsWvxgtMrOCeX6eA_yqQ"
id: 'zCnsWvxgtMrOCeX6eA_yqQ'
rawId: 'zCnsWvxgtMrOCeX6eA_yqQ'
response:
attestationObject: "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViU0RE6Bmg2J-FxNrC8136ZQSeTWKWtdni_Lpfv5XR4bDtdAAAAALraVWanqkAfvZZFYZpVEg0AEMwp7Fr8YLTKzgnl-ngP8qmlAQIDJiABIVgg3XjPRqX1a22te029Du57F1w56XXy3GARb842fEtQlIEiWCC1Jce4J3bN1P-V-78elqwVy0u6MAxEcZwCvkSLqZjkjA"
clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiSGlwZ0NKLWR0bU1FeWxRN05pRnV4VXE0allNbFIwMDA1V2VmcEJWQm9payIsIm9yaWdpbiI6Imh0dHBzOi8vcmVhY3QtYXBvbGxvLmV4YW1wbGUubmhvc3QuaW8ifQ"
type: "public-key"
attestationObject: 'o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViU0RE6Bmg2J-FxNrC8136ZQSeTWKWtdni_Lpfv5XR4bDtdAAAAALraVWanqkAfvZZFYZpVEg0AEMwp7Fr8YLTKzgnl-ngP8qmlAQIDJiABIVgg3XjPRqX1a22te029Du57F1w56XXy3GARb842fEtQlIEiWCC1Jce4J3bN1P-V-78elqwVy0u6MAxEcZwCvkSLqZjkjA'
clientDataJSON: 'eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiSGlwZ0NKLWR0bU1FeWxRN05pRnV4VXE0allNbFIwMDA1V2VmcEJWQm9payIsIm9yaWdpbiI6Imh0dHBzOi8vcmVhY3QtYXBvbGxvLmV4YW1wbGUubmhvc3QuaW8ifQ'
type: 'public-key'
clientExtensionResults: {}
authenticatorAttachment: "platform"
authenticatorAttachment: 'platform'
transports:
- "internal"
- "hybrid"
- 'internal'
- 'hybrid'
options: {}
required:
- credential
@@ -807,18 +805,18 @@ components:
authenticatorAttachment:
type: string
example:
email: "nuno@nhost.io"
email: 'nuno@nhost.io'
credential:
id: "zCnsWvxgtMrOCeX6eA_yqQ"
rawId: "zCnsWvxgtMrOCeX6eA_yqQ"
id: 'zCnsWvxgtMrOCeX6eA_yqQ'
rawId: 'zCnsWvxgtMrOCeX6eA_yqQ'
response:
authenticatorData: "0RE6Bmg2J-FxNrC8136ZQSeTWKWtdni_Lpfv5XR4bDsdAAAAAA"
clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiTkNSSVRVU1pjeFE1ZTFhdUtUcXVlNnA4R0ZacHdxUS1kZzM4bnlWa3NCRSIsIm9yaWdpbiI6Imh0dHBzOi8vcmVhY3QtYXBvbGxvLmV4YW1wbGUubmhvc3QuaW8ifQ"
signature: "MEUCIQDRXq3aY-gXWsuYJZhOzqqn6UpoRQfcPdNLP7hpZ7IdvQIgX5rY6TomkYUtqydu-w88fW7KeFm-0oE-5jTdLNHg9zw"
userHandle: "8881037a-8495-48ef-8a04-ebbdb69415db"
type: "public-key"
authenticatorData: '0RE6Bmg2J-FxNrC8136ZQSeTWKWtdni_Lpfv5XR4bDsdAAAAAA'
clientDataJSON: 'eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiTkNSSVRVU1pjeFE1ZTFhdUtUcXVlNnA4R0ZacHdxUS1kZzM4bnlWa3NCRSIsIm9yaWdpbiI6Imh0dHBzOi8vcmVhY3QtYXBvbGxvLmV4YW1wbGUubmhvc3QuaW8ifQ'
signature: 'MEUCIQDRXq3aY-gXWsuYJZhOzqqn6UpoRQfcPdNLP7hpZ7IdvQIgX5rY6TomkYUtqydu-w88fW7KeFm-0oE-5jTdLNHg9zw'
userHandle: '8881037a-8495-48ef-8a04-ebbdb69415db'
type: 'public-key'
clientExtensionResults: {}
authenticatorAttachment: "platform"
authenticatorAttachment: 'platform'
required:
- email
- credential
@@ -870,18 +868,18 @@ components:
authenticatorAttachment:
type: string
example:
email: "nuno@nhost.io"
email: 'nuno@nhost.io'
credential:
id: "zCnsWvxgtMrOCeX6eA_yqQ"
rawId: "zCnsWvxgtMrOCeX6eA_yqQ"
id: 'zCnsWvxgtMrOCeX6eA_yqQ'
rawId: 'zCnsWvxgtMrOCeX6eA_yqQ'
response:
authenticatorData: "0RE6Bmg2J-FxNrC8136ZQSeTWKWtdni_Lpfv5XR4bDsdAAAAAA"
clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiTkNSSVRVU1pjeFE1ZTFhdUtUcXVlNnA4R0ZacHdxUS1kZzM4bnlWa3NCRSIsIm9yaWdpbiI6Imh0dHBzOi8vcmVhY3QtYXBvbGxvLmV4YW1wbGUubmhvc3QuaW8ifQ"
signature: "MEUCIQDRXq3aY-gXWsuYJZhOzqqn6UpoRQfcPdNLP7hpZ7IdvQIgX5rY6TomkYUtqydu-w88fW7KeFm-0oE-5jTdLNHg9zw"
userHandle: "8881037a-8495-48ef-8a04-ebbdb69415db"
type: "public-key"
authenticatorData: '0RE6Bmg2J-FxNrC8136ZQSeTWKWtdni_Lpfv5XR4bDsdAAAAAA'
clientDataJSON: 'eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiTkNSSVRVU1pjeFE1ZTFhdUtUcXVlNnA4R0ZacHdxUS1kZzM4bnlWa3NCRSIsIm9yaWdpbiI6Imh0dHBzOi8vcmVhY3QtYXBvbGxvLmV4YW1wbGUubmhvc3QuaW8ifQ'
signature: 'MEUCIQDRXq3aY-gXWsuYJZhOzqqn6UpoRQfcPdNLP7hpZ7IdvQIgX5rY6TomkYUtqydu-w88fW7KeFm-0oE-5jTdLNHg9zw'
userHandle: '8881037a-8495-48ef-8a04-ebbdb69415db'
type: 'public-key'
clientExtensionResults: {}
authenticatorAttachment: "platform"
authenticatorAttachment: 'platform'
required:
- email
- credential
@@ -1386,10 +1384,6 @@ components:
- expiresAt
paths:
/signin/anonymous:
post:
description: 'Sign In a user anonymously'
@@ -1475,7 +1469,7 @@ paths:
application/json:
schema:
type: string
example: "OK"
example: 'OK'
description: SMS sent successfully
'400':
content:
@@ -1626,7 +1620,7 @@ paths:
/signin/webauthn:
post:
description: ""
description: ''
parameters: []
requestBody:
content:
@@ -1822,7 +1816,7 @@ paths:
application/json:
schema:
type: string
example: "OK"
example: 'OK'
description: Successfully signed out
'400':
content:

View File

@@ -9,7 +9,7 @@ info:
name: LICENSE-TBD
url: https://LICENSE-TBD
servers:
- url: https://local.storage.nhost.run/v1
- url: https://local.storage.local.nhost.run/v1
description: API Server
security:
- AdminSecret: []
@@ -184,8 +184,8 @@ paths:
$ref: '#/components/schemas/Error'
/files/{id}:
head:
summary: "Download File Metadata"
description: "Retrieve metadata of a file"
summary: 'Download File Metadata'
description: 'Retrieve metadata of a file'
tags:
- storage
security:
@@ -321,7 +321,7 @@ paths:
type: string
get:
summary: Download File
description: "Download a file from storage"
description: 'Download a file from storage'
tags:
- storage
security:
@@ -498,7 +498,7 @@ paths:
$ref: '#/components/schemas/Error'
delete:
summary: Delete File
description: "Delete file from storage"
description: 'Delete file from storage'
tags:
- storage
security:
@@ -521,7 +521,7 @@ paths:
/files/{id}/presignedurl:
get:
summary: Presigned URL
summary: Presigned URL
description: |
Retrieve presigned URL to retrieve the file. Expiration of the URL is
determined by bucket configuration
@@ -552,8 +552,8 @@ paths:
/files/{id}/presignedurl/contents:
get:
summary: "Get File Content"
description: "Retrieve content of a file"
summary: 'Get File Content'
description: 'Retrieve content of a file'
tags:
- storage
security:

View File

@@ -2,12 +2,11 @@
openapi: post /files/
---
<RequestExample>
```bash Request
curl --request POST \
--url https://local.storage.nhost.run/v1/files/ \
--url https://local.storage.local.nhost.run/v1/files/ \
--header 'Authorization: <authorization>' \
--header 'Content-Type: multipart/form-data' \
--form 'file[]=@path-to-file'
@@ -16,7 +15,7 @@ curl --request POST \
```python Python
import requests
url = "https://local.storage.nhost.run/v1/files/"
url = "https://local.storage.local.nhost.run/v1/files/"
files = {
'file': ('<filename>', open('<path-to-file>', 'rb'))
@@ -50,7 +49,7 @@ const options = {
body: form
};
fetch('https://local.storage.nhost.run/v1/files/', options)
fetch('https://local.storage.local.nhost.run/v1/files/', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
@@ -60,7 +59,7 @@ fetch('https://local.storage.nhost.run/v1/files/', options)
<?php
$curl = curl_init();
$file_path = '<path_to_file>';
$file_path = '<path_to_file>';
$postfields = [
"bucket-id" => "<string>",
@@ -73,7 +72,7 @@ $postfields = [
];
curl_setopt_array($curl, [
CURLOPT_URL => "https://local.storage.nhost.run/v1/files/",
CURLOPT_URL => "https://local.storage.local.nhost.run/v1/files/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
@@ -112,7 +111,7 @@ import (
)
func main() {
url := "https://local.storage.nhost.run/v1/files/"
url := "https://local.storage.nhost.local.run/v1/files/"
var b bytes.Buffer
w := multipart.NewWriter(&b)
@@ -160,7 +159,7 @@ public class Main {
try {
File file = new File("<path_to_file>");
HttpResponse<String> response = Unirest.post("https://local.storage.nhost.run/v1/files/")
HttpResponse<String> response = Unirest.post("https://local.storage.local.nhost.run/v1/files/")
.header("Authorization", "<authorization>")
// Removed Content-Type header, Unirest handles it
.field("bucket-id", "<string>")
@@ -175,6 +174,5 @@ public class Main {
}
}
```
</RequestExample>

View File

@@ -1,5 +1,12 @@
# @nhost-examples/cli
## 0.3.18
### Patch Changes
- Updated dependencies [6b8163d]
- @nhost/nhost-js@3.2.5
## 0.3.17
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost-examples/cli",
"version": "0.3.17",
"version": "0.3.18",
"main": "src/index.mjs",
"private": true,
"scripts": {

View File

@@ -1,5 +1,12 @@
# @nhost-examples/codegen-react-apollo
## 0.5.1
### Patch Changes
- @nhost/react@3.10.1
- @nhost/react-apollo@17.0.1
## 0.5.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost-examples/codegen-react-apollo",
"version": "0.5.0",
"version": "0.5.1",
"private": true,
"scripts": {
"codegen": "graphql-codegen",

View File

@@ -1,5 +1,12 @@
# @nhost-examples/codegen-react-query
## 0.5.1
### Patch Changes
- 6b8163d: fix(nhost-js) update service URL generation for local environments
- @nhost/react@3.10.1
## 0.5.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost-examples/codegen-react-query",
"version": "0.5.0",
"version": "0.5.1",
"private": true,
"scripts": {
"codegen": "graphql-codegen",

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