Skip to content

馃 Feature Request: Support JSON Schema Compound Schema Documents聽#2164

Description

@ya7010

Preflight

  • I have searched existing Issues and Discussions for related requests.
  • This is not only a request to add a JSON Schema for a third-party project. For that case, I will ask the target project and SchemaStore instead.

Problem

Tombi does not currently resolve an embedded schema resource by its canonical $id within a JSON Schema Compound Schema Document.

Shoko uses two different resource identifiers for a package:

  • shoko://<namespace>/<name> is a versionless dependency alias generated from a lockfile.
  • shoko://<namespace>/<name>/versions/<version>/schema.json is the immutable canonical $id of a published schema.

When a Compound Schema Document contains both resources, Tombi should resolve the versionless alias to the locked, versioned embedded resource. It currently attempts to load a shoko:// reference as an external document instead.

This prevents standards-based, offline distribution of resolved schema dependency graphs. A direct JSON Pointer such as #/$defs/dependency works, but it couples references to the generated bundle layout instead of preserving each resource's canonical identity.

Proposal

Implement JSON Schema resource indexing and reference resolution for Compound Schema Documents, following Draft 2020-12 URI and scope semantics.

Minimal version-resolved example:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$ref": "shoko://python/pyproject",
  "$defs": {
    "python-pyproject-alias": {
      "$id": "shoko://python/pyproject",
      "$ref": "shoko://python/pyproject/versions/1.0.0/schema.json"
    },
    "python-pyproject-1.0.0": {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "$id": "shoko://python/pyproject/versions/1.0.0/schema.json",
      "type": "object",
      "properties": {
        "tool": {
          "type": "object",
          "properties": {
            "tombi": {
              "$ref": "shoko://tombi-toml/tombi"
            }
          },
          "required": ["tombi"]
        }
      },
      "required": ["tool"]
    },
    "tombi-alias": {
      "$id": "shoko://tombi-toml/tombi",
      "$ref": "shoko://tombi-toml/tombi/versions/1.2.3/schema.json"
    },
    "tombi-1.2.3": {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "$id": "shoko://tombi-toml/tombi/versions/1.2.3/schema.json",
      "type": "object",
      "properties": {
        "strict": {
          "type": "boolean",
          "description": "Enable strict validation."
        }
      },
      "required": ["strict"],
      "additionalProperties": false
    }
  }
}

For this TOML:

[tool.tombi]
strict = 42

Tombi should resolve this chain entirely inside the loaded document:

shoko://python/pyproject
  -> shoko://python/pyproject/versions/1.0.0/schema.json
    -> shoko://tombi-toml/tombi
      -> shoko://tombi-toml/tombi/versions/1.2.3/schema.json

It should report that strict must be a boolean without performing any external shoko:// fetch. No Shoko-specific URI handler should be required: these URIs are opaque canonical identifiers once their resources are present in the loaded Compound Schema Document.

Required behavior

  • Discover schema resources introduced by non-fragment $id values throughout a loaded schema document.
  • Resolve each resource's canonical URI against the correct enclosing base URI.
  • Consult the loaded document's embedded-resource index before attempting an external fetch.
  • Maintain independent dialect, base URI, and anchor scopes for each embedded resource.
  • Support nested embedded resources and references between sibling or transitive embedded resources.
  • Resolve $anchor, $dynamicAnchor, $ref, and $dynamicRef using their correct resource and dynamic scopes.
  • Reject duplicate canonical resource URIs deterministically instead of silently choosing one.
  • Use the same resolution model for validation, completion, hover, go-to-definition, and document links.
  • Preserve normal external file, http, and https resolution when a referenced resource is not embedded.
  • Work offline when every referenced resource is present in the Compound Schema Document.

Acceptance criteria

  • The example above reports that tool.tombi.strict = 42 is not a boolean.
  • No fetcher is called for either the versionless or versioned embedded shoko:// resources.
  • Validation, completion, hover, go-to-definition, and document links have regression tests using an embedded resource.
  • Tests cover:
    • absolute and relative $id;
    • versionless alias resources pointing to immutable versioned resources;
    • sibling and nested embedded resources;
    • references from an embedded resource back to another resource;
    • mixed dialect resources with an explicit $schema;
    • $anchor and $dynamicRef/$dynamicAnchor scope;
    • duplicate canonical resource IDs;
    • offline operation;
    • fallback to an external resource when no embedded resource matches.
  • Existing direct JSON Pointer references such as #/$defs/name continue to work.

Alternatives

Shoko could rewrite every dependency reference to a generated #/$defs/... JSON Pointer or introduce a resolver-specific file format. That would work with Tombi today, but it would create a non-standard coupling between schema identity and generated bundle layout. Supporting Compound Schema Documents keeps the resolved artifact entirely within JSON Schema semantics.

Additional context

  • JSON Schema 2020-12 guidance: Bundling
  • JSON Schema 2020-12 Core specification: Schema Resources
  • VS Code's JSON language service added embedded-resource indexing in microsoft/vscode-json-languageservice@24c3800.
  • Verified compatibility boundary from the Shoko investigation:
    • VS Code JSON / vscode-json-languageservice >= 6.0.0-next.2: supported.
    • yaml-language-server >= 1.23.0: supported.
    • The corrected versionless-alias-to-versioned-resource example was tested successfully with vscode-json-languageservice 6.0.0-next.3 and yaml-language-server 1.24.0.
    • Tombi currently resolves #/$defs/... but not an absolute $id for an embedded resource.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions