mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
parent
17ff5c40f0
commit
51ba76eff6
6 changed files with 115 additions and 6 deletions
8
integration-tests/fixtures/federation-init.graphql
Normal file
8
integration-tests/fixtures/federation-init.graphql
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
type Query {
|
||||
users: [User!]!
|
||||
}
|
||||
|
||||
type User {
|
||||
id: ID!
|
||||
email: String!
|
||||
}
|
||||
|
|
@ -573,6 +573,28 @@ export async function fetchSchemaFromCDN(selector: TargetSelectorInput, token: s
|
|||
};
|
||||
}
|
||||
|
||||
export async function fetchSupergraphFromCDN(selector: TargetSelectorInput, token: string) {
|
||||
const cdnAccessResult = await createCdnAccess(selector, token);
|
||||
|
||||
if (cdnAccessResult.body.errors) {
|
||||
throw new Error(cdnAccessResult.body.errors[0].message);
|
||||
}
|
||||
|
||||
const cdn = cdnAccessResult.body.data!.createCdnToken;
|
||||
|
||||
const res = await axios.get<string>(`${cdn.url}/supergraph`, {
|
||||
headers: {
|
||||
'X-Hive-CDN-Key': cdn.token,
|
||||
},
|
||||
responseType: 'text',
|
||||
});
|
||||
|
||||
return {
|
||||
body: res.data,
|
||||
status: res.status,
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchMetadataFromCDN(selector: TargetSelectorInput, token: string) {
|
||||
const cdnAccessResult = await createCdnAccess(selector, token);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
import { TargetAccessScope, ProjectType } from '@app/gql/graphql';
|
||||
import { schemaPublish, schemaCheck } from '../../testkit/cli';
|
||||
import { authenticate } from '../../testkit/auth';
|
||||
import { createOrganization, joinOrganization, createProject, createToken } from '../../testkit/flow';
|
||||
import {
|
||||
createOrganization,
|
||||
joinOrganization,
|
||||
createProject,
|
||||
createToken,
|
||||
fetchSupergraphFromCDN,
|
||||
} from '../../testkit/flow';
|
||||
|
||||
test('can publish and check a schema with target:registry:read access', async () => {
|
||||
const { access_token: owner_access_token } = await authenticate('main');
|
||||
|
|
@ -62,3 +68,72 @@ test('can publish and check a schema with target:registry:read access', async ()
|
|||
'EXIT: 1'
|
||||
);
|
||||
});
|
||||
|
||||
test('service url should be available in supergraph', async () => {
|
||||
const { access_token: owner_access_token } = await authenticate('main');
|
||||
const orgResult = await createOrganization(
|
||||
{
|
||||
name: 'foo',
|
||||
},
|
||||
owner_access_token
|
||||
);
|
||||
const org = orgResult.body.data!.createOrganization.ok!.createdOrganizationPayload.organization;
|
||||
const code = org.inviteCode;
|
||||
|
||||
// Join
|
||||
const { access_token: member_access_token } = await authenticate('extra');
|
||||
await joinOrganization(code, member_access_token);
|
||||
|
||||
const projectResult = await createProject(
|
||||
{
|
||||
organization: org.cleanId,
|
||||
type: ProjectType.Federation,
|
||||
name: 'foo',
|
||||
},
|
||||
owner_access_token
|
||||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
{
|
||||
name: 'test',
|
||||
organization: org.cleanId,
|
||||
project: project.cleanId,
|
||||
target: target.cleanId,
|
||||
organizationScopes: [],
|
||||
projectScopes: [],
|
||||
targetScopes: [TargetAccessScope.RegistryRead, TargetAccessScope.RegistryWrite],
|
||||
},
|
||||
owner_access_token
|
||||
);
|
||||
expect(writeTokenResult.body.errors).not.toBeDefined();
|
||||
const writeToken = writeTokenResult.body.data!.createToken.ok!.secret;
|
||||
|
||||
await schemaPublish([
|
||||
'--token',
|
||||
writeToken,
|
||||
'--author',
|
||||
'Kamil',
|
||||
'--commit',
|
||||
'abc123',
|
||||
'--service',
|
||||
'users',
|
||||
'--url',
|
||||
'https://api.com/users-subgraph',
|
||||
'fixtures/federation-init.graphql',
|
||||
]);
|
||||
|
||||
const supergraph = await fetchSupergraphFromCDN(
|
||||
{
|
||||
organization: org.cleanId,
|
||||
project: project.cleanId,
|
||||
target: target.cleanId,
|
||||
},
|
||||
writeToken
|
||||
);
|
||||
|
||||
expect(supergraph.body).toMatch('(name: "users" url: "https://api.com/users-subgraph")');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ export class SchemaPublisher {
|
|||
url: incomingSchema.url ?? null,
|
||||
});
|
||||
|
||||
this.publishToCDN({
|
||||
await this.publishToCDN({
|
||||
valid,
|
||||
target,
|
||||
project,
|
||||
|
|
@ -457,7 +457,7 @@ export class SchemaPublisher {
|
|||
}
|
||||
|
||||
if (incomingSchema.metadata && latest.version && previousSchema) {
|
||||
this.publishToCDN({
|
||||
await this.publishToCDN({
|
||||
valid,
|
||||
target,
|
||||
project,
|
||||
|
|
@ -505,7 +505,7 @@ export class SchemaPublisher {
|
|||
errors,
|
||||
initial: isInitialSchema,
|
||||
});
|
||||
this.publishToCDN({
|
||||
await this.publishToCDN({
|
||||
valid,
|
||||
target,
|
||||
project,
|
||||
|
|
@ -619,7 +619,7 @@ export class SchemaPublisher {
|
|||
}) {
|
||||
try {
|
||||
if (valid) {
|
||||
this.updateCDN({
|
||||
await this.updateCDN({
|
||||
target,
|
||||
project,
|
||||
schemas,
|
||||
|
|
|
|||
|
|
@ -141,6 +141,9 @@ export async function handleRequest(request: Request, keyValidator: typeof isKey
|
|||
});
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
`CDN Artifact not found for targetId=${targetId}, artifactType=${artifactType}, storageKeyType=${storageKeyType}`
|
||||
);
|
||||
return new CDNArtifactNotFound(artifactType, targetId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,13 +85,14 @@ interface CompositionFailure {
|
|||
}
|
||||
|
||||
const createFederation: (redis: RedisInstance, logger: FastifyLoggerInstance) => Orchestrator = (redis, logger) => {
|
||||
const compose = reuse<ValidationInput, CompositionSuccess | CompositionFailure>(
|
||||
const compose = reuse<ValidationInput | SupergraphInput, CompositionSuccess | CompositionFailure>(
|
||||
async schemas => {
|
||||
const result = composeAndValidate(
|
||||
schemas.map(schema => {
|
||||
return {
|
||||
typeDefs: trimDescriptions(parse(schema.raw)),
|
||||
name: schema.source,
|
||||
url: 'url' in schema && typeof schema.url === 'string' ? schema.url : undefined,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue