summaryrefslogtreecommitdiff
path: root/pkgs/data/json-schema/lib.nix
blob: 599c58c40fce91fd1a9ec342738a53a50326b790 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
{
  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}";
          pname = "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;
        };
        passthru = {
          inherit groups;
        };
        nativeBuildInputs = [
          jq
          json-schema-catalog-rs
        ];
        __structuredAttrs = true;
      }
      // 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.
        printf "%s" "$catalogJson" | jq . >"$out_file"

        json-schema-catalog check "$out_file"
      '';
    in
    package;
in
{
  lib =
    # Exported as part of `pkgs.jsonSchemaCatalogs`
    {
      inherit newCatalog;
    };
}