Skip to content

Commit cb004b5

Browse files
committed
move utility
Signed-off-by: Utkarsh Srivastava <[email protected]>
1 parent da22eff commit cb004b5

10 files changed

+359
-173
lines changed

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@
1313

1414
# Dependency directories (remove the comment below to include it)
1515
# vendor/
16+
node_modules
17+
18+
*.yaml
19+
openapi-jsonschema*
20+

.golangci.yml

-150
This file was deleted.

Makefile

+7-21
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,10 @@
1-
check:
2-
golangci-lint run
1+
make: linux darwin windows
32

4-
check-clean-cache:
5-
golangci-lint cache clean
3+
darwin:
4+
nexe index.js -t darwin-x64 -o kubeopenapi-jsonschema-darwin
65

7-
protoc-setup:
8-
wget -P meshes https://raw.githubusercontent.com/layer5io/meshery/master/meshes/meshops.proto
6+
linux:
7+
nexe index.js -t linux-x64 -o kubeopenapi-jsonschema
98

10-
proto:
11-
protoc -I meshes/ meshes/meshops.proto --go_out=plugins=grpc:./meshes/
12-
13-
14-
15-
16-
17-
site:
18-
$(jekyll) serve --drafts --livereload
19-
20-
build:
21-
$(jekyll) build --drafts
22-
23-
docker:
24-
docker run --name site -d --rm -p 4000:4000 -v `pwd`:"/srv/jekyll" jekyll/jekyll:4.0.0 bash -c "bundle install; jekyll serve --drafts --livereload"
9+
windows:
10+
nexe index.js -t windows-x64 -o kubeopenapi-jsonschema

README.md

+26-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
1-
# layer5-repo-template
2-
This repository is used as the boilerplate for consistency across all Layer5 repos.
1+
# KubeOpenAPI - JSON Schema
2+
3+
This is a very basic node based CLI for converting OpenAPI schema to JSON Schema Draft 4
4+
5+
6+
```
7+
Usage: openapi-jsonschema [options]
8+
9+
Options:
10+
-t, --type [type] set type of input, can be either yaml or json (default: "yaml")
11+
-l, --location <location> location of the schema
12+
-f, --filter [query] give a query if a OpenAPISchema is nested
13+
--kubernetes enable kubernetes specific filters (default: false)
14+
-o [output-format] output format (default: "json")
15+
--o-filter [output-filter] output filter query
16+
--silent skip output (default: false)
17+
-h, --help display help for command
18+
```
19+
20+
## Example
21+
22+
Download the binaries from the github releases. Only linux-x64, darwin-x64 and windows-x64 binaries are released
23+
24+
```bash
25+
openapi-jsonschema --location ./istio.yaml -t yaml --filter '$[?(@.kind=="CustomResourceDefinition" && @.spec.names.kind=="EnvoyFilter")]..validation.openAPIV3Schema.properties.spec' -o yaml --o-filter '$[0]'
26+
```
327

428
<div>&nbsp;</div>
529

helper/createQuery.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* CreateQuery generates a jsonpath based query
3+
* @param {string} query jsonpath query
4+
* @param {boolean} isKubernetes is the query to be generated for K8s CRD
5+
* @returns {string} generated query
6+
*/
7+
function CreateQuery(query = "", isKubernetes = true) {
8+
if (isKubernetes || !query)
9+
return `$[?(@.kind=="CustomResourceDefinition")]..validation.openAPIV3Schema`;
10+
11+
return query;
12+
}
13+
14+
module.exports = CreateQuery;

helper/output.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const { dump } = require("js-yaml");
2+
const jp = require("jsonpath");
3+
4+
/**
5+
* Output takes in the data that needs to be printed and
6+
* an output format
7+
* @param {*} data
8+
* @param {"json" | "yaml"} format output format
9+
*/
10+
function Output(data, format = "json", filter = "", silent = false) {
11+
if (silent) return;
12+
13+
data = jp.query(data, filter);
14+
if (format === "yaml") return console.log(dump(data));
15+
if (format === "json") return console.log(JSON.stringify(data, null, 2));
16+
}
17+
18+
module.exports = Output;

