i18nsmith 0.1.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 (213) hide show
  1. package/dist/commands/audit.d.ts +3 -0
  2. package/dist/commands/audit.d.ts.map +1 -0
  3. package/dist/commands/audit.js +180 -0
  4. package/dist/commands/audit.js.map +1 -0
  5. package/dist/commands/backup.d.ts +6 -0
  6. package/dist/commands/backup.d.ts.map +1 -0
  7. package/dist/commands/backup.js +85 -0
  8. package/dist/commands/backup.js.map +1 -0
  9. package/dist/commands/check.d.ts +3 -0
  10. package/dist/commands/check.d.ts.map +1 -0
  11. package/dist/commands/check.js +151 -0
  12. package/dist/commands/check.js.map +1 -0
  13. package/dist/commands/config.d.ts +3 -0
  14. package/dist/commands/config.d.ts.map +1 -0
  15. package/dist/commands/config.js +235 -0
  16. package/dist/commands/config.js.map +1 -0
  17. package/dist/commands/debug-patterns.d.ts +3 -0
  18. package/dist/commands/debug-patterns.d.ts.map +1 -0
  19. package/dist/commands/debug-patterns.js +192 -0
  20. package/dist/commands/debug-patterns.js.map +1 -0
  21. package/dist/commands/debug-patterns.test.d.ts +2 -0
  22. package/dist/commands/debug-patterns.test.d.ts.map +1 -0
  23. package/dist/commands/debug-patterns.test.js +109 -0
  24. package/dist/commands/debug-patterns.test.js.map +1 -0
  25. package/dist/commands/diagnose.d.ts +3 -0
  26. package/dist/commands/diagnose.d.ts.map +1 -0
  27. package/dist/commands/diagnose.js +117 -0
  28. package/dist/commands/diagnose.js.map +1 -0
  29. package/dist/commands/init.d.ts +8 -0
  30. package/dist/commands/init.d.ts.map +1 -0
  31. package/dist/commands/init.js +450 -0
  32. package/dist/commands/init.js.map +1 -0
  33. package/dist/commands/init.test.d.ts +2 -0
  34. package/dist/commands/init.test.d.ts.map +1 -0
  35. package/dist/commands/init.test.js +74 -0
  36. package/dist/commands/init.test.js.map +1 -0
  37. package/dist/commands/install-hooks.d.ts +3 -0
  38. package/dist/commands/install-hooks.d.ts.map +1 -0
  39. package/dist/commands/install-hooks.js +52 -0
  40. package/dist/commands/install-hooks.js.map +1 -0
  41. package/dist/commands/preflight.d.ts +7 -0
  42. package/dist/commands/preflight.d.ts.map +1 -0
  43. package/dist/commands/preflight.js +417 -0
  44. package/dist/commands/preflight.js.map +1 -0
  45. package/dist/commands/preflight.test.d.ts +5 -0
  46. package/dist/commands/preflight.test.d.ts.map +1 -0
  47. package/dist/commands/preflight.test.js +108 -0
  48. package/dist/commands/preflight.test.js.map +1 -0
  49. package/dist/commands/rename.d.ts +6 -0
  50. package/dist/commands/rename.d.ts.map +1 -0
  51. package/dist/commands/rename.js +204 -0
  52. package/dist/commands/rename.js.map +1 -0
  53. package/dist/commands/scaffold-adapter.d.ts +3 -0
  54. package/dist/commands/scaffold-adapter.d.ts.map +1 -0
  55. package/dist/commands/scaffold-adapter.js +204 -0
  56. package/dist/commands/scaffold-adapter.js.map +1 -0
  57. package/dist/commands/scaffold-adapter.test.d.ts +2 -0
  58. package/dist/commands/scaffold-adapter.test.d.ts.map +1 -0
  59. package/dist/commands/scaffold-adapter.test.js +102 -0
  60. package/dist/commands/scaffold-adapter.test.js.map +1 -0
  61. package/dist/commands/scan.d.ts +3 -0
  62. package/dist/commands/scan.d.ts.map +1 -0
  63. package/dist/commands/scan.js +93 -0
  64. package/dist/commands/scan.js.map +1 -0
  65. package/dist/commands/sync-seed.test.d.ts +2 -0
  66. package/dist/commands/sync-seed.test.d.ts.map +1 -0
  67. package/dist/commands/sync-seed.test.js +86 -0
  68. package/dist/commands/sync-seed.test.js.map +1 -0
  69. package/dist/commands/sync.d.ts +3 -0
  70. package/dist/commands/sync.d.ts.map +1 -0
  71. package/dist/commands/sync.js +590 -0
  72. package/dist/commands/sync.js.map +1 -0
  73. package/dist/commands/transform.d.ts +3 -0
  74. package/dist/commands/transform.d.ts.map +1 -0
  75. package/dist/commands/transform.js +114 -0
  76. package/dist/commands/transform.js.map +1 -0
  77. package/dist/commands/translate/csv-handler.d.ts +21 -0
  78. package/dist/commands/translate/csv-handler.d.ts.map +1 -0
  79. package/dist/commands/translate/csv-handler.js +270 -0
  80. package/dist/commands/translate/csv-handler.js.map +1 -0
  81. package/dist/commands/translate/executor.d.ts +31 -0
  82. package/dist/commands/translate/executor.d.ts.map +1 -0
  83. package/dist/commands/translate/executor.js +117 -0
  84. package/dist/commands/translate/executor.js.map +1 -0
  85. package/dist/commands/translate/index.d.ts +10 -0
  86. package/dist/commands/translate/index.d.ts.map +1 -0
  87. package/dist/commands/translate/index.js +170 -0
  88. package/dist/commands/translate/index.js.map +1 -0
  89. package/dist/commands/translate/reporter.d.ts +29 -0
  90. package/dist/commands/translate/reporter.d.ts.map +1 -0
  91. package/dist/commands/translate/reporter.js +103 -0
  92. package/dist/commands/translate/reporter.js.map +1 -0
  93. package/dist/commands/translate/types.d.ts +50 -0
  94. package/dist/commands/translate/types.d.ts.map +1 -0
  95. package/dist/commands/translate/types.js +5 -0
  96. package/dist/commands/translate/types.js.map +1 -0
  97. package/dist/commands/translate.d.ts +7 -0
  98. package/dist/commands/translate.d.ts.map +1 -0
  99. package/dist/commands/translate.js +7 -0
  100. package/dist/commands/translate.js.map +1 -0
  101. package/dist/commands/translate.test.d.ts +2 -0
  102. package/dist/commands/translate.test.d.ts.map +1 -0
  103. package/dist/commands/translate.test.js +118 -0
  104. package/dist/commands/translate.test.js.map +1 -0
  105. package/dist/e2e.test.d.ts +6 -0
  106. package/dist/e2e.test.d.ts.map +1 -0
  107. package/dist/e2e.test.js +376 -0
  108. package/dist/e2e.test.js.map +1 -0
  109. package/dist/index.d.ts +4 -0
  110. package/dist/index.d.ts.map +1 -0
  111. package/dist/index.js +39 -0
  112. package/dist/index.js.map +1 -0
  113. package/dist/integration.test.d.ts +6 -0
  114. package/dist/integration.test.d.ts.map +1 -0
  115. package/dist/integration.test.js +320 -0
  116. package/dist/integration.test.js.map +1 -0
  117. package/dist/utils/diagnostics-exit.d.ts +12 -0
  118. package/dist/utils/diagnostics-exit.d.ts.map +1 -0
  119. package/dist/utils/diagnostics-exit.js +49 -0
  120. package/dist/utils/diagnostics-exit.js.map +1 -0
  121. package/dist/utils/diagnostics-exit.test.d.ts +2 -0
  122. package/dist/utils/diagnostics-exit.test.d.ts.map +1 -0
  123. package/dist/utils/diagnostics-exit.test.js +40 -0
  124. package/dist/utils/diagnostics-exit.test.js.map +1 -0
  125. package/dist/utils/diff-utils.d.ts +4 -0
  126. package/dist/utils/diff-utils.d.ts.map +1 -0
  127. package/dist/utils/diff-utils.js +30 -0
  128. package/dist/utils/diff-utils.js.map +1 -0
  129. package/dist/utils/diff-utils.test.d.ts +2 -0
  130. package/dist/utils/diff-utils.test.d.ts.map +1 -0
  131. package/dist/utils/diff-utils.test.js +30 -0
  132. package/dist/utils/diff-utils.test.js.map +1 -0
  133. package/dist/utils/exit-codes.d.ts +142 -0
  134. package/dist/utils/exit-codes.d.ts.map +1 -0
  135. package/dist/utils/exit-codes.js +168 -0
  136. package/dist/utils/exit-codes.js.map +1 -0
  137. package/dist/utils/package-manager.d.ts +4 -0
  138. package/dist/utils/package-manager.d.ts.map +1 -0
  139. package/dist/utils/package-manager.js +40 -0
  140. package/dist/utils/package-manager.js.map +1 -0
  141. package/dist/utils/pkg.d.ts +3 -0
  142. package/dist/utils/pkg.d.ts.map +1 -0
  143. package/dist/utils/pkg.js +24 -0
  144. package/dist/utils/pkg.js.map +1 -0
  145. package/dist/utils/provider-injector.d.ts +36 -0
  146. package/dist/utils/provider-injector.d.ts.map +1 -0
  147. package/dist/utils/provider-injector.js +223 -0
  148. package/dist/utils/provider-injector.js.map +1 -0
  149. package/dist/utils/provider-injector.test.d.ts +2 -0
  150. package/dist/utils/provider-injector.test.d.ts.map +1 -0
  151. package/dist/utils/provider-injector.test.js +67 -0
  152. package/dist/utils/provider-injector.test.js.map +1 -0
  153. package/dist/utils/scaffold.d.ts +20 -0
  154. package/dist/utils/scaffold.d.ts.map +1 -0
  155. package/dist/utils/scaffold.js +197 -0
  156. package/dist/utils/scaffold.js.map +1 -0
  157. package/package.json +35 -0
  158. package/src/commands/audit.ts +234 -0
  159. package/src/commands/backup.ts +96 -0
  160. package/src/commands/check.ts +191 -0
  161. package/src/commands/config.ts +263 -0
  162. package/src/commands/debug-patterns.test.ts +134 -0
  163. package/src/commands/debug-patterns.ts +257 -0
  164. package/src/commands/diagnose.ts +136 -0
  165. package/src/commands/init.test.ts +82 -0
  166. package/src/commands/init.ts +536 -0
  167. package/src/commands/install-hooks.ts +66 -0
  168. package/src/commands/preflight.test.ts +139 -0
  169. package/src/commands/preflight.ts +488 -0
  170. package/src/commands/rename.ts +264 -0
  171. package/src/commands/scaffold-adapter.test.ts +110 -0
  172. package/src/commands/scaffold-adapter.ts +250 -0
  173. package/src/commands/scan.ts +125 -0
  174. package/src/commands/sync-seed.test.ts +116 -0
  175. package/src/commands/sync.ts +736 -0
  176. package/src/commands/transform.ts +151 -0
  177. package/src/commands/translate/README.md +75 -0
  178. package/src/commands/translate/csv-handler.ts +301 -0
  179. package/src/commands/translate/executor.ts +188 -0
  180. package/src/commands/translate/index.ts +220 -0
  181. package/src/commands/translate/reporter.ts +138 -0
  182. package/src/commands/translate/types.ts +56 -0
  183. package/src/commands/translate.test.ts +173 -0
  184. package/src/commands/translate.ts +6 -0
  185. package/src/e2e.test.ts +479 -0
  186. package/src/fixtures/README.md +61 -0
  187. package/src/fixtures/basic-react/i18n.config.json +15 -0
  188. package/src/fixtures/basic-react/locales/de.json +8 -0
  189. package/src/fixtures/basic-react/locales/en.json +8 -0
  190. package/src/fixtures/basic-react/locales/fr.json +8 -0
  191. package/src/fixtures/basic-react/src/App.tsx +15 -0
  192. package/src/fixtures/basic-react/src/Messages.tsx +12 -0
  193. package/src/fixtures/nested-locales/i18n.config.json +9 -0
  194. package/src/fixtures/nested-locales/locales/en.json +23 -0
  195. package/src/fixtures/nested-locales/locales/fr.json +23 -0
  196. package/src/fixtures/nested-locales/src/HomePage.tsx +13 -0
  197. package/src/fixtures/suspicious-keys/i18n.config.json +9 -0
  198. package/src/fixtures/suspicious-keys/locales/en.json +11 -0
  199. package/src/fixtures/suspicious-keys/locales/fr.json +11 -0
  200. package/src/fixtures/suspicious-keys/src/BadKeys.tsx +19 -0
  201. package/src/index.ts +43 -0
  202. package/src/integration.test.ts +438 -0
  203. package/src/utils/diagnostics-exit.test.ts +47 -0
  204. package/src/utils/diagnostics-exit.ts +63 -0
  205. package/src/utils/diff-utils.test.ts +36 -0
  206. package/src/utils/diff-utils.ts +42 -0
  207. package/src/utils/exit-codes.ts +201 -0
  208. package/src/utils/package-manager.ts +44 -0
  209. package/src/utils/pkg.ts +23 -0
  210. package/src/utils/provider-injector.test.ts +79 -0
  211. package/src/utils/provider-injector.ts +315 -0
  212. package/src/utils/scaffold.ts +240 -0
  213. package/tsconfig.json +17 -0
