UNPKG

@jsonjoy.com/json-type

Version:

High-performance JSON Pointer implementation

205 lines (204 loc) 6.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TypeBuilder = void 0; const tslib_1 = require("tslib"); const schema = tslib_1.__importStar(require("../schema")); const classes = tslib_1.__importStar(require("./classes")); const { s } = schema; class TypeBuilder { constructor(system) { this.system = system; } get any() { return this.Any(); } get undef() { return this.Const(undefined); } get nil() { return this.Const(null); } get bool() { return this.Boolean(); } get num() { return this.Number(); } get str() { return this.String(); } get bin() { return this.Binary(this.any); } get arr() { return this.Array(this.any); } get obj() { return this.Object(); } get map() { return this.Map(this.any); } get fn() { return this.Function(this.any, this.any); } get fn$() { return this.Function$(this.any, this.any); } Any(options) { const type = new classes.AnyType(s.Any(options)); type.system = this.system; return type; } Const(value, options) { const type = new classes.ConstType(schema.s.Const(value, options)); type.system = this.system; return type; } Boolean(options) { const type = new classes.BooleanType(s.Boolean(options)); type.system = this.system; return type; } Number(options) { const type = new classes.NumberType(s.Number(options)); type.system = this.system; return type; } String(options) { const type = new classes.StringType(s.String(options)); type.system = this.system; return type; } Binary(type, options = {}) { const bin = new classes.BinaryType(type, options); bin.system = this.system; return bin; } Array(type, options) { const arr = new classes.ArrayType(type, options); arr.system = this.system; return arr; } Tuple(...types) { const tup = new classes.TupleType(types); tup.system = this.system; return tup; } Object(...fields) { const obj = new classes.ObjectType(fields); obj.system = this.system; return obj; } prop(key, value) { const field = new classes.ObjectFieldType(key, value); field.system = this.system; return field; } propOpt(key, value) { const field = new classes.ObjectOptionalFieldType(key, value); field.system = this.system; return field; } Map(type, options) { const map = new classes.MapType(type, options); map.system = this.system; return map; } Or(...types) { const or = new classes.OrType(types); or.system = this.system; return or; } Ref(ref) { const type = new classes.RefType(ref); type.system = this.system; return type; } /** @todo Shorten to `Func`. */ Function(req, res) { const fn = new classes.FunctionType(req, res); fn.system = this.system; return fn; } Function$(req, res) { const fn = new classes.FunctionStreamingType(req, res); fn.system = this.system; return fn; } import(node) { switch (node.kind) { case 'any': return this.Any(node); case 'bool': return this.Boolean(node); case 'num': return this.Number(node); case 'str': return this.String(node); case 'bin': return this.Binary(this.import(node.type), node); case 'arr': return this.Array(this.import(node.type), node); case 'tup': return this.Tuple(...node.types.map((t) => this.import(t))).options(node); case 'obj': { return this.Object(...node.fields.map((f) => f.optional ? this.propOpt(f.key, this.import(f.type)).options(f) : this.prop(f.key, this.import(f.type)).options(f))).options(node); } case 'map': return this.Map(this.import(node.type), node); case 'const': return this.Const(node.value).options(node); case 'or': return this.Or(...node.types.map((t) => this.import(t))).options(node); case 'ref': return this.Ref(node.ref).options(node); case 'fn': return this.Function(this.import(node.req), this.import(node.res)).options(node); case 'fn$': return this.Function$(this.import(node.req), this.import(node.res)).options(node); } throw new Error(`UNKNOWN_NODE [${node.kind}]`); } from(value) { switch (typeof value) { case 'undefined': return this.undef; case 'boolean': return this.bool; case 'number': return this.num; case 'string': return this.str; case 'object': if (value === null) return this.nil; if (Array.isArray(value)) { if (value.length === 0) return this.arr; const getType = (v) => { switch (typeof v) { case 'object': if (v === null) return 'nil'; if (Array.isArray(v)) return 'arr'; return 'obj'; default: return typeof v; } }; const allElementsOfTheSameType = value.every((v) => getType(v) === getType(value[0])); return allElementsOfTheSameType ? this.Array(this.from(value[0])) : this.Tuple(...value.map((v) => this.from(v))); } return this.Object(...Object.entries(value).map(([key, value]) => this.prop(key, this.from(value)))); default: return this.any; } } } exports.TypeBuilder = TypeBuilder;