fork of hey-api/openapi-ts because I need some additional things
at feat/skip-token 155 lines 4.1 kB view raw
1import { Ono } from '@jsdevtools/ono'; 2 3import type { $RefParser } from '..'; 4import type $Ref from '../ref'; 5import type { JSONSchema } from '../types'; 6import { getHash, stripHash, toFileSystemPath } from './url'; 7 8export type JSONParserErrorType = 9 | 'EUNKNOWN' 10 | 'EPARSER' 11 | 'EUNMATCHEDPARSER' 12 | 'ETIMEOUT' 13 | 'ERESOLVER' 14 | 'EUNMATCHEDRESOLVER' 15 | 'EMISSINGPOINTER' 16 | 'EINVALIDPOINTER'; 17 18export class JSONParserError extends Error { 19 public readonly name: string; 20 public readonly message: string; 21 public source: string | undefined; 22 public path: Array<string | number> | null; 23 public readonly code: JSONParserErrorType; 24 public constructor(message: string, source?: string) { 25 super(); 26 27 this.code = 'EUNKNOWN'; 28 this.name = 'JSONParserError'; 29 this.message = message; 30 this.source = source; 31 this.path = null; 32 33 Ono.extend(this); 34 } 35 36 get footprint() { 37 return `${this.path}+${this.source}+${this.code}+${this.message}`; 38 } 39} 40 41export class JSONParserErrorGroup<S extends object = JSONSchema> extends Error { 42 files: $RefParser; 43 44 constructor(parser: $RefParser) { 45 super(); 46 47 this.files = parser; 48 this.name = 'JSONParserErrorGroup'; 49 this.message = `${this.errors.length} error${ 50 this.errors.length > 1 ? 's' : '' 51 } occurred while reading '${toFileSystemPath(parser.$refs._root$Ref!.path)}'`; 52 53 Ono.extend(this); 54 } 55 56 static getParserErrors<S extends object = JSONSchema>(parser: $RefParser) { 57 const errors = []; 58 59 for (const $ref of Object.values(parser.$refs._$refs) as $Ref<S>[]) { 60 if ($ref.errors) { 61 errors.push(...$ref.errors); 62 } 63 } 64 65 return errors; 66 } 67 68 get errors(): Array< 69 | JSONParserError 70 | InvalidPointerError 71 | ResolverError 72 | ParserError 73 | MissingPointerError 74 | UnmatchedParserError 75 | UnmatchedResolverError 76 > { 77 return JSONParserErrorGroup.getParserErrors<S>(this.files); 78 } 79} 80 81export class ParserError extends JSONParserError { 82 code = 'EPARSER' as JSONParserErrorType; 83 name = 'ParserError'; 84 constructor(message: any, source: any) { 85 super(`Error parsing ${source}: ${message}`, source); 86 } 87} 88 89export class UnmatchedParserError extends JSONParserError { 90 code = 'EUNMATCHEDPARSER' as JSONParserErrorType; 91 name = 'UnmatchedParserError'; 92 93 constructor(source: string) { 94 super(`Could not find parser for "${source}"`, source); 95 } 96} 97 98export class ResolverError extends JSONParserError { 99 code = 'ERESOLVER' as JSONParserErrorType; 100 name = 'ResolverError'; 101 ioErrorCode?: string; 102 constructor(ex: Error | any, source?: string) { 103 super(ex.message || `Error reading file "${source}"`, source); 104 if ('code' in ex) { 105 this.ioErrorCode = String(ex.code); 106 } 107 } 108} 109 110export class UnmatchedResolverError extends JSONParserError { 111 code = 'EUNMATCHEDRESOLVER' as JSONParserErrorType; 112 name = 'UnmatchedResolverError'; 113 constructor(source: any) { 114 super(`Could not find resolver for "${source}"`, source); 115 } 116} 117 118export class MissingPointerError extends JSONParserError { 119 code = 'EMISSINGPOINTER' as JSONParserErrorType; 120 name = 'MissingPointerError'; 121 constructor(token: string, path: string) { 122 super( 123 `Missing $ref pointer "${getHash(path)}". Token "${token}" does not exist.`, 124 stripHash(path), 125 ); 126 } 127} 128 129export class TimeoutError extends JSONParserError { 130 code = 'ETIMEOUT' as JSONParserErrorType; 131 name = 'TimeoutError'; 132 constructor(timeout: number) { 133 super(`Dereferencing timeout reached: ${timeout}ms`); 134 } 135} 136 137export class InvalidPointerError extends JSONParserError { 138 code = 'EUNMATCHEDRESOLVER' as JSONParserErrorType; 139 name = 'InvalidPointerError'; 140 constructor(pointer: string, path: string) { 141 super(`Invalid $ref pointer "${pointer}". Pointers must begin with "#/"`, stripHash(path)); 142 } 143} 144 145export function isHandledError(err: any): err is JSONParserError { 146 return err instanceof JSONParserError || err instanceof JSONParserErrorGroup; 147} 148 149export function normalizeError(err: any) { 150 if (err.path === null) { 151 err.path = []; 152 } 153 154 return err; 155}