From 708205944e17f097fc5dfee7fbd0007f1509f48c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20de=20=C3=81vila=20Martins?= Date: Wed, 22 Jan 2025 14:49:05 -0300 Subject: [PATCH] refactor required (#252) * refactor required * fixes * refactor required * refactor * avoid unecessary funcs * better regex * handle const * codec * tpl * arr * obj * str fmt * all, any * consts * all call extra * arr like * more * clippy * clippy --- .prettierignore | 1 - .../bug-rust-repro/src/generated/parser.d.ts | 2 +- .../bug-rust-repro/src/generated/parser.js | 27 +- .../src/generated/validators.js | 433 +++--- e2e-tests/standalone-parser/CHANGELOG.md | 8 + e2e-tests/standalone-parser/package.json | 2 +- .../src/generated/parser.d.ts | 2 +- .../standalone-parser/src/generated/parser.js | 207 ++- .../src/generated/schema.d.ts | 2 +- .../standalone-parser/src/generated/schema.js | 7 +- .../src/generated/validators.js | 1193 +++++++++-------- e2e-tests/standalone-parser/src/parser.ts | 8 + .../standalone-parser/tests/parser.test.ts | 104 +- packages/beff-cli/CHANGELOG.md | 6 + packages/beff-cli/package.json | 2 +- packages/beff-client/CHANGELOG.md | 8 + packages/beff-client/package.json | 4 +- packages/beff-core/src/print/decoder.rs | 464 +++---- packages/beff-core/src/print/printer.rs | 24 +- ...parser__tests__ok_discriminated_union.snap | 48 +- .../beff-wasm/bundled-code/build-parsers.js | 21 +- .../beff-wasm/bundled-code/build-schema.js | 6 +- packages/beff-wasm/bundled-code/decoders.js | 428 +++--- packages/beff-wasm/bundled-code/parser.d.ts | 2 +- packages/beff-wasm/bundled-code/schema.d.ts | 2 +- .../export-decoder/bff-generated/parser.d.ts | 2 +- .../export-decoder/bff-generated/parser.js | 59 +- .../bff-generated/validators.js | 501 +++---- packages/beff-wasm/package.json | 2 +- packages/beff-wasm/ts-node/bundle-to-disk.ts | 19 +- pnpm-lock.yaml | 4 +- 31 files changed, 1862 insertions(+), 1736 deletions(-) diff --git a/.prettierignore b/.prettierignore index 63e4b7c1..9fe466bd 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,7 +2,6 @@ *.next/ *dist/ *pkg/ -packages/beff-wasm/bundled-code/ packages/beff-cli/dist-cli/ packages/beff-wasm/dist-cli/ packages/web-docs/static/playground/assets/ diff --git a/e2e-tests/bug-rust-repro/src/generated/parser.d.ts b/e2e-tests/bug-rust-repro/src/generated/parser.d.ts index 6edf910a..f7182b08 100644 --- a/e2e-tests/bug-rust-repro/src/generated/parser.d.ts +++ b/e2e-tests/bug-rust-repro/src/generated/parser.d.ts @@ -3,7 +3,7 @@ import { BuildParserFunction } from "@beff/cli"; declare const _exports: { - buildParsers: BuildParserFunction + buildParsers: BuildParserFunction; }; export default _exports; diff --git a/e2e-tests/bug-rust-repro/src/generated/parser.js b/e2e-tests/bug-rust-repro/src/generated/parser.js index de096ffa..0a49cc03 100644 --- a/e2e-tests/bug-rust-repro/src/generated/parser.js +++ b/e2e-tests/bug-rust-repro/src/generated/parser.js @@ -4,20 +4,17 @@ import {printErrors} from '@beff/client'; import {z} from 'zod'; -import validatorsMod from "./validators.js"; const { decodeObject, decodeArray, decodeString, decodeNumber, decodeCodec, decodeFunction, decodeStringWithFormat, decodeAnyOf, decodeAllOf, decodeBoolean, decodeAny, decodeTuple, decodeNull, decodeNever, decodeConst, registerCustomFormatter, validators, c } = validatorsMod; +import validatorsMod from "./validators.js"; const { ObjectDecoder, ArrayDecoder, decodeString, decodeNumber, CodecDecoder, decodeFunction, StringWithFormatDecoder, AnyOfDecoder, AllOfDecoder, decodeBoolean, decodeAny, TupleDecoder, decodeNull, decodeNever, RegexDecoder, ConstDecoder, registerCustomFormatter, AnyOfConstsDecoder, AnyOfDiscriminatedDecoder, validators, c } = validatorsMod; const RequiredCustomFormats = ["ValidCurrency"]; const buildParsersInput = { - "A": function(ctx, input, required = true) { - return validators.A(ctx, input, required); - } + "A": validators.A }; function buildParsers(args) { - - const customFormats = args?.customFormats ?? {} + const customFormats = args?.customFormats ?? {}; for (const k of RequiredCustomFormats) { if (customFormats[k] == null) { @@ -31,7 +28,6 @@ function buildParsers(args) { registerCustomFormatter(k, v); }); - let decoders = {}; Object.keys(buildParsersInput).forEach((k) => { @@ -57,16 +53,19 @@ function buildParsers(args) { const error = new Error(`Failed to parse ${k}`); error.errors = safe.errors; - throw error + throw error; }; const zod = () => { - return z.custom(data => safeParse(data).success, val => { - const errors = safeParse(val).errors; - - return printErrors(errors, []) - }) - } + return z.custom( + (data) => safeParse(data).success, + (val) => { + const errors = safeParse(val).errors; + + return printErrors(errors, []); + } + ); + }; decoders[k] = { parse, safeParse, diff --git a/e2e-tests/bug-rust-repro/src/generated/validators.js b/e2e-tests/bug-rust-repro/src/generated/validators.js index 12be8de7..2a58202a 100644 --- a/e2e-tests/bug-rust-repro/src/generated/validators.js +++ b/e2e-tests/bug-rust-repro/src/generated/validators.js @@ -4,7 +4,7 @@ -const customFormatters = {} +const customFormatters = {}; function registerCustomFormatter(name, validator) { customFormatters[name] = validator; @@ -45,70 +45,71 @@ function buildUnionError(received, ctx, errors) { }); } -function decodeObject(ctx, input, required, data, additionalPropsValidator = null) { - if (!required && input == null) { - return input; +class ObjectDecoder { + constructor(data, additionalPropsValidator = null) { + this.data = data; + this.additionalPropsValidator = additionalPropsValidator; } - const disallowExtraProperties = ctx?.disallowExtraProperties ?? false; + decode(ctx, input) { + const disallowExtraProperties = ctx?.disallowExtraProperties ?? false; - const allowedExtraProperties = ctx.allowedExtraProperties__ ?? [] + const allowedExtraProperties = ctx.allowedExtraProperties__ ?? []; - if (typeof input === "object" && !Array.isArray(input) && input !== null) { - const acc = {}; - for (const [k, v] of Object.entries(data)) { - pushPath(ctx, k); - acc[k] = v(ctx, input[k]); - popPath(ctx); - } + if (typeof input === "object" && !Array.isArray(input) && input !== null) { + const acc = {}; + for (const [k, v] of Object.entries(this.data)) { + pushPath(ctx, k); + acc[k] = v(ctx, input[k]); + popPath(ctx); + } - if (additionalPropsValidator != null) { - for (const [k, v] of Object.entries(input)) { - if (acc[k] == null) { - pushPath(ctx, k); - - acc[k] = additionalPropsValidator(ctx, v); - popPath(ctx); + if (this.additionalPropsValidator != null) { + for (const [k, v] of Object.entries(input)) { + if (acc[k] == null) { + pushPath(ctx, k); + acc[k] = this.additionalPropsValidator(ctx, v); + popPath(ctx); + } } } - } - if (disallowExtraProperties) { - for (const k of Object.keys(input)) { - if (acc[k] == null && allowedExtraProperties.indexOf(k) == -1) { - pushPath(ctx, k); - buildError(input[k], ctx, "extra property"); - popPath(ctx); + if (disallowExtraProperties) { + for (const k of Object.keys(input)) { + if (acc[k] == null && allowedExtraProperties.indexOf(k) == -1) { + pushPath(ctx, k); + buildError(input[k], ctx, "extra property"); + popPath(ctx); + } } } - } - return acc; + return acc; + } + return buildError(input, ctx, "expected object"); } - return buildError(input, ctx, "expected object"); } -function decodeArray(ctx, input, required, data) { - if (!required && input == null) { - return input; +class ArrayDecoder { + constructor(data) { + this.data = data; } - if (Array.isArray(input)) { - const acc = []; - for (let i = 0; i < input.length; i++) { - const v = input[i]; - pushPath(ctx, "[" + i + "]"); - acc.push(data(ctx, v)); - popPath(ctx); + + decode(ctx, input) { + if (Array.isArray(input)) { + const acc = []; + for (let i = 0; i < input.length; i++) { + const v = input[i]; + pushPath(ctx, "[" + i + "]"); + acc.push(this.data(ctx, v)); + popPath(ctx); + } + return acc; } - return acc; + return buildError(input, ctx, "expected array"); } - return buildError(input, ctx, "expected array"); } -function decodeString(ctx, input, required) { - if (!required && input == null) { - return input; - } - +function decodeString(ctx, input) { if (typeof input === "string") { return input; } @@ -116,10 +117,7 @@ function decodeString(ctx, input, required) { return buildError(input, ctx, "expected string"); } -function decodeNumber(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeNumber(ctx, input) { if (typeof input === "number") { return input; } @@ -130,223 +128,246 @@ function decodeNumber(ctx, input, required) { return buildError(input, ctx, "expected number"); } -function decodeFunction(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeFunction(ctx, input) { if (typeof input === "function") { return input; } return buildError(input, ctx, "expected function"); } - -function decodeCodec(ctx, input, required, codec) { - if (!required && input == null) { - return input; - } - switch (codec) { - case "Codec::ISO8061": { - const d = new Date(input); - if (isNaN(d.getTime())) { - return buildError(input, ctx, "expected ISO8061 date"); - } - return d; - } - case "Codec::BigInt": { - if (typeof input === "bigint") { - return input; - } - if (typeof input === "number") { - return BigInt(input); +class CodecDecoder { + constructor(codec) { + this.codec = codec; + } + decode(ctx, input) { + switch (this.codec) { + case "Codec::ISO8061": { + const d = new Date(input); + if (isNaN(d.getTime())) { + return buildError(input, ctx, "expected ISO8061 date"); + } + return d; } - if (typeof input === "string") { - try { + case "Codec::BigInt": { + if (typeof input === "bigint") { + return input; + } + if (typeof input === "number") { return BigInt(input); - } catch (e) { - } + if (typeof input === "string") { + try { + return BigInt(input); + } catch (e) { + + } + } + return buildError(input, ctx, "expected bigint"); } - return buildError(input, ctx, "expected bigint"); } + return buildError(input, ctx, "codec " + this.codec + " not implemented"); } - return buildError(input, ctx, "codec " + codec + " not implemented"); } -function decodeStringWithFormat(ctx, input, required, format) { - if (!required && input == null) { - return input; - } - if (typeof input !== "string") { - return buildError(input, ctx, "expected string with format " + JSON.stringify(format)); +class StringWithFormatDecoder { + constructor(format) { + this.format = format; } - const validator = customFormatters[format]; + decode(ctx, input) { + if (typeof input !== "string") { + return buildError(input, ctx, "expected string with format " + JSON.stringify(this.format)); + } - if (validator == null) { - return buildError(input, ctx, "format " + JSON.stringify(format) + " not implemented"); - } + const validator = customFormatters[this.format]; - const isOk = validator(input); - if (isOk) { - return input; - } - return buildError(input, ctx, "expected string with format " + JSON.stringify(format)); -} + if (validator == null) { + return buildError(input, ctx, "format " + JSON.stringify(this.format) + " not implemented"); + } -function decodeAnyOfDiscriminated(ctx, input, required, discriminator, mapping) { - if (!required && input == null) { - return input; + const isOk = validator(input); + if (isOk) { + return input; + } + return buildError(input, ctx, "expected string with format " + JSON.stringify(this.format)); } - const d = input[discriminator]; - if (d == null) { - return buildError(input, ctx, "expected discriminator key " + JSON.stringify(discriminator)) - } - const v = mapping[d]; - if (v == null) { - pushPath(ctx, discriminator); - const err = buildError(d, ctx, "expected one of " + Object.keys(mapping).map(it => JSON.stringify(it)).join(", ")); - popPath(ctx); - return err; - } - const prevAllow = (ctx.allowedExtraProperties__ ?? []); - ctx.allowedExtraProperties__ = [...prevAllow, discriminator] - const out = v(ctx, input); - ctx.allowedExtraProperties__ = prevAllow; - return { ...out, [discriminator]: d }; } - -function decodeAnyOfConsts(ctx, input, required, consts) { - if (!required && input == null) { - return input; +class AnyOfDiscriminatedDecoder { + constructor(discriminator, mapping) { + this.discriminator = discriminator; + this.mapping = mapping; } - for (const c of consts) { - if (input === c) { - return c; + + decode(ctx, input) { + const d = input[this.discriminator]; + if (d == null) { + return buildError(input, ctx, "expected discriminator key " + JSON.stringify(this.discriminator)); + } + const v = this.mapping[d]; + if (v == null) { + pushPath(ctx, this.discriminator); + const err = buildError( + d, + ctx, + "expected one of " + + Object.keys(this.mapping) + .map((it) => JSON.stringify(it)) + .join(", ") + ); + popPath(ctx); + return err; } + const prevAllow = ctx.allowedExtraProperties__ ?? []; + ctx.allowedExtraProperties__ = [...prevAllow, this.discriminator]; + const out = v(ctx, input); + ctx.allowedExtraProperties__ = prevAllow; + return { ...out, [this.discriminator]: d }; } - return buildError(input, ctx, "expected one of " + consts.map(it => JSON.stringify(it)).join(", ")); } -function decodeAnyOf(ctx, input, required, vs) { - if (!required && input == null) { - return input; - } - let accErrors = []; - for (const v of vs) { - const validatorCtx = {}; - const newValue = v(validatorCtx, input); - if (validatorCtx.errors == null) { - return newValue; +class AnyOfConstsDecoder { + constructor(consts) { + this.consts = consts; + } + decode(ctx, input) { + for (const c of this.consts) { + if (input === c) { + return c; + } } - accErrors.push(...(validatorCtx.errors ?? [])); + return buildError( + input, + ctx, + "expected one of " + this.consts.map((it) => JSON.stringify(it)).join(", ") + ); } - return buildUnionError(input, ctx, accErrors); } -function decodeAllOf(ctx, input, required, vs) { - if (!required && input == null) { - return input; - } - let acc = {}; - let foundOneObject = false; - let allObjects = true; - for (const v of vs) { - const newValue = v(ctx, input); - const isObj = typeof newValue === "object"; - allObjects = allObjects && isObj; - if (isObj) { - foundOneObject = true; - acc = { ...acc, ...newValue }; + +class AnyOfDecoder { + constructor(vs) { + this.vs = vs; + } + decode(ctx, input) { + let accErrors = []; + for (const v of this.vs) { + const validatorCtx = {}; + const newValue = v(validatorCtx, input); + if (validatorCtx.errors == null) { + return newValue; + } + accErrors.push(...(validatorCtx.errors ?? [])); } + return buildUnionError(input, ctx, accErrors); } - if (foundOneObject && allObjects) { - return acc; - } - return input; } -function decodeTuple(ctx, input, required, vs) { - if (!required && input == null) { +class AllOfDecoder { + constructor(vs) { + this.vs = vs; + } + decode(ctx, input) { + let acc = {}; + let foundOneObject = false; + let allObjects = true; + for (const v of this.vs) { + const newValue = v(ctx, input); + const isObj = typeof newValue === "object"; + allObjects = allObjects && isObj; + if (isObj) { + foundOneObject = true; + acc = { ...acc, ...newValue }; + } + } + if (foundOneObject && allObjects) { + return acc; + } return input; } - if (Array.isArray(input)) { - const acc = []; - let idx = 0; - for (const v of vs.prefix) { - pushPath(ctx, "[" + idx + "]"); - const newValue = v(ctx, input[idx]); - popPath(ctx); - acc.push(newValue); - idx++; - } - if (vs.items != null) { - for (let i = idx; i < input.length; i++) { - const v = input[i]; - pushPath(ctx, "[" + i + "]"); - acc.push(vs.items(ctx, v)); +} +class TupleDecoder { + constructor(vs) { + this.vs = vs; + } + decode(ctx, input) { + if (Array.isArray(input)) { + const acc = []; + let idx = 0; + for (const v of this.vs.prefix) { + pushPath(ctx, "[" + idx + "]"); + const newValue = v(ctx, input[idx]); popPath(ctx); + acc.push(newValue); + idx++; } - } else { - if (input.length > idx) { - return buildError(input, ctx, "tuple has too many items"); + if (this.vs.items != null) { + for (let i = idx; i < input.length; i++) { + const v = input[i]; + pushPath(ctx, "[" + i + "]"); + acc.push(this.vs.items(ctx, v)); + popPath(ctx); + } + } else { + if (input.length > idx) { + return buildError(input, ctx, "tuple has too many items"); + } } + return acc; } - return acc; + return buildError(input, ctx, "expected tuple"); } - return buildError(input, ctx, "expected tuple"); } -function decodeBoolean(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeBoolean(ctx, input) { if (typeof input === "boolean") { return input; } return buildError(input, ctx, "expected boolean"); } -function decodeAny(ctx, input, required) { +function decodeAny(ctx, input) { return input; } -function decodeNull(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeNull(ctx, input) { if (input == null) { - return null; - } - return buildError(input, ctx, "expected null"); -} -function decodeNever(ctx, input, required) { - if (!required && input == null) { return input; } + return buildError(input, ctx, "expected nullish value"); +} +function decodeNever(ctx, input) { return buildError(input, ctx, "never"); } -function decodeConst(ctx, input, required, constValue) { - if (!required && input == null) { - return input; + +class ConstDecoder { + constructor(value) { + this.value = value; } - if (input == constValue) { - return constValue; + + decode(ctx, input) { + if (input == this.value) { + return this.value; + } + return buildError(input, ctx, "expected " + JSON.stringify(this.value)); } - return buildError(input, ctx, "expected " + JSON.stringify(constValue)); } -function decodeRegex(ctx, input, required, regex, description) { - if (!required && input == null) { - return input; +class RegexDecoder { + constructor(regex, description) { + this.regex = regex; + this.description = description; } - if (typeof input === "string") { - if (regex.test(input)) { - return input; + + decode(ctx, input) { + if (typeof input === "string") { + if (this.regex.test(input)) { + return input; + } } + return buildError(input, ctx, "expected string matching " + this.description); } - return buildError(input, ctx, "expected string matching " + description); } -function DecodeA(ctx, input, required = true) { - return decodeString(ctx, input, required); + +function DecodeA(ctx, input) { + return (decodeString)(ctx, input); } const validators = { A: DecodeA }; -export default { decodeObject, decodeArray, decodeString, decodeNumber, decodeCodec, decodeFunction, decodeStringWithFormat, decodeAnyOf, decodeAllOf, decodeBoolean, decodeAny, decodeTuple, decodeNull, decodeNever, decodeConst, registerCustomFormatter, validators }; \ No newline at end of file +export default { ObjectDecoder, ArrayDecoder, decodeString, decodeNumber, CodecDecoder, decodeFunction, StringWithFormatDecoder, AnyOfDecoder, AllOfDecoder, decodeBoolean, decodeAny, TupleDecoder, decodeNull, decodeNever, RegexDecoder, ConstDecoder, registerCustomFormatter, AnyOfConstsDecoder, AnyOfDiscriminatedDecoder, validators }; \ No newline at end of file diff --git a/e2e-tests/standalone-parser/CHANGELOG.md b/e2e-tests/standalone-parser/CHANGELOG.md index ca818f4c..5d3af8f6 100644 --- a/e2e-tests/standalone-parser/CHANGELOG.md +++ b/e2e-tests/standalone-parser/CHANGELOG.md @@ -1,5 +1,13 @@ # node-server +## 1.0.67 + +### Patch Changes + +- Updated dependencies + - @beff/cli@0.0.70 + - @beff/client@0.0.70 + ## 1.0.66 ### Patch Changes diff --git a/e2e-tests/standalone-parser/package.json b/e2e-tests/standalone-parser/package.json index 7dd0e155..9ed9bce1 100644 --- a/e2e-tests/standalone-parser/package.json +++ b/e2e-tests/standalone-parser/package.json @@ -1,6 +1,6 @@ { "name": "standalone-parser", - "version": "1.0.66", + "version": "1.0.67", "description": "", "main": "index.js", "scripts": { diff --git a/e2e-tests/standalone-parser/src/generated/parser.d.ts b/e2e-tests/standalone-parser/src/generated/parser.d.ts index 6edf910a..f7182b08 100644 --- a/e2e-tests/standalone-parser/src/generated/parser.d.ts +++ b/e2e-tests/standalone-parser/src/generated/parser.d.ts @@ -3,7 +3,7 @@ import { BuildParserFunction } from "@beff/cli"; declare const _exports: { - buildParsers: BuildParserFunction + buildParsers: BuildParserFunction; }; export default _exports; diff --git a/e2e-tests/standalone-parser/src/generated/parser.js b/e2e-tests/standalone-parser/src/generated/parser.js index 256cba47..08d4a5c2 100644 --- a/e2e-tests/standalone-parser/src/generated/parser.js +++ b/e2e-tests/standalone-parser/src/generated/parser.js @@ -4,137 +4,80 @@ import {printErrors} from '@beff/client'; import {z} from 'zod'; -import validatorsMod from "./validators.js"; const { decodeObject, decodeArray, decodeString, decodeNumber, decodeCodec, decodeFunction, decodeStringWithFormat, decodeAnyOf, decodeAllOf, decodeBoolean, decodeAny, decodeTuple, decodeNull, decodeNever, decodeConst, registerCustomFormatter, validators, c } = validatorsMod; +import validatorsMod from "./validators.js"; const { ObjectDecoder, ArrayDecoder, decodeString, decodeNumber, CodecDecoder, decodeFunction, StringWithFormatDecoder, AnyOfDecoder, AllOfDecoder, decodeBoolean, decodeAny, TupleDecoder, decodeNull, decodeNever, RegexDecoder, ConstDecoder, registerCustomFormatter, AnyOfConstsDecoder, AnyOfDiscriminatedDecoder, validators, c } = validatorsMod; const RequiredCustomFormats = ["ValidCurrency"]; +const hoisted_BigIntCodec_0 = new CodecDecoder("Codec::BigInt"); +const hoisted_TupleCodec_1 = new TupleDecoder({ + prefix: [ + decodeNumber, + decodeNumber, + decodeNumber + ], + items: null +}); +const hoisted_TupleCodecRest_2 = new TupleDecoder({ + prefix: [ + decodeNumber, + decodeNumber + ], + items: decodeString +}); +const hoisted_StringArrCodec_3 = new ArrayDecoder(decodeString); +const hoisted_ImportEnumTypeof_4 = new ConstDecoder("a"); +const hoisted_ImportEnumTypeof_5 = new ObjectDecoder({ + "A": hoisted_ImportEnumTypeof_4.decode.bind(hoisted_ImportEnumTypeof_4) +}); const buildParsersInput = { - "AObject": function(ctx, input, required = true) { - return validators.AObject(ctx, input, required); - }, - "AccessLevel": function(ctx, input, required = true) { - return validators.AccessLevel(ctx, input, required); - }, - "AccessLevelCodec": function(ctx, input, required = true) { - return validators.AccessLevel(ctx, input, required); - }, - "AccessLevelTpl": function(ctx, input, required = true) { - return validators.AccessLevelTpl(ctx, input, required); - }, - "AccessLevelTpl2": function(ctx, input, required = true) { - return validators.AccessLevelTpl2(ctx, input, required); - }, - "AllTs": function(ctx, input, required = true) { - return validators.AllTs(ctx, input, required); - }, - "AllTypes": function(ctx, input, required = true) { - return validators.AllTypes(ctx, input, required); - }, - "Arr2C": function(ctx, input, required = true) { - return validators.Arr2(ctx, input, required); - }, - "Arr3": function(ctx, input, required = true) { - return validators.Arr3(ctx, input, required); - }, - "AvatarSize": function(ctx, input, required = true) { - return validators.AvatarSize(ctx, input, required); - }, - "BObject": function(ctx, input, required = true) { - return validators.BObject(ctx, input, required); - }, - "DiscriminatedUnion": function(ctx, input, required = true) { - return validators.DiscriminatedUnion(ctx, input, required); - }, - "DiscriminatedUnion2": function(ctx, input, required = true) { - return validators.DiscriminatedUnion2(ctx, input, required); - }, - "DiscriminatedUnion3": function(ctx, input, required = true) { - return validators.DiscriminatedUnion3(ctx, input, required); - }, - "DiscriminatedUnion4": function(ctx, input, required = true) { - return validators.DiscriminatedUnion4(ctx, input, required); - }, - "Extra": function(ctx, input, required = true) { - return validators.Extra(ctx, input, required); - }, - "ImportEnumTypeof": function(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_ImportEnumTypeof_0); - }, - "K": function(ctx, input, required = true) { - return validators.K(ctx, input, required); - }, - "KABC": function(ctx, input, required = true) { - return validators.KABC(ctx, input, required); - }, - "KDEF": function(ctx, input, required = true) { - return validators.KDEF(ctx, input, required); - }, - "LevelAndDSettings": function(ctx, input, required = true) { - return validators.LevelAndDSettings(ctx, input, required); - }, - "Mapped": function(ctx, input, required = true) { - return validators.Mapped(ctx, input, required); - }, - "MappedOptional": function(ctx, input, required = true) { - return validators.MappedOptional(ctx, input, required); - }, - "OmitSettings": function(ctx, input, required = true) { - return validators.OmitSettings(ctx, input, required); - }, - "OtherEnum": function(ctx, input, required = true) { - return validators.OtherEnum(ctx, input, required); - }, - "PartialObject": function(ctx, input, required = true) { - return validators.PartialObject(ctx, input, required); - }, - "PartialSettings": function(ctx, input, required = true) { - return validators.PartialSettings(ctx, input, required); - }, - "PublicUser": function(ctx, input, required = true) { - return validators.PublicUser(ctx, input, required); - }, - "Repro1": function(ctx, input, required = true) { - return validators.Repro1(ctx, input, required); - }, - "Req": function(ctx, input, required = true) { - return validators.Req(ctx, input, required); - }, - "RequiredPartialObject": function(ctx, input, required = true) { - return validators.RequiredPartialObject(ctx, input, required); - }, - "SettingsUpdate": function(ctx, input, required = true) { - return validators.SettingsUpdate(ctx, input, required); - }, - "T3": function(ctx, input, required = true) { - return validators.T3(ctx, input, required); - }, - "TransportedValue": function(ctx, input, required = true) { - return validators.TransportedValue(ctx, input, required); - }, - "UnionWithEnumAccess": function(ctx, input, required = true) { - return validators.UnionWithEnumAccess(ctx, input, required); - }, - "User": function(ctx, input, required = true) { - return validators.User(ctx, input, required); - }, - "ValidCurrency": function(ctx, input, required = true) { - return validators.ValidCurrency(ctx, input, required); - }, - "Version": function(ctx, input, required = true) { - return validators.Version(ctx, input, required); - }, - "Version2": function(ctx, input, required = true) { - return validators.Version2(ctx, input, required); - } -}; -const hoisted_ImportEnumTypeof_0 = { - "A": (ctx, input)=>(decodeConst(ctx, input, true, "a")) + "AObject": validators.AObject, + "AccessLevel": validators.AccessLevel, + "AccessLevelCodec": validators.AccessLevel, + "AccessLevelTpl": validators.AccessLevelTpl, + "AccessLevelTpl2": validators.AccessLevelTpl2, + "AllTs": validators.AllTs, + "AllTypes": validators.AllTypes, + "Arr2C": validators.Arr2, + "Arr3": validators.Arr3, + "AvatarSize": validators.AvatarSize, + "BObject": validators.BObject, + "BigIntCodec": hoisted_BigIntCodec_0.decode.bind(hoisted_BigIntCodec_0), + "DiscriminatedUnion": validators.DiscriminatedUnion, + "DiscriminatedUnion2": validators.DiscriminatedUnion2, + "DiscriminatedUnion3": validators.DiscriminatedUnion3, + "DiscriminatedUnion4": validators.DiscriminatedUnion4, + "Extra": validators.Extra, + "ImportEnumTypeof": hoisted_ImportEnumTypeof_5.decode.bind(hoisted_ImportEnumTypeof_5), + "K": validators.K, + "KABC": validators.KABC, + "KDEF": validators.KDEF, + "LevelAndDSettings": validators.LevelAndDSettings, + "Mapped": validators.Mapped, + "MappedOptional": validators.MappedOptional, + "OmitSettings": validators.OmitSettings, + "OtherEnum": validators.OtherEnum, + "PartialObject": validators.PartialObject, + "PartialSettings": validators.PartialSettings, + "PublicUser": validators.PublicUser, + "Repro1": validators.Repro1, + "Req": validators.Req, + "RequiredPartialObject": validators.RequiredPartialObject, + "SettingsUpdate": validators.SettingsUpdate, + "StringArrCodec": hoisted_StringArrCodec_3.decode.bind(hoisted_StringArrCodec_3), + "T3": validators.T3, + "TransportedValue": validators.TransportedValue, + "TupleCodec": hoisted_TupleCodec_1.decode.bind(hoisted_TupleCodec_1), + "TupleCodecRest": hoisted_TupleCodecRest_2.decode.bind(hoisted_TupleCodecRest_2), + "UnionWithEnumAccess": validators.UnionWithEnumAccess, + "User": validators.User, + "ValidCurrency": validators.ValidCurrency, + "Version": validators.Version, + "Version2": validators.Version2 }; function buildParsers(args) { - - const customFormats = args?.customFormats ?? {} + const customFormats = args?.customFormats ?? {}; for (const k of RequiredCustomFormats) { if (customFormats[k] == null) { @@ -148,7 +91,6 @@ function buildParsers(args) { registerCustomFormatter(k, v); }); - let decoders = {}; Object.keys(buildParsersInput).forEach((k) => { @@ -174,16 +116,19 @@ function buildParsers(args) { const error = new Error(`Failed to parse ${k}`); error.errors = safe.errors; - throw error + throw error; }; const zod = () => { - return z.custom(data => safeParse(data).success, val => { - const errors = safeParse(val).errors; - - return printErrors(errors, []) - }) - } + return z.custom( + (data) => safeParse(data).success, + (val) => { + const errors = safeParse(val).errors; + + return printErrors(errors, []); + } + ); + }; decoders[k] = { parse, safeParse, diff --git a/e2e-tests/standalone-parser/src/generated/schema.d.ts b/e2e-tests/standalone-parser/src/generated/schema.d.ts index 4d7b705f..6b3cc37e 100644 --- a/e2e-tests/standalone-parser/src/generated/schema.d.ts +++ b/e2e-tests/standalone-parser/src/generated/schema.d.ts @@ -3,7 +3,7 @@ import { BuildSchemaFunction } from "@beff/cli"; declare const _exports: { - buildSchemas: BuildSchemaFunction + buildSchemas: BuildSchemaFunction; }; export default _exports; diff --git a/e2e-tests/standalone-parser/src/generated/schema.js b/e2e-tests/standalone-parser/src/generated/schema.js index b9a3b350..910a77f0 100644 --- a/e2e-tests/standalone-parser/src/generated/schema.js +++ b/e2e-tests/standalone-parser/src/generated/schema.js @@ -43,6 +43,7 @@ const jsonSchema = { function buildSchemas() { - - return jsonSchema -}export default {buildSchemas}; \ No newline at end of file + + return jsonSchema; +} +export default {buildSchemas}; \ No newline at end of file diff --git a/e2e-tests/standalone-parser/src/generated/validators.js b/e2e-tests/standalone-parser/src/generated/validators.js index aafc8bcb..c426aa7f 100644 --- a/e2e-tests/standalone-parser/src/generated/validators.js +++ b/e2e-tests/standalone-parser/src/generated/validators.js @@ -4,7 +4,7 @@ -const customFormatters = {} +const customFormatters = {}; function registerCustomFormatter(name, validator) { customFormatters[name] = validator; @@ -45,70 +45,71 @@ function buildUnionError(received, ctx, errors) { }); } -function decodeObject(ctx, input, required, data, additionalPropsValidator = null) { - if (!required && input == null) { - return input; +class ObjectDecoder { + constructor(data, additionalPropsValidator = null) { + this.data = data; + this.additionalPropsValidator = additionalPropsValidator; } - const disallowExtraProperties = ctx?.disallowExtraProperties ?? false; + decode(ctx, input) { + const disallowExtraProperties = ctx?.disallowExtraProperties ?? false; - const allowedExtraProperties = ctx.allowedExtraProperties__ ?? [] + const allowedExtraProperties = ctx.allowedExtraProperties__ ?? []; - if (typeof input === "object" && !Array.isArray(input) && input !== null) { - const acc = {}; - for (const [k, v] of Object.entries(data)) { - pushPath(ctx, k); - acc[k] = v(ctx, input[k]); - popPath(ctx); - } + if (typeof input === "object" && !Array.isArray(input) && input !== null) { + const acc = {}; + for (const [k, v] of Object.entries(this.data)) { + pushPath(ctx, k); + acc[k] = v(ctx, input[k]); + popPath(ctx); + } - if (additionalPropsValidator != null) { - for (const [k, v] of Object.entries(input)) { - if (acc[k] == null) { - pushPath(ctx, k); - - acc[k] = additionalPropsValidator(ctx, v); - popPath(ctx); + if (this.additionalPropsValidator != null) { + for (const [k, v] of Object.entries(input)) { + if (acc[k] == null) { + pushPath(ctx, k); + acc[k] = this.additionalPropsValidator(ctx, v); + popPath(ctx); + } } } - } - if (disallowExtraProperties) { - for (const k of Object.keys(input)) { - if (acc[k] == null && allowedExtraProperties.indexOf(k) == -1) { - pushPath(ctx, k); - buildError(input[k], ctx, "extra property"); - popPath(ctx); + if (disallowExtraProperties) { + for (const k of Object.keys(input)) { + if (acc[k] == null && allowedExtraProperties.indexOf(k) == -1) { + pushPath(ctx, k); + buildError(input[k], ctx, "extra property"); + popPath(ctx); + } } } - } - return acc; + return acc; + } + return buildError(input, ctx, "expected object"); } - return buildError(input, ctx, "expected object"); } -function decodeArray(ctx, input, required, data) { - if (!required && input == null) { - return input; +class ArrayDecoder { + constructor(data) { + this.data = data; } - if (Array.isArray(input)) { - const acc = []; - for (let i = 0; i < input.length; i++) { - const v = input[i]; - pushPath(ctx, "[" + i + "]"); - acc.push(data(ctx, v)); - popPath(ctx); + + decode(ctx, input) { + if (Array.isArray(input)) { + const acc = []; + for (let i = 0; i < input.length; i++) { + const v = input[i]; + pushPath(ctx, "[" + i + "]"); + acc.push(this.data(ctx, v)); + popPath(ctx); + } + return acc; } - return acc; + return buildError(input, ctx, "expected array"); } - return buildError(input, ctx, "expected array"); } -function decodeString(ctx, input, required) { - if (!required && input == null) { - return input; - } - +function decodeString(ctx, input) { if (typeof input === "string") { return input; } @@ -116,10 +117,7 @@ function decodeString(ctx, input, required) { return buildError(input, ctx, "expected string"); } -function decodeNumber(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeNumber(ctx, input) { if (typeof input === "number") { return input; } @@ -130,349 +128,372 @@ function decodeNumber(ctx, input, required) { return buildError(input, ctx, "expected number"); } -function decodeFunction(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeFunction(ctx, input) { if (typeof input === "function") { return input; } return buildError(input, ctx, "expected function"); } - -function decodeCodec(ctx, input, required, codec) { - if (!required && input == null) { - return input; +class CodecDecoder { + constructor(codec) { + this.codec = codec; } - switch (codec) { - case "Codec::ISO8061": { - const d = new Date(input); - if (isNaN(d.getTime())) { - return buildError(input, ctx, "expected ISO8061 date"); - } - return d; - } - case "Codec::BigInt": { - if (typeof input === "bigint") { - return input; - } - if (typeof input === "number") { - return BigInt(input); + decode(ctx, input) { + switch (this.codec) { + case "Codec::ISO8061": { + const d = new Date(input); + if (isNaN(d.getTime())) { + return buildError(input, ctx, "expected ISO8061 date"); + } + return d; } - if (typeof input === "string") { - try { + case "Codec::BigInt": { + if (typeof input === "bigint") { + return input; + } + if (typeof input === "number") { return BigInt(input); - } catch (e) { - } + if (typeof input === "string") { + try { + return BigInt(input); + } catch (e) { + + } + } + return buildError(input, ctx, "expected bigint"); } - return buildError(input, ctx, "expected bigint"); } + return buildError(input, ctx, "codec " + this.codec + " not implemented"); } - return buildError(input, ctx, "codec " + codec + " not implemented"); } -function decodeStringWithFormat(ctx, input, required, format) { - if (!required && input == null) { - return input; - } - if (typeof input !== "string") { - return buildError(input, ctx, "expected string with format " + JSON.stringify(format)); +class StringWithFormatDecoder { + constructor(format) { + this.format = format; } - const validator = customFormatters[format]; + decode(ctx, input) { + if (typeof input !== "string") { + return buildError(input, ctx, "expected string with format " + JSON.stringify(this.format)); + } - if (validator == null) { - return buildError(input, ctx, "format " + JSON.stringify(format) + " not implemented"); - } + const validator = customFormatters[this.format]; - const isOk = validator(input); - if (isOk) { - return input; - } - return buildError(input, ctx, "expected string with format " + JSON.stringify(format)); -} + if (validator == null) { + return buildError(input, ctx, "format " + JSON.stringify(this.format) + " not implemented"); + } -function decodeAnyOfDiscriminated(ctx, input, required, discriminator, mapping) { - if (!required && input == null) { - return input; - } - const d = input[discriminator]; - if (d == null) { - return buildError(input, ctx, "expected discriminator key " + JSON.stringify(discriminator)) - } - const v = mapping[d]; - if (v == null) { - pushPath(ctx, discriminator); - const err = buildError(d, ctx, "expected one of " + Object.keys(mapping).map(it => JSON.stringify(it)).join(", ")); - popPath(ctx); - return err; + const isOk = validator(input); + if (isOk) { + return input; + } + return buildError(input, ctx, "expected string with format " + JSON.stringify(this.format)); } - const prevAllow = (ctx.allowedExtraProperties__ ?? []); - ctx.allowedExtraProperties__ = [...prevAllow, discriminator] - const out = v(ctx, input); - ctx.allowedExtraProperties__ = prevAllow; - return { ...out, [discriminator]: d }; } - -function decodeAnyOfConsts(ctx, input, required, consts) { - if (!required && input == null) { - return input; +class AnyOfDiscriminatedDecoder { + constructor(discriminator, mapping) { + this.discriminator = discriminator; + this.mapping = mapping; } - for (const c of consts) { - if (input === c) { - return c; + + decode(ctx, input) { + const d = input[this.discriminator]; + if (d == null) { + return buildError(input, ctx, "expected discriminator key " + JSON.stringify(this.discriminator)); + } + const v = this.mapping[d]; + if (v == null) { + pushPath(ctx, this.discriminator); + const err = buildError( + d, + ctx, + "expected one of " + + Object.keys(this.mapping) + .map((it) => JSON.stringify(it)) + .join(", ") + ); + popPath(ctx); + return err; } + const prevAllow = ctx.allowedExtraProperties__ ?? []; + ctx.allowedExtraProperties__ = [...prevAllow, this.discriminator]; + const out = v(ctx, input); + ctx.allowedExtraProperties__ = prevAllow; + return { ...out, [this.discriminator]: d }; } - return buildError(input, ctx, "expected one of " + consts.map(it => JSON.stringify(it)).join(", ")); } -function decodeAnyOf(ctx, input, required, vs) { - if (!required && input == null) { - return input; - } - let accErrors = []; - for (const v of vs) { - const validatorCtx = {}; - const newValue = v(validatorCtx, input); - if (validatorCtx.errors == null) { - return newValue; +class AnyOfConstsDecoder { + constructor(consts) { + this.consts = consts; + } + decode(ctx, input) { + for (const c of this.consts) { + if (input === c) { + return c; + } } - accErrors.push(...(validatorCtx.errors ?? [])); + return buildError( + input, + ctx, + "expected one of " + this.consts.map((it) => JSON.stringify(it)).join(", ") + ); } - return buildUnionError(input, ctx, accErrors); } -function decodeAllOf(ctx, input, required, vs) { - if (!required && input == null) { - return input; - } - let acc = {}; - let foundOneObject = false; - let allObjects = true; - for (const v of vs) { - const newValue = v(ctx, input); - const isObj = typeof newValue === "object"; - allObjects = allObjects && isObj; - if (isObj) { - foundOneObject = true; - acc = { ...acc, ...newValue }; + +class AnyOfDecoder { + constructor(vs) { + this.vs = vs; + } + decode(ctx, input) { + let accErrors = []; + for (const v of this.vs) { + const validatorCtx = {}; + const newValue = v(validatorCtx, input); + if (validatorCtx.errors == null) { + return newValue; + } + accErrors.push(...(validatorCtx.errors ?? [])); } + return buildUnionError(input, ctx, accErrors); + } +} +class AllOfDecoder { + constructor(vs) { + this.vs = vs; + } + decode(ctx, input) { + let acc = {}; + let foundOneObject = false; + let allObjects = true; + for (const v of this.vs) { + const newValue = v(ctx, input); + const isObj = typeof newValue === "object"; + allObjects = allObjects && isObj; + if (isObj) { + foundOneObject = true; + acc = { ...acc, ...newValue }; + } + } + if (foundOneObject && allObjects) { + return acc; + } + return input; } - if (foundOneObject && allObjects) { - return acc; - } - return input; } -function decodeTuple(ctx, input, required, vs) { - if (!required && input == null) { - return input; +class TupleDecoder { + constructor(vs) { + this.vs = vs; } - if (Array.isArray(input)) { - const acc = []; - let idx = 0; - for (const v of vs.prefix) { - pushPath(ctx, "[" + idx + "]"); - const newValue = v(ctx, input[idx]); - popPath(ctx); - acc.push(newValue); - idx++; - } - if (vs.items != null) { - for (let i = idx; i < input.length; i++) { - const v = input[i]; - pushPath(ctx, "[" + i + "]"); - acc.push(vs.items(ctx, v)); + decode(ctx, input) { + if (Array.isArray(input)) { + const acc = []; + let idx = 0; + for (const v of this.vs.prefix) { + pushPath(ctx, "[" + idx + "]"); + const newValue = v(ctx, input[idx]); popPath(ctx); + acc.push(newValue); + idx++; } - } else { - if (input.length > idx) { - return buildError(input, ctx, "tuple has too many items"); + if (this.vs.items != null) { + for (let i = idx; i < input.length; i++) { + const v = input[i]; + pushPath(ctx, "[" + i + "]"); + acc.push(this.vs.items(ctx, v)); + popPath(ctx); + } + } else { + if (input.length > idx) { + return buildError(input, ctx, "tuple has too many items"); + } } + return acc; } - return acc; + return buildError(input, ctx, "expected tuple"); } - return buildError(input, ctx, "expected tuple"); } -function decodeBoolean(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeBoolean(ctx, input) { if (typeof input === "boolean") { return input; } return buildError(input, ctx, "expected boolean"); } -function decodeAny(ctx, input, required) { +function decodeAny(ctx, input) { return input; } -function decodeNull(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeNull(ctx, input) { if (input == null) { - return null; - } - return buildError(input, ctx, "expected null"); -} -function decodeNever(ctx, input, required) { - if (!required && input == null) { return input; } + return buildError(input, ctx, "expected nullish value"); +} +function decodeNever(ctx, input) { return buildError(input, ctx, "never"); } -function decodeConst(ctx, input, required, constValue) { - if (!required && input == null) { - return input; + +class ConstDecoder { + constructor(value) { + this.value = value; } - if (input == constValue) { - return constValue; + + decode(ctx, input) { + if (input == this.value) { + return this.value; + } + return buildError(input, ctx, "expected " + JSON.stringify(this.value)); } - return buildError(input, ctx, "expected " + JSON.stringify(constValue)); } -function decodeRegex(ctx, input, required, regex, description) { - if (!required && input == null) { - return input; +class RegexDecoder { + constructor(regex, description) { + this.regex = regex; + this.description = description; } - if (typeof input === "string") { - if (regex.test(input)) { - return input; + + decode(ctx, input) { + if (typeof input === "string") { + if (this.regex.test(input)) { + return input; + } } + return buildError(input, ctx, "expected string matching " + this.description); } - return buildError(input, ctx, "expected string matching " + description); } -function DecodeTransportedValue(ctx, input, required = true) { - return decodeAnyOf(ctx, input, required, hoisted_TransportedValue_2); + +function DecodeTransportedValue(ctx, input) { + return (hoisted_TransportedValue_2.decode.bind(hoisted_TransportedValue_2))(ctx, input); } -function DecodeAllTs(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_AllTs_3); +function DecodeAllTs(ctx, input) { + return (hoisted_AllTs_3.decode.bind(hoisted_AllTs_3))(ctx, input); } -function DecodeAObject(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_AObject_4); +function DecodeAObject(ctx, input) { + return (hoisted_AObject_5.decode.bind(hoisted_AObject_5))(ctx, input); } -function DecodeVersion(ctx, input, required = true) { - return decodeRegex(ctx, input, required, /(\d+(\.\d+)?)(\.)(\d+(\.\d+)?)(\.)(\d+(\.\d+)?)/, "${number}.${number}.${number}"); +function DecodeVersion(ctx, input) { + return (hoisted_Version_6.decode.bind(hoisted_Version_6))(ctx, input); } -function DecodeVersion2(ctx, input, required = true) { - return decodeRegex(ctx, input, required, /(v)(\d+(\.\d+)?)(\.)(\d+(\.\d+)?)(\.)(\d+(\.\d+)?)/, "v${number}.${number}.${number}"); +function DecodeVersion2(ctx, input) { + return (hoisted_Version2_7.decode.bind(hoisted_Version2_7))(ctx, input); } -function DecodeAccessLevel2(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_AccessLevel2_5); +function DecodeAccessLevel2(ctx, input) { + return (hoisted_AccessLevel2_8.decode.bind(hoisted_AccessLevel2_8))(ctx, input); } -function DecodeAccessLevelTpl2(ctx, input, required = true) { - return decodeRegex(ctx, input, required, /((ADMIN Admin)|(USER User))/, '("ADMIN Admin" | "USER User")'); +function DecodeAccessLevelTpl2(ctx, input) { + return (hoisted_AccessLevelTpl2_9.decode.bind(hoisted_AccessLevelTpl2_9))(ctx, input); } -function DecodeAccessLevel(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_AccessLevel_6); +function DecodeAccessLevel(ctx, input) { + return (hoisted_AccessLevel_10.decode.bind(hoisted_AccessLevel_10))(ctx, input); } -function DecodeAccessLevelTpl(ctx, input, required = true) { - return decodeRegex(ctx, input, required, /((ADMIN)|(USER))/, '("ADMIN" | "USER")'); +function DecodeAccessLevelTpl(ctx, input) { + return (hoisted_AccessLevelTpl_11.decode.bind(hoisted_AccessLevelTpl_11))(ctx, input); } -function DecodeArr3(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_Arr3_7); +function DecodeArr3(ctx, input) { + return (hoisted_Arr3_12.decode.bind(hoisted_Arr3_12))(ctx, input); } -function DecodeOmitSettings(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_OmitSettings_10); +function DecodeOmitSettings(ctx, input) { + return (hoisted_OmitSettings_16.decode.bind(hoisted_OmitSettings_16))(ctx, input); } -function DecodeSettings(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_Settings_13); +function DecodeSettings(ctx, input) { + return (hoisted_Settings_20.decode.bind(hoisted_Settings_20))(ctx, input); } -function DecodePartialObject(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_PartialObject_14); +function DecodePartialObject(ctx, input) { + return (hoisted_PartialObject_23.decode.bind(hoisted_PartialObject_23))(ctx, input); } -function DecodeRequiredPartialObject(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_RequiredPartialObject_15); +function DecodeRequiredPartialObject(ctx, input) { + return (hoisted_RequiredPartialObject_24.decode.bind(hoisted_RequiredPartialObject_24))(ctx, input); } -function DecodeLevelAndDSettings(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_LevelAndDSettings_18); +function DecodeLevelAndDSettings(ctx, input) { + return (hoisted_LevelAndDSettings_28.decode.bind(hoisted_LevelAndDSettings_28))(ctx, input); } -function DecodePartialSettings(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_PartialSettings_21); +function DecodePartialSettings(ctx, input) { + return (hoisted_PartialSettings_35.decode.bind(hoisted_PartialSettings_35))(ctx, input); } -function DecodeExtra(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_Extra_22, (ctx, input)=>(decodeString(ctx, input, false))); +function DecodeExtra(ctx, input) { + return (hoisted_Extra_36.decode.bind(hoisted_Extra_36))(ctx, input); } -function DecodeAvatarSize(ctx, input, required = true) { - return decodeRegex(ctx, input, required, /(\d+(\.\d+)?)(x)(\d+(\.\d+)?)/, "${number}x${number}"); +function DecodeAvatarSize(ctx, input) { + return (hoisted_AvatarSize_37.decode.bind(hoisted_AvatarSize_37))(ctx, input); } -function DecodeUser(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_User_24); +function DecodeUser(ctx, input) { + return (hoisted_User_39.decode.bind(hoisted_User_39))(ctx, input); } -function DecodePublicUser(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_PublicUser_25); +function DecodePublicUser(ctx, input) { + return (hoisted_PublicUser_40.decode.bind(hoisted_PublicUser_40))(ctx, input); } -function DecodeReq(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_Req_26); +function DecodeReq(ctx, input) { + return (hoisted_Req_41.decode.bind(hoisted_Req_41))(ctx, input); } -function DecodeWithOptionals(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_WithOptionals_27); +function DecodeWithOptionals(ctx, input) { + return (hoisted_WithOptionals_43.decode.bind(hoisted_WithOptionals_43))(ctx, input); } -function DecodeRepro1(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_Repro1_28); +function DecodeRepro1(ctx, input) { + return (hoisted_Repro1_45.decode.bind(hoisted_Repro1_45))(ctx, input); } -function DecodeRepro2(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_Repro2_29); +function DecodeRepro2(ctx, input) { + return (hoisted_Repro2_46.decode.bind(hoisted_Repro2_46))(ctx, input); } -function DecodeSettingsUpdate(ctx, input, required = true) { - return decodeAnyOf(ctx, input, required, hoisted_SettingsUpdate_31); +function DecodeSettingsUpdate(ctx, input) { + return (hoisted_SettingsUpdate_49.decode.bind(hoisted_SettingsUpdate_49))(ctx, input); } -function DecodeMapped(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_Mapped_34); +function DecodeMapped(ctx, input) { + return (hoisted_Mapped_54.decode.bind(hoisted_Mapped_54))(ctx, input); } -function DecodeMappedOptional(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_MappedOptional_37); +function DecodeMappedOptional(ctx, input) { + return (hoisted_MappedOptional_61.decode.bind(hoisted_MappedOptional_61))(ctx, input); } -function DecodeDiscriminatedUnion(ctx, input, required = true) { - return decodeAnyOfDiscriminated(ctx, input, required, "type", hoisted_DiscriminatedUnion_42); +function DecodeDiscriminatedUnion(ctx, input) { + return (hoisted_DiscriminatedUnion_67.decode.bind(hoisted_DiscriminatedUnion_67))(ctx, input); } -function DecodeDiscriminatedUnion2(ctx, input, required = true) { - return decodeAnyOf(ctx, input, required, hoisted_DiscriminatedUnion2_47); +function DecodeDiscriminatedUnion2(ctx, input) { + return (hoisted_DiscriminatedUnion2_80.decode.bind(hoisted_DiscriminatedUnion2_80))(ctx, input); } -function DecodeDiscriminatedUnion3(ctx, input, required = true) { - return decodeAnyOfDiscriminated(ctx, input, required, "type", hoisted_DiscriminatedUnion3_51); +function DecodeDiscriminatedUnion3(ctx, input) { + return (hoisted_DiscriminatedUnion3_84.decode.bind(hoisted_DiscriminatedUnion3_84))(ctx, input); } -function DecodeDiscriminatedUnion4(ctx, input, required = true) { - return decodeAnyOfDiscriminated(ctx, input, required, "type", hoisted_DiscriminatedUnion4_57); +function DecodeDiscriminatedUnion4(ctx, input) { + return (hoisted_DiscriminatedUnion4_92.decode.bind(hoisted_DiscriminatedUnion4_92))(ctx, input); } -function DecodeAllTypes(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_AllTypes_58); +function DecodeAllTypes(ctx, input) { + return (hoisted_AllTypes_93.decode.bind(hoisted_AllTypes_93))(ctx, input); } -function DecodeOtherEnum(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_OtherEnum_59); +function DecodeOtherEnum(ctx, input) { + return (hoisted_OtherEnum_94.decode.bind(hoisted_OtherEnum_94))(ctx, input); } -function DecodeArr2(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_Arr2_60); +function DecodeArr2(ctx, input) { + return (hoisted_Arr2_95.decode.bind(hoisted_Arr2_95))(ctx, input); } -function DecodeValidCurrency(ctx, input, required = true) { - return decodeStringWithFormat(ctx, input, required, "ValidCurrency"); +function DecodeValidCurrency(ctx, input) { + return (hoisted_ValidCurrency_96.decode.bind(hoisted_ValidCurrency_96))(ctx, input); } -function DecodeUnionWithEnumAccess(ctx, input, required = true) { - return decodeAnyOfDiscriminated(ctx, input, required, "tag", hoisted_UnionWithEnumAccess_64); +function DecodeUnionWithEnumAccess(ctx, input) { + return (hoisted_UnionWithEnumAccess_100.decode.bind(hoisted_UnionWithEnumAccess_100))(ctx, input); } -function DecodeShape(ctx, input, required = true) { - return decodeAnyOfDiscriminated(ctx, input, required, "kind", hoisted_Shape_68); +function DecodeShape(ctx, input) { + return (hoisted_Shape_104.decode.bind(hoisted_Shape_104))(ctx, input); } -function DecodeT3(ctx, input, required = true) { - return decodeAnyOfDiscriminated(ctx, input, required, "kind", hoisted_T3_71); +function DecodeT3(ctx, input) { + return (hoisted_T3_107.decode.bind(hoisted_T3_107))(ctx, input); } -function DecodeBObject(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_BObject_72); +function DecodeBObject(ctx, input) { + return (hoisted_BObject_109.decode.bind(hoisted_BObject_109))(ctx, input); } -function DecodeDEF(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_DEF_73); +function DecodeDEF(ctx, input) { + return (hoisted_DEF_110.decode.bind(hoisted_DEF_110))(ctx, input); } -function DecodeKDEF(ctx, input, required = true) { - return decodeConst(ctx, input, required, "a"); +function DecodeKDEF(ctx, input) { + return (hoisted_KDEF_111.decode.bind(hoisted_KDEF_111))(ctx, input); } -function DecodeABC(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_ABC_74); +function DecodeABC(ctx, input) { + return (hoisted_ABC_112.decode.bind(hoisted_ABC_112))(ctx, input); } -function DecodeKABC(ctx, input, required = true) { - return decodeNever(ctx, input, required); +function DecodeKABC(ctx, input) { + return (decodeNever)(ctx, input); } -function DecodeK(ctx, input, required = true) { - return decodeAnyOf(ctx, input, required, hoisted_K_75); +function DecodeK(ctx, input) { + return (hoisted_K_113.decode.bind(hoisted_K_113))(ctx, input); } const validators = { TransportedValue: DecodeTransportedValue, @@ -520,287 +541,361 @@ const validators = { KABC: DecodeKABC, K: DecodeK }; -const hoisted_TransportedValue_0 = [ - (ctx, input)=>(decodeNull(ctx, input, true)), - (ctx, input)=>(decodeString(ctx, input, true)), - (ctx, input)=>(decodeNumber(ctx, input, true)) -]; -const hoisted_TransportedValue_1 = (ctx, input)=>(decodeAnyOf(ctx, input, true, hoisted_TransportedValue_0)); -const hoisted_TransportedValue_2 = [ - (ctx, input)=>(decodeNull(ctx, input, true)), - (ctx, input)=>(decodeString(ctx, input, true)), - (ctx, input)=>(decodeArray(ctx, input, true, hoisted_TransportedValue_1)) -]; -const hoisted_AllTs_3 = [ +const hoisted_TransportedValue_0 = new AnyOfDecoder([ + decodeNull, + decodeString, + decodeNumber +]); +const hoisted_TransportedValue_1 = new ArrayDecoder(hoisted_TransportedValue_0.decode.bind(hoisted_TransportedValue_0)); +const hoisted_TransportedValue_2 = new AnyOfDecoder([ + decodeNull, + decodeString, + hoisted_TransportedValue_1.decode.bind(hoisted_TransportedValue_1) +]); +const hoisted_AllTs_3 = new AnyOfConstsDecoder([ "a", "b" -]; -const hoisted_AObject_4 = { - "tag": (ctx, input)=>(decodeConst(ctx, input, true, "a")) -}; -const hoisted_AccessLevel2_5 = [ +]); +const hoisted_AObject_4 = new ConstDecoder("a"); +const hoisted_AObject_5 = new ObjectDecoder({ + "tag": hoisted_AObject_4.decode.bind(hoisted_AObject_4) +}); +const hoisted_Version_6 = new RegexDecoder(/(\d+(\.\d+)?)(\.)(\d+(\.\d+)?)(\.)(\d+(\.\d+)?)/, "${number}.${number}.${number}"); +const hoisted_Version2_7 = new RegexDecoder(/(v)(\d+(\.\d+)?)(\.)(\d+(\.\d+)?)(\.)(\d+(\.\d+)?)/, "v${number}.${number}.${number}"); +const hoisted_AccessLevel2_8 = new AnyOfConstsDecoder([ "ADMIN Admin", "USER User" -]; -const hoisted_AccessLevel_6 = [ +]); +const hoisted_AccessLevelTpl2_9 = new RegexDecoder(/((ADMIN Admin)|(USER User))/, '("ADMIN Admin" | "USER User")'); +const hoisted_AccessLevel_10 = new AnyOfConstsDecoder([ "ADMIN", "USER" -]; -const hoisted_Arr3_7 = [ +]); +const hoisted_AccessLevelTpl_11 = new RegexDecoder(/((ADMIN)|(USER))/, '("ADMIN" | "USER")'); +const hoisted_Arr3_12 = new AnyOfConstsDecoder([ "X", "Y" -]; -const hoisted_OmitSettings_8 = { - "tag": (ctx, input)=>(decodeConst(ctx, input, true, "d")) -}; -const hoisted_OmitSettings_9 = [ +]); +const hoisted_OmitSettings_13 = new ConstDecoder("d"); +const hoisted_OmitSettings_14 = new ObjectDecoder({ + "tag": hoisted_OmitSettings_13.decode.bind(hoisted_OmitSettings_13) +}); +const hoisted_OmitSettings_15 = new AnyOfConstsDecoder([ "a", "b" -]; -const hoisted_OmitSettings_10 = { - "d": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_OmitSettings_8)), - "level": (ctx, input)=>(decodeAnyOfConsts(ctx, input, true, hoisted_OmitSettings_9)) -}; -const hoisted_Settings_11 = { - "tag": (ctx, input)=>(decodeConst(ctx, input, true, "d")) -}; -const hoisted_Settings_12 = [ +]); +const hoisted_OmitSettings_16 = new ObjectDecoder({ + "d": hoisted_OmitSettings_14.decode.bind(hoisted_OmitSettings_14), + "level": hoisted_OmitSettings_15.decode.bind(hoisted_OmitSettings_15) +}); +const hoisted_Settings_17 = new ConstDecoder("d"); +const hoisted_Settings_18 = new ObjectDecoder({ + "tag": hoisted_Settings_17.decode.bind(hoisted_Settings_17) +}); +const hoisted_Settings_19 = new AnyOfConstsDecoder([ "a", "b" -]; -const hoisted_Settings_13 = { - "a": (ctx, input)=>(decodeString(ctx, input, true)), - "d": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_Settings_11)), - "level": (ctx, input)=>(decodeAnyOfConsts(ctx, input, true, hoisted_Settings_12)) -}; -const hoisted_PartialObject_14 = { - "a": (ctx, input)=>(decodeString(ctx, input, false)), - "b": (ctx, input)=>(decodeNumber(ctx, input, false)) -}; -const hoisted_RequiredPartialObject_15 = { - "a": (ctx, input)=>(decodeString(ctx, input, true)), - "b": (ctx, input)=>(decodeNumber(ctx, input, true)) -}; -const hoisted_LevelAndDSettings_16 = { - "tag": (ctx, input)=>(decodeConst(ctx, input, true, "d")) -}; -const hoisted_LevelAndDSettings_17 = [ +]); +const hoisted_Settings_20 = new ObjectDecoder({ + "a": decodeString, + "d": hoisted_Settings_18.decode.bind(hoisted_Settings_18), + "level": hoisted_Settings_19.decode.bind(hoisted_Settings_19) +}); +const hoisted_PartialObject_21 = new AnyOfDecoder([ + decodeNull, + decodeString +]); +const hoisted_PartialObject_22 = new AnyOfDecoder([ + decodeNull, + decodeNumber +]); +const hoisted_PartialObject_23 = new ObjectDecoder({ + "a": hoisted_PartialObject_21.decode.bind(hoisted_PartialObject_21), + "b": hoisted_PartialObject_22.decode.bind(hoisted_PartialObject_22) +}); +const hoisted_RequiredPartialObject_24 = new ObjectDecoder({ + "a": decodeString, + "b": decodeNumber +}); +const hoisted_LevelAndDSettings_25 = new ConstDecoder("d"); +const hoisted_LevelAndDSettings_26 = new ObjectDecoder({ + "tag": hoisted_LevelAndDSettings_25.decode.bind(hoisted_LevelAndDSettings_25) +}); +const hoisted_LevelAndDSettings_27 = new AnyOfConstsDecoder([ "a", "b" -]; -const hoisted_LevelAndDSettings_18 = { - "d": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_LevelAndDSettings_16)), - "level": (ctx, input)=>(decodeAnyOfConsts(ctx, input, true, hoisted_LevelAndDSettings_17)) -}; -const hoisted_PartialSettings_19 = { - "tag": (ctx, input)=>(decodeConst(ctx, input, true, "d")) -}; -const hoisted_PartialSettings_20 = [ +]); +const hoisted_LevelAndDSettings_28 = new ObjectDecoder({ + "d": hoisted_LevelAndDSettings_26.decode.bind(hoisted_LevelAndDSettings_26), + "level": hoisted_LevelAndDSettings_27.decode.bind(hoisted_LevelAndDSettings_27) +}); +const hoisted_PartialSettings_29 = new AnyOfDecoder([ + decodeNull, + decodeString +]); +const hoisted_PartialSettings_30 = new ConstDecoder("d"); +const hoisted_PartialSettings_31 = new ObjectDecoder({ + "tag": hoisted_PartialSettings_30.decode.bind(hoisted_PartialSettings_30) +}); +const hoisted_PartialSettings_32 = new AnyOfDecoder([ + decodeNull, + hoisted_PartialSettings_31.decode.bind(hoisted_PartialSettings_31) +]); +const hoisted_PartialSettings_33 = new AnyOfConstsDecoder([ "a", "b" -]; -const hoisted_PartialSettings_21 = { - "a": (ctx, input)=>(decodeString(ctx, input, false)), - "d": (ctx, input)=>(decodeObject(ctx, input, false, hoisted_PartialSettings_19)), - "level": (ctx, input)=>(decodeAnyOfConsts(ctx, input, false, hoisted_PartialSettings_20)) -}; -const hoisted_Extra_22 = {}; -const hoisted_User_23 = (ctx, input)=>(validators.User(ctx, input, true)); -const hoisted_User_24 = { - "accessLevel": (ctx, input)=>(validators.AccessLevel(ctx, input, true)), - "avatarSize": (ctx, input)=>(validators.AvatarSize(ctx, input, true)), - "extra": (ctx, input)=>(validators.Extra(ctx, input, true)), - "friends": (ctx, input)=>(decodeArray(ctx, input, true, hoisted_User_23)), - "name": (ctx, input)=>(decodeString(ctx, input, true)) -}; -const hoisted_PublicUser_25 = { - "accessLevel": (ctx, input)=>(validators.AccessLevel(ctx, input, true)), - "avatarSize": (ctx, input)=>(validators.AvatarSize(ctx, input, true)), - "extra": (ctx, input)=>(validators.Extra(ctx, input, true)), - "name": (ctx, input)=>(decodeString(ctx, input, true)) -}; -const hoisted_Req_26 = { - "optional": (ctx, input)=>(decodeString(ctx, input, true)) -}; -const hoisted_WithOptionals_27 = { - "optional": (ctx, input)=>(decodeString(ctx, input, false)) -}; -const hoisted_Repro1_28 = { - "sizes": (ctx, input)=>(validators.Repro2(ctx, input, false)) -}; -const hoisted_Repro2_29 = { - "useSmallerSizes": (ctx, input)=>(decodeBoolean(ctx, input, true)) -}; -const hoisted_SettingsUpdate_30 = { - "tag": (ctx, input)=>(decodeConst(ctx, input, true, "d")) -}; -const hoisted_SettingsUpdate_31 = [ - (ctx, input)=>(decodeString(ctx, input, true)), - (ctx, input)=>(decodeObject(ctx, input, true, hoisted_SettingsUpdate_30)) -]; -const hoisted_Mapped_32 = { - "value": (ctx, input)=>(decodeConst(ctx, input, true, "a")) -}; -const hoisted_Mapped_33 = { - "value": (ctx, input)=>(decodeConst(ctx, input, true, "b")) -}; -const hoisted_Mapped_34 = { - "a": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_Mapped_32)), - "b": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_Mapped_33)) -}; -const hoisted_MappedOptional_35 = { - "value": (ctx, input)=>(decodeConst(ctx, input, true, "a")) -}; -const hoisted_MappedOptional_36 = { - "value": (ctx, input)=>(decodeConst(ctx, input, true, "b")) -}; -const hoisted_MappedOptional_37 = { - "a": (ctx, input)=>(decodeObject(ctx, input, false, hoisted_MappedOptional_35)), - "b": (ctx, input)=>(decodeObject(ctx, input, false, hoisted_MappedOptional_36)) -}; -const hoisted_DiscriminatedUnion_38 = { - "a1": (ctx, input)=>(decodeString(ctx, input, true)), - "a11": (ctx, input)=>(decodeString(ctx, input, false)) -}; -const hoisted_DiscriminatedUnion_39 = { - "a2": (ctx, input)=>(decodeString(ctx, input, true)) -}; -const hoisted_DiscriminatedUnion_40 = { - "a1": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion_38)), - "a2": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion_39)) -}; -const hoisted_DiscriminatedUnion_41 = { - "value": (ctx, input)=>(decodeNumber(ctx, input, true)) -}; -const hoisted_DiscriminatedUnion_42 = { - "a": (ctx, input)=>(decodeAnyOfDiscriminated(ctx, input, true, "subType", hoisted_DiscriminatedUnion_40)), - "b": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion_41)) -}; -const hoisted_DiscriminatedUnion2_43 = { - "a1": (ctx, input)=>(decodeString(ctx, input, true)), - "a11": (ctx, input)=>(decodeString(ctx, input, false)), - "subType": (ctx, input)=>(decodeConst(ctx, input, true, "a1")), - "type": (ctx, input)=>(decodeConst(ctx, input, true, "a")) -}; -const hoisted_DiscriminatedUnion2_44 = { - "a2": (ctx, input)=>(decodeString(ctx, input, true)), - "subType": (ctx, input)=>(decodeConst(ctx, input, true, "a2")), - "type": (ctx, input)=>(decodeConst(ctx, input, true, "a")) -}; -const hoisted_DiscriminatedUnion2_45 = { - "type": (ctx, input)=>(decodeConst(ctx, input, false, "d")), - "valueD": (ctx, input)=>(decodeNumber(ctx, input, true)) -}; -const hoisted_DiscriminatedUnion2_46 = { - "type": (ctx, input)=>(decodeConst(ctx, input, true, "b")), - "value": (ctx, input)=>(decodeNumber(ctx, input, true)) -}; -const hoisted_DiscriminatedUnion2_47 = [ - (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion2_43)), - (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion2_44)), - (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion2_45)), - (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion2_46)) -]; -const hoisted_DiscriminatedUnion3_48 = { - "a1": (ctx, input)=>(decodeString(ctx, input, true)) -}; -const hoisted_DiscriminatedUnion3_49 = { - "value": (ctx, input)=>(decodeNumber(ctx, input, true)) -}; -const hoisted_DiscriminatedUnion3_50 = { - "a1": (ctx, input)=>(decodeString(ctx, input, true)) -}; -const hoisted_DiscriminatedUnion3_51 = { - "a": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion3_48)), - "b": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion3_49)), - "c": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion3_50)) -}; -const hoisted_DiscriminatedUnion4_52 = { - "a1": (ctx, input)=>(decodeString(ctx, input, true)), - "subType": (ctx, input)=>(decodeConst(ctx, input, true, "a1")) -}; -const hoisted_DiscriminatedUnion4_53 = { - "a": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion4_52)) -}; -const hoisted_DiscriminatedUnion4_54 = { - "a2": (ctx, input)=>(decodeString(ctx, input, true)), - "subType": (ctx, input)=>(decodeConst(ctx, input, true, "a2")) -}; -const hoisted_DiscriminatedUnion4_55 = { - "a": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion4_54)) -}; -const hoisted_DiscriminatedUnion4_56 = [ - (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion4_53)), - (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion4_55)) -]; -const hoisted_DiscriminatedUnion4_57 = { - "a": (ctx, input)=>(decodeAnyOf(ctx, input, true, hoisted_DiscriminatedUnion4_56)) -}; -const hoisted_AllTypes_58 = [ +]); +const hoisted_PartialSettings_34 = new AnyOfDecoder([ + decodeNull, + hoisted_PartialSettings_33.decode.bind(hoisted_PartialSettings_33) +]); +const hoisted_PartialSettings_35 = new ObjectDecoder({ + "a": hoisted_PartialSettings_29.decode.bind(hoisted_PartialSettings_29), + "d": hoisted_PartialSettings_32.decode.bind(hoisted_PartialSettings_32), + "level": hoisted_PartialSettings_34.decode.bind(hoisted_PartialSettings_34) +}); +const hoisted_Extra_36 = new ObjectDecoder({}, decodeString); +const hoisted_AvatarSize_37 = new RegexDecoder(/(\d+(\.\d+)?)(x)(\d+(\.\d+)?)/, "${number}x${number}"); +const hoisted_User_38 = new ArrayDecoder(validators.User); +const hoisted_User_39 = new ObjectDecoder({ + "accessLevel": validators.AccessLevel, + "avatarSize": validators.AvatarSize, + "extra": validators.Extra, + "friends": hoisted_User_38.decode.bind(hoisted_User_38), + "name": decodeString +}); +const hoisted_PublicUser_40 = new ObjectDecoder({ + "accessLevel": validators.AccessLevel, + "avatarSize": validators.AvatarSize, + "extra": validators.Extra, + "name": decodeString +}); +const hoisted_Req_41 = new ObjectDecoder({ + "optional": decodeString +}); +const hoisted_WithOptionals_42 = new AnyOfDecoder([ + decodeNull, + decodeString +]); +const hoisted_WithOptionals_43 = new ObjectDecoder({ + "optional": hoisted_WithOptionals_42.decode.bind(hoisted_WithOptionals_42) +}); +const hoisted_Repro1_44 = new AnyOfDecoder([ + decodeNull, + validators.Repro2 +]); +const hoisted_Repro1_45 = new ObjectDecoder({ + "sizes": hoisted_Repro1_44.decode.bind(hoisted_Repro1_44) +}); +const hoisted_Repro2_46 = new ObjectDecoder({ + "useSmallerSizes": decodeBoolean +}); +const hoisted_SettingsUpdate_47 = new ConstDecoder("d"); +const hoisted_SettingsUpdate_48 = new ObjectDecoder({ + "tag": hoisted_SettingsUpdate_47.decode.bind(hoisted_SettingsUpdate_47) +}); +const hoisted_SettingsUpdate_49 = new AnyOfDecoder([ + decodeString, + hoisted_SettingsUpdate_48.decode.bind(hoisted_SettingsUpdate_48) +]); +const hoisted_Mapped_50 = new ConstDecoder("a"); +const hoisted_Mapped_51 = new ObjectDecoder({ + "value": hoisted_Mapped_50.decode.bind(hoisted_Mapped_50) +}); +const hoisted_Mapped_52 = new ConstDecoder("b"); +const hoisted_Mapped_53 = new ObjectDecoder({ + "value": hoisted_Mapped_52.decode.bind(hoisted_Mapped_52) +}); +const hoisted_Mapped_54 = new ObjectDecoder({ + "a": hoisted_Mapped_51.decode.bind(hoisted_Mapped_51), + "b": hoisted_Mapped_53.decode.bind(hoisted_Mapped_53) +}); +const hoisted_MappedOptional_55 = new ConstDecoder("a"); +const hoisted_MappedOptional_56 = new ObjectDecoder({ + "value": hoisted_MappedOptional_55.decode.bind(hoisted_MappedOptional_55) +}); +const hoisted_MappedOptional_57 = new AnyOfDecoder([ + decodeNull, + hoisted_MappedOptional_56.decode.bind(hoisted_MappedOptional_56) +]); +const hoisted_MappedOptional_58 = new ConstDecoder("b"); +const hoisted_MappedOptional_59 = new ObjectDecoder({ + "value": hoisted_MappedOptional_58.decode.bind(hoisted_MappedOptional_58) +}); +const hoisted_MappedOptional_60 = new AnyOfDecoder([ + decodeNull, + hoisted_MappedOptional_59.decode.bind(hoisted_MappedOptional_59) +]); +const hoisted_MappedOptional_61 = new ObjectDecoder({ + "a": hoisted_MappedOptional_57.decode.bind(hoisted_MappedOptional_57), + "b": hoisted_MappedOptional_60.decode.bind(hoisted_MappedOptional_60) +}); +const hoisted_DiscriminatedUnion_62 = new AnyOfDecoder([ + decodeNull, + decodeString +]); +const hoisted_DiscriminatedUnion_63 = new ObjectDecoder({ + "a1": decodeString, + "a11": hoisted_DiscriminatedUnion_62.decode.bind(hoisted_DiscriminatedUnion_62) +}); +const hoisted_DiscriminatedUnion_64 = new ObjectDecoder({ + "a2": decodeString +}); +const hoisted_DiscriminatedUnion_65 = new AnyOfDiscriminatedDecoder("subType", { + "a1": hoisted_DiscriminatedUnion_63.decode.bind(hoisted_DiscriminatedUnion_63), + "a2": hoisted_DiscriminatedUnion_64.decode.bind(hoisted_DiscriminatedUnion_64) +}); +const hoisted_DiscriminatedUnion_66 = new ObjectDecoder({ + "value": decodeNumber +}); +const hoisted_DiscriminatedUnion_67 = new AnyOfDiscriminatedDecoder("type", { + "a": hoisted_DiscriminatedUnion_65.decode.bind(hoisted_DiscriminatedUnion_65), + "b": hoisted_DiscriminatedUnion_66.decode.bind(hoisted_DiscriminatedUnion_66) +}); +const hoisted_DiscriminatedUnion2_68 = new AnyOfDecoder([ + decodeNull, + decodeString +]); +const hoisted_DiscriminatedUnion2_69 = new ConstDecoder("a1"); +const hoisted_DiscriminatedUnion2_70 = new ConstDecoder("a"); +const hoisted_DiscriminatedUnion2_71 = new ObjectDecoder({ + "a1": decodeString, + "a11": hoisted_DiscriminatedUnion2_68.decode.bind(hoisted_DiscriminatedUnion2_68), + "subType": hoisted_DiscriminatedUnion2_69.decode.bind(hoisted_DiscriminatedUnion2_69), + "type": hoisted_DiscriminatedUnion2_70.decode.bind(hoisted_DiscriminatedUnion2_70) +}); +const hoisted_DiscriminatedUnion2_72 = new ConstDecoder("a2"); +const hoisted_DiscriminatedUnion2_73 = new ConstDecoder("a"); +const hoisted_DiscriminatedUnion2_74 = new ObjectDecoder({ + "a2": decodeString, + "subType": hoisted_DiscriminatedUnion2_72.decode.bind(hoisted_DiscriminatedUnion2_72), + "type": hoisted_DiscriminatedUnion2_73.decode.bind(hoisted_DiscriminatedUnion2_73) +}); +const hoisted_DiscriminatedUnion2_75 = new ConstDecoder("d"); +const hoisted_DiscriminatedUnion2_76 = new AnyOfDecoder([ + decodeNull, + hoisted_DiscriminatedUnion2_75.decode.bind(hoisted_DiscriminatedUnion2_75) +]); +const hoisted_DiscriminatedUnion2_77 = new ObjectDecoder({ + "type": hoisted_DiscriminatedUnion2_76.decode.bind(hoisted_DiscriminatedUnion2_76), + "valueD": decodeNumber +}); +const hoisted_DiscriminatedUnion2_78 = new ConstDecoder("b"); +const hoisted_DiscriminatedUnion2_79 = new ObjectDecoder({ + "type": hoisted_DiscriminatedUnion2_78.decode.bind(hoisted_DiscriminatedUnion2_78), + "value": decodeNumber +}); +const hoisted_DiscriminatedUnion2_80 = new AnyOfDecoder([ + hoisted_DiscriminatedUnion2_71.decode.bind(hoisted_DiscriminatedUnion2_71), + hoisted_DiscriminatedUnion2_74.decode.bind(hoisted_DiscriminatedUnion2_74), + hoisted_DiscriminatedUnion2_77.decode.bind(hoisted_DiscriminatedUnion2_77), + hoisted_DiscriminatedUnion2_79.decode.bind(hoisted_DiscriminatedUnion2_79) +]); +const hoisted_DiscriminatedUnion3_81 = new ObjectDecoder({ + "a1": decodeString +}); +const hoisted_DiscriminatedUnion3_82 = new ObjectDecoder({ + "value": decodeNumber +}); +const hoisted_DiscriminatedUnion3_83 = new ObjectDecoder({ + "a1": decodeString +}); +const hoisted_DiscriminatedUnion3_84 = new AnyOfDiscriminatedDecoder("type", { + "a": hoisted_DiscriminatedUnion3_81.decode.bind(hoisted_DiscriminatedUnion3_81), + "b": hoisted_DiscriminatedUnion3_82.decode.bind(hoisted_DiscriminatedUnion3_82), + "c": hoisted_DiscriminatedUnion3_83.decode.bind(hoisted_DiscriminatedUnion3_83) +}); +const hoisted_DiscriminatedUnion4_85 = new ConstDecoder("a1"); +const hoisted_DiscriminatedUnion4_86 = new ObjectDecoder({ + "a1": decodeString, + "subType": hoisted_DiscriminatedUnion4_85.decode.bind(hoisted_DiscriminatedUnion4_85) +}); +const hoisted_DiscriminatedUnion4_87 = new ObjectDecoder({ + "a": hoisted_DiscriminatedUnion4_86.decode.bind(hoisted_DiscriminatedUnion4_86) +}); +const hoisted_DiscriminatedUnion4_88 = new ConstDecoder("a2"); +const hoisted_DiscriminatedUnion4_89 = new ObjectDecoder({ + "a2": decodeString, + "subType": hoisted_DiscriminatedUnion4_88.decode.bind(hoisted_DiscriminatedUnion4_88) +}); +const hoisted_DiscriminatedUnion4_90 = new ObjectDecoder({ + "a": hoisted_DiscriminatedUnion4_89.decode.bind(hoisted_DiscriminatedUnion4_89) +}); +const hoisted_DiscriminatedUnion4_91 = new AnyOfDecoder([ + hoisted_DiscriminatedUnion4_87.decode.bind(hoisted_DiscriminatedUnion4_87), + hoisted_DiscriminatedUnion4_90.decode.bind(hoisted_DiscriminatedUnion4_90) +]); +const hoisted_DiscriminatedUnion4_92 = new AnyOfDiscriminatedDecoder("type", { + "a": hoisted_DiscriminatedUnion4_91.decode.bind(hoisted_DiscriminatedUnion4_91) +}); +const hoisted_AllTypes_93 = new AnyOfConstsDecoder([ "LevelAndDSettings", "OmitSettings", "PartialSettings", "RequiredPartialObject" -]; -const hoisted_OtherEnum_59 = [ +]); +const hoisted_OtherEnum_94 = new AnyOfConstsDecoder([ "a", "b" -]; -const hoisted_Arr2_60 = [ +]); +const hoisted_Arr2_95 = new AnyOfConstsDecoder([ "A", "B", "C" -]; -const hoisted_UnionWithEnumAccess_61 = { - "value": (ctx, input)=>(decodeString(ctx, input, true)) -}; -const hoisted_UnionWithEnumAccess_62 = { - "value": (ctx, input)=>(decodeNumber(ctx, input, true)) -}; -const hoisted_UnionWithEnumAccess_63 = { - "value": (ctx, input)=>(decodeBoolean(ctx, input, true)) -}; -const hoisted_UnionWithEnumAccess_64 = { - "a": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_UnionWithEnumAccess_61)), - "b": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_UnionWithEnumAccess_62)), - "c": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_UnionWithEnumAccess_63)) -}; -const hoisted_Shape_65 = { - "radius": (ctx, input)=>(decodeNumber(ctx, input, true)) -}; -const hoisted_Shape_66 = { - "x": (ctx, input)=>(decodeNumber(ctx, input, true)) -}; -const hoisted_Shape_67 = { - "x": (ctx, input)=>(decodeNumber(ctx, input, true)), - "y": (ctx, input)=>(decodeNumber(ctx, input, true)) -}; -const hoisted_Shape_68 = { - "circle": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_Shape_65)), - "square": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_Shape_66)), - "triangle": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_Shape_67)) -}; -const hoisted_T3_69 = { - "x": (ctx, input)=>(decodeNumber(ctx, input, true)) -}; -const hoisted_T3_70 = { - "x": (ctx, input)=>(decodeNumber(ctx, input, true)), - "y": (ctx, input)=>(decodeNumber(ctx, input, true)) -}; -const hoisted_T3_71 = { - "square": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_T3_69)), - "triangle": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_T3_70)) -}; -const hoisted_BObject_72 = { - "tag": (ctx, input)=>(decodeConst(ctx, input, true, "b")) -}; -const hoisted_DEF_73 = { - "a": (ctx, input)=>(decodeString(ctx, input, true)) -}; -const hoisted_ABC_74 = {}; -const hoisted_K_75 = [ - (ctx, input)=>(validators.KABC(ctx, input, true)), - (ctx, input)=>(validators.KDEF(ctx, input, true)) -]; +]); +const hoisted_ValidCurrency_96 = new StringWithFormatDecoder("ValidCurrency"); +const hoisted_UnionWithEnumAccess_97 = new ObjectDecoder({ + "value": decodeString +}); +const hoisted_UnionWithEnumAccess_98 = new ObjectDecoder({ + "value": decodeNumber +}); +const hoisted_UnionWithEnumAccess_99 = new ObjectDecoder({ + "value": decodeBoolean +}); +const hoisted_UnionWithEnumAccess_100 = new AnyOfDiscriminatedDecoder("tag", { + "a": hoisted_UnionWithEnumAccess_97.decode.bind(hoisted_UnionWithEnumAccess_97), + "b": hoisted_UnionWithEnumAccess_98.decode.bind(hoisted_UnionWithEnumAccess_98), + "c": hoisted_UnionWithEnumAccess_99.decode.bind(hoisted_UnionWithEnumAccess_99) +}); +const hoisted_Shape_101 = new ObjectDecoder({ + "radius": decodeNumber +}); +const hoisted_Shape_102 = new ObjectDecoder({ + "x": decodeNumber +}); +const hoisted_Shape_103 = new ObjectDecoder({ + "x": decodeNumber, + "y": decodeNumber +}); +const hoisted_Shape_104 = new AnyOfDiscriminatedDecoder("kind", { + "circle": hoisted_Shape_101.decode.bind(hoisted_Shape_101), + "square": hoisted_Shape_102.decode.bind(hoisted_Shape_102), + "triangle": hoisted_Shape_103.decode.bind(hoisted_Shape_103) +}); +const hoisted_T3_105 = new ObjectDecoder({ + "x": decodeNumber +}); +const hoisted_T3_106 = new ObjectDecoder({ + "x": decodeNumber, + "y": decodeNumber +}); +const hoisted_T3_107 = new AnyOfDiscriminatedDecoder("kind", { + "square": hoisted_T3_105.decode.bind(hoisted_T3_105), + "triangle": hoisted_T3_106.decode.bind(hoisted_T3_106) +}); +const hoisted_BObject_108 = new ConstDecoder("b"); +const hoisted_BObject_109 = new ObjectDecoder({ + "tag": hoisted_BObject_108.decode.bind(hoisted_BObject_108) +}); +const hoisted_DEF_110 = new ObjectDecoder({ + "a": decodeString +}); +const hoisted_KDEF_111 = new ConstDecoder("a"); +const hoisted_ABC_112 = new ObjectDecoder({}); +const hoisted_K_113 = new AnyOfDecoder([ + validators.KABC, + validators.KDEF +]); -export default { decodeObject, decodeArray, decodeString, decodeNumber, decodeCodec, decodeFunction, decodeStringWithFormat, decodeAnyOf, decodeAllOf, decodeBoolean, decodeAny, decodeTuple, decodeNull, decodeNever, decodeConst, registerCustomFormatter, validators }; \ No newline at end of file +export default { ObjectDecoder, ArrayDecoder, decodeString, decodeNumber, CodecDecoder, decodeFunction, StringWithFormatDecoder, AnyOfDecoder, AllOfDecoder, decodeBoolean, decodeAny, TupleDecoder, decodeNull, decodeNever, RegexDecoder, ConstDecoder, registerCustomFormatter, AnyOfConstsDecoder, AnyOfDiscriminatedDecoder, validators }; \ No newline at end of file diff --git a/e2e-tests/standalone-parser/src/parser.ts b/e2e-tests/standalone-parser/src/parser.ts index 0a264747..ab1f81b0 100644 --- a/e2e-tests/standalone-parser/src/parser.ts +++ b/e2e-tests/standalone-parser/src/parser.ts @@ -223,8 +223,16 @@ export const { BObject, AllTs, TransportedValue, + BigIntCodec: BigIntCodec, + TupleCodec: TupleCodec, + TupleCodecRest: TupleCodecRest, + StringArrCodec: StringArrCodec, } = parse.buildParsers<{ TransportedValue: TransportedValue; + BigIntCodec: bigint; + TupleCodec: [number, number, number]; + TupleCodecRest: [number, number, ...string[]]; + StringArrCodec: string[]; AllTs: T4.AllTs; AObject: AObject; Version: Version; diff --git a/e2e-tests/standalone-parser/tests/parser.test.ts b/e2e-tests/standalone-parser/tests/parser.test.ts index 925acdad..8807114e 100644 --- a/e2e-tests/standalone-parser/tests/parser.test.ts +++ b/e2e-tests/standalone-parser/tests/parser.test.ts @@ -27,13 +27,17 @@ import { AllTs, TransportedValue, ImportEnumTypeofCodec, + BigIntCodec, + TupleCodec, + TupleCodecRest, + StringArrCodec, } from "../src/parser"; import { Arr2 } from "../src/types"; import { Schemas } from "../src/schema"; it("TransportedValue bug", () => { expect(TransportedValue.parse(null)).toEqual(null); - expect(TransportedValue.parse(undefined)).toEqual(null); + expect(TransportedValue.parse(undefined)).toEqual(undefined); expect(TransportedValue.parse("")).toEqual(""); expect(TransportedValue.parse(["abc"])).toStrictEqual(["abc"]); expect(TransportedValue.parse([123])).toStrictEqual([123]); @@ -56,6 +60,79 @@ it("import enum typeof", () => { `); }); +it("BigIntCodec", () => { + expect(BigIntCodec.parse("123")).toMatchInlineSnapshot(`123n`); +}); +it("TupleCodec", () => { + expect(TupleCodec.safeParse([1])).toMatchInlineSnapshot(` + { + "errors": [ + { + "message": "expected number", + "path": [ + "[1]", + ], + "received": undefined, + }, + { + "message": "expected number", + "path": [ + "[2]", + ], + "received": undefined, + }, + ], + "success": false, + } + `); +}); +it("TupleCodecRest", () => { + expect(TupleCodecRest.safeParse([1, 2, 3])).toMatchInlineSnapshot(` + { + "errors": [ + { + "message": "expected string", + "path": [ + "[2]", + ], + "received": 3, + }, + ], + "success": false, + } + `); +}); +it("StringArrCodec", () => { + expect(StringArrCodec.safeParse([1, 2, 3])).toMatchInlineSnapshot(` + { + "errors": [ + { + "message": "expected string", + "path": [ + "[0]", + ], + "received": 1, + }, + { + "message": "expected string", + "path": [ + "[1]", + ], + "received": 2, + }, + { + "message": "expected string", + "path": [ + "[2]", + ], + "received": 3, + }, + ], + "success": false, + } + `); +}); + it("tpl", () => { expect(Version2.parse("v1.2.3")).toMatchInlineSnapshot('"v1.2.3"'); expect(Version2.safeParse("UNKNOWN")).toMatchInlineSnapshot(` @@ -229,11 +306,11 @@ it("disallow extra properties", () => { } ) ).toMatchInlineSnapshot(` - { - "kind": "square", - "x": 1, - } -`); + { + "kind": "square", + "x": 1, + } + `); expect( T3.safeParse( { @@ -389,7 +466,20 @@ it("DiscriminatedUnion", () => { { "errors": [ { - "message": "expected string", + "errors": [ + { + "message": "expected nullish value", + "path": [], + "received": 123, + }, + { + "message": "expected string", + "path": [], + "received": 123, + }, + ], + "isUnionError": true, + "message": "expected one of", "path": [ "a11", ], diff --git a/packages/beff-cli/CHANGELOG.md b/packages/beff-cli/CHANGELOG.md index b51ff8d2..7a5c44c2 100644 --- a/packages/beff-cli/CHANGELOG.md +++ b/packages/beff-cli/CHANGELOG.md @@ -1,5 +1,11 @@ # @beff/cli +## 0.0.70 + +### Patch Changes + +- required reimpl + ## 0.0.69 ### Patch Changes diff --git a/packages/beff-cli/package.json b/packages/beff-cli/package.json index bfac0e61..b6079268 100644 --- a/packages/beff-cli/package.json +++ b/packages/beff-cli/package.json @@ -1,6 +1,6 @@ { "name": "@beff/cli", - "version": "0.0.69", + "version": "0.0.70", "description": "", "bin": { "beff": "./bin/index.js" diff --git a/packages/beff-client/CHANGELOG.md b/packages/beff-client/CHANGELOG.md index 4a77a2f3..d4ebb3b4 100644 --- a/packages/beff-client/CHANGELOG.md +++ b/packages/beff-client/CHANGELOG.md @@ -1,5 +1,13 @@ # @beff/client +## 0.0.70 + +### Patch Changes + +- required reimpl +- Updated dependencies + - @beff/cli@0.0.70 + ## 0.0.69 ### Patch Changes diff --git a/packages/beff-client/package.json b/packages/beff-client/package.json index 278f5c9c..08a79ad5 100644 --- a/packages/beff-client/package.json +++ b/packages/beff-client/package.json @@ -1,6 +1,6 @@ { "name": "@beff/client", - "version": "0.0.69", + "version": "0.0.70", "description": "", "main": "dist/cjs/index.js", "scripts": { @@ -20,7 +20,7 @@ "author": "", "license": "ISC", "dependencies": { - "@beff/cli": "workspace:^0.0.69", + "@beff/cli": "workspace:^0.0.70", "zod": "^3.23.5" }, "devDependencies": { diff --git a/packages/beff-core/src/print/decoder.rs b/packages/beff-core/src/print/decoder.rs index d64b60f4..7a56c100 100644 --- a/packages/beff-core/src/print/decoder.rs +++ b/packages/beff-core/src/print/decoder.rs @@ -6,10 +6,9 @@ use crate::{ use std::collections::{BTreeMap, BTreeSet}; use swc_common::DUMMY_SP; use swc_ecma_ast::{ - ArrayLit, ArrowExpr, AssignPat, BindingIdent, BlockStmt, BlockStmtOrExpr, Bool, CallExpr, - Callee, Expr, ExprOrSpread, Function, Ident, KeyValueProp, Lit, MemberExpr, MemberProp, - ModuleItem, Null, ObjectLit, Param, ParenExpr, Pat, Prop, PropName, PropOrSpread, Regex, - ReturnStmt, Stmt, Str, + ArrayLit, BindingIdent, BlockStmt, CallExpr, Callee, Expr, ExprOrSpread, Function, Ident, + KeyValueProp, Lit, MemberExpr, MemberProp, ModuleItem, NewExpr, Null, ObjectLit, Param, + ParenExpr, Pat, Prop, PropName, PropOrSpread, Regex, ReturnStmt, Stmt, Str, }; struct SwcBuilder; @@ -33,71 +32,14 @@ impl SwcBuilder { } } -#[derive(Debug, Clone, Copy)] -enum Required { - Known(bool), - FromArgs, -} struct DecoderFnGenerator<'a> { validators: &'a Vec, name: String, } impl DecoderFnGenerator<'_> { - fn decode_call(fn_name: &str, required: Required) -> Expr { - Self::decode_call_extra(fn_name, required, vec![]) - } - - fn require_to_expr(required: Required) -> Expr { - match required { - Required::Known(v) => Expr::Lit(Lit::Bool(Bool { - span: DUMMY_SP, - value: v, - })), - Required::FromArgs => SwcBuilder::ident_expr("required"), - } - } - fn base_args(required: Required) -> Vec { - vec![ - ExprOrSpread { - spread: None, - expr: SwcBuilder::ident_expr("ctx").into(), - }, - ExprOrSpread { - spread: None, - expr: SwcBuilder::ident_expr("input").into(), - }, - ExprOrSpread { - spread: None, - expr: Self::require_to_expr(required).into(), - }, - ] - } - - fn decode_call_extra(fn_name: &str, required: Required, extra: Vec) -> Expr { - Expr::Call(CallExpr { - span: DUMMY_SP, - callee: Callee::Expr( - Expr::Ident(Ident { - span: DUMMY_SP, - sym: fn_name.into(), - optional: false, - }) - .into(), - ), - args: Self::base_args(required) - .into_iter() - .chain(extra.into_iter().map(|it| ExprOrSpread { - spread: None, - expr: it.into(), - })) - .collect(), - type_args: None, - }) - } - - fn decode_ref(schema_ref: &str, required: Required) -> Expr { - let decoder_ref_fn = Expr::Member(MemberExpr { + fn decode_ref(schema_ref: &str) -> Expr { + Expr::Member(MemberExpr { span: DUMMY_SP, obj: Expr::Ident(Ident { span: DUMMY_SP, @@ -110,90 +52,29 @@ impl DecoderFnGenerator<'_> { sym: schema_ref.into(), optional: false, }), - }); - - Expr::Call(CallExpr { - span: DUMMY_SP, - callee: Callee::Expr(decoder_ref_fn.into()), - args: Self::base_args(required), - type_args: None, - }) - } - - fn make_cb(extra: Expr) -> Expr { - Expr::Arrow(ArrowExpr { - span: DUMMY_SP, - params: vec![ - Pat::Ident(BindingIdent { - id: Ident { - span: DUMMY_SP, - sym: "ctx".into(), - optional: false, - }, - type_ann: None, - }), - Pat::Ident(BindingIdent { - id: Ident { - span: DUMMY_SP, - sym: "input".into(), - optional: false, - }, - type_ann: None, - }), - ], - body: BlockStmtOrExpr::Expr( - Expr::Paren(ParenExpr { - span: DUMMY_SP, - expr: extra.into(), - }) - .into(), - ) - .into(), - is_async: false, - is_generator: false, - type_params: None, - return_type: None, }) } fn decode_union_or_intersection( &self, decoder_name: &str, - required: Required, vs: &BTreeSet, hoisted: &mut Vec, ) -> Expr { - let els_expr: Vec = vs - .iter() - .map(|it| { - self.decode_expr( - it, - // force inner to be required, because we're checking outside already - Required::Known(true), - hoisted, - ) - }) - .collect(); - - Self::decode_call_extra( - decoder_name, - required, - vec![self.hoist_expr( - hoisted, - Expr::Array(ArrayLit { - span: DUMMY_SP, - elems: els_expr - .into_iter() - .map(|it| { - Some(ExprOrSpread { - spread: None, - expr: Self::make_cb(it).into(), - }) - }) - .collect(), - }), - )], - ) + let els_expr: Vec = vs.iter().map(|it| self.decode_expr(it, hoisted)).collect(); + let arr_lit = Expr::Array(ArrayLit { + span: DUMMY_SP, + elems: els_expr + .into_iter() + .map(|it| { + Some(ExprOrSpread { + spread: None, + expr: it.into(), + }) + }) + .collect(), + }); + Self::decode_bound(self.new_hoisted_decoder(hoisted, decoder_name, vec![arr_lit])) } fn extract_union(&self, it: &JsonSchema) -> Vec { match it { @@ -212,7 +93,7 @@ impl DecoderFnGenerator<'_> { fn decode_any_of_discriminated( &self, - required: Required, + discriminator: String, discriminator_strings: BTreeSet, object_vs: Vec<&BTreeMap>>, @@ -258,33 +139,28 @@ impl DecoderFnGenerator<'_> { value: key.clone().into(), raw: None, }), - value: Box::new(Self::make_cb(self.decode_expr( - value, - Required::Known(true), - hoisted, - ))), + value: Box::new(self.decode_expr(value, hoisted)), }))) }) .collect(), }); - - Self::decode_call_extra( - "decodeAnyOfDiscriminated", - required, + Self::decode_bound(self.new_hoisted_decoder( + hoisted, + "AnyOfDiscriminatedDecoder", vec![ Expr::Lit(Lit::Str(Str { span: DUMMY_SP, value: discriminator.clone().into(), raw: None, })), - self.hoist_expr(hoisted, extra_obj), + extra_obj, ], - ) + )) } fn maybe_decode_any_of_discriminated( &self, flat_values: &BTreeSet, - required: Required, + hoisted: &mut Vec, ) -> Option { let all_objects_without_rest = flat_values @@ -352,7 +228,6 @@ impl DecoderFnGenerator<'_> { .collect::>(); return Some(self.decode_any_of_discriminated( - required, discriminator, discriminator_strings, object_vs, @@ -378,10 +253,59 @@ impl DecoderFnGenerator<'_> { }) } + fn decode_bound(hoisted: Expr) -> Expr { + let member = Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: hoisted.clone().into(), + prop: MemberProp::Ident(Ident { + span: DUMMY_SP, + sym: "decode".into(), + optional: false, + }), + }); + let bind_member = Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: member.into(), + prop: MemberProp::Ident(Ident { + span: DUMMY_SP, + sym: "bind".into(), + optional: false, + }), + }); + Expr::Call(CallExpr { + span: DUMMY_SP, + callee: Callee::Expr(bind_member.into()), + args: vec![hoisted.into()], + type_args: None, + }) + } + + fn new_hoisted_decoder( + &self, + hoisted: &mut Vec, + class: &str, + args: Vec, + ) -> Expr { + let new_expr = Expr::New(NewExpr { + span: DUMMY_SP, + callee: Box::new(SwcBuilder::ident_expr(class)), + args: Some( + args.into_iter() + .map(|it| ExprOrSpread { + spread: None, + expr: it.into(), + }) + .collect(), + ), + type_args: None, + }); + self.hoist_expr(hoisted, new_expr) + } + fn maybe_decode_any_of_consts( &self, flat_values: &BTreeSet, - required: Required, + hoisted: &mut Vec, ) -> Option { let all_consts = flat_values @@ -396,35 +320,28 @@ impl DecoderFnGenerator<'_> { }) .collect(); - let consts = self.hoist_expr( - hoisted, - Expr::Array(ArrayLit { - span: DUMMY_SP, - elems: consts - .into_iter() - .map(|it| { - Some(ExprOrSpread { - spread: None, - expr: it.into(), - }) + let consts = Expr::Array(ArrayLit { + span: DUMMY_SP, + elems: consts + .into_iter() + .map(|it| { + Some(ExprOrSpread { + spread: None, + expr: it.into(), }) - .collect(), - }), - ); - return Some(Self::decode_call_extra( - "decodeAnyOfConsts", - required, + }) + .collect(), + }); + + return Some(Self::decode_bound(self.new_hoisted_decoder( + hoisted, + "AnyOfConstsDecoder", vec![consts], - )); + ))); } None } - fn decode_any_of( - &self, - vs: &BTreeSet, - required: Required, - hoisted: &mut Vec, - ) -> Expr { + fn decode_any_of(&self, vs: &BTreeSet, hoisted: &mut Vec) -> Expr { if vs.is_empty() { panic!("empty anyOf is not allowed") } @@ -434,51 +351,42 @@ impl DecoderFnGenerator<'_> { .flat_map(|it| self.extract_union(it)) .collect::>(); - if let Some(consts) = self.maybe_decode_any_of_consts(&flat_values, required, hoisted) { + if let Some(consts) = self.maybe_decode_any_of_consts(&flat_values, hoisted) { return consts; } - if let Some(discriminated) = - self.maybe_decode_any_of_discriminated(&flat_values, required, hoisted) - { + if let Some(discriminated) = self.maybe_decode_any_of_discriminated(&flat_values, hoisted) { return discriminated; } - self.decode_union_or_intersection("decodeAnyOf", required, vs, hoisted) + self.decode_union_or_intersection("AnyOfDecoder", vs, hoisted) } - fn decode_expr( - &self, - schema: &JsonSchema, - required: Required, - hoisted: &mut Vec, - ) -> Expr { - match schema { + fn decode_expr(&self, schema: &JsonSchema, hoisted: &mut Vec) -> Expr { + let call = match schema { JsonSchema::StNot(_) => { unreachable!("should not create decoders for semantic types") } - JsonSchema::StNever => Self::decode_call("decodeNever", required), - JsonSchema::AnyArrayLike => self.decode_expr( - &JsonSchema::Array(JsonSchema::Any.into()), - required, + JsonSchema::StNever => SwcBuilder::ident_expr("decodeNever"), + JsonSchema::AnyArrayLike => { + self.decode_expr(&JsonSchema::Array(JsonSchema::Any.into()), hoisted) + } + JsonSchema::Null => SwcBuilder::ident_expr("decodeNull"), + JsonSchema::Boolean => SwcBuilder::ident_expr("decodeBoolean"), + JsonSchema::String => SwcBuilder::ident_expr("decodeString"), + JsonSchema::Number => SwcBuilder::ident_expr("decodeNumber"), + JsonSchema::Any => SwcBuilder::ident_expr("decodeAny"), + JsonSchema::StringWithFormat(format) => Self::decode_bound(self.new_hoisted_decoder( hoisted, - ), - JsonSchema::Null => Self::decode_call("decodeNull", required), - JsonSchema::Boolean => Self::decode_call("decodeBoolean", required), - JsonSchema::String => Self::decode_call("decodeString", required), - JsonSchema::Number => Self::decode_call("decodeNumber", required), - JsonSchema::Any => Self::decode_call("decodeAny", required), - JsonSchema::StringWithFormat(format) => Self::decode_call_extra( - "decodeStringWithFormat", - required, + "StringWithFormatDecoder", vec![Expr::Lit(Lit::Str(Str { span: DUMMY_SP, value: format.to_string().into(), raw: None, }))], - ), - JsonSchema::Ref(r_name) => Self::decode_ref(r_name, required), + )), + JsonSchema::Ref(r_name) => Self::decode_ref(r_name), JsonSchema::Object { vs, rest } => { let obj_to_hoist = Expr::Object(ObjectLit { span: DUMMY_SP, @@ -491,30 +399,39 @@ impl DecoderFnGenerator<'_> { value: key.clone().into(), raw: None, }), - value: Box::new(Self::make_cb(match value { + value: Box::new(match value { Optionality::Optional(schema) => { - self.decode_expr(schema, Required::Known(false), hoisted) + let nullable_schema = &JsonSchema::AnyOf( + vec![JsonSchema::Null, schema.clone()] + .into_iter() + .collect(), + ); + self.decode_expr(nullable_schema, hoisted) } Optionality::Required(schema) => { - self.decode_expr(schema, Required::Known(true), hoisted) + self.decode_expr(schema, hoisted) } - })), + }), }))) }) .collect(), }); - let mut extra = vec![self.hoist_expr(hoisted, obj_to_hoist)]; + let mut extra = vec![obj_to_hoist]; if let Some(rest) = rest { - let rest = self.decode_expr(rest, Required::Known(false), hoisted); - extra.push(Self::make_cb(rest)); + let rest = self.decode_expr(rest, hoisted); + extra.push(rest); } - Self::decode_call_extra("decodeObject", required, extra) + Self::decode_bound(self.new_hoisted_decoder(hoisted, "ObjectDecoder", extra)) } JsonSchema::Array(ty) => { - let decoding = self.decode_expr(ty, Required::Known(true), hoisted); - let decoding = self.hoist_expr(hoisted, Self::make_cb(decoding)); - Self::decode_call_extra("decodeArray", required, vec![decoding]) + let decoding = self.decode_expr(ty, hoisted); + + Self::decode_bound(self.new_hoisted_decoder( + hoisted, + "ArrayDecoder", + vec![decoding], + )) } JsonSchema::Tuple { prefix_items, @@ -537,12 +454,7 @@ impl DecoderFnGenerator<'_> { .map(|it| { Some(ExprOrSpread { spread: None, - expr: Self::make_cb(self.decode_expr( - it, - Required::Known(true), - hoisted, - )) - .into(), + expr: self.decode_expr(it, hoisted).into(), }) }) .collect(), @@ -558,11 +470,7 @@ impl DecoderFnGenerator<'_> { optional: false, }), value: Box::new(match items { - Some(v) => Self::make_cb(self.decode_expr( - v, - Required::Known(true), - hoisted, - )), + Some(v) => self.decode_expr(v, hoisted), None => Expr::Lit(Lit::Null(Null { span: DUMMY_SP })), }), }) @@ -571,30 +479,28 @@ impl DecoderFnGenerator<'_> { ], }); - Self::decode_call_extra( - "decodeTuple", - required, - vec![self.hoist_expr(hoisted, tpl_extra)], - ) - } - JsonSchema::AnyOf(vs) => self.decode_any_of(vs, required, hoisted), - JsonSchema::AllOf(vs) => { - self.decode_union_or_intersection("decodeAllOf", required, vs, hoisted) + Self::decode_bound(self.new_hoisted_decoder( + hoisted, + "TupleDecoder", + vec![tpl_extra], + )) } - JsonSchema::Const(json) => Self::decode_call_extra( - "decodeConst", - required, + JsonSchema::AnyOf(vs) => self.decode_any_of(vs, hoisted), + JsonSchema::AllOf(vs) => self.decode_union_or_intersection("AllOfDecoder", vs, hoisted), + JsonSchema::Const(json) => Self::decode_bound(self.new_hoisted_decoder( + hoisted, + "ConstDecoder", vec![json.clone().to_json().to_expr()], - ), - JsonSchema::Codec(format) => Self::decode_call_extra( - "decodeCodec", - required, + )), + JsonSchema::Codec(format) => Self::decode_bound(self.new_hoisted_decoder( + hoisted, + "CodecDecoder", vec![Expr::Lit(Lit::Str(Str { span: DUMMY_SP, value: format.to_string().into(), raw: None, }))], - ), + )), JsonSchema::TplLitType(items) => { let mut regex_exp = String::new(); @@ -602,9 +508,9 @@ impl DecoderFnGenerator<'_> { regex_exp.push_str(&item.regex_expr()); } - Self::decode_call_extra( - "decodeRegex", - required, + Self::decode_bound(self.new_hoisted_decoder( + hoisted, + "RegexDecoder", vec![ Expr::Lit(Lit::Regex(Regex { span: DUMMY_SP, @@ -617,10 +523,12 @@ impl DecoderFnGenerator<'_> { raw: None, })), ], - ) + )) } - JsonSchema::Function => Self::decode_call("decodeFunction", required), - } + JsonSchema::Function => SwcBuilder::ident_expr("decodeFunction"), + }; + + call } fn fn_decoder_from_schema( @@ -650,27 +558,6 @@ impl DecoderFnGenerator<'_> { type_ann: None, }), }, - Param { - span: DUMMY_SP, - decorators: vec![], - pat: Pat::Assign(AssignPat { - span: DUMMY_SP, - left: Pat::Ident(BindingIdent { - id: Ident { - span: DUMMY_SP, - sym: "required".into(), - optional: false, - }, - type_ann: None, - }) - .into(), - right: Expr::Lit(Lit::Bool(Bool { - span: DUMMY_SP, - value: true, - })) - .into(), - }), - }, ], decorators: vec![], span: DUMMY_SP, @@ -678,11 +565,24 @@ impl DecoderFnGenerator<'_> { span: DUMMY_SP, stmts: vec![Stmt::Return(ReturnStmt { span: DUMMY_SP, - arg: Some(Box::new(self.decode_expr( - schema, - Required::FromArgs, - hoisted, - ))), + arg: Some(Box::new(Expr::Call(CallExpr { + span: DUMMY_SP, + callee: Callee::Expr(Box::new(Expr::Paren(ParenExpr { + span: DUMMY_SP, + expr: Box::new(self.decode_expr(schema, hoisted)), + }))), + args: vec![ + ExprOrSpread { + spread: None, + expr: SwcBuilder::ident_expr("ctx").into(), + }, + ExprOrSpread { + spread: None, + expr: SwcBuilder::ident_expr("input").into(), + }, + ], + type_args: None, + }))), })], } .into(), @@ -706,3 +606,17 @@ pub fn from_schema( } .fn_decoder_from_schema(schema, hoisted) } + +#[must_use] +pub fn from_schema_expr( + schema: &JsonSchema, + validators: &Vec, + hoisted: &mut Vec, + name: &str, +) -> Expr { + DecoderFnGenerator { + validators, + name: name.to_owned(), + } + .decode_expr(schema, hoisted) +} diff --git a/packages/beff-core/src/print/printer.rs b/packages/beff-core/src/print/printer.rs index f320797f..565f9c26 100644 --- a/packages/beff-core/src/print/printer.rs +++ b/packages/beff-core/src/print/printer.rs @@ -8,8 +8,8 @@ use anyhow::{anyhow, Result}; use serde::{Deserialize, Serialize}; use swc_common::DUMMY_SP; use swc_ecma_ast::{ - BindingIdent, Decl, Expr, FnDecl, FnExpr, Ident, KeyValueProp, ModuleItem, ObjectLit, Pat, - Prop, PropName, PropOrSpread, Stmt, Str, VarDecl, VarDeclKind, VarDeclarator, + BindingIdent, Decl, Expr, FnDecl, Ident, KeyValueProp, ModuleItem, ObjectLit, Pat, Prop, + PropName, PropOrSpread, Stmt, Str, VarDecl, VarDeclKind, VarDeclarator, }; pub fn const_decl(name: &str, init: Expr) -> ModuleItem { @@ -56,16 +56,12 @@ fn build_decoders_expr( .map(|decoder| { ( decoder.exported_name.clone(), - Expr::Fn(FnExpr { - ident: None, - function: decoder::from_schema( - &decoder.schema, - validators, - hoisted, - &decoder.exported_name, - ) - .into(), - }), + decoder::from_schema_expr( + &decoder.schema, + validators, + hoisted, + &decoder.exported_name, + ), ) }) .collect(); @@ -180,9 +176,9 @@ impl ToWritableModules for ExtractResult { let built_st = const_decl("buildParsersInput", decoders_expr); js_built_parsers = Some(emit_module( - vec![built_st] + acc_hoisted .into_iter() - .chain(acc_hoisted.into_iter()) + .chain(vec![built_st].into_iter()) .collect(), "\n", )?); diff --git a/packages/beff-core/tests/snapshots/print_parser__tests__ok_discriminated_union.snap b/packages/beff-core/tests/snapshots/print_parser__tests__ok_discriminated_union.snap index 4a833ec4..82de46e8 100644 --- a/packages/beff-core/tests/snapshots/print_parser__tests__ok_discriminated_union.snap +++ b/packages/beff-core/tests/snapshots/print_parser__tests__ok_discriminated_union.snap @@ -2,30 +2,32 @@ source: packages/beff-core/tests/print_parser.rs expression: "decoder(r#\"\n export type DiscriminatedUnion4 =\n | {\n type: \"a\";\n a: {\n subType: \"a1\";\n a1: string;\n };\n }\n | {\n type: \"a\";\n a: {\n subType: \"a2\";\n a2: string;\n };\n };\n parse.buildParsers<{ DiscriminatedUnion4: DiscriminatedUnion4 }>();\n \"#)" --- -function DecodeDiscriminatedUnion4(ctx, input, required = true) { - return decodeAnyOfDiscriminated(ctx, input, required, "type", hoisted_DiscriminatedUnion4_5); +function DecodeDiscriminatedUnion4(ctx, input) { + return (hoisted_DiscriminatedUnion4_7.decode.bind(hoisted_DiscriminatedUnion4_7))(ctx, input); } const validators = { DiscriminatedUnion4: DecodeDiscriminatedUnion4 }; -const hoisted_DiscriminatedUnion4_0 = { - "a1": (ctx, input)=>(decodeString(ctx, input, true)), - "subType": (ctx, input)=>(decodeConst(ctx, input, true, "a1")) -}; -const hoisted_DiscriminatedUnion4_1 = { - "a": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion4_0)) -}; -const hoisted_DiscriminatedUnion4_2 = { - "a2": (ctx, input)=>(decodeString(ctx, input, true)), - "subType": (ctx, input)=>(decodeConst(ctx, input, true, "a2")) -}; -const hoisted_DiscriminatedUnion4_3 = { - "a": (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion4_2)) -}; -const hoisted_DiscriminatedUnion4_4 = [ - (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion4_1)), - (ctx, input)=>(decodeObject(ctx, input, true, hoisted_DiscriminatedUnion4_3)) -]; -const hoisted_DiscriminatedUnion4_5 = { - "a": (ctx, input)=>(decodeAnyOf(ctx, input, true, hoisted_DiscriminatedUnion4_4)) -}; +const hoisted_DiscriminatedUnion4_0 = new ConstDecoder("a1"); +const hoisted_DiscriminatedUnion4_1 = new ObjectDecoder({ + "a1": decodeString, + "subType": hoisted_DiscriminatedUnion4_0.decode.bind(hoisted_DiscriminatedUnion4_0) +}); +const hoisted_DiscriminatedUnion4_2 = new ObjectDecoder({ + "a": hoisted_DiscriminatedUnion4_1.decode.bind(hoisted_DiscriminatedUnion4_1) +}); +const hoisted_DiscriminatedUnion4_3 = new ConstDecoder("a2"); +const hoisted_DiscriminatedUnion4_4 = new ObjectDecoder({ + "a2": decodeString, + "subType": hoisted_DiscriminatedUnion4_3.decode.bind(hoisted_DiscriminatedUnion4_3) +}); +const hoisted_DiscriminatedUnion4_5 = new ObjectDecoder({ + "a": hoisted_DiscriminatedUnion4_4.decode.bind(hoisted_DiscriminatedUnion4_4) +}); +const hoisted_DiscriminatedUnion4_6 = new AnyOfDecoder([ + hoisted_DiscriminatedUnion4_2.decode.bind(hoisted_DiscriminatedUnion4_2), + hoisted_DiscriminatedUnion4_5.decode.bind(hoisted_DiscriminatedUnion4_5) +]); +const hoisted_DiscriminatedUnion4_7 = new AnyOfDiscriminatedDecoder("type", { + "a": hoisted_DiscriminatedUnion4_6.decode.bind(hoisted_DiscriminatedUnion4_6) +}); diff --git a/packages/beff-wasm/bundled-code/build-parsers.js b/packages/beff-wasm/bundled-code/build-parsers.js index 3cbef07b..bf329ac8 100644 --- a/packages/beff-wasm/bundled-code/build-parsers.js +++ b/packages/beff-wasm/bundled-code/build-parsers.js @@ -2,8 +2,7 @@ //@ts-check function buildParsers(args) { - - const customFormats = args?.customFormats ?? {} + const customFormats = args?.customFormats ?? {}; //@ts-ignore for (const k of RequiredCustomFormats) { if (customFormats[k] == null) { @@ -17,7 +16,6 @@ function buildParsers(args) { registerCustomFormatter(k, v); }); - let decoders = {}; //@ts-ignore Object.keys(buildParsersInput).forEach((k) => { @@ -43,16 +41,19 @@ function buildParsers(args) { const error = new Error(`Failed to parse ${k}`); //@ts-ignore error.errors = safe.errors; - throw error + throw error; }; const zod = () => { //@ts-ignore - return z.custom(data => safeParse(data).success, val => { - const errors = safeParse(val).errors; - //@ts-ignore - return printErrors(errors, []) - }) - } + return z.custom( + (data) => safeParse(data).success, + (val) => { + const errors = safeParse(val).errors; + //@ts-ignore + return printErrors(errors, []); + } + ); + }; decoders[k] = { parse, safeParse, diff --git a/packages/beff-wasm/bundled-code/build-schema.js b/packages/beff-wasm/bundled-code/build-schema.js index da454338..ab78c706 100644 --- a/packages/beff-wasm/bundled-code/build-schema.js +++ b/packages/beff-wasm/bundled-code/build-schema.js @@ -1,6 +1,6 @@ /* eslint-disable no-undef */ //@ts-check function buildSchemas() { - //@ts-ignore - return jsonSchema -} \ No newline at end of file + //@ts-ignore + return jsonSchema; +} diff --git a/packages/beff-wasm/bundled-code/decoders.js b/packages/beff-wasm/bundled-code/decoders.js index a926e062..6b6309c9 100644 --- a/packages/beff-wasm/bundled-code/decoders.js +++ b/packages/beff-wasm/bundled-code/decoders.js @@ -1,7 +1,7 @@ /* eslint-disable */ //@ts-check -const customFormatters = {} +const customFormatters = {}; function registerCustomFormatter(name, validator) { customFormatters[name] = validator; @@ -42,70 +42,71 @@ function buildUnionError(received, ctx, errors) { }); } -function decodeObject(ctx, input, required, data, additionalPropsValidator = null) { - if (!required && input == null) { - return input; +class ObjectDecoder { + constructor(data, additionalPropsValidator = null) { + this.data = data; + this.additionalPropsValidator = additionalPropsValidator; } - const disallowExtraProperties = ctx?.disallowExtraProperties ?? false; + decode(ctx, input) { + const disallowExtraProperties = ctx?.disallowExtraProperties ?? false; - const allowedExtraProperties = ctx.allowedExtraProperties__ ?? [] + const allowedExtraProperties = ctx.allowedExtraProperties__ ?? []; - if (typeof input === "object" && !Array.isArray(input) && input !== null) { - const acc = {}; - for (const [k, v] of Object.entries(data)) { - pushPath(ctx, k); - acc[k] = v(ctx, input[k]); - popPath(ctx); - } + if (typeof input === "object" && !Array.isArray(input) && input !== null) { + const acc = {}; + for (const [k, v] of Object.entries(this.data)) { + pushPath(ctx, k); + acc[k] = v(ctx, input[k]); + popPath(ctx); + } - if (additionalPropsValidator != null) { - for (const [k, v] of Object.entries(input)) { - if (acc[k] == null) { - pushPath(ctx, k); - //@ts-ignore - acc[k] = additionalPropsValidator(ctx, v); - popPath(ctx); + if (this.additionalPropsValidator != null) { + for (const [k, v] of Object.entries(input)) { + if (acc[k] == null) { + pushPath(ctx, k); + acc[k] = this.additionalPropsValidator(ctx, v); + popPath(ctx); + } } } - } - if (disallowExtraProperties) { - for (const k of Object.keys(input)) { - if (acc[k] == null && allowedExtraProperties.indexOf(k) == -1) { - pushPath(ctx, k); - buildError(input[k], ctx, "extra property"); - popPath(ctx); + if (disallowExtraProperties) { + for (const k of Object.keys(input)) { + if (acc[k] == null && allowedExtraProperties.indexOf(k) == -1) { + pushPath(ctx, k); + buildError(input[k], ctx, "extra property"); + popPath(ctx); + } } } - } - return acc; + return acc; + } + return buildError(input, ctx, "expected object"); } - return buildError(input, ctx, "expected object"); } -function decodeArray(ctx, input, required, data) { - if (!required && input == null) { - return input; +class ArrayDecoder { + constructor(data) { + this.data = data; } - if (Array.isArray(input)) { - const acc = []; - for (let i = 0; i < input.length; i++) { - const v = input[i]; - pushPath(ctx, "[" + i + "]"); - acc.push(data(ctx, v)); - popPath(ctx); + + decode(ctx, input) { + if (Array.isArray(input)) { + const acc = []; + for (let i = 0; i < input.length; i++) { + const v = input[i]; + pushPath(ctx, "[" + i + "]"); + acc.push(this.data(ctx, v)); + popPath(ctx); + } + return acc; } - return acc; + return buildError(input, ctx, "expected array"); } - return buildError(input, ctx, "expected array"); } -function decodeString(ctx, input, required) { - if (!required && input == null) { - return input; - } - +function decodeString(ctx, input) { if (typeof input === "string") { return input; } @@ -113,10 +114,7 @@ function decodeString(ctx, input, required) { return buildError(input, ctx, "expected string"); } -function decodeNumber(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeNumber(ctx, input) { if (typeof input === "number") { return input; } @@ -127,214 +125,236 @@ function decodeNumber(ctx, input, required) { return buildError(input, ctx, "expected number"); } -function decodeFunction(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeFunction(ctx, input) { if (typeof input === "function") { return input; } return buildError(input, ctx, "expected function"); } - -function decodeCodec(ctx, input, required, codec) { - if (!required && input == null) { - return input; - } - switch (codec) { - case "Codec::ISO8061": { - const d = new Date(input); - if (isNaN(d.getTime())) { - return buildError(input, ctx, "expected ISO8061 date"); - } - return d; - } - case "Codec::BigInt": { - if (typeof input === "bigint") { - return input; - } - if (typeof input === "number") { - return BigInt(input); +class CodecDecoder { + constructor(codec) { + this.codec = codec; + } + decode(ctx, input) { + switch (this.codec) { + case "Codec::ISO8061": { + const d = new Date(input); + if (isNaN(d.getTime())) { + return buildError(input, ctx, "expected ISO8061 date"); + } + return d; } - if (typeof input === "string") { - try { + case "Codec::BigInt": { + if (typeof input === "bigint") { + return input; + } + if (typeof input === "number") { return BigInt(input); - } catch (e) { - //noop } + if (typeof input === "string") { + try { + return BigInt(input); + } catch (e) { + //noop + } + } + return buildError(input, ctx, "expected bigint"); } - return buildError(input, ctx, "expected bigint"); } + return buildError(input, ctx, "codec " + this.codec + " not implemented"); } - return buildError(input, ctx, "codec " + codec + " not implemented"); } -function decodeStringWithFormat(ctx, input, required, format) { - if (!required && input == null) { - return input; - } - if (typeof input !== "string") { - return buildError(input, ctx, "expected string with format " + JSON.stringify(format)); +class StringWithFormatDecoder { + constructor(format) { + this.format = format; } - const validator = customFormatters[format]; + decode(ctx, input) { + if (typeof input !== "string") { + return buildError(input, ctx, "expected string with format " + JSON.stringify(this.format)); + } - if (validator == null) { - return buildError(input, ctx, "format " + JSON.stringify(format) + " not implemented"); - } + const validator = customFormatters[this.format]; - const isOk = validator(input); - if (isOk) { - return input; - } - return buildError(input, ctx, "expected string with format " + JSON.stringify(format)); -} + if (validator == null) { + return buildError(input, ctx, "format " + JSON.stringify(this.format) + " not implemented"); + } -function decodeAnyOfDiscriminated(ctx, input, required, discriminator, mapping) { - if (!required && input == null) { - return input; + const isOk = validator(input); + if (isOk) { + return input; + } + return buildError(input, ctx, "expected string with format " + JSON.stringify(this.format)); } - const d = input[discriminator]; - if (d == null) { - return buildError(input, ctx, "expected discriminator key " + JSON.stringify(discriminator)) - } - const v = mapping[d]; - if (v == null) { - pushPath(ctx, discriminator); - const err = buildError(d, ctx, "expected one of " + Object.keys(mapping).map(it => JSON.stringify(it)).join(", ")); - popPath(ctx); - return err; - } - const prevAllow = (ctx.allowedExtraProperties__ ?? []); - ctx.allowedExtraProperties__ = [...prevAllow, discriminator] - const out = v(ctx, input); - ctx.allowedExtraProperties__ = prevAllow; - return { ...out, [discriminator]: d }; } - -function decodeAnyOfConsts(ctx, input, required, consts) { - if (!required && input == null) { - return input; +class AnyOfDiscriminatedDecoder { + constructor(discriminator, mapping) { + this.discriminator = discriminator; + this.mapping = mapping; } - for (const c of consts) { - if (input === c) { - return c; + + decode(ctx, input) { + const d = input[this.discriminator]; + if (d == null) { + return buildError(input, ctx, "expected discriminator key " + JSON.stringify(this.discriminator)); + } + const v = this.mapping[d]; + if (v == null) { + pushPath(ctx, this.discriminator); + const err = buildError( + d, + ctx, + "expected one of " + + Object.keys(this.mapping) + .map((it) => JSON.stringify(it)) + .join(", ") + ); + popPath(ctx); + return err; } + const prevAllow = ctx.allowedExtraProperties__ ?? []; + ctx.allowedExtraProperties__ = [...prevAllow, this.discriminator]; + const out = v(ctx, input); + ctx.allowedExtraProperties__ = prevAllow; + return { ...out, [this.discriminator]: d }; } - return buildError(input, ctx, "expected one of " + consts.map(it => JSON.stringify(it)).join(", ")); } -function decodeAnyOf(ctx, input, required, vs) { - if (!required && input == null) { - return input; - } - let accErrors = []; - for (const v of vs) { - const validatorCtx = {}; - const newValue = v(validatorCtx, input); - if (validatorCtx.errors == null) { - return newValue; +class AnyOfConstsDecoder { + constructor(consts) { + this.consts = consts; + } + decode(ctx, input) { + for (const c of this.consts) { + if (input === c) { + return c; + } } - accErrors.push(...(validatorCtx.errors ?? [])); + return buildError( + input, + ctx, + "expected one of " + this.consts.map((it) => JSON.stringify(it)).join(", ") + ); } - return buildUnionError(input, ctx, accErrors); } -function decodeAllOf(ctx, input, required, vs) { - if (!required && input == null) { - return input; - } - let acc = {}; - let foundOneObject = false; - let allObjects = true; - for (const v of vs) { - const newValue = v(ctx, input); - const isObj = typeof newValue === "object"; - allObjects = allObjects && isObj; - if (isObj) { - foundOneObject = true; - acc = { ...acc, ...newValue }; + +class AnyOfDecoder { + constructor(vs) { + this.vs = vs; + } + decode(ctx, input) { + let accErrors = []; + for (const v of this.vs) { + const validatorCtx = {}; + const newValue = v(validatorCtx, input); + if (validatorCtx.errors == null) { + return newValue; + } + accErrors.push(...(validatorCtx.errors ?? [])); } + return buildUnionError(input, ctx, accErrors); } - if (foundOneObject && allObjects) { - return acc; - } - return input; } -function decodeTuple(ctx, input, required, vs) { - if (!required && input == null) { +class AllOfDecoder { + constructor(vs) { + this.vs = vs; + } + decode(ctx, input) { + let acc = {}; + let foundOneObject = false; + let allObjects = true; + for (const v of this.vs) { + const newValue = v(ctx, input); + const isObj = typeof newValue === "object"; + allObjects = allObjects && isObj; + if (isObj) { + foundOneObject = true; + acc = { ...acc, ...newValue }; + } + } + if (foundOneObject && allObjects) { + return acc; + } return input; } - if (Array.isArray(input)) { - const acc = []; - let idx = 0; - for (const v of vs.prefix) { - pushPath(ctx, "[" + idx + "]"); - const newValue = v(ctx, input[idx]); - popPath(ctx); - acc.push(newValue); - idx++; - } - if (vs.items != null) { - for (let i = idx; i < input.length; i++) { - const v = input[i]; - pushPath(ctx, "[" + i + "]"); - acc.push(vs.items(ctx, v)); +} +class TupleDecoder { + constructor(vs) { + this.vs = vs; + } + decode(ctx, input) { + if (Array.isArray(input)) { + const acc = []; + let idx = 0; + for (const v of this.vs.prefix) { + pushPath(ctx, "[" + idx + "]"); + const newValue = v(ctx, input[idx]); popPath(ctx); + acc.push(newValue); + idx++; } - } else { - if (input.length > idx) { - return buildError(input, ctx, "tuple has too many items"); + if (this.vs.items != null) { + for (let i = idx; i < input.length; i++) { + const v = input[i]; + pushPath(ctx, "[" + i + "]"); + acc.push(this.vs.items(ctx, v)); + popPath(ctx); + } + } else { + if (input.length > idx) { + return buildError(input, ctx, "tuple has too many items"); + } } + return acc; } - return acc; + return buildError(input, ctx, "expected tuple"); } - return buildError(input, ctx, "expected tuple"); } -function decodeBoolean(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeBoolean(ctx, input) { if (typeof input === "boolean") { return input; } return buildError(input, ctx, "expected boolean"); } -function decodeAny(ctx, input, required) { +function decodeAny(ctx, input) { return input; } -function decodeNull(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeNull(ctx, input) { if (input == null) { - return null; - } - return buildError(input, ctx, "expected null"); -} -function decodeNever(ctx, input, required) { - if (!required && input == null) { return input; } + return buildError(input, ctx, "expected nullish value"); +} +function decodeNever(ctx, input) { return buildError(input, ctx, "never"); } -function decodeConst(ctx, input, required, constValue) { - if (!required && input == null) { - return input; + +class ConstDecoder { + constructor(value) { + this.value = value; } - if (input == constValue) { - return constValue; + + decode(ctx, input) { + if (input == this.value) { + return this.value; + } + return buildError(input, ctx, "expected " + JSON.stringify(this.value)); } - return buildError(input, ctx, "expected " + JSON.stringify(constValue)); } -function decodeRegex(ctx, input, required, regex, description) { - if (!required && input == null) { - return input; +class RegexDecoder { + constructor(regex, description) { + this.regex = regex; + this.description = description; } - if (typeof input === "string") { - if (regex.test(input)) { - return input; + + decode(ctx, input) { + if (typeof input === "string") { + if (this.regex.test(input)) { + return input; + } } + return buildError(input, ctx, "expected string matching " + this.description); } - return buildError(input, ctx, "expected string matching " + description); -} \ No newline at end of file +} diff --git a/packages/beff-wasm/bundled-code/parser.d.ts b/packages/beff-wasm/bundled-code/parser.d.ts index 3629c0ba..d00ffa67 100644 --- a/packages/beff-wasm/bundled-code/parser.d.ts +++ b/packages/beff-wasm/bundled-code/parser.d.ts @@ -1,7 +1,7 @@ import { BuildParserFunction } from "@beff/cli"; declare const _exports: { - buildParsers: BuildParserFunction + buildParsers: BuildParserFunction; }; export default _exports; diff --git a/packages/beff-wasm/bundled-code/schema.d.ts b/packages/beff-wasm/bundled-code/schema.d.ts index c357ee23..6c11f83d 100644 --- a/packages/beff-wasm/bundled-code/schema.d.ts +++ b/packages/beff-wasm/bundled-code/schema.d.ts @@ -1,7 +1,7 @@ import { BuildSchemaFunction } from "@beff/cli"; declare const _exports: { - buildSchemas: BuildSchemaFunction + buildSchemas: BuildSchemaFunction; }; export default _exports; diff --git a/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/parser.d.ts b/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/parser.d.ts index 6edf910a..f7182b08 100644 --- a/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/parser.d.ts +++ b/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/parser.d.ts @@ -3,7 +3,7 @@ import { BuildParserFunction } from "@beff/cli"; declare const _exports: { - buildParsers: BuildParserFunction + buildParsers: BuildParserFunction; }; export default _exports; diff --git a/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/parser.js b/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/parser.js index b08621fb..04beeede 100644 --- a/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/parser.js +++ b/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/parser.js @@ -4,42 +4,27 @@ import {printErrors} from '@beff/client'; import {z} from 'zod'; -import validatorsMod from "./validators.js"; const { decodeObject, decodeArray, decodeString, decodeNumber, decodeCodec, decodeFunction, decodeStringWithFormat, decodeAnyOf, decodeAllOf, decodeBoolean, decodeAny, decodeTuple, decodeNull, decodeNever, decodeConst, registerCustomFormatter, validators, c } = validatorsMod; +import validatorsMod from "./validators.js"; const { ObjectDecoder, ArrayDecoder, decodeString, decodeNumber, CodecDecoder, decodeFunction, StringWithFormatDecoder, AnyOfDecoder, AllOfDecoder, decodeBoolean, decodeAny, TupleDecoder, decodeNull, decodeNever, RegexDecoder, ConstDecoder, registerCustomFormatter, AnyOfConstsDecoder, AnyOfDiscriminatedDecoder, validators, c } = validatorsMod; const RequiredCustomFormats = ["password","StartsWithA"]; +const hoisted_Users_0 = new ArrayDecoder(validators.User); +const hoisted_float_1 = new ConstDecoder(123.456); +const hoisted_int_2 = new ConstDecoder(123); const buildParsersInput = { - "NotPublicRenamed": function(ctx, input, required = true) { - return validators.NotPublic(ctx, input, required); - }, - "Password": function(ctx, input, required = true) { - return validators.Password(ctx, input, required); - }, - "StartsWithA": function(ctx, input, required = true) { - return validators.StartsWithA(ctx, input, required); - }, - "User": function(ctx, input, required = true) { - return validators.User(ctx, input, required); - }, - "Users": function(ctx, input, required = true) { - return decodeArray(ctx, input, required, hoisted_Users_0); - }, - "float": function(ctx, input, required = true) { - return decodeConst(ctx, input, required, 123.456); - }, - "int": function(ctx, input, required = true) { - return decodeConst(ctx, input, required, 123); - }, - "union": function(ctx, input, required = true) { - return validators.UnionNested(ctx, input, required); - } + "NotPublicRenamed": validators.NotPublic, + "Password": validators.Password, + "StartsWithA": validators.StartsWithA, + "User": validators.User, + "Users": hoisted_Users_0.decode.bind(hoisted_Users_0), + "float": hoisted_float_1.decode.bind(hoisted_float_1), + "int": hoisted_int_2.decode.bind(hoisted_int_2), + "union": validators.UnionNested }; -const hoisted_Users_0 = (ctx, input)=>(validators.User(ctx, input, true)); function buildParsers(args) { - - const customFormats = args?.customFormats ?? {} + const customFormats = args?.customFormats ?? {}; for (const k of RequiredCustomFormats) { if (customFormats[k] == null) { @@ -53,7 +38,6 @@ function buildParsers(args) { registerCustomFormatter(k, v); }); - let decoders = {}; Object.keys(buildParsersInput).forEach((k) => { @@ -79,16 +63,19 @@ function buildParsers(args) { const error = new Error(`Failed to parse ${k}`); error.errors = safe.errors; - throw error + throw error; }; const zod = () => { - return z.custom(data => safeParse(data).success, val => { - const errors = safeParse(val).errors; - - return printErrors(errors, []) - }) - } + return z.custom( + (data) => safeParse(data).success, + (val) => { + const errors = safeParse(val).errors; + + return printErrors(errors, []); + } + ); + }; decoders[k] = { parse, safeParse, diff --git a/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/validators.js b/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/validators.js index 15f38e57..bdb18a0e 100644 --- a/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/validators.js +++ b/packages/beff-wasm/fixtures/codegen-snaps/export-decoder/bff-generated/validators.js @@ -4,7 +4,7 @@ -const customFormatters = {} +const customFormatters = {}; function registerCustomFormatter(name, validator) { customFormatters[name] = validator; @@ -45,70 +45,71 @@ function buildUnionError(received, ctx, errors) { }); } -function decodeObject(ctx, input, required, data, additionalPropsValidator = null) { - if (!required && input == null) { - return input; +class ObjectDecoder { + constructor(data, additionalPropsValidator = null) { + this.data = data; + this.additionalPropsValidator = additionalPropsValidator; } - const disallowExtraProperties = ctx?.disallowExtraProperties ?? false; + decode(ctx, input) { + const disallowExtraProperties = ctx?.disallowExtraProperties ?? false; - const allowedExtraProperties = ctx.allowedExtraProperties__ ?? [] + const allowedExtraProperties = ctx.allowedExtraProperties__ ?? []; - if (typeof input === "object" && !Array.isArray(input) && input !== null) { - const acc = {}; - for (const [k, v] of Object.entries(data)) { - pushPath(ctx, k); - acc[k] = v(ctx, input[k]); - popPath(ctx); - } + if (typeof input === "object" && !Array.isArray(input) && input !== null) { + const acc = {}; + for (const [k, v] of Object.entries(this.data)) { + pushPath(ctx, k); + acc[k] = v(ctx, input[k]); + popPath(ctx); + } - if (additionalPropsValidator != null) { - for (const [k, v] of Object.entries(input)) { - if (acc[k] == null) { - pushPath(ctx, k); - - acc[k] = additionalPropsValidator(ctx, v); - popPath(ctx); + if (this.additionalPropsValidator != null) { + for (const [k, v] of Object.entries(input)) { + if (acc[k] == null) { + pushPath(ctx, k); + acc[k] = this.additionalPropsValidator(ctx, v); + popPath(ctx); + } } } - } - if (disallowExtraProperties) { - for (const k of Object.keys(input)) { - if (acc[k] == null && allowedExtraProperties.indexOf(k) == -1) { - pushPath(ctx, k); - buildError(input[k], ctx, "extra property"); - popPath(ctx); + if (disallowExtraProperties) { + for (const k of Object.keys(input)) { + if (acc[k] == null && allowedExtraProperties.indexOf(k) == -1) { + pushPath(ctx, k); + buildError(input[k], ctx, "extra property"); + popPath(ctx); + } } } - } - return acc; + return acc; + } + return buildError(input, ctx, "expected object"); } - return buildError(input, ctx, "expected object"); } -function decodeArray(ctx, input, required, data) { - if (!required && input == null) { - return input; +class ArrayDecoder { + constructor(data) { + this.data = data; } - if (Array.isArray(input)) { - const acc = []; - for (let i = 0; i < input.length; i++) { - const v = input[i]; - pushPath(ctx, "[" + i + "]"); - acc.push(data(ctx, v)); - popPath(ctx); + + decode(ctx, input) { + if (Array.isArray(input)) { + const acc = []; + for (let i = 0; i < input.length; i++) { + const v = input[i]; + pushPath(ctx, "[" + i + "]"); + acc.push(this.data(ctx, v)); + popPath(ctx); + } + return acc; } - return acc; + return buildError(input, ctx, "expected array"); } - return buildError(input, ctx, "expected array"); } -function decodeString(ctx, input, required) { - if (!required && input == null) { - return input; - } - +function decodeString(ctx, input) { if (typeof input === "string") { return input; } @@ -116,10 +117,7 @@ function decodeString(ctx, input, required) { return buildError(input, ctx, "expected string"); } -function decodeNumber(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeNumber(ctx, input) { if (typeof input === "number") { return input; } @@ -130,244 +128,267 @@ function decodeNumber(ctx, input, required) { return buildError(input, ctx, "expected number"); } -function decodeFunction(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeFunction(ctx, input) { if (typeof input === "function") { return input; } return buildError(input, ctx, "expected function"); } - -function decodeCodec(ctx, input, required, codec) { - if (!required && input == null) { - return input; +class CodecDecoder { + constructor(codec) { + this.codec = codec; } - switch (codec) { - case "Codec::ISO8061": { - const d = new Date(input); - if (isNaN(d.getTime())) { - return buildError(input, ctx, "expected ISO8061 date"); - } - return d; - } - case "Codec::BigInt": { - if (typeof input === "bigint") { - return input; - } - if (typeof input === "number") { - return BigInt(input); + decode(ctx, input) { + switch (this.codec) { + case "Codec::ISO8061": { + const d = new Date(input); + if (isNaN(d.getTime())) { + return buildError(input, ctx, "expected ISO8061 date"); + } + return d; } - if (typeof input === "string") { - try { + case "Codec::BigInt": { + if (typeof input === "bigint") { + return input; + } + if (typeof input === "number") { return BigInt(input); - } catch (e) { - } + if (typeof input === "string") { + try { + return BigInt(input); + } catch (e) { + + } + } + return buildError(input, ctx, "expected bigint"); } - return buildError(input, ctx, "expected bigint"); } + return buildError(input, ctx, "codec " + this.codec + " not implemented"); } - return buildError(input, ctx, "codec " + codec + " not implemented"); } -function decodeStringWithFormat(ctx, input, required, format) { - if (!required && input == null) { - return input; - } - if (typeof input !== "string") { - return buildError(input, ctx, "expected string with format " + JSON.stringify(format)); +class StringWithFormatDecoder { + constructor(format) { + this.format = format; } - const validator = customFormatters[format]; + decode(ctx, input) { + if (typeof input !== "string") { + return buildError(input, ctx, "expected string with format " + JSON.stringify(this.format)); + } - if (validator == null) { - return buildError(input, ctx, "format " + JSON.stringify(format) + " not implemented"); - } + const validator = customFormatters[this.format]; - const isOk = validator(input); - if (isOk) { - return input; - } - return buildError(input, ctx, "expected string with format " + JSON.stringify(format)); -} + if (validator == null) { + return buildError(input, ctx, "format " + JSON.stringify(this.format) + " not implemented"); + } -function decodeAnyOfDiscriminated(ctx, input, required, discriminator, mapping) { - if (!required && input == null) { - return input; - } - const d = input[discriminator]; - if (d == null) { - return buildError(input, ctx, "expected discriminator key " + JSON.stringify(discriminator)) - } - const v = mapping[d]; - if (v == null) { - pushPath(ctx, discriminator); - const err = buildError(d, ctx, "expected one of " + Object.keys(mapping).map(it => JSON.stringify(it)).join(", ")); - popPath(ctx); - return err; + const isOk = validator(input); + if (isOk) { + return input; + } + return buildError(input, ctx, "expected string with format " + JSON.stringify(this.format)); } - const prevAllow = (ctx.allowedExtraProperties__ ?? []); - ctx.allowedExtraProperties__ = [...prevAllow, discriminator] - const out = v(ctx, input); - ctx.allowedExtraProperties__ = prevAllow; - return { ...out, [discriminator]: d }; } - -function decodeAnyOfConsts(ctx, input, required, consts) { - if (!required && input == null) { - return input; +class AnyOfDiscriminatedDecoder { + constructor(discriminator, mapping) { + this.discriminator = discriminator; + this.mapping = mapping; } - for (const c of consts) { - if (input === c) { - return c; + + decode(ctx, input) { + const d = input[this.discriminator]; + if (d == null) { + return buildError(input, ctx, "expected discriminator key " + JSON.stringify(this.discriminator)); } + const v = this.mapping[d]; + if (v == null) { + pushPath(ctx, this.discriminator); + const err = buildError( + d, + ctx, + "expected one of " + + Object.keys(this.mapping) + .map((it) => JSON.stringify(it)) + .join(", ") + ); + popPath(ctx); + return err; + } + const prevAllow = ctx.allowedExtraProperties__ ?? []; + ctx.allowedExtraProperties__ = [...prevAllow, this.discriminator]; + const out = v(ctx, input); + ctx.allowedExtraProperties__ = prevAllow; + return { ...out, [this.discriminator]: d }; } - return buildError(input, ctx, "expected one of " + consts.map(it => JSON.stringify(it)).join(", ")); } -function decodeAnyOf(ctx, input, required, vs) { - if (!required && input == null) { - return input; - } - let accErrors = []; - for (const v of vs) { - const validatorCtx = {}; - const newValue = v(validatorCtx, input); - if (validatorCtx.errors == null) { - return newValue; +class AnyOfConstsDecoder { + constructor(consts) { + this.consts = consts; + } + decode(ctx, input) { + for (const c of this.consts) { + if (input === c) { + return c; + } } - accErrors.push(...(validatorCtx.errors ?? [])); + return buildError( + input, + ctx, + "expected one of " + this.consts.map((it) => JSON.stringify(it)).join(", ") + ); } - return buildUnionError(input, ctx, accErrors); } -function decodeAllOf(ctx, input, required, vs) { - if (!required && input == null) { - return input; - } - let acc = {}; - let foundOneObject = false; - let allObjects = true; - for (const v of vs) { - const newValue = v(ctx, input); - const isObj = typeof newValue === "object"; - allObjects = allObjects && isObj; - if (isObj) { - foundOneObject = true; - acc = { ...acc, ...newValue }; + +class AnyOfDecoder { + constructor(vs) { + this.vs = vs; + } + decode(ctx, input) { + let accErrors = []; + for (const v of this.vs) { + const validatorCtx = {}; + const newValue = v(validatorCtx, input); + if (validatorCtx.errors == null) { + return newValue; + } + accErrors.push(...(validatorCtx.errors ?? [])); } + return buildUnionError(input, ctx, accErrors); + } +} +class AllOfDecoder { + constructor(vs) { + this.vs = vs; + } + decode(ctx, input) { + let acc = {}; + let foundOneObject = false; + let allObjects = true; + for (const v of this.vs) { + const newValue = v(ctx, input); + const isObj = typeof newValue === "object"; + allObjects = allObjects && isObj; + if (isObj) { + foundOneObject = true; + acc = { ...acc, ...newValue }; + } + } + if (foundOneObject && allObjects) { + return acc; + } + return input; } - if (foundOneObject && allObjects) { - return acc; - } - return input; } -function decodeTuple(ctx, input, required, vs) { - if (!required && input == null) { - return input; +class TupleDecoder { + constructor(vs) { + this.vs = vs; } - if (Array.isArray(input)) { - const acc = []; - let idx = 0; - for (const v of vs.prefix) { - pushPath(ctx, "[" + idx + "]"); - const newValue = v(ctx, input[idx]); - popPath(ctx); - acc.push(newValue); - idx++; - } - if (vs.items != null) { - for (let i = idx; i < input.length; i++) { - const v = input[i]; - pushPath(ctx, "[" + i + "]"); - acc.push(vs.items(ctx, v)); + decode(ctx, input) { + if (Array.isArray(input)) { + const acc = []; + let idx = 0; + for (const v of this.vs.prefix) { + pushPath(ctx, "[" + idx + "]"); + const newValue = v(ctx, input[idx]); popPath(ctx); + acc.push(newValue); + idx++; } - } else { - if (input.length > idx) { - return buildError(input, ctx, "tuple has too many items"); + if (this.vs.items != null) { + for (let i = idx; i < input.length; i++) { + const v = input[i]; + pushPath(ctx, "[" + i + "]"); + acc.push(this.vs.items(ctx, v)); + popPath(ctx); + } + } else { + if (input.length > idx) { + return buildError(input, ctx, "tuple has too many items"); + } } + return acc; } - return acc; + return buildError(input, ctx, "expected tuple"); } - return buildError(input, ctx, "expected tuple"); } -function decodeBoolean(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeBoolean(ctx, input) { if (typeof input === "boolean") { return input; } return buildError(input, ctx, "expected boolean"); } -function decodeAny(ctx, input, required) { +function decodeAny(ctx, input) { return input; } -function decodeNull(ctx, input, required) { - if (!required && input == null) { - return input; - } +function decodeNull(ctx, input) { if (input == null) { - return null; - } - return buildError(input, ctx, "expected null"); -} -function decodeNever(ctx, input, required) { - if (!required && input == null) { return input; } + return buildError(input, ctx, "expected nullish value"); +} +function decodeNever(ctx, input) { return buildError(input, ctx, "never"); } -function decodeConst(ctx, input, required, constValue) { - if (!required && input == null) { - return input; + +class ConstDecoder { + constructor(value) { + this.value = value; } - if (input == constValue) { - return constValue; + + decode(ctx, input) { + if (input == this.value) { + return this.value; + } + return buildError(input, ctx, "expected " + JSON.stringify(this.value)); } - return buildError(input, ctx, "expected " + JSON.stringify(constValue)); } -function decodeRegex(ctx, input, required, regex, description) { - if (!required && input == null) { - return input; +class RegexDecoder { + constructor(regex, description) { + this.regex = regex; + this.description = description; } - if (typeof input === "string") { - if (regex.test(input)) { - return input; + + decode(ctx, input) { + if (typeof input === "string") { + if (this.regex.test(input)) { + return input; + } } + return buildError(input, ctx, "expected string matching " + this.description); } - return buildError(input, ctx, "expected string matching " + description); } -function DecodeUser(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_User_0); + +function DecodeUser(ctx, input) { + return (hoisted_User_0.decode.bind(hoisted_User_0))(ctx, input); } -function DecodeNotPublic(ctx, input, required = true) { - return decodeObject(ctx, input, required, hoisted_NotPublic_1); +function DecodeNotPublic(ctx, input) { + return (hoisted_NotPublic_1.decode.bind(hoisted_NotPublic_1))(ctx, input); } -function DecodeStartsWithA(ctx, input, required = true) { - return decodeStringWithFormat(ctx, input, required, "StartsWithA"); +function DecodeStartsWithA(ctx, input) { + return (hoisted_StartsWithA_2.decode.bind(hoisted_StartsWithA_2))(ctx, input); } -function DecodePassword(ctx, input, required = true) { - return decodeStringWithFormat(ctx, input, required, "password"); +function DecodePassword(ctx, input) { + return (hoisted_Password_3.decode.bind(hoisted_Password_3))(ctx, input); } -function DecodeA(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_A_2); +function DecodeA(ctx, input) { + return (hoisted_A_4.decode.bind(hoisted_A_4))(ctx, input); } -function DecodeB(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_B_3); +function DecodeB(ctx, input) { + return (hoisted_B_5.decode.bind(hoisted_B_5))(ctx, input); } -function DecodeD(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_D_4); +function DecodeD(ctx, input) { + return (hoisted_D_6.decode.bind(hoisted_D_6))(ctx, input); } -function DecodeE(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_E_5); +function DecodeE(ctx, input) { + return (hoisted_E_7.decode.bind(hoisted_E_7))(ctx, input); } -function DecodeUnionNested(ctx, input, required = true) { - return decodeAnyOfConsts(ctx, input, required, hoisted_UnionNested_6); +function DecodeUnionNested(ctx, input) { + return (hoisted_UnionNested_8.decode.bind(hoisted_UnionNested_8))(ctx, input); } const validators = { User: DecodeUser, @@ -380,36 +401,38 @@ const validators = { E: DecodeE, UnionNested: DecodeUnionNested }; -const hoisted_User_0 = { - "age": (ctx, input)=>(decodeNumber(ctx, input, true)), - "name": (ctx, input)=>(decodeString(ctx, input, true)) -}; -const hoisted_NotPublic_1 = { - "a": (ctx, input)=>(decodeString(ctx, input, true)) -}; -const hoisted_A_2 = [ +const hoisted_User_0 = new ObjectDecoder({ + "age": decodeNumber, + "name": decodeString +}); +const hoisted_NotPublic_1 = new ObjectDecoder({ + "a": decodeString +}); +const hoisted_StartsWithA_2 = new StringWithFormatDecoder("StartsWithA"); +const hoisted_Password_3 = new StringWithFormatDecoder("password"); +const hoisted_A_4 = new AnyOfConstsDecoder([ 1, 2 -]; -const hoisted_B_3 = [ +]); +const hoisted_B_5 = new AnyOfConstsDecoder([ 2, 3 -]; -const hoisted_D_4 = [ +]); +const hoisted_D_6 = new AnyOfConstsDecoder([ 4, 5 -]; -const hoisted_E_5 = [ +]); +const hoisted_E_7 = new AnyOfConstsDecoder([ 5, 6 -]; -const hoisted_UnionNested_6 = [ +]); +const hoisted_UnionNested_8 = new AnyOfConstsDecoder([ 1, 2, 3, 4, 5, 6 -]; +]); -export default { decodeObject, decodeArray, decodeString, decodeNumber, decodeCodec, decodeFunction, decodeStringWithFormat, decodeAnyOf, decodeAllOf, decodeBoolean, decodeAny, decodeTuple, decodeNull, decodeNever, decodeConst, registerCustomFormatter, validators }; \ No newline at end of file +export default { ObjectDecoder, ArrayDecoder, decodeString, decodeNumber, CodecDecoder, decodeFunction, StringWithFormatDecoder, AnyOfDecoder, AllOfDecoder, decodeBoolean, decodeAny, TupleDecoder, decodeNull, decodeNever, RegexDecoder, ConstDecoder, registerCustomFormatter, AnyOfConstsDecoder, AnyOfDiscriminatedDecoder, validators }; \ No newline at end of file diff --git a/packages/beff-wasm/package.json b/packages/beff-wasm/package.json index 04874afb..448555c5 100644 --- a/packages/beff-wasm/package.json +++ b/packages/beff-wasm/package.json @@ -41,7 +41,7 @@ }, "devDependencies": { "@babel/code-frame": "^7.22.13", - "@beff/cli": "workspace:^0.0.69", + "@beff/cli": "workspace:^0.0.70", "@types/babel__code-frame": "^7.0.4", "@types/node": "^20.6.2", "@types/vscode": "^1.73.0", diff --git a/packages/beff-wasm/ts-node/bundle-to-disk.ts b/packages/beff-wasm/ts-node/bundle-to-disk.ts index 8bf3a492..d3e48ac4 100644 --- a/packages/beff-wasm/ts-node/bundle-to-disk.ts +++ b/packages/beff-wasm/ts-node/bundle-to-disk.ts @@ -5,22 +5,25 @@ import { ProjectJson, ProjectModule } from "./project"; import gen from "./generated/bundle"; const decodersExported = [ - "decodeObject", - "decodeArray", + "ObjectDecoder", + "ArrayDecoder", "decodeString", "decodeNumber", - "decodeCodec", + "CodecDecoder", "decodeFunction", - "decodeStringWithFormat", - "decodeAnyOf", - "decodeAllOf", + "StringWithFormatDecoder", + "AnyOfDecoder", + "AllOfDecoder", "decodeBoolean", "decodeAny", - "decodeTuple", + "TupleDecoder", "decodeNull", "decodeNever", - "decodeConst", + "RegexDecoder", + "ConstDecoder", "registerCustomFormatter", + "AnyOfConstsDecoder", + "AnyOfDiscriminatedDecoder", ]; const esmTag = (mod: ProjectModule) => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aef8df8b..16a218f2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -55,7 +55,7 @@ importers: packages/beff-client: dependencies: '@beff/cli': - specifier: workspace:^0.0.69 + specifier: workspace:^0.0.70 version: link:../beff-cli zod: specifier: ^3.23.5 @@ -89,7 +89,7 @@ importers: specifier: ^7.22.13 version: 7.22.13 '@beff/cli': - specifier: workspace:^0.0.69 + specifier: workspace:^0.0.70 version: link:../beff-cli '@types/babel__code-frame': specifier: ^7.0.4