johankit 0.1.5 → 0.4.2

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 (59) hide show
  1. package/README.md +26 -58
  2. package/dist/cli/commands/sync.js +37 -57
  3. package/dist/core/validation.js +6 -18
  4. package/dist/core/write.js +9 -7
  5. package/dist/src/cli/commands/copy.js +11 -0
  6. package/dist/src/cli/commands/paste.js +120 -0
  7. package/dist/src/cli/commands/prompt.js +54 -0
  8. package/dist/src/cli/commands/sync.js +173 -0
  9. package/dist/src/core/clipboard.js +64 -0
  10. package/dist/src/core/config.js +39 -0
  11. package/dist/{core → src/core}/diff.js +9 -12
  12. package/dist/src/core/scan.js +70 -0
  13. package/dist/src/core/schema.js +18 -0
  14. package/dist/src/core/validation.js +11 -0
  15. package/dist/src/core/write.js +24 -0
  16. package/dist/src/index.js +34 -0
  17. package/dist/src/tests/cleanCodeBlock.test.js +23 -0
  18. package/dist/src/tests/scan.test.js +35 -0
  19. package/dist/src/tests/schema.test.js +22 -0
  20. package/dist/src/utils/cleanCodeBlock.js +21 -0
  21. package/dist/types.js +1 -0
  22. package/johankit.yml +6 -0
  23. package/package.json +20 -10
  24. package/src/cli/commands/copy.ts +6 -19
  25. package/src/cli/commands/paste.ts +70 -31
  26. package/src/cli/commands/prompt.ts +24 -64
  27. package/src/cli/commands/sync.ts +121 -73
  28. package/src/core/clipboard.ts +46 -80
  29. package/src/core/config.ts +20 -32
  30. package/src/core/diff.ts +10 -21
  31. package/src/core/scan.ts +43 -40
  32. package/src/core/schema.ts +17 -34
  33. package/src/core/validation.ts +8 -27
  34. package/src/core/write.ts +11 -17
  35. package/src/index.ts +38 -77
  36. package/src/types.ts +4 -50
  37. package/src/utils/cleanCodeBlock.ts +17 -8
  38. package/tsconfig.json +14 -6
  39. package/Readme.md +0 -56
  40. package/dist/cli/commands/copy.js +0 -21
  41. package/dist/cli/commands/paste.js +0 -48
  42. package/dist/cli/commands/prompt.js +0 -88
  43. package/dist/cli/commands/three.js +0 -106
  44. package/dist/cli/commands/tree.js +0 -106
  45. package/dist/core/clipboard.js +0 -88
  46. package/dist/core/config.js +0 -51
  47. package/dist/core/scan.js +0 -66
  48. package/dist/core/schema.js +0 -40
  49. package/dist/index.js +0 -72
  50. package/dist/services/JohankitService.js +0 -59
  51. package/dist/utils/cleanCodeBlock.js +0 -12
  52. package/dist/utils/createAsciiTree.js +0 -46
  53. package/johankit.yaml +0 -2
  54. package/src/cli/commands/tree.ts +0 -119
  55. package/src/services/JohankitService.ts +0 -70
  56. package/src/utils/createAsciiTree.ts +0 -53
  57. package/types.ts +0 -11
  58. /package/dist/{core → src/core}/git.js +0 -0
  59. /package/{types.js → dist/src/types.js} +0 -0
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = cleanCodeBlock;
4
- function cleanCodeBlock(content) {
5
- const langMatch = content.match(/^```(\w+)?/);
6
- const lang = langMatch ? langMatch[1] : null;
7
- let cleaned = content.replace(/^\uFEFF/, '');
8
- cleaned = cleaned.replace(/^```(\w+)?\s*/, '').replace(/```$/, '');
9
- cleaned = cleaned.replace(/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\u007F-\u009F]/g, '');
10
- cleaned = cleaned.trim();
11
- return { lang, cleaned };
12
- }
@@ -1,46 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = createAsciiTree;
4
- function createAsciiTree(files) {
5
- let out = "";
6
- files.forEach((file, i) => {
7
- const lastFile = i === files.length - 1;
8
- const fPrefix = lastFile ? "└── " : "├── ";
9
- const fIndent = lastFile ? " " : "│ ";
10
- out += `${fPrefix}📄 ${file.path} (${file.kind})\n`;
11
- /* -------- Imports -------- */
12
- if (file.imports.length) {
13
- out += `${fIndent}├── 📦 Imports [${file.imports.length}]\n`;
14
- file.imports.forEach((imp, idx) => {
15
- const last = idx === file.imports.length - 1;
16
- out += `${fIndent}${last ? "└── " : "├── "}${imp}\n`;
17
- });
18
- }
19
- /* -------- Exports -------- */
20
- if (file.exports.length) {
21
- out += `${fIndent}├── 🔑 Exports\n`;
22
- file.exports.forEach((e, idx) => {
23
- const last = idx === file.exports.length - 1;
24
- const main = e.name === file.mainExport ? " ⭐" : "";
25
- out += `${fIndent}${last ? "└── " : "├── "}${e.name} (${e.kind})${main}\n`;
26
- });
27
- }
28
- /* -------- Variables -------- */
29
- file.variables.forEach(v => {
30
- out += `${fIndent}├── 💡 ${v.name}: ${v.type} (${v.scope})\n`;
31
- });
32
- /* -------- Functions -------- */
33
- file.functions.forEach(fn => {
34
- out += `${fIndent}├── ⚡ ${fn.name}(${fn.params.join(", ")}): ${fn.returnType}\n`;
35
- });
36
- /* -------- Classes -------- */
37
- file.classes.forEach(cls => {
38
- out += `${fIndent}├── ⚙️ Class ${cls.name}\n`;
39
- cls.methods.forEach((m, mi) => {
40
- const last = mi === cls.methods.length - 1;
41
- out += `${fIndent}│ ${last ? "└── " : "├── "}➡️ ${m.name}(${m.params.join(", ")}): ${m.returnType}\n`;
42
- });
43
- });
44
- });
45
- return out;
46
- }
package/johankit.yaml DELETED
@@ -1,2 +0,0 @@
1
- ignore:
2
- - dist
@@ -1,119 +0,0 @@
1
- import path from "path";
2
- import { Project, SourceFile, SyntaxKind } from "ts-morph";
3
- import {
4
- FileTree,
5
- ClassInfo,
6
- FunctionInfo,
7
- VariableInfo,
8
- ExportInfo,
9
- FileKind
10
- } from "types";
11
-
12
- /**
13
- * Heurística simples para classificar arquivos
14
- */
15
- function detectFileKind(filePath: string, exportsCount: number): FileKind {
16
- if (filePath.includes("/cli/")) return "cli";
17
- if (filePath.endsWith("index.ts") || filePath.endsWith("main.ts")) return "entry";
18
- if (exportsCount === 0) return "util";
19
- if (exportsCount > 3) return "domain";
20
- return "unknown";
21
- }
22
-
23
- export async function tree(dir: string): Promise<FileTree[]> {
24
- const project = new Project({});
25
-
26
- project.addSourceFilesAtPaths([
27
- `${dir}/**/*.{ts,tsx,js,jsx}`,
28
- `!${dir}/**/node_modules/**/*`,
29
- `!${dir}/**/dist/**/*`,
30
- ]);
31
-
32
- const tree: FileTree[] = [];
33
-
34
- for (const file of project.getSourceFiles()) {
35
- const absolutePath = file.getFilePath();
36
- const filePath = path.relative(dir, absolutePath);
37
-
38
- console.log(filePath);
39
-
40
- if (filePath.includes("node_modules") || filePath.includes("/dist/")) {
41
- continue;
42
- }
43
-
44
- /* ---------------- IMPORTS ---------------- */
45
- const imports = file
46
- .getImportDeclarations()
47
- .map(i => i.getModuleSpecifierValue());
48
-
49
- /* ---------------- CLASSES ---------------- */
50
- const classes: ClassInfo[] = file.getClasses().map(cls => ({
51
- name: cls.getName() || "<anonymous>",
52
- methods: cls.getMethods().map(m => ({
53
- name: m.getName(),
54
- params: m.getParameters().map(p => p.getName()),
55
- returnType: safeType(() => m.getReturnType().getText()),
56
- scope: "class",
57
- }))
58
- }));
59
-
60
- /* ---------------- FUNCTIONS ---------------- */
61
- const functions: FunctionInfo[] = file.getFunctions().map(fn => ({
62
- name: fn.getName() || "<anonymous>",
63
- params: fn.getParameters().map(p => p.getName()),
64
- returnType: safeType(() => fn.getReturnType().getText()),
65
- scope: "global",
66
- }));
67
-
68
- /* ---------------- VARIABLES ---------------- */
69
- const variables: VariableInfo[] = file.getVariableDeclarations().map(v => ({
70
- name: v.getName(),
71
- type: safeType(() => v.getType().getText()),
72
- scope: v.getParent() instanceof SourceFile ? "global" : "local",
73
- }));
74
-
75
- /* ---------------- EXPORTS ---------------- */
76
- const exports: ExportInfo[] = [];
77
- let mainExport: string | undefined;
78
-
79
- file.getExportedDeclarations().forEach((decls, name) => {
80
- decls.forEach(d => {
81
- let kind: ExportInfo["kind"] = "unknown";
82
-
83
- if (d.getKind() === SyntaxKind.ClassDeclaration) kind = "class";
84
- if (d.getKind() === SyntaxKind.FunctionDeclaration) kind = "function";
85
- if (d.getKind() === SyntaxKind.VariableDeclaration) kind = "variable";
86
- if (d.getKind() === SyntaxKind.TypeAliasDeclaration) kind = "type";
87
-
88
- exports.push({ name, kind });
89
- });
90
- });
91
-
92
- if (exports.length === 1) {
93
- mainExport = exports[0].name;
94
- }
95
-
96
- const kind = detectFileKind(filePath, exports.length);
97
-
98
- tree.push({
99
- path: filePath,
100
- kind,
101
- imports,
102
- classes,
103
- functions,
104
- variables,
105
- exports,
106
- mainExport,
107
- });
108
- }
109
-
110
- return tree;
111
- }
112
-
113
- function safeType(fn: () => string): string {
114
- try {
115
- return fn();
116
- } catch {
117
- return "unknown";
118
- }
119
- }
@@ -1,70 +0,0 @@
1
- import createAsciiTree from "../utils/createAsciiTree";
2
- import { copy } from "../cli/commands/copy";
3
- import { paste } from "../cli/commands/paste";
4
- import { prompt } from "../cli/commands/prompt";
5
- import { tree as treeCommand } from "../cli/commands/tree";
6
- import { scanDir } from "../core/scan";
7
- import { applyDiff, DiffPatch } from "../core/diff";
8
- import { validatePatches } from "../core/validation";
9
- import { writeFiles } from "../core/write";
10
-
11
- interface JohankitServiceOptions {
12
- isolated?: boolean;
13
- }
14
-
15
- export class JohankitService {
16
- private isolated: boolean;
17
- private internalInput?: any;
18
-
19
- constructor(options: JohankitServiceOptions = {}) {
20
- this.isolated = options.isolated ?? false;
21
- }
22
-
23
- setInput(input: any) {
24
- this.internalInput = input;
25
- }
26
-
27
- async copy(dir: string = ".") {
28
- return copy(dir);
29
- }
30
-
31
- async paste(dir: string = ".") {
32
- return paste(dir);
33
- }
34
-
35
- async prompt(dir: string, userPrompt: string, diff = false) {
36
- if (!userPrompt) {
37
- throw new Error("Missing user prompt");
38
- }
39
- return prompt(dir, userPrompt, diff);
40
- }
41
-
42
- async sync(dir: string = ".", diff = false) {
43
- const snapshotBefore = scanDir(dir);
44
-
45
- const input = this.isolated ? this.internalInput : undefined;
46
-
47
- if (!this.isolated && input === undefined) {
48
- throw new Error("sync() without isolation must be used via CLI (stdin)");
49
- }
50
-
51
- if (!input) {
52
- throw new Error("No input provided for isolated sync");
53
- }
54
-
55
- if (diff) {
56
- const validated = validatePatches(input) as DiffPatch[];
57
- applyDiff(dir, validated);
58
- } else {
59
- writeFiles(dir, input, true);
60
- }
61
-
62
- const snapshotAfter = scanDir(dir);
63
- return { before: snapshotBefore, after: snapshotAfter };
64
- }
65
-
66
- async tree(dir: string = ".") {
67
- const _tree = await treeCommand(dir);
68
- return createAsciiTree(_tree);
69
- }
70
- }
@@ -1,53 +0,0 @@
1
- import { FileTree } from "types";
2
-
3
- export default function createAsciiTree(files: FileTree[]): string {
4
- let out = "";
5
-
6
- files.forEach((file, i) => {
7
- const lastFile = i === files.length - 1;
8
- const fPrefix = lastFile ? "└── " : "├── ";
9
- const fIndent = lastFile ? " " : "│ ";
10
-
11
- out += `${fPrefix}📄 ${file.path} (${file.kind})\n`;
12
-
13
- /* -------- Imports -------- */
14
- if (file.imports.length) {
15
- out += `${fIndent}├── 📦 Imports [${file.imports.length}]\n`;
16
- file.imports.forEach((imp, idx) => {
17
- const last = idx === file.imports.length - 1;
18
- out += `${fIndent}${last ? "└── " : "├── "}${imp}\n`;
19
- });
20
- }
21
-
22
- /* -------- Exports -------- */
23
- if (file.exports.length) {
24
- out += `${fIndent}├── 🔑 Exports\n`;
25
- file.exports.forEach((e, idx) => {
26
- const last = idx === file.exports.length - 1;
27
- const main = e.name === file.mainExport ? " ⭐" : "";
28
- out += `${fIndent}${last ? "└── " : "├── "}${e.name} (${e.kind})${main}\n`;
29
- });
30
- }
31
-
32
- /* -------- Variables -------- */
33
- file.variables.forEach(v => {
34
- out += `${fIndent}├── 💡 ${v.name}: ${v.type} (${v.scope})\n`;
35
- });
36
-
37
- /* -------- Functions -------- */
38
- file.functions.forEach(fn => {
39
- out += `${fIndent}├── ⚡ ${fn.name}(${fn.params.join(", ")}): ${fn.returnType}\n`;
40
- });
41
-
42
- /* -------- Classes -------- */
43
- file.classes.forEach(cls => {
44
- out += `${fIndent}├── ⚙️ Class ${cls.name}\n`;
45
- cls.methods.forEach((m, mi) => {
46
- const last = mi === cls.methods.length - 1;
47
- out += `${fIndent}│ ${last ? "└── " : "├── "}➡️ ${m.name}(${m.params.join(", ")}): ${m.returnType}\n`;
48
- });
49
- });
50
- });
51
-
52
- return out;
53
- }
package/types.ts DELETED
@@ -1,11 +0,0 @@
1
- // src/types.ts
2
- export interface FileSnapshot {
3
- path: string;
4
- content: string;
5
- type?: "modify" | "create" | "delete";
6
- }
7
-
8
- export interface ScanOptions {
9
- extensions?: string[]; // ['.js', '.ts', '.css']
10
- ignore?: string[];
11
- }
File without changes
File without changes