docs-cache 0.5.4 → 0.5.5
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.
- package/README.md +3 -1
- package/dist/esm/git/fetch-source.mjs +45 -28
- package/dist/esm/git/git-env.d.ts +3 -0
- package/dist/esm/git/git-env.mjs +33 -0
- package/dist/esm/git/resolve-remote.mjs +6 -6
- package/package.json +135 -138
package/README.md
CHANGED
|
@@ -100,10 +100,12 @@ These fields can be set in `defaults` and are inherited by every source unless o
|
|
|
100
100
|
| `maxBytes` | Maximum total bytes to materialize. Default: `200000000` (200 MB). |
|
|
101
101
|
| `maxFiles` | Maximum total files to materialize. |
|
|
102
102
|
| `ignoreHidden` | Skip hidden files and directories (dotfiles). Default: `false`. |
|
|
103
|
-
| `allowHosts` | Allowed Git hosts. Default: `["github.com", "gitlab.com", "visualstudio.com"]`.
|
|
103
|
+
| `allowHosts` | Allowed Git hosts. Default: `["github.com", "gitlab.com", "visualstudio.com"]`. |
|
|
104
104
|
| `toc` | Generate per-source `TOC.md`. Default: `true`. Supports `true`, `false`, or a format: `"tree"` (human readable), `"compressed"` |
|
|
105
105
|
| `unwrapSingleRootDir` | If the materialized output is nested under a single directory, unwrap it (recursively). Default: `true`. |
|
|
106
106
|
|
|
107
|
+
> Brace expansion in `include` supports comma-separated lists (including multiple groups) like `**/*.{md,mdx}` and is capped at 500 expanded patterns per include entry. It does not support nested braces or numeric ranges.
|
|
108
|
+
|
|
107
109
|
### Source options
|
|
108
110
|
|
|
109
111
|
#### Required
|
|
@@ -7,36 +7,12 @@ import { execa } from "execa";
|
|
|
7
7
|
import { getErrnoCode } from "#core/errors";
|
|
8
8
|
import { assertSafeSourceId } from "#core/source-id";
|
|
9
9
|
import { exists, resolveGitCacheDir } from "#git/cache-dir";
|
|
10
|
+
import { buildGitEnv, resolveGitCommand } from "#git/git-env";
|
|
10
11
|
const DEFAULT_TIMEOUT_MS = 12e4;
|
|
11
12
|
const DEFAULT_GIT_DEPTH = 1;
|
|
12
13
|
const DEFAULT_RM_RETRIES = 3;
|
|
13
14
|
const DEFAULT_RM_BACKOFF_MS = 100;
|
|
14
|
-
const
|
|
15
|
-
const pathValue = process.env.PATH ?? process.env.Path;
|
|
16
|
-
const pathExtValue = process.env.PATHEXT ?? (process.platform === "win32" ? ".COM;.EXE;.BAT;.CMD" : void 0);
|
|
17
|
-
return {
|
|
18
|
-
...process.env,
|
|
19
|
-
...pathValue ? { PATH: pathValue, Path: pathValue } : {},
|
|
20
|
-
...pathExtValue ? { PATHEXT: pathExtValue } : {},
|
|
21
|
-
HOME: process.env.HOME,
|
|
22
|
-
USER: process.env.USER,
|
|
23
|
-
USERPROFILE: process.env.USERPROFILE,
|
|
24
|
-
TMPDIR: process.env.TMPDIR,
|
|
25
|
-
TMP: process.env.TMP,
|
|
26
|
-
TEMP: process.env.TEMP,
|
|
27
|
-
SYSTEMROOT: process.env.SYSTEMROOT,
|
|
28
|
-
WINDIR: process.env.WINDIR,
|
|
29
|
-
SSH_AUTH_SOCK: process.env.SSH_AUTH_SOCK,
|
|
30
|
-
SSH_AGENT_PID: process.env.SSH_AGENT_PID,
|
|
31
|
-
HTTP_PROXY: process.env.HTTP_PROXY,
|
|
32
|
-
HTTPS_PROXY: process.env.HTTPS_PROXY,
|
|
33
|
-
NO_PROXY: process.env.NO_PROXY,
|
|
34
|
-
GIT_TERMINAL_PROMPT: "0",
|
|
35
|
-
GIT_CONFIG_NOSYSTEM: "1",
|
|
36
|
-
GIT_CONFIG_NOGLOBAL: "1",
|
|
37
|
-
...process.platform === "win32" ? {} : { GIT_ASKPASS: "/bin/false" }
|
|
38
|
-
};
|
|
39
|
-
};
|
|
15
|
+
const MAX_BRACE_EXPANSIONS = 500;
|
|
40
16
|
const buildGitConfigs = (allowFileProtocol) => [
|
|
41
17
|
"-c",
|
|
42
18
|
"core.hooksPath=/dev/null",
|
|
@@ -91,7 +67,7 @@ const git = async (args, options) => {
|
|
|
91
67
|
);
|
|
92
68
|
const commandLabel = `git ${commandArgs.join(" ")}`;
|
|
93
69
|
options?.logger?.(commandLabel);
|
|
94
|
-
const subprocess = execa(
|
|
70
|
+
const subprocess = execa(resolveGitCommand(), commandArgs, {
|
|
95
71
|
cwd: options?.cwd,
|
|
96
72
|
timeout: options?.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
97
73
|
maxBuffer: 10 * 1024 * 1024,
|
|
@@ -178,7 +154,48 @@ const ensureCommitAvailable = async (repoPath, commit, options) => {
|
|
|
178
154
|
});
|
|
179
155
|
};
|
|
180
156
|
const patternHasGlob = (pattern) => pattern.includes("*") || pattern.includes("?") || pattern.includes("[");
|
|
181
|
-
const
|
|
157
|
+
const expandBracePattern = (pattern) => {
|
|
158
|
+
const results = [];
|
|
159
|
+
const expand = (value) => {
|
|
160
|
+
const braceMatch = value.match(/^(.*?){([^}]+)}(.*)$/);
|
|
161
|
+
if (!braceMatch) {
|
|
162
|
+
if (results.length >= MAX_BRACE_EXPANSIONS) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
`Brace expansion exceeded ${MAX_BRACE_EXPANSIONS} patterns for '${pattern}'.`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
results.push(value);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const [, prefix, values, suffix] = braceMatch;
|
|
171
|
+
const valueList = values.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
172
|
+
if (valueList.length === 0) {
|
|
173
|
+
if (results.length >= MAX_BRACE_EXPANSIONS) {
|
|
174
|
+
throw new Error(
|
|
175
|
+
`Brace expansion exceeded ${MAX_BRACE_EXPANSIONS} patterns for '${pattern}'.`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
results.push(value);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
for (const entry of valueList) {
|
|
182
|
+
const expandedPattern = `${prefix}${entry}${suffix}`;
|
|
183
|
+
expand(expandedPattern);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
expand(pattern);
|
|
187
|
+
return results;
|
|
188
|
+
};
|
|
189
|
+
const normalizeSparsePatterns = (include) => {
|
|
190
|
+
const patterns = include ?? [];
|
|
191
|
+
const expanded = [];
|
|
192
|
+
for (const pattern of patterns) {
|
|
193
|
+
const normalized = pattern.replace(/\\/g, "/");
|
|
194
|
+
if (!normalized) continue;
|
|
195
|
+
expanded.push(...expandBracePattern(normalized));
|
|
196
|
+
}
|
|
197
|
+
return expanded;
|
|
198
|
+
};
|
|
182
199
|
const isDirectoryLiteral = (pattern) => pattern.endsWith("/");
|
|
183
200
|
const toNoConePattern = (pattern) => {
|
|
184
201
|
if (!patternHasGlob(pattern) && isDirectoryLiteral(pattern)) {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const resolveGitCommand = () => {
|
|
2
|
+
const override = process.env.DOCS_CACHE_GIT_COMMAND;
|
|
3
|
+
if (override) {
|
|
4
|
+
return override;
|
|
5
|
+
}
|
|
6
|
+
return "git";
|
|
7
|
+
};
|
|
8
|
+
const buildGitEnv = () => {
|
|
9
|
+
const pathValue = process.env.PATH ?? process.env.Path;
|
|
10
|
+
const pathExtValue = process.env.PATHEXT ?? (process.platform === "win32" ? ".COM;.EXE;.BAT;.CMD" : void 0);
|
|
11
|
+
return {
|
|
12
|
+
...process.env,
|
|
13
|
+
...pathValue ? { PATH: pathValue, Path: pathValue } : {},
|
|
14
|
+
...pathExtValue ? { PATHEXT: pathExtValue } : {},
|
|
15
|
+
HOME: process.env.HOME,
|
|
16
|
+
USER: process.env.USER,
|
|
17
|
+
USERPROFILE: process.env.USERPROFILE,
|
|
18
|
+
TMPDIR: process.env.TMPDIR,
|
|
19
|
+
TMP: process.env.TMP,
|
|
20
|
+
TEMP: process.env.TEMP,
|
|
21
|
+
SYSTEMROOT: process.env.SYSTEMROOT,
|
|
22
|
+
WINDIR: process.env.WINDIR,
|
|
23
|
+
SSH_AUTH_SOCK: process.env.SSH_AUTH_SOCK,
|
|
24
|
+
SSH_AGENT_PID: process.env.SSH_AGENT_PID,
|
|
25
|
+
HTTP_PROXY: process.env.HTTP_PROXY,
|
|
26
|
+
HTTPS_PROXY: process.env.HTTPS_PROXY,
|
|
27
|
+
NO_PROXY: process.env.NO_PROXY,
|
|
28
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
29
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
30
|
+
...process.platform === "win32" ? {} : { GIT_ASKPASS: "/bin/false" }
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export { buildGitEnv, resolveGitCommand };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import { buildGitEnv, resolveGitCommand } from "#git/git-env";
|
|
3
3
|
import { redactRepoUrl } from "#git/redact";
|
|
4
|
-
const execFileAsync = promisify(execFile);
|
|
5
4
|
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
6
5
|
const BLOCKED_PROTOCOLS = /* @__PURE__ */ new Set(["file:", "ftp:", "data:", "javascript:"]);
|
|
7
6
|
const assertAllowedProtocol = (repo) => {
|
|
@@ -65,12 +64,13 @@ export const resolveRemoteCommit = async (params) => {
|
|
|
65
64
|
enforceHostAllowlist(params.repo, params.allowHosts);
|
|
66
65
|
const repoLabel = redactRepoUrl(params.repo);
|
|
67
66
|
params.logger?.(`git ls-remote ${repoLabel} ${params.ref}`);
|
|
68
|
-
const { stdout } = await
|
|
69
|
-
|
|
67
|
+
const { stdout } = await execa(
|
|
68
|
+
resolveGitCommand(),
|
|
70
69
|
["ls-remote", params.repo, params.ref],
|
|
71
70
|
{
|
|
72
71
|
timeout: params.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
73
|
-
maxBuffer: 1024 * 1024
|
|
72
|
+
maxBuffer: 1024 * 1024,
|
|
73
|
+
env: buildGitEnv()
|
|
74
74
|
}
|
|
75
75
|
);
|
|
76
76
|
const resolvedCommit = parseLsRemote(stdout);
|
package/package.json
CHANGED
|
@@ -1,139 +1,136 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
]
|
|
138
|
-
}
|
|
139
|
-
}
|
|
2
|
+
"name": "docs-cache",
|
|
3
|
+
"private": false,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"version": "0.5.5",
|
|
6
|
+
"description": "CLI for deterministic local caching of external documentation for agents and tools",
|
|
7
|
+
"author": "Frederik Bosch",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"homepage": "https://github.com/fbosch/docs-cache#readme",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/fbosch/docs-cache.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/fbosch/docs-cache/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"docs",
|
|
19
|
+
"documentation",
|
|
20
|
+
"cache",
|
|
21
|
+
"agent",
|
|
22
|
+
"ai",
|
|
23
|
+
"git",
|
|
24
|
+
"cli"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=18"
|
|
29
|
+
},
|
|
30
|
+
"bin": {
|
|
31
|
+
"docs-cache": "./bin/docs-cache.mjs"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"bin",
|
|
35
|
+
"dist/cli.mjs",
|
|
36
|
+
"dist/esm/**/*.mjs",
|
|
37
|
+
"dist/esm/**/*.d.ts",
|
|
38
|
+
"dist/lock.mjs",
|
|
39
|
+
"dist/shared/*.mjs",
|
|
40
|
+
"README.md",
|
|
41
|
+
"LICENSE"
|
|
42
|
+
],
|
|
43
|
+
"imports": {
|
|
44
|
+
"#cache/*": {
|
|
45
|
+
"types": "./dist/esm/cache/*.d.ts",
|
|
46
|
+
"default": "./dist/esm/cache/*.mjs"
|
|
47
|
+
},
|
|
48
|
+
"#cli/*": {
|
|
49
|
+
"types": "./dist/esm/cli/*.d.ts",
|
|
50
|
+
"default": "./dist/esm/cli/*.mjs"
|
|
51
|
+
},
|
|
52
|
+
"#commands/*": {
|
|
53
|
+
"types": "./dist/esm/commands/*.d.ts",
|
|
54
|
+
"default": "./dist/esm/commands/*.mjs"
|
|
55
|
+
},
|
|
56
|
+
"#core/*": {
|
|
57
|
+
"types": "./dist/esm/*.d.ts",
|
|
58
|
+
"default": "./dist/esm/*.mjs"
|
|
59
|
+
},
|
|
60
|
+
"#config": {
|
|
61
|
+
"types": "./dist/esm/config/index.d.ts",
|
|
62
|
+
"default": "./dist/esm/config/index.mjs"
|
|
63
|
+
},
|
|
64
|
+
"#config/*": {
|
|
65
|
+
"types": "./dist/esm/config/*.d.ts",
|
|
66
|
+
"default": "./dist/esm/config/*.mjs"
|
|
67
|
+
},
|
|
68
|
+
"#git/*": {
|
|
69
|
+
"types": "./dist/esm/git/*.d.ts",
|
|
70
|
+
"default": "./dist/esm/git/*.mjs"
|
|
71
|
+
},
|
|
72
|
+
"#types/*": {
|
|
73
|
+
"types": "./dist/esm/types/*.d.ts",
|
|
74
|
+
"default": "./dist/esm/types/*.mjs"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"dependencies": {
|
|
78
|
+
"@clack/prompts": "^1.0.0",
|
|
79
|
+
"cac": "^6.7.14",
|
|
80
|
+
"cli-truncate": "^4.0.0",
|
|
81
|
+
"execa": "^9.6.1",
|
|
82
|
+
"fast-glob": "^3.3.2",
|
|
83
|
+
"log-update": "^7.0.2",
|
|
84
|
+
"picocolors": "^1.1.1",
|
|
85
|
+
"picomatch": "^4.0.3",
|
|
86
|
+
"zod": "^4.3.6"
|
|
87
|
+
},
|
|
88
|
+
"devDependencies": {
|
|
89
|
+
"@biomejs/biome": "^2.3.14",
|
|
90
|
+
"@size-limit/file": "^12.0.0",
|
|
91
|
+
"@types/node": "^25.2.0",
|
|
92
|
+
"bumpp": "^10.3.2",
|
|
93
|
+
"c8": "^10.1.3",
|
|
94
|
+
"jiti": "^2.5.1",
|
|
95
|
+
"lint-staged": "^16.2.7",
|
|
96
|
+
"simple-git-hooks": "^2.13.1",
|
|
97
|
+
"size-limit": "^12.0.0",
|
|
98
|
+
"tinybench": "^6.0.0",
|
|
99
|
+
"ts-complex": "^1.0.0",
|
|
100
|
+
"typescript": "^5.9.3",
|
|
101
|
+
"unbuild": "^3.6.1"
|
|
102
|
+
},
|
|
103
|
+
"size-limit": [
|
|
104
|
+
{
|
|
105
|
+
"path": "dist/cli.mjs",
|
|
106
|
+
"limit": "10 kB"
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"complexity": {
|
|
110
|
+
"maxCyclomatic": 20,
|
|
111
|
+
"minMaintainability": 60,
|
|
112
|
+
"top": 10
|
|
113
|
+
},
|
|
114
|
+
"simple-git-hooks": {
|
|
115
|
+
"pre-commit": "pnpm lint-staged && pnpm typecheck"
|
|
116
|
+
},
|
|
117
|
+
"lint-staged": {
|
|
118
|
+
"*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}": [
|
|
119
|
+
"biome check --write --no-errors-on-unmatched"
|
|
120
|
+
]
|
|
121
|
+
},
|
|
122
|
+
"scripts": {
|
|
123
|
+
"build": "unbuild",
|
|
124
|
+
"dev": "unbuild --stub",
|
|
125
|
+
"lint": "biome check .",
|
|
126
|
+
"release": "pnpm run lint && pnpm run typecheck && bumpp && pnpm publish --access public",
|
|
127
|
+
"test": "pnpm build && node --test",
|
|
128
|
+
"test:coverage": "pnpm build && c8 --include dist --exclude bin --reporter=text node --test",
|
|
129
|
+
"bench": "pnpm build && node scripts/benchmarks/run.mjs",
|
|
130
|
+
"complexity": "node scripts/complexity/run.mjs",
|
|
131
|
+
"schema:build": "node scripts/generate-schema.mjs",
|
|
132
|
+
"size": "size-limit",
|
|
133
|
+
"test:watch": "node --test --watch",
|
|
134
|
+
"typecheck": "tsc --noEmit"
|
|
135
|
+
}
|
|
136
|
+
}
|