@gitpagedocs/cli 1.1.62 → 1.1.63
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 +193 -193
- package/ai/application/ai-command.ts +24 -24
- package/ai/application/ai-provider-factory.ts +22 -22
- package/ai/application/docs-pattern.ts +68 -68
- package/ai/application/run-ai-cli-command.ts +167 -167
- package/ai/config.ts +50 -50
- package/ai/core/models/ai-cli-config.ts +33 -33
- package/ai/core/models/parse-ai-cli-config.ts +78 -78
- package/ai/core/ports/illm-provider.ts +32 -32
- package/ai/infrastructure/ai-config-file.ts +101 -101
- package/ai/infrastructure/file-system-adapter.ts +85 -85
- package/ai/infrastructure/llm/tools-llm-provider.ts +54 -54
- package/ai/infrastructure/version-docs-writer.ts +143 -143
- package/ai/presentation/ai-prompts.ts +239 -239
- package/application/ports/cli-runtime-ports.ts +91 -91
- package/application/report/config-only-reporter.mjs +64 -64
- package/application/use-cases/dispatch-mode.ts +18 -18
- package/builders/config-orchestrator.mjs +34 -34
- package/builders/project-links.mjs +50 -50
- package/builders/root-config-builder.mjs +61 -61
- package/builders/route-builders.mjs +136 -136
- package/builders/theme-template.mjs +76 -76
- package/builders/version-config-builder.mjs +186 -186
- package/content/docs-en.mjs +549 -549
- package/content/docs-es.mjs +462 -462
- package/content/docs-pt.mjs +462 -462
- package/contracts/doc-versions.mjs +3 -3
- package/data/default-site-config.mjs +321 -321
- package/data/i18n-langmenu.mjs +347 -347
- package/data/layouts.mjs +436 -436
- package/data/path-mappings.mjs +26 -26
- package/data/route-metas.mjs +93 -93
- package/data/theme-colors.mjs +443 -443
- package/data/urls.mjs +12 -12
- package/domain/models/cli-options.ts +33 -33
- package/home/constants.mjs +4 -4
- package/index.mjs +37 -37
- package/infrastructure/gitpagedocs-config-file.ts +47 -47
- package/infrastructure/home/runtime.mjs +37 -37
- package/package.json +3 -3
- package/presentation/commands/ai-info.ts +57 -57
- package/presentation/commands/config-clear.ts +23 -23
- package/presentation/commands/config-info.ts +24 -24
- package/presentation/commands/diagnostics.ts +164 -164
- package/presentation/commands/docs.ts +37 -37
- package/presentation/commands/mcp.ts +20 -20
- package/presentation/commands/pages.ts +101 -101
- package/presentation/commands/password.ts +62 -62
- package/presentation/commands/run-command.ts +70 -70
- package/presentation/index.ts +124 -124
- package/presentation/options/parser.ts +119 -119
- package/presentation/options/resolver.ts +46 -46
- package/presentation/ui/clack.ts +91 -91
- package/presentation/ui/prompts.ts +146 -146
- package/runtime/git-ops.mjs +110 -110
- package/runtime/output.mjs +159 -159
- package/runtime/workflow.mjs +129 -129
- package/start.mjs +12 -12
- package/ui/logger.mjs +9 -9
|
@@ -1,119 +1,119 @@
|
|
|
1
|
-
import type { CliOptions } from "../../domain/models/cli-options";
|
|
2
|
-
import { DEFAULTS } from "./schema";
|
|
3
|
-
import { normalizeLayoutsDir } from "../../contracts/layouts-paths.mjs";
|
|
4
|
-
|
|
5
|
-
const KNOWN_FLAGS = new Set([
|
|
6
|
-
"--build",
|
|
7
|
-
"--serve",
|
|
8
|
-
"--layoutconfig",
|
|
9
|
-
"--full",
|
|
10
|
-
"--push",
|
|
11
|
-
"--home",
|
|
12
|
-
"--search",
|
|
13
|
-
"--path",
|
|
14
|
-
"--output",
|
|
15
|
-
"--layouts-dir",
|
|
16
|
-
"--interactive",
|
|
17
|
-
"-i",
|
|
18
|
-
"--no-interactive",
|
|
19
|
-
"--yes",
|
|
20
|
-
"-y",
|
|
21
|
-
"--ai",
|
|
22
|
-
"--pages-actions",
|
|
23
|
-
]);
|
|
24
|
-
|
|
25
|
-
function readOptionValue(args: string[], optionName: string): string {
|
|
26
|
-
const equalsArg = args.find((a) => a.startsWith(`${optionName}=`));
|
|
27
|
-
if (equalsArg) return equalsArg.slice(optionName.length + 1).trim();
|
|
28
|
-
const index = args.indexOf(optionName);
|
|
29
|
-
if (index >= 0) {
|
|
30
|
-
const next = args[index + 1];
|
|
31
|
-
if (next && !next.startsWith("--")) return next.trim();
|
|
32
|
-
}
|
|
33
|
-
return "";
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function parseCliOptions(argv: string[], env: NodeJS.ProcessEnv): CliOptions {
|
|
37
|
-
const args = argv.slice(2);
|
|
38
|
-
|
|
39
|
-
let githubOwner = readOptionValue(args, "--owner");
|
|
40
|
-
let githubRepo = readOptionValue(args, "--repo");
|
|
41
|
-
const docsPath = readOptionValue(args, "--path");
|
|
42
|
-
const outputDir = readOptionValue(args, "--output");
|
|
43
|
-
const layoutsDir = readOptionValue(args, "--layouts-dir");
|
|
44
|
-
const searchRaw = readOptionValue(args, "--search");
|
|
45
|
-
|
|
46
|
-
const fallbackDashedArgs = args
|
|
47
|
-
.filter((a) => a.startsWith("--"))
|
|
48
|
-
.filter((a) => !KNOWN_FLAGS.has(a))
|
|
49
|
-
.filter((a) => !a.startsWith("--owner"))
|
|
50
|
-
.filter((a) => !a.startsWith("--repo"))
|
|
51
|
-
.filter((a) => !a.startsWith("--path"))
|
|
52
|
-
.filter((a) => !a.startsWith("--home"))
|
|
53
|
-
.filter((a) => !a.startsWith("--output"))
|
|
54
|
-
.filter((a) => !a.startsWith("--layouts-dir"))
|
|
55
|
-
.filter((a) => !a.startsWith("--search"))
|
|
56
|
-
.map((a) => a.replace(/^--/, "").trim())
|
|
57
|
-
.filter(Boolean);
|
|
58
|
-
|
|
59
|
-
if (!githubOwner && fallbackDashedArgs[0]) githubOwner = fallbackDashedArgs[0];
|
|
60
|
-
if (!githubRepo && fallbackDashedArgs[1]) githubRepo = fallbackDashedArgs[1];
|
|
61
|
-
|
|
62
|
-
// New verb aliases (Phase 6) that map onto existing modes without new modes.
|
|
63
|
-
const command = args[0];
|
|
64
|
-
const isDocument = command === "document" || (command?.startsWith("document:") ?? false);
|
|
65
|
-
const isDeploy = command === "deploy" || command === "pages";
|
|
66
|
-
|
|
67
|
-
const isBuild = args.includes("--build") || env.GITPAGEDOCS_BUILD === "1";
|
|
68
|
-
const isServe = args.includes("--serve");
|
|
69
|
-
const useLocalLayoutConfig = args.includes("--layoutconfig");
|
|
70
|
-
const shouldPush = args.includes("--push") || isDeploy;
|
|
71
|
-
const isHome = args.includes("--home");
|
|
72
|
-
const isInteractive = args.includes("--interactive") || args.includes("-i");
|
|
73
|
-
const isAi = command === "ai" || args.includes("--ai") || isDocument;
|
|
74
|
-
const aiCommand =
|
|
75
|
-
command === "ai"
|
|
76
|
-
? args[1]
|
|
77
|
-
: command === "document"
|
|
78
|
-
? args[1] ?? "repo"
|
|
79
|
-
: command?.startsWith("document:")
|
|
80
|
-
? command.split(":")[1]
|
|
81
|
-
: undefined;
|
|
82
|
-
|
|
83
|
-
const mode: import("../../domain/models/cli-options").CliMode = isAi ? "ai" : isHome ? "home" : args.includes("--full") ? "full" : "config-only";
|
|
84
|
-
const repositorySearch =
|
|
85
|
-
searchRaw === "true"
|
|
86
|
-
? true
|
|
87
|
-
: searchRaw === "false"
|
|
88
|
-
? false
|
|
89
|
-
: isHome
|
|
90
|
-
? DEFAULTS.home.repositorySearch
|
|
91
|
-
: undefined;
|
|
92
|
-
|
|
93
|
-
const normalizedPath = docsPath.trim();
|
|
94
|
-
|
|
95
|
-
return {
|
|
96
|
-
isBuild,
|
|
97
|
-
isServe,
|
|
98
|
-
mode,
|
|
99
|
-
aiCommand,
|
|
100
|
-
outputDir: outputDir || (isHome ? DEFAULTS.home.outputDir : DEFAULTS.outputDir),
|
|
101
|
-
layoutsDir: normalizeLayoutsDir(layoutsDir || DEFAULTS.layoutsDir),
|
|
102
|
-
useLocalLayoutConfig,
|
|
103
|
-
shouldPush,
|
|
104
|
-
githubOwner,
|
|
105
|
-
githubRepo,
|
|
106
|
-
docsPath: normalizedPath,
|
|
107
|
-
basePath: normalizedPath,
|
|
108
|
-
repositorySearch,
|
|
109
|
-
isInteractive,
|
|
110
|
-
hasArgs: args.length > 0,
|
|
111
|
-
explicit: {
|
|
112
|
-
useLocalLayoutConfig,
|
|
113
|
-
layoutsDir: Boolean(layoutsDir),
|
|
114
|
-
githubOwner: Boolean(githubOwner),
|
|
115
|
-
githubRepo: Boolean(githubRepo),
|
|
116
|
-
outputDir: Boolean(outputDir),
|
|
117
|
-
},
|
|
118
|
-
};
|
|
119
|
-
}
|
|
1
|
+
import type { CliOptions } from "../../domain/models/cli-options";
|
|
2
|
+
import { DEFAULTS } from "./schema";
|
|
3
|
+
import { normalizeLayoutsDir } from "../../contracts/layouts-paths.mjs";
|
|
4
|
+
|
|
5
|
+
const KNOWN_FLAGS = new Set([
|
|
6
|
+
"--build",
|
|
7
|
+
"--serve",
|
|
8
|
+
"--layoutconfig",
|
|
9
|
+
"--full",
|
|
10
|
+
"--push",
|
|
11
|
+
"--home",
|
|
12
|
+
"--search",
|
|
13
|
+
"--path",
|
|
14
|
+
"--output",
|
|
15
|
+
"--layouts-dir",
|
|
16
|
+
"--interactive",
|
|
17
|
+
"-i",
|
|
18
|
+
"--no-interactive",
|
|
19
|
+
"--yes",
|
|
20
|
+
"-y",
|
|
21
|
+
"--ai",
|
|
22
|
+
"--pages-actions",
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
function readOptionValue(args: string[], optionName: string): string {
|
|
26
|
+
const equalsArg = args.find((a) => a.startsWith(`${optionName}=`));
|
|
27
|
+
if (equalsArg) return equalsArg.slice(optionName.length + 1).trim();
|
|
28
|
+
const index = args.indexOf(optionName);
|
|
29
|
+
if (index >= 0) {
|
|
30
|
+
const next = args[index + 1];
|
|
31
|
+
if (next && !next.startsWith("--")) return next.trim();
|
|
32
|
+
}
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function parseCliOptions(argv: string[], env: NodeJS.ProcessEnv): CliOptions {
|
|
37
|
+
const args = argv.slice(2);
|
|
38
|
+
|
|
39
|
+
let githubOwner = readOptionValue(args, "--owner");
|
|
40
|
+
let githubRepo = readOptionValue(args, "--repo");
|
|
41
|
+
const docsPath = readOptionValue(args, "--path");
|
|
42
|
+
const outputDir = readOptionValue(args, "--output");
|
|
43
|
+
const layoutsDir = readOptionValue(args, "--layouts-dir");
|
|
44
|
+
const searchRaw = readOptionValue(args, "--search");
|
|
45
|
+
|
|
46
|
+
const fallbackDashedArgs = args
|
|
47
|
+
.filter((a) => a.startsWith("--"))
|
|
48
|
+
.filter((a) => !KNOWN_FLAGS.has(a))
|
|
49
|
+
.filter((a) => !a.startsWith("--owner"))
|
|
50
|
+
.filter((a) => !a.startsWith("--repo"))
|
|
51
|
+
.filter((a) => !a.startsWith("--path"))
|
|
52
|
+
.filter((a) => !a.startsWith("--home"))
|
|
53
|
+
.filter((a) => !a.startsWith("--output"))
|
|
54
|
+
.filter((a) => !a.startsWith("--layouts-dir"))
|
|
55
|
+
.filter((a) => !a.startsWith("--search"))
|
|
56
|
+
.map((a) => a.replace(/^--/, "").trim())
|
|
57
|
+
.filter(Boolean);
|
|
58
|
+
|
|
59
|
+
if (!githubOwner && fallbackDashedArgs[0]) githubOwner = fallbackDashedArgs[0];
|
|
60
|
+
if (!githubRepo && fallbackDashedArgs[1]) githubRepo = fallbackDashedArgs[1];
|
|
61
|
+
|
|
62
|
+
// New verb aliases (Phase 6) that map onto existing modes without new modes.
|
|
63
|
+
const command = args[0];
|
|
64
|
+
const isDocument = command === "document" || (command?.startsWith("document:") ?? false);
|
|
65
|
+
const isDeploy = command === "deploy" || command === "pages";
|
|
66
|
+
|
|
67
|
+
const isBuild = args.includes("--build") || env.GITPAGEDOCS_BUILD === "1";
|
|
68
|
+
const isServe = args.includes("--serve");
|
|
69
|
+
const useLocalLayoutConfig = args.includes("--layoutconfig");
|
|
70
|
+
const shouldPush = args.includes("--push") || isDeploy;
|
|
71
|
+
const isHome = args.includes("--home");
|
|
72
|
+
const isInteractive = args.includes("--interactive") || args.includes("-i");
|
|
73
|
+
const isAi = command === "ai" || args.includes("--ai") || isDocument;
|
|
74
|
+
const aiCommand =
|
|
75
|
+
command === "ai"
|
|
76
|
+
? args[1]
|
|
77
|
+
: command === "document"
|
|
78
|
+
? args[1] ?? "repo"
|
|
79
|
+
: command?.startsWith("document:")
|
|
80
|
+
? command.split(":")[1]
|
|
81
|
+
: undefined;
|
|
82
|
+
|
|
83
|
+
const mode: import("../../domain/models/cli-options").CliMode = isAi ? "ai" : isHome ? "home" : args.includes("--full") ? "full" : "config-only";
|
|
84
|
+
const repositorySearch =
|
|
85
|
+
searchRaw === "true"
|
|
86
|
+
? true
|
|
87
|
+
: searchRaw === "false"
|
|
88
|
+
? false
|
|
89
|
+
: isHome
|
|
90
|
+
? DEFAULTS.home.repositorySearch
|
|
91
|
+
: undefined;
|
|
92
|
+
|
|
93
|
+
const normalizedPath = docsPath.trim();
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
isBuild,
|
|
97
|
+
isServe,
|
|
98
|
+
mode,
|
|
99
|
+
aiCommand,
|
|
100
|
+
outputDir: outputDir || (isHome ? DEFAULTS.home.outputDir : DEFAULTS.outputDir),
|
|
101
|
+
layoutsDir: normalizeLayoutsDir(layoutsDir || DEFAULTS.layoutsDir),
|
|
102
|
+
useLocalLayoutConfig,
|
|
103
|
+
shouldPush,
|
|
104
|
+
githubOwner,
|
|
105
|
+
githubRepo,
|
|
106
|
+
docsPath: normalizedPath,
|
|
107
|
+
basePath: normalizedPath,
|
|
108
|
+
repositorySearch,
|
|
109
|
+
isInteractive,
|
|
110
|
+
hasArgs: args.length > 0,
|
|
111
|
+
explicit: {
|
|
112
|
+
useLocalLayoutConfig,
|
|
113
|
+
layoutsDir: Boolean(layoutsDir),
|
|
114
|
+
githubOwner: Boolean(githubOwner),
|
|
115
|
+
githubRepo: Boolean(githubRepo),
|
|
116
|
+
outputDir: Boolean(outputDir),
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import type { CliOptions } from "../../domain/models/cli-options";
|
|
2
|
-
import { parseCliOptions } from "./parser";
|
|
3
|
-
import {
|
|
4
|
-
shouldRunInteractive,
|
|
5
|
-
promptConfigOnlyOptions,
|
|
6
|
-
promptHomeOptions,
|
|
7
|
-
promptDeployOptions,
|
|
8
|
-
ensureGitRepoInteractive,
|
|
9
|
-
interactivePromptsAvailable,
|
|
10
|
-
} from "../ui/prompts";
|
|
11
|
-
import { DEFAULTS } from "./schema";
|
|
12
|
-
// @ts-expect-error .mjs runtime module is type-less in this package.
|
|
13
|
-
import { detectRepoFromGit } from "../../runtime/git-ops.mjs";
|
|
14
|
-
|
|
15
|
-
export async function resolveOptions(argv: string[], env: NodeJS.ProcessEnv): Promise<CliOptions> {
|
|
16
|
-
const parsed = parseCliOptions(argv, env);
|
|
17
|
-
|
|
18
|
-
if (parsed.mode === "home") {
|
|
19
|
-
parsed.repositorySearch = parsed.repositorySearch ?? DEFAULTS.home.repositorySearch;
|
|
20
|
-
parsed.basePath = parsed.basePath ?? parsed.docsPath ?? DEFAULTS.home.basePath;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// `deploy` / `--push` need owner + repo AND a git repo. If anything is
|
|
24
|
-
// missing, prompt interactively (owner/repo pre-filled from the git origin
|
|
25
|
-
// remote; offer to `git init`) instead of throwing. In CI/non-TTY we fall
|
|
26
|
-
// through so the explicit guards in the push flow still fire clearly.
|
|
27
|
-
if (parsed.shouldPush && interactivePromptsAvailable()) {
|
|
28
|
-
let resolved = parsed;
|
|
29
|
-
if (!parsed.githubOwner || !parsed.githubRepo) {
|
|
30
|
-
const detected = detectRepoFromGit(process.cwd()) as { owner: string; repo: string } | null;
|
|
31
|
-
resolved = await promptDeployOptions(parsed, detected);
|
|
32
|
-
}
|
|
33
|
-
await ensureGitRepoInteractive(process.cwd());
|
|
34
|
-
return resolved;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Every command prompts in a real terminal; shouldRunInteractive owns the
|
|
38
|
-
// CI / piped-stdin / --no-interactive opt-outs, and each prompt asks only for
|
|
39
|
-
// what the command line left unanswered.
|
|
40
|
-
if (!shouldRunInteractive(argv)) return parsed;
|
|
41
|
-
|
|
42
|
-
if (parsed.mode === "home") return promptHomeOptions(parsed);
|
|
43
|
-
if (parsed.mode === "config-only") return promptConfigOnlyOptions(parsed);
|
|
44
|
-
|
|
45
|
-
return parsed;
|
|
46
|
-
}
|
|
1
|
+
import type { CliOptions } from "../../domain/models/cli-options";
|
|
2
|
+
import { parseCliOptions } from "./parser";
|
|
3
|
+
import {
|
|
4
|
+
shouldRunInteractive,
|
|
5
|
+
promptConfigOnlyOptions,
|
|
6
|
+
promptHomeOptions,
|
|
7
|
+
promptDeployOptions,
|
|
8
|
+
ensureGitRepoInteractive,
|
|
9
|
+
interactivePromptsAvailable,
|
|
10
|
+
} from "../ui/prompts";
|
|
11
|
+
import { DEFAULTS } from "./schema";
|
|
12
|
+
// @ts-expect-error .mjs runtime module is type-less in this package.
|
|
13
|
+
import { detectRepoFromGit } from "../../runtime/git-ops.mjs";
|
|
14
|
+
|
|
15
|
+
export async function resolveOptions(argv: string[], env: NodeJS.ProcessEnv): Promise<CliOptions> {
|
|
16
|
+
const parsed = parseCliOptions(argv, env);
|
|
17
|
+
|
|
18
|
+
if (parsed.mode === "home") {
|
|
19
|
+
parsed.repositorySearch = parsed.repositorySearch ?? DEFAULTS.home.repositorySearch;
|
|
20
|
+
parsed.basePath = parsed.basePath ?? parsed.docsPath ?? DEFAULTS.home.basePath;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// `deploy` / `--push` need owner + repo AND a git repo. If anything is
|
|
24
|
+
// missing, prompt interactively (owner/repo pre-filled from the git origin
|
|
25
|
+
// remote; offer to `git init`) instead of throwing. In CI/non-TTY we fall
|
|
26
|
+
// through so the explicit guards in the push flow still fire clearly.
|
|
27
|
+
if (parsed.shouldPush && interactivePromptsAvailable()) {
|
|
28
|
+
let resolved = parsed;
|
|
29
|
+
if (!parsed.githubOwner || !parsed.githubRepo) {
|
|
30
|
+
const detected = detectRepoFromGit(process.cwd()) as { owner: string; repo: string } | null;
|
|
31
|
+
resolved = await promptDeployOptions(parsed, detected);
|
|
32
|
+
}
|
|
33
|
+
await ensureGitRepoInteractive(process.cwd());
|
|
34
|
+
return resolved;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Every command prompts in a real terminal; shouldRunInteractive owns the
|
|
38
|
+
// CI / piped-stdin / --no-interactive opt-outs, and each prompt asks only for
|
|
39
|
+
// what the command line left unanswered.
|
|
40
|
+
if (!shouldRunInteractive(argv)) return parsed;
|
|
41
|
+
|
|
42
|
+
if (parsed.mode === "home") return promptHomeOptions(parsed);
|
|
43
|
+
if (parsed.mode === "config-only") return promptConfigOnlyOptions(parsed);
|
|
44
|
+
|
|
45
|
+
return parsed;
|
|
46
|
+
}
|
package/presentation/ui/clack.ts
CHANGED
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Thin, cancellation-aware wrappers over @clack/prompts. Centralizes the
|
|
3
|
-
* isCancel handling so prompt modules stay declarative and a Ctrl-C exits
|
|
4
|
-
* cleanly (mirroring the previous inquirer behaviour).
|
|
5
|
-
*/
|
|
6
|
-
import {
|
|
7
|
-
text,
|
|
8
|
-
password,
|
|
9
|
-
confirm,
|
|
10
|
-
select,
|
|
11
|
-
multiselect,
|
|
12
|
-
isCancel,
|
|
13
|
-
cancel,
|
|
14
|
-
} from "@clack/prompts";
|
|
15
|
-
|
|
16
|
-
function exitIfCancelled<T>(value: T | symbol): T {
|
|
17
|
-
if (isCancel(value)) {
|
|
18
|
-
cancel("Operation cancelled.");
|
|
19
|
-
process.exit(0);
|
|
20
|
-
}
|
|
21
|
-
return value as T;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface AskTextOptions {
|
|
25
|
-
message: string;
|
|
26
|
-
defaultValue?: string;
|
|
27
|
-
placeholder?: string;
|
|
28
|
-
validate?: (value: string) => string | undefined;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function askText(options: AskTextOptions): Promise<string> {
|
|
32
|
-
const result = await text({
|
|
33
|
-
message: options.message,
|
|
34
|
-
placeholder: options.placeholder,
|
|
35
|
-
defaultValue: options.defaultValue,
|
|
36
|
-
initialValue: undefined,
|
|
37
|
-
validate: options.validate
|
|
38
|
-
? (value) => options.validate?.(value ?? "")
|
|
39
|
-
: undefined,
|
|
40
|
-
});
|
|
41
|
-
return exitIfCancelled(result);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface AskPasswordOptions {
|
|
45
|
-
message: string;
|
|
46
|
-
validate?: (value: string) => string | undefined;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Masked password prompt (input hidden as the user types). */
|
|
50
|
-
export async function askPassword(options: AskPasswordOptions): Promise<string> {
|
|
51
|
-
const result = await password({
|
|
52
|
-
message: options.message,
|
|
53
|
-
validate: options.validate
|
|
54
|
-
? (value) => options.validate?.(value ?? "")
|
|
55
|
-
: undefined,
|
|
56
|
-
});
|
|
57
|
-
return exitIfCancelled(result);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export async function askConfirm(message: string, initialValue = false): Promise<boolean> {
|
|
61
|
-
const result = await confirm({ message, initialValue });
|
|
62
|
-
return exitIfCancelled(result);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface Choice<T extends string> {
|
|
66
|
-
value: T;
|
|
67
|
-
label: string;
|
|
68
|
-
hint?: string;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export async function askSelect<T extends string>(
|
|
72
|
-
message: string,
|
|
73
|
-
options: Choice<T>[],
|
|
74
|
-
initialValue?: T,
|
|
75
|
-
): Promise<T> {
|
|
76
|
-
// clack's Option<Value> is a conditional type TS can't match against a generic
|
|
77
|
-
// Choice<T> (identical shape); cast at the boundary, inference flows from initialValue.
|
|
78
|
-
const result = await select<T>({ message, options: options as never, initialValue });
|
|
79
|
-
return exitIfCancelled(result);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export async function askMultiSelect<T extends string>(
|
|
83
|
-
message: string,
|
|
84
|
-
options: Choice<T>[],
|
|
85
|
-
initialValues?: T[],
|
|
86
|
-
): Promise<T[]> {
|
|
87
|
-
const result = await multiselect<T>({ message, options: options as never, initialValues, required: true });
|
|
88
|
-
return exitIfCancelled(result);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export { intro, outro, note, spinner } from "@clack/prompts";
|
|
1
|
+
/**
|
|
2
|
+
* Thin, cancellation-aware wrappers over @clack/prompts. Centralizes the
|
|
3
|
+
* isCancel handling so prompt modules stay declarative and a Ctrl-C exits
|
|
4
|
+
* cleanly (mirroring the previous inquirer behaviour).
|
|
5
|
+
*/
|
|
6
|
+
import {
|
|
7
|
+
text,
|
|
8
|
+
password,
|
|
9
|
+
confirm,
|
|
10
|
+
select,
|
|
11
|
+
multiselect,
|
|
12
|
+
isCancel,
|
|
13
|
+
cancel,
|
|
14
|
+
} from "@clack/prompts";
|
|
15
|
+
|
|
16
|
+
function exitIfCancelled<T>(value: T | symbol): T {
|
|
17
|
+
if (isCancel(value)) {
|
|
18
|
+
cancel("Operation cancelled.");
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
return value as T;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AskTextOptions {
|
|
25
|
+
message: string;
|
|
26
|
+
defaultValue?: string;
|
|
27
|
+
placeholder?: string;
|
|
28
|
+
validate?: (value: string) => string | undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function askText(options: AskTextOptions): Promise<string> {
|
|
32
|
+
const result = await text({
|
|
33
|
+
message: options.message,
|
|
34
|
+
placeholder: options.placeholder,
|
|
35
|
+
defaultValue: options.defaultValue,
|
|
36
|
+
initialValue: undefined,
|
|
37
|
+
validate: options.validate
|
|
38
|
+
? (value) => options.validate?.(value ?? "")
|
|
39
|
+
: undefined,
|
|
40
|
+
});
|
|
41
|
+
return exitIfCancelled(result);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface AskPasswordOptions {
|
|
45
|
+
message: string;
|
|
46
|
+
validate?: (value: string) => string | undefined;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Masked password prompt (input hidden as the user types). */
|
|
50
|
+
export async function askPassword(options: AskPasswordOptions): Promise<string> {
|
|
51
|
+
const result = await password({
|
|
52
|
+
message: options.message,
|
|
53
|
+
validate: options.validate
|
|
54
|
+
? (value) => options.validate?.(value ?? "")
|
|
55
|
+
: undefined,
|
|
56
|
+
});
|
|
57
|
+
return exitIfCancelled(result);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function askConfirm(message: string, initialValue = false): Promise<boolean> {
|
|
61
|
+
const result = await confirm({ message, initialValue });
|
|
62
|
+
return exitIfCancelled(result);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface Choice<T extends string> {
|
|
66
|
+
value: T;
|
|
67
|
+
label: string;
|
|
68
|
+
hint?: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export async function askSelect<T extends string>(
|
|
72
|
+
message: string,
|
|
73
|
+
options: Choice<T>[],
|
|
74
|
+
initialValue?: T,
|
|
75
|
+
): Promise<T> {
|
|
76
|
+
// clack's Option<Value> is a conditional type TS can't match against a generic
|
|
77
|
+
// Choice<T> (identical shape); cast at the boundary, inference flows from initialValue.
|
|
78
|
+
const result = await select<T>({ message, options: options as never, initialValue });
|
|
79
|
+
return exitIfCancelled(result);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export async function askMultiSelect<T extends string>(
|
|
83
|
+
message: string,
|
|
84
|
+
options: Choice<T>[],
|
|
85
|
+
initialValues?: T[],
|
|
86
|
+
): Promise<T[]> {
|
|
87
|
+
const result = await multiselect<T>({ message, options: options as never, initialValues, required: true });
|
|
88
|
+
return exitIfCancelled(result);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { intro, outro, note, spinner } from "@clack/prompts";
|