@fluenti/cli 0.5.0 → 0.6.1

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 (117) hide show
  1. package/dist/cli/src/ai-provider.d.ts.map +1 -0
  2. package/dist/{catalog.d.ts → cli/src/catalog.d.ts} +1 -1
  3. package/dist/cli/src/catalog.d.ts.map +1 -0
  4. package/dist/cli/src/check.d.ts.map +1 -0
  5. package/dist/cli/src/cli.d.ts.map +1 -0
  6. package/dist/cli/src/codemod.d.ts +19 -0
  7. package/dist/cli/src/codemod.d.ts.map +1 -0
  8. package/dist/cli/src/compile-cache.d.ts.map +1 -0
  9. package/dist/cli/src/compile-runner.d.ts.map +1 -0
  10. package/dist/cli/src/compile-worker.d.ts.map +1 -0
  11. package/dist/cli/src/compile.d.ts.map +1 -0
  12. package/dist/cli/src/config-loader.d.ts.map +1 -0
  13. package/dist/{config.d.ts → cli/src/config.d.ts} +1 -1
  14. package/dist/cli/src/config.d.ts.map +1 -0
  15. package/dist/cli/src/doctor.d.ts +19 -0
  16. package/dist/cli/src/doctor.d.ts.map +1 -0
  17. package/dist/{extract-cache.d.ts → cli/src/extract-cache.d.ts} +1 -1
  18. package/dist/cli/src/extract-cache.d.ts.map +1 -0
  19. package/dist/cli/src/extract-runner.d.ts.map +1 -0
  20. package/dist/cli/src/glossary.d.ts.map +1 -0
  21. package/dist/{index.d.ts → cli/src/index.d.ts} +6 -2
  22. package/dist/cli/src/index.d.ts.map +1 -0
  23. package/dist/cli/src/init.d.ts.map +1 -0
  24. package/dist/cli/src/json-format.d.ts.map +1 -0
  25. package/dist/cli/src/lint.d.ts.map +1 -0
  26. package/dist/cli/src/migrate.d.ts.map +1 -0
  27. package/dist/cli/src/parallel-compile.d.ts.map +1 -0
  28. package/dist/cli/src/po-format.d.ts.map +1 -0
  29. package/dist/cli/src/stats-format.d.ts.map +1 -0
  30. package/dist/cli/src/translate-parse.d.ts.map +1 -0
  31. package/dist/cli/src/translate-prompt.d.ts.map +1 -0
  32. package/dist/cli/src/translate.d.ts.map +1 -0
  33. package/dist/{tsx-extractor.d.ts → cli/src/tsx-extractor.d.ts} +1 -1
  34. package/dist/cli/src/tsx-extractor.d.ts.map +1 -0
  35. package/dist/cli/src/validation.d.ts.map +1 -0
  36. package/dist/{vue-extractor.d.ts → cli/src/vue-extractor.d.ts} +1 -1
  37. package/dist/cli/src/vue-extractor.d.ts.map +1 -0
  38. package/dist/cli.cjs +10 -22
  39. package/dist/cli.cjs.map +1 -1
  40. package/dist/cli.js +333 -406
  41. package/dist/cli.js.map +1 -1
  42. package/dist/compile-C3VLvhUf.cjs +8 -0
  43. package/dist/{compile-kXClO6q4.cjs.map → compile-C3VLvhUf.cjs.map} +1 -1
  44. package/dist/{compile-CdA4EZ-p.js → compile-CZVpE5Md.js} +2 -2
  45. package/dist/{compile-CdA4EZ-p.js.map → compile-CZVpE5Md.js.map} +1 -1
  46. package/dist/compile-worker.cjs +1 -1
  47. package/dist/compile-worker.cjs.map +1 -1
  48. package/dist/compile-worker.js +1 -1
  49. package/dist/doctor-BqXXxyST.js +670 -0
  50. package/dist/doctor-BqXXxyST.js.map +1 -0
  51. package/dist/doctor-xp8WS8sr.cjs +24 -0
  52. package/dist/doctor-xp8WS8sr.cjs.map +1 -0
  53. package/dist/index.cjs +1 -1
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.js +64 -64
  56. package/dist/index.js.map +1 -1
  57. package/dist/tsx-extractor-AOjsbOmp.cjs +2 -0
  58. package/dist/{tsx-extractor-B0vFXziu.cjs.map → tsx-extractor-AOjsbOmp.cjs.map} +1 -1
  59. package/dist/tsx-extractor-C-HZNobu.js.map +1 -1
  60. package/dist/vue-extractor.cjs +1 -1
  61. package/dist/vue-extractor.cjs.map +1 -1
  62. package/dist/vue-extractor.js.map +1 -1
  63. package/package.json +2 -2
  64. package/dist/ai-provider.d.ts.map +0 -1
  65. package/dist/catalog.d.ts.map +0 -1
  66. package/dist/check.d.ts.map +0 -1
  67. package/dist/cli.d.ts.map +0 -1
  68. package/dist/compile-cache.d.ts.map +0 -1
  69. package/dist/compile-kXClO6q4.cjs +0 -8
  70. package/dist/compile-runner.d.ts.map +0 -1
  71. package/dist/compile-worker.d.ts.map +0 -1
  72. package/dist/compile.d.ts.map +0 -1
  73. package/dist/config-loader.d.ts.map +0 -1
  74. package/dist/config.d.ts.map +0 -1
  75. package/dist/extract-cache-BioSaoFo.cjs +0 -10
  76. package/dist/extract-cache-BioSaoFo.cjs.map +0 -1
  77. package/dist/extract-cache-C-MI1_ll.js +0 -325
  78. package/dist/extract-cache-C-MI1_ll.js.map +0 -1
  79. package/dist/extract-cache.d.ts.map +0 -1
  80. package/dist/extract-runner.d.ts.map +0 -1
  81. package/dist/glossary.d.ts.map +0 -1
  82. package/dist/index.d.ts.map +0 -1
  83. package/dist/init.d.ts.map +0 -1
  84. package/dist/json-format.d.ts.map +0 -1
  85. package/dist/lint.d.ts.map +0 -1
  86. package/dist/migrate.d.ts.map +0 -1
  87. package/dist/parallel-compile.d.ts.map +0 -1
  88. package/dist/po-format.d.ts.map +0 -1
  89. package/dist/stats-format.d.ts.map +0 -1
  90. package/dist/translate-parse.d.ts.map +0 -1
  91. package/dist/translate-prompt.d.ts.map +0 -1
  92. package/dist/translate.d.ts.map +0 -1
  93. package/dist/tsx-extractor-B0vFXziu.cjs +0 -2
  94. package/dist/tsx-extractor.d.ts.map +0 -1
  95. package/dist/validation.d.ts.map +0 -1
  96. package/dist/vue-extractor.d.ts.map +0 -1
  97. /package/dist/{ai-provider.d.ts → cli/src/ai-provider.d.ts} +0 -0
  98. /package/dist/{check.d.ts → cli/src/check.d.ts} +0 -0
  99. /package/dist/{cli.d.ts → cli/src/cli.d.ts} +0 -0
  100. /package/dist/{compile-cache.d.ts → cli/src/compile-cache.d.ts} +0 -0
  101. /package/dist/{compile-runner.d.ts → cli/src/compile-runner.d.ts} +0 -0
  102. /package/dist/{compile-worker.d.ts → cli/src/compile-worker.d.ts} +0 -0
  103. /package/dist/{compile.d.ts → cli/src/compile.d.ts} +0 -0
  104. /package/dist/{config-loader.d.ts → cli/src/config-loader.d.ts} +0 -0
  105. /package/dist/{extract-runner.d.ts → cli/src/extract-runner.d.ts} +0 -0
  106. /package/dist/{glossary.d.ts → cli/src/glossary.d.ts} +0 -0
  107. /package/dist/{init.d.ts → cli/src/init.d.ts} +0 -0
  108. /package/dist/{json-format.d.ts → cli/src/json-format.d.ts} +0 -0
  109. /package/dist/{lint.d.ts → cli/src/lint.d.ts} +0 -0
  110. /package/dist/{migrate.d.ts → cli/src/migrate.d.ts} +0 -0
  111. /package/dist/{parallel-compile.d.ts → cli/src/parallel-compile.d.ts} +0 -0
  112. /package/dist/{po-format.d.ts → cli/src/po-format.d.ts} +0 -0
  113. /package/dist/{stats-format.d.ts → cli/src/stats-format.d.ts} +0 -0
  114. /package/dist/{translate-parse.d.ts → cli/src/translate-parse.d.ts} +0 -0
  115. /package/dist/{translate-prompt.d.ts → cli/src/translate-prompt.d.ts} +0 -0
  116. /package/dist/{translate.d.ts → cli/src/translate.d.ts} +0 -0
  117. /package/dist/{validation.d.ts → cli/src/validation.d.ts} +0 -0
