@chappibunny/repolens 1.15.5 → 1.16.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 +35 -0
- package/README.md +17 -14
- package/app.yml +23 -0
- package/github-app-manifest.json +22 -0
- package/llms-full.txt +1 -0
- package/llms-install.md +1 -0
- package/llms.txt +1 -0
- package/package.json +8 -6
- package/src/analyzers/context-builder.js +11 -3
- package/src/analyzers/dependency-graph.js +6 -6
- package/src/cli-args.js +4 -0
- package/src/cli.js +11 -0
- package/src/core/scan.js +62 -20
- package/src/docs/llms-text.js +2 -0
- package/src/github-app/auth.js +130 -0
- package/src/github-app/checkout.js +70 -0
- package/src/github-app/handler.js +170 -0
- package/src/github-app/manifest.js +36 -0
- package/src/github-app/run.js +67 -0
- package/src/github-app/server.js +120 -0
- package/src/github-app/signature.js +22 -0
- package/src/help.js +44 -0
- package/src/renderers/renderDiff.js +5 -3
- package/src/renderers/renderMap.js +7 -5
- package/src/utils/route-params.js +50 -0
- package/src/utils/yaml.js +11 -6
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { replaceBracketParams } from "../utils/route-params.js";
|
|
2
|
+
|
|
1
3
|
function isRouteFile(file) {
|
|
2
4
|
return (
|
|
3
5
|
file.includes("/pages/api/") ||
|
|
@@ -15,10 +17,10 @@ function routePathFromFile(file) {
|
|
|
15
17
|
const appIndex = file.indexOf("/app/");
|
|
16
18
|
const relative = file.slice(appIndex + 5);
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
const cleaned = relative
|
|
19
21
|
.replace(/\/page\.(ts|tsx|js|jsx)$/, "")
|
|
20
|
-
.replace(/\/route\.(ts|tsx|js|jsx)$/, "")
|
|
21
|
-
|
|
22
|
+
.replace(/\/route\.(ts|tsx|js|jsx)$/, "");
|
|
23
|
+
return `/${replaceBracketParams(cleaned)}`;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
if (file.includes("/pages/api/")) {
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
+
import { replaceLeadingAppGroup, replaceSlashGroups } from "../utils/route-params.js";
|
|
2
|
+
|
|
1
3
|
function sanitizeNodeId(value) {
|
|
2
4
|
return value.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
3
5
|
}
|
|
4
6
|
|
|
5
7
|
function normalizeLabel(value) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
.replace(/^app\/\((.*?)\)/, "app/$1")
|
|
9
|
-
.replace(/\/\((.*?)\)/g, "/$1")
|
|
10
|
-
.replace(/\/+/g, "/");
|
|
8
|
+
const withoutSrc = value.replace(/^src\//, "");
|
|
9
|
+
return replaceSlashGroups(replaceLeadingAppGroup(withoutSrc)).replace(/\/+/g, "/");
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
function buildModuleGraph(modules, depGraph) {
|
|
@@ -96,9 +95,11 @@ function buildModuleGraph(modules, depGraph) {
|
|
|
96
95
|
*/
|
|
97
96
|
function findModuleForFile(fileKey, modules) {
|
|
98
97
|
const normalized = fileKey.replace(/\\/g, "/");
|
|
98
|
+
const flat = modules.find((mod) => mod.flat) || modules.find((mod) => mod.key === "root");
|
|
99
99
|
let bestMatch = null;
|
|
100
100
|
for (const mod of modules) {
|
|
101
101
|
const modKey = mod.key;
|
|
102
|
+
if (flat && modKey === flat.key) continue;
|
|
102
103
|
// Direct match (with or without extension)
|
|
103
104
|
if (normalized === modKey || normalized === modKey.replace(/\.[^/.]+$/, "")) {
|
|
104
105
|
return modKey;
|
|
@@ -110,6 +111,7 @@ function findModuleForFile(fileKey, modules) {
|
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
113
|
}
|
|
114
|
+
if (!bestMatch && flat && !normalized.includes("/")) return flat.key;
|
|
113
115
|
return bestMatch;
|
|
114
116
|
}
|
|
115
117
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linear replacements for route and label text.
|
|
3
|
+
*
|
|
4
|
+
* A lazy `.*?` between two markers is polynomial: on a long string with no
|
|
5
|
+
* closer, each start position scans to the end (CodeQL js/polynomial-redos).
|
|
6
|
+
* These walks stop at the first closer and never re-scan, which matches the
|
|
7
|
+
* old `String.prototype.replace` result.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
function replaceMarked(input, open, close, mapInner) {
|
|
11
|
+
const value = String(input ?? "");
|
|
12
|
+
let out = "";
|
|
13
|
+
let cursor = 0;
|
|
14
|
+
while (cursor < value.length) {
|
|
15
|
+
const start = value.indexOf(open, cursor);
|
|
16
|
+
if (start === -1) {
|
|
17
|
+
out += value.slice(cursor);
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
const end = value.indexOf(close, start + open.length);
|
|
21
|
+
if (end === -1) {
|
|
22
|
+
out += value.slice(cursor);
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
out += value.slice(cursor, start);
|
|
26
|
+
out += mapInner(value.slice(start + open.length, end));
|
|
27
|
+
cursor = end + close.length;
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** `[param]` → `:param`, including the first `]` only. Global, non-overlapping. */
|
|
33
|
+
export function replaceBracketParams(value) {
|
|
34
|
+
return replaceMarked(value, "[", "]", (inner) => `:${inner}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** `/(group)` → `/group`. Used for Next.js route groups in diagram labels. */
|
|
38
|
+
export function replaceSlashGroups(value) {
|
|
39
|
+
return replaceMarked(value, "/(", ")", (inner) => `/${inner}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** A leading `app/(group)` → `app/group`. Later groups use {@link replaceSlashGroups}. */
|
|
43
|
+
export function replaceLeadingAppGroup(value) {
|
|
44
|
+
const input = String(value ?? "");
|
|
45
|
+
const prefix = "app/(";
|
|
46
|
+
if (!input.startsWith(prefix)) return input;
|
|
47
|
+
const end = input.indexOf(")", prefix.length);
|
|
48
|
+
if (end === -1) return input;
|
|
49
|
+
return `app/${input.slice(prefix.length, end)}${input.slice(end + 1)}`;
|
|
50
|
+
}
|
package/src/utils/yaml.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { CORE_SCHEMA, load, mergeTag } from "js-yaml";
|
|
2
2
|
|
|
3
3
|
const MAX_YAML_CHARS = 1_000_000;
|
|
4
4
|
const MAX_YAML_ALIASES = 2000;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Parse YAML without executing custom tags.
|
|
8
|
-
* js-yaml
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* js-yaml 5 `load` uses the YAML 1.2 Core schema (`true`/`false` are booleans;
|
|
9
|
+
* the YAML 1.1 spellings `yes` and `no` stay strings). The merge key (`<<`)
|
|
10
|
+
* is added back so configs that relied on js-yaml 4's merge still parse.
|
|
11
|
+
* A size cap and `maxAliases` stop a billion-laughs document.
|
|
12
|
+
* An empty file returns `undefined`, matching the previous loader.
|
|
12
13
|
*/
|
|
13
14
|
export function loadYaml(raw) {
|
|
14
15
|
if (typeof raw !== "string") {
|
|
@@ -17,11 +18,15 @@ export function loadYaml(raw) {
|
|
|
17
18
|
if (raw.length > MAX_YAML_CHARS) {
|
|
18
19
|
throw new Error(`YAML document exceeds ${MAX_YAML_CHARS} characters`);
|
|
19
20
|
}
|
|
21
|
+
if (raw.trim() === "") return undefined;
|
|
20
22
|
|
|
21
23
|
const aliasUses = raw.match(/(^|[\s\[\{,])\*[A-Za-z_][\w-]*/g);
|
|
22
24
|
if (aliasUses && aliasUses.length > MAX_YAML_ALIASES) {
|
|
23
25
|
throw new Error(`YAML document has too many aliases (${aliasUses.length})`);
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
return
|
|
28
|
+
return load(raw, {
|
|
29
|
+
schema: CORE_SCHEMA.withTags(mergeTag),
|
|
30
|
+
maxAliases: MAX_YAML_ALIASES,
|
|
31
|
+
});
|
|
27
32
|
}
|