@jsonjoy.com/json-type
Version:
High-performance JSON Pointer implementation
265 lines • 9.09 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateSchema = exports.validateTType = void 0;
const validateDisplay = ({ title, description, intro }) => {
if (title !== undefined && typeof title !== 'string')
throw new Error('INVALID_TITLE');
if (description !== undefined && typeof description !== 'string')
throw new Error('INVALID_DESCRIPTION');
if (intro !== undefined && typeof intro !== 'string')
throw new Error('INVALID_INTRO');
};
const validateTExample = (example) => {
validateDisplay(example);
};
const validateTType = (tType, kind) => {
validateDisplay(tType);
// const {id} = tType;
// if (id !== undefined && typeof id !== 'string') throw new Error('INVALID_ID');
if (tType.kind !== kind)
throw new Error('INVALID_TYPE');
const { examples } = tType;
if (examples) {
if (!Array.isArray(examples))
throw new Error('INVALID_EXAMPLES');
examples.forEach(validateTExample);
}
};
exports.validateTType = validateTType;
const validateMinMax = (min, max) => {
if (min !== undefined) {
if (typeof min !== 'number')
throw new Error('MIN_TYPE');
if (min < 0)
throw new Error('MIN_NEGATIVE');
if (min % 1 !== 0)
throw new Error('MIN_DECIMAL');
}
if (max !== undefined) {
if (typeof max !== 'number')
throw new Error('MAX_TYPE');
if (max < 0)
throw new Error('MAX_NEGATIVE');
if (max % 1 !== 0)
throw new Error('MAX_DECIMAL');
}
if (min !== undefined && max !== undefined && min > max)
throw new Error('MIN_MAX');
};
const validateAnySchema = (schema) => {
(0, exports.validateTType)(schema, 'any');
};
const validateBoolSchema = (schema) => {
(0, exports.validateTType)(schema, 'bool');
};
const validateNumSchema = (schema) => {
(0, exports.validateTType)(schema, 'num');
const { format, gt, gte, lt, lte } = schema;
if (gt !== undefined && typeof gt !== 'number')
throw new Error('GT_TYPE');
if (gte !== undefined && typeof gte !== 'number')
throw new Error('GTE_TYPE');
if (lt !== undefined && typeof lt !== 'number')
throw new Error('LT_TYPE');
if (lte !== undefined && typeof lte !== 'number')
throw new Error('LTE_TYPE');
if (gt !== undefined && gte !== undefined)
throw new Error('GT_GTE');
if (lt !== undefined && lte !== undefined)
throw new Error('LT_LTE');
if ((gt !== undefined || gte !== undefined) && (lt !== undefined || lte !== undefined))
if ((gt ?? gte) > (lt ?? lte))
throw new Error('GT_LT');
if (format !== undefined) {
if (typeof format !== 'string')
throw new Error('FORMAT_TYPE');
if (!format)
throw new Error('FORMAT_EMPTY');
switch (format) {
case 'i':
case 'u':
case 'f':
case 'i8':
case 'i16':
case 'i32':
case 'i64':
case 'u8':
case 'u16':
case 'u32':
case 'u64':
case 'f32':
case 'f64':
break;
default:
throw new Error('FORMAT_INVALID');
}
}
};
const validateStrSchema = (schema) => {
(0, exports.validateTType)(schema, 'str');
const { min, max, ascii, noJsonEscape, format } = schema;
validateMinMax(min, max);
if (ascii !== undefined) {
if (typeof ascii !== 'boolean')
throw new Error('ASCII');
}
if (noJsonEscape !== undefined) {
if (typeof noJsonEscape !== 'boolean')
throw new Error('NO_JSON_ESCAPE_TYPE');
}
if (format !== undefined) {
if (format !== 'ascii' && format !== 'utf8') {
throw new Error('INVALID_STRING_FORMAT');
}
// If both format and ascii are specified, they should be consistent
if (ascii !== undefined && format === 'ascii' && !ascii) {
throw new Error('FORMAT_ASCII_MISMATCH');
}
}
};
const binaryFormats = new Set(['bencode', 'bson', 'cbor', 'ion', 'json', 'msgpack', 'resp3', 'ubjson']);
const validateBinSchema = (schema) => {
(0, exports.validateTType)(schema, 'bin');
const { min, max, format } = schema;
validateMinMax(min, max);
if (format !== undefined) {
if (!binaryFormats.has(format))
throw new Error('FORMAT');
}
(0, exports.validateSchema)(schema.type);
};
const validateArrSchema = (schema) => {
(0, exports.validateTType)(schema, 'arr');
const { min, max } = schema;
validateMinMax(min, max);
if (!('head' in schema) && !('type' in schema) && !('tail' in schema))
throw new Error('EMPTY_ARR');
if ('tail' in schema && !('type' in schema))
throw new Error('LONE_TAIL');
const { head, type, tail } = schema;
if (type)
(0, exports.validateSchema)(type);
if (head)
for (const h of head)
(0, exports.validateSchema)(h);
if (tail)
for (const t of tail)
(0, exports.validateSchema)(t);
};
const validateConSchema = (schema) => {
(0, exports.validateTType)(schema, 'con');
};
const validateObjSchema = (schema) => {
(0, exports.validateTType)(schema, 'obj');
const { keys, decodeUnknownKeys, encodeUnknownKeys } = schema;
if (!Array.isArray(keys))
throw new Error('KEYS_TYPE');
if (decodeUnknownKeys !== undefined && typeof decodeUnknownKeys !== 'boolean')
throw new Error('DECODE_UNKNOWN_KEYS_TYPE');
if (encodeUnknownKeys !== undefined && typeof encodeUnknownKeys !== 'boolean')
throw new Error('ENCODE_UNKNOWN_KEYS_TYPE');
for (const key of keys)
(0, exports.validateSchema)(key);
};
const validateKeySchema = (schema) => {
(0, exports.validateTType)(schema, 'key');
const { key, optional } = schema;
if (typeof key !== 'string')
throw new Error('KEY_TYPE');
if (optional !== undefined && typeof optional !== 'boolean')
throw new Error('OPTIONAL_TYPE');
(0, exports.validateSchema)(schema.value);
};
const validateMapSchema = (schema) => {
(0, exports.validateTType)(schema, 'map');
(0, exports.validateSchema)(schema.value);
if (schema.key) {
(0, exports.validateSchema)(schema.key);
}
};
const validateRefSchema = (schema) => {
(0, exports.validateTType)(schema, 'ref');
const { ref } = schema;
if (typeof ref !== 'string')
throw new Error('REF_TYPE');
if (!ref)
throw new Error('REF_EMPTY');
};
const validateOrSchema = (schema) => {
(0, exports.validateTType)(schema, 'or');
const { types, discriminator } = schema;
if (!discriminator || (discriminator[0] === 'num' && discriminator[1] === -1))
throw new Error('DISCRIMINATOR');
if (!Array.isArray(types))
throw new Error('TYPES_TYPE');
if (!types.length)
throw new Error('TYPES_LENGTH');
for (const type of types)
(0, exports.validateSchema)(type);
};
const validateFunctionSchema = (schema) => {
(0, exports.validateTType)(schema, 'fn');
(0, exports.validateSchema)(schema.req);
(0, exports.validateSchema)(schema.res);
};
const validateFunctionStreamingSchema = (schema) => {
(0, exports.validateTType)(schema, 'fn$');
(0, exports.validateSchema)(schema.req);
(0, exports.validateSchema)(schema.res);
};
/**
* Main router function that validates a schema based on its kind.
* This replaces the individual validateSchema() methods from type classes.
*/
const validateSchema = (schema) => {
if (typeof schema !== 'object')
throw new Error('INVALID_SCHEMA');
switch (schema.kind) {
case 'any':
validateAnySchema(schema);
break;
case 'bool':
validateBoolSchema(schema);
break;
case 'num':
validateNumSchema(schema);
break;
case 'str':
validateStrSchema(schema);
break;
case 'bin':
validateBinSchema(schema);
break;
case 'arr':
validateArrSchema(schema);
break;
case 'con':
validateConSchema(schema);
break;
case 'obj':
validateObjSchema(schema);
break;
case 'key':
validateKeySchema(schema);
break;
case 'map':
validateMapSchema(schema);
break;
case 'ref':
validateRefSchema(schema);
break;
case 'or':
validateOrSchema(schema);
break;
case 'fn':
validateFunctionSchema(schema);
break;
case 'fn$':
validateFunctionStreamingSchema(schema);
break;
default:
throw new Error(`Unknown schema kind: ${schema.kind}`);
}
};
exports.validateSchema = validateSchema;
//# sourceMappingURL=validate.js.map