Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
nulltoken committed Mar 22, 2020
1 parent cbca454 commit a463568
Show file tree
Hide file tree
Showing 24 changed files with 2,683 additions and 47 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"scripts": {
"build.binary": "pkg . --output ./binaries/spectral",
"build.clean": "rimraf ./coverage && rimraf ./dist && rimraf ./rulesets && rimraf ./__karma__/__fixtures__",
"build.oas-functions": "rollup -c",
"build.functions": "rollup -c",
"build": "tsc -p ./tsconfig.build.json",
"cli": "node -r ts-node/register -r tsconfig-paths/register src/cli/index.ts",
"cli:debug": "node -r ts-node/register -r tsconfig-paths/register --inspect-brk src/cli/index.ts",
Expand All @@ -44,9 +44,9 @@
"lint.fix": "yarn lint --fix",
"lint": "tsc --noEmit && tslint 'src/**/*.ts'",
"copy.html-templates": "copyfiles -u 1 \"./src/formatters/html/*.html\" \"./dist/\"",
"postbuild.oas-functions": "copyfiles -u 1 \"dist/rulesets/oas*/functions/*.js\" ./",
"postbuild": "yarn build.oas-functions && yarn generate-assets",
"prebuild": "yarn build.clean && copyfiles -u 1 \"src/rulesets/oas*/**/*.json\" dist && copyfiles -u 1 \"src/rulesets/oas*/**/*.json\" ./ && yarn copy.html-templates",
"postbuild.functions": "copyfiles -u 1 \"dist/rulesets/{oas,asyncapi}/functions/*.js\" ./",
"postbuild": "yarn build.functions && yarn generate-assets",
"prebuild": "yarn build.clean && copyfiles -u 1 \"src/rulesets/{oas,asyncapi}/**/*.json\" dist && copyfiles -u 1 \"src/rulesets/{oas,asyncapi}/**/*.json\" ./ && yarn copy.html-templates",
"prebuild.binary": "yarn build",
"pretest.karma": "node ./scripts/generate-karma-fixtures.js && yarn pretest",
"pretest": "yarn generate-assets",
Expand Down
29 changes: 19 additions & 10 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,27 @@ import commonjs from 'rollup-plugin-commonjs';
import { terser } from 'rollup-plugin-terser';

const BASE_PATH = process.cwd();
const directory = 'dist/rulesets/oas/functions';
const targetDir = path.join(BASE_PATH, directory);

const functions = [];
for (const file of fs.readdirSync(targetDir)) {
const targetFile = path.join(targetDir, file);
const stat = fs.statSync(targetFile);
if (!stat.isFile()) continue;
const ext = path.extname(targetFile);
if (ext !== '.js') continue;

functions.push(targetFile);

const builtIns = ['oas', 'asyncapi']

for (const rulesetName of builtIns) {
const targetDir = path.join(BASE_PATH, `dist/rulesets/${rulesetName}/functions/`);

if (!fs.existsSync(targetDir)) {
continue;
}

for (const file of fs.readdirSync(targetDir)) {
const targetFile = path.join(targetDir, file);
const stat = fs.statSync(targetFile);
if (!stat.isFile()) continue;
const ext = path.extname(targetFile);
if (ext !== '.js') continue;

functions.push(targetFile);
}
}

module.exports = functions.map(fn => ({
Expand Down
22 changes: 14 additions & 8 deletions scripts/generate-assets.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/**
* This script generates a list of assets that are needed to load spectral:oas ruleset.
* It contains all OAS custom functions and *resolved* rulesets.
* The assets are stores in a single filed call assets.json in the following format:
* This script generates a list of assets that are needed to load spectral:oas and spectral:asyncapi rulesets.
* It contains all custom functions and *resolved* rulesets.
* The assets are stored in a single file named `assets.json` in the following format:
* `<require-call-path>: <content>`
* where the `require-call-path` is the path you'd normally pass to require(), i.e. `@stoplight/spectral/rulesets/oas/index.js` and `content` is the text data.
* Assets can be loaded using Spectral#registerStaticAssets statc method, i.e. `Spectral.registerStaticAssets(require('@stoplight/spectral/rulesets/assets/assets.json'))`;
* Assets can be loaded using Spectral#registerStaticAssets static method, i.e. `Spectral.registerStaticAssets(require('@stoplight/spectral/rulesets/assets/assets.json'))`;
* If you execute the code above, ruleset will be loaded fully offline, without a need to make any request.
*/

Expand All @@ -30,14 +30,16 @@ const assetsPath = path.join(baseDir, `assets.json`);
const generatedAssets = {};

(async () => {
await processDirectory(generatedAssets, path.join(__dirname, '../rulesets/oas'));
await writeFileAsync(assetsPath, JSON.stringify(generatedAssets, null, 2));
for (const kind of ['oas', 'asyncapi']) {
await processDirectory(generatedAssets, path.join(__dirname, `../rulesets/${kind}`));
await writeFileAsync(assetsPath, JSON.stringify(generatedAssets, null, 2));
}
})();

async function processDirectory(assets: Record<string, string>, dir: string) {
await Promise.all(
(await readdirAsync(dir)).map(async (name: string) => {
if (name === 'schemas') return;
if (['schemas', '__tests__'].includes(name)) return;
const target = path.join(dir, name);
const stats = await statAsync(target);
if (stats.isDirectory()) {
Expand All @@ -53,7 +55,11 @@ async function processDirectory(assets: Record<string, string>, dir: string) {
baseUri: target,
parseResolveResult(opts) {
return new Promise<IUriParserResult>(resolve => {
resolve({ result: parse(opts.result) });
try {
resolve({ result: parse(opts.result) });
} catch (e) {
resolve({ error: e });
}
});
},
})
Expand Down
2 changes: 1 addition & 1 deletion scripts/generate-karma-fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if (!fs.existsSync(baseDir)) {
fs.mkdirSync(baseDir);
}

for (const rulesetName of ['oas']) {
for (const rulesetName of ['oas', 'asyncapi']) {
const target = path.join(baseDir, `${rulesetName}-functions.json`);
const fnsPath = path.join(__dirname, `../rulesets/${rulesetName}/functions`);
const bundledFns = {};
Expand Down
30 changes: 24 additions & 6 deletions setupKarma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ const oasRuleset = JSON.parse(JSON.stringify(require('./rulesets/oas/index.json'
const oasFunctions = JSON.parse(JSON.stringify(require('./__karma__/__fixtures__/oas-functions.json')));
const oas2Schema = JSON.parse(JSON.stringify(require('./rulesets/oas/schemas/schema.oas2.json')));
const oas3Schema = JSON.parse(JSON.stringify(require('./rulesets/oas/schemas/schema.oas3.json')));
const asyncApiRuleset = JSON.parse(JSON.stringify(require('./rulesets/asyncapi/index.json')));
const asyncApiFunctions = JSON.parse(JSON.stringify(require('./__karma__/__fixtures__/asyncapi-functions.json')));
const asyncApi2Schema = JSON.parse(JSON.stringify(require('./rulesets/asyncapi/schemas/schema.asyncapi2.json')));

const { fetch } = window;
let fetchMock: FetchMockSandbox;
Expand Down Expand Up @@ -33,12 +36,27 @@ beforeEach(() => {
body: JSON.parse(JSON.stringify(oas3Schema)),
});

for (const [name, fn] of Object.entries<string>(oasFunctions)) {
fetchMock.get(`https://unpkg.com/@stoplight/spectral/rulesets/oas/functions/${name}`, {
status: 200,
body: fn,
});
}
fetchMock.get('https://unpkg.com/@stoplight/spectral/rulesets/asyncapi/index.json', {
status: 200,
body: JSON.parse(JSON.stringify(asyncApiRuleset)),
});

fetchMock.get('https://unpkg.com/@stoplight/spectral/rulesets/asyncapi/schemas/schema.asyncapi2.json', {
status: 200,
body: JSON.parse(JSON.stringify(asyncApi2Schema)),
});

[
['oas', oasFunctions],
['asyncapi', asyncApiFunctions],
].forEach(([rulesetName, funcs]) => {
for (const [name, fn] of Object.entries<string>(funcs)) {
fetchMock.get(`https://unpkg.com/@stoplight/spectral/rulesets/${rulesetName}/functions/${name}`, {
status: 200,
body: fn,
});
}
});

fetchMock.get('http://json-schema.org/draft-04/schema', {
status: 200,
Expand Down
32 changes: 32 additions & 0 deletions setupTests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { RulesetExceptionCollection } from './src/types/ruleset';

import { Dictionary } from '@stoplight/types';
import { IRunRule, isAsyncApiv2, Rule, Spectral } from './src';
import { readRuleset } from './src/rulesets';
import { getDiagnosticSeverity } from './src/rulesets/severity';

export const buildRulesetExceptionCollectionFrom = (
loc: string,
rules: string[] = ['a'],
Expand All @@ -8,3 +13,30 @@ export const buildRulesetExceptionCollectionFrom = (
source[loc] = rules;
return source;
};

export const buildTestSpectralWithAsyncApiRule = async (ruleName: string): Promise<[Spectral, IRunRule]> => {
const ruleset = await readRuleset('spectral:asyncapi');

expect(Object.keys(ruleset.rules)).toContain(ruleName);

const s = new Spectral();
s.registerFormat('asyncapi2', isAsyncApiv2);

const dic: Dictionary<Rule, string> = {};
const rule = ruleset.rules[ruleName];
dic[ruleName] = rule;

if (rule.severity === void 0) {
throw new Error('Unexpected undefined severity');
}

const expectedSeverity = getDiagnosticSeverity(rule.severity);

expect(expectedSeverity).not.toEqual(-1);

s.setRules(dic);

expect(Object.keys(s.rules)).toContain(ruleName);

return [s, s.rules[ruleName]];
};
Loading

0 comments on commit a463568

Please sign in to comment.