| [9af201e] | 1 | "use strict";
|
|---|
| 2 |
|
|---|
| 3 | Object.defineProperty(exports, "__esModule", {
|
|---|
| 4 | value: true
|
|---|
| 5 | });
|
|---|
| 6 | exports.default = void 0;
|
|---|
| 7 | /** @typedef {import("ajv").default} Ajv */
|
|---|
| 8 | /** @typedef {import("ajv").Code} Code */
|
|---|
| 9 | /** @typedef {import("ajv").Name} Name */
|
|---|
| 10 | /** @typedef {import("ajv").KeywordErrorDefinition} KeywordErrorDefinition */
|
|---|
| 11 |
|
|---|
| 12 | /**
|
|---|
| 13 | * @param {Ajv} ajv ajv
|
|---|
| 14 | * @returns {Ajv} ajv with limit keyword
|
|---|
| 15 | */
|
|---|
| 16 | function addLimitKeyword(ajv) {
|
|---|
| 17 | const {
|
|---|
| 18 | _,
|
|---|
| 19 | str,
|
|---|
| 20 | KeywordCxt,
|
|---|
| 21 | nil,
|
|---|
| 22 | Name
|
|---|
| 23 | } = require("ajv");
|
|---|
| 24 |
|
|---|
| 25 | /**
|
|---|
| 26 | * @param {Code | Name} nameOrCode name or code
|
|---|
| 27 | * @returns {Code | Name} name or code
|
|---|
| 28 | */
|
|---|
| 29 | function par(nameOrCode) {
|
|---|
| 30 | return nameOrCode instanceof Name ? nameOrCode : _`(${nameOrCode})`;
|
|---|
| 31 | }
|
|---|
| 32 |
|
|---|
| 33 | /**
|
|---|
| 34 | * @param {Code} op op
|
|---|
| 35 | * @returns {(xValue: Code, yValue: Code) => Code} code
|
|---|
| 36 | */
|
|---|
| 37 | function mappend(op) {
|
|---|
| 38 | return (xValue, yValue) => xValue === nil ? yValue : yValue === nil ? xValue : _`${par(xValue)} ${op} ${par(yValue)}`;
|
|---|
| 39 | }
|
|---|
| 40 | const orCode = mappend(_`||`);
|
|---|
| 41 |
|
|---|
| 42 | // boolean OR (||) expression with the passed arguments
|
|---|
| 43 | /**
|
|---|
| 44 | * @param {...Code} args args
|
|---|
| 45 | * @returns {Code} code
|
|---|
| 46 | */
|
|---|
| 47 | function or(...args) {
|
|---|
| 48 | return args.reduce(orCode);
|
|---|
| 49 | }
|
|---|
| 50 |
|
|---|
| 51 | /**
|
|---|
| 52 | * @param {string | number} key key
|
|---|
| 53 | * @returns {Code} property
|
|---|
| 54 | */
|
|---|
| 55 | function getProperty(key) {
|
|---|
| 56 | return _`[${key}]`;
|
|---|
| 57 | }
|
|---|
| 58 | const keywords = {
|
|---|
| 59 | formatMaximum: {
|
|---|
| 60 | okStr: "<=",
|
|---|
| 61 | ok: _`<=`,
|
|---|
| 62 | fail: _`>`
|
|---|
| 63 | },
|
|---|
| 64 | formatMinimum: {
|
|---|
| 65 | okStr: ">=",
|
|---|
| 66 | ok: _`>=`,
|
|---|
| 67 | fail: _`<`
|
|---|
| 68 | },
|
|---|
| 69 | formatExclusiveMaximum: {
|
|---|
| 70 | okStr: "<",
|
|---|
| 71 | ok: _`<`,
|
|---|
| 72 | fail: _`>=`
|
|---|
| 73 | },
|
|---|
| 74 | formatExclusiveMinimum: {
|
|---|
| 75 | okStr: ">",
|
|---|
| 76 | ok: _`>`,
|
|---|
| 77 | fail: _`<=`
|
|---|
| 78 | }
|
|---|
| 79 | };
|
|---|
| 80 |
|
|---|
| 81 | /** @type {KeywordErrorDefinition} */
|
|---|
| 82 | const error = {
|
|---|
| 83 | message: ({
|
|---|
| 84 | keyword,
|
|---|
| 85 | schemaCode
|
|---|
| 86 | }) => str`should be ${keywords[(/** @type {keyof typeof keywords} */keyword)].okStr} ${schemaCode}`,
|
|---|
| 87 | params: ({
|
|---|
| 88 | keyword,
|
|---|
| 89 | schemaCode
|
|---|
| 90 | }) => _`{comparison: ${keywords[(/** @type {keyof typeof keywords} */keyword)].okStr}, limit: ${schemaCode}}`
|
|---|
| 91 | };
|
|---|
| 92 | for (const keyword of Object.keys(keywords)) {
|
|---|
| 93 | ajv.addKeyword({
|
|---|
| 94 | keyword,
|
|---|
| 95 | type: "string",
|
|---|
| 96 | schemaType: keyword.startsWith("formatExclusive") ? ["string", "boolean"] : ["string", "number"],
|
|---|
| 97 | $data: true,
|
|---|
| 98 | error,
|
|---|
| 99 | code(cxt) {
|
|---|
| 100 | const {
|
|---|
| 101 | gen,
|
|---|
| 102 | data,
|
|---|
| 103 | schemaCode,
|
|---|
| 104 | keyword,
|
|---|
| 105 | it
|
|---|
| 106 | } = cxt;
|
|---|
| 107 | const {
|
|---|
| 108 | opts,
|
|---|
| 109 | self
|
|---|
| 110 | } = it;
|
|---|
| 111 | if (!opts.validateFormats) return;
|
|---|
| 112 | const fCxt = new KeywordCxt(it,
|
|---|
| 113 | // eslint-disable-next-line jsdoc/no-restricted-syntax
|
|---|
| 114 | /** @type {any} */
|
|---|
| 115 | self.RULES.all.format.definition, "format");
|
|---|
| 116 |
|
|---|
| 117 | /**
|
|---|
| 118 | * @param {Name} fmt fmt
|
|---|
| 119 | * @returns {Code} code
|
|---|
| 120 | */
|
|---|
| 121 | function compareCode(fmt) {
|
|---|
| 122 | return _`${fmt}.compare(${data}, ${schemaCode}) ${keywords[(/** @type {keyof typeof keywords} */keyword)].fail} 0`;
|
|---|
| 123 | }
|
|---|
| 124 |
|
|---|
| 125 | /**
|
|---|
| 126 | * @returns {void}
|
|---|
| 127 | */
|
|---|
| 128 | function validate$DataFormat() {
|
|---|
| 129 | const fmts = gen.scopeValue("formats", {
|
|---|
| 130 | ref: self.formats,
|
|---|
| 131 | code: opts.code.formats
|
|---|
| 132 | });
|
|---|
| 133 | const fmt = gen.const("fmt", _`${fmts}[${fCxt.schemaCode}]`);
|
|---|
| 134 | cxt.fail$data(or(_`typeof ${fmt} != "object"`, _`${fmt} instanceof RegExp`, _`typeof ${fmt}.compare != "function"`, compareCode(fmt)));
|
|---|
| 135 | }
|
|---|
| 136 |
|
|---|
| 137 | /**
|
|---|
| 138 | * @returns {void}
|
|---|
| 139 | */
|
|---|
| 140 | function validateFormat() {
|
|---|
| 141 | const format = fCxt.schema;
|
|---|
| 142 | const fmtDef = self.formats[format];
|
|---|
| 143 | if (!fmtDef || fmtDef === true) {
|
|---|
| 144 | return;
|
|---|
| 145 | }
|
|---|
| 146 | if (typeof fmtDef !== "object" || fmtDef instanceof RegExp || typeof fmtDef.compare !== "function") {
|
|---|
| 147 | throw new Error(`"${keyword}": format "${format}" does not define "compare" function`);
|
|---|
| 148 | }
|
|---|
| 149 | const fmt = gen.scopeValue("formats", {
|
|---|
| 150 | key: format,
|
|---|
| 151 | ref: fmtDef,
|
|---|
| 152 | code: opts.code.formats ? _`${opts.code.formats}${getProperty(format)}` : undefined
|
|---|
| 153 | });
|
|---|
| 154 | cxt.fail$data(compareCode(fmt));
|
|---|
| 155 | }
|
|---|
| 156 | if (fCxt.$data) {
|
|---|
| 157 | validate$DataFormat();
|
|---|
| 158 | } else {
|
|---|
| 159 | validateFormat();
|
|---|
| 160 | }
|
|---|
| 161 | },
|
|---|
| 162 | dependencies: ["format"]
|
|---|
| 163 | });
|
|---|
| 164 | }
|
|---|
| 165 | return ajv;
|
|---|
| 166 | }
|
|---|
| 167 | var _default = exports.default = addLimitKeyword; |
|---|