Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

145 lines
3.9 KiB
Go

package resolver
import (
"sort"
"strings"
"github.com/zzet/gortex/internal/graph"
)
// sveltekitLoadVia tags the synthesized page→server-load edges.
const sveltekitLoadVia = "sveltekit_load"
// ResolveSvelteKitLoad pairs a SvelteKit route's page with the server load
// module that feeds it: `+page.svelte` / `+page.ts` and the `+page.server.ts`
// in the same route directory share data through `load()`. This emits a
// tier-tagged edge from the page component to the server load function (or the
// server module file when no explicit `load` is found), so a trace from the
// rendered page reaches its server-side data source — a cross-file dependency a
// file-by-file scanner never connects. Repo-scoped via sameDispatchBoundary.
func ResolveSvelteKitLoad(g graph.Store) int {
if g == nil {
return 0
}
// Per route dir: the page node and the server module file, plus the load
// function declared in the server module.
type routeDir struct {
pageNode *graph.Node
serverFile *graph.Node
serverLoadID string
}
dirs := map[string]*routeDir{}
get := func(dir string) *routeDir {
if dirs[dir] == nil {
dirs[dir] = &routeDir{}
}
return dirs[dir]
}
// First pass over file + component nodes to populate the page / server file.
for n := range g.NodesByKind(graph.KindFile) {
if n == nil {
continue
}
base, dir := pathBaseDir(n.FilePath)
if isSvelteKitServerFile(base) {
get(dir).serverFile = n
}
}
for _, kind := range []graph.NodeKind{graph.KindType, graph.KindFunction} {
for n := range g.NodesByKind(kind) {
if n == nil {
continue
}
base, dir := pathBaseDir(n.FilePath)
switch {
case kind == graph.KindType && isSvelteKitPageFile(base):
// The component node (Meta component=true) is the page.
if c, _ := n.Meta["component"].(bool); c {
get(dir).pageNode = n
}
case kind == graph.KindFunction && isSvelteKitServerFile(base) && n.Name == "load":
get(dir).serverLoadID = n.ID
}
}
}
dirNames := make([]string, 0, len(dirs))
for d := range dirs {
dirNames = append(dirNames, d)
}
sort.Strings(dirNames)
var batch []*graph.Edge
for _, d := range dirNames {
rd := dirs[d]
if rd.pageNode == nil {
continue
}
// Prefer the explicit load function; fall back to the server module file.
to := rd.serverLoadID
var toNode *graph.Node
if to != "" {
toNode = g.GetNode(to)
} else if rd.serverFile != nil {
to = rd.serverFile.ID
toNode = rd.serverFile
}
if to == "" || toNode == nil {
continue
}
if !sameDispatchBoundary(rd.pageNode, toNode) {
continue
}
batch = append(batch, &graph.Edge{
From: rd.pageNode.ID,
To: to,
Kind: graph.EdgeReferences,
FilePath: rd.pageNode.FilePath,
Line: rd.pageNode.StartLine,
Confidence: 0.6,
ConfidenceLabel: graph.ConfidenceLabelFor(graph.EdgeReferences, 0.6),
Origin: graph.OriginASTInferred,
Meta: map[string]any{
"via": sveltekitLoadVia,
MetaSynthesizedBy: SynthSvelteKitLoad,
MetaProvenance: ProvenanceHeuristic,
},
})
}
for _, e := range batch {
g.AddEdge(e)
}
return len(batch)
}
// pathBaseDir splits a slash path into its basename and directory.
func pathBaseDir(p string) (base, dir string) {
p = strings.ReplaceAll(p, "\\", "/")
if i := strings.LastIndexByte(p, '/'); i >= 0 {
return p[i+1:], p[:i]
}
return p, ""
}
// isSvelteKitPageFile reports whether a basename is a SvelteKit page entry.
func isSvelteKitPageFile(base string) bool {
for _, p := range []string{"+page.svelte", "+page.ts", "+page.js"} {
if base == p {
return true
}
}
return false
}
// isSvelteKitServerFile reports whether a basename is a SvelteKit server module.
func isSvelteKitServerFile(base string) bool {
for _, p := range []string{"+page.server.ts", "+page.server.js", "+layout.server.ts", "+layout.server.js"} {
if base == p {
return true
}
}
return false
}