docs-cache 0.4.3 → 0.5.2
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/dist/cli.mjs +13 -13
- package/dist/esm/api.d.ts +14 -0
- package/dist/esm/api.mjs +14 -0
- package/dist/esm/cache/cache-layout.d.ts +1 -0
- package/dist/esm/cache/cache-layout.mjs +12 -0
- package/dist/esm/cache/lock.d.ts +21 -0
- package/dist/esm/cache/lock.mjs +91 -0
- package/dist/esm/cache/manifest.d.ts +11 -0
- package/dist/esm/cache/manifest.mjs +68 -0
- package/dist/esm/cache/materialize.d.ts +26 -0
- package/dist/esm/cache/materialize.mjs +442 -0
- package/dist/esm/cache/targets.d.ts +19 -0
- package/dist/esm/cache/targets.mjs +67 -0
- package/dist/esm/cache/toc.d.ts +12 -0
- package/dist/esm/cache/toc.mjs +167 -0
- package/dist/esm/cli/exit-code.d.ts +11 -0
- package/dist/esm/cli/exit-code.mjs +5 -0
- package/dist/esm/cli/index.d.ts +5 -0
- package/dist/esm/cli/index.mjs +345 -0
- package/dist/esm/cli/live-output.d.ts +12 -0
- package/dist/esm/cli/live-output.mjs +30 -0
- package/dist/esm/cli/parse-args.d.ts +13 -0
- package/dist/esm/cli/parse-args.mjs +295 -0
- package/dist/esm/cli/run.d.ts +1 -0
- package/dist/esm/cli/run.mjs +2 -0
- package/dist/esm/cli/task-reporter.d.ts +32 -0
- package/dist/esm/cli/task-reporter.mjs +122 -0
- package/dist/esm/cli/types.d.ts +51 -0
- package/dist/esm/cli/types.mjs +0 -0
- package/dist/esm/cli/ui.d.ts +21 -0
- package/dist/esm/cli/ui.mjs +64 -0
- package/dist/esm/commands/add.d.ts +20 -0
- package/dist/esm/commands/add.mjs +81 -0
- package/dist/esm/commands/clean-git-cache.d.ts +10 -0
- package/dist/esm/commands/clean-git-cache.mjs +48 -0
- package/dist/esm/commands/clean.d.ts +10 -0
- package/dist/esm/commands/clean.mjs +27 -0
- package/dist/esm/commands/init.d.ts +19 -0
- package/dist/esm/commands/init.mjs +179 -0
- package/dist/esm/commands/prune.d.ts +11 -0
- package/dist/esm/commands/prune.mjs +52 -0
- package/dist/esm/commands/remove.d.ts +12 -0
- package/dist/esm/commands/remove.mjs +87 -0
- package/dist/esm/commands/status.d.ts +16 -0
- package/dist/esm/commands/status.mjs +78 -0
- package/dist/esm/commands/sync.d.ts +33 -0
- package/dist/esm/commands/sync.mjs +730 -0
- package/dist/esm/commands/verify.d.ts +11 -0
- package/dist/esm/commands/verify.mjs +120 -0
- package/dist/esm/config/index.d.ts +15 -0
- package/dist/esm/config/index.mjs +196 -0
- package/dist/esm/config/io.d.ts +30 -0
- package/dist/esm/config/io.mjs +112 -0
- package/dist/esm/config/schema.d.ts +171 -0
- package/dist/esm/config/schema.mjs +69 -0
- package/dist/esm/errors.d.ts +3 -0
- package/dist/esm/errors.mjs +2 -0
- package/dist/esm/git/cache-dir.d.ts +16 -0
- package/dist/esm/git/cache-dir.mjs +23 -0
- package/dist/esm/git/fetch-source.d.ts +19 -0
- package/dist/esm/git/fetch-source.mjs +477 -0
- package/dist/esm/git/redact.d.ts +1 -0
- package/dist/esm/git/redact.mjs +4 -0
- package/dist/esm/git/resolve-remote.d.ts +15 -0
- package/dist/esm/git/resolve-remote.mjs +87 -0
- package/dist/esm/git/resolve-repo.d.ts +5 -0
- package/dist/esm/git/resolve-repo.mjs +52 -0
- package/dist/esm/gitignore.d.ts +18 -0
- package/dist/esm/gitignore.mjs +80 -0
- package/dist/esm/paths.d.ts +8 -0
- package/dist/esm/paths.mjs +34 -0
- package/dist/esm/source-id.d.ts +1 -0
- package/dist/esm/source-id.mjs +29 -0
- package/dist/esm/types/sync.d.ts +25 -0
- package/dist/esm/types/sync.mjs +0 -0
- package/package.json +51 -7
- package/dist/chunks/add.mjs +0 -3
- package/dist/chunks/clean-git-cache.mjs +0 -2
- package/dist/chunks/clean.mjs +0 -2
- package/dist/chunks/init.mjs +0 -3
- package/dist/chunks/prune.mjs +0 -2
- package/dist/chunks/remove.mjs +0 -3
- package/dist/chunks/status.mjs +0 -2
- package/dist/chunks/sync.mjs +0 -9
- package/dist/chunks/verify.mjs +0 -2
- package/dist/shared/docs-cache.BOr9BnyP.mjs +0 -5
- package/dist/shared/docs-cache.BSvQNKuf.mjs +0 -2
- package/dist/shared/docs-cache.CQiaFDb_.mjs +0 -7
- package/dist/shared/docs-cache.CaOcl4OS.mjs +0 -3
- package/dist/shared/docs-cache.kK1DPQIQ.mjs +0 -2
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI exit codes.
|
|
3
|
+
*
|
|
4
|
+
* @see https://nodejs.org/api/process.html#process_exit_codes
|
|
5
|
+
*/
|
|
6
|
+
export declare const ExitCode: {
|
|
7
|
+
Success: number;
|
|
8
|
+
FatalError: number;
|
|
9
|
+
InvalidArgument: number;
|
|
10
|
+
};
|
|
11
|
+
export type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
import { ExitCode } from "#cli/exit-code";
|
|
5
|
+
import { parseArgs } from "#cli/parse-args";
|
|
6
|
+
import { setSilentMode, setVerboseMode, symbols, ui } from "#cli/ui";
|
|
7
|
+
export const CLI_NAME = "docs-cache";
|
|
8
|
+
const HELP_TEXT = `
|
|
9
|
+
Usage: ${CLI_NAME} <command> [options]
|
|
10
|
+
|
|
11
|
+
Commands:
|
|
12
|
+
add Add sources to the config (supports github:org/repo#ref)
|
|
13
|
+
remove Remove sources from the config and targets
|
|
14
|
+
sync Synchronize cache with config
|
|
15
|
+
status Show cache status
|
|
16
|
+
clean Remove project cache
|
|
17
|
+
clean-cache Clear global git cache
|
|
18
|
+
prune Remove unused data
|
|
19
|
+
verify Validate cache integrity
|
|
20
|
+
init Create a new config interactively
|
|
21
|
+
|
|
22
|
+
Global options:
|
|
23
|
+
--config <path>
|
|
24
|
+
--cache-dir <path>
|
|
25
|
+
--offline
|
|
26
|
+
--fail-on-miss
|
|
27
|
+
--lock-only
|
|
28
|
+
--concurrency <n>
|
|
29
|
+
--json
|
|
30
|
+
--timeout-ms <n>
|
|
31
|
+
--silent
|
|
32
|
+
--verbose
|
|
33
|
+
|
|
34
|
+
Add options:
|
|
35
|
+
--source <repo>
|
|
36
|
+
--target <dir>
|
|
37
|
+
--target-dir <path>
|
|
38
|
+
--id <id>
|
|
39
|
+
`;
|
|
40
|
+
const printHelp = () => {
|
|
41
|
+
process.stdout.write(HELP_TEXT.trimStart());
|
|
42
|
+
};
|
|
43
|
+
const printError = (message) => {
|
|
44
|
+
process.stderr.write(`${symbols.error} ${message}
|
|
45
|
+
`);
|
|
46
|
+
};
|
|
47
|
+
const runAdd = async (parsed) => {
|
|
48
|
+
const options = parsed.options;
|
|
49
|
+
const { addSources } = await import("#commands/add");
|
|
50
|
+
const { runSync } = await import("#commands/sync");
|
|
51
|
+
if (parsed.entries.length === 0) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
"Usage: docs-cache add [--source <repo> --target <dir>] <repo...>"
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
const result = await addSources({
|
|
57
|
+
configPath: options.config,
|
|
58
|
+
entries: parsed.entries
|
|
59
|
+
});
|
|
60
|
+
if (options.offline) {
|
|
61
|
+
if (!options.json) {
|
|
62
|
+
ui.line(`${symbols.warn} Offline: skipped sync`);
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
await runSync({
|
|
66
|
+
configPath: options.config,
|
|
67
|
+
cacheDirOverride: options.cacheDir,
|
|
68
|
+
json: options.json,
|
|
69
|
+
lockOnly: options.lockOnly,
|
|
70
|
+
offline: options.offline,
|
|
71
|
+
failOnMiss: options.failOnMiss,
|
|
72
|
+
sourceFilter: result.sources.map((source) => source.id),
|
|
73
|
+
timeoutMs: options.timeoutMs,
|
|
74
|
+
verbose: options.verbose
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (options.json) {
|
|
78
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
79
|
+
`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
for (const source of result.sources) {
|
|
83
|
+
const repoLabel = source.repo.replace(/^https?:\/\//, "").replace(/\.git$/, "");
|
|
84
|
+
const targetLabel = source.targetDir ? ` ${pc.dim("->")} ${pc.magenta(source.targetDir)}` : "";
|
|
85
|
+
ui.item(symbols.success, source.id, `${pc.blue(repoLabel)}${targetLabel}`);
|
|
86
|
+
}
|
|
87
|
+
if (result.skipped?.length) {
|
|
88
|
+
ui.line(
|
|
89
|
+
`${symbols.warn} Skipped ${result.skipped.length} existing source${result.skipped.length === 1 ? "" : "s"}: ${result.skipped.join(", ")}`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
ui.line(
|
|
93
|
+
`${symbols.info} Updated ${pc.gray(path.relative(process.cwd(), result.configPath) || "docs.config.json")}`
|
|
94
|
+
);
|
|
95
|
+
if (result.gitignoreUpdated && result.gitignorePath) {
|
|
96
|
+
ui.line(
|
|
97
|
+
`${symbols.info} Updated ${pc.gray(ui.path(result.gitignorePath))}`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const runRemove = async (parsed) => {
|
|
102
|
+
const options = parsed.options;
|
|
103
|
+
const { removeSources } = await import("#commands/remove");
|
|
104
|
+
const { pruneCache } = await import("#commands/prune");
|
|
105
|
+
if (parsed.ids.length === 0) {
|
|
106
|
+
throw new Error("Usage: docs-cache remove <id...>");
|
|
107
|
+
}
|
|
108
|
+
const result = await removeSources({
|
|
109
|
+
configPath: options.config,
|
|
110
|
+
ids: parsed.ids
|
|
111
|
+
});
|
|
112
|
+
if (options.json) {
|
|
113
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
114
|
+
`);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (result.removed.length > 0) {
|
|
118
|
+
ui.line(
|
|
119
|
+
`${symbols.success} Removed ${result.removed.length} source${result.removed.length === 1 ? "" : "s"}: ${result.removed.join(", ")}`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
if (result.missing.length > 0) {
|
|
123
|
+
ui.line(
|
|
124
|
+
`${symbols.warn} Missing ${result.missing.length} source${result.missing.length === 1 ? "" : "s"}: ${result.missing.join(", ")}`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
if (result.targetsRemoved.length > 0) {
|
|
128
|
+
const targetLabels = result.targetsRemoved.map((entry) => `${entry.id} -> ${ui.path(entry.targetDir)}`).join(", ");
|
|
129
|
+
ui.line(
|
|
130
|
+
`${symbols.success} Removed ${result.targetsRemoved.length} target${result.targetsRemoved.length === 1 ? "" : "s"}: ${targetLabels}`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
ui.line(
|
|
134
|
+
`${symbols.info} Updated ${pc.gray(path.relative(process.cwd(), result.configPath) || "docs.config.json")}`
|
|
135
|
+
);
|
|
136
|
+
if (options.prune) {
|
|
137
|
+
await pruneCache({
|
|
138
|
+
configPath: options.config,
|
|
139
|
+
cacheDirOverride: options.cacheDir,
|
|
140
|
+
json: options.json
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const runStatus = async (parsed) => {
|
|
145
|
+
const options = parsed.options;
|
|
146
|
+
const { getStatus, printStatus } = await import("#commands/status");
|
|
147
|
+
const status = await getStatus({
|
|
148
|
+
configPath: options.config,
|
|
149
|
+
cacheDirOverride: options.cacheDir,
|
|
150
|
+
json: options.json
|
|
151
|
+
});
|
|
152
|
+
if (options.json) {
|
|
153
|
+
process.stdout.write(`${JSON.stringify(status, null, 2)}
|
|
154
|
+
`);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
printStatus(status);
|
|
158
|
+
};
|
|
159
|
+
const runClean = async (parsed) => {
|
|
160
|
+
const options = parsed.options;
|
|
161
|
+
const { cleanCache } = await import("#commands/clean");
|
|
162
|
+
const result = await cleanCache({
|
|
163
|
+
configPath: options.config,
|
|
164
|
+
cacheDirOverride: options.cacheDir,
|
|
165
|
+
json: options.json
|
|
166
|
+
});
|
|
167
|
+
if (options.json) {
|
|
168
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
169
|
+
`);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (result.removed) {
|
|
173
|
+
ui.line(`${symbols.success} Removed cache at ${ui.path(result.cacheDir)}`);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
ui.line(
|
|
177
|
+
`${symbols.info} Cache already missing at ${ui.path(result.cacheDir)}`
|
|
178
|
+
);
|
|
179
|
+
};
|
|
180
|
+
const runCleanCache = async (parsed) => {
|
|
181
|
+
const options = parsed.options;
|
|
182
|
+
const { cleanGitCache } = await import("#commands/clean-git-cache");
|
|
183
|
+
const result = await cleanGitCache();
|
|
184
|
+
if (options.json) {
|
|
185
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
186
|
+
`);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (!result.removed) {
|
|
190
|
+
ui.line(
|
|
191
|
+
`${symbols.info} Global git cache already empty at ${ui.path(result.cacheDir)}`
|
|
192
|
+
);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const sizeInMB = result.bytesFreed !== void 0 ? `${(result.bytesFreed / 1024 / 1024).toFixed(2)} MB` : "unknown size";
|
|
196
|
+
const repoLabel = result.repoCount !== void 0 ? ` (${result.repoCount} cached repositor${result.repoCount === 1 ? "y" : "ies"})` : "";
|
|
197
|
+
ui.line(
|
|
198
|
+
`${symbols.success} Cleared global git cache${repoLabel}: ${sizeInMB} freed`
|
|
199
|
+
);
|
|
200
|
+
ui.line(`${symbols.info} Cache location: ${ui.path(result.cacheDir)}`);
|
|
201
|
+
};
|
|
202
|
+
const runPrune = async (parsed) => {
|
|
203
|
+
const options = parsed.options;
|
|
204
|
+
const { pruneCache } = await import("#commands/prune");
|
|
205
|
+
const result = await pruneCache({
|
|
206
|
+
configPath: options.config,
|
|
207
|
+
cacheDirOverride: options.cacheDir,
|
|
208
|
+
json: options.json
|
|
209
|
+
});
|
|
210
|
+
if (options.json) {
|
|
211
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
212
|
+
`);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (result.removed.length === 0) {
|
|
216
|
+
ui.line(`${symbols.info} No cache entries to prune.`);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
ui.line(
|
|
220
|
+
`${symbols.success} Pruned ${result.removed.length} cache entr${result.removed.length === 1 ? "y" : "ies"}: ${result.removed.join(", ")}`
|
|
221
|
+
);
|
|
222
|
+
};
|
|
223
|
+
const runSyncCommand = async (parsed) => {
|
|
224
|
+
const options = parsed.options;
|
|
225
|
+
const { printSyncPlan, runSync } = await import("#commands/sync");
|
|
226
|
+
const plan = await runSync({
|
|
227
|
+
configPath: options.config,
|
|
228
|
+
cacheDirOverride: options.cacheDir,
|
|
229
|
+
json: options.json,
|
|
230
|
+
lockOnly: options.lockOnly,
|
|
231
|
+
offline: options.offline,
|
|
232
|
+
failOnMiss: options.failOnMiss,
|
|
233
|
+
timeoutMs: options.timeoutMs,
|
|
234
|
+
verbose: options.verbose
|
|
235
|
+
});
|
|
236
|
+
if (options.json) {
|
|
237
|
+
process.stdout.write(`${JSON.stringify(plan, null, 2)}
|
|
238
|
+
`);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
printSyncPlan(plan);
|
|
242
|
+
};
|
|
243
|
+
const runVerify = async (parsed) => {
|
|
244
|
+
const options = parsed.options;
|
|
245
|
+
const { printVerify, verifyCache } = await import("#commands/verify");
|
|
246
|
+
const report = await verifyCache({
|
|
247
|
+
configPath: options.config,
|
|
248
|
+
cacheDirOverride: options.cacheDir,
|
|
249
|
+
json: options.json
|
|
250
|
+
});
|
|
251
|
+
if (options.json) {
|
|
252
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}
|
|
253
|
+
`);
|
|
254
|
+
} else {
|
|
255
|
+
printVerify(report);
|
|
256
|
+
}
|
|
257
|
+
if (report.results.some((result) => !result.ok)) {
|
|
258
|
+
process.exit(ExitCode.FatalError);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
const runInit = async (parsed) => {
|
|
262
|
+
const options = parsed.options;
|
|
263
|
+
const { initConfig } = await import("#commands/init");
|
|
264
|
+
if (options.config) {
|
|
265
|
+
throw new Error("Init does not accept --config. Use the project root.");
|
|
266
|
+
}
|
|
267
|
+
const result = await initConfig({
|
|
268
|
+
cacheDirOverride: options.cacheDir,
|
|
269
|
+
json: options.json
|
|
270
|
+
});
|
|
271
|
+
if (options.json) {
|
|
272
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
273
|
+
`);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
ui.line(`${symbols.success} Wrote ${pc.gray(ui.path(result.configPath))}`);
|
|
277
|
+
if (result.gitignoreUpdated && result.gitignorePath) {
|
|
278
|
+
ui.line(
|
|
279
|
+
`${symbols.info} Updated ${pc.gray(ui.path(result.gitignorePath))}`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
const runCommand = async (parsed) => {
|
|
284
|
+
switch (parsed.command) {
|
|
285
|
+
case "add":
|
|
286
|
+
await runAdd(parsed);
|
|
287
|
+
return;
|
|
288
|
+
case "remove":
|
|
289
|
+
await runRemove(parsed);
|
|
290
|
+
return;
|
|
291
|
+
case "status":
|
|
292
|
+
await runStatus(parsed);
|
|
293
|
+
return;
|
|
294
|
+
case "clean":
|
|
295
|
+
await runClean(parsed);
|
|
296
|
+
return;
|
|
297
|
+
case "clean-cache":
|
|
298
|
+
await runCleanCache(parsed);
|
|
299
|
+
return;
|
|
300
|
+
case "prune":
|
|
301
|
+
await runPrune(parsed);
|
|
302
|
+
return;
|
|
303
|
+
case "sync":
|
|
304
|
+
await runSyncCommand(parsed);
|
|
305
|
+
return;
|
|
306
|
+
case "verify":
|
|
307
|
+
await runVerify(parsed);
|
|
308
|
+
return;
|
|
309
|
+
case "init":
|
|
310
|
+
await runInit(parsed);
|
|
311
|
+
return;
|
|
312
|
+
default:
|
|
313
|
+
ui.line(`${CLI_NAME} ${parsed.command}: not implemented yet.`);
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
export async function main() {
|
|
317
|
+
try {
|
|
318
|
+
process.on("uncaughtException", errorHandler);
|
|
319
|
+
process.on("unhandledRejection", errorHandler);
|
|
320
|
+
const parsed = parseArgs();
|
|
321
|
+
setSilentMode(parsed.options.silent);
|
|
322
|
+
setVerboseMode(parsed.options.verbose);
|
|
323
|
+
if (parsed.help) {
|
|
324
|
+
printHelp();
|
|
325
|
+
process.exit(ExitCode.Success);
|
|
326
|
+
}
|
|
327
|
+
if (!parsed.command) {
|
|
328
|
+
printHelp();
|
|
329
|
+
process.exit(ExitCode.InvalidArgument);
|
|
330
|
+
}
|
|
331
|
+
if (parsed.command !== "add" && parsed.command !== "remove" && parsed.positionals.length > 0) {
|
|
332
|
+
printError(`${CLI_NAME}: unexpected arguments.`);
|
|
333
|
+
printHelp();
|
|
334
|
+
process.exit(ExitCode.InvalidArgument);
|
|
335
|
+
}
|
|
336
|
+
await runCommand(parsed.parsed);
|
|
337
|
+
} catch (error) {
|
|
338
|
+
errorHandler(error);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
function errorHandler(error) {
|
|
342
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
343
|
+
printError(message);
|
|
344
|
+
process.exit(ExitCode.FatalError);
|
|
345
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type LiveOutputOptions = {
|
|
2
|
+
stdout?: NodeJS.WriteStream;
|
|
3
|
+
maxWidth?: number;
|
|
4
|
+
};
|
|
5
|
+
export type LiveOutput = {
|
|
6
|
+
render: (lines: string[]) => void;
|
|
7
|
+
persist: (lines: string[]) => void;
|
|
8
|
+
clear: () => void;
|
|
9
|
+
stop: () => void;
|
|
10
|
+
};
|
|
11
|
+
export declare const createLiveOutput: (options?: LiveOutputOptions) => LiveOutput;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import cliTruncate from "cli-truncate";
|
|
2
|
+
import { createLogUpdate } from "log-update";
|
|
3
|
+
const normalizeLines = (lines) => lines.map((line) => line.length === 0 ? line : line);
|
|
4
|
+
export const createLiveOutput = (options = {}) => {
|
|
5
|
+
const stdout = options.stdout ?? process.stdout;
|
|
6
|
+
const updater = createLogUpdate(stdout);
|
|
7
|
+
const maxWidth = options.maxWidth ?? Math.max(20, (stdout.columns ?? 80) - 2);
|
|
8
|
+
const truncate = (line) => cliTruncate(line, maxWidth, { position: "end" });
|
|
9
|
+
const render = (lines) => {
|
|
10
|
+
const output = normalizeLines(lines).map(truncate).join("\n");
|
|
11
|
+
updater(output);
|
|
12
|
+
};
|
|
13
|
+
const persist = (lines) => {
|
|
14
|
+
const output = normalizeLines(lines).map(truncate).join("\n");
|
|
15
|
+
updater(output);
|
|
16
|
+
updater.done();
|
|
17
|
+
};
|
|
18
|
+
const clear = () => {
|
|
19
|
+
updater.clear();
|
|
20
|
+
};
|
|
21
|
+
const stop = () => {
|
|
22
|
+
updater.done();
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
render,
|
|
26
|
+
persist,
|
|
27
|
+
clear,
|
|
28
|
+
stop
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CliCommand, CliOptions } from "./types";
|
|
2
|
+
declare const COMMANDS: readonly ["add", "remove", "sync", "status", "clean", "clean-cache", "prune", "verify", "init"];
|
|
3
|
+
type Command = (typeof COMMANDS)[number];
|
|
4
|
+
export type ParsedArgs = {
|
|
5
|
+
command: Command | null;
|
|
6
|
+
options: CliOptions;
|
|
7
|
+
positionals: string[];
|
|
8
|
+
rawArgs: string[];
|
|
9
|
+
help: boolean;
|
|
10
|
+
parsed: CliCommand;
|
|
11
|
+
};
|
|
12
|
+
export declare const parseArgs: (argv?: any) => ParsedArgs;
|
|
13
|
+
export {};
|