UNPKG

@apistudio/apim-cli

Version:

CLI for API Management Products

260 lines (190 loc) 7.26 kB
# Guide: Generating Spectral Rules from an External OpenAPI Specification This guide provides step-by-step instructions for generating Spectral rules from an OpenAPI specification in another repository. ## Prerequisites - Node.js installed - npm or yarn installed - Access to the external OpenAPI specification file (YAML or JSON) ## Step 1: Set Up Your Project Create a new directory for your Spectral rulesets: ```bash mkdir -p spectral-rulesets cd spectral-rulesets npm init -y npm install js-yaml @stoplight/spectral-core ``` ## Step 2: Copy the Enhanced Ruleset Generator Copy the `enhanced-generate-rulesets.js` file from this repository to your new project. You'll need to modify it to work with your external OpenAPI specification. ## Step 3: Modify the Script for Your OpenAPI Specification Edit the `enhanced-generate-rulesets.js` file to point to your external OpenAPI specification: ```javascript // Update this path to point to your external OpenAPI specification file const specFilePath = '../path/to/your/openapi-specification.yaml'; ``` ## Step 4: Adjust the Schema Component Extraction Logic If your OpenAPI specification has a different structure, you may need to adjust how schema components are extracted: ```javascript function generateAllRulesets() { const openApiSpec = readOpenAPISpec(); // Update this line to match your schema structure const schemas = openApiSpec.components.schemas; // Generate rulesets for each schema component Object.entries(schemas).forEach(([componentName, schema]) => { // Skip any non-component schemas if needed if (componentName === 'SomeNonComponentSchema') return; const ruleset = generateRuleset(componentName, schema); writeRulesetToFile(componentName, ruleset); }); } ``` ## Step 5: Run the Generator ```bash node enhanced-generate-rulesets.js ``` This will generate individual ruleset files for each schema component in your OpenAPI specification. ## Step 6: Create a Combined Ruleset File Create a `combined-ruleset.js` file that imports all the individual ruleset files: ```javascript // Function to get combined ruleset data for all schema components // Import all ruleset files dynamically export async function getCombinedRuleset() { // Import all ruleset files - adjust the list based on your components const component1Ruleset = (await import('./component1.ruleset.js')).default; const component2Ruleset = (await import('./component2.ruleset.js')).default; // Add more imports as needed return { "component1.ruleset.yaml": component1Ruleset, "component2.ruleset.yaml": component2Ruleset, // Add more components as needed }; } ``` ## Step 7: Create a Test Script Create a `test-ruleset.js` file to verify your rulesets: ```javascript // Test script to verify the combined ruleset import { getCombinedRuleset } from './combined-ruleset.js'; // Main async function to run the tests async function runTests() { try { // Get the combined ruleset const combinedRuleset = await getCombinedRuleset(); // Print total number of components and rules const totalComponents = Object.keys(combinedRuleset).length; let totalRules = 0; let specFieldRules = 0; Object.entries(combinedRuleset).forEach(([component, ruleset]) => { if (ruleset && ruleset.rules) { const ruleCount = Object.keys(ruleset.rules).length; totalRules += ruleCount; console.log(` Component ${component} loaded successfully with ${ruleCount} rules`); // Count rules specifically for spec field properties const specRules = Object.keys(ruleset.rules).filter(ruleName => ruleName.startsWith('spec-') && !['spec-details-not-exist', 'spec-details-whitelist-check'].includes(ruleName) ).length; specFieldRules += specRules; } }); console.log(`\nTotal components: ${totalComponents}`); console.log(`Total rules: ${totalRules}`); console.log(`Rules for spec field properties: ${specFieldRules}`); } catch (error) { console.error('Error running tests:', error); } } // Run the tests runTests(); ``` ## Step 8: Run the Test Script ```bash node test-ruleset.js ``` ## Step 9: Use the Rulesets with Spectral Install the Spectral CLI: ```bash npm install -g @stoplight/spectral-cli ``` Create a script to use your rulesets with Spectral: ```javascript import { Spectral } from '@stoplight/spectral-core'; import { getCombinedRuleset } from './combined-ruleset.js'; import fs from 'fs'; async function validateWithSpectral(apiDocument, componentName) { const combinedRuleset = await getCombinedRuleset(); const ruleset = combinedRuleset[`${componentName}.ruleset.yaml`]; if (!ruleset) { console.error(`Ruleset for ${componentName} not found`); return; } const spectral = new Spectral(); spectral.setRuleset(ruleset); const results = await spectral.run(apiDocument); return results; } // Example usage const apiDocument = JSON.parse(fs.readFileSync('./path/to/api-document.json', 'utf8')); validateWithSpectral(apiDocument, 'component1') .then(results => console.log(results)) .catch(err => console.error(err)); ``` ## Step 10: Customize Rules as Needed You can customize the rules in the generated ruleset files to match your specific requirements. Each ruleset file follows this structure: ```javascript export default { "rules": { "rule-name": { "description": "Rule description", "severity": "error", "given": "$", "then": { "field": "fieldName", "function": "truthy" } }, // More rules... } }; ``` ## Troubleshooting ### Common Issues 1. **Path not found**: Ensure the path to your OpenAPI specification is correct. 2. **Schema structure mismatch**: If your OpenAPI specification has a different structure, adjust the schema extraction logic. 3. **Module import errors**: Make sure you're using the correct import syntax for your Node.js version. ### Tips - Use `console.log` statements to debug the script execution. - Validate your OpenAPI specification before generating rules. - Start with a small subset of components to test the process. ## Advanced Usage ### Generating Rules for Specific Components Modify the script to generate rules for specific components only: ```javascript const targetComponents = ['Component1', 'Component2']; Object.entries(schemas).forEach(([componentName, schema]) => { if (targetComponents.includes(componentName)) { const ruleset = generateRuleset(componentName, schema); writeRulesetToFile(componentName, ruleset); } }); ``` ### Adding Custom Rules You can add custom rules to the generated rulesets: ```javascript function generateRuleset(componentName, schema) { const rules = { // Generated rules... }; // Add custom rules rules["custom-rule"] = { "description": "Custom rule description", "severity": "error", "given": "$", "then": { "function": "truthy" } }; return { rules }; } ``` ## Conclusion By following these steps, you can generate Spectral rules from any external OpenAPI specification and use them to validate your API documents. // Made with Bob