import { Document, Ruleset, Spectral } from '@stoplight/spectral-core'; import * as Parsers from '@stoplight/spectral-parsers'; import { bundleAndLoadRuleset } from '@stoplight/spectral-ruleset-bundler/with-loader'; import { fetch } from '@stoplight/spectral-runtime'; import * as fs from 'fs'; import * as glob from 'glob'; import * as path from 'path'; import { MessageCodegenOptions } from './message-codegen-options'; export async function lint(options: MessageCodegenOptions): Promise { console.log(`Linting schemas at ${options.inputDir}.`); // Configure Spectral const spectral = new Spectral({}); spectral.setRuleset(await getRuleset(options)); let lintingErrors = false; // Find JSON schemas and lint const schemas = glob.sync(path.join(options.inputDir, '/**/*.json'), { absolute: true, }); if (schemas.length === 0) { console.log('Could not find any schemas, exiting.'); process.exit(1); } for (const schema of schemas) { // console.log(schema); const document = new Document( fs.readFileSync(schema, 'utf-8'), Parsers.Json, schema, ); const results = await spectral.run(document); const errors = results.filter((r) => r.severity === 0); if (errors.length > 0) { lintingErrors = true; console.log(`\nErrors in\n${schema}:`); errors.forEach((e) => { console.log(`* ${e.message}`); }); } } if (lintingErrors) { console.log('There were linting errors.'); process.exit(1); } else { console.log('No linting errors found.'); } } async function getRuleset(options: MessageCodegenOptions): Promise { // This has to be an abs path, otherwise Spectral will fall back to network resolution. let rulesetPath: string; if (!options.rulesetPath) { console.log( 'No ruleset path provided, trying to find one in the input directory.', ); const defaultRulesetPath = path.resolve(options.inputDir, '.spectral.yaml'); if (!fs.existsSync(defaultRulesetPath)) { console.log( `Could not find default ruleset at ${defaultRulesetPath}, exiting.`, ); process.exit(1); } rulesetPath = defaultRulesetPath; } else { rulesetPath = path.resolve(options.rulesetPath); } console.log(`Using ruleset ${rulesetPath}`); const ruleset = await bundleAndLoadRuleset(rulesetPath, { fs, fetch }); return ruleset; }