aboutsummaryrefslogtreecommitdiff
path: root/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/testAppNevena/Front/node_modules/ajv/lib/compile')
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/code.ts168
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/index.ts832
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/scope.ts215
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/errors.ts184
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/index.ts324
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/parse.ts411
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/serialize.ts260
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/types.ts16
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/names.ts27
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/ref_error.ts12
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/resolve.ts146
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/rules.ts50
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/util.ts213
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/applicability.ts22
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/boolSchema.ts47
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/dataType.ts229
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/defaults.ts32
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/index.ts573
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/keyword.ts171
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/subschema.ts135
20 files changed, 4067 insertions, 0 deletions
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/code.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/code.ts
new file mode 100644
index 00000000..b1770197
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/code.ts
@@ -0,0 +1,168 @@
+export abstract class _CodeOrName {
+ abstract readonly str: string
+ abstract readonly names: UsedNames
+ abstract toString(): string
+ abstract emptyStr(): boolean
+}
+
+export const IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i
+
+export class Name extends _CodeOrName {
+ readonly str: string
+ constructor(s: string) {
+ super()
+ if (!IDENTIFIER.test(s)) throw new Error("CodeGen: name must be a valid identifier")
+ this.str = s
+ }
+
+ toString(): string {
+ return this.str
+ }
+
+ emptyStr(): boolean {
+ return false
+ }
+
+ get names(): UsedNames {
+ return {[this.str]: 1}
+ }
+}
+
+export class _Code extends _CodeOrName {
+ readonly _items: readonly CodeItem[]
+ private _str?: string
+ private _names?: UsedNames
+
+ constructor(code: string | readonly CodeItem[]) {
+ super()
+ this._items = typeof code === "string" ? [code] : code
+ }
+
+ toString(): string {
+ return this.str
+ }
+
+ emptyStr(): boolean {
+ if (this._items.length > 1) return false
+ const item = this._items[0]
+ return item === "" || item === '""'
+ }
+
+ get str(): string {
+ return (this._str ??= this._items.reduce((s: string, c: CodeItem) => `${s}${c}`, ""))
+ }
+
+ get names(): UsedNames {
+ return (this._names ??= this._items.reduce((names: UsedNames, c) => {
+ if (c instanceof Name) names[c.str] = (names[c.str] || 0) + 1
+ return names
+ }, {}))
+ }
+}
+
+export type CodeItem = Name | string | number | boolean | null
+
+export type UsedNames = Record<string, number | undefined>
+
+export type Code = _Code | Name
+
+export type SafeExpr = Code | number | boolean | null
+
+export const nil = new _Code("")
+
+type CodeArg = SafeExpr | string | undefined
+
+export function _(strs: TemplateStringsArray, ...args: CodeArg[]): _Code {
+ const code: CodeItem[] = [strs[0]]
+ let i = 0
+ while (i < args.length) {
+ addCodeArg(code, args[i])
+ code.push(strs[++i])
+ }
+ return new _Code(code)
+}
+
+const plus = new _Code("+")
+
+export function str(strs: TemplateStringsArray, ...args: (CodeArg | string[])[]): _Code {
+ const expr: CodeItem[] = [safeStringify(strs[0])]
+ let i = 0
+ while (i < args.length) {
+ expr.push(plus)
+ addCodeArg(expr, args[i])
+ expr.push(plus, safeStringify(strs[++i]))
+ }
+ optimize(expr)
+ return new _Code(expr)
+}
+
+export function addCodeArg(code: CodeItem[], arg: CodeArg | string[]): void {
+ if (arg instanceof _Code) code.push(...arg._items)
+ else if (arg instanceof Name) code.push(arg)
+ else code.push(interpolate(arg))
+}
+
+function optimize(expr: CodeItem[]): void {
+ let i = 1
+ while (i < expr.length - 1) {
+ if (expr[i] === plus) {
+ const res = mergeExprItems(expr[i - 1], expr[i + 1])
+ if (res !== undefined) {
+ expr.splice(i - 1, 3, res)
+ continue
+ }
+ expr[i++] = "+"
+ }
+ i++
+ }
+}
+
+function mergeExprItems(a: CodeItem, b: CodeItem): CodeItem | undefined {
+ if (b === '""') return a
+ if (a === '""') return b
+ if (typeof a == "string") {
+ if (b instanceof Name || a[a.length - 1] !== '"') return
+ if (typeof b != "string") return `${a.slice(0, -1)}${b}"`
+ if (b[0] === '"') return a.slice(0, -1) + b.slice(1)
+ return
+ }
+ if (typeof b == "string" && b[0] === '"' && !(a instanceof Name)) return `"${a}${b.slice(1)}`
+ return
+}
+
+export function strConcat(c1: Code, c2: Code): Code {
+ return c2.emptyStr() ? c1 : c1.emptyStr() ? c2 : str`${c1}${c2}`
+}
+
+// TODO do not allow arrays here
+function interpolate(x?: string | string[] | number | boolean | null): SafeExpr | string {
+ return typeof x == "number" || typeof x == "boolean" || x === null
+ ? x
+ : safeStringify(Array.isArray(x) ? x.join(",") : x)
+}
+
+export function stringify(x: unknown): Code {
+ return new _Code(safeStringify(x))
+}
+
+export function safeStringify(x: unknown): string {
+ return JSON.stringify(x)
+ .replace(/\u2028/g, "\\u2028")
+ .replace(/\u2029/g, "\\u2029")
+}
+
+export function getProperty(key: Code | string | number): Code {
+ return typeof key == "string" && IDENTIFIER.test(key) ? new _Code(`.${key}`) : _`[${key}]`
+}
+
+//Does best effort to format the name properly
+export function getEsmExportName(key: Code | string | number): Code {
+ if (typeof key == "string" && IDENTIFIER.test(key)) {
+ return new _Code(`${key}`)
+ }
+ throw new Error(`CodeGen: invalid export name: ${key}, use explicit $id name mapping`)
+}
+
+export function regexpCode(rx: RegExp): Code {
+ return new _Code(rx.toString())
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/index.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/index.ts
new file mode 100644
index 00000000..9d29055d
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/index.ts
@@ -0,0 +1,832 @@
+import type {ScopeValueSets, NameValue, ValueScope, ValueScopeName} from "./scope"
+import {_, nil, _Code, Code, Name, UsedNames, CodeItem, addCodeArg, _CodeOrName} from "./code"
+import {Scope, varKinds} from "./scope"
+
+export {_, str, strConcat, nil, getProperty, stringify, regexpCode, Name, Code} from "./code"
+export {Scope, ScopeStore, ValueScope, ValueScopeName, ScopeValueSets, varKinds} from "./scope"
+
+// type for expressions that can be safely inserted in code without quotes
+export type SafeExpr = Code | number | boolean | null
+
+// type that is either Code of function that adds code to CodeGen instance using its methods
+export type Block = Code | (() => void)
+
+export const operators = {
+ GT: new _Code(">"),
+ GTE: new _Code(">="),
+ LT: new _Code("<"),
+ LTE: new _Code("<="),
+ EQ: new _Code("==="),
+ NEQ: new _Code("!=="),
+ NOT: new _Code("!"),
+ OR: new _Code("||"),
+ AND: new _Code("&&"),
+ ADD: new _Code("+"),
+}
+
+abstract class Node {
+ abstract readonly names: UsedNames
+
+ optimizeNodes(): this | ChildNode | ChildNode[] | undefined {
+ return this
+ }
+
+ optimizeNames(_names: UsedNames, _constants: Constants): this | undefined {
+ return this
+ }
+
+ // get count(): number {
+ // return 1
+ // }
+}
+
+class Def extends Node {
+ constructor(private readonly varKind: Name, private readonly name: Name, private rhs?: SafeExpr) {
+ super()
+ }
+
+ render({es5, _n}: CGOptions): string {
+ const varKind = es5 ? varKinds.var : this.varKind
+ const rhs = this.rhs === undefined ? "" : ` = ${this.rhs}`
+ return `${varKind} ${this.name}${rhs};` + _n
+ }
+
+ optimizeNames(names: UsedNames, constants: Constants): this | undefined {
+ if (!names[this.name.str]) return
+ if (this.rhs) this.rhs = optimizeExpr(this.rhs, names, constants)
+ return this
+ }
+
+ get names(): UsedNames {
+ return this.rhs instanceof _CodeOrName ? this.rhs.names : {}
+ }
+}
+
+class Assign extends Node {
+ constructor(readonly lhs: Code, public rhs: SafeExpr, private readonly sideEffects?: boolean) {
+ super()
+ }
+
+ render({_n}: CGOptions): string {
+ return `${this.lhs} = ${this.rhs};` + _n
+ }
+
+ optimizeNames(names: UsedNames, constants: Constants): this | undefined {
+ if (this.lhs instanceof Name && !names[this.lhs.str] && !this.sideEffects) return
+ this.rhs = optimizeExpr(this.rhs, names, constants)
+ return this
+ }
+
+ get names(): UsedNames {
+ const names = this.lhs instanceof Name ? {} : {...this.lhs.names}
+ return addExprNames(names, this.rhs)
+ }
+}
+
+class AssignOp extends Assign {
+ constructor(lhs: Code, private readonly op: Code, rhs: SafeExpr, sideEffects?: boolean) {
+ super(lhs, rhs, sideEffects)
+ }
+
+ render({_n}: CGOptions): string {
+ return `${this.lhs} ${this.op}= ${this.rhs};` + _n
+ }
+}
+
+class Label extends Node {
+ readonly names: UsedNames = {}
+ constructor(readonly label: Name) {
+ super()
+ }
+
+ render({_n}: CGOptions): string {
+ return `${this.label}:` + _n
+ }
+}
+
+class Break extends Node {
+ readonly names: UsedNames = {}
+ constructor(readonly label?: Code) {
+ super()
+ }
+
+ render({_n}: CGOptions): string {
+ const label = this.label ? ` ${this.label}` : ""
+ return `break${label};` + _n
+ }
+}
+
+class Throw extends Node {
+ constructor(readonly error: Code) {
+ super()
+ }
+
+ render({_n}: CGOptions): string {
+ return `throw ${this.error};` + _n
+ }
+
+ get names(): UsedNames {
+ return this.error.names
+ }
+}
+
+class AnyCode extends Node {
+ constructor(private code: SafeExpr) {
+ super()
+ }
+
+ render({_n}: CGOptions): string {
+ return `${this.code};` + _n
+ }
+
+ optimizeNodes(): this | undefined {
+ return `${this.code}` ? this : undefined
+ }
+
+ optimizeNames(names: UsedNames, constants: Constants): this {
+ this.code = optimizeExpr(this.code, names, constants)
+ return this
+ }
+
+ get names(): UsedNames {
+ return this.code instanceof _CodeOrName ? this.code.names : {}
+ }
+}
+
+abstract class ParentNode extends Node {
+ constructor(readonly nodes: ChildNode[] = []) {
+ super()
+ }
+
+ render(opts: CGOptions): string {
+ return this.nodes.reduce((code, n) => code + n.render(opts), "")
+ }
+
+ optimizeNodes(): this | ChildNode | ChildNode[] | undefined {
+ const {nodes} = this
+ let i = nodes.length
+ while (i--) {
+ const n = nodes[i].optimizeNodes()
+ if (Array.isArray(n)) nodes.splice(i, 1, ...n)
+ else if (n) nodes[i] = n
+ else nodes.splice(i, 1)
+ }
+ return nodes.length > 0 ? this : undefined
+ }
+
+ optimizeNames(names: UsedNames, constants: Constants): this | undefined {
+ const {nodes} = this
+ let i = nodes.length
+ while (i--) {
+ // iterating backwards improves 1-pass optimization
+ const n = nodes[i]
+ if (n.optimizeNames(names, constants)) continue
+ subtractNames(names, n.names)
+ nodes.splice(i, 1)
+ }
+ return nodes.length > 0 ? this : undefined
+ }
+
+ get names(): UsedNames {
+ return this.nodes.reduce((names: UsedNames, n) => addNames(names, n.names), {})
+ }
+
+ // get count(): number {
+ // return this.nodes.reduce((c, n) => c + n.count, 1)
+ // }
+}
+
+abstract class BlockNode extends ParentNode {
+ render(opts: CGOptions): string {
+ return "{" + opts._n + super.render(opts) + "}" + opts._n
+ }
+}
+
+class Root extends ParentNode {}
+
+class Else extends BlockNode {
+ static readonly kind = "else"
+}
+
+class If extends BlockNode {
+ static readonly kind = "if"
+ else?: If | Else
+ constructor(private condition: Code | boolean, nodes?: ChildNode[]) {
+ super(nodes)
+ }
+
+ render(opts: CGOptions): string {
+ let code = `if(${this.condition})` + super.render(opts)
+ if (this.else) code += "else " + this.else.render(opts)
+ return code
+ }
+
+ optimizeNodes(): If | ChildNode[] | undefined {
+ super.optimizeNodes()
+ const cond = this.condition
+ if (cond === true) return this.nodes // else is ignored here
+ let e = this.else
+ if (e) {
+ const ns = e.optimizeNodes()
+ e = this.else = Array.isArray(ns) ? new Else(ns) : (ns as Else | undefined)
+ }
+ if (e) {
+ if (cond === false) return e instanceof If ? e : e.nodes
+ if (this.nodes.length) return this
+ return new If(not(cond), e instanceof If ? [e] : e.nodes)
+ }
+ if (cond === false || !this.nodes.length) return undefined
+ return this
+ }
+
+ optimizeNames(names: UsedNames, constants: Constants): this | undefined {
+ this.else = this.else?.optimizeNames(names, constants)
+ if (!(super.optimizeNames(names, constants) || this.else)) return
+ this.condition = optimizeExpr(this.condition, names, constants)
+ return this
+ }
+
+ get names(): UsedNames {
+ const names = super.names
+ addExprNames(names, this.condition)
+ if (this.else) addNames(names, this.else.names)
+ return names
+ }
+
+ // get count(): number {
+ // return super.count + (this.else?.count || 0)
+ // }
+}
+
+abstract class For extends BlockNode {
+ static readonly kind = "for"
+}
+
+class ForLoop extends For {
+ constructor(private iteration: Code) {
+ super()
+ }
+
+ render(opts: CGOptions): string {
+ return `for(${this.iteration})` + super.render(opts)
+ }
+
+ optimizeNames(names: UsedNames, constants: Constants): this | undefined {
+ if (!super.optimizeNames(names, constants)) return
+ this.iteration = optimizeExpr(this.iteration, names, constants)
+ return this
+ }
+
+ get names(): UsedNames {
+ return addNames(super.names, this.iteration.names)
+ }
+}
+
+class ForRange extends For {
+ constructor(
+ private readonly varKind: Name,
+ private readonly name: Name,
+ private readonly from: SafeExpr,
+ private readonly to: SafeExpr
+ ) {
+ super()
+ }
+
+ render(opts: CGOptions): string {
+ const varKind = opts.es5 ? varKinds.var : this.varKind
+ const {name, from, to} = this
+ return `for(${varKind} ${name}=${from}; ${name}<${to}; ${name}++)` + super.render(opts)
+ }
+
+ get names(): UsedNames {
+ const names = addExprNames(super.names, this.from)
+ return addExprNames(names, this.to)
+ }
+}
+
+class ForIter extends For {
+ constructor(
+ private readonly loop: "of" | "in",
+ private readonly varKind: Name,
+ private readonly name: Name,
+ private iterable: Code
+ ) {
+ super()
+ }
+
+ render(opts: CGOptions): string {
+ return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts)
+ }
+
+ optimizeNames(names: UsedNames, constants: Constants): this | undefined {
+ if (!super.optimizeNames(names, constants)) return
+ this.iterable = optimizeExpr(this.iterable, names, constants)
+ return this
+ }
+
+ get names(): UsedNames {
+ return addNames(super.names, this.iterable.names)
+ }
+}
+
+class Func extends BlockNode {
+ static readonly kind = "func"
+ constructor(public name: Name, public args: Code, public async?: boolean) {
+ super()
+ }
+
+ render(opts: CGOptions): string {
+ const _async = this.async ? "async " : ""
+ return `${_async}function ${this.name}(${this.args})` + super.render(opts)
+ }
+}
+
+class Return extends ParentNode {
+ static readonly kind = "return"
+
+ render(opts: CGOptions): string {
+ return "return " + super.render(opts)
+ }
+}
+
+class Try extends BlockNode {
+ catch?: Catch
+ finally?: Finally
+
+ render(opts: CGOptions): string {
+ let code = "try" + super.render(opts)
+ if (this.catch) code += this.catch.render(opts)
+ if (this.finally) code += this.finally.render(opts)
+ return code
+ }
+
+ optimizeNodes(): this {
+ super.optimizeNodes()
+ this.catch?.optimizeNodes() as Catch | undefined
+ this.finally?.optimizeNodes() as Finally | undefined
+ return this
+ }
+
+ optimizeNames(names: UsedNames, constants: Constants): this {
+ super.optimizeNames(names, constants)
+ this.catch?.optimizeNames(names, constants)
+ this.finally?.optimizeNames(names, constants)
+ return this
+ }
+
+ get names(): UsedNames {
+ const names = super.names
+ if (this.catch) addNames(names, this.catch.names)
+ if (this.finally) addNames(names, this.finally.names)
+ return names
+ }
+
+ // get count(): number {
+ // return super.count + (this.catch?.count || 0) + (this.finally?.count || 0)
+ // }
+}
+
+class Catch extends BlockNode {
+ static readonly kind = "catch"
+ constructor(readonly error: Name) {
+ super()
+ }
+
+ render(opts: CGOptions): string {
+ return `catch(${this.error})` + super.render(opts)
+ }
+}
+
+class Finally extends BlockNode {
+ static readonly kind = "finally"
+ render(opts: CGOptions): string {
+ return "finally" + super.render(opts)
+ }
+}
+
+type StartBlockNode = If | For | Func | Return | Try
+
+type LeafNode = Def | Assign | Label | Break | Throw | AnyCode
+
+type ChildNode = StartBlockNode | LeafNode
+
+type EndBlockNodeType =
+ | typeof If
+ | typeof Else
+ | typeof For
+ | typeof Func
+ | typeof Return
+ | typeof Catch
+ | typeof Finally
+
+type Constants = Record<string, SafeExpr | undefined>
+
+export interface CodeGenOptions {
+ es5?: boolean
+ lines?: boolean
+ ownProperties?: boolean
+}
+
+interface CGOptions extends CodeGenOptions {
+ _n: "\n" | ""
+}
+
+export class CodeGen {
+ readonly _scope: Scope
+ readonly _extScope: ValueScope
+ readonly _values: ScopeValueSets = {}
+ private readonly _nodes: ParentNode[]
+ private readonly _blockStarts: number[] = []
+ private readonly _constants: Constants = {}
+ private readonly opts: CGOptions
+
+ constructor(extScope: ValueScope, opts: CodeGenOptions = {}) {
+ this.opts = {...opts, _n: opts.lines ? "\n" : ""}
+ this._extScope = extScope
+ this._scope = new Scope({parent: extScope})
+ this._nodes = [new Root()]
+ }
+
+ toString(): string {
+ return this._root.render(this.opts)
+ }
+
+ // returns unique name in the internal scope
+ name(prefix: string): Name {
+ return this._scope.name(prefix)
+ }
+
+ // reserves unique name in the external scope
+ scopeName(prefix: string): ValueScopeName {
+ return this._extScope.name(prefix)
+ }
+
+ // reserves unique name in the external scope and assigns value to it
+ scopeValue(prefixOrName: ValueScopeName | string, value: NameValue): Name {
+ const name = this._extScope.value(prefixOrName, value)
+ const vs = this._values[name.prefix] || (this._values[name.prefix] = new Set())
+ vs.add(name)
+ return name
+ }
+
+ getScopeValue(prefix: string, keyOrRef: unknown): ValueScopeName | undefined {
+ return this._extScope.getValue(prefix, keyOrRef)
+ }
+
+ // return code that assigns values in the external scope to the names that are used internally
+ // (same names that were returned by gen.scopeName or gen.scopeValue)
+ scopeRefs(scopeName: Name): Code {
+ return this._extScope.scopeRefs(scopeName, this._values)
+ }
+
+ scopeCode(): Code {
+ return this._extScope.scopeCode(this._values)
+ }
+
+ private _def(
+ varKind: Name,
+ nameOrPrefix: Name | string,
+ rhs?: SafeExpr,
+ constant?: boolean
+ ): Name {
+ const name = this._scope.toName(nameOrPrefix)
+ if (rhs !== undefined && constant) this._constants[name.str] = rhs
+ this._leafNode(new Def(varKind, name, rhs))
+ return name
+ }
+
+ // `const` declaration (`var` in es5 mode)
+ const(nameOrPrefix: Name | string, rhs: SafeExpr, _constant?: boolean): Name {
+ return this._def(varKinds.const, nameOrPrefix, rhs, _constant)
+ }
+
+ // `let` declaration with optional assignment (`var` in es5 mode)
+ let(nameOrPrefix: Name | string, rhs?: SafeExpr, _constant?: boolean): Name {
+ return this._def(varKinds.let, nameOrPrefix, rhs, _constant)
+ }
+
+ // `var` declaration with optional assignment
+ var(nameOrPrefix: Name | string, rhs?: SafeExpr, _constant?: boolean): Name {
+ return this._def(varKinds.var, nameOrPrefix, rhs, _constant)
+ }
+
+ // assignment code
+ assign(lhs: Code, rhs: SafeExpr, sideEffects?: boolean): CodeGen {
+ return this._leafNode(new Assign(lhs, rhs, sideEffects))
+ }
+
+ // `+=` code
+ add(lhs: Code, rhs: SafeExpr): CodeGen {
+ return this._leafNode(new AssignOp(lhs, operators.ADD, rhs))
+ }
+
+ // appends passed SafeExpr to code or executes Block
+ code(c: Block | SafeExpr): CodeGen {
+ if (typeof c == "function") c()
+ else if (c !== nil) this._leafNode(new AnyCode(c))
+ return this
+ }
+
+ // returns code for object literal for the passed argument list of key-value pairs
+ object(...keyValues: [Name | string, SafeExpr | string][]): _Code {
+ const code: CodeItem[] = ["{"]
+ for (const [key, value] of keyValues) {
+ if (code.length > 1) code.push(",")
+ code.push(key)
+ if (key !== value || this.opts.es5) {
+ code.push(":")
+ addCodeArg(code, value)
+ }
+ }
+ code.push("}")
+ return new _Code(code)
+ }
+
+ // `if` clause (or statement if `thenBody` and, optionally, `elseBody` are passed)
+ if(condition: Code | boolean, thenBody?: Block, elseBody?: Block): CodeGen {
+ this._blockNode(new If(condition))
+
+ if (thenBody && elseBody) {
+ this.code(thenBody).else().code(elseBody).endIf()
+ } else if (thenBody) {
+ this.code(thenBody).endIf()
+ } else if (elseBody) {
+ throw new Error('CodeGen: "else" body without "then" body')
+ }
+ return this
+ }
+
+ // `else if` clause - invalid without `if` or after `else` clauses
+ elseIf(condition: Code | boolean): CodeGen {
+ return this._elseNode(new If(condition))
+ }
+
+ // `else` clause - only valid after `if` or `else if` clauses
+ else(): CodeGen {
+ return this._elseNode(new Else())
+ }
+
+ // end `if` statement (needed if gen.if was used only with condition)
+ endIf(): CodeGen {
+ return this._endBlockNode(If, Else)
+ }
+
+ private _for(node: For, forBody?: Block): CodeGen {
+ this._blockNode(node)
+ if (forBody) this.code(forBody).endFor()
+ return this
+ }
+
+ // a generic `for` clause (or statement if `forBody` is passed)
+ for(iteration: Code, forBody?: Block): CodeGen {
+ return this._for(new ForLoop(iteration), forBody)
+ }
+
+ // `for` statement for a range of values
+ forRange(
+ nameOrPrefix: Name | string,
+ from: SafeExpr,
+ to: SafeExpr,
+ forBody: (index: Name) => void,
+ varKind: Code = this.opts.es5 ? varKinds.var : varKinds.let
+ ): CodeGen {
+ const name = this._scope.toName(nameOrPrefix)
+ return this._for(new ForRange(varKind, name, from, to), () => forBody(name))
+ }
+
+ // `for-of` statement (in es5 mode replace with a normal for loop)
+ forOf(
+ nameOrPrefix: Name | string,
+ iterable: Code,
+ forBody: (item: Name) => void,
+ varKind: Code = varKinds.const
+ ): CodeGen {
+ const name = this._scope.toName(nameOrPrefix)
+ if (this.opts.es5) {
+ const arr = iterable instanceof Name ? iterable : this.var("_arr", iterable)
+ return this.forRange("_i", 0, _`${arr}.length`, (i) => {
+ this.var(name, _`${arr}[${i}]`)
+ forBody(name)
+ })
+ }
+ return this._for(new ForIter("of", varKind, name, iterable), () => forBody(name))
+ }
+
+ // `for-in` statement.
+ // With option `ownProperties` replaced with a `for-of` loop for object keys
+ forIn(
+ nameOrPrefix: Name | string,
+ obj: Code,
+ forBody: (item: Name) => void,
+ varKind: Code = this.opts.es5 ? varKinds.var : varKinds.const
+ ): CodeGen {
+ if (this.opts.ownProperties) {
+ return this.forOf(nameOrPrefix, _`Object.keys(${obj})`, forBody)
+ }
+ const name = this._scope.toName(nameOrPrefix)
+ return this._for(new ForIter("in", varKind, name, obj), () => forBody(name))
+ }
+
+ // end `for` loop
+ endFor(): CodeGen {
+ return this._endBlockNode(For)
+ }
+
+ // `label` statement
+ label(label: Name): CodeGen {
+ return this._leafNode(new Label(label))
+ }
+
+ // `break` statement
+ break(label?: Code): CodeGen {
+ return this._leafNode(new Break(label))
+ }
+
+ // `return` statement
+ return(value: Block | SafeExpr): CodeGen {
+ const node = new Return()
+ this._blockNode(node)
+ this.code(value)
+ if (node.nodes.length !== 1) throw new Error('CodeGen: "return" should have one node')
+ return this._endBlockNode(Return)
+ }
+
+ // `try` statement
+ try(tryBody: Block, catchCode?: (e: Name) => void, finallyCode?: Block): CodeGen {
+ if (!catchCode && !finallyCode) throw new Error('CodeGen: "try" without "catch" and "finally"')
+ const node = new Try()
+ this._blockNode(node)
+ this.code(tryBody)
+ if (catchCode) {
+ const error = this.name("e")
+ this._currNode = node.catch = new Catch(error)
+ catchCode(error)
+ }
+ if (finallyCode) {
+ this._currNode = node.finally = new Finally()
+ this.code(finallyCode)
+ }
+ return this._endBlockNode(Catch, Finally)
+ }
+
+ // `throw` statement
+ throw(error: Code): CodeGen {
+ return this._leafNode(new Throw(error))
+ }
+
+ // start self-balancing block
+ block(body?: Block, nodeCount?: number): CodeGen {
+ this._blockStarts.push(this._nodes.length)
+ if (body) this.code(body).endBlock(nodeCount)
+ return this
+ }
+
+ // end the current self-balancing block
+ endBlock(nodeCount?: number): CodeGen {
+ const len = this._blockStarts.pop()
+ if (len === undefined) throw new Error("CodeGen: not in self-balancing block")
+ const toClose = this._nodes.length - len
+ if (toClose < 0 || (nodeCount !== undefined && toClose !== nodeCount)) {
+ throw new Error(`CodeGen: wrong number of nodes: ${toClose} vs ${nodeCount} expected`)
+ }
+ this._nodes.length = len
+ return this
+ }
+
+ // `function` heading (or definition if funcBody is passed)
+ func(name: Name, args: Code = nil, async?: boolean, funcBody?: Block): CodeGen {
+ this._blockNode(new Func(name, args, async))
+ if (funcBody) this.code(funcBody).endFunc()
+ return this
+ }
+
+ // end function definition
+ endFunc(): CodeGen {
+ return this._endBlockNode(Func)
+ }
+
+ optimize(n = 1): void {
+ while (n-- > 0) {
+ this._root.optimizeNodes()
+ this._root.optimizeNames(this._root.names, this._constants)
+ }
+ }
+
+ private _leafNode(node: LeafNode): CodeGen {
+ this._currNode.nodes.push(node)
+ return this
+ }
+
+ private _blockNode(node: StartBlockNode): void {
+ this._currNode.nodes.push(node)
+ this._nodes.push(node)
+ }
+
+ private _endBlockNode(N1: EndBlockNodeType, N2?: EndBlockNodeType): CodeGen {
+ const n = this._currNode
+ if (n instanceof N1 || (N2 && n instanceof N2)) {
+ this._nodes.pop()
+ return this
+ }
+ throw new Error(`CodeGen: not in block "${N2 ? `${N1.kind}/${N2.kind}` : N1.kind}"`)
+ }
+
+ private _elseNode(node: If | Else): CodeGen {
+ const n = this._currNode
+ if (!(n instanceof If)) {
+ throw new Error('CodeGen: "else" without "if"')
+ }
+ this._currNode = n.else = node
+ return this
+ }
+
+ private get _root(): Root {
+ return this._nodes[0] as Root
+ }
+
+ private get _currNode(): ParentNode {
+ const ns = this._nodes
+ return ns[ns.length - 1]
+ }
+
+ private set _currNode(node: ParentNode) {
+ const ns = this._nodes
+ ns[ns.length - 1] = node
+ }
+
+ // get nodeCount(): number {
+ // return this._root.count
+ // }
+}
+
+function addNames(names: UsedNames, from: UsedNames): UsedNames {
+ for (const n in from) names[n] = (names[n] || 0) + (from[n] || 0)
+ return names
+}
+
+function addExprNames(names: UsedNames, from: SafeExpr): UsedNames {
+ return from instanceof _CodeOrName ? addNames(names, from.names) : names
+}
+
+function optimizeExpr<T extends SafeExpr | Code>(expr: T, names: UsedNames, constants: Constants): T
+function optimizeExpr(expr: SafeExpr, names: UsedNames, constants: Constants): SafeExpr {
+ if (expr instanceof Name) return replaceName(expr)
+ if (!canOptimize(expr)) return expr
+ return new _Code(
+ expr._items.reduce((items: CodeItem[], c: SafeExpr | string) => {
+ if (c instanceof Name) c = replaceName(c)
+ if (c instanceof _Code) items.push(...c._items)
+ else items.push(c)
+ return items
+ }, [])
+ )
+
+ function replaceName(n: Name): SafeExpr {
+ const c = constants[n.str]
+ if (c === undefined || names[n.str] !== 1) return n
+ delete names[n.str]
+ return c
+ }
+
+ function canOptimize(e: SafeExpr): e is _Code {
+ return (
+ e instanceof _Code &&
+ e._items.some(
+ (c) => c instanceof Name && names[c.str] === 1 && constants[c.str] !== undefined
+ )
+ )
+ }
+}
+
+function subtractNames(names: UsedNames, from: UsedNames): void {
+ for (const n in from) names[n] = (names[n] || 0) - (from[n] || 0)
+}
+
+export function not<T extends Code | SafeExpr>(x: T): T
+export function not(x: Code | SafeExpr): Code | SafeExpr {
+ return typeof x == "boolean" || typeof x == "number" || x === null ? !x : _`!${par(x)}`
+}
+
+const andCode = mappend(operators.AND)
+
+// boolean AND (&&) expression with the passed arguments
+export function and(...args: Code[]): Code {
+ return args.reduce(andCode)
+}
+
+const orCode = mappend(operators.OR)
+
+// boolean OR (||) expression with the passed arguments
+export function or(...args: Code[]): Code {
+ return args.reduce(orCode)
+}
+
+type MAppend = (x: Code, y: Code) => Code
+
+function mappend(op: Code): MAppend {
+ return (x, y) => (x === nil ? y : y === nil ? x : _`${par(x)} ${op} ${par(y)}`)
+}
+
+function par(x: Code): Code {
+ return x instanceof Name ? x : _`(${x})`
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/scope.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/scope.ts
new file mode 100644
index 00000000..51199229
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/scope.ts
@@ -0,0 +1,215 @@
+import {_, nil, Code, Name} from "./code"
+
+interface NameGroup {
+ prefix: string
+ index: number
+}
+
+export interface NameValue {
+ ref: ValueReference // this is the reference to any value that can be referred to from generated code via `globals` var in the closure
+ key?: unknown // any key to identify a global to avoid duplicates, if not passed ref is used
+ code?: Code // this is the code creating the value needed for standalone code wit_out closure - can be a primitive value, function or import (`require`)
+}
+
+export type ValueReference = unknown // possibly make CodeGen parameterized type on this type
+
+class ValueError extends Error {
+ readonly value?: NameValue
+ constructor(name: ValueScopeName) {
+ super(`CodeGen: "code" for ${name} not defined`)
+ this.value = name.value
+ }
+}
+
+interface ScopeOptions {
+ prefixes?: Set<string>
+ parent?: Scope
+}
+
+interface ValueScopeOptions extends ScopeOptions {
+ scope: ScopeStore
+ es5?: boolean
+ lines?: boolean
+}
+
+export type ScopeStore = Record<string, ValueReference[] | undefined>
+
+type ScopeValues = {
+ [Prefix in string]?: Map<unknown, ValueScopeName>
+}
+
+export type ScopeValueSets = {
+ [Prefix in string]?: Set<ValueScopeName>
+}
+
+export enum UsedValueState {
+ Started,
+ Completed,
+}
+
+export type UsedScopeValues = {
+ [Prefix in string]?: Map<ValueScopeName, UsedValueState | undefined>
+}
+
+export const varKinds = {
+ const: new Name("const"),
+ let: new Name("let"),
+ var: new Name("var"),
+}
+
+export class Scope {
+ protected readonly _names: {[Prefix in string]?: NameGroup} = {}
+ protected readonly _prefixes?: Set<string>
+ protected readonly _parent?: Scope
+
+ constructor({prefixes, parent}: ScopeOptions = {}) {
+ this._prefixes = prefixes
+ this._parent = parent
+ }
+
+ toName(nameOrPrefix: Name | string): Name {
+ return nameOrPrefix instanceof Name ? nameOrPrefix : this.name(nameOrPrefix)
+ }
+
+ name(prefix: string): Name {
+ return new Name(this._newName(prefix))
+ }
+
+ protected _newName(prefix: string): string {
+ const ng = this._names[prefix] || this._nameGroup(prefix)
+ return `${prefix}${ng.index++}`
+ }
+
+ private _nameGroup(prefix: string): NameGroup {
+ if (this._parent?._prefixes?.has(prefix) || (this._prefixes && !this._prefixes.has(prefix))) {
+ throw new Error(`CodeGen: prefix "${prefix}" is not allowed in this scope`)
+ }
+ return (this._names[prefix] = {prefix, index: 0})
+ }
+}
+
+interface ScopePath {
+ property: string
+ itemIndex: number
+}
+
+export class ValueScopeName extends Name {
+ readonly prefix: string
+ value?: NameValue
+ scopePath?: Code
+
+ constructor(prefix: string, nameStr: string) {
+ super(nameStr)
+ this.prefix = prefix
+ }
+
+ setValue(value: NameValue, {property, itemIndex}: ScopePath): void {
+ this.value = value
+ this.scopePath = _`.${new Name(property)}[${itemIndex}]`
+ }
+}
+
+interface VSOptions extends ValueScopeOptions {
+ _n: Code
+}
+
+const line = _`\n`
+
+export class ValueScope extends Scope {
+ protected readonly _values: ScopeValues = {}
+ protected readonly _scope: ScopeStore
+ readonly opts: VSOptions
+
+ constructor(opts: ValueScopeOptions) {
+ super(opts)
+ this._scope = opts.scope
+ this.opts = {...opts, _n: opts.lines ? line : nil}
+ }
+
+ get(): ScopeStore {
+ return this._scope
+ }
+
+ name(prefix: string): ValueScopeName {
+ return new ValueScopeName(prefix, this._newName(prefix))
+ }
+
+ value(nameOrPrefix: ValueScopeName | string, value: NameValue): ValueScopeName {
+ if (value.ref === undefined) throw new Error("CodeGen: ref must be passed in value")
+ const name = this.toName(nameOrPrefix) as ValueScopeName
+ const {prefix} = name
+ const valueKey = value.key ?? value.ref
+ let vs = this._values[prefix]
+ if (vs) {
+ const _name = vs.get(valueKey)
+ if (_name) return _name
+ } else {
+ vs = this._values[prefix] = new Map()
+ }
+ vs.set(valueKey, name)
+
+ const s = this._scope[prefix] || (this._scope[prefix] = [])
+ const itemIndex = s.length
+ s[itemIndex] = value.ref
+ name.setValue(value, {property: prefix, itemIndex})
+ return name
+ }
+
+ getValue(prefix: string, keyOrRef: unknown): ValueScopeName | undefined {
+ const vs = this._values[prefix]
+ if (!vs) return
+ return vs.get(keyOrRef)
+ }
+
+ scopeRefs(scopeName: Name, values: ScopeValues | ScopeValueSets = this._values): Code {
+ return this._reduceValues(values, (name: ValueScopeName) => {
+ if (name.scopePath === undefined) throw new Error(`CodeGen: name "${name}" has no value`)
+ return _`${scopeName}${name.scopePath}`
+ })
+ }
+
+ scopeCode(
+ values: ScopeValues | ScopeValueSets = this._values,
+ usedValues?: UsedScopeValues,
+ getCode?: (n: ValueScopeName) => Code | undefined
+ ): Code {
+ return this._reduceValues(
+ values,
+ (name: ValueScopeName) => {
+ if (name.value === undefined) throw new Error(`CodeGen: name "${name}" has no value`)
+ return name.value.code
+ },
+ usedValues,
+ getCode
+ )
+ }
+
+ private _reduceValues(
+ values: ScopeValues | ScopeValueSets,
+ valueCode: (n: ValueScopeName) => Code | undefined,
+ usedValues: UsedScopeValues = {},
+ getCode?: (n: ValueScopeName) => Code | undefined
+ ): Code {
+ let code: Code = nil
+ for (const prefix in values) {
+ const vs = values[prefix]
+ if (!vs) continue
+ const nameSet = (usedValues[prefix] = usedValues[prefix] || new Map())
+ vs.forEach((name: ValueScopeName) => {
+ if (nameSet.has(name)) return
+ nameSet.set(name, UsedValueState.Started)
+ let c = valueCode(name)
+ if (c) {
+ const def = this.opts.es5 ? varKinds.var : varKinds.const
+ code = _`${code}${def} ${name} = ${c};${this.opts._n}`
+ } else if ((c = getCode?.(name))) {
+ code = _`${code}${c}${this.opts._n}`
+ } else {
+ throw new ValueError(name)
+ }
+ nameSet.set(name, UsedValueState.Completed)
+ })
+ }
+ return code
+ }
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/errors.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/errors.ts
new file mode 100644
index 00000000..18424a0f
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/errors.ts
@@ -0,0 +1,184 @@
+import type {KeywordErrorCxt, KeywordErrorDefinition} from "../types"
+import type {SchemaCxt} from "./index"
+import {CodeGen, _, str, strConcat, Code, Name} from "./codegen"
+import {SafeExpr} from "./codegen/code"
+import {getErrorPath, Type} from "./util"
+import N from "./names"
+
+export const keywordError: KeywordErrorDefinition = {
+ message: ({keyword}) => str`must pass "${keyword}" keyword validation`,
+}
+
+export const keyword$DataError: KeywordErrorDefinition = {
+ message: ({keyword, schemaType}) =>
+ schemaType
+ ? str`"${keyword}" keyword must be ${schemaType} ($data)`
+ : str`"${keyword}" keyword is invalid ($data)`,
+}
+
+export interface ErrorPaths {
+ instancePath?: Code
+ schemaPath?: string
+ parentSchema?: boolean
+}
+
+export function reportError(
+ cxt: KeywordErrorCxt,
+ error: KeywordErrorDefinition = keywordError,
+ errorPaths?: ErrorPaths,
+ overrideAllErrors?: boolean
+): void {
+ const {it} = cxt
+ const {gen, compositeRule, allErrors} = it
+ const errObj = errorObjectCode(cxt, error, errorPaths)
+ if (overrideAllErrors ?? (compositeRule || allErrors)) {
+ addError(gen, errObj)
+ } else {
+ returnErrors(it, _`[${errObj}]`)
+ }
+}
+
+export function reportExtraError(
+ cxt: KeywordErrorCxt,
+ error: KeywordErrorDefinition = keywordError,
+ errorPaths?: ErrorPaths
+): void {
+ const {it} = cxt
+ const {gen, compositeRule, allErrors} = it
+ const errObj = errorObjectCode(cxt, error, errorPaths)
+ addError(gen, errObj)
+ if (!(compositeRule || allErrors)) {
+ returnErrors(it, N.vErrors)
+ }
+}
+
+export function resetErrorsCount(gen: CodeGen, errsCount: Name): void {
+ gen.assign(N.errors, errsCount)
+ gen.if(_`${N.vErrors} !== null`, () =>
+ gen.if(
+ errsCount,
+ () => gen.assign(_`${N.vErrors}.length`, errsCount),
+ () => gen.assign(N.vErrors, null)
+ )
+ )
+}
+
+export function extendErrors({
+ gen,
+ keyword,
+ schemaValue,
+ data,
+ errsCount,
+ it,
+}: KeywordErrorCxt): void {
+ /* istanbul ignore if */
+ if (errsCount === undefined) throw new Error("ajv implementation error")
+ const err = gen.name("err")
+ gen.forRange("i", errsCount, N.errors, (i) => {
+ gen.const(err, _`${N.vErrors}[${i}]`)
+ gen.if(_`${err}.instancePath === undefined`, () =>
+ gen.assign(_`${err}.instancePath`, strConcat(N.instancePath, it.errorPath))
+ )
+ gen.assign(_`${err}.schemaPath`, str`${it.errSchemaPath}/${keyword}`)
+ if (it.opts.verbose) {
+ gen.assign(_`${err}.schema`, schemaValue)
+ gen.assign(_`${err}.data`, data)
+ }
+ })
+}
+
+function addError(gen: CodeGen, errObj: Code): void {
+ const err = gen.const("err", errObj)
+ gen.if(
+ _`${N.vErrors} === null`,
+ () => gen.assign(N.vErrors, _`[${err}]`),
+ _`${N.vErrors}.push(${err})`
+ )
+ gen.code(_`${N.errors}++`)
+}
+
+function returnErrors(it: SchemaCxt, errs: Code): void {
+ const {gen, validateName, schemaEnv} = it
+ if (schemaEnv.$async) {
+ gen.throw(_`new ${it.ValidationError as Name}(${errs})`)
+ } else {
+ gen.assign(_`${validateName}.errors`, errs)
+ gen.return(false)
+ }
+}
+
+const E = {
+ keyword: new Name("keyword"),
+ schemaPath: new Name("schemaPath"), // also used in JTD errors
+ params: new Name("params"),
+ propertyName: new Name("propertyName"),
+ message: new Name("message"),
+ schema: new Name("schema"),
+ parentSchema: new Name("parentSchema"),
+}
+
+function errorObjectCode(
+ cxt: KeywordErrorCxt,
+ error: KeywordErrorDefinition,
+ errorPaths?: ErrorPaths
+): Code {
+ const {createErrors} = cxt.it
+ if (createErrors === false) return _`{}`
+ return errorObject(cxt, error, errorPaths)
+}
+
+function errorObject(
+ cxt: KeywordErrorCxt,
+ error: KeywordErrorDefinition,
+ errorPaths: ErrorPaths = {}
+): Code {
+ const {gen, it} = cxt
+ const keyValues: [Name, SafeExpr | string][] = [
+ errorInstancePath(it, errorPaths),
+ errorSchemaPath(cxt, errorPaths),
+ ]
+ extraErrorProps(cxt, error, keyValues)
+ return gen.object(...keyValues)
+}
+
+function errorInstancePath({errorPath}: SchemaCxt, {instancePath}: ErrorPaths): [Name, Code] {
+ const instPath = instancePath
+ ? str`${errorPath}${getErrorPath(instancePath, Type.Str)}`
+ : errorPath
+ return [N.instancePath, strConcat(N.instancePath, instPath)]
+}
+
+function errorSchemaPath(
+ {keyword, it: {errSchemaPath}}: KeywordErrorCxt,
+ {schemaPath, parentSchema}: ErrorPaths
+): [Name, string | Code] {
+ let schPath = parentSchema ? errSchemaPath : str`${errSchemaPath}/${keyword}`
+ if (schemaPath) {
+ schPath = str`${schPath}${getErrorPath(schemaPath, Type.Str)}`
+ }
+ return [E.schemaPath, schPath]
+}
+
+function extraErrorProps(
+ cxt: KeywordErrorCxt,
+ {params, message}: KeywordErrorDefinition,
+ keyValues: [Name, SafeExpr | string][]
+): void {
+ const {keyword, data, schemaValue, it} = cxt
+ const {opts, propertyName, topSchemaRef, schemaPath} = it
+ keyValues.push(
+ [E.keyword, keyword],
+ [E.params, typeof params == "function" ? params(cxt) : params || _`{}`]
+ )
+ if (opts.messages) {
+ keyValues.push([E.message, typeof message == "function" ? message(cxt) : message])
+ }
+ if (opts.verbose) {
+ keyValues.push(
+ [E.schema, schemaValue],
+ [E.parentSchema, _`${topSchemaRef}${schemaPath}`],
+ [N.data, data]
+ )
+ }
+ if (propertyName) keyValues.push([E.propertyName, propertyName])
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/index.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/index.ts
new file mode 100644
index 00000000..ebdbe3c7
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/index.ts
@@ -0,0 +1,324 @@
+import type {
+ AnySchema,
+ AnySchemaObject,
+ AnyValidateFunction,
+ AsyncValidateFunction,
+ EvaluatedProperties,
+ EvaluatedItems,
+} from "../types"
+import type Ajv from "../core"
+import type {InstanceOptions} from "../core"
+import {CodeGen, _, nil, stringify, Name, Code, ValueScopeName} from "./codegen"
+import ValidationError from "../runtime/validation_error"
+import N from "./names"
+import {LocalRefs, getFullPath, _getFullPath, inlineRef, normalizeId, resolveUrl} from "./resolve"
+import {schemaHasRulesButRef, unescapeFragment} from "./util"
+import {validateFunctionCode} from "./validate"
+import * as URI from "uri-js"
+import {JSONType} from "./rules"
+
+export type SchemaRefs = {
+ [Ref in string]?: SchemaEnv | AnySchema
+}
+
+export interface SchemaCxt {
+ readonly gen: CodeGen
+ readonly allErrors?: boolean // validation mode - whether to collect all errors or break on error
+ readonly data: Name // Name with reference to the current part of data instance
+ readonly parentData: Name // should be used in keywords modifying data
+ readonly parentDataProperty: Code | number // should be used in keywords modifying data
+ readonly dataNames: Name[]
+ readonly dataPathArr: (Code | number)[]
+ readonly dataLevel: number // the level of the currently validated data,
+ // it can be used to access both the property names and the data on all levels from the top.
+ dataTypes: JSONType[] // data types applied to the current part of data instance
+ definedProperties: Set<string> // set of properties to keep track of for required checks
+ readonly topSchemaRef: Code
+ readonly validateName: Name
+ evaluated?: Name
+ readonly ValidationError?: Name
+ readonly schema: AnySchema // current schema object - equal to parentSchema passed via KeywordCxt
+ readonly schemaEnv: SchemaEnv
+ readonly rootId: string
+ baseId: string // the current schema base URI that should be used as the base for resolving URIs in references (\$ref)
+ readonly schemaPath: Code // the run-time expression that evaluates to the property name of the current schema
+ readonly errSchemaPath: string // this is actual string, should not be changed to Code
+ readonly errorPath: Code
+ readonly propertyName?: Name
+ readonly compositeRule?: boolean // true indicates that the current schema is inside the compound keyword,
+ // where failing some rule doesn't mean validation failure (`anyOf`, `oneOf`, `not`, `if`).
+ // This flag is used to determine whether you can return validation result immediately after any error in case the option `allErrors` is not `true.
+ // You only need to use it if you have many steps in your keywords and potentially can define multiple errors.
+ props?: EvaluatedProperties | Name // properties evaluated by this schema - used by parent schema or assigned to validation function
+ items?: EvaluatedItems | Name // last item evaluated by this schema - used by parent schema or assigned to validation function
+ jtdDiscriminator?: string
+ jtdMetadata?: boolean
+ readonly createErrors?: boolean
+ readonly opts: InstanceOptions // Ajv instance option.
+ readonly self: Ajv // current Ajv instance
+}
+
+export interface SchemaObjCxt extends SchemaCxt {
+ readonly schema: AnySchemaObject
+}
+interface SchemaEnvArgs {
+ readonly schema: AnySchema
+ readonly schemaId?: "$id" | "id"
+ readonly root?: SchemaEnv
+ readonly baseId?: string
+ readonly schemaPath?: string
+ readonly localRefs?: LocalRefs
+ readonly meta?: boolean
+}
+
+export class SchemaEnv implements SchemaEnvArgs {
+ readonly schema: AnySchema
+ readonly schemaId?: "$id" | "id"
+ readonly root: SchemaEnv
+ baseId: string // TODO possibly, it should be readonly
+ schemaPath?: string
+ localRefs?: LocalRefs
+ readonly meta?: boolean
+ readonly $async?: boolean // true if the current schema is asynchronous.
+ readonly refs: SchemaRefs = {}
+ readonly dynamicAnchors: {[Ref in string]?: true} = {}
+ validate?: AnyValidateFunction
+ validateName?: ValueScopeName
+ serialize?: (data: unknown) => string
+ serializeName?: ValueScopeName
+ parse?: (data: string) => unknown
+ parseName?: ValueScopeName
+
+ constructor(env: SchemaEnvArgs) {
+ let schema: AnySchemaObject | undefined
+ if (typeof env.schema == "object") schema = env.schema
+ this.schema = env.schema
+ this.schemaId = env.schemaId
+ this.root = env.root || this
+ this.baseId = env.baseId ?? normalizeId(schema?.[env.schemaId || "$id"])
+ this.schemaPath = env.schemaPath
+ this.localRefs = env.localRefs
+ this.meta = env.meta
+ this.$async = schema?.$async
+ this.refs = {}
+ }
+}
+
+// let codeSize = 0
+// let nodeCount = 0
+
+// Compiles schema in SchemaEnv
+export function compileSchema(this: Ajv, sch: SchemaEnv): SchemaEnv {
+ // TODO refactor - remove compilations
+ const _sch = getCompilingSchema.call(this, sch)
+ if (_sch) return _sch
+ const rootId = getFullPath(sch.root.baseId) // TODO if getFullPath removed 1 tests fails
+ const {es5, lines} = this.opts.code
+ const {ownProperties} = this.opts
+ const gen = new CodeGen(this.scope, {es5, lines, ownProperties})
+ let _ValidationError
+ if (sch.$async) {
+ _ValidationError = gen.scopeValue("Error", {
+ ref: ValidationError,
+ code: _`require("ajv/dist/runtime/validation_error").default`,
+ })
+ }
+
+ const validateName = gen.scopeName("validate")
+ sch.validateName = validateName
+
+ const schemaCxt: SchemaCxt = {
+ gen,
+ allErrors: this.opts.allErrors,
+ data: N.data,
+ parentData: N.parentData,
+ parentDataProperty: N.parentDataProperty,
+ dataNames: [N.data],
+ dataPathArr: [nil], // TODO can its length be used as dataLevel if nil is removed?
+ dataLevel: 0,
+ dataTypes: [],
+ definedProperties: new Set<string>(),
+ topSchemaRef: gen.scopeValue(
+ "schema",
+ this.opts.code.source === true
+ ? {ref: sch.schema, code: stringify(sch.schema)}
+ : {ref: sch.schema}
+ ),
+ validateName,
+ ValidationError: _ValidationError,
+ schema: sch.schema,
+ schemaEnv: sch,
+ rootId,
+ baseId: sch.baseId || rootId,
+ schemaPath: nil,
+ errSchemaPath: sch.schemaPath || (this.opts.jtd ? "" : "#"),
+ errorPath: _`""`,
+ opts: this.opts,
+ self: this,
+ }
+
+ let sourceCode: string | undefined
+ try {
+ this._compilations.add(sch)
+ validateFunctionCode(schemaCxt)
+ gen.optimize(this.opts.code.optimize)
+ // gen.optimize(1)
+ const validateCode = gen.toString()
+ sourceCode = `${gen.scopeRefs(N.scope)}return ${validateCode}`
+ // console.log((codeSize += sourceCode.length), (nodeCount += gen.nodeCount))
+ if (this.opts.code.process) sourceCode = this.opts.code.process(sourceCode, sch)
+ // console.log("\n\n\n *** \n", sourceCode)
+ const makeValidate = new Function(`${N.self}`, `${N.scope}`, sourceCode)
+ const validate: AnyValidateFunction = makeValidate(this, this.scope.get())
+ this.scope.value(validateName, {ref: validate})
+
+ validate.errors = null
+ validate.schema = sch.schema
+ validate.schemaEnv = sch
+ if (sch.$async) (validate as AsyncValidateFunction).$async = true
+ if (this.opts.code.source === true) {
+ validate.source = {validateName, validateCode, scopeValues: gen._values}
+ }
+ if (this.opts.unevaluated) {
+ const {props, items} = schemaCxt
+ validate.evaluated = {
+ props: props instanceof Name ? undefined : props,
+ items: items instanceof Name ? undefined : items,
+ dynamicProps: props instanceof Name,
+ dynamicItems: items instanceof Name,
+ }
+ if (validate.source) validate.source.evaluated = stringify(validate.evaluated)
+ }
+ sch.validate = validate
+ return sch
+ } catch (e) {
+ delete sch.validate
+ delete sch.validateName
+ if (sourceCode) this.logger.error("Error compiling schema, function code:", sourceCode)
+ // console.log("\n\n\n *** \n", sourceCode, this.opts)
+ throw e
+ } finally {
+ this._compilations.delete(sch)
+ }
+}
+
+export function resolveRef(
+ this: Ajv,
+ root: SchemaEnv,
+ baseId: string,
+ ref: string
+): AnySchema | SchemaEnv | undefined {
+ ref = resolveUrl(baseId, ref)
+ const schOrFunc = root.refs[ref]
+ if (schOrFunc) return schOrFunc
+
+ let _sch = resolve.call(this, root, ref)
+ if (_sch === undefined) {
+ const schema = root.localRefs?.[ref] // TODO maybe localRefs should hold SchemaEnv
+ const {schemaId} = this.opts
+ if (schema) _sch = new SchemaEnv({schema, schemaId, root, baseId})
+ }
+
+ if (_sch === undefined) return
+ return (root.refs[ref] = inlineOrCompile.call(this, _sch))
+}
+
+function inlineOrCompile(this: Ajv, sch: SchemaEnv): AnySchema | SchemaEnv {
+ if (inlineRef(sch.schema, this.opts.inlineRefs)) return sch.schema
+ return sch.validate ? sch : compileSchema.call(this, sch)
+}
+
+// Index of schema compilation in the currently compiled list
+export function getCompilingSchema(this: Ajv, schEnv: SchemaEnv): SchemaEnv | void {
+ for (const sch of this._compilations) {
+ if (sameSchemaEnv(sch, schEnv)) return sch
+ }
+}
+
+function sameSchemaEnv(s1: SchemaEnv, s2: SchemaEnv): boolean {
+ return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId
+}
+
+// resolve and compile the references ($ref)
+// TODO returns AnySchemaObject (if the schema can be inlined) or validation function
+function resolve(
+ this: Ajv,
+ root: SchemaEnv, // information about the root schema for the current schema
+ ref: string // reference to resolve
+): SchemaEnv | undefined {
+ let sch
+ while (typeof (sch = this.refs[ref]) == "string") ref = sch
+ return sch || this.schemas[ref] || resolveSchema.call(this, root, ref)
+}
+
+// Resolve schema, its root and baseId
+export function resolveSchema(
+ this: Ajv,
+ root: SchemaEnv, // root object with properties schema, refs TODO below SchemaEnv is assigned to it
+ ref: string // reference to resolve
+): SchemaEnv | undefined {
+ const p = URI.parse(ref)
+ const refPath = _getFullPath(p)
+ let baseId = getFullPath(root.baseId)
+ // TODO `Object.keys(root.schema).length > 0` should not be needed - but removing breaks 2 tests
+ if (Object.keys(root.schema).length > 0 && refPath === baseId) {
+ return getJsonPointer.call(this, p, root)
+ }
+
+ const id = normalizeId(refPath)
+ const schOrRef = this.refs[id] || this.schemas[id]
+ if (typeof schOrRef == "string") {
+ const sch = resolveSchema.call(this, root, schOrRef)
+ if (typeof sch?.schema !== "object") return
+ return getJsonPointer.call(this, p, sch)
+ }
+
+ if (typeof schOrRef?.schema !== "object") return
+ if (!schOrRef.validate) compileSchema.call(this, schOrRef)
+ if (id === normalizeId(ref)) {
+ const {schema} = schOrRef
+ const {schemaId} = this.opts
+ const schId = schema[schemaId]
+ if (schId) baseId = resolveUrl(baseId, schId)
+ return new SchemaEnv({schema, schemaId, root, baseId})
+ }
+ return getJsonPointer.call(this, p, schOrRef)
+}
+
+const PREVENT_SCOPE_CHANGE = new Set([
+ "properties",
+ "patternProperties",
+ "enum",
+ "dependencies",
+ "definitions",
+])
+
+function getJsonPointer(
+ this: Ajv,
+ parsedRef: URI.URIComponents,
+ {baseId, schema, root}: SchemaEnv
+): SchemaEnv | undefined {
+ if (parsedRef.fragment?.[0] !== "/") return
+ for (const part of parsedRef.fragment.slice(1).split("/")) {
+ if (typeof schema === "boolean") return
+ const partSchema = schema[unescapeFragment(part)]
+ if (partSchema === undefined) return
+ schema = partSchema
+ // TODO PREVENT_SCOPE_CHANGE could be defined in keyword def?
+ const schId = typeof schema === "object" && schema[this.opts.schemaId]
+ if (!PREVENT_SCOPE_CHANGE.has(part) && schId) {
+ baseId = resolveUrl(baseId, schId)
+ }
+ }
+ let env: SchemaEnv | undefined
+ if (typeof schema != "boolean" && schema.$ref && !schemaHasRulesButRef(schema, this.RULES)) {
+ const $ref = resolveUrl(baseId, schema.$ref)
+ env = resolveSchema.call(this, root, $ref)
+ }
+ // even though resolution failed we need to return SchemaEnv to throw exception
+ // so that compileAsync loads missing schema.
+ const {schemaId} = this.opts
+ env = env || new SchemaEnv({schema, schemaId, root, baseId})
+ if (env.schema !== env.root.schema) return env
+ return undefined
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/parse.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/parse.ts
new file mode 100644
index 00000000..cd2611e7
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/parse.ts
@@ -0,0 +1,411 @@
+import type Ajv from "../../core"
+import type {SchemaObject} from "../../types"
+import {jtdForms, JTDForm, SchemaObjectMap} from "./types"
+import {SchemaEnv, getCompilingSchema} from ".."
+import {_, str, and, or, nil, not, CodeGen, Code, Name, SafeExpr} from "../codegen"
+import MissingRefError from "../ref_error"
+import N from "../names"
+import {hasPropFunc} from "../../vocabularies/code"
+import {hasRef} from "../../vocabularies/jtd/ref"
+import {intRange, IntType} from "../../vocabularies/jtd/type"
+import {parseJson, parseJsonNumber, parseJsonString} from "../../runtime/parseJson"
+import {useFunc} from "../util"
+import validTimestamp from "../../runtime/timestamp"
+
+type GenParse = (cxt: ParseCxt) => void
+
+const genParse: {[F in JTDForm]: GenParse} = {
+ elements: parseElements,
+ values: parseValues,
+ discriminator: parseDiscriminator,
+ properties: parseProperties,
+ optionalProperties: parseProperties,
+ enum: parseEnum,
+ type: parseType,
+ ref: parseRef,
+}
+
+interface ParseCxt {
+ readonly gen: CodeGen
+ readonly self: Ajv // current Ajv instance
+ readonly schemaEnv: SchemaEnv
+ readonly definitions: SchemaObjectMap
+ schema: SchemaObject
+ data: Code
+ parseName: Name
+ char: Name
+}
+
+export default function compileParser(
+ this: Ajv,
+ sch: SchemaEnv,
+ definitions: SchemaObjectMap
+): SchemaEnv {
+ const _sch = getCompilingSchema.call(this, sch)
+ if (_sch) return _sch
+ const {es5, lines} = this.opts.code
+ const {ownProperties} = this.opts
+ const gen = new CodeGen(this.scope, {es5, lines, ownProperties})
+ const parseName = gen.scopeName("parse")
+ const cxt: ParseCxt = {
+ self: this,
+ gen,
+ schema: sch.schema as SchemaObject,
+ schemaEnv: sch,
+ definitions,
+ data: N.data,
+ parseName,
+ char: gen.name("c"),
+ }
+
+ let sourceCode: string | undefined
+ try {
+ this._compilations.add(sch)
+ sch.parseName = parseName
+ parserFunction(cxt)
+ gen.optimize(this.opts.code.optimize)
+ const parseFuncCode = gen.toString()
+ sourceCode = `${gen.scopeRefs(N.scope)}return ${parseFuncCode}`
+ const makeParse = new Function(`${N.scope}`, sourceCode)
+ const parse: (json: string) => unknown = makeParse(this.scope.get())
+ this.scope.value(parseName, {ref: parse})
+ sch.parse = parse
+ } catch (e) {
+ if (sourceCode) this.logger.error("Error compiling parser, function code:", sourceCode)
+ delete sch.parse
+ delete sch.parseName
+ throw e
+ } finally {
+ this._compilations.delete(sch)
+ }
+ return sch
+}
+
+const undef = _`undefined`
+
+function parserFunction(cxt: ParseCxt): void {
+ const {gen, parseName, char} = cxt
+ gen.func(parseName, _`${N.json}, ${N.jsonPos}, ${N.jsonPart}`, false, () => {
+ gen.let(N.data)
+ gen.let(char)
+ gen.assign(_`${parseName}.message`, undef)
+ gen.assign(_`${parseName}.position`, undef)
+ gen.assign(N.jsonPos, _`${N.jsonPos} || 0`)
+ gen.const(N.jsonLen, _`${N.json}.length`)
+ parseCode(cxt)
+ skipWhitespace(cxt)
+ gen.if(N.jsonPart, () => {
+ gen.assign(_`${parseName}.position`, N.jsonPos)
+ gen.return(N.data)
+ })
+ gen.if(_`${N.jsonPos} === ${N.jsonLen}`, () => gen.return(N.data))
+ jsonSyntaxError(cxt)
+ })
+}
+
+function parseCode(cxt: ParseCxt): void {
+ let form: JTDForm | undefined
+ for (const key of jtdForms) {
+ if (key in cxt.schema) {
+ form = key
+ break
+ }
+ }
+ if (form) parseNullable(cxt, genParse[form])
+ else parseEmpty(cxt)
+}
+
+const parseBoolean = parseBooleanToken(true, parseBooleanToken(false, jsonSyntaxError))
+
+function parseNullable(cxt: ParseCxt, parseForm: GenParse): void {
+ const {gen, schema, data} = cxt
+ if (!schema.nullable) return parseForm(cxt)
+ tryParseToken(cxt, "null", parseForm, () => gen.assign(data, null))
+}
+
+function parseElements(cxt: ParseCxt): void {
+ const {gen, schema, data} = cxt
+ parseToken(cxt, "[")
+ const ix = gen.let("i", 0)
+ gen.assign(data, _`[]`)
+ parseItems(cxt, "]", () => {
+ const el = gen.let("el")
+ parseCode({...cxt, schema: schema.elements, data: el})
+ gen.assign(_`${data}[${ix}++]`, el)
+ })
+}
+
+function parseValues(cxt: ParseCxt): void {
+ const {gen, schema, data} = cxt
+ parseToken(cxt, "{")
+ gen.assign(data, _`{}`)
+ parseItems(cxt, "}", () => parseKeyValue(cxt, schema.values))
+}
+
+function parseItems(cxt: ParseCxt, endToken: string, block: () => void): void {
+ tryParseItems(cxt, endToken, block)
+ parseToken(cxt, endToken)
+}
+
+function tryParseItems(cxt: ParseCxt, endToken: string, block: () => void): void {
+ const {gen} = cxt
+ gen.for(_`;${N.jsonPos}<${N.jsonLen} && ${jsonSlice(1)}!==${endToken};`, () => {
+ block()
+ tryParseToken(cxt, ",", () => gen.break(), hasItem)
+ })
+
+ function hasItem(): void {
+ tryParseToken(cxt, endToken, () => {}, jsonSyntaxError)
+ }
+}
+
+function parseKeyValue(cxt: ParseCxt, schema: SchemaObject): void {
+ const {gen} = cxt
+ const key = gen.let("key")
+ parseString({...cxt, data: key})
+ parseToken(cxt, ":")
+ parsePropertyValue(cxt, key, schema)
+}
+
+function parseDiscriminator(cxt: ParseCxt): void {
+ const {gen, data, schema} = cxt
+ const {discriminator, mapping} = schema
+ parseToken(cxt, "{")
+ gen.assign(data, _`{}`)
+ const startPos = gen.const("pos", N.jsonPos)
+ const value = gen.let("value")
+ const tag = gen.let("tag")
+ tryParseItems(cxt, "}", () => {
+ const key = gen.let("key")
+ parseString({...cxt, data: key})
+ parseToken(cxt, ":")
+ gen.if(
+ _`${key} === ${discriminator}`,
+ () => {
+ parseString({...cxt, data: tag})
+ gen.assign(_`${data}[${key}]`, tag)
+ gen.break()
+ },
+ () => parseEmpty({...cxt, data: value}) // can be discarded/skipped
+ )
+ })
+ gen.assign(N.jsonPos, startPos)
+ gen.if(_`${tag} === undefined`)
+ parsingError(cxt, str`discriminator tag not found`)
+ for (const tagValue in mapping) {
+ gen.elseIf(_`${tag} === ${tagValue}`)
+ parseSchemaProperties({...cxt, schema: mapping[tagValue]}, discriminator)
+ }
+ gen.else()
+ parsingError(cxt, str`discriminator value not in schema`)
+ gen.endIf()
+}
+
+function parseProperties(cxt: ParseCxt): void {
+ const {gen, data} = cxt
+ parseToken(cxt, "{")
+ gen.assign(data, _`{}`)
+ parseSchemaProperties(cxt)
+}
+
+function parseSchemaProperties(cxt: ParseCxt, discriminator?: string): void {
+ const {gen, schema, data} = cxt
+ const {properties, optionalProperties, additionalProperties} = schema
+ parseItems(cxt, "}", () => {
+ const key = gen.let("key")
+ parseString({...cxt, data: key})
+ parseToken(cxt, ":")
+ gen.if(false)
+ parseDefinedProperty(cxt, key, properties)
+ parseDefinedProperty(cxt, key, optionalProperties)
+ if (discriminator) {
+ gen.elseIf(_`${key} === ${discriminator}`)
+ const tag = gen.let("tag")
+ parseString({...cxt, data: tag}) // can be discarded, it is already assigned
+ }
+ gen.else()
+ if (additionalProperties) {
+ parseEmpty({...cxt, data: _`${data}[${key}]`})
+ } else {
+ parsingError(cxt, str`property ${key} not allowed`)
+ }
+ gen.endIf()
+ })
+ if (properties) {
+ const hasProp = hasPropFunc(gen)
+ const allProps: Code = and(
+ ...Object.keys(properties).map((p): Code => _`${hasProp}.call(${data}, ${p})`)
+ )
+ gen.if(not(allProps), () => parsingError(cxt, str`missing required properties`))
+ }
+}
+
+function parseDefinedProperty(cxt: ParseCxt, key: Name, schemas: SchemaObjectMap = {}): void {
+ const {gen} = cxt
+ for (const prop in schemas) {
+ gen.elseIf(_`${key} === ${prop}`)
+ parsePropertyValue(cxt, key, schemas[prop] as SchemaObject)
+ }
+}
+
+function parsePropertyValue(cxt: ParseCxt, key: Name, schema: SchemaObject): void {
+ parseCode({...cxt, schema, data: _`${cxt.data}[${key}]`})
+}
+
+function parseType(cxt: ParseCxt): void {
+ const {gen, schema, data, self} = cxt
+ switch (schema.type) {
+ case "boolean":
+ parseBoolean(cxt)
+ break
+ case "string":
+ parseString(cxt)
+ break
+ case "timestamp": {
+ parseString(cxt)
+ const vts = useFunc(gen, validTimestamp)
+ const {allowDate, parseDate} = self.opts
+ const notValid = allowDate ? _`!${vts}(${data}, true)` : _`!${vts}(${data})`
+ const fail: Code = parseDate
+ ? or(notValid, _`(${data} = new Date(${data}), false)`, _`isNaN(${data}.valueOf())`)
+ : notValid
+ gen.if(fail, () => parsingError(cxt, str`invalid timestamp`))
+ break
+ }
+ case "float32":
+ case "float64":
+ parseNumber(cxt)
+ break
+ default: {
+ const t = schema.type as IntType
+ if (!self.opts.int32range && (t === "int32" || t === "uint32")) {
+ parseNumber(cxt, 16) // 2 ** 53 - max safe integer
+ if (t === "uint32") {
+ gen.if(_`${data} < 0`, () => parsingError(cxt, str`integer out of range`))
+ }
+ } else {
+ const [min, max, maxDigits] = intRange[t]
+ parseNumber(cxt, maxDigits)
+ gen.if(_`${data} < ${min} || ${data} > ${max}`, () =>
+ parsingError(cxt, str`integer out of range`)
+ )
+ }
+ }
+ }
+}
+
+function parseString(cxt: ParseCxt): void {
+ parseToken(cxt, '"')
+ parseWith(cxt, parseJsonString)
+}
+
+function parseEnum(cxt: ParseCxt): void {
+ const {gen, data, schema} = cxt
+ const enumSch = schema.enum
+ parseToken(cxt, '"')
+ // TODO loopEnum
+ gen.if(false)
+ for (const value of enumSch) {
+ const valueStr = JSON.stringify(value).slice(1) // remove starting quote
+ gen.elseIf(_`${jsonSlice(valueStr.length)} === ${valueStr}`)
+ gen.assign(data, str`${value}`)
+ gen.add(N.jsonPos, valueStr.length)
+ }
+ gen.else()
+ jsonSyntaxError(cxt)
+ gen.endIf()
+}
+
+function parseNumber(cxt: ParseCxt, maxDigits?: number): void {
+ const {gen} = cxt
+ skipWhitespace(cxt)
+ gen.if(
+ _`"-0123456789".indexOf(${jsonSlice(1)}) < 0`,
+ () => jsonSyntaxError(cxt),
+ () => parseWith(cxt, parseJsonNumber, maxDigits)
+ )
+}
+
+function parseBooleanToken(bool: boolean, fail: GenParse): GenParse {
+ return (cxt) => {
+ const {gen, data} = cxt
+ tryParseToken(
+ cxt,
+ `${bool}`,
+ () => fail(cxt),
+ () => gen.assign(data, bool)
+ )
+ }
+}
+
+function parseRef(cxt: ParseCxt): void {
+ const {gen, self, definitions, schema, schemaEnv} = cxt
+ const {ref} = schema
+ const refSchema = definitions[ref]
+ if (!refSchema) throw new MissingRefError("", ref, `No definition ${ref}`)
+ if (!hasRef(refSchema)) return parseCode({...cxt, schema: refSchema})
+ const {root} = schemaEnv
+ const sch = compileParser.call(self, new SchemaEnv({schema: refSchema, root}), definitions)
+ partialParse(cxt, getParser(gen, sch), true)
+}
+
+function getParser(gen: CodeGen, sch: SchemaEnv): Code {
+ return sch.parse
+ ? gen.scopeValue("parse", {ref: sch.parse})
+ : _`${gen.scopeValue("wrapper", {ref: sch})}.parse`
+}
+
+function parseEmpty(cxt: ParseCxt): void {
+ parseWith(cxt, parseJson)
+}
+
+function parseWith(cxt: ParseCxt, parseFunc: {code: string}, args?: SafeExpr): void {
+ partialParse(cxt, useFunc(cxt.gen, parseFunc), args)
+}
+
+function partialParse(cxt: ParseCxt, parseFunc: Name, args?: SafeExpr): void {
+ const {gen, data} = cxt
+ gen.assign(data, _`${parseFunc}(${N.json}, ${N.jsonPos}${args ? _`, ${args}` : nil})`)
+ gen.assign(N.jsonPos, _`${parseFunc}.position`)
+ gen.if(_`${data} === undefined`, () => parsingError(cxt, _`${parseFunc}.message`))
+}
+
+function parseToken(cxt: ParseCxt, tok: string): void {
+ tryParseToken(cxt, tok, jsonSyntaxError)
+}
+
+function tryParseToken(cxt: ParseCxt, tok: string, fail: GenParse, success?: GenParse): void {
+ const {gen} = cxt
+ const n = tok.length
+ skipWhitespace(cxt)
+ gen.if(
+ _`${jsonSlice(n)} === ${tok}`,
+ () => {
+ gen.add(N.jsonPos, n)
+ success?.(cxt)
+ },
+ () => fail(cxt)
+ )
+}
+
+function skipWhitespace({gen, char: c}: ParseCxt): void {
+ gen.code(
+ _`while((${c}=${N.json}[${N.jsonPos}],${c}===" "||${c}==="\\n"||${c}==="\\r"||${c}==="\\t"))${N.jsonPos}++;`
+ )
+}
+
+function jsonSlice(len: number | Name): Code {
+ return len === 1
+ ? _`${N.json}[${N.jsonPos}]`
+ : _`${N.json}.slice(${N.jsonPos}, ${N.jsonPos}+${len})`
+}
+
+function jsonSyntaxError(cxt: ParseCxt): void {
+ parsingError(cxt, _`"unexpected token " + ${N.json}[${N.jsonPos}]`)
+}
+
+function parsingError({gen, parseName}: ParseCxt, msg: Code): void {
+ gen.assign(_`${parseName}.message`, msg)
+ gen.assign(_`${parseName}.position`, N.jsonPos)
+ gen.return(undef)
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/serialize.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/serialize.ts
new file mode 100644
index 00000000..a8b36bd8
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/serialize.ts
@@ -0,0 +1,260 @@
+import type Ajv from "../../core"
+import type {SchemaObject} from "../../types"
+import {jtdForms, JTDForm, SchemaObjectMap} from "./types"
+import {SchemaEnv, getCompilingSchema} from ".."
+import {_, str, and, getProperty, CodeGen, Code, Name} from "../codegen"
+import MissingRefError from "../ref_error"
+import N from "../names"
+import {isOwnProperty} from "../../vocabularies/code"
+import {hasRef} from "../../vocabularies/jtd/ref"
+import {useFunc} from "../util"
+import quote from "../../runtime/quote"
+
+const genSerialize: {[F in JTDForm]: (cxt: SerializeCxt) => void} = {
+ elements: serializeElements,
+ values: serializeValues,
+ discriminator: serializeDiscriminator,
+ properties: serializeProperties,
+ optionalProperties: serializeProperties,
+ enum: serializeString,
+ type: serializeType,
+ ref: serializeRef,
+}
+
+interface SerializeCxt {
+ readonly gen: CodeGen
+ readonly self: Ajv // current Ajv instance
+ readonly schemaEnv: SchemaEnv
+ readonly definitions: SchemaObjectMap
+ schema: SchemaObject
+ data: Code
+}
+
+export default function compileSerializer(
+ this: Ajv,
+ sch: SchemaEnv,
+ definitions: SchemaObjectMap
+): SchemaEnv {
+ const _sch = getCompilingSchema.call(this, sch)
+ if (_sch) return _sch
+ const {es5, lines} = this.opts.code
+ const {ownProperties} = this.opts
+ const gen = new CodeGen(this.scope, {es5, lines, ownProperties})
+ const serializeName = gen.scopeName("serialize")
+ const cxt: SerializeCxt = {
+ self: this,
+ gen,
+ schema: sch.schema as SchemaObject,
+ schemaEnv: sch,
+ definitions,
+ data: N.data,
+ }
+
+ let sourceCode: string | undefined
+ try {
+ this._compilations.add(sch)
+ sch.serializeName = serializeName
+ gen.func(serializeName, N.data, false, () => {
+ gen.let(N.json, str``)
+ serializeCode(cxt)
+ gen.return(N.json)
+ })
+ gen.optimize(this.opts.code.optimize)
+ const serializeFuncCode = gen.toString()
+ sourceCode = `${gen.scopeRefs(N.scope)}return ${serializeFuncCode}`
+ const makeSerialize = new Function(`${N.scope}`, sourceCode)
+ const serialize: (data: unknown) => string = makeSerialize(this.scope.get())
+ this.scope.value(serializeName, {ref: serialize})
+ sch.serialize = serialize
+ } catch (e) {
+ if (sourceCode) this.logger.error("Error compiling serializer, function code:", sourceCode)
+ delete sch.serialize
+ delete sch.serializeName
+ throw e
+ } finally {
+ this._compilations.delete(sch)
+ }
+ return sch
+}
+
+function serializeCode(cxt: SerializeCxt): void {
+ let form: JTDForm | undefined
+ for (const key of jtdForms) {
+ if (key in cxt.schema) {
+ form = key
+ break
+ }
+ }
+ serializeNullable(cxt, form ? genSerialize[form] : serializeEmpty)
+}
+
+function serializeNullable(cxt: SerializeCxt, serializeForm: (_cxt: SerializeCxt) => void): void {
+ const {gen, schema, data} = cxt
+ if (!schema.nullable) return serializeForm(cxt)
+ gen.if(
+ _`${data} === undefined || ${data} === null`,
+ () => gen.add(N.json, _`"null"`),
+ () => serializeForm(cxt)
+ )
+}
+
+function serializeElements(cxt: SerializeCxt): void {
+ const {gen, schema, data} = cxt
+ gen.add(N.json, str`[`)
+ const first = gen.let("first", true)
+ gen.forOf("el", data, (el) => {
+ addComma(cxt, first)
+ serializeCode({...cxt, schema: schema.elements, data: el})
+ })
+ gen.add(N.json, str`]`)
+}
+
+function serializeValues(cxt: SerializeCxt): void {
+ const {gen, schema, data} = cxt
+ gen.add(N.json, str`{`)
+ const first = gen.let("first", true)
+ gen.forIn("key", data, (key) => serializeKeyValue(cxt, key, schema.values, first))
+ gen.add(N.json, str`}`)
+}
+
+function serializeKeyValue(cxt: SerializeCxt, key: Name, schema: SchemaObject, first: Name): void {
+ const {gen, data} = cxt
+ addComma(cxt, first)
+ serializeString({...cxt, data: key})
+ gen.add(N.json, str`:`)
+ const value = gen.const("value", _`${data}${getProperty(key)}`)
+ serializeCode({...cxt, schema, data: value})
+}
+
+function serializeDiscriminator(cxt: SerializeCxt): void {
+ const {gen, schema, data} = cxt
+ const {discriminator} = schema
+ gen.add(N.json, str`{${JSON.stringify(discriminator)}:`)
+ const tag = gen.const("tag", _`${data}${getProperty(discriminator)}`)
+ serializeString({...cxt, data: tag})
+ gen.if(false)
+ for (const tagValue in schema.mapping) {
+ gen.elseIf(_`${tag} === ${tagValue}`)
+ const sch = schema.mapping[tagValue]
+ serializeSchemaProperties({...cxt, schema: sch}, discriminator)
+ }
+ gen.endIf()
+ gen.add(N.json, str`}`)
+}
+
+function serializeProperties(cxt: SerializeCxt): void {
+ const {gen} = cxt
+ gen.add(N.json, str`{`)
+ serializeSchemaProperties(cxt)
+ gen.add(N.json, str`}`)
+}
+
+function serializeSchemaProperties(cxt: SerializeCxt, discriminator?: string): void {
+ const {gen, schema, data} = cxt
+ const {properties, optionalProperties} = schema
+ const props = keys(properties)
+ const optProps = keys(optionalProperties)
+ const allProps = allProperties(props.concat(optProps))
+ let first = !discriminator
+ for (const key of props) {
+ serializeProperty(key, properties[key], keyValue(key))
+ }
+ for (const key of optProps) {
+ const value = keyValue(key)
+ gen.if(and(_`${value} !== undefined`, isOwnProperty(gen, data, key)), () =>
+ serializeProperty(key, optionalProperties[key], value)
+ )
+ }
+ if (schema.additionalProperties) {
+ gen.forIn("key", data, (key) =>
+ gen.if(isAdditional(key, allProps), () =>
+ serializeKeyValue(cxt, key, {}, gen.let("first", first))
+ )
+ )
+ }
+
+ function keys(ps?: SchemaObjectMap): string[] {
+ return ps ? Object.keys(ps) : []
+ }
+
+ function allProperties(ps: string[]): string[] {
+ if (discriminator) ps.push(discriminator)
+ if (new Set(ps).size !== ps.length) {
+ throw new Error("JTD: properties/optionalProperties/disciminator overlap")
+ }
+ return ps
+ }
+
+ function keyValue(key: string): Name {
+ return gen.const("value", _`${data}${getProperty(key)}`)
+ }
+
+ function serializeProperty(key: string, propSchema: SchemaObject, value: Name): void {
+ if (first) first = false
+ else gen.add(N.json, str`,`)
+ gen.add(N.json, str`${JSON.stringify(key)}:`)
+ serializeCode({...cxt, schema: propSchema, data: value})
+ }
+
+ function isAdditional(key: Name, ps: string[]): Code | true {
+ return ps.length ? and(...ps.map((p) => _`${key} !== ${p}`)) : true
+ }
+}
+
+function serializeType(cxt: SerializeCxt): void {
+ const {gen, schema, data} = cxt
+ switch (schema.type) {
+ case "boolean":
+ gen.add(N.json, _`${data} ? "true" : "false"`)
+ break
+ case "string":
+ serializeString(cxt)
+ break
+ case "timestamp":
+ gen.if(
+ _`${data} instanceof Date`,
+ () => gen.add(N.json, _`'"' + ${data}.toISOString() + '"'`),
+ () => serializeString(cxt)
+ )
+ break
+ default:
+ serializeNumber(cxt)
+ }
+}
+
+function serializeString({gen, data}: SerializeCxt): void {
+ gen.add(N.json, _`${useFunc(gen, quote)}(${data})`)
+}
+
+function serializeNumber({gen, data}: SerializeCxt): void {
+ gen.add(N.json, _`"" + ${data}`)
+}
+
+function serializeRef(cxt: SerializeCxt): void {
+ const {gen, self, data, definitions, schema, schemaEnv} = cxt
+ const {ref} = schema
+ const refSchema = definitions[ref]
+ if (!refSchema) throw new MissingRefError("", ref, `No definition ${ref}`)
+ if (!hasRef(refSchema)) return serializeCode({...cxt, schema: refSchema})
+ const {root} = schemaEnv
+ const sch = compileSerializer.call(self, new SchemaEnv({schema: refSchema, root}), definitions)
+ gen.add(N.json, _`${getSerialize(gen, sch)}(${data})`)
+}
+
+function getSerialize(gen: CodeGen, sch: SchemaEnv): Code {
+ return sch.serialize
+ ? gen.scopeValue("serialize", {ref: sch.serialize})
+ : _`${gen.scopeValue("wrapper", {ref: sch})}.serialize`
+}
+
+function serializeEmpty({gen, data}: SerializeCxt): void {
+ gen.add(N.json, _`JSON.stringify(${data})`)
+}
+
+function addComma({gen}: SerializeCxt, first: Name): void {
+ gen.if(
+ first,
+ () => gen.assign(first, false),
+ () => gen.add(N.json, str`,`)
+ )
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/types.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/types.ts
new file mode 100644
index 00000000..7f361957
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/jtd/types.ts
@@ -0,0 +1,16 @@
+import type {SchemaObject} from "../../types"
+
+export type SchemaObjectMap = {[Ref in string]?: SchemaObject}
+
+export const jtdForms = [
+ "elements",
+ "values",
+ "discriminator",
+ "properties",
+ "optionalProperties",
+ "enum",
+ "type",
+ "ref",
+] as const
+
+export type JTDForm = typeof jtdForms[number]
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/names.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/names.ts
new file mode 100644
index 00000000..b4b242e1
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/names.ts
@@ -0,0 +1,27 @@
+import {Name} from "./codegen"
+
+const names = {
+ // validation function arguments
+ data: new Name("data"), // data passed to validation function
+ // args passed from referencing schema
+ valCxt: new Name("valCxt"), // validation/data context - should not be used directly, it is destructured to the names below
+ instancePath: new Name("instancePath"),
+ parentData: new Name("parentData"),
+ parentDataProperty: new Name("parentDataProperty"),
+ rootData: new Name("rootData"), // root data - same as the data passed to the first/top validation function
+ dynamicAnchors: new Name("dynamicAnchors"), // used to support recursiveRef and dynamicRef
+ // function scoped variables
+ vErrors: new Name("vErrors"), // null or array of validation errors
+ errors: new Name("errors"), // counter of validation errors
+ this: new Name("this"),
+ // "globals"
+ self: new Name("self"),
+ scope: new Name("scope"),
+ // JTD serialize/parse name for JSON string and position
+ json: new Name("json"),
+ jsonPos: new Name("jsonPos"),
+ jsonLen: new Name("jsonLen"),
+ jsonPart: new Name("jsonPart"),
+}
+
+export default names
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/ref_error.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/ref_error.ts
new file mode 100644
index 00000000..22b70b99
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/ref_error.ts
@@ -0,0 +1,12 @@
+import {resolveUrl, normalizeId, getFullPath} from "./resolve"
+
+export default class MissingRefError extends Error {
+ readonly missingRef: string
+ readonly missingSchema: string
+
+ constructor(baseId: string, ref: string, msg?: string) {
+ super(msg || `can't resolve reference ${ref} from id ${baseId}`)
+ this.missingRef = resolveUrl(baseId, ref)
+ this.missingSchema = normalizeId(getFullPath(this.missingRef))
+ }
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/resolve.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/resolve.ts
new file mode 100644
index 00000000..9031e039
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/resolve.ts
@@ -0,0 +1,146 @@
+import type {AnySchema, AnySchemaObject} from "../types"
+import type Ajv from "../ajv"
+import {eachItem} from "./util"
+import * as equal from "fast-deep-equal"
+import * as traverse from "json-schema-traverse"
+import * as URI from "uri-js"
+
+// the hash of local references inside the schema (created by getSchemaRefs), used for inline resolution
+export type LocalRefs = {[Ref in string]?: AnySchemaObject}
+
+// TODO refactor to use keyword definitions
+const SIMPLE_INLINED = new Set([
+ "type",
+ "format",
+ "pattern",
+ "maxLength",
+ "minLength",
+ "maxProperties",
+ "minProperties",
+ "maxItems",
+ "minItems",
+ "maximum",
+ "minimum",
+ "uniqueItems",
+ "multipleOf",
+ "required",
+ "enum",
+ "const",
+])
+
+export function inlineRef(schema: AnySchema, limit: boolean | number = true): boolean {
+ if (typeof schema == "boolean") return true
+ if (limit === true) return !hasRef(schema)
+ if (!limit) return false
+ return countKeys(schema) <= limit
+}
+
+const REF_KEYWORDS = new Set([
+ "$ref",
+ "$recursiveRef",
+ "$recursiveAnchor",
+ "$dynamicRef",
+ "$dynamicAnchor",
+])
+
+function hasRef(schema: AnySchemaObject): boolean {
+ for (const key in schema) {
+ if (REF_KEYWORDS.has(key)) return true
+ const sch = schema[key]
+ if (Array.isArray(sch) && sch.some(hasRef)) return true
+ if (typeof sch == "object" && hasRef(sch)) return true
+ }
+ return false
+}
+
+function countKeys(schema: AnySchemaObject): number {
+ let count = 0
+ for (const key in schema) {
+ if (key === "$ref") return Infinity
+ count++
+ if (SIMPLE_INLINED.has(key)) continue
+ if (typeof schema[key] == "object") {
+ eachItem(schema[key], (sch) => (count += countKeys(sch)))
+ }
+ if (count === Infinity) return Infinity
+ }
+ return count
+}
+
+export function getFullPath(id = "", normalize?: boolean): string {
+ if (normalize !== false) id = normalizeId(id)
+ const p = URI.parse(id)
+ return _getFullPath(p)
+}
+
+export function _getFullPath(p: URI.URIComponents): string {
+ return URI.serialize(p).split("#")[0] + "#"
+}
+
+const TRAILING_SLASH_HASH = /#\/?$/
+export function normalizeId(id: string | undefined): string {
+ return id ? id.replace(TRAILING_SLASH_HASH, "") : ""
+}
+
+export function resolveUrl(baseId: string, id: string): string {
+ id = normalizeId(id)
+ return URI.resolve(baseId, id)
+}
+
+const ANCHOR = /^[a-z_][-a-z0-9._]*$/i
+
+export function getSchemaRefs(this: Ajv, schema: AnySchema, baseId: string): LocalRefs {
+ if (typeof schema == "boolean") return {}
+ const {schemaId} = this.opts
+ const schId = normalizeId(schema[schemaId] || baseId)
+ const baseIds: {[JsonPtr in string]?: string} = {"": schId}
+ const pathPrefix = getFullPath(schId, false)
+ const localRefs: LocalRefs = {}
+ const schemaRefs: Set<string> = new Set()
+
+ traverse(schema, {allKeys: true}, (sch, jsonPtr, _, parentJsonPtr) => {
+ if (parentJsonPtr === undefined) return
+ const fullPath = pathPrefix + jsonPtr
+ let baseId = baseIds[parentJsonPtr]
+ if (typeof sch[schemaId] == "string") baseId = addRef.call(this, sch[schemaId])
+ addAnchor.call(this, sch.$anchor)
+ addAnchor.call(this, sch.$dynamicAnchor)
+ baseIds[jsonPtr] = baseId
+
+ function addRef(this: Ajv, ref: string): string {
+ ref = normalizeId(baseId ? URI.resolve(baseId, ref) : ref)
+ if (schemaRefs.has(ref)) throw ambiguos(ref)
+ schemaRefs.add(ref)
+ let schOrRef = this.refs[ref]
+ if (typeof schOrRef == "string") schOrRef = this.refs[schOrRef]
+ if (typeof schOrRef == "object") {
+ checkAmbiguosRef(sch, schOrRef.schema, ref)
+ } else if (ref !== normalizeId(fullPath)) {
+ if (ref[0] === "#") {
+ checkAmbiguosRef(sch, localRefs[ref], ref)
+ localRefs[ref] = sch
+ } else {
+ this.refs[ref] = fullPath
+ }
+ }
+ return ref
+ }
+
+ function addAnchor(this: Ajv, anchor: unknown): void {
+ if (typeof anchor == "string") {
+ if (!ANCHOR.test(anchor)) throw new Error(`invalid anchor "${anchor}"`)
+ addRef.call(this, `#${anchor}`)
+ }
+ }
+ })
+
+ return localRefs
+
+ function checkAmbiguosRef(sch1: AnySchema, sch2: AnySchema | undefined, ref: string): void {
+ if (sch2 !== undefined && !equal(sch1, sch2)) throw ambiguos(ref)
+ }
+
+ function ambiguos(ref: string): Error {
+ return new Error(`reference "${ref}" resolves to more than one schema`)
+ }
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/rules.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/rules.ts
new file mode 100644
index 00000000..ea65074f
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/rules.ts
@@ -0,0 +1,50 @@
+import type {AddedKeywordDefinition} from "../types"
+
+const _jsonTypes = ["string", "number", "integer", "boolean", "null", "object", "array"] as const
+
+export type JSONType = typeof _jsonTypes[number]
+
+const jsonTypes: Set<string> = new Set(_jsonTypes)
+
+export function isJSONType(x: unknown): x is JSONType {
+ return typeof x == "string" && jsonTypes.has(x)
+}
+
+type ValidationTypes = {
+ [K in JSONType]: boolean | RuleGroup | undefined
+}
+
+export interface ValidationRules {
+ rules: RuleGroup[]
+ post: RuleGroup
+ all: {[Key in string]?: boolean | Rule} // rules that have to be validated
+ keywords: {[Key in string]?: boolean} // all known keywords (superset of "all")
+ types: ValidationTypes
+}
+
+export interface RuleGroup {
+ type?: JSONType
+ rules: Rule[]
+}
+
+// This interface wraps KeywordDefinition because definition can have multiple keywords
+export interface Rule {
+ keyword: string
+ definition: AddedKeywordDefinition
+}
+
+export function getRules(): ValidationRules {
+ const groups: Record<"number" | "string" | "array" | "object", RuleGroup> = {
+ number: {type: "number", rules: []},
+ string: {type: "string", rules: []},
+ array: {type: "array", rules: []},
+ object: {type: "object", rules: []},
+ }
+ return {
+ types: {...groups, integer: true, boolean: true, null: true},
+ rules: [{rules: []}, groups.number, groups.string, groups.array, groups.object],
+ post: {rules: []},
+ all: {},
+ keywords: {},
+ }
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/util.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/util.ts
new file mode 100644
index 00000000..cefae51c
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/util.ts
@@ -0,0 +1,213 @@
+import type {AnySchema, EvaluatedProperties, EvaluatedItems} from "../types"
+import type {SchemaCxt, SchemaObjCxt} from "."
+import {_, getProperty, Code, Name, CodeGen} from "./codegen"
+import {_Code} from "./codegen/code"
+import type {Rule, ValidationRules} from "./rules"
+
+// TODO refactor to use Set
+export function toHash<T extends string = string>(arr: T[]): {[K in T]?: true} {
+ const hash: {[K in T]?: true} = {}
+ for (const item of arr) hash[item] = true
+ return hash
+}
+
+export function alwaysValidSchema(it: SchemaCxt, schema: AnySchema): boolean | void {
+ if (typeof schema == "boolean") return schema
+ if (Object.keys(schema).length === 0) return true
+ checkUnknownRules(it, schema)
+ return !schemaHasRules(schema, it.self.RULES.all)
+}
+
+export function checkUnknownRules(it: SchemaCxt, schema: AnySchema = it.schema): void {
+ const {opts, self} = it
+ if (!opts.strictSchema) return
+ if (typeof schema === "boolean") return
+ const rules = self.RULES.keywords
+ for (const key in schema) {
+ if (!rules[key]) checkStrictMode(it, `unknown keyword: "${key}"`)
+ }
+}
+
+export function schemaHasRules(
+ schema: AnySchema,
+ rules: {[Key in string]?: boolean | Rule}
+): boolean {
+ if (typeof schema == "boolean") return !schema
+ for (const key in schema) if (rules[key]) return true
+ return false
+}
+
+export function schemaHasRulesButRef(schema: AnySchema, RULES: ValidationRules): boolean {
+ if (typeof schema == "boolean") return !schema
+ for (const key in schema) if (key !== "$ref" && RULES.all[key]) return true
+ return false
+}
+
+export function schemaRefOrVal(
+ {topSchemaRef, schemaPath}: SchemaObjCxt,
+ schema: unknown,
+ keyword: string,
+ $data?: string | false
+): Code | number | boolean {
+ if (!$data) {
+ if (typeof schema == "number" || typeof schema == "boolean") return schema
+ if (typeof schema == "string") return _`${schema}`
+ }
+ return _`${topSchemaRef}${schemaPath}${getProperty(keyword)}`
+}
+
+export function unescapeFragment(str: string): string {
+ return unescapeJsonPointer(decodeURIComponent(str))
+}
+
+export function escapeFragment(str: string | number): string {
+ return encodeURIComponent(escapeJsonPointer(str))
+}
+
+export function escapeJsonPointer(str: string | number): string {
+ if (typeof str == "number") return `${str}`
+ return str.replace(/~/g, "~0").replace(/\//g, "~1")
+}
+
+export function unescapeJsonPointer(str: string): string {
+ return str.replace(/~1/g, "/").replace(/~0/g, "~")
+}
+
+export function eachItem<T>(xs: T | T[], f: (x: T) => void): void {
+ if (Array.isArray(xs)) {
+ for (const x of xs) f(x)
+ } else {
+ f(xs)
+ }
+}
+
+type SomeEvaluated = EvaluatedProperties | EvaluatedItems
+
+type MergeEvaluatedFunc<T extends SomeEvaluated> = (
+ gen: CodeGen,
+ from: Name | T,
+ to: Name | Exclude<T, true> | undefined,
+ toName?: typeof Name
+) => Name | T
+
+interface MakeMergeFuncArgs<T extends SomeEvaluated> {
+ mergeNames: (gen: CodeGen, from: Name, to: Name) => void
+ mergeToName: (gen: CodeGen, from: T, to: Name) => void
+ mergeValues: (from: T, to: Exclude<T, true>) => T
+ resultToName: (gen: CodeGen, res?: T) => Name
+}
+
+function makeMergeEvaluated<T extends SomeEvaluated>({
+ mergeNames,
+ mergeToName,
+ mergeValues,
+ resultToName,
+}: MakeMergeFuncArgs<T>): MergeEvaluatedFunc<T> {
+ return (gen, from, to, toName) => {
+ const res =
+ to === undefined
+ ? from
+ : to instanceof Name
+ ? (from instanceof Name ? mergeNames(gen, from, to) : mergeToName(gen, from, to), to)
+ : from instanceof Name
+ ? (mergeToName(gen, to, from), from)
+ : mergeValues(from, to)
+ return toName === Name && !(res instanceof Name) ? resultToName(gen, res) : res
+ }
+}
+
+interface MergeEvaluated {
+ props: MergeEvaluatedFunc<EvaluatedProperties>
+ items: MergeEvaluatedFunc<EvaluatedItems>
+}
+
+export const mergeEvaluated: MergeEvaluated = {
+ props: makeMergeEvaluated({
+ mergeNames: (gen, from, to) =>
+ gen.if(_`${to} !== true && ${from} !== undefined`, () => {
+ gen.if(
+ _`${from} === true`,
+ () => gen.assign(to, true),
+ () => gen.assign(to, _`${to} || {}`).code(_`Object.assign(${to}, ${from})`)
+ )
+ }),
+ mergeToName: (gen, from, to) =>
+ gen.if(_`${to} !== true`, () => {
+ if (from === true) {
+ gen.assign(to, true)
+ } else {
+ gen.assign(to, _`${to} || {}`)
+ setEvaluated(gen, to, from)
+ }
+ }),
+ mergeValues: (from, to) => (from === true ? true : {...from, ...to}),
+ resultToName: evaluatedPropsToName,
+ }),
+ items: makeMergeEvaluated({
+ mergeNames: (gen, from, to) =>
+ gen.if(_`${to} !== true && ${from} !== undefined`, () =>
+ gen.assign(to, _`${from} === true ? true : ${to} > ${from} ? ${to} : ${from}`)
+ ),
+ mergeToName: (gen, from, to) =>
+ gen.if(_`${to} !== true`, () =>
+ gen.assign(to, from === true ? true : _`${to} > ${from} ? ${to} : ${from}`)
+ ),
+ mergeValues: (from, to) => (from === true ? true : Math.max(from, to)),
+ resultToName: (gen, items) => gen.var("items", items),
+ }),
+}
+
+export function evaluatedPropsToName(gen: CodeGen, ps?: EvaluatedProperties): Name {
+ if (ps === true) return gen.var("props", true)
+ const props = gen.var("props", _`{}`)
+ if (ps !== undefined) setEvaluated(gen, props, ps)
+ return props
+}
+
+export function setEvaluated(gen: CodeGen, props: Name, ps: {[K in string]?: true}): void {
+ Object.keys(ps).forEach((p) => gen.assign(_`${props}${getProperty(p)}`, true))
+}
+
+const snippets: {[S in string]?: _Code} = {}
+
+export function useFunc(gen: CodeGen, f: {code: string}): Name {
+ return gen.scopeValue("func", {
+ ref: f,
+ code: snippets[f.code] || (snippets[f.code] = new _Code(f.code)),
+ })
+}
+
+export enum Type {
+ Num,
+ Str,
+}
+
+export function getErrorPath(
+ dataProp: Name | string | number,
+ dataPropType?: Type,
+ jsPropertySyntax?: boolean
+): Code | string {
+ // let path
+ if (dataProp instanceof Name) {
+ const isNumber = dataPropType === Type.Num
+ return jsPropertySyntax
+ ? isNumber
+ ? _`"[" + ${dataProp} + "]"`
+ : _`"['" + ${dataProp} + "']"`
+ : isNumber
+ ? _`"/" + ${dataProp}`
+ : _`"/" + ${dataProp}.replace(/~/g, "~0").replace(/\\//g, "~1")` // TODO maybe use global escapePointer
+ }
+ return jsPropertySyntax ? getProperty(dataProp).toString() : "/" + escapeJsonPointer(dataProp)
+}
+
+export function checkStrictMode(
+ it: SchemaCxt,
+ msg: string,
+ mode: boolean | "log" = it.opts.strictSchema
+): void {
+ if (!mode) return
+ msg = `strict mode: ${msg}`
+ if (mode === true) throw new Error(msg)
+ it.self.logger.warn(msg)
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/applicability.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/applicability.ts
new file mode 100644
index 00000000..478b704a
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/applicability.ts
@@ -0,0 +1,22 @@
+import type {AnySchemaObject} from "../../types"
+import type {SchemaObjCxt} from ".."
+import type {JSONType, RuleGroup, Rule} from "../rules"
+
+export function schemaHasRulesForType(
+ {schema, self}: SchemaObjCxt,
+ type: JSONType
+): boolean | undefined {
+ const group = self.RULES.types[type]
+ return group && group !== true && shouldUseGroup(schema, group)
+}
+
+export function shouldUseGroup(schema: AnySchemaObject, group: RuleGroup): boolean {
+ return group.rules.some((rule) => shouldUseRule(schema, rule))
+}
+
+export function shouldUseRule(schema: AnySchemaObject, rule: Rule): boolean | undefined {
+ return (
+ schema[rule.keyword] !== undefined ||
+ rule.definition.implements?.some((kwd) => schema[kwd] !== undefined)
+ )
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/boolSchema.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/boolSchema.ts
new file mode 100644
index 00000000..15635501
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/boolSchema.ts
@@ -0,0 +1,47 @@
+import type {KeywordErrorDefinition, KeywordErrorCxt} from "../../types"
+import type {SchemaCxt} from ".."
+import {reportError} from "../errors"
+import {_, Name} from "../codegen"
+import N from "../names"
+
+const boolError: KeywordErrorDefinition = {
+ message: "boolean schema is false",
+}
+
+export function topBoolOrEmptySchema(it: SchemaCxt): void {
+ const {gen, schema, validateName} = it
+ if (schema === false) {
+ falseSchemaError(it, false)
+ } else if (typeof schema == "object" && schema.$async === true) {
+ gen.return(N.data)
+ } else {
+ gen.assign(_`${validateName}.errors`, null)
+ gen.return(true)
+ }
+}
+
+export function boolOrEmptySchema(it: SchemaCxt, valid: Name): void {
+ const {gen, schema} = it
+ if (schema === false) {
+ gen.var(valid, false) // TODO var
+ falseSchemaError(it)
+ } else {
+ gen.var(valid, true) // TODO var
+ }
+}
+
+function falseSchemaError(it: SchemaCxt, overrideAllErrors?: boolean): void {
+ const {gen, data} = it
+ // TODO maybe some other interface should be used for non-keyword validation errors...
+ const cxt: KeywordErrorCxt = {
+ gen,
+ keyword: "false schema",
+ data,
+ schema: false,
+ schemaCode: false,
+ schemaValue: false,
+ params: {},
+ it,
+ }
+ reportError(cxt, boolError, undefined, overrideAllErrors)
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/dataType.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/dataType.ts
new file mode 100644
index 00000000..b315c2ce
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/dataType.ts
@@ -0,0 +1,229 @@
+import type {
+ KeywordErrorDefinition,
+ KeywordErrorCxt,
+ ErrorObject,
+ AnySchemaObject,
+} from "../../types"
+import type {SchemaObjCxt} from ".."
+import {isJSONType, JSONType} from "../rules"
+import {schemaHasRulesForType} from "./applicability"
+import {reportError} from "../errors"
+import {_, nil, and, not, operators, Code, Name} from "../codegen"
+import {toHash, schemaRefOrVal} from "../util"
+
+export enum DataType {
+ Correct,
+ Wrong,
+}
+
+export function getSchemaTypes(schema: AnySchemaObject): JSONType[] {
+ const types = getJSONTypes(schema.type)
+ const hasNull = types.includes("null")
+ if (hasNull) {
+ if (schema.nullable === false) throw new Error("type: null contradicts nullable: false")
+ } else {
+ if (!types.length && schema.nullable !== undefined) {
+ throw new Error('"nullable" cannot be used without "type"')
+ }
+ if (schema.nullable === true) types.push("null")
+ }
+ return types
+}
+
+export function getJSONTypes(ts: unknown | unknown[]): JSONType[] {
+ const types: unknown[] = Array.isArray(ts) ? ts : ts ? [ts] : []
+ if (types.every(isJSONType)) return types
+ throw new Error("type must be JSONType or JSONType[]: " + types.join(","))
+}
+
+export function coerceAndCheckDataType(it: SchemaObjCxt, types: JSONType[]): boolean {
+ const {gen, data, opts} = it
+ const coerceTo = coerceToTypes(types, opts.coerceTypes)
+ const checkTypes =
+ types.length > 0 &&
+ !(coerceTo.length === 0 && types.length === 1 && schemaHasRulesForType(it, types[0]))
+ if (checkTypes) {
+ const wrongType = checkDataTypes(types, data, opts.strictNumbers, DataType.Wrong)
+ gen.if(wrongType, () => {
+ if (coerceTo.length) coerceData(it, types, coerceTo)
+ else reportTypeError(it)
+ })
+ }
+ return checkTypes
+}
+
+const COERCIBLE: Set<JSONType> = new Set(["string", "number", "integer", "boolean", "null"])
+function coerceToTypes(types: JSONType[], coerceTypes?: boolean | "array"): JSONType[] {
+ return coerceTypes
+ ? types.filter((t) => COERCIBLE.has(t) || (coerceTypes === "array" && t === "array"))
+ : []
+}
+
+function coerceData(it: SchemaObjCxt, types: JSONType[], coerceTo: JSONType[]): void {
+ const {gen, data, opts} = it
+ const dataType = gen.let("dataType", _`typeof ${data}`)
+ const coerced = gen.let("coerced", _`undefined`)
+ if (opts.coerceTypes === "array") {
+ gen.if(_`${dataType} == 'object' && Array.isArray(${data}) && ${data}.length == 1`, () =>
+ gen
+ .assign(data, _`${data}[0]`)
+ .assign(dataType, _`typeof ${data}`)
+ .if(checkDataTypes(types, data, opts.strictNumbers), () => gen.assign(coerced, data))
+ )
+ }
+ gen.if(_`${coerced} !== undefined`)
+ for (const t of coerceTo) {
+ if (COERCIBLE.has(t) || (t === "array" && opts.coerceTypes === "array")) {
+ coerceSpecificType(t)
+ }
+ }
+ gen.else()
+ reportTypeError(it)
+ gen.endIf()
+
+ gen.if(_`${coerced} !== undefined`, () => {
+ gen.assign(data, coerced)
+ assignParentData(it, coerced)
+ })
+
+ function coerceSpecificType(t: string): void {
+ switch (t) {
+ case "string":
+ gen
+ .elseIf(_`${dataType} == "number" || ${dataType} == "boolean"`)
+ .assign(coerced, _`"" + ${data}`)
+ .elseIf(_`${data} === null`)
+ .assign(coerced, _`""`)
+ return
+ case "number":
+ gen
+ .elseIf(
+ _`${dataType} == "boolean" || ${data} === null
+ || (${dataType} == "string" && ${data} && ${data} == +${data})`
+ )
+ .assign(coerced, _`+${data}`)
+ return
+ case "integer":
+ gen
+ .elseIf(
+ _`${dataType} === "boolean" || ${data} === null
+ || (${dataType} === "string" && ${data} && ${data} == +${data} && !(${data} % 1))`
+ )
+ .assign(coerced, _`+${data}`)
+ return
+ case "boolean":
+ gen
+ .elseIf(_`${data} === "false" || ${data} === 0 || ${data} === null`)
+ .assign(coerced, false)
+ .elseIf(_`${data} === "true" || ${data} === 1`)
+ .assign(coerced, true)
+ return
+ case "null":
+ gen.elseIf(_`${data} === "" || ${data} === 0 || ${data} === false`)
+ gen.assign(coerced, null)
+ return
+
+ case "array":
+ gen
+ .elseIf(
+ _`${dataType} === "string" || ${dataType} === "number"
+ || ${dataType} === "boolean" || ${data} === null`
+ )
+ .assign(coerced, _`[${data}]`)
+ }
+ }
+}
+
+function assignParentData({gen, parentData, parentDataProperty}: SchemaObjCxt, expr: Name): void {
+ // TODO use gen.property
+ gen.if(_`${parentData} !== undefined`, () =>
+ gen.assign(_`${parentData}[${parentDataProperty}]`, expr)
+ )
+}
+
+export function checkDataType(
+ dataType: JSONType,
+ data: Name,
+ strictNums?: boolean | "log",
+ correct = DataType.Correct
+): Code {
+ const EQ = correct === DataType.Correct ? operators.EQ : operators.NEQ
+ let cond: Code
+ switch (dataType) {
+ case "null":
+ return _`${data} ${EQ} null`
+ case "array":
+ cond = _`Array.isArray(${data})`
+ break
+ case "object":
+ cond = _`${data} && typeof ${data} == "object" && !Array.isArray(${data})`
+ break
+ case "integer":
+ cond = numCond(_`!(${data} % 1) && !isNaN(${data})`)
+ break
+ case "number":
+ cond = numCond()
+ break
+ default:
+ return _`typeof ${data} ${EQ} ${dataType}`
+ }
+ return correct === DataType.Correct ? cond : not(cond)
+
+ function numCond(_cond: Code = nil): Code {
+ return and(_`typeof ${data} == "number"`, _cond, strictNums ? _`isFinite(${data})` : nil)
+ }
+}
+
+export function checkDataTypes(
+ dataTypes: JSONType[],
+ data: Name,
+ strictNums?: boolean | "log",
+ correct?: DataType
+): Code {
+ if (dataTypes.length === 1) {
+ return checkDataType(dataTypes[0], data, strictNums, correct)
+ }
+ let cond: Code
+ const types = toHash(dataTypes)
+ if (types.array && types.object) {
+ const notObj = _`typeof ${data} != "object"`
+ cond = types.null ? notObj : _`!${data} || ${notObj}`
+ delete types.null
+ delete types.array
+ delete types.object
+ } else {
+ cond = nil
+ }
+ if (types.number) delete types.integer
+ for (const t in types) cond = and(cond, checkDataType(t as JSONType, data, strictNums, correct))
+ return cond
+}
+
+export type TypeError = ErrorObject<"type", {type: string}>
+
+const typeError: KeywordErrorDefinition = {
+ message: ({schema}) => `must be ${schema}`,
+ params: ({schema, schemaValue}) =>
+ typeof schema == "string" ? _`{type: ${schema}}` : _`{type: ${schemaValue}}`,
+}
+
+export function reportTypeError(it: SchemaObjCxt): void {
+ const cxt = getTypeErrorContext(it)
+ reportError(cxt, typeError)
+}
+
+function getTypeErrorContext(it: SchemaObjCxt): KeywordErrorCxt {
+ const {gen, data, schema} = it
+ const schemaCode = schemaRefOrVal(it, schema, "type")
+ return {
+ gen,
+ keyword: "type",
+ data,
+ schema: schema.type,
+ schemaCode,
+ schemaValue: schemaCode,
+ parentSchema: schema,
+ params: {},
+ it,
+ }
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/defaults.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/defaults.ts
new file mode 100644
index 00000000..2ad3d4df
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/defaults.ts
@@ -0,0 +1,32 @@
+import type {SchemaObjCxt} from ".."
+import {_, getProperty, stringify} from "../codegen"
+import {checkStrictMode} from "../util"
+
+export function assignDefaults(it: SchemaObjCxt, ty?: string): void {
+ const {properties, items} = it.schema
+ if (ty === "object" && properties) {
+ for (const key in properties) {
+ assignDefault(it, key, properties[key].default)
+ }
+ } else if (ty === "array" && Array.isArray(items)) {
+ items.forEach((sch, i: number) => assignDefault(it, i, sch.default))
+ }
+}
+
+function assignDefault(it: SchemaObjCxt, prop: string | number, defaultValue: unknown): void {
+ const {gen, compositeRule, data, opts} = it
+ if (defaultValue === undefined) return
+ const childData = _`${data}${getProperty(prop)}`
+ if (compositeRule) {
+ checkStrictMode(it, `default is ignored for: ${childData}`)
+ return
+ }
+
+ let condition = _`${childData} === undefined`
+ if (opts.useDefaults === "empty") {
+ condition = _`${condition} || ${childData} === null || ${childData} === ""`
+ }
+ // `${childData} === undefined` +
+ // (opts.useDefaults === "empty" ? ` || ${childData} === null || ${childData} === ""` : "")
+ gen.if(condition, _`${childData} = ${stringify(defaultValue)}`)
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/index.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/index.ts
new file mode 100644
index 00000000..0f40584e
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/index.ts
@@ -0,0 +1,573 @@
+import type {
+ AddedKeywordDefinition,
+ AnySchema,
+ AnySchemaObject,
+ KeywordErrorCxt,
+ KeywordCxtParams,
+} from "../../types"
+import type {SchemaCxt, SchemaObjCxt} from ".."
+import type {InstanceOptions} from "../../core"
+import {boolOrEmptySchema, topBoolOrEmptySchema} from "./boolSchema"
+import {coerceAndCheckDataType, getSchemaTypes} from "./dataType"
+import {shouldUseGroup, shouldUseRule} from "./applicability"
+import {checkDataType, checkDataTypes, reportTypeError, DataType} from "./dataType"
+import {assignDefaults} from "./defaults"
+import {funcKeywordCode, macroKeywordCode, validateKeywordUsage, validSchemaType} from "./keyword"
+import {getSubschema, extendSubschemaData, SubschemaArgs, extendSubschemaMode} from "./subschema"
+import {_, nil, str, or, not, getProperty, Block, Code, Name, CodeGen} from "../codegen"
+import N from "../names"
+import {resolveUrl} from "../resolve"
+import {
+ schemaRefOrVal,
+ schemaHasRulesButRef,
+ checkUnknownRules,
+ checkStrictMode,
+ unescapeJsonPointer,
+ mergeEvaluated,
+} from "../util"
+import type {JSONType, Rule, RuleGroup} from "../rules"
+import {
+ ErrorPaths,
+ reportError,
+ reportExtraError,
+ resetErrorsCount,
+ keyword$DataError,
+} from "../errors"
+
+// schema compilation - generates validation function, subschemaCode (below) is used for subschemas
+export function validateFunctionCode(it: SchemaCxt): void {
+ if (isSchemaObj(it)) {
+ checkKeywords(it)
+ if (schemaCxtHasRules(it)) {
+ topSchemaObjCode(it)
+ return
+ }
+ }
+ validateFunction(it, () => topBoolOrEmptySchema(it))
+}
+
+function validateFunction(
+ {gen, validateName, schema, schemaEnv, opts}: SchemaCxt,
+ body: Block
+): void {
+ if (opts.code.es5) {
+ gen.func(validateName, _`${N.data}, ${N.valCxt}`, schemaEnv.$async, () => {
+ gen.code(_`"use strict"; ${funcSourceUrl(schema, opts)}`)
+ destructureValCxtES5(gen, opts)
+ gen.code(body)
+ })
+ } else {
+ gen.func(validateName, _`${N.data}, ${destructureValCxt(opts)}`, schemaEnv.$async, () =>
+ gen.code(funcSourceUrl(schema, opts)).code(body)
+ )
+ }
+}
+
+function destructureValCxt(opts: InstanceOptions): Code {
+ return _`{${N.instancePath}="", ${N.parentData}, ${N.parentDataProperty}, ${N.rootData}=${
+ N.data
+ }${opts.dynamicRef ? _`, ${N.dynamicAnchors}={}` : nil}}={}`
+}
+
+function destructureValCxtES5(gen: CodeGen, opts: InstanceOptions): void {
+ gen.if(
+ N.valCxt,
+ () => {
+ gen.var(N.instancePath, _`${N.valCxt}.${N.instancePath}`)
+ gen.var(N.parentData, _`${N.valCxt}.${N.parentData}`)
+ gen.var(N.parentDataProperty, _`${N.valCxt}.${N.parentDataProperty}`)
+ gen.var(N.rootData, _`${N.valCxt}.${N.rootData}`)
+ if (opts.dynamicRef) gen.var(N.dynamicAnchors, _`${N.valCxt}.${N.dynamicAnchors}`)
+ },
+ () => {
+ gen.var(N.instancePath, _`""`)
+ gen.var(N.parentData, _`undefined`)
+ gen.var(N.parentDataProperty, _`undefined`)
+ gen.var(N.rootData, N.data)
+ if (opts.dynamicRef) gen.var(N.dynamicAnchors, _`{}`)
+ }
+ )
+}
+
+function topSchemaObjCode(it: SchemaObjCxt): void {
+ const {schema, opts, gen} = it
+ validateFunction(it, () => {
+ if (opts.$comment && schema.$comment) commentKeyword(it)
+ checkNoDefault(it)
+ gen.let(N.vErrors, null)
+ gen.let(N.errors, 0)
+ if (opts.unevaluated) resetEvaluated(it)
+ typeAndKeywords(it)
+ returnResults(it)
+ })
+ return
+}
+
+function resetEvaluated(it: SchemaObjCxt): void {
+ // TODO maybe some hook to execute it in the end to check whether props/items are Name, as in assignEvaluated
+ const {gen, validateName} = it
+ it.evaluated = gen.const("evaluated", _`${validateName}.evaluated`)
+ gen.if(_`${it.evaluated}.dynamicProps`, () => gen.assign(_`${it.evaluated}.props`, _`undefined`))
+ gen.if(_`${it.evaluated}.dynamicItems`, () => gen.assign(_`${it.evaluated}.items`, _`undefined`))
+}
+
+function funcSourceUrl(schema: AnySchema, opts: InstanceOptions): Code {
+ const schId = typeof schema == "object" && schema[opts.schemaId]
+ return schId && (opts.code.source || opts.code.process) ? _`/*# sourceURL=${schId} */` : nil
+}
+
+// schema compilation - this function is used recursively to generate code for sub-schemas
+function subschemaCode(it: SchemaCxt, valid: Name): void {
+ if (isSchemaObj(it)) {
+ checkKeywords(it)
+ if (schemaCxtHasRules(it)) {
+ subSchemaObjCode(it, valid)
+ return
+ }
+ }
+ boolOrEmptySchema(it, valid)
+}
+
+function schemaCxtHasRules({schema, self}: SchemaCxt): boolean {
+ if (typeof schema == "boolean") return !schema
+ for (const key in schema) if (self.RULES.all[key]) return true
+ return false
+}
+
+function isSchemaObj(it: SchemaCxt): it is SchemaObjCxt {
+ return typeof it.schema != "boolean"
+}
+
+function subSchemaObjCode(it: SchemaObjCxt, valid: Name): void {
+ const {schema, gen, opts} = it
+ if (opts.$comment && schema.$comment) commentKeyword(it)
+ updateContext(it)
+ checkAsyncSchema(it)
+ const errsCount = gen.const("_errs", N.errors)
+ typeAndKeywords(it, errsCount)
+ // TODO var
+ gen.var(valid, _`${errsCount} === ${N.errors}`)
+}
+
+function checkKeywords(it: SchemaObjCxt): void {
+ checkUnknownRules(it)
+ checkRefsAndKeywords(it)
+}
+
+function typeAndKeywords(it: SchemaObjCxt, errsCount?: Name): void {
+ if (it.opts.jtd) return schemaKeywords(it, [], false, errsCount)
+ const types = getSchemaTypes(it.schema)
+ const checkedTypes = coerceAndCheckDataType(it, types)
+ schemaKeywords(it, types, !checkedTypes, errsCount)
+}
+
+function checkRefsAndKeywords(it: SchemaObjCxt): void {
+ const {schema, errSchemaPath, opts, self} = it
+ if (schema.$ref && opts.ignoreKeywordsWithRef && schemaHasRulesButRef(schema, self.RULES)) {
+ self.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`)
+ }
+}
+
+function checkNoDefault(it: SchemaObjCxt): void {
+ const {schema, opts} = it
+ if (schema.default !== undefined && opts.useDefaults && opts.strictSchema) {
+ checkStrictMode(it, "default is ignored in the schema root")
+ }
+}
+
+function updateContext(it: SchemaObjCxt): void {
+ const schId = it.schema[it.opts.schemaId]
+ if (schId) it.baseId = resolveUrl(it.baseId, schId)
+}
+
+function checkAsyncSchema(it: SchemaObjCxt): void {
+ if (it.schema.$async && !it.schemaEnv.$async) throw new Error("async schema in sync schema")
+}
+
+function commentKeyword({gen, schemaEnv, schema, errSchemaPath, opts}: SchemaObjCxt): void {
+ const msg = schema.$comment
+ if (opts.$comment === true) {
+ gen.code(_`${N.self}.logger.log(${msg})`)
+ } else if (typeof opts.$comment == "function") {
+ const schemaPath = str`${errSchemaPath}/$comment`
+ const rootName = gen.scopeValue("root", {ref: schemaEnv.root})
+ gen.code(_`${N.self}.opts.$comment(${msg}, ${schemaPath}, ${rootName}.schema)`)
+ }
+}
+
+function returnResults(it: SchemaCxt): void {
+ const {gen, schemaEnv, validateName, ValidationError, opts} = it
+ if (schemaEnv.$async) {
+ // TODO assign unevaluated
+ gen.if(
+ _`${N.errors} === 0`,
+ () => gen.return(N.data),
+ () => gen.throw(_`new ${ValidationError as Name}(${N.vErrors})`)
+ )
+ } else {
+ gen.assign(_`${validateName}.errors`, N.vErrors)
+ if (opts.unevaluated) assignEvaluated(it)
+ gen.return(_`${N.errors} === 0`)
+ }
+}
+
+function assignEvaluated({gen, evaluated, props, items}: SchemaCxt): void {
+ if (props instanceof Name) gen.assign(_`${evaluated}.props`, props)
+ if (items instanceof Name) gen.assign(_`${evaluated}.items`, items)
+}
+
+function schemaKeywords(
+ it: SchemaObjCxt,
+ types: JSONType[],
+ typeErrors: boolean,
+ errsCount?: Name
+): void {
+ const {gen, schema, data, allErrors, opts, self} = it
+ const {RULES} = self
+ if (schema.$ref && (opts.ignoreKeywordsWithRef || !schemaHasRulesButRef(schema, RULES))) {
+ gen.block(() => keywordCode(it, "$ref", (RULES.all.$ref as Rule).definition)) // TODO typecast
+ return
+ }
+ if (!opts.jtd) checkStrictTypes(it, types)
+ gen.block(() => {
+ for (const group of RULES.rules) groupKeywords(group)
+ groupKeywords(RULES.post)
+ })
+
+ function groupKeywords(group: RuleGroup): void {
+ if (!shouldUseGroup(schema, group)) return
+ if (group.type) {
+ gen.if(checkDataType(group.type, data, opts.strictNumbers))
+ iterateKeywords(it, group)
+ if (types.length === 1 && types[0] === group.type && typeErrors) {
+ gen.else()
+ reportTypeError(it)
+ }
+ gen.endIf()
+ } else {
+ iterateKeywords(it, group)
+ }
+ // TODO make it "ok" call?
+ if (!allErrors) gen.if(_`${N.errors} === ${errsCount || 0}`)
+ }
+}
+
+function iterateKeywords(it: SchemaObjCxt, group: RuleGroup): void {
+ const {
+ gen,
+ schema,
+ opts: {useDefaults},
+ } = it
+ if (useDefaults) assignDefaults(it, group.type)
+ gen.block(() => {
+ for (const rule of group.rules) {
+ if (shouldUseRule(schema, rule)) {
+ keywordCode(it, rule.keyword, rule.definition, group.type)
+ }
+ }
+ })
+}
+
+function checkStrictTypes(it: SchemaObjCxt, types: JSONType[]): void {
+ if (it.schemaEnv.meta || !it.opts.strictTypes) return
+ checkContextTypes(it, types)
+ if (!it.opts.allowUnionTypes) checkMultipleTypes(it, types)
+ checkKeywordTypes(it, it.dataTypes)
+}
+
+function checkContextTypes(it: SchemaObjCxt, types: JSONType[]): void {
+ if (!types.length) return
+ if (!it.dataTypes.length) {
+ it.dataTypes = types
+ return
+ }
+ types.forEach((t) => {
+ if (!includesType(it.dataTypes, t)) {
+ strictTypesError(it, `type "${t}" not allowed by context "${it.dataTypes.join(",")}"`)
+ }
+ })
+ it.dataTypes = it.dataTypes.filter((t) => includesType(types, t))
+}
+
+function checkMultipleTypes(it: SchemaObjCxt, ts: JSONType[]): void {
+ if (ts.length > 1 && !(ts.length === 2 && ts.includes("null"))) {
+ strictTypesError(it, "use allowUnionTypes to allow union type keyword")
+ }
+}
+
+function checkKeywordTypes(it: SchemaObjCxt, ts: JSONType[]): void {
+ const rules = it.self.RULES.all
+ for (const keyword in rules) {
+ const rule = rules[keyword]
+ if (typeof rule == "object" && shouldUseRule(it.schema, rule)) {
+ const {type} = rule.definition
+ if (type.length && !type.some((t) => hasApplicableType(ts, t))) {
+ strictTypesError(it, `missing type "${type.join(",")}" for keyword "${keyword}"`)
+ }
+ }
+ }
+}
+
+function hasApplicableType(schTs: JSONType[], kwdT: JSONType): boolean {
+ return schTs.includes(kwdT) || (kwdT === "number" && schTs.includes("integer"))
+}
+
+function includesType(ts: JSONType[], t: JSONType): boolean {
+ return ts.includes(t) || (t === "integer" && ts.includes("number"))
+}
+
+function strictTypesError(it: SchemaObjCxt, msg: string): void {
+ const schemaPath = it.schemaEnv.baseId + it.errSchemaPath
+ msg += ` at "${schemaPath}" (strictTypes)`
+ checkStrictMode(it, msg, it.opts.strictTypes)
+}
+
+export class KeywordCxt implements KeywordErrorCxt {
+ readonly gen: CodeGen
+ readonly allErrors?: boolean
+ readonly keyword: string
+ readonly data: Name // Name referencing the current level of the data instance
+ readonly $data?: string | false
+ schema: any // keyword value in the schema
+ readonly schemaValue: Code | number | boolean // Code reference to keyword schema value or primitive value
+ readonly schemaCode: Code | number | boolean // Code reference to resolved schema value (different if schema is $data)
+ readonly schemaType: JSONType[] // allowed type(s) of keyword value in the schema
+ readonly parentSchema: AnySchemaObject
+ readonly errsCount?: Name // Name reference to the number of validation errors collected before this keyword,
+ // requires option trackErrors in keyword definition
+ params: KeywordCxtParams // object to pass parameters to error messages from keyword code
+ readonly it: SchemaObjCxt // schema compilation context (schema is guaranteed to be an object, not boolean)
+ readonly def: AddedKeywordDefinition
+
+ constructor(it: SchemaObjCxt, def: AddedKeywordDefinition, keyword: string) {
+ validateKeywordUsage(it, def, keyword)
+ this.gen = it.gen
+ this.allErrors = it.allErrors
+ this.keyword = keyword
+ this.data = it.data
+ this.schema = it.schema[keyword]
+ this.$data = def.$data && it.opts.$data && this.schema && this.schema.$data
+ this.schemaValue = schemaRefOrVal(it, this.schema, keyword, this.$data)
+ this.schemaType = def.schemaType
+ this.parentSchema = it.schema
+ this.params = {}
+ this.it = it
+ this.def = def
+
+ if (this.$data) {
+ this.schemaCode = it.gen.const("vSchema", getData(this.$data, it))
+ } else {
+ this.schemaCode = this.schemaValue
+ if (!validSchemaType(this.schema, def.schemaType, def.allowUndefined)) {
+ throw new Error(`${keyword} value must be ${JSON.stringify(def.schemaType)}`)
+ }
+ }
+
+ if ("code" in def ? def.trackErrors : def.errors !== false) {
+ this.errsCount = it.gen.const("_errs", N.errors)
+ }
+ }
+
+ result(condition: Code, successAction?: () => void, failAction?: () => void): void {
+ this.failResult(not(condition), successAction, failAction)
+ }
+
+ failResult(condition: Code, successAction?: () => void, failAction?: () => void): void {
+ this.gen.if(condition)
+ if (failAction) failAction()
+ else this.error()
+ if (successAction) {
+ this.gen.else()
+ successAction()
+ if (this.allErrors) this.gen.endIf()
+ } else {
+ if (this.allErrors) this.gen.endIf()
+ else this.gen.else()
+ }
+ }
+
+ pass(condition: Code, failAction?: () => void): void {
+ this.failResult(not(condition), undefined, failAction)
+ }
+
+ fail(condition?: Code): void {
+ if (condition === undefined) {
+ this.error()
+ if (!this.allErrors) this.gen.if(false) // this branch will be removed by gen.optimize
+ return
+ }
+ this.gen.if(condition)
+ this.error()
+ if (this.allErrors) this.gen.endIf()
+ else this.gen.else()
+ }
+
+ fail$data(condition: Code): void {
+ if (!this.$data) return this.fail(condition)
+ const {schemaCode} = this
+ this.fail(_`${schemaCode} !== undefined && (${or(this.invalid$data(), condition)})`)
+ }
+
+ error(append?: boolean, errorParams?: KeywordCxtParams, errorPaths?: ErrorPaths): void {
+ if (errorParams) {
+ this.setParams(errorParams)
+ this._error(append, errorPaths)
+ this.setParams({})
+ return
+ }
+ this._error(append, errorPaths)
+ }
+
+ private _error(append?: boolean, errorPaths?: ErrorPaths): void {
+ ;(append ? reportExtraError : reportError)(this, this.def.error, errorPaths)
+ }
+
+ $dataError(): void {
+ reportError(this, this.def.$dataError || keyword$DataError)
+ }
+
+ reset(): void {
+ if (this.errsCount === undefined) throw new Error('add "trackErrors" to keyword definition')
+ resetErrorsCount(this.gen, this.errsCount)
+ }
+
+ ok(cond: Code | boolean): void {
+ if (!this.allErrors) this.gen.if(cond)
+ }
+
+ setParams(obj: KeywordCxtParams, assign?: true): void {
+ if (assign) Object.assign(this.params, obj)
+ else this.params = obj
+ }
+
+ block$data(valid: Name, codeBlock: () => void, $dataValid: Code = nil): void {
+ this.gen.block(() => {
+ this.check$data(valid, $dataValid)
+ codeBlock()
+ })
+ }
+
+ check$data(valid: Name = nil, $dataValid: Code = nil): void {
+ if (!this.$data) return
+ const {gen, schemaCode, schemaType, def} = this
+ gen.if(or(_`${schemaCode} === undefined`, $dataValid))
+ if (valid !== nil) gen.assign(valid, true)
+ if (schemaType.length || def.validateSchema) {
+ gen.elseIf(this.invalid$data())
+ this.$dataError()
+ if (valid !== nil) gen.assign(valid, false)
+ }
+ gen.else()
+ }
+
+ invalid$data(): Code {
+ const {gen, schemaCode, schemaType, def, it} = this
+ return or(wrong$DataType(), invalid$DataSchema())
+
+ function wrong$DataType(): Code {
+ if (schemaType.length) {
+ /* istanbul ignore if */
+ if (!(schemaCode instanceof Name)) throw new Error("ajv implementation error")
+ const st = Array.isArray(schemaType) ? schemaType : [schemaType]
+ return _`${checkDataTypes(st, schemaCode, it.opts.strictNumbers, DataType.Wrong)}`
+ }
+ return nil
+ }
+
+ function invalid$DataSchema(): Code {
+ if (def.validateSchema) {
+ const validateSchemaRef = gen.scopeValue("validate$data", {ref: def.validateSchema}) // TODO value.code for standalone
+ return _`!${validateSchemaRef}(${schemaCode})`
+ }
+ return nil
+ }
+ }
+
+ subschema(appl: SubschemaArgs, valid: Name): SchemaCxt {
+ const subschema = getSubschema(this.it, appl)
+ extendSubschemaData(subschema, this.it, appl)
+ extendSubschemaMode(subschema, appl)
+ const nextContext = {...this.it, ...subschema, items: undefined, props: undefined}
+ subschemaCode(nextContext, valid)
+ return nextContext
+ }
+
+ mergeEvaluated(schemaCxt: SchemaCxt, toName?: typeof Name): void {
+ const {it, gen} = this
+ if (!it.opts.unevaluated) return
+ if (it.props !== true && schemaCxt.props !== undefined) {
+ it.props = mergeEvaluated.props(gen, schemaCxt.props, it.props, toName)
+ }
+ if (it.items !== true && schemaCxt.items !== undefined) {
+ it.items = mergeEvaluated.items(gen, schemaCxt.items, it.items, toName)
+ }
+ }
+
+ mergeValidEvaluated(schemaCxt: SchemaCxt, valid: Name): boolean | void {
+ const {it, gen} = this
+ if (it.opts.unevaluated && (it.props !== true || it.items !== true)) {
+ gen.if(valid, () => this.mergeEvaluated(schemaCxt, Name))
+ return true
+ }
+ }
+}
+
+function keywordCode(
+ it: SchemaObjCxt,
+ keyword: string,
+ def: AddedKeywordDefinition,
+ ruleType?: JSONType
+): void {
+ const cxt = new KeywordCxt(it, def, keyword)
+ if ("code" in def) {
+ def.code(cxt, ruleType)
+ } else if (cxt.$data && def.validate) {
+ funcKeywordCode(cxt, def)
+ } else if ("macro" in def) {
+ macroKeywordCode(cxt, def)
+ } else if (def.compile || def.validate) {
+ funcKeywordCode(cxt, def)
+ }
+}
+
+const JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/
+const RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/
+export function getData(
+ $data: string,
+ {dataLevel, dataNames, dataPathArr}: SchemaCxt
+): Code | number {
+ let jsonPointer
+ let data: Code
+ if ($data === "") return N.rootData
+ if ($data[0] === "/") {
+ if (!JSON_POINTER.test($data)) throw new Error(`Invalid JSON-pointer: ${$data}`)
+ jsonPointer = $data
+ data = N.rootData
+ } else {
+ const matches = RELATIVE_JSON_POINTER.exec($data)
+ if (!matches) throw new Error(`Invalid JSON-pointer: ${$data}`)
+ const up: number = +matches[1]
+ jsonPointer = matches[2]
+ if (jsonPointer === "#") {
+ if (up >= dataLevel) throw new Error(errorMsg("property/index", up))
+ return dataPathArr[dataLevel - up]
+ }
+ if (up > dataLevel) throw new Error(errorMsg("data", up))
+ data = dataNames[dataLevel - up]
+ if (!jsonPointer) return data
+ }
+
+ let expr = data
+ const segments = jsonPointer.split("/")
+ for (const segment of segments) {
+ if (segment) {
+ data = _`${data}${getProperty(unescapeJsonPointer(segment))}`
+ expr = _`${expr} && ${data}`
+ }
+ }
+ return expr
+
+ function errorMsg(pointerType: string, up: number): string {
+ return `Cannot access ${pointerType} ${up} levels up, current level is ${dataLevel}`
+ }
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/keyword.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/keyword.ts
new file mode 100644
index 00000000..f854aa71
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/keyword.ts
@@ -0,0 +1,171 @@
+import type {KeywordCxt} from "."
+import type {
+ AnySchema,
+ SchemaValidateFunction,
+ AnyValidateFunction,
+ AddedKeywordDefinition,
+ MacroKeywordDefinition,
+ FuncKeywordDefinition,
+} from "../../types"
+import type {SchemaObjCxt} from ".."
+import {_, nil, not, stringify, Code, Name, CodeGen} from "../codegen"
+import N from "../names"
+import type {JSONType} from "../rules"
+import {callValidateCode} from "../../vocabularies/code"
+import {extendErrors} from "../errors"
+
+type KeywordCompilationResult = AnySchema | SchemaValidateFunction | AnyValidateFunction
+
+export function macroKeywordCode(cxt: KeywordCxt, def: MacroKeywordDefinition): void {
+ const {gen, keyword, schema, parentSchema, it} = cxt
+ const macroSchema = def.macro.call(it.self, schema, parentSchema, it)
+ const schemaRef = useKeyword(gen, keyword, macroSchema)
+ if (it.opts.validateSchema !== false) it.self.validateSchema(macroSchema, true)
+
+ const valid = gen.name("valid")
+ cxt.subschema(
+ {
+ schema: macroSchema,
+ schemaPath: nil,
+ errSchemaPath: `${it.errSchemaPath}/${keyword}`,
+ topSchemaRef: schemaRef,
+ compositeRule: true,
+ },
+ valid
+ )
+ cxt.pass(valid, () => cxt.error(true))
+}
+
+export function funcKeywordCode(cxt: KeywordCxt, def: FuncKeywordDefinition): void {
+ const {gen, keyword, schema, parentSchema, $data, it} = cxt
+ checkAsyncKeyword(it, def)
+ const validate =
+ !$data && def.compile ? def.compile.call(it.self, schema, parentSchema, it) : def.validate
+ const validateRef = useKeyword(gen, keyword, validate)
+ const valid = gen.let("valid")
+ cxt.block$data(valid, validateKeyword)
+ cxt.ok(def.valid ?? valid)
+
+ function validateKeyword(): void {
+ if (def.errors === false) {
+ assignValid()
+ if (def.modifying) modifyData(cxt)
+ reportErrs(() => cxt.error())
+ } else {
+ const ruleErrs = def.async ? validateAsync() : validateSync()
+ if (def.modifying) modifyData(cxt)
+ reportErrs(() => addErrs(cxt, ruleErrs))
+ }
+ }
+
+ function validateAsync(): Name {
+ const ruleErrs = gen.let("ruleErrs", null)
+ gen.try(
+ () => assignValid(_`await `),
+ (e) =>
+ gen.assign(valid, false).if(
+ _`${e} instanceof ${it.ValidationError as Name}`,
+ () => gen.assign(ruleErrs, _`${e}.errors`),
+ () => gen.throw(e)
+ )
+ )
+ return ruleErrs
+ }
+
+ function validateSync(): Code {
+ const validateErrs = _`${validateRef}.errors`
+ gen.assign(validateErrs, null)
+ assignValid(nil)
+ return validateErrs
+ }
+
+ function assignValid(_await: Code = def.async ? _`await ` : nil): void {
+ const passCxt = it.opts.passContext ? N.this : N.self
+ const passSchema = !(("compile" in def && !$data) || def.schema === false)
+ gen.assign(
+ valid,
+ _`${_await}${callValidateCode(cxt, validateRef, passCxt, passSchema)}`,
+ def.modifying
+ )
+ }
+
+ function reportErrs(errors: () => void): void {
+ gen.if(not(def.valid ?? valid), errors)
+ }
+}
+
+function modifyData(cxt: KeywordCxt): void {
+ const {gen, data, it} = cxt
+ gen.if(it.parentData, () => gen.assign(data, _`${it.parentData}[${it.parentDataProperty}]`))
+}
+
+function addErrs(cxt: KeywordCxt, errs: Code): void {
+ const {gen} = cxt
+ gen.if(
+ _`Array.isArray(${errs})`,
+ () => {
+ gen
+ .assign(N.vErrors, _`${N.vErrors} === null ? ${errs} : ${N.vErrors}.concat(${errs})`)
+ .assign(N.errors, _`${N.vErrors}.length`)
+ extendErrors(cxt)
+ },
+ () => cxt.error()
+ )
+}
+
+function checkAsyncKeyword({schemaEnv}: SchemaObjCxt, def: FuncKeywordDefinition): void {
+ if (def.async && !schemaEnv.$async) throw new Error("async keyword in sync schema")
+}
+
+function useKeyword(gen: CodeGen, keyword: string, result?: KeywordCompilationResult): Name {
+ if (result === undefined) throw new Error(`keyword "${keyword}" failed to compile`)
+ return gen.scopeValue(
+ "keyword",
+ typeof result == "function" ? {ref: result} : {ref: result, code: stringify(result)}
+ )
+}
+
+export function validSchemaType(
+ schema: unknown,
+ schemaType: JSONType[],
+ allowUndefined = false
+): boolean {
+ // TODO add tests
+ return (
+ !schemaType.length ||
+ schemaType.some((st) =>
+ st === "array"
+ ? Array.isArray(schema)
+ : st === "object"
+ ? schema && typeof schema == "object" && !Array.isArray(schema)
+ : typeof schema == st || (allowUndefined && typeof schema == "undefined")
+ )
+ )
+}
+
+export function validateKeywordUsage(
+ {schema, opts, self, errSchemaPath}: SchemaObjCxt,
+ def: AddedKeywordDefinition,
+ keyword: string
+): void {
+ /* istanbul ignore if */
+ if (Array.isArray(def.keyword) ? !def.keyword.includes(keyword) : def.keyword !== keyword) {
+ throw new Error("ajv implementation error")
+ }
+
+ const deps = def.dependencies
+ if (deps?.some((kwd) => !Object.prototype.hasOwnProperty.call(schema, kwd))) {
+ throw new Error(`parent schema must have dependencies of ${keyword}: ${deps.join(",")}`)
+ }
+
+ if (def.validateSchema) {
+ const valid = def.validateSchema(schema[keyword])
+ if (!valid) {
+ const msg =
+ `keyword "${keyword}" value is invalid at path "${errSchemaPath}": ` +
+ self.errorsText(def.validateSchema.errors)
+ if (opts.validateSchema === "log") self.logger.error(msg)
+ else throw new Error(msg)
+ }
+ }
+}
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/subschema.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/subschema.ts
new file mode 100644
index 00000000..9072ed77
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/validate/subschema.ts
@@ -0,0 +1,135 @@
+import type {AnySchema} from "../../types"
+import type {SchemaObjCxt} from ".."
+import {_, str, getProperty, Code, Name} from "../codegen"
+import {escapeFragment, getErrorPath, Type} from "../util"
+import type {JSONType} from "../rules"
+
+export interface SubschemaContext {
+ // TODO use Optional? align with SchemCxt property types
+ schema: AnySchema
+ schemaPath: Code
+ errSchemaPath: string
+ topSchemaRef?: Code
+ errorPath?: Code
+ dataLevel?: number
+ dataTypes?: JSONType[]
+ data?: Name
+ parentData?: Name
+ parentDataProperty?: Code | number
+ dataNames?: Name[]
+ dataPathArr?: (Code | number)[]
+ propertyName?: Name
+ jtdDiscriminator?: string
+ jtdMetadata?: boolean
+ compositeRule?: true
+ createErrors?: boolean
+ allErrors?: boolean
+}
+
+export type SubschemaArgs = Partial<{
+ keyword: string
+ schemaProp: string | number
+ schema: AnySchema
+ schemaPath: Code
+ errSchemaPath: string
+ topSchemaRef: Code
+ data: Name | Code
+ dataProp: Code | string | number
+ dataTypes: JSONType[]
+ definedProperties: Set<string>
+ propertyName: Name
+ dataPropType: Type
+ jtdDiscriminator: string
+ jtdMetadata: boolean
+ compositeRule: true
+ createErrors: boolean
+ allErrors: boolean
+}>
+
+export function getSubschema(
+ it: SchemaObjCxt,
+ {keyword, schemaProp, schema, schemaPath, errSchemaPath, topSchemaRef}: SubschemaArgs
+): SubschemaContext {
+ if (keyword !== undefined && schema !== undefined) {
+ throw new Error('both "keyword" and "schema" passed, only one allowed')
+ }
+
+ if (keyword !== undefined) {
+ const sch = it.schema[keyword]
+ return schemaProp === undefined
+ ? {
+ schema: sch,
+ schemaPath: _`${it.schemaPath}${getProperty(keyword)}`,
+ errSchemaPath: `${it.errSchemaPath}/${keyword}`,
+ }
+ : {
+ schema: sch[schemaProp],
+ schemaPath: _`${it.schemaPath}${getProperty(keyword)}${getProperty(schemaProp)}`,
+ errSchemaPath: `${it.errSchemaPath}/${keyword}/${escapeFragment(schemaProp)}`,
+ }
+ }
+
+ if (schema !== undefined) {
+ if (schemaPath === undefined || errSchemaPath === undefined || topSchemaRef === undefined) {
+ throw new Error('"schemaPath", "errSchemaPath" and "topSchemaRef" are required with "schema"')
+ }
+ return {
+ schema,
+ schemaPath,
+ topSchemaRef,
+ errSchemaPath,
+ }
+ }
+
+ throw new Error('either "keyword" or "schema" must be passed')
+}
+
+export function extendSubschemaData(
+ subschema: SubschemaContext,
+ it: SchemaObjCxt,
+ {dataProp, dataPropType: dpType, data, dataTypes, propertyName}: SubschemaArgs
+): void {
+ if (data !== undefined && dataProp !== undefined) {
+ throw new Error('both "data" and "dataProp" passed, only one allowed')
+ }
+
+ const {gen} = it
+
+ if (dataProp !== undefined) {
+ const {errorPath, dataPathArr, opts} = it
+ const nextData = gen.let("data", _`${it.data}${getProperty(dataProp)}`, true)
+ dataContextProps(nextData)
+ subschema.errorPath = str`${errorPath}${getErrorPath(dataProp, dpType, opts.jsPropertySyntax)}`
+ subschema.parentDataProperty = _`${dataProp}`
+ subschema.dataPathArr = [...dataPathArr, subschema.parentDataProperty]
+ }
+
+ if (data !== undefined) {
+ const nextData = data instanceof Name ? data : gen.let("data", data, true) // replaceable if used once?
+ dataContextProps(nextData)
+ if (propertyName !== undefined) subschema.propertyName = propertyName
+ // TODO something is possibly wrong here with not changing parentDataProperty and not appending dataPathArr
+ }
+
+ if (dataTypes) subschema.dataTypes = dataTypes
+
+ function dataContextProps(_nextData: Name): void {
+ subschema.data = _nextData
+ subschema.dataLevel = it.dataLevel + 1
+ subschema.dataTypes = []
+ it.definedProperties = new Set<string>()
+ subschema.parentData = it.data
+ subschema.dataNames = [...it.dataNames, _nextData]
+ }
+}
+
+export function extendSubschemaMode(
+ subschema: SubschemaContext,
+ {jtdDiscriminator, jtdMetadata, compositeRule, createErrors, allErrors}: SubschemaArgs
+): void {
+ if (compositeRule !== undefined) subschema.compositeRule = compositeRule
+ if (createErrors !== undefined) subschema.createErrors = createErrors
+ if (allErrors !== undefined) subschema.allErrors = allErrors
+ subschema.jtdDiscriminator = jtdDiscriminator // not inherited
+ subschema.jtdMetadata = jtdMetadata // not inherited
+}