usetraceforge-cli 0.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.
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ import { intro, outro, text, select, spinner } from "@clack/prompts";
3
+ import chalk from "chalk";
4
+ import { execa } from "execa";
5
+ import { installNextJs } from "./installers/nextjs.js";
6
+ async function main() {
7
+ console.log();
8
+ intro(chalk.bgBlue.white.bold(" TraceForge Wizard "));
9
+ const apiKey = await text({
10
+ message: "What is your TraceForge API Key?",
11
+ placeholder: "tf_...",
12
+ validate(value) {
13
+ if (value.length === 0)
14
+ return "API Key is required";
15
+ },
16
+ });
17
+ if (typeof apiKey !== "string") {
18
+ outro(chalk.red("Installation cancelled."));
19
+ process.exit(1);
20
+ }
21
+ const framework = await select({
22
+ message: "Which framework are you using?",
23
+ options: [
24
+ { value: "nextjs", label: "Next.js (React)" },
25
+ { value: "express", label: "Express (Node.js)" },
26
+ ],
27
+ });
28
+ if (typeof framework !== "string") {
29
+ outro(chalk.red("Installation cancelled."));
30
+ process.exit(1);
31
+ }
32
+ const s = spinner();
33
+ s.start("Installing usetraceforge SDK...");
34
+ try {
35
+ await execa("npm", ["install", "usetraceforge@latest"]);
36
+ s.stop(chalk.green("SDK installed successfully."));
37
+ }
38
+ catch (error) {
39
+ s.stop(chalk.red("Failed to install SDK. Please run 'npm install usetraceforge' manually."));
40
+ }
41
+ if (framework === "nextjs") {
42
+ await installNextJs(apiKey);
43
+ }
44
+ else if (framework === "express") {
45
+ // await installExpress(apiKey);
46
+ console.log(chalk.yellow("Express auto-installation coming soon."));
47
+ }
48
+ outro(chalk.green("✨ You're all set! TraceForge is now protecting your application."));
49
+ }
50
+ main().catch((err) => {
51
+ console.error(err);
52
+ process.exit(1);
53
+ });
@@ -0,0 +1,60 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { spinner } from "@clack/prompts";
4
+ import chalk from "chalk";
5
+ export async function installNextJs(apiKey) {
6
+ const s = spinner();
7
+ s.start("Configuring Next.js...");
8
+ try {
9
+ // 1. Add API key to .env.local
10
+ const envPath = path.resolve(process.cwd(), ".env.local");
11
+ const envVar = `\nNEXT_PUBLIC_TRACEFORGE_API_KEY="${apiKey}"\n`;
12
+ if (fs.existsSync(envPath)) {
13
+ const content = fs.readFileSync(envPath, "utf-8");
14
+ if (!content.includes("NEXT_PUBLIC_TRACEFORGE_API_KEY")) {
15
+ fs.appendFileSync(envPath, envVar);
16
+ }
17
+ }
18
+ else {
19
+ fs.writeFileSync(envPath, envVar);
20
+ }
21
+ // 2. Find layout.tsx
22
+ const layoutPaths = [
23
+ path.resolve(process.cwd(), "app/layout.tsx"),
24
+ path.resolve(process.cwd(), "src/app/layout.tsx"),
25
+ path.resolve(process.cwd(), "app/layout.jsx"),
26
+ path.resolve(process.cwd(), "src/app/layout.jsx"),
27
+ ];
28
+ let targetLayout = null;
29
+ for (const p of layoutPaths) {
30
+ if (fs.existsSync(p)) {
31
+ targetLayout = p;
32
+ break;
33
+ }
34
+ }
35
+ if (!targetLayout) {
36
+ s.stop(chalk.yellow("Could not find app/layout.tsx. Please configure TraceForge manually."));
37
+ return;
38
+ }
39
+ // 3. Inject code into layout.tsx
40
+ let layoutCode = fs.readFileSync(targetLayout, "utf-8");
41
+ // Check if already injected
42
+ if (layoutCode.includes("TraceForgeErrorBoundary")) {
43
+ s.stop(chalk.green("TraceForge is already configured in layout.tsx!"));
44
+ return;
45
+ }
46
+ // Add import statement
47
+ const importStatement = `import { TraceForgeErrorBoundary } from "usetraceforge/react";\n`;
48
+ layoutCode = importStatement + layoutCode;
49
+ // Replace <body> with <body><TraceForgeErrorBoundary>
50
+ layoutCode = layoutCode.replace(/(<body[^>]*>)/g, `$1\n <TraceForgeErrorBoundary>`);
51
+ // Replace </body> with </TraceForgeErrorBoundary></body>
52
+ layoutCode = layoutCode.replace(/<\/body>/g, ` </TraceForgeErrorBoundary>\n </body>`);
53
+ fs.writeFileSync(targetLayout, layoutCode);
54
+ s.stop(chalk.green("Next.js configuration complete!"));
55
+ }
56
+ catch (error) {
57
+ s.stop(chalk.red("Failed to configure Next.js automatically."));
58
+ console.error(error);
59
+ }
60
+ }
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "usetraceforge-cli",
3
+ "version": "0.1.0",
4
+ "description": "TraceForge CLI Wizard for 2-click installations",
5
+ "bin": {
6
+ "traceforge": "./dist/index.js"
7
+ },
8
+ "type": "module",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "npx tsc -p tsconfig.json",
14
+ "dev": "tsx src/index.ts",
15
+ "prepack": "npm run build",
16
+ "publish:public": "npm publish --access public"
17
+ },
18
+ "dependencies": {
19
+ "@clack/prompts": "^0.7.0",
20
+ "chalk": "^5.3.0",
21
+ "execa": "^9.3.0"
22
+ },
23
+ "devDependencies": {
24
+ "@types/node": "^20.0.0",
25
+ "typescript": "^5.5.4",
26
+ "tsx": "^4.16.2"
27
+ }
28
+ }