legacyver 2.1.7 → 2.1.8

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/README.md CHANGED
@@ -1,199 +1,96 @@
1
- # Legacyver
1
+ # 🚀 Legacyver
2
2
 
3
- Auto-generate technical documentation for legacy and undocumented codebases using AST parsing + LLMs.
4
-
5
- ```bash
6
- npx legacyver analyze ./src
7
- ```
8
-
9
- No documentation written beforehand. No configuration required. One command.
3
+ **AI-powered CLI tool** untuk generate dokumentasi teknis secara otomatis dari codebase yang sudah ada (legacy) atau tidak memiliki dokumentasi. Menggunakan parsing AST yang mendalam dikombinasikan dengan LLM (Groq, Gemini, Ollama, dll.) untuk menjelaskan struktur, logika, dan pola kode kamu.
10
4
 
11
5
  ---
12
6
 
13
- ## Install
7
+ ## ⚡ Panduan Cepat (Step-by-Step)
14
8
 
9
+ Ikuti urutan ini untuk membuat dokumentasi kamu siap dalam hitungan menit:
10
+
11
+ ### 1. Instalasi
12
+ Instal package secara global melalui npm:
15
13
  ```bash
16
14
  npm install -g legacyver
17
15
  ```
16
+ *Atau gunakan `npx legacyver` jika kamu tidak ingin menginstalnya secara global.*
18
17
 
19
- Or use without installing:
20
-
18
+ ### 2. Login (Cloud Sync)
19
+ Masuk ke akun Legacyver kamu untuk mengaktifkan sinkronisasi cloud dan menyimpan dokumentasi di dashboard:
21
20
  ```bash
22
- npx legacyver analyze ./src
21
+ legacyver login
23
22
  ```
24
23
 
25
- ---
26
-
27
- ## Quick Start
28
-
29
- **1. Initialize (saves your API key):**
30
-
24
+ ### 3. Inisialisasi Konfigurasi
25
+ Jalankan wizard setup untuk menyimpan API key (Groq, Gemini, dll.) dan membuat file konfigurasi `.legacyverrc`:
31
26
  ```bash
32
27
  legacyver init
33
28
  ```
34
29
 
35
- **2. Analyze a codebase:**
36
-
30
+ ### 4. Analisis & Generate
31
+ Jalankan perintah utama untuk menganalisis folder project kamu:
37
32
  ```bash
38
- legacyver analyze ./src
39
- ```
40
-
41
- **3. View the output:**
42
-
43
- ```
44
- legacyver-docs/
45
- index.md ← project overview + dependency graph + route map (Laravel)
46
- SUMMARY.md ← GitBook/Docusaurus compatible table of contents
47
- src/
48
- app.md
49
- routes/users.md
50
- ...
33
+ legacyver analyze ./src --incremental
51
34
  ```
35
+ *Flag `--incremental` memastikan hanya file yang dimodifikasi yang akan diproses ulang di jalankan berikutnya (lebih cepat & hemat).*
52
36
 
53
37
  ---
54
38
 
55
- ## CLI Commands
39
+ ## 🛠️ Daftar Perintah (CLI Commands)
56
40
 
57
- ### `legacyver analyze <dir>`
41
+ ### `legacyver analyze [target]`
42
+ Perintah utama untuk memindai codebase dan membuat dokumentasi.
58
43
 
59
- Run the full documentation pipeline.
60
-
61
- | Flag | Default | Description |
62
- |------|---------|-------------|
63
- | `--out <dir>` | `./legacyver-docs` | Output directory |
64
- | `--format <fmt>` | `markdown` | Output format: `markdown`, `html`, `json` |
65
- | `--provider <p>` | `openrouter` | LLM provider: `openrouter`, `ollama` |
66
- | `--model <id>` | `meta-llama/llama-3.3-70b-instruct:free` | Model ID |
67
- | `--incremental` | `false` | Skip files unchanged since last run |
68
- | `--dry-run` | `false` | Estimate cost without calling LLM |
69
- | `--concurrency <n>` | `3` | Max parallel LLM requests |
70
- | `--max-file-size <kb>` | `500` | Skip files larger than this |
71
- | `--no-confirm` | — | Skip cost confirmation prompt |
72
- | `--verbose` | `false` | Enable debug logging |
44
+ | Flag | Default | Deskripsi |
45
+ |------|---------|-----------|
46
+ | `--out <dir>` | `./legacyver-docs` | Folder output hasil dokumentasi |
47
+ | `--format <fmt>` | `markdown` | Format output: `markdown`, `html`, `json` |
48
+ | `--provider <p>` | `groq` | Provider AI: `groq`, `gemini`, `ollama`, `openrouter` |
49
+ | `--incremental` | `false` | Hanya proses file yang berubah (lebih cepat) |
50
+ | `--dry-run` | `false` | Estimasi penggunaan token tanpa memanggil AI |
51
+ | `--no-confirm` | | Lewati konfirmasi estimasi biaya |
73
52
 
74
53
  ### `legacyver init`
75
-
76
- Interactive wizard. Detects existing `.legacyverrc` and warns before overwriting. Saves API key to OS user config.
54
+ Wizard interaktif untuk setup API key dan preferensi lokal.
77
55
 
78
56
  ### `legacyver providers`
57
+ Cek status API key dan daftar model AI yang tersedia.
79
58
 
80
- List all supported providers, API key status, and per-model pricing.
59
+ ### `legacyver login / logout`
60
+ Kelola sesi untuk sinkronisasi dokumentasi ke cloud.
81
61
 
82
- ### `legacyver cache clear`
62
+ ---
83
63
 
84
- Delete the `.legacyver-cache/` directory to force full re-analysis on next run.
64
+ ## 🏗️ Dukungan Framework & Bahasa
85
65
 
86
- ### `legacyver --version`
66
+ | Kategori | Item yang Didukung |
67
+ |----------|--------------------|
68
+ | **Bahasa** | JavaScript, TypeScript, PHP, Python, Java, Go |
69
+ | **Framework** | **Laravel** (Deteksi Otomatis Routes, Models, ERD), **Express** |
70
+ | **Integrasi** | GitHub Actions, GitBook, Docusaurus |
87
71
 
88
- Print the installed version.
72
+ ### 🐘 Integrasi Mendalam Laravel
73
+ Jika file `artisan` terdeteksi, Legacyver otomatis mengekstrak:
74
+ - **Route Maps**: Daftar lengkap method, URI, dan Controller.
75
+ - **ER Diagrams**: Membuat diagram Mermaid otomatis untuk Model kamu.
76
+ - **Service Providers**: Mendokumentasikan binding dependency yang kompleks.
89
77
 
90
78
  ---
91
79
 
92
- ## `.legacyverrc` Schema
93
-
94
- Create a `.legacyverrc` (JSON or YAML) in your project root:
80
+ ## ⚙️ Konfigurasi (`.legacyverrc`)
81
+ Sesuaikan alur kerja kamu dengan file konfigurasi:
95
82
 
96
83
  ```json
97
84
  {
98
- "provider": "openrouter",
99
- "model": "meta-llama/llama-3.3-70b-instruct:free",
85
+ "provider": "gemini",
86
+ "model": "gemini-1.5-flash",
100
87
  "format": "markdown",
101
- "out": "./legacyver-docs",
102
- "concurrency": 3,
103
- "maxFileSizeKb": 500,
104
- "incremental": true
88
+ "incremental": true,
89
+ "out": "./legacyver-docs"
105
90
  }
106
91
  ```
107
92
 
108
- All fields are optional. CLI flags override file config.
109
-
110
- Also supported: `legacyver.config.js`, `legacyver.config.yaml`.
111
-
112
- ---
113
-
114
- ## Supported Languages
115
-
116
- | Language | Extensions | Framework Support |
117
- |----------|-----------|-------------------|
118
- | JavaScript | `.js`, `.jsx`, `.mjs` | Express (auto-detected) |
119
- | TypeScript | `.ts`, `.tsx` | — |
120
- | Python | `.py` | — |
121
- | Java | `.java` | — |
122
- | Go | `.go` | — |
123
- | PHP | `.php`, `.blade.php` | Laravel (auto-detected) |
124
-
125
- **Laravel extras:** When an `artisan` file is detected, Legacyver automatically extracts:
126
- - Route Map (Method, URI, Controller, Middleware, Route Name)
127
- - Model Relationships (as Mermaid `erDiagram`)
128
- - Service Provider Bindings
129
-
130
93
  ---
131
94
 
132
- ## Supported LLM Providers
133
-
134
- | Provider | Env Var | Notes |
135
- |----------|---------|-------|
136
- | OpenRouter | `OPENROUTER_API_KEY` | Default. Free models available (`:free` suffix). Get a key at [openrouter.ai/keys](https://openrouter.ai/keys) |
137
- | Ollama | — | Local/offline. Requires Ollama running: `ollama serve` |
138
-
139
- **Free usage:** The default model `meta-llama/llama-3.3-70b-instruct:free` is free via OpenRouter (rate-limited). Legacyver automatically caps concurrency to 1 for free models.
140
-
141
- ---
142
-
143
- ## Ignore Files
144
-
145
- Create a `.legacyverignore` in your project root using gitignore syntax:
146
-
147
- ```
148
- # .legacyverignore
149
- dist/
150
- build/
151
- coverage/
152
- *.min.js
153
- ```
154
-
155
- See `.legacyverignore.example` for a documented example.
156
-
157
- ---
158
-
159
- ## CI/CD Integration
160
-
161
- ```yaml
162
- # GitHub Actions example
163
- - name: Generate docs
164
- env:
165
- OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
166
- run: |
167
- npx legacyver analyze ./src --no-confirm --incremental --out ./docs
168
- ```
169
-
170
- Legacyver detects non-TTY environments and disables spinners/progress bars automatically (plain log output only).
171
-
172
- ---
173
-
174
- ## How It Works
175
-
176
- 1. **Crawl** — `fast-glob` walks the directory, respects `.legacyverignore`
177
- 2. **Parse** — Regex/heuristic AST extracts facts: function names, params, complexity scores, imports, exports, call patterns
178
- 3. **PKG** — Assembles a Project Knowledge Graph linking all facts
179
- 4. **LLM** — Sends grounded facts + raw source to LLM; system prompt enforces anti-hallucination contract
180
- 5. **Validate** — Post-generation checks: hallucination detection, completeness check (all exports documented)
181
- 6. **Render** — Writes Markdown/HTML/JSON to output directory
182
-
183
- **Design principle:** The LLM is a _writer_, not an analyst. AST extracts facts; LLM only explains them.
184
-
185
- ---
186
-
187
- ## Contributing
188
-
189
- ```bash
190
- git clone https://github.com/user/legacyver
191
- npm install
192
- npx vitest run
193
- ```
194
-
195
- ---
196
-
197
- ## License
198
-
199
- MIT
95
+ ## 📄 Lisensi
96
+ MIT License. Dibuat dengan ❤️ untuk developer yang berjuang melawan legacy code.
package/bin/legacyver.js CHANGED
@@ -69,4 +69,12 @@ program
69
69
  .description('Log out and stop syncing docs to the cloud')
70
70
  .action(logoutCmd);
71
71
 
72
+ // push command
73
+ const pushCmd = require('../src/cli/commands/push');
74
+ program
75
+ .command('push [target]')
76
+ .description('Manually push generated docs to the cloud database')
77
+ .option('--out <dir>', 'Docs output directory to read from', './legacyver-docs')
78
+ .action(pushCmd);
79
+
72
80
  program.parse(process.argv);
@@ -1,51 +1,50 @@
1
1
  ## Overview
2
- The components.tsx file contains a collection of reusable React components and a utility function for formatting currency.
2
+ This file contains React components and a utility function for formatting currency. The components include a Button and a UserCard.
3
3
 
4
4
  ## Functions
5
5
  ### Button
6
- The Button function is a React component that renders a button element with a specified label, click handler, and variant.
6
+ The Button component is a React functional component that renders a button element.
7
7
  #### Parameters
8
- | Name | Type | Description |
8
+ | Parameter | Type | Description |
9
9
  | --- | --- | --- |
10
- | label | string | The text displayed on the button |
11
- | onClick | () => void | The function called when the button is clicked |
12
- | disabled | boolean | Whether the button is disabled (optional, default: false) |
13
- | variant | 'primary' | 'secondary' | 'danger' | The style variant of the button (optional, default: 'primary') |
10
+ | label | string | The text to display on the button |
11
+ | onClick | () => void | The function to call when the button is clicked |
12
+ | disabled | boolean | Optional, whether the button is disabled |
13
+ | variant | 'primary' | 'secondary' | 'danger' | Optional, the style variant of the button |
14
14
  #### Return Value
15
- A React button element
15
+ The Button component returns a JSX button element.
16
16
 
17
17
  ### UserCard
18
- The UserCard function is a React component that fetches and displays user data based on a provided user ID.
18
+ The UserCard component is a React functional component that fetches user data and displays it in a card.
19
19
  #### Parameters
20
- | Name | Type | Description |
20
+ | Parameter | Type | Description |
21
21
  | --- | --- | --- |
22
- | userId | number | The ID of the user to fetch and display |
23
- | onClose | () => void | The function called when the close button is clicked |
22
+ | userId | number | The ID of the user to fetch |
23
+ | onClose | () => void | The function to call when the close button is clicked |
24
24
  #### Return Value
25
- A React element containing the user's name, email, and a close button, or a loading indicator if the data is not yet available
25
+ The UserCard component returns a JSX div element containing the user's data or a loading/error message.
26
26
 
27
27
  ### formatCurrency
28
- The formatCurrency function formats a given amount as a currency string.
28
+ The formatCurrency function formats a number as a currency string.
29
29
  #### Parameters
30
- | Name | Type | Description |
30
+ | Parameter | Type | Description |
31
31
  | --- | --- | --- |
32
32
  | amount | number | The amount to format |
33
- | currency | string | The currency to use for formatting (optional, default: 'USD') |
33
+ | currency | string | Optional, the currency to use (default: 'USD') |
34
34
  #### Return Value
35
- A string representing the formatted amount
35
+ The formatCurrency function returns a string representing the formatted currency amount.
36
36
 
37
37
  ## Dependencies
38
38
  * React
39
- * useState
40
- * useEffect
39
+ * Intl.NumberFormat
41
40
 
42
41
  ## Usage Example
43
- No clear usage example is visible in the provided code, but the components can be used as follows:
42
+ No clear usage example is visible in the provided code. However, components can be used as follows:
44
43
  ```jsx
45
44
  import { Button, UserCard, formatCurrency } from './components';
46
45
 
47
46
  const App = () => {
48
- const handleButtonClick = () => {
47
+ const handleButtonClicked = () => {
49
48
  console.log('Button clicked');
50
49
  };
51
50
 
@@ -55,9 +54,9 @@ const App = () => {
55
54
 
56
55
  return (
57
56
  <div>
58
- <Button label="Click me" onClick={handleButtonClick} />
59
- <UserCard userId={123} onClose={handleUserCardClose} />
60
- <p>Formatted amount: {formatCurrency(12345.67)}</p>
57
+ <Button label="Click me" onClick={handleButtonClicked} />
58
+ <UserCard userId={1} onClose={handleUserCardClose} />
59
+ <p>Formatted currency: {formatCurrency(1000)}</p>
61
60
  </div>
62
61
  );
63
62
  };
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Primary language:** typescript
4
4
  **Total files:** 1
5
- **Analyzed at:** 2026-02-21T18:11:04.560Z
5
+ **Analyzed at:** 2026-02-22T03:13:37.724Z
6
6
 
7
7
  ## Files
8
8
 
package/nul ADDED
@@ -0,0 +1 @@
1
+ /usr/bin/bash: line 1: type: %USERPROFILE%\.legacyver\session.json: not found
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "legacyver",
3
- "version": "2.1.7",
3
+ "version": "2.1.8",
4
4
  "description": "AI-powered CLI tool to auto-generate technical documentation from legacy/undocumented codebases",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -0,0 +1,99 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+ const pc = require('picocolors');
6
+ const { loadSession } = require('../../utils/config');
7
+ const logger = require('../../utils/logger');
8
+
9
+ /**
10
+ * legacyver push [target]
11
+ *
12
+ * Manually push existing generated docs to the cloud database.
13
+ * Reads markdown files from the output directory (default: ./legacyver-docs)
14
+ * and pushes them as documentation pages.
15
+ *
16
+ * Useful when:
17
+ * - analyze ran but DB was down at that time
18
+ * - you want to re-push after fixing DB issues
19
+ * - you generated docs on a machine without login and want to push from another
20
+ */
21
+ module.exports = async function pushCommand(target, options) {
22
+ const session = loadSession();
23
+ if (!session.token) {
24
+ console.log(pc.red('\n Not logged in. Run ') + pc.cyan('legacyver login') + pc.red(' first.\n'));
25
+ process.exitCode = 1;
26
+ return;
27
+ }
28
+
29
+ const targetDir = path.resolve(target || '.');
30
+ const outDir = path.resolve(options.out || './legacyver-docs');
31
+
32
+ // Check if output directory exists
33
+ if (!fs.existsSync(outDir)) {
34
+ console.log(pc.red(`\n Output directory not found: ${outDir}`));
35
+ console.log(pc.dim(' Run ') + pc.cyan('legacyver analyze') + pc.dim(' first to generate docs.\n'));
36
+ process.exitCode = 1;
37
+ return;
38
+ }
39
+
40
+ // Collect all .md files from the output directory
41
+ const fragments = [];
42
+ collectMarkdownFiles(outDir, outDir, fragments);
43
+
44
+ if (fragments.length === 0) {
45
+ console.log(pc.yellow('\n No markdown files found in ') + pc.cyan(outDir));
46
+ console.log(pc.dim(' Run ') + pc.cyan('legacyver analyze') + pc.dim(' first to generate docs.\n'));
47
+ return;
48
+ }
49
+
50
+ console.log(pc.bold('\nLegacyver Push\n'));
51
+ console.log(pc.dim(` Source: ${targetDir}`));
52
+ console.log(pc.dim(` Docs: ${outDir}`));
53
+ console.log(pc.dim(` Files: ${fragments.length} markdown files\n`));
54
+
55
+ // Dynamically require ora for spinner
56
+ let spinner;
57
+ try {
58
+ const ora = require('ora');
59
+ spinner = ora('Pushing docs to cloud...').start();
60
+ } catch {
61
+ console.log(' Pushing docs to cloud...');
62
+ spinner = { succeed: (m) => console.log(pc.green(' ' + m)), fail: (m) => console.log(pc.red(' ' + m)) };
63
+ }
64
+
65
+ try {
66
+ const { pushToDatabase } = require('../../db/index');
67
+ const result = await pushToDatabase(fragments, targetDir);
68
+
69
+ if (result.skipped) {
70
+ spinner.fail('Push skipped — token may be invalid or expired. Try logging in again.');
71
+ process.exitCode = 1;
72
+ } else {
73
+ spinner.succeed(`Pushed ${result.pushed} files to cloud`);
74
+ console.log(pc.dim('\n Docs are now visible on the web dashboard.\n'));
75
+ }
76
+ } catch (err) {
77
+ spinner.fail('Push failed: ' + err.message);
78
+ logger.error('Push error details:', err);
79
+ process.exitCode = 1;
80
+ }
81
+ };
82
+
83
+ /**
84
+ * Recursively collect .md files from a directory.
85
+ * Each file becomes a fragment with { relativePath, content }.
86
+ */
87
+ function collectMarkdownFiles(baseDir, dir, results) {
88
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
89
+ for (const entry of entries) {
90
+ const fullPath = path.join(dir, entry.name);
91
+ if (entry.isDirectory()) {
92
+ collectMarkdownFiles(baseDir, fullPath, results);
93
+ } else if (entry.isFile() && entry.name.endsWith('.md')) {
94
+ const relativePath = path.relative(baseDir, fullPath);
95
+ const content = fs.readFileSync(fullPath, 'utf8');
96
+ results.push({ relativePath, content });
97
+ }
98
+ }
99
+ }