Skip to content

Commit fe701dc

Browse files
committed
add token provider
1 parent 3409792 commit fe701dc

File tree

5 files changed

+110
-81
lines changed

5 files changed

+110
-81
lines changed

ng-swagger-gen.js

Lines changed: 76 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ function ngSwaggerGen(options) {
2424

2525
$RefParser.bundle(options.swagger,
2626
{ dereference: { circular: false },
27-
resolve: { http: { timeout: options.timeout } } }).then(
28-
data => {
29-
doGenerate(data, options);
30-
},
31-
err => {
32-
console.error(
33-
`Error reading swagger location ${options.swagger}: ${err}`
34-
);
27+
resolve: { http: { timeout: options.timeout } } }).then(
28+
data => {
29+
doGenerate(data, options);
30+
},
31+
err => {
32+
console.error(
33+
`Error reading swagger location ${options.swagger}: ${err}`
34+
);
35+
process.exit(1);
36+
}
37+
).catch(function (error) {
38+
console.error(`Error: ${error}`);
3539
process.exit(1);
36-
}
37-
).catch(function (error) {
38-
console.error(`Error: ${error}`);
39-
process.exit(1);
40-
});
40+
});
4141
}
4242

4343
/**
@@ -121,7 +121,7 @@ function doGenerate(swagger, options) {
121121
if (swagger.swagger !== '2.0') {
122122
console.error(
123123
'Invalid swagger specification. Must be a 2.0. Currently ' +
124-
swagger.swagger
124+
swagger.swagger
125125
);
126126
process.exit(1);
127127
}
@@ -157,14 +157,14 @@ function doGenerate(swagger, options) {
157157
var fallbackTemplates = path.join(__dirname, 'templates');
158158
fs.readdirSync(fallbackTemplates)
159159
.forEach(function (file) {
160-
var pos = file.indexOf('.mustache');
161-
if (pos >= 0) {
162-
var fullFile = path.join(fallbackTemplates, file);
163-
if (!(file.substr(0, pos) in templates)) {
164-
templates[file.substr(0, pos)] = fs.readFileSync(fullFile, 'utf-8');
160+
var pos = file.indexOf('.mustache');
161+
if (pos >= 0) {
162+
var fullFile = path.join(fallbackTemplates, file);
163+
if (!(file.substr(0, pos) in templates)) {
164+
templates[file.substr(0, pos)] = fs.readFileSync(fullFile, 'utf-8');
165+
}
165166
}
166-
}
167-
});
167+
});
168168

169169
// Prepare the output folder
170170
const modelsOutput = path.join(output, 'models');
@@ -248,7 +248,7 @@ function doGenerate(swagger, options) {
248248
var model = models[normalizeModelName(modelName)];
249249
if (basename == model.modelFile + '.ts'
250250
|| basename == model.modelExampleFile + '.ts'
251-
&& model.modelExampleStr != null) {
251+
&& model.modelExampleStr != null) {
252252
ok = true;
253253
break;
254254
}
@@ -318,8 +318,8 @@ function doGenerate(swagger, options) {
318318
var fullModuleFile = path.join(output, moduleFile + '.ts');
319319
if (options.apiModule !== false) {
320320
generate(templates.module, applyGlobals({
321-
services: servicesArray
322-
}),
321+
services: servicesArray
322+
}),
323323
fullModuleFile);
324324
} else if (removeStaleFiles) {
325325
rmIfExists(fullModuleFile);
@@ -339,8 +339,8 @@ function doGenerate(swagger, options) {
339339
}
340340

341341
generate(templates.configuration, applyGlobals({
342-
rootUrl: rootUrl,
343-
}),
342+
rootUrl: rootUrl,
343+
}),
344344
path.join(output, configurationFile + '.ts')
345345
);
346346
}
@@ -416,8 +416,8 @@ function applyTagFilter(models, services, options) {
416416
// This model is not used - remove it
417417
console.info(
418418
'Ignoring model ' +
419-
modelName +
420-
' because it was not used by any service'
419+
modelName +
420+
' because it was not used by any service'
421421
);
422422
delete models[normalizeModelName(modelName)];
423423
}
@@ -632,8 +632,8 @@ function processModels(swagger, options) {
632632
properties = (model.allOf.find(val => !!val.properties) || {}).properties || {};
633633
requiredProperties = (model.allOf.find(val => !!val.required) || {}).required || [];
634634
if (parents && parents.length) {
635-
simpleType = null;
636-
enumValues = null;
635+
simpleType = null;
636+
enumValues = null;
637637
}
638638
} else if (model.type === 'string') {
639639
enumValues = model.enum || [];
@@ -664,7 +664,7 @@ function processModels(swagger, options) {
664664
properties = model.properties || {};
665665
requiredProperties = model.required || [];
666666
additionalPropertiesType = model.additionalProperties &&
667-
(typeof model.additionalProperties === 'object' ? propertyType(model.additionalProperties) : 'any');
667+
(typeof model.additionalProperties === 'object' ? propertyType(model.additionalProperties) : 'any');
668668
} else {
669669
simpleType = propertyType(model);
670670
}
@@ -725,12 +725,12 @@ function processModels(swagger, options) {
725725
model.modelParents = parents
726726
.filter(parentName => !!parentName)
727727
.map(parentName => {
728-
// Make the parent be the actual model, not the name
729-
var parentModel = models[normalizeModelName(parentName)];
728+
// Make the parent be the actual model, not the name
729+
var parentModel = models[normalizeModelName(parentName)];
730730

731-
// Append this model on the parent's subclasses
732-
parentModel.modelSubclasses.push(model);
733-
return parentModel;
731+
// Append this model on the parent's subclasses
732+
parentModel.modelSubclasses.push(model);
733+
return parentModel;
734734
});
735735
model.modelParentNames = model.modelParents.map(
736736
(parent, index) => ({
@@ -892,8 +892,8 @@ function propertyType(property) {
892892
if (Array.isArray(property.items)) { // support for tuples
893893
if (!property.maxItems) return 'Array<any>'; // there is unable to define unlimited tuple in TypeScript
894894
let minItems = property.minItems || 0,
895-
maxItems = property.maxItems,
896-
types = property.items.map(propertyType);
895+
maxItems = property.maxItems,
896+
types = property.items.map(propertyType);
897897
types.push(property.additionalItems ? propertyType(property.additionalItems) : 'any');
898898
let variants = [];
899899
for (let i = minItems; i <= maxItems; i++) variants.push(types.slice(0, i));
@@ -928,15 +928,15 @@ function propertyType(property) {
928928
if (memberCount++) def += ', ';
929929
type = propertyType(prop);
930930
allTypes.push(type);
931-
let required = property.required && property.required.indexOf(name) >= 0;
932-
def += name + (required ? ': ' : '?: ') + type;
931+
let required = property.required && property.required.indexOf(name) >= 0;
932+
def += name + (required ? ': ' : '?: ') + type;
933933
}
934934
}
935935
if (property.additionalProperties) {
936936
if (memberCount++) def += ', ';
937937
type = typeof property.additionalProperties === 'object' ?
938-
propertyType(property.additionalProperties) : 'any';
939-
allTypes.push(type);
938+
propertyType(property.additionalProperties) : 'any';
939+
allTypes.push(type);
940940
def += '[key: string]: ' + type;
941941
}
942942
def += '}';
@@ -1103,25 +1103,25 @@ function operationId(given, method, url, allKnown) {
11031103
if (generate) {
11041104
console.warn(
11051105
"Operation '" +
1106-
method +
1107-
"' on '" +
1108-
url +
1109-
"' defines no operationId. Assuming '" +
1110-
id +
1111-
"'."
1106+
method +
1107+
"' on '" +
1108+
url +
1109+
"' defines no operationId. Assuming '" +
1110+
id +
1111+
"'."
11121112
);
11131113
} else if (duplicated) {
11141114
console.warn(
11151115
"Operation '" +
1116-
method +
1117-
"' on '" +
1118-
url +
1119-
"' defines a duplicated operationId: " +
1120-
given +
1121-
'. ' +
1122-
"Assuming '" +
1123-
id +
1124-
"'."
1116+
method +
1117+
"' on '" +
1118+
url +
1119+
"' defines a duplicated operationId: " +
1120+
given +
1121+
'. ' +
1122+
"Assuming '" +
1123+
id +
1124+
"'."
11251125
);
11261126
}
11271127
allKnown.add(id);
@@ -1139,7 +1139,7 @@ function processServices(swagger, models, options) {
11391139
var sortParams = options.sortParams || 'desc';
11401140
for (var url in swagger.paths) {
11411141
var path = swagger.paths[url];
1142-
var methodParameters = path.parameters;
1142+
var methodParameters = path.parameters;
11431143
for (var method in path || {}) {
11441144
var def = path[method];
11451145
if (!def || method == 'parameters') {
@@ -1167,12 +1167,21 @@ function processServices(swagger, models, options) {
11671167
descriptor.operationIds
11681168
);
11691169

1170+
const hasBearerAuth = !!(def.security && (def.security.filter(v => v && v.hasOwnProperty('bearer'))).length > 0);
1171+
11701172
var parameters = def.parameters || [];
11711173

11721174
if (methodParameters) {
11731175
parameters = parameters.concat(methodParameters);
11741176
}
11751177

1178+
var tokenParameter = null;
1179+
if (hasBearerAuth) {
1180+
const tokenParameterIdx = parameters.findIndex(param => !!(param.in === 'header' && (param.name || '').match(/authorization/i)));
1181+
const param = parameters.splice(tokenParameterIdx, 1)[0];
1182+
tokenParameter = { paramName: param.name, paramIn: param.in };
1183+
}
1184+
11761185
var paramsClass = null;
11771186
var paramsClassComments = null;
11781187
if (parameters.length >= minParamsForContainer) {
@@ -1197,6 +1206,7 @@ function processServices(swagger, models, options) {
11971206
var paramDescriptor = {
11981207
paramName: param.name,
11991208
paramIn: param.in,
1209+
paramPlaceholderVar: 'paramValue_' + paramVar,
12001210
paramVar: paramVar,
12011211
paramFullVar: (paramsClass == null ? '' : 'params.') + paramVar,
12021212
paramRequired: param.required === true || param.in === 'path',
@@ -1296,6 +1306,7 @@ function processServices(swagger, models, options) {
12961306
operationHttpResponseType: '__StrictHttpResponse<' + resultType + '>',
12971307
operationComments: toComments(docString, 1),
12981308
operationParameters: operationParameters,
1309+
tokenParameter: tokenParameter,
12991310
operationResponses: operationResponses,
13001311
};
13011312
var modelResult = models[normalizeModelName(removeBrackets(resultType))];
@@ -1319,13 +1330,13 @@ function processServices(swagger, models, options) {
13191330
operation.operationIsByteArray = actualType === 'ArrayBuffer';
13201331
operation.operationResponseType =
13211332
operation.operationIsFile ? 'blob' :
1322-
operation.operationIsByteArray ? 'arraybuffer' :
1323-
operation.operationIsVoid ||
1324-
operation.operationIsString ||
1325-
operation.operationIsNumber ||
1326-
operation.operationIsBoolean ||
1327-
operation.operationIsEnum ?
1328-
'text' : 'json';
1333+
operation.operationIsByteArray ? 'arraybuffer' :
1334+
operation.operationIsVoid ||
1335+
operation.operationIsString ||
1336+
operation.operationIsNumber ||
1337+
operation.operationIsBoolean ||
1338+
operation.operationIsEnum ?
1339+
'text' : 'json';
13291340
operation.operationIsUnknown = !(
13301341
operation.operationIsVoid ||
13311342
operation.operationIsString ||

templates/baseService.mustache

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* tslint:disable */
22
import { HttpClient, HttpParameterCodec, HttpParams } from '@angular/common/http';
33
import { {{ configurationClass }} } from './{{configurationFile}}';
4+
import { Observable, of } from 'rxjs';
45

