Skip to content

Commit

Permalink
Merge pull request #3 from algolia/feat/js-client-custom-template
Browse files Browse the repository at this point in the history
feat(js): automate with custom templates
  • Loading branch information
shortcuts authored Nov 4, 2021
2 parents 4b8d926 + 3002913 commit 097acb7
Show file tree
Hide file tree
Showing 34 changed files with 3,702 additions and 10 deletions.
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
node_modules
.bash_profile
.env
dist
.pnp.cjs

yarn-error.log

.yarn/*
!.yarn/releases
!.yarn/plugins

*/.openapi-generator
*/node_modules
*/dist
*/.openapi-generator-ignore
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
16.13.0
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 100
}
631 changes: 631 additions & 0 deletions .yarn/releases/yarn-3.0.2.cjs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-3.0.2.cjs
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# How to run

## Install and setup env

```bash
nvm use && yarn
```

## Generate client based on `search_spec.yml`

```bash
yarn generate
```

## Build generated client

```bash
yarn client:build
```

## Test built client response

```bash
yarn client:test
```
23 changes: 23 additions & 0 deletions algolia-typescript-template/api-all.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{{#apiInfo}}
{{#apis}}
{{#operations}}
export * from './{{ classFilename }}';
import { {{ classname }} } from './{{ classFilename }}';
{{/operations}}
{{#withInterfaces}}
export * from './{{ classFilename }}Interface'
{{/withInterfaces}}
{{/apis}}
import * as http from 'http';

export class HttpError extends Error {
constructor (public response: http.IncomingMessage, public body: any, public statusCode?: number) {
super('HTTP request failed');
this.name = 'HttpError';
}
}

export { RequestFile } from '../model/models';

export const APIS = [{{#apis}}{{#operations}}{{ classname }}{{/operations}}{{^-last}}, {{/-last}}{{/apis}}];
{{/apiInfo}}
281 changes: 281 additions & 0 deletions algolia-typescript-template/api-single.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
import localVarRequest from 'request';
import http from 'http';

{{#imports}}
import { {{classname}} } from '{{filename}}';
{{/imports}}

import { ObjectSerializer, Authentication, VoidAuth, Interceptor } from '../model/models';
{{#hasAuthMethods}}
import { HttpBasicAuth, HttpBearerAuth, ApiKeyAuth, OAuth } from '../model/models';
{{/hasAuthMethods}}

import { HttpError, RequestFile } from './apis';

let defaultBasePath = '{{{basePath}}}';

// ===============================================
// This file is autogenerated - Please do not edit
// ===============================================

{{#operations}}
{{#description}}
/**
* {{&description}}
*/
{{/description}}
export enum {{classname}}ApiKeys {
{{#authMethods}}
{{#isApiKey}}
{{name}},
{{/isApiKey}}
{{/authMethods}}
}

export class {{classname}} {
protected _basePath = defaultBasePath;
protected _defaultHeaders : any = {};
protected _useQuerystring : boolean = false;

protected authentications = {
'default': <Authentication>new VoidAuth(),
{{#hasAuthMethods}}
{{#authMethods}}
{{#isBasicBasic}}
'{{name}}': new HttpBasicAuth(),
{{/isBasicBasic}}
{{#isBasicBearer}}
'{{name}}': new HttpBearerAuth(),
{{/isBasicBearer}}
{{#isApiKey}}
'{{name}}': new ApiKeyAuth({{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}{{#isKeyInCookie}}'cookie'{{/isKeyInCookie}}, '{{keyParamName}}'),
{{/isApiKey}}
{{#isOAuth}}
'{{name}}': new OAuth(),
{{/isOAuth}}
{{/authMethods}}
{{/hasAuthMethods}}
}

protected interceptors: Interceptor[] = [];

constructor(basePath?: string);
{{#authMethods}}
{{#isBasicBasic}}
constructor(username: string, password: string, basePath?: string);
{{/isBasicBasic}}
{{/authMethods}}
constructor(basePathOrUsername: string, password?: string, basePath?: string) {
if (password) {
{{#authMethods}}
{{#isBasicBasic}}
this.username = basePathOrUsername;
this.password = password
{{/isBasicBasic}}
{{/authMethods}}
if (basePath) {
this.basePath = basePath;
}
} else {
if (basePathOrUsername) {
this.basePath = basePathOrUsername
}
}
}

set useQuerystring(value: boolean) {
this._useQuerystring = value;
}

set basePath(basePath: string) {
this._basePath = basePath;
}

set defaultHeaders(defaultHeaders: any) {
this._defaultHeaders = defaultHeaders;
}

get defaultHeaders() {
return this._defaultHeaders;
}

get basePath() {
return this._basePath;
}

public setDefaultAuthentication(auth: Authentication) {
this.authentications.default = auth;
}

public setApiKey(key: {{classname}}ApiKeys, value: string) {
(this.authentications as any)[{{classname}}ApiKeys[key]].apiKey = value;
}
{{#hasAuthMethods}}
{{#authMethods}}
{{#isBasicBasic}}

set username(username: string) {
this.authentications.{{name}}.username = username;
}

set password(password: string) {
this.authentications.{{name}}.password = password;
}
{{/isBasicBasic}}
{{#isBasicBearer}}

set accessToken(accessToken: string | (() => string)) {
this.authentications.{{name}}.accessToken = accessToken;
}
{{/isBasicBearer}}
{{#isOAuth}}

set accessToken(token: string) {
this.authentications.{{name}}.accessToken = token;
}
{{/isOAuth}}
{{/authMethods}}
{{/hasAuthMethods}}

public addInterceptor(interceptor: Interceptor) {
this.interceptors.push(interceptor);
}

{{#operation}}
/**
* {{&notes}}
{{#summary}}
* @summary {{&summary}}
{{/summary}}
{{#allParams}}
* @param {{paramName}} {{description}}
{{/allParams}}
*/
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}} }> {
const localVarPath = this.basePath + '{{{path}}}'{{#pathParams}}
.replace('{' + '{{baseName}}' + '}', encodeURIComponent(String({{paramName}}))){{/pathParams}};
let localVarQueryParameters: any = {};
let localVarHeaderParams: any = (<any>Object).assign({}, this._defaultHeaders);
{{#hasProduces}}
const produces = [{{#produces}}'{{{mediaType}}}'{{^-last}}, {{/-last}}{{/produces}}];
// give precedence to 'application/json'
if (produces.indexOf('application/json') >= 0) {
localVarHeaderParams.Accept = 'application/json';
} else {
localVarHeaderParams.Accept = produces.join(',');
}
{{/hasProduces}}
let localVarFormParams: any = {};

{{#allParams}}
{{#required}}
// verify required parameter '{{paramName}}' is not null or undefined
if ({{paramName}} === null || {{paramName}} === undefined) {
throw new Error('Required parameter {{paramName}} was null or undefined when calling {{nickname}}.');
}

{{/required}}
{{/allParams}}
{{#queryParams}}
if ({{paramName}} !== undefined) {
localVarQueryParameters['{{baseName}}'] = ObjectSerializer.serialize({{paramName}}, "{{{dataType}}}");
}

{{/queryParams}}
{{#headerParams}}
localVarHeaderParams['{{baseName}}'] = ObjectSerializer.serialize({{paramName}}, "{{{dataType}}}");
{{/headerParams}}
(<any>Object).assign(localVarHeaderParams, options.headers);

let localVarUseFormData = false;

{{#formParams}}
if ({{paramName}} !== undefined) {
{{#isFile}}
localVarFormParams['{{baseName}}'] = {{paramName}};
{{/isFile}}
{{^isFile}}
localVarFormParams['{{baseName}}'] = ObjectSerializer.serialize({{paramName}}, "{{{dataType}}}");
{{/isFile}}
}
{{#isFile}}
localVarUseFormData = true;
{{/isFile}}

{{/formParams}}
let localVarRequestOptions: localVarRequest.Options = {
method: '{{httpMethod}}',
qs: localVarQueryParameters,
headers: localVarHeaderParams,
uri: localVarPath,
useQuerystring: this._useQuerystring,
{{^isResponseFile}}
json: true,
{{/isResponseFile}}
{{#isResponseFile}}
encoding: null,
{{/isResponseFile}}
{{#bodyParam}}
body: ObjectSerializer.serialize({{paramName}}, "{{{dataType}}}")
{{/bodyParam}}
};

let authenticationPromise = Promise.resolve();
{{#authMethods}}
{{#isApiKey}}
if (this.authentications.{{name}}.apiKey) {
authenticationPromise = authenticationPromise.then(() => this.authentications.{{name}}.applyToRequest(localVarRequestOptions));
}
{{/isApiKey}}
{{#isBasicBasic}}
if (this.authentications.{{name}}.username && this.authentications.{{name}}.password) {
authenticationPromise = authenticationPromise.then(() => this.authentications.{{name}}.applyToRequest(localVarRequestOptions));
}
{{/isBasicBasic}}
{{#isBasicBearer}}
if (this.authentications.{{name}}.accessToken) {
authenticationPromise = authenticationPromise.then(() => this.authentications.{{name}}.applyToRequest(localVarRequestOptions));
}
{{/isBasicBearer}}
{{#isOAuth}}
if (this.authentications.{{name}}.accessToken) {
authenticationPromise = authenticationPromise.then(() => this.authentications.{{name}}.applyToRequest(localVarRequestOptions));
}
{{/isOAuth}}
{{/authMethods}}
authenticationPromise = authenticationPromise.then(() => this.authentications.default.applyToRequest(localVarRequestOptions));

let interceptorPromise = authenticationPromise;
for (const interceptor of this.interceptors) {
interceptorPromise = interceptorPromise.then(() => interceptor(localVarRequestOptions));
}

return interceptorPromise.then(() => {
if (Object.keys(localVarFormParams).length) {
if (localVarUseFormData) {
(<any>localVarRequestOptions).formData = localVarFormParams;
} else {
localVarRequestOptions.form = localVarFormParams;
}
}
return new Promise<{ response: http.IncomingMessage; {{#returnType}}body: {{{returnType}}}; {{/returnType}}{{^returnType}}body?: any; {{/returnType}} }>((resolve, reject) => {
localVarRequest(localVarRequestOptions, (error, response, body) => {
if (error) {
reject(error);
} else {
{{#returnType}}
body = ObjectSerializer.deserialize(body, "{{{returnType}}}");
{{/returnType}}
if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) {
resolve({ response: response, body: body });
} else {
reject(new HttpError(response, body, response.statusCode));
}
}
});
});
});
}
{{/operation}}
}
{{/operations}}
3 changes: 3 additions & 0 deletions algolia-typescript-template/api.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This is the entrypoint for the package
export * from './client-search/apis';
export * from './model/models';
6 changes: 6 additions & 0 deletions algolia-typescript-template/gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
typings
dist
build
.env
.vscode
11 changes: 11 additions & 0 deletions algolia-typescript-template/licenseInfo.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* {{{appName}}}
* {{{appDescription}}}
*
* {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}}
* {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}}
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
Loading

0 comments on commit 097acb7

Please sign in to comment.