diff --git a/.gitignore b/.gitignore index 52e4271dfe3..c175fb3b488 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ node_modules/ packages/compute-baseline/dist/ packages/web-features/index.d.ts packages/**/LICENSE.txt +packages/web-features/data.json +packages/web-features/data.schema.json packages/web-features/types.ts -data.json index.js diff --git a/package.json b/package.json index d892bb06146..79ba4b63d06 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,8 @@ "dist": "tsx scripts/dist.ts", "feature-init": "tsx scripts/feature-init.ts", "format": "npx prettier --write .", - "schema-defs:write": "npm run schema-defs -- --out ./schemas/defs.schema.json", - "schema-defs": "ts-json-schema-generator --tsconfig ./tsconfig.json --type WebFeaturesData --path ./types.ts --id defs", + "schema:write": "npm run schema -- --out ./schemas/data.schema.json", + "schema": "ts-json-schema-generator --tsconfig ./tsconfig.json --path ./types.ts", "test:caniuse": "tsx scripts/caniuse.ts", "test:coverage": "npm run --workspaces test:coverage", "test:dist": "tsx scripts/dist.ts --check", diff --git a/packages/web-features/README.md b/packages/web-features/README.md index 696e5bba5eb..f86c6c08a86 100644 --- a/packages/web-features/README.md +++ b/packages/web-features/README.md @@ -19,6 +19,12 @@ import data from "web-features/data.json" with { type: "json" }; const { features, groups, snapshots } = data; ``` +To import the JSON schema with or without Node.js: + +```js +import schema from "web-features/data.schema.json" with { type: "json" }; +``` + ## Rendering Baseline statuses with `web-features` If you're using `web-features` to render Baseline iconography or browser logos with support markers, then you must follow these procedures to ensure consistent usage. diff --git a/packages/web-features/package.json b/packages/web-features/package.json index 072722d90f0..e3aa6ada92c 100644 --- a/packages/web-features/package.json +++ b/packages/web-features/package.json @@ -11,13 +11,15 @@ "main": "index.js", "exports": { ".": "./index.js", - "./data.json": "./data.json" + "./data.json": "./data.json", + "./data.schema.json": "./data.schema.json" }, "types": "./index.d.ts", "files": [ "index.d.ts", "index.js", - "data.json" + "data.json", + "data.schema.json" ], "scripts": { "prepare": "tsc && rm types.js && tsup ./index.ts --dts-only --format=esm --out-dir=." diff --git a/schemas/defs.schema.json b/schemas/data.schema.json similarity index 98% rename from schemas/defs.schema.json rename to schemas/data.schema.json index de1f1b8d67b..8d07d51fcd8 100644 --- a/schemas/defs.schema.json +++ b/schemas/data.schema.json @@ -1,6 +1,4 @@ { - "$id": "defs", - "$ref": "#/definitions/WebFeaturesData", "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "FeatureData": { diff --git a/scripts/build.ts b/scripts/build.ts index 472de2bcd88..239affce9f3 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -1,6 +1,7 @@ -import { execSync } from "child_process"; +import { basename } from "node:path"; +import { execSync } from "node:child_process"; +import fs from "node:fs"; import stringify from "fast-json-stable-stringify"; -import fs from "fs"; import yargs from "yargs"; import * as data from "../index.js"; @@ -17,14 +18,17 @@ yargs(process.argv.slice(2)) function buildPackage() { const packageDir = new URL("./packages/web-features/", rootDir); - const filesToCopy = ["LICENSE.txt", "types.ts"]; + const filesToCopy = ["LICENSE.txt", "types.ts", "schemas/data.schema.json"]; const json = stringify(data); // TODO: Validate the resulting JSON against a schema. const path = new URL("data.json", packageDir); fs.writeFileSync(path, json); for (const file of filesToCopy) { - fs.copyFileSync(new URL(file, rootDir), new URL(file, packageDir)); + fs.copyFileSync( + new URL(file, rootDir), + new URL(basename(file), packageDir), + ); } execSync("npm install", { cwd: "./packages/web-features", diff --git a/scripts/schema.ts b/scripts/schema.ts index 6eabf047312..81a110a6a14 100644 --- a/scripts/schema.ts +++ b/scripts/schema.ts @@ -8,19 +8,19 @@ import addFormats from 'ajv-formats'; import * as data from '../index.js'; -import defs from '../schemas/defs.schema.json' assert { type: 'json' }; +import schema from '../schemas/data.schema.json' assert { type: 'json' }; let status: 0 | 1 = 0; -function checkDefsConsistency(): void { - const defsPath: string = path.join(path.dirname(url.fileURLToPath(import.meta.url)), "../schemas/defs.schema.json"); - const defsOnDisk: string = fs.readFileSync(defsPath, { encoding: "utf-8"}); - const defsGenerated: string = child_process.execSync("npm run --silent schema-defs", { encoding: "utf-8"}).trim(); +function checkSchemaConsistency(): void { + const schemaPath: string = path.join(path.dirname(url.fileURLToPath(import.meta.url)), "../schemas/data.schema.json"); + const schemaOnDisk: string = fs.readFileSync(schemaPath, { encoding: "utf-8"}); + const schemaGenerated: string = child_process.execSync("npm run --silent schema", { encoding: "utf-8"}).trim(); - if (defsOnDisk !== defsGenerated) { - console.error("There's a mismatch between the schema defs on disk and types in `index.ts`."); + if (schemaOnDisk !== schemaGenerated) { + console.error("There's a mismatch between the schema on disk and types in `index.ts`."); console.error("This may produce misleading results for feature validation."); - console.error("To fix this, run `npm run schema-defs:write`."); + console.error("To fix this, run `npm run schema:write`."); status = 1; } } @@ -29,7 +29,7 @@ function validate() { const ajv = new Ajv({allErrors: true}); addFormats(ajv); - const validate = ajv.compile(defs); + const validate = ajv.compile(schema); const valid = validate(data); if (!valid) { @@ -40,6 +40,6 @@ function validate() { } } -checkDefsConsistency(); +checkSchemaConsistency(); validate(); process.exit(status);