Skip to content

Commit eb5a367

Browse files
authored
Chore: add tests (#3)
1 parent 9a99263 commit eb5a367

File tree

15 files changed

+761
-10
lines changed

15 files changed

+761
-10
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ node_modules/
44
.AppleDouble
55
.LSOverride
66
dist
7+
openapi-*.yml

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"devDependencies": {
1616
"@conqa/serverless-openapi-documentation": "^1.1.0",
1717
"@types/jest": "^27.0.1",
18+
"@types/serverless": "^1.78.35",
1819
"jest": "^27.0.6",
1920
"serverless": "^2.56.0",
2021
"ts-jest": "^27.0.5",

src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
import ServerlessOpenapiTypeScript from "./serverless-openapi-typescript";
2-
3-
export default ServerlessOpenapiTypeScript;
2+
export = ServerlessOpenapiTypeScript;

src/serverless-openapi-typescript.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import type Serverless from "serverless";
22
import fs from "fs";
33
import yaml from "js-yaml";
4-
import tsj, {SchemaGenerator} from "ts-json-schema-generator";
4+
import {SchemaGenerator, createGenerator} from "ts-json-schema-generator";
55
import {upperFirst, mergeWith, set, isArray, get, isEmpty } from "lodash" ;
6+
import {ApiGatewayEvent} from "serverless/plugins/aws/package/compile/events/apiGateway/lib/validate";
67

78
interface Options {
89
typescriptApiPath?: string;
910
tsconfigPath?: string;
1011
}
1112

13+
type HttpEvent = ApiGatewayEvent['http'] & {
14+
documentation?: any;
15+
private?: boolean;
16+
}
17+
1218
export default class ServerlessOpenapiTypeScript {
1319
private readonly functionsMissingDocumentation: string[];
1420
private readonly disable: boolean;
@@ -23,7 +29,7 @@ export default class ServerlessOpenapiTypeScript {
2329
this.initOptions(options);
2430
this.functionsMissingDocumentation = [];
2531

26-
if (!this.serverless.service.custom.documentation) {
32+
if (!this.serverless.service.custom?.documentation) {
2733
this.log(
2834
`Disabling OpenAPI generation for ${this.serverless.service.service} - no 'custom.documentation' attribute found`
2935
);
@@ -64,9 +70,8 @@ export default class ServerlessOpenapiTypeScript {
6470
async populateServerlessWithModels() {
6571
this.log('Scanning functions for documentation attribute');
6672
Object.keys(this.functions).forEach(functionName => {
67-
const events = get(this.functions, `${functionName}.events`, []);
68-
events.forEach(event => {
69-
const httpEvent = event.http;
73+
this.functions[functionName]?.events?.forEach((event: ApiGatewayEvent) => {
74+
const httpEvent = event.http as HttpEvent;
7075
if (httpEvent) {
7176
if (httpEvent.documentation) {
7277
this.log(`Generating docs for ${functionName}`);
@@ -161,6 +166,7 @@ export default class ServerlessOpenapiTypeScript {
161166
}
162167

163168
postProcessOpenApi() {
169+
// @ts-ignore
164170
const outputFile = this.serverless.processedInput.options.output;
165171
const openApi = yaml.load(fs.readFileSync(outputFile));
166172
this.patchOpenApiVersion(openApi);
@@ -210,7 +216,7 @@ export default class ServerlessOpenapiTypeScript {
210216

211217
this.schemaGenerator =
212218
this.schemaGenerator ||
213-
tsj.createGenerator({
219+
createGenerator({
214220
path: this.typescriptApiModelPath,
215221
tsconfig: this.tsconfigPath,
216222
type: `*`,

test/fixtures/expect-openapi-full.yml

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
openapi: 3.1.0
2+
components:
3+
schemas:
4+
ObjectType:
5+
type: object
6+
properties:
7+
types:
8+
type: array
9+
items:
10+
type: string
11+
children:
12+
type: array
13+
items:
14+
$ref: '#/components/schemas/ObjectType'
15+
additionalProperties: false
16+
ProjectApi.CreateFunc.Request.Body:
17+
type: object
18+
properties:
19+
data:
20+
type: string
21+
statusCode:
22+
type: number
23+
enable:
24+
type: boolean
25+
object:
26+
$ref: '#/components/schemas/ObjectType'
27+
required:
28+
- data
29+
- enable
30+
additionalProperties: false
31+
ProjectApi.CreateFunc.Response:
32+
type: object
33+
properties:
34+
id:
35+
type: string
36+
uuid:
37+
type: string
38+
required:
39+
- id
40+
- uuid
41+
additionalProperties: false
42+
ProjectApi.UpdateFunc.Request.Body:
43+
type: object
44+
properties:
45+
id:
46+
type: string
47+
data:
48+
type: string
49+
required:
50+
- id
51+
- data
52+
additionalProperties: false
53+
ProjectApi.UpdateFunc.Response:
54+
type: object
55+
properties:
56+
id:
57+
type: string
58+
required:
59+
- id
60+
additionalProperties: false
61+
ProjectApi.GetFunc.Response:
62+
type: object
63+
properties:
64+
data:
65+
type: string
66+
required:
67+
- data
68+
additionalProperties: false
69+
info:
70+
title: Project
71+
description: >
72+
It is a long established fact that a reader will be distracted by the
73+
readable content of a
74+
75+
page when looking at its layout. The point of using Lorem Ipsum is that
76+
77+
it has a more-or-less normal distribution of letters, as opposed to using
78+
79+
'Content here, content here', making it look like readable English. Many
80+
desktop publishing
81+
82+
packages and web page editors now use Lorem Ipsum as their default model
83+
text, and a search
84+
85+
for 'lorem ipsum' will uncover many web sites still in their infancy.
86+
Various versions have evolved over the years,
87+
88+
sometimes by accident, sometimes on purpose (injected humour and the like).
89+
90+
91+
More on https://google.com
92+
version: 633016ae-c93a-44ee-9162-b3befc3b722a
93+
paths:
94+
/create/{funcName}:
95+
post:
96+
operationId: createFunc
97+
summary: Create Function
98+
description: |
99+
Create Function1
100+
Create Function2
101+
Create Function3
102+
requestBody:
103+
content:
104+
application/json:
105+
schema:
106+
$ref: '#/components/schemas/ProjectApi.CreateFunc.Request.Body'
107+
description: ''
108+
parameters:
109+
- name: funcName
110+
in: path
111+
description: ''
112+
required: true
113+
schema:
114+
type: string
115+
- name: param1
116+
in: query
117+
description: Param 1
118+
required: false
119+
allowEmptyValue: false
120+
schema:
121+
type: string
122+
enum:
123+
- 'true'
124+
- 'false'
125+
- name: param2
126+
in: query
127+
description: Param 2
128+
required: true
129+
allowEmptyValue: false
130+
schema:
131+
type: string
132+
- name: param3
133+
in: query
134+
description: Param 3
135+
required: false
136+
allowEmptyValue: false
137+
schema:
138+
type: number
139+
responses:
140+
'200':
141+
description: ''
142+
content:
143+
application/json:
144+
schema:
145+
$ref: '#/components/schemas/ProjectApi.CreateFunc.Response'
146+
tags:
147+
- Project
148+
/delete/{funcName}:
149+
delete:
150+
operationId: deleteFunc
151+
summary: Delete Function
152+
description: Delete
153+
parameters:
154+
- name: funcName
155+
in: path
156+
description: ''
157+
required: true
158+
schema:
159+
type: string
160+
responses:
161+
'204':
162+
description: Status 204 Response
163+
content: {}
164+
tags:
165+
- Project
166+
/update:
167+
put:
168+
operationId: updateFunc
169+
summary: Delete Function
170+
description: Delete
171+
requestBody:
172+
content:
173+
application/json:
174+
schema:
175+
$ref: '#/components/schemas/ProjectApi.UpdateFunc.Request.Body'
176+
description: ''
177+
parameters: []
178+
responses:
179+
'200':
180+
description: ''
181+
content:
182+
application/json:
183+
schema:
184+
$ref: '#/components/schemas/ProjectApi.UpdateFunc.Response'
185+
tags:
186+
- Project
187+
/get/{funcName}:
188+
get:
189+
operationId: getFunc
190+
summary: Get Function
191+
parameters:
192+
- name: funcName
193+
in: path
194+
description: ''
195+
required: true
196+
schema:
197+
type: string
198+
responses:
199+
'200':
200+
description: ''
201+
content:
202+
application/json:
203+
schema:
204+
$ref: '#/components/schemas/ProjectApi.GetFunc.Response'
205+
tags:
206+
- Project
207+
tags:
208+
- name: Project
209+
description: >
210+
It is a long established fact that a reader will be distracted by the
211+
readable content of a
212+
213+
page when looking at its layout. The point of using Lorem Ipsum is that
214+
215+
it has a more-or-less normal distribution of letters, as opposed to using
216+
217+
'Content here, content here', making it look like readable English. Many
218+
desktop publishing
219+
220+
packages and web page editors now use Lorem Ipsum as their default model
221+
text, and a search
222+
223+
for 'lorem ipsum' will uncover many web sites still in their infancy.
224+
Various versions have evolved over the years,
225+
226+
sometimes by accident, sometimes on purpose (injected humour and the
227+
like).
228+
229+
230+
More on https://google.com

test/serverless-disable/api.d.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
interface ObjectType {
2+
types?: string[];
3+
children?: ObjectType[];
4+
}
5+
6+
export namespace ProjectApi {
7+
export type Bool = 'true' | 'false';
8+
export type Number = number
9+
export type String = string;
10+
11+
export namespace CreateFunc {
12+
export namespace Request {
13+
export type Body = {
14+
data: string;
15+
statusCode?: number;
16+
enable: boolean;
17+
object?: ObjectType;
18+
};
19+
}
20+
21+
export type Response = {
22+
id: string;
23+
uuid: string;
24+
};
25+
}
26+
27+
export namespace DeleteFunc {
28+
export namespace Request {
29+
export type Body = {
30+
id: string;
31+
};
32+
}
33+
}
34+
35+
export namespace UpdateFunc {
36+
export namespace Request {
37+
export type Body = {
38+
id: string;
39+
data: string;
40+
};
41+
}
42+
43+
export type Response = {
44+
id: string;
45+
};
46+
}
47+
48+
export namespace GetFunc {
49+
export type Response = {
50+
data: string;
51+
};
52+
}
53+
}

0 commit comments

Comments
 (0)