@invect/cli 0.0.1
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/LICENSE +21 -0
- package/dist/api.js +42 -0
- package/dist/chunk-DGBTXQND.js +109 -0
- package/dist/chunk-K4RRNATQ.js +458 -0
- package/dist/chunk-Q6JKV7VX.js +157 -0
- package/dist/chunk-T4KEEHFJ.js +569 -0
- package/dist/generate-JDAYY3OL.js +10 -0
- package/dist/index.js +581 -0
- package/dist/migrate-JMKLRLSJ.js +9 -0
- package/package.json +67 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// src/utils/config-loader.ts
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import pc from "picocolors";
|
|
5
|
+
var CONFIG_FILENAMES = [
|
|
6
|
+
"invect.config.ts",
|
|
7
|
+
"invect.config.js",
|
|
8
|
+
"invect.config.mjs"
|
|
9
|
+
];
|
|
10
|
+
var CONFIG_DIRECTORIES = [".", "src", "lib", "config", "utils"];
|
|
11
|
+
function findConfigPath(explicitPath) {
|
|
12
|
+
if (explicitPath) {
|
|
13
|
+
const resolved = path.resolve(process.cwd(), explicitPath);
|
|
14
|
+
if (fs.existsSync(resolved)) {
|
|
15
|
+
return resolved;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
for (const dir of CONFIG_DIRECTORIES) {
|
|
20
|
+
for (const filename of CONFIG_FILENAMES) {
|
|
21
|
+
const candidate = path.resolve(process.cwd(), dir, filename);
|
|
22
|
+
if (fs.existsSync(candidate)) {
|
|
23
|
+
return candidate;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
function stripJsonComments(jsonString) {
|
|
30
|
+
return jsonString.replace(
|
|
31
|
+
/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g,
|
|
32
|
+
(m, g) => g ? "" : m
|
|
33
|
+
).replace(/,(?=\s*[}\]])/g, "");
|
|
34
|
+
}
|
|
35
|
+
function getPathAliases(cwd) {
|
|
36
|
+
let tsConfigPath = path.join(cwd, "tsconfig.json");
|
|
37
|
+
if (!fs.existsSync(tsConfigPath)) {
|
|
38
|
+
tsConfigPath = path.join(cwd, "jsconfig.json");
|
|
39
|
+
}
|
|
40
|
+
if (!fs.existsSync(tsConfigPath)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const result = getPathAliasesRecursive(tsConfigPath, /* @__PURE__ */ new Set());
|
|
45
|
+
return Object.keys(result).length > 0 ? result : null;
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function getPathAliasesRecursive(configPath, visited) {
|
|
51
|
+
const resolvedPath = path.resolve(configPath);
|
|
52
|
+
if (visited.has(resolvedPath)) return {};
|
|
53
|
+
visited.add(resolvedPath);
|
|
54
|
+
if (!fs.existsSync(resolvedPath)) return {};
|
|
55
|
+
let tsConfig;
|
|
56
|
+
try {
|
|
57
|
+
const text = fs.readFileSync(resolvedPath, "utf-8");
|
|
58
|
+
tsConfig = JSON.parse(stripJsonComments(text));
|
|
59
|
+
} catch {
|
|
60
|
+
return {};
|
|
61
|
+
}
|
|
62
|
+
const result = {};
|
|
63
|
+
const compilerOptions = tsConfig.compilerOptions;
|
|
64
|
+
const paths = compilerOptions?.paths;
|
|
65
|
+
const baseUrl = compilerOptions?.baseUrl;
|
|
66
|
+
const configDir = path.dirname(resolvedPath);
|
|
67
|
+
if (paths) {
|
|
68
|
+
for (const [alias, targets] of Object.entries(paths)) {
|
|
69
|
+
if (typeof alias === "string" && alias.endsWith("/*") && Array.isArray(targets) && targets.length > 0) {
|
|
70
|
+
const aliasPrefix = alias.slice(0, -2);
|
|
71
|
+
const targetDir = targets[0].replace(/\/\*$/, "");
|
|
72
|
+
const resolvedTarget = baseUrl ? path.resolve(configDir, baseUrl, targetDir) : path.resolve(configDir, targetDir);
|
|
73
|
+
result[aliasPrefix] = resolvedTarget;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const references = tsConfig.references;
|
|
78
|
+
if (references) {
|
|
79
|
+
for (const ref of references) {
|
|
80
|
+
const refPath = path.resolve(configDir, ref.path);
|
|
81
|
+
const refConfigPath = refPath.endsWith(".json") ? refPath : path.join(refPath, "tsconfig.json");
|
|
82
|
+
const refAliases = getPathAliasesRecursive(refConfigPath, visited);
|
|
83
|
+
Object.assign(result, refAliases);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
async function loadConfig(configPath) {
|
|
89
|
+
const aliases = getPathAliases(process.cwd()) || {};
|
|
90
|
+
const { createJiti } = await import("jiti");
|
|
91
|
+
const jiti = createJiti(import.meta.url, {
|
|
92
|
+
interopDefault: true,
|
|
93
|
+
// Pass resolved path aliases so @/ imports work
|
|
94
|
+
alias: aliases
|
|
95
|
+
});
|
|
96
|
+
let configModule;
|
|
97
|
+
try {
|
|
98
|
+
configModule = await jiti.import(configPath);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
+
if (message.includes("Cannot find module") || message.includes("Cannot resolve")) {
|
|
102
|
+
console.error(pc.red("\n\u2717 Failed to load config file."));
|
|
103
|
+
console.error(pc.dim(" If your config uses import aliases (e.g., @/ or ~/),"));
|
|
104
|
+
console.error(pc.dim(" try using relative paths instead, then run the CLI again."));
|
|
105
|
+
console.error(pc.dim(`
|
|
106
|
+
Error: ${message}
|
|
107
|
+
`));
|
|
108
|
+
}
|
|
109
|
+
throw new Error(`Failed to load config from ${configPath}: ${message}`);
|
|
110
|
+
}
|
|
111
|
+
const raw = resolveConfigExport(configModule);
|
|
112
|
+
if (!raw || typeof raw !== "object") {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`Config file at ${configPath} does not export a valid Invect config object.
|
|
115
|
+
Expected: export default { baseDatabaseConfig: ..., plugins: [...] }`
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
const config = raw;
|
|
119
|
+
const plugins = Array.isArray(config.plugins) ? config.plugins : [];
|
|
120
|
+
for (let i = 0; i < plugins.length; i++) {
|
|
121
|
+
const plugin = plugins[i];
|
|
122
|
+
if (!plugin || typeof plugin !== "object" || !("id" in plugin)) {
|
|
123
|
+
console.warn(
|
|
124
|
+
pc.yellow(`\u26A0 Plugin at index ${i} does not have an 'id' property \u2014 skipping`)
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const validPlugins = plugins.filter(
|
|
129
|
+
(p) => p !== null && typeof p === "object" && "id" in p
|
|
130
|
+
);
|
|
131
|
+
return {
|
|
132
|
+
plugins: validPlugins,
|
|
133
|
+
baseDatabaseConfig: config.baseDatabaseConfig,
|
|
134
|
+
raw: config,
|
|
135
|
+
configPath
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function resolveConfigExport(module) {
|
|
139
|
+
if (!module || typeof module !== "object") return module;
|
|
140
|
+
const mod = module;
|
|
141
|
+
if ("default" in mod) {
|
|
142
|
+
const def = mod.default;
|
|
143
|
+
if (def && typeof def === "object" && "default" in def) {
|
|
144
|
+
return def.default;
|
|
145
|
+
}
|
|
146
|
+
return def;
|
|
147
|
+
}
|
|
148
|
+
if ("config" in mod) return mod.config;
|
|
149
|
+
if ("invectConfig" in mod) return mod.invectConfig;
|
|
150
|
+
if ("baseDatabaseConfig" in mod || "plugins" in mod) return mod;
|
|
151
|
+
return mod;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export {
|
|
155
|
+
findConfigPath,
|
|
156
|
+
loadConfig
|
|
157
|
+
};
|