gitnexus 1.2.0 → 1.2.1
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/cli/index.js +2 -1
- package/dist/cli/wiki.d.ts +1 -0
- package/dist/cli/wiki.js +79 -3
- package/dist/core/wiki/generator.d.ts +1 -0
- package/dist/core/wiki/generator.js +15 -6
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -15,7 +15,7 @@ const program = new Command();
|
|
|
15
15
|
program
|
|
16
16
|
.name('gitnexus')
|
|
17
17
|
.description('GitNexus local CLI and MCP server')
|
|
18
|
-
.version('1.
|
|
18
|
+
.version('1.2.0');
|
|
19
19
|
program
|
|
20
20
|
.command('setup')
|
|
21
21
|
.description('One-time setup: configure MCP for Cursor, Claude Code, OpenCode')
|
|
@@ -56,6 +56,7 @@ program
|
|
|
56
56
|
.option('--model <model>', 'LLM model name (default: gpt-4o-mini)')
|
|
57
57
|
.option('--base-url <url>', 'LLM API base URL (default: OpenAI)')
|
|
58
58
|
.option('--api-key <key>', 'LLM API key (saved to ~/.gitnexus/config.json)')
|
|
59
|
+
.option('--gist', 'Publish wiki as a public GitHub Gist after generation')
|
|
59
60
|
.action(wikiCommand);
|
|
60
61
|
program
|
|
61
62
|
.command('augment <pattern>')
|
package/dist/cli/wiki.d.ts
CHANGED
package/dist/cli/wiki.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import path from 'path';
|
|
8
8
|
import readline from 'readline';
|
|
9
|
+
import { execSync } from 'child_process';
|
|
9
10
|
import cliProgress from 'cli-progress';
|
|
10
11
|
import { getGitRoot, isGitRepo } from '../storage/git.js';
|
|
11
12
|
import { getStoragePaths, loadMeta, loadCLIConfig, saveCLIConfig } from '../storage/repo-manager.js';
|
|
@@ -160,17 +161,19 @@ export const wikiCommand = async (inputPath, options) => {
|
|
|
160
161
|
bar.update(100, { phase: 'Done' });
|
|
161
162
|
bar.stop();
|
|
162
163
|
const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
|
|
164
|
+
const wikiDir = path.join(storagePath, 'wiki');
|
|
165
|
+
const viewerPath = path.join(wikiDir, 'index.html');
|
|
163
166
|
if (result.mode === 'up-to-date' && !options?.force) {
|
|
164
167
|
console.log('\n Wiki is already up to date.');
|
|
165
|
-
console.log(` ${
|
|
168
|
+
console.log(` Viewer: ${viewerPath}\n`);
|
|
169
|
+
await maybePublishGist(viewerPath, options?.gist);
|
|
166
170
|
return;
|
|
167
171
|
}
|
|
168
|
-
const wikiDir = path.join(storagePath, 'wiki');
|
|
169
172
|
console.log(`\n Wiki generated successfully (${elapsed}s)\n`);
|
|
170
173
|
console.log(` Mode: ${result.mode}`);
|
|
171
174
|
console.log(` Pages: ${result.pagesGenerated}`);
|
|
172
175
|
console.log(` Output: ${wikiDir}`);
|
|
173
|
-
console.log(` Viewer: ${
|
|
176
|
+
console.log(` Viewer: ${viewerPath}`);
|
|
174
177
|
if (result.failedModules && result.failedModules.length > 0) {
|
|
175
178
|
console.log(`\n Failed modules (${result.failedModules.length}):`);
|
|
176
179
|
for (const mod of result.failedModules) {
|
|
@@ -179,6 +182,7 @@ export const wikiCommand = async (inputPath, options) => {
|
|
|
179
182
|
console.log(' Re-run to retry failed modules (pages will be regenerated).');
|
|
180
183
|
}
|
|
181
184
|
console.log('');
|
|
185
|
+
await maybePublishGist(viewerPath, options?.gist);
|
|
182
186
|
}
|
|
183
187
|
catch (err) {
|
|
184
188
|
bar.stop();
|
|
@@ -197,3 +201,75 @@ export const wikiCommand = async (inputPath, options) => {
|
|
|
197
201
|
process.exitCode = 1;
|
|
198
202
|
}
|
|
199
203
|
};
|
|
204
|
+
// ─── Gist Publishing ───────────────────────────────────────────────────
|
|
205
|
+
function hasGhCLI() {
|
|
206
|
+
try {
|
|
207
|
+
execSync('gh --version', { stdio: 'ignore' });
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function publishGist(htmlPath) {
|
|
215
|
+
try {
|
|
216
|
+
const output = execSync(`gh gist create "${htmlPath}" --desc "Repository Wiki — generated by GitNexus" --public`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
217
|
+
// gh gist create prints the gist URL as the last line
|
|
218
|
+
const lines = output.split('\n');
|
|
219
|
+
const gistUrl = lines.find(l => l.includes('gist.github.com')) || lines[lines.length - 1];
|
|
220
|
+
if (!gistUrl || !gistUrl.includes('gist.github.com'))
|
|
221
|
+
return null;
|
|
222
|
+
// Build a raw viewer URL via gist.githack.com
|
|
223
|
+
// gist URL format: https://gist.github.com/{user}/{id}
|
|
224
|
+
const match = gistUrl.match(/gist\.github\.com\/([^/]+)\/([a-f0-9]+)/);
|
|
225
|
+
let rawUrl = gistUrl;
|
|
226
|
+
if (match) {
|
|
227
|
+
rawUrl = `https://gistcdn.githack.com/${match[1]}/${match[2]}/raw/index.html`;
|
|
228
|
+
}
|
|
229
|
+
return { url: gistUrl.trim(), rawUrl };
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
async function maybePublishGist(htmlPath, gistFlag) {
|
|
236
|
+
if (gistFlag === false)
|
|
237
|
+
return;
|
|
238
|
+
// Check that the HTML file exists
|
|
239
|
+
try {
|
|
240
|
+
const fs = await import('fs/promises');
|
|
241
|
+
await fs.access(htmlPath);
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (!hasGhCLI()) {
|
|
247
|
+
if (gistFlag) {
|
|
248
|
+
console.log(' GitHub CLI (gh) is not installed. Cannot publish gist.');
|
|
249
|
+
console.log(' Install it: https://cli.github.com\n');
|
|
250
|
+
}
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
let shouldPublish = !!gistFlag;
|
|
254
|
+
if (!shouldPublish && process.stdin.isTTY) {
|
|
255
|
+
const answer = await new Promise((resolve) => {
|
|
256
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
257
|
+
rl.question(' Publish wiki as a GitHub Gist for easy viewing? (Y/n): ', (ans) => {
|
|
258
|
+
rl.close();
|
|
259
|
+
resolve(ans.trim().toLowerCase());
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
shouldPublish = !answer || answer === 'y' || answer === 'yes';
|
|
263
|
+
}
|
|
264
|
+
if (!shouldPublish)
|
|
265
|
+
return;
|
|
266
|
+
console.log('\n Publishing to GitHub Gist...');
|
|
267
|
+
const result = publishGist(htmlPath);
|
|
268
|
+
if (result) {
|
|
269
|
+
console.log(` Gist: ${result.url}`);
|
|
270
|
+
console.log(` Viewer: ${result.rawUrl}\n`);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
console.log(' Failed to publish gist. Make sure `gh auth login` is configured.\n');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
@@ -51,6 +51,8 @@ export class WikiGenerator {
|
|
|
51
51
|
const forceMode = this.options.force;
|
|
52
52
|
// Up-to-date check (skip if --force)
|
|
53
53
|
if (!forceMode && existingMeta && existingMeta.fromCommit === currentCommit) {
|
|
54
|
+
// Still regenerate the HTML viewer in case it's missing
|
|
55
|
+
await this.ensureHTMLViewer();
|
|
54
56
|
return { pagesGenerated: 0, mode: 'up-to-date', failedModules: [] };
|
|
55
57
|
}
|
|
56
58
|
// Force mode: delete snapshot to force full re-grouping
|
|
@@ -85,14 +87,21 @@ export class WikiGenerator {
|
|
|
85
87
|
finally {
|
|
86
88
|
await closeWikiDb();
|
|
87
89
|
}
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
this.onProgress('html', 98, 'Building HTML viewer...');
|
|
91
|
-
const repoName = path.basename(this.repoPath);
|
|
92
|
-
await generateHTMLViewer(this.wikiDir, repoName);
|
|
93
|
-
}
|
|
90
|
+
// Always generate the HTML viewer after wiki content changes
|
|
91
|
+
await this.ensureHTMLViewer();
|
|
94
92
|
return result;
|
|
95
93
|
}
|
|
94
|
+
// ─── HTML Viewer ─────────────────────────────────────────────────────
|
|
95
|
+
async ensureHTMLViewer() {
|
|
96
|
+
// Only generate if there are markdown pages to bundle
|
|
97
|
+
const dirEntries = await fs.readdir(this.wikiDir).catch(() => []);
|
|
98
|
+
const hasMd = dirEntries.some(f => f.endsWith('.md'));
|
|
99
|
+
if (!hasMd)
|
|
100
|
+
return;
|
|
101
|
+
this.onProgress('html', 98, 'Building HTML viewer...');
|
|
102
|
+
const repoName = path.basename(this.repoPath);
|
|
103
|
+
await generateHTMLViewer(this.wikiDir, repoName);
|
|
104
|
+
}
|
|
96
105
|
// ─── Full Generation ────────────────────────────────────────────────
|
|
97
106
|
async fullGeneration(currentCommit) {
|
|
98
107
|
let pagesGenerated = 0;
|
package/package.json
CHANGED