| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
A version-gated npm registry bridge that lets package managers install pkg.pr.new Vite+ preview builds using normal npm registry semantics. Runs as a single Cloudflare Worker.
Live: https://registry-bridge.viteplus.dev
The package name selects the upstream package; the version pattern selects the source:
@voidzero-dev/vite-plus-core@0.0.0-commit.a832a55 -> pkg.pr.new commit build vite-plus@0.0.0-commit.a832a55 -> pkg.pr.new commit build vite-plus@0.2.1, react@latest -> npm registry
Only immutable commit builds (0.0.0-commit.<sha>) are supported. PR-number versions (0.0.0-pr.<n>) are intentionally rejected: a PR ref is mutable (it advances to newer commits), so its generated metadata/tarball would be overwritten and could mismatch what a consumer already pinned in a lockfile. Pinning a commit sha keeps the content immutable.
This makes a Bun alias override work through the bridge:
{
"overrides": {
"vite": "npm:@voidzero-dev/vite-plus-core@0.0.0-commit.a832a55"
}
}See rfcs/0001-pkg-pr-new-registry-bridge-cloudflare-workers.md for the full design, and examples/bun-validation for a runnable example.
To run preview builds for a different project, fork and reconfigure: the upstream repo, package allowlist, and origin are all configuration. See docs/self-hosting.md.
npm caps a package's packument (the metadata document listing every version) at 100 MB uncompressed, and clients download it in full on every fresh install. A build per commit consumes that budget: Drizzle ORM hit the cap after roughly 763 releases, and the registry then blocked new publishes for about a month (vlt.io on packument size limits). The bridge keeps per-commit previews out of npm's packument. It serves them from a separate registry as synthetic versions over a bounded, TTL-pruned ref set, so the real packument stays small and previews install with normal npm semantics.
Only @voidzero-dev/vite-plus-core and vite-plus receive synthetic preview versions (strict allowlist). Owner/repo are fixed to voidzero-dev/vite-plus.
bunfig.toml:
[install]
registry = "https://registry-bridge.viteplus.dev/"
# REQUIRED for large installs. Bun's default network concurrency (48) triggers
# an HTTP/2 client bug against Cloudflare on big dependency graphs (vite-plus
# pulls 400+ packages): streams get dropped and resolution fails with "no
# version matching". Capping concurrency avoids it. The bridge serves correct
# responses; this is a bun-side workaround.
networkConcurrency = 8package.json (prefer an immutable commit build for reproducibility):
{
"devDependencies": {
"vite": "npm:@voidzero-dev/vite-plus-core@0.0.0-commit.<sha>",
"@voidzero-dev/vite-plus-core": "0.0.0-commit.<sha>",
"vite-plus": "0.0.0-commit.<sha>"
},
"overrides": {
"vite": "npm:@voidzero-dev/vite-plus-core@0.0.0-commit.<sha>"
}
}Note on registry env overrides: bun honours npm_config_registry (which pnpm/npm derive from e.g. PNPM_CONFIG_REGISTRY) over bunfig.toml. If you run bun install through another package manager's script and have a registry mirror configured, unset that override or run bun directly so the bridge registry is used.
A package manager fetches the packument (GET /vite-plus) to discover which versions exist before it resolves a version, and the request carries no desired-version hint. So the bridge has to know which synthetic preview versions to list in that packument. pkg.pr.new has no API to enumerate its builds as semver versions, so the set is maintained explicitly.
The tarball endpoint, by contrast, accepts any valid preview version without configuration; only packument-based discovery needs the list.
Refs are registered at runtime via the admin endpoints below (the publish action calls them from CI), stored in a single R2 index object read with a cheap get (not a rate-limited KV list) and pruned by a TTL. No redeploy and no static configuration: a published preview appears as soon as the action registers it.
For refs published from a PR (the action forwards the PR url), the served packument also exposes a pr-<n> dist-tag pointing at that PR's latest-published commit version. The per-commit versions stay immutable; the tag moves as the PR advances, so npm/pnpm install <pkg>@pr-<n> against this registry installs the PR's head build.
A pkg.pr.new-style URL resolves a ref to a tarball, handy for a curl download or a single self-contained package. Swap the hostname on any pkg.pr.new URL:
# The repo's main package (vite-plus) at a PR's latest commit, or a commit sha:
curl -L https://registry-bridge.viteplus.dev/voidzero-dev/vite-plus@1891
curl -L https://registry-bridge.viteplus.dev/voidzero-dev/vite-plus@<sha>
# A specific (here scoped) package:
curl -L https://registry-bridge.viteplus.dev/voidzero-dev/vite-plus/@voidzero-dev/vite-plus-core@1891A GET 302-redirects to the canonical /tarballs/<pkg>/<version>.tgz. A HEAD answers 200 (no body) and resolves the ref to its exact commit via pkg.pr.new-style headers, so a tool can pin a (mutable) PR number to a commit without downloading:
curl -I https://registry-bridge.viteplus.dev/voidzero-dev/vite-plus@1891
# HTTP/2 200
# x-commit-key: voidzero-dev:vite-plus:<sha>
# x-pkg-name-key: vite-plusBoth GET and HEAD carry x-commit-key/x-pkg-name-key. Note a published preview tarball's transitive deps are pinned to versions (not pkg.pr.new URLs), so for a full install of the meta-package with its platform binaries, use the registry + pr-<n> tag above rather than this URL as a bare dependency.
Writes are guarded by Authorization: Bearer <ADMIN_TOKEN> (set ADMIN_TOKEN with void secret put ADMIN_TOKEN); without it configured the write endpoints return 503. GET /-/refs is a public read.
The three publish endpoints (tarball upload, /-/publish, /-/register) also accept a GitHub Actions OIDC token, so CI can publish without holding a bridge secret and fork pull requests can publish at all. /-/purge stays admin-token only: an OIDC identity can add preview builds and nothing else. See docs/ci-setup.md for the vars and the workflow split.
# List registered refs - no auth required.
# Each entry: { ref, version, publishedAt, prUrl, expiresAt }. publishedAt is the
# server-stamped release date; prUrl is null unless published from a PR; expiresAt
# is the index TTL (90 days out).
curl https://.../-/refs
# Purge a generated build (its tarball + meta) from R2
curl -X POST -H "authorization: Bearer $ADMIN_TOKEN" -H 'content-type: application/json' \
-d '{"package":"vite-plus","version":"0.0.0-commit.a832a55"}' https://.../-/purgeRefs are created by publishing: tarball upload (PUT /-/tarball/<pkg>/<version>.tgz) then POST /-/publish (stores metadata + registers the ref), both guarded and driven by the publish action, not by hand.
A published ref is reflected immediately and built into the packument on the next request. This is the no-redeploy path for exposing new preview builds.
The heavy work (pack, rewrite, re-pack, hash) runs in CI via a reusable action, in the same job that built the artifacts, so the Worker only serves and pkg.pr.new is not involved. Wire it into vite-plus's publish workflow: see docs/ci-setup.md. To publish by hand (same code path), run PKG_PR_BRIDGE_ADMIN_TOKEN=… pnpm warm --repo <built-vite-plus-checkout> <sha>.
The action's bundle is committed (.github/actions/publish-preview/dist/index.mjs); rebuild it with pnpm build:action after changing the action or any module it imports.
Non-secret values are declared in env.ts (typed and validated) and set in .env (committed), with per-environment overrides in .env.production. Secrets are uploaded with void secret put:
| Var | Meaning |
|---|---|
| PUBLIC_BASE_URL | Public origin of the bridge; used in dist.tarball URLs. Must match the deployed route. |
| NPM_REGISTRY | npm fallback registry (https://registry.npmjs.org). |
| PREVIEW_OWNER / PREVIEW_REPO | Fixed upstream repo (voidzero-dev / vite-plus). |
| WORKSPACE_PACKAGES | Allowlist for the tarball endpoint. Exact names or prefix*, e.g. vite-plus,@voidzero-dev/vite-plus-*. |
Bindings/secrets:
This is a Void app: voidPlugin() in vite.config.ts builds the Worker from the routes/ layer, which forwards every request to the Hono registry app in src/app.ts. Void infers the STORAGE R2 binding and loads .env* into the Worker's vars.
vp install # also runs `void prepare` (generates .void/ types)
vp check # format + lint + type-check (oxfmt, oxlint, tsgolint)
vp test # vitest, runs the worker in workerd (Miniflare)
vp dev # local worker via Miniflare, http://localhost:5173For local admin testing, put ADMIN_TOKEN=… in .env.local (gitignored).
Deploys to the Void managed platform with void deploy; Void provisions the Worker and the STORAGE R2 bucket (no Cloudflare account needed). To run an independent bridge for another project (fork, configure, deploy, wire CI), follow docs/self-hosting.md.
# One-time: authenticate and set the admin secret on the project.
void auth login
void secret put ADMIN_TOKEN # guards the admin write endpoints
# Deploy and run the end-to-end bun install check.
# Use `pnpm run deploy` (not `pnpm deploy`, which is pnpm's built-in command).
pnpm run deploy # void deploy + e2epnpm run deploy runs void deploy, then pnpm test:e2e (a real bun install against the live bridge that asserts the alias/override resolves to the synthetic version, using a ref the bridge already serves). Use pnpm run deploy:only for void deploy alone.
The public origin (PUBLIC_BASE_URL in .env.production) is the custom domain https://registry-bridge.viteplus.dev, attached with void domain add (the underlying Void platform URL pkg-pr-registry-bridge.void.app keeps working too).
CI deploys in two stages, both smoke-testing the REAL Void runtime, which the pool-workers unit tests can't emulate (e.g. the platform forbidding caches.default, which 500'd every packument while all unit tests passed):
The smoke test hits /_health, the /vite-plus packument (200 with time), /-/refs, and a download redirect.
The push-to-main workflow authenticates with GitHub OIDC: void deploy exchanges a short-lived OIDC token for a project-scoped deploy token, so no secret is involved. This requires the repo to be connected once per project (void github connect <project> --repo voidzero-dev/pkg-pr-registry-bridge --branch main --executor github_actions) and the workflow file to be named exactly void-deploy.yml. The PR staging deploy still needs a VOID_TOKEN repository secret (void auth token copies one to your clipboard): the platform refuses to mint deploy tokens for pull_request events, which run untrusted code. Run the smoke test locally with pnpm smoke <url>, and deploy staging by hand with pnpm deploy:staging.
| Back | FazBrowse Home | New Git URL |