ezctx 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 (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +108 -0
  3. package/dist/config.type.d.ts +9 -0
  4. package/dist/config.type.d.ts.map +1 -0
  5. package/dist/config.type.js +2 -0
  6. package/dist/config.type.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +60 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/index.type.d.ts +2 -0
  12. package/dist/index.type.d.ts.map +1 -0
  13. package/dist/index.type.js +8 -0
  14. package/dist/index.type.js.map +1 -0
  15. package/dist/test.d.ts +2 -0
  16. package/dist/test.d.ts.map +1 -0
  17. package/dist/test.js +21 -0
  18. package/dist/test.js.map +1 -0
  19. package/dist/utils/buildGraph.d.ts +13 -0
  20. package/dist/utils/buildGraph.d.ts.map +1 -0
  21. package/dist/utils/buildGraph.js +38 -0
  22. package/dist/utils/buildGraph.js.map +1 -0
  23. package/dist/utils/getConfig.d.ts +2 -0
  24. package/dist/utils/getConfig.d.ts.map +1 -0
  25. package/dist/utils/getConfig.js +4 -0
  26. package/dist/utils/getConfig.js.map +1 -0
  27. package/dist/utils/loadConfig.d.ts +10 -0
  28. package/dist/utils/loadConfig.d.ts.map +1 -0
  29. package/dist/utils/loadConfig.js +63 -0
  30. package/dist/utils/loadConfig.js.map +1 -0
  31. package/dist/utils/outputFormatter.d.ts +12 -0
  32. package/dist/utils/outputFormatter.d.ts.map +1 -0
  33. package/dist/utils/outputFormatter.js +30 -0
  34. package/dist/utils/outputFormatter.js.map +1 -0
  35. package/dist/utils/stringFormatter.d.ts +12 -0
  36. package/dist/utils/stringFormatter.d.ts.map +1 -0
  37. package/dist/utils/stringFormatter.js +17 -0
  38. package/dist/utils/stringFormatter.js.map +1 -0
  39. package/dist/utils/utils.type.d.ts +9 -0
  40. package/dist/utils/utils.type.d.ts.map +1 -0
  41. package/dist/utils/utils.type.js +2 -0
  42. package/dist/utils/utils.type.js.map +1 -0
  43. package/dist/utils/visualizeGraph.d.ts +11 -0
  44. package/dist/utils/visualizeGraph.d.ts.map +1 -0
  45. package/dist/utils/visualizeGraph.js +27 -0
  46. package/dist/utils/visualizeGraph.js.map +1 -0
  47. package/dist/utils/writeFiles.d.ts +16 -0
  48. package/dist/utils/writeFiles.d.ts.map +1 -0
  49. package/dist/utils/writeFiles.js +52 -0
  50. package/dist/utils/writeFiles.js.map +1 -0
  51. package/dist/utils/writeOutput.d.ts +16 -0
  52. package/dist/utils/writeOutput.d.ts.map +1 -0
  53. package/dist/utils/writeOutput.js +56 -0
  54. package/dist/utils/writeOutput.js.map +1 -0
  55. package/package.json +30 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 arhayashi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # ezctx
2
+
3
+ **ezctx** (short for _easy context_) puts all of your source code into one or several `.txt` file(s), allowing you to easily paste it into an external AI platform instead of having to tediously upload each individual file.
4
+
5
+ In addition, this program adds a graph/visualization of your project's files/directories to the first output `.txt` file, helping the AI map your project.
6
+
7
+ This program's "bundling" behavior can be modied by adding a configuration file. See below for usage, description, and configuration options.
8
+
9
+ ## Usage
10
+
11
+ ```
12
+ npx ezctx
13
+ ```
14
+
15
+ - Node.js version must support the promised-based `fs` API.
16
+ - The program outputs the `.txt` file(s) wherever the command was executed.
17
+
18
+ ## Description
19
+
20
+ _To view an example of this program's output, see [ezctx_1.txt](https://github.com/arhayashi/ezctx/blob/main/ezctx_1.txt)_.
21
+
22
+ When running this program, please ensure that your project has read and write permissions enabled or an error will be thrown.
23
+
24
+ ### Default Behavior
25
+
26
+ This section will describe the program's **default** behavior and some of the ways it can be modified using the [configuration](#configuration) file.
27
+
28
+ This program recursively writes your projects's source code into a singular `.txt` file so that you can easily access all your source code in a central location. Because this program does not require an npm installation, you can use it with projects that use different languages outside of the Node.js/npm ecosystem.
29
+
30
+ For instance, if you `cd` into a directory, `my_project`, executing `npx ezctx` will produce `my_project/ezctx_1.txt` containing all of your project's source code. If you need the outputted `.txt` file to be smaller, you can change the configuration's `chunkSize` which will ensure that each output file is no larger than `chunkSize`. This may result in serveral output `.txt` files in the format `ezctx_{i}.txt` where `i` corresponds to the `nth` output file. Note that if there are multiple output `.txt` files, they will live under the `ezctx` directory. Otherwise, the singular output `.txt` file will live wherever the `npx ezctx` commands was executed. These default behaviors can be modified in the program's [configuration](#configuration).
31
+
32
+ This program runs on a _file-by-file_ basis to ensure that the size of the content in the current source code file plus the content in the current output `.txt` file is less than `chunkSize`. Effectively, this means that if one of your source code files is greater than `chunkSize`, it will not be added to an output `.txt` file.
33
+
34
+ ### Output File
35
+
36
+ Before writing your project's source code to the output `.txt` file(s), this program creates a visualization of your project's files/directories from a recursively created graph. This visualization is added only to the first outputted `.txt` file. For example, the visualization of _this program_ looks like the below and is the first item written to the `ezctx_1.txt` output.
37
+
38
+ ```
39
+ *** project structure ***
40
+
41
+ \ezctx
42
+ |__.ezctxrc.json
43
+ |__README.md
44
+ |__src/
45
+ |__config.type.ts
46
+ |__index.ts
47
+ |__utils/
48
+ |__buildGraph.ts
49
+ |__loadConfig.ts
50
+ |__outputFormatter.ts
51
+ |__stringFormatter.ts
52
+ |__utils.type.ts
53
+ |__visualizeGraph.ts
54
+ |__writeOutput.ts
55
+ |__tsconfig.json
56
+
57
+ ```
58
+
59
+ Additionally, when writing each of your project's files to the output `.txt` file(s), they will be in the format defined below and will go under your project's visualization.
60
+
61
+ ```
62
+ *** {file_name_1} ***
63
+
64
+ // ...
65
+
66
+ *** {file_name_2} ***
67
+
68
+ // ...
69
+
70
+ ```
71
+
72
+ ## Configuration
73
+
74
+ To modify this program's default "bundling" behavior, add a `JSON` file in the same directory where the `npx ezctx` command will be executed. This configuration file must contain the substring "ezctx" within its name, like `ezctx.config.json`, `.ezctxrc.json`, or `ezctx.json`. The modifiable configuration fields are defined below.
75
+
76
+ ### Configuration Options
77
+
78
+ | Field | Type | Description |
79
+ | ------------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
80
+ | `chunkSize` | `number` | The maximum size (in bytes) of each output `.txt` file. This program's recursive process occurs on a file-by-file basis, so if a file's size is larger than `chunkSize`, it will not be included in the output `.txt` file(s). |
81
+ | `defaultIgnores` | `boolean` | Wether to use the program's default ignores. If `true`, the user defined `ignores` will be merged with the program's default `ignores` (see the default config below). If `false`, only the user defined `ignores` will be used. |
82
+ | `ignores` | `string[]` | The files/directories that will not be included in the output `.txt` file(s). |
83
+ | `outDir` | `string` | The name of the directory where the output `.txt` file(s) will live under. |
84
+ | `outDirSingleEmit` | `boolean` | Applies when there is only a single output `.txt` file. If `true`, the outputted `.txt` file will live under `outDir`. If `false`, it will be placed wherever the `npx ezctx` command was executed. |
85
+ | `outFile` | `string` | The name of each output `.txt` file. Add `{i}` to denote where the file's numbering should go within its name. If `{i}` is not included, the file's numbering (along with an underscore) will be added to the end of the file's name by default (see the default config below). |
86
+
87
+ ### Default Configuration
88
+
89
+ If no configuration file is defined, or a field is omitted, the default configuration/corresponding field (defined below) will be used instead.
90
+
91
+ ```
92
+ {
93
+ chunkSize: Infinity,
94
+ defaultIgnores: true,
95
+ ignores: [
96
+ "node_modules",
97
+ "package-lock.json",
98
+ "package.json",
99
+ ".git",
100
+ ".gitignore",
101
+ ".DS_Store",
102
+ ".vscode",
103
+ ],
104
+ outDir: "ezctx",
105
+ outDirSingleEmit: false,
106
+ outFile: "ezctx_{i}.txt"
107
+ }
108
+ ```
@@ -0,0 +1,9 @@
1
+ export type Config = {
2
+ chunkSize: number;
3
+ ignores: string[];
4
+ outDir: string;
5
+ outDirSingleEmit: boolean;
6
+ defaultIgnores: boolean;
7
+ outFile: string;
8
+ };
9
+ //# sourceMappingURL=config.type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.type.d.ts","sourceRoot":"","sources":["../src/config.type.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,MAAM,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.type.js","sourceRoot":"","sources":["../src/config.type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ import * as fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import buildGraph from "./utils/buildGraph.js";
5
+ import visualizeGraph from "./utils/visualizeGraph.js";
6
+ import writeOutput from "./utils/writeOutput.js";
7
+ import loadConfig from "./utils/loadConfig.js";
8
+ import outputFormatter from "./utils/outputFormatter.js";
9
+ try {
10
+ // loads in the configs
11
+ const config = await loadConfig();
12
+ const ignores = config["ignores"];
13
+ const outDir = config["outDir"];
14
+ const outDirSingleEmit = config["outDirSingleEmit"];
15
+ const outFile = config["outFile"];
16
+ const chunkSize = config["chunkSize"];
17
+ // builds graph
18
+ let graph = await buildGraph(process.cwd(), ignores);
19
+ // creates visualization from the graph
20
+ const visualization = "*** project structure ***\n\n" + visualizeGraph(graph) + "\n";
21
+ // creates output directory; removes previous ones
22
+ const finalOutDir = path.join(process.cwd(), outDir);
23
+ await fs.rm(finalOutDir, { recursive: true, force: true });
24
+ await fs.mkdir(finalOutDir, { recursive: true });
25
+ // creates output path;
26
+ const finalOutPath = path.join(finalOutDir, outFile);
27
+ // creates path of the first output file
28
+ const firstFinalOutPath = outputFormatter(finalOutPath, 1);
29
+ // writes the visualization to the first output file
30
+ await fs.writeFile(firstFinalOutPath, visualization, {
31
+ flag: "w+",
32
+ });
33
+ // count object to access number of output files
34
+ // from outside the writeOutput function
35
+ const count = { count: 1 };
36
+ // adds file contents to output
37
+ await writeOutput(graph, finalOutPath, chunkSize, count);
38
+ // creates path for single emits
39
+ const singleEmitOutPath = path.join(process.cwd(), path.basename(firstFinalOutPath));
40
+ // detects if only a single output file and emits it
41
+ // in the working directory instead of the outDir
42
+ if (count.count === 1 && !outDirSingleEmit) {
43
+ // creates path of the first output file for single emits
44
+ await fs.rename(firstFinalOutPath, singleEmitOutPath);
45
+ await fs.rm(finalOutDir, { recursive: true, force: true });
46
+ }
47
+ else {
48
+ await fs.rm(singleEmitOutPath, { force: true });
49
+ }
50
+ }
51
+ catch (error) {
52
+ if (error instanceof Error) {
53
+ console.log(error.message);
54
+ }
55
+ else {
56
+ console.log(error);
57
+ }
58
+ process.exit(1);
59
+ }
60
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.type.d.ts","sourceRoot":"","sources":["../src/index.type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export {};
2
+ // export type Node = {
3
+ // name: string;
4
+ // path: string;
5
+ // type: string;
6
+ // children?: undefined | Node[];
7
+ // };
8
+ //# sourceMappingURL=index.type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.type.js","sourceRoot":"","sources":["../src/index.type.ts"],"names":[],"mappings":";AAAA,uBAAuB;AACvB,oBAAoB;AACpB,oBAAoB;AACpB,oBAAoB;AACpB,qCAAqC;AACrC,KAAK"}
package/dist/test.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../test.ts"],"names":[],"mappings":""}
package/dist/test.js ADDED
@@ -0,0 +1,21 @@
1
+ // const INDENT = " ";
2
+ // const SUB_CONTENT = "|____";
3
+ export {};
4
+ // function printStructure(file: string, type: "dir" | "file"): string {
5
+ // return "t";
6
+ // }
7
+ /*
8
+
9
+ ***PROJECT_STRUCTURE***
10
+
11
+ path
12
+ |____hello world
13
+ |____hello world
14
+ |____test
15
+
16
+
17
+ **********************
18
+
19
+
20
+ */
21
+ //# sourceMappingURL=test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../test.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,+BAA+B;;AAG/B,wEAAwE;AACxE,kBAAkB;AAClB,IAAI;AAEJ;;;;;;;;;;;;;EAaE"}
@@ -0,0 +1,13 @@
1
+ import type { FileNode } from "./utils.type.js";
2
+ /**
3
+ * Recursively constructs a graph of the project starting from the path
4
+ * given by dirPath.
5
+ *
6
+ * @param dirPath Path where the graph should start
7
+ * @param ignores Directories/filters to ignore
8
+ * @param maxDepth Max depth to recurse to prevent infinite recursion
9
+ * @param depth Current depth
10
+ * @returns FileNode object
11
+ */
12
+ export default function buildGraph(dirPath: string, ignores?: string[], maxDepth?: number, depth?: number): Promise<FileNode>;
13
+ //# sourceMappingURL=buildGraph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildGraph.d.ts","sourceRoot":"","sources":["../../src/utils/buildGraph.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;GASG;AACH,wBAA8B,UAAU,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,MAAM,EAAO,EACtB,QAAQ,GAAE,MAAa,EACvB,KAAK,GAAE,MAAU,GAClB,OAAO,CAAC,QAAQ,CAAC,CAyCnB"}
@@ -0,0 +1,38 @@
1
+ import * as fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ /**
4
+ * Recursively constructs a graph of the project starting from the path
5
+ * given by dirPath.
6
+ *
7
+ * @param dirPath Path where the graph should start
8
+ * @param ignores Directories/filters to ignore
9
+ * @param maxDepth Max depth to recurse to prevent infinite recursion
10
+ * @param depth Current depth
11
+ * @returns FileNode object
12
+ */
13
+ export default async function buildGraph(dirPath, ignores = [], maxDepth = 1000, depth = 0) {
14
+ // gets name of directory/file
15
+ const name = path.basename(dirPath);
16
+ // get stats about directory/file
17
+ const stats = await fs.stat(dirPath);
18
+ // creates a new node
19
+ const fileNode = {
20
+ name,
21
+ path: dirPath,
22
+ type: stats.isDirectory() ? "directory" : "file",
23
+ depth,
24
+ size: stats.size,
25
+ };
26
+ // recursively adds children nodes
27
+ if (stats.isDirectory() && depth < maxDepth) {
28
+ // gets all the files/directories within the current one
29
+ const entries = await fs.readdir(dirPath);
30
+ // filter out ignores files/directories
31
+ let filteredEntries = entries.filter((entry) => !ignores.includes(entry));
32
+ // add sub-directories and their files
33
+ // as a children property to the parent node
34
+ fileNode.children = await Promise.all(filteredEntries.map((entry) => buildGraph(path.join(dirPath, entry), ignores, maxDepth, depth + 1)));
35
+ }
36
+ return fileNode;
37
+ }
38
+ //# sourceMappingURL=buildGraph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildGraph.js","sourceRoot":"","sources":["../../src/utils/buildGraph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,UAAU,CACpC,OAAe,EACf,UAAoB,EAAE,EACtB,WAAmB,IAAI,EACvB,QAAgB,CAAC;IAEjB,8BAA8B;IAC9B,MAAM,IAAI,GAAW,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAE5C,iCAAiC;IACjC,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAErC,qBAAqB;IACrB,MAAM,QAAQ,GAAa;QACvB,IAAI;QACJ,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM;QAChD,KAAK;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;KACnB,CAAC;IAEF,kCAAkC;IAClC,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;QAC1C,wDAAwD;QACxD,MAAM,OAAO,GAAa,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAEpD,uCAAuC;QACvC,IAAI,eAAe,GAAa,OAAO,CAAC,MAAM,CAC1C,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CACtC,CAAC;QAEF,sCAAsC;QACtC,4CAA4C;QAC5C,QAAQ,CAAC,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CACjC,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC1B,UAAU,CACN,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,KAAK,GAAG,CAAC,CACZ,CACJ,CACJ,CAAC;IACN,CAAC;IAED,OAAO,QAAQ,CAAC;AACpB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=getConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getConfig.d.ts","sourceRoot":"","sources":["../../src/utils/getConfig.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import { cosmiconfig } from "cosmiconfig";
2
+ const explorer = cosmiconfig("ezctx");
3
+ explorer.search().then(result => console.log(result));
4
+ //# sourceMappingURL=getConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getConfig.js","sourceRoot":"","sources":["../../src/utils/getConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;AACtC,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Config } from "../config.type.js";
2
+ /**
3
+ * Loads in the user's config and merges it with default config
4
+ * to fill undefined fields. Assumes the user's config is in the
5
+ * same directory as process.cwd(), contains "ezctx", and is a JSON file.
6
+ *
7
+ * @returns Config
8
+ */
9
+ export default function loadConfig(): Promise<Config>;
10
+ //# sourceMappingURL=loadConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadConfig.d.ts","sourceRoot":"","sources":["../../src/utils/loadConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAwBhD;;;;;;GAMG;AACH,wBAA8B,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CA8C1D"}
@@ -0,0 +1,63 @@
1
+ import fs from "node:fs/promises";
2
+ import outputFormatter from "./outputFormatter.js";
3
+ // default ignores
4
+ const _defaultIgnores = [
5
+ "node_modules",
6
+ "package-lock.json",
7
+ "package.json",
8
+ ".git",
9
+ ".gitignore",
10
+ ".DS_Store",
11
+ ".vscode",
12
+ ];
13
+ // default config
14
+ const defaultConfig = {
15
+ chunkSize: Infinity,
16
+ defaultIgnores: true,
17
+ ignores: _defaultIgnores,
18
+ outDir: "ezctx",
19
+ outDirSingleEmit: false,
20
+ outFile: "ezctx_{i}.txt",
21
+ };
22
+ /**
23
+ * Loads in the user's config and merges it with default config
24
+ * to fill undefined fields. Assumes the user's config is in the
25
+ * same directory as process.cwd(), contains "ezctx", and is a JSON file.
26
+ *
27
+ * @returns Config
28
+ */
29
+ export default async function loadConfig() {
30
+ // searches for a user-defined config
31
+ let userConfig;
32
+ const userConfigName = (await fs.readdir(process.cwd())).find((file) => file.includes("ezctx"));
33
+ if (userConfigName) {
34
+ userConfig = JSON.parse(await fs.readFile(userConfigName, "utf-8"));
35
+ }
36
+ else {
37
+ userConfig = defaultConfig;
38
+ }
39
+ // merges the program's default ignores with
40
+ // the user-defined ignores
41
+ // stores the merged ignores
42
+ let mergedIgnores;
43
+ if (userConfig.defaultIgnores === undefined || userConfig.defaultIgnores) {
44
+ mergedIgnores = [..._defaultIgnores, ...(userConfig.ignores || [])];
45
+ }
46
+ else {
47
+ mergedIgnores = [...(userConfig.ignores || [])];
48
+ }
49
+ // add program's output directory and output file to ignores
50
+ // to prevent duplicate writes
51
+ mergedIgnores.push(userConfig.outDir || defaultConfig.outDir);
52
+ mergedIgnores.push(userConfig.outFile
53
+ ? outputFormatter(userConfig.outFile, 1)
54
+ : outputFormatter(defaultConfig.outFile, 1));
55
+ // creates merged config
56
+ const mergedConfig = {
57
+ ...defaultConfig,
58
+ ...Object.fromEntries(Object.entries(userConfig).filter(([_, value]) => value !== undefined)),
59
+ ignores: mergedIgnores,
60
+ };
61
+ return mergedConfig;
62
+ }
63
+ //# sourceMappingURL=loadConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadConfig.js","sourceRoot":"","sources":["../../src/utils/loadConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,OAAO,eAAe,MAAM,sBAAsB,CAAC;AAEnD,kBAAkB;AAClB,MAAM,eAAe,GAAa;IAC9B,cAAc;IACd,mBAAmB;IACnB,cAAc;IACd,MAAM;IACN,YAAY;IACZ,WAAW;IACX,SAAS;CACZ,CAAC;AAEF,iBAAiB;AACjB,MAAM,aAAa,GAAW;IAC1B,SAAS,EAAE,QAAQ;IACnB,cAAc,EAAE,IAAI;IACpB,OAAO,EAAE,eAAe;IACxB,MAAM,EAAE,OAAO;IACf,gBAAgB,EAAE,KAAK;IACvB,OAAO,EAAE,eAAe;CAC3B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,UAAU;IACpC,qCAAqC;IACrC,IAAI,UAA2B,CAAC;IAChC,MAAM,cAAc,GAAuB,CACvC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAClC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAEzC,IAAI,cAAc,EAAE,CAAC;QACjB,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;IACxE,CAAC;SAAM,CAAC;QACJ,UAAU,GAAG,aAAa,CAAC;IAC/B,CAAC;IAED,4CAA4C;IAC5C,2BAA2B;IAE3B,4BAA4B;IAC5B,IAAI,aAAuB,CAAC;IAE5B,IAAI,UAAU,CAAC,cAAc,KAAK,SAAS,IAAI,UAAU,CAAC,cAAc,EAAE,CAAC;QACvE,aAAa,GAAG,CAAC,GAAG,eAAe,EAAE,GAAG,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IACxE,CAAC;SAAM,CAAC;QACJ,aAAa,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,4DAA4D;IAC5D,8BAA8B;IAC9B,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9D,aAAa,CAAC,IAAI,CACd,UAAU,CAAC,OAAO;QACd,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;QACxC,CAAC,CAAC,eAAe,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAClD,CAAC;IAEF,wBAAwB;IACxB,MAAM,YAAY,GAAW;QACzB,GAAG,aAAa;QAChB,GAAG,MAAM,CAAC,WAAW,CACjB,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,CAC7B,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CACtC,CACJ;QACD,OAAO,EAAE,aAAa;KACzB,CAAC;IAEF,OAAO,YAAY,CAAC;AACxB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Takes in a path or file and embeds the current file count
3
+ * within the output file defined in the config. If the raw
4
+ * output file does not define a place to embed the count, this
5
+ * program defaulty adds "_{count}" before the file name.
6
+ *
7
+ * @param outFile The raw output file format defined in the config
8
+ * @param count The nth output file that is being created
9
+ * @returns A formatted path/file name with the count embedded
10
+ */
11
+ export default function outputFormatter(outputPath: string, count: number): string;
12
+ //# sourceMappingURL=outputFormatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outputFormatter.d.ts","sourceRoot":"","sources":["../../src/utils/outputFormatter.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,MAAM,CAAC,OAAO,UAAU,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GACd,MAAM,CAqBR"}
@@ -0,0 +1,30 @@
1
+ import path from "node:path";
2
+ /**
3
+ * Takes in a path or file and embeds the current file count
4
+ * within the output file defined in the config. If the raw
5
+ * output file does not define a place to embed the count, this
6
+ * program defaulty adds "_{count}" before the file name.
7
+ *
8
+ * @param outFile The raw output file format defined in the config
9
+ * @param count The nth output file that is being created
10
+ * @returns A formatted path/file name with the count embedded
11
+ */
12
+ export default function outputFormatter(outputPath, count) {
13
+ // extracts the file name
14
+ const fileName = path.basename(outputPath);
15
+ // extracts the file dirname
16
+ const dirName = path.dirname(outputPath);
17
+ // gets index of the section to replace with the
18
+ // current file count
19
+ const index = fileName.indexOf("{i}");
20
+ if (index == -1) {
21
+ // if not defined, add default count
22
+ const fileNameParts = fileName.split(".");
23
+ const finalOutputFile = fileNameParts[0] + `_${count}.` + fileNameParts[1];
24
+ return path.join(dirName, finalOutputFile);
25
+ }
26
+ // otherwise, replace the {i} with the current file count
27
+ const finalOutputFile = fileName.substring(0, index) + count + fileName.substring(index + 3);
28
+ return path.join(dirName, finalOutputFile);
29
+ }
30
+ //# sourceMappingURL=outputFormatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outputFormatter.js","sourceRoot":"","sources":["../../src/utils/outputFormatter.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;;GASG;AAEH,MAAM,CAAC,OAAO,UAAU,eAAe,CACnC,UAAkB,EAClB,KAAa;IAEb,yBAAyB;IACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC3C,4BAA4B;IAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACzC,gDAAgD;IAChD,qBAAqB;IACrB,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAEtC,IAAI,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC;QACd,oCAAoC;QACpC,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,eAAe,GACjB,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAC/C,CAAC;IAED,yDAAyD;IACzD,MAAM,eAAe,GACjB,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACzE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Formats a given resource by adding spacing and lines
3
+ * to ensure that it is properly placed when creating a
4
+ * visualization of the project's structure
5
+ *
6
+ * @param depth Current depth within the graph
7
+ * @param name Name of the file/directory
8
+ * @param type Type of the given resource
9
+ * @returns A formatted string of the resource
10
+ */
11
+ export default function stringFormatter(depth: number, name: string, type: "directory" | "file"): string;
12
+ //# sourceMappingURL=stringFormatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stringFormatter.d.ts","sourceRoot":"","sources":["../../src/utils/stringFormatter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,OAAO,UAAU,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,WAAW,GAAG,MAAM,GAC3B,MAAM,CAKR"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Formats a given resource by adding spacing and lines
3
+ * to ensure that it is properly placed when creating a
4
+ * visualization of the project's structure
5
+ *
6
+ * @param depth Current depth within the graph
7
+ * @param name Name of the file/directory
8
+ * @param type Type of the given resource
9
+ * @returns A formatted string of the resource
10
+ */
11
+ export default function stringFormatter(depth, name, type) {
12
+ return depth == 0
13
+ ? `\\${name}\n`
14
+ : ` `.repeat(depth - 1) +
15
+ `|__${name}${type === "directory" ? "/" : ""}\n`;
16
+ }
17
+ //# sourceMappingURL=stringFormatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stringFormatter.js","sourceRoot":"","sources":["../../src/utils/stringFormatter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,OAAO,UAAU,eAAe,CACnC,KAAa,EACb,IAAY,EACZ,IAA0B;IAE1B,OAAO,KAAK,IAAI,CAAC;QACb,CAAC,CAAC,KAAK,IAAI,IAAI;QACf,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;YACnB,MAAM,IAAI,GAAG,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,9 @@
1
+ export type FileNode = {
2
+ name: string;
3
+ path: string;
4
+ type: "directory" | "file";
5
+ size: number;
6
+ depth: number;
7
+ children?: undefined | FileNode[];
8
+ };
9
+ //# sourceMappingURL=utils.type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.type.d.ts","sourceRoot":"","sources":["../../src/utils/utils.type.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,QAAQ,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,GAAG,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,EAAE,CAAC;CACrC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=utils.type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.type.js","sourceRoot":"","sources":["../../src/utils/utils.type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { FileNode } from "./utils.type.js";
2
+ /**
3
+ * Recursively creates a visualization of the project's graph.
4
+ * Uses stringFormatter.ts to format each directory/file
5
+ *
6
+ * @param graph Project's graph
7
+ * @param output Store's recursive output
8
+ * @returns A visualization of the given graph
9
+ */
10
+ export default function visualizeGraph(graph: FileNode | FileNode[] | undefined, output?: string): string;
11
+ //# sourceMappingURL=visualizeGraph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visualizeGraph.d.ts","sourceRoot":"","sources":["../../src/utils/visualizeGraph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGhD;;;;;;;GAOG;AAEH,MAAM,CAAC,OAAO,UAAU,cAAc,CAClC,KAAK,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,SAAS,EACxC,MAAM,GAAE,MAAW,GACpB,MAAM,CAgBR"}
@@ -0,0 +1,27 @@
1
+ import stringFormatter from "./stringFormatter.js";
2
+ /**
3
+ * Recursively creates a visualization of the project's graph.
4
+ * Uses stringFormatter.ts to format each directory/file
5
+ *
6
+ * @param graph Project's graph
7
+ * @param output Store's recursive output
8
+ * @returns A visualization of the given graph
9
+ */
10
+ export default function visualizeGraph(graph, output = "") {
11
+ // if graph is undefined, reach end/tip
12
+ if (!graph)
13
+ return output;
14
+ // if not array, it's the root or a child within an array
15
+ if (!Array.isArray(graph)) {
16
+ output += stringFormatter(graph.depth, graph.name, graph.type);
17
+ output = visualizeGraph(graph.children, output);
18
+ }
19
+ else {
20
+ graph.forEach((child) => {
21
+ output += stringFormatter(child.depth, child.name, child.type);
22
+ output = visualizeGraph(child.children, output);
23
+ });
24
+ }
25
+ return output;
26
+ }
27
+ //# sourceMappingURL=visualizeGraph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visualizeGraph.js","sourceRoot":"","sources":["../../src/utils/visualizeGraph.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,MAAM,sBAAsB,CAAC;AAEnD;;;;;;;GAOG;AAEH,MAAM,CAAC,OAAO,UAAU,cAAc,CAClC,KAAwC,EACxC,SAAiB,EAAE;IAEnB,uCAAuC;IACvC,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC;IAE1B,yDAAyD;IACzD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,eAAe,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/D,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACJ,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,MAAM,IAAI,eAAe,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAC/D,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { FileNode } from "./utils.type.js";
2
+ /**
3
+ * Recursively adds content to the output files while ensuring
4
+ * that the size of each output file is less than the given chunkSize.
5
+ * If it is, it starts a new output file with the file namen given in
6
+ * outputPath.
7
+ *
8
+ * @param {FileNode | FileNode[] | undefined} graph Project's graph
9
+ * @param {string} outputPath The path to write output to
10
+ * @param {number} chunkSize The max size of each output file
11
+ * @param {number} count The count of the current output file
12
+ */
13
+ export default function writeFiles(graph: FileNode | FileNode[] | undefined, outputPath: string, chunkSize: number, count?: {
14
+ count: number;
15
+ }): Promise<void>;
16
+ //# sourceMappingURL=writeFiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writeFiles.d.ts","sourceRoot":"","sources":["../../src/utils/writeFiles.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGhD;;;;;;;;;;GAUG;AAEH,wBAA8B,UAAU,CACpC,KAAK,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,SAAS,EACxC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAiB,GACxC,OAAO,CAAC,IAAI,CAAC,CAsCf"}
@@ -0,0 +1,52 @@
1
+ import * as fs from "node:fs/promises";
2
+ import outputFormatter from "./outputFormatter.js";
3
+ /**
4
+ * Recursively adds content to the output files while ensuring
5
+ * that the size of each output file is less than the given chunkSize.
6
+ * If it is, it starts a new output file with the file namen given in
7
+ * outputPath.
8
+ *
9
+ * @param {FileNode | FileNode[] | undefined} graph Project's graph
10
+ * @param {string} outputPath The path to write output to
11
+ * @param {number} chunkSize The max size of each output file
12
+ * @param {number} count The count of the current output file
13
+ */
14
+ export default async function writeFiles(graph, outputPath, chunkSize, count = { count: 1 }) {
15
+ // if graph is null/undefined, reach tip
16
+ if (!graph)
17
+ return;
18
+ // turn current node into array to handle empty directories
19
+ const nodes = Array.isArray(graph) ? graph : [graph];
20
+ // recursively adds each nodes' file content to the output
21
+ for (const node of nodes) {
22
+ if (node.type === "directory") {
23
+ await writeFiles(node.children, outputPath, chunkSize, count);
24
+ }
25
+ else if (node.type === "file") {
26
+ // get file's content and add formatting
27
+ const content = "*** " +
28
+ node.name +
29
+ " ***" +
30
+ "\n\n" +
31
+ (await fs.readFile(node.path)) +
32
+ "\n";
33
+ // get the correct output path
34
+ let currentPath = outputFormatter(outputPath, count.count);
35
+ // get the size of the current content
36
+ const contentSize = Buffer.byteLength(content, "utf-8");
37
+ // try-catch block because the currentPath may be exist on disk
38
+ // ie. first time writing to this output file
39
+ try {
40
+ // get size of current output file
41
+ const { size } = await fs.stat(currentPath);
42
+ // ensures that the chunkSize condition is respected
43
+ if (size > 0 && contentSize + size > chunkSize) {
44
+ currentPath = outputFormatter(outputPath, ++count.count);
45
+ }
46
+ }
47
+ catch (error) { }
48
+ await fs.writeFile(currentPath, content, { flag: "a" });
49
+ }
50
+ }
51
+ }
52
+ //# sourceMappingURL=writeFiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writeFiles.js","sourceRoot":"","sources":["../../src/utils/writeFiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,OAAO,eAAe,MAAM,sBAAsB,CAAC;AAEnD;;;;;;;;;;GAUG;AAEH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,UAAU,CACpC,KAAwC,EACxC,UAAkB,EAClB,SAAiB,EACjB,QAA2B,EAAE,KAAK,EAAE,CAAC,EAAE;IAEvC,wCAAwC;IACxC,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,2DAA2D;IAC3D,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAErD,0DAA0D;IAC1D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC5B,MAAM,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAClE,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC9B,wCAAwC;YACxC,MAAM,OAAO,GACT,MAAM;gBACN,IAAI,CAAC,IAAI;gBACT,MAAM;gBACN,MAAM;gBACN,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC9B,IAAI,CAAC;YACT,+BAA+B;YAC/B,IAAI,WAAW,GAAG,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAC3D,sCAAsC;YACtC,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACxD,+DAA+D;YAC/D,6CAA6C;YAC7C,IAAI,CAAC;gBACD,kCAAkC;gBAClC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAC5C,oDAAoD;gBACpD,IAAI,IAAI,GAAG,CAAC,IAAI,WAAW,GAAG,IAAI,GAAG,SAAS,EAAE,CAAC;oBAC7C,WAAW,GAAG,eAAe,CAAC,UAAU,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC7D,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC,CAAA,CAAC;YAElB,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5D,CAAC;IACL,CAAC;AACL,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { FileNode } from "./utils.type.js";
2
+ /**
3
+ * Recursively adds content to the output files while ensuring
4
+ * that the size of each output file is less than the given chunkSize.
5
+ * If it is, it starts a new output file with the file namen given in
6
+ * outputPath. Stores the count as an object to have it persist.
7
+ *
8
+ * @param graph Project's graph
9
+ * @param outputPath The path to write output to
10
+ * @param chunkSize The max size of each output file
11
+ * @param count The count of the current output file
12
+ */
13
+ export default function writeOutput(graph: FileNode | FileNode[] | undefined, outputPath: string, chunkSize: number, count: {
14
+ count: number;
15
+ }): Promise<void>;
16
+ //# sourceMappingURL=writeOutput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writeOutput.d.ts","sourceRoot":"","sources":["../../src/utils/writeOutput.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGhD;;;;;;;;;;GAUG;AAEH,wBAA8B,WAAW,CACrC,KAAK,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,SAAS,EACxC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACzB,OAAO,CAAC,IAAI,CAAC,CA2Cf"}
@@ -0,0 +1,56 @@
1
+ import * as fs from "node:fs/promises";
2
+ import outputFormatter from "./outputFormatter.js";
3
+ /**
4
+ * Recursively adds content to the output files while ensuring
5
+ * that the size of each output file is less than the given chunkSize.
6
+ * If it is, it starts a new output file with the file namen given in
7
+ * outputPath. Stores the count as an object to have it persist.
8
+ *
9
+ * @param graph Project's graph
10
+ * @param outputPath The path to write output to
11
+ * @param chunkSize The max size of each output file
12
+ * @param count The count of the current output file
13
+ */
14
+ export default async function writeOutput(graph, outputPath, chunkSize, count) {
15
+ // if graph is null/undefined, reach tip
16
+ if (!graph)
17
+ return;
18
+ // turn current node into array to handle empty directories
19
+ const nodes = Array.isArray(graph) ? graph : [graph];
20
+ // recursively adds each nodes' file content to the output
21
+ for (const node of nodes) {
22
+ if (node.type === "directory") {
23
+ await writeOutput(node.children, outputPath, chunkSize, count);
24
+ }
25
+ else if (node.type === "file") {
26
+ // get file's content and add formatting
27
+ const content = "*** " +
28
+ node.name +
29
+ " ***" +
30
+ "\n\n" +
31
+ (await fs.readFile(node.path)) +
32
+ "\n";
33
+ // get the correct output path
34
+ let currentOutputPath = outputFormatter(outputPath, count.count);
35
+ // get the size of the current content
36
+ const contentSize = Buffer.byteLength(content, "utf-8");
37
+ // try-catch block because the currentOutputPath may not exist on disk
38
+ // ie. first time writing to this output file
39
+ try {
40
+ // get size of current output file
41
+ const { size } = await fs.stat(currentOutputPath);
42
+ // if the size of the current content is bigger
43
+ // than chunk size, skip file
44
+ if (contentSize > chunkSize)
45
+ return;
46
+ // ensures that the chunkSize condition is respected
47
+ if (size > 0 && contentSize + size > chunkSize) {
48
+ currentOutputPath = outputFormatter(outputPath, ++count.count);
49
+ }
50
+ }
51
+ catch (error) { }
52
+ await fs.writeFile(currentOutputPath, content, { flag: "a" });
53
+ }
54
+ }
55
+ }
56
+ //# sourceMappingURL=writeOutput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writeOutput.js","sourceRoot":"","sources":["../../src/utils/writeOutput.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,OAAO,eAAe,MAAM,sBAAsB,CAAC;AAEnD;;;;;;;;;;GAUG;AAEH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,WAAW,CACrC,KAAwC,EACxC,UAAkB,EAClB,SAAiB,EACjB,KAAwB;IAExB,wCAAwC;IACxC,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,2DAA2D;IAC3D,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAErD,0DAA0D;IAC1D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC5B,MAAM,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QACnE,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC9B,wCAAwC;YACxC,MAAM,OAAO,GACT,MAAM;gBACN,IAAI,CAAC,IAAI;gBACT,MAAM;gBACN,MAAM;gBACN,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC9B,IAAI,CAAC;YACT,+BAA+B;YAC/B,IAAI,iBAAiB,GAAG,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YACjE,sCAAsC;YACtC,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACxD,sEAAsE;YACtE,6CAA6C;YAC7C,IAAI,CAAC;gBACD,kCAAkC;gBAClC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBAElD,+CAA+C;gBAC/C,6BAA6B;gBAC7B,IAAI,WAAW,GAAG,SAAS;oBAAE,OAAO;gBAEpC,oDAAoD;gBACpD,IAAI,IAAI,GAAG,CAAC,IAAI,WAAW,GAAG,IAAI,GAAG,SAAS,EAAE,CAAC;oBAC7C,iBAAiB,GAAG,eAAe,CAAC,UAAU,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;gBACnE,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC,CAAA,CAAC;YAElB,MAAM,EAAE,CAAC,SAAS,CAAC,iBAAiB,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAClE,CAAC;IACL,CAAC;AACL,CAAC"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "ezctx",
3
+ "version": "1.0.0",
4
+ "description": "Puts all of your source code into one or several `.txt` file(s), allowing you to easily paste it into an external AI platform instead of having to tediously upload each individual file.",
5
+ "license": "MIT",
6
+ "author": "zye123",
7
+ "type": "module",
8
+ "main": "dist/index.ts",
9
+ "bin": "./dist/index.js",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/arhayashi/ezctx.git"
13
+ },
14
+ "homepage": "https://github.com/arhayashi/ezctx#readme",
15
+ "scripts": {
16
+ "ezctx": "npx tsc && node ./dist/index.js"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "^24.10.1",
20
+ "typescript": "^5.9.3"
21
+ },
22
+ "keywords": [
23
+ "context",
24
+ "ai",
25
+ "bundler"
26
+ ],
27
+ "files": [
28
+ "/dist"
29
+ ]
30
+ }