@graphql-inspector/coverage-command 3.1.2 → 3.1.3

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
File without changes
File without changes
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@graphql-inspector/coverage-command",
3
+ "version": "3.1.3",
4
+ "description": "Schema Coverage in GraphQL Inspector",
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.3",
11
+ "@graphql-inspector/core": "3.1.3",
12
+ "@graphql-inspector/logger": "3.1.3",
13
+ "tslib": "^2.0.0"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "kamilkisiela/graphql-inspector",
18
+ "directory": "packages/commands/coverage"
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/package.json CHANGED
@@ -1,48 +1,51 @@
1
1
  {
2
2
  "name": "@graphql-inspector/coverage-command",
3
- "version": "3.1.2",
3
+ "version": "3.1.3",
4
4
  "description": "Schema Coverage in GraphQL Inspector",
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.2",
11
- "@graphql-inspector/core": "3.1.2",
12
- "@graphql-inspector/logger": "3.1.2",
13
- "tslib": "^2.0.0"
14
- },
15
- "repository": {
16
- "type": "git",
17
- "url": "kamilkisiela/graphql-inspector",
18
- "directory": "packages/commands/coverage"
19
- },
20
5
  "keywords": [
21
6
  "graphql",
22
7
  "graphql-inspector",
23
8
  "graphql-inspector-command",
24
9
  "tools"
25
10
  ],
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
+ },
26
28
  "author": {
27
29
  "name": "Kamil Kisiela",
28
30
  "email": "kamil.kisiela@gmail.com",
29
31
  "url": "https://github.com/kamilkisiela"
30
32
  },
31
33
  "license": "MIT",
32
- "main": "index.js",
33
- "module": "index.mjs",
34
- "typings": "index.d.ts",
35
- "typescript": {
36
- "definition": "index.d.ts"
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "kamilkisiela/graphql-inspector",
37
+ "directory": "packages/commands/coverage"
37
38
  },
38
- "exports": {
39
- ".": {
40
- "require": "./index.js",
41
- "import": "./index.mjs"
42
- },
43
- "./*": {
44
- "require": "./*.js",
45
- "import": "./*.mjs"
46
- }
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.3",
44
+ "@graphql-inspector/core": "3.1.3",
45
+ "@graphql-inspector/logger": "3.1.3",
46
+ "tslib": "^2.0.0"
47
+ },
48
+ "scripts": {
49
+ "prepack": "bob prepack"
47
50
  }
48
51
  }
