3706 lines
90 KiB
TypeScript
3706 lines
90 KiB
TypeScript
import type { Options as AjvOptions } from "ajv"
|
|
import { Effect, JsonSchema, Option, Predicate, Schema, SchemaGetter } from "effect"
|
|
// import { FastCheck } from "effect/testing"
|
|
import { describe, it } from "vitest"
|
|
import { assertTrue, deepStrictEqual, throws } from "../utils/assert.ts"
|
|
|
|
// oxlint-disable-next-line @typescript-eslint/no-require-imports
|
|
const Ajv2020 = require("ajv/dist/2020")
|
|
|
|
const baseAjvOptions: AjvOptions = {
|
|
allErrors: true,
|
|
strict: false, // warns/throws on unknown keywords depending on Ajv version
|
|
validateSchema: true,
|
|
code: { esm: true } // optional
|
|
}
|
|
|
|
const ajvDraft2020_12 = new Ajv2020.default(baseAjvOptions)
|
|
|
|
function assertUnsupportedSchema(
|
|
schema: Schema.Constraint,
|
|
message: string,
|
|
options?: Schema.ToJsonSchemaOptions
|
|
) {
|
|
throws(() => Schema.toJsonSchemaDocument(schema, options), message)
|
|
}
|
|
|
|
function assertJsonSchemaDocument<T, E, RD>(
|
|
schema: Schema.Codec<T, E, RD, never>,
|
|
expected: { schema: JsonSchema.JsonSchema; definitions?: JsonSchema.Definitions },
|
|
options?: Schema.ToJsonSchemaOptions
|
|
) {
|
|
const document = Schema.toJsonSchemaDocument(schema, options)
|
|
deepStrictEqual(document, {
|
|
dialect: "draft-2020-12",
|
|
schema: expected.schema,
|
|
definitions: expected.definitions ?? {}
|
|
})
|
|
const jsonSchema = {
|
|
$schema: JsonSchema.META_SCHEMA_URI_DRAFT_2020_12,
|
|
...document.schema,
|
|
$defs: document.definitions
|
|
}
|
|
const valid = ajvDraft2020_12.validateSchema(jsonSchema)
|
|
assertTrue(valid)
|
|
// const validate = ajvDraft2020_12.compile(jsonSchema)
|
|
// const arb = Schema.toArbitrary(schema)
|
|
// const codec = Schema.toCodecJson(schema)
|
|
// const encode = Schema.encodeSync(codec)
|
|
// FastCheck.assert(FastCheck.property(arb, (t) => {
|
|
// const e = encode(t)
|
|
// return validate(e)
|
|
// }))
|
|
}
|
|
|
|
describe("toJsonSchemaDocument", () => {
|
|
describe("Unsupported schemas", () => {
|
|
it("Tuple: unsupported post-rest elements", () => {
|
|
assertUnsupportedSchema(
|
|
Schema.TupleWithRest(Schema.Tuple([]), [Schema.Finite, Schema.String]),
|
|
"Generating a JSON Schema for post-rest elements is not supported"
|
|
)
|
|
})
|
|
|
|
it("Struct: unsupported property signature name", () => {
|
|
const a = Symbol.for("effect/Schema/test/a")
|
|
assertUnsupportedSchema(
|
|
Schema.Struct({ [a]: Schema.String }),
|
|
`Unsupported property signature name: Symbol(effect/Schema/test/a)`
|
|
)
|
|
})
|
|
|
|
it("Record: unsupported index signature parameter", () => {
|
|
assertUnsupportedSchema(
|
|
Schema.Record(Schema.Symbol, Schema.Finite),
|
|
`Unsupported index signature parameter: Symbol`
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("options", () => {
|
|
it("generateDescriptions: true", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({ expected: "b" }),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "b"
|
|
}
|
|
},
|
|
{ generateDescriptions: true }
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({ description: "a", expected: "b" }),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "a"
|
|
}
|
|
},
|
|
{ generateDescriptions: true }
|
|
)
|
|
})
|
|
|
|
describe("additionalProperties", () => {
|
|
it(`false (default)`, () => {
|
|
const schema = Schema.Struct({ a: Schema.String })
|
|
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}, {
|
|
additionalProperties: false
|
|
})
|
|
})
|
|
|
|
it(`true`, () => {
|
|
const schema = Schema.Struct({ a: Schema.String })
|
|
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": true
|
|
}
|
|
}, {
|
|
additionalProperties: true
|
|
})
|
|
})
|
|
|
|
it(`schema`, () => {
|
|
const schema = Schema.Struct({ a: Schema.String })
|
|
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}, {
|
|
additionalProperties: { "type": "string" }
|
|
})
|
|
})
|
|
})
|
|
|
|
describe("includeAnnotationKey", () => {
|
|
it("passthroughs matching annotation keys at schema level", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({
|
|
title: "Name",
|
|
description: "A name",
|
|
"markdownDescription": "The **name** field"
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"title": "Name",
|
|
"description": "A name",
|
|
"markdownDescription": "The **name** field"
|
|
}
|
|
},
|
|
{ includeAnnotationKey: (key) => key === "markdownDescription" }
|
|
)
|
|
})
|
|
|
|
it("does not include keys not matching the predicate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({
|
|
title: "Name",
|
|
description: "A name",
|
|
"markdownDescription": "The **name** field",
|
|
"customKey": "value"
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"title": "Name",
|
|
"description": "A name",
|
|
"markdownDescription": "The **name** field"
|
|
}
|
|
},
|
|
{ includeAnnotationKey: (key) => key === "markdownDescription" }
|
|
)
|
|
})
|
|
|
|
it("does not include matching keys with undefined values", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({
|
|
"x-missing": undefined,
|
|
"x-value": "value"
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"x-value": "value"
|
|
}
|
|
},
|
|
{ includeAnnotationKey: (key) => key.startsWith("x-") }
|
|
)
|
|
})
|
|
|
|
it("standard keys are always included regardless of predicate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({
|
|
title: "Name",
|
|
description: "A name",
|
|
default: "hello"
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"title": "Name",
|
|
"description": "A name",
|
|
"default": "hello"
|
|
}
|
|
},
|
|
{ includeAnnotationKey: (_key) => false }
|
|
)
|
|
})
|
|
|
|
it("does not overwrite generated contentSchema with the raw annotation", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.fromJsonString(Schema.Struct({
|
|
a: Schema.String
|
|
})),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"contentMediaType": "application/json",
|
|
"contentSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
},
|
|
{ includeAnnotationKey: (key) => key === "contentSchema" }
|
|
)
|
|
})
|
|
|
|
it("passthroughs at property level in structs", () => {
|
|
const schema = Schema.Struct({
|
|
name: Schema.String.annotate({
|
|
description: "A name",
|
|
"markdownDescription": "The **name** field"
|
|
}),
|
|
tag: Schema.String.annotate({
|
|
description: "A tag",
|
|
"defaultSnippets": [{ label: "v1", body: "v1" }]
|
|
})
|
|
})
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"name": {
|
|
"type": "string",
|
|
"description": "A name",
|
|
"markdownDescription": "The **name** field"
|
|
},
|
|
"tag": {
|
|
"type": "string",
|
|
"description": "A tag",
|
|
"defaultSnippets": [{ label: "v1", body: "v1" }]
|
|
}
|
|
},
|
|
"required": ["name", "tag"],
|
|
"additionalProperties": false
|
|
}
|
|
},
|
|
{ includeAnnotationKey: (key) => key === "markdownDescription" || key === "defaultSnippets" }
|
|
)
|
|
})
|
|
|
|
it("passthroughs at check level", () => {
|
|
const schema = Schema.String
|
|
.annotate({ description: "A string" })
|
|
.pipe(
|
|
Schema.check(
|
|
Schema.isMinLength(1, {
|
|
"x-check-annotation": true
|
|
})
|
|
)
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "A string",
|
|
"allOf": [{
|
|
"minLength": 1,
|
|
"x-check-annotation": true
|
|
}]
|
|
}
|
|
},
|
|
{ includeAnnotationKey: (key) => key.startsWith("x-") }
|
|
)
|
|
})
|
|
|
|
it("passthroughs x- prefixed vendor extensions", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({
|
|
description: "A value",
|
|
"x-custom": true,
|
|
"x-extension": { foo: "bar" }
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "A value",
|
|
"x-custom": true,
|
|
"x-extension": { foo: "bar" }
|
|
}
|
|
},
|
|
{ includeAnnotationKey: (key) => key.startsWith("x-") }
|
|
)
|
|
})
|
|
})
|
|
})
|
|
|
|
it("should support JSON Schema annotations", () => {
|
|
const schema = Schema.String.annotate({
|
|
title: "a",
|
|
description: "b",
|
|
default: "c",
|
|
examples: ["d"],
|
|
readOnly: true,
|
|
writeOnly: true
|
|
})
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "string",
|
|
"title": "a",
|
|
"description": "b",
|
|
"default": "c",
|
|
"examples": ["d"],
|
|
"readOnly": true,
|
|
"writeOnly": true
|
|
}
|
|
})
|
|
})
|
|
|
|
describe("identifier handling", () => {
|
|
it(`refs should escape "~" and "/"`, () => {
|
|
const S = Schema.String.annotate({ identifier: "id~a/b" })
|
|
assertJsonSchemaDocument(
|
|
S,
|
|
{
|
|
schema: { "$ref": "#/$defs/id~0a~1b" },
|
|
definitions: {
|
|
"id~a/b": { "type": "string" }
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("using the same identifier annotated schema twice", () => {
|
|
const S = Schema.String.annotate({ identifier: "id" })
|
|
assertJsonSchemaDocument(
|
|
Schema.Union([S, S]),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{ "$ref": "#/$defs/id" },
|
|
{ "$ref": "#/$defs/id" }
|
|
]
|
|
},
|
|
definitions: {
|
|
id: { "type": "string" }
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("should handle duplicate identifiers on different schemas with different representations", () => {
|
|
const S = Schema.Union([
|
|
Schema.String.annotate({ identifier: "id", description: "a" }),
|
|
Schema.String.annotate({ identifier: "id", description: "b" })
|
|
])
|
|
assertJsonSchemaDocument(S, {
|
|
schema: {
|
|
"anyOf": [
|
|
{ "$ref": "#/$defs/id" },
|
|
{ "$ref": "#/$defs/id1" }
|
|
]
|
|
},
|
|
definitions: {
|
|
id: { "type": "string", "description": "a" },
|
|
id1: { "type": "string", "description": "b" }
|
|
}
|
|
})
|
|
})
|
|
|
|
it("should handle duplicate identifiers on different schemas with the same representation", () => {
|
|
const X = Schema.String.annotate({ title: "X", identifier: "X" })
|
|
const S = Schema.Struct({
|
|
a: X,
|
|
b: Schema.NullOr(X),
|
|
c: Schema.optionalKey(X),
|
|
d: Schema.optionalKey(Schema.NullOr(X)),
|
|
e: Schema.NullOr(X).pipe(
|
|
Schema.encodeTo(Schema.optionalKey(X), {
|
|
decode: SchemaGetter.transformOptional(Option.orElseSome(() => null)),
|
|
encode: SchemaGetter.transformOptional(Option.filter(Predicate.isNotNull))
|
|
})
|
|
)
|
|
})
|
|
assertJsonSchemaDocument(S, {
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"$ref": "#/$defs/X"
|
|
},
|
|
"b": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/$defs/X"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"c": {
|
|
"$ref": "#/$defs/X"
|
|
},
|
|
"d": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/$defs/X"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"e": {
|
|
"$ref": "#/$defs/X"
|
|
}
|
|
},
|
|
"required": [
|
|
"a",
|
|
"b"
|
|
],
|
|
"additionalProperties": false
|
|
},
|
|
definitions: {
|
|
"X": {
|
|
"type": "string",
|
|
"title": "X"
|
|
}
|
|
}
|
|
})
|
|
})
|
|
})
|
|
|
|
describe("Declaration", () => {
|
|
it("Date", () => {
|
|
const schema = Schema.Date
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "string"
|
|
}
|
|
})
|
|
})
|
|
|
|
it("DateValid", () => {
|
|
const schema = Schema.DateValid
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "format": "date-time" }
|
|
]
|
|
}
|
|
})
|
|
})
|
|
|
|
it("URL", () => {
|
|
const schema = Schema.URL
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "string"
|
|
}
|
|
})
|
|
})
|
|
|
|
it("Error", () => {
|
|
const schema = Schema.Error()
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"name": { "type": "string" },
|
|
"message": { "type": "string" },
|
|
"stack": { "type": "string" },
|
|
"cause": {}
|
|
},
|
|
"required": ["message"],
|
|
"additionalProperties": false
|
|
}
|
|
})
|
|
})
|
|
|
|
it("RegExp", () => {
|
|
const schema = Schema.RegExp
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"source": { "type": "string" },
|
|
"flags": { "type": "string" }
|
|
},
|
|
"required": ["source", "flags"],
|
|
"additionalProperties": false
|
|
}
|
|
})
|
|
})
|
|
|
|
it("Uint8Array", () => {
|
|
const schema = Schema.Uint8Array
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "string",
|
|
"format": "byte",
|
|
"contentEncoding": "base64"
|
|
}
|
|
})
|
|
})
|
|
|
|
it("Duration", () => {
|
|
const schema = Schema.Duration
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"_tag": {
|
|
"type": "string",
|
|
"enum": ["Infinity"]
|
|
}
|
|
},
|
|
"required": ["_tag"],
|
|
"additionalProperties": false
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"_tag": {
|
|
"type": "string",
|
|
"enum": ["NegativeInfinity"]
|
|
}
|
|
},
|
|
"required": ["_tag"],
|
|
"additionalProperties": false
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"_tag": {
|
|
"type": "string",
|
|
"enum": ["Nanos"]
|
|
},
|
|
"value": {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "pattern": "^-?\\d+$" }
|
|
]
|
|
}
|
|
},
|
|
"required": ["_tag", "value"],
|
|
"additionalProperties": false
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"_tag": {
|
|
"type": "string",
|
|
"enum": ["Millis"]
|
|
},
|
|
"value": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": ["_tag", "value"],
|
|
"additionalProperties": false
|
|
}
|
|
]
|
|
}
|
|
})
|
|
})
|
|
|
|
it("Option(String)", () => {
|
|
const schema = Schema.Option(Schema.String)
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"_tag": {
|
|
"type": "string",
|
|
"enum": ["Some"]
|
|
},
|
|
"value": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["_tag", "value"],
|
|
"additionalProperties": false
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"_tag": {
|
|
"type": "string",
|
|
"enum": ["None"]
|
|
}
|
|
},
|
|
"required": ["_tag"],
|
|
"additionalProperties": false
|
|
}
|
|
]
|
|
}
|
|
})
|
|
})
|
|
})
|
|
|
|
it("Any", () => {
|
|
const schema = Schema.Any
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Json", () => {
|
|
const schema = Schema.Json
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("MutableJson", () => {
|
|
const schema = Schema.MutableJson
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Unknown", () => {
|
|
const schema = Schema.Unknown
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Void", () => {
|
|
const schema = Schema.Void
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "null"
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "null",
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Undefined", () => {
|
|
const schema = Schema.Undefined
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "null"
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "null",
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("BigInt", () => {
|
|
const schema = Schema.BigInt
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "pattern": "^-?\\d+$" }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Symbol", () => {
|
|
const schema = Schema.Symbol
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "pattern": "^Symbol\\((.*)\\)$" }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("UniqueSymbol", () => {
|
|
const schema = Schema.UniqueSymbol(Symbol.for("a"))
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "pattern": "^Symbol\\((.*)\\)$" }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Never", () => {
|
|
const schema = Schema.Never
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"not": {}
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"description": "a",
|
|
"not": {}
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Null", () => {
|
|
const schema = Schema.Null
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "null"
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "null",
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
describe("String", () => {
|
|
it("String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String,
|
|
{
|
|
schema: {
|
|
"type": "string"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("should ignore annotateKey annotations if the schema is not contextual", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotateKey({
|
|
description: "a"
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "string"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & check", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.check(Schema.isMinLength(2)),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "minLength": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & custom check without annotation", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.check(Schema.makeFilter(() => true)),
|
|
{
|
|
schema: {
|
|
"type": "string"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate & check", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({ description: "a" }).check(Schema.isMinLength(2)),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "a",
|
|
"allOf": [
|
|
{ "minLength": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & check & annotate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.check(Schema.isMinLength(2)).annotate({
|
|
description: "a"
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "minLength": 2, "description": "a" }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & check & check", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.check(Schema.isMinLength(2), Schema.isMaxLength(3)),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "minLength": 2 },
|
|
{ "maxLength": 3 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate & check & check", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({ description: "a" }).check(Schema.isMinLength(2), Schema.isMaxLength(3)),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "a",
|
|
"allOf": [
|
|
{ "minLength": 2 },
|
|
{ "maxLength": 3 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & check & check & annotate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.check(Schema.isMinLength(2), Schema.isMaxLength(3)).annotate({
|
|
description: "a"
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{
|
|
"minLength": 2
|
|
},
|
|
{
|
|
"maxLength": 3,
|
|
"description": "a"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate & check & check & annotate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({ description: "a" }).check(
|
|
Schema.isMinLength(2),
|
|
Schema.isMaxLength(3, { description: "c" })
|
|
),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "a",
|
|
"allOf": [
|
|
{
|
|
"minLength": 2
|
|
},
|
|
{
|
|
"maxLength": 3,
|
|
"description": "c"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & check & annotations & check & annotations", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.check(
|
|
Schema.isMinLength(2, { description: "b" }),
|
|
Schema.isMaxLength(3, { description: "c" })
|
|
),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{
|
|
"minLength": 2,
|
|
"description": "b"
|
|
},
|
|
{
|
|
"maxLength": 3,
|
|
"description": "c"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotations & check & annotations & check & annotations", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({ description: "a" }).check(
|
|
Schema.isMinLength(2, { description: "b" }),
|
|
Schema.isMaxLength(3, { description: "c" })
|
|
),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "a",
|
|
"allOf": [
|
|
{
|
|
"minLength": 2,
|
|
"description": "b"
|
|
},
|
|
{
|
|
"maxLength": 3,
|
|
"description": "c"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
describe("checks", () => {
|
|
it("isPattern", () => {
|
|
assertJsonSchemaDocument(Schema.String.check(Schema.isPattern(/^abb+$/)), {
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "pattern": "^abb+$" }
|
|
]
|
|
}
|
|
})
|
|
})
|
|
|
|
it("isTrimmed", () => {
|
|
const schema = Schema.Trimmed
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "pattern": "^\\S[\\s\\S]*\\S$|^\\S$|^$" }
|
|
]
|
|
}
|
|
})
|
|
})
|
|
|
|
it("isLowercased", () => {
|
|
const schema = Schema.String.check(Schema.isLowercased())
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "pattern": "^[^A-Z]*$" }
|
|
]
|
|
}
|
|
})
|
|
})
|
|
|
|
it("isUppercased", () => {
|
|
const schema = Schema.String.check(Schema.isUppercased())
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "pattern": "^[^a-z]*$" }
|
|
]
|
|
}
|
|
})
|
|
})
|
|
|
|
it("isCapitalized", () => {
|
|
const schema = Schema.String.check(Schema.isCapitalized())
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "pattern": "^[^a-z]?.*$" }
|
|
]
|
|
}
|
|
})
|
|
})
|
|
|
|
it("isUncapitalized", () => {
|
|
const schema = Schema.String.check(Schema.isUncapitalized())
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "pattern": "^[^A-Z]?.*$" }
|
|
]
|
|
}
|
|
})
|
|
})
|
|
|
|
describe("isLengthBetween", () => {
|
|
it("String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.check(Schema.isLengthBetween(2, 2)),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "minLength": 2 },
|
|
{ "maxLength": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Array", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Array(Schema.String).check(Schema.isLengthBetween(2, 2)),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"allOf": [
|
|
{ "minItems": 2 },
|
|
{ "maxItems": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("NonEmptyArray", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.NonEmptyArray(Schema.String).check(Schema.isLengthBetween(2, 2)),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [{
|
|
"type": "string"
|
|
}],
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"minItems": 1,
|
|
"allOf": [
|
|
{ "minItems": 2 },
|
|
{ "maxItems": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("isMinLength", () => {
|
|
it("String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.check(Schema.isMinLength(2)),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "minLength": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Array", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Array(Schema.String).check(Schema.isMinLength(2)),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"allOf": [
|
|
{ "minItems": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("NonEmptyArray", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.NonEmptyArray(Schema.String).check(Schema.isMinLength(2)),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [{
|
|
"type": "string"
|
|
}],
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"minItems": 1,
|
|
"allOf": [
|
|
{ "minItems": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("isMaxLength", () => {
|
|
it("String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.check(Schema.isMaxLength(2)),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "maxLength": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Array", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Array(Schema.String).check(Schema.isMaxLength(2)),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"allOf": [
|
|
{ "maxItems": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("NonEmptyArray", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.NonEmptyArray(Schema.String).check(Schema.isMaxLength(2)),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"prefixItems": [{
|
|
"type": "string"
|
|
}],
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"allOf": [
|
|
{ "maxItems": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
it("isUUID", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({ description: "description" }).check(Schema.isUUID()),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "description",
|
|
"allOf": [
|
|
{
|
|
"format": "uuid",
|
|
"pattern":
|
|
"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|[fF]{8}-[fF]{4}-[fF]{4}-[fF]{4}-[fF]{12})$"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isGUID", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({ description: "description" }).check(Schema.isGUID()),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "description",
|
|
"allOf": [
|
|
{
|
|
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isBase64", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({ description: "description" }).check(Schema.isBase64()),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "description",
|
|
"allOf": [
|
|
{ "pattern": "^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$" }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isBase64Url", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.String.annotate({ description: "description" }).check(Schema.isBase64Url()),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"description": "description",
|
|
"allOf": [
|
|
{ "pattern": "^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$" }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe("Number", () => {
|
|
it("Number", () => {
|
|
const schema = Schema.Number
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{ "type": "number" },
|
|
{ "type": "string", "enum": ["NaN"] },
|
|
{ "type": "string", "enum": ["Infinity"] },
|
|
{ "type": "string", "enum": ["-Infinity"] }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{ "type": "number" },
|
|
{ "type": "string", "enum": ["NaN"] },
|
|
{ "type": "string", "enum": ["Infinity"] },
|
|
{ "type": "string", "enum": ["-Infinity"] }
|
|
],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("Finite", () => {
|
|
it("Finite", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite,
|
|
{
|
|
schema: {
|
|
"type": "number"
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"allOf": [{
|
|
"description": "a"
|
|
}]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
describe("checks", () => {
|
|
it("isInt", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.check(Schema.isInt()),
|
|
{
|
|
schema: {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isInt32", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.check(Schema.isInt32()),
|
|
{
|
|
schema: {
|
|
"type": "integer",
|
|
"allOf": [
|
|
{ "maximum": 2147483647, "minimum": -2147483648 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isUint32", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.check(Schema.isUint32()),
|
|
{
|
|
schema: {
|
|
"type": "integer",
|
|
"allOf": [
|
|
{ "maximum": 4294967295, "minimum": 0 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.check(Schema.isUint32({ description: "a" })),
|
|
{
|
|
schema: {
|
|
"type": "integer",
|
|
"allOf": [
|
|
{
|
|
"description": "a",
|
|
"allOf": [
|
|
{ "maximum": 4294967295, "minimum": 0 }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.check(
|
|
Schema.isUint32({ description: "a" })
|
|
),
|
|
{
|
|
schema: {
|
|
"type": "integer",
|
|
"allOf": [
|
|
{
|
|
"description": "a",
|
|
"allOf": [
|
|
{ "maximum": 4294967295, "minimum": 0 }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isGreaterThan", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.check(Schema.isGreaterThan(1)),
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"allOf": [
|
|
{ "exclusiveMinimum": 1 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isGreaterThanOrEqualTo", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1)),
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"allOf": [
|
|
{ "minimum": 1 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isLessThan", () => {
|
|
assertJsonSchemaDocument(Schema.Finite.check(Schema.isLessThan(1)), {
|
|
schema: {
|
|
"type": "number",
|
|
"allOf": [
|
|
{ "exclusiveMaximum": 1 }
|
|
]
|
|
}
|
|
})
|
|
})
|
|
|
|
it("isLessThanOrEqualTo", () => {
|
|
assertJsonSchemaDocument(Schema.Finite.check(Schema.isLessThanOrEqualTo(1)), {
|
|
schema: {
|
|
"type": "number",
|
|
"allOf": [
|
|
{ "maximum": 1 }
|
|
]
|
|
}
|
|
})
|
|
})
|
|
|
|
it("isBetween", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.check(Schema.isBetween({ minimum: 1, maximum: 10 })),
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"allOf": [
|
|
{ "minimum": 1, "maximum": 10 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.check(
|
|
Schema.isBetween({ minimum: 1, maximum: 10, exclusiveMinimum: true })
|
|
),
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"allOf": [
|
|
{ "exclusiveMinimum": 1, "maximum": 10 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.check(
|
|
Schema.isBetween({ minimum: 1, maximum: 10, exclusiveMaximum: true })
|
|
),
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"allOf": [
|
|
{ "minimum": 1, "exclusiveMaximum": 10 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.Finite.check(
|
|
Schema.isBetween({ minimum: 1, maximum: 10, exclusiveMinimum: true, exclusiveMaximum: true })
|
|
),
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"allOf": [
|
|
{ "exclusiveMinimum": 1, "exclusiveMaximum": 10 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isMultipleOf", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Int.check(Schema.isMultipleOf(2)),
|
|
{
|
|
schema: {
|
|
"type": "integer",
|
|
"allOf": [
|
|
{ "multipleOf": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
})
|
|
|
|
it("Boolean", () => {
|
|
const schema = Schema.Boolean
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "boolean"
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "boolean",
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("ObjectKeyword", () => {
|
|
const schema = Schema.ObjectKeyword
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: { anyOf: [{ type: "object" }, { type: "array" }] }
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{ "type": "object" },
|
|
{ "type": "array" }
|
|
],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
describe("Literal", () => {
|
|
it("string", () => {
|
|
const schema = Schema.Literal("a")
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"enum": ["a"]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"enum": ["a"],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("number", () => {
|
|
const schema = Schema.Literal(1)
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"enum": [1]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"enum": [1],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("boolean", () => {
|
|
const schema = Schema.Literal(true)
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "boolean",
|
|
"enum": [true]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "boolean",
|
|
"enum": [true],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("bigint", () => {
|
|
const schema = Schema.Literal(1n)
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"enum": ["1"]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"enum": ["1"],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("Literals", () => {
|
|
it("empty literals", () => {
|
|
const schema = Schema.Literals([])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"not": {}
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"not": {},
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("strings", () => {
|
|
const schema = Schema.Literals(["a", "b"])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"enum": ["a", "b"]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"enum": ["a", "b"],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("numbers", () => {
|
|
const schema = Schema.Literals([1, 2])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"enum": [1, 2]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"enum": [1, 2],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("booleans", () => {
|
|
const schema = Schema.Literals([true, false])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "boolean",
|
|
"enum": [true, false]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "boolean",
|
|
"enum": [true, false],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("strings & numbers", () => {
|
|
const schema = Schema.Literals(["a", 1])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "string",
|
|
"enum": ["a"]
|
|
},
|
|
{
|
|
"type": "number",
|
|
"enum": [1]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "string",
|
|
"enum": ["a"]
|
|
},
|
|
{
|
|
"type": "number",
|
|
"enum": [1]
|
|
}
|
|
],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("Union of literals", () => {
|
|
it("strings", () => {
|
|
const schema = Schema.Union([
|
|
Schema.Literal("a"),
|
|
Schema.Literal("b")
|
|
])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"enum": ["a", "b"]
|
|
}
|
|
}
|
|
)
|
|
const jsonAnnotations = {
|
|
"title": "title",
|
|
"description": "description",
|
|
"default": "a" as const,
|
|
"examples": ["a", "b"] as const
|
|
}
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ ...jsonAnnotations }),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"enum": ["a", "b"],
|
|
...jsonAnnotations
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("nested literals", () => {
|
|
const schema = Schema.Union([
|
|
Schema.Literal("a"),
|
|
Schema.Literals(["b", "c"])
|
|
])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"enum": ["a", "b", "c"]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("strings & inner annotate", () => {
|
|
const schema = Schema.Union([
|
|
Schema.Literal("a"),
|
|
Schema.Literal("b").annotate({ description: "b-description" })
|
|
])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "string",
|
|
"enum": ["a"]
|
|
},
|
|
{
|
|
"type": "string",
|
|
"enum": ["b"],
|
|
"description": "b-description"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
const jsonAnnotations = {
|
|
"title": "title",
|
|
"description": "description",
|
|
"default": "a" as const,
|
|
"examples": ["a", "b"] as const
|
|
}
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ ...jsonAnnotations }),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "string",
|
|
"enum": ["a"]
|
|
},
|
|
{
|
|
"type": "string",
|
|
"enum": ["b"],
|
|
"description": "b-description"
|
|
}
|
|
],
|
|
...jsonAnnotations
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("numbers", () => {
|
|
const schema = Schema.Union([
|
|
Schema.Literal(1),
|
|
Schema.Literal(2)
|
|
])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"enum": [1, 2]
|
|
}
|
|
}
|
|
)
|
|
const jsonAnnotations = {
|
|
"title": "title",
|
|
"description": "description",
|
|
"default": 1 as const,
|
|
"examples": [1, 2] as const
|
|
}
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ ...jsonAnnotations }),
|
|
{
|
|
schema: {
|
|
"type": "number",
|
|
"enum": [1, 2],
|
|
...jsonAnnotations
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("booleans", () => {
|
|
const schema = Schema.Union([
|
|
Schema.Literal(true),
|
|
Schema.Literal(false)
|
|
])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "boolean",
|
|
"enum": [true, false]
|
|
}
|
|
}
|
|
)
|
|
const jsonAnnotations = {
|
|
"title": "title",
|
|
"description": "description",
|
|
"default": true as const,
|
|
"examples": [true, false] as const
|
|
}
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ ...jsonAnnotations }),
|
|
{
|
|
schema: {
|
|
"type": "boolean",
|
|
"enum": [true, false],
|
|
...jsonAnnotations
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("strings & numbers", () => {
|
|
const schema = Schema.Union([
|
|
Schema.Literal("a"),
|
|
Schema.Literal(1)
|
|
])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "string",
|
|
"enum": ["a"]
|
|
},
|
|
{
|
|
"type": "number",
|
|
"enum": [1]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
const jsonAnnotations = {
|
|
"title": "title",
|
|
"description": "description",
|
|
"default": "a" as const,
|
|
"examples": ["a", 1] as const
|
|
}
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ ...jsonAnnotations }),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "string",
|
|
"enum": ["a"]
|
|
},
|
|
{
|
|
"type": "number",
|
|
"enum": [1]
|
|
}
|
|
],
|
|
...jsonAnnotations
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("Enum", () => {
|
|
it("empty enum", () => {
|
|
enum Empty {}
|
|
const schema = Schema.Enum(Empty)
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"not": {}
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"not": {},
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("single enum", () => {
|
|
enum Fruits {
|
|
Apple
|
|
}
|
|
const schema = Schema.Enum(Fruits)
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"enum": [0],
|
|
"title": "Apple"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"description": "a",
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"enum": [0],
|
|
"title": "Apple"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("mixed enums (number & string)", () => {
|
|
enum Fruits {
|
|
Apple,
|
|
Banana,
|
|
Orange = "orange"
|
|
}
|
|
const schema = Schema.Enum(Fruits)
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"enum": [0],
|
|
"title": "Apple"
|
|
},
|
|
{
|
|
"type": "number",
|
|
"enum": [1],
|
|
"title": "Banana"
|
|
},
|
|
{
|
|
"type": "string",
|
|
"enum": ["orange"],
|
|
"title": "Orange"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "number",
|
|
"enum": [0],
|
|
"title": "Apple"
|
|
},
|
|
{
|
|
"type": "number",
|
|
"enum": [1],
|
|
"title": "Banana"
|
|
},
|
|
{
|
|
"type": "string",
|
|
"enum": ["orange"],
|
|
"title": "Orange"
|
|
}
|
|
],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("const enum", () => {
|
|
const Fruits = {
|
|
Apple: "apple",
|
|
Banana: "banana",
|
|
Cantaloupe: 3
|
|
} as const
|
|
const schema = Schema.Enum(Fruits)
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "string",
|
|
"title": "Apple",
|
|
"enum": ["apple"]
|
|
},
|
|
{
|
|
"type": "string",
|
|
"title": "Banana",
|
|
"enum": ["banana"]
|
|
},
|
|
{
|
|
"type": "number",
|
|
"title": "Cantaloupe",
|
|
"enum": [3]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
it("TemplateLiteral", () => {
|
|
const schema = Schema.TemplateLiteral(["a", Schema.String])
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"type": "string",
|
|
"pattern": "^a[\\s\\S]*?$"
|
|
}
|
|
})
|
|
assertJsonSchemaDocument(schema.annotate({ description: "a" }), {
|
|
schema: {
|
|
"type": "string",
|
|
"pattern": "^a[\\s\\S]*?$",
|
|
"description": "a"
|
|
}
|
|
})
|
|
})
|
|
|
|
describe("Struct", () => {
|
|
it("empty struct", () => {
|
|
const schema = Schema.Struct({})
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{ "type": "object" },
|
|
{ "type": "array" }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "object"
|
|
},
|
|
{
|
|
"type": "array"
|
|
}
|
|
],
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
describe("required property", () => {
|
|
it("String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.String
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.String.annotate({ description: "a" })
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string",
|
|
"description": "a"
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotateKey", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.String.annotateKey({ description: "a-key" })
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string",
|
|
"allOf": [{
|
|
"description": "a-key"
|
|
}]
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate & annotateKey", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.String.annotate({ description: "a" }).annotateKey({ description: "a-key" })
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string",
|
|
"description": "a",
|
|
"allOf": [{
|
|
"description": "a-key"
|
|
}]
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("optionalKey", () => {
|
|
it("String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.optionalKey(Schema.String)
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": { "type": "string" }
|
|
},
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.optionalKey(Schema.String.annotate({ description: "a" })),
|
|
b: Schema.optionalKey(Schema.String).annotate({ description: "b" })
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string",
|
|
"description": "a"
|
|
},
|
|
"b": {
|
|
"type": "string",
|
|
"description": "b"
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotateKey", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.optionalKey(Schema.String.annotateKey({ description: "a-key" })),
|
|
b: Schema.optionalKey(Schema.String).annotateKey({ description: "b-key" })
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string",
|
|
"allOf": [{
|
|
"description": "a-key"
|
|
}]
|
|
},
|
|
"b": {
|
|
"type": "string",
|
|
"allOf": [{
|
|
"description": "b-key"
|
|
}]
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate & annotateKey", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.optionalKey(Schema.String.annotate({ description: "a" }).annotateKey({ description: "a-key" })),
|
|
b: Schema.optionalKey(Schema.String).annotate({ description: "b" }).annotateKey({ description: "b-key" }),
|
|
c: Schema.optionalKey(Schema.String.annotate({ description: "a" }).annotateKey({ description: "a-key" }))
|
|
.annotate({ description: "c-outer" }).annotateKey({ description: "c-outer-key" })
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string",
|
|
"description": "a",
|
|
"allOf": [{
|
|
"description": "a-key"
|
|
}]
|
|
},
|
|
"b": {
|
|
"type": "string",
|
|
"description": "b",
|
|
"allOf": [{
|
|
"description": "b-key"
|
|
}]
|
|
},
|
|
"c": {
|
|
"type": "string",
|
|
"description": "c-outer",
|
|
"allOf": [{
|
|
"description": "c-outer-key"
|
|
}]
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("optionalKey(String) to String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.optionalKey(Schema.String).pipe(Schema.encodeTo(Schema.String, {
|
|
decode: SchemaGetter.passthrough(),
|
|
encode: SchemaGetter.withDefault(Effect.succeed(""))
|
|
}))
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("optional", () => {
|
|
it("String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.optional(Schema.String)
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"anyOf": [
|
|
{ "type": "string" },
|
|
{ "type": "null" }
|
|
]
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.optional(Schema.String.annotate({ description: "a" })),
|
|
b: Schema.optional(Schema.String).annotate({ description: "b" })
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"anyOf": [
|
|
{ "type": "string", "description": "a" },
|
|
{ "type": "null" }
|
|
]
|
|
},
|
|
"b": {
|
|
"anyOf": [
|
|
{ "type": "string" },
|
|
{ "type": "null" }
|
|
],
|
|
"description": "b"
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotateKey", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.optional(Schema.String).annotateKey({ description: "a-key" }),
|
|
b: Schema.optional(Schema.String.annotate({ description: "b" })).annotateKey({ description: "b-key" })
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"anyOf": [
|
|
{ "type": "string" },
|
|
{ "type": "null" }
|
|
],
|
|
"allOf": [{
|
|
"description": "a-key"
|
|
}]
|
|
},
|
|
"b": {
|
|
"anyOf": [
|
|
{ "type": "string", "description": "b" },
|
|
{ "type": "null" }
|
|
],
|
|
"allOf": [{
|
|
"description": "b-key"
|
|
}]
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("optional(String) to String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.optional(Schema.String).pipe(Schema.encodeTo(Schema.String, {
|
|
decode: SchemaGetter.passthrough(),
|
|
encode: SchemaGetter.withDefault(Effect.succeed(""))
|
|
}))
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("UndefinedOr", () => {
|
|
it("String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.UndefinedOr(Schema.String)
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"anyOf": [
|
|
{ "type": "string" },
|
|
{ "type": "null" }
|
|
]
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.UndefinedOr(Schema.String.annotate({ description: "a" })),
|
|
b: Schema.UndefinedOr(Schema.String).annotate({ description: "b" })
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"anyOf": [
|
|
{ "type": "string", "description": "a" },
|
|
{ "type": "null" }
|
|
]
|
|
},
|
|
"b": {
|
|
"anyOf": [
|
|
{ "type": "string" },
|
|
{ "type": "null" }
|
|
],
|
|
"description": "b"
|
|
}
|
|
},
|
|
"required": ["a", "b"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotateKey", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.UndefinedOr(Schema.String).annotateKey({ description: "a-key" }),
|
|
b: Schema.UndefinedOr(Schema.String.annotate({ description: "b" })).annotateKey({ description: "b-key" })
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"anyOf": [
|
|
{ "type": "string" },
|
|
{ "type": "null" }
|
|
],
|
|
"allOf": [{
|
|
"description": "a-key"
|
|
}]
|
|
},
|
|
"b": {
|
|
"anyOf": [
|
|
{ "type": "string", "description": "b" },
|
|
{ "type": "null" }
|
|
],
|
|
"allOf": [{
|
|
"description": "b-key"
|
|
}]
|
|
}
|
|
},
|
|
"required": ["a", "b"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("UndefinedOr(String) to String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Struct({
|
|
a: Schema.UndefinedOr(Schema.String).pipe(Schema.encodeTo(Schema.String, {
|
|
decode: SchemaGetter.passthrough(),
|
|
encode: SchemaGetter.transform((s) => s ?? "")
|
|
}))
|
|
}),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe("Record", () => {
|
|
it("Record(String, Never)", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Record(Schema.String, Schema.Never),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.Record(Schema.String, Schema.Never.annotate({ description: "a" })),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"description": "a",
|
|
"not": {}
|
|
}
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Record(String, Finite)", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Record(Schema.String, Schema.Finite),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.Record(
|
|
Schema.String.annotate({ description: "k" }), // TODO: where can we attach the description?
|
|
Schema.Finite.annotate({ description: "v" })
|
|
).annotate({ description: "r" }),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "number",
|
|
"allOf": [{
|
|
"description": "v"
|
|
}]
|
|
},
|
|
"description": "r"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Record(String, Json)", () => {
|
|
const schema = Schema.Record(Schema.String, Schema.Json)
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: { "type": "object" }
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Record(`a${string}`, Number) & annotate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Record(Schema.TemplateLiteral(["a", Schema.String]), Schema.Finite),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"patternProperties": {
|
|
"^a[\\s\\S]*?$": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Record(Literals(['a', 'b']), Finite)", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Record(Schema.Literals(["a", "b"]), Schema.Finite),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": { "type": "number" },
|
|
"b": { "type": "number" }
|
|
},
|
|
"required": ["a", "b"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("Record(isUppercased, Number)", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Record(Schema.String.check(Schema.isUppercased()), Schema.Finite),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"patternProperties": {
|
|
"^[^a-z]*$": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
describe("checks", () => {
|
|
it("isMinProperties", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Record(Schema.String, Schema.Finite).check(Schema.isMinProperties(2)),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "number"
|
|
},
|
|
"allOf": [
|
|
{ "minProperties": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isMaxProperties", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Record(Schema.String, Schema.Finite).check(Schema.isMaxProperties(2)),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"additionalProperties": { "type": "number" },
|
|
"allOf": [{ "maxProperties": 2 }]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isPropertiesLengthBetween", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Record(Schema.String, Schema.Finite).check(Schema.isPropertiesLengthBetween(2, 2)),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"additionalProperties": { "type": "number" },
|
|
"allOf": [{ "minProperties": 2, "maxProperties": 2 }]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
})
|
|
|
|
it("StructWithRest", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.StructWithRest(Schema.Struct({ a: Schema.String }), [
|
|
Schema.Record(Schema.String, Schema.Union([Schema.Finite, Schema.String]))
|
|
]),
|
|
{
|
|
schema: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": { "type": "string" }
|
|
},
|
|
"additionalProperties": {
|
|
"anyOf": [
|
|
{ "type": "number" },
|
|
{ "type": "string" }
|
|
]
|
|
},
|
|
"required": ["a"]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
describe("Tuple", () => {
|
|
it("empty tuple", () => {
|
|
const schema = Schema.Tuple([])
|
|
assertJsonSchemaDocument(
|
|
schema,
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"items": false
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
schema.annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"items": false,
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
describe("required element", () => {
|
|
it("String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Tuple([
|
|
Schema.String
|
|
]),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [{ "type": "string" }],
|
|
"minItems": 1,
|
|
"maxItems": 1
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Tuple([
|
|
Schema.String.annotate({ description: "a" })
|
|
]),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [{ "type": "string", "description": "a" }],
|
|
"minItems": 1,
|
|
"maxItems": 1
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotateKey", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Tuple([
|
|
Schema.String.annotateKey({ description: "a-key" })
|
|
]),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [{ "type": "string", "allOf": [{ "description": "a-key" }] }],
|
|
"minItems": 1,
|
|
"maxItems": 1
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate & annotateKey", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Tuple([
|
|
Schema.String.annotate({ description: "a" }).annotateKey({ description: "a-key" })
|
|
]),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [{ "type": "string", "description": "a", "allOf": [{ "description": "a-key" }] }],
|
|
"minItems": 1,
|
|
"maxItems": 1
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("optionalKey", () => {
|
|
it("String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Tuple([
|
|
Schema.optionalKey(Schema.String)
|
|
]),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [
|
|
{ "type": "string" }
|
|
],
|
|
"maxItems": 1
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Tuple([
|
|
Schema.optionalKey(Schema.String.annotate({ description: "a" })),
|
|
Schema.optionalKey(Schema.String).annotate({ description: "b" })
|
|
]),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [
|
|
{ "type": "string", "description": "a" },
|
|
{ "type": "string", "description": "b" }
|
|
],
|
|
"maxItems": 2
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotateKey", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Tuple([
|
|
Schema.optionalKey(Schema.String.annotateKey({ description: "a-key" })),
|
|
Schema.optionalKey(Schema.String).annotateKey({ description: "b-key" })
|
|
]),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [
|
|
{ "type": "string", "allOf": [{ "description": "a-key" }] },
|
|
{
|
|
"type": "string",
|
|
"allOf": [{ "description": "b-key" }]
|
|
}
|
|
],
|
|
"maxItems": 2
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String & annotate & annotateKey", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Tuple([
|
|
Schema.optionalKey(Schema.String.annotate({ description: "a" }).annotateKey({ description: "a-key" })),
|
|
Schema.optionalKey(Schema.String).annotate({ description: "b" }).annotateKey({ description: "b-key" }),
|
|
Schema.optionalKey(Schema.String.annotate({ description: "a" }).annotateKey({ description: "a-key" }))
|
|
.annotate({ description: "c-outer" }).annotateKey({ description: "c-outer-key" })
|
|
]),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [
|
|
{ "type": "string", "description": "a", "allOf": [{ "description": "a-key" }] },
|
|
{
|
|
"type": "string",
|
|
"description": "b",
|
|
"allOf": [{ "description": "b-key" }]
|
|
},
|
|
{ "type": "string", "description": "c-outer", "allOf": [{ "description": "c-outer-key" }] }
|
|
],
|
|
"maxItems": 3
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("optionalKey(String) to String", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Tuple([
|
|
Schema.optionalKey(Schema.String).pipe(Schema.encodeTo(Schema.String, {
|
|
decode: SchemaGetter.passthrough(),
|
|
encode: SchemaGetter.withDefault(Effect.succeed(""))
|
|
}))
|
|
]),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [{ "type": "string" }],
|
|
"minItems": 1,
|
|
"maxItems": 1
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
it("optionalKey to required key", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Tuple([
|
|
Schema.optionalKey(Schema.String).pipe(Schema.encodeTo(Schema.String, {
|
|
decode: SchemaGetter.passthrough(),
|
|
encode: SchemaGetter.withDefault(Effect.succeed(""))
|
|
}))
|
|
]),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [
|
|
{ "type": "string" }
|
|
],
|
|
"minItems": 1,
|
|
"maxItems": 1
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("Array", () => {
|
|
it("Array(String)", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Array(Schema.String),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"items": { "type": "string" }
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.Array(Schema.String).annotate({ description: "a" }),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"description": "a"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
describe("checks", () => {
|
|
it("isMinLength", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Array(Schema.String).check(Schema.isMinLength(2)),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"allOf": [
|
|
{ "minItems": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isMaxLength", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Array(Schema.String).check(Schema.isMaxLength(2)),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"allOf": [
|
|
{ "maxItems": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("isLengthBetween", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Array(Schema.String).check(Schema.isLengthBetween(2, 2)),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"allOf": [
|
|
{ "minItems": 2 },
|
|
{ "maxItems": 2 }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("UniqueArray", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.UniqueArray(Schema.String),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"allOf": [
|
|
{ "uniqueItems": true }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
})
|
|
|
|
it("TupleWithRest", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.TupleWithRest(Schema.Tuple([Schema.String]), [Schema.Finite]),
|
|
{
|
|
schema: {
|
|
"type": "array",
|
|
"prefixItems": [
|
|
{ "type": "string" }
|
|
],
|
|
"items": { "type": "number" },
|
|
"minItems": 1
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
describe("Union", () => {
|
|
it("empty union", () => {
|
|
const schema = Schema.Union([])
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"not": {}
|
|
}
|
|
})
|
|
assertJsonSchemaDocument(Schema.Union([]).annotate({ description: "a" }), {
|
|
schema: {
|
|
"not": {},
|
|
"description": "a"
|
|
}
|
|
})
|
|
})
|
|
|
|
it("single member", () => {
|
|
const schema = Schema.Union([Schema.String])
|
|
assertJsonSchemaDocument(schema, {
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
}
|
|
]
|
|
}
|
|
})
|
|
assertJsonSchemaDocument(Schema.Union([Schema.String]).annotate({ description: "a" }), {
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
}
|
|
],
|
|
"description": "a"
|
|
}
|
|
})
|
|
assertJsonSchemaDocument(
|
|
Schema.Union([Schema.String.annotate({ description: "inner" })]).annotate({ description: "outer" }),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "string",
|
|
"description": "inner"
|
|
}
|
|
],
|
|
"description": "outer"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String | Number", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Union([
|
|
Schema.String,
|
|
Schema.Finite
|
|
]),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{ "type": "string" },
|
|
{ "type": "number" }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.Union([
|
|
Schema.String,
|
|
Schema.Finite
|
|
]).annotate({ description: "description" }),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{ "type": "string" },
|
|
{ "type": "number" }
|
|
],
|
|
"description": "description"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("String | BigInt", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.Union([
|
|
Schema.String,
|
|
Schema.BigInt
|
|
]),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{
|
|
"type": "string",
|
|
"allOf": [
|
|
{ "pattern": "^-?\\d+$" }
|
|
]
|
|
},
|
|
{ "type": "string" }
|
|
]
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Schema.Union([
|
|
Schema.String,
|
|
Schema.Finite
|
|
]).annotate({ description: "description" }),
|
|
{
|
|
schema: {
|
|
"anyOf": [
|
|
{ "type": "string" },
|
|
{ "type": "number" }
|
|
],
|
|
"description": "description"
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
it("mutually recursive schemas", () => {
|
|
interface Expression {
|
|
readonly type: "expression"
|
|
readonly value: number | Operation
|
|
}
|
|
|
|
interface Operation {
|
|
readonly type: "operation"
|
|
readonly operator: "+" | "-"
|
|
readonly left: Expression
|
|
readonly right: Expression
|
|
}
|
|
|
|
const Expression = Schema.Struct({
|
|
type: Schema.Literal("expression"),
|
|
value: Schema.Union([Schema.Finite, Schema.suspend((): Schema.Codec<Operation> => Operation)])
|
|
}).annotate({ identifier: "Expression" })
|
|
|
|
const Operation = Schema.Struct({
|
|
type: Schema.Literal("operation"),
|
|
operator: Schema.Literals(["+", "-"]),
|
|
left: Expression,
|
|
right: Expression
|
|
}).annotate({ identifier: "Operation" })
|
|
|
|
assertJsonSchemaDocument(
|
|
Operation,
|
|
{
|
|
schema: {
|
|
"$ref": "#/$defs/Operation"
|
|
},
|
|
definitions: {
|
|
Operation: {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"operation"
|
|
]
|
|
},
|
|
"operator": {
|
|
"type": "string",
|
|
"enum": [
|
|
"+",
|
|
"-"
|
|
]
|
|
},
|
|
"left": {
|
|
"$ref": "#/$defs/Expression"
|
|
},
|
|
"right": {
|
|
"$ref": "#/$defs/Expression"
|
|
}
|
|
},
|
|
"required": [
|
|
"type",
|
|
"operator",
|
|
"left",
|
|
"right"
|
|
],
|
|
"additionalProperties": false
|
|
},
|
|
Expression: {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"expression"
|
|
]
|
|
},
|
|
"value": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"$ref": "#/$defs/Operation"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"required": [
|
|
"type",
|
|
"value"
|
|
],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
}
|
|
)
|
|
assertJsonSchemaDocument(
|
|
Expression,
|
|
{
|
|
schema: {
|
|
"$ref": "#/$defs/Expression"
|
|
},
|
|
definitions: {
|
|
Operation: {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"operation"
|
|
]
|
|
},
|
|
"operator": {
|
|
"type": "string",
|
|
"enum": [
|
|
"+",
|
|
"-"
|
|
]
|
|
},
|
|
"left": {
|
|
"$ref": "#/$defs/Expression"
|
|
},
|
|
"right": {
|
|
"$ref": "#/$defs/Expression"
|
|
}
|
|
},
|
|
"required": [
|
|
"type",
|
|
"operator",
|
|
"left",
|
|
"right"
|
|
],
|
|
"additionalProperties": false
|
|
},
|
|
Expression: {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"expression"
|
|
]
|
|
},
|
|
"value": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"$ref": "#/$defs/Operation"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"required": [
|
|
"type",
|
|
"value"
|
|
],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
describe("fromJsonString", () => {
|
|
it("top level fromJsonString", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.fromJsonString(Schema.FiniteFromString),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"contentMediaType": "application/json",
|
|
"contentSchema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("preserves the content schema identifier", () => {
|
|
const MyEvent = Schema.Struct({
|
|
value: Schema.String
|
|
}).annotate({ identifier: "MyEvent" })
|
|
|
|
assertJsonSchemaDocument(
|
|
Schema.fromJsonString(MyEvent),
|
|
{
|
|
schema: {
|
|
"$ref": "#/$defs/MyEventJsonString"
|
|
},
|
|
definitions: {
|
|
"MyEvent": {
|
|
"type": "object",
|
|
"properties": {
|
|
"value": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"value"
|
|
],
|
|
"additionalProperties": false
|
|
},
|
|
"MyEventJsonString": {
|
|
"type": "string",
|
|
"contentMediaType": "application/json",
|
|
"contentSchema": {
|
|
"$ref": "#/$defs/MyEvent"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("respects an explicit encoded-side identifier", () => {
|
|
const MyEvent = Schema.Struct({
|
|
value: Schema.String
|
|
}).annotate({ identifier: "MyEvent" })
|
|
const MyWireEvent = Schema.flip(
|
|
Schema.flip(Schema.fromJsonString(MyEvent)).annotate({ identifier: "MyWireEvent" })
|
|
)
|
|
|
|
assertJsonSchemaDocument(
|
|
MyWireEvent,
|
|
{
|
|
schema: {
|
|
"$ref": "#/$defs/MyWireEvent"
|
|
},
|
|
definitions: {
|
|
"MyEvent": {
|
|
"type": "object",
|
|
"properties": {
|
|
"value": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"value"
|
|
],
|
|
"additionalProperties": false
|
|
},
|
|
"MyWireEvent": {
|
|
"type": "string",
|
|
"contentMediaType": "application/json",
|
|
"contentSchema": {
|
|
"$ref": "#/$defs/MyEvent"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("nested fromJsonString", () => {
|
|
assertJsonSchemaDocument(
|
|
Schema.fromJsonString(Schema.Struct({
|
|
a: Schema.fromJsonString(Schema.FiniteFromString)
|
|
})),
|
|
{
|
|
schema: {
|
|
"type": "string",
|
|
"contentMediaType": "application/json",
|
|
"contentSchema": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"a": {
|
|
"contentMediaType": "application/json",
|
|
"contentSchema": {
|
|
"type": "string"
|
|
},
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"a"
|
|
],
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
)
|
|
})
|
|
})
|
|
|
|
it("Class", () => {
|
|
class A extends Schema.Class<A>("A")({
|
|
a: Schema.String
|
|
}) {}
|
|
assertJsonSchemaDocument(
|
|
A,
|
|
{
|
|
schema: {
|
|
"$ref": "#/$defs/A"
|
|
},
|
|
definitions: {
|
|
A: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": { "type": "string" }
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
it("ErrorClass", () => {
|
|
class E extends Schema.ErrorClass<E>("E")({
|
|
a: Schema.String
|
|
}) {}
|
|
assertJsonSchemaDocument(E, {
|
|
schema: {
|
|
"$ref": "#/$defs/E"
|
|
},
|
|
definitions: {
|
|
E: {
|
|
"type": "object",
|
|
"properties": {
|
|
"a": { "type": "string" }
|
|
},
|
|
"required": ["a"],
|
|
"additionalProperties": false
|
|
}
|
|
}
|
|
})
|
|
})
|
|
})
|