Skip to content

Commit

Permalink
[TypeScript][Aurelia] Create Aurelia code generator swagger-api#5987 (s…
Browse files Browse the repository at this point in the history
…wagger-api#5991)

* [TypeScript][Aurelia] Create Aurelia code generator swagger-api#5987

* Implement authentication methods for Aurelia swagger-api#5987

* Support form data in Aurelia swagger-api#5987

* Generate an index.ts file for Aurelia swagger-api#5987

* Add return type to Aurelia model imports swagger-api#5987

* Add Aurelia client options test swagger-api#5987
  • Loading branch information
ksm2 authored and wing328 committed Jul 23, 2017
1 parent e298964 commit 21619c5
Show file tree
Hide file tree
Showing 16 changed files with 731 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package io.swagger.codegen.languages;

import io.swagger.codegen.*;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

public class TypeScriptAureliaClientCodegen extends AbstractTypeScriptClientCodegen {

public static final String NPM_NAME = "npmName";
public static final String NPM_VERSION = "npmVersion";

protected String npmName = null;
protected String npmVersion = "1.0.0";

public TypeScriptAureliaClientCodegen() {
super();

apiTemplateFiles.put("api.mustache", ".ts");

// clear import mapping (from default generator) as TS does not use it
// at the moment
importMapping.clear();

outputFolder = "generated-code/typescript-aurelia";
embeddedTemplateDir = templateDir = "typescript-aurelia";
this.cliOptions.add(new CliOption(NPM_NAME, "The name under which you want to publish generated npm package"));
this.cliOptions.add(new CliOption(NPM_VERSION, "The version of your npm package"));
}

@Override
public void processOpts() {
super.processOpts();

if (additionalProperties.containsKey(NPM_NAME)) {
this.setNpmName(additionalProperties.get(NPM_NAME).toString());
}

if (additionalProperties.containsKey(NPM_VERSION)) {
this.setNpmVersion(additionalProperties.get(NPM_VERSION).toString());
}

// Set supporting files
supportingFiles.add(new SupportingFile("models.mustache", "", "models.ts"));
supportingFiles.add(new SupportingFile("index.ts.mustache", "", "index.ts"));
supportingFiles.add(new SupportingFile("Api.ts.mustache", "", "Api.ts"));
supportingFiles.add(new SupportingFile("AuthStorage.ts.mustache", "", "AuthStorage.ts"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
supportingFiles.add(new SupportingFile("package.json.mustache", "", "package.json"));
supportingFiles.add(new SupportingFile("tsconfig.json.mustache", "", "tsconfig.json"));
supportingFiles.add(new SupportingFile("tslint.json.mustache", "", "tslint.json"));
supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore"));
}

@Override
public String getName() {
return "typescript-aurelia";
}

@Override
public String getHelp() {
return "Generates a TypeScript client library for the Aurelia framework (beta).";
}

public String getNpmName() {
return npmName;
}

public void setNpmName(String npmName) {
this.npmName = npmName;
}

public String getNpmVersion() {
return npmVersion;
}

public void setNpmVersion(String npmVersion) {
this.npmVersion = npmVersion;
}

@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
objs = super.postProcessOperations(objs);

HashSet<String> modelImports = new HashSet<>();
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation op : operationList) {
// Aurelia uses "asGet", "asPost", ... methods; change the method format
op.httpMethod = initialCaps(op.httpMethod.toLowerCase());

// Collect models to be imported
for (CodegenParameter param : op.allParams) {
if (!param.isPrimitiveType) {
modelImports.add(param.dataType);
}
}
if (op.returnBaseType != null && !op.returnTypeIsPrimitive) {
modelImports.add(op.returnBaseType);
}
}

objs.put("modelImports", modelImports);

return objs;
}

@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
// process enum in models
List<Object> models = (List<Object>) postProcessModelsEnum(objs).get("models");
for (Object _mo : models) {
Map<String, Object> mo = (Map<String, Object>) _mo;
CodegenModel cm = (CodegenModel) mo.get("model");
cm.imports = new TreeSet(cm.imports);
for (CodegenProperty var : cm.vars) {
// name enum with model name, e.g. StatuEnum => PetStatusEnum
if (Boolean.TRUE.equals(var.isEnum)) {
var.datatypeWithEnum = var.datatypeWithEnum.replace(var.enumName, cm.classname + var.enumName);
var.enumName = cm.classname + var.enumName;
}
}
}

return objs;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ io.swagger.codegen.languages.SwiftCodegen
io.swagger.codegen.languages.TizenClientCodegen
io.swagger.codegen.languages.TypeScriptAngular2ClientCodegen
io.swagger.codegen.languages.TypeScriptAngularClientCodegen
io.swagger.codegen.languages.TypeScriptAureliaClientCodegen
io.swagger.codegen.languages.TypeScriptFetchClientCodegen
io.swagger.codegen.languages.TypeScriptJqueryClientCodegen
io.swagger.codegen.languages.TypeScriptNodeClientCodegen
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{{>licenseInfo}}
import { HttpClient } from 'aurelia-http-client';
import { AuthStorage } from './AuthStorage';

const BASE_PATH = '{{{basePath}}}'.replace(/\/+$/, '');

export class Api {
basePath: string;
httpClient: HttpClient;
authStorage: AuthStorage;
constructor(httpClient: HttpClient, authStorage: AuthStorage, basePath: string = BASE_PATH) {
this.basePath = basePath;
this.httpClient = httpClient;
this.authStorage = authStorage;
}

/**
* Encodes a query string.
*
* @param params The params to encode.
* @return An encoded query string.
*/
protected queryString(params: { [key: string]: any }): string {
const queries = [];
for (let key in params) {
const value = this.toString(params[key]);
if (value != null) {
queries.push(`${key}=${encodeURIComponent(value)}`);
}
}

return queries.join('&');
}

/**
* Converts a value to string.
*
* @param value The value to convert.
*/
protected toString(value: any): string | null {
if (value === null) {
return null;
}
switch (typeof value) {
case 'undefined': return null;
case 'boolean': return value ? 'true' : 'false';
case 'string': return value;
default: return '' + value;
}
}

/**
* Ensures that a given parameter is set.
*
* @param context A name for the callee's context.
* @param params The parameters being set.
* @param paramName The required parameter to check.
*/
protected ensureParamIsSet<T>(context: string, params: T, paramName: keyof T): void {
if (null === params[paramName]) {
throw new Error(`Missing required parameter ${paramName} when calling ${context}`);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{{>licenseInfo}}
/**
* Class to storage authentication data
*/
export class AuthStorage {
private storage: Map<string, string>;
constructor() {
this.storage = new Map();
}
{{#authMethods}}

/**
* Sets the {{name}} auth method value.
*
* @param value The new value to set for {{name}}.
*/
set{{name}}(value: string): this {
this.storage.set('{{name}}', value);
return this;
}

/**
* Removes the {{name}} auth method value.
*/
remove{{name}}(): this {
this.storage.delete('{{name}}');
return this;
}

/**
* Gets the {{name}} auth method value.
*/
get{{name}}(): null | string {
return this.storage.get('{{name}}') || null;
}
{{/authMethods}}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# TypeScript-Aurelia

This generator creates TypeScript/JavaScript client that is injectable by [Aurelia](http://aurelia.io/).
The generated Node module can be used in the following environments:

Environment
* Node.js
* Webpack
* Browserify

Language level
* ES5 - you must have a Promises/A+ library installed
* ES6

Module system
* CommonJS
* ES6 module system

It can be used in both TypeScript and JavaScript. In TypeScript, the definition should be automatically resolved via `package.json`. ([Reference](http://www.typescriptlang.org/docs/handbook/typings-for-npm-packages.html))

### Installation ###

`swagger-codegen` does not generate JavaScript directly. The generated Node module comes with `package.json` that bundles `typescript` and `typings` so it can self-compile during `prepublish` stage. The should be run automatically during `npm install` or `npm publish`.

CAVEAT: Due to [privilege implications](https://docs.npmjs.com/misc/scripts#user), `npm` would skip all scripts if the user is `root`. You would need to manually run it with `npm run prepublish` or run `npm install --unsafe-perm`.

#### NPM ####
You may publish the module to NPM. In this case, you would be able to install the module as any other NPM module. It maybe useful to use [scoped packages](https://docs.npmjs.com/misc/scope).

You can also use `npm link` to link the module. However, this would not modify `package.json` of the installing project, as such you would need to relink every time you deploy that project.

You can also directly install the module using `npm install file_path`. If you do `npm install file_path --save`, NPM will save relative path to `package.json`. In this case, `npm install` and `npm shrinkwrap` may misbehave. You would need to manually edit `package.json` and replace it with absolute path.

Regardless of which method you deployed your NPM module, the ES6 module syntaxes are as follows:
```
import * as localName from 'npmName';
import {operationId} from 'npmName';
```
The CommonJS syntax is as follows:
```
import localName = require('npmName');
```

#### Direct copy/symlink ####
You may also simply copy or symlink the generated module into a directory under your project. The syntax of this is as follows:

With ES6 module syntax, the following syntaxes are supported:
```
import * as localName from './symlinkDir';
import {operationId} from './symlinkDir';
```
The CommonJS syntax is as follows:
```
import localName = require('./symlinkDir')';
```
Loading

0 comments on commit 21619c5

Please sign in to comment.