UNPKG

apisurf

Version:

Analyze API surface changes between npm package versions to catch breaking changes

57 lines (56 loc) 2.14 kB
/** * Parse interface definition from source lines */ export function parseInterfaceDefinition(lines, startIndex, name) { const properties = []; let braceCount = 0; let inInterface = false; for (let i = startIndex; i < lines.length; i++) { const line = lines[i].trim(); // Count the brace level before parsing const prevBraceCount = braceCount; // Count braces const openBraces = (line.match(/{/g) || []).length; const closeBraces = (line.match(/}/g) || []).length; if (openBraces > 0) { braceCount += openBraces; if (!inInterface) { inInterface = true; } } // Only parse properties at the top level (braceCount === 1 BEFORE counting this line's braces) if (inInterface && prevBraceCount === 1 && !line.startsWith('}')) { // Match properties like: propertyName: type; or propertyName?: type; // This includes properties with object types like: user: { ... } const propMatch = line.match(/^\s*(\w+)(\?)?:\s*/); if (propMatch && !line.match(/^\s*\w+\s*\(/)) { // Not a method properties.push({ name: propMatch[1], required: !propMatch[2] }); } // Match method signatures like: methodName(): void; else if (line.match(/^\s*(\w+)(\?)?\s*\(/)) { const methodMatch = line.match(/^\s*(\w+)(\?)?\s*\(/); if (methodMatch) { properties.push({ name: methodMatch[1], required: !methodMatch[2] }); } } } if (closeBraces > 0) { braceCount -= closeBraces; if (braceCount === 0) { break; } } } return { name, kind: 'interface', extendedProperties: properties, signature: `export interface ${name} { ${properties.map(p => `${p.name}${p.required ? '' : '?'}: any`).join('; ')} }` }; }