lmgrep 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.
Files changed (51) hide show
  1. package/README.md +181 -0
  2. package/completions/_lmgrep +88 -0
  3. package/dist/chunker/context.d.ts +25 -0
  4. package/dist/chunker/context.js +204 -0
  5. package/dist/chunker/context.js.map +1 -0
  6. package/dist/chunker/index.d.ts +3 -0
  7. package/dist/chunker/index.js +145 -0
  8. package/dist/chunker/index.js.map +1 -0
  9. package/dist/chunker/languages.d.ts +15 -0
  10. package/dist/chunker/languages.js +251 -0
  11. package/dist/chunker/languages.js.map +1 -0
  12. package/dist/cli.d.ts +2 -0
  13. package/dist/cli.js +69 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/config.d.ts +2 -0
  16. package/dist/config.js +31 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/embedder.d.ts +3 -0
  19. package/dist/embedder.js +55 -0
  20. package/dist/embedder.js.map +1 -0
  21. package/dist/index-cmd.d.ts +9 -0
  22. package/dist/index-cmd.js +250 -0
  23. package/dist/index-cmd.js.map +1 -0
  24. package/dist/mcp.d.ts +2 -0
  25. package/dist/mcp.js +80 -0
  26. package/dist/mcp.js.map +1 -0
  27. package/dist/providers.d.ts +1 -0
  28. package/dist/providers.js +43 -0
  29. package/dist/providers.js.map +1 -0
  30. package/dist/repair-cmd.d.ts +5 -0
  31. package/dist/repair-cmd.js +112 -0
  32. package/dist/repair-cmd.js.map +1 -0
  33. package/dist/search-cmd.d.ts +10 -0
  34. package/dist/search-cmd.js +60 -0
  35. package/dist/search-cmd.js.map +1 -0
  36. package/dist/serve-cmd.d.ts +1 -0
  37. package/dist/serve-cmd.js +139 -0
  38. package/dist/serve-cmd.js.map +1 -0
  39. package/dist/status-cmd.d.ts +5 -0
  40. package/dist/status-cmd.js +119 -0
  41. package/dist/status-cmd.js.map +1 -0
  42. package/dist/store.d.ts +25 -0
  43. package/dist/store.js +207 -0
  44. package/dist/store.js.map +1 -0
  45. package/dist/types.d.ts +40 -0
  46. package/dist/types.js +2 -0
  47. package/dist/types.js.map +1 -0
  48. package/dist/walker.d.ts +3 -0
  49. package/dist/walker.js +90 -0
  50. package/dist/walker.js.map +1 -0
  51. package/package.json +57 -0
@@ -0,0 +1,139 @@
1
+ import { watch } from "node:fs";
2
+ import { readFileSync, writeFileSync, unlinkSync, existsSync } from "node:fs";
3
+ import { join, extname } from "node:path";
4
+ import { statSync as fstatSync } from "node:fs";
5
+ import { getDbPath, findIndexedAncestor } from "./store.js";
6
+ import { CODE_EXTENSIONS, DEFAULT_IGNORE } from "./walker.js";
7
+ import { indexCommand } from "./index-cmd.js";
8
+ import ignore from "ignore";
9
+ const DEBOUNCE_MS = 2000;
10
+ function getLockPath(cwd) {
11
+ return `${getDbPath(cwd)}.lock`;
12
+ }
13
+ function isProcessAlive(pid) {
14
+ try {
15
+ process.kill(pid, 0);
16
+ return true;
17
+ }
18
+ catch {
19
+ return false;
20
+ }
21
+ }
22
+ function acquireLock(cwd) {
23
+ const lockPath = getLockPath(cwd);
24
+ if (existsSync(lockPath)) {
25
+ try {
26
+ const pid = Number.parseInt(readFileSync(lockPath, "utf-8").trim(), 10);
27
+ if (isProcessAlive(pid)) {
28
+ return false; // already running
29
+ }
30
+ }
31
+ catch {
32
+ // stale/corrupt lock, take over
33
+ }
34
+ }
35
+ writeFileSync(lockPath, `${process.pid}\n`);
36
+ return true;
37
+ }
38
+ function releaseLock(cwd) {
39
+ try {
40
+ unlinkSync(getLockPath(cwd));
41
+ }
42
+ catch {
43
+ // ignore
44
+ }
45
+ }
46
+ function log(msg) {
47
+ console.log(`[${new Date().toISOString()}] ${msg}`);
48
+ }
49
+ export async function serveCommand(cwd) {
50
+ // Require an existing index
51
+ const ancestor = findIndexedAncestor(cwd);
52
+ if (!ancestor) {
53
+ const dbPath = getDbPath(cwd);
54
+ try {
55
+ fstatSync(dbPath);
56
+ }
57
+ catch {
58
+ console.error("No index found. Run `lmgrep index` first.");
59
+ process.exit(1);
60
+ }
61
+ }
62
+ if (!acquireLock(cwd)) {
63
+ log("Already running for this project.");
64
+ process.exit(0);
65
+ }
66
+ // Clean up lock on exit
67
+ const cleanup = () => releaseLock(cwd);
68
+ process.on("exit", cleanup);
69
+ process.on("SIGINT", () => {
70
+ cleanup();
71
+ process.exit(0);
72
+ });
73
+ process.on("SIGTERM", () => {
74
+ cleanup();
75
+ process.exit(0);
76
+ });
77
+ // Initial index
78
+ log("Running initial index...");
79
+ await indexCommand(cwd, {});
80
+ // Build ignore filter
81
+ const ig = ignore();
82
+ ig.add(DEFAULT_IGNORE);
83
+ const gitignorePath = join(cwd, ".gitignore");
84
+ if (existsSync(gitignorePath)) {
85
+ ig.add(readFileSync(gitignorePath, "utf-8"));
86
+ }
87
+ const lmgrepIgnorePath = join(cwd, ".lmgrepignore");
88
+ if (existsSync(lmgrepIgnorePath)) {
89
+ ig.add(readFileSync(lmgrepIgnorePath, "utf-8"));
90
+ }
91
+ // Watch for changes
92
+ let debounceTimer;
93
+ let indexing = false;
94
+ let pendingReindex = false;
95
+ function scheduleIndex() {
96
+ if (debounceTimer)
97
+ clearTimeout(debounceTimer);
98
+ debounceTimer = setTimeout(async () => {
99
+ if (indexing) {
100
+ pendingReindex = true;
101
+ return;
102
+ }
103
+ indexing = true;
104
+ try {
105
+ log("Changes detected, re-indexing...");
106
+ await indexCommand(cwd, {});
107
+ }
108
+ catch (err) {
109
+ log(`Index error: ${err instanceof Error ? err.message : err}`);
110
+ }
111
+ finally {
112
+ indexing = false;
113
+ if (pendingReindex) {
114
+ pendingReindex = false;
115
+ scheduleIndex();
116
+ }
117
+ }
118
+ }, DEBOUNCE_MS);
119
+ }
120
+ log("Watching for changes...");
121
+ watch(cwd, { recursive: true }, (_event, filename) => {
122
+ if (!filename)
123
+ return;
124
+ // Filter: code extensions only
125
+ const ext = extname(filename);
126
+ if (!CODE_EXTENSIONS.has(ext))
127
+ return;
128
+ // Filter: not ignored
129
+ try {
130
+ if (ig.ignores(filename))
131
+ return;
132
+ }
133
+ catch {
134
+ return;
135
+ }
136
+ scheduleIndex();
137
+ });
138
+ }
139
+ //# sourceMappingURL=serve-cmd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-cmd.js","sourceRoot":"","sources":["../src/serve-cmd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ interface StatusOptions {
2
+ changes?: boolean;
3
+ }
4
+ export declare function statusCommand(cwd: string, opts?: StatusOptions): Promise<void>;
5
+ export {};
@@ -0,0 +1,119 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { loadConfig } from "./config.js";
5
+ import { embedQuery } from "./embedder.js";
6
+ import { findIndexedAncestor, getFileHashes, getIndexedFiles, getIndexedHashes, } from "./store.js";
7
+ import { walkFiles } from "./walker.js";
8
+ export async function statusCommand(cwd, opts = {}) {
9
+ // Resolve project root
10
+ const ancestor = findIndexedAncestor(cwd);
11
+ const projectRoot = ancestor ? ancestor.root : cwd;
12
+ const prefix = ancestor?.prefix || "";
13
+ console.log(`Project root: ${projectRoot}`);
14
+ if (prefix) {
15
+ console.log(`Subdirectory: ${prefix}`);
16
+ }
17
+ // Config
18
+ const config = loadConfig(projectRoot);
19
+ console.log(`Model: ${config.model}`);
20
+ if (config.provider)
21
+ console.log(`Provider: ${config.provider}`);
22
+ if (config.baseURL)
23
+ console.log(`Base URL: ${config.baseURL}`);
24
+ console.log(`Batch size: ${config.batchSize}`);
25
+ if (config.maxTokens)
26
+ console.log(`Max tokens: ${config.maxTokens}`);
27
+ // Index stats
28
+ const files = await getIndexedFiles(projectRoot);
29
+ const hashes = await getIndexedHashes(projectRoot);
30
+ if (files.size === 0) {
31
+ console.log("\nNo index found. Run `lmgrep index` first.");
32
+ return;
33
+ }
34
+ let totalChunks = 0;
35
+ for (const [, h] of files)
36
+ totalChunks += h.length;
37
+ console.log(`\nIndex stats:`);
38
+ console.log(` Files: ${files.size}`);
39
+ console.log(` Chunks: ${totalChunks}`);
40
+ console.log(` Unique hashes: ${hashes.size}`);
41
+ if (totalChunks !== hashes.size) {
42
+ console.log(` Duplicates: ${totalChunks - hashes.size}`);
43
+ }
44
+ // Embedding health check
45
+ console.log(`\nEmbedding check:`);
46
+ try {
47
+ const start = Date.now();
48
+ await embedQuery("test", config);
49
+ const elapsed = Date.now() - start;
50
+ console.log(` OK (${elapsed}ms)`);
51
+ }
52
+ catch (err) {
53
+ console.log(` FAILED: ${err instanceof Error ? err.message : err}`);
54
+ }
55
+ // Changes detection
56
+ if (opts.changes) {
57
+ console.log(`\nScanning for changes...`);
58
+ const storedFileHashes = await getFileHashes(projectRoot);
59
+ const currentFiles = walkFiles(projectRoot);
60
+ const added = [];
61
+ const modified = [];
62
+ const deleted = [];
63
+ const seen = new Set();
64
+ for (const file of currentFiles) {
65
+ seen.add(file);
66
+ try {
67
+ const content = readFileSync(join(projectRoot, file));
68
+ const fileHash = createHash("sha256")
69
+ .update(content)
70
+ .digest("hex")
71
+ .slice(0, 16);
72
+ const stored = storedFileHashes.get(file);
73
+ if (!stored) {
74
+ added.push(file);
75
+ }
76
+ else if (stored !== fileHash) {
77
+ modified.push(file);
78
+ }
79
+ }
80
+ catch {
81
+ // skip unreadable
82
+ }
83
+ }
84
+ for (const [fp] of storedFileHashes) {
85
+ if (!seen.has(fp)) {
86
+ deleted.push(fp);
87
+ }
88
+ }
89
+ const total = added.length + modified.length + deleted.length;
90
+ if (total === 0) {
91
+ console.log(" No changes detected.");
92
+ }
93
+ else {
94
+ if (added.length > 0) {
95
+ console.log(` Added: ${added.length}`);
96
+ for (const f of added.slice(0, 10))
97
+ console.log(` + ${f}`);
98
+ if (added.length > 10)
99
+ console.log(` ... and ${added.length - 10} more`);
100
+ }
101
+ if (modified.length > 0) {
102
+ console.log(` Modified: ${modified.length}`);
103
+ for (const f of modified.slice(0, 10))
104
+ console.log(` ~ ${f}`);
105
+ if (modified.length > 10)
106
+ console.log(` ... and ${modified.length - 10} more`);
107
+ }
108
+ if (deleted.length > 0) {
109
+ console.log(` Deleted: ${deleted.length}`);
110
+ for (const f of deleted.slice(0, 10))
111
+ console.log(` - ${f}`);
112
+ if (deleted.length > 10)
113
+ console.log(` ... and ${deleted.length - 10} more`);
114
+ }
115
+ console.log(`\n Run \`lmgrep index\` to update the index.`);
116
+ }
117
+ }
118
+ }
119
+ //# sourceMappingURL=status-cmd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-cmd.js","sourceRoot":"","sources":["../src/status-cmd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { IndexedChunk, SearchResult } from "./types.js";
2
+ export declare function getDbPath(cwd: string): string;
3
+ /**
4
+ * Find the nearest indexed ancestor directory.
5
+ * Returns { root, prefix } where root is the indexed project dir
6
+ * and prefix is the relative path from root to cwd (e.g. "backend/shared").
7
+ * Returns undefined if no indexed ancestor is found.
8
+ */
9
+ export declare function findIndexedAncestor(cwd: string): {
10
+ root: string;
11
+ prefix: string;
12
+ } | undefined;
13
+ export declare function upsertChunks(chunks: IndexedChunk[], cwd: string): Promise<void>;
14
+ export declare function deleteByFiles(filePaths: string[], cwd: string): Promise<void>;
15
+ export declare function search(queryVector: number[], cwd: string, limit?: number, filePrefix?: string): Promise<SearchResult[]>;
16
+ export declare function getIndexedFiles(cwd: string): Promise<Map<string, string[]>>;
17
+ export declare function getIndexedHashes(cwd: string): Promise<Set<string>>;
18
+ export declare function getFileHashes(cwd: string): Promise<Map<string, string>>;
19
+ export declare function upsertFileHashes(entries: Array<{
20
+ filePath: string;
21
+ fileHash: string;
22
+ }>, cwd: string): Promise<void>;
23
+ export declare function deleteFileHashes(filePaths: string[], cwd: string): Promise<void>;
24
+ export declare function getChunkCount(cwd: string): Promise<number>;
25
+ export declare function resetIndex(cwd: string): Promise<void>;
package/dist/store.js ADDED
@@ -0,0 +1,207 @@
1
+ import { connect } from "@lancedb/lancedb";
2
+ import { createHash } from "node:crypto";
3
+ import { mkdirSync, statSync } from "node:fs";
4
+ import { homedir } from "node:os";
5
+ import { join, resolve } from "node:path";
6
+ const TABLE_NAME = "chunks";
7
+ const FILES_TABLE_NAME = "files";
8
+ let db;
9
+ let table;
10
+ let filesTable;
11
+ export function getDbPath(cwd) {
12
+ const absolute = resolve(cwd);
13
+ const hash = createHash("sha256").update(absolute).digest("hex").slice(0, 6);
14
+ // Use last 2 path segments as a human-readable prefix
15
+ const parts = absolute.split("/").filter(Boolean);
16
+ const slug = parts.slice(-2).join("-").replace(/[^a-zA-Z0-9_-]/g, "_");
17
+ return join(homedir(), ".local", "state", "lmgrep", `${slug}-${hash}`);
18
+ }
19
+ /**
20
+ * Find the nearest indexed ancestor directory.
21
+ * Returns { root, prefix } where root is the indexed project dir
22
+ * and prefix is the relative path from root to cwd (e.g. "backend/shared").
23
+ * Returns undefined if no indexed ancestor is found.
24
+ */
25
+ export function findIndexedAncestor(cwd) {
26
+ const absolute = resolve(cwd);
27
+ let current = absolute;
28
+ while (true) {
29
+ const dbPath = getDbPath(current);
30
+ try {
31
+ const stat = statSync(dbPath);
32
+ if (stat.isDirectory()) {
33
+ const prefix = current === absolute
34
+ ? ""
35
+ : absolute.slice(current.length + 1);
36
+ return { root: current, prefix };
37
+ }
38
+ }
39
+ catch {
40
+ // not found, keep going up
41
+ }
42
+ const parent = resolve(current, "..");
43
+ if (parent === current)
44
+ break;
45
+ current = parent;
46
+ }
47
+ return undefined;
48
+ }
49
+ async function getDb(cwd) {
50
+ if (db)
51
+ return db;
52
+ const dbPath = getDbPath(cwd);
53
+ mkdirSync(dbPath, { recursive: true });
54
+ db = await connect(dbPath);
55
+ return db;
56
+ }
57
+ async function getTable(cwd) {
58
+ if (table)
59
+ return table;
60
+ const connection = await getDb(cwd);
61
+ const tables = await connection.tableNames();
62
+ if (tables.includes(TABLE_NAME)) {
63
+ table = await connection.openTable(TABLE_NAME);
64
+ return table;
65
+ }
66
+ return undefined;
67
+ }
68
+ export async function upsertChunks(chunks, cwd) {
69
+ if (chunks.length === 0)
70
+ return;
71
+ const connection = await getDb(cwd);
72
+ const records = chunks.map((c) => ({
73
+ id: c.id,
74
+ filePath: c.filePath,
75
+ startLine: c.startLine,
76
+ endLine: c.endLine,
77
+ type: c.type,
78
+ name: c.name,
79
+ content: c.content,
80
+ context: c.context,
81
+ hash: c.hash,
82
+ vector: c.vector,
83
+ }));
84
+ const tables = await connection.tableNames();
85
+ if (tables.includes(TABLE_NAME)) {
86
+ table = await connection.openTable(TABLE_NAME);
87
+ await table.add(records);
88
+ }
89
+ else {
90
+ table = await connection.createTable(TABLE_NAME, records);
91
+ }
92
+ }
93
+ export async function deleteByFiles(filePaths, cwd) {
94
+ const t = await getTable(cwd);
95
+ if (!t)
96
+ return;
97
+ for (const fp of filePaths) {
98
+ await t.delete(`filePath = '${fp.replace(/'/g, "''")}'`);
99
+ }
100
+ }
101
+ export async function search(queryVector, cwd, limit = 25, filePrefix) {
102
+ const t = await getTable(cwd);
103
+ if (!t) {
104
+ throw new Error("No index found. Run `lmgrep index` first.");
105
+ }
106
+ let query = t.search(queryVector).limit(limit);
107
+ if (filePrefix) {
108
+ query = query.where(`filePath LIKE '${filePrefix.replace(/'/g, "''")}%'`);
109
+ }
110
+ const results = await query.toArray();
111
+ return results.map((r) => ({
112
+ filePath: r.filePath,
113
+ startLine: r.startLine,
114
+ endLine: r.endLine,
115
+ type: r.type,
116
+ name: r.name,
117
+ content: r.content,
118
+ context: r.context,
119
+ score: r._distance != null ? 1 - r._distance : 0,
120
+ }));
121
+ }
122
+ export async function getIndexedFiles(cwd) {
123
+ const t = await getTable(cwd);
124
+ if (!t)
125
+ return new Map();
126
+ const rows = await t.query().select(["filePath", "hash"]).toArray();
127
+ const fileHashes = new Map();
128
+ for (const row of rows) {
129
+ const fp = row.filePath;
130
+ const hash = row.hash;
131
+ const existing = fileHashes.get(fp) ?? [];
132
+ existing.push(hash);
133
+ fileHashes.set(fp, existing);
134
+ }
135
+ return fileHashes;
136
+ }
137
+ export async function getIndexedHashes(cwd) {
138
+ const t = await getTable(cwd);
139
+ if (!t)
140
+ return new Set();
141
+ const rows = await t.query().select(["hash"]).toArray();
142
+ return new Set(rows.map((r) => r.hash));
143
+ }
144
+ export async function getFileHashes(cwd) {
145
+ const connection = await getDb(cwd);
146
+ const tables = await connection.tableNames();
147
+ if (!tables.includes(FILES_TABLE_NAME))
148
+ return new Map();
149
+ if (!filesTable) {
150
+ filesTable = await connection.openTable(FILES_TABLE_NAME);
151
+ }
152
+ const rows = await filesTable.query().select(["filePath", "fileHash"]).toArray();
153
+ const map = new Map();
154
+ for (const row of rows) {
155
+ map.set(row.filePath, row.fileHash);
156
+ }
157
+ return map;
158
+ }
159
+ export async function upsertFileHashes(entries, cwd) {
160
+ if (entries.length === 0)
161
+ return;
162
+ const connection = await getDb(cwd);
163
+ const tables = await connection.tableNames();
164
+ // LanceDB doesn't support upsert, so delete then re-add
165
+ if (tables.includes(FILES_TABLE_NAME)) {
166
+ filesTable = await connection.openTable(FILES_TABLE_NAME);
167
+ for (const e of entries) {
168
+ await filesTable.delete(`filePath = '${e.filePath.replace(/'/g, "''")}'`);
169
+ }
170
+ await filesTable.add(entries);
171
+ }
172
+ else {
173
+ filesTable = await connection.createTable(FILES_TABLE_NAME, entries);
174
+ }
175
+ }
176
+ export async function deleteFileHashes(filePaths, cwd) {
177
+ const connection = await getDb(cwd);
178
+ const tables = await connection.tableNames();
179
+ if (!tables.includes(FILES_TABLE_NAME))
180
+ return;
181
+ if (!filesTable) {
182
+ filesTable = await connection.openTable(FILES_TABLE_NAME);
183
+ }
184
+ for (const fp of filePaths) {
185
+ await filesTable.delete(`filePath = '${fp.replace(/'/g, "''")}'`);
186
+ }
187
+ }
188
+ export async function getChunkCount(cwd) {
189
+ const t = await getTable(cwd);
190
+ if (!t)
191
+ return 0;
192
+ const rows = await t.query().select(["hash"]).toArray();
193
+ return rows.length;
194
+ }
195
+ export async function resetIndex(cwd) {
196
+ const connection = await getDb(cwd);
197
+ const tables = await connection.tableNames();
198
+ if (tables.includes(TABLE_NAME)) {
199
+ await connection.dropTable(TABLE_NAME);
200
+ }
201
+ if (tables.includes(FILES_TABLE_NAME)) {
202
+ await connection.dropTable(FILES_TABLE_NAME);
203
+ }
204
+ table = undefined;
205
+ filesTable = undefined;
206
+ }
207
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ export interface LmgrepConfig {
2
+ /** Model in "provider:model" format, e.g. "openai:text-embedding-3-small" */
3
+ model: string;
4
+ /** Override the provider package (defaults to "@ai-sdk/<provider>") */
5
+ provider?: string;
6
+ /** Base URL for OpenAI-compatible providers */
7
+ baseURL?: string;
8
+ batchSize: number;
9
+ dimensions?: number;
10
+ /** Prefix prepended to queries at search time (e.g. "search_query: ") */
11
+ queryPrefix?: string;
12
+ /** Prefix prepended to documents at index time (e.g. "search_document: ") */
13
+ documentPrefix?: string;
14
+ /** Max tokens per chunk — chunks exceeding this are skipped (estimated at 4 chars/token) */
15
+ maxTokens?: number;
16
+ }
17
+ export interface Chunk {
18
+ id: string;
19
+ filePath: string;
20
+ startLine: number;
21
+ endLine: number;
22
+ type: string;
23
+ name: string;
24
+ content: string;
25
+ context: string;
26
+ hash: string;
27
+ }
28
+ export interface IndexedChunk extends Chunk {
29
+ vector: number[];
30
+ }
31
+ export interface SearchResult {
32
+ filePath: string;
33
+ startLine: number;
34
+ endLine: number;
35
+ type: string;
36
+ name: string;
37
+ content: string;
38
+ context: string;
39
+ score: number;
40
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export declare const DEFAULT_IGNORE: string[];
2
+ export declare const CODE_EXTENSIONS: Set<string>;
3
+ export declare function walkFiles(cwd: string): string[];
package/dist/walker.js ADDED
@@ -0,0 +1,90 @@
1
+ import { readFileSync, existsSync } from "node:fs";
2
+ import { join, relative } from "node:path";
3
+ import { globSync } from "glob";
4
+ import ignore from "ignore";
5
+ export const DEFAULT_IGNORE = [
6
+ "node_modules",
7
+ ".git",
8
+ "dist",
9
+ "build",
10
+ ".next",
11
+ "__pycache__",
12
+ ".venv",
13
+ "vendor",
14
+ "target",
15
+ ".lmgrep",
16
+ "*.min.js",
17
+ "*.min.css",
18
+ "*.map",
19
+ "*.lock",
20
+ "pnpm-lock.yaml",
21
+ "package-lock.json",
22
+ "yarn.lock",
23
+ "*.png",
24
+ "*.jpg",
25
+ "*.jpeg",
26
+ "*.gif",
27
+ "*.ico",
28
+ "*.woff",
29
+ "*.woff2",
30
+ "*.ttf",
31
+ "*.eot",
32
+ "*.svg",
33
+ "*.zip",
34
+ "*.tar",
35
+ "*.gz",
36
+ "*.bin",
37
+ "*.exe",
38
+ "*.dll",
39
+ "*.so",
40
+ "*.dylib",
41
+ "*.wasm",
42
+ ];
43
+ export const CODE_EXTENSIONS = new Set([
44
+ ".js",
45
+ ".ts",
46
+ ".jsx",
47
+ ".tsx",
48
+ ".py",
49
+ ".rs",
50
+ ".go",
51
+ ".rb",
52
+ ".c",
53
+ ".h",
54
+ ".cpp",
55
+ ".hpp",
56
+ ".cc",
57
+ ".swift",
58
+ ".json",
59
+ ".yaml",
60
+ ".yml",
61
+ ".toml",
62
+ ".lua",
63
+ ".scala",
64
+ ".zig",
65
+ ]);
66
+ export function walkFiles(cwd) {
67
+ const ig = ignore();
68
+ ig.add(DEFAULT_IGNORE);
69
+ const gitignorePath = join(cwd, ".gitignore");
70
+ if (existsSync(gitignorePath)) {
71
+ ig.add(readFileSync(gitignorePath, "utf-8"));
72
+ }
73
+ const lmgrepIgnorePath = join(cwd, ".lmgrepignore");
74
+ if (existsSync(lmgrepIgnorePath)) {
75
+ ig.add(readFileSync(lmgrepIgnorePath, "utf-8"));
76
+ }
77
+ const allFiles = globSync("**/*", {
78
+ cwd,
79
+ nodir: true,
80
+ dot: false,
81
+ });
82
+ return allFiles
83
+ .filter((f) => {
84
+ const ext = f.slice(f.lastIndexOf("."));
85
+ return CODE_EXTENSIONS.has(ext);
86
+ })
87
+ .filter((f) => !ig.ignores(f))
88
+ .map((f) => relative("", f));
89
+ }
90
+ //# sourceMappingURL=walker.js.map