fork of hey-api/openapi-ts because I need some additional things
at feat/use-mutation-hooks 120 lines 3.6 kB view raw
1import colors from 'ansi-colors'; 2 3import type { IR } from '../ir/types'; 4import { httpMethods } from '../openApi/shared/utils/operation'; 5 6export interface PrintOptions { 7 /** 8 * Indentation depth for `JSON.stringify()` when printing objects. 9 * 10 * @default 2 11 */ 12 depth?: number; 13 /** 14 * Which section of the IR to print. Use 'all' to print every section. 15 * 16 * @default 'all' 17 */ 18 section?: keyof IR.Model | 'all'; 19 /** 20 * How much detail to print. 21 * 22 * - `summary` → only keys, names, operationIds, status codes 23 * - `full` → dump full JSON structures 24 * 25 * @default 'summary' 26 */ 27 verbosity?: 'full' | 'summary'; 28} 29 30const indent = (level: number) => ' '.repeat(level); 31 32const log = (message: string, level?: number) => console.log(`${indent(level ?? 0)}${message}`); 33 34const print = (ir: IR.Model, options: PrintOptions = {}) => { 35 const { depth = 2, section = 'all', verbosity = 'summary' } = options; 36 37 const printObject = ( 38 obj: unknown, 39 level: number, 40 kind: 'responses' | 'requestBody' | 'schema' | 'generic' = 'generic', 41 ) => { 42 if (verbosity === 'summary' && obj && typeof obj === 'object') { 43 if (kind === 'responses') { 44 const count = Object.keys(obj).length; 45 const noun = count === 1 ? 'code' : 'codes'; 46 log(`responses: ${colors.yellow(`${count} ${noun}`)}`, level); 47 } else if (kind === 'requestBody') { 48 log(`requestBody: ${Object.keys(obj).join(', ')}`, level); 49 } else if (kind === 'schema') { 50 log(`schema keys: ${Object.keys(obj).join(', ')}`, level); 51 } else { 52 log(`keys: ${Object.keys(obj).join(', ')}`, level); 53 } 54 } else { 55 log(JSON.stringify(obj, null, depth), level); 56 } 57 }; 58 59 const printPathItem = ( 60 key: string, 61 item: IR.PathItemObject | IR.ReferenceObject, 62 base: number = 1, 63 ) => { 64 if ('$ref' in item) { 65 log(`${colors.cyan(key)} is a $ref → ${colors.yellow(item.$ref)}`, base); 66 return; 67 } 68 69 for (const method of Object.keys(item) as Array<keyof IR.PathItemObject>) { 70 if (!httpMethods.includes(method)) continue; 71 72 const operation = item[method]!; 73 log( 74 `${colors.green(method.toUpperCase())} ${colors.cyan(key)} (${colors.magenta(operation.operationId ?? '')})`, 75 base, 76 ); 77 78 if (operation.body) printObject(operation.body, base + 1, 'requestBody'); 79 if (operation.responses) printObject(operation.responses, base + 1, 'responses'); 80 } 81 }; 82 83 const sections = 84 section === 'all' ? (Object.keys(ir) as unknown as ReadonlyArray<keyof IR.Model>) : [section]; 85 86 for (const section of sections) { 87 switch (section) { 88 case 'components': 89 if (ir.components?.schemas) { 90 log(`Components: ${Object.keys(ir.components.schemas).length} schemas`); 91 for (const [, schema] of Object.entries(ir.components.schemas)) { 92 printObject(schema, 1, 'schema'); 93 } 94 } 95 break; 96 case 'paths': { 97 const paths = ir.paths || {}; 98 log(`paths (${Object.keys(paths).length} items):`); 99 for (const [path, item] of Object.entries(paths)) { 100 printPathItem(path, item); 101 } 102 break; 103 } 104 case 'servers': 105 break; 106 case 'webhooks': { 107 const webhooks = ir.webhooks || {}; 108 log(`webhooks (${Object.keys(webhooks).length} items):`); 109 for (const [path, item] of Object.entries(webhooks)) { 110 printPathItem(path, item); 111 } 112 break; 113 } 114 } 115 } 116}; 117 118export const ir = { 119 print, 120} as const;