Home
Pages

src/cli/commands/bootstrap

declarative-hex-worlds

declarative-hex-worlds


declarative-hex-worlds / src/cli/commands/bootstrap

src/cli/commands/bootstrap

src/cli/commands/bootstrap/ — the bootstrap CLI command + its runtime asset-bootstrap implementation.

Remarks

Bootstrap is a CLI-domain capability (reachable only from src/cli/), not a runtime-library domain — the umbrella does not re-export it. The published npm tarball does NOT ship KayKit GLTF binaries; consumers run the CLI bootstrap subcommand (or call bootstrapKayKitAssets directly via the ./bootstrap subpath) after install to materialize the asset tree under their app's asset root. Two source modes are supported:

  • { kind: 'github' } — downloads the upstream GitHub tarball via https (CC0 FREE edition only).
  • { kind: 'zip', path } — extracts a user-supplied zip on disk (works for both FREE and the EXTRA edition purchased on itch.io).

Both modes mirror only the .gltf + .bin + texture files (unless includeSourceFormats is set), preserving the upstream Assets/gltf/ directory structure under <out>/addons/kaykit_medieval_hexagon_pack/Assets/gltf/. A .bootstrap.json integrity sidecar is written alongside, recording per-file SHA-256 hashes plus provenance. verifyBootstrap re-hashes a bootstrapped tree and reports drift.

Interfaces

BootstrapFileEntry

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:154

Per-file entry in the integrity sidecar.

Properties

bytes

readonly bytes: number

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:160

Byte length of the file at fetch time.

path

readonly path: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:156

POSIX path relative to <out>/addons/kaykit_medieval_hexagon_pack/.

sha256

readonly sha256: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:158

SHA-256 hash of the file's contents, lowercase hex.


BootstrapKayKitAssetsOptions

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:95

Inputs to bootstrapKayKitAssets.

Properties

edition?

readonly optional edition?: "free" | "extra"

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:104

Pack edition (default free). extra requires source.kind === 'zip'.

fetchedAt?

readonly optional fetchedAt?: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:125

Reproducible timestamp written into the integrity sidecar. Default new Date().toISOString().

force?

readonly optional force?: boolean

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:110

When true, the destination is wiped before mirroring. When false (default), an existing non-empty target throws unless its sidecar matches the requested edition.

githubSource?

readonly optional githubSource?: object

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:143

GitHub archive source for the pack (RFC0-10). Defaults to the KayKit Medieval Hexagon repo. Pass a pack descriptor's github to fetch a different pack's archive. Only used when source.kind === 'github'.

archiveUrlTemplate

readonly archiveUrlTemplate: string

defaultRef

readonly defaultRef: string

owner

readonly owner: string

repo

readonly repo: string

includeSourceFormats?

readonly optional includeSourceFormats?: boolean

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:115

Include .fbx, .fbx(unity), .obj, .mtl files. Default false — only .gltf, .bin, and PNG textures are mirrored.

layout?

readonly optional layout?: KayKitUpstreamLayout

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:137

Target upstream layout (RFC0-10). Defaults to the edition-derived KayKit Medieval Hexagon layout. Pass a characterPackLayout(...) to bootstrap a character pack (Adventurers/Skeletons) instead. When set, detection and mirroring use THIS layout rather than the medieval-hexagon detection list.

libraryVersion?

readonly optional libraryVersion?: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:130

Override for the integrity sidecar's libraryVersion field. Defaults to the value resolved from the closest package.json.

out

readonly out: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:102

Consumer's asset root. The bootstrap step writes <out>/addons/kaykit_medieval_hexagon_pack/... under this folder.

outRoot?

readonly optional outRoot?: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:120

Optional jail root for out resolution. Defaults to process.cwd(). The bootstrap function refuses to write outside this root.

source

readonly source: BootstrapKayKitAssetsSource

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:97

Where to fetch the upstream source tree from.


BootstrapPackOptions

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:51

Options for bootstrapPack.

Properties

fetchedAt?

readonly optional fetchedAt?: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:65

Reproducible sidecar timestamp (tests).

