Skip to content

Commit 0267828

Browse files
committed
[repo] Ensure that projects.json is appropriately linted
This requires a few bigger changes: The existing schema was against an old spec version, but included some features from newer spec versions. This commit includes a bump to a newer standard.
1 parent 12f4f4d commit 0267828

File tree

7 files changed

+155
-6
lines changed

7 files changed

+155
-6
lines changed

.lintstagedrc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@
77
],
88
"src/**/*.{js,jsx,ts,tsx,mjs}": [
99
"cspell --no-must-find-files --no-progress"
10+
],
11+
"data/projects.json": [
12+
"yarn ajv --spec=draft2019 validate -s static/schema/projects.json -d"
1013
]
1114
}

.vscode/extensions.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"davidanson.vscode-markdownlint",
77
"streetsidesoftware.code-spell-checker",
88
"dbaeumer.vscode-eslint",
9-
"tberman.json-schema-validator",
109
"silvenon.mdx",
1110
"gamunu.vscode-yarn",
1211
"EditorConfig.EditorConfig"

cspell.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const config = {
5555
],
5656
ignorePaths: [
5757
'*.js',
58+
'*.mjs',
5859
'CHANGELOG.md',
5960
'package.json',
6061
'yarn.lock',

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,14 @@
5959
]
6060
},
6161
"devDependencies": {
62+
"@apidevtools/json-schema-ref-parser": "^9.0.9",
6263
"@docusaurus/module-type-aliases": "^2.0.0-beta.18",
6364
"@tsconfig/docusaurus": "^1.0.5",
6465
"@types/core-js": "^2.5.5",
6566
"@types/node": "^17.0.31",
6667
"@typescript-eslint/eslint-plugin": "^5.19.0",
6768
"@typescript-eslint/parser": "^5.19.0",
69+
"ajv-cli": "^5.0.0",
6870
"babel-jest": "^27.5.1",
6971
"cspell": "^5.19.7",
7072
"eslint": "^8.13.0",

scripts/jsonlint.mjs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env node --experimental-json-modules
2+
/**
3+
* Copyright (c) Moodle Pty Ltd.
4+
*
5+
* Moodle is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* Moodle is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
/* eslint-disable import/no-extraneous-dependencies */
20+
import path from 'path';
21+
import { readFile } from 'fs/promises';
22+
import { program } from 'commander';
23+
import $RefParser from '@apidevtools/json-schema-ref-parser';
24+
import Ajv from 'ajv/dist/2019.js';
25+
import Draft7Schema from 'ajv/dist/refs/json-schema-draft-07.json' assert {type: 'json'};
26+
27+
program
28+
.name('jsonlint')
29+
.description('Check a JSON file for validity against a schema')
30+
.version('1.0.0');
31+
32+
const getSchemaDefinition = async (schema) => {
33+
console.log(`Getting schema at ${schema}`);
34+
try {
35+
return await $RefParser.dereference(schema);
36+
} catch (err) {
37+
console.error(err);
38+
process.exit(1);
39+
}
40+
return Promise.reject();
41+
};
42+
43+
const getSchema = (filepath, schema) => {
44+
if (schema.startsWith('http://') || schema.startsWith('https://')) {
45+
return schema;
46+
}
47+
48+
if (schema.startsWith('file://') || schema.startsWith('.')) {
49+
return path.resolve(path.dirname(filepath), schema);
50+
}
51+
52+
return schema;
53+
};
54+
55+
program
56+
.arguments('<filepath>', 'Path to the file to check')
57+
.action(async (filename) => {
58+
const filepath = path.resolve(filename);
59+
const rawJson = await readFile(filepath, { encoding: 'utf-8' });
60+
const json = JSON.parse(rawJson);
61+
if (typeof json.$schema === 'undefined') {
62+
console.log('Nothing to validate against');
63+
process.exit(0);
64+
}
65+
66+
const schema = await getSchemaDefinition(getSchema(filepath, json.$schema));
67+
68+
const ajv = new Ajv();
69+
ajv.addMetaSchema(Draft7Schema);
70+
71+
const valid = ajv.validate(schema, json);
72+
if (valid) {
73+
console.log(`No errors found validating ${filepath} against ${json.$schema}`);
74+
} else {
75+
console.log(ajv.errors);
76+
process.exit(1);
77+
}
78+
});
79+
80+
program.parse();

static/schema/projects.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"title": "JSON schema for the Moodle Project list",
3-
"$schema": "http://json-schema.org/draft-04/schema",
43
"$id": "https://moodle.github.io/devdocs/schema/projects.json",
4+
"$schema": "https://json-schema.org/draft/2019-09/schema",
55
"type": "object",
66
"properties": {
77
"projects": {

yarn.lock

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,16 @@
181181
jsonpointer "^5.0.0"
182182
leven "^3.1.0"
183183

184+
"@apidevtools/json-schema-ref-parser@^9.0.9":
185+
version "9.0.9"
186+
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b"
187+
integrity sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==
188+
dependencies:
189+
"@jsdevtools/ono" "^7.1.3"
190+
"@types/json-schema" "^7.0.6"
191+
call-me-maybe "^1.0.1"
192+
js-yaml "^4.1.0"
193+
184194
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3":
185195
version "7.16.7"
186196
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789"
@@ -2291,6 +2301,11 @@
22912301
"@jridgewell/resolve-uri" "^3.0.3"
22922302
"@jridgewell/sourcemap-codec" "^1.4.10"
22932303

2304+
"@jsdevtools/ono@^7.1.3":
2305+
version "7.1.3"
2306+
resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
2307+
integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==
2308+
22942309
"@mdx-js/mdx@^1.6.22":
22952310
version "1.6.22"
22962311
resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.22.tgz#8a723157bf90e78f17dc0f27995398e6c731f1ba"
@@ -2826,7 +2841,7 @@
28262841
dependencies:
28272842
"@types/istanbul-lib-report" "*"
28282843

2829-
"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
2844+
"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
28302845
version "7.0.11"
28312846
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
28322847
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
@@ -3309,6 +3324,19 @@ aggregate-error@^3.0.0:
33093324
clean-stack "^2.0.0"
33103325
indent-string "^4.0.0"
33113326

3327+
ajv-cli@^5.0.0:
3328+
version "5.0.0"
3329+
resolved "https://registry.yarnpkg.com/ajv-cli/-/ajv-cli-5.0.0.tgz#78956ed2934e6dde4c9e696b587be1c2998862e8"
3330+
integrity sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==
3331+
dependencies:
3332+
ajv "^8.0.0"
3333+
fast-json-patch "^2.0.0"
3334+
glob "^7.1.0"
3335+
js-yaml "^3.14.0"
3336+
json-schema-migrate "^2.0.0"
3337+
json5 "^2.1.3"
3338+
minimist "^1.2.0"
3339+
33123340
ajv-formats@^2.1.1:
33133341
version "2.1.1"
33143342
resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
@@ -3976,6 +4004,11 @@ call-bind@^1.0.0, call-bind@^1.0.2:
39764004
function-bind "^1.1.1"
39774005
get-intrinsic "^1.0.2"
39784006

4007+
call-me-maybe@^1.0.1:
4008+
version "1.0.1"
4009+
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
4010+
integrity sha512-wCyFsDQkKPwwF8BDwOiWNx/9K45L/hvggQiDbve+viMNMQnWhrlYIuBk09offfwCRtCO9P6XwUttufzU11WCVw==
4011+
39794012
callsites@^3.0.0, callsites@^3.1.0:
39804013
version "3.1.0"
39814014
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
@@ -6365,6 +6398,11 @@ extsprintf@^1.2.0:
63656398
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07"
63666399
integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
63676400

6401+
fast-deep-equal@^2.0.1:
6402+
version "2.0.1"
6403+
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
6404+
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
6405+
63686406
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
63696407
version "3.1.3"
63706408
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
@@ -6386,6 +6424,13 @@ fast-glob@^3.2.11, fast-glob@^3.2.7, fast-glob@^3.2.9:
63866424
merge2 "^1.3.0"
63876425
micromatch "^4.0.4"
63886426

6427+
fast-json-patch@^2.0.0:
6428+
version "2.2.1"
6429+
resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-2.2.1.tgz#18150d36c9ab65c7209e7d4eb113f4f8eaabe6d9"
6430+
integrity sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==
6431+
dependencies:
6432+
fast-deep-equal "^2.0.1"
6433+
63896434
fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0:
63906435
version "2.1.0"
63916436
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
@@ -6805,6 +6850,18 @@ glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, gl
68056850
once "^1.3.0"
68066851
path-is-absolute "^1.0.0"
68076852

6853+
glob@^7.1.0:
6854+
version "7.2.3"
6855+
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
6856+
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
6857+
dependencies:
6858+
fs.realpath "^1.0.0"
6859+
inflight "^1.0.4"
6860+
inherits "2"
6861+
minimatch "^3.1.1"
6862+
once "^1.3.0"
6863+
path-is-absolute "^1.0.0"
6864+
68086865
global-dirs@^0.1.1:
68096866
version "0.1.1"
68106867
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
@@ -8321,7 +8378,7 @@ joi@^17.6.0:
83218378
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
83228379
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
83238380

8324-
js-yaml@^3.13.1:
8381+
js-yaml@^3.13.1, js-yaml@^3.14.0:
83258382
version "3.14.1"
83268383
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
83278384
integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
@@ -8404,6 +8461,13 @@ json-parse-even-better-errors@^2.3.0:
84048461
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
84058462
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
84068463

8464+
json-schema-migrate@^2.0.0:
8465+
version "2.0.0"
8466+
resolved "https://registry.yarnpkg.com/json-schema-migrate/-/json-schema-migrate-2.0.0.tgz#335ef5218cd32fcc96c1ddce66c71ba586224496"
8467+
integrity sha512-r38SVTtojDRp4eD6WsCqiE0eNDt4v1WalBXb9cyZYw9ai5cGtBwzRNWjHzJl38w6TxFkXAIA7h+fyX3tnrAFhQ==
8468+
dependencies:
8469+
ajv "^8.0.0"
8470+
84078471
json-schema-traverse@^0.4.1:
84088472
version "0.4.1"
84098473
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
@@ -8429,7 +8493,7 @@ json-stringify-safe@~5.0.1:
84298493
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
84308494
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
84318495

8432-
json5@2.x, json5@^2.1.2, json5@^2.2.0:
8496+
json5@2.x, json5@^2.1.2, json5@^2.1.3, json5@^2.2.0:
84338497
version "2.2.1"
84348498
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
84358499
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
@@ -9160,7 +9224,7 @@ minimatch@3.0.4:
91609224
dependencies:
91619225
brace-expansion "^1.1.7"
91629226

9163-
minimatch@^3.0.4, minimatch@^3.1.2:
9227+
minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
91649228
version "3.1.2"
91659229
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
91669230
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==

0 commit comments

Comments
 (0)