Skip to content

Commit

Permalink
Merge pull request #142 from kjb085/master
Browse files Browse the repository at this point in the history
Add support for Joi.any().cast() to string and number types
  • Loading branch information
mrjono1 authored Sep 9, 2021
2 parents 8b68919 + acc1934 commit 56a3d28
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ export interface Settings {
- .allow(null) - will add as an optional type eg `string | null`
- .unknown(true) - will add a property `[x: string]: unknown;`
- .example() - jsdoc
- .cast() - currently will honor casting to string and number types, map and set to be added later
Any many others

## Contributing
Expand Down
45 changes: 45 additions & 0 deletions src/__tests__/cast/cast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { existsSync, readFileSync, rmdirSync } from 'fs';

import { convertFromDirectory } from '../../index';

describe('Cast primitive types', () => {
const typeOutputDirectory = './src/__tests__/cast/interfaces';

beforeAll(() => {
if (existsSync(typeOutputDirectory)) {
rmdirSync(typeOutputDirectory, { recursive: true });
}
});

test('casts all variations from file', async () => {
const result = await convertFromDirectory({
schemaDirectory: './src/__tests__/cast/schemas',
typeOutputDirectory
});

expect(result).toBe(true);

const oneContent = readFileSync(`${typeOutputDirectory}/One.ts`).toString();

expect(oneContent).toBe(
`/**
* This file was automatically generated by joi-to-typescript
* Do not modify this file manually
*/
export type NumberType = number;
export interface Numbers {
bool: number;
day: number;
}
export type StringType = string;
export interface Strings {
num: string;
}
`
);
});
});
14 changes: 14 additions & 0 deletions src/__tests__/cast/schemas/OneSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Joi from 'joi';

export const NumberSchema = Joi.object({
bool: Joi.boolean().cast('number').required(),
day: Joi.date().cast('number').required(),
}).meta({ className: 'Numbers' });

export const StringSchema = Joi.object({
num: Joi.number().cast('string').required()
}).meta({ className: 'Strings' })

export const StringType = Joi.number().cast('string')

export const NumberType = Joi.boolean().cast('number')
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ function defaultSettings(settings: Partial<Settings>): Settings {
sortPropertiesByName: true,
commentEverything: false,
ignoreFiles: [],
indentationChacters: ' '
indentationChacters: ' ',
honorCastTo: [],
},
settings
) as Settings;
Expand Down
4 changes: 4 additions & 0 deletions src/joiDescribeTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ export interface BaseDescribe extends Joi.Description {
* https://joi.dev/api/#objectunknownallow
*/
unknown?: boolean;
/**
* https://joi.dev/api/?v=17.4.2#anycastto
*/
cast?: 'string' | 'number' | 'map' | 'set';
};
metas?: Meta[];
}
Expand Down
11 changes: 11 additions & 0 deletions src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import { getInterfaceOrTypeName, getMetadataFromDetails } from './joiUtils';
// see __tests__/joiTypes.ts for more information
export const supportedJoiTypes = ['array', 'object', 'alternatives', 'any', 'boolean', 'date', 'number', 'string'];

// @TODO - Temporarily used prevent 'map' and 'set' from being used by cast
// Remove once support for 'map' and 'set' is added
const validCastTo = ['string', 'number'];

function getCommonDetails(
details: Describe,
settings: Settings
Expand Down Expand Up @@ -184,6 +188,13 @@ export function parseSchema(
rootSchema?: boolean
): TypeContent | undefined {
function parseHelper(): TypeContent | undefined {
// Convert type if a valid cast type is present
if (details.flags?.cast && validCastTo.includes(details.flags?.cast as ('number' | 'string'))) {
// @NOTE - if additional values are added beyond 'string' and 'number' further transformation will
// be needed on the details object to support those types
details.type = details.flags?.cast as ('string' | 'number');
}

switch (details.type) {
case 'array':
return parseArray(details, settings);
Expand Down

0 comments on commit 56a3d28

Please sign in to comment.