mirror of
https://github.com/Sevichecc/Urara-Blog.git
synced 2025-05-06 01:49:14 +08:00
202 lines
No EOL
8.1 KiB
Text
202 lines
No EOL
8.1 KiB
Text
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.reportTypeError = exports.checkDataTypes = exports.checkDataType = exports.coerceAndCheckDataType = exports.getJSONTypes = exports.getSchemaTypes = exports.DataType = void 0;
|
|
const rules_1 = require("../rules");
|
|
const applicability_1 = require("./applicability");
|
|
const errors_1 = require("../errors");
|
|
const codegen_1 = require("../codegen");
|
|
const util_1 = require("../util");
|
|
var DataType;
|
|
(function (DataType) {
|
|
DataType[DataType["Correct"] = 0] = "Correct";
|
|
DataType[DataType["Wrong"] = 1] = "Wrong";
|
|
})(DataType = exports.DataType || (exports.DataType = {}));
|
|
function getSchemaTypes(schema) {
|
|
const types = getJSONTypes(schema.type);
|
|
const hasNull = types.includes("null");
|
|
if (hasNull) {
|
|
if (schema.nullable === false)
|
|
throw new Error("type: null contradicts nullable: false");
|
|
}
|
|
else {
|
|
if (!types.length && schema.nullable !== undefined) {
|
|
throw new Error('"nullable" cannot be used without "type"');
|
|
}
|
|
if (schema.nullable === true)
|
|
types.push("null");
|
|
}
|
|
return types;
|
|
}
|
|
exports.getSchemaTypes = getSchemaTypes;
|
|
function getJSONTypes(ts) {
|
|
const types = Array.isArray(ts) ? ts : ts ? [ts] : [];
|
|
if (types.every(rules_1.isJSONType))
|
|
return types;
|
|
throw new Error("type must be JSONType or JSONType[]: " + types.join(","));
|
|
}
|
|
exports.getJSONTypes = getJSONTypes;
|
|
function coerceAndCheckDataType(it, types) {
|
|
const { gen, data, opts } = it;
|
|
const coerceTo = coerceToTypes(types, opts.coerceTypes);
|
|
const checkTypes = types.length > 0 &&
|
|
!(coerceTo.length === 0 && types.length === 1 && (0, applicability_1.schemaHasRulesForType)(it, types[0]));
|
|
if (checkTypes) {
|
|
const wrongType = checkDataTypes(types, data, opts.strictNumbers, DataType.Wrong);
|
|
gen.if(wrongType, () => {
|
|
if (coerceTo.length)
|
|
coerceData(it, types, coerceTo);
|
|
else
|
|
reportTypeError(it);
|
|
});
|
|
}
|
|
return checkTypes;
|
|
}
|
|
exports.coerceAndCheckDataType = coerceAndCheckDataType;
|
|
const COERCIBLE = new Set(["string", "number", "integer", "boolean", "null"]);
|
|
function coerceToTypes(types, coerceTypes) {
|
|
return coerceTypes
|
|
? types.filter((t) => COERCIBLE.has(t) || (coerceTypes === "array" && t === "array"))
|
|
: [];
|
|
}
|
|
function coerceData(it, types, coerceTo) {
|
|
const { gen, data, opts } = it;
|
|
const dataType = gen.let("dataType", (0, codegen_1._) `typeof ${data}`);
|
|
const coerced = gen.let("coerced", (0, codegen_1._) `undefined`);
|
|
if (opts.coerceTypes === "array") {
|
|
gen.if((0, codegen_1._) `${dataType} == 'object' && Array.isArray(${data}) && ${data}.length == 1`, () => gen
|
|
.assign(data, (0, codegen_1._) `${data}[0]`)
|
|
.assign(dataType, (0, codegen_1._) `typeof ${data}`)
|
|
.if(checkDataTypes(types, data, opts.strictNumbers), () => gen.assign(coerced, data)));
|
|
}
|
|
gen.if((0, codegen_1._) `${coerced} !== undefined`);
|
|
for (const t of coerceTo) {
|
|
if (COERCIBLE.has(t) || (t === "array" && opts.coerceTypes === "array")) {
|
|
coerceSpecificType(t);
|
|
}
|
|
}
|
|
gen.else();
|
|
reportTypeError(it);
|
|
gen.endIf();
|
|
gen.if((0, codegen_1._) `${coerced} !== undefined`, () => {
|
|
gen.assign(data, coerced);
|
|
assignParentData(it, coerced);
|
|
});
|
|
function coerceSpecificType(t) {
|
|
switch (t) {
|
|
case "string":
|
|
gen
|
|
.elseIf((0, codegen_1._) `${dataType} == "number" || ${dataType} == "boolean"`)
|
|
.assign(coerced, (0, codegen_1._) `"" + ${data}`)
|
|
.elseIf((0, codegen_1._) `${data} === null`)
|
|
.assign(coerced, (0, codegen_1._) `""`);
|
|
return;
|
|
case "number":
|
|
gen
|
|
.elseIf((0, codegen_1._) `${dataType} == "boolean" || ${data} === null
|
|
|| (${dataType} == "string" && ${data} && ${data} == +${data})`)
|
|
.assign(coerced, (0, codegen_1._) `+${data}`);
|
|
return;
|
|
case "integer":
|
|
gen
|
|
.elseIf((0, codegen_1._) `${dataType} === "boolean" || ${data} === null
|
|
|| (${dataType} === "string" && ${data} && ${data} == +${data} && !(${data} % 1))`)
|
|
.assign(coerced, (0, codegen_1._) `+${data}`);
|
|
return;
|
|
case "boolean":
|
|
gen
|
|
.elseIf((0, codegen_1._) `${data} === "false" || ${data} === 0 || ${data} === null`)
|
|
.assign(coerced, false)
|
|
.elseIf((0, codegen_1._) `${data} === "true" || ${data} === 1`)
|
|
.assign(coerced, true);
|
|
return;
|
|
case "null":
|
|
gen.elseIf((0, codegen_1._) `${data} === "" || ${data} === 0 || ${data} === false`);
|
|
gen.assign(coerced, null);
|
|
return;
|
|
case "array":
|
|
gen
|
|
.elseIf((0, codegen_1._) `${dataType} === "string" || ${dataType} === "number"
|
|
|| ${dataType} === "boolean" || ${data} === null`)
|
|
.assign(coerced, (0, codegen_1._) `[${data}]`);
|
|
}
|
|
}
|
|
}
|
|
function assignParentData({ gen, parentData, parentDataProperty }, expr) {
|
|
// TODO use gen.property
|
|
gen.if((0, codegen_1._) `${parentData} !== undefined`, () => gen.assign((0, codegen_1._) `${parentData}[${parentDataProperty}]`, expr));
|
|
}
|
|
function checkDataType(dataType, data, strictNums, correct = DataType.Correct) {
|
|
const EQ = correct === DataType.Correct ? codegen_1.operators.EQ : codegen_1.operators.NEQ;
|
|
let cond;
|
|
switch (dataType) {
|
|
case "null":
|
|
return (0, codegen_1._) `${data} ${EQ} null`;
|
|
case "array":
|
|
cond = (0, codegen_1._) `Array.isArray(${data})`;
|
|
break;
|
|
case "object":
|
|
cond = (0, codegen_1._) `${data} && typeof ${data} == "object" && !Array.isArray(${data})`;
|
|
break;
|
|
case "integer":
|
|
cond = numCond((0, codegen_1._) `!(${data} % 1) && !isNaN(${data})`);
|
|
break;
|
|
case "number":
|
|
cond = numCond();
|
|
break;
|
|
default:
|
|
return (0, codegen_1._) `typeof ${data} ${EQ} ${dataType}`;
|
|
}
|
|
return correct === DataType.Correct ? cond : (0, codegen_1.not)(cond);
|
|
function numCond(_cond = codegen_1.nil) {
|
|
return (0, codegen_1.and)((0, codegen_1._) `typeof ${data} == "number"`, _cond, strictNums ? (0, codegen_1._) `isFinite(${data})` : codegen_1.nil);
|
|
}
|
|
}
|
|
exports.checkDataType = checkDataType;
|
|
function checkDataTypes(dataTypes, data, strictNums, correct) {
|
|
if (dataTypes.length === 1) {
|
|
return checkDataType(dataTypes[0], data, strictNums, correct);
|
|
}
|
|
let cond;
|
|
const types = (0, util_1.toHash)(dataTypes);
|
|
if (types.array && types.object) {
|
|
const notObj = (0, codegen_1._) `typeof ${data} != "object"`;
|
|
cond = types.null ? notObj : (0, codegen_1._) `!${data} || ${notObj}`;
|
|
delete types.null;
|
|
delete types.array;
|
|
delete types.object;
|
|
}
|
|
else {
|
|
cond = codegen_1.nil;
|
|
}
|
|
if (types.number)
|
|
delete types.integer;
|
|
for (const t in types)
|
|
cond = (0, codegen_1.and)(cond, checkDataType(t, data, strictNums, correct));
|
|
return cond;
|
|
}
|
|
exports.checkDataTypes = checkDataTypes;
|
|
const typeError = {
|
|
message: ({ schema }) => `must be ${schema}`,
|
|
params: ({ schema, schemaValue }) => typeof schema == "string" ? (0, codegen_1._) `{type: ${schema}}` : (0, codegen_1._) `{type: ${schemaValue}}`,
|
|
};
|
|
function reportTypeError(it) {
|
|
const cxt = getTypeErrorContext(it);
|
|
(0, errors_1.reportError)(cxt, typeError);
|
|
}
|
|
exports.reportTypeError = reportTypeError;
|
|
function getTypeErrorContext(it) {
|
|
const { gen, data, schema } = it;
|
|
const schemaCode = (0, util_1.schemaRefOrVal)(it, schema, "type");
|
|
return {
|
|
gen,
|
|
keyword: "type",
|
|
data,
|
|
schema: schema.type,
|
|
schemaCode,
|
|
schemaValue: schemaCode,
|
|
parentSchema: schema,
|
|
params: {},
|
|
it,
|
|
};
|
|
}
|
|
//# sourceMappingURL=dataType.js.map |