Skip to content

Commit

Permalink
fix #20
Browse files Browse the repository at this point in the history
  • Loading branch information
StarpTech committed May 16, 2021
1 parent 1cde7b0 commit 18d3143
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 28 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ State: Experimental
- Serves schema for GraphQL gateway based on provided services & their versions
- Validates new schema to be compatible with other running services
- Validates that all client operations are supported by your schema
- Produce a diff between your proposed schema and the current registry state
- Produce a diff between your proposed schema and the current registry state to detect breaking changes and more
- Lightweight authorization concept based on JWT.

[**Read more**](https://principledgraphql.com/integrity#3-track-the-schema-in-a-registry)
Expand Down
6 changes: 4 additions & 2 deletions docs/api.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Composition stability

Whenever a schema is pushed or fetched, Graph-Registry ensures that the schema is valid. You can't fetch or push an invalid schema.
Whenever a schema is pushed or fetched, Graph-Registry ensures that the schema is valid. You can't fetch or produce an invalid registry state.

# Terminology

Expand Down Expand Up @@ -35,6 +35,8 @@ POST - `/schema/push` Creates a new graph and schema for a service. If you omit

**Notice:** A schema is normalized before it's stored in the database. Whitespaces are stipped and graphql elements are sorted lexicographically.

**Notice:** The schema isn't validated for breaking-changes. Use [schema diff](#produce-a-diff-from-your-schema) to understand the implications of your update.

<details>
<summary>Example Request</summary>
<p>
Expand Down Expand Up @@ -93,7 +95,7 @@ PUT - `/schema/deactivate` Deactivates a schema by id. The schema will no longer

### Produce a diff from your schema

POST - `/schema/diff` Returns the schema report of all services and the provided new schema.
POST - `/schema/diff` Returns the schema report between provided and latest schemas.

<details>
<summary>Example Request</summary>
Expand Down
60 changes: 60 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"dependencies": {
"@apollo/federation": "^0.25.0",
"@graphql-inspector/core": "2.5.0",
"@graphql-tools/utils": "^7.10.0",
"ajv": "6.12.6",
"env-schema": "^3.0.1",
"fastify": "^3.15.1",
Expand Down
2 changes: 1 addition & 1 deletion src/core/federation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function composeAndValidateSchema(servicesSchemaMap: ServiceSchema[]) {

return {
name: schema.name,
url: '',
url: schema.url,
typeDefs,
}
})
Expand Down
8 changes: 5 additions & 3 deletions src/core/graphql-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ import {
buildSchema,
GraphQLSchema,
lexicographicSortSchema,
printSchema,
stripIgnoredCharacters,
} from 'graphql'
import { printSchemaWithDirectives } from '@graphql-tools/utils'

export function normalize(typeDefs: string): string {
const schema = buildSchema(typeDefs)
const schema = buildSchema(typeDefs, { assumeValidSDL: true })
return stripIgnoredCharacters(printSorted(schema))
}

export function printSorted(schema: GraphQLSchema): string {
return printSchema(lexicographicSortSchema(schema))
const sorted = lexicographicSortSchema(schema)
// without this the default implementation of "printSchema" would remove metadata like "directives"
return printSchemaWithDirectives(sorted)
}
2 changes: 1 addition & 1 deletion src/migrations/20210504193054_initial_schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export async function up(knex: Knex): Promise<void> {
.createTable(SchemaDBModel.table, (table) => {
table.increments(SchemaDBModel.field('id')).primary()

table.string(SchemaDBModel.field('typeDefs'))
table.text(SchemaDBModel.field('typeDefs'))
table.boolean(SchemaDBModel.field('isActive')).notNullable().defaultTo(true)
table
.timestamp(SchemaDBModel.field('createdAt'), { useTz: true })
Expand Down
8 changes: 4 additions & 4 deletions src/registry/federation/compose-schema-versions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,14 @@ test('Should return schema of two services', async (t) => {
t.truthy(response.data[0].lastUpdatedAt)
t.like(response.data[0], {
serviceName: `${t.context.testPrefix}_foo`,
typeDefs: 'type Query{hello:String}',
typeDefs: 'schema{query:Query}type Query{hello:String}',
version: '2',
})

t.truthy(response.data[1].lastUpdatedAt)
t.like(response.data[1], {
serviceName: `${t.context.testPrefix}_bar`,
typeDefs: 'type Query{world:String}',
typeDefs: 'schema{query:Query}type Query{world:String}',
version: '2',
})
})
Expand Down Expand Up @@ -327,7 +327,7 @@ test('Version "current" should always return the latest (not versioned) register

t.like(response.data[0], {
serviceName: `${t.context.testPrefix}_foo`,
typeDefs: `type Query{world:String}`,
typeDefs: `schema{query:Query}type Query{world:String}`,
version: CURRENT_VERSION,
})
})
Expand Down Expand Up @@ -374,7 +374,7 @@ test('Should include "routingUrl" of the service', async (t) => {

t.like(response.data[0], {
serviceName: `${t.context.testPrefix}_foo`,
typeDefs: 'type Query{hello:String}',
typeDefs: 'schema{query:Query}type Query{hello:String}',
routingUrl: 'http://localhost:3000/api/graphql',
version: '1',
})
Expand Down
8 changes: 4 additions & 4 deletions src/registry/federation/compose-schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ test('Should return schema of two services', async (t) => {
t.truthy(response.data[0].lastUpdatedAt)
t.like(response.data[0], {
serviceName: `${t.context.testPrefix}_bar`,
typeDefs: 'type Query{world:String}',
typeDefs: 'schema{query:Query}type Query{world:String}',
version: '2',
})

t.truthy(response.data[1].lastUpdatedAt)
t.like(response.data[1], {
serviceName: `${t.context.testPrefix}_foo`,
typeDefs: `type Query{hello:String}`,
typeDefs: `schema{query:Query}type Query{hello:String}`,
version: '1',
})
})
Expand Down Expand Up @@ -136,7 +136,7 @@ test('Version "current" has no precedence over the last updated', async (t) => {

t.like(response.data[0], {
serviceName: `${t.context.testPrefix}_foo`,
typeDefs: 'type Query{world:String}',
typeDefs: 'schema{query:Query}type Query{world:String}',
version: '2',
})
})
Expand Down Expand Up @@ -177,7 +177,7 @@ test('Should include "routingUrl" of the service', async (t) => {

t.like(response.data[0], {
serviceName: `${t.context.testPrefix}_foo`,
typeDefs: 'type Query{hello:String}',
typeDefs: 'schema{query:Query}type Query{hello:String}',
routingUrl: 'http://localhost:3000/api/graphql',
version: '1',
})
Expand Down
Loading

0 comments on commit 18d3143

Please sign in to comment.