[79a0317] | 1 | "use strict";
|
---|
| 2 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
| 3 | exports.validateProperties = exports.error = void 0;
|
---|
| 4 | const code_1 = require("../code");
|
---|
| 5 | const util_1 = require("../../compile/util");
|
---|
| 6 | const codegen_1 = require("../../compile/codegen");
|
---|
| 7 | const metadata_1 = require("./metadata");
|
---|
| 8 | const nullable_1 = require("./nullable");
|
---|
| 9 | const error_1 = require("./error");
|
---|
| 10 | var PropError;
|
---|
| 11 | (function (PropError) {
|
---|
| 12 | PropError["Additional"] = "additional";
|
---|
| 13 | PropError["Missing"] = "missing";
|
---|
| 14 | })(PropError || (PropError = {}));
|
---|
| 15 | exports.error = {
|
---|
| 16 | message: (cxt) => {
|
---|
| 17 | const { params } = cxt;
|
---|
| 18 | return params.propError
|
---|
| 19 | ? params.propError === PropError.Additional
|
---|
| 20 | ? "must NOT have additional properties"
|
---|
| 21 | : `must have property '${params.missingProperty}'`
|
---|
| 22 | : (0, error_1.typeErrorMessage)(cxt, "object");
|
---|
| 23 | },
|
---|
| 24 | params: (cxt) => {
|
---|
| 25 | const { params } = cxt;
|
---|
| 26 | return params.propError
|
---|
| 27 | ? params.propError === PropError.Additional
|
---|
| 28 | ? (0, codegen_1._) `{error: ${params.propError}, additionalProperty: ${params.additionalProperty}}`
|
---|
| 29 | : (0, codegen_1._) `{error: ${params.propError}, missingProperty: ${params.missingProperty}}`
|
---|
| 30 | : (0, error_1.typeErrorParams)(cxt, "object");
|
---|
| 31 | },
|
---|
| 32 | };
|
---|
| 33 | const def = {
|
---|
| 34 | keyword: "properties",
|
---|
| 35 | schemaType: "object",
|
---|
| 36 | error: exports.error,
|
---|
| 37 | code: validateProperties,
|
---|
| 38 | };
|
---|
| 39 | // const error: KeywordErrorDefinition = {
|
---|
| 40 | // message: "should NOT have additional properties",
|
---|
| 41 | // params: ({params}) => _`{additionalProperty: ${params.additionalProperty}}`,
|
---|
| 42 | // }
|
---|
| 43 | function validateProperties(cxt) {
|
---|
| 44 | (0, metadata_1.checkMetadata)(cxt);
|
---|
| 45 | const { gen, data, parentSchema, it } = cxt;
|
---|
| 46 | const { additionalProperties, nullable } = parentSchema;
|
---|
| 47 | if (it.jtdDiscriminator && nullable)
|
---|
| 48 | throw new Error("JTD: nullable inside discriminator mapping");
|
---|
| 49 | if (commonProperties()) {
|
---|
| 50 | throw new Error("JTD: properties and optionalProperties have common members");
|
---|
| 51 | }
|
---|
| 52 | const [allProps, properties] = schemaProperties("properties");
|
---|
| 53 | const [allOptProps, optProperties] = schemaProperties("optionalProperties");
|
---|
| 54 | if (properties.length === 0 && optProperties.length === 0 && additionalProperties) {
|
---|
| 55 | return;
|
---|
| 56 | }
|
---|
| 57 | const [valid, cond] = it.jtdDiscriminator === undefined
|
---|
| 58 | ? (0, nullable_1.checkNullableObject)(cxt, data)
|
---|
| 59 | : [gen.let("valid", false), true];
|
---|
| 60 | gen.if(cond, () => gen.assign(valid, true).block(() => {
|
---|
| 61 | validateProps(properties, "properties", true);
|
---|
| 62 | validateProps(optProperties, "optionalProperties");
|
---|
| 63 | if (!additionalProperties)
|
---|
| 64 | validateAdditional();
|
---|
| 65 | }));
|
---|
| 66 | cxt.pass(valid);
|
---|
| 67 | function commonProperties() {
|
---|
| 68 | const props = parentSchema.properties;
|
---|
| 69 | const optProps = parentSchema.optionalProperties;
|
---|
| 70 | if (!(props && optProps))
|
---|
| 71 | return false;
|
---|
| 72 | for (const p in props) {
|
---|
| 73 | if (Object.prototype.hasOwnProperty.call(optProps, p))
|
---|
| 74 | return true;
|
---|
| 75 | }
|
---|
| 76 | return false;
|
---|
| 77 | }
|
---|
| 78 | function schemaProperties(keyword) {
|
---|
| 79 | const schema = parentSchema[keyword];
|
---|
| 80 | const allPs = schema ? (0, code_1.allSchemaProperties)(schema) : [];
|
---|
| 81 | if (it.jtdDiscriminator && allPs.some((p) => p === it.jtdDiscriminator)) {
|
---|
| 82 | throw new Error(`JTD: discriminator tag used in ${keyword}`);
|
---|
| 83 | }
|
---|
| 84 | const ps = allPs.filter((p) => !(0, util_1.alwaysValidSchema)(it, schema[p]));
|
---|
| 85 | return [allPs, ps];
|
---|
| 86 | }
|
---|
| 87 | function validateProps(props, keyword, required) {
|
---|
| 88 | const _valid = gen.var("valid");
|
---|
| 89 | for (const prop of props) {
|
---|
| 90 | gen.if((0, code_1.propertyInData)(gen, data, prop, it.opts.ownProperties), () => applyPropertySchema(prop, keyword, _valid), () => missingProperty(prop));
|
---|
| 91 | cxt.ok(_valid);
|
---|
| 92 | }
|
---|
| 93 | function missingProperty(prop) {
|
---|
| 94 | if (required) {
|
---|
| 95 | gen.assign(_valid, false);
|
---|
| 96 | cxt.error(false, { propError: PropError.Missing, missingProperty: prop }, { schemaPath: prop });
|
---|
| 97 | }
|
---|
| 98 | else {
|
---|
| 99 | gen.assign(_valid, true);
|
---|
| 100 | }
|
---|
| 101 | }
|
---|
| 102 | }
|
---|
| 103 | function applyPropertySchema(prop, keyword, _valid) {
|
---|
| 104 | cxt.subschema({
|
---|
| 105 | keyword,
|
---|
| 106 | schemaProp: prop,
|
---|
| 107 | dataProp: prop,
|
---|
| 108 | }, _valid);
|
---|
| 109 | }
|
---|
| 110 | function validateAdditional() {
|
---|
| 111 | gen.forIn("key", data, (key) => {
|
---|
| 112 | const addProp = isAdditional(key, allProps, "properties", it.jtdDiscriminator);
|
---|
| 113 | const addOptProp = isAdditional(key, allOptProps, "optionalProperties");
|
---|
| 114 | const extra = addProp === true ? addOptProp : addOptProp === true ? addProp : (0, codegen_1.and)(addProp, addOptProp);
|
---|
| 115 | gen.if(extra, () => {
|
---|
| 116 | if (it.opts.removeAdditional) {
|
---|
| 117 | gen.code((0, codegen_1._) `delete ${data}[${key}]`);
|
---|
| 118 | }
|
---|
| 119 | else {
|
---|
| 120 | cxt.error(false, { propError: PropError.Additional, additionalProperty: key }, { instancePath: key, parentSchema: true });
|
---|
| 121 | if (!it.opts.allErrors)
|
---|
| 122 | gen.break();
|
---|
| 123 | }
|
---|
| 124 | });
|
---|
| 125 | });
|
---|
| 126 | }
|
---|
| 127 | function isAdditional(key, props, keyword, jtdDiscriminator) {
|
---|
| 128 | let additional;
|
---|
| 129 | if (props.length > 8) {
|
---|
| 130 | // TODO maybe an option instead of hard-coded 8?
|
---|
| 131 | const propsSchema = (0, util_1.schemaRefOrVal)(it, parentSchema[keyword], keyword);
|
---|
| 132 | additional = (0, codegen_1.not)((0, code_1.isOwnProperty)(gen, propsSchema, key));
|
---|
| 133 | if (jtdDiscriminator !== undefined) {
|
---|
| 134 | additional = (0, codegen_1.and)(additional, (0, codegen_1._) `${key} !== ${jtdDiscriminator}`);
|
---|
| 135 | }
|
---|
| 136 | }
|
---|
| 137 | else if (props.length || jtdDiscriminator !== undefined) {
|
---|
| 138 | const ps = jtdDiscriminator === undefined ? props : [jtdDiscriminator].concat(props);
|
---|
| 139 | additional = (0, codegen_1.and)(...ps.map((p) => (0, codegen_1._) `${key} !== ${p}`));
|
---|
| 140 | }
|
---|
| 141 | else {
|
---|
| 142 | additional = true;
|
---|
| 143 | }
|
---|
| 144 | return additional;
|
---|
| 145 | }
|
---|
| 146 | }
|
---|
| 147 | exports.validateProperties = validateProperties;
|
---|
| 148 | exports.default = def;
|
---|
| 149 | //# sourceMappingURL=properties.js.map |
---|