force?

readonly optional force?: boolean

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:63

Overwrite an existing non-empty target.

libraryVersion?

readonly optional libraryVersion?: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:67

Sidecar library-version override (tests).

outRoot?

readonly optional outRoot?: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:59

Jail root for path resolution (defaults to cwd inside core).

rawAssetsRoot

readonly rawAssetsRoot: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:57

Gitignored raw-assets ROOT. The pack materializes into <rawAssetsRoot>/<packId>/ — the id subdir is appended internally so the write location always matches resolveDefaultPackKit/assertPackPresent.

ref?

readonly optional ref?: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:61

Git ref to fetch (defaults to the descriptor's default ref).


BootstrapResult

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:185

Return value of bootstrapKayKitAssets.

Properties

edition

readonly edition: "free" | "extra"

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:187

Pack edition that was bootstrapped.

fileCount

readonly fileCount: number

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:191

Total number of files written (gltf + bin + textures + any extras).

integritySidecar

readonly integritySidecar: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:195

Absolute path of the integrity sidecar.

outRoot

readonly outRoot: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:189

Absolute path of the bootstrap target root.

totalBytes

readonly totalBytes: number

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:193

Sum of BootstrapFileEntry.bytes.


BootstrapSidecar

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:167

Integrity sidecar serialized as .bootstrap.json inside each bootstrap target.

Properties

edition

readonly edition: "free" | "extra"

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:171

Pack edition this target was bootstrapped for.

fetchedAt

readonly fetchedAt: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:177

ISO-8601 timestamp at which the bootstrap was performed.

files

readonly files: readonly BootstrapFileEntry[]

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:179

Sorted list of every mirrored file plus its SHA-256.

libraryVersion

readonly libraryVersion: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:173

Library version that produced this bootstrap.

schemaVersion

readonly schemaVersion: "1.0.0"

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:169

Sidecar schema version.

sourceUrl

readonly sourceUrl: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:175

Provenance URL (https://...) or file:// URL for zip-sourced bootstraps.


BootstrapVerificationReport

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:201

Verification report returned by verifyBootstrap.

Properties

drift

readonly drift: readonly string[]

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:205

Human-readable descriptions of any drift discovered.

ok

readonly ok: boolean

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:203

True when every recorded file matches its expected hash and length.

sidecarPath

readonly sidecarPath: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:207

Sidecar that was checked.


PackResolution

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:104

A pack's default-resolution status against a raw-assets root.

Properties

dir

readonly dir: string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:108

Absolute directory the pack resolves to (whether or not it's present).

id

readonly id: "medieval-hexagon" | "adventurers" | "skeletons"

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:106

Pack id.

present

readonly present: boolean

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:110

True when the pack is materialized there.

Type Aliases

BootstrapKayKitAssetsSource

BootstrapKayKitAssetsSource = { commit?: string; kind: "github"; } | { kind: "zip"; path: string; }

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:78

Source descriptor for BootstrapKayKitAssetsOptions. Discriminates between fetching from the upstream GitHub repo and extracting a locally cached zip archive.

Union Members

Type Literal

{ commit?: string; kind: "github"; }

commit?

readonly optional commit?: string

Optional git ref (commit / tag / branch). Defaults to KAYKIT_FREE_GITHUB_DEFAULT_REF.

kind

readonly kind: "github"

Source kind discriminator selecting the upstream-GitHub tarball path.


Type Literal

{ kind: "zip"; path: string; }

kind

readonly kind: "zip"

Source kind discriminator selecting the local-zip extraction path.

path

readonly path: string

Filesystem path of the locally cached pack zip.


PackCategory

PackCategory = typeof PACK_CATEGORIES[number]

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:38

Gameplay category a pack fills.


PackDescriptor

PackDescriptor = z.infer<typeof packDescriptorSchema>

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:75

A downloadable-pack descriptor.


PackGithubSource

PackGithubSource = z.infer<typeof packGithubSourceSchema>

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:55

Upstream GitHub source descriptor.


PackId

PackId = typeof PACK_IDS[number]

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:25

One of the recognized downloadable pack ids.


PackRole

PackRole = typeof PACK_ROLES[number]

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:30

Asset role a pack contributes (tiles vs models).

Variables

KAYKIT_BOOTSTRAP_GLTF_RELATIVE

const KAYKIT_BOOTSTRAP_GLTF_RELATIVE: string = BOOTSTRAP_PATHS.gltfRelative

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/target.ts:14

Sub-folder under the consumer's asset root holding the mirrored GLTF tree. Empty string means GLTFs land directly in the asset root (flat layout).


KAYKIT_BOOTSTRAP_SIDECAR

const KAYKIT_BOOTSTRAP_SIDECAR: string = BOOTSTRAP_PATHS.sidecarFileName

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/target.ts:24

Filename of the integrity sidecar written into each bootstrap target.


KAYKIT_BOOTSTRAP_TEXTURE_RELATIVE

const KAYKIT_BOOTSTRAP_TEXTURE_RELATIVE: string = BOOTSTRAP_PATHS.textureRelative

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/target.ts:19

Sub-folder under the consumer's asset root holding mirrored shared textures.


KAYKIT_FREE_GITHUB_DEFAULT_REF

const KAYKIT_FREE_GITHUB_DEFAULT_REF: string = KAYKIT_SOURCE.github.defaultRef

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:71

Default git ref the bootstrap CLI fetches when no --commit is supplied.


KAYKIT_FREE_GITHUB_OWNER

const KAYKIT_FREE_GITHUB_OWNER: string = KAYKIT_SOURCE.github.owner

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:60

Canonical GitHub organization holding the FREE edition source tree.


KAYKIT_FREE_GITHUB_REPO

const KAYKIT_FREE_GITHUB_REPO: string = KAYKIT_SOURCE.github.repo

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:66

Canonical GitHub repository name for the FREE edition (the repo at KayKit-Game-Assets/KayKit-Medieval-Hexagon-Pack-1.0).


PACK_CATEGORIES

const PACK_CATEGORIES: readonly ["terrain", "playable", "enemy"]

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:36

Gameplay category a pack fills — drives default source composition (terrain board vs playable units vs enemies) so three packs compose into a full game.


PACK_IDS

const PACK_IDS: readonly ["medieval-hexagon", "adventurers", "skeletons"]

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:23

A stable pack identifier used by the CLI (bootstrap --pack &lt;id&gt;) and resolution.


PACK_REGISTRY

const PACK_REGISTRY: Readonly<Record<PackId, PackDescriptor>>

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:86

The three first-class downloadable CC0 packs. Together they are a full game from defaults: a hex tile board, playable characters, and enemies. GitHub reports these repos as NOASSERTION (no machine-readable LICENSE), but KayKit's itch.io pages license the packs CC0; the attribution is a courtesy credit.


PACK_ROLES

const PACK_ROLES: readonly ["tile", "model"]

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:28

How a pack's assets map into an AssetSource role.


packDescriptorSchema

const packDescriptorSchema: ZodObject<{ attribution: ZodString; category: ZodEnum<{ enemy: "enemy"; playable: "playable"; terrain: "terrain"; }>; displayName: ZodString; github: ZodObject<{ archiveUrlTemplate: ZodString; defaultRef: ZodString; owner: ZodString; repo: ZodString; }, $strip>; id: ZodEnum<{ adventurers: "adventurers"; medieval-hexagon: "medieval-hexagon"; skeletons: "skeletons"; }>; packFolder: ZodString; role: ZodEnum<{ model: "model"; tile: "tile"; }>; }, $strip>

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:58

A single downloadable-pack descriptor.


packGithubSourceSchema

const packGithubSourceSchema: ZodObject<{ archiveUrlTemplate: ZodString; defaultRef: ZodString; owner: ZodString; repo: ZodString; }, $strip>

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:41

Upstream GitHub source for a pack's CC0 archive.

Functions

assertPackPresent()

assertPackPresent(id, rawAssetsRoot): string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:132

Assert a pack is materialized at &lt;rawAssetsRoot&gt;/&lt;packId&gt;, or throw a clear error naming the pack + the exact command to fetch it. This is the "absent → clear error" half of default source resolution (RFC0-10).

Parameters

id

string

rawAssetsRoot

string

Returns

string


bootstrapKayKitAssets()

bootstrapKayKitAssets(options): Promise<BootstrapResult>

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:218

Materialize the KayKit asset tree under the consumer's asset root.

Parameters

options

BootstrapKayKitAssetsOptions

Returns

Promise<BootstrapResult>


bootstrapPack()

bootstrapPack(id, options): Promise<BootstrapResult>

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:76

Fetch a registered pack by id from its upstream GitHub archive into &lt;rawAssetsRoot&gt;/&lt;packId&gt;/. Throws a clear error for an unknown pack id (via packDescriptor). The per-pack subdir is computed here (not caller-chosen) so the fetched pack is always locatable by the default-source resolvers.

Parameters

id

string

options

BootstrapPackOptions

Returns

Promise<BootstrapResult>


detectDefaultBootstrapOut()

detectDefaultBootstrapOut(): string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/index.ts:141

Default --out heuristic. Prefers existing models (flat bootstrap default), then public/models (Vite / Next.js public dir convention), then falls back to models. Cosmetic only: every call still routes through safeResolveOutput.

Returns

string


formatBytes()

formatBytes(value): string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/index.ts:170

Parameters

value

number

Returns

string


isPackId()

isPackId(value): value is "medieval-hexagon" | "adventurers" | "skeletons"

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:132

True if value names a registered pack (proto-safe — used on external input).

Parameters

value

string

Returns

value is "medieval-hexagon" | "adventurers" | "skeletons"


isPackMaterialized()

isPackMaterialized(id, rawAssetsRoot): boolean

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:99

Whether a pack is materialized at &lt;rawAssetsRoot&gt;/&lt;packId&gt; (sidecar present). Validates the id at runtime (not just by the PackId type) so an external caller passing an unknown/hostile id gets a clear error, never a stray path.

Parameters

id

string

rawAssetsRoot

string

Returns

boolean


kayKitFreeGithubTarballUrl()

kayKitFreeGithubTarballUrl(commit?): string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:349

Format the canonical GitHub source-archive zip URL for a given ref (or main when unset). GitHub serves a stable, never-changing archive at /archive/refs/heads/&lt;ref&gt;.zip, so bootstrap downloads it and feeds the exact same local-zip extraction flow as a user-supplied archive — no tarball decompression and no git dependency.

Parameters

commit?

string

Returns

string


layoutForPack()

layoutForPack(descriptor): KayKitUpstreamLayout

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:32

Resolve the upstream layout for a pack descriptor. terrain packs use the medieval-hexagon layout (FREE edition); playable/enemy character packs use the flat character-pack layout keyed by the descriptor's addons/ folder.

Parameters

descriptor
attribution

string = ...

Attribution string (CC0 — no attribution required, but credited by courtesy).

category

"enemy" | "terrain" | "playable" = ...

Gameplay category the pack fills.

displayName

string = ...

Human-facing name for CLI listings + docs.

github

{ archiveUrlTemplate: string; defaultRef: string; owner: string; repo: string; } = packGithubSourceSchema

Upstream GitHub source.

github.archiveUrlTemplate

string = ...

Archive-URL template with {owner}/{repo}/{ref} placeholders. Kept per descriptor (not global) so a pack hosted differently can override it.

github.defaultRef

string = ...

Default git ref fetched when none is supplied.

github.owner

string = ...

GitHub owner/org.

github.repo

string = ...

Repository name.

id

"medieval-hexagon" | "adventurers" | "skeletons" = ...

Stable pack id.

packFolder

string = ...

Upstream addons/&lt;packFolder&gt;/ directory name the pack publishes under.

role

"tile" | "model" = ...

Asset role the pack contributes.

Returns

KayKitUpstreamLayout


listPackDescriptors()

listPackDescriptors(): readonly object[]

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:149

Every pack descriptor, in registry order.

Returns

readonly object[]


packArchiveUrl()

packArchiveUrl(descriptor, ref?): string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:154

Format a pack's upstream archive URL for a given ref (or its default ref).

Parameters

descriptor
attribution

string = ...

Attribution string (CC0 — no attribution required, but credited by courtesy).

category

"enemy" | "terrain" | "playable" = ...

Gameplay category the pack fills.

displayName

string = ...

Human-facing name for CLI listings + docs.

github

{ archiveUrlTemplate: string; defaultRef: string; owner: string; repo: string; } = packGithubSourceSchema

Upstream GitHub source.

github.archiveUrlTemplate

string = ...

Archive-URL template with {owner}/{repo}/{ref} placeholders. Kept per descriptor (not global) so a pack hosted differently can override it.

github.defaultRef

string = ...

Default git ref fetched when none is supplied.

github.owner

string = ...

GitHub owner/org.

github.repo

string = ...

Repository name.

id

"medieval-hexagon" | "adventurers" | "skeletons" = ...

Stable pack id.

packFolder

string = ...

Upstream addons/&lt;packFolder&gt;/ directory name the pack publishes under.

role

"tile" | "model" = ...

Asset role the pack contributes.

ref?

string

Returns

string


packDescriptor()

packDescriptor(id): object

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/registry.ts:141

Look up a pack descriptor by id, or throw a clear error listing the valid ids. Uses Object.hasOwn so an id equal to an Object.prototype member can't return an inherited value.

Parameters

id

string

Returns

attribution

attribution: string

Attribution string (CC0 — no attribution required, but credited by courtesy).

category

category: "enemy" | "terrain" | "playable"

Gameplay category the pack fills.

displayName

displayName: string

Human-facing name for CLI listings + docs.

github

github: object = packGithubSourceSchema

Upstream GitHub source.

github.archiveUrlTemplate

archiveUrlTemplate: string

Archive-URL template with {owner}/{repo}/{ref} placeholders. Kept per descriptor (not global) so a pack hosted differently can override it.

github.defaultRef

defaultRef: string

Default git ref fetched when none is supplied.

github.owner

owner: string

GitHub owner/org.

github.repo

repo: string

Repository name.

id

id: "medieval-hexagon" | "adventurers" | "skeletons"

Stable pack id.

packFolder

packFolder: string

Upstream addons/&lt;packFolder&gt;/ directory name the pack publishes under.

role

role: "tile" | "model"

Asset role the pack contributes.


packDir()

packDir(rawAssetsRoot, id): string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:46

The single source of truth for where a pack lives under a raw-assets root: &lt;rawAssetsRoot&gt;/&lt;packId&gt;/. bootstrapPack WRITES here and the default-source resolvers READ here, so a pack fetched by the CLI is always found by resolveDefaultPackKit/assertPackPresent — the convention can't diverge. Uses the validated descriptor.id (never a raw caller string) in the join.

Parameters

rawAssetsRoot

string

id

string

Returns

string


printBootstrapResult()

printBootstrapResult(result): void

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/index.ts:152

Parameters

result

BootstrapResult

Returns

void


printBootstrapVerifyReport()

printBootstrapVerifyReport(report): void

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/index.ts:159

Parameters

report

BootstrapVerificationReport

Returns

void


registeredPackClassifiers()

registeredPackClassifiers(): readonly PlacementClassifier[]

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:157

The recognized-pack PlacementClassifiers (RFC0-TAGb): one per registered pack, mapping each pack's registry category to its default gameplay classifiers (Adventurers → playable, Skeletons → enemy/random-encounter; terrain packs contribute none). Compose these ON TOP of DEFAULT_PLACEMENT_CLASSIFIERS so a placement sourced from a recognized pack is auto-classified:

const classifiers = [...DEFAULT_PLACEMENT_CLASSIFIERS, ...registeredPackClassifiers()];
classifyPlacement(placement, classifiers);

Returns

readonly PlacementClassifier[]


resolveBootstrapGltfRoot()

resolveBootstrapGltfRoot(assetRoot): string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/target.ts:30

Resolve the absolute path to a bootstrap target's GLTF tree root. With the flat layout (gltfRelative = ""), this is the asset root itself.

Parameters

assetRoot

string

Returns

string


resolveBootstrapSidecarPath()

resolveBootstrapSidecarPath(assetRoot): string

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/target.ts:40

Resolve the absolute path to a bootstrap target's integrity sidecar.

Parameters

assetRoot

string

Returns

string


resolveDefaultPackKit()

resolveDefaultPackKit(rawAssetsRoot): readonly PackResolution[]

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/pack-bootstrap.ts:119

Resolve every registered pack against a raw-assets root, reporting which are present and which are missing. An app composes its default game from the present packs; assertPackPresent turns a missing required pack into a clear, actionable error. Convention: each pack lives at &lt;root&gt;/&lt;packId&gt;/.

Parameters

rawAssetsRoot

string

Returns

readonly PackResolution[]


runBootstrap()

runBootstrap(parsed, edition): Promise<void>

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/index.ts:61

Parameters

parsed

ParsedArgs

edition

"free" | "extra"

Returns

Promise<void>


verifyBootstrap()

verifyBootstrap(outRoot): Promise<BootstrapVerificationReport>

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:299

Re-hash every file recorded in an integrity sidecar and report drift.

Parameters

outRoot

string

Returns

Promise<BootstrapVerificationReport>


zipEntryEscapesRoot()

zipEntryEscapesRoot(entryPath): boolean

Defined in: packages/declarative-hex-worlds/src/cli/commands/bootstrap/core.ts:917

True when a zip entry name is unsafe to extract — it would escape the destination directory, or is malformed in a way that makes containment platform-dependent (zip-slip, CWE-22).

Parameters

entryPath

string

Returns

boolean

Remarks

Judged entirely on the RAW entry name, never on a join()-ed path. That is the whole point: join() normalizes both escape shapes back INSIDE the target, so a post-join() test silently passes them.

  • join('/root', '/etc/passwd') is '/root/etc/passwd' — a leading separator is treated as root-relative, so isAbsolute() on the joined path can never fire. A Windows drive prefix (C:\...) is matched explicitly, since isAbsolute() is platform-dependent and returns false for it on POSIX.
  • A backslash is a legal filename character on POSIX but a SEPARATOR on Windows, so join()/relative() on POSIX see a\..\..\etc as one opaque segment and find no traversal — while the same archive extracted on Windows escapes. Splitting the raw name on BOTH separators makes the verdict independent of where extraction runs. The zip spec (APPNOTE 4.4.17) mandates forward slashes, so a backslash is malformed regardless.

Traversal is detected per SEGMENT, not with a startsWith('..') prefix test — the latter also rejects legitimate names that merely begin with two dots (..foo/x, .../x, ...), which an asset pack may legally contain.

A .. segment is rejected even when it would resolve back inside the root (a/../b). Deliberate: it matches yauzl's rule exactly, so the two layers agree on what a valid entry name is rather than subtly diverging.

yauzl's own validateFileName already refuses every one of these before an entry event fires, so in practice this is defense in depth. It is exported so its contract can be tested directly — an end-to-end assertion cannot distinguish this guard working from yauzl covering for it.

References

characterPackLayout

Re-exports characterPackLayout


detectKayKitLayout

Re-exports detectKayKitLayout


detectLayoutFrom

Re-exports detectLayoutFrom


expectedTexturePaths

Re-exports expectedTexturePaths


KAYKIT_MEDIEVAL_EXTRA_LAYOUT

Re-exports KAYKIT_MEDIEVAL_EXTRA_LAYOUT


KAYKIT_MEDIEVAL_FREE_LAYOUT

Re-exports KAYKIT_MEDIEVAL_FREE_LAYOUT


KAYKIT_UPSTREAM_LAYOUTS

Re-exports KAYKIT_UPSTREAM_LAYOUTS


kayKitLayoutForEdition

Re-exports kayKitLayoutForEdition


KayKitUpstreamLayout

Re-exports KayKitUpstreamLayout