graphql-buddy 0.0.0 → 0.1.1

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.
Files changed (61) hide show
  1. package/README.md +23 -0
  2. package/dist/api.d.ts +42 -8
  3. package/dist/api.js +9 -5
  4. package/dist/chunk-ZIUWDMA7.js +190 -0
  5. package/dist/chunk-ZIUWDMA7.js.map +1 -0
  6. package/dist/cli.js +21 -6
  7. package/dist/cli.js.map +1 -1
  8. package/package.json +1 -1
  9. package/pnpm-workspace.yaml +3 -0
  10. package/src/api/commands/bundle.test.ts +4 -4
  11. package/src/api/commands/bundle.ts +1 -1
  12. package/src/api/commands/validate.test.ts +131 -24
  13. package/src/api/commands/validate.ts +36 -12
  14. package/src/api/shared/GraphqlFiles.ts +61 -0
  15. package/src/api/shared/index.ts +3 -0
  16. package/src/api/shared/loadDocuments.ts +48 -0
  17. package/src/api/shared/loadSchema.ts +11 -57
  18. package/src/api/shared/validateDocuments.ts +97 -0
  19. package/src/cli/commands/validate.ts +22 -5
  20. package/src/cli/index.ts +2 -0
  21. package/test_fixtures/documents/aliased_import/documents/AllFoo.graphql +7 -0
  22. package/test_fixtures/documents/aliased_import/documents/fragments/FooFields.graphql +4 -0
  23. package/test_fixtures/documents/aliased_import/schema/schema.graphql +20 -0
  24. package/test_fixtures/documents/anonymous_operation/documents/Anonymous.graphql +11 -0
  25. package/test_fixtures/documents/anonymous_operation/schema/schema.graphql +20 -0
  26. package/test_fixtures/documents/broken_import/documents/AllFoo.graphql +7 -0
  27. package/test_fixtures/documents/broken_import/schema/schema.graphql +20 -0
  28. package/test_fixtures/documents/duplicate_names/documents/First.graphql +5 -0
  29. package/test_fixtures/documents/duplicate_names/documents/Second.graphql +5 -0
  30. package/test_fixtures/documents/duplicate_names/schema/schema.graphql +20 -0
  31. package/test_fixtures/documents/fragment_library/documents/FooFields.graphql +4 -0
  32. package/test_fixtures/documents/fragment_library/schema/Foo.graphql +7 -0
  33. package/test_fixtures/documents/imported_fragment/documents/AllFoo.graphql +12 -0
  34. package/test_fixtures/documents/imported_fragment/documents/FooFields.graphql +4 -0
  35. package/test_fixtures/documents/imported_fragment/schema/schema.graphql +20 -0
  36. package/test_fixtures/documents/invalid_fragment/documents/FooFields.graphql +4 -0
  37. package/test_fixtures/documents/invalid_fragment/schema/schema.graphql +20 -0
  38. package/test_fixtures/documents/missing_argument/documents/MissingArgument.graphql +5 -0
  39. package/test_fixtures/documents/missing_argument/schema/schema.graphql +20 -0
  40. package/test_fixtures/documents/missing_root_type/documents/AllFoo.graphql +5 -0
  41. package/test_fixtures/documents/missing_root_type/schema/Foo.graphql +7 -0
  42. package/test_fixtures/documents/mixed_sdl/documents/MixedSdl.graphql +9 -0
  43. package/test_fixtures/documents/mixed_sdl/schema/schema.graphql +20 -0
  44. package/test_fixtures/documents/nested_imports/documents/AllFoo.graphql +7 -0
  45. package/test_fixtures/documents/nested_imports/documents/BarFields.graphql +5 -0
  46. package/test_fixtures/documents/nested_imports/documents/FooFields.graphql +8 -0
  47. package/test_fixtures/documents/nested_imports/schema/schema.graphql +20 -0
  48. package/test_fixtures/documents/unknown_field/documents/BadFoo.graphql +6 -0
  49. package/test_fixtures/documents/unknown_field/schema/schema.graphql +20 -0
  50. package/test_fixtures/documents/unused_variable/documents/UnusedVariable.graphql +5 -0
  51. package/test_fixtures/documents/unused_variable/schema/schema.graphql +20 -0
  52. package/dist/chunk-Z7B4AQ2U.js +0 -124
  53. package/dist/chunk-Z7B4AQ2U.js.map +0 -1
  54. /package/test_fixtures/{missing_scalar → schema/missing_scalar}/schema.graphql +0 -0
  55. /package/test_fixtures/{multiple_files → schema/multiple_files}/Bar.graphql +0 -0
  56. /package/test_fixtures/{multiple_files → schema/multiple_files}/Baz.graphql +0 -0
  57. /package/test_fixtures/{multiple_files → schema/multiple_files}/Foo.graphql +0 -0
  58. /package/test_fixtures/{multiple_files → schema/multiple_files}/Mutation.graphql +0 -0
  59. /package/test_fixtures/{multiple_files → schema/multiple_files}/Query.graphql +0 -0
  60. /package/test_fixtures/{single_file → schema/single_file}/schema.graphql +0 -0
  61. /package/test_fixtures/{single_file_with_extra_deps → schema/single_file_with_extra_deps}/schema.graphql +0 -0
package/README.md CHANGED
@@ -63,6 +63,29 @@ For example:
63
63
  npx graphql-buddy validate **/*.graphql
64
64
  ```
65
65
 
66
+ You can also validate GraphQL operations (queries, mutations, subscriptions,
67
+ and fragments) against the schema with `--operations` (`-o`). Each operation is
68
+ checked against the schema, ensuring every referenced field, argument, and type
69
+ exists.
70
+
71
+ ```sh
72
+ npx graphql-buddy validate schema/**/*.graphql --operations 'operations/**/*.graphql'
73
+ ```
74
+
75
+ Operations are validated one file at a time. When an operation depends on a
76
+ fragment defined elsewhere, pull it in with an `#import` (the same mechanism the
77
+ schema loader uses); the imported fragment is resolved before validation:
78
+
79
+ ```graphql
80
+ # import "./FooFields.graphql"
81
+
82
+ query AllFoo {
83
+ allFoo {
84
+ ...FooFields
85
+ }
86
+ }
87
+ ```
88
+
66
89
  For many build systems (such as BUCK and BAZEL) all build steps _must_ emit a
67
90
  file. Validate accomodates this by writing "validation stamps", a file only
68
91
  written if validation is successful and documents the exact settings used during
package/dist/api.d.ts CHANGED
@@ -1,21 +1,53 @@
1
+ import * as graphqlUtils from '@graphql-tools/utils';
1
2
  import * as graphql from 'graphql';
2
3
 
3
- type LoadSchemaOptions = {
4
+ type GraphqlFiles = UnsafeGraphqlFiles | NormalizedGraphqlFiles;
5
+ type UnsafeGraphqlFiles = {
4
6
  normalized?: false | null;
5
7
  files: Array<string>;
6
8
  base?: string | null;
7
9
  pathAliases?: Map<string, string> | null;
8
10
  };
9
- declare const loadSchema: (options: LoadSchemaOptions | NormalizedLoadSchemaOptions) => Promise<graphql.GraphQLSchema>;
10
- type NormalizedLoadSchemaOptions = {
11
+ type NormalizedGraphqlFiles = {
11
12
  normalized: true;
12
13
  files: Array<string>;
13
14
  pathAliases: Map<string, string>;
14
15
  };
15
- declare const normalizeLoadSchemaOptions: (options: LoadSchemaOptions) => Promise<NormalizedLoadSchemaOptions>;
16
+ declare const normalizeGraphqlFiles: (graphqlFiles: GraphqlFiles) => Promise<NormalizedGraphqlFiles>;
17
+
18
+ /**
19
+ * Loads, validates, and parses graphql documents.
20
+ *
21
+ * @param graphqlFiles - Operation or fragment files to process.
22
+ *
23
+ * @returns The parsed GraphQL documents (or throws an error if parsing fails).
24
+ */
25
+ declare const loadDocuments: (graphqlFiles: GraphqlFiles) => Promise<Array<graphqlUtils.Source>>;
26
+
27
+ /**
28
+ * Loads, validates, and parses graphql schema.
29
+ *
30
+ * @param graphqlFiles - Schema files to process.
31
+ *
32
+ * @returns The parsed GraphQL schema (or throws an error if parsing fails).
33
+ */
34
+ declare const loadSchema: (graphqlFiles: GraphqlFiles) => Promise<graphql.GraphQLSchema>;
35
+
36
+ type ValidateDocumentsOptions = {
37
+ schema: graphql.GraphQLSchema;
38
+ documents: Array<graphqlUtils.Source>;
39
+ };
40
+ /**
41
+ * Validates GraphQL documents against their target schema.
42
+ *
43
+ * @param options - Validation options (schema and documents).
44
+ *
45
+ * @throws GraphQLError instances when validation fails.
46
+ */
47
+ declare const validateDocuments: (options: ValidateDocumentsOptions) => void;
16
48
 
17
49
  type BundleOptions = {
18
- schema: LoadSchemaOptions;
50
+ schema: GraphqlFiles;
19
51
  shake?: boolean | null;
20
52
  };
21
53
  /**
@@ -28,11 +60,13 @@ type BundleOptions = {
28
60
  declare const bundle: (options: BundleOptions) => Promise<string>;
29
61
 
30
62
  type ValidateOptions = {
31
- schema: LoadSchemaOptions;
63
+ schema: GraphqlFiles;
64
+ operations?: GraphqlFiles | null;
32
65
  };
33
66
  /**
34
67
  * Validates that the provided GraphQL schema contain valid syntax and have no
35
- * unknown symbols.
68
+ * unknown symbols. When operations are provided, additionally validates that
69
+ * every operation is valid against that schema.
36
70
  *
37
71
  * @param options - Validate options.
38
72
  *
@@ -43,4 +77,4 @@ type ValidateOptions = {
43
77
  */
44
78
  declare const validate: (options: ValidateOptions) => Promise<string>;
45
79
 
46
- export { type BundleOptions, type LoadSchemaOptions, type NormalizedLoadSchemaOptions, type ValidateOptions, bundle, loadSchema, normalizeLoadSchemaOptions, validate };
80
+ export { type BundleOptions, type GraphqlFiles, type NormalizedGraphqlFiles, type UnsafeGraphqlFiles, type ValidateDocumentsOptions, type ValidateOptions, bundle, loadDocuments, loadSchema, normalizeGraphqlFiles, validate, validateDocuments };
package/dist/api.js CHANGED
@@ -1,13 +1,17 @@
1
1
  import {
2
2
  bundle,
3
+ loadDocuments,
3
4
  loadSchema,
4
- normalizeLoadSchemaOptions,
5
- validate
6
- } from "./chunk-Z7B4AQ2U.js";
5
+ normalizeGraphqlFiles,
6
+ validate,
7
+ validateDocuments
8
+ } from "./chunk-ZIUWDMA7.js";
7
9
  export {
8
10
  bundle,
11
+ loadDocuments,
9
12
  loadSchema,
10
- normalizeLoadSchemaOptions,
11
- validate
13
+ normalizeGraphqlFiles,
14
+ validate,
15
+ validateDocuments
12
16
  };
13
17
  //# sourceMappingURL=api.js.map
@@ -0,0 +1,190 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __spreadValues = (a, b) => {
7
+ for (var prop in b || (b = {}))
8
+ if (__hasOwnProp.call(b, prop))
9
+ __defNormalProp(a, prop, b[prop]);
10
+ if (__getOwnPropSymbols)
11
+ for (var prop of __getOwnPropSymbols(b)) {
12
+ if (__propIsEnum.call(b, prop))
13
+ __defNormalProp(a, prop, b[prop]);
14
+ }
15
+ return a;
16
+ };
17
+ var __async = (__this, __arguments, generator) => {
18
+ return new Promise((resolve2, reject) => {
19
+ var fulfilled = (value) => {
20
+ try {
21
+ step(generator.next(value));
22
+ } catch (e) {
23
+ reject(e);
24
+ }
25
+ };
26
+ var rejected = (value) => {
27
+ try {
28
+ step(generator.throw(value));
29
+ } catch (e) {
30
+ reject(e);
31
+ }
32
+ };
33
+ var step = (x) => x.done ? resolve2(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
34
+ step((generator = generator.apply(__this, __arguments)).next());
35
+ });
36
+ };
37
+
38
+ // src/api/commands/bundle.ts
39
+ import * as graphqlToolsUtils from "@graphql-tools/utils";
40
+ import * as graphql2 from "graphql";
41
+
42
+ // src/api/shared/GraphqlFiles.ts
43
+ import * as nodePath from "path";
44
+ import * as glob from "glob";
45
+ var normalizeGraphqlFiles = (graphqlFiles) => __async(null, null, function* () {
46
+ var _a;
47
+ if (graphqlFiles.normalized) {
48
+ return graphqlFiles;
49
+ }
50
+ const base = (_a = graphqlFiles.base) != null ? _a : process.cwd();
51
+ const files = yield glob.glob(
52
+ graphqlFiles.files.map((file) => nodePath.resolve(base, file))
53
+ );
54
+ const pathAliases = /* @__PURE__ */ new Map();
55
+ if (graphqlFiles.pathAliases != null) {
56
+ for (const [alias, source] of graphqlFiles.pathAliases.entries()) {
57
+ pathAliases.set(alias, nodePath.resolve(base, source));
58
+ }
59
+ }
60
+ return {
61
+ normalized: true,
62
+ files,
63
+ pathAliases
64
+ };
65
+ });
66
+
67
+ // src/api/shared/loadDocuments.ts
68
+ import * as nodeFs from "fs/promises";
69
+ import * as graphqlFileLoader from "@graphql-tools/graphql-file-loader";
70
+ import * as graphqlLoad from "@graphql-tools/load";
71
+ var loadDocuments2 = (graphqlFiles) => __async(null, null, function* () {
72
+ const { files, pathAliases } = yield normalizeGraphqlFiles(graphqlFiles);
73
+ for (const file of files) {
74
+ try {
75
+ yield nodeFs.access(file, nodeFs.constants.F_OK);
76
+ } catch (e) {
77
+ throw new Error(`File does not exist: ${file}`);
78
+ }
79
+ }
80
+ return yield graphqlLoad.loadDocuments(files, {
81
+ loaders: [new graphqlFileLoader.GraphQLFileLoader()],
82
+ pathAliases: {
83
+ mappings: Object.fromEntries(pathAliases.entries())
84
+ }
85
+ });
86
+ });
87
+
88
+ // src/api/shared/loadSchema.ts
89
+ import * as nodeFs2 from "fs/promises";
90
+ import * as graphqlFileLoader2 from "@graphql-tools/graphql-file-loader";
91
+ import * as graphqlLoad2 from "@graphql-tools/load";
92
+ var loadSchema2 = (graphqlFiles) => __async(null, null, function* () {
93
+ const { files, pathAliases } = yield normalizeGraphqlFiles(graphqlFiles);
94
+ for (const file of files) {
95
+ try {
96
+ yield nodeFs2.access(file, nodeFs2.constants.F_OK);
97
+ } catch (e) {
98
+ throw new Error(`File does not exist: ${file}`);
99
+ }
100
+ }
101
+ return graphqlLoad2.loadSchema(files, {
102
+ loaders: [new graphqlFileLoader2.GraphQLFileLoader()],
103
+ pathAliases: {
104
+ mappings: Object.fromEntries(pathAliases.entries())
105
+ }
106
+ });
107
+ });
108
+
109
+ // src/api/shared/validateDocuments.ts
110
+ import * as graphql from "graphql";
111
+ var validateDocuments = (options) => {
112
+ const { schema, documents } = options;
113
+ for (const source of documents) {
114
+ if (source.document == null) {
115
+ continue;
116
+ }
117
+ const definesOperation = source.document.definitions.some(
118
+ (definition) => definition.kind === graphql.Kind.OPERATION_DEFINITION
119
+ );
120
+ const errors = graphql.validate(
121
+ schema,
122
+ source.document,
123
+ graphql.specifiedRules.filter(
124
+ (rule) => definesOperation || rule !== graphql.NoUnusedFragmentsRule
125
+ )
126
+ );
127
+ if (errors.length > 0) {
128
+ throw errors[0];
129
+ }
130
+ }
131
+ };
132
+
133
+ // src/api/commands/bundle.ts
134
+ var bundle = (options) => __async(null, null, function* () {
135
+ var _a;
136
+ const shake = (_a = options.shake) != null ? _a : true;
137
+ let schema = yield loadSchema2(options.schema);
138
+ if (shake) {
139
+ schema = graphqlToolsUtils.pruneSchema(schema);
140
+ }
141
+ return graphql2.printSchema(schema);
142
+ });
143
+
144
+ // src/api/commands/validate.ts
145
+ import * as stringifyObject from "stringify-object";
146
+ var validate2 = (options) => __async(null, null, function* () {
147
+ const normalizedSchemaOptions = yield normalizeGraphqlFiles(
148
+ options.schema
149
+ );
150
+ const schema = yield loadSchema2(normalizedSchemaOptions);
151
+ if (options.operations == null) {
152
+ return createValidationStamp({ schema: normalizedSchemaOptions });
153
+ }
154
+ const normalizedOperationsOptions = yield normalizeGraphqlFiles(
155
+ options.operations
156
+ );
157
+ validateDocuments({
158
+ schema,
159
+ documents: yield loadDocuments2(normalizedOperationsOptions)
160
+ });
161
+ return createValidationStamp({
162
+ schema: normalizedSchemaOptions,
163
+ operations: normalizedOperationsOptions
164
+ });
165
+ });
166
+ var createValidationStamp = (options) => stringifyObject.default(
167
+ {
168
+ options: {
169
+ schema: options.schema,
170
+ operations: options.operations
171
+ },
172
+ outcome: { valid: true }
173
+ },
174
+ {
175
+ indent: ` `,
176
+ filter: (container, property) => !(container === options.schema && property === `normalized`) && !(container === options.operations && property === `normalized`)
177
+ }
178
+ );
179
+
180
+ export {
181
+ __spreadValues,
182
+ __async,
183
+ normalizeGraphqlFiles,
184
+ loadDocuments2 as loadDocuments,
185
+ loadSchema2 as loadSchema,
186
+ validateDocuments,
187
+ bundle,
188
+ validate2 as validate
189
+ };
190
+ //# sourceMappingURL=chunk-ZIUWDMA7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/commands/bundle.ts","../src/api/shared/GraphqlFiles.ts","../src/api/shared/loadDocuments.ts","../src/api/shared/loadSchema.ts","../src/api/shared/validateDocuments.ts","../src/api/commands/validate.ts"],"sourcesContent":["import * as graphqlToolsUtils from '@graphql-tools/utils';\nimport * as graphql from 'graphql';\n\nimport * as shared from '../shared';\n\nexport type BundleOptions = {\n schema: shared.GraphqlFiles;\n\n // Defaults to true.\n shake?: boolean | null;\n};\n\n/**\n * Bundles multiple schema together into a single file.\n *\n * @param options - Bundle options.\n *\n * @returns The merged schema as text.\n */\nexport const bundle = async (options: BundleOptions): Promise<string> => {\n const shake = options.shake ?? true;\n\n let schema = await shared.loadSchema(options.schema);\n if (shake) {\n schema = graphqlToolsUtils.pruneSchema(schema);\n }\n\n return graphql.printSchema(schema);\n};\n","import * as nodePath from 'node:path';\n\nimport * as glob from 'glob';\n\nexport type GraphqlFiles = UnsafeGraphqlFiles | NormalizedGraphqlFiles;\n\nexport type UnsafeGraphqlFiles = {\n normalized?: false | null;\n\n // Relative paths will be resolved using `base`.\n //\n // Also accepts glob patterns.\n files: Array<string>;\n\n // Directory from which `files` are resolved.\n //\n // Defaults to `process.cwd()`.\n base?: string | null;\n\n // See @graphql-tools/import#PathAliases\n //\n // Note that relative paths will be resolved relative to `base` to maintain\n // parity with `files`.\n pathAliases?: Map<string, string> | null;\n};\n\nexport type NormalizedGraphqlFiles = {\n normalized: true;\n\n // Absolute paths.\n files: Array<string>;\n\n // See @graphql-tools/import#PathAliases\n pathAliases: Map<string, string>;\n};\n\nexport const normalizeGraphqlFiles = async (\n graphqlFiles: GraphqlFiles,\n): Promise<NormalizedGraphqlFiles> => {\n if (graphqlFiles.normalized) {\n return graphqlFiles;\n }\n\n const base = graphqlFiles.base ?? process.cwd();\n const files = await glob.glob(\n graphqlFiles.files.map((file) => nodePath.resolve(base, file)),\n );\n\n const pathAliases = new Map<string, string>();\n if (graphqlFiles.pathAliases != null) {\n for (const [alias, source] of graphqlFiles.pathAliases.entries()) {\n pathAliases.set(alias, nodePath.resolve(base, source));\n }\n }\n\n return {\n normalized: true,\n files,\n pathAliases,\n };\n};\n","import * as nodeFs from 'node:fs/promises';\n\nimport * as graphqlFileLoader from '@graphql-tools/graphql-file-loader';\nimport * as graphqlLoad from '@graphql-tools/load';\n\nimport type * as graphqlUtils from '@graphql-tools/utils';\n\nimport * as graphqlFilesModule from './GraphqlFiles';\n\n/**\n * Loads, validates, and parses graphql documents.\n *\n * @param graphqlFiles - Operation or fragment files to process.\n *\n * @returns The parsed GraphQL documents (or throws an error if parsing fails).\n */\nexport const loadDocuments = async (\n graphqlFiles: graphqlFilesModule.GraphqlFiles,\n): Promise<Array<graphqlUtils.Source>> => {\n const { files, pathAliases } =\n await graphqlFilesModule.normalizeGraphqlFiles(graphqlFiles);\n\n // @graphql-tools/graphql-file-loader silently skips input files which are not\n // found. I suspect this is so that it can delegate missing inputs to other\n // loaders. For our purposes, this is undesirable because we want to inform\n // clients if expected inputs are missing. For that reason, we manually\n // validate that the files exist first.\n for (const file of files) {\n try {\n await nodeFs.access(file, nodeFs.constants.F_OK);\n } catch {\n throw new Error(`File does not exist: ${file}`);\n }\n }\n\n return await graphqlLoad.loadDocuments(files, {\n loaders: [new graphqlFileLoader.GraphQLFileLoader()],\n pathAliases: {\n mappings: Object.fromEntries(pathAliases.entries()),\n },\n });\n};\n","import * as nodeFs from 'node:fs/promises';\n\nimport * as graphqlFileLoader from '@graphql-tools/graphql-file-loader';\nimport * as graphqlLoad from '@graphql-tools/load';\n\nimport type * as graphql from 'graphql';\n\nimport * as graphqlFilesModule from './GraphqlFiles';\n\n/**\n * Loads, validates, and parses graphql schema.\n *\n * @param graphqlFiles - Schema files to process.\n *\n * @returns The parsed GraphQL schema (or throws an error if parsing fails).\n */\nexport const loadSchema = async (\n graphqlFiles: graphqlFilesModule.GraphqlFiles,\n): Promise<graphql.GraphQLSchema> => {\n const { files, pathAliases } =\n await graphqlFilesModule.normalizeGraphqlFiles(graphqlFiles);\n\n // @graphql-tools/graphql-file-loader silently skips input files which are not\n // found. I suspect this is so that it can delegate missing inputs to other\n // loaders. For our purposes, this is undesirable because we want to inform\n // clients if expected inputs are missing. For that reason, we manually\n // validate that the files exist first.\n for (const file of files) {\n try {\n await nodeFs.access(file, nodeFs.constants.F_OK);\n } catch {\n throw new Error(`File does not exist: ${file}`);\n }\n }\n\n return graphqlLoad.loadSchema(files, {\n loaders: [new graphqlFileLoader.GraphQLFileLoader()],\n pathAliases: {\n mappings: Object.fromEntries(pathAliases.entries()),\n },\n });\n};\n","import * as graphql from 'graphql';\n\nimport type * as graphqlUtils from '@graphql-tools/utils';\n\nexport type ValidateDocumentsOptions = {\n schema: graphql.GraphQLSchema;\n documents: Array<graphqlUtils.Source>;\n};\n\n/**\n * Validates GraphQL documents against their target schema.\n *\n * @param options - Validation options (schema and documents).\n *\n * @throws GraphQLError instances when validation fails.\n */\nexport const validateDocuments = (options: ValidateDocumentsOptions): void => {\n const { schema, documents } = options;\n\n for (const source of documents) {\n if (source.document == null) {\n continue;\n }\n\n // Fragment-only documents are fragment \"libraries\" that operations pull in\n // via `#import`. Validated in isolation they would trip\n // `NoUnusedFragmentsRule`, so we drop that single rule for them. Every\n // other rule, most importantly that each referenced field, argument, and\n // type actually exists, are still enforced.\n const definesOperation = source.document.definitions.some(\n (definition) => definition.kind === graphql.Kind.OPERATION_DEFINITION,\n );\n\n const errors = graphql.validate(\n schema,\n source.document,\n graphql.specifiedRules.filter(\n (rule) => definesOperation || rule !== graphql.NoUnusedFragmentsRule,\n ),\n );\n if (errors.length > 0) {\n throw errors[0];\n }\n }\n};\n","import * as stringifyObject from 'stringify-object';\n\nimport * as shared from '../shared';\n\nexport type ValidateOptions = {\n schema: shared.GraphqlFiles;\n\n // Optional GraphQL operation documents (queries, mutations, subscriptions,\n // and fragments) to validate against the loaded schema. When omitted, only\n // the schema itself is validated.\n operations?: shared.GraphqlFiles | null;\n};\n\n/**\n * Validates that the provided GraphQL schema contain valid syntax and have no\n * unknown symbols. When operations are provided, additionally validates that\n * every operation is valid against that schema.\n *\n * @param options - Validate options.\n *\n * @returns If validation is successful, returns a validation stamp: a text blob\n * describing the successful outcome and options used during validation. This\n * is often useful in build systems where a build step *must* emit a file. If\n * validation fails, a runtime error will be thrown.\n */\nexport const validate = async (options: ValidateOptions): Promise<string> => {\n // We manually normalize the `LoadSchemaOptions` so that we can write the most\n // accurate data in our validation stamp. For example, normalization expands\n // globs and resolves absolute paths. These are critical steps to ensure the\n // validation stamp describes without ambiguity which schema were loaded.\n const normalizedSchemaOptions = await shared.normalizeGraphqlFiles(\n options.schema,\n );\n\n const schema = await shared.loadSchema(normalizedSchemaOptions);\n\n if (options.operations == null) {\n return createValidationStamp({ schema: normalizedSchemaOptions });\n }\n\n const normalizedOperationsOptions = await shared.normalizeGraphqlFiles(\n options.operations,\n );\n shared.validateDocuments({\n schema,\n documents: await shared.loadDocuments(normalizedOperationsOptions),\n });\n\n return createValidationStamp({\n schema: normalizedSchemaOptions,\n operations: normalizedOperationsOptions,\n });\n};\n\nconst createValidationStamp = (options: {\n schema: shared.NormalizedGraphqlFiles;\n operations?: shared.NormalizedGraphqlFiles;\n}): string =>\n stringifyObject.default(\n {\n options: {\n schema: options.schema,\n operations: options.operations,\n },\n outcome: { valid: true },\n },\n {\n indent: ` `,\n filter: (container, property) =>\n !(container === options.schema && property === `normalized`) &&\n !(container === options.operations && property === `normalized`),\n },\n );\n"],"mappings":"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","names":["graphql","loadDocuments","nodeFs","graphqlFileLoader","graphqlLoad","loadSchema","loadSchema","validate","loadSchema","loadDocuments"]}
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  __spreadValues,
5
5
  bundle,
6
6
  validate
7
- } from "./chunk-Z7B4AQ2U.js";
7
+ } from "./chunk-ZIUWDMA7.js";
8
8
 
9
9
  // src/cli/index.ts
10
10
  import * as commander3 from "@commander-js/extra-typings";
@@ -73,12 +73,17 @@ var bundle2 = (options) => __async(null, null, function* () {
73
73
  import * as nodeFs2 from "fs/promises";
74
74
  import * as nodePath2 from "path";
75
75
  import * as commander2 from "@commander-js/extra-typings";
76
- var createValidateCommand = () => new commander2.Command().name(`validate`).description(`Checks that all provided GraphQL files form a valid schema.`).argument(`<schema...>`, `Input GraphQL schema files to validate.`).option(
76
+ var createValidateCommand = () => new commander2.Command().name(`validate`).description(
77
+ `Checks that all provided GraphQL files form a valid schema, and optionally that operations are valid against it.`
78
+ ).argument(`<schema...>`, `Input GraphQL schema files to validate.`).option(
77
79
  `-b, --base <directory>`,
78
80
  `Base directory from which paths are resolved.`
79
81
  ).option(
80
82
  `-a, --alias <pattern...>`,
81
83
  `Path alias options for @graphql-tools/load.`
84
+ ).option(
85
+ `-o, --operations <operations...>`,
86
+ `GraphQL operation documents to validate against the schema.`
82
87
  ).option(
83
88
  `--stamp <file>`,
84
89
  `Creates a validation stamp to confirm valid GraphQL schema.`
@@ -88,14 +93,23 @@ var createValidateCommand = () => new commander2.Command().name(`validate`).desc
88
93
  }, options))
89
94
  );
90
95
  var validate2 = (options) => __async(null, null, function* () {
91
- const { schema, base, alias, stamp, silent } = options;
92
- const validationStamp = yield validate({
96
+ const { schema, base, alias, operations, stamp, silent } = options;
97
+ const pathAliases = parsePathAliases(alias != null ? alias : []);
98
+ const validateOptions = {
93
99
  schema: {
94
100
  files: schema,
95
101
  base,
96
- pathAliases: parsePathAliases(alias != null ? alias : [])
102
+ pathAliases
97
103
  }
98
- });
104
+ };
105
+ if (operations != null) {
106
+ validateOptions.operations = {
107
+ files: operations,
108
+ base,
109
+ pathAliases
110
+ };
111
+ }
112
+ const validationStamp = yield validate(validateOptions);
99
113
  if (stamp != null) {
100
114
  const destination = nodePath2.resolve(base != null ? base : process.cwd(), stamp);
101
115
  yield nodeFs2.writeFile(destination, validationStamp);
@@ -113,6 +127,7 @@ var main = () => {
113
127
  return;
114
128
  }
115
129
  console.error(error);
130
+ process.exit(1);
116
131
  });
117
132
  commander3.program.name(`graphql-buddy`).description(
118
133
  `CLI tools for manipulating graphql // designed for build system tooling.`
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/index.ts","../src/cli/commands/bundle.ts","../src/cli/shared/parsePathAliases.ts","../src/cli/commands/validate.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as commander from '@commander-js/extra-typings';\nimport * as graphql from 'graphql';\n\nimport * as commands from './commands';\n\nconst main = () => {\n process.setUncaughtExceptionCaptureCallback((error) => {\n // When thrown natively, GraphQLError prints like any other error with\n // minimal context, however, when logged with `.toString()` it prints\n // helpful debugging information critical for debugging syntax errors (such\n // as source file, location, symbol, etc...).\n //\n // For example:\n //\n // ```\n // Syntax Error: Expected \":\", found Name \"ID\".\n //\n // src/services/api/schema/CurrentUser.graphql:2:6\n // 1 | type CurrentUser {\n // 2 | id ID!\n // | ^\n // 3 | dateCreated: DateTime!\n // ```\n //\n // Versus the naive output:\n //\n // ```\n // return new _GraphQLError.GraphQLError(`Syntax Error: ${description}`, {\n // GraphQLError: Syntax Error: Expected \":\", found Name \"ID\".\n // at syntaxError (node_modules/graphql/error/syntaxError.js:15:10)\n // ```\n if (error instanceof graphql.GraphQLError) {\n console.error(error.toString());\n return;\n }\n\n console.error(error);\n });\n\n commander.program\n .name(`graphql-buddy`)\n .description(\n `CLI tools for manipulating graphql // designed for build system tooling.`,\n )\n .addCommand(commands.createBundleCommand())\n .addCommand(commands.createValidateCommand())\n .parse();\n};\n\nmain();\n","import * as nodeFs from 'node:fs/promises';\nimport * as nodePath from 'node:path';\n\nimport * as commander from '@commander-js/extra-typings';\n\nimport * as api from '../../api';\nimport * as shared from '../shared';\n\nexport const createBundleCommand = () =>\n new commander.Command()\n .name(`bundle`)\n .description(`Bundles multiple GraphQL inputs into a single file.`)\n .argument(`<schema...>`, `Input GraphQL schema files to bundle.`)\n .option(\n `-b, --base <directory>`,\n `Base directory from which paths are resolved.`,\n )\n .option(\n `-a, --alias <pattern...>`,\n `Path alias options for @graphql-tools/load.`,\n )\n .option(\n `--out <file>`,\n `Where to write the bundled schema.`,\n `bundle.graphql`,\n )\n .option(`--no-shake`, `Prevents pruning of unused types.`)\n .option(`-s, --silent`, `Only log critical information.`, false)\n .action((schema, options) =>\n bundle({\n schema,\n ...options,\n }),\n );\n\nconst bundle = async (options: {\n schema: Array<string>;\n base?: string;\n alias?: Array<string>;\n out: string;\n shake: boolean;\n silent: boolean;\n}): Promise<void> => {\n const { schema, base, alias, shake, silent } = options;\n const out = nodePath.resolve(base ?? process.cwd(), options.out);\n\n await nodeFs.writeFile(\n out,\n await api.bundle({\n schema: {\n files: schema,\n base,\n pathAliases: shared.parsePathAliases(alias ?? []),\n },\n shake,\n }),\n );\n\n if (!silent) {\n console.log(`✅ bundler encountered no errors.`);\n }\n};\n","export type PathAliases = Map<string, string>;\n\nexport const parsePathAliases = (\n encodedAliases: Array<string>,\n): PathAliases => {\n const decodedAliases = new Map<string, string>();\n\n for (const encodedAlias of encodedAliases) {\n const parts = encodedAlias.split(`=`);\n if (parts.length !== 2) {\n throw new Error(\n `Expected an alias in the form \"alias=source\" but found \"${encodedAlias}\"`,\n );\n }\n\n const [alias, source] = parts;\n if (decodedAliases.has(alias)) {\n throw new Error(`Alias \"${alias}\" is set multiple times.`);\n }\n\n decodedAliases.set(alias, source);\n }\n\n return decodedAliases;\n};\n","import * as nodeFs from 'node:fs/promises';\nimport * as nodePath from 'node:path';\n\nimport * as commander from '@commander-js/extra-typings';\n\nimport * as api from '../../api';\nimport * as shared from '../shared';\n\nexport const createValidateCommand = () =>\n new commander.Command()\n .name(`validate`)\n .description(`Checks that all provided GraphQL files form a valid schema.`)\n .argument(`<schema...>`, `Input GraphQL schema files to validate.`)\n .option(\n `-b, --base <directory>`,\n `Base directory from which paths are resolved.`,\n )\n .option(\n `-a, --alias <pattern...>`,\n `Path alias options for @graphql-tools/load.`,\n )\n .option(\n `--stamp <file>`,\n `Creates a validation stamp to confirm valid GraphQL schema.`,\n )\n .option(`-s, --silent`, `Only log critical information.`, false)\n .action((schema, options) =>\n validate({\n schema,\n ...options,\n }),\n );\n\nconst validate = async (options: {\n schema: Array<string>;\n base?: string;\n alias?: Array<string>;\n stamp?: string;\n silent: boolean;\n}): Promise<void> => {\n const { schema, base, alias, stamp, silent } = options;\n\n const validationStamp = await api.validate({\n schema: {\n files: schema,\n base,\n pathAliases: shared.parsePathAliases(alias ?? []),\n },\n });\n\n if (stamp != null) {\n const destination = nodePath.resolve(base ?? process.cwd(), stamp);\n await nodeFs.writeFile(destination, validationStamp);\n }\n\n if (!silent) {\n console.log(`✅ validation encountered no errors.`);\n }\n};\n"],"mappings":"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","names":["commander","bundle","nodeFs","nodePath","commander","validate"]}
1
+ {"version":3,"sources":["../src/cli/index.ts","../src/cli/commands/bundle.ts","../src/cli/shared/parsePathAliases.ts","../src/cli/commands/validate.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as commander from '@commander-js/extra-typings';\nimport * as graphql from 'graphql';\n\nimport * as commands from './commands';\n\nconst main = () => {\n process.setUncaughtExceptionCaptureCallback((error) => {\n // When thrown natively, GraphQLError prints like any other error with\n // minimal context, however, when logged with `.toString()` it prints\n // helpful debugging information critical for debugging syntax errors (such\n // as source file, location, symbol, etc...).\n //\n // For example:\n //\n // ```\n // Syntax Error: Expected \":\", found Name \"ID\".\n //\n // src/services/api/schema/CurrentUser.graphql:2:6\n // 1 | type CurrentUser {\n // 2 | id ID!\n // | ^\n // 3 | dateCreated: DateTime!\n // ```\n //\n // Versus the naive output:\n //\n // ```\n // return new _GraphQLError.GraphQLError(`Syntax Error: ${description}`, {\n // GraphQLError: Syntax Error: Expected \":\", found Name \"ID\".\n // at syntaxError (node_modules/graphql/error/syntaxError.js:15:10)\n // ```\n if (error instanceof graphql.GraphQLError) {\n console.error(error.toString());\n return;\n }\n\n console.error(error);\n\n process.exit(1);\n });\n\n commander.program\n .name(`graphql-buddy`)\n .description(\n `CLI tools for manipulating graphql // designed for build system tooling.`,\n )\n .addCommand(commands.createBundleCommand())\n .addCommand(commands.createValidateCommand())\n .parse();\n};\n\nmain();\n","import * as nodeFs from 'node:fs/promises';\nimport * as nodePath from 'node:path';\n\nimport * as commander from '@commander-js/extra-typings';\n\nimport * as api from '../../api';\nimport * as shared from '../shared';\n\nexport const createBundleCommand = () =>\n new commander.Command()\n .name(`bundle`)\n .description(`Bundles multiple GraphQL inputs into a single file.`)\n .argument(`<schema...>`, `Input GraphQL schema files to bundle.`)\n .option(\n `-b, --base <directory>`,\n `Base directory from which paths are resolved.`,\n )\n .option(\n `-a, --alias <pattern...>`,\n `Path alias options for @graphql-tools/load.`,\n )\n .option(\n `--out <file>`,\n `Where to write the bundled schema.`,\n `bundle.graphql`,\n )\n .option(`--no-shake`, `Prevents pruning of unused types.`)\n .option(`-s, --silent`, `Only log critical information.`, false)\n .action((schema, options) =>\n bundle({\n schema,\n ...options,\n }),\n );\n\nconst bundle = async (options: {\n schema: Array<string>;\n base?: string;\n alias?: Array<string>;\n out: string;\n shake: boolean;\n silent: boolean;\n}): Promise<void> => {\n const { schema, base, alias, shake, silent } = options;\n const out = nodePath.resolve(base ?? process.cwd(), options.out);\n\n await nodeFs.writeFile(\n out,\n await api.bundle({\n schema: {\n files: schema,\n base,\n pathAliases: shared.parsePathAliases(alias ?? []),\n },\n shake,\n }),\n );\n\n if (!silent) {\n console.log(`✅ bundler encountered no errors.`);\n }\n};\n","export type PathAliases = Map<string, string>;\n\nexport const parsePathAliases = (\n encodedAliases: Array<string>,\n): PathAliases => {\n const decodedAliases = new Map<string, string>();\n\n for (const encodedAlias of encodedAliases) {\n const parts = encodedAlias.split(`=`);\n if (parts.length !== 2) {\n throw new Error(\n `Expected an alias in the form \"alias=source\" but found \"${encodedAlias}\"`,\n );\n }\n\n const [alias, source] = parts;\n if (decodedAliases.has(alias)) {\n throw new Error(`Alias \"${alias}\" is set multiple times.`);\n }\n\n decodedAliases.set(alias, source);\n }\n\n return decodedAliases;\n};\n","import * as nodeFs from 'node:fs/promises';\nimport * as nodePath from 'node:path';\n\nimport * as commander from '@commander-js/extra-typings';\n\nimport * as api from '../../api';\nimport * as shared from '../shared';\n\nexport const createValidateCommand = () =>\n new commander.Command()\n .name(`validate`)\n .description(\n `Checks that all provided GraphQL files form a valid schema, and optionally that operations are valid against it.`,\n )\n .argument(`<schema...>`, `Input GraphQL schema files to validate.`)\n .option(\n `-b, --base <directory>`,\n `Base directory from which paths are resolved.`,\n )\n .option(\n `-a, --alias <pattern...>`,\n `Path alias options for @graphql-tools/load.`,\n )\n .option(\n `-o, --operations <operations...>`,\n `GraphQL operation documents to validate against the schema.`,\n )\n .option(\n `--stamp <file>`,\n `Creates a validation stamp to confirm valid GraphQL schema.`,\n )\n .option(`-s, --silent`, `Only log critical information.`, false)\n .action((schema, options) =>\n validate({\n schema,\n ...options,\n }),\n );\n\nconst validate = async (options: {\n schema: Array<string>;\n base?: string;\n alias?: Array<string>;\n operations?: Array<string>;\n stamp?: string;\n silent: boolean;\n}): Promise<void> => {\n const { schema, base, alias, operations, stamp, silent } = options;\n\n const pathAliases = shared.parsePathAliases(alias ?? []);\n\n const validateOptions: api.ValidateOptions = {\n schema: {\n files: schema,\n base,\n pathAliases,\n },\n };\n if (operations != null) {\n validateOptions.operations = {\n files: operations,\n base,\n pathAliases,\n };\n }\n const validationStamp = await api.validate(validateOptions);\n\n if (stamp != null) {\n const destination = nodePath.resolve(base ?? process.cwd(), stamp);\n await nodeFs.writeFile(destination, validationStamp);\n }\n\n if (!silent) {\n console.log(`✅ validation encountered no errors.`);\n }\n};\n"],"mappings":"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","names":["commander","bundle","nodeFs","nodePath","commander","validate"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphql-buddy",
3
- "version": "0.0.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Hunter John Larco",
@@ -1,3 +1,6 @@
1
+ allowBuilds:
2
+ esbuild: true
3
+ unrs-resolver: true
1
4
  onlyBuiltDependencies:
2
5
  - esbuild
3
6
  - unrs-resolver
@@ -12,7 +12,7 @@ describe(`bundle`, () => {
12
12
  files: [`*.graphql`],
13
13
  base: nodePath.resolve(
14
14
  __dirname,
15
- `../../../test_fixtures/single_file`,
15
+ `../../../test_fixtures/schema/single_file`,
16
16
  ),
17
17
  },
18
18
  }),
@@ -43,7 +43,7 @@ type Bar {
43
43
  files: [`*.graphql`],
44
44
  base: nodePath.resolve(
45
45
  __dirname,
46
- `../../../test_fixtures/multiple_files`,
46
+ `../../../test_fixtures/schema/multiple_files`,
47
47
  ),
48
48
  },
49
49
  }),
@@ -87,7 +87,7 @@ type Query {
87
87
  files: [`*.graphql`],
88
88
  base: nodePath.resolve(
89
89
  __dirname,
90
- `../../../test_fixtures/single_file_with_extra_deps`,
90
+ `../../../test_fixtures/schema/single_file_with_extra_deps`,
91
91
  ),
92
92
  },
93
93
  }),
@@ -129,7 +129,7 @@ type FooEvent {
129
129
  files: [`*.graphql`],
130
130
  base: nodePath.resolve(
131
131
  __dirname,
132
- `../../../test_fixtures/missing_scalar`,
132
+ `../../../test_fixtures/schema/missing_scalar`,
133
133
  ),
134
134
  },
135
135
  }),
@@ -4,7 +4,7 @@ import * as graphql from 'graphql';
4
4
  import * as shared from '../shared';
5
5
 
6
6
  export type BundleOptions = {
7
- schema: shared.LoadSchemaOptions;
7
+ schema: shared.GraphqlFiles;
8
8
 
9
9
  // Defaults to true.
10
10
  shake?: boolean | null;