Skip to content

Commit c92098e

Browse files
authored
Merge pull request #86 from Kosta-Github/add-props
fix/enhance support for "additionalProperties"
2 parents 70dffc7 + 3802680 commit c92098e

File tree

11 files changed

+450
-88
lines changed

11 files changed

+450
-88
lines changed

__tests__/__snapshots__/runner.js.snap

Lines changed: 277 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,8 @@ export type Order = {
738738
'shipDate' ? : string;
739739
'status' ? : \\"placed\\" | \\"approved\\" | \\"delivered\\";
740740
'complete' ? : boolean;
741+
} & {
742+
[key: string]: any;
741743
};
742744

743745
export type User = {
@@ -749,16 +751,22 @@ export type User = {
749751
'password' ? : string;
750752
'phone' ? : string;
751753
'userStatus' ? : number;
754+
} & {
755+
[key: string]: any;
752756
};
753757

754758
export type Category = {
755759
'id' ? : number;
756760
'name' ? : string;
761+
} & {
762+
[key: string]: any;
757763
};
758764

759765
export type Tag = {
760766
'id' ? : number;
761767
'name' ? : string;
768+
} & {
769+
[key: string]: any;
762770
};
763771

764772
export type Pet = {
@@ -770,12 +778,16 @@ export type Pet = {
770778
'tags' ? : Array < Tag >
771779
;
772780
'status' ? : \\"available\\" | \\"pending\\" | \\"sold\\";
781+
} & {
782+
[key: string]: any;
773783
};
774784

775785
export type ApiResponse = {
776786
'code': number;
777787
'type': string;
778788
'message' ? : string;
789+
} & {
790+
[key: string]: any;
779791
};
780792

781793
export type Logger = {
@@ -1425,9 +1437,7 @@ export class PetshopApi {
14251437
* @method
14261438
* @name PetshopApi#getInventory
14271439
*/
1428-
getInventory(parameters: {} & CommonRequestOptions): Promise < ResponseWithBody < 200, {
1429-
[key: string]: number
1430-
} >> {
1440+
getInventory(parameters: {} & CommonRequestOptions): Promise < ResponseWithBody < 200, object >> {
14311441
const domain = parameters.$domain ? parameters.$domain : this.domain;
14321442
let path = '/store/inventory';
14331443
if (parameters.$path) {
@@ -2464,6 +2474,270 @@ export class UsersApi {
24642474
export default UsersApi;"
24652475
`;
24662476

2477+
exports[`Should resolve "additionalProperties" 1`] = `
2478+
"// tslint:disable
2479+
2480+
import * as request from \\"superagent\\";
2481+
import {
2482+
SuperAgentStatic,
2483+
SuperAgentRequest,
2484+
Response
2485+
} from \\"superagent\\";
2486+
2487+
export type RequestHeaders = {
2488+
[header: string]: string;
2489+
}
2490+
export type RequestHeadersHandler = (headers: RequestHeaders) => RequestHeaders;
2491+
2492+
export type ConfigureAgentHandler = (agent: SuperAgentStatic) => SuperAgentStatic;
2493+
2494+
export type ConfigureRequestHandler = (agent: SuperAgentRequest) => SuperAgentRequest;
2495+
2496+
export type CallbackHandler = (err: any, res ? : request.Response) => void;
2497+
2498+
export type some_def = {
2499+
'some_def' ? : string;
2500+
};
2501+
2502+
export type test_add_props_01 = {
2503+
'some_prop' ? : string;
2504+
} & {
2505+
[key: string]: any;
2506+
};
2507+
2508+
export type test_add_props_02 = {
2509+
'some_prop' ? : string;
2510+
};
2511+
2512+
export type test_add_props_03 = {
2513+
'some_prop' ? : string;
2514+
} & {
2515+
[key: string]: any;
2516+
};
2517+
2518+
export type test_add_props_04 = {
2519+
'some_prop' ? : string;
2520+
} & {
2521+
[key: string]: string;
2522+
};
2523+
2524+
export type test_add_props_05 = {
2525+
'some_prop' ? : string;
2526+
} & {
2527+
[key: string]: {
2528+
'nested_prop' ? : string;
2529+
} & {
2530+
[key: string]: any;
2531+
};
2532+
};
2533+
2534+
export type test_add_props_06 = {
2535+
'some_prop' ? : string;
2536+
} & {
2537+
[key: string]: some_def;
2538+
};
2539+
2540+
export type test_add_props_07 = {} & {
2541+
[key: string]: any;
2542+
};
2543+
2544+
export type test_add_props_08 = {};
2545+
2546+
export type test_add_props_09 = {} & {
2547+
[key: string]: any;
2548+
};
2549+
2550+
export type test_add_props_10 = {} & {
2551+
[key: string]: string;
2552+
};
2553+
2554+
export type test_add_props_11 = {} & {
2555+
[key: string]: {
2556+
'nested_prop' ? : string;
2557+
} & {
2558+
[key: string]: any;
2559+
};
2560+
};
2561+
2562+
export type test_add_props_12 = {} & {
2563+
[key: string]: some_def;
2564+
};
2565+
2566+
export type Logger = {
2567+
log: (line: string) => any
2568+
};
2569+
2570+
export interface ResponseWithBody < S extends number, T > extends Response {
2571+
status: S;
2572+
body: T;
2573+
}
2574+
2575+
export type QueryParameters = {
2576+
[param: string]: any
2577+
};
2578+
2579+
export interface CommonRequestOptions {
2580+
$queryParameters ? : QueryParameters;
2581+
$domain ? : string;
2582+
$path ? : string | ((path: string) => string);
2583+
$retries ? : number; // number of retries; see: https://github.com/visionmedia/superagent/blob/master/docs/index.md#retrying-requests
2584+
$timeout ? : number; // request timeout in milliseconds; see: https://github.com/visionmedia/superagent/blob/master/docs/index.md#timeouts
2585+
$deadline ? : number; // request deadline in milliseconds; see: https://github.com/visionmedia/superagent/blob/master/docs/index.md#timeouts
2586+
}
2587+
2588+
/**
2589+
*
2590+
* @class AddpropsApi
2591+
* @param {(string)} [domainOrOptions] - The project domain.
2592+
*/
2593+
export class AddpropsApi {
2594+
2595+
private domain: string = \\"\\";
2596+
private errorHandlers: CallbackHandler[] = [];
2597+
private requestHeadersHandler ? : RequestHeadersHandler;
2598+
private configureAgentHandler ? : ConfigureAgentHandler;
2599+
private configureRequestHandler ? : ConfigureRequestHandler;
2600+
2601+
constructor(domain ? : string, private logger ? : Logger) {
2602+
if (domain) {
2603+
this.domain = domain;
2604+
}
2605+
}
2606+
2607+
getDomain() {
2608+
return this.domain;
2609+
}
2610+
2611+
addErrorHandler(handler: CallbackHandler) {
2612+
this.errorHandlers.push(handler);
2613+
}
2614+
2615+
setRequestHeadersHandler(handler: RequestHeadersHandler) {
2616+
this.requestHeadersHandler = handler;
2617+
}
2618+
2619+
setConfigureAgentHandler(handler: ConfigureAgentHandler) {
2620+
this.configureAgentHandler = handler;
2621+
}
2622+
2623+
setConfigureRequestHandler(handler: ConfigureRequestHandler) {
2624+
this.configureRequestHandler = handler;
2625+
}
2626+
2627+
private request(method: string, url: string, body: any, headers: RequestHeaders, queryParameters: QueryParameters, form: any, reject: CallbackHandler, resolve: CallbackHandler, opts: CommonRequestOptions) {
2628+
if (this.logger) {
2629+
this.logger.log(\`Call \${method} \${url}\`);
2630+
}
2631+
2632+
const agent = this.configureAgentHandler ?
2633+
this.configureAgentHandler(request.default) :
2634+
request.default;
2635+
2636+
let req = agent(method, url);
2637+
if (this.configureRequestHandler) {
2638+
req = this.configureRequestHandler(req);
2639+
}
2640+
2641+
req = req.query(queryParameters);
2642+
2643+
if (body) {
2644+
req.send(body);
2645+
2646+
if (typeof(body) === 'object' && !(body.constructor.name === 'Buffer')) {
2647+
headers['Content-Type'] = 'application/json';
2648+
}
2649+
}
2650+
2651+
if (Object.keys(form).length > 0) {
2652+
req.type('form');
2653+
req.send(form);
2654+
}
2655+
2656+
if (this.requestHeadersHandler) {
2657+
headers = this.requestHeadersHandler({
2658+
...headers
2659+
});
2660+
}
2661+
2662+
req.set(headers);
2663+
2664+
if (opts.$retries && opts.$retries > 0) {
2665+
req.retry(opts.$retries);
2666+
}
2667+
2668+
if (opts.$timeout && opts.$timeout > 0 || opts.$deadline && opts.$deadline > 0) {
2669+
req.timeout({
2670+
deadline: opts.$deadline,
2671+
response: opts.$timeout
2672+
});
2673+
}
2674+
2675+
req.end((error, response) => {
2676+
// an error will also be emitted for a 4xx and 5xx status code
2677+
// the error object will then have error.status and error.response fields
2678+
// see superagent error handling: https://github.com/visionmedia/superagent/blob/master/docs/index.md#error-handling
2679+
if (error) {
2680+
reject(error);
2681+
this.errorHandlers.forEach(handler => handler(error));
2682+
} else {
2683+
resolve(response);
2684+
}
2685+
});
2686+
}
2687+
2688+
get_personURL(parameters: {} & CommonRequestOptions): string {
2689+
let queryParameters: QueryParameters = {};
2690+
const domain = parameters.$domain ? parameters.$domain : this.domain;
2691+
let path = '/persons';
2692+
if (parameters.$path) {
2693+
path = (typeof(parameters.$path) === 'function') ? parameters.$path(path) : parameters.$path;
2694+
}
2695+
2696+
if (parameters.$queryParameters) {
2697+
queryParameters = {
2698+
...queryParameters,
2699+
...parameters.$queryParameters
2700+
};
2701+
}
2702+
2703+
let keys = Object.keys(queryParameters);
2704+
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '');
2705+
}
2706+
2707+
/**
2708+
* Gets \`Person\` object.
2709+
* @method
2710+
* @name AddpropsApi#get_person
2711+
*/
2712+
get_person(parameters: {} & CommonRequestOptions): Promise < ResponseWithBody < 200, void >> {
2713+
const domain = parameters.$domain ? parameters.$domain : this.domain;
2714+
let path = '/persons';
2715+
if (parameters.$path) {
2716+
path = (typeof(parameters.$path) === 'function') ? parameters.$path(path) : parameters.$path;
2717+
}
2718+
2719+
let body: any;
2720+
let queryParameters: QueryParameters = {};
2721+
let headers: RequestHeaders = {};
2722+
let form: any = {};
2723+
return new Promise((resolve, reject) => {
2724+
2725+
if (parameters.$queryParameters) {
2726+
queryParameters = {
2727+
...queryParameters,
2728+
...parameters.$queryParameters
2729+
};
2730+
}
2731+
2732+
this.request('GET', domain + path, body, headers, queryParameters, form, reject, resolve, parameters);
2733+
});
2734+
}
2735+
2736+
}
2737+
2738+
export default AddpropsApi;"
2739+
`;
2740+
24672741
exports[`Should resolve protected api 1`] = `
24682742
"// tslint:disable
24692743

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"swagger": "2.0",
3+
"info": { "version": "0.0.1", "title": "your title" },
4+
"paths": {
5+
"/persons": {
6+
"get": {
7+
"operationId": "get_person",
8+
"description": "Gets `Person` object.",
9+
"responses": { "200": { "description": "empty schema" } }
10+
}
11+
}
12+
},
13+
"definitions": {
14+
"some_def": { "type": "object", "properties": { "some_def": { "type": "string" } }, "additionalProperties": false },
15+
16+
"test_add_props_01": { "type": "object", "properties": { "some_prop": { "type": "string" } } },
17+
"test_add_props_02": { "type": "object", "properties": { "some_prop": { "type": "string" } }, "additionalProperties": false },
18+
"test_add_props_03": { "type": "object", "properties": { "some_prop": { "type": "string" } }, "additionalProperties": true },
19+
"test_add_props_04": { "type": "object", "properties": { "some_prop": { "type": "string" } }, "additionalProperties": { "type": "string" } },
20+
"test_add_props_05": { "type": "object", "properties": { "some_prop": { "type": "string" } }, "additionalProperties": { "type": "object", "properties": { "nested_prop": { "type": "string" } } } },
21+
"test_add_props_06": { "type": "object", "properties": { "some_prop": { "type": "string" } }, "additionalProperties": { "$ref": "#/definitions/some_def" } },
22+
"test_add_props_07": { "type": "object" },
23+
"test_add_props_08": { "type": "object", "additionalProperties": false },
24+
"test_add_props_09": { "type": "object", "additionalProperties": true },
25+
"test_add_props_10": { "type": "object", "additionalProperties": { "type": "string" } },
26+
"test_add_props_11": { "type": "object", "additionalProperties": { "type": "object", "properties": { "nested_prop": { "type": "string" } } } },
27+
"test_add_props_12": { "type": "object", "additionalProperties": { "$ref": "#/definitions/some_def" } }
28+
}
29+
}

__tests__/runner.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ var testCases = [
1313
desc: "Should resolve references",
1414
fixture: "ref"
1515
},
16+
{
17+
desc: "Should resolve \"additionalProperties\"",
18+
fixture: "addProps"
19+
},
1620
{
1721
desc: "Real world: Uber",
1822
fixture: "uber"

src/swagger/Swagger.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export interface SwaggerType {
2121
readonly properties: {
2222
readonly [index: string]: SwaggerType;
2323
};
24+
readonly additionalProperties?: boolean | SwaggerType;
2425
}
2526

2627
export interface SwaggerArray extends SwaggerType {

src/test-helpers/testHelpers.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,15 @@ export function makeEmptyTypeSpec(): TypeSpec {
3737
description: undefined,
3838
isEnum: false,
3939
isArray: false,
40-
isDictionary: false,
4140
isObject: false,
4241
isRef: false,
4342
isNullable: false,
4443
isRequired: true,
4544
tsType: undefined,
4645
isAtomic: false,
4746
target: undefined,
48-
properties: undefined
47+
properties: undefined,
48+
hasAdditionalProperties: false,
49+
additionalPropertiesType: undefined
4950
};
5051
}

0 commit comments

Comments
 (0)