@lepid-labs/weft-core 0.1.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 (266) hide show
  1. package/LICENSE +21 -0
  2. package/dist/anchors/__tests__/markdown.test.d.ts +2 -0
  3. package/dist/anchors/__tests__/markdown.test.d.ts.map +1 -0
  4. package/dist/anchors/__tests__/markdown.test.js +130 -0
  5. package/dist/anchors/__tests__/markdown.test.js.map +1 -0
  6. package/dist/anchors/__tests__/openapi.test.d.ts +2 -0
  7. package/dist/anchors/__tests__/openapi.test.d.ts.map +1 -0
  8. package/dist/anchors/__tests__/openapi.test.js +115 -0
  9. package/dist/anchors/__tests__/openapi.test.js.map +1 -0
  10. package/dist/anchors/index.d.ts +35 -0
  11. package/dist/anchors/index.d.ts.map +1 -0
  12. package/dist/anchors/index.js +68 -0
  13. package/dist/anchors/index.js.map +1 -0
  14. package/dist/anchors/markdown.d.ts +15 -0
  15. package/dist/anchors/markdown.d.ts.map +1 -0
  16. package/dist/anchors/markdown.js +71 -0
  17. package/dist/anchors/markdown.js.map +1 -0
  18. package/dist/anchors/openapi.d.ts +24 -0
  19. package/dist/anchors/openapi.d.ts.map +1 -0
  20. package/dist/anchors/openapi.js +75 -0
  21. package/dist/anchors/openapi.js.map +1 -0
  22. package/dist/browser.d.ts +10 -0
  23. package/dist/browser.d.ts.map +1 -0
  24. package/dist/browser.js +8 -0
  25. package/dist/browser.js.map +1 -0
  26. package/dist/config.d.ts +47 -0
  27. package/dist/config.d.ts.map +1 -0
  28. package/dist/config.js +393 -0
  29. package/dist/config.js.map +1 -0
  30. package/dist/config.test.d.ts +2 -0
  31. package/dist/config.test.d.ts.map +1 -0
  32. package/dist/config.test.js +454 -0
  33. package/dist/config.test.js.map +1 -0
  34. package/dist/content.d.ts +37 -0
  35. package/dist/content.d.ts.map +1 -0
  36. package/dist/content.js +57 -0
  37. package/dist/content.js.map +1 -0
  38. package/dist/content.test.d.ts +2 -0
  39. package/dist/content.test.d.ts.map +1 -0
  40. package/dist/content.test.js +100 -0
  41. package/dist/content.test.js.map +1 -0
  42. package/dist/contributions.d.ts +64 -0
  43. package/dist/contributions.d.ts.map +1 -0
  44. package/dist/contributions.js +184 -0
  45. package/dist/contributions.js.map +1 -0
  46. package/dist/contributions.test.d.ts +2 -0
  47. package/dist/contributions.test.d.ts.map +1 -0
  48. package/dist/contributions.test.js +202 -0
  49. package/dist/contributions.test.js.map +1 -0
  50. package/dist/fetch/auth.d.ts +15 -0
  51. package/dist/fetch/auth.d.ts.map +1 -0
  52. package/dist/fetch/auth.js +38 -0
  53. package/dist/fetch/auth.js.map +1 -0
  54. package/dist/fetch/cache.d.ts +25 -0
  55. package/dist/fetch/cache.d.ts.map +1 -0
  56. package/dist/fetch/cache.js +68 -0
  57. package/dist/fetch/cache.js.map +1 -0
  58. package/dist/fetch/cache.test.d.ts +2 -0
  59. package/dist/fetch/cache.test.d.ts.map +1 -0
  60. package/dist/fetch/cache.test.js +73 -0
  61. package/dist/fetch/cache.test.js.map +1 -0
  62. package/dist/fetch/clone.d.ts +26 -0
  63. package/dist/fetch/clone.d.ts.map +1 -0
  64. package/dist/fetch/clone.js +105 -0
  65. package/dist/fetch/clone.js.map +1 -0
  66. package/dist/fetch/fetch.test.d.ts +2 -0
  67. package/dist/fetch/fetch.test.d.ts.map +1 -0
  68. package/dist/fetch/fetch.test.js +167 -0
  69. package/dist/fetch/fetch.test.js.map +1 -0
  70. package/dist/fetch/resolve.d.ts +34 -0
  71. package/dist/fetch/resolve.d.ts.map +1 -0
  72. package/dist/fetch/resolve.js +59 -0
  73. package/dist/fetch/resolve.js.map +1 -0
  74. package/dist/freshness.d.ts +29 -0
  75. package/dist/freshness.d.ts.map +1 -0
  76. package/dist/freshness.js +170 -0
  77. package/dist/freshness.js.map +1 -0
  78. package/dist/freshness.test.d.ts +2 -0
  79. package/dist/freshness.test.d.ts.map +1 -0
  80. package/dist/freshness.test.js +209 -0
  81. package/dist/freshness.test.js.map +1 -0
  82. package/dist/frontmatter.d.ts +15 -0
  83. package/dist/frontmatter.d.ts.map +1 -0
  84. package/dist/frontmatter.js +24 -0
  85. package/dist/frontmatter.js.map +1 -0
  86. package/dist/frontmatter.test.d.ts +2 -0
  87. package/dist/frontmatter.test.d.ts.map +1 -0
  88. package/dist/frontmatter.test.js +54 -0
  89. package/dist/frontmatter.test.js.map +1 -0
  90. package/dist/git.d.ts +55 -0
  91. package/dist/git.d.ts.map +1 -0
  92. package/dist/git.js +127 -0
  93. package/dist/git.js.map +1 -0
  94. package/dist/git.test.d.ts +2 -0
  95. package/dist/git.test.d.ts.map +1 -0
  96. package/dist/git.test.js +198 -0
  97. package/dist/git.test.js.map +1 -0
  98. package/dist/includes.d.ts +53 -0
  99. package/dist/includes.d.ts.map +1 -0
  100. package/dist/includes.js +73 -0
  101. package/dist/includes.js.map +1 -0
  102. package/dist/includes.test.d.ts +2 -0
  103. package/dist/includes.test.d.ts.map +1 -0
  104. package/dist/includes.test.js +106 -0
  105. package/dist/includes.test.js.map +1 -0
  106. package/dist/index.d.ts +33 -0
  107. package/dist/index.d.ts.map +1 -0
  108. package/dist/index.js +23 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/links/__tests__/markdown.test.d.ts +2 -0
  111. package/dist/links/__tests__/markdown.test.d.ts.map +1 -0
  112. package/dist/links/__tests__/markdown.test.js +173 -0
  113. package/dist/links/__tests__/markdown.test.js.map +1 -0
  114. package/dist/links/__tests__/sidecar.test.d.ts +2 -0
  115. package/dist/links/__tests__/sidecar.test.d.ts.map +1 -0
  116. package/dist/links/__tests__/sidecar.test.js +238 -0
  117. package/dist/links/__tests__/sidecar.test.js.map +1 -0
  118. package/dist/links/index.d.ts +3 -0
  119. package/dist/links/index.d.ts.map +1 -0
  120. package/dist/links/index.js +3 -0
  121. package/dist/links/index.js.map +1 -0
  122. package/dist/links/markdown.d.ts +13 -0
  123. package/dist/links/markdown.d.ts.map +1 -0
  124. package/dist/links/markdown.js +93 -0
  125. package/dist/links/markdown.js.map +1 -0
  126. package/dist/links/sidecar.d.ts +12 -0
  127. package/dist/links/sidecar.d.ts.map +1 -0
  128. package/dist/links/sidecar.js +88 -0
  129. package/dist/links/sidecar.js.map +1 -0
  130. package/dist/manifest.d.ts +45 -0
  131. package/dist/manifest.d.ts.map +1 -0
  132. package/dist/manifest.js +269 -0
  133. package/dist/manifest.js.map +1 -0
  134. package/dist/manifest.test.d.ts +2 -0
  135. package/dist/manifest.test.d.ts.map +1 -0
  136. package/dist/manifest.test.js +625 -0
  137. package/dist/manifest.test.js.map +1 -0
  138. package/dist/multi-repo.test.d.ts +2 -0
  139. package/dist/multi-repo.test.d.ts.map +1 -0
  140. package/dist/multi-repo.test.js +179 -0
  141. package/dist/multi-repo.test.js.map +1 -0
  142. package/dist/node-path.d.ts +13 -0
  143. package/dist/node-path.d.ts.map +1 -0
  144. package/dist/node-path.js +21 -0
  145. package/dist/node-path.js.map +1 -0
  146. package/dist/node-path.test.d.ts +2 -0
  147. package/dist/node-path.test.d.ts.map +1 -0
  148. package/dist/node-path.test.js +29 -0
  149. package/dist/node-path.test.js.map +1 -0
  150. package/dist/published-links.d.ts +16 -0
  151. package/dist/published-links.d.ts.map +1 -0
  152. package/dist/published-links.js +59 -0
  153. package/dist/published-links.js.map +1 -0
  154. package/dist/published-links.test.d.ts +2 -0
  155. package/dist/published-links.test.d.ts.map +1 -0
  156. package/dist/published-links.test.js +82 -0
  157. package/dist/published-links.test.js.map +1 -0
  158. package/dist/repos.d.ts +32 -0
  159. package/dist/repos.d.ts.map +1 -0
  160. package/dist/repos.js +46 -0
  161. package/dist/repos.js.map +1 -0
  162. package/dist/repos.test.d.ts +2 -0
  163. package/dist/repos.test.d.ts.map +1 -0
  164. package/dist/repos.test.js +61 -0
  165. package/dist/repos.test.js.map +1 -0
  166. package/dist/scalar-source.d.ts +15 -0
  167. package/dist/scalar-source.d.ts.map +1 -0
  168. package/dist/scalar-source.js +21 -0
  169. package/dist/scalar-source.js.map +1 -0
  170. package/dist/search.d.ts +14 -0
  171. package/dist/search.d.ts.map +1 -0
  172. package/dist/search.js +59 -0
  173. package/dist/search.js.map +1 -0
  174. package/dist/service-concurrency.test.d.ts +2 -0
  175. package/dist/service-concurrency.test.d.ts.map +1 -0
  176. package/dist/service-concurrency.test.js +89 -0
  177. package/dist/service-concurrency.test.js.map +1 -0
  178. package/dist/service-history.test.d.ts +2 -0
  179. package/dist/service-history.test.d.ts.map +1 -0
  180. package/dist/service-history.test.js +76 -0
  181. package/dist/service-history.test.js.map +1 -0
  182. package/dist/service.d.ts +118 -0
  183. package/dist/service.d.ts.map +1 -0
  184. package/dist/service.js +347 -0
  185. package/dist/service.js.map +1 -0
  186. package/dist/service.test.d.ts +2 -0
  187. package/dist/service.test.d.ts.map +1 -0
  188. package/dist/service.test.js +313 -0
  189. package/dist/service.test.js.map +1 -0
  190. package/dist/types.d.ts +403 -0
  191. package/dist/types.d.ts.map +1 -0
  192. package/dist/types.js +2 -0
  193. package/dist/types.js.map +1 -0
  194. package/dist/validate/__tests__/artifacts.test.d.ts +2 -0
  195. package/dist/validate/__tests__/artifacts.test.d.ts.map +1 -0
  196. package/dist/validate/__tests__/artifacts.test.js +167 -0
  197. package/dist/validate/__tests__/artifacts.test.js.map +1 -0
  198. package/dist/validate/__tests__/assertions.test.d.ts +2 -0
  199. package/dist/validate/__tests__/assertions.test.d.ts.map +1 -0
  200. package/dist/validate/__tests__/assertions.test.js +254 -0
  201. package/dist/validate/__tests__/assertions.test.js.map +1 -0
  202. package/dist/validate/__tests__/duplicates.test.d.ts +2 -0
  203. package/dist/validate/__tests__/duplicates.test.d.ts.map +1 -0
  204. package/dist/validate/__tests__/duplicates.test.js +130 -0
  205. package/dist/validate/__tests__/duplicates.test.js.map +1 -0
  206. package/dist/validate/__tests__/edge-resolution.test.d.ts +2 -0
  207. package/dist/validate/__tests__/edge-resolution.test.d.ts.map +1 -0
  208. package/dist/validate/__tests__/edge-resolution.test.js +279 -0
  209. package/dist/validate/__tests__/edge-resolution.test.js.map +1 -0
  210. package/dist/validate/__tests__/history.test.d.ts +2 -0
  211. package/dist/validate/__tests__/history.test.d.ts.map +1 -0
  212. package/dist/validate/__tests__/history.test.js +93 -0
  213. package/dist/validate/__tests__/history.test.js.map +1 -0
  214. package/dist/validate/__tests__/includes.test.d.ts +2 -0
  215. package/dist/validate/__tests__/includes.test.d.ts.map +1 -0
  216. package/dist/validate/__tests__/includes.test.js +93 -0
  217. package/dist/validate/__tests__/includes.test.js.map +1 -0
  218. package/dist/validate/__tests__/registry.test.d.ts +2 -0
  219. package/dist/validate/__tests__/registry.test.d.ts.map +1 -0
  220. package/dist/validate/__tests__/registry.test.js +78 -0
  221. package/dist/validate/__tests__/registry.test.js.map +1 -0
  222. package/dist/validate/__tests__/run.test.d.ts +2 -0
  223. package/dist/validate/__tests__/run.test.d.ts.map +1 -0
  224. package/dist/validate/__tests__/run.test.js +215 -0
  225. package/dist/validate/__tests__/run.test.js.map +1 -0
  226. package/dist/validate/history.d.ts +23 -0
  227. package/dist/validate/history.d.ts.map +1 -0
  228. package/dist/validate/history.js +45 -0
  229. package/dist/validate/history.js.map +1 -0
  230. package/dist/validate/index.d.ts +10 -0
  231. package/dist/validate/index.d.ts.map +1 -0
  232. package/dist/validate/index.js +9 -0
  233. package/dist/validate/index.js.map +1 -0
  234. package/dist/validate/registry.d.ts +27 -0
  235. package/dist/validate/registry.d.ts.map +1 -0
  236. package/dist/validate/registry.js +67 -0
  237. package/dist/validate/registry.js.map +1 -0
  238. package/dist/validate/rules/artifacts.d.ts +25 -0
  239. package/dist/validate/rules/artifacts.d.ts.map +1 -0
  240. package/dist/validate/rules/artifacts.js +87 -0
  241. package/dist/validate/rules/artifacts.js.map +1 -0
  242. package/dist/validate/rules/assertions.d.ts +19 -0
  243. package/dist/validate/rules/assertions.d.ts.map +1 -0
  244. package/dist/validate/rules/assertions.js +149 -0
  245. package/dist/validate/rules/assertions.js.map +1 -0
  246. package/dist/validate/rules/duplicates.d.ts +20 -0
  247. package/dist/validate/rules/duplicates.d.ts.map +1 -0
  248. package/dist/validate/rules/duplicates.js +0 -0
  249. package/dist/validate/rules/duplicates.js.map +1 -0
  250. package/dist/validate/rules/edge-resolution.d.ts +15 -0
  251. package/dist/validate/rules/edge-resolution.d.ts.map +1 -0
  252. package/dist/validate/rules/edge-resolution.js +185 -0
  253. package/dist/validate/rules/edge-resolution.js.map +1 -0
  254. package/dist/validate/rules/includes.d.ts +21 -0
  255. package/dist/validate/rules/includes.d.ts.map +1 -0
  256. package/dist/validate/rules/includes.js +112 -0
  257. package/dist/validate/rules/includes.js.map +1 -0
  258. package/dist/validate/run.d.ts +20 -0
  259. package/dist/validate/run.d.ts.map +1 -0
  260. package/dist/validate/run.js +90 -0
  261. package/dist/validate/run.js.map +1 -0
  262. package/dist/validate/types.d.ts +101 -0
  263. package/dist/validate/types.d.ts.map +1 -0
  264. package/dist/validate/types.js +2 -0
  265. package/dist/validate/types.js.map +1 -0
  266. package/package.json +54 -0
