I use swagger-codegen with the -l typescript-angular
option to generate a library of REST consumer services. The generated code looks like this (DefaultApi.ts
):
namespace API.Client {
'use strict';
export class DefaultApi {
protected basePath = 'http://localhost:7331/v1';
public defaultHeaders : any = {};
static $inject: string[] = ['$http', '$httpParamSerializer', 'basePath'];
constructor(protected $http: ng.IHttpService, protected $httpParamSerializer?: (d: any) => any, basePath?: string) {
if (basePath !== undefined) {
this.basePath = basePath;
}
}
private extendObj<T1,T2>(objA: T1, objB: T2) {
for(let key in objB){
if(objB.hasOwnProperty(key)){
objA[key] = objB[key];
}
}
return <T1&T2>objA;
}
/**
* Delete a person.
* Deletes a specified individual and all of that person's connections.
* @param id The id of the person to delete
*/
public deletePersonById (id: number, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> {/*...*/}
/* etc... */
}
}
As you can see, there are concrete classes that need to be used but are declared inside of a namespace, i.e. not import
able. My editor (VSCode) doesn't complain when I reference API.Client.DefaultApi
despite the lack of an import
because it picks up the definition as part of a declared namespace I suppose. But at run-time the browser complains that API
is not defined.
I am using webpack to bundle my code. I see a few other questions on SO that are kind of like this one, but had no luck with the answers there.
EDIT:
As requested, here are my configuration files for ts and webpack:
webpack config file:
const webpack = require('webpack');
const conf = require('./gulp.conf');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer');
module.exports = {
module: {
preLoaders: [
{
test: /\.ts$/,
exclude: /node_modules/,
loader: 'tslint'
}
],
loaders: [
{
test: /.json$/,
loaders: [
'json'
]
},
{
test: /\.(css|less)$/,
loaders: [
'style',
'css',
'less',
'postcss'
]
},
{
test: /\.ts$/,
exclude: /node_modules/,
loaders: [
'ng-annotate',
'ts'
]
},
{
test: /.html$/,
loaders: [
'html'
]
}
]
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.NoErrorsPlugin(),
new HtmlWebpackPlugin({
template: conf.path.src('index.html')
})
],
postcss: () => [autoprefixer],
debug: true,
devtool: 'source-map',
output: {
path: path.join(process.cwd(), conf.paths.tmp),
filename: 'index.js'
},
resolve: {
modules: [
path.resolve(__dirname, '../src/app'),
path.resolve(__dirname, '../node_modules')
],
extensions: [
'',
'.webpack.js',
'.web.js',
'.js',
'.ts'
]
},
entry: `./${conf.path.src('index')}`,
ts: {
configFileName: '../tsconfig.json'
},
tslint: {
configuration: require('../tslint.json')
}
};
tsconfig.json:
{
"compilerOptions": {
"baseUrl": "src/app",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false,
"module": "commonjs"
},
"compileOnSave": false,
"include": [
"src/**/*.ts"
],
"exclude": [
"!typings/**",
"!node_modules/**"
]
}
You have two options to fix this, an ease and another complex:
Add the following code at the end of generated code:
export = API.Client;
Now, you can use import
in your modules without problems, eg:
import {DefaultApi} from './generated-code';
The idea:
Split the modular code and not modular code with differents tsconfig. Mix modular code and not modular with Salsa, webpack resolve alias and javascript support.
Tutorial:
TL;DR Here a GitHub repository applying this solution.
{
"compilerOptions": {
"outFile": "module-generated-code.js"
},
"files": ["generated-code.ts"]
}
{
"compilerOptions": {
},
"exclude": ["generated-code.ts"]
}
api.js
file and reference it in your tsconfig.generate.json
. Yes, it is a js file, it is here that Salsa gets into action. And to do this you must enable allowJs
feature in tsconfig{
"compilerOptions": {
"outFile": "module-generate-code.js", "allowJs": true
},
"files": ["generated-code.ts", "api.js"]
}
These files are basically to export via commonjs your generated code without touch it.
/// <reference path="./namespacing-code.ts" />
// typescript compiler don't warning this because is Salsa!
module.exports = API.Client;
Now, note in tsconfig.generate.json
and your outFile
property. If you test the compiler (tsc -p tsconfig.generate.json
), you see all your generated files concatenated in module-generate-code.js
, and the last line must be like in this:
module.exports = API.Client;
Nearly Done!
Now, you can use the module-generate-code.js
in your own code with import
! But how js files do not have the best definitions, then you have config a resolve.alias in webpack.config and tsconfig.json
{ //webpack.config
resolve: {
extensions: ['', '.webpack.js', '.web.js', '.ts', '.js'],
alias:{ 'api':'./module-generated-code.js'
}
}
{ //tsconfig.json
"compilerOptions": {
"allowJs": true, //remember of enabling Salsa here too
"baseUrl": ".",
"paths": {
"api":["api.js"] //it is just get type definitions from generated files
}
},
Now you can use your generate code without touch it: import api from 'api';
Any doubt, here a GitHub repo using this approach. I hope I´ve helped
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With