Skip to content

Commit 097acb7

Browse files
authored
Merge pull request #3 from algolia/feat/js-client-custom-template
feat(js): automate with custom templates
2 parents 4b8d926 + 3002913 commit 097acb7

34 files changed

+3702
-10
lines changed

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
node_modules
2+
.bash_profile
3+
.env
4+
dist
5+
.pnp.cjs
6+
7+
yarn-error.log
8+
9+
.yarn/*
10+
!.yarn/releases
11+
!.yarn/plugins
12+
13+
*/.openapi-generator
14+
*/node_modules
15+
*/dist
16+
*/.openapi-generator-ignore

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
16.13.0

.prettierrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"trailingComma": "es5",
3+
"singleQuote": true,
4+
"printWidth": 100
5+
}

.yarn/releases/yarn-3.0.2.cjs

Lines changed: 631 additions & 0 deletions
Large diffs are not rendered by default.

.yarnrc.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
nodeLinker: node-modules
2+
3+
yarnPath: .yarn/releases/yarn-3.0.2.cjs

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# How to run
2+
3+
## Install and setup env
4+
5+
```bash
6+
nvm use && yarn
7+
```
8+
9+
## Generate client based on `search_spec.yml`
10+
11+
```bash
12+
yarn generate
13+
```
14+
15+
## Build generated client
16+
17+
```bash
18+
yarn client:build
19+
```
20+
21+
## Test built client response
22+
23+
```bash
24+
yarn client:test
25+
```
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{{#apiInfo}}
2+
{{#apis}}
3+
{{#operations}}
4+
export * from './{{ classFilename }}';
5+
import { {{ classname }} } from './{{ classFilename }}';
6+
{{/operations}}
7+
{{#withInterfaces}}
8+
export * from './{{ classFilename }}Interface'
9+
{{/withInterfaces}}
10+
{{/apis}}
11+
import * as http from 'http';
12+
13+
export class HttpError extends Error {
14+
constructor (public response: http.IncomingMessage, public body: any, public statusCode?: number) {
15+
super('HTTP request failed');
16+
this.name = 'HttpError';
17+
}
18+
}
19+
20+
export { RequestFile } from '../model/models';
21+
22+
export const APIS = [{{#apis}}{{#operations}}{{ classname }}{{/operations}}{{^-last}}, {{/-last}}{{/apis}}];
23+
{{/apiInfo}}
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
import localVarRequest from 'request';
2+
import http from 'http';
3+
4+
{{#imports}}
5+
import { {{classname}} } from '{{filename}}';
6+
{{/imports}}
7+
8+
import { ObjectSerializer, Authentication, VoidAuth, Interceptor } from '../model/models';
9+
{{#hasAuthMethods}}
10+
import { HttpBasicAuth, HttpBearerAuth, ApiKeyAuth, OAuth } from '../model/models';
11+
{{/hasAuthMethods}}
12+
13+
import { HttpError, RequestFile } from './apis';
14+
15+
let defaultBasePath = '{{{basePath}}}';
16+
17+
// ===============================================
18+
// This file is autogenerated - Please do not edit
19+
// ===============================================
20+
21+
{{#operations}}
22+
{{#description}}
23+
/**
24+
* {{&description}}
25+
*/
26+
{{/description}}
27+
export enum {{classname}}ApiKeys {
28+
{{#authMethods}}
29+
{{#isApiKey}}
30+
{{name}},
31+
{{/isApiKey}}
32+
{{/authMethods}}
33+
}
34+
35+
export class {{classname}} {
36+
protected _basePath = defaultBasePath;
37+
protected _defaultHeaders : any = {};
38+
protected _useQuerystring : boolean = false;
39+
40+
protected authentications = {
41+
'default': <Authentication>new VoidAuth(),
42+
{{#hasAuthMethods}}
43+
{{#authMethods}}
44+
{{#isBasicBasic}}
45+
'{{name}}': new HttpBasicAuth(),
46+
{{/isBasicBasic}}
47+
{{#isBasicBearer}}
48+
'{{name}}': new HttpBearerAuth(),
49+
{{/isBasicBearer}}
50+
{{#isApiKey}}
51+
'{{name}}': new ApiKeyAuth({{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}{{#isKeyInCookie}}'cookie'{{/isKeyInCookie}}, '{{keyParamName}}'),
52+
{{/isApiKey}}
53+
{{#isOAuth}}
54+
'{{name}}': new OAuth(),
55+
{{/isOAuth}}
56+
{{/authMethods}}
57+
{{/hasAuthMethods}}
58+
}
59+
60+
protected interceptors: Interceptor[] = [];
61+
62+
constructor(basePath?: string);
63+
{{#authMethods}}
64+
{{#isBasicBasic}}
65+
constructor(username: string, password: string, basePath?: string);
66+
{{/isBasicBasic}}
67+
{{/authMethods}}
68+
constructor(basePathOrUsername: string, password?: string, basePath?: string) {
69+
if (password) {
70+
{{#authMethods}}
71+
{{#isBasicBasic}}
72+
this.username = basePathOrUsername;
73+
this.password = password
74+
{{/isBasicBasic}}
75+
{{/authMethods}}
76+
if (basePath) {
77+
this.basePath = basePath;
78+
}
79+
} else {
80+
if (basePathOrUsername) {
81+
this.basePath = basePathOrUsername
82+
}
83+
}
84+
}
85+
86+
set useQuerystring(value: boolean) {
87+
this._useQuerystring = value;
88+
}
89+
90+
set basePath(basePath: string) {
91+
this._basePath = basePath;
92+
}
93+
94+
set defaultHeaders(defaultHeaders: any) {
95+
this._defaultHeaders = defaultHeaders;
96+
}
97+
98+
get defaultHeaders() {
99+
return this._defaultHeaders;
100+
}
101+
102+
get basePath() {
103+
return this._basePath;
104+
}
105+
106+
public setDefaultAuthentication(auth: Authentication) {
107+
this.authentications.default = auth;
108+
}
109+
110+
public setApiKey(key: {{classname}}ApiKeys, value: string) {
111+
(this.authentications as any)[{{classname}}ApiKeys[key]].apiKey = value;
112+
}
113+
{{#hasAuthMethods}}
114+
{{#authMethods}}
115+
{{#isBasicBasic}}
116+
117+
set username(username: string) {
118+
this.authentications.{{name}}.username = username;
119+
}
120+
121+
set password(password: string) {
122+
this.authentications.{{name}}.password = password;
123+
}
124+
{{/isBasicBasic}}
125+
{{#isBasicBearer}}
126+
127+
set accessToken(accessToken: string | (() => string)) {
128+
this.authentications.{{name}}.accessToken = accessToken;
129+
}
130+
{{/isBasicBearer}}
131+
{{#isOAuth}}
132+
133+
set accessToken(token: string) {
134+
this.authentications.{{name}}.accessToken = token;
135+
}
136+
{{/isOAuth}}
137+
{{/authMethods}}
138+
{{/hasAuthMethods}}
139+
140+
public addInterceptor(interceptor: Interceptor) {
141+
this.interceptors.push(interceptor);
142+
}
143+
144+
{{#operation}}
145+
/**
146+
* {{&notes}}
147+
{{#summary}}
148+
* @summary {{&summary}}
149+
{{/summary}}
150+
{{#allParams}}
151+
* @param {{paramName}} {{description}}
152+
{{/allParams}}
153+
*/
154+
public async {{nickname}} ({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options: {headers: {[name: string]: string}} = {headers: {}}) : Promise<{ response: http.IncomingMessage; {{#returnType}}body: {{{returnType}}}; {{/returnType}}{{^returnType}}body?: any; {{/returnType}} }> {
155+
const localVarPath = this.basePath + '{{{path}}}'{{#pathParams}}
156+
.replace('{' + '{{baseName}}' + '}', encodeURIComponent(String({{paramName}}))){{/pathParams}};
157+
let localVarQueryParameters: any = {};
158+
let localVarHeaderParams: any = (<any>Object).assign({}, this._defaultHeaders);
159+
{{#hasProduces}}
160+
const produces = [{{#produces}}'{{{mediaType}}}'{{^-last}}, {{/-last}}{{/produces}}];
161+
// give precedence to 'application/json'
162+
if (produces.indexOf('application/json') >= 0) {
163+
localVarHeaderParams.Accept = 'application/json';
164+
} else {
165+
localVarHeaderParams.Accept = produces.join(',');
166+
}
167+
{{/hasProduces}}
168+
let localVarFormParams: any = {};
169+
170+
{{#allParams}}
171+
{{#required}}
172+
// verify required parameter '{{paramName}}' is not null or undefined
173+
if ({{paramName}} === null || {{paramName}} === undefined) {
174+
throw new Error('Required parameter {{paramName}} was null or undefined when calling {{nickname}}.');
175+
}
176+
177+
{{/required}}
178+
{{/allParams}}
179+
{{#queryParams}}
180+
if ({{paramName}} !== undefined) {
181+
localVarQueryParameters['{{baseName}}'] = ObjectSerializer.serialize({{paramName}}, "{{{dataType}}}");
182+
}
183+
184+
{{/queryParams}}
185+
{{#headerParams}}
186+
localVarHeaderParams['{{baseName}}'] = ObjectSerializer.serialize({{paramName}}, "{{{dataType}}}");
187+
{{/headerParams}}
188+
(<any>Object).assign(localVarHeaderParams, options.headers);
189+
190+
let localVarUseFormData = false;
191+
192+
{{#formParams}}
193+
if ({{paramName}} !== undefined) {
194+
{{#isFile}}
195+
localVarFormParams['{{baseName}}'] = {{paramName}};
196+
{{/isFile}}
197+
{{^isFile}}
198+
localVarFormParams['{{baseName}}'] = ObjectSerializer.serialize({{paramName}}, "{{{dataType}}}");
199+
{{/isFile}}
200+
}
201+
{{#isFile}}
202+
localVarUseFormData = true;
203+
{{/isFile}}
204+
205+
{{/formParams}}
206+
let localVarRequestOptions: localVarRequest.Options = {
207+
method: '{{httpMethod}}',
208+
qs: localVarQueryParameters,
209+
headers: localVarHeaderParams,
210+
uri: localVarPath,
211+
useQuerystring: this._useQuerystring,
212+
{{^isResponseFile}}
213+
json: true,
214+
{{/isResponseFile}}
215+
{{#isResponseFile}}
216+
encoding: null,
217+
{{/isResponseFile}}
218+
{{#bodyParam}}
219+
body: ObjectSerializer.serialize({{paramName}}, "{{{dataType}}}")
220+
{{/bodyParam}}
221+
};
222+
223+
let authenticationPromise = Promise.resolve();
224+
{{#authMethods}}
225+
{{#isApiKey}}
226+
if (this.authentications.{{name}}.apiKey) {
227+
authenticationPromise = authenticationPromise.then(() => this.authentications.{{name}}.applyToRequest(localVarRequestOptions));
228+
}
229+
{{/isApiKey}}
230+
{{#isBasicBasic}}
231+
if (this.authentications.{{name}}.username && this.authentications.{{name}}.password) {
232+
authenticationPromise = authenticationPromise.then(() => this.authentications.{{name}}.applyToRequest(localVarRequestOptions));
233+
}
234+
{{/isBasicBasic}}
235+
{{#isBasicBearer}}
236+
if (this.authentications.{{name}}.accessToken) {
237+
authenticationPromise = authenticationPromise.then(() => this.authentications.{{name}}.applyToRequest(localVarRequestOptions));
238+
}
239+
{{/isBasicBearer}}
240+
{{#isOAuth}}
241+
if (this.authentications.{{name}}.accessToken) {
242+
authenticationPromise = authenticationPromise.then(() => this.authentications.{{name}}.applyToRequest(localVarRequestOptions));
243+
}
244+
{{/isOAuth}}
245+
{{/authMethods}}
246+
authenticationPromise = authenticationPromise.then(() => this.authentications.default.applyToRequest(localVarRequestOptions));
247+
248+
let interceptorPromise = authenticationPromise;
249+
for (const interceptor of this.interceptors) {
250+
interceptorPromise = interceptorPromise.then(() => interceptor(localVarRequestOptions));
251+
}
252+
253+
return interceptorPromise.then(() => {
254+
if (Object.keys(localVarFormParams).length) {
255+
if (localVarUseFormData) {
256+
(<any>localVarRequestOptions).formData = localVarFormParams;
257+
} else {
258+
localVarRequestOptions.form = localVarFormParams;
259+
}
260+
}
261+
return new Promise<{ response: http.IncomingMessage; {{#returnType}}body: {{{returnType}}}; {{/returnType}}{{^returnType}}body?: any; {{/returnType}} }>((resolve, reject) => {
262+
localVarRequest(localVarRequestOptions, (error, response, body) => {
263+
if (error) {
264+
reject(error);
265+
} else {
266+
{{#returnType}}
267+
body = ObjectSerializer.deserialize(body, "{{{returnType}}}");
268+
{{/returnType}}
269+
if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) {
270+
resolve({ response: response, body: body });
271+
} else {
272+
reject(new HttpError(response, body, response.statusCode));
273+
}
274+
}
275+
});
276+
});
277+
});
278+
}
279+
{{/operation}}
280+
}
281+
{{/operations}}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// This is the entrypoint for the package
2+
export * from './client-search/apis';
3+
export * from './model/models';

algolia-typescript-template/gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
typings
3+
dist
4+
build
5+
.env
6+
.vscode
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* {{{appName}}}
3+
* {{{appDescription}}}
4+
*
5+
* {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}}
6+
* {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}}
7+
*
8+
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
9+
* https://openapi-generator.tech
10+
* Do not edit the class manually.
11+
*/

0 commit comments

Comments
 (0)