UNPKG

@jsonjoy.com/json-type

Version:

High-performance JSON Pointer implementation

282 lines (281 loc) 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AbsType = void 0; const ValidatorCodegenContext_1 = require("../../codegen/validator/ValidatorCodegenContext"); const JsonTextEncoderCodegenContext_1 = require("../../codegen/json/JsonTextEncoderCodegenContext"); const CborEncoderCodegenContext_1 = require("../../codegen/binary/CborEncoderCodegenContext"); const JsonEncoderCodegenContext_1 = require("../../codegen/binary/JsonEncoderCodegenContext"); const CborEncoder_1 = require("@jsonjoy.com/json-pack/lib/cbor/CborEncoder"); const JsExpression_1 = require("@jsonjoy.com/util/lib/codegen/util/JsExpression"); const MessagePackEncoderCodegenContext_1 = require("../../codegen/binary/MessagePackEncoderCodegenContext"); const msgpack_1 = require("@jsonjoy.com/json-pack/lib/msgpack"); const lazyFunction_1 = require("@jsonjoy.com/util/lib/lazyFunction"); const JsonEncoder_1 = require("@jsonjoy.com/json-pack/lib/json/JsonEncoder"); const Writer_1 = require("@jsonjoy.com/util/lib/buffers/Writer"); const CapacityEstimatorCodegenContext_1 = require("../../codegen/capacity/CapacityEstimatorCodegenContext"); const estimators_1 = require("../../codegen/capacity/estimators"); const generator_1 = require("../../random/generator"); class AbsType { constructor() { this.validators = {}; this.encoders = new Map(); } getSystem() { const system = this.system; if (!system) throw new Error('NO_SYSTEM'); return system; } getTypeName() { return this.schema.kind; } /** * @todo Add ability to export the whole schema, including aliases. */ getSchema() { return this.schema; } getValidatorNames() { const { validator } = this.schema; if (!validator) return []; return Array.isArray(validator) ? validator : [validator]; } toJsonSchema(ctx) { // Use dynamic import to avoid circular dependency const converter = require('../../json-schema/converter'); return converter.typeToJsonSchema(this, ctx); } options(options) { Object.assign(this.schema, options); return this; } title(title) { this.schema.title = title; return this; } intro(intro) { this.schema.intro = intro; return this; } description(description) { this.schema.description = description; return this; } default(value) { this.schema.default = value; return this; } example(value, title, options) { var _a; const examples = ((_a = this.schema).examples ?? (_a.examples = [])); const example = { ...options, value }; if (typeof title === 'string') example.title = title; examples.push(example); return this; } getOptions() { const { kind, ...options } = this.schema; return options; } /** Validates own schema, throws on errors. */ validateSchema() { const { validateSchema } = require('../../schema/validate'); validateSchema(this.getSchema()); } validate(value) { const validator = this.validator('string'); const err = validator(value); if (err) throw new Error(JSON.parse(err)[0]); } compileValidator(options) { const ctx = new ValidatorCodegenContext_1.ValidatorCodegenContext({ system: this.system, errors: 'object', ...options, type: this, }); this.codegenValidator(ctx, [], ctx.codegen.options.args[0]); return ctx.compile(); } __compileValidator(kind) { return (this.validators[kind] = this.compileValidator({ errors: kind, system: this.system, skipObjectExtraFieldsCheck: kind === 'boolean', unsafeMode: kind === 'boolean', })); } validator(kind) { return this.validators[kind] || (0, lazyFunction_1.lazy)(() => this.__compileValidator(kind)); } compileJsonTextEncoder(options) { const ctx = new JsonTextEncoderCodegenContext_1.JsonTextEncoderCodegenContext({ ...options, system: this.system, type: this, }); const r = ctx.codegen.options.args[0]; const value = new JsExpression_1.JsExpression(() => r); this.codegenJsonTextEncoder(ctx, value); return ctx.compile(); } codegenJsonTextEncoder(ctx, value) { // Use the centralized router function const { generate } = require('../../codegen/json/jsonTextEncoders'); generate(ctx, value, this); } jsonTextEncoder() { return (this.__jsonEncoder || (this.__jsonEncoder = (0, lazyFunction_1.lazy)(() => (this.__jsonEncoder = this.compileJsonTextEncoder({}))))); } compileEncoder(format, name) { switch (format) { case 0 /* EncodingFormat.Cbor */: { const encoder = this.compileCborEncoder({ name }); this.encoders.set(0 /* EncodingFormat.Cbor */, encoder); return encoder; } case 1 /* EncodingFormat.MsgPack */: { const encoder = this.compileMessagePackEncoder({ name }); this.encoders.set(1 /* EncodingFormat.MsgPack */, encoder); return encoder; } case 2 /* EncodingFormat.Json */: { const encoder = this.compileJsonEncoder({ name }); this.encoders.set(2 /* EncodingFormat.Json */, encoder); return encoder; } default: throw new Error(`Unsupported encoding format: ${format}`); } } encoder(kind) { const encoders = this.encoders; const cachedEncoder = encoders.get(kind); if (cachedEncoder) return cachedEncoder; const temporaryWrappedEncoder = (0, lazyFunction_1.lazy)(() => this.compileEncoder(kind)); encoders.set(kind, temporaryWrappedEncoder); return temporaryWrappedEncoder; } encode(codec, value) { const encoder = this.encoder(codec.format); const writer = codec.encoder.writer; writer.reset(); encoder(value, codec.encoder); return writer.flush(); } codegenValidator(ctx, path, r) { // Use the centralized router function const { generate } = require('../../codegen/validator/validators'); generate(ctx, path, r, this); } compileCborEncoder(options) { const ctx = new CborEncoderCodegenContext_1.CborEncoderCodegenContext({ system: this.system, encoder: new CborEncoder_1.CborEncoder(), ...options, type: this, }); const r = ctx.codegen.options.args[0]; const value = new JsExpression_1.JsExpression(() => r); this.codegenCborEncoder(ctx, value); return ctx.compile(); } codegenCborEncoder(ctx, value) { // Use the centralized router function const { generate } = require('../../codegen/binary/cborEncoders'); generate(ctx, value, this); } compileMessagePackEncoder(options) { const ctx = new MessagePackEncoderCodegenContext_1.MessagePackEncoderCodegenContext({ system: this.system, encoder: new msgpack_1.MsgPackEncoder(), ...options, type: this, }); const r = ctx.codegen.options.args[0]; const value = new JsExpression_1.JsExpression(() => r); this.codegenMessagePackEncoder(ctx, value); return ctx.compile(); } codegenMessagePackEncoder(ctx, value) { // Use the centralized router function const { generate } = require('../../codegen/binary/messagePackEncoders'); generate(ctx, value, this); } compileJsonEncoder(options) { const writer = new Writer_1.Writer(); const ctx = new JsonEncoderCodegenContext_1.JsonEncoderCodegenContext({ system: this.system, encoder: new JsonEncoder_1.JsonEncoder(writer), ...options, type: this, }); const r = ctx.codegen.options.args[0]; const value = new JsExpression_1.JsExpression(() => r); this.codegenJsonEncoder(ctx, value); return ctx.compile(); } codegenJsonEncoder(ctx, value) { // Use the centralized router function const { generate } = require('../../codegen/binary/jsonEncoders'); generate(ctx, value, this); } codegenCapacityEstimator(ctx, value) { // Use the centralized router function (0, estimators_1.generate)(ctx, value, this); } compileCapacityEstimator(options) { const ctx = new CapacityEstimatorCodegenContext_1.CapacityEstimatorCodegenContext({ system: this.system, ...options, type: this, }); const r = ctx.codegen.options.args[0]; const value = new JsExpression_1.JsExpression(() => r); // Use the centralized router instead of the abstract method (0, estimators_1.generate)(ctx, value, this); return ctx.compile(); } capacityEstimator() { return (this.__capacityEstimator || (this.__capacityEstimator = (0, lazyFunction_1.lazy)(() => (this.__capacityEstimator = this.compileCapacityEstimator({}))))); } random() { return (0, generator_1.random)(this); } toTypeScriptAst() { // Use dynamic import to avoid circular dependency const converter = require('../../typescript/converter'); return converter.toTypeScriptAst(this.getSchema()); } toJson(value, system = this.system) { return JSON.stringify(value); } toStringTitle() { return this.getTypeName(); } toStringOptions() { const options = this.getOptions(); const title = options.title || options.intro || options.description; if (!title) return ''; return JSON.stringify(title); } toStringName() { return 'AbsType'; } toString(tab = '') { const options = this.toStringOptions(); return this.toStringTitle() + (options ? ` ${options}` : ''); } toJtdForm() { // Use dynamic import to avoid circular dependency const converter = require('../../jtd/converter'); return converter.toJtdForm(this.getSchema()); } } exports.AbsType = AbsType;