feat: Filemagedon
Some checks failed
Build, check & Test / run (push) Failing after 1m45s
Lint / run (push) Failing after 48s
Build Docker Image / build_docker (push) Failing after 3m18s

Signed-off-by: Avior <git@avior.me>
This commit is contained in:
2024-09-11 14:38:58 +02:00
parent 3e91597dca
commit bc97d9106b
45 changed files with 4548 additions and 64 deletions

View File

@ -0,0 +1,169 @@
import type { ValidationResult } from '.'
import Schema from '.'
import { isNull } from './utils'
export interface Messages {
globalInvalid: string
}
/**
* An element of a schema
*/
export default abstract class SchemaItem<T> {
/**
* get additionnal attributes used to make the Schema work with outside libs
*/
public attributes: Array<string> = []
/**
* the list of validations
*/
protected validations: Array<{
fn: (input: T) => boolean
message?: string | undefined
}> = []
protected parseActions: Array<(input: unknown) => T | unknown> = []
protected transforms: Array<(input: T) => T> = []
/**
* set the list of attributes for the item of the schema
* @param attributes the attributes
*/
public attr(...attributes: Array<string>) {
this.attributes = attributes
return this
}
/**
* set the default value of the schema element
* @param value the default value
* @param strict if strict, it will use it for null/undefined, else it will check for falthy values
*/
public defaultValue(value: T, strict = true) {
this.parseActions.push((input) => {
if (strict && isNull(input)) {
return value
}
if (!value) {
return input
}
return input
})
return this
}
/**
*
* @param values the possible values the field can be
* @param message the message returned if it does not respect the value
*/
public in(values: Array<T>, message?: string) {
this.validations.push({
fn: (input) => values.includes(input),
message
})
return this
}
/**
* Try to parse the input from another format
*
* @param input the input to transform, it is done before validation, so the value can be anything
* @returns the transformed value
*/
public parse(input: unknown): T | unknown {
for (const transform of this.parseActions) {
const tmp = transform(input)
if (this.isOfType(tmp)) {
return tmp
}
}
return input
}
/**
* transform a valid value
*
* @param input the input to transform, it MUST be validated beforehand
* @returns the transformed value
*/
public transform(input: T): T {
let res = input
for (const action of this.transforms) {
res = action(res)
}
return res
}
/**
* validate that the input is valid or not
* @param input the input to validate
* @param fast if true the validation stops at the first error
* @returns a string if it's not valid, else null
*/
public validate(input: T, fast = false): ValidationResult<T> {
for (const validation of this.validations) {
if (!validation.fn(input as T)) {
return {
error: [{
message: validation.message ?? Schema.messages.globalInvalid
}]
}
}
}
return {
object: input as T
}
}
/**
* validate that the input value is of the type of the schema item
*
* it makes others functions easier to works with
* @param input the input to validate
*/
public abstract isOfType(input: unknown): input is T
// public abstract toJSON(): JSONSchemaItem
}
type Parseable = string | number | boolean
export interface ValidatorJSON {
/**
* the function name (ex: `min`, `max`)
*/
name: string
/**
* the function parameters
*/
params?: Array<Parseable>
}
export interface JSONSchemaItem {
/**
* Schema item
*
* ex: `string`, `number`, `boolean`, ...
*/
type: string
/**
* constructor params
*/
params?: Array<Parseable>
/**
* list of attributes
*/
attributes?: Array<string>
actions?: Array<ValidatorJSON>
}
export type JSONSchema = {
[a: string]: JSONSchemaItem
}