npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tileset-scope-versioner

v0.1.2

Published

Content-addressed, scope-local cache versions for external 3D Tiles trees.

Readme

tileset-scope-versioner

npm

Content-addressed, scope-local cache versions for external 3D Tiles trees.

A single deployment-wide cache token is easy to implement, but changing one small external tileset then invalidates every model and texture. This package discovers local external tilesets, treats their directories as independent version scopes, and hashes each scope without folding nested scopes into the parent. One changed region can therefore receive one new token.

The implementation has no renderer, web framework, cloud provider, or application schema dependency.

Install

npm install tileset-scope-versioner

Node.js 22 or newer is required. The package is ESM-only, includes TypeScript declarations, and has no runtime dependencies.

What it produces

Given this tree:

tileset.json
north/tileset.json
north/model.glb
south/tileset.json
south/model.glb

the sidecar contains a default root version and separate north/ and south/ versions:

{
  "schemaVersion": 1,
  "algorithm": "sha256-128",
  "generatedAt": "2026-07-27T00:00:00.000Z",
  "defaultVersion": "ca64d7e9fddcc93d512147f42d1e0d53",
  "scopes": [
    {
      "id": "root",
      "prefix": "",
      "match": "prefix",
      "version": "ca64d7e9fddcc93d512147f42d1e0d53",
      "manifests": ["tileset.json"]
    },
    {
      "id": "external:north",
      "prefix": "north/",
      "match": "prefix",
      "version": "db18b48153d50e421df5afb76911fc29",
      "manifests": ["north/tileset.json"]
    },
    {
      "id": "external:south",
      "prefix": "south/",
      "match": "prefix",
      "version": "7f3c0a51b9e264d8a1c6e0f4b2d78a90",
      "manifests": ["south/tileset.json"]
    }
  ]
}

Editing south/model.glb rotates only the south/ version; the root and north/ tokens are unchanged. Tokens in this example are illustrative.

A runnable version of this tree ships in the package under examples/scoped-tileset. From a repository clone, run:

node examples/scoped-tileset/demo.mjs

It edits one external tileset in a temporary copy and prints which scopes changed. See examples/scoped-tileset for the full walkthrough.

CLI

tileset-scope-version --root ./public/tiles

This writes:

  • asset-versions.json, the client-facing sidecar;
  • .scoped-version-state.json, the previous fingerprint state.

Useful options:

# Preview only
tileset-scope-version --root ./public/tiles --dry-run

# Also set the standard field in every discovered manifest
tileset-scope-version --root ./public/tiles --write-standard

# Version shared assets independently
tileset-scope-version \
  --root ./public/tiles \
  --scope shared-textures=shared/textures

# Print the installed package version
tileset-scope-version --version

Generated asset.tilesetVersion values are removed before hashing, so writing them does not create a self-invalidating loop. Output files and .DS_Store files are excluded as well. Local references that escape the asset root and symbolic links inside a scope are rejected.

Library API

import {
  appendScopedVersion,
  publishScopedVersions
} from "tileset-scope-versioner";

const { versionMap, changedScopes } = await publishScopedVersions({
  root: "./public/tiles",
  writeStandard: true,
  additionalScopes: [
    { id: "shared-textures", path: "shared/textures" }
  ]
});

const url = appendScopedVersion(
  "north/model.glb?quality=high",
  versionMap
);

For absolute asset URLs, pass the public asset base:

appendScopedVersion(assetUrl, versionMap, {
  baseUrl: "https://cdn.example.test/tiles/"
});

baseUrl must be an absolute HTTP(S) directory URL ending in /. The URL helper uses the longest matching prefix, and a file scope uses exact matching. It leaves non-HTTP URLs, relative paths that escape the implicit root, and URLs outside baseUrl unchanged. Protocol-relative HTTP(S) inputs remain protocol-relative. Malformed maps, duplicate selectors, URL percent-encoding, and encoded path separators are rejected instead of being interpreted permissively.

See the API reference for all discovery, version-map, publish, and URL helper options and return types.

Boundaries

  • Local .json content references are treated as external tilesets.
  • Network, data, and root-absolute references are not fetched or rewritten.
  • Versions are deterministic SHA-256 prefixes, not release counters.
  • Directory scopes are a deployment policy layered on standard tileset structure; the sidecar format itself is package-specific.
  • State and sidecar paths must be distinct files and cannot overlap a discovered manifest. Generated output used as a file scope is also rejected.
  • Existing symbolic links in an output path are rejected, including links in parent directories.
  • Each file replacement is atomic, but a publication that changes several manifests and sidecars is not a filesystem transaction. A process or storage failure can leave a subset updated; publish through a staged asset directory when all-or-nothing replacement is required.
  • The sidecar schema and CLI may change during the 0.x series.

Use --dry-run and review changedScopes before adding the command to a deployment. Back up manifests when first enabling --write-standard.

Standards context

This package implements cache-versioning behavior around the OGC 3D Tiles 1.1 Community Standard, notably local content.uri references and the optional asset.tilesetVersion field. 3D Tiles was created by Cesium and adopted by the Open Geospatial Consortium.

No OGC specification text, schema, Cesium source code, or third-party runtime is included. This is an independent implementation, is not affiliated with or endorsed by OGC or Cesium, and does not claim conformance certification.

Development

npm ci
npm run check

See CONTRIBUTING.md for filesystem test expectations and SECURITY.md for private reporting.

License

The package source is available under the MIT license. Tilesets and other assets processed by the package remain subject to their own licenses.