UNPKG

5.27 kBJavaScriptView Raw
1import { isValidPath, asArray, AggregateError, parseGraphQLJSON } from '@graphql-tools/utils';
2import { isAbsolute, resolve } from 'path';
3import { existsSync, readFileSync, promises } from 'fs';
4import { cwd, env } from 'process';
5import globby from 'globby';
6import unixify from 'unixify';
7
8const { readFile, access } = promises;
9const FILE_EXTENSIONS = ['.json'];
10function createGlobbyOptions(options) {
11 return { absolute: true, ...options, ignore: [] };
12}
13const buildIgnoreGlob = (path) => `!${path}`;
14/**
15 * This loader loads documents and type definitions from JSON files.
16 *
17 * The JSON file can be the result of an introspection query made against a schema:
18 *
19 * ```js
20 * const schema = await loadSchema('schema-introspection.json', {
21 * loaders: [
22 * new JsonFileLoader()
23 * ]
24 * });
25 * ```
26 *
27 * Or it can be a `DocumentNode` object representing a GraphQL document or type definitions:
28 *
29 * ```js
30 * const documents = await loadDocuments('queries/*.json', {
31 * loaders: [
32 * new GraphQLFileLoader()
33 * ]
34 * });
35 * ```
36 */
37class JsonFileLoader {
38 async canLoad(pointer, options) {
39 if (isValidPath(pointer)) {
40 if (FILE_EXTENSIONS.find(extension => pointer.endsWith(extension))) {
41 const normalizedFilePath = isAbsolute(pointer) ? pointer : resolve(options.cwd || cwd(), pointer);
42 try {
43 await access(normalizedFilePath);
44 return true;
45 }
46 catch (_a) {
47 return false;
48 }
49 }
50 }
51 return false;
52 }
53 canLoadSync(pointer, options) {
54 if (isValidPath(pointer)) {
55 if (FILE_EXTENSIONS.find(extension => pointer.endsWith(extension))) {
56 const normalizedFilePath = isAbsolute(pointer) ? pointer : resolve(options.cwd || cwd(), pointer);
57 return existsSync(normalizedFilePath);
58 }
59 }
60 return false;
61 }
62 _buildGlobs(glob, options) {
63 const ignores = asArray(options.ignore || []);
64 const globs = [unixify(glob), ...ignores.map(v => buildIgnoreGlob(unixify(v)))];
65 return globs;
66 }
67 async resolveGlobs(glob, options) {
68 const globs = this._buildGlobs(glob, options);
69 const result = await globby(globs, createGlobbyOptions(options));
70 return result;
71 }
72 resolveGlobsSync(glob, options) {
73 const globs = this._buildGlobs(glob, options);
74 const result = globby.sync(globs, createGlobbyOptions(options));
75 return result;
76 }
77 async load(pointer, options) {
78 const resolvedPaths = await this.resolveGlobs(pointer, options);
79 const finalResult = [];
80 const errors = [];
81 await Promise.all(resolvedPaths.map(async (path) => {
82 if (await this.canLoad(path, options)) {
83 try {
84 const normalizedFilePath = isAbsolute(path) ? path : resolve(options.cwd || cwd(), path);
85 const rawSDL = await readFile(normalizedFilePath, { encoding: 'utf8' });
86 finalResult.push(this.handleFileContent(normalizedFilePath, rawSDL, options));
87 }
88 catch (e) {
89 if (env['DEBUG']) {
90 console.error(e);
91 }
92 errors.push(e);
93 }
94 }
95 }));
96 if (errors.length > 0 && (options.noSilentErrors || finalResult.length === 0)) {
97 if (errors.length === 1) {
98 throw errors[0];
99 }
100 throw new AggregateError(errors, `Reading from ${pointer} failed ; \n ` + errors.map((e) => e.message).join('\n'));
101 }
102 return finalResult;
103 }
104 loadSync(pointer, options) {
105 const resolvedPaths = this.resolveGlobsSync(pointer, options);
106 const finalResult = [];
107 const errors = [];
108 for (const path of resolvedPaths) {
109 if (this.canLoadSync(path, options)) {
110 try {
111 const normalizedFilePath = isAbsolute(path) ? path : resolve(options.cwd || cwd(), path);
112 const rawSDL = readFileSync(normalizedFilePath, { encoding: 'utf8' });
113 finalResult.push(this.handleFileContent(normalizedFilePath, rawSDL, options));
114 }
115 catch (e) {
116 if (env['DEBUG']) {
117 console.error(e);
118 }
119 errors.push(e);
120 }
121 }
122 }
123 if (errors.length > 0 && (options.noSilentErrors || finalResult.length === 0)) {
124 if (errors.length === 1) {
125 throw errors[0];
126 }
127 throw new AggregateError(errors, `Reading from ${pointer} failed ; \n ` + errors.map((e) => e.message).join('\n'));
128 }
129 return finalResult;
130 }
131 handleFileContent(normalizedFilePath, rawSDL, options) {
132 try {
133 return parseGraphQLJSON(normalizedFilePath, rawSDL, options);
134 }
135 catch (e) {
136 throw new Error(`Unable to read JSON file: ${normalizedFilePath}: ${e.message || /* istanbul ignore next */ e}`);
137 }
138 }
139}
140
141export { JsonFileLoader };