@archznn/xavva 2.9.0 → 3.1.0

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.
@@ -0,0 +1,138 @@
1
+ import { Logger } from "./ui";
2
+
3
+ export type LogLevel = "silent" | "error" | "warn" | "info" | "verbose" | "trace" | "silly";
4
+
5
+ interface LogLevelConfig {
6
+ value: number;
7
+ color: string;
8
+ prefix: string;
9
+ }
10
+
11
+ export class LoggerLevel {
12
+ private static currentLevel: LogLevel = "info";
13
+ private static readonly levels: Record<LogLevel, LogLevelConfig> = {
14
+ silent: { value: 0, color: "", prefix: "" },
15
+ error: { value: 1, color: Logger.C.error, prefix: "ERR" },
16
+ warn: { value: 2, color: Logger.C.warning, prefix: "WRN" },
17
+ info: { value: 3, color: Logger.C.info, prefix: "INF" },
18
+ verbose: { value: 4, color: Logger.C.primary, prefix: "VRB" },
19
+ trace: { value: 5, color: Logger.C.gray, prefix: "TRC" },
20
+ silly: { value: 6, color: Logger.C.darkGray, prefix: "SLY" },
21
+ };
22
+
23
+ static setLevel(level: LogLevel): void {
24
+ this.currentLevel = level;
25
+ }
26
+
27
+ static getLevel(): LogLevel {
28
+ return this.currentLevel;
29
+ }
30
+
31
+ static shouldLog(level: LogLevel): boolean {
32
+ return this.levels[level].value <= this.levels[this.currentLevel].value;
33
+ }
34
+
35
+ private static log(level: LogLevel, message: string, ...args: unknown[]): void {
36
+ if (!this.shouldLog(level)) return;
37
+
38
+ const config = this.levels[level];
39
+ const formatted = args.length > 0
40
+ ? this.formatMessage(message, args)
41
+ : message;
42
+
43
+ if (level === "error") {
44
+ Logger.error(formatted);
45
+ } else if (level === "warn") {
46
+ Logger.warn(formatted);
47
+ } else {
48
+ console.log(`${Logger.C.gray}│${Logger.C.reset} ${config.color}[${config.prefix}]${Logger.C.reset} ${formatted}`);
49
+ }
50
+ }
51
+
52
+ private static formatMessage(message: string, args: unknown[]): string {
53
+ return args.reduce((msg, arg, index) => {
54
+ const placeholder = `%${index + 1}`;
55
+ const str = typeof arg === "object"
56
+ ? JSON.stringify(arg, null, 2)
57
+ : String(arg);
58
+ return msg.replace(placeholder, str);
59
+ }, message);
60
+ }
61
+
62
+ // Public logging methods
63
+ static error(message: string, ...args: unknown[]): void {
64
+ this.log("error", message, ...args);
65
+ }
66
+
67
+ static warn(message: string, ...args: unknown[]): void {
68
+ this.log("warn", message, ...args);
69
+ }
70
+
71
+ static info(message: string, ...args: unknown[]): void {
72
+ this.log("info", message, ...args);
73
+ }
74
+
75
+ static verbose(message: string, ...args: unknown[]): void {
76
+ this.log("verbose", message, ...args);
77
+ }
78
+
79
+ static trace(message: string, ...args: unknown[]): void {
80
+ this.log("trace", message, ...args);
81
+ }
82
+
83
+ static silly(message: string, ...args: unknown[]): void {
84
+ this.log("silly", message, ...args);
85
+ }
86
+
87
+ // Utility methods for specific debug scenarios
88
+ static debugCommand(command: string, args: string[]): void {
89
+ if (this.shouldLog("verbose")) {
90
+ this.verbose("Executing: %1 %2", command, args.join(" "));
91
+ }
92
+ }
93
+
94
+ static debugSpawn(cmd: string, options: Record<string, unknown>): void {
95
+ if (this.shouldLog("trace")) {
96
+ this.trace("Spawn: %1 with options: %2", cmd, options);
97
+ }
98
+ }
99
+
100
+ static debugHttp(method: string, url: string, status?: number): void {
101
+ if (this.shouldLog("verbose")) {
102
+ const statusStr = status !== undefined ? ` -> ${status}` : "";
103
+ this.verbose("HTTP %1 %2%3", method.toUpperCase(), url, statusStr);
104
+ }
105
+ }
106
+
107
+ static debugFile(operation: string, path: string, details?: unknown): void {
108
+ if (this.shouldLog("trace")) {
109
+ this.trace("File %1: %2 %3", operation, path, details || "");
110
+ }
111
+ }
112
+
113
+ static debugConfig(key: string, value: unknown): void {
114
+ if (this.shouldLog("silly")) {
115
+ this.silly("Config: %1 = %2", key, value);
116
+ }
117
+ }
118
+
119
+ static debugPerformance(operation: string, durationMs: number): void {
120
+ if (this.shouldLog("verbose")) {
121
+ this.verbose("Performance: %1 took %2ms", operation, durationMs);
122
+ }
123
+ }
124
+
125
+ static debugTiming(label: string): () => void {
126
+ if (!this.shouldLog("verbose")) {
127
+ return () => {}; // No-op
128
+ }
129
+
130
+ const start = performance.now();
131
+ this.verbose("Timing started: %1", label);
132
+
133
+ return () => {
134
+ const duration = Math.round(performance.now() - start);
135
+ this.verbose("Timing ended: %1 took %2ms", label, duration);
136
+ };
137
+ }
138
+ }
@@ -44,6 +44,29 @@ export class ConfigManager {
44
44
  "dry-run": { type: "boolean" },
45
45
  force: { type: "boolean" },
46
46
  src: { type: "string" },
47
+ // Multi-environment
48
+ env: { type: "string" },
49
+ environment: { type: "string" },
50
+ // Test runner
51
+ coverage: { type: "boolean" },
52
+ "fail-fast": { type: "boolean" },
53
+ parallel: { type: "boolean" },
54
+ // HTTP client
55
+ interactive: { type: "boolean", short: "i" },
56
+ "base-url": { type: "string" },
57
+ body: { type: "string" },
58
+ file: { type: "string" },
59
+ header: { type: "string", multiple: true },
60
+ "content-type": { type: "string" },
61
+ accept: { type: "string" },
62
+ param: { type: "string", multiple: true },
63
+ timeout: { type: "string" },
64
+ // Docker
65
+ tag: { type: "string" },
66
+ "java-version": { type: "string" },
67
+ detached: { type: "boolean", short: "d" },
68
+ registry: { type: "string" },
69
+ namespace: { type: "string" },
47
70
  },
