Skip to content

chore: fix bugs and update docs #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ The hierarchical structure of the directory is converted to the hierarchical str

## Usage

- [Playground](https://himenon.github.io/openapi-typescript-code-generator-playground/index.html)

## Installation

```bash
Expand Down
2 changes: 2 additions & 0 deletions docs/ja/README-ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

## 使い方

- [Playground](https://himenon.github.io/openapi-typescript-code-generator-playground/index.html)

### インストール

```bash
Expand Down
20 changes: 2 additions & 18 deletions example/sample-axios.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,14 @@
import * as Formatter from "@himenon/openapi-parameter-formatter";
import * as axios from "axios";

import { ApiClient, Client, HttpMethod, ObjectLike, QueryParameters } from "./client";
import { generateQueryString } from "./utils";

export interface RequestOption {
retries?: number;
timeout?: number;
deadline?: number;
}

const generateQueryString = (queryParameters: QueryParameters | undefined): string | undefined => {
if (!queryParameters) {
return undefined;
}
return Object.entries(queryParameters).reduce((queryString, [key, item]) => {
if (!item.style) {
return queryString + "&" + `${key}=${item}`;
}
const result = Formatter.QueryParameter.generate(key, item as Formatter.QueryParameter.Parameter);
if (result) {
return queryString + "&" + result;
}
return queryString;
}, "");
};

const convertHttpMethodToAxiosMethod = (httpMethod: HttpMethod): axios.Method => {
const patterns: { [key in HttpMethod]: axios.Method } = {
GET: "GET",
Expand All @@ -49,7 +33,7 @@ const apiClientImpl: ApiClient<RequestOption> = {
options?: RequestOption,
): Promise<any> => {
const query = generateQueryString(queryParameters);
const requestUrl = query ? url + "&" + query : url;
const requestUrl = query ? url + "?" + encodeURI(query) : url;
const response = await axios.default.request({
url: requestUrl,
method: convertHttpMethodToAxiosMethod(httpMethod),
Expand Down
21 changes: 2 additions & 19 deletions example/sample-debug.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
import * as Formatter from "@himenon/openapi-parameter-formatter";

import { ApiClient, Client, HttpMethod, ObjectLike, QueryParameters } from "./client";
import { generateQueryString } from "./utils";

export interface RequestOption {
timeout?: number;
}

const generateQueryString = (queryParameters: QueryParameters | undefined): string | undefined => {
if (!queryParameters) {
return undefined;
}
return Object.entries(queryParameters).reduce((queryString, [key, item]) => {
if (!item.style) {
return queryString + "&" + `${key}=${item}`;
}
const result = Formatter.QueryParameter.generate(key, item as Formatter.QueryParameter.Parameter);
if (result) {
return queryString + "&" + result;
}
return queryString;
}, "");
};

const apiClientImpl: ApiClient<RequestOption> = {
request: async (
httpMethod: HttpMethod,
Expand All @@ -32,7 +15,7 @@ const apiClientImpl: ApiClient<RequestOption> = {
options?: RequestOption,
): Promise<any> => {
const query = generateQueryString(queryParameters);
const requestUrl = query ? url + "&" + query : url;
const requestUrl = query ? url + "?" + encodeURI(query) : url;
console.log({
httpMethod,
url,
Expand Down
22 changes: 3 additions & 19 deletions example/sample-fetch.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,12 @@
import * as Formatter from "@himenon/openapi-parameter-formatter";
import fetch from "node-fetch";

import { ApiClient, Client, HttpMethod, ObjectLike, QueryParameters } from "./client";
import { generateQueryString } from "./utils";

export interface RequestOption {
timeout?: number;
}

const generateQueryString = (queryParameters: QueryParameters | undefined): string | undefined => {
if (!queryParameters) {
return undefined;
}
return Object.entries(queryParameters).reduce((queryString, [key, item]) => {
if (!item.style) {
return queryString + "&" + `${key}=${item}`;
}
const result = Formatter.QueryParameter.generate(key, item as Formatter.QueryParameter.Parameter);
if (result) {
return queryString + "&" + result;
}
return queryString;
}, "");
};

const apiClientImpl: ApiClient<RequestOption> = {
request: async (
httpMethod: HttpMethod,
Expand All @@ -33,9 +17,9 @@ const apiClientImpl: ApiClient<RequestOption> = {
options?: RequestOption,
): Promise<any> => {
const query = generateQueryString(queryParameters);
const requestUrl = query ? url + "&" + query : url;
const requestUrl = query ? url + "?" + encodeURI(query) : url;
const response = await fetch(requestUrl, {
body: requestBody,
body: JSON.stringify(requestBody),
headers,
method: httpMethod,
timeout: options?.timeout,
Expand Down
20 changes: 2 additions & 18 deletions example/sample-superagent.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,14 @@
import * as Formatter from "@himenon/openapi-parameter-formatter";
import * as Superagent from "superagent";

import { ApiClient, Client, HttpMethod, ObjectLike, QueryParameters } from "./client";
import { generateQueryString } from "./utils";

export interface RequestOption {
retries?: number;
timeout?: number;
deadline?: number;
}

const generateQueryString = (queryParameters: QueryParameters | undefined): string | undefined => {
if (!queryParameters) {
return undefined;
}
return Object.entries(queryParameters).reduce((queryString, [key, item]) => {
if (!item.style) {
return queryString + "&" + `${key}=${item}`;
}
const result = Formatter.QueryParameter.generate(key, item as Formatter.QueryParameter.Parameter);
if (result) {
return queryString + "&" + result;
}
return queryString;
}, "");
};

const apiClientImpl: ApiClient<RequestOption> = {
request: (
httpMethod: HttpMethod,
Expand All @@ -35,7 +19,7 @@ const apiClientImpl: ApiClient<RequestOption> = {
options?: RequestOption,
): Promise<any> => {
const query = generateQueryString(queryParameters);
const requestUrl = query ? url + "&" + query : url;
const requestUrl = query ? url + "?" + encodeURI(query) : url;

return new Promise((resolve, reject) => {
const agent = Superagent;
Expand Down
24 changes: 24 additions & 0 deletions example/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as Formatter from "@himenon/openapi-parameter-formatter";

import { QueryParameters } from "./client";

export const generateQueryString = (queryParameters: QueryParameters | undefined): string | undefined => {
if (!queryParameters) {
return undefined;
}
const queries = Object.entries(queryParameters).reduce<string[]>((queryStringList, [key, item]) => {
if (!item.value) {
return queryStringList;
}
if (!item.style) {
return queryStringList.concat(`${key}=${item.value}`);
}
const result = Formatter.QueryParameter.generate(key, item as Formatter.QueryParameter.Parameter);
if (result) {
return queryStringList.concat(result);
}
return queryStringList;
}, []);

return queries.join("&");
};
1 change: 1 addition & 0 deletions src/Converter/v3/components/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export const generateTypeAlias = (
export: true,
name,
type,
comment: schema.description,
});
};

Expand Down
1 change: 1 addition & 0 deletions src/Converter/v3/components/Schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export const generateNamespace = (
value: factory.TypeAliasDeclaration.create({
export: true,
name: name,
comment: reference.data.description,
type: factory.TypeReferenceNode.create({
name: context.getReferenceName(currentPoint, reference.path),
}),
Expand Down
50 changes: 21 additions & 29 deletions src/Converter/v3/toTypeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,44 +175,36 @@ export const convert: Convert = (
return nullable(factory, typeNode, !!schema.nullable);
}
case "object": {
if (!schema.properties) {
return factory.TypeNode.create({
type: "object",
value: [],
});
}
let typeNode: ts.TypeNode;
const required: string[] = schema.required || [];
// https://swagger.io/docs/specification/data-models/dictionaries/#free-form
// // https://swagger.io/docs/specification/data-models/dictionaries/#free-form
if (schema.additionalProperties === true) {
typeNode = factory.TypeNode.create({
return factory.TypeNode.create({
type: schema.type,
value: [],
});
} else {
const value: ts.PropertySignature[] = Object.entries(schema.properties).map(([name, jsonSchema]) => {
return factory.PropertySignature.create({
name,
type: convert(entryPoint, currentPoint, factory, jsonSchema, context, { parent: schema.properties }),
optional: !required.includes(name),
comment: typeof jsonSchema !== "boolean" ? jsonSchema.description : undefined,
});
}
const value: ts.PropertySignature[] = Object.entries(schema.properties || {}).map(([name, jsonSchema]) => {
return factory.PropertySignature.create({
name,
type: convert(entryPoint, currentPoint, factory, jsonSchema, context, { parent: schema.properties }),
optional: !required.includes(name),
comment: typeof jsonSchema !== "boolean" ? jsonSchema.description : undefined,
});
if (schema.additionalProperties) {
const additionalProperties = factory.IndexSignatureDeclaration.create({
name: "key",
type: convert(entryPoint, currentPoint, factory, schema.additionalProperties, context, { parent: schema.properties }),
});
return factory.TypeNode.create({
type: schema.type,
value: [...value, additionalProperties],
});
}
typeNode = factory.TypeNode.create({
});
if (schema.additionalProperties) {
const additionalProperties = factory.IndexSignatureDeclaration.create({
name: "key",
type: convert(entryPoint, currentPoint, factory, schema.additionalProperties, context, { parent: schema.properties }),
});
return factory.TypeNode.create({
type: schema.type,
value,
value: [...value, additionalProperties],
});
}
const typeNode = factory.TypeNode.create({
type: schema.type,
value,
});
return nullable(factory, typeNode, !!schema.nullable);
}
default:
Expand Down
19 changes: 19 additions & 0 deletions test/__tests__/__snapshots__/snapshot-test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ exports[`Generate Code Snapshot Test api.test.domain 1`] = `

/** @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#schemaObject */
export namespace Schemas {
/** String Literal */
export type StringType = string;
export type StringHasEnumType = \\"a\\" | \\"A\\" | \\"b\\" | \\"B\\" | \\"c\\" | \\"C\\";
export type StringDateType = string;
Expand All @@ -20,12 +21,14 @@ export namespace Schemas {
export type StringByteType = string;
export type StringBinaryType = string;
export type StringWithPatternType = string;
/** Number Literal */
export type NumberType = number;
export type NumberHasEnumType = 1 | 2 | 3 | 100 | 123 | 0.1 | -0.1 | 0;
export type NumberInt32Type = number;
export type NumberInt64Type = number;
export type NumberFloat = number;
export type NumberDouble = number;
/** Boolean Literal */
export type BooleanType = boolean;
export type ArrayStringType = string[];
export type ArrayNumberType = number[];
Expand Down Expand Up @@ -64,8 +67,10 @@ export namespace Schemas {
export type RemoteString = string;
export type RemoteRefString = Schemas.RemoteString;
export namespace Level1 {
/** Level 1 */
export type RemoteBoolean = boolean;
export namespace Level2 {
/** Level 2 */
export type RemoteNumber = number;
export namespace Level3 {
/** Level 3 */
Expand All @@ -80,9 +85,13 @@ export namespace Schemas {
}
}
}
/** Level 1 */
export type RemoteRefBoolean = Schemas.Level1.RemoteBoolean;
/** Level 2 */
export type RemoteRefNumber = Schemas.Level1.Level2.RemoteNumber;
/** Level 3 */
export type RemoteRefArray = Schemas.Level1.Level2.Level3.RemoteArray;
/** Level 4 */
export type RemoteRefObject = Schemas.Level1.Level2.Level3.Level4.RemoteObject;
export namespace DirectRef {
export type ForHeader = string;
Expand Down Expand Up @@ -218,6 +227,16 @@ export namespace Parameters {
export type RemoteReferenceB = Parameters.level1.B;
/** parameters -> schemas */
export type ReferenceOfParameterToSchema = Schemas.DirectRef.ForParameters;
/** deepObject */
export type DeepObjectParameter = {
[key: string]: {
gt?: string;
gte?: string;
lt?: string;
lte?: string;
any?: string | number | boolean;
};
};
}
/** @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#componentsObject */
export namespace RequestBodies {
Expand Down
23 changes: 23 additions & 0 deletions test/api.test.domain/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,29 @@ components:
name: ForReference
schema:
$ref: "./components/schemas/DirectRef/ForParameters.yml"
DeepObjectParameter:
description: deepObject
required: true
in: query
name: filter
schema:
type: object
additionalProperties:
type: object
properties:
gt:
type: string
gte:
type: string
lt:
type: string
lte:
type: string
any:
oneOf:
- type: string
- type: number
- type: boolean
responses:
Continue:
description: |
Expand Down