Skip to content

Commit a0cb45d

Browse files
committed
chore: merge
2 parents 5cc1ab2 + 2f4029a commit a0cb45d

21 files changed

Lines changed: 546 additions & 170 deletions

.github/workflows/ci.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,47 @@ on:
88
- master
99

1010
jobs:
11+
precheck:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
17+
- name: Setup pnpm
18+
uses: pnpm/action-setup@v4
19+
with:
20+
run_install: false
21+
22+
- name: Setup Node
23+
uses: actions/setup-node@v4
24+
with:
25+
node-version: 22
26+
cache: pnpm
27+
28+
- name: Install dependencies
29+
run: pnpm install --frozen-lockfile
30+
31+
- name: Audit dependencies
32+
run: pnpm audit --audit-level=high
33+
34+
- name: Lint
35+
run: pnpm lint
36+
37+
- name: Typecheck
38+
run: pnpm typecheck
39+
40+
- name: Test
41+
run: pnpm test
42+
43+
- name: Build
44+
run: pnpm build
45+
46+
- name: Size limit
47+
run: pnpm size
48+
1149
build:
50+
needs: precheck
51+
if: needs.precheck.result == 'success'
1252
runs-on: ${{ matrix.os }}
1353
strategy:
1454
fail-fast: false

README.md

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -88,18 +88,18 @@ npx docs-cache clean
8888

8989
All fields in `defaults` apply to all sources unless overridden per-source.
9090

91-
| Field | Details |
92-
| ------------ | ---------------------------------------------------------------------------------------------------------------- |
93-
| `ref` | Branch, tag, or commit. Default: `"HEAD"`. |
94-
| `mode` | Cache mode. Default: `"materialize"`. |
95-
| `include` | Glob patterns to copy. Default: `["**/*.{md,mdx,markdown,mkd,txt,rst,adoc,asciidoc}"]`. |
96-
| `targetMode` | How to link or copy from the cache to the destination. Default: `"symlink"` on Unix, `"copy"` on Windows. |
97-
| `depth` | Git clone depth. Default: `1`. |
98-
| `required` | Whether missing sources should fail. Default: `true`. |
99-
| `maxBytes` | Maximum total bytes to materialize. Default: `200000000` (200 MB). |
100-
| `maxFiles` | Maximum total files to materialize. |
101-
| `allowHosts` | Allowed Git hosts. Default: `["github.com", "gitlab.com"]`. |
102-
| `toc` | Generate per-source `TOC.md`. Default: `true`. Supports `true`, `false`, or a format (`"tree"`, `"compressed"`). |
91+
| Field | Details |
92+
| --------------------- | ---------------------------------------------------------------------------------------------------------------- |
93+
| `ref` | Branch, tag, or commit. Default: `"HEAD"`. |
94+
| `mode` | Cache mode. Default: `"materialize"`. |
95+
| `include` | Glob patterns to copy. Default: `["**/*.{md,mdx,markdown,mkd,txt,rst,adoc,asciidoc}"]`. |
96+
| `targetMode` | How to link or copy from the cache to the destination. Default: `"symlink"` on Unix, `"copy"` on Windows. |
97+
| `required` | Whether missing sources should fail. Default: `true`. |
98+
| `maxBytes` | Maximum total bytes to materialize. Default: `200000000` (200 MB). |
99+
| `maxFiles` | Maximum total files to materialize. |
100+
| `allowHosts` | Allowed Git hosts. Default: `["github.com", "gitlab.com"]`. |
101+
| `toc` | Generate per-source `TOC.md`. Default: `true`. Supports `true`, `false`, or a format (`"tree"`, `"compressed"`). |
102+
| `unwrapSingleRootDir` | If the materialized output is nested under a single directory, unwrap it (recursively). Default: `false`. |
103103

104104
### Source options
105105

@@ -112,17 +112,18 @@ All fields in `defaults` apply to all sources unless overridden per-source.
112112

113113
#### Optional
114114