56
/**
67
* Custom parameter codec to correctly handle the plus sign in parameter

templates/operationResponse.mustache

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,21 @@
1111
__body = __formData;{{/operationIsMultipart}}
1212
{{#operationParameters}}{{>parameter}}
1313
{{/operationParameters}}
14-
let req = new HttpRequest<any>(
15-
'{{operationMethod}}',
16-
this.rootUrl + `{{{operationPathExpression}}}`,
17-
__body,
18-
{
19-
headers: __headers,
20-
params: __params,
21-
responseType: '{{{operationResponseType}}}'
22-
});
14+
return {{#tokenParameter}}this.tokenProvider('{{paramName}}'){{/tokenParameter}}{{^tokenParameter}}__of(null){{/tokenParameter}}.pipe(
15+
__switchMap(_token => {
16+
{{#tokenParameter}}if (_token != null) __headers = __headers.set('{{paramName}}', _token.toString());
17+
{{/tokenParameter}}let req = new HttpRequest<any>(
18+
'{{operationMethod}}',
19+
this.rootUrl + `{{{operationPathExpression}}}`,
20+
__body,
21+
{
22+
headers: __headers,
23+
params: __params,
24+
responseType: '{{{operationResponseType}}}'
25+
});
2326

24-
return this.http.request<any>(req).pipe(
27+
return this.http.request<any>(req);
28+
}),
2529
__filter(_r => _r instanceof HttpResponse),
2630
__map((_r) => {
2731
{{#operationIsVoid}}return (_r as HttpResponse<any>).clone({ body: null }) as {{{operationHttpResponseType}}}{{/operationIsVoid

templates/service.mustache

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
/* tslint:disable */
2-
import { Injectable } from '@angular/core';
2+
import { Injectable, InjectionToken, Optional, Inject } from '@angular/core';
33
import { HttpClient, HttpRequest, HttpResponse, HttpHeaders } from '@angular/common/http';
44
import { BaseService as __BaseService } from '../base-service';
55
import { {{ configurationClass }} as __Configuration } from '../{{configurationFile}}';
66
import { StrictHttpResponse as __StrictHttpResponse } from '../strict-http-response';
7-
import { Observable as __Observable } from 'rxjs';
8-
import { map as __map, filter as __filter } from 'rxjs/operators';
7+
import { Observable as __Observable, of as __of } from 'rxjs';
8+
import { map as __map, filter as __filter, switchMap as __switchMap } from 'rxjs/operators';
9+
10+
interface {{serviceClass}}TokenProvider {
11+
getToken: (name: string) => __Observable<string>;
12+
}
13+
14+
const {{serviceClass}}TokenProviderInjectionToken = new InjectionToken<{{serviceClass}}TokenProvider>('{{serviceClass}}TokenProviderInjectionToken')
915

