Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Metadata Minifier Laravel Package

composer/metadata-minifier

A small PHP utility that minifies and expands Composer package version metadata using version diffs, powering Composer 2.x's repository metadata protocol. Requires PHP 5.3.2+, MIT licensed.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer; this is a plain PHP library with no service provider or Laravel integration surface:

composer require composer/metadata-minifier

Everything you need lives on one class, Composer\MetadataMinifier\MetadataMinifier, with two static methods:

  • MetadataMinifier::minify(array $versions) — takes a normal array of version arrays and returns a minified array where the first entry is full and subsequent entries are diffs.
  • MetadataMinifier::expand(array $versions) — reverses the above back to full version arrays.

The fastest first use case is expanding Packagist's Composer 2 metadata, which is served pre-minified. Read the README example as your starting point:

$packageName = 'monolog/monolog';
$url = "https://repo.packagist.org/p2/{$packageName}~dev.json";
$json = json_decode(file_get_contents($url), true);
$versions = \Composer\MetadataMinifier\MetadataMinifier::expand($json['packages'][$packageName]);

If you only need to consume package metadata, this is the whole story: the minified wire format is [fullVersion, diff, diff, ...] where each diff holds only keys that changed, and deletions are marked with the literal string '__unset'.

Implementation Patterns

Read path — expanding a package's available versions. This is the canonical use. Fetch https://repo.packagist.org/p2/{name}.json for tagged releases, and ...~dev.json for dev branches; expand() each packages[name] array and merge if you need the full picture. Handy for building internal dependency dashboards, "what versions are available" UI, or upgrade-suggestion tooling.

Write path — producing Composer 2 repository metadata. If you serve your own package mirror or a private package index consumed by Composer 2, you must emit the minified format. Take your array of full version arrays ordered oldest-to-newest (or however Composer's resolver expects), pass it through MetadataMinifier::minify(), and write it out. Composer 2 clients will call expand() on their side.

Round-trip invariant as a test contract. When generating fixtures for a private repo or integration test, assert expand(minify($versions)) === $versions. This catches ordering bugs, missing __unset handling, and accidental key mutations that would otherwise only surface when Composer tries to install a package.

Caching expanded metadata. expand() runs in PHP, is allocation-cheap, and is synchronous — but the network fetch is not. Cache the raw minified JSON (it's smaller) in your cache layer and expand on read. That keeps cache entries compact and lets expand() do the lightweight transform per request.

Wrapping in an Artisan command. The package has no facade or config, but wrapping it is trivial. A useful pattern: an Artisan command that fetches, expands, and prints diffs (version, dist URL, requires) for a given package, useful for debugging "why is Composer picking version X." A second command that takes a local array of version arrays, minifies, and writes to storage/app/ — useful when building test repos.

Dev-branch handling. Remember ~dev is a separate endpoint and a separate package key (name vs. name with a -dev-derived branch set). Loop over both URLs, expand, and concatenate before sorting.

Gotchas and Tips

This is not a composer.lock minifier. The README, the class name, and the source are unambiguous: the only two operations are over version arrays from Composer 2 repository metadata. There is no CLI binary, no --preserve flag, no config file, and it does not touch composer.json or composer.lock. If you saw writeups claiming otherwise, verify against the actual composer/metadata-minifier source before wiring anything into CI — you'll otherwise build workflows around flags that don't exist.

Only Composer 2 has minified metadata. Composer 1.x used a flat, unminified packages.json per package and doesn't serve this format at all. If your tooling talks to both, gate the minify/expand logic on protocol version rather than attempting to run the transform on Composer 1 payloads.

The first element is always full. expand() relies on $versions[0] representing the complete, unprefixed state. If your input array is somehow reordered or filtered before minify, subsequent deltas will be relative to the wrong base. Sort deterministically (Composer emits newest-first) before minifying.

__unset is a string, not a null. Deletions in the minified diff are encoded as the literal sentinel '__unset'. If you post-process the JSON (e.g., array_filter, PHP-side merging), be careful not to strip these before calling expand() — you'll resurrect keys the original array had removed.

Nested arrays are diffed wholesale. minify() compares top-level keys; nested structures like require, autoload, or extra are replaced as a whole unit, not recursively diffed. That's fine for the Composer 2 protocol but means you shouldn't assume minimal diffs inside large nested blocks.

Always fetch the ~dev variant. https://repo.packagist.org/p2/monolog/monolog.json does not include dev branches. If you build a "list available versions" screen and it's missing dev versions, this is why.

No framework coupling means no auto-discovery surprises. There's no service provider, no config publishing, no facade. Call MetadataMinifier statically; it's safe to use inside jobs, Artisan commands, and service classes without container wiring.

Version drift is low-risk. The public API is two static methods, the package is tiny, and the wire format is dictated by Composer itself. Pin it in composer.json for reproducibility, but expect zero maintenance across minor upgrades. If a future Composer protocol change lands, it will arrive as a major bump — track the GitHub releases page rather than the README, which is minimal.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core