115-
| Field | Details |
116-
| ------------ | ----------------------------------------------------------------------------------------------- |
117-
| `ref` | Branch, tag, or commit. |
118-
| `include` | Glob patterns to copy. |
119-
| `exclude` | Glob patterns to skip. |
120-
| `targetDir` | Path where files should be symlinked/copied to, outside `.docs`. |
121-
| `targetMode` | How to link or copy from the cache to the destination. |
122-
| `required` | Whether missing sources should fail. |
123-
| `maxBytes` | Maximum total bytes to materialize. |
124-
| `maxFiles` | Maximum total files to materialize. |
125-
| `toc` | Generate per-source `TOC.md`. Supports `true`, `false`, or a format (`"tree"`, `"compressed"`). |
115+
| Field | Details |
116+
| --------------------- | ----------------------------------------------------------------------------------------------- |
117+
| `ref` | Branch, tag, or commit. |
118+
| `include` | Glob patterns to copy. |
119+
| `exclude` | Glob patterns to skip. |
120+
| `targetDir` | Path where files should be symlinked/copied to, outside `.docs`. |
121+
| `targetMode` | How to link or copy from the cache to the destination. |
122+
| `required` | Whether missing sources should fail. |
123+
| `maxBytes` | Maximum total bytes to materialize. |
124+
| `maxFiles` | Maximum total files to materialize. |
125+
| `toc` | Generate per-source `TOC.md`. Supports `true`, `false`, or a format (`"tree"`, `"compressed"`). |
126+
| `unwrapSingleRootDir` | If the materialized output is nested under a single directory, unwrap it (recursively). |
126127

127128
> **Note**: Sources are always downloaded to `.docs/<id>/`. If you provide a `targetDir`, `docs-cache` will create a symlink or copy pointing from the cache to that target directory. The target should be outside `.docs`. Git operation timeout is configured via the `--timeout-ms` CLI flag, not as a per-source configuration option.
128129