@@ -0,0 +1,403 @@
1
+ /**
2
+ * A ui-std-lib style selection: one theme name, or a scheme pair the UI's
3
+ * light/dark toggle switches between. Names are validated by the UI against
4
+ * the installed @nazuraki/styles manifest (core stays dependency-free, and a
5
+ * theme newer than the installed set is reachable via `styleUrl`).
6
+ */
7
+ export type StyleConfig = string | {
8
+ dark: string;
9
+ light: string;
10
+ };
11
+ /** A single product's docs root in a multi-project (monorepo) setup. */
12
+ export interface WeftProject {
13
+ /** Display name, shown as a group header in the left-hand nav. */
14
+ name: string;
15
+ /**
16
+ * Directory to scan for this project's documents. Relative to the project
17
+ * root, or — when `repo` is set — to that repo's mapped checkout.
18
+ */
19
+ docsDir: string;
20
+ /** Id/URL namespace for this project's documents. Defaults to a kebab-cased `name`. */
21
+ slug?: string;
22
+ /**
23
+ * Repo identity (`org/repo`) whose checkout holds this project's docs. The
24
+ * identity must appear in the `repos` map; where the checkout lives is the
25
+ * map's business, so the committed config never embeds a machine's layout.
26
+ */
27
+ repo?: string;
28
+ /**
29
+ * Write this project's manifest into its own checkout even when the checkout
30
+ * lives outside the project root. Off by default, because `weft index`
31
+ * dirtying the git status of a repo it does not own is a surprise; opt in
32
+ * for a co-owned repo that wants its manifest alongside its docs.
33
+ */
34
+ manifestInRepo?: boolean;
35
+ }
36
+ /** A project as recorded in a manifest — always has its slug resolved. */
37
+ export interface WeftProjectRef {
38
+ name: string;
39
+ slug: string;
40
+ /** Relative to the project root, or to `repo`'s checkout when `repo` is set. */
41
+ docsDir: string;
42
+ /** Repo identity (`org/repo`) the docs live in, for roots outside the project's own repo. */
43
+ repo?: string;
44
+ }
45
+ export interface WeftConfig {
46
+ rootDir: string;
47
+ docsDir: string;
48
+ entryPoint: string;
49
+ ignore: string[];
50
+ /**
51
+ * Multiple docs roots, one per product. When set, node ids are namespaced by
52
+ * project slug (`alpha/api.md`) and `docsDir` is ignored.
53
+ */
54
+ projects?: WeftProject[];
55
+ /**
56
+ * Local checkouts of other repos, keyed by repo identity (`org/repo`).
57
+ *
58
+ * The map does two jobs: a `projects` entry may name a `repo` instead of
59
+ * embedding a relative path, and a GitHub blob URL to a mapped repo resolves
60
+ * against its checkout — becoming a graph edge when the file falls inside a
61
+ * configured docs root.
62
+ *
63
+ * Values are paths — relative to the project root, absolute, or `~`-prefixed.
64
+ * Because they describe one machine's layout, they belong in
65
+ * `weft.config.local.yaml` (gitignored) rather than the committed config;
66
+ * local entries override committed ones per identity.
67
+ */
68
+ repos?: Record<string, string>;
69
+ /** Default theme when no user preference is saved. Falls back to system preference if unset. */
70
+ defaultTheme?: "light" | "dark";
71
+ /**
72
+ * ui-std-lib style: one theme name (fixed scheme, toggle hidden) or a
73
+ * {dark, light} pair the toggle switches between. Defaults to
74
+ * dark=luminous-precision / light=summer-cloud.
75
+ */
76
+ style?: StyleConfig;
77
+ /**
78
+ * Base URL serving ui-std-lib theme CSS and manifest.json (e.g. a jsDelivr
79
+ * styles/ path) — the escape hatch for themes newer than the styles
80
+ * package the UI was built with.
81
+ */
82
+ styleUrl?: string;
83
+ /** Site name used in og:site_name and title fallbacks. */
84
+ siteTitle?: string;
85
+ /** Canonical base URL (e.g. https://docs.example.com) — used to build absolute og:image URLs. */
86
+ siteUrl?: string;
87
+ /** Default og:image path (relative to project root or absolute URL). */
88
+ ogImage?: string;
89
+ /** Layout mode for the UI. "reader" hides the linked-items sidebar. Defaults to "default". */
90
+ layout?: "reader" | "default";
91
+ /** Explicit document order for the LHN. Unlisted docs appear after, in alpha order. */
92
+ docOrder?: string[];
93
+ /** When true, only docs listed in docOrder appear in the LHN. Default false. */
94
+ docOrderStrict?: boolean;
95
+ /** Per-rule severity for the validation stage. "off" disables the rule entirely. */
96
+ rules?: Record<string, RuleSeverity>;
97
+ /**
98
+ * Contribution files an external build writes, as globs relative to the
99
+ * project root. Merged into the manifest after source is indexed.
100
+ */
101
+ contributions?: string[];
102
+ /**
103
+ * Generated outputs to register as nodes, as globs relative to each docs
104
+ * root. A PDF built from a document is not indexable, so without this there
105
+ * is nothing for a `derives-from` edge to point at.
106
+ *
107
+ * Relative to the docs root rather than the project root so ids stay clean
108
+ * and resolvable; an output living elsewhere is declared by a contribution
109
+ * instead.
110
+ */
111
+ artifacts?: string[];
112
+ /**
113
+ * Extra file extensions to index, beyond the built-in defaults, mapped to
114
+ * the doc type each should parse as. Keys carry the leading dot (`.qmd`),
115
+ * matching `EXTENSION_MAP`'s own key style.
116
+ *
117
+ * Additive only: a key already known to `EXTENSION_MAP` with a *different*
118
+ * value is rejected at load time, since silently remapping a built-in
119
+ * extension would change how every already-indexed file of that type
120
+ * parses. A key that agrees with its built-in mapping (`.json: openapi`) is
121
+ * allowed — it only opts an unindexed-by-default type into scanning.
122
+ */
123
+ extensions?: Record<string, "markdown" | "openapi">;
124
+ /**
125
+ * Global defaults for `includes` edges. Each option can be overridden per
126
+ * edge in the sidecar that declares it. Resolved values are stamped onto the
127
+ * edges at build time, so the manifest is self-contained.
128
+ */
129
+ includes?: IncludeDefaults;
130
+ }
131
+ /**
132
+ * How an included section's heading levels relate to the document they land in.
133
+ *
134
+ * `auto` demotes the included headings beneath the heading level at the point
135
+ * of inclusion, so the composed document reads as one outline. `none` preserves
136
+ * the source levels, for sources already authored at the right depth — an FAQ
137
+ * whose answers are all written as `##` sections, say.
138
+ */
139
+ export type IncludeHeadingShift = "auto" | "none";
140
+ /**
141
+ * Where included content counts for search and navigation.
142
+ *
143
+ * `source` attributes it only to the node it came from, so a search never
144
+ * returns duplicate hits. `inline` also attributes it to the including
145
+ * document — a reader searching the FAQ finds the FAQ.
146
+ */
147
+ export type IncludeContributes = "source" | "inline";
148
+ /** Global defaults for include edges, overridable per edge in the sidecar. */
149
+ export interface IncludeDefaults {
150
+ headingShift?: IncludeHeadingShift;
151
+ contributes?: IncludeContributes;
152
+ }
153
+ /** How serious a diagnostic is. Only "error" fails `weft check`. */
154
+ export type Severity = "error" | "warn" | "info";
155
+ /** A rule's configured severity. "off" means the rule does not run. */
156
+ export type RuleSeverity = Severity | "off";
157
+ /**
158
+ * A linkable position within a document.
159
+ *
160
+ * `slug` is the only field an edge matches on — `line`, `level` and `text` exist
161
+ * so a consumer can order, nest, jump to, or recognise an anchor. Notably they
162
+ * let a renamed heading be told apart from a deleted one, which a bare slug
163
+ * cannot express.
164
+ */
165
+ export interface Anchor {
166
+ /** URL fragment including the leading "#", exactly as `LinkRef.anchor` writes it. */
167
+ slug: string;
168
+ /**
169
+ * Text the slug was derived from: the heading as rendered, with inline
170
+ * markup resolved, or the operation id / schema name.
171
+ *
172
+ * Rendered rather than raw because that is what the page slugs, so an id in
173
+ * the document and an anchor in the graph cannot disagree.
174
+ */
175
+ text: string;
176
+ /** 1-based line in the source file. Absent for anchors with no line, such as OpenAPI. */
177
+ line?: number;
178
+ /** Heading level, 1-6. Absent for anchors that are not headings. */
179
+ level?: number;
180
+ }
181
+ export interface WeftNode {
182
+ id: string;
183
+ /**
184
+ * What kind of thing this node is.
185
+ *
186
+ * `artifact` is a generated output — a PDF built from markdown, say. It is a
187
+ * full graph node and a valid edge endpoint, but it is not a document: it has
188
+ * no anchors, nothing to render, and it never appears in navigation. Consumers
189
+ * that read a node's content must skip it, since reading a binary as text
190
+ * succeeds and yields nonsense rather than failing.
191
+ */
192
+ type: "markdown" | "openapi" | "artifact";
193
+ title: string;
194
+ anchors: Anchor[];
195
+ /** Slug of the owning project. Absent in single-project mode. */
196
+ project?: string;
197
+ theme?: "light" | "dark";
198
+ description?: string;
199
+ ogImage?: string;
200
+ /**
201
+ * Excluded from the left-hand nav by `docOrderStrict`. Still a full graph
202
+ * node: reachable by link, search and traversal, and a valid edge endpoint.
203
+ */
204
+ hiddenFromNav?: boolean;
205
+ /**
206
+ * Hash of the document's content, for telling two copies apart and for
207
+ * noticing that a generated output no longer reflects its source.
208
+ *
209
+ * Optional because not every node is indexed from a file — a node declared
210
+ * by an external tool may arrive without one.
211
+ */
212
+ contentHash?: string;
213
+ /**
214
+ * Lines of text in the document, so a claim made about its length can be
215
+ * checked. Absent for nodes that have no lines, such as a binary artifact.
216
+ */
217
+ lineCount?: number;
218
+ /**
219
+ * Version the document declares in its own frontmatter.
220
+ *
221
+ * Declared rather than computed, because only the author knows which edits
222
+ * constitute a new version. Absence is normal and never an error — an
223
+ * append-only registry has no version to give.
224
+ */
225
+ version?: string;
226
+ /**
227
+ * When the document last changed, as an ISO 8601 timestamp with offset.
228
+ *
229
+ * Taken from the last commit touching the file rather than from the
230
+ * filesystem: git does not preserve modification times, so a fresh clone or
231
+ * a CI checkout makes every file look simultaneously modified — meaningless
232
+ * in exactly the environment these checks run in. Absent when the file is
233
+ * untracked, uncommitted, or the project is not a git repository.
234
+ */
235
+ modified?: string;
236
+ }
237
+ /**
238
+ * Claims a link makes about the document it points at, checked against that
239
+ * document's current state.
240
+ *
241
+ * A key-value bag rather than a `version` field, because a mechanism built for
242
+ * version alone needs reopening the first time someone cites a length or a
243
+ * date. Every value is optional, and asserting nothing is the normal case.
244
+ */
245
+ export interface Assertions {
246
+ /** The target's declared version, compared exactly as written. */
247
+ version?: string;
248
+ /**
249
+ * The target's length. A number must match exactly; `"~3500"` allows ten
250
+ * percent either way, for the "roughly N lines" claim prose actually makes.
251
+ */
252
+ lineCount?: number | string;
253
+ /**
254
+ * When the target last changed, as a prefix of its ISO timestamp — `"2026-07"`
255
+ * accepts any day in that month, and a full timestamp matches only itself.
256
+ */
257
+ modified?: string;
258
+ }
259
+ export interface LinkRef {
260
+ node: string;
261
+ anchor?: string;
262
+ }
263
+ export interface WeftEdge {
264
+ from: LinkRef;
265
+ to: LinkRef;
266
+ type: string;
267
+ label?: string;
268
+ /**
269
+ * The link path as written, when it differed from the node it resolved to —
270
+ * a link to a document's published form (`guide.html`) pointing at the source
271
+ * it was rendered from (`guide.md`). Absent when the link already named a node.
272
+ */
273
+ resolvedFrom?: string;
274
+ /**
275
+ * The target is known not to exist yet. Writing a pointer to something you
276
+ * are about to create is normal practice, so validation reports these
277
+ * separately instead of as breakage — but still reports them, so a reference
278
+ * left pending stays visible and countable.
279
+ *
280
+ * Only sidecar links can declare this today; an inline Markdown link has
281
+ * nowhere to put it.
282
+ */
283
+ pending?: boolean;
284
+ /**
285
+ * Claims this link makes about its target. Like `pending`, only a sidecar
286
+ * link can declare them — an inline Markdown link has nowhere to put them.
287
+ */
288
+ asserts?: Assertions;
289
+ /**
290
+ * On an `includes` edge: how the included headings are levelled into the
291
+ * including document. Stamped from config defaults at build time, so a
292
+ * manifest consumer never has to know what the defaults were.
293
+ */
294
+ headingShift?: IncludeHeadingShift;
295
+ /**
296
+ * On an `includes` edge: whether the included content is searchable only
297
+ * under its source node or also under the including document. Stamped from
298
+ * config defaults at build time, like `headingShift`.
299
+ */
300
+ contributes?: IncludeContributes;
301
+ /**
302
+ * On a `derives-from` edge: the source's content hash at the moment the
303
+ * artifact was generated. An artifact is stale when this no longer equals the
304
+ * source's current hash.
305
+ *
306
+ * Kin to `asserts` — both record what was true when written — but kept
307
+ * separate because the finding differs. A stale assertion is fixed by editing
308
+ * the claim; a stale artifact is fixed by regenerating it.
309
+ *
310
+ * Recorded by whatever did the generating, which is the only party that knows
311
+ * it. `hashContent` documents the recipe so a build can compute it without
312
+ * running Weft.
313
+ */
314
+ sourceHash?: string;
315
+ }
316
+ /** Presentation config carried in the manifest so the UI needs no config access. */
317
+ export interface SiteConfig {
318
+ defaultTheme?: "light" | "dark";
319
+ style?: StyleConfig;
320
+ styleUrl?: string;
321
+ layout?: "reader" | "default";
322
+ siteTitle?: string;
323
+ siteUrl?: string;
324
+ ogImage?: string;
325
+ }
326
+ /**
327
+ * Provenance for a manifest — when it was built, and a baseline of what it
328
+ * was built from.
329
+ *
330
+ * Lives on the manifest itself rather than beside it: every consumer that
331
+ * reads `manifest.json` directly (SSR, a static build script) gets one read
332
+ * with no way to end up with a graph and no idea how stale it is.
333
+ */
334
+ export interface ManifestBuild {
335
+ /** When the manifest was built, as an ISO 8601 UTC timestamp (`toISOString()` form). */
336
+ builtAt: string;
337
+ /**
338
+ * Baseline hash of the state the manifest was built from: the sorted set
339
+ * of indexed file and artifact paths, plus the content of every input
340
+ * that is not itself a node — sidecar files, contribution files, and the
341
+ * config files (including the machine-local overlay).
342
+ *
343
+ * Comparing it against a fresh computation catches a node added or
344
+ * removed — document or artifact — or a change to one of those non-node
345
+ * inputs. It does not cover an edited node's content — every node already
346
+ * carries its own `contentHash` for that, so re-hashing it here would be
347
+ * redundant.
348
+ */
349
+ inputsHash: string;
350
+ }
351
+ export interface Manifest {
352
+ version: number;
353
+ nodes: WeftNode[];
354
+ edges: WeftEdge[];
355
+ /** Configured projects. Present only in multi-project mode. */
356
+ projects?: WeftProjectRef[];
357
+ /** Presentation config for the UI. Absent when nothing is configured. */
358
+ site?: SiteConfig;
359
+ /** When and from what this manifest was built. Absent from a pre-freshness manifest. */
360
+ build?: ManifestBuild;
361
+ }
362
+ /** A manifest scoped to one project, written to `<project docsDir>/.weft/manifest.json`. */
363
+ export interface ProjectManifest {
364
+ version: number;
365
+ project: WeftProjectRef;
366
+ nodes: WeftNode[];
367
+ /** Edges originating in this project. Targets may point at other projects. */
368
+ edges: WeftEdge[];
369
+ }
370
+ /** Index of the per-project manifests, written to `<rootDir>/.weft/projects.json`. */
371
+ export interface ProjectsIndex {
372
+ version: number;
373
+ projects: (WeftProjectRef & {
374
+ /** Path to this project's manifest, relative to the project root. */
375
+ manifest: string;
376
+ })[];
377
+ /** Path to the merged manifest, relative to the project root. */
378
+ manifest: string;
379
+ }
380
+ /** Whether a manifest still reflects the docs tree it was built from. */
381
+ export type FreshnessStatus = "fresh" | "stale" | "unknown";
382
+ /**
383
+ * Result of comparing a manifest's recorded provenance against its docs tree.
384
+ *
385
+ * `unknown` is not a hedge — it is the honest answer for a manifest built by
386
+ * an older Weft that carries no `build` block to compare at all. Collapsing
387
+ * it into `fresh` would claim confidence about provenance that was never
388
+ * recorded; collapsing it into `stale` would make every pre-upgrade manifest
389
+ * look broken.
390
+ */
391
+ export interface Freshness {
392
+ status: FreshnessStatus;
393
+ /** When the manifest was built. Absent when `status` is "unknown". */
394
+ builtAt?: string;
395
+ }
396
+ export interface SearchResult {
397
+ id: string;
398
+ title: string;
399
+ anchor?: string;
400
+ score: number;
401
+ match: Record<string, string[]>;
402
+ }
403
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=artifacts.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifacts.test.d.ts","sourceRoot":"","sources":["../../../src/validate/__tests__/artifacts.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,167 @@
1
+ import { resolve } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { describe, expect, it } from "vitest";
4
+ import { buildManifest } from "../../manifest.js";
5
+ import { ValidatorRegistry } from "../registry.js";
6
+ import { artifactValidator } from "../rules/artifacts.js";
7
+ import { validateManifest } from "../run.js";
8
+ const CONFIG = {
9
+ rootDir: "/project",
10
+ docsDir: "docs",
11
+ entryPoint: "docs/README.md",
12
+ ignore: [],
13
+ };
14
+ const CURRENT = "aaaaaaaaaaaaaaaa";
15
+ const OLDER = "bbbbbbbbbbbbbbbb";
16
+ function source(id, contentHash = CURRENT) {
17
+ return { id, type: "markdown", title: id, anchors: [], contentHash };
18
+ }
19
+ /** A source Weft never read, so it carries no hash to compare against. */
20
+ function unhashedSource(id) {
21
+ return { id, type: "markdown", title: id, anchors: [] };
22
+ }
23
+ function artifact(id) {
24
+ return { id, type: "artifact", title: id, anchors: [], hiddenFromNav: true };
25
+ }
26
+ function derives(from, to, extra = {}) {
27
+ return { from: { node: from }, to: { node: to }, type: "derives-from", ...extra };
28
+ }
29
+ /** Run only this validator, so the assertions are about it alone. */
30
+ async function check(manifest, config = CONFIG) {
31
+ const registry = new ValidatorRegistry().register(artifactValidator);
32
+ return validateManifest(manifest, config, registry);
33
+ }
34
+ function graph(nodes, edges) {
35
+ return { version: 2, nodes, edges };
36
+ }
37
+ describe("artifact staleness", () => {
38
+ it("reports nothing when the recorded hash still matches", async () => {
39
+ const manifest = graph([artifact("guide.pdf"), source("guide.md")], [derives("guide.pdf", "guide.md", { sourceHash: CURRENT })]);
40
+ expect((await check(manifest)).diagnostics).toEqual([]);
41
+ });
42
+ it("reports an artifact built from an older source", async () => {
43
+ const manifest = graph([artifact("guide.pdf"), source("guide.md")], [derives("guide.pdf", "guide.md", { sourceHash: OLDER })]);
44
+ const [diagnostic] = (await check(manifest)).diagnostics;
45
+ expect(diagnostic.rule).toBe("artifact-stale");
46
+ expect(diagnostic.message).toBe("guide.pdf was generated from an older guide.md");
47
+ expect(diagnostic.data).toMatchObject({ generatedFrom: OLDER, current: CURRENT });
48
+ });
49
+ it("fails a build, because the stale copy is the one the audience sees", async () => {
50
+ const manifest = graph([artifact("guide.pdf"), source("guide.md")], [derives("guide.pdf", "guide.md", { sourceHash: OLDER })]);
51
+ expect((await check(manifest)).counts.error).toBe(1);
52
+ });
53
+ it("suggests regenerating rather than editing the record", async () => {
54
+ const manifest = graph([artifact("guide.pdf"), source("guide.md")], [derives("guide.pdf", "guide.md", { sourceHash: OLDER })]);
55
+ expect((await check(manifest)).diagnostics[0].hint).toContain("Regenerate guide.pdf");
56
+ });
57
+ it("checks each source of a multi-input artifact on its own", async () => {
58
+ // A stylesheet or template change invalidates an output just as surely as
59
+ // an edit to its document.
60
+ const manifest = graph([artifact("guide.pdf"), source("guide.md"), source("theme.md")], [
61
+ derives("guide.pdf", "guide.md", { sourceHash: CURRENT }),
62
+ derives("guide.pdf", "theme.md", { sourceHash: OLDER }),
63
+ ]);
64
+ const { diagnostics } = await check(manifest);
65
+ expect(diagnostics).toHaveLength(1);
66
+ expect(diagnostics[0].data?.source).toBe("theme.md");
67
+ });
68
+ it("reports every stale artifact, not just the first", async () => {
69
+ const manifest = graph([artifact("a.pdf"), artifact("b.pdf"), source("guide.md")], [
70
+ derives("a.pdf", "guide.md", { sourceHash: OLDER }),
71
+ derives("b.pdf", "guide.md", { sourceHash: OLDER }),
72
+ ]);
73
+ expect((await check(manifest)).counts.error).toBe(2);
74
+ });
75
+ it("can be turned down for a project that regenerates on release", async () => {
76
+ const manifest = graph([artifact("guide.pdf"), source("guide.md")], [derives("guide.pdf", "guide.md", { sourceHash: OLDER })]);
77
+ const result = await check(manifest, { ...CONFIG, rules: { "artifact-stale": "warn" } });
78
+ expect(result.counts).toMatchObject({ error: 0, warn: 1 });
79
+ });
80
+ });
81
+ describe("artifact staleness (what cannot be checked)", () => {
82
+ it("reports a derives-from edge that records no hash", async () => {
83
+ const manifest = graph([artifact("guide.pdf"), source("guide.md")], [derives("guide.pdf", "guide.md")]);
84
+ const [diagnostic] = (await check(manifest)).diagnostics;
85
+ expect(diagnostic.rule).toBe("artifact-source-unrecorded");
86
+ expect(diagnostic.message).toContain("No source hash recorded for guide.pdf");
87
+ });
88
+ it("keeps that at info, so plain modelling is not punished", async () => {
89
+ // `derives-from` is also a reasonable way to say two things are related
90
+ // without asking for the relationship to be checked.
91
+ const manifest = graph([artifact("guide.pdf"), source("guide.md")], [derives("guide.pdf", "guide.md")]);
92
+ expect((await check(manifest)).counts).toMatchObject({ error: 0, warn: 0, info: 1 });
93
+ });
94
+ it("reports a source that has no hash of its own", async () => {
95
+ const manifest = graph([artifact("guide.pdf"), unhashedSource("guide.md")], [derives("guide.pdf", "guide.md", { sourceHash: CURRENT })]);
96
+ const [diagnostic] = (await check(manifest)).diagnostics;
97
+ expect(diagnostic.rule).toBe("artifact-source-unrecorded");
98
+ expect(diagnostic.message).toContain("guide.md has no content hash");
99
+ });
100
+ it("says nothing when the source is not in the graph", async () => {
101
+ // Whether the edge resolves at all is edge-resolution's finding.
102
+ const manifest = graph([artifact("guide.pdf")], [derives("guide.pdf", "gone.md", { sourceHash: OLDER })]);
103
+ expect((await check(manifest)).diagnostics).toEqual([]);
104
+ });
105
+ it("says nothing about a pending derives-from edge", async () => {
106
+ const manifest = graph([artifact("guide.pdf"), source("guide.md")], [derives("guide.pdf", "guide.md", { sourceHash: OLDER, pending: true })]);
107
+ expect((await check(manifest)).diagnostics).toEqual([]);
108
+ });
109
+ it("ignores edges of any other type", async () => {
110
+ const manifest = graph([source("README.md"), source("guide.md")], [{ from: { node: "README.md" }, to: { node: "guide.md" }, type: "references" }]);
111
+ expect((await check(manifest)).diagnostics).toEqual([]);
112
+ });
113
+ it("ignores a sourceHash on an edge that is not derives-from", async () => {
114
+ // The edge type is what gives the hash its meaning; without it there is no
115
+ // claim that one thing was generated from the other.
116
+ const manifest = graph([source("README.md"), source("guide.md")], [
117
+ {
118
+ from: { node: "README.md" },
119
+ to: { node: "guide.md" },
120
+ type: "references",
121
+ sourceHash: OLDER,
122
+ },
123
+ ]);
124
+ expect((await check(manifest)).diagnostics).toEqual([]);
125
+ });
126
+ });
127
+ // Extraction and checking exercised together over real files, since the check is
128
+ // only as good as the edges and hashes the indexer hands it.
129
+ describe("artifact staleness (over a real docs tree)", () => {
130
+ const FIXTURE = resolve(fileURLToPath(import.meta.url), "../../../__fixtures__/artifacts");
131
+ const config = {
132
+ rootDir: FIXTURE,
133
+ docsDir: "docs",
134
+ entryPoint: "docs/README.md",
135
+ ignore: [],
136
+ artifacts: ["**/*.pdf"],
137
+ };
138
+ async function checkFixture() {
139
+ return check(await buildManifest(config), config);
140
+ }
141
+ it("reports the stale artifact and the unrecorded input, by rule", async () => {
142
+ const { diagnostics } = await checkFixture();
143
+ expect(diagnostics.map((d) => d.rule).sort()).toEqual([
144
+ "artifact-source-unrecorded",
145
+ "artifact-stale",
146
+ ]);
147
+ });
148
+ it("fails the build on the stale artifact alone", async () => {
149
+ expect((await checkFixture()).counts).toEqual({ error: 1, warn: 0, info: 1 });
150
+ });
151
+ it("names the artifact and the source it fell behind", async () => {
152
+ const stale = (await checkFixture()).diagnostics.find((d) => d.rule === "artifact-stale");
153
+ expect(stale?.data).toMatchObject({ artifact: "appendix.pdf", source: "appendix.md" });
154
+ });
155
+ it("compares against the source's freshly indexed hash", async () => {
156
+ const manifest = await buildManifest(config);
157
+ const appendix = manifest.nodes.find((n) => n.id === "appendix.md");
158
+ const stale = (await check(manifest, config)).diagnostics.find((d) => d.rule === "artifact-stale");
159
+ expect(stale?.data?.current).toBe(appendix?.contentHash);
160
+ });
161
+ it("leaves the artifact whose recorded hash is current alone", async () => {
162
+ const { diagnostics } = await checkFixture();
163
+ const artifacts = diagnostics.map((d) => d.target.kind === "edge" ? d.target.edge.from.node : "");
164
+ expect(artifacts).not.toContain("handbook.pdf");
165
+ });
166
+ });
167
+ //# sourceMappingURL=artifacts.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifacts.test.js","sourceRoot":"","sources":["../../../src/validate/__tests__/artifacts.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=assertions.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertions.test.d.ts","sourceRoot":"","sources":["../../../src/validate/__tests__/assertions.test.ts"],"names":[],"mappings":""}