@@ -0,0 +1,320 @@
1
+ /**
2
+ * Integration tests for CLI commands
3
+ * These tests run the actual CLI commands against real file systems
4
+ */
5
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
+ import fs from 'fs/promises';
7
+ import path from 'path';
8
+ import os from 'os';
9
+ import { spawnSync } from 'child_process';
10
+ import { fileURLToPath } from 'url';
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+ // Get the correct CLI path regardless of where tests are run from
14
+ const CLI_PATH = path.resolve(__dirname, '../dist/index.js');
15
+ // Helper to run CLI commands
16
+ function runCli(args, options = {}) {
17
+ const result = spawnSync('node', [CLI_PATH, ...args], {
18
+ cwd: options.cwd ?? process.cwd(),
19
+ encoding: 'utf8',
20
+ timeout: 30000,
21
+ env: {
22
+ ...process.env,
23
+ CI: 'true',
24
+ NO_COLOR: '1',
25
+ FORCE_COLOR: '0',
26
+ },
27
+ });
28
+ const stdout = result.stdout ?? '';
29
+ const stderr = result.stderr ?? '';
30
+ return {
31
+ stdout,
32
+ stderr,
33
+ output: stdout + stderr,
34
+ exitCode: result.status ?? 1,
35
+ };
36
+ }
37
+ // Helper to extract JSON from CLI output (may contain log messages before JSON)
38
+ function extractJson(output) {
39
+ const jsonMatch = output.match(/\{[\s\S]*\}/);
40
+ if (!jsonMatch) {
41
+ throw new Error(`No JSON found in output: ${output.slice(0, 200)}...`);
42
+ }
43
+ return JSON.parse(jsonMatch[0]);
44
+ }
45
+ describe('CLI Integration Tests', () => {
46
+ let tmpDir;
47
+ beforeEach(async () => {
48
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'i18nsmith-cli-integration-'));
49
+ });
50
+ afterEach(async () => {
51
+ await fs.rm(tmpDir, { recursive: true, force: true });
52
+ });
53
+ describe('preflight command', () => {
54
+ it('should fail when no config file exists', async () => {
55
+ const result = runCli(['preflight'], { cwd: tmpDir });
56
+ expect(result.exitCode).toBe(1);
57
+ expect(result.output).toContain('Config File');
58
+ });
59
+ it('should pass with valid config and locales', async () => {
60
+ const config = {
61
+ sourceLanguage: 'en',
62
+ targetLanguages: ['fr'],
63
+ localesDir: 'locales',
64
+ include: ['src/**/*.tsx'],
65
+ };
66
+ await fs.writeFile(path.join(tmpDir, 'i18n.config.json'), JSON.stringify(config, null, 2));
67
+ await fs.mkdir(path.join(tmpDir, 'locales'));
68
+ await fs.writeFile(path.join(tmpDir, 'locales', 'en.json'), '{}');
69
+ await fs.mkdir(path.join(tmpDir, 'src'));
70
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), 'export function App() { return <div>Hello</div>; }');
71
+ const result = runCli(['preflight'], { cwd: tmpDir });
72
+ expect(result.output).toContain('Config File');
73
+ expect(result.output).toContain('pass');
74
+ });
75
+ it('should output JSON when --json flag is used', async () => {
76
+ const config = {
77
+ sourceLanguage: 'en',
78
+ targetLanguages: ['fr'],
79
+ localesDir: 'locales',
80
+ include: ['src/**/*.tsx'],
81
+ };
82
+ await fs.writeFile(path.join(tmpDir, 'i18n.config.json'), JSON.stringify(config, null, 2));
83
+ await fs.mkdir(path.join(tmpDir, 'locales'));
84
+ await fs.writeFile(path.join(tmpDir, 'locales', 'en.json'), '{}');
85
+ await fs.mkdir(path.join(tmpDir, 'src'));
86
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), 'export function App() {}');
87
+ const result = runCli(['preflight', '--json'], { cwd: tmpDir });
88
+ const parsed = JSON.parse(result.stdout);
89
+ expect(parsed).toHaveProperty('passed');
90
+ expect(parsed).toHaveProperty('checks');
91
+ expect(Array.isArray(parsed.checks)).toBe(true);
92
+ });
93
+ it('should create missing directories with --fix', async () => {
94
+ const config = {
95
+ sourceLanguage: 'en',
96
+ targetLanguages: ['fr'],
97
+ localesDir: 'i18n/locales',
98
+ include: ['src/**/*.tsx'],
99
+ };
100
+ await fs.writeFile(path.join(tmpDir, 'i18n.config.json'), JSON.stringify(config, null, 2));
101
+ await fs.mkdir(path.join(tmpDir, 'src'));
102
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), 'export function App() {}');
103
+ runCli(['preflight', '--fix'], { cwd: tmpDir });
104
+ const localesDirExists = await fs.access(path.join(tmpDir, 'i18n', 'locales'))
105
+ .then(() => true)
106
+ .catch(() => false);
107
+ expect(localesDirExists).toBe(true);
108
+ });
109
+ });
110
+ describe('scan command', () => {
111
+ beforeEach(async () => {
112
+ const config = {
113
+ sourceLanguage: 'en',
114
+ targetLanguages: ['fr', 'de'],
115
+ localesDir: 'locales',
116
+ include: ['src/**/*.tsx'],
117
+ };
118
+ await fs.writeFile(path.join(tmpDir, 'i18n.config.json'), JSON.stringify(config, null, 2));
119
+ await fs.mkdir(path.join(tmpDir, 'locales'));
120
+ await fs.writeFile(path.join(tmpDir, 'locales', 'en.json'), '{}');
121
+ await fs.mkdir(path.join(tmpDir, 'src'), { recursive: true });
122
+ });
123
+ it('should scan and find translatable strings', async () => {
124
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `
125
+ import React from 'react';
126
+
127
+ export function App() {
128
+ return (
129
+ <div>
130
+ <h1>Welcome to our app</h1>
131
+ <p>This is a description</p>
132
+ </div>
133
+ );
134
+ }
135
+ `);
136
+ const result = runCli(['scan'], { cwd: tmpDir });
137
+ expect(result.exitCode).toBe(0);
138
+ expect(result.output).toContain('Scanned');
139
+ });
140
+ it('should output JSON when --json flag is used', async () => {
141
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `export function App() { return <div>Hello</div>; }`);
142
+ const result = runCli(['scan', '--json'], { cwd: tmpDir });
143
+ const parsed = extractJson(result.stdout);
144
+ expect(parsed).toHaveProperty('filesScanned');
145
+ expect(parsed).toHaveProperty('candidates');
146
+ });
147
+ });
148
+ describe('sync command', () => {
149
+ beforeEach(async () => {
150
+ const config = {
151
+ sourceLanguage: 'en',
152
+ targetLanguages: ['fr'],
153
+ localesDir: 'locales',
154
+ include: ['src/**/*.tsx'],
155
+ };
156
+ await fs.writeFile(path.join(tmpDir, 'i18n.config.json'), JSON.stringify(config, null, 2));
157
+ await fs.mkdir(path.join(tmpDir, 'locales'));
158
+ await fs.writeFile(path.join(tmpDir, 'locales', 'en.json'), JSON.stringify({ 'existing.key': 'Existing Value' }, null, 2));
159
+ await fs.writeFile(path.join(tmpDir, 'locales', 'fr.json'), JSON.stringify({ 'existing.key': 'Valeur existante' }, null, 2));
160
+ await fs.mkdir(path.join(tmpDir, 'src'), { recursive: true });
161
+ });
162
+ it('should run dry-run by default', async () => {
163
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `
164
+ import { useTranslation } from 'react-i18next';
165
+
166
+ export function App() {
167
+ const { t } = useTranslation();
168
+ return <div>{t('new.key')}</div>;
169
+ }
170
+ `);
171
+ const result = runCli(['sync'], { cwd: tmpDir });
172
+ expect(result.output).toContain('DRY RUN');
173
+ });
174
+ it('should add missing keys with --write', async () => {
175
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `
176
+ import { useTranslation } from 'react-i18next';
177
+
178
+ export function App() {
179
+ const { t } = useTranslation();
180
+ return <div>{t('new.key')}</div>;
181
+ }
182
+ `);
183
+ const result = runCli(['sync', '--write', '-y'], { cwd: tmpDir });
184
+ expect(result.exitCode).toBe(0);
185
+ const enContent = await fs.readFile(path.join(tmpDir, 'locales', 'en.json'), 'utf8');
186
+ const enData = JSON.parse(enContent);
187
+ expect(enData).toHaveProperty('new.key');
188
+ });
189
+ it('should not prune by default even with --write', async () => {
190
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `export function App() { return <div>Hello</div>; }`);
191
+ runCli(['sync', '--write', '-y'], { cwd: tmpDir });
192
+ const enContent = await fs.readFile(path.join(tmpDir, 'locales', 'en.json'), 'utf8');
193
+ const enData = JSON.parse(enContent);
194
+ expect(enData).toHaveProperty('existing.key');
195
+ });
196
+ it('should prune unused keys with --write --prune', async () => {
197
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `export function App() { return <div>Hello</div>; }`);
198
+ runCli(['sync', '--write', '--prune', '-y'], { cwd: tmpDir });
199
+ const enContent = await fs.readFile(path.join(tmpDir, 'locales', 'en.json'), 'utf8');
200
+ const enData = JSON.parse(enContent);
201
+ expect(enData).not.toHaveProperty('existing.key');
202
+ });
203
+ it('should create backup when pruning', async () => {
204
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `export function App() { return <div>Hello</div>; }`);
205
+ runCli(['sync', '--write', '--prune', '-y'], { cwd: tmpDir });
206
+ const backupDir = path.join(tmpDir, '.i18nsmith-backup');
207
+ const backupExists = await fs.access(backupDir).then(() => true).catch(() => false);
208
+ expect(backupExists).toBe(true);
209
+ });
210
+ it('should skip backup with --no-backup', async () => {
211
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `export function App() { return <div>Hello</div>; }`);
212
+ runCli(['sync', '--write', '--prune', '-y', '--no-backup'], { cwd: tmpDir });
213
+ const backupDir = path.join(tmpDir, '.i18nsmith-backup');
214
+ const backupExists = await fs.access(backupDir).then(() => true).catch(() => false);
215
+ expect(backupExists).toBe(false);
216
+ });
217
+ });
218
+ describe('backup commands', () => {
219
+ beforeEach(async () => {
220
+ const config = {
221
+ sourceLanguage: 'en',
222
+ targetLanguages: ['fr'],
223
+ localesDir: 'locales',
224
+ include: ['src/**/*.tsx'],
225
+ };
226
+ await fs.writeFile(path.join(tmpDir, 'i18n.config.json'), JSON.stringify(config, null, 2));
227
+ await fs.mkdir(path.join(tmpDir, 'locales'));
228
+ await fs.writeFile(path.join(tmpDir, 'locales', 'en.json'), JSON.stringify({ 'original.key': 'Original' }, null, 2));
229
+ await fs.mkdir(path.join(tmpDir, 'src'));
230
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `export function App() { return <div>Hello</div>; }`);
231
+ });
232
+ it('should list no backups when none exist', async () => {
233
+ const result = runCli(['backup-list'], { cwd: tmpDir });
234
+ expect(result.exitCode).toBe(0);
235
+ expect(result.output).toContain('No backups found');
236
+ });
237
+ it('should list backups after sync creates one', async () => {
238
+ runCli(['sync', '--write', '--prune', '-y'], { cwd: tmpDir });
239
+ const result = runCli(['backup-list'], { cwd: tmpDir });
240
+ expect(result.exitCode).toBe(0);
241
+ expect(result.output).toContain('Found');
242
+ expect(result.output).toContain('backup');
243
+ });
244
+ });
245
+ describe('transform command', () => {
246
+ beforeEach(async () => {
247
+ const config = {
248
+ sourceLanguage: 'en',
249
+ targetLanguages: ['fr'],
250
+ localesDir: 'locales',
251
+ include: ['src/**/*.tsx'],
252
+ translationAdapter: {
253
+ module: 'react-i18next',
254
+ hookName: 'useTranslation',
255
+ translationIdentifier: 't',
256
+ },
257
+ };
258
+ await fs.writeFile(path.join(tmpDir, 'i18n.config.json'), JSON.stringify(config, null, 2));
259
+ await fs.mkdir(path.join(tmpDir, 'locales'));
260
+ await fs.writeFile(path.join(tmpDir, 'locales', 'en.json'), '{}');
261
+ await fs.mkdir(path.join(tmpDir, 'src'));
262
+ });
263
+ it('should run dry-run by default', async () => {
264
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `export function App() { return <div>Hello World</div>; }`);
265
+ const result = runCli(['transform'], { cwd: tmpDir });
266
+ expect(result.output).toContain('DRY RUN');
267
+ });
268
+ it('should output JSON with --json flag', async () => {
269
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `export function App() { return <div>Hello</div>; }`);
270
+ const result = runCli(['transform', '--json'], { cwd: tmpDir });
271
+ const parsed = extractJson(result.stdout);
272
+ expect(parsed).toHaveProperty('filesScanned');
273
+ expect(parsed).toHaveProperty('candidates');
274
+ expect(Array.isArray(parsed.candidates)).toBe(true);
275
+ });
276
+ });
277
+ describe('check command', () => {
278
+ beforeEach(async () => {
279
+ const config = {
280
+ sourceLanguage: 'en',
281
+ targetLanguages: ['fr'],
282
+ localesDir: 'locales',
283
+ include: ['src/**/*.tsx'],
284
+ };
285
+ await fs.writeFile(path.join(tmpDir, 'i18n.config.json'), JSON.stringify(config, null, 2));
286
+ await fs.mkdir(path.join(tmpDir, 'locales'));
287
+ await fs.writeFile(path.join(tmpDir, 'locales', 'en.json'), JSON.stringify({ 'hello': 'Hello' }, null, 2));
288
+ await fs.writeFile(path.join(tmpDir, 'locales', 'fr.json'), JSON.stringify({ 'hello': 'Bonjour' }, null, 2));
289
+ await fs.mkdir(path.join(tmpDir, 'src'));
290
+ });
291
+ it('should run health check successfully', async () => {
292
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `
293
+ import { useTranslation } from 'react-i18next';
294
+
295
+ export function App() {
296
+ const { t } = useTranslation();
297
+ return <div>{t('hello')}</div>;
298
+ }
299
+ `);
300
+ const result = runCli(['check'], { cwd: tmpDir });
301
+ expect(result.exitCode).toBe(0);
302
+ expect(result.output).toContain('Locales directory');
303
+ });
304
+ it('should output JSON with --json flag', async () => {
305
+ await fs.writeFile(path.join(tmpDir, 'src', 'App.tsx'), `
306
+ import { useTranslation } from 'react-i18next';
307
+
308
+ export function App() {
309
+ const { t } = useTranslation();
310
+ return <div>{t('hello')}</div>;
311
+ }
312
+ `);
313
+ const result = runCli(['check', '--json'], { cwd: tmpDir });
314
+ const parsed = extractJson(result.stdout);
315
+ expect(parsed).toHaveProperty('diagnostics');
316
+ expect(parsed).toHaveProperty('sync');
317
+ });
318
+ });
319
+ });
320
+ //# sourceMappingURL=integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../src/integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { DiagnoseConflict, DiagnosisReport } from '@i18nsmith/core';
2
+ export interface DiagnosisExitSignal {
3
+ code: number;
4
+ reason: string;
5
+ }
6
+ export declare function getDiagnosisExitSignal(report: Pick<DiagnosisReport, 'conflicts'>): DiagnosisExitSignal | null;
7
+ export declare function selectExitSignal(conflicts: DiagnoseConflict[]): DiagnosisExitSignal | null;
8
+ export declare function describeDiagnosisExitCodes(): Array<{
9
+ code: number;
10
+ reason: string;
11
+ }>;
12
+ //# sourceMappingURL=diagnostics-exit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics-exit.d.ts","sourceRoot":"","sources":["../../src/utils/diagnostics-exit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGzE,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAiBD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,GAAG,mBAAmB,GAAG,IAAI,CAE7G;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,gBAAgB,EAAE,GAAG,mBAAmB,GAAG,IAAI,CA2B1F;AAED,wBAAgB,0BAA0B,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAMpF"}
@@ -0,0 +1,49 @@
1
+ import { DIAGNOSTICS_EXIT_CODES, DIAGNOSTICS_EXIT_DESCRIPTIONS } from './exit-codes.js';
2
+ const CONFLICT_EXIT_SIGNALS = {
3
+ 'missing-source-locale': {
4
+ code: DIAGNOSTICS_EXIT_CODES.MISSING_SOURCE_LOCALE,
5
+ reason: DIAGNOSTICS_EXIT_DESCRIPTIONS[DIAGNOSTICS_EXIT_CODES.MISSING_SOURCE_LOCALE],
6
+ },
7
+ 'invalid-locale-json': {
8
+ code: DIAGNOSTICS_EXIT_CODES.INVALID_LOCALE_JSON,
9
+ reason: DIAGNOSTICS_EXIT_DESCRIPTIONS[DIAGNOSTICS_EXIT_CODES.INVALID_LOCALE_JSON],
10
+ },
11
+ 'unsafe-provider-clash': {
12
+ code: DIAGNOSTICS_EXIT_CODES.UNSAFE_PROVIDER_CLASH,
13
+ reason: DIAGNOSTICS_EXIT_DESCRIPTIONS[DIAGNOSTICS_EXIT_CODES.UNSAFE_PROVIDER_CLASH],
14
+ },
15
+ };
16
+ export function getDiagnosisExitSignal(report) {
17
+ return selectExitSignal(report.conflicts);
18
+ }
19
+ export function selectExitSignal(conflicts) {
20
+ if (!conflicts.length) {
21
+ return null;
22
+ }
23
+ let chosen = null;
24
+ for (const conflict of conflicts) {
25
+ const knownSignal = CONFLICT_EXIT_SIGNALS[conflict.kind];
26
+ if (knownSignal) {
27
+ if (!chosen || knownSignal.code > chosen.code) {
28
+ chosen = knownSignal;
29
+ }
30
+ continue;
31
+ }
32
+ const fallbackSignal = {
33
+ code: DIAGNOSTICS_EXIT_CODES.GENERAL_CONFLICT,
34
+ reason: conflict.message,
35
+ };
36
+ if (!chosen || fallbackSignal.code > chosen.code) {
37
+ chosen = fallbackSignal;
38
+ }
39
+ }
40
+ return chosen;
41
+ }
42
+ export function describeDiagnosisExitCodes() {
43
+ const entries = Object.values(CONFLICT_EXIT_SIGNALS).sort((a, b) => a.code - b.code);
44
+ return entries.concat({
45
+ code: DIAGNOSTICS_EXIT_CODES.GENERAL_CONFLICT,
46
+ reason: DIAGNOSTICS_EXIT_DESCRIPTIONS[DIAGNOSTICS_EXIT_CODES.GENERAL_CONFLICT],
47
+ });
48
+ }
49
+ //# sourceMappingURL=diagnostics-exit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics-exit.js","sourceRoot":"","sources":["../../src/utils/diagnostics-exit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAC;AAOxF,MAAM,qBAAqB,GAAwC;IACjE,uBAAuB,EAAE;QACvB,IAAI,EAAE,sBAAsB,CAAC,qBAAqB;QAClD,MAAM,EAAE,6BAA6B,CAAC,sBAAsB,CAAC,qBAAqB,CAAC;KACpF;IACD,qBAAqB,EAAE;QACrB,IAAI,EAAE,sBAAsB,CAAC,mBAAmB;QAChD,MAAM,EAAE,6BAA6B,CAAC,sBAAsB,CAAC,mBAAmB,CAAC;KAClF;IACD,uBAAuB,EAAE;QACvB,IAAI,EAAE,sBAAsB,CAAC,qBAAqB;QAClD,MAAM,EAAE,6BAA6B,CAAC,sBAAsB,CAAC,qBAAqB,CAAC;KACpF;CACF,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,MAA0C;IAC/E,OAAO,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,SAA6B;IAC5D,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,GAA+B,IAAI,CAAC;IAE9C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,WAAW,GAAG,qBAAqB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,IAAI,WAAW,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC9C,MAAM,GAAG,WAAW,CAAC;YACvB,CAAC;YACD,SAAS;QACX,CAAC;QAED,MAAM,cAAc,GAAwB;YAC1C,IAAI,EAAE,sBAAsB,CAAC,gBAAgB;YAC7C,MAAM,EAAE,QAAQ,CAAC,OAAO;SACzB,CAAC;QAEF,IAAI,CAAC,MAAM,IAAI,cAAc,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YACjD,MAAM,GAAG,cAAc,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IACrF,OAAO,OAAO,CAAC,MAAM,CAAC;QACpB,IAAI,EAAE,sBAAsB,CAAC,gBAAgB;QAC7C,MAAM,EAAE,6BAA6B,CAAC,sBAAsB,CAAC,gBAAgB,CAAC;KAC/E,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=diagnostics-exit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics-exit.test.d.ts","sourceRoot":"","sources":["../../src/utils/diagnostics-exit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,40 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { selectExitSignal } from './diagnostics-exit';
3
+ import { DIAGNOSTICS_EXIT_CODES, DIAGNOSTICS_EXIT_DESCRIPTIONS } from './exit-codes';
4
+ describe('selectExitSignal', () => {
5
+ it('returns null when there are no conflicts', () => {
6
+ expect(selectExitSignal([])).toBeNull();
7
+ });
8
+ it('returns the mapped exit code for missing source locale conflicts', () => {
9
+ const conflicts = [
10
+ { kind: 'missing-source-locale', message: 'Source locale missing' },
11
+ ];
12
+ const result = selectExitSignal(conflicts);
13
+ expect(result).toEqual({
14
+ code: DIAGNOSTICS_EXIT_CODES.MISSING_SOURCE_LOCALE,
15
+ reason: DIAGNOSTICS_EXIT_DESCRIPTIONS[DIAGNOSTICS_EXIT_CODES.MISSING_SOURCE_LOCALE],
16
+ });
17
+ });
18
+ it('prefers higher severity codes when multiple conflicts exist', () => {
19
+ const conflicts = [
20
+ { kind: 'missing-source-locale', message: 'Source missing' },
21
+ { kind: 'invalid-locale-json', message: 'Invalid JSON detected' },
22
+ ];
23
+ const result = selectExitSignal(conflicts);
24
+ expect(result).toEqual({
25
+ code: DIAGNOSTICS_EXIT_CODES.INVALID_LOCALE_JSON,
26
+ reason: DIAGNOSTICS_EXIT_DESCRIPTIONS[DIAGNOSTICS_EXIT_CODES.INVALID_LOCALE_JSON],
27
+ });
28
+ });
29
+ it('falls back to a general conflict exit code for unknown kinds', () => {
30
+ const conflicts = [
31
+ { kind: 'custom-conflict', message: 'Something unexpected happened' },
32
+ ];
33
+ const result = selectExitSignal(conflicts);
34
+ expect(result).toEqual({
35
+ code: DIAGNOSTICS_EXIT_CODES.GENERAL_CONFLICT,
36
+ reason: 'Something unexpected happened',
37
+ });
38
+ });
39
+ });
40
+ //# sourceMappingURL=diagnostics-exit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics-exit.test.js","sourceRoot":"","sources":["../../src/utils/diagnostics-exit.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAErF,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,SAAS,GAAuB;YACpC,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,uBAAuB,EAAE;SACpE,CAAC;QAEF,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,sBAAsB,CAAC,qBAAqB;YAClD,MAAM,EAAE,6BAA6B,CAAC,sBAAsB,CAAC,qBAAqB,CAAC;SACpF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,SAAS,GAAuB;YACpC,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,gBAAgB,EAAE;YAC5D,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,uBAAuB,EAAE;SAClE,CAAC;QAEF,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,sBAAsB,CAAC,mBAAmB;YAChD,MAAM,EAAE,6BAA6B,CAAC,sBAAsB,CAAC,mBAAmB,CAAC;SAClF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,SAAS,GAAuB;YACpC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,+BAA+B,EAAE;SACtE,CAAC;QAEF,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,sBAAsB,CAAC,gBAAgB;YAC7C,MAAM,EAAE,+BAA+B;SACxC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { SyncSummary } from '@i18nsmith/core';
2
+ export declare function printLocaleDiffs(diffs: SyncSummary['diffs']): void;
3
+ export declare function writeLocaleDiffPatches(diffs: SyncSummary['diffs'], directory: string): Promise<void>;
4
+ //# sourceMappingURL=diff-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-utils.d.ts","sourceRoot":"","sources":["../../src/utils/diff-utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,QAW3D;AAED,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,iBAuB1F"}
@@ -0,0 +1,30 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import chalk from 'chalk';
4
+ export function printLocaleDiffs(diffs) {
5
+ if (!diffs.length) {
6
+ console.log(chalk.gray('No locale diffs to display.'));
7
+ return;
8
+ }
9
+ console.log(chalk.blue('\nUnified locale diffs:'));
10
+ diffs.forEach((entry) => {
11
+ console.log(chalk.yellow(`\n--- ${entry.locale} (${entry.path})`));
12
+ console.log(entry.diff.trimEnd());
13
+ });
14
+ }
15
+ export async function writeLocaleDiffPatches(diffs, directory) {
16
+ if (!diffs.length) {
17
+ console.log(chalk.gray('No locale diffs to write.'));
18
+ return;
19
+ }
20
+ const targetDir = path.isAbsolute(directory) ? directory : path.resolve(process.cwd(), directory);
21
+ await fs.mkdir(targetDir, { recursive: true });
22
+ await Promise.all(diffs.map((entry) => {
23
+ const safeLocale = entry.locale.replace(/[^a-z0-9_-]/gi, '-');
24
+ const fileName = `${safeLocale || 'locale'}.patch`;
25
+ const filePath = path.join(targetDir, fileName);
26
+ return fs.writeFile(filePath, `${entry.diff.trimEnd()}\n`, 'utf8');
27
+ }));
28
+ console.log(chalk.green(`Wrote ${diffs.length} locale patch file${diffs.length === 1 ? '' : 's'} to ${targetDir}.`));
29
+ }
30
+ //# sourceMappingURL=diff-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-utils.js","sourceRoot":"","sources":["../../src/utils/diff-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,UAAU,gBAAgB,CAAC,KAA2B;IAC1D,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;QACvD,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC;IACnD,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,KAA2B,EAAE,SAAiB;IACzF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IAClG,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE/C,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAClB,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,GAAG,UAAU,IAAI,QAAQ,QAAQ,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAChD,OAAO,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACrE,CAAC,CAAC,CACH,CAAC;IAEF,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CACT,SAAS,KAAK,CAAC,MAAM,qBAAqB,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,SAAS,GAAG,CAC3F,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=diff-utils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-utils.test.d.ts","sourceRoot":"","sources":["../../src/utils/diff-utils.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import fs from 'fs/promises';
3
+ import os from 'os';
4
+ import path from 'path';
5
+ import { writeLocaleDiffPatches, printLocaleDiffs } from './diff-utils';
6
+ describe('diff-utils', () => {
7
+ it('writes patch files for provided diffs', async () => {
8
+ const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'i18nsmith-test-'));
9
+ const diffs = [
10
+ { locale: 'en', path: '/locales/en.json', diff: '--- a\n+++ b\n+"hello": "Hello"', added: ['hello'], updated: [], removed: [] },
11
+ { locale: 'fr', path: '/locales/fr.json', diff: '--- a\n+++ b\n+"hello": "Bonjour"', added: ['hello'], updated: [], removed: [] },
12
+ ];
13
+ await writeLocaleDiffPatches(diffs, tmp);
14
+ const files = await fs.readdir(tmp);
15
+ expect(files.length).toBe(2);
16
+ const enContent = await fs.readFile(path.join(tmp, 'en.patch'), 'utf8');
17
+ expect(enContent).toContain('Hello');
18
+ // cleanup
19
+ await fs.rm(tmp, { recursive: true, force: true });
20
+ });
21
+ it('prints diffs without throwing', () => {
22
+ const diffs = [
23
+ { locale: 'en', path: '/locales/en.json', diff: '--- a\n+++ b\n+"hello": "Hello"', added: [], updated: [], removed: [] },
24
+ ];
25
+ const spy = vi.spyOn(console, 'log').mockImplementation(() => { });
26
+ expect(() => printLocaleDiffs(diffs)).not.toThrow();
27
+ spy.mockRestore();
28
+ });
29
+ });
30
+ //# sourceMappingURL=diff-utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-utils.test.js","sourceRoot":"","sources":["../../src/utils/diff-utils.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAExE,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACxE,MAAM,KAAK,GAAG;YACZ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,iCAAiC,EAAE,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;YAC/H,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,mCAAmC,EAAE,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;SAClI,CAAC;QAEF,MAAM,sBAAsB,CAAC,KAAY,EAAE,GAAG,CAAC,CAAC;QAEhD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAE7B,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;QACxE,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAErC,UAAU;QACV,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,KAAK,GAAG;YACZ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,iCAAiC,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;SACzH,CAAC;QAEF,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAY,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC3D,GAAG,CAAC,WAAW,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}