A
arktypeā€¢4mo ago
Dimava

Usage for HTTP validation

I'm looking to use Arktype as a Request/Response validator This comes with the following requirements: - Request body should be validated with deep reject unknownKeys so invalid requests are immediately 422 - Response should be validated with deep delete unknownKeys so local information can't passthrough - Response input should be cloned rather then inline-morphed (including key deletion) so you can pass in input objects as-is
let User = type({ name: string, meta: { bio: 'string' } })
let CreateUser = type([ User, '&', { password: string, meta: { age: 'number' } } ])
let UserModel = type([ CreateUser, '&', { meta: { isAdult: 'boolean' } } ])

let oneUser: UserModel;
function addUser(user: CreateUser) {
// should throw on inputs with extra keys on user and on user.meta
let newUser = AT_asHttpIn(CreateUser).assert(user)
newUser.meta.isAdult = newUser.meta.age >= 18
oneUser = AT_strict(UserModel).assert(newUser)
}
function getUser() {
// should remove password and age
// should not remove them on actual data
return AT_asHttpOut(User).assert(oneUser)
}
let User = type({ name: string, meta: { bio: 'string' } })
let CreateUser = type([ User, '&', { password: string, meta: { age: 'number' } } ])
let UserModel = type([ CreateUser, '&', { meta: { isAdult: 'boolean' } } ])

let oneUser: UserModel;
function addUser(user: CreateUser) {
// should throw on inputs with extra keys on user and on user.meta
let newUser = AT_asHttpIn(CreateUser).assert(user)
newUser.meta.isAdult = newUser.meta.age >= 18
oneUser = AT_strict(UserModel).assert(newUser)
}
function getUser() {
// should remove password and age
// should not remove them on actual data
return AT_asHttpOut(User).assert(oneUser)
}
Please list recommended AT APIs for this Please link the related undone issues is any
36 Replies
Unknown User
Unknown Userā€¢4mo ago
Message Not Public
Sign In & Join Server To View
Dimava
Dimavaā€¢4mo ago
Well, it's either 400 or 422, and if you want to 400 for whatever else it's 422 Github uses 422 Validation failed As I understood it's history, 422 did mean "you sent valid XML but its contents is šŸ’©" So 400 is more or JSON.parse failure then validation failure @ssalbdivad ping
ssalbdivad
ssalbdivadā€¢4mo ago
I've already answered this haven't I?
Dimava
Dimavaā€¢4mo ago
ah, it's still sumday, nevermind
ssalbdivad
ssalbdivadā€¢4mo ago
I am working today Oh Maybe you meant the m
Dimava
Dimavaā€¢4mo ago
I've made this #questions so I don't ever ask it again
ssalbdivad
ssalbdivadā€¢4mo ago
Actually I added a deep param for onUndeclaredKey I still can't configure it at a scope level yet that's tricky and kinda what I'm working on now Have to be very careful with caching across scopes
Dimava
Dimavaā€¢4mo ago
So, I'd like to have a unit test for this So please list what functions I need and I'll try to make one
ssalbdivad
ssalbdivadā€¢4mo ago
If you want to fuck around with stuff though which you generally do maybe you should look at the transform API on t.raw (t.internal on the next release).
Dimava
Dimavaā€¢4mo ago
Hmm What that does?
ssalbdivad
ssalbdivadā€¢4mo ago
Deeply transforms type nodes
Dimava
Dimavaā€¢4mo ago
Ah
ssalbdivad
ssalbdivadā€¢4mo ago
Here's how I use it to configure description at multkple levels:
configureShallowDescendants(configOrDescription: BaseMeta | string): this {
const config: BaseMeta =
typeof configOrDescription === "string" ?
{ description: configOrDescription }
: (configOrDescription as never)
return this.transform((kind, inner) => ({ ...inner, ...config }), {
shouldTransform: node => node.kind !== "structure"
}) as never
}
configureShallowDescendants(configOrDescription: BaseMeta | string): this {
const config: BaseMeta =
typeof configOrDescription === "string" ?
{ description: configOrDescription }
: (configOrDescription as never)
return this.transform((kind, inner) => ({ ...inner, ...config }), {
shouldTransform: node => node.kind !== "structure"
}) as never
}
Here's the new onUndeclaredKey implementation:
onUndeclaredKey(cfg: UndeclaredKeyBehavior | UndeclaredKeyConfig): BaseRoot {
const rule = typeof cfg === "string" ? cfg : cfg.rule
const deep = typeof cfg === "string" ? false : cfg.deep
return this.transform(
(kind, inner) =>
kind === "structure" ?
rule === "ignore" ?
omit(inner as StructureInner, { undeclared: 1 })
: { ...inner, undeclared: rule }
: inner,
deep ? undefined : (
{ shouldTransform: node => !includes(structuralKinds, node.kind) }
)
)
}
onUndeclaredKey(cfg: UndeclaredKeyBehavior | UndeclaredKeyConfig): BaseRoot {
const rule = typeof cfg === "string" ? cfg : cfg.rule
const deep = typeof cfg === "string" ? false : cfg.deep
return this.transform(
(kind, inner) =>
kind === "structure" ?
rule === "ignore" ?
omit(inner as StructureInner, { undeclared: 1 })
: { ...inner, undeclared: rule }
: inner,
deep ? undefined : (
{ shouldTransform: node => !includes(structuralKinds, node.kind) }
)
)
}
You'd have to learn a bit about the different node kinds to use this effectively but it is very powerful for this sort of thing What are the cases you are referring to?
Dimava
Dimavaā€¢4mo ago
Validation of untrusted input and serialization of untrimmed output? Using exact same input Type A la Zod's default behaviour I guess (is it? I didn't really use zod) Or what are you asking
ssalbdivad
ssalbdivadā€¢4mo ago
So, I'd like to have a unit test for this So please list what functions I need and I'll try to make one
What are you asking for the names of the APIs?
Want results from more Discord servers?
Add your server