docs.config.schema.json

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@
3737
"type": "string",
3838
"enum": ["symlink", "copy"]
3939
},
40-
"depth": {
41-
"type": "number",
42-
"minimum": 1
43-
},
4440
"required": {
4541
"type": "boolean"
4642
},
@@ -60,6 +56,9 @@
6056
"minLength": 1
6157
}
6258
},
59+
"unwrapSingleRootDir": {
60+
"type": "boolean"
61+
},
6362
"toc": {
6463
"anyOf": [
6564
{
@@ -107,10 +106,6 @@
107106
"type": "string",
108107
"enum": ["materialize"]
109108
},
110-
"depth": {
111-
"type": "number",
112-
"minimum": 1
113-
},
114109
"include": {
115110
"type": "array",
116111
"items": {
@@ -171,6 +166,9 @@
171166
"tocFormat": {
172167
"type": "string",
173168
"enum": ["tree", "compressed"]
169+
},
170+
"unwrapSingleRootDir": {
171+
"type": "boolean"
174172
}
175173
},
176174
"required": ["id", "repo"],

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
}
8585
],
8686
"simple-git-hooks": {
87-
"pre-commit": "pnpm lint-staged"
87+
"pre-commit": "pnpm lint-staged && pnpm typecheck"
8888
},
8989
"lint-staged": {
9090
"*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}": [

src/cli/index.ts

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import process from "node:process";
33
import pc from "picocolors";
44
import { ExitCode } from "./exit-code";
55
import { parseArgs } from "./parse-args";
6-
import type { CliOptions } from "./types";
6+
import type { CliCommand } from "./types";
77
import { setSilentMode, symbols, ui } from "./ui";
88

99
export const CLI_NAME = "docs-cache";
@@ -93,12 +93,10 @@ const parseAddEntries = (rawArgs: string[]) => {
9393
return entries;
9494
};
9595

96-
const runCommand = async (
97-
command: string,
98-
options: CliOptions,
99-
positionals: string[],
100-
rawArgs: string[],
101-
) => {
96+
const runCommand = async (parsed: CliCommand, rawArgs: string[]) => {
97+
const command = parsed.command;
98+
const options = parsed.options;
99+
const positionals = parsed.args;
102100
if (command === "add") {
103101
const { addSources } = await import("../add");
104102
const { runSync } = await import("../sync");
@@ -380,12 +378,7 @@ export async function main(): Promise<void> {
380378
process.exit(ExitCode.InvalidArgument);
381379
}
382380

383-
await runCommand(
384-
parsed.command,
385-
parsed.options,
386-
parsed.positionals,
387-
parsed.rawArgs,
388-
);
381+
await runCommand(parsed.parsed, parsed.rawArgs);
389382
} catch (error) {
390383
errorHandler(error as Error);
391384
}

src/cli/parse-args.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import process from "node:process";
22

33
import cac from "cac";
44
import { ExitCode } from "./exit-code";
5-
import type { CliOptions } from "./types";
5+
import type { CliCommand, CliOptions } from "./types";
66

77
const COMMANDS = [
88
"add",
@@ -23,6 +23,7 @@ export type ParsedArgs = {
2323
positionals: string[];
2424
rawArgs: string[];
2525
help: boolean;
26+
parsed: CliCommand;
2627
};
2728

2829
export const parseArgs = (argv = process.argv): ParsedArgs => {
@@ -83,6 +84,11 @@ export const parseArgs = (argv = process.argv): ParsedArgs => {
8384
positionals: result.args.slice(1),
8485
rawArgs,
8586
help: Boolean(result.options.help),
87+
parsed: {
88+
command: command ?? null,
89+
args: result.args.slice(1),
90+
options,
91+
},
8692
};
8793
} catch (error) {
8894
const message = error instanceof Error ? error.message : String(error);

src/cli/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,15 @@ export type CliOptions = {
1111
timeoutMs?: number;
1212
silent: boolean;
1313
};
14+
15+
export type CliCommand =
16+
| { command: "add"; args: string[]; options: CliOptions }
17+
| { command: "remove"; args: string[]; options: CliOptions }
18+
| { command: "sync"; args: string[]; options: CliOptions }
19+
| { command: "status"; args: string[]; options: CliOptions }
20+
| { command: "clean"; args: string[]; options: CliOptions }
21+
| { command: "clean-cache"; args: string[]; options: CliOptions }
22+
| { command: "prune"; args: string[]; options: CliOptions }
23+
| { command: "verify"; args: string[]; options: CliOptions }
24+
| { command: "init"; args: string[]; options: CliOptions }
25+
| { command: null; args: string[]; options: CliOptions };

src/config-schema.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ export const DefaultsSchema = z
1616
mode: CacheModeSchema,
1717
include: z.array(z.string().min(1)).min(1),
1818
targetMode: TargetModeSchema.optional(),
19-
depth: z.number().min(1),
2019
required: z.boolean(),
2120
maxBytes: z.number().min(1),
2221
maxFiles: z.number().min(1).optional(),
2322
allowHosts: z.array(z.string().min(1)).min(1),
2423
toc: z.union([z.boolean(), TocFormatSchema]).optional(),
24+
unwrapSingleRootDir: z.boolean().optional(),
2525
})
2626
.strict();
2727

@@ -33,14 +33,14 @@ export const SourceSchema = z
3333
targetMode: TargetModeSchema.optional(),
3434
ref: z.string().min(1).optional(),
3535
mode: CacheModeSchema.optional(),
36-
depth: z.number().min(1).optional(),
3736
include: z.array(z.string().min(1)).optional(),
3837
exclude: z.array(z.string().min(1)).optional(),
3938
required: z.boolean().optional(),
4039
maxBytes: z.number().min(1).optional(),
4140
maxFiles: z.number().min(1).optional(),
4241
integrity: IntegritySchema.optional(),
4342
toc: z.union([z.boolean(), TocFormatSchema]).optional(),
43+
unwrapSingleRootDir: z.boolean().optional(),
4444
})
4545
.strict();
4646

0 commit comments

Comments
 (0)