Skip to content

Commit

Permalink
Enable optional chaining in codebase (airtasker#750)
Browse files Browse the repository at this point in the history
  • Loading branch information
lfportal authored Mar 24, 2020
1 parent 39ab2bd commit 70b768d
Show file tree
Hide file tree
Showing 21 changed files with 48 additions and 68 deletions.
2 changes: 1 addition & 1 deletion cli/src/commands/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default class Mock extends Command {
const contract = parse(args[ARG_API]);
await runMockServer(contract, {
port,
pathPrefix: pathPrefix || "",
pathPrefix: pathPrefix ?? "",
...proxyConfig,
logger: this
}).defer();
Expand Down
2 changes: 1 addition & 1 deletion cli/src/common/infer-proxy-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default function inferProxyConfig(
return null;
}

const [protocol] = proxyBaseUrl && proxyBaseUrl.split("://");
const [protocol] = proxyBaseUrl.split("://");

if (protocol !== "http" && protocol !== "https") {
throw new Error(
Expand Down
7 changes: 3 additions & 4 deletions lib/src/generators/openapi2/openapi2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@ function endpointsToPathsObject(
)
.join("/");

// Note: acc[pathName] || {} breaks type safety, ternary operation is type safe
acc[pathName] = acc[pathName] ? acc[pathName] : {};
acc[pathName] = acc[pathName] ?? {};
const pathItemMethod = httpMethodToPathItemMethod(endpoint.method);
acc[pathName][pathItemMethod] = endpointToOperationObject(
endpoint,
Expand Down Expand Up @@ -173,7 +172,7 @@ function endpointRequestToParameterObjects(

return parameters
.concat(pathParameters, queryParameters, headerParameters)
.concat(bodyParameter || []);
.concat(bodyParameter ?? []);
}

function endpointResponsesToResponsesObject(
Expand Down Expand Up @@ -209,7 +208,7 @@ function endpointResponseToResponseObject(
typeTable: TypeTable
): ResponseObject {
const description =
response.description ||
response.description ??
(isSpecificResponse(response)
? `${response.status} response`
: "default response");
Expand Down
7 changes: 3 additions & 4 deletions lib/src/generators/openapi3/openapi3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,7 @@ function endpointsToPathsObject(
)
.join("/");

// Note: acc[pathName] || {} breaks type safety, ternary operation is type safe
acc[pathName] = acc[pathName] ? acc[pathName] : {};
acc[pathName] = acc[pathName] ?? {};
const pathItemMethod = httpMethodToPathItemMethod(endpoint.method);
acc[pathName][pathItemMethod] = endpointToOperationObject(
endpoint,
Expand All @@ -119,7 +118,7 @@ function endpointToOperationObject(
config: Config
): OperationObject {
const endpointRequest = endpoint.request;
const endpointRequestBody = endpointRequest && endpointRequest.body;
const endpointRequestBody = endpointRequest?.body;

return {
tags: endpoint.tags.length > 0 ? endpoint.tags : undefined,
Expand Down Expand Up @@ -263,7 +262,7 @@ function endpointResponseToResponseObject(
typeTable: TypeTable
): ResponseObject {
const description =
response.description ||
response.description ??
(isSpecificResponse(response)
? `${response.status} response`
: "default response");
Expand Down
4 changes: 2 additions & 2 deletions lib/src/linting/rules/has-request-payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function hasRequestPayload(contract: Contract): LintingRuleViolation[] {
contract.endpoints.forEach(endpoint => {
switch (endpoint.method) {
case "GET":
if (endpoint.request && endpoint.request.body) {
if (endpoint.request?.body) {
violations.push({
message: `Endpoint (${endpoint.name}) with HTTP method ${endpoint.method} must not contain a request body`
});
Expand All @@ -25,7 +25,7 @@ export function hasRequestPayload(contract: Contract): LintingRuleViolation[] {
case "POST":
case "PATCH":
case "PUT":
if (!(endpoint.request && endpoint.request.body)) {
if (!endpoint.request?.body) {
violations.push({
message: `Endpoint (${endpoint.name}) with HTTP method ${endpoint.method} must contain a request body`
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,14 @@ export function noNullableFieldsWithinRequestBodies(
const violations: LintingRuleViolation[] = [];

contract.endpoints.forEach(endpoint => {
if (endpoint.request) {
if (endpoint.request.body) {
findNullableFieldViolation(
endpoint.request.body.type,
typeTable
).forEach(path => {
if (endpoint.request?.body) {
findNullableFieldViolation(endpoint.request.body.type, typeTable).forEach(
path => {
violations.push({
message: `Endpoint (${endpoint.name}) request body contains a nullable field: #/${path}`
});
});
}
}
);
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,16 @@ export function noOmittableFieldsWithinResponseBodies(
);
}
});
if (endpoint.defaultResponse) {
if (endpoint.defaultResponse.body) {
findOmittableFieldViolation(
endpoint.defaultResponse.body.type,
typeTable
).forEach(path => {
violations.push({
message: `Endpoint (${endpoint.name}) response (default) body contains an omittable field: #/${path}`
});

if (endpoint.defaultResponse?.body) {
findOmittableFieldViolation(
endpoint.defaultResponse.body.type,
typeTable
).forEach(path => {
violations.push({
message: `Endpoint (${endpoint.name}) response (default) body contains an omittable field: #/${path}`
});
}
});
}
});

Expand Down
2 changes: 1 addition & 1 deletion lib/src/mock-server/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function proxyRequest({

const proxyRequest = requestHandler.request(proxyBaseUrl, options, res => {
// Forward headers
response.writeHead(res.statusCode || response.statusCode, res.headers);
response.writeHead(res.statusCode ?? response.statusCode, res.headers);
res.pipe(response);
});

Expand Down
2 changes: 1 addition & 1 deletion lib/src/mock-server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function runMockServer(
}

logger.log(`Request hit for ${endpoint.name} registered.`);
const response = endpoint.responses[0] || endpoint.defaultResponse;
const response = endpoint.responses[0] ?? endpoint.defaultResponse;
if (!response) {
logger.error(`No response defined for endpoint ${endpoint.name}`);
return;
Expand Down
4 changes: 2 additions & 2 deletions lib/src/parsers/contract-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function parseContract(

// Handle description
const descriptionDoc = getJsDoc(klass);
const description = descriptionDoc && descriptionDoc.getDescription().trim();
const description = descriptionDoc?.getDescription().trim();

// Handle config
const configResult = resolveConfig(klass);
Expand All @@ -70,7 +70,7 @@ export function parseContract(
securityHeaderProp &&
parseSecurityHeader(securityHeaderProp, typeTable, lociTable);
if (securityResult && securityResult.isErr()) return securityResult;
const security = securityResult && securityResult.unwrap();
const security = securityResult?.unwrap();

// Add location data
lociTable.addMorphNode(LociTable.apiClassKey(), klass);
Expand Down
3 changes: 1 addition & 2 deletions lib/src/parsers/default-response-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export function parseDefaultResponse(
method.getDecoratorOrThrow("defaultResponse");
const headersParam = getParamWithDecorator(method, "headers");
const bodyParam = getParamWithDecorator(method, "body");
const descriptionDoc = getJsDoc(method);

const headers = [];
if (headersParam) {
Expand All @@ -34,7 +33,7 @@ export function parseDefaultResponse(

return ok({
headers,
description: descriptionDoc && descriptionDoc.getDescription().trim(),
description: getJsDoc(method)?.getDescription().trim(),
body
});
}
8 changes: 3 additions & 5 deletions lib/src/parsers/endpoint-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ export function parseEndpoint(
const tags = tagsResult.unwrap();

// Handle jsdoc
const descriptionDoc = getJsDoc(klass);
const description = descriptionDoc && descriptionDoc.getDescription().trim();
const description = getJsDoc(klass)?.getDescription().trim();

// Handle draft
const draft = klass.getDecorator("draft") !== undefined;
Expand Down Expand Up @@ -88,9 +87,8 @@ export function parseEndpoint(

// Check request path params cover the path dynamic components
const pathParamsInPath = getDynamicPathComponents(path);
const pathParamsInRequest = request
? request.pathParams.map(pathParam => pathParam.name)
: [];
const pathParamsInRequest =
request?.pathParams.map(pathParam => pathParam.name) ?? [];

const exclusivePathParamsInPath = pathParamsInPath.filter(
pathParam => !pathParamsInRequest.includes(pathParam)
Expand Down
3 changes: 1 addition & 2 deletions lib/src/parsers/headers-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ export function parseHeaders(
if (typeResult.isErr()) return typeResult;
const type = typeResult.unwrap();

const pDescription = getJsDoc(propertySignature);
const description = pDescription && pDescription.getDescription().trim();
const description = getJsDoc(propertySignature)?.getDescription().trim();

const optional = propertySignature.hasQuestionToken();

Expand Down
3 changes: 1 addition & 2 deletions lib/src/parsers/path-params-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ function extractPathParam(
if (typeResult.isErr()) return typeResult;
const type = typeResult.unwrap();

const pDescription = getJsDoc(propertySignature);
const description = pDescription && pDescription.getDescription().trim();
const description = getJsDoc(propertySignature)?.getDescription().trim();

return ok({ name, type, description });
}
Expand Down
3 changes: 1 addition & 2 deletions lib/src/parsers/query-params-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ export function parseQueryParams(
if (typeResult.isErr()) return typeResult;
const type = typeResult.unwrap();

const pDescription = getJsDoc(propertySignature);
const description = pDescription && pDescription.getDescription().trim();
const description = getJsDoc(propertySignature)?.getDescription().trim();

const optional = propertySignature.hasQuestionToken();

Expand Down
3 changes: 1 addition & 2 deletions lib/src/parsers/response-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export function parseResponse(
const statusLiteral = getPropValueAsNumberOrThrow(statusProp);
const headersParam = getParamWithDecorator(method, "headers");
const bodyParam = getParamWithDecorator(method, "body");
const descriptionDoc = getJsDoc(method);

const headers = [];
if (headersParam) {
Expand All @@ -48,7 +47,7 @@ export function parseResponse(
return ok({
status: statusLiteral.getLiteralValue(),
headers,
description: descriptionDoc && descriptionDoc.getDescription().trim(),
description: getJsDoc(method)?.getDescription().trim(),
body
});
}
3 changes: 1 addition & 2 deletions lib/src/parsers/security-header-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ export function parseSecurityHeader(
const name = nameResult.unwrap();

// Handle description
const descriptionDoc = getJsDoc(property);
const description = descriptionDoc && descriptionDoc.getDescription().trim();
const description = getJsDoc(property)?.getDescription().trim();

// Handle type
const typeResult = extractType(property, typeTable, lociTable);
Expand Down
8 changes: 2 additions & 6 deletions lib/src/parsers/type-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,9 @@ function parseObjectLiteralType(

if (propTypeResult.isErr()) return propTypeResult;

const psDescription = getJsDoc(ps);

const prop = {
name: getPropertyName(ps),
description: psDescription && psDescription.getDescription().trim(),
description: getJsDoc(ps)?.getDescription().trim(),
type: propTypeResult.unwrap(),
optional: ps.hasQuestionToken()
};
Expand Down Expand Up @@ -399,11 +397,9 @@ function parseInterfaceDeclaration(

if (propTypeResult.isErr()) return propTypeResult;

const psDescription = getJsDoc(ps);

const prop = {
name: getPropertyName(ps),
description: psDescription && psDescription.getDescription().trim(),
description: getJsDoc(ps)?.getDescription().trim(),
type: propTypeResult.unwrap(),
optional: ps.hasQuestionToken()
};
Expand Down
2 changes: 1 addition & 1 deletion lib/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ export function inferDiscriminator(
const current = possibleDiscriminators.get(property.name);
possibleDiscriminators.set(
property.name,
(current || []).concat({
(current ?? []).concat({
value: dereferencedPropertyType.value,
type
})
Expand Down
16 changes: 7 additions & 9 deletions lib/src/validation-server/verifications/contract-mismatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export class ContractMismatcher {

// Find request header mismatches
const requestHeaderMismatches = this.findHeaderMismatches(
(expectedRequest && expectedRequest.headers) || [],
expectedRequest?.headers ?? [],
userInputRequest.headers,
true
);
Expand Down Expand Up @@ -183,7 +183,7 @@ export class ContractMismatcher {

// Find request body mismatches
const requestBodyMismatches = this.findBodyMismatches(
expectedRequest && expectedRequest.body,
expectedRequest?.body,
userInputRequest.body,
true
);
Expand Down Expand Up @@ -354,8 +354,7 @@ export class ContractMismatcher {
contractEndpoint: Endpoint,
inputPath: string
): PathParamTypeDisparityMismatch[] {
const contractPathParams =
(contractEndpoint.request && contractEndpoint.request.pathParams) || [];
const contractPathParams = contractEndpoint.request?.pathParams ?? [];

const contractPathArray = contractEndpoint.path.split("/");
const inputPathArray = inputPath.split("?")[0].split("/");
Expand Down Expand Up @@ -444,7 +443,7 @@ export class ContractMismatcher {

const bodyTypeMismatches = validateFn.errors.map(e => {
return `#${e.dataPath} ${
e.message || "JsonSchemaValidator encountered an unexpected error"
e.message ?? "JsonSchemaValidator encountered an unexpected error"
}`;
});

Expand Down Expand Up @@ -475,10 +474,9 @@ export class ContractMismatcher {
| UndefinedQueryParamMismatch
| QueryParamTypeDisparityMismatch
)[] {
const contractQueryParams =
(contractEndpoint.request && contractEndpoint.request.queryParams) || [];
const contractQueryParams = contractEndpoint.request?.queryParams ?? [];

const queryStringComponent = url.parse(inputPath).query || "";
const queryStringComponent = url.parse(inputPath).query ?? "";

const inputQueryParams = qs.parse(queryStringComponent, {
...this.getQueryParamsArraySerializationStrategy()
Expand Down Expand Up @@ -582,7 +580,7 @@ export class ContractMismatcher {
);
});

return endpoint || null;
return endpoint ?? null;
}
}

Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
/* Basic Options */
"target": "esnext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
"target": "es2019" /* Optional chaining was introduced in es2020. This project supports node >= 12. Only node >= 14 supports optional chaining. */,
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
// "lib": [], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
Expand Down

0 comments on commit 70b768d

Please sign in to comment.