@repo-map/core 0.1.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.
@@ -0,0 +1,20 @@
1
+ import type { ModuleInfo } from "./module-detector.js";
2
+ export type EntryType = "web-route" | "controller" | "service" | "cli-entry" | "job" | "worker" | "unknown-entry";
3
+ export interface EntryInfo {
4
+ path: string;
5
+ type: EntryType;
6
+ }
7
+ export interface ModuleEntries {
8
+ path: string;
9
+ entries: EntryInfo[];
10
+ }
11
+ export interface EntryMap {
12
+ modules: ModuleEntries[];
13
+ }
14
+ export interface EntryDetectorOptions {
15
+ files: Iterable<string>;
16
+ modules: ModuleInfo[];
17
+ includeUnknown?: boolean;
18
+ maxEntriesPerModule?: number;
19
+ }
20
+ export declare const detectEntries: (options: EntryDetectorOptions) => EntryMap;
@@ -0,0 +1,192 @@
1
+ import path from "node:path";
2
+ const CODE_EXTENSIONS = new Set([
3
+ ".js",
4
+ ".jsx",
5
+ ".ts",
6
+ ".tsx",
7
+ ".mjs",
8
+ ".cjs",
9
+ ".mts",
10
+ ".cts",
11
+ ".py",
12
+ ".go"
13
+ ]);
14
+ const WEB_ROUTE_SEGMENTS = new Set([
15
+ "routes",
16
+ "route",
17
+ "router",
18
+ "routing",
19
+ "routers",
20
+ "endpoints",
21
+ "endpoint",
22
+ "pages",
23
+ "api"
24
+ ]);
25
+ const CONTROLLER_SEGMENTS = new Set(["controller", "controllers"]);
26
+ const SERVICE_SEGMENTS = new Set(["service", "services"]);
27
+ const CLI_SEGMENTS = new Set(["cli", "bin", "cmd", "command", "commands"]);
28
+ const WORKER_SEGMENTS = new Set(["worker", "workers", "queue", "queues"]);
29
+ const JOB_SEGMENTS = new Set(["job", "jobs", "cron", "scheduler", "schedule", "task", "tasks"]);
30
+ const TEST_SEGMENTS = new Set([
31
+ "test",
32
+ "tests",
33
+ "__tests__",
34
+ "spec",
35
+ "specs",
36
+ "__specs__",
37
+ "fixture",
38
+ "fixtures",
39
+ "mock",
40
+ "mocks",
41
+ "__mocks__"
42
+ ]);
43
+ const ENTRY_TYPE_ORDER = [
44
+ "web-route",
45
+ "controller",
46
+ "service",
47
+ "cli-entry",
48
+ "worker",
49
+ "job",
50
+ "unknown-entry"
51
+ ];
52
+ const ENTRY_TYPE_RANK = new Map(ENTRY_TYPE_ORDER.map((type, index) => [type, index]));
53
+ const normalizePosixPath = (value) => {
54
+ let normalized = value.replace(/\\/g, "/").trim();
55
+ if (normalized.startsWith("./"))
56
+ normalized = normalized.slice(2);
57
+ while (normalized.endsWith("/") && normalized.length > 1) {
58
+ normalized = normalized.slice(0, -1);
59
+ }
60
+ return normalized.length === 0 ? "." : normalized;
61
+ };
62
+ const compareNames = (left, right) => {
63
+ if (left === right)
64
+ return 0;
65
+ return left < right ? -1 : 1;
66
+ };
67
+ const resolveModuleRoot = (filePath, moduleRoots, cache) => {
68
+ let dir = path.posix.dirname(filePath);
69
+ if (dir === ".")
70
+ dir = ".";
71
+ const visited = [];
72
+ while (true) {
73
+ const cached = cache.get(dir);
74
+ if (cached) {
75
+ for (const entry of visited)
76
+ cache.set(entry, cached);
77
+ return cached;
78
+ }
79
+ visited.push(dir);
80
+ if (moduleRoots.has(dir)) {
81
+ for (const entry of visited)
82
+ cache.set(entry, dir);
83
+ return dir;
84
+ }
85
+ if (dir === ".") {
86
+ for (const entry of visited)
87
+ cache.set(entry, ".");
88
+ return ".";
89
+ }
90
+ dir = path.posix.dirname(dir);
91
+ }
92
+ };
93
+ const hasSegment = (segments, set) => segments.some((segment) => set.has(segment));
94
+ const isTestFile = (segments, baseName) => {
95
+ if (hasSegment(segments, TEST_SEGMENTS))
96
+ return true;
97
+ return baseName.includes(".test") || baseName.includes(".spec");
98
+ };
99
+ const detectEntryType = (filePath) => {
100
+ const ext = path.posix.extname(filePath);
101
+ if (!CODE_EXTENSIONS.has(ext))
102
+ return null;
103
+ const segments = filePath
104
+ .split("/")
105
+ .filter(Boolean)
106
+ .map((segment) => segment.toLowerCase());
107
+ const baseName = path.posix.basename(filePath, ext).toLowerCase();
108
+ if (isTestFile(segments, baseName))
109
+ return null;
110
+ const baseHas = (needle) => baseName.includes(needle);
111
+ const webRouteMatch = hasSegment(segments, WEB_ROUTE_SEGMENTS) ||
112
+ baseHas("route") ||
113
+ baseHas("router") ||
114
+ baseHas("routing");
115
+ if (webRouteMatch)
116
+ return "web-route";
117
+ const controllerMatch = hasSegment(segments, CONTROLLER_SEGMENTS) || baseHas("controller");
118
+ if (controllerMatch)
119
+ return "controller";
120
+ const serviceMatch = hasSegment(segments, SERVICE_SEGMENTS) || baseHas("service");
121
+ if (serviceMatch)
122
+ return "service";
123
+ const cliMatch = hasSegment(segments, CLI_SEGMENTS) ||
124
+ baseHas("cli") ||
125
+ baseName === "main";
126
+ if (cliMatch)
127
+ return "cli-entry";
128
+ const workerMatch = hasSegment(segments, WORKER_SEGMENTS) || baseHas("worker") || baseHas("queue");
129
+ if (workerMatch)
130
+ return "worker";
131
+ const jobMatch = hasSegment(segments, JOB_SEGMENTS) || baseHas("job") || baseHas("cron");
132
+ if (jobMatch)
133
+ return "job";
134
+ return null;
135
+ };
136
+ const addEntry = (map, entryKeys, modulePath, entry, maxEntriesPerModule) => {
137
+ const entries = map.get(modulePath) ?? [];
138
+ if (entries.length >= maxEntriesPerModule)
139
+ return;
140
+ const keySet = entryKeys.get(modulePath) ?? new Set();
141
+ const key = `${entry.type}:${entry.path}`;
142
+ if (keySet.has(key))
143
+ return;
144
+ entries.push(entry);
145
+ keySet.add(key);
146
+ map.set(modulePath, entries);
147
+ entryKeys.set(modulePath, keySet);
148
+ };
149
+ export const detectEntries = (options) => {
150
+ const includeUnknown = options.includeUnknown ?? true;
151
+ const maxEntriesPerModule = options.maxEntriesPerModule ?? 200;
152
+ const files = Array.isArray(options.files)
153
+ ? options.files.map(normalizePosixPath)
154
+ : Array.from(options.files, normalizePosixPath);
155
+ const moduleRoots = new Set(options.modules.map((module) => normalizePosixPath(module.path)));
156
+ if (!moduleRoots.has("."))
157
+ moduleRoots.add(".");
158
+ const moduleMap = new Map();
159
+ const entryKeys = new Map();
160
+ const dirCache = new Map();
161
+ for (const filePath of files) {
162
+ if (!filePath || filePath === ".")
163
+ continue;
164
+ const entryType = detectEntryType(filePath);
165
+ if (!entryType)
166
+ continue;
167
+ const moduleRoot = resolveModuleRoot(filePath, moduleRoots, dirCache);
168
+ addEntry(moduleMap, entryKeys, moduleRoot, { path: filePath, type: entryType }, maxEntriesPerModule);
169
+ }
170
+ const modules = Array.from(moduleRoots).sort(compareNames);
171
+ const entries = [];
172
+ for (const modulePath of modules) {
173
+ const moduleEntries = moduleMap.get(modulePath) ?? [];
174
+ moduleEntries.sort((a, b) => {
175
+ const rankA = ENTRY_TYPE_RANK.get(a.type) ?? 999;
176
+ const rankB = ENTRY_TYPE_RANK.get(b.type) ?? 999;
177
+ if (rankA !== rankB)
178
+ return rankA - rankB;
179
+ return compareNames(a.path, b.path);
180
+ });
181
+ if (moduleEntries.length === 0 && includeUnknown) {
182
+ entries.push({
183
+ path: modulePath,
184
+ entries: [{ path: "", type: "unknown-entry" }]
185
+ });
186
+ continue;
187
+ }
188
+ entries.push({ path: modulePath, entries: moduleEntries });
189
+ }
190
+ return { modules: entries };
191
+ };
192
+ //# sourceMappingURL=entry-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry-detector.js","sourceRoot":"","sources":["../src/entry-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { HashAlgorithm } from "./meta.js";
2
+ export interface FileIndexEntry {
3
+ path: string;
4
+ size: number;
5
+ mtimeMs: number;
6
+ hash: string | null;
7
+ }
8
+ export interface FileIndex {
9
+ repoRoot: string;
10
+ hashAlgorithm: HashAlgorithm;
11
+ files: FileIndexEntry[];
12
+ }
13
+ export interface FileChangeSet {
14
+ hashAlgorithm: HashAlgorithm;
15
+ added: string[];
16
+ modified: string[];
17
+ deleted: string[];
18
+ }
19
+ export interface BuildFileIndexOptions {
20
+ repoRoot: string;
21
+ files: Iterable<string>;
22
+ hashAlgorithm?: HashAlgorithm;
23
+ concurrency?: number;
24
+ onError?: (err: NodeJS.ErrnoException, path: string) => void;
25
+ }
26
+ export declare const buildFileIndex: (options: BuildFileIndexOptions) => Promise<FileIndex>;
27
+ export declare const diffFileIndex: (previous: FileIndex, current: FileIndex) => FileChangeSet;
@@ -0,0 +1,132 @@
1
+ import path from "node:path";
2
+ import * as fs from "node:fs/promises";
3
+ import { createReadStream } from "node:fs";
4
+ import { createHash } from "node:crypto";
5
+ const DEFAULT_CONCURRENCY = 8;
6
+ const compareNames = (left, right) => {
7
+ if (left === right)
8
+ return 0;
9
+ return left < right ? -1 : 1;
10
+ };
11
+ const normalizePosixPath = (value) => {
12
+ let normalized = value.replace(/\\/g, "/").trim();
13
+ if (normalized.startsWith("./"))
14
+ normalized = normalized.slice(2);
15
+ while (normalized.endsWith("/") && normalized.length > 1) {
16
+ normalized = normalized.slice(0, -1);
17
+ }
18
+ return normalized.length === 0 ? "." : normalized;
19
+ };
20
+ const reportError = (err, targetPath, onError) => {
21
+ if (!onError)
22
+ return;
23
+ const error = err;
24
+ if (error?.code === "ENOENT")
25
+ return;
26
+ onError(error, targetPath);
27
+ };
28
+ const resolveAbsPath = (repoRoot, filePath) => {
29
+ const segments = filePath === "." ? [] : filePath.split("/");
30
+ return path.resolve(repoRoot, ...segments);
31
+ };
32
+ const hashFile = (absPath, algorithm, onError) => new Promise((resolve) => {
33
+ const hash = createHash(algorithm);
34
+ const stream = createReadStream(absPath);
35
+ stream.on("data", (chunk) => hash.update(chunk));
36
+ stream.on("error", (err) => {
37
+ reportError(err, absPath, onError);
38
+ resolve(null);
39
+ });
40
+ stream.on("end", () => {
41
+ resolve(hash.digest("hex"));
42
+ });
43
+ });
44
+ const buildEntry = async (repoRoot, filePath, algorithm, onError) => {
45
+ const absPath = resolveAbsPath(repoRoot, filePath);
46
+ try {
47
+ const stats = await fs.stat(absPath);
48
+ const hash = await hashFile(absPath, algorithm, onError);
49
+ return {
50
+ path: filePath,
51
+ size: stats.size,
52
+ mtimeMs: stats.mtimeMs,
53
+ hash
54
+ };
55
+ }
56
+ catch (err) {
57
+ reportError(err, absPath, onError);
58
+ return null;
59
+ }
60
+ };
61
+ export const buildFileIndex = async (options) => {
62
+ const repoRoot = path.resolve(options.repoRoot);
63
+ const hashAlgorithm = options.hashAlgorithm ?? "sha256";
64
+ const concurrency = Math.max(1, options.concurrency ?? DEFAULT_CONCURRENCY);
65
+ const files = Array.isArray(options.files)
66
+ ? options.files.map(normalizePosixPath)
67
+ : Array.from(options.files, normalizePosixPath);
68
+ const onError = options.onError;
69
+ const entries = [];
70
+ let index = 0;
71
+ const worker = async () => {
72
+ while (true) {
73
+ const current = index;
74
+ index += 1;
75
+ if (current >= files.length)
76
+ break;
77
+ const filePath = files[current];
78
+ if (!filePath || filePath === ".")
79
+ continue;
80
+ const entry = await buildEntry(repoRoot, filePath, hashAlgorithm, onError);
81
+ if (entry)
82
+ entries.push(entry);
83
+ }
84
+ };
85
+ const workers = Array.from({ length: Math.min(concurrency, files.length) }, () => worker());
86
+ await Promise.all(workers);
87
+ entries.sort((a, b) => compareNames(a.path, b.path));
88
+ return {
89
+ repoRoot,
90
+ hashAlgorithm,
91
+ files: entries
92
+ };
93
+ };
94
+ const entryChanged = (prev, next, useHash) => {
95
+ if (useHash && prev.hash && next.hash) {
96
+ return prev.hash !== next.hash;
97
+ }
98
+ return prev.size !== next.size || prev.mtimeMs !== next.mtimeMs;
99
+ };
100
+ export const diffFileIndex = (previous, current) => {
101
+ const prevMap = new Map(previous.files.map((entry) => [entry.path, entry]));
102
+ const nextMap = new Map(current.files.map((entry) => [entry.path, entry]));
103
+ const useHash = previous.hashAlgorithm === current.hashAlgorithm;
104
+ const added = [];
105
+ const modified = [];
106
+ const deleted = [];
107
+ for (const entry of current.files) {
108
+ const prevEntry = prevMap.get(entry.path);
109
+ if (!prevEntry) {
110
+ added.push(entry.path);
111
+ continue;
112
+ }
113
+ if (entryChanged(prevEntry, entry, useHash)) {
114
+ modified.push(entry.path);
115
+ }
116
+ }
117
+ for (const entry of previous.files) {
118
+ if (!nextMap.has(entry.path)) {
119
+ deleted.push(entry.path);
120
+ }
121
+ }
122
+ added.sort(compareNames);
123
+ modified.sort(compareNames);
124
+ deleted.sort(compareNames);
125
+ return {
126
+ hashAlgorithm: current.hashAlgorithm,
127
+ added,
128
+ modified,
129
+ deleted
130
+ };
131
+ };
132
+ //# sourceMappingURL=file-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-index.js","sourceRoot":"","sources":["../src/file-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export * from "./meta.js";
2
+ export * from "./walker.js";
3
+ export * from "./module-detector.js";
4
+ export * from "./keyword-extractor.js";
5
+ export * from "./module-index.js";
6
+ export * from "./entry-detector.js";
7
+ export * from "./summary.js";
8
+ export * from "./file-index.js";
9
+ export * from "./query.js";
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export * from "./meta.js";
2
+ export * from "./walker.js";
3
+ export * from "./module-detector.js";
4
+ export * from "./keyword-extractor.js";
5
+ export * from "./module-index.js";
6
+ export * from "./entry-detector.js";
7
+ export * from "./summary.js";
8
+ export * from "./file-index.js";
9
+ export * from "./query.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ModuleInfo } from "./module-detector.js";
2
+ export interface ModuleKeywords {
3
+ path: string;
4
+ keywords: string[];
5
+ }
6
+ export interface KeywordExtractorOptions {
7
+ repoRoot: string;
8
+ files: Iterable<string>;
9
+ modules: ModuleInfo[];
10
+ includeModules?: string[] | Set<string>;
11
+ minKeywords?: number;
12
+ maxKeywords?: number;
13
+ maxContentBytes?: number;
14
+ maxContentFiles?: number;
15
+ includeFileNames?: boolean;
16
+ includeExports?: boolean;
17
+ includeRoutes?: boolean;
18
+ includeInterfaces?: boolean;
19
+ onError?: (err: NodeJS.ErrnoException, path: string) => void;
20
+ }
21
+ export declare function extractModuleKeywords(options: KeywordExtractorOptions): Promise<ModuleKeywords[]>;