v8r 0.10.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +5 -5
- package/src/ajv.js +1 -1
- package/src/catalogs.js +68 -0
- package/src/cli.js +4 -72
- package/src/io.js +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 📦 [0.11.1](https://www.npmjs.com/package/v8r/v/0.11.1) - 2022-03-03
|
|
4
|
+
|
|
5
|
+
* Fix: call minimatch with `{dot: true}`, fixes [#174](https://github.com/chris48s/v8r/issues/174)
|
|
6
|
+
|
|
7
|
+
## 📦 [0.11.0](https://www.npmjs.com/package/v8r/v/0.11.0) - 2022-02-27
|
|
8
|
+
|
|
9
|
+
* Drop compatibility with node 12, now requires node `^14.13.1 || >=15.0.0`
|
|
10
|
+
* Upgrade to got 12 internally
|
|
11
|
+
* Call ajv with `allErrors` flag
|
|
12
|
+
|
|
13
|
+
## 📦 [0.10.1](https://www.npmjs.com/package/v8r/v/0.10.1) - 2022-01-06
|
|
14
|
+
|
|
15
|
+
* Fix `--version` flag when installed globally in some environments
|
|
16
|
+
|
|
3
17
|
## 📦 [0.10.0](https://www.npmjs.com/package/v8r/v/0.10.0) - 2022-01-03
|
|
4
18
|
|
|
5
19
|
* Accept multiple filenames or globs as positional args. e.g:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "v8r",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "A command-line JSON and YAML validator that's on your wavelength",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "V8R_CACHE_NAME=v8r-test c8 --reporter=text mocha \"src/**/*.spec.js\"",
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"chalk": "^5.0.0",
|
|
30
30
|
"flat-cache": "^3.0.4",
|
|
31
31
|
"glob": "^7.2.0",
|
|
32
|
-
"got": "^
|
|
32
|
+
"got": "^12.0.1",
|
|
33
33
|
"is-url": "^1.2.4",
|
|
34
34
|
"js-yaml": "^4.0.0",
|
|
35
35
|
"json5": "^2.2.0",
|
|
36
|
-
"minimatch": "^
|
|
36
|
+
"minimatch": "^5.0.1",
|
|
37
37
|
"yargs": "^17.0.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
@@ -42,14 +42,14 @@
|
|
|
42
42
|
"chai-as-promised": "^7.1.1",
|
|
43
43
|
"eslint": "^8.0.1",
|
|
44
44
|
"eslint-config-prettier": "^8.1.0",
|
|
45
|
-
"eslint-plugin-mocha": "^
|
|
45
|
+
"eslint-plugin-mocha": "^10.0.3",
|
|
46
46
|
"eslint-plugin-prettier": "^4.0.0",
|
|
47
47
|
"mocha": "^9.0.0",
|
|
48
48
|
"nock": "^13.0.4",
|
|
49
49
|
"prettier": "^2.1.2"
|
|
50
50
|
},
|
|
51
51
|
"engines": {
|
|
52
|
-
"node": "^
|
|
52
|
+
"node": "^14.13.1 || >=15.0.0"
|
|
53
53
|
},
|
|
54
54
|
"type": "module",
|
|
55
55
|
"keywords": [
|
package/src/ajv.js
CHANGED
|
@@ -11,7 +11,7 @@ import addFormats from "ajv-formats";
|
|
|
11
11
|
|
|
12
12
|
function _ajvFactory(schema, cache) {
|
|
13
13
|
const resolver = (url) => cache.fetch(url);
|
|
14
|
-
const opts = { loadSchema: resolver, strict: "log" };
|
|
14
|
+
const opts = { allErrors: true, loadSchema: resolver, strict: "log" };
|
|
15
15
|
|
|
16
16
|
if (
|
|
17
17
|
typeof schema["$schema"] === "string" ||
|
package/src/catalogs.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import minimatch from "minimatch";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { validate } from "./ajv.js";
|
|
4
|
+
import { getFromUrlOrFile } from "./io.js";
|
|
5
|
+
import logging from "./logging.js";
|
|
6
|
+
|
|
7
|
+
const SCHEMASTORE_CATALOG_SCHEMA_URL =
|
|
8
|
+
"https://json.schemastore.org/schema-catalog.json";
|
|
9
|
+
|
|
10
|
+
async function getSchemaUrlForFilename(catalogs, filename, cache) {
|
|
11
|
+
for (const [i, catalogLocation] of catalogs.entries()) {
|
|
12
|
+
const catalog = await getFromUrlOrFile(catalogLocation, cache);
|
|
13
|
+
const catalogSchema = await getFromUrlOrFile(
|
|
14
|
+
SCHEMASTORE_CATALOG_SCHEMA_URL,
|
|
15
|
+
cache
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
// Validate the catalog
|
|
19
|
+
const valid = await validate(catalog, catalogSchema, cache);
|
|
20
|
+
if (!valid || catalog.schemas === undefined) {
|
|
21
|
+
throw new Error(`Malformed catalog at ${catalogLocation}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const { schemas } = catalog;
|
|
25
|
+
const matches = getSchemaMatchesForFilename(schemas, filename);
|
|
26
|
+
logging.debug(`Searching for schema in ${catalogLocation} ...`);
|
|
27
|
+
if (matches.length === 1) {
|
|
28
|
+
logging.info(`Found schema in ${catalogLocation} ...`);
|
|
29
|
+
return matches[0].url; // Match found. We're done.
|
|
30
|
+
}
|
|
31
|
+
if (matches.length === 0 && i < catalogs.length - 1) {
|
|
32
|
+
continue; // No match found. Try the next catalog in the array.
|
|
33
|
+
}
|
|
34
|
+
if (matches.length > 1) {
|
|
35
|
+
// We found >1 matches in the same catalog. This is always a hard error.
|
|
36
|
+
const matchesLog = matches
|
|
37
|
+
.map((match) => ` ${match.description}: ${match.url}`)
|
|
38
|
+
.join("\n");
|
|
39
|
+
logging.info(
|
|
40
|
+
`Found multiple possible schemas for ${filename}. Possible matches:\n${matchesLog}`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
// Either we found >1 matches in the same catalog or we found 0 matches
|
|
44
|
+
// in the last catalog and there are no more catalogs left to try.
|
|
45
|
+
throw new Error(`Could not find a schema to validate ${filename}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getSchemaMatchesForFilename(schemas, filename) {
|
|
50
|
+
const matches = [];
|
|
51
|
+
schemas.forEach(function (schema) {
|
|
52
|
+
if ("fileMatch" in schema) {
|
|
53
|
+
if (schema.fileMatch.includes(path.basename(filename))) {
|
|
54
|
+
matches.push(schema);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
for (const glob of schema.fileMatch) {
|
|
58
|
+
if (minimatch(path.normalize(filename), glob, { dot: true })) {
|
|
59
|
+
matches.push(schema);
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return matches;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { getSchemaMatchesForFilename, getSchemaUrlForFilename };
|
package/src/cli.js
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import flatCache from "flat-cache";
|
|
2
2
|
import fs from "fs";
|
|
3
|
-
import
|
|
4
|
-
import minimatch from "minimatch";
|
|
3
|
+
import { createRequire } from "module";
|
|
5
4
|
import os from "os";
|
|
6
5
|
import path from "path";
|
|
7
6
|
import yargs from "yargs";
|
|
8
7
|
import { hideBin } from "yargs/helpers";
|
|
9
8
|
import { validate } from "./ajv.js";
|
|
10
9
|
import { Cache } from "./cache.js";
|
|
10
|
+
import { getSchemaUrlForFilename } from "./catalogs.js";
|
|
11
11
|
import { getFiles } from "./glob.js";
|
|
12
|
+
import { getFromUrlOrFile } from "./io.js";
|
|
12
13
|
import logging from "./logging.js";
|
|
13
14
|
import { parseFile } from "./parser.js";
|
|
14
15
|
|
|
15
16
|
const SCHEMASTORE_CATALOG_URL =
|
|
16
17
|
"https://www.schemastore.org/api/json/catalog.json";
|
|
17
18
|
|
|
18
|
-
const SCHEMASTORE_CATALOG_SCHEMA_URL =
|
|
19
|
-
"https://json.schemastore.org/schema-catalog.json";
|
|
20
|
-
|
|
21
19
|
const EXIT = {
|
|
22
20
|
VALID: 0,
|
|
23
21
|
ERROR: 1,
|
|
@@ -27,70 +25,6 @@ const EXIT = {
|
|
|
27
25
|
|
|
28
26
|
const CACHE_DIR = path.join(os.tmpdir(), "flat-cache");
|
|
29
27
|
|
|
30
|
-
async function getFromUrlOrFile(location, cache) {
|
|
31
|
-
return isUrl(location)
|
|
32
|
-
? await cache.fetch(location)
|
|
33
|
-
: JSON.parse(await fs.promises.readFile(location, "utf8"));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function getSchemaUrlForFilename(catalogs, filename, cache) {
|
|
37
|
-
for (const [i, catalogLocation] of catalogs.entries()) {
|
|
38
|
-
const catalog = await getFromUrlOrFile(catalogLocation, cache);
|
|
39
|
-
const catalogSchema = await getFromUrlOrFile(
|
|
40
|
-
SCHEMASTORE_CATALOG_SCHEMA_URL,
|
|
41
|
-
cache
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
// Validate the catalog
|
|
45
|
-
const valid = await validate(catalog, catalogSchema, cache);
|
|
46
|
-
if (!valid || catalog.schemas === undefined) {
|
|
47
|
-
throw new Error(`Malformed catalog at ${catalogLocation}`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const { schemas } = catalog;
|
|
51
|
-
const matches = getSchemaMatchesForFilename(schemas, filename);
|
|
52
|
-
logging.debug(`Searching for schema in ${catalogLocation} ...`);
|
|
53
|
-
if (matches.length === 1) {
|
|
54
|
-
logging.info(`Found schema in ${catalogLocation} ...`);
|
|
55
|
-
return matches[0].url; // Match found. We're done.
|
|
56
|
-
}
|
|
57
|
-
if (matches.length === 0 && i < catalogs.length - 1) {
|
|
58
|
-
continue; // No match found. Try the next catalog in the array.
|
|
59
|
-
}
|
|
60
|
-
if (matches.length > 1) {
|
|
61
|
-
// We found >1 matches in the same catalog. This is always a hard error.
|
|
62
|
-
const matchesLog = matches
|
|
63
|
-
.map((match) => ` ${match.description}: ${match.url}`)
|
|
64
|
-
.join("\n");
|
|
65
|
-
logging.info(
|
|
66
|
-
`Found multiple possible schemas for ${filename}. Possible matches:\n${matchesLog}`
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
// Either we found >1 matches in the same catalog or we found 0 matches
|
|
70
|
-
// in the last catalog and there are no more catalogs left to try.
|
|
71
|
-
throw new Error(`Could not find a schema to validate ${filename}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function getSchemaMatchesForFilename(schemas, filename) {
|
|
76
|
-
const matches = [];
|
|
77
|
-
schemas.forEach(function (schema) {
|
|
78
|
-
if ("fileMatch" in schema) {
|
|
79
|
-
if (schema.fileMatch.includes(path.basename(filename))) {
|
|
80
|
-
matches.push(schema);
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
for (const glob of schema.fileMatch) {
|
|
84
|
-
if (minimatch(path.normalize(filename), glob)) {
|
|
85
|
-
matches.push(schema);
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
return matches;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
28
|
function secondsToMilliseconds(seconds) {
|
|
95
29
|
return seconds * 1000;
|
|
96
30
|
}
|
|
@@ -202,9 +136,7 @@ function parseArgs(argv) {
|
|
|
202
136
|
.version(
|
|
203
137
|
// Workaround for https://github.com/yargs/yargs/issues/1934
|
|
204
138
|
// TODO: remove once fixed
|
|
205
|
-
|
|
206
|
-
fs.readFileSync(new URL("../package.json", import.meta.url).pathname)
|
|
207
|
-
).version
|
|
139
|
+
createRequire(import.meta.url)("../package.json").version
|
|
208
140
|
)
|
|
209
141
|
.option("verbose", {
|
|
210
142
|
alias: "v",
|
package/src/io.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import isUrl from "is-url";
|
|
3
|
+
|
|
4
|
+
async function getFromUrlOrFile(location, cache) {
|
|
5
|
+
return isUrl(location)
|
|
6
|
+
? await cache.fetch(location)
|
|
7
|
+
: JSON.parse(await fs.promises.readFile(location, "utf8"));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { getFromUrlOrFile };
|