diff --git a/cli/.gitignore b/cli/.gitignore new file mode 100644 index 0000000..8b86740 --- /dev/null +++ b/cli/.gitignore @@ -0,0 +1,2 @@ +dist/ +cli \ No newline at end of file diff --git a/cli/go.mod b/cli/go.mod new file mode 100644 index 0000000..153a194 --- /dev/null +++ b/cli/go.mod @@ -0,0 +1,3 @@ +module cli + +go 1.26.1 diff --git a/cli/main.go b/cli/main.go new file mode 100644 index 0000000..1c537cc --- /dev/null +++ b/cli/main.go @@ -0,0 +1,53 @@ +package main + +import ( + "embed" + b64 "encoding/base64" + "fmt" + "io/fs" + "log" + "math/rand" + "net/http" + "os" + "strconv" + + _ "embed" +) + +//go:embed all:dist +var website embed.FS + +func main() { + + fileOrStringArgs := os.Args[1:] + if len(fileOrStringArgs) != 1 { + log.Fatal("To many Arguments Provided") + } + + fileOrString := fileOrStringArgs[0] + var base64 string + if _, err := os.Stat(fileOrString); err == nil { + + data, err := os.ReadFile(fileOrString) + if err != nil { + fmt.Println("Failed to read File", err) + } + + base64 = b64.StdEncoding.EncodeToString(data) + + } else { + + base64 = b64.StdEncoding.EncodeToString([]byte(fileOrString)) + } + public, err := fs.Sub(website, "dist") + if err != nil { + log.Fatal(err) + } + + fs := http.FileServerFS(public) + http.Handle("/", fs) + + port := 10000 + rand.Intn(55000) + fmt.Printf("Stats available at http://localhost:%d/?file=%s\n", port, base64) + log.Fatal(http.ListenAndServe(":"+strconv.Itoa(port), nil)) +} diff --git a/docs/README.md b/docs/README.md index df40f19..ee775e0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -66,6 +66,12 @@ analysis you may compare two _named_ analyses at a time. > UI bugs or areas where UI polish is very clearly missing. Please crate an > issue if the generated graph or the site UI looks off. Thanks :) +### CLI + +1. Create the JSON export or display the text in terminal and pass it into the cli + +Kongratz it creates a Temp server with a link to ur benchmark visualization + #### Snapshots Snapshots are an "experimental" (just means they're new and unpolished) feature @@ -90,6 +96,9 @@ $ pnpm run dev # Build a static site $ pnpm run build + +# Build the cli +$ pnpm run build:cli ``` If submitting pull requests, please ensure that format (`pnpm run fmt`) and lint diff --git a/package.json b/package.json index ccf0918..5fa3081 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "fmt": "prettier --write .", "build": "pnpm -r --filter '!@ns/web' build && pnpm -F @ns/web build", "build:web": "pnpm -r --filter '!@ns/web' build && pnpm -F @ns/web build", + "build:cli": "pnpm run build && cp -r packages/web/dist cli/dist && go build -o cli/cli cli/main.go", "preview": "pnpm -F @ns/web preview" }, "devDependencies": { diff --git a/packages/tui/README.md b/packages/tui/README.md deleted file mode 100644 index 1916c2a..0000000 --- a/packages/tui/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# @ns/tui - -Provides a terminal-based interface for viewing and analyzing Nix evaluator -statistics. diff --git a/packages/tui/package.json b/packages/tui/package.json deleted file mode 100644 index 382354a..0000000 --- a/packages/tui/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "@ns/tui", - "version": "1.0.0", - "type": "module", - "bin": { - "ns-tui": "./dist/cli.js" - }, - "scripts": { - "build": "tsc", - "check": "tsc --noEmit", - "dev": "node --loader ts-node/esm src/cli.ts" - }, - "dependencies": { - "@ns/core": "workspace:*" - }, - "devDependencies": { - "@types/node": "^25.5.2", - "typescript": "^6.0.2" - } -} diff --git a/packages/tui/src/cli.ts b/packages/tui/src/cli.ts deleted file mode 100644 index 828c129..0000000 --- a/packages/tui/src/cli.ts +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env node - -import { readFile } from 'fs/promises'; -import { parseStats } from '@ns/core'; - -async function main() { - const args = process.argv.slice(2); - - // FIXME: nuke all of this actually - if (args.length === 0) { - console.log('NS'); - console.log('\nUsage: ns-tui '); - process.exit(1); - } - - const filePath = args[0]; - - try { - const content = await readFile(filePath, 'utf-8'); - const raw = JSON.parse(content); - const stats = parseStats(raw); - - console.log('\n=== Nix Evaluator Statistics ===\n'); - console.log(`CPU Time: ${stats.cpuTime.toFixed(3)}s`); - console.log(`Expressions: ${stats.nrExprs.toLocaleString()}`); - console.log(`Thunks: ${stats.nrThunks.toLocaleString()}`); - console.log(` - Avoided: ${stats.nrAvoided.toLocaleString()}`); - console.log(` - Ratio: ${((stats.nrAvoided / stats.nrThunks) * 100).toFixed(2)}%`); - - const totalMemory = - stats.envs.bytes + - stats.list.bytes + - stats.values.bytes + - stats.symbols.bytes + - stats.sets.bytes; - console.log(`Total Memory: ${(totalMemory / 1024 / 1024).toFixed(2)} MB`); - - console.log('\n=== Memory Breakdown ===\n'); - console.log(`Environments: ${(stats.envs.bytes / 1024 / 1024).toFixed(2)} MB`); - console.log(`Lists: ${(stats.list.bytes / 1024 / 1024).toFixed(2)} MB`); - console.log(`Values: ${(stats.values.bytes / 1024 / 1024).toFixed(2)} MB`); - console.log(`Symbols: ${(stats.symbols.bytes / 1024 / 1024).toFixed(2)} MB`); - console.log(`Sets: ${(stats.sets.bytes / 1024 / 1024).toFixed(2)} MB`); - - if (stats.gc) { - console.log('\n=== Garbage Collection ===\n'); - console.log(`Heap Size: ${(stats.gc.heapSize / 1024 / 1024).toFixed(2)} MB`); - console.log(`Total Alloc: ${(stats.gc.totalBytes / 1024 / 1024).toFixed(2)} MB`); - console.log(`GC Cycles: ${stats.gc.cycles.toLocaleString()}`); - } - - console.log('\n' + '='.repeat(40)); - console.log('='.repeat(40) + '\n'); - } catch (error) { - console.error('Error:', error instanceof Error ? error.message : String(error)); - process.exit(1); - } -} - -main(); diff --git a/packages/tui/tsconfig.json b/packages/tui/tsconfig.json deleted file mode 100644 index 4a61882..0000000 --- a/packages/tui/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "types": ["node"], - "moduleResolution": "bundler", - "outDir": "./dist", - "rootDir": "./src", - "declaration": true, - "declarationMap": true, - "sourceMap": true, - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true - }, - "include": ["src/**/*"] -} diff --git a/packages/web/src/index.tsx b/packages/web/src/index.tsx index 578bb8a..f7059be 100644 --- a/packages/web/src/index.tsx +++ b/packages/web/src/index.tsx @@ -38,6 +38,13 @@ function App() { // Load from localStorage on mount onMount(() => { + const query = window.location.search; + const urlParams = new URLSearchParams(query); + + const file = urlParams.get('file'); + if (file) { + loadFromText(atob(file)); + } try { const saved = localStorage.getItem(STORAGE_KEY); if (saved) { diff --git a/shell.nix b/shell.nix index 99b2c08..c71dafc 100644 --- a/shell.nix +++ b/shell.nix @@ -3,5 +3,6 @@ pkgs.mkShell { packages = [ pkgs.nodejs-slim pkgs.pnpm + pkgs.go ]; }