Compare commits

..

5 Commits

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


# Releases
## @nhost/dashboard@1.5.0

### Minor Changes

-   c2ef17c0a: feat: add support for new Team plan

## @nhost/docs@2.1.0

### Minor Changes

-   65b6a48d5: feat: added graphite/cli documentation

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-01-22 11:31:49 -01:00
Nuno Pato
c2ef17c0a0 feat: dashboard: new Team plan (#2473) 2024-01-22 11:13:26 -01:00
David Barroso
1045ea0a46 fix(docs): set correct hostname for connecting to run service internally (#2471) 2024-01-17 12:34:01 +01:00
Nevada Le Master
5faaf36e26 chore: add maskedErrors param to CreateServerProps (#2129)
this PR addresses https://github.com/nhost/nhost/issues/1218, adding
`maskedErrors` param when creating Stripe and Google Translate GraphQL
Yoga servers

Co-authored-by: David Barroso <dbarrosop@dravetech.com>
2024-01-16 16:36:51 +01:00
David Barroso
65b6a48d51 feat(docs): added graphite/cli documentation (#2457)
Co-authored-by: Nuno Pato <nunopato@gmail.com>
2024-01-10 17:19:58 +01:00
23 changed files with 188 additions and 38 deletions

View File

@@ -1,5 +1,11 @@
# @nhost/dashboard
## 1.5.0
### Minor Changes
- c2ef17c0a: feat: add support for new Team plan
## 1.4.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/dashboard",
"version": "1.4.0",
"version": "1.5.0",
"private": true,
"scripts": {
"preinstall": "npx only-allow pnpm",

View File

@@ -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&apos;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

View File

@@ -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>
)}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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"

View File

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

View File

@@ -1,5 +1,11 @@
# @nhost/docs
## 2.1.0
### Minor Changes
- 65b6a48d5: feat: added graphite/cli documentation
## 2.0.0
### Major Changes

View File

@@ -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">
![database settings](/images/guides/ai/enabling/database.png)
</Tab>
<Tab title="toml">
```toml
[postgres]
version = '14.6-20231018-1'
```
</Tab>
</Tabs>
![database settings](/images/guides/ai/enabling/database.png)
</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>

View 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`:
![nhost up](/images/guides/ai/local_development/nhost_up.png)
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:
![git status](/images/guides/ai/local_development/git_status.png)
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:
![migration](/images/guides/ai/local_development/migration.png)
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:
![git status](/images/guides/ai/local_development/git_status_functions.png)
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.

View File

@@ -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:

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 916 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 KiB

View File

@@ -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",

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/docs",
"version": "2.0.0",
"version": "2.1.0",
"private": true,
"scripts": {
"start": "mintlify dev"

View File

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

View File

@@ -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,
})
}

View File

@@ -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
}

View File

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

View File

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