@@ -217,7 +217,10 @@ export default async function load(schema: URL | Subschema | Readable, options:
217
217
218
218
// hints help external partial schemas pick up where the root left off (for external complete/valid schemas, skip this)
219
219
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 } ) ;
221
224
222
225
// if root schema is remote and this is a relative reference, treat as remote
223
226
if ( schema instanceof URL ) {
@@ -306,105 +309,116 @@ function relativePath(src: URL, dest: URL): string {
306
309
return dest . href ;
307
310
}
308
311
312
+ export interface GetHintOptions {
313
+ path : string [ ] ;
314
+ external : boolean ;
315
+ startFrom ?: Subschema [ "hint" ] ;
316
+ }
317
+
309
318
/** 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 {
311
320
if ( startFrom && startFrom !== "OpenAPI3" ) {
312
321
switch ( startFrom ) {
313
322
case "OperationObject" :
314
- return getHintFromOperationObject ( path ) ;
323
+ return getHintFromOperationObject ( path , external ) ;
315
324
case "RequestBodyObject" :
316
- return getHintFromRequestBodyObject ( path ) ;
325
+ return getHintFromRequestBodyObject ( path , external ) ;
317
326
case "ResponseObject" :
318
- return getHintFromResponseObject ( path ) ;
327
+ return getHintFromResponseObject ( path , external ) ;
319
328
default :
320
329
return startFrom ;
321
330
}
322
331
}
323
332
switch ( path [ 0 ] as keyof OpenAPI3 ) {
324
333
case "paths" :
325
- return getHintFromPathItemObject ( path . slice ( 2 ) ) ; // skip URL at [1]
334
+ return getHintFromPathItemObject ( path . slice ( 2 ) , external ) ; // skip URL at [1]
326
335
case "components" :
327
- return getHintFromComponentsObject ( path . slice ( 1 ) ) ;
336
+ return getHintFromComponentsObject ( path . slice ( 1 ) , external ) ;
328
337
}
329
338
return undefined ;
330
339
}
331
- function getHintFromComponentsObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] | undefined {
340
+ function getHintFromComponentsObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] | undefined {
332
341
switch ( path [ 0 ] as keyof ComponentsObject ) {
333
342
case "schemas" :
334
343
case "headers" :
335
- return getHintFromSchemaObject ( path . slice ( 2 ) ) ;
344
+ return getHintFromSchemaObject ( path . slice ( 2 ) , external ) ;
336
345
case "parameters" :
337
- return getHintFromParameterObject ( path . slice ( 2 ) ) ;
346
+ return getHintFromParameterObject ( path . slice ( 2 ) , external ) ;
338
347
case "responses" :
339
- return getHintFromResponseObject ( path . slice ( 2 ) ) ;
348
+ return getHintFromResponseObject ( path . slice ( 2 ) , external ) ;
340
349
case "requestBodies" :
341
- return getHintFromRequestBodyObject ( path . slice ( 2 ) ) ;
350
+ return getHintFromRequestBodyObject ( path . slice ( 2 ) , external ) ;
342
351
case "pathItems" :
343
- return getHintFromPathItemObject ( path . slice ( 2 ) ) ;
352
+ return getHintFromPathItemObject ( path . slice ( 2 ) , external ) ;
344
353
}
345
354
return "SchemaObject" ;
346
355
}
347
- function getHintFromMediaTypeObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
356
+ function getHintFromMediaTypeObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
348
357
switch ( path [ 0 ] ) {
349
358
case "schema" :
350
- return getHintFromSchemaObject ( path . slice ( 1 ) ) ;
359
+ return getHintFromSchemaObject ( path . slice ( 1 ) , external ) ;
351
360
}
352
361
return "MediaTypeObject" ;
353
362
}
354
- function getHintFromOperationObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
363
+ function getHintFromOperationObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
355
364
switch ( path [ 0 ] as keyof OperationObject ) {
356
365
case "parameters" :
357
366
return "ParameterObject[]" ;
358
367
case "requestBody" :
359
- return getHintFromRequestBodyObject ( path . slice ( 1 ) ) ;
368
+ return getHintFromRequestBodyObject ( path . slice ( 1 ) , external ) ;
360
369
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]
362
371
}
363
372
return "OperationObject" ;
364
373
}
365
- function getHintFromParameterObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
374
+ function getHintFromParameterObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
366
375
switch ( path [ 0 ] ) {
367
376
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]
369
378
case "schema" :
370
- return getHintFromSchemaObject ( path . slice ( 1 ) ) ;
379
+ return getHintFromSchemaObject ( path . slice ( 1 ) , external ) ;
371
380
}
372
381
return "ParameterObject" ;
373
382
}
374
- function getHintFromPathItemObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] | undefined {
383
+ function getHintFromPathItemObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] | undefined {
375
384
switch ( path [ 0 ] as keyof PathItemObject ) {
376
385
case "parameters" : {
377
386
if ( typeof path [ 1 ] === "number" ) {
378
387
return "ParameterObject[]" ;
379
388
}
380
- return getHintFromParameterObject ( path . slice ( 1 ) ) ;
389
+ return getHintFromParameterObject ( path . slice ( 1 ) , external ) ;
381
390
}
382
391
default :
383
- return getHintFromOperationObject ( path . slice ( 1 ) ) ;
392
+ return getHintFromOperationObject ( path . slice ( 1 ) , external ) ;
384
393
}
385
394
}
386
- function getHintFromRequestBodyObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
395
+ function getHintFromRequestBodyObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
387
396
switch ( path [ 0 ] as keyof RequestBodyObject ) {
388
397
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]
390
399
}
391
400
return "RequestBodyObject" ;
392
401
}
393
- function getHintFromResponseObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
402
+ function getHintFromResponseObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
394
403
switch ( path [ 0 ] as keyof ResponseObject ) {
395
404
case "headers" :
396
- return getHintFromSchemaObject ( path . slice ( 2 ) ) ; // skip name at [1]
405
+ return getHintFromSchemaObject ( path . slice ( 2 ) , external ) ; // skip name at [1]
397
406
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]
399
408
}
400
409
return "ResponseObject" ;
401
410
}
402
- function getHintFromSchemaObject ( path : ( string | number ) [ ] ) : Subschema [ "hint" ] {
411
+ function getHintFromSchemaObject ( path : ( string | number ) [ ] , external : boolean ) : Subschema [ "hint" ] {
403
412
switch ( path [ 0 ] ) {
404
413
case "allOf" :
405
414
case "anyOf" :
406
415
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" ;
408
421
}
422
+ // otherwise, path length of 1 means partial schema is likely a SchemaObject (or it’s unknown, in which case assume SchemaObject)
409
423
return "SchemaObject" ;
410
424
}
0 commit comments