jsonSchemaCatalogs: init

This commit is contained in:
Robert Hensing
2025-05-30 10:11:21 +02:00
parent 57d64ea427
commit bfe8a98e48
7 changed files with 300 additions and 0 deletions

View File

@@ -1,6 +1,7 @@
{
callPackage,
fetchFromGitHub,
jsonSchemaCatalogs,
lib,
nix-update-script,
rustPlatform,
@@ -28,6 +29,9 @@ rustPlatform.buildRustPackage (finalAttrs: {
passthru = {
tests = {
run = callPackage ./test-run.nix { json-schema-catalog-rs = finalAttrs.finalPackage; };
jsonSchemaCatalogs = jsonSchemaCatalogs.tests.override {
json-schema-catalog-rs = finalAttrs.finalPackage;
};
};
updateScript = nix-update-script { };

View File

@@ -0,0 +1,33 @@
{
fetchurl,
lib,
newCatalog,
}:
newCatalog {
name = "json-patch-schemastore";
displayName = "JSON Patch as maintained by the https://www.schemastore.org community";
version = "2024-11-26";
groups = {
"JSON Patch" = {
"https://json.schemastore.org/json-patch.json" = fetchurl {
name = "json-patch-schema";
# Note that we don't use the json.schemastore.org URLs directly, as those are mutable resources.
# Make sure to update the version above!
url = "https://github.com/schemastore/schemastore/raw/138439cd4f9d7bf57d6747b674ce5bbcffbfafdc/src/schemas/json/json-patch.json";
hash = "sha256-vrqlgvlU61aEO6jd1SLLEqJDZG1k+eTBozcyPmhUp2U=";
};
};
};
extraDescription = ''
A JSON Patch is a sequence of editing and checking operations to perform against another JSON document.
It is specified in IETF RFC 6902: https://datatracker.ietf.org/doc/html/rfc6902/
The schema is maintained by the community at https://www.schemastore.org, which is a collection of JSON Schemas for various purposes.
'';
meta = {
maintainers = with lib.maintainers; [ roberth ];
license = lib.licenses.asl20;
changelog = "https://github.com/schemastore/schemastore/commits/master/src/schemas/json/json-patch.json";
};
}

View File

@@ -0,0 +1,39 @@
{
fetchurl,
lib,
newCatalog,
}:
newCatalog {
name = "json-schema";
displayName = "JSON Schema Metaschemas";
groups = {
"JSON Schema" = {
"http://json-schema.org/draft-04/schema#" = fetchurl {
name = "json-schema-draft-04";
url = "https://json-schema.org/draft-04/schema";
hash = "sha256-4UidC0dV8CeTMCWR0/y48Htok6gqlPJIlfjk7fEbguI=";
};
"http://json-schema.org/draft-06/schema#" = fetchurl {
name = "json-schema-draft-06";
url = "https://json-schema.org/draft-06/schema";
hash = "sha256-AGTogLohS/8c7lEeZ4++SMmCbdNZ6R4kI/w23mey6+E=";
};
"http://json-schema.org/draft-07/schema#" = fetchurl {
name = "json-schema-draft-07";
url = "https://json-schema.org/draft-07/schema";
hash = "sha256-aS4dFl5Hr8tfEbLOHGOWNf+oNANdbstrzzCHSB2uhAQ=";
};
# Unclear how newer metaschemas should be handled, so leaving them out for now.
# https://github.com/roberth/json-schema-catalog-rs/issues/8
};
};
meta = {
maintainers = with lib.maintainers; [ roberth ];
# https://github.com/json-schema-org/json-schema-spec/blob/main/LICENSE
license = [
lib.licenses.bsd3
lib.licenses.afl3
];
};
}

View File

@@ -0,0 +1,28 @@
{
lib,
newScope,
json-schema-catalog-rs,
jsonschema-cli,
}:
let
inherit (lib) concatMapAttrs optionalAttrs;
inherit (lib.strings) hasSuffix removeSuffix;
jsonSchemaCatalogs = lib.makeScope newScope (
self:
{
inherit ((self.callPackage ./lib.nix { }).lib) newCatalog;
tests = self.callPackage ./tests.nix { };
}
// concatMapAttrs (
k: v:
optionalAttrs (v == "regular" && hasSuffix ".nix" k) {
${removeSuffix ".nix" k} = self.callPackage (./catalogs + "/${k}") { };
}
) (builtins.readDir ./catalogs)
);
in
{
# Exported to `pkgs`
inherit jsonSchemaCatalogs;
}

View File

@@ -0,0 +1,120 @@
{
lib,
json-schema-catalog-rs,
runCommand,
jq,
}:
let
/**
A somewhat opinionated method for constructing a JSON Schema Catalog from files in a Nix store.
The input is a slightly simpler format:
```nix
{
name = "my-catalog"; # derivation name, default displayName
displayName = "My Catalog"; # optional
groups = {
"Group One" = {
"https://example.com/schemas/one-v1.json" = pkgs.fetchurl { ... };
"https://example.com/schemas/one-v2.json" = pkgs.fetchurl { ... };
"https://example.com/schemas/one-common.json" = pkgs.fetchurl { ... };
};
"Group Two" = {
"https://example.com/schemas/two-v1.json" = ./two-v1.json; # Files can be local
};
};
}
```
*/
newCatalog =
{
name,
displayName ? name,
groups,
version ? null,
extraDescription ? null,
meta ? { },
}:
let
# lazyDerivation tidies up the package attributes
package = lib.lazyDerivation {
derivation = drv;
passthru = {
name = "catalog-${name}";
internals = drv;
}
// lib.optionalAttrs (version != null) {
inherit version;
};
meta = {
description = "JSON Schema Catalog for ${displayName}";
longDescription =
let
licenses = lib.toList meta.license;
show = license: license.fullName or license;
theLicensesApply =
if lib.length licenses == 1 then
"The package license, ${show (lib.head licenses)}, applies"
else
"The package licenses, ${lib.concatMapStringsSep " / " show licenses}, apply";
in
''
A JSON Schema Catalog is a mapping from URIs to JSON Schema documents.
It enables offline use, e.g. in build processes, and therefore it improves performance, robustness and safety.
${lib.optionalString (extraDescription != null) "\n${extraDescription}\n"}
${theLicensesApply} to the schemas in this catalog. The catalog file itself is licensed under the terms of the Nix expression that governs it, e.g. MIT in the case of Nixpkgs.
'';
}
// meta;
};
drvArgs = {
pname = name;
catalogJson = builtins.toJSON {
name = displayName;
groups = lib.mapAttrsToList (name: group: {
inherit name;
# TODO dedup the longest common prefix by putting it in baseLocation
baseLocation = "/";
schemas = lib.mapAttrsToList (id: location: {
inherit id;
inherit location;
}) group;
}) groups;
};
passAsFile = [ "catalogJson" ];
passthru = {
inherit groups;
};
nativeBuildInputs = [
jq
json-schema-catalog-rs
];
}
// lib.optionalAttrs (version != null) {
inherit version;
};
drv = runCommand "${package.name}${lib.optionalString (version != null) "-${version}"}" drvArgs ''
out_dir="$out/share/json-schema-catalogs"
out_file="$out_dir/$name.json"
mkdir -p "$out_dir"
# Write the catalog JSON. `jq` formats it nicely.
jq . <"$catalogJsonPath" >"$out_file"
json-schema-catalog check "$out_file"
'';
in
package;
in
{
lib =
# Exported as part of `pkgs.jsonSchemaCatalogs`
{
inherit newCatalog;
};
}

View File

@@ -0,0 +1,69 @@
{
json-schema,
lib,
json-schema-catalog-rs,
runCommand,
}:
lib.recurseIntoAttrs {
test-with-json-schema-catalog-rs =
runCommand "json-schema-catalogs-integration-test"
{
nativeBuildInputs = [
json-schema
json-schema-catalog-rs
];
}
''
cat >example.json <<"EOF"
{
"$id": "https://example.com/schemas/integration-test.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Integration Test",
"type": "object",
"oneOf": [
{
"$ref": "http://json-schema.org/draft-07/schema#"
},
{
"$ref": "http://json-schema.org/draft-07/schema#/definitions/yolo"
},
{
"$ref": "./foo.json#/definitions/bar"
}
]
}
EOF
cat >example.json.expected <<"EOF"
{
"$id": "https://example.com/schemas/integration-test.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"oneOf": [
{
"$ref": "file://${
json-schema.internals.groups."JSON Schema"."http://json-schema.org/draft-07/schema#"
}#"
},
{
"$ref": "file://${
json-schema.internals.groups."JSON Schema"."http://json-schema.org/draft-07/schema#"
}#/definitions/yolo"
},
{
"$ref": "./foo.json#/definitions/bar"
}
],
"title": "Integration Test",
"type": "object"
}
EOF
( set -x;
! grep '##' example.json.expected
)
json-schema-catalog replace --verbose example.json > example.json.out
diff -U3 --color=always example.json.expected example.json.out
touch $out
'';
}

View File

@@ -11474,6 +11474,13 @@ with pkgs;
iosevka-comfy = recurseIntoAttrs (callPackages ../data/fonts/iosevka/comfy.nix { });
/**
A JSON Schema Catalog is a mapping from URIs to JSON Schema documents.
It enables offline use, e.g. in build processes, and it improves performance, robustness and safety.
*/
inherit (callPackage ../data/json-schema/default.nix { }) jsonSchemaCatalogs;
kde-rounded-corners =
kdePackages.callPackage ../data/themes/kwin-decorations/kde-rounded-corners
{ };