@omnigraph/openapi 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.
- package/cjs/getJSONSchemaOptionsFromOpenAPIOptions.js +471 -0
- package/cjs/index.js +9 -0
- package/cjs/loadGraphQLSchemaFromOpenAPI.js +29 -0
- package/cjs/package.json +1 -0
- package/cjs/types.js +0 -0
- package/cjs/utils.js +44 -0
- package/esm/getJSONSchemaOptionsFromOpenAPIOptions.js +467 -0
- package/esm/index.js +3 -0
- package/esm/loadGraphQLSchemaFromOpenAPI.js +23 -0
- package/esm/types.js +0 -0
- package/esm/utils.js +40 -0
- package/package.json +28 -21
- package/typings/getJSONSchemaOptionsFromOpenAPIOptions.d.cts +26 -0
- package/typings/getJSONSchemaOptionsFromOpenAPIOptions.d.ts +26 -0
- package/typings/index.d.cts +4 -0
- package/typings/index.d.ts +4 -0
- package/typings/loadGraphQLSchemaFromOpenAPI.d.cts +10 -0
- package/{loadGraphQLSchemaFromOpenAPI.d.ts → typings/loadGraphQLSchemaFromOpenAPI.d.ts} +3 -1
- package/typings/types.d.cts +10 -0
- package/{types.d.ts → typings/types.d.ts} +2 -2
- package/typings/utils.d.ts +1 -0
- package/bundle.d.ts +0 -8
- package/getJSONSchemaOptionsFromOpenAPIOptions.d.ts +0 -24
- package/index.d.ts +0 -4
- package/index.js +0 -355
- package/index.mjs +0 -345
- /package/{utils.d.ts → typings/utils.d.cts} +0 -0
package/index.mjs
DELETED
|
@@ -1,345 +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 { dereferenceObject, resolvePath } 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;
|
|
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
|
-
for (const method in pathObj) {
|
|
70
|
-
const methodObj = pathObj[method];
|
|
71
|
-
const operationConfig = {
|
|
72
|
-
method: method.toUpperCase(),
|
|
73
|
-
path: relativePath,
|
|
74
|
-
type: method.toUpperCase() === 'GET' ? 'query' : 'mutation',
|
|
75
|
-
field: methodObj.operationId && sanitizeNameForGraphQL(methodObj.operationId),
|
|
76
|
-
description: methodObj.description || methodObj.summary,
|
|
77
|
-
schemaHeaders,
|
|
78
|
-
operationHeaders,
|
|
79
|
-
responseByStatusCode: {},
|
|
80
|
-
};
|
|
81
|
-
operations.push(operationConfig);
|
|
82
|
-
for (const paramObjIndex in methodObj.parameters) {
|
|
83
|
-
const paramObj = methodObj.parameters[paramObjIndex];
|
|
84
|
-
const argName = sanitizeNameForGraphQL(paramObj.name);
|
|
85
|
-
switch (paramObj.in) {
|
|
86
|
-
case 'query':
|
|
87
|
-
if (method.toUpperCase() === 'GET') {
|
|
88
|
-
const requestSchema = (operationConfig.requestSchema = operationConfig.requestSchema || {
|
|
89
|
-
type: 'object',
|
|
90
|
-
properties: {},
|
|
91
|
-
});
|
|
92
|
-
requestSchema.properties[paramObj.name] =
|
|
93
|
-
paramObj.schema || ((_b = (_a = paramObj.content) === null || _a === void 0 ? void 0 : _a['application/json']) === null || _b === void 0 ? void 0 : _b.schema) || paramObj;
|
|
94
|
-
if (!requestSchema.properties[paramObj.name].title) {
|
|
95
|
-
requestSchema.properties[paramObj.name].name = paramObj.name;
|
|
96
|
-
}
|
|
97
|
-
if (!requestSchema.properties[paramObj.name].description) {
|
|
98
|
-
requestSchema.properties[paramObj.name].description = paramObj.description;
|
|
99
|
-
}
|
|
100
|
-
if (requestSchema.properties.__typename) {
|
|
101
|
-
delete requestSchema.properties.__typename;
|
|
102
|
-
}
|
|
103
|
-
if (paramObj.required) {
|
|
104
|
-
requestSchema.required = requestSchema.required || [];
|
|
105
|
-
requestSchema.required.push(paramObj.name);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
if (!operationConfig.path.includes('?')) {
|
|
110
|
-
operationConfig.path += '?';
|
|
111
|
-
}
|
|
112
|
-
operationConfig.path += `${paramObj.name}={args.${argName}}`;
|
|
113
|
-
}
|
|
114
|
-
break;
|
|
115
|
-
case 'path': {
|
|
116
|
-
// If it is in the path, let JSON Schema handler put it
|
|
117
|
-
operationConfig.path = operationConfig.path.replace(`{${paramObj.name}}`, `{args.${argName}}`);
|
|
118
|
-
break;
|
|
119
|
-
}
|
|
120
|
-
case 'header': {
|
|
121
|
-
operationConfig.headers = operationConfig.headers || {};
|
|
122
|
-
operationConfig.headers[paramObj.name] = `{args.${argName}}`;
|
|
123
|
-
break;
|
|
124
|
-
}
|
|
125
|
-
case 'cookie': {
|
|
126
|
-
operationConfig.headers = operationConfig.headers || {};
|
|
127
|
-
operationConfig.headers.cookie = operationConfig.headers.cookie || '';
|
|
128
|
-
const cookieParams = operationConfig.headers.cookie.split('; ');
|
|
129
|
-
cookieParams.push(`${paramObj.name}={args.${argName}}`);
|
|
130
|
-
operationConfig.headers.cookie = cookieParams.join('; ');
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
case 'body':
|
|
134
|
-
if (paramObj.schema && Object.keys(paramObj.schema).length > 0) {
|
|
135
|
-
operationConfig.requestSchema = `${oasFilePath}#/paths/${relativePath
|
|
136
|
-
.split('/')
|
|
137
|
-
.join('~1')}/${method}/parameters/${paramObjIndex}/schema`;
|
|
138
|
-
}
|
|
139
|
-
if (paramObj.example) {
|
|
140
|
-
operationConfig.requestSample = paramObj.example;
|
|
141
|
-
}
|
|
142
|
-
if (paramObj.examples) {
|
|
143
|
-
operationConfig.requestSample = Object.values(paramObj.examples)[0];
|
|
144
|
-
}
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
147
|
-
switch (((_c = paramObj.schema) === null || _c === void 0 ? void 0 : _c.type) || paramObj.type) {
|
|
148
|
-
case 'string':
|
|
149
|
-
operationConfig.argTypeMap = operationConfig.argTypeMap || {};
|
|
150
|
-
operationConfig.argTypeMap[argName] = 'String';
|
|
151
|
-
break;
|
|
152
|
-
case 'integer':
|
|
153
|
-
operationConfig.argTypeMap = operationConfig.argTypeMap || {};
|
|
154
|
-
operationConfig.argTypeMap[argName] = 'Int';
|
|
155
|
-
break;
|
|
156
|
-
case 'number':
|
|
157
|
-
operationConfig.argTypeMap = operationConfig.argTypeMap || {};
|
|
158
|
-
operationConfig.argTypeMap[argName] = 'Float';
|
|
159
|
-
break;
|
|
160
|
-
case 'boolean':
|
|
161
|
-
operationConfig.argTypeMap = operationConfig.argTypeMap || {};
|
|
162
|
-
operationConfig.argTypeMap[argName] = 'Boolean';
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
165
|
-
if (paramObj.required) {
|
|
166
|
-
operationConfig.argTypeMap = operationConfig.argTypeMap || {};
|
|
167
|
-
operationConfig.argTypeMap[argName] = operationConfig.argTypeMap[argName] || 'ID';
|
|
168
|
-
operationConfig.argTypeMap[argName] += '!';
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
if ('requestBody' in methodObj) {
|
|
172
|
-
const requestBodyObj = methodObj.requestBody;
|
|
173
|
-
if ('content' in requestBodyObj) {
|
|
174
|
-
const contentKey = Object.keys(requestBodyObj.content)[0];
|
|
175
|
-
const contentSchema = (_d = requestBodyObj.content[contentKey]) === null || _d === void 0 ? void 0 : _d.schema;
|
|
176
|
-
if (contentSchema && Object.keys(contentSchema).length > 0) {
|
|
177
|
-
operationConfig.requestSchema = `${oasFilePath}#/paths/${relativePath
|
|
178
|
-
.split('/')
|
|
179
|
-
.join('~1')}/${method}/requestBody/content/${contentKey === null || contentKey === void 0 ? void 0 : contentKey.toString().split('/').join('~1')}/schema`;
|
|
180
|
-
}
|
|
181
|
-
const examplesObj = (_e = requestBodyObj.content[contentKey]) === null || _e === void 0 ? void 0 : _e.examples;
|
|
182
|
-
if (examplesObj) {
|
|
183
|
-
operationConfig.requestSample = Object.values(examplesObj)[0];
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
const responseByStatusCode = operationConfig.responseByStatusCode;
|
|
188
|
-
// Handling multiple response types
|
|
189
|
-
for (const responseKey in methodObj.responses) {
|
|
190
|
-
const responseObj = methodObj.responses[responseKey];
|
|
191
|
-
let schemaObj;
|
|
192
|
-
if ('content' in responseObj) {
|
|
193
|
-
const contentKey = Object.keys(responseObj.content)[0];
|
|
194
|
-
schemaObj = responseObj.content[contentKey].schema;
|
|
195
|
-
if (schemaObj && Object.keys(schemaObj).length > 0) {
|
|
196
|
-
responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
|
|
197
|
-
responseByStatusCode[responseKey].responseSchema = `${oasFilePath}#/paths/${relativePath
|
|
198
|
-
.split('/')
|
|
199
|
-
.join('~1')}/${method}/responses/${responseKey}/content/${contentKey === null || contentKey === void 0 ? void 0 : contentKey.toString().split('/').join('~1')}/schema`;
|
|
200
|
-
}
|
|
201
|
-
const examplesObj = responseObj.content[contentKey].examples;
|
|
202
|
-
if (examplesObj) {
|
|
203
|
-
responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
|
|
204
|
-
responseByStatusCode[responseKey].responseSample = Object.values(examplesObj)[0];
|
|
205
|
-
}
|
|
206
|
-
const example = responseObj.content[contentKey].example;
|
|
207
|
-
if (example) {
|
|
208
|
-
responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
|
|
209
|
-
responseByStatusCode[responseKey].responseSample = example;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
else if ('schema' in responseObj) {
|
|
213
|
-
schemaObj = responseObj.schema;
|
|
214
|
-
if (schemaObj && Object.keys(schemaObj).length > 0) {
|
|
215
|
-
responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
|
|
216
|
-
responseByStatusCode[responseKey].responseSchema = `${oasFilePath}#/paths/${relativePath
|
|
217
|
-
.split('/')
|
|
218
|
-
.join('~1')}/${method}/responses/${responseKey}/schema`;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
else if ('examples' in responseObj) {
|
|
222
|
-
const examples = Object.values(responseObj.examples);
|
|
223
|
-
responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
|
|
224
|
-
responseByStatusCode[responseKey].responseSample = examples[0];
|
|
225
|
-
}
|
|
226
|
-
else if (responseKey.toString() === '204') {
|
|
227
|
-
responseByStatusCode[responseKey] = responseByStatusCode[responseKey] || {};
|
|
228
|
-
responseByStatusCode[responseKey].responseSchema = {
|
|
229
|
-
type: 'null',
|
|
230
|
-
description: responseObj.description,
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
if ('links' in responseObj) {
|
|
234
|
-
const dereferencedLinkObj = await dereferenceObject({
|
|
235
|
-
links: responseObj.links,
|
|
236
|
-
}, {
|
|
237
|
-
cwd,
|
|
238
|
-
root: oasOrSwagger,
|
|
239
|
-
fetchFn,
|
|
240
|
-
logger,
|
|
241
|
-
headers: schemaHeaders,
|
|
242
|
-
});
|
|
243
|
-
responseByStatusCode[responseKey].links = responseByStatusCode[responseKey].links || {};
|
|
244
|
-
for (const linkName in dereferencedLinkObj.links) {
|
|
245
|
-
const linkObj = responseObj.links[linkName];
|
|
246
|
-
if ('$ref' in linkObj) {
|
|
247
|
-
throw new Error('Unexpected $ref in dereferenced link object');
|
|
248
|
-
}
|
|
249
|
-
const args = {};
|
|
250
|
-
for (const parameterName in linkObj.parameters || {}) {
|
|
251
|
-
const parameterExp = linkObj.parameters[parameterName].split('-').join('_');
|
|
252
|
-
args[sanitizeNameForGraphQL(parameterName)] = parameterExp.startsWith('$')
|
|
253
|
-
? `{root.${parameterExp}}`
|
|
254
|
-
: parameterExp.split('$').join('root.$');
|
|
255
|
-
}
|
|
256
|
-
if ('operationRef' in linkObj) {
|
|
257
|
-
const [externalPath, ref] = linkObj.operationRef.split('#');
|
|
258
|
-
if (externalPath) {
|
|
259
|
-
if (process.env.DEBUG) {
|
|
260
|
-
console.warn(`Skipping external operation reference ${linkObj.operationRef}\n Use additionalTypeDefs and additionalResolvers instead.`);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
const actualOperation = resolvePath(ref, oasOrSwagger);
|
|
265
|
-
if (actualOperation.operationId) {
|
|
266
|
-
const fieldName = sanitizeNameForGraphQL(actualOperation.operationId);
|
|
267
|
-
responseByStatusCode[responseKey].links[linkName] = {
|
|
268
|
-
fieldName,
|
|
269
|
-
args,
|
|
270
|
-
description: linkObj.description,
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
console.warn('Missing operationId skipping...');
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
else if ('operationId' in linkObj) {
|
|
279
|
-
responseByStatusCode[responseKey].links[linkName] = {
|
|
280
|
-
fieldName: sanitizeNameForGraphQL(linkObj.operationId),
|
|
281
|
-
args,
|
|
282
|
-
description: linkObj.description,
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
if (!operationConfig.field) {
|
|
288
|
-
methodObj.operationId = getFieldNameFromPath(relativePath, method, schemaObj === null || schemaObj === void 0 ? void 0 : schemaObj.$ref);
|
|
289
|
-
// Operation ID might not be avaiable so let's generate field name from path and response type schema
|
|
290
|
-
operationConfig.field = sanitizeNameForGraphQL(methodObj.operationId);
|
|
291
|
-
}
|
|
292
|
-
// Give a better name to the request input object
|
|
293
|
-
if (typeof operationConfig.requestSchema === 'object' && !operationConfig.requestSchema.title) {
|
|
294
|
-
operationConfig.requestSchema.title = operationConfig.field + '_request';
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
if (fieldTypeMap[operationConfig.field]) {
|
|
298
|
-
operationConfig.type = fieldTypeMap[operationConfig.field];
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
return {
|
|
303
|
-
operations,
|
|
304
|
-
baseUrl,
|
|
305
|
-
cwd,
|
|
306
|
-
fetch: fetchFn,
|
|
307
|
-
schemaHeaders,
|
|
308
|
-
operationHeaders,
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Creates a local GraphQLSchema instance from a OpenAPI Document.
|
|
314
|
-
* Everytime this function is called, the OpenAPI file and its dependencies will be resolved on runtime.
|
|
315
|
-
* If you want to avoid this, use `createBundle` function to create a bundle once and save it to a storage
|
|
316
|
-
* then load it with `loadGraphQLSchemaFromBundle`.
|
|
317
|
-
*/
|
|
318
|
-
async function loadGraphQLSchemaFromOpenAPI(name, options) {
|
|
319
|
-
const extraJSONSchemaOptions = await getJSONSchemaOptionsFromOpenAPIOptions(options);
|
|
320
|
-
return loadGraphQLSchemaFromJSONSchemas(name, {
|
|
321
|
-
...options,
|
|
322
|
-
...extraJSONSchemaOptions,
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Creates a bundle by downloading and resolving the internal references once
|
|
328
|
-
* to load the schema locally later
|
|
329
|
-
*/
|
|
330
|
-
async function createBundle(name, openApiLoaderOptions) {
|
|
331
|
-
const { operations, baseUrl, cwd, fetch, schemaHeaders, operationHeaders } = await getJSONSchemaOptionsFromOpenAPIOptions(openApiLoaderOptions);
|
|
332
|
-
return createBundle$1(name, {
|
|
333
|
-
operations,
|
|
334
|
-
baseUrl,
|
|
335
|
-
cwd,
|
|
336
|
-
fetch,
|
|
337
|
-
schemaHeaders,
|
|
338
|
-
operationHeaders,
|
|
339
|
-
ignoreErrorResponses: openApiLoaderOptions.ignoreErrorResponses,
|
|
340
|
-
logger: openApiLoaderOptions.logger,
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
export default loadGraphQLSchemaFromOpenAPI;
|
|
345
|
-
export { createBundle, getJSONSchemaOptionsFromOpenAPIOptions };
|
|
File without changes
|