helper/toJSONSchema.js

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// @ts-check
2+
const toJSONSchema = require("@openapi-contrib/openapi-schema-to-json-schema");
3+
const yaml = require("js-yaml");
4+
const { readFileSync, writeFileSync } = require("fs");
5+
const { tmpdir } = require("os");
6+
const path = require("path");
7+
const jp = require("jsonpath");
8+
9+
/**
10+
* convertAllSchemasToJSONSchema takes in the OpenAPIV3 Schemas in an array
11+
* and return an array of an equivalent JSON Schema Draft 4 schemas
12+
* @param {any[]} schemas array of schemas in JSON format
13+
* @returns {any[]} JSON Schema draft 4 formatted schemas
14+
*/
15+
function convertAllSchemasToJSONSchema(schemas) {
16+
if (Array.isArray(schemas))
17+
return schemas.map((schema) => toJSONSchema(schema));
18+
19+
return [];
20+
}
21+
22+
/**
23+
* readSchema will read schema file from the given location, it expects
24+
* the schema to be in JSON format
25+
*
26+
* readSchema will also apply the given jsonpath filter to the read schema
27+
* and will return only the filtered JSONs
28+
* @param {string} location
29+
* @param {string} query jsonpath based query
30+
* @returns {any[]}
31+
*/
32+
function readSchema(location, query) {
33+
const data = readFileSync(location, "utf-8");
34+
const parsed = JSON.parse(data);
35+
36+
return jp.query(parsed, query);
37+
}
38+
39+
/**
40+
* setupFiles takes the location of the files and convert them into json
41+
* and return the new location
42+
* @param {string} location
43+
* @param {"yaml" | "json"} type
44+
* @returns {string} location of the schema files
45+
*/
46+
function setupFiles(location, type) {
47+
if (type === "json") return location;
48+
49+
if (type === "yaml") {
50+
try {
51+
// Create a file name
52+
const filename = `ucnv-${Math.random().toString(36).substr(2, 5)}.json`;
53+
54+
// Create destination path
55+
const dest = path.join(tmpdir(), filename);
56+
57+
// Read file into memory and convert into json
58+
const doc = yaml.loadAll(readFileSync(location, "utf-8"));
59+
60+
// Write the converted file to the disk
61+
writeFileSync(dest, JSON.stringify(doc));
62+
63+
return dest;
64+
} catch (error) {
65+
return "";
66+
}
67+
}
68+
}
69+
70+
/**
71+
* ToJSONSchema will convert he OpenAPIV3 based schema to JSONSchema Draft 4 schemas
72+
* @param {string} location location of the schemas in open api v3 format
73+
* @param {"yaml" | "json"} type encoding in which the openapi schema is present
74+
* @param {string} query jsonpath query to filter the read schemas
75+
*/
76+
function ToJSONSchema(location, type = "yaml", query = "") {
77+
if (type !== "yaml" && type !== "json")
78+
throw Error('invalid type received: can be either "yaml" or "json"');
79+
80+
const source = setupFiles(location, type);
81+
82+
const schemas = readSchema(source, query);
83+
84+
return convertAllSchemasToJSONSchema(schemas);
85+
}
86+
87+
module.exports = ToJSONSchema;

index.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// @ts-check
2+
const { program } = require("commander");
3+
const CreateQuery = require("./helper/createQuery");
4+
const Output = require("./helper/output");
5+
const ToJSONSchema = require("./helper/toJSONSchema");
6+
7+
program
8+
.option(
9+
"-t, --type [type]",
10+
"set type of input, can be either yaml or json",
11+
"yaml"
12+
)
13+
.option("-l, --location <location>", "location of the schema")
14+
.option("-f, --filter [query]", "give a query if a OpenAPISchema is nested")
15+
.option("--kubernetes", "enable kubernetes specific filters", false)
16+
.option("-o [output-format]", "output format", "json")
17+
.option("--o-filter [output-filter]", "output filter query")
18+
.option("--silent", "skip output", false);
19+
20+
program.parse(process.argv);
21+
22+
const options = program.opts();
23+
24+
Output(
25+
ToJSONSchema(
26+
options.location,
27+
options.type,
28+
CreateQuery(options.filter, options.kubernetes)
29+
),
30+
options.o,
31+
options.oFilter,
32+
options.silent
33+
);

0 commit comments

Comments
 (0)