@housekit/kit 0.1.30 → 0.1.32
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 +20 -0
- package/dist/index.js +63 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -42,6 +42,7 @@ Perfect for early-stage projects or local development. It computes the delta bet
|
|
|
42
42
|
- **Safe**: Asks for confirmation before any destructive change.
|
|
43
43
|
- **Fast**: Skips the creation of migration files.
|
|
44
44
|
- **Smart**: Handles column renames and type changes.
|
|
45
|
+
- **CI/CD Ready**: Use `-y` flag or pipe commands for non-interactive mode.
|
|
45
46
|
|
|
46
47
|
### 2. Controlled Production: `housekit generate` & `migrate`
|
|
47
48
|
The standard for CI/CD and production environments.
|
|
@@ -65,6 +66,25 @@ The standard for CI/CD and production environments.
|
|
|
65
66
|
| `list` | Summarizes row counts, engines, and sizes for all tables. |
|
|
66
67
|
| `reset` | Wipes the database and restarts from your code schema (Dev only). |
|
|
67
68
|
|
|
69
|
+
### Global Options
|
|
70
|
+
|
|
71
|
+
| Option | Description |
|
|
72
|
+
| :--- | :--- |
|
|
73
|
+
| `-y, --yes` | Auto-confirm all prompts (useful for CI/CD and scripts). |
|
|
74
|
+
| `-d, --database <name>` | Target a specific database from your config. |
|
|
75
|
+
|
|
76
|
+
### Non-Interactive Mode
|
|
77
|
+
|
|
78
|
+
When running in non-interactive environments (CI/CD pipelines, scripts with piped input), HouseKit automatically detects this and uses default values for prompts. For explicit control, use the `-y` flag:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Auto-confirm all prompts
|
|
82
|
+
bunx housekit push -y
|
|
83
|
+
|
|
84
|
+
# Works in CI/CD pipelines
|
|
85
|
+
bunx housekit migrate -y --database production
|
|
86
|
+
```
|
|
87
|
+
|
|
68
88
|
---
|
|
69
89
|
|
|
70
90
|
## ⚙️ Configuration
|
package/dist/index.js
CHANGED
|
@@ -7949,9 +7949,16 @@ var globalYes = false;
|
|
|
7949
7949
|
function setGlobalYesMode(enabled) {
|
|
7950
7950
|
globalYes = enabled;
|
|
7951
7951
|
}
|
|
7952
|
+
function isInteractive() {
|
|
7953
|
+
return process.stdin.isTTY === true;
|
|
7954
|
+
}
|
|
7952
7955
|
async function confirmPrompt(message, defaultYes = true) {
|
|
7953
7956
|
if (globalYes)
|
|
7954
7957
|
return true;
|
|
7958
|
+
if (!isInteractive()) {
|
|
7959
|
+
info(`${message} (auto-confirmed, non-interactive mode)`);
|
|
7960
|
+
return defaultYes;
|
|
7961
|
+
}
|
|
7955
7962
|
const { ok } = await inquirer.prompt([{
|
|
7956
7963
|
type: "confirm",
|
|
7957
7964
|
name: "ok",
|
|
@@ -7967,6 +7974,12 @@ async function listPrompt(message, choices, defaultValue) {
|
|
|
7967
7974
|
if (choices.length === 0) {
|
|
7968
7975
|
throw new Error("No choices provided to listPrompt");
|
|
7969
7976
|
}
|
|
7977
|
+
if (!isInteractive()) {
|
|
7978
|
+
const selected = defaultValue !== undefined ? defaultValue : choices[0].value;
|
|
7979
|
+
const selectedName = choices.find((c) => c.value === selected)?.name || String(selected);
|
|
7980
|
+
info(`${message} → ${selectedName} (auto-selected, non-interactive mode)`);
|
|
7981
|
+
return selected;
|
|
7982
|
+
}
|
|
7970
7983
|
const defaultIndex = defaultValue !== undefined ? choices.findIndex((c) => c.value === defaultValue) : 0;
|
|
7971
7984
|
const result = await inquirer.prompt([{
|
|
7972
7985
|
type: "rawlist",
|
|
@@ -7990,6 +8003,13 @@ async function inputPrompt(message, defaultValue, validate2) {
|
|
|
7990
8003
|
if (globalYes && defaultValue !== undefined) {
|
|
7991
8004
|
return defaultValue;
|
|
7992
8005
|
}
|
|
8006
|
+
if (!isInteractive()) {
|
|
8007
|
+
if (defaultValue !== undefined) {
|
|
8008
|
+
info(`${message} → ${defaultValue} (auto-selected, non-interactive mode)`);
|
|
8009
|
+
return defaultValue;
|
|
8010
|
+
}
|
|
8011
|
+
throw new Error(`Input required for "${message}" but running in non-interactive mode without default value. Use -y flag with appropriate defaults.`);
|
|
8012
|
+
}
|
|
7993
8013
|
const { value } = await inquirer.prompt([{
|
|
7994
8014
|
type: "input",
|
|
7995
8015
|
name: "value",
|
|
@@ -8009,6 +8029,11 @@ async function checkboxPrompt(message, choices, defaultSelected) {
|
|
|
8009
8029
|
if (choices.length === 0) {
|
|
8010
8030
|
throw new Error("No choices provided to checkboxPrompt");
|
|
8011
8031
|
}
|
|
8032
|
+
if (!isInteractive()) {
|
|
8033
|
+
const selected = defaultSelected || [];
|
|
8034
|
+
info(`${message} → [${selected.length} items] (auto-selected, non-interactive mode)`);
|
|
8035
|
+
return selected;
|
|
8036
|
+
}
|
|
8012
8037
|
const defaultValues = defaultSelected || [];
|
|
8013
8038
|
const result = await inquirer.prompt([{
|
|
8014
8039
|
type: "checkbox",
|
|
@@ -9446,7 +9471,24 @@ async function pushCommand(options) {
|
|
|
9446
9471
|
} catch (e) {
|
|
9447
9472
|
error("Push failed");
|
|
9448
9473
|
error("Error during push:");
|
|
9449
|
-
|
|
9474
|
+
if (e instanceof AggregateError) {
|
|
9475
|
+
error("Multiple errors occurred:");
|
|
9476
|
+
for (const err of e.errors) {
|
|
9477
|
+
error(` • ${err instanceof Error ? err.message : String(err)}`);
|
|
9478
|
+
if (err instanceof Error && err.stack) {
|
|
9479
|
+
const stackLines = err.stack.split(`
|
|
9480
|
+
`).slice(1, 3);
|
|
9481
|
+
stackLines.forEach((line) => error(` ${line.trim()}`));
|
|
9482
|
+
}
|
|
9483
|
+
}
|
|
9484
|
+
} else if (e instanceof Error) {
|
|
9485
|
+
error(e.message);
|
|
9486
|
+
if (e.cause) {
|
|
9487
|
+
error(`Caused by: ${e.cause instanceof Error ? e.cause.message : String(e.cause)}`);
|
|
9488
|
+
}
|
|
9489
|
+
} else {
|
|
9490
|
+
error(String(e));
|
|
9491
|
+
}
|
|
9450
9492
|
} finally {
|
|
9451
9493
|
await client.close();
|
|
9452
9494
|
}
|
|
@@ -11556,13 +11598,32 @@ program.hook("preAction", (thisCommand) => {
|
|
|
11556
11598
|
const opts = thisCommand.optsWithGlobals?.() ?? thisCommand.opts();
|
|
11557
11599
|
setGlobalYesMode(Boolean(opts.yes));
|
|
11558
11600
|
});
|
|
11601
|
+
function formatError(err) {
|
|
11602
|
+
const lines = [];
|
|
11603
|
+
if (err instanceof AggregateError) {
|
|
11604
|
+
lines.push("Multiple errors occurred:");
|
|
11605
|
+
for (const e of err.errors) {
|
|
11606
|
+
lines.push(` • ${e instanceof Error ? e.message : String(e)}`);
|
|
11607
|
+
}
|
|
11608
|
+
} else if (err instanceof Error) {
|
|
11609
|
+
lines.push(err.message);
|
|
11610
|
+
if (err.cause) {
|
|
11611
|
+
lines.push(`Caused by: ${err.cause instanceof Error ? err.cause.message : String(err.cause)}`);
|
|
11612
|
+
}
|
|
11613
|
+
} else {
|
|
11614
|
+
lines.push(String(err));
|
|
11615
|
+
}
|
|
11616
|
+
return lines;
|
|
11617
|
+
}
|
|
11559
11618
|
function withErrorHandling(fn) {
|
|
11560
11619
|
return async (...args) => {
|
|
11561
11620
|
try {
|
|
11562
11621
|
await fn(...args);
|
|
11563
11622
|
} catch (error3) {
|
|
11623
|
+
const errorLines = formatError(error3);
|
|
11564
11624
|
console.error(chalk5.red(`
|
|
11565
|
-
✖ Error: ` +
|
|
11625
|
+
✖ Error: ` + errorLines[0]));
|
|
11626
|
+
errorLines.slice(1).forEach((line) => console.error(chalk5.red(line)));
|
|
11566
11627
|
if (process.env.DEBUG) {
|
|
11567
11628
|
console.error(error3);
|
|
11568
11629
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@housekit/kit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"description": "CLI tool for HouseKit - manage ClickHouse schemas, migrations, and database operations with type-safe workflows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@clickhouse/client": "^1.14.0",
|
|
51
|
-
"@housekit/orm": "^0.1.
|
|
51
|
+
"@housekit/orm": "^0.1.38",
|
|
52
52
|
"boxen": "8.0.1",
|
|
53
53
|
"chalk": "^5.6.2",
|
|
54
54
|
"cli-table3": "^0.6.5",
|