@@ -63,6 +63,174 @@ export namespace LlmTypeCheckerV3 {
63
63
} ) ;
64
64
} ;
65
65
66
+ export const covers = ( x : ILlmSchemaV3 , y : ILlmSchemaV3 ) : boolean => {
67
+ const alpha : ILlmSchemaV3 [ ] = flatSchema ( x ) ;
68
+ const beta : ILlmSchemaV3 [ ] = flatSchema ( y ) ;
69
+ if ( alpha . some ( ( x ) => isUnknown ( x ) ) ) return true ;
70
+ else if ( beta . some ( ( x ) => isUnknown ( x ) ) ) return false ;
71
+ return beta . every ( ( b ) =>
72
+ alpha . some ( ( a ) => {
73
+ // CHECK EQUALITY
74
+ if ( a === b ) return true ;
75
+ else if ( isUnknown ( a ) ) return true ;
76
+ else if ( isUnknown ( b ) ) return false ;
77
+ else if ( isNullOnly ( a ) ) return isNullOnly ( b ) ;
78
+ else if ( isNullOnly ( b ) ) return isNullable ( a ) ;
79
+ else if ( isNullable ( a ) && ! isNullable ( b ) ) return false ;
80
+ // ATOMIC CASE
81
+ else if ( isBoolean ( a ) ) return isBoolean ( b ) && coverBoolean ( a , b ) ;
82
+ else if ( isInteger ( a ) ) return isInteger ( b ) && coverInteger ( a , b ) ;
83
+ else if ( isNumber ( a ) )
84
+ return ( isNumber ( b ) || isInteger ( b ) ) && coverNumber ( a , b ) ;
85
+ else if ( isString ( a ) ) return isString ( b ) && covertString ( a , b ) ;
86
+ // INSTANCE CASE
87
+ else if ( isArray ( a ) ) return isArray ( b ) && coverArray ( a , b ) ;
88
+ else if ( isObject ( a ) ) return isObject ( b ) && coverObject ( a , b ) ;
89
+ else if ( isOneOf ( a ) ) return false ;
90
+ } ) ,
91
+ ) ;
92
+ } ;
93
+
94
+ /**
95
+ * @internal
96
+ */
97
+ const coverBoolean = (
98
+ x : ILlmSchemaV3 . IBoolean ,
99
+ y : ILlmSchemaV3 . IBoolean ,
100
+ ) : boolean =>
101
+ x . enum === undefined ||
102
+ ( y . enum !== undefined && x . enum . every ( ( v ) => y . enum ! . includes ( v ) ) ) ;
103
+
104
+ /**
105
+ * @internal
106
+ */
107
+ const coverInteger = (
108
+ x : ILlmSchemaV3 . IInteger ,
109
+ y : ILlmSchemaV3 . IInteger ,
110
+ ) : boolean => {
111
+ if ( x . enum !== undefined )
112
+ return y . enum !== undefined && x . enum . every ( ( v ) => y . enum ! . includes ( v ) ) ;
113
+ return [
114
+ x . type === y . type ,
115
+ x . minimum === undefined ||
116
+ ( y . minimum !== undefined && x . minimum <= y . minimum ) ,
117
+ x . maximum === undefined ||
118
+ ( y . maximum !== undefined && x . maximum >= y . maximum ) ,
119
+ x . exclusiveMinimum !== true ||
120
+ x . minimum === undefined ||
121
+ ( y . minimum !== undefined &&
122
+ ( y . exclusiveMinimum === true || x . minimum < y . minimum ) ) ,
123
+ x . exclusiveMaximum !== true ||
124
+ x . maximum === undefined ||
125
+ ( y . maximum !== undefined &&
126
+ ( y . exclusiveMaximum === true || x . maximum > y . maximum ) ) ,
127
+ x . multipleOf === undefined ||
128
+ ( y . multipleOf !== undefined &&
129
+ y . multipleOf / x . multipleOf ===
130
+ Math . floor ( y . multipleOf / x . multipleOf ) ) ,
131
+ ] . every ( ( v ) => v ) ;
132
+ } ;
133
+
134
+ /**
135
+ * @internal
136
+ */
137
+ const coverNumber = (
138
+ x : ILlmSchemaV3 . INumber ,
139
+ y : ILlmSchemaV3 . INumber | ILlmSchemaV3 . IInteger ,
140
+ ) : boolean => {
141
+ if ( x . enum !== undefined )
142
+ return y . enum !== undefined && x . enum . every ( ( v ) => y . enum ! . includes ( v ) ) ;
143
+ return [
144
+ x . type === y . type || ( x . type === "number" && y . type === "integer" ) ,
145
+ x . minimum === undefined ||
146
+ ( y . minimum !== undefined && x . minimum <= y . minimum ) ,
147
+ x . maximum === undefined ||
148
+ ( y . maximum !== undefined && x . maximum >= y . maximum ) ,
149
+ x . exclusiveMinimum !== true ||
150
+ x . minimum === undefined ||
151
+ ( y . minimum !== undefined &&
152
+ ( y . exclusiveMinimum === true || x . minimum < y . minimum ) ) ,
153
+ x . exclusiveMaximum !== true ||
154
+ x . maximum === undefined ||
155
+ ( y . maximum !== undefined &&
156
+ ( y . exclusiveMaximum === true || x . maximum > y . maximum ) ) ,
157
+ x . multipleOf === undefined ||
158
+ ( y . multipleOf !== undefined &&
159
+ y . multipleOf / x . multipleOf ===
160
+ Math . floor ( y . multipleOf / x . multipleOf ) ) ,
161
+ ] . every ( ( v ) => v ) ;
162
+ } ;
163
+
164
+ /**
165
+ * @internal
166
+ */
167
+ const covertString = (
168
+ x : ILlmSchemaV3 . IString ,
169
+ y : ILlmSchemaV3 . IString ,
170
+ ) : boolean => {
171
+ if ( x . enum !== undefined )
172
+ return y . enum !== undefined && x . enum . every ( ( v ) => y . enum ! . includes ( v ) ) ;
173
+ return [
174
+ x . type === y . type ,
175
+ x . format === undefined ||
176
+ ( y . format !== undefined && coverFormat ( x . format , y . format ) ) ,
177
+ x . pattern === undefined || x . pattern === y . pattern ,
178
+ x . minLength === undefined ||
179
+ ( y . minLength !== undefined && x . minLength <= y . minLength ) ,
180
+ x . maxLength === undefined ||
181
+ ( y . maxLength !== undefined && x . maxLength >= y . maxLength ) ,
182
+ ] . every ( ( v ) => v ) ;
183
+ } ;
184
+
185
+ const coverFormat = (
186
+ x : Required < ILlmSchemaV3 . IString > [ "format" ] ,
187
+ y : Required < ILlmSchemaV3 . IString > [ "format" ] ,
188
+ ) : boolean =>
189
+ x === y ||
190
+ ( x === "idn-email" && y === "email" ) ||
191
+ ( x === "idn-hostname" && y === "hostname" ) ||
192
+ ( [ "uri" , "iri" ] . includes ( x ) && y === "url" ) ||
193
+ ( x === "iri" && y === "uri" ) ||
194
+ ( x === "iri-reference" && y === "uri-reference" ) ;
195
+
196
+ /**
197
+ * @internal
198
+ */
199
+ const coverArray = (
200
+ x : ILlmSchemaV3 . IArray ,
201
+ y : ILlmSchemaV3 . IArray ,
202
+ ) : boolean => covers ( x . items , y . items ) ;
203
+
204
+ const coverObject = (
205
+ x : ILlmSchemaV3 . IObject ,
206
+ y : ILlmSchemaV3 . IObject ,
207
+ ) : boolean => {
208
+ if ( ! x . additionalProperties && ! ! y . additionalProperties ) return false ;
209
+ else if (
210
+ ( ! ! x . additionalProperties &&
211
+ ! ! y . additionalProperties &&
212
+ typeof x . additionalProperties === "object" &&
213
+ y . additionalProperties === true ) ||
214
+ ( typeof x . additionalProperties === "object" &&
215
+ typeof y . additionalProperties === "object" &&
216
+ ! covers ( x . additionalProperties , y . additionalProperties ) )
217
+ )
218
+ return false ;
219
+ return Object . entries ( y . properties ?? { } ) . every ( ( [ key , b ] ) => {
220
+ const a : ILlmSchemaV3 | undefined = x . properties ?. [ key ] ;
221
+ if ( a === undefined ) return false ;
222
+ else if (
223
+ ( x . required ?. includes ( key ) ?? false ) === true &&
224
+ ( y . required ?. includes ( key ) ?? false ) === false
225
+ )
226
+ return false ;
227
+ return covers ( a , b ) ;
228
+ } ) ;
229
+ } ;
230
+
231
+ const flatSchema = ( schema : ILlmSchemaV3 ) : ILlmSchemaV3 [ ] =>
232
+ isOneOf ( schema ) ? schema . oneOf . flatMap ( flatSchema ) : [ schema ] ;
233
+
66
234
/* -----------------------------------------------------------
67
235
TYPE CHECKERS
68
236
----------------------------------------------------------- */
0 commit comments