Skip to content

Commit

Permalink
Merge pull request #356 from danilvalov/master
Browse files Browse the repository at this point in the history
Add support for simple object pattern in schema
  • Loading branch information
mrjono1 authored Dec 5, 2024
2 parents 92a1ecc + 6f3e9f2 commit 70c3b6e
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 47 deletions.
7 changes: 5 additions & 2 deletions src/__tests__/description/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,16 @@ export interface DisableDescriptionObject {
/**
* A simple description
*/
[x: string]: Example;
[pattern: string]: Example;
};
/**
* withoutDescription
*/
withoutDescription?: {
[x: string]: Example;
/**
* A simple description
*/
[pattern: string]: Example;
};
}
Expand Down
74 changes: 74 additions & 0 deletions src/__tests__/patterns.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import Joi from 'joi';

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

describe('test `Joi.object().pattern()`', () => {
test('`pattern(Joi.string(), Joi.AnySchema())`', () => {
const schema = Joi.object()
.pattern(Joi.string(), Joi.array().items(Joi.object({
id: Joi.string().required(),
propertyName1: Joi.boolean().required()
})))
.description('a test pattern schema definition');

const result = convertSchema({}, schema, 'TestSchema');
expect(result).not.toBeUndefined;
expect(result?.content).toBe(`/**
* a test pattern schema definition
*/
export interface TestSchema {
[pattern: string]: {
id: string;
propertyName1: boolean;
}[];
}`);
});

test('`pattern(Joi.string(), Joi.number())`', () => {
const schema = Joi.object()
.description('a test deep pattern schema definition')
.pattern(Joi.string(), Joi.number().description('Number Property'));

const result = convertSchema({}, schema, 'TestSchema');
expect(result).not.toBeUndefined;
expect(result?.content).toBe(`/**
* a test deep pattern schema definition
*/
export interface TestSchema {
/**
* Number Property
*/
[pattern: string]: number;
}`);
});

test('`pattern(/^test$/, Joi.AnySchema())`', () => {
const schema = Joi.object({
name: Joi.string(),
})
.description('a test regex pattern schema definition')
.pattern(Joi.string(), {
name: Joi.string().optional(),
propertyName1: Joi.object().pattern(/^test$/, Joi.object({
propertyName2: Joi.boolean()
})).required()
});

const result = convertSchema({ sortPropertiesByName: false }, schema, 'TestSchema');
expect(result).not.toBeUndefined;
expect(result?.content).toBe(`/**
* a test regex pattern schema definition
*/
export interface TestSchema {
name?: string;
[pattern: string]: {
name?: string;
propertyName1: {
[pattern: string]: {
propertyName2?: boolean;
};
};
};
}`);
});
});
42 changes: 0 additions & 42 deletions src/__tests__/unknown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,28 +65,6 @@ export interface TestSchema {
}`);
});

test('`pattern(Joi.string(), Joi.number())`', () => {
const schema = Joi.object({
name: Joi.string()
})
.meta({ className: 'TestSchema', unknownType: 'number' })
.description('a test schema definition')
.pattern(Joi.string(), Joi.number());

const result = convertSchema({ sortPropertiesByName: false }, schema);
expect(result).not.toBeUndefined;
expect(result?.content).toBe(`/**
* a test schema definition
*/
export interface TestSchema {
name?: string;
/**
* Number Property
*/
[x: string]: number;
}`);
});

test('`unknown(true).meta({ unknownType: Joi.AnySchema() })`', () => {
const schema = Joi.object({})
.unknown(true)
Expand All @@ -109,26 +87,6 @@ export interface TestSchema {
[x: string]: {
id: string;
}[];
}`);
});

test('`pattern(Joi.string(), Joi.AnySchema())`', () => {
const unknownTypeSchema = Joi.array().items(Joi.object({ id: Joi.string().required() }));

const schema = Joi.object({})
.pattern(Joi.string(), unknownTypeSchema)
.meta({ className: 'TestSchema', unknownType: unknownTypeSchema })
.description('a test schema definition');

const result = convertSchema({}, schema);
expect(result).not.toBeUndefined;
expect(result?.content).toBe(`/**
* a test schema definition
*/
export interface TestSchema {
[x: string]: {
id: string;
}[];
}`);
});
});
3 changes: 2 additions & 1 deletion src/joiDescribeTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ export interface BaseDescribe extends Joi.Description {
* https://joi.dev/api/#objectpatternpattern-schema-options
*/
patterns?: {
schema: Describe;
schema?: Describe;
regex?: string;
rule: Describe;
}[];
metas?: Meta[];
Expand Down
21 changes: 19 additions & 2 deletions src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,19 @@ function parseUnknown(details: ObjectDescribe, settings: Settings): TypeContent
return buildUnknownTypeContent();
}

function parsePatterns(details: ObjectDescribe, settings: Settings): TypeContent {
const parsedSchema = details.patterns ? parseSchema(details.patterns[0].rule, settings) : null;

if (!parsedSchema) {
return parseUnknown(details, settings);
}

parsedSchema.required = true;
parsedSchema.interfaceOrTypeName = '[pattern: string]';

return parsedSchema;
}

function parseObjects(details: ObjectDescribe, settings: Settings): TypeContent | undefined {
const joinOperation: TypeContentRoot['joinOperation'] =
details.keys === undefined
Expand All @@ -740,8 +753,12 @@ function parseObjects(details: ObjectDescribe, settings: Settings): TypeContent
parsedSchema.interfaceOrTypeName = /^[$A-Z_][0-9A-Z_$]*$/i.test(key || '') ? key : `'${key}'`;
return parsedSchema;
});
const isMap = details.patterns?.length === 1 && details.patterns[0].schema.type === 'string';
if (details?.flags?.unknown === true || isMap) {

if (details.patterns?.length === 1 && (details.patterns[0].schema?.type === 'string' || details.patterns[0].regex)) {
children.push(parsePatterns(details, settings));
}

if (details?.flags?.unknown === true) {
children.push(parseUnknown(details, settings));
}

Expand Down

0 comments on commit 70c3b6e

Please sign in to comment.