Refactor OpenAPI parsing logic to improve error handling and type safety. Update integration tests to validate handling of malformed JSON and YAML inputs, ensuring consistent detection of non-OpenAPI content.

This commit is contained in:
Luke Hagar
2025-09-27 01:33:45 +00:00
parent 56c90e9426
commit 5a0986930b
2 changed files with 28 additions and 39 deletions

View File

@@ -1,5 +1,5 @@
import * as yaml from 'js-yaml';
import type{ AstPath, Doc, Parser, ParserOptions, Printer, SupportLanguage } from 'prettier';
import type { AstPath, Doc, Parser, ParserOptions, Printer, SupportLanguage } from 'prettier';
import { getVendorExtensions } from './extensions/vendor-loader.js';
export type PrintFn = (path: AstPath) => Doc;
@@ -35,9 +35,8 @@ import {
// Type definitions for better type safety
interface OpenAPINode {
isOpenAPI: boolean;
content: any;
originalText: string;
format: 'json' | 'yaml';
content?: any;
format?: 'json' | 'yaml';
}
interface OpenAPIPluginOptions {
@@ -48,10 +47,6 @@ interface OpenAPIPluginOptions {
// Load vendor extensions
const vendorExtensions = getVendorExtensions();
// ============================================================================
// UNIFIED PARSER FUNCTIONS
// ============================================================================
/**
* Unified parser that can handle both JSON and YAML OpenAPI files
*/
@@ -81,27 +76,25 @@ function parseOpenAPIFile(text: string, options?: any): OpenAPINode {
let parsed: any;
switch (format) {
case 'yaml':
try {
parsed = yaml.load(text, {
schema: yaml.DEFAULT_SCHEMA,
onWarning: (warning) => {
// Handle YAML warnings if needed
console.warn('YAML parsing warning:', warning);
try {
switch (format) {
case 'yaml':
parsed = yaml.load(text, {
schema: yaml.DEFAULT_SCHEMA,
onWarning: (warning) => {
// Handle YAML warnings if needed
console.warn('YAML parsing warning:', warning);
}
});
} catch (error) {
throw new Error(`Failed to parse OpenAPI YAML: ${error}`);
}
break;
case 'json':
try {
break;
case 'json':
parsed = JSON.parse(text);
} catch (error) {
throw new Error(`Failed to parse OpenAPI JSON: ${error}`);
}
break;
break;
}
} catch (error) {
return {
isOpenAPI: false,
}
}
let isOpenAPI: boolean;
@@ -111,9 +104,6 @@ function parseOpenAPIFile(text: string, options?: any): OpenAPINode {
} catch (error) {
return {
isOpenAPI: false,
content: parsed,
originalText: text,
format: format,
}
}
@@ -122,16 +112,11 @@ function parseOpenAPIFile(text: string, options?: any): OpenAPINode {
return {
isOpenAPI: true,
content: parsed,
originalText: text,
format: format,
}
case false:
default:
return {
isOpenAPI: false,
content: parsed,
originalText: text,
format: format,
}
}
}
@@ -272,7 +257,7 @@ export const parsers: Record<string, Parser> = {
},
astFormat: 'openapi-ast',
locStart: (node: OpenAPINode) => 0,
locEnd: (node: OpenAPINode) => node.originalText?.length || 0,
locEnd: (node: OpenAPINode) => node.content?.length || 0,
},
}

View File

@@ -457,7 +457,10 @@ describe('Integration Tests', () => {
const malformedJson = '{"openapi": "3.0.0", "info": {';
// @ts-expect-error We are mocking things here
expect(() => parser?.parse(malformedJson, { filepath: 'test.json' })).toThrow();
const result = parser?.parse(malformedJson, { filepath: 'test.json' });
expect(result).toBeDefined();
expect(result?.isOpenAPI).toBeFalse();
});
it('should handle malformed YAML gracefully', () => {
@@ -467,7 +470,10 @@ describe('Integration Tests', () => {
const malformedYaml = 'openapi: 3.0.0\ninfo:\n title: Test\n version: 1.0.0\n invalid: [';
// @ts-expect-error We are mocking things here
expect(() => parser?.parse(malformedYaml, { filepath: 'test.yaml' })).toThrow();
const result = parser?.parse(malformedYaml, { filepath: 'test.yaml' });
expect(result).toBeDefined();
expect(result?.isOpenAPI).toBeFalse();
});
it('should handle non-OpenAPI content', () => {
@@ -485,8 +491,6 @@ describe('Integration Tests', () => {
const parsedData = parser?.parse(nonOpenAPI, { filepath: 'test.json' })
expect(parsedData).toBeDefined();
expect(parsedData?.isOpenAPI).toBeFalse();
expect(parsedData?.content).toBeDefined();
expect(parsedData?.content).toEqual(parsedJSON);
});
});