1 | import { fetchFactory } from 'fetchache';
|
2 | import { fetch, Request, Response, Headers } from 'cross-fetch';
|
3 | import isUrl from 'is-url';
|
4 | export { default as isUrl } from 'is-url';
|
5 | import { load } from 'js-yaml';
|
6 | import { isAbsolute, resolve, join, dirname } from 'path';
|
7 | import { promises, readFileSync } from 'fs';
|
8 | import { Interpolator } from '@ardatan/string-interpolation';
|
9 | import { format } from 'date-fns';
|
10 | import objectHash from 'object-hash';
|
11 | import { isInputType, GraphQLInt, GraphQLFloat, GraphQLBoolean, GraphQLString, GraphQLID, parse, print } from 'graphql';
|
12 | import { getResolversFromSchema } from '@graphql-tools/utils';
|
13 | import flatstr from 'flatstr';
|
14 | import lru from 'tiny-lru';
|
15 | import { compileQuery, isCompiledQuery } from 'graphql-jit';
|
16 |
|
17 | const { readFile, stat } = promises || {};
|
18 | function getCachedFetch(cache) {
|
19 | return fetchFactory({
|
20 | fetch,
|
21 | Request,
|
22 | Response,
|
23 | cache,
|
24 | });
|
25 | }
|
26 | async function readFileOrUrlWithCache(filePathOrUrl, cache, config) {
|
27 | if (isUrl(filePathOrUrl)) {
|
28 | return readUrlWithCache(filePathOrUrl, cache, config);
|
29 | }
|
30 | else {
|
31 | return readFileWithCache(filePathOrUrl, cache, config);
|
32 | }
|
33 | }
|
34 | async function readFileWithCache(filePath, cache, config) {
|
35 | const { allowUnknownExtensions, cwd, fallbackFormat } = config || {};
|
36 | const actualPath = isAbsolute(filePath) ? filePath : resolve(cwd || process.cwd(), filePath);
|
37 | const cachedObj = await cache.get(actualPath);
|
38 | const stats = await stat(actualPath);
|
39 | if (cachedObj) {
|
40 | if (stats.mtimeMs <= cachedObj.mtimeMs) {
|
41 | return cachedObj.result;
|
42 | }
|
43 | }
|
44 | let result = await readFile(actualPath, 'utf-8');
|
45 | if (/json$/.test(filePath)) {
|
46 | result = JSON.parse(result);
|
47 | }
|
48 | else if (/yaml$/.test(filePath) || /yml$/.test(filePath)) {
|
49 | result = load(result);
|
50 | }
|
51 | else if (fallbackFormat) {
|
52 | switch (fallbackFormat) {
|
53 | case 'json':
|
54 | result = JSON.parse(result);
|
55 | break;
|
56 | case 'yaml':
|
57 | result = load(result);
|
58 | break;
|
59 | }
|
60 | }
|
61 | else if (!allowUnknownExtensions) {
|
62 | throw new Error(`Failed to parse JSON/YAML. Ensure file '${filePath}' has ` +
|
63 | `the correct extension (i.e. '.json', '.yaml', or '.yml).`);
|
64 | }
|
65 | cache.set(filePath, { result, mtimeMs: stats.mtimeMs });
|
66 | return result;
|
67 | }
|
68 | async function readUrlWithCache(path, cache, config) {
|
69 | var _a;
|
70 | const { allowUnknownExtensions, fallbackFormat } = config || {};
|
71 | const fetch = (config === null || config === void 0 ? void 0 : config.fetch) || getCachedFetch(cache);
|
72 | const response = await fetch(path, config);
|
73 | const contentType = ((_a = response.headers) === null || _a === void 0 ? void 0 : _a.get('content-type')) || '';
|
74 | const responseText = await response.text();
|
75 | if (/json$/.test(path) || contentType.startsWith('application/json') || fallbackFormat === 'json') {
|
76 | return JSON.parse(responseText);
|
77 | }
|
78 | else if (/yaml$/.test(path) ||
|
79 | /yml$/.test(path) ||
|
80 | contentType.includes('yaml') ||
|
81 | contentType.includes('yml') ||
|
82 | fallbackFormat === 'yaml') {
|
83 | return load(responseText);
|
84 | }
|
85 | else if (!allowUnknownExtensions) {
|
86 | throw new Error(`Failed to parse JSON/YAML. Ensure URL '${path}' has ` +
|
87 | `the correct extension (i.e. '.json', '.yaml', or '.yml) or mime type in the response headers.`);
|
88 | }
|
89 | return responseText;
|
90 | }
|
91 |
|
92 | const stringInterpolator = new Interpolator({
|
93 | delimiter: ['{', '}'],
|
94 | });
|
95 | stringInterpolator.addAlias('typeName', 'info.parentType.name');
|
96 | stringInterpolator.addAlias('type', 'info.parentType.name');
|
97 | stringInterpolator.addAlias('parentType', 'info.parentType.name');
|
98 | stringInterpolator.addAlias('fieldName', 'info.fieldName');
|
99 | stringInterpolator.registerModifier('date', (formatStr) => format(new Date(), formatStr));
|
100 | stringInterpolator.registerModifier('hash', (value) => objectHash(value, { ignoreUnknown: true }));
|
101 |
|
102 | async function loadFromModuleExportExpression(expression, options) {
|
103 | if (typeof expression !== 'string') {
|
104 | return expression;
|
105 | }
|
106 | const { defaultExportName, cwd } = options || {};
|
107 | const [modulePath, exportName = defaultExportName] = expression.split('#');
|
108 | const mod = await tryImport(modulePath, cwd);
|
109 | if (exportName === 'default' || !exportName) {
|
110 | return mod.default || mod;
|
111 | }
|
112 | else {
|
113 | return mod[exportName] || (mod.default && mod.default[exportName]);
|
114 | }
|
115 | }
|
116 | async function tryImport(modulePath, cwd) {
|
117 | try {
|
118 | return await import(modulePath);
|
119 | }
|
120 | catch (e1) {
|
121 | if (!isAbsolute(modulePath)) {
|
122 | try {
|
123 | const absoluteModulePath = isAbsolute(modulePath) ? modulePath : join(cwd || process.cwd(), modulePath);
|
124 | return await import(absoluteModulePath);
|
125 | }
|
126 | catch (e2) {
|
127 | if (e2.message.includes('Cannot find module')) {
|
128 | throw e1;
|
129 | }
|
130 | else {
|
131 | throw e2;
|
132 | }
|
133 | }
|
134 | }
|
135 | throw e1;
|
136 | }
|
137 | }
|
138 | function loadFromModuleExportExpressionSync(expression, options) {
|
139 | if (typeof expression !== 'string') {
|
140 | return expression;
|
141 | }
|
142 | const { defaultExportName, cwd } = options || {};
|
143 | const [modulePath, exportName = defaultExportName] = expression.split('#');
|
144 | const mod = tryImportSync(modulePath, cwd);
|
145 | if (exportName === 'default' || !exportName) {
|
146 | return mod.default || mod;
|
147 | }
|
148 | else {
|
149 | return mod[exportName] || (mod.default && mod.default[exportName]);
|
150 | }
|
151 | }
|
152 | function tryImportSync(modulePath, cwd) {
|
153 | try {
|
154 | return require(modulePath);
|
155 | }
|
156 | catch (e1) {
|
157 | if (!isAbsolute(modulePath)) {
|
158 | try {
|
159 | const absoluteModulePath = isAbsolute(modulePath) ? modulePath : join(cwd || process.cwd(), modulePath);
|
160 | return require(absoluteModulePath);
|
161 | }
|
162 | catch (e2) {
|
163 | if (e2.message.includes('Cannot find module')) {
|
164 | throw e1;
|
165 | }
|
166 | else {
|
167 | throw e2;
|
168 | }
|
169 | }
|
170 | }
|
171 | throw e1;
|
172 | }
|
173 | }
|
174 |
|
175 | var ArgType;
|
176 | (function (ArgType) {
|
177 | ArgType["ID"] = "ID";
|
178 | ArgType["String"] = "String";
|
179 | ArgType["Boolean"] = "Boolean";
|
180 | ArgType["Float"] = "Float";
|
181 | ArgType["Int"] = "Int";
|
182 | })(ArgType || (ArgType = {}));
|
183 | function getInputTypeFromTypeName(typeName) {
|
184 | if (isInputType(typeName)) {
|
185 | return typeName;
|
186 | }
|
187 | else {
|
188 | switch (typeName) {
|
189 | case ArgType.ID:
|
190 | return GraphQLID;
|
191 | case ArgType.String:
|
192 | return GraphQLString;
|
193 | case ArgType.Boolean:
|
194 | return GraphQLBoolean;
|
195 | case ArgType.Float:
|
196 | return GraphQLFloat;
|
197 | case ArgType.Int:
|
198 | return GraphQLInt;
|
199 | }
|
200 | }
|
201 | }
|
202 | function parseInterpolationStrings(interpolationStrings, argTypeMap) {
|
203 | const interpolationKeys = interpolationStrings.reduce((keys, str) => [...keys, ...(str ? stringInterpolator.parseRules(str).map((match) => match.key) : [])], []);
|
204 | const args = {};
|
205 | const contextVariables = [];
|
206 | for (const interpolationKey of interpolationKeys) {
|
207 | const interpolationKeyParts = interpolationKey.split('.');
|
208 | const varName = interpolationKeyParts[interpolationKeyParts.length - 1];
|
209 | if (interpolationKeyParts[0] === 'args') {
|
210 | const argType = argTypeMap && varName in argTypeMap ? getInputTypeFromTypeName(argTypeMap[varName]) : GraphQLID;
|
211 | args[varName] = {
|
212 | type: argType,
|
213 | };
|
214 | }
|
215 | else if (interpolationKeyParts[0] === 'context') {
|
216 | contextVariables.push(varName);
|
217 | }
|
218 | }
|
219 | return {
|
220 | args,
|
221 | contextVariables,
|
222 | };
|
223 | }
|
224 | function getInterpolatedStringFactory(nonInterpolatedString) {
|
225 | return resolverData => stringInterpolator.parse(nonInterpolatedString, resolverData);
|
226 | }
|
227 | function getInterpolatedHeadersFactory(nonInterpolatedHeaders = {}) {
|
228 | return resolverData => {
|
229 | const headers = new Headers();
|
230 | for (const headerName in nonInterpolatedHeaders) {
|
231 | const headerValue = nonInterpolatedHeaders[headerName];
|
232 | if (headerValue) {
|
233 | headers.set(headerName, stringInterpolator.parse(headerValue, resolverData));
|
234 | }
|
235 | }
|
236 | return headers;
|
237 | };
|
238 | }
|
239 | function getHeadersObject(headers) {
|
240 | const headersObj = {};
|
241 | headers.forEach((value, key) => {
|
242 | headersObj[key] = value;
|
243 | });
|
244 | return headersObj;
|
245 | }
|
246 |
|
247 | function withCancel(asyncIteratorLike, onCancel) {
|
248 | const asyncIterator = asyncIteratorLike[Symbol.asyncIterator]();
|
249 | if (!asyncIterator.return) {
|
250 | asyncIterator.return = () => Promise.resolve({ value: undefined, done: true });
|
251 | }
|
252 | const savedReturn = asyncIterator.return.bind(asyncIterator);
|
253 | asyncIterator.return = () => {
|
254 | onCancel();
|
255 | return savedReturn();
|
256 | };
|
257 | return asyncIterator;
|
258 | }
|
259 |
|
260 | function extractResolvers(schema) {
|
261 | const allResolvers = getResolversFromSchema(schema);
|
262 | const filteredResolvers = {};
|
263 | for (const prop in allResolvers) {
|
264 | if (!prop.startsWith('_')) {
|
265 | filteredResolvers[prop] = allResolvers[prop];
|
266 | }
|
267 | }
|
268 | return filteredResolvers;
|
269 | }
|
270 |
|
271 | function ensureDocumentNode(document) {
|
272 | return typeof document === 'string' ? parse(document) : document;
|
273 | }
|
274 |
|
275 | function groupTransforms(transforms) {
|
276 | const wrapTransforms = [];
|
277 | const noWrapTransforms = [];
|
278 | transforms === null || transforms === void 0 ? void 0 : transforms.forEach(transform => {
|
279 | if (transform.noWrap) {
|
280 | noWrapTransforms.push(transform);
|
281 | }
|
282 | else {
|
283 | wrapTransforms.push(transform);
|
284 | }
|
285 | });
|
286 | return { wrapTransforms, noWrapTransforms };
|
287 | }
|
288 |
|
289 | function applySchemaTransforms(originalWrappingSchema, subschemaConfig, transformedSchema, transforms) {
|
290 | return transforms.reduce((schema, transform) => 'transformSchema' in transform ? transform.transformSchema(schema, subschemaConfig, transformedSchema) : schema, originalWrappingSchema);
|
291 | }
|
292 | function applyRequestTransforms(originalRequest, delegationContext, transformationContext, transforms) {
|
293 | transformationContext.contextMap = transformationContext.contextMap || new WeakMap();
|
294 | const contextMap = transformationContext.contextMap;
|
295 | transforms === null || transforms === void 0 ? void 0 : transforms.forEach(transform => {
|
296 | if (!contextMap.has(transform)) {
|
297 | contextMap.set(transform, {
|
298 | nextIndex: 0,
|
299 | paths: {},
|
300 | });
|
301 | }
|
302 | });
|
303 | return transforms.reduceRight((request, transform) => 'transformRequest' in transform
|
304 | ? transform.transformRequest(request, delegationContext, contextMap.get(transform))
|
305 | : request, originalRequest);
|
306 | }
|
307 | function applyResultTransforms(originalResult, delegationContext, transformationContext, transforms) {
|
308 | const contextMap = transformationContext.contextMap;
|
309 | return transforms.reduceRight((result, transform) => 'transformResult' in transform
|
310 | ? transform.transformResult(result, delegationContext, contextMap.get(transform))
|
311 | : result, originalResult);
|
312 | }
|
313 |
|
314 | function flatString(str) {
|
315 | return flatstr(str);
|
316 | }
|
317 | function jsonFlatStringify(data, replacer, space) {
|
318 | return flatString(JSON.stringify(data, replacer, space));
|
319 | }
|
320 |
|
321 | const { stat: stat$1, writeFile: fsWriteFile, readFile: readFile$1, mkdir: fsMkdir } = promises || {};
|
322 | async function pathExists(path) {
|
323 | if (!path) {
|
324 | return false;
|
325 | }
|
326 | try {
|
327 | await stat$1(path);
|
328 | return true;
|
329 | }
|
330 | catch (e) {
|
331 | if (e.toString().includes('ENOENT')) {
|
332 | return false;
|
333 | }
|
334 | else {
|
335 | throw e;
|
336 | }
|
337 | }
|
338 | }
|
339 | function readJSONSync(path) {
|
340 | const fileContent = readFileSync(path, 'utf-8');
|
341 | return JSON.parse(fileContent);
|
342 | }
|
343 | async function readJSON(path) {
|
344 | const fileContent = await readFile$1(path, 'utf-8');
|
345 | return JSON.parse(fileContent);
|
346 | }
|
347 | function writeJSON(path, data, replacer, space) {
|
348 | const stringified = jsonFlatStringify(data, replacer, space);
|
349 | return writeFile(path, stringified, 'utf-8');
|
350 | }
|
351 | const writeFile = async (path, ...args) => {
|
352 | if (typeof path === 'string') {
|
353 | const containingDir = dirname(path);
|
354 | if (!(await pathExists(containingDir))) {
|
355 | await mkdir(containingDir);
|
356 | }
|
357 | }
|
358 | return fsWriteFile(path, ...args);
|
359 | };
|
360 | async function mkdir(path, options = { recursive: true }) {
|
361 | const ifExists = await pathExists(path);
|
362 | if (!ifExists) {
|
363 | await fsMkdir(path, options);
|
364 | }
|
365 | }
|
366 |
|
367 | const globalLruCache = lru();
|
368 |
|
369 | const jitExecutorFactory = (schema, prefix) => ({ document, variables, context }, operationName, rootValue) => {
|
370 | const documentStr = print(document);
|
371 | const cacheKey = [prefix, documentStr, operationName].join('_');
|
372 | if (!globalLruCache.has(cacheKey)) {
|
373 | const compiledQuery = compileQuery(schema, document, operationName, {
|
374 | disableLeafSerialization: true,
|
375 | customJSONSerializer: true,
|
376 | });
|
377 | globalLruCache.set(cacheKey, compiledQuery);
|
378 | }
|
379 | const cachedQuery = globalLruCache.get(cacheKey);
|
380 | if (isCompiledQuery(cachedQuery)) {
|
381 | return cachedQuery.query(rootValue, context, variables);
|
382 | }
|
383 | return cachedQuery;
|
384 | };
|
385 |
|
386 | export { ArgType, applyRequestTransforms, applyResultTransforms, applySchemaTransforms, ensureDocumentNode, extractResolvers, flatString, getCachedFetch, getHeadersObject, getInputTypeFromTypeName, getInterpolatedHeadersFactory, getInterpolatedStringFactory, globalLruCache, groupTransforms, jitExecutorFactory, jsonFlatStringify, loadFromModuleExportExpression, loadFromModuleExportExpressionSync, mkdir, parseInterpolationStrings, pathExists, readFileOrUrlWithCache, readFileWithCache, readJSON, readJSONSync, readUrlWithCache, stringInterpolator, withCancel, writeFile, writeJSON };
|
387 |
|