@brewnet/cli 0.0.8 → 0.0.9

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.
Files changed (31) hide show
  1. package/dist/admin-server-FN7HZVZW.js +16 -0
  2. package/dist/{app-manager-BD3DG3RL.js → app-manager-6PEKSRZ2.js} +4 -4
  3. package/dist/{boilerplate-manager-WEFTHL2O.js → boilerplate-manager-5GPTMOYL.js} +4 -4
  4. package/dist/{chunk-OH233QV2.js → chunk-7VX572H4.js} +9 -9
  5. package/dist/{chunk-ZKMWE5AH.js → chunk-BD4MDAIG.js} +2 -2
  6. package/dist/{chunk-HCHY5UIQ.js → chunk-F2M6G5C7.js} +3 -3
  7. package/dist/chunk-F2M6G5C7.js.map +1 -0
  8. package/dist/{chunk-54WFZCU6.js → chunk-F2Y226UA.js} +3 -3
  9. package/dist/{chunk-76C5BGZK.js → chunk-JMKFUHZO.js} +19 -15
  10. package/dist/chunk-JMKFUHZO.js.map +1 -0
  11. package/dist/{chunk-AXSHZEB3.js → chunk-MOQNPKUG.js} +2 -2
  12. package/dist/{chunk-YAYXULLO.js → chunk-MSVYAYKQ.js} +4 -4
  13. package/dist/{compose-generator-OFJ2YWMB.js → compose-generator-MIAP3RBT.js} +3 -3
  14. package/dist/index.js +28 -43
  15. package/dist/index.js.map +1 -1
  16. package/dist/services/admin-daemon.js +6 -6
  17. package/dist/{state-2SI3P4JG.js → state-CJSUDM4H.js} +3 -3
  18. package/package.json +1 -1
  19. package/dist/admin-server-CBZFDDWG.js +0 -16
  20. package/dist/chunk-76C5BGZK.js.map +0 -1
  21. package/dist/chunk-HCHY5UIQ.js.map +0 -1
  22. /package/dist/{admin-server-CBZFDDWG.js.map → admin-server-FN7HZVZW.js.map} +0 -0
  23. /package/dist/{app-manager-BD3DG3RL.js.map → app-manager-6PEKSRZ2.js.map} +0 -0
  24. /package/dist/{boilerplate-manager-WEFTHL2O.js.map → boilerplate-manager-5GPTMOYL.js.map} +0 -0
  25. /package/dist/{chunk-OH233QV2.js.map → chunk-7VX572H4.js.map} +0 -0
  26. /package/dist/{chunk-ZKMWE5AH.js.map → chunk-BD4MDAIG.js.map} +0 -0
  27. /package/dist/{chunk-54WFZCU6.js.map → chunk-F2Y226UA.js.map} +0 -0
  28. /package/dist/{chunk-AXSHZEB3.js.map → chunk-MOQNPKUG.js.map} +0 -0
  29. /package/dist/{chunk-YAYXULLO.js.map → chunk-MSVYAYKQ.js.map} +0 -0
  30. /package/dist/{compose-generator-OFJ2YWMB.js.map → compose-generator-MIAP3RBT.js.map} +0 -0
  31. /package/dist/{state-2SI3P4JG.js.map → state-CJSUDM4H.js.map} +0 -0
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ createAdminServer
4
+ } from "./chunk-JMKFUHZO.js";
5
+ import "./chunk-7VX572H4.js";
6
+ import "./chunk-MSVYAYKQ.js";
7
+ import "./chunk-JIPAYMOA.js";
8
+ import "./chunk-YXFDB5YX.js";
9
+ import "./chunk-MOQNPKUG.js";
10
+ import "./chunk-BD4MDAIG.js";
11
+ import "./chunk-F2M6G5C7.js";
12
+ import "./chunk-SYV6PK3R.js";
13
+ export {
14
+ createAdminServer
15
+ };
16
+ //# sourceMappingURL=admin-server-FN7HZVZW.js.map
@@ -21,10 +21,10 @@ import {
21
21
  startApp,
22
22
  stopApp,
23
23
  updateDeploySettings
24
- } from "./chunk-OH233QV2.js";
24
+ } from "./chunk-7VX572H4.js";
25
25
  import "./chunk-JIPAYMOA.js";
26
- import "./chunk-ZKMWE5AH.js";
27
- import "./chunk-HCHY5UIQ.js";
26
+ import "./chunk-BD4MDAIG.js";
27
+ import "./chunk-F2M6G5C7.js";
28
28
  export {
29
29
  createApp,
30
30
  deployApp,
@@ -48,4 +48,4 @@ export {
48
48
  stopApp,
49
49
  updateDeploySettings
50
50
  };
51
- //# sourceMappingURL=app-manager-BD3DG3RL.js.map
51
+ //# sourceMappingURL=app-manager-6PEKSRZ2.js.map
@@ -9,11 +9,11 @@ import {
9
9
  reinitGit,
10
10
  startContainers,
11
11
  verifyEndpoints
12
- } from "./chunk-54WFZCU6.js";
13
- import "./chunk-AXSHZEB3.js";
12
+ } from "./chunk-F2Y226UA.js";
13
+ import "./chunk-MOQNPKUG.js";
14
14
  import {
15
15
  BOILERPLATE_REPO_URL
16
- } from "./chunk-HCHY5UIQ.js";
16
+ } from "./chunk-F2M6G5C7.js";
17
17
  export {
18
18
  BOILERPLATE_REPO_URL,
19
19
  cloneStack,
@@ -26,4 +26,4 @@ export {
26
26
  startContainers,
27
27
  verifyEndpoints
28
28
  };
29
- //# sourceMappingURL=boilerplate-manager-WEFTHL2O.js.map
29
+ //# sourceMappingURL=boilerplate-manager-5GPTMOYL.js.map
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  getLastProject,
12
12
  loadState
13
- } from "./chunk-ZKMWE5AH.js";
13
+ } from "./chunk-BD4MDAIG.js";
14
14
 
