mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
Support schemas with only extended types (#7630)
This commit is contained in:
parent
a65b0bc772
commit
ef246a17fe
3 changed files with 91 additions and 8 deletions
|
|
@ -176,7 +176,7 @@ export function compareDirectiveLists(
|
|||
const newItems = newMap[itemName];
|
||||
const oldItems = oldMap[itemName];
|
||||
for (let i = (oldItems ?? []).length; i < (newItems ?? []).length; i++) {
|
||||
const oldItem = oldItems[i];
|
||||
const oldItem = oldItems?.[i];
|
||||
const newItem = newItems[i];
|
||||
if (oldItem === undefined) {
|
||||
added.push(newItem);
|
||||
|
|
|
|||
|
|
@ -108,14 +108,14 @@ export function ChangeRow(props: {
|
|||
'bg-neutral-2 px-2',
|
||||
props.className,
|
||||
props.type === 'removal' && 'bg-[#561c1d]',
|
||||
props.type === 'addition' && 'bg-[#11362b]',
|
||||
props.type === 'addition' && 'bg-green-600 dark:bg-[#11362b]',
|
||||
)}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
'bg-neutral-2',
|
||||
props.type === 'removal' && 'bg-[#561c1d] line-through decoration-[#998c8b]',
|
||||
props.type === 'addition' && 'bg-[#11362b]',
|
||||
props.type === 'addition' && 'bg-green-600 dark:bg-[#11362b]',
|
||||
)}
|
||||
>
|
||||
{!!props.indent &&
|
||||
|
|
@ -178,7 +178,14 @@ function Addition(props: { children: ReactNode; className?: string }): ReactNode
|
|||
}
|
||||
}, [change.addition]);
|
||||
return (
|
||||
<span className={cn('bg-neutral-3 hover:bg-green-900', props.className)}>{props.children}</span>
|
||||
<span
|
||||
className={cn(
|
||||
'bg-green-600 hover:bg-green-700 dark:bg-[#11362b] dark:hover:bg-green-900',
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
import { useMemo } from 'react';
|
||||
import { buildSchema, GraphQLSchema } from 'graphql';
|
||||
import {
|
||||
buildASTSchema,
|
||||
buildSchema,
|
||||
DefinitionNode,
|
||||
DocumentNode,
|
||||
GraphQLSchema,
|
||||
isTypeDefinitionNode,
|
||||
isTypeExtensionNode,
|
||||
Kind,
|
||||
parse,
|
||||
visit,
|
||||
} from 'graphql';
|
||||
import { useMutation, useQuery } from 'urql';
|
||||
import { Page, TargetLayout } from '@/components/layouts/target';
|
||||
import { CompositionErrorsSection_SchemaErrorConnection } from '@/components/target/history/errors-and-changes';
|
||||
|
|
@ -179,6 +190,68 @@ export function TargetProposalsSinglePage(props: {
|
|||
);
|
||||
}
|
||||
|
||||
const extensionToDefinitionKindMap = {
|
||||
[Kind.OBJECT_TYPE_EXTENSION]: Kind.OBJECT_TYPE_DEFINITION,
|
||||
[Kind.INPUT_OBJECT_TYPE_EXTENSION]: Kind.INPUT_OBJECT_TYPE_DEFINITION,
|
||||
[Kind.INTERFACE_TYPE_EXTENSION]: Kind.INTERFACE_TYPE_DEFINITION,
|
||||
[Kind.UNION_TYPE_EXTENSION]: Kind.UNION_TYPE_DEFINITION,
|
||||
[Kind.ENUM_TYPE_EXTENSION]: Kind.ENUM_TYPE_DEFINITION,
|
||||
[Kind.SCALAR_TYPE_EXTENSION]: Kind.SCALAR_TYPE_DEFINITION,
|
||||
} as const;
|
||||
|
||||
function addTypeForExtensions(ast: DocumentNode) {
|
||||
const trackTypeDefs = new Map<
|
||||
string,
|
||||
| {
|
||||
state: 'TYPE_ONLY';
|
||||
}
|
||||
| {
|
||||
state: 'EXTENSION_ONLY' | 'VALID_EXTENSION';
|
||||
kind:
|
||||
| Kind.OBJECT_TYPE_EXTENSION
|
||||
| Kind.ENUM_TYPE_EXTENSION
|
||||
| Kind.UNION_TYPE_EXTENSION
|
||||
| Kind.SCALAR_TYPE_EXTENSION
|
||||
| Kind.INTERFACE_TYPE_EXTENSION
|
||||
| Kind.INPUT_OBJECT_TYPE_EXTENSION;
|
||||
}
|
||||
>();
|
||||
for (const node of ast.definitions) {
|
||||
if ('name' in node && node.name) {
|
||||
const name = node.name.value;
|
||||
const entry = trackTypeDefs.get(name);
|
||||
if (isTypeExtensionNode(node)) {
|
||||
if (!entry) {
|
||||
trackTypeDefs.set(name, { state: 'EXTENSION_ONLY', kind: node.kind });
|
||||
} else if (entry.state === 'TYPE_ONLY') {
|
||||
trackTypeDefs.set(name, { kind: node.kind, state: 'VALID_EXTENSION' });
|
||||
}
|
||||
} else if (isTypeDefinitionNode(node)) {
|
||||
if (!entry) {
|
||||
trackTypeDefs.set(name, { state: 'TYPE_ONLY' });
|
||||
} else if (entry.state === 'EXTENSION_ONLY') {
|
||||
trackTypeDefs.set(name, { ...entry, state: 'VALID_EXTENSION' });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const astCopy = visit(ast, {});
|
||||
for (const [name, entry] of trackTypeDefs) {
|
||||
if (entry.state === 'EXTENSION_ONLY') {
|
||||
console.log('FOUND EXTENSION: ', name, entry.kind);
|
||||
(astCopy.definitions as DefinitionNode[]).push({
|
||||
kind: extensionToDefinitionKindMap[entry.kind],
|
||||
name: {
|
||||
kind: Kind.NAME,
|
||||
value: name,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
return astCopy;
|
||||
}
|
||||
|
||||
const ProposalsContent = (props: Parameters<typeof TargetProposalsSinglePage>[0]) => {
|
||||
// fetch main page details
|
||||
const [query, refreshProposal] = useQuery({
|
||||
|
|
@ -252,9 +325,12 @@ const ProposalsContent = (props: Parameters<typeof TargetProposalsSinglePage>[0]
|
|||
(proposalVersion.serviceName == null || proposalVersion.serviceName === '') */,
|
||||
)?.node.source;
|
||||
|
||||
const beforeSchema = existingSchema?.length
|
||||
? buildSchema(existingSchema, { assumeValid: true, assumeValidSDL: true })
|
||||
: null;
|
||||
let beforeSchema: GraphQLSchema | null = null;
|
||||
if (existingSchema?.length) {
|
||||
const ast = addTypeForExtensions(parse(existingSchema));
|
||||
beforeSchema = buildASTSchema(ast, { assumeValid: true, assumeValidSDL: true });
|
||||
}
|
||||
|
||||
// @todo better handle pagination
|
||||
const allChanges =
|
||||
proposalVersion.schemaChanges?.edges
|
||||
|
|
|
|||
Loading…
Reference in a new issue