@@ -217,7 +217,10 @@ export default async function load(schema: URL | Subschema | Readable, options:
217217
218218 // hints help external partial schemas pick up where the root left off (for external complete/valid schemas, skip this)
219219 const isRemoteFullSchema = ref . path [ 0 ] === "paths" || ref . path [ 0 ] === "components" ; // if the initial ref is "paths" or "components" this must be a full schema
220- const hint = isRemoteFullSchema ? "OpenAPI3" : getHint ( [ ...nodePath , ...ref . path ] , options . hint ) ;
220+ const hintPath : string [ ] = [ ...( nodePath as string [ ] ) ] ;
221+ if ( ref . filename ) hintPath . push ( ref . filename ) ;
222+ hintPath . push ( ...ref . path ) ;
223+ const hint = isRemoteFullSchema ? "OpenAPI3" : getHint ( { path : hintPath , external : ! ! ref . filename , startFrom : options . hint } ) ;
221224
222225 // if root schema is remote and this is a relative reference, treat as remote
223226 if ( schema instanceof URL ) {
@@ -306,105 +309,116 @@ function relativePath(src: URL, dest: URL): string {
306309 return dest . href ;
307310}
308311
312+ export interface GetHintOptions {
313+ path : string [ ] ;
314+ external : boolean ;
315+ startFrom ?: Subschema [ "hint" ] ;
316+ }
317+
309318/** given a path array (an array of indices), what type of object is this? */
310- export function getHint ( path : ( string | number ) [ ] , startFrom ?: Subschema [ "hint" ] ) : Subschema [ "hint" ] | undefined {
319+ export function getHint ( { path, external , startFrom } : GetHintOptions ) : Subschema [ "hint" ] | undefined {
311320 if ( startFrom && startFrom !== "OpenAPI3" ) {
312321 switch ( startFrom ) {
313322 case "OperationObject" :
314- return getHintFromOperationObject ( path ) ;
323+ return getHintFromOperationObject ( path , external ) ;
315324 case "RequestBodyObject" :
316- return getHintFromRequestBodyObject ( path ) ;
325+ return getHintFromRequestBodyObject ( path , external ) ;
317326 case "ResponseObject" :
318- return getHintFromResponseObject ( path ) ;
327+ return getHintFromResponseObject ( path , external ) ;
319328 default :
320329 return startFrom ;
321330 }
322331 }
323332 switch ( path [ 0 ] as keyof OpenAPI3 ) {
324333 case "paths" :
325- return getHintFromPathItemObject ( path . slice ( 2 ) ) ; // skip URL at [1]
334+ return getHintFromPathItemObject ( path . slice ( 2 ) , external ) ; // skip URL at [1]
326335 case "components" :
327- return getHintFromComponentsObject ( path . slice ( 1 ) ) ;
336+ return getHintFromComponentsObject ( path . slice ( 1 ) , external ) ;
328337 }
329338 return undefined ;
330339}
331- function getHintFromComponentsObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] | undefined {
340+ function getHintFromComponentsObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] | undefined {
332341 switch ( path [ 0 ] as keyof ComponentsObject ) {
333342 case "schemas" :
334343 case "headers" :
335- return getHintFromSchemaObject ( path . slice ( 2 ) ) ;
344+ return getHintFromSchemaObject ( path . slice ( 2 ) , external ) ;
336345 case "parameters" :
337- return getHintFromParameterObject ( path . slice ( 2 ) ) ;
346+ return getHintFromParameterObject ( path . slice ( 2 ) , external ) ;
338347 case "responses" :
339- return getHintFromResponseObject ( path . slice ( 2 ) ) ;
348+ return getHintFromResponseObject ( path . slice ( 2 ) , external ) ;
340349 case "requestBodies" :
341- return getHintFromRequestBodyObject ( path . slice ( 2 ) ) ;
350+ return getHintFromRequestBodyObject ( path . slice ( 2 ) , external ) ;
342351 case "pathItems" :
343- return getHintFromPathItemObject ( path . slice ( 2 ) ) ;
352+ return getHintFromPathItemObject ( path . slice ( 2 ) , external ) ;
344353 }
345354 return "SchemaObject" ;
346355}
347- function getHintFromMediaTypeObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
356+ function getHintFromMediaTypeObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
348357 switch ( path [ 0 ] ) {
349358 case "schema" :
350- return getHintFromSchemaObject ( path . slice ( 1 ) ) ;
359+ return getHintFromSchemaObject ( path . slice ( 1 ) , external ) ;
351360 }
352361 return "MediaTypeObject" ;
353362}
354- function getHintFromOperationObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
363+ function getHintFromOperationObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
355364 switch ( path [ 0 ] as keyof OperationObject ) {
356365 case "parameters" :
357366 return "ParameterObject[]" ;
358367 case "requestBody" :
359- return getHintFromRequestBodyObject ( path . slice ( 1 ) ) ;
368+ return getHintFromRequestBodyObject ( path . slice ( 1 ) , external ) ;
360369 case "responses" :
361- return getHintFromResponseObject ( path . slice ( 2 ) ) ; // skip the response code at [1]
370+ return getHintFromResponseObject ( path . slice ( 2 ) , external ) ; // skip the response code at [1]
362371 }
363372 return "OperationObject" ;
364373}
365- function getHintFromParameterObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
374+ function getHintFromParameterObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
366375 switch ( path [ 0 ] ) {
367376 case "content" :
368- return getHintFromMediaTypeObject ( path . slice ( 2 ) ) ; // skip content type at [1]
377+ return getHintFromMediaTypeObject ( path . slice ( 2 ) , external ) ; // skip content type at [1]
369378 case "schema" :
370- return getHintFromSchemaObject ( path . slice ( 1 ) ) ;
379+ return getHintFromSchemaObject ( path . slice ( 1 ) , external ) ;
371380 }
372381 return "ParameterObject" ;
373382}
374- function getHintFromPathItemObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] | undefined {
383+ function getHintFromPathItemObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] | undefined {
375384 switch ( path [ 0 ] as keyof PathItemObject ) {
376385 case "parameters" : {
377386 if ( typeof path [ 1 ] === "number" ) {
378387 return "ParameterObject[]" ;
379388 }
380- return getHintFromParameterObject ( path . slice ( 1 ) ) ;
389+ return getHintFromParameterObject ( path . slice ( 1 ) , external ) ;
381390 }
382391 default :
383- return getHintFromOperationObject ( path . slice ( 1 ) ) ;
392+ return getHintFromOperationObject ( path . slice ( 1 ) , external ) ;
384393 }
385394}
386- function getHintFromRequestBodyObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
395+ function getHintFromRequestBodyObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
387396 switch ( path [ 0 ] as keyof RequestBodyObject ) {
388397 case "content" :
389- return getHintFromMediaTypeObject ( path . slice ( 2 ) ) ; // skip content type at [1]
398+ return getHintFromMediaTypeObject ( path . slice ( 2 ) , external ) ; // skip content type at [1]
390399 }
391400 return "RequestBodyObject" ;
392401}
393- function getHintFromResponseObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
402+ function getHintFromResponseObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
394403 switch ( path [ 0 ] as keyof ResponseObject ) {
395404 case "headers" :
396- return getHintFromSchemaObject ( path . slice ( 2 ) ) ; // skip name at [1]
405+ return getHintFromSchemaObject ( path . slice ( 2 ) , external ) ; // skip name at [1]
397406 case "content" :
398- return getHintFromMediaTypeObject ( path . slice ( 2 ) ) ; // skip content type at [1]
407+ return getHintFromMediaTypeObject ( path . slice ( 2 ) , external ) ; // skip content type at [1]
399408 }
400409 return "ResponseObject" ;
401410}
402- function getHintFromSchemaObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
411+ function getHintFromSchemaObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
403412 switch ( path [ 0 ] ) {
404413 case "allOf" :
405414 case "anyOf" :
406415 case "oneOf" :
407- return getHintFromSchemaObject ( path . slice ( 2 ) ) ; // skip array index at [1]
416+ return getHintFromSchemaObject ( path . slice ( 2 ) , external ) ; // skip array index at [1]
417+ }
418+ // if this is external, and the path is [filename, key], then the external schema is probably a SchemaMap
419+ if ( path . length === 2 && external ) {
420+ return "SchemaMap" ;
408421 }
422+ // otherwise, path length of 1 means partial schema is likely a SchemaObject (or it’s unknown, in which case assume SchemaObject)
409423 return "SchemaObject" ;
410424}
0 commit comments