178 lines
5.3 KiB
TypeScript
178 lines
5.3 KiB
TypeScript
import Trava from "trava"
|
|
import {spec, isPojo} from "@welshman/lib"
|
|
import {isRelayUrl, Address} from "@welshman/util"
|
|
import {Scope, FeedType} from "./core.js"
|
|
import {getFeedArgs} from "./utils.js"
|
|
|
|
const {ValidationError, Compose, Check, Each, Optional, Keys} = Trava
|
|
|
|
const validateNumber = Check((x: any) => typeof x === "number", "Value must be a number")
|
|
|
|
const validateString = Check((x: any) => typeof x === "string", "Value must be a string")
|
|
|
|
const validateRelay = Check((x: any) => typeof x === "string" && isRelayUrl(x), "Invalid relay url")
|
|
|
|
const validateScope = Check((x: any) => Object.values(Scope).includes(x), "Invalid scope")
|
|
|
|
const validateHex = Check((x: any) => typeof x === "string" && x.length === 64, "Invalid hex value")
|
|
|
|
const validateAddress = Check(
|
|
(x: any) => typeof x === "string" && Address.isAddress(x),
|
|
"Invalid address",
|
|
)
|
|
|
|
const validateArray = Check((x: any) => Array.isArray(x), "Value must be an array")
|
|
|
|
const validateObject = Check((x: any) => isPojo(x), "Value must be an object")
|
|
|
|
export {ValidationError}
|
|
|
|
export const validateTagFeedMapping = Compose([
|
|
validateArray,
|
|
Check(spec({length: 2}), "Tag feed mappings must have two entries"),
|
|
(a: any[]) => validateString(a[0]),
|
|
(a: any[]) => validateFeed(a[1]),
|
|
])
|
|
|
|
export const validateFeedArgs = (validateArgument: Trava.Validator) => (feed: any) => {
|
|
let error = validateArray(feed)
|
|
if (error instanceof ValidationError) return error
|
|
|
|
for (const argument of getFeedArgs(feed)) {
|
|
error = validateArgument(argument)
|
|
if (error instanceof ValidationError) return error
|
|
}
|
|
|
|
return feed
|
|
}
|
|
|
|
export const validateAddressFeed = validateFeedArgs(validateAddress)
|
|
|
|
export const validateAuthorFeed = validateFeedArgs(validateHex)
|
|
|
|
export const validateCreatedAtFeed = validateFeedArgs(
|
|
Keys({
|
|
since: Optional(validateNumber),
|
|
until: Optional(validateNumber),
|
|
relative: Optional(Each(validateString)),
|
|
}),
|
|
)
|
|
|
|
export const validateDVMFeed = validateFeedArgs(
|
|
Keys({
|
|
kind: validateNumber,
|
|
tags: Optional(Each(validateString)),
|
|
relays: Optional(Each(validateString)),
|
|
mappings: Optional(Each(validateTagFeedMapping)),
|
|
}),
|
|
)
|
|
|
|
export const validateDifferenceFeed = validateFeedArgs((x: any) => validateFeed(x))
|
|
|
|
export const validateIDFeed = validateFeedArgs(validateHex)
|
|
|
|
export const validateIntersectionFeed = validateFeedArgs((x: any) => validateFeed(x))
|
|
|
|
export const validateGlobalFeed = validateFeedArgs((x: any) => validateFeed(x))
|
|
|
|
export const validateKindFeed = validateFeedArgs(validateNumber)
|
|
|
|
export const validateListFeed = validateFeedArgs(
|
|
Keys({
|
|
addresses: Optional(Each(validateString)),
|
|
mappings: Optional(Each(validateTagFeedMapping)),
|
|
}),
|
|
)
|
|
|
|
export const validateLabelFeed = validateFeedArgs(
|
|
Compose([
|
|
validateObject,
|
|
(item: any) => {
|
|
const validateRelays = Each(validateRelay)
|
|
const validateAuthors = Each(validateHex)
|
|
const validateStrings = Each(validateString)
|
|
const validateMappings = Each(validateTagFeedMapping)
|
|
|
|
for (const [key, value] of Object.entries(item)) {
|
|
let error
|
|
if (key === "relays") {
|
|
error = validateRelays(value)
|
|
} else if (key === "authors") {
|
|
error = validateAuthors(value)
|
|
} else if (key === "mappings") {
|
|
error = validateMappings(value)
|
|
} else if (key.match("^#.$")) {
|
|
error = validateStrings(value)
|
|
} else {
|
|
error = new ValidationError("Invalid label item")
|
|
}
|
|
|
|
if (error instanceof ValidationError) return error
|
|
}
|
|
|
|
return item
|
|
},
|
|
]),
|
|
)
|
|
|
|
export const validateWOTFeed = validateFeedArgs(
|
|
Keys({
|
|
min: Optional(validateNumber),
|
|
max: Optional(validateNumber),
|
|
}),
|
|
)
|
|
|
|
export const validateRelayFeed = validateFeedArgs(validateRelay)
|
|
|
|
export const validateScopeFeed = validateFeedArgs(validateScope)
|
|
|
|
export const validateSearchFeed = validateFeedArgs(validateString)
|
|
|
|
export const validateTagFeed = validateFeedArgs(validateString)
|
|
|
|
export const validateUnionFeed = validateFeedArgs((x: any) => validateFeed(x))
|
|
|
|
export const validateFeed = (feed: any) => {
|
|
const error = validateArray(feed)
|
|
if (error instanceof ValidationError) return error
|
|
|
|
switch (feed[0]) {
|
|
case FeedType.Address:
|
|
return validateAddressFeed(feed)
|
|
case FeedType.Author:
|
|
return validateAuthorFeed(feed)
|
|
case FeedType.CreatedAt:
|
|
return validateCreatedAtFeed(feed)
|
|
case FeedType.DVM:
|
|
return validateDVMFeed(feed)
|
|
case FeedType.Difference:
|
|
return validateDifferenceFeed(feed)
|
|
case FeedType.ID:
|
|
return validateIDFeed(feed)
|
|
case FeedType.Intersection:
|
|
return validateIntersectionFeed(feed)
|
|
case FeedType.Global:
|
|
return validateGlobalFeed(feed)
|
|
case FeedType.Kind:
|
|
return validateKindFeed(feed)
|
|
case FeedType.List:
|
|
return validateListFeed(feed)
|
|
case FeedType.Label:
|
|
return validateLabelFeed(feed)
|
|
case FeedType.WOT:
|
|
return validateWOTFeed(feed)
|
|
case FeedType.Relay:
|
|
return validateRelayFeed(feed)
|
|
case FeedType.Scope:
|
|
return validateScopeFeed(feed)
|
|
case FeedType.Search:
|
|
return validateSearchFeed(feed)
|
|
case FeedType.Tag:
|
|
return validateTagFeed(feed)
|
|
case FeedType.Union:
|
|
return validateUnionFeed(feed)
|
|
default:
|
|
return new ValidationError("Unknown feed type")
|
|
}
|
|
}
|