@babelize/engine 0.0.0-stage → 0.1.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 (270) hide show
  1. package/LICENSE +202 -0
  2. package/dist/BabelizeEngine.d.ts +12 -0
  3. package/dist/BabelizeEngine.js +47 -0
  4. package/dist/analysis/analyze.d.ts +106 -0
  5. package/dist/analysis/analyze.js +323 -0
  6. package/dist/config/env.d.ts +9 -0
  7. package/dist/config/env.js +16 -0
  8. package/dist/config.d.ts +74 -0
  9. package/dist/config.js +47 -0
  10. package/dist/detection/stack.d.ts +42 -0
  11. package/dist/detection/stack.js +277 -0
  12. package/dist/django/catalog.d.ts +92 -0
  13. package/dist/django/catalog.js +677 -0
  14. package/dist/django/extract.d.ts +20 -0
  15. package/dist/django/extract.js +79 -0
  16. package/dist/django/inject-file.d.ts +6 -0
  17. package/dist/django/inject-file.js +52 -0
  18. package/dist/django/inject.d.ts +11 -0
  19. package/dist/django/inject.js +205 -0
  20. package/dist/django/keys.d.ts +21 -0
  21. package/dist/django/keys.js +63 -0
  22. package/dist/django/locale-names.d.ts +13 -0
  23. package/dist/django/locale-names.js +60 -0
  24. package/dist/django/mo-file.d.ts +6 -0
  25. package/dist/django/mo-file.js +60 -0
  26. package/dist/django/plural-forms.d.ts +34 -0
  27. package/dist/django/plural-forms.js +216 -0
  28. package/dist/django/po-file.d.ts +38 -0
  29. package/dist/django/po-file.js +273 -0
  30. package/dist/django/python-extract.d.ts +34 -0
  31. package/dist/django/python-extract.js +619 -0
  32. package/dist/django/python-lexer.d.ts +65 -0
  33. package/dist/django/python-lexer.js +398 -0
  34. package/dist/django/template-extract.d.ts +32 -0
  35. package/dist/django/template-extract.js +680 -0
  36. package/dist/django/types.d.ts +49 -0
  37. package/dist/django/types.js +15 -0
  38. package/dist/index.d.ts +59 -0
  39. package/dist/index.js +140 -0
  40. package/dist/injection/InjectionStrategy.d.ts +62 -0
  41. package/dist/injection/InjectionStrategy.js +2 -0
  42. package/dist/injection/StrategyFactory.d.ts +4 -0
  43. package/dist/injection/StrategyFactory.js +29 -0
  44. package/dist/injection/html/html-injector.d.ts +11 -0
  45. package/dist/injection/html/html-injector.js +173 -0
  46. package/dist/injection/strategies/NextIntlStrategy.d.ts +25 -0
  47. package/dist/injection/strategies/NextIntlStrategy.js +141 -0
  48. package/dist/injection/strategies/ReactI18nextStrategy.d.ts +19 -0
  49. package/dist/injection/strategies/ReactI18nextStrategy.js +116 -0
  50. package/dist/injection/strategies/VanillaStrategy.d.ts +11 -0
  51. package/dist/injection/strategies/VanillaStrategy.js +73 -0
  52. package/dist/injection/strategies/VueI18nStrategy.d.ts +11 -0
  53. package/dist/injection/strategies/VueI18nStrategy.js +84 -0
  54. package/dist/local/formatter.d.ts +26 -0
  55. package/dist/local/formatter.js +105 -0
  56. package/dist/local/git.d.ts +23 -0
  57. package/dist/local/git.js +136 -0
  58. package/dist/local/hosted-provider.d.ts +68 -0
  59. package/dist/local/hosted-provider.js +215 -0
  60. package/dist/local/index.d.ts +23 -0
  61. package/dist/local/index.js +75 -0
  62. package/dist/local/provider.d.ts +56 -0
  63. package/dist/local/provider.js +119 -0
  64. package/dist/local/pseudo-provider.d.ts +18 -0
  65. package/dist/local/pseudo-provider.js +208 -0
  66. package/dist/local/report.d.ts +177 -0
  67. package/dist/local/report.js +186 -0
  68. package/dist/local/translate-core.d.ts +218 -0
  69. package/dist/local/translate-core.js +499 -0
  70. package/dist/local/translate-messages.d.ts +49 -0
  71. package/dist/local/translate-messages.js +89 -0
  72. package/dist/local/workspace-copy.d.ts +91 -0
  73. package/dist/local/workspace-copy.js +355 -0
  74. package/dist/modules/extractor/extract.d.ts +20 -0
  75. package/dist/modules/extractor/extract.js +709 -0
  76. package/dist/modules/extractor/index.d.ts +2 -0
  77. package/dist/modules/extractor/index.js +63 -0
  78. package/dist/modules/finalization/django-finalize.d.ts +28 -0
  79. package/dist/modules/finalization/django-finalize.js +412 -0
  80. package/dist/modules/finalization/finalize.d.ts +38 -0
  81. package/dist/modules/finalization/finalize.js +745 -0
  82. package/dist/modules/finalization/index.d.ts +1 -0
  83. package/dist/modules/finalization/index.js +5 -0
  84. package/dist/modules/finalization/nextjs-finalize.d.ts +40 -0
  85. package/dist/modules/finalization/nextjs-finalize.js +328 -0
  86. package/dist/modules/finalization/static-runtime.d.ts +9 -0
  87. package/dist/modules/finalization/static-runtime.js +261 -0
  88. package/dist/modules/finalization/writes.d.ts +29 -0
  89. package/dist/modules/finalization/writes.js +78 -0
  90. package/dist/modules/format-injection/index.d.ts +19 -0
  91. package/dist/modules/format-injection/index.js +273 -0
  92. package/dist/modules/format-injection/inject-formats.d.ts +31 -0
  93. package/dist/modules/format-injection/inject-formats.js +208 -0
  94. package/dist/modules/glossary/index.d.ts +2 -0
  95. package/dist/modules/glossary/index.js +16 -0
  96. package/dist/modules/glossary/rules.d.ts +81 -0
  97. package/dist/modules/glossary/rules.js +244 -0
  98. package/dist/modules/glossary/types.d.ts +22 -0
  99. package/dist/modules/glossary/types.js +2 -0
  100. package/dist/modules/injection/index.d.ts +1 -0
  101. package/dist/modules/injection/index.js +6 -0
  102. package/dist/modules/injection/inject.d.ts +29 -0
  103. package/dist/modules/injection/inject.js +1050 -0
  104. package/dist/modules/keygen/index.d.ts +1 -0
  105. package/dist/modules/keygen/index.js +11 -0
  106. package/dist/modules/keygen/keygen.d.ts +4 -0
  107. package/dist/modules/keygen/keygen.js +123 -0
  108. package/dist/modules/keygen/locale-data.d.ts +7 -0
  109. package/dist/modules/keygen/locale-data.js +73 -0
  110. package/dist/modules/keygen/public.d.ts +2 -0
  111. package/dist/modules/keygen/public.js +12 -0
  112. package/dist/modules/locale-builder/index.d.ts +1 -0
  113. package/dist/modules/locale-builder/index.js +7 -0
  114. package/dist/modules/locale-builder/locales.d.ts +13 -0
  115. package/dist/modules/locale-builder/locales.js +130 -0
  116. package/dist/modules/lockfile/hasher.d.ts +7 -0
  117. package/dist/modules/lockfile/hasher.js +13 -0
  118. package/dist/modules/lockfile/index.d.ts +3 -0
  119. package/dist/modules/lockfile/index.js +22 -0
  120. package/dist/modules/lockfile/lockfile-manager.d.ts +99 -0
  121. package/dist/modules/lockfile/lockfile-manager.js +497 -0
  122. package/dist/modules/lockfile/schema.d.ts +196 -0
  123. package/dist/modules/lockfile/schema.js +56 -0
  124. package/dist/modules/parser/index.d.ts +2 -0
  125. package/dist/modules/parser/index.js +9 -0
  126. package/dist/modules/summary/index.d.ts +1 -0
  127. package/dist/modules/summary/index.js +7 -0
  128. package/dist/modules/summary/summary.d.ts +9 -0
  129. package/dist/modules/summary/summary.js +195 -0
  130. package/dist/modules/sync-detector/index.d.ts +2 -0
  131. package/dist/modules/sync-detector/index.js +7 -0
  132. package/dist/modules/sync-detector/reporter.d.ts +3 -0
  133. package/dist/modules/sync-detector/reporter.js +16 -0
  134. package/dist/modules/sync-detector/sync-detector.d.ts +39 -0
  135. package/dist/modules/sync-detector/sync-detector.js +374 -0
  136. package/dist/modules/translator/batch-optimizer.d.ts +12 -0
  137. package/dist/modules/translator/batch-optimizer.js +30 -0
  138. package/dist/modules/translator/client/byok.provider.d.ts +64 -0
  139. package/dist/modules/translator/client/byok.provider.js +319 -0
  140. package/dist/modules/translator/client/direct-translator.client.d.ts +12 -0
  141. package/dist/modules/translator/client/direct-translator.client.js +71 -0
  142. package/dist/modules/translator/client/gemini.provider.d.ts +1 -0
  143. package/dist/modules/translator/client/gemini.provider.js +110 -0
  144. package/dist/modules/translator/client/groq.provider.d.ts +1 -0
  145. package/dist/modules/translator/client/groq.provider.js +111 -0
  146. package/dist/modules/translator/client/request.types.d.ts +1 -0
  147. package/dist/modules/translator/client/request.types.js +2 -0
  148. package/dist/modules/translator/client/retry.d.ts +29 -0
  149. package/dist/modules/translator/client/retry.js +94 -0
  150. package/dist/modules/translator/client/test-utils/mock.client.d.ts +31 -0
  151. package/dist/modules/translator/client/test-utils/mock.client.js +59 -0
  152. package/dist/modules/translator/client/translator.interface.d.ts +1 -0
  153. package/dist/modules/translator/client/translator.interface.js +2 -0
  154. package/dist/modules/translator/icu-branches.d.ts +138 -0
  155. package/dist/modules/translator/icu-branches.js +393 -0
  156. package/dist/modules/translator/language-codes/errors.d.ts +10 -0
  157. package/dist/modules/translator/language-codes/errors.js +18 -0
  158. package/dist/modules/translator/language-codes/flores-map.d.ts +1 -0
  159. package/dist/modules/translator/language-codes/flores-map.js +107 -0
  160. package/dist/modules/translator/language-codes/index.d.ts +11 -0
  161. package/dist/modules/translator/language-codes/index.js +24 -0
  162. package/dist/modules/translator/language-codes/language-mapper.d.ts +25 -0
  163. package/dist/modules/translator/language-codes/language-mapper.js +132 -0
  164. package/dist/modules/translator/language-codes/rtl-languages.d.ts +2 -0
  165. package/dist/modules/translator/language-codes/rtl-languages.js +9 -0
  166. package/dist/modules/translator/memory/memory-matcher.d.ts +8 -0
  167. package/dist/modules/translator/memory/memory-matcher.js +218 -0
  168. package/dist/modules/translator/memory/types.d.ts +22 -0
  169. package/dist/modules/translator/memory/types.js +2 -0
  170. package/dist/modules/translator/translate.d.ts +74 -0
  171. package/dist/modules/translator/translate.js +1047 -0
  172. package/dist/modules/vue/migrate.d.ts +13 -0
  173. package/dist/modules/vue/migrate.js +40 -0
  174. package/dist/modules/vue/script-inject.d.ts +16 -0
  175. package/dist/modules/vue/script-inject.js +115 -0
  176. package/dist/modules/vue/sfc.d.ts +11 -0
  177. package/dist/modules/vue/sfc.js +51 -0
  178. package/dist/modules/vue/template-rewrite.d.ts +25 -0
  179. package/dist/modules/vue/template-rewrite.js +76 -0
  180. package/dist/modules/vue/template-scan.d.ts +29 -0
  181. package/dist/modules/vue/template-scan.js +264 -0
  182. package/dist/modules/workspace/index.d.ts +1 -0
  183. package/dist/modules/workspace/index.js +5 -0
  184. package/dist/modules/workspace/validate.d.ts +13 -0
  185. package/dist/modules/workspace/validate.js +333 -0
  186. package/dist/orchestrator.d.ts +13 -0
  187. package/dist/orchestrator.js +727 -0
  188. package/dist/providers/default-translation-provider.d.ts +20 -0
  189. package/dist/providers/default-translation-provider.js +30 -0
  190. package/dist/providers/index.d.ts +2 -0
  191. package/dist/providers/index.js +21 -0
  192. package/dist/providers/types.d.ts +153 -0
  193. package/dist/providers/types.js +2 -0
  194. package/dist/qa/check-project.d.ts +50 -0
  195. package/dist/qa/check-project.js +193 -0
  196. package/dist/qa/gettext-files.d.ts +15 -0
  197. package/dist/qa/gettext-files.js +115 -0
  198. package/dist/qa/locale-files.d.ts +44 -0
  199. package/dist/qa/locale-files.js +159 -0
  200. package/dist/qa/locale-qa.d.ts +61 -0
  201. package/dist/qa/locale-qa.js +342 -0
  202. package/dist/qa/review.d.ts +43 -0
  203. package/dist/qa/review.js +175 -0
  204. package/dist/runtime/config.d.ts +8 -0
  205. package/dist/runtime/config.js +37 -0
  206. package/dist/runtime/index.d.ts +3 -0
  207. package/dist/runtime/index.js +8 -0
  208. package/dist/runtime/types.d.ts +427 -0
  209. package/dist/runtime/types.js +38 -0
  210. package/dist/types.d.ts +134 -0
  211. package/dist/types.js +12 -0
  212. package/dist/utils/ast-helpers.d.ts +57 -0
  213. package/dist/utils/ast-helpers.js +608 -0
  214. package/dist/utils/cache-keys.d.ts +8 -0
  215. package/dist/utils/cache-keys.js +18 -0
  216. package/dist/utils/circuit-breaker.d.ts +43 -0
  217. package/dist/utils/circuit-breaker.js +119 -0
  218. package/dist/utils/concurrent-map.d.ts +4 -0
  219. package/dist/utils/concurrent-map.js +21 -0
  220. package/dist/utils/detect-format.d.ts +5 -0
  221. package/dist/utils/detect-format.js +125 -0
  222. package/dist/utils/extraction-options.d.ts +29 -0
  223. package/dist/utils/extraction-options.js +33 -0
  224. package/dist/utils/file-utils.d.ts +33 -0
  225. package/dist/utils/file-utils.js +267 -0
  226. package/dist/utils/glossary-match.d.ts +9 -0
  227. package/dist/utils/glossary-match.js +25 -0
  228. package/dist/utils/html-extractor.d.ts +8 -0
  229. package/dist/utils/html-extractor.js +317 -0
  230. package/dist/utils/i18next-icu.d.ts +38 -0
  231. package/dist/utils/i18next-icu.js +159 -0
  232. package/dist/utils/icu-message.d.ts +65 -0
  233. package/dist/utils/icu-message.js +346 -0
  234. package/dist/utils/icu-spans.d.ts +10 -0
  235. package/dist/utils/icu-spans.js +126 -0
  236. package/dist/utils/jsx-message.d.ts +93 -0
  237. package/dist/utils/jsx-message.js +628 -0
  238. package/dist/utils/key-usage.d.ts +35 -0
  239. package/dist/utils/key-usage.js +247 -0
  240. package/dist/utils/logger.d.ts +24 -0
  241. package/dist/utils/logger.js +33 -0
  242. package/dist/utils/metadata.d.ts +82 -0
  243. package/dist/utils/metadata.js +261 -0
  244. package/dist/utils/module-constants.d.ts +30 -0
  245. package/dist/utils/module-constants.js +265 -0
  246. package/dist/utils/not-injected.d.ts +6 -0
  247. package/dist/utils/not-injected.js +38 -0
  248. package/dist/utils/placeholder-protection.d.ts +74 -0
  249. package/dist/utils/placeholder-protection.js +181 -0
  250. package/dist/utils/pseudo-markers.d.ts +9 -0
  251. package/dist/utils/pseudo-markers.js +16 -0
  252. package/dist/utils/string-utils.d.ts +52 -0
  253. package/dist/utils/string-utils.js +270 -0
  254. package/dist/utils/translation-quality.d.ts +34 -0
  255. package/dist/utils/translation-quality.js +156 -0
  256. package/dist/utils/translation-sanitizer.d.ts +11 -0
  257. package/dist/utils/translation-sanitizer.js +71 -0
  258. package/dist/utils/translator-caller.d.ts +32 -0
  259. package/dist/utils/translator-caller.js +217 -0
  260. package/dist/utils/translator-load-balancer.d.ts +73 -0
  261. package/dist/utils/translator-load-balancer.js +297 -0
  262. package/dist/utils/ui-copy.d.ts +32 -0
  263. package/dist/utils/ui-copy.js +126 -0
  264. package/dist/utils/untranslated.d.ts +15 -0
  265. package/dist/utils/untranslated.js +34 -0
  266. package/dist/utils/workspace.d.ts +14 -0
  267. package/dist/utils/workspace.js +89 -0
  268. package/package.json +64 -4
  269. package/schemas/translate-report.schema.json +297 -0
  270. package/README.md +0 -3
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Directories never copied into the temp workspace and never diffed back.
3
+ * Dependencies and VCS/tool caches are skipped at any depth.
4
+ */
5
+ export declare const EXCLUDED_DIRS_ANY_DEPTH: ReadonlySet<string>;
6
+ /**
7
+ * Build output, skipped only at the project root: the same names deeper down
8
+ * are often real source (a Next.js route like `app/build/page.tsx`).
9
+ */
10
+ export declare const EXCLUDED_DIRS_AT_ROOT: ReadonlySet<string>;
11
+ /** Always copied, even when gitignored: it holds the lockfile that makes reruns incremental. */
12
+ export declare const BABELIZE_DIR = ".babelize";
13
+ export declare function isExcluded(rel: string): boolean;
14
+ /** Regular files under `root/dir`, relative to `root`. Symlinks are never followed. */
15
+ export declare function walk(root: string, dir?: string, out?: string[]): Promise<string[]>;
16
+ /**
17
+ * Tracked + untracked-but-not-ignored files under `dir`, relative to it, or
18
+ * null when `dir` is not in a git work tree (or git is missing).
19
+ */
20
+ export declare function listGitFiles(dir: string): Promise<string[] | null>;
21
+ export interface TempWorkspace {
22
+ dir: string;
23
+ cleanup(): Promise<void>;
24
+ }
25
+ /**
26
+ * Copy the project into a fresh private temp dir. `files` (paths relative to
27
+ * `projectDir`, e.g. from `git ls-files`) limits the copy; without it the
28
+ * whole tree is walked. `.babelize/` is always included (it is often
29
+ * gitignored, but the lockfile in it is what keeps reruns incremental).
30
+ */
31
+ export declare function createTempCopy(projectDir: string, opts?: {
32
+ files?: string[];
33
+ tmpRoot?: string;
34
+ }): Promise<TempWorkspace>;
35
+ /** Relative path → sha256 for every regular file under `root` (excluded dirs skipped). */
36
+ export declare function snapshot(root: string): Promise<Map<string, string>>;
37
+ export interface WorkspaceChanges {
38
+ added: string[];
39
+ modified: string[];
40
+ deleted: string[];
41
+ }
42
+ export declare function diffSnapshots(before: Map<string, string>, after: Map<string, string>): WorkspaceChanges;
43
+ export declare function changeCount(changes: WorkspaceChanges): number;
44
+ /**
45
+ * Project files that no longer match what the run started from: a file the
46
+ * run would overwrite or delete was edited (or removed) meanwhile, or a file
47
+ * it would create now exists (created during the run, or never copied
48
+ * because it is gitignored). Applying over those would lose the user's work.
49
+ */
50
+ export declare function findConflicts(changes: WorkspaceChanges, baseline: Map<string, string>, projectDir: string): Promise<string[]>;
51
+ /** File operations used by applyChanges; injectable so tests can simulate a failing disk. */
52
+ export interface ApplyIo {
53
+ copyFile(src: string, dest: string): Promise<void>;
54
+ rename(from: string, to: string): Promise<void>;
55
+ unlink(file: string): Promise<void>;
56
+ /** Used to restore originals on rollback. */
57
+ writeFile(file: string, data: Buffer): Promise<void>;
58
+ /** Used to remove new files on rollback. */
59
+ remove(file: string): Promise<void>;
60
+ }
61
+ /**
62
+ * applyChanges failed. When `rolledBack` is true the project is exactly as it
63
+ * was before; otherwise `changedFiles` lists what is still different.
64
+ */
65
+ export declare class ApplyError extends Error {
66
+ readonly cause: unknown;
67
+ readonly rolledBack: boolean;
68
+ readonly changedFiles: string[];
69
+ constructor(message: string, cause: unknown, rolledBack: boolean, changedFiles: string[]);
70
+ }
71
+ /**
72
+ * Apply the engine's changes from the temp copy to the project, as one
73
+ * transaction: originals of every file about to be overwritten or deleted are
74
+ * read into memory first, each write goes through temp file + rename, and on
75
+ * any failure every file already touched is restored (new files removed).
76
+ */
77
+ export declare function applyChanges(changes: WorkspaceChanges, fromDir: string, toDir: string, io?: ApplyIo): Promise<void>;
78
+ /** Unified diff (git-style a/ b/ headers) of what applyChanges would do. */
79
+ export declare function renderUnifiedDiff(changes: WorkspaceChanges, beforeDir: string, afterDir: string): Promise<string>;
80
+ export interface FileDiffStat {
81
+ file: string;
82
+ kind: 'added' | 'modified' | 'deleted';
83
+ /** Lines added / removed (numstat semantics). */
84
+ added: number;
85
+ removed: number;
86
+ }
87
+ /**
88
+ * Lines added/removed per changed file, from the files' old and new content
89
+ * (never from a rendered diff). Unreadable files count as empty.
90
+ */
91
+ export declare function diffStats(changes: WorkspaceChanges, beforeDir: string, afterDir: string): Promise<FileDiffStat[]>;
@@ -0,0 +1,355 @@
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 () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ApplyError = exports.BABELIZE_DIR = exports.EXCLUDED_DIRS_AT_ROOT = exports.EXCLUDED_DIRS_ANY_DEPTH = void 0;
37
+ exports.isExcluded = isExcluded;
38
+ exports.walk = walk;
39
+ exports.listGitFiles = listGitFiles;
40
+ exports.createTempCopy = createTempCopy;
41
+ exports.snapshot = snapshot;
42
+ exports.diffSnapshots = diffSnapshots;
43
+ exports.changeCount = changeCount;
44
+ exports.findConflicts = findConflicts;
45
+ exports.applyChanges = applyChanges;
46
+ exports.renderUnifiedDiff = renderUnifiedDiff;
47
+ exports.diffStats = diffStats;
48
+ const node_child_process_1 = require("node:child_process");
49
+ const node_crypto_1 = require("node:crypto");
50
+ const diff_1 = require("diff");
51
+ const fsp = __importStar(require("node:fs/promises"));
52
+ const node_os_1 = require("node:os");
53
+ const path = __importStar(require("node:path"));
54
+ const node_util_1 = require("node:util");
55
+ const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
56
+ /**
57
+ * Directories never copied into the temp workspace and never diffed back.
58
+ * Dependencies and VCS/tool caches are skipped at any depth.
59
+ */
60
+ exports.EXCLUDED_DIRS_ANY_DEPTH = new Set(['node_modules', '.git', '.next', '.turbo']);
61
+ /**
62
+ * Build output, skipped only at the project root: the same names deeper down
63
+ * are often real source (a Next.js route like `app/build/page.tsx`).
64
+ */
65
+ exports.EXCLUDED_DIRS_AT_ROOT = new Set(['dist', 'build', 'coverage']);
66
+ /** Always copied, even when gitignored: it holds the lockfile that makes reruns incremental. */
67
+ exports.BABELIZE_DIR = '.babelize';
68
+ /** Engine scratch files that must never be applied back (lockfile write lock / temp). */
69
+ function isEngineScratch(rel) {
70
+ if (!rel.startsWith(`${exports.BABELIZE_DIR}/`))
71
+ return false;
72
+ return /babelize-lock\.json\.(lock|tmp)(\/|$)/.test(rel);
73
+ }
74
+ function toPosix(rel) {
75
+ return rel.split(path.sep).join('/');
76
+ }
77
+ function isExcluded(rel) {
78
+ const parts = rel.split('/');
79
+ if (parts.length > 1 && exports.EXCLUDED_DIRS_AT_ROOT.has(parts[0]))
80
+ return true;
81
+ return parts.slice(0, -1).some((part) => exports.EXCLUDED_DIRS_ANY_DEPTH.has(part));
82
+ }
83
+ /** Resolve `rel` under `root`, refusing anything that escapes it. */
84
+ function safeJoin(root, rel) {
85
+ const abs = path.resolve(root, rel);
86
+ const relBack = path.relative(root, abs);
87
+ if (relBack.startsWith('..') || path.isAbsolute(relBack)) {
88
+ throw new Error(`Refusing to touch a path outside the project: ${rel}`);
89
+ }
90
+ return abs;
91
+ }
92
+ /** Regular files under `root/dir`, relative to `root`. Symlinks are never followed. */
93
+ async function walk(root, dir = '', out = []) {
94
+ const entries = await fsp.readdir(path.join(root, dir), { withFileTypes: true }).catch((err) => {
95
+ if (err.code === 'ENOENT')
96
+ return [];
97
+ throw err;
98
+ });
99
+ for (const entry of entries) {
100
+ const rel = dir ? `${dir}/${entry.name}` : entry.name;
101
+ if (entry.isDirectory()) {
102
+ if (exports.EXCLUDED_DIRS_ANY_DEPTH.has(entry.name))
103
+ continue;
104
+ if (!dir && exports.EXCLUDED_DIRS_AT_ROOT.has(entry.name))
105
+ continue;
106
+ await walk(root, rel, out);
107
+ }
108
+ else if (entry.isFile()) {
109
+ out.push(rel);
110
+ }
111
+ }
112
+ return out;
113
+ }
114
+ /**
115
+ * Tracked + untracked-but-not-ignored files under `dir`, relative to it, or
116
+ * null when `dir` is not in a git work tree (or git is missing).
117
+ */
118
+ async function listGitFiles(dir) {
119
+ try {
120
+ const { stdout } = await execFileAsync('git', ['ls-files', '-z', '--cached', '--others', '--exclude-standard', '--', '.'], {
121
+ cwd: dir,
122
+ maxBuffer: 256 * 1024 * 1024,
123
+ });
124
+ return stdout.split('\0').filter(Boolean);
125
+ }
126
+ catch {
127
+ return null;
128
+ }
129
+ }
130
+ /**
131
+ * Copy the project into a fresh private temp dir. `files` (paths relative to
132
+ * `projectDir`, e.g. from `git ls-files`) limits the copy; without it the
133
+ * whole tree is walked. `.babelize/` is always included (it is often
134
+ * gitignored, but the lockfile in it is what keeps reruns incremental).
135
+ */
136
+ async function createTempCopy(projectDir, opts = {}) {
137
+ const dir = await fsp.mkdtemp(path.join(opts.tmpRoot ?? (0, node_os_1.tmpdir)(), 'babelize-translate-'));
138
+ const cleanup = () => fsp.rm(dir, { recursive: true, force: true });
139
+ try {
140
+ const listed = opts.files ? opts.files.map(toPosix) : await walk(projectDir);
141
+ const files = new Set([...listed, ...(await walk(projectDir, exports.BABELIZE_DIR))]);
142
+ for (const rel of files) {
143
+ if (isExcluded(rel) || isEngineScratch(rel))
144
+ continue;
145
+ const src = safeJoin(projectDir, rel);
146
+ const st = await fsp.lstat(src).catch(() => null);
147
+ if (!st || !st.isFile())
148
+ continue; // deleted-but-tracked, symlink, or dir
149
+ const dest = safeJoin(dir, rel);
150
+ await fsp.mkdir(path.dirname(dest), { recursive: true });
151
+ await fsp.copyFile(src, dest);
152
+ }
153
+ }
154
+ catch (err) {
155
+ await cleanup();
156
+ throw err;
157
+ }
158
+ return { dir, cleanup };
159
+ }
160
+ /** Relative path → sha256 for every regular file under `root` (excluded dirs skipped). */
161
+ async function snapshot(root) {
162
+ const result = new Map();
163
+ for (const rel of await walk(root)) {
164
+ const content = await fsp.readFile(path.join(root, rel));
165
+ result.set(rel, (0, node_crypto_1.createHash)('sha256').update(content).digest('hex'));
166
+ }
167
+ return result;
168
+ }
169
+ function diffSnapshots(before, after) {
170
+ const added = [];
171
+ const modified = [];
172
+ const deleted = [];
173
+ for (const [rel, hash] of after) {
174
+ if (isEngineScratch(rel))
175
+ continue;
176
+ const prev = before.get(rel);
177
+ if (prev === undefined)
178
+ added.push(rel);
179
+ else if (prev !== hash)
180
+ modified.push(rel);
181
+ }
182
+ for (const rel of before.keys()) {
183
+ if (!after.has(rel) && !isEngineScratch(rel))
184
+ deleted.push(rel);
185
+ }
186
+ return { added: added.sort(), modified: modified.sort(), deleted: deleted.sort() };
187
+ }
188
+ function changeCount(changes) {
189
+ return changes.added.length + changes.modified.length + changes.deleted.length;
190
+ }
191
+ /**
192
+ * Project files that no longer match what the run started from: a file the
193
+ * run would overwrite or delete was edited (or removed) meanwhile, or a file
194
+ * it would create now exists (created during the run, or never copied
195
+ * because it is gitignored). Applying over those would lose the user's work.
196
+ */
197
+ async function findConflicts(changes, baseline, projectDir) {
198
+ const conflicts = [];
199
+ const hashOf = async (rel) => {
200
+ try {
201
+ return (0, node_crypto_1.createHash)('sha256').update(await fsp.readFile(safeJoin(projectDir, rel))).digest('hex');
202
+ }
203
+ catch (err) {
204
+ if (err.code === 'ENOENT')
205
+ return null;
206
+ throw err;
207
+ }
208
+ };
209
+ for (const rel of [...changes.modified, ...changes.deleted]) {
210
+ if ((await hashOf(rel)) !== baseline.get(rel))
211
+ conflicts.push(rel);
212
+ }
213
+ for (const rel of changes.added) {
214
+ if ((await hashOf(rel)) !== null)
215
+ conflicts.push(rel);
216
+ }
217
+ return conflicts.sort();
218
+ }
219
+ const defaultIo = {
220
+ copyFile: (s, d) => fsp.copyFile(s, d),
221
+ rename: (a, b) => fsp.rename(a, b),
222
+ unlink: (f) => fsp.unlink(f),
223
+ writeFile: (f, d) => fsp.writeFile(f, d),
224
+ remove: (f) => fsp.rm(f, { force: true }),
225
+ };
226
+ /**
227
+ * applyChanges failed. When `rolledBack` is true the project is exactly as it
228
+ * was before; otherwise `changedFiles` lists what is still different.
229
+ */
230
+ class ApplyError extends Error {
231
+ constructor(message, cause, rolledBack, changedFiles) {
232
+ super(message);
233
+ this.cause = cause;
234
+ this.rolledBack = rolledBack;
235
+ this.changedFiles = changedFiles;
236
+ this.name = 'ApplyError';
237
+ }
238
+ }
239
+ exports.ApplyError = ApplyError;
240
+ /**
241
+ * Apply the engine's changes from the temp copy to the project, as one
242
+ * transaction: originals of every file about to be overwritten or deleted are
243
+ * read into memory first, each write goes through temp file + rename, and on
244
+ * any failure every file already touched is restored (new files removed).
245
+ */
246
+ async function applyChanges(changes, fromDir, toDir, io = defaultIo) {
247
+ const backups = new Map();
248
+ for (const rel of [...changes.modified, ...changes.deleted]) {
249
+ const abs = safeJoin(toDir, rel);
250
+ const content = await fsp.readFile(abs).catch((err) => {
251
+ if (err.code === 'ENOENT')
252
+ return null;
253
+ throw err;
254
+ });
255
+ if (content)
256
+ backups.set(rel, content);
257
+ }
258
+ const touched = [];
259
+ try {
260
+ for (const rel of [...changes.added, ...changes.modified]) {
261
+ const src = safeJoin(fromDir, rel);
262
+ const dest = safeJoin(toDir, rel);
263
+ await fsp.mkdir(path.dirname(dest), { recursive: true });
264
+ const staging = `${dest}.babelize-tmp-${process.pid}`;
265
+ try {
266
+ await io.copyFile(src, staging);
267
+ await io.rename(staging, dest);
268
+ touched.push(rel);
269
+ }
270
+ finally {
271
+ await fsp.rm(staging, { force: true });
272
+ }
273
+ }
274
+ for (const rel of changes.deleted) {
275
+ await io.unlink(safeJoin(toDir, rel)).catch((err) => {
276
+ if (err.code !== 'ENOENT')
277
+ throw err;
278
+ });
279
+ touched.push(rel);
280
+ }
281
+ }
282
+ catch (err) {
283
+ const notRestored = [];
284
+ for (const rel of touched.reverse()) {
285
+ const abs = safeJoin(toDir, rel);
286
+ try {
287
+ const original = backups.get(rel);
288
+ if (original)
289
+ await io.writeFile(abs, original);
290
+ else
291
+ await io.remove(abs);
292
+ }
293
+ catch {
294
+ notRestored.push(rel);
295
+ }
296
+ }
297
+ const reason = err?.message ?? String(err);
298
+ if (notRestored.length === 0) {
299
+ throw new ApplyError(`Writing changes failed (${reason}); all changes were rolled back.`, err, true, []);
300
+ }
301
+ throw new ApplyError(`Writing changes failed (${reason}) and ${notRestored.length} file(s) could not be restored.`, err, false, notRestored.sort());
302
+ }
303
+ }
304
+ /** Unified diff (git-style a/ b/ headers) of what applyChanges would do. */
305
+ async function renderUnifiedDiff(changes, beforeDir, afterDir) {
306
+ const read = (root, rel) => fsp.readFile(safeJoin(root, rel), 'utf8');
307
+ const patches = [];
308
+ const all = [
309
+ ...changes.added.map((rel) => ({ rel, kind: 'added' })),
310
+ ...changes.modified.map((rel) => ({ rel, kind: 'modified' })),
311
+ ...changes.deleted.map((rel) => ({ rel, kind: 'deleted' })),
312
+ ].sort((a, b) => a.rel.localeCompare(b.rel));
313
+ for (const { rel, kind } of all) {
314
+ const oldText = kind === 'added' ? '' : await read(beforeDir, rel);
315
+ const newText = kind === 'deleted' ? '' : await read(afterDir, rel);
316
+ const header = `diff --git a/${rel} b/${rel}\n` +
317
+ (kind === 'added' ? 'new file\n' : kind === 'deleted' ? 'deleted file\n' : '');
318
+ const patch = (0, diff_1.createPatch)(rel, oldText, newText, '', '', { context: 3 })
319
+ // createPatch emits "Index: x\n===\n--- x\n+++ x"; rewrite to git's a/ b/ form.
320
+ .replace(/^Index: .*\n=+\n/, '')
321
+ .replace(/^--- .*$/m, kind === 'added' ? '--- /dev/null' : `--- a/${rel}`)
322
+ .replace(/^\+\+\+ .*$/m, kind === 'deleted' ? '+++ /dev/null' : `+++ b/${rel}`);
323
+ patches.push(header + patch);
324
+ }
325
+ return patches.join('');
326
+ }
327
+ function lineCount(text) {
328
+ if (!text)
329
+ return 0;
330
+ return text.split('\n').length - (text.endsWith('\n') ? 1 : 0);
331
+ }
332
+ /**
333
+ * Lines added/removed per changed file, from the files' old and new content
334
+ * (never from a rendered diff). Unreadable files count as empty.
335
+ */
336
+ async function diffStats(changes, beforeDir, afterDir) {
337
+ const read = (root, rel) => fsp.readFile(safeJoin(root, rel), 'utf8').catch(() => '');
338
+ const out = [];
339
+ for (const file of changes.added)
340
+ out.push({ file, kind: 'added', added: lineCount(await read(afterDir, file)), removed: 0 });
341
+ for (const file of changes.deleted)
342
+ out.push({ file, kind: 'deleted', added: 0, removed: lineCount(await read(beforeDir, file)) });
343
+ for (const file of changes.modified) {
344
+ let added = 0;
345
+ let removed = 0;
346
+ for (const part of (0, diff_1.diffLines)(await read(beforeDir, file), await read(afterDir, file))) {
347
+ if (part.added)
348
+ added += part.count ?? lineCount(part.value);
349
+ else if (part.removed)
350
+ removed += part.count ?? lineCount(part.value);
351
+ }
352
+ out.push({ file, kind: 'modified', added, removed });
353
+ }
354
+ return out.sort((a, b) => a.file.localeCompare(b.file));
355
+ }
@@ -0,0 +1,20 @@
1
+ import type { ExtractedString, Phase1Result, Warning, WorkspaceInfo } from '../../runtime/types';
2
+ import type { NotInjectedString } from '../../runtime/types';
3
+ export interface ExtractOptions {
4
+ /**
5
+ * Group JSX sentences into one message. Off when the runtime can't format
6
+ * ICU (react-i18next without i18next-icu). Default: on for React/Next.js.
7
+ */
8
+ sentences?: boolean;
9
+ /** Generate ICU plurals in sentences ("{count} items"). Needs an LLM translator. Default true. */
10
+ plurals?: boolean;
11
+ }
12
+ export declare function extractStrings(workspace: WorkspaceInfo, filesToProcess?: string[], extractOptions?: ExtractOptions): Promise<Phase1Result>;
13
+ export declare function extractStringsFromFile(content: string, filePath: string, detectFormats?: boolean, options?: {
14
+ relaxComponentGuard?: boolean;
15
+ framework?: string;
16
+ } & ExtractOptions): Promise<{
17
+ strings: ExtractedString[];
18
+ warnings: Warning[];
19
+ notInjected?: NotInjectedString[];
20
+ }>;