Skip to content

Commit 4d62643

Browse files
authored
chore: Trim the trailing slash of the baseUrl with constructor (#56)
1 parent 9cdc602 commit 4d62643

File tree

10 files changed

+134
-49
lines changed

10 files changed

+134
-49
lines changed

src/code-templates/api-client/ApiClientClass/Class.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@ export const create = (factory: TsGenerator.Factory.Type, members: ts.ClassEleme
1111
return factory.ClassDeclaration.create({
1212
name: "Client",
1313
export: true,
14-
members,
14+
members: [
15+
factory.PropertyDeclaration.create({
16+
modifiers: [ts.factory.createModifier(ts.SyntaxKind.PrivateKeyword)],
17+
name: "baseUrl",
18+
type: ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
19+
})
20+
,...members],
1521
typeParameterDeclaration: [
1622
factory.TypeParameterDeclaration.create({
1723
name: "RequestOption",

src/code-templates/api-client/ApiClientClass/Constructor.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,33 @@ export const create = (factory: TsGenerator.Factory.Type): ts.ConstructorDeclara
1919
}),
2020
});
2121
const parameter2 = factory.ParameterDeclaration.create({
22-
modifiers: "private",
2322
name: "baseUrl",
2423
type: factory.TypeNode.create({
2524
type: "string",
2625
}),
2726
});
27+
2828
return factory.ConstructorDeclaration.create({
2929
parameters: [parameter1, parameter2],
3030
body: factory.Block.create({
31-
statements: [],
31+
statements: [
32+
factory.ExpressionStatement.create({
33+
expression: factory.BinaryExpression.create({
34+
left: factory.PropertyAccessExpression.create({
35+
expression: "this",
36+
name: "baseUrl",
37+
}),
38+
operator: "=",
39+
right: factory.CallExpression.create({
40+
expression: factory.PropertyAccessExpression.create({
41+
expression: "baseUrl",
42+
name: "replace",
43+
}),
44+
argumentsArray: [factory.RegularExpressionLiteral.create({ text: "/\\/$/" }), factory.StringLiteral.create({ text: "" })],
45+
}),
46+
}),
47+
}),
48+
],
3249
multiLine: false,
3350
}),
3451
});

src/code-templates/api-client/ApiClientClass/MethodBody/PathParameter.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,9 @@ const generateUrlVariableStatement = (
2121
factory.VariableDeclaration.create({
2222
name: "url",
2323
initializer: factory.BinaryExpression.create({
24-
left: factory.CallExpression.create({
25-
expression: factory.PropertyAccessExpression.create({
26-
expression: factory.PropertyAccessExpression.create({
27-
name: "baseUrl",
28-
expression: "this",
29-
}),
30-
name: "replace",
31-
}),
32-
argumentsArray: [factory.RegularExpressionLiteral.create({ text: "/\\\/$/" }), factory.StringLiteral.create({ text: "" })],
24+
left: factory.PropertyAccessExpression.create({
25+
name: "baseUrl",
26+
expression: "this",
3327
}),
3428
operator: "+",
3529
right: Utils.generateTemplateExpression(factory, urlTemplate),

src/internal/TsGenerator/factory/BinaryExpression.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import ts from "typescript";
22

33
const operators = {
44
"+": ts.SyntaxKind.PlusToken,
5+
"=": ts.SyntaxKind.EqualsToken,
56
} as const;
67

78
export interface Params {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import ts from "typescript";
2+
3+
export interface Params$Create {
4+
expression: ts.Expression;
5+
}
6+
7+
export interface Factory {
8+
create: (params: Params$Create) => ts.ExpressionStatement;
9+
}
10+
11+
export const create = ({ factory }: Pick<ts.TransformationContext, "factory">): Factory["create"] => (params: Params$Create): ts.ExpressionStatement => {
12+
const node = factory.createExpressionStatement(params.expression);
13+
return node;
14+
};
15+
16+
export const make = (context: Pick<ts.TransformationContext, "factory">): Factory => {
17+
return {
18+
create: create(context),
19+
};
20+
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import ts from "typescript";
2+
3+
export interface Params {
4+
decorators?: readonly ts.Decorator[] | undefined;
5+
modifiers: readonly ts.Modifier[] | undefined;
6+
name: string | ts.PropertyName;
7+
questionOrExclamationToken?: ts.QuestionToken | ts.ExclamationToken | undefined;
8+
type: ts.TypeNode | undefined;
9+
initializer?: ts.Expression | undefined;
10+
}
11+
12+
export interface Factory {
13+
create: (params: Params) => ts.PropertyDeclaration;
14+
}
15+
16+
export const create = ({ factory }: Pick<ts.TransformationContext, "factory">): Factory["create"] => (
17+
params: Params,
18+
): ts.PropertyDeclaration => {
19+
const node = factory.createPropertyDeclaration(
20+
params.decorators,
21+
params.modifiers,
22+
params.name,
23+
params.questionOrExclamationToken,
24+
params.type,
25+
params.initializer,
26+
);
27+
return node;
28+
};
29+
30+
export const make = (context: Pick<ts.TransformationContext, "factory">): Factory => {
31+
return {
32+
create: create(context),
33+
};
34+
};

src/internal/TsGenerator/factory/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as CallExpression from "./CallExpression";
66
import * as ClassDeclaration from "./ClassDeclaration";
77
import * as ConstructorDeclaration from "./ConstructorDeclaration";
88
import * as ElementAccessExpression from "./ElementAccessExpression";
9+
import * as ExpressionStatement from "./ExpressionStatement";
910
import * as FunctionTypeNode from "./FunctionTypeNode";
1011
import * as Identifier from "./Identifier";
1112
import * as IndexedAccessTypeNode from "./IndexedAccessTypeNode";
@@ -21,6 +22,7 @@ import * as ParameterDeclaration from "./ParameterDeclaration";
2122
import * as PropertyAccessExpression from "./PropertyAccessExpression";
2223
import * as PropertyAssignment from "./PropertyAssignment";
2324
import * as PropertySignature from "./PropertySignature";
25+
import * as PropertyDeclaration from "./PropertyDeclaration";
2426
import * as RegularExpressionLiteral from "./RegularExpressionLiteral";
2527
import * as ReturnStatement from "./ReturnStatement";
2628
import * as StringLiteral from "./StringLiteral";
@@ -50,6 +52,7 @@ export interface Type {
5052
TypeOperatorNode: TypeOperatorNode.Factory;
5153
Namespace: Namespace.Factory;
5254
PropertySignature: PropertySignature.Factory;
55+
PropertyDeclaration: PropertyDeclaration.Factory;
5356
RegularExpressionLiteral: RegularExpressionLiteral.Factory;
5457
TypeAliasDeclaration: TypeAliasDeclaration.Factory;
5558
TypeNode: TypeNode.Factory;
@@ -76,6 +79,7 @@ export interface Type {
7679
PropertyAssignment: PropertyAssignment.Factory;
7780
ObjectLiteralExpression: ObjectLiteralExpression.Factory;
7881
ElementAccessExpression: ElementAccessExpression.Factory;
82+
ExpressionStatement: ExpressionStatement.Factory;
7983
CallExpression: CallExpression.Factory;
8084
StringLiteral: StringLiteral.Factory;
8185
FunctionTypeNode: FunctionTypeNode.Factory;
@@ -94,6 +98,7 @@ export const create = (): Type => {
9498
IndexedAccessTypeNode: IndexedAccessTypeNode.make(context),
9599
Namespace: Namespace.make(context),
96100
PropertySignature: PropertySignature.make(context),
101+
PropertyDeclaration: PropertyDeclaration.make(context),
97102
TypeAliasDeclaration: TypeAliasDeclaration.make(context),
98103
TypeNode: TypeNode.make(context),
99104
LiteralTypeNode: LiteralTypeNode.make(context),
@@ -122,6 +127,7 @@ export const create = (): Type => {
122127
PropertyAssignment: PropertyAssignment.make(context),
123128
ObjectLiteralExpression: ObjectLiteralExpression.make(context),
124129
ElementAccessExpression: ElementAccessExpression.make(context),
130+
ExpressionStatement: ExpressionStatement.make(context),
125131
CallExpression: CallExpression.make(context),
126132
StringLiteral: StringLiteral.make(context),
127133
FunctionTypeNode: FunctionTypeNode.make(context),

test/__tests__/__snapshots__/spit-code-test.ts.snap

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,14 @@ export interface ApiClient<RequestOption> {
105105
request: <T = SuccessResponses>(httpMethod: HttpMethod, url: string, headers: ObjectLike | any, requestBody: ObjectLike | any, queryParameters: QueryParameters | undefined, options?: RequestOption) => Promise<T>;
106106
}
107107
export class Client<RequestOption> {
108-
constructor(private apiClient: ApiClient<RequestOption>, private baseUrl: string) { }
108+
private baseUrl: string;
109+
constructor(private apiClient: ApiClient<RequestOption>, baseUrl: string) { this.baseUrl = baseUrl.replace(/\\\\/$/, \\"\\"); }
109110
/**
110111
* operationId: getIncludeLocalReference
111112
* Request URI: /get/IncludeLocalReference
112113
*/
113114
public async getIncludeLocalReference(params: Params$getIncludeLocalReference, option?: RequestOption): Promise<Response$getIncludeLocalReference$Status$200[\\"application/json\\"]> {
114-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/IncludeLocalReference\`;
115+
const url = this.baseUrl + \`/get/IncludeLocalReference\`;
115116
const headers = {
116117
Accept: \\"application/json\\"
117118
};
@@ -125,7 +126,7 @@ export class Client<RequestOption> {
125126
* Request URI: /get/IncludeRemoteReference
126127
*/
127128
public async getIncludeRemoteReference(params: Params$getIncludeRemoteReference, option?: RequestOption): Promise<void> {
128-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/IncludeRemoteReference\`;
129+
const url = this.baseUrl + \`/get/IncludeRemoteReference\`;
129130
const headers = {
130131
\\"Content-Type\\": \\"application/json\\"
131132
};
@@ -139,7 +140,7 @@ export class Client<RequestOption> {
139140
* Request URI: /FullRemoteReference
140141
*/
141142
public async getFullRemoteReference(params: Params$getFullRemoteReference, option?: RequestOption): Promise<Response$getFullRemoteReference$Status$200[\\"application/json\\"]> {
142-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/FullRemoteReference\`;
143+
const url = this.baseUrl + \`/FullRemoteReference\`;
143144
const headers = {
144145
Accept: \\"application/json\\"
145146
};
@@ -153,7 +154,7 @@ export class Client<RequestOption> {
153154
* Request URI: /get/reference/items
154155
*/
155156
public async getReferenceItems(option?: RequestOption): Promise<Response$getReferenceItems$Status$200[\\"application/json\\"]> {
156-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/reference/items\`;
157+
const url = this.baseUrl + \`/get/reference/items\`;
157158
const headers = {
158159
Accept: \\"application/json\\"
159160
};
@@ -164,7 +165,7 @@ export class Client<RequestOption> {
164165
* Request URI: /get/books/{id}
165166
*/
166167
public async getBookById(params: Params$getBookById, option?: RequestOption): Promise<Response$getBookById$Status$200[\\"application/json\\"]> {
167-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/books/\${params.parameter.id}\`;
168+
const url = this.baseUrl + \`/get/books/\${params.parameter.id}\`;
168169
const headers = {
169170
Accept: \\"application/json\\"
170171
};
@@ -175,7 +176,7 @@ export class Client<RequestOption> {
175176
* Request URI: /get/books/{id}
176177
*/
177178
public async deleteBook(params: Params$deleteBook, option?: RequestOption): Promise<Response$deleteBook$Status$200[\\"application/json\\"]> {
178-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/books/\${params.parameter.id}\`;
179+
const url = this.baseUrl + \`/get/books/\${params.parameter.id}\`;
179180
const headers = {
180181
Accept: \\"application/json\\"
181182
};

test/__tests__/__snapshots__/template-only-test.ts.snap

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ export interface ApiClient<RequestOption> {
5757
request: <T = SuccessResponses>(httpMethod: HttpMethod, url: string, headers: ObjectLike | any, requestBody: ObjectLike | any, queryParameters: QueryParameters | undefined, options?: RequestOption) => Promise<T>;
5858
}
5959
export class Client<RequestOption> {
60-
constructor(private apiClient: ApiClient<RequestOption>, private baseUrl: string) { }
60+
private baseUrl: string;
61+
constructor(private apiClient: ApiClient<RequestOption>, baseUrl: string) { this.baseUrl = baseUrl.replace(/\\\\/$/, \\"\\"); }
6162
public async getIncludeLocalReference(params: Params$getIncludeLocalReference, option?: RequestOption): Promise<Response$getIncludeLocalReference$Status$200[\\"application/json\\"]> {
62-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/IncludeLocalReference\`;
63+
const url = this.baseUrl + \`/get/IncludeLocalReference\`;
6364
const headers = {
6465
Accept: \\"application/json\\"
6566
};
@@ -69,7 +70,7 @@ export class Client<RequestOption> {
6970
return this.apiClient.request(\\"GET\\", url, headers, undefined, queryParameters, option);
7071
}
7172
public async getIncludeRemoteReference(params: Params$getIncludeRemoteReference, option?: RequestOption): Promise<void> {
72-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/IncludeRemoteReference\`;
73+
const url = this.baseUrl + \`/get/IncludeRemoteReference\`;
7374
const headers = {
7475
\\"Content-Type\\": \\"application/json\\"
7576
};
@@ -79,7 +80,7 @@ export class Client<RequestOption> {
7980
return this.apiClient.request(\\"GET\\", url, headers, params.requestBody, queryParameters, option);
8081
}
8182
public async getFullRemoteReference(params: Params$getFullRemoteReference, option?: RequestOption): Promise<Response$getFullRemoteReference$Status$200[\\"application/json\\"]> {
82-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/FullRemoteReference\`;
83+
const url = this.baseUrl + \`/FullRemoteReference\`;
8384
const headers = {
8485
Accept: \\"application/json\\"
8586
};
@@ -89,21 +90,21 @@ export class Client<RequestOption> {
8990
return this.apiClient.request(\\"GET\\", url, headers, undefined, queryParameters, option);
9091
}
9192
public async getReferenceItems(option?: RequestOption): Promise<Response$getReferenceItems$Status$200[\\"application/json\\"]> {
92-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/reference/items\`;
93+
const url = this.baseUrl + \`/get/reference/items\`;
9394
const headers = {
9495
Accept: \\"application/json\\"
9596
};
9697
return this.apiClient.request(\\"GET\\", url, headers, undefined, undefined, option);
9798
}
9899
public async getBookById(params: Params$getBookById, option?: RequestOption): Promise<Response$getBookById$Status$200[\\"application/json\\"]> {
99-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/books/\${params.parameter.id}\`;
100+
const url = this.baseUrl + \`/get/books/\${params.parameter.id}\`;
100101
const headers = {
101102
Accept: \\"application/json\\"
102103
};
103104
return this.apiClient.request(\\"GET\\", url, headers, undefined, undefined, option);
104105
}
105106
public async deleteBook(params: Params$deleteBook, option?: RequestOption): Promise<Response$deleteBook$Status$200[\\"application/json\\"]> {
106-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/books/\${params.parameter.id}\`;
107+
const url = this.baseUrl + \`/get/books/\${params.parameter.id}\`;
107108
const headers = {
108109
Accept: \\"application/json\\"
109110
};
@@ -170,9 +171,10 @@ export interface ApiClient<RequestOption> {
170171
request: <T = SuccessResponses>(httpMethod: HttpMethod, url: string, headers: ObjectLike | any, requestBody: ObjectLike | any, queryParameters: QueryParameters | undefined, options?: RequestOption) => T;
171172
}
172173
export class Client<RequestOption> {
173-
constructor(private apiClient: ApiClient<RequestOption>, private baseUrl: string) { }
174+
private baseUrl: string;
175+
constructor(private apiClient: ApiClient<RequestOption>, baseUrl: string) { this.baseUrl = baseUrl.replace(/\\\\/$/, \\"\\"); }
174176
public getIncludeLocalReference(params: Params$getIncludeLocalReference, option?: RequestOption): Response$getIncludeLocalReference$Status$200[\\"application/json\\"] {
175-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/IncludeLocalReference\`;
177+
const url = this.baseUrl + \`/get/IncludeLocalReference\`;
176178
const headers = {
177179
Accept: \\"application/json\\"
178180
};
@@ -182,7 +184,7 @@ export class Client<RequestOption> {
182184
return this.apiClient.request(\\"GET\\", url, headers, undefined, queryParameters, option);
183185
}
184186
public getIncludeRemoteReference(params: Params$getIncludeRemoteReference, option?: RequestOption): void {
185-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/IncludeRemoteReference\`;
187+
const url = this.baseUrl + \`/get/IncludeRemoteReference\`;
186188
const headers = {
187189
\\"Content-Type\\": \\"application/json\\"
188190
};
@@ -192,7 +194,7 @@ export class Client<RequestOption> {
192194
return this.apiClient.request(\\"GET\\", url, headers, params.requestBody, queryParameters, option);
193195
}
194196
public getFullRemoteReference(params: Params$getFullRemoteReference, option?: RequestOption): Response$getFullRemoteReference$Status$200[\\"application/json\\"] {
195-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/FullRemoteReference\`;
197+
const url = this.baseUrl + \`/FullRemoteReference\`;
196198
const headers = {
197199
Accept: \\"application/json\\"
198200
};
@@ -202,21 +204,21 @@ export class Client<RequestOption> {
202204
return this.apiClient.request(\\"GET\\", url, headers, undefined, queryParameters, option);
203205
}
204206
public getReferenceItems(option?: RequestOption): Response$getReferenceItems$Status$200[\\"application/json\\"] {
205-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/reference/items\`;
207+
const url = this.baseUrl + \`/get/reference/items\`;
206208
const headers = {
207209
Accept: \\"application/json\\"
208210
};
209211
return this.apiClient.request(\\"GET\\", url, headers, undefined, undefined, option);
210212
}
211213
public getBookById(params: Params$getBookById, option?: RequestOption): Response$getBookById$Status$200[\\"application/json\\"] {
212-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/books/\${params.parameter.id}\`;
214+
const url = this.baseUrl + \`/get/books/\${params.parameter.id}\`;
213215
const headers = {
214216
Accept: \\"application/json\\"
215217
};
216218
return this.apiClient.request(\\"GET\\", url, headers, undefined, undefined, option);
217219
}
218220
public deleteBook(params: Params$deleteBook, option?: RequestOption): Response$deleteBook$Status$200[\\"application/json\\"] {
219-
const url = this.baseUrl.replace(/\\\\/$/, \\"\\") + \`/get/books/\${params.parameter.id}\`;
221+
const url = this.baseUrl + \`/get/books/\${params.parameter.id}\`;
220222
const headers = {
221223
Accept: \\"application/json\\"
222224
};
@@ -254,7 +256,8 @@ export interface ApiClient<RequestOption> {
254256
request: <T = SuccessResponses>(httpMethod: HttpMethod, url: string, headers: ObjectLike | any, requestBody: ObjectLike | any, queryParameters: QueryParameters | undefined, options?: RequestOption) => T;
255257
}
256258
export class Client<RequestOption> {
257-
constructor(private apiClient: ApiClient<RequestOption>, private baseUrl: string) { }
259+
private baseUrl: string;
260+
constructor(private apiClient: ApiClient<RequestOption>, baseUrl: string) { this.baseUrl = baseUrl.replace(/\\\\/$/, \\"\\"); }
258261
}
259262
"
260263
`;

0 commit comments

Comments
 (0)