@graphql-mesh/utils 1.0.0-alpha-3fc47d119.0 → 1.0.0-alpha-20230420181317-a95037648

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 (85) hide show
  1. package/cjs/apply-transforms.js +35 -0
  2. package/cjs/defaultImportFn.js +57 -0
  3. package/cjs/extract-resolvers.js +23 -0
  4. package/cjs/fileURLToPath.js +50 -0
  5. package/cjs/fs-operations.js +65 -0
  6. package/cjs/getHeadersObj.js +61 -0
  7. package/cjs/global-lru-cache.js +9 -0
  8. package/cjs/group-transforms.js +17 -0
  9. package/cjs/index.js +20 -0
  10. package/cjs/load-from-module-export-expression.js +29 -0
  11. package/cjs/logger.js +127 -0
  12. package/cjs/package.json +1 -0
  13. package/cjs/parseAndPrintWithCache.js +42 -0
  14. package/cjs/pubsub.js +57 -0
  15. package/cjs/read-file-or-url.js +132 -0
  16. package/cjs/resolve-additional-resolvers.js +350 -0
  17. package/cjs/sanitize-name-for-graphql.js +96 -0
  18. package/cjs/with-cancel.js +34 -0
  19. package/cjs/with-cookies.js +18 -0
  20. package/cjs/with-filter.js +53 -0
  21. package/esm/apply-transforms.js +29 -0
  22. package/esm/defaultImportFn.js +32 -0
  23. package/esm/extract-resolvers.js +19 -0
  24. package/esm/fileURLToPath.js +46 -0
  25. package/esm/fs-operations.js +57 -0
  26. package/esm/getHeadersObj.js +57 -0
  27. package/esm/global-lru-cache.js +4 -0
  28. package/esm/group-transforms.js +13 -0
  29. package/esm/index.js +17 -0
  30. package/esm/load-from-module-export-expression.js +25 -0
  31. package/esm/logger.js +118 -0
  32. package/esm/parseAndPrintWithCache.js +37 -0
  33. package/esm/pubsub.js +53 -0
  34. package/esm/read-file-or-url.js +124 -0
  35. package/esm/resolve-additional-resolvers.js +344 -0
  36. package/esm/sanitize-name-for-graphql.js +91 -0
  37. package/esm/with-cancel.js +30 -0
  38. package/esm/with-cookies.js +14 -0
  39. package/esm/with-filter.js +49 -0
  40. package/package.json +28 -23
  41. package/typings/apply-transforms.d.cts +6 -0
  42. package/{apply-transforms.d.ts → typings/apply-transforms.d.ts} +3 -3
  43. package/typings/defaultImportFn.d.cts +2 -0
  44. package/typings/defaultImportFn.d.ts +2 -0
  45. package/typings/extract-resolvers.d.ts +2 -0
  46. package/typings/fileURLToPath.d.ts +1 -0
  47. package/typings/fs-operations.d.ts +7 -0
  48. package/typings/getHeadersObj.d.cts +1 -0
  49. package/typings/getHeadersObj.d.ts +1 -0
  50. package/typings/global-lru-cache.d.cts +3 -0
  51. package/{global-lru-cache.d.ts → typings/global-lru-cache.d.ts} +2 -2
  52. package/typings/group-transforms.d.ts +5 -0
  53. package/typings/index.d.cts +17 -0
  54. package/typings/index.d.ts +17 -0
  55. package/typings/load-from-module-export-expression.d.cts +8 -0
  56. package/{load-from-module-export-expression.d.ts → typings/load-from-module-export-expression.d.ts} +1 -1
  57. package/typings/logger.d.cts +22 -0
  58. package/{logger.d.ts → typings/logger.d.ts} +1 -1
  59. package/typings/parseAndPrintWithCache.d.ts +4 -0
  60. package/typings/pubsub.d.cts +13 -0
  61. package/{pubsub.d.ts → typings/pubsub.d.ts} +3 -2
  62. package/typings/read-file-or-url.d.cts +14 -0
  63. package/{read-file-or-url.d.ts → typings/read-file-or-url.d.ts} +3 -3
  64. package/typings/resolve-additional-resolvers.d.cts +4 -0
  65. package/{resolve-additional-resolvers.d.ts → typings/resolve-additional-resolvers.d.ts} +1 -1
  66. package/typings/sanitize-name-for-graphql.d.cts +2 -0
  67. package/{sanitize-name-for-graphql.d.ts → typings/sanitize-name-for-graphql.d.ts} +1 -0
  68. package/typings/with-cancel.d.cts +1 -0
  69. package/typings/with-cancel.d.ts +1 -0
  70. package/typings/with-cookies.d.cts +3 -0
  71. package/typings/with-cookies.d.ts +3 -0
  72. package/typings/with-filter.d.cts +4 -0
  73. package/typings/with-filter.d.ts +4 -0
  74. package/defaultImportFn.d.ts +0 -1
  75. package/getHeadersObj.d.ts +0 -1
  76. package/index.d.ts +0 -16
  77. package/index.js +0 -1112
  78. package/index.mjs +0 -1054
  79. package/with-cancel.d.ts +0 -1
  80. package/with-filter.d.ts +0 -4
  81. /package/{extract-resolvers.d.ts → typings/extract-resolvers.d.cts} +0 -0
  82. /package/{fileURLToPath.d.ts → typings/fileURLToPath.d.cts} +0 -0
  83. /package/{fs-operations.d.ts → typings/fs-operations.d.cts} +0 -0
  84. /package/{group-transforms.d.ts → typings/group-transforms.d.cts} +0 -0
  85. /package/{parseAndPrintWithCache.d.ts → typings/parseAndPrintWithCache.d.cts} +0 -0
