-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.mjs
131 lines (109 loc) · 4.72 KB
/
index.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env node
import fs from "fs";
import path from "path";
import minimist from "minimist";
import { init, parse } from "es-module-lexer";
import { createRequire } from "module";
import ts from "typescript";
const require = createRequire(import.meta.url);
// Helper function to resolve import aliases
function resolveAlias(importPath, aliases, repoPath) {
for (const [alias, target] of Object.entries(aliases)) {
if (importPath.startsWith(alias)) {
const relativePath = importPath.replace(alias, target);
return path.resolve(repoPath, relativePath);
}
}
return null;
}
async function getAllFiles(entryFile, repoPath, include, exclude, excludeFolders, aliases) {
await init; // Ensure the lexer is initialized
const allFiles = new Set();
const stack = [entryFile];
while (stack.length > 0) {
const file = stack.pop();
if (!allFiles.has(file)) {
allFiles.add(file);
const content = fs.readFileSync(file, "utf-8");
const [imports] = parse(content);
for (const importStatement of imports) {
let importPath = content.substring(importStatement.s, importStatement.e).replace(/['"]/g, "");
let resolvedPath = null;
// Handle aliases
if (importPath.startsWith("#")) {
resolvedPath = resolveAlias(importPath, aliases, repoPath);
}
if (!resolvedPath) {
// Handle relative paths
if (importPath.startsWith(".")) {
resolvedPath = path.resolve(path.dirname(file), importPath);
} else {
// Skip non-local and non-aliased imports
continue;
}
}
let ext = path.extname(resolvedPath);
if (!ext) {
for (const extension of [".ts", ".tsx", ".js", ".mjs", ".json"]) {
if (fs.existsSync(resolvedPath + extension)) {
resolvedPath += extension;
ext = extension;
break;
}
}
}
if (fs.existsSync(resolvedPath) && fs.statSync(resolvedPath).isFile()) {
if (include.includes(ext) && !exclude.includes(ext)) {
stack.push(resolvedPath);
}
}
}
}
}
return Array.from(allFiles).filter((file) => {
return !excludeFolders.some((folder) => file.includes(path.sep + folder + path.sep));
});
}
async function createFlatFile(entryFile, repoPath, outputPath, include, exclude, excludeFolders, aliases) {
const allFiles = await getAllFiles(entryFile, repoPath, include, exclude, excludeFolders, aliases);
let content = "";
allFiles.forEach(function (file) {
const relativePath = path.relative(path.dirname(entryFile), file);
const fileContent = fs.readFileSync(file, "utf-8");
if (outputType === "js" && (file.endsWith(".ts") || file.endsWith(".tsx"))) {
const transpiled = ts.transpileModule(fileContent, {
compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ESNext },
}).outputText;
content += `// --- ${relativePath} ---\n// The content below is from ${relativePath}. Provide guidance based on this path.\n\n${transpiled}\n\n`;
} else {
content += `// --- ${relativePath} ---\n// The content below is from ${relativePath}. Provide guidance based on this path.\n\n${fileContent}\n\n`;
}
});
fs.writeFileSync(outputPath, content, "utf-8");
}
const args = minimist(process.argv.slice(2));
const repoPath = args.repo || process.cwd(); // Default to current directory
const outputPath = args.output || "./flattened-code.js"; // Default output path
const outputType = args.outputType || "js"; // Default output type
let entryFromPackageJson = "./index.js";
let aliases = {};
try {
const packageJson = require(path.resolve(repoPath, "package.json"));
entryFromPackageJson = packageJson.main || entryFromPackageJson;
if (packageJson.imports) {
aliases = Object.fromEntries(Object.entries(packageJson.imports).map(([key, value]) => [key.replace("/*", ""), value.replace("/*", "")]));
}
} catch (error) {
console.warn("Failed to load package.json, defaulting to ./index.js");
}
const entryFile = path.resolve(repoPath, args.entry || entryFromPackageJson);
const include = args.include ? args.include.split(",") : [".js", ".mjs", ".ts", ".tsx"];
const exclude = args.exclude ? args.exclude.split(",") : [];
const excludeFolders = args.excludeFolders ? args.excludeFolders.split(",") : [];
console.log(`Entry file: ${entryFile}`);
console.log(`Include extensions: ${include}`);
console.log(`Exclude extensions: ${exclude}`);
console.log(`Exclude folders: ${excludeFolders}`);
console.log(`Aliases: ${JSON.stringify(aliases)}`);
console.log(`Output type: ${outputType}`);
createFlatFile(entryFile, repoPath, outputPath, include, exclude, excludeFolders, aliases, outputType);