Improve documentation (#1549)
2
.gitignore
vendored
|
|
@ -127,3 +127,5 @@ packages/web/app/next.config.mjs
|
|||
packages/web/app/environment-*.mjs
|
||||
packages/web/app/src/gql/*.ts
|
||||
packages/web/app/src/graphql/*.ts
|
||||
|
||||
_redirects
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ GraphQL Hive has been built with 3 main objectives in mind:
|
|||
Registry, Performance Monitoring, Alerts, and Integrations.
|
||||
- **Support all kinds of GraphQL APIs**, from Federation, and Stitching, to standalone APIs.
|
||||
- **Open Source at the heart**: 100% open-source and build in public with the community.
|
||||
- **A plug and play SaaS solution**: to give access to Hive to most people with a generous free
|
||||
- **A plug and play Cloud solution**: to give access to Hive to most people with a generous free
|
||||
"Hobby plan"
|
||||
|
||||
## Features Overview
|
||||
|
|
@ -75,10 +75,10 @@ See you in Hive! 🐝
|
|||
- General: NodeJS, TypeScript
|
||||
- Authentication: SuperTokens
|
||||
- HTTP Server: Fastify
|
||||
- APIs: GraphQL, GraphQL-Yoga, GraphQL-Codegen, GraphQL Inspector, GraphQL-Modules
|
||||
- APIs: GraphQL, GraphQL-Yoga, GraphQL-Codegen, GraphQL-Inspector, GraphQL-Modules
|
||||
- App: React, Next.js, Tailwind CSS, Radix Primitives
|
||||
- CLI: Oclif
|
||||
- Deployment (SaaS): Pulumi, K8s, Contour (Envoy), Azure Cloud, CloudFlare Workers, KV Cache, R2
|
||||
- Deployment (Cloud): Pulumi, K8s, Contour (Envoy), Azure Cloud, CloudFlare Workers, CloudFlare R2
|
||||
- Monitoring: Prometheus, Grafana, Sentry
|
||||
- Databases: Postgres, Redis, ClickHouse
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ const currentPackage = packagesMetadata.packages.find(p => p.dir === libDir);
|
|||
export const commonWatchList = () => {
|
||||
return [
|
||||
libDir + '/src/**/*',
|
||||
libDir + '/.env',
|
||||
libDir + '/tsconfig.json',
|
||||
rootDir + '/tsconfig.json',
|
||||
rootDir + '/tsup.config.*',
|
||||
|
|
|
|||
|
|
@ -125,11 +125,11 @@ export DOCKER_TAG=":IMAGE_TAG_HERE"
|
|||
Keep in mind that integration tests are running a combination of 2 Docker Compose files:
|
||||
|
||||
1. `docker-compose.community.yml` - this is also used for self-hosting Hive, so this file contains
|
||||
all services and configurations needed for running Hive core (without SaaS-specific services,
|
||||
all services and configurations needed for running Hive core (without Cloud-specific services,
|
||||
like billing).
|
||||
2. `docker-compose.integration.yaml` - An extension and overrides file: we are using that file to
|
||||
run local services such as CloudFlare CDN mock, external composition service and so on - this is
|
||||
done in order to mock a complete Hive SaaS environment and test all features. **This file also
|
||||
done in order to mock a complete Hive Cloud environment and test all features. **This file also
|
||||
includes overrides such as environment variables that are specific only for integration testing -
|
||||
so make sure to choose wisely where to add environment variables!**
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Note: this is an overrides file for ./docker/docker-compose.community.yml:
|
||||
# It's used for setting special environment and configurations for running integration tests.
|
||||
# This file also includes services that only exists in Hive's SaaS version, and are not available in the self-hosted version.
|
||||
# This file also includes services that only exists in Hive's Cloud version, and are not available in the self-hosted version.
|
||||
# Please refer to TESTING.md for more information.
|
||||
|
||||
version: '3.8'
|
||||
|
|
|
|||
|
|
@ -1,38 +1,36 @@
|
|||
# GraphQL Hive CLI
|
||||
# Hive CLI (Command Line Interface)
|
||||
|
||||
A CLI util to manage and control your GraphQL Hive
|
||||
A CLI util to manage and control your GraphQL Hive. You can perform
|
||||
[schema-registry actions](https://docs.graphql-hive.com/features/schema-registry#actions-on-schemas)
|
||||
on your Hive targets using the Hive CLI.
|
||||
|
||||
[](https://oclif.io)
|
||||
[](https://npmjs.org/package/@graphql-hive/cli)
|
||||
[](https://npmjs.org/package/@graphql-hive/cli)
|
||||
|
||||
<!-- toc -->
|
||||
## Installation
|
||||
|
||||
- [GraphQL Hive CLI](#graphql-hive-cli)
|
||||
- [Usage](#usage)
|
||||
- [Commands](#commands)
|
||||
- [Config](#config)
|
||||
<!-- tocstop -->
|
||||
### NodeJS
|
||||
|
||||
# Usage
|
||||
If you are running a JavaScript/NodeJS project, you can install Hive CLI from the `npm` registry:
|
||||
|
||||
<!-- usage -->
|
||||
|
||||
```sh-session
|
||||
$ npm install -g @graphql-hive/cli
|
||||
$ hive COMMAND
|
||||
running command...
|
||||
$ hive (--version)
|
||||
@graphql-hive/cli/0.20.0 darwin-arm64 node-v18.14.0
|
||||
$ hive --help [COMMAND]
|
||||
USAGE
|
||||
$ hive COMMAND
|
||||
...
|
||||
```
|
||||
pnpm install -D @graphql-hive/cli
|
||||
yarn add -D @graphql-hive/cli
|
||||
npm install -D @graphql-hive/cli
|
||||
```
|
||||
|
||||
<!-- usagestop -->
|
||||
> We recommend installing Hive CLI as part of your project, under `devDependencies`, instead of
|
||||
> using a global installation.
|
||||
|
||||
# Commands
|
||||
### Binary
|
||||
|
||||
If you are running a non-JavaScript project, you can download the prebuilt binary of Hive CLI using
|
||||
the following command:
|
||||
|
||||
```bash
|
||||
curl -sSL https://graphql-hive.com/install.sh | sh
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
<!-- commands -->
|
||||
|
||||
|
|
@ -55,7 +53,7 @@ deletes specific cli configuration
|
|||
|
||||
```
|
||||
USAGE
|
||||
$ hive config:delete [KEY]
|
||||
$ hive config:delete KEY
|
||||
|
||||
ARGUMENTS
|
||||
KEY config key
|
||||
|
|
@ -65,7 +63,7 @@ DESCRIPTION
|
|||
```
|
||||
|
||||
_See code:
|
||||
[dist/commands/config/delete.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.0/dist/commands/config/delete.js)_
|
||||
[dist/commands/config/delete.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.2/dist/commands/config/delete.js)_
|
||||
|
||||
## `hive config:get KEY`
|
||||
|
||||
|
|
@ -73,7 +71,7 @@ prints specific cli configuration
|
|||
|
||||
```
|
||||
USAGE
|
||||
$ hive config:get [KEY]
|
||||
$ hive config:get KEY
|
||||
|
||||
ARGUMENTS
|
||||
KEY config key
|
||||
|
|
@ -83,7 +81,7 @@ DESCRIPTION
|
|||
```
|
||||
|
||||
_See code:
|
||||
[dist/commands/config/get.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.0/dist/commands/config/get.js)_
|
||||
[dist/commands/config/get.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.2/dist/commands/config/get.js)_
|
||||
|
||||
## `hive config:reset`
|
||||
|
||||
|
|
@ -98,7 +96,7 @@ DESCRIPTION
|
|||
```
|
||||
|
||||
_See code:
|
||||
[dist/commands/config/reset.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.0/dist/commands/config/reset.js)_
|
||||
[dist/commands/config/reset.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.2/dist/commands/config/reset.js)_
|
||||
|
||||
## `hive config:set KEY VALUE`
|
||||
|
||||
|
|
@ -106,7 +104,7 @@ updates specific cli configuration
|
|||
|
||||
```
|
||||
USAGE
|
||||
$ hive config:set [KEY] [VALUE]
|
||||
$ hive config:set KEY VALUE
|
||||
|
||||
ARGUMENTS
|
||||
KEY config key
|
||||
|
|
@ -117,7 +115,7 @@ DESCRIPTION
|
|||
```
|
||||
|
||||
_See code:
|
||||
[dist/commands/config/set.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.0/dist/commands/config/set.js)_
|
||||
[dist/commands/config/set.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.2/dist/commands/config/set.js)_
|
||||
|
||||
## `hive help [COMMANDS]`
|
||||
|
||||
|
|
@ -138,7 +136,7 @@ DESCRIPTION
|
|||
```
|
||||
|
||||
_See code:
|
||||
[@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v5.2.4/src/commands/help.ts)_
|
||||
[@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v5.2.6/src/commands/help.ts)_
|
||||
|
||||
## `hive operations:check FILE`
|
||||
|
||||
|
|
@ -146,7 +144,7 @@ checks operations against a published schema
|
|||
|
||||
```
|
||||
USAGE
|
||||
$ hive operations:check [FILE] [--registry <value>] [--token <value>] [--require <value>]
|
||||
$ hive operations:check FILE [--registry <value>] [--token <value>] [--require <value>]
|
||||
|
||||
ARGUMENTS
|
||||
FILE Glob pattern to find the operations
|
||||
|
|
@ -161,7 +159,7 @@ DESCRIPTION
|
|||
```
|
||||
|
||||
_See code:
|
||||
[dist/commands/operations/check.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.0/dist/commands/operations/check.js)_
|
||||
[dist/commands/operations/check.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.2/dist/commands/operations/check.js)_
|
||||
|
||||
## `hive operations:publish FILE`
|
||||
|
||||
|
|
@ -169,7 +167,7 @@ saves operations to the store
|
|||
|
||||
```
|
||||
USAGE
|
||||
$ hive operations:publish [FILE] [--registry <value>] [--token <value>] [--require <value>]
|
||||
$ hive operations:publish FILE [--registry <value>] [--token <value>] [--require <value>]
|
||||
|
||||
ARGUMENTS
|
||||
FILE Glob pattern to find the operations
|
||||
|
|
@ -185,7 +183,7 @@ DESCRIPTION
|
|||
```
|
||||
|
||||
_See code:
|
||||
[dist/commands/operations/publish.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.0/dist/commands/operations/publish.js)_
|
||||
[dist/commands/operations/publish.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.2/dist/commands/operations/publish.js)_
|
||||
|
||||
## `hive schema:check FILE`
|
||||
|
||||
|
|
@ -193,7 +191,7 @@ checks schema
|
|||
|
||||
```
|
||||
USAGE
|
||||
$ hive schema:check [FILE] [--service <value>] [--registry <value>] [--token <value>] [--forceSafe] [--github]
|
||||
$ hive schema:check FILE [--service <value>] [--registry <value>] [--token <value>] [--forceSafe] [--github]
|
||||
[--require <value>]
|
||||
|
||||
ARGUMENTS
|
||||
|
|
@ -213,7 +211,7 @@ DESCRIPTION
|
|||
```
|
||||
|
||||
_See code:
|
||||
[dist/commands/schema/check.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.0/dist/commands/schema/check.js)_
|
||||
[dist/commands/schema/check.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.2/dist/commands/schema/check.js)_
|
||||
|
||||
## `hive schema:delete SERVICE`
|
||||
|
||||
|
|
@ -221,7 +219,7 @@ deletes a schema
|
|||
|
||||
```
|
||||
USAGE
|
||||
$ hive schema:delete [SERVICE] [--registry <value>] [--token <value>] [--dryRun] [--confirm]
|
||||
$ hive schema:delete SERVICE [--registry <value>] [--token <value>] [--dryRun] [--confirm]
|
||||
|
||||
ARGUMENTS
|
||||
SERVICE name of the service
|
||||
|
|
@ -237,7 +235,7 @@ DESCRIPTION
|
|||
```
|
||||
|
||||
_See code:
|
||||
[dist/commands/schema/delete.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.0/dist/commands/schema/delete.js)_
|
||||
[dist/commands/schema/delete.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.2/dist/commands/schema/delete.js)_
|
||||
|
||||
## `hive schema:publish FILE`
|
||||
|
||||
|
|
@ -245,8 +243,8 @@ publishes schema
|
|||
|
||||
```
|
||||
USAGE
|
||||
$ hive schema:publish [FILE] [--service <value>] [--url <value>] [--metadata <value>] [--registry <value>]
|
||||
[--token <value>] [--author <value>] [--commit <value>] [--github] [--force] [--experimental_acceptBreakingChanges]
|
||||
$ hive schema:publish FILE [--service <value>] [--url <value>] [--metadata <value>] [--registry <value>] [--token
|
||||
<value>] [--author <value>] [--commit <value>] [--github] [--force] [--experimental_acceptBreakingChanges]
|
||||
[--require <value>]
|
||||
|
||||
ARGUMENTS
|
||||
|
|
@ -273,7 +271,7 @@ DESCRIPTION
|
|||
```
|
||||
|
||||
_See code:
|
||||
[dist/commands/schema/publish.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.0/dist/commands/schema/publish.js)_
|
||||
[dist/commands/schema/publish.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.2/dist/commands/schema/publish.js)_
|
||||
|
||||
## `hive update [CHANNEL]`
|
||||
|
||||
|
|
@ -311,7 +309,7 @@ EXAMPLES
|
|||
```
|
||||
|
||||
_See code:
|
||||
[@oclif/plugin-update](https://github.com/oclif/plugin-update/blob/v3.1.3/src/commands/update.ts)_
|
||||
[@oclif/plugin-update](https://github.com/oclif/plugin-update/blob/v3.1.6/src/commands/update.ts)_
|
||||
|
||||
## `hive whoami`
|
||||
|
||||
|
|
@ -330,30 +328,25 @@ DESCRIPTION
|
|||
```
|
||||
|
||||
_See code:
|
||||
[dist/commands/whoami.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.0/dist/commands/whoami.js)_
|
||||
[dist/commands/whoami.js](https://github.com/kamilkisiela/graphql-hive/blob/v0.20.2/dist/commands/whoami.js)_
|
||||
|
||||
<!-- commandsstop -->
|
||||
|
||||
<!-- config -->
|
||||
## Configuration
|
||||
|
||||
# Config
|
||||
### Environment Variables
|
||||
|
||||
In addition to using the CLI args, you can also define your configuration in a JSON file which the
|
||||
CLI would pick up when it runs.
|
||||
You may set the `HIVE_TOKEN` environment variable while running the Hive CLI, in order to set it
|
||||
globally.
|
||||
|
||||
You can use the `HIVE_CONFIG` environment variable to define the path to the JSON file as follows:
|
||||
### Config file (`hive.json`)
|
||||
|
||||
`HIVE_CONFIG=/path/to/hive.json hive schema:publish --author Vignesh path/to/file.gql`
|
||||
|
||||
Note that the CLI args will override the values in config if both are specified.
|
||||
|
||||
This is how the structure of the config file should look like:
|
||||
You can create a `hive.json` file to manage your Hive configuration, you may use the following JSON
|
||||
keys:
|
||||
|
||||
```json
|
||||
{
|
||||
"registry": "<yourRegistryURL>",
|
||||
"token": "<yourtoken>"
|
||||
"registry": "<HIVE_REGISTRY_URL_GRAPHQL_ENDPOINT>",
|
||||
"token": "<HIVE_REGISTRY_TOKEN>"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- configstop -->
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ export default gql`
|
|||
id: ID!
|
||||
cleanId: ID!
|
||||
name: String!
|
||||
project: Project!
|
||||
}
|
||||
|
||||
type TargetSettings {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { z } from 'zod';
|
||||
import { createConnection } from '../../shared/schema';
|
||||
import { OrganizationManager } from '../organization/providers/organization-manager';
|
||||
import { ProjectManager } from '../project/providers/project-manager';
|
||||
import { IdTranslator } from '../shared/providers/id-translator';
|
||||
import type { TargetModule } from './__generated__/types';
|
||||
import { TargetManager } from './providers/target-manager';
|
||||
|
|
@ -9,6 +10,13 @@ const TargetNameModel = z.string().min(2).max(30);
|
|||
const PercentageModel = z.number().min(0).max(100);
|
||||
|
||||
export const resolvers: TargetModule.Resolvers = {
|
||||
Target: {
|
||||
project: (target, args, { injector }) =>
|
||||
injector.get(ProjectManager).getProject({
|
||||
project: target.projectId,
|
||||
organization: target.orgId,
|
||||
}),
|
||||
},
|
||||
Query: {
|
||||
async target(_, { selector }, { injector }) {
|
||||
const translator = injector.get(IdTranslator);
|
||||
|
|
|
|||
5
packages/services/cdn-worker/.env.template
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
S3_ENDPOINT=http://localhost:9000
|
||||
S3_ACCESS_KEY_ID="minioadmin"
|
||||
S3_SECRET_ACCESS_KEY="minioadmin"
|
||||
S3_BUCKET_NAME="artifacts"
|
||||
S3_PUBLIC_URL="http://localhost:9000"
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
"@types/service-worker-mock": "2.0.1",
|
||||
"@whatwg-node/fetch": "0.8.2",
|
||||
"@whatwg-node/server": "0.7.4",
|
||||
"dotenv": "16.0.3",
|
||||
"esbuild": "0.17.11",
|
||||
"fastify": "3.29.5",
|
||||
"itty-router": "2.6.6",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'dotenv/config';
|
||||
import { crypto, Headers, ReadableStream, Request, Response } from '@whatwg-node/fetch';
|
||||
|
||||
if (!globalThis.Response) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Hive comes with support for Apollo Federation v2, based on
|
|||
[external composition](https://docs.graphql-hive.com/features/external-schema-composition).
|
||||
|
||||
This package provides a reference for running external composition as a NodeJS service, on your
|
||||
local infrastructure, and connect GraphQL Hive (SaaS or self-service).
|
||||
local infrastructure, and connect GraphQL Hive (Cloud or self-service).
|
||||
|
||||
# Usage
|
||||
|
||||
|
|
@ -31,8 +31,8 @@ docker run -p 3069 -e SECRET="MY_SECRET_HERE" ghcr.io/kamilkisiela/graphql-hive/
|
|||
The container runs on port `3069` by default (you can chnage it using `PORT` env var), and listens
|
||||
to `POST /compose` requests coming from Hive platform.
|
||||
|
||||
You should make this service publicly available and accessible to use it with Hive SaaS platform, or
|
||||
make it availble in your local/private network if you are using Hive on-prem.
|
||||
You should make this service publicly available and accessible to use it with Hive Cloud platform,
|
||||
or make it availble in your local/private network if you are using Hive on-prem.
|
||||
|
||||
## Running from source code
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "@hive/rate-limit",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"description": "A microservice for Hive SaaS, that exposes information about rate limits per given org/target.",
|
||||
"description": "A microservice for Hive Cloud, that exposes information about rate limits per given org/target.",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ INTEGRATION_GITHUB_APP_ID="<sync>"
|
|||
INTEGRATION_GITHUB_APP_PRIVATE_KEY="<sync>"
|
||||
|
||||
# CDN Configuration
|
||||
CDN='1'
|
||||
CDN_CF='1'
|
||||
CDN_CF_BASE_URL=http://localhost:4010
|
||||
CDN_CF_BASE_PATH=http://localhost:4010
|
||||
CDN_CF_ACCOUNT_ID=103df45224310d669213971ce28b5b70
|
||||
CDN_CF_AUTH_TOKEN=85e20c26c03759603c0f45884824a1c3
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ The GraphQL API for GraphQL Hive.
|
|||
|
||||
## Hive Hosted Configuration
|
||||
|
||||
If you are self-hosting GraphQL Hive, you can ignore this section. It is only required for the SaaS
|
||||
If you are self-hosting GraphQL Hive, you can ignore this section. It is only required for the Cloud
|
||||
version.
|
||||
|
||||
| Name | Required | Description | Example Value |
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "@hive/stripe-billing",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"description": "A microservice for Hive SaaS, that syncs usage information to Stripe (metered billing)",
|
||||
"description": "A microservice for Hive Cloud, that syncs usage information to Stripe (metered billing)",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "@hive/usage-estimator",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"description": "A microservice for Hive SaaS, that calculates and exposes usage information.",
|
||||
"description": "A microservice for Hive Cloud, that calculates and exposes usage information.",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import { graphql } from '@/gql';
|
|||
import { CompareDocument, VersionsDocument } from '@/graphql';
|
||||
import { useRouteSelector } from '@/lib/hooks/use-route-selector';
|
||||
import { withSessionProtection } from '@/lib/supertokens/guard';
|
||||
import { CrossCircledIcon, RowsIcon } from '@radix-ui/react-icons';
|
||||
import { CrossCircledIcon, ExternalLinkIcon, RowsIcon } from '@radix-ui/react-icons';
|
||||
|
||||
function DiffView({
|
||||
view,
|
||||
|
|
@ -94,11 +94,13 @@ function DiffView({
|
|||
// URQL's Infinite scrolling pattern
|
||||
// https://formidable.com/open-source/urql/docs/basics/ui-patterns/#infinite-scrolling
|
||||
function ListPage({
|
||||
gitRepository,
|
||||
variables,
|
||||
isLastPage,
|
||||
onLoadMore,
|
||||
versionId,
|
||||
}: {
|
||||
gitRepository?: string;
|
||||
variables: { after: string; limit: number };
|
||||
isLastPage: boolean;
|
||||
onLoadMore: (after: string) => void;
|
||||
|
|
@ -125,36 +127,51 @@ function ListPage({
|
|||
return (
|
||||
<>
|
||||
{versions?.nodes.map(version => (
|
||||
<NextLink
|
||||
key={version.id}
|
||||
href={`/${router.organizationId}/${router.projectId}/${router.targetId}/history/${version.id}`}
|
||||
scroll={false} // disable the scroll to top on page
|
||||
<div
|
||||
className={clsx(
|
||||
'flex flex-col rounded-md p-2.5 hover:bg-gray-800/40',
|
||||
versionId === version.id && 'bg-gray-800/40',
|
||||
)}
|
||||
>
|
||||
<h3 className="truncate font-bold">
|
||||
{'commit' in version.log ? version.log.commit : `Deleted ${version.log.deletedService}`}
|
||||
</h3>
|
||||
{'author' in version.log ? (
|
||||
<div className="truncate text-xs font-medium text-gray-500">
|
||||
<span className="overflow-hidden truncate">{version.log.author}</span>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="mt-2.5 mb-1.5 flex align-middle text-xs font-medium text-[#c4c4c4]">
|
||||
<div className={clsx('w-1/2 ', !version.valid && 'text-red-500')}>
|
||||
<Badge color={version.valid ? 'green' : 'red'} /> Published{' '}
|
||||
<TimeAgo date={version.date} />
|
||||
</div>
|
||||
|
||||
{'service' in version.log && version.log.service ? (
|
||||
<div className="ml-auto mr-0 w-1/2 overflow-hidden text-ellipsis whitespace-nowrap text-right font-bold">
|
||||
{version.log.service}
|
||||
<NextLink
|
||||
key={version.id}
|
||||
href={`/${router.organizationId}/${router.projectId}/${router.targetId}/history/${version.id}`}
|
||||
scroll={false} // disable the scroll to top on page
|
||||
>
|
||||
<h3 className="truncate font-bold">
|
||||
{'commit' in version.log
|
||||
? version.log.commit
|
||||
: `Deleted ${version.log.deletedService}`}
|
||||
</h3>
|
||||
{'author' in version.log ? (
|
||||
<div className="truncate text-xs font-medium text-gray-500">
|
||||
<span className="overflow-hidden truncate">{version.log.author}</span>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</NextLink>
|
||||
<div className="mt-2.5 mb-1.5 flex align-middle text-xs font-medium text-[#c4c4c4]">
|
||||
<div className={clsx('w-1/2 ', !version.valid && 'text-red-500')}>
|
||||
<Badge color={version.valid ? 'green' : 'red'} /> Published{' '}
|
||||
<TimeAgo date={version.date} />
|
||||
</div>
|
||||
|
||||
{'service' in version.log && version.log.service ? (
|
||||
<div className="ml-auto mr-0 w-1/2 overflow-hidden text-ellipsis whitespace-nowrap text-right font-bold">
|
||||
{version.log.service}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</NextLink>
|
||||
{gitRepository && 'commit' in version.log && version.log.commit ? (
|
||||
<a
|
||||
className="text-xs font-medium text-gray-500 hover:text-gray-400"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={`https://github.com/${gitRepository}/commit/${version.log.commit}`}
|
||||
>
|
||||
<ExternalLinkIcon className="inline" /> associated with Git commit
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
))}
|
||||
{isLastPage && hasMore && (
|
||||
<Button
|
||||
|
|
@ -175,7 +192,7 @@ function ListPage({
|
|||
|
||||
type View = 'SDL' | 'list';
|
||||
|
||||
function Page({ versionId }: { versionId: string }) {
|
||||
function Page({ versionId, gitRepository }: { versionId: string; gitRepository?: string }) {
|
||||
const [pageVariables, setPageVariables] = useState([{ limit: 10, after: '' }]);
|
||||
|
||||
const [view, setView] = useState<View>('list');
|
||||
|
|
@ -190,6 +207,7 @@ function Page({ versionId }: { versionId: string }) {
|
|||
<div className="flex h-0 min-w-[420px] grow flex-col gap-2.5 overflow-y-auto rounded-md border border-gray-800/50 p-2.5">
|
||||
{pageVariables.map((variables, i) => (
|
||||
<ListPage
|
||||
gitRepository={gitRepository}
|
||||
key={variables.after}
|
||||
variables={variables}
|
||||
isLastPage={i === pageVariables.length - 1}
|
||||
|
|
@ -242,6 +260,7 @@ const TargetHistoryPageQuery = graphql(`
|
|||
}
|
||||
project(selector: { organization: $organizationId, project: $projectId }) {
|
||||
...TargetLayout_ProjectFragment
|
||||
gitRepository
|
||||
}
|
||||
targets(selector: { organization: $organizationId, project: $projectId }) {
|
||||
...TargetLayout_TargetConnectionFragment
|
||||
|
|
@ -267,9 +286,13 @@ function HistoryPage(): ReactElement {
|
|||
className="flex h-full items-stretch gap-x-5"
|
||||
query={TargetHistoryPageQuery}
|
||||
>
|
||||
{({ target }) => {
|
||||
{({ target, project }) => {
|
||||
const versionId = router.versionId ?? target?.latestSchemaVersion?.id;
|
||||
return versionId ? <Page versionId={versionId} /> : noSchemaVersion;
|
||||
return versionId ? (
|
||||
<Page gitRepository={project?.gitRepository ?? undefined} versionId={versionId} />
|
||||
) : (
|
||||
noSchemaVersion
|
||||
);
|
||||
}}
|
||||
</TargetLayout>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { ReactElement } from 'react';
|
|||
import { GraphiQL } from 'graphiql';
|
||||
import { authenticated } from '@/components/authenticated-container';
|
||||
import { TargetLayout } from '@/components/layouts';
|
||||
import { Button, Title } from '@/components/v2';
|
||||
import { Button, DocsLink, DocsNote, Title } from '@/components/v2';
|
||||
import { HiveLogo, Link2Icon } from '@/components/v2/icon';
|
||||
import { ConnectLabModal } from '@/components/v2/modals/connect-lab';
|
||||
import { graphql } from '@/gql';
|
||||
|
|
@ -14,13 +14,14 @@ import 'graphiql/graphiql.css';
|
|||
const Page = ({ endpoint }: { endpoint: string }): ReactElement => {
|
||||
return (
|
||||
<>
|
||||
<p className="mb-5 font-light text-gray-500">
|
||||
Experiment, mock and create live environment for your schema, without running any backend.
|
||||
</p>
|
||||
<DocsNote>
|
||||
Explore your GraphQL schema and run queries against a mocked version of your GraphQL
|
||||
service. <DocsLink href="/features/laboratory">Learn more about the Laboratory</DocsLink>
|
||||
</DocsNote>
|
||||
<style global jsx>{`
|
||||
body.graphiql-dark .graphiql-container {
|
||||
--color-base: transparent;
|
||||
--color-primary: 40, 89%, 60%;
|
||||
.graphiql-container {
|
||||
--color-base: transparent !important;
|
||||
--color-primary: 40, 89%, 60% !important;
|
||||
}
|
||||
`}</style>
|
||||
<GraphiQL fetcher={createGraphiQLFetcher({ url: endpoint })}>
|
||||
|
|
@ -67,7 +68,7 @@ function LaboratoryPage(): ReactElement {
|
|||
connect={
|
||||
<>
|
||||
<Button size="large" variant="primary" onClick={toggleModalOpen} className="ml-auto">
|
||||
Connect
|
||||
Use Schema Externally
|
||||
<Link2Icon className="ml-8 h-4 w-4" />
|
||||
</Button>
|
||||
<ConnectLabModal
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import { OperationsList } from '@/components/target/operations/List';
|
|||
import { OperationsStats } from '@/components/target/operations/Stats';
|
||||
import { EmptyList, RadixSelect, Title } from '@/components/v2';
|
||||
import { graphql } from '@/gql';
|
||||
import { getDocsUrl } from '@/lib/docs-url';
|
||||
import { withSessionProtection } from '@/lib/supertokens/guard';
|
||||
|
||||
function floorDate(date: Date): Date {
|
||||
|
|
@ -131,9 +130,6 @@ function OperationsPage(): ReactElement {
|
|||
{({ organization, project, target, hasCollectedOperations }) =>
|
||||
organization && project && target ? (
|
||||
<div className="relative">
|
||||
<p className="mb-5 font-light text-gray-500">
|
||||
Data collected based on operation executed against your GraphQL schema.
|
||||
</p>
|
||||
{hasCollectedOperations ? (
|
||||
<OperationsView
|
||||
organizationCleanId={organization.organization.cleanId}
|
||||
|
|
@ -144,7 +140,7 @@ function OperationsPage(): ReactElement {
|
|||
<EmptyList
|
||||
title="Hive is waiting for your first collected operation"
|
||||
description="You can collect usage of your GraphQL API with Hive Client"
|
||||
docsUrl={getDocsUrl('/features/monitoring')}
|
||||
docsUrl="/features/usage-reporting"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import {
|
|||
Button,
|
||||
Card,
|
||||
Checkbox,
|
||||
DocsLink,
|
||||
DocsNote,
|
||||
Heading,
|
||||
Input,
|
||||
Spinner,
|
||||
|
|
@ -25,7 +27,6 @@ import {
|
|||
Tr,
|
||||
} from '@/components/v2';
|
||||
import { Combobox } from '@/components/v2/combobox';
|
||||
import { AlertTriangleIcon } from '@/components/v2/icon';
|
||||
import { CreateAccessTokenModal, DeleteTargetModal } from '@/components/v2/modals';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { DeleteTokensDocument, SetTargetValidationDocument, TokensDocument } from '@/graphql';
|
||||
|
|
@ -81,6 +82,14 @@ function RegistryAccessTokens(props: {
|
|||
<p className="mb-3 font-light text-gray-300">
|
||||
Be careful! These tokens allow to read and write your target data.
|
||||
</p>
|
||||
<DocsNote>
|
||||
Registry Access Tokens are used to access to Hive Registry and perform actions on your
|
||||
targets/projects. In most cases, this token is used from the Hive CLI.
|
||||
<br />
|
||||
<DocsLink href="/management/targets#registry-access-tokens">
|
||||
Learn more about Registry Access Token
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
{canManage && (
|
||||
<div className="my-3.5 flex justify-between">
|
||||
<Button variant="secondary" onClick={toggleModalOpen} size="large" className="px-5">
|
||||
|
|
@ -162,11 +171,14 @@ const ExtendBaseSchema = (props: { baseSchema: string }): ReactElement => {
|
|||
return (
|
||||
<Card>
|
||||
<Heading className="mb-2">Extend Your Schema</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">
|
||||
Define a piece of SDL that will be added to every published schema.
|
||||
<DocsNote>
|
||||
Schema Extensions is pre-defined GraphQL schema that is automatically merged with your
|
||||
published schemas, before being checked and validated.
|
||||
<br />
|
||||
Useful for AWS AppSync users to not send platform-specific part of schema to Hive.
|
||||
</p>
|
||||
<DocsLink href="/management/targets#schema-extensions">
|
||||
You can find more details and examples in the documentation
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
<SchemaEditor
|
||||
theme="vs-dark"
|
||||
options={{ readOnly: mutation.fetching }}
|
||||
|
|
@ -424,9 +436,14 @@ const ConditionalBreakingChanges = (): ReactElement => {
|
|||
/>
|
||||
)}
|
||||
</Heading>
|
||||
<DocsNote>
|
||||
Conditional Breaking Changes can change the behavior of schema checks, based on real
|
||||
traffic data sent to Hive.{' '}
|
||||
<DocsLink href="/management/targets#conditional-breaking-changes">Learn more</DocsLink>
|
||||
</DocsNote>
|
||||
<div
|
||||
className={clsx(
|
||||
'mb-3 flex flex-col items-start gap-3 font-light text-gray-300',
|
||||
'mb-3 mt-4 flex flex-col items-start gap-3 font-light text-gray-300',
|
||||
!isEnabled && 'pointer-events-none opacity-25',
|
||||
)}
|
||||
>
|
||||
|
|
@ -652,10 +669,15 @@ const Page = (props: {
|
|||
return (
|
||||
<>
|
||||
<Card>
|
||||
<Heading className="mb-2">Target Info</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">
|
||||
Name of your target visible within organization.
|
||||
</p>
|
||||
<Heading className="mb-2">Target Name</Heading>
|
||||
<DocsNote warn>
|
||||
Changing the name of your target will also change the slug of your target URL, and will
|
||||
invalidate any existing links to your target.
|
||||
<br />
|
||||
<DocsLink href="/management/targets#rename-a-target">
|
||||
You can read more about it in the documentation
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
<form onSubmit={handleSubmit} className="flex gap-x-2">
|
||||
<Input
|
||||
placeholder="Target name"
|
||||
|
|
@ -699,22 +721,29 @@ const Page = (props: {
|
|||
|
||||
{canDelete && (
|
||||
<Card>
|
||||
<Heading className="mb-2">Delete Target</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">Permanently remove your Target</p>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<Button
|
||||
variant="primary"
|
||||
size="large"
|
||||
danger
|
||||
onClick={toggleModalOpen}
|
||||
className="px-5"
|
||||
>
|
||||
Delete Target
|
||||
</Button>
|
||||
<Tag color="yellow" className="py-2.5 px-4">
|
||||
<AlertTriangleIcon className="h-5 w-5" />
|
||||
This action is not reversible!
|
||||
</Tag>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<Heading className="mb-2">Delete Target</Heading>
|
||||
<DocsNote warn>
|
||||
Deleting an project also delete all schemas and data associated with it.
|
||||
<br />
|
||||
<DocsLink href="/management/targets#delete-a-target">
|
||||
<strong>This action is not reversible!</strong> You can find more information
|
||||
about this process in the documentation
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
</div>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<Button
|
||||
variant="primary"
|
||||
size="large"
|
||||
danger
|
||||
onClick={toggleModalOpen}
|
||||
className="px-5"
|
||||
>
|
||||
Delete Target
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import {
|
|||
import { LinkIcon, MoreIcon, SettingsIcon } from '@/components/v2/icon';
|
||||
import { graphql } from '@/gql';
|
||||
import { TargetQuery, TargetsDocument, VersionsDocument } from '@/graphql';
|
||||
import { getDocsUrl } from '@/lib/docs-url';
|
||||
import { useClipboard } from '@/lib/hooks/use-clipboard';
|
||||
import { useRouteSelector } from '@/lib/hooks/use-route-selector';
|
||||
import { withSessionProtection } from '@/lib/supertokens/guard';
|
||||
|
|
@ -130,7 +129,7 @@ const Page = () => {
|
|||
<EmptyList
|
||||
title="Hive is waiting for your first target"
|
||||
description='You can create a target by clicking the "New Target" button'
|
||||
docsUrl={getDocsUrl('/get-started/targets')}
|
||||
docsUrl="/management/targets#create-a-new-target"
|
||||
/>
|
||||
) : (
|
||||
targets?.nodes.map(target => <TargetCard key={target.id} target={target} />)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,20 @@ import { ReactElement, useState } from 'react';
|
|||
import { useMutation, useQuery } from 'urql';
|
||||
import { authenticated } from '@/components/authenticated-container';
|
||||
import { ProjectLayout } from '@/components/layouts';
|
||||
import { Button, Card, Checkbox, Heading, Table, Tag, TBody, Td, Title, Tr } from '@/components/v2';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Checkbox,
|
||||
DocsLink,
|
||||
DocsNote,
|
||||
Heading,
|
||||
Table,
|
||||
Tag,
|
||||
TBody,
|
||||
Td,
|
||||
Title,
|
||||
Tr,
|
||||
} from '@/components/v2';
|
||||
import { CreateAlertModal, CreateChannelModal } from '@/components/v2/modals';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import {
|
||||
|
|
@ -37,7 +50,11 @@ function Channels(): ReactElement {
|
|||
return (
|
||||
<Card>
|
||||
<Heading className="mb-2">Available Channels</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">Channel represents a form of communication</p>
|
||||
<DocsNote>
|
||||
Alert Channels are a way to configure <strong>how</strong> you want to receive alerts and
|
||||
notifications from Hive.{' '}
|
||||
<DocsLink href="/management/projects#alert-channels">Learn more</DocsLink>
|
||||
</DocsNote>
|
||||
<Table>
|
||||
<TBody>
|
||||
{channelAlerts.map(channelAlert => (
|
||||
|
|
@ -139,8 +156,12 @@ const Page = (props: {
|
|||
<>
|
||||
<Channels />
|
||||
<Card>
|
||||
<Heading className="mb-2">Active Alerts</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">Alerts are sent over the Channels</p>
|
||||
<Heading className="mb-2">Active Alerts and Notifications</Heading>
|
||||
<DocsNote>
|
||||
Alerts are a way to configure <strong>when</strong> you want to receive alerts and
|
||||
notifications from Hive.{' '}
|
||||
<DocsLink href="/management/projects#alerts-and-notifications-1">Learn more</DocsLink>
|
||||
</DocsNote>
|
||||
<Table>
|
||||
<TBody>
|
||||
{alerts.map(alert => (
|
||||
|
|
|
|||
|
|
@ -6,8 +6,18 @@ import { authenticated } from '@/components/authenticated-container';
|
|||
import { ProjectLayout } from '@/components/layouts';
|
||||
import { ExternalCompositionSettings } from '@/components/project/settings/external-composition';
|
||||
import { ModelMigrationSettings } from '@/components/project/settings/model-migration';
|
||||
import { Button, Card, Heading, Input, Link, Select, Tag, Title } from '@/components/v2';
|
||||
import { AlertTriangleIcon } from '@/components/v2/icon';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
DocsLink,
|
||||
DocsNote,
|
||||
Heading,
|
||||
Input,
|
||||
Link,
|
||||
Select,
|
||||
Tag,
|
||||
Title,
|
||||
} from '@/components/v2';
|
||||
import { DeleteProjectModal } from '@/components/v2/modals';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { GetGitHubIntegrationDetailsDocument, ProjectType } from '@/graphql';
|
||||
|
|
@ -212,9 +222,14 @@ const Page = (props: {
|
|||
<ModelMigrationSettings project={project} organizationId={organization.cleanId} />
|
||||
<Card>
|
||||
<Heading className="mb-2">Project Name</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">
|
||||
Name of your project visible within organization
|
||||
</p>
|
||||
<DocsNote warn>
|
||||
Changing the name of your project will also change the slug of your project URL, and will
|
||||
invalidate any existing links to your project.
|
||||
<br />
|
||||
<DocsLink href="/management/projects#rename-a-project">
|
||||
You can read more about it in the documentation
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
<form onSubmit={handleSubmit} className="flex gap-x-2">
|
||||
<Input
|
||||
placeholder="Project name"
|
||||
|
|
@ -248,9 +263,14 @@ const Page = (props: {
|
|||
|
||||
<Card>
|
||||
<Heading className="mb-2">Git Repository</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">
|
||||
Connect the project with your Git repository
|
||||
</p>
|
||||
<DocsNote>
|
||||
Associate your project with a Git repository to enable commit linking and to allow CI
|
||||
integration.
|
||||
<br />
|
||||
<DocsLink href="/management/projects#github-repository">
|
||||
Learn more about GitHub integration
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
<GitHubIntegration gitRepository={project.gitRepository ?? null} />
|
||||
</Card>
|
||||
|
||||
|
|
@ -260,24 +280,30 @@ const Page = (props: {
|
|||
|
||||
{canAccessProject(ProjectAccessScope.Delete, organization.me) && (
|
||||
<Card>
|
||||
<Heading className="mb-2">Delete Project</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">
|
||||
Permanently remove your Project and all targets from the Organization
|
||||
</p>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<Button
|
||||
variant="primary"
|
||||
size="large"
|
||||
danger
|
||||
onClick={toggleModalOpen}
|
||||
className="px-5"
|
||||
>
|
||||
Delete Project
|
||||
</Button>
|
||||
<Tag color="yellow" className="py-2.5 px-4">
|
||||
<AlertTriangleIcon className="h-5 w-5" />
|
||||
This action is not reversible!
|
||||
</Tag>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<Heading className="mb-2">Delete Project</Heading>
|
||||
<DocsNote warn>
|
||||
Deleting an project will delete all the targets, schemas and data associated with
|
||||
it.
|
||||
<br />
|
||||
<DocsLink href="/management/projects#delete-a-project">
|
||||
<strong>This action is not reversible!</strong> You can find more information
|
||||
about this process in the documentation
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
</div>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<Button
|
||||
variant="primary"
|
||||
size="large"
|
||||
danger
|
||||
onClick={toggleModalOpen}
|
||||
className="px-5"
|
||||
>
|
||||
Delete Project
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ import { FragmentType, graphql, useFragment } from '@/gql';
|
|||
import { ProjectActivitiesDocument } from '@/graphql';
|
||||
import { canAccessProject, ProjectAccessScope } from '@/lib/access/project';
|
||||
import { writeLastVisitedOrganization } from '@/lib/cookies';
|
||||
import { getDocsUrl } from '@/lib/docs-url';
|
||||
import { fixDuplicatedFragments } from '@/lib/graphql';
|
||||
import { useClipboard } from '@/lib/hooks/use-clipboard';
|
||||
import { useRouteSelector } from '@/lib/hooks/use-route-selector';
|
||||
|
|
@ -162,7 +161,7 @@ function ProjectsPage(): ReactElement {
|
|||
<EmptyList
|
||||
title="Hive is waiting for your first project"
|
||||
description='You can create a project by clicking the "Create Project" button'
|
||||
docsUrl={getDocsUrl('/get-started/projects')}
|
||||
docsUrl="/management/projects#create-a-new-project"
|
||||
/>
|
||||
) : (
|
||||
<div className="grid grid-cols-2 gap-5 items-stretch">
|
||||
|
|
|
|||
|
|
@ -4,7 +4,17 @@ import { useMutation, useQuery } from 'urql';
|
|||
import * as Yup from 'yup';
|
||||
import { authenticated } from '@/components/authenticated-container';
|
||||
import { OrganizationLayout } from '@/components/layouts';
|
||||
import { Avatar, Button, Card, Checkbox, Input, Title } from '@/components/v2';
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
Card,
|
||||
Checkbox,
|
||||
DocsLink,
|
||||
DocsNote,
|
||||
Heading,
|
||||
Input,
|
||||
Title,
|
||||
} from '@/components/v2';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
|
|
@ -256,7 +266,7 @@ const OrganizationInvitations = (props: {
|
|||
|
||||
return org.invitations.nodes.length ? (
|
||||
<div className="pt-3">
|
||||
<div className="border-t-4 border-solid pb-6" />
|
||||
<Heading className="mb-2">Pending Invitations</Heading>
|
||||
{org.invitations.nodes.map(node => (
|
||||
<Invitation key={node.id} invitation={node} organizationCleanId={org.cleanId} />
|
||||
))}
|
||||
|
|
@ -300,9 +310,12 @@ function Page(props: { organization: FragmentType<typeof Page_OrganizationFragme
|
|||
|
||||
return (
|
||||
<>
|
||||
<p className="mb-3 font-light text-gray-300">
|
||||
Invite others to your organization and manage access
|
||||
</p>
|
||||
<DocsNote>
|
||||
You may invite other members to collaborate with you on this organization.{' '}
|
||||
<DocsLink href="/management/organizations#members">
|
||||
Learn more about membership and invitations
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
{selectedMember && (
|
||||
<ChangePermissionsModal
|
||||
isOpen={isPermissionsModalOpen}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import * as Yup from 'yup';
|
|||
import { authenticated } from '@/components/authenticated-container';
|
||||
import { OrganizationLayout } from '@/components/layouts';
|
||||
import { OIDCIntegrationSection } from '@/components/organization/settings/oidc-integration-section';
|
||||
import { Button, Card, Heading, Input, Tag, Title } from '@/components/v2';
|
||||
import { AlertTriangleIcon, GitHubIcon, SlackIcon } from '@/components/v2/icon';
|
||||
import { Button, Card, DocsLink, DocsNote, Heading, Input, Tag, Title } from '@/components/v2';
|
||||
import { GitHubIcon, SlackIcon } from '@/components/v2/icon';
|
||||
import {
|
||||
DeleteOrganizationModal,
|
||||
TransferOrganizationOwnershipModal,
|
||||
|
|
@ -197,9 +197,6 @@ const SettingsPageRenderer = (props: {
|
|||
<>
|
||||
<Card>
|
||||
<Heading className="mb-2">Organization Name</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">
|
||||
Name of your organization visible within Hive
|
||||
</p>
|
||||
<form onSubmit={handleSubmit} className="flex gap-x-2">
|
||||
<Input
|
||||
placeholder="Organization name"
|
||||
|
|
@ -232,12 +229,27 @@ const SettingsPageRenderer = (props: {
|
|||
{mutation.error && (
|
||||
<div>{mutation.error.graphQLErrors[0]?.message ?? mutation.error.message}</div>
|
||||
)}
|
||||
<DocsNote warn>
|
||||
Changing the name of your organization will also change the slug of your organization URL,
|
||||
and will invalidate any existing links to your organization.
|
||||
<br />
|
||||
<DocsLink href="/management/organizations#rename-an-organization">
|
||||
You can read more about it in the documentation
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
</Card>
|
||||
|
||||
{canAccessOrganization(OrganizationAccessScope.Integrations, organization.me) && (
|
||||
<Card>
|
||||
<Heading className="mb-2">Integrations</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">Connect Hive to other services</p>
|
||||
<DocsNote>
|
||||
Authorize external services to make them available for your the projects under this
|
||||
organization.
|
||||
<br />
|
||||
<DocsLink href="/management/organizations#integrations">
|
||||
You can find here instructions and full documentation for the available integration
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
<div className="flex flex-col gap-y-4 text-gray-500">
|
||||
<Integrations />
|
||||
</div>
|
||||
|
|
@ -249,7 +261,14 @@ const SettingsPageRenderer = (props: {
|
|||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<Heading className="mb-2">Transfer Ownership</Heading>
|
||||
<p className="font-light text-gray-300">Transfer this organization to another user</p>
|
||||
<DocsNote>
|
||||
<strong>You are currently the owner of the organization.</strong> You can transfer
|
||||
the organization to another member of the organization, or to an external user.
|
||||
<br />
|
||||
<DocsLink href="/management/organizations#transfer-ownership">
|
||||
Learn more about the process
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
|
|
@ -259,7 +278,7 @@ const SettingsPageRenderer = (props: {
|
|||
onClick={toggleTransferModalOpen}
|
||||
className="px-5"
|
||||
>
|
||||
Transfer
|
||||
Transfer Ownership
|
||||
</Button>
|
||||
<TransferOrganizationOwnershipModal
|
||||
isOpen={isTransferModalOpen}
|
||||
|
|
@ -276,13 +295,17 @@ const SettingsPageRenderer = (props: {
|
|||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<Heading className="mb-2">Delete Organization</Heading>
|
||||
<p className="font-light text-gray-300">Permanently remove your organization</p>
|
||||
<DocsNote warn>
|
||||
Deleting an organization will delete all the projects, targets, schemas and data
|
||||
associated with it.
|
||||
<br />
|
||||
<DocsLink href="/management/organizations#delete-an-organization">
|
||||
<strong>This action is not reversible!</strong> You can find more information
|
||||
about this process in the documentation
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
</div>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<Tag color="yellow" className="py-2.5 px-4">
|
||||
<AlertTriangleIcon className="h-5 w-5" />
|
||||
This action is not reversible!
|
||||
</Tag>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="large"
|
||||
|
|
|
|||
|
|
@ -80,12 +80,9 @@ function Page(props: {
|
|||
</Tabs.Trigger>
|
||||
</Tabs.List>
|
||||
<Tabs.Content value="overview">
|
||||
<p className="mb-3 font-light text-gray-300">
|
||||
Information about your Hive plan, subscription, usage and data ingestion
|
||||
</p>
|
||||
<RateLimitWarn organization={organization} />
|
||||
<Card className="mt-8">
|
||||
<Heading className="mb-2">Plan and Reserved Volume</Heading>
|
||||
<Heading className="mb-2">Your current plan</Heading>
|
||||
<div>
|
||||
<BillingView organization={organization} query={query}>
|
||||
{organization.billingConfiguration?.upcomingInvoice && (
|
||||
|
|
|
|||
|
|
@ -233,6 +233,7 @@ function Inner(props: {
|
|||
<Card className="w-full">
|
||||
<Heading className="mb-4">Choose Your Plan</Heading>
|
||||
<BillingPlanPicker
|
||||
disabled={organization.plan === BillingPlanType.Enterprise}
|
||||
activePlan={organization.plan}
|
||||
value={plan}
|
||||
plans={billingPlans}
|
||||
|
|
|
|||
|
|
@ -77,28 +77,37 @@ function GetStartedWizard({
|
|||
<Drawer.Title>Get Started</Drawer.Title>
|
||||
<p>Complete these steps to experience the full power of GraphQL Hive</p>
|
||||
<div className="mt-4 flex flex-col divide-y-2 divide-gray-900">
|
||||
<Task link={getDocsUrl('/get-started/projects')} completed={tasks.creatingProject}>
|
||||
<Task
|
||||
link={getDocsUrl('/management/projects#create-a-new-project')}
|
||||
completed={tasks.creatingProject}
|
||||
>
|
||||
Create a project
|
||||
</Task>
|
||||
<Task link={getDocsUrl('/features/publish-schema')} completed={tasks.publishingSchema}>
|
||||
<Task
|
||||
link={getDocsUrl('/features/schema-registry#publish-a-schema')}
|
||||
completed={tasks.publishingSchema}
|
||||
>
|
||||
Publish a schema
|
||||
</Task>
|
||||
<Task link={getDocsUrl('/features/checking-schema')} completed={tasks.checkingSchema}>
|
||||
<Task
|
||||
link={getDocsUrl('/features/schema-registry#check-a-schema')}
|
||||
completed={tasks.checkingSchema}
|
||||
>
|
||||
Check a schema
|
||||
</Task>
|
||||
{'invitingMembers' in tasks && typeof tasks.invitingMembers === 'boolean' ? (
|
||||
<Task
|
||||
link={getDocsUrl('/get-started/organizations#members')}
|
||||
link={getDocsUrl('/management/organizations#members')}
|
||||
completed={tasks.invitingMembers}
|
||||
>
|
||||
Invite members
|
||||
</Task>
|
||||
) : null}
|
||||
<Task link={getDocsUrl('/features/monitoring')} completed={tasks.reportingOperations}>
|
||||
<Task link={getDocsUrl('/features/usage-reporting')} completed={tasks.reportingOperations}>
|
||||
Report operations
|
||||
</Task>
|
||||
<Task
|
||||
link={getDocsUrl('/features/checking-schema#with-usage-enabled')}
|
||||
link={getDocsUrl('/management/targets#conditional-breaking-changes')}
|
||||
completed={tasks.enablingUsageBasedBreakingChanges}
|
||||
>
|
||||
Enable usage-based breaking changes
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ export const TargetLayout = <
|
|||
onClick={toggleModalOpen}
|
||||
className="ml-auto"
|
||||
>
|
||||
Connect
|
||||
Connect to CDN
|
||||
<Link2Icon className="ml-8 h-4 w-4" />
|
||||
</Button>
|
||||
<ConnectSchemaModal isOpen={isModalOpen} toggleModalOpen={toggleModalOpen} />
|
||||
|
|
|
|||
|
|
@ -117,8 +117,10 @@ export function BillingPlanPicker({
|
|||
value,
|
||||
onPlanChange,
|
||||
activePlan,
|
||||
disabled,
|
||||
...props
|
||||
}: {
|
||||
disabled?: boolean;
|
||||
value: BillingPlanType;
|
||||
activePlan: BillingPlanType;
|
||||
plans: ReadonlyArray<FragmentType<typeof BillingPlanPicker_PlanFragment>>;
|
||||
|
|
@ -128,7 +130,12 @@ export function BillingPlanPicker({
|
|||
return (
|
||||
<RadioGroup value={value} onValueChange={onPlanChange} className="flex gap-4 md:!flex-row">
|
||||
{plans.map(plan => (
|
||||
<Radio value={plan.planType} key={plan.id} className="!rounded-md border p-4 md:w-1/3">
|
||||
<Radio
|
||||
disabled={disabled}
|
||||
value={plan.planType}
|
||||
key={plan.id}
|
||||
className="!rounded-md border p-4 md:w-1/3"
|
||||
>
|
||||
<Plan
|
||||
key={plan.id}
|
||||
name={plan.name}
|
||||
|
|
|
|||
|
|
@ -94,10 +94,8 @@ export function PlanSummary({
|
|||
<Stat.Label>Plan Type</Stat.Label>
|
||||
<Stat.Number>{plan.planType}</Stat.Number>
|
||||
<Stat.HelpText>
|
||||
Enterprise plan is for organizations that needs to ship and ingest large amount of data.
|
||||
<br />
|
||||
If you wish to upgrade to Enterprise, or you can't find the plan for you, please contact
|
||||
us and we'll find the right plan for your organization.
|
||||
Enterprise plan is for organizations that needs to ship and ingest large amount of data,
|
||||
and needs ongoing support around GraphQL APIs.
|
||||
</Stat.HelpText>
|
||||
</Stat>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,17 @@ import { useCallback, useState } from 'react';
|
|||
import { useFormik } from 'formik';
|
||||
import { useMutation, useQuery } from 'urql';
|
||||
import * as Yup from 'yup';
|
||||
import { Button, Card, Heading, Input, Spinner, Switch, Tooltip } from '@/components/v2';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
DocsLink,
|
||||
DocsNote,
|
||||
Heading,
|
||||
Input,
|
||||
Spinner,
|
||||
Switch,
|
||||
Tooltip,
|
||||
} from '@/components/v2';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { useNotifications } from '@/lib/hooks';
|
||||
import { CheckIcon, Cross2Icon, UpdateIcon } from '@radix-ui/react-icons';
|
||||
|
|
@ -332,9 +342,13 @@ export const ExternalCompositionSettings = (props: {
|
|||
)}
|
||||
</div>
|
||||
</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">
|
||||
Compose and validate schema outside GraphQL Hive
|
||||
</p>
|
||||
<DocsNote>
|
||||
External Schema Composition is required for using Apollo Federation 2 with Hive.
|
||||
<br />
|
||||
<DocsLink href="/management/external-schema-composition">
|
||||
Learn more about Apollo Federation 2 support
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
{isFormVisible ? (
|
||||
<ExternalCompositionForm
|
||||
project={project}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import * as Yup from 'yup';
|
|||
import {
|
||||
Button,
|
||||
Card,
|
||||
DocsLink,
|
||||
DocsNote,
|
||||
Heading,
|
||||
Input,
|
||||
Modal,
|
||||
|
|
@ -111,7 +113,7 @@ function CreateCDNAccessTokenModal(props: {
|
|||
|
||||
<div className="mt-auto flex w-full gap-2 self-end">
|
||||
<Button size="large" className="ml-auto" onClick={props.onClose}>
|
||||
Abort
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
|
|
@ -224,7 +226,7 @@ function DeleteCDNAccessTokenModal(props: {
|
|||
|
||||
<div className="mt-auto flex w-full gap-2 self-end">
|
||||
<Button variant="primary" size="large" className="ml-auto" onClick={onClose}>
|
||||
Abort
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
disabled={deleteCdnAccessToken.fetching}
|
||||
|
|
@ -380,9 +382,14 @@ export function CDNAccessTokens(props: {
|
|||
<Heading id="cdn-access-tokens" className="mb-2">
|
||||
CDN Access Token
|
||||
</Heading>
|
||||
<p className="mb-3 font-light text-gray-300">
|
||||
Be careful! These tokens allow accessing the schema artifacts of your target.
|
||||
</p>
|
||||
<DocsNote>
|
||||
CDN Access Tokens are used to access to Hive High-Availability CDN and read your schema
|
||||
artifacts.
|
||||
<br />
|
||||
<DocsLink href="/management/targets#cdn-access-tokens">
|
||||
Learn more about CDN Access Token
|
||||
</DocsLink>
|
||||
</DocsNote>
|
||||
{canManage && (
|
||||
<div className="my-3.5 flex justify-between">
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { ReactElement, ReactNode } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { Fallback, Image, Root } from '@radix-ui/react-avatar';
|
||||
import { Image, Root } from '@radix-ui/react-avatar';
|
||||
import { PersonIcon } from '@radix-ui/react-icons';
|
||||
|
||||
type Size = 'lg' | 'md' | 'sm' | 'xs';
|
||||
// 50 40 34 20
|
||||
|
|
@ -18,7 +19,6 @@ export const Avatar = ({
|
|||
alt,
|
||||
shape = 'square',
|
||||
size = 'md',
|
||||
fallback,
|
||||
className,
|
||||
...props
|
||||
}: AvatarProps & { className?: string }): ReactElement => {
|
||||
|
|
@ -38,8 +38,17 @@ export const Avatar = ({
|
|||
)}
|
||||
{...props}
|
||||
>
|
||||
<Image src={src ?? undefined} alt={alt} className="drag-none h-full w-full object-cover" />
|
||||
{fallback && <Fallback delayMs={500}>{fallback}</Fallback>}
|
||||
{src ? (
|
||||
<>
|
||||
<Image
|
||||
src={src ?? undefined}
|
||||
alt={alt}
|
||||
className="drag-none h-full w-full object-cover"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<PersonIcon />
|
||||
)}
|
||||
</Root>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
29
packages/web/app/src/components/v2/docs-note.tsx
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import { getDocsUrl } from '@/lib/docs-url';
|
||||
import { ExclamationTriangleIcon, ExternalLinkIcon, InfoCircledIcon } from '@radix-ui/react-icons';
|
||||
import { Link } from './link';
|
||||
|
||||
export const DocsNote = ({ children, warn }: { warn?: boolean; children: React.ReactNode }) => {
|
||||
return (
|
||||
<div className="flex my-2">
|
||||
<div className="items-center align-middle pr-2 flex">
|
||||
{warn ? (
|
||||
<ExclamationTriangleIcon className="text-orange-500" />
|
||||
) : (
|
||||
<InfoCircledIcon className="text-current" />
|
||||
)}
|
||||
</div>
|
||||
<div className="grow text-gray-500 text-sm align-middle">{children}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const DocsLink = ({ href, children }: { href: string; children: React.ReactNode }) => {
|
||||
const fullUrl = getDocsUrl(href) || 'https://docs.graphql-hive.com/';
|
||||
|
||||
return (
|
||||
<Link className="text-orange-500" href={fullUrl} target="_blank" rel="noreferrer">
|
||||
{children}
|
||||
<ExternalLinkIcon className="inline pl-1" />
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import { ReactElement } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { Card, Heading, Link } from '@/components/v2/index';
|
||||
import { getDocsUrl } from '@/lib/docs-url';
|
||||
import { Card, DocsLink, Heading } from '@/components/v2/index';
|
||||
import magnifier from '../../../public/images/figures/magnifier.svg';
|
||||
|
||||
export const EmptyList = ({
|
||||
|
|
@ -25,9 +24,7 @@ export const EmptyList = ({
|
|||
<Heading>{title}</Heading>
|
||||
<span className="text-center text-sm font-medium text-gray-500">{description}</span>
|
||||
{docsUrl === null ? null : (
|
||||
<Link variant="primary" href={docsUrl} target="_blank" rel="noreferrer" className="my-5">
|
||||
Read about it in the documentation
|
||||
</Link>
|
||||
<DocsLink href={docsUrl}>Read about it in the documentation</DocsLink>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -37,7 +34,7 @@ export const noSchema = (
|
|||
<EmptyList
|
||||
title="Schema Registry contains no schema"
|
||||
description="You can publish a schema with Hive CLI and Hive Client"
|
||||
docsUrl={getDocsUrl('/features/publish-schema')}
|
||||
docsUrl="/features/schema-registry#publish-a-schema"
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
@ -45,6 +42,6 @@ export const noSchemaVersion = (
|
|||
<EmptyList
|
||||
title="Hive is waiting for your first schema"
|
||||
description="You can publish a schema with Hive CLI and Hive Client"
|
||||
docsUrl={getDocsUrl('/features/publish-schema')}
|
||||
docsUrl="/features/schema-registry#publish-a-schema"
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -38,3 +38,4 @@ export { TimeAgo } from '@/components/v2/time-ago';
|
|||
export { Title } from '@/components/v2/title';
|
||||
export { ToggleGroup, ToggleGroupItem } from '@/components/v2/toggle-group';
|
||||
export { Tooltip } from '@/components/v2/tooltip';
|
||||
export { DocsNote, DocsLink } from '@/components/v2/docs-note';
|
||||
|
|
|
|||
|
|
@ -11,18 +11,19 @@ export const ConnectLabModal = ({
|
|||
toggleModalOpen: () => void;
|
||||
endpoint: string;
|
||||
}): ReactElement => {
|
||||
const docsUrl = getDocsUrl('/features/tokens') || '';
|
||||
const docsUrl = getDocsUrl('/management/targets#registry-access-tokens') || '';
|
||||
|
||||
return (
|
||||
<Modal open={isOpen} onOpenChange={toggleModalOpen} className="flex w-[650px] flex-col gap-5">
|
||||
<Heading className="text-center">Connect to Lab</Heading>
|
||||
<Modal open={isOpen} onOpenChange={toggleModalOpen} className="flex w-[750px] flex-col gap-5">
|
||||
<Heading className="text-center">Use GraphQL Schema Externally</Heading>
|
||||
<p className="text-sm text-gray-500">
|
||||
Hive allow you to consume and use this schema with your configured mocks while developing.
|
||||
Hive allow you to consume and use the Laboratory schema with your configured mocks while
|
||||
developing.
|
||||
</p>
|
||||
<span className="text-sm text-gray-500">You can use the following endpoint:</span>
|
||||
<CopyValue value={endpoint} />
|
||||
<span className="text-sm text-gray-500">
|
||||
To authenticate, use the following HTTP headers:
|
||||
To authenticate, use the following HTTP headers, with a token that has `target:read` scope:
|
||||
</span>
|
||||
<Tag>
|
||||
X-Hive-Key:{' '}
|
||||
|
|
@ -35,7 +36,7 @@ export const ConnectLabModal = ({
|
|||
<Link variant="primary" target="_blank" rel="noreferrer" href={docsUrl}>
|
||||
Managing Tokens
|
||||
</Link>{' '}
|
||||
chapter in our documentation.
|
||||
chapter in our documentation to create a Registry Access Token.
|
||||
</p>
|
||||
<Button
|
||||
type="button"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,17 @@
|
|||
import { ReactElement } from 'react';
|
||||
import { ReactElement, useState } from 'react';
|
||||
import { useQuery } from 'urql';
|
||||
import { Button, CopyValue, Heading, Link, Modal, Tag } from '@/components/v2';
|
||||
import {
|
||||
Button,
|
||||
CopyValue,
|
||||
DocsLink,
|
||||
Heading,
|
||||
Link,
|
||||
Modal,
|
||||
RadixSelect,
|
||||
Tag,
|
||||
} from '@/components/v2';
|
||||
import { graphql } from '@/gql';
|
||||
import { ProjectType } from '@/graphql';
|
||||
import { getDocsUrl } from '@/lib/docs-url';
|
||||
import { useRouteSelector } from '@/lib/hooks';
|
||||
|
||||
|
|
@ -9,11 +19,34 @@ const ConnectSchemaModalQuery = graphql(`
|
|||
query ConnectSchemaModal($targetSelector: TargetSelectorInput!) {
|
||||
target(selector: $targetSelector) {
|
||||
id
|
||||
project {
|
||||
id
|
||||
type
|
||||
}
|
||||
cdnUrl
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
type CdnArtifactType = 'sdl' | 'services' | 'supergraph' | 'metadata';
|
||||
|
||||
const ArtifactToProjectTypeMapping: Record<ProjectType, CdnArtifactType[]> = {
|
||||
[ProjectType.Single]: ['sdl', 'metadata'],
|
||||
[ProjectType.Stitching]: ['sdl', 'services'],
|
||||
[ProjectType.Federation]: ['sdl', 'services', 'supergraph'],
|
||||
};
|
||||
|
||||
const ArtifactTypeToDisplayName: Record<CdnArtifactType, string> = {
|
||||
sdl: 'GraphQL SDL',
|
||||
services: 'Services Definition and SDL',
|
||||
supergraph: 'Apollo Federation Supergraph',
|
||||
metadata: 'Hive Schema Metadata',
|
||||
};
|
||||
|
||||
function composeEndpoint(baseUrl: string, artifactType: CdnArtifactType): string {
|
||||
return `${baseUrl}/${artifactType}`;
|
||||
}
|
||||
|
||||
export const ConnectSchemaModal = ({
|
||||
isOpen,
|
||||
toggleModalOpen,
|
||||
|
|
@ -21,6 +54,7 @@ export const ConnectSchemaModal = ({
|
|||
isOpen: boolean;
|
||||
toggleModalOpen: () => void;
|
||||
}): ReactElement => {
|
||||
const [selectedArtifact, setSelectedArtifact] = useState<CdnArtifactType>('sdl');
|
||||
const router = useRouteSelector();
|
||||
const [query] = useQuery({
|
||||
query: ConnectSchemaModalQuery,
|
||||
|
|
@ -35,55 +69,82 @@ export const ConnectSchemaModal = ({
|
|||
});
|
||||
|
||||
return (
|
||||
<Modal open={isOpen} onOpenChange={toggleModalOpen} className="flex w-[650px] flex-col gap-5">
|
||||
<Heading className="text-center">Connect to Hive</Heading>
|
||||
<Modal open={isOpen} onOpenChange={toggleModalOpen} className="flex w-[800px] flex-col gap-5">
|
||||
<Heading className="text-center">Hive CDN Access</Heading>
|
||||
|
||||
{query.data?.target && (
|
||||
<>
|
||||
<p className="text-sm text-gray-500">
|
||||
With high-availability and multi-zone CDN service based on Cloudflare, Hive allows you
|
||||
to access the schema of your API, through a secured external service, that's always up
|
||||
regardless of Hive.
|
||||
Hive leverages the{' '}
|
||||
<Link
|
||||
variant="primary"
|
||||
className="font-bold underline"
|
||||
href="https://www.cloudflare.com/network"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
CloudFlare Global Network
|
||||
</Link>{' '}
|
||||
to deliver your GraphQL schema and schema metadata. This means that your schema will be
|
||||
available from the nearest location to your GraphQL gateway, with 100% uptime,
|
||||
regardless of Hive's status.
|
||||
</p>
|
||||
<span className="text-sm text-gray-500">You can use the following endpoint:</span>
|
||||
<CopyValue value={query.data.target.cdnUrl} />
|
||||
<p className="text-sm text-gray-500">
|
||||
Based on your project type, you can access different artifacts from Hive's CDN:
|
||||
</p>
|
||||
<div>
|
||||
<RadixSelect
|
||||
placeholder="Select Artifact"
|
||||
name="artifact-select"
|
||||
position="popper"
|
||||
value={selectedArtifact}
|
||||
options={ArtifactToProjectTypeMapping[query.data.target.project.type].map(t => ({
|
||||
value: t,
|
||||
label: ArtifactTypeToDisplayName[t],
|
||||
}))}
|
||||
onChange={setSelectedArtifact}
|
||||
/>
|
||||
</div>
|
||||
<span className="text-sm text-gray-500">
|
||||
To authenticate, use the access HTTP headers. <br />
|
||||
To access your schema from Hive's CDN, use the following endpoint:
|
||||
</span>
|
||||
<CopyValue value={composeEndpoint(query.data.target.cdnUrl, selectedArtifact)} />
|
||||
<span className="text-sm text-gray-500">
|
||||
To authenticate,{' '}
|
||||
<Link
|
||||
variant="primary"
|
||||
className="font-bold underline"
|
||||
href={`/${router.organizationId}/${router.projectId}/${router.targetId}/settings#cdn-access-tokens`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
create a CDN Access Token from your target's Settings page
|
||||
</Link>{' '}
|
||||
use the CDN access token in your HTTP headers:
|
||||
<br />
|
||||
</span>
|
||||
<p className="text-sm text-gray-500">
|
||||
<Tag>
|
||||
X-Hive-CDN-Key: {'<'}Your Access Token{'>'}
|
||||
</Tag>
|
||||
</p>
|
||||
<p className="text-sm text-gray-500">
|
||||
You can manage and generate CDN access tokens in the{' '}
|
||||
<Link
|
||||
variant="primary"
|
||||
href={
|
||||
'/' +
|
||||
[
|
||||
router.organizationId,
|
||||
router.projectId,
|
||||
router.targetId,
|
||||
'settings#cdn-access-tokens',
|
||||
].join('/')
|
||||
}
|
||||
>
|
||||
target settings
|
||||
</Link>
|
||||
</p>
|
||||
<p className="text-sm text-gray-500">
|
||||
Read the{' '}
|
||||
<Link
|
||||
variant="primary"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={getDocsUrl('/features/registry-usage#apollo-federation') ?? ''}
|
||||
>
|
||||
Using the Registry with a Apollo Gateway
|
||||
</Link>{' '}
|
||||
chapter in our documentation.
|
||||
</p>
|
||||
<DocsLink href="/features/high-availability-cdn">
|
||||
Learn more about Hive High-Availability CDN
|
||||
</DocsLink>
|
||||
{query.data.target.project.type === ProjectType.Federation ? (
|
||||
<p className="text-sm text-gray-500">
|
||||
Read the{' '}
|
||||
<Link
|
||||
variant="primary"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={getDocsUrl('/integrations/apollo-gateway#supergraph-sdl-from-the-cdn') ?? ''}
|
||||
>
|
||||
Using the Registry with a Apollo Gateway
|
||||
</Link>{' '}
|
||||
chapter in our documentation.
|
||||
</p>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -4,4 +4,71 @@ export default withGuildDocs({
|
|||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
redirects: async () => [
|
||||
{
|
||||
source: '/get-started/organizations',
|
||||
destination: '/management/organizations',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/get-started/projects',
|
||||
destination: '/management/projects',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/get-started/targets',
|
||||
destination: '/management/targets',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/features/tokens',
|
||||
destination: '/management/targets#manage-tokens',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/features/publish-schema',
|
||||
destination: '/features/schema-registry#publish-a-schema',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/features/checking-schema',
|
||||
destination: '/features/schema-registry#check-a-schema',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/features/delete-schema',
|
||||
destination: '/features/schema-registry#delete-a-service',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/features/registry-usage',
|
||||
destination: '/features/high-availability-cdn',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/features/monitoring',
|
||||
destination: '/features/usage-reporting',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/features/schema-history',
|
||||
destination: '/features/schema-registry#schema-history-and-changelog',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/features/integrations',
|
||||
destination: '/management/organizations#integrations',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/features/alerts-notifications',
|
||||
destination: '/management/projects#alerts-and-notifications',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/features/external-schema-composition',
|
||||
destination: '/management/external-schema-composition',
|
||||
permanent: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 31 KiB |
BIN
packages/web/docs/public/docs/pages/features/history-diff.png
Normal file
|
After Width: | Height: | Size: 309 KiB |
BIN
packages/web/docs/public/docs/pages/features/lab-form.png
Normal file
|
After Width: | Height: | Size: 133 KiB |
BIN
packages/web/docs/public/docs/pages/features/lab.png
Normal file
|
After Width: | Height: | Size: 257 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
BIN
packages/web/docs/public/docs/pages/features/schema-explorer.png
Normal file
|
After Width: | Height: | Size: 150 KiB |
BIN
packages/web/docs/public/docs/pages/features/usage-clients.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 202 KiB |
|
After Width: | Height: | Size: 70 KiB |
BIN
packages/web/docs/public/docs/pages/features/usage-stats.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
packages/web/docs/public/docs/pages/first-steps/org.png
Normal file
|
After Width: | Height: | Size: 226 KiB |
BIN
packages/web/docs/public/docs/pages/first-steps/project.png
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
packages/web/docs/public/docs/pages/first-steps/signup.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
packages/web/docs/public/docs/pages/guides/cdn_token.png
Normal file
|
After Width: | Height: | Size: 183 KiB |
|
After Width: | Height: | Size: 214 KiB |
|
After Width: | Height: | Size: 245 KiB |
|
After Width: | Height: | Size: 194 KiB |
BIN
packages/web/docs/public/docs/pages/guides/federation-schema.png
Normal file
|
After Width: | Height: | Size: 197 KiB |
BIN
packages/web/docs/public/docs/pages/guides/history.png
Normal file
|
After Width: | Height: | Size: 436 KiB |
|
After Width: | Height: | Size: 133 KiB |
BIN
packages/web/docs/public/docs/pages/guides/stitching-history.png
Normal file
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 142 KiB |
BIN
packages/web/docs/public/docs/pages/guides/token.png
Normal file
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 228 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 186 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 188 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |