@verbaly/compiler 0.16.0 → 0.17.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.
@@ -1,3 +1,4 @@
1
+ import { t as isModuleNotFound } from "./cli.js";
1
2
  //#region src/providers/claude.ts
2
3
  const DEFAULT_MODEL = "claude-sonnet-5";
3
4
  const SYSTEM = `You translate UI strings for the Verbaly i18n library.
@@ -44,10 +45,7 @@ async function loadSdk(load = () => import("@anthropic-ai/sdk")) {
44
45
  throw error;
45
46
  }
46
47
  }
47
- function isModuleNotFound(error, name) {
48
- return error instanceof Error && error.code === "ERR_MODULE_NOT_FOUND" && error.message.includes(name);
49
- }
50
48
  //#endregion
51
49
  export { claudeProvider };
52
50
 
53
- //# sourceMappingURL=claude-Bi_Ex2hm.js.map
51
+ //# sourceMappingURL=claude-mpjdqqnY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-mpjdqqnY.js","names":[],"sources":["../src/providers/claude.ts"],"sourcesContent":["import { isModuleNotFound } from '../config';\nimport type { TranslateProvider, TranslateRequest } from '../translate';\n\nexport interface ClaudeProviderOptions {\n model?: string;\n apiKey?: string;\n maxTokens?: number;\n}\n\n// balanced default for translation\nconst DEFAULT_MODEL = 'claude-sonnet-5';\n\nconst SYSTEM = `You translate UI strings for the Verbaly i18n library.\nRules:\n- Translate only the human-readable text, naturally for the target locale.\n- Preserve verbatim: placeholders like {name}, format specs like {price:currency/EUR}, variant blocks like {count | one: ... | other: # ...} (translate only the text inside each variant, keep keys and # as-is), ICU syntax, named tags like <em>...</em> and escapes {{ }} || ##.\n- Keys are opaque identifiers: return exactly the same keys, never translate or rename them.`;\n\nexport function claudeProvider(options: ClaudeProviderOptions = {}): TranslateProvider {\n return async (request: TranslateRequest) => {\n const Anthropic = await loadSdk();\n const client = new Anthropic(options.apiKey ? { apiKey: options.apiKey } : {});\n const response = await client.messages.create({\n model: options.model ?? DEFAULT_MODEL,\n max_tokens: options.maxTokens ?? 16000,\n thinking: { type: 'disabled' },\n system: SYSTEM,\n messages: [{ role: 'user', content: buildPrompt(request) }],\n output_config: { format: batchFormat(request) },\n });\n const text = response.content.find((block) => block.type === 'text')?.text ?? '{}';\n return JSON.parse(text) as Record<string, string>;\n };\n}\n\nexport function buildPrompt(request: TranslateRequest): string {\n return (\n `Translate each value from \"${request.sourceLocale}\" to \"${request.targetLocale}\". ` +\n `Return a JSON object with the same keys and translated values.\\n\\n` +\n JSON.stringify(request.messages, null, 2)\n );\n}\n\nexport function batchFormat(request: TranslateRequest) {\n const keys = Object.keys(request.messages);\n return {\n type: 'json_schema' as const,\n schema: {\n type: 'object',\n properties: Object.fromEntries(keys.map((key) => [key, { type: 'string' }])),\n required: keys,\n additionalProperties: false,\n },\n };\n}\n\ntype SdkModule = { default: typeof import('@anthropic-ai/sdk').default };\n\n// injectable for tests\nexport async function loadSdk(\n load: () => Promise<SdkModule> = () => import('@anthropic-ai/sdk'),\n): Promise<SdkModule['default']> {\n try {\n const mod = await load();\n return mod.default;\n } catch (error) {\n if (isModuleNotFound(error, '@anthropic-ai/sdk')) {\n throw new Error(\n '[verbaly] the claude translate provider needs @anthropic-ai/sdk — install it as a dev dependency (e.g. `pnpm add -D @anthropic-ai/sdk` / `npm i -D @anthropic-ai/sdk`) and set ANTHROPIC_API_KEY',\n { cause: error },\n );\n }\n throw error;\n }\n}\n\n"],"mappings":";;AAUA,MAAM,gBAAgB;AAEtB,MAAM,SAAS;;;;;AAMf,SAAgB,eAAe,UAAiC,CAAC,GAAsB;CACrF,OAAO,OAAO,YAA8B;EAW1C,MAAM,QAAO,MARU,KADJ,OADK,QAAQ,IACH,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC,CAChD,CAAC,CAAC,SAAS,OAAO;GAC5C,OAAO,QAAQ,SAAS;GACxB,YAAY,QAAQ,aAAa;GACjC,UAAU,EAAE,MAAM,WAAW;GAC7B,QAAQ;GACR,UAAU,CAAC;IAAE,MAAM;IAAQ,SAAS,YAAY,OAAO;GAAE,CAAC;GAC1D,eAAe,EAAE,QAAQ,YAAY,OAAO,EAAE;EAChD,CAAC,EAAA,CACqB,QAAQ,MAAM,UAAU,MAAM,SAAS,MAAM,CAAC,EAAE,QAAQ;EAC9E,OAAO,KAAK,MAAM,IAAI;CACxB;AACF;AAEA,SAAgB,YAAY,SAAmC;CAC7D,OACE,8BAA8B,QAAQ,aAAa,QAAQ,QAAQ,aAAa,yEAEhF,KAAK,UAAU,QAAQ,UAAU,MAAM,CAAC;AAE5C;AAEA,SAAgB,YAAY,SAA2B;CACrD,MAAM,OAAO,OAAO,KAAK,QAAQ,QAAQ;CACzC,OAAO;EACL,MAAM;EACN,QAAQ;GACN,MAAM;GACN,YAAY,OAAO,YAAY,KAAK,KAAK,QAAQ,CAAC,KAAK,EAAE,MAAM,SAAS,CAAC,CAAC,CAAC;GAC3E,UAAU;GACV,sBAAsB;EACxB;CACF;AACF;AAKA,eAAsB,QACpB,aAAuC,OAAO,sBACf;CAC/B,IAAI;EAEF,QAAO,MADW,KAAK,EAAA,CACZ;CACb,SAAS,OAAO;EACd,IAAI,iBAAiB,OAAO,mBAAmB,GAC7C,MAAM,IAAI,MACR,oMACA,EAAE,OAAO,MAAM,CACjB;EAEF,MAAM;CACR;AACF"}
package/dist/cli.js CHANGED
@@ -159,6 +159,9 @@ ${lines.join("\n")}
159
159
  export function createInstance(
160
160
  options?: import('verbaly').VerbalyOptions<VerbalyKey>,
161
161
  ): import('verbaly').Verbaly<VerbalyKey>;
162
+ export function createRequestInstance(
163
+ locale: string,
164
+ ): Promise<import('verbaly').Verbaly<VerbalyKey>>;
162
165
 
163
166
  export function t<K extends VerbalyKey>(
164
167
  key: K,
@@ -186,6 +189,125 @@ function writeDts(cfg, entries) {
186
189
  writeFileSync(join(cfg.root, "verbaly.d.ts"), generateDts(entries));
187
190
  }
188
191
  //#endregion
192
+ //#region src/pseudo.ts
193
+ const PSEUDO_LOCALE = "en-XA";
194
+ const ACCENTS = {
195
+ a: "á",
196
+ b: "ƀ",
197
+ c: "ç",
198
+ d: "đ",
199
+ e: "é",
200
+ f: "ƒ",
201
+ g: "ğ",
202
+ h: "ĥ",
203
+ i: "í",
204
+ j: "ĵ",
205
+ k: "ķ",
206
+ l: "ĺ",
207
+ m: "ɱ",
208
+ n: "ñ",
209
+ o: "ó",
210
+ p: "þ",
211
+ q: "ǫ",
212
+ r: "ŕ",
213
+ s: "š",
214
+ t: "ţ",
215
+ u: "ú",
216
+ v: "ṽ",
217
+ w: "ŵ",
218
+ x: "ẋ",
219
+ y: "ý",
220
+ z: "ž",
221
+ A: "Á",
222
+ B: "Ɓ",
223
+ C: "Ç",
224
+ D: "Đ",
225
+ E: "É",
226
+ F: "Ƒ",
227
+ G: "Ğ",
228
+ H: "Ĥ",
229
+ I: "Í",
230
+ J: "Ĵ",
231
+ K: "Ķ",
232
+ L: "Ĺ",
233
+ M: "Ḿ",
234
+ N: "Ñ",
235
+ O: "Ó",
236
+ P: "Þ",
237
+ Q: "Ǫ",
238
+ R: "Ŕ",
239
+ S: "Š",
240
+ T: "Ţ",
241
+ U: "Ú",
242
+ V: "Ṽ",
243
+ W: "Ŵ",
244
+ X: "Ẍ",
245
+ Y: "Ý",
246
+ Z: "Ž"
247
+ };
248
+ const TAG_AT = /<\/?[a-zA-Z][\w-]*\/?>/y;
249
+ function pseudoLocalize(message) {
250
+ let out = "";
251
+ let letters = 0;
252
+ let i = 0;
253
+ while (i < message.length) {
254
+ const two = message.slice(i, i + 2);
255
+ if (two === "{{" || two === "}}" || two === "||" || two === "##") {
256
+ out += two;
257
+ i += 2;
258
+ continue;
259
+ }
260
+ const ch = message[i];
261
+ if (ch === "{") {
262
+ const end = matchBrace(message, i);
263
+ out += message.slice(i, end);
264
+ i = end;
265
+ continue;
266
+ }
267
+ if (ch === "<") {
268
+ TAG_AT.lastIndex = i;
269
+ const m = TAG_AT.exec(message);
270
+ if (m) {
271
+ out += m[0];
272
+ i += m[0].length;
273
+ continue;
274
+ }
275
+ }
276
+ const mapped = ACCENTS[ch];
277
+ if (mapped) {
278
+ out += mapped;
279
+ letters += 1;
280
+ } else out += ch;
281
+ i += 1;
282
+ }
283
+ const pad = "~".repeat(Math.ceil(letters / 3));
284
+ return `⟦${out}${pad ? " " + pad : ""}⟧`;
285
+ }
286
+ function matchBrace(message, start) {
287
+ let depth = 0;
288
+ for (let i = start; i < message.length; i++) {
289
+ const two = message.slice(i, i + 2);
290
+ if (two === "{{" || two === "}}") {
291
+ i += 1;
292
+ continue;
293
+ }
294
+ const ch = message[i];
295
+ if (ch === "{") depth += 1;
296
+ else if (ch === "}") {
297
+ depth -= 1;
298
+ if (depth === 0) return i + 1;
299
+ }
300
+ }
301
+ return message.length;
302
+ }
303
+ function pseudoCatalogs(cfg, catalogs, locale = PSEUDO_LOCALE) {
304
+ const source = catalogs[cfg.sourceLocale] ?? {};
305
+ const target = {};
306
+ for (const [key, msg] of Object.entries(source)) target[key] = msg ? pseudoLocalize(msg) : "";
307
+ catalogs[locale] = target;
308
+ return Object.keys(target).filter((key) => target[key]);
309
+ }
310
+ //#endregion
189
311
  //#region src/config.ts
190
312
  function resolveConfig(config = {}) {
191
313
  const root = resolve(config.root ?? process.cwd());
@@ -193,7 +315,7 @@ function resolveConfig(config = {}) {
193
315
  const sourceLocale = config.sourceLocale ?? "en";
194
316
  const locales = /* @__PURE__ */ new Set([sourceLocale, ...config.locales ?? []]);
195
317
  if (existsSync(dir)) {
196
- for (const file of readdirSync(dir)) if (file.endsWith(".json")) locales.add(file.slice(0, -5));
318
+ for (const file of readdirSync(dir)) if (file.endsWith(".json") && file !== `en-XA.json`) locales.add(file.slice(0, -5));
197
319
  }
198
320
  return {
199
321
  root,
@@ -242,6 +364,9 @@ async function loadTsConfig(path) {
242
364
  function isModuleNotFound(error, name) {
243
365
  return error instanceof Error && error.code === "ERR_MODULE_NOT_FOUND" && error.message.includes(name);
244
366
  }
367
+ function targetLocales(cfg, override) {
368
+ return (override ?? cfg.locales).filter((locale) => locale !== cfg.sourceLocale && cfg.locales.includes(locale));
369
+ }
245
370
  async function loadConfig(root, overrides = {}) {
246
371
  return resolveConfig({
247
372
  ...await loadConfigFile(root),
@@ -395,7 +520,7 @@ function buildTransMessage(code, children) {
395
520
  text += escapeText(expr.value);
396
521
  continue;
397
522
  }
398
- if (expr.type === "TaggedTemplateExpression") return void 0;
523
+ if (containsTaggedT(expr)) return void 0;
399
524
  const source = code.slice(expr.start, expr.end);
400
525
  const name = uniqueName(deriveName(expr, params.length), source, takenParams);
401
526
  params.push({
@@ -448,6 +573,15 @@ function selfClosedSource(code, opening) {
448
573
  const src = code.slice(opening.start, opening.end);
449
574
  return src.endsWith("/>") ? src : `${src.slice(0, -1).trimEnd()} />`;
450
575
  }
576
+ function containsTaggedT(node) {
577
+ let found = false;
578
+ walk(node, (n) => {
579
+ if (n.type !== "TaggedTemplateExpression") return;
580
+ const tag = n.tag;
581
+ if (isTReference(tag) || explicitId(tag)) found = true;
582
+ });
583
+ return found;
584
+ }
451
585
  function isTReference(node) {
452
586
  if (node.type === "Identifier") return node.name === "t";
453
587
  if (node.type === "MemberExpression" && !node.computed) {
@@ -465,6 +599,7 @@ function buildMessage(code, quasi) {
465
599
  for (let i = 0; i < expressions.length; i++) {
466
600
  const expr = expressions[i];
467
601
  if (!expr) return void 0;
602
+ if (containsTaggedT(expr)) return void 0;
468
603
  const source = code.slice(expr.start, expr.end);
469
604
  const name = uniqueName(deriveName(expr, i), source, taken);
470
605
  params.push({
@@ -768,7 +903,7 @@ function readDeps(root) {
768
903
  //#region src/translate.ts
769
904
  async function translateCatalogs(cfg, catalogs, provider, options = {}) {
770
905
  const batchSize = options.batchSize ?? 20;
771
- const targets = (options.locales ?? cfg.locales).filter((locale) => locale !== cfg.sourceLocale && cfg.locales.includes(locale));
906
+ const targets = targetLocales(cfg, options.locales);
772
907
  const source = catalogs[cfg.sourceLocale] ?? {};
773
908
  const result = {
774
909
  translated: {},
@@ -827,7 +962,7 @@ function exportCatalogs(cfg, catalogs, options = {}) {
827
962
  const format = options.format ?? "xliff";
828
963
  const dir = resolve(cfg.root, options.out ?? "verbaly-export");
829
964
  const source = catalogs[cfg.sourceLocale] ?? {};
830
- const targets = (options.locales ?? cfg.locales).filter((locale) => locale !== cfg.sourceLocale && cfg.locales.includes(locale));
965
+ const targets = targetLocales(cfg, options.locales);
831
966
  const files = [];
832
967
  mkdirSync(dir, { recursive: true });
833
968
  for (const locale of targets) {
@@ -1006,125 +1141,6 @@ function csvRows(content) {
1006
1141
  return rows;
1007
1142
  }
1008
1143
  //#endregion
1009
- //#region src/pseudo.ts
1010
- const PSEUDO_LOCALE = "en-XA";
1011
- const ACCENTS = {
1012
- a: "á",
1013
- b: "ƀ",
1014
- c: "ç",
1015
- d: "đ",
1016
- e: "é",
1017
- f: "ƒ",
1018
- g: "ğ",
1019
- h: "ĥ",
1020
- i: "í",
1021
- j: "ĵ",
1022
- k: "ķ",
1023
- l: "ĺ",
1024
- m: "ɱ",
1025
- n: "ñ",
1026
- o: "ó",
1027
- p: "þ",
1028
- q: "ǫ",
1029
- r: "ŕ",
1030
- s: "š",
1031
- t: "ţ",
1032
- u: "ú",
1033
- v: "ṽ",
1034
- w: "ŵ",
1035
- x: "ẋ",
1036
- y: "ý",
1037
- z: "ž",
1038
- A: "Á",
1039
- B: "Ɓ",
1040
- C: "Ç",
1041
- D: "Đ",
1042
- E: "É",
1043
- F: "Ƒ",
1044
- G: "Ğ",
1045
- H: "Ĥ",
1046
- I: "Í",
1047
- J: "Ĵ",
1048
- K: "Ķ",
1049
- L: "Ĺ",
1050
- M: "Ḿ",
1051
- N: "Ñ",
1052
- O: "Ó",
1053
- P: "Þ",
1054
- Q: "Ǫ",
1055
- R: "Ŕ",
1056
- S: "Š",
1057
- T: "Ţ",
1058
- U: "Ú",
1059
- V: "Ṽ",
1060
- W: "Ŵ",
1061
- X: "Ẍ",
1062
- Y: "Ý",
1063
- Z: "Ž"
1064
- };
1065
- const TAG_AT = /<\/?[a-zA-Z][\w-]*\/?>/y;
1066
- function pseudoLocalize(message) {
1067
- let out = "";
1068
- let letters = 0;
1069
- let i = 0;
1070
- while (i < message.length) {
1071
- const two = message.slice(i, i + 2);
1072
- if (two === "{{" || two === "}}" || two === "||" || two === "##") {
1073
- out += two;
1074
- i += 2;
1075
- continue;
1076
- }
1077
- const ch = message[i];
1078
- if (ch === "{") {
1079
- const end = matchBrace(message, i);
1080
- out += message.slice(i, end);
1081
- i = end;
1082
- continue;
1083
- }
1084
- if (ch === "<") {
1085
- TAG_AT.lastIndex = i;
1086
- const m = TAG_AT.exec(message);
1087
- if (m) {
1088
- out += m[0];
1089
- i += m[0].length;
1090
- continue;
1091
- }
1092
- }
1093
- const mapped = ACCENTS[ch];
1094
- if (mapped) {
1095
- out += mapped;
1096
- letters += 1;
1097
- } else out += ch;
1098
- i += 1;
1099
- }
1100
- const pad = "~".repeat(Math.ceil(letters / 3));
1101
- return `⟦${out}${pad ? " " + pad : ""}⟧`;
1102
- }
1103
- function matchBrace(message, start) {
1104
- let depth = 0;
1105
- for (let i = start; i < message.length; i++) {
1106
- const two = message.slice(i, i + 2);
1107
- if (two === "{{" || two === "}}") {
1108
- i += 1;
1109
- continue;
1110
- }
1111
- const ch = message[i];
1112
- if (ch === "{") depth += 1;
1113
- else if (ch === "}") {
1114
- depth -= 1;
1115
- if (depth === 0) return i + 1;
1116
- }
1117
- }
1118
- return message.length;
1119
- }
1120
- function pseudoCatalogs(cfg, catalogs, locale = PSEUDO_LOCALE) {
1121
- const source = catalogs[cfg.sourceLocale] ?? {};
1122
- const target = {};
1123
- for (const [key, msg] of Object.entries(source)) target[key] = msg ? pseudoLocalize(msg) : "";
1124
- catalogs[locale] = target;
1125
- return Object.keys(target).filter((key) => target[key]);
1126
- }
1127
- //#endregion
1128
1144
  //#region src/render.ts
1129
1145
  const HREFLANG_OPEN = "<!--verbaly:hreflang-->";
1130
1146
  const HREFLANG_CLOSE = "<!--/verbaly:hreflang-->";
@@ -1395,7 +1411,7 @@ function decodeEntities(text) {
1395
1411
  return text.replace(/&quot;/g, "\"").replace(/&#39;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
1396
1412
  }
1397
1413
  //#endregion
1398
- //#region src/cli.ts
1414
+ //#region src/run.ts
1399
1415
  const HELP = `verbaly — i18n compiler
1400
1416
 
1401
1417
  Usage:
@@ -1416,7 +1432,7 @@ Options:
1416
1432
  --locales <csv> extra locales; for translate: target locales to fill
1417
1433
  --prune drop keys no longer referenced (extract)
1418
1434
  --model <id> model override for the claude provider (translate)
1419
- --dry-run list what would happen, write nothing (translate, import)
1435
+ --dry-run list what would happen, write nothing (translate, import, extract)
1420
1436
  --format <f> export format: xliff (default) or csv (export)
1421
1437
  --out <path> export directory (export, default: verbaly-export)
1422
1438
  --missing export only untranslated entries (export)
@@ -1431,8 +1447,9 @@ Options:
1431
1447
  Config file: verbaly.config.{js,mjs,ts,mts,json} at root (flags win).
1432
1448
  The claude provider needs @anthropic-ai/sdk installed and ANTHROPIC_API_KEY set.
1433
1449
  `;
1434
- async function main() {
1450
+ async function runCli(args = process.argv.slice(2)) {
1435
1451
  const { positionals, values } = parseArgs({
1452
+ args,
1436
1453
  allowPositionals: true,
1437
1454
  options: {
1438
1455
  root: { type: "string" },
@@ -1464,6 +1481,7 @@ async function main() {
1464
1481
  process.exitCode = command ? 0 : 1;
1465
1482
  return;
1466
1483
  }
1484
+ if (rejectStrayFlags(command, values)) return;
1467
1485
  if (command === "init") {
1468
1486
  const result = init({
1469
1487
  root: values.root,
@@ -1505,18 +1523,21 @@ async function main() {
1505
1523
  return;
1506
1524
  }
1507
1525
  if (command === "extract") {
1526
+ const dryRun = values["dry-run"];
1508
1527
  const registry = await extractProject(cfg);
1509
1528
  const catalogs = loadCatalogs(cfg);
1510
1529
  if (values.prune) {
1511
1530
  const removed = pruneCatalogs(cfg, catalogs, registry);
1512
- for (const [locale, keys] of Object.entries(removed)) console.log(` ${locale}: -${keys.length} pruned`);
1531
+ for (const [locale, keys] of Object.entries(removed)) console.log(dryRun ? ` ${locale}: would prune ${keys.length} — ${keys.join(", ")}` : ` ${locale}: -${keys.length} pruned`);
1513
1532
  }
1514
1533
  const { added } = syncCatalogs(cfg, catalogs, registry);
1515
- for (const locale of cfg.locales) writeCatalog(cfg, locale, catalogs[locale] ?? {});
1516
- writeDts(cfg, new Map(Object.entries(catalogs[cfg.sourceLocale] ?? {})));
1534
+ if (!dryRun) {
1535
+ for (const locale of cfg.locales) writeCatalog(cfg, locale, catalogs[locale] ?? {});
1536
+ writeDts(cfg, new Map(Object.entries(catalogs[cfg.sourceLocale] ?? {})));
1537
+ }
1517
1538
  const total = registry.messages().size;
1518
- console.log(`[verbaly] ${total} messages · locales: ${cfg.locales.join(", ")}`);
1519
- for (const [locale, keys] of Object.entries(added)) console.log(` ${locale}: +${keys.length}`);
1539
+ console.log(`[verbaly] ${total} messages · locales: ${cfg.locales.join(", ")}${dryRun ? " (dry run, nothing written)" : ""}`);
1540
+ for (const [locale, keys] of Object.entries(added)) console.log(` ${locale}: ${dryRun ? `would add ${keys.length}` : `+${keys.length}`}`);
1520
1541
  return;
1521
1542
  }
1522
1543
  if (command === "check") {
@@ -1623,17 +1644,61 @@ async function main() {
1623
1644
  console.error(`[verbaly] unknown command "${command}"\n${HELP}`);
1624
1645
  process.exitCode = 1;
1625
1646
  }
1647
+ const COMMON_FLAGS = /* @__PURE__ */ new Set([
1648
+ "root",
1649
+ "dir",
1650
+ "source",
1651
+ "locales",
1652
+ "help"
1653
+ ]);
1654
+ const COMMAND_FLAGS = {
1655
+ init: [],
1656
+ doctor: [],
1657
+ extract: ["prune", "dry-run"],
1658
+ check: [],
1659
+ translate: ["model", "dry-run"],
1660
+ export: [
1661
+ "format",
1662
+ "out",
1663
+ "missing"
1664
+ ],
1665
+ import: [
1666
+ "locale",
1667
+ "overwrite",
1668
+ "dry-run"
1669
+ ],
1670
+ pseudo: ["locale"],
1671
+ render: [
1672
+ "site",
1673
+ "attribute",
1674
+ "base-url",
1675
+ "sitemap",
1676
+ "clean"
1677
+ ]
1678
+ };
1679
+ function rejectStrayFlags(command, values) {
1680
+ const own = COMMAND_FLAGS[command];
1681
+ if (!own) return false;
1682
+ const allowed = /* @__PURE__ */ new Set([...COMMON_FLAGS, ...own]);
1683
+ const stray = Object.keys(values).filter((k) => values[k] !== void 0 && !allowed.has(k));
1684
+ if (stray.length === 0) return false;
1685
+ for (const flag of stray) console.error(`[verbaly] --${flag} is not a "${command}" flag${flag === "locale" ? " — did you mean --locales?" : ""}`);
1686
+ process.exitCode = 1;
1687
+ return true;
1688
+ }
1626
1689
  async function resolveProvider(cfg, model) {
1627
1690
  const configured = cfg.translate.provider;
1628
1691
  if (typeof configured === "function") return configured;
1629
- const { claudeProvider } = await import("./claude-Bi_Ex2hm.js");
1692
+ const { claudeProvider } = await import("./claude-mpjdqqnY.js");
1630
1693
  return claudeProvider({ model: model ?? cfg.translate.model });
1631
1694
  }
1632
- main().catch((error) => {
1695
+ //#endregion
1696
+ //#region src/cli.ts
1697
+ runCli().catch((error) => {
1633
1698
  console.error("[verbaly]", error instanceof Error ? error.message : error);
1634
1699
  process.exitCode = 1;
1635
1700
  });
1636
1701
  //#endregion
1637
- export {};
1702
+ export { isModuleNotFound as t };
1638
1703
 
1639
1704
  //# sourceMappingURL=cli.js.map