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

@edv4h/spire-gen

v0.2.0

Published

Deterministic lane-based DAG map generation for Spire

Readme

@edv4h/spire-gen

決定的なマップ生成。同じ GenSpec + シードなら常に同じ MapDocument になる。

GenSpec ─▶ ① skeleton  グリッド + ウォークで DAG 骨格(StS 型)
        ─▶ ② assign    制約充足でノードタイプ割当
        ─▶ ③ populate  ContentProvider で node.data に注入(任意)
        ─▶ ④ validate  位相不変条件 + GenSpec 制約の最終検証
        ─▶ MapDocument

各段は個別にも公開している(buildSkeleton / assignTypes)。

GenSpec は純粋な JSON

振る舞いはすべて登録済み ID で参照する。関数はどこにも入らないので、spec はそのまま保存・共有・再生できる。

{
  "seed": 42,
  "skeleton": { "algorithm": "sts-walks", "grid": { "cols": 5, "rows": 12 }, "walks": 4, "minStarts": 2 },
  "types": {
    "assigner": "rejection",
    "distribution": { "step": 0.7, "gate": 0.2, "bonus": 0.1 },
    "constraints": [{ "rule": "fixedRow", "row": -1, "type": "final" }]
  },
  "populate": null
}

組み込みの制約ルール

| id | 意味 | |---|---| | fixedRow | その行はその型、かつその型はその行だけ(row: -1 は終端行) | | minRow | その型は指定行以降にのみ現れる | | noAdjacentSame | 指定型は隣接ノード同士で連続しない | | branchDistinct | 同じ親からの分岐先は異なる型(exempt で除外可) | | maxPerRow | 1行あたりの同型上限 |

追加のルール・骨格アルゴリズム・割当戦略・コンテンツプロバイダはプラグインで登録する。

始端と終端の数

既定は入口1つ・ゴール1つ。 何も書かなければ目標マップの形になる。

| | 既定 | 意味 | |---|---|---| | minStarts | 1 | row 0 の入口の最小数 | | maxStarts | (省略) | 省略すると minStarts に固定。数値で範囲、null で上限なし | | maxEnds | 1 | 終端行のノードの最大数。null で上限なし |

// 既定のまま — 入口1つ、ゴール1つ
"skeleton": { "grid": { "cols": 5, "rows": 12 }, "walks": 6 }

// 入口3つ、終端は絞らない
"skeleton": { "grid": { "cols": 5, "rows": 12 }, "walks": 6,
              "minStarts": 3, "maxEnds": null }

maxStarts を省略したときに上限なしではなく minStarts 固定にしているのは、 下限だけ指定する意図はたいてい「この数だけ」だから。上限を外したいときは null を明示する。

maxEnds は「1歩で1列しか動けない」性質を使い、終端に近づくほどウォークが居られる列を 狭めることで実現している。全ウォークが同じ区間に制約されるので左右の順序が入れ替わらず、 絞り込みが交差を生むことがない。

停止性

割当は rejection sampling で、試行上限(既定 1000)と早期打ち切り(同一ノードが同一理由で25回連続ブロック)を持つ。矛盾する GenSpec は無限に回らず、どのノードがどのルールに阻まれたかを含むエラーで返る。

マップの編集

| | | |---|---| | insertNode(map, { type, row, col? }) | 空きセルにノードを追加する。骨格生成が walks < cols で列に空きを残しているのはこのため。不変条件を壊さずに繋げられなければ no_space を返し、勝手に壊れたマップを返さない | | regenerate(map, spec, { keepCompleted }) | 未完了ノードのタイプを再割当する。構造は据え置き。完了済みノードは type と data を保持したまま固定され、新しい spec の制約に反する場合は map.meta.regenerateWarnings で報告する(エラーにはしない) |