Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

adria-forms

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

adria-forms - npm Package Compare versions

Comparing version 0.2.4 to 0.3.0

16

form.d.ts
declare type MaybePromise<T> = T | Promise<T>;
declare type FormDataMap<T = any> = Map<T, any | null>;
declare type Validate<T> = (value: any | null, form: FormDataMap<T>) => MaybePromise<any | void>;
declare type ParseFunction<T> = (value: any | null, form: FormDataMap<T>) => MaybePromise<any>;
declare type Not<T, A> = T extends A ? never : T;
declare type FieldRecord<T> = Record<string, Validate<T>>;
declare type ErrorRecord<F extends FieldRecord<string> | FieldRecord<never>> = {
declare type FieldRecord<T> = Record<string, ParseFunction<T>>;
declare type ResultRecord<F extends FieldRecord<string> | FieldRecord<never>> = {
[FieldName in keyof F]: Awaited<ReturnType<F[FieldName]>>;

@@ -12,5 +12,11 @@ };

constructor(fields?: Fields);
field: <FieldName extends string, V extends Validate<FieldName | keyof Fields>>(fieldName: Not<FieldName, keyof Fields>, validate: V) => Form<Fields & Record<FieldName, V>>;
validate: (formData: FormData | Record<string, string | number>) => Promise<ErrorRecord<Fields> | null>;
field: <FieldName extends string, PF extends ParseFunction<FieldName | keyof Fields>>(fieldName: Not<FieldName, keyof Fields>, parseFunction: PF) => Form<Fields & Record<FieldName, PF>>;
parse: (formData: FormData | Record<string, string | number>) => Promise<{
errors: null;
data: ResultRecord<Fields>;
} | {
errors: { [k in keyof Fields]?: unknown; };
data: null;
}>;
}
export {};

@@ -6,7 +6,7 @@ export class Form {

}
field = (fieldName, validate) => {
this.fields[fieldName] = validate;
field = (fieldName, parseFunction) => {
this.fields[fieldName] = parseFunction;
return this;
};
validate = async (formData) => {
parse = async (formData) => {
const errors = {};

@@ -16,13 +16,25 @@ const formDataMap = formData instanceof FormData

: new Map(Object.entries(formData));
for (const [fieldName, validate] of Object.entries(this.fields)) {
const data = {};
for (const [fieldName, parse] of Object.entries(this.fields)) {
const formValue = formDataMap.get(fieldName);
const result = await validate(formValue, formDataMap);
if (result === undefined)
continue;
errors[fieldName] = result;
try {
const parseResult = await parse(formValue, formDataMap);
if (parseResult === undefined)
continue;
data[fieldName] = parseResult;
}
catch (e) {
errors[fieldName] = e;
}
}
if (Object.keys(errors).length > 0)
return errors;
return null;
return {
errors: errors,
data: null,
};
return {
errors: null,
data: data,
};
};
}
{
"name": "adria-forms",
"version": "0.2.4",
"version": "0.3.0",
"description": "A super simple form validation library",

@@ -5,0 +5,0 @@ "main": "index.js",

# Adria
A super simple form validation library, with autocomplete and value/type checking using the power of TypeScript.
A super simple form validation and parsing library written in TypeScript. Works both in the client and server.
```bash
npm i adria-forms
yarn add adria-forms
pnpm add adria-forms
```

@@ -17,6 +19,6 @@

const form = new Form().field("username", (value) => {
if (!value) return "Please enter your username";
if (typeof value !== "string") return "Invalid input";
if (value.length < 4) return "Username must be at least 4 characters long";
return; // success
if (!value) throw "Please enter your username";
if (typeof value !== "string") throw "Invalid input";
if (value.length < 4) throw "Username must be at least 4 characters long";
return value;
});

@@ -26,7 +28,6 @@

const errors = await form.validate(formData);
/*
usernameError will be typed as "Please enter..." or "Username must be..."
*/
const usernameError = errors?.username; // autocomplete
const { data, errors } = await form.parse(formData);
// intellisense
const usernameError = errors?.username;
const { username } = data;
```

@@ -36,17 +37,19 @@

### .field()
## `Form`
Creates a new field. `fieldName` cannot be an existing field name, and `validate` can be a synchronous or asynchronous function. A `void` return from `validate` will tell Adria the value has passed the validation.
#### `field()`
Creates a new field. `fieldName` cannot be an existing field name, and `parse` can be a synchronous or asynchronous function. The return value will be mapped to `data[fieldName]` of the return type of `parse()`.
```ts
const field: (
fieldName: string,
validate: (
parse: (
value: null | FormDataEntryValue,
formData: Map<string, FormDataEntryValue | null>
) => MaybePromise<void | any>
) => this;
) => MaybePromise<any>
) => Form;
```
#### Example
##### Example

@@ -57,7 +60,7 @@ ```ts

if (!value)
return {
throw {
code: 0,
message: "empty input",
};
return; // success
return value; // success
})

@@ -74,10 +77,11 @@ .field("password", (_, formData) => {

### .validate()
#### `parse()`
Validates the form data. Will only check fields defined with `.field()`. Will return `null` if the form data is valid or a `fieldName:errorMessage` record if not.
Validates and parses the form data. Will only check fields defined with `.field()`. Either `errors` or `data` will be `null`, but not both.
```ts
const validate: (
formData: FormData | Record<any, any>
) => Promise<Record<string, any> | null>;
const parse: (formData: FormData | Record<any, any>) => Promise<{
errors: Record<string, any> | null; // <fieldName, error>
data: Record<string, any> | null; // <fieldName, parseResult>
}>;
```

@@ -89,32 +93,18 @@

const form = new Form()
.field("username", () => {
return "error";
.field("username", (val) => {
return val;
})
.field("password", () => {
return {
code: 0,
};
.field("password", (val) => {
if (invalid) throw Error;
return val;
});
const errors = await form.validate(formData);
const { errors, data } = await form.parse(formData);
const userNameError: "fail" = errors.username; // autocomplete username, password
const randomError = errors.random; // TS will yell at you since field random does not exist
const passwordErrorCode: number = errors.password.code; // since password can return an object, code will be typed as number and not 0
```
## TypeScript
In the previous example (`validate()`), errors will only be typed with a value when the validate function returns a string/number. We can fix this by typing the return value of the validate function `as const`.
```ts
const form = new Form().field("password", () => {
return {
code: 0,
} as const;
});
const errors = await form.validate(formData as FormData);
const passwordErrorCode: number = errors.password.code; // typed as 0, and not number as before
```
if (errors) {
const usernameError: undefined | unknown = errors.username;
const passwordError: undefined | unknown = errors.password;
} else {
const { username, password } = data;
}
```

@@ -1,6 +0,6 @@

export declare const pattern: <R extends RegExp, E extends unknown>(regexp: R, error: E) => (value: any) => E | undefined;
export declare const max: <Max extends number, E extends unknown>(maxNum: Max, error: E) => (value: any) => E | undefined;
export declare const min: <Min extends number, E extends unknown>(minNum: Min, error: E) => (value: any) => E | undefined;
export declare const maxLength: <Max extends number, E extends unknown>(maxNum: Max, error: E) => (value: any) => E | undefined;
export declare const minLength: <Min extends number, E extends unknown>(minNum: Min, error: E) => (value: any) => E | undefined;
export declare const required: <E extends unknown>(error: E) => (value: any) => E | undefined;
export declare const pattern: (regexp: RegExp, error: any) => (value: any) => string;
export declare const max: (maxNum: number, error: any) => (value: any) => number;
export declare const min: (minNum: number, error: any) => (value: any) => number;
export declare const maxLength: (maxNum: number, error: any) => (value: any) => string;
export declare const minLength: (minNum: number, error: any) => (value: any) => string;
export declare const required: (error: any) => (value: any) => string;
export const pattern = (regexp, error) => {
return (value) => {
if (typeof value !== "string")
return error;
throw error;
if (!regexp.test(value))
return error;
throw error;
return value;
};

@@ -11,6 +12,8 @@ };

return (value) => {
if (typeof value !== "string" && typeof value !== "number")
return error;
if (Number(value) > maxNum)
return error;
const parsedValue = Number(value);
if (isNaN(parsedValue))
throw error;
if (parsedValue > maxNum)
throw error;
return parsedValue;
};

@@ -20,6 +23,8 @@ };

return (value) => {
if (typeof value !== "string" && typeof value !== "number")
return error;
if (Number(value) < minNum)
return error;
const parsedValue = Number(value);
if (isNaN(parsedValue))
throw error;
if (parsedValue < minNum)
throw error;
return parsedValue;
};

@@ -30,5 +35,7 @@ };

if (typeof value !== "string" && typeof value !== "number")
return error;
if (value.toString().length > maxNum)
return error;
throw error;
const parsedValue = value.toString();
if (parsedValue.length > maxNum)
throw error;
return parsedValue;
};

@@ -39,5 +46,7 @@ };

if (typeof value !== "string" && typeof value !== "number")
return error;
if (value.toString().length < minNum)
return error;
throw error;
const parsedValue = value.toString();
if (parsedValue.length < minNum)
throw error;
return parsedValue;
};

@@ -48,6 +57,8 @@ };

if (typeof value !== "string" && typeof value !== "number")
return error;
if (value.toString().length < 1)
return error;
throw error;
const parsedValue = value.toString();
if (parsedValue.length < 1)
throw error;
return parsedValue;
};
};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc