@heroiclands/package-build 0.6.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/CHANGELOG-content-build.md +965 -0
  2. package/CHANGELOG.md +95 -0
  3. package/CONTENT.md +824 -0
  4. package/MIGRATING.md +127 -0
  5. package/README.md +29 -17
  6. package/bin/content-build.mjs +1082 -0
  7. package/bin/package-build.mjs +2 -2
  8. package/bin/report.mjs +2 -2
  9. package/config.mjs +21 -18
  10. package/content-config.mjs +1424 -0
  11. package/coverage.mjs +1 -1
  12. package/e2e.mjs +1 -1
  13. package/engine/abbreviations.mjs +0 -0
  14. package/engine/base-compiler.mjs +608 -0
  15. package/engine/code-fences.mjs +311 -0
  16. package/engine/compendiums.mjs +353 -0
  17. package/engine/content-address.mjs +141 -0
  18. package/engine/content-links.mjs +438 -0
  19. package/engine/content-lint.mjs +204 -0
  20. package/engine/content-package.mjs +67 -0
  21. package/engine/content-slug.mjs +169 -0
  22. package/engine/content-tables.mjs +1216 -0
  23. package/engine/content-tree.mjs +56 -0
  24. package/engine/diagnostics.mjs +270 -0
  25. package/engine/field-reference.mjs +242 -0
  26. package/engine/field-spec.mjs +218 -0
  27. package/engine/foreign-catalog.mjs +450 -0
  28. package/engine/foreign-manifests.mjs +129 -0
  29. package/engine/frontmatter-lint.mjs +343 -0
  30. package/engine/frontmatter.mjs +258 -0
  31. package/engine/generate.mjs +305 -0
  32. package/engine/helpers.mjs +809 -0
  33. package/engine/ids.mjs +192 -0
  34. package/engine/index.mjs +142 -0
  35. package/engine/item-docs.mjs +153 -0
  36. package/engine/item-registry.mjs +129 -0
  37. package/engine/journals.mjs +374 -0
  38. package/engine/kb-manifest.mjs +473 -0
  39. package/engine/macros.mjs +333 -0
  40. package/engine/manifest-emit.mjs +339 -0
  41. package/engine/map-notes.mjs +1302 -0
  42. package/engine/pack-config.mjs +479 -0
  43. package/engine/pack-router.mjs +254 -0
  44. package/engine/prose-config.mjs +238 -0
  45. package/engine/prose-lint.mjs +294 -0
  46. package/engine/region-events.mjs +79 -0
  47. package/engine/scene-levels.mjs +420 -0
  48. package/engine/scenes.mjs +528 -0
  49. package/engine/site-build.mjs +778 -0
  50. package/engine/site-index.mjs +332 -0
  51. package/engine/web-wikilinks.mjs +330 -0
  52. package/engine/wikilink-syntax.mjs +105 -0
  53. package/engine/wikilinks.mjs +645 -0
  54. package/index.mjs +42 -25
  55. package/lang.mjs +1 -1
  56. package/manifest.mjs +79 -5
  57. package/markdownlint-config.mjs +45 -0
  58. package/package.json +78 -34
  59. package/prettier-config.mjs +34 -0
  60. package/sohl/actors.mjs +581 -0
  61. package/sohl/affiliation-standings.mjs +44 -0
  62. package/sohl/being-info.mjs +173 -0
  63. package/sohl/default-item-art.mjs +82 -0
  64. package/sohl/index.mjs +55 -0
  65. package/sohl/item-builders.mjs +114 -0
  66. package/sohl/item-fields.mjs +867 -0
  67. package/sohl/items.mjs +197 -0
  68. package/sohl/kb-passes.mjs +207 -0
  69. package/sohl/note-schemas.mjs +322 -0
  70. package/templates.mjs +1 -1
  71. package/types/config.d.mts +1 -1
  72. package/types/content-config.d.mts +571 -0
  73. package/types/engine/abbreviations.d.mts +44 -0
  74. package/types/engine/base-compiler.d.mts +320 -0
  75. package/types/engine/code-fences.d.mts +102 -0
  76. package/types/engine/compendiums.d.mts +77 -0
  77. package/types/engine/content-address.d.mts +61 -0
  78. package/types/engine/content-links.d.mts +87 -0
  79. package/types/engine/content-lint.d.mts +47 -0
  80. package/types/engine/content-package.d.mts +36 -0
  81. package/types/engine/content-slug.d.mts +59 -0
  82. package/types/engine/content-tables.d.mts +131 -0
  83. package/types/engine/content-tree.d.mts +12 -0
  84. package/types/engine/diagnostics.d.mts +152 -0
  85. package/types/engine/field-reference.d.mts +20 -0
  86. package/types/engine/field-spec.d.mts +181 -0
  87. package/types/engine/foreign-catalog.d.mts +103 -0
  88. package/types/engine/foreign-manifests.d.mts +43 -0
  89. package/types/engine/frontmatter-lint.d.mts +74 -0
  90. package/types/engine/frontmatter.d.mts +99 -0
  91. package/types/engine/generate.d.mts +56 -0
  92. package/types/engine/helpers.d.mts +348 -0
  93. package/types/engine/ids.d.mts +126 -0
  94. package/types/engine/index.d.mts +33 -0
  95. package/types/engine/item-docs.d.mts +73 -0
  96. package/types/engine/item-registry.d.mts +57 -0
  97. package/types/engine/journals.d.mts +121 -0
  98. package/types/engine/kb-manifest.d.mts +214 -0
  99. package/types/engine/macros.d.mts +201 -0
  100. package/types/engine/manifest-emit.d.mts +137 -0
  101. package/types/engine/map-notes.d.mts +283 -0
  102. package/types/engine/pack-config.d.mts +77 -0
  103. package/types/engine/pack-router.d.mts +53 -0
  104. package/types/engine/prose-config.d.mts +121 -0
  105. package/types/engine/prose-lint.d.mts +59 -0
  106. package/types/engine/region-events.d.mts +43 -0
  107. package/types/engine/scene-levels.d.mts +36 -0
  108. package/types/engine/scenes.d.mts +48 -0
  109. package/types/engine/site-build.d.mts +214 -0
  110. package/types/engine/site-index.d.mts +141 -0
  111. package/types/engine/web-wikilinks.d.mts +67 -0
  112. package/types/engine/wikilink-syntax.d.mts +101 -0
  113. package/types/engine/wikilinks.d.mts +172 -0
  114. package/types/index.d.mts +3 -0
  115. package/types/manifest.d.mts +52 -4
  116. package/types/markdownlint-config.d.mts +8 -0
  117. package/types/prettier-config.d.mts +1 -0
  118. package/types/sohl/actors.d.mts +65 -0
  119. package/types/sohl/affiliation-standings.d.mts +22 -0
  120. package/types/sohl/being-info.d.mts +78 -0
  121. package/types/sohl/default-item-art.d.mts +28 -0
  122. package/types/sohl/index.d.mts +7 -0
  123. package/types/sohl/item-builders.d.mts +11 -0
  124. package/types/sohl/item-fields.d.mts +20 -0
  125. package/types/sohl/items.d.mts +19 -0
  126. package/types/sohl/kb-passes.d.mts +71 -0
  127. package/types/sohl/note-schemas.d.mts +7 -0
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Every declared relationship that opted into supplying an item catalogue.
3
+ *
4
+ * @param {object} config - The resolved build configuration.
5
+ * @returns {Array<{id: string, manifest: string, kind: string, verified: string|undefined}>}
6
+ * The opted-in relationships, in declaration order.
7
+ */
8
+ export function itemCatalogRelationships(config: object): Array<{
9
+ id: string;
10
+ manifest: string;
11
+ kind: string;
12
+ verified: string | undefined;
13
+ }>;
14
+ /**
15
+ * The cache directory for one dependency at one version.
16
+ *
17
+ * Keyed by version so that changing the pinned version is a different cache
18
+ * rather than a silent overwrite, and so a second build costs nothing.
19
+ *
20
+ * @param {object} config - The resolved build configuration.
21
+ * @param {string} id - The dependency's package id.
22
+ * @param {string} version - Its resolved version.
23
+ * @returns {string} The directory.
24
+ */
25
+ export function catalogDir(config: object, id: string, version: string): string;
26
+ /**
27
+ * Write an unzipped archive's entries under `dest`.
28
+ *
29
+ * @param {Record<string, Uint8Array>} files - The archive's entries.
30
+ * @param {string} dest - Where to write them.
31
+ * @returns {void}
32
+ */
33
+ export function writeZipEntries(files: Record<string, Uint8Array>, dest: string): void;
34
+ /**
35
+ * The manifest URL to actually read, pinned to the declared version.
36
+ *
37
+ * A consumer writes `releases/latest/download/system.json`, which is the right
38
+ * thing to publish and the wrong thing to build against: the artifact behind it
39
+ * changes when somebody else cuts a release, so a build names no particular
40
+ * dependency and "thalorna 0.1.0" stops being reproducible. The declared
41
+ * `compatibility.verified` is the version this repository was actually built
42
+ * against, so that is the one to fetch.
43
+ *
44
+ * GitHub's release URLs are rewritable — `releases/latest/download/X` is
45
+ * `releases/download/v<version>/X`. Where the URL is not that shape there is
46
+ * nothing to rewrite, so the declared URL is read and its version checked
47
+ * instead: floating silently is the one outcome not on offer.
48
+ *
49
+ * @param {string} url - The declared manifest URL.
50
+ * @param {string|undefined} verified - The declared verified version.
51
+ * @returns {{url: string, pinned: boolean}} The URL to read.
52
+ */
53
+ export function pinnedManifestUrl(url: string, verified: string | undefined): {
54
+ url: string;
55
+ pinned: boolean;
56
+ };
57
+ /**
58
+ * Fetch one dependency and extract its Item packs.
59
+ *
60
+ * Idempotent: a complete cache for the resolved version is left alone.
61
+ *
62
+ * @param {object} config - The resolved build configuration.
63
+ * @param {{id: string, manifest: string}} rel - The declared relationship.
64
+ * @returns {Promise<string>} The dependency's cache directory.
65
+ */
66
+ export function fetchCatalog(config: object, rel: {
67
+ id: string;
68
+ manifest: string;
69
+ }): Promise<string>;
70
+ /**
71
+ * Fill the cache from a locally built artifact rather than a release.
72
+ *
73
+ * `source` is either the `.zip` a package build emits or the directory it was
74
+ * built from. Either way the manifest inside it names the version, so the cache
75
+ * stays version-keyed and a compile cannot tell the difference — which is the
76
+ * point: a consumer can be built against a dependency that has not shipped.
77
+ *
78
+ * @param {object} config - The resolved build configuration.
79
+ * @param {{id: string}} rel - The declared relationship.
80
+ * @param {string} source - Path to the artifact or its directory.
81
+ * @returns {Promise<string>} The dependency's cache directory.
82
+ */
83
+ export function fetchCatalogFromPath(config: object, rel: {
84
+ id: string;
85
+ }, source: string): Promise<string>;
86
+ /**
87
+ * Fetch every opted-in dependency. The `deps fetch` command.
88
+ *
89
+ * @param {object} config - The resolved build configuration.
90
+ * @returns {Promise<number>} How many dependencies were fetched.
91
+ */
92
+ export function fetchAllCatalogs(config: object): Promise<number>;
93
+ /**
94
+ * The extracted item directories the actors pass should resolve against, on
95
+ * top of this repository's own.
96
+ *
97
+ * Reads the cache only. A cold cache is an error naming the command that fills
98
+ * it, rather than a download nobody asked for.
99
+ *
100
+ * @param {object} config - The resolved build configuration.
101
+ * @returns {string[]} Every cached dependency's item directories.
102
+ */
103
+ export function foreignItemCatalogDirs(config: object): string[];
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Every foreign package whose manifest entries a build cannot address.
3
+ *
4
+ * A package is reported only when it contributes entries and **none** of them
5
+ * yields a readable canonical key — the total, silent failure described above.
6
+ * Partial drift is deliberately not reported here: it resolves something, and
7
+ * whatever it fails to resolve surfaces as an ordinary dead address, pointed at
8
+ * the note that cites it. A package contributing no entries at all is likewise
9
+ * not a finding; a pack-only package publishes no addressable pages by design
10
+ * (#1516), and one being brought up publishes nothing yet.
11
+ *
12
+ * @param {Map<string, {package?: string}>} foreignIndex - `foreign.index` as
13
+ * returned by `loadForeignManifests`, keyed by canonical key.
14
+ * @returns {Array<{package: string, entries: number, sampleKey: string}>} One
15
+ * finding per drifted package, in the order the index first names each.
16
+ */
17
+ export function unaddressableForeignPackages(foreignIndex: Map<string, {
18
+ package?: string;
19
+ }>): Array<{
20
+ package: string;
21
+ entries: number;
22
+ sampleKey: string;
23
+ }>;
24
+ /**
25
+ * One finding, in the standard `file:line:column: severity: message` form.
26
+ *
27
+ * The position is recovered by locating the offending key in the manifest text:
28
+ * the finding is about a literal the reader can see in the file, so its position
29
+ * is implicit rather than absent. When the file cannot be read, or the key is
30
+ * not in it, the locator degrades to the file alone — a dropped field, never a
31
+ * guessed `1:1` that would send the reader to the top of a 500 KB manifest for a
32
+ * finding that is not there.
33
+ *
34
+ * @param {{package: string, entries: number, sampleKey: string}} finding - One
35
+ * finding from {@link unaddressableForeignPackages}.
36
+ * @param {string} manifestDir - The directory the manifests were loaded from.
37
+ * @returns {string} The formatted diagnostic, path first on the line.
38
+ */
39
+ export function formatUnaddressableFinding(finding: {
40
+ package: string;
41
+ entries: number;
42
+ sampleKey: string;
43
+ }, manifestDir: string): string;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Whether a value satisfies a declared {@link FieldSpec.kind}.
3
+ *
4
+ * Deliberately lenient about the spellings YAML makes ambiguous: `"12"` is a
5
+ * number, because a quoted scalar is how a number arrives from many editors,
6
+ * and a map authored as an empty list is a map, because Obsidian's property
7
+ * editor serialises an emptied map that way (#8). What it rejects is a value
8
+ * that cannot mean what the field is for — `weight: heavy`.
9
+ *
10
+ * @param {unknown} value - The authored value.
11
+ * @param {string} kind - The declared kind.
12
+ * @returns {boolean} Whether it is acceptable.
13
+ */
14
+ export function matchesKind(value: unknown, kind: string): boolean;
15
+ /**
16
+ * Check one note against its type's schema.
17
+ *
18
+ * @param {object} note - A note from the link index (`{fm, file, raw, type}`).
19
+ * @param {object} opts
20
+ * @param {Record<string, readonly object[]>} opts.schemas - Type → declaration.
21
+ * @param {object} [opts.index] - The link index, for the reference check. Its
22
+ * absence skips that check rather than reporting every reference as dead.
23
+ * @returns {object[]} Findings, each with a locator where one is obtainable.
24
+ */
25
+ export function lintNote(note: object, { schemas, index }: {
26
+ schemas: Record<string, readonly object[]>;
27
+ index?: object | undefined;
28
+ }): object[];
29
+ /**
30
+ * Check every note in a built index against its type's schema.
31
+ *
32
+ * @param {object} index - From `buildLinkIndex`.
33
+ * @param {object} opts
34
+ * @param {Record<string, readonly object[]>} opts.schemas - Type → declaration.
35
+ * @param {boolean} [opts.references=true] - Whether to check references.
36
+ * @returns {{findings: object[], notes: number}} The findings, and how many
37
+ * notes were inspected.
38
+ */
39
+ export function lintFrontmatter(index: object, { schemas, references }: {
40
+ schemas: Record<string, readonly object[]>;
41
+ references?: boolean | undefined;
42
+ }): {
43
+ findings: object[];
44
+ notes: number;
45
+ };
46
+ /**
47
+ * `sohl:` keys every type accepts, whatever its schema says.
48
+ *
49
+ * Neither is part of a type's vocabulary — both are read for *any* note, by
50
+ * passes that run before a builder sees it — so neither appears in a field
51
+ * declaration and both would otherwise be reported as unknown on every note
52
+ * that uses them.
53
+ *
54
+ * - `folder` — the compendium folder the document is filed in.
55
+ * - `pack` — which compendium of the note's document type receives it, for a
56
+ * repository shipping several (#1566).
57
+ * - `archetype` — the archetype flag, read for any note by the walk itself.
58
+ * - `kbcat` — the knowledgebase category a note is grouped under.
59
+ *
60
+ * `kbcat` is the one that matters for what this check *is*. **The pack build is
61
+ * not the only reader of a note's frontmatter.** A note also feeds a
62
+ * knowledgebase and a website, and those surfaces consume classification the
63
+ * compiler never emits — `kbcat` alone is read 51 times across SoHL's
64
+ * knowledgebase layouts. A check that equated "the vocabulary" with "what the
65
+ * builder compiles" would report every one of those as an unknown property and
66
+ * turn a correct tree red, which is exactly what it did on first run: 4,241
67
+ * findings against SoHL's own content, none of them a defect.
68
+ *
69
+ * So a type's schema declares what a note **may write**, which is broader than
70
+ * what any one consumer reads.
71
+ *
72
+ * @type {ReadonlySet<string>}
73
+ */
74
+ export const UNIVERSAL_KEYS: ReadonlySet<string>;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Resolves a dotted frontmatter key (e.g., "name.full") into the nested
3
+ * value. Returns `defaultValue` if any path segment is missing.
4
+ */
5
+ export function getFrontmatter(fm: any, key: any, defaultValue?: undefined): any;
6
+ /**
7
+ * Reads a key from `fm.sohl` (the vault's nested system-fields block).
8
+ * Supports dotted notation, e.g. sohlField(fm, "charges.value", 0).
9
+ * Falls back to top-level `fm[key]` if `sohl` doesn't carry the key.
10
+ */
11
+ export function sohlField(fm: any, key: any, defaultValue?: undefined): any;
12
+ /**
13
+ * Resolve the `charges` block shared by Mystery and Mystical Ability items.
14
+ *
15
+ * Charge usage is carried by the **maximum** alone (#1129): a `null` max means
16
+ * the item does not use charges at all, `0` means it is counted but uncapped,
17
+ * and a positive number is a real cap. `value` is the current count, with
18
+ * `null` meaning "infinite remaining". Both persist as nullable NumberFields,
19
+ * so absent frontmatter must resolve to `null` — coercing it to `0` would ship
20
+ * every item as an uncapped charge-user.
21
+ *
22
+ * A legacy `usesCharges` flag in authored frontmatter is ignored: it was inert
23
+ * and has been dropped from the schema.
24
+ *
25
+ * @param {object} fm - The item frontmatter.
26
+ * @returns {{value: number|null, max: number|null}} The persisted charges block.
27
+ */
28
+ export function resolveCharges(fm: object): {
29
+ value: number | null;
30
+ max: number | null;
31
+ };
32
+ /**
33
+ * Resolve an item's `skillAptitudes` map — selector → mastery-level modifier,
34
+ * where a selector is a skill shortcode or `subType:<value>`.
35
+ *
36
+ * Authored values must be whole numbers: the persisted field is an integer
37
+ * `NumberField`, and a fractional or non-numeric entry would be silently
38
+ * coerced at load, shipping an aptitude nobody authored. A malformed entry is a
39
+ * build error rather than a rounded surprise. A `0` is legitimate and must be
40
+ * kept — an element a sign leaves untouched still beats one another sign
41
+ * hinders, so it carries real weight when maps merge.
42
+ *
43
+ * An absent property, an empty map, and the empty **list** Obsidian's property
44
+ * editor writes for a cleared map all mean the same thing — see
45
+ * {@link readMapEntries}.
46
+ *
47
+ * @param {object} fm - The item frontmatter.
48
+ * @param {string} [ctx] - Label for the error (defaults to "item").
49
+ * @returns {Record<string, number>} The persisted aptitude map (empty when
50
+ * the item authors none).
51
+ * @throws {Error} When the value is not a map, or a value is not an integer.
52
+ */
53
+ export function resolveSkillAptitudes(fm: object, ctx?: string): Record<string, number>;
54
+ /**
55
+ * Resolve an affiliation's `relation` map — the shortcode of another
56
+ * affiliation → this one's standing toward it (#1404).
57
+ *
58
+ * An unrecognized standing would fail the schema's `choices` validation at load
59
+ * and be dropped silently, shipping an affiliation whose authored hostility had
60
+ * quietly become neutrality — so it is a build error instead.
61
+ *
62
+ * An absent property, an empty map, and the empty **list** Obsidian's property
63
+ * editor writes for a cleared map all mean the same thing — neutral toward
64
+ * everyone. See {@link readMapEntries}.
65
+ *
66
+ * @param {object} fm - The item frontmatter.
67
+ * @param {string} [ctx] - Label for the error (defaults to "item").
68
+ * @returns {Record<string, string>} The persisted relation map (empty when the
69
+ * affiliation authors none — neutral toward everyone).
70
+ * @throws {Error} When the map is malformed or names an unknown standing.
71
+ */
72
+ export function resolveRelation(fm: object, ctx?: string): Record<string, string>;
73
+ /**
74
+ * Read the mandatory `subType` from an item's frontmatter, throwing when it is
75
+ * absent or blank.
76
+ *
77
+ * Every subType-bearing item type declares `subType` as `required` with **no**
78
+ * default in its DataModel — a subtype must always be specified, and it is an
79
+ * error to omit it. The builder therefore substitutes no fallback: a content
80
+ * file missing `subType` is a build error, surfaced here rather than shipped as
81
+ * an invalid (typeless-fallback) item.
82
+ *
83
+ * @param {object} fm - The item frontmatter.
84
+ * @param {string} [ctx] - Optional label for the error (defaults to the item's
85
+ * title/name, else "item").
86
+ * @returns {string} The declared subType.
87
+ * @throws {Error} When `subType` is missing or blank.
88
+ */
89
+ export function requireSubType(fm: object, ctx?: string): string;
90
+ /**
91
+ * Parses the valueDesc / threshold array format. Accepts either:
92
+ * - Array of "Label:MaxValue" strings, e.g. ["Ugly:4", "Plain:12"]
93
+ * - Array of objects, e.g. [{ label, maxValue }]
94
+ * Returns a normalized array of `{ label, maxValue: number }`.
95
+ */
96
+ export function parseValueDesc(raw: any): {
97
+ label: string;
98
+ maxValue: number;
99
+ }[];
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The generated JSON of **every** configured Item pack — what the actors pass
3
+ * reads its predefined items from.
4
+ *
5
+ * All of them, not the first: a repository may ship several Item packs (#1566),
6
+ * and an actor's embedded items may be sourced from any of them. Finding one
7
+ * pack and stopping is how embedded-item resolution would silently miss every
8
+ * item that landed in another. Returned in configured order, which is also the
9
+ * order they compile in, so a pack later in the list cannot be read before it
10
+ * is written.
11
+ *
12
+ * @param {object} [config] - The resolved build configuration. Defaults to this
13
+ * repository's.
14
+ * @returns {string[]} Each Item pack's JSON directory. Empty when the
15
+ * repository ships no items at all — the actors pass, which is the only
16
+ * caller that needs one, refuses that itself.
17
+ */
18
+ export function itemPackJsonDirs(config?: object): string[];
19
+ /**
20
+ * The passes that compiled nothing when they were expected to compile
21
+ * something — a build failure, not a quiet no-op.
22
+ *
23
+ * A pack compiler selects its entries by the configured content package, so a
24
+ * single wrong package id rejects every note in a perfectly good tree and every
25
+ * pack ships blank while the build exits 0 (#1502). The empty-tree guard in
26
+ * {@link generatePacksJson} cannot see that: the tree is full, it is the
27
+ * *output* that is empty.
28
+ *
29
+ * @param {Array<{name: string, compiled: number, mayBeEmpty?: boolean}>} passes -
30
+ * One entry per generated pack.
31
+ * @returns {string[]} One message per pass that must not have been empty.
32
+ */
33
+ export function emptyPassErrors(passes: Array<{
34
+ name: string;
35
+ compiled: number;
36
+ mayBeEmpty?: boolean;
37
+ }>): string[];
38
+ /**
39
+ * Generate the build-only JSON for every pack (or one, when `only` is given).
40
+ *
41
+ * @param {object} [opts]
42
+ * @param {string} [opts.only] - Restrict to a single pack name.
43
+ * @param {object} [opts.config] - The resolved build configuration. Defaults to
44
+ * this repository's. Supplying one is how a caller compiles a *different*
45
+ * package's tree — and how the guard-order test below induces id drift, now
46
+ * that the manifest is located by configuration rather than by the working
47
+ * directory.
48
+ * @returns {Promise<number>} Total error count across the generated packs.
49
+ * @throws {Error} If the configured Foundry package id has drifted from the
50
+ * shipped manifest's `id` (see `package-manifest.mjs`).
51
+ */
52
+ export function generatePacksJson({ only, config, }?: {
53
+ only?: string | undefined;
54
+ config?: object | undefined;
55
+ }): Promise<number>;
56
+ export function packJsonDir(name: string, config?: object): string;