@@ -0,0 +1,124 @@
1
+ import { DEFAULT_SCHEMA, load as loadYamlFromJsYaml, Type } from 'js-yaml';
2
+ import { fs, path as pathModule } from '@graphql-mesh/cross-helpers';
3
+ import { loadFromModuleExportExpression } from './load-from-module-export-expression.js';
4
+ export function isUrl(str) {
5
+ return /^https?:\/\//.test(str);
6
+ }
7
+ export async function readFileOrUrl(filePathOrUrl, config) {
8
+ if (isUrl(filePathOrUrl)) {
9
+ config.logger.debug(`Fetching ${filePathOrUrl} via HTTP`);
10
+ return readUrl(filePathOrUrl, config);
11
+ }
12
+ else if (filePathOrUrl.startsWith('{') || filePathOrUrl.startsWith('[')) {
13
+ return JSON.parse(filePathOrUrl);
14
+ }
15
+ else {
16
+ config.logger.debug(`Reading ${filePathOrUrl} from the file system`);
17
+ return readFile(filePathOrUrl, config);
18
+ }
19
+ }
20
+ function getSchema(filepath, logger) {
21
+ return DEFAULT_SCHEMA.extend([
22
+ new Type('!include', {
23
+ kind: 'scalar',
24
+ resolve(path) {
25
+ return typeof path === 'string';
26
+ },
27
+ construct(path) {
28
+ const newCwd = pathModule.dirname(filepath);
29
+ const absoluteFilePath = pathModule.isAbsolute(path)
30
+ ? path
31
+ : pathModule.resolve(newCwd, path);
32
+ const content = fs.readFileSync(absoluteFilePath, 'utf8');
33
+ return loadYaml(absoluteFilePath, content, logger);
34
+ },
35
+ }),
36
+ new Type('!includes', {
37
+ kind: 'scalar',
38
+ resolve(path) {
39
+ return typeof path === 'string';
40
+ },
41
+ construct(path) {
42
+ const newCwd = pathModule.dirname(filepath);
43
+ const absoluteDirPath = pathModule.isAbsolute(path)
44
+ ? path
45
+ : pathModule.resolve(newCwd, path);
46
+ const files = fs.readdirSync(absoluteDirPath);
47
+ return files.map(filePath => {
48
+ const absoluteFilePath = pathModule.resolve(absoluteDirPath, filePath);
49
+ const fileContent = fs.readFileSync(absoluteFilePath, 'utf8');
50
+ return loadYaml(absoluteFilePath, fileContent, logger);
51
+ });
52
+ },
53
+ }),
54
+ ]);
55
+ }
56
+ export function loadYaml(filepath, content, logger) {
57
+ return loadYamlFromJsYaml(content, {
58
+ filename: filepath,
59
+ schema: getSchema(filepath, logger),
60
+ onWarning(warning) {
61
+ logger.warn(`${filepath}: ${warning.message}\n${warning.stack}`);
62
+ },
63
+ });
64
+ }
65
+ export async function readFile(fileExpression, { allowUnknownExtensions, cwd, fallbackFormat, importFn, logger }) {
66
+ const [filePath] = fileExpression.split('#');
67
+ if (/js$/.test(filePath) || /ts$/.test(filePath)) {
68
+ return loadFromModuleExportExpression(fileExpression, {
69
+ cwd,
70
+ importFn,
71
+ defaultExportName: 'default',
72
+ });
73
+ }
74
+ const actualPath = pathModule.isAbsolute(filePath) ? filePath : pathModule.join(cwd, filePath);
75
+ const rawResult = await fs.promises.readFile(actualPath, 'utf-8');
76
+ if (/json$/.test(actualPath)) {
77
+ return JSON.parse(rawResult);
78
+ }
79
+ if (/yaml$/.test(actualPath) || /yml$/.test(actualPath)) {
80
+ return loadYaml(actualPath, rawResult, logger);
81
+ }
82
+ else if (fallbackFormat) {
83
+ switch (fallbackFormat) {
84
+ case 'json':
85
+ return JSON.parse(rawResult);
86
+ case 'yaml':
87
+ return loadYaml(actualPath, rawResult, logger);
88
+ case 'ts':
89
+ case 'js':
90
+ return importFn(actualPath);
91
+ }
92
+ }
93
+ else if (!allowUnknownExtensions) {
94
+ throw new Error(`Failed to parse JSON/YAML. Ensure file '${filePath}' has ` +
95
+ `the correct extension (i.e. '.json', '.yaml', or '.yml).`);
96
+ }
97
+ return rawResult;
98
+ }
99
+ export async function readUrl(path, config) {
100
+ var _a, _b;
101
+ const { allowUnknownExtensions, fallbackFormat } = config || {};
102
+ config.headers = config.headers || {};
103
+ const response = await config.fetch(path, config);
104
+ const contentType = ((_a = response.headers) === null || _a === void 0 ? void 0 : _a.get('content-type')) || '';
105
+ const responseText = await response.text();
106
+ (_b = config === null || config === void 0 ? void 0 : config.logger) === null || _b === void 0 ? void 0 : _b.debug(`${path} returned `, responseText);
107
+ if (/json$/.test(path) ||
108
+ contentType.startsWith('application/json') ||
109
+ fallbackFormat === 'json') {
110
+ return JSON.parse(responseText);
111
+ }
112
+ else if (/yaml$/.test(path) ||
113
+ /yml$/.test(path) ||
114
+ contentType.includes('yaml') ||
115
+ contentType.includes('yml') ||
116
+ fallbackFormat === 'yaml') {
117
+ return loadYaml(path, responseText, config === null || config === void 0 ? void 0 : config.logger);
118
+ }
119
+ else if (!allowUnknownExtensions) {
120
+ throw new Error(`Failed to parse JSON/YAML. Ensure URL '${path}' has ` +
121
+ `the correct extension (i.e. '.json', '.yaml', or '.yml) or mime type in the response headers.`);
122
+ }
123
+ return responseText;
124
+ }
@@ -0,0 +1,344 @@
1
+ import { dset } from 'dset';
2
+ import { getNamedType, isAbstractType, isInterfaceType, isObjectType, Kind, } from 'graphql';
3
+ import lodashGet from 'lodash.get';
4
+ import toPath from 'lodash.topath';
5
+ import { process } from '@graphql-mesh/cross-helpers';
6
+ import { stringInterpolator } from '@graphql-mesh/string-interpolation';
7
+ import { parseSelectionSet } from '@graphql-tools/utils';
8
+ import { loadFromModuleExportExpression } from './load-from-module-export-expression.js';
9
+ import { withFilter } from './with-filter.js';
10
+ function getTypeByPath(type, path) {
11
+ if ('ofType' in type) {
12
+ return getTypeByPath(getNamedType(type), path);
13
+ }
14
+ if (path.length === 0) {
15
+ return getNamedType(type);
16
+ }
17
+ if (!('getFields' in type)) {
18
+ throw new Error(`${type} cannot have a path ${path.join('.')}`);
19
+ }
20
+ const fieldMap = type.getFields();
21
+ const currentFieldName = path[0];
22
+ // Might be an index of an array
23
+ if (!Number.isNaN(parseInt(currentFieldName))) {
24
+ return getTypeByPath(type, path.slice(1));
25
+ }
26
+ const field = fieldMap[currentFieldName];
27
+ if (!(field === null || field === void 0 ? void 0 : field.type)) {
28
+ throw new Error(`${type}.${currentFieldName} is not a valid field.`);
29
+ }
30
+ return getTypeByPath(field.type, path.slice(1));
31
+ }
32
+ function generateSelectionSetFactory(schema, additionalResolver) {
33
+ if (additionalResolver.sourceSelectionSet) {
34
+ return () => parseSelectionSet(additionalResolver.sourceSelectionSet);
35
+ // If result path provided without a selectionSet
36
+ }
37
+ else if (additionalResolver.result) {
38
+ const resultPath = toPath(additionalResolver.result);
39
+ let abstractResultTypeName;
40
+ const sourceType = schema.getType(additionalResolver.sourceTypeName);
41
+ const sourceTypeFields = sourceType.getFields();
42
+ const sourceField = sourceTypeFields[additionalResolver.sourceFieldName];
43
+ const resultFieldType = getTypeByPath(sourceField.type, resultPath);
44
+ if (isAbstractType(resultFieldType)) {
45
+ if (additionalResolver.resultType) {
46
+ abstractResultTypeName = additionalResolver.resultType;
47
+ }
48
+ else {
49
+ const targetType = schema.getType(additionalResolver.targetTypeName);
50
+ const targetTypeFields = targetType.getFields();
51
+ const targetField = targetTypeFields[additionalResolver.targetFieldName];
52
+ const targetFieldType = getNamedType(targetField.type);
53
+ abstractResultTypeName = targetFieldType === null || targetFieldType === void 0 ? void 0 : targetFieldType.name;
54
+ }
55
+ if (abstractResultTypeName !== resultFieldType.name) {
56
+ const abstractResultType = schema.getType(abstractResultTypeName);
57
+ if ((isInterfaceType(abstractResultType) || isObjectType(abstractResultType)) &&
58
+ !schema.isSubType(resultFieldType, abstractResultType)) {
59
+ throw new Error(`${additionalResolver.sourceTypeName}.${additionalResolver.sourceFieldName}.${resultPath.join('.')} doesn't implement ${abstractResultTypeName}.}`);
60
+ }
61
+ }
62
+ }
63
+ return (subtree) => {
64
+ let finalSelectionSet = subtree;
65
+ let isLastResult = true;
66
+ const resultPathReversed = [...resultPath].reverse();
67
+ for (const pathElem of resultPathReversed) {
68
+ // Ensure the path elem is not array index
69
+ if (Number.isNaN(parseInt(pathElem))) {
70
+ if (isLastResult &&
71
+ abstractResultTypeName &&
72
+ abstractResultTypeName !== resultFieldType.name) {
73
+ finalSelectionSet = {
74
+ kind: Kind.SELECTION_SET,
75
+ selections: [
76
+ {
77
+ kind: Kind.INLINE_FRAGMENT,
78
+ typeCondition: {
79
+ kind: Kind.NAMED_TYPE,
80
+ name: {
81
+ kind: Kind.NAME,
82
+ value: abstractResultTypeName,
83
+ },
84
+ },
85
+ selectionSet: finalSelectionSet,
86
+ },
87
+ ],
88
+ };
89
+ }
90
+ finalSelectionSet = {
91
+ kind: Kind.SELECTION_SET,
92
+ selections: [
93
+ {
94
+ // we create a wrapping AST Field
95
+ kind: Kind.FIELD,
96
+ name: {
97
+ kind: Kind.NAME,
98
+ value: pathElem,
99
+ },
100
+ // Inside the field selection
101
+ selectionSet: finalSelectionSet,
102
+ },
103
+ ],
104
+ };
105
+ isLastResult = false;
106
+ }
107
+ }
108
+ return finalSelectionSet;
109
+ };
110
+ }
111
+ return undefined;
112
+ }
113
+ function generateValuesFromResults(resultExpression) {
114
+ return function valuesFromResults(result) {
115
+ if (Array.isArray(result)) {
116
+ return result.map(valuesFromResults);
117
+ }
118
+ return lodashGet(result, resultExpression);
119
+ };
120
+ }
121
+ export function resolveAdditionalResolversWithoutImport(additionalResolver, pubsub) {
122
+ const baseOptions = {};
123
+ if (additionalResolver.result) {
124
+ baseOptions.valuesFromResults = generateValuesFromResults(additionalResolver.result);
125
+ }
126
+ if ('pubsubTopic' in additionalResolver) {
127
+ return {
128
+ [additionalResolver.targetTypeName]: {
129
+ [additionalResolver.targetFieldName]: {
130
+ subscribe: withFilter((root, args, context, info) => {
131
+ const resolverData = { root, args, context, info, env: process.env };
132
+ const topic = stringInterpolator.parse(additionalResolver.pubsubTopic, resolverData);
133
+ return pubsub.asyncIterator(topic);
134
+ }, (root, args, context, info) => {
135
+ return additionalResolver.filterBy
136
+ ? // eslint-disable-next-line no-new-func
137
+ new Function(`return ${additionalResolver.filterBy}`)()
138
+ : true;
139
+ }),
140
+ resolve: (payload) => {
141
+ if (baseOptions.valuesFromResults) {
142
+ return baseOptions.valuesFromResults(payload);
143
+ }
144
+ return payload;
145
+ },
146
+ },
147
+ },
148
+ };
149
+ }
150
+ else if ('keysArg' in additionalResolver) {
151
+ return {
152
+ [additionalResolver.targetTypeName]: {
153
+ [additionalResolver.targetFieldName]: {
154
+ selectionSet: additionalResolver.requiredSelectionSet || `{ ${additionalResolver.keyField} }`,
155
+ resolve: async (root, args, context, info) => {
156
+ if (!baseOptions.selectionSet) {
157
+ baseOptions.selectionSet = generateSelectionSetFactory(info.schema, additionalResolver);
158
+ }
159
+ const resolverData = { root, args, context, info, env: process.env };
160
+ const targetArgs = {};
161
+ for (const argPath in additionalResolver.additionalArgs || {}) {
162
+ dset(targetArgs, argPath, stringInterpolator.parse(additionalResolver.additionalArgs[argPath], resolverData));
163
+ }
164
+ const options = {
165
+ ...baseOptions,
166
+ root,
167
+ context,
168
+ info,
169
+ argsFromKeys: (keys) => {
170
+ const args = {};
171
+ dset(args, additionalResolver.keysArg, keys);
172
+ Object.assign(args, targetArgs);
173
+ return args;
174
+ },
175
+ key: lodashGet(root, additionalResolver.keyField),
176
+ };
177
+ return context[additionalResolver.sourceName][additionalResolver.sourceTypeName][additionalResolver.sourceFieldName](options);
178
+ },
179
+ },
180
+ },
181
+ };
182
+ }
183
+ else if ('targetTypeName' in additionalResolver) {
184
+ return {
185
+ [additionalResolver.targetTypeName]: {
186
+ [additionalResolver.targetFieldName]: {
187
+ selectionSet: additionalResolver.requiredSelectionSet,
188
+ resolve: (root, args, context, info) => {
189
+ // Assert source exists
190
+ if (!context[additionalResolver.sourceName]) {
191
+ throw new Error(`No source found named "${additionalResolver.sourceName}"`);
192
+ }
193
+ if (!context[additionalResolver.sourceName][additionalResolver.sourceTypeName]) {
194
+ throw new Error(`No root type found named "${additionalResolver.sourceTypeName}" exists in the source ${additionalResolver.sourceName}\n` +
195
+ `It should be one of the following; ${Object.keys(context[additionalResolver.sourceName]).join(',')})}}`);
196
+ }
197
+ if (!context[additionalResolver.sourceName][additionalResolver.sourceTypeName][additionalResolver.sourceFieldName]) {
198
+ throw new Error(`No field named "${additionalResolver.sourceFieldName}" exists in the type ${additionalResolver.sourceTypeName} from the source ${additionalResolver.sourceName}`);
199
+ }
200
+ if (!baseOptions.selectionSet) {
201
+ baseOptions.selectionSet = generateSelectionSetFactory(info.schema, additionalResolver);
202
+ }
203
+ const resolverData = { root, args, context, info, env: process.env };
204
+ const targetArgs = {};
205
+ for (const argPath in additionalResolver.sourceArgs) {
206
+ dset(targetArgs, argPath, stringInterpolator.parse(additionalResolver.sourceArgs[argPath].toString(), resolverData));
207
+ }
208
+ const options = {
209
+ ...baseOptions,
210
+ root,
211
+ args: targetArgs,
212
+ context,
213
+ info,
214
+ };
215
+ return context[additionalResolver.sourceName][additionalResolver.sourceTypeName][additionalResolver.sourceFieldName](options);
216
+ },
217
+ },
218
+ },
219
+ };
220
+ }
221
+ else {
222
+ return additionalResolver;
223
+ }
224
+ }
225
+ export function resolveAdditionalResolvers(baseDir, additionalResolvers, importFn, pubsub) {
226
+ return Promise.all((additionalResolvers || []).map(async (additionalResolver) => {
227
+ if (typeof additionalResolver === 'string') {
228
+ const resolvers = await loadFromModuleExportExpression(additionalResolver, {
229
+ cwd: baseDir,
230
+ defaultExportName: 'resolvers',
231
+ importFn,
232
+ });
233
+ if (!resolvers) {
234
+ console.warn(`Unable to load resolvers from file: ${additionalResolver}`);
235
+ return {};
236
+ }
237
+ return resolvers;
238
+ }
239
+ else {
240
+ const baseOptions = {};
241
+ if (additionalResolver.result) {
242
+ baseOptions.valuesFromResults = generateValuesFromResults(additionalResolver.result);
243
+ }
244
+ if ('pubsubTopic' in additionalResolver) {
245
+ return {
246
+ [additionalResolver.targetTypeName]: {
247
+ [additionalResolver.targetFieldName]: {
248
+ subscribe: withFilter((root, args, context, info) => {
249
+ const resolverData = { root, args, context, info, env: process.env };
250
+ const topic = stringInterpolator.parse(additionalResolver.pubsubTopic, resolverData);
251
+ return pubsub.asyncIterator(topic);
252
+ }, (root, args, context, info) => {
253
+ return additionalResolver.filterBy
254
+ ? // eslint-disable-next-line no-new-func
255
+ new Function(`return ${additionalResolver.filterBy}`)()
256
+ : true;
257
+ }),
258
+ resolve: (payload) => {
259
+ if (baseOptions.valuesFromResults) {
260
+ return baseOptions.valuesFromResults(payload);
261
+ }
262
+ return payload;
263
+ },
264
+ },
265
+ },
266
+ };
267
+ }
268
+ else if ('keysArg' in additionalResolver) {
269
+ return {
270
+ [additionalResolver.targetTypeName]: {
271
+ [additionalResolver.targetFieldName]: {
272
+ selectionSet: additionalResolver.requiredSelectionSet || `{ ${additionalResolver.keyField} }`,
273
+ resolve: async (root, args, context, info) => {
274
+ if (!baseOptions.selectionSet) {
275
+ baseOptions.selectionSet = generateSelectionSetFactory(info.schema, additionalResolver);
276
+ }
277
+ const resolverData = { root, args, context, info, env: process.env };
278
+ const targetArgs = {};
279
+ for (const argPath in additionalResolver.additionalArgs || {}) {
280
+ dset(targetArgs, argPath, stringInterpolator.parse(additionalResolver.additionalArgs[argPath], resolverData));
281
+ }
282
+ const options = {
283
+ ...baseOptions,
284
+ root,
285
+ context,
286
+ info,
287
+ argsFromKeys: (keys) => {
288
+ const args = {};
289
+ dset(args, additionalResolver.keysArg, keys);
290
+ Object.assign(args, targetArgs);
291
+ return args;
292
+ },
293
+ key: lodashGet(root, additionalResolver.keyField),
294
+ };
295
+ return context[additionalResolver.sourceName][additionalResolver.sourceTypeName][additionalResolver.sourceFieldName](options);
296
+ },
297
+ },
298
+ },
299
+ };
300
+ }
301
+ else if ('targetTypeName' in additionalResolver) {
302
+ return {
303
+ [additionalResolver.targetTypeName]: {
304
+ [additionalResolver.targetFieldName]: {
305
+ selectionSet: additionalResolver.requiredSelectionSet,
306
+ resolve: (root, args, context, info) => {
307
+ // Assert source exists
308
+ if (!context[additionalResolver.sourceName]) {
309
+ throw new Error(`No source found named "${additionalResolver.sourceName}"`);
310
+ }
311
+ if (!context[additionalResolver.sourceName][additionalResolver.sourceTypeName]) {
312
+ throw new Error(`No root type found named "${additionalResolver.sourceTypeName}" exists in the source ${additionalResolver.sourceName}\n` +
313
+ `It should be one of the following; ${Object.keys(context[additionalResolver.sourceName]).join(',')})}}`);
314
+ }
315
+ if (!context[additionalResolver.sourceName][additionalResolver.sourceTypeName][additionalResolver.sourceFieldName]) {
316
+ throw new Error(`No field named "${additionalResolver.sourceFieldName}" exists in the type ${additionalResolver.sourceTypeName} from the source ${additionalResolver.sourceName}`);
317
+ }
318
+ if (!baseOptions.selectionSet) {
319
+ baseOptions.selectionSet = generateSelectionSetFactory(info.schema, additionalResolver);
320
+ }
321
+ const resolverData = { root, args, context, info, env: process.env };
322
+ const targetArgs = {};
323
+ for (const argPath in additionalResolver.sourceArgs) {
324
+ dset(targetArgs, argPath, stringInterpolator.parse(additionalResolver.sourceArgs[argPath].toString(), resolverData));
325
+ }
326
+ const options = {
327
+ ...baseOptions,
328
+ root,
329
+ args: targetArgs,
330
+ context,
331
+ info,
332
+ };
333
+ return context[additionalResolver.sourceName][additionalResolver.sourceTypeName][additionalResolver.sourceFieldName](options);
334
+ },
335
+ },
336
+ },
337
+ };
338
+ }
339
+ else {
340
+ return additionalResolver;
341
+ }
342
+ }
343
+ }));
344
+ }
@@ -0,0 +1,91 @@
1
+ const reservedNames = ['Query', 'Mutation', 'Subscription', 'File'];
2
+ const KNOWN_CHARACTERS = {
3
+ '+': 'PLUS',
4
+ '-': 'MINUS',
5
+ '>': 'GREATER_THAN',
6
+ '<': 'LESS_THAN',
7
+ '=': 'EQUALS',
8
+ '&': 'AMPERSAND',
9
+ '|': 'PIPE',
10
+ '@': 'AT',
11
+ '*': 'STAR',
12
+ ':': 'COLON',
13
+ '{': 'LEFT_CURLY_BRACE',
14
+ '}': 'RIGHT_CURLY_BRACE',
15
+ '[': 'LEFT_SQUARE_BRACE',
16
+ ']': 'RIGHT_SQUARE_BRACE',
17
+ ',': 'COMMA',
18
+ '%': 'PERCENT',
19
+ $: 'DOLLAR',
20
+ '#': 'POUND',
21
+ '^': 'CARET',
22
+ '~': 'TILDE',
23
+ '?': 'QUESTION_MARK',
24
+ '!': 'EXCLAMATION_MARK',
25
+ '"': 'QUOTATION_MARK',
26
+ "'": 'SINGLE_QUOTE',
27
+ '\\': 'BACKSLASH',
28
+ '/': 'SLASH',
29
+ '.': 'DOT',
30
+ '`': 'BACKTICK',
31
+ ';': 'SEMICOLON',
32
+ '(': 'LEFT_PARENTHESIS',
33
+ ')': 'RIGHT_PARENTHESIS',
34
+ };
35
+ function getKnownCharacterOrCharCode(ch) {
36
+ return KNOWN_CHARACTERS[ch] || ch.charCodeAt(0).toString();
37
+ }
38
+ export function removeClosedBrackets(val) {
39
+ let out = val;
40
+ for (;;) {
41
+ // finds the first and shortest closed bracket match, starting from the left
42
+ const match = out.match(/\(.+?\)/);
43
+ const yesbrack = match === null || match === void 0 ? void 0 : match[0];
44
+ if (!yesbrack) {
45
+ break;
46
+ }
47
+ // remove the brackets
48
+ const nobrack = yesbrack.substring(1, yesbrack.length - 1);
49
+ // replace the match removing bracks, just once starting from the left
50
+ out = out.replace(yesbrack, nobrack);
51
+ }
52
+ return out;
53
+ }
54
+ export function sanitizeNameForGraphQL(unsafeName) {
55
+ let sanitizedName = unsafeName.trim();
56
+ sanitizedName = removeClosedBrackets(sanitizedName);
57
+ if (!isNaN(parseInt(sanitizedName))) {
58
+ if (sanitizedName.startsWith('-')) {
59
+ sanitizedName = sanitizedName.replace('-', 'NEGATIVE_');
60
+ }
61
+ else {
62
+ sanitizedName = '_' + sanitizedName;
63
+ }
64
+ }
65
+ if (!/^[_a-zA-Z0-9]*$/.test(sanitizedName)) {
66
+ const unsanitizedName = sanitizedName;
67
+ sanitizedName = '';
68
+ for (const ch of unsanitizedName) {
69
+ if (/^[_a-zA-Z0-9]$/.test(ch)) {
70
+ sanitizedName += ch;
71
+ }
72
+ else if (ch === ' ' || ch === '-' || ch === '.' || ch === '/' || ch === ':') {
73
+ sanitizedName += '_';
74
+ }
75
+ else {
76
+ sanitizedName += `_${getKnownCharacterOrCharCode(ch)}_`;
77
+ }
78
+ }
79
+ }
80
+ // Names cannot start with __
81
+ if (sanitizedName.startsWith('__')) {
82
+ sanitizedName = sanitizedName.replace('__', '_0');
83
+ }
84
+ if (reservedNames.includes(sanitizedName)) {
85
+ sanitizedName += '_';
86
+ }
87
+ if (sanitizedName.length === 0) {
88
+ return '_';
89
+ }
90
+ return sanitizedName;
91
+ }
@@ -0,0 +1,30 @@
1
+ export function withCancel(asyncIterable, onCancel) {
2
+ return new Proxy(asyncIterable, {
3
+ get(asyncIterable, prop) {
4
+ if (prop === Symbol.asyncIterator) {
5
+ return function getIteratorWithCancel() {
6
+ const asyncIterator = asyncIterable[Symbol.asyncIterator]();
7
+ return {
8
+ next: asyncIterator.next ? (...args) => asyncIterator.next(...args) : undefined,
9
+ return: async (...args) => {
10
+ onCancel();
11
+ if (asyncIterator.return) {
12
+ return asyncIterator.return(...args);
13
+ }
14
+ return {
15
+ value: undefined,
16
+ done: true,
17
+ };
18
+ },
19
+ throw: asyncIterator.throw ? (...args) => asyncIterator.throw(...args) : undefined,
20
+ };
21
+ };
22
+ }
23
+ const propVal = asyncIterable[prop];
24
+ if (typeof propVal === 'function') {
25
+ return propVal.bind(asyncIterable);
26
+ }
27
+ return propVal;
28
+ },
29
+ });
30
+ }
@@ -0,0 +1,14 @@
1
+ // withCookies - embeds cookies object into the request
2
+ export const withCookies = (request) => {
3
+ request.cookies = {};
4
+ try {
5
+ request.cookies = (request.headers.get('Cookie') || '')
6
+ .split(/;\s*/)
7
+ .map(pair => pair.split(/=(.+)/))
8
+ .reduce((acc, [key, value]) => {
9
+ acc[key] = value;
10
+ return acc;
11
+ }, {});
12
+ }
13
+ catch (err) { }
14
+ };
@@ -0,0 +1,49 @@
1
+ export function withFilter(asyncIteratorFn, filterFn) {
2
+ return async (rootValue, args, context, info) => {
3
+ const asyncIterator = await asyncIteratorFn(rootValue, args, context, info);
4
+ const getNextPromise = () => {
5
+ return new Promise((resolve, reject) => {
6
+ const inner = () => {
7
+ asyncIterator
8
+ .next()
9
+ .then(payload => {
10
+ if (payload.done === true) {
11
+ resolve(payload);
12
+ return;
13
+ }
14
+ Promise.resolve(filterFn(payload.value, args, context, info))
15
+ .catch(() => false) // We ignore errors from filter function
16
+ .then(filterResult => {
17
+ if (filterResult === true) {
18
+ resolve(payload);
19
+ return;
20
+ }
21
+ // Skip the current value and wait for the next one
22
+ inner();
23
+ })
24
+ .catch(() => false); // We ignore errors from filter function;
25
+ })
26
+ .catch(err => {
27
+ reject(err);
28
+ });
29
+ };
30
+ inner();
31
+ });
32
+ };
33
+ const asyncIterator2 = {
34
+ next() {
35
+ return getNextPromise();
36
+ },
37
+ return() {
38
+ return asyncIterator.return();
39
+ },
40
+ throw(error) {
41
+ return asyncIterator.throw(error);
42
+ },
43
+ [Symbol.asyncIterator]() {
44
+ return this;
45
+ },
46
+ };
47
+ return asyncIterator2;
48
+ };
49
+ }