CoolFace
Apppublic

strong-tie/inbound-calls

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
limit.ts100 linesDownload Raw Back to src
1import type Ajv from "ajv"2import type {3  Plugin,4  CodeKeywordDefinition,5  KeywordErrorDefinition,6  Code,7  Name,8  ErrorObject,9} from "ajv"10import type {AddedFormat} from "ajv/dist/types"11import type {Rule} from "ajv/dist/compile/rules"12import {KeywordCxt} from "ajv"13import {_, str, or, getProperty, operators} from "ajv/dist/compile/codegen"14 15type Kwd = "formatMaximum" | "formatMinimum" | "formatExclusiveMaximum" | "formatExclusiveMinimum"16 17type Comparison = "<=" | ">=" | "<" | ">"18 19const ops = operators20 21const KWDs: {[K in Kwd]: {okStr: Comparison; ok: Code; fail: Code}} = {22  formatMaximum: {okStr: "<=", ok: ops.LTE, fail: ops.GT},23  formatMinimum: {okStr: ">=", ok: ops.GTE, fail: ops.LT},24  formatExclusiveMaximum: {okStr: "<", ok: ops.LT, fail: ops.GTE},25  formatExclusiveMinimum: {okStr: ">", ok: ops.GT, fail: ops.LTE},26}27 28export type LimitFormatError = ErrorObject<Kwd, {limit: string; comparison: Comparison}>29 30const error: KeywordErrorDefinition = {31  message: ({keyword, schemaCode}) => str`should be ${KWDs[keyword as Kwd].okStr} ${schemaCode}`,32  params: ({keyword, schemaCode}) =>33    _`{comparison: ${KWDs[keyword as Kwd].okStr}, limit: ${schemaCode}}`,34}35 36export const formatLimitDefinition: CodeKeywordDefinition = {37  keyword: Object.keys(KWDs),38  type: "string",39  schemaType: "string",40  $data: true,41  error,42  code(cxt) {43    const {gen, data, schemaCode, keyword, it} = cxt44    const {opts, self} = it45    if (!opts.validateFormats) return46 47    const fCxt = new KeywordCxt(it, (self.RULES.all.format as Rule).definition, "format")48    if (fCxt.$data) validate$DataFormat()49    else validateFormat()50 51    function validate$DataFormat(): void {52      const fmts = gen.scopeValue("formats", {53        ref: self.formats,54        code: opts.code.formats,55      })56      const fmt = gen.const("fmt", _`${fmts}[${fCxt.schemaCode}]`)57      cxt.fail$data(58        or(59          _`typeof ${fmt} != "object"`,60          _`${fmt} instanceof RegExp`,61          _`typeof ${fmt}.compare != "function"`,62          compareCode(fmt)63        )64      )65    }66 67    function validateFormat(): void {68      const format = fCxt.schema as string69      const fmtDef: AddedFormat | undefined = self.formats[format]70      if (!fmtDef || fmtDef === true) return71      if (72        typeof fmtDef != "object" ||73        fmtDef instanceof RegExp ||74        typeof fmtDef.compare != "function"75      ) {76        throw new Error(`"${keyword}": format "${format}" does not define "compare" function`)77      }78      const fmt = gen.scopeValue("formats", {79        key: format,80        ref: fmtDef,81        code: opts.code.formats ? _`${opts.code.formats}${getProperty(format)}` : undefined,82      })83 84      cxt.fail$data(compareCode(fmt))85    }86 87    function compareCode(fmt: Name): Code {88      return _`${fmt}.compare(${data}, ${schemaCode}) ${KWDs[keyword as Kwd].fail} 0`89    }90  },91  dependencies: ["format"],92}93 94const formatLimitPlugin: Plugin<undefined> = (ajv: Ajv): Ajv => {95  ajv.addKeyword(formatLimitDefinition)96  return ajv97}98 99export default formatLimitPlugin100