johankit 0.0.2 → 0.0.3

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 (52) hide show
  1. package/README.md +0 -5
  2. package/Readme.md +56 -0
  3. package/cli/commands/paste.js +42 -0
  4. package/cli/commands/paste.ts +42 -0
  5. package/cli/commands/prompt.js +59 -0
  6. package/cli/commands/prompt.ts +57 -0
  7. package/cli/commands/sync.js +83 -0
  8. package/cli/commands/sync.ts +87 -0
  9. package/commands/paste.js +42 -0
  10. package/commands/paste.ts +45 -0
  11. package/core/config.js +44 -0
  12. package/core/config.ts +42 -0
  13. package/core/schema.js +30 -0
  14. package/core/schema.ts +29 -0
  15. package/core/vm.js +20 -0
  16. package/core/vm.ts +18 -0
  17. package/dist/cli/commands/copy.js +3 -4
  18. package/dist/cli/commands/paste.js +6 -2
  19. package/dist/cli/commands/prompt.js +2 -2
  20. package/dist/core/clean.js +13 -0
  21. package/dist/utils/cleanCodeBlock.js +12 -0
  22. package/package.json +4 -2
  23. package/src/cli/commands/copy.ts +3 -4
  24. package/src/cli/commands/paste.ts +3 -2
  25. package/src/cli/commands/prompt.ts +3 -3
  26. package/src/utils/cleanCodeBlock.ts +13 -0
  27. package/tsconfig.json +4 -0
  28. package/dist/tests/cli/commands/copy.test.js +0 -47
  29. package/dist/tests/cli/commands/paste.test.js +0 -41
  30. package/dist/tests/cli/commands/prompt.test.js +0 -37
  31. package/dist/tests/cli/commands/sync.test.js +0 -47
  32. package/dist/tests/core/clipboard.test.js +0 -20
  33. package/dist/tests/core/config.test.js +0 -23
  34. package/dist/tests/core/diff.test.js +0 -24
  35. package/dist/tests/core/git.test.js +0 -11
  36. package/dist/tests/core/scan.test.js +0 -16
  37. package/dist/tests/core/schema.test.js +0 -13
  38. package/dist/tests/core/validation.test.js +0 -13
  39. package/dist/tests/core/write.test.js +0 -41
  40. package/package-lock.json +0 -250
  41. package/src/tests/cli/commands/copy.test.ts +0 -26
  42. package/src/tests/cli/commands/paste.test.ts +0 -19
  43. package/src/tests/cli/commands/prompt.test.ts +0 -14
  44. package/src/tests/cli/commands/sync.test.ts +0 -26
  45. package/src/tests/core/clipboard.test.ts +0 -21
  46. package/src/tests/core/config.test.ts +0 -21
  47. package/src/tests/core/diff.test.ts +0 -22
  48. package/src/tests/core/git.test.ts +0 -11
  49. package/src/tests/core/scan.test.ts +0 -13
  50. package/src/tests/core/schema.test.ts +0 -13
  51. package/src/tests/core/validation.test.ts +0 -13
  52. package/src/tests/core/write.test.ts +0 -15
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
- });
@@ -1,21 +0,0 @@
1
- import { copyToClipboard, readClipboard } from '../../../core/clipboard';
2
- import { spawn } from 'child_process';
3
-
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') cb(0); })
10
- }))
11
- }));
12
-
13
- describe('clipboard', () => {
14
- it('should copy to clipboard', async () => {
15
- await expect(copyToClipboard('hi')).resolves.toBeUndefined();
16
- });
17
-
18
- it('should read from clipboard', async () => {
19
- await expect(readClipboard()).resolves.toBe('');
20
- });
21
- });
@@ -1,21 +0,0 @@
1
- import { loadConfig } from '../../../core/config';
2
- import fs from 'fs';
3
- import { load as yamlLoad } from 'js-yaml';
4
-
5
- jest.mock('fs');
6
- jest.mock('js-yaml');
7
-
8
- describe('loadConfig', () => {
9
- it('should return defaults if file missing', () => {
10
- (fs.readFileSync as jest.Mock).mockImplementation(() => { throw { code: 'ENOENT' }; });
11
- const config = loadConfig('.');
12
- expect(config.ignore).toContain('.git');
13
- });
14
-
15
- it('should merge user ignore', () => {
16
- (fs.readFileSync as jest.Mock).mockReturnValue('ignore:\n - test');
17
- (yamlLoad as jest.Mock).mockReturnValue({ ignore: ['test'] });
18
- const config = loadConfig('.');
19
- expect(config.ignore).toContain('test');
20
- });
21
- });
@@ -1,22 +0,0 @@
1
- import { applyDiff, DiffPatch } from '../../../core/diff';
2
- import fs from 'fs';
3
-
4
- jest.mock('fs');
5
-
6
- describe('applyDiff', () => {
7
- it('should handle create and modify', () => {
8
- const patches: DiffPatch[] = [
9
- { type: 'create', path: 'a.txt', content: 'x' },
10
- { type: 'modify', path: 'b.txt', content: 'y' }
11
- ];
12
- applyDiff('.', patches);
13
- expect(fs.writeFileSync).toHaveBeenCalledTimes(2);
14
- });
15
-
16
- it('should handle delete', () => {
17
- (fs.existsSync as jest.Mock).mockReturnValue(true);
18
- const patches: DiffPatch[] = [{ type: 'delete', path: 'c.txt' }];
19
- applyDiff('.', patches);
20
- expect(fs.unlinkSync).toHaveBeenCalledWith('./c.txt');
21
- });
22
- });
@@ -1,11 +0,0 @@
1
- import { ensureGitCommit } from '../../../core/git';
2
- import { execSync } from 'child_process';
3
-
4
- jest.mock('child_process');
5
-
6
- describe('ensureGitCommit', () => {
7
- it('should call git commands without crashing', () => {
8
- (execSync as jest.Mock).mockImplementation(() => '');
9
- expect(() => ensureGitCommit()).not.toThrow();
10
- });
11
- });
@@ -1,13 +0,0 @@
1
- import { scanDir } from '../../../core/scan';
2
- import fs from 'fs';
3
-
4
- jest.mock('fs');
5
-
6
- describe('scanDir', () => {
7
- it('should scan files with default ignores', () => {
8
- (fs.readdirSync as jest.Mock).mockReturnValue([{ name: 'a.txt', isDirectory: () => false }]);
9
- (fs.readFileSync as jest.Mock).mockReturnValue('content');
10
- const files = scanDir('.');
11
- expect(files[0].path).toBe('a.txt');
12
- });
13
- });
@@ -1,13 +0,0 @@
1
- import { validatePatches } from '../../../core/schema';
2
-
3
- describe('validatePatches', () => {
4
- it('should validate correct patches', () => {
5
- const patches = [{ type: 'create', path: 'a.txt', content: 'x' }];
6
- expect(validatePatches(patches)).toEqual(patches);
7
- });
8
-
9
- it('should throw on invalid patches', () => {
10
- const patches = [{ type: 'invalid', path: 'a.txt', content: 'x' }];
11
- expect(() => validatePatches(patches)).toThrow();
12
- });
13
- });
@@ -1,13 +0,0 @@
1
- import { validatePatches } from '../../../core/validation';
2
-
3
- describe('validation', () => {
4
- it('validates correct array', () => {
5
- const input = [{ type: 'create', path: 'a.txt', content: 'x' }];
6
- expect(validatePatches(input)).toEqual(input);
7
- });
8
-
9
- it('throws on missing content', () => {
10
- const input = [{ type: 'create', path: 'a.txt' }];
11
- expect(() => validatePatches(input)).toThrow();
12
- });
13
- });
@@ -1,15 +0,0 @@
1
- import { writeFiles } from '../../../core/write';
2
- import fs from 'fs';
3
- import * as git from '../../../core/git';
4
-
5
- jest.mock('fs');
6
- jest.mock('../../../core/git');
7
-
8
- describe('writeFiles', () => {
9
- it('should write files and commit', () => {
10
- const files = [{ path: 'a.txt', content: 'x' }];
11
- writeFiles('.', files, true);
12
- expect(fs.writeFileSync).toHaveBeenCalledWith('./a.txt', 'x', 'utf8');
13
- expect(git.ensureGitCommit).toHaveBeenCalled();
14
- });
15
- });