@apizr-io/class-utils
TypeScript icon, indicating that this package has built-in type declarations

0.8.1 • Public • Published

class-utils

This package contains all class-validator and class-tranformer functions with custom class decorators that can be used to validate a class.

Usage

import { IsString } from '@apizr/class-utils/validators';
import { Transform } from '@apizr/class-utils/transformers';

class MyClass {
  @IsString()
  myString: string;

  @Transform((value) => value === 'true')
  myBoolean: boolean;
}

Dependencies

This package depends on jsonpath-plus to be able to use some decorators (e.g. ValidateSubKeyExistIf). See documentation for more information.

class-validator decorators and class-transformer

See documentation of class-validator for the list of default exports. See documentation of class-transformer for the list of default export.

Custom transformers

SplitString

SplitString(separator: string = ',')

Will transform a string received to an array of string split by separator.

Usage

import { SplitString } from '@apizr/class-utils/tranformers';

class MyStringClass {
  @SplitString()
  myString: string[];
}

Custom decorators

IsBeforeDate

IsBeforeDate(property: string, options: ValidationOptions)

Checks if the date is before the date present in the same objet at the specified key.

Usage

import { IsBeforeDate } from '@apizr/class-utils/validators';

class Dates {
  @IsBeforeDate('end')
  start: Date;

  end: Date;
}

If the other date is optional, you can specify a flag to prevent an error if no date is present

import { IsBeforeDate } from '@apizr/class-utils/validators';

class Dates {
  @IsBeforeDate('end', { context: { otherDateIsOptional: true } })
  start: Date;

  end?: Date;
}

IsAfterDate

IsAfterDate(property: string, options: ValidationOptions)

Checks if the date is after the date present in the same objet at the specified key.

Usage

import { IsAfterDate } from '@apizr/class-utils/validators';

class Dates {
  start: Date;

  @IsAfterDate('start')
  end: Date;
}

If the other date is optional, you can specify a flag to prevent an error if no date is present

import { IsAfterDate } from '@apizr/class-utils/validators';

class Dates {
  start?: Date;

  @IsAfterDate('start', { context: { otherDateIsOptional: true } })
  end: Date;
}

IsFutureDate

IsFutureDate(void)

Checks if the date is in the future.

Usage

import { IsFutureDate } from '@apizr/class-utils/validators';

class Date {
  @IsFutureDate()
  end: Date;
}

StartsWith

StartsWith(startValue: string | string[])

Checks if the string starts with the specified value

Usage

import { StartsWith } from '@apizr/class-utils/validators';

class Order {
  @StartsWith('PROD-')
  id: string;
}

OneOfKeysIsDefined

OneOfKeysIsDefined(keysToValidate: string[])

Checks if at least one of the key has value (not null or undefined).

Usage

import { OneOfKeysIsDefined } from '@apizr/class-utils/validators';

class Product {
  id: string;
  description?: string;
  name?: string;
}

class Order {
  @ValidateNested({ each: true })
  @Type(() => Product)
  @OneOfKeysIsDefined(['description', 'name'], { each: true })
  products: Product[];
}

ValidateSort

ValidateSort(allowedSort: string | string[])

Checks that the string array contains valid keys with valid sorting directions (asc or desc).

usage

import { ValidateSort } from '@apizr/class-utils/validators';

class Filters {
  @ValidateSort(['date.creation', 'date.modification'])
  sort: string[];
}

This will allow date.creation:asc or date.modification:desc for example.

ValidateAtLeastOneKeyGroupExists

ValidateAtLeastOneKeyGroupExists(groups: string[][])

Checks if one of the keys groups exist in class.

Usage

@ValidateAtLeastOneKeyGroupExists([
  ['key1', 'key2'],
  ['key2', 'key3']
])

Will validate that (key1 and key2) or (key2 and key3) exists in the class.

Usage

import { ValidateAtLeastOneKeyGroupExists } from '@apizr/class-utils/validators';

@ValidateAtLeastOneKeyGroupExists([
  ['email', 'birthday'],
  ['firstname', 'lastname'],
])
class Customer {
  email: string;

  firstname: string;

  lastname: string;

  birthday: string;
}

ValidateOnlyOneKeyGroupExists

ValidateOnlyOneKeyGroupExists(groups: string[][])

Checks if keys of a key groups exist in class.

Usage

@ValidateOneKeyGroupExists([
  ['key1', 'key2'],
  ['key2', 'key3']
])

Will validate that (key1 and key2) xor (exclusive or) (key2 and key3) exists in the class.

Usage

import { ValidateOnlyOneKeyGroupExists } from '@apizr/class-utils/validators';

@ValidateOnlyOneKeyGroupExists([
  ['email', 'birthday'],
  ['firstname', 'lastname'],
])
class Customer {
  email: string;

  firstname: string;

  lastname: string;

  birthday: string;
}

ValidateSubKeyExistIf

ValidateSubKeyExistIf(path: string, condition: (value: any) => boolean)

Allows validating the presence of a specified key in a child object based on a given condition. The child value described by the path option must have the @IsOptional() decorator (see example below).

Usage

import { ValidateSubKeyExistIf } from '@apizr/class-utils/validators';

class ChildClass {
  @IsOptional() // Mandatory when this decorator is used
  targetedValue?: any;
}

