.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / table / node_modules / ajv / lib / vocabularies / applicator / dependencies.ts
1 import type {
2   CodeKeywordDefinition,
3   ErrorObject,
4   KeywordErrorDefinition,
5   SchemaMap,
6   AnySchema,
7 } from "../../types"
8 import type {KeywordCxt} from "../../compile/validate"
9 import {_, str} from "../../compile/codegen"
10 import {alwaysValidSchema} from "../../compile/util"
11 import {checkReportMissingProp, checkMissingProp, reportMissingProp, propertyInData} from "../code"
12
13 export type PropertyDependencies = {[K in string]?: string[]}
14
15 export interface DependenciesErrorParams {
16   property: string
17   missingProperty: string
18   depsCount: number
19   deps: string // TODO change to string[]
20 }
21
22 type SchemaDependencies = SchemaMap
23
24 export type DependenciesError = ErrorObject<
25   "dependencies",
26   DependenciesErrorParams,
27   {[K in string]?: string[] | AnySchema}
28 >
29
30 export const error: KeywordErrorDefinition = {
31   message: ({params: {property, depsCount, deps}}) => {
32     const property_ies = depsCount === 1 ? "property" : "properties"
33     return str`must have ${property_ies} ${deps} when property ${property} is present`
34   },
35   params: ({params: {property, depsCount, deps, missingProperty}}) =>
36     _`{property: ${property},
37     missingProperty: ${missingProperty},
38     depsCount: ${depsCount},
39     deps: ${deps}}`, // TODO change to reference
40 }
41
42 const def: CodeKeywordDefinition = {
43   keyword: "dependencies",
44   type: "object",
45   schemaType: "object",
46   error,
47   code(cxt: KeywordCxt) {
48     const [propDeps, schDeps] = splitDependencies(cxt)
49     validatePropertyDeps(cxt, propDeps)
50     validateSchemaDeps(cxt, schDeps)
51   },
52 }
53
54 function splitDependencies({schema}: KeywordCxt): [PropertyDependencies, SchemaDependencies] {
55   const propertyDeps: PropertyDependencies = {}
56   const schemaDeps: SchemaDependencies = {}
57   for (const key in schema) {
58     if (key === "__proto__") continue
59     const deps = Array.isArray(schema[key]) ? propertyDeps : schemaDeps
60     deps[key] = schema[key]
61   }
62   return [propertyDeps, schemaDeps]
63 }
64
65 export function validatePropertyDeps(
66   cxt: KeywordCxt,
67   propertyDeps: {[K in string]?: string[]} = cxt.schema
68 ): void {
69   const {gen, data, it} = cxt
70   if (Object.keys(propertyDeps).length === 0) return
71   const missing = gen.let("missing")
72   for (const prop in propertyDeps) {
73     const deps = propertyDeps[prop] as string[]
74     if (deps.length === 0) continue
75     const hasProperty = propertyInData(gen, data, prop, it.opts.ownProperties)
76     cxt.setParams({
77       property: prop,
78       depsCount: deps.length,
79       deps: deps.join(", "),
80     })
81     if (it.allErrors) {
82       gen.if(hasProperty, () => {
83         for (const depProp of deps) {
84           checkReportMissingProp(cxt, depProp)
85         }
86       })
87     } else {
88       gen.if(_`${hasProperty} && (${checkMissingProp(cxt, deps, missing)})`)
89       reportMissingProp(cxt, missing)
90       gen.else()
91     }
92   }
93 }
94
95 export function validateSchemaDeps(cxt: KeywordCxt, schemaDeps: SchemaMap = cxt.schema): void {
96   const {gen, data, keyword, it} = cxt
97   const valid = gen.name("valid")
98   for (const prop in schemaDeps) {
99     if (alwaysValidSchema(it, schemaDeps[prop] as AnySchema)) continue
100     gen.if(
101       propertyInData(gen, data, prop, it.opts.ownProperties),
102       () => {
103         const schCxt = cxt.subschema({keyword, schemaProp: prop}, valid)
104         cxt.mergeValidEvaluated(schCxt, valid)
105       },
106       () => gen.var(valid, true) // TODO var
107     )
108     cxt.ok(valid)
109   }
110 }
111
112 export default def