@apistudio/apim-cli
Version:
CLI for API Management Products
260 lines (190 loc) • 7.26 kB
Markdown
# 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 /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 /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