@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,38 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ const run = promisify(execFile);
4
+ /**
5
+ * Resolve a GitHub token: `GH_TOKEN`, then `GITHUB_TOKEN`, then `gh auth token`
6
+ * when the GitHub CLI is on PATH. No credential store of our own — anyone with
7
+ * a private repo to fetch already has one of these.
8
+ */
9
+ export async function resolveToken(env = process.env) {
10
+ const fromEnv = env.GH_TOKEN?.trim() || env.GITHUB_TOKEN?.trim();
11
+ if (fromEnv)
12
+ return fromEnv;
13
+ try {
14
+ const { stdout } = await run("gh", ["auth", "token"], { windowsHide: true });
15
+ return stdout.trim() || undefined;
16
+ }
17
+ catch {
18
+ return undefined;
19
+ }
20
+ }
21
+ /**
22
+ * Environment that hands git an Authorization header for github.com.
23
+ *
24
+ * Passed as `GIT_CONFIG_*` variables rather than `-c` arguments or a rewritten
25
+ * remote URL, so the token never lands in a process listing or in the cached
26
+ * clone's `.git/config`.
27
+ */
28
+ export function gitAuthEnv(token) {
29
+ if (!token)
30
+ return {};
31
+ const basic = Buffer.from(`x-access-token:${token}`).toString("base64");
32
+ return {
33
+ GIT_CONFIG_COUNT: "1",
34
+ GIT_CONFIG_KEY_0: "http.https://github.com/.extraheader",
35
+ GIT_CONFIG_VALUE_0: `Authorization: Basic ${basic}`,
36
+ };
37
+ }
38
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/fetch/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEhC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CACjC,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;IACjE,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,IAAI,CAAC;QACJ,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7E,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,KAAyB;IACnD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,kBAAkB,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACxE,OAAO;QACN,gBAAgB,EAAE,GAAG;QACrB,gBAAgB,EAAE,sCAAsC;QACxD,kBAAkB,EAAE,wBAAwB,KAAK,EAAE;KACnD,CAAC;AACH,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * How long a branch's ref→sha resolution is trusted before `ls-remote` runs
3
+ * again. A sha or tag record never expires — the clone it names cannot change.
4
+ */
5
+ export declare const REF_TTL_MS: number;
6
+ /**
7
+ * Root of the fetch cache: `WEFT_CACHE_DIR`, else `$XDG_CACHE_HOME/weft`,
8
+ * else `~/.cache/weft`.
9
+ */
10
+ export declare function cacheRoot(env?: NodeJS.ProcessEnv): string;
11
+ /**
12
+ * Where a fetched repo lands, keyed by resolved commit sha so a moved branch
13
+ * invalidates cleanly: `<cache>/github.com/<org>/<repo>/<sha>`.
14
+ */
15
+ export declare function repoCacheDir(identity: string, sha: string, env?: NodeJS.ProcessEnv): string;
16
+ /**
17
+ * True when a path lies inside the fetch cache — a fetched checkout, which is
18
+ * read-only by construction and never worth watching for edits.
19
+ */
20
+ export declare function isCachePath(absPath: string, env?: NodeJS.ProcessEnv): boolean;
21
+ /** The remembered sha for a ref, or undefined when there is none or it has aged out. */
22
+ export declare function readCachedSha(identity: string, ref: string, env?: NodeJS.ProcessEnv): string | undefined;
23
+ /** Remember a ref resolution for {@link readCachedSha}. */
24
+ export declare function writeCachedSha(identity: string, ref: string, sha: string, movable: boolean, env?: NodeJS.ProcessEnv): void;
25
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/fetch/cache.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,eAAO,MAAM,UAAU,QAAiB,CAAC;AAEzC;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAItE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC3B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,GAAG,GAAE,MAAM,CAAC,UAAwB,GAClC,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAG1F;AAyBD,wFAAwF;AACxF,wBAAgB,aAAa,CAC5B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,GAAG,GAAE,MAAM,CAAC,UAAwB,GAClC,MAAM,GAAG,SAAS,CAKpB;AAED,2DAA2D;AAC3D,wBAAgB,cAAc,CAC7B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,GAAG,GAAE,MAAM,CAAC,UAAwB,GAClC,IAAI,CAMN"}
@@ -0,0 +1,68 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
4
+ /**
5
+ * How long a branch's ref→sha resolution is trusted before `ls-remote` runs
6
+ * again. A sha or tag record never expires — the clone it names cannot change.
7
+ */
8
+ export const REF_TTL_MS = 15 * 60 * 1000;
9
+ /**
10
+ * Root of the fetch cache: `WEFT_CACHE_DIR`, else `$XDG_CACHE_HOME/weft`,
11
+ * else `~/.cache/weft`.
12
+ */
13
+ export function cacheRoot(env = process.env) {
14
+ if (env.WEFT_CACHE_DIR)
15
+ return resolve(env.WEFT_CACHE_DIR);
16
+ const base = env.XDG_CACHE_HOME ? resolve(env.XDG_CACHE_HOME) : join(homedir(), ".cache");
17
+ return join(base, "weft");
18
+ }
19
+ /**
20
+ * Where a fetched repo lands, keyed by resolved commit sha so a moved branch
21
+ * invalidates cleanly: `<cache>/github.com/<org>/<repo>/<sha>`.
22
+ */
23
+ export function repoCacheDir(identity, sha, env = process.env) {
24
+ return join(cacheRoot(env), "github.com", identity, sha);
25
+ }
26
+ /**
27
+ * True when a path lies inside the fetch cache — a fetched checkout, which is
28
+ * read-only by construction and never worth watching for edits.
29
+ */
30
+ export function isCachePath(absPath, env = process.env) {
31
+ const rel = relative(cacheRoot(env), resolve(absPath));
32
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
33
+ }
34
+ function refRecordPath(identity, env) {
35
+ return join(cacheRoot(env), "github.com", identity, "refs.json");
36
+ }
37
+ function readRecords(path) {
38
+ if (!existsSync(path))
39
+ return {};
40
+ try {
41
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
42
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
43
+ return {};
44
+ return parsed;
45
+ }
46
+ catch {
47
+ // An unreadable record only costs one ls-remote.
48
+ return {};
49
+ }
50
+ }
51
+ /** The remembered sha for a ref, or undefined when there is none or it has aged out. */
52
+ export function readCachedSha(identity, ref, env = process.env) {
53
+ const record = readRecords(refRecordPath(identity, env))[ref];
54
+ if (!record?.sha)
55
+ return undefined;
56
+ if (record.movable && Date.now() - Date.parse(record.resolvedAt) > REF_TTL_MS)
57
+ return undefined;
58
+ return record.sha;
59
+ }
60
+ /** Remember a ref resolution for {@link readCachedSha}. */
61
+ export function writeCachedSha(identity, ref, sha, movable, env = process.env) {
62
+ const path = refRecordPath(identity, env);
63
+ const records = readRecords(path);
64
+ records[ref] = { sha, resolvedAt: new Date().toISOString(), movable };
65
+ mkdirSync(dirname(path), { recursive: true });
66
+ writeFileSync(path, JSON.stringify(records, null, 2));
67
+ }
68
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/fetch/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cache.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.d.ts","sourceRoot":"","sources":["../../src/fetch/cache.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,73 @@
1
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join, resolve } from "node:path";
4
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
5
+ import { gitAuthEnv, resolveToken } from "./auth.js";
6
+ import { REF_TTL_MS, cacheRoot, isCachePath, readCachedSha, repoCacheDir, writeCachedSha, } from "./cache.js";
7
+ const SHA = "a".repeat(40);
8
+ let tmp;
9
+ let env;
10
+ beforeAll(() => {
11
+ tmp = mkdtempSync(join(tmpdir(), "weft-fetch-cache-"));
12
+ env = { WEFT_CACHE_DIR: tmp };
13
+ });
14
+ afterAll(() => rmSync(tmp, { recursive: true, force: true }));
15
+ describe("resolveToken", () => {
16
+ it("prefers GH_TOKEN over GITHUB_TOKEN", async () => {
17
+ await expect(resolveToken({ GH_TOKEN: "gh", GITHUB_TOKEN: "hub" })).resolves.toBe("gh");
18
+ await expect(resolveToken({ GITHUB_TOKEN: "hub" })).resolves.toBe("hub");
19
+ });
20
+ it("ignores a blank variable", async () => {
21
+ await expect(resolveToken({ GH_TOKEN: " ", GITHUB_TOKEN: "hub" })).resolves.toBe("hub");
22
+ });
23
+ });
24
+ describe("gitAuthEnv", () => {
25
+ it("scopes a basic Authorization header to github.com via GIT_CONFIG variables", () => {
26
+ const authEnv = gitAuthEnv("t0ken");
27
+ expect(authEnv.GIT_CONFIG_KEY_0).toBe("http.https://github.com/.extraheader");
28
+ expect(authEnv.GIT_CONFIG_VALUE_0).toBe(`Authorization: Basic ${Buffer.from("x-access-token:t0ken").toString("base64")}`);
29
+ });
30
+ it("is empty without a token", () => {
31
+ expect(gitAuthEnv(undefined)).toEqual({});
32
+ expect(gitAuthEnv("")).toEqual({});
33
+ });
34
+ });
35
+ describe("cache layout", () => {
36
+ it("honors WEFT_CACHE_DIR, then XDG_CACHE_HOME", () => {
37
+ expect(cacheRoot({ WEFT_CACHE_DIR: tmp })).toBe(resolve(tmp));
38
+ expect(cacheRoot({ XDG_CACHE_HOME: tmp })).toBe(join(resolve(tmp), "weft"));
39
+ });
40
+ it("keys a checkout by host, identity and sha", () => {
41
+ expect(repoCacheDir("acme/alpha", SHA, env)).toBe(join(tmp, "github.com", "acme/alpha", SHA));
42
+ });
43
+ it("recognizes paths inside the cache and only those", () => {
44
+ expect(isCachePath(join(tmp, "github.com", "acme", "alpha", SHA), env)).toBe(true);
45
+ expect(isCachePath(tmp, env)).toBe(false);
46
+ expect(isCachePath(join(tmpdir(), "elsewhere"), env)).toBe(false);
47
+ });
48
+ });
49
+ describe("ref records", () => {
50
+ it("round-trips a resolution", () => {
51
+ writeCachedSha("acme/alpha", "v1", SHA, false, env);
52
+ expect(readCachedSha("acme/alpha", "v1", env)).toBe(SHA);
53
+ });
54
+ it("expires a branch resolution after the TTL, but never a tag's", () => {
55
+ const stale = new Date(Date.now() - REF_TTL_MS - 1000).toISOString();
56
+ const path = join(tmp, "github.com", "acme/beta", "refs.json");
57
+ mkdirSync(join(tmp, "github.com", "acme/beta"), { recursive: true });
58
+ writeFileSync(path, JSON.stringify({
59
+ main: { sha: SHA, resolvedAt: stale, movable: true },
60
+ v1: { sha: SHA, resolvedAt: stale, movable: false },
61
+ }));
62
+ expect(readCachedSha("acme/beta", "main", env)).toBeUndefined();
63
+ expect(readCachedSha("acme/beta", "v1", env)).toBe(SHA);
64
+ });
65
+ it("returns undefined for an unknown ref or unreadable record", () => {
66
+ expect(readCachedSha("acme/alpha", "nope", env)).toBeUndefined();
67
+ const path = join(tmp, "github.com", "acme/gamma", "refs.json");
68
+ mkdirSync(join(tmp, "github.com", "acme/gamma"), { recursive: true });
69
+ writeFileSync(path, "not json");
70
+ expect(readCachedSha("acme/gamma", "main", env)).toBeUndefined();
71
+ });
72
+ });
73
+ //# sourceMappingURL=cache.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.js","sourceRoot":"","sources":["../../src/fetch/cache.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /** The HTTPS clone URL for a repo identity. */
2
+ export declare function githubUrl(identity: string): string;
3
+ /** A resolved remote ref. `movable` is true when it named a branch (or HEAD). */
4
+ export interface ResolvedRef {
5
+ sha: string;
6
+ movable: boolean;
7
+ }
8
+ /**
9
+ * Resolve a ref to a commit sha with `ls-remote`. No ref means the remote HEAD.
10
+ * A full sha resolves to itself without touching the network.
11
+ */
12
+ export declare function resolveRemoteRef(url: string, ref: string | undefined, token?: string): Promise<ResolvedRef>;
13
+ /**
14
+ * Materialize a repo at a commit into `dir` as a blobless partial clone.
15
+ *
16
+ * `--filter=blob:none` keeps every commit and tree, so `git log` — and with it
17
+ * every `modified` date and history-reading rule — answers exactly as it would
18
+ * over a full checkout; only file content is fetched on demand at checkout.
19
+ * A tarball would be smaller and silently date-less, the failure mode the
20
+ * issue tracker calls out.
21
+ *
22
+ * Idempotent per directory: a completed clone is reused, an interrupted one
23
+ * is discarded and redone.
24
+ */
25
+ export declare function cloneAtSha(url: string, sha: string, dir: string, token?: string): Promise<void>;
26
+ //# sourceMappingURL=clone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone.d.ts","sourceRoot":"","sources":["../../src/fetch/clone.ts"],"names":[],"mappings":"AAiBA,+CAA+C;AAC/C,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAElD;AA6BD,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,KAAK,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,WAAW,CAAC,CA6BtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAC/B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAkBf"}
@@ -0,0 +1,105 @@
1
+ import { execFile } from "node:child_process";
2
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { promisify } from "node:util";
5
+ import { gitAuthEnv } from "./auth.js";
6
+ const exec = promisify(execFile);
7
+ /** A full object id, which needs no ls-remote to resolve. */
8
+ const FULL_SHA = /^[0-9a-f]{40}$/;
9
+ /**
10
+ * Marks a cache entry whose clone ran to completion. Written last, so an
11
+ * interrupted clone leaves a directory that reads as absent and is redone.
12
+ */
13
+ const COMPLETE_MARKER = "weft-complete";
14
+ /** The HTTPS clone URL for a repo identity. */
15
+ export function githubUrl(identity) {
16
+ return `https://github.com/${identity}.git`;
17
+ }
18
+ async function git(args, token) {
19
+ const { stdout } = await exec("git", args, {
20
+ windowsHide: true,
21
+ // Never prompt for credentials — fail instead, so the error below can say
22
+ // what to set.
23
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0", ...gitAuthEnv(token) },
24
+ });
25
+ return stdout;
26
+ }
27
+ /**
28
+ * GitHub reports a private repo it will not serve exactly as it reports a repo
29
+ * that does not exist, so the error has to say both.
30
+ */
31
+ function fetchError(what, token, cause) {
32
+ const stderr = cause?.stderr?.trim();
33
+ return new Error([
34
+ `weft fetch: could not fetch ${what} — the repository was not found, or you do not have access.`,
35
+ token
36
+ ? "A token was supplied; check that it can read this repository."
37
+ : "For a private repository, set GH_TOKEN or GITHUB_TOKEN, or run `gh auth login`.",
38
+ ...(stderr ? [stderr] : []),
39
+ ].join("\n"));
40
+ }
41
+ /**
42
+ * Resolve a ref to a commit sha with `ls-remote`. No ref means the remote HEAD.
43
+ * A full sha resolves to itself without touching the network.
44
+ */
45
+ export async function resolveRemoteRef(url, ref, token) {
46
+ if (ref && FULL_SHA.test(ref))
47
+ return { sha: ref, movable: false };
48
+ const patterns = ref ? [ref, `${ref}^{}`] : ["HEAD"];
49
+ let stdout;
50
+ try {
51
+ stdout = await git(["ls-remote", url, ...patterns], token);
52
+ }
53
+ catch (err) {
54
+ throw fetchError(ref ? `${url} at "${ref}"` : url, token, err);
55
+ }
56
+ const lines = stdout
57
+ .split("\n")
58
+ .filter(Boolean)
59
+ .map((line) => line.split("\t"));
60
+ if (lines.length === 0) {
61
+ throw fetchError(`${url} at "${ref ?? "HEAD"}" (no such ref)`, token, undefined);
62
+ }
63
+ const byName = new Map(lines.map(([sha, name]) => [name, sha]));
64
+ const branch = ref ? byName.get(`refs/heads/${ref}`) : byName.get("HEAD");
65
+ // The peeled entry first: an annotated tag's own sha is not a commit.
66
+ const sha = branch ??
67
+ byName.get(`refs/tags/${ref}^{}`) ??
68
+ byName.get(`refs/tags/${ref}`) ??
69
+ byName.get(ref) ??
70
+ lines[0][0];
71
+ return { sha, movable: branch !== undefined };
72
+ }
73
+ /**
74
+ * Materialize a repo at a commit into `dir` as a blobless partial clone.
75
+ *
76
+ * `--filter=blob:none` keeps every commit and tree, so `git log` — and with it
77
+ * every `modified` date and history-reading rule — answers exactly as it would
78
+ * over a full checkout; only file content is fetched on demand at checkout.
79
+ * A tarball would be smaller and silently date-less, the failure mode the
80
+ * issue tracker calls out.
81
+ *
82
+ * Idempotent per directory: a completed clone is reused, an interrupted one
83
+ * is discarded and redone.
84
+ */
85
+ export async function cloneAtSha(url, sha, dir, token) {
86
+ if (existsSync(join(dir, ".git", COMPLETE_MARKER)))
87
+ return;
88
+ rmSync(dir, { recursive: true, force: true });
89
+ mkdirSync(dirname(dir), { recursive: true });
90
+ try {
91
+ await git(["init", "-q", dir], token);
92
+ await git(["-C", dir, "remote", "add", "origin", url], token);
93
+ // Fetching the sha itself (GitHub allows reachable-sha-in-want) rather
94
+ // than a ref name, so the checkout is exactly what ls-remote resolved
95
+ // even if the branch has moved since.
96
+ await git(["-C", dir, "fetch", "-q", "--filter=blob:none", "origin", sha], token);
97
+ await git(["-C", dir, "-c", "advice.detachedHead=false", "checkout", "-q", sha], token);
98
+ }
99
+ catch (err) {
100
+ rmSync(dir, { recursive: true, force: true });
101
+ throw fetchError(`${url} at ${sha}`, token, err);
102
+ }
103
+ writeFileSync(join(dir, ".git", COMPLETE_MARKER), "");
104
+ }
105
+ //# sourceMappingURL=clone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone.js","sourceRoot":"","sources":["../../src/fetch/clone.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=fetch.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.test.d.ts","sourceRoot":"","sources":["../../src/fetch/fetch.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,167 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
7
+ import { lastCommitDates } from "../git.js";
8
+ import { buildManifest } from "../manifest.js";
9
+ import { repoCacheDir } from "./cache.js";
10
+ import { cloneAtSha, resolveRemoteRef } from "./clone.js";
11
+ import { fetchRepo, resolveFetchedRepos } from "./resolve.js";
12
+ /**
13
+ * The whole fetch path against a local `file://` remote: ref resolution,
14
+ * blobless cloning with history intact, cache reuse, and filling a config's
15
+ * `repos` gaps by fetching — with a real local checkout still winning.
16
+ */
17
+ const COMMIT_DATE = "2026-03-04T00:00:00+00:00";
18
+ let workspace;
19
+ let remote;
20
+ let remoteUrl;
21
+ let cacheDir;
22
+ let env;
23
+ let headSha;
24
+ /** file:// transport, no token, cache under the workspace. */
25
+ const opts = () => ({ token: "", urlFor: () => remoteUrl, env });
26
+ function git(cwd, ...args) {
27
+ return execFileSync("git", args, { cwd, encoding: "utf8" }).trim();
28
+ }
29
+ beforeAll(() => {
30
+ workspace = mkdtempSync(join(tmpdir(), "weft-fetch-"));
31
+ cacheDir = join(workspace, "cache");
32
+ env = { WEFT_CACHE_DIR: cacheDir };
33
+ remote = join(workspace, "remote");
34
+ mkdirSync(join(remote, "docs"), { recursive: true });
35
+ writeFileSync(join(remote, "docs", "README.md"), "# Fetched\n\n[Guide](guide.md)\n");
36
+ writeFileSync(join(remote, "docs", "guide.md"), "# Guide\n");
37
+ writeFileSync(join(remote, "weft.config.yaml"), "docsDir: docs\n");
38
+ git(remote, "init", "-q");
39
+ git(remote, "config", "user.email", "test@example.com");
40
+ git(remote, "config", "user.name", "Test");
41
+ git(remote, "config", "commit.gpgsign", "false");
42
+ // What GitHub's servers allow: partial clones, and fetching by sha.
43
+ git(remote, "config", "uploadpack.allowFilter", "true");
44
+ git(remote, "config", "uploadpack.allowReachableSHA1InWant", "true");
45
+ git(remote, "add", "-A");
46
+ git(remote, "commit", "-q", "-m", "init", "--date", COMMIT_DATE);
47
+ git(remote, "tag", "-a", "v1", "-m", "v1");
48
+ headSha = git(remote, "rev-parse", "HEAD");
49
+ remoteUrl = pathToFileURL(remote).href;
50
+ });
51
+ afterAll(() => rmSync(workspace, { recursive: true, force: true }));
52
+ describe("resolveRemoteRef", () => {
53
+ it("resolves HEAD when no ref is given, as movable", async () => {
54
+ await expect(resolveRemoteRef(remoteUrl, undefined)).resolves.toEqual({
55
+ sha: headSha,
56
+ movable: true,
57
+ });
58
+ });
59
+ it("resolves a branch as movable and an annotated tag to its commit, immovable", async () => {
60
+ const branch = git(remote, "branch", "--show-current");
61
+ await expect(resolveRemoteRef(remoteUrl, branch)).resolves.toEqual({
62
+ sha: headSha,
63
+ movable: true,
64
+ });
65
+ await expect(resolveRemoteRef(remoteUrl, "v1")).resolves.toEqual({
66
+ sha: headSha,
67
+ movable: false,
68
+ });
69
+ });
70
+ it("passes a full sha through without touching the network", async () => {
71
+ await expect(resolveRemoteRef("https://invalid.invalid/none.git", headSha)).resolves.toEqual({
72
+ sha: headSha,
73
+ movable: false,
74
+ });
75
+ });
76
+ it("says not-found and no-access are indistinguishable, and how to authenticate", async () => {
77
+ const missing = pathToFileURL(join(workspace, "no-such-repo")).href;
78
+ await expect(resolveRemoteRef(missing, undefined)).rejects.toThrow(/not found.*access/s);
79
+ await expect(resolveRemoteRef(missing, undefined)).rejects.toThrow(/GH_TOKEN/);
80
+ });
81
+ it("reports a ref the remote does not have", async () => {
82
+ await expect(resolveRemoteRef(remoteUrl, "no-such-ref")).rejects.toThrow(/no such ref/);
83
+ });
84
+ });
85
+ describe("cloneAtSha", () => {
86
+ it("materializes the tree with its git history intact", async () => {
87
+ const dir = join(workspace, "clone");
88
+ await cloneAtSha(remoteUrl, headSha, dir);
89
+ expect(existsSync(join(dir, "docs", "README.md"))).toBe(true);
90
+ // The blobless clone still answers `git log`, so `modified` dates survive
91
+ // — the property that ruled out tarballs.
92
+ const dates = await lastCommitDates(join(dir, "docs"));
93
+ expect(Date.parse(dates.get("README.md"))).toBe(Date.parse(COMMIT_DATE));
94
+ });
95
+ it("reuses a completed clone without re-fetching", async () => {
96
+ const dir = join(workspace, "clone");
97
+ const sentinel = join(dir, "sentinel");
98
+ writeFileSync(sentinel, "");
99
+ await cloneAtSha("https://invalid.invalid/none.git", headSha, dir);
100
+ expect(existsSync(sentinel)).toBe(true);
101
+ });
102
+ });
103
+ describe("fetchRepo and resolveFetchedRepos", () => {
104
+ it("fetches into the sha-keyed cache and remembers the resolution", async () => {
105
+ const dir = await fetchRepo("acme/fetched", opts());
106
+ expect(dir).toBe(repoCacheDir("acme/fetched", headSha, env));
107
+ expect(existsSync(join(dir, "docs", "guide.md"))).toBe(true);
108
+ // A second fetch resolves from the record and reuses the clone.
109
+ await expect(fetchRepo("acme/fetched", { ...opts(), urlFor: () => "file:///nope" })).resolves.toBe(dir);
110
+ });
111
+ it("fills repos gaps by fetching, and indexes the fetched root with dates", async () => {
112
+ const meta = join(workspace, "meta");
113
+ mkdirSync(join(meta, "docs"), { recursive: true });
114
+ writeFileSync(join(meta, "docs", "README.md"), "# Meta\n");
115
+ const config = {
116
+ rootDir: meta,
117
+ docsDir: "docs",
118
+ entryPoint: "docs/README.md",
119
+ ignore: [],
120
+ projects: [
121
+ { name: "Meta", docsDir: "docs" },
122
+ { name: "Fetched", docsDir: "docs", repo: "acme/fetched" },
123
+ ],
124
+ };
125
+ const resolved = await resolveFetchedRepos(config, opts());
126
+ expect(resolved.repos?.["acme/fetched"]).toBe(repoCacheDir("acme/fetched", headSha, env));
127
+ const manifest = await buildManifest(resolved);
128
+ const node = manifest.nodes.find((n) => n.id === "fetched/guide.md");
129
+ expect(node).toBeDefined();
130
+ expect(Date.parse(node?.modified)).toBe(Date.parse(COMMIT_DATE));
131
+ });
132
+ it("keeps a real local checkout over fetching", async () => {
133
+ const local = join(workspace, "local-alpha");
134
+ mkdirSync(join(local, "docs"), { recursive: true });
135
+ const config = {
136
+ rootDir: workspace,
137
+ docsDir: "docs",
138
+ entryPoint: "docs/README.md",
139
+ ignore: [],
140
+ repos: { "acme/alpha": local },
141
+ projects: [{ name: "Alpha", docsDir: "docs", repo: "acme/alpha" }],
142
+ };
143
+ // urlFor throws, proving no fetch is attempted for the mapped repo.
144
+ const resolved = await resolveFetchedRepos(config, {
145
+ ...opts(),
146
+ urlFor: () => {
147
+ throw new Error("should not fetch");
148
+ },
149
+ });
150
+ expect(resolved).toBe(config);
151
+ });
152
+ it("fetches a mapped repo whose local path does not exist", async () => {
153
+ const config = {
154
+ rootDir: workspace,
155
+ docsDir: "docs",
156
+ entryPoint: "docs/README.md",
157
+ ignore: [],
158
+ repos: { "acme/fetched": join(workspace, "missing-checkout") },
159
+ };
160
+ const resolved = await resolveFetchedRepos(config, opts());
161
+ expect(resolved.repos?.["acme/fetched"]).toBe(repoCacheDir("acme/fetched", headSha, env));
162
+ });
163
+ it("rejects a malformed identity", async () => {
164
+ await expect(fetchRepo("not-an-identity", opts())).rejects.toThrow(/org\/repo/);
165
+ });
166
+ });
167
+ //# sourceMappingURL=fetch.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.test.js","sourceRoot":"","sources":["../../src/fetch/fetch.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { WeftConfig } from "../types.js";
2
+ /** How a fetch run resolves refs, credentials and cache placement. */
3
+ export interface FetchOptions {
4
+ /** Ref to fetch — branch, tag or full sha. Defaults to the remote HEAD. */
5
+ ref?: string;
6
+ /** Re-resolve refs even when a cached resolution is still fresh. */
7
+ refresh?: boolean;
8
+ /** Token to authenticate with. Undefined means resolve one; "" means none. */
9
+ token?: string;
10
+ /** Clone URL per identity. A test seam; defaults to github.com HTTPS. */
11
+ urlFor?: (identity: string) => string;
12
+ /** Environment for cache placement and token lookup. Defaults to process.env. */
13
+ env?: NodeJS.ProcessEnv;
14
+ }
15
+ /**
16
+ * Fetch a repo into the cache and return the checkout's absolute path.
17
+ *
18
+ * Resolution is remembered per ref (with a TTL for branches) and the clone is
19
+ * keyed by commit sha, so repeated serves of an unmoved ref cost one
20
+ * `ls-remote` at most and no clone.
21
+ */
22
+ export declare function fetchRepo(identity: string, opts?: FetchOptions): Promise<string>;
23
+ /**
24
+ * Fill the gaps in `config.repos` by fetching, and return the config with the
25
+ * fetched checkout paths in place.
26
+ *
27
+ * A repo mapped to a real local path keeps winning — fetching is the fallback,
28
+ * not the override — so someone with three of five repos checked out reads
29
+ * their local working trees for those three and fetched copies of the rest.
30
+ * Referenced repos are fetched at their remote HEAD; a ref in `opts` names a
31
+ * ref of the primary repo, not of everything it references.
32
+ */
33
+ export declare function resolveFetchedRepos(config: WeftConfig, opts?: FetchOptions): Promise<WeftConfig>;
34
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/fetch/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9C,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC5B,2EAA2E;IAC3E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmB1F;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACxC,MAAM,EAAE,UAAU,EAClB,IAAI,GAAE,YAAiB,GACrB,OAAO,CAAC,UAAU,CAAC,CAgBrB"}