chore: improved validations
This commit is contained in:
parent
613c298410
commit
6526935620
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -12,6 +12,7 @@
|
||||
"Cachaça",
|
||||
"Caturra",
|
||||
"Coren",
|
||||
"EAN",
|
||||
"espadín",
|
||||
"Genever",
|
||||
"Jägermeister",
|
||||
@ -42,6 +43,7 @@
|
||||
"Robusta",
|
||||
"RRP",
|
||||
"screwcap",
|
||||
"SKU",
|
||||
"Soju",
|
||||
"Sokujō",
|
||||
"Solera",
|
||||
@ -50,6 +52,7 @@
|
||||
"Tequilana",
|
||||
"tobalá",
|
||||
"Typica",
|
||||
"UPC",
|
||||
"Verte",
|
||||
"VSOP",
|
||||
"Yamahai",
|
||||
|
@ -4,3 +4,4 @@ export * from './review'
|
||||
export * from './wine'
|
||||
export * from './spirit'
|
||||
export * from './product'
|
||||
export * from './validations'
|
||||
|
@ -3,23 +3,37 @@ import {
|
||||
Ingredient,
|
||||
SpiritType,
|
||||
SpiritVolume,
|
||||
VintageOptions,
|
||||
SpiritCharacteristics
|
||||
} from '../../types'
|
||||
import { isObject, spiritVariantMap, spiritCharacteristicsMap } from '../'
|
||||
import {
|
||||
vintageValidation,
|
||||
productCodeEANvalidation,
|
||||
productCodeUPCvalidation,
|
||||
productCodeSKUvalidation,
|
||||
countryValidation,
|
||||
nameValidation,
|
||||
typeValidation,
|
||||
producerIdValidation,
|
||||
volumeValidation,
|
||||
alcoholValidation,
|
||||
RRPamountValidation,
|
||||
RRPcurrencyValidation,
|
||||
descriptionValidation,
|
||||
urlValidation,
|
||||
imageValidation
|
||||
} from './'
|
||||
|
||||
export const spiritValidation = (data: unknown): Joi.ValidationResult =>
|
||||
Joi.object({
|
||||
productCodeEAN: Joi.string().allow('').required(),
|
||||
productCodeUPC: Joi.string().allow('').required(),
|
||||
productCodeSKU: Joi.string().allow('').required(),
|
||||
country: Joi.string().length(2),
|
||||
productCodeEAN: productCodeEANvalidation,
|
||||
productCodeUPC: productCodeUPCvalidation,
|
||||
productCodeSKU: productCodeSKUvalidation,
|
||||
country: countryValidation,
|
||||
region: Joi.string(),
|
||||
name: Joi.string().required(),
|
||||
producerId: Joi.string().length(24).required(),
|
||||
type: Joi.string()
|
||||
.valid(...Object.values(SpiritType))
|
||||
.required(),
|
||||
name: nameValidation,
|
||||
producerId: producerIdValidation,
|
||||
type: typeValidation(SpiritType),
|
||||
variant: Joi.alternatives().try(
|
||||
Joi.string().custom((variant, helper) => {
|
||||
// return if no value
|
||||
@ -267,23 +281,15 @@ export const spiritValidation = (data: unknown): Joi.ValidationResult =>
|
||||
})
|
||||
)
|
||||
.required(),
|
||||
|
||||
ingredients: Joi.array()
|
||||
.items(Joi.string().valid(...Object.values(Ingredient)))
|
||||
.required(),
|
||||
volume: Joi.string()
|
||||
.valid(...Object.values(SpiritVolume))
|
||||
.required(),
|
||||
alcohol: Joi.number().min(0).max(0.99).required(),
|
||||
vintage: Joi.alternatives()
|
||||
.try(
|
||||
Joi.string().valid(...Object.values(VintageOptions)),
|
||||
Joi.number().min(1700).max(new Date().getFullYear())
|
||||
)
|
||||
.required(),
|
||||
RRPamount: Joi.number().required(),
|
||||
RRPcurrency: Joi.string().length(3).required(),
|
||||
description: Joi.string().required(),
|
||||
url: Joi.string(),
|
||||
image: Joi.string()
|
||||
volume: volumeValidation(SpiritVolume),
|
||||
alcohol: alcoholValidation,
|
||||
vintage: vintageValidation,
|
||||
RRPamount: RRPamountValidation,
|
||||
RRPcurrency: RRPcurrencyValidation,
|
||||
description: descriptionValidation,
|
||||
url: urlValidation,
|
||||
image: imageValidation
|
||||
}).validate(data)
|
||||
|
38
src/utils/validation/validations.ts
Normal file
38
src/utils/validation/validations.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import Joi from 'joi'
|
||||
import { VintageOptions } from '../../types'
|
||||
|
||||
export const vintageValidation = Joi.alternatives()
|
||||
.try(
|
||||
Joi.string().valid(...Object.values(VintageOptions)),
|
||||
Joi.number().min(1700).max(new Date().getFullYear())
|
||||
)
|
||||
.required()
|
||||
|
||||
export const productCodeEANvalidation = Joi.string().allow('').required()
|
||||
export const productCodeUPCvalidation = Joi.string().allow('').required()
|
||||
export const productCodeSKUvalidation = Joi.string().allow('').required()
|
||||
|
||||
export const countryValidation = Joi.string().length(2)
|
||||
|
||||
export const nameValidation = Joi.string().required()
|
||||
|
||||
export const typeValidation = (typeEnum: { [key: string]: string }) =>
|
||||
Joi.string()
|
||||
.valid(...Object.values(typeEnum))
|
||||
.required()
|
||||
|
||||
export const producerIdValidation = Joi.string().length(24).required()
|
||||
|
||||
export const volumeValidation = (volumeEnum: { [key: string]: string }) =>
|
||||
Joi.string()
|
||||
.valid(...Object.values(volumeEnum))
|
||||
.required()
|
||||
|
||||
export const alcoholValidation = Joi.number().min(0).max(0.99).required()
|
||||
|
||||
export const RRPamountValidation = Joi.number().required()
|
||||
export const RRPcurrencyValidation = Joi.string().length(3).required()
|
||||
|
||||
export const descriptionValidation = Joi.string().required()
|
||||
export const urlValidation = Joi.string()
|
||||
export const imageValidation = Joi.string()
|
@ -1,7 +1,6 @@
|
||||
import Joi from 'joi'
|
||||
import {
|
||||
WineType,
|
||||
VintageOptions,
|
||||
BottleClosure,
|
||||
Viticulture,
|
||||
WineRegion,
|
||||
@ -13,90 +12,30 @@ import {
|
||||
RedWineCharacteristic
|
||||
} from '../../types'
|
||||
import { wineRegionsMap, isObject } from '../'
|
||||
import {
|
||||
vintageValidation,
|
||||
productCodeEANvalidation,
|
||||
productCodeUPCvalidation,
|
||||
productCodeSKUvalidation,
|
||||
countryValidation,
|
||||
nameValidation,
|
||||
typeValidation,
|
||||
producerIdValidation,
|
||||
volumeValidation,
|
||||
alcoholValidation,
|
||||
RRPamountValidation,
|
||||
RRPcurrencyValidation,
|
||||
descriptionValidation,
|
||||
urlValidation,
|
||||
imageValidation
|
||||
} from './'
|
||||
|
||||
export const wineValidation = (data: unknown): Joi.ValidationResult =>
|
||||
Joi.object({
|
||||
productCodeEAN: Joi.string().allow('').required(),
|
||||
productCodeUPC: Joi.string().allow('').required(),
|
||||
productCodeSKU: Joi.string().allow('').required(),
|
||||
type: Joi.string()
|
||||
.valid(...Object.values(WineType))
|
||||
.required(),
|
||||
style: Joi.string()
|
||||
.valid(...Object.values(WineStyle))
|
||||
.required(),
|
||||
characteristics: Joi.array()
|
||||
.items(Joi.string())
|
||||
.custom((value: string[], helper) => {
|
||||
// return if no value
|
||||
if (!value) {
|
||||
return value
|
||||
}
|
||||
// return if no state ancestors
|
||||
if (!helper.state.ancestors) {
|
||||
return value
|
||||
}
|
||||
|
||||
const wineType: WineType = helper.state.ancestors[0].type
|
||||
|
||||
// return if no wineType
|
||||
if (!wineType) {
|
||||
return value
|
||||
}
|
||||
|
||||
let options: string[] = []
|
||||
|
||||
switch (wineType) {
|
||||
case WineType.White:
|
||||
{
|
||||
options = Object.values(WhiteWineCharacteristic)
|
||||
}
|
||||
|
||||
break
|
||||
case WineType.Amber:
|
||||
{
|
||||
options = Object.values(AmberWineCharacteristic)
|
||||
}
|
||||
|
||||
break
|
||||
case WineType.Rose:
|
||||
{
|
||||
options = Object.values(RoseWineCharacteristic)
|
||||
}
|
||||
|
||||
break
|
||||
case WineType.Red:
|
||||
{
|
||||
options = Object.values(RedWineCharacteristic)
|
||||
}
|
||||
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if (!options.length) {
|
||||
return helper.message({
|
||||
custom: Joi.expression(
|
||||
`no characteristics found for provided type of wine`
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
for (const characteristic of value) {
|
||||
if (!options.includes(characteristic)) {
|
||||
return helper.message({
|
||||
custom: Joi.expression(
|
||||
`"${characteristic}" is not a valid characteristic for "${wineType}" wine. Valid options are [${options.map((option) => `"${option}"`).join(', ')}]`
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return value
|
||||
}),
|
||||
country: Joi.string().length(2),
|
||||
productCodeEAN: productCodeEANvalidation,
|
||||
productCodeUPC: productCodeUPCvalidation,
|
||||
productCodeSKU: productCodeSKUvalidation,
|
||||
country: countryValidation,
|
||||
// TODO: improve types
|
||||
region: Joi.alternatives()
|
||||
.try(
|
||||
@ -356,19 +295,87 @@ export const wineValidation = (data: unknown): Joi.ValidationResult =>
|
||||
)
|
||||
.allow('')
|
||||
.required(),
|
||||
name: Joi.string().required(),
|
||||
producerId: Joi.string().length(24).required(),
|
||||
name: nameValidation,
|
||||
producerId: producerIdValidation,
|
||||
type: typeValidation(WineType),
|
||||
style: Joi.string()
|
||||
.valid(...Object.values(WineStyle))
|
||||
.required(),
|
||||
characteristics: Joi.array()
|
||||
.items(Joi.string())
|
||||
.custom((value: string[], helper) => {
|
||||
// return if no value
|
||||
if (!value) {
|
||||
return value
|
||||
}
|
||||
// return if no state ancestors
|
||||
if (!helper.state.ancestors) {
|
||||
return value
|
||||
}
|
||||
|
||||
const wineType: WineType = helper.state.ancestors[0].type
|
||||
|
||||
// return if no wineType
|
||||
if (!wineType) {
|
||||
return value
|
||||
}
|
||||
|
||||
let options: string[] = []
|
||||
|
||||
switch (wineType) {
|
||||
case WineType.White:
|
||||
{
|
||||
options = Object.values(WhiteWineCharacteristic)
|
||||
}
|
||||
|
||||
break
|
||||
case WineType.Amber:
|
||||
{
|
||||
options = Object.values(AmberWineCharacteristic)
|
||||
}
|
||||
|
||||
break
|
||||
case WineType.Rose:
|
||||
{
|
||||
options = Object.values(RoseWineCharacteristic)
|
||||
}
|
||||
|
||||
break
|
||||
case WineType.Red:
|
||||
{
|
||||
options = Object.values(RedWineCharacteristic)
|
||||
}
|
||||
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if (!options.length) {
|
||||
return helper.message({
|
||||
custom: Joi.expression(
|
||||
`no characteristics found for provided type of wine`
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
for (const characteristic of value) {
|
||||
if (!options.includes(characteristic)) {
|
||||
return helper.message({
|
||||
custom: Joi.expression(
|
||||
`"${characteristic}" is not a valid characteristic for "${wineType}" wine. Valid options are [${options.map((option) => `"${option}"`).join(', ')}]`
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return value
|
||||
}),
|
||||
varietal: Joi.string().required(),
|
||||
vintage: Joi.alternatives()
|
||||
.try(
|
||||
Joi.string().valid(...Object.values(VintageOptions)),
|
||||
Joi.number().min(1700).max(new Date().getFullYear())
|
||||
)
|
||||
.required(),
|
||||
volume: Joi.string()
|
||||
.valid(...Object.values(WineVolume))
|
||||
.required(),
|
||||
alcohol: Joi.number().min(0).max(0.99).required(),
|
||||
volume: volumeValidation(WineVolume),
|
||||
alcohol: alcoholValidation,
|
||||
vintage: vintageValidation,
|
||||
viticulture: Joi.string()
|
||||
.valid(...Object.values(Viticulture))
|
||||
.required(),
|
||||
@ -379,9 +386,9 @@ export const wineValidation = (data: unknown): Joi.ValidationResult =>
|
||||
closure: Joi.string()
|
||||
.valid(...Object.values(BottleClosure))
|
||||
.required(),
|
||||
RRPamount: Joi.number().required(),
|
||||
RRPcurrency: Joi.string().length(3).required(),
|
||||
description: Joi.string().required(),
|
||||
url: Joi.string(),
|
||||
image: Joi.string()
|
||||
RRPamount: RRPamountValidation,
|
||||
RRPcurrency: RRPcurrencyValidation,
|
||||
description: descriptionValidation,
|
||||
url: urlValidation,
|
||||
image: imageValidation
|
||||
}).validate(data)
|
||||
|
Loading…
x
Reference in New Issue
Block a user