geopilot 0.0.0-stage → 0.0.1-bootstrap.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/LICENSE +202 -0
- package/README.md +72 -2
- package/dist/agent/install.d.ts +23 -0
- package/dist/agent/install.js +75 -0
- package/dist/agent/install.js.map +1 -0
- package/dist/cache/runs.d.ts +18 -0
- package/dist/cache/runs.js +91 -0
- package/dist/cache/runs.js.map +1 -0
- package/dist/cli/args.d.ts +20 -0
- package/dist/cli/args.js +116 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/commands/agent.d.ts +2 -0
- package/dist/cli/commands/agent.js +48 -0
- package/dist/cli/commands/agent.js.map +1 -0
- package/dist/cli/commands/fix.d.ts +2 -0
- package/dist/cli/commands/fix.js +284 -0
- package/dist/cli/commands/fix.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.js +62 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/insights.d.ts +17 -0
- package/dist/cli/commands/insights.js +143 -0
- package/dist/cli/commands/insights.js.map +1 -0
- package/dist/cli/commands/rules.d.ts +5 -0
- package/dist/cli/commands/rules.js +86 -0
- package/dist/cli/commands/rules.js.map +1 -0
- package/dist/cli/commands/scan.d.ts +14 -0
- package/dist/cli/commands/scan.js +127 -0
- package/dist/cli/commands/scan.js.map +1 -0
- package/dist/cli/commands-list.d.ts +6 -0
- package/dist/cli/commands-list.js +15 -0
- package/dist/cli/commands-list.js.map +1 -0
- package/dist/cli/context.d.ts +26 -0
- package/dist/cli/context.js +108 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/io.d.ts +16 -0
- package/dist/cli/io.js +28 -0
- package/dist/cli/io.js.map +1 -0
- package/dist/cli/main.d.ts +15 -0
- package/dist/cli/main.js +118 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/collect/crawl.d.ts +51 -0
- package/dist/collect/crawl.js +187 -0
- package/dist/collect/crawl.js.map +1 -0
- package/dist/config/config.d.ts +86 -0
- package/dist/config/config.js +396 -0
- package/dist/config/config.js.map +1 -0
- package/dist/core/errors.d.ts +20 -0
- package/dist/core/errors.js +32 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/hash.d.ts +7 -0
- package/dist/core/hash.js +28 -0
- package/dist/core/hash.js.map +1 -0
- package/dist/core/redact.d.ts +3 -0
- package/dist/core/redact.js +23 -0
- package/dist/core/redact.js.map +1 -0
- package/dist/core/tty.d.ts +12 -0
- package/dist/core/tty.js +33 -0
- package/dist/core/tty.js.map +1 -0
- package/dist/core/version.d.ts +6 -0
- package/dist/core/version.js +10 -0
- package/dist/core/version.js.map +1 -0
- package/dist/fix/apply.d.ts +119 -0
- package/dist/fix/apply.js +334 -0
- package/dist/fix/apply.js.map +1 -0
- package/dist/fix/diff.d.ts +1 -0
- package/dist/fix/diff.js +35 -0
- package/dist/fix/diff.js.map +1 -0
- package/dist/fix/plan.d.ts +42 -0
- package/dist/fix/plan.js +385 -0
- package/dist/fix/plan.js.map +1 -0
- package/dist/fix/serve.d.ts +13 -0
- package/dist/fix/serve.js +112 -0
- package/dist/fix/serve.js.map +1 -0
- package/dist/fix/variants.d.ts +13 -0
- package/dist/fix/variants.js +8 -0
- package/dist/fix/variants.js.map +1 -0
- package/dist/frameworks/ast.d.ts +84 -0
- package/dist/frameworks/ast.js +231 -0
- package/dist/frameworks/ast.js.map +1 -0
- package/dist/frameworks/nextjs-app/analyze.d.ts +92 -0
- package/dist/frameworks/nextjs-app/analyze.js +350 -0
- package/dist/frameworks/nextjs-app/analyze.js.map +1 -0
- package/dist/frameworks/static/analyze.d.ts +18 -0
- package/dist/frameworks/static/analyze.js +66 -0
- package/dist/frameworks/static/analyze.js.map +1 -0
- package/dist/html/parse.d.ts +50 -0
- package/dist/html/parse.js +205 -0
- package/dist/html/parse.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/insights/validate.d.ts +74 -0
- package/dist/insights/validate.js +213 -0
- package/dist/insights/validate.js.map +1 -0
- package/dist/net/address.d.ts +10 -0
- package/dist/net/address.js +116 -0
- package/dist/net/address.js.map +1 -0
- package/dist/net/fetch.d.ts +53 -0
- package/dist/net/fetch.js +281 -0
- package/dist/net/fetch.js.map +1 -0
- package/dist/repo/detect.d.ts +3 -0
- package/dist/repo/detect.js +92 -0
- package/dist/repo/detect.js.map +1 -0
- package/dist/repo/reader.d.ts +12 -0
- package/dist/repo/reader.js +97 -0
- package/dist/repo/reader.js.map +1 -0
- package/dist/report/render.d.ts +20 -0
- package/dist/report/render.js +176 -0
- package/dist/report/render.js.map +1 -0
- package/dist/robots/crawlers.d.ts +10 -0
- package/dist/robots/crawlers.js +20 -0
- package/dist/robots/crawlers.js.map +1 -0
- package/dist/robots/robots.d.ts +33 -0
- package/dist/robots/robots.js +133 -0
- package/dist/robots/robots.js.map +1 -0
- package/dist/rules/catalogue.d.ts +43 -0
- package/dist/rules/catalogue.js +361 -0
- package/dist/rules/catalogue.js.map +1 -0
- package/dist/rules/context.d.ts +36 -0
- package/dist/rules/context.js +129 -0
- package/dist/rules/context.js.map +1 -0
- package/dist/rules/evaluate.d.ts +11 -0
- package/dist/rules/evaluate.js +1070 -0
- package/dist/rules/evaluate.js.map +1 -0
- package/dist/rules/finalize.d.ts +34 -0
- package/dist/rules/finalize.js +93 -0
- package/dist/rules/finalize.js.map +1 -0
- package/dist/scan.d.ts +27 -0
- package/dist/scan.js +147 -0
- package/dist/scan.js.map +1 -0
- package/dist/scoring/compare.d.ts +21 -0
- package/dist/scoring/compare.js +47 -0
- package/dist/scoring/compare.js.map +1 -0
- package/dist/scoring/score.d.ts +21 -0
- package/dist/scoring/score.js +112 -0
- package/dist/scoring/score.js.map +1 -0
- package/dist/sitemap/sitemap.d.ts +10 -0
- package/dist/sitemap/sitemap.js +48 -0
- package/dist/sitemap/sitemap.js.map +1 -0
- package/dist/types.d.ts +155 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/hosts/claude-project/.claude/agents/geopilot-explainer.md +36 -0
- package/hosts/claude-project/.claude/agents/geopilot-fixer.md +42 -0
- package/hosts/claude-project/.claude/agents/geopilot-investigator.md +45 -0
- package/hosts/claude-project/.claude/agents/geopilot-reviewer.md +41 -0
- package/hosts/claude-project/.claude/agents/geopilot-scanner.md +47 -0
- package/hosts/claude-project/.claude/skills/geo/SKILL.md +95 -0
- package/hosts/claude-project/.claude/skills/geo/references/frameworks.md +20 -0
- package/hosts/claude-project/.claude/skills/geo/references/insight-contract.md +42 -0
- package/hosts/claude-project/.claude/skills/geo/references/safety.md +30 -0
- package/hosts/claude-project/.claude/skills/geo/references/workflow-explain.md +8 -0
- package/hosts/claude-project/.claude/skills/geo/references/workflow-fix.md +20 -0
- package/hosts/claude-project/.claude/skills/geo/references/workflow-init.md +6 -0
- package/hosts/claude-project/.claude/skills/geo/references/workflow-insights.md +13 -0
- package/hosts/claude-project/.claude/skills/geo/references/workflow-plan.md +13 -0
- package/hosts/claude-project/.claude/skills/geo/references/workflow-review.md +8 -0
- package/hosts/claude-project/.claude/skills/geo/references/workflow-scan.md +18 -0
- package/hosts/claude-project/.claude/skills/geo/schemas/insights.schema.json +255 -0
- package/hosts/claude-project/.claude/skills/geo/scripts/geo.ps1 +11 -0
- package/hosts/claude-project/.claude/skills/geo/scripts/geo.sh +11 -0
- package/hosts/claude-project/.claude/skills/geopilot-explain/SKILL.md +9 -0
- package/hosts/claude-project/.claude/skills/geopilot-fix/SKILL.md +12 -0
- package/hosts/claude-project/.claude/skills/geopilot-init/SKILL.md +15 -0
- package/hosts/claude-project/.claude/skills/geopilot-insights/SKILL.md +11 -0
- package/hosts/claude-project/.claude/skills/geopilot-review/SKILL.md +11 -0
- package/hosts/claude-project/.claude/skills/geopilot-scan/SKILL.md +11 -0
- package/hosts/geopilot/.claude-plugin/plugin.json +22 -0
- package/hosts/geopilot/README.md +25 -0
- package/hosts/geopilot/agents/explainer.agent.md +36 -0
- package/hosts/geopilot/agents/fixer.agent.md +42 -0
- package/hosts/geopilot/agents/investigator.agent.md +45 -0
- package/hosts/geopilot/agents/reviewer.agent.md +41 -0
- package/hosts/geopilot/agents/scanner.agent.md +47 -0
- package/hosts/geopilot/assets/icon.png +0 -0
- package/hosts/geopilot/skills/explain/SKILL.md +9 -0
- package/hosts/geopilot/skills/fix/SKILL.md +12 -0
- package/hosts/geopilot/skills/geo/SKILL.md +95 -0
- package/hosts/geopilot/skills/geo/references/frameworks.md +20 -0
- package/hosts/geopilot/skills/geo/references/insight-contract.md +42 -0
- package/hosts/geopilot/skills/geo/references/safety.md +30 -0
- package/hosts/geopilot/skills/geo/references/workflow-explain.md +8 -0
- package/hosts/geopilot/skills/geo/references/workflow-fix.md +20 -0
- package/hosts/geopilot/skills/geo/references/workflow-init.md +6 -0
- package/hosts/geopilot/skills/geo/references/workflow-insights.md +13 -0
- package/hosts/geopilot/skills/geo/references/workflow-plan.md +13 -0
- package/hosts/geopilot/skills/geo/references/workflow-review.md +8 -0
- package/hosts/geopilot/skills/geo/references/workflow-scan.md +18 -0
- package/hosts/geopilot/skills/geo/schemas/insights.schema.json +255 -0
- package/hosts/geopilot/skills/geo/scripts/geo.ps1 +11 -0
- package/hosts/geopilot/skills/geo/scripts/geo.sh +11 -0
- package/hosts/geopilot/skills/init/SKILL.md +15 -0
- package/hosts/geopilot/skills/insights/SKILL.md +11 -0
- package/hosts/geopilot/skills/review/SKILL.md +11 -0
- package/hosts/geopilot/skills/scan/SKILL.md +11 -0
- package/hosts/opencode/.opencode/agents/geopilot-explainer.md +39 -0
- package/hosts/opencode/.opencode/agents/geopilot-fixer.md +45 -0
- package/hosts/opencode/.opencode/agents/geopilot-investigator.md +48 -0
- package/hosts/opencode/.opencode/agents/geopilot-reviewer.md +44 -0
- package/hosts/opencode/.opencode/agents/geopilot-scanner.md +50 -0
- package/hosts/opencode/.opencode/commands/geopilot-explain.md +8 -0
- package/hosts/opencode/.opencode/commands/geopilot-fix.md +10 -0
- package/hosts/opencode/.opencode/commands/geopilot-init.md +12 -0
- package/hosts/opencode/.opencode/commands/geopilot-insights.md +10 -0
- package/hosts/opencode/.opencode/commands/geopilot-review.md +10 -0
- package/hosts/opencode/.opencode/commands/geopilot-scan.md +10 -0
- package/hosts/opencode/.opencode/skills/geo/SKILL.md +95 -0
- package/hosts/opencode/.opencode/skills/geo/references/frameworks.md +20 -0
- package/hosts/opencode/.opencode/skills/geo/references/insight-contract.md +42 -0
- package/hosts/opencode/.opencode/skills/geo/references/safety.md +30 -0
- package/hosts/opencode/.opencode/skills/geo/references/workflow-explain.md +8 -0
- package/hosts/opencode/.opencode/skills/geo/references/workflow-fix.md +20 -0
- package/hosts/opencode/.opencode/skills/geo/references/workflow-init.md +6 -0
- package/hosts/opencode/.opencode/skills/geo/references/workflow-insights.md +13 -0
- package/hosts/opencode/.opencode/skills/geo/references/workflow-plan.md +13 -0
- package/hosts/opencode/.opencode/skills/geo/references/workflow-review.md +8 -0
- package/hosts/opencode/.opencode/skills/geo/references/workflow-scan.md +18 -0
- package/hosts/opencode/.opencode/skills/geo/schemas/insights.schema.json +255 -0
- package/hosts/opencode/.opencode/skills/geo/scripts/geo.ps1 +11 -0
- package/hosts/opencode/.opencode/skills/geo/scripts/geo.sh +11 -0
- package/package.json +65 -4
- package/schemas/config-v1.json +392 -0
- package/schemas/insights-v1.json +255 -0
- package/schemas/merged-v1.json +71 -0
- package/schemas/report-v1.json +836 -0
- package/skill/geo/SKILL.md +95 -0
- package/skill/geo/references/frameworks.md +20 -0
- package/skill/geo/references/insight-contract.md +42 -0
- package/skill/geo/references/safety.md +30 -0
- package/skill/geo/references/workflow-explain.md +8 -0
- package/skill/geo/references/workflow-fix.md +20 -0
- package/skill/geo/references/workflow-init.md +6 -0
- package/skill/geo/references/workflow-insights.md +13 -0
- package/skill/geo/references/workflow-plan.md +13 -0
- package/skill/geo/references/workflow-review.md +8 -0
- package/skill/geo/references/workflow-scan.md +18 -0
- package/skill/geo/schemas/insights.schema.json +255 -0
- package/skill/geo/scripts/geo.ps1 +11 -0
- package/skill/geo/scripts/geo.sh +11 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { posix } from 'node:path';
|
|
2
|
+
import { exportsOf, findJsxHtml, hasDirective, hasObjectKey, importsOf, lineCol, parseModule, staticValue, } from "../ast.js";
|
|
3
|
+
// Next.js App Router, read as source (spec 11). Supported majors are a
|
|
4
|
+
// versioned table; an unknown major downgrades provenance rather than guessing.
|
|
5
|
+
export const SUPPORTED_NEXT_MAJORS = [13, 14, 15, 16];
|
|
6
|
+
const PAGE_EXT = ['tsx', 'ts', 'jsx', 'js', 'mdx'];
|
|
7
|
+
const CODE_EXT = ['tsx', 'ts', 'jsx', 'js'];
|
|
8
|
+
const MAX_IMPORT_DEPTH = 5;
|
|
9
|
+
function firstExisting(repo, candidates) {
|
|
10
|
+
for (const c of candidates)
|
|
11
|
+
if (repo.has(c))
|
|
12
|
+
return c;
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
export function findAppDir(repo) {
|
|
16
|
+
for (const dir of ['app', 'src/app']) {
|
|
17
|
+
if (repo.files.some((f) => f.startsWith(`${dir}/`) && /\/(page|layout)\.(tsx|ts|jsx|js|mdx)$/.test(`/${f.slice(dir.length + 1)}`)))
|
|
18
|
+
return dir;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
export function nextMajorOf(repo) {
|
|
23
|
+
const text = repo.read('package.json');
|
|
24
|
+
if (!text)
|
|
25
|
+
return null;
|
|
26
|
+
try {
|
|
27
|
+
const pkg = JSON.parse(text);
|
|
28
|
+
const range = pkg.dependencies?.next ?? pkg.devDependencies?.next;
|
|
29
|
+
if (!range)
|
|
30
|
+
return null;
|
|
31
|
+
const m = /(\d+)\./.exec(range) ?? /^[\^~>=\s]*(\d+)$/.exec(range);
|
|
32
|
+
return m ? Number(m[1]) : null;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function segmentToRoute(seg) {
|
|
39
|
+
if (/^\(.*\)$/.test(seg) && !/^\(\.+\)/.test(seg))
|
|
40
|
+
return { part: null, dynamic: false, uncertain: null };
|
|
41
|
+
if (/^\(\.+\)/.test(seg))
|
|
42
|
+
return { part: seg.replace(/^\(\.+\)/, ''), dynamic: false, uncertain: `intercepting route segment ${seg}` };
|
|
43
|
+
if (seg.startsWith('@'))
|
|
44
|
+
return { part: null, dynamic: false, uncertain: `parallel route slot ${seg}` };
|
|
45
|
+
if (/^\[.*\]$/.test(seg))
|
|
46
|
+
return { part: seg, dynamic: true, uncertain: null };
|
|
47
|
+
return { part: seg, dynamic: false, uncertain: null };
|
|
48
|
+
}
|
|
49
|
+
function isPrivate(segments) {
|
|
50
|
+
return segments.some((s) => s.startsWith('_'));
|
|
51
|
+
}
|
|
52
|
+
function resolveImport(repo, fromFile, spec) {
|
|
53
|
+
let base = null;
|
|
54
|
+
if (spec.startsWith('.'))
|
|
55
|
+
base = posix.normalize(posix.join(posix.dirname(fromFile), spec));
|
|
56
|
+
else if (spec.startsWith('@/'))
|
|
57
|
+
base = repo.has('src') || repo.files.some((f) => f.startsWith('src/')) ? `src/${spec.slice(2)}` : spec.slice(2);
|
|
58
|
+
else if (spec.startsWith('~/'))
|
|
59
|
+
base = spec.slice(2);
|
|
60
|
+
if (base === null)
|
|
61
|
+
return null;
|
|
62
|
+
const candidates = [base, ...CODE_EXT.map((e) => `${base}.${e}`), ...CODE_EXT.map((e) => `${base}/index.${e}`)];
|
|
63
|
+
return firstExisting(repo, candidates);
|
|
64
|
+
}
|
|
65
|
+
export function analyzeNextApp(repo) {
|
|
66
|
+
const appDir = findAppDir(repo);
|
|
67
|
+
if (!appDir)
|
|
68
|
+
return null;
|
|
69
|
+
const modules = new Map();
|
|
70
|
+
const parseErrors = [];
|
|
71
|
+
const load = (file) => {
|
|
72
|
+
if (modules.has(file))
|
|
73
|
+
return modules.get(file);
|
|
74
|
+
const src = repo.read(file);
|
|
75
|
+
if (src === null || file.endsWith('.mdx'))
|
|
76
|
+
return null;
|
|
77
|
+
const mod = parseModule(file, src);
|
|
78
|
+
if ('error' in mod) {
|
|
79
|
+
parseErrors.push({ file, reason: mod.error });
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
modules.set(file, mod);
|
|
83
|
+
return mod;
|
|
84
|
+
};
|
|
85
|
+
const appFiles = repo.files.filter((f) => f.startsWith(`${appDir}/`));
|
|
86
|
+
const routes = [];
|
|
87
|
+
for (const file of appFiles) {
|
|
88
|
+
const rel = file.slice(appDir.length + 1);
|
|
89
|
+
const m = new RegExp(`^(.*/)?page\\.(${PAGE_EXT.join('|')})$`).exec(rel);
|
|
90
|
+
if (!m)
|
|
91
|
+
continue;
|
|
92
|
+
const dirSegments = (m[1] ?? '').split('/').filter(Boolean);
|
|
93
|
+
if (isPrivate(dirSegments))
|
|
94
|
+
continue;
|
|
95
|
+
const parts = [];
|
|
96
|
+
let dynamic = false;
|
|
97
|
+
const uncertain = [];
|
|
98
|
+
for (const seg of dirSegments) {
|
|
99
|
+
const r = segmentToRoute(seg);
|
|
100
|
+
if (r.part)
|
|
101
|
+
parts.push(r.part);
|
|
102
|
+
if (r.dynamic)
|
|
103
|
+
dynamic = true;
|
|
104
|
+
if (r.uncertain)
|
|
105
|
+
uncertain.push(r.uncertain);
|
|
106
|
+
}
|
|
107
|
+
const layoutFiles = [];
|
|
108
|
+
for (let i = 0; i <= dirSegments.length; i++) {
|
|
109
|
+
const dir = [appDir, ...dirSegments.slice(0, i)].join('/');
|
|
110
|
+
const layout = firstExisting(repo, CODE_EXT.map((e) => `${dir}/layout.${e}`));
|
|
111
|
+
if (layout)
|
|
112
|
+
layoutFiles.push(layout);
|
|
113
|
+
}
|
|
114
|
+
const mod = load(file);
|
|
115
|
+
routes.push({
|
|
116
|
+
route: `/${parts.join('/')}`,
|
|
117
|
+
pageFile: file,
|
|
118
|
+
layoutFiles,
|
|
119
|
+
dynamic,
|
|
120
|
+
uncertain,
|
|
121
|
+
clientPage: mod ? hasDirective(mod, 'use client') : false,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
routes.sort((a, b) => (a.route < b.route ? -1 : a.route > b.route ? 1 : a.pageFile < b.pageFile ? -1 : 1));
|
|
125
|
+
const meta = new Map();
|
|
126
|
+
const metaOf = (file) => {
|
|
127
|
+
if (meta.has(file))
|
|
128
|
+
return meta.get(file);
|
|
129
|
+
const result = readMetadata(repo, file, load, parseErrors);
|
|
130
|
+
meta.set(file, result);
|
|
131
|
+
return result;
|
|
132
|
+
};
|
|
133
|
+
for (const r of routes) {
|
|
134
|
+
metaOf(r.pageFile);
|
|
135
|
+
for (const l of r.layoutFiles)
|
|
136
|
+
metaOf(l);
|
|
137
|
+
}
|
|
138
|
+
const rootLayout = firstExisting(repo, CODE_EXT.map((e) => `${appDir}/layout.${e}`));
|
|
139
|
+
const rootMod = rootLayout ? load(rootLayout) : null;
|
|
140
|
+
const html = rootMod ? findJsxHtml(rootMod) : null;
|
|
141
|
+
const nextConfigFile = firstExisting(repo, ['next.config.ts', 'next.config.mjs', 'next.config.js', 'next.config.cjs', 'next.config.mts']);
|
|
142
|
+
let nextConfig = null;
|
|
143
|
+
if (nextConfigFile) {
|
|
144
|
+
const mod = load(nextConfigFile);
|
|
145
|
+
nextConfig = { file: nextConfigFile, keys: mod ? hasObjectKey(mod, new Set(['i18n', 'headers', 'rewrites', 'redirects', 'basePath', 'trailingSlash', 'output'])) : ['unparsed'] };
|
|
146
|
+
}
|
|
147
|
+
const i18n = [];
|
|
148
|
+
if (nextConfig?.keys.includes('i18n'))
|
|
149
|
+
i18n.push(`${nextConfig.file} declares i18n`);
|
|
150
|
+
for (const r of routes) {
|
|
151
|
+
const first = r.route.split('/')[1] ?? '';
|
|
152
|
+
if (/^\[(locale|lang|lng|language)\]$/.test(first)) {
|
|
153
|
+
i18n.push(`dynamic locale segment ${first}`);
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const middleware = firstExisting(repo, [
|
|
158
|
+
...CODE_EXT.map((e) => `middleware.${e}`),
|
|
159
|
+
...CODE_EXT.map((e) => `src/middleware.${e}`),
|
|
160
|
+
...CODE_EXT.map((e) => `proxy.${e}`),
|
|
161
|
+
...CODE_EXT.map((e) => `src/proxy.${e}`),
|
|
162
|
+
]);
|
|
163
|
+
const nextMajor = nextMajorOf(repo);
|
|
164
|
+
return {
|
|
165
|
+
appDir,
|
|
166
|
+
routes,
|
|
167
|
+
meta,
|
|
168
|
+
modules,
|
|
169
|
+
rootLayout,
|
|
170
|
+
html,
|
|
171
|
+
robots: {
|
|
172
|
+
publicTxt: repo.has('public/robots.txt') ? 'public/robots.txt' : null,
|
|
173
|
+
appTxt: repo.has(`${appDir}/robots.txt`) ? `${appDir}/robots.txt` : null,
|
|
174
|
+
appCode: firstExisting(repo, CODE_EXT.map((e) => `${appDir}/robots.${e}`)),
|
|
175
|
+
},
|
|
176
|
+
sitemap: {
|
|
177
|
+
publicXml: repo.files.filter((f) => /^public\/sitemap[^/]*\.xml$/.test(f)),
|
|
178
|
+
appXml: repo.has(`${appDir}/sitemap.xml`) ? `${appDir}/sitemap.xml` : null,
|
|
179
|
+
appCode: appFiles.filter((f) => /(^|\/)sitemap\.(tsx|ts|jsx|js)$/.test(f)),
|
|
180
|
+
},
|
|
181
|
+
middleware,
|
|
182
|
+
nextConfig,
|
|
183
|
+
i18n,
|
|
184
|
+
nextMajor,
|
|
185
|
+
supportedMajor: nextMajor !== null && SUPPORTED_NEXT_MAJORS.includes(nextMajor),
|
|
186
|
+
parseErrors,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function readMetadata(repo, file, load, parseErrors) {
|
|
190
|
+
const mod = load(file);
|
|
191
|
+
if (!mod) {
|
|
192
|
+
const err = parseErrors.find((e) => e.file === file);
|
|
193
|
+
return err ? { kind: 'parse_error', file, reason: err.reason } : { kind: 'none', file };
|
|
194
|
+
}
|
|
195
|
+
const exp = exportsOf(mod);
|
|
196
|
+
if (exp.has('generateMetadata'))
|
|
197
|
+
return { kind: 'generate', file, line: lineCol(exp.get('generateMetadata').node).line };
|
|
198
|
+
const md = exp.get('metadata');
|
|
199
|
+
if (!md)
|
|
200
|
+
return { kind: 'none', file };
|
|
201
|
+
return followMetadata(repo, mod, md.kind === 'reexport' ? null : md.init, md.from ?? null, 'metadata', file, load, 0);
|
|
202
|
+
}
|
|
203
|
+
function followMetadata(repo, mod, init, reexportFrom, name, declaredIn, load, depth) {
|
|
204
|
+
if (depth > MAX_IMPORT_DEPTH)
|
|
205
|
+
return { kind: 'opaque', file: declaredIn, line: 1, reason: `import chain deeper than ${MAX_IMPORT_DEPTH}` };
|
|
206
|
+
if (reexportFrom !== null) {
|
|
207
|
+
const target = resolveImport(repo, mod.file, reexportFrom);
|
|
208
|
+
const tmod = target ? load(target) : null;
|
|
209
|
+
if (!tmod)
|
|
210
|
+
return { kind: 'opaque', file: declaredIn, line: 1, reason: `re-export from unresolved module ${reexportFrom}` };
|
|
211
|
+
const e = exportsOf(tmod).get(name);
|
|
212
|
+
if (!e)
|
|
213
|
+
return { kind: 'opaque', file: declaredIn, line: 1, reason: `${reexportFrom} has no export ${name}` };
|
|
214
|
+
return followMetadata(repo, tmod, e.kind === 'reexport' ? null : e.init, e.from ?? null, name, declaredIn, load, depth + 1);
|
|
215
|
+
}
|
|
216
|
+
if (!init)
|
|
217
|
+
return { kind: 'opaque', file: declaredIn, line: 1, reason: 'metadata has no initialiser' };
|
|
218
|
+
const value = staticValue(init);
|
|
219
|
+
if (value.kind === 'object')
|
|
220
|
+
return { kind: 'literal', file: mod.file, value, declaredIn };
|
|
221
|
+
if (value.kind === 'dynamic' && init.type === 'Identifier') {
|
|
222
|
+
const imp = importsOf(mod).get(init.name);
|
|
223
|
+
if (imp) {
|
|
224
|
+
const target = resolveImport(repo, mod.file, imp.from);
|
|
225
|
+
const tmod = target ? load(target) : null;
|
|
226
|
+
if (!tmod)
|
|
227
|
+
return { kind: 'opaque', file: declaredIn, line: lineCol(init).line, reason: `imported from unresolved module ${imp.from}` };
|
|
228
|
+
const e = exportsOf(tmod).get(imp.imported);
|
|
229
|
+
if (!e)
|
|
230
|
+
return { kind: 'opaque', file: declaredIn, line: lineCol(init).line, reason: `${imp.from} has no export ${imp.imported}` };
|
|
231
|
+
return followMetadata(repo, tmod, e.kind === 'reexport' ? null : e.init, e.from ?? null, imp.imported, declaredIn, load, depth + 1);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return { kind: 'opaque', file: mod.file, line: lineCol(init).line, reason: value.kind === 'dynamic' ? value.reason : `metadata is a ${value.kind}` };
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Resolve one top-level metadata key for a route by Next's shallow per-key
|
|
238
|
+
* precedence: the nearest segment that defines the key wins outright.
|
|
239
|
+
*/
|
|
240
|
+
export function resolveMetaKey(a, route, key) {
|
|
241
|
+
const chain = [route.pageFile, ...[...route.layoutFiles].reverse()];
|
|
242
|
+
let imported = null;
|
|
243
|
+
for (const file of chain) {
|
|
244
|
+
const src = a.meta.get(file);
|
|
245
|
+
if (!src || src.kind === 'none')
|
|
246
|
+
continue;
|
|
247
|
+
if (src.kind === 'parse_error')
|
|
248
|
+
return { level: 'unmapped', value: null, locations: [{ file }], reason: `could not parse ${file}`, literalFile: null, prop: null };
|
|
249
|
+
if (src.kind === 'generate') {
|
|
250
|
+
return { level: 'file', value: null, locations: [{ file, line: src.line }], reason: `${file} computes metadata in generateMetadata`, literalFile: null, prop: null };
|
|
251
|
+
}
|
|
252
|
+
if (src.kind === 'opaque') {
|
|
253
|
+
return { level: 'file', value: null, locations: [{ file: src.file, line: src.line }], reason: src.reason, literalFile: null, prop: null };
|
|
254
|
+
}
|
|
255
|
+
const prop = src.value.props.get(key);
|
|
256
|
+
if (prop) {
|
|
257
|
+
const loc = { file: src.file, ...lineCol(prop.node) };
|
|
258
|
+
if (prop.value.kind === 'dynamic') {
|
|
259
|
+
return { level: 'file', value: prop.value, locations: [loc], reason: `${key} is computed (${prop.value.reason})`, literalFile: null, prop: prop.node };
|
|
260
|
+
}
|
|
261
|
+
const imported = src.file !== src.declaredIn;
|
|
262
|
+
return {
|
|
263
|
+
level: imported ? 'file' : 'exact',
|
|
264
|
+
value: prop.value,
|
|
265
|
+
locations: [loc],
|
|
266
|
+
reason: imported ? `${key} is imported into ${src.declaredIn} from ${src.file}` : `literal ${key} in ${src.file}`,
|
|
267
|
+
literalFile: imported ? null : src.file,
|
|
268
|
+
prop: prop.node,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
if (src.file !== src.declaredIn)
|
|
272
|
+
imported ??= `${src.declaredIn} imports its metadata from ${src.file}`;
|
|
273
|
+
if (src.value.dynamicKeys) {
|
|
274
|
+
return { level: 'candidate', value: null, locations: [{ file: src.file, ...lineCol(src.value.node) }], reason: `metadata in ${src.file} spreads or computes keys; ${key} may come from there`, literalFile: null, prop: null };
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const reason = `no segment from ${route.pageFile} to the root layout defines ${key}`;
|
|
278
|
+
// Absence is proven, but with imported metadata the insertion point is not.
|
|
279
|
+
if (imported)
|
|
280
|
+
return { level: 'candidate', value: null, locations: chain.map((file) => ({ file })), reason: `${reason}; ${imported}`, literalFile: null, prop: null, missing: true };
|
|
281
|
+
return { level: 'absent', value: null, locations: chain.map((file) => ({ file })), reason, literalFile: null, prop: null, missing: true };
|
|
282
|
+
}
|
|
283
|
+
/** Global and per-route conditions that cap provenance below exact (spec 11). */
|
|
284
|
+
export function provenanceCaps(a, route, concern) {
|
|
285
|
+
const caps = [];
|
|
286
|
+
if (!a.supportedMajor)
|
|
287
|
+
caps.push(a.nextMajor === null ? 'Next.js version could not be read from package.json' : `Next.js ${a.nextMajor} is not in the supported-version table`);
|
|
288
|
+
if (a.middleware)
|
|
289
|
+
caps.push(`${a.middleware} can rewrite or add headers to any route`);
|
|
290
|
+
if (concern !== 'html' && a.nextConfig?.keys.some((k) => k === 'headers' || k === 'rewrites'))
|
|
291
|
+
caps.push(`${a.nextConfig.file} declares headers or rewrites`);
|
|
292
|
+
if (concern === 'html' && a.i18n.length > 0)
|
|
293
|
+
caps.push(...a.i18n);
|
|
294
|
+
if (route) {
|
|
295
|
+
caps.push(...route.uncertain);
|
|
296
|
+
if (route.dynamic)
|
|
297
|
+
caps.push(`${route.route} has dynamic parameters`);
|
|
298
|
+
}
|
|
299
|
+
return caps;
|
|
300
|
+
}
|
|
301
|
+
export function capLevel(level, caps) {
|
|
302
|
+
if (caps.length === 0)
|
|
303
|
+
return level;
|
|
304
|
+
return level === 'exact' || level === 'absent' ? 'candidate' : level;
|
|
305
|
+
}
|
|
306
|
+
/** Match a URL path to the most specific route (static segments beat dynamic). */
|
|
307
|
+
export function matchRoute(routes, pathname) {
|
|
308
|
+
const parts = pathname.replace(/\/+$/, '').split('/').filter(Boolean);
|
|
309
|
+
let best = null;
|
|
310
|
+
for (const r of routes) {
|
|
311
|
+
const rp = r.route.split('/').filter(Boolean);
|
|
312
|
+
let score = 0;
|
|
313
|
+
let ok = true;
|
|
314
|
+
let i = 0;
|
|
315
|
+
for (; i < rp.length; i++) {
|
|
316
|
+
const seg = rp[i];
|
|
317
|
+
if (/^\[\[\.\.\..+\]\]$/.test(seg)) {
|
|
318
|
+
i = rp.length;
|
|
319
|
+
score += 0;
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
if (/^\[\.\.\..+\]$/.test(seg)) {
|
|
323
|
+
if (parts.length <= i)
|
|
324
|
+
ok = false;
|
|
325
|
+
i = rp.length;
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
const p = parts[i];
|
|
329
|
+
if (p === undefined) {
|
|
330
|
+
ok = false;
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
if (/^\[.+\]$/.test(seg))
|
|
334
|
+
score += 1;
|
|
335
|
+
else if (decodeURIComponent(p) === seg)
|
|
336
|
+
score += 10;
|
|
337
|
+
else {
|
|
338
|
+
ok = false;
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
const catchAll = rp.some((s) => s.startsWith('[...') || s.startsWith('[[...'));
|
|
343
|
+
if (ok && !catchAll && parts.length !== rp.length)
|
|
344
|
+
ok = false;
|
|
345
|
+
if (ok && (!best || score > best.score))
|
|
346
|
+
best = { route: r, score };
|
|
347
|
+
}
|
|
348
|
+
return best?.route ?? null;
|
|
349
|
+
}
|
|
350
|
+
//# sourceMappingURL=analyze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../../src/frameworks/nextjs-app/analyze.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RepoReader } from '../../repo/reader.ts';
|
|
2
|
+
import { type Document, type HeadFacts } from '../../html/parse.ts';
|
|
3
|
+
export interface StaticPage {
|
|
4
|
+
readonly route: string;
|
|
5
|
+
readonly file: string;
|
|
6
|
+
readonly doc: Document;
|
|
7
|
+
readonly facts: HeadFacts;
|
|
8
|
+
/** Head values a script on the page may rewrite at runtime. */
|
|
9
|
+
readonly scriptTouches: ReadonlySet<'title' | 'lang' | 'description' | 'robots' | 'canonical'>;
|
|
10
|
+
}
|
|
11
|
+
export interface StaticAnalysis {
|
|
12
|
+
readonly root: string;
|
|
13
|
+
readonly pages: readonly StaticPage[];
|
|
14
|
+
readonly robotsFile: string | null;
|
|
15
|
+
readonly sitemapFiles: readonly string[];
|
|
16
|
+
}
|
|
17
|
+
export declare function findStaticRoot(repo: RepoReader): string | null;
|
|
18
|
+
export declare function analyzeStatic(repo: RepoReader): StaticAnalysis | null;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { headFacts, parseHtml } from "../../html/parse.js";
|
|
2
|
+
export function findStaticRoot(repo) {
|
|
3
|
+
if (repo.has('index.html'))
|
|
4
|
+
return '';
|
|
5
|
+
for (const dir of ['public', 'site', 'docs', 'www'])
|
|
6
|
+
if (repo.has(`${dir}/index.html`))
|
|
7
|
+
return dir;
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
function routeFor(rel) {
|
|
11
|
+
const noExt = rel.replace(/\.html?$/, '');
|
|
12
|
+
if (noExt === 'index')
|
|
13
|
+
return '/';
|
|
14
|
+
if (noExt.endsWith('/index'))
|
|
15
|
+
return `/${noExt.slice(0, -'/index'.length)}`;
|
|
16
|
+
return `/${noExt}`;
|
|
17
|
+
}
|
|
18
|
+
function scriptTouches(doc) {
|
|
19
|
+
const out = new Set();
|
|
20
|
+
for (const el of doc.elements) {
|
|
21
|
+
if (el.name !== 'script')
|
|
22
|
+
continue;
|
|
23
|
+
const body = el.text ?? '';
|
|
24
|
+
if (el.attrs.has('src')) {
|
|
25
|
+
// An external script can do anything to the head; it is not read.
|
|
26
|
+
out.add('title').add('lang').add('description').add('robots').add('canonical');
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (/document\.title\s*=/.test(body))
|
|
30
|
+
out.add('title');
|
|
31
|
+
if (/documentElement\.(lang\s*=|setAttribute\(\s*['"]lang)/.test(body))
|
|
32
|
+
out.add('lang');
|
|
33
|
+
if (/createElement\(\s*['"]meta/.test(body) || /querySelector\([^)]*meta/.test(body))
|
|
34
|
+
out.add('description').add('robots');
|
|
35
|
+
if (/rel\s*=\s*['"]?canonical|['"]canonical['"]/.test(body))
|
|
36
|
+
out.add('canonical');
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
export function analyzeStatic(repo) {
|
|
41
|
+
const root = findStaticRoot(repo);
|
|
42
|
+
if (root === null)
|
|
43
|
+
return null;
|
|
44
|
+
const prefix = root ? `${root}/` : '';
|
|
45
|
+
const pages = [];
|
|
46
|
+
for (const file of repo.files) {
|
|
47
|
+
if (!file.startsWith(prefix) || !/\.html?$/.test(file))
|
|
48
|
+
continue;
|
|
49
|
+
const rel = file.slice(prefix.length);
|
|
50
|
+
if (rel.split('/').some((s) => s.startsWith('_') || s === 'node_modules'))
|
|
51
|
+
continue;
|
|
52
|
+
const src = repo.read(file);
|
|
53
|
+
if (src === null)
|
|
54
|
+
continue;
|
|
55
|
+
const doc = parseHtml(src);
|
|
56
|
+
pages.push({ route: routeFor(rel), file, doc, facts: headFacts(doc), scriptTouches: scriptTouches(doc) });
|
|
57
|
+
}
|
|
58
|
+
pages.sort((a, b) => (a.route < b.route ? -1 : 1));
|
|
59
|
+
return {
|
|
60
|
+
root,
|
|
61
|
+
pages,
|
|
62
|
+
robotsFile: repo.has(`${prefix}robots.txt`) ? `${prefix}robots.txt` : null,
|
|
63
|
+
sitemapFiles: repo.files.filter((f) => f.startsWith(prefix) && /^sitemap[^/]*\.xml$/.test(f.slice(prefix.length))),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=analyze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../../src/frameworks/static/analyze.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export interface Element {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly attrs: ReadonlyMap<string, string>;
|
|
4
|
+
/** Offsets of the start tag in the source, for evidence and patching. */
|
|
5
|
+
readonly start: number;
|
|
6
|
+
readonly end: number;
|
|
7
|
+
/** Text content for raw-text elements (script, style, title, textarea). */
|
|
8
|
+
readonly text?: string;
|
|
9
|
+
readonly inHead: boolean;
|
|
10
|
+
readonly depthInNoscript: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function decodeEntities(text: string): string;
|
|
13
|
+
export interface Document {
|
|
14
|
+
readonly source: string;
|
|
15
|
+
readonly elements: readonly Element[];
|
|
16
|
+
/** Visible text outside script/style, whitespace-collapsed. */
|
|
17
|
+
readonly text: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function parseHtml(source: string): Document;
|
|
20
|
+
export declare function lineOf(source: string, offset: number): number;
|
|
21
|
+
export interface HeadFacts {
|
|
22
|
+
readonly lang: string | null;
|
|
23
|
+
readonly title: string | null;
|
|
24
|
+
readonly description: string | null;
|
|
25
|
+
readonly robots: readonly {
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly content: string;
|
|
28
|
+
}[];
|
|
29
|
+
readonly canonical: readonly string[];
|
|
30
|
+
readonly jsonLd: readonly {
|
|
31
|
+
readonly raw: string;
|
|
32
|
+
readonly offset: number;
|
|
33
|
+
}[];
|
|
34
|
+
readonly links: readonly string[];
|
|
35
|
+
readonly hasMain: boolean;
|
|
36
|
+
}
|
|
37
|
+
export declare function headFacts(doc: Document): HeadFacts;
|
|
38
|
+
export interface Directives {
|
|
39
|
+
/** User agent the directives are scoped to, or `*` for all. */
|
|
40
|
+
readonly agent: string;
|
|
41
|
+
readonly values: ReadonlySet<string>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Parse one robots meta content or X-Robots-Tag header value. A header may be
|
|
45
|
+
* scoped (`googlebot: noindex`); a leading token followed by a colon is an
|
|
46
|
+
* agent unless it is itself a directive name such as `max-snippet`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function parseDirectives(value: string, agent?: string): Directives;
|
|
49
|
+
export declare function blocksIndexing(d: Directives): boolean;
|
|
50
|
+
export declare function restrictsSnippets(d: Directives): boolean;
|