hatchkit 0.1.13 → 0.1.15
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/adopt.d.ts.map +1 -1
- package/dist/adopt.js +4 -3
- package/dist/adopt.js.map +1 -1
- package/dist/deploy/coolify.d.ts.map +1 -1
- package/dist/deploy/coolify.js +6 -1
- package/dist/deploy/coolify.js.map +1 -1
- package/dist/deploy/pages.js.map +1 -1
- package/dist/index.js +22 -27
- package/dist/index.js.map +1 -1
- package/dist/prompts.d.ts +5 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +26 -11
- package/dist/prompts.js.map +1 -1
- package/dist/scaffold/update.d.ts.map +1 -1
- package/dist/scaffold/update.js +3 -2
- package/dist/scaffold/update.js.map +1 -1
- package/dist/utils/flags.d.ts +3 -2
- package/dist/utils/flags.d.ts.map +1 -1
- package/dist/utils/flags.js +4 -1
- package/dist/utils/flags.js.map +1 -1
- package/dist/utils/multiselect.d.ts +34 -0
- package/dist/utils/multiselect.d.ts.map +1 -0
- package/dist/utils/multiselect.js +156 -0
- package/dist/utils/multiselect.js.map +1 -0
- package/package.json +6 -4
- package/scripts/release-bump.mjs +62 -0
- package/scripts/release-prep.mjs +6 -7
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-select prompt with intuitive keybindings:
|
|
3
|
+
* ↑↓ navigate
|
|
4
|
+
* Enter toggle the highlighted option
|
|
5
|
+
* Tab submit (advance to the next prompt)
|
|
6
|
+
* Space also toggles (kept as an alias for inquirer-muscle-memory)
|
|
7
|
+
*
|
|
8
|
+
* Built on @inquirer/core so it composes with the rest of the
|
|
9
|
+
* @inquirer/prompts the CLI already uses (input/select/confirm). The
|
|
10
|
+
* vanilla `checkbox` from @inquirer/prompts uses Space=toggle +
|
|
11
|
+
* Enter=submit, which conflicts with the rest of the flow where Enter
|
|
12
|
+
* is the universal "go" key — this swap makes Enter behave consistently
|
|
13
|
+
* (it always advances state on the current prompt) and Tab moves to the
|
|
14
|
+
* next prompt, which is the same convention as web forms.
|
|
15
|
+
*/
|
|
16
|
+
import { Separator } from "@inquirer/core";
|
|
17
|
+
export interface MultiselectChoice<Value> {
|
|
18
|
+
value: Value;
|
|
19
|
+
name?: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
disabled?: boolean | string;
|
|
22
|
+
checked?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface MultiselectConfig<Value> {
|
|
25
|
+
message: string;
|
|
26
|
+
choices: ReadonlyArray<Separator | MultiselectChoice<Value>>;
|
|
27
|
+
pageSize?: number;
|
|
28
|
+
loop?: boolean;
|
|
29
|
+
required?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** Typed wrapper that gives back `Value[]` for callers. */
|
|
32
|
+
export declare function multiselect<Value>(config: MultiselectConfig<Value>): Promise<Value[]>;
|
|
33
|
+
export { Separator };
|
|
34
|
+
//# sourceMappingURL=multiselect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multiselect.d.ts","sourceRoot":"","sources":["../../src/utils/multiselect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EACL,SAAS,EAeV,MAAM,gBAAgB,CAAC;AAIxB,MAAM,WAAW,iBAAiB,CAAC,KAAK;IACtC,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB,CAAC,KAAK;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,aAAa,CAAC,SAAS,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAkKD,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAErF;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-select prompt with intuitive keybindings:
|
|
3
|
+
* ↑↓ navigate
|
|
4
|
+
* Enter toggle the highlighted option
|
|
5
|
+
* Tab submit (advance to the next prompt)
|
|
6
|
+
* Space also toggles (kept as an alias for inquirer-muscle-memory)
|
|
7
|
+
*
|
|
8
|
+
* Built on @inquirer/core so it composes with the rest of the
|
|
9
|
+
* @inquirer/prompts the CLI already uses (input/select/confirm). The
|
|
10
|
+
* vanilla `checkbox` from @inquirer/prompts uses Space=toggle +
|
|
11
|
+
* Enter=submit, which conflicts with the rest of the flow where Enter
|
|
12
|
+
* is the universal "go" key — this swap makes Enter behave consistently
|
|
13
|
+
* (it always advances state on the current prompt) and Tab moves to the
|
|
14
|
+
* next prompt, which is the same convention as web forms.
|
|
15
|
+
*/
|
|
16
|
+
import { Separator, ValidationError, createPrompt, isDownKey, isEnterKey, isNumberKey, isSpaceKey, isTabKey, isUpKey, makeTheme, useKeypress, useMemo, usePagination, usePrefix, useState, } from "@inquirer/core";
|
|
17
|
+
import figures from "@inquirer/figures";
|
|
18
|
+
import chalk from "chalk";
|
|
19
|
+
function isSelectable(item) {
|
|
20
|
+
return !Separator.isSeparator(item) && !item.disabled;
|
|
21
|
+
}
|
|
22
|
+
function normalize(choices) {
|
|
23
|
+
return choices.map((c) => {
|
|
24
|
+
if (Separator.isSeparator(c))
|
|
25
|
+
return c;
|
|
26
|
+
const name = c.name ?? String(c.value);
|
|
27
|
+
return {
|
|
28
|
+
value: c.value,
|
|
29
|
+
name,
|
|
30
|
+
description: c.description,
|
|
31
|
+
disabled: c.disabled ?? false,
|
|
32
|
+
checked: c.checked ?? false,
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const corePrompt = createPrompt((config, done) => {
|
|
37
|
+
const { pageSize = 10, loop = true, required = false } = config;
|
|
38
|
+
const theme = makeTheme();
|
|
39
|
+
const [status, setStatus] = useState("idle");
|
|
40
|
+
const prefix = usePrefix({ status, theme });
|
|
41
|
+
const [items, setItems] = useState(normalize(config.choices));
|
|
42
|
+
const bounds = useMemo(() => {
|
|
43
|
+
const first = items.findIndex(isSelectable);
|
|
44
|
+
let last = -1;
|
|
45
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
46
|
+
if (isSelectable(items[i])) {
|
|
47
|
+
last = i;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (first === -1) {
|
|
52
|
+
throw new ValidationError("[multiselect] No selectable choices.");
|
|
53
|
+
}
|
|
54
|
+
return { first, last };
|
|
55
|
+
}, [items]);
|
|
56
|
+
const [active, setActive] = useState(bounds.first);
|
|
57
|
+
const [errorMsg, setError] = useState();
|
|
58
|
+
const toggleAt = (index) => {
|
|
59
|
+
setError(undefined);
|
|
60
|
+
setItems(items.map((c, i) => {
|
|
61
|
+
if (i !== index)
|
|
62
|
+
return c;
|
|
63
|
+
if (!isSelectable(c))
|
|
64
|
+
return c;
|
|
65
|
+
return { ...c, checked: !c.checked };
|
|
66
|
+
}));
|
|
67
|
+
};
|
|
68
|
+
useKeypress((key) => {
|
|
69
|
+
if (isTabKey(key)) {
|
|
70
|
+
const selection = items.filter((c) => isSelectable(c) && c.checked);
|
|
71
|
+
if (required && selection.length === 0) {
|
|
72
|
+
setError("Pick at least one (use Enter to toggle).");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
setStatus("done");
|
|
76
|
+
done(selection.map((c) => c.value));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (isEnterKey(key) || isSpaceKey(key)) {
|
|
80
|
+
toggleAt(active);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (isUpKey(key) || isDownKey(key)) {
|
|
84
|
+
if (loop ||
|
|
85
|
+
(isUpKey(key) && active !== bounds.first) ||
|
|
86
|
+
(isDownKey(key) && active !== bounds.last)) {
|
|
87
|
+
const offset = isUpKey(key) ? -1 : 1;
|
|
88
|
+
let next = active;
|
|
89
|
+
do {
|
|
90
|
+
next = (next + offset + items.length) % items.length;
|
|
91
|
+
} while (!isSelectable(items[next]));
|
|
92
|
+
setActive(next);
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (isNumberKey(key)) {
|
|
97
|
+
const idx = Number(key.name) - 1;
|
|
98
|
+
let seen = -1;
|
|
99
|
+
const pos = items.findIndex((it) => {
|
|
100
|
+
if (Separator.isSeparator(it))
|
|
101
|
+
return false;
|
|
102
|
+
seen++;
|
|
103
|
+
return seen === idx;
|
|
104
|
+
});
|
|
105
|
+
if (pos !== -1 && isSelectable(items[pos])) {
|
|
106
|
+
setActive(pos);
|
|
107
|
+
toggleAt(pos);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
const message = theme.style.message(config.message, status);
|
|
112
|
+
if (status === "done") {
|
|
113
|
+
const selected = items.filter((c) => isSelectable(c) && c.checked);
|
|
114
|
+
const tail = selected.length > 0 ? selected.map((c) => c.name).join(", ") : chalk.dim("none");
|
|
115
|
+
return `${prefix} ${message} ${theme.style.answer(tail)}`;
|
|
116
|
+
}
|
|
117
|
+
let description;
|
|
118
|
+
const page = usePagination({
|
|
119
|
+
items,
|
|
120
|
+
active,
|
|
121
|
+
renderItem({ item, isActive }) {
|
|
122
|
+
if (Separator.isSeparator(item))
|
|
123
|
+
return ` ${item.separator}`;
|
|
124
|
+
if (item.disabled) {
|
|
125
|
+
const label = typeof item.disabled === "string" ? item.disabled : "(disabled)";
|
|
126
|
+
return chalk.dim(`- ${item.name} ${label}`);
|
|
127
|
+
}
|
|
128
|
+
if (isActive)
|
|
129
|
+
description = item.description;
|
|
130
|
+
const box = item.checked ? chalk.green(figures.circleFilled) : figures.circle;
|
|
131
|
+
const cursor = isActive ? figures.pointer : " ";
|
|
132
|
+
const line = `${cursor}${box} ${item.name}`;
|
|
133
|
+
return isActive ? theme.style.highlight(line) : line;
|
|
134
|
+
},
|
|
135
|
+
pageSize,
|
|
136
|
+
loop,
|
|
137
|
+
});
|
|
138
|
+
const help = chalk.dim(`${chalk.bold("↑↓")} navigate · ${chalk.bold("enter")} toggle · ${chalk.bold("tab")} submit`);
|
|
139
|
+
return [
|
|
140
|
+
`${prefix} ${message}`,
|
|
141
|
+
page,
|
|
142
|
+
" ",
|
|
143
|
+
description ? chalk.cyan(description) : "",
|
|
144
|
+
errorMsg ? theme.style.error(errorMsg) : "",
|
|
145
|
+
help,
|
|
146
|
+
]
|
|
147
|
+
.filter(Boolean)
|
|
148
|
+
.join("\n")
|
|
149
|
+
.trimEnd();
|
|
150
|
+
});
|
|
151
|
+
/** Typed wrapper that gives back `Value[]` for callers. */
|
|
152
|
+
export function multiselect(config) {
|
|
153
|
+
return corePrompt(config);
|
|
154
|
+
}
|
|
155
|
+
export { Separator };
|
|
156
|
+
//# sourceMappingURL=multiselect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multiselect.js","sourceRoot":"","sources":["../../src/utils/multiselect.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hatchkit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"packageManager": "pnpm@10.33.2",
|
|
5
5
|
"description": "Interactive CLI for scaffolding full-stack projects and provisioning observability/email clients",
|
|
6
6
|
"type": "module",
|
|
@@ -24,13 +24,15 @@
|
|
|
24
24
|
"check": "pnpm run typecheck && pnpm run lint && pnpm run test",
|
|
25
25
|
"install-local": "pnpm run build && npm install -g .",
|
|
26
26
|
"release": "pnpm run release:patch",
|
|
27
|
-
"release:patch": "node scripts/release-prep.mjs &&
|
|
28
|
-
"release:minor": "node scripts/release-prep.mjs &&
|
|
29
|
-
"release:major": "node scripts/release-prep.mjs &&
|
|
27
|
+
"release:patch": "node scripts/release-prep.mjs && node scripts/release-bump.mjs patch && pnpm run _release:finish",
|
|
28
|
+
"release:minor": "node scripts/release-prep.mjs && node scripts/release-bump.mjs minor && pnpm run _release:finish",
|
|
29
|
+
"release:major": "node scripts/release-prep.mjs && node scripts/release-bump.mjs major && pnpm run _release:finish",
|
|
30
30
|
"_release:finish": "pnpm run build && pnpm run typecheck && npm publish --access public && git push --follow-tags && npm install -g .",
|
|
31
31
|
"prepublishOnly": "pnpm run build"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
+
"@inquirer/core": "^10.3.0",
|
|
35
|
+
"@inquirer/figures": "^1.0.0",
|
|
34
36
|
"@inquirer/prompts": "^7.0.0",
|
|
35
37
|
"chalk": "^5.3.0",
|
|
36
38
|
"conf": "^13.0.0",
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
* release-bump — bump cli/package.json + commit + tag, atomically.
|
|
4
|
+
*
|
|
5
|
+
* Replaces `npm version <bump> -m "..."` because npm's built-in
|
|
6
|
+
* version command silently skips the commit/tag step in this monorepo
|
|
7
|
+
* layout (cli/ is a workspace member, not the repo root, and the lock
|
|
8
|
+
* file npm tries to stage doesn't exist anymore — pnpm-lock.yaml at
|
|
9
|
+
* the workspace root is the source of truth). The result: every
|
|
10
|
+
* release left cli/package.json modified-but-uncommitted, the publish
|
|
11
|
+
* succeeded against an untracked version, and the release machinery
|
|
12
|
+
* drifted from git history.
|
|
13
|
+
*
|
|
14
|
+
* Doing the three steps ourselves is unambiguous: bump, stage, commit,
|
|
15
|
+
* tag. release-prep.mjs has already verified the working tree is
|
|
16
|
+
* clean before this runs, so the commit only contains the version bump.
|
|
17
|
+
*
|
|
18
|
+
* Usage: node scripts/release-bump.mjs <patch|minor|major>
|
|
19
|
+
*/
|
|
20
|
+
import { execSync } from "node:child_process";
|
|
21
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
22
|
+
import { dirname, join } from "node:path";
|
|
23
|
+
import { fileURLToPath } from "node:url";
|
|
24
|
+
|
|
25
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const cliDir = join(here, "..");
|
|
27
|
+
const pkgPath = join(cliDir, "package.json");
|
|
28
|
+
|
|
29
|
+
const bumpKind = process.argv[2];
|
|
30
|
+
if (!["patch", "minor", "major"].includes(bumpKind)) {
|
|
31
|
+
console.error(`release-bump: expected patch|minor|major, got ${bumpKind ?? "(nothing)"}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function sh(cmd, opts = {}) {
|
|
36
|
+
return execSync(cmd, { encoding: "utf-8", ...opts }).trim();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const repoRoot = sh("git rev-parse --show-toplevel");
|
|
40
|
+
|
|
41
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
42
|
+
const current = pkg.version;
|
|
43
|
+
const [maj, min, pat] = current.split(".").map((n) => Number(n) || 0);
|
|
44
|
+
const next =
|
|
45
|
+
bumpKind === "major"
|
|
46
|
+
? `${maj + 1}.0.0`
|
|
47
|
+
: bumpKind === "minor"
|
|
48
|
+
? `${maj}.${min + 1}.0`
|
|
49
|
+
: `${maj}.${min}.${pat + 1}`;
|
|
50
|
+
|
|
51
|
+
pkg.version = next;
|
|
52
|
+
// npm's `npm version` keeps a trailing newline; preserve that so diffs
|
|
53
|
+
// stay 1 line and don't churn whitespace.
|
|
54
|
+
writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`, "utf-8");
|
|
55
|
+
console.log(` release-bump: ${current} → ${next}`);
|
|
56
|
+
|
|
57
|
+
// Stage + commit + tag from the repo root so the path in the commit
|
|
58
|
+
// is `cli/package.json` regardless of where the script was invoked.
|
|
59
|
+
sh(`git add ${JSON.stringify(join("cli", "package.json"))}`, { cwd: repoRoot });
|
|
60
|
+
sh(`git commit -m ${JSON.stringify(`chore: release v${next}`)}`, { cwd: repoRoot });
|
|
61
|
+
sh(`git tag ${JSON.stringify(`v${next}`)}`, { cwd: repoRoot });
|
|
62
|
+
console.log(` release-bump: committed + tagged v${next}`);
|
package/scripts/release-prep.mjs
CHANGED
|
@@ -8,11 +8,10 @@
|
|
|
8
8
|
* same baseline.
|
|
9
9
|
*
|
|
10
10
|
* ALSO refuses when the local cli/package.json version is at-or-
|
|
11
|
-
* behind the version published to npm.
|
|
12
|
-
* from the LOCAL version,
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* front instead.
|
|
11
|
+
* behind the version published to npm. release-bump.mjs increments
|
|
12
|
+
* from the LOCAL version, so drift between local and registry leads
|
|
13
|
+
* to the bump generating a number that's already taken and the
|
|
14
|
+
* publish step crashing after build/typecheck. Catch it up front.
|
|
16
15
|
*
|
|
17
16
|
* Skip with RELEASE_SKIP_PREP=1 (e.g. a CI-driven release that's
|
|
18
17
|
* already vouched for cleanliness). RELEASE_SKIP_NPM_CHECK=1 only
|
|
@@ -118,13 +117,13 @@ function checkNpmDrift(repoRoot) {
|
|
|
118
117
|
return [
|
|
119
118
|
`local ${name}@${local} is behind the registry's ${registry}.`,
|
|
120
119
|
"",
|
|
121
|
-
"
|
|
120
|
+
" release-bump.mjs increments from the LOCAL version, so a release now",
|
|
122
121
|
" would try to publish a version that's already taken. Sync first:",
|
|
123
122
|
"",
|
|
124
123
|
` cd ${join(repoRoot, "cli")}`,
|
|
125
124
|
` npm version ${registry} --no-git-tag-version # match the registry`,
|
|
126
125
|
` cd ${repoRoot}`,
|
|
127
|
-
` git add cli/package.json
|
|
126
|
+
` git add cli/package.json`,
|
|
128
127
|
` git commit -m "chore: release v${registry}"`,
|
|
129
128
|
` git tag v${registry}`,
|
|
130
129
|
"",
|