@omnigraph/openapi 1.0.0-alpha-20220804093904-8e2e41f7f → 1.0.0-alpha-20230420220344-25b6b92bf

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.
package/index.mjs DELETED
@@ -1,369 +0,0 @@
1
- import { loadGraphQLSchemaFromJSONSchemas, createBundle as createBundle$1 } from '@omnigraph/json-schema';
2
- export { getGraphQLSchemaFromBundle } from '@omnigraph/json-schema';
3
- import { DefaultLogger, readFileOrUrl, defaultImportFn, sanitizeNameForGraphQL } from '@graphql-mesh/utils';
4
- import { resolvePath, dereferenceObject } from 'json-machete';
5
- import { camelCase } from 'change-case';
6
- import { getInterpolatedHeadersFactory } from '@graphql-mesh/string-interpolation';
7
- import { process } from '@graphql-mesh/cross-helpers';
8
-
9
- function getFieldNameFromPath(path, method, responseTypeSchemaRef) {
10
- // Replace identifiers with "by"
11
- path = path.split('{').join('by_').split('}').join('');
12
- const [actualPartsStr, allQueryPartsStr] = path.split('?');
13
- const actualParts = actualPartsStr.split('/').filter(Boolean);
14
- let fieldNameWithoutMethod = actualParts.join('_');
15
- // If path doesn't give any field name without identifiers, we can use the return type with HTTP Method name
16
- if ((!fieldNameWithoutMethod || fieldNameWithoutMethod.startsWith('by')) && responseTypeSchemaRef) {
17
- const refArr = responseTypeSchemaRef.split('/');
18
- // lowercase looks better in the schema
19
- const prefix = camelCase(refArr[refArr.length - 1]);
20
- if (fieldNameWithoutMethod) {
21
- fieldNameWithoutMethod = prefix + '_' + fieldNameWithoutMethod;
22
- }
23
- else {
24
- fieldNameWithoutMethod = prefix;
25
- }
26
- }
27
- if (allQueryPartsStr) {
28
- const queryParts = allQueryPartsStr.split('&');
29
- for (const queryPart of queryParts) {
30
- const [queryName] = queryPart.split('=');
31
- fieldNameWithoutMethod += '_' + 'by' + '_' + queryName;
32
- }
33
- }
34
- // get_ doesn't look good in field names
35
- const methodPrefix = method.toLowerCase();
36
- if (methodPrefix === 'get') {
37
- return fieldNameWithoutMethod;
38
- }
39
- if (fieldNameWithoutMethod) {
40
- return methodPrefix + '_' + fieldNameWithoutMethod;
41
- }
42
- return methodPrefix;
43
- }
44
-
45
- async function getJSONSchemaOptionsFromOpenAPIOptions({ oasFilePath, fallbackFormat, cwd, fetch: fetchFn, baseUrl, schemaHeaders, operationHeaders, selectQueryOrMutationField = [], logger = new DefaultLogger('getJSONSchemaOptionsFromOpenAPIOptions'), }) {
46
- var _a, _b, _c, _d, _e, _f;
47
- const fieldTypeMap = {};
48
- for (const { fieldName, type } of selectQueryOrMutationField) {
49
- fieldTypeMap[fieldName] = type;
50
- }
51
- const schemaHeadersFactory = getInterpolatedHeadersFactory(schemaHeaders);
52
- logger === null || logger === void 0 ? void 0 : logger.debug(`Fetching OpenAPI Document from ${oasFilePath}`);
53
- const oasOrSwagger = typeof oasFilePath === 'string'
54
- ? await readFileOrUrl(oasFilePath, {
55
- cwd,
56
- fallbackFormat,
57
- headers: schemaHeadersFactory({ env: process.env }),
58
- fetch: fetchFn,
59
- importFn: defaultImportFn,
60
- logger,
61
- })
62
- : oasFilePath;
63
- const operations = [];
64
- if ('servers' in oasOrSwagger) {
65
- baseUrl = baseUrl || oasOrSwagger.servers[0].url;
66
- }
67
- for (const relativePath in oasOrSwagger.paths) {
68
- const pathObj = oasOrSwagger.paths[relativePath];
69
- const pathParameters = pathObj.parameters;
70
- for (const method in pathObj) {
71
- if (method === 'parameters') {
72
- continue;
73
- }
74
- const methodObj = pathObj[method];
75
- const operationConfig = {
76
- method: method.toUpperCase(),
77
- path: relativePath,
78
- type: method.toUpperCase() === 'GET' ? 'query' : 'mutation',
79
- field: methodObj.operationId && sanitizeNameForGraphQL(methodObj.operationId),
80
- description: methodObj.description || methodObj.summary,
81
- schemaHeaders,
82
- operationHeaders,
83
- responseByStatusCode: {},
84
- };
85
- operations.push(operationConfig);
86
- let allParams;
87
- if (methodObj.parameters && Array.isArray(methodObj.parameters)) {
88
- allParams = [...(pathParameters || []), ...methodObj.parameters];
89
- }
90
- else {
91
- allParams = {
92
- ...(pathParameters || {}),
93
- ...(methodObj.parameters || {}),
94
- };
95
- }
96
- for (const paramObjIndex in allParams) {
97
- let paramObj = allParams[paramObjIndex];
98
- if ('$ref' in paramObj) {
99
- paramObj = resolvePath(paramObj.$ref.split('#')[1], oasOrSwagger);
100
- }
101
- const argName = sanitizeNameForGraphQL(paramObj.name);
102
- switch (paramObj.in) {
103
- case 'query':
104
- if (method.toUpperCase() === 'GET') {
105
- const requestSchema = (operationConfig.requestSchema = operationConfig.requestSchema || {
106
- type: 'object',
107
- properties: {},
108
- });
109
- requestSchema.properties[paramObj.name] =
110
- paramObj.schema || ((_b = (_a = paramObj.content) === null || _a === void 0 ? void 0 : _a['application/json']) === null || _b === void 0 ? void 0 : _b.schema) || paramObj;
111
- if (!requestSchema.properties[paramObj.name].title) {
112
- requestSchema.properties[paramObj.name].name = paramObj.name;
113
- }
114
- if (!requestSchema.properties[paramObj.name].description) {
115
- requestSchema.properties[paramObj.name].description = paramObj.description;
116
- }
117
- if (requestSchema.properties.__typename) {
118
- delete requestSchema.properties.__typename;
119
- }
120
- if (paramObj.required) {
121
- requestSchema.required = requestSchema.required || [];
122
- requestSchema.required.push(paramObj.name);
123
- }
124
- // Fix the reference
125
- if ((_c = requestSchema.properties[paramObj.name].$ref) === null || _c === void 0 ? void 0 : _c.startsWith('#')) {
126
- requestSchema.properties[paramObj.name].$ref = `${oasFilePath}${requestSchema.properties[paramObj.name].$ref}`;
127
- }
128
- }
129
- else {
130
- if (!operationConfig.path.includes('?')) {
131
- operationConfig.path += '?';
132
- }
133
- if (operationConfig.path !== '?') {
134
- operationConfig.path += '&';
135
- }
136
- operationConfig.path += `${paramObj.name}={args.${argName}}`;
137
- }
138
- break;
139
- case 'path': {
140
- // If it is in the path, let JSON Schema handler put it
141
- operationConfig.path = operationConfig.path.replace(`{${paramObj.name}}`, `{args.${argName}}`);
142
- break;
143
- }
144
- case 'header': {
145
- operationConfig.headers = operationConfig.headers || {};
146
- operationConfig.headers[paramObj.name] = `{args.${argName}}`;
147
- break;
148
- }
149
- case 'cookie': {
150
- operationConfig.headers = operationConfig.headers || {};
151
- operationConfig.headers.cookie = operationConfig.headers.cookie || '';
152
- const cookieParams = operationConfig.headers.cookie.split('; ');
153
- cookieParams.push(`${paramObj.name}={args.${argName}}`);
154
- operationConfig.headers.cookie = cookieParams.join('; ');
155
- break;
156
- }
157
- case 'body':
158
- if (paramObj.schema && Object.keys(paramObj.schema).length > 0) {
159
- operationConfig.requestSchema = `${oasFilePath}#/paths/${relativePath
160
- .split('/')
161
- .join('~1')}/${method}/parameters/${paramObjIndex}/schema`;
162
- }
163
- if (paramObj.example) {
164
- operationConfig.requestSample = paramObj.example;
165
- }
166
- if (paramObj.examples) {
167
- operationConfig.requestSample = Object.values(paramObj.examples)[0];
168
- }
169
- break;
170
- }
171
- switch (((_d = paramObj.schema) === null || _d === void 0 ? void 0 : _d.type) || paramObj.type) {
172
- case 'string':
173
- operationConfig.argTypeMap = operationConfig.argTypeMap || {};
174
- operationConfig.argTypeMap[argName] = 'String';
175
- break;
176
- case 'integer':
177
- operationConfig.argTypeMap = operationConfig.argTypeMap || {};
178
- operationConfig.argTypeMap[argName] = 'Int';
179
- break;
180
- case 'number':
181
- operationConfig.argTypeMap = operationConfig.argTypeMap || {};
182
- operationConfig.argTypeMap[argName] = 'Float';
183
- break;
184
- case 'boolean':
185
- operationConfig.argTypeMap = operationConfig.argTypeMap || {};
186
- operationConfig.argTypeMap[argName] = 'Boolean';
187
- break;
188
- }
189
- if (paramObj.required) {
190
- operationConfig.argTypeMap = operationConfig.argTypeMap || {};
191
- operationConfig.argTypeMap[argName] = operationConfig.argTypeMap[argName] || 'ID';
192
- operationConfig.argTypeMap[argName] += '!';
193
- }
194
- }
195
- if ('requestBody' in methodObj) {
196
- const requestBodyObj = methodObj.requestBody;
197
- if ('content' in requestBodyObj) {
198
- const contentKey = Object.keys(requestBodyObj.content)[0];
199
- const contentSchema = (_e = requestBodyObj.content[contentKey]) === null || _e === void 0 ? void 0 : _e.schema;
200
- if (contentSchema && Object.keys(contentSchema).length > 0) {
201
- operationConfig.requestSchema = `${oasFilePath}#/paths/${relativePath
202
- .split('/')
203
- .join('~1')}/${method}/requestBody/content/${contentKey === null || contentKey === void 0 ? void 0 : contentKey.toString().split('/').join('~1')}/schema`;
204
- }
205
- const examplesObj = (_f = requestBodyObj.content[contentKey]) === null || _f === void 0 ? void 0 : _f.examples;
206
- if (examplesObj) {
207
- operationConfig.requestSample = Object.values(examplesObj)[0];
208
- }
209
- }
210
- }
211
- const responseByStatusCode = operationConfig.responseByStatusCode;
212
- // Handling multiple response types
213
- for (const responseKey in methodObj.responses) {
214
- const responseObj = methodObj.responses[responseKey];
215
- let schemaObj;
216
- if ('content' in responseObj) {
217
- const contentKey = Object.keys(responseObj.content)[0];
218
- schemaObj = responseObj.content[contentKey].schema;
219
- if (schemaObj && Object.keys(schemaObj).length > 0) {
220
- responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
221
- responseByStatusCode[responseKey].responseSchema = `${oasFilePath}#/paths/${relativePath
222
- .split('/')
223
- .join('~1')}/${method}/responses/${responseKey}/content/${contentKey === null || contentKey === void 0 ? void 0 : contentKey.toString().split('/').join('~1')}/schema`;
224
- }
225
- const examplesObj = responseObj.content[contentKey].examples;
226
- if (examplesObj) {
227
- responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
228
- responseByStatusCode[responseKey].responseSample = Object.values(examplesObj)[0];
229
- }
230
- const example = responseObj.content[contentKey].example;
231
- if (example) {
232
- responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
233
- responseByStatusCode[responseKey].responseSample = example;
234
- }
235
- }
236
- else if ('schema' in responseObj) {
237
- schemaObj = responseObj.schema;
238
- if (schemaObj && Object.keys(schemaObj).length > 0) {
239
- responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
240
- responseByStatusCode[responseKey].responseSchema = `${oasFilePath}#/paths/${relativePath
241
- .split('/')
242
- .join('~1')}/${method}/responses/${responseKey}/schema`;
243
- }
244
- }
245
- else if ('examples' in responseObj) {
246
- const examples = Object.values(responseObj.examples);
247
- responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
248
- responseByStatusCode[responseKey].responseSample = examples[0];
249
- }
250
- else if (responseKey.toString() === '204') {
251
- responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
252
- responseByStatusCode[responseKey].responseSchema = {
253
- type: 'null',
254
- description: responseObj.description,
255
- };
256
- }
257
- if ('links' in responseObj) {
258
- const dereferencedLinkObj = await dereferenceObject({
259
- links: responseObj.links,
260
- }, {
261
- cwd,
262
- root: oasOrSwagger,
263
- fetchFn,
264
- logger,
265
- headers: schemaHeaders,
266
- });
267
- responseByStatusCode[responseKey].links = responseByStatusCode[responseKey].links || {};
268
- for (const linkName in dereferencedLinkObj.links) {
269
- const linkObj = responseObj.links[linkName];
270
- if ('$ref' in linkObj) {
271
- throw new Error('Unexpected $ref in dereferenced link object');
272
- }
273
- const args = {};
274
- for (const parameterName in linkObj.parameters || {}) {
275
- const parameterExp = linkObj.parameters[parameterName].split('-').join('_');
276
- args[sanitizeNameForGraphQL(parameterName)] = parameterExp.startsWith('$')
277
- ? `{root.${parameterExp}}`
278
- : parameterExp.split('$').join('root.$');
279
- }
280
- if ('operationRef' in linkObj) {
281
- const [externalPath, ref] = linkObj.operationRef.split('#');
282
- if (externalPath) {
283
- if (process.env.DEBUG) {
284
- console.warn(`Skipping external operation reference ${linkObj.operationRef}\n Use additionalTypeDefs and additionalResolvers instead.`);
285
- }
286
- }
287
- else {
288
- const actualOperation = resolvePath(ref, oasOrSwagger);
289
- if (actualOperation.operationId) {
290
- const fieldName = sanitizeNameForGraphQL(actualOperation.operationId);
291
- responseByStatusCode[responseKey].links[linkName] = {
292
- fieldName,
293
- args,
294
- description: linkObj.description,
295
- };
296
- }
297
- else {
298
- console.warn('Missing operationId skipping...');
299
- }
300
- }
301
- }
302
- else if ('operationId' in linkObj) {
303
- responseByStatusCode[responseKey].links[linkName] = {
304
- fieldName: sanitizeNameForGraphQL(linkObj.operationId),
305
- args,
306
- description: linkObj.description,
307
- };
308
- }
309
- }
310
- }
311
- if (!operationConfig.field) {
312
- methodObj.operationId = getFieldNameFromPath(relativePath, method, schemaObj === null || schemaObj === void 0 ? void 0 : schemaObj.$ref);
313
- // Operation ID might not be avaiable so let's generate field name from path and response type schema
314
- operationConfig.field = sanitizeNameForGraphQL(methodObj.operationId);
315
- }
316
- // Give a better name to the request input object
317
- if (typeof operationConfig.requestSchema === 'object' && !operationConfig.requestSchema.title) {
318
- operationConfig.requestSchema.title = operationConfig.field + '_request';
319
- }
320
- }
321
- if (fieldTypeMap[operationConfig.field]) {
322
- operationConfig.type = fieldTypeMap[operationConfig.field];
323
- }
324
- }
325
- }
326
- return {
327
- operations,
328
- baseUrl,
329
- cwd,
330
- fetch: fetchFn,
331
- schemaHeaders,
332
- operationHeaders,
333
- };
334
- }
335
-
336
- /**
337
- * Creates a local GraphQLSchema instance from a OpenAPI Document.
338
- * Everytime this function is called, the OpenAPI file and its dependencies will be resolved on runtime.
339
- * If you want to avoid this, use `createBundle` function to create a bundle once and save it to a storage
340
- * then load it with `loadGraphQLSchemaFromBundle`.
341
- */
342
- async function loadGraphQLSchemaFromOpenAPI(name, options) {
343
- const extraJSONSchemaOptions = await getJSONSchemaOptionsFromOpenAPIOptions(options);
344
- return loadGraphQLSchemaFromJSONSchemas(name, {
345
- ...options,
346
- ...extraJSONSchemaOptions,
347
- });
348
- }
349
-
350
- /**
351
- * Creates a bundle by downloading and resolving the internal references once
352
- * to load the schema locally later
353
- */
354
- async function createBundle(name, openApiLoaderOptions) {
355
- const { operations, baseUrl, cwd, fetch, schemaHeaders, operationHeaders } = await getJSONSchemaOptionsFromOpenAPIOptions(openApiLoaderOptions);
356
- return createBundle$1(name, {
357
- operations,
358
- baseUrl,
359
- cwd,
360
- fetch,
361
- schemaHeaders,
362
- operationHeaders,
363
- ignoreErrorResponses: openApiLoaderOptions.ignoreErrorResponses,
364
- logger: openApiLoaderOptions.logger,
365
- });
366
- }
367
-
368
- export default loadGraphQLSchemaFromOpenAPI;
369
- export { createBundle, getJSONSchemaOptionsFromOpenAPIOptions };
File without changes