Skip to content

Commit

Permalink
refactor(oas): extract uri template logic
Browse files Browse the repository at this point in the history
relates-to #120
  • Loading branch information
pmstss committed Feb 17, 2022
1 parent d77cc7c commit 2004ded
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 117 deletions.
12 changes: 7 additions & 5 deletions packages/oas/src/converter/BaseUrlParser.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isOASV2, isOASV3 } from '../utils';
import { ConvertError } from '../errors';
import { Sampler } from './Sampler';
import { UriTemplator } from './UriTemplator';
import {
normalizeUrl,
removeLeadingSlash,
Expand All @@ -10,9 +11,10 @@ import {
OpenAPIV3
} from '@har-sdk/core';
import pointer from 'json-pointer';
import template from 'url-template';

export class BaseUrlParser {
private readonly uriTemplator = new UriTemplator();

constructor(private readonly sampler: Sampler) {}

public parse(spec: OpenAPI.Document): string {
Expand Down Expand Up @@ -101,11 +103,11 @@ export class BaseUrlParser {
}),
{}
);
const templateUrl = template.parse(server.url);
const rawUrl = templateUrl.expand(params);
const jsonPointer = pointer.compile(['servers', idx.toString()]);

return this.normalizeUrl(rawUrl, { jsonPointer });
return this.normalizeUrl(
this.uriTemplator.substitute(server.url, params),
{ jsonPointer: pointer.compile(['servers', idx.toString()]) }
);
});
}
}
10 changes: 2 additions & 8 deletions packages/oas/src/converter/DefaultConverter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { BaseUrlParser } from './BaseUrlParser';
import { Converter } from './Converter';
import { ParamsSerializer } from './ParamsSerializer';
import { Sampler } from './Sampler';
import {
SubPart,
Expand All @@ -26,7 +25,6 @@ type PathItemObject = OpenAPIV2.PathItemObject | OpenAPIV3.PathItemObject;

export class DefaultConverter implements Converter {
private readonly sampler = new Sampler();
private readonly paramsSerializer = new ParamsSerializer();
private readonly baseUrlConverter = new BaseUrlParser(this.sampler);

private spec: OpenAPI.Document;
Expand Down Expand Up @@ -117,15 +115,11 @@ export class DefaultConverter implements Converter {
case SubPart.HEADERS:
return new HeadersConverter(spec, this.sampler);
case SubPart.PATH:
return new PathConverter(spec, this.sampler, this.paramsSerializer);
return new PathConverter(spec, this.sampler);
case SubPart.POST_DATA:
return new PostDataConverter(spec, this.sampler);
case SubPart.QUERY_STRING:
return new QueryStringConverter(
spec,
this.sampler,
this.paramsSerializer
);
return new QueryStringConverter(spec, this.sampler);
}
}

Expand Down
42 changes: 42 additions & 0 deletions packages/oas/src/converter/Oas2ValueSerializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { isObject, Flattener } from '../utils';
import { OpenAPIV2 } from '@har-sdk/core';

export class Oas2ValueSerializer {
private readonly flattener = new Flattener();

public serialize(
param: OpenAPIV2.Parameter,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
value: any
): any {
const style = param.collectionFormat;
const explode = param.collectionFormat === 'multi';

if (explode) {
return value;
}

const delimiter = this.getDelimiter(style);
if (Array.isArray(value)) {
return value.join(delimiter);
} else if (isObject(value)) {
return this.flattener.toFlattenArray(value).join(delimiter);
}

return value;
}

private getDelimiter(style: string): string {
switch (style) {
case 'ssv':
return ' ';
case 'tsv':
return '\t';
case 'pipes':
return '|';
case 'csv':
default:
return ',';
}
}
}
66 changes: 0 additions & 66 deletions packages/oas/src/converter/ParamsSerializer.ts

This file was deleted.

7 changes: 7 additions & 0 deletions packages/oas/src/converter/UriTemplator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import template from 'url-template';

export class UriTemplator {
public substitute(templateStr: string, values: Record<string, any>): string {
return template.parse(templateStr).expand(values);
}
}
56 changes: 27 additions & 29 deletions packages/oas/src/converter/subconverters/PathConverter.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { ParameterObject } from '../../types';
import { isOASV2, getParameters, filterLocationParams } from '../../utils';
import { Sampler } from '../Sampler';
import { ParamsSerializer } from '../ParamsSerializer';
import { Oas2ValueSerializer } from '../Oas2ValueSerializer';
import { UriTemplator } from '../UriTemplator';
import { SubConverter } from './SubConverter';
import { OpenAPI, OpenAPIV2, OpenAPIV3 } from '@har-sdk/core';
import template from 'url-template';

export class PathConverter implements SubConverter<string> {
private uriTemplator = new UriTemplator();
private oas2ValueSerializer = new Oas2ValueSerializer();

constructor(
private readonly spec: OpenAPI.Document,
private readonly sampler: Sampler,
private readonly paramsSerializer: ParamsSerializer
private readonly sampler: Sampler
) {}

public convert(path: string, method: string): string {
const params: ParameterObject[] = getParameters(this.spec, path, method);
const pathParams = filterLocationParams(params, 'path');

const tokens = ['paths', path, method];
const sampledParams = pathParams.map((param) =>
const sampledParamValues = pathParams.map((param) =>
this.sampler.sampleParam(param, {
tokens,
spec: this.spec,
Expand All @@ -27,63 +29,59 @@ export class PathConverter implements SubConverter<string> {
);

return isOASV2(this.spec)
? this.serializeOas2Path(
? this.parseOas2Path(
path,
pathParams as OpenAPIV2.Parameter[],
sampledParams
sampledParamValues
)
: this.serializeOas3Path(
: this.parseOas3Path(
path,
pathParams as OpenAPIV3.ParameterObject[],
sampledParams
sampledParamValues
);
}

private serializeOas2Path(
private parseOas2Path(
path: string,
pathParams: OpenAPIV2.Parameter[],
sampledParams: any[]
values: any[]
): string {
return encodeURI(
pathParams.reduce(
(res, param, idx) =>
res.replace(
`{${param.name}}`,
this.paramsSerializer.serializeValue(
param,
sampledParams[idx],
false
)
this.oas2ValueSerializer.serialize(param, values[idx])
),
path
)
);
}

// TODO extract URI template logic
private serializeOas3Path(
path: string,
pathParams: OpenAPIV3.ParameterObject[],
sampledParams: any[]
private parseOas3Path(
input: string,
params: OpenAPIV3.ParameterObject[],
values: any[]
): string {
const uriTemplatePath = pathParams.reduce(
const pathTemplateStr = params.reduce(
(res, param) =>
res.replace(`{${param.name}}`, this.getParamUriTemplate(param)),
path
res.replace(`{${param.name}}`, this.getOas3PathParamUriTemplate(param)),
input
);

return template.parse(uriTemplatePath).expand(
pathParams.reduce(
(res: Record<string, any>, param, idx) => ({
return this.uriTemplator.substitute(
pathTemplateStr,
params.reduce(
(res, param, idx) => ({
...res,
[param.name]: sampledParams[idx]
[param.name]: values[idx]
}),
{}
)
);
}

private getParamUriTemplate({
private getOas3PathParamUriTemplate({
name,
style,
explode
Expand Down
Loading

0 comments on commit 2004ded

Please sign in to comment.