usetraceforge-cli 0.1.3 → 0.1.5
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/dist/installers/nextjs.js +73 -43
- package/package.json +5 -4
|
@@ -2,9 +2,10 @@ import fs from "fs";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { spinner } from "@clack/prompts";
|
|
4
4
|
import chalk from "chalk";
|
|
5
|
+
import { Project, SyntaxKind } from "ts-morph";
|
|
5
6
|
export async function installNextJs(apiKey, endpoint) {
|
|
6
7
|
const s = spinner();
|
|
7
|
-
s.start("
|
|
8
|
+
s.start("Agent: Scanning and configuring Next.js...");
|
|
8
9
|
try {
|
|
9
10
|
// 1. Add API key and endpoint to .env.local
|
|
10
11
|
const envPath = path.resolve(process.cwd(), ".env.local");
|
|
@@ -18,34 +19,53 @@ export async function installNextJs(apiKey, endpoint) {
|
|
|
18
19
|
else {
|
|
19
20
|
fs.writeFileSync(envPath, envVar);
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const project = new Project();
|
|
23
|
+
// 2. Next.js Config AST Injection
|
|
24
|
+
const configPaths = [
|
|
25
|
+
path.resolve(process.cwd(), "next.config.ts"),
|
|
26
|
+
path.resolve(process.cwd(), "next.config.mjs"),
|
|
27
|
+
path.resolve(process.cwd(), "next.config.js"),
|
|
28
|
+
];
|
|
29
|
+
let targetConfig = null;
|
|
30
|
+
for (const p of configPaths) {
|
|
31
|
+
if (fs.existsSync(p)) {
|
|
32
|
+
targetConfig = p;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
25
35
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
if (targetConfig) {
|
|
37
|
+
const sourceFile = project.addSourceFileAtPath(targetConfig);
|
|
38
|
+
const text = sourceFile.getFullText();
|
|
39
|
+
if (!text.includes("withTraceForgeConfig")) {
|
|
40
|
+
const isEsm = targetConfig.endsWith(".ts") || targetConfig.endsWith(".mjs") || text.includes("export default");
|
|
41
|
+
if (isEsm) {
|
|
42
|
+
sourceFile.addImportDeclaration({
|
|
43
|
+
namedImports: ["withTraceForgeConfig"],
|
|
44
|
+
moduleSpecifier: "usetraceforge/next-plugin"
|
|
45
|
+
});
|
|
46
|
+
const defaultExport = sourceFile.getExportAssignment(d => !d.isExportEquals());
|
|
47
|
+
if (defaultExport) {
|
|
48
|
+
const expression = defaultExport.getExpression();
|
|
49
|
+
defaultExport.setExpression(`withTraceForgeConfig(${expression.getText()})`);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.log(chalk.yellow("\nAgent: Could not parse export default in next.config. Please wrap your config manually."));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Fallback to simpler regex for CJS files if AST binary expression is too complex
|
|
57
|
+
let configCode = fs.readFileSync(targetConfig, "utf-8");
|
|
58
|
+
configCode = `const { withTraceForgeConfig } = require("usetraceforge/next-plugin");\n` + configCode;
|
|
59
|
+
configCode = configCode.replace(/module\.exports = (.+);/g, `module.exports = withTraceForgeConfig($1);`);
|
|
60
|
+
fs.writeFileSync(targetConfig, configCode);
|
|
61
|
+
}
|
|
62
|
+
sourceFile.saveSync();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.log(chalk.yellow("\nAgent: Could not locate next.config.ts/mjs. Please configure Webpack loader manually."));
|
|
67
|
+
}
|
|
68
|
+
// 3. Layout AST Injection
|
|
49
69
|
const layoutPaths = [
|
|
50
70
|
path.resolve(process.cwd(), "app/layout.tsx"),
|
|
51
71
|
path.resolve(process.cwd(), "src/app/layout.tsx"),
|
|
@@ -57,25 +77,35 @@ export function TraceForgeProvider({ children }: { children: React.ReactNode })
|
|
|
57
77
|
break;
|
|
58
78
|
}
|
|
59
79
|
}
|
|
60
|
-
if (
|
|
61
|
-
|
|
62
|
-
|
|
80
|
+
if (targetLayout) {
|
|
81
|
+
const sourceFile = project.addSourceFileAtPath(targetLayout);
|
|
82
|
+
if (!sourceFile.getFullText().includes("TraceForgeProvider")) {
|
|
83
|
+
sourceFile.addImportDeclaration({
|
|
84
|
+
namedImports: ["TraceForgeProvider"],
|
|
85
|
+
moduleSpecifier: "usetraceforge/react"
|
|
86
|
+
});
|
|
87
|
+
// Find body tag
|
|
88
|
+
const jsxElements = sourceFile.getDescendantsOfKind(SyntaxKind.JsxElement);
|
|
89
|
+
let bodyTag = jsxElements.find(el => el.getOpeningElement().getTagNameNode().getText() === "body");
|
|
90
|
+
if (bodyTag) {
|
|
91
|
+
const childrenText = bodyTag.getJsxChildren().map(c => c.getText()).join("");
|
|
92
|
+
const opening = bodyTag.getOpeningElement().getText();
|
|
93
|
+
const closing = bodyTag.getClosingElement().getText();
|
|
94
|
+
bodyTag.replaceWithText(`${opening}\n <TraceForgeProvider>\n ${childrenText}\n </TraceForgeProvider>\n ${closing}`);
|
|
95
|
+
sourceFile.saveSync();
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
console.log(chalk.yellow("\nAgent: Could not find <body> tag in layout.tsx. Please add <TraceForgeProvider> manually."));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
63
101
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (layoutCode.includes("TraceForgeProvider")) {
|
|
67
|
-
s.stop(chalk.green("TraceForge is already configured in layout.tsx!"));
|
|
68
|
-
return;
|
|
102
|
+
else {
|
|
103
|
+
console.log(chalk.yellow("\nAgent: Could not find layout.tsx. Please add <TraceForgeProvider> manually."));
|
|
69
104
|
}
|
|
70
|
-
|
|
71
|
-
layoutCode = importStatement + layoutCode;
|
|
72
|
-
layoutCode = layoutCode.replace(/(<body[^>]*>)/g, `$1\n <TraceForgeProvider>`);
|
|
73
|
-
layoutCode = layoutCode.replace(/<\/body>/g, ` </TraceForgeProvider>\n </body>`);
|
|
74
|
-
fs.writeFileSync(targetLayout, layoutCode);
|
|
75
|
-
s.stop(chalk.green("Next.js configuration complete!"));
|
|
105
|
+
s.stop(chalk.green("Agent: Next.js configuration complete!"));
|
|
76
106
|
}
|
|
77
107
|
catch (error) {
|
|
78
|
-
s.stop(chalk.red("
|
|
108
|
+
s.stop(chalk.red("Agent: An error occurred while parsing files. Please configure manually."));
|
|
79
109
|
console.error(error);
|
|
80
110
|
}
|
|
81
111
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "usetraceforge-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "TraceForge CLI Wizard for 2-click installations",
|
|
5
5
|
"bin": {
|
|
6
6
|
"traceforge": "./dist/index.js"
|
|
@@ -18,11 +18,12 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@clack/prompts": "^0.7.0",
|
|
20
20
|
"chalk": "^5.3.0",
|
|
21
|
-
"execa": "^9.3.0"
|
|
21
|
+
"execa": "^9.3.0",
|
|
22
|
+
"ts-morph": "^28.0.0"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@types/node": "^20.0.0",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
26
|
+
"tsx": "^4.16.2",
|
|
27
|
+
"typescript": "^5.5.4"
|
|
27
28
|
}
|
|
28
29
|
}
|