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
package/README.md
ADDED
package/lib/arrayify.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.arrayifyToFlatObjects = void 0;
|
|
4
|
+
function isPlainObject(value) {
|
|
5
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
function flattenValue(value) {
|
|
8
|
+
if (Array.isArray(value)) {
|
|
9
|
+
const primitiveArray = value.every(item => item == null || typeof item !== 'object');
|
|
10
|
+
if (primitiveArray) {
|
|
11
|
+
return value.join(', ');
|
|
12
|
+
}
|
|
13
|
+
return JSON.stringify(value);
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
function flattenObject(obj, prefix = '', out = {}, visited = new WeakSet()) {
|
|
18
|
+
if (visited.has(obj))
|
|
19
|
+
return out;
|
|
20
|
+
visited.add(obj);
|
|
21
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
22
|
+
const nextKey = prefix ? `${prefix}.${key}` : key;
|
|
23
|
+
if (isPlainObject(value)) {
|
|
24
|
+
flattenObject(value, nextKey, out, visited);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
out[nextKey] = flattenValue(value);
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
function unwrapArrayItem(item) {
|
|
32
|
+
if (isPlainObject(item) && isPlainObject(item.node)) {
|
|
33
|
+
return item.node;
|
|
34
|
+
}
|
|
35
|
+
return item;
|
|
36
|
+
}
|
|
37
|
+
function collectArrayCandidates(value, set, visited = new WeakSet(), depth = 0) {
|
|
38
|
+
if (depth > 10)
|
|
39
|
+
return;
|
|
40
|
+
if (Array.isArray(value)) {
|
|
41
|
+
set.add(value);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (!isPlainObject(value))
|
|
45
|
+
return;
|
|
46
|
+
if (visited.has(value))
|
|
47
|
+
return;
|
|
48
|
+
visited.add(value);
|
|
49
|
+
if (Array.isArray(value.edges))
|
|
50
|
+
set.add(value.edges);
|
|
51
|
+
if (Array.isArray(value.nodes))
|
|
52
|
+
set.add(value.nodes);
|
|
53
|
+
if (Array.isArray(value.items))
|
|
54
|
+
set.add(value.items);
|
|
55
|
+
for (const nested of Object.values(value)) {
|
|
56
|
+
collectArrayCandidates(nested, set, visited, depth + 1);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function findUniqueArrayCandidate(value) {
|
|
60
|
+
var _a;
|
|
61
|
+
if (Array.isArray(value))
|
|
62
|
+
return value;
|
|
63
|
+
const candidates = new Set();
|
|
64
|
+
collectArrayCandidates(value, candidates);
|
|
65
|
+
if (candidates.size !== 1)
|
|
66
|
+
return null;
|
|
67
|
+
return (_a = candidates.values().next().value) !== null && _a !== void 0 ? _a : null;
|
|
68
|
+
}
|
|
69
|
+
function arrayifyToFlatObjects(input) {
|
|
70
|
+
const arrayCandidate = findUniqueArrayCandidate(input);
|
|
71
|
+
if (!arrayCandidate)
|
|
72
|
+
return undefined;
|
|
73
|
+
return arrayCandidate.map(item => {
|
|
74
|
+
const unwrapped = unwrapArrayItem(item);
|
|
75
|
+
if (isPlainObject(unwrapped)) {
|
|
76
|
+
return flattenObject(unwrapped);
|
|
77
|
+
}
|
|
78
|
+
return { value: unwrapped };
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
exports.arrayifyToFlatObjects = arrayifyToFlatObjects;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.graphQlDriver = void 0;
|
|
4
|
+
const graphqlIntrospection_1 = require("./graphqlIntrospection");
|
|
5
|
+
const restDriverBase_1 = require("./restDriverBase");
|
|
6
|
+
const restAuthTools_1 = require("./restAuthTools");
|
|
7
|
+
async function loadGraphQlSchema(dbhan) {
|
|
8
|
+
var _a;
|
|
9
|
+
if (!((_a = dbhan === null || dbhan === void 0 ? void 0 : dbhan.connection) === null || _a === void 0 ? void 0 : _a.apiServerUrl1)) {
|
|
10
|
+
throw new Error('DBGM-00310 GraphQL endpoint URL is not configured');
|
|
11
|
+
}
|
|
12
|
+
const introspectionResult = await (0, graphqlIntrospection_1.fetchGraphQLSchema)(dbhan.connection.apiServerUrl1, (0, restAuthTools_1.buildRestAuthHeaders)(dbhan.connection.restAuth), dbhan.axios);
|
|
13
|
+
if (!introspectionResult || typeof introspectionResult !== 'object') {
|
|
14
|
+
throw new Error('DBGM-00311 GraphQL schema is empty or could not be loaded');
|
|
15
|
+
}
|
|
16
|
+
return introspectionResult;
|
|
17
|
+
}
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
exports.graphQlDriver = {
|
|
20
|
+
...restDriverBase_1.apiDriverBase,
|
|
21
|
+
engine: 'graphql@rest',
|
|
22
|
+
title: 'GraphQL',
|
|
23
|
+
databaseEngineTypes: ['rest', 'graphql'],
|
|
24
|
+
icon: '<svg version="1.1" id="GraphQL_Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 400 400" enable-background="new 0 0 400 400" xml:space="preserve"><g><g><g><rect x="122" y="-0.4" transform="matrix(-0.866 -0.5 0.5 -0.866 163.3196 363.3136)" fill="#E535AB" width="16.6" height="320.3"/></g></g><g><g><rect x="39.8" y="272.2" fill="#E535AB" width="320.3" height="16.6"/></g></g><g><g><rect x="37.9" y="312.2" transform="matrix(-0.866 -0.5 0.5 -0.866 83.0693 663.3409)" fill="#E535AB" width="185" height="16.6"/></g></g><g><g><rect x="177.1" y="71.1" transform="matrix(-0.866 -0.5 0.5 -0.866 463.3409 283.0693)" fill="#E535AB" width="185" height="16.6"/></g></g><g><g><rect x="122.1" y="-13" transform="matrix(-0.5 -0.866 0.866 -0.5 126.7903 232.1221)" fill="#E535AB" width="16.6" height="185"/></g></g><g><g><rect x="109.6" y="151.6" transform="matrix(-0.5 -0.866 0.866 -0.5 266.0828 473.3766)" fill="#E535AB" width="320.3" height="16.6"/></g></g><g><g><rect x="52.5" y="107.5" fill="#E535AB" width="16.6" height="185"/></g></g><g><g><rect x="330.9" y="107.5" fill="#E535AB" width="16.6" height="185"/></g></g><g><g><rect x="262.4" y="240.1" transform="matrix(-0.5 -0.866 0.866 -0.5 126.7953 714.2875)" fill="#E535AB" width="14.5" height="160.9"/></g></g><path fill="#E535AB" d="M369.5,297.9c-9.6,16.7-31,22.4-47.7,12.8c-16.7-9.6-22.4-31-12.8-47.7c9.6-16.7,31-22.4,47.7-12.8 C373.5,259.9,379.2,281.2,369.5,297.9"/><path fill="#E535AB" d="M90.9,137c-9.6,16.7-31,22.4-47.7,12.8c-16.7-9.6-22.4-31-12.8-47.7c9.6-16.7,31-22.4,47.7-12.8 C94.8,99,100.5,120.3,90.9,137"/><path fill="#E535AB" d="M30.5,297.9c-9.6-16.7-3.9-38,12.8-47.7c16.7-9.6,38-3.9,47.7,12.8c9.6,16.7,3.9,38-12.8,47.7 C61.4,320.3,40.1,314.6,30.5,297.9"/><path fill="#E535AB" d="M309.1,137c-9.6-16.7-3.9-38,12.8-47.7c16.7-9.6,38-3.9,47.7,12.8c9.6-16.7,3.9-38-12.8,47.7 C340.1,159.4,318.7,153.7,309.1,137"/><path fill="#E535AB" d="M200,395.8c-19.3,0-34.9-15.6-34.9-34.9c0-19.3,15.6-34.9,34.9-34.9c19.3,0,34.9,15.6,34.9,34.9 C234.9,380.1,219.3,395.8,200,395.8"/><path fill="#E535AB" d="M200,74c-19.3,0-34.9-15.6-34.9-34.9c0-19.3,15.6-34.9,34.9-34.9c19.3,0,34.9,15.6,34.9,34.9 C234.9,58.4,219.3,74,200,74"/></g></svg>',
|
|
25
|
+
showConnectionField: (field, values) => {
|
|
26
|
+
if (restDriverBase_1.apiDriverBase.showAuthConnectionField(field, values))
|
|
27
|
+
return true;
|
|
28
|
+
if (field === 'apiServerUrl1')
|
|
29
|
+
return true;
|
|
30
|
+
return false;
|
|
31
|
+
},
|
|
32
|
+
apiServerUrl1Label: 'GraphQL Endpoint URL',
|
|
33
|
+
beforeConnectionSave: connection => ({
|
|
34
|
+
...connection,
|
|
35
|
+
singleDatabase: true,
|
|
36
|
+
defaultDatabase: '_api_database_',
|
|
37
|
+
}),
|
|
38
|
+
async connect(connection) {
|
|
39
|
+
return {
|
|
40
|
+
connection,
|
|
41
|
+
client: null,
|
|
42
|
+
database: '_api_database_',
|
|
43
|
+
axios: connection.axios,
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
async getVersion(dbhan) {
|
|
47
|
+
var _a;
|
|
48
|
+
const introspectionResult = await loadGraphQlSchema(dbhan);
|
|
49
|
+
const schema = introspectionResult.__schema;
|
|
50
|
+
// const version = 'GraphQL';
|
|
51
|
+
return {
|
|
52
|
+
version: `GraphQL, ${((_a = schema.types) === null || _a === void 0 ? void 0 : _a.length) || 0} types`,
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
};
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseGraphQlSelectionPaths = void 0;
|
|
4
|
+
function parseGraphQlSelectionPaths(text) {
|
|
5
|
+
if (!text)
|
|
6
|
+
return { fieldPaths: [], argumentPaths: [], argumentValues: {} };
|
|
7
|
+
const cleaned = text.replace(/#[^\n]*/g, '');
|
|
8
|
+
const tokens = cleaned.match(/\.\.\.|"(?:[^"\\]|\\.)*"|[A-Za-z_][A-Za-z0-9_]*|\$[A-Za-z_][A-Za-z0-9_]*|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|[@{}()\[\],!:$]/g) || [];
|
|
9
|
+
const startIndex = tokens.indexOf('{');
|
|
10
|
+
if (startIndex === -1)
|
|
11
|
+
return { fieldPaths: [], argumentPaths: [], argumentValues: {} };
|
|
12
|
+
const result = parseSelectionSet(tokens, startIndex, []);
|
|
13
|
+
return {
|
|
14
|
+
fieldPaths: result.fieldPaths.map(parts => parts.join('.')),
|
|
15
|
+
argumentPaths: result.argumentPaths.map(parts => parts.join('.')),
|
|
16
|
+
argumentValues: result.argumentValues,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
exports.parseGraphQlSelectionPaths = parseGraphQlSelectionPaths;
|
|
20
|
+
function parseArgumentValue(tokens, startIndex) {
|
|
21
|
+
const valueTokens = [];
|
|
22
|
+
let index = startIndex;
|
|
23
|
+
let parenthesesDepth = 0;
|
|
24
|
+
let bracketDepth = 0;
|
|
25
|
+
let braceDepth = 0;
|
|
26
|
+
while (index < tokens.length) {
|
|
27
|
+
const token = tokens[index];
|
|
28
|
+
if (token === '(') {
|
|
29
|
+
parenthesesDepth += 1;
|
|
30
|
+
valueTokens.push(token);
|
|
31
|
+
index += 1;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (token === '[') {
|
|
35
|
+
bracketDepth += 1;
|
|
36
|
+
valueTokens.push(token);
|
|
37
|
+
index += 1;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (token === '{') {
|
|
41
|
+
braceDepth += 1;
|
|
42
|
+
valueTokens.push(token);
|
|
43
|
+
index += 1;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (token === ')') {
|
|
47
|
+
if (parenthesesDepth === 0 && bracketDepth === 0 && braceDepth === 0) {
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
parenthesesDepth -= 1;
|
|
51
|
+
valueTokens.push(token);
|
|
52
|
+
index += 1;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (token === ']') {
|
|
56
|
+
if (bracketDepth === 0)
|
|
57
|
+
break;
|
|
58
|
+
bracketDepth -= 1;
|
|
59
|
+
valueTokens.push(token);
|
|
60
|
+
index += 1;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (token === '}') {
|
|
64
|
+
if (braceDepth === 0)
|
|
65
|
+
break;
|
|
66
|
+
braceDepth -= 1;
|
|
67
|
+
valueTokens.push(token);
|
|
68
|
+
index += 1;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (token === ',' && parenthesesDepth === 0 && bracketDepth === 0 && braceDepth === 0) {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
valueTokens.push(token);
|
|
75
|
+
index += 1;
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
value: valueTokens.join(''),
|
|
79
|
+
endIndex: index,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function parseArgumentsFromField(tokens, startIndex) {
|
|
83
|
+
const args = [];
|
|
84
|
+
let index = startIndex;
|
|
85
|
+
if (tokens[index] !== '(') {
|
|
86
|
+
return { arguments: args, endIndex: index };
|
|
87
|
+
}
|
|
88
|
+
let depth = 1;
|
|
89
|
+
index += 1;
|
|
90
|
+
while (index < tokens.length && depth > 0) {
|
|
91
|
+
if (tokens[index] === '(')
|
|
92
|
+
depth += 1;
|
|
93
|
+
if (tokens[index] === ')')
|
|
94
|
+
depth -= 1;
|
|
95
|
+
// Look for argument names (identifier followed by colon) and their values
|
|
96
|
+
if (depth > 0 && /^[A-Za-z_]/.test(tokens[index]) && tokens[index + 1] === ':') {
|
|
97
|
+
const argumentName = tokens[index];
|
|
98
|
+
const { value, endIndex } = parseArgumentValue(tokens, index + 2);
|
|
99
|
+
args.push({ name: argumentName, value });
|
|
100
|
+
index = endIndex;
|
|
101
|
+
if (tokens[index] === ',') {
|
|
102
|
+
index += 1;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
index += 1;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return { arguments: args, endIndex: index };
|
|
110
|
+
}
|
|
111
|
+
function parseSelectionSet(tokens, startIndex, prefix) {
|
|
112
|
+
const fieldPaths = [];
|
|
113
|
+
const argumentPaths = [];
|
|
114
|
+
const argumentValues = {};
|
|
115
|
+
let index = startIndex + 1;
|
|
116
|
+
while (index < tokens.length) {
|
|
117
|
+
const token = tokens[index];
|
|
118
|
+
if (token === '}') {
|
|
119
|
+
return { fieldPaths, argumentPaths, argumentValues, index: index + 1 };
|
|
120
|
+
}
|
|
121
|
+
if (token === '...') {
|
|
122
|
+
index += 1;
|
|
123
|
+
if (tokens[index] === 'on') {
|
|
124
|
+
index += 2;
|
|
125
|
+
}
|
|
126
|
+
while (index < tokens.length && tokens[index] !== '{' && tokens[index] !== '}') {
|
|
127
|
+
index += 1;
|
|
128
|
+
}
|
|
129
|
+
if (tokens[index] === '{') {
|
|
130
|
+
const frag = parseSelectionSet(tokens, index, prefix);
|
|
131
|
+
fieldPaths.push(...frag.fieldPaths);
|
|
132
|
+
argumentPaths.push(...frag.argumentPaths);
|
|
133
|
+
for (const [fieldPath, values] of Object.entries(frag.argumentValues)) {
|
|
134
|
+
argumentValues[fieldPath] = {
|
|
135
|
+
...(argumentValues[fieldPath] || {}),
|
|
136
|
+
...values,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
index = frag.index;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (/^[A-Za-z_]/.test(token)) {
|
|
145
|
+
let fieldName = token;
|
|
146
|
+
if (tokens[index + 1] === ':' && /^[A-Za-z_]/.test(tokens[index + 2] || '')) {
|
|
147
|
+
fieldName = tokens[index + 2];
|
|
148
|
+
index += 3;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
index += 1;
|
|
152
|
+
}
|
|
153
|
+
// Parse arguments if present
|
|
154
|
+
const { arguments: args, endIndex: argsEndIndex } = parseArgumentsFromField(tokens, index);
|
|
155
|
+
index = argsEndIndex;
|
|
156
|
+
// Add argument paths for this field
|
|
157
|
+
const currentFieldPath = [...prefix, fieldName].join('.');
|
|
158
|
+
for (const arg of args) {
|
|
159
|
+
argumentPaths.push([...prefix, fieldName, arg.name]);
|
|
160
|
+
if (!argumentValues[currentFieldPath]) {
|
|
161
|
+
argumentValues[currentFieldPath] = {};
|
|
162
|
+
}
|
|
163
|
+
argumentValues[currentFieldPath][arg.name] = arg.value;
|
|
164
|
+
}
|
|
165
|
+
while (tokens[index] === '@') {
|
|
166
|
+
index += 2;
|
|
167
|
+
if (tokens[index] === '(') {
|
|
168
|
+
let depth = 1;
|
|
169
|
+
index += 1;
|
|
170
|
+
while (index < tokens.length && depth > 0) {
|
|
171
|
+
if (tokens[index] === '(')
|
|
172
|
+
depth += 1;
|
|
173
|
+
if (tokens[index] === ')')
|
|
174
|
+
depth -= 1;
|
|
175
|
+
index += 1;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (tokens[index] === '{') {
|
|
180
|
+
const nested = parseSelectionSet(tokens, index, [...prefix, fieldName]);
|
|
181
|
+
if (nested.fieldPaths.length > 0) {
|
|
182
|
+
fieldPaths.push(...nested.fieldPaths);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
fieldPaths.push([...prefix, fieldName]);
|
|
186
|
+
}
|
|
187
|
+
argumentPaths.push(...nested.argumentPaths);
|
|
188
|
+
for (const [fieldPath, values] of Object.entries(nested.argumentValues)) {
|
|
189
|
+
argumentValues[fieldPath] = {
|
|
190
|
+
...(argumentValues[fieldPath] || {}),
|
|
191
|
+
...values,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
index = nested.index;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
fieldPaths.push([...prefix, fieldName]);
|
|
198
|
+
}
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
index += 1;
|
|
202
|
+
}
|
|
203
|
+
return { fieldPaths, argumentPaths, argumentValues, index };
|
|
204
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type GraphQlVariableDefinition = {
|
|
2
|
+
name: string;
|
|
3
|
+
type: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function extractGraphQlVariableDefinitions(text: string): GraphQlVariableDefinition[];
|
|
6
|
+
export declare function convertGraphQlVariablesForRequest(queryText: string, rawVariables?: Record<string, string>): Record<string, any>;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertGraphQlVariablesForRequest = exports.extractGraphQlVariableDefinitions = void 0;
|
|
4
|
+
function extractGraphQlVariableDefinitions(text) {
|
|
5
|
+
if (!text)
|
|
6
|
+
return [];
|
|
7
|
+
const cleaned = text.replace(/#[^\n]*/g, '');
|
|
8
|
+
const regex = /\$([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([^=,)\n]+)/g;
|
|
9
|
+
const names = new Set();
|
|
10
|
+
const definitions = [];
|
|
11
|
+
let match = null;
|
|
12
|
+
while ((match = regex.exec(cleaned))) {
|
|
13
|
+
const name = match[1];
|
|
14
|
+
if (names.has(name))
|
|
15
|
+
continue;
|
|
16
|
+
names.add(name);
|
|
17
|
+
definitions.push({
|
|
18
|
+
name,
|
|
19
|
+
type: match[2].trim(),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return definitions;
|
|
23
|
+
}
|
|
24
|
+
exports.extractGraphQlVariableDefinitions = extractGraphQlVariableDefinitions;
|
|
25
|
+
function unwrapNonNull(typeText) {
|
|
26
|
+
let current = (typeText || '').trim();
|
|
27
|
+
while (current.endsWith('!')) {
|
|
28
|
+
current = current.slice(0, -1).trim();
|
|
29
|
+
}
|
|
30
|
+
return current;
|
|
31
|
+
}
|
|
32
|
+
function isListType(typeText) {
|
|
33
|
+
const unwrapped = unwrapNonNull(typeText);
|
|
34
|
+
return unwrapped.startsWith('[') && unwrapped.endsWith(']');
|
|
35
|
+
}
|
|
36
|
+
function getInnerListType(typeText) {
|
|
37
|
+
const unwrapped = unwrapNonNull(typeText);
|
|
38
|
+
if (!(unwrapped.startsWith('[') && unwrapped.endsWith(']')))
|
|
39
|
+
return unwrapped;
|
|
40
|
+
return unwrapped.slice(1, -1).trim();
|
|
41
|
+
}
|
|
42
|
+
function getBaseType(typeText) {
|
|
43
|
+
let current = unwrapNonNull(typeText);
|
|
44
|
+
while (current.startsWith('[') && current.endsWith(']')) {
|
|
45
|
+
current = current.slice(1, -1).trim();
|
|
46
|
+
current = unwrapNonNull(current);
|
|
47
|
+
}
|
|
48
|
+
return current;
|
|
49
|
+
}
|
|
50
|
+
function parseJsonIfPossible(raw) {
|
|
51
|
+
const trimmed = (raw || '').trim();
|
|
52
|
+
if (!trimmed)
|
|
53
|
+
return null;
|
|
54
|
+
try {
|
|
55
|
+
return JSON.parse(trimmed);
|
|
56
|
+
}
|
|
57
|
+
catch (_a) {
|
|
58
|
+
return raw;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function toInt(raw) {
|
|
62
|
+
const trimmed = (raw || '').trim();
|
|
63
|
+
if (!trimmed)
|
|
64
|
+
return null;
|
|
65
|
+
const num = Number(trimmed);
|
|
66
|
+
if (!Number.isFinite(num))
|
|
67
|
+
return null;
|
|
68
|
+
return Math.trunc(num);
|
|
69
|
+
}
|
|
70
|
+
function toFloat(raw) {
|
|
71
|
+
const trimmed = (raw || '').trim();
|
|
72
|
+
if (!trimmed)
|
|
73
|
+
return null;
|
|
74
|
+
const num = Number(trimmed);
|
|
75
|
+
if (!Number.isFinite(num))
|
|
76
|
+
return null;
|
|
77
|
+
return num;
|
|
78
|
+
}
|
|
79
|
+
function toBoolean(raw) {
|
|
80
|
+
const lowered = (raw || '').trim().toLowerCase();
|
|
81
|
+
if (!lowered)
|
|
82
|
+
return null;
|
|
83
|
+
if (['true', '1', 'yes', 'y', 'on'].includes(lowered))
|
|
84
|
+
return true;
|
|
85
|
+
if (['false', '0', 'no', 'n', 'off'].includes(lowered))
|
|
86
|
+
return false;
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
function convertByGraphQlTypeValue(raw, graphQlType) {
|
|
90
|
+
if (raw == null)
|
|
91
|
+
return null;
|
|
92
|
+
if (isListType(graphQlType)) {
|
|
93
|
+
const innerType = getInnerListType(graphQlType);
|
|
94
|
+
const parsed = typeof raw === 'string' ? parseJsonIfPossible(raw) : raw;
|
|
95
|
+
const arrayValue = Array.isArray(parsed) ? parsed : [parsed];
|
|
96
|
+
return arrayValue.map(item => convertByGraphQlTypeValue(item, innerType));
|
|
97
|
+
}
|
|
98
|
+
const baseType = getBaseType(graphQlType);
|
|
99
|
+
const stringValue = typeof raw === 'string' ? raw : JSON.stringify(raw);
|
|
100
|
+
if (baseType === 'Int')
|
|
101
|
+
return toInt(stringValue);
|
|
102
|
+
if (baseType === 'Float')
|
|
103
|
+
return toFloat(stringValue);
|
|
104
|
+
if (baseType === 'Boolean')
|
|
105
|
+
return toBoolean(stringValue);
|
|
106
|
+
if (baseType === 'String' || baseType === 'ID')
|
|
107
|
+
return String(raw);
|
|
108
|
+
if (typeof raw === 'string') {
|
|
109
|
+
return parseJsonIfPossible(raw);
|
|
110
|
+
}
|
|
111
|
+
return raw;
|
|
112
|
+
}
|
|
113
|
+
function convertGraphQlVariablesForRequest(queryText, rawVariables = {}) {
|
|
114
|
+
var _a;
|
|
115
|
+
const definitions = extractGraphQlVariableDefinitions(queryText || '');
|
|
116
|
+
const next = {};
|
|
117
|
+
for (const definition of definitions) {
|
|
118
|
+
const raw = (_a = rawVariables === null || rawVariables === void 0 ? void 0 : rawVariables[definition.name]) !== null && _a !== void 0 ? _a : '';
|
|
119
|
+
next[definition.name] = convertByGraphQlTypeValue(raw, definition.type);
|
|
120
|
+
}
|
|
121
|
+
return next;
|
|
122
|
+
}
|
|
123
|
+
exports.convertGraphQlVariablesForRequest = convertGraphQlVariablesForRequest;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { GraphQLIntrospectionResult } from './graphqlIntrospection';
|
|
2
|
+
export type GraphQLExplorerOperationType = 'query' | 'mutation' | 'subscription';
|
|
3
|
+
export interface GraphQLExplorerFieldNode {
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
typeName: string;
|
|
7
|
+
typeDisplay: string;
|
|
8
|
+
isLeaf: boolean;
|
|
9
|
+
isArgument?: boolean;
|
|
10
|
+
arguments?: GraphQLExplorerFieldNode[];
|
|
11
|
+
children?: GraphQLExplorerFieldNode[];
|
|
12
|
+
}
|
|
13
|
+
export interface GraphQLExplorerOperation {
|
|
14
|
+
operationType: GraphQLExplorerOperationType;
|
|
15
|
+
rootTypeName: string;
|
|
16
|
+
fields: GraphQLExplorerFieldNode[];
|
|
17
|
+
}
|
|
18
|
+
interface GraphQLExplorerOptions {
|
|
19
|
+
maxDepth?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function buildGraphQlExplorerOperations(introspectionResult: GraphQLIntrospectionResult, options?: GraphQLExplorerOptions): GraphQLExplorerOperation[];
|
|
22
|
+
export declare function buildGraphQlQueryText(operationType: GraphQLExplorerOperationType, selectionPaths: string[], options?: {
|
|
23
|
+
operationName?: string;
|
|
24
|
+
indent?: string;
|
|
25
|
+
}): string;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildGraphQlQueryText = exports.buildGraphQlExplorerOperations = void 0;
|
|
4
|
+
const DEFAULT_MAX_DEPTH = 2;
|
|
5
|
+
function getTypeDisplay(typeRef) {
|
|
6
|
+
if (!typeRef)
|
|
7
|
+
return 'Unknown';
|
|
8
|
+
if (typeRef.kind === 'NON_NULL')
|
|
9
|
+
return `${getTypeDisplay(typeRef.ofType)}!`;
|
|
10
|
+
if (typeRef.kind === 'LIST')
|
|
11
|
+
return `[${getTypeDisplay(typeRef.ofType)}]`;
|
|
12
|
+
return typeRef.name || 'Unknown';
|
|
13
|
+
}
|
|
14
|
+
function unwrapNamedType(typeRef) {
|
|
15
|
+
if (!typeRef)
|
|
16
|
+
return null;
|
|
17
|
+
if (typeRef.kind === 'NON_NULL' || typeRef.kind === 'LIST')
|
|
18
|
+
return unwrapNamedType(typeRef.ofType);
|
|
19
|
+
return typeRef;
|
|
20
|
+
}
|
|
21
|
+
function buildTypeMap(types) {
|
|
22
|
+
return new Map(types.map(type => [type.name, type]));
|
|
23
|
+
}
|
|
24
|
+
function isCompositeType(type) {
|
|
25
|
+
return (type === null || type === void 0 ? void 0 : type.kind) === 'OBJECT' || (type === null || type === void 0 ? void 0 : type.kind) === 'INTERFACE';
|
|
26
|
+
}
|
|
27
|
+
function buildFieldNode(field, typeMap, depth, maxDepth, visitedTypes) {
|
|
28
|
+
const namedType = unwrapNamedType(field.type);
|
|
29
|
+
const typeDef = (namedType === null || namedType === void 0 ? void 0 : namedType.name) ? typeMap.get(namedType.name) : undefined;
|
|
30
|
+
const composite = isCompositeType(typeDef);
|
|
31
|
+
const nextVisited = new Set(visitedTypes);
|
|
32
|
+
if (typeDef === null || typeDef === void 0 ? void 0 : typeDef.name) {
|
|
33
|
+
nextVisited.add(typeDef.name);
|
|
34
|
+
}
|
|
35
|
+
let children;
|
|
36
|
+
if (composite && depth < maxDepth && (typeDef === null || typeDef === void 0 ? void 0 : typeDef.fields) && !visitedTypes.has(typeDef.name)) {
|
|
37
|
+
children = typeDef.fields.map(childField => buildFieldNode(childField, typeMap, depth + 1, maxDepth, nextVisited));
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
name: field.name,
|
|
41
|
+
description: field.description,
|
|
42
|
+
typeName: (namedType === null || namedType === void 0 ? void 0 : namedType.name) || 'Unknown',
|
|
43
|
+
typeDisplay: getTypeDisplay(field.type),
|
|
44
|
+
isLeaf: !composite || !children || children.length === 0,
|
|
45
|
+
children,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function buildOperationFields(rootTypeName, types, maxDepth) {
|
|
49
|
+
const typeMap = buildTypeMap(types);
|
|
50
|
+
const rootType = typeMap.get(rootTypeName);
|
|
51
|
+
if (!(rootType === null || rootType === void 0 ? void 0 : rootType.fields))
|
|
52
|
+
return [];
|
|
53
|
+
return rootType.fields.map(field => buildFieldNode(field, typeMap, 1, maxDepth, new Set([rootTypeName])));
|
|
54
|
+
}
|
|
55
|
+
function buildGraphQlExplorerOperations(introspectionResult, options = {}) {
|
|
56
|
+
var _a, _b, _c, _d;
|
|
57
|
+
const { __schema } = introspectionResult || {};
|
|
58
|
+
if (!(__schema === null || __schema === void 0 ? void 0 : __schema.types))
|
|
59
|
+
return [];
|
|
60
|
+
const maxDepth = (_a = options.maxDepth) !== null && _a !== void 0 ? _a : DEFAULT_MAX_DEPTH;
|
|
61
|
+
const operations = [];
|
|
62
|
+
if ((_b = __schema.queryType) === null || _b === void 0 ? void 0 : _b.name) {
|
|
63
|
+
operations.push({
|
|
64
|
+
operationType: 'query',
|
|
65
|
+
rootTypeName: __schema.queryType.name,
|
|
66
|
+
fields: buildOperationFields(__schema.queryType.name, __schema.types, maxDepth),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if ((_c = __schema.mutationType) === null || _c === void 0 ? void 0 : _c.name) {
|
|
70
|
+
operations.push({
|
|
71
|
+
operationType: 'mutation',
|
|
72
|
+
rootTypeName: __schema.mutationType.name,
|
|
73
|
+
fields: buildOperationFields(__schema.mutationType.name, __schema.types, maxDepth),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if ((_d = __schema.subscriptionType) === null || _d === void 0 ? void 0 : _d.name) {
|
|
77
|
+
operations.push({
|
|
78
|
+
operationType: 'subscription',
|
|
79
|
+
rootTypeName: __schema.subscriptionType.name,
|
|
80
|
+
fields: buildOperationFields(__schema.subscriptionType.name, __schema.types, maxDepth),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return operations;
|
|
84
|
+
}
|
|
85
|
+
exports.buildGraphQlExplorerOperations = buildGraphQlExplorerOperations;
|
|
86
|
+
function buildGraphQlQueryText(operationType, selectionPaths, options = {}) {
|
|
87
|
+
var _a, _b;
|
|
88
|
+
const indent = (_a = options.indent) !== null && _a !== void 0 ? _a : ' ';
|
|
89
|
+
const opName = (_b = options.operationName) === null || _b === void 0 ? void 0 : _b.trim();
|
|
90
|
+
const tree = new Map();
|
|
91
|
+
for (const path of selectionPaths) {
|
|
92
|
+
if (!path)
|
|
93
|
+
continue;
|
|
94
|
+
const parts = path.split('.').filter(Boolean);
|
|
95
|
+
let node = tree;
|
|
96
|
+
for (const part of parts) {
|
|
97
|
+
if (!node.has(part)) {
|
|
98
|
+
node.set(part, new Map());
|
|
99
|
+
}
|
|
100
|
+
node = node.get(part);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const renderTree = (node, level) => {
|
|
104
|
+
const lines = [];
|
|
105
|
+
for (const [name, children] of node.entries()) {
|
|
106
|
+
if (children.size === 0) {
|
|
107
|
+
lines.push(`${indent.repeat(level)}${name}`);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
lines.push(`${indent.repeat(level)}${name} {`);
|
|
111
|
+
lines.push(...renderTree(children, level + 1));
|
|
112
|
+
lines.push(`${indent.repeat(level)}}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return lines;
|
|
116
|
+
};
|
|
117
|
+
const header = opName ? `${operationType} ${opName}` : operationType;
|
|
118
|
+
const lines = [`${header} {`];
|
|
119
|
+
if (tree.size > 0) {
|
|
120
|
+
lines.push(...renderTree(tree, 1));
|
|
121
|
+
}
|
|
122
|
+
lines.push('}');
|
|
123
|
+
return lines.join('\n');
|
|
124
|
+
}
|
|
125
|
+
exports.buildGraphQlQueryText = buildGraphQlQueryText;
|