@jsonjoy.com/json-type
Version:
High-performance JSON Pointer implementation
205 lines (204 loc) • 6.53 kB
JavaScript
"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;