@graphql-inspector/diff-command 0.0.0-canary.6f0f272 → 0.0.0-canary.7db8980
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.
- package/index.d.ts +10 -1
- package/index.js +197 -0
- package/index.mjs +193 -0
- package/package.json +17 -7
- package/index.cjs.js +0 -162
- package/index.cjs.js.map +0 -1
- package/index.esm.js +0 -160
- package/index.esm.js.map +0 -1
package/index.d.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CommandFactory, GlobalArgs } from '@graphql-inspector/commands';
|
|
2
|
+
import { GraphQLSchema } from 'graphql';
|
|
2
3
|
export { CommandFactory };
|
|
4
|
+
export declare function handler(input: {
|
|
5
|
+
oldSchema: GraphQLSchema;
|
|
6
|
+
newSchema: GraphQLSchema;
|
|
7
|
+
onComplete?: string;
|
|
8
|
+
onUsage?: string;
|
|
9
|
+
rules?: Array<string | number>;
|
|
10
|
+
}): Promise<void>;
|
|
3
11
|
declare const _default: CommandFactory<{}, {
|
|
4
12
|
oldSchema: string;
|
|
5
13
|
newSchema: string;
|
|
6
14
|
rule?: (string | number)[] | undefined;
|
|
7
15
|
onComplete?: string | undefined;
|
|
16
|
+
onUsage?: string | undefined;
|
|
8
17
|
} & GlobalArgs>;
|
|
9
18
|
export default _default;
|
package/index.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
const tslib = require('tslib');
|
|
6
|
+
const commands = require('@graphql-inspector/commands');
|
|
7
|
+
const core = require('@graphql-inspector/core');
|
|
8
|
+
const logger = require('@graphql-inspector/logger');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
|
|
11
|
+
function handler(input) {
|
|
12
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
13
|
+
const onComplete = input.onComplete ? resolveCompletionHandler(input.onComplete) : failOnBreakingChanges;
|
|
14
|
+
const rules = input.rules
|
|
15
|
+
? input.rules
|
|
16
|
+
.filter(isString)
|
|
17
|
+
.map((name) => {
|
|
18
|
+
const rule = resolveRule(name);
|
|
19
|
+
if (!rule) {
|
|
20
|
+
throw new Error(`\Rule '${name}' does not exist!\n`);
|
|
21
|
+
}
|
|
22
|
+
return rule;
|
|
23
|
+
})
|
|
24
|
+
.filter(f => f)
|
|
25
|
+
: [];
|
|
26
|
+
const changes = yield core.diff(input.oldSchema, input.newSchema, rules, {
|
|
27
|
+
checkUsage: input.onUsage ? resolveUsageHandler(input.onUsage) : undefined,
|
|
28
|
+
});
|
|
29
|
+
if (changes.length === 0) {
|
|
30
|
+
logger.Logger.success('No changes detected');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
logger.Logger.log(`\nDetected the following changes (${changes.length}) between schemas:\n`);
|
|
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);
|
|
37
|
+
if (breakingChanges.length) {
|
|
38
|
+
reportBreakingChanges(breakingChanges);
|
|
39
|
+
}
|
|
40
|
+
if (dangerousChanges.length) {
|
|
41
|
+
reportDangerousChanges(dangerousChanges);
|
|
42
|
+
}
|
|
43
|
+
if (nonBreakingChanges.length) {
|
|
44
|
+
reportNonBreakingChanges(nonBreakingChanges);
|
|
45
|
+
}
|
|
46
|
+
onComplete({ breakingChanges, dangerousChanges, nonBreakingChanges });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const index = commands.createCommand(api => {
|
|
50
|
+
const { loaders } = api;
|
|
51
|
+
return {
|
|
52
|
+
command: 'diff <oldSchema> <newSchema>',
|
|
53
|
+
describe: 'Compare two GraphQL Schemas',
|
|
54
|
+
builder(yargs) {
|
|
55
|
+
return yargs
|
|
56
|
+
.positional('oldSchema', {
|
|
57
|
+
describe: 'Point to an old schema',
|
|
58
|
+
type: 'string',
|
|
59
|
+
demandOption: true,
|
|
60
|
+
})
|
|
61
|
+
.positional('newSchema', {
|
|
62
|
+
describe: 'Point to a new schema',
|
|
63
|
+
type: 'string',
|
|
64
|
+
demandOption: true,
|
|
65
|
+
})
|
|
66
|
+
.options({
|
|
67
|
+
rule: {
|
|
68
|
+
describe: 'Add rules',
|
|
69
|
+
array: true,
|
|
70
|
+
},
|
|
71
|
+
onComplete: {
|
|
72
|
+
describe: 'Handle Completion',
|
|
73
|
+
type: 'string',
|
|
74
|
+
},
|
|
75
|
+
onUsage: {
|
|
76
|
+
describe: 'Checks usage of schema',
|
|
77
|
+
type: 'string',
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
handler(args) {
|
|
82
|
+
var _a;
|
|
83
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
try {
|
|
85
|
+
const oldSchemaPointer = args.oldSchema;
|
|
86
|
+
const newSchemaPointer = args.newSchema;
|
|
87
|
+
const apolloFederation = args.federation || false;
|
|
88
|
+
const aws = args.aws || false;
|
|
89
|
+
const method = ((_a = args.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || 'POST';
|
|
90
|
+
const { headers, leftHeaders, rightHeaders, token } = commands.parseGlobalArgs(args);
|
|
91
|
+
const oldSchemaHeaders = Object.assign(Object.assign({}, (headers !== null && headers !== void 0 ? headers : {})), (leftHeaders !== null && leftHeaders !== void 0 ? leftHeaders : {}));
|
|
92
|
+
const newSchemaHeaders = Object.assign(Object.assign({}, (headers !== null && headers !== void 0 ? headers : {})), (rightHeaders !== null && rightHeaders !== void 0 ? rightHeaders : {}));
|
|
93
|
+
const oldSchema = yield loaders.loadSchema(oldSchemaPointer, {
|
|
94
|
+
headers: oldSchemaHeaders,
|
|
95
|
+
token,
|
|
96
|
+
method,
|
|
97
|
+
}, apolloFederation, aws);
|
|
98
|
+
const newSchema = yield loaders.loadSchema(newSchemaPointer, {
|
|
99
|
+
headers: newSchemaHeaders,
|
|
100
|
+
token,
|
|
101
|
+
method,
|
|
102
|
+
}, apolloFederation, aws);
|
|
103
|
+
yield handler({
|
|
104
|
+
oldSchema,
|
|
105
|
+
newSchema,
|
|
106
|
+
rules: args.rule,
|
|
107
|
+
onComplete: args.onComplete,
|
|
108
|
+
onUsage: args.onUsage,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
logger.Logger.error(error);
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
function sortChanges(changes) {
|
|
120
|
+
return changes.slice().sort((a, b) => {
|
|
121
|
+
const aPath = a.path || '';
|
|
122
|
+
const bPath = b.path || '';
|
|
123
|
+
if (aPath > bPath) {
|
|
124
|
+
return 1;
|
|
125
|
+
}
|
|
126
|
+
if (bPath > aPath) {
|
|
127
|
+
return -1;
|
|
128
|
+
}
|
|
129
|
+
return 0;
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function reportBreakingChanges(changes) {
|
|
133
|
+
const label = logger.symbols.error;
|
|
134
|
+
const sorted = sortChanges(changes);
|
|
135
|
+
sorted.forEach(change => {
|
|
136
|
+
logger.Logger.log(`${label} ${logger.bolderize(change.message)}`);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function reportDangerousChanges(changes) {
|
|
140
|
+
const label = logger.symbols.warning;
|
|
141
|
+
const sorted = sortChanges(changes);
|
|
142
|
+
sorted.forEach(change => {
|
|
143
|
+
logger.Logger.log(`${label} ${logger.bolderize(change.message)}`);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function reportNonBreakingChanges(changes) {
|
|
147
|
+
const label = logger.symbols.success;
|
|
148
|
+
const sorted = sortChanges(changes);
|
|
149
|
+
sorted.forEach(change => {
|
|
150
|
+
logger.Logger.log(`${label} ${logger.bolderize(change.message)}`);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
function resolveRule(name) {
|
|
154
|
+
const filepath = commands.ensureAbsolute(name);
|
|
155
|
+
if (fs.existsSync(filepath)) {
|
|
156
|
+
return require(filepath);
|
|
157
|
+
}
|
|
158
|
+
return core.DiffRule[name];
|
|
159
|
+
}
|
|
160
|
+
function resolveCompletionHandler(name) {
|
|
161
|
+
const filepath = commands.ensureAbsolute(name);
|
|
162
|
+
try {
|
|
163
|
+
require.resolve(filepath);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
throw new Error(`CompletionHandler '${name}' does not exist!`);
|
|
167
|
+
}
|
|
168
|
+
const mod = require(filepath);
|
|
169
|
+
return (mod === null || mod === void 0 ? void 0 : mod.default) || mod;
|
|
170
|
+
}
|
|
171
|
+
function resolveUsageHandler(name) {
|
|
172
|
+
const filepath = commands.ensureAbsolute(name);
|
|
173
|
+
try {
|
|
174
|
+
require.resolve(filepath);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
throw new Error(`UsageHandler '${name}' does not exist!`);
|
|
178
|
+
}
|
|
179
|
+
const mod = require(filepath);
|
|
180
|
+
return (mod === null || mod === void 0 ? void 0 : mod.default) || mod;
|
|
181
|
+
}
|
|
182
|
+
function failOnBreakingChanges({ breakingChanges }) {
|
|
183
|
+
const breakingCount = breakingChanges.length;
|
|
184
|
+
if (breakingCount) {
|
|
185
|
+
logger.Logger.error(`Detected ${breakingCount} breaking change${breakingCount > 1 ? 's' : ''}`);
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
logger.Logger.success('No breaking changes detected');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function isString(val) {
|
|
193
|
+
return typeof val === 'string';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
exports.default = index;
|
|
197
|
+
exports.handler = handler;
|
package/index.mjs
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { __awaiter } from 'tslib';
|
|
2
|
+
import { createCommand, parseGlobalArgs, ensureAbsolute } from '@graphql-inspector/commands';
|
|
3
|
+
import { diff, CriticalityLevel, DiffRule } from '@graphql-inspector/core';
|
|
4
|
+
import { Logger, symbols, bolderize } from '@graphql-inspector/logger';
|
|
5
|
+
import { existsSync } from 'fs';
|
|
6
|
+
|
|
7
|
+
function handler(input) {
|
|
8
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9
|
+
const onComplete = input.onComplete ? resolveCompletionHandler(input.onComplete) : failOnBreakingChanges;
|
|
10
|
+
const rules = input.rules
|
|
11
|
+
? input.rules
|
|
12
|
+
.filter(isString)
|
|
13
|
+
.map((name) => {
|
|
14
|
+
const rule = resolveRule(name);
|
|
15
|
+
if (!rule) {
|
|
16
|
+
throw new Error(`\Rule '${name}' does not exist!\n`);
|
|
17
|
+
}
|
|
18
|
+
return rule;
|
|
19
|
+
})
|
|
20
|
+
.filter(f => f)
|
|
21
|
+
: [];
|
|
22
|
+
const changes = yield diff(input.oldSchema, input.newSchema, rules, {
|
|
23
|
+
checkUsage: input.onUsage ? resolveUsageHandler(input.onUsage) : undefined,
|
|
24
|
+
});
|
|
25
|
+
if (changes.length === 0) {
|
|
26
|
+
Logger.success('No changes detected');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
Logger.log(`\nDetected the following changes (${changes.length}) between schemas:\n`);
|
|
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);
|
|
33
|
+
if (breakingChanges.length) {
|
|
34
|
+
reportBreakingChanges(breakingChanges);
|
|
35
|
+
}
|
|
36
|
+
if (dangerousChanges.length) {
|
|
37
|
+
reportDangerousChanges(dangerousChanges);
|
|
38
|
+
}
|
|
39
|
+
if (nonBreakingChanges.length) {
|
|
40
|
+
reportNonBreakingChanges(nonBreakingChanges);
|
|
41
|
+
}
|
|
42
|
+
onComplete({ breakingChanges, dangerousChanges, nonBreakingChanges });
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const index = createCommand(api => {
|
|
46
|
+
const { loaders } = api;
|
|
47
|
+
return {
|
|
48
|
+
command: 'diff <oldSchema> <newSchema>',
|
|
49
|
+
describe: 'Compare two GraphQL Schemas',
|
|
50
|
+
builder(yargs) {
|
|
51
|
+
return yargs
|
|
52
|
+
.positional('oldSchema', {
|
|
53
|
+
describe: 'Point to an old schema',
|
|
54
|
+
type: 'string',
|
|
55
|
+
demandOption: true,
|
|
56
|
+
})
|
|
57
|
+
.positional('newSchema', {
|
|
58
|
+
describe: 'Point to a new schema',
|
|
59
|
+
type: 'string',
|
|
60
|
+
demandOption: true,
|
|
61
|
+
})
|
|
62
|
+
.options({
|
|
63
|
+
rule: {
|
|
64
|
+
describe: 'Add rules',
|
|
65
|
+
array: true,
|
|
66
|
+
},
|
|
67
|
+
onComplete: {
|
|
68
|
+
describe: 'Handle Completion',
|
|
69
|
+
type: 'string',
|
|
70
|
+
},
|
|
71
|
+
onUsage: {
|
|
72
|
+
describe: 'Checks usage of schema',
|
|
73
|
+
type: 'string',
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
handler(args) {
|
|
78
|
+
var _a;
|
|
79
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
80
|
+
try {
|
|
81
|
+
const oldSchemaPointer = args.oldSchema;
|
|
82
|
+
const newSchemaPointer = args.newSchema;
|
|
83
|
+
const apolloFederation = args.federation || false;
|
|
84
|
+
const aws = args.aws || false;
|
|
85
|
+
const method = ((_a = args.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || 'POST';
|
|
86
|
+
const { headers, leftHeaders, rightHeaders, token } = parseGlobalArgs(args);
|
|
87
|
+
const oldSchemaHeaders = Object.assign(Object.assign({}, (headers !== null && headers !== void 0 ? headers : {})), (leftHeaders !== null && leftHeaders !== void 0 ? leftHeaders : {}));
|
|
88
|
+
const newSchemaHeaders = Object.assign(Object.assign({}, (headers !== null && headers !== void 0 ? headers : {})), (rightHeaders !== null && rightHeaders !== void 0 ? rightHeaders : {}));
|
|
89
|
+
const oldSchema = yield loaders.loadSchema(oldSchemaPointer, {
|
|
90
|
+
headers: oldSchemaHeaders,
|
|
91
|
+
token,
|
|
92
|
+
method,
|
|
93
|
+
}, apolloFederation, aws);
|
|
94
|
+
const newSchema = yield loaders.loadSchema(newSchemaPointer, {
|
|
95
|
+
headers: newSchemaHeaders,
|
|
96
|
+
token,
|
|
97
|
+
method,
|
|
98
|
+
}, apolloFederation, aws);
|
|
99
|
+
yield handler({
|
|
100
|
+
oldSchema,
|
|
101
|
+
newSchema,
|
|
102
|
+
rules: args.rule,
|
|
103
|
+
onComplete: args.onComplete,
|
|
104
|
+
onUsage: args.onUsage,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
Logger.error(error);
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
function sortChanges(changes) {
|
|
116
|
+
return changes.slice().sort((a, b) => {
|
|
117
|
+
const aPath = a.path || '';
|
|
118
|
+
const bPath = b.path || '';
|
|
119
|
+
if (aPath > bPath) {
|
|
120
|
+
return 1;
|
|
121
|
+
}
|
|
122
|
+
if (bPath > aPath) {
|
|
123
|
+
return -1;
|
|
124
|
+
}
|
|
125
|
+
return 0;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function reportBreakingChanges(changes) {
|
|
129
|
+
const label = symbols.error;
|
|
130
|
+
const sorted = sortChanges(changes);
|
|
131
|
+
sorted.forEach(change => {
|
|
132
|
+
Logger.log(`${label} ${bolderize(change.message)}`);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function reportDangerousChanges(changes) {
|
|
136
|
+
const label = symbols.warning;
|
|
137
|
+
const sorted = sortChanges(changes);
|
|
138
|
+
sorted.forEach(change => {
|
|
139
|
+
Logger.log(`${label} ${bolderize(change.message)}`);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
function reportNonBreakingChanges(changes) {
|
|
143
|
+
const label = symbols.success;
|
|
144
|
+
const sorted = sortChanges(changes);
|
|
145
|
+
sorted.forEach(change => {
|
|
146
|
+
Logger.log(`${label} ${bolderize(change.message)}`);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
function resolveRule(name) {
|
|
150
|
+
const filepath = ensureAbsolute(name);
|
|
151
|
+
if (existsSync(filepath)) {
|
|
152
|
+
return require(filepath);
|
|
153
|
+
}
|
|
154
|
+
return DiffRule[name];
|
|
155
|
+
}
|
|
156
|
+
function resolveCompletionHandler(name) {
|
|
157
|
+
const filepath = ensureAbsolute(name);
|
|
158
|
+
try {
|
|
159
|
+
require.resolve(filepath);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
throw new Error(`CompletionHandler '${name}' does not exist!`);
|
|
163
|
+
}
|
|
164
|
+
const mod = require(filepath);
|
|
165
|
+
return (mod === null || mod === void 0 ? void 0 : mod.default) || mod;
|
|
166
|
+
}
|
|
167
|
+
function resolveUsageHandler(name) {
|
|
168
|
+
const filepath = ensureAbsolute(name);
|
|
169
|
+
try {
|
|
170
|
+
require.resolve(filepath);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
throw new Error(`UsageHandler '${name}' does not exist!`);
|
|
174
|
+
}
|
|
175
|
+
const mod = require(filepath);
|
|
176
|
+
return (mod === null || mod === void 0 ? void 0 : mod.default) || mod;
|
|
177
|
+
}
|
|
178
|
+
function failOnBreakingChanges({ breakingChanges }) {
|
|
179
|
+
const breakingCount = breakingChanges.length;
|
|
180
|
+
if (breakingCount) {
|
|
181
|
+
Logger.error(`Detected ${breakingCount} breaking change${breakingCount > 1 ? 's' : ''}`);
|
|
182
|
+
process.exit(1);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
Logger.success('No breaking changes detected');
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function isString(val) {
|
|
189
|
+
return typeof val === 'string';
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export default index;
|
|
193
|
+
export { handler };
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-inspector/diff-command",
|
|
3
|
-
"version": "0.0.0-canary.
|
|
3
|
+
"version": "0.0.0-canary.7db8980",
|
|
4
4
|
"description": "Compare GraphQL Schemas",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"graphql": "^0.13.0 || ^14.0.0 || ^15.0.0"
|
|
7
|
+
"graphql": "^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@graphql-inspector/commands": "0.0.0-canary.
|
|
11
|
-
"@graphql-inspector/core": "0.0.0-canary.
|
|
12
|
-
"@graphql-inspector/logger": "0.0.0-canary.
|
|
10
|
+
"@graphql-inspector/commands": "0.0.0-canary.7db8980",
|
|
11
|
+
"@graphql-inspector/core": "0.0.0-canary.7db8980",
|
|
12
|
+
"@graphql-inspector/logger": "0.0.0-canary.7db8980",
|
|
13
13
|
"tslib": "^2.0.0"
|
|
14
14
|
},
|
|
15
15
|
"repository": {
|
|
@@ -29,10 +29,20 @@
|
|
|
29
29
|
"url": "https://github.com/kamilkisiela"
|
|
30
30
|
},
|
|
31
31
|
"license": "MIT",
|
|
32
|
-
"main": "index.
|
|
33
|
-
"module": "index.
|
|
32
|
+
"main": "index.js",
|
|
33
|
+
"module": "index.mjs",
|
|
34
34
|
"typings": "index.d.ts",
|
|
35
35
|
"typescript": {
|
|
36
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
|
+
}
|
|
37
47
|
}
|
|
38
48
|
}
|
package/index.cjs.js
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const tslib = require('tslib');
|
|
4
|
-
const commands = require('@graphql-inspector/commands');
|
|
5
|
-
const logger = require('@graphql-inspector/logger');
|
|
6
|
-
const core = require('@graphql-inspector/core');
|
|
7
|
-
const fs = require('fs');
|
|
8
|
-
|
|
9
|
-
const index = commands.createCommand((api) => {
|
|
10
|
-
const { loaders, interceptArguments, interceptPositional, interceptOptions, } = api;
|
|
11
|
-
return {
|
|
12
|
-
command: 'diff <oldSchema> <newSchema>',
|
|
13
|
-
describe: 'Compare two GraphQL Schemas',
|
|
14
|
-
builder(yargs) {
|
|
15
|
-
return yargs
|
|
16
|
-
.positional('oldSchema', interceptPositional('oldSchema', {
|
|
17
|
-
describe: 'Point to an old schema',
|
|
18
|
-
type: 'string',
|
|
19
|
-
demandOption: true,
|
|
20
|
-
}))
|
|
21
|
-
.positional('newSchema', interceptPositional('newSchema', {
|
|
22
|
-
describe: 'Point to a new schema',
|
|
23
|
-
type: 'string',
|
|
24
|
-
demandOption: true,
|
|
25
|
-
}))
|
|
26
|
-
.options(interceptOptions({
|
|
27
|
-
rule: {
|
|
28
|
-
describe: 'Add rules',
|
|
29
|
-
array: true,
|
|
30
|
-
},
|
|
31
|
-
onComplete: {
|
|
32
|
-
describe: 'Handle Completion',
|
|
33
|
-
type: 'string',
|
|
34
|
-
},
|
|
35
|
-
}));
|
|
36
|
-
},
|
|
37
|
-
handler(args) {
|
|
38
|
-
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
39
|
-
try {
|
|
40
|
-
yield interceptArguments(args);
|
|
41
|
-
const oldSchemaPointer = args.oldSchema;
|
|
42
|
-
const newSchemaPointer = args.newSchema;
|
|
43
|
-
const { headers, token } = commands.parseGlobalArgs(args);
|
|
44
|
-
const oldSchema = yield loaders.loadSchema(oldSchemaPointer, {
|
|
45
|
-
headers,
|
|
46
|
-
token,
|
|
47
|
-
});
|
|
48
|
-
const newSchema = yield loaders.loadSchema(newSchemaPointer, {
|
|
49
|
-
headers,
|
|
50
|
-
token,
|
|
51
|
-
});
|
|
52
|
-
const onComplete = args.onComplete
|
|
53
|
-
? resolveCompletionHandler(args.onComplete)
|
|
54
|
-
: failOnBreakingChanges;
|
|
55
|
-
const rules = args.rule
|
|
56
|
-
? args.rule
|
|
57
|
-
.filter(isString)
|
|
58
|
-
.map((name) => {
|
|
59
|
-
const rule = resolveRule(name);
|
|
60
|
-
if (!rule) {
|
|
61
|
-
throw new Error(`\Rule '${name}' does not exist!\n`);
|
|
62
|
-
}
|
|
63
|
-
return rule;
|
|
64
|
-
})
|
|
65
|
-
.filter((f) => f)
|
|
66
|
-
: [];
|
|
67
|
-
const changes = core.diff(oldSchema, newSchema, rules);
|
|
68
|
-
if (changes.length === 0) {
|
|
69
|
-
logger.Logger.success('No changes detected');
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
logger.Logger.log(`\nDetected the following changes (${changes.length}) between schemas:\n`);
|
|
73
|
-
const breakingChanges = changes.filter((change) => change.criticality.level === core.CriticalityLevel.Breaking);
|
|
74
|
-
const dangerousChanges = changes.filter((change) => change.criticality.level === core.CriticalityLevel.Dangerous);
|
|
75
|
-
const nonBreakingChanges = changes.filter((change) => change.criticality.level === core.CriticalityLevel.NonBreaking);
|
|
76
|
-
if (breakingChanges.length) {
|
|
77
|
-
reportBreakingChanges(breakingChanges);
|
|
78
|
-
}
|
|
79
|
-
if (dangerousChanges.length) {
|
|
80
|
-
reportDangerousChanges(dangerousChanges);
|
|
81
|
-
}
|
|
82
|
-
if (nonBreakingChanges.length) {
|
|
83
|
-
reportNonBreakingChanges(nonBreakingChanges);
|
|
84
|
-
}
|
|
85
|
-
onComplete({ breakingChanges, dangerousChanges, nonBreakingChanges });
|
|
86
|
-
}
|
|
87
|
-
catch (error) {
|
|
88
|
-
logger.Logger.error(error);
|
|
89
|
-
throw error;
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
});
|
|
95
|
-
function sortChanges(changes) {
|
|
96
|
-
return changes.slice().sort((a, b) => {
|
|
97
|
-
const aPath = a.path || '';
|
|
98
|
-
const bPath = b.path || '';
|
|
99
|
-
if (aPath > bPath) {
|
|
100
|
-
return 1;
|
|
101
|
-
}
|
|
102
|
-
if (bPath > aPath) {
|
|
103
|
-
return -1;
|
|
104
|
-
}
|
|
105
|
-
return 0;
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
function reportBreakingChanges(changes) {
|
|
109
|
-
const label = logger.symbols.error;
|
|
110
|
-
const sorted = sortChanges(changes);
|
|
111
|
-
sorted.forEach((change) => {
|
|
112
|
-
logger.Logger.log(`${label} ${logger.bolderize(change.message)}`);
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
function reportDangerousChanges(changes) {
|
|
116
|
-
const label = logger.symbols.warning;
|
|
117
|
-
const sorted = sortChanges(changes);
|
|
118
|
-
sorted.forEach((change) => {
|
|
119
|
-
logger.Logger.log(`${label} ${logger.bolderize(change.message)}`);
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
function reportNonBreakingChanges(changes) {
|
|
123
|
-
const label = logger.symbols.success;
|
|
124
|
-
const sorted = sortChanges(changes);
|
|
125
|
-
sorted.forEach((change) => {
|
|
126
|
-
logger.Logger.log(`${label} ${logger.bolderize(change.message)}`);
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
function resolveRule(name) {
|
|
130
|
-
const filepath = commands.ensureAbsolute(name);
|
|
131
|
-
if (fs.existsSync(filepath)) {
|
|
132
|
-
return require(filepath);
|
|
133
|
-
}
|
|
134
|
-
return core.DiffRule[name];
|
|
135
|
-
}
|
|
136
|
-
function resolveCompletionHandler(name) {
|
|
137
|
-
const filepath = commands.ensureAbsolute(name);
|
|
138
|
-
try {
|
|
139
|
-
require.resolve(filepath);
|
|
140
|
-
}
|
|
141
|
-
catch (error) {
|
|
142
|
-
throw new Error(`CompletionHandler '${name}' does not exist!`);
|
|
143
|
-
}
|
|
144
|
-
const mod = require(filepath);
|
|
145
|
-
return (mod === null || mod === void 0 ? void 0 : mod.default) || mod;
|
|
146
|
-
}
|
|
147
|
-
function failOnBreakingChanges({ breakingChanges }) {
|
|
148
|
-
const breakingCount = breakingChanges.length;
|
|
149
|
-
if (breakingCount) {
|
|
150
|
-
logger.Logger.error(`Detected ${breakingCount} breaking change${breakingCount > 1 ? 's' : ''}`);
|
|
151
|
-
process.exit(1);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
logger.Logger.success('No breaking changes detected');
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
function isString(val) {
|
|
158
|
-
return typeof val === 'string';
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
module.exports = index;
|
|
162
|
-
//# sourceMappingURL=index.cjs.js.map
|
package/index.cjs.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../../dist/commands/diff/src/index.js"],"sourcesContent":["import { __awaiter } from \"tslib\";\nimport { createCommand, ensureAbsolute, parseGlobalArgs, } from '@graphql-inspector/commands';\nimport { symbols, Logger, bolderize } from '@graphql-inspector/logger';\nimport { diff as diffSchema, CriticalityLevel, DiffRule, } from '@graphql-inspector/core';\nimport { existsSync } from 'fs';\nexport default createCommand((api) => {\n const { loaders, interceptArguments, interceptPositional, interceptOptions, } = api;\n return {\n command: 'diff <oldSchema> <newSchema>',\n describe: 'Compare two GraphQL Schemas',\n builder(yargs) {\n return yargs\n .positional('oldSchema', interceptPositional('oldSchema', {\n describe: 'Point to an old schema',\n type: 'string',\n demandOption: true,\n }))\n .positional('newSchema', interceptPositional('newSchema', {\n describe: 'Point to a new schema',\n type: 'string',\n demandOption: true,\n }))\n .options(interceptOptions({\n rule: {\n describe: 'Add rules',\n array: true,\n },\n onComplete: {\n describe: 'Handle Completion',\n type: 'string',\n },\n }));\n },\n handler(args) {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n yield interceptArguments(args);\n const oldSchemaPointer = args.oldSchema;\n const newSchemaPointer = args.newSchema;\n const { headers, token } = parseGlobalArgs(args);\n const oldSchema = yield loaders.loadSchema(oldSchemaPointer, {\n headers,\n token,\n });\n const newSchema = yield loaders.loadSchema(newSchemaPointer, {\n headers,\n token,\n });\n const onComplete = args.onComplete\n ? resolveCompletionHandler(args.onComplete)\n : failOnBreakingChanges;\n const rules = args.rule\n ? args.rule\n .filter(isString)\n .map((name) => {\n const rule = resolveRule(name);\n if (!rule) {\n throw new Error(`\\Rule '${name}' does not exist!\\n`);\n }\n return rule;\n })\n .filter((f) => f)\n : [];\n const changes = diffSchema(oldSchema, newSchema, rules);\n if (changes.length === 0) {\n Logger.success('No changes detected');\n return;\n }\n Logger.log(`\\nDetected the following changes (${changes.length}) between schemas:\\n`);\n const breakingChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.Breaking);\n const dangerousChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.Dangerous);\n const nonBreakingChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.NonBreaking);\n if (breakingChanges.length) {\n reportBreakingChanges(breakingChanges);\n }\n if (dangerousChanges.length) {\n reportDangerousChanges(dangerousChanges);\n }\n if (nonBreakingChanges.length) {\n reportNonBreakingChanges(nonBreakingChanges);\n }\n onComplete({ breakingChanges, dangerousChanges, nonBreakingChanges });\n }\n catch (error) {\n Logger.error(error);\n throw error;\n }\n });\n },\n };\n});\nfunction sortChanges(changes) {\n return changes.slice().sort((a, b) => {\n const aPath = a.path || '';\n const bPath = b.path || '';\n if (aPath > bPath) {\n return 1;\n }\n if (bPath > aPath) {\n return -1;\n }\n return 0;\n });\n}\nfunction reportBreakingChanges(changes) {\n const label = symbols.error;\n const sorted = sortChanges(changes);\n sorted.forEach((change) => {\n Logger.log(`${label} ${bolderize(change.message)}`);\n });\n}\nfunction reportDangerousChanges(changes) {\n const label = symbols.warning;\n const sorted = sortChanges(changes);\n sorted.forEach((change) => {\n Logger.log(`${label} ${bolderize(change.message)}`);\n });\n}\nfunction reportNonBreakingChanges(changes) {\n const label = symbols.success;\n const sorted = sortChanges(changes);\n sorted.forEach((change) => {\n Logger.log(`${label} ${bolderize(change.message)}`);\n });\n}\nfunction resolveRule(name) {\n const filepath = ensureAbsolute(name);\n if (existsSync(filepath)) {\n return require(filepath);\n }\n return DiffRule[name];\n}\nfunction resolveCompletionHandler(name) {\n const filepath = ensureAbsolute(name);\n try {\n require.resolve(filepath);\n }\n catch (error) {\n throw new Error(`CompletionHandler '${name}' does not exist!`);\n }\n const mod = require(filepath);\n return (mod === null || mod === void 0 ? void 0 : mod.default) || mod;\n}\nfunction failOnBreakingChanges({ breakingChanges }) {\n const breakingCount = breakingChanges.length;\n if (breakingCount) {\n Logger.error(`Detected ${breakingCount} breaking change${breakingCount > 1 ? 's' : ''}`);\n process.exit(1);\n }\n else {\n Logger.success('No breaking changes detected');\n }\n}\nfunction isString(val) {\n return typeof val === 'string';\n}\n//# sourceMappingURL=index.js.map"],"names":["createCommand","__awaiter","parseGlobalArgs","diffSchema","Logger","CriticalityLevel","symbols","bolderize","ensureAbsolute","existsSync","DiffRule"],"mappings":"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"}
|
package/index.esm.js
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { __awaiter } from 'tslib';
|
|
2
|
-
import { createCommand, parseGlobalArgs, ensureAbsolute } from '@graphql-inspector/commands';
|
|
3
|
-
import { Logger, symbols, bolderize } from '@graphql-inspector/logger';
|
|
4
|
-
import { diff, CriticalityLevel, DiffRule } from '@graphql-inspector/core';
|
|
5
|
-
import { existsSync } from 'fs';
|
|
6
|
-
|
|
7
|
-
const index = createCommand((api) => {
|
|
8
|
-
const { loaders, interceptArguments, interceptPositional, interceptOptions, } = api;
|
|
9
|
-
return {
|
|
10
|
-
command: 'diff <oldSchema> <newSchema>',
|
|
11
|
-
describe: 'Compare two GraphQL Schemas',
|
|
12
|
-
builder(yargs) {
|
|
13
|
-
return yargs
|
|
14
|
-
.positional('oldSchema', interceptPositional('oldSchema', {
|
|
15
|
-
describe: 'Point to an old schema',
|
|
16
|
-
type: 'string',
|
|
17
|
-
demandOption: true,
|
|
18
|
-
}))
|
|
19
|
-
.positional('newSchema', interceptPositional('newSchema', {
|
|
20
|
-
describe: 'Point to a new schema',
|
|
21
|
-
type: 'string',
|
|
22
|
-
demandOption: true,
|
|
23
|
-
}))
|
|
24
|
-
.options(interceptOptions({
|
|
25
|
-
rule: {
|
|
26
|
-
describe: 'Add rules',
|
|
27
|
-
array: true,
|
|
28
|
-
},
|
|
29
|
-
onComplete: {
|
|
30
|
-
describe: 'Handle Completion',
|
|
31
|
-
type: 'string',
|
|
32
|
-
},
|
|
33
|
-
}));
|
|
34
|
-
},
|
|
35
|
-
handler(args) {
|
|
36
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
-
try {
|
|
38
|
-
yield interceptArguments(args);
|
|
39
|
-
const oldSchemaPointer = args.oldSchema;
|
|
40
|
-
const newSchemaPointer = args.newSchema;
|
|
41
|
-
const { headers, token } = parseGlobalArgs(args);
|
|
42
|
-
const oldSchema = yield loaders.loadSchema(oldSchemaPointer, {
|
|
43
|
-
headers,
|
|
44
|
-
token,
|
|
45
|
-
});
|
|
46
|
-
const newSchema = yield loaders.loadSchema(newSchemaPointer, {
|
|
47
|
-
headers,
|
|
48
|
-
token,
|
|
49
|
-
});
|
|
50
|
-
const onComplete = args.onComplete
|
|
51
|
-
? resolveCompletionHandler(args.onComplete)
|
|
52
|
-
: failOnBreakingChanges;
|
|
53
|
-
const rules = args.rule
|
|
54
|
-
? args.rule
|
|
55
|
-
.filter(isString)
|
|
56
|
-
.map((name) => {
|
|
57
|
-
const rule = resolveRule(name);
|
|
58
|
-
if (!rule) {
|
|
59
|
-
throw new Error(`\Rule '${name}' does not exist!\n`);
|
|
60
|
-
}
|
|
61
|
-
return rule;
|
|
62
|
-
})
|
|
63
|
-
.filter((f) => f)
|
|
64
|
-
: [];
|
|
65
|
-
const changes = diff(oldSchema, newSchema, rules);
|
|
66
|
-
if (changes.length === 0) {
|
|
67
|
-
Logger.success('No changes detected');
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
Logger.log(`\nDetected the following changes (${changes.length}) between schemas:\n`);
|
|
71
|
-
const breakingChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.Breaking);
|
|
72
|
-
const dangerousChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.Dangerous);
|
|
73
|
-
const nonBreakingChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.NonBreaking);
|
|
74
|
-
if (breakingChanges.length) {
|
|
75
|
-
reportBreakingChanges(breakingChanges);
|
|
76
|
-
}
|
|
77
|
-
if (dangerousChanges.length) {
|
|
78
|
-
reportDangerousChanges(dangerousChanges);
|
|
79
|
-
}
|
|
80
|
-
if (nonBreakingChanges.length) {
|
|
81
|
-
reportNonBreakingChanges(nonBreakingChanges);
|
|
82
|
-
}
|
|
83
|
-
onComplete({ breakingChanges, dangerousChanges, nonBreakingChanges });
|
|
84
|
-
}
|
|
85
|
-
catch (error) {
|
|
86
|
-
Logger.error(error);
|
|
87
|
-
throw error;
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
});
|
|
93
|
-
function sortChanges(changes) {
|
|
94
|
-
return changes.slice().sort((a, b) => {
|
|
95
|
-
const aPath = a.path || '';
|
|
96
|
-
const bPath = b.path || '';
|
|
97
|
-
if (aPath > bPath) {
|
|
98
|
-
return 1;
|
|
99
|
-
}
|
|
100
|
-
if (bPath > aPath) {
|
|
101
|
-
return -1;
|
|
102
|
-
}
|
|
103
|
-
return 0;
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
function reportBreakingChanges(changes) {
|
|
107
|
-
const label = symbols.error;
|
|
108
|
-
const sorted = sortChanges(changes);
|
|
109
|
-
sorted.forEach((change) => {
|
|
110
|
-
Logger.log(`${label} ${bolderize(change.message)}`);
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
function reportDangerousChanges(changes) {
|
|
114
|
-
const label = symbols.warning;
|
|
115
|
-
const sorted = sortChanges(changes);
|
|
116
|
-
sorted.forEach((change) => {
|
|
117
|
-
Logger.log(`${label} ${bolderize(change.message)}`);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
function reportNonBreakingChanges(changes) {
|
|
121
|
-
const label = symbols.success;
|
|
122
|
-
const sorted = sortChanges(changes);
|
|
123
|
-
sorted.forEach((change) => {
|
|
124
|
-
Logger.log(`${label} ${bolderize(change.message)}`);
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
function resolveRule(name) {
|
|
128
|
-
const filepath = ensureAbsolute(name);
|
|
129
|
-
if (existsSync(filepath)) {
|
|
130
|
-
return require(filepath);
|
|
131
|
-
}
|
|
132
|
-
return DiffRule[name];
|
|
133
|
-
}
|
|
134
|
-
function resolveCompletionHandler(name) {
|
|
135
|
-
const filepath = ensureAbsolute(name);
|
|
136
|
-
try {
|
|
137
|
-
require.resolve(filepath);
|
|
138
|
-
}
|
|
139
|
-
catch (error) {
|
|
140
|
-
throw new Error(`CompletionHandler '${name}' does not exist!`);
|
|
141
|
-
}
|
|
142
|
-
const mod = require(filepath);
|
|
143
|
-
return (mod === null || mod === void 0 ? void 0 : mod.default) || mod;
|
|
144
|
-
}
|
|
145
|
-
function failOnBreakingChanges({ breakingChanges }) {
|
|
146
|
-
const breakingCount = breakingChanges.length;
|
|
147
|
-
if (breakingCount) {
|
|
148
|
-
Logger.error(`Detected ${breakingCount} breaking change${breakingCount > 1 ? 's' : ''}`);
|
|
149
|
-
process.exit(1);
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
Logger.success('No breaking changes detected');
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
function isString(val) {
|
|
156
|
-
return typeof val === 'string';
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export default index;
|
|
160
|
-
//# sourceMappingURL=index.esm.js.map
|
package/index.esm.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../../dist/commands/diff/src/index.js"],"sourcesContent":["import { __awaiter } from \"tslib\";\nimport { createCommand, ensureAbsolute, parseGlobalArgs, } from '@graphql-inspector/commands';\nimport { symbols, Logger, bolderize } from '@graphql-inspector/logger';\nimport { diff as diffSchema, CriticalityLevel, DiffRule, } from '@graphql-inspector/core';\nimport { existsSync } from 'fs';\nexport default createCommand((api) => {\n const { loaders, interceptArguments, interceptPositional, interceptOptions, } = api;\n return {\n command: 'diff <oldSchema> <newSchema>',\n describe: 'Compare two GraphQL Schemas',\n builder(yargs) {\n return yargs\n .positional('oldSchema', interceptPositional('oldSchema', {\n describe: 'Point to an old schema',\n type: 'string',\n demandOption: true,\n }))\n .positional('newSchema', interceptPositional('newSchema', {\n describe: 'Point to a new schema',\n type: 'string',\n demandOption: true,\n }))\n .options(interceptOptions({\n rule: {\n describe: 'Add rules',\n array: true,\n },\n onComplete: {\n describe: 'Handle Completion',\n type: 'string',\n },\n }));\n },\n handler(args) {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n yield interceptArguments(args);\n const oldSchemaPointer = args.oldSchema;\n const newSchemaPointer = args.newSchema;\n const { headers, token } = parseGlobalArgs(args);\n const oldSchema = yield loaders.loadSchema(oldSchemaPointer, {\n headers,\n token,\n });\n const newSchema = yield loaders.loadSchema(newSchemaPointer, {\n headers,\n token,\n });\n const onComplete = args.onComplete\n ? resolveCompletionHandler(args.onComplete)\n : failOnBreakingChanges;\n const rules = args.rule\n ? args.rule\n .filter(isString)\n .map((name) => {\n const rule = resolveRule(name);\n if (!rule) {\n throw new Error(`\\Rule '${name}' does not exist!\\n`);\n }\n return rule;\n })\n .filter((f) => f)\n : [];\n const changes = diffSchema(oldSchema, newSchema, rules);\n if (changes.length === 0) {\n Logger.success('No changes detected');\n return;\n }\n Logger.log(`\\nDetected the following changes (${changes.length}) between schemas:\\n`);\n const breakingChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.Breaking);\n const dangerousChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.Dangerous);\n const nonBreakingChanges = changes.filter((change) => change.criticality.level === CriticalityLevel.NonBreaking);\n if (breakingChanges.length) {\n reportBreakingChanges(breakingChanges);\n }\n if (dangerousChanges.length) {\n reportDangerousChanges(dangerousChanges);\n }\n if (nonBreakingChanges.length) {\n reportNonBreakingChanges(nonBreakingChanges);\n }\n onComplete({ breakingChanges, dangerousChanges, nonBreakingChanges });\n }\n catch (error) {\n Logger.error(error);\n throw error;\n }\n });\n },\n };\n});\nfunction sortChanges(changes) {\n return changes.slice().sort((a, b) => {\n const aPath = a.path || '';\n const bPath = b.path || '';\n if (aPath > bPath) {\n return 1;\n }\n if (bPath > aPath) {\n return -1;\n }\n return 0;\n });\n}\nfunction reportBreakingChanges(changes) {\n const label = symbols.error;\n const sorted = sortChanges(changes);\n sorted.forEach((change) => {\n Logger.log(`${label} ${bolderize(change.message)}`);\n });\n}\nfunction reportDangerousChanges(changes) {\n const label = symbols.warning;\n const sorted = sortChanges(changes);\n sorted.forEach((change) => {\n Logger.log(`${label} ${bolderize(change.message)}`);\n });\n}\nfunction reportNonBreakingChanges(changes) {\n const label = symbols.success;\n const sorted = sortChanges(changes);\n sorted.forEach((change) => {\n Logger.log(`${label} ${bolderize(change.message)}`);\n });\n}\nfunction resolveRule(name) {\n const filepath = ensureAbsolute(name);\n if (existsSync(filepath)) {\n return require(filepath);\n }\n return DiffRule[name];\n}\nfunction resolveCompletionHandler(name) {\n const filepath = ensureAbsolute(name);\n try {\n require.resolve(filepath);\n }\n catch (error) {\n throw new Error(`CompletionHandler '${name}' does not exist!`);\n }\n const mod = require(filepath);\n return (mod === null || mod === void 0 ? void 0 : mod.default) || mod;\n}\nfunction failOnBreakingChanges({ breakingChanges }) {\n const breakingCount = breakingChanges.length;\n if (breakingCount) {\n Logger.error(`Detected ${breakingCount} breaking change${breakingCount > 1 ? 's' : ''}`);\n process.exit(1);\n }\n else {\n Logger.success('No breaking changes detected');\n }\n}\nfunction isString(val) {\n return typeof val === 'string';\n}\n//# sourceMappingURL=index.js.map"],"names":["diffSchema"],"mappings":"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"}
|