48
71
  strict: false,
49
72
  allowPositionals: true,
@@ -142,19 +165,30 @@ export class ConfigManager {
142
165
  tomcatPath = embeddedService.getTomcatHome();
143
166
  }
144
167
 
168
+ // Detectar environment
169
+ const environment = String(cliValues.env || cliValues.environment || xavvaJson.env || xavvaJson.environment || "");
170
+ const envConfig = environment && (xavvaJson as any).environments?.[environment];
171
+
172
+ // Merge environment config
173
+ const finalPort = envConfig?.port
174
+ ? parseInt(String(envConfig.port))
175
+ : parseInt(String(cliValues.port || xavvaJson.port || String(DEFAULT_TOMCAT_PORT)));
176
+ const finalProfile = envConfig?.profile || String(cliValues.profile || xavvaJson.profile || "");
177
+
145
178
  const config: AppConfig = {
146
179
  tomcat: {
147
180
  path: tomcatPath,
148
- port: parseInt(String(cliValues.port || xavvaJson.port || String(DEFAULT_TOMCAT_PORT))),
181
+ port: finalPort,
149
182
  webapps: "webapps",
150
183
  grep: cliValues.grep || xavvaJson.grep ? String(cliValues.grep || xavvaJson.grep) : "",
151
184
  embedded: useEmbedded,
152
185
  version: embeddedVersion,
186
+ ...(envConfig?.tomcat || {})
153
187
  },
154
188
  project: {
155
189
  appName: cliValues.name || xavvaJson.name ? String(cliValues.name || xavvaJson.name) : "",
156
190
  buildTool: (cliValues.tool as any) || (xavvaJson.tool as any) || detectedTool,
157
- profile: String(cliValues.profile || xavvaJson.profile || ""),
191
+ profile: finalProfile,
158
192
  skipBuild: !!(cliValues["no-build"] ?? xavvaJson["no-build"]),
159
193
  skipScan: cliValues.scan !== undefined ? !cliValues.scan : (xavvaJson.scan !== undefined ? !xavvaJson.scan : true),
160
194
  clean: !!(cliValues.clean ?? xavvaJson.clean),
@@ -168,6 +202,8 @@ export class ConfigManager {
168
202
  encoding: cliValues.encoding || xavvaJson.encoding || "",
169
203
  war: !!(cliValues.war ?? xavvaJson.war),
170
204
  cache: !!(cliValues.cache ?? xavvaJson.cache),
205
+ environment,
206
+ environments: (xavvaJson as any).environments
171
207
  }
172
208
  };
173
209