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