@better-translate/cli 2.0.1 → 3.0.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.
package/README.md CHANGED
@@ -76,3 +76,27 @@ export default defineConfig({
76
76
  ```
77
77
 
78
78
  Full docs: [better-translate-placeholder.com/en/docs/cli](https://better-translate-placeholder.com/en/docs/cli)
79
+
80
+ ## Commands
81
+
82
+ Extract new source keys:
83
+
84
+ ```sh
85
+ npx bt extract
86
+ ```
87
+
88
+ Generate translated locale files:
89
+
90
+ ```sh
91
+ npx bt generate
92
+ ```
93
+
94
+ When markdown generation is enabled and `bt generate` would create or overwrite translated `.md` or `.mdx` files, the CLI asks for confirmation before it makes changes.
95
+
96
+ Use `--yes` or `-y` to skip that confirmation, especially in CI or other non-interactive environments:
97
+
98
+ ```sh
99
+ npx bt generate --yes
100
+ ```
101
+
102
+ In non-interactive environments, markdown generation requires `--yes` when translated markdown files would be written.
@@ -25,7 +25,7 @@ function createOutputValidator(request) {
25
25
  function isSchemaTooLargeError(error) {
26
26
  const message = error instanceof Error ? error.message : String(error);
27
27
  const normalizedMessage = message.toLowerCase();
28
- return normalizedMessage.includes("compiled grammar is too large") || normalizedMessage.includes("reduce the number of strict tools") || normalizedMessage.includes("simplify your tool schemas") || normalizedMessage.includes("tool schemas");
28
+ return normalizedMessage.includes("compiled grammar is too large") || normalizedMessage.includes("reduce the number of strict tools") || normalizedMessage.includes("tool schemas exceed") || normalizedMessage.includes("tool schema size") || normalizedMessage.includes("exceeds maximum schema size") || normalizedMessage.includes("too many tools");
29
29
  }
30
30
  function extractJsonPayload(text) {
31
31
  const trimmed = text.trim();
@@ -41,6 +41,11 @@ function extractJsonPayload(text) {
41
41
  return trimmed;
42
42
  }
43
43
  function parseJsonText(text, request) {
44
+ if (!request.validate) {
45
+ throw new Error(
46
+ `Fallback JSON parsing failed for "${request.sourcePath}": no validator provided`
47
+ );
48
+ }
44
49
  const payload = extractJsonPayload(text);
45
50
  try {
46
51
  return validateGeneratedValue(JSON.parse(payload), request);
@@ -1 +1 @@
1
- {"version":3,"file":"ai-sdk-generator.d.ts","sourceRoot":"","sources":["../src/ai-sdk-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAyF9D,wBAAsB,iBAAiB,CAAC,OAAO,EAC7C,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,2BAA2B,CAAC,OAAO,CAAC,GAC5C,OAAO,CAAC,OAAO,CAAC,CAoClB"}
1
+ {"version":3,"file":"ai-sdk-generator.d.ts","sourceRoot":"","sources":["../src/ai-sdk-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAiG9D,wBAAsB,iBAAiB,CAAC,OAAO,EAC7C,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,2BAA2B,CAAC,OAAO,CAAC,GAC5C,OAAO,CAAC,OAAO,CAAC,CAoClB"}
package/dist/bin.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  extractProject,
4
4
  generateProject
5
- } from "./chunk-55TGASZJ.js";
5
+ } from "./chunk-RBZAR5EL.js";
6
6
 
7
7
  // src/cli.ts
8
8
  import pc2 from "picocolors";
@@ -137,19 +137,24 @@ function usage() {
137
137
  return [
138
138
  "Usage:",
139
139
  " bt extract [--config ./better-translate.config.ts] [--dry-run] [--max-length 40]",
140
- " bt generate [--config ./better-translate.config.ts] [--dry-run]"
140
+ " bt generate [--config ./better-translate.config.ts] [--dry-run] [--yes|-y]"
141
141
  ].join("\n");
142
142
  }
143
143
  function parseCommonArgs(argv) {
144
144
  let configPath;
145
145
  let dryRun = false;
146
146
  let maxLength;
147
+ let yes = false;
147
148
  for (let index = 0; index < argv.length; index += 1) {
148
149
  const arg = argv[index];
149
150
  if (arg === "--dry-run") {
150
151
  dryRun = true;
151
152
  continue;
152
153
  }
154
+ if (arg === "--yes" || arg === "-y") {
155
+ yes = true;
156
+ continue;
157
+ }
153
158
  if (arg === "--config" || arg === "-c") {
154
159
  const value = argv[index + 1];
155
160
  if (!value) {
@@ -180,12 +185,15 @@ function parseCommonArgs(argv) {
180
185
  return {
181
186
  configPath,
182
187
  dryRun,
183
- maxLength
188
+ maxLength,
189
+ yes
184
190
  };
185
191
  }
186
192
  async function runCli(argv = process.argv.slice(2), options = {}) {
187
193
  const stderr = options.stderr ?? console.error;
188
194
  const stdout = options.stdout ?? console.log;
195
+ const extractProjectImpl = options.extractProjectImpl ?? extractProject;
196
+ const generateProjectImpl = options.generateProjectImpl ?? generateProject;
189
197
  const [command, ...args] = argv;
190
198
  if (!command || command === "--help" || command === "-h") {
191
199
  stdout(usage());
@@ -200,12 +208,17 @@ ${usage()}`);
200
208
  const parsed = parseCommonArgs(args);
201
209
  if (command === "generate" && parsed.maxLength !== void 0) {
202
210
  stderr(`--max-length is not valid for "generate".
211
+ ${usage()}`);
212
+ return 1;
213
+ }
214
+ if (command === "extract" && parsed.yes) {
215
+ stderr(`--yes is not valid for "extract".
203
216
  ${usage()}`);
204
217
  return 1;
205
218
  }
206
219
  console.log(pc2.bold("\n better-translate\n"));
207
220
  if (command === "extract") {
208
- await extractProject({
221
+ await extractProjectImpl({
209
222
  configPath: parsed.configPath,
210
223
  cwd: options.cwd,
211
224
  dryRun: parsed.dryRun,
@@ -213,11 +226,12 @@ ${usage()}`);
213
226
  maxLength: parsed.maxLength
214
227
  });
215
228
  } else {
216
- await generateProject({
229
+ await generateProjectImpl({
217
230
  configPath: parsed.configPath,
218
231
  cwd: options.cwd,
219
232
  dryRun: parsed.dryRun,
220
- logger: createSpinnerLogger()
233
+ logger: createSpinnerLogger(),
234
+ yes: parsed.yes
221
235
  });
222
236
  }
223
237
  return 0;
@@ -931,12 +931,85 @@ async function extractProject(options = {}) {
931
931
  }
932
932
 
933
933
  // src/generate.ts
934
- import { mkdir, writeFile as writeFile3 } from "fs/promises";
935
- import path7 from "path";
934
+ import { access, mkdir, writeFile as writeFile3 } from "fs/promises";
935
+ import path8 from "path";
936
+
937
+ // src/confirm.ts
938
+ import path6 from "path";
939
+ import readline from "readline";
940
+ var MAX_PREVIEW_WRITES = 5;
941
+ function pluralize(count, singular, plural) {
942
+ return `${count} ${count === 1 ? singular : plural}`;
943
+ }
944
+ function formatSummary(request) {
945
+ const parts = [];
946
+ if (request.createCount > 0) {
947
+ parts.push(`create ${pluralize(request.createCount, "new file", "new files")}`);
948
+ }
949
+ if (request.overwriteCount > 0) {
950
+ parts.push(
951
+ `overwrite ${pluralize(request.overwriteCount, "existing file", "existing files")}`
952
+ );
953
+ }
954
+ if (parts.length === 0) {
955
+ return "write translated markdown files";
956
+ }
957
+ if (parts.length === 1) {
958
+ return parts[0] ?? "write translated markdown files";
959
+ }
960
+ return `${parts[0]} and ${parts[1]}`;
961
+ }
962
+ function formatTargetPath(targetPath, projectCwd) {
963
+ const relativePath = path6.relative(projectCwd, targetPath);
964
+ if (relativePath.length > 0 && !relativePath.startsWith("..") && !path6.isAbsolute(relativePath)) {
965
+ return relativePath;
966
+ }
967
+ return targetPath;
968
+ }
969
+ async function confirmMarkdownWrites(request) {
970
+ if (request.writes.length === 0) {
971
+ return true;
972
+ }
973
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
974
+ throw new Error(
975
+ "Markdown translation would create or overwrite translated .md/.mdx files in a non-interactive environment. Re-run with --yes to continue."
976
+ );
977
+ }
978
+ const locales = Array.from(new Set(request.writes.map((write) => write.locale))).sort().join(", ");
979
+ const projectCwd = request.projectCwd ?? process.cwd();
980
+ const previewWrites = request.writes.slice(0, MAX_PREVIEW_WRITES);
981
+ const remainingCount = request.writes.length - previewWrites.length;
982
+ const preview = previewWrites.map(
983
+ (write) => ` - ${write.action}: ${formatTargetPath(write.targetPath, projectCwd)}`
984
+ ).join("\n");
985
+ const prompt = [
986
+ "",
987
+ `This run will ${formatSummary(request)} as translated markdown files (.md/.mdx).`,
988
+ `Target locales: ${locales}`,
989
+ "Planned markdown writes:",
990
+ preview,
991
+ remainingCount > 0 ? ` - ...and ${remainingCount} more planned write${remainingCount === 1 ? "" : "s"}` : "",
992
+ "",
993
+ "Continue? [y/N] "
994
+ ].filter(Boolean).join("\n");
995
+ const rl = readline.createInterface({
996
+ input: process.stdin,
997
+ output: process.stdout
998
+ });
999
+ try {
1000
+ const answer = await new Promise((resolve) => {
1001
+ rl.question(prompt, resolve);
1002
+ });
1003
+ const normalized = answer.trim().toLowerCase();
1004
+ return normalized === "y" || normalized === "yes";
1005
+ } finally {
1006
+ rl.close();
1007
+ }
1008
+ }
936
1009
 
937
1010
  // src/markdown.ts
938
1011
  import { readdir as readdir2, readFile as readFile4 } from "fs/promises";
939
- import path6 from "path";
1012
+ import path7 from "path";
940
1013
  import matter from "gray-matter";
941
1014
  async function walkDirectory(directory) {
942
1015
  const entries = await readdir2(directory, {
@@ -944,7 +1017,7 @@ async function walkDirectory(directory) {
944
1017
  });
945
1018
  const files = await Promise.all(
946
1019
  entries.map(async (entry) => {
947
- const entryPath = path6.join(directory, entry.name);
1020
+ const entryPath = path7.join(directory, entry.name);
948
1021
  if (entry.isDirectory()) {
949
1022
  return walkDirectory(entryPath);
950
1023
  }
@@ -1034,7 +1107,7 @@ async function loadMarkdownDocument(rootDir, sourcePath) {
1034
1107
  const parsed = matter(sourceText);
1035
1108
  const frontmatter = isRecord(parsed.data) ? parsed.data : {};
1036
1109
  const frontmatterStrings = extractFrontmatterStrings(frontmatter);
1037
- const relativePath = path6.relative(rootDir, sourcePath).split(path6.sep).join("/");
1110
+ const relativePath = path7.relative(rootDir, sourcePath).split(path7.sep).join("/");
1038
1111
  return {
1039
1112
  body: parsed.content,
1040
1113
  frontmatter,
@@ -1046,15 +1119,15 @@ async function loadMarkdownDocument(rootDir, sourcePath) {
1046
1119
  };
1047
1120
  }
1048
1121
  function deriveTargetMarkdownRoot(rootDir, sourceLocale, targetLocale) {
1049
- const basename = path6.basename(rootDir);
1122
+ const basename = path7.basename(rootDir);
1050
1123
  assert(
1051
1124
  basename === sourceLocale,
1052
1125
  `markdown.rootDir must end with the source locale "${sourceLocale}" so the CLI can mirror sibling locale folders.`
1053
1126
  );
1054
- return path6.join(path6.dirname(rootDir), targetLocale);
1127
+ return path7.join(path7.dirname(rootDir), targetLocale);
1055
1128
  }
1056
1129
  function deriveTargetMarkdownPath(rootDir, sourceLocale, targetLocale, relativePath) {
1057
- return path6.join(
1130
+ return path7.join(
1058
1131
  deriveTargetMarkdownRoot(rootDir, sourceLocale, targetLocale),
1059
1132
  relativePath
1060
1133
  );
@@ -1150,6 +1223,46 @@ function createConsoleLogger() {
1150
1223
  function describeError(error) {
1151
1224
  return error instanceof Error ? error.message : String(error);
1152
1225
  }
1226
+ async function pathExists(filePath) {
1227
+ try {
1228
+ await access(filePath);
1229
+ return true;
1230
+ } catch (error) {
1231
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
1232
+ return false;
1233
+ }
1234
+ throw error;
1235
+ }
1236
+ }
1237
+ function toMarkdownRelativePath(rootDir, sourcePath) {
1238
+ return path8.relative(rootDir, sourcePath).split(path8.sep).join("/");
1239
+ }
1240
+ async function createMarkdownWriteConfirmationRequest(options) {
1241
+ const writes = await Promise.all(
1242
+ options.locales.flatMap(
1243
+ (locale) => options.sourcePaths.map(async (sourcePath) => {
1244
+ const targetPath = deriveTargetMarkdownPath(
1245
+ options.markdownRootDir,
1246
+ options.sourceLocale,
1247
+ locale,
1248
+ toMarkdownRelativePath(options.markdownRootDir, sourcePath)
1249
+ );
1250
+ return {
1251
+ action: await pathExists(targetPath) ? "overwrite" : "create",
1252
+ locale,
1253
+ sourcePath,
1254
+ targetPath
1255
+ };
1256
+ })
1257
+ )
1258
+ );
1259
+ return {
1260
+ createCount: writes.filter((write) => write.action === "create").length,
1261
+ overwriteCount: writes.filter((write) => write.action === "overwrite").length,
1262
+ projectCwd: options.projectCwd,
1263
+ writes
1264
+ };
1265
+ }
1153
1266
  async function persistWrite(write, options) {
1154
1267
  if (options.dryRun) {
1155
1268
  options.logger.info(
@@ -1157,7 +1270,7 @@ async function persistWrite(write, options) {
1157
1270
  );
1158
1271
  return;
1159
1272
  }
1160
- await mkdir(path7.dirname(write.targetPath), {
1273
+ await mkdir(path8.dirname(write.targetPath), {
1161
1274
  recursive: true
1162
1275
  });
1163
1276
  await writeFile3(write.targetPath, write.content, "utf8");
@@ -1173,7 +1286,7 @@ function prepareGatewayEnvironment(apiKey) {
1173
1286
  process.env.AI_GATEWAY_API_KEY = apiKey;
1174
1287
  }
1175
1288
  async function createDefaultGenerator(model) {
1176
- const { generateWithAiSdk } = await import("./ai-sdk-generator-F2X3W7NC.js");
1289
+ const { generateWithAiSdk } = await import("./ai-sdk-generator-QEGOC4LN.js");
1177
1290
  return async (request) => generateWithAiSdk(model, request);
1178
1291
  }
1179
1292
  async function resolveRuntimeModel(config) {
@@ -1243,6 +1356,19 @@ async function generateProject(options = {}) {
1243
1356
  } else {
1244
1357
  logger.info("Markdown generation disabled.");
1245
1358
  }
1359
+ if (config.markdown && markdownSources.length > 0 && !options.dryRun && !options.yes) {
1360
+ const confirmationRequest = await createMarkdownWriteConfirmationRequest({
1361
+ locales: config.locales,
1362
+ markdownRootDir: config.markdown.rootDir,
1363
+ projectCwd: cwd,
1364
+ sourceLocale: config.sourceLocale,
1365
+ sourcePaths: markdownSources
1366
+ });
1367
+ const confirmed = await (options.confirmMarkdownWrites ?? confirmMarkdownWrites)(confirmationRequest);
1368
+ if (!confirmed) {
1369
+ throw new Error("Markdown translation cancelled. No files were written.");
1370
+ }
1371
+ }
1246
1372
  for (const locale of config.locales) {
1247
1373
  logger.info(`Starting locale "${locale}"...`);
1248
1374
  const messagePrompt = createMessagesPrompt({
package/dist/cli.d.ts CHANGED
@@ -1,5 +1,9 @@
1
+ import { extractProject } from "./extract.js";
2
+ import { generateProject } from "./generate.js";
1
3
  export declare function runCli(argv?: string[], options?: {
2
4
  cwd?: string;
5
+ extractProjectImpl?: typeof extractProject;
6
+ generateProjectImpl?: typeof generateProject;
3
7
  stderr?: (message: string) => void;
4
8
  stdout?: (message: string) => void;
5
9
  }): Promise<number>;
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AA2EA,wBAAsB,MAAM,CAC1B,IAAI,WAAwB,EAC5B,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B,GACL,OAAO,CAAC,MAAM,CAAC,CAmDjB"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAgFhD,wBAAsB,MAAM,CAC1B,IAAI,WAAwB,EAC5B,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,OAAO,cAAc,CAAC;IAC3C,mBAAmB,CAAC,EAAE,OAAO,eAAe,CAAC;IAC7C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B,GACL,OAAO,CAAC,MAAM,CAAC,CA2DjB"}
@@ -0,0 +1,3 @@
1
+ import type { MarkdownWriteConfirmationRequest } from "./types.js";
2
+ export declare function confirmMarkdownWrites(request: MarkdownWriteConfirmationRequest): Promise<boolean>;
3
+ //# sourceMappingURL=confirm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm.d.ts","sourceRoot":"","sources":["../src/confirm.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,YAAY,CAAC;AA8CnE,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,gCAAgC,GACxC,OAAO,CAAC,OAAO,CAAC,CAqDlB"}
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAGV,sBAAsB,EACtB,qBAAqB,EAGtB,MAAM,YAAY,CAAC;AA2GpB,wBAAsB,eAAe,CACnC,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CA6KhC"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAGV,sBAAsB,EACtB,qBAAqB,EAKtB,MAAM,YAAY,CAAC;AAqKpB,wBAAsB,eAAe,CACnC,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAoMhC"}
package/dist/index.d.ts CHANGED
@@ -2,5 +2,5 @@ export { loadCliConfig } from "./config-loader.js";
2
2
  export { defineConfig } from "./define-config.js";
3
3
  export { extractProject } from "./extract.js";
4
4
  export { generateProject } from "./generate.js";
5
- export type { BetterTranslateCliConfig, BetterTranslateCliDirectModelConfig, BetterTranslateCliGatewayConfig, CliLanguageModel, CliLogger, ExtractProjectOptions, ExtractProjectResult, CliWriteOperation, GenerateProjectOptions, GenerateProjectResult, LoadedBetterTranslateCliConfig, MarkdownExtension, ResolvedBetterTranslateCliConfig, ResolvedBetterTranslateCliDirectModelConfig, ResolvedBetterTranslateCliGatewayConfig, StructuredGenerationRequest, StructuredGenerator, } from "./types.js";
5
+ export type { BetterTranslateCliConfig, BetterTranslateCliDirectModelConfig, BetterTranslateCliGatewayConfig, CliLanguageModel, CliLogger, ExtractProjectOptions, ExtractProjectResult, CliWriteOperation, GenerateProjectOptions, GenerateProjectResult, LoadedBetterTranslateCliConfig, MarkdownWriteConfirmationEntry, MarkdownWriteConfirmationRequest, MarkdownExtension, ResolvedBetterTranslateCliConfig, ResolvedBetterTranslateCliDirectModelConfig, ResolvedBetterTranslateCliGatewayConfig, StructuredGenerationRequest, StructuredGenerator, } from "./types.js";
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,YAAY,EACV,wBAAwB,EACxB,mCAAmC,EACnC,+BAA+B,EAC/B,gBAAgB,EAChB,SAAS,EACT,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,8BAA8B,EAC9B,iBAAiB,EACjB,gCAAgC,EAChC,2CAA2C,EAC3C,uCAAuC,EACvC,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,YAAY,EACV,wBAAwB,EACxB,mCAAmC,EACnC,+BAA+B,EAC/B,gBAAgB,EAChB,SAAS,EACT,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,8BAA8B,EAC9B,8BAA8B,EAC9B,gCAAgC,EAChC,iBAAiB,EACjB,gCAAgC,EAChC,2CAA2C,EAC3C,uCAAuC,EACvC,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  extractProject,
3
3
  generateProject,
4
4
  loadCliConfig
5
- } from "./chunk-55TGASZJ.js";
5
+ } from "./chunk-RBZAR5EL.js";
6
6
  import {
7
7
  defineConfig
8
8
  } from "./chunk-VYOBAIBH.js";
package/dist/types.d.ts CHANGED
@@ -56,6 +56,18 @@ export interface CliWriteOperation {
56
56
  sourcePath: string;
57
57
  targetPath: string;
58
58
  }
59
+ export interface MarkdownWriteConfirmationEntry {
60
+ action: "create" | "overwrite";
61
+ locale: string;
62
+ sourcePath: string;
63
+ targetPath: string;
64
+ }
65
+ export interface MarkdownWriteConfirmationRequest {
66
+ createCount: number;
67
+ overwriteCount: number;
68
+ projectCwd?: string;
69
+ writes: readonly MarkdownWriteConfirmationEntry[];
70
+ }
59
71
  export interface CliLogger {
60
72
  error(message: string): void;
61
73
  info(message: string): void;
@@ -72,10 +84,12 @@ export interface StructuredGenerationRequest<TOutput> {
72
84
  export type StructuredGenerator = <TOutput>(request: StructuredGenerationRequest<TOutput>) => Promise<TOutput>;
73
85
  export interface GenerateProjectOptions {
74
86
  configPath?: string;
87
+ confirmMarkdownWrites?: (request: MarkdownWriteConfirmationRequest) => Promise<boolean>;
75
88
  cwd?: string;
76
89
  dryRun?: boolean;
77
90
  generator?: StructuredGenerator;
78
91
  logger?: CliLogger;
92
+ yes?: boolean;
79
93
  }
80
94
  export interface GenerateProjectResult {
81
95
  dryRun: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,MAAM,CAAC;AAE/C,MAAM,MAAM,gBAAgB,GAAG,eAAe,CAAC;AAE/C,UAAU,4BAA4B;IACpC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;QAC1C,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,+BACf,SAAQ,4BAA4B;IACpC,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mCACf,SAAQ,4BAA4B;IACpC,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,MAAM,wBAAwB,GAChC,+BAA+B,GAC/B,mCAAmC,CAAC;AAExC,UAAU,oCAAoC;IAC5C,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAC;QACzC,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,uCACf,SAAQ,oCAAoC;IAC5C,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,2CACf,SAAQ,oCAAoC;IAC5C,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,MAAM,gCAAgC,GACxC,uCAAuC,GACvC,2CAA2C,CAAC;AAEhD,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,gCAAgC,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,2BAA2B,CAAC,OAAO;IAClD,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CACxC;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EACxC,OAAO,EAAE,2BAA2B,CAAC,OAAO,CAAC,KAC1C,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,8BAA8B,CAAC;IAC7C,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,8BAA8B,CAAC;IAC7C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,MAAM,CAAC;AAE/C,MAAM,MAAM,gBAAgB,GAAG,eAAe,CAAC;AAE/C,UAAU,4BAA4B;IACpC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;QAC1C,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,+BACf,SAAQ,4BAA4B;IACpC,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mCACf,SAAQ,4BAA4B;IACpC,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,MAAM,wBAAwB,GAChC,+BAA+B,GAC/B,mCAAmC,CAAC;AAExC,UAAU,oCAAoC;IAC5C,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAC;QACzC,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,uCACf,SAAQ,oCAAoC;IAC5C,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,2CACf,SAAQ,oCAAoC;IAC5C,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,MAAM,gCAAgC,GACxC,uCAAuC,GACvC,2CAA2C,CAAC;AAEhD,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,gCAAgC,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gCAAgC;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,8BAA8B,EAAE,CAAC;CACnD;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,2BAA2B,CAAC,OAAO;IAClD,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CACxC;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EACxC,OAAO,EAAE,2BAA2B,CAAC,OAAO,CAAC,KAC1C,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB,CAAC,EAAE,CACtB,OAAO,EAAE,gCAAgC,KACtC,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,8BAA8B,CAAC;IAC7C,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,8BAA8B,CAAC;IAC7C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-translate/cli",
3
- "version": "2.0.1",
3
+ "version": "3.0.0",
4
4
  "description": "AI-powered translation generation CLI for Better Translate.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "@ai-sdk/provider": "^3.0.8",
49
- "@better-translate/core": "^2.0.0",
49
+ "@better-translate/core": "^2.1.0",
50
50
  "ai": "^6.0.116",
51
51
  "dotenv": "^17.2.3",
52
52
  "gray-matter": "^4.0.3",