Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: prepare assets generation for future changes #1013

Merged
merged 5 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"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",
"generate-assets": "node ./scripts/generate-assets.js",
"generate-assets": "node -r ts-node/register ./scripts/generate-assets.ts",
"inline-version": "./scripts/inline-version.js",
"lint.fix": "yarn lint --fix",
"lint": "tsc --noEmit && tslint 'src/**/*.ts'",
Expand All @@ -49,7 +49,7 @@
"prebuild": "yarn build.clean && copyfiles -u 1 \"src/rulesets/oas*/**/*.json\" dist && copyfiles -u 1 \"src/rulesets/oas*/**/*.json\" ./ && yarn copy.html-templates",
"prebuild.binary": "yarn build",
"pretest.karma": "node ./scripts/generate-karma-fixtures.js && yarn pretest",
"pretest": "node ./scripts/generate-assets.js",
"pretest": "yarn generate-assets",
"schema.update": "yarn typescript-json-schema --id \"http://stoplight.io/schemas/rule.schema.json\" --required tsconfig.json IRule --out ./src/meta/rule.schema.json",
"test.harness": "jest -c ./jest.harness.config.js",
"test.karma": "karma start",
Expand Down
61 changes: 0 additions & 61 deletions scripts/generate-assets.js

This file was deleted.

68 changes: 68 additions & 0 deletions scripts/generate-assets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* 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:
* `<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'))`;
* If you execute the code above, ruleset will be loaded fully offline, without a need to make any request.
*/

import { IUriParserResult } from '@stoplight/json-ref-resolver/types';
import * as path from '@stoplight/path';
import { parse } from '@stoplight/yaml';
import * as fs from 'fs';
import { promisify } from 'util';
import { httpAndFileResolver } from '../dist/resolvers/http-and-file';

const readFileAsync = promisify(fs.readFile);
const writeFileAsync = promisify(fs.writeFile);
const readdirAsync = promisify(fs.readdir);
const statAsync = promisify(fs.stat);

const baseDir = path.join(__dirname, '../rulesets/assets/');

if (!fs.existsSync(baseDir)) {
fs.mkdirSync(baseDir);
}

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));
})();

async function processDirectory(assets: Record<string, string>, dir: string) {
await Promise.all(
(await readdirAsync(dir)).map(async (name: string) => {
if (name === 'schemas') return;
const target = path.join(dir, name);
const stats = await statAsync(target);
if (stats.isDirectory()) {
return processDirectory(assets, target);
} else {
let content = await readFileAsync(target, 'utf8');
if (path.extname(name) === '.json') {
content = JSON.stringify(
(
await httpAndFileResolver.resolve(JSON.parse(content), {
dereferenceRemote: true,
dereferenceInline: false,
baseUri: target,
parseResolveResult(opts) {
return new Promise<IUriParserResult>(resolve => {
resolve({ result: parse(opts.result) });
});
},
})
).result,
);
}

assets[path.join('@stoplight/spectral', path.relative(path.join(__dirname, '..'), target))] = content;
}
}),
);
}
6 changes: 3 additions & 3 deletions scripts/generate-karma-fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ if (!fs.existsSync(baseDir)) {
fs.mkdirSync(baseDir);
}

for (const spec of ['', '2', '3']) {
const target = path.join(baseDir, `oas${spec}-functions.json`);
const fnsPath = path.join(__dirname, `../rulesets/oas${spec}/functions`);
for (const rulesetName of ['oas']) {
const target = path.join(baseDir, `${rulesetName}-functions.json`);
const fnsPath = path.join(__dirname, `../rulesets/${rulesetName}/functions`);
const bundledFns = {};

if (fs.existsSync(fnsPath)) {
Expand Down
38 changes: 38 additions & 0 deletions src/__tests__/generate-assets.jest.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { existsSync, readFileSync } from 'fs';

describe('generate-assets', () => {
let assets: Record<string, string>;

beforeAll(() => {
const path = __dirname + '/../../rulesets/assets/assets.json';
if (!existsSync(path)) {
fail('Missing assets.json file. Please run `yarn generate-assets`.');
}

const content = readFileSync(path, { encoding: 'utf8' });
assets = JSON.parse(content);
expect(assets).not.toBeUndefined();
expect(Object.keys(assets).length).toBeGreaterThan(1);
});

describe('produces properly serialized built-in rulesets', () => {
const testCases = [
['oas', 'oas2-schema', 'title', 'A JSON Schema for Swagger 2.0 API.'],
['oas', 'oas3-schema', 'description', 'Validation schema for OpenAPI Specification 3.0.X.'],
];

it.each(testCases)(
"Ruleset '%s' contains a rule '%s' with an inlined schema bearing a '%s' property",
(ruleset: string, ruleName: string, schemaKey: string, schemaValue: string) => {
const key = `@stoplight/spectral/rulesets/${ruleset}/index.json`;
expect(Object.keys(assets)).toContain(key);
const content = JSON.parse(assets[key]);
const rule = content.rules[ruleName];
expect(rule).not.toBeUndefined();
const schema = rule.then.functionOptions.schema;
expect(schema[schemaKey]).not.toBeUndefined();
expect(schema[schemaKey]).toEqual(schemaValue);
},
);
});
});
2 changes: 1 addition & 1 deletion src/rulesets/__tests__/offline.schemas.jest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ describe('Online vs Offline context', () => {
test('all rulesets are accounted for', async () => {
const dir = path.join(__dirname, '../../../rulesets/');

// Would that fail, run `yarn generate-assets` ;-)
// Would that fail, run `yarn build` ;-)
expect(fs.existsSync(dir)).toBeTruthy();

const discoveredRulesets: string[] = [];
Expand Down