package/src/index.ts ADDED
@@ -0,0 +1,180 @@
1
+ import {
2
+ createCommand,
3
+ GlobalArgs,
4
+ ensureAbsolute,
5
+ parseGlobalArgs,
6
+ CommandFactory,
7
+ } from '@graphql-inspector/commands';
8
+ import { Logger, chalk } from '@graphql-inspector/logger';
9
+ import {
10
+ coverage as calculateCoverage,
11
+ SchemaCoverage,
12
+ getTypePrefix,
13
+ } from '@graphql-inspector/core';
14
+ import { Source as DocumentSource } from '@graphql-tools/utils';
15
+ import { Source, print, GraphQLSchema } from 'graphql';
16
+ import { extname } from 'path';
17
+ import { writeFileSync } from 'fs';
18
+
19
+ export { CommandFactory };
20
+
21
+ export function handler({
22
+ schema,
23
+ documents,
24
+ silent,
25
+ writePath,
26
+ }: {
27
+ schema: GraphQLSchema;
28
+ documents: DocumentSource[];
29
+ silent?: boolean;
30
+ writePath?: string;
31
+ }) {
32
+ const shouldWrite = typeof writePath !== 'undefined';
33
+ const coverage = calculateCoverage(
34
+ schema,
35
+ documents.map((doc) => new Source(print(doc.document!), doc.location)),
36
+ );
37
+
38
+ if (silent !== true) {
39
+ renderCoverage(coverage);
40
+ }
41
+
42
+ if (shouldWrite) {
43
+ if (typeof writePath !== 'string') {
44
+ throw new Error(`--write is not valid file path: ${writePath}`);
45
+ }
46
+
47
+ const absPath = ensureAbsolute(writePath);
48
+ const ext = extname(absPath).replace('.', '').toLocaleLowerCase();
49
+
50
+ let output: string | undefined = undefined;
51
+
52
+ if (ext === 'json') {
53
+ output = outputJSON(coverage);
54
+ }
55
+
56
+ if (output) {
57
+ writeFileSync(absPath, output, {
58
+ encoding: 'utf-8',
59
+ });
60
+
61
+ Logger.success(`Available at ${absPath}\n`);
62
+ } else {
63
+ throw new Error(`Extension ${ext} is not supported`);
64
+ }
65
+ }
66
+ }
67
+
68
+ export default createCommand<
69
+ {},
70
+ {
71
+ schema: string;
72
+ documents: string;
73
+ write?: string;
74
+ silent?: boolean;
75
+ } & GlobalArgs
76
+ >((api) => {
77
+ const { loaders } = api;
78
+
79
+ return {
80
+ command: 'coverage <documents> <schema>',
81
+ describe: 'Schema coverage based on documents',
82
+ builder(yargs) {
83
+ return yargs
84
+ .positional('schema', {
85
+ describe: 'Point to a schema',
86
+ type: 'string',
87
+ demandOption: true,
88
+ })
89
+ .positional('documents', {
90
+ describe: 'Point to documents',
91
+ type: 'string',
92
+ demandOption: true,
93
+ })
94
+ .options({
95
+ w: {
96
+ alias: 'write',
97
+ describe: 'Write a file with coverage stats',
98
+ type: 'string',
99
+ },
100
+ s: {
101
+ alias: 'silent',
102
+ describe: 'Do not render any stats in the terminal',
103
+ type: 'boolean',
104
+ },
105
+ });
106
+ },
107
+ async handler(args) {
108
+ const writePath = args.write;
109
+ const silent = args.silent;
110
+ const { headers, token } = parseGlobalArgs(args);
111
+ const apolloFederation = args.federation || false;
112
+ const aws = args.aws || false;
113
+ const method = args.method?.toUpperCase() || 'POST';
114
+
115
+ const schema = await loaders.loadSchema(
116
+ args.schema,
117
+ {
118
+ token,
119
+ headers,
120
+ method,
121
+ },
122
+ apolloFederation,
123
+ aws,
124
+ );
125
+ const documents = await loaders.loadDocuments(args.documents);
126
+
127
+ return handler({ schema, documents, silent, writePath });
128
+ },
129
+ };
130
+ });
131
+
132
+ function outputJSON(coverage: SchemaCoverage): string {
133
+ return JSON.stringify(coverage, null, 2);
134
+ }
135
+
136
+ function renderCoverage(coverage: SchemaCoverage) {
137
+ Logger.info('Schema coverage based on documents:\n');
138
+
139
+ for (const typeName in coverage.types) {
140
+ if (coverage.types.hasOwnProperty(typeName)) {
141
+ const typeCoverage = coverage.types[typeName];
142
+
143
+ Logger.log(
144
+ [
145
+ chalk.grey(getTypePrefix(typeCoverage.type)),
146
+ chalk.bold(`${typeName}`),
147
+ chalk.grey('{'),
148
+ ].join(' '),
149
+ );
150
+
151
+ for (const childName in typeCoverage.children) {
152
+ if (typeCoverage.children.hasOwnProperty(childName)) {
153
+ const childCoverage = typeCoverage.children[childName];
154
+
155
+ if (childCoverage.hits) {
156
+ Logger.log(
157
+ [
158
+ indent(childName, 2),
159
+ chalk.italic.grey(`x ${childCoverage.hits}`),
160
+ ].join(' '),
161
+ );
162
+ } else {
163
+ Logger.log(
164
+ [
165
+ chalk.redBright(indent(childName, 2)),
166
+ chalk.italic.grey('x 0'),
167
+ ].join(' '),
168
+ );
169
+ }
170
+ }
171
+ }
172
+
173
+ Logger.log(chalk.grey('}\n'));
174
+ }
175
+ }
176
+ }
177
+
178
+ function indent(line: string, space: number): string {
179
+ return line.padStart(line.length + space, ' ');
180
+ }