@@ -0,0 +1,670 @@
1
+ import { hashMessage as e } from "@fluenti/core/compiler";
2
+ import * as t from "gettext-parser";
3
+ import { loadConfig as n } from "@fluenti/core/config";
4
+ import { appendFileSync as r, existsSync as i, mkdirSync as a, readFileSync as o, statSync as s, writeFileSync as c } from "node:fs";
5
+ import { dirname as l, resolve as u } from "node:path";
6
+ import { Worker as d } from "node:worker_threads";
7
+ import { availableParallelism as f } from "node:os";
8
+ import { fileURLToPath as p } from "node:url";
9
+ import m from "fast-glob";
10
+ import h from "consola";
11
+ //#region src/catalog.ts
12
+ function g(e, t, n) {
13
+ let r = new Set(t.map((e) => e.id)), i = /* @__PURE__ */ new Set(), a = {}, o = 0, s = 0, c = 0;
14
+ for (let r of t) {
15
+ let t = e[r.id], c = t ? void 0 : v(e, r, i), l = `${r.origin.file}:${r.origin.line}`, u = t ?? c?.entry;
16
+ if (c && i.add(c.id), u) a[r.id] = {
17
+ ...u,
18
+ message: r.message ?? u.message,
19
+ context: r.context,
20
+ comment: r.comment,
21
+ origin: l,
22
+ obsolete: !1
23
+ }, s++;
24
+ else if (a[r.id]) {
25
+ let e = a[r.id];
26
+ a[r.id] = {
27
+ ...e,
28
+ origin: _(e.origin, l)
29
+ };
30
+ } else a[r.id] = {
31
+ message: r.message,
32
+ context: r.context,
33
+ comment: r.comment,
34
+ origin: l
35
+ }, o++;
36
+ if (n?.stripFuzzy) {
37
+ let { fuzzy: e, ...t } = a[r.id];
38
+ a[r.id] = t;
39
+ }
40
+ }
41
+ for (let [t, i] of Object.entries(e)) if (!r.has(t)) {
42
+ let { fuzzy: e, ...r } = i;
43
+ a[t] = n?.stripFuzzy ? {
44
+ ...r,
45
+ obsolete: !0
46
+ } : {
47
+ ...i,
48
+ obsolete: !0
49
+ }, c++;
50
+ }
51
+ return {
52
+ catalog: a,
53
+ result: {
54
+ added: o,
55
+ unchanged: s,
56
+ obsolete: c
57
+ }
58
+ };
59
+ }
60
+ function _(e, t) {
61
+ if (!e) return t;
62
+ let n = [...new Set([...Array.isArray(e) ? e : [e], t])];
63
+ return n.length === 1 ? n[0] : n;
64
+ }
65
+ function v(e, t, n) {
66
+ if (!t.context) return;
67
+ let r = `${t.origin.file}:${t.origin.line}`;
68
+ for (let [i, a] of Object.entries(e)) if (!n.has(i) && a.context === void 0 && a.message === t.message && y(a.origin, r)) return {
69
+ id: i,
70
+ entry: a
71
+ };
72
+ }
73
+ function y(e, t) {
74
+ return e ? (Array.isArray(e) ? e : [e]).some((e) => e === t || b(e) === b(t)) : !1;
75
+ }
76
+ function b(e) {
77
+ return e.match(/^(.*):\d+$/)?.[1] ?? e;
78
+ }
79
+ //#endregion
80
+ //#region src/json-format.ts
81
+ function x(e) {
82
+ let t = JSON.parse(e), n = {};
83
+ for (let [e, r] of Object.entries(t)) if (typeof r == "object" && r) {
84
+ let t = r;
85
+ n[e] = {
86
+ message: typeof t.message == "string" ? t.message : void 0,
87
+ context: typeof t.context == "string" ? t.context : void 0,
88
+ comment: typeof t.comment == "string" ? t.comment : void 0,
89
+ translation: typeof t.translation == "string" ? t.translation : void 0,
90
+ origin: typeof t.origin == "string" || Array.isArray(t.origin) && t.origin.every((e) => typeof e == "string") ? t.origin : void 0,
91
+ obsolete: typeof t.obsolete == "boolean" ? t.obsolete : void 0,
92
+ fuzzy: typeof t.fuzzy == "boolean" ? t.fuzzy : void 0
93
+ };
94
+ }
95
+ return n;
96
+ }
97
+ function ee(e) {
98
+ let t = {};
99
+ for (let [n, r] of Object.entries(e)) {
100
+ let e = {};
101
+ r.message !== void 0 && (e.message = r.message), r.context !== void 0 && (e.context = r.context), r.comment !== void 0 && (e.comment = r.comment), r.translation !== void 0 && (e.translation = r.translation), r.origin !== void 0 && (e.origin = r.origin), r.obsolete && (e.obsolete = !0), r.fuzzy && (e.fuzzy = !0), t[n] = e;
102
+ }
103
+ return JSON.stringify(t, null, 2) + "\n";
104
+ }
105
+ //#endregion
106
+ //#region src/po-format.ts
107
+ var S = "fluenti-id:";
108
+ function C(t, n, r) {
109
+ for (let [i, a] of Object.entries(t)) for (let [t, o] of Object.entries(a)) {
110
+ if (!t) continue;
111
+ let a = i || o.msgctxt || void 0, s = o.msgstr?.[0] ?? void 0, c = o.comments?.reference ?? void 0, l = c?.includes("\n") ? c.split("\n").map((e) => e.trim()).filter(Boolean) : c?.includes(" ") ? c.split(/\s+/).filter(Boolean) : c, u = Array.isArray(l) && l.length === 1 ? l[0] : l, d = !r && (o.comments?.flag?.includes("fuzzy") ?? !1), { comment: f, customId: p, sourceMessage: m } = E(o.comments?.extracted), h = m && (p !== void 0 || e(m, a) === t) ? m : void 0, g = p ?? (h ? t : e(t, a));
112
+ n[g] = {
113
+ message: h ?? t,
114
+ ...a === void 0 ? {} : { context: a },
115
+ ...f === void 0 ? {} : { comment: f },
116
+ ...s ? { translation: s } : {},
117
+ ...u === void 0 ? {} : { origin: u },
118
+ ...d ? { fuzzy: !0 } : {},
119
+ ...r ? { obsolete: !0 } : {}
120
+ };
121
+ }
122
+ }
123
+ function w(e) {
124
+ let n = t.po.parse(e), r = {};
125
+ return C(n.translations ?? {}, r, !1), n.obsolete && C(n.obsolete, r, !0), r;
126
+ }
127
+ function T(n) {
128
+ let r = { "": { "": {
129
+ msgid: "",
130
+ msgstr: ["Content-Type: text/plain; charset=UTF-8\n"]
131
+ } } }, i = {};
132
+ for (let [t, a] of Object.entries(n)) {
133
+ let n = {
134
+ msgid: a.message !== void 0 && e(a.message, a.context) === t ? a.message ?? t : t,
135
+ ...a.context === void 0 ? {} : { msgctxt: a.context },
136
+ msgstr: [a.translation ?? ""]
137
+ }, o = {};
138
+ a.origin && !a.obsolete && (o.reference = Array.isArray(a.origin) ? a.origin.join("\n") : a.origin);
139
+ let s = O(t, a.message ?? t, a.context, a.comment);
140
+ if (s && (o.extracted = s), a.fuzzy && !a.obsolete && (o.flag = "fuzzy"), (o.reference || o.extracted || o.flag) && (n.comments = o), a.obsolete) {
141
+ let e = a.context ?? "";
142
+ i[e] ??= {}, i[e][n.msgid] = n;
143
+ } else {
144
+ let e = a.context ?? "";
145
+ r[e] ??= {}, r[e][n.msgid] = n;
146
+ }
147
+ }
148
+ let a = {
149
+ headers: { "Content-Type": "text/plain; charset=UTF-8" },
150
+ translations: r,
151
+ ...Object.keys(i).length > 0 ? { obsolete: i } : {}
152
+ };
153
+ return t.po.compile(a).toString();
154
+ }
155
+ function E(e) {
156
+ if (!e) return {};
157
+ let t = e.split("\n").map((e) => e.trim()).filter(Boolean), n, r, i = [];
158
+ for (let e of t) {
159
+ if (e.startsWith(S)) {
160
+ n = e.slice(11).trim() || void 0;
161
+ continue;
162
+ }
163
+ if (e.startsWith("msg`") && e.endsWith("`")) {
164
+ r = e.slice(4, -1);
165
+ continue;
166
+ }
167
+ if (e.startsWith("Trans: ")) {
168
+ r = D(e.slice(7));
169
+ continue;
170
+ }
171
+ i.push(e);
172
+ }
173
+ return {
174
+ ...i.length > 0 ? { comment: i.join("\n") } : {},
175
+ ...n ? { customId: n } : {},
176
+ ...r ? { sourceMessage: r } : {}
177
+ };
178
+ }
179
+ function D(e) {
180
+ let t = [], n = 0;
181
+ return e.replace(/<\/?([a-zA-Z][\w-]*)>/g, (e, r) => {
182
+ let i = r;
183
+ if (e.startsWith("</")) {
184
+ for (let e = t.length - 1; e >= 0; e--) {
185
+ let n = t[e];
186
+ if (n?.tag === i) return t = t.filter((t, n) => n !== e), `</${n.index}>`;
187
+ }
188
+ return e;
189
+ }
190
+ let a = n++;
191
+ return t.push({
192
+ tag: i,
193
+ index: a
194
+ }), `<${a}>`;
195
+ });
196
+ }
197
+ function O(t, n, r, i) {
198
+ let a = [];
199
+ return i && a.push(i), t !== e(n, r) && (a.push(`${S} ${t}`), a.push(`msg\`${n}\``)), a.length > 0 ? a.join("\n") : void 0;
200
+ }
201
+ //#endregion
202
+ //#region src/parallel-compile.ts
203
+ var k = 3e4;
204
+ function A() {
205
+ return u(typeof __dirname < "u" ? __dirname : l(p(import.meta.url)), "compile-worker.js");
206
+ }
207
+ async function j(e, t) {
208
+ if (e.length === 0) return [];
209
+ if (e.length === 1) {
210
+ let { compileCatalog: t } = await import("./compile-CZVpE5Md.js").then((e) => e.a), n = e[0], { code: r, stats: i } = t(n.catalog, n.locale, n.allIds, n.sourceLocale, n.options);
211
+ return [{
212
+ locale: n.locale,
213
+ code: r,
214
+ stats: i
215
+ }];
216
+ }
217
+ let n = A();
218
+ if (!i(n)) return te(e);
219
+ let r = t ?? Math.min(e.length, f()), a = [], o = [...e], s = !1;
220
+ return new Promise((e, t) => {
221
+ let i = 0;
222
+ function c() {
223
+ if (s) return;
224
+ let r = o.shift();
225
+ if (!r) {
226
+ i === 0 && e(a);
227
+ return;
228
+ }
229
+ i++;
230
+ let l = new d(n), u = setTimeout(() => {
231
+ s || (s = !0, i--, l.terminate(), t(/* @__PURE__ */ Error(`Worker timed out after ${k}ms compiling locale "${r.locale}"`)));
232
+ }, k);
233
+ l.on("message", (e) => {
234
+ if (clearTimeout(u), !s) {
235
+ if (e.error) {
236
+ s = !0, i--, l.terminate(), t(/* @__PURE__ */ Error(`Failed to compile locale "${e.locale}": ${e.error}`));
237
+ return;
238
+ }
239
+ a.push({
240
+ locale: e.locale,
241
+ code: e.code,
242
+ stats: e.stats
243
+ }), i--, l.terminate(), c();
244
+ }
245
+ }), l.on("error", (e) => {
246
+ clearTimeout(u), s || (s = !0, l.terminate(), t(/* @__PURE__ */ Error(`Worker error compiling locale "${r.locale}": ${e.message}`)));
247
+ }), l.on("exit", (e) => {
248
+ clearTimeout(u), e !== 0 && !s && (s = !0, t(/* @__PURE__ */ Error(`Worker exited with code ${e} while compiling locale "${r.locale}"`)));
249
+ });
250
+ let f = {
251
+ locale: r.locale,
252
+ catalog: r.catalog,
253
+ allIds: r.allIds,
254
+ sourceLocale: r.sourceLocale,
255
+ options: r.options
256
+ };
257
+ l.postMessage(f);
258
+ }
259
+ let l = Math.min(r, o.length);
260
+ for (let e = 0; e < l; e++) c();
261
+ });
262
+ }
263
+ async function te(e) {
264
+ let { compileCatalog: t } = await import("./compile-CZVpE5Md.js").then((e) => e.a);
265
+ return Promise.all(e.map((e) => {
266
+ let { code: n, stats: r } = t(e.catalog, e.locale, e.allIds, e.sourceLocale, e.options);
267
+ return {
268
+ locale: e.locale,
269
+ code: n,
270
+ stats: r
271
+ };
272
+ }));
273
+ }
274
+ //#endregion
275
+ //#region src/extract-cache.ts
276
+ var M = "1", N = class {
277
+ data;
278
+ cachePath;
279
+ dirty = !1;
280
+ constructor(e, t) {
281
+ this.cachePath = u(t ? u(e, ".cache", t) : u(e, ".cache"), "extract-cache.json"), this.data = this.load();
282
+ }
283
+ get(e) {
284
+ let t = this.data.entries[e];
285
+ if (t) try {
286
+ let n = s(e);
287
+ if (n.mtimeMs === t.mtime && n.size === t.size) return t.messages;
288
+ } catch {}
289
+ }
290
+ set(e, t) {
291
+ try {
292
+ let n = s(e);
293
+ this.data.entries[e] = {
294
+ mtime: n.mtimeMs,
295
+ size: n.size,
296
+ messages: t
297
+ }, this.dirty = !0;
298
+ } catch {}
299
+ }
300
+ prune(e) {
301
+ for (let t of Object.keys(this.data.entries)) e.has(t) || (delete this.data.entries[t], this.dirty = !0);
302
+ }
303
+ save() {
304
+ if (this.dirty) try {
305
+ a(l(this.cachePath), { recursive: !0 }), c(this.cachePath, JSON.stringify(this.data), "utf-8"), this.dirty = !1;
306
+ } catch {}
307
+ }
308
+ get size() {
309
+ return Object.keys(this.data.entries).length;
310
+ }
311
+ load() {
312
+ try {
313
+ if (i(this.cachePath)) {
314
+ let e = o(this.cachePath, "utf-8"), t = JSON.parse(e);
315
+ if (t.version === M) return t;
316
+ }
317
+ } catch {}
318
+ return {
319
+ version: M,
320
+ entries: {}
321
+ };
322
+ }
323
+ }, P = new Set([
324
+ "Trans",
325
+ "Plural",
326
+ "Select",
327
+ "DateTime",
328
+ "NumberFormat"
329
+ ]), F = [
330
+ "src/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs,vue,mdx}",
331
+ "app/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs,vue,mdx}",
332
+ "pages/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs,vue,mdx}",
333
+ "components/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs,vue,mdx}",
334
+ "layouts/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs,vue,mdx}"
335
+ ];
336
+ function I(e) {
337
+ let t = e.trim(), n = t.startsWith("type "), r = (n ? t.slice(5).trim() : t).split(/\s+as\s+/);
338
+ return {
339
+ imported: r[0].trim(),
340
+ local: (r[1] ?? r[0]).trim(),
341
+ isType: n
342
+ };
343
+ }
344
+ function L(e) {
345
+ let t = e.isType ? "type " : "";
346
+ return e.imported === e.local ? `${t}${e.imported}` : `${t}${e.imported} as ${e.local}`;
347
+ }
348
+ function R(e) {
349
+ let t = /* @__PURE__ */ new Set(), n = [];
350
+ for (let r of e) {
351
+ let e = `${r.isType ? "type:" : "value:"}${r.imported}:${r.local}`;
352
+ t.has(e) || (t.add(e), n.push(r));
353
+ }
354
+ return n;
355
+ }
356
+ function z(e, t) {
357
+ let n = RegExp(`import\\s*\\{([\\s\\S]*?)\\}\\s*from\\s*['"]${t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}['"];?\\n?`, "g"), r = [...e.matchAll(n)];
358
+ if (r.length <= 1) return e;
359
+ let i = `import { ${R(r.flatMap((e) => e[1].split(",").map((e) => I(e)).filter((e) => e.imported.length > 0))).map(L).join(", ")} } from '${t}'\n`, a = !0;
360
+ return e.replace(n, () => a ? (a = !1, i) : "");
361
+ }
362
+ function B(e) {
363
+ let t = e, n = !1, r = !1;
364
+ if (t = t.replace(/import\s*\{([\s\S]*?)\}\s*from\s*['"](@fluenti\/(react|vue|solid)(?:\/components)?)['"];?/g, (e, t, i, a) => {
365
+ let o = t.split(",").map((e) => e.trim()).filter(Boolean).map(I), s = [], c = [], l = [];
366
+ for (let e of o) {
367
+ let t = { ...e };
368
+ if (a === "solid" && t.imported === "createFluentiContext" && (t.imported = "createFluenti", t.local === "createFluentiContext" && (t.local = "createFluenti", r = !0)), t.imported === "interpolate") {
369
+ l.push({
370
+ ...t,
371
+ isType: !1
372
+ });
373
+ continue;
374
+ }
375
+ if (!t.isType && P.has(t.imported) && i.endsWith("/components")) {
376
+ c.push(t);
377
+ continue;
378
+ }
379
+ s.push(t);
380
+ }
381
+ let u = [];
382
+ s.length > 0 && !i.endsWith("/components") && u.push(`import { ${R(s).map(L).join(", ")} } from '@fluenti/${a}'`), c.length > 0 && u.push(`import { ${R(c).map(L).join(", ")} } from '@fluenti/${a}/components'`), l.length > 0 && u.push(`import { ${R(l).map(L).join(", ")} } from '@fluenti/core/runtime'`), s.length > 0 && i.endsWith("/components") && u.unshift(`import { ${R(s).map(L).join(", ")} } from '@fluenti/${a}'`);
383
+ let d = u.join("\n");
384
+ return d !== e && (n = !0), d;
385
+ }), r) {
386
+ let e = t.replace(/\bcreateFluentiContext\b/g, "createFluenti");
387
+ e !== t && (t = e, n = !0);
388
+ }
389
+ for (let e of [
390
+ "@fluenti/react",
391
+ "@fluenti/react/components",
392
+ "@fluenti/vue",
393
+ "@fluenti/vue/components",
394
+ "@fluenti/solid",
395
+ "@fluenti/solid/components",
396
+ "@fluenti/core/runtime"
397
+ ]) {
398
+ let r = z(t, e);
399
+ r !== t && (t = r, n = !0);
400
+ }
401
+ return {
402
+ code: t,
403
+ changed: n
404
+ };
405
+ }
406
+ async function V(e) {
407
+ let t = await m(e.include && e.include.length > 0 ? e.include : F, {
408
+ cwd: e.cwd,
409
+ absolute: !1,
410
+ ignore: [
411
+ "**/node_modules/**",
412
+ "**/dist/**",
413
+ "**/.fluenti/**"
414
+ ]
415
+ }), n = [];
416
+ for (let r of t) {
417
+ let t = u(e.cwd, r), i = B(o(t, "utf-8"));
418
+ i.changed && (e.write && c(t, i.code, "utf-8"), n.push({
419
+ file: r,
420
+ changed: !0
421
+ }));
422
+ }
423
+ return {
424
+ changedFiles: n,
425
+ changedCount: n.length
426
+ };
427
+ }
428
+ //#endregion
429
+ //#region src/init.ts
430
+ var H = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{1,8})*$/;
431
+ function U(e) {
432
+ if (!H.test(e)) throw Error(`Invalid locale format: "${e}"`);
433
+ return e;
434
+ }
435
+ var W = [
436
+ {
437
+ dep: "next",
438
+ name: "nextjs",
439
+ pluginPackage: "@fluenti/next"
440
+ },
441
+ {
442
+ dep: "nuxt",
443
+ name: "nuxt",
444
+ pluginPackage: "@fluenti/vue"
445
+ },
446
+ {
447
+ dep: "@solidjs/start",
448
+ name: "solidstart",
449
+ pluginPackage: "@fluenti/solid"
450
+ },
451
+ {
452
+ dep: "vue",
453
+ name: "vue",
454
+ pluginPackage: "@fluenti/vue"
455
+ },
456
+ {
457
+ dep: "solid-js",
458
+ name: "solid",
459
+ pluginPackage: "@fluenti/solid"
460
+ },
461
+ {
462
+ dep: "react",
463
+ name: "react",
464
+ pluginPackage: "@fluenti/react"
465
+ }
466
+ ];
467
+ function G(e) {
468
+ for (let t of W) if (t.dep in e) return {
469
+ name: t.name,
470
+ pluginPackage: t.pluginPackage
471
+ };
472
+ return {
473
+ name: "unknown",
474
+ pluginPackage: null
475
+ };
476
+ }
477
+ function K(e) {
478
+ let t = e.locales.map((e) => JSON.stringify(e)).join(", ");
479
+ return `import { defineConfig } from '@fluenti/cli'
480
+
481
+ export default defineConfig({
482
+ sourceLocale: ${JSON.stringify(e.sourceLocale)},
483
+ locales: [${t}],
484
+ catalogDir: './locales',
485
+ format: ${JSON.stringify(e.format)},
486
+ include: ['./src/**/*.{vue,tsx,jsx,ts,js}'],
487
+ compileOutDir: './src/locales/compiled',
488
+ })
489
+ `;
490
+ }
491
+ async function q(e) {
492
+ let t = u(e.cwd, "package.json");
493
+ if (!i(t)) {
494
+ h.error("No package.json found in current directory.");
495
+ return;
496
+ }
497
+ let n = JSON.parse(o(t, "utf-8")), a = G({
498
+ ...n.dependencies,
499
+ ...n.devDependencies
500
+ });
501
+ h.info(`Detected framework: ${a.name}`), a.pluginPackage && h.info(`Recommended plugin: ${a.pluginPackage}`);
502
+ let s = u(e.cwd, "fluenti.config.ts");
503
+ if (i(s)) {
504
+ h.warn("fluenti.config.ts already exists. Skipping config generation.");
505
+ return;
506
+ }
507
+ let l = await h.prompt("Source locale?", {
508
+ type: "text",
509
+ default: "en",
510
+ placeholder: "en"
511
+ });
512
+ if (typeof l == "symbol") return;
513
+ let d = await h.prompt("Target locales (comma-separated)?", {
514
+ type: "text",
515
+ default: "ja,zh-CN",
516
+ placeholder: "ja,zh-CN"
517
+ });
518
+ if (typeof d == "symbol") return;
519
+ let f = await h.prompt("Catalog format?", {
520
+ type: "select",
521
+ options: ["po", "json"],
522
+ initial: "po"
523
+ });
524
+ if (typeof f == "symbol") return;
525
+ let p = d.split(",").map((e) => e.trim()).filter(Boolean);
526
+ U(l);
527
+ for (let e of p) U(e);
528
+ c(s, K({
529
+ sourceLocale: l,
530
+ locales: [l, ...p.filter((e) => e !== l)],
531
+ format: f
532
+ }), "utf-8"), h.success("Created fluenti.config.ts");
533
+ let m = u(e.cwd, ".gitignore"), g = "src/locales/compiled/";
534
+ i(m) ? o(m, "utf-8").includes(g) || (r(m, `\n# Fluenti compiled catalogs\n${g}\n`), h.success("Updated .gitignore")) : (c(m, `# Fluenti compiled catalogs\n${g}\n`), h.success("Created .gitignore"));
535
+ let _ = n.scripts ?? {}, v = {}, y = !1;
536
+ if (_["i18n:extract"] || (v["i18n:extract"] = "fluenti extract", y = !0), _["i18n:compile"] || (v["i18n:compile"] = "fluenti compile", y = !0), y) {
537
+ let e = {
538
+ ...n,
539
+ scripts: {
540
+ ..._,
541
+ ...v
542
+ }
543
+ };
544
+ c(t, JSON.stringify(e, null, 2) + "\n", "utf-8"), h.success("Added i18n:extract and i18n:compile scripts to package.json");
545
+ }
546
+ h.log(""), h.box({
547
+ title: "Next steps",
548
+ message: [
549
+ a.pluginPackage ? `1. Install: pnpm add -D ${a.pluginPackage} @fluenti/cli` : "1. Install: pnpm add -D @fluenti/cli",
550
+ a.name === "nextjs" ? "2. Add withFluenti() to your next.config.ts" : a.name === "unknown" ? "2. Configure your build tool with the framework Vite plugin or @fluenti/next" : "2. Add the Vite plugin to your vite.config.ts (e.g. fluentiVue() from @fluenti/vue/vite-plugin)",
551
+ "3. Run: npx fluenti extract",
552
+ "4. Translate your messages",
553
+ "5. Run: npx fluenti compile"
554
+ ].join("\n")
555
+ });
556
+ }
557
+ //#endregion
558
+ //#region src/doctor.ts
559
+ var J = [
560
+ "src/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs,vue,mdx}",
561
+ "app/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs,vue,mdx}",
562
+ "pages/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs,vue,mdx}",
563
+ "components/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs,vue,mdx}",
564
+ "layouts/**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs,vue,mdx}"
565
+ ], Y = /import\s*\{[\s\S]*?\binterpolate\b[\s\S]*?\}\s*from\s*['"]@fluenti\/(react|vue|solid)(?:\/components)?['"]/g, X = /from\s*['"]@fluenti\/core\/internal['"]/g;
566
+ function Z(e) {
567
+ return i(e) ? o(e, "utf-8") : void 0;
568
+ }
569
+ function ne(e, t) {
570
+ if (t) return u(e, t);
571
+ for (let t of [
572
+ "fluenti.config.ts",
573
+ "fluenti.config.mts",
574
+ "fluenti.config.js",
575
+ "fluenti.config.mjs"
576
+ ]) {
577
+ let n = u(e, t);
578
+ if (i(n)) return n;
579
+ }
580
+ }
581
+ async function re(e) {
582
+ return m(J, {
583
+ cwd: e,
584
+ absolute: !1,
585
+ ignore: [
586
+ "**/node_modules/**",
587
+ "**/dist/**",
588
+ "**/.fluenti/**"
589
+ ]
590
+ });
591
+ }
592
+ function Q(e, t, n, r) {
593
+ e.push({
594
+ severity: t,
595
+ code: n,
596
+ message: r
597
+ });
598
+ }
599
+ function ie(e) {
600
+ let t = Z(u(e, "package.json"));
601
+ if (t) return JSON.parse(t);
602
+ }
603
+ function ae(e) {
604
+ return e ? e.includes("@fluenti/") && e.includes("vite-plugin") : !1;
605
+ }
606
+ function $(e, t) {
607
+ return [...e.matchAll(t)].length;
608
+ }
609
+ async function oe(e) {
610
+ let t = [], r = ie(e.cwd);
611
+ if (!r) return {
612
+ framework: "unknown",
613
+ findings: [{
614
+ severity: "error",
615
+ code: "missing-package-json",
616
+ message: "No package.json found in the current directory."
617
+ }]
618
+ };
619
+ let a = G({
620
+ ...r.dependencies,
621
+ ...r.devDependencies
622
+ }), s = ne(e.cwd, e.config), c = await re(e.cwd), l = 0, d = 0, f = !1, p = !1;
623
+ for (let t of c) {
624
+ let n = o(u(e.cwd, t), "utf-8");
625
+ l += $(n, Y), d += $(n, X), f ||= n.includes("@fluenti/"), p ||= n.includes("from '@fluenti/") && n.includes(" t`");
626
+ }
627
+ if (l > 0 && Q(t, "warning", "main-entry-interpolate", `Found ${l} import(s) of interpolate from framework packages. Import interpolate from @fluenti/core/runtime instead.`), d > 0 && Q(t, "warning", "core-internal-imports", `Found ${d} import(s) from @fluenti/core/internal. Use @fluenti/core/runtime or @fluenti/core/compiler.`), s || Q(t, "warning", "missing-config", "No fluenti.config.* file found."), a.name === "nextjs") {
628
+ let n = [
629
+ "next.config.ts",
630
+ "next.config.mjs",
631
+ "next.config.js"
632
+ ].map((t) => u(e.cwd, t)).find((e) => i(e)), r = n ? Z(n) : void 0;
633
+ f && !r?.includes("withFluenti(") && Q(t, "error", "missing-with-fluenti", "Next.js project imports Fluenti but next.config does not call withFluenti().");
634
+ }
635
+ if (a.name === "react" || a.name === "vue" || a.name === "solid") {
636
+ let n = [
637
+ "vite.config.ts",
638
+ "vite.config.mts",
639
+ "vite.config.js",
640
+ "vite.config.mjs"
641
+ ].map((t) => u(e.cwd, t)).find((e) => i(e)), r = n ? Z(n) : void 0;
642
+ (f || p) && !ae(r) && Q(t, "warning", "missing-vite-plugin", "Project imports Fluenti but vite.config does not appear to include a Fluenti Vite plugin.");
643
+ }
644
+ if (s && i(s)) try {
645
+ let r = await n(s), a = r.format === "json" ? ".json" : ".po", o = u(e.cwd, r.catalogDir, `${r.sourceLocale}${a}`);
646
+ i(o) || Q(t, "warning", "missing-source-catalog", `Source catalog not found: ${o}`);
647
+ let c = u(e.cwd, r.compileOutDir, "index.js");
648
+ i(c) || Q(t, "warning", "missing-compiled-catalogs", `Compiled catalogs not found at ${c}. Run "fluenti compile".`);
649
+ } catch (e) {
650
+ Q(t, "error", "invalid-config", `Failed to load Fluenti config: ${e instanceof Error ? e.message : String(e)}`);
651
+ }
652
+ return t.length === 0 && Q(t, "info", "ok", "No Fluenti migration or configuration issues detected."), {
653
+ framework: a.name,
654
+ findings: t,
655
+ ...s ? { configPath: s } : {}
656
+ };
657
+ }
658
+ function se(e) {
659
+ let t = [`Framework: ${e.framework}`];
660
+ e.configPath && t.push(`Config: ${e.configPath}`), t.push("");
661
+ for (let n of e.findings) {
662
+ let e = n.severity === "error" ? "✖" : n.severity === "warning" ? "⚠" : "•";
663
+ t.push(`${e} [${n.code}] ${n.message}`);
664
+ }
665
+ return t.join("\n");
666
+ }
667
+ //#endregion
668
+ export { V as a, n as c, x as d, ee as f, B as i, w as l, oe as n, N as o, g as p, q as r, j as s, se as t, T as u };
669
+
670
+ //# sourceMappingURL=doctor-BqXXxyST.js.map