UNPKG

@naturalcycles/js-lib

Version:

Standard library for universal (browser + Node.js) javascript

363 lines (362 loc) 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JsonSchemaTupleBuilder = exports.JsonSchemaArrayBuilder = exports.JsonSchemaObjectBuilder = exports.JsonSchemaStringBuilder = exports.JsonSchemaNumberBuilder = exports.JsonSchemaAnyBuilder = exports.jsonSchema = void 0; const array_util_1 = require("../array/array.util"); const index_1 = require("../index"); const jsonSchema_cnst_1 = require("./jsonSchema.cnst"); /** * Fluent (chainable) API to manually create Json Schemas. * Inspired by Joi */ exports.jsonSchema = { any() { return new JsonSchemaAnyBuilder({}); }, const(value) { return new JsonSchemaAnyBuilder({ const: value, }); }, null() { return new JsonSchemaAnyBuilder({ type: 'null', }); }, ref($ref) { return new JsonSchemaAnyBuilder({ $ref, }); }, enum(enumValues) { return new JsonSchemaAnyBuilder({ enum: enumValues }); }, boolean() { return new JsonSchemaAnyBuilder({ type: 'boolean', }); }, buffer() { return new JsonSchemaAnyBuilder({ instanceof: 'Buffer', }); }, // number types number() { return new JsonSchemaNumberBuilder(); }, integer() { return new JsonSchemaNumberBuilder().integer(); }, unixTimestamp() { return new JsonSchemaNumberBuilder().unixTimestamp(); }, unixTimestamp2000() { return new JsonSchemaNumberBuilder().unixTimestamp2000(); }, // string types string() { return new JsonSchemaStringBuilder(); }, dateString() { return new JsonSchemaStringBuilder().date(); }, // email: () => new JsonSchemaStringBuilder().email(), // complex types object(props) { return new JsonSchemaObjectBuilder().addProperties(props); }, rootObject(props) { return new JsonSchemaObjectBuilder().addProperties(props).$schemaDraft7(); }, array(itemSchema) { return new JsonSchemaArrayBuilder(itemSchema); }, tuple(items) { return new JsonSchemaTupleBuilder(items); }, oneOf(items) { return new JsonSchemaAnyBuilder({ oneOf: items.map(b => b.build()), }); }, allOf(items) { return new JsonSchemaAnyBuilder({ allOf: items.map(b => b.build()), }); }, }; class JsonSchemaAnyBuilder { schema; constructor(schema) { this.schema = schema; } /** * Used in ObjectBuilder to access schema.optionalProperty */ getSchema() { return this.schema; } $schema($schema) { Object.assign(this.schema, { $schema }); return this; } $schemaDraft7() { this.$schema('http://json-schema.org/draft-07/schema#'); return this; } $id($id) { Object.assign(this.schema, { $id }); return this; } title(title) { Object.assign(this.schema, { title }); return this; } description(description) { Object.assign(this.schema, { description }); return this; } deprecated(deprecated = true) { Object.assign(this.schema, { deprecated }); return this; } type(type) { Object.assign(this.schema, { type }); return this; } default(v) { Object.assign(this.schema, { default: v }); return this; } oneOf(schemas) { Object.assign(this.schema, { oneOf: schemas }); return this; } allOf(schemas) { Object.assign(this.schema, { allOf: schemas }); return this; } instanceof(of) { this.schema.instanceof = of; return this; } optional(optional = true) { if (optional) { this.schema.optionalField = true; } else { this.schema.optionalField = undefined; } return this; } /** * Produces a "clean schema object" without methods. * Same as if it would be JSON.stringified. */ build() { return (0, index_1._sortObject)(JSON.parse(JSON.stringify(this.schema)), jsonSchema_cnst_1.JSON_SCHEMA_ORDER); } clone() { return new JsonSchemaAnyBuilder((0, index_1._deepCopy)(this.schema)); } } exports.JsonSchemaAnyBuilder = JsonSchemaAnyBuilder; class JsonSchemaNumberBuilder extends JsonSchemaAnyBuilder { constructor() { super({ type: 'number', }); } integer() { Object.assign(this.schema, { type: 'integer' }); return this; } multipleOf(multipleOf) { Object.assign(this.schema, { multipleOf }); return this; } min(minimum) { Object.assign(this.schema, { minimum }); return this; } exclusiveMin(exclusiveMinimum) { Object.assign(this.schema, { exclusiveMinimum }); return this; } max(maximum) { Object.assign(this.schema, { maximum }); return this; } exclusiveMax(exclusiveMaximum) { Object.assign(this.schema, { exclusiveMaximum }); return this; } /** * Both ranges are inclusive. */ range(minimum, maximum) { Object.assign(this.schema, { minimum, maximum }); return this; } format(format) { Object.assign(this.schema, { format }); return this; } int32 = () => this.format('int32'); int64 = () => this.format('int64'); float = () => this.format('float'); double = () => this.format('double'); unixTimestamp = () => this.format('unixTimestamp'); unixTimestamp2000 = () => this.format('unixTimestamp2000'); unixTimestampMillis = () => this.format('unixTimestampMillis'); unixTimestampMillis2000 = () => this.format('unixTimestampMillis2000'); utcOffset = () => this.format('utcOffset'); utcOffsetHours = () => this.format('utcOffsetHours'); } exports.JsonSchemaNumberBuilder = JsonSchemaNumberBuilder; class JsonSchemaStringBuilder extends JsonSchemaAnyBuilder { constructor() { super({ type: 'string', }); } pattern(pattern) { Object.assign(this.schema, { pattern }); return this; } min(minLength) { Object.assign(this.schema, { minLength }); return this; } max(maxLength) { Object.assign(this.schema, { maxLength }); return this; } length(minLength, maxLength) { Object.assign(this.schema, { minLength, maxLength }); return this; } format(format) { Object.assign(this.schema, { format }); return this; } email = () => this.format('email'); date = () => this.format('date'); url = () => this.format('url'); ipv4 = () => this.format('ipv4'); ipv6 = () => this.format('ipv6'); password = () => this.format('password'); id = () => this.format('id'); slug = () => this.format('slug'); semVer = () => this.format('semVer'); languageTag = () => this.format('languageTag'); countryCode = () => this.format('countryCode'); currency = () => this.format('currency'); trim = (trim = true) => this.transformModify('trim', trim); toLowerCase = (toLowerCase = true) => this.transformModify('toLowerCase', toLowerCase); toUpperCase = (toUpperCase = true) => this.transformModify('toUpperCase', toUpperCase); transformModify(t, add) { if (add) { this.schema.transform = (0, array_util_1._uniq)([...(this.schema.transform || []), t]); } else { this.schema.transform = this.schema.transform?.filter(s => s !== t); } return this; } } exports.JsonSchemaStringBuilder = JsonSchemaStringBuilder; class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder { constructor() { super({ type: 'object', properties: {}, required: [], additionalProperties: false, }); } addProperties(props) { Object.entries(props).forEach(([k, builder]) => { const schema = builder.build(); if (!schema.optionalField) { this.schema.required.push(k); } else { schema.optionalField = undefined; } this.schema.properties[k] = schema; }); this.required(this.schema.required); // ensure it's sorted and _uniq return this; } /** * Ensures `required` is always sorted and _uniq */ required(required) { Object.assign(this.schema, { required }); this.schema.required = (0, array_util_1._uniq)(required).sort(); return this; } addRequired(required) { return this.required([...this.schema.required, ...required]); } minProps(minProperties) { Object.assign(this.schema, { minProperties }); return this; } maxProps(maxProperties) { Object.assign(this.schema, { maxProperties }); return this; } additionalProps(additionalProperties) { Object.assign(this.schema, { additionalProperties }); return this; } baseDBEntity() { Object.assign(this.schema.properties, { id: { type: 'string' }, created: { type: 'number', format: 'unixTimestamp2000' }, updated: { type: 'number', format: 'unixTimestamp2000' }, }); return this.addRequired(['id', 'created', 'updated']); } extend(s2) { const builder = new JsonSchemaObjectBuilder(); Object.assign(builder.schema, (0, index_1._deepCopy)(this.schema)); (0, index_1.mergeJsonSchemaObjects)(builder.schema, s2.schema); return builder; } } exports.JsonSchemaObjectBuilder = JsonSchemaObjectBuilder; class JsonSchemaArrayBuilder extends JsonSchemaAnyBuilder { constructor(itemsSchema) { super({ type: 'array', items: itemsSchema.build(), }); } min(minItems) { Object.assign(this.schema, { minItems }); return this; } max(maxItems) { Object.assign(this.schema, { maxItems }); return this; } unique(uniqueItems) { Object.assign(this.schema, { uniqueItems }); return this; } } exports.JsonSchemaArrayBuilder = JsonSchemaArrayBuilder; class JsonSchemaTupleBuilder extends JsonSchemaAnyBuilder { constructor(items) { super({ type: 'array', items: items.map(b => b.build()), minItems: items.length, maxItems: items.length, }); } } exports.JsonSchemaTupleBuilder = JsonSchemaTupleBuilder;