15
15
  // src/services/app-manager.ts
16
16
  import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, readdirSync } from "fs";
@@ -527,7 +527,7 @@ async function _runDeploy(job, appName) {
527
527
  if (isShallowNew) {
528
528
  appendLog(job, "[pull] shallow clone detected \u2014 unshallowing");
529
529
  await execa("git", ["fetch", "--unshallow", "origin"], { cwd: app.appDir }).catch(async () => {
530
- const { reinitGit } = await import("./boilerplate-manager-WEFTHL2O.js");
530
+ const { reinitGit } = await import("./boilerplate-manager-5GPTMOYL.js");
531
531
  await reinitGit(app.appDir);
532
532
  });
533
533
  }
@@ -549,7 +549,7 @@ async function _runDeploy(job, appName) {
549
549
  if (isShallow) {
550
550
  appendLog(job, "[pull] shallow clone detected \u2014 unshallowing");
551
551
  await execa("git", ["fetch", "--unshallow", "origin"], { cwd: app.appDir }).catch(async () => {
552
- const { reinitGit } = await import("./boilerplate-manager-WEFTHL2O.js");
552
+ const { reinitGit } = await import("./boilerplate-manager-5GPTMOYL.js");
553
553
  await reinitGit(app.appDir);
554
554
  });
555
555
  }
@@ -677,7 +677,7 @@ async function _injectQuickTunnelIfNeeded(appDir, appName, port) {
677
677
  const last = getLastProject();
678
678
  const state = loadState(last ?? "");
679
679
  if (state?.domain?.cloudflare?.tunnelMode !== "quick") return;
680
- const { injectTraefikForQuickTunnel } = await import("./boilerplate-manager-WEFTHL2O.js");
680
+ const { injectTraefikForQuickTunnel } = await import("./boilerplate-manager-5GPTMOYL.js");
681
681
  injectTraefikForQuickTunnel(appDir, appName, port);
682
682
  } catch (err) {
683
683
  console.error(`[Quick Tunnel] Failed to inject Traefik labels for ${appName}: ${err instanceof Error ? err.message : String(err)}`);
@@ -959,7 +959,7 @@ async function _createModeA(job, opts, ctx, gitea, appsJson) {
959
959
  const shallowCheck = await execa("git", ["rev-parse", "--is-shallow-repository"], { cwd: meta.appDir }).catch(() => ({ stdout: "false" }));
960
960
  if (shallowCheck.stdout.trim() === "true") {
961
961
  await execa("git", ["fetch", "--unshallow", "origin"], { cwd: meta.appDir }).catch(async () => {
962
- const { reinitGit } = await import("./boilerplate-manager-WEFTHL2O.js");
962
+ const { reinitGit } = await import("./boilerplate-manager-5GPTMOYL.js");
963
963
  await reinitGit(meta.appDir);
964
964
  });
965
965
  }
@@ -999,7 +999,7 @@ async function _createModeB(job, opts, ctx, gitea, appsJson) {
999
999
  const port = opts.port ?? 8080;
1000
1000
  const appDir = join(ctx.projectPath, "apps", opts.appName);
1001
1001
  setStep(job, 2, "running", "Cloning external repository...");
1002
- const { reinitGit: reinitGitB } = await import("./boilerplate-manager-WEFTHL2O.js");
1002
+ const { reinitGit: reinitGitB } = await import("./boilerplate-manager-5GPTMOYL.js");
1003
1003
  const { rmSync } = await import("fs");
1004
1004
  if (existsSync2(appDir)) {
1005
1005
  rmSync(appDir, { recursive: true, force: true });
@@ -1012,7 +1012,7 @@ async function _createModeB(job, opts, ctx, gitea, appsJson) {
1012
1012
  const envExPath = join(appDir, ".env.example");
1013
1013
  const envPath = join(appDir, ".env");
1014
1014
  if (existsSync2(envExPath)) {
1015
- const { findFreePort: findFreePortB } = await import("./boilerplate-manager-WEFTHL2O.js");
1015
+ const { findFreePort: findFreePortB } = await import("./boilerplate-manager-5GPTMOYL.js");
1016
1016
  let envContent = readFileSync2(envExPath, "utf-8");
1017
1017
  envContent = envContent.replace(/^BACKEND_PORT=.*/m, `BACKEND_PORT=${port}`);
1018
1018
  const fePort = await findFreePortB(port + 1);
@@ -1062,7 +1062,7 @@ async function _createModeB(job, opts, ctx, gitea, appsJson) {
1062
1062
  });
1063
1063
  }
1064
1064
  async function _createModeC(job, opts, ctx, gitea, appsJson) {
1065
- const { cloneStack, generateEnv, reinitGit, findFreePort } = await import("./boilerplate-manager-WEFTHL2O.js");
1065
+ const { cloneStack, generateEnv, reinitGit, findFreePort } = await import("./boilerplate-manager-5GPTMOYL.js");
1066
1066
  const { getStackById } = await import("./stacks-M4FBTVO5.js");
1067
1067
  const stackId = opts._resolvedStackId;
1068
1068
  const requestedPort = opts.port ?? 8080;
@@ -1156,4 +1156,4 @@ export {
1156
1156
  stopApp,
1157
1157
  removeApp2 as removeApp
1158
1158
  };
1159
- //# sourceMappingURL=chunk-OH233QV2.js.map
1159
+ //# sourceMappingURL=chunk-7VX572H4.js.map
@@ -3,7 +3,7 @@ import {
3
3
  ACCESS_LOG_MAX_BYTES,
4
4
  CLI_LOG_RETENTION_DAYS,
5
5
  SCHEMA_VERSION
6
- } from "./chunk-HCHY5UIQ.js";
6
+ } from "./chunk-F2M6G5C7.js";
7
7
 
8
8
  // src/wizard/state.ts
9
9
  import {
@@ -441,4 +441,4 @@ export {
441
441
  listProjects,
442
442
  _resetGlobalConfig
443
443
  };
444
- //# sourceMappingURL=chunk-ZKMWE5AH.js.map
444
+ //# sourceMappingURL=chunk-BD4MDAIG.js.map
@@ -4,8 +4,8 @@
4
4
  var SCHEMA_VERSION = 7;
5
5
  var DOCKER_COMPOSE_FILENAME = "docker-compose.yml";
6
6
  var DB_VERSIONS = {
7
- postgresql: ["18.3", "17.9", "16.13"],
8
- mysql: ["8.4", "8.0", "5.7"],
7
+ postgresql: ["18.3"],
8
+ mysql: ["8.4"],
9
9
  sqlite: ["3"]
10
10
  };
11
11
  var BOILERPLATE_REPO_URL = "https://github.com/claude-code-expert/brewnet-boilerplate.git";
@@ -298,4 +298,4 @@ export {
298
298
  LOG_QUERY_DEFAULT_LIMIT,
299
299
  LOG_QUERY_MAX_LIMIT
300
300
  };
301
- //# sourceMappingURL=chunk-HCHY5UIQ.js.map
301
+ //# sourceMappingURL=chunk-F2M6G5C7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../shared/src/utils/constants.ts","../../shared/src/types/errors.ts","../../shared/src/schemas/wizard-state.schema.ts","../../shared/src/schemas/config.schema.ts"],"sourcesContent":["// T013 — Shared constants used across the Brewnet CLI and Dashboard\n\n// ─── Schema & Versioning ────────────────────────────────────────────────────\n\n/** Current wizard state schema version */\nexport const SCHEMA_VERSION = 7 as const;\n\n/** Minimum schema version that can be migrated (older versions are reset) */\nexport const MIN_MIGRATABLE_SCHEMA_VERSION = 3;\n\n// ─── Project Defaults ────────────────────────────────────────────────────────\n\nexport const DEFAULT_PROJECT_NAME = 'my-homeserver';\nexport const DEFAULT_PROJECT_PATH_PREFIX = '~/brewnet';\nexport const DEFAULT_DATA_DIR = '~/.brewnet';\nexport const DEFAULT_CONFIG_FILENAME = 'brewnet.config.json';\n\n// ─── Admin & Credentials ────────────────────────────────────────────────────\n\nexport const DEFAULT_ADMIN_USERNAME = 'admin';\nexport const DEFAULT_ADMIN_PASSWORD_LENGTH = 20;\nexport const DEFAULT_SERVICE_PASSWORD_LENGTH = 16;\nexport const DEFAULT_DB_NAME = 'brewnet';\nexport const DEFAULT_DB_USER = 'brewnet';\n\n// ─── Port Defaults ───────────────────────────────────────────────────────────\n\nexport const DEFAULT_SSH_PORT = 2222;\nexport const DEFAULT_GIT_WEB_PORT = 3000;\nexport const DEFAULT_GIT_SSH_PORT = 3022;\nexport const DEFAULT_HTTP_PORT = 80;\nexport const DEFAULT_HTTPS_PORT = 443;\nexport const DEFAULT_TRAEFIK_DASHBOARD_PORT = 8080;\n\n// ─── Health Check ────────────────────────────────────────────────────────────\n\n/** Maximum time to wait for all health checks to pass (ms) */\nexport const HEALTH_CHECK_TIMEOUT_MS = 120_000;\n\n/** Interval between health check polls (ms) */\nexport const HEALTH_CHECK_INTERVAL_MS = 2_000;\n\n/** Number of consecutive successes required to consider a service healthy */\nexport const HEALTH_CHECK_SUCCESS_THRESHOLD = 3;\n\n/** Number of consecutive failures before marking a service as unhealthy */\nexport const HEALTH_CHECK_FAILURE_THRESHOLD = 5;\n\n// ─── Docker ──────────────────────────────────────────────────────────────────\n\nexport const DOCKER_COMPOSE_FILENAME = 'docker-compose.yml';\nexport const DOCKER_NETWORK_EXTERNAL = 'brewnet';\nexport const DOCKER_NETWORK_INTERNAL = 'brewnet-internal';\nexport const DOCKER_RESTART_POLICY = 'unless-stopped';\nexport const DOCKER_COMPOSE_VERSION = '3.8';\n\n// ─── File Permissions ────────────────────────────────────────────────────────\n\n/** Permission for .env files containing secrets (owner read/write only) */\nexport const ENV_FILE_PERMISSIONS = 0o600;\n\n/** Permission for SSH private keys (owner read only) */\nexport const SSH_KEY_PERMISSIONS = 0o600;\n\n/** Permission for SSH authorized_keys (owner read/write only) */\nexport const SSH_AUTHORIZED_KEYS_PERMISSIONS = 0o600;\n\n/** Permission for directories (owner rwx, group rx, others rx) */\nexport const DEFAULT_DIR_PERMISSIONS = 0o755;\n\n// ─── Storage Keys ────────────────────────────────────────────────────────────\n\n/** localStorage key for wizard state (used by demo and dashboard) */\nexport const WIZARD_STATE_STORAGE_KEY = 'brewnet_wizard_state';\n\n// ─── Service Images ─────────────────────────────────────────────────────────\n\nexport const SERVICE_IMAGES = {\n traefik: 'traefik:v3.1',\n nginx: 'nginx:1.27-alpine',\n caddy: 'caddy:2-alpine',\n nextcloud: 'nextcloud:29-apache',\n minio: 'minio/minio:latest',\n gitea: 'gitea/gitea:1.22',\n postgresql: 'postgres:18.3-alpine',\n mysql: 'mysql:8.4',\n sqlite: '',\n redis: 'redis:7-alpine',\n valkey: 'valkey/valkey:8-alpine',\n keydb: 'eqalpha/keydb:latest',\n jellyfin: 'jellyfin/jellyfin:latest',\n\n filebrowser: 'filebrowser/filebrowser:latest',\n pgadmin: 'dpage/pgadmin4:latest',\n phpmyadmin: 'phpmyadmin:latest',\n} as const;\n\n// ─── Database Versions ───────────────────────────────────────────────────────\n\nexport const DB_VERSIONS: Record<string, string[]> = {\n postgresql: ['18.3'],\n mysql: ['8.4'],\n sqlite: ['3'],\n};\n\n// ─── Default Web Server ──────────────────────────────────────────────────────\n\nexport const DEFAULT_WEB_SERVER = 'traefik' as const;\n\n// ─── Domain Defaults ─────────────────────────────────────────────────────────\n\nexport const DEFAULT_DOMAIN_PROVIDER = 'local' as const;\nexport const DEFAULT_SSL_MODE = 'self-signed' as const;\n\n// ─── Boilerplate Defaults ────────────────────────────────────────────────────\n\nexport const DEFAULT_DEV_MODE = 'hot-reload' as const;\n\n/** Git repository URL for Brewnet boilerplate templates (not yet populated) */\nexport const BOILERPLATE_REPO_URL = 'https://github.com/claude-code-expert/brewnet-boilerplate.git';\n\n// ─── CLI Metadata ────────────────────────────────────────────────────────────\n\nexport const CLI_NAME = 'brewnet';\nexport const CLI_DESCRIPTION = 'Your Home Server, Brewed Fresh';\n\n// ─── Rate Limiting ───────────────────────────────────────────────────────────\n\n/** Maximum API requests per minute for free tier */\nexport const RATE_LIMIT_FREE = 60;\n\n/** Maximum API requests per minute for Pro tier */\nexport const RATE_LIMIT_PRO = 300;\n\n// ─── Backup ──────────────────────────────────────────────────────────────────\n\n/** Maximum number of backup archives to retain */\nexport const MAX_BACKUP_RETENTION = 10;\n\n/** Default backup directory name within ~/.brewnet */\nexport const BACKUP_DIR_NAME = 'backups';\n\n// ─── Timeouts ────────────────────────────────────────────────────────────────\n\n/** Timeout for Docker image pull operations (ms) */\nexport const DOCKER_PULL_TIMEOUT_MS = 300_000;\n\n/** Timeout for Docker container start operations (ms) */\nexport const DOCKER_START_TIMEOUT_MS = 60_000;\n\n/** Timeout for SSL certificate issuance (ms) */\nexport const SSL_ISSUANCE_TIMEOUT_MS = 120_000;\n\n/** Timeout for DNS propagation check (ms) */\nexport const DNS_PROPAGATION_TIMEOUT_MS = 300_000;\n\n// ─── Logging ────────────────────────────────────────────────────────────────\n\n/** Maximum log file size per container (Docker json-file driver) */\nexport const DOCKER_LOG_MAX_SIZE = '10m';\n\n/** Maximum number of rotated log files per container */\nexport const DOCKER_LOG_MAX_FILES = '3';\n\n/** Days before CLI log files are deleted */\nexport const CLI_LOG_RETENTION_DAYS = 30;\n\n/** Maximum access/tunnel log file size before copytruncate rotation (bytes) */\nexport const ACCESS_LOG_MAX_BYTES = 50 * 1024 * 1024;\n\n/** Default page size for log queries */\nexport const LOG_QUERY_DEFAULT_LIMIT = 100;\n\n/** Maximum page size for log queries */\nexport const LOG_QUERY_MAX_LIMIT = 1000;\n\n/** Admin Panel log auto-refresh interval (ms) */\nexport const LOG_POLL_INTERVAL_MS = 5000;\n","// T010 — Error codes, backup records, log entries, and generated config types\n\n// ─── Error Codes ─────────────────────────────────────────────────────────────\n\nexport enum ErrorCode {\n /** Docker daemon not running */\n BN001 = 'BN001',\n /** Port already in use */\n BN002 = 'BN002',\n /** SSL certificate issuance failed */\n BN003 = 'BN003',\n /** Invalid license key */\n BN004 = 'BN004',\n /** Rate limit exceeded */\n BN005 = 'BN005',\n /** Build failed */\n BN006 = 'BN006',\n /** Invalid Git repository */\n BN007 = 'BN007',\n /** Resource not found */\n BN008 = 'BN008',\n /** Database error */\n BN009 = 'BN009',\n /** Feature requires Pro plan */\n BN010 = 'BN010',\n}\n\n/** Maps error codes to their corresponding HTTP status codes */\nexport const ERROR_HTTP_STATUS: Record<ErrorCode, number> = {\n [ErrorCode.BN001]: 503,\n [ErrorCode.BN002]: 409,\n [ErrorCode.BN003]: 500,\n [ErrorCode.BN004]: 401,\n [ErrorCode.BN005]: 429,\n [ErrorCode.BN006]: 500,\n [ErrorCode.BN007]: 400,\n [ErrorCode.BN008]: 404,\n [ErrorCode.BN009]: 500,\n [ErrorCode.BN010]: 403,\n};\n\n/** Human-readable descriptions for each error code */\nexport const ERROR_MESSAGES: Record<ErrorCode, string> = {\n [ErrorCode.BN001]: 'Docker daemon is not running. Please start Docker and try again.',\n [ErrorCode.BN002]: 'Port is already in use. Please free the port or choose a different one.',\n [ErrorCode.BN003]: 'SSL certificate issuance failed. Check your domain configuration.',\n [ErrorCode.BN004]: 'Invalid license key. Please verify your license.',\n [ErrorCode.BN005]: 'Rate limit exceeded. Please wait and try again.',\n [ErrorCode.BN006]: 'Build failed. Check the build logs for details.',\n [ErrorCode.BN007]: 'Invalid Git repository. Ensure the repository URL is correct.',\n [ErrorCode.BN008]: 'Resource not found.',\n [ErrorCode.BN009]: 'Database error. Check the database configuration and logs.',\n [ErrorCode.BN010]: 'This feature requires a Pro plan. Upgrade to access it.',\n};\n\n// ─── Brewnet Error Class ─────────────────────────────────────────────────────\n\nexport class BrewnetError extends Error {\n public readonly code: ErrorCode;\n public readonly httpStatus: number;\n public readonly metadata?: Record<string, unknown>;\n\n constructor(code: ErrorCode, message?: string, metadata?: Record<string, unknown>) {\n super(message ?? ERROR_MESSAGES[code]);\n this.name = 'BrewnetError';\n this.code = code;\n this.httpStatus = ERROR_HTTP_STATUS[code];\n this.metadata = metadata;\n\n // Maintain proper prototype chain for instanceof checks\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n// ─── Log Entry ───────────────────────────────────────────────────────────────\n\nexport type LogLevel = 'info' | 'warn' | 'error';\n\nexport interface LogEntry {\n /** Timestamp of the log entry */\n timestamp: Date;\n /** Severity level */\n level: LogLevel;\n /** CLI command that generated this log (e.g., \"brewnet add jellyfin\") */\n command: string;\n /** Human-readable log message */\n message: string;\n /** Optional structured metadata */\n metadata?: Record<string, unknown>;\n}\n\n// ─── Backup Record ───────────────────────────────────────────────────────────\n\nexport interface BackupRecord {\n /** Unique backup identifier (UUID) */\n id: string;\n /** Filesystem path to the backup archive */\n path: string;\n /** Backup archive size in bytes */\n size: number;\n /** List of service IDs included in this backup */\n services: string[];\n /** When the backup was created */\n createdAt: Date;\n /** Name of the project that was backed up */\n projectName: string;\n /** Filesystem path of the project that was backed up */\n projectPath: string;\n}\n\n// ─── Generated Config ────────────────────────────────────────────────────────\n\nexport interface GeneratedFile {\n /** Relative file path within the project directory */\n path: string;\n /** Full file content as a string */\n content: string;\n /** Unix file permissions (e.g., 0o600 for .env files) */\n permissions?: number;\n}\n\nexport interface GeneratedConfig {\n /** Absolute path to the project directory */\n projectPath: string;\n /** List of files to be written */\n files: GeneratedFile[];\n}\n","// T011 — Zod schema for WizardState validation\n// Validates the complete wizard state object including all sub-schemas.\n\nimport { z } from 'zod';\nimport type { WizardState } from '../types/wizard-state.js';\n\n// ─── Primitive Schemas ───────────────────────────────────────────────────────\n\nexport const languageSchema = z.enum([\n 'python', 'nodejs', 'java', 'rust', 'go', 'kotlin',\n]);\n\nexport const frontendTechSchema = z.enum([\n 'react', 'vue', 'none',\n]);\n\nexport const webServerServiceSchema = z.enum(['traefik', 'nginx', 'caddy']);\n\nexport const fileServerServiceSchema = z.enum(['nextcloud', 'minio', '']);\n\nexport const dbPrimarySchema = z.enum(['postgresql', 'mysql', 'sqlite', '']);\n\nexport const cacheServiceSchema = z.enum(['']);\n\nexport const domainProviderSchema = z.enum(['local', 'tunnel', 'quick-tunnel']);\n\nexport const sslModeSchema = z.enum(['self-signed', 'letsencrypt', 'cloudflare']);\n\nexport const setupTypeSchema = z.enum(['full', 'partial']);\n\nexport const fileBrowserModeSchema = z.enum(['directory', 'standalone', '']);\n\nexport const devModeSchema = z.enum(['hot-reload', 'production']);\n\n// ─── Sub-Schemas ─────────────────────────────────────────────────────────────\n\nexport const adminConfigSchema = z.object({\n username: z.string().min(1, 'Admin username is required'),\n password: z.string().min(8, 'Admin password must be at least 8 characters'),\n storage: z.literal('local'),\n});\n\nexport const webServerConfigSchema = z.object({\n enabled: z.literal(true),\n service: webServerServiceSchema,\n});\n\nexport const fileServerConfigSchema = z.object({\n enabled: z.boolean(),\n service: fileServerServiceSchema,\n});\n\nexport const gitServerConfigSchema = z.object({\n enabled: z.literal(true),\n service: z.literal('gitea'),\n port: z.number().int().min(1).max(65535),\n sshPort: z.number().int().min(1).max(65535),\n});\n\nexport const dbServerConfigSchema = z.object({\n enabled: z.boolean(),\n primary: dbPrimarySchema,\n primaryVersion: z.string(),\n dbName: z.string(),\n dbUser: z.string(),\n dbPassword: z.string(),\n adminUI: z.boolean(),\n pgadminEmail: z.string(),\n cache: cacheServiceSchema,\n});\n\nexport const mediaConfigSchema = z.object({\n enabled: z.boolean(),\n services: z.array(z.string()),\n});\n\nexport const sshServerConfigSchema = z.object({\n enabled: z.boolean(),\n port: z.number().int().min(1).max(65535),\n passwordAuth: z.boolean(),\n sftp: z.boolean(),\n});\n\nexport const appServerConfigSchema = z.object({\n enabled: z.boolean(),\n});\n\nexport const fileBrowserConfigSchema = z.object({\n enabled: z.boolean(),\n mode: fileBrowserModeSchema,\n});\n\nexport const serverComponentsSchema = z.object({\n webServer: webServerConfigSchema,\n fileServer: fileServerConfigSchema,\n gitServer: gitServerConfigSchema,\n dbServer: dbServerConfigSchema,\n media: mediaConfigSchema,\n sshServer: sshServerConfigSchema,\n appServer: appServerConfigSchema,\n fileBrowser: fileBrowserConfigSchema,\n});\n\nexport const devStackConfigSchema = z.object({\n languages: z.array(languageSchema),\n frameworks: z.record(z.string(), z.string()),\n frontend: frontendTechSchema.nullable(),\n});\n\nexport const boilerplateConfigSchema = z.object({\n generate: z.boolean(),\n sampleData: z.boolean(),\n devMode: devModeSchema,\n});\n\nexport const tunnelModeSchema = z.enum(['quick', 'named', 'none']);\n\nexport const cloudflareConfigSchema = z.object({\n enabled: z.boolean(),\n tunnelMode: tunnelModeSchema,\n quickTunnelUrl: z.string(),\n accountId: z.string(),\n apiToken: z.string(),\n tunnelId: z.string(),\n tunnelToken: z.string(),\n tunnelName: z.string(),\n zoneId: z.string(),\n zoneName: z.string(),\n});\n\nexport const domainConfigSchema = z.object({\n provider: domainProviderSchema,\n name: z.string(),\n ssl: sslModeSchema,\n cloudflare: cloudflareConfigSchema,\n});\n\nexport const domainScenarioSchema = z.enum(['A', 'B', 'C']);\n\nexport const domainConnectionSchema = z.object({\n appName: z.string().min(1, 'App name is required'),\n subdomain: z.string().min(1, 'Subdomain is required').regex(\n /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/,\n 'Subdomain must be a valid DNS label (lowercase alphanumeric + hyphens, max 63 chars)',\n ),\n domain: z.string().min(1, 'Domain is required'),\n hostname: z.string().min(1, 'Hostname is required'),\n tunnelId: z.string().min(1, 'Tunnel ID is required'),\n cnameRecordId: z.string(),\n containerPort: z.number().int().min(1).max(65535),\n connectedAt: z.string().datetime(),\n scenario: domainScenarioSchema,\n});\n\n// ─── Root Schema ─────────────────────────────────────────────────────────────\n\nexport const wizardStateSchema = z.object({\n schemaVersion: z.literal(7),\n projectName: z.string().min(1, 'Project name is required').regex(\n /^[a-z0-9][a-z0-9-]*$/,\n 'Project name must start with a lowercase letter or number and contain only lowercase letters, numbers, and hyphens',\n ),\n projectPath: z.string().min(1, 'Project path is required'),\n setupType: setupTypeSchema,\n admin: adminConfigSchema,\n servers: serverComponentsSchema,\n devStack: devStackConfigSchema,\n boilerplate: boilerplateConfigSchema,\n domain: domainConfigSchema,\n domainConnections: z.array(domainConnectionSchema),\n portRemapping: z.record(z.coerce.number(), z.number().int().min(1).max(65535)),\n}) satisfies z.ZodType<WizardState>;\n\nexport type ValidatedWizardState = z.infer<typeof wizardStateSchema>;\n\n// ─── Validation Helpers ──────────────────────────────────────────────────────\n\n/**\n * Validates a WizardState object and returns the parsed result.\n * Throws a ZodError if validation fails.\n */\nexport function validateWizardState(data: unknown): WizardState {\n return wizardStateSchema.parse(data);\n}\n\n/**\n * Safely validates a WizardState object without throwing.\n * Returns a discriminated union with success/error.\n */\nexport function safeValidateWizardState(data: unknown): z.SafeParseReturnType<unknown, WizardState> {\n return wizardStateSchema.safeParse(data);\n}\n","// T012 — Zod schema for brewnet.config.json import/export\n// A subset of WizardState used when exporting or importing wizard configurations.\n// Sensitive fields (passwords, tokens) are excluded from export by default.\n\nimport { z } from 'zod';\nimport {\n setupTypeSchema,\n webServerServiceSchema,\n fileServerServiceSchema,\n dbPrimarySchema,\n cacheServiceSchema,\n domainProviderSchema,\n sslModeSchema,\n fileBrowserModeSchema,\n devModeSchema,\n languageSchema,\n frontendTechSchema,\n} from './wizard-state.schema.js';\n\n// ─── Config Sub-Schemas (export-safe, no secrets) ────────────────────────────\n\nconst configAdminSchema = z.object({\n username: z.string().min(1),\n storage: z.literal('local'),\n});\n\nconst configWebServerSchema = z.object({\n enabled: z.literal(true),\n service: webServerServiceSchema,\n});\n\nconst configFileServerSchema = z.object({\n enabled: z.boolean(),\n service: fileServerServiceSchema,\n});\n\nconst configGitServerSchema = z.object({\n enabled: z.literal(true),\n service: z.literal('gitea'),\n port: z.number().int().min(1).max(65535),\n sshPort: z.number().int().min(1).max(65535),\n});\n\nconst configDbServerSchema = z.object({\n enabled: z.boolean(),\n primary: dbPrimarySchema,\n primaryVersion: z.string(),\n dbName: z.string(),\n dbUser: z.string(),\n adminUI: z.boolean(),\n pgadminEmail: z.string(),\n cache: cacheServiceSchema,\n // dbPassword is intentionally excluded from export\n});\n\nconst configMediaSchema = z.object({\n enabled: z.boolean(),\n services: z.array(z.string()),\n});\n\nconst configSshServerSchema = z.object({\n enabled: z.boolean(),\n port: z.number().int().min(1).max(65535),\n passwordAuth: z.boolean(),\n sftp: z.boolean(),\n});\n\nconst configAppServerSchema = z.object({\n enabled: z.boolean(),\n});\n\nconst configFileBrowserSchema = z.object({\n enabled: z.boolean(),\n mode: fileBrowserModeSchema,\n});\n\nconst configServersSchema = z.object({\n webServer: configWebServerSchema,\n fileServer: configFileServerSchema,\n gitServer: configGitServerSchema,\n dbServer: configDbServerSchema,\n media: configMediaSchema,\n sshServer: configSshServerSchema,\n appServer: configAppServerSchema,\n fileBrowser: configFileBrowserSchema,\n});\n\nconst configDevStackSchema = z.object({\n languages: z.array(languageSchema),\n frameworks: z.record(z.string(), z.string()),\n frontend: frontendTechSchema.nullable(),\n});\n\nconst configBoilerplateSchema = z.object({\n generate: z.boolean(),\n sampleData: z.boolean(),\n devMode: devModeSchema,\n});\n\nconst configCloudflareSchema = z.object({\n enabled: z.boolean(),\n tunnelName: z.string(),\n // tunnelToken is intentionally excluded from export\n});\n\nconst configDomainSchema = z.object({\n provider: domainProviderSchema,\n name: z.string(),\n ssl: sslModeSchema,\n cloudflare: configCloudflareSchema,\n});\n\n// ─── Root Config Schema ──────────────────────────────────────────────────────\n\nexport const brewnetConfigSchema = z.object({\n schemaVersion: z.literal(7),\n projectName: z.string().min(1).regex(\n /^[a-z0-9][a-z0-9-]*$/,\n 'Project name must start with a lowercase letter or number and contain only lowercase letters, numbers, and hyphens',\n ),\n projectPath: z.string().min(1),\n setupType: setupTypeSchema,\n admin: configAdminSchema,\n servers: configServersSchema,\n devStack: configDevStackSchema,\n boilerplate: configBoilerplateSchema,\n domain: configDomainSchema,\n});\n\nexport type BrewnetConfig = z.infer<typeof brewnetConfigSchema>;\n\n// ─── Validation Helpers ──────────────────────────────────────────────────────\n\n/**\n * Validates a brewnet.config.json object. Throws on failure.\n */\nexport function validateBrewnetConfig(data: unknown): BrewnetConfig {\n return brewnetConfigSchema.parse(data);\n}\n\n/**\n * Safely validates a brewnet.config.json object without throwing.\n */\nexport function safeValidateBrewnetConfig(data: unknown): z.SafeParseReturnType<unknown, BrewnetConfig> {\n return brewnetConfigSchema.safeParse(data);\n}\n"],"mappings":"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","names":["ErrorCode","z","z"]}
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  addQuickTunnelAppLabels
4
- } from "./chunk-AXSHZEB3.js";
4
+ } from "./chunk-MOQNPKUG.js";
5
5
  import {
6
6
  BOILERPLATE_REPO_URL
7
- } from "./chunk-HCHY5UIQ.js";
7
+ } from "./chunk-F2M6G5C7.js";
8
8
 
9
9
  // src/services/boilerplate-manager.ts
10
10
  import { readFileSync, writeFileSync, rmSync, readdirSync, statSync, existsSync } from "fs";
@@ -290,4 +290,4 @@ export {
290
290
  pollHealth,
291
291
  verifyEndpoints
292
292
  };
293
- //# sourceMappingURL=chunk-54WFZCU6.js.map
293
+ //# sourceMappingURL=chunk-F2Y226UA.js.map
@@ -16,7 +16,7 @@ import {
16
16
  startApp,
17
17
  stopApp,
18
18
  updateDeploySettings
19
- } from "./chunk-OH233QV2.js";
19
+ } from "./chunk-7VX572H4.js";
20
20
  import {
21
21
  DomainManager,
22
22
  addService,
@@ -25,19 +25,19 @@ import {
25
25
  listBackups,
26
26
  queryLogs,
27
27
  removeService
28
- } from "./chunk-YAYXULLO.js";
28
+ } from "./chunk-MSVYAYKQ.js";
29
29
  import {
30
30
  verifyToken
31
31
  } from "./chunk-YXFDB5YX.js";
32
32
  import {
33
33
  SERVICE_REGISTRY,
34
34
  getServiceDefinition
35
- } from "./chunk-AXSHZEB3.js";
35
+ } from "./chunk-MOQNPKUG.js";
36
36
  import {
37
37
  getLastProject,
38
38
  loadState,
39
39
  logger
40
- } from "./chunk-ZKMWE5AH.js";
40
+ } from "./chunk-BD4MDAIG.js";
41
41
  import {
42
42
  getStackById
43
43
  } from "./chunk-SYV6PK3R.js";
@@ -51,9 +51,7 @@ import { fileURLToPath } from "url";
51
51
  import { homedir } from "os";
52
52
  import Dockerode from "dockerode";
53
53
  var PKG_ROOT = join(fileURLToPath(import.meta.url), "../../../..");
54
- var ADMIN_UI_BUNDLED = join(fileURLToPath(import.meta.url), "../../admin-ui");
55
- var ADMIN_UI_MONOREPO = join(PKG_ROOT, "packages/admin-ui/dist");
56
- var ADMIN_UI_DIST = existsSync(join(ADMIN_UI_BUNDLED, "index.html")) ? ADMIN_UI_BUNDLED : ADMIN_UI_MONOREPO;
54
+ var ADMIN_UI_DIST = join(fileURLToPath(import.meta.url), "../admin-ui");
57
55
  var MIME_TYPES = {
58
56
  ".html": "text/html; charset=utf-8",
59
57
  ".js": "application/javascript; charset=utf-8",
@@ -916,7 +914,13 @@ function createAdminServer(options = {}) {
916
914
  return;
917
915
  }
918
916
  res.writeHead(503, { "Content-Type": "text/plain" });
919
- res.end("Admin UI not built. Run: pnpm --filter @brewnet/admin-ui build");
917
+ res.end(
918
+ `Admin UI not found.
919
+
920
+ Expected: ${ADMIN_UI_DIST}/index.html
921
+
922
+ Reinstall: curl -fsSL https://raw.githubusercontent.com/claude-code-expert/brewnet/main/install.sh | bash`
923
+ );
920
924
  return;
921
925
  }
922
926
  if (parts[0] === "api") {
@@ -1768,7 +1772,7 @@ async function handleCloudflareZones(res, state) {
1768
1772
  const firstAccountId = zones[0]?.accountId;
1769
1773
  if (firstAccountId) {
1770
1774
  state.domain.cloudflare.accountId = firstAccountId;
1771
- const { saveState: save } = await import("./state-2SI3P4JG.js");
1775
+ const { saveState: save } = await import("./state-CJSUDM4H.js");
1772
1776
  save(state);
1773
1777
  }
1774
1778
  }
@@ -1814,7 +1818,7 @@ async function handleCreateTunnel(res, body, state, projectPath) {
1814
1818
  try {
1815
1819
  const { createTunnel: cfCreateTunnel } = await import("./cloudflare-client-F2TGQXGS.js");
1816
1820
  const result = await cfCreateTunnel(cf.apiToken, cf.accountId, tunnelName.trim());
1817
- const { saveState: save } = await import("./state-2SI3P4JG.js");
1821
+ const { saveState: save } = await import("./state-CJSUDM4H.js");
1818
1822
  state.domain.cloudflare.tunnelId = result.tunnelId;
1819
1823
  state.domain.cloudflare.tunnelToken = result.tunnelToken;
1820
1824
  state.domain.cloudflare.tunnelName = tunnelName.trim();
@@ -1827,7 +1831,7 @@ async function handleCreateTunnel(res, body, state, projectPath) {
1827
1831
  }
1828
1832
  const zoneName = cf.zoneName;
1829
1833
  try {
1830
- const { saveGiteaConfig } = await import("./app-manager-BD3DG3RL.js");
1834
+ const { saveGiteaConfig } = await import("./app-manager-6PEKSRZ2.js");
1831
1835
  const adminUsername = state.admin?.username ?? "admin";
1832
1836
  saveGiteaConfig("http://localhost/git", adminUsername);
1833
1837
  logger.info("tunnel", `[${tunnelName}] gitea-config.json normalized \u2192 http://localhost/git`);
@@ -1841,7 +1845,7 @@ async function handleCreateTunnel(res, body, state, projectPath) {
1841
1845
  const { existsSync: fsExists } = await import("fs");
1842
1846
  if (fsExists(composePath)) {
1843
1847
  try {
1844
- const { patchCloudflaredToNamedTunnel } = await import("./compose-generator-OFJ2YWMB.js");
1848
+ const { patchCloudflaredToNamedTunnel } = await import("./compose-generator-MIAP3RBT.js");
1845
1849
  composeUpdated = patchCloudflaredToNamedTunnel(composePath, result.tunnelToken);
1846
1850
  logger.info("tunnel", `[${tunnelName}] compose patch: composeUpdated=${composeUpdated}`);
1847
1851
  } catch (e) {
@@ -1895,7 +1899,7 @@ async function handleCreateTunnel(res, body, state, projectPath) {
1895
1899
  }
1896
1900
  if (zoneName) {
1897
1901
  try {
1898
- const { patchBuiltinServicesForNamedTunnel } = await import("./compose-generator-OFJ2YWMB.js");
1902
+ const { patchBuiltinServicesForNamedTunnel } = await import("./compose-generator-MIAP3RBT.js");
1899
1903
  const patchedServices = patchBuiltinServicesForNamedTunnel(composePath, zoneName);
1900
1904
  steps.push({ step: "services_env_patched", success: true, services: patchedServices });
1901
1905
  logger.info("tunnel", `[${tunnelName}] env patched for: ${patchedServices.join(", ") || "none"}`);
@@ -2002,7 +2006,7 @@ async function handleSettingsCloudflarePut(res, body, state) {
2002
2006
  });
2003
2007
  return;
2004
2008
  }
2005
- const { saveState: save } = await import("./state-2SI3P4JG.js");
2009
+ const { saveState: save } = await import("./state-CJSUDM4H.js");
2006
2010
  state.domain.cloudflare.apiToken = apiToken;
2007
2011
  let resolvedAccountId = accountId || state.domain.cloudflare.accountId || await (await import("./cloudflare-client-F2TGQXGS.js")).getAccounts(apiToken).then((a) => a[0]?.id ?? "").catch(() => "");
2008
2012
  if (zoneId) state.domain.cloudflare.zoneId = zoneId;
@@ -2039,4 +2043,4 @@ async function handleSettingsCloudflarePut(res, body, state) {
2039
2043
  export {
2040
2044
  createAdminServer
2041
2045
  };
2042
- //# sourceMappingURL=chunk-76C5BGZK.js.map
2046
+ //# sourceMappingURL=chunk-JMKFUHZO.js.map