johankit 0.0.2 → 0.0.4

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 (50) hide show
  1. package/README.md +0 -5
  2. package/Readme.md +56 -0
  3. package/dist/cli/commands/copy.js +3 -4
  4. package/dist/cli/commands/paste.js +19 -10
  5. package/dist/cli/commands/prompt.js +40 -8
  6. package/dist/cli/commands/sync.js +10 -6
  7. package/dist/cli/commands/three.js +106 -0
  8. package/dist/index.js +52 -34
  9. package/dist/services/JohankitService.js +59 -0
  10. package/dist/utils/cleanCodeBlock.js +12 -0
  11. package/dist/utils/createAsciiTree.js +46 -0
  12. package/johankit.yaml +2 -0
  13. package/package.json +5 -2
  14. package/src/cli/commands/copy.ts +3 -4
  15. package/src/cli/commands/paste.ts +16 -16
  16. package/src/cli/commands/prompt.ts +47 -9
  17. package/src/cli/commands/sync.ts +8 -6
  18. package/src/cli/commands/three.ts +117 -0
  19. package/src/core/scan.ts +1 -1
  20. package/src/index.ts +54 -37
  21. package/src/services/JohankitService.ts +70 -0
  22. package/src/types.ts +45 -0
  23. package/src/utils/cleanCodeBlock.ts +13 -0
  24. package/src/utils/createAsciiTree.ts +53 -0
  25. package/tsconfig.json +4 -0
  26. package/dist/tests/cli/commands/copy.test.js +0 -47
  27. package/dist/tests/cli/commands/paste.test.js +0 -41
  28. package/dist/tests/cli/commands/prompt.test.js +0 -37
  29. package/dist/tests/cli/commands/sync.test.js +0 -47
  30. package/dist/tests/core/clipboard.test.js +0 -20
  31. package/dist/tests/core/config.test.js +0 -23
  32. package/dist/tests/core/diff.test.js +0 -24
  33. package/dist/tests/core/git.test.js +0 -11
  34. package/dist/tests/core/scan.test.js +0 -16
  35. package/dist/tests/core/schema.test.js +0 -13
  36. package/dist/tests/core/validation.test.js +0 -13
  37. package/dist/tests/core/write.test.js +0 -41
  38. package/package-lock.json +0 -250
  39. package/src/tests/cli/commands/copy.test.ts +0 -26
  40. package/src/tests/cli/commands/paste.test.ts +0 -19
  41. package/src/tests/cli/commands/prompt.test.ts +0 -14
  42. package/src/tests/cli/commands/sync.test.ts +0 -26
  43. package/src/tests/core/clipboard.test.ts +0 -21
  44. package/src/tests/core/config.test.ts +0 -21
  45. package/src/tests/core/diff.test.ts +0 -22
  46. package/src/tests/core/git.test.ts +0 -11
  47. package/src/tests/core/scan.test.ts +0 -13
  48. package/src/tests/core/schema.test.ts +0 -13
  49. package/src/tests/core/validation.test.ts +0 -13
  50. package/src/tests/core/write.test.ts +0 -15
