feat(npm): dist-tags packument generation (S11 Step 25, part 1/3)

📦 What this MR does

First of three stacked MRs delivering the S11 npm packument generator (Step 25) — a pure-function library that turns already-fetched npm_versions / npm_tags rows into the packument blobs, with no HTTP or database I/O. This part ships the dist-tags (kind=1) slice:

  • PackumentInput / Document — the shared input and the rendered-blob (bytes + SHA-256) types.
  • resolveDistTags — resolves each npm_tags row's NpmVersionID to its version string, drops tags that resolve to no supplied version, and synthesizes nothing (a missing latest row yields no latest entry, per AC 14 / AC 15).
  • GenerateDistTags — the kind=1 public entry (the bare {tag: version} map as a deterministic Document), consumed by the dist-tags GET handler (Step 10) and the cache rebuild (Step 12).

✂️ Split change

This is a split change. Step 25 is delivered as three stacked MRs for reviewability; the full and abbreviated kinds build on this dist-tags slice:

🧪 Tests

Unit suite (packument_test.go): dist-tags map resolution, the dangling-tag skip branch, no-latest synthesis (AC 14), latest omitted after the latest-holding version is unpublished (AC 15), the empty-tags case, and tag-order-independent determinism.

Related to #143 (closed)

Edited by David Fernandez

Merge request reports

Loading
Loading