mirror of
https://github.com/Sevichecc/Urara-Blog.git
synced 2025-05-03 22:39:30 +08:00
75 lines
2.5 KiB
Text
75 lines
2.5 KiB
Text
import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types"
|
|
import type {KeywordCxt} from "../../compile/validate"
|
|
import {_, nil, or, Code} from "../../compile/codegen"
|
|
import validTimestamp from "../../runtime/timestamp"
|
|
import {useFunc} from "../../compile/util"
|
|
import {checkMetadata} from "./metadata"
|
|
import {typeErrorMessage, typeErrorParams, _JTDTypeError} from "./error"
|
|
|
|
export type JTDTypeError = _JTDTypeError<"type", JTDType, JTDType>
|
|
|
|
export type IntType = "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32"
|
|
|
|
export const intRange: {[T in IntType]: [number, number, number]} = {
|
|
int8: [-128, 127, 3],
|
|
uint8: [0, 255, 3],
|
|
int16: [-32768, 32767, 5],
|
|
uint16: [0, 65535, 5],
|
|
int32: [-2147483648, 2147483647, 10],
|
|
uint32: [0, 4294967295, 10],
|
|
}
|
|
|
|
export type JTDType = "boolean" | "string" | "timestamp" | "float32" | "float64" | IntType
|
|
|
|
const error: KeywordErrorDefinition = {
|
|
message: (cxt) => typeErrorMessage(cxt, cxt.schema),
|
|
params: (cxt) => typeErrorParams(cxt, cxt.schema),
|
|
}
|
|
|
|
function timestampCode(cxt: KeywordCxt): Code {
|
|
const {gen, data, it} = cxt
|
|
const {timestamp, allowDate} = it.opts
|
|
if (timestamp === "date") return _`${data} instanceof Date `
|
|
const vts = useFunc(gen, validTimestamp)
|
|
const allowDateArg = allowDate ? _`, true` : nil
|
|
const validString = _`typeof ${data} == "string" && ${vts}(${data}${allowDateArg})`
|
|
return timestamp === "string" ? validString : or(_`${data} instanceof Date`, validString)
|
|
}
|
|
|
|
const def: CodeKeywordDefinition = {
|
|
keyword: "type",
|
|
schemaType: "string",
|
|
error,
|
|
code(cxt: KeywordCxt) {
|
|
checkMetadata(cxt)
|
|
const {data, schema, parentSchema, it} = cxt
|
|
let cond: Code
|
|
switch (schema) {
|
|
case "boolean":
|
|
case "string":
|
|
cond = _`typeof ${data} == ${schema}`
|
|
break
|
|
case "timestamp": {
|
|
cond = timestampCode(cxt)
|
|
break
|
|
}
|
|
case "float32":
|
|
case "float64":
|
|
cond = _`typeof ${data} == "number"`
|
|
break
|
|
default: {
|
|
const sch = schema as IntType
|
|
cond = _`typeof ${data} == "number" && isFinite(${data}) && !(${data} % 1)`
|
|
if (!it.opts.int32range && (sch === "int32" || sch === "uint32")) {
|
|
if (sch === "uint32") cond = _`${cond} && ${data} >= 0`
|
|
} else {
|
|
const [min, max] = intRange[sch]
|
|
cond = _`${cond} && ${data} >= ${min} && ${data} <= ${max}`
|
|
}
|
|
}
|
|
}
|
|
cxt.pass(parentSchema.nullable ? or(_`${data} === null`, cond) : cond)
|
|
},
|
|
}
|
|
|
|
export default def
|