small-type-forms
v1.4.2
Published
TypeScript forms & validation library
Maintainers
Readme
small-forms-ts
Small Forms TS est une librairie de forms & validation inspirée du package PHP small/forms.
Elle apporte un système de formulaires typés, de validation, de transformation (modifiers),
ainsi qu'un support avancé pour DTOs via décorateurs et adaptateurs.
Ce package est conçu pour :
- Node
- SvelteKit
- Front-end TypeScript
- DTOs & mapping
- Interopérabilité small/type-dependency-injection
Installation
npm install small-type-forms reflect-metadataAjoutez dans votre tsconfig.json :
{
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}Puis dans votre bootstrap :
import "reflect-metadata";Quick Start avec décorateurs
Les validateurs et modifiers s'utilisent maintenant comme des décorateurs de propriété.
Il n'est plus nécessaire d'écrire new ValidateRequired() ou new TrimModifier() dans @FormField.
Un champ décoré uniquement avec des validateurs/modifiers est aussi enregistré automatiquement : @FormField n'est requis que si vous voulez forcer un type précis, renommer le champ, ou hydrater un objet imbriqué.
import {
ClassAdapter,
ValidateRequired,
ValidateEmail,
TrimModifier
} from "small-type-forms";
class UserDTO {
@TrimModifier()
@ValidateRequired()
@ValidateEmail()
email!: string;
}
const form = ClassAdapter.from(UserDTO);
form.fill({ email: " [email protected] " });
form.validate();
console.log(form.toObject());
// { email: "[email protected]" }FormBuilder
Le FormBuilder reste disponible pour créer un formulaire manuellement.
Les règles et modifiers restent représentés en interne par les interfaces Rule et Modifier.
Pour les cas avancés, vous pouvez utiliser UseRule(...) et UseModifier(...) avec vos propres implémentations.
FormBuilder.create()
.addField("name", new StringType())
.addField("age", new NumberType())
.getForm();Types
StringTypeNumberTypeBooleanTypeDateTypeMixedTypeObjectType
Validators décorateurs
Tous les validateurs s'appliquent maintenant directement sur une propriété. @FormField est optionnel pour les types simples :
class LoginDTO {
@TrimModifier()
@ValidateRequired()
@ValidateEmail()
email!: string;
}Liste des validateurs inclus
ValidateAtLeastOneOf
ValidateBoolean
ValidateCallback
ValidateChoice
ValidateCountLessOrEqualThan
ValidateCountGreaterThan
ValidateCountLessThan
ValidateDateTime
ValidateDecimal
ValidateDivisibleBy
ValidateEmail
ValidateString
ValidateStringArray
ValidateUnique
ValidateEmpty
ValidateEqual
ValidateFloat
ValidateFloatArray
ValidateGreater
ValidateGreaterOrEqual
ValidateInt
ValidateIntArray
ValidateIsFalse
ValidateIsNull
ValidateIsTrue
ValidateJson
ValidateLess
ValidateLessOrEqual
ValidateMatchRegex
ValidateMixedArray
ValidateNegativeNumber
ValidateNotEmpty
ValidateNotEqual
ValidateNotMatchRegex
ValidateNotNull
ValidateNumberCharsBetween
ValidateNumberCharLessThan
ValidatePositiveNumber
ValidateRange
ValidateRequired
ValidateSequencialy
ValidateInteger
ValidateInstanceOf
Modifiers décorateurs
Tous les modifiers s'appliquent aussi comme décorateurs :
class ProductDTO {
@FormField(new StringType())
@TrimModifier()
@ToLowerModifier()
slug!: string;
}Modifiers inclus
ExplodeModifier
FalseIfEmptyModifier
FormBooleanToPhpModifier
ImplodeModifier
LTrimModifier
NullIfEmptyModifier
RoundModifier
RTrimModifier
StringToDateTimeImmutableModifier
StringToDateTimeModifier
SubStrModifier
ToLowerModifier
ToUpperModifier
TrimModifier
UcFirstModifier
UcWordsModifier
Objets imbriqués
Utilisez ObjectType quand un champ doit être hydraté comme une instance de classe.
ValidateInstanceOf permet ensuite de vérifier le type obtenu.
import {
ClassAdapter,
FormField,
ObjectType,
TrimModifier,
ValidateInstanceOf,
ValidateRequired
} from "small-type-forms";
class ShopAddress {
constructor(init?: Partial<ShopAddress>) {
Object.assign(this, init);
}
@ValidateRequired()
@TrimModifier()
street!: string;
}
class Shop {
@ValidateRequired()
@ValidateInstanceOf(ShopAddress)
@FormField(new ObjectType(ShopAddress))
address!: ShopAddress;
}
const form = ClassAdapter.from(Shop);
form.fill({ address: { street: " rue de la paix " } });
form.validate();
const shop = form.hydrate(new Shop());
console.log(shop.address instanceof ShopAddress); // true
console.log(shop.address.street); // "rue de la paix"Décorateurs personnalisés
Vous pouvez conserver vos propres règles/modifiers via les interfaces bas niveau :
import { FormField, StringType, UseRule, type Rule } from "small-type-forms";
class MyRule implements Rule {
validate(value: unknown): string | null {
return value === "ok" ? null : "Value must be ok.";
}
}
class DTO {
@FormField(new StringType())
@UseRule(new MyRule())
value!: string;
}Adapters
ClassAdapter
const form = ClassAdapter.from(UserDTO);
form.fill(dto);
form.validate();ObjectAdapter
const form = ObjectAdapter.fromObject({ name: "seb", age: 33 });Intégration SvelteKit
export const actions = {
default: async ({ request }) => {
const data = Object.fromEntries(await request.formData());
const form = ObjectAdapter.fromObject(data);
try {
form.validate();
return { success: true };
} catch (e) {
return fail(400, { errors: e.errors });
}
}
};Licence
MIT — Sébastien Kus
https://small-project.dev
