kaven-cli 0.4.0 → 0.5.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.
- package/README.md +154 -215
- package/dist/EnvManager-NMS3NMIE.js +15 -0
- package/dist/MarketplaceClient-YCFH2VU4.js +1 -0
- package/dist/chunk-JHLQ46NG.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +216 -286
- package/dist/tier-table-DQMPQSI2.js +6 -0
- package/package.json +26 -10
- package/dist/commands/auth/login.js +0 -122
- package/dist/commands/auth/logout.js +0 -23
- package/dist/commands/auth/whoami.js +0 -36
- package/dist/commands/cache/index.js +0 -43
- package/dist/commands/config/features.js +0 -1026
- package/dist/commands/config/index.js +0 -95
- package/dist/commands/index.js +0 -2
- package/dist/commands/init/index.js +0 -197
- package/dist/commands/init-ci/index.js +0 -153
- package/dist/commands/license/index.js +0 -10
- package/dist/commands/license/status.js +0 -44
- package/dist/commands/license/tier-table.js +0 -46
- package/dist/commands/marketplace/browse.js +0 -186
- package/dist/commands/marketplace/install.js +0 -263
- package/dist/commands/marketplace/list.js +0 -122
- package/dist/commands/module/activate.js +0 -206
- package/dist/commands/module/add.js +0 -69
- package/dist/commands/module/doctor.js +0 -175
- package/dist/commands/module/publish.js +0 -258
- package/dist/commands/module/remove.js +0 -58
- package/dist/commands/telemetry/view.js +0 -27
- package/dist/commands/upgrade/check.js +0 -162
- package/dist/commands/upgrade/index.js +0 -185
- package/dist/core/AuthService.js +0 -222
- package/dist/core/CacheManager.js +0 -154
- package/dist/core/ConfigManager.js +0 -166
- package/dist/core/EnvManager.js +0 -196
- package/dist/core/ErrorRecovery.js +0 -192
- package/dist/core/LicenseService.js +0 -83
- package/dist/core/ManifestParser.js +0 -52
- package/dist/core/MarkerService.js +0 -62
- package/dist/core/ModuleDoctor.js +0 -451
- package/dist/core/ModuleInstaller.js +0 -169
- package/dist/core/ProjectInitializer.js +0 -166
- package/dist/core/RegistryResolver.js +0 -95
- package/dist/core/SchemaActivator.js +0 -270
- package/dist/core/ScriptRunner.js +0 -73
- package/dist/core/SignatureVerifier.js +0 -75
- package/dist/core/index.js +0 -2
- package/dist/infrastructure/Container.js +0 -37
- package/dist/infrastructure/MarketplaceClient.js +0 -399
- package/dist/infrastructure/TelemetryBuffer.js +0 -73
- package/dist/infrastructure/TransactionalFileSystem.js +0 -77
- package/dist/infrastructure/errors.js +0 -63
- package/dist/infrastructure/index.js +0 -2
- package/dist/types/auth.js +0 -2
- package/dist/types/manifest.js +0 -45
- package/dist/types/markers.js +0 -10
- package/dist/types/marketplace.js +0 -2
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.moduleActivate = moduleActivate;
|
|
7
|
-
exports.moduleDeactivate = moduleDeactivate;
|
|
8
|
-
exports.moduleListActivation = moduleListActivation;
|
|
9
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
-
const ora_1 = __importDefault(require("ora"));
|
|
11
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
-
const SchemaActivator_1 = require("../../core/SchemaActivator");
|
|
13
|
-
const TelemetryBuffer_1 = require("../../infrastructure/TelemetryBuffer");
|
|
14
|
-
// ============================================================
|
|
15
|
-
// Helpers
|
|
16
|
-
// ============================================================
|
|
17
|
-
function findModuleDef(moduleId) {
|
|
18
|
-
return SchemaActivator_1.KAVEN_MODULES.find((m) => m.id === moduleId.toLowerCase());
|
|
19
|
-
}
|
|
20
|
-
function assertSchemaExists(exists, root) {
|
|
21
|
-
if (!exists) {
|
|
22
|
-
const fullPath = node_path_1.default.join(root, "packages", "database", "prisma", "schema.extended.prisma");
|
|
23
|
-
console.error(chalk_1.default.red(`\nErro: Schema não encontrado em: ${fullPath}`));
|
|
24
|
-
console.error(chalk_1.default.gray("Certifique-se de que o caminho fornecido é a raiz de um projeto Kaven válido."));
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
// ============================================================
|
|
29
|
-
// kaven module activate <name>
|
|
30
|
-
// ============================================================
|
|
31
|
-
async function moduleActivate(moduleName, projectRoot) {
|
|
32
|
-
const telemetry = TelemetryBuffer_1.TelemetryBuffer.getInstance();
|
|
33
|
-
const startTime = Date.now();
|
|
34
|
-
telemetry.capture("cli.module.activate.start", { moduleName });
|
|
35
|
-
const root = projectRoot ?? process.cwd();
|
|
36
|
-
const activator = new SchemaActivator_1.SchemaActivator(root);
|
|
37
|
-
const spinner = (0, ora_1.default)(`Ativando módulo ${moduleName}...`).start();
|
|
38
|
-
try {
|
|
39
|
-
// 1. Validar que o schema existe
|
|
40
|
-
const exists = await activator.exists();
|
|
41
|
-
spinner.stop();
|
|
42
|
-
assertSchemaExists(exists, root);
|
|
43
|
-
// 2. Validar que o módulo é conhecido
|
|
44
|
-
const def = findModuleDef(moduleName);
|
|
45
|
-
if (!def) {
|
|
46
|
-
console.error(chalk_1.default.red(`\nMódulo desconhecido: "${moduleName}".`));
|
|
47
|
-
console.error(chalk_1.default.gray(`Módulos disponíveis: ${SchemaActivator_1.KAVEN_MODULES.map((m) => m.id).join(", ")}`));
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
50
|
-
// 3. Verificar dependências
|
|
51
|
-
if (def.dependsOn.length > 0) {
|
|
52
|
-
spinner.start("Verificando dependências...");
|
|
53
|
-
const depStatuses = [];
|
|
54
|
-
for (const depId of def.dependsOn) {
|
|
55
|
-
const depDef = findModuleDef(depId);
|
|
56
|
-
if (!depDef)
|
|
57
|
-
continue;
|
|
58
|
-
const status = await activator.getModuleStatus(depDef);
|
|
59
|
-
depStatuses.push(status);
|
|
60
|
-
}
|
|
61
|
-
const missing = depStatuses.filter((s) => !s.active);
|
|
62
|
-
if (missing.length > 0) {
|
|
63
|
-
spinner.stop();
|
|
64
|
-
console.error(chalk_1.default.red(`\nDependências inativas para "${moduleName}": ${missing.map((m) => m.id).join(", ")}`));
|
|
65
|
-
console.error(chalk_1.default.gray(`Ative as dependências primeiro:\n${missing.map((m) => ` kaven module activate ${m.id}`).join("\n")}`));
|
|
66
|
-
process.exit(1);
|
|
67
|
-
}
|
|
68
|
-
spinner.stop();
|
|
69
|
-
}
|
|
70
|
-
// 4. Verificar se já está ativo
|
|
71
|
-
const current = await activator.getModuleStatus(def);
|
|
72
|
-
if (current.active) {
|
|
73
|
-
console.log(chalk_1.default.yellow(`\nMódulo "${def.label}" já está ativo.`));
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
// 5. Ativar
|
|
77
|
-
spinner.start(`Descomentando modelos de ${def.label} no schema...`);
|
|
78
|
-
await activator.activateModule(def);
|
|
79
|
-
spinner.succeed(chalk_1.default.green(`\nMódulo ${def.label} ativado. ${def.models.length} models adicionados: ${def.models.join(", ")}`));
|
|
80
|
-
console.log(chalk_1.default.cyan("\nSugestão: Execute `pnpm db:generate && pnpm db:migrate` para aplicar as mudanças."));
|
|
81
|
-
telemetry.capture("cli.module.activate.success", { moduleName: def.id, models: def.models.length }, Date.now() - startTime);
|
|
82
|
-
await telemetry.flush();
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
spinner.fail(chalk_1.default.red(`Falha ao ativar módulo: ${error instanceof Error ? error.message : String(error)}`));
|
|
86
|
-
telemetry.capture("cli.module.activate.error", { moduleName, error: error.message }, Date.now() - startTime);
|
|
87
|
-
await telemetry.flush();
|
|
88
|
-
process.exit(1);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
// ============================================================
|
|
92
|
-
// kaven module deactivate <name>
|
|
93
|
-
// ============================================================
|
|
94
|
-
async function moduleDeactivate(moduleName, projectRoot) {
|
|
95
|
-
const telemetry = TelemetryBuffer_1.TelemetryBuffer.getInstance();
|
|
96
|
-
const startTime = Date.now();
|
|
97
|
-
telemetry.capture("cli.module.deactivate.start", { moduleName });
|
|
98
|
-
const root = projectRoot ?? process.cwd();
|
|
99
|
-
const activator = new SchemaActivator_1.SchemaActivator(root);
|
|
100
|
-
const spinner = (0, ora_1.default)(`Desativando módulo ${moduleName}...`).start();
|
|
101
|
-
try {
|
|
102
|
-
// 1. Validar que o schema existe
|
|
103
|
-
const exists = await activator.exists();
|
|
104
|
-
spinner.stop();
|
|
105
|
-
assertSchemaExists(exists, root);
|
|
106
|
-
// 2. Validar módulo
|
|
107
|
-
const def = findModuleDef(moduleName);
|
|
108
|
-
if (!def) {
|
|
109
|
-
console.error(chalk_1.default.red(`\nMódulo desconhecido: "${moduleName}".`));
|
|
110
|
-
console.error(chalk_1.default.gray(`Módulos disponíveis: ${SchemaActivator_1.KAVEN_MODULES.map((m) => m.id).join(", ")}`));
|
|
111
|
-
process.exit(1);
|
|
112
|
-
}
|
|
113
|
-
// 3. Verificar se outros módulos ativos dependem deste
|
|
114
|
-
spinner.start("Verificando dependências reversas...");
|
|
115
|
-
const dependents = [];
|
|
116
|
-
for (const candidate of SchemaActivator_1.KAVEN_MODULES) {
|
|
117
|
-
if (candidate.id === def.id)
|
|
118
|
-
continue;
|
|
119
|
-
if (!candidate.dependsOn.includes(def.id))
|
|
120
|
-
continue;
|
|
121
|
-
const status = await activator.getModuleStatus(candidate);
|
|
122
|
-
if (status.active) {
|
|
123
|
-
dependents.push(candidate.id);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
if (dependents.length > 0) {
|
|
127
|
-
spinner.stop();
|
|
128
|
-
console.error(chalk_1.default.red(`\nNão é possível desativar "${moduleName}": os seguintes módulos dependem dele e estão ativos:`));
|
|
129
|
-
console.error(chalk_1.default.gray(` ${dependents.join(", ")}`));
|
|
130
|
-
console.error(chalk_1.default.gray(`Desative-os primeiro:\n${dependents.map((d) => ` kaven module deactivate ${d}`).join("\n")}`));
|
|
131
|
-
process.exit(1);
|
|
132
|
-
}
|
|
133
|
-
// 4. Verificar se já está inativo
|
|
134
|
-
const current = await activator.getModuleStatus(def);
|
|
135
|
-
if (!current.active) {
|
|
136
|
-
spinner.stop();
|
|
137
|
-
console.log(chalk_1.default.yellow(`\nMódulo "${def.label}" já está inativo.`));
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
// 5. Desativar
|
|
141
|
-
spinner.start(`Comentando modelos de ${def.label} no schema...`);
|
|
142
|
-
await activator.deactivateModule(def);
|
|
143
|
-
spinner.succeed(chalk_1.default.green(`\nMódulo ${def.label} desativado com sucesso.`));
|
|
144
|
-
console.log(chalk_1.default.cyan("\nSugestão: Execute `pnpm db:generate && pnpm db:migrate` para aplicar as mudanças."));
|
|
145
|
-
telemetry.capture("cli.module.deactivate.success", { moduleName: def.id }, Date.now() - startTime);
|
|
146
|
-
await telemetry.flush();
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
spinner.fail(chalk_1.default.red(`Falha ao desativar módulo: ${error instanceof Error ? error.message : String(error)}`));
|
|
150
|
-
telemetry.capture("cli.module.deactivate.error", { moduleName, error: error.message }, Date.now() - startTime);
|
|
151
|
-
await telemetry.flush();
|
|
152
|
-
process.exit(1);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
// ============================================================
|
|
156
|
-
// kaven module list
|
|
157
|
-
// ============================================================
|
|
158
|
-
async function moduleListActivation(projectRoot) {
|
|
159
|
-
const root = projectRoot ?? process.cwd();
|
|
160
|
-
const activator = new SchemaActivator_1.SchemaActivator(root);
|
|
161
|
-
const schemaExists = await activator.exists();
|
|
162
|
-
// Cabeçalho da tabela
|
|
163
|
-
const COL = {
|
|
164
|
-
module: 14,
|
|
165
|
-
status: 10,
|
|
166
|
-
models: 44,
|
|
167
|
-
deps: 20,
|
|
168
|
-
};
|
|
169
|
-
const header = chalk_1.default.bold("Module".padEnd(COL.module)) +
|
|
170
|
-
chalk_1.default.bold("Status".padEnd(COL.status)) +
|
|
171
|
-
chalk_1.default.bold("Models".padEnd(COL.models)) +
|
|
172
|
-
chalk_1.default.bold("Depends on");
|
|
173
|
-
const divider = "─".repeat(COL.module + COL.status + COL.models + COL.deps);
|
|
174
|
-
console.log();
|
|
175
|
-
console.log(chalk_1.default.blue("Módulos Kaven disponíveis\n"));
|
|
176
|
-
console.log(header);
|
|
177
|
-
console.log(chalk_1.default.gray(divider));
|
|
178
|
-
if (!schemaExists) {
|
|
179
|
-
for (const def of SchemaActivator_1.KAVEN_MODULES) {
|
|
180
|
-
const modCol = def.id.padEnd(COL.module);
|
|
181
|
-
const statusCol = chalk_1.default.gray("unknown".padEnd(COL.status));
|
|
182
|
-
const modelsCol = def.models.join(", ").padEnd(COL.models);
|
|
183
|
-
const depsCol = def.dependsOn.length > 0 ? def.dependsOn.join(", ") : "—";
|
|
184
|
-
console.log(`${modCol}${statusCol}${modelsCol}${depsCol}`);
|
|
185
|
-
}
|
|
186
|
-
console.log();
|
|
187
|
-
console.log(chalk_1.default.yellow("Atenção: schema.extended.prisma não encontrado. Status não pode ser determinado."));
|
|
188
|
-
console.log(chalk_1.default.gray("Execute este comando na raiz de um projeto Kaven para ver o status real."));
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
for (const def of SchemaActivator_1.KAVEN_MODULES) {
|
|
192
|
-
const status = await activator.getModuleStatus(def);
|
|
193
|
-
const modCol = def.id.padEnd(COL.module);
|
|
194
|
-
const statusText = status.active ? "active" : "inactive";
|
|
195
|
-
const statusColored = status.active
|
|
196
|
-
? chalk_1.default.green(statusText.padEnd(COL.status))
|
|
197
|
-
: chalk_1.default.gray(statusText.padEnd(COL.status));
|
|
198
|
-
const modelsCol = def.models.join(", ").padEnd(COL.models);
|
|
199
|
-
const depsCol = def.dependsOn.length > 0 ? def.dependsOn.join(", ") : "—";
|
|
200
|
-
console.log(`${modCol}${statusColored}${modelsCol}${depsCol}`);
|
|
201
|
-
}
|
|
202
|
-
console.log();
|
|
203
|
-
console.log(chalk_1.default.gray("Core (sempre ativo): Tenant, User, Role, Capability, AuthSession, AuditLog"));
|
|
204
|
-
console.log();
|
|
205
|
-
console.log(chalk_1.default.gray("Para ativar: kaven module activate <name> | Para desativar: kaven module deactivate <name>"));
|
|
206
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.moduleAdd = moduleAdd;
|
|
7
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
-
const ora_1 = __importDefault(require("ora"));
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
11
|
-
const ModuleInstaller_1 = require("../../core/ModuleInstaller");
|
|
12
|
-
const MarkerService_1 = require("../../core/MarkerService");
|
|
13
|
-
const ManifestParser_1 = require("../../core/ManifestParser");
|
|
14
|
-
const TelemetryBuffer_1 = require("../../infrastructure/TelemetryBuffer");
|
|
15
|
-
async function moduleAdd(manifestPath, projectRoot) {
|
|
16
|
-
const telemetry = TelemetryBuffer_1.TelemetryBuffer.getInstance();
|
|
17
|
-
const startTime = Date.now();
|
|
18
|
-
telemetry.capture("cli.module.add.start", { manifestPath });
|
|
19
|
-
const root = projectRoot || process.cwd();
|
|
20
|
-
const spinner = (0, ora_1.default)("Preparando instalação do módulo...").start();
|
|
21
|
-
try {
|
|
22
|
-
const markerService = new MarkerService_1.MarkerService();
|
|
23
|
-
const manifestParser = new ManifestParser_1.ManifestParser();
|
|
24
|
-
const installer = new ModuleInstaller_1.ModuleInstaller(root, markerService);
|
|
25
|
-
// 1. Resolver caminho do manifest
|
|
26
|
-
const absolutePath = path_1.default.isAbsolute(manifestPath)
|
|
27
|
-
? manifestPath
|
|
28
|
-
: path_1.default.join(root, manifestPath);
|
|
29
|
-
if (!(await fs_extra_1.default.pathExists(absolutePath))) {
|
|
30
|
-
throw new Error(`Arquivo de manifest não encontrado: ${manifestPath}`);
|
|
31
|
-
}
|
|
32
|
-
// 2. Parse do manifest
|
|
33
|
-
spinner.text = "Validando manifest...";
|
|
34
|
-
const manifest = await manifestParser.parse(absolutePath);
|
|
35
|
-
// 3. Instalar
|
|
36
|
-
spinner.text = `Instalando ${manifest.name}@${manifest.version}...`;
|
|
37
|
-
await installer.install(manifest);
|
|
38
|
-
// 4. Atualizar kaven.json
|
|
39
|
-
spinner.text = "Atualizando configuração do projeto...";
|
|
40
|
-
await updateKavenConfig(root, manifest.name, manifest.version);
|
|
41
|
-
// 5. Cache do manifest para desinstalação futura
|
|
42
|
-
spinner.text = "Salvando cache do manifest...";
|
|
43
|
-
const cacheDir = path_1.default.join(root, ".kaven", "modules", manifest.name);
|
|
44
|
-
await fs_extra_1.default.ensureDir(cacheDir);
|
|
45
|
-
await fs_extra_1.default.writeJson(path_1.default.join(cacheDir, "module.json"), manifest, {
|
|
46
|
-
spaces: 2,
|
|
47
|
-
});
|
|
48
|
-
spinner.succeed(chalk_1.default.green(`Módulo ${manifest.name} instalado com sucesso!`));
|
|
49
|
-
telemetry.capture("cli.module.add.success", { name: manifest.name }, Date.now() - startTime);
|
|
50
|
-
await telemetry.flush();
|
|
51
|
-
}
|
|
52
|
-
catch (error) {
|
|
53
|
-
telemetry.capture("cli.module.add.error", { error: error.message }, Date.now() - startTime);
|
|
54
|
-
await telemetry.flush();
|
|
55
|
-
spinner.fail(chalk_1.default.red(`Falha na instalação: ${error instanceof Error ? error.message : String(error)}`));
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
async function updateKavenConfig(projectRoot, name, version) {
|
|
60
|
-
const configPath = path_1.default.join(projectRoot, "kaven.json");
|
|
61
|
-
let config = { modules: {} };
|
|
62
|
-
if (await fs_extra_1.default.pathExists(configPath)) {
|
|
63
|
-
config = await fs_extra_1.default.readJson(configPath);
|
|
64
|
-
}
|
|
65
|
-
if (!config.modules)
|
|
66
|
-
config.modules = {};
|
|
67
|
-
config.modules[name] = version;
|
|
68
|
-
await fs_extra_1.default.writeJson(configPath, config, { spaces: 2 });
|
|
69
|
-
}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.moduleDoctor = moduleDoctor;
|
|
7
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
-
const child_process_1 = require("child_process");
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
11
|
-
const ModuleDoctor_1 = require("../../core/ModuleDoctor");
|
|
12
|
-
const MarkerService_1 = require("../../core/MarkerService");
|
|
13
|
-
const ManifestParser_1 = require("../../core/ManifestParser");
|
|
14
|
-
function severityPrefix(severity) {
|
|
15
|
-
switch (severity) {
|
|
16
|
-
case "error":
|
|
17
|
-
return chalk_1.default.red("[ERROR]");
|
|
18
|
-
case "warning":
|
|
19
|
-
return chalk_1.default.yellow("[WARN] ");
|
|
20
|
-
case "info":
|
|
21
|
-
return chalk_1.default.cyan("[INFO] ");
|
|
22
|
-
default:
|
|
23
|
-
return chalk_1.default.green("[OK] ");
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
/** Attempt auto-fixes for fixable issues. */
|
|
27
|
-
async function applyFixes(results, projectRoot) {
|
|
28
|
-
const fixable = results.filter((r) => r.fixable);
|
|
29
|
-
if (fixable.length === 0) {
|
|
30
|
-
console.log(chalk_1.default.gray(" No automatically fixable issues found."));
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
for (const result of fixable) {
|
|
34
|
-
const msg = result.message.toLowerCase();
|
|
35
|
-
// Missing npm deps: run pnpm install
|
|
36
|
-
if (msg.includes("missing npm dependency") || msg.includes("pnpm install")) {
|
|
37
|
-
console.log(chalk_1.default.blue(` Fixing: ${result.message}`));
|
|
38
|
-
try {
|
|
39
|
-
(0, child_process_1.execSync)("pnpm install", { cwd: projectRoot, stdio: "inherit" });
|
|
40
|
-
console.log(chalk_1.default.green(" ✓ pnpm install completed"));
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
console.log(chalk_1.default.red(" ✗ pnpm install failed"));
|
|
44
|
-
}
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
// Stale Prisma: run prisma generate
|
|
48
|
-
if (msg.includes("prisma")) {
|
|
49
|
-
console.log(chalk_1.default.blue(` Fixing: ${result.message}`));
|
|
50
|
-
try {
|
|
51
|
-
(0, child_process_1.execSync)("npx prisma generate", { cwd: projectRoot, stdio: "inherit" });
|
|
52
|
-
console.log(chalk_1.default.green(" ✓ npx prisma generate completed"));
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
console.log(chalk_1.default.red(" ✗ npx prisma generate failed"));
|
|
56
|
-
}
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
// Missing env vars: append placeholder
|
|
60
|
-
if (msg.includes("missing env vars") && result.file === ".env") {
|
|
61
|
-
const envPath = path_1.default.join(projectRoot, ".env");
|
|
62
|
-
const envExamplePath = path_1.default.join(projectRoot, ".env.example");
|
|
63
|
-
console.log(chalk_1.default.blue(` Fixing: ${result.message}`));
|
|
64
|
-
try {
|
|
65
|
-
const exampleContent = await fs_extra_1.default.readFile(envExamplePath, "utf-8");
|
|
66
|
-
const envContent = (await fs_extra_1.default.pathExists(envPath))
|
|
67
|
-
? await fs_extra_1.default.readFile(envPath, "utf-8")
|
|
68
|
-
: "";
|
|
69
|
-
const parseKeys = (content) => {
|
|
70
|
-
const keys = new Set();
|
|
71
|
-
for (const line of content.split("\n")) {
|
|
72
|
-
const trimmed = line.trim();
|
|
73
|
-
if (trimmed.startsWith("#") || !trimmed.includes("="))
|
|
74
|
-
continue;
|
|
75
|
-
const key = trimmed.split("=")[0].trim();
|
|
76
|
-
if (key)
|
|
77
|
-
keys.add(key);
|
|
78
|
-
}
|
|
79
|
-
return keys;
|
|
80
|
-
};
|
|
81
|
-
const exampleKeys = parseKeys(exampleContent);
|
|
82
|
-
const envKeys = parseKeys(envContent);
|
|
83
|
-
let appendContent = "\n# Added by kaven doctor --fix\n";
|
|
84
|
-
for (const key of exampleKeys) {
|
|
85
|
-
if (!envKeys.has(key)) {
|
|
86
|
-
appendContent += `${key}=PLACEHOLDER\n`;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
await fs_extra_1.default.appendFile(envPath, appendContent);
|
|
90
|
-
console.log(chalk_1.default.green(" ✓ Placeholder env vars appended to .env"));
|
|
91
|
-
}
|
|
92
|
-
catch {
|
|
93
|
-
console.log(chalk_1.default.red(" ✗ Could not append env vars"));
|
|
94
|
-
}
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
// Generic fallback
|
|
98
|
-
console.log(chalk_1.default.yellow(` Manual action required: ${result.message}`));
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
async function moduleDoctor(options) {
|
|
102
|
-
if (!options.json) {
|
|
103
|
-
console.log(chalk_1.default.blue("Running module doctor...\n"));
|
|
104
|
-
}
|
|
105
|
-
const markerService = new MarkerService_1.MarkerService();
|
|
106
|
-
const manifestParser = new ManifestParser_1.ManifestParser();
|
|
107
|
-
const doctor = new ModuleDoctor_1.ModuleDoctor(process.cwd(), markerService, manifestParser);
|
|
108
|
-
let results = [];
|
|
109
|
-
try {
|
|
110
|
-
results = await doctor.checkAll();
|
|
111
|
-
}
|
|
112
|
-
catch (error) {
|
|
113
|
-
if (options.json) {
|
|
114
|
-
console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error), results: [] }));
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
console.error(chalk_1.default.red(`[ERROR] Heavy failure during doctor audit: ${error instanceof Error ? error.message : String(error)}`));
|
|
118
|
-
}
|
|
119
|
-
process.exit(1);
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
// JSON output mode
|
|
123
|
-
if (options.json) {
|
|
124
|
-
const errors = results.filter((r) => r.severity === "error");
|
|
125
|
-
const warnings = results.filter((r) => r.severity === "warning");
|
|
126
|
-
console.log(JSON.stringify({
|
|
127
|
-
success: errors.length === 0,
|
|
128
|
-
errors: errors.length,
|
|
129
|
-
warnings: warnings.length,
|
|
130
|
-
results,
|
|
131
|
-
}, null, 2));
|
|
132
|
-
process.exit(errors.length > 0 ? 1 : warnings.length > 0 ? 2 : 0);
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
// Human-readable output
|
|
136
|
-
for (const result of results) {
|
|
137
|
-
const prefix = severityPrefix(result.severity);
|
|
138
|
-
console.log(`${prefix} ${result.message}`);
|
|
139
|
-
if (result.file) {
|
|
140
|
-
console.log(chalk_1.default.gray(` file: ${result.file}`));
|
|
141
|
-
}
|
|
142
|
-
if (result.fixable && !options.fix) {
|
|
143
|
-
console.log(chalk_1.default.gray(` (fixable: run with --fix)`));
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
const errors = results.filter((r) => r.severity === "error");
|
|
147
|
-
const warnings = results.filter((r) => r.severity === "warning");
|
|
148
|
-
console.log();
|
|
149
|
-
if (errors.length === 0 && warnings.length === 0) {
|
|
150
|
-
console.log(chalk_1.default.green("[OK] All checks passed! Your project is healthy."));
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
if (errors.length > 0) {
|
|
154
|
-
console.log(chalk_1.default.red(`[ERROR] Found ${errors.length} error(s)`));
|
|
155
|
-
}
|
|
156
|
-
if (warnings.length > 0) {
|
|
157
|
-
console.log(chalk_1.default.yellow(`[WARN] Found ${warnings.length} warning(s)`));
|
|
158
|
-
}
|
|
159
|
-
if (!options.fix) {
|
|
160
|
-
console.log(chalk_1.default.gray("\nTip: Run with --fix to attempt automatic repairs"));
|
|
161
|
-
console.log(chalk_1.default.gray("Try: kaven module doctor --fix"));
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
if (options.fix) {
|
|
165
|
-
console.log();
|
|
166
|
-
console.log(chalk_1.default.blue("Applying auto-fixes...\n"));
|
|
167
|
-
await applyFixes(results, process.cwd());
|
|
168
|
-
console.log(chalk_1.default.green("\nAuto-fix completed."));
|
|
169
|
-
}
|
|
170
|
-
// Exit codes: 0=all pass, 1=errors, 2=warnings only
|
|
171
|
-
if (errors.length > 0)
|
|
172
|
-
process.exit(1);
|
|
173
|
-
if (warnings.length > 0)
|
|
174
|
-
process.exit(2);
|
|
175
|
-
}
|