diff --git a/src/__tests__/basic.ts b/src/__tests__/basic.ts index 6e19e2eb..7f6b822b 100644 --- a/src/__tests__/basic.ts +++ b/src/__tests__/basic.ts @@ -10,7 +10,8 @@ describe('some basic tests', () => { propertyName1: Joi.boolean().required(), dateCreated: Joi.date(), count: Joi.number(), - obj: Joi.object() + obj: Joi.object(), + escape: Joi.string().valid("a'b", 'c"d', "e'f'g", 'h"i"j', '\\\\').required() }) .label('TestSchema') .description('a test schema definition'); @@ -23,6 +24,7 @@ describe('some basic tests', () => { export interface TestSchema { count?: number; dateCreated?: Date; + escape: 'a\\'b' | 'c"d' | 'e\\'f\\'g' | 'h"i"j' | '\\\\\\\\'; /** * Test Schema Name */ diff --git a/src/__tests__/enum.ts b/src/__tests__/enum.ts index 73313cc9..73c67e73 100644 --- a/src/__tests__/enum.ts +++ b/src/__tests__/enum.ts @@ -6,7 +6,8 @@ describe('enums tests', () => { test('enums using valid()', () => { const schema = Joi.object({ topColour: Joi.string().valid('red', 'green', 'orange', 'blue').required(), - bottomColour: Joi.string().valid('red', 'green', 'orange', 'blue').required() + bottomColour: Joi.string().valid('red', 'green', 'orange', 'blue').required(), + escape: Joi.string().valid("a'b", 'c"d', "e'f'g", 'h"i"j', '\\\\').required() }) .label('TestSchema') .description('a test schema definition'); @@ -19,6 +20,7 @@ describe('enums tests', () => { export interface TestSchema { topColour: 'red' | 'green' | 'orange' | 'blue'; bottomColour: 'red' | 'green' | 'orange' | 'blue'; + escape: 'a\\'b' | 'c"d' | 'e\\'f\\'g' | 'h"i"j' | '\\\\\\\\'; }`); }); diff --git a/src/parse.ts b/src/parse.ts index 2aafb7ed..49d00582 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -1,5 +1,5 @@ import Joi from 'joi'; -import { filterMap } from './utils'; +import { filterMap, toStringLiteral } from './utils'; import { TypeContent, makeTypeContentRoot, makeTypeContentChild, Settings, JsDoc } from './types'; // see __tests__/joiTypes.ts for more information @@ -249,7 +249,7 @@ function parseBasicSchema(details: BasicDescribe, settings: Settings): TypeConte // at least one value if (values && values.length !== 0) { const allowedValues = values.map((value: unknown) => - makeTypeContentChild({ content: typeof value === 'string' ? `'${value}'` : `${value}` }) + makeTypeContentChild({ content: typeof value === 'string' ? toStringLiteral(value) : `${value}` }) ); if (values[0] === null) { @@ -274,7 +274,7 @@ function parseStringSchema(details: StringDescribe, settings: Settings): TypeCon const allowedValues = values.map(value => stringAllowValues.includes(value) && value !== '' ? makeTypeContentChild({ content: `${value}` }) - : makeTypeContentChild({ content: `'${value}'` }) + : makeTypeContentChild({ content: toStringLiteral(value) }) ); if (values.filter(value => stringAllowValues.includes(value)).length == values.length) { diff --git a/src/utils.ts b/src/utils.ts index 7ecdb374..7062c072 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -14,3 +14,11 @@ export function filterMap(list: T[], mapper: (t: T) => K | undefined): K[] return res; }, []); } + +/** + * Escape value so that it can be go into single quoted string literal. + * @param value + */ +export function toStringLiteral(value: string): string { + return `'${value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`; +}