dbgate-rest 7.1.3-alpha.2
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/README.md +7 -0
- package/lib/arrayify.d.ts +3 -0
- package/lib/arrayify.js +81 -0
- package/lib/graphQlDriver.d.ts +2 -0
- package/lib/graphQlDriver.js +55 -0
- package/lib/graphQlQueryParser.d.ts +5 -0
- package/lib/graphQlQueryParser.js +204 -0
- package/lib/graphQlVariables.d.ts +6 -0
- package/lib/graphQlVariables.js +123 -0
- package/lib/graphqlExplorer.d.ts +26 -0
- package/lib/graphqlExplorer.js +125 -0
- package/lib/graphqlIntrospection.d.ts +56 -0
- package/lib/graphqlIntrospection.js +409 -0
- package/lib/index.d.ts +13 -0
- package/lib/index.js +29 -0
- package/lib/oDataAdapter.d.ts +33 -0
- package/lib/oDataAdapter.js +358 -0
- package/lib/oDataAdapter.test.d.ts +2 -0
- package/lib/oDataAdapter.test.js +61 -0
- package/lib/oDataDriver.d.ts +2 -0
- package/lib/oDataDriver.js +85 -0
- package/lib/oDataMetadataParser.d.ts +2 -0
- package/lib/oDataMetadataParser.js +137 -0
- package/lib/openApiAdapter.d.ts +7 -0
- package/lib/openApiAdapter.js +254 -0
- package/lib/openApiDriver.d.ts +2 -0
- package/lib/openApiDriver.js +90 -0
- package/lib/restApiDef.d.ts +55 -0
- package/lib/restApiDef.js +2 -0
- package/lib/restApiExecutor.d.ts +4 -0
- package/lib/restApiExecutor.js +292 -0
- package/lib/restApiExecutor.test.d.ts +16 -0
- package/lib/restApiExecutor.test.js +99 -0
- package/lib/restAuthTools.d.ts +2 -0
- package/lib/restAuthTools.js +20 -0
- package/lib/restDriverBase.d.ts +61 -0
- package/lib/restDriverBase.js +49 -0
- package/package.json +42 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { RestApiDefinition } from './restApiDef';
|
|
2
|
+
import type { AxiosInstance } from 'axios';
|
|
3
|
+
export interface GraphQLTypeRef {
|
|
4
|
+
kind: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
ofType?: GraphQLTypeRef | null;
|
|
7
|
+
}
|
|
8
|
+
export interface GraphQLInputValue {
|
|
9
|
+
name: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
type: GraphQLTypeRef;
|
|
12
|
+
defaultValue?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface GraphQLField {
|
|
15
|
+
name: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
type: GraphQLTypeRef;
|
|
18
|
+
args?: GraphQLInputValue[];
|
|
19
|
+
}
|
|
20
|
+
export interface GraphQLType {
|
|
21
|
+
kind: string;
|
|
22
|
+
name: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
fields?: GraphQLField[];
|
|
25
|
+
inputFields?: GraphQLField[];
|
|
26
|
+
possibleTypes?: GraphQLTypeRef[];
|
|
27
|
+
}
|
|
28
|
+
export interface GraphQLIntrospectionResult {
|
|
29
|
+
__schema: {
|
|
30
|
+
types: GraphQLType[];
|
|
31
|
+
queryType?: {
|
|
32
|
+
name: string;
|
|
33
|
+
};
|
|
34
|
+
mutationType?: {
|
|
35
|
+
name: string;
|
|
36
|
+
};
|
|
37
|
+
subscriptionType?: {
|
|
38
|
+
name: string;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export declare function scoreFieldName(name: string): number;
|
|
43
|
+
export declare function chooseUsefulNodeAttributes(nodeType: GraphQLType | undefined, typeMap: Map<string, GraphQLType>): string[];
|
|
44
|
+
export declare function buildFirstTenArgs(field: GraphQLField, filterParamName?: string | null, filterValue?: string): string;
|
|
45
|
+
export type GraphQLConnectionProjection = {
|
|
46
|
+
kind: 'edges';
|
|
47
|
+
nodeTypeName: string;
|
|
48
|
+
hasPageInfo: boolean;
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'listField';
|
|
51
|
+
listFieldName: string;
|
|
52
|
+
nodeTypeName: string;
|
|
53
|
+
};
|
|
54
|
+
export declare function detectConnectionProjection(field: GraphQLField, typeMap: Map<string, GraphQLType>): GraphQLConnectionProjection | null;
|
|
55
|
+
export declare function extractRestApiDefinitionFromGraphQlIntrospectionResult(introspectionResult: GraphQLIntrospectionResult): RestApiDefinition;
|
|
56
|
+
export declare function fetchGraphQLSchema(url: string, headers: Record<string, string>, axios: AxiosInstance, maxDepth?: number): Promise<GraphQLIntrospectionResult>;
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchGraphQLSchema = exports.extractRestApiDefinitionFromGraphQlIntrospectionResult = exports.detectConnectionProjection = exports.buildFirstTenArgs = exports.chooseUsefulNodeAttributes = exports.scoreFieldName = void 0;
|
|
4
|
+
const DEFAULT_INTROSPECTION_DEPTH = 6;
|
|
5
|
+
function buildTypeRefSelection(depth) {
|
|
6
|
+
if (depth <= 0) {
|
|
7
|
+
return `
|
|
8
|
+
kind
|
|
9
|
+
name
|
|
10
|
+
`;
|
|
11
|
+
}
|
|
12
|
+
return `
|
|
13
|
+
kind
|
|
14
|
+
name
|
|
15
|
+
ofType {
|
|
16
|
+
${buildTypeRefSelection(depth - 1)}
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
}
|
|
20
|
+
function buildIntrospectionQuery(maxDepth) {
|
|
21
|
+
const typeRefSelection = buildTypeRefSelection(maxDepth);
|
|
22
|
+
return `
|
|
23
|
+
query IntrospectionQuery {
|
|
24
|
+
__schema {
|
|
25
|
+
types {
|
|
26
|
+
kind
|
|
27
|
+
name
|
|
28
|
+
description
|
|
29
|
+
fields {
|
|
30
|
+
name
|
|
31
|
+
description
|
|
32
|
+
type {
|
|
33
|
+
${typeRefSelection}
|
|
34
|
+
}
|
|
35
|
+
args {
|
|
36
|
+
name
|
|
37
|
+
description
|
|
38
|
+
type {
|
|
39
|
+
${typeRefSelection}
|
|
40
|
+
}
|
|
41
|
+
defaultValue
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
inputFields {
|
|
45
|
+
name
|
|
46
|
+
description
|
|
47
|
+
type {
|
|
48
|
+
${typeRefSelection}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
queryType {
|
|
53
|
+
name
|
|
54
|
+
}
|
|
55
|
+
mutationType {
|
|
56
|
+
name
|
|
57
|
+
}
|
|
58
|
+
subscriptionType {
|
|
59
|
+
name
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
`;
|
|
64
|
+
}
|
|
65
|
+
function getTypeString(type) {
|
|
66
|
+
if (!type)
|
|
67
|
+
return 'Unknown';
|
|
68
|
+
if (type.kind === 'NON_NULL')
|
|
69
|
+
return getTypeString(type.ofType) + '!';
|
|
70
|
+
if (type.kind === 'LIST')
|
|
71
|
+
return '[' + getTypeString(type.ofType) + ']';
|
|
72
|
+
return type.name || 'Unknown';
|
|
73
|
+
}
|
|
74
|
+
function findType(types, name) {
|
|
75
|
+
return types.find(t => t.name === name);
|
|
76
|
+
}
|
|
77
|
+
function unwrapNamedTypeRef(typeRef) {
|
|
78
|
+
if (!typeRef)
|
|
79
|
+
return null;
|
|
80
|
+
if (typeRef.kind === 'NON_NULL' || typeRef.kind === 'LIST')
|
|
81
|
+
return unwrapNamedTypeRef(typeRef.ofType);
|
|
82
|
+
return typeRef;
|
|
83
|
+
}
|
|
84
|
+
function unwrapListTypeRef(typeRef) {
|
|
85
|
+
if (!typeRef)
|
|
86
|
+
return null;
|
|
87
|
+
if (typeRef.kind === 'NON_NULL')
|
|
88
|
+
return unwrapListTypeRef(typeRef.ofType);
|
|
89
|
+
if (typeRef.kind === 'LIST')
|
|
90
|
+
return unwrapNamedTypeRef(typeRef.ofType);
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
function buildTypeMap(types) {
|
|
94
|
+
return new Map((types || []).map(type => [type.name, type]));
|
|
95
|
+
}
|
|
96
|
+
function isScalarLikeField(field, typeMap) {
|
|
97
|
+
const namedType = unwrapNamedTypeRef(field.type);
|
|
98
|
+
if (!(namedType === null || namedType === void 0 ? void 0 : namedType.name))
|
|
99
|
+
return false;
|
|
100
|
+
const type = typeMap.get(namedType.name);
|
|
101
|
+
if (!type)
|
|
102
|
+
return namedType.kind === 'SCALAR' || namedType.kind === 'ENUM';
|
|
103
|
+
return type.kind === 'SCALAR' || type.kind === 'ENUM';
|
|
104
|
+
}
|
|
105
|
+
function scoreFieldName(name) {
|
|
106
|
+
const lowerName = (name || '').toLowerCase();
|
|
107
|
+
const exactOrder = [
|
|
108
|
+
'id',
|
|
109
|
+
'name',
|
|
110
|
+
'title',
|
|
111
|
+
'email',
|
|
112
|
+
'username',
|
|
113
|
+
'status',
|
|
114
|
+
'createdat',
|
|
115
|
+
'updatedat',
|
|
116
|
+
'type',
|
|
117
|
+
'code',
|
|
118
|
+
'key',
|
|
119
|
+
];
|
|
120
|
+
const exactIndex = exactOrder.indexOf(lowerName);
|
|
121
|
+
if (exactIndex >= 0) {
|
|
122
|
+
return 500 - exactIndex;
|
|
123
|
+
}
|
|
124
|
+
if (lowerName.endsWith('id'))
|
|
125
|
+
return 300;
|
|
126
|
+
if (lowerName.includes('name'))
|
|
127
|
+
return 280;
|
|
128
|
+
if (lowerName.includes('title'))
|
|
129
|
+
return 260;
|
|
130
|
+
if (lowerName.includes('email'))
|
|
131
|
+
return 240;
|
|
132
|
+
if (lowerName.includes('status'))
|
|
133
|
+
return 220;
|
|
134
|
+
if (lowerName.includes('date') || lowerName.endsWith('at'))
|
|
135
|
+
return 200;
|
|
136
|
+
return 100;
|
|
137
|
+
}
|
|
138
|
+
exports.scoreFieldName = scoreFieldName;
|
|
139
|
+
function chooseUsefulNodeAttributes(nodeType, typeMap) {
|
|
140
|
+
var _a;
|
|
141
|
+
if (!((_a = nodeType === null || nodeType === void 0 ? void 0 : nodeType.fields) === null || _a === void 0 ? void 0 : _a.length))
|
|
142
|
+
return ['__typename'];
|
|
143
|
+
const scalarFields = nodeType.fields.filter(field => isScalarLikeField(field, typeMap));
|
|
144
|
+
if (scalarFields.length === 0)
|
|
145
|
+
return ['__typename'];
|
|
146
|
+
return scalarFields
|
|
147
|
+
.map((field, index) => ({
|
|
148
|
+
field,
|
|
149
|
+
score: scoreFieldName(field.name),
|
|
150
|
+
index,
|
|
151
|
+
}))
|
|
152
|
+
.sort((left, right) => {
|
|
153
|
+
if (right.score !== left.score)
|
|
154
|
+
return right.score - left.score;
|
|
155
|
+
return left.index - right.index;
|
|
156
|
+
})
|
|
157
|
+
.slice(0, 10)
|
|
158
|
+
.map(item => item.field.name);
|
|
159
|
+
}
|
|
160
|
+
exports.chooseUsefulNodeAttributes = chooseUsefulNodeAttributes;
|
|
161
|
+
function stringifyArgumentValue(argumentTypeRef, value) {
|
|
162
|
+
const namedType = unwrapNamedTypeRef(argumentTypeRef);
|
|
163
|
+
if (!(namedType === null || namedType === void 0 ? void 0 : namedType.name)) {
|
|
164
|
+
// Fallback: safely stringify as a JSON string literal
|
|
165
|
+
return JSON.stringify(String(value));
|
|
166
|
+
}
|
|
167
|
+
const typeName = namedType.name.toLowerCase();
|
|
168
|
+
if (typeName === 'int' || typeName === 'float') {
|
|
169
|
+
const numValue = typeof value === 'number' ? value : Number(value);
|
|
170
|
+
if (Number.isFinite(numValue)) {
|
|
171
|
+
return String(numValue);
|
|
172
|
+
}
|
|
173
|
+
// If the value cannot be parsed as a valid number, fall back to a quoted string
|
|
174
|
+
return JSON.stringify(String(value));
|
|
175
|
+
}
|
|
176
|
+
// For non-numeric types, safely serialize as a JSON string literal
|
|
177
|
+
return JSON.stringify(String(value));
|
|
178
|
+
}
|
|
179
|
+
function buildFirstTenArgs(field, filterParamName, filterValue) {
|
|
180
|
+
const args = field.args || [];
|
|
181
|
+
if (args.length === 0)
|
|
182
|
+
return '';
|
|
183
|
+
const argPairs = [];
|
|
184
|
+
// Add pagination argument
|
|
185
|
+
const candidates = ['first', 'limit', 'pagesize', 'perpage', 'take', 'size', 'count', 'maxresults'];
|
|
186
|
+
const paginationArg = args.find(item => candidates.includes((item.name || '').toLowerCase()));
|
|
187
|
+
if (paginationArg) {
|
|
188
|
+
argPairs.push(`${paginationArg.name}: ${stringifyArgumentValue(paginationArg.type, 10)}`);
|
|
189
|
+
}
|
|
190
|
+
// Add filter argument if provided
|
|
191
|
+
if (filterParamName && filterValue) {
|
|
192
|
+
const filterArg = args.find(item => item.name === filterParamName);
|
|
193
|
+
if (filterArg) {
|
|
194
|
+
argPairs.push(`${filterParamName}: ${stringifyArgumentValue(filterArg.type, filterValue)}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (argPairs.length === 0)
|
|
198
|
+
return '';
|
|
199
|
+
return `(${argPairs.join(', ')})`;
|
|
200
|
+
}
|
|
201
|
+
exports.buildFirstTenArgs = buildFirstTenArgs;
|
|
202
|
+
function detectConnectionProjection(field, typeMap) {
|
|
203
|
+
var _a, _b;
|
|
204
|
+
const fieldTypeRef = unwrapNamedTypeRef(field.type);
|
|
205
|
+
if (!(fieldTypeRef === null || fieldTypeRef === void 0 ? void 0 : fieldTypeRef.name))
|
|
206
|
+
return null;
|
|
207
|
+
const returnType = typeMap.get(fieldTypeRef.name);
|
|
208
|
+
if (!returnType || returnType.kind !== 'OBJECT' || !((_a = returnType.fields) === null || _a === void 0 ? void 0 : _a.length))
|
|
209
|
+
return null;
|
|
210
|
+
const edgesField = returnType.fields.find(item => item.name === 'edges');
|
|
211
|
+
if (edgesField) {
|
|
212
|
+
const edgeTypeRef = unwrapListTypeRef(edgesField.type);
|
|
213
|
+
if (edgeTypeRef === null || edgeTypeRef === void 0 ? void 0 : edgeTypeRef.name) {
|
|
214
|
+
const edgeType = typeMap.get(edgeTypeRef.name);
|
|
215
|
+
const nodeField = (_b = edgeType === null || edgeType === void 0 ? void 0 : edgeType.fields) === null || _b === void 0 ? void 0 : _b.find(item => item.name === 'node');
|
|
216
|
+
const nodeTypeRef = unwrapNamedTypeRef(nodeField === null || nodeField === void 0 ? void 0 : nodeField.type);
|
|
217
|
+
if (nodeTypeRef === null || nodeTypeRef === void 0 ? void 0 : nodeTypeRef.name) {
|
|
218
|
+
const hasPageInfo = !!returnType.fields.find(item => item.name === 'pageInfo');
|
|
219
|
+
return {
|
|
220
|
+
kind: 'edges',
|
|
221
|
+
nodeTypeName: nodeTypeRef.name,
|
|
222
|
+
hasPageInfo,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const listFieldNames = ['nodes', 'items', 'results', 'data'];
|
|
228
|
+
for (const listFieldName of listFieldNames) {
|
|
229
|
+
const listField = returnType.fields.find(item => item.name === listFieldName);
|
|
230
|
+
if (!listField)
|
|
231
|
+
continue;
|
|
232
|
+
const listItemTypeRef = unwrapListTypeRef(listField.type);
|
|
233
|
+
if (!(listItemTypeRef === null || listItemTypeRef === void 0 ? void 0 : listItemTypeRef.name))
|
|
234
|
+
continue;
|
|
235
|
+
return {
|
|
236
|
+
kind: 'listField',
|
|
237
|
+
listFieldName,
|
|
238
|
+
nodeTypeName: listItemTypeRef.name,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
exports.detectConnectionProjection = detectConnectionProjection;
|
|
244
|
+
function buildConnectionQuery(field, typeMap) {
|
|
245
|
+
const projection = detectConnectionProjection(field, typeMap);
|
|
246
|
+
if (!projection)
|
|
247
|
+
return null;
|
|
248
|
+
const nodeType = typeMap.get(projection.nodeTypeName);
|
|
249
|
+
const selectedAttributes = chooseUsefulNodeAttributes(nodeType, typeMap);
|
|
250
|
+
const argsString = buildFirstTenArgs(field);
|
|
251
|
+
const attributeBlock = selectedAttributes.map(attr => ` ${attr}`).join('\n');
|
|
252
|
+
if (projection.kind === 'edges') {
|
|
253
|
+
const pageInfoBlock = projection.hasPageInfo
|
|
254
|
+
? `
|
|
255
|
+
pageInfo {
|
|
256
|
+
hasNextPage
|
|
257
|
+
endCursor
|
|
258
|
+
}`
|
|
259
|
+
: '';
|
|
260
|
+
return `query {
|
|
261
|
+
${field.name}${argsString} {
|
|
262
|
+
edges {
|
|
263
|
+
node {
|
|
264
|
+
${attributeBlock}
|
|
265
|
+
}
|
|
266
|
+
}${pageInfoBlock}
|
|
267
|
+
}
|
|
268
|
+
}`;
|
|
269
|
+
}
|
|
270
|
+
return `query {
|
|
271
|
+
${field.name}${argsString} {
|
|
272
|
+
${projection.listFieldName} {
|
|
273
|
+
${attributeBlock}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}`;
|
|
277
|
+
}
|
|
278
|
+
function buildConnectionEndpoints(types, rootTypeName) {
|
|
279
|
+
var _a;
|
|
280
|
+
if (!rootTypeName)
|
|
281
|
+
return [];
|
|
282
|
+
const rootType = findType(types, rootTypeName);
|
|
283
|
+
if (!((_a = rootType === null || rootType === void 0 ? void 0 : rootType.fields) === null || _a === void 0 ? void 0 : _a.length))
|
|
284
|
+
return [];
|
|
285
|
+
const typeMap = buildTypeMap(types);
|
|
286
|
+
const connectionEndpoints = [];
|
|
287
|
+
for (const field of rootType.fields) {
|
|
288
|
+
const connectionQuery = buildConnectionQuery(field, typeMap);
|
|
289
|
+
if (!connectionQuery)
|
|
290
|
+
continue;
|
|
291
|
+
connectionEndpoints.push({
|
|
292
|
+
name: field.name,
|
|
293
|
+
description: field.description || '',
|
|
294
|
+
fields: field.description,
|
|
295
|
+
connectionQuery,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return connectionEndpoints;
|
|
299
|
+
}
|
|
300
|
+
function buildOperationEndpoints(types, operationType, rootTypeName) {
|
|
301
|
+
if (!rootTypeName)
|
|
302
|
+
return [];
|
|
303
|
+
const rootType = findType(types, rootTypeName);
|
|
304
|
+
if (!rootType || !rootType.fields)
|
|
305
|
+
return [];
|
|
306
|
+
return rootType.fields.map(field => ({
|
|
307
|
+
name: field.name,
|
|
308
|
+
description: field.description || '',
|
|
309
|
+
fields: field.description,
|
|
310
|
+
}));
|
|
311
|
+
}
|
|
312
|
+
function extractRestApiDefinitionFromGraphQlIntrospectionResult(introspectionResult) {
|
|
313
|
+
var _a, _b, _c, _d;
|
|
314
|
+
const { __schema } = introspectionResult;
|
|
315
|
+
const categories = [];
|
|
316
|
+
// Connections (query fields returning connection-like payloads)
|
|
317
|
+
if ((_a = __schema.queryType) === null || _a === void 0 ? void 0 : _a.name) {
|
|
318
|
+
const connectionEndpoints = buildConnectionEndpoints(__schema.types, __schema.queryType.name);
|
|
319
|
+
if (connectionEndpoints.length > 0) {
|
|
320
|
+
categories.push({
|
|
321
|
+
name: 'Connections',
|
|
322
|
+
endpoints: connectionEndpoints.map(connection => ({
|
|
323
|
+
method: 'POST',
|
|
324
|
+
path: connection.name,
|
|
325
|
+
summary: connection.description,
|
|
326
|
+
description: connection.fields,
|
|
327
|
+
parameters: [],
|
|
328
|
+
connectionQuery: connection.connectionQuery,
|
|
329
|
+
})),
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
// Queries
|
|
334
|
+
if ((_b = __schema.queryType) === null || _b === void 0 ? void 0 : _b.name) {
|
|
335
|
+
const queryEndpoints = buildOperationEndpoints(__schema.types, 'OBJECT', __schema.queryType.name);
|
|
336
|
+
if (queryEndpoints.length > 0) {
|
|
337
|
+
categories.push({
|
|
338
|
+
name: 'Queries',
|
|
339
|
+
endpoints: queryEndpoints.map(q => ({
|
|
340
|
+
method: 'POST',
|
|
341
|
+
path: q.name,
|
|
342
|
+
summary: q.description,
|
|
343
|
+
description: q.fields,
|
|
344
|
+
parameters: [],
|
|
345
|
+
})),
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// Mutations
|
|
350
|
+
if ((_c = __schema.mutationType) === null || _c === void 0 ? void 0 : _c.name) {
|
|
351
|
+
const mutationEndpoints = buildOperationEndpoints(__schema.types, 'OBJECT', __schema.mutationType.name);
|
|
352
|
+
if (mutationEndpoints.length > 0) {
|
|
353
|
+
categories.push({
|
|
354
|
+
name: 'Mutations',
|
|
355
|
+
endpoints: mutationEndpoints.map(m => ({
|
|
356
|
+
method: 'POST',
|
|
357
|
+
path: m.name,
|
|
358
|
+
summary: m.description,
|
|
359
|
+
description: m.fields,
|
|
360
|
+
parameters: [],
|
|
361
|
+
})),
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// Subscriptions
|
|
366
|
+
if ((_d = __schema.subscriptionType) === null || _d === void 0 ? void 0 : _d.name) {
|
|
367
|
+
const subscriptionEndpoints = buildOperationEndpoints(__schema.types, 'OBJECT', __schema.subscriptionType.name);
|
|
368
|
+
if (subscriptionEndpoints.length > 0) {
|
|
369
|
+
categories.push({
|
|
370
|
+
name: 'Subscriptions',
|
|
371
|
+
endpoints: subscriptionEndpoints.map(s => ({
|
|
372
|
+
method: 'POST',
|
|
373
|
+
path: s.name,
|
|
374
|
+
summary: s.description,
|
|
375
|
+
description: s.fields,
|
|
376
|
+
parameters: [],
|
|
377
|
+
})),
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return {
|
|
382
|
+
categories,
|
|
383
|
+
servers: [],
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
exports.extractRestApiDefinitionFromGraphQlIntrospectionResult = extractRestApiDefinitionFromGraphQlIntrospectionResult;
|
|
387
|
+
async function fetchGraphQLSchema(url, headers, axios, maxDepth = DEFAULT_INTROSPECTION_DEPTH) {
|
|
388
|
+
try {
|
|
389
|
+
const query = buildIntrospectionQuery(maxDepth);
|
|
390
|
+
const response = await axios.post(url, { query }, {
|
|
391
|
+
timeout: 10000,
|
|
392
|
+
headers: {
|
|
393
|
+
'Content-Type': 'application/json',
|
|
394
|
+
...headers,
|
|
395
|
+
},
|
|
396
|
+
});
|
|
397
|
+
if (response.data.errors) {
|
|
398
|
+
throw new Error(`GraphQL introspection error: ${JSON.stringify(response.data.errors)}`);
|
|
399
|
+
}
|
|
400
|
+
if (!response.data.data) {
|
|
401
|
+
throw new Error('Invalid introspection response: no data field');
|
|
402
|
+
}
|
|
403
|
+
return response.data.data;
|
|
404
|
+
}
|
|
405
|
+
catch (err) {
|
|
406
|
+
throw new Error(`DBGM-00312 Could not fetch GraphQL schema: ${err.message}`);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
exports.fetchGraphQLSchema = fetchGraphQLSchema;
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './openApiDriver';
|
|
2
|
+
export * from './oDataDriver';
|
|
3
|
+
export * from './graphQlDriver';
|
|
4
|
+
export * from './openApiAdapter';
|
|
5
|
+
export * from './oDataAdapter';
|
|
6
|
+
export * from './oDataMetadataParser';
|
|
7
|
+
export * from './restApiExecutor';
|
|
8
|
+
export * from './arrayify';
|
|
9
|
+
export * from './graphqlIntrospection';
|
|
10
|
+
export * from './graphqlExplorer';
|
|
11
|
+
export * from './graphQlQueryParser';
|
|
12
|
+
export * from './graphQlVariables';
|
|
13
|
+
export * from './restAuthTools';
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./openApiDriver"), exports);
|
|
18
|
+
__exportStar(require("./oDataDriver"), exports);
|
|
19
|
+
__exportStar(require("./graphQlDriver"), exports);
|
|
20
|
+
__exportStar(require("./openApiAdapter"), exports);
|
|
21
|
+
__exportStar(require("./oDataAdapter"), exports);
|
|
22
|
+
__exportStar(require("./oDataMetadataParser"), exports);
|
|
23
|
+
__exportStar(require("./restApiExecutor"), exports);
|
|
24
|
+
__exportStar(require("./arrayify"), exports);
|
|
25
|
+
__exportStar(require("./graphqlIntrospection"), exports);
|
|
26
|
+
__exportStar(require("./graphqlExplorer"), exports);
|
|
27
|
+
__exportStar(require("./graphQlQueryParser"), exports);
|
|
28
|
+
__exportStar(require("./graphQlVariables"), exports);
|
|
29
|
+
__exportStar(require("./restAuthTools"), exports);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { RestApiDefinition } from './restApiDef';
|
|
2
|
+
export type ODataServiceResource = {
|
|
3
|
+
name?: string;
|
|
4
|
+
kind?: string;
|
|
5
|
+
url?: string;
|
|
6
|
+
};
|
|
7
|
+
export type ODataServiceDocument = {
|
|
8
|
+
'@odata.context'?: string;
|
|
9
|
+
value?: ODataServiceResource[];
|
|
10
|
+
};
|
|
11
|
+
export interface ODataMetadataNavigationProperty {
|
|
12
|
+
name: string;
|
|
13
|
+
type?: string;
|
|
14
|
+
containsTarget: boolean;
|
|
15
|
+
nullable: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface ODataMetadataEntityType {
|
|
18
|
+
typeName: string;
|
|
19
|
+
fullTypeName: string;
|
|
20
|
+
keyProperties: string[];
|
|
21
|
+
stringProperties: string[];
|
|
22
|
+
navigationProperties: ODataMetadataNavigationProperty[];
|
|
23
|
+
}
|
|
24
|
+
export interface ODataMetadataEntitySet {
|
|
25
|
+
name: string;
|
|
26
|
+
entityType: string;
|
|
27
|
+
navigationBindings: Record<string, string>;
|
|
28
|
+
}
|
|
29
|
+
export interface ODataMetadataDocument {
|
|
30
|
+
entityTypes: Record<string, ODataMetadataEntityType>;
|
|
31
|
+
entitySets: Record<string, ODataMetadataEntitySet>;
|
|
32
|
+
}
|
|
33
|
+
export declare function analyseODataDefinition(doc: ODataServiceDocument, endpointUrl: string, metadataDocumentXml?: string | null): RestApiDefinition;
|