From e3a16e039946d03f502962b5eb74fabcbfe58aad Mon Sep 17 00:00:00 2001 From: Alexey Rodionov Date: Sun, 18 Oct 2020 16:08:01 +0300 Subject: [PATCH 1/2] Implement visual diff --- packages/commands/diff/package.json | 3 + packages/commands/diff/src/index.ts | 33 ++++- packages/commands/diff/src/static/index.html | 128 +++++++++++++++++++ 3 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 packages/commands/diff/src/static/index.html diff --git a/packages/commands/diff/package.json b/packages/commands/diff/package.json index e181b439b1..cc42c519a6 100644 --- a/packages/commands/diff/package.json +++ b/packages/commands/diff/package.json @@ -33,6 +33,9 @@ "@graphql-inspector/core": "0.0.0-PLACEHOLDER", "@graphql-inspector/commands": "0.0.0-PLACEHOLDER", "@graphql-inspector/logger": "0.0.0-PLACEHOLDER", + "express": "4.17.1", + "express-graphql": "0.11.0", + "graphql-tools": "6.2.4-alpha-34c1194a.0", "tslib": "^2.0.0" }, "scripts": { diff --git a/packages/commands/diff/src/index.ts b/packages/commands/diff/src/index.ts index b1bff93cd0..aa923fc3fe 100644 --- a/packages/commands/diff/src/index.ts +++ b/packages/commands/diff/src/index.ts @@ -17,14 +17,19 @@ import { } from '@graphql-inspector/core'; import {existsSync} from 'fs'; import {GraphQLSchema} from 'graphql'; +import {mergeSchemas} from '@graphql-tools/merge'; +import express from 'express'; +import {graphqlHTTP} from 'express-graphql'; +import path from 'path'; export {CommandFactory}; export function handler(input: { oldSchema: GraphQLSchema; newSchema: GraphQLSchema; - onComplete?: string; rules?: Array; + port?: number; + onComplete?: string; }) { const onComplete = input.onComplete ? resolveCompletionHandler(input.onComplete) @@ -54,6 +59,18 @@ export function handler(input: { return; } + const schema = mergeSchemas({ + schemas: [input.oldSchema, input.newSchema], + onFieldTypeConflict: (_, right) => right, + }); + + const app = express(); + app.set('json spaces', 2); + app.use('/graphql', graphqlHTTP({schema})); + app.get('/changes', (_, res) => res.status(200).json(changes)); + app.use('/voyager', express.static(path.join(__dirname, 'static'))); + app.listen(input.port); + Logger.log( `\nDetected the following changes (${changes.length}) between schemas:\n`, ); @@ -80,6 +97,10 @@ export function handler(input: { reportNonBreakingChanges(nonBreakingChanges); } + Logger.log(`\nJSON Diff:\thttp://localhost:${input.port}/changes`); + + Logger.log(`Visual Diff:\thttp://localhost:${input.port}/voyager`); + onComplete({breakingChanges, dangerousChanges, nonBreakingChanges}); } @@ -89,6 +110,7 @@ export default createCommand< oldSchema: string; newSchema: string; rule?: Array; + port?: number; onComplete?: string; } & GlobalArgs >((api) => { @@ -114,6 +136,12 @@ export default createCommand< describe: 'Add rules', array: true, }, + port: { + alias: 'p', + describe: 'Port', + type: 'number', + default: 4000, + }, onComplete: { describe: 'Handle Completion', type: 'string', @@ -148,6 +176,7 @@ export default createCommand< oldSchema, newSchema, rules: args.rule, + port: args.port, onComplete: args.onComplete, }); } catch (error) { @@ -234,7 +263,7 @@ function failOnBreakingChanges({breakingChanges}: CompletionArgs) { breakingCount > 1 ? 's' : '' }`, ); - process.exit(1); + // process.exit(1); } else { Logger.success('No breaking changes detected'); } diff --git a/packages/commands/diff/src/static/index.html b/packages/commands/diff/src/static/index.html new file mode 100644 index 0000000000..c7bb240aea --- /dev/null +++ b/packages/commands/diff/src/static/index.html @@ -0,0 +1,128 @@ + + + + + + + + + + + +
Loading...
+ + + From 965e62f6b431210a809f93055313367a4b7e19d2 Mon Sep 17 00:00:00 2001 From: Alexey Rodionov Date: Mon, 26 Oct 2020 20:58:10 +0300 Subject: [PATCH 2/2] Addressing code review feedback --- packages/commands/diff/src/index.ts | 51 +++++++++++++++++++---------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/packages/commands/diff/src/index.ts b/packages/commands/diff/src/index.ts index aa923fc3fe..262f1a436b 100644 --- a/packages/commands/diff/src/index.ts +++ b/packages/commands/diff/src/index.ts @@ -28,6 +28,7 @@ export function handler(input: { oldSchema: GraphQLSchema; newSchema: GraphQLSchema; rules?: Array; + visual?: boolean; port?: number; onComplete?: string; }) { @@ -59,18 +60,6 @@ export function handler(input: { return; } - const schema = mergeSchemas({ - schemas: [input.oldSchema, input.newSchema], - onFieldTypeConflict: (_, right) => right, - }); - - const app = express(); - app.set('json spaces', 2); - app.use('/graphql', graphqlHTTP({schema})); - app.get('/changes', (_, res) => res.status(200).json(changes)); - app.use('/voyager', express.static(path.join(__dirname, 'static'))); - app.listen(input.port); - Logger.log( `\nDetected the following changes (${changes.length}) between schemas:\n`, ); @@ -97,11 +86,28 @@ export function handler(input: { reportNonBreakingChanges(nonBreakingChanges); } - Logger.log(`\nJSON Diff:\thttp://localhost:${input.port}/changes`); + onComplete( + {breakingChanges, dangerousChanges, nonBreakingChanges}, + input.visual, + ); + + if (input.visual) { + const schema = mergeSchemas({ + schemas: [input.oldSchema, input.newSchema], + onFieldTypeConflict: (_, right) => right, + }); - Logger.log(`Visual Diff:\thttp://localhost:${input.port}/voyager`); + const app = express(); + app.set('json spaces', 2); + app.use('/graphql', graphqlHTTP({schema})); + app.get('/changes', (_, res) => res.status(200).json(changes)); + app.use('/voyager', express.static(path.join(__dirname, 'static'))); + app.listen(input.port); - onComplete({breakingChanges, dangerousChanges, nonBreakingChanges}); + Logger.log(`\nJSON Diff:\thttp://localhost:${input.port}/changes`); + + Logger.log(`Visual Diff:\thttp://localhost:${input.port}/voyager`); + } } export default createCommand< @@ -110,6 +116,7 @@ export default createCommand< oldSchema: string; newSchema: string; rule?: Array; + visual?: boolean; port?: number; onComplete?: string; } & GlobalArgs @@ -136,6 +143,10 @@ export default createCommand< describe: 'Add rules', array: true, }, + visual: { + describe: 'Enable visual diff', + type: 'boolean', + }, port: { alias: 'p', describe: 'Port', @@ -176,6 +187,7 @@ export default createCommand< oldSchema, newSchema, rules: args.rule, + visual: args.visual, port: args.port, onComplete: args.onComplete, }); @@ -254,7 +266,10 @@ function resolveCompletionHandler(name: string): CompletionHandler | never { return mod?.default || mod; } -function failOnBreakingChanges({breakingChanges}: CompletionArgs) { +function failOnBreakingChanges( + {breakingChanges}: CompletionArgs, + proceed?: boolean, +) { const breakingCount = breakingChanges.length; if (breakingCount) { @@ -263,7 +278,9 @@ function failOnBreakingChanges({breakingChanges}: CompletionArgs) { breakingCount > 1 ? 's' : '' }`, ); - // process.exit(1); + if (!proceed) { + process.exit(1); + } } else { Logger.success('No breaking changes detected'); }