1016
{{#serviceDependencies}}import { {{modelClass}} } from '../models/{{modelFile}}';
1117
{{/serviceDependencies}}
@@ -15,12 +21,19 @@ import { map as __map, filter as __filter } from 'rxjs/operators';
1521
class {{serviceClass}} extends __BaseService {
1622
{{#serviceOperations}}{{>operationEndpoints}}{{/serviceOperations}}
1723

24+
private tokenProvider: (name: string) => __Observable<string> = _ => __of(null);
25+
1826
constructor(
1927
config: __Configuration,
20-
http: HttpClient
28+
http: HttpClient,
29+
@Optional() @Inject({{serviceClass}}TokenProviderInjectionToken) tokenProvider: {{serviceClass}}TokenProvider,
2130
) {
2231
super(config, http);
32+
if (tokenProvider) {
33+
this.tokenProvider = (v: string) => tokenProvider.getToken(v);
34+
}
2335
}
36+
2437
{{#serviceOperations}}{{>operationResponse}}{{>operationBody}}{{/serviceOperations}}
2538
}
2639

@@ -34,4 +47,4 @@ module {{serviceClass}} {
3447
{{/operationParamsClass}}{{/serviceOperations}}
3548
}
3649

37-
export { {{serviceClass}} }
50+
export { {{serviceClass}}, {{serviceClass}}TokenProvider, {{serviceClass}}TokenProviderInjectionToken }

templates/services.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{{#services}}
2-
export { {{serviceClass}} } from './services/{{serviceFile}}';
2+
export { {{serviceClass}}, {{serviceClass}}TokenProvider, {{serviceClass}}TokenProviderInjectionToken } from './services/{{serviceFile}}';
33
{{/services}}

0 commit comments

Comments
 (0)