fln 1.0.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 (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +330 -0
  3. package/dist/api/fln.d.ts +3 -0
  4. package/dist/api/fln.d.ts.map +1 -0
  5. package/dist/api/fln.js +71 -0
  6. package/dist/api/index.d.ts +3 -0
  7. package/dist/api/index.d.ts.map +1 -0
  8. package/dist/api/index.js +2 -0
  9. package/dist/api/types.d.ts +34 -0
  10. package/dist/api/types.d.ts.map +1 -0
  11. package/dist/api/types.js +1 -0
  12. package/dist/cli/commandLine.d.ts +2 -0
  13. package/dist/cli/commandLine.d.ts.map +1 -0
  14. package/dist/cli/commandLine.js +120 -0
  15. package/dist/cli/help.d.ts +2 -0
  16. package/dist/cli/help.d.ts.map +1 -0
  17. package/dist/cli/help.js +40 -0
  18. package/dist/cli/index.d.ts +2 -0
  19. package/dist/cli/index.d.ts.map +1 -0
  20. package/dist/cli/index.js +1 -0
  21. package/dist/cli/main.d.ts +3 -0
  22. package/dist/cli/main.d.ts.map +1 -0
  23. package/dist/cli/main.js +9 -0
  24. package/dist/cli/output/components/breakdown.d.ts +2 -0
  25. package/dist/cli/output/components/breakdown.d.ts.map +1 -0
  26. package/dist/cli/output/components/breakdown.js +21 -0
  27. package/dist/cli/output/components/errors.d.ts +6 -0
  28. package/dist/cli/output/components/errors.d.ts.map +1 -0
  29. package/dist/cli/output/components/errors.js +13 -0
  30. package/dist/cli/output/components/progressBar.d.ts +7 -0
  31. package/dist/cli/output/components/progressBar.d.ts.map +1 -0
  32. package/dist/cli/output/components/progressBar.js +38 -0
  33. package/dist/cli/output/components/summary.d.ts +8 -0
  34. package/dist/cli/output/components/summary.d.ts.map +1 -0
  35. package/dist/cli/output/components/summary.js +12 -0
  36. package/dist/cli/output/components/warnings.d.ts +6 -0
  37. package/dist/cli/output/components/warnings.d.ts.map +1 -0
  38. package/dist/cli/output/components/warnings.js +11 -0
  39. package/dist/cli/output/formatter.d.ts +5 -0
  40. package/dist/cli/output/formatter.d.ts.map +1 -0
  41. package/dist/cli/output/formatter.js +28 -0
  42. package/dist/cli/output/index.d.ts +8 -0
  43. package/dist/cli/output/index.d.ts.map +1 -0
  44. package/dist/cli/output/index.js +4 -0
  45. package/dist/cli/output/renderer.d.ts +21 -0
  46. package/dist/cli/output/renderer.d.ts.map +1 -0
  47. package/dist/cli/output/renderer.js +121 -0
  48. package/dist/cli/output/styles.d.ts +23 -0
  49. package/dist/cli/output/styles.d.ts.map +1 -0
  50. package/dist/cli/output/styles.js +26 -0
  51. package/dist/config/defaults.d.ts +3 -0
  52. package/dist/config/defaults.d.ts.map +1 -0
  53. package/dist/config/defaults.js +2 -0
  54. package/dist/config/index.d.ts +6 -0
  55. package/dist/config/index.d.ts.map +1 -0
  56. package/dist/config/index.js +5 -0
  57. package/dist/config/loader.d.ts +3 -0
  58. package/dist/config/loader.d.ts.map +1 -0
  59. package/dist/config/loader.js +11 -0
  60. package/dist/config/resolver.d.ts +8 -0
  61. package/dist/config/resolver.d.ts.map +1 -0
  62. package/dist/config/resolver.js +66 -0
  63. package/dist/config/types.d.ts +40 -0
  64. package/dist/config/types.d.ts.map +1 -0
  65. package/dist/config/types.js +1 -0
  66. package/dist/config/utils.d.ts +7 -0
  67. package/dist/config/utils.d.ts.map +1 -0
  68. package/dist/config/utils.js +161 -0
  69. package/dist/core/ignoreMatcher.d.ts +15 -0
  70. package/dist/core/ignoreMatcher.d.ts.map +1 -0
  71. package/dist/core/ignoreMatcher.js +97 -0
  72. package/dist/core/index.d.ts +8 -0
  73. package/dist/core/index.d.ts.map +1 -0
  74. package/dist/core/index.js +7 -0
  75. package/dist/core/renderOutput.d.ts +4 -0
  76. package/dist/core/renderOutput.d.ts.map +1 -0
  77. package/dist/core/renderOutput.js +218 -0
  78. package/dist/core/renderTree.d.ts +3 -0
  79. package/dist/core/renderTree.d.ts.map +1 -0
  80. package/dist/core/renderTree.js +23 -0
  81. package/dist/core/scanTree.d.ts +4 -0
  82. package/dist/core/scanTree.d.ts.map +1 -0
  83. package/dist/core/scanTree.js +348 -0
  84. package/dist/core/size.d.ts +4 -0
  85. package/dist/core/size.d.ts.map +1 -0
  86. package/dist/core/size.js +32 -0
  87. package/dist/core/statsCollector.d.ts +4 -0
  88. package/dist/core/statsCollector.d.ts.map +1 -0
  89. package/dist/core/statsCollector.js +28 -0
  90. package/dist/core/types.d.ts +53 -0
  91. package/dist/core/types.d.ts.map +1 -0
  92. package/dist/core/types.js +1 -0
  93. package/dist/index.d.ts +4 -0
  94. package/dist/index.d.ts.map +1 -0
  95. package/dist/index.js +3 -0
  96. package/dist/infra/countTokens.d.ts +2 -0
  97. package/dist/infra/countTokens.d.ts.map +1 -0
  98. package/dist/infra/countTokens.js +186 -0
  99. package/dist/infra/datetime.d.ts +3 -0
  100. package/dist/infra/datetime.d.ts.map +1 -0
  101. package/dist/infra/datetime.js +15 -0
  102. package/dist/infra/index.d.ts +7 -0
  103. package/dist/infra/index.d.ts.map +1 -0
  104. package/dist/infra/index.js +6 -0
  105. package/dist/infra/logger.d.ts +19 -0
  106. package/dist/infra/logger.d.ts.map +1 -0
  107. package/dist/infra/logger.js +99 -0
  108. package/dist/infra/outputWriter.d.ts +15 -0
  109. package/dist/infra/outputWriter.d.ts.map +1 -0
  110. package/dist/infra/outputWriter.js +35 -0
  111. package/dist/infra/terminal.d.ts +91 -0
  112. package/dist/infra/terminal.d.ts.map +1 -0
  113. package/dist/infra/terminal.js +189 -0
  114. package/dist/infra/usageTracker.d.ts +3 -0
  115. package/dist/infra/usageTracker.d.ts.map +1 -0
  116. package/dist/infra/usageTracker.js +39 -0
  117. package/dist/version.d.ts +2 -0
  118. package/dist/version.d.ts.map +1 -0
  119. package/dist/version.js +1 -0
  120. package/package.json +79 -0
@@ -0,0 +1,348 @@
1
+ import { lstat, open, readdir, readlink, realpath, stat } from "node:fs/promises";
2
+ import { cpus } from "node:os";
3
+ import { relative, sep } from "node:path";
4
+ import ignore from "ignore";
5
+ import { IgnoreMatcher } from "./ignoreMatcher";
6
+ function normalizePathSegment(pathSegment) {
7
+ if (sep === "/")
8
+ return pathSegment;
9
+ return pathSegment.split(sep).join("/");
10
+ }
11
+ function getFileScore(fileName) {
12
+ const lowerName = fileName.toLowerCase();
13
+ if (lowerName.startsWith("readme"))
14
+ return 0;
15
+ if (lowerName === "package.json" ||
16
+ lowerName.startsWith("tsconfig") ||
17
+ lowerName === "pyproject.toml" ||
18
+ lowerName === "cargo.toml" ||
19
+ lowerName === "go.mod" ||
20
+ lowerName === "cmakelists.txt" ||
21
+ lowerName === "makefile" ||
22
+ lowerName === "dockerfile" ||
23
+ lowerName === "vcpkg.json" ||
24
+ lowerName.startsWith(".env") ||
25
+ lowerName.includes(".config.") ||
26
+ lowerName.startsWith(".prettier") ||
27
+ lowerName.startsWith(".eslintrc"))
28
+ return 1;
29
+ if (lowerName.startsWith("index.") ||
30
+ lowerName.startsWith("main.") ||
31
+ lowerName.startsWith("app.") ||
32
+ lowerName.startsWith("server.") ||
33
+ lowerName.startsWith("mod.") ||
34
+ lowerName.startsWith("lib."))
35
+ return 2;
36
+ if (lowerName.includes("types") ||
37
+ lowerName.includes("interface") ||
38
+ lowerName.includes("schema") ||
39
+ lowerName.includes("config") ||
40
+ lowerName.includes("constants") ||
41
+ lowerName.endsWith(".d.ts") ||
42
+ lowerName.endsWith(".h") ||
43
+ lowerName.endsWith(".hpp"))
44
+ return 3;
45
+ if (lowerName.startsWith("license") ||
46
+ lowerName.startsWith("changelog") ||
47
+ lowerName.startsWith("contributing") ||
48
+ lowerName.startsWith("code_of_conduct") ||
49
+ lowerName.startsWith("security"))
50
+ return 15;
51
+ if (lowerName.includes(".test.") ||
52
+ lowerName.includes(".spec.") ||
53
+ lowerName.startsWith("test_") ||
54
+ lowerName.endsWith("_test.go"))
55
+ return 20;
56
+ return 10;
57
+ }
58
+ async function isBinaryFile(filePath, fileSize) {
59
+ if (fileSize === 0)
60
+ return false;
61
+ const handle = await open(filePath, "r");
62
+ try {
63
+ const buffer = Buffer.alloc(Math.min(512, fileSize));
64
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
65
+ for (let index = 0; index < bytesRead; index++)
66
+ if (buffer[index] === 0)
67
+ return true;
68
+ return false;
69
+ }
70
+ finally {
71
+ await handle.close();
72
+ }
73
+ }
74
+ async function isGeneratedFile(filePath, fileSize) {
75
+ if (fileSize === 0)
76
+ return false;
77
+ const handle = await open(filePath, "r");
78
+ try {
79
+ const buffer = Buffer.alloc(Math.min(100, fileSize));
80
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
81
+ const content = buffer.toString("utf8", 0, bytesRead);
82
+ return content.includes("<!-- 🥞 fln");
83
+ }
84
+ catch {
85
+ return false;
86
+ }
87
+ finally {
88
+ await handle.close();
89
+ }
90
+ }
91
+ export async function scanTree(options, logger) {
92
+ const stats = {
93
+ files: 0,
94
+ directories: 0,
95
+ binary: 0,
96
+ skipped: 0,
97
+ errors: 0,
98
+ totalSizeBytes: 0,
99
+ outputSizeBytes: 0,
100
+ outputTokenCount: 0
101
+ };
102
+ const ignoreMatcher = new IgnoreMatcher({
103
+ rootDirectory: options.rootDirectory,
104
+ excludePatterns: options.excludePatterns,
105
+ useGitignore: options.useGitignore,
106
+ logger
107
+ });
108
+ const includeMatcher = ignore().add(options.includePatterns);
109
+ const concurrencyLimit = Math.max(8, Math.min(64, cpus().length * 4));
110
+ const excludedPathSet = new Set(options.excludedPaths.map(pathItem => normalizePathSegment(pathItem)));
111
+ const visitedRealPaths = new Set();
112
+ let processedItems = 0;
113
+ let totalEstimate = 0;
114
+ if (options.followSymlinks)
115
+ try {
116
+ const rootRealPath = await realpath(options.rootDirectory);
117
+ visitedRealPaths.add(rootRealPath);
118
+ }
119
+ catch {
120
+ logger.debug("Failed to resolve root real path.");
121
+ }
122
+ const rootNode = await scanEntry(options.rootDirectory, "");
123
+ if (!rootNode || rootNode.type !== "directory")
124
+ throw new Error("Root directory is empty or all files were excluded.");
125
+ return { projectName: options.projectName, root: rootNode, stats };
126
+ async function scanEntry(currentPath, relativePath, dirent) {
127
+ const normalizedRelativePath = normalizePathSegment(relativePath);
128
+ const name = dirent?.name ?? currentPath.split(sep).pop() ?? "";
129
+ if (normalizedRelativePath !== "" && excludedPathSet.has(normalizedRelativePath))
130
+ return undefined;
131
+ const isExplicitlyIncluded = normalizedRelativePath !== "" && includeMatcher.ignores(normalizedRelativePath);
132
+ if (!isExplicitlyIncluded && normalizedRelativePath !== "" && ignoreMatcher.ignores(normalizedRelativePath))
133
+ return undefined;
134
+ if (!options.includeHidden && name.startsWith(".") && name !== ".")
135
+ return undefined;
136
+ try {
137
+ let symlinkTarget;
138
+ const isSymlink = dirent ? dirent.isSymbolicLink() : undefined;
139
+ if (isSymlink) {
140
+ symlinkTarget = await readlink(currentPath);
141
+ if (!options.followSymlinks)
142
+ return {
143
+ name,
144
+ path: normalizedRelativePath,
145
+ type: "symlink",
146
+ size: 0,
147
+ target: symlinkTarget
148
+ };
149
+ const resolvedPath = await realpath(currentPath);
150
+ if (visitedRealPaths.has(resolvedPath)) {
151
+ stats.skipped++;
152
+ return {
153
+ name,
154
+ path: normalizedRelativePath,
155
+ type: "symlink",
156
+ size: 0,
157
+ target: symlinkTarget,
158
+ skipReason: "symlinkCycle"
159
+ };
160
+ }
161
+ visitedRealPaths.add(resolvedPath);
162
+ const statsResult = await stat(currentPath);
163
+ if (statsResult.isFile())
164
+ return await buildFileNode({
165
+ currentPath,
166
+ normalizedRelativePath,
167
+ name,
168
+ fileSize: statsResult.size,
169
+ symlinkTarget,
170
+ isExplicitlyIncluded
171
+ });
172
+ if (statsResult.isDirectory())
173
+ return await buildDirectoryNode({
174
+ currentPath,
175
+ normalizedRelativePath,
176
+ name,
177
+ symlinkTarget
178
+ });
179
+ return undefined;
180
+ }
181
+ if (dirent?.isDirectory())
182
+ return await buildDirectoryNode({
183
+ currentPath,
184
+ normalizedRelativePath,
185
+ name
186
+ });
187
+ if (dirent?.isFile()) {
188
+ const statsResult = await stat(currentPath);
189
+ return await buildFileNode({
190
+ currentPath,
191
+ normalizedRelativePath,
192
+ name,
193
+ fileSize: statsResult.size,
194
+ isExplicitlyIncluded
195
+ });
196
+ }
197
+ if (dirent)
198
+ return undefined;
199
+ const entryStats = await lstat(currentPath);
200
+ if (entryStats.isSymbolicLink()) {
201
+ symlinkTarget = await readlink(currentPath);
202
+ if (!options.followSymlinks)
203
+ return {
204
+ name,
205
+ path: normalizedRelativePath,
206
+ type: "symlink",
207
+ size: 0,
208
+ target: symlinkTarget
209
+ };
210
+ const resolvedPath = await realpath(currentPath);
211
+ if (visitedRealPaths.has(resolvedPath)) {
212
+ stats.skipped++;
213
+ return {
214
+ name,
215
+ path: normalizedRelativePath,
216
+ type: "symlink",
217
+ size: 0,
218
+ target: symlinkTarget,
219
+ skipReason: "symlinkCycle"
220
+ };
221
+ }
222
+ visitedRealPaths.add(resolvedPath);
223
+ }
224
+ const statsResult = options.followSymlinks ? await stat(currentPath) : entryStats;
225
+ if (statsResult.isFile())
226
+ return await buildFileNode({
227
+ currentPath,
228
+ normalizedRelativePath,
229
+ name,
230
+ fileSize: statsResult.size,
231
+ symlinkTarget,
232
+ isExplicitlyIncluded
233
+ });
234
+ if (statsResult.isDirectory())
235
+ return await buildDirectoryNode({
236
+ currentPath,
237
+ normalizedRelativePath,
238
+ name,
239
+ symlinkTarget
240
+ });
241
+ }
242
+ catch (error) {
243
+ stats.errors++;
244
+ logger.warn(`Failed to access ${normalizedRelativePath || "."}: ${String(error)}`);
245
+ }
246
+ return undefined;
247
+ }
248
+ async function buildFileNode(input) {
249
+ stats.files++;
250
+ stats.totalSizeBytes += input.fileSize;
251
+ processedItems++;
252
+ if (totalEstimate === 0)
253
+ totalEstimate = Math.max(processedItems + 50, 100);
254
+ if (options.onProgress)
255
+ options.onProgress(processedItems, Math.max(totalEstimate, processedItems));
256
+ let skipReason;
257
+ if (!input.isExplicitlyIncluded && await isGeneratedFile(input.currentPath, input.fileSize))
258
+ skipReason = "generated";
259
+ if (!skipReason && input.fileSize > options.maximumFileSizeBytes)
260
+ skipReason = "tooLarge";
261
+ let isBinary = false;
262
+ if (!skipReason)
263
+ try {
264
+ isBinary = await isBinaryFile(input.currentPath, input.fileSize);
265
+ }
266
+ catch (error) {
267
+ stats.errors++;
268
+ skipReason = "readError";
269
+ logger.warn(`Failed to read ${input.normalizedRelativePath || "."}: ${String(error)}`);
270
+ }
271
+ if (isBinary)
272
+ stats.binary++;
273
+ if (skipReason) {
274
+ stats.skipped++;
275
+ return {
276
+ name: input.name,
277
+ path: input.normalizedRelativePath,
278
+ type: "file",
279
+ size: input.fileSize,
280
+ isBinary,
281
+ target: input.symlinkTarget,
282
+ skipReason
283
+ };
284
+ }
285
+ return {
286
+ name: input.name,
287
+ path: input.normalizedRelativePath,
288
+ type: "file",
289
+ size: input.fileSize,
290
+ isBinary,
291
+ target: input.symlinkTarget
292
+ };
293
+ }
294
+ async function buildDirectoryNode(input) {
295
+ stats.directories++;
296
+ await ignoreMatcher.addGitignoreForDirectory(input.currentPath);
297
+ const entries = await readdir(input.currentPath, { withFileTypes: true });
298
+ totalEstimate = Math.max(totalEstimate, processedItems + entries.length);
299
+ const children = (await mapWithConcurrency(entries, concurrencyLimit, async (entry) => {
300
+ const childPath = `${input.currentPath}${sep}${entry.name}`;
301
+ const childRelativePath = relative(options.rootDirectory, childPath);
302
+ return scanEntry(childPath, childRelativePath, entry);
303
+ }))
304
+ .filter((node) => node !== undefined)
305
+ .sort((left, right) => {
306
+ if (left.type !== right.type)
307
+ return left.type === "directory" ? 1 : -1;
308
+ if (left.type === "file" && right.type === "file") {
309
+ const scoreA = getFileScore(left.name);
310
+ const scoreB = getFileScore(right.name);
311
+ if (scoreA !== scoreB)
312
+ return scoreA - scoreB;
313
+ }
314
+ return left.name.localeCompare(right.name, undefined, { numeric: true, sensitivity: "base" });
315
+ });
316
+ return {
317
+ name: input.name,
318
+ path: input.normalizedRelativePath,
319
+ type: "directory",
320
+ size: 0,
321
+ children,
322
+ target: input.symlinkTarget
323
+ };
324
+ }
325
+ }
326
+ async function mapWithConcurrency(items, concurrency, mapper) {
327
+ if (items.length === 0)
328
+ return [];
329
+ const limit = Math.max(1, Math.min(concurrency, items.length));
330
+ if (limit === 1) {
331
+ const results = [];
332
+ for (const item of items)
333
+ results.push(await mapper(item));
334
+ return results;
335
+ }
336
+ const results = new Array(items.length);
337
+ let nextIndex = 0;
338
+ const workers = Array.from({ length: limit }, async () => {
339
+ while (true) {
340
+ const currentIndex = nextIndex++;
341
+ if (currentIndex >= items.length)
342
+ return;
343
+ results[currentIndex] = await mapper(items[currentIndex]);
344
+ }
345
+ });
346
+ await Promise.all(workers);
347
+ return results;
348
+ }
@@ -0,0 +1,4 @@
1
+ export declare function parseByteSize(input: string): number;
2
+ export declare function formatByteSize(sizeBytes: number): string;
3
+ export declare function formatTokenCount(count: number): string;
4
+ //# sourceMappingURL=size.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"size.d.ts","sourceRoot":"","sources":["../../src/core/size.ts"],"names":[],"mappings":"AAIA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgBnD;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CASxD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOtD"}
@@ -0,0 +1,32 @@
1
+ const kibibyte = 1024;
2
+ const mebibyte = kibibyte * 1024;
3
+ const gibibyte = mebibyte * 1024;
4
+ export function parseByteSize(input) {
5
+ const normalizedInput = input.trim().toLowerCase();
6
+ const match = normalizedInput.match(/^(\d+(?:\.\d+)?)\s*(b|kb|mb|gb)?$/);
7
+ if (!match)
8
+ throw new Error(`Invalid size: "${input}"`);
9
+ const value = Number(match[1]);
10
+ const unit = match[2] ?? "b";
11
+ const multiplier = unit === "kb" ? kibibyte :
12
+ unit === "mb" ? mebibyte :
13
+ unit === "gb" ? gibibyte :
14
+ 1;
15
+ return Math.floor(value * multiplier);
16
+ }
17
+ export function formatByteSize(sizeBytes) {
18
+ if (sizeBytes >= gibibyte)
19
+ return `${(sizeBytes / gibibyte).toFixed(2)} GB`;
20
+ if (sizeBytes >= mebibyte)
21
+ return `${(sizeBytes / mebibyte).toFixed(2)} MB`;
22
+ if (sizeBytes >= kibibyte)
23
+ return `${(sizeBytes / kibibyte).toFixed(2)} KB`;
24
+ return `${sizeBytes} B`;
25
+ }
26
+ export function formatTokenCount(count) {
27
+ if (count >= 1_000_000)
28
+ return `≈ ${(count / 1_000_000).toFixed(1)}M`;
29
+ if (count >= 1000)
30
+ return `≈ ${(count / 1000).toFixed(1)}K`;
31
+ return `≈ ${count}`;
32
+ }
@@ -0,0 +1,4 @@
1
+ import type { FileNode } from "./types";
2
+ export declare function collectExtensionStats(root: FileNode): Map<string, number>;
3
+ export declare function collectProcessedFiles(root: FileNode): string[];
4
+ //# sourceMappingURL=statsCollector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statsCollector.d.ts","sourceRoot":"","sources":["../../src/core/statsCollector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGxC,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBzE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAkB9D"}
@@ -0,0 +1,28 @@
1
+ import { extname } from "node:path";
2
+ export function collectExtensionStats(root) {
3
+ const stats = new Map();
4
+ function walk(node) {
5
+ if (node.type === "file" && !node.isBinary && !node.skipReason) {
6
+ const ext = extname(node.name) || "(no ext)";
7
+ stats.set(ext, (stats.get(ext) || 0) + 1);
8
+ }
9
+ if (node.children)
10
+ for (const child of node.children)
11
+ walk(child);
12
+ }
13
+ walk(root);
14
+ return stats;
15
+ }
16
+ export function collectProcessedFiles(root) {
17
+ const files = [];
18
+ function walk(node, parentPath = "") {
19
+ const currentPath = parentPath ? `${parentPath}/${node.name}` : node.name;
20
+ if (node.type === "file" && !node.isBinary && !node.skipReason)
21
+ files.push(currentPath);
22
+ if (node.children)
23
+ for (const child of node.children)
24
+ walk(child, currentPath);
25
+ }
26
+ walk(root);
27
+ return files;
28
+ }
@@ -0,0 +1,53 @@
1
+ export type OutputFormat = "json" | "md";
2
+ export type SkipReason = "generated" | "readError" | "symlinkCycle" | "tooLarge" | "totalSizeLimit";
3
+ export type FileType = "directory" | "file" | "symlink";
4
+ export type LogLevel = "debug" | "normal" | "silent" | "verbose";
5
+ export type FileNode = {
6
+ name: string;
7
+ path: string;
8
+ type: FileType;
9
+ size: number;
10
+ children?: FileNode[];
11
+ target?: string;
12
+ isBinary?: boolean;
13
+ skipReason?: SkipReason;
14
+ };
15
+ export type ScanStats = {
16
+ files: number;
17
+ directories: number;
18
+ binary: number;
19
+ skipped: number;
20
+ errors: number;
21
+ totalSizeBytes: number;
22
+ outputSizeBytes: number;
23
+ outputTokenCount: number;
24
+ };
25
+ export type ScanResult = {
26
+ projectName: string;
27
+ root: FileNode;
28
+ stats: ScanStats;
29
+ };
30
+ export type ProgressCallback = (current: number, total: number) => void;
31
+ export type ScanOptions = {
32
+ projectName: string;
33
+ rootDirectory: string;
34
+ excludePatterns: string[];
35
+ includePatterns: string[];
36
+ excludedPaths: string[];
37
+ includeHidden: boolean;
38
+ useGitignore: boolean;
39
+ maximumFileSizeBytes: number;
40
+ maximumTotalSizeBytes: number;
41
+ followSymlinks: boolean;
42
+ onProgress?: ProgressCallback;
43
+ };
44
+ export type RenderOptions = {
45
+ outputFile: string;
46
+ format: OutputFormat;
47
+ includeTree: boolean;
48
+ includeContents: boolean;
49
+ useAnsi: boolean;
50
+ banner?: string;
51
+ footer?: string;
52
+ };
53
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,IAAI,CAAC;AAEzC,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,WAAW,GAAG,cAAc,GAAG,UAAU,GAAG,gBAAgB,CAAC;AAEpG,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAExD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjE,MAAM,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,SAAS,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAExE,MAAM,MAAM,WAAW,GAAG;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,YAAY,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export * from "./api";
2
+ export * from "./core";
3
+ export * from "./version";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./api";
2
+ export * from "./core";
3
+ export * from "./version";
@@ -0,0 +1,2 @@
1
+ export declare function countTokens(text: string): number;
2
+ //# sourceMappingURL=countTokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"countTokens.d.ts","sourceRoot":"","sources":["../../src/infra/countTokens.ts"],"names":[],"mappings":"AAqEA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAuKhD"}