@ValidateSubKeyExistIf(
  'child.targetedValue',
  (o) => o.conditionalValue !== false,
)
class ParentClass {
  @IsString()
  conditionalValue: boolean;

  @ValidateNested({ each: true })
  @Type(() => ChildClass)
  child: ChildClass;
}

You can also use jsonpath-plus to validate a key in an array of objects:

import { ValidateSubKeyExistIf } from '@apizr/class-utils/validators';

class LittleChildClass {
  @IsOptional() // Mandatory when this decorator is used
  targetedValue?: string;
}

class ChildClass {
  @IsOptional()
  @ValidateNested({ each: true })
  @Type(() => LittleChildClass)
  myOtherValue?: LittleChildClass[];
}

@ValidateSubKeyExistIf(
  'child.myOtherValue[*].targetedValue',
  (o) => o.conditionalValue !== false,
)
class ParentClass {
  conditionalValue: boolean;
  @ValidateNested({ each: true })
  @Type(() => ChildClass)
  child: ChildClass;
}

IsRecord

IsRecord(allowedRecordType: AllowedType | AllowedType[], options: IsRecordValidateOptions)

Check if the record is compliant to specified definition.

By default, the key type will be checked to be a string.

Usage

import { IsRecord } from '@apizr/class-utils/validators';

class ChildClass {
  @IsString()
  key: string;
}

class ExampleClass {
  @IsRecord('boolean')
  record: Record<string, boolean>;

  @IsRecord(['string', 'undefined'])
  record: Record<string, string | undefined>;

  @IsRecord(ChildClass)
  record: Record<string, ChildClass>;

  @IsRecord('string', { key: 'number' })
  record: Record<number, string>;

  @IsRecord(ChildClass, { each: true })
  records: Record<string, ChildClass>[];

  @IsRecord([ChildClass, ChildClass2, 'undefined'])
  record: Record<string, ChildClass | ChildClass2 | undefined>;

  @IsRecord([{ type: ChildClass, array: true }, ChildClass2])
  record: Record<string, ChildClass[] | ChildClass2>;

  @IsRecord([{ type: [ChildClass, ChildClass2], array: true }, ChildClass3])
  record: Record<string, (ChildClass | ChildClass2)[] | ChildClass3>;
}

MustNotExistIf

MustNotExistIf(condition: (value: any) => boolean, jsonpath?: string, options?: ValidationOptions)

Check if the value must not exist if the condition is met.

Usage

import { MustNotExistIf } from '@apizr/class-utils/validators';

class User {
  @MustNotExistIf((o) => o.isGuest)
  password: string;

  isGuest: boolean;
}

const user = new User();
user.isGuest = true;
user.password = 'securePassword'; // Validation will fail because `isGuest` is true.

You can also use jsonpath-plus to validate a nested key:

import { MustNotExistIf } from '@apizr/class-utils/validators';

class UserProfile {
  @MustNotExistIf(
    (jsonpathValue) =>
      Array.isArray(jsonpathValue) && jsonpathValue.includes('restricted'),
    '$.roles[*]',
  )
  adminSettings: string;

  roles: string[];
}

const profile = new UserProfile();
profile.roles = ['user', 'restricted'];
profile.adminSettings = 'Some Settings'; // Validation will fail because "roles" contains "restricted".

Default error message is Property {{property}} must not exist if {{condition}} is true but you can override it by passing a message option in the ValidationOptions object.

IsUnion

IsUnion(allowedUnionType: AllowedType[], options: IsUnionValidateOptions)

Check if the union is compliant to specified definition.

Usage

import { IsUnion } from '@apizr/class-utils/validators';

class ChildClass {
  @IsString()
  key: string;
}

class ExampleClass {
  @IsUnion(['string', 'undefined'])
  union: string | undefined;

  @IsUnion(['string', 'number'], { each: true })
  union: (string | number)[];

  @IsUnion([ChildClass, ChildClass2, 'undefined'])
  union: ChildClass | ChildClass2 | undefined;

  @IsUnion([{ type: ChildClass, array: true }, ChildClass2])
  union: ChildClass[] | ChildClass2;

  @IsUnion([{ type: [ChildClass, ChildClass2], array: true }, ChildClass3])
  union: (ChildClass | ChildClass2)[] | ChildClass3;

  @IsUnion([
    {
      type: [
        ChildClass,
        {
          key: 'string',
          value: { type: ChildClass2, array: true },
        },
      ],
      array: true,
    },
    ChildClass3,
  ])
  union: (ChildClass | Record<string, ChildClass2[]>)[] | ChildClass3;
}

IsCron

IsCron(inputOptions?: InputOptions['override'])

Checks if the string is cron expression valid

See documentation of cron-validate lib to see the options.

Usage

import { IsCron } from '@apizr/class-utils/validators';

class ExampleClass {
  @IsCron()
  cronExpression: string;

  @IsCron({
    useSeconds: true,
  })
  cronExpression: string;
}

Dependents (0)

Package Sidebar

Install

npm i @apizr-io/class-utils

Weekly Downloads

181

Version

0.8.1

License

ISC

Unpacked Size

125 kB

Total Files

54

Last publish

Collaborators

  • apizr-admin