Skip to content

Commit

Permalink
Handle kebab-cased names (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
DangoDev committed Jun 12, 2019
1 parent 7926ca7 commit 62d635f
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 33 deletions.
79 changes: 46 additions & 33 deletions src/swagger-2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,14 @@ function capitalize(str: string): string {
}

function camelCase(name: string): string {
return name.replace(/(-|_|\.|\s)+\w/g, letter => letter.toUpperCase().replace(/[^0-9a-z]/gi, ''));
return name.replace(
/(-|_|\.|\s)+\w/g,
(letter): string => letter.toUpperCase().replace(/[^0-9a-z]/gi, '')
);
}

function sanitize(name: string): string {
return name.includes('-') ? `'${name}'` : name;
}

function parse(spec: Swagger2, options: Swagger2Options = {}): string {
Expand Down Expand Up @@ -88,7 +95,7 @@ function parse(spec: Swagger2, options: Swagger2Options = {}): string {
}

if (Array.isArray(value.oneOf)) {
return value.oneOf.map(def => getType(def, '')).join(' | ');
return value.oneOf.map((def): string => getType(def, '')).join(' | ');
}

if (value.properties) {
Expand All @@ -114,15 +121,17 @@ function parse(spec: Swagger2, options: Swagger2Options = {}): string {

// Include allOf, if specified
if (Array.isArray(allOf)) {
allOf.forEach(item => {
// Add “implements“ if this references other items
if (item.$ref) {
const [refName] = getRef(item.$ref);
includes.push(refName);
} else if (item.properties) {
allProperties = { ...allProperties, ...item.properties };
allOf.forEach(
(item): void => {
// Add “implements“ if this references other items
if (item.$ref) {
const [refName] = getRef(item.$ref);
includes.push(refName);
} else if (item.properties) {
allProperties = { ...allProperties, ...item.properties };
}
}
});
);
}

// If nothing’s here, let’s skip this one.
Expand All @@ -140,26 +149,28 @@ function parse(spec: Swagger2, options: Swagger2Options = {}): string {
output.push(`export interface ${shouldCamelCase ? camelCase(ID) : ID}${isExtending} {`);

// Populate interface
Object.entries(allProperties).forEach(([key, value]) => {
const optional = !Array.isArray(required) || required.indexOf(key) === -1;
const formattedKey = shouldCamelCase ? camelCase(key) : key;
const name = `${formattedKey}${optional ? '?' : ''}`;
const newID = `${ID}${capitalize(formattedKey)}`;
const interfaceType = getType(value, newID);

if (typeof value.description === 'string') {
// Print out descriptions as comments, but only if there’s something there (.*)
output.push(`// ${value.description.replace(/\n$/, '').replace(/\n/g, '\n// ')}`);
}
Object.entries(allProperties).forEach(
([key, value]): void => {
const optional = !Array.isArray(required) || required.indexOf(key) === -1;
const formattedKey = shouldCamelCase ? camelCase(key) : key;
const name = `${sanitize(formattedKey)}${optional ? '?' : ''}`;
const newID = `${ID}${capitalize(formattedKey)}`;
const interfaceType = getType(value, newID);

if (typeof value.description === 'string') {
// Print out descriptions as comments, but only if there’s something there (.*)
output.push(`// ${value.description.replace(/\n$/, '').replace(/\n/g, '\n// ')}`);
}

// Handle enums in the same definition
if (Array.isArray(value.enum)) {
output.push(`${name}: ${value.enum.map(option => JSON.stringify(option)).join(' | ')};`);
return;
}
// Handle enums in the same definition
if (Array.isArray(value.enum)) {
output.push(`${name}: ${value.enum.map(option => JSON.stringify(option)).join(' | ')};`);
return;
}

output.push(`${name}: ${interfaceType};`);
});
output.push(`${name}: ${interfaceType};`);
}
);

if (additionalProperties) {
if ((additionalProperties as boolean) === true) {
Expand All @@ -177,12 +188,14 @@ function parse(spec: Swagger2, options: Swagger2Options = {}): string {
}

// Begin parsing top-level entries
Object.entries(definitions).forEach(entry => {
// Ignore top-level array definitions
if (entry[1].type === 'object') {
queue.push(entry);
Object.entries(definitions).forEach(
(entry): void => {
// Ignore top-level array definitions
if (entry[1].type === 'object') {
queue.push(entry);
}
}
});
);
queue.sort((a, b) => a[0].localeCompare(b[0]));
while (queue.length > 0) {
buildNextInterface();
Expand Down
22 changes: 22 additions & 0 deletions tests/swagger-2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,28 @@ describe('Swagger 2 spec', () => {

expect(swaggerToTS(swagger, { camelcase: true })).toBe(ts);
});

it('handles kebab-case property names', () => {
const swagger: Swagger2 = {
definitions: {
User: {
properties: {
'profile-image': { type: 'string' },
'address-line-1': { type: 'string' },
},
type: 'object',
},
},
};

const ts = format(`
export interface User {
'profile-image'?: string;
'address-line-1'?: string;
}`);

expect(swaggerToTS(swagger)).toBe(ts);
});
});

describe('TS features', () => {
Expand Down

0 comments on commit 62d635f

Please sign in to comment.