@@ -1,41 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- const paste_1 = require("../../../cli/commands/paste");
27
- const clipboard = __importStar(require("../../../core/clipboard"));
28
- const write = __importStar(require("../../../core/write"));
29
- jest.mock('../../../core/clipboard');
30
- jest.mock('../../../core/write');
31
- describe('paste', () => {
32
- it('should write files from clipboard JSON', async () => {
33
- clipboard.readClipboard.mockResolvedValue(JSON.stringify([{ path: 'a.txt', content: 'hi' }]));
34
- await (0, paste_1.paste)('dir');
35
- expect(write.writeFiles).toHaveBeenCalledWith('dir', [{ path: 'a.txt', content: 'hi' }], true);
36
- });
37
- it('should throw on invalid JSON', async () => {
38
- clipboard.readClipboard.mockResolvedValue('not json');
39
- await expect((0, paste_1.paste)('dir')).rejects.toThrow('Clipboard content is not valid JSON');
40
- });
41
- });
@@ -1,37 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- const prompt_1 = require("../../../cli/commands/prompt");
27
- const scan = __importStar(require("../../../core/scan"));
28
- const clipboard = __importStar(require("../../../core/clipboard"));
29
- jest.mock('../../../core/scan');
30
- jest.mock('../../../core/clipboard');
31
- describe('prompt', () => {
32
- it('should generate prompt with snapshot and copy to clipboard', async () => {
33
- scan.scanDir.mockReturnValue([{ path: 'file.js', content: 'console.log(1)' }]);
34
- await (0, prompt_1.prompt)('.', 'do something');
35
- expect(clipboard.copyToClipboard).toHaveBeenCalled();
36
- });
37
- });
@@ -1,47 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- const sync_1 = require("../../../cli/commands/sync");
27
- const scan = __importStar(require("../../../core/scan"));
28
- const clipboard = __importStar(require("../../../core/clipboard"));
29
- const diff = __importStar(require("../../../core/diff"));
30
- const validation = __importStar(require("../../../core/validation"));
31
- jest.mock('../../../core/scan');
32
- jest.mock('../../../core/clipboard');
33
- jest.mock('../../../core/diff');
34
- jest.mock('../../../core/validation');
35
- describe('sync', () => {
36
- it('should apply patches and update clipboard', async () => {
37
- scan.scanDir.mockReturnValue([]);
38
- clipboard.copyToClipboard.mockResolvedValue(undefined);
39
- validation.validatePatches.mockImplementation(p => p);
40
- const input = JSON.stringify([{ type: 'create', path: 'a.txt', content: 'x' }]);
41
- process.stdin.push(input);
42
- process.stdin.push(null);
43
- await (0, sync_1.sync)('.');
44
- expect(diff.applyDiff).toHaveBeenCalled();
45
- expect(clipboard.copyToClipboard).toHaveBeenCalledTimes(2);
46
- });
47
- });
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const clipboard_1 = require("../../../core/clipboard");
4
- jest.mock('child_process', () => ({
5
- spawn: jest.fn(() => ({
6
- stdin: { write: jest.fn(), end: jest.fn() },
7
- stdout: { on: jest.fn() },
8
- stderr: { on: jest.fn() },
9
- on: jest.fn((event, cb) => { if (event === 'close')
10
- cb(0); })
11
- }))
12
- }));
13
- describe('clipboard', () => {
14
- it('should copy to clipboard', async () => {
15
- await expect((0, clipboard_1.copyToClipboard)('hi')).resolves.toBeUndefined();
16
- });
17
- it('should read from clipboard', async () => {
18
- await expect((0, clipboard_1.readClipboard)()).resolves.toBe('');
19
- });
20
- });
@@ -1,23 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const config_1 = require("../../../core/config");
7
- const fs_1 = __importDefault(require("fs"));
8
- const js_yaml_1 = require("js-yaml");
9
- jest.mock('fs');
10
- jest.mock('js-yaml');
11
- describe('loadConfig', () => {
12
- it('should return defaults if file missing', () => {
13
- fs_1.default.readFileSync.mockImplementation(() => { throw { code: 'ENOENT' }; });
14
- const config = (0, config_1.loadConfig)('.');
15
- expect(config.ignore).toContain('.git');
16
- });
17
- it('should merge user ignore', () => {
18
- fs_1.default.readFileSync.mockReturnValue('ignore:\n - test');
19
- js_yaml_1.load.mockReturnValue({ ignore: ['test'] });
20
- const config = (0, config_1.loadConfig)('.');
21
- expect(config.ignore).toContain('test');
22
- });
23
- });
@@ -1,24 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const diff_1 = require("../../../core/diff");
7
- const fs_1 = __importDefault(require("fs"));
8
- jest.mock('fs');
9
- describe('applyDiff', () => {
10
- it('should handle create and modify', () => {
11
- const patches = [
12
- { type: 'create', path: 'a.txt', content: 'x' },
13
- { type: 'modify', path: 'b.txt', content: 'y' }
14
- ];
15
- (0, diff_1.applyDiff)('.', patches);
16
- expect(fs_1.default.writeFileSync).toHaveBeenCalledTimes(2);
17
- });
18
- it('should handle delete', () => {
19
- fs_1.default.existsSync.mockReturnValue(true);
20
- const patches = [{ type: 'delete', path: 'c.txt' }];
21
- (0, diff_1.applyDiff)('.', patches);
22
- expect(fs_1.default.unlinkSync).toHaveBeenCalledWith('./c.txt');
23
- });
24
- });
@@ -1,11 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const git_1 = require("../../../core/git");
4
- const child_process_1 = require("child_process");
5
- jest.mock('child_process');
6
- describe('ensureGitCommit', () => {
7
- it('should call git commands without crashing', () => {
8
- child_process_1.execSync.mockImplementation(() => '');
9
- expect(() => (0, git_1.ensureGitCommit)()).not.toThrow();
10
- });
11
- });
@@ -1,16 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const scan_1 = require("../../../core/scan");
7
- const fs_1 = __importDefault(require("fs"));
8
- jest.mock('fs');
9
- describe('scanDir', () => {
10
- it('should scan files with default ignores', () => {
11
- fs_1.default.readdirSync.mockReturnValue([{ name: 'a.txt', isDirectory: () => false }]);
12
- fs_1.default.readFileSync.mockReturnValue('content');
13
- const files = (0, scan_1.scanDir)('.');
14
- expect(files[0].path).toBe('a.txt');
15
- });
16
- });
@@ -1,13 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const schema_1 = require("../../../core/schema");
4
- describe('validatePatches', () => {
5
- it('should validate correct patches', () => {
6
- const patches = [{ type: 'create', path: 'a.txt', content: 'x' }];
7
- expect((0, schema_1.validatePatches)(patches)).toEqual(patches);
8
- });
9
- it('should throw on invalid patches', () => {
10
- const patches = [{ type: 'invalid', path: 'a.txt', content: 'x' }];
11
- expect(() => (0, schema_1.validatePatches)(patches)).toThrow();
12
- });
13
- });
@@ -1,13 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const validation_1 = require("../../../core/validation");
4
- describe('validation', () => {
5
- it('validates correct array', () => {
6
- const input = [{ type: 'create', path: 'a.txt', content: 'x' }];
7
- expect((0, validation_1.validatePatches)(input)).toEqual(input);
8
- });
9
- it('throws on missing content', () => {
10
- const input = [{ type: 'create', path: 'a.txt' }];
11
- expect(() => (0, validation_1.validatePatches)(input)).toThrow();
12
- });
13
- });
@@ -1,41 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- const write_1 = require("../../../core/write");
30
- const fs_1 = __importDefault(require("fs"));
31
- const git = __importStar(require("../../../core/git"));
32
- jest.mock('fs');
33
- jest.mock('../../../core/git');
34
- describe('writeFiles', () => {
35
- it('should write files and commit', () => {
36
- const files = [{ path: 'a.txt', content: 'x' }];
37
- (0, write_1.writeFiles)('.', files, true);
38
- expect(fs_1.default.writeFileSync).toHaveBeenCalledWith('./a.txt', 'x', 'utf8');
39
- expect(git.ensureGitCommit).toHaveBeenCalled();
40
- });
41
- });
package/package-lock.json DELETED
@@ -1,250 +0,0 @@
1
- {
2
- "name": "johankit",
3
- "version": "1.0.0",
4
- "lockfileVersion": 3,
5
- "requires": true,
6
- "packages": {
7
- "": {
8
- "name": "johankit",
9
- "version": "1.0.0",
10
- "license": "ISC",
11
- "dependencies": {
12
- "commander": "^14.0.2"
13
- },
14
- "devDependencies": {
15
- "@types/node": "^25.0.1",
16
- "ts-node": "^10.9.2",
17
- "typescript": "^5.9.3"
18
- }
19
- },
20
- "node_modules/@cspotcode/source-map-support": {
21
- "version": "0.8.1",
22
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
23
- "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
24
- "dev": true,
25
- "license": "MIT",
26
- "dependencies": {
27
- "@jridgewell/trace-mapping": "0.3.9"
28
- },
29
- "engines": {
30
- "node": ">=12"
31
- }
32
- },
33
- "node_modules/@jridgewell/resolve-uri": {
34
- "version": "3.1.2",
35
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
36
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
37
- "dev": true,
38
- "license": "MIT",
39
- "engines": {
40
- "node": ">=6.0.0"
41
- }
42
- },
43
- "node_modules/@jridgewell/sourcemap-codec": {
44
- "version": "1.5.5",
45
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
46
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
47
- "dev": true,
48
- "license": "MIT"
49
- },
50
- "node_modules/@jridgewell/trace-mapping": {
51
- "version": "0.3.9",
52
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
53
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
54
- "dev": true,
55
- "license": "MIT",
56
- "dependencies": {
57
- "@jridgewell/resolve-uri": "^3.0.3",
58
- "@jridgewell/sourcemap-codec": "^1.4.10"
59
- }
60
- },
61
- "node_modules/@tsconfig/node10": {
62
- "version": "1.0.12",
63
- "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
64
- "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==",
65
- "dev": true,
66
- "license": "MIT"
67
- },
68
- "node_modules/@tsconfig/node12": {
69
- "version": "1.0.11",
70
- "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
71
- "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
72
- "dev": true,
73
- "license": "MIT"
74
- },
75
- "node_modules/@tsconfig/node14": {
76
- "version": "1.0.3",
77
- "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
78
- "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
79
- "dev": true,
80
- "license": "MIT"
81
- },
82
- "node_modules/@tsconfig/node16": {
83
- "version": "1.0.4",
84
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
85
- "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
86
- "dev": true,
87
- "license": "MIT"
88
- },
89
- "node_modules/@types/node": {
90
- "version": "25.0.1",
91
- "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.1.tgz",
92
- "integrity": "sha512-czWPzKIAXucn9PtsttxmumiQ9N0ok9FrBwgRWrwmVLlp86BrMExzvXRLFYRJ+Ex3g6yqj+KuaxfX1JTgV2lpfg==",
93
- "dev": true,
94
- "license": "MIT",
95
- "peer": true,
96
- "dependencies": {
97
- "undici-types": "~7.16.0"
98
- }
99
- },
100
- "node_modules/acorn": {
101
- "version": "8.15.0",
102
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
103
- "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
104
- "dev": true,
105
- "license": "MIT",
106
- "bin": {
107
- "acorn": "bin/acorn"
108
- },
109
- "engines": {
110
- "node": ">=0.4.0"
111
- }
112
- },
113
- "node_modules/acorn-walk": {
114
- "version": "8.3.4",
115
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
116
- "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
117
- "dev": true,
118
- "license": "MIT",
119
- "dependencies": {
120
- "acorn": "^8.11.0"
121
- },
122
- "engines": {
123
- "node": ">=0.4.0"
124
- }
125
- },
126
- "node_modules/arg": {
127
- "version": "4.1.3",
128
- "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
129
- "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
130
- "dev": true,
131
- "license": "MIT"
132
- },
133
- "node_modules/commander": {
134
- "version": "14.0.2",
135
- "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz",
136
- "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==",
137
- "license": "MIT",
138
- "engines": {
139
- "node": ">=20"
140
- }
141
- },
142
- "node_modules/create-require": {
143
- "version": "1.1.1",
144
- "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
145
- "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
146
- "dev": true,
147
- "license": "MIT"
148
- },
149
- "node_modules/diff": {
150
- "version": "4.0.2",
151
- "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
152
- "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
153
- "dev": true,
154
- "license": "BSD-3-Clause",
155
- "engines": {
156
- "node": ">=0.3.1"
157
- }
158
- },
159
- "node_modules/make-error": {
160
- "version": "1.3.6",
161
- "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
162
- "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
163
- "dev": true,
164
- "license": "ISC"
165
- },
166
- "node_modules/ts-node": {
167
- "version": "10.9.2",
168
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
169
- "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
170
- "dev": true,
171
- "license": "MIT",
172
- "dependencies": {
173
- "@cspotcode/source-map-support": "^0.8.0",
174
- "@tsconfig/node10": "^1.0.7",
175
- "@tsconfig/node12": "^1.0.7",
176
- "@tsconfig/node14": "^1.0.0",
177
- "@tsconfig/node16": "^1.0.2",
178
- "acorn": "^8.4.1",
179
- "acorn-walk": "^8.1.1",
180
- "arg": "^4.1.0",
181
- "create-require": "^1.1.0",
182
- "diff": "^4.0.1",
183
- "make-error": "^1.1.1",
184
- "v8-compile-cache-lib": "^3.0.1",
185
- "yn": "3.1.1"
186
- },
187
- "bin": {
188
- "ts-node": "dist/bin.js",
189
- "ts-node-cwd": "dist/bin-cwd.js",
190
- "ts-node-esm": "dist/bin-esm.js",
191
- "ts-node-script": "dist/bin-script.js",
192
- "ts-node-transpile-only": "dist/bin-transpile.js",
193
- "ts-script": "dist/bin-script-deprecated.js"
194
- },
195
- "peerDependencies": {
196
- "@swc/core": ">=1.2.50",
197
- "@swc/wasm": ">=1.2.50",
198
- "@types/node": "*",
199
- "typescript": ">=2.7"
200
- },
201
- "peerDependenciesMeta": {
202
- "@swc/core": {
203
- "optional": true
204
- },
205
- "@swc/wasm": {
206
- "optional": true
207
- }
208
- }
209
- },
210
- "node_modules/typescript": {
211
- "version": "5.9.3",
212
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
213
- "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
214
- "dev": true,
215
- "license": "Apache-2.0",
216
- "peer": true,
217
- "bin": {
218
- "tsc": "bin/tsc",
219
- "tsserver": "bin/tsserver"
220
- },
221
- "engines": {
222
- "node": ">=14.17"
223
- }
224
- },
225
- "node_modules/undici-types": {
226
- "version": "7.16.0",
227
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
228
- "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
229
- "dev": true,
230
- "license": "MIT"
231
- },
232
- "node_modules/v8-compile-cache-lib": {
233
- "version": "3.0.1",
234
- "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
235
- "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
236
- "dev": true,
237
- "license": "MIT"
238
- },
239
- "node_modules/yn": {
240
- "version": "3.1.1",
241
- "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
242
- "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
243
- "dev": true,
244
- "license": "MIT",
245
- "engines": {
246
- "node": ">=6"
247
- }
248
- }
249
- }
250
- }
@@ -1,26 +0,0 @@
1
- import { copy } from '../../../cli/commands/copy';
2
- import * as scan from '../../../core/scan';
3
- import * as clipboard from '../../../core/clipboard';
4
-
5
- jest.mock('../../../core/scan');
6
- jest.mock('../../../core/clipboard');
7
-
8
- describe('copy', () => {
9
- it('should copy single file snapshot to clipboard', () => {
10
- (scan.scanDir as jest.Mock).mockReturnValue([{ path: 'file.txt', content: 'hello' }]);
11
- copy('file.txt');
12
- expect(clipboard.copyToClipboard).toHaveBeenCalledWith(JSON.stringify([{ path: 'file.txt', content: 'hello' }], null, 2));
13
- });
14
-
15
- it('should copy multiple file snapshots to clipboard', () => {
16
- (scan.scanDir as jest.Mock)
17
- .mockReturnValueOnce([{ path: 'file1.txt', content: 'a' }])
18
- .mockReturnValueOnce([{ path: 'file2.txt', content: 'b' }]);
19
-
20
- copy(['file1.txt', 'file2.txt']);
21
- expect(clipboard.copyToClipboard).toHaveBeenCalledWith(JSON.stringify([
22
- { path: 'file1.txt', content: 'a' },
23
- { path: 'file2.txt', content: 'b' }
24
- ], null, 2));
25
- });
26
- });
@@ -1,19 +0,0 @@
1
- import { paste } from '../../../cli/commands/paste';
2
- import * as clipboard from '../../../core/clipboard';
3
- import * as write from '../../../core/write';
4
-
5
- jest.mock('../../../core/clipboard');
6
- jest.mock('../../../core/write');
7
-
8
- describe('paste', () => {
9
- it('should write files from clipboard JSON', async () => {
10
- (clipboard.readClipboard as jest.Mock).mockResolvedValue(JSON.stringify([{ path: 'a.txt', content: 'hi' }]));
11
- await paste('dir');
12
- expect(write.writeFiles).toHaveBeenCalledWith('dir', [{ path: 'a.txt', content: 'hi' }], true);
13
- });
14
-
15
- it('should throw on invalid JSON', async () => {
16
- (clipboard.readClipboard as jest.Mock).mockResolvedValue('not json');
17
- await expect(paste('dir')).rejects.toThrow('Clipboard content is not valid JSON');
18
- });
19
- });
@@ -1,14 +0,0 @@
1
- import { prompt } from '../../../cli/commands/prompt';
2
- import * as scan from '../../../core/scan';
3
- import * as clipboard from '../../../core/clipboard';
4
-
5
- jest.mock('../../../core/scan');
6
- jest.mock('../../../core/clipboard');
7
-
8
- describe('prompt', () => {
9
- it('should generate prompt with snapshot and copy to clipboard', async () => {
10
- (scan.scanDir as jest.Mock).mockReturnValue([{ path: 'file.js', content: 'console.log(1)' }]);
11
- await prompt('.', 'do something');
12
- expect(clipboard.copyToClipboard).toHaveBeenCalled();
13
- });
14
- });
@@ -1,26 +0,0 @@
1
- import { sync } from '../../../cli/commands/sync';
2
- import * as scan from '../../../core/scan';
3
- import * as clipboard from '../../../core/clipboard';
4
- import * as diff from '../../../core/diff';
5
- import * as validation from '../../../core/validation';
6
-
7
- jest.mock('../../../core/scan');
8
- jest.mock('../../../core/clipboard');
9
- jest.mock('../../../core/diff');
10
- jest.mock('../../../core/validation');
11
-
12
- describe('sync', () => {
13
- it('should apply patches and update clipboard', async () => {
14
- (scan.scanDir as jest.Mock).mockReturnValue([]);
15
- (clipboard.copyToClipboard as jest.Mock).mockResolvedValue(undefined);
16
- (validation.validatePatches as jest.Mock).mockImplementation(p => p);
17
-
18
- const input = JSON.stringify([{ type: 'create', path: 'a.txt', content: 'x' }]);
19
- process.stdin.push(input);
20
- process.stdin.push(null);
21
-
22
- await sync('.');
23
- expect(diff.applyDiff).toHaveBeenCalled();
24
- expect(clipboard.copyToClipboard).toHaveBeenCalledTimes(2);
25
- });
26
- });