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.
@@ -0,0 +1,254 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.analyseOpenApiDefinition = void 0;
4
+ /**
5
+ * Converts an OpenAPI v3.1 document into a simplified REST API definition
6
+ * Organizes endpoints by tags into categories
7
+ */
8
+ function analyseOpenApiDefinition(doc) {
9
+ const categories = new Map();
10
+ // Process all paths and methods
11
+ if (doc.paths) {
12
+ for (const [path, pathItem] of Object.entries(doc.paths)) {
13
+ if (!pathItem)
14
+ continue;
15
+ // Process each HTTP method in the path
16
+ const methods = ['get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'trace'];
17
+ for (const method of methods) {
18
+ const operation = pathItem[method];
19
+ if (!operation)
20
+ continue;
21
+ const endpoint = {
22
+ method: method.toUpperCase(),
23
+ path,
24
+ summary: operation.summary,
25
+ description: operation.description,
26
+ parameters: extractParameters(operation, pathItem),
27
+ };
28
+ // Use tags to organize into categories
29
+ const tags = operation.tags || ['Other'];
30
+ for (const tag of tags) {
31
+ if (!categories.has(tag)) {
32
+ categories.set(tag, []);
33
+ }
34
+ categories.get(tag).push(endpoint);
35
+ }
36
+ }
37
+ }
38
+ }
39
+ // Convert Map to RestApiCategory array
40
+ const categoryArray = Array.from(categories.entries()).map(([name, endpoints]) => ({
41
+ name,
42
+ endpoints,
43
+ }));
44
+ const servers = (doc.servers || []).map(server => ({
45
+ url: server.url,
46
+ description: server.description,
47
+ }));
48
+ return {
49
+ categories: categoryArray,
50
+ servers,
51
+ };
52
+ }
53
+ exports.analyseOpenApiDefinition = analyseOpenApiDefinition;
54
+ /**
55
+ * Extract parameters from operation and path item
56
+ */
57
+ function extractParameters(operation, pathItem) {
58
+ const parameters = [];
59
+ // Path item level parameters (apply to all methods)
60
+ if (pathItem.parameters) {
61
+ for (const param of pathItem.parameters) {
62
+ if (!('$ref' in param)) {
63
+ parameters.push(convertParameter(param));
64
+ }
65
+ }
66
+ }
67
+ // Operation level parameters
68
+ if (operation.parameters) {
69
+ for (const param of operation.parameters) {
70
+ if (!('$ref' in param)) {
71
+ parameters.push(convertParameter(param));
72
+ }
73
+ }
74
+ }
75
+ const bodyParameter = convertRequestBodyParameter(operation.requestBody);
76
+ if (bodyParameter) {
77
+ parameters.push(bodyParameter);
78
+ }
79
+ return parameters;
80
+ }
81
+ function isSchemaObject(schema) {
82
+ return !!schema && !('$ref' in schema);
83
+ }
84
+ function isExampleObject(example) {
85
+ return !!example && !('$ref' in example);
86
+ }
87
+ function cloneValue(value) {
88
+ if (value == null)
89
+ return value;
90
+ if (typeof value !== 'object')
91
+ return value;
92
+ try {
93
+ return JSON.parse(JSON.stringify(value));
94
+ }
95
+ catch (_a) {
96
+ return value;
97
+ }
98
+ }
99
+ function extractMediaTypeExample(mediaType) {
100
+ if (!mediaType)
101
+ return undefined;
102
+ if (mediaType.example !== undefined)
103
+ return cloneValue(mediaType.example);
104
+ if (mediaType.examples) {
105
+ const firstExample = Object.values(mediaType.examples)[0];
106
+ if (isExampleObject(firstExample) && firstExample.value !== undefined) {
107
+ return cloneValue(firstExample.value);
108
+ }
109
+ }
110
+ return undefined;
111
+ }
112
+ function buildSchemaExample(schema, recursionDepth = 0) {
113
+ var _a, _b, _c, _d, _e;
114
+ if (!schema || recursionDepth > 6)
115
+ return undefined;
116
+ if (schema.example !== undefined)
117
+ return cloneValue(schema.example);
118
+ if (schema.default !== undefined)
119
+ return cloneValue(schema.default);
120
+ if ((_a = schema.oneOf) === null || _a === void 0 ? void 0 : _a.length) {
121
+ const oneOfSchema = schema.oneOf[0];
122
+ return isSchemaObject(oneOfSchema) ? buildSchemaExample(oneOfSchema, recursionDepth + 1) : undefined;
123
+ }
124
+ if ((_b = schema.anyOf) === null || _b === void 0 ? void 0 : _b.length) {
125
+ const anyOfSchema = schema.anyOf[0];
126
+ return isSchemaObject(anyOfSchema) ? buildSchemaExample(anyOfSchema, recursionDepth + 1) : undefined;
127
+ }
128
+ if ((_c = schema.allOf) === null || _c === void 0 ? void 0 : _c.length) {
129
+ const mergedObject = {};
130
+ let hasValue = false;
131
+ for (const item of schema.allOf) {
132
+ if (!isSchemaObject(item))
133
+ continue;
134
+ const itemExample = buildSchemaExample(item, recursionDepth + 1);
135
+ if (itemExample && typeof itemExample === 'object' && !Array.isArray(itemExample)) {
136
+ Object.assign(mergedObject, itemExample);
137
+ hasValue = true;
138
+ }
139
+ }
140
+ return hasValue ? mergedObject : undefined;
141
+ }
142
+ if ((_d = schema.enum) === null || _d === void 0 ? void 0 : _d.length)
143
+ return cloneValue(schema.enum[0]);
144
+ if (schema.type === 'object' || schema.properties || schema.additionalProperties) {
145
+ const result = {};
146
+ let hasAnyProperty = false;
147
+ for (const [propertyName, propertySchema] of Object.entries(schema.properties || {})) {
148
+ if (!isSchemaObject(propertySchema))
149
+ continue;
150
+ const propertyValue = buildSchemaExample(propertySchema, recursionDepth + 1);
151
+ if (propertyValue !== undefined) {
152
+ result[propertyName] = propertyValue;
153
+ hasAnyProperty = true;
154
+ }
155
+ }
156
+ if (schema.additionalProperties) {
157
+ if (schema.additionalProperties === true) {
158
+ result.additionalProp1 = 'string';
159
+ hasAnyProperty = true;
160
+ }
161
+ else if (isSchemaObject(schema.additionalProperties)) {
162
+ result.additionalProp1 = (_e = buildSchemaExample(schema.additionalProperties, recursionDepth + 1)) !== null && _e !== void 0 ? _e : 'string';
163
+ hasAnyProperty = true;
164
+ }
165
+ }
166
+ return hasAnyProperty ? result : {};
167
+ }
168
+ if (schema.type === 'array') {
169
+ if (isSchemaObject(schema.items)) {
170
+ const itemValue = buildSchemaExample(schema.items, recursionDepth + 1);
171
+ return itemValue !== undefined ? [itemValue] : [];
172
+ }
173
+ return [];
174
+ }
175
+ if (schema.type === 'number' || schema.type === 'integer')
176
+ return 0;
177
+ if (schema.type === 'boolean')
178
+ return true;
179
+ if (schema.type === 'null')
180
+ return null;
181
+ return 'string';
182
+ }
183
+ function getSchemaType(schema) {
184
+ if (!schema)
185
+ return undefined;
186
+ if (schema.type === 'array') {
187
+ if (isSchemaObject(schema.items)) {
188
+ return `array<${schema.items.type || 'any'}>`;
189
+ }
190
+ return 'array';
191
+ }
192
+ if (Array.isArray(schema.type))
193
+ return schema.type.join(' | ');
194
+ if (schema.type)
195
+ return schema.type;
196
+ if (schema.properties)
197
+ return 'object';
198
+ return undefined;
199
+ }
200
+ function isStringListSchema(schema) {
201
+ return (schema === null || schema === void 0 ? void 0 : schema.type) === 'array' && isSchemaObject(schema.items) && schema.items.type === 'string';
202
+ }
203
+ function convertRequestBodyParameter(requestBody) {
204
+ if (!requestBody || '$ref' in requestBody || !requestBody.content)
205
+ return null;
206
+ const preferredContentTypes = [
207
+ 'application/json',
208
+ 'application/x-www-form-urlencoded',
209
+ 'multipart/form-data',
210
+ 'text/plain',
211
+ ];
212
+ const availableContentTypes = Object.keys(requestBody.content);
213
+ if (availableContentTypes.length === 0)
214
+ return null;
215
+ const selectedContentType = preferredContentTypes.find(contentType => { var _a; return (_a = requestBody.content) === null || _a === void 0 ? void 0 : _a[contentType]; }) || availableContentTypes[0];
216
+ const mediaType = requestBody.content[selectedContentType];
217
+ if (!mediaType || !isSchemaObject(mediaType.schema)) {
218
+ return {
219
+ name: 'body',
220
+ in: 'body',
221
+ contentType: selectedContentType,
222
+ description: requestBody.description,
223
+ required: requestBody.required,
224
+ };
225
+ }
226
+ const schema = mediaType.schema;
227
+ const mediaTypeExample = extractMediaTypeExample(mediaType);
228
+ const generatedExample = buildSchemaExample(schema);
229
+ return {
230
+ name: 'body',
231
+ in: 'body',
232
+ dataType: getSchemaType(schema),
233
+ contentType: selectedContentType,
234
+ isStringList: isStringListSchema(schema),
235
+ description: requestBody.description,
236
+ required: requestBody.required,
237
+ defaultValue: mediaTypeExample !== null && mediaTypeExample !== void 0 ? mediaTypeExample : generatedExample,
238
+ };
239
+ }
240
+ /**
241
+ * Convert OpenAPI parameter to REST API parameter
242
+ */
243
+ function convertParameter(param) {
244
+ const schema = isSchemaObject(param.schema) ? param.schema : undefined;
245
+ return {
246
+ name: param.name,
247
+ in: param.in,
248
+ dataType: getSchemaType(schema),
249
+ isStringList: isStringListSchema(schema),
250
+ description: param.description,
251
+ required: param.required,
252
+ defaultValue: schema === null || schema === void 0 ? void 0 : schema.default,
253
+ };
254
+ }
@@ -0,0 +1,2 @@
1
+ import type { EngineDriver } from 'dbgate-types';
2
+ export declare const openApiDriver: EngineDriver;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.openApiDriver = void 0;
7
+ const js_yaml_1 = __importDefault(require("js-yaml"));
8
+ const restDriverBase_1 = require("./restDriverBase");
9
+ async function loadOpenApiDefinition(dbhan) {
10
+ var _a;
11
+ if (!((_a = dbhan === null || dbhan === void 0 ? void 0 : dbhan.connection) === null || _a === void 0 ? void 0 : _a.apiServerUrl1)) {
12
+ throw new Error('DBGM-00313 REST connection URL is not configured');
13
+ }
14
+ const response = await dbhan.axios.get(dbhan.connection.apiServerUrl1);
15
+ const content = response === null || response === void 0 ? void 0 : response.data;
16
+ let openApiDefinition = content;
17
+ if (typeof content === 'string') {
18
+ try {
19
+ openApiDefinition = JSON.parse(content);
20
+ }
21
+ catch (_b) {
22
+ openApiDefinition = js_yaml_1.default.load(content);
23
+ }
24
+ }
25
+ if (!openApiDefinition || typeof openApiDefinition !== 'object') {
26
+ throw new Error('DBGM-00314 API documentation is empty or could not be parsed');
27
+ }
28
+ return openApiDefinition;
29
+ }
30
+ // @ts-ignore
31
+ exports.openApiDriver = {
32
+ ...restDriverBase_1.apiDriverBase,
33
+ engine: 'openapi@rest',
34
+ title: 'OpenAPI - REST',
35
+ databaseEngineTypes: ['rest', 'openapi'],
36
+ icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><path fill="#85ea2d" d="M63.999 124.945c-33.607 0-60.95-27.34-60.95-60.949C3.05 30.388 30.392 3.048 64 3.048s60.95 27.342 60.95 60.95c0 33.607-27.343 60.946-60.95 60.946z"/><path fill="#173647" d="M40.3 43.311c-.198 2.19.072 4.454-.073 6.668-.173 2.217-.444 4.407-.888 6.596-.615 3.126-2.56 5.489-5.24 7.458 5.218 3.396 5.807 8.662 6.152 14.003.172 2.88.098 5.785.394 8.638.221 2.215 1.082 2.782 3.372 2.854.935.025 1.894 0 2.978 0v6.842c-6.768 1.156-12.354-.762-13.734-6.496a39.329 39.329 0 0 1-.836-6.4c-.148-2.287.097-4.577-.074-6.864-.492-6.277-1.305-8.393-7.308-8.689v-7.8c.441-.1.86-.174 1.302-.223 3.298-.172 4.701-1.182 5.414-4.43a37.512 37.512 0 0 0 .616-5.536c.247-3.569.148-7.21.763-10.754.86-5.094 4.01-7.556 9.254-7.852 1.476-.074 2.978 0 4.676 0v6.99c-.714.05-1.33.147-1.969.147-4.258-.148-4.48 1.304-4.8 4.848zm8.195 16.193h-.099c-2.462-.123-4.578 1.796-4.702 4.258-.122 2.485 1.797 4.603 4.259 4.724h.295c2.436.148 4.527-1.724 4.676-4.16v-.245c.05-2.486-1.944-4.527-4.43-4.577zm15.43 0c-2.386-.074-4.38 1.796-4.454 4.159 0 .149 0 .271.024.418 0 2.684 1.821 4.406 4.578 4.406 2.707 0 4.406-1.772 4.406-4.553-.025-2.682-1.823-4.455-4.554-4.43Zm15.801 0a4.596 4.596 0 0 0-4.676 4.454 4.515 4.515 0 0 0 4.528 4.528h.05c2.264.394 4.553-1.796 4.701-4.429.122-2.437-2.092-4.553-4.604-4.553Zm21.682.369c-2.855-.123-4.284-1.083-4.996-3.79a27.444 27.444 0 0 1-.811-5.292c-.198-3.298-.174-6.62-.395-9.918-.516-7.826-6.177-10.557-14.397-9.205v6.792c1.304 0 2.313 0 3.322.025 1.748.024 3.077.69 3.249 2.634.172 1.772.172 3.568.344 5.365.346 3.57.542 7.187 1.157 10.706.542 2.904 2.536 5.07 5.02 6.841-4.355 2.929-5.636 7.113-5.857 11.814-.122 3.223-.196 6.472-.368 9.721-.148 2.953-1.181 3.913-4.16 3.987-.835.024-1.648.098-2.583.148v6.964c1.748 0 3.347.1 4.946 0 4.971-.295 7.974-2.706 8.96-7.531.417-2.658.662-5.34.737-8.023.171-2.46.148-4.946.394-7.382.369-3.815 2.116-5.389 5.93-5.636a5.161 5.161 0 0 0 1.06-.245v-7.801c-.64-.074-1.084-.148-1.552-.173zM64 6.1c31.977 0 57.9 25.92 57.9 57.898 0 31.977-25.923 57.899-57.9 57.899-31.976 0-57.898-25.922-57.898-57.9C6.102 32.023 32.024 6.101 64 6.101m0-6.1C28.71 0 0 28.71 0 64c0 35.288 28.71 63.998 64 63.998 35.289 0 64-28.71 64-64S99.289.002 64 .002Z"/></svg>',
37
+ apiServerUrl1Label: 'API Definition URL',
38
+ apiServerUrl2Label: 'API Server URL',
39
+ apiServerUrl2Placeholder: '(optional - if not set, the first server URL from the API definition will be used)',
40
+ loadApiServerUrl2Options: true,
41
+ showConnectionField: (field, values) => {
42
+ if (restDriverBase_1.apiDriverBase.showAuthConnectionField(field, values))
43
+ return true;
44
+ if (field === 'apiServerUrl1')
45
+ return true;
46
+ if (field === 'apiServerUrl2')
47
+ return true;
48
+ return false;
49
+ },
50
+ beforeConnectionSave: connection => ({
51
+ ...connection,
52
+ singleDatabase: true,
53
+ defaultDatabase: '_api_database_',
54
+ }),
55
+ async connect(connection) {
56
+ return {
57
+ connection,
58
+ client: null,
59
+ database: '_api_database_',
60
+ axios: connection.axios
61
+ };
62
+ },
63
+ async listDatabases(dbhan) {
64
+ const openApiDefinition = await loadOpenApiDefinition(dbhan);
65
+ const servers = Array.isArray(openApiDefinition.servers) ? openApiDefinition.servers : [];
66
+ return servers
67
+ .map(server => { var _a; return String((_a = server === null || server === void 0 ? void 0 : server.url) !== null && _a !== void 0 ? _a : '').trim(); })
68
+ .filter(Boolean)
69
+ .map(url => ({
70
+ name: url,
71
+ }));
72
+ },
73
+ async getVersion(dbhan) {
74
+ var _a, _b, _c, _d;
75
+ const openApiDefinition = await loadOpenApiDefinition(dbhan);
76
+ const specVersion = String((_b = (_a = openApiDefinition.openapi) !== null && _a !== void 0 ? _a : openApiDefinition.swagger) !== null && _b !== void 0 ? _b : '').trim();
77
+ const apiVersion = String((_d = (_c = openApiDefinition.info) === null || _c === void 0 ? void 0 : _c.version) !== null && _d !== void 0 ? _d : '').trim();
78
+ const version = apiVersion || specVersion || 'Unknown';
79
+ const versionText = [
80
+ apiVersion ? `API ${apiVersion}` : null,
81
+ specVersion ? `OpenAPI ${specVersion}` : null,
82
+ ]
83
+ .filter(Boolean)
84
+ .join(', ');
85
+ return {
86
+ version,
87
+ ...(versionText ? { versionText } : {}),
88
+ };
89
+ },
90
+ };
@@ -0,0 +1,55 @@
1
+ export interface RestApiParameter {
2
+ name: string;
3
+ in: 'query' | 'header' | 'path' | 'cookie' | 'body';
4
+ dataType?: string;
5
+ contentType?: string;
6
+ isStringList?: boolean;
7
+ description?: string;
8
+ required?: boolean;
9
+ defaultValue?: any;
10
+ options?: Array<{
11
+ label: string;
12
+ value: string;
13
+ }>;
14
+ odataLookupPath?: string;
15
+ odataLookupEntitySet?: string;
16
+ odataLookupValueField?: string;
17
+ odataLookupLabelField?: string;
18
+ }
19
+ export interface RestApiEndpoint {
20
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
21
+ path: string;
22
+ summary?: string;
23
+ description?: string;
24
+ parameters: RestApiParameter[];
25
+ }
26
+ export interface RestApiCategory {
27
+ name: string;
28
+ endpoints: RestApiEndpoint[];
29
+ }
30
+ export interface RestApiServer {
31
+ url: string;
32
+ description?: string;
33
+ }
34
+ export interface RestApiDefinition {
35
+ categories: RestApiCategory[];
36
+ servers?: RestApiServer[];
37
+ }
38
+ export interface RestApiAuthorization_None {
39
+ type: 'none';
40
+ }
41
+ export interface RestApiAuthorization_Basic {
42
+ type: 'basic';
43
+ user: string;
44
+ password: string;
45
+ }
46
+ export interface RestApiAuthorization_Bearer {
47
+ type: 'bearer';
48
+ token: string;
49
+ }
50
+ export interface RestApiAuthorization_ApiKey {
51
+ type: 'apikey';
52
+ header: string;
53
+ value: string;
54
+ }
55
+ export type RestApiAuthorization = RestApiAuthorization_None | RestApiAuthorization_Basic | RestApiAuthorization_Bearer | RestApiAuthorization_ApiKey;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ import type { AxiosInstance } from 'axios';
2
+ import { RestApiAuthorization, RestApiDefinition } from './restApiDef';
3
+ export declare function executeRestApiEndpointOpenApi(definition: RestApiDefinition, endpoint: string, method: string, parameterValues: Record<string, any>, server: string, auth: RestApiAuthorization | null, axios: AxiosInstance): Promise<any>;
4
+ export declare function executeODataApiEndpoint(definition: RestApiDefinition, endpoint: string, method: string, parameterValues: Record<string, any>, server: string, auth: RestApiAuthorization | null, axios: AxiosInstance): Promise<any>;