Compare commits
5 Commits
@nhost/das
...
@nhost/das
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4341c3706 | ||
|
|
c2ef17c0a0 | ||
|
|
1045ea0a46 | ||
|
|
5faaf36e26 | ||
|
|
65b6a48d51 |
@@ -1,5 +1,11 @@
|
||||
# @nhost/dashboard
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- c2ef17c0a: feat: add support for new Team plan
|
||||
|
||||
## 1.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/dashboard",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
|
||||
@@ -4,9 +4,17 @@ import type { DetailedHTMLProps, HTMLProps } from 'react';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export interface ContactUsProps
|
||||
extends DetailedHTMLProps<HTMLProps<HTMLDivElement>, HTMLDivElement> {}
|
||||
extends DetailedHTMLProps<HTMLProps<HTMLDivElement>, HTMLDivElement> {
|
||||
isTeam?: boolean;
|
||||
isOwner?: boolean;
|
||||
}
|
||||
|
||||
export default function FeedbackForm({ className, ...props }: ContactUsProps) {
|
||||
export default function FeedbackForm({
|
||||
className,
|
||||
isTeam,
|
||||
isOwner,
|
||||
...props
|
||||
}: ContactUsProps) {
|
||||
return (
|
||||
<div
|
||||
className={twMerge(
|
||||
@@ -19,6 +27,30 @@ export default function FeedbackForm({ className, ...props }: ContactUsProps) {
|
||||
Contact us
|
||||
</Text>
|
||||
|
||||
{isTeam && isOwner && (
|
||||
<Text>
|
||||
If this is a new Team project, or you need to manage members, reach
|
||||
out to us on discord or via email at{' '}
|
||||
<Link
|
||||
href="mailto:support@nhost.io"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
underline="hover"
|
||||
>
|
||||
support@nhost.io
|
||||
</Link>{' '}
|
||||
so we can have your dedicated channel set up.
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{isTeam && !isOwner && (
|
||||
<Text>
|
||||
As part of a team plan you can reach out to us on the private channel
|
||||
for this workspace. If you haven't been added to the channel, ask
|
||||
the workspace owner to add you.
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<Text>
|
||||
To report issues with Nhost, please open a GitHub issue in the{' '}
|
||||
<Link
|
||||
|
||||
@@ -13,6 +13,7 @@ import { Dropdown } from '@/components/ui/v2/Dropdown';
|
||||
import { GraphiteIcon } from '@/components/ui/v2/icons/GraphiteIcon';
|
||||
import { DevAssistant } from '@/features/ai/DevAssistant';
|
||||
import { useCurrentWorkspaceAndProject } from '@/features/projects/common/hooks/useCurrentWorkspaceAndProject';
|
||||
import { useIsCurrentUserOwner } from '@/features/projects/common/hooks/useIsCurrentUserOwner';
|
||||
import { useIsPlatform } from '@/features/projects/common/hooks/useIsPlatform';
|
||||
import { ApplicationStatus } from '@/types/application';
|
||||
import { getToastStyleProps } from '@/utils/constants/settings';
|
||||
@@ -37,6 +38,8 @@ export default function Header({ className, ...props }: HeaderProps) {
|
||||
const { currentProject, refetch: refetchProject } =
|
||||
useCurrentWorkspaceAndProject();
|
||||
|
||||
const isOwner = useIsCurrentUserOwner();
|
||||
|
||||
const isProjectUpdating =
|
||||
currentProject?.appStates[0]?.stateId === ApplicationStatus.Updating;
|
||||
|
||||
@@ -114,7 +117,11 @@ export default function Header({ className, ...props }: HeaderProps) {
|
||||
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||
>
|
||||
<ContactUs className="max-w-md" />
|
||||
<ContactUs
|
||||
className="max-w-md"
|
||||
isTeam={currentProject?.plan?.name === 'Team'}
|
||||
isOwner={isOwner}
|
||||
/>
|
||||
</Dropdown.Content>
|
||||
</Dropdown.Root>
|
||||
)}
|
||||
|
||||
@@ -10,7 +10,7 @@ export default function useIsCurrentUserOwner() {
|
||||
const { currentWorkspace, loading } = useCurrentWorkspaceAndProject();
|
||||
const currentUser = useUserData();
|
||||
|
||||
if (loading || !currentWorkspace.workspaceMembers || !currentUser) {
|
||||
if (loading || !currentWorkspace?.workspaceMembers || !currentUser) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const planDescriptions = {
|
||||
Starter: '1 GB database, 5 GB of file storage, 10 GB of network traffic.',
|
||||
Pro: '10 GB database, 25 GB of file storage, 50 GB of network traffic, and backups.',
|
||||
Team: 'Reach out to us at support@nhost.io to have your private channel set up.',
|
||||
};
|
||||
|
||||
export default planDescriptions;
|
||||
|
||||
@@ -16,7 +16,7 @@ export default function OverviewTopBar() {
|
||||
const isPlatform = useIsPlatform();
|
||||
const { currentWorkspace, currentProject } = useCurrentWorkspaceAndProject();
|
||||
const isOwner = useIsCurrentUserOwner();
|
||||
const isPro = !currentProject?.plan?.isFree;
|
||||
const isStarter = currentProject?.plan?.name === 'Starter';
|
||||
const { openDialog } = useDialog();
|
||||
const { maintenanceActive } = useUI();
|
||||
|
||||
@@ -65,7 +65,6 @@ export default function OverviewTopBar() {
|
||||
>
|
||||
{currentProject.name}
|
||||
</Text>
|
||||
|
||||
{currentProject.creator && (
|
||||
<Text
|
||||
color="secondary"
|
||||
@@ -81,15 +80,14 @@ export default function OverviewTopBar() {
|
||||
ago
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<div className="mt-1 inline-grid grid-flow-col items-center justify-start gap-2 md:mt-0">
|
||||
<Chip
|
||||
size="small"
|
||||
label={currentProject.plan.name}
|
||||
color={isPro ? 'primary' : 'default'}
|
||||
color={!isStarter ? 'primary' : 'default'}
|
||||
/>
|
||||
|
||||
{!isPro && isOwner && (
|
||||
{isStarter && isOwner && (
|
||||
<Button
|
||||
variant="borderless"
|
||||
className="mr-2"
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
import type { ApolloError } from '@apollo/client';
|
||||
import { useUserData } from '@nhost/nextjs';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import type { FormEvent, ReactElement } from 'react';
|
||||
import { cloneElement, isValidElement, useState } from 'react';
|
||||
@@ -444,6 +445,19 @@ export function NewProjectPageContent({
|
||||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
<Text variant="subtitle2">
|
||||
Select a plan that suits your infrastructure needs.{' '}
|
||||
<Link href="https://nhost.io/pricing">
|
||||
<a
|
||||
href="https://nhost.io/pricing"
|
||||
className="underline"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</Link>
|
||||
</Text>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @nhost/docs
|
||||
|
||||
## 2.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 65b6a48d5: feat: added graphite/cli documentation
|
||||
|
||||
## 2.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
@@ -8,8 +8,19 @@ You can enable Graphite, Nhost's AI service, with the following steps:
|
||||
<Steps>
|
||||
<Step title="Check your database version">
|
||||
Check your project's settings and make sure the database version is at least `14.6-20231018-1`. If it isn't upgrade your database version (latest available version is recommended).
|
||||
<Tabs>
|
||||
<Tab title="Dashboard">
|
||||

|
||||
</Tab>
|
||||
|
||||
<Tab title="toml">
|
||||
```toml
|
||||
[postgres]
|
||||
version = '14.6-20231018-1'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||

|
||||
</Step>
|
||||
<Step title="Get an OpenAPI key">
|
||||
Get an OpenAI API key from their [customer portal](https://platform.openai.com/account/api-keys).
|
||||
@@ -27,7 +38,7 @@ You can enable Graphite, Nhost's AI service, with the following steps:
|
||||
```toml
|
||||
[ai]
|
||||
# Version of the service to use. Check the settings page for available versions
|
||||
version = '0.1.0'
|
||||
version = '0.3.1'
|
||||
|
||||
# Used to validate requests between postgres and the AI service.
|
||||
# The AI service will also include the header X-Graphite-Webhook-Secret
|
||||
@@ -41,13 +52,13 @@ You can enable Graphite, Nhost's AI service, with the following steps:
|
||||
|
||||
[ai.openai]
|
||||
# Key to use for authenticating API requests to OpenAI.
|
||||
apiKey = '{{ secrets.OPEANAI_API_KEY }}'
|
||||
apiKey = '{{ secrets.OPENAI_API_KEY }}'
|
||||
# OpenAI organization to use.
|
||||
organization = 'my-org'
|
||||
|
||||
[ai.resources.compute]
|
||||
# Dedicated resources allocated for the service
|
||||
cpu = 125
|
||||
cpu = 128
|
||||
memory = 256
|
||||
```
|
||||
</Tab>
|
||||
|
||||
45
docs/guides/ai/local_development.mdx
Normal file
45
docs/guides/ai/local_development.mdx
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "Local Development"
|
||||
icon: code
|
||||
---
|
||||
|
||||
If you are using the Nhost CLI for local development, as of [v0.12.0](https://github.com/nhost/cli/releases/tag/v1.12.0) you can also start Graphite locally. To do so, follow the next steps:
|
||||
|
||||
|
||||
|
||||
<Steps>
|
||||
<Step title="Configuring the Service">
|
||||
Follow the steps highlighed in the ["Enabling Service"](enabling-service) guide and don't forget to add the relevant secrets to your `.secrets` file.
|
||||
</Step>
|
||||
<Step title="Start nhost">
|
||||
Run `nhost up`:
|
||||
|
||||

|
||||
|
||||
After starting the service the first thing you will notice is that there is a new `ai` service running.
|
||||
</Step>
|
||||
<Step title="Commit metadata changes">
|
||||
As you start the AI service metadata changes may be proposed:
|
||||
|
||||

|
||||
|
||||
We strongly recommmend you to commit them to your git repository so they can be deployed alongside your application.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
|
||||
### Synhcronizing Auto-Embeddings
|
||||
|
||||
If you add [auto-embeddings](/guides/ai/auto-embeddings) configuration locally and want to synchronize them with the cloud we recommend inserting them using a migration rather than with the auto-embeddings UI:
|
||||
|
||||

|
||||
|
||||
And then running `nhost up` to download the updated metadata. Afterwards you should see both database migrations and functions' metadata changes in your local project:
|
||||
|
||||

|
||||
|
||||
Pushing them to your deployment branch will also deploy them to your cloud project.
|
||||
|
||||
### Synhcronizing Assistants
|
||||
|
||||
Similar to auto-embeddings, if you want to synchronize [assistants](/guides/ai/assistants) we recommend you to insert them using a migration and then running `nhost up` to update any metadata if necessary. After pushing the proposed changes to the deployment branch all the changes should be deployed to the cloud project.
|
||||
@@ -19,7 +19,7 @@ To connect your service to the Nhost stack, use the following information:
|
||||
|
||||
To connect to your own service internally from another service, follow these steps:
|
||||
|
||||
1. Expose the desired port(s).
|
||||
1. Configure the desired port(s).
|
||||
|
||||
Example for Redis service:
|
||||
|
||||
@@ -40,9 +40,9 @@ publish = false
|
||||
</Tabs>
|
||||
|
||||
|
||||
2. Once the port is exposed, you can connect to the service using its name and the corresponding port.
|
||||
2. Once the port is configured, you can connect to the service using as host `run-${name}` and the corresponding port.
|
||||
|
||||
Example: `redis://user:password@redis:6379`
|
||||
Example: `redis://user:password@run-redis:6379`
|
||||
|
||||
If needed, you can open internally more than one port by repeating the block for each one of them:
|
||||
|
||||
|
||||
BIN
docs/images/guides/ai/local_development/git_status.png
Normal file
BIN
docs/images/guides/ai/local_development/git_status.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
BIN
docs/images/guides/ai/local_development/git_status_functions.png
Normal file
BIN
docs/images/guides/ai/local_development/git_status_functions.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 110 KiB |
BIN
docs/images/guides/ai/local_development/migration.png
Normal file
BIN
docs/images/guides/ai/local_development/migration.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 916 KiB |
BIN
docs/images/guides/ai/local_development/nhost_up.png
Normal file
BIN
docs/images/guides/ai/local_development/nhost_up.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 393 KiB |
@@ -102,6 +102,7 @@
|
||||
"group": "AI",
|
||||
"pages": [
|
||||
"guides/ai/enabling-service",
|
||||
"guides/ai/local_development",
|
||||
"guides/ai/auto-embeddings",
|
||||
"guides/ai/assistants",
|
||||
"guides/ai/dev-assistant"
|
||||
@@ -110,8 +111,8 @@
|
||||
{
|
||||
"group": "Authentication",
|
||||
"pages": [
|
||||
{
|
||||
"group": "Social Sign In",
|
||||
{
|
||||
"group": "Social Sign In",
|
||||
"icon": "at",
|
||||
"pages": [
|
||||
"guides/auth/social/sign-in-apple",
|
||||
@@ -161,7 +162,7 @@
|
||||
"icon": "users",
|
||||
"pages": [
|
||||
{
|
||||
"group": "Email and Password",
|
||||
"group": "Email and Password",
|
||||
"icon": "envelope",
|
||||
"pages": [
|
||||
"reference/auth/sign-up-email-and-password",
|
||||
@@ -169,7 +170,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Passwordless",
|
||||
"group": "Passwordless",
|
||||
"icon": "message-sms",
|
||||
"pages": [
|
||||
"reference/auth/sign-in-email-passwordless",
|
||||
@@ -178,7 +179,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "OAuth",
|
||||
"group": "OAuth",
|
||||
"icon": "at",
|
||||
"pages": [
|
||||
"reference/auth/sign-in-oauth-provider",
|
||||
@@ -186,7 +187,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "WebAuthn",
|
||||
"group": "WebAuthn",
|
||||
"icon": "atom",
|
||||
"pages": [
|
||||
"reference/auth/sign-up-using-email-via-fido2-webauthn-authentication",
|
||||
@@ -196,7 +197,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Anonymous",
|
||||
"group": "Anonymous",
|
||||
"icon": "luchador-mask",
|
||||
"pages": [
|
||||
"reference/auth/sign-in-anonymous",
|
||||
@@ -204,7 +205,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "MFA",
|
||||
"group": "MFA",
|
||||
"icon": "message-sms",
|
||||
"pages": [
|
||||
"reference/auth/generate-a-secret-to-request-the-activation-of-time-based-one-time-password-totp-multi-factor-authentication",
|
||||
@@ -213,7 +214,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "User",
|
||||
"group": "User",
|
||||
"icon": "user",
|
||||
"pages": [
|
||||
"reference/auth/change-the-current-users-email",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nhost/docs",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "mintlify dev"
|
||||
|
||||
@@ -50,10 +50,12 @@ 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="Auto-Embeddings" icon="square-2" href="../guides/ai/auto-embeddings">
|
||||
<Card title="Local Development" icon="square-2" href="../guides/ai/local_development">
|
||||
</Card>
|
||||
<Card title="Assistants" icon="square-3" href="../guides/ai/assistants">
|
||||
<Card title="Auto-Embeddings" icon="square-3" href="../guides/ai/auto-embeddings">
|
||||
</Card>
|
||||
<Card title="Developer Assistant" icon="square-4" href="../guides/ai/dev-assistant">
|
||||
<Card title="Assistants" icon="square-4" href="../guides/ai/assistants">
|
||||
</Card>
|
||||
<Card title="Developer Assistant" icon="square-5" href="../guides/ai/dev-assistant">
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -17,7 +17,8 @@ export const createGoogleTranslationGraphQLServer = ({
|
||||
defaultLanguage = 'en',
|
||||
getUserLanguage = defaultGetUserLanguage,
|
||||
canTranslate = defaultCanTranslate,
|
||||
logger = console.log
|
||||
logger = console.log,
|
||||
maskedErrors = true,
|
||||
}: CreateServerProps = {}) => {
|
||||
const translator = new v2.Translate({ projectId, key: apiKey })
|
||||
|
||||
@@ -62,6 +63,7 @@ export const createGoogleTranslationGraphQLServer = ({
|
||||
...context,
|
||||
userLanguage: await getUserLanguage(context)
|
||||
}),
|
||||
schema: builder.toSchema()
|
||||
schema: builder.toSchema(),
|
||||
maskedErrors,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -59,4 +59,10 @@ export type CreateServerProps = {
|
||||
* Logger function
|
||||
*/
|
||||
logger?: Logger
|
||||
/**
|
||||
* Whether to enable GraphQL Yoga error masking
|
||||
* @see {@link https://the-guild.dev/graphql/yoga-server/docs/features/error-masking#disabling-error-masking}
|
||||
* @default true
|
||||
*/
|
||||
maskedErrors?: boolean
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { createYoga, YogaInitialContext } from 'graphql-yoga'
|
||||
import { createServer } from 'node:http'
|
||||
|
||||
import { schema } from './schema'
|
||||
import { Context, CreateServerProps } from './types'
|
||||
import { getUserClaims } from './utils'
|
||||
|
||||
const createStripeGraphQLServer = (params?: CreateServerProps) => {
|
||||
const cors = params?.cors
|
||||
const isAllowed = params?.isAllowed
|
||||
const graphiql = params?.graphiql
|
||||
|
||||
const createStripeGraphQLServer = ({
|
||||
cors,
|
||||
isAllowed,
|
||||
graphiql,
|
||||
maskedErrors = true,
|
||||
}: CreateServerProps = {}) => {
|
||||
const context = (context: YogaInitialContext): Context => {
|
||||
const { request } = context
|
||||
|
||||
@@ -50,7 +52,8 @@ const createStripeGraphQLServer = (params?: CreateServerProps) => {
|
||||
graphiql,
|
||||
context,
|
||||
schema,
|
||||
graphqlEndpoint: '*'
|
||||
graphqlEndpoint: '*',
|
||||
maskedErrors,
|
||||
})
|
||||
|
||||
return yoga
|
||||
|
||||
@@ -11,9 +11,25 @@ export type StripeGraphQLContext = {
|
||||
export type Context = YogaInitialContext & StripeGraphQLContext
|
||||
|
||||
export type CreateServerProps = {
|
||||
/**
|
||||
* GraphQL Yoga CORS configuration
|
||||
* @see {@link https://www.the-guild.dev/graphql/yoga-server/docs/features/cors}
|
||||
*/
|
||||
cors?: CORSOptions
|
||||
/**
|
||||
* Function to determine more granular user permission
|
||||
*/
|
||||
isAllowed?: (stripeCustomerId: string, context: Context) => boolean | Promise<boolean>
|
||||
/**
|
||||
* Whether to enable the GraphiQL interface
|
||||
*/
|
||||
graphiql?: boolean
|
||||
/**
|
||||
* Whether to enable GraphQL Yoga error masking
|
||||
* @see {@link https://the-guild.dev/graphql/yoga-server/docs/features/error-masking#disabling-error-masking}
|
||||
* @default true
|
||||
*/
|
||||
maskedErrors?: boolean
|
||||
}
|
||||
|
||||
// removing Stripe.Customer from `customer` because we will never expand
|
||||
|
||||
Reference in New Issue
Block a user