@trayio/tray-openapi 2.11.0 → 2.12.0
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 +39 -0
- package/dist/OpenApiSchemaImporter.d.ts +1 -17
- package/dist/OpenApiSchemaImporter.d.ts.map +1 -1
- package/dist/OpenApiSchemaImporter.js +5 -5
- package/dist/OpenApiSchemaImporter.test.js +11 -9
- package/dist/OpenApiSchemaTransformer.d.ts +9 -0
- package/dist/OpenApiSchemaTransformer.d.ts.map +1 -0
- package/dist/OpenApiSchemaTransformer.js +68 -0
- package/dist/OpenApiSchemaTransformer.test.d.ts +2 -0
- package/dist/OpenApiSchemaTransformer.test.d.ts.map +1 -0
- package/dist/OpenApiSchemaTransformer.test.js +118 -0
- package/dist/OpenApiTypeDescriptors.d.ts +39 -6
- package/dist/OpenApiTypeDescriptors.d.ts.map +1 -1
- package/dist/OpenApiTypeDescriptors.js +5 -11
- package/dist/file-generators/GenerateHandler.test.js +18 -0
- package/dist/file-generators/GenerateHandlerTest.test.js +33 -0
- package/dist/file-generators/types/GenerateInputSchema.d.ts +2 -1
- package/dist/file-generators/types/GenerateInputSchema.d.ts.map +1 -1
- package/dist/file-generators/types/GenerateInputSchema.js +25 -27
- package/dist/file-generators/types/GenerateInputSchema.test.js +63 -9
- package/dist/file-generators/types/GenerateInputType.test.js +60 -13
- package/dist/file-generators/types/GenerateInputTypes.d.ts.map +1 -1
- package/dist/file-generators/types/GenerateInputTypes.js +4 -0
- package/dist/file-generators/types/GenerateOutput.d.ts.map +1 -1
- package/dist/file-generators/types/GenerateOutput.js +5 -4
- package/dist/file-generators/types/GenerateOutput.test.js +10 -0
- package/dist/test-openapi-spec.json +159 -139
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
This module speeds up the development process of creating a new Tray CDK connector by parsing an OpenAPI specification file for a given API and generating operation handlers, meta data, input and output types.
|
|
2
|
+
|
|
3
|
+
This beta functionality is available from the @trayio/cdk-cli module via the `tray-cdk import-openapi-spec` command. If you encounter any issues that you wish the team to investigate further please supply us with OpenApi specification you are importing and the `errors.json` that has been generated during the import process.
|
|
4
|
+
|
|
5
|
+
These are the features that are currently supported/unsupported:
|
|
6
|
+
- OpenAPI spec interpretation:
|
|
7
|
+
- Supported:
|
|
8
|
+
- schema internal component references
|
|
9
|
+
- JSON OpenAPI specification version 3
|
|
10
|
+
- If your version is older you can use this to update it: [Swagger Editor](https://editor.swagger.io/) (From the top menu bar, select edit, convert to Open API 3, you can also use this to convert from YAML to JSON)
|
|
11
|
+
- Unsupported:
|
|
12
|
+
- Swagger API version 2
|
|
13
|
+
- YAML spec files
|
|
14
|
+
- open API specs with multiple server URLs, manually edit the file to set your desired server to the first in the array
|
|
15
|
+
- recursive schema references
|
|
16
|
+
- external schema references
|
|
17
|
+
- schema references that target nested components
|
|
18
|
+
- Authentication
|
|
19
|
+
- Unsupported:
|
|
20
|
+
- generation of Auth type
|
|
21
|
+
- handlers utilising the auth token in handlers
|
|
22
|
+
- Input/output types:
|
|
23
|
+
- Supported:
|
|
24
|
+
- Primitive types: number, string, boolean
|
|
25
|
+
- Objects
|
|
26
|
+
- 2XX response schemas
|
|
27
|
+
- Empty input/output
|
|
28
|
+
- Unsupported:
|
|
29
|
+
- enum types
|
|
30
|
+
- array types
|
|
31
|
+
- non 2XX response schemas
|
|
32
|
+
- Request/Response types:
|
|
33
|
+
- Supported:
|
|
34
|
+
- Json request/response
|
|
35
|
+
- Unsupported:
|
|
36
|
+
- xml request/response
|
|
37
|
+
- text request/response
|
|
38
|
+
- file request/response
|
|
39
|
+
- form request/response
|
|
@@ -1,22 +1,7 @@
|
|
|
1
1
|
import * as TE from 'fp-ts/TaskEither';
|
|
2
2
|
import { FileStorage } from '@trayio/commons/file/File';
|
|
3
3
|
import { Generator } from '@trayio/generator/generator/Generator';
|
|
4
|
-
import {
|
|
5
|
-
type BaseOperation = {
|
|
6
|
-
httpMethod: OpenApiHttpMethod;
|
|
7
|
-
path: string;
|
|
8
|
-
};
|
|
9
|
-
type OperationError = BaseOperation & {
|
|
10
|
-
tag: 'error';
|
|
11
|
-
errorMessage: string;
|
|
12
|
-
};
|
|
13
|
-
type OperationSuccess = BaseOperation & {
|
|
14
|
-
tag: 'success';
|
|
15
|
-
};
|
|
16
|
-
export type BuildConnectorResponse = {
|
|
17
|
-
successes: OperationSuccess[];
|
|
18
|
-
errors: OperationError[];
|
|
19
|
-
};
|
|
4
|
+
import { BuildConnectorResponse } from './OpenApiTypeDescriptors';
|
|
20
5
|
export declare class OpenApiSchemaImporter {
|
|
21
6
|
private generator;
|
|
22
7
|
private fileStorage;
|
|
@@ -29,5 +14,4 @@ export declare class OpenApiSchemaImporter {
|
|
|
29
14
|
private generateConnectorDirectory;
|
|
30
15
|
private generateOperationDirectory;
|
|
31
16
|
}
|
|
32
|
-
export {};
|
|
33
17
|
//# sourceMappingURL=OpenApiSchemaImporter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenApiSchemaImporter.d.ts","sourceRoot":"","sources":["../src/OpenApiSchemaImporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AASvC,OAAO,EAAQ,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AAGlE,OAAO,
|
|
1
|
+
{"version":3,"file":"OpenApiSchemaImporter.d.ts","sourceRoot":"","sources":["../src/OpenApiSchemaImporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AASvC,OAAO,EAAQ,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AAGlE,OAAO,EAEN,sBAAsB,EAMtB,MAAM,0BAA0B,CAAC;AAalC,qBAAa,qBAAqB;IACrB,OAAO,CAAC,SAAS;IAAa,OAAO,CAAC,WAAW;gBAAzC,SAAS,EAAE,SAAS,EAAU,WAAW,EAAE,WAAW;IAE1E,cAAc,CACb,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,GACnB,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,sBAAsB,CAAC;IAoD/C,OAAO,CAAC,yBAAyB;IAyDjC,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,cAAc;IAoCtB,OAAO,CAAC,oCAAoC;IAgF5C,OAAO,CAAC,0BAA0B;IAwBlC,OAAO,CAAC,0BAA0B;CAclC"}
|
|
@@ -33,8 +33,8 @@ const Apply_1 = require("fp-ts/Apply");
|
|
|
33
33
|
const json_ref_resolver_1 = require("@stoplight/json-ref-resolver");
|
|
34
34
|
const StringExtensions_1 = require("@trayio/commons/string/StringExtensions");
|
|
35
35
|
const lodash_1 = require("lodash");
|
|
36
|
-
const stream_1 = require("stream");
|
|
37
36
|
const BufferExtensions_1 = require("@trayio/commons/buffer/BufferExtensions");
|
|
37
|
+
const stream_1 = require("stream");
|
|
38
38
|
const OpenApiCodecs_1 = require("./OpenApiCodecs");
|
|
39
39
|
const GenerateHandler_1 = require("./file-generators/GenerateHandler");
|
|
40
40
|
const GenerateOutput_1 = require("./file-generators/types/GenerateOutput");
|
|
@@ -42,6 +42,7 @@ const GenerateInputTypes_1 = require("./file-generators/types/GenerateInputTypes
|
|
|
42
42
|
const GenerateHandlerTest_1 = require("./file-generators/GenerateHandlerTest");
|
|
43
43
|
const GenerateOperationJson_1 = require("./file-generators/GenerateOperationJson");
|
|
44
44
|
const GenerateInputSchema_1 = require("./file-generators/types/GenerateInputSchema");
|
|
45
|
+
const OpenApiSchemaTransformer_1 = require("./OpenApiSchemaTransformer");
|
|
45
46
|
class OpenApiSchemaImporter {
|
|
46
47
|
constructor(generator, fileStorage) {
|
|
47
48
|
this.generator = generator;
|
|
@@ -60,7 +61,6 @@ class OpenApiSchemaImporter {
|
|
|
60
61
|
})),
|
|
61
62
|
})));
|
|
62
63
|
}), TE.chain(({ openApiSpec, connectorPath, paths }) => (0, Array_1.traverse)(TE.ApplicativeSeq)((path) => this.generateOperationFromPath(path, connectorPath, openApiSpec.servers[0].url, connectorName))(paths)), TE.map((operation) => {
|
|
63
|
-
console.log(operation);
|
|
64
64
|
const flatOperations = operation.flat();
|
|
65
65
|
const buildConnectorResponse = flatOperations.reduce((acc, curr) => {
|
|
66
66
|
if (curr.tag === 'error') {
|
|
@@ -72,7 +72,7 @@ class OpenApiSchemaImporter {
|
|
|
72
72
|
}));
|
|
73
73
|
}
|
|
74
74
|
generateOperationFromPath(path, connectorPath, baseUrl, connectorName) {
|
|
75
|
-
return (0, function_1.pipe)((0, Array_1.traverse)(TE.ApplicativeSeq)((route) => (0, function_1.pipe)(this.decodeOperation(route.path, path.path, route.method), TE.bindTo('decodedPath'), TE.chain(({ decodedPath }) => (0, function_1.pipe)(this.generateOperationDirectory(connectorPath, decodedPath.operationId), TE.bind('inputs', () => TE.
|
|
75
|
+
return (0, function_1.pipe)((0, Array_1.traverse)(TE.ApplicativeSeq)((route) => (0, function_1.pipe)(this.decodeOperation(route.path, path.path, route.method), TE.bindTo('decodedPath'), TE.chain(({ decodedPath }) => (0, function_1.pipe)(this.generateOperationDirectory(connectorPath, decodedPath.operationId), TE.bind('inputs', () => TE.fromEither((0, GenerateInputSchema_1.generateInputSchema)(decodedPath))), TE.bind('outputs', () => (0, GenerateOutput_1.generateOutputSchema)(decodedPath.responses)), TE.bind('decodedPath', () => TE.right(decodedPath)))), TE.chain(({ inputs, outputs, decodedPath }) => this.generateHandlerFilesAndOperationJson(route.method, decodedPath, `${connectorPath}/src/${(0, lodash_1.kebabCase)(decodedPath.operationId)}`, baseUrl, path.path, connectorName, inputs, outputs)), TE.map(() => ({
|
|
76
76
|
tag: 'success',
|
|
77
77
|
httpMethod: route.method,
|
|
78
78
|
path: path.path,
|
|
@@ -91,7 +91,7 @@ class OpenApiSchemaImporter {
|
|
|
91
91
|
const resolver = new json_ref_resolver_1.Resolver({});
|
|
92
92
|
const resolvedOpenApiSpec = resolver.resolve(openApiSpec, {});
|
|
93
93
|
return resolvedOpenApiSpec;
|
|
94
|
-
}, (reason) => new Error(`Failed to resolve references in schema: ${reason}`))), TE.chain((openApiSpec) => TE.
|
|
94
|
+
}, (reason) => new Error(`Failed to resolve references in schema: ${reason}`))), TE.chain((openApiSpec) => TE.fromEither((0, OpenApiSchemaTransformer_1.mergePathLevelParamsIntoHttpMethod)(openApiSpec.result))));
|
|
95
95
|
}
|
|
96
96
|
generateHandlerFilesAndOperationJson(method, path, operationPath, baseUrl, httpPath, connectorName, input, output) {
|
|
97
97
|
const writeFile = (content, fileName) => this.fileStorage.write({
|
|
@@ -129,7 +129,7 @@ class OpenApiSchemaImporter {
|
|
|
129
129
|
connectorNameKebabCase: (0, lodash_1.kebabCase)(connectorName),
|
|
130
130
|
connectorNamePascalCase: StringExtensions_1.StringExtensions.pascalCase(connectorName),
|
|
131
131
|
connectorNameCamelCase: (0, lodash_1.camelCase)(connectorName),
|
|
132
|
-
}), TE.chain((parameters) => this.generator.generate(`${__dirname}/templates/connector-template.zip`,
|
|
132
|
+
}), TE.chain((parameters) => this.generator.generate(`${__dirname}/templates/connector-template.zip`, process.cwd(), parameters)), TE.map(() => `/${(0, lodash_1.kebabCase)(connectorName)}`), TE.mapLeft((error) => new Error(`Failed to generate connector directory: ${error}`)));
|
|
133
133
|
}
|
|
134
134
|
generateOperationDirectory(connectorPath, operationName) {
|
|
135
135
|
return (0, function_1.pipe)(TE.tryCatch(this.fileStorage.createDirectory(`${connectorPath}/src/${(0, lodash_1.kebabCase)(operationName)}`), (error) => new Error(`Failed to create operation directory: ${error}`)), TE.map(() => `${connectorPath}/src/${(0, lodash_1.kebabCase)(operationName)}`));
|
|
@@ -44,40 +44,42 @@ describe('openApiSchemaImporter', () => {
|
|
|
44
44
|
const fileStorage = new FakeFileStorage_1.FakeFileStorage();
|
|
45
45
|
const openApiSchemaImporter = new OpenApiSchemaImporter_1.OpenApiSchemaImporter(generator, fileStorage);
|
|
46
46
|
let result;
|
|
47
|
+
const spec = 'test-openapi-spec.json';
|
|
47
48
|
beforeAll(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
49
|
fileStorage.write({
|
|
49
|
-
key: `${__dirname}
|
|
50
|
-
metadata: { name:
|
|
50
|
+
key: `${__dirname}/${spec}`,
|
|
51
|
+
metadata: { name: spec },
|
|
51
52
|
content: stream_1.Readable.from(Buffer.from(JSON.stringify(openApiSpec))),
|
|
52
53
|
});
|
|
53
|
-
result = yield openApiSchemaImporter.buildConnector(`${__dirname}
|
|
54
|
+
result = yield openApiSchemaImporter.buildConnector(`${__dirname}/${spec}`, 'testConnector')();
|
|
54
55
|
}));
|
|
55
56
|
afterAll(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
56
57
|
yield fs.rm(`${process.cwd()}/test/`, { recursive: true, force: true });
|
|
57
58
|
}));
|
|
58
59
|
it('should import successfully', () => {
|
|
59
60
|
const buildConnectorResponse = E.getOrElse((error) => {
|
|
61
|
+
console.error(error);
|
|
60
62
|
throw new Error('Should have been right');
|
|
61
63
|
})(result);
|
|
62
64
|
expect(buildConnectorResponse.successes.length).toEqual(1);
|
|
63
65
|
expect(buildConnectorResponse.errors.length).toEqual(1);
|
|
64
66
|
});
|
|
65
67
|
it('should generate a operation handler', () => {
|
|
66
|
-
expect(fileStorage.files.has(`/test
|
|
68
|
+
expect(fileStorage.files.has(`/test-connector/src/get-post/handler.ts`)).toEqual(true);
|
|
67
69
|
});
|
|
68
70
|
it('should generate an operation handler test', () => {
|
|
69
|
-
expect(fileStorage.files.has(`/test
|
|
71
|
+
expect(fileStorage.files.has(`/test-connector/src/get-post/handler.test.ts`)).toEqual(true);
|
|
70
72
|
});
|
|
71
73
|
it('should generate an operation.json', () => {
|
|
72
|
-
expect(fileStorage.files.has(`/test
|
|
74
|
+
expect(fileStorage.files.has(`/test-connector/src/get-post/operation.json`)).toEqual(true);
|
|
73
75
|
});
|
|
74
76
|
it('should generate an output.ts', () => {
|
|
75
|
-
expect(fileStorage.files.has(`/test
|
|
77
|
+
expect(fileStorage.files.has(`/test-connector/src/get-post/output.ts`)).toEqual(true);
|
|
76
78
|
});
|
|
77
79
|
it('should generate a operation directory', () => {
|
|
78
|
-
expect(fileStorage.files.has(`/test
|
|
80
|
+
expect(fileStorage.files.has(`/test-connector/src/get-post`)).toEqual(true);
|
|
79
81
|
});
|
|
80
82
|
it('should not generate a operation directory when failing to decode', () => {
|
|
81
|
-
expect(fileStorage.files.has(`/test
|
|
83
|
+
expect(fileStorage.files.has(`/test-connector/src/update-post`)).toEqual(false);
|
|
82
84
|
});
|
|
83
85
|
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as E from 'fp-ts/Either';
|
|
2
|
+
import { BaseOpenApiSpec } from './OpenApiTypeDescriptors';
|
|
3
|
+
export declare const isObject: (value: unknown) => value is Record<string, unknown>;
|
|
4
|
+
export declare const isObjectWithParameters: (value: unknown) => value is Record<string, unknown> & {
|
|
5
|
+
parameters: unknown[];
|
|
6
|
+
};
|
|
7
|
+
export declare const getMergedParameters: (pathValue: Record<string, unknown>, httpMethodValue: Record<string, unknown>) => unknown[];
|
|
8
|
+
export declare const mergePathLevelParamsIntoHttpMethod: (openApiSpec: BaseOpenApiSpec) => E.Either<Error, BaseOpenApiSpec>;
|
|
9
|
+
//# sourceMappingURL=OpenApiSchemaTransformer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenApiSchemaTransformer.d.ts","sourceRoot":"","sources":["../src/OpenApiSchemaTransformer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE3D,eAAO,MAAM,QAAQ,UAAW,OAAO,qCACK,CAAC;AAE7C,eAAO,MAAM,sBAAsB,UAC3B,OAAO;gBACqC,OAAO,EAAE;CACpB,CAAC;AAE1C,eAAO,MAAM,mBAAmB,cACpB,OAAO,MAAM,EAAE,OAAO,CAAC,mBACjB,OAAO,MAAM,EAAE,OAAO,CAAC,KACtC,OAAO,EAcT,CAAC;AAEF,eAAO,MAAM,kCAAkC,gBACjC,eAAe,KAC1B,EAAE,MAAM,CAAC,KAAK,EAAE,eAAe,CAkCjC,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.mergePathLevelParamsIntoHttpMethod = exports.getMergedParameters = exports.isObjectWithParameters = exports.isObject = void 0;
|
|
27
|
+
const E = __importStar(require("fp-ts/Either"));
|
|
28
|
+
const isObject = (value) => typeof value === 'object' && value !== null;
|
|
29
|
+
exports.isObject = isObject;
|
|
30
|
+
const isObjectWithParameters = (value) => (0, exports.isObject)(value) && 'parameters' in value;
|
|
31
|
+
exports.isObjectWithParameters = isObjectWithParameters;
|
|
32
|
+
const getMergedParameters = (pathValue, httpMethodValue) => {
|
|
33
|
+
if (!Array.isArray(pathValue.parameters)) {
|
|
34
|
+
throw new Error('Path parameters is not an array');
|
|
35
|
+
}
|
|
36
|
+
// if the method contains existing parameters, we merge them with the path parameters
|
|
37
|
+
if ('parameters' in httpMethodValue &&
|
|
38
|
+
Array.isArray(httpMethodValue.parameters)) {
|
|
39
|
+
return [...httpMethodValue.parameters, ...pathValue.parameters];
|
|
40
|
+
}
|
|
41
|
+
return pathValue.parameters;
|
|
42
|
+
};
|
|
43
|
+
exports.getMergedParameters = getMergedParameters;
|
|
44
|
+
const mergePathLevelParamsIntoHttpMethod = (openApiSpec) => {
|
|
45
|
+
const paths = Object.entries(openApiSpec.paths).reduce((pathAcc, [pathName, pathValue]) => {
|
|
46
|
+
// if the path doesn't contain top level params, we just return it
|
|
47
|
+
if (!(0, exports.isObjectWithParameters)(pathValue)) {
|
|
48
|
+
pathAcc[pathName] = pathValue;
|
|
49
|
+
return pathAcc;
|
|
50
|
+
}
|
|
51
|
+
const updatedPathValue = Object.entries(pathValue).reduce((methodAcc, [httpMethodName, httpMethodValue]) => {
|
|
52
|
+
if (!(0, exports.isObject)(httpMethodValue)) {
|
|
53
|
+
throw new Error('Http method value is not an object');
|
|
54
|
+
}
|
|
55
|
+
// we skip adding the parameters object to the path object
|
|
56
|
+
if (httpMethodName === 'parameters') {
|
|
57
|
+
return methodAcc;
|
|
58
|
+
}
|
|
59
|
+
const parameters = (0, exports.getMergedParameters)(pathValue, httpMethodValue);
|
|
60
|
+
methodAcc[httpMethodName] = Object.assign(Object.assign({}, httpMethodValue), { parameters });
|
|
61
|
+
return methodAcc;
|
|
62
|
+
}, {});
|
|
63
|
+
pathAcc[pathName] = updatedPathValue;
|
|
64
|
+
return pathAcc;
|
|
65
|
+
}, {});
|
|
66
|
+
return E.right(Object.assign(Object.assign({}, openApiSpec), { paths }));
|
|
67
|
+
};
|
|
68
|
+
exports.mergePathLevelParamsIntoHttpMethod = mergePathLevelParamsIntoHttpMethod;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenApiSchemaTransformer.test.d.ts","sourceRoot":"","sources":["../src/OpenApiSchemaTransformer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,118 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const E = __importStar(require("fp-ts/Either"));
|
|
27
|
+
const OpenApiSchemaTransformer_1 = require("./OpenApiSchemaTransformer");
|
|
28
|
+
describe('mergePathLevelParamsIntoHttpMethod', () => {
|
|
29
|
+
it('should merge path level parameters into HTTP methods', () => {
|
|
30
|
+
const openApiSpec = {
|
|
31
|
+
openapi: '3.0.0',
|
|
32
|
+
info: {
|
|
33
|
+
version: '1.0.0',
|
|
34
|
+
title: 'JSON Placeholder API',
|
|
35
|
+
description: 'See https://jsonplaceholder.typicode.com/',
|
|
36
|
+
},
|
|
37
|
+
servers: [
|
|
38
|
+
{
|
|
39
|
+
url: 'https://jsonplaceholder.typicode.com',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
paths: {
|
|
43
|
+
'/path': {
|
|
44
|
+
parameters: [{ name: 'param1', in: 'query', required: false }],
|
|
45
|
+
get: {
|
|
46
|
+
parameters: [{ name: 'param2', in: 'query', required: true }],
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
const result = (0, OpenApiSchemaTransformer_1.mergePathLevelParamsIntoHttpMethod)(openApiSpec);
|
|
52
|
+
E.fold((error) => {
|
|
53
|
+
throw new Error(`Test failed with error: ${error.message}`);
|
|
54
|
+
}, (updatedOpenApiSpec) => {
|
|
55
|
+
expect(updatedOpenApiSpec.paths['/path'].get.parameters).toEqual([
|
|
56
|
+
{ name: 'param2', in: 'query', required: true },
|
|
57
|
+
{ name: 'param1', in: 'query', required: false },
|
|
58
|
+
]);
|
|
59
|
+
})(result);
|
|
60
|
+
});
|
|
61
|
+
it('should return the original spec if no top level parameters', () => {
|
|
62
|
+
const openApiSpec = {
|
|
63
|
+
openapi: '3.0.0',
|
|
64
|
+
info: {
|
|
65
|
+
version: '1.0.0',
|
|
66
|
+
title: 'JSON Placeholder API',
|
|
67
|
+
description: 'See https://jsonplaceholder.typicode.com/',
|
|
68
|
+
},
|
|
69
|
+
servers: [
|
|
70
|
+
{
|
|
71
|
+
url: 'https://jsonplaceholder.typicode.com',
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
paths: {
|
|
75
|
+
'/path': {
|
|
76
|
+
get: {
|
|
77
|
+
parameters: [{ name: 'param2', in: 'query', required: true }],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
const result = (0, OpenApiSchemaTransformer_1.mergePathLevelParamsIntoHttpMethod)(openApiSpec);
|
|
83
|
+
E.fold((error) => {
|
|
84
|
+
throw new Error(`Test failed with error: ${error.message}`);
|
|
85
|
+
}, (updatedOpenApiSpec) => {
|
|
86
|
+
expect(updatedOpenApiSpec).toEqual(openApiSpec);
|
|
87
|
+
})(result);
|
|
88
|
+
});
|
|
89
|
+
it('should add path level parameters into HTTP methods, if no method params already exist', () => {
|
|
90
|
+
const openApiSpec = {
|
|
91
|
+
openapi: '3.0.0',
|
|
92
|
+
info: {
|
|
93
|
+
version: '1.0.0',
|
|
94
|
+
title: 'JSON Placeholder API',
|
|
95
|
+
description: 'See https://jsonplaceholder.typicode.com/',
|
|
96
|
+
},
|
|
97
|
+
servers: [
|
|
98
|
+
{
|
|
99
|
+
url: 'https://jsonplaceholder.typicode.com',
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
paths: {
|
|
103
|
+
'/path': {
|
|
104
|
+
parameters: [{ name: 'param1', in: 'query', required: false }],
|
|
105
|
+
get: {},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
const result = (0, OpenApiSchemaTransformer_1.mergePathLevelParamsIntoHttpMethod)(openApiSpec);
|
|
110
|
+
E.fold((error) => {
|
|
111
|
+
throw new Error(`Test failed with error: ${error.message}`);
|
|
112
|
+
}, (updatedOpenApiSpec) => {
|
|
113
|
+
expect(updatedOpenApiSpec.paths['/path'].get.parameters).toEqual([
|
|
114
|
+
{ name: 'param1', in: 'query', required: false },
|
|
115
|
+
]);
|
|
116
|
+
})(result);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
import * as t from 'io-ts';
|
|
2
2
|
import * as O from 'fp-ts/Option';
|
|
3
|
+
export type FlatPath = {
|
|
4
|
+
path: string;
|
|
5
|
+
routes: {
|
|
6
|
+
method: OpenApiHttpMethod;
|
|
7
|
+
path: unknown;
|
|
8
|
+
}[];
|
|
9
|
+
};
|
|
10
|
+
export type Server = {
|
|
11
|
+
url: string;
|
|
12
|
+
};
|
|
13
|
+
export type BaseOpenApiSpec = {
|
|
14
|
+
openapi: string;
|
|
15
|
+
info: {
|
|
16
|
+
version: string;
|
|
17
|
+
title: string;
|
|
18
|
+
description: string;
|
|
19
|
+
};
|
|
20
|
+
servers: Server[];
|
|
21
|
+
paths: Record<string, Record<string, unknown>>;
|
|
22
|
+
};
|
|
23
|
+
export type BaseOperation = {
|
|
24
|
+
httpMethod: OpenApiHttpMethod;
|
|
25
|
+
path: string;
|
|
26
|
+
};
|
|
27
|
+
export type OperationError = BaseOperation & {
|
|
28
|
+
tag: 'error';
|
|
29
|
+
errorMessage: string;
|
|
30
|
+
};
|
|
31
|
+
export type OperationSuccess = BaseOperation & {
|
|
32
|
+
tag: 'success';
|
|
33
|
+
};
|
|
34
|
+
export type Operation = OperationError | OperationSuccess;
|
|
35
|
+
export type BuildConnectorResponse = {
|
|
36
|
+
successes: OperationSuccess[];
|
|
37
|
+
errors: OperationError[];
|
|
38
|
+
};
|
|
3
39
|
export type Path = {
|
|
4
40
|
description: string;
|
|
5
41
|
tags: O.Option<string[]>;
|
|
@@ -12,12 +48,8 @@ export type Parameter = {
|
|
|
12
48
|
name: string;
|
|
13
49
|
in: string;
|
|
14
50
|
description: string;
|
|
15
|
-
required: boolean
|
|
16
|
-
schema:
|
|
17
|
-
type: string;
|
|
18
|
-
format: O.Option<string>;
|
|
19
|
-
items: O.Option<SchemaObject>;
|
|
20
|
-
};
|
|
51
|
+
required: O.Option<boolean>;
|
|
52
|
+
schema: SchemaObject;
|
|
21
53
|
};
|
|
22
54
|
export type RequestBody = {
|
|
23
55
|
content: Record<string, MediaTypeObject>;
|
|
@@ -57,6 +89,7 @@ export interface NonArraySchemaObject extends BaseSchemaObject {
|
|
|
57
89
|
type: O.Option<NonArraySchemaObjectType>;
|
|
58
90
|
}
|
|
59
91
|
export type BaseSchemaObject = {
|
|
92
|
+
title: O.Option<string>;
|
|
60
93
|
additionalProperties: O.Option<boolean | SchemaObject>;
|
|
61
94
|
properties: O.Option<Record<string, SchemaObject>>;
|
|
62
95
|
required: O.Option<string[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenApiTypeDescriptors.d.ts","sourceRoot":"","sources":["../src/OpenApiTypeDescriptors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,OAAO,CAAC;AAE3B,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"OpenApiTypeDescriptors.d.ts","sourceRoot":"","sources":["../src/OpenApiTypeDescriptors.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,7 +27,7 @@ exports.openApiSpecTypeDescriptor = exports.openApiSpecPathTypeDescriptor = expo
|
|
|
27
27
|
const t = __importStar(require("io-ts"));
|
|
28
28
|
const io_ts_types_1 = require("io-ts-types");
|
|
29
29
|
const TypeCodec_1 = require("@trayio/commons/codec/TypeCodec");
|
|
30
|
-
//
|
|
30
|
+
// Type Descriptors
|
|
31
31
|
const nonArraySchemaObjectType = t.keyof({
|
|
32
32
|
boolean: null,
|
|
33
33
|
object: null,
|
|
@@ -36,6 +36,7 @@ const nonArraySchemaObjectType = t.keyof({
|
|
|
36
36
|
integer: null,
|
|
37
37
|
});
|
|
38
38
|
exports.baseSchemaObjectSchemaTypeDescriptor = t.recursion('baseSchema', () => t.type({
|
|
39
|
+
title: (0, io_ts_types_1.optionFromNullable)(t.string),
|
|
39
40
|
additionalProperties: (0, io_ts_types_1.optionFromNullable)(t.union([t.boolean, exports.schemaObjectTypeDescriptor])),
|
|
40
41
|
properties: (0, io_ts_types_1.optionFromNullable)(t.record(t.string, exports.schemaObjectTypeDescriptor)),
|
|
41
42
|
required: (0, io_ts_types_1.optionFromNullable)(t.array(t.string)),
|
|
@@ -61,10 +62,7 @@ exports.schemaObjectTypeDescriptor = t.recursion('schemaObject', () => t.union([
|
|
|
61
62
|
arraySchemaObjectSchemaTypeDescriptor,
|
|
62
63
|
nonArraySchemaObjectSchemaTypeDescriptor,
|
|
63
64
|
]));
|
|
64
|
-
exports.schemaObjectTypeCodec = TypeCodec_1.TypeCodec.fromDescriptor(
|
|
65
|
-
arraySchemaObjectSchemaTypeDescriptor,
|
|
66
|
-
nonArraySchemaObjectSchemaTypeDescriptor,
|
|
67
|
-
])));
|
|
65
|
+
exports.schemaObjectTypeCodec = TypeCodec_1.TypeCodec.fromDescriptor(exports.schemaObjectTypeDescriptor);
|
|
68
66
|
const componentSchemaTypeDescriptor = t.type({
|
|
69
67
|
schemas: (0, io_ts_types_1.optionFromNullable)(t.record(t.string, exports.schemaObjectTypeDescriptor)),
|
|
70
68
|
});
|
|
@@ -82,12 +80,8 @@ exports.parameterSchemaTypeDescriptor = t.type({
|
|
|
82
80
|
name: t.string,
|
|
83
81
|
in: t.string,
|
|
84
82
|
description: t.string,
|
|
85
|
-
required: t.boolean,
|
|
86
|
-
schema:
|
|
87
|
-
type: t.string,
|
|
88
|
-
format: (0, io_ts_types_1.optionFromNullable)(t.string),
|
|
89
|
-
items: (0, io_ts_types_1.optionFromNullable)(exports.schemaObjectTypeDescriptor),
|
|
90
|
-
}),
|
|
83
|
+
required: (0, io_ts_types_1.optionFromNullable)(t.boolean),
|
|
84
|
+
schema: exports.schemaObjectTypeDescriptor,
|
|
91
85
|
});
|
|
92
86
|
exports.openApiSpecPathTypeDescriptor = t.type({
|
|
93
87
|
description: t.string,
|
|
@@ -27,6 +27,7 @@ const E = __importStar(require("fp-ts/Either"));
|
|
|
27
27
|
const O = __importStar(require("fp-ts/Option"));
|
|
28
28
|
const GenerateHandler_1 = require("./GenerateHandler");
|
|
29
29
|
const getGenerateHandlerInput = (input) => (Object.assign({ connectorNamePascalCase: 'OpenApiTest', operationNamePascalCase: 'GetPhoto', operationNameCamelCase: 'getPhoto', httpMethod: 'get', baseUrl: 'https://jsonplaceholder.typicode.com', input: {
|
|
30
|
+
title: O.none,
|
|
30
31
|
properties: O.none,
|
|
31
32
|
additionalProperties: O.none,
|
|
32
33
|
required: O.none,
|
|
@@ -62,8 +63,10 @@ describe('GenerateHandler', () => {
|
|
|
62
63
|
it('it should generate a handler with a path parameter', () => {
|
|
63
64
|
const input = {
|
|
64
65
|
type: O.some('object'),
|
|
66
|
+
title: O.none,
|
|
65
67
|
properties: O.some({
|
|
66
68
|
photoId: {
|
|
69
|
+
title: O.none,
|
|
67
70
|
type: O.some('string'),
|
|
68
71
|
in: O.some('path'),
|
|
69
72
|
properties: O.none,
|
|
@@ -109,8 +112,10 @@ describe('GenerateHandler', () => {
|
|
|
109
112
|
it('it should generate a handler with a body input as json', () => {
|
|
110
113
|
const input = {
|
|
111
114
|
type: O.some('object'),
|
|
115
|
+
title: O.none,
|
|
112
116
|
properties: O.some({
|
|
113
117
|
photoId: {
|
|
118
|
+
title: O.none,
|
|
114
119
|
type: O.some('string'),
|
|
115
120
|
in: O.some('body'),
|
|
116
121
|
properties: O.none,
|
|
@@ -153,8 +158,10 @@ describe('GenerateHandler', () => {
|
|
|
153
158
|
it('it should generate a handler with a query string input', () => {
|
|
154
159
|
const input = {
|
|
155
160
|
type: O.some('object'),
|
|
161
|
+
title: O.none,
|
|
156
162
|
properties: O.some({
|
|
157
163
|
id: {
|
|
164
|
+
title: O.none,
|
|
158
165
|
type: O.some('string'),
|
|
159
166
|
in: O.some('query'),
|
|
160
167
|
properties: O.none,
|
|
@@ -197,8 +204,10 @@ describe('GenerateHandler', () => {
|
|
|
197
204
|
it('it should generate a handler with a header input', () => {
|
|
198
205
|
const input = {
|
|
199
206
|
type: O.some('object'),
|
|
207
|
+
title: O.none,
|
|
200
208
|
properties: O.some({
|
|
201
209
|
'Content-Type': {
|
|
210
|
+
title: O.none,
|
|
202
211
|
type: O.some('string'),
|
|
203
212
|
in: O.some('header'),
|
|
204
213
|
properties: O.none,
|
|
@@ -241,8 +250,10 @@ describe('GenerateHandler', () => {
|
|
|
241
250
|
it('it should generate a handler and transform number type to string for input', () => {
|
|
242
251
|
const input = {
|
|
243
252
|
type: O.some('object'),
|
|
253
|
+
title: O.none,
|
|
244
254
|
properties: O.some({
|
|
245
255
|
'Content-Type': {
|
|
256
|
+
title: O.none,
|
|
246
257
|
type: O.some('integer'),
|
|
247
258
|
in: O.some('header'),
|
|
248
259
|
properties: O.none,
|
|
@@ -285,8 +296,10 @@ describe('GenerateHandler', () => {
|
|
|
285
296
|
it('it should generate a handler with a query string and path param input', () => {
|
|
286
297
|
const input = {
|
|
287
298
|
type: O.some('object'),
|
|
299
|
+
title: O.none,
|
|
288
300
|
properties: O.some({
|
|
289
301
|
id: {
|
|
302
|
+
title: O.none,
|
|
290
303
|
type: O.some('string'),
|
|
291
304
|
in: O.some('query'),
|
|
292
305
|
properties: O.none,
|
|
@@ -298,6 +311,7 @@ describe('GenerateHandler', () => {
|
|
|
298
311
|
not: O.none,
|
|
299
312
|
},
|
|
300
313
|
photoId: {
|
|
314
|
+
title: O.none,
|
|
301
315
|
type: O.some('string'),
|
|
302
316
|
in: O.some('path'),
|
|
303
317
|
properties: O.none,
|
|
@@ -309,6 +323,7 @@ describe('GenerateHandler', () => {
|
|
|
309
323
|
not: O.none,
|
|
310
324
|
},
|
|
311
325
|
commentId: {
|
|
326
|
+
title: O.none,
|
|
312
327
|
type: O.some('string'),
|
|
313
328
|
in: O.some('path'),
|
|
314
329
|
properties: O.none,
|
|
@@ -354,8 +369,10 @@ describe('GenerateHandler', () => {
|
|
|
354
369
|
it('it should generate a handler with a query string and body param input', () => {
|
|
355
370
|
const input = {
|
|
356
371
|
type: O.some('object'),
|
|
372
|
+
title: O.none,
|
|
357
373
|
properties: O.some({
|
|
358
374
|
id: {
|
|
375
|
+
title: O.none,
|
|
359
376
|
type: O.some('string'),
|
|
360
377
|
in: O.some('query'),
|
|
361
378
|
properties: O.none,
|
|
@@ -367,6 +384,7 @@ describe('GenerateHandler', () => {
|
|
|
367
384
|
not: O.none,
|
|
368
385
|
},
|
|
369
386
|
photoId: {
|
|
387
|
+
title: O.none,
|
|
370
388
|
type: O.some('string'),
|
|
371
389
|
in: O.some('body'),
|
|
372
390
|
properties: O.none,
|