@kidd-cli/cli 0.1.2 → 0.1.4
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/commands/add/command.mjs +7 -24
- package/dist/commands/add/index.mjs +1 -3
- package/dist/commands/add/middleware.mjs +5 -21
- package/dist/commands/build.mjs +3 -16
- package/dist/commands/commands.mjs +4 -18
- package/dist/commands/dev.mjs +3 -16
- package/dist/commands/doctor.mjs +15 -32
- package/dist/commands/init.mjs +26 -20
- package/dist/config-helpers-wZhBJJXJ.mjs +13 -0
- package/dist/{detect-CSSt9GdX.mjs → detect-DcO0_CWy.mjs} +3 -15
- package/dist/index.mjs +1 -4
- package/dist/lib/templates/project/package.json.liquid +5 -4
- package/dist/lib/templates/project/tsconfig.json.liquid +1 -1
- package/dist/{write-DDGnajpV.mjs → write-CdoqLFeH.mjs} +21 -24
- package/package.json +11 -9
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { n as renderTemplate, t as writeFiles } from "../../write-
|
|
2
|
-
import { t as detectProject } from "../../detect-
|
|
1
|
+
import { n as isKebabCase, r as renderTemplate, t as writeFiles } from "../../write-CdoqLFeH.mjs";
|
|
2
|
+
import { t as detectProject } from "../../detect-DcO0_CWy.mjs";
|
|
3
3
|
import { command } from "@kidd-cli/core";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { loadConfig } from "@kidd-cli/config/loader";
|
|
6
6
|
import { z } from "zod";
|
|
7
|
-
|
|
8
7
|
//#region src/commands/add/command.ts
|
|
9
|
-
const KEBAB_CASE_CHARS_RE = /^[a-z][\da-z-]*$/;
|
|
10
8
|
const addCommandCommand = command({
|
|
11
9
|
args: z.object({
|
|
12
10
|
args: z.boolean().describe("Include args schema").optional(),
|
|
@@ -18,8 +16,7 @@ const addCommandCommand = command({
|
|
|
18
16
|
const [detectError, project] = await detectProject(process.cwd());
|
|
19
17
|
if (detectError) return ctx.fail(detectError.message);
|
|
20
18
|
if (!project) return ctx.fail("Not in a kidd project. Run `kidd init` first.");
|
|
21
|
-
const [
|
|
22
|
-
if (configError) {}
|
|
19
|
+
const [, configResult] = await loadConfig({ cwd: project.rootDir });
|
|
23
20
|
const commandName = await resolveCommandName(ctx);
|
|
24
21
|
const commandDescription = await resolveDescription(ctx);
|
|
25
22
|
const includeArgs = await resolveIncludeArgs(ctx);
|
|
@@ -50,24 +47,11 @@ const addCommandCommand = command({
|
|
|
50
47
|
return ctx.fail(writeError.message);
|
|
51
48
|
}
|
|
52
49
|
ctx.spinner.stop("Command created!");
|
|
53
|
-
result.written.map((file) =>
|
|
54
|
-
|
|
50
|
+
const summary = [...result.written.map((file) => ` created ${file}`), ...result.skipped.map((file) => ` skipped ${file} (already exists)`)].join("\n");
|
|
51
|
+
if (summary.length > 0) ctx.output.raw(summary);
|
|
55
52
|
}
|
|
56
53
|
});
|
|
57
54
|
/**
|
|
58
|
-
* Check whether a string is valid kebab-case.
|
|
59
|
-
*
|
|
60
|
-
* @param value - The string to validate.
|
|
61
|
-
* @returns True when the string is kebab-case.
|
|
62
|
-
* @private
|
|
63
|
-
*/
|
|
64
|
-
function isKebabCase(value) {
|
|
65
|
-
if (!KEBAB_CASE_CHARS_RE.test(value)) return false;
|
|
66
|
-
if (value.endsWith("-")) return false;
|
|
67
|
-
if (value.includes("--")) return false;
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
55
|
* Resolve the command name from args or prompt.
|
|
72
56
|
*
|
|
73
57
|
* @param ctx - Command context.
|
|
@@ -110,7 +94,7 @@ async function resolveDescription(ctx) {
|
|
|
110
94
|
* @private
|
|
111
95
|
*/
|
|
112
96
|
async function resolveIncludeArgs(ctx) {
|
|
113
|
-
if (ctx.args.args !== void 0
|
|
97
|
+
if (ctx.args.args !== void 0) return ctx.args.args;
|
|
114
98
|
return ctx.prompts.confirm({
|
|
115
99
|
initialValue: true,
|
|
116
100
|
message: "Include args schema?"
|
|
@@ -132,6 +116,5 @@ function resolveCommandsDir(configResult, rootDir) {
|
|
|
132
116
|
if (configResult) return join(rootDir, configResult.config.commands ?? DEFAULT_COMMANDS);
|
|
133
117
|
return join(rootDir, DEFAULT_COMMANDS);
|
|
134
118
|
}
|
|
135
|
-
|
|
136
119
|
//#endregion
|
|
137
|
-
export { addCommandCommand as default };
|
|
120
|
+
export { addCommandCommand as default };
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { n as renderTemplate, t as writeFiles } from "../../write-
|
|
2
|
-
import { t as detectProject } from "../../detect-
|
|
1
|
+
import { n as isKebabCase, r as renderTemplate, t as writeFiles } from "../../write-CdoqLFeH.mjs";
|
|
2
|
+
import { t as detectProject } from "../../detect-DcO0_CWy.mjs";
|
|
3
3
|
import { command } from "@kidd-cli/core";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
-
|
|
7
6
|
//#region src/commands/add/middleware.ts
|
|
8
|
-
const KEBAB_CASE_CHARS_RE = /^[a-z][\da-z-]*$/;
|
|
9
7
|
const addMiddlewareCommand = command({
|
|
10
8
|
args: z.object({
|
|
11
9
|
description: z.string().describe("Middleware description").optional(),
|
|
@@ -44,24 +42,11 @@ const addMiddlewareCommand = command({
|
|
|
44
42
|
return ctx.fail(writeError.message);
|
|
45
43
|
}
|
|
46
44
|
ctx.spinner.stop("Middleware created!");
|
|
47
|
-
result.written.map((file) =>
|
|
48
|
-
|
|
45
|
+
const summary = [...result.written.map((file) => ` created ${file}`), ...result.skipped.map((file) => ` skipped ${file} (already exists)`)].join("\n");
|
|
46
|
+
if (summary.length > 0) ctx.output.raw(summary);
|
|
49
47
|
}
|
|
50
48
|
});
|
|
51
49
|
/**
|
|
52
|
-
* Check whether a string is valid kebab-case.
|
|
53
|
-
*
|
|
54
|
-
* @param value - The string to validate.
|
|
55
|
-
* @returns True when the string is kebab-case.
|
|
56
|
-
* @private
|
|
57
|
-
*/
|
|
58
|
-
function isKebabCase(value) {
|
|
59
|
-
if (!KEBAB_CASE_CHARS_RE.test(value)) return false;
|
|
60
|
-
if (value.endsWith("-")) return false;
|
|
61
|
-
if (value.includes("--")) return false;
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
50
|
* Resolve the middleware name from args or prompt.
|
|
66
51
|
*
|
|
67
52
|
* @param ctx - Command context.
|
|
@@ -96,6 +81,5 @@ async function resolveDescription(ctx) {
|
|
|
96
81
|
placeholder: "What does this middleware do?"
|
|
97
82
|
});
|
|
98
83
|
}
|
|
99
|
-
|
|
100
84
|
//#endregion
|
|
101
|
-
export { addMiddlewareCommand as default };
|
|
85
|
+
export { addMiddlewareCommand as default };
|
package/dist/commands/build.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { t as extractConfig } from "../config-helpers-wZhBJJXJ.mjs";
|
|
1
2
|
import { command } from "@kidd-cli/core";
|
|
2
3
|
import { relative } from "node:path";
|
|
3
4
|
import { build, compile, resolveTargetLabel } from "@kidd-cli/bundler";
|
|
4
5
|
import { loadConfig } from "@kidd-cli/config/loader";
|
|
5
6
|
import { z } from "zod";
|
|
6
|
-
|
|
7
7
|
//#region src/commands/build.ts
|
|
8
8
|
/**
|
|
9
9
|
* Build a kidd CLI project for production using tsdown.
|
|
@@ -21,9 +21,8 @@ const buildCommand = command({
|
|
|
21
21
|
description: "Build a kidd CLI project for production",
|
|
22
22
|
handler: async (ctx) => {
|
|
23
23
|
const cwd = process.cwd();
|
|
24
|
-
const [
|
|
24
|
+
const [, configResult] = await loadConfig({ cwd });
|
|
25
25
|
const config = extractConfig(configResult);
|
|
26
|
-
if (configError) {}
|
|
27
26
|
ctx.spinner.start("Bundling with tsdown...");
|
|
28
27
|
const [buildError, buildOutput] = await build({
|
|
29
28
|
config,
|
|
@@ -73,17 +72,6 @@ const buildCommand = command({
|
|
|
73
72
|
}
|
|
74
73
|
});
|
|
75
74
|
/**
|
|
76
|
-
* Extract a KiddConfig from a load result, falling back to empty defaults.
|
|
77
|
-
*
|
|
78
|
-
* @private
|
|
79
|
-
* @param result - The result from loadConfig, or null when loading failed.
|
|
80
|
-
* @returns The loaded config or an empty object (all KiddConfig fields are optional).
|
|
81
|
-
*/
|
|
82
|
-
function extractConfig(result) {
|
|
83
|
-
if (result) return result.config;
|
|
84
|
-
return {};
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
75
|
* Determine whether compilation should run based on CLI flags and config.
|
|
88
76
|
*
|
|
89
77
|
* Resolution order:
|
|
@@ -158,6 +146,5 @@ function formatBinariesNote(params) {
|
|
|
158
146
|
const maxLen = Math.max(...params.binaries.map((b) => b.label.length));
|
|
159
147
|
return params.binaries.map((binary) => `${binary.label.padEnd(maxLen)} ${relative(params.cwd, binary.path)}`).join("\n");
|
|
160
148
|
}
|
|
161
|
-
|
|
162
149
|
//#endregion
|
|
163
|
-
export { buildCommand as default };
|
|
150
|
+
export { buildCommand as default };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { t as extractConfig } from "../config-helpers-wZhBJJXJ.mjs";
|
|
1
2
|
import { autoload, command } from "@kidd-cli/core";
|
|
2
3
|
import { join } from "node:path";
|
|
3
4
|
import { loadConfig } from "@kidd-cli/config/loader";
|
|
4
5
|
import { existsSync } from "node:fs";
|
|
5
|
-
|
|
6
6
|
//#region src/commands/commands.ts
|
|
7
7
|
/**
|
|
8
8
|
* Display the command tree for a kidd CLI project.
|
|
@@ -15,10 +15,8 @@ const commandsCommand = command({
|
|
|
15
15
|
description: "Display the command tree for a kidd CLI project",
|
|
16
16
|
handler: async (ctx) => {
|
|
17
17
|
const cwd = process.cwd();
|
|
18
|
-
const [
|
|
19
|
-
const
|
|
20
|
-
if (configError) {}
|
|
21
|
-
const commandsDir = join(cwd, config.commands ?? "commands");
|
|
18
|
+
const [, configResult] = await loadConfig({ cwd });
|
|
19
|
+
const commandsDir = join(cwd, extractConfig(configResult).commands ?? "commands");
|
|
22
20
|
if (!existsSync(commandsDir)) ctx.fail(`Commands directory not found: ${commandsDir}`);
|
|
23
21
|
ctx.spinner.start("Scanning commands...");
|
|
24
22
|
const tree = await buildTree(await autoload({ dir: commandsDir }));
|
|
@@ -31,17 +29,6 @@ const commandsCommand = command({
|
|
|
31
29
|
}
|
|
32
30
|
});
|
|
33
31
|
/**
|
|
34
|
-
* Extract a KiddConfig from a load result, falling back to empty defaults.
|
|
35
|
-
*
|
|
36
|
-
* @private
|
|
37
|
-
* @param result - The result from loadConfig, or null when loading failed.
|
|
38
|
-
* @returns The loaded config or an empty object (all KiddConfig fields are optional).
|
|
39
|
-
*/
|
|
40
|
-
function extractConfig(result) {
|
|
41
|
-
if (result) return result.config;
|
|
42
|
-
return {};
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
32
|
* Resolve a command's subcommands field, which may be a Promise, a map, or undefined.
|
|
46
33
|
*
|
|
47
34
|
* @private
|
|
@@ -130,6 +117,5 @@ function formatLabel(name, description) {
|
|
|
130
117
|
if (description) return `${name} — ${description}`;
|
|
131
118
|
return name;
|
|
132
119
|
}
|
|
133
|
-
|
|
134
120
|
//#endregion
|
|
135
|
-
export { commandsCommand as default };
|
|
121
|
+
export { commandsCommand as default };
|
package/dist/commands/dev.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { t as extractConfig } from "../config-helpers-wZhBJJXJ.mjs";
|
|
1
2
|
import { command } from "@kidd-cli/core";
|
|
2
3
|
import { watch } from "@kidd-cli/bundler";
|
|
3
4
|
import { loadConfig } from "@kidd-cli/config/loader";
|
|
4
|
-
|
|
5
5
|
//#region src/commands/dev.ts
|
|
6
6
|
/**
|
|
7
7
|
* Start a kidd CLI project in development mode with file watching.
|
|
@@ -13,9 +13,8 @@ const devCommand = command({
|
|
|
13
13
|
description: "Start a kidd CLI project in development mode",
|
|
14
14
|
handler: async (ctx) => {
|
|
15
15
|
const cwd = process.cwd();
|
|
16
|
-
const [
|
|
16
|
+
const [, configResult] = await loadConfig({ cwd });
|
|
17
17
|
const config = extractConfig(configResult);
|
|
18
|
-
if (configError) {}
|
|
19
18
|
ctx.spinner.start("Starting dev server...");
|
|
20
19
|
const [watchError] = await watch({
|
|
21
20
|
config,
|
|
@@ -29,17 +28,6 @@ const devCommand = command({
|
|
|
29
28
|
}
|
|
30
29
|
});
|
|
31
30
|
/**
|
|
32
|
-
* Extract a KiddConfig from a load result, falling back to empty defaults.
|
|
33
|
-
*
|
|
34
|
-
* @private
|
|
35
|
-
* @param result - The result from loadConfig, or null when loading failed.
|
|
36
|
-
* @returns The loaded config or an empty object (all KiddConfig fields are optional).
|
|
37
|
-
*/
|
|
38
|
-
function extractConfig(result) {
|
|
39
|
-
if (result) return result.config;
|
|
40
|
-
return {};
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
31
|
* Create an onSuccess callback that tracks first-build state.
|
|
44
32
|
*
|
|
45
33
|
* On the first invocation the spinner is stopped and a "watching" message is
|
|
@@ -63,6 +51,5 @@ function createOnSuccess(ctx) {
|
|
|
63
51
|
ctx.logger.success("Rebuilt successfully");
|
|
64
52
|
};
|
|
65
53
|
}
|
|
66
|
-
|
|
67
54
|
//#endregion
|
|
68
|
-
export { devCommand as default };
|
|
55
|
+
export { devCommand as default };
|
package/dist/commands/doctor.mjs
CHANGED
|
@@ -3,11 +3,11 @@ import { dirname, join, relative } from "node:path";
|
|
|
3
3
|
import { readManifest } from "@kidd-cli/utils/manifest";
|
|
4
4
|
import { loadConfig } from "@kidd-cli/config/loader";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
+
import { attemptAsync, err, match, ok } from "@kidd-cli/utils/fp";
|
|
6
7
|
import pc from "picocolors";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
8
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
9
|
+
import { fileExists } from "@kidd-cli/utils/fs";
|
|
9
10
|
import { jsonParse, jsonStringify } from "@kidd-cli/utils/json";
|
|
10
|
-
|
|
11
11
|
//#region src/lib/checks.ts
|
|
12
12
|
/**
|
|
13
13
|
* Default entry point for the CLI source.
|
|
@@ -440,17 +440,6 @@ async function readRawPackageJson(cwd) {
|
|
|
440
440
|
return ok(data);
|
|
441
441
|
}
|
|
442
442
|
/**
|
|
443
|
-
* Check whether a path exists on disk.
|
|
444
|
-
*
|
|
445
|
-
* @private
|
|
446
|
-
* @param filePath - The path to check.
|
|
447
|
-
* @returns True when the path is accessible, false otherwise.
|
|
448
|
-
*/
|
|
449
|
-
async function fileExists(filePath) {
|
|
450
|
-
const [accessError] = await attemptAsync(() => access(filePath));
|
|
451
|
-
return accessError === null;
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
443
|
* Extract a KiddConfig from a load result, returning null when absent.
|
|
455
444
|
*
|
|
456
445
|
* @private
|
|
@@ -503,7 +492,6 @@ async function updatePackageJson(cwd, transform) {
|
|
|
503
492
|
if (writeError) return err(`Failed to write package.json: ${writeError.message}`);
|
|
504
493
|
return ok();
|
|
505
494
|
}
|
|
506
|
-
|
|
507
495
|
//#endregion
|
|
508
496
|
//#region src/commands/doctor.ts
|
|
509
497
|
/**
|
|
@@ -618,24 +606,23 @@ async function applyFixes(results, context) {
|
|
|
618
606
|
* @param fixResults - The fix results (empty when --fix was not used).
|
|
619
607
|
*/
|
|
620
608
|
function displayResults(ctx, results, fixResults) {
|
|
621
|
-
results.map((result) => formatResultLine(
|
|
609
|
+
const output = results.map((result) => formatResultLine(result, fixResults)).join("");
|
|
610
|
+
if (output.length > 0) ctx.output.raw(output);
|
|
622
611
|
}
|
|
623
612
|
/**
|
|
624
|
-
* Format
|
|
613
|
+
* Format a single check result line with optional hint.
|
|
625
614
|
*
|
|
626
615
|
* @private
|
|
627
|
-
* @param
|
|
628
|
-
* @param result - The check result to display.
|
|
616
|
+
* @param result - The check result to format.
|
|
629
617
|
* @param fixResults - The fix results to check for applied fixes.
|
|
618
|
+
* @returns The formatted result line string.
|
|
630
619
|
*/
|
|
631
|
-
function formatResultLine(
|
|
620
|
+
function formatResultLine(result, fixResults) {
|
|
632
621
|
const appliedFix = fixResults.find((f) => f.name === result.name && f.fixed);
|
|
633
|
-
if (appliedFix) {
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
ctx.output.raw(` ${formatDisplayStatus(result.status)} ${result.name} - ${result.message}\n`);
|
|
638
|
-
if (result.hint && result.status !== "pass") ctx.output.raw(` ${pc.dim(`→ ${result.hint}`)}\n`);
|
|
622
|
+
if (appliedFix) return ` ${formatDisplayStatus("fix")} ${result.name} - ${appliedFix.message}\n`;
|
|
623
|
+
const line = ` ${formatDisplayStatus(result.status)} ${result.name} - ${result.message}\n`;
|
|
624
|
+
if (result.hint && result.status !== "pass") return `${line} ${pc.dim(`→ ${result.hint}`)}\n`;
|
|
625
|
+
return line;
|
|
639
626
|
}
|
|
640
627
|
/**
|
|
641
628
|
* Format a display status with color.
|
|
@@ -647,10 +634,7 @@ function formatResultLine(ctx, result, fixResults) {
|
|
|
647
634
|
* @returns A colored string representation of the status.
|
|
648
635
|
*/
|
|
649
636
|
function formatDisplayStatus(status) {
|
|
650
|
-
|
|
651
|
-
if (status === "warn") return pc.yellow("warn");
|
|
652
|
-
if (status === "fix") return pc.blue("fix ");
|
|
653
|
-
return pc.red("fail");
|
|
637
|
+
return match(status).with("pass", () => pc.green("pass")).with("warn", () => pc.yellow("warn")).with("fix", () => pc.blue("fix ")).with("fail", () => pc.red("fail")).exhaustive();
|
|
654
638
|
}
|
|
655
639
|
/**
|
|
656
640
|
* Format the summary line with counts.
|
|
@@ -675,6 +659,5 @@ function pluralizeCheck(count) {
|
|
|
675
659
|
if (count === 1) return "check";
|
|
676
660
|
return "checks";
|
|
677
661
|
}
|
|
678
|
-
|
|
679
662
|
//#endregion
|
|
680
|
-
export { doctorCommand as default };
|
|
663
|
+
export { doctorCommand as default };
|
package/dist/commands/init.mjs
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
import { n as renderTemplate, t as writeFiles } from "../write-
|
|
1
|
+
import { n as isKebabCase, r as renderTemplate, t as writeFiles } from "../write-CdoqLFeH.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { command } from "@kidd-cli/core";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { readManifest } from "@kidd-cli/utils/manifest";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { attempt } from "@kidd-cli/utils/fp";
|
|
8
|
-
|
|
8
|
+
//#region src/generated/template-versions.ts
|
|
9
|
+
/**
|
|
10
|
+
* Zod version from the workspace catalog.
|
|
11
|
+
*/
|
|
12
|
+
const ZOD_VERSION = "^4.3.6";
|
|
13
|
+
/**
|
|
14
|
+
* TypeScript version from the workspace catalog.
|
|
15
|
+
*/
|
|
16
|
+
const TYPESCRIPT_VERSION = "^5.9.3";
|
|
17
|
+
/**
|
|
18
|
+
* Vitest version from the workspace catalog.
|
|
19
|
+
*/
|
|
20
|
+
const VITEST_VERSION = "^4.0.18";
|
|
21
|
+
/**
|
|
22
|
+
* Tsdown version from the workspace catalog.
|
|
23
|
+
*/
|
|
24
|
+
const TSDOWN_VERSION = "^0.21.1";
|
|
25
|
+
//#endregion
|
|
9
26
|
//#region src/commands/init.ts
|
|
10
|
-
const KEBAB_CASE_CHARS_RE = /^[a-z][\da-z-]*$/;
|
|
11
27
|
const initCommand = command({
|
|
12
28
|
args: z.object({
|
|
13
29
|
description: z.string().describe("Project description").optional(),
|
|
@@ -35,7 +51,11 @@ const initCommand = command({
|
|
|
35
51
|
coreVersion,
|
|
36
52
|
description: projectDescription,
|
|
37
53
|
name: projectName,
|
|
38
|
-
packageManager
|
|
54
|
+
packageManager,
|
|
55
|
+
tsdownVersion: TSDOWN_VERSION,
|
|
56
|
+
typescriptVersion: TYPESCRIPT_VERSION,
|
|
57
|
+
vitestVersion: VITEST_VERSION,
|
|
58
|
+
zodVersion: ZOD_VERSION
|
|
39
59
|
}
|
|
40
60
|
});
|
|
41
61
|
if (renderError) {
|
|
@@ -59,19 +79,6 @@ const initCommand = command({
|
|
|
59
79
|
}
|
|
60
80
|
});
|
|
61
81
|
/**
|
|
62
|
-
* Check whether a string is valid kebab-case.
|
|
63
|
-
*
|
|
64
|
-
* @param value - The string to validate.
|
|
65
|
-
* @returns True when the string is kebab-case.
|
|
66
|
-
* @private
|
|
67
|
-
*/
|
|
68
|
-
function isKebabCase(value) {
|
|
69
|
-
if (!KEBAB_CASE_CHARS_RE.test(value)) return false;
|
|
70
|
-
if (value.endsWith("-")) return false;
|
|
71
|
-
if (value.includes("--")) return false;
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
82
|
* Resolve the project name from args or prompt.
|
|
76
83
|
*
|
|
77
84
|
* @param ctx - Command context.
|
|
@@ -141,7 +148,7 @@ async function resolvePackageManager(ctx) {
|
|
|
141
148
|
* @private
|
|
142
149
|
*/
|
|
143
150
|
async function resolveIncludeExample(ctx) {
|
|
144
|
-
if (ctx.args.example !== void 0
|
|
151
|
+
if (ctx.args.example !== void 0) return ctx.args.example;
|
|
145
152
|
return ctx.prompts.confirm({
|
|
146
153
|
initialValue: true,
|
|
147
154
|
message: "Include example command?"
|
|
@@ -204,6 +211,5 @@ async function resolveDependencyVersion(packageName) {
|
|
|
204
211
|
if (manifestError || !manifest.version) return DEFAULT_VERSION;
|
|
205
212
|
return manifest.version;
|
|
206
213
|
}
|
|
207
|
-
|
|
208
214
|
//#endregion
|
|
209
|
-
export { initCommand as default };
|
|
215
|
+
export { initCommand as default };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/lib/config-helpers.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extract a KiddConfig from a load result, falling back to empty defaults.
|
|
4
|
+
*
|
|
5
|
+
* @param result - The result from loadConfig, or null when loading failed.
|
|
6
|
+
* @returns The loaded config or an empty object (all KiddConfig fields are optional).
|
|
7
|
+
*/
|
|
8
|
+
function extractConfig(result) {
|
|
9
|
+
if (result) return result.config;
|
|
10
|
+
return {};
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { extractConfig as t };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
import { access, readFile } from "node:fs/promises";
|
|
3
2
|
import { attemptAsync, ok, toErrorMessage } from "@kidd-cli/utils/fp";
|
|
4
|
-
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { fileExists } from "@kidd-cli/utils/fs";
|
|
5
5
|
//#region src/lib/detect.ts
|
|
6
6
|
/**
|
|
7
7
|
* Detect whether the given directory contains a kidd-based CLI project.
|
|
@@ -57,17 +57,5 @@ async function readPackageJson(filePath) {
|
|
|
57
57
|
}, null];
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
/**
|
|
61
|
-
* Check whether a path exists on disk.
|
|
62
|
-
*
|
|
63
|
-
* @param filePath - The path to check.
|
|
64
|
-
* @returns True when the path is accessible, false otherwise.
|
|
65
|
-
* @private
|
|
66
|
-
*/
|
|
67
|
-
async function fileExists(filePath) {
|
|
68
|
-
const [err] = await attemptAsync(() => access(filePath));
|
|
69
|
-
return err === null;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
60
|
//#endregion
|
|
73
|
-
export { detectProject as t };
|
|
61
|
+
export { detectProject as t };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { cli } from "@kidd-cli/core";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { readManifest } from "@kidd-cli/utils/manifest";
|
|
4
|
-
|
|
5
4
|
//#region src/manifest.ts
|
|
6
5
|
/**
|
|
7
6
|
* Read and validate the CLI package manifest.
|
|
@@ -26,7 +25,6 @@ async function loadCLIManifest(baseDir) {
|
|
|
26
25
|
version: manifest.version
|
|
27
26
|
};
|
|
28
27
|
}
|
|
29
|
-
|
|
30
28
|
//#endregion
|
|
31
29
|
//#region src/index.ts
|
|
32
30
|
const manifest = await loadCLIManifest(import.meta.dirname);
|
|
@@ -36,6 +34,5 @@ await cli({
|
|
|
36
34
|
name: manifest.name,
|
|
37
35
|
version: manifest.version
|
|
38
36
|
});
|
|
39
|
-
|
|
40
37
|
//#endregion
|
|
41
|
-
export {
|
|
38
|
+
export {};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
8
|
-
"{{ name }}": "./dist/index.
|
|
8
|
+
"{{ name }}": "./dist/index.mjs"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"dist"
|
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@kidd-cli/core": "^{{ coreVersion }}",
|
|
22
|
-
"zod": "
|
|
22
|
+
"zod": "{{ zodVersion }}"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@kidd-cli/cli": "^{{ cliVersion }}",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
26
|
+
"tsdown": "{{ tsdownVersion }}",
|
|
27
|
+
"typescript": "{{ typescriptVersion }}",
|
|
28
|
+
"vitest": "{{ vitestVersion }}"
|
|
28
29
|
}
|
|
29
30
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { dirname, join, relative } from "node:path";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { ok, toErrorMessage } from "@kidd-cli/utils/fp";
|
|
3
|
+
import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
4
|
+
import { fileExists } from "@kidd-cli/utils/fs";
|
|
4
5
|
import { Liquid } from "liquidjs";
|
|
5
|
-
|
|
6
6
|
//#region src/lib/render.ts
|
|
7
7
|
/**
|
|
8
8
|
* Render all `.liquid` templates in a directory using LiquidJS.
|
|
@@ -91,7 +91,21 @@ function isGenerateError(value) {
|
|
|
91
91
|
if (typeof value !== "object" || value === null) return false;
|
|
92
92
|
return "type" in value && "message" in value;
|
|
93
93
|
}
|
|
94
|
-
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/lib/validate.ts
|
|
96
|
+
const KEBAB_CASE_CHARS_RE = /^[a-z][\da-z-]*$/;
|
|
97
|
+
/**
|
|
98
|
+
* Check whether a string is valid kebab-case.
|
|
99
|
+
*
|
|
100
|
+
* @param value - The string to validate.
|
|
101
|
+
* @returns True when the string is kebab-case.
|
|
102
|
+
*/
|
|
103
|
+
function isKebabCase(value) {
|
|
104
|
+
if (!KEBAB_CASE_CHARS_RE.test(value)) return false;
|
|
105
|
+
if (value.endsWith("-")) return false;
|
|
106
|
+
if (value.includes("--")) return false;
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
95
109
|
//#endregion
|
|
96
110
|
//#region src/lib/write.ts
|
|
97
111
|
/**
|
|
@@ -105,18 +119,13 @@ function isGenerateError(value) {
|
|
|
105
119
|
* @returns An async Result with counts of written/skipped files or a GenerateError.
|
|
106
120
|
*/
|
|
107
121
|
async function writeFiles(params) {
|
|
108
|
-
const written = [];
|
|
109
|
-
const skipped = [];
|
|
110
122
|
const results = await Promise.all(params.files.map((file) => writeSingleFile(file, params.outputDir, params.overwrite)));
|
|
111
123
|
const firstError = results.find((r) => r[0] !== null);
|
|
112
124
|
if (firstError) return [firstError[0], null];
|
|
113
125
|
const validStatuses = results.filter((r) => r[1] !== null);
|
|
114
|
-
const
|
|
115
|
-
const skippedPaths = validStatuses.filter(([, status]) => status.action === "skipped").map(([, status]) => status.path);
|
|
116
|
-
writtenPaths.map((p) => written.push(p));
|
|
117
|
-
skippedPaths.map((p) => skipped.push(p));
|
|
126
|
+
const written = validStatuses.filter(([, status]) => status.action === "written").map(([, status]) => status.path);
|
|
118
127
|
return ok({
|
|
119
|
-
skipped,
|
|
128
|
+
skipped: validStatuses.filter(([, status]) => status.action === "skipped").map(([, status]) => status.path),
|
|
120
129
|
written
|
|
121
130
|
});
|
|
122
131
|
}
|
|
@@ -150,17 +159,5 @@ async function writeSingleFile(file, outputDir, overwrite) {
|
|
|
150
159
|
}, null];
|
|
151
160
|
}
|
|
152
161
|
}
|
|
153
|
-
/**
|
|
154
|
-
* Check whether a path exists on disk.
|
|
155
|
-
*
|
|
156
|
-
* @param filePath - The path to check.
|
|
157
|
-
* @returns True when the path is accessible, false otherwise.
|
|
158
|
-
* @private
|
|
159
|
-
*/
|
|
160
|
-
async function fileExists(filePath) {
|
|
161
|
-
const [err] = await attemptAsync(() => access(filePath));
|
|
162
|
-
return err === null;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
162
|
//#endregion
|
|
166
|
-
export {
|
|
163
|
+
export { isKebabCase as n, renderTemplate as r, writeFiles as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kidd-cli/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "DX companion CLI for the kidd framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -22,20 +22,21 @@
|
|
|
22
22
|
],
|
|
23
23
|
"type": "module",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"fs-extra": "^11.3.
|
|
26
|
-
"liquidjs": "^10.
|
|
25
|
+
"fs-extra": "^11.3.4",
|
|
26
|
+
"liquidjs": "^10.25.0",
|
|
27
27
|
"picocolors": "^1.1.1",
|
|
28
28
|
"zod": "^4.3.6",
|
|
29
|
-
"@kidd-cli/bundler": "0.1.
|
|
30
|
-
"@kidd-cli/config": "0.1.
|
|
31
|
-
"@kidd-cli/core": "0.
|
|
32
|
-
"@kidd-cli/utils": "0.1.
|
|
29
|
+
"@kidd-cli/bundler": "0.1.3",
|
|
30
|
+
"@kidd-cli/config": "0.1.3",
|
|
31
|
+
"@kidd-cli/core": "0.3.0",
|
|
32
|
+
"@kidd-cli/utils": "0.1.3"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/fs-extra": "^11.0.4",
|
|
36
|
-
"tsdown": "0.21.
|
|
36
|
+
"tsdown": "0.21.1",
|
|
37
37
|
"typescript": "^5.9.3",
|
|
38
|
-
"vitest": "^4.0.18"
|
|
38
|
+
"vitest": "^4.0.18",
|
|
39
|
+
"yaml": "^2.8.0"
|
|
39
40
|
},
|
|
40
41
|
"scripts": {
|
|
41
42
|
"build": "tsdown && mkdir -p dist/lib && cp -r src/lib/templates dist/lib/templates",
|
|
@@ -43,6 +44,7 @@
|
|
|
43
44
|
"lint": "oxlint --ignore-pattern node_modules",
|
|
44
45
|
"lint:fix": "oxlint --fix --ignore-pattern node_modules",
|
|
45
46
|
"test": "vitest run",
|
|
47
|
+
"test:coverage": "vitest run --coverage",
|
|
46
48
|
"test:watch": "vitest"
|
|
47
49
|
}
|
|
48
50
|
}
|