feat(cli): add client commands and home-based local runtime defaults

This commit is contained in:
Forgotten
2026-02-20 07:10:58 -06:00
parent 8e3c2fae35
commit 8f3fc077fa
40 changed files with 2284 additions and 138 deletions

View File

@@ -1,7 +1,10 @@
import * as p from "@clack/prompts";
import type { DatabaseConfig } from "../config/schema.js";
import { resolveDefaultEmbeddedPostgresDir, resolvePaperclipInstanceId } from "../config/home.js";
export async function promptDatabase(): Promise<DatabaseConfig> {
const defaultEmbeddedDir = resolveDefaultEmbeddedPostgresDir(resolvePaperclipInstanceId());
const mode = await p.select({
message: "Database mode",
options: [
@@ -33,15 +36,15 @@ export async function promptDatabase(): Promise<DatabaseConfig> {
return {
mode: "postgres",
connectionString,
embeddedPostgresDataDir: "./data/embedded-postgres",
embeddedPostgresDataDir: defaultEmbeddedDir,
embeddedPostgresPort: 54329,
};
}
const embeddedPostgresDataDir = await p.text({
message: "Embedded PostgreSQL data directory",
defaultValue: "./data/embedded-postgres",
placeholder: "./data/embedded-postgres",
defaultValue: defaultEmbeddedDir,
placeholder: defaultEmbeddedDir,
});
if (p.isCancel(embeddedPostgresDataDir)) {
@@ -66,7 +69,7 @@ export async function promptDatabase(): Promise<DatabaseConfig> {
return {
mode: "embedded-postgres",
embeddedPostgresDataDir: embeddedPostgresDataDir || "./data/embedded-postgres",
embeddedPostgresDataDir: embeddedPostgresDataDir || defaultEmbeddedDir,
embeddedPostgresPort: Number(embeddedPostgresPort || "54329"),
};
}

View File

@@ -1,7 +1,9 @@
import * as p from "@clack/prompts";
import type { LoggingConfig } from "../config/schema.js";
import { resolveDefaultLogsDir, resolvePaperclipInstanceId } from "../config/home.js";
export async function promptLogging(): Promise<LoggingConfig> {
const defaultLogDir = resolveDefaultLogsDir(resolvePaperclipInstanceId());
const mode = await p.select({
message: "Logging mode",
options: [
@@ -18,8 +20,8 @@ export async function promptLogging(): Promise<LoggingConfig> {
if (mode === "file") {
const logDir = await p.text({
message: "Log directory",
defaultValue: "./data/logs",
placeholder: "./data/logs",
defaultValue: defaultLogDir,
placeholder: defaultLogDir,
});
if (p.isCancel(logDir)) {
@@ -27,9 +29,9 @@ export async function promptLogging(): Promise<LoggingConfig> {
process.exit(0);
}
return { mode: "file", logDir: logDir || "./data/logs" };
return { mode: "file", logDir: logDir || defaultLogDir };
}
p.note("Cloud logging is coming soon. Using file-based logging for now.");
return { mode: "file", logDir: "./data/logs" };
return { mode: "file", logDir: defaultLogDir };
}

View File

@@ -1,15 +1,19 @@
import * as p from "@clack/prompts";
import type { SecretProvider } from "@paperclip/shared";
import type { SecretsConfig } from "../config/schema.js";
import { resolveDefaultSecretsKeyFilePath, resolvePaperclipInstanceId } from "../config/home.js";
const DEFAULT_KEY_FILE_PATH = "./data/secrets/master.key";
function defaultKeyFilePath(): string {
return resolveDefaultSecretsKeyFilePath(resolvePaperclipInstanceId());
}
export function defaultSecretsConfig(): SecretsConfig {
const keyFilePath = defaultKeyFilePath();
return {
provider: "local_encrypted",
strictMode: false,
localEncrypted: {
keyFilePath: DEFAULT_KEY_FILE_PATH,
keyFilePath,
},
};
}
@@ -59,12 +63,13 @@ export async function promptSecrets(current?: SecretsConfig): Promise<SecretsCon
process.exit(0);
}
let keyFilePath = base.localEncrypted.keyFilePath || DEFAULT_KEY_FILE_PATH;
const fallbackDefault = defaultKeyFilePath();
let keyFilePath = base.localEncrypted.keyFilePath || fallbackDefault;
if (provider === "local_encrypted") {
const keyPath = await p.text({
message: "Local encrypted key file path",
defaultValue: keyFilePath,
placeholder: DEFAULT_KEY_FILE_PATH,
placeholder: fallbackDefault,
validate: (value) => {
if (!value || value.trim().length === 0) return "Key file path is required";
},