Skip to content

Commit

Permalink
feat(schema): add support for unknown enum values (#160)
Browse files Browse the repository at this point in the history
 feat(schema): add support for unknown enum values
closes #159
 
Co-authored-by: MaryamAdnan3 <maryam.adnan@apimatic.com>
  • Loading branch information
MaryamAdnan3 authored Mar 29, 2024
1 parent ef51237 commit e132c2c
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 13 deletions.
2 changes: 1 addition & 1 deletion packages/schema/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@apimatic/schema",
"author": "APIMatic Ltd.",
"version": "0.7.6",
"version": "0.7.7",
"license": "MIT",
"sideEffects": false,
"main": "lib/index.js",
Expand Down
23 changes: 16 additions & 7 deletions packages/schema/src/types/numberEnum.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
import { Schema } from '../schema';
import {
isNumericString,
coerceNumericStringToNumber,
createSymmetricSchema,
isNumericString,
toValidator,
} from '../utils';

function createEnumChecker<T extends string, TEnumValue extends number>(
enumVariable: { [key in T]: TEnumValue }
enumVariable: { [key in T]: TEnumValue },
allowForUnknownProps: boolean = false
) {
const enumValues = Object.values(enumVariable);
return (value: unknown): value is TEnumValue =>
isNumericString(value) &&
enumValues.includes(coerceNumericStringToNumber(value));

if (allowForUnknownProps) {
return (value: unknown): value is TEnumValue => isNumericString(value);
} else {
return (value: unknown): value is TEnumValue =>
isNumericString(value) &&
enumValues.includes(coerceNumericStringToNumber(value));
}
}

/**
* Create a schema for a number enumeration.
*/
export function numberEnum<T extends string, TEnumValue extends number>(
enumVariable: { [key in T]: TEnumValue }
enumVariable: { [key in T]: TEnumValue },
allowForUnknownProps: boolean = false
): Schema<TEnumValue, TEnumValue> {
const validate = toValidator(createEnumChecker(enumVariable));
const validate = toValidator(
createEnumChecker(enumVariable, allowForUnknownProps)
);

return createSymmetricSchema({
type: `Enum<${Object.values(enumVariable)
Expand Down
19 changes: 14 additions & 5 deletions packages/schema/src/types/stringEnum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,29 @@ import {
} from '../utils';

function createEnumChecker<T extends string, TEnumValue extends string>(
enumVariable: { [key in T]: TEnumValue }
enumVariable: { [key in T]: TEnumValue },
allowForUnknownProps: boolean = false
) {
const enumValues = Object.values(enumVariable);
return (value: unknown): value is TEnumValue =>
typeof value === 'string' && enumValues.includes(value);

if (allowForUnknownProps) {
return (value: unknown): value is TEnumValue => typeof value === 'string';
} else {
return (value: unknown): value is TEnumValue =>
typeof value === 'string' && enumValues.includes(value as TEnumValue);
}
}

/**
* Create a schema for a string enumeration.
*/
export function stringEnum<T extends string, TEnumValue extends string>(
enumVariable: { [key in T]: TEnumValue }
enumVariable: { [key in T]: TEnumValue },
allowForUnknownProps: boolean = false
): Schema<TEnumValue, TEnumValue> {
const validate = toValidator(createEnumChecker(enumVariable));
const validate = toValidator(
createEnumChecker(enumVariable, allowForUnknownProps)
);

return createSymmetricSchema({
type: `Enum<${Object.values(enumVariable).map(literalToString).join(',')}>`,
Expand Down
20 changes: 20 additions & 0 deletions packages/schema/test/types/numberSchema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,26 @@ describe('Number Enum', () => {
Diamonds,
}
describe('Mapping', () => {
it('should map unknown numeric value in enum', () => {
const input = 5;
const output = validateAndMap(
input as any,
numberEnum(SampleNumberEnum, true)
);
expect(output.errors).toBeFalsy();
expect((output as any).result).toBe(5);
});

it('should map unknown numeric string value in enum', () => {
const input = '5';
const output = validateAndMap(
input as any,
numberEnum(SampleNumberEnum, true)
);
expect(output.errors).toBeFalsy();
expect((output as any).result).toBe(5);
});

it('should map enum', () => {
const input = 0;
const output = validateAndMap(input as any, numberEnum(SampleNumberEnum));
Expand Down
10 changes: 10 additions & 0 deletions packages/schema/test/types/stringEnum.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ describe('String Enum', () => {
Diamonds = '_diamonds',
}
describe('Mapping', () => {
it('should map unknown string value in enum', () => {
const input = 'unknown';
const output = validateAndMap(
input as any,
stringEnum(SampleStringEnum, true)
);
expect(output.errors).toBeFalsy();
expect((output as any).result).toBe('unknown');
});

it('should map enum', () => {
const input = '_hearts';
const output = validateAndMap(input as any, stringEnum(SampleStringEnum));
Expand Down

0 comments on commit e132c2c

Please sign in to comment.