Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow getting the original TileJSON #2965

Open
jleedev opened this issue Aug 9, 2023 · 6 comments
Open

Allow getting the original TileJSON #2965

jleedev opened this issue Aug 9, 2023 · 6 comments
Labels
need more info Further information is requested

Comments

@jleedev
Copy link
Contributor

jleedev commented Aug 9, 2023

User Story

As a map developer, I can access the TileJSON data from the source's URL, so that I can use all the metadata.

Rationale

The specification says so:

implementations MUST expose unknown key value pairs so users can optionally handle these keys.

Apart from that, there are a variety of reasons this is useful, many sources include the replication timestamp of the source material, tippecanoe includes the command line arguments and statistical information, and so on. A control could look for a particular key value pair and put the planet date in the corner of the map. And so on.

It appears that the current implementation copies the fields it likes out of the TileJSON and discards the rest. It would probably make sense to save the raw TileJSON object for later retrieval, rather than trying to extend this logic to avoid clobbering the Source object with arbitrary keys.

Impact

As a workaround, a developer could fetch the TileJSON separately from the tile source doing so, which might be inefficient and less generalizable.

@1ec5
Copy link
Contributor

1ec5 commented Aug 9, 2023

(This issue has also been reported as mapbox/mapbox-gl-js#5471.)

@HarelM
Copy link
Collaborator

HarelM commented Aug 10, 2023

I generally think the workaround is OK if this is what you need, but I'm open to hear what other options can solve this in maplibre (i.e. a design) from your perspective.

@HarelM HarelM added the need more info Further information is requested label Aug 10, 2023
@jleedev
Copy link
Contributor Author

jleedev commented Aug 10, 2023

The workaround is limited in utility. Some examples:

  • The PMTiles protocol finds the tileJSON in its own way and passes it to the callback, so hooking into that would be the only way to access that object. Rather, the custom code to acquire the tileJSON would have to know that it's going through the special PMTiles protocol, or else fetch the object and add the source to the map by value rather than by URL.

  • A map control that adds the planet time may be written in a generic way over the several well-known values for this, e.g.

    onAdd(map) {
      map.on("sourcedata", e => {
        const {metadata} = e.getSource();
        if (metadata["planetiler:osm:osmosisreplicationtime"]) {
          this.setText(new Date(metadata["planetiler:osm:osmosisreplicationtime"]).toLocaleDateString();
        } else if (metadata["planettime"]) {
          this.setText(new Date(+metadata["planettime"]).toLocaleDateString();
        }
      });
    }

    Being able to do this in any sort of reusable way would necessarily require either knowledge of where the source is coming from, again given the PMTiles custom protocol example, or to fetch the tileJSON separately and install it as the source object rather than the URL, both of which really don't lend themselves to this being a reusable control.

    This would allow the control to contain knowledge of what the different sources are shaped like (specifically Planetiler vs Maptiler) without also containing knowledge of how the particular map fetches its source.

  • This somewhat precludes a style json referencing a tile source by URL, which should be the most common way, without, again, additional introspection.

@1ec5
Copy link
Contributor

1ec5 commented Aug 11, 2023

This behavior dates to 43df2ac. Unfortunately there doesn’t seem to be any public discussion as to why this commit switched from including all the TileJSON properties to only including a few that GL JS used directly.

As far as an API design, the TileJSON specification doesn’t say exactly how to expose the unrecognized properties; it only requires that they be exposed somehow. Since MapLibre now uses TypeScript, I suppose the freeform approach of just dumping these properties into the source object would be problematic. But perhaps loadTileJson could set a metadata property to an object that contains all the unrecognized TileJSON properties. The name “metadata” would be consistent with the style specification, which reserves a metadata property at the root and in layer objects but not in source objects.

@jleedev
Copy link
Contributor Author

jleedev commented Aug 19, 2023

contains all the unrecognized TileJSON properties

That feels like it would be unnecessarily brittle? This object contains all the properties we don't support, until maybe one day whoops, we decide that "name" or "center" is interesting enough and it moves elsewhere.

@1ec5
Copy link
Contributor

1ec5 commented Aug 19, 2023

I was just thinking about how to keep the StyleSpecification type strongly typed. If this project decides, for example, that center is interesting, it’ll probably be represented by something other than an array. It looks like this problem has already been solved elsewhere in the API: Map.queryRenderedFeatures returns MapGeoJSONFeature, a type alias for a rather convoluted type that uses DistributiveOmit to omit certain keys from the type definition that need to be represented by something other than the raw JSON.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
need more info Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants