@graphql-inspector/diff-command 3.1.4 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -10,9 +10,7 @@ const fs = require('fs');
10
10
 
11
11
  function handler(input) {
12
12
  return tslib.__awaiter(this, void 0, void 0, function* () {
13
- const onComplete = input.onComplete
14
- ? resolveCompletionHandler(input.onComplete)
15
- : failOnBreakingChanges;
13
+ const onComplete = input.onComplete ? resolveCompletionHandler(input.onComplete) : failOnBreakingChanges;
16
14
  const rules = input.rules
17
15
  ? input.rules
18
16
  .filter(isString)
@@ -23,7 +21,7 @@ function handler(input) {
23
21
  }
24
22
  return rule;
25
23
  })
26
- .filter((f) => f)
24
+ .filter(f => f)
27
25
  : [];
28
26
  const changes = yield core.diff(input.oldSchema, input.newSchema, rules, {
29
27
  checkUsage: input.onUsage ? resolveUsageHandler(input.onUsage) : undefined,
@@ -33,9 +31,9 @@ function handler(input) {
33
31
  return;
34
32
  }
35
33
  logger.Logger.log(`\nDetected the following changes (${changes.length}) between schemas:\n`);
36
- const breakingChanges = changes.filter((change) => change.criticality.level === core.CriticalityLevel.Breaking);
37
- const dangerousChanges = changes.filter((change) => change.criticality.level === core.CriticalityLevel.Dangerous);
38
- const nonBreakingChanges = changes.filter((change) => change.criticality.level === core.CriticalityLevel.NonBreaking);
34
+ const breakingChanges = changes.filter(change => change.criticality.level === core.CriticalityLevel.Breaking);
35
+ const dangerousChanges = changes.filter(change => change.criticality.level === core.CriticalityLevel.Dangerous);
36
+ const nonBreakingChanges = changes.filter(change => change.criticality.level === core.CriticalityLevel.NonBreaking);
39
37
  if (breakingChanges.length) {
40
38
  reportBreakingChanges(breakingChanges);
41
39
  }
@@ -48,7 +46,7 @@ function handler(input) {
48
46
  onComplete({ breakingChanges, dangerousChanges, nonBreakingChanges });
49
47
  });
50
48
  }
51
- const index = commands.createCommand((api) => {
49
+ const index = commands.createCommand(api => {
52
50
  const { loaders } = api;
53
51
  return {
54
52
  command: 'diff <oldSchema> <newSchema>',
@@ -134,21 +132,21 @@ function sortChanges(changes) {
134
132
  function reportBreakingChanges(changes) {
135
133
  const label = logger.symbols.error;
136
134
  const sorted = sortChanges(changes);
137
- sorted.forEach((change) => {
135
+ sorted.forEach(change => {
138
136
  logger.Logger.log(`${label} ${logger.bolderize(change.message)}`);
139
137
  });
140
138
  }
141
139
  function reportDangerousChanges(changes) {
142
140
  const label = logger.symbols.warning;
143
141
  const sorted = sortChanges(changes);
144
- sorted.forEach((change) => {
142
+ sorted.forEach(change => {
145
143
  logger.Logger.log(`${label} ${logger.bolderize(change.message)}`);
146
144
  });
147
145
  }
148
146
  function reportNonBreakingChanges(changes) {
149
147
  const label = logger.symbols.success;
150
148
  const sorted = sortChanges(changes);
151
- sorted.forEach((change) => {
149
+ sorted.forEach(change => {
152
150
  logger.Logger.log(`${label} ${logger.bolderize(change.message)}`);
153
151
  });
154
152
  }
@@ -6,9 +6,7 @@ import { existsSync } from 'fs';
6
6
 
7
7
  function handler(input) {
8
8
  return __awaiter(this, void 0, void 0, function* () {
9
- const onComplete = input.onComplete
10
- ? resolveCompletionHandler(input.onComplete)
11
- : failOnBreakingChanges;
9
+ const onComplete = input.onComplete ? resolveCompletionHandler(input.onComplete) : failOnBreakingChanges;
12
10
  const rules = input.rules
13
11
  ? input.rules
14
12
  .filter(isString)
@@ -19,7 +17,7 @@ function handler(input) {
19
17
  }
20
18
  return rule;
21
19
  })
22
- .filter((f) => f)
20
+ .filter(f => f)
23
21
  : [];
24
22
  const changes = yield diff(input.oldSchema, input.newSchema, rules, {
25
23
  checkUsage: input.onUsage ? resolveUsageHandler(input.onUsage) : undefined,
@@ -29,9 +27,9 @@ function handler(input) {
29
27
  return;
30
28
  }
31
29
  Logger.log(`\nDetected the following changes (${changes.length}) between schemas:\n`);
32
- const breakingChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.Breaking);
33
- const dangerousChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.Dangerous);
34
- const nonBreakingChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.NonBreaking);
30
+ const breakingChanges = changes.filter(change => change.criticality.level === CriticalityLevel.Breaking);
31
+ const dangerousChanges = changes.filter(change => change.criticality.level === CriticalityLevel.Dangerous);
32
+ const nonBreakingChanges = changes.filter(change => change.criticality.level === CriticalityLevel.NonBreaking);
35
33
  if (breakingChanges.length) {
36
34
  reportBreakingChanges(breakingChanges);
37
35
  }
@@ -44,7 +42,7 @@ function handler(input) {
44
42
  onComplete({ breakingChanges, dangerousChanges, nonBreakingChanges });
45
43
  });
46
44
  }
47
- const index = createCommand((api) => {
45
+ const index = createCommand(api => {
48
46
  const { loaders } = api;
49
47
  return {
50
48
  command: 'diff <oldSchema> <newSchema>',
@@ -130,21 +128,21 @@ function sortChanges(changes) {
130
128
  function reportBreakingChanges(changes) {
131
129
  const label = symbols.error;
132
130
  const sorted = sortChanges(changes);
133
- sorted.forEach((change) => {
131
+ sorted.forEach(change => {
134
132
  Logger.log(`${label} ${bolderize(change.message)}`);
135
133
  });
136
134
  }
137
135
  function reportDangerousChanges(changes) {
138
136
  const label = symbols.warning;
139
137
  const sorted = sortChanges(changes);
140
- sorted.forEach((change) => {
138
+ sorted.forEach(change => {
141
139
  Logger.log(`${label} ${bolderize(change.message)}`);
142
140
  });
143
141
  }
144
142
  function reportNonBreakingChanges(changes) {
145
143
  const label = symbols.success;
146
144
  const sorted = sortChanges(changes);
147
- sorted.forEach((change) => {
145
+ sorted.forEach(change => {
148
146
  Logger.log(`${label} ${bolderize(change.message)}`);
149
147
  });
150
148
  }
package/package.json CHANGED
@@ -1,51 +1,48 @@
1
1
  {
2
2
  "name": "@graphql-inspector/diff-command",
3
- "version": "3.1.4",
3
+ "version": "3.4.0",
4
4
  "description": "Compare GraphQL Schemas",
5
+ "sideEffects": false,
6
+ "peerDependencies": {
7
+ "graphql": "^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
8
+ },
9
+ "dependencies": {
10
+ "@graphql-inspector/commands": "3.4.0",
11
+ "@graphql-inspector/core": "3.4.0",
12
+ "@graphql-inspector/logger": "3.4.0",
13
+ "tslib": "^2.0.0"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "kamilkisiela/graphql-inspector",
18
+ "directory": "packages/commands/diff"
19
+ },
5
20
  "keywords": [
6
21
  "graphql",
7
22
  "graphql-inspector",
8
23
  "graphql-inspector-command",
9
24
  "tools"
10
25
  ],
11
- "sideEffects": false,
12
- "main": "dist/index.js",
13
- "module": "dist/index.mjs",
14
- "exports": {
15
- ".": {
16
- "require": "./dist/index.js",
17
- "import": "./dist/index.mjs"
18
- },
19
- "./*": {
20
- "require": "./dist/*.js",
21
- "import": "./dist/*.mjs"
22
- }
23
- },
24
- "typings": "dist/index.d.ts",
25
- "typescript": {
26
- "definition": "dist/index.d.ts"
27
- },
28
26
  "author": {
29
27
  "name": "Kamil Kisiela",
30
28
  "email": "kamil.kisiela@gmail.com",
31
29
  "url": "https://github.com/kamilkisiela"
32
30
  },
33
31
  "license": "MIT",
34
- "repository": {
35
- "type": "git",
36
- "url": "kamilkisiela/graphql-inspector",
37
- "directory": "packages/commands/diff"
38
- },
39
- "peerDependencies": {
40
- "graphql": "^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
41
- },
42
- "dependencies": {
43
- "@graphql-inspector/commands": "3.1.4",
44
- "@graphql-inspector/core": "3.1.4",
45
- "@graphql-inspector/logger": "3.1.4",
46
- "tslib": "^2.0.0"
32
+ "main": "index.js",
33
+ "module": "index.mjs",
34
+ "typings": "index.d.ts",
35
+ "typescript": {
36
+ "definition": "index.d.ts"
47
37
  },
48
- "scripts": {
49
- "prepack": "bob prepack"
38
+ "exports": {
39
+ ".": {
40
+ "require": "./index.js",
41
+ "import": "./index.mjs"
42
+ },
43
+ "./*": {
44
+ "require": "./*.js",
45
+ "import": "./*.mjs"
46
+ }
50
47
  }
51
48
  }
@@ -1 +0,0 @@
1
- module.exports = () => process.exit(2);
@@ -1 +0,0 @@
1
- module.exports = ({ changes }) => changes;
@@ -1,154 +0,0 @@
1
- import '@graphql-inspector/testing';
2
- import { mockCommand } from '@graphql-inspector/commands';
3
- import { mockLogger, unmockLogger } from '@graphql-inspector/logger';
4
- import yargs from 'yargs';
5
- import { buildSchema } from 'graphql';
6
- import { resolve } from 'path';
7
- import createCommand from '../src';
8
-
9
- const oldSchema = buildSchema(/* GraphQL */ `
10
- type Post {
11
- id: ID
12
- title: String
13
- createdAt: String
14
- modifiedAt: String
15
- }
16
-
17
- type Query {
18
- post: Post!
19
- }
20
- `);
21
- const newSchema = buildSchema(/* GraphQL */ `
22
- type Post {
23
- id: ID!
24
- title: String!
25
- createdAt: String!
26
- }
27
-
28
- type Query {
29
- post: Post!
30
- }
31
- `);
32
-
33
- const diff = createCommand({
34
- config: {
35
- commands: [],
36
- loaders: [],
37
- },
38
- loaders: {
39
- async loadSchema(pointer) {
40
- if (pointer.includes('old')) {
41
- return oldSchema;
42
- }
43
-
44
- return newSchema;
45
- },
46
- async loadDocuments() {
47
- throw new Error('Not implemented');
48
- },
49
- },
50
- });
51
-
52
- describe('diff', () => {
53
- let spyReporter: jest.SpyInstance;
54
- let spyProcessExit: jest.SpyInstance;
55
- let spyProcessCwd: jest.SpyInstance;
56
-
57
- beforeEach(() => {
58
- yargs.reset();
59
- spyProcessExit = jest.spyOn(process, 'exit');
60
- spyProcessExit.mockImplementation();
61
-
62
- spyProcessCwd = jest
63
- .spyOn(process, 'cwd')
64
- .mockImplementation(() => __dirname);
65
-
66
- spyReporter = jest.fn();
67
- mockLogger(spyReporter as any);
68
- });
69
-
70
- afterEach(() => {
71
- yargs.reset();
72
- unmockLogger();
73
- spyProcessExit.mockRestore();
74
- spyProcessCwd.mockRestore();
75
- spyReporter.mockRestore();
76
- });
77
-
78
- test('should load graphql file', async () => {
79
- await mockCommand(diff, 'diff old.graphql old.graphql');
80
-
81
- expect(spyReporter).toHaveBeenCalledNormalized('No changes detected');
82
- expect(spyReporter).not.toHaveBeenCalledNormalized(
83
- 'Detected the following changes',
84
- );
85
- });
86
-
87
- test('should load different schema from graphql file', async () => {
88
- await mockCommand(diff, 'diff old.graphql new.graphql');
89
-
90
- expect(spyReporter).not.toHaveBeenCalledWith('No changes detected');
91
- expect(spyReporter).toHaveBeenCalledNormalized(
92
- 'Detected the following changes (4) between schemas:',
93
- );
94
-
95
- expect(spyProcessExit).toHaveBeenCalledWith(1);
96
- });
97
-
98
- test('should load rule by name', async () => {
99
- await mockCommand(
100
- diff,
101
- 'diff old.graphql new.graphql --rule suppressRemovalOfDeprecatedField',
102
- );
103
-
104
- expect(spyReporter).not.toHaveBeenCalledNormalized('does not exist');
105
- });
106
-
107
- test('should load rules with local path from fs', async () => {
108
- await mockCommand(
109
- diff,
110
- 'diff old.graphql new.graphql --rule ./assets/rule.js',
111
- );
112
-
113
- expect(spyReporter).not.toHaveBeenCalledNormalized('does not exist');
114
- });
115
-
116
- test('should load rules with absolute path from fs', async () => {
117
- await mockCommand(
118
- diff,
119
- `diff old.graphql new.graphql --rule ${resolve(
120
- __dirname,
121
- 'assets/rule.js',
122
- )}`,
123
- );
124
-
125
- expect(spyReporter).not.toHaveBeenCalledNormalized('does not exist');
126
- });
127
-
128
- test('should render error if file does not exist', async () => {
129
- await mockCommand(diff, `diff old.graphql new.graphql --rule noop.js`);
130
-
131
- expect(spyReporter).toHaveBeenCalledNormalized('does not exist');
132
- });
133
-
134
- test('should render error if file does not exist', async () => {
135
- await mockCommand(
136
- diff,
137
- `diff old.graphql new.graphql --onComplete ${resolve(
138
- __dirname,
139
- 'assets/onComplete.js',
140
- )}`,
141
- );
142
-
143
- expect(spyProcessExit).toHaveBeenCalledWith(2);
144
- });
145
-
146
- test('should render error if file does not exist', async () => {
147
- await mockCommand(
148
- diff,
149
- `diff old.graphql new.graphql --onComplete noop.js`,
150
- );
151
-
152
- expect(spyReporter).toHaveBeenCalledNormalized('does not exist');
153
- });
154
- });
package/dist/package.json DELETED
@@ -1,48 +0,0 @@
1
- {
2
- "name": "@graphql-inspector/diff-command",
3
- "version": "3.1.4",
4
- "description": "Compare GraphQL Schemas",
5
- "sideEffects": false,
6
- "peerDependencies": {
7
- "graphql": "^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
8
- },
9
- "dependencies": {
10
- "@graphql-inspector/commands": "3.1.4",
11
- "@graphql-inspector/core": "3.1.4",
12
- "@graphql-inspector/logger": "3.1.4",
13
- "tslib": "^2.0.0"
14
- },
15
- "repository": {
16
- "type": "git",
17
- "url": "kamilkisiela/graphql-inspector",
18
- "directory": "packages/commands/diff"
19
- },
20
- "keywords": [
21
- "graphql",
22
- "graphql-inspector",
23
- "graphql-inspector-command",
24
- "tools"
25
- ],
26
- "author": {
27
- "name": "Kamil Kisiela",
28
- "email": "kamil.kisiela@gmail.com",
29
- "url": "https://github.com/kamilkisiela"
30
- },
31
- "license": "MIT",
32
- "main": "index.js",
33
- "module": "index.mjs",
34
- "typings": "index.d.ts",
35
- "typescript": {
36
- "definition": "index.d.ts"
37
- },
38
- "exports": {
39
- ".": {
40
- "require": "./index.js",
41
- "import": "./index.mjs"
42
- },
43
- "./*": {
44
- "require": "./*.js",
45
- "import": "./*.mjs"
46
- }
47
- }
48
- }
package/src/index.ts DELETED
@@ -1,283 +0,0 @@
1
- import {
2
- CommandFactory,
3
- createCommand,
4
- ensureAbsolute,
5
- GlobalArgs,
6
- parseGlobalArgs,
7
- } from '@graphql-inspector/commands';
8
- import {
9
- Change,
10
- CompletionArgs,
11
- CompletionHandler,
12
- UsageHandler,
13
- CriticalityLevel,
14
- diff as diffSchema,
15
- DiffRule,
16
- Rule,
17
- } from '@graphql-inspector/core';
18
- import { bolderize, Logger, symbols } from '@graphql-inspector/logger';
19
- import { existsSync } from 'fs';
20
- import { GraphQLSchema } from 'graphql';
21
-
22
- export { CommandFactory };
23
-
24
- export async function handler(input: {
25
- oldSchema: GraphQLSchema;
26
- newSchema: GraphQLSchema;
27
- onComplete?: string;
28
- onUsage?: string;
29
- rules?: Array<string | number>;
30
- }) {
31
- const onComplete = input.onComplete
32
- ? resolveCompletionHandler(input.onComplete)
33
- : failOnBreakingChanges;
34
-
35
- const rules = input.rules
36
- ? input.rules
37
- .filter(isString)
38
- .map((name): Rule => {
39
- const rule = resolveRule(name);
40
-
41
- if (!rule) {
42
- throw new Error(`\Rule '${name}' does not exist!\n`);
43
- }
44
-
45
- return rule;
46
- })
47
- .filter((f) => f)
48
- : [];
49
-
50
- const changes = await diffSchema(input.oldSchema, input.newSchema, rules, {
51
- checkUsage: input.onUsage ? resolveUsageHandler(input.onUsage) : undefined,
52
- });
53
-
54
- if (changes.length === 0) {
55
- Logger.success('No changes detected');
56
- return;
57
- }
58
-
59
- Logger.log(
60
- `\nDetected the following changes (${changes.length}) between schemas:\n`,
61
- );
62
-
63
- const breakingChanges = changes.filter(
64
- (change) => change.criticality.level === CriticalityLevel.Breaking,
65
- );
66
- const dangerousChanges = changes.filter(
67
- (change) => change.criticality.level === CriticalityLevel.Dangerous,
68
- );
69
- const nonBreakingChanges = changes.filter(
70
- (change) => change.criticality.level === CriticalityLevel.NonBreaking,
71
- );
72
-
73
- if (breakingChanges.length) {
74
- reportBreakingChanges(breakingChanges);
75
- }
76
-
77
- if (dangerousChanges.length) {
78
- reportDangerousChanges(dangerousChanges);
79
- }
80
-
81
- if (nonBreakingChanges.length) {
82
- reportNonBreakingChanges(nonBreakingChanges);
83
- }
84
-
85
- onComplete({ breakingChanges, dangerousChanges, nonBreakingChanges });
86
- }
87
-
88
- export default createCommand<
89
- {},
90
- {
91
- oldSchema: string;
92
- newSchema: string;
93
- rule?: Array<string | number>;
94
- onComplete?: string;
95
- onUsage?: string;
96
- } & GlobalArgs
97
- >((api) => {
98
- const { loaders } = api;
99
-
100
- return {
101
- command: 'diff <oldSchema> <newSchema>',
102
- describe: 'Compare two GraphQL Schemas',
103
- builder(yargs) {
104
- return yargs
105
- .positional('oldSchema', {
106
- describe: 'Point to an old schema',
107
- type: 'string',
108
- demandOption: true,
109
- })
110
- .positional('newSchema', {
111
- describe: 'Point to a new schema',
112
- type: 'string',
113
- demandOption: true,
114
- })
115
- .options({
116
- rule: {
117
- describe: 'Add rules',
118
- array: true,
119
- },
120
- onComplete: {
121
- describe: 'Handle Completion',
122
- type: 'string',
123
- },
124
- onUsage: {
125
- describe: 'Checks usage of schema',
126
- type: 'string',
127
- },
128
- });
129
- },
130
- async handler(args) {
131
- try {
132
- const oldSchemaPointer = args.oldSchema;
133
- const newSchemaPointer = args.newSchema;
134
- const apolloFederation = args.federation || false;
135
- const aws = args.aws || false;
136
- const method = args.method?.toUpperCase() || 'POST';
137
- const { headers, leftHeaders, rightHeaders, token } =
138
- parseGlobalArgs(args);
139
-
140
- const oldSchemaHeaders = {
141
- ...(headers ?? {}),
142
- ...(leftHeaders ?? {}),
143
- };
144
- const newSchemaHeaders = {
145
- ...(headers ?? {}),
146
- ...(rightHeaders ?? {}),
147
- };
148
-
149
- const oldSchema = await loaders.loadSchema(
150
- oldSchemaPointer,
151
- {
152
- headers: oldSchemaHeaders,
153
- token,
154
- method,
155
- },
156
- apolloFederation,
157
- aws,
158
- );
159
- const newSchema = await loaders.loadSchema(
160
- newSchemaPointer,
161
- {
162
- headers: newSchemaHeaders,
163
- token,
164
- method,
165
- },
166
- apolloFederation,
167
- aws,
168
- );
169
-
170
- await handler({
171
- oldSchema,
172
- newSchema,
173
- rules: args.rule,
174
- onComplete: args.onComplete,
175
- onUsage: args.onUsage,
176
- });
177
- } catch (error) {
178
- Logger.error(error);
179
- throw error;
180
- }
181
- },
182
- };
183
- });
184
-
185
- function sortChanges(changes: Change[]) {
186
- return changes.slice().sort((a, b) => {
187
- const aPath = a.path || '';
188
- const bPath = b.path || '';
189
-
190
- if (aPath > bPath) {
191
- return 1;
192
- }
193
-
194
- if (bPath > aPath) {
195
- return -1;
196
- }
197
-
198
- return 0;
199
- });
200
- }
201
-
202
- function reportBreakingChanges(changes: Change[]) {
203
- const label = symbols.error;
204
- const sorted = sortChanges(changes);
205
-
206
- sorted.forEach((change) => {
207
- Logger.log(`${label} ${bolderize(change.message)}`);
208
- });
209
- }
210
-
211
- function reportDangerousChanges(changes: Change[]) {
212
- const label = symbols.warning;
213
- const sorted = sortChanges(changes);
214
-
215
- sorted.forEach((change) => {
216
- Logger.log(`${label} ${bolderize(change.message)}`);
217
- });
218
- }
219
-
220
- function reportNonBreakingChanges(changes: Change[]) {
221
- const label = symbols.success;
222
- const sorted = sortChanges(changes);
223
-
224
- sorted.forEach((change) => {
225
- Logger.log(`${label} ${bolderize(change.message)}`);
226
- });
227
- }
228
-
229
- function resolveRule(name: string): Rule | undefined {
230
- const filepath = ensureAbsolute(name);
231
- if (existsSync(filepath)) {
232
- return require(filepath);
233
- }
234
-
235
- return DiffRule[name as keyof typeof DiffRule];
236
- }
237
-
238
- function resolveCompletionHandler(name: string): CompletionHandler | never {
239
- const filepath = ensureAbsolute(name);
240
-
241
- try {
242
- require.resolve(filepath);
243
- } catch (error) {
244
- throw new Error(`CompletionHandler '${name}' does not exist!`);
245
- }
246
-
247
- const mod = require(filepath);
248
-
249
- return mod?.default || mod;
250
- }
251
-
252
- function resolveUsageHandler(name: string): UsageHandler | never {
253
- const filepath = ensureAbsolute(name);
254
-
255
- try {
256
- require.resolve(filepath);
257
- } catch (error) {
258
- throw new Error(`UsageHandler '${name}' does not exist!`);
259
- }
260
-
261
- const mod = require(filepath);
262
-
263
- return mod?.default || mod;
264
- }
265
-
266
- function failOnBreakingChanges({ breakingChanges }: CompletionArgs) {
267
- const breakingCount = breakingChanges.length;
268
-
269
- if (breakingCount) {
270
- Logger.error(
271
- `Detected ${breakingCount} breaking change${
272
- breakingCount > 1 ? 's' : ''
273
- }`,
274
- );
275
- process.exit(1);
276
- } else {
277
- Logger.success('No breaking changes detected');
278
- }
279
- }
280
-
281
- function isString(val: any): val is string {
282
- return typeof val === 'string';
283
- }