Compare commits
27 Commits
@nhost/das
...
@nhost/rea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
614c20cbbf | ||
|
|
aef4a0a4fc | ||
|
|
d0c9f4cd17 | ||
|
|
e2646cab55 | ||
|
|
d5077c7ca4 | ||
|
|
c6d5c5cc8c | ||
|
|
f1d9b472d1 | ||
|
|
c6dc7f44df | ||
|
|
3cea460c36 | ||
|
|
4c351714f5 | ||
|
|
3143d66a8e | ||
|
|
8512a7f181 | ||
|
|
e503b8fe8b | ||
|
|
304065ae22 | ||
|
|
68e0622eb0 | ||
|
|
70c6834636 | ||
|
|
a7bde37bba | ||
|
|
1bc615beca | ||
|
|
a58c5cfc96 | ||
|
|
c61228e45d | ||
|
|
6cec04bd6f | ||
|
|
a448d7d182 | ||
|
|
948048940e | ||
|
|
5e91221d5a | ||
|
|
7278991a59 | ||
|
|
5924bc3248 | ||
|
|
c5ad634799 |
@@ -1,5 +1,58 @@
|
||||
# @nhost/dashboard
|
||||
|
||||
## 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
|
||||
|
||||
2
dashboard/e2e/e2e-tests-project/.gitignore
vendored
Normal file
2
dashboard/e2e/e2e-tests-project/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.secrets
|
||||
.nhost
|
||||
1
dashboard/e2e/e2e-tests-project/nhost/config.yaml
Normal file
1
dashboard/e2e/e2e-tests-project/nhost/config.yaml
Normal file
@@ -0,0 +1 @@
|
||||
version: 3
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Потвърдете смяната на вашия имейл</h2>
|
||||
<p>Използвайте посочения линк, за да повърдите смяната на имейл:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Смени имейл
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Потвърждение за смяна на имейл
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Потвърдете вашия имейл</h2>
|
||||
<p>Използвайте посочения линк, за да потвърдите вашия имейл:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Потвърдете имейл
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Потвърждаване на имейл
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Смяна на парола</h2>
|
||||
<p>Използвайте посочения линк, за да смените вашата парола:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Смяна на парола
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Смяна на парола
|
||||
@@ -0,0 +1 @@
|
||||
Вашият код е ${code}.
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Магически линк за вход</h2>
|
||||
<p>Използвайте посочения линк за защитен и бърз вход:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Вход
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Магически линк за вход
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Potvrzení změny emailové adresy</h2>
|
||||
<p>Použijte tento odkaz k potvrzení změny emailové adresy:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Změnit email
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Změna vaší emailové adresy
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Ověření emailové adresy</h2>
|
||||
<p>Použijte tento odkaz k ověření vaší emailové adresy:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Ověřit emailovou adresu
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Ověření vaší emailové adresy
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Obnova hesla</h2>
|
||||
<p>Použijte tento odkaz k obnovení vašeho hesla:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Obnova hesla
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Obnova hesla
|
||||
@@ -0,0 +1 @@
|
||||
Váš kód je ${code}.
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Magický odkaz</h2>
|
||||
<p>Použijte tento odkaz k bezpečnému přihlášení:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Přihlášení
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Bezpečný odkaz k přihlášení
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Confirm Email Change</h2>
|
||||
<p>Use this link to confirm changing email:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Change email
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Change your email address
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Verify Email</h2>
|
||||
<p>Use this link to verify your email:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Verify Email
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Verify your email
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Reset Password</h2>
|
||||
<p>Use this link to reset your password:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Reset password
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Reset your password
|
||||
@@ -0,0 +1 @@
|
||||
Your code is ${code}.
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Magic Link</h2>
|
||||
<p>Use this link to securely sign in:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Sign In
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Secure sign-in link
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Confirmar cambio de correo electrónico</h2>
|
||||
<p>Utiliza el siguiente enlace para confirmar el cambio de correo:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Cambiar correo electrónico
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Cambiar dirección de correo electrónico
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Verificar correo electrónico</h2>
|
||||
<p>Utilza el siguiente enlace para verificar tu correo:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Verificar correo electrónico
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Verifica tu correo electrónico
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Recuperar contraseña</h2>
|
||||
<p>Utiliza el siguiente enlace para recuperar tu contraseña:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Recuperar contraseña
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Recuperar contraseña
|
||||
@@ -0,0 +1 @@
|
||||
Tu código es ${code}.
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Enlace mágico</h2>
|
||||
<p>Utiliza este enlace para iniciar sesión de forma segura:</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Iniciar sesión
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Enlace de acceso seguro
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Confirmer changement de courriel</h2>
|
||||
<p>Utilisez ce lien pour confirmer le changement de courriel :</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Changer courriel
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Changez votre adresse courriel
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Vérifiez votre courriel</h2>
|
||||
<p>Utilisez ce lien pour vérifier votre courriel :</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Vérifier courriel
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Vérifier votre courriel
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Réinitialiser votre mot de passe</h2>
|
||||
<p>Utilisez ce lien pour réinitialiser votre mot de passe :</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Réinitialiser mot de passe
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Réinitialiser votre mot de passe
|
||||
@@ -0,0 +1 @@
|
||||
Votre code est ${code}.
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Lien magique</h2>
|
||||
<p>Utilisez ce lien pour vous connecter de façon sécurisée :</p>
|
||||
<p>
|
||||
<a href="${link}">
|
||||
Connexion
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Lien de connexion sécurisé
|
||||
@@ -0,0 +1,8 @@
|
||||
${link},
|
||||
${displayName},
|
||||
${email},
|
||||
${ticket},
|
||||
${redirectTo},
|
||||
${serverUrl},
|
||||
${clientUrl},
|
||||
${locale},
|
||||
@@ -0,0 +1 @@
|
||||
${link}, ${displayName}, ${email}, ${ticket}, ${redirectTo}, ${serverUrl}, ${clientUrl}, ${locale}
|
||||
151
dashboard/e2e/e2e-tests-project/nhost/nhost.toml
Normal file
151
dashboard/e2e/e2e-tests-project/nhost/nhost.toml
Normal file
@@ -0,0 +1,151 @@
|
||||
[global]
|
||||
|
||||
[hasura]
|
||||
version = 'v2.33.4-ce'
|
||||
adminSecret = '{{ secrets.HASURA_GRAPHQL_ADMIN_SECRET }}'
|
||||
webhookSecret = '{{ secrets.NHOST_WEBHOOK_SECRET }}'
|
||||
|
||||
[[hasura.jwtSecrets]]
|
||||
type = 'HS256'
|
||||
key = '{{ secrets.HASURA_GRAPHQL_JWT_SECRET }}'
|
||||
|
||||
[hasura.settings]
|
||||
corsDomain = ['*']
|
||||
devMode = true
|
||||
enableAllowList = false
|
||||
enableConsole = true
|
||||
enableRemoteSchemaPermissions = false
|
||||
enabledAPIs = ['metadata', 'graphql', 'pgdump', 'config']
|
||||
liveQueriesMultiplexedRefetchInterval = 1000
|
||||
stringifyNumericTypes = false
|
||||
|
||||
[hasura.logs]
|
||||
level = 'warn'
|
||||
|
||||
[hasura.events]
|
||||
httpPoolSize = 100
|
||||
|
||||
[functions]
|
||||
[functions.node]
|
||||
version = 18
|
||||
|
||||
[auth]
|
||||
version = '0.24.1'
|
||||
|
||||
[auth.elevatedPrivileges]
|
||||
mode = 'disabled'
|
||||
|
||||
[auth.redirections]
|
||||
clientUrl = 'http://localhost:3000'
|
||||
|
||||
[auth.signUp]
|
||||
enabled = true
|
||||
disableNewUsers = false
|
||||
|
||||
[auth.user]
|
||||
[auth.user.roles]
|
||||
default = 'user'
|
||||
allowed = ['user', 'me']
|
||||
|
||||
[auth.user.locale]
|
||||
default = 'en'
|
||||
allowed = ['en']
|
||||
|
||||
[auth.user.gravatar]
|
||||
enabled = true
|
||||
default = 'blank'
|
||||
rating = 'g'
|
||||
|
||||
[auth.user.email]
|
||||
|
||||
[auth.user.emailDomains]
|
||||
|
||||
[auth.session]
|
||||
[auth.session.accessToken]
|
||||
expiresIn = 900
|
||||
|
||||
[auth.session.refreshToken]
|
||||
expiresIn = 2592000
|
||||
|
||||
[auth.method]
|
||||
[auth.method.anonymous]
|
||||
enabled = false
|
||||
|
||||
[auth.method.emailPasswordless]
|
||||
enabled = false
|
||||
|
||||
[auth.method.emailPassword]
|
||||
hibpEnabled = false
|
||||
emailVerificationRequired = true
|
||||
passwordMinLength = 9
|
||||
|
||||
[auth.method.smsPasswordless]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth]
|
||||
[auth.method.oauth.apple]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.azuread]
|
||||
tenant = 'common'
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.bitbucket]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.discord]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.facebook]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.github]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.gitlab]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.google]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.linkedin]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.spotify]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.strava]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.twitch]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.twitter]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.windowslive]
|
||||
enabled = false
|
||||
|
||||
[auth.method.oauth.workos]
|
||||
enabled = false
|
||||
|
||||
[auth.method.webauthn]
|
||||
enabled = false
|
||||
|
||||
[auth.method.webauthn.attestation]
|
||||
timeout = 60000
|
||||
|
||||
[auth.totp]
|
||||
enabled = false
|
||||
|
||||
[postgres]
|
||||
version = '14.6-20240129-1'
|
||||
|
||||
[provider]
|
||||
|
||||
[storage]
|
||||
version = '0.6.0'
|
||||
|
||||
[observability]
|
||||
[observability.grafana]
|
||||
adminPassword = '{{ secrets.GRAFANA_ADMIN_PASSWORD }}'
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/dashboard",
|
||||
"version": "1.13.2",
|
||||
"version": "1.16.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
|
||||
@@ -29,10 +29,10 @@ const getInternalErrorMessage = (
|
||||
|
||||
if (error.name === 'ApolloError') {
|
||||
// @ts-ignore
|
||||
const internalError = error.graphQLErrors?.[0]?.extensions?.internal as {
|
||||
error: { message: string };
|
||||
};
|
||||
return internalError?.error?.message || null;
|
||||
const graphqlError = error.graphQLErrors?.[0];
|
||||
const graphqlExtensionsError = graphqlError?.extensions?.internal
|
||||
?.error as { message: string };
|
||||
return graphqlError.message || graphqlExtensionsError?.message || null;
|
||||
}
|
||||
|
||||
if (error instanceof Error) {
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
import { ApplyLocalSettingsDialog } from '@/components/common/ApplyLocalSettingsDialog';
|
||||
import { useDialog } from '@/components/common/DialogProvider';
|
||||
import { useUI } from '@/components/common/UIProvider';
|
||||
import { SettingsContainer } from '@/components/layout/SettingsContainer';
|
||||
import { Box } from '@/components/ui/v2/Box';
|
||||
import { Button } from '@/components/ui/v2/Button';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { useIsPlatform } from '@/features/projects/common/hooks/useIsPlatform';
|
||||
import { useLocalMimirClient } from '@/hooks/useLocalMimirClient';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetSmtpSettingsDocument,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { useState } from 'react';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
function ConfirmDeleteSMTPSettingsModal({
|
||||
close,
|
||||
onDelete,
|
||||
}: {
|
||||
onDelete?: () => Promise<any>;
|
||||
close: () => void;
|
||||
}) {
|
||||
const onClickDelete = async () => {
|
||||
await onDelete();
|
||||
close();
|
||||
};
|
||||
|
||||
return (
|
||||
<Box className={twMerge('w-full rounded-lg p-6 text-left')}>
|
||||
<div className="grid grid-flow-row gap-4">
|
||||
<Text variant="h3" component="h2">
|
||||
Delete SMTP Settings?
|
||||
</Text>
|
||||
|
||||
<Text>This will reset all your SMTP and Postmark settings.</Text>
|
||||
|
||||
<div className="grid grid-flow-row gap-2">
|
||||
<Button color="error" onClick={onClickDelete}>
|
||||
Delete
|
||||
</Button>
|
||||
|
||||
<Button variant="outlined" color="secondary" onClick={close}>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DeleteSMTPSettings() {
|
||||
const { openDialog, closeDialog } = useDialog();
|
||||
|
||||
const isPlatform = useIsPlatform();
|
||||
const localMimirClient = useLocalMimirClient();
|
||||
const { maintenanceActive } = useUI();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
|
||||
const [updateConfig] = useUpdateConfigMutation({
|
||||
refetchQueries: [GetSmtpSettingsDocument],
|
||||
...(!isPlatform ? { client: localMimirClient } : {}),
|
||||
});
|
||||
|
||||
const deleteSMTPSettings = async () => {
|
||||
const updateConfigPromise = updateConfig({
|
||||
variables: {
|
||||
appId: currentProject.id,
|
||||
config: {
|
||||
provider: {
|
||||
smtp: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
setLoading(true);
|
||||
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
|
||||
if (!isPlatform) {
|
||||
openDialog({
|
||||
title: 'Apply your changes',
|
||||
component: <ApplyLocalSettingsDialog />,
|
||||
props: {
|
||||
PaperProps: {
|
||||
className: 'max-w-2xl',
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
loadingMessage: 'SMTP settings are being deleted...',
|
||||
successMessage: 'SMTP settings have been deleted successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to delete the SMTP settings.',
|
||||
},
|
||||
);
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const confirmDeleteSMTPSettings = async () => {
|
||||
openDialog({
|
||||
component: (
|
||||
<ConfirmDeleteSMTPSettingsModal
|
||||
close={closeDialog}
|
||||
onDelete={deleteSMTPSettings}
|
||||
/>
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingsContainer
|
||||
title="Delete SMTP Settings"
|
||||
description="Delete SMTP settings and revert to default values"
|
||||
className="px-0"
|
||||
slotProps={{
|
||||
submitButton: { className: 'hidden' },
|
||||
footer: { className: 'hidden' },
|
||||
}}
|
||||
>
|
||||
<Box className="grid grid-flow-row border-t-1">
|
||||
<Button
|
||||
color="error"
|
||||
className="mx-4 mt-4 justify-self-end"
|
||||
onClick={confirmDeleteSMTPSettings}
|
||||
disabled={loading || maintenanceActive}
|
||||
loading={loading}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</Box>
|
||||
</SettingsContainer>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default as DeleteSTMPSettings } from './DeleteSMTPSettings';
|
||||
@@ -0,0 +1,149 @@
|
||||
import { ApplyLocalSettingsDialog } from '@/components/common/ApplyLocalSettingsDialog';
|
||||
import { useDialog } from '@/components/common/DialogProvider';
|
||||
import { useUI } from '@/components/common/UIProvider';
|
||||
import { Form } from '@/components/form/Form';
|
||||
import { SettingsContainer } from '@/components/layout/SettingsContainer';
|
||||
import { Input } from '@/components/ui/v2/Input';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { useIsPlatform } from '@/features/projects/common/hooks/useIsPlatform';
|
||||
import { useLocalMimirClient } from '@/hooks/useLocalMimirClient';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetSmtpSettingsDocument,
|
||||
useGetSmtpSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import * as yup from 'yup';
|
||||
|
||||
const validationSchema = yup
|
||||
.object({
|
||||
sender: yup.string().label('SMTP Sender').email().required(),
|
||||
password: yup.string().label('Password').required(),
|
||||
})
|
||||
.required();
|
||||
|
||||
export type PostmarkFormValues = yup.InferType<typeof validationSchema>;
|
||||
|
||||
export default function PostmarkSettings() {
|
||||
const { openDialog } = useDialog();
|
||||
const isPlatform = useIsPlatform();
|
||||
const { maintenanceActive } = useUI();
|
||||
const localMimirClient = useLocalMimirClient();
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
|
||||
const { data } = useGetSmtpSettingsQuery({
|
||||
variables: { appId: currentProject?.id },
|
||||
...(!isPlatform ? { client: localMimirClient } : {}),
|
||||
});
|
||||
|
||||
const { sender, password } = data?.config?.provider?.smtp || {};
|
||||
|
||||
const [updateConfig] = useUpdateConfigMutation({
|
||||
refetchQueries: [GetSmtpSettingsDocument],
|
||||
...(!isPlatform ? { client: localMimirClient } : {}),
|
||||
});
|
||||
|
||||
const form = useForm<PostmarkFormValues>({
|
||||
reValidateMode: 'onSubmit',
|
||||
resolver: yupResolver(validationSchema),
|
||||
defaultValues: {
|
||||
password: '',
|
||||
sender: '',
|
||||
},
|
||||
values: {
|
||||
password: password || '',
|
||||
sender: sender || '',
|
||||
},
|
||||
mode: 'onSubmit',
|
||||
criteriaMode: 'all',
|
||||
});
|
||||
|
||||
const {
|
||||
register,
|
||||
formState: { errors, isDirty, isSubmitting },
|
||||
} = form;
|
||||
|
||||
const handleEditPostmarkSettings = async (values: PostmarkFormValues) => {
|
||||
const updateConfigPromise = updateConfig({
|
||||
variables: {
|
||||
appId: currentProject.id,
|
||||
config: {
|
||||
provider: {
|
||||
smtp: { method: 'LOGIN', host: 'postmark', ...values },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
|
||||
if (!isPlatform) {
|
||||
openDialog({
|
||||
title: 'Apply your changes',
|
||||
component: <ApplyLocalSettingsDialog />,
|
||||
props: {
|
||||
PaperProps: {
|
||||
className: 'max-w-2xl',
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Postmark settings are being updated...',
|
||||
successMessage: 'Postmark settings have been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update your Postmark settings.',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<Form onSubmit={handleEditPostmarkSettings}>
|
||||
<SettingsContainer
|
||||
title="Postmark Settings"
|
||||
description="Configure postmark's native integration to send emails from your email domain."
|
||||
submitButtonText="Save"
|
||||
className="grid grid-cols-9 gap-4"
|
||||
slotProps={{
|
||||
submitButton: {
|
||||
disabled: !isDirty || maintenanceActive,
|
||||
loading: isSubmitting,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
{...register('sender')}
|
||||
id="sender"
|
||||
name="sender"
|
||||
label="From Email"
|
||||
placeholder="noreply@nhost.app"
|
||||
className="lg:col-span-4"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.sender)}
|
||||
helperText={errors.sender?.message}
|
||||
/>
|
||||
|
||||
<Input
|
||||
{...register('password')}
|
||||
id="password"
|
||||
label="Password"
|
||||
type="password"
|
||||
placeholder="Enter password"
|
||||
className="lg:col-span-5"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.password)}
|
||||
helperText={errors.password?.message}
|
||||
/>
|
||||
</SettingsContainer>
|
||||
</Form>
|
||||
</FormProvider>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './PostmarkSettings';
|
||||
export { default as PostmarkSettings } from './PostmarkSettings';
|
||||
@@ -0,0 +1,238 @@
|
||||
import { ApplyLocalSettingsDialog } from '@/components/common/ApplyLocalSettingsDialog';
|
||||
import { useDialog } from '@/components/common/DialogProvider';
|
||||
import { useUI } from '@/components/common/UIProvider';
|
||||
import { ControlledCheckbox } from '@/components/form/ControlledCheckbox';
|
||||
import { Form } from '@/components/form/Form';
|
||||
import { SettingsContainer } from '@/components/layout/SettingsContainer';
|
||||
import { Input } from '@/components/ui/v2/Input';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { useIsPlatform } from '@/features/projects/common/hooks/useIsPlatform';
|
||||
import { useLocalMimirClient } from '@/hooks/useLocalMimirClient';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetSmtpSettingsDocument,
|
||||
useGetSmtpSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { type Optional } from 'utility-types';
|
||||
import * as yup from 'yup';
|
||||
|
||||
const smtpValidationSchema = yup
|
||||
.object({
|
||||
secure: yup.bool().label('SMTP Secure'),
|
||||
host: yup
|
||||
.string()
|
||||
.label('SMTP Host')
|
||||
.matches(
|
||||
/((https?):\/\/)?(www\.)?[a-z0-9]+(\.[a-z]{2,}){1,3}(#[a-zA-Z0-9#]+?)*\/?(\?[a-zA-Z0-9-_]+=[a-zA-Z0-9-%]+&?)?$/,
|
||||
'SMTP Host must be a valid URL',
|
||||
)
|
||||
.required(),
|
||||
port: yup
|
||||
.number()
|
||||
.typeError('The SMTP port should contain only numbers.')
|
||||
.required(),
|
||||
user: yup.string().label('Username').required(),
|
||||
password: yup.string().label('Password'),
|
||||
method: yup.string().required(),
|
||||
sender: yup.string().label('SMTP Sender').email().required(),
|
||||
})
|
||||
.required();
|
||||
|
||||
export type SmtpFormValues = yup.InferType<typeof smtpValidationSchema>;
|
||||
|
||||
export default function SMTPSettings() {
|
||||
const { maintenanceActive } = useUI();
|
||||
const { openDialog } = useDialog();
|
||||
const isPlatform = useIsPlatform();
|
||||
const localMimirClient = useLocalMimirClient();
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
|
||||
const { data } = useGetSmtpSettingsQuery({
|
||||
variables: { appId: currentProject?.id },
|
||||
...(!isPlatform ? { client: localMimirClient } : {}),
|
||||
});
|
||||
|
||||
const { secure, host, port, user, method, sender, password } =
|
||||
data?.config?.provider?.smtp || {};
|
||||
|
||||
const form = useForm<Optional<SmtpFormValues, 'password'>>({
|
||||
reValidateMode: 'onSubmit',
|
||||
resolver: yupResolver(smtpValidationSchema),
|
||||
defaultValues: {
|
||||
secure: false,
|
||||
host: '',
|
||||
port: undefined,
|
||||
user: '',
|
||||
password: '',
|
||||
method: '',
|
||||
sender: '',
|
||||
},
|
||||
values: {
|
||||
secure: secure || false,
|
||||
host: host || '',
|
||||
port,
|
||||
user: user || '',
|
||||
password: password || '',
|
||||
method: method || '',
|
||||
sender: sender || '',
|
||||
},
|
||||
mode: 'onSubmit',
|
||||
criteriaMode: 'all',
|
||||
});
|
||||
|
||||
const {
|
||||
register: registerSmtp,
|
||||
formState: { errors, isDirty, isSubmitting },
|
||||
} = form;
|
||||
|
||||
const [updateConfig] = useUpdateConfigMutation({
|
||||
refetchQueries: [GetSmtpSettingsDocument],
|
||||
...(!isPlatform ? { client: localMimirClient } : {}),
|
||||
});
|
||||
|
||||
const handleEditSMTPSettings = async (values: SmtpFormValues) => {
|
||||
const { password: newPassword, ...valuesWithoutPassword } = values;
|
||||
|
||||
const updateConfigPromise = updateConfig({
|
||||
variables: {
|
||||
appId: currentProject.id,
|
||||
config: {
|
||||
provider: {
|
||||
smtp: newPassword ? values : valuesWithoutPassword,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
|
||||
if (!isPlatform) {
|
||||
openDialog({
|
||||
title: 'Apply your changes',
|
||||
component: <ApplyLocalSettingsDialog />,
|
||||
props: {
|
||||
PaperProps: {
|
||||
className: 'max-w-2xl',
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
loadingMessage: 'SMTP settings are being updated...',
|
||||
successMessage: 'SMTP settings have been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update the SMTP settings.',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<Form onSubmit={handleEditSMTPSettings}>
|
||||
<SettingsContainer
|
||||
title="SMTP Settings"
|
||||
description="Configure your SMTP settings to send emails from your email domain."
|
||||
submitButtonText="Save"
|
||||
className="grid grid-cols-9 gap-4"
|
||||
slotProps={{
|
||||
submitButton: {
|
||||
disabled: !isDirty || maintenanceActive,
|
||||
loading: isSubmitting,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
{...registerSmtp('sender')}
|
||||
id="sender"
|
||||
name="sender"
|
||||
label="From Email"
|
||||
placeholder="noreply@nhost.app"
|
||||
className="lg:col-span-4"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.sender)}
|
||||
helperText={errors.sender?.message}
|
||||
/>
|
||||
|
||||
<Input
|
||||
{...registerSmtp('host')}
|
||||
id="host"
|
||||
name="host"
|
||||
label="SMTP Host"
|
||||
className="lg:col-span-4"
|
||||
placeholder="e.g. smtp.sendgrid.net"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.host)}
|
||||
helperText={errors.host?.message}
|
||||
/>
|
||||
|
||||
<Input
|
||||
{...registerSmtp('port')}
|
||||
id="port"
|
||||
name="port"
|
||||
label="Port"
|
||||
type="number"
|
||||
placeholder="587"
|
||||
className="lg:col-span-1"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.port)}
|
||||
helperText={errors.port?.message}
|
||||
/>
|
||||
|
||||
<Input
|
||||
{...registerSmtp('user')}
|
||||
id="user"
|
||||
label="SMTP Username"
|
||||
placeholder="SMTP Username"
|
||||
className="lg:col-span-4"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.user)}
|
||||
helperText={errors.user?.message}
|
||||
/>
|
||||
|
||||
<Input
|
||||
{...registerSmtp('password')}
|
||||
id="password"
|
||||
label="SMTP Password"
|
||||
type="password"
|
||||
placeholder="Enter SMTP password"
|
||||
className="lg:col-span-5"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.password)}
|
||||
helperText={errors.password?.message}
|
||||
/>
|
||||
|
||||
<Input
|
||||
{...registerSmtp('method')}
|
||||
id="method"
|
||||
name="method"
|
||||
label="SMTP Auth Method"
|
||||
placeholder="LOGIN"
|
||||
hideEmptyHelperText
|
||||
className="lg:col-span-4"
|
||||
fullWidth
|
||||
error={Boolean(errors.method)}
|
||||
helperText={errors.method?.message}
|
||||
/>
|
||||
|
||||
<ControlledCheckbox
|
||||
name="secure"
|
||||
id="secure"
|
||||
label="Use SSL"
|
||||
className="lg:col-span-9"
|
||||
/>
|
||||
</SettingsContainer>
|
||||
</Form>
|
||||
</FormProvider>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './SMTPSettings';
|
||||
export { default as SMTPSettings } from './SMTPSettings';
|
||||
@@ -31,9 +31,10 @@ import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useTheme } from '@mui/material';
|
||||
import { format } from 'date-fns';
|
||||
import kebabCase from 'just-kebab-case';
|
||||
import debounce from 'lodash.debounce';
|
||||
import Image from 'next/image';
|
||||
import type { RemoteAppUser } from 'pages/[workspaceSlug]/[appSlug]/users';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -76,6 +77,21 @@ export const EditUserFormValidationSchema = Yup.object({
|
||||
locale: Yup.string(),
|
||||
defaultRole: Yup.string(),
|
||||
roles: Yup.array().of(Yup.boolean()),
|
||||
metadata: Yup.string().test(
|
||||
'is-valid-json',
|
||||
'Metadata must be valid JSON or empty',
|
||||
(value) => {
|
||||
if (value === '') {
|
||||
return true;
|
||||
} // Allow empty string as valid input
|
||||
try {
|
||||
JSON.parse(value);
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
),
|
||||
});
|
||||
|
||||
export type EditUserFormValues = Yup.InferType<
|
||||
@@ -116,14 +132,55 @@ export default function EditUserForm({
|
||||
locale: user.locale,
|
||||
defaultRole: user.defaultRole,
|
||||
roles: roles.map((role) => Object.values(role)[0]),
|
||||
metadata: user?.metadata ? JSON.stringify(user.metadata, null, 2) : '',
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
register,
|
||||
setError,
|
||||
clearErrors,
|
||||
formState: { errors, dirtyFields, isSubmitting, isValidating },
|
||||
} = form;
|
||||
|
||||
const handleMetadataError = useMemo(() => {
|
||||
const debouncedSetError = debounce((value) => {
|
||||
try {
|
||||
JSON.parse(value);
|
||||
// Only set an error if JSON parsing fails
|
||||
} catch (error) {
|
||||
setError('metadata', {
|
||||
type: 'manual',
|
||||
message: 'Invalid JSON format',
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
|
||||
return {
|
||||
call: debouncedSetError,
|
||||
cancel: debouncedSetError.cancel, // lodash debounce provides a cancel method to stop the delayed function
|
||||
};
|
||||
}, [setError]);
|
||||
|
||||
const handleMetadataChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { value } = event.target;
|
||||
if (value === '') {
|
||||
clearErrors('metadata'); // Clear errors when the input is explicitly cleared
|
||||
handleMetadataError.cancel(); // Cancel any debounced error checks
|
||||
} else {
|
||||
try {
|
||||
JSON.parse(value);
|
||||
clearErrors('metadata'); // Clear errors when valid JSON is entered
|
||||
handleMetadataError.cancel(); // Cancel pending debounced error checks
|
||||
} catch (error) {
|
||||
handleMetadataError.call(value); // Call the debounced error setter
|
||||
}
|
||||
}
|
||||
},
|
||||
[clearErrors, handleMetadataError],
|
||||
);
|
||||
|
||||
const isDirty = Object.keys(dirtyFields).length > 0;
|
||||
|
||||
useEffect(() => {
|
||||
@@ -467,6 +524,28 @@ export default function EditUserForm({
|
||||
</div>
|
||||
</Box>
|
||||
)}
|
||||
<Box component="section" className="grid grid-flow-row gap-8 p-6">
|
||||
<Input
|
||||
{...register('metadata', { onChange: handleMetadataChange })}
|
||||
id="metadata"
|
||||
label="Metadata"
|
||||
variant="inline"
|
||||
hideEmptyHelperText
|
||||
error={!!errors.metadata}
|
||||
fullWidth
|
||||
multiline
|
||||
inputProps={{
|
||||
className: 'resize-y min-h-[130px]',
|
||||
}}
|
||||
helperText={
|
||||
errors.metadata
|
||||
? errors.metadata.message
|
||||
: 'Enter valid JSON. This can be a number, boolean, array, or object.'
|
||||
}
|
||||
maxRows={100}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box className="grid w-full flex-shrink-0 snap-end grid-flow-col justify-between gap-3 place-self-end border-t-1 p-2">
|
||||
|
||||
@@ -113,6 +113,9 @@ export default function UsersBody({ users, onSubmit }: UsersBodyProps) {
|
||||
phoneNumber: values.phoneNumber,
|
||||
phoneNumberVerified: values.phoneNumberVerified,
|
||||
locale: values.locale,
|
||||
...(values?.metadata !== undefined && values.metadata !== ''
|
||||
? { metadata: JSON.parse(values.metadata) }
|
||||
: { metadata: null }),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import { ApplyLocalSettingsDialog } from '@/components/common/ApplyLocalSettingsDialog';
|
||||
import { useDialog } from '@/components/common/DialogProvider';
|
||||
import { useUI } from '@/components/common/UIProvider';
|
||||
import { Form } from '@/components/form/Form';
|
||||
import { SettingsContainer } from '@/components/layout/SettingsContainer';
|
||||
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
|
||||
import { Alert } from '@/components/ui/v2/Alert';
|
||||
@@ -7,11 +11,32 @@ import type { InputProps } from '@/components/ui/v2/Input';
|
||||
import { Input } from '@/components/ui/v2/Input';
|
||||
import { InputAdornment } from '@/components/ui/v2/InputAdornment';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { useIsPlatform } from '@/features/projects/common/hooks/useIsPlatform';
|
||||
import { generateAppServiceUrl } from '@/features/projects/common/utils/generateAppServiceUrl';
|
||||
import { useLocalMimirClient } from '@/hooks/useLocalMimirClient';
|
||||
import { copy } from '@/utils/copy';
|
||||
import { useGetPostgresSettingsQuery } from '@/utils/__generated__/graphql';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
useGetPostgresSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
const databasePublicAccessValidationSchema = Yup.object({
|
||||
enablePublicAccess: Yup.bool(),
|
||||
});
|
||||
|
||||
type DatabasePublicAccessFormValues = Yup.InferType<
|
||||
typeof databasePublicAccessValidationSchema
|
||||
>;
|
||||
|
||||
export default function DatabaseConnectionInfo() {
|
||||
const { openDialog } = useDialog();
|
||||
const isPlatform = useIsPlatform();
|
||||
const { maintenanceActive } = useUI();
|
||||
const localMimirClient = useLocalMimirClient();
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
|
||||
const { data, loading, error } = useGetPostgresSettingsQuery({
|
||||
@@ -19,6 +44,61 @@ export default function DatabaseConnectionInfo() {
|
||||
fetchPolicy: 'cache-only',
|
||||
});
|
||||
|
||||
const [updateConfig] = useUpdateConfigMutation({
|
||||
...(!isPlatform ? { client: localMimirClient } : {}),
|
||||
});
|
||||
|
||||
const enablePublicAccess =
|
||||
!!data?.config?.postgres?.resources?.enablePublicAccess;
|
||||
|
||||
const form = useForm<DatabasePublicAccessFormValues>({
|
||||
reValidateMode: 'onSubmit',
|
||||
defaultValues: {
|
||||
enablePublicAccess,
|
||||
},
|
||||
resolver: yupResolver(databasePublicAccessValidationSchema),
|
||||
});
|
||||
|
||||
async function handleSubmit(formValues: DatabasePublicAccessFormValues) {
|
||||
const updateConfigPromise = updateConfig({
|
||||
variables: {
|
||||
appId: currentProject.id,
|
||||
config: {
|
||||
postgres: {
|
||||
resources: {
|
||||
enablePublicAccess: formValues.enablePublicAccess,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
form.reset(formValues);
|
||||
|
||||
if (!isPlatform) {
|
||||
openDialog({
|
||||
title: 'Apply your changes',
|
||||
component: <ApplyLocalSettingsDialog />,
|
||||
props: {
|
||||
PaperProps: {
|
||||
className: 'max-w-2xl',
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
loadingMessage: 'Database settings are being updated...',
|
||||
successMessage: 'Database settings have been updated successfully.',
|
||||
errorMessage:
|
||||
"An error occurred while trying to update the project's database settings.",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<ActivityIndicator
|
||||
@@ -76,49 +156,72 @@ export default function DatabaseConnectionInfo() {
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<SettingsContainer
|
||||
title="Connection Info"
|
||||
description="Connect directly to the Postgres database with this information."
|
||||
slotProps={{ footer: { className: 'hidden' } }}
|
||||
className="grid grid-cols-6 gap-4 pb-2"
|
||||
>
|
||||
{settingsDatabaseCustomInputs.map(
|
||||
({ name, label, className, value: inputValue }) => (
|
||||
<Input
|
||||
key={name}
|
||||
label={label}
|
||||
required
|
||||
disabled
|
||||
value={inputValue}
|
||||
className={className}
|
||||
slotProps={{ inputRoot: { className: '!pr-8 truncate' } }}
|
||||
fullWidth
|
||||
hideEmptyHelperText
|
||||
endAdornment={
|
||||
<InputAdornment position="end" className="absolute right-2">
|
||||
<Button
|
||||
sx={{ minWidth: 0, padding: 0 }}
|
||||
color="secondary"
|
||||
variant="borderless"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copy(inputValue as string, `${label}`);
|
||||
}}
|
||||
>
|
||||
<CopyIcon className="h-4 w-4" />
|
||||
</Button>
|
||||
</InputAdornment>
|
||||
}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
const { formState } = form;
|
||||
|
||||
<Alert severity="info" className="col-span-6 text-left">
|
||||
To connect to the Postgres database directly, generate a new password,
|
||||
securely save it, and then modify your connection string with the newly
|
||||
created password.
|
||||
</Alert>
|
||||
</SettingsContainer>
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<SettingsContainer
|
||||
title="Public access"
|
||||
description={
|
||||
enablePublicAccess
|
||||
? 'Connect directly to the Postgres database with this information.'
|
||||
: 'Enable public access to your Postgres database.'
|
||||
}
|
||||
slotProps={{
|
||||
submitButton: {
|
||||
disabled: !formState.isDirty || maintenanceActive,
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
className="grid grid-cols-6 gap-4 pb-2"
|
||||
switchId="enablePublicAccess"
|
||||
showSwitch
|
||||
>
|
||||
{enablePublicAccess && (
|
||||
<>
|
||||
{settingsDatabaseCustomInputs.map(
|
||||
({ name, label, className, value: inputValue }) => (
|
||||
<Input
|
||||
key={name}
|
||||
label={label}
|
||||
required
|
||||
disabled
|
||||
value={inputValue}
|
||||
className={className}
|
||||
slotProps={{ inputRoot: { className: '!pr-8 truncate' } }}
|
||||
fullWidth
|
||||
hideEmptyHelperText
|
||||
endAdornment={
|
||||
<InputAdornment
|
||||
position="end"
|
||||
className="absolute right-2"
|
||||
>
|
||||
<Button
|
||||
sx={{ minWidth: 0, padding: 0 }}
|
||||
color="secondary"
|
||||
variant="borderless"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copy(inputValue as string, `${label}`);
|
||||
}}
|
||||
>
|
||||
<CopyIcon className="w-4 h-4" />
|
||||
</Button>
|
||||
</InputAdornment>
|
||||
}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
<Alert severity="info" className="col-span-6 text-left">
|
||||
To connect to the Postgres database directly, generate a new
|
||||
password, securely save it, and then modify your connection
|
||||
string with the newly created password.
|
||||
</Alert>
|
||||
</>
|
||||
)}
|
||||
</SettingsContainer>
|
||||
</Form>
|
||||
</FormProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ query GetPostgresSettings($appId: uuid!) {
|
||||
storage {
|
||||
capacity
|
||||
}
|
||||
enablePublicAccess
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ query GetSmtpSettings($appId: uuid!) {
|
||||
secure
|
||||
sender
|
||||
user
|
||||
password
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ mutation UpdateConfig($appId: uuid!, $config: ConfigConfigUpdateInput!) {
|
||||
storage {
|
||||
capacity
|
||||
}
|
||||
enablePublicAccess
|
||||
}
|
||||
}
|
||||
ai {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
mutation insertGraphiteAutoEmbeddingsConfiguration(
|
||||
$name: String
|
||||
$model: embedding_model_enum
|
||||
$model: String
|
||||
$schemaName: String
|
||||
$tableName: String
|
||||
$columnName: String
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
mutation updateGraphiteAutoEmbeddingsConfiguration(
|
||||
$id: uuid!
|
||||
$name: String
|
||||
$model: embedding_model_enum
|
||||
$model: String
|
||||
$schemaName: String
|
||||
$tableName: String
|
||||
$columnName: String
|
||||
|
||||
@@ -11,6 +11,7 @@ fragment RemoteAppGetUsers on users {
|
||||
defaultRole
|
||||
lastSeen
|
||||
locale
|
||||
metadata
|
||||
roles {
|
||||
id
|
||||
role
|
||||
|
||||
@@ -1,100 +1,35 @@
|
||||
import { ApplyLocalSettingsDialog } from '@/components/common/ApplyLocalSettingsDialog';
|
||||
import { useDialog } from '@/components/common/DialogProvider';
|
||||
import { useUI } from '@/components/common/UIProvider';
|
||||
import { ControlledCheckbox } from '@/components/form/ControlledCheckbox';
|
||||
import { Form } from '@/components/form/Form';
|
||||
import { Container } from '@/components/layout/Container';
|
||||
import { SettingsContainer } from '@/components/layout/SettingsContainer';
|
||||
import { SettingsLayout } from '@/components/layout/SettingsLayout';
|
||||
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
|
||||
import { Input } from '@/components/ui/v2/Input';
|
||||
import { Option } from '@/components/ui/v2/Option';
|
||||
import { Select } from '@/components/ui/v2/Select';
|
||||
import DeleteSMTPSettings from '@/features/authentication/settings/components/DeleteSMTPSettings/DeleteSMTPSettings';
|
||||
import { PostmarkSettings } from '@/features/authentication/settings/components/PostmarkSettings';
|
||||
import { SMTPSettings } from '@/features/authentication/settings/components/SMTPSettings';
|
||||
import { UpgradeNotification } from '@/features/projects/common/components/UpgradeNotification';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { useIsPlatform } from '@/features/projects/common/hooks/useIsPlatform';
|
||||
import { useLocalMimirClient } from '@/hooks/useLocalMimirClient';
|
||||
import { execPromiseWithErrorToast } from '@/utils/execPromiseWithErrorToast';
|
||||
import {
|
||||
GetSmtpSettingsDocument,
|
||||
useGetSmtpSettingsQuery,
|
||||
useUpdateConfigMutation,
|
||||
} from '@/utils/__generated__/graphql';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import type { ReactElement } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import type { Optional } from 'utility-types';
|
||||
import * as yup from 'yup';
|
||||
|
||||
const smtpValidationSchema = yup
|
||||
.object({
|
||||
secure: yup.bool().label('SMTP Secure'),
|
||||
host: yup
|
||||
.string()
|
||||
.label('SMTP Host')
|
||||
.matches(
|
||||
/((https?):\/\/)?(www.)?[a-z0-9]+(\.[a-z]{2,}){1,3}(#?\/?[a-zA-Z0-9#]+)*\/?(\?[a-zA-Z0-9-_]+=[a-zA-Z0-9-%]+&?)?$/,
|
||||
'SMTP Host must be a valid URL',
|
||||
)
|
||||
.required(),
|
||||
port: yup
|
||||
.number()
|
||||
.typeError('The SMTP port should contain only numbers.')
|
||||
.required(),
|
||||
user: yup.string().label('Username').required(),
|
||||
password: yup.string().label('Password'),
|
||||
method: yup.string().required(),
|
||||
sender: yup.string().label('SMTP Sender').email().required(),
|
||||
})
|
||||
.required();
|
||||
|
||||
export type SmtpFormValues = yup.InferType<typeof smtpValidationSchema>;
|
||||
import { useGetSmtpSettingsQuery } from '@/utils/__generated__/graphql';
|
||||
import { useEffect, useState, type ReactElement } from 'react';
|
||||
|
||||
export default function SMTPSettingsPage() {
|
||||
const { openDialog } = useDialog();
|
||||
const isPlatform = useIsPlatform();
|
||||
const { maintenanceActive } = useUI();
|
||||
const localMimirClient = useLocalMimirClient();
|
||||
const { currentProject } = useCurrentWorkspaceAndProject();
|
||||
|
||||
const [mode, setMode] = useState('postmark');
|
||||
|
||||
const { data, loading, error } = useGetSmtpSettingsQuery({
|
||||
variables: { appId: currentProject?.id },
|
||||
...(!isPlatform ? { client: localMimirClient } : {}),
|
||||
});
|
||||
|
||||
const { secure, host, port, user, method, sender } =
|
||||
data?.config?.provider?.smtp || {};
|
||||
const { host } = data?.config?.provider?.smtp || {};
|
||||
|
||||
const form = useForm<Optional<SmtpFormValues, 'password'>>({
|
||||
reValidateMode: 'onSubmit',
|
||||
resolver: yupResolver(smtpValidationSchema),
|
||||
defaultValues: {
|
||||
secure: false,
|
||||
host: '',
|
||||
port: undefined,
|
||||
user: '',
|
||||
method: '',
|
||||
sender: '',
|
||||
},
|
||||
values: {
|
||||
secure: secure || false,
|
||||
host: host || '',
|
||||
port,
|
||||
user: user || '',
|
||||
method: method || '',
|
||||
sender: sender || '',
|
||||
},
|
||||
mode: 'onSubmit',
|
||||
criteriaMode: 'all',
|
||||
});
|
||||
|
||||
const {
|
||||
register,
|
||||
formState: { errors, isDirty, isSubmitting },
|
||||
} = form;
|
||||
|
||||
const [updateConfig] = useUpdateConfigMutation({
|
||||
refetchQueries: [GetSmtpSettingsDocument],
|
||||
...(!isPlatform ? { client: localMimirClient } : {}),
|
||||
});
|
||||
useEffect(() => {
|
||||
setMode(host !== 'postmark' ? 'smtp' : 'postmark');
|
||||
}, [host]);
|
||||
|
||||
if (isPlatform && currentProject?.plan?.isFree) {
|
||||
return (
|
||||
@@ -121,151 +56,29 @@ export default function SMTPSettingsPage() {
|
||||
throw error;
|
||||
}
|
||||
|
||||
const handleEditSMTPSettings = async (values: SmtpFormValues) => {
|
||||
const { password, ...valuesWithoutPassword } = values;
|
||||
|
||||
const updateConfigPromise = updateConfig({
|
||||
variables: {
|
||||
appId: currentProject.id,
|
||||
config: {
|
||||
provider: {
|
||||
smtp: password ? values : valuesWithoutPassword,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await execPromiseWithErrorToast(
|
||||
async () => {
|
||||
await updateConfigPromise;
|
||||
|
||||
if (!isPlatform) {
|
||||
openDialog({
|
||||
title: 'Apply your changes',
|
||||
component: <ApplyLocalSettingsDialog />,
|
||||
props: {
|
||||
PaperProps: {
|
||||
className: 'max-w-2xl',
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
loadingMessage: 'SMTP settings are being updated...',
|
||||
successMessage: 'SMTP settings have been updated successfully.',
|
||||
errorMessage:
|
||||
'An error occurred while trying to update the SMTP settings.',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Container
|
||||
className="grid max-w-5xl grid-flow-row gap-4 bg-transparent"
|
||||
rootClassName="bg-transparent"
|
||||
>
|
||||
<FormProvider {...form}>
|
||||
<Form onSubmit={handleEditSMTPSettings}>
|
||||
<SettingsContainer
|
||||
title="SMTP Settings"
|
||||
description="Configure your SMTP settings to send emails from your email domain."
|
||||
submitButtonText="Save"
|
||||
className="grid grid-cols-9 gap-4"
|
||||
slotProps={{
|
||||
submitButton: {
|
||||
disabled: !isDirty || maintenanceActive,
|
||||
loading: isSubmitting,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
{...register('sender')}
|
||||
id="sender"
|
||||
name="sender"
|
||||
label="From Email"
|
||||
placeholder="noreply@nhost.app"
|
||||
className="lg:col-span-4"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.sender)}
|
||||
helperText={errors.sender?.message}
|
||||
/>
|
||||
<Select
|
||||
slotProps={{
|
||||
popper: { disablePortal: false, className: 'z-[10000]' },
|
||||
}}
|
||||
value={mode}
|
||||
onChange={(_, value) => setMode(value as string)}
|
||||
fullWidth
|
||||
>
|
||||
<Option key="smtp" value="smtp">
|
||||
SMTP
|
||||
</Option>
|
||||
<Option key="postmark" value="postmark">
|
||||
Postmark
|
||||
</Option>
|
||||
</Select>
|
||||
|
||||
<Input
|
||||
{...register('host')}
|
||||
id="host"
|
||||
name="host"
|
||||
label="SMTP Host"
|
||||
className="lg:col-span-4"
|
||||
placeholder="e.g. smtp.sendgrid.net"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.host)}
|
||||
helperText={errors.host?.message}
|
||||
/>
|
||||
|
||||
<Input
|
||||
{...register('port')}
|
||||
id="port"
|
||||
name="port"
|
||||
label="Port"
|
||||
type="number"
|
||||
placeholder="587"
|
||||
className="lg:col-span-1"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.port)}
|
||||
helperText={errors.port?.message}
|
||||
/>
|
||||
|
||||
<Input
|
||||
{...register('user')}
|
||||
id="user"
|
||||
label="SMTP Username"
|
||||
placeholder="SMTP Username"
|
||||
className="lg:col-span-4"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.user)}
|
||||
helperText={errors.user?.message}
|
||||
/>
|
||||
|
||||
<Input
|
||||
{...register('password')}
|
||||
id="password"
|
||||
label="SMTP Password"
|
||||
type="password"
|
||||
placeholder="Enter SMTP password"
|
||||
className="lg:col-span-5"
|
||||
hideEmptyHelperText
|
||||
fullWidth
|
||||
error={Boolean(errors.password)}
|
||||
helperText={errors.password?.message}
|
||||
/>
|
||||
|
||||
<Input
|
||||
{...register('method')}
|
||||
id="method"
|
||||
name="method"
|
||||
label="SMTP Auth Method"
|
||||
placeholder="LOGIN"
|
||||
hideEmptyHelperText
|
||||
className="lg:col-span-4"
|
||||
fullWidth
|
||||
error={Boolean(errors.method)}
|
||||
helperText={errors.method?.message}
|
||||
/>
|
||||
|
||||
<ControlledCheckbox
|
||||
name="secure"
|
||||
id="secure"
|
||||
label="Use SSL"
|
||||
className="lg:col-span-9"
|
||||
/>
|
||||
</SettingsContainer>
|
||||
</Form>
|
||||
</FormProvider>
|
||||
{mode === 'postmark' ? <PostmarkSettings /> : <SMTPSettings />}
|
||||
<DeleteSMTPSettings />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -82,7 +82,11 @@ export default function SelectWorkspaceAndProject() {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
checkConfigFromQuery(router.query?.config as string);
|
||||
const config = router.query?.config as string;
|
||||
|
||||
if (config) {
|
||||
checkConfigFromQuery(router.query?.config as string);
|
||||
}
|
||||
}, [checkConfigFromQuery, router.query]);
|
||||
|
||||
const goToServices = async (project: {
|
||||
@@ -133,7 +137,7 @@ export default function SelectWorkspaceAndProject() {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex w-full justify-center">
|
||||
<div className="flex justify-center w-full">
|
||||
<ActivityIndicator
|
||||
delay={500}
|
||||
label="Loading workspaces and projects..."
|
||||
@@ -156,7 +160,7 @@ export default function SelectWorkspaceAndProject() {
|
||||
/>
|
||||
|
||||
<div>
|
||||
<div className="mb-2 flex w-full">
|
||||
<div className="flex w-full mb-2">
|
||||
<Input
|
||||
placeholder="Search..."
|
||||
onChange={handleFilterChange}
|
||||
@@ -166,11 +170,11 @@ export default function SelectWorkspaceAndProject() {
|
||||
</div>
|
||||
<RetryableErrorBoundary>
|
||||
{projectsToDisplay.length === 0 ? (
|
||||
<Box className="h-import py-2">
|
||||
<Box className="py-2 h-import">
|
||||
<Text variant="subtitle2">No results found.</Text>
|
||||
</Box>
|
||||
) : (
|
||||
<List className="h-import overflow-y-auto">
|
||||
<List className="overflow-y-auto h-import">
|
||||
{projectsToDisplay.map((project, index) => (
|
||||
<Fragment key={project.value}>
|
||||
<ListItem.Root
|
||||
@@ -186,7 +190,7 @@ export default function SelectWorkspaceAndProject() {
|
||||
}
|
||||
>
|
||||
<ListItem.Avatar>
|
||||
<span className="inline-block h-6 w-6 overflow-hidden rounded-md">
|
||||
<span className="inline-block w-6 h-6 overflow-hidden rounded-md">
|
||||
<Image
|
||||
src="/logos/new.svg"
|
||||
alt="Nhost Logo"
|
||||
|
||||
389
dashboard/src/utils/__generated__/graphite.graphql.ts
generated
389
dashboard/src/utils/__generated__/graphite.graphql.ts
generated
@@ -16,9 +16,7 @@ export type Scalars = {
|
||||
bigint: any;
|
||||
bytea: any;
|
||||
citext: any;
|
||||
embedding_model_enum: any;
|
||||
jsonb: any;
|
||||
timestamp: any;
|
||||
timestamptz: any;
|
||||
timestampz: any;
|
||||
uuid: any;
|
||||
@@ -1547,9 +1545,9 @@ export type AuthUserProviders_Bool_Exp = {
|
||||
export enum AuthUserProviders_Constraint {
|
||||
/** unique or primary key constraint on columns "id" */
|
||||
UserProvidersPkey = 'user_providers_pkey',
|
||||
/** unique or primary key constraint on columns "provider_id", "provider_user_id" */
|
||||
/** unique or primary key constraint on columns "provider_user_id", "provider_id" */
|
||||
UserProvidersProviderIdProviderUserIdKey = 'user_providers_provider_id_provider_user_id_key',
|
||||
/** unique or primary key constraint on columns "provider_id", "user_id" */
|
||||
/** unique or primary key constraint on columns "user_id", "provider_id" */
|
||||
UserProvidersUserIdProviderIdKey = 'user_providers_user_id_provider_id_key'
|
||||
}
|
||||
|
||||
@@ -2684,19 +2682,6 @@ export enum Cursor_Ordering {
|
||||
Desc = 'DESC'
|
||||
}
|
||||
|
||||
/** Boolean expression to compare columns of type "embedding_model_enum". All fields are combined with logical 'AND'. */
|
||||
export type Embedding_Model_Enum_Comparison_Exp = {
|
||||
_eq?: InputMaybe<Scalars['embedding_model_enum']>;
|
||||
_gt?: InputMaybe<Scalars['embedding_model_enum']>;
|
||||
_gte?: InputMaybe<Scalars['embedding_model_enum']>;
|
||||
_in?: InputMaybe<Array<Scalars['embedding_model_enum']>>;
|
||||
_is_null?: InputMaybe<Scalars['Boolean']>;
|
||||
_lt?: InputMaybe<Scalars['embedding_model_enum']>;
|
||||
_lte?: InputMaybe<Scalars['embedding_model_enum']>;
|
||||
_neq?: InputMaybe<Scalars['embedding_model_enum']>;
|
||||
_nin?: InputMaybe<Array<Scalars['embedding_model_enum']>>;
|
||||
};
|
||||
|
||||
/** columns and relationships of "storage.files" */
|
||||
export type Files = {
|
||||
__typename?: 'files';
|
||||
@@ -3297,7 +3282,7 @@ export type GraphiteAutoEmbeddingsConfiguration = {
|
||||
createdAt: Scalars['timestamptz'];
|
||||
id: Scalars['uuid'];
|
||||
lastRun?: Maybe<Scalars['timestamptz']>;
|
||||
model: Scalars['embedding_model_enum'];
|
||||
model: Scalars['String'];
|
||||
mutation?: Maybe<Scalars['String']>;
|
||||
name: Scalars['String'];
|
||||
query?: Maybe<Scalars['String']>;
|
||||
@@ -3337,7 +3322,7 @@ export type GraphiteAutoEmbeddingsConfiguration_Bool_Exp = {
|
||||
createdAt?: InputMaybe<Timestamptz_Comparison_Exp>;
|
||||
id?: InputMaybe<Uuid_Comparison_Exp>;
|
||||
lastRun?: InputMaybe<Timestamptz_Comparison_Exp>;
|
||||
model?: InputMaybe<Embedding_Model_Enum_Comparison_Exp>;
|
||||
model?: InputMaybe<String_Comparison_Exp>;
|
||||
mutation?: InputMaybe<String_Comparison_Exp>;
|
||||
name?: InputMaybe<String_Comparison_Exp>;
|
||||
query?: InputMaybe<String_Comparison_Exp>;
|
||||
@@ -3352,7 +3337,7 @@ export enum GraphiteAutoEmbeddingsConfiguration_Constraint {
|
||||
AutoEmbeddingsConfigurationNameKey = 'auto_embeddings_configuration_name_key',
|
||||
/** unique or primary key constraint on columns "id" */
|
||||
AutoEmbeddingsConfigurationPkey = 'auto_embeddings_configuration_pkey',
|
||||
/** unique or primary key constraint on columns "table_name", "column_name", "schema_name" */
|
||||
/** unique or primary key constraint on columns "column_name", "schema_name", "table_name" */
|
||||
AutoEmbeddingsConfigurationSchemaNameTableNameColumnKey = 'auto_embeddings_configuration_schema_name_table_name_column_key'
|
||||
}
|
||||
|
||||
@@ -3362,7 +3347,7 @@ export type GraphiteAutoEmbeddingsConfiguration_Insert_Input = {
|
||||
createdAt?: InputMaybe<Scalars['timestamptz']>;
|
||||
id?: InputMaybe<Scalars['uuid']>;
|
||||
lastRun?: InputMaybe<Scalars['timestamptz']>;
|
||||
model?: InputMaybe<Scalars['embedding_model_enum']>;
|
||||
model?: InputMaybe<Scalars['String']>;
|
||||
mutation?: InputMaybe<Scalars['String']>;
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
query?: InputMaybe<Scalars['String']>;
|
||||
@@ -3378,7 +3363,7 @@ export type GraphiteAutoEmbeddingsConfiguration_Max_Fields = {
|
||||
createdAt?: Maybe<Scalars['timestamptz']>;
|
||||
id?: Maybe<Scalars['uuid']>;
|
||||
lastRun?: Maybe<Scalars['timestamptz']>;
|
||||
model?: Maybe<Scalars['embedding_model_enum']>;
|
||||
model?: Maybe<Scalars['String']>;
|
||||
mutation?: Maybe<Scalars['String']>;
|
||||
name?: Maybe<Scalars['String']>;
|
||||
query?: Maybe<Scalars['String']>;
|
||||
@@ -3394,7 +3379,7 @@ export type GraphiteAutoEmbeddingsConfiguration_Min_Fields = {
|
||||
createdAt?: Maybe<Scalars['timestamptz']>;
|
||||
id?: Maybe<Scalars['uuid']>;
|
||||
lastRun?: Maybe<Scalars['timestamptz']>;
|
||||
model?: Maybe<Scalars['embedding_model_enum']>;
|
||||
model?: Maybe<Scalars['String']>;
|
||||
mutation?: Maybe<Scalars['String']>;
|
||||
name?: Maybe<Scalars['String']>;
|
||||
query?: Maybe<Scalars['String']>;
|
||||
@@ -3471,7 +3456,7 @@ export type GraphiteAutoEmbeddingsConfiguration_Set_Input = {
|
||||
createdAt?: InputMaybe<Scalars['timestamptz']>;
|
||||
id?: InputMaybe<Scalars['uuid']>;
|
||||
lastRun?: InputMaybe<Scalars['timestamptz']>;
|
||||
model?: InputMaybe<Scalars['embedding_model_enum']>;
|
||||
model?: InputMaybe<Scalars['String']>;
|
||||
mutation?: InputMaybe<Scalars['String']>;
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
query?: InputMaybe<Scalars['String']>;
|
||||
@@ -3494,7 +3479,7 @@ export type GraphiteAutoEmbeddingsConfiguration_Stream_Cursor_Value_Input = {
|
||||
createdAt?: InputMaybe<Scalars['timestamptz']>;
|
||||
id?: InputMaybe<Scalars['uuid']>;
|
||||
lastRun?: InputMaybe<Scalars['timestamptz']>;
|
||||
model?: InputMaybe<Scalars['embedding_model_enum']>;
|
||||
model?: InputMaybe<Scalars['String']>;
|
||||
mutation?: InputMaybe<Scalars['String']>;
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
query?: InputMaybe<Scalars['String']>;
|
||||
@@ -3898,10 +3883,6 @@ export type Mutation_Root = {
|
||||
deleteVirus?: Maybe<Virus>;
|
||||
/** delete data from the table: "storage.virus" */
|
||||
deleteViruses?: Maybe<Virus_Mutation_Response>;
|
||||
/** delete data from the table: "todos" */
|
||||
delete_todos?: Maybe<Todos_Mutation_Response>;
|
||||
/** delete single row from the table: "todos" */
|
||||
delete_todos_by_pk?: Maybe<Todos>;
|
||||
graphite?: Maybe<GraphiteMutation>;
|
||||
/** insert a single row into the table: "auth.providers" */
|
||||
insertAuthProvider?: Maybe<AuthProviders>;
|
||||
@@ -3955,10 +3936,6 @@ export type Mutation_Root = {
|
||||
insertVirus?: Maybe<Virus>;
|
||||
/** insert data into the table: "storage.virus" */
|
||||
insertViruses?: Maybe<Virus_Mutation_Response>;
|
||||
/** insert data into the table: "todos" */
|
||||
insert_todos?: Maybe<Todos_Mutation_Response>;
|
||||
/** insert a single row into the table: "todos" */
|
||||
insert_todos_one?: Maybe<Todos>;
|
||||
/** update single row of the table: "auth.providers" */
|
||||
updateAuthProvider?: Maybe<AuthProviders>;
|
||||
/** update single row of the table: "auth.provider_requests" */
|
||||
@@ -4033,12 +4010,6 @@ export type Mutation_Root = {
|
||||
update_buckets_many?: Maybe<Array<Maybe<Buckets_Mutation_Response>>>;
|
||||
/** update multiples rows of table: "storage.files" */
|
||||
update_files_many?: Maybe<Array<Maybe<Files_Mutation_Response>>>;
|
||||
/** update data of the table: "todos" */
|
||||
update_todos?: Maybe<Todos_Mutation_Response>;
|
||||
/** update single row of the table: "todos" */
|
||||
update_todos_by_pk?: Maybe<Todos>;
|
||||
/** update multiples rows of table: "todos" */
|
||||
update_todos_many?: Maybe<Array<Maybe<Todos_Mutation_Response>>>;
|
||||
/** update multiples rows of table: "auth.users" */
|
||||
update_users_many?: Maybe<Array<Maybe<Users_Mutation_Response>>>;
|
||||
/** update multiples rows of table: "storage.virus" */
|
||||
@@ -4304,18 +4275,6 @@ export type Mutation_RootDeleteVirusesArgs = {
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootDelete_TodosArgs = {
|
||||
where: Todos_Bool_Exp;
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootDelete_Todos_By_PkArgs = {
|
||||
id: Scalars['uuid'];
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootInsertAuthProviderArgs = {
|
||||
object: AuthProviders_Insert_Input;
|
||||
@@ -4498,20 +4457,6 @@ export type Mutation_RootInsertVirusesArgs = {
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootInsert_TodosArgs = {
|
||||
objects: Array<Todos_Insert_Input>;
|
||||
on_conflict?: InputMaybe<Todos_On_Conflict>;
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootInsert_Todos_OneArgs = {
|
||||
object: Todos_Insert_Input;
|
||||
on_conflict?: InputMaybe<Todos_On_Conflict>;
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootUpdateAuthProviderArgs = {
|
||||
_set?: InputMaybe<AuthProviders_Set_Input>;
|
||||
@@ -4816,26 +4761,6 @@ export type Mutation_RootUpdate_Files_ManyArgs = {
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootUpdate_TodosArgs = {
|
||||
_set?: InputMaybe<Todos_Set_Input>;
|
||||
where: Todos_Bool_Exp;
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootUpdate_Todos_By_PkArgs = {
|
||||
_set?: InputMaybe<Todos_Set_Input>;
|
||||
pk_columns: Todos_Pk_Columns_Input;
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootUpdate_Todos_ManyArgs = {
|
||||
updates: Array<Todos_Updates>;
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootUpdate_Users_ManyArgs = {
|
||||
updates: Array<Users_Updates>;
|
||||
@@ -4944,12 +4869,6 @@ export type Query_Root = {
|
||||
graphiteAutoEmbeddingsConfigurationAggregate: GraphiteAutoEmbeddingsConfiguration_Aggregate;
|
||||
/** fetch data from the table: "graphite.auto_embeddings_configuration" */
|
||||
graphiteAutoEmbeddingsConfigurations: Array<GraphiteAutoEmbeddingsConfiguration>;
|
||||
/** fetch data from the table: "todos" */
|
||||
todos: Array<Todos>;
|
||||
/** fetch aggregated fields from the table: "todos" */
|
||||
todos_aggregate: Todos_Aggregate;
|
||||
/** fetch data from the table: "todos" using primary key columns */
|
||||
todos_by_pk?: Maybe<Todos>;
|
||||
/** fetch data from the table: "auth.users" using primary key columns */
|
||||
user?: Maybe<Users>;
|
||||
/** fetch data from the table: "auth.users" */
|
||||
@@ -5264,29 +5183,6 @@ export type Query_RootGraphiteAutoEmbeddingsConfigurationsArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type Query_RootTodosArgs = {
|
||||
distinct_on?: InputMaybe<Array<Todos_Select_Column>>;
|
||||
limit?: InputMaybe<Scalars['Int']>;
|
||||
offset?: InputMaybe<Scalars['Int']>;
|
||||
order_by?: InputMaybe<Array<Todos_Order_By>>;
|
||||
where?: InputMaybe<Todos_Bool_Exp>;
|
||||
};
|
||||
|
||||
|
||||
export type Query_RootTodos_AggregateArgs = {
|
||||
distinct_on?: InputMaybe<Array<Todos_Select_Column>>;
|
||||
limit?: InputMaybe<Scalars['Int']>;
|
||||
offset?: InputMaybe<Scalars['Int']>;
|
||||
order_by?: InputMaybe<Array<Todos_Order_By>>;
|
||||
where?: InputMaybe<Todos_Bool_Exp>;
|
||||
};
|
||||
|
||||
|
||||
export type Query_RootTodos_By_PkArgs = {
|
||||
id: Scalars['uuid'];
|
||||
};
|
||||
|
||||
|
||||
export type Query_RootUserArgs = {
|
||||
id: Scalars['uuid'];
|
||||
};
|
||||
@@ -5438,14 +5334,6 @@ export type Subscription_Root = {
|
||||
graphiteAutoEmbeddingsConfigurationStream: Array<GraphiteAutoEmbeddingsConfiguration>;
|
||||
/** fetch data from the table: "graphite.auto_embeddings_configuration" */
|
||||
graphiteAutoEmbeddingsConfigurations: Array<GraphiteAutoEmbeddingsConfiguration>;
|
||||
/** fetch data from the table: "todos" */
|
||||
todos: Array<Todos>;
|
||||
/** fetch aggregated fields from the table: "todos" */
|
||||
todos_aggregate: Todos_Aggregate;
|
||||
/** fetch data from the table: "todos" using primary key columns */
|
||||
todos_by_pk?: Maybe<Todos>;
|
||||
/** fetch data from the table in a streaming manner: "todos" */
|
||||
todos_stream: Array<Todos>;
|
||||
/** fetch data from the table: "auth.users" using primary key columns */
|
||||
user?: Maybe<Users>;
|
||||
/** fetch data from the table: "auth.users" */
|
||||
@@ -5855,36 +5743,6 @@ export type Subscription_RootGraphiteAutoEmbeddingsConfigurationsArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type Subscription_RootTodosArgs = {
|
||||
distinct_on?: InputMaybe<Array<Todos_Select_Column>>;
|
||||
limit?: InputMaybe<Scalars['Int']>;
|
||||
offset?: InputMaybe<Scalars['Int']>;
|
||||
order_by?: InputMaybe<Array<Todos_Order_By>>;
|
||||
where?: InputMaybe<Todos_Bool_Exp>;
|
||||
};
|
||||
|
||||
|
||||
export type Subscription_RootTodos_AggregateArgs = {
|
||||
distinct_on?: InputMaybe<Array<Todos_Select_Column>>;
|
||||
limit?: InputMaybe<Scalars['Int']>;
|
||||
offset?: InputMaybe<Scalars['Int']>;
|
||||
order_by?: InputMaybe<Array<Todos_Order_By>>;
|
||||
where?: InputMaybe<Todos_Bool_Exp>;
|
||||
};
|
||||
|
||||
|
||||
export type Subscription_RootTodos_By_PkArgs = {
|
||||
id: Scalars['uuid'];
|
||||
};
|
||||
|
||||
|
||||
export type Subscription_RootTodos_StreamArgs = {
|
||||
batch_size: Scalars['Int'];
|
||||
cursor: Array<InputMaybe<Todos_Stream_Cursor_Input>>;
|
||||
where?: InputMaybe<Todos_Bool_Exp>;
|
||||
};
|
||||
|
||||
|
||||
export type Subscription_RootUserArgs = {
|
||||
id: Scalars['uuid'];
|
||||
};
|
||||
@@ -5944,19 +5802,6 @@ export type Subscription_RootVirusesAggregateArgs = {
|
||||
where?: InputMaybe<Virus_Bool_Exp>;
|
||||
};
|
||||
|
||||
/** Boolean expression to compare columns of type "timestamp". All fields are combined with logical 'AND'. */
|
||||
export type Timestamp_Comparison_Exp = {
|
||||
_eq?: InputMaybe<Scalars['timestamp']>;
|
||||
_gt?: InputMaybe<Scalars['timestamp']>;
|
||||
_gte?: InputMaybe<Scalars['timestamp']>;
|
||||
_in?: InputMaybe<Array<Scalars['timestamp']>>;
|
||||
_is_null?: InputMaybe<Scalars['Boolean']>;
|
||||
_lt?: InputMaybe<Scalars['timestamp']>;
|
||||
_lte?: InputMaybe<Scalars['timestamp']>;
|
||||
_neq?: InputMaybe<Scalars['timestamp']>;
|
||||
_nin?: InputMaybe<Array<Scalars['timestamp']>>;
|
||||
};
|
||||
|
||||
/** Boolean expression to compare columns of type "timestamptz". All fields are combined with logical 'AND'. */
|
||||
export type Timestamptz_Comparison_Exp = {
|
||||
_eq?: InputMaybe<Scalars['timestamptz']>;
|
||||
@@ -5970,208 +5815,6 @@ export type Timestamptz_Comparison_Exp = {
|
||||
_nin?: InputMaybe<Array<Scalars['timestamptz']>>;
|
||||
};
|
||||
|
||||
/** columns and relationships of "todos" */
|
||||
export type Todos = {
|
||||
__typename?: 'todos';
|
||||
/** An object relationship */
|
||||
attachment?: Maybe<Files>;
|
||||
createdAt: Scalars['timestamp'];
|
||||
done: Scalars['Boolean'];
|
||||
file_id?: Maybe<Scalars['uuid']>;
|
||||
id: Scalars['uuid'];
|
||||
title: Scalars['String'];
|
||||
updatedAt: Scalars['timestamptz'];
|
||||
/** An object relationship */
|
||||
user: Users;
|
||||
user_id: Scalars['uuid'];
|
||||
};
|
||||
|
||||
/** aggregated selection of "todos" */
|
||||
export type Todos_Aggregate = {
|
||||
__typename?: 'todos_aggregate';
|
||||
aggregate?: Maybe<Todos_Aggregate_Fields>;
|
||||
nodes: Array<Todos>;
|
||||
};
|
||||
|
||||
/** aggregate fields of "todos" */
|
||||
export type Todos_Aggregate_Fields = {
|
||||
__typename?: 'todos_aggregate_fields';
|
||||
count: Scalars['Int'];
|
||||
max?: Maybe<Todos_Max_Fields>;
|
||||
min?: Maybe<Todos_Min_Fields>;
|
||||
};
|
||||
|
||||
|
||||
/** aggregate fields of "todos" */
|
||||
export type Todos_Aggregate_FieldsCountArgs = {
|
||||
columns?: InputMaybe<Array<Todos_Select_Column>>;
|
||||
distinct?: InputMaybe<Scalars['Boolean']>;
|
||||
};
|
||||
|
||||
/** Boolean expression to filter rows from the table "todos". All fields are combined with a logical 'AND'. */
|
||||
export type Todos_Bool_Exp = {
|
||||
_and?: InputMaybe<Array<Todos_Bool_Exp>>;
|
||||
_not?: InputMaybe<Todos_Bool_Exp>;
|
||||
_or?: InputMaybe<Array<Todos_Bool_Exp>>;
|
||||
attachment?: InputMaybe<Files_Bool_Exp>;
|
||||
createdAt?: InputMaybe<Timestamp_Comparison_Exp>;
|
||||
done?: InputMaybe<Boolean_Comparison_Exp>;
|
||||
file_id?: InputMaybe<Uuid_Comparison_Exp>;
|
||||
id?: InputMaybe<Uuid_Comparison_Exp>;
|
||||
title?: InputMaybe<String_Comparison_Exp>;
|
||||
updatedAt?: InputMaybe<Timestamptz_Comparison_Exp>;
|
||||
user?: InputMaybe<Users_Bool_Exp>;
|
||||
user_id?: InputMaybe<Uuid_Comparison_Exp>;
|
||||
};
|
||||
|
||||
/** unique or primary key constraints on table "todos" */
|
||||
export enum Todos_Constraint {
|
||||
/** unique or primary key constraint on columns "id" */
|
||||
TodosPkey = 'todos_pkey'
|
||||
}
|
||||
|
||||
/** input type for inserting data into table "todos" */
|
||||
export type Todos_Insert_Input = {
|
||||
attachment?: InputMaybe<Files_Obj_Rel_Insert_Input>;
|
||||
createdAt?: InputMaybe<Scalars['timestamp']>;
|
||||
done?: InputMaybe<Scalars['Boolean']>;
|
||||
file_id?: InputMaybe<Scalars['uuid']>;
|
||||
id?: InputMaybe<Scalars['uuid']>;
|
||||
title?: InputMaybe<Scalars['String']>;
|
||||
updatedAt?: InputMaybe<Scalars['timestamptz']>;
|
||||
user?: InputMaybe<Users_Obj_Rel_Insert_Input>;
|
||||
user_id?: InputMaybe<Scalars['uuid']>;
|
||||
};
|
||||
|
||||
/** aggregate max on columns */
|
||||
export type Todos_Max_Fields = {
|
||||
__typename?: 'todos_max_fields';
|
||||
createdAt?: Maybe<Scalars['timestamp']>;
|
||||
file_id?: Maybe<Scalars['uuid']>;
|
||||
id?: Maybe<Scalars['uuid']>;
|
||||
title?: Maybe<Scalars['String']>;
|
||||
updatedAt?: Maybe<Scalars['timestamptz']>;
|
||||
user_id?: Maybe<Scalars['uuid']>;
|
||||
};
|
||||
|
||||
/** aggregate min on columns */
|
||||
export type Todos_Min_Fields = {
|
||||
__typename?: 'todos_min_fields';
|
||||
createdAt?: Maybe<Scalars['timestamp']>;
|
||||
file_id?: Maybe<Scalars['uuid']>;
|
||||
id?: Maybe<Scalars['uuid']>;
|
||||
title?: Maybe<Scalars['String']>;
|
||||
updatedAt?: Maybe<Scalars['timestamptz']>;
|
||||
user_id?: Maybe<Scalars['uuid']>;
|
||||
};
|
||||
|
||||
/** response of any mutation on the table "todos" */
|
||||
export type Todos_Mutation_Response = {
|
||||
__typename?: 'todos_mutation_response';
|
||||
/** number of rows affected by the mutation */
|
||||
affected_rows: Scalars['Int'];
|
||||
/** data from the rows affected by the mutation */
|
||||
returning: Array<Todos>;
|
||||
};
|
||||
|
||||
/** on_conflict condition type for table "todos" */
|
||||
export type Todos_On_Conflict = {
|
||||
constraint: Todos_Constraint;
|
||||
update_columns?: Array<Todos_Update_Column>;
|
||||
where?: InputMaybe<Todos_Bool_Exp>;
|
||||
};
|
||||
|
||||
/** Ordering options when selecting data from "todos". */
|
||||
export type Todos_Order_By = {
|
||||
attachment?: InputMaybe<Files_Order_By>;
|
||||
createdAt?: InputMaybe<Order_By>;
|
||||
done?: InputMaybe<Order_By>;
|
||||
file_id?: InputMaybe<Order_By>;
|
||||
id?: InputMaybe<Order_By>;
|
||||
title?: InputMaybe<Order_By>;
|
||||
updatedAt?: InputMaybe<Order_By>;
|
||||
user?: InputMaybe<Users_Order_By>;
|
||||
user_id?: InputMaybe<Order_By>;
|
||||
};
|
||||
|
||||
/** primary key columns input for table: todos */
|
||||
export type Todos_Pk_Columns_Input = {
|
||||
id: Scalars['uuid'];
|
||||
};
|
||||
|
||||
/** select columns of table "todos" */
|
||||
export enum Todos_Select_Column {
|
||||
/** column name */
|
||||
CreatedAt = 'createdAt',
|
||||
/** column name */
|
||||
Done = 'done',
|
||||
/** column name */
|
||||
FileId = 'file_id',
|
||||
/** column name */
|
||||
Id = 'id',
|
||||
/** column name */
|
||||
Title = 'title',
|
||||
/** column name */
|
||||
UpdatedAt = 'updatedAt',
|
||||
/** column name */
|
||||
UserId = 'user_id'
|
||||
}
|
||||
|
||||
/** input type for updating data in table "todos" */
|
||||
export type Todos_Set_Input = {
|
||||
createdAt?: InputMaybe<Scalars['timestamp']>;
|
||||
done?: InputMaybe<Scalars['Boolean']>;
|
||||
file_id?: InputMaybe<Scalars['uuid']>;
|
||||
id?: InputMaybe<Scalars['uuid']>;
|
||||
title?: InputMaybe<Scalars['String']>;
|
||||
updatedAt?: InputMaybe<Scalars['timestamptz']>;
|
||||
user_id?: InputMaybe<Scalars['uuid']>;
|
||||
};
|
||||
|
||||
/** Streaming cursor of the table "todos" */
|
||||
export type Todos_Stream_Cursor_Input = {
|
||||
/** Stream column input with initial value */
|
||||
initial_value: Todos_Stream_Cursor_Value_Input;
|
||||
/** cursor ordering */
|
||||
ordering?: InputMaybe<Cursor_Ordering>;
|
||||
};
|
||||
|
||||
/** Initial value of the column from where the streaming should start */
|
||||
export type Todos_Stream_Cursor_Value_Input = {
|
||||
createdAt?: InputMaybe<Scalars['timestamp']>;
|
||||
done?: InputMaybe<Scalars['Boolean']>;
|
||||
file_id?: InputMaybe<Scalars['uuid']>;
|
||||
id?: InputMaybe<Scalars['uuid']>;
|
||||
title?: InputMaybe<Scalars['String']>;
|
||||
updatedAt?: InputMaybe<Scalars['timestamptz']>;
|
||||
user_id?: InputMaybe<Scalars['uuid']>;
|
||||
};
|
||||
|
||||
/** update columns of table "todos" */
|
||||
export enum Todos_Update_Column {
|
||||
/** column name */
|
||||
CreatedAt = 'createdAt',
|
||||
/** column name */
|
||||
Done = 'done',
|
||||
/** column name */
|
||||
FileId = 'file_id',
|
||||
/** column name */
|
||||
Id = 'id',
|
||||
/** column name */
|
||||
Title = 'title',
|
||||
/** column name */
|
||||
UpdatedAt = 'updatedAt',
|
||||
/** column name */
|
||||
UserId = 'user_id'
|
||||
}
|
||||
|
||||
export type Todos_Updates = {
|
||||
/** sets the columns of the filtered rows to the given values */
|
||||
_set?: InputMaybe<Todos_Set_Input>;
|
||||
/** filter the rows which have to be updated */
|
||||
where: Todos_Bool_Exp;
|
||||
};
|
||||
|
||||
/** User account information. Don't modify its structure as Hasura Auth relies on it to function properly. */
|
||||
export type Users = {
|
||||
__typename?: 'users';
|
||||
@@ -7150,11 +6793,11 @@ export type GetGraphiteAutoEmbeddingsConfigurationsQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type GetGraphiteAutoEmbeddingsConfigurationsQuery = { __typename?: 'query_root', graphiteAutoEmbeddingsConfigurations: Array<{ __typename?: 'graphiteAutoEmbeddingsConfiguration', id: any, name: string, model: any, schemaName: string, tableName: string, columnName: string, query?: string | null, mutation?: string | null, createdAt: any, updatedAt: any }>, graphiteAutoEmbeddingsConfigurationAggregate: { __typename?: 'graphiteAutoEmbeddingsConfiguration_aggregate', aggregate?: { __typename?: 'graphiteAutoEmbeddingsConfiguration_aggregate_fields', count: number } | null } };
|
||||
export type GetGraphiteAutoEmbeddingsConfigurationsQuery = { __typename?: 'query_root', graphiteAutoEmbeddingsConfigurations: Array<{ __typename?: 'graphiteAutoEmbeddingsConfiguration', id: any, name: string, model: string, schemaName: string, tableName: string, columnName: string, query?: string | null, mutation?: string | null, createdAt: any, updatedAt: any }>, graphiteAutoEmbeddingsConfigurationAggregate: { __typename?: 'graphiteAutoEmbeddingsConfiguration_aggregate', aggregate?: { __typename?: 'graphiteAutoEmbeddingsConfiguration_aggregate_fields', count: number } | null } };
|
||||
|
||||
export type InsertGraphiteAutoEmbeddingsConfigurationMutationVariables = Exact<{
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
model?: InputMaybe<Scalars['embedding_model_enum']>;
|
||||
model?: InputMaybe<Scalars['String']>;
|
||||
schemaName?: InputMaybe<Scalars['String']>;
|
||||
tableName?: InputMaybe<Scalars['String']>;
|
||||
columnName?: InputMaybe<Scalars['String']>;
|
||||
@@ -7168,7 +6811,7 @@ export type InsertGraphiteAutoEmbeddingsConfigurationMutation = { __typename?: '
|
||||
export type UpdateGraphiteAutoEmbeddingsConfigurationMutationVariables = Exact<{
|
||||
id: Scalars['uuid'];
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
model?: InputMaybe<Scalars['embedding_model_enum']>;
|
||||
model?: InputMaybe<Scalars['String']>;
|
||||
schemaName?: InputMaybe<Scalars['String']>;
|
||||
tableName?: InputMaybe<Scalars['String']>;
|
||||
columnName?: InputMaybe<Scalars['String']>;
|
||||
@@ -7177,7 +6820,7 @@ export type UpdateGraphiteAutoEmbeddingsConfigurationMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdateGraphiteAutoEmbeddingsConfigurationMutation = { __typename?: 'mutation_root', updateGraphiteAutoEmbeddingsConfiguration?: { __typename?: 'graphiteAutoEmbeddingsConfiguration', id: any, name: string, model: any, schemaName: string, tableName: string, columnName: string, query?: string | null, mutation?: string | null } | null };
|
||||
export type UpdateGraphiteAutoEmbeddingsConfigurationMutation = { __typename?: 'mutation_root', updateGraphiteAutoEmbeddingsConfiguration?: { __typename?: 'graphiteAutoEmbeddingsConfiguration', id: any, name: string, model: string, schemaName: string, tableName: string, columnName: string, query?: string | null, mutation?: string | null } | null };
|
||||
|
||||
export type SendDevMessageMutationVariables = Exact<{
|
||||
sessionId: Scalars['String'];
|
||||
@@ -7489,7 +7132,7 @@ export function refetchGetGraphiteAutoEmbeddingsConfigurationsQuery(variables: G
|
||||
return { query: GetGraphiteAutoEmbeddingsConfigurationsDocument, variables: variables }
|
||||
}
|
||||
export const InsertGraphiteAutoEmbeddingsConfigurationDocument = gql`
|
||||
mutation insertGraphiteAutoEmbeddingsConfiguration($name: String, $model: embedding_model_enum, $schemaName: String, $tableName: String, $columnName: String, $query: String, $mutation: String) {
|
||||
mutation insertGraphiteAutoEmbeddingsConfiguration($name: String, $model: String, $schemaName: String, $tableName: String, $columnName: String, $query: String, $mutation: String) {
|
||||
insertGraphiteAutoEmbeddingsConfiguration(
|
||||
object: {name: $name, model: $model, schemaName: $schemaName, tableName: $tableName, columnName: $columnName, query: $query, mutation: $mutation}
|
||||
) {
|
||||
@@ -7530,7 +7173,7 @@ export type InsertGraphiteAutoEmbeddingsConfigurationMutationHookResult = Return
|
||||
export type InsertGraphiteAutoEmbeddingsConfigurationMutationResult = Apollo.MutationResult<InsertGraphiteAutoEmbeddingsConfigurationMutation>;
|
||||
export type InsertGraphiteAutoEmbeddingsConfigurationMutationOptions = Apollo.BaseMutationOptions<InsertGraphiteAutoEmbeddingsConfigurationMutation, InsertGraphiteAutoEmbeddingsConfigurationMutationVariables>;
|
||||
export const UpdateGraphiteAutoEmbeddingsConfigurationDocument = gql`
|
||||
mutation updateGraphiteAutoEmbeddingsConfiguration($id: uuid!, $name: String, $model: embedding_model_enum, $schemaName: String, $tableName: String, $columnName: String, $query: String, $mutation: String) {
|
||||
mutation updateGraphiteAutoEmbeddingsConfiguration($id: uuid!, $name: String, $model: String, $schemaName: String, $tableName: String, $columnName: String, $query: String, $mutation: String) {
|
||||
updateGraphiteAutoEmbeddingsConfiguration(
|
||||
pk_columns: {id: $id}
|
||||
_set: {name: $name, model: $model, schemaName: $schemaName, tableName: $tableName, columnName: $columnName, query: $query, mutation: $mutation}
|
||||
|
||||
91
dashboard/src/utils/__generated__/graphql.ts
generated
91
dashboard/src/utils/__generated__/graphql.ts
generated
@@ -1804,6 +1804,7 @@ export type ConfigPostgresInsertInput = {
|
||||
export type ConfigPostgresResources = {
|
||||
__typename?: 'ConfigPostgresResources';
|
||||
compute?: Maybe<ConfigResourcesCompute>;
|
||||
enablePublicAccess?: Maybe<Scalars['Boolean']>;
|
||||
networking?: Maybe<ConfigNetworking>;
|
||||
/** Number of replicas for a service */
|
||||
replicas?: Maybe<Scalars['ConfigUint8']>;
|
||||
@@ -1815,6 +1816,7 @@ export type ConfigPostgresResourcesComparisonExp = {
|
||||
_not?: InputMaybe<ConfigPostgresResourcesComparisonExp>;
|
||||
_or?: InputMaybe<Array<ConfigPostgresResourcesComparisonExp>>;
|
||||
compute?: InputMaybe<ConfigResourcesComputeComparisonExp>;
|
||||
enablePublicAccess?: InputMaybe<ConfigBooleanComparisonExp>;
|
||||
networking?: InputMaybe<ConfigNetworkingComparisonExp>;
|
||||
replicas?: InputMaybe<ConfigUint8ComparisonExp>;
|
||||
storage?: InputMaybe<ConfigPostgresStorageComparisonExp>;
|
||||
@@ -1822,6 +1824,7 @@ export type ConfigPostgresResourcesComparisonExp = {
|
||||
|
||||
export type ConfigPostgresResourcesInsertInput = {
|
||||
compute?: InputMaybe<ConfigResourcesComputeInsertInput>;
|
||||
enablePublicAccess?: InputMaybe<Scalars['Boolean']>;
|
||||
networking?: InputMaybe<ConfigNetworkingInsertInput>;
|
||||
replicas?: InputMaybe<Scalars['ConfigUint8']>;
|
||||
storage?: InputMaybe<ConfigPostgresStorageInsertInput>;
|
||||
@@ -1829,6 +1832,7 @@ export type ConfigPostgresResourcesInsertInput = {
|
||||
|
||||
export type ConfigPostgresResourcesUpdateInput = {
|
||||
compute?: InputMaybe<ConfigResourcesComputeUpdateInput>;
|
||||
enablePublicAccess?: InputMaybe<Scalars['Boolean']>;
|
||||
networking?: InputMaybe<ConfigNetworkingUpdateInput>;
|
||||
replicas?: InputMaybe<Scalars['ConfigUint8']>;
|
||||
storage?: InputMaybe<ConfigPostgresStorageUpdateInput>;
|
||||
@@ -2524,7 +2528,9 @@ export type ConfigSystemConfigPostgres = {
|
||||
__typename?: 'ConfigSystemConfigPostgres';
|
||||
connectionString: ConfigSystemConfigPostgresConnectionString;
|
||||
database: Scalars['String'];
|
||||
disk?: Maybe<ConfigSystemConfigPostgresDisk>;
|
||||
enabled?: Maybe<Scalars['Boolean']>;
|
||||
majorVersion?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type ConfigSystemConfigPostgresComparisonExp = {
|
||||
@@ -2533,7 +2539,9 @@ export type ConfigSystemConfigPostgresComparisonExp = {
|
||||
_or?: InputMaybe<Array<ConfigSystemConfigPostgresComparisonExp>>;
|
||||
connectionString?: InputMaybe<ConfigSystemConfigPostgresConnectionStringComparisonExp>;
|
||||
database?: InputMaybe<ConfigStringComparisonExp>;
|
||||
disk?: InputMaybe<ConfigSystemConfigPostgresDiskComparisonExp>;
|
||||
enabled?: InputMaybe<ConfigBooleanComparisonExp>;
|
||||
majorVersion?: InputMaybe<ConfigStringComparisonExp>;
|
||||
};
|
||||
|
||||
export type ConfigSystemConfigPostgresConnectionString = {
|
||||
@@ -2568,16 +2576,44 @@ export type ConfigSystemConfigPostgresConnectionStringUpdateInput = {
|
||||
storage?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type ConfigSystemConfigPostgresDisk = {
|
||||
__typename?: 'ConfigSystemConfigPostgresDisk';
|
||||
iops?: Maybe<Scalars['ConfigUint32']>;
|
||||
tput?: Maybe<Scalars['ConfigUint32']>;
|
||||
};
|
||||
|
||||
export type ConfigSystemConfigPostgresDiskComparisonExp = {
|
||||
_and?: InputMaybe<Array<ConfigSystemConfigPostgresDiskComparisonExp>>;
|
||||
_not?: InputMaybe<ConfigSystemConfigPostgresDiskComparisonExp>;
|
||||
_or?: InputMaybe<Array<ConfigSystemConfigPostgresDiskComparisonExp>>;
|
||||
iops?: InputMaybe<ConfigUint32ComparisonExp>;
|
||||
tput?: InputMaybe<ConfigUint32ComparisonExp>;
|
||||
};
|
||||
|
||||
export type ConfigSystemConfigPostgresDiskInsertInput = {
|
||||
iops?: InputMaybe<Scalars['ConfigUint32']>;
|
||||
tput?: InputMaybe<Scalars['ConfigUint32']>;
|
||||
};
|
||||
|
||||
export type ConfigSystemConfigPostgresDiskUpdateInput = {
|
||||
iops?: InputMaybe<Scalars['ConfigUint32']>;
|
||||
tput?: InputMaybe<Scalars['ConfigUint32']>;
|
||||
};
|
||||
|
||||
export type ConfigSystemConfigPostgresInsertInput = {
|
||||
connectionString: ConfigSystemConfigPostgresConnectionStringInsertInput;
|
||||
database: Scalars['String'];
|
||||
disk?: InputMaybe<ConfigSystemConfigPostgresDiskInsertInput>;
|
||||
enabled?: InputMaybe<Scalars['Boolean']>;
|
||||
majorVersion?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type ConfigSystemConfigPostgresUpdateInput = {
|
||||
connectionString?: InputMaybe<ConfigSystemConfigPostgresConnectionStringUpdateInput>;
|
||||
database?: InputMaybe<Scalars['String']>;
|
||||
disk?: InputMaybe<ConfigSystemConfigPostgresDiskUpdateInput>;
|
||||
enabled?: InputMaybe<Scalars['Boolean']>;
|
||||
majorVersion?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type ConfigSystemConfigUpdateInput = {
|
||||
@@ -2659,14 +2695,6 @@ export type Metrics = {
|
||||
value: Scalars['float64'];
|
||||
};
|
||||
|
||||
export type StatsDailyLiveFreeApps = {
|
||||
__typename?: 'StatsDailyLiveFreeApps';
|
||||
avg: Scalars['Int'];
|
||||
max: Scalars['Int'];
|
||||
min: Scalars['Int'];
|
||||
raw: Array<Scalars['Int']>;
|
||||
};
|
||||
|
||||
export type StatsLiveApps = {
|
||||
__typename?: 'StatsLiveApps';
|
||||
appID: Array<Scalars['uuid']>;
|
||||
@@ -11798,6 +11826,7 @@ export type Mutation_Root = {
|
||||
billingUpdatePersistentVolume: Scalars['Boolean'];
|
||||
billingUpdateReports: Scalars['Boolean'];
|
||||
billingUploadReports: Scalars['Boolean'];
|
||||
changeDatabaseVersion: Scalars['Boolean'];
|
||||
/** delete single row from the table: "apps" */
|
||||
deleteApp?: Maybe<Apps>;
|
||||
/** delete single row from the table: "app_states" */
|
||||
@@ -12483,6 +12512,14 @@ export type Mutation_RootBillingUpdateReportsArgs = {
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootChangeDatabaseVersionArgs = {
|
||||
appID: Scalars['uuid'];
|
||||
force?: InputMaybe<Scalars['Boolean']>;
|
||||
version: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
/** mutation root */
|
||||
export type Mutation_RootDeleteAppArgs = {
|
||||
id: Scalars['uuid'];
|
||||
@@ -15988,12 +16025,6 @@ export type Query_Root = {
|
||||
softwareVersions: Array<Software_Versions>;
|
||||
/** fetch aggregated fields from the table: "software_versions" */
|
||||
softwareVersionsAggregate: Software_Versions_Aggregate;
|
||||
/**
|
||||
* Returns the per-day number of free live apps in the given time range, as well as the min, max and avg.
|
||||
*
|
||||
* Requests that returned a 4xx or 5xx status code are not counted as live traffic.
|
||||
*/
|
||||
statsDailyLiveFreeApps: StatsDailyLiveFreeApps;
|
||||
/**
|
||||
* Returns lists of apps that have some live traffic in the give time range.
|
||||
* From defaults to 24 hours ago and to defaults to now.
|
||||
@@ -16003,6 +16034,8 @@ export type Query_Root = {
|
||||
statsLiveApps: StatsLiveApps;
|
||||
systemConfig?: Maybe<ConfigSystemConfig>;
|
||||
systemConfigs: Array<ConfigAppSystemConfig>;
|
||||
/** Returns system logs for a given application */
|
||||
systemLogs: Array<Log>;
|
||||
/** fetch data from the table: "auth.users" using primary key columns */
|
||||
user?: Maybe<Users>;
|
||||
/** fetch data from the table: "auth.users" */
|
||||
@@ -17051,12 +17084,6 @@ export type Query_RootSoftwareVersionsAggregateArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type Query_RootStatsDailyLiveFreeAppsArgs = {
|
||||
from?: InputMaybe<Scalars['Timestamp']>;
|
||||
to?: InputMaybe<Scalars['Timestamp']>;
|
||||
};
|
||||
|
||||
|
||||
export type Query_RootStatsLiveAppsArgs = {
|
||||
from?: InputMaybe<Scalars['Timestamp']>;
|
||||
to?: InputMaybe<Scalars['Timestamp']>;
|
||||
@@ -17073,6 +17100,14 @@ export type Query_RootSystemConfigsArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type Query_RootSystemLogsArgs = {
|
||||
action: Scalars['String'];
|
||||
appID: Scalars['String'];
|
||||
from?: InputMaybe<Scalars['Timestamp']>;
|
||||
to?: InputMaybe<Scalars['Timestamp']>;
|
||||
};
|
||||
|
||||
|
||||
export type Query_RootUserArgs = {
|
||||
id: Scalars['uuid'];
|
||||
};
|
||||
@@ -22662,7 +22697,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', 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?: 'ConfigPostgresStorage', capacity: any } | null } | null } | null } | null };
|
||||
|
||||
export type ResetDatabasePasswordMutationVariables = Exact<{
|
||||
appId: Scalars['String'];
|
||||
@@ -22886,7 +22921,7 @@ export type GetSmtpSettingsQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type GetSmtpSettingsQuery = { __typename?: 'query_root', config?: { __typename: 'ConfigConfig', id: 'ConfigConfig', provider?: { __typename: 'ConfigProvider', id: 'ConfigProvider', smtp?: { __typename?: 'ConfigSmtp', host: string, method: string, port: any, secure: boolean, sender: string, user: string } | null } | null } | null };
|
||||
export type GetSmtpSettingsQuery = { __typename?: 'query_root', config?: { __typename: 'ConfigConfig', id: 'ConfigConfig', provider?: { __typename: 'ConfigProvider', id: 'ConfigProvider', smtp?: { __typename?: 'ConfigSmtp', host: string, method: string, port: any, secure: boolean, sender: string, user: string, password: string } | null } | null } | null };
|
||||
|
||||
export type UpdateConfigMutationVariables = Exact<{
|
||||
appId: Scalars['uuid'];
|
||||
@@ -22894,7 +22929,7 @@ export type UpdateConfigMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdateConfigMutation = { __typename?: 'mutation_root', updateConfig: { __typename?: 'ConfigConfig', id: 'ConfigConfig', postgres?: { __typename?: 'ConfigPostgres', resources?: { __typename?: 'ConfigPostgresResources', 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?: '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 UnpauseApplicationMutationVariables = Exact<{
|
||||
appId: Scalars['uuid'];
|
||||
@@ -23098,7 +23133,7 @@ export type GetRemoteAppMetricsQueryVariables = Exact<{ [key: string]: never; }>
|
||||
|
||||
export type GetRemoteAppMetricsQuery = { __typename?: 'query_root', filesAggregate: { __typename?: 'files_aggregate', aggregate?: { __typename?: 'files_aggregate_fields', count: number, sum?: { __typename?: 'files_sum_fields', size?: number | null } | null } | null }, usersAggregate: { __typename?: 'users_aggregate', aggregate?: { __typename?: 'users_aggregate_fields', count: number } | null } };
|
||||
|
||||
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, roles: Array<{ __typename?: 'authUserRoles', id: any, role: string }>, userProviders: Array<{ __typename?: 'authUserProviders', id: any, providerId: string }> };
|
||||
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<{
|
||||
where: Users_Bool_Exp;
|
||||
@@ -23107,7 +23142,7 @@ export type RemoteAppGetUsersQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
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, 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 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 RemoteAppGetUsersCustomQueryVariables = Exact<{
|
||||
where: Users_Bool_Exp;
|
||||
@@ -23124,7 +23159,7 @@ export type RemoteAppGetUsersWholeQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type RemoteAppGetUsersWholeQuery = { __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, roles: Array<{ __typename?: 'authUserRoles', id: any, role: string }>, userProviders: Array<{ __typename?: 'authUserProviders', id: any, providerId: string }> }>, usersAggregate: { __typename?: 'users_aggregate', aggregate?: { __typename?: 'users_aggregate_fields', count: number } | null } };
|
||||
export type RemoteAppGetUsersWholeQuery = { __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 }> }>, usersAggregate: { __typename?: 'users_aggregate', aggregate?: { __typename?: 'users_aggregate_fields', count: number } | null } };
|
||||
|
||||
export type TotalUsersQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -23623,6 +23658,7 @@ export const RemoteAppGetUsersFragmentDoc = gql`
|
||||
defaultRole
|
||||
lastSeen
|
||||
locale
|
||||
metadata
|
||||
roles {
|
||||
id
|
||||
role
|
||||
@@ -24036,6 +24072,7 @@ export const GetPostgresSettingsDocument = gql`
|
||||
storage {
|
||||
capacity
|
||||
}
|
||||
enablePublicAccess
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25353,6 +25390,7 @@ export const GetSmtpSettingsDocument = gql`
|
||||
secure
|
||||
sender
|
||||
user
|
||||
password
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25398,6 +25436,7 @@ export const UpdateConfigDocument = gql`
|
||||
storage {
|
||||
capacity
|
||||
}
|
||||
enablePublicAccess
|
||||
}
|
||||
}
|
||||
ai {
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
# @nhost/docs
|
||||
|
||||
## 2.12.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- d5077c7: feat: added docs about how to connect to postgres
|
||||
|
||||
## 2.11.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- c6dc7f4: chore: docs: add Nhost client reference
|
||||
|
||||
## 2.10.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- a58c5cf: fix: broken link
|
||||
|
||||
## 2.10.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 9480489: fix: update docs performance info
|
||||
|
||||
## 2.10.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
43
docs/guides/database/access.mdx
Normal file
43
docs/guides/database/access.mdx
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Accessing the Database
|
||||
description: How to access the database directly using the connection string
|
||||
icon: key
|
||||
---
|
||||
|
||||
In most cases you will not need to access the database directly, choosing to interact with the data via the Graphql API, however, if you need direct access to postgres you can access it via the connection string.
|
||||
|
||||
|
||||
# Nhost Run
|
||||
|
||||
You can find details on how to connect to the database from an [Nhost Run](/product/run) service [here](/guides/run/networking#connecting-to-the-nhost-stack). If you don't know the password you can set a new password in the dashboard:
|
||||
|
||||
**Project Dashboard -> Settings -> Database**
|
||||
|
||||

|
||||
|
||||
# Public Access
|
||||
|
||||
For security reasons, by default your database won't be accessible online. If you need to access it directly from the Internet, first you will need to enable public access (enabling public access will also show the connection details):
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Dashboard">
|
||||
**Project Dashboard -> Settings -> Database**
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
<Tab title="Config">
|
||||
```toml
|
||||
[postgres.resources]
|
||||
enablePublicAccess = true
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Note>
|
||||
Public access to your database utilizes [pgbouncer](http://www.pgbouncer.org). As this pooler is shared infrastructure the pooler will still be available even if your database has no public access configured. The pooler will simply not have access to your database.
|
||||
</Note>
|
||||
|
||||
# Functions
|
||||
|
||||
[Functions](/product/functions) run on a separate network, which means in order to access the database you will first need to [make it public](#public-access).
|
||||
BIN
docs/images/guides/database/access/public.png
Normal file
BIN
docs/images/guides/database/access/public.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 426 KiB |
BIN
docs/images/guides/database/access/reset.png
Normal file
BIN
docs/images/guides/database/access/reset.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 382 KiB |
@@ -96,7 +96,7 @@
|
||||
},
|
||||
{
|
||||
"group": "Database",
|
||||
"pages": ["guides/database/configuring-postgres", "guides/database/extensions", "guides/database/performance"]
|
||||
"pages": ["guides/database/configuring-postgres", "guides/database/access", "guides/database/extensions", "guides/database/performance"]
|
||||
},
|
||||
{
|
||||
"group": "AI",
|
||||
@@ -298,6 +298,10 @@
|
||||
"group": "JavaScript",
|
||||
"icon": "js",
|
||||
"pages": [
|
||||
{
|
||||
"group": "nhost-js",
|
||||
"pages": ["reference/javascript/nhost-js/nhost-client", "reference/javascript/nhost-js/set-role", "reference/javascript/nhost-js/unset-role"]
|
||||
},
|
||||
{
|
||||
"group": "Auth",
|
||||
"pages": [
|
||||
@@ -338,7 +342,10 @@
|
||||
"reference/javascript/storage/get-public-url",
|
||||
"reference/javascript/storage/delete",
|
||||
"reference/javascript/storage/set-access-token",
|
||||
"reference/javascript/storage/set-admin-secret"
|
||||
"reference/javascript/storage/set-admin-secret",
|
||||
"reference/javascript/storage/set-headers",
|
||||
"reference/javascript/storage/unset-headers",
|
||||
"reference/javascript/storage/get-headers"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -347,7 +354,10 @@
|
||||
"reference/javascript/graphql/nhost-graphql-client",
|
||||
"reference/javascript/graphql/get-url",
|
||||
"reference/javascript/graphql/set-access-token",
|
||||
"reference/javascript/graphql/request"
|
||||
"reference/javascript/graphql/request",
|
||||
"reference/javascript/graphql/set-headers",
|
||||
"reference/javascript/graphql/unset-headers",
|
||||
"reference/javascript/graphql/get-headers"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/docs",
|
||||
"version": "2.10.1",
|
||||
"version": "2.12.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "mintlify dev"
|
||||
|
||||
@@ -74,19 +74,4 @@ To setup dedicated resources for your project, you can either use the Dashboard
|
||||
|
||||
## Disk Performance
|
||||
|
||||
Services may require a disk provisioned to store data. For instance, [postgres](/guides/database/configuring-postgres#configuration-example) comes with a disk provisioned by default and [Nhost Run](/product/run) may [too](/guides/run/resources#storage). For these cases we provisioned SSD disks with the following performance:
|
||||
|
||||
- Baseline: 3000 IOPS
|
||||
- Baseline: 125Mbps of thoughput
|
||||
- Every 50GB: +350 IOPS and +15Mbps of throughput
|
||||
|
||||
For example, the following disk sizes will have the following performance:
|
||||
|
||||
| Size | IOPS | Throughput |
|
||||
| ---- | ---- | ---------- |
|
||||
| 1 | 3000| 125 |
|
||||
| 10 | 3000| 125 |
|
||||
| 49 | 3000| 125 |
|
||||
| 50 | 3350| 140 |
|
||||
| 100 | 3700 | 155 |
|
||||
| 300 | 5100 | 215 |
|
||||
By default disks are provisioned with a capacity for 3000 IOPS and 125 Mbps of throughput. If you need higher performance don't hesitate to contact us.
|
||||
|
||||
@@ -50,7 +50,7 @@ In addition, thanks to [pgvector](https://github.com/pgvector/pgvector) you can
|
||||
<CardGroup cols={4}>
|
||||
<Card title="Enabling Service" icon="square-1" href="../guides/ai/enabling-service">
|
||||
</Card>
|
||||
<Card title="Local Development" icon="square-2" href="../guides/ai/local_development">
|
||||
<Card title="Local Development" icon="square-2" href="../guides/ai/local-development">
|
||||
</Card>
|
||||
<Card title="Auto-Embeddings" icon="square-3" href="../guides/ai/auto-embeddings">
|
||||
</Card>
|
||||
|
||||
10
docs/reference/javascript/graphql/get-headers.mdx
Normal file
10
docs/reference/javascript/graphql/get-headers.mdx
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: getHeaders()
|
||||
sidebarTitle: getHeaders()
|
||||
---
|
||||
|
||||
Use `nhost.graphql.getHeaders` to get the global headers sent with all graphql requests
|
||||
|
||||
```ts
|
||||
nhost.graphql.getHeaders()
|
||||
```
|
||||
20
docs/reference/javascript/graphql/set-headers.mdx
Normal file
20
docs/reference/javascript/graphql/set-headers.mdx
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: setHeaders()
|
||||
sidebarTitle: setHeaders()
|
||||
---
|
||||
|
||||
Use `nhost.graphql.setHeaders` to set global headers to be sent in all subsequent graphql requests
|
||||
|
||||
```ts
|
||||
nhost.graphql.setHeaders({
|
||||
'x-hasura-role': 'admin'
|
||||
})
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">headers</span>** <span className="optional-status">optional</span> <code>Record<string, string></code>
|
||||
|
||||
---
|
||||
11
docs/reference/javascript/graphql/unset-headers.mdx
Normal file
11
docs/reference/javascript/graphql/unset-headers.mdx
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: unsetHeaders()
|
||||
sidebarTitle: unsetHeaders()
|
||||
---
|
||||
|
||||
Use `nhost.graphql.unsetHeaders` to remove global headers sent with all requests, except for the role header to preserve
|
||||
the role set by 'setRole' method.
|
||||
|
||||
```ts
|
||||
nhost.graphql.unsetHeaders()
|
||||
```
|
||||
51
docs/reference/javascript/nhost-js/nhost-client.mdx
Normal file
51
docs/reference/javascript/nhost-js/nhost-client.mdx
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: NhostClient
|
||||
description: The Nhost client is the entry point to Nhost services.
|
||||
---
|
||||
|
||||
# `NhostClient`
|
||||
|
||||
```ts
|
||||
// Create a new Nhost client from subdomain and region.
|
||||
const nhost = new NhostClient({ subdomain, region })
|
||||
```
|
||||
|
||||
```ts
|
||||
// Create a new Nhost client from individual service URLs (custom domains, self-hosting, etc).
|
||||
const nhost = new NhostClient({
|
||||
authUrl: 'my-auth-service-url',
|
||||
storageUrl: 'my-storage-service-url',
|
||||
graphqlUrl: 'my-graphql-service-url',
|
||||
functionsUrl: 'my-functions-service-url'
|
||||
})
|
||||
```
|
||||
|
||||
```ts
|
||||
// Create a new Nhost client for local development.
|
||||
const nhost = new NhostClient({ subdomain: 'local' })
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">\_\_namedParameters</span>** <span className="optional-status">required</span> [`NhostClientConstructorParams`](/reference/javascript/nhost-js/types/nhost-client-constructor-params)
|
||||
|
||||
| Property | Type | Required | Notes |
|
||||
| :------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------ | :------: | :--------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>adminSecret</span> | <code>string</code> | | When set, the admin secret is sent as a header, `x-hasura-admin-secret`, for all requests to GraphQL, Storage, and Serverless Functions. |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>functionsUrl</span> | <code>string</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>storageUrl</span> | <code>string</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>graphqlUrl</span> | <code>string</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>authUrl</span> | <code>string</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>region</span> | <code>string</code> | | Project region (e.g. `eu-central-1`) Project region is not required during local development (when `subdomain` is `localhost`) |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>subdomain</span> | <code>string</code> | | Project subdomain (e.g. `ieingiwnginwnfnegqwvdqwdwq`) Use `localhost` during local development |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>devTools</span> | <code>boolean</code> | | Activate devTools e.g. the ability to connect to the xstate inspector |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>autoSignIn</span> | <code>boolean</code> | | When set to true, will parse the url on startup to check if it contains a refresh token to start the session with |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>autoRefreshToken</span> | <code>boolean</code> | | When set to true, will automatically refresh token before it expires |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>clientStorage</span> | [`ClientStorage`](/reference/javascript/nhost-js/types/client-storage) | | Object where the refresh token will be persisted and read locally. |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>clientStorageType</span> | [`ClientStorageType`](/reference/javascript/nhost-js/types/client-storage-type) | | Define a way to get information about the refresh token and its exipration date. |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>refreshIntervalTime</span> | <code>number</code> | | Time interval until token refreshes, in seconds |
|
||||
| <span className="parameter-name"><span className="light-grey">\_\_namedParameters.</span>start</span> | <code>boolean</code> | | |
|
||||
|
||||
---
|
||||
29
docs/reference/javascript/nhost-js/set-role.mdx
Normal file
29
docs/reference/javascript/nhost-js/set-role.mdx
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
title: setRole()
|
||||
sidebarTitle: setRole()
|
||||
---
|
||||
|
||||
Use `nhost.setRole` to set the user role for all subsequent GraphQL, storage, and functions calls.
|
||||
Underneath, this method sets the `x-hasura-role` header on the graphql, storage,
|
||||
and functions clients.
|
||||
|
||||
```ts
|
||||
nhost.graphql.setHeaders({ 'x-hasura-role': role })
|
||||
nhost.storage.setHeaders({ 'x-hasura-role': role })
|
||||
nhost.functions.setHeaders({ 'x-hasura-role': role })
|
||||
```
|
||||
|
||||
Note: Exercise caution when mixing the use of `setRole` along with `setHeaders` when setting the
|
||||
`x-hasura-role` header, as the last call will override any previous ones.
|
||||
|
||||
```ts
|
||||
nhost.setRole('admin')
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">role</span>** <span className="optional-status">required</span> <code>string</code>
|
||||
|
||||
---
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: ClientStorageType
|
||||
sidebarTitle: ClientStorageType
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `ClientStorageType`
|
||||
|
||||
```ts
|
||||
type ClientStorageType =
|
||||
| 'capacitor'
|
||||
| 'custom'
|
||||
| 'expo-secure-storage'
|
||||
| 'localStorage'
|
||||
| 'react-native'
|
||||
| 'web'
|
||||
| 'cookie'
|
||||
```
|
||||
55
docs/reference/javascript/nhost-js/types/client-storage.mdx
Normal file
55
docs/reference/javascript/nhost-js/types/client-storage.mdx
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: ClientStorage
|
||||
sidebarTitle: ClientStorage
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `ClientStorage`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">customSet</span>** <span className="optional-status">optional</span> <code>(key: string, value: null | string) => void | Promise<void></code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">customGet</span>** <span className="optional-status">optional</span> <code>(key: string) => null | string | Promise<null | string></code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">deleteItemAsync</span>** <span className="optional-status">optional</span> <code>(key: string) => void</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">getItemAsync</span>** <span className="optional-status">optional</span> <code>(key: string) => any</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">setItemAsync</span>** <span className="optional-status">optional</span> <code>(key: string, value: string) => void</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">remove</span>** <span className="optional-status">optional</span> <code>(options: { key: string }) => void</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">get</span>** <span className="optional-status">optional</span> <code>(options: { key: string }) => any</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">set</span>** <span className="optional-status">optional</span> <code>(options: { key: string, value: string }) => void</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">removeItem</span>** <span className="optional-status">optional</span> <code>(key: string) => void</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">getItem</span>** <span className="optional-status">optional</span> <code>(key: string) => any</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">setItem</span>** <span className="optional-status">optional</span> <code>(\_key: string, \_value: string) => void</code>
|
||||
|
||||
---
|
||||
@@ -0,0 +1,118 @@
|
||||
---
|
||||
title: NhostClientConstructorParams
|
||||
sidebarTitle: NhostClientConstructorParams
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `NhostClientConstructorParams`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">start</span>** <span className="optional-status">optional</span> <code>boolean</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">refreshIntervalTime</span>** <span className="optional-status">optional</span> <code>number</code>
|
||||
|
||||
Time interval until token refreshes, in seconds
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">clientStorageType</span>** <span className="optional-status">optional</span> [`ClientStorageType`](/reference/javascript/nhost-js/types/client-storage-type)
|
||||
|
||||
Define a way to get information about the refresh token and its exipration date.
|
||||
|
||||
**`@default`**
|
||||
|
||||
`web`
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">clientStorage</span>** <span className="optional-status">optional</span> [`ClientStorage`](/reference/javascript/nhost-js/types/client-storage)
|
||||
|
||||
Object where the refresh token will be persisted and read locally.
|
||||
|
||||
Recommended values:
|
||||
|
||||
- `'web'` and `'cookies'`: no value is required
|
||||
- `'react-native'`: `import Storage from @react-native-async-storage/async-storage`
|
||||
- `'cookies'`: `localStorage`
|
||||
- `'custom'`: an object that defines the following methods:
|
||||
- `setItem` or `setItemAsync`
|
||||
- `getItem` or `getItemAsync`
|
||||
- `removeItem`
|
||||
- `'capacitor'`: `import { Storage } from @capacitor/storage`
|
||||
- `'expo-secure-store'`: `import * as SecureStore from 'expo-secure-store'`
|
||||
|
||||
| Property | Type | Required | Notes |
|
||||
| :-------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | :------: | :---- |
|
||||
| <span className="parameter-name"><span className="light-grey">clientStorage.</span>setItem</span> | <code>(\_key: string, \_value: string) => void</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">clientStorage.</span>getItem</span> | <code>(key: string) => any</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">clientStorage.</span>removeItem</span> | <code>(key: string) => void</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">clientStorage.</span>set</span> | <code>(options: { key: string, value: string }) => void</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">clientStorage.</span>get</span> | <code>(options: { key: string }) => any</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">clientStorage.</span>remove</span> | <code>(options: { key: string }) => void</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">clientStorage.</span>setItemAsync</span> | <code>(key: string, value: string) => void</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">clientStorage.</span>getItemAsync</span> | <code>(key: string) => any</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">clientStorage.</span>deleteItemAsync</span> | <code>(key: string) => void</code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">clientStorage.</span>customGet</span> | <code>(key: string) => null | string | Promise<null | string></code> | | |
|
||||
| <span className="parameter-name"><span className="light-grey">clientStorage.</span>customSet</span> | <code>(key: string, value: null | string) => void | Promise<void></code> | | |
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">autoRefreshToken</span>** <span className="optional-status">optional</span> <code>boolean</code>
|
||||
|
||||
When set to true, will automatically refresh token before it expires
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">autoSignIn</span>** <span className="optional-status">optional</span> <code>boolean</code>
|
||||
|
||||
When set to true, will parse the url on startup to check if it contains a refresh token to start the session with
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">devTools</span>** <span className="optional-status">optional</span> <code>boolean</code>
|
||||
|
||||
Activate devTools e.g. the ability to connect to the xstate inspector
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">subdomain</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
Project subdomain (e.g. `ieingiwnginwnfnegqwvdqwdwq`)
|
||||
Use `localhost` during local development
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">region</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
Project region (e.g. `eu-central-1`)
|
||||
Project region is not required during local development (when `subdomain` is `localhost`)
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">authUrl</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">graphqlUrl</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">storageUrl</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">functionsUrl</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">adminSecret</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
When set, the admin secret is sent as a header, `x-hasura-admin-secret`,
|
||||
for all requests to GraphQL, Storage, and Serverless Functions.
|
||||
|
||||
---
|
||||
14
docs/reference/javascript/nhost-js/unset-role.mdx
Normal file
14
docs/reference/javascript/nhost-js/unset-role.mdx
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: unsetRole()
|
||||
sidebarTitle: unsetRole()
|
||||
---
|
||||
|
||||
Use `nhost.unsetRole` to unset the user role for all subsequent graphql, storage and functions calls.
|
||||
Underneath, this method removes the `x-hasura-role` header from the graphql, storage and functions clients.
|
||||
|
||||
Note: Exercise caution when mixing the use of `unsetRole` along with `setHeaders` when setting the
|
||||
`x-hasura-role` header, as the last call will override any previous ones.
|
||||
|
||||
```ts
|
||||
nhost.unsetRole()
|
||||
```
|
||||
@@ -22,6 +22,6 @@ const { file, error } = await nhost.storage.download({ fileId: '<File-ID>' })
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>quality</span> | <code>number</code> | | Image quality, between 1 and 100, 100 being the best quality |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>height</span> | <code>number</code> | | Image height, in pixels |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>width</span> | <code>number</code> | | Image width, in pixels |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>headers</span> | <code>Record<string, string></code> | | Optional headers to be sent with the request |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>headers</span> | <code>Record<string, string></code> | | |
|
||||
|
||||
---
|
||||
|
||||
10
docs/reference/javascript/storage/get-headers.mdx
Normal file
10
docs/reference/javascript/storage/get-headers.mdx
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: getHeaders()
|
||||
sidebarTitle: getHeaders()
|
||||
---
|
||||
|
||||
Use `nhost.storage.getHeaders` to get global headers sent with all storage requests.
|
||||
|
||||
```ts
|
||||
nhost.storage.getHeaders()
|
||||
```
|
||||
@@ -24,12 +24,13 @@ console.log('expiration: ', presignedUrl.expiration)
|
||||
|
||||
**<span className="parameter-name">params</span>** <span className="optional-status">required</span> [`StorageGetPresignedUrlParams`](/reference/javascript/storage/types/storage-get-presigned-url-params)
|
||||
|
||||
| Property | Type | Required | Notes |
|
||||
| :----------------------------------------------------------------------------------------- | :------------------ | :------: | :----------------------------------------------------------- |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>fileId</span> | <code>string</code> | ✔️ | |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>blur</span> | <code>number</code> | | Image blur, between 0 and 100 |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>quality</span> | <code>number</code> | | Image quality, between 1 and 100, 100 being the best quality |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>height</span> | <code>number</code> | | Image height, in pixels |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>width</span> | <code>number</code> | | Image width, in pixels |
|
||||
| Property | Type | Required | Notes |
|
||||
| :----------------------------------------------------------------------------------------- | :---------------------------------------- | :------: | :----------------------------------------------------------- |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>fileId</span> | <code>string</code> | ✔️ | |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>blur</span> | <code>number</code> | | Image blur, between 0 and 100 |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>quality</span> | <code>number</code> | | Image quality, between 1 and 100, 100 being the best quality |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>height</span> | <code>number</code> | | Image height, in pixels |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>width</span> | <code>number</code> | | Image width, in pixels |
|
||||
| <span className="parameter-name"><span className="light-grey">params.</span>headers</span> | <code>Record<string, string></code> | | |
|
||||
|
||||
---
|
||||
|
||||
22
docs/reference/javascript/storage/set-headers.mdx
Normal file
22
docs/reference/javascript/storage/set-headers.mdx
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: setHeaders()
|
||||
sidebarTitle: setHeaders()
|
||||
---
|
||||
|
||||
Use `nhost.storage.setHeaders` to set global headers to be sent for all subsequent storage requests.
|
||||
|
||||
```ts
|
||||
nhost.storage.setHeaders({
|
||||
'x-hasura-role': 'admin'
|
||||
})
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">headers</span>** <span className="optional-status">optional</span> <code>Record<string, string></code>
|
||||
|
||||
key value headers object
|
||||
|
||||
---
|
||||
@@ -10,6 +10,10 @@ description: No description provided.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">headers</span>** <span className="optional-status">optional</span> <code>Record<string, string></code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">fileId</span>** <span className="optional-status">required</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
@@ -10,6 +10,10 @@ description: No description provided.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">headers</span>** <span className="optional-status">optional</span> <code>Record<string, string></code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">fileId</span>** <span className="optional-status">required</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
@@ -40,6 +40,4 @@ Image width, in pixels
|
||||
|
||||
**<span className="parameter-name">headers</span>** <span className="optional-status">optional</span> <code>Record<string, string></code>
|
||||
|
||||
Optional headers to be sent with the request
|
||||
|
||||
---
|
||||
|
||||
@@ -37,3 +37,7 @@ Image height, in pixels
|
||||
Image width, in pixels
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">headers</span>** <span className="optional-status">optional</span> <code>Record<string, string></code>
|
||||
|
||||
---
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: StorageHeadersParam
|
||||
sidebarTitle: StorageHeadersParam
|
||||
description: No description provided.
|
||||
---
|
||||
|
||||
# `StorageHeadersParam`
|
||||
|
||||
## Parameters
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">headers</span>** <span className="optional-status">optional</span> <code>Record<string, string></code>
|
||||
|
||||
---
|
||||
@@ -25,3 +25,7 @@ description: No description provided.
|
||||
**<span className="parameter-name">id</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">headers</span>** <span className="optional-status">optional</span> <code>Record<string, string></code>
|
||||
|
||||
---
|
||||
|
||||
@@ -14,10 +14,10 @@ description: No description provided.
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">headers</span>** <span className="optional-status">optional</span> <code>Record<string, string></code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">bucketId</span>** <span className="optional-status">optional</span> <code>string</code>
|
||||
|
||||
---
|
||||
|
||||
**<span className="parameter-name">headers</span>** <span className="optional-status">optional</span> <code>Record<string, string></code>
|
||||
|
||||
---
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user