@chappibunny/repolens 1.12.2 → 1.13.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/CHANGELOG.md +100 -0
- package/README.md +25 -36
- package/bin/repolens.js +21 -1
- package/package.json +20 -11
- package/src/ai/provider.js +1 -2
- package/src/analyzers/monorepo-detector.js +8 -20
- package/src/cli-args.js +60 -0
- package/src/cli.js +80 -100
- package/src/core/config-schema.js +47 -1
- package/src/core/config.js +5 -2
- package/src/core/diff.js +43 -20
- package/src/core/scan.js +24 -4
- package/src/delivery/comment.js +5 -2
- package/src/docs/write-doc-set.js +9 -7
- package/src/doctor.js +16 -3
- package/src/help.js +54 -0
- package/src/index.js +13 -0
- package/src/init.js +99 -62
- package/src/integrations/discord.js +16 -2
- package/src/migrate.js +2 -2
- package/src/publishers/confluence.js +17 -3
- package/src/publishers/github-wiki.js +61 -32
- package/src/publishers/index.js +24 -9
- package/src/publishers/markdown.js +3 -2
- package/src/publishers/notion.js +10 -4
- package/src/publishers/obsidian.js +716 -0
- package/src/utils/branch.js +37 -42
- package/src/utils/github-repo.js +8 -0
- package/src/utils/interactive.js +20 -0
- package/src/utils/logger.js +5 -1
- package/src/utils/retry.js +30 -6
- package/src/utils/safe-path.js +50 -0
- package/src/utils/secrets.js +3 -1
- package/src/utils/telemetry.js +34 -6
- package/src/utils/update-check.js +23 -6
- package/src/utils/validate.js +70 -1
- package/src/utils/yaml.js +27 -0
- package/src/watch.js +1 -1
- package/docs/AI.md +0 -329
- package/docs/ARCHITECTURE.md +0 -145
- package/docs/CONFIGURATION.md +0 -121
- package/docs/DEVELOPMENT.md +0 -79
- package/docs/ENVIRONMENT.md +0 -79
- package/docs/INSTALLATION.md +0 -45
- package/docs/KNOWN_ISSUES.md +0 -309
- package/docs/MIGRATION.md +0 -311
- package/docs/ONBOARDING.md +0 -382
- package/docs/PRODUCTION_CHECKLIST.md +0 -470
- package/docs/RELEASE.md +0 -76
- package/docs/ROADMAP.md +0 -151
- package/docs/STABILITY.md +0 -265
- package/docs/TELEMETRY.md +0 -166
- package/docs/TROUBLESHOOTING.md +0 -377
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,106 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to RepoLens will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 1.13.0
|
|
6
|
+
|
|
7
|
+
### Obsidian vault publisher
|
|
8
|
+
|
|
9
|
+
Publish generated docs into a folder in a local Obsidian vault. No network calls and no credentials.
|
|
10
|
+
|
|
11
|
+
- New publisher: `obsidian` (`src/publishers/obsidian.js`)
|
|
12
|
+
- Notes get YAML frontmatter (`title`, `aliases`, `tags`, `type`, `project`, `branch`) and an index note (`RepoLens.md`) with wikilinks
|
|
13
|
+
- Markdown links to generated pages become `[[wikilinks]]`. External URLs and fenced code blocks are left alone
|
|
14
|
+
- Re-running publish is idempotent: identical notes are not rewritten, and notes RepoLens previously published but no longer generates are removed. Other files in the folder stay
|
|
15
|
+
- `obsidian.folder` must resolve inside `obsidian.vault`. Absolute folders, `..`, and symlinks that leave the vault are rejected
|
|
16
|
+
- Optional config on schema v1: `obsidian.vault`, `obsidian.folder`, `obsidian.branches`, `obsidian.index`, `obsidian.frontmatter`, `obsidian.wikilinks`. Existing configs keep working
|
|
17
|
+
- `repolens init` can select the Obsidian publisher and ask for a vault path
|
|
18
|
+
- `repolens doctor` checks that `obsidian.vault` is set and does not require env vars for it
|
|
19
|
+
- Wikilink rewriting is a linear scan with bounded label and target lengths. The previous link regex was polynomial on hostile markdown (CodeQL)
|
|
20
|
+
|
|
21
|
+
### Security
|
|
22
|
+
|
|
23
|
+
- `repolens init` workflows grant `contents: read` and `pull-requests: write`. Architecture Diff comments use the Issues comments API on the pull request, which accepts `pull-requests: write`. `contents: write` is not granted. GitHub Wiki pushes still need `contents: write` on that job only
|
|
24
|
+
|
|
25
|
+
### Docs
|
|
26
|
+
|
|
27
|
+
- `docs/ROADMAP.md` now summarizes what shipped from v1.1.0 through v1.12.4, and marks the VS Code extension and the Obsidian publisher as shipped
|
|
28
|
+
- README roadmap matches `docs/ROADMAP.md`
|
|
29
|
+
- The README no longer hard-codes the release version. It points at `package.json`, which is the source of the version
|
|
30
|
+
- Test totals are no longer hard-coded in the README, development guide, or security guide. The tests badge follows the `test.yml` workflow status
|
|
31
|
+
- Handbook pages (README, `docs/*`, `SECURITY.md`, `CONTRIBUTING.md`, and `.github/copilot-instructions.md`) describe 1.13.0 and the Obsidian publisher
|
|
32
|
+
- Corrected drift against the code: `scan.ignore` (there is no `scan.exclude`), `publish` has no `--dry-run`, CI installs with `npm ci`, the publish workflow is `repolens.yml`, diagrams are Unicode, and local files use two filename schemes. `outputs.pages` stays the frozen allowlist; the generator still emits the full 17-document plan unless `documentation.sections` or `features` filters it
|
|
33
|
+
|
|
34
|
+
## 1.12.4
|
|
35
|
+
|
|
36
|
+
### Security
|
|
37
|
+
|
|
38
|
+
- GitHub Wiki git commands use an argument array. The token is passed with `http.extraheader` and is no longer written into the clone URL or `origin` remote
|
|
39
|
+
- Wiki page names and generated document names cannot leave their output directory
|
|
40
|
+
- `documentation.output_dir` must stay inside the repository. Absolute paths and `..` are rejected
|
|
41
|
+
- Scan results that resolve outside the repository root are dropped, and absolute `scan.include` patterns are rejected
|
|
42
|
+
- Monorepo workspace globs that point outside the repository are ignored
|
|
43
|
+
- YAML configs are size-capped and alias-capped before `js-yaml` parses them. The js-yaml 4 schema is unchanged
|
|
44
|
+
- Notion, Confluence, GitHub, and Discord error bodies are truncated and redacted before they are logged
|
|
45
|
+
- Confluence URLs with embedded credentials, or a scheme other than http/https, are rejected
|
|
46
|
+
- Discord webhooks must be `https` and time out after 15 seconds
|
|
47
|
+
- AI startup logs no longer print a prefix of the API key
|
|
48
|
+
- Secret detection covers fine-grained GitHub tokens (`github_pat_`), `gho_` / `ghu_` / `ghr_` tokens, and npm tokens
|
|
49
|
+
- `Retry-After` values that are not seconds or an HTTP date no longer become `NaN` delays
|
|
50
|
+
- Browser signup links are opened without a shell
|
|
51
|
+
- GitHub Actions: test and security jobs are `contents: read`. `id-token: write` is only on the npm publish job. The token-present check no longer prints the token length
|
|
52
|
+
- Test workflow runs on Node.js 18, 20, and 22. Node 18 runs `scripts/node18-runtime.js` because Vitest 4 cannot start there (`util.styleText` needs Node 20.12). Node 20 and 22 run the full Vitest suite
|
|
53
|
+
|
|
54
|
+
### Fixes
|
|
55
|
+
|
|
56
|
+
- Update checks query `@chappibunny/repolens` on the npm registry. The cache file uses the real home directory on Windows and Unix
|
|
57
|
+
- `repolens init` in CI, tests, and non-TTY sessions scaffolds files instead of exiting before writing anything
|
|
58
|
+
- `repolens demo --target` looks for `.repolens.yml` from the target directory, so a demo of another folder does not scan the shell's current repository
|
|
59
|
+
- `repolens feedback` exits 2 when there is no terminal, and exits 1 when sending fails
|
|
60
|
+
- Unknown flags and missing `--config` / `--target` values exit 2. `--help` and `--version` work before or after the command
|
|
61
|
+
- `repolens --version` and `repolens --help` from the installed binary do not load the scanner or telemetry
|
|
62
|
+
- Empty repositories finish the scan with a warning instead of looking like a hung run. Binary files and files over 1 MB are not parsed as source
|
|
63
|
+
- Git renames in `git diff --name-status` record the new path. Unsafe diff refs are ignored instead of being interpolated into a shell command. A missing repo or ref no longer prints git's usage text, and the diff runs in the scanned repository rather than whatever directory the shell happened to be in
|
|
64
|
+
- Branch filters escape regex metacharacters, so a pattern like `release/*)` does not throw
|
|
65
|
+
- Confluence page-cache filenames cannot contain path separators from the branch name
|
|
66
|
+
- Notion block pagination stops if a cursor repeats
|
|
67
|
+
|
|
68
|
+
### Dependencies
|
|
69
|
+
|
|
70
|
+
- `dotenv` 18.0.8 (`import "dotenv/config"` is unchanged; Node `-r dotenv/config` preload was removed upstream)
|
|
71
|
+
- `tinyexec` 1.3.1 (dev dependency, Node 18+)
|
|
72
|
+
- js-yaml stays on 4.x, Vitest stays on 4.x, and `@sentry/node` stays on 10.x so `engines` can remain `>=18`
|
|
73
|
+
|
|
74
|
+
## 1.12.3
|
|
75
|
+
|
|
76
|
+
### Security
|
|
77
|
+
|
|
78
|
+
- Bump runtime `js-yaml` to 4.3.2 (merge-key CPU limit and `!!omap` duplicate-key complexity fixes)
|
|
79
|
+
- Bump transitive `source-map-js` to 1.2.2 (CVE-2026-93749)
|
|
80
|
+
- Bump transitive `postcss` to 8.5.31 (Dependabot #8 requested 8.5.25; 8.5.31 includes those fixes)
|
|
81
|
+
- Bump `vitest` and `@vitest/mocker` to 4.1.12 (Dependabot #10 requested 4.1.11; 4.1.12 is the current 4.1 release and includes that fix)
|
|
82
|
+
- No patched `braces` release exists for GHSA-vfj7-8cjw-p6xm (latest is 3.0.3, which the advisory covers). The release audit now checks production dependencies only and waives that one advisory. Any other high or critical runtime finding still fails the job. See `scripts/audit-waivers.json` and `SECURITY.md`.
|
|
83
|
+
|
|
84
|
+
### Packaging
|
|
85
|
+
|
|
86
|
+
- Require Node.js `>=18` (`engines`), matching built-in `fetch` and `node:readline/promises`
|
|
87
|
+
- Add an `exports` map. `main` now points at `src/index.js`, so importing the package does not run the CLI
|
|
88
|
+
- Keep the `repolens` binary on `bin/repolens.js`
|
|
89
|
+
- Replace `node-fetch` with the built-in `fetch` (`AbortSignal.timeout` for the update check)
|
|
90
|
+
- Move `@sentry/node` to `optionalDependencies`. Telemetry and feedback no-op when it is not installed
|
|
91
|
+
- Stop publishing the `docs/` handbook. Runtime document generation stays in `src/docs/`
|
|
92
|
+
|
|
93
|
+
### CI
|
|
94
|
+
|
|
95
|
+
- Publish Documentation runs on pushes to `main` and manual dispatch, and skips `dependabot[bot]`, because publisher secrets are not available on Dependabot branches
|
|
96
|
+
- Add a Test workflow that runs `npm test` on pull requests and branch pushes
|
|
97
|
+
- CI installs with `npm ci` so the committed lockfile is what runs. A fresh `npm install` on npm 10 crashes while resolving Vitest 4.1 optional peers
|
|
98
|
+
- Release workflow publishes with `npm publish --provenance` (requires an `NPM_TOKEN` Actions secret)
|
|
99
|
+
|
|
100
|
+
### Fixes
|
|
101
|
+
|
|
102
|
+
- `docs:publish` discovers `.repolens.yml` from the current directory instead of `../../.repolens.yml`
|
|
103
|
+
- `release:check` runs `npm pack --dry-run`
|
|
104
|
+
|
|
5
105
|
## 1.12.0
|
|
6
106
|
|
|
7
107
|
### 🛡️ Security Pattern Detection
|
package/README.md
CHANGED
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
|
|
11
11
|
[](https://www.npmjs.com/package/@chappibunny/repolens)
|
|
12
12
|
[](https://marketplace.visualstudio.com/items?itemName=CHAPIBUNNY.repolens-architecture)
|
|
13
|
-
[](https://github.com/CHAPIBUNNY/repolens/actions/workflows/test.yml)
|
|
14
14
|
[](LICENSE)
|
|
15
15
|
|
|
16
16
|
**Your architecture docs are already outdated.** RepoLens fixes that.
|
|
17
17
|
|
|
18
|
-
RepoLens scans your repository, generates living architecture documentation, and publishes it to Notion, Confluence, GitHub Wiki, or Markdown — automatically on every push. Engineers get technical docs. Stakeholders get readable system overviews. Nobody writes a word.
|
|
18
|
+
RepoLens scans your repository, generates living architecture documentation, and publishes it to Notion, Confluence, GitHub Wiki, Obsidian, or Markdown — automatically on every push. Engineers get technical docs. Stakeholders get readable system overviews. Nobody writes a word.
|
|
19
19
|
|
|
20
|
-
> Stable as of v1.0 — [API guarantees](docs/STABILITY.md) · [Security hardened](SECURITY.md) ·
|
|
20
|
+
> Stable as of v1.0 — [API guarantees](docs/STABILITY.md) · [Security hardened](SECURITY.md) · version from [`package.json`](package.json)
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -50,7 +50,7 @@ Plus framework detection: **Django** · **FastAPI** · **Flask** · **Gin** · *
|
|
|
50
50
|
|
|
51
51
|
## 🚀 Quick Start (60 seconds)
|
|
52
52
|
|
|
53
|
-
**Step 1: Install**
|
|
53
|
+
**Step 1: Install** (Node.js 18+)
|
|
54
54
|
```bash
|
|
55
55
|
npm install @chappibunny/repolens
|
|
56
56
|
```
|
|
@@ -83,7 +83,7 @@ CONFLUENCE_SPACE_KEY=DOCS
|
|
|
83
83
|
npx @chappibunny/repolens publish
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
**Done!**
|
|
86
|
+
**Done!** Numbered notes and the Markdown publisher’s files are in `.repolens/`. Notion, Confluence, GitHub Wiki, and Obsidian publish only when you configure them. Obsidian needs `obsidian.vault` in `.repolens.yml` and does not use an API key.
|
|
87
87
|
|
|
88
88
|
**🔄 Upgrading from v0.3.0 or earlier?**
|
|
89
89
|
Run `npx @chappibunny/repolens migrate` to automatically update your workflow files. See [MIGRATION.md](docs/MIGRATION.md) for details.
|
|
@@ -96,9 +96,9 @@ Run `npx @chappibunny/repolens migrate` to automatically update your workflow fi
|
|
|
96
96
|
|
|
97
97
|
| Audience | Documents |
|
|
98
98
|
|---|---|
|
|
99
|
-
| **Stakeholders**
|
|
100
|
-
| **
|
|
101
|
-
| **Engineers** | Architecture Overview · Module Catalog · API Surface ·
|
|
99
|
+
| **Stakeholders** | Executive Summary |
|
|
100
|
+
| **Mixed** | System Overview · Business Domains · Route Map · Data Flows · Change Impact · System Map · Architecture Drift · Code Health |
|
|
101
|
+
| **Engineers** | Architecture Overview · Module Catalog · API Surface · Developer Onboarding · GraphQL Schema · TypeScript Type Graph · Dependency Graph · Security Hotspots |
|
|
102
102
|
|
|
103
103
|
**Two modes:** Deterministic (free, fast, always works) or AI-Enhanced (optional — GitHub Models, OpenAI, Anthropic, Google, Azure, Ollama).
|
|
104
104
|
|
|
@@ -110,7 +110,7 @@ Run `npx @chappibunny/repolens migrate` to automatically update your workflow fi
|
|
|
110
110
|
|---|---|
|
|
111
111
|
| 🤖 **Autonomous** | Runs on every push via GitHub Actions — docs stay evergreen |
|
|
112
112
|
| 👥 **Multi-Audience** | Technical docs + stakeholder-readable overviews from one scan |
|
|
113
|
-
| 📤 **Multi-Publisher** | Notion, Confluence, GitHub Wiki, Markdown — or
|
|
113
|
+
| 📤 **Multi-Publisher** | Notion, Confluence, GitHub Wiki, Obsidian, Markdown — together or one at a time |
|
|
114
114
|
| 🧠 **AI-Assisted** | Optional AI with zero-hallucination policy (structured context only) |
|
|
115
115
|
| 🔍 **Smart Detection** | Frameworks, domains, data flows, dependencies, drift — all automatic |
|
|
116
116
|
| 🔌 **Extensible** | Plugin system for custom renderers, publishers, and hooks |
|
|
@@ -155,7 +155,7 @@ The extension reads your `.repolens.yml` configuration and provides an interacti
|
|
|
155
155
|
|
|
156
156
|
## 🎓 Onboarding Guide
|
|
157
157
|
|
|
158
|
-
Step-by-step setup for publishers, AI features, Notion, Confluence, GitHub Wiki, Discord, and CI/CD automation.
|
|
158
|
+
Step-by-step setup for publishers, AI features, Notion, Confluence, GitHub Wiki, Obsidian, Discord, and CI/CD automation.
|
|
159
159
|
|
|
160
160
|
**[→ Full Onboarding Guide](docs/ONBOARDING.md)**
|
|
161
161
|
|
|
@@ -183,28 +183,11 @@ Step-by-step setup for publishers, AI features, Notion, Confluence, GitHub Wiki,
|
|
|
183
183
|
|
|
184
184
|
## 📸 Example Output
|
|
185
185
|
|
|
186
|
-
### System
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
Publishers[src/publishers<br/>6 files] --> Core
|
|
192
|
-
Publishers --> Renderers[src/renderers<br/>4 files]
|
|
193
|
-
Publishers --> Utils[src/utils<br/>10 files]
|
|
194
|
-
Renderers --> Core
|
|
195
|
-
Delivery[src/delivery<br/>1 file] --> Publishers
|
|
196
|
-
Tests[tests<br/>15 files] -. tests .-> CLI
|
|
197
|
-
Tests -. tests .-> Core
|
|
198
|
-
Tests -. tests .-> Publishers
|
|
199
|
-
|
|
200
|
-
style CLI fill:#9b59b6,color:#fff
|
|
201
|
-
style Core fill:#f39c12,color:#000
|
|
202
|
-
style Publishers fill:#27ae60,color:#fff
|
|
203
|
-
style Renderers fill:#27ae60,color:#fff
|
|
204
|
-
style Delivery fill:#16a085,color:#fff
|
|
205
|
-
style Utils fill:#95a5a6,color:#000
|
|
206
|
-
style Tests fill:#e67e22,color:#fff
|
|
207
|
-
```
|
|
186
|
+
### System map
|
|
187
|
+
|
|
188
|
+
Published system maps are Unicode diagrams drawn from import edges. RepoLens does not emit Mermaid.
|
|
189
|
+
|
|
190
|
+
The publisher set in 1.13.0 is Notion, Confluence, GitHub Wiki, Obsidian, and Markdown (`src/publishers`, 7 files). Layout and counts are in [ARCHITECTURE.md](docs/ARCHITECTURE.md).
|
|
208
191
|
|
|
209
192
|
### System Overview (Technical Profile)
|
|
210
193
|
|
|
@@ -255,11 +238,11 @@ When you open a pull request, RepoLens posts:
|
|
|
255
238
|
|
|
256
239
|
| Guide | Description |
|
|
257
240
|
|---|---|
|
|
258
|
-
| [Onboarding Guide](docs/ONBOARDING.md) | Step-by-step setup: publishers, AI, Notion, Confluence, Discord |
|
|
241
|
+
| [Onboarding Guide](docs/ONBOARDING.md) | Step-by-step setup: publishers, AI, Notion, Confluence, GitHub Wiki, Obsidian, Discord |
|
|
259
242
|
| [Configuration](docs/CONFIGURATION.md) | Complete `.repolens.yml` schema and examples |
|
|
260
243
|
| [Environment Variables](docs/ENVIRONMENT.md) | All env vars by publisher and feature |
|
|
261
244
|
| [Architecture](docs/ARCHITECTURE.md) | Pipeline diagram, project structure |
|
|
262
|
-
| [Development](docs/DEVELOPMENT.md) | Setup, tests
|
|
245
|
+
| [Development](docs/DEVELOPMENT.md) | Setup, tests, and the release process |
|
|
263
246
|
| [Security](SECURITY.md) | Threat model, secret detection, validation layers |
|
|
264
247
|
| [Telemetry](docs/TELEMETRY.md) | Opt-in privacy-first usage analytics |
|
|
265
248
|
| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common issues and fixes |
|
|
@@ -285,10 +268,16 @@ v1.0+ features complete — CLI, config schema, and plugin interface are frozen.
|
|
|
285
268
|
|
|
286
269
|
**Completed:**
|
|
287
270
|
- [x] VS Code extension ([available on Marketplace](https://marketplace.visualstudio.com/items?itemName=CHAPIBUNNY.repolens-architecture))
|
|
271
|
+
- [x] Obsidian vault publisher (local notes with wikilinks and frontmatter)
|
|
288
272
|
|
|
289
273
|
**Next:**
|
|
290
|
-
- [ ]
|
|
291
|
-
- [ ]
|
|
274
|
+
- [ ] GitHub App for automated setup and status checks
|
|
275
|
+
- [ ] Slack notifications
|
|
276
|
+
- [ ] Custom webhook support
|
|
277
|
+
- [ ] Cross-repository architecture analysis
|
|
278
|
+
- [ ] Security boundary validation
|
|
279
|
+
- [ ] Interactive HTML documentation output
|
|
280
|
+
- [ ] Architecture decision records (ADR) generation
|
|
292
281
|
|
|
293
282
|
See [ROADMAP.md](docs/ROADMAP.md) for detailed planning.
|
|
294
283
|
|
package/bin/repolens.js
CHANGED
|
@@ -1,2 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
|
|
4
|
+
const argv = process.argv.slice(2);
|
|
5
|
+
const wantsHelp = argv.includes("--help") || argv.includes("-h") || argv[0] === "help";
|
|
6
|
+
const wantsVersion = argv.includes("--version") || argv.includes("-v") || argv[0] === "version";
|
|
7
|
+
|
|
8
|
+
// --version and --help must not load the scanner, publishers, or telemetry.
|
|
9
|
+
if (wantsVersion && !wantsHelp) {
|
|
10
|
+
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
11
|
+
console.log(pkg.version || "0.0.0");
|
|
12
|
+
process.exit(0);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (wantsHelp) {
|
|
16
|
+
const { printHelp } = await import("../src/help.js");
|
|
17
|
+
printHelp();
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { runCli } = await import("../src/cli.js");
|
|
22
|
+
runCli();
|
package/package.json
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chappibunny/repolens",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "AI-assisted documentation intelligence system for technical and non-technical audiences",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18"
|
|
9
|
+
},
|
|
10
|
+
"main": "./src/index.js",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./src/index.js",
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
8
15
|
"bin": {
|
|
9
16
|
"repolens": "bin/repolens.js"
|
|
10
17
|
},
|
|
11
18
|
"files": [
|
|
12
19
|
"bin",
|
|
13
20
|
"src",
|
|
14
|
-
"docs",
|
|
15
21
|
"package.json",
|
|
16
22
|
"README.md",
|
|
17
23
|
"CHANGELOG.md"
|
|
@@ -30,6 +36,7 @@
|
|
|
30
36
|
"metrics",
|
|
31
37
|
"team-collaboration",
|
|
32
38
|
"discord",
|
|
39
|
+
"obsidian",
|
|
33
40
|
"ai-documentation"
|
|
34
41
|
],
|
|
35
42
|
"repository": {
|
|
@@ -47,26 +54,28 @@
|
|
|
47
54
|
},
|
|
48
55
|
"scripts": {
|
|
49
56
|
"test:notion": "node notion-test.js",
|
|
50
|
-
"docs:publish": "node
|
|
57
|
+
"docs:publish": "node bin/repolens.js publish",
|
|
51
58
|
"init:test": "node src/cli.js init --target /tmp/repolens-init-test",
|
|
52
59
|
"test": "NODE_ENV=test vitest run --no-watch --reporter=verbose",
|
|
53
60
|
"pack:check": "npm pack",
|
|
54
|
-
"
|
|
61
|
+
"audit:runtime": "node scripts/audit-runtime.js",
|
|
62
|
+
"release:check": "npm test && npm run audit:runtime && npm pack --dry-run",
|
|
55
63
|
"test:install": "./test-install.sh",
|
|
56
64
|
"release:patch": "npm version patch",
|
|
57
65
|
"release:minor": "npm version minor",
|
|
58
66
|
"release:major": "npm version major"
|
|
59
67
|
},
|
|
60
68
|
"dependencies": {
|
|
61
|
-
"
|
|
62
|
-
"dotenv": "^17.3.1",
|
|
69
|
+
"dotenv": "^18.0.8",
|
|
63
70
|
"fast-glob": "^3.3.3",
|
|
64
|
-
"js-yaml": "^4.
|
|
65
|
-
|
|
71
|
+
"js-yaml": "^4.3.2"
|
|
72
|
+
},
|
|
73
|
+
"optionalDependencies": {
|
|
74
|
+
"@sentry/node": "^10.42.0"
|
|
66
75
|
},
|
|
67
76
|
"devDependencies": {
|
|
68
|
-
"tinyexec": "1.
|
|
69
|
-
"vitest": "^4.1.
|
|
77
|
+
"tinyexec": "^1.3.1",
|
|
78
|
+
"vitest": "^4.1.11"
|
|
70
79
|
},
|
|
71
80
|
"overrides": {
|
|
72
81
|
"yauzl": ">=3.2.1",
|
package/src/ai/provider.js
CHANGED
|
@@ -83,8 +83,7 @@ export async function generateText({ system, user, temperature, maxTokens, confi
|
|
|
83
83
|
|
|
84
84
|
// Log configuration once per run
|
|
85
85
|
if (!hasLoggedConfig) {
|
|
86
|
-
|
|
87
|
-
info(`AI Config: provider=${provider}, model=${model}, key=${keyPreview}`);
|
|
86
|
+
info(`AI Config: provider=${provider}, model=${model}, key=set`);
|
|
88
87
|
hasLoggedConfig = true;
|
|
89
88
|
}
|
|
90
89
|
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import fs from "node:fs/promises";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { info } from "../utils/logger.js";
|
|
7
|
+
import { isInsideRoot } from "../utils/safe-path.js";
|
|
8
|
+
import { loadYaml } from "../utils/yaml.js";
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Detect monorepo workspaces in a repository.
|
|
@@ -68,24 +70,8 @@ async function detectPnpmWorkspaces(repoRoot) {
|
|
|
68
70
|
try {
|
|
69
71
|
const yamlPath = path.join(repoRoot, "pnpm-workspace.yaml");
|
|
70
72
|
const raw = await fs.readFile(yamlPath, "utf8");
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const patterns = [];
|
|
74
|
-
let inPackages = false;
|
|
75
|
-
for (const line of raw.split("\n")) {
|
|
76
|
-
const trimmed = line.trim();
|
|
77
|
-
if (trimmed === "packages:") {
|
|
78
|
-
inPackages = true;
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
if (inPackages) {
|
|
82
|
-
if (trimmed.startsWith("- ")) {
|
|
83
|
-
patterns.push(trimmed.slice(2).replace(/['"]/g, "").trim());
|
|
84
|
-
} else if (trimmed && !trimmed.startsWith("#")) {
|
|
85
|
-
break; // End of packages list
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
73
|
+
const doc = loadYaml(raw);
|
|
74
|
+
const patterns = Array.isArray(doc?.packages) ? doc.packages.filter((item) => typeof item === "string") : [];
|
|
89
75
|
|
|
90
76
|
return await resolveWorkspacePatterns(repoRoot, patterns);
|
|
91
77
|
} catch {
|
|
@@ -116,8 +102,10 @@ async function resolveWorkspacePatterns(repoRoot, patterns) {
|
|
|
116
102
|
for (const pattern of patterns) {
|
|
117
103
|
// Convert glob pattern to directory search
|
|
118
104
|
// e.g. "packages/*" → list dirs in packages/
|
|
119
|
-
|
|
120
|
-
const
|
|
105
|
+
if (typeof pattern !== "string" || pattern.includes("\0")) continue;
|
|
106
|
+
const basePath = pattern.replace(/\/?\*.*$/, "") || ".";
|
|
107
|
+
const searchDir = path.resolve(repoRoot, basePath);
|
|
108
|
+
if (!isInsideRoot(repoRoot, searchDir)) continue;
|
|
121
109
|
|
|
122
110
|
try {
|
|
123
111
|
const entries = await fs.readdir(searchDir, { withFileTypes: true });
|
package/src/cli-args.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const FLAGS_WITH_VALUE = new Set(["--config", "--target"]);
|
|
2
|
+
const BOOLEAN_FLAGS = new Set([
|
|
3
|
+
"--quick",
|
|
4
|
+
"--non-interactive",
|
|
5
|
+
"--dry-run",
|
|
6
|
+
"--force",
|
|
7
|
+
"--verbose",
|
|
8
|
+
"--help",
|
|
9
|
+
"-h",
|
|
10
|
+
"--version",
|
|
11
|
+
"-v",
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Parse RepoLens argv (already sliced past node and the script path).
|
|
16
|
+
* Global options may appear before or after the command.
|
|
17
|
+
*/
|
|
18
|
+
export function parseCliArgs(argv) {
|
|
19
|
+
const flags = {};
|
|
20
|
+
const positionals = [];
|
|
21
|
+
const errors = [];
|
|
22
|
+
|
|
23
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
24
|
+
const arg = argv[i];
|
|
25
|
+
if (arg === "--") {
|
|
26
|
+
positionals.push(...argv.slice(i + 1));
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
if (arg.startsWith("-")) {
|
|
30
|
+
if (FLAGS_WITH_VALUE.has(arg)) {
|
|
31
|
+
const value = argv[i + 1];
|
|
32
|
+
if (value == null || value.startsWith("-")) {
|
|
33
|
+
errors.push(`${arg} requires a value`);
|
|
34
|
+
} else {
|
|
35
|
+
flags[arg] = value;
|
|
36
|
+
i += 1;
|
|
37
|
+
}
|
|
38
|
+
} else if (BOOLEAN_FLAGS.has(arg)) {
|
|
39
|
+
flags[arg] = true;
|
|
40
|
+
} else {
|
|
41
|
+
errors.push(`Unknown option: ${arg}`);
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
positionals.push(arg);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (positionals.length > 1) {
|
|
49
|
+
errors.push(`Unexpected argument: ${positionals.slice(1).join(" ")}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const command = positionals[0];
|
|
53
|
+
return {
|
|
54
|
+
command,
|
|
55
|
+
flags,
|
|
56
|
+
errors,
|
|
57
|
+
help: Boolean(flags["--help"] || flags["-h"] || command === "help"),
|
|
58
|
+
version: Boolean(flags["--version"] || flags["-v"] || command === "version"),
|
|
59
|
+
};
